diff options
1306 files changed, 111980 insertions, 77682 deletions
diff --git a/.ci/build.bat b/.ci/build.bat deleted file mode 100644 index c2f560fb7c..0000000000 --- a/.ci/build.bat +++ /dev/null @@ -1,44 +0,0 @@ -:: These are native MinGW builds, but they use the toolchain inside -:: MSYS2, this allows using all the dependencies and tools available -:: in MSYS2, but we cannot build inside the MSYS2 shell. -echo on -if "%CONFIGURATION%" == "MINGW_32" ( - set ARCH=i686 - set BITS=32 -) else ( - set ARCH=x86_64 - set BITS=64 -) -:: We cannot have sh.exe in the PATH (MinGW) -set PATH=%PATH:C:\Program Files\Git\usr\bin;=% -set PATH=C:\msys64\mingw%BITS%\bin;C:\Windows\System32;C:\Windows;%PATH% -:: The default cpack in the PATH is not CMake -set PATH=C:\Program Files (x86)\CMake\bin\cpack.exe;%PATH% - -:: Build third-party dependencies -C:\msys64\usr\bin\bash -lc "pacman --verbose --noconfirm -Su" || goto :error -C:\msys64\usr\bin\bash -lc "pacman --verbose --noconfirm --needed -S mingw-w64-%ARCH%-cmake mingw-w64-%ARCH%-perl mingw-w64-%ARCH%-python2 mingw-w64-%ARCH%-diffutils gperf" || goto :error - -mkdir .deps -cd .deps -cmake -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release ..\third-party\ || goto :error -mingw32-make VERBOSE=1 || goto :error -cd .. - -:: Build Neovim -mkdir build -cd build -cmake -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release -DBUSTED_OUTPUT_TYPE=gtest -DGPERF_PRG="C:\msys64\usr\bin\gperf.exe" .. || goto :error -mingw32-make VERBOSE=1 || goto :error -bin\nvim --version || goto :error - -:: Functional tests -mingw32-make functionaltest VERBOSE=1 || goto :error - -:: Build artifacts -cpack -G ZIP -C Release -if defined APPVEYOR_REPO_TAG_NAME cpack -G NSIS -C Release - -goto :EOF -:error -exit /b %errorlevel% diff --git a/.ci/common/test.sh b/.ci/common/test.sh deleted file mode 100644 index dc59f4f793..0000000000 --- a/.ci/common/test.sh +++ /dev/null @@ -1,113 +0,0 @@ -check_core_dumps() { - sleep 2 - - if [[ "${TRAVIS_OS_NAME}" == osx ]]; then - local cores="$(find /cores/ -type f -print)" - local dbg_cmd="lldb -Q -o bt -f ${BUILD_DIR}/bin/nvim -c" - else - # FIXME (fwalch): Will trigger if a file named core.* exists outside of $DEPS_BUILD_DIR. - local cores="$(find ./ -type f -not -path "*${DEPS_BUILD_DIR}*" -name 'core.*' -print)" - local dbg_cmd="gdb -n -batch -ex bt ${BUILD_DIR}/bin/nvim" - fi - - if [ -z "${cores}" ]; then - return - fi - for core in $cores; do - ${dbg_cmd} "${core}" - done - exit 1 -} - -check_logs() { - # Iterate through each log to remove an useless warning. - for log in $(find "${1}" -type f -name "${2}"); do - sed -i "${log}" \ - -e '/Warning: noted but unhandled ioctl/d' \ - -e '/could cause spurious value errors to appear/d' \ - -e '/See README_MISSING_SYSCALL_OR_IOCTL for guidance/d' - done - - # Now do it again, but only consider files with size > 0. - local err="" - for log in $(find "${1}" -type f -name "${2}" -size +0); do - cat "${log}" - err=1 - done - if [[ -n "${err}" ]]; then - echo "Runtime errors detected." - exit 1 - fi -} - -valgrind_check() { - check_logs "${1}" "valgrind-*" -} - -asan_check() { - check_logs "${1}" "*san.*" -} - -run_unittests() { - ${MAKE_CMD} -C "${BUILD_DIR}" unittest -} - -run_functionaltests() { - if ! ${MAKE_CMD} -C "${BUILD_DIR}" ${FUNCTIONALTEST}; then - asan_check "${LOG_DIR}" - valgrind_check "${LOG_DIR}" - exit 1 - fi - asan_check "${LOG_DIR}" - valgrind_check "${LOG_DIR}" -} - -run_oldtests() { - ${MAKE_CMD} -C "${BUILD_DIR}" helptags - if ! make -C "${TRAVIS_BUILD_DIR}/src/nvim/testdir"; then - reset - asan_check "${LOG_DIR}" - valgrind_check "${LOG_DIR}" - exit 1 - fi - asan_check "${LOG_DIR}" - valgrind_check "${LOG_DIR}" -} - -install_nvim() { - ${MAKE_CMD} -C "${BUILD_DIR}" install - - "${INSTALL_PREFIX}/bin/nvim" --version - "${INSTALL_PREFIX}/bin/nvim" -u NONE -e -c ':help' -c ':qall' || { - echo "Running ':help' in the installed nvim failed." - echo "Maybe the helptags have not been generated properly." - exit 1 - } - - local genvimsynf=syntax/vim/generated.vim - # Check that all runtime files were installed - for file in doc/tags $genvimsynf $( - cd runtime ; git ls-files | grep -e '.vim$' -e '.ps$' -e '.dict$' -e '.py$' -e '.tutor$' - ) ; do - if ! test -e "${INSTALL_PREFIX}/share/nvim/runtime/$file" ; then - echo "It appears that $file is not installed." - exit 1 - fi - done - - # Check that generated syntax file has function names, #5060. - local gpat='syn keyword vimFuncName .*eval' - if ! grep -q "$gpat" "${INSTALL_PREFIX}/share/nvim/runtime/$genvimsynf"; then - echo "It appears that $genvimsynf does not contain $gpat." - exit 1 - fi - - for file in $( - cd runtime ; git ls-files | grep -e '.awk$' -e '.sh$' -e '.bat$' - ) ; do - if ! test -x "${INSTALL_PREFIX}/share/nvim/runtime/$file" ; then - echo "It appears that $file is not installed or is not executable." - exit 1 - fi - done -} diff --git a/.ci/run_tests.sh b/.ci/run_tests.sh deleted file mode 100755 index d542a2f121..0000000000 --- a/.ci/run_tests.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env bash - -set -e -set -o pipefail - -CI_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -source "${CI_DIR}/common/build.sh" -source "${CI_DIR}/common/test.sh" - -build_nvim - -if [ "$CLANG_SANITIZER" != "TSAN" ]; then - # Additional threads are only created when the builtin UI starts, which - # doesn't happen in the unit/functional tests - run_unittests - run_functionaltests -fi -run_oldtests - -install_nvim - -touch "${SUCCESS_MARKER}" diff --git a/.gitignore b/.gitignore index 3fb3d62517..3a8994a5f6 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,6 @@ /.deps/ /tmp/ -*.rej *.orig *.mo .*.sw? @@ -18,6 +17,9 @@ tags /src/nvim/po/vim.pot /src/nvim/po/*.ck +# generated by tests with $NVIM_LOG_FILE set. +/.nvimlog + # Files generated by scripts/vim-patch.sh /.vim-src/ @@ -40,9 +42,6 @@ tags # generated by luacheck during `make testlint' /test/.luacheckcache -# luarocks, not added as a subtree because of the large number of blobs -/third-party/luarocks - # local make targets local.mk @@ -50,6 +49,3 @@ local.mk /runtime/doc/*.html /runtime/doc/tags.ref /runtime/doc/errors.log - -# clint errors, generated by `make lint` -/errors.json diff --git a/.travis.yml b/.travis.yml index 0baf3feb74..2bab1635ad 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,7 +10,7 @@ env: # http://docs.travis-ci.com/user/speeding-up-the-build/#Paralellizing-your-build-on-one-VM - MAKE_CMD="make -j2" # Update PATH for pip. - - PATH="$(python2.7 -c 'import site; print(site.getuserbase())')/bin:/usr/lib/llvm-symbolizer-3.8/bin:$PATH" + - PATH="$(python2.7 -c 'import site; print(site.getuserbase())')/bin:/usr/lib/llvm-symbolizer-4.0/bin:$PATH" # Build directory for Neovim. - BUILD_DIR="$TRAVIS_BUILD_DIR/build" # Build directory for third-party dependencies. @@ -21,13 +21,15 @@ env: - INSTALL_PREFIX="$HOME/nvim-install" # Log directory for Clang sanitizers and Valgrind. - LOG_DIR="$BUILD_DIR/log" + # Nvim log file. + - NVIM_LOG_FILE="$BUILD_DIR/.nvimlog" # Default CMake flags. - CMAKE_FLAGS="-DTRAVIS_CI_BUILD=ON -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX:PATH=$INSTALL_PREFIX - -DBUSTED_OUTPUT_TYPE=gtest + -DBUSTED_OUTPUT_TYPE=nvim -DDEPS_PREFIX=$DEPS_BUILD_DIR/usr - -DMIN_LOG_LEVEL=0" + -DMIN_LOG_LEVEL=3" - DEPS_CMAKE_FLAGS="-DDEPS_DOWNLOAD_DIR:PATH=$DEPS_DOWNLOAD_DIR" # Additional CMake flags for 32-bit builds. - CMAKE_FLAGS_32BIT="-DCMAKE_SYSTEM_LIBRARY_PATH=/lib32:/usr/lib32:/usr/local/lib32 @@ -43,22 +45,20 @@ env: # If this file exists, we know that the cache contains compiled # dependencies and we can use it. - CACHE_MARKER="$HOME/.cache/nvim-deps/.travis_cache_marker" - # Test success marker. If this file exists, we know that all tests - # were successful. Required because we only want to update the cache - # if the tests were successful, but don't have this information - # available in before_cache (which is run before after_success). - - SUCCESS_MARKER="$BUILD_DIR/.tests_successful" # default target name for functional tests - FUNCTIONALTEST=functionaltest + - CI_TARGET=tests -matrix: +jobs: include: - - os: linux - env: CI_TARGET=lint - - os: linux - compiler: gcc-5 - env: GCOV=gcov-5 CMAKE_FLAGS="$CMAKE_FLAGS -DUSE_GCOV=ON" - - os: linux + - stage: sanitizers + os: linux + compiler: clang-4.0 + env: > + CLANG_SANITIZER=ASAN_UBSAN + CMAKE_FLAGS="$CMAKE_FLAGS -DPREFER_LUA=ON" + - stage: normal builds + os: linux compiler: gcc-5 env: FUNCTIONALTEST=functionaltest-lua - os: linux @@ -67,39 +67,45 @@ matrix: # dependencies in a separate cache. compiler: gcc-5 -m32 env: BUILD_32BIT=ON - - os: linux - compiler: clang-3.8 - env: CLANG_SANITIZER=ASAN_UBSAN - - os: linux - compiler: clang-3.8 - env: CLANG_SANITIZER=TSAN - os: osx compiler: clang osx_image: xcode7.3 # macOS 10.11 - os: osx compiler: gcc-4.9 osx_image: xcode7.3 # macOS 10.11 + - stage: lint + os: linux + env: CI_TARGET=lint + - stage: Flaky builds + os: linux + compiler: gcc-5 + env: GCOV=gcov-5 CMAKE_FLAGS="$CMAKE_FLAGS -DUSE_GCOV=ON" + - os: linux + compiler: clang-4.0 + env: CLANG_SANITIZER=TSAN allow_failures: - env: GCOV=gcov-5 CMAKE_FLAGS="$CMAKE_FLAGS -DUSE_GCOV=ON" + - env: CLANG_SANITIZER=TSAN fast_finish: true -before_install: .ci/before_install.sh -install: .ci/install.sh -before_script: .ci/before_script.sh -script: .ci/script.sh -before_cache: .ci/before_cache.sh -after_success: .ci/after_success.sh +before_install: ci/before_install.sh +install: ci/install.sh +before_script: ci/before_script.sh +script: ci/script.sh +before_cache: ci/before_cache.sh +after_success: ci/after_success.sh addons: apt: sources: - ubuntu-toolchain-r-test - - llvm-toolchain-precise-3.8 + - llvm-toolchain-trusty-4.0 packages: - autoconf - automake + - apport - build-essential - - clang-3.8 + - clang-4.0 - cmake - cscope - g++-5-multilib @@ -107,9 +113,11 @@ addons: - gcc-5-multilib - gcc-multilib - gdb + - language-pack-tr - libc6-dev-i386 - libtool - - llvm-3.8-dev + - llvm-4.0-dev + - locales - pkg-config - unzip - valgrind diff --git a/CMakeLists.txt b/CMakeLists.txt index cb8302deb7..17e14bcbd0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,33 +42,35 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") if(CMAKE_COMPILER_IS_GNUCXX) set(CMAKE_INCLUDE_SYSTEM_FLAG_CXX "-isystem ") endif() +endif() - # Enable fixing case-insensitive filenames for Mac. +if(WIN32 OR CMAKE_SYSTEM_NAME STREQUAL "Darwin") + # Enable fixing case-insensitive filenames for Windows and Mac. set(USE_FNAME_CASE TRUE) endif() # Set default build type. if(NOT CMAKE_BUILD_TYPE) - message(STATUS "CMAKE_BUILD_TYPE not given, defaulting to 'Dev'.") - set(CMAKE_BUILD_TYPE "Dev" CACHE STRING "Choose the type of build." FORCE) + message(STATUS "CMAKE_BUILD_TYPE not given, defaulting to 'Debug'.") + set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Choose the type of build." FORCE) 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" "Dev" "Release" "MinSizeRel" "RelWithDebInfo") + STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo") # If not in a git repo (e.g., a tarball) these tokens define the complete # version string, else they are combined with the result of `git describe`. set(NVIM_VERSION_MAJOR 0) set(NVIM_VERSION_MINOR 2) -set(NVIM_VERSION_PATCH 0) +set(NVIM_VERSION_PATCH 1) set(NVIM_VERSION_PRERELEASE "-dev") # for package maintainers # API level -set(NVIM_API_LEVEL 1) # Bump this after any API change. +set(NVIM_API_LEVEL 3) # Bump this after any API change. set(NVIM_API_LEVEL_COMPAT 0) # Adjust this after a _breaking_ API change. -set(NVIM_API_PRERELEASE false) +set(NVIM_API_PRERELEASE true) file(TO_CMAKE_PATH ${CMAKE_CURRENT_LIST_DIR}/.git FORCED_GIT_DIR) include(GetGitRevisionDescription) @@ -94,65 +96,43 @@ 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") +# Minimize logging for release-type builds. +if(NOT CMAKE_C_FLAGS_RELEASE MATCHES DMIN_LOG_LEVEL) + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -DMIN_LOG_LEVEL=3") endif() -if(NOT CMAKE_C_FLAGS_MINSIZEREL MATCHES DDISABLE_LOG) - set(CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL} -DDISABLE_LOG") +if(NOT CMAKE_C_FLAGS_MINSIZEREL MATCHES DMIN_LOG_LEVEL) + set(CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL} -DMIN_LOG_LEVEL=3") endif() -if(NOT CMAKE_C_FLAGS_RELWITHDEBINFO MATCHES DDISABLE_LOG) - set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -DDISABLE_LOG") +if(NOT CMAKE_C_FLAGS_RELWITHDEBINFO MATCHES DMIN_LOG_LEVEL) + set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -DMIN_LOG_LEVEL=3") endif() -# Enable assertions for RelWithDebInfo. -if(CMAKE_C_FLAGS_RELWITHDEBINFO MATCHES DNDEBUG) - string(REPLACE "-DNDEBUG" "" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}") +if(CMAKE_COMPILER_IS_GNUCC) + check_c_compiler_flag(-Og HAS_OG_FLAG) +else() + set(HAS_OG_FLAG 0) endif() -# Set build flags for custom Dev build type. +# Set custom build flags for RelWithDebInfo. # -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() +if(HAS_OG_FLAG) + set(CMAKE_C_FLAGS_RELWITHDEBINFO "-Og -g" + CACHE STRING "Flags used by the compiler during release-with-debug builds." FORCE) +elseif(NOT MSVC) + set(CMAKE_C_FLAGS_RELWITHDEBINFO "-O2 -g" + CACHE STRING "Flags used by the compiler during release-with-debug builds." FORCE) +elseif(CMAKE_C_FLAGS_RELWITHDEBINFO MATCHES DNDEBUG) + string(REPLACE "-DNDEBUG" "" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}") 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") endif() -# gcc 4.0 and better turn on _FORTIFY_SOURCE=2 automatically. This currently +# gcc 4.0+ sets _FORTIFY_SOURCE=2 automatically. This currently # does not work with Neovim due to some uses of dynamically-sized structures. -# See https://github.com/neovim/neovim/issues/223 for details. +# https://github.com/neovim/neovim/issues/223 include(CheckCSourceCompiles) # Include the build type's default flags in the check for _FORTIFY_SOURCE, @@ -212,6 +192,16 @@ if(CMAKE_EXE_LINKER_FLAGS MATCHES "--sort-common" OR string(REGEX REPLACE "-Wl($| )" "" CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS}") endif() +check_c_source_compiles(" +#include <execinfo.h> +int main(void) +{ + void *trace[1]; + int trace_size = backtrace(trace, 1); + return 0; +} +" HAVE_EXECINFO_BACKTRACE) + if(MSVC) # XXX: /W4 gives too many warnings. #3241 add_definitions(/W3 -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE) @@ -219,9 +209,14 @@ else() add_definitions(-Wall -Wextra -pedantic -Wno-unused-parameter -Wstrict-prototypes -std=gnu99) + check_c_compiler_flag(-Wimplicit-fallthrough HAS_WIMPLICIT_FALLTHROUGH_FLAG) + if(HAS_WIMPLICIT_FALLTHROUGH_FLAG) + add_definitions(-Wimplicit-fallthrough) + endif() + # On FreeBSD 64 math.h uses unguarded C11 extension, which taints clang # 3.4.1 used there. - if(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD") + if(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD" AND CMAKE_C_COMPILER_ID MATCHES "Clang") add_definitions(-Wno-c11-extensions) endif() endif() @@ -255,11 +250,18 @@ if(HAS_DIAG_COLOR_FLAG) add_definitions(-fdiagnostics-color=auto) endif() -option( - TRAVIS_CI_BUILD "Travis CI build. Extra compilation flags will be set." OFF) +if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.8.5") + # Array-bounds testing is broken in some GCC versions before 4.8.5. + # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56273 + add_definitions(-Wno-array-bounds) + endif() +endif() + +option(TRAVIS_CI_BUILD "Travis/QuickBuild CI. Extra flags will be set." OFF) if(TRAVIS_CI_BUILD) - message(STATUS "Travis CI build enabled.") + message(STATUS "Travis/QuickBuild CI build enabled.") add_definitions(-Werror) if(DEFINED ENV{BUILD_32BIT}) # Get some test coverage for unsigned char @@ -274,7 +276,6 @@ else() endif() add_definitions(-DINCLUDE_GENERATED_DECLARATIONS) -add_definitions(-DHAVE_CONFIG_H) if(CMAKE_COMPILER_IS_GNUCXX AND CMAKE_SYSTEM_NAME STREQUAL "Linux") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--no-undefined") @@ -309,12 +310,36 @@ include_directories(SYSTEM ${LIBUV_INCLUDE_DIRS}) find_package(Msgpack 1.0.0 REQUIRED) include_directories(SYSTEM ${MSGPACK_INCLUDE_DIRS}) -if(UNIX) - option(FEAT_TUI "Enable the Terminal UI" ON) +# Note: The test lib requires LuaJIT; it will be skipped if LuaJIT is missing. +option(PREFER_LUA "Prefer Lua over LuaJIT in the nvim executable." OFF) + +if(PREFER_LUA) + find_package(Lua REQUIRED) + set(LUA_PREFERRED_INCLUDE_DIRS ${LUA_INCLUDE_DIR}) + set(LUA_PREFERRED_LIBRARIES ${LUA_LIBRARIES}) + find_package(LuaJit) else() - option(FEAT_TUI "Enable the Terminal UI" OFF) + find_package(LuaJit REQUIRED) + set(LUA_PREFERRED_INCLUDE_DIRS ${LUAJIT_INCLUDE_DIRS}) + set(LUA_PREFERRED_LIBRARIES ${LUAJIT_LIBRARIES}) endif() +list(APPEND CMAKE_REQUIRED_INCLUDES "${MSGPACK_INCLUDE_DIRS}") +check_c_source_compiles(" +#include <msgpack.h> + +int +main(void) +{ + return MSGPACK_OBJECT_FLOAT32; +} +" MSGPACK_HAS_FLOAT32) +if(MSGPACK_HAS_FLOAT32) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DNVIM_MSGPACK_HAS_FLOAT32") +endif() + +option(FEAT_TUI "Enable the Terminal UI" ON) + if(FEAT_TUI) find_package(Unibilium REQUIRED) include_directories(SYSTEM ${UNIBILIUM_INCLUDE_DIRS}) @@ -326,6 +351,11 @@ endif() find_package(LibVterm REQUIRED) include_directories(SYSTEM ${LIBVTERM_INCLUDE_DIRS}) +if(WIN32) + find_package(Winpty REQUIRED) + include_directories(SYSTEM ${WINPTY_INCLUDE_DIRS}) +endif() + option(CLANG_ASAN_UBSAN "Enable Clang address & undefined behavior sanitizer for nvim binary." OFF) option(CLANG_MSAN "Enable Clang memory sanitizer for nvim binary." OFF) option(CLANG_TSAN "Enable Clang thread sanitizer for nvim binary." OFF) @@ -340,8 +370,8 @@ if((CLANG_ASAN_UBSAN OR CLANG_MSAN OR CLANG_TSAN) AND NOT CMAKE_C_COMPILER_ID MA message(FATAL_ERROR "Sanitizers are only supported for Clang.") endif() -if(CMAKE_SYSTEM_NAME STREQUAL "OpenBSD") - message(STATUS "detected OpenBSD; disabled jemalloc. #5318") +if(CMAKE_SYSTEM_NAME MATCHES "OpenBSD|FreeBSD") + message(STATUS "detected OpenBSD/FreeBSD; disabled jemalloc. #5318") option(ENABLE_JEMALLOC "enable jemalloc" OFF) else() option(ENABLE_JEMALLOC "enable jemalloc" ON) @@ -415,15 +445,10 @@ message(STATUS "Using the Lua interpreter ${LUA_PRG}.") find_program(BUSTED_PRG NAMES busted busted.bat) find_program(BUSTED_LUA_PRG busted-lua) if(NOT BUSTED_OUTPUT_TYPE) - if(WIN32) - set(BUSTED_OUTPUT_TYPE "plainTerminal") - else() - set(BUSTED_OUTPUT_TYPE "utfTerminal") - endif() + set(BUSTED_OUTPUT_TYPE "nvim") endif() find_program(LUACHECK_PRG luacheck) - find_program(GPERF_PRG gperf) include(InstallHelpers) @@ -431,7 +456,6 @@ include(InstallHelpers) file(GLOB MANPAGES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} man/nvim.1) - install_helper( FILES ${MANPAGES} DESTINATION ${CMAKE_INSTALL_MANDIR}/man1) @@ -439,11 +463,11 @@ install_helper( # MIN_LOG_LEVEL for log.h if(DEFINED MIN_LOG_LEVEL) if(NOT MIN_LOG_LEVEL MATCHES "^[0-3]$") - message(FATAL_ERROR "MIN_LOG_LEVEL must be a number DEBUG (0), INFO (1), WARNING (2) or ERROR (3)") + message(FATAL_ERROR "invalid MIN_LOG_LEVEL: " ${MIN_LOG_LEVEL}) endif() - message(STATUS "Log level set to ${MIN_LOG_LEVEL}") + message(STATUS "MIN_LOG_LEVEL set to ${MIN_LOG_LEVEL}") else() - message(STATUS "Log level not specified, defaulting to INFO(1)") + message(STATUS "MIN_LOG_LEVEL not specified, defaulting to 1 (INFO)") endif() # Go down the tree. @@ -456,7 +480,7 @@ get_compile_flags(NVIM_VERSION_CFLAGS) add_subdirectory(test/includes) add_subdirectory(config) -add_subdirectory(test/functional/fixtures) # compile pty/shell test programs +add_subdirectory(test/functional/fixtures) # compile test programs add_subdirectory(runtime) # Setup some test-related bits. We do this after going down the tree because we @@ -489,10 +513,9 @@ if(BUSTED_PRG) ${CMAKE_BINARY_DIR}/test/config/paths.lua) set(UNITTEST_PREREQS nvim-test unittest-headers) - if(WIN32) - set(FUNCTIONALTEST_PREREQS nvim shell-test) - else() - set(FUNCTIONALTEST_PREREQS nvim tty-test shell-test) + set(FUNCTIONALTEST_PREREQS nvim printargs-test shell-test) + if(NOT WIN32) + list(APPEND FUNCTIONALTEST_PREREQS tty-test) endif() set(BENCHMARK_PREREQS nvim tty-test) @@ -522,8 +545,7 @@ if(BUSTED_PRG) DEPENDS ${UNITTEST_PREREQS} ${TEST_TARGET_ARGS}) else() - message(WARNING "The Luajit ffi is not available in ${LUA_PRG}" - ", disabling unit tests") + message(WARNING "disabling unit tests: no Luajit FFI in ${LUA_PRG}") endif() add_custom_target(functionaltest @@ -578,9 +600,26 @@ if(LUACHECK_PRG) add_custom_target(testlint COMMAND ${CMAKE_COMMAND} -DLUACHECK_PRG=${LUACHECK_PRG} - -DTEST_DIR=${CMAKE_CURRENT_SOURCE_DIR}/test + -DLUAFILES_DIR=${CMAKE_CURRENT_SOURCE_DIR}/test + -DIGNORE_PATTERN="*/preload.lua" -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME} - -P ${PROJECT_SOURCE_DIR}/cmake/RunTestsLint.cmake) + -P ${PROJECT_SOURCE_DIR}/cmake/RunLuacheck.cmake) + + add_custom_target( + blobcodelint + COMMAND + ${CMAKE_COMMAND} + -DLUACHECK_PRG=${LUACHECK_PRG} + -DLUAFILES_DIR=${CMAKE_CURRENT_SOURCE_DIR}/src/nvim/lua + -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME} + -DREAD_GLOBALS=vim + -P ${PROJECT_SOURCE_DIR}/cmake/RunLuacheck.cmake + ) + # TODO(ZyX-I): Run linter for all lua code in src + add_custom_target( + lualint + DEPENDS blobcodelint + ) endif() set(CPACK_PACKAGE_NAME "Neovim") diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 54bed1e72e..20bce8ca62 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -6,10 +6,16 @@ Getting started If you want to help but don't know where to start, here are some low-risk/isolated tasks: -- Help us [review pull requests](#reviewing)! -- Merge a [Vim patch]. +- [Merge a Vim patch]. - Try a [complexity:low] issue. -- Fix [clang-scan] or [coverity](#coverity) warnings. +- Fix bugs found by [clang scan-build](#clang-scan-build), + [coverity](#coverity), and [PVS](#pvs-studio). + +Developer guidelines +-------------------- + +- Nvim developers should read `:help dev-help`. +- External UI developers should read `:help dev-ui`. Reporting problems ------------------ @@ -17,26 +23,33 @@ Reporting problems - Check the [**FAQ**][wiki-faq]. - Search [existing issues][github-issues] (including closed!) - Update Neovim to the latest version to see if your problem persists. -- If you're using a plugin manager, comment out your plugins, then add them back - in one by one, to narrow down the cause of the issue. -- Crash reports which include a stacktrace are 10x more valuable. -- [Bisecting][git-bisect] to the cause of a regression often leads to an - immediate fix. +- Disable plugins incrementally, to narrow down the cause of the issue. +- When reporting a crash, include a stacktrace. +- [Bisect][git-bisect] to the cause of a regression, if you are able. This is _extremely_ helpful. +- Check `$NVIM_LOG_FILE`, if it exists. +- Include `cmake --system-information` for **build** issues. Pull requests ("PRs") --------------------- -- To avoid duplicate work, you may want to create a `[WIP]` pull request so that - others know what you are working on. -- Avoid cosmetic changes to unrelated files in the same commit: extra noise - makes reviews more difficult. +- To avoid duplicate work, create a `[WIP]` pull request as soon as possible. +- Avoid cosmetic changes to unrelated files in the same commit. - Use a [feature branch][git-feature-branch] instead of the master branch. -- [Rebase your feature branch][git-rebasing] onto (upstream) master before - opening the PR. -- After addressing the review comments, it's fine to rebase and force-push to - your review. -- Try to [tidy your history][git-history-rewriting]: combine related commits - with interactive rebasing, separate monolithic commits, etc. +- Use a **rebase workflow** for small PRs. + - After addressing review comments, it's fine to rebase and force-push. +- Use a **merge workflow** for big, high-risk PRs. + - Merge `master` into your PR when there are conflicts or when master + introduces breaking changes. + - Use the `ri` git alias: + ``` + [alias] + ri = "!sh -c 't=\"${1:-master}\"; s=\"${2:-HEAD}\"; mb=\"$(git merge-base \"$t\" \"$s\")\"; if test \"x$mb\" = x ; then o=\"$t\"; else lm=\"$(git log -n1 --merges \"$t..$s\" --pretty=%H)\"; if test \"x$lm\" = x ; then o=\"$mb\"; else o=\"$lm\"; fi; fi; test $# -gt 0 && shift; test $# -gt 0 && shift; git rebase --interactive \"$o\" \"$@\"'" + ``` + This avoids unnecessary rebases yet still allows you to combine related + commits, separate monolithic commits, etc. + - Do not edit commits that come before the merge commit. +- During a squash/fixup, use `exec make -C build unittest` between each + pick/edit/reword. ### Stages: WIP, RFC, RDY @@ -73,16 +86,18 @@ the VCS/git logs more valuable. ### Automated builds (CI) -Each pull request must pass the automated builds ([travis CI] and [quickbuild]). +Each pull request must pass the automated builds on [travis CI], [quickbuild] +and [AppVeyor]. -- CI builds are compiled with [`-Werror`][gcc-warnings], so if your PR - introduces any compiler warnings, the build will fail. +- CI builds are compiled with [`-Werror`][gcc-warnings], so compiler warnings + will fail the build. - If any tests fail, the build will fail. See [Building Neovim#running-tests][wiki-run-tests] to run tests locally. Passing locally doesn't guarantee passing the CI build, because of the different compilers and platforms tested against. -- CI runs [ASan] and other analyzers. To run valgrind locally: - `VALGRIND=1 make test` +- CI runs [ASan] and other analyzers. + - To run valgrind locally: `VALGRIND=1 make test` + - To run Clang ASan/UBSan locally: `CC=clang make CMAKE_FLAGS="-DCLANG_ASAN_UBSAN=ON"` - The `lint` build ([#3174][3174]) checks modified lines _and their immediate neighbors_. This is to encourage incrementally updating the legacy style to meet our style guidelines. @@ -90,11 +105,28 @@ Each pull request must pass the automated builds ([travis CI] and [quickbuild]). a commit that contains only style changes. - [How to investigate QuickBuild failures](https://github.com/neovim/neovim/pull/4718#issuecomment-217631350) +QuickBuild uses this invocation: + + mkdir -p build/${params.get("buildType")} \ + && cd build/${params.get("buildType")} \ + && cmake -G "Unix Makefiles" -DBUSTED_OUTPUT_TYPE=TAP -DCMAKE_BUILD_TYPE=${params.get("buildType")} + -DTRAVIS_CI_BUILD=ON ../.. && ${node.getAttribute("make", "make")} + VERBOSE=1 nvim unittest-prereqs functionaltest-prereqs + + +### Clang scan-build + +The auto-generated [clang-scan] report presents walk-throughs of bugs found by +Clang's [scan-build](https://clang-analyzer.llvm.org/scan-build.html) static +analyzer. To verify a fix locally, run `scan-build` like this: + + rm -rf build/ + scan-build --use-analyzer=/usr/bin/clang make + ### Coverity [Coverity](https://scan.coverity.com/projects/neovim-neovim) runs against the -master build. If you want to view the defects, just request access at the -_Contributor_ level. An Admin will grant you permission. +master build. To view the defects, just request access; you will be approved. Use this commit-message format for coverity fixes: @@ -102,6 +134,12 @@ Use this commit-message format for coverity fixes: where `<id>` is the Coverity ID (CID). For example see [#804](https://github.com/neovim/neovim/pull/804). +### PVS-Studio + +View the [PVS analysis report](https://neovim.io/doc/reports/pvs/) to see bugs +found by [PVS Studio](https://www.viva64.com/en/pvs-studio/). +You can run `scripts/pvscheck.sh` locally to run PVS on your machine. + Reviewing --------- @@ -136,6 +174,7 @@ as context, use the `-W` argument as well. [3174]: https://github.com/neovim/neovim/issues/3174 [travis CI]: https://travis-ci.org/neovim/neovim [quickbuild]: http://neovim-qb.szakmeister.net/dashboard -[Vim patch]: https://github.com/neovim/neovim/wiki/Merging-patches-from-upstream-Vim +[AppVeyor]: https://ci.appveyor.com/project/neovim/neovim +[Merge a Vim patch]: https://github.com/neovim/neovim/wiki/Merging-patches-from-upstream-Vim [clang-scan]: https://neovim.io/doc/reports/clang/ [complexity:low]: https://github.com/neovim/neovim/issues?q=is%3Aopen+is%3Aissue+label%3Acomplexity%3Alow diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md index 011739396d..1a7268a51e 100644 --- a/ISSUE_TEMPLATE.md +++ b/ISSUE_TEMPLATE.md @@ -1,16 +1,19 @@ +<!-- Before reporting: search existing issues and check the FAQ. --> + - `nvim --version`: - Vim (version: ) behaves differently? - Operating system/version: - Terminal name/version: - `$TERM`: -### Actual behaviour - -### Expected behaviour - ### Steps to reproduce using `nvim -u NORC` ``` nvim -u NORC ``` + +### Actual behaviour + +### Expected behaviour + @@ -4,6 +4,7 @@ filter-true = $(strip $(filter-out 1 on ON true TRUE,$1)) # See contrib/local.mk.example -include local.mk +CMAKE_PRG ?= $(shell (command -v cmake3 || echo cmake)) CMAKE_BUILD_TYPE ?= Debug CMAKE_FLAGS := -DCMAKE_BUILD_TYPE=$(CMAKE_BUILD_TYPE) @@ -15,7 +16,7 @@ BUILD_TYPE ?= $(shell (type ninja > /dev/null 2>&1 && echo "Ninja") || \ ifeq (,$(BUILD_TOOL)) ifeq (Ninja,$(BUILD_TYPE)) - ifneq ($(shell cmake --help 2>/dev/null | grep Ninja),) + ifneq ($(shell $(CMAKE_PRG) --help 2>/dev/null | grep Ninja),) BUILD_TOOL := ninja else # User's version of CMake doesn't support Ninja @@ -67,7 +68,7 @@ cmake: $(MAKE) build/.ran-cmake build/.ran-cmake: | deps - cd build && cmake -G '$(BUILD_TYPE)' $(CMAKE_FLAGS) $(CMAKE_EXTRA_FLAGS) .. + cd build && $(CMAKE_PRG) -G '$(BUILD_TYPE)' $(CMAKE_FLAGS) $(CMAKE_EXTRA_FLAGS) .. touch $@ deps: | build/.ran-third-party-cmake @@ -79,14 +80,20 @@ build/.ran-third-party-cmake: ifeq ($(call filter-true,$(USE_BUNDLED_DEPS)),) mkdir -p .deps cd .deps && \ - cmake -G '$(BUILD_TYPE)' $(BUNDLED_CMAKE_FLAG) $(BUNDLED_LUA_CMAKE_FLAG) \ + $(CMAKE_PRG) -G '$(BUILD_TYPE)' $(BUNDLED_CMAKE_FLAG) $(BUNDLED_LUA_CMAKE_FLAG) \ $(DEPS_CMAKE_FLAGS) ../third-party endif mkdir -p build touch $@ +# TODO: cmake 3.2+ add_custom_target() has a USES_TERMINAL flag. oldtest: | nvim helptags - +$(SINGLE_MAKE) -C src/nvim/testdir $(MAKEOVERRIDES) + +$(SINGLE_MAKE) -C src/nvim/testdir clean +ifeq ($(strip $(TEST_FILE)),) + +$(SINGLE_MAKE) -C src/nvim/testdir NVIM_PRG="$(realpath build/bin/nvim)" $(MAKEOVERRIDES) +else + +$(SINGLE_MAKE) -C src/nvim/testdir NVIM_PRG="$(realpath build/bin/nvim)" NEW_TESTS=$(TEST_FILE) SCRIPTS= $(MAKEOVERRIDES) +endif helptags: | nvim +$(BUILD_CMD) -C build helptags @@ -100,6 +107,9 @@ functionaltest-lua: | nvim testlint: | build/.ran-cmake deps $(BUILD_CMD) -C build testlint +lualint: | build/.ran-cmake deps + $(BUILD_CMD) -C build lualint + unittest: | nvim +$(BUILD_CMD) -C build unittest @@ -119,12 +129,18 @@ distclean: clean install: | nvim +$(BUILD_CMD) -C build install -clint: - cmake -DLINT_PRG=./src/clint.py \ - -DLINT_DIR=src \ - -DLINT_SUPPRESS_URL="$(DOC_DOWNLOAD_URL_BASE)$(CLINT_ERRORS_FILE_PATH)" \ - -P cmake/RunLint.cmake +clint: build/.ran-cmake + +$(BUILD_CMD) -C build clint + +clint-full: build/.ran-cmake + +$(BUILD_CMD) -C build clint-full + +check-single-includes: build/.ran-cmake + +$(BUILD_CMD) -C build check-single-includes + +appimage: + bash scripts/genappimage.sh -lint: clint testlint +lint: check-single-includes clint testlint lualint -.PHONY: test testlint functionaltest unittest lint clint clean distclean nvim libnvim cmake deps install +.PHONY: test testlint lualint functionaltest unittest lint clint clean distclean nvim libnvim cmake deps install appimage @@ -1,4 +1,4 @@ -[](https://neovim.io) +[](https://neovim.io) [Wiki](https://github.com/neovim/neovim/wiki) | [Documentation](https://neovim.io/doc) | @@ -8,49 +8,79 @@ [](https://travis-ci.org/neovim/neovim) [](https://ci.appveyor.com/project/neovim/neovim/branch/master) -[](https://waffle.io/neovim/neovim) -[](https://coveralls.io/r/neovim/neovim) +[](https://codecov.io/gh/neovim/neovim) [](https://scan.coverity.com/projects/2227) [](https://neovim.io/doc/reports/clang) +[](https://neovim.io/doc/reports/pvs) + <a href="https://buildd.debian.org/neovim"><img src="https://www.debian.org/logos/openlogo-nd-25.png" width="13" height="15">Debian</a> +[](https://github.com/neovim/neovim/releases/) Neovim is a project that seeks to aggressively refactor Vim in order to: - Simplify maintenance and encourage [contributions](CONTRIBUTING.md) - Split the work between multiple developers -- Enable advanced [external UIs] without modifications to the core -- Improve extensibility with a new [plugin architecture](https://github.com/neovim/neovim/wiki/Plugin-UI-architecture) +- Enable [advanced UIs] without modifications to the core +- Maximize [extensibility](https://github.com/neovim/neovim/wiki/Plugin-UI-architecture) -For more details, see -[the wiki](https://github.com/neovim/neovim/wiki/Introduction)! +See [the wiki](https://github.com/neovim/neovim/wiki/Introduction) and [Roadmap] +for more information. [](https://waffle.io/neovim/neovim/metrics) -What's been done so far ------------------------ - -- RPC API based on [MessagePack](https://msgpack.org) -- Embedded [terminal emulator](https://neovim.io/doc/user/nvim_terminal_emulator.html) +Install from source +------------------- + + make CMAKE_BUILD_TYPE=RelWithDebInfo + sudo make install + +See [the wiki](https://github.com/neovim/neovim/wiki/Building-Neovim) for details. + +Install from package +-------------------- + +Pre-built packages for Windows, macOS, and Linux are found at the +[Releases](https://github.com/neovim/neovim/releases/) page. + +Managed packages are in [Homebrew], [Debian], [Ubuntu], [Fedora], [Arch Linux], [Gentoo], +and [more](https://github.com/neovim/neovim/wiki/Installing-Neovim)! + +Project layout +-------------- + + โโ ci/ build automation + โโ cmake/ build scripts + โโ runtime/ user plugins/docs + โโ src/ application source code (see src/nvim/README.md) + โ โโ api/ API subsystem + โ โโ eval/ VimL subsystem + โ โโ event/ event-loop subsystem + โ โโ generators/ code generation (pre-compilation) + โ โโ lib/ generic data structures + โ โโ lua/ lua subsystem + โ โโ msgpack_rpc/ RPC subsystem + โ โโ os/ low-level platform code + โ โโ tui/ built-in UI + โโ third-party/ cmake subproject to build dependencies + โโ test/ tests (see test/README.md) + +- To disable `third-party/` specify `USE_BUNDLED_DEPS=NO` or `USE_BUNDLED=NO` + (CMake option). + +Features +-------- + +- Modern [GUIs](https://github.com/neovim/neovim/wiki/Related-projects#gui) +- [API](https://github.com/neovim/neovim/wiki/Related-projects#api-clients) + access from any language including clojure, lisp, go, haskell, lua, + javascript, perl, python, ruby, rust. +- Embedded, scriptable [terminal emulator](https://neovim.io/doc/user/nvim_terminal_emulator.html) - Asynchronous [job control](https://github.com/neovim/neovim/pull/2247) - [Shared data (shada)](https://github.com/neovim/neovim/pull/2506) among multiple editor instances - [XDG base directories](https://github.com/neovim/neovim/pull/3470) support -- [libuv](https://github.com/libuv/libuv/)-based platform/OS/"mch" layer -- [Pushdown automaton](https://github.com/neovim/neovim/pull/3413) input model -- 1000s of new tests -- Legacy tests converted to Lua tests - -See [`:help nvim-features`][nvim-features] for a comprehensive list. - -What's being worked on now --------------------------- - -See the [Roadmap]. - -How do I get it? ----------------- +- Compatible with most Vim plugins, including Ruby and Python plugins. -There is a Debian package, homebrew formula, PKGBUILD for Arch Linux, RPM, and -more. See [the wiki](https://github.com/neovim/neovim/wiki/Installing-Neovim)! +See [`:help nvim-features`][nvim-features] for the full list! License ------- @@ -81,6 +111,12 @@ See `LICENSE` for details. [license-commit]: https://github.com/neovim/neovim/commit/b17d9691a24099c9210289f16afb1a498a89d803 [nvim-features]: https://neovim.io/doc/user/vim_diff.html#nvim-features [Roadmap]: https://neovim.io/roadmap/ -[external UIs]: https://github.com/neovim/neovim/wiki/Related-projects#gui-projects +[advanced UIs]: https://github.com/neovim/neovim/wiki/Related-projects#gui +[Homebrew]: https://github.com/neovim/homebrew-neovim#installation +[Debian]: https://packages.debian.org/testing/neovim +[Ubuntu]: http://packages.ubuntu.com/search?keywords=neovim +[Fedora]: https://admin.fedoraproject.org/pkgdb/package/rpms/neovim +[Arch Linux]: https://www.archlinux.org/packages/?q=neovim +[Gentoo]: https://packages.gentoo.org/packages/app-editors/neovim <!-- vim: set tw=80: --> diff --git a/appveyor.yml b/appveyor.yml index eb3064c3b1..ecea6c5fa3 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -2,9 +2,16 @@ version: '{build}' configuration: - MINGW_64 - MINGW_32 +- MINGW_64-gcov +matrix: + allow_failures: + - configuration: MINGW_64-gcov install: [] build_script: -- call .ci\build.bat +- call ci\build.bat +cache: +- C:\msys64\var\cache\pacman\pkg -> ci\build.bat +- .deps -> third-party\** artifacts: - path: build/Neovim.zip - path: build/bin/nvim.exe diff --git a/busted/outputHandlers/TAP.lua b/busted/outputHandlers/TAP.lua new file mode 100644 index 0000000000..ff93a7cc75 --- /dev/null +++ b/busted/outputHandlers/TAP.lua @@ -0,0 +1,92 @@ +-- TODO(jkeyes): remove this and use the upstream version as soon as it is +-- available in a release of busted. + +local pretty = require 'pl.pretty' + +return function(options) + local busted = require 'busted' + local handler = require 'busted.outputHandlers.base'() + + local success = 'ok %u - %s' + local failure = 'not ' .. success + local skip = 'ok %u - # SKIP %s' + local counter = 0 + + handler.suiteReset = function() + counter = 0 + return nil, true + end + + handler.suiteEnd = function() + print('1..' .. counter) + io.flush() + return nil, true + end + + local function showFailure(t) + local message = t.message + local trace = t.trace or {} + + if message == nil then + message = 'Nil error' + elseif type(message) ~= 'string' then + message = pretty.write(message) + end + + print(failure:format(counter, t.name)) + print('# ' .. t.element.trace.short_src .. ' @ ' .. t.element.trace.currentline) + if t.randomseed then print('# Random seed: ' .. t.randomseed) end + print('# Failure message: ' .. message:gsub('\n', '\n# ')) + if options.verbose and trace.traceback then + print('# ' .. trace.traceback:gsub('^\n', '', 1):gsub('\n', '\n# ')) + end + end + + handler.testStart = function(element, parent) + local trace = element.trace + if options.verbose and trace and trace.short_src then + local fileline = trace.short_src .. ' @ ' .. trace.currentline .. ': ' + local testName = fileline .. handler.getFullName(element) + print('# ' .. testName) + end + io.flush() + + return nil, true + end + + handler.testEnd = function(element, parent, status, trace) + counter = counter + 1 + if status == 'success' then + local t = handler.successes[#handler.successes] + print(success:format(counter, t.name)) + elseif status == 'pending' then + local t = handler.pendings[#handler.pendings] + print(skip:format(counter, (t.message or t.name))) + elseif status == 'failure' then + showFailure(handler.failures[#handler.failures]) + elseif status == 'error' then + showFailure(handler.errors[#handler.errors]) + end + io.flush() + + return nil, true + end + + handler.error = function(element, parent, message, debug) + if element.descriptor ~= 'it' then + counter = counter + 1 + showFailure(handler.errors[#handler.errors]) + end + io.flush() + + return nil, true + end + + busted.subscribe({ 'suite', 'reset' }, handler.suiteReset) + busted.subscribe({ 'suite', 'end' }, handler.suiteEnd) + busted.subscribe({ 'test', 'start' }, handler.testStart, { predicate = handler.cancelOnPending }) + busted.subscribe({ 'test', 'end' }, handler.testEnd, { predicate = handler.cancelOnPending }) + busted.subscribe({ 'error' }, handler.error) + + return handler +end diff --git a/busted/outputHandlers/nvim.lua b/busted/outputHandlers/nvim.lua new file mode 100644 index 0000000000..b612ead070 --- /dev/null +++ b/busted/outputHandlers/nvim.lua @@ -0,0 +1,305 @@ +local s = require 'say' +local pretty = require 'pl.pretty' +local term = require 'term' + +local colors + +local isWindows = package.config:sub(1,1) == '\\' + +if isWindows then + colors = setmetatable({}, {__index = function() return function(s) return s end end}) +else + colors = require 'term.colors' +end + +return function(options) + local busted = require 'busted' + local handler = require 'busted.outputHandlers.base'() + + local c = { + succ = function(s) return colors.bright(colors.green(s)) end, + skip = function(s) return colors.bright(colors.yellow(s)) end, + fail = function(s) return colors.bright(colors.magenta(s)) end, + errr = function(s) return colors.bright(colors.red(s)) end, + test = tostring, + file = colors.cyan, + time = colors.dim, + note = colors.yellow, + sect = function(s) return colors.green(colors.dim(s)) end, + nmbr = colors.bright, + } + + local repeatSuiteString = '\nRepeating all tests (run %d of %d) . . .\n\n' + local randomizeString = c.note('Note: Randomizing test order with a seed of %d.\n') + local globalSetup = c.sect('[----------]') .. ' Global test environment setup.\n' + local fileStartString = c.sect('[----------]') .. ' Running tests from ' .. c.file('%s') .. '\n' + local runString = c.sect('[ RUN ]') .. ' ' .. c.test('%s') .. ': ' + local successString = c.succ('OK') .. '\n' + local skippedString = c.skip('SKIP') .. '\n' + local failureString = c.fail('FAIL') .. '\n' + local errorString = c.errr('ERR') .. '\n' + local fileEndString = c.sect('[----------]') .. ' '.. c.nmbr('%d') .. ' %s from ' .. c.file('%s') .. ' ' .. c.time('(%.2f ms total)') .. '\n\n' + local globalTeardown = c.sect('[----------]') .. ' Global test environment teardown.\n' + local suiteEndString = c.sect('[==========]') .. ' ' .. c.nmbr('%d') .. ' %s from ' .. c.nmbr('%d') .. ' test %s ran. ' .. c.time('(%.2f ms total)') .. '\n' + local successStatus = c.succ('[ PASSED ]') .. ' ' .. c.nmbr('%d') .. ' %s.\n' + local timeString = c.time('%.2f ms') + + local summaryStrings = { + skipped = { + header = c.skip('[ SKIPPED ]') .. ' ' .. c.nmbr('%d') .. ' %s, listed below:\n', + test = c.skip('[ SKIPPED ]') .. ' %s\n', + footer = ' ' .. c.nmbr('%d') .. ' SKIPPED %s\n', + }, + + failure = { + header = c.fail('[ FAILED ]') .. ' ' .. c.nmbr('%d') .. ' %s, listed below:\n', + test = c.fail('[ FAILED ]') .. ' %s\n', + footer = ' ' .. c.nmbr('%d') .. ' FAILED %s\n', + }, + + error = { + header = c.errr('[ ERROR ]') .. ' ' .. c.nmbr('%d') .. ' %s, listed below:\n', + test = c.errr('[ ERROR ]') .. ' %s\n', + footer = ' ' .. c.nmbr('%d') .. ' %s\n', + }, + } + + c = nil + + local fileCount = 0 + local fileTestCount = 0 + local testCount = 0 + local successCount = 0 + local skippedCount = 0 + local failureCount = 0 + local errorCount = 0 + + local pendingDescription = function(pending) + local name = pending.name + local string = '' + + if type(pending.message) == 'string' then + string = string .. pending.message .. '\n' + elseif pending.message ~= nil then + string = string .. pretty.write(pending.message) .. '\n' + end + + return string + end + + local failureDescription = function(failure) + local string = failure.randomseed and ('Random seed: ' .. failure.randomseed .. '\n') or '' + if type(failure.message) == 'string' then + string = string .. failure.message + elseif failure.message == nil then + string = string .. 'Nil error' + else + string = string .. pretty.write(failure.message) + end + + string = string .. '\n' + + if options.verbose and failure.trace and failure.trace.traceback then + string = string .. failure.trace.traceback .. '\n' + end + + return string + end + + local getFileLine = function(element) + local fileline = '' + if element.trace or element.trace.short_src then + fileline = colors.cyan(element.trace.short_src) .. ' @ ' .. + colors.cyan(element.trace.currentline) .. ': ' + end + return fileline + end + + local getTestList = function(status, count, list, getDescription) + local string = '' + local header = summaryStrings[status].header + if count > 0 and header then + local tests = (count == 1 and 'test' or 'tests') + local errors = (count == 1 and 'error' or 'errors') + string = header:format(count, status == 'error' and errors or tests) + + local testString = summaryStrings[status].test + if testString then + for _, t in ipairs(list) do + local fullname = getFileLine(t.element) .. colors.bright(t.name) + string = string .. testString:format(fullname) + string = string .. getDescription(t) + end + end + end + return string + end + + local getSummary = function(status, count) + local string = '' + local footer = summaryStrings[status].footer + if count > 0 and footer then + local tests = (count == 1 and 'TEST' or 'TESTS') + local errors = (count == 1 and 'ERROR' or 'ERRORS') + string = footer:format(count, status == 'error' and errors or tests) + end + return string + end + + local getSummaryString = function() + local tests = (successCount == 1 and 'test' or 'tests') + local string = successStatus:format(successCount, tests) + + string = string .. getTestList('skipped', skippedCount, handler.pendings, pendingDescription) + string = string .. getTestList('failure', failureCount, handler.failures, failureDescription) + string = string .. getTestList('error', errorCount, handler.errors, failureDescription) + + string = string .. ((skippedCount + failureCount + errorCount) > 0 and '\n' or '') + string = string .. getSummary('skipped', skippedCount) + string = string .. getSummary('failure', failureCount) + string = string .. getSummary('error', errorCount) + + return string + end + + handler.suiteReset = function() + fileCount = 0 + fileTestCount = 0 + testCount = 0 + successCount = 0 + skippedCount = 0 + failureCount = 0 + errorCount = 0 + + return nil, true + end + + handler.suiteStart = function(suite, count, total, randomseed) + if total > 1 then + io.write(repeatSuiteString:format(count, total)) + end + if randomseed then + io.write(randomizeString:format(randomseed)) + end + io.write(globalSetup) + io.flush() + + return nil, true + end + + local function getElapsedTime(tbl) + if tbl.duration then + return tbl.duration * 1000 + else + return tonumber('nan') + end + end + + handler.suiteEnd = function(suite, count, total) + local elapsedTime_ms = getElapsedTime(suite) + local tests = (testCount == 1 and 'test' or 'tests') + local files = (fileCount == 1 and 'file' or 'files') + io.write(globalTeardown) + io.write(suiteEndString:format(testCount, tests, fileCount, files, elapsedTime_ms)) + io.write(getSummaryString()) + io.flush() + + return nil, true + end + + handler.fileStart = function(file) + fileTestCount = 0 + io.write(fileStartString:format(file.name)) + io.flush() + return nil, true + end + + handler.fileEnd = function(file) + local elapsedTime_ms = getElapsedTime(file) + local tests = (fileTestCount == 1 and 'test' or 'tests') + fileCount = fileCount + 1 + io.write(fileEndString:format(fileTestCount, tests, file.name, elapsedTime_ms)) + io.flush() + return nil, true + end + + handler.testStart = function(element, parent) + io.write(runString:format(handler.getFullName(element))) + io.flush() + + return nil, true + end + + handler.testEnd = function(element, parent, status, debug) + local elapsedTime_ms = getElapsedTime(element) + local string + + fileTestCount = fileTestCount + 1 + testCount = testCount + 1 + if status == 'success' then + successCount = successCount + 1 + string = successString + elseif status == 'pending' then + skippedCount = skippedCount + 1 + string = skippedString + elseif status == 'failure' then + failureCount = failureCount + 1 + string = nil + elseif status == 'error' then + errorCount = errorCount + 1 + string = nil + end + + if string ~= nil then + if elapsedTime_ms == elapsedTime_ms then + string = timeString:format(elapsedTime_ms) .. ' ' .. string + end + io.write(string) + io.flush() + end + + return nil, true + end + + handler.testFailure = function(element, parent, message, debug) + io.write(failureString) + io.flush() + + io.write(failureDescription(handler.failures[#handler.failures])) + io.flush() + return nil, true + end + + handler.testError = function(element, parent, message, debug) + io.write(errorString) + io.flush() + + io.write(failureDescription(handler.errors[#handler.errors])) + io.flush() + return nil, true + end + + handler.error = function(element, parent, message, debug) + if element.descriptor ~= 'it' then + io.write(failureDescription(handler.errors[#handler.errors])) + io.flush() + errorCount = errorCount + 1 + end + + return nil, true + end + + busted.subscribe({ 'suite', 'reset' }, handler.suiteReset) + busted.subscribe({ 'suite', 'start' }, handler.suiteStart) + busted.subscribe({ 'suite', 'end' }, handler.suiteEnd) + busted.subscribe({ 'file', 'start' }, handler.fileStart) + busted.subscribe({ 'file', 'end' }, handler.fileEnd) + busted.subscribe({ 'test', 'start' }, handler.testStart, { predicate = handler.cancelOnPending }) + busted.subscribe({ 'test', 'end' }, handler.testEnd, { predicate = handler.cancelOnPending }) + busted.subscribe({ 'failure', 'it' }, handler.testFailure) + busted.subscribe({ 'error', 'it' }, handler.testError) + busted.subscribe({ 'failure' }, handler.error) + busted.subscribe({ 'error' }, handler.error) + + return handler +end diff --git a/.ci/after_success.sh b/ci/after_success.sh index 0215eb139b..388b6eb714 100755 --- a/.ci/after_success.sh +++ b/ci/after_success.sh @@ -5,4 +5,5 @@ set -o pipefail if [[ -n "${GCOV}" ]]; then coveralls --gcov "$(which "${GCOV}")" --encoding iso-8859-1 || echo 'coveralls upload failed.' + bash <(curl -s https://codecov.io/bash) || echo 'codecov upload failed.' fi diff --git a/.ci/before_cache.sh b/ci/before_cache.sh index dd1fcf2bf7..3d7cc0ec5a 100755 --- a/.ci/before_cache.sh +++ b/ci/before_cache.sh @@ -3,12 +3,15 @@ set -e set -o pipefail +CI_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "${CI_DIR}/common/suite.sh" + # Don't cache pip's log and selfcheck. rm -rf "${HOME}/.cache/pip/log" rm -f "${HOME}/.cache/pip/selfcheck.json" # Update the third-party dependency cache only if the build was successful. -if [[ -f "${SUCCESS_MARKER}" ]]; then +if ended_successfully; then rm -rf "${HOME}/.cache/nvim-deps" mv "${DEPS_BUILD_DIR}" "${HOME}/.cache/nvim-deps" touch "${CACHE_MARKER}" diff --git a/.ci/before_install.sh b/ci/before_install.sh index 9aac37de12..5b36adaef2 100755 --- a/.ci/before_install.sh +++ b/ci/before_install.sh @@ -3,7 +3,7 @@ set -e set -o pipefail -if [[ -n "${CI_TARGET}" ]]; then +if [[ "${CI_TARGET}" == lint ]]; then exit fi diff --git a/.ci/before_script.sh b/ci/before_script.sh index 4a75e89fbe..445996a8df 100755 --- a/.ci/before_script.sh +++ b/ci/before_script.sh @@ -3,7 +3,7 @@ set -e set -o pipefail -if [[ -n "${CI_TARGET}" ]]; then +if [[ "${CI_TARGET}" == lint ]]; then exit fi diff --git a/ci/build.bat b/ci/build.bat new file mode 100644 index 0000000000..6eb22176a9 --- /dev/null +++ b/ci/build.bat @@ -0,0 +1,62 @@ +:: These are native MinGW builds, but they use the toolchain inside +:: MSYS2, this allows using all the dependencies and tools available +:: in MSYS2, but we cannot build inside the MSYS2 shell. +echo on +if "%CONFIGURATION%" == "MINGW_32" ( + set ARCH=i686 + set BITS=32 +) else ( + set ARCH=x86_64 + set BITS=64 +) +if "%CONFIGURATION%" == "MINGW_64-gcov" ( + set USE_GCOV="-DUSE_GCOV=ON" +) + +:: We cannot have sh.exe in the PATH (MinGW) +set PATH=%PATH:C:\Program Files\Git\usr\bin;=% +set PATH=C:\msys64\mingw%BITS%\bin;C:\Windows\System32;C:\Windows;%PATH% +:: The default cpack in the PATH is not CMake +set PATH=C:\Program Files (x86)\CMake\bin\cpack.exe;%PATH% + +:: Build third-party dependencies +C:\msys64\usr\bin\bash -lc "pacman --verbose --noconfirm -Su" || goto :error +C:\msys64\usr\bin\bash -lc "pacman --verbose --noconfirm --needed -S mingw-w64-%ARCH%-cmake mingw-w64-%ARCH%-perl mingw-w64-%ARCH%-diffutils mingw-w64-%ARCH%-unibilium gperf" || goto :error + +:: Setup python (use AppVeyor system python) +C:\Python27\python.exe -m pip install neovim || goto :error +C:\Python35\python.exe -m pip install neovim || goto :error +:: Disambiguate python3 +move c:\Python35\python.exe c:\Python35\python3.exe +set PATH=C:\Python35;C:\Python27;%PATH% +:: Sanity check +python -c "import neovim; print(str(neovim))" || goto :error +python3 -c "import neovim; print(str(neovim))" || goto :error + +mkdir .deps +cd .deps +cmake -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=RelWithDebInfo ..\third-party\ || goto :error +mingw32-make VERBOSE=1 || goto :error +cd .. + +:: Build Neovim +mkdir build +cd build +cmake -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=RelWithDebInfo -DBUSTED_OUTPUT_TYPE=nvim %USE_GCOV% -DGPERF_PRG="C:\msys64\usr\bin\gperf.exe" .. || goto :error +mingw32-make VERBOSE=1 || goto :error +bin\nvim --version || goto :error + +:: Functional tests +mingw32-make functionaltest VERBOSE=1 || goto :error + +if defined USE_GCOV ( + C:\msys64\usr\bin\bash -lc "cd /c/projects/neovim; bash <(curl -s https://codecov.io/bash) || echo 'codecov upload failed.'" +) + +:: Build artifacts +cpack -G ZIP -C RelWithDebInfo +if defined APPVEYOR_REPO_TAG_NAME cpack -G NSIS -C RelWithDebInfo + +goto :EOF +:error +exit /b %errorlevel% diff --git a/.ci/common/build.sh b/ci/common/build.sh index 5cf34935d6..f398a1a1cc 100644 --- a/.ci/common/build.sh +++ b/ci/common/build.sh @@ -1,8 +1,17 @@ +top_make() { + ${MAKE_CMD} "$@" +} + +build_make() { + top_make -C "${BUILD_DIR}" "$@" +} + build_deps() { - if [[ "${BUILD_32BIT}" == ON ]]; then + if test "${BUILD_32BIT}" = ON ; then DEPS_CMAKE_FLAGS="${DEPS_CMAKE_FLAGS} ${CMAKE_FLAGS_32BIT}" fi - if [[ "${FUNCTIONALTEST}" == "functionaltest-lua" ]]; then + if test "${FUNCTIONALTEST}" = "functionaltest-lua" \ + || test "${CLANG_SANITIZER}" = "ASAN_UBSAN" ; then DEPS_CMAKE_FLAGS="${DEPS_CMAKE_FLAGS} -DUSE_BUNDLED_LUA=ON" fi @@ -10,16 +19,15 @@ build_deps() { # If there is a valid cache and we're not forced to recompile, # use cached third-party dependencies. - if [[ -f "${CACHE_MARKER}" ]] && [[ "${BUILD_NVIM_DEPS}" != true ]]; then - if [[ "${TRAVIS_OS_NAME}" == osx ]]; then - local statcmd="stat -f '%Sm'" - else - local statcmd="stat -c '%y'" + if test -f "${CACHE_MARKER}" && test "${BUILD_NVIM_DEPS}" != "true" ; then + local statcmd="stat -c '%y'" + if test "${TRAVIS_OS_NAME}" = osx ; then + statcmd="stat -f '%Sm'" fi echo "Using third-party dependencies from Travis's cache (last updated: $(${statcmd} "${CACHE_MARKER}"))." - mkdir -p "$(dirname "${DEPS_BUILD_DIR}")" - mv "${HOME}/.cache/nvim-deps" "${DEPS_BUILD_DIR}" + mkdir -p "$(dirname "${DEPS_BUILD_DIR}")" + mv "${HOME}/.cache/nvim-deps" "${DEPS_BUILD_DIR}" else mkdir -p "${DEPS_BUILD_DIR}" fi @@ -30,45 +38,47 @@ build_deps() { echo "Configuring with '${DEPS_CMAKE_FLAGS}'." CC= cmake ${DEPS_CMAKE_FLAGS} "${TRAVIS_BUILD_DIR}/third-party/" - if ! ${MAKE_CMD}; then + if ! top_make; then exit 1 fi cd "${TRAVIS_BUILD_DIR}" } -build_nvim() { - if [[ -n "${CLANG_SANITIZER}" ]]; then +prepare_build() { + if test -n "${CLANG_SANITIZER}" ; then CMAKE_FLAGS="${CMAKE_FLAGS} -DCLANG_${CLANG_SANITIZER}=ON" fi - if [[ "${BUILD_32BIT}" == ON ]]; then + if test "${BUILD_32BIT}" = ON ; then CMAKE_FLAGS="${CMAKE_FLAGS} ${CMAKE_FLAGS_32BIT}" fi mkdir -p "${BUILD_DIR}" cd "${BUILD_DIR}" - echo "Configuring with '${CMAKE_FLAGS}'." - cmake ${CMAKE_FLAGS} "${TRAVIS_BUILD_DIR}" + echo "Configuring with '${CMAKE_FLAGS} $@'." + cmake ${CMAKE_FLAGS} "$@" "${TRAVIS_BUILD_DIR}" +} +build_nvim() { echo "Building nvim." - if ! ${MAKE_CMD} nvim; then + if ! top_make nvim ; then exit 1 fi - if [ "$CLANG_SANITIZER" != "TSAN" ]; then + if test "$CLANG_SANITIZER" != "TSAN" ; then echo "Building libnvim." - if ! ${MAKE_CMD} libnvim; then + if ! top_make libnvim ; then exit 1 fi echo "Building nvim-test." - if ! ${MAKE_CMD} nvim-test; then + if ! top_make nvim-test ; then exit 1 fi fi # Invoke nvim to trigger *San early. - if ! (bin/nvim --version && bin/nvim -u NONE -e -c ':qall'); then + if ! (bin/nvim --version && bin/nvim -u NONE -e -c ':qall') ; then asan_check "${LOG_DIR}" exit 1 fi diff --git a/ci/common/suite.sh b/ci/common/suite.sh new file mode 100644 index 0000000000..d3fbcd1eda --- /dev/null +++ b/ci/common/suite.sh @@ -0,0 +1,199 @@ +# HACK: get newline for use in strings given that "\n" and $'' do not work. +NL="$(printf '\nE')" +NL="${NL%E}" + +FAIL_SUMMARY="" + +# Test success marker. If END_MARKER file exists, we know that all tests +# finished. If FAIL_SUMMARY_FILE exists we know that some tests failed, this +# file will contain information about failed tests. Build is considered +# successful if tests ended without any of them failing. +END_MARKER="$BUILD_DIR/.tests_finished" +FAIL_SUMMARY_FILE="$BUILD_DIR/.test_errors" + +ANSI_CLEAR="\033[0K" + +travis_fold() { + local action="$1" + local name="$2" + name="$(echo -n "$name" | tr '\n\0' '--' | sed 's/[^A-Za-z0-9]\{1,\}/-/g')" + name="$(echo -n "$name" | sed 's/-$//')" + echo -en "travis_fold:${action}:${name}\r${ANSI_CLEAR}" +} + +if test "$TRAVIS" != "true" ; then + travis_fold() { + return 0 + } +fi + +enter_suite() { + set +x + FAILED=0 + rm -f "${END_MARKER}" + local suite_name="$1" + export NVIM_TEST_CURRENT_SUITE="${NVIM_TEST_CURRENT_SUITE}/$suite_name" + travis_fold start "${NVIM_TEST_CURRENT_SUITE}" + set -x +} + +exit_suite() { + set +x + if test -f "$NVIM_LOG_FILE" ; then + printf "===============================================================================\n" + printf "NVIM_LOG_FILE: $NVIM_LOG_FILE\n" + cat "$NVIM_LOG_FILE" 2>/dev/null || printf '(empty)' + printf "\n" + rm -rf "$NVIM_LOG_FILE" + fi + travis_fold end "${NVIM_TEST_CURRENT_SUITE}" + if test $FAILED -ne 0 ; then + echo "Suite ${NVIM_TEST_CURRENT_SUITE} failed, summary:" + echo "${FAIL_SUMMARY}" + fi + export NVIM_TEST_CURRENT_SUITE="${NVIM_TEST_CURRENT_SUITE%/*}" + if test "$1" != "--continue" ; then + exit $FAILED + else + local saved_failed=$FAILED + FAILED=0 + return $saved_failed + fi +} + +fail() { + local test_name="$1" + local fail_char="$2" + local message="$3" + + : ${fail_char:=F} + : ${message:=Test $test_name failed} + + local full_msg="$fail_char $NVIM_TEST_CURRENT_SUITE|$test_name :: $message" + FAIL_SUMMARY="${FAIL_SUMMARY}${NL}${full_msg}" + echo "${full_msg}" >> "${FAIL_SUMMARY_FILE}" + echo "Failed: $full_msg" + FAILED=1 +} + +run_test() { + local cmd="$1" + test $# -gt 0 && shift + local test_name="$1" + : ${test_name:=$cmd} + test $# -gt 0 && shift + if ! eval "$cmd" ; then + fail "${test_name}" "$@" + fi +} + +run_test_wd() { + local hang_ok= + if test "$1" = "--allow-hang" ; then + hang_ok=1 + shift + fi + + local timeout="$1" + test $# -gt 0 && shift + + local cmd="$1" + test $# -gt 0 && shift + + local restart_cmd="$1" + : ${restart_cmd:=true} + test $# -gt 0 && shift + + local test_name="$1" + : ${test_name:=$cmd} + test $# -gt 0 && shift + + local output_file="$(mktemp)" + local status_file="$(mktemp)" + local sid_file="$(mktemp)" + + local restarts=5 + local prev_tmpsize=-1 + while test $restarts -gt 0 ; do + : > "$status_file" + : > "$sid_file" + setsid \ + env \ + output_file="$output_file" \ + status_file="$status_file" \ + sid_file="$sid_file" \ + cmd="$cmd" \ + CI_DIR="$CI_DIR" \ + sh -c ' + . "${CI_DIR}/common/test.sh" + ps -o sid= > "$sid_file" + ( + ret=0 + if ! eval "$cmd" 2>&1 ; then + ret=1 + fi + echo "$ret" > "$status_file" + ) | tee -a "$output_file" + ' + while test "$(stat -c "%s" "$status_file")" -eq 0 ; do + prev_tmpsize=$tmpsize + sleep $timeout + tmpsize="$(stat -c "%s" "$output_file")" + if test $tempsize -eq $prev_temsize ; then + # no output, assuming either hang or exit + break + fi + done + restarts=$(( restarts - 1 )) + if test "$(stat -c "%s" "$status_file")" -eq 0 ; then + # Status file not updated, assuming hang + + # SID not known, this should not ever happen + if test "$(stat -c "%s" "$sid_file")" -eq 0 ; then + fail "$test_name" E "Shell did not run" + break + fi + + # Kill all processes which belong to one session: should get rid of test + # processes as well as sh itself. + pkill -KILL -s$(cat "$sid_file") + + if test $restarts -eq 0 ; then + if test -z "$hang_ok" ; then + fail "$test_name" E "Test hang up" + fi + else + echo "Test ${test_name} hang up, restarting" + eval "$restart_cmd" + fi + else + local new_failed="$(cat "$status_file")" + if test "$new_failed" != "0" ; then + fail "$test_name" F "Test failed in run_test_wd" + fi + break + fi + done + + rm -f "$output_file" + rm -f "$status_file" + rm -f "$sid_file" +} + +ended_successfully() { + if test -f "${FAIL_SUMMARY_FILE}" ; then + echo 'Test failed, complete summary:' + cat "${FAIL_SUMMARY_FILE}" + return 1 + fi + if ! test -f "${END_MARKER}" ; then + echo 'ended_successfully called before end marker was touched' + return 1 + fi + return 0 +} + +end_tests() { + touch "${END_MARKER}" + ended_successfully +} diff --git a/ci/common/test.sh b/ci/common/test.sh new file mode 100644 index 0000000000..55f76ca798 --- /dev/null +++ b/ci/common/test.sh @@ -0,0 +1,174 @@ +. "${CI_DIR}/common/build.sh" +. "${CI_DIR}/common/suite.sh" + +print_core() { + local app="$1" + local core="$2" + if test "$app" = quiet ; then + echo "Found core $core" + return 0 + fi + echo "======= Core file $core =======" + if test "${TRAVIS_OS_NAME}" = osx ; then + lldb -Q -o "bt all" -f "${app}" -c "${core}" + else + gdb -n -batch -ex 'thread apply all bt full' "${app}" -c "${core}" + fi +} + +check_core_dumps() { + local del= + if test "$1" = "--delete" ; then + del=1 + shift + fi + local app="${1:-${BUILD_DIR}/bin/nvim}" + if test "${TRAVIS_OS_NAME}" = osx ; then + local cores="$(find /cores/ -type f -print)" + else + local cores="$(find ./ -type f -name 'core.*' -print)" + fi + + if test -z "${cores}" ; then + return + fi + local core + for core in $cores; do + if test "$del" = "1" ; then + print_core "$app" "$core" >&2 + rm "$core" + else + print_core "$app" "$core" + fi + done + if test "$app" != quiet ; then + fail 'cores' E 'Core dumps found' + fi +} + +check_logs() { + # Iterate through each log to remove an useless warning. + for log in $(find "${1}" -type f -name "${2}"); do + sed -i "${log}" \ + -e '/Warning: noted but unhandled ioctl/d' \ + -e '/could cause spurious value errors to appear/d' \ + -e '/See README_MISSING_SYSCALL_OR_IOCTL for guidance/d' + done + + # Now do it again, but only consider files with size > 0. + local err="" + for log in $(find "${1}" -type f -name "${2}" -size +0); do + cat "${log}" + err=1 + done + if test -n "${err}" ; then + fail 'logs' E 'Runtime errors detected.' + fi +} + +valgrind_check() { + check_logs "${1}" "valgrind-*" +} + +asan_check() { + check_logs "${1}" "*san.*" +} + +run_unittests() {( + enter_suite unittests + ulimit -c unlimited || true + if ! build_make unittest ; then + fail 'unittests' F 'Unit tests failed' + fi + check_core_dumps "$(which luajit)" + exit_suite +)} + +run_functionaltests() {( + enter_suite functionaltests + ulimit -c unlimited || true + if ! build_make ${FUNCTIONALTEST}; then + fail 'functionaltests' F 'Functional tests failed' + fi + asan_check "${LOG_DIR}" + valgrind_check "${LOG_DIR}" + check_core_dumps + exit_suite +)} + +run_oldtests() {( + enter_suite oldtests + ulimit -c unlimited || true + if ! make -C "${TRAVIS_BUILD_DIR}/src/nvim/testdir"; then + reset + fail 'oldtests' F 'Legacy tests failed' + fi + asan_check "${LOG_DIR}" + valgrind_check "${LOG_DIR}" + check_core_dumps + exit_suite +)} + +check_runtime_files() {( + set +x + local test_name="$1" ; shift + local message="$1" ; shift + local tst="$1" ; shift + + cd runtime + for file in $(git ls-files "$@") ; do + # Check that test is not trying to work with files with spaces/etc + # Prefer failing the build over using more robust construct because files + # with IFS are not welcome. + if ! test -e "$file" ; then + fail "$test_name" E \ + "It appears that $file is only a part of the file name" + fi + if ! test "$tst" "$INSTALL_PREFIX/share/nvim/runtime/$file" ; then + fail "$test_name" F "$(printf "$message" "$file")" + fi + done +)} + +install_nvim() {( + enter_suite 'install_nvim' + if ! build_make install ; then + fail 'install' E 'make install failed' + exit_suite + fi + + "${INSTALL_PREFIX}/bin/nvim" --version + if ! "${INSTALL_PREFIX}/bin/nvim" -u NONE -e -c ':help' -c ':qall' ; then + echo "Running ':help' in the installed nvim failed." + echo "Maybe the helptags have not been generated properly." + fail 'help' F 'Failed running :help' + fi + + # Check that all runtime files were installed + check_runtime_files \ + 'runtime-install' \ + 'It appears that %s is not installed.' \ + -e \ + '*.vim' '*.ps' '*.dict' '*.py' '*.tutor' + + # Check that some runtime files are installed and are executables + check_runtime_files \ + 'not-exe' \ + 'It appears that %s is not installed or is not executable.' \ + -x \ + '*.awk' '*.sh' '*.bat' + + # Check that generated syntax file has function names, #5060. + local genvimsynf=syntax/vim/generated.vim + local gpat='syn keyword vimFuncName .*eval' + if ! grep -q "$gpat" "${INSTALL_PREFIX}/share/nvim/runtime/$genvimsynf" ; then + fail 'funcnames' F "It appears that $genvimsynf does not contain $gpat." + fi + + exit_suite +)} + +csi_clean() { + find "${BUILD_DIR}/bin" -name 'test-includes-*' -delete + find "${BUILD_DIR}" -name '*test-include*.o' -delete +} diff --git a/.ci/install.sh b/ci/install.sh index 98d3dc01cb..4ee99e1e44 100755 --- a/.ci/install.sh +++ b/ci/install.sh @@ -3,7 +3,7 @@ set -e set -o pipefail -if [[ -n "${CI_TARGET}" ]]; then +if [[ "${CI_TARGET}" == lint ]]; then exit fi diff --git a/ci/run_lint.sh b/ci/run_lint.sh new file mode 100755 index 0000000000..e7f6727448 --- /dev/null +++ b/ci/run_lint.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash + +set -e +set -o pipefail + +CI_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +source "${CI_DIR}/common/build.sh" +source "${CI_DIR}/common/suite.sh" + +enter_suite 'clint' + +run_test 'top_make clint-full' clint + +exit_suite --continue + +enter_suite 'testlint' + +run_test 'top_make testlint' testlint + +exit_suite --continue + +enter_suite 'lualint' + +run_test 'top_make lualint' lualint + +exit_suite --continue + +enter_suite single-includes + +CLICOLOR_FORCE=1 run_test_wd \ + --allow-hang \ + 10s \ + 'top_make check-single-includes' \ + 'csi_clean' \ + single-includes + +exit_suite --continue + +end_tests diff --git a/ci/run_tests.sh b/ci/run_tests.sh new file mode 100755 index 0000000000..a0bf6e010d --- /dev/null +++ b/ci/run_tests.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash + +set -e +set -o pipefail + +CI_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "${CI_DIR}/common/build.sh" +source "${CI_DIR}/common/test.sh" +source "${CI_DIR}/common/suite.sh" + +enter_suite build + +check_core_dumps --delete quiet + +prepare_build +build_nvim + +exit_suite --continue + +enter_suite tests + +if test "$CLANG_SANITIZER" != "TSAN" ; then + # Additional threads are only created when the builtin UI starts, which + # doesn't happen in the unit/functional tests + run_test run_unittests + run_test run_functionaltests +fi +run_test run_oldtests + +run_test install_nvim + +exit_suite --continue + +end_tests diff --git a/.ci/script.sh b/ci/script.sh index 46c4eecf38..a59c40cd2d 100755 --- a/.ci/script.sh +++ b/ci/script.sh @@ -3,16 +3,11 @@ set -e set -o pipefail -if [[ -n "${CI_TARGET}" ]]; then - make "${CI_TARGET}" - exit 0 -fi - # This will pass the environment variables down to a bash process which runs # as $USER, while retaining the environment variables defined and belonging # to secondary groups given above in usermod. if [[ "${TRAVIS_OS_NAME}" == osx ]]; then - sudo -E su "${USER}" -c ".ci/run_tests.sh" + sudo -E su "${USER}" -c "ci/run_${CI_TARGET}.sh" else - .ci/run_tests.sh + ci/run_${CI_TARGET}.sh fi diff --git a/cmake/Download.cmake b/cmake/Download.cmake new file mode 100644 index 0000000000..50a77816bc --- /dev/null +++ b/cmake/Download.cmake @@ -0,0 +1,18 @@ +file( + DOWNLOAD "${URL}" "${FILE}" + STATUS status + LOG log +) + +list(GET status 0 status_code) +list(GET status 1 status_string) + +if(NOT status_code EQUAL 0) + if(NOT ALLOW_FAILURE) + message(FATAL_ERROR "error: downloading '${URL}' failed + status_code: ${status_code} + status_string: ${status_string} + log: ${log} + ") + endif() +endif() diff --git a/cmake/FindJeMalloc.cmake b/cmake/FindJeMalloc.cmake index f36cbc6f7a..f139196a38 100644 --- a/cmake/FindJeMalloc.cmake +++ b/cmake/FindJeMalloc.cmake @@ -4,7 +4,7 @@ # JEMALLOC_INCLUDE_DIRS - The jemalloc include directories # JEMALLOC_LIBRARIES - The libraries needed to use jemalloc -if(NOT JEMALLOC_USE_BUNDLED) +if(NOT USE_BUNDLED_JEMALLOC) find_package(PkgConfig) if (PKG_CONFIG_FOUND) pkg_check_modules(PC_JEMALLOC QUIET jemalloc) @@ -27,6 +27,9 @@ find_path(JEMALLOC_INCLUDE_DIR jemalloc/jemalloc.h if(JEMALLOC_USE_STATIC) list(APPEND JEMALLOC_NAMES "${CMAKE_STATIC_LIBRARY_PREFIX}jemalloc${CMAKE_STATIC_LIBRARY_SUFFIX}") +elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + list(INSERT JEMALLOC_NAMES 0 + "${CMAKE_STATIC_LIBRARY_PREFIX}jemalloc${CMAKE_STATIC_LIBRARY_SUFFIX}") endif() list(APPEND JEMALLOC_NAMES jemalloc) diff --git a/cmake/FindLibTermkey.cmake b/cmake/FindLibTermkey.cmake index 144deceaae..66fd2e6c89 100644 --- a/cmake/FindLibTermkey.cmake +++ b/cmake/FindLibTermkey.cmake @@ -4,7 +4,7 @@ # LIBTERMKEY_INCLUDE_DIRS - The libtermkey include directories # LIBTERMKEY_LIBRARIES - The libraries needed to use libtermkey -if(NOT LIBTERMKEY_USE_BUNDLED) +if(NOT USE_BUNDLED_LIBTERMKEY) find_package(PkgConfig) if (PKG_CONFIG_FOUND) pkg_check_modules(PC_LIBTERMKEY QUIET termkey) diff --git a/cmake/FindLibUV.cmake b/cmake/FindLibUV.cmake index dcdd5e48b7..3a60a831ea 100644 --- a/cmake/FindLibUV.cmake +++ b/cmake/FindLibUV.cmake @@ -8,7 +8,7 @@ # Set the LIBUV_USE_STATIC variable to specify if static libraries should # be preferred to shared ones. -if(NOT LIBUV_USE_BUNDLED) +if(NOT USE_BUNDLED_LIBUV) find_package(PkgConfig) if (PKG_CONFIG_FOUND) pkg_check_modules(PC_LIBUV QUIET libuv) @@ -65,7 +65,7 @@ if(HAVE_LIBKSTAT) endif() check_library_exists(kvm kvm_open "kvm.h" HAVE_LIBKVM) -if(HAVE_LIBKVM) +if(HAVE_LIBKVM AND NOT CMAKE_SYSTEM_NAME STREQUAL "OpenBSD") list(APPEND LIBUV_LIBRARIES kvm) endif() diff --git a/cmake/FindLibVterm.cmake b/cmake/FindLibVterm.cmake index 0d773d8896..2cbd3215c5 100644 --- a/cmake/FindLibVterm.cmake +++ b/cmake/FindLibVterm.cmake @@ -4,7 +4,7 @@ # LIBVTERM_INCLUDE_DIRS - The libvterm include directories # LIBVTERM_LIBRARIES - The libraries needed to use libvterm -if(NOT LIBVTERM_USE_BUNDLED) +if(NOT USE_BUNDLED_LIBVTERM) find_package(PkgConfig) if (PKG_CONFIG_FOUND) pkg_check_modules(PC_LIBVTERM QUIET vterm) diff --git a/cmake/FindLua.cmake b/cmake/FindLua.cmake new file mode 100644 index 0000000000..b669a49f29 --- /dev/null +++ b/cmake/FindLua.cmake @@ -0,0 +1,197 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#.rst: +# FindLua +# ------- +# +# +# +# Locate Lua library This module defines +# +# :: +# +# LUA_FOUND - if false, do not try to link to Lua +# LUA_LIBRARIES - both lua and lualib +# LUA_INCLUDE_DIR - where to find lua.h +# LUA_VERSION_STRING - the version of Lua found +# LUA_VERSION_MAJOR - the major version of Lua +# LUA_VERSION_MINOR - the minor version of Lua +# LUA_VERSION_PATCH - the patch version of Lua +# +# +# +# Note that the expected include convention is +# +# :: +# +# #include "lua.h" +# +# and not +# +# :: +# +# #include <lua/lua.h> +# +# This is because, the lua location is not standardized and may exist in +# locations other than lua/ + +unset(_lua_include_subdirs) +unset(_lua_library_names) +unset(_lua_append_versions) + +# this is a function only to have all the variables inside go away automatically +function(_lua_set_version_vars) + set(LUA_VERSIONS5 5.3 5.2 5.1 5.0) + + if (Lua_FIND_VERSION_EXACT) + if (Lua_FIND_VERSION_COUNT GREATER 1) + set(_lua_append_versions ${Lua_FIND_VERSION_MAJOR}.${Lua_FIND_VERSION_MINOR}) + endif () + elseif (Lua_FIND_VERSION) + # once there is a different major version supported this should become a loop + if (NOT Lua_FIND_VERSION_MAJOR GREATER 5) + if (Lua_FIND_VERSION_COUNT EQUAL 1) + set(_lua_append_versions ${LUA_VERSIONS5}) + else () + foreach (subver IN LISTS LUA_VERSIONS5) + if (NOT subver VERSION_LESS ${Lua_FIND_VERSION}) + list(APPEND _lua_append_versions ${subver}) + endif () + endforeach () + endif () + endif () + else () + # once there is a different major version supported this should become a loop + set(_lua_append_versions ${LUA_VERSIONS5}) + endif () + + list(APPEND _lua_include_subdirs "include/lua" "include") + + foreach (ver IN LISTS _lua_append_versions) + string(REGEX MATCH "^([0-9]+)\\.([0-9]+)$" _ver "${ver}") + list(APPEND _lua_include_subdirs + include/lua${CMAKE_MATCH_1}${CMAKE_MATCH_2} + include/lua${CMAKE_MATCH_1}.${CMAKE_MATCH_2} + include/lua-${CMAKE_MATCH_1}.${CMAKE_MATCH_2} + ) + endforeach () + + set(_lua_include_subdirs "${_lua_include_subdirs}" PARENT_SCOPE) + set(_lua_append_versions "${_lua_append_versions}" PARENT_SCOPE) +endfunction(_lua_set_version_vars) + +function(_lua_check_header_version _hdr_file) + # At least 5.[012] have different ways to express the version + # so all of them need to be tested. Lua 5.2 defines LUA_VERSION + # and LUA_RELEASE as joined by the C preprocessor, so avoid those. + file(STRINGS "${_hdr_file}" lua_version_strings + REGEX "^#define[ \t]+LUA_(RELEASE[ \t]+\"Lua [0-9]|VERSION([ \t]+\"Lua [0-9]|_[MR])).*") + + string(REGEX REPLACE ".*;#define[ \t]+LUA_VERSION_MAJOR[ \t]+\"([0-9])\"[ \t]*;.*" "\\1" LUA_VERSION_MAJOR ";${lua_version_strings};") + if (LUA_VERSION_MAJOR MATCHES "^[0-9]+$") + string(REGEX REPLACE ".*;#define[ \t]+LUA_VERSION_MINOR[ \t]+\"([0-9])\"[ \t]*;.*" "\\1" LUA_VERSION_MINOR ";${lua_version_strings};") + string(REGEX REPLACE ".*;#define[ \t]+LUA_VERSION_RELEASE[ \t]+\"([0-9])\"[ \t]*;.*" "\\1" LUA_VERSION_PATCH ";${lua_version_strings};") + set(LUA_VERSION_STRING "${LUA_VERSION_MAJOR}.${LUA_VERSION_MINOR}.${LUA_VERSION_PATCH}") + else () + string(REGEX REPLACE ".*;#define[ \t]+LUA_RELEASE[ \t]+\"Lua ([0-9.]+)\"[ \t]*;.*" "\\1" LUA_VERSION_STRING ";${lua_version_strings};") + if (NOT LUA_VERSION_STRING MATCHES "^[0-9.]+$") + string(REGEX REPLACE ".*;#define[ \t]+LUA_VERSION[ \t]+\"Lua ([0-9.]+)\"[ \t]*;.*" "\\1" LUA_VERSION_STRING ";${lua_version_strings};") + endif () + string(REGEX REPLACE "^([0-9]+)\\.[0-9.]*$" "\\1" LUA_VERSION_MAJOR "${LUA_VERSION_STRING}") + string(REGEX REPLACE "^[0-9]+\\.([0-9]+)[0-9.]*$" "\\1" LUA_VERSION_MINOR "${LUA_VERSION_STRING}") + string(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([0-9]).*" "\\1" LUA_VERSION_PATCH "${LUA_VERSION_STRING}") + endif () + foreach (ver IN LISTS _lua_append_versions) + if (ver STREQUAL "${LUA_VERSION_MAJOR}.${LUA_VERSION_MINOR}") + set(LUA_VERSION_MAJOR ${LUA_VERSION_MAJOR} PARENT_SCOPE) + set(LUA_VERSION_MINOR ${LUA_VERSION_MINOR} PARENT_SCOPE) + set(LUA_VERSION_PATCH ${LUA_VERSION_PATCH} PARENT_SCOPE) + set(LUA_VERSION_STRING ${LUA_VERSION_STRING} PARENT_SCOPE) + return() + endif () + endforeach () +endfunction(_lua_check_header_version) + +_lua_set_version_vars() + +if (LUA_INCLUDE_DIR AND EXISTS "${LUA_INCLUDE_DIR}/lua.h") + _lua_check_header_version("${LUA_INCLUDE_DIR}/lua.h") +endif () + +if (NOT LUA_VERSION_STRING) + foreach (subdir IN LISTS _lua_include_subdirs) + unset(LUA_INCLUDE_PREFIX CACHE) + find_path(LUA_INCLUDE_PREFIX ${subdir}/lua.h + HINTS + ENV LUA_DIR + PATHS + ~/Library/Frameworks + /Library/Frameworks + /sw # Fink + /opt/local # DarwinPorts + /opt/csw # Blastwave + /opt + ) + if (LUA_INCLUDE_PREFIX) + _lua_check_header_version("${LUA_INCLUDE_PREFIX}/${subdir}/lua.h") + if (LUA_VERSION_STRING) + set(LUA_INCLUDE_DIR "${LUA_INCLUDE_PREFIX}/${subdir}") + break() + endif () + endif () + endforeach () +endif () +unset(_lua_include_subdirs) +unset(_lua_append_versions) + +if (LUA_VERSION_STRING) + set(_lua_library_names + lua${LUA_VERSION_MAJOR}${LUA_VERSION_MINOR} + lua${LUA_VERSION_MAJOR}.${LUA_VERSION_MINOR} + lua-${LUA_VERSION_MAJOR}.${LUA_VERSION_MINOR} + lua.${LUA_VERSION_MAJOR}.${LUA_VERSION_MINOR} + ) +endif () + +find_library(LUA_LIBRARY + NAMES ${_lua_library_names} lua + HINTS + ENV LUA_DIR + PATH_SUFFIXES lib + PATHS + ~/Library/Frameworks + /Library/Frameworks + /sw + /opt/local + /opt/csw + /opt +) +unset(_lua_library_names) + +if (LUA_LIBRARY) + # include the math library for Unix + if (UNIX AND NOT APPLE AND NOT BEOS) + find_library(LUA_MATH_LIBRARY m) + set(LUA_LIBRARIES "${LUA_LIBRARY};${LUA_MATH_LIBRARY}") + + # include dl library for statically-linked Lua library + get_filename_component(LUA_LIB_EXT ${LUA_LIBRARY} EXT) + if(LUA_LIB_EXT STREQUAL CMAKE_STATIC_LIBRARY_SUFFIX) + list(APPEND LUA_LIBRARIES ${CMAKE_DL_LIBS}) + endif() + + # For Windows and Mac, don't need to explicitly include the math library + else () + set(LUA_LIBRARIES "${LUA_LIBRARY}") + endif () +endif () + +include(FindPackageHandleStandardArgs) +# handle the QUIETLY and REQUIRED arguments and set LUA_FOUND to TRUE if +# all listed variables are TRUE +FIND_PACKAGE_HANDLE_STANDARD_ARGS(Lua + REQUIRED_VARS LUA_LIBRARIES LUA_INCLUDE_DIR + VERSION_VAR LUA_VERSION_STRING) + +mark_as_advanced(LUA_INCLUDE_DIR LUA_LIBRARY LUA_MATH_LIBRARY) diff --git a/cmake/FindLuaJit.cmake b/cmake/FindLuaJit.cmake index e9ff53ab62..b8eda6388b 100644 --- a/cmake/FindLuaJit.cmake +++ b/cmake/FindLuaJit.cmake @@ -4,7 +4,7 @@ # LUAJIT_INCLUDE_DIRS - The luajit include directories # LUAJIT_LIBRARIES - The libraries needed to use luajit -if(NOT LUAJIT_USE_BUNDLED) +if(NOT USE_BUNDLED_LUAJIT) find_package(PkgConfig) if (PKG_CONFIG_FOUND) pkg_check_modules(PC_LUAJIT QUIET luajit) diff --git a/cmake/FindMsgpack.cmake b/cmake/FindMsgpack.cmake index 8881a34332..6716289a98 100644 --- a/cmake/FindMsgpack.cmake +++ b/cmake/FindMsgpack.cmake @@ -4,7 +4,7 @@ # MSGPACK_INCLUDE_DIRS - The msgpack include directories # MSGPACK_LIBRARIES - The libraries needed to use msgpack -if(NOT MSGPACK_USE_BUNDLED) +if(NOT USE_BUNDLED_MSGPACK) find_package(PkgConfig) if (PKG_CONFIG_FOUND) pkg_search_module(PC_MSGPACK QUIET diff --git a/cmake/FindUnibilium.cmake b/cmake/FindUnibilium.cmake index e1e0de9b7e..cf0ccda877 100644 --- a/cmake/FindUnibilium.cmake +++ b/cmake/FindUnibilium.cmake @@ -4,7 +4,7 @@ # UNIBILIUM_INCLUDE_DIRS - The unibilium include directories # UNIBILIUM_LIBRARIES - The libraries needed to use unibilium -if(NOT UNIBILIUM_USE_BUNDLED) +if(NOT USE_BUNDLED_UNIBILIUM) find_package(PkgConfig) if (PKG_CONFIG_FOUND) pkg_check_modules(PC_UNIBILIUM QUIET unibilium) diff --git a/cmake/FindWinpty.cmake b/cmake/FindWinpty.cmake new file mode 100644 index 0000000000..8feafc58a8 --- /dev/null +++ b/cmake/FindWinpty.cmake @@ -0,0 +1,10 @@ +include(LibFindMacros) + +find_path(WINPTY_INCLUDE_DIR winpty.h) +set(WINPTY_INCLUDE_DIRS ${WINPTY_INCLUDE_DIR}) + +find_library(WINPTY_LIBRARY winpty) +find_program(WINPTY_AGENT_EXE winpty-agent.exe) +set(WINPTY_LIBRARIES ${WINPTY_LIBRARY}) + +find_package_handle_standard_args(Winpty DEFAULT_MSG WINPTY_LIBRARY WINPTY_INCLUDE_DIR) diff --git a/cmake/InstallClintErrors.cmake b/cmake/InstallClintErrors.cmake new file mode 100644 index 0000000000..bd5ca07828 --- /dev/null +++ b/cmake/InstallClintErrors.cmake @@ -0,0 +1,2 @@ +file(GLOB_RECURSE JSON_FILES *.json) +file(COPY ${JSON_FILES} DESTINATION "${TARGET}") diff --git a/cmake/InstallHelpers.cmake b/cmake/InstallHelpers.cmake index ee07ba2c66..ca20ddf354 100644 --- a/cmake/InstallHelpers.cmake +++ b/cmake/InstallHelpers.cmake @@ -1,3 +1,12 @@ +# Fix CMAKE_INSTALL_MANDIR on BSD before including GNUInstallDirs. #6771 +if(CMAKE_SYSTEM_NAME MATCHES "BSD" AND NOT DEFINED CMAKE_INSTALL_MANDIR) + if(DEFINED ENV{MANPREFIX}) + set(CMAKE_INSTALL_MANDIR "$ENV{MANPREFIX}/man") + else() + set(CMAKE_INSTALL_MANDIR "/usr/local/man") + endif() +endif() + # For $CMAKE_INSTALL_{DATAROOT,MAN, ...}DIR include(GNUInstallDirs) diff --git a/cmake/RunLint.cmake b/cmake/RunLint.cmake deleted file mode 100644 index 306e938232..0000000000 --- a/cmake/RunLint.cmake +++ /dev/null @@ -1,32 +0,0 @@ -get_filename_component(LINT_DIR ${LINT_DIR} ABSOLUTE) -get_filename_component(LINT_PREFIX ${LINT_DIR} PATH) -set(LINT_SUPPRESS_FILE "${LINT_PREFIX}/errors.json") - -if(DEFINED ENV{LINT_FILE}) - file(GLOB_RECURSE LINT_FILES "$ENV{LINT_FILE}") -else() - file(GLOB_RECURSE LINT_FILES ${LINT_DIR}/*.c ${LINT_DIR}/*.h) -endif() - -set(LINT_ARGS) - -if(LINT_SUPPRESS_URL) - file(DOWNLOAD ${LINT_SUPPRESS_URL} ${LINT_SUPPRESS_FILE}) - list(APPEND LINT_ARGS "--suppress-errors=${LINT_SUPPRESS_FILE}") -endif() - -foreach(lint_file ${LINT_FILES}) - file(RELATIVE_PATH lint_file "${LINT_PREFIX}" "${lint_file}") - list(APPEND LINT_ARGS "${lint_file}") -endforeach() - -execute_process( - COMMAND ${LINT_PRG} ${LINT_ARGS} - RESULT_VARIABLE res - WORKING_DIRECTORY "${LINT_PREFIX}") - -file(REMOVE ${LINT_SUPPRESS_FILE}) - -if(NOT res EQUAL 0) - message(FATAL_ERROR "Linting failed: ${res}.") -endif() diff --git a/cmake/RunLuacheck.cmake b/cmake/RunLuacheck.cmake new file mode 100644 index 0000000000..5129541cd8 --- /dev/null +++ b/cmake/RunLuacheck.cmake @@ -0,0 +1,22 @@ +set(LUACHECK_ARGS -q "${LUAFILES_DIR}") +if(DEFINED IGNORE_PATTERN) + list(APPEND LUACHECK_ARGS --exclude-files "${LUAFILES_DIR}/${IGNORE_PATTERN}") +endif() +if(DEFINED CHECK_PATTERN) + list(APPEND LUACHECK_ARGS --include-files "${LUAFILES_DIR}/${CHECK_PATTERN}") +endif() +if(DEFINED READ_GLOBALS) + list(APPEND LUACHECK_ARGS --read-globals "${READ_GLOBALS}") +endif() + +execute_process( + COMMAND "${LUACHECK_PRG}" ${LUACHECK_ARGS} + WORKING_DIRECTORY "${LUAFILES_DIR}" + ERROR_VARIABLE err + RESULT_VARIABLE res +) + +if(NOT res EQUAL 0) + message(STATUS "Output to stderr:\n${err}") + message(FATAL_ERROR "Linting tests failed with error: ${res}.") +endif() diff --git a/cmake/RunTests.cmake b/cmake/RunTests.cmake index 58f19b6fa5..95c06aeb94 100644 --- a/cmake/RunTests.cmake +++ b/cmake/RunTests.cmake @@ -1,13 +1,17 @@ -get_filename_component(BUSTED_DIR ${BUSTED_PRG} PATH) -set(ENV{PATH} "${BUSTED_DIR}:$ENV{PATH}") +# Set LC_ALL to meet expectations of some locale-sensitive tests. +set(ENV{LC_ALL} "en_US.UTF-8") set(ENV{VIMRUNTIME} ${WORKING_DIR}/runtime) set(ENV{NVIM_RPLUGIN_MANIFEST} ${WORKING_DIR}/Xtest_rplugin_manifest) set(ENV{XDG_CONFIG_HOME} ${WORKING_DIR}/Xtest_xdg/config) set(ENV{XDG_DATA_HOME} ${WORKING_DIR}/Xtest_xdg/share) +if(NOT DEFINED ENV{NVIM_LOG_FILE}) + set(ENV{NVIM_LOG_FILE} ${WORKING_DIR}/.nvimlog) +endif() + if(NVIM_PRG) - set(ENV{NVIM_PROG} "${NVIM_PRG}") + set(ENV{NVIM_PRG} "${NVIM_PRG}") endif() if(DEFINED ENV{TEST_FILE}) @@ -28,6 +32,8 @@ if(DEFINED ENV{TEST_FILTER}) set(TEST_TAG "--filter=$ENV{TEST_FILTER}") endif() +execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${WORKING_DIR}/Xtest-tmpdir) +set(ENV{TMPDIR} ${WORKING_DIR}/Xtest-tmpdir) set(ENV{SYSTEM_NAME} ${SYSTEM_NAME}) execute_process( COMMAND ${BUSTED_PRG} ${TEST_TAG} ${TEST_FILTER} -v -o ${BUSTED_OUTPUT_TYPE} @@ -40,6 +46,7 @@ execute_process( file(REMOVE ${WORKING_DIR}/Xtest_rplugin_manifest) file(REMOVE_RECURSE ${WORKING_DIR}/Xtest_xdg) +file(REMOVE_RECURSE ${WORKING_DIR}/Xtest-tmpdir) if(NOT res EQUAL 0) message(STATUS "Output to stderr:\n${err}") diff --git a/cmake/RunTestsLint.cmake b/cmake/RunTestsLint.cmake deleted file mode 100644 index addc9ab35e..0000000000 --- a/cmake/RunTestsLint.cmake +++ /dev/null @@ -1,13 +0,0 @@ -set(IGNORE_FILES "${TEST_DIR}/*/preload.lua") - -execute_process( - COMMAND ${LUACHECK_PRG} -q ${TEST_DIR} --exclude-files ${IGNORE_FILES} - WORKING_DIRECTORY ${TEST_DIR} - ERROR_VARIABLE err - RESULT_VARIABLE res - ${EXTRA_ARGS}) - -if(NOT res EQUAL 0) - message(STATUS "Output to stderr:\n${err}") - message(FATAL_ERROR "Linting tests failed with error: ${res}.") -endif() diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 0000000000..0b3de06b97 --- /dev/null +++ b/codecov.yml @@ -0,0 +1,27 @@ +codecov: + notify: + require_ci_to_pass: yes + ci: + - appveyor + - travis + - !neovim-qb.szakmeister.net + +coverage: + precision: 2 + round: down + range: "70...100" + + status: + project: yes + patch: yes + changes: no + +parsers: + gcov: + branch_detection: + conditional: yes + loop: yes + method: no + macro: no + +comment: off diff --git a/config/config.h.in b/config/config.h.in index f26b5a50a8..962eefd7a7 100644 --- a/config/config.h.in +++ b/config/config.h.in @@ -68,4 +68,6 @@ #cmakedefine ORDER_BIG_ENDIAN #define ENDIAN_INCLUDE_FILE <@ENDIAN_INCLUDE_FILE@> +#cmakedefine HAVE_EXECINFO_BACKTRACE + #endif // AUTO_CONFIG_H diff --git a/contrib/YouCompleteMe/README.md b/contrib/YouCompleteMe/README.md index 0c07440a44..345a9d8d12 100644 --- a/contrib/YouCompleteMe/README.md +++ b/contrib/YouCompleteMe/README.md @@ -2,7 +2,9 @@ ## 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 developers working on 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 @@ -13,10 +15,17 @@ Install [YouCompleteMe](https://github.com/Valloric/YouCompleteMe). ### Step 2 ```bash -cp contrib/YouCompleteMe/ycm_extra_conf.py src/.ycm_extra_conf.py +cp contrib/YouCompleteMe/ycm_extra_conf.py .ycm_extra_conf.py echo .ycm_extra_conf.py >> .git/info/exclude make +``` + +Tip: to improve source code navigation, add something like this to your nvim +configuration: -(Add the following somewhere in your vimrc) -autocmd FileType c nnoremap <buffer> <silent> <C-]> :YcmCompleter GoTo<cr> +```vim +au FileType c,cpp nnoremap <buffer> <c-]> :YcmCompleter GoTo<CR> ``` + +And use `ctrl+]` when the cursor is positioned in a symbol to quickly jump to a +definition or declaration. diff --git a/contrib/YouCompleteMe/ycm_extra_conf.py b/contrib/YouCompleteMe/ycm_extra_conf.py index 7c54677c8f..e436609ce2 100644 --- a/contrib/YouCompleteMe/ycm_extra_conf.py +++ b/contrib/YouCompleteMe/ycm_extra_conf.py @@ -9,47 +9,57 @@ def DirectoryOfThisScript(): def GetDatabase(): compilation_database_folder = os.path.join(DirectoryOfThisScript(), - '..', 'build') + 'build') if os.path.exists(compilation_database_folder): return ycm_core.CompilationDatabase(compilation_database_folder) return None -def IsHeaderFile(filename): - extension = os.path.splitext(filename)[1] - return extension == '.h' - - def GetCompilationInfoForFile(filename): database = GetDatabase() if not database: return None - if IsHeaderFile(filename): - basename = os.path.splitext(filename)[0] - c_file = basename + '.c' - # for pure headers (no c file), default to main.c - if not os.path.exists(c_file): - c_file = os.path.join(DirectoryOfThisScript(), 'nvim', 'main.c') - if os.path.exists(c_file): - compilation_info = database.GetCompilationInfoForFile(c_file) - if compilation_info.compiler_flags_: - return compilation_info - return None return database.GetCompilationInfoForFile(filename) +# It seems YCM does not resolve directories correctly. This function will +# adjust paths in the compiler flags to be absolute +def FixDirectories(args, compiler_working_dir): + def adjust_path(path): + return os.path.abspath(os.path.join(compiler_working_dir, path)) + + adjust_next_arg = False + new_args = [] + for arg in args: + if adjust_next_arg: + arg = adjust_path(arg) + adjust_next_arg = False + else: + for dir_flag in ['-I', '-isystem', '-o', '-c']: + if arg.startswith(dir_flag): + if arg != dir_flag: + # flag and path are concatenated in same arg + path = arg[len(dir_flag):] + new_path = adjust_path(path) + arg = '{0}{1}'.format(dir_flag, new_path) + else: + # path is specified in next argument + adjust_next_arg = True + new_args.append(arg) + return new_args + + def FlagsForFile(filename): compilation_info = GetCompilationInfoForFile(filename) if not compilation_info: return None # Add flags not needed for clang-the-binary, # but needed for libclang-the-library (YCM uses this last one). - flags = (list(compilation_info.compiler_flags_) - if compilation_info.compiler_flags_ - else []) + flags = FixDirectories((list(compilation_info.compiler_flags_) + if compilation_info.compiler_flags_ + else []), compilation_info.compiler_working_dir_) extra_flags = ['-Wno-newline-eof'] - final_flags = flags + extra_flags return { - 'flags': final_flags, + 'flags': flags + extra_flags, 'do_cache': True } diff --git a/contrib/local.mk.example b/contrib/local.mk.example index a0b2d034e1..23fe11622b 100644 --- a/contrib/local.mk.example +++ b/contrib/local.mk.example @@ -13,27 +13,21 @@ # Sets the build type; defaults to Debug. Valid values: # -# - Debug: Disables optimizations (-O0), enables debug information and logging. +# - Debug: Disables optimizations (-O0), enables debug information. # -# - Dev: Enables all optimizations that do not interfere with -# debugging (-Og if available, -O2 and -g if not). -# Enables debug information and logging. -# -# - RelWithDebInfo: Enables optimizations (-O2) and debug information. -# Disables logging. +# - RelWithDebInfo: Enables optimizations (-Og or -O2) with debug information. # # - 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 and logging. +# Disables debug information. # # - Release: Same as RelWithDebInfo, but disables debug information. # # CMAKE_BUILD_TYPE := Debug -# By default, nvim's log level is INFO (1) (unless CMAKE_BUILD_TYPE is -# "Release", in which case logging is disabled). -# The log level must be a number DEBUG (0), INFO (1), WARNING (2) or ERROR (3). +# Log levels: 0 (DEBUG), 1 (INFO), 2 (WARNING), 3 (ERROR) +# Default is 1 (INFO) unless CMAKE_BUILD_TYPE is Release or RelWithDebInfo. # CMAKE_EXTRA_FLAGS += -DMIN_LOG_LEVEL=1 # By default, nvim uses bundled versions of its required third-party @@ -62,3 +56,12 @@ # CMAKE_EXTRA_FLAGS += -DLIBVTERM_USE_STATIC=OFF # CMAKE_EXTRA_FLAGS += -DLUAJIT_USE_STATIC=OFF # CMAKE_EXTRA_FLAGS += -DMSGPACK_USE_STATIC=OFF +# +# +# .DEFAULT_GOAL := nvim +# +# Run doxygen over the source code. +# Output will be in build/doxygen +# +# doxygen: +# doxygen src/Doxyfile diff --git a/man/nvim.1 b/man/nvim.1 index 70bf480f2b..d2a3ea5c43 100644 --- a/man/nvim.1 +++ b/man/nvim.1 @@ -371,26 +371,6 @@ See Used to set the 'shell' option, which determines the shell used by the .Ic :terminal command. -.It Ev NVIM_TUI_ENABLE_CURSOR_SHAPE -If defined, change the cursor shape to a vertical bar while in insert mode. -Requires that the host terminal supports the DECSCUSR CSI escape sequence. -Has no effect in GUIs. -.Pp -Depending on the terminal emulator, using this option with -.Nm -under -.Xr tmux 1 -might require adding the following to -.Pa ~/.tmux.conf : -.Bd -literal -offset indent -set -ga terminal-overrides ',*:Ss=\eE[%p1%d q:Se=\eE[2 q' -.Ed -.Pp -See -.Ic terminal-overrides -in the -.Xr tmux 1 -manual page for more information. .El .Sh FILES .Bl -tag -width "~/.config/nvim/init.vim" diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt index cced1a8d04..a9efc90b87 100644 --- a/runtime/CMakeLists.txt +++ b/runtime/CMakeLists.txt @@ -114,6 +114,16 @@ install_helper( FILES ${GENERATED_SYN_VIM} DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/nvim/runtime/syntax/vim) +if(NOT APPLE) + install_helper( + FILES ${CMAKE_CURRENT_SOURCE_DIR}/nvim.desktop + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/applications) + + install_helper( + FILES ${CMAKE_CURRENT_SOURCE_DIR}/nvim.png + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/pixmaps) +endif() + file(GLOB_RECURSE RUNTIME_PROGRAMS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.awk *.sh *.bat) diff --git a/runtime/autoload/ada.vim b/runtime/autoload/ada.vim index cc5191fa43..ce3a19369a 100644 --- a/runtime/autoload/ada.vim +++ b/runtime/autoload/ada.vim @@ -2,12 +2,13 @@ " Description: Perform Ada specific completion & tagging. " Language: Ada (2005) " $Id: ada.vim 887 2008-07-08 14:29:01Z krischik $ -" Maintainer: Martin Krischik <krischik@users.sourceforge.net> +" Maintainer: Mathias Brousset <mathiasb17@gmail.com> +" Martin Krischik <krischik@users.sourceforge.net> " Taylor Venable <taylor@metasyntax.net> " Neil Bird <neil@fnxweb.com> " Ned Okie <nokie@radford.edu> " $Author: krischik $ -" $Date: 2008-07-08 16:29:01 +0200 (Di, 08 Jul 2008) $ +" $Date: 2017-01-31 20:20:05 +0200 (Mon, 01 Jan 2017) $ " Version: 4.6 " $Revision: 887 $ " $HeadURL: https://gnuada.svn.sourceforge.net/svnroot/gnuada/trunk/tools/vim/autoload/ada.vim $ @@ -23,6 +24,7 @@ " 09.05.2007 MK Session just won't work no matter how much " tweaking is done " 19.09.2007 NO still some mapleader problems +" 31.01.2017 MB fix more mapleader problems " Help Page: ft-ada-functions "------------------------------------------------------------------------------ @@ -585,11 +587,11 @@ function ada#Map_Menu (Text, Keys, Command) \ " :" . a:Command . "<CR>" execute \ "nnoremap <buffer>" . - \ escape(l:leader . "a" . a:Keys , '\') . + \ " <Leader>a" . a:Keys . \" :" . a:Command execute \ "inoremap <buffer>" . - \ escape(l:leader . "a" . a:Keys , '\') . + \ " <Learder>a" . a:Keys . \" <C-O>:" . a:Command endif return diff --git a/runtime/autoload/context.vim b/runtime/autoload/context.vim new file mode 100644 index 0000000000..254d710c01 --- /dev/null +++ b/runtime/autoload/context.vim @@ -0,0 +1,184 @@ +" Language: ConTeXt typesetting engine +" Maintainer: Nicola Vitacolonna <nvitacolonna@gmail.com> +" Latest Revision: 2016 Oct 21 + +let s:keepcpo= &cpo +set cpo&vim + +" Helper functions {{{ +function! s:context_echo(message, mode) + redraw + echo "\r" + execute 'echohl' a:mode + echomsg '[ConTeXt]' a:message + echohl None +endf + +function! s:sh() + return has('win32') || has('win64') || has('win16') || has('win95') + \ ? ['cmd.exe', '/C'] + \ : ['/bin/sh', '-c'] +endfunction + +" For backward compatibility +if exists('*win_getid') + + function! s:win_getid() + return win_getid() + endf + + function! s:win_id2win(winid) + return win_id2win(a:winid) + endf + +else + + function! s:win_getid() + return winnr() + endf + + function! s:win_id2win(winnr) + return a:winnr + endf + +endif +" }}} + +" ConTeXt jobs {{{ +if has('job') + + let g:context_jobs = [] + + " Print the status of ConTeXt jobs + function! context#job_status() + let l:jobs = filter(g:context_jobs, 'job_status(v:val) == "run"') + let l:n = len(l:jobs) + call s:context_echo( + \ 'There '.(l:n == 1 ? 'is' : 'are').' '.(l:n == 0 ? 'no' : l:n) + \ .' job'.(l:n == 1 ? '' : 's').' running' + \ .(l:n == 0 ? '.' : ' (' . join(l:jobs, ', ').').'), + \ 'ModeMsg') + endfunction + + " Stop all ConTeXt jobs + function! context#stop_jobs() + let l:jobs = filter(g:context_jobs, 'job_status(v:val) == "run"') + for job in l:jobs + call job_stop(job) + endfor + sleep 1 + let l:tmp = [] + for job in l:jobs + if job_status(job) == "run" + call add(l:tmp, job) + endif + endfor + let g:context_jobs = l:tmp + if empty(g:context_jobs) + call s:context_echo('Done. No jobs running.', 'ModeMsg') + else + call s:context_echo('There are still some jobs running. Please try again.', 'WarningMsg') + endif + endfunction + + function! context#callback(path, job, status) + if index(g:context_jobs, a:job) != -1 && job_status(a:job) != 'run' " just in case + call remove(g:context_jobs, index(g:context_jobs, a:job)) + endif + call s:callback(a:path, a:job, a:status) + endfunction + + function! context#close_cb(channel) + call job_status(ch_getjob(a:channel)) " Trigger exit_cb's callback for faster feedback + endfunction + + function! s:typeset(path) + call add(g:context_jobs, + \ job_start(add(s:sh(), context#command() . ' ' . shellescape(fnamemodify(a:path, ":t"))), { + \ 'close_cb' : 'context#close_cb', + \ 'exit_cb' : function(get(b:, 'context_callback', get(g:, 'context_callback', 'context#callback')), + \ [a:path]), + \ 'in_io' : 'null' + \ })) + endfunction + +else " No jobs + + function! context#job_status() + call s:context_echo('Not implemented', 'WarningMsg') + endfunction! + + function! context#stop_jobs() + call s:context_echo('Not implemented', 'WarningMsg') + endfunction + + function! context#callback(path, job, status) + call s:callback(a:path, a:job, a:status) + endfunction + + function! s:typeset(path) + execute '!' . context#command() . ' ' . shellescape(fnamemodify(a:path, ":t")) + call call(get(b:, 'context_callback', get(g:, 'context_callback', 'context#callback')), + \ [a:path, 0, v:shell_error]) + endfunction + +endif " has('job') + +function! s:callback(path, job, status) abort + if a:status < 0 " Assume the job was terminated + return + endif + " Get info about the current window + let l:winid = s:win_getid() " Save window id + let l:efm = &l:errorformat " Save local errorformat + let l:cwd = fnamemodify(getcwd(), ":p") " Save local working directory + " Set errorformat to parse ConTeXt errors + execute 'setl efm=' . escape(b:context_errorformat, ' ') + try " Set cwd to expand error file correctly + execute 'lcd' fnameescape(fnamemodify(a:path, ':h')) + catch /.*/ + execute 'setl efm=' . escape(l:efm, ' ') + throw v:exception + endtry + try + execute 'cgetfile' fnameescape(fnamemodify(a:path, ':r') . '.log') + botright cwindow + finally " Restore cwd and errorformat + execute s:win_id2win(l:winid) . 'wincmd w' + execute 'lcd ' . fnameescape(l:cwd) + execute 'setl efm=' . escape(l:efm, ' ') + endtry + if a:status == 0 + call s:context_echo('Success!', 'ModeMsg') + else + call s:context_echo('There are errors. ', 'ErrorMsg') + endif +endfunction + +function! context#command() + return get(b:, 'context_mtxrun', get(g:, 'context_mtxrun', 'mtxrun')) + \ . ' --script context --autogenerate --nonstopmode' + \ . ' --synctex=' . (get(b:, 'context_synctex', get(g:, 'context_synctex', 0)) ? '1' : '0') + \ . ' ' . get(b:, 'context_extra_options', get(g:, 'context_extra_options', '')) +endfunction + +" Accepts an optional path (useful for big projects, when the file you are +" editing is not the project's root document). If no argument is given, uses +" the path of the current buffer. +function! context#typeset(...) abort + let l:path = fnamemodify(strlen(a:000[0]) > 0 ? a:1 : expand("%"), ":p") + let l:cwd = fnamemodify(getcwd(), ":p") " Save local working directory + call s:context_echo('Typesetting...', 'ModeMsg') + execute 'lcd' fnameescape(fnamemodify(l:path, ":h")) + try + call s:typeset(l:path) + finally " Restore local working directory + execute 'lcd ' . fnameescape(l:cwd) + endtry +endfunction! +"}}} + +let &cpo = s:keepcpo +unlet s:keepcpo + +" vim: sw=2 fdm=marker diff --git a/runtime/autoload/contextcomplete.vim b/runtime/autoload/contextcomplete.vim new file mode 100644 index 0000000000..5b93bb0986 --- /dev/null +++ b/runtime/autoload/contextcomplete.vim @@ -0,0 +1,25 @@ +" Language: ConTeXt typesetting engine +" Maintainer: Nicola Vitacolonna <nvitacolonna@gmail.com> +" Latest Revision: 2016 Oct 15 + +let s:keepcpo= &cpo +set cpo&vim + +" Complete keywords in MetaPost blocks +function! contextcomplete#Complete(findstart, base) + if a:findstart == 1 + if len(synstack(line('.'), 1)) > 0 && + \ synIDattr(synstack(line('.'), 1)[0], "name") ==# 'contextMPGraphic' + return syntaxcomplete#Complete(a:findstart, a:base) + else + return -3 + endif + else + return syntaxcomplete#Complete(a:findstart, a:base) + endif +endfunction + +let &cpo = s:keepcpo +unlet s:keepcpo + +" vim: sw=2 fdm=marker diff --git a/runtime/autoload/gzip.vim b/runtime/autoload/gzip.vim index a6b4605b06..e4adec0947 100644 --- a/runtime/autoload/gzip.vim +++ b/runtime/autoload/gzip.vim @@ -1,6 +1,6 @@ " Vim autoload file for editing compressed files. " Maintainer: Bram Moolenaar <Bram@vim.org> -" Last Change: 2014 Nov 05 +" Last Change: 2016 Sep 28 " These functions are used by the gzip plugin. @@ -63,6 +63,9 @@ fun gzip#read(cmd) " set 'modifiable' let ma_save = &ma setlocal ma + " set 'write' + let write_save = &write + set write " Reset 'foldenable', otherwise line numbers get adjusted. if has("folding") let fen_save = &fen @@ -127,6 +130,7 @@ fun gzip#read(cmd) let &pm = pm_save let &cpo = cpo_save let &l:ma = ma_save + let &write = write_save if has("folding") let &l:fen = fen_save endif diff --git a/runtime/autoload/health.vim b/runtime/autoload/health.vim index 93ca4dfc54..bd99a0e104 100644 --- a/runtime/autoload/health.vim +++ b/runtime/autoload/health.vim @@ -9,17 +9,9 @@ function! s:enhance_syntax() abort \ containedin=markdownCodeBlock,mkdListItemLine highlight link healthWarning WarningMsg - syntax keyword healthInfo INFO - \ containedin=markdownCodeBlock,mkdListItemLine - highlight link healthInfo ModeMsg - syntax keyword healthSuccess SUCCESS \ containedin=markdownCodeBlock,mkdListItemLine - highlight link healthSuccess ModeMsg - - syntax keyword healthSuggestion SUGGESTIONS - \ containedin=markdownCodeBlock,mkdListItemLine - highlight link healthSuggestion String + highlight healthSuccess guibg=#5fff00 guifg=#080808 ctermbg=82 ctermfg=232 syntax match healthHelp "|.\{-}|" contains=healthBar \ containedin=markdownCodeBlock,mkdListItemLine @@ -42,6 +34,7 @@ function! health#check(plugin_names) abort setlocal filetype=markdown setlocal conceallevel=2 concealcursor=nc setlocal keywordprg=:help + let &l:iskeyword='!-~,^*,^|,^",192-255' call s:enhance_syntax() if empty(healthchecks) @@ -74,6 +67,7 @@ function! health#check(plugin_names) abort " needed for plasticboy/vim-markdown, because it uses fdm=expr normal! zR setlocal nomodified + setlocal bufhidden=hide redraw|echo '' endfunction @@ -96,7 +90,7 @@ endfunction " Changes ':h clipboard' to ':help |clipboard|'. function! s:help_to_link(s) abort - return substitute(a:s, '\v[''"]?:h%[elp] ([^''"]+)[''"]?', '":help |\1|"', 'g') + return substitute(a:s, '\v:h%[elp] ([^|][^"\r\n ]+)', ':help |\1|', 'g') endfunction " Format a message for a specific report item diff --git a/runtime/autoload/health/nvim.vim b/runtime/autoload/health/nvim.vim index e2ad9f7ccb..3834cbd054 100644 --- a/runtime/autoload/health/nvim.vim +++ b/runtime/autoload/health/nvim.vim @@ -1,15 +1,18 @@ -let s:suggest_faq = 'See https://github.com/neovim/neovim/wiki/FAQ' +let s:suggest_faq = 'https://github.com/neovim/neovim/wiki/FAQ' function! s:check_config() abort + let ok = v:true call health#report_start('Configuration') - if !get(g:, 'loaded_sensible', 0) + + if exists('$NVIM_TUI_ENABLE_CURSOR_SHAPE') + let ok = v:false + call health#report_warn("$NVIM_TUI_ENABLE_CURSOR_SHAPE is ignored in Nvim 0.2+", + \ [ "Use the 'guicursor' option to configure cursor shape. :help 'guicursor'", + \ 'https://github.com/neovim/neovim/wiki/Following-HEAD#20170402' ]) + endif + + if ok call health#report_ok('no issues found') - else - let sensible_pi = globpath(&runtimepath, '**/sensible.vim', 1, 1) - call health#report_info("found sensible.vim plugin:\n".join(sensible_pi, "\n")) - call health#report_error("sensible.vim plugin is not needed; Nvim has the same defaults built-in." - \ ." Also, sensible.vim sets 'ttimeoutlen' to a sub-optimal value.", - \ ["Remove sensible.vim plugin, or wrap it in a `if !has('nvim')` check."]) endif endfunction @@ -113,11 +116,27 @@ function! s:check_tmux() abort call health#report_ok('escape-time: '.tmux_esc_time.'ms') endif - " check $TERM + " check default-terminal and $TERM call health#report_info('$TERM: '.$TERM) - if $TERM !~# '\v(tmux-256color|screen-256color)' + let cmd = 'tmux show-option -qvg default-terminal' + let out = system(cmd) + let tmux_default_term = substitute(out, '\v(\s|\r|\n)', '', 'g') + if empty(tmux_default_term) + let cmd = 'tmux show-option -qvgs default-terminal' + let out = system(cmd) + let tmux_default_term = substitute(out, '\v(\s|\r|\n)', '', 'g') + endif + + if v:shell_error + call health#report_error('command failed: '.cmd."\n".out) + elseif tmux_default_term !=# $TERM + call health#report_info('default-terminal: '.tmux_default_term) + call health#report_error( + \ '$TERM differs from the tmux `default-terminal` setting. Colors might look wrong.', + \ ['$TERM may have been set by some rc (.bashrc, .zshrc, ...).']) + elseif $TERM !~# '\v(tmux-256color|screen-256color)' call health#report_error( - \ '$TERM should be "screen-256color" or "tmux-256color" when running tmux.', + \ '$TERM should be "screen-256color" or "tmux-256color" in tmux. Colors might look wrong.', \ ["Set default-terminal in ~/.tmux.conf:\nset-option -g default-terminal \"screen-256color\"", \ s:suggest_faq]) endif diff --git a/runtime/autoload/health/provider.vim b/runtime/autoload/health/provider.vim index 417426c101..26db5b77b7 100644 --- a/runtime/autoload/health/provider.vim +++ b/runtime/autoload/health/provider.vim @@ -8,6 +8,11 @@ function! s:trim(s) abort return substitute(a:s, '^\_s*\|\_s*$', '', 'g') endfunction +" Convert '\' to '/'. Collapse '//' and '/./'. +function! s:normalize_path(s) abort + return substitute(substitute(a:s, '\', '/', 'g'), '/\./\|/\+', '/', 'g') +endfunction + " Simple version comparison. function! s:version_cmp(a, b) abort let a = split(a:a, '\.', 0) @@ -26,13 +31,23 @@ endfunction " Handler for s:system() function. function! s:system_handler(jobid, data, event) dict abort - if a:event == 'stdout' || a:event == 'stderr' + if a:event ==# 'stdout' || a:event ==# 'stderr' let self.output .= join(a:data, '') - elseif a:event == 'exit' + elseif a:event ==# 'exit' let s:shell_error = a:data endif endfunction +" Attempts to construct a shell command from an args list. +" Only for display, to help users debug a failed command. +function! s:shellify(cmd) abort + if type(a:cmd) != type([]) + return a:cmd + endif + return join(map(copy(a:cmd), + \'v:val =~# ''\m[\-.a-zA-Z_/]'' ? shellescape(v:val) : v:val'), ' ') +endfunction + " Run a system command and timeout after 30 seconds. function! s:system(cmd, ...) abort let stdin = a:0 ? a:1 : '' @@ -49,8 +64,7 @@ function! s:system(cmd, ...) abort let jobid = jobstart(a:cmd, opts) if jobid < 1 - call health#report_error(printf('Command error %d: %s', jobid, - \ type(a:cmd) == type([]) ? join(a:cmd) : a:cmd))) + call health#report_error(printf('Command error (job=%d): %s', jobid, s:shellify(a:cmd))) let s:shell_error = 1 return opts.output endif @@ -61,13 +75,11 @@ function! s:system(cmd, ...) abort let res = jobwait([jobid], 30000) if res[0] == -1 - call health#report_error(printf('Command timed out: %s', - \ type(a:cmd) == type([]) ? join(a:cmd) : a:cmd)) + call health#report_error(printf('Command timed out: %s', s:shellify(a:cmd))) call jobstop(jobid) elseif s:shell_error != 0 && !ignore_error - call health#report_error(printf("Command error (%d) %s: %s", jobid, - \ type(a:cmd) == type([]) ? join(a:cmd) : a:cmd, - \ opts.output)) + call health#report_error(printf("Command error (job=%d): %s\nOutput: %s", jobid, + \ s:shellify(a:cmd), opts.output)) endif return opts.output @@ -106,13 +118,17 @@ endfunction " Check for clipboard tools. function! s:check_clipboard() abort - call health#report_start('Clipboard') + call health#report_start('Clipboard (optional)') let clipboard_tool = provider#clipboard#Executable() - if empty(clipboard_tool) + if exists('g:clipboard') && empty(clipboard_tool) + call health#report_error( + \ provider#clipboard#Error(), + \ ["Use the example in :help g:clipboard as a template, or don't set g:clipboard at all."]) + elseif empty(clipboard_tool) call health#report_warn( - \ "No clipboard tool found. Clipboard registers will not work.", - \ ['See ":help clipboard".']) + \ 'No clipboard tool found. Clipboard registers (`"+` and `"*`) will not work.', + \ [':help clipboard']) else call health#report_ok('Clipboard tool found: '. clipboard_tool) endif @@ -152,7 +168,7 @@ function! s:version_info(python) abort \ ])) if empty(python_version) - let python_version = 'unable to parse python response' + let python_version = 'unable to parse '.a:python.' response' endif let nvim_path = s:trim(s:system([ @@ -164,14 +180,14 @@ function! s:version_info(python) abort " Assuming that multiple versions of a package are installed, sort them " numerically in descending order. - function! s:compare(metapath1, metapath2) + function! s:compare(metapath1, metapath2) abort let a = matchstr(fnamemodify(a:metapath1, ':p:h:t'), '[0-9.]\+') let b = matchstr(fnamemodify(a:metapath2, ':p:h:t'), '[0-9.]\+') return a == b ? 0 : a > b ? 1 : -1 endfunction " Try to get neovim.VERSION (added in 0.1.11dev). - let nvim_version = s:system(['python', '-c', + let nvim_version = s:system([a:python, '-c', \ 'from neovim import VERSION as v; '. \ 'print("{}.{}.{}{}".format(v.major, v.minor, v.patch, v.prerelease))'], \ '', 1, 1) @@ -208,7 +224,7 @@ endfunction " Check the Python interpreter's usability. function! s:check_bin(bin) abort - if !filereadable(a:bin) + if !filereadable(a:bin) && (!has('win32') || !filereadable(a:bin.'.exe')) call health#report_error(printf('"%s" was not found.', a:bin)) return 0 elseif executable(a:bin) != 1 @@ -219,22 +235,28 @@ function! s:check_bin(bin) abort endfunction function! s:check_python(version) abort - call health#report_start('Python ' . a:version . ' provider') + call health#report_start('Python ' . a:version . ' provider (optional)') - let python_bin_name = 'python'.(a:version == 2 ? '' : '3') + let pyname = 'python'.(a:version == 2 ? '' : '3') let pyenv = resolve(exepath('pyenv')) let pyenv_root = exists('$PYENV_ROOT') ? resolve($PYENV_ROOT) : 'n' let venv = exists('$VIRTUAL_ENV') ? resolve($VIRTUAL_ENV) : '' - let host_prog_var = python_bin_name.'_host_prog' + let host_prog_var = pyname.'_host_prog' + let loaded_var = 'g:loaded_'.pyname.'_provider' let python_bin = '' let python_multiple = [] + if exists(loaded_var) && !exists('*provider#'.pyname.'#Call') + call health#report_info('Disabled. '.loaded_var.'='.eval(loaded_var)) + return + endif + if exists('g:'.host_prog_var) call health#report_info(printf('Using: g:%s = "%s"', host_prog_var, get(g:, host_prog_var))) endif - let [python_bin_name, pythonx_errs] = provider#pythonx#Detect(a:version) - if empty(python_bin_name) + let [pyname, pythonx_errs] = provider#pythonx#Detect(a:version) + if empty(pyname) call health#report_warn('No Python interpreter was found with the neovim ' \ . 'module. Using the first available for diagnostics.') if !empty(pythonx_errs) @@ -242,21 +264,21 @@ function! s:check_python(version) abort endif endif - if !empty(python_bin_name) + if !empty(pyname) if exists('g:'.host_prog_var) - let python_bin = exepath(python_bin_name) + let python_bin = exepath(pyname) endif - let python_bin_name = fnamemodify(python_bin_name, ':t') + let pyname = fnamemodify(pyname, ':t') endif if !empty(pythonx_errs) call health#report_error('Python provider error', pythonx_errs) endif - if !empty(python_bin_name) && empty(python_bin) && empty(pythonx_errs) + if !empty(pyname) && empty(python_bin) && empty(pythonx_errs) if !exists('g:'.host_prog_var) call health#report_info(printf('`g:%s` is not set. Searching for ' - \ . '%s in the environment.', host_prog_var, python_bin_name)) + \ . '%s in the environment.', host_prog_var, pyname)) endif if !empty(pyenv) @@ -269,20 +291,21 @@ function! s:check_python(version) abort call health#report_ok(printf('pyenv found: "%s"', pyenv)) endif - let python_bin = s:trim(s:system([pyenv, 'which', python_bin_name], '', 1)) + let python_bin = s:trim(s:system([pyenv, 'which', pyname], '', 1)) if empty(python_bin) - call health#report_warn(printf('pyenv could not find %s.', python_bin_name)) + call health#report_warn(printf('pyenv could not find %s.', pyname)) endif endif if empty(python_bin) - let python_bin = exepath(python_bin_name) + let python_bin = exepath(pyname) if exists('$PATH') - for path in split($PATH, ':') - let path_bin = path.'/'.python_bin_name - if path_bin != python_bin && index(python_multiple, path_bin) == -1 + for path in split($PATH, has('win32') ? ';' : ':') + let path_bin = s:normalize_path(path.'/'.pyname) + if path_bin != s:normalize_path(python_bin) + \ && index(python_multiple, path_bin) == -1 \ && executable(path_bin) call add(python_multiple, path_bin) endif @@ -292,7 +315,7 @@ function! s:check_python(version) abort " This is worth noting since the user may install something " that changes $PATH, like homebrew. call health#report_info(printf('Multiple %s executables found. ' - \ . 'Set `g:%s` to avoid surprises.', python_bin_name, host_prog_var)) + \ . 'Set `g:%s` to avoid surprises.', pyname, host_prog_var)) endif if python_bin =~# '\<shims\>' @@ -333,9 +356,9 @@ function! s:check_python(version) abort endif endif - if empty(python_bin) && !empty(python_bin_name) + if empty(python_bin) && !empty(pyname) " An error message should have already printed. - call health#report_error(printf('`%s` was not found.', python_bin_name)) + call health#report_error(printf('`%s` was not found.', pyname)) elseif !empty(python_bin) && !s:check_bin(python_bin) let python_bin = '' endif @@ -349,7 +372,7 @@ function! s:check_python(version) abort if $VIRTUAL_ENV != pyenv_prefix let virtualenv_inactive = 1 endif - elseif !empty(python_bin_name) && exepath(python_bin_name) !~# '^'.$VIRTUAL_ENV.'/' + elseif !empty(pyname) && exepath(pyname) !~# '^'.$VIRTUAL_ENV.'/' let virtualenv_inactive = 1 endif endif @@ -381,9 +404,9 @@ function! s:check_python(version) abort call health#report_info('Python'.a:version.' version: ' . pyversion) if s:is_bad_response(status) - call health#report_info(printf('%s-neovim version: %s (%s)', python_bin_name, current, status)) + call health#report_info(printf('%s-neovim version: %s (%s)', pyname, current, status)) else - call health#report_info(printf('%s-neovim version: %s', python_bin_name, current)) + call health#report_info(printf('%s-neovim version: %s', pyname, current)) endif if s:is_bad_response(current) @@ -397,22 +420,28 @@ function! s:check_python(version) abort call health#report_error('HTTP request failed: '.latest) elseif s:is_bad_response(status) call health#report_warn(printf('Latest %s-neovim is NOT installed: %s', - \ python_bin_name, latest)) + \ pyname, latest)) elseif !s:is_bad_response(current) call health#report_ok(printf('Latest %s-neovim is installed: %s', - \ python_bin_name, latest)) + \ pyname, latest)) endif endif endfunction function! s:check_ruby() abort - call health#report_start('Ruby provider') + call health#report_start('Ruby provider (optional)') + + let loaded_var = 'g:loaded_ruby_provider' + if exists(loaded_var) && !exists('*provider#ruby#Call') + call health#report_info('Disabled. '.loaded_var.'='.eval(loaded_var)) + return + endif if !executable('ruby') || !executable('gem') call health#report_warn( - \ "`ruby` and `gem` must be in $PATH.", - \ ["Install Ruby and verify that `ruby` and `gem` commands work."]) + \ '`ruby` and `gem` must be in $PATH.', + \ ['Install Ruby and verify that `ruby` and `gem` commands work.']) return endif call health#report_info('Ruby: '. s:system('ruby -v')) @@ -420,26 +449,28 @@ function! s:check_ruby() abort let host = provider#ruby#Detect() if empty(host) call health#report_warn('Missing "neovim" gem.', - \ ['Run in shell: gem install neovim']) + \ ['Run in shell: gem install neovim', + \ 'Is the gem bin directory in $PATH? Check `gem environment`.', + \ 'If you are using rvm/rbenv/chruby, try "rehashing".']) return endif call health#report_info('Host: '. host) - let latest_gem_cmd = 'gem list -ra ^neovim$' + let latest_gem_cmd = has('win32') ? 'cmd /c gem list -ra ^^neovim$' : 'gem list -ra ^neovim$' let latest_gem = s:system(split(latest_gem_cmd)) if s:shell_error || empty(latest_gem) call health#report_error('Failed to run: '. latest_gem_cmd, \ ["Make sure you're connected to the internet.", - \ "Are you behind a firewall or proxy?"]) + \ 'Are you behind a firewall or proxy?']) return endif - let latest_gem = get(split(latest_gem, ' (\|, \|)$' ), 1, 'not found') + let latest_gem = get(split(latest_gem, 'neovim (\|, \|)$' ), 1, 'not found') let current_gem_cmd = host .' --version' let current_gem = s:system(current_gem_cmd) if s:shell_error call health#report_error('Failed to run: '. current_gem_cmd, - \ ["Report this issue with the output of: ", current_gem_cmd]) + \ ['Report this issue with the output of: ', current_gem_cmd]) return endif @@ -449,7 +480,7 @@ function! s:check_ruby() abort \ current_gem, latest_gem), \ ['Run in shell: gem update neovim']) else - call health#report_ok('Gem "neovim" is up-to-date: '. current_gem) + call health#report_ok('Latest "neovim" gem is installed: '. current_gem) endif endfunction diff --git a/runtime/autoload/man.vim b/runtime/autoload/man.vim index 251e6eee41..dd71ede680 100644 --- a/runtime/autoload/man.vim +++ b/runtime/autoload/man.vim @@ -1,16 +1,31 @@ " Maintainer: Anmol Sethi <anmol@aubble.com> -let s:man_find_arg = "-w" +let s:find_arg = '-w' +let s:localfile_arg = v:true " Always use -l if possible. #6683 +let s:section_arg = '-s' -" TODO(nhooyr) Completion may work on SunOS; I'm not sure if `man -l` displays -" the list of searched directories. -try - if !has('win32') && $OSTYPE !~? 'cygwin\|linux' && system('uname -s') =~? 'SunOS' && system('uname -r') =~# '^5' - let s:man_find_arg = '-l' +function! s:init_section_flag() + call system(['env', 'MANPAGER=cat', 'man', s:section_arg, '1', 'man']) + if v:shell_error + let s:section_arg = '-S' endif -catch /E145:/ - " Ignore the error in restricted mode -endtry +endfunction + +function! s:init() abort + call s:init_section_flag() + " TODO(nhooyr): Does `man -l` on SunOS list searched directories? + try + if !has('win32') && $OSTYPE !~? 'cygwin\|linux' && system('uname -s') =~? 'SunOS' && system('uname -r') =~# '^5' + let s:find_arg = '-l' + endif + " Check for -l support. + call s:get_page(s:get_path('', 'man')[0:-2]) + catch /E145:/ + " Ignore the error in restricted mode + catch /command error .*/ + let s:localfile_arg = v:false + endtry +endfunction function! man#open_page(count, count1, mods, ...) abort if a:0 > 2 @@ -39,7 +54,6 @@ function! man#open_page(count, count1, mods, ...) abort let sect = string(a:count) endif let [sect, name, path] = s:verify_exists(sect, name) - let page = s:get_page(path) catch call s:error(v:exception) return @@ -47,11 +61,29 @@ function! man#open_page(count, count1, mods, ...) abort call s:push_tag() let bufname = 'man://'.name.(empty(sect)?'':'('.sect.')') - if a:mods !~# 'tab' && s:find_man() - noautocmd execute 'silent edit' fnameescape(bufname) - else - noautocmd execute 'silent' a:mods 'split' fnameescape(bufname) - endif + + try + set eventignore+=BufReadCmd + if a:mods !~# 'tab' && s:find_man() + execute 'silent edit' fnameescape(bufname) + else + execute 'silent' a:mods 'split' fnameescape(bufname) + endif + finally + set eventignore-=BufReadCmd + endtry + + try + let page = s:get_page(path) + catch + if a:mods =~# 'tab' || !s:find_man() + " a new window was opened + close + endif + call s:error(v:exception) + return + endtry + let b:man_sect = sect call s:put_page(page) endfunction @@ -59,21 +91,20 @@ endfunction function! man#read_page(ref) abort try let [sect, name] = man#extract_sect_and_name_ref(a:ref) - let [b:man_sect, name, path] = s:verify_exists(sect, name) + let [sect, name, path] = s:verify_exists(sect, name) let page = s:get_page(path) catch - " call to s:error() is unnecessary + call s:error(v:exception) return endtry + let b:man_sect = sect call s:put_page(page) endfunction " Handler for s:system() function. function! s:system_handler(jobid, data, event) dict abort - if a:event == 'stdout' - let self.stdout .= join(a:data, "\n") - elseif a:event == 'stderr' - let self.stderr .= join(a:data, "\n") + if a:event is# 'stdout' || a:event is# 'stderr' + let self[a:event] .= join(a:data, "\n") else let self.exit_code = a:data endif @@ -100,7 +131,7 @@ function! s:system(cmd, ...) abort try call jobstop(jobid) throw printf('command timed out: %s', join(a:cmd)) - catch /^Vim\%((\a\+)\)\=:E900/ + catch /^Vim(call):E900:/ endtry elseif res[0] == -2 throw printf('command interrupted: %s', join(a:cmd)) @@ -117,7 +148,8 @@ function! s:get_page(path) abort let manwidth = empty($MANWIDTH) ? winwidth(0) : $MANWIDTH " Force MANPAGER=cat to ensure Vim is not recursively invoked (by man-db). " http://comments.gmane.org/gmane.editors.vim.devel/29085 - return s:system(['env', 'MANPAGER=cat', 'MANWIDTH='.manwidth, 'man', a:path]) + let cmd = ['env', 'MANPAGER=cat', 'MANWIDTH='.manwidth, 'man'] + return s:system(cmd + (s:localfile_arg ? ['-l', a:path] : [a:path])) endfunction function! s:put_page(page) abort @@ -125,14 +157,39 @@ function! s:put_page(page) abort setlocal noreadonly silent keepjumps %delete _ silent put =a:page - " Remove all backspaced characters. - execute 'silent keeppatterns keepjumps %substitute,.\b,,e'.(&gdefault?'':'g') + " Remove all backspaced/escape characters. + execute 'silent keeppatterns keepjumps %substitute,.\b\|\e\[\d\+m,,e'.(&gdefault?'':'g') while getline(1) =~# '^\s*$' silent keepjumps 1delete _ endwhile setlocal filetype=man endfunction +function! man#show_toc() abort + let bufname = bufname('%') + let info = getloclist(0, {'winid': 1}) + if !empty(info) && getwinvar(info.winid, 'qf_toc') ==# bufname + lopen + return + endif + + let toc = [] + let lnum = 2 + let last_line = line('$') - 1 + while lnum && lnum < last_line + let text = getline(lnum) + if text =~# '^\%( \{3\}\)\=\S.*$' + call add(toc, {'bufnr': bufnr('%'), 'lnum': lnum, 'text': text}) + endif + let lnum = nextnonblank(lnum + 1) + endwhile + + call setloclist(0, toc, ' ') + call setloclist(0, [], 'a', {'title': 'Man TOC'}) + lopen + let w:qf_toc = bufname +endfunction + " attempt to extract the name and sect out of 'name(sect)' " otherwise just return the largest string of valid characters in ref function! man#extract_sect_and_name_ref(ref) abort @@ -156,24 +213,26 @@ endfunction function! s:get_path(sect, name) abort if empty(a:sect) - return s:system(['man', s:man_find_arg, a:name]) + return s:system(['man', s:find_arg, a:name]) endif " '-s' flag handles: " - tokens like 'printf(echo)' " - sections starting with '-' " - 3pcap section (found on macOS) " - commas between sections (for section priority) - return s:system(['man', s:man_find_arg, '-s', a:sect, a:name]) + return s:system(['man', s:find_arg, s:section_arg, a:sect, a:name]) endfunction function! s:verify_exists(sect, name) abort - let path = s:get_path(a:sect, a:name) - if path !~# '^\/' - let path = s:get_path(get(b:, 'man_default_sects', ''), a:name) - if path !~# '^\/' + try + let path = s:get_path(a:sect, a:name) + catch /^command error (/ + try + let path = s:get_path(get(b:, 'man_default_sects', ''), a:name) + catch /^command error (/ let path = s:get_path('', a:name) - endif - endif + endtry + endtry " We need to extract the section from the path because sometimes " the actual section of the manpage is more specific than the section " we provided to `man`. Try ':Man 3 App::CLI'. @@ -286,7 +345,7 @@ endfunction function! s:complete(sect, psect, name) abort try - let mandirs = join(split(s:system(['man', s:man_find_arg]), ':\|\n'), ',') + let mandirs = join(split(s:system(['man', s:find_arg]), ':\|\n'), ',') catch call s:error(v:exception) return @@ -311,8 +370,8 @@ function! s:format_candidate(path, psect) abort endfunction function! man#init_pager() abort - " Remove all backspaced characters. - execute 'silent keeppatterns keepjumps %substitute,.\b,,e'.(&gdefault?'':'g') + " Remove all backspaced/escape characters. + execute 'silent keeppatterns keepjumps %substitute,.\b\|\e\[\d\+m,,e'.(&gdefault?'':'g') if getline(1) =~# '^\s*$' silent keepjumps 1delete _ else @@ -328,3 +387,5 @@ function! man#init_pager() abort endtry execute 'silent file man://'.fnameescape(ref) endfunction + +call s:init() diff --git a/runtime/autoload/netrw.vim b/runtime/autoload/netrw.vim index de85844d5d..76485c2f38 100644 --- a/runtime/autoload/netrw.vim +++ b/runtime/autoload/netrw.vim @@ -22,8 +22,8 @@ if &cp || exists("g:loaded_netrw") finish endif -" netrw requires vim having patch 213; netrw will benefit from vim's having patch#656, too -if v:version < 704 || !has("patch213") +" netrw requires vim having patch 7.4.213; netrw will benefit from vim's having patch#656, too +if v:version < 704 || (v:version == 704 && !has("patch213")) if !exists("s:needpatch213") unsilent echomsg "***sorry*** this version of netrw requires vim v7.4 with patch 213" endif diff --git a/runtime/autoload/phpcomplete.vim b/runtime/autoload/phpcomplete.vim index 7f25d9df33..8e38867a77 100644 --- a/runtime/autoload/phpcomplete.vim +++ b/runtime/autoload/phpcomplete.vim @@ -3,7 +3,7 @@ " Maintainer: Dรกvid Szabรณ ( complex857 AT gmail DOT com ) " Previous Maintainer: Mikolaj Machowski ( mikmach AT wp DOT pl ) " URL: https://github.com/shawncplus/phpcomplete.vim -" Last Change: 2015 Jul 13 +" Last Change: 2016 Oct 10 " " OPTIONS: " @@ -195,6 +195,8 @@ function! phpcomplete#CompletePHP(findstart, base) " {{{ " }}} elseif context =~? 'implements' return phpcomplete#CompleteClassName(a:base, ['i'], current_namespace, imports) + elseif context =~? 'instanceof' + return phpcomplete#CompleteClassName(a:base, ['c', 'n'], current_namespace, imports) elseif context =~? 'extends\s\+.\+$' && a:base == '' return ['implements'] elseif context =~? 'extends' @@ -787,6 +789,8 @@ function! phpcomplete#CompleteClassName(base, kinds, current_namespace, imports) if kinds == ['c', 'i'] let filterstr = 'v:val =~? "\\(class\\|interface\\)\\s\\+[a-zA-Z_\\x7f-\\xff][a-zA-Z_0-9\\x7f-\\xff]*\\s*"' + elseif kinds == ['c', 'n'] + let filterstr = 'v:val =~? "\\(class\\|namespace\\)\\s\\+[a-zA-Z_\\x7f-\\xff][a-zA-Z_0-9\\x7f-\\xff]*\\s*"' elseif kinds == ['c'] let filterstr = 'v:val =~? "class\\s\\+[a-zA-Z_\\x7f-\\xff][a-zA-Z_0-9\\x7f-\\xff]*\\s*"' elseif kinds == ['i'] @@ -931,7 +935,7 @@ function! phpcomplete#EvaluateModifiers(modifiers, required_modifiers, prohibite endfor for modifier in a:modifiers - " if the modifier is prohibited its a no match + " if the modifier is prohibited it's a no match if index(a:prohibited_modifiers, modifier) != -1 return 0 endif @@ -996,7 +1000,7 @@ function! phpcomplete#CompleteUserClass(context, base, sccontent, visibility) " let required_modifiers += ['static'] endif let all_variable = filter(deepcopy(a:sccontent), - \ 'v:val =~ "^\\s*\\(var\\s\\+\\|public\\s\\+\\|protected\\s\\+\\|private\\s\\+\\|final\\s\\+\\|abstract\\s\\+\\|static\\s\\+\\)\\+\\$"') + \ 'v:val =~ "\\(^\\s*\\(var\\s\\+\\|public\\s\\+\\|protected\\s\\+\\|private\\s\\+\\|final\\s\\+\\|abstract\\s\\+\\|static\\s\\+\\)\\+\\$\\|^\\s*\\(\\/\\|\\*\\)*\\s*@property\\s\\+\\S\\+\\s\\S\\{-}\\s*$\\)"') let variables = [] for i in all_variable @@ -1160,6 +1164,14 @@ function! phpcomplete#GetTaglist(pattern) " {{{ endif let tags = taglist(a:pattern) + for tag in tags + for prop in keys(tag) + if prop == 'cmd' || prop == 'static' || prop == 'kind' || prop == 'builtin' + continue + endif + let tag[prop] = substitute(tag[prop], '\\\\', '\\', 'g') + endfor + endfor let s:cache_tags[a:pattern] = tags let has_key = has_key(s:cache_tags, a:pattern) let s:cache_tags_checksum = cache_checksum @@ -1379,7 +1391,7 @@ function! phpcomplete#GetCallChainReturnType(classname_candidate, class_candidat " Get Structured information of all classes and subclasses including namespace and includes " try to find the method's return type in docblock comment for classstructure in classcontents - let docblock_target_pattern = 'function\s\+&\?'.method.'\|\(public\|private\|protected\|var\).\+\$'.method + let docblock_target_pattern = 'function\s\+&\?'.method.'\>\|\(public\|private\|protected\|var\).\+\$'.method.'\>\|@property.\+\$'.method.'\>' let doc_str = phpcomplete#GetDocBlock(split(classstructure.content, '\n'), docblock_target_pattern) if doc_str != '' break @@ -1387,8 +1399,17 @@ function! phpcomplete#GetCallChainReturnType(classname_candidate, class_candidat endfor if doc_str != '' let docblock = phpcomplete#ParseDocBlock(doc_str) - if has_key(docblock.return, 'type') || has_key(docblock.var, 'type') - let type = has_key(docblock.return, 'type') ? docblock.return.type : docblock.var.type + if has_key(docblock.return, 'type') || has_key(docblock.var, 'type') || len(docblock.properties) > 0 + let type = has_key(docblock.return, 'type') ? docblock.return.type : has_key(docblock.var, 'type') ? docblock.var.type : '' + + if type == '' + for property in docblock.properties + if property.description =~? method + let type = property.type + break + endif + endfor + endif " there's a namespace in the type, threat the type as FQCN if type =~ '\\' @@ -1554,6 +1575,9 @@ function! phpcomplete#GetClassName(start_line, context, current_namespace, impor elseif get(methodstack, 0) =~# function_invocation_pattern let function_name = matchstr(methodstack[0], '^\s*\zs'.function_name_pattern) let function_file = phpcomplete#GetFunctionLocation(function_name, a:current_namespace) + if function_file == '' + let function_file = phpcomplete#GetFunctionLocation(function_name, '\') + endif if function_file == 'VIMPHP_BUILTINFUNCTION' " built in function, grab the return type from the info string @@ -1569,7 +1593,7 @@ function! phpcomplete#GetClassName(start_line, context, current_namespace, impor let [class_candidate_namespace, function_imports] = phpcomplete#GetCurrentNameSpace(file_lines) " try to expand the classname of the returned type with the context got from the function's source file - let [classname_candidate, unused] = phpcomplete#ExpandClassName(classname_candidate, class_candidate_namespace, function_imports) + let [classname_candidate, class_candidate_namespace] = phpcomplete#ExpandClassName(classname_candidate, class_candidate_namespace, function_imports) endif endif if classname_candidate != '' @@ -1650,9 +1674,10 @@ function! phpcomplete#GetClassName(start_line, context, current_namespace, impor let sub_methodstack = phpcomplete#GetMethodStack(matchstr(line, '^\s*'.object.'\s*=&\?\s*\s\+\zs.*')) let [classname_candidate, class_candidate_namespace] = phpcomplete#GetCallChainReturnType( \ classname, - \ a:current_namespace, + \ namespace_for_class, \ a:imports, \ sub_methodstack) + return (class_candidate_namespace == '\' || class_candidate_namespace == '') ? classname_candidate : class_candidate_namespace.'\'.classname_candidate endif endif @@ -1783,6 +1808,9 @@ function! phpcomplete#GetClassName(start_line, context, current_namespace, impor let [function_name, function_namespace] = phpcomplete#ExpandClassName(function_name, a:current_namespace, a:imports) let function_file = phpcomplete#GetFunctionLocation(function_name, function_namespace) + if function_file == '' + let function_file = phpcomplete#GetFunctionLocation(function_name, '\') + endif if function_file == 'VIMPHP_BUILTINFUNCTION' " built in function, grab the return type from the info string @@ -1798,7 +1826,7 @@ function! phpcomplete#GetClassName(start_line, context, current_namespace, impor let classname_candidate = docblock.return.type let [class_candidate_namespace, function_imports] = phpcomplete#GetCurrentNameSpace(file_lines) " try to expand the classname of the returned type with the context got from the function's source file - let [classname_candidate, unused] = phpcomplete#ExpandClassName(classname_candidate, class_candidate_namespace, function_imports) + let [classname_candidate, class_candidate_namespace] = phpcomplete#ExpandClassName(classname_candidate, class_candidate_namespace, function_imports) break endif endif @@ -1861,6 +1889,8 @@ function! phpcomplete#GetClassName(start_line, context, current_namespace, impor for tag in tags if tag.kind ==? 'v' && tag.cmd =~? '=\s*new\s\+\zs'.class_name_pattern.'\ze' let classname = matchstr(tag.cmd, '=\s*new\s\+\zs'.class_name_pattern.'\ze') + " unescape the classname, it would have "\" doubled since it is an ex command + let classname = substitute(classname, '\\\(\_.\)', '\1', 'g') return classname endif endfor @@ -2077,6 +2107,19 @@ function! phpcomplete#GetClassContentsStructure(file_path, file_lines, class_nam endif call searchpair('{', '', '}', 'W') let class_closing_bracket_line = line('.') + + " Include class docblock + let doc_line = cfline - 1 + if getline(doc_line) =~? '^\s*\*/' + while doc_line != 0 + if getline(doc_line) =~? '^\s*/\*\*' + let cfline = doc_line + break + endif + let doc_line -= 1 + endwhile + endif + let classcontent = join(getline(cfline, class_closing_bracket_line), "\n") let used_traits = [] @@ -2241,8 +2284,19 @@ function! phpcomplete#GetDocBlock(sccontent, search) " {{{ let line = a:sccontent[i] " search for a function declaration if line =~? a:search - let l = i - 1 - " start backward serch for the comment block + if line =~? '@property' + let doc_line = i + while doc_line != sccontent_len - 1 + if a:sccontent[doc_line] =~? '^\s*\*/' + let l = doc_line + break + endif + let doc_line += 1 + endwhile + else + let l = i - 1 + endif + " start backward search for the comment block while l != 0 let line = a:sccontent[l] " if it's a one line docblock like comment and we can just return it right away @@ -2263,7 +2317,7 @@ function! phpcomplete#GetDocBlock(sccontent, search) " {{{ return '' end - while l != 0 + while l >= 0 let line = a:sccontent[l] if line =~? '^\s*/\*\*' let comment_start = l @@ -2297,9 +2351,10 @@ function! phpcomplete#ParseDocBlock(docblock) " {{{ \ 'return': {}, \ 'throws': [], \ 'var': {}, + \ 'properties': [], \ } - let res.description = substitute(matchstr(a:docblock, '\zs\_.\{-}\ze\(@var\|@param\|@return\|$\)'), '\(^\_s*\|\_s*$\)', '', 'g') + let res.description = substitute(matchstr(a:docblock, '\zs\_.\{-}\ze\(@type\|@var\|@param\|@return\|$\)'), '\(^\_s*\|\_s*$\)', '', 'g') let docblock_lines = split(a:docblock, "\n") let param_lines = filter(copy(docblock_lines), 'v:val =~? "^@param"') @@ -2334,15 +2389,26 @@ function! phpcomplete#ParseDocBlock(docblock) " {{{ endif endfor - let var_line = filter(copy(docblock_lines), 'v:val =~? "^@var"') + let var_line = filter(copy(docblock_lines), 'v:val =~? "^\\(@var\\|@type\\)"') if len(var_line) > 0 - let var_parts = matchlist(var_line[0], '@var\s\+\(\S\+\)\s*\(.*\)') + let var_parts = matchlist(var_line[0], '\(@var\|@type\)\s\+\(\S\+\)\s*\(.*\)') let res['var'] = { \ 'line': var_parts[0], - \ 'type': phpcomplete#GetTypeFromDocBlockParam(get(var_parts, 1, '')), - \ 'description': get(var_parts, 2, '')} + \ 'type': phpcomplete#GetTypeFromDocBlockParam(get(var_parts, 2, '')), + \ 'description': get(var_parts, 3, '')} endif + let property_lines = filter(copy(docblock_lines), 'v:val =~? "^@property"') + for property_line in property_lines + let parts = matchlist(property_line, '\(@property\)\s\+\(\S\+\)\s*\(.*\)') + if len(parts) > 0 + call add(res.properties, { + \ 'line': parts[0], + \ 'type': phpcomplete#GetTypeFromDocBlockParam(get(parts, 2, '')), + \ 'description': get(parts, 3, '')}) + endif + endfor + return res endfunction " }}} @@ -2498,6 +2564,7 @@ function! phpcomplete#GetCurrentNameSpace(file_lines) " {{{ let name = matchstr(name, '\\\zs[^\\]\+\ze$') endif endif + " leading slash is not required use imports are always absolute let imports[name] = {'name': object, 'kind': ''} endfor @@ -2533,6 +2600,7 @@ function! phpcomplete#GetCurrentNameSpace(file_lines) " {{{ elseif !exists('no_namespace_candidate') " save the first namespacless match to be used if no better " candidate found later on + let tag.namespace = namespace_for_classes let no_namespace_candidate = tag endif endif diff --git a/runtime/autoload/provider.vim b/runtime/autoload/provider.vim new file mode 100644 index 0000000000..e6514f5ba8 --- /dev/null +++ b/runtime/autoload/provider.vim @@ -0,0 +1,20 @@ +" Common functionality for providers + +let s:stderr = {} + +function! provider#stderr_collector(chan_id, data, event) + let stderr = get(s:stderr, a:chan_id, ['']) + let stderr[-1] .= a:data[0] + call extend(stderr, a:data[1:]) + let s:stderr[a:chan_id] = stderr +endfunction + +function! provider#clear_stderr(chan_id) + if has_key(s:stderr, a:chan_id) + call remove(s:stderr, a:chan_id) + endif +endfunction + +function! provider#get_stderr(chan_id) + return get(s:stderr, a:chan_id, []) +endfunction diff --git a/runtime/autoload/provider/clipboard.vim b/runtime/autoload/provider/clipboard.vim index b8baaa8c64..6454a01c2a 100644 --- a/runtime/autoload/provider/clipboard.vim +++ b/runtime/autoload/provider/clipboard.vim @@ -3,28 +3,36 @@ " available. let s:copy = {} let s:paste = {} +let s:clipboard = {} " When caching is enabled, store the jobid of the xclip/xsel process keeping " ownership of the selection, so we know how long the cache is valid. -let s:selection = { 'owner': 0, 'data': [] } +let s:selection = { 'owner': 0, 'data': [], 'on_stderr': function('provider#stderr_collector') } -function! s:selection.on_exit(jobid, data, event) +function! s:selection.on_exit(jobid, data, event) abort " At this point this nvim instance might already have launched " a new provider instance. Don't drop ownership in this case. if self.owner == a:jobid let self.owner = 0 endif + if a:data != 0 + let stderr = provider#get_stderr(a:jobid) + echohl WarningMsg + echomsg 'clipboard: error invoking '.get(self.argv, 0, '?').': '.join(stderr) + echohl None + endif + call provider#clear_stderr(a:jobid) endfunction -let s:selections = { '*': s:selection, '+': copy(s:selection)} +let s:selections = { '*': s:selection, '+': copy(s:selection) } -function! s:try_cmd(cmd, ...) +function! s:try_cmd(cmd, ...) abort let argv = split(a:cmd, " ") let out = a:0 ? systemlist(argv, a:1, 1) : systemlist(argv, [''], 1) if v:shell_error if !exists('s:did_error_try_cmd') echohl WarningMsg - echomsg "clipboard: error: ".(len(out) ? out[0] : '') + echomsg "clipboard: error: ".(len(out) ? out[0] : v:shell_error) echohl None let s:did_error_try_cmd = 1 endif @@ -34,7 +42,7 @@ function! s:try_cmd(cmd, ...) endfunction " Returns TRUE if `cmd` exits with success, else FALSE. -function! s:cmd_ok(cmd) +function! s:cmd_ok(cmd) abort call system(a:cmd) return v:shell_error == 0 endfunction @@ -47,7 +55,18 @@ function! provider#clipboard#Error() abort endfunction function! provider#clipboard#Executable() abort - if executable('pbcopy') + if exists('g:clipboard') + if type({}) isnot# type(g:clipboard) + \ || type({}) isnot# type(get(g:clipboard, 'copy', v:null)) + \ || type({}) isnot# type(get(g:clipboard, 'paste', v:null)) + let s:err = 'clipboard: invalid g:clipboard' + return '' + endif + let s:copy = get(g:clipboard, 'copy', { '+': v:null, '*': v:null }) + let s:paste = get(g:clipboard, 'paste', { '+': v:null, '*': v:null }) + let s:cache_enabled = get(g:clipboard, 'cache_enabled', 0) + return get(g:clipboard, 'name', 'g:clipboard') + elseif has('mac') && executable('pbcopy') let s:copy['+'] = 'pbcopy' let s:paste['+'] = 'pbpaste' let s:copy['*'] = s:copy['+'] @@ -78,26 +97,39 @@ function! provider#clipboard#Executable() abort let s:copy['*'] = s:copy['+'] let s:paste['*'] = s:paste['+'] return 'doitclient' + elseif executable('win32yank') + let s:copy['+'] = 'win32yank -i --crlf' + let s:paste['+'] = 'win32yank -o --lf' + let s:copy['*'] = s:copy['+'] + let s:paste['*'] = s:paste['+'] + return 'win32yank' + elseif exists('$TMUX') && executable('tmux') + let s:copy['+'] = 'tmux load-buffer -' + let s:paste['+'] = 'tmux save-buffer -' + let s:copy['*'] = s:copy['+'] + let s:paste['*'] = s:paste['+'] + return 'tmux' endif - let s:err = 'clipboard: No clipboard tool available. See :help clipboard' + let s:err = 'clipboard: No clipboard tool. :help clipboard' return '' endfunction if empty(provider#clipboard#Executable()) + " provider#clipboard#Call() *must not* be defined if the provider is broken. + " Otherwise eval_has_provider() thinks the clipboard provider is + " functioning, and eval_call_provider() will happily call it. finish endif -let s:clipboard = {} - -function! s:clipboard.get(reg) +function! s:clipboard.get(reg) abort if s:selections[a:reg].owner > 0 return s:selections[a:reg].data end return s:try_cmd(s:paste[a:reg]) endfunction -function! s:clipboard.set(lines, regtype, reg) +function! s:clipboard.set(lines, regtype, reg) abort if a:reg == '"' call s:clipboard.set(a:lines,a:regtype,'+') if s:copy['*'] != s:copy['+'] @@ -118,20 +150,31 @@ function! s:clipboard.set(lines, regtype, reg) end let selection.data = [a:lines, a:regtype] let argv = split(s:copy[a:reg], " ") + let selection.argv = argv let selection.detach = s:cache_enabled let selection.cwd = "/" let jobid = jobstart(argv, selection) - if jobid <= 0 + if jobid > 0 + call jobsend(jobid, a:lines) + call jobclose(jobid, 'stdin') + let selection.owner = jobid + else echohl WarningMsg - echo "clipboard: error when invoking provider" + echomsg 'clipboard: failed to execute: '.(s:copy[a:reg]) echohl None return 0 endif - call jobsend(jobid, a:lines) - call jobclose(jobid, 'stdin') - let selection.owner = jobid + return 1 endfunction -function! provider#clipboard#Call(method, args) - return call(s:clipboard[a:method],a:args,s:clipboard) +function! provider#clipboard#Call(method, args) abort + if get(s:, 'here', v:false) " Clipboard provider must not recurse. #7184 + return 0 + endif + let s:here = v:true + try + return call(s:clipboard[a:method],a:args,s:clipboard) + finally + let s:here = v:false + endtry endfunction diff --git a/runtime/autoload/provider/python.vim b/runtime/autoload/provider/python.vim index b99a046375..81fe194cb9 100644 --- a/runtime/autoload/provider/python.vim +++ b/runtime/autoload/provider/python.vim @@ -1,5 +1,5 @@ " The Python provider uses a Python host to emulate an environment for running -" python-vim plugins. See ":help provider". +" python-vim plugins. :help provider " " Associating the plugin with the Python host is the first step because plugins " will be passed as command-line arguments diff --git a/runtime/autoload/provider/python3.vim b/runtime/autoload/provider/python3.vim index 4f47a03a9b..0c3b75b73d 100644 --- a/runtime/autoload/provider/python3.vim +++ b/runtime/autoload/provider/python3.vim @@ -1,5 +1,5 @@ " The Python3 provider uses a Python3 host to emulate an environment for running -" python3 plugins. See ":help provider". +" python3 plugins. :help provider " " Associating the plugin with the Python3 host is the first step because " plugins will be passed as command-line arguments diff --git a/runtime/autoload/provider/pythonx.vim b/runtime/autoload/provider/pythonx.vim index 08a0f39b01..7285ed43ea 100644 --- a/runtime/autoload/provider/pythonx.vim +++ b/runtime/autoload/provider/pythonx.vim @@ -5,17 +5,7 @@ endif let s:loaded_pythonx_provider = 1 -let s:stderr = {} -let s:job_opts = {'rpc': v:true} - -" TODO(bfredl): this logic is common and should be builtin -function! s:job_opts.on_stderr(chan_id, data, event) - let stderr = get(s:stderr, a:chan_id, ['']) - let last = remove(stderr, -1) - let a:data[0] = last.a:data[0] - call extend(stderr, a:data) - let s:stderr[a:chan_id] = stderr -endfunction +let s:job_opts = {'rpc': v:true, 'on_stderr': function('provider#stderr_collector')} function! provider#pythonx#Require(host) abort let ver = (a:host.orig_name ==# 'python') ? 2 : 3 @@ -38,9 +28,11 @@ function! provider#pythonx#Require(host) abort catch echomsg v:throwpoint echomsg v:exception - for row in get(s:stderr, channel_id, []) + for row in provider#get_stderr(channel_id) echomsg row endfor + finally + call provider#clear_stderr(channel_id) endtry throw remote#host#LoadErrorForHost(a:host.orig_name, \ '$NVIM_PYTHON_LOG_FILE') @@ -112,15 +104,14 @@ function! s:check_interpreter(prog, major_ver) abort endif if v:shell_error == 2 - return [0, prog_path . ' does not have the neovim module installed. ' - \ . 'See ":help provider-python".'] + return [0, prog_path.' does not have the "neovim" module. :help provider-python'] elseif v:shell_error == 127 " This can happen with pyenv's shims. return [0, prog_path . ' does not exist: ' . prog_ver] elseif v:shell_error return [0, 'Checking ' . prog_path . ' caused an unknown error. ' \ . '(' . v:shell_error . ', output: ' . prog_ver . ')' - \ . ' Please report this at github.com/neovim/neovim.'] + \ . ' Report this at https://github.com/neovim/neovim'] endif return [1, ''] diff --git a/runtime/autoload/provider/ruby.vim b/runtime/autoload/provider/ruby.vim index c8ede20a75..91b7fb9f2c 100644 --- a/runtime/autoload/provider/ruby.vim +++ b/runtime/autoload/provider/ruby.vim @@ -16,7 +16,11 @@ function! s:job_opts.on_stderr(chan_id, data, event) endfunction function! provider#ruby#Detect() abort - return exepath('neovim-ruby-host') + if exists("g:ruby_host_prog") + return g:ruby_host_prog + else + return exepath('neovim-ruby-host') + end endfunction function! provider#ruby#Prog() @@ -24,15 +28,15 @@ function! provider#ruby#Prog() endfunction function! provider#ruby#Require(host) abort - let args = [provider#ruby#Prog()] + let prog = provider#ruby#Prog() let ruby_plugins = remote#host#PluginsForHost(a:host.name) for plugin in ruby_plugins - call add(args, plugin.path) + let prog .= " " . shellescape(plugin.path) endfor try - let channel_id = jobstart(args, s:job_opts) + let channel_id = jobstart(prog, s:job_opts) if rpcrequest(channel_id, 'poll') ==# 'ok' return channel_id endif diff --git a/runtime/autoload/provider/script_host.rb b/runtime/autoload/provider/script_host.rb index 1dade766c7..a1c58bde85 100644 --- a/runtime/autoload/provider/script_host.rb +++ b/runtime/autoload/provider/script_host.rb @@ -1,8 +1,6 @@ begin - require "neovim/ruby_provider" + require 'neovim/ruby_provider' rescue LoadError - warn( - "Your neovim RubyGem is missing or out of date. " + - "Install the latest version using `gem install neovim`." - ) + warn('Your neovim RubyGem is missing or out of date.', + 'Install the latest version using `gem install neovim`.') end diff --git a/runtime/autoload/remote/host.vim b/runtime/autoload/remote/host.vim index 51f7e5886f..e695fb7df7 100644 --- a/runtime/autoload/remote/host.vim +++ b/runtime/autoload/remote/host.vim @@ -2,7 +2,6 @@ let s:hosts = {} let s:plugin_patterns = {} let s:plugins_for_host = {} - " Register a host by associating it with a factory(funcref) function! remote#host#Register(name, pattern, factory) abort let s:hosts[a:name] = {'factory': a:factory, 'channel': 0, 'initialized': 0} @@ -13,7 +12,6 @@ function! remote#host#Register(name, pattern, factory) abort endif endfunction - " Register a clone to an existing host. The new host will use the same factory " as `source`, but it will run as a different process. This can be used by " plugins that should run isolated from other plugins created for the same host @@ -31,12 +29,8 @@ function! remote#host#RegisterClone(name, orig_name) abort \ } endfunction - " Get a host channel, bootstrapping it if necessary function! remote#host#Require(name) abort - if empty(s:plugins_for_host) - call remote#host#LoadRemotePlugins() - endif if !has_key(s:hosts, a:name) throw 'No host named "'.a:name.'" is registered' endif @@ -52,7 +46,6 @@ function! remote#host#Require(name) abort return host.channel endfunction - function! remote#host#IsRunning(name) abort if !has_key(s:hosts, a:name) throw 'No host named "'.a:name.'" is registered' @@ -60,7 +53,6 @@ function! remote#host#IsRunning(name) abort return s:hosts[a:name].channel != 0 endfunction - " Example of registering a Python plugin with two commands (one async), one " autocmd (async) and one function (sync): " @@ -117,73 +109,6 @@ function! remote#host#RegisterPlugin(host, path, specs) abort call add(plugins, {'path': a:path, 'specs': a:specs}) endfunction - -" Get the path to the rplugin manifest file. -function! s:GetManifestPath() abort - let manifest_base = '' - - if exists('$NVIM_RPLUGIN_MANIFEST') - return fnamemodify($NVIM_RPLUGIN_MANIFEST, ':p') - endif - - let dest = has('win32') ? '$LOCALAPPDATA' : '$XDG_DATA_HOME' - if !exists(dest) - let dest = has('win32') ? '~/AppData/Local' : '~/.local/share' - endif - - let dest = fnamemodify(expand(dest), ':p') - if !empty(dest) && !filereadable(dest) - let dest .= ('/' ==# dest[-1:] ? '' : '/') . 'nvim' - call mkdir(dest, 'p', 0700) - let manifest_base = dest - endif - - return manifest_base.'/rplugin.vim' -endfunction - - -" Old manifest file based on known script locations. -function! s:GetOldManifestPath() abort - let prefix = exists('$MYVIMRC') - \ ? $MYVIMRC - \ : matchstr(get(split(execute('scriptnames'), '\n'), 0, ''), '\f\+$') - return fnamemodify(expand(prefix, 1), ':h') - \.'/.'.fnamemodify(prefix, ':t').'-rplugin~' -endfunction - - -function! s:GetManifest() abort - let manifest = s:GetManifestPath() - - if !filereadable(manifest) - " Check if an old manifest file exists and move it to the new location. - let old_manifest = s:GetOldManifestPath() - if filereadable(old_manifest) - call rename(old_manifest, manifest) - endif - endif - - return manifest -endfunction - - -function! remote#host#LoadRemotePlugins() abort - let manifest = s:GetManifest() - if filereadable(manifest) - execute 'source' fnameescape(manifest) - endif -endfunction - - -function! remote#host#LoadRemotePluginsEvent(event, pattern) abort - autocmd! nvim-rplugin - call remote#host#LoadRemotePlugins() - if exists('#'.a:event.'#'.a:pattern) " Avoid 'No matching autocommands'. - execute 'silent doautocmd <nomodeline>' a:event a:pattern - endif -endfunction - - function! s:RegistrationCommands(host) abort " Register a temporary host clone for discovering specs let host_id = a:host.'-registration-clone' @@ -228,7 +153,6 @@ function! s:RegistrationCommands(host) abort return lines endfunction - function! remote#host#UpdateRemotePlugins() abort let commands = [] let hosts = keys(s:hosts) @@ -245,12 +169,11 @@ function! remote#host#UpdateRemotePlugins() abort endtry endif endfor - call writefile(commands, s:GetManifest()) + call writefile(commands, g:loaded_remote_plugins) echomsg printf('remote/host: generated rplugin manifest: %s', - \ s:GetManifest()) + \ g:loaded_remote_plugins) endfunction - function! remote#host#PluginsForHost(host) abort if !has_key(s:plugins_for_host, a:host) let s:plugins_for_host[a:host] = [] @@ -258,7 +181,6 @@ function! remote#host#PluginsForHost(host) abort return s:plugins_for_host[a:host] endfunction - function! remote#host#LoadErrorForHost(host, log) abort return 'Failed to load '. a:host . ' host. '. \ 'You can try to see what happened by starting nvim with '. @@ -266,7 +188,6 @@ function! remote#host#LoadErrorForHost(host, log) abort \ ' Also, the host stderr is available in messages.' endfunction - " Registration of standard hosts " Python/Python3 diff --git a/runtime/autoload/rubycomplete.vim b/runtime/autoload/rubycomplete.vim index e1064c8a58..40b87f4cbe 100644 --- a/runtime/autoload/rubycomplete.vim +++ b/runtime/autoload/rubycomplete.vim @@ -93,7 +93,7 @@ function! s:GetBufferRubyEntity( name, type, ... ) let stopline = 1 - let crex = '^\s*\<' . a:type . '\>\s*\<' . a:name . '\>\s*\(<\s*.*\s*\)\?' + let crex = '^\s*\<' . a:type . '\>\s*\<' . escape(a:name, '*') . '\>\s*\(<\s*.*\s*\)\?' let [lnum,lcol] = searchpos( crex, 'w' ) "let [lnum,lcol] = searchpairpos( crex . '\zs', '', '\(end\|}\)', 'w' ) @@ -149,7 +149,7 @@ function! s:GetRubyVarType(v) let ctors = ctors.'\)' let fstr = '=\s*\([^ \t]\+.' . ctors .'\>\|[\[{"''/]\|%[xwQqr][(\[{@]\|[A-Za-z0-9@:\-()\.]\+...\?\|lambda\|&\)' - let sstr = ''.a:v.'\>\s*[+\-*/]*'.fstr + let sstr = ''.escape(a:v, '*').'\>\s*[+\-*/]*'.fstr let [lnum,lcol] = searchpos(sstr,'nb',stopline) if lnum != 0 && lcol != 0 let str = matchstr(getline(lnum),fstr,lcol) @@ -196,7 +196,7 @@ function! rubycomplete#Complete(findstart, base) if c =~ '\w' continue elseif ! c =~ '\.' - idx = -1 + let idx = -1 break else break @@ -266,6 +266,28 @@ class VimRubyCompletion end end + def load_gems + fpath = VIM::evaluate("get(g:, 'rubycomplete_gemfile_path', 'Gemfile')") + return unless File.file?(fpath) && File.readable?(fpath) + want_bundler = VIM::evaluate("get(g:, 'rubycomplete_use_bundler')") + parse_file = !want_bundler + begin + require 'bundler' + Bundler.setup + Bundler.require + rescue Exception + parse_file = true + end + if parse_file + File.new(fpath).each_line do |line| + begin + require $1 if /\s*gem\s*['"]([^'"]+)/.match(line) + rescue Exception + end + end + end + end + def load_buffer_class(name) dprint "load_buffer_class(%s) START" % name classdef = get_buffer_entity(name, 's:GetBufferRubyClass("%s")') @@ -588,6 +610,10 @@ class VimRubyCompletion load_rails end + want_gems = VIM::evaluate("get(g:, 'rubycomplete_load_gemfile')") + load_gems unless want_gems.to_i.zero? + + input = VIM::Buffer.current.line cpos = VIM::Window.current.cursor[1] - 1 input = input[0..cpos] @@ -678,7 +704,9 @@ class VimRubyCompletion cv = eval("self.class.constants") vartype = get_var_type( receiver ) dprint "vartype: %s" % vartype - if vartype != '' + + invalid_vartype = ['', "gets"] + if !invalid_vartype.include?(vartype) load_buffer_class( vartype ) begin @@ -706,7 +734,7 @@ class VimRubyCompletion methods.concat m.instance_methods(false) } end - variables += add_rails_columns( "#{vartype}" ) if vartype && vartype.length > 0 + variables += add_rails_columns( "#{vartype}" ) if vartype && !invalid_vartype.include?(vartype) when /^\(?\s*[A-Za-z0-9:^@.%\/+*\(\)]+\.\.\.?[A-Za-z0-9:^@.%\/+*\(\)]+\s*\)?\.([^.]*)/ message = $1 diff --git a/runtime/autoload/shada.vim b/runtime/autoload/shada.vim index cf27ee608a..87acc515ee 100644 --- a/runtime/autoload/shada.vim +++ b/runtime/autoload/shada.vim @@ -45,7 +45,7 @@ call map(copy(s:SHADA_ENTRY_NAMES), let s:SHADA_MAP_ENTRIES = { \'search_pattern': ['sp', 'sh', 'ss', 'sb', 'sm', 'sc', 'sl', 'se', 'so', \ 'su'], - \'register': ['n', 'rc', 'rw', 'rt'], + \'register': ['n', 'rc', 'rw', 'rt', 'ru'], \'global_mark': ['n', 'f', 'l', 'c'], \'local_mark': ['f', 'n', 'l', 'c'], \'jump': ['f', 'l', 'c'], @@ -139,6 +139,7 @@ let s:SHADA_STANDARD_KEYS = { \'rt': ['type', 'regtype', s:SHADA_ENUMS.regtype.CHARACTERWISE], \'rw': ['block width', 'uint', 0], \'rc': ['contents', 'binarray', s:SHADA_REQUIRED], + \'ru': ['is_unnamed', 'boolean', g:msgpack#false], \'n': ['name', 'intchar', char2nr('"')], \'l': ['line number', 'uint', 1], \'c': ['column', 'uint', 0], diff --git a/runtime/autoload/tar.vim b/runtime/autoload/tar.vim index 5e76870cce..9c518cb9d0 100644 --- a/runtime/autoload/tar.vim +++ b/runtime/autoload/tar.vim @@ -117,7 +117,7 @@ fun! tar#Browse(tarfile) if !filereadable(a:tarfile) " call Decho('a:tarfile<'.a:tarfile.'> not filereadable') if a:tarfile !~# '^\a\+://' - " if its an url, don't complain, let url-handlers such as vim do its thing + " if it's an url, don't complain, let url-handlers such as vim do its thing redraw! echohl Error | echo "***error*** (tar#Browse) File not readable<".a:tarfile.">" | echohl None endif diff --git a/runtime/autoload/tutor.vim b/runtime/autoload/tutor.vim index 43d8a87886..56e2283465 100644 --- a/runtime/autoload/tutor.vim +++ b/runtime/autoload/tutor.vim @@ -15,30 +15,17 @@ function! tutor#SetupVim() endif endfunction -" Mappings: {{{1 - -function! s:CheckMaps() - nmap +" Loads metadata file, if available +function! tutor#LoadMetadata() + let b:tutor_metadata = json_decode(join(readfile(expand('%').'.json'), "\n")) endfunction -function! s:MapKeyWithRedirect(key, cmd) - if maparg(a:key) !=# '' - redir => l:keys - silent call s:CheckMaps() - redir END - let l:key_list = split(l:keys, '\n') - - let l:raw_map = filter(copy(l:key_list), "v:val =~# '\\* ".a:key."'") - if len(l:raw_map) == 0 - exe "nnoremap <buffer> <expr> ".a:key." ".a:cmd - return - endif - let l:map_data = split(l:raw_map[0], '\s*') +" Mappings: {{{1 - exe "nnoremap <buffer> <expr> ".l:map_data[0]." ".a:cmd - else - exe "nnoremap <buffer> <expr> ".a:key." ".a:cmd - endif +function! tutor#SetNormalMappings() + nnoremap <silent> <buffer> <CR> :call tutor#FollowLink(0)<cr> + nnoremap <silent> <buffer> <2-LeftMouse> :call tutor#MouseDoubleClick()<cr> + nnoremap <buffer> >> :call tutor#InjectCommand()<cr> endfunction function! tutor#MouseDoubleClick() @@ -46,7 +33,7 @@ function! tutor#MouseDoubleClick() normal! zo else if match(getline('.'), '^#\{1,} ') > -1 - normal! zc + silent normal! zc else call tutor#FollowLink(0) endif @@ -59,114 +46,6 @@ function! tutor#InjectCommand() redraw | echohl WarningMsg | echon "tutor: ran" | echohl None | echon " " | echohl Statement | echon l:cmd endfunction -function! tutor#SetNormalMappings() - call s:MapKeyWithRedirect('l', 'tutor#ForwardSkipConceal(v:count1)') - call s:MapKeyWithRedirect('h', 'tutor#BackwardSkipConceal(v:count1)') - call s:MapKeyWithRedirect('<right>', 'tutor#ForwardSkipConceal(v:count1)') - call s:MapKeyWithRedirect('<left>', 'tutor#BackwardSkipConceal(v:count1)') - - nnoremap <silent> <buffer> <CR> :call tutor#FollowLink(0)<cr> - nnoremap <silent> <buffer> <2-LeftMouse> :call tutor#MouseDoubleClick()<cr> - nnoremap <buffer> >> :call tutor#InjectCommand()<cr> -endfunction - -function! tutor#SetSampleTextMappings() - noremap <silent> <buffer> A :if match(getline('.'), '^--->') > -1 \| call search('\s{\@=', 'Wc') \| startinsert \| else \| startinsert! \| endif<cr> - noremap <silent> <buffer> $ :if match(getline('.'), '^--->') > -1 \| call search('.\s{\@=', 'Wc') \| else \| call search('$', 'Wc') \| endif<cr> - onoremap <silent> <buffer> $ :if match(getline('.'), '^--->') > -1 \| call search('.\s{\@=', 'Wc') \| else \| call search('$', 'Wc') \| endif<cr> - noremap <silent> <buffer> ^ :if match(getline('.'), '^--->') > -1 \| call search('\(--->\s\)\@<=.', 'bcW') \| else \| call search('^', 'bcW') \|endif<cr> - onoremap <silent> <buffer> ^ :if match(getline('.'), '^--->') > -1 \| call search('\(--->\s\)\@<=.', 'bcW') \| else \| call search('^', 'bcW') \|endif<cr> - nmap <silent> <buffer> 0 ^<esc> - nmap <silent> <buffer> <Home> ^<esc> - nmap <silent> <buffer> <End> $ - imap <silent> <buffer> <Home> <esc>^<esc>:startinsert<cr> - imap <silent> <buffer> <End> <esc>$:startinsert<cr> - noremap <silent> <buffer> I :exe "normal! 0" \| startinsert<cr> -endfunction - -" Navigation: {{{1 - -" taken from http://stackoverflow.com/a/24224578 - -function! tutor#ForwardSkipConceal(count) - let cnt=a:count - let mvcnt=0 - let c=col('.') - let l=line('.') - let lc=col('$') - let line=getline('.') - while cnt - if c>=lc - let mvcnt+=cnt - break - endif - if stridx(&concealcursor, 'n')==-1 - let isconcealed=0 - else - let [isconcealed, cchar, group] = synconcealed(l, c) - endif - if isconcealed - let cnt-=strchars(cchar) - let oldc=c - let c+=1 - while c < lc - let [isconcealed2, cchar2, group2] = synconcealed(l, c) - if !isconcealed2 || cchar2 != cchar - break - endif - let c+= 1 - endwhile - let mvcnt+=strchars(line[oldc-1:c-2]) - else - let cnt-=1 - let mvcnt+=1 - let c+=len(matchstr(line[c-1:], '.')) - endif - endwhile - return mvcnt.'l' -endfunction - -function! tutor#BackwardSkipConceal(count) - let cnt=a:count - let mvcnt=0 - let c=col('.') - let l=line('.') - let lc=0 - let line=getline('.') - while cnt - if c<=1 - let mvcnt+=cnt - break - endif - if stridx(&concealcursor, 'n')==-1 || c == 0 - let isconcealed=0 - else - let [isconcealed, cchar, group]=synconcealed(l, c-1) - endif - if isconcealed - let cnt-=strchars(cchar) - let oldc=c - let c-=1 - while c>1 - let [isconcealed2, cchar2, group2] = synconcealed(l, c-1) - if !isconcealed2 || cchar2 != cchar - break - endif - let c-=1 - endwhile - let c = max([c, 1]) - let mvcnt+=strchars(line[c-1:oldc-2]) - else - let cnt-=1 - let mvcnt+=1 - let c-=len(matchstr(line[:c-2], '.$')) - endif - endwhile - return mvcnt.'h' -endfunction - -" Hypertext: {{{1 - function! tutor#FollowLink(force) let l:stack_s = join(map(synstack(line('.'), col('.')), 'synIDattr(v:val, "name")'), '') if l:stack_s =~# 'tutorLink' @@ -209,42 +88,40 @@ function! tutor#InfoText() return join(l:info_parts, " ") endfunction -" Marks {{{1 -function! tutor#PlaceXMarks() - call cursor(1, 1) - let b:tutor_sign_id = 1 - while search('^--->', 'W') > 0 - call tutor#CheckText(getline('.')) - let b:tutor_sign_id+=1 - endwhile - call cursor(1, 1) + +" Marks: {{{1 + +function! tutor#ApplyMarks() + hi! link tutorExpect Special + if exists('b:tutor_metadata') && has_key(b:tutor_metadata, 'expect') + let b:tutor_sign_id = 1 + for expct in keys(b:tutor_metadata['expect']) + let lnum = eval(expct) + call matchaddpos('tutorExpect', [lnum]) + call tutor#CheckLine(lnum) + endfor + endif endfunction -function! tutor#CheckText(text) - if match(a:text, '{expect:ANYTHING}\s*$') == -1 - if match(getline('.'), '^--->\s*$') > -1 - exe "sign place ".b:tutor_sign_id." line=".line('.')." name=tutorbad buffer=".bufnr('%') - else - if match(getline('.'), '|expect:.\+|') == -1 - let l:cur_text = matchstr(a:text, '---> \zs.\{-}\ze {expect:') - let l:expected_text = matchstr(a:text, '{expect:\zs.*\ze}\s*$') - else - let l:cur_text = matchstr(a:text, '---> \zs.\{-}\ze |expect:') - let l:expected_text = matchstr(a:text, '|expect:\zs.*\ze|\s*$') - endif - if l:cur_text ==# l:expected_text - exe "sign place ".b:tutor_sign_id." line=".line('.')." name=tutorok buffer=".bufnr('%') - else - exe "sign place ".b:tutor_sign_id." line=".line('.')." name=tutorbad buffer=".bufnr('%') - endif +function! tutor#ApplyMarksOnChanged() + if exists('b:tutor_metadata') && has_key(b:tutor_metadata, 'expect') + let lnum = line('.') + if index(keys(b:tutor_metadata['expect']), string(lnum)) > -1 + call tutor#CheckLine(lnum) endif endif endfunction -function! tutor#OnTextChanged() - let l:text = getline('.') - if match(l:text, '^--->') > -1 - call tutor#CheckText(l:text) +function! tutor#CheckLine(line) + if exists('b:tutor_metadata') && has_key(b:tutor_metadata, 'expect') + let bufn = bufnr('%') + let ctext = getline(a:line) + if b:tutor_metadata['expect'][string(a:line)] == -1 || ctext ==# b:tutor_metadata['expect'][string(a:line)] + exe "sign place ".b:tutor_sign_id." line=".a:line." name=tutorok buffer=".bufn + else + exe "sign place ".b:tutor_sign_id." line=".a:line." name=tutorbad buffer=".bufn + endif + let b:tutor_sign_id+=1 endif endfunction diff --git a/runtime/autoload/zip.vim b/runtime/autoload/zip.vim index 687500ebe3..ea086e0882 100644 --- a/runtime/autoload/zip.vim +++ b/runtime/autoload/zip.vim @@ -1,7 +1,7 @@ " zip.vim: Handles browsing zipfiles " AUTOLOAD PORTION -" Date: Jul 02, 2013 -" Version: 27 +" Date: Sep 13, 2016 +" Version: 28 " Maintainer: Charles E Campbell <NdrOchip@ScampbellPfamily.AbizM-NOSPAM> " License: Vim License (see vim's :help license) " Copyright: Copyright (C) 2005-2013 Charles E. Campbell {{{1 @@ -20,10 +20,10 @@ if &cp || exists("g:loaded_zip") finish endif -let g:loaded_zip= "v27" +let g:loaded_zip= "v28" if v:version < 702 echohl WarningMsg - echo "***warning*** this version of zip needs vim 7.2" + echo "***warning*** this version of zip needs vim 7.2 or later" echohl Normal finish endif @@ -53,6 +53,9 @@ endif if !exists("g:zip_unzipcmd") let g:zip_unzipcmd= "unzip" endif +if !exists("g:zip_extractcmd") + let g:zip_extractcmd= g:zip_unzipcmd +endif " ---------------- " Functions: {{{1 @@ -62,14 +65,14 @@ endif " zip#Browse: {{{2 fun! zip#Browse(zipfile) " call Dfunc("zip#Browse(zipfile<".a:zipfile.">)") - " sanity check: insure that the zipfile has "PK" as its first two letters + " sanity check: ensure that the zipfile has "PK" as its first two letters " (zipped files have a leading PK as a "magic cookie") if !filereadable(a:zipfile) || readfile(a:zipfile, "", 1)[0] !~ '^PK' exe "noautocmd e ".fnameescape(a:zipfile) " call Dret("zip#Browse : not a zipfile<".a:zipfile.">") return " else " Decho -" call Decho("zip#Browse: a:zipfile<".a:zipfile."> passed PK test - its a zip file") +" call Decho("zip#Browse: a:zipfile<".a:zipfile."> passed PK test - it's a zip file") endif let repkeep= &report @@ -92,7 +95,7 @@ fun! zip#Browse(zipfile) endif if !filereadable(a:zipfile) if a:zipfile !~# '^\a\+://' - " if its an url, don't complain, let url-handlers such as vim do its thing + " if it's an url, don't complain, let url-handlers such as vim do its thing redraw! echohl Error | echo "***error*** (zip#Browse) File not readable<".a:zipfile.">" | echohl None " call inputsave()|call input("Press <cr> to continue")|call inputrestore() @@ -136,8 +139,10 @@ fun! zip#Browse(zipfile) return endif + " Maps associated with zip plugin setlocal noma nomod ro - noremap <silent> <buffer> <cr> :call <SID>ZipBrowseSelect()<cr> + noremap <silent> <buffer> <cr> :call <SID>ZipBrowseSelect()<cr> + noremap <silent> <buffer> x :call zip#Extract()<cr> let &report= repkeep " call Dret("zip#Browse") @@ -204,6 +209,15 @@ fun! zip#Read(fname,mode) endif " call Decho("zipfile<".zipfile.">") " call Decho("fname <".fname.">") + " sanity check + if !executable(substitute(g:zip_unzipcmd,'\s\+.*$','','')) + redraw! + echohl Error | echo "***error*** (zip#Read) sorry, your system doesn't appear to have the ".g:zip_unzipcmd." program" | echohl None +" call inputsave()|call input("Press <cr> to continue")|call inputrestore() + let &report= repkeep +" call Dret("zip#Write") + return + endif " the following code does much the same thing as " exe "keepj sil! r! ".g:zip_unzipcmd." -p -- ".s:Escape(zipfile,1)." ".s:Escape(fnameescape(fname),1) @@ -236,9 +250,9 @@ fun! zip#Write(fname) set report=10 " sanity checks - if !executable(g:zip_zipcmd) + if !executable(substitute(g:zip_zipcmd,'\s\+.*$','','')) redraw! - echohl Error | echo "***error*** (zip#Write) sorry, your system doesn't appear to have the zip pgm" | echohl None + echohl Error | echo "***error*** (zip#Write) sorry, your system doesn't appear to have the ".g:zip_zipcmd." program" | echohl None " call inputsave()|call input("Press <cr> to continue")|call inputrestore() let &report= repkeep " call Dret("zip#Write") @@ -345,6 +359,48 @@ fun! zip#Write(fname) endfun " --------------------------------------------------------------------- +" zip#Extract: extract a file from a zip archive {{{2 +fun! zip#Extract() +" call Dfunc("zip#Extract()") + + let repkeep= &report + set report=10 + let fname= getline(".") +" call Decho("fname<".fname.">") + + " sanity check + if fname =~ '^"' + let &report= repkeep +" call Dret("zip#Extract") + return + endif + if fname =~ '/$' + redraw! + echohl Error | echo "***error*** (zip#Extract) Please specify a file, not a directory" | echohl None + let &report= repkeep +" call Dret("zip#Extract") + return + endif + + " extract the file mentioned under the cursor +" call Decho("system(".g:zip_extractcmd." ".shellescape(b:zipfile)." ".shellescape(shell).")") + call system(g:zip_extractcmd." ".shellescape(b:zipfile)." ".shellescape(shell)) +" call Decho("zipfile<".b:zipfile.">") + if v:shell_error != 0 + echohl Error | echo "***error*** ".g:zip_extractcmd." ".b:zipfile." ".fname.": failed!" | echohl NONE + elseif !filereadable(fname) + echohl Error | echo "***error*** attempted to extract ".fname." but it doesn't appear to be present!" + else + echo "***note*** successfully extracted ".fname + endif + + " restore option + let &report= repkeep + +" call Dret("zip#Extract") +endfun + +" --------------------------------------------------------------------- " s:Escape: {{{2 fun! s:Escape(fname,isfilt) " call Dfunc("QuoteFileDir(fname<".a:fname."> isfilt=".a:isfilt.")") diff --git a/runtime/bugreport.vim b/runtime/bugreport.vim index f0c045e6c3..650e37940d 100644 --- a/runtime/bugreport.vim +++ b/runtime/bugreport.vim @@ -53,7 +53,6 @@ : scriptnames :endif :set all -:set termcap :if has("autocmd") : au :endif diff --git a/runtime/colors/README.txt b/runtime/colors/README.txt index 3b3445cbc9..8fa6f322ab 100644 --- a/runtime/colors/README.txt +++ b/runtime/colors/README.txt @@ -41,9 +41,16 @@ this autocmd might be useful: autocmd SourcePre */colors/blue_sky.vim set background=dark Replace "blue_sky" with the name of the colorscheme. -In case you want to tweak a colorscheme after it was loaded, check out that +In case you want to tweak a colorscheme after it was loaded, check out the ColorScheme autocmd event. +To customize a colorscheme use another name, e.g. "~/.vim/colors/mine.vim", +and use `:runtime` to load the original colorscheme: + " load the "evening" colorscheme + runtime colors/evening.vim + " change the color of statements + hi Statement ctermfg=Blue guifg=Blue + To see which highlight group is used where, find the help for "highlight-groups" and "group-name". diff --git a/runtime/colors/evening.vim b/runtime/colors/evening.vim index 5dae08280e..5257307593 100644 --- a/runtime/colors/evening.vim +++ b/runtime/colors/evening.vim @@ -1,6 +1,6 @@ " Vim color file " Maintainer: Bram Moolenaar <Bram@vim.org> -" Last Change: 2006 Apr 14 +" Last Change: 2016 Oct 10 " This color scheme uses a dark grey background. @@ -45,8 +45,8 @@ hi CursorColumn term=reverse ctermbg=Black guibg=grey40 hi CursorLine term=underline cterm=underline guibg=grey40 " Groups for syntax highlighting -hi Constant term=underline ctermfg=Magenta guifg=#ffa0a0 guibg=grey5 -hi Special term=bold ctermfg=LightRed guifg=Orange guibg=grey5 +hi Constant term=underline ctermfg=Magenta guifg=#ffa0a0 +hi Special term=bold ctermfg=LightRed guifg=Orange if &t_Co > 8 hi Statement term=bold cterm=bold ctermfg=Yellow guifg=#ffff60 gui=bold endif diff --git a/runtime/colors/koehler.vim b/runtime/colors/koehler.vim index a36f9f6972..250472a162 100644 --- a/runtime/colors/koehler.vim +++ b/runtime/colors/koehler.vim @@ -2,7 +2,7 @@ " vim: tw=0 ts=4 sw=4 " Vim color file " Maintainer: Ron Aaron <ron@ronware.org> -" Last Change: 2013 May 23 +" Last Change: 2016 Sep 04 hi clear set background=dark @@ -45,6 +45,7 @@ hi TabLineFill term=bold,reverse cterm=bold ctermfg=lightblue ctermbg=white g hi TabLineSel term=reverse ctermfg=white ctermbg=lightblue guifg=white guibg=blue hi Underlined term=underline cterm=bold,underline ctermfg=lightblue guifg=lightblue gui=bold,underline hi Ignore ctermfg=black ctermbg=black guifg=black guibg=black +hi EndOfBuffer term=bold cterm=bold ctermfg=darkred guifg=#cc0000 gui=bold hi link IncSearch Visual hi link String Constant hi link Character Constant diff --git a/runtime/compiler/context.vim b/runtime/compiler/context.vim new file mode 100644 index 0000000000..cb78c96df0 --- /dev/null +++ b/runtime/compiler/context.vim @@ -0,0 +1,54 @@ +" Vim compiler file +" Compiler: ConTeXt typesetting engine +" Maintainer: Nicola Vitacolonna <nvitacolonna@gmail.com> +" Last Change: 2016 Oct 21 + +if exists("current_compiler") + finish +endif +let s:keepcpo= &cpo +set cpo&vim + +if exists(":CompilerSet") != 2 " older Vim always used :setlocal + command -nargs=* CompilerSet setlocal <args> +endif + +" If makefile exists and we are not asked to ignore it, we use standard make +" (do not redefine makeprg) +if get(b:, 'context_ignore_makefile', get(g:, 'context_ignore_makefile', 0)) || + \ (!filereadable('Makefile') && !filereadable('makefile')) + let current_compiler = 'context' + " The following assumes that the current working directory is set to the + " directory of the file to be typeset + let &l:makeprg = get(b:, 'context_mtxrun', get(g:, 'context_mtxrun', 'mtxrun')) + \ . ' --script context --autogenerate --nonstopmode --synctex=' + \ . (get(b:, 'context_synctex', get(g:, 'context_synctex', 0)) ? '1' : '0') + \ . ' ' . get(b:, 'context_extra_options', get(g:, 'context_extra_options', '')) + \ . ' ' . shellescape(expand('%:p:t')) +else + let current_compiler = 'make' +endif + +let b:context_errorformat = '' + \ . '%-Popen source%.%#> %f,' + \ . '%-Qclose source%.%#> %f,' + \ . "%-Popen source%.%#name '%f'," + \ . "%-Qclose source%.%#name '%f'," + \ . '%Etex %trror%.%#mp error on line %l in file %f:%.%#,' + \ . 'tex %trror%.%#error on line %l in file %f: %m,' + \ . '%Elua %trror%.%#error on line %l in file %f:,' + \ . '%+Emetapost %#> error: %#,' + \ . '! error: %#%m,' + \ . '%-C %#,' + \ . '%C! %m,' + \ . '%Z[ctxlua]%m,' + \ . '%+C<*> %.%#,' + \ . '%-C%.%#,' + \ . '%Z...%m,' + \ . '%-Zno-error,' + \ . '%-G%.%#' " Skip remaining lines + +execute 'CompilerSet errorformat=' . escape(b:context_errorformat, ' ') + +let &cpo = s:keepcpo +unlet s:keepcpo diff --git a/runtime/compiler/csslint.vim b/runtime/compiler/csslint.vim new file mode 100644 index 0000000000..14c4289a24 --- /dev/null +++ b/runtime/compiler/csslint.vim @@ -0,0 +1,16 @@ +" Vim compiler file +" Compiler: csslint for CSS +" Maintainer: Daniel Moch <daniel@danielmoch.com> +" Last Change: 2016 May 21 + +if exists("current_compiler") + finish +endif +let current_compiler = "csslint" + +if exists(":CompilerSet") != 2 " older Vim always used :setlocal + command -nargs=* CompilerSet setlocal <args> +endif + +CompilerSet makeprg=csslint\ --format=compact +CompilerSet errorformat=%-G,%-G%f:\ lint\ free!,%f:\ line\ %l\\,\ col\ %c\\,\ %trror\ -\ %m,%f:\ line\ %l\\,\ col\ %c\\,\ %tarning\ -\ %m,%f:\ line\ %l\\,\ col\ %c\\,\ %m diff --git a/runtime/compiler/cucumber.vim b/runtime/compiler/cucumber.vim index c020be6e3b..17ce3627c1 100644 --- a/runtime/compiler/cucumber.vim +++ b/runtime/compiler/cucumber.vim @@ -1,7 +1,7 @@ " Vim compiler file " Compiler: Cucumber " Maintainer: Tim Pope <vimNOSPAM@tpope.org> -" Last Change: 2010 Aug 09 +" Last Change: 2016 Aug 29 if exists("current_compiler") finish @@ -19,7 +19,7 @@ CompilerSet makeprg=cucumber CompilerSet errorformat= \%W%m\ (Cucumber::Undefined), - \%E%m\ (%.%#), + \%E%m\ (%\\S%#), \%Z%f:%l, \%Z%f:%l:%.%# diff --git a/runtime/compiler/ghc.vim b/runtime/compiler/ghc.vim new file mode 100644 index 0000000000..c98ae302a8 --- /dev/null +++ b/runtime/compiler/ghc.vim @@ -0,0 +1,26 @@ +" Vim compiler file +" Compiler: GHC Haskell Compiler +" Maintainer: Daniel Campoverde <alx@sillybytes.net> +" Latest Revision: 2016-11-29 + +if exists("current_compiler") + finish +endif +let current_compiler = "ghc" + +let s:cpo_save = &cpo +set cpo&vim + +CompilerSet errorformat= + \%-G%.%#:\ build, + \%-G%.%#preprocessing\ library\ %.%#, + \%-G[%.%#]%.%#, + \%E%f:%l:%c:\ %m, + \%-G--%.%# + +if exists('g:compiler_ghc_ignore_unmatched_lines') + CompilerSet errorformat+=%-G%.%# +endif + +let &cpo = s:cpo_save +unlet s:cpo_save diff --git a/runtime/compiler/haml.vim b/runtime/compiler/haml.vim index b06a672df7..9464c3dc85 100644 --- a/runtime/compiler/haml.vim +++ b/runtime/compiler/haml.vim @@ -1,7 +1,7 @@ " Vim compiler file " Compiler: Haml " Maintainer: Tim Pope <vimNOSPAM@tpope.org> -" Last Change: 2013 May 30 +" Last Change: 2016 Aug 29 if exists("current_compiler") finish @@ -15,7 +15,7 @@ endif let s:cpo_save = &cpo set cpo-=C -CompilerSet makeprg=haml\ -c +CompilerSet makeprg=haml CompilerSet errorformat= \Haml\ %trror\ on\ line\ %l:\ %m, diff --git a/runtime/compiler/pylint.vim b/runtime/compiler/pylint.vim new file mode 100644 index 0000000000..93079ce61d --- /dev/null +++ b/runtime/compiler/pylint.vim @@ -0,0 +1,16 @@ +" Vim compiler file +" Compiler: Pylint for Python +" Maintainer: Daniel Moch <daniel@danielmoch.com> +" Last Change: 2016 May 20 + +if exists("current_compiler") + finish +endif +let current_compiler = "pylint" + +if exists(":CompilerSet") != 2 " older Vim always used :setlocal + command -nargs=* CompilerSet setlocal <args> +endif + +CompilerSet makeprg=pylint\ --output-format=text\ --msg-template=\"{path}:{line}:{column}:{C}:\ [{symbol}]\ {msg}\"\ --reports=no +CompilerSet errorformat=%A%f:%l:%c:%t:\ %m,%A%f:%l:\ %m,%A%f:(%l):\ %m,%-Z%p^%.%#,%-G%.%# diff --git a/runtime/compiler/rake.vim b/runtime/compiler/rake.vim index 3bd9da0daf..8490f2a9e9 100644 --- a/runtime/compiler/rake.vim +++ b/runtime/compiler/rake.vim @@ -27,7 +27,11 @@ CompilerSet errorformat= \%\\s%#[%f:%l:\ %#%m, \%\\s%#%f:%l:\ %#%m, \%\\s%#%f:%l:, - \%m\ [%f:%l]: + \%m\ [%f:%l]:, + \%+Erake\ aborted!, + \%+EDon't\ know\ how\ to\ build\ task\ %.%#, + \%+Einvalid\ option:%.%#, + \%+Irake\ %\\S%\\+%\\s%\\+#\ %.%# let &cpo = s:cpo_save unlet s:cpo_save diff --git a/runtime/compiler/rspec.vim b/runtime/compiler/rspec.vim index 7c340bab15..c77bd70da7 100644 --- a/runtime/compiler/rspec.vim +++ b/runtime/compiler/rspec.vim @@ -22,9 +22,10 @@ CompilerSet errorformat= \%f:%l:\ %tarning:\ %m, \%E%.%#:in\ `load':\ %f:%l:%m, \%E%f:%l:in\ `%*[^']':\ %m, - \%-Z\ \ \ \ \ \#\ %f:%l:%.%#, + \%-Z\ \ \ \ \ %\\+\#\ %f:%l:%.%#, \%E\ \ %\\d%\\+)%.%#, \%C\ \ \ \ \ %m, + \%C%\\s%#, \%-G%.%# let &cpo = s:cpo_save diff --git a/runtime/compiler/rubyunit.vim b/runtime/compiler/rubyunit.vim index 93a0c8e653..ed0639b581 100644 --- a/runtime/compiler/rubyunit.vim +++ b/runtime/compiler/rubyunit.vim @@ -17,6 +17,8 @@ let s:cpo_save = &cpo set cpo-=C CompilerSet makeprg=testrb +" CompilerSet makeprg=ruby\ -Itest +" CompilerSet makeprg=m CompilerSet errorformat=\%W\ %\\+%\\d%\\+)\ Failure:, \%C%m\ [%f:%l]:, diff --git a/runtime/compiler/sass.vim b/runtime/compiler/sass.vim index 376a52b303..9c540ac443 100644 --- a/runtime/compiler/sass.vim +++ b/runtime/compiler/sass.vim @@ -1,7 +1,7 @@ " Vim compiler file " Compiler: Sass " Maintainer: Tim Pope <vimNOSPAM@tpope.org> -" Last Change: 2013 May 30 +" Last Change: 2016 Aug 29 if exists("current_compiler") finish @@ -15,7 +15,7 @@ endif let s:cpo_save = &cpo set cpo-=C -CompilerSet makeprg=sass\ -c +CompilerSet makeprg=sass CompilerSet errorformat= \%f:%l:%m\ (Sass::Syntax%trror), diff --git a/runtime/doc/api-funcs.txt b/runtime/doc/api-funcs.txt deleted file mode 100644 index 706941fd12..0000000000 --- a/runtime/doc/api-funcs.txt +++ /dev/null @@ -1,716 +0,0 @@ -*api-funcs.txt* Neovim API Function Reference {Nvim} - -Note: This documentation is generated from Neovim's API source code. - -Contents: - -1. Global Functions |api-global| -2. Buffer Functions |api-buffer| -3. Window Functions |api-window| -4. Tabpage Functions |api-tabpage| -5. UI Functions |api-ui| - -============================================================================== -1. Global Functions *api-global* - -nvim_command({command}) *nvim_command()* - Executes an ex-command. On VimL error: Returns the VimL error; - v:errmsg is not updated. - - Parameters:~ - {command} Ex-command string - -nvim_feedkeys({keys}, {mode}, {escape_csi}) *nvim_feedkeys()* - Passes input keys to Nvim. On VimL error: Does not fail, but - updates v:errmsg. - - Parameters:~ - {keys} to be typed - {mode} mapping options - {escape_csi} If true, escape K_SPECIAL/CSI bytes in - `keys` - -nvim_input({keys}) *nvim_input()* - Passes keys to Nvim as raw user-input. On VimL error: Does not - fail, but updates v:errmsg. - - Unlike `nvim_feedkeys`, this uses a lower-level input buffer - and the call is not deferred. This is the most reliable way to - emulate real user input. - - Parameters:~ - {keys} to be typed - - Return:~ - Number of bytes actually written (can be fewer than - requested if the buffer becomes full). - - *nvim_replace_termcodes()* -nvim_replace_termcodes({str}, {from_part}, {do_lt}, {special}) - Replaces any terminal codes with the internal representation - -nvim_command_output({str}) *nvim_command_output()* - TODO: Documentation - -nvim_eval({expr}) *nvim_eval()* - Evaluates a VimL expression (:help expression). Dictionaries - and Lists are recursively expanded. On VimL error: Returns a - generic error; v:errmsg is not updated. - - Parameters:~ - {expr} VimL expression string - - Return:~ - Evaluation result or expanded object - -nvim_call_function({fname}, {args}) *nvim_call_function()* - Calls a VimL function with the given arguments. On VimL error: - Returns a generic error; v:errmsg is not updated. - - Parameters:~ - {fname} Function to call - {args} Function arguments packed in an Array - - Return:~ - Result of the function call - -nvim_strwidth({str}) *nvim_strwidth()* - Calculates the number of display cells occupied by `text`. - <Tab> counts as one cell. - - Parameters:~ - {text} Some text - - Return:~ - Number of cells - -nvim_list_runtime_paths() *nvim_list_runtime_paths()* - Gets the paths contained in 'runtimepath'. - - Return:~ - List of paths - -nvim_set_current_dir({dir}) *nvim_set_current_dir()* - Changes the global working directory. - - Parameters:~ - {dir} Directory path - -nvim_get_current_line() *nvim_get_current_line()* - Gets the current line - - Parameters:~ - - Return:~ - Current line string - -nvim_set_current_line({line}) *nvim_set_current_line()* - Sets the current line - - Parameters:~ - {line} Line contents - -nvim_del_current_line() *nvim_del_current_line()* - Deletes the current line - - Parameters:~ - -nvim_get_var({name}) *nvim_get_var()* - Gets a global (g:) variable - - Parameters:~ - {name} Variable name - - Return:~ - Variable value - -nvim_set_var({name}, {value}) *nvim_set_var()* - Sets a global (g:) variable - - Parameters:~ - {name} Variable name - {value} Variable value - -nvim_del_var({name}) *nvim_del_var()* - Removes a global (g:) variable - - Parameters:~ - {name} Variable name - -nvim_get_vvar({name}) *nvim_get_vvar()* - Gets a v: variable - - Parameters:~ - {name} Variable name - - Return:~ - Variable value - -nvim_get_option({name}) *nvim_get_option()* - Gets an option value string - - Parameters:~ - {name} Option name - - Return:~ - Option value - -nvim_set_option({name}, {value}) *nvim_set_option()* - Sets an option value - - Parameters:~ - {name} Option name - {value} New option value - -nvim_out_write({str}) *nvim_out_write()* - Writes a message to vim output buffer - - Parameters:~ - {str} Message - -nvim_err_write({str}) *nvim_err_write()* - Writes a message to vim error buffer - - Parameters:~ - {str} Message - -nvim_err_writeln({str}) *nvim_err_writeln()* - Writes a message to vim error buffer. Appends a linefeed to - ensure all contents are written. - - Parameters:~ - {str} Message - -nvim_list_bufs() *nvim_list_bufs()* - Gets the current list of buffer handles - - Return:~ - List of buffer handles - -nvim_get_current_buf() *nvim_get_current_buf()* - Gets the current buffer - - Return:~ - Buffer handle - -nvim_set_current_buf({buffer}) *nvim_set_current_buf()* - Sets the current buffer - - Parameters:~ - {id} Buffer handle - -nvim_list_wins() *nvim_list_wins()* - Gets the current list of window handles - - Return:~ - List of window handles - -nvim_get_current_win() *nvim_get_current_win()* - Gets the current window - - Return:~ - Window handle - -nvim_set_current_win({window}) *nvim_set_current_win()* - Sets the current window - - Parameters:~ - {handle} Window handle - -nvim_list_tabpages() *nvim_list_tabpages()* - Gets the current list of tabpage handles - - Return:~ - List of tabpage handles - -nvim_get_current_tabpage() *nvim_get_current_tabpage()* - Gets the current tabpage - - Return:~ - Tabpage handle - -nvim_set_current_tabpage({tabpage}) *nvim_set_current_tabpage()* - Sets the current tabpage - - Parameters:~ - {handle} Tabpage handle - -nvim_subscribe({event}) *nvim_subscribe()* - Subscribes to event broadcasts - - Parameters:~ - {event} Event type string - -nvim_unsubscribe({event}) *nvim_unsubscribe()* - Unsubscribes to event broadcasts - - Parameters:~ - {event} Event type string - -nvim_get_color_by_name({name}) *nvim_get_color_by_name()* - TODO: Documentation - -nvim_get_color_map() *nvim_get_color_map()* - TODO: Documentation - -nvim_get_api_info() *nvim_get_api_info()* - TODO: Documentation - -nvim_call_atomic({calls}) *nvim_call_atomic()* - Call many api methods atomically - - This has two main usages: Firstly, to perform several requests - from an async context atomically, i.e. without processing - requests from other rpc clients or redrawing or allowing user - interaction in between. Note that api methods that could fire - autocommands or do event processing still might do so. For - instance invoking the :sleep command might call timer - callbacks. Secondly, it can be used to reduce rpc overhead - (roundtrips) when doing many requests in sequence. - - Parameters:~ - {calls} an array of calls, where each call is described - by an array with two elements: the request name, - and an array of arguments. - - Return:~ - an array with two elements. The first is an array of - return values. The second is NIL if all calls succeeded. - If a call resulted in an error, it is a three-element - array with the zero-based index of the call which resulted - in an error, the error type and the error message. If an - error ocurred, the values from all preceding calls will - still be returned. - - -============================================================================== -2. Buffer Functions *api-buffer* - -nvim_buf_line_count({buffer}) *nvim_buf_line_count()* - Gets the buffer line count - - Parameters:~ - {buffer} Buffer handle - - Return:~ - Line count - - *nvim_buf_get_lines()* -nvim_buf_get_lines({buffer}, {start}, {end}, {strict_indexing}) - Retrieves a line range from the buffer - - Indexing is zero-based, end-exclusive. Negative indices are - interpreted as length+1+index, i e -1 refers to the index past - the end. So to get the last element set start=-2 and end=-1. - - Out-of-bounds indices are clamped to the nearest valid value, - unless `strict_indexing` is set. - - Parameters:~ - {buffer} Buffer handle - {start} First line index - {end} Last line index (exclusive) - {strict_indexing} Whether out-of-bounds should be an - error. - - Return:~ - Array of lines - - *nvim_buf_set_lines()* -nvim_buf_set_lines({buffer}, {start}, {end}, {strict_indexing}, - {replacement}) - Replaces line range on the buffer - - Indexing is zero-based, end-exclusive. Negative indices are - interpreted as length+1+index, i e -1 refers to the index past - the end. So to change or delete the last element set start=-2 - and end=-1. - - To insert lines at a given index, set both start and end to - the same index. To delete a range of lines, set replacement to - an empty array. - - Out-of-bounds indices are clamped to the nearest valid value, - unless `strict_indexing` is set. - - Parameters:~ - {buffer} Buffer handle - {start} First line index - {end} Last line index (exclusive) - {strict_indexing} Whether out-of-bounds should be an - error. - {replacement} Array of lines to use as replacement - -nvim_buf_get_var({buffer}, {name}) *nvim_buf_get_var()* - Gets a buffer-scoped (b:) variable. - - Parameters:~ - {buffer} Buffer handle - {name} Variable name - - Return:~ - Variable value - -nvim_buf_set_var({buffer}, {name}, {value}) *nvim_buf_set_var()* - Sets a buffer-scoped (b:) variable - - Parameters:~ - {buffer} Buffer handle - {name} Variable name - {value} Variable value - -nvim_buf_del_var({buffer}, {name}) *nvim_buf_del_var()* - Removes a buffer-scoped (b:) variable - - Parameters:~ - {buffer} Buffer handle - {name} Variable name - -nvim_buf_get_option({buffer}, {name}) *nvim_buf_get_option()* - Gets a buffer option value - - Parameters:~ - {buffer} Buffer handle - {name} Option name - - Return:~ - Option value - -nvim_buf_set_option({buffer}, {name}, {value}) *nvim_buf_set_option()* - Sets a buffer option value. Passing 'nil' as value deletes the - option (only works if there's a global fallback) - - Parameters:~ - {buffer} Buffer handle - {name} Option name - {value} Option value - -nvim_buf_get_number({buffer}) *nvim_buf_get_number()* - Gets the buffer number - - Parameters:~ - {buffer} Buffer handle - - Return:~ - Buffer number - -nvim_buf_get_name({buffer}) *nvim_buf_get_name()* - Gets the full file name for the buffer - - Parameters:~ - {buffer} Buffer handle - - Return:~ - Buffer name - -nvim_buf_set_name({buffer}, {name}) *nvim_buf_set_name()* - Sets the full file name for a buffer - - Parameters:~ - {buffer} Buffer handle - {name} Buffer name - -nvim_buf_is_valid({buffer}) *nvim_buf_is_valid()* - Checks if a buffer is valid - - Parameters:~ - {buffer} Buffer handle - - Return:~ - true if the buffer is valid, false otherwise - -nvim_buf_get_mark({buffer}, {name}) *nvim_buf_get_mark()* - Return a tuple (row,col) representing the position of the - named mark - - Parameters:~ - {buffer} Buffer handle - {name} Mark name - - Return:~ - (row, col) tuple - - *nvim_buf_add_highlight()* -nvim_buf_add_highlight({buffer}, {src_id}, {hl_group}, {line}, - {col_start}, {col_end}) - Adds a highlight to buffer. - - This can be used for plugins which dynamically generate - highlights to a buffer (like a semantic highlighter or - linter). The function adds a single highlight to a buffer. - Unlike matchaddpos() highlights follow changes to line - numbering (as lines are inserted/removed above the highlighted - line), like signs and marks do. - - "src_id" is useful for batch deletion/updating of a set of - highlights. When called with src_id = 0, an unique source id - is generated and returned. Succesive calls can pass in it as - "src_id" to add new highlights to the same source group. All - highlights in the same group can then be cleared with - nvim_buf_clear_highlight. If the highlight never will be - manually deleted pass in -1 for "src_id". - - If "hl_group" is the empty string no highlight is added, but a - new src_id is still returned. This is useful for an external - plugin to synchrounously request an unique src_id at - initialization, and later asynchronously add and clear - highlights in response to buffer changes. - - Parameters:~ - {buffer} Buffer handle - {src_id} Source group to use or 0 to use a new group, - or -1 for ungrouped highlight - {hl_group} Name of the highlight group to use - {line} Line to highlight - {col_start} Start of range of columns to highlight - {col_end} End of range of columns to highlight, or -1 - to highlight to end of line - - Return:~ - The src_id that was used - - *nvim_buf_clear_highlight()* -nvim_buf_clear_highlight({buffer}, {src_id}, {line_start}, {line_end}) - Clears highlights from a given source group and a range of - lines - - To clear a source group in the entire buffer, pass in 1 and -1 - to line_start and line_end respectively. - - Parameters:~ - {buffer} Buffer handle - {src_id} Highlight source group to clear, or -1 to - clear all. - {line_start} Start of range of lines to clear - {line_end} End of range of lines to clear (exclusive) - or -1 to clear to end of file. - - -============================================================================== -3. Window Functions *api-window* - -nvim_win_get_buf({window}) *nvim_win_get_buf()* - Gets the current buffer in a window - - Parameters:~ - {window} Window handle - - Return:~ - Buffer handle - -nvim_win_get_cursor({window}) *nvim_win_get_cursor()* - Gets the cursor position in the window - - Parameters:~ - {window} Window handle - - Return:~ - (row, col) tuple - -nvim_win_set_cursor({window}, {pos}) *nvim_win_set_cursor()* - Sets the cursor position in the window - - Parameters:~ - {window} Window handle - {pos} (row, col) tuple representing the new position - -nvim_win_get_height({window}) *nvim_win_get_height()* - Gets the window height - - Parameters:~ - {window} Window handle - - Return:~ - Height as a count of rows - -nvim_win_set_height({window}, {height}) *nvim_win_set_height()* - Sets the window height. This will only succeed if the screen - is split horizontally. - - Parameters:~ - {window} Window handle - {height} Height as a count of rows - -nvim_win_get_width({window}) *nvim_win_get_width()* - Gets the window width - - Parameters:~ - {window} Window handle - - Return:~ - Width as a count of columns - -nvim_win_set_width({window}, {width}) *nvim_win_set_width()* - Sets the window width. This will only succeed if the screen is - split vertically. - - Parameters:~ - {window} Window handle - {width} Width as a count of columns - -nvim_win_get_var({window}, {name}) *nvim_win_get_var()* - Gets a window-scoped (w:) variable - - Parameters:~ - {window} Window handle - {name} Variable name - - Return:~ - Variable value - -nvim_win_set_var({window}, {name}, {value}) *nvim_win_set_var()* - Sets a window-scoped (w:) variable - - Parameters:~ - {window} Window handle - {name} Variable name - {value} Variable value - -nvim_win_del_var({window}, {name}) *nvim_win_del_var()* - Removes a window-scoped (w:) variable - - Parameters:~ - {window} Window handle - {name} Variable name - -nvim_win_get_option({window}, {name}) *nvim_win_get_option()* - Gets a window option value - - Parameters:~ - {window} Window handle - {name} Option name - - Return:~ - Option value - -nvim_win_set_option({window}, {name}, {value}) *nvim_win_set_option()* - Sets a window option value. Passing 'nil' as value deletes the - option(only works if there's a global fallback) - - Parameters:~ - {window} Window handle - {name} Option name - {value} Option value - -nvim_win_get_position({window}) *nvim_win_get_position()* - Gets the window position in display cells. First position is - zero. - - Parameters:~ - {window} Window handle - - Return:~ - (row, col) tuple with the window position - -nvim_win_get_tabpage({window}) *nvim_win_get_tabpage()* - Gets the window tabpage - - Parameters:~ - {window} Window handle - - Return:~ - Tabpage that contains the window - -nvim_win_get_number({window}) *nvim_win_get_number()* - Gets the window number - - Parameters:~ - {window} Window handle - - Return:~ - Window number - -nvim_win_is_valid({window}) *nvim_win_is_valid()* - Checks if a window is valid - - Parameters:~ - {window} Window handle - - Return:~ - true if the window is valid, false otherwise - - -============================================================================== -4. Tabpage Functions *api-tabpage* - -nvim_tabpage_list_wins({tabpage}) *nvim_tabpage_list_wins()* - Gets the windows in a tabpage - - Parameters:~ - {tabpage} Tabpage - - Return:~ - List of windows in tabpage - -nvim_tabpage_get_var({tabpage}, {name}) *nvim_tabpage_get_var()* - Gets a tab-scoped (t:) variable - - Parameters:~ - {tabpage} Tabpage handle - {name} Variable name - - Return:~ - Variable value - -nvim_tabpage_set_var({tabpage}, {name}, {value}) *nvim_tabpage_set_var()* - Sets a tab-scoped (t:) variable - - Parameters:~ - {tabpage} Tabpage handle - {name} Variable name - {value} Variable value - -nvim_tabpage_del_var({tabpage}, {name}) *nvim_tabpage_del_var()* - Removes a tab-scoped (t:) variable - - Parameters:~ - {tabpage} Tabpage handle - {name} Variable name - -nvim_tabpage_get_win({tabpage}) *nvim_tabpage_get_win()* - Gets the current window in a tabpage - - Parameters:~ - {tabpage} Tabpage handle - - Return:~ - Window handle - -nvim_tabpage_get_number({tabpage}) *nvim_tabpage_get_number()* - Gets the tabpage number - - Parameters:~ - {tabpage} Tabpage handle - - Return:~ - Tabpage number - -nvim_tabpage_is_valid({tabpage}) *nvim_tabpage_is_valid()* - Checks if a tabpage is valid - - Parameters:~ - {tabpage} Tabpage handle - - Return:~ - true if the tabpage is valid, false otherwise - - -============================================================================== -5. UI Functions *api-ui* - -remote_ui_disconnect() *remote_ui_disconnect()* - TODO: Documentation - -nvim_ui_attach({width}, {height}, {options}) *nvim_ui_attach()* - TODO: Documentation - -nvim_ui_detach() *nvim_ui_detach()* - TODO: Documentation - -nvim_ui_try_resize({width}, {height}) *nvim_ui_try_resize()* - TODO: Documentation - -nvim_ui_set_option({name}, {value}) *nvim_ui_set_option()* - TODO: Documentation - - vim:tw=78:ts=8:ft=help:norl:
\ No newline at end of file diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt index 171b0124f6..e12cd1cfa9 100644 --- a/runtime/doc/api.txt +++ b/runtime/doc/api.txt @@ -1,29 +1,20 @@ -*api.txt* {Nvim} +*api.txt* Nvim NVIM REFERENCE MANUAL by Thiago de Arruda -C API for Nvim *API* *api* +Nvim API *API* *api* -1. Introduction |api-intro| -2. API Types |api-types| -3. API metadata |api-metadata| -4. Buffer highlighting |api-highlights| +Nvim exposes a powerful API that can be used by plugins and external processes +via |msgpack-rpc|, Lua and VimL (|eval-api|). -============================================================================== -1. Introduction *api-intro* +Applications can also embed libnvim to work with the C API directly. -Nvim exposes a public API for external code to interact with the Nvim core. -The API is used by external processes to interact with Nvim using the -msgpack-rpc protocol, see |msgpack-rpc|. The API is used from vimscript to -access some new Nvim core features. See |eval-api| for how api functions are -called from vimscript. Later on, Nvim might be embeddable in C applications as -libnvim, and the application will then control the embedded instance by calling -the C API directly. + Type <M-]> to see the table of contents. ============================================================================== -2. API Types *api-types* +API Types *api-types* Nvim's C API uses custom types for all functions. Some are just typedefs around C99 standard types, and some are Nvim-defined data structures. @@ -47,7 +38,7 @@ Window -> enum value kObjectTypeWindow Tabpage -> enum value kObjectTypeTabpage ============================================================================== -3. API metadata *api-metadata* +API metadata *api-metadata* Nvim exposes API metadata as a Dictionary. Some items are described below: @@ -57,6 +48,7 @@ version.api_compatible API is backwards-compatible with this level version.api_prerelease Declares the current API level as unstable > (version.api_prerelease && fn.since == version.api_level) functions API function signatures +ui_events UI event signatures |rpc-remote-ui| {fn}.since API level where function {fn} was introduced {fn}.deprecated_since API level where function {fn} was deprecated types Custom handle types defined by Nvim @@ -65,7 +57,29 @@ error_types Possible error types returned by API functions External programs ("clients") can use the metadata to discover the |rpc-api|. ============================================================================== -4. Buffer highlighting *api-highlights* +API contract *api-contract* + +The API is made of functions and events. Clients call functions like those +described at |api-global|, and may "attach" in order to receive rich events, +described at |rpc-remote-ui|. + +As Nvim develops, its API may change only according the following "contract": + +- New functions and events may be added. + - Any such extensions are OPTIONAL: old clients may ignore them. +- Function signatures will NOT CHANGE (after release). + - Functions introduced in the development (unreleased) version MAY CHANGE. + (Clients can dynamically check `api_prerelease`, etc. |api-metadata|) +- Event parameters will not be removed or reordered (after release). +- Events may be EXTENDED: new parameters may be added. +- New items may be ADDED to map/list parameters/results of functions and + events. + - Any such new items are OPTIONAL: old clients may ignore them. + - Existing items will not be removed (after release). +- Deprecated functions will not be removed until Nvim version 2.0 + +============================================================================== +Buffer highlighting *api-highlights* Nvim allows plugins to add position-based highlights to buffers. This is similar to |matchaddpos()| but with some key differences. The added highlights @@ -112,4 +126,826 @@ An example of calling the api from vimscript: > call nvim_buf_clear_highlight(0, src, 0, -1) > ============================================================================== - vim:tw=78:ts=8:noet:ft=help:norl: +Global Functions *api-global* + +nvim_command({command}) *nvim_command()* + Executes an ex-command. On VimL error: Returns the VimL error; + v:errmsg is not updated. + + Parameters:~ + {command} Ex-command string + +nvim_feedkeys({keys}, {mode}, {escape_csi}) *nvim_feedkeys()* + Passes input keys to Nvim. On VimL error: Does not fail, but + updates v:errmsg. + + Parameters:~ + {keys} to be typed + {mode} mapping options + {escape_csi} If true, escape K_SPECIAL/CSI bytes in + `keys` + +nvim_input({keys}) *nvim_input()* + Passes keys to Nvim as raw user-input. On VimL error: Does not + fail, but updates v:errmsg. + + Unlike `nvim_feedkeys`, this uses a lower-level input buffer + and the call is not deferred. This is the most reliable way to + emulate real user input. + + Attributes:~ + {async} + + Parameters:~ + {keys} to be typed + + Return:~ + Number of bytes actually written (can be fewer than + requested if the buffer becomes full). + + *nvim_replace_termcodes()* +nvim_replace_termcodes({str}, {from_part}, {do_lt}, {special}) + Replaces terminal codes and |keycodes| (<CR>, <Esc>, ...) in a + string with the internal representation. + + Parameters:~ + {str} String to be converted. + {from_part} Legacy Vim parameter. Usually true. + {do_lt} Also translate <lt>. Ignored if `special` is + false. + {special} Replace |keycodes|, e.g. <CR> becomes a "\n" + char. + +nvim_command_output({str}) *nvim_command_output()* + TODO: Documentation + +nvim_eval({expr}) *nvim_eval()* + Evaluates a VimL expression (:help expression). Dictionaries + and Lists are recursively expanded. On VimL error: Returns a + generic error; v:errmsg is not updated. + + Parameters:~ + {expr} VimL expression string + + Return:~ + Evaluation result or expanded object + +nvim_call_function({fname}, {args}) *nvim_call_function()* + Calls a VimL function with the given arguments + + On VimL error: Returns a generic error; v:errmsg is not + updated. + + Parameters:~ + {fname} Function to call + {args} Function arguments packed in an Array + + Return:~ + Result of the function call + +nvim_execute_lua({code}, {args}) *nvim_execute_lua()* + Execute lua code. Parameters might be passed, they are + available inside the chunk as `...`. The chunk can return a + value. + + To evaluate an expression, it must be prefixed with "return ". + For instance, to call a lua function with arguments sent in + and get its return value back, use the code "return + my_function(...)". + + Parameters:~ + {code} lua code to execute + {args} Arguments to the code + + Return:~ + Return value of lua code if present or NIL. + +nvim_strwidth({str}) *nvim_strwidth()* + Calculates the number of display cells occupied by `text`. + <Tab> counts as one cell. + + Parameters:~ + {text} Some text + + Return:~ + Number of cells + +nvim_list_runtime_paths() *nvim_list_runtime_paths()* + Gets the paths contained in 'runtimepath'. + + Return:~ + List of paths + +nvim_set_current_dir({dir}) *nvim_set_current_dir()* + Changes the global working directory. + + Parameters:~ + {dir} Directory path + +nvim_get_current_line() *nvim_get_current_line()* + Gets the current line + + Parameters:~ + + Return:~ + Current line string + +nvim_set_current_line({line}) *nvim_set_current_line()* + Sets the current line + + Parameters:~ + {line} Line contents + +nvim_del_current_line() *nvim_del_current_line()* + Deletes the current line + + Parameters:~ + +nvim_get_var({name}) *nvim_get_var()* + Gets a global (g:) variable + + Parameters:~ + {name} Variable name + + Return:~ + Variable value + +nvim_set_var({name}, {value}) *nvim_set_var()* + Sets a global (g:) variable + + Parameters:~ + {name} Variable name + {value} Variable value + +nvim_del_var({name}) *nvim_del_var()* + Removes a global (g:) variable + + Parameters:~ + {name} Variable name + +nvim_get_vvar({name}) *nvim_get_vvar()* + Gets a v: variable + + Parameters:~ + {name} Variable name + + Return:~ + Variable value + +nvim_get_option({name}) *nvim_get_option()* + Gets an option value string + + Parameters:~ + {name} Option name + + Return:~ + Option value (global) + +nvim_set_option({name}, {value}) *nvim_set_option()* + Sets an option value + + Parameters:~ + {name} Option name + {value} New option value + +nvim_out_write({str}) *nvim_out_write()* + Writes a message to the Vim output buffer. Does not append + "\n", the message is buffered (won't display) until a linefeed + is written. + + Parameters:~ + {str} Message + +nvim_err_write({str}) *nvim_err_write()* + Writes a message to the Vim error buffer. Does not append + "\n", the message is buffered (won't display) until a linefeed + is written. + + Parameters:~ + {str} Message + +nvim_err_writeln({str}) *nvim_err_writeln()* + Writes a message to the Vim error buffer. Appends "\n", so the + buffer is flushed (and displayed). + + Parameters:~ + {str} Message + +nvim_list_bufs() *nvim_list_bufs()* + Gets the current list of buffer handles + + Return:~ + List of buffer handles + +nvim_get_current_buf() *nvim_get_current_buf()* + Gets the current buffer + + Return:~ + Buffer handle + +nvim_set_current_buf({buffer}) *nvim_set_current_buf()* + Sets the current buffer + + Parameters:~ + {id} Buffer handle + +nvim_list_wins() *nvim_list_wins()* + Gets the current list of window handles + + Return:~ + List of window handles + +nvim_get_current_win() *nvim_get_current_win()* + Gets the current window + + Return:~ + Window handle + +nvim_set_current_win({window}) *nvim_set_current_win()* + Sets the current window + + Parameters:~ + {handle} Window handle + +nvim_list_tabpages() *nvim_list_tabpages()* + Gets the current list of tabpage handles + + Return:~ + List of tabpage handles + +nvim_get_current_tabpage() *nvim_get_current_tabpage()* + Gets the current tabpage + + Return:~ + Tabpage handle + +nvim_set_current_tabpage({tabpage}) *nvim_set_current_tabpage()* + Sets the current tabpage + + Parameters:~ + {handle} Tabpage handle + +nvim_subscribe({event}) *nvim_subscribe()* + Subscribes to event broadcasts + + Parameters:~ + {event} Event type string + +nvim_unsubscribe({event}) *nvim_unsubscribe()* + Unsubscribes to event broadcasts + + Parameters:~ + {event} Event type string + +nvim_get_color_by_name({name}) *nvim_get_color_by_name()* + TODO: Documentation + +nvim_get_color_map() *nvim_get_color_map()* + TODO: Documentation + +nvim_get_mode() *nvim_get_mode()* + Gets the current mode. + mode: Mode string. |mode()| + blocking: true if Nvim is waiting for input. + + Attributes:~ + {async} + + Return:~ + Dictionary { "mode": String, "blocking": Boolean } + +nvim_get_keymap({mode}) *nvim_get_keymap()* + Get a list of dictionaries describing global (i.e. non-buffer) + mappings Note that the "buffer" key will be 0 to represent + false. + + Parameters:~ + {mode} The abbreviation for the mode + + Return:~ + An array of maparg() like dictionaries describing mappings + +nvim_get_api_info() *nvim_get_api_info()* + TODO: Documentation + + Attributes:~ + {async} + +nvim_call_atomic({calls}) *nvim_call_atomic()* + Call many api methods atomically + + This has two main usages: Firstly, to perform several requests + from an async context atomically, i.e. without processing + requests from other rpc clients or redrawing or allowing user + interaction in between. Note that api methods that could fire + autocommands or do event processing still might do so. For + instance invoking the :sleep command might call timer + callbacks. Secondly, it can be used to reduce rpc overhead + (roundtrips) when doing many requests in sequence. + + Parameters:~ + {calls} an array of calls, where each call is described + by an array with two elements: the request name, + and an array of arguments. + + Return:~ + an array with two elements. The first is an array of + return values. The second is NIL if all calls succeeded. + If a call resulted in an error, it is a three-element + array with the zero-based index of the call which resulted + in an error, the error type and the error message. If an + error ocurred, the values from all preceding calls will + still be returned. + +nvim__id({obj}) *nvim__id()* + Returns object given as argument + + This API function is used for testing. One should not rely on + its presence in plugins. + + Parameters:~ + {obj} Object to return. + + Return:~ + its argument. + +nvim__id_array({arr}) *nvim__id_array()* + Returns array given as argument + + This API function is used for testing. One should not rely on + its presence in plugins. + + Parameters:~ + {arr} Array to return. + + Return:~ + its argument. + +nvim__id_dictionary({dct}) *nvim__id_dictionary()* + Returns dictionary given as argument + + This API function is used for testing. One should not rely on + its presence in plugins. + + Parameters:~ + {dct} Dictionary to return. + + Return:~ + its argument. + +nvim__id_float({flt}) *nvim__id_float()* + Returns floating-point value given as argument + + This API function is used for testing. One should not rely on + its presence in plugins. + + Parameters:~ + {flt} Value to return. + + Return:~ + its argument. + + +============================================================================== +Buffer Functions *api-buffer* + +nvim_buf_line_count({buffer}) *nvim_buf_line_count()* + Gets the buffer line count + + Parameters:~ + {buffer} Buffer handle + + Return:~ + Line count + + *nvim_buf_get_lines()* +nvim_buf_get_lines({buffer}, {start}, {end}, {strict_indexing}) + Retrieves a line range from the buffer + + Indexing is zero-based, end-exclusive. Negative indices are + interpreted as length+1+index, i e -1 refers to the index past + the end. So to get the last element set start=-2 and end=-1. + + Out-of-bounds indices are clamped to the nearest valid value, + unless `strict_indexing` is set. + + Parameters:~ + {buffer} Buffer handle + {start} First line index + {end} Last line index (exclusive) + {strict_indexing} Whether out-of-bounds should be an + error. + + Return:~ + Array of lines + + *nvim_buf_set_lines()* +nvim_buf_set_lines({buffer}, {start}, {end}, {strict_indexing}, + {replacement}) + Replaces line range on the buffer + + Indexing is zero-based, end-exclusive. Negative indices are + interpreted as length+1+index, i e -1 refers to the index past + the end. So to change or delete the last element set start=-2 + and end=-1. + + To insert lines at a given index, set both start and end to + the same index. To delete a range of lines, set replacement to + an empty array. + + Out-of-bounds indices are clamped to the nearest valid value, + unless `strict_indexing` is set. + + Parameters:~ + {buffer} Buffer handle + {start} First line index + {end} Last line index (exclusive) + {strict_indexing} Whether out-of-bounds should be an + error. + {replacement} Array of lines to use as replacement + +nvim_buf_get_var({buffer}, {name}) *nvim_buf_get_var()* + Gets a buffer-scoped (b:) variable. + + Parameters:~ + {buffer} Buffer handle + {name} Variable name + + Return:~ + Variable value + +nvim_buf_get_changedtick({buffer}) *nvim_buf_get_changedtick()* + Gets a changed tick of a buffer + + Parameters:~ + {buffer} Buffer handle. + + Return:~ + b:changedtickvalue. + +nvim_buf_get_keymap({buffer}, {mode}) *nvim_buf_get_keymap()* + Get a list of dictionaries describing buffer-local mappings + Note that the buffer key in the dictionary will represent the + buffer handle where the mapping is present + + Parameters:~ + {mode} The abbreviation for the mode + {buffer_id} Buffer handle + + Return:~ + An array of maparg() like dictionaries describing mappings + +nvim_buf_set_var({buffer}, {name}, {value}) *nvim_buf_set_var()* + Sets a buffer-scoped (b:) variable + + Parameters:~ + {buffer} Buffer handle + {name} Variable name + {value} Variable value + +nvim_buf_del_var({buffer}, {name}) *nvim_buf_del_var()* + Removes a buffer-scoped (b:) variable + + Parameters:~ + {buffer} Buffer handle + {name} Variable name + +nvim_buf_get_option({buffer}, {name}) *nvim_buf_get_option()* + Gets a buffer option value + + Parameters:~ + {buffer} Buffer handle + {name} Option name + + Return:~ + Option value + +nvim_buf_set_option({buffer}, {name}, {value}) *nvim_buf_set_option()* + Sets a buffer option value. Passing 'nil' as value deletes the + option (only works if there's a global fallback) + + Parameters:~ + {buffer} Buffer handle + {name} Option name + {value} Option value + +nvim_buf_get_name({buffer}) *nvim_buf_get_name()* + Gets the full file name for the buffer + + Parameters:~ + {buffer} Buffer handle + + Return:~ + Buffer name + +nvim_buf_set_name({buffer}, {name}) *nvim_buf_set_name()* + Sets the full file name for a buffer + + Parameters:~ + {buffer} Buffer handle + {name} Buffer name + +nvim_buf_is_valid({buffer}) *nvim_buf_is_valid()* + Checks if a buffer is valid + + Parameters:~ + {buffer} Buffer handle + + Return:~ + true if the buffer is valid, false otherwise + +nvim_buf_get_mark({buffer}, {name}) *nvim_buf_get_mark()* + Return a tuple (row,col) representing the position of the + named mark + + Parameters:~ + {buffer} Buffer handle + {name} Mark name + + Return:~ + (row, col) tuple + + *nvim_buf_add_highlight()* +nvim_buf_add_highlight({buffer}, {src_id}, {hl_group}, {line}, + {col_start}, {col_end}) + Adds a highlight to buffer. + + This can be used for plugins which dynamically generate + highlights to a buffer (like a semantic highlighter or + linter). The function adds a single highlight to a buffer. + Unlike matchaddpos() highlights follow changes to line + numbering (as lines are inserted/removed above the highlighted + line), like signs and marks do. + + "src_id" is useful for batch deletion/updating of a set of + highlights. When called with src_id = 0, an unique source id + is generated and returned. Succesive calls can pass in it as + "src_id" to add new highlights to the same source group. All + highlights in the same group can then be cleared with + nvim_buf_clear_highlight. If the highlight never will be + manually deleted pass in -1 for "src_id". + + If "hl_group" is the empty string no highlight is added, but a + new src_id is still returned. This is useful for an external + plugin to synchrounously request an unique src_id at + initialization, and later asynchronously add and clear + highlights in response to buffer changes. + + Parameters:~ + {buffer} Buffer handle + {src_id} Source group to use or 0 to use a new group, + or -1 for ungrouped highlight + {hl_group} Name of the highlight group to use + {line} Line to highlight + {col_start} Start of range of columns to highlight + {col_end} End of range of columns to highlight, or -1 + to highlight to end of line + + Return:~ + The src_id that was used + + *nvim_buf_clear_highlight()* +nvim_buf_clear_highlight({buffer}, {src_id}, {line_start}, {line_end}) + Clears highlights from a given source group and a range of + lines + + To clear a source group in the entire buffer, pass in 1 and -1 + to line_start and line_end respectively. + + Parameters:~ + {buffer} Buffer handle + {src_id} Highlight source group to clear, or -1 to + clear all. + {line_start} Start of range of lines to clear + {line_end} End of range of lines to clear (exclusive) + or -1 to clear to end of file. + + +============================================================================== +Window Functions *api-window* + +nvim_win_get_buf({window}) *nvim_win_get_buf()* + Gets the current buffer in a window + + Parameters:~ + {window} Window handle + + Return:~ + Buffer handle + +nvim_win_get_cursor({window}) *nvim_win_get_cursor()* + Gets the cursor position in the window + + Parameters:~ + {window} Window handle + + Return:~ + (row, col) tuple + +nvim_win_set_cursor({window}, {pos}) *nvim_win_set_cursor()* + Sets the cursor position in the window + + Parameters:~ + {window} Window handle + {pos} (row, col) tuple representing the new position + +nvim_win_get_height({window}) *nvim_win_get_height()* + Gets the window height + + Parameters:~ + {window} Window handle + + Return:~ + Height as a count of rows + +nvim_win_set_height({window}, {height}) *nvim_win_set_height()* + Sets the window height. This will only succeed if the screen + is split horizontally. + + Parameters:~ + {window} Window handle + {height} Height as a count of rows + +nvim_win_get_width({window}) *nvim_win_get_width()* + Gets the window width + + Parameters:~ + {window} Window handle + + Return:~ + Width as a count of columns + +nvim_win_set_width({window}, {width}) *nvim_win_set_width()* + Sets the window width. This will only succeed if the screen is + split vertically. + + Parameters:~ + {window} Window handle + {width} Width as a count of columns + +nvim_win_get_var({window}, {name}) *nvim_win_get_var()* + Gets a window-scoped (w:) variable + + Parameters:~ + {window} Window handle + {name} Variable name + + Return:~ + Variable value + +nvim_win_set_var({window}, {name}, {value}) *nvim_win_set_var()* + Sets a window-scoped (w:) variable + + Parameters:~ + {window} Window handle + {name} Variable name + {value} Variable value + +nvim_win_del_var({window}, {name}) *nvim_win_del_var()* + Removes a window-scoped (w:) variable + + Parameters:~ + {window} Window handle + {name} Variable name + +nvim_win_get_option({window}, {name}) *nvim_win_get_option()* + Gets a window option value + + Parameters:~ + {window} Window handle + {name} Option name + + Return:~ + Option value + +nvim_win_set_option({window}, {name}, {value}) *nvim_win_set_option()* + Sets a window option value. Passing 'nil' as value deletes the + option(only works if there's a global fallback) + + Parameters:~ + {window} Window handle + {name} Option name + {value} Option value + +nvim_win_get_position({window}) *nvim_win_get_position()* + Gets the window position in display cells. First position is + zero. + + Parameters:~ + {window} Window handle + + Return:~ + (row, col) tuple with the window position + +nvim_win_get_tabpage({window}) *nvim_win_get_tabpage()* + Gets the window tabpage + + Parameters:~ + {window} Window handle + + Return:~ + Tabpage that contains the window + +nvim_win_get_number({window}) *nvim_win_get_number()* + Gets the window number + + Parameters:~ + {window} Window handle + + Return:~ + Window number + +nvim_win_is_valid({window}) *nvim_win_is_valid()* + Checks if a window is valid + + Parameters:~ + {window} Window handle + + Return:~ + true if the window is valid, false otherwise + + +============================================================================== +Tabpage Functions *api-tabpage* + +nvim_tabpage_list_wins({tabpage}) *nvim_tabpage_list_wins()* + Gets the windows in a tabpage + + Parameters:~ + {tabpage} Tabpage + + Return:~ + List of windows in tabpage + +nvim_tabpage_get_var({tabpage}, {name}) *nvim_tabpage_get_var()* + Gets a tab-scoped (t:) variable + + Parameters:~ + {tabpage} Tabpage handle + {name} Variable name + + Return:~ + Variable value + +nvim_tabpage_set_var({tabpage}, {name}, {value}) *nvim_tabpage_set_var()* + Sets a tab-scoped (t:) variable + + Parameters:~ + {tabpage} Tabpage handle + {name} Variable name + {value} Variable value + +nvim_tabpage_del_var({tabpage}, {name}) *nvim_tabpage_del_var()* + Removes a tab-scoped (t:) variable + + Parameters:~ + {tabpage} Tabpage handle + {name} Variable name + +nvim_tabpage_get_win({tabpage}) *nvim_tabpage_get_win()* + Gets the current window in a tabpage + + Parameters:~ + {tabpage} Tabpage handle + + Return:~ + Window handle + +nvim_tabpage_get_number({tabpage}) *nvim_tabpage_get_number()* + Gets the tabpage number + + Parameters:~ + {tabpage} Tabpage handle + + Return:~ + Tabpage number + +nvim_tabpage_is_valid({tabpage}) *nvim_tabpage_is_valid()* + Checks if a tabpage is valid + + Parameters:~ + {tabpage} Tabpage handle + + Return:~ + true if the tabpage is valid, false otherwise + + +============================================================================== +UI Functions *api-ui* + +remote_ui_disconnect() *remote_ui_disconnect()* + TODO: Documentation + +nvim_ui_attach({width}, {height}, {options}) *nvim_ui_attach()* + TODO: Documentation + +nvim_ui_detach() *nvim_ui_detach()* + TODO: Documentation + +nvim_ui_try_resize({width}, {height}) *nvim_ui_try_resize()* + TODO: Documentation + +nvim_ui_set_option({name}, {value}) *nvim_ui_set_option()* + TODO: Documentation + + vim:tw=78:ts=8:ft=help:norl: diff --git a/runtime/doc/arabic.txt b/runtime/doc/arabic.txt index 6f17b38a7a..3f30d7b5bc 100644 --- a/runtime/doc/arabic.txt +++ b/runtime/doc/arabic.txt @@ -1,4 +1,4 @@ -*arabic.txt* For Vim version 7.4. Last change: 2010 Nov 13 +*arabic.txt* Nvim VIM REFERENCE MANUAL by Nadim Shaikli diff --git a/runtime/doc/autocmd.txt b/runtime/doc/autocmd.txt index 090c216fcb..fd2a7c2641 100644 --- a/runtime/doc/autocmd.txt +++ b/runtime/doc/autocmd.txt @@ -1,4 +1,4 @@ -*autocmd.txt* For Vim version 7.4. Last change: 2016 Jun 09 +*autocmd.txt* Nvim VIM REFERENCE MANUAL by Bram Moolenaar @@ -8,17 +8,7 @@ Automatic commands *autocommand* For a basic explanation, see section |40.3| in the user manual. -1. Introduction |autocmd-intro| -2. Defining autocommands |autocmd-define| -3. Removing autocommands |autocmd-remove| -4. Listing autocommands |autocmd-list| -5. Events |autocmd-events| -6. Patterns |autocmd-patterns| -7. Buffer-local autocommands |autocmd-buflocal| -8. Groups |autocmd-groups| -9. Executing autocommands |autocmd-execute| -10. Using autocommands |autocmd-use| -11. Disabling autocommands |autocmd-disable| + Type <M-]> to see the table of contents. ============================================================================== 1. Introduction *autocmd-intro* @@ -30,7 +20,7 @@ files matching *.c. You can also use autocommands to implement advanced features, such as editing compressed files (see |gzip-example|). The usual place to put autocommands is in your vimrc file. - *E203* *E204* *E143* *E855* + *E203* *E204* *E143* *E855* *E937* WARNING: Using autocommands is very powerful, and may lead to unexpected side effects. Be careful not to destroy your text. - It's a good idea to do some testing on an expendable copy of a file first. @@ -76,11 +66,15 @@ exception is that "<sfile>" is expanded when the autocmd is defined. Example: Here Vim expands <sfile> to the name of the file containing this line. -When your vimrc file is sourced twice, the autocommands will appear twice. -To avoid this, put this command in your vimrc file, before defining -autocommands: > +`:autocmd` adds to the list of autocommands regardless of whether they are +already present. When your .vimrc file is sourced twice, the autocommands +will appear twice. To avoid this, define your autocommands in a group, so +that you can easily clear them: > - :autocmd! " Remove ALL autocommands for the current group. + augroup vimrc + autocmd! " Remove all vimrc autocommands + au BufNewFile,BufRead *.html so <sfile>:h/html.vim + augroup END If you don't want to remove all autocommands, you can instead use a variable to ensure that Vim includes the autocommands only once: > @@ -127,8 +121,13 @@ prompt. When one command outputs two messages this can happen anyway. :au[tocmd]! [group] {event} Remove ALL autocommands for {event}. + Warning: You should not do this without a group for + |BufRead| and other common events, it can break + plugins, syntax highlighting, etc. :au[tocmd]! [group] Remove ALL autocommands. + Warning: You should normally not do this without a + group, it breaks plugins, syntax highlighting, etc. When the [group] argument is not given, Vim uses the current group (as defined with ":augroup"); otherwise, Vim uses the group defined with [group]. @@ -273,8 +272,10 @@ Name triggered by ~ |VimLeave| before exiting Vim, after writing the shada file Various +|DirChanged| after the |current-directory| was changed + |FileChangedShell| Vim notices that a file changed since editing started -|FileChangedShellPost| After handling a file changed since editing started +|FileChangedShellPost| after handling a file changed since editing started |FileChangedRO| before making the first change to a read-only file |ShellCmdPost| after executing a shell command @@ -294,6 +295,7 @@ Name triggered by ~ |CursorMoved| the cursor was moved in Normal mode |CursorMovedI| the cursor was moved in Insert mode +|WinNew| after creating a new window |WinEnter| after entering another window |WinLeave| before leaving a window |TabEnter| after entering another tab page @@ -419,8 +421,8 @@ BufUnload Before unloading a buffer. This is when the NOTE: When this autocommand is executed, the current buffer "%" may be different from the buffer being unloaded "<afile>". - Don't change to another buffer, it will cause - problems. + Don't change to another buffer or window, it + will cause problems! When exiting and v:dying is 2 or more this event is not triggered. *BufWinEnter* @@ -562,6 +564,12 @@ CursorMoved After the cursor was moved in Normal or Visual CursorMovedI After the cursor was moved in Insert mode. Not triggered when the popup menu is visible. Otherwise the same as CursorMoved. + *DirChanged* +DirChanged After the |current-directory| was changed. + Sets these |v:event| keys: + cwd: current working directory + scope: "global", "tab", "window" + Recursion is ignored. *FileAppendCmd* FileAppendCmd Before appending to a file. Should do the appending to the file. Use the '[ and '] @@ -726,13 +734,12 @@ InsertCharPre When a character is typed in Insert mode, *TextYankPost* TextYankPost Just after a |yank| or |deleting| command, but not if the black hole register |quote_| is used nor - for |setreg()|. Pattern must be * because its - meaning may change in the future. + for |setreg()|. Pattern must be *. Sets these |v:event| keys: - operator - regcontents - regname - regtype + operator + regcontents + regname + regtype Recursion is ignored. It is not allowed to change the text |textlock|. *InsertEnter* @@ -786,7 +793,9 @@ QuickFixCmdPre Before a quickfix command is run (|:make|, |:vimgrepadd|, |:lvimgrepadd|, |:cscope|, |:cfile|, |:cgetfile|, |:caddfile|, |:lfile|, |:lgetfile|, |:laddfile|, |:helpgrep|, - |:lhelpgrep|). + |:lhelpgrep|, |:cexpr|, |:cgetexpr|, + |:caddexpr|, |:cbuffer|, |:cgetbuffer|, + |:caddbuffer|). The pattern is matched against the command being run. When |:grep| is used but 'grepprg' is set to "internal" it still matches "grep". @@ -911,7 +920,7 @@ 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 - setting buffer variables. |terminal-emulator| + setting buffer variables. |terminal| *TermResponse* TermResponse After the response to |t_RV| is received from the terminal. The value of |v:termresponse| @@ -958,9 +967,9 @@ VimEnter After doing all the startup stuff, including VimLeave Before exiting Vim, just after writing the .shada file. Executed only once, like VimLeavePre. - To detect an abnormal exit use |v:dying|. - When v:dying is 2 or more this event is not - triggered. +< Use |v:dying| to detect an abnormal exit. + Use |v:exiting| to get the exit code. + Not triggered if |v:dying| is 2 or more. *VimLeavePre* VimLeavePre Before exiting Vim, just before writing the .shada file. This is executed only once, @@ -968,9 +977,9 @@ VimLeavePre Before exiting Vim, just before writing the happens to be the current buffer when exiting. Mostly useful with a "*" pattern. > :autocmd VimLeavePre * call CleanupStuff() -< To detect an abnormal exit use |v:dying|. - When v:dying is 2 or more this event is not - triggered. +< Use |v:dying| to detect an abnormal exit. + Use |v:exiting| to get the exit code. + Not triggered if |v:dying| is 2 or more. *VimResized* VimResized After the Vim window was resized, thus 'lines' and/or 'columns' changed. Not when starting @@ -992,6 +1001,11 @@ WinLeave Before leaving a window. If the window to be WinLeave autocommands (but not for ":new"). Not used for ":qa" or ":q" when exiting Vim. + *WinNew* +WinNew When a new window was created. Not done for + the first window, when Vim has just started. + Before a WinEnter event. + ============================================================================== 6. Patterns *autocmd-patterns* *{pat}* @@ -1073,6 +1087,9 @@ Note that for all systems the '/' character is used for path separator (even Windows). This was done because the backslash is difficult to use in a pattern and to make the autocommands portable across different systems. +It is possible to use |pattern| items, but they may not work as expected, +because of the translation done for the above. + *autocmd-changes* Matching with the pattern is done when an event is triggered. Changing the buffer name in one of the autocommands, or even deleting the buffer, does not @@ -1171,10 +1188,12 @@ name! different from existing {event} names, as this most likely will not do what you intended. - *:augroup-delete* *E367* + *:augroup-delete* *E367* *W19* *E936* :aug[roup]! {name} Delete the autocmd group {name}. Don't use this if there is still an autocommand using - this group! This is not checked. + this group! You will get a warning if doing + it anyway. when the group is the current group + you will get error E936. To enter autocommands for a specific group, use this method: 1. Select the group with ":augroup {name}". diff --git a/runtime/doc/change.txt b/runtime/doc/change.txt index 31a46f53bb..f82d61370c 100644 --- a/runtime/doc/change.txt +++ b/runtime/doc/change.txt @@ -1,4 +1,4 @@ -*change.txt* For Vim version 7.4. Last change: 2016 Apr 12 +*change.txt* Nvim VIM REFERENCE MANUAL by Bram Moolenaar @@ -9,20 +9,10 @@ changing text means deleting the text and replacing it with other text using one command. You can undo all of these commands. You can repeat the non-Ex commands with the "." command. -1. Deleting text |deleting| -2. Delete and insert |delete-insert| -3. Simple changes |simple-change| *changing* -4. Complex changes |complex-change| - 4.1 Filter commands |filter| - 4.2 Substitute |:substitute| - 4.3 Search and replace |search-replace| - 4.4 Changing tabs |change-tabs| -5. Copying and moving text |copy-move| -6. Formatting text |formatting| -7. Sorting text |sorting| - For inserting text see |insert.txt|. + Type <M-]> to see the table of contents. + ============================================================================== 1. Deleting text *deleting* *E470* @@ -259,7 +249,7 @@ Or use "caw" (see |aw|). command is executed. ============================================================================== -3. Simple changes *simple-change* +3. Simple changes *simple-change* *changing* *r* r{char} Replace the character under the cursor with {char}. @@ -398,11 +388,6 @@ CTRL-X Subtract [count] from the number or alphabetic {Visual}CTRL-X Subtract [count] from the number or alphabetic character in the highlighted text. {not in Vi} - On MS-Windows, this is mapped to cut Visual text - |dos-standard-mappings|. If you want to disable the - mapping, use this: > - silent! vunmap <C-X> -< *v_g_CTRL-X* {Visual}g CTRL-X Subtract [count] from the number or alphabetic character in the highlighted text. If several lines @@ -601,8 +586,8 @@ all files in it are deleted. When Vim has the setuid bit set this may cause problems, the temp file is owned by the setuid user but the filter command probably runs as the original user. Directory for temporary files is created in the first suitable directory of: -For Unix: $TMPDIR, /tmp, current-dir, $HOME. -For MS-Windows: $TMP, $TEMP, $USERPROFILE, current-dir. + Unix: $TMPDIR, /tmp, current-dir, $HOME. + Windows: $TMPDIR, $TMP, $TEMP, $USERPROFILE, current-dir. @@ -614,12 +599,14 @@ For MS-Windows: $TMP, $TEMP, $USERPROFILE, current-dir. For the {pattern} see |pattern|. {string} can be a literal string, or something special; see |sub-replace-special|. + *E939* When [range] and [count] are omitted, replace in the - current line only. - When [count] is given, replace in [count] lines, - starting with the last line in [range]. When [range] - is omitted start in the current line. - Also see |cmdline-ranges|. + current line only. When [count] is given, replace in + [count] lines, starting with the last line in [range]. + When [range] is omitted start in the current line. + [count] must be a positive number. Also see + |cmdline-ranges|. + See |:s_flags| for [flags]. :[range]s[ubstitute] [flags] [count] @@ -833,6 +820,7 @@ The numbering of "\1", "\2" etc. is done based on which "\(" comes first in the pattern (going left to right). When a parentheses group matches several times, the last one will be used for "\1", "\2", etc. Example: > :s/\(\(a[a-d] \)*\)/\2/ modifies "aa ab x" to "ab x" +The "\2" is for "\(a[a-d] \)". At first it matches "aa ", secondly "ab ". When using parentheses in combination with '|', like in \([ab]\)\|\([cd]\), either the first or second pattern in parentheses did not match, so either @@ -873,8 +861,7 @@ Exceptions: Substitute with an expression *sub-replace-expression* *sub-replace-\=* *s/\=* When the substitute string starts with "\=" the remainder is interpreted as an -expression. This does not work recursively: a |substitute()| function inside -the expression cannot use "\=" for the substitute string. +expression. The special meaning for characters as mentioned at |sub-replace-special| does not apply except for "<CR>". A <NL> character is used as a line break, you diff --git a/runtime/doc/cmdline.txt b/runtime/doc/cmdline.txt index a123ea711b..652487d8ab 100644 --- a/runtime/doc/cmdline.txt +++ b/runtime/doc/cmdline.txt @@ -1,4 +1,4 @@ -*cmdline.txt* For Vim version 7.4. Last change: 2015 Dec 17 +*cmdline.txt* Nvim VIM REFERENCE MANUAL by Bram Moolenaar @@ -13,13 +13,7 @@ Command-line mode is used to enter Ex commands (":"), search patterns Basic command line editing is explained in chapter 20 of the user manual |usr_20.txt|. -1. Command-line editing |cmdline-editing| -2. Command-line completion |cmdline-completion| -3. Ex command-lines |cmdline-lines| -4. Ex command-line ranges |cmdline-ranges| -5. Ex command-line flags |ex-flags| -6. Ex special characters |cmdline-special| -7. Command-line window |cmdline-window| + Type <M-]> to see the table of contents. ============================================================================== 1. Command-line editing *cmdline-editing* @@ -219,9 +213,10 @@ CTRL-Y When there is a modeless selection, copy the selection into the clipboard. |modeless-selection| If there is no selection CTRL-Y is inserted as a character. -CTRL-J *c_CTRL-J* *c_<NL>* *c_<CR>* *c_CR* +CTRL-M or CTRL-J *c_CTRL-M* *c_CTRL-J* *c_<NL>* *c_<CR>* *c_CR* <CR> or <NL> start entered command - *c_<Esc>* *c_Esc* + +CTRL-[ *c_CTRL-[* *c_<Esc>* *c_Esc* <Esc> When typed and 'x' not present in 'cpoptions', quit Command-line mode without executing. In macros or when 'x' present in 'cpoptions', start entered command. @@ -332,8 +327,11 @@ terminals) List entries 6 to 12 from the search history: > :history / 6,12 < - List the recent five entries from all histories: > - :history all -5, + List the penultimate entry from all histories: > + :history all -2 +< + List the most recent two entries from all histories: > + :history all -2, :keepp[atterns] {command} *:keepp* *:keeppatterns* Execute {command}, without adding anything to the search @@ -394,12 +392,26 @@ CTRL-L A match is done on the pattern in front of the cursor. If If there are multiple matches the longest common part is inserted in place of the pattern. If the result is shorter than the pattern, no completion is done. + */_CTRL-L* When 'incsearch' is set, entering a search pattern for "/" or "?" and the current match is displayed then CTRL-L will add one character from the end of the current match. If 'ignorecase' and 'smartcase' are set and the command line has no uppercase characters, the added character is converted to lowercase. + *c_CTRL-G* */_CTRL-G* +CTRL-G When 'incsearch' is set, entering a search pattern for "/" or + "?" and the current match is displayed then CTRL-G will move + to the next match (does not take |search-offset| into account) + Use CTRL-T to move to the previous match. Hint: on a regular + keyboard T is above G. + *c_CTRL-T* */_CTRL-T* +CTRL-T When 'incsearch' is set, entering a search pattern for "/" or + "?" and the current match is displayed then CTRL-T will move + to the previous match (does not take |search-offset| into + account). + Use CTRL-G to move to the next match. Hint: on a regular + keyboard T is above G. The 'wildchar' option defaults to <Tab> (CTRL-E when in Vi compatible mode; in a previous version <Esc> was used). In the pattern standard wildcards '*' and @@ -999,10 +1011,10 @@ There are several ways to leave the command-line window: Insert and in Normal mode. CTRL-C Continue in Command-line mode. The command-line under the cursor is used as the command-line. Works both in Insert and - in Normal mode. ":close" also works. There is no redraw, - thus the window will remain visible. + in Normal mode. There is no redraw, thus the window will + remain visible. :quit Discard the command line and go back to Normal mode. - ":exit", ":xit" and CTRL-\ CTRL-N also work. + ":close", ":exit", ":xit" and CTRL-\ CTRL-N also work. :qall Quit Vim, unless there are changes in some buffer. :qall! Quit Vim, discarding changes to any buffer. diff --git a/runtime/doc/debug.txt b/runtime/doc/debug.txt index f03116ffed..fd2c4fa54e 100644 --- a/runtime/doc/debug.txt +++ b/runtime/doc/debug.txt @@ -1,4 +1,4 @@ -*debug.txt* For Vim version 7.4. Last change: 2012 Feb 11 +*debug.txt* Nvim VIM REFERENCE MANUAL by Bram Moolenaar @@ -9,9 +9,7 @@ Debugging Vim *debug-vim* This is for debugging Vim itself, when it doesn't work properly. For debugging Vim scripts, functions, etc. see |debug-scripts| -1. Location of a crash, using gcc and gdb |debug-gcc| -2. Locating memory leaks |debug-leaks| -3. Windows Bug Reporting |debug-win32| + Type <M-]> to see the table of contents. ============================================================================== diff --git a/runtime/doc/deprecated.txt b/runtime/doc/deprecated.txt index 6997d331e4..b3e2f7a92f 100644 --- a/runtime/doc/deprecated.txt +++ b/runtime/doc/deprecated.txt @@ -1,4 +1,4 @@ -*deprecated.txt* {Nvim} +*deprecated.txt* Nvim NVIM REFERENCE MANUAL @@ -16,20 +16,19 @@ Normal commands ~ *]f* *[f* Same as "gf". - Commands ~ *:rv* *:rviminfo* Deprecated alias to |:rshada| command. *:wv* *:wviminfo* Deprecated alias to |:wshada| command. - Events ~ *EncodingChanged* Never fired; 'encoding' is always "utf-8". *FileEncoding* Never fired; equivalent to |EncodingChanged|. -Highlight groups ~ -*hl-VisualNOS* Obsolete. |vim-differences| {Nvim} +Keycodes ~ +*<MouseDown>* Use <ScrollWheelUp> instead. +*<MouseUp>* Use <ScrollWheelDown> instead. Functions ~ *buffer_exists()* Obsolete name for |bufexists()|. @@ -40,9 +39,16 @@ Functions ~ *highlightID()* Obsolete name for |hlID()|. *last_buffer_nr()* Obsolete name for bufnr("$"). +Modifiers ~ +*:menu-<special>* +*:menu-special* <> notation is always enabled. |cpo-<| +*:map-<special>* +*:map-special* <> notation is always enabled. |cpo-<| + Options ~ *'fe'* 'fenc'+'enc' before Vim 6.0; no longer used. +*'langnoremap'* Deprecated alias to 'nolangremap'. *'vi'* *'viminfo'* Deprecated alias to 'shada' option. - vim:tw=78:ts=8:ft=help:norl: + vim:noet:tw=78:ts=8:ft=help:norl: diff --git a/runtime/doc/develop.txt b/runtime/doc/develop.txt index b738da9bec..5d5523e73f 100644 --- a/runtime/doc/develop.txt +++ b/runtime/doc/develop.txt @@ -1,4 +1,4 @@ -*develop.txt* +*develop.txt* Nvim NVIM REFERENCE MANUAL @@ -6,22 +6,19 @@ Development of Nvim. *development* -1. Design goals |design-goals| -2. Design decisions |design-decisions| - Nvim is open source software. Everybody is encouraged to contribute. https://github.com/neovim/neovim/blob/master/CONTRIBUTING.md -See src/nvim/README.md for a high-level overview of the source code: - https://github.com/neovim/neovim/blob/master/src/nvim/README.md +See src/nvim/README.md for an overview of the source code. + + Type <M-]> to see the table of contents. ============================================================================== -1. Design goals *design-goals* +Design goals *design-goals* Most important things come first (roughly). -Note that quite a few items are contradicting. This is intentional. A -balance must be found between them. +Note that some items conflict; this is intentional. A balance must be found. NVIM IS... IMPROVED *design-improved* @@ -41,7 +38,7 @@ completely different editor. Extensions are done with a "Vi spirit". - There are many first-time and inexperienced Vim users. Make it easy for them to start using Vim and learn more over time. - There is no limit to the features that can be added. Selecting new features - is one based on (1) what users ask for, (2) how much effort it takes to + is based on (1) what users ask for, (2) how much effort it takes to implement and (3) someone actually implementing it. @@ -56,33 +53,21 @@ Vim tries to help as many users on as many platforms as possible. - Support many compilers and libraries. Not everybody is able or allowed to install another compiler or GUI library. - People switch from one platform to another, and from GUI to terminal - version. Features should be present in all versions, or at least in as many - as possible with a reasonable effort. Try to avoid that users must switch - between platforms to accomplish their work efficiently. -- That a feature is not possible on some platforms, or only possible on one - platform, does not mean it cannot be implemented. [This intentionally - contradicts the previous item, these two must be balanced.] + version. Features should be present in all versions. NVIM IS... WELL DOCUMENTED *design-documented* - A feature that isn't documented is a useless feature. A patch for a new feature must include the documentation. -- Documentation should be comprehensive and understandable. Using examples is - recommended. +- Documentation should be comprehensive and understandable. Use examples. - Don't make the text unnecessarily long. Less documentation means that an item is easier to find. -- Do not prefix doc-tags with "nvim-". Use |vim_diff.txt| to document - differences from Vim. The {Nvim} annotation is also available - to mark a specific feature. No other distinction is necessary. -- If a feature is removed, delete its doc entry and move its tag to - |vim_diff.txt|. NVIM IS... HIGH SPEED AND SMALL IN SIZE *design-speed-size* -Using Vim must not be a big attack on system resources. Keep it small and -fast. +Keep Nvim small and fast. - Computers are becoming faster and bigger each year. Vim can grow too, but no faster than computers are growing. Keep Vim usable on older systems. - Many users start Vim from a shell very often. Startup time must be short. @@ -118,13 +103,14 @@ 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 -include the kitchen sink... but you can use it for plumbing." +include the kitchen sink... but it's good for plumbing." ============================================================================== -2. Design decisions *design-decisions* +Developer guidelines *dev* -JARGON *dev-jargon* + +JARGON *dev-jargon* API client ~ All external UIs and remote plugins (as opposed to regular Vim plugins) are @@ -150,15 +136,14 @@ the xterm window, a window inside Vim to view a buffer. To avoid confusion, other items that are sometimes called window have been given another name. Here is an overview of the related items: -screen The whole display. For the GUI it's something like 1024x768 - pixels. The Vim shell can use the whole screen or part of it. +screen The whole display. shell The Vim application. This can cover the whole screen (e.g., when running in a console) or part of it (xterm or GUI). window View on a buffer. There can be several windows in Vim, together with the command line, menubar, toolbar, etc. they fit in the shell. -PROVIDERS *dev-provider* +PROVIDERS *dev-provider* A goal of Nvim is to allow extension of the editor without special knowledge in the core. But some Vim components are too tightly coupled; in those cases @@ -201,8 +186,20 @@ defined if a valid external Python host is found. That works well with the Python host isn't installed then the plugin will "think" it is running in a Vim compiled without the |+python| feature. +DOCUMENTATION *dev-doc* + +- Do not prefix help tags with "nvim-". Use |vim_diff.txt| to document + differences from Vim; no other distinction is necessary. +- If a Vim feature is removed, delete its help section and move its tag to + |vim_diff.txt|. +- Move deprecated features to |deprecated.txt|. +- Use consistent language. + - "terminal" in a help tag always means "the embedded terminal emulator", not + "the user host terminal". + - Use "tui-" to prefix help tags related to the host terminal, and "TUI" + in prose if possible. -API *dev-api* +API *dev-api* Use this pattern to name new API functions: nvim_{thing}_{action}_{arbitrary-qualifiers} @@ -233,4 +230,23 @@ _not_ a Buffer). The common {action} "list" indicates that it lists all bufs (plural) in the global context. +EXTERNAL UI *dev-ui* + +External UIs should be aware of the |api-contract|. In particular, future +versions of Nvim may add optional, new items to existing events. The API is +strongly backwards-compatible, but clients must not break if new fields are +added to existing events. + +External UIs are expected to implement some common features. + +- Users may want to configure UI-specific options. The UI should publish the + |GUIEnter| autocmd after attaching to Nvim: > + doautocmd GUIEnter +- Options can be monitored for changes by the |OptionSet| autocmd. E.g. if the + user sets the 'guifont' option, this autocmd notifies channel 42: > + autocmd OptionSet guifont call rpcnotify(42, 'option-changed', 'guifont', &guifont) +- cursor-shape change: 'guicursor' properties are sent in the mode_info_set UI + event. + + vim:tw=78:ts=8:ft=help:norl: diff --git a/runtime/doc/diff.txt b/runtime/doc/diff.txt index 6b45f8552f..74a3d183a3 100644 --- a/runtime/doc/diff.txt +++ b/runtime/doc/diff.txt @@ -1,4 +1,4 @@ -*diff.txt* For Vim version 7.4. Last change: 2016 Aug 24 +*diff.txt* Nvim VIM REFERENCE MANUAL by Bram Moolenaar @@ -10,11 +10,7 @@ eight versions of the same file. The basics are explained in section |08.7| of the user manual. -1. Starting diff mode |diff-mode| -2. Viewing diffs |view-diffs| -3. Jumping to diffs |jumpto-diffs| -4. Copying diffs |copy-diffs| -5. Diff options |diff-options| + Type <M-]> to see the table of contents. ============================================================================== 1. Starting diff mode @@ -123,6 +119,8 @@ file for a moment and come back to the same file and be in diff mode again. related options only happens in a window that has 'diff' set, if the current window does not have 'diff' set then no options in it are changed. + Hidden buffers are also removed from the list of diff'ed + buffers. The `:diffoff` command resets the relevant options to the values they had when using `:diffsplit`, `:diffpatch` , `:diffthis`. or starting Vim in diff mode. @@ -156,7 +154,8 @@ The alignment of text will go wrong when: All the buffers edited in a window where the 'diff' option is set will join in the diff. This is also possible for hidden buffers. They must have been -edited in a window first for this to be possible. +edited in a window first for this to be possible. To get rid of the hidden +buffers use `:diffoff!`. *:DiffOrig* *diff-original-file* Since 'diff' is a window-local option, it's possible to view the same buffer diff --git a/runtime/doc/digraph.txt b/runtime/doc/digraph.txt index 84024fd1b3..43f8ccab06 100644 --- a/runtime/doc/digraph.txt +++ b/runtime/doc/digraph.txt @@ -1,4 +1,4 @@ -*digraph.txt* For Vim version 7.4. Last change: 2014 Jun 19 +*digraph.txt* Nvim VIM REFERENCE MANUAL by Bram Moolenaar @@ -14,9 +14,7 @@ with CTRL-V (see |i_CTRL-V|). There is a brief introduction on digraphs in the user manual: |24.9| An alternative is using the 'keymap' option. -1. Defining digraphs |digraphs-define| -2. Using digraphs |digraphs-use| -3. Default digraphs |digraphs-default| + Type <M-]> to see the table of contents. ============================================================================== 1. Defining digraphs *digraphs-define* @@ -145,7 +143,7 @@ a standard meaning: Two 2 Hook Nine 9 Horn - Equals = Cyrillic (= used as second char) + Equals = Cyrillic (= used as second char) Asterisk * Greek Percent sign % Greek/Cyrillic special Plus + smalls: Arabic, capitals: Hebrew @@ -924,6 +922,7 @@ char digraph hex dec official name ~ โ /- 2020 8224 DAGGER โก /= 2021 8225 DOUBLE DAGGER โฅ .. 2025 8229 TWO DOT LEADER +โฆ ,. 2026 8230 HORIZONTAL ELLIPSIS โฐ %0 2030 8240 PER MILLE SIGN โฒ 1' 2032 8242 PRIME โณ 2' 2033 8243 DOUBLE PRIME diff --git a/runtime/doc/editing.txt b/runtime/doc/editing.txt index 5bfffac1f1..9fe815ea9c 100644 --- a/runtime/doc/editing.txt +++ b/runtime/doc/editing.txt @@ -1,4 +1,4 @@ -*editing.txt* For Vim version 7.4. Last change: 2016 Aug 06 +*editing.txt* Nvim VIM REFERENCE MANUAL by Bram Moolenaar @@ -6,17 +6,7 @@ Editing files *edit-files* -1. Introduction |edit-intro| -2. Editing a file |edit-a-file| -3. The argument list |argument-list| -4. Writing |writing| -5. Writing and quitting |write-quit| -6. Dialogs |edit-dialogs| -7. The current directory |current-directory| -8. Editing binary files |edit-binary| -9. Encryption |encryption| -10. Timestamps |timestamps| -11. File Searching |file-searching| + Type <M-]> to see the table of contents. ============================================================================== 1. Introduction *edit-intro* @@ -160,7 +150,8 @@ start editing another file, Vim will refuse this. In order to overrule this protection, add a '!' to the command. The changes will then be lost. For example: ":q" will not work if the buffer was changed, but ":q!" will. To see whether the buffer was changed use the "CTRL-G" command. The message includes -the string "[Modified]" if the buffer has been changed. +the string "[Modified]" if the buffer has been changed, or "+" if the 'm' flag +is in 'shortmess'. If you want to automatically save the changes without asking, switch on the 'autowriteall' option. 'autowrite' is the associated Vi-compatible option diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 78124debe1..b37b0e8836 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -1,4 +1,4 @@ -*eval.txt* For Vim version 7.4. Last change: 2016 Aug 27 +*eval.txt* Nvim VIM REFERENCE MANUAL by Bram Moolenaar @@ -12,23 +12,7 @@ Note: Expression evaluation can be disabled at compile time. If this has been done, the features in this document are not available. See |+eval| and |no-eval-feature|. -1. Variables |variables| - 1.1 Variable types - 1.2 Function references |Funcref| - 1.3 Lists |Lists| - 1.4 Dictionaries |Dictionaries| - 1.5 More about variables |more-variables| -2. Expression syntax |expression-syntax| -3. Internal variable |internal-variables| -4. Builtin Functions |functions| -5. Defining functions |user-functions| -6. Curly braces names |curly-braces-names| -7. Commands |expression-commands| -8. Exception handling |exception-handling| -9. Examples |eval-examples| -10. No +eval feature |no-eval-feature| -11. The sandbox |eval-sandbox| -12. Textlock |textlock| + Type <M-]> to see the table of contents. ============================================================================== 1. Variables *variables* @@ -38,7 +22,9 @@ done, the features in this document are not available. See |+eval| and There are six types of variables: Number A 32 or 64 bit signed number. |expr-number| *Number* - Examples: -123 0x10 0177 + 64-bit Number is available only when compiled with the + |+num64| feature. + Examples: -123 0x10 0177 0b1011 Float A floating point number. |floating-point-format| *Float* Examples: 123.456 1.15e-6 -1.1e3 @@ -89,14 +75,30 @@ To force conversion from String to Number, add zero to it: > To avoid a leading zero to cause octal conversion, or for using a different base, use |str2nr()|. + *TRUE* *FALSE* For boolean operators Numbers are used. Zero is FALSE, non-zero is TRUE. +You can also use |v:false| and |v:true|. When TRUE is returned from a +function it is the Number one, FALSE is the number zero. -Note that in the command > +Note that in the command: > :if "foo" -"foo" is converted to 0, which means FALSE. To test for a non-empty string, -use empty(): > + :" NOT executed +"foo" is converted to 0, which means FALSE. If the string starts with a +non-zero number it means TRUE: > + :if "8foo" + :" executed +To test for a non-empty string, use empty(): > :if !empty("foo") -< *E745* *E728* *E703* *E729* *E730* *E731* +< + *non-zero-arg* +Function arguments often behave slightly different from |TRUE|: If the +argument is present and it evaluates to a non-zero Number, |v:true| or a +non-empty String, then the value is considered to be TRUE. +Note that " " and "0" are also non-empty strings, thus cause the mode to be +cleared. A List, Dictionary or Float is not a Number or String, thus +evaluates to FALSE. + + *E745* *E728* *E703* *E729* *E730* *E731* List, Dictionary and Funcref types are not automatically converted. *E805* *E806* *E808* @@ -112,9 +114,10 @@ You will not get an error if you try to change the type of a variable. 1.2 Function references ~ *Funcref* *E695* *E718* -A Funcref variable is obtained with the |function()| function. It can be used -in an expression in the place of a function name, before the parenthesis -around the arguments, to invoke the function it refers to. Example: > +A Funcref variable is obtained with the |function()| function or created with +the lambda expression |expr-lambda|. It can be used in an expression in the +place of a function name, before the parenthesis around the arguments, to +invoke the function it refers to. Example: > :let Fn = function("MyFunc") :echo Fn() @@ -175,7 +178,7 @@ this won't happen: > let otherDict.myFunction = myDict.myFunction call otherDict.myFunction() -Here "self" will be "myDict", because it was bound explitly. +Here "self" will be "myDict", because it was bound explicitly. 1.3 Lists ~ @@ -230,7 +233,7 @@ it. To change a list in-place see |list-modification| below. Sublist ~ - + *sublist* A part of the List can be obtained by specifying the first and last index, separated by a colon in square brackets: > :let shortlist = mylist[2:-1] " get List [3, "four"] @@ -377,10 +380,6 @@ This works like: > : let index = index + 1 :endwhile -Note that all items in the list should be of the same type, otherwise this -results in error |E706|. To avoid this |:unlet| the variable at the end of -the loop. - If all you want to do is modify each item in the list then the |map()| function will be a simpler method than a for loop. @@ -614,13 +613,17 @@ It's possible to form a variable name with curly braces, see Expression syntax summary, from least to most significant: -|expr1| expr2 ? expr1 : expr1 if-then-else +|expr1| expr2 + expr2 ? expr1 : expr1 if-then-else -|expr2| expr3 || expr3 .. logical OR +|expr2| expr3 + expr3 || expr3 .. logical OR -|expr3| expr4 && expr4 .. logical AND +|expr3| expr4 + expr4 && expr4 .. logical AND -|expr4| expr5 == expr5 equal +|expr4| expr5 + expr5 == expr5 equal expr5 != expr5 not equal expr5 > expr5 greater than expr5 >= expr5 greater than or equal @@ -637,24 +640,28 @@ Expression syntax summary, from least to most significant: expr5 is expr5 same |List| instance expr5 isnot expr5 different |List| instance -|expr5| expr6 + expr6 .. number addition or list concatenation +|expr5| expr6 + expr6 + expr6 .. number addition or list concatenation expr6 - expr6 .. number subtraction expr6 . expr6 .. string concatenation -|expr6| expr7 * expr7 .. number multiplication +|expr6| expr7 + expr7 * expr7 .. number multiplication expr7 / expr7 .. number division expr7 % expr7 .. number modulo -|expr7| ! expr7 logical NOT +|expr7| expr8 + ! expr7 logical NOT - expr7 unary minus + expr7 unary plus -|expr8| expr8[expr1] byte of a String or item of a |List| +|expr8| expr9 + expr8[expr1] byte of a String or item of a |List| expr8[expr1 : expr1] substring of a String or sublist of a |List| expr8.name entry in a |Dictionary| expr8(expr1, ...) function call with |Funcref| variable -|expr9| number number constant +|expr9| number number constant "string" string constant, backslash is special 'string' string constant, ' is doubled [expr1, ...] |List| @@ -667,6 +674,7 @@ Expression syntax summary, from least to most significant: @r contents of register 'r' function(expr1, ...) function call func{ti}on(expr1, ...) function call with curly braces + {args -> expr1} lambda expression ".." indicates that the operations in this level can be concatenated. @@ -682,7 +690,7 @@ expr1 *expr1* *E109* expr2 ? expr1 : expr1 The expression before the '?' is evaluated to a number. If it evaluates to -non-zero, the result is the value of the expression between the '?' and ':', +|TRUE|, the result is the value of the expression between the '?' and ':', otherwise the result is the value of the expression after the ':'. Example: > :echo lnum == 1 ? "top" : lnum @@ -710,12 +718,12 @@ expr2 and expr3 *expr2* *expr3* The "||" and "&&" operators take one argument on each side. The arguments are (converted to) Numbers. The result is: - input output ~ -n1 n2 n1 || n2 n1 && n2 ~ -zero zero zero zero -zero non-zero non-zero zero -non-zero zero non-zero zero -non-zero non-zero non-zero non-zero + input output ~ +n1 n2 n1 || n2 n1 && n2 ~ +|FALSE| |FALSE| |FALSE| |FALSE| +|FALSE| |TRUE| |TRUE| |FALSE| +|TRUE| |FALSE| |TRUE| |FALSE| +|TRUE| |TRUE| |TRUE| |TRUE| The operators can be concatenated, for example: > @@ -731,8 +739,8 @@ arguments are not evaluated. This is like what happens in C. For example: > let a = 1 echo a || b -This is valid even if there is no variable called "b" because "a" is non-zero, -so the result must be non-zero. Similarly below: > +This is valid even if there is no variable called "b" because "a" is |TRUE|, +so the result must be |TRUE|. Similarly below: > echo exists("b") && b == "yes" @@ -784,8 +792,16 @@ equal" and "is" can be used. This compares the key/values of the |Dictionary| recursively. Ignoring case means case is ignored when comparing item values. *E694* -A |Funcref| can only be compared with a |Funcref| and only "equal" and "not -equal" can be used. Case is never ignored. +A |Funcref| can only be compared with a |Funcref| and only "equal", "not +equal", "is" and "isnot" can be used. Case is never ignored. Whether +arguments or a Dictionary are bound (with a partial) matters. The +Dictionaries must also be equal (or the same, in case of "is") and the +arguments must be equal (or the same). + +To compare Funcrefs to see if they refer to the same function, ignoring bound +Dictionary and arguments, use |get()| to get the function name: > + if get(Part1, 'name') == get(Part2, 'name') + " Part1 and Part2 refer to the same function When using "is" or "isnot" with a |List| or a |Dictionary| this checks if the expressions are referring to the same |List| or |Dictionary| instance. A copy @@ -806,7 +822,7 @@ and the comparison is done on Numbers. This means that: > echo 0 == 'x' 1 because 'x' converted to a Number is zero. However: > - echo 0 == 'x' + echo [0] == ['x'] 0 Inside a List or Dictionary this conversion is not used. @@ -873,6 +889,11 @@ When dividing a Number by zero the result depends on the value: <0 / 0 = -0x7fffffff (like negative infinity) (before Vim 7.2 it was always 0x7fffffff) +When 64-bit Number support is enabled: + 0 / 0 = -0x8000000000000000 (like NaN for Float) + >0 / 0 = 0x7fffffffffffffff (like positive infinity) + <0 / 0 = -0x7fffffffffffffff (like negative infinity) + When the righthand side of '%' is zero, the result is 0. None of these work for |Funcref|s. @@ -886,7 +907,7 @@ expr7 *expr7* - expr7 unary minus *expr-unary--* + expr7 unary plus *expr-unary-+* -For '!' non-zero becomes zero, zero becomes one. +For '!' |TRUE| becomes |FALSE|, |FALSE| becomes |TRUE| (one). For '-' the sign of the number is changed. For '+' the number is unchanged. @@ -905,7 +926,7 @@ expr8[expr1] item of String or |List| *expr-[]* *E111* If expr8 is a Number or String this results in a String that contains the expr1'th single byte from expr8. expr8 is used as a String, expr1 as a -Number. This doesn't recognize multi-byte encodings, see |byteidx()| for +Number. This doesn't recognize multi-byte encodings, see `byteidx()` for an alternative, or use `split()` to turn the string into a list of characters. Index zero gives the first byte. This is like it works in C. Careful: @@ -949,10 +970,10 @@ Examples: > :let s = line(".")[4:] " from the fifth byte to the end :let s = s[:-3] " remove last two bytes < - *sublist* *slice* + *slice* If expr8 is a |List| this results in a new |List| with the items indicated by the indexes expr1a and expr1b. This works like with a String, as explained -just above, except that indexes out of range cause an error. Examples: > +just above. Also see |sublist| below. Examples: > :let l = mylist[:3] " first four items :let l = mylist[4:4] " List with one item :let l = mylist[:] " shallow copy of a List @@ -996,9 +1017,10 @@ When expr8 is a |Funcref| type variable, invoke the function it refers to. number ------ number number constant *expr-number* - *hex-number* *octal-number* + *hex-number* *octal-number* *binary-number* -Decimal, Hexadecimal (starting with 0x or 0X), or Octal (starting with 0). +Decimal, Hexadecimal (starting with 0x or 0X), Binary (starting with 0b or 0B) +and Octal (starting with 0). *floating-point-format* Floating point numbers can be written in two forms: @@ -1166,6 +1188,62 @@ function(expr1, ...) function call See below |functions|. +lambda expression *expr-lambda* *lambda* +----------------- +{args -> expr1} lambda expression + +A lambda expression creates a new unnamed function which returns the result of +evaluating |expr1|. Lambda expressions differ from |user-functions| in +the following ways: + +1. The body of the lambda expression is an |expr1| and not a sequence of |Ex| + commands. +2. The prefix "a:" should not be used for arguments. E.g.: > + :let F = {arg1, arg2 -> arg1 - arg2} + :echo F(5, 2) +< 3 + +The arguments are optional. Example: > + :let F = {-> 'error function'} + :echo F() +< error function + *closure* +Lambda expressions can access outer scope variables and arguments. This is +often called a closure. Example where "i" and "a:arg" are used in a lambda +while they exist in the function scope. They remain valid even after the +function returns: > + :function Foo(arg) + : let i = 3 + : return {x -> x + i - a:arg} + :endfunction + :let Bar = Foo(4) + :echo Bar(6) +< 5 +See also |:func-closure|. Lambda and closure support can be checked with: > + if has('lambda') + +Examples for using a lambda expression with |sort()|, |map()| and |filter()|: > + :echo map([1, 2, 3], {idx, val -> val + 1}) +< [2, 3, 4] > + :echo sort([3,7,2,1,4], {a, b -> a - b}) +< [1, 2, 3, 4, 7] + +The lambda expression is also useful for jobs and timers: > + :let timer = timer_start(500, + \ {-> execute("echo 'Handler called'", "")}, + \ {'repeat': 3}) +< Handler called + Handler called + Handler called + +Note how execute() is used to execute an Ex command. That's ugly though. + + +Lambda expressions have internal names like '<lambda>42'. If you get an error +for a lambda expression, you can find what it is with the following command: > + :function {'<lambda>42'} +See also: |numbered-function| + ============================================================================== 3. Internal variable *internal-variables* *E461* @@ -1214,7 +1292,8 @@ b:changedtick The total number of changes to the current buffer. It is : let my_changedtick = b:changedtick : call My_Update() :endif -< +< You cannot change or delete the b:changedtick variable. + *window-variable* *w:var* *w:* A variable name that is preceded with "w:" is local to the current window. It is deleted when the window is closed. @@ -1343,8 +1422,8 @@ v:beval_winnr The number of the window, over which the mouse pointer is. Only window gets a number). *v:beval_winid* *beval_winid-variable* -v:beval_winid The window ID of the window, over which the mouse pointer is. - Otherwise like v:beval_winnr. +v:beval_winid The |window-ID| of the window, over which the mouse pointer + is. Otherwise like v:beval_winnr. *v:char* *char-variable* v:char Argument for evaluating 'formatexpr' and used for the typed @@ -1421,7 +1500,7 @@ v:dying Normally zero. When a deadly signal is caught it's set to VimLeave autocommands will not be executed. *v:exiting* *exiting-variable* -v:exiting The exit value Nvim will use. Before exiting, it is |v:null|. +v:exiting Exit code, or |v:null| if not exiting. |VimLeave| *v:errmsg* *errmsg-variable* v:errmsg Last given error message. It's allowed to set this variable. @@ -1442,13 +1521,20 @@ v:errors Errors found by assert functions, such as |assert_true()|. list by the assert function. *v:event* *event-variable* -v:event Dictionary of event data for the current |autocommand|. The - available keys differ per event type and are specified at the - documentation for each |event|. The possible keys are: - operator The operation performed. Unlike - |v:operator|, it is set also for an Ex - mode command. For instance, |:yank| is - translated to "|y|". +v:event Dictionary of event data for the current |autocommand|. Valid + only during the event lifetime; storing or passing v:event is + invalid! Copy it instead: > + au TextYankPost * let g:foo = deepcopy(v:event) +< Keys vary by event; see the documentation for the specific + event, e.g. |DirChanged| or |TextYankPost|. + KEY DESCRIPTION ~ + cwd Current working directory + scope Event-specific scope name. + operator Current |operator|. Also set for Ex + commands (unlike |v:operator|). For + example if |TextYankPost| is triggered + by the |:yank| Ex command then + `v:event['operator']` is "y". regcontents Text stored in the register as a |readfile()|-style list of lines. regname Requested register (e.g "x" for "xyy) @@ -1473,7 +1559,7 @@ v:false Special value used to put "false" in JSON and msgpack. See |json_encode()|. This value is converted to "v:false" when used as a String (e.g. in |expr5| with string concatenation operator) and to zero when used as a Number (e.g. in |expr5| - or |expr7| when used with numeric operators). + or |expr7| when used with numeric operators). Read-only. *v:fcs_reason* *fcs_reason-variable* v:fcs_reason The reason why the |FileChangedShell| event was triggered. @@ -1599,7 +1685,7 @@ v:mouse_win Window number for a mouse click obtained with |getchar()|. zero when there was no mouse button click. *v:mouse_winid* *mouse_winid-variable* -v:mouse_winid Window ID for a mouse click obtained with |getchar()|. +v:mouse_winid |window-ID| for a mouse click obtained with |getchar()|. The value is zero when there was no mouse button click. *v:mouse_lnum* *mouse_lnum-variable* @@ -1623,7 +1709,7 @@ v:null Special value used to put "null" in JSON and NIL in msgpack. See |json_encode()|. This value is converted to "v:null" when used as a String (e.g. in |expr5| with string concatenation operator) and to zero when used as a Number (e.g. in |expr5| - or |expr7| when used with numeric operators). + or |expr7| when used with numeric operators). Read-only. *v:oldfiles* *oldfiles-variable* v:oldfiles List of file names that is loaded from the |shada| file on @@ -1672,17 +1758,11 @@ v:profiling Normally zero. Set to one after using ":profile start". See |profiling|. *v:progname* *progname-variable* -v:progname Contains the name (with path removed) with which Nvim was - invoked. Allows you to do special initialisations for any - other name you might symlink to Nvim. +v:progname The name by which Nvim was invoked (with path removed). Read-only. *v:progpath* *progpath-variable* -v:progpath Contains the command with which Vim was invoked, including the - path. To get the full path use: > - echo exepath(v:progpath) -< NOTE: This does not work when the command is a relative path - and the current directory has changed. +v:progpath Absolute path to the current running Nvim. Read-only. *v:register* *register-variable* @@ -1758,26 +1838,27 @@ v:swapcommand Normal mode command to be executed after a file has been example, when jumping to a tag the value is ":tag tagname\r". For ":edit +cmd file" the value is ":cmd\r". - *v:t_TYPE* *v:t_bool* *t_bool-varialble* + *v:t_TYPE* *v:t_bool* *t_bool-variable* v:t_bool Value of Boolean type. Read-only. See: |type()| - *v:t_dict* *t_dict-varialble* + *v:t_dict* *t_dict-variable* v:t_dict Value of Dictionary type. Read-only. See: |type()| - *v:t_float* *t_float-varialble* + *v:t_float* *t_float-variable* v:t_float Value of Float type. Read-only. See: |type()| - *v:t_func* *t_func-varialble* + *v:t_func* *t_func-variable* v:t_func Value of Funcref type. Read-only. See: |type()| - *v:t_list* *t_list-varialble* + *v:t_list* *t_list-variable* v:t_list Value of List type. Read-only. See: |type()| - *v:t_number* *t_number-varialble* + *v:t_number* *t_number-variable* v:t_number Value of Number type. Read-only. See: |type()| - *v:t_string* *t_string-varialble* + *v:t_string* *t_string-variable* v:t_string Value of String type. Read-only. See: |type()| *v:termresponse* *termresponse-variable* -v:termresponse The escape sequence returned by the terminal for the |t_RV| - termcap entry. It is set when Vim receives an escape sequence - that starts with ESC [ or CSI and ends in a 'c', with only - digits, ';' and '.' in between. +v:termresponse The escape sequence returned by the terminal for the DA + (request primary device attributes) control sequence. It is + set when Vim receives an escape sequence that starts with ESC + [ or CSI and ends in a 'c', with only digits, ';' and '.' in + between. When this option is set, the TermResponse autocommand event is fired, so that you can react to the response from the terminal. @@ -1787,6 +1868,9 @@ v:termresponse The escape sequence returned by the terminal for the |t_RV| always 95 or bigger). Pc is always zero. {only when compiled with |+termresponse| feature} + *v:testing* *testing-variable* +v:testing Must be set before using `test_garbagecollect_now()`. + *v:this_session* *this_session-variable* v:this_session Full filename of the last loaded or saved session file. See |:mksession|. It is allowed to set this variable. When no @@ -1810,7 +1894,7 @@ v:true Special value used to put "true" in JSON and msgpack. See |json_encode()|. This value is converted to "v:true" when used as a String (e.g. in |expr5| with string concatenation operator) and to one when used as a Number (e.g. in |expr5| or - |expr7| when used with numeric operators). + |expr7| when used with numeric operators). Read-only. *v:val* *val-variable* v:val Value of the current item of a |List| or |Dictionary|. Only @@ -1835,10 +1919,11 @@ v:vim_did_enter Zero until most of startup is done. It is set to one just *v:warningmsg* *warningmsg-variable* v:warningmsg Last given warning message. It's allowed to set this variable. - *v:windowid* *windowid-variable* {Nvim} -v:windowid Application-specific window ID ("window handle" in MS-Windows) - which may be set by any attached UI. Defaults to zero. - Note: for windows inside Vim use |winnr()| or |win_getid()|. + *v:windowid* *windowid-variable* +v:windowid Application-specific window "handle" which may be set by any + attached UI. Defaults to zero. + Note: For Nvim |windows| use |winnr()| or |win_getid()|, see + |window-ID|. ============================================================================== 4. Builtin Functions *functions* @@ -1861,26 +1946,35 @@ argidx() Number current index in the argument list arglistid([{winnr} [, {tabnr}]]) Number argument list id argv({nr}) String {nr} entry of the argument list argv() List the argument list -assert_equal({exp}, {act} [, {msg}]) none assert {exp} is equal to {act} -assert_exception( {error} [, {msg}]) none assert {error} is in v:exception -assert_fails( {cmd} [, {error}]) none assert {cmd} fails -assert_false({actual} [, {msg}]) none assert {actual} is false -assert_match( {pat}, {text} [, {msg}]) none assert {pat} matches {text} -assert_notequal( {exp}, {act} [, {msg}]) none assert {exp} is not equal {act} -assert_notmatch( {pat}, {text} [, {msg}]) none assert {pat} not matches {text} -assert_true({actual} [, {msg}]) none assert {actual} is true +assert_equal({exp}, {act} [, {msg}]) + none assert {exp} is equal to {act} +assert_exception({error} [, {msg}]) + none assert {error} is in v:exception +assert_fails({cmd} [, {error}]) none assert {cmd} fails +assert_false({actual} [, {msg}]) + none assert {actual} is false +assert_inrange({lower}, {upper}, {actual} [, {msg}]) + none assert {actual} is inside the range +assert_match({pat}, {text} [, {msg}]) + none assert {pat} matches {text} +assert_notequal({exp}, {act} [, {msg}]) + none assert {exp} is not equal {act} +assert_notmatch({pat}, {text} [, {msg}]) + none assert {pat} not matches {text} +assert_report({msg}) none report a test failure +assert_true({actual} [, {msg}]) none assert {actual} is true asin({expr}) Float arc sine of {expr} atan({expr}) Float arc tangent of {expr} atan2({expr}, {expr}) Float arc tangent of {expr1} / {expr2} browse({save}, {title}, {initdir}, {default}) String put up a file requester browsedir({title}, {initdir}) String put up a directory requester -bufexists({expr}) Number TRUE if buffer {expr} exists -buflisted({expr}) Number TRUE if buffer {expr} is listed -bufloaded({expr}) Number TRUE if buffer {expr} is loaded +bufexists({expr}) Number |TRUE| if buffer {expr} exists +buflisted({expr}) Number |TRUE| if buffer {expr} is listed +bufloaded({expr}) Number |TRUE| if buffer {expr} is loaded bufname({expr}) String Name of the buffer {expr} bufnr({expr} [, {create}]) Number Number of the buffer {expr} -bufwinid({expr}) Number window ID of buffer {expr} +bufwinid({expr}) Number |window-ID| of buffer {expr} bufwinnr({expr}) Number window number of buffer {expr} byte2line({byte}) Number line number at byte count {byte} byteidx({expr}, {nr}) Number byte index of {nr}'th char in {expr} @@ -1903,7 +1997,7 @@ cos({expr}) Float cosine of {expr} cosh({expr}) Float hyperbolic cosine of {expr} count({list}, {expr} [, {ic} [, {start}]]) Number count how many {expr} are in {list} -cscope_connection([{num} , {dbpath} [, {prepend}]]) +cscope_connection([{num}, {dbpath} [, {prepend}]]) Number checks existence of cscope connection cursor({lnum}, {col} [, {off}]) Number move cursor to {lnum}, {col}, {off} @@ -1914,27 +2008,27 @@ 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 +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} -empty({expr}) Number TRUE if {expr} is empty +empty({expr}) Number |TRUE| if {expr} is empty escape({string}, {chars}) String escape {chars} in {string} with '\' eval({string}) any evaluate {string} into its value -eventhandler() Number TRUE if inside an event handler +eventhandler() Number |TRUE| if inside an event handler executable({expr}) Number 1 if executable {expr} exists execute({command}) String execute and capture output of {command} exepath({expr}) String full path of the command {expr} -exists({expr}) Number TRUE if {expr} exists +exists({expr}) Number |TRUE| if {expr} exists extend({expr1}, {expr2} [, {expr3}]) List/Dict insert items of {expr2} into {expr1} exp({expr}) Float exponential of {expr} expand({expr} [, {nosuf} [, {list}]]) any expand special keywords in {expr} feedkeys({string} [, {mode}]) Number add key sequence to typeahead buffer -filereadable({file}) Number TRUE if {file} is a readable file -filewritable({file}) Number TRUE if {file} is a writable file -filter({expr}, {string}) List/Dict remove items from {expr} where - {string} is 0 +filereadable({file}) Number |TRUE| if {file} is a readable file +filewritable({file}) Number |TRUE| if {file} is a writable file +filter({expr1}, {expr2}) List/Dict remove items from {expr1} where + {expr2} is 0 finddir({name}[, {path}[, {count}]]) String find directory {name} in {path} findfile({name}[, {path}[, {count}]]) @@ -1950,13 +2044,15 @@ foldlevel({lnum}) Number fold level at {lnum} foldtext() String line displayed for closed fold foldtextresult({lnum}) String text for closed fold at {lnum} foreground() Number bring the Vim window to the foreground -function({name} [, {arglist}] [, {dict}]) +funcref({name} [, {arglist}] [, {dict}]) Funcref reference to function {name} +function({name} [, {arglist}] [, {dict}]) + Funcref named reference to function {name} garbagecollect([{atexit}]) none free memory, breaking cyclic references get({list}, {idx} [, {def}]) any get item {idx} from {list} or {def} get({dict}, {key} [, {def}]) any get item {key} from {dict} or {def} get({func}, {what}) any get property of funcref/partial {func} -getbufinfo( [{expr}]) List information about buffers +getbufinfo([{expr}]) List information about buffers getbufline({expr}, {lnum} [, {end}]) List lines {lnum} to {end} of buffer {expr} getbufvar({expr}, {varname} [, {def}]) @@ -1971,48 +2067,48 @@ getcmdwintype() String return current command-line window type getcompletion({pat}, {type} [, {filtered}]) List list of cmdline completion matches getcurpos() List position of the cursor -getcwd([{winnr} [, {tabnr}]]) String the current working directory +getcwd([{winnr} [, {tabnr}]]) String get the current working directory getfontname([{name}]) String name of font being used getfperm({fname}) String file permissions of file {fname} getfsize({fname}) Number size in bytes of file {fname} getftime({fname}) Number last modification time of file getftype({fname}) String description of type of file {fname} -getline({lnum}) String line {lnum} of current buffer +getline({lnum}) String line {lnum} of current buffer getline({lnum}, {end}) List lines {lnum} to {end} of current buffer -getloclist({nr}) List list of location list items +getloclist({nr}[, {what}]) List list of location list items getmatches() List list of current matches getpid() Number process ID of Vim getpos({expr}) List position of cursor, mark, etc. -getqflist() List list of quickfix items +getqflist([{what}]) List list of quickfix items getreg([{regname} [, 1 [, {list}]]]) String or List contents of register -getregtype([{regname}]) String type of register -gettabinfo( [{expr}]) List list of tab pages +getregtype([{regname}]) String type of register +gettabinfo([{expr}]) List list of tab pages gettabvar({nr}, {varname} [, {def}]) any variable {varname} in tab {nr} or {def} gettabwinvar({tabnr}, {winnr}, {name} [, {def}]) any {name} in {winnr} in tab page {tabnr} -getwininfo( [{winid}]) List list of windows +getwininfo([{winid}]) List list of windows getwinposx() Number X coord in pixels of GUI Vim window getwinposy() Number Y coord in pixels of GUI Vim window getwinvar({nr}, {varname} [, {def}]) any variable {varname} in window {nr} glob({expr} [, {nosuf} [, {list} [, {alllinks}]]]) any expand file wildcards in {expr} -glob2regpat({expr}) String convert a glob pat into a search pat +glob2regpat({expr}) String convert a glob pat into a search pat globpath({path}, {expr} [, {nosuf} [, {list} [, {alllinks}]]]) String do glob({expr}) for all dirs in {path} -has({feature}) Number TRUE if feature {feature} supported -has_key({dict}, {key}) Number TRUE if {dict} has entry {key} +has({feature}) Number |TRUE| if feature {feature} supported +has_key({dict}, {key}) Number |TRUE| if {dict} has entry {key} haslocaldir([{winnr} [, {tabnr}]]) - Number TRUE if current window executed |:lcd| + Number |TRUE| if current window executed |:lcd| hasmapto({what} [, {mode} [, {abbr}]]) - Number TRUE if mapping to {what} exists + Number |TRUE| if mapping to {what} exists histadd({history}, {item}) String add an item to a history histdel({history} [, {item}]) String remove an item from a history histget({history} [, {index}]) String get the item {index} from a history histnr({history}) Number highest index of a history -hlexists({name}) Number TRUE if highlight group {name} exists +hlexists({name}) Number |TRUE| if highlight group {name} exists hlID({name}) Number syntax ID of highlight group {name} hostname() String name of the machine Vim is running on iconv({expr}, {from}, {to}) String convert encoding of {expr} @@ -2030,8 +2126,9 @@ inputsecret({prompt} [, {text}]) insert({list}, {item} [, {idx}]) List insert {item} in {list} [before {idx}] invert({expr}) Number bitwise invert -isdirectory({directory}) Number TRUE if {directory} is a directory -islocked({expr}) Number TRUE if {expr} is locked +isdirectory({directory}) Number |TRUE| if {directory} is a directory +islocked({expr}) Number |TRUE| if {expr} is locked +id({expr}) String identifier of the container items({dict}) List key-value pairs in {dict} jobclose({job}[, {stream}]) Number Closes a job stream(s) jobpid({job}) Number Returns pid of a job. @@ -2054,7 +2151,8 @@ lispindent({lnum}) Number Lisp indent for line {lnum} localtime() Number current time log({expr}) Float natural logarithm (base e) of {expr} log10({expr}) Float logarithm of Float {expr} to base 10 -map({expr}, {string}) List/Dict change each item in {expr} to {expr} +luaeval({expr}[, {expr}]) any evaluate Lua expression +map({expr1}, {expr2}) List/Dict change each item in {expr1} to {expr} maparg({name}[, {mode} [, {abbr} [, {dict}]]]) String or Dict rhs of mapping {name} in mode {mode} @@ -2074,10 +2172,10 @@ matchlist({expr}, {pat}[, {start}[, {count}]]) List match and submatches of {pat} in {expr} matchstr({expr}, {pat}[, {start}[, {count}]]) String {count}'th match of {pat} in {expr} -matchstrpos( {expr}, {pat}[, {start}[, {count}]]) +matchstrpos({expr}, {pat}[, {start}[, {count}]]) List {count}'th match of {pat} in {expr} -max({list}) Number maximum value of items in {list} -min({list}) Number minimum value of items in {list} +max({expr}) Number maximum value of items in {expr} +min({expr}) Number minimum value of items in {expr} mkdir({name} [, {path} [, {prot}]]) Number create directory {name} mode([expr]) String current editing mode @@ -2093,7 +2191,7 @@ prevnonblank({lnum}) Number line nr of non-blank line <= {lnum} printf({fmt}, {expr1}...) String format text pumvisible() Number whether popup menu is visible pyeval({expr}) any evaluate |Python| expression -py3eval({expr}) any evaluate |python3| expression +py3eval({expr}) any evaluate |python3| expression range({expr} [, {max} [, {stride}]]) List items from {expr} to {max} readfile({fname} [, {binary} [, {max}]]) @@ -2106,15 +2204,15 @@ remote_expr({server}, {string} [, {idvar}]) remote_foreground({server}) Number bring Vim server to the foreground remote_peek({serverid} [, {retvar}]) Number check for reply string -remote_read({serverid}) String read reply string +remote_read({serverid}) String read reply string remote_send({server}, {string} [, {idvar}]) String send key sequence -remove({list}, {idx} [, {end}]) any remove items {idx}-{end} from {list} +remove({list}, {idx} [, {end}]) any remove items {idx}-{end} from {list} remove({dict}, {key}) any remove entry {key} from {dict} rename({from}, {to}) Number rename (move) file from {from} to {to} -repeat({expr}, {count}) String repeat {expr} {count} times +repeat({expr}, {count}) String repeat {expr} {count} times resolve({filename}) String get filename a shortcut points to -reverse({list}) List reverse {list} in-place +reverse({list}) List reverse {list} in-place round({expr}) Float round off {expr} rpcnotify({channel}, {event}[, {args}...]) Sends an |RPC| notification to {channel} @@ -2142,12 +2240,12 @@ setbufvar({expr}, {varname}, {val}) set {varname} in buffer {expr} to {val} setcharsearch({dict}) Dict set character search from {dict} setcmdpos({pos}) Number set cursor position in command-line setfperm({fname}, {mode} Number set {fname} file permissions to {mode} -setline({lnum}, {line}) Number set line {lnum} to {line} -setloclist({nr}, {list}[, {action}[, {title}]]) +setline({lnum}, {line}) Number set line {lnum} to {line} +setloclist({nr}, {list}[, {action}[, {what}]]) Number modify location list using {list} setmatches({list}) Number restore a list of matches setpos({expr}, {list}) Number set the {expr} position to {list} -setqflist({list}[, {action}[, {title}]] +setqflist({list}[, {action}[, {what}]] Number modify quickfix list using {list} setreg({n}, {v}[, {opt}]) Number set register to value and type settabvar({nr}, {varname}, {val}) set {varname} in tab page {nr} to {val} @@ -2201,20 +2299,24 @@ synconcealed({lnum}, {col}) List info about concealing synstack({lnum}, {col}) List stack of syntax IDs at {lnum} and {col} system({cmd} [, {input}]) String output of shell command/filter {cmd} systemlist({cmd} [, {input}]) List output of shell command/filter {cmd} -tabpagebuflist([{arg}]) List list of buffer numbers in tab page +tabpagebuflist([{arg}]) List list of buffer numbers in tab page tabpagenr([{arg}]) Number number of current or last tab page tabpagewinnr({tabarg}[, {arg}]) Number number of current window in tab page -taglist({expr}) List list of tags matching {expr} +taglist({expr}[, {filename}]) List list of tags matching {expr} tagfiles() List tags files used tan({expr}) Float tangent of {expr} tanh({expr}) Float hyperbolic tangent of {expr} tempname() String name for a temporary file +test_garbagecollect_now() none free memory right now for testing +timer_info([{id}]) List information about timers +timer_pause({id}, {pause}) none pause or unpause a timer timer_start({time}, {callback} [, {options}]) Number create a timer timer_stop({timer}) none stop a timer -tolower({expr}) String the String {expr} switched to lowercase -toupper({expr}) String the String {expr} switched to uppercase +timer_stopall() none stop all timers +tolower({expr}) String the String {expr} switched to lowercase +toupper({expr}) String the String {expr} switched to uppercase tr({src}, {fromstr}, {tostr}) String translate chars of {src} in {fromstr} to chars in {tostr} trunc({expr}) Float truncate Float {expr} @@ -2224,19 +2326,19 @@ undotree() List undo file tree uniq({list} [, {func} [, {dict}]]) List remove adjacent duplicates from a list values({dict}) List values in {dict} -virtcol({expr}) Number screen column of cursor or mark +virtcol({expr}) Number screen column of cursor or mark visualmode([expr]) String last visual mode used wildmenumode() Number whether 'wildmenu' mode is active -win_findbuf( {bufnr}) List find windows containing {bufnr} -win_getid( [{win} [, {tab}]]) Number get window ID for {win} in {tab} -win_gotoid( {expr}) Number go to window with ID {expr} -win_id2tabwin( {expr}) List get tab window nr from window ID -win_id2win( {expr}) Number get window nr from window ID +win_findbuf({bufnr}) List find windows containing {bufnr} +win_getid([{win} [, {tab}]]) Number get |window-ID| for {win} in {tab} +win_gotoid({expr}) Number go to |window-ID| {expr} +win_id2tabwin({expr}) List get tab and window nr from |window-ID| +win_id2win({expr}) Number get window nr from |window-ID| winbufnr({nr}) Number buffer number of window {nr} wincol() Number window column of the cursor -winheight({nr}) Number height of window {nr} +winheight({nr}) Number height of window {nr} winline() Number window line of the cursor -winnr([{expr}]) Number number of current window +winnr([{expr}]) Number number of current window winrestcmd() String returns command to restore window sizes winrestview({dict}) none restore view of current window winsaveview() Dict save view of current window @@ -2244,7 +2346,7 @@ winwidth({nr}) Number width of window {nr} wordcount() Dict get byte/char/word statistics writefile({list}, {fname} [, {flags}]) Number write list of lines to file {fname} -xor({expr}, {expr}) Number bitwise XOR +xor({expr}, {expr}) Number bitwise XOR abs({expr}) *abs()* @@ -2322,7 +2424,7 @@ arglistid([{winnr} [, {tabnr}]]) With {winnr} only use this window in the current tab page. With {winnr} and {tabnr} use the window in the specified tab page. - {winnr} can be the window number or the window ID. + {winnr} can be the window number or the |window-ID|. *argv()* argv([{nr}]) The result is the {nr}th file in the argument list of the @@ -2368,15 +2470,23 @@ assert_exception({error} [, {msg}]) *assert_exception()* assert_fails({cmd} [, {error}]) *assert_fails()* Run {cmd} and add an error message to |v:errors| if it does NOT produce an error. - When {error} is given it must match |v:errmsg|. + When {error} is given it must match in |v:errmsg|. assert_false({actual} [, {msg}]) *assert_false()* When {actual} is not false an error message is added to |v:errors|, like with |assert_equal()|. A value is false when it is zero or |v:false|. When "{actual}" is not a number or |v:false| the assert fails. - When {msg} is omitted an error in the form "Expected False but - got {actual}" is produced. + When {msg} is omitted an error in the form + "Expected False but got {actual}" is produced. + +assert_inrange({lower}, {upper}, {actual} [, {msg}]) *assert_inrange()* + This asserts number values. When {actual} is lower than + {lower} or higher than {upper} an error message is added to + |v:errors|. + When {msg} is omitted an error in the form + "Expected range {lower} - {upper}, but got {actual}" is + produced. *assert_match()* assert_match({pattern}, {actual} [, {msg}]) @@ -2391,8 +2501,8 @@ assert_match({pattern}, {actual} [, {msg}]) Use "^" and "$" to match with the start and end of the text. Use both to match the whole text. - When {msg} is omitted an error in the form "Pattern {pattern} - does not match {actual}" is produced. + When {msg} is omitted an error in the form + "Pattern {pattern} does not match {actual}" is produced. Example: > assert_match('^f.*o$', 'foobar') < Will result in a string to be added to |v:errors|: @@ -2408,10 +2518,13 @@ assert_notmatch({pattern}, {actual} [, {msg}]) The opposite of `assert_match()`: add an error message to |v:errors| when {pattern} matches {actual}. +assert_report({msg}) *assert_report()* + Report a test failure directly, using {msg}. + assert_true({actual} [, {msg}]) *assert_true()* When {actual} is not true an error message is added to |v:errors|, like with |assert_equal()|. - A value is true when it is a non-zero number or |v:true|. + A value is |TRUE| when it is a non-zero number or |v:true|. When {actual} is not a number or |v:true| the assert fails. When {msg} is omitted an error in the form "Expected True but got {actual}" is produced. @@ -2453,9 +2566,9 @@ atan2({expr1}, {expr2}) *atan2()* *browse()* browse({save}, {title}, {initdir}, {default}) Put up a file requester. This only works when "has("browse")" - returns non-zero (only in some GUI versions). + returns |TRUE| (only in some GUI versions). The input fields are: - {save} when non-zero, select file to write + {save} when |TRUE|, select file to write {title} title for the requester {initdir} directory to start browsing in {default} default file name @@ -2465,7 +2578,7 @@ browse({save}, {title}, {initdir}, {default}) *browsedir()* browsedir({title}, {initdir}) Put up a directory requester. This only works when - "has("browse")" returns non-zero (only in some GUI versions). + "has("browse")" returns |TRUE| (only in some GUI versions). On systems where a directory browser is not supported a file browser is used. In that case: select a file in the directory to be used. @@ -2476,7 +2589,7 @@ browsedir({title}, {initdir}) browsing is not possible, an empty string is returned. bufexists({expr}) *bufexists()* - The result is a Number, which is non-zero if a buffer called + The result is a Number, which is |TRUE| if a buffer called {expr} exists. If the {expr} argument is a number, buffer numbers are used. If the {expr} argument is a string it must match a buffer name @@ -2496,12 +2609,12 @@ bufexists({expr}) *bufexists()* file name. buflisted({expr}) *buflisted()* - The result is a Number, which is non-zero if a buffer called + The result is a Number, which is |TRUE| if a buffer called {expr} exists and is listed (has the 'buflisted' option set). The {expr} argument is used like with |bufexists()|. bufloaded({expr}) *bufloaded()* - The result is a Number, which is non-zero if a buffer called + The result is a Number, which is |TRUE| if a buffer called {expr} exists and is loaded (shown in a window or hidden). The {expr} argument is used like with |bufexists()|. @@ -2549,7 +2662,7 @@ bufnr({expr} [, {create}]) them. Use bufexists() to test for the existence of a buffer. bufwinid({expr}) *bufwinid()* - The result is a Number, which is the window ID of the first + The result is a Number, which is the |window-ID| of the first window associated with buffer {expr}. For the use of {expr}, see |bufname()| above. If buffer {expr} doesn't exist or there is no such window, -1 is returned. Example: > @@ -2704,8 +2817,8 @@ col({expr}) The result is a Number, which is the byte index of the column complete({startcol}, {matches}) *complete()* *E785* Set the matches for Insert mode completion. Can only be used in Insert mode. You need to use a mapping - with CTRL-R = |i_CTRL-R|. It does not work after CTRL-O or - with an expression mapping. + with CTRL-R = (see |i_CTRL-R|). It does not work after CTRL-O + or with an expression mapping. {startcol} is the byte offset in the line where the completed text start. The text up to the cursor is the original text that will be replaced by the matches. Use col('.') for an @@ -2742,7 +2855,7 @@ complete_add({expr}) *complete_add()* complete_check() *complete_check()* Check for a key typed while looking for completion matches. This is to be used when looking for matches takes some time. - Returns non-zero when searching for matches is to be aborted, + Returns |TRUE| when searching for matches is to be aborted, zero otherwise. Only to be used by the function specified with the 'completefunc' option. @@ -2752,8 +2865,6 @@ confirm({msg} [, {choices} [, {default} [, {type}]]]) Confirm() offers the user a dialog, from which a choice can be made. It returns the number of the choice. For the first choice this is 1. - Note: confirm() is only supported when compiled with dialog - support, see |+dialog_con| and |+dialog_gui|. {msg} is displayed in a |dialog| with {choices} as the alternatives. When {choices} is missing or empty, "&OK" is @@ -2836,7 +2947,7 @@ count({comp}, {expr} [, {ic} [, {start}]]) *count()* in |List| or |Dictionary| {comp}. If {start} is given then start with the item with this index. {start} can only be used with a |List|. - When {ic} is given and it's non-zero then case is ignored. + When {ic} is given and it's |TRUE| then case is ignored. *cscope_connection()* @@ -2939,6 +3050,8 @@ delete({fname} [, {flags}]) *delete()* When {flags} is "rf": Deletes the directory by the name {fname} and everything in it, recursively. BE CAREFUL! + Note: on MS-Windows it is not possible to delete a directory + that is being used. The result is a Number, which is 0 if the delete operation was successful and -1 when the deletion failed or partly failed. @@ -2989,7 +3102,7 @@ dictwatcherdel({dict}, {pattern}, {callback}) *dictwatcherdel()* order for the watcher to be successfully deleted. *did_filetype()* -did_filetype() Returns non-zero when autocommands are being executed and the +did_filetype() Returns |TRUE| when autocommands are being executed and the FileType event has been triggered at least once. Can be used to avoid triggering the FileType event again in the scripts that detect the file type. |FileType| @@ -3087,24 +3200,28 @@ execute({command} [, {silent}]) *execute()* The default is 'silent'. Note that with "silent!", unlike `:redir`, error messages are dropped. - This function is not available in the |sandbox|. + To get a list of lines use |split()| on the result: > + split(execute('args'), "\n") + +< This function is not available in the |sandbox|. Note: If nested, an outer execute() will not observe output of the inner calls. Note: Text attributes (highlights) are not captured. exepath({expr}) *exepath()* - If {expr} is an executable and is either an absolute path, a - relative path or found in $PATH, return the full path. - Note that the current directory is used when {expr} starts - with "./", which may be a problem for Vim: > - echo exepath(v:progpath) -< If {expr} cannot be found in $PATH or is not executable then - an empty string is returned. + Returns the full path of {expr} if it is an executable and + given as a (partial or full) path or is found in $PATH. + Returns empty string otherwise. + If {expr} starts with "./" the |current-directory| is used. *exists()* -exists({expr}) The result is a Number, which is non-zero if {expr} is - defined, zero otherwise. The {expr} argument is a string, - which contains one of these: +exists({expr}) The result is a Number, which is |TRUE| if {expr} is + defined, zero otherwise. + + For checking for a supported feature use |has()|. + For checking if a file exists use |filereadable()|. + + The {expr} argument is a string, which contains one of these: &option-name Vim option (only checks if it exists, not if it really works) +option-name Vim option that works. @@ -3152,7 +3269,6 @@ exists({expr}) The result is a Number, which is non-zero if {expr} is event and pattern. ##event autocommand for this event is supported. - For checking for a supported feature use |has()|. Examples: > exists("&mouse") @@ -3198,7 +3314,7 @@ expand({expr} [, {nosuf} [, {list}]]) *expand()* Expand wildcards and the following special keywords in {expr}. 'wildignorecase' applies. - If {list} is given and it is non-zero, a List will be returned. + If {list} is given and it is |TRUE|, a List will be returned. Otherwise the result is a String and when there are several matches, they are separated by <NL> characters. [Note: in version 5.0 a space was used, which caused problems when a @@ -3257,7 +3373,7 @@ expand({expr} [, {nosuf} [, {list}]]) *expand()* When {expr} does not start with '%', '#' or '<', it is expanded like a file name is expanded on the command line. 'suffixes' and 'wildignore' are used, unless the optional - {nosuf} argument is given and it is non-zero. + {nosuf} argument is given and it is |TRUE|. Names for non-existing files are included. The "**" item can be used to search in a directory tree. For example, to find all "README" files in the current directory and below: > @@ -3349,9 +3465,9 @@ feedkeys({string} [, {mode}]) *feedkeys()* Return value is always 0. filereadable({file}) *filereadable()* - The result is a Number, which is TRUE when a file with the + The result is a Number, which is |TRUE| when a file with the name {file} exists, and can be read. If {file} doesn't exist, - or is a directory, the result is FALSE. {file} is any + or is a directory, the result is |FALSE|. {file} is any expression, which is used as a String. If you don't care about the file being readable you can use |glob()|. @@ -3364,31 +3480,52 @@ filewritable({file}) *filewritable()* directory, and we can write to it, the result is 2. -filter({expr}, {string}) *filter()* - {expr} must be a |List| or a |Dictionary|. - For each item in {expr} evaluate {string} and when the result +filter({expr1}, {expr2}) *filter()* + {expr1} must be a |List| or a |Dictionary|. + For each item in {expr1} evaluate {expr2} and when the result is zero remove the item from the |List| or |Dictionary|. - Inside {string} |v:val| has the value of the current item. + {expr2} must be a |string| or |Funcref|. + + If {expr2} is a |string|, inside {expr2} |v:val| has the value + of the current item. For a |Dictionary| |v:key| has the key + of the current item and for a |List| |v:key| has the index of + the current item. For a |Dictionary| |v:key| has the key of the current item. Examples: > - :call filter(mylist, 'v:val !~ "OLD"') + call filter(mylist, 'v:val !~ "OLD"') < Removes the items where "OLD" appears. > - :call filter(mydict, 'v:key >= 8') + call filter(mydict, 'v:key >= 8') < Removes the items with a key below 8. > - :call filter(var, 0) + call filter(var, 0) < Removes all the items, thus clears the |List| or |Dictionary|. - Note that {string} is the result of expression and is then + Note that {expr2} is the result of expression and is then used as an expression again. Often it is good to use a |literal-string| to avoid having to double backslashes. + If {expr2} is a |Funcref| it must take two arguments: + 1. the key or the index of the current item. + 2. the value of the current item. + The function must return |TRUE| if the item should be kept. + Example that keeps the odd items of a list: > + func Odd(idx, val) + return a:idx % 2 == 1 + endfunc + call filter(mylist, function('Odd')) +< It is shorter when using a |lambda|: > + call filter(myList, {idx, val -> idx * val <= 42}) +< If you do not use "val" you can leave it out: > + call filter(myList, {idx -> idx % 2 == 1}) +< The operation is done in-place. If you want a |List| or |Dictionary| to remain unmodified make a copy first: > :let l = filter(copy(mylist), 'v:val =~ "KEEP"') -< Returns {expr}, the |List| or |Dictionary| that was filtered. - When an error is encountered while evaluating {string} no - further items in {expr} are processed. +< Returns {expr1}, the |List| or |Dictionary| that was filtered. + When an error is encountered while evaluating {expr2} no + further items in {expr1} are processed. When {expr2} is a + Funcref errors inside a function are ignored, unless it was + defined with the "abort" flag. finddir({name}[, {path}[, {count}]]) *finddir()* @@ -3419,17 +3556,19 @@ float2nr({expr}) *float2nr()* decimal point. {expr} must evaluate to a |Float| or a Number. When the value of {expr} is out of range for a |Number| the - result is truncated to 0x7fffffff or -0x7fffffff. NaN results - in -0x80000000. + result is truncated to 0x7fffffff or -0x7fffffff (or when + 64-bit Number support is enabled, 0x7fffffffffffffff or + -0x7fffffffffffffff. NaN results in -0x80000000 (or when + 64-bit Number support is enabled, -0x8000000000000000). Examples: > echo float2nr(3.95) < 3 > echo float2nr(-23.45) < -23 > echo float2nr(1.0e100) -< 2147483647 > +< 2147483647 (or 9223372036854775807) > echo float2nr(-1.0e150) -< -2147483647 > +< -2147483647 (or -9223372036854775807) > echo float2nr(1.0e-100) < 0 @@ -3515,11 +3654,14 @@ foldtext() Returns a String, to be displayed for a closed fold. This is |v:foldstart|, |v:foldend| and |v:folddashes| variables. The returned string looks like this: > +-- 45 lines: abcdef -< The number of dashes depends on the foldlevel. The "45" is - the number of lines in the fold. "abcdef" is the text in the - first non-blank line of the fold. Leading white space, "//" - or "/*" and the text from the 'foldmarker' and 'commentstring' - options is removed. +< The number of leading dashes depends on the foldlevel. The + "45" is the number of lines in the fold. "abcdef" is the text + in the first non-blank line of the fold. Leading white space, + "//" or "/*" and the text from the 'foldmarker' and + 'commentstring' options is removed. + When used to draw the actual foldtext, the rest of the line + will be filled with the fold char from the 'fillchars' + setting. {not available when compiled without the |+folding| feature} foldtextresult({lnum}) *foldtextresult()* @@ -3540,12 +3682,31 @@ foreground() Move the Vim window to the foreground. Useful when sent from |remote_foreground()| instead. {only in the Win32 GUI and console version} + *funcref()* +funcref({name} [, {arglist}] [, {dict}]) + Just like |function()|, but the returned Funcref will lookup + the function by reference, not by name. This matters when the + function {name} is redefined later. + + Unlike |function()|, {name} must be an existing user function. + Also for autoloaded functions. {name} cannot be a builtin + function. *function()* *E700* *E922* *E923* function({name} [, {arglist}] [, {dict}]) Return a |Funcref| variable that refers to function {name}. {name} can be a user defined function or an internal function. + {name} can also be a Funcref or a partial. When it is a + partial the dict stored in it will be used and the {dict} + argument is not allowed. E.g.: > + let FuncWithArg = function(dict.Func, [arg]) + let Broken = function(dict.Func, [arg], dict) +< + When using the Funcref the function will be found by {name}, + also when it was redefined later. Use |funcref()| to keep the + same function. + When {arglist} or {dict} is present this creates a partial. That mans the argument list and/or the dictionary is stored in the Funcref and will be used when the Funcref is called. @@ -3584,18 +3745,25 @@ function({name} [, {arglist}] [, {dict}]) garbagecollect([{atexit}]) *garbagecollect()* Cleanup unused |Lists| and |Dictionaries| that have circular - references. There is hardly ever a need to invoke this - function, as it is automatically done when Vim runs out of - memory or is waiting for the user to press a key after - 'updatetime'. Items without circular references are always - freed when they become unused. + references. + + There is hardly ever a need to invoke this function, as it is + automatically done when Vim runs out of memory or is waiting + for the user to press a key after 'updatetime'. Items without + circular references are always freed when they become unused. This is useful if you have deleted a very big |List| and/or |Dictionary| with circular references in a script that runs for a long time. + When the optional {atexit} argument is one, garbage collection will also be done when exiting Vim, if it wasn't done before. This is useful when checking for memory leaks. + The garbage collection is not done immediately but only when + it's safe to perform. This is when waiting for the user to + type a character. To force garbage collection immediately use + |test_garbagecollect_now()|. + get({list}, {idx} [, {default}]) *get()* Get item {idx} from |List| {list}. When this item is not available return {default}. Return zero when {default} is @@ -3861,6 +4029,7 @@ getcompletion({pat}, {type} [, {filtered}]) *getcompletion()* augroup autocmd groups buffer buffer names behave :behave suboptions + cmdline |cmdline-completion| color color schemes command Ex command (and arguments) compiler compilers @@ -3879,7 +4048,9 @@ getcompletion({pat}, {type} [, {filtered}]) *getcompletion()* locale locale names (as output of locale -a) mapping mapping name menu menus + messages |:messages| suboptions option options + packadd optional package |pack-add| names shellcmd Shell command sign |:sign| suboptions syntax syntax file names |'syntax'| @@ -3889,7 +4060,7 @@ getcompletion({pat}, {type} [, {filtered}]) *getcompletion()* user user names var user variables - If {pat} is an empty string, then all the matches are returned. + If {pat} is an empty string then all matches are returned. Otherwise only items matching {pat} are returned. See |wildcards| for the use of special characters in {pat}. @@ -3922,7 +4093,7 @@ getcwd([{winnr}[, {tabnr}]]) *getcwd()* getcwd(0) getcwd(0, 0) < If {winnr} is -1 it is ignored, only the tab is resolved. - {winnr} can be the window number or the window ID. + {winnr} can be the window number or the |window-ID|. getfsize({fname}) *getfsize()* @@ -4015,15 +4186,19 @@ getline({lnum} [, {end}]) < To get lines from another buffer see |getbufline()| -getloclist({nr}) *getloclist()* +getloclist({nr},[, {what}]) *getloclist()* Returns a list with all the entries in the location list for - window {nr}. {nr} can be the window number or the window ID. + window {nr}. {nr} can be the window number or the |window-ID|. When {nr} is zero the current window is used. For a location list window, the displayed location list is returned. For an invalid window number {nr}, an empty list is returned. Otherwise, same as |getqflist()|. + If the optional {what} dictionary argument is supplied, then + returns the items listed in {what} as a dictionary. Refer to + |getqflist()| for the supported items in {what}. + getmatches() *getmatches()* Returns a |List| with all matches previously defined by |matchadd()| and the |:match| commands. |getmatches()| is @@ -4073,22 +4248,22 @@ getpos({expr}) Get the position for {expr}. For possible values of {expr} < Also see |getcurpos()| and |setpos()|. -getqflist() *getqflist()* +getqflist([{what}]) *getqflist()* Returns a list with all the current quickfix errors. Each list item is a dictionary with these entries: bufnr number of buffer that has the file name, use bufname() to get the name lnum line number in the buffer (first line is 1) col column number (first column is 1) - vcol non-zero: "col" is visual column - zero: "col" is byte index + vcol |TRUE|: "col" is visual column + |FALSE|: "col" is byte index nr error number pattern search pattern used to locate the error text description of the error type type of the error, 'E', '1', etc. - valid non-zero: recognized error message + valid |TRUE|: recognized error message - When there is no error list or it's empty an empty list is + When there is no error list or it's empty, an empty list is returned. Quickfix list entries with non-existing buffer number are returned with "bufnr" set to zero. @@ -4098,13 +4273,35 @@ getqflist() *getqflist()* :for d in getqflist() : echo bufname(d.bufnr) ':' d.lnum '=' d.text :endfor +< + If the optional {what} dictionary argument is supplied, then + returns only the items listed in {what} as a dictionary. The + following string items are supported in {what}: + nr get information for this quickfix list; zero + means the current quickfix list + title get the list title + winid get the |window-ID| (if opened) + all all of the above quickfix properties + Non-string items in {what} are ignored. + If "nr" is not present then the current quickfix list is used. + In case of error processing {what}, an empty dictionary is + returned. + The returned dictionary contains the following entries: + nr quickfix list number + title quickfix list title text + winid quickfix |window-ID| (if opened) + + Examples: > + :echo getqflist({'all': 1}) + :echo getqflist({'nr': 2, 'title': 1}) +< getreg([{regname} [, 1 [, {list}]]]) *getreg()* The result is a String, which is the contents of register {regname}. Example: > :let cliptext = getreg('*') -< When {regname} was not set the result is a empty string. +< When {regname} was not set the result is an empty string. getreg('=') returns the last evaluated value of the expression register. (For use in maps.) @@ -4112,7 +4309,7 @@ getreg([{regname} [, 1 [, {list}]]]) *getreg()* be restored with |setreg()|. For other registers the extra argument is ignored, thus you can always give it. - If {list} is present and non-zero, the result type is changed + If {list} is present and |TRUE|, the result type is changed to |List|. Each list item is one text line. Use it if you care about zero bytes possibly present inside register: without third argument both NLs and zero bytes are represented as NLs @@ -4140,10 +4337,10 @@ gettabinfo([{arg}]) *gettabinfo()* empty List is returned. Each List item is a Dictionary with the following entries: - nr tab page number. + tabnr tab page number. variables a reference to the dictionary with tabpage-local variables - windows List of window IDs in the tag page. + windows List of |window-ID|s in the tag page. gettabvar({tabnr}, {varname} [, {def}]) *gettabvar()* Get the value of a tab-local variable {varname} in tab page @@ -4167,7 +4364,7 @@ gettabwinvar({tabnr}, {winnr}, {varname} [, {def}]) *gettabwinvar()* Note that {varname} must be the name without "w:". Tabs are numbered starting with one. For the current tabpage use |getwinvar()|. - {winnr} can be the window number or the window ID. + {winnr} can be the window number or the |window-ID|. When {winnr} is zero the current window is used. This also works for a global option, buffer-local option and window-local option, but it doesn't work for a global variable @@ -4195,20 +4392,20 @@ getwininfo([{winid}]) *getwininfo()* is returned. If the window does not exist the result is an empty list. - Without an information about all the windows in all the tab - pages is returned. + Without {winid} information about all the windows in all the + tab pages is returned. Each List item is a Dictionary with the following entries: - bufnum number of buffer in the window + bufnr number of buffer in the window height window height loclist 1 if showing a location list - nr window number quickfix 1 if quickfix or location list window - tpnr tab page number + tabnr tab page number variables a reference to the dictionary with window-local variables width window width - winid window ID + winid |window-ID| + winnr window number To obtain all window-local variables use: > gettabwinvar({tabnr}, {winnr}, '&') @@ -4223,13 +4420,13 @@ glob({expr} [, {nosuf} [, {list} [, {alllinks}]]]) *glob()* Expand the file wildcards in {expr}. See |wildcards| for the use of special characters. - Unless the optional {nosuf} argument is given and is non-zero, + Unless the optional {nosuf} argument is given and is |TRUE|, the 'suffixes' and 'wildignore' options apply: Names matching one of the patterns in 'wildignore' will be skipped and 'suffixes' affect the ordering of matches. 'wildignorecase' always applies. - When {list} is present and it is non-zero the result is a List + When {list} is present and it is |TRUE| the result is a List with all matching files. The advantage of using a List is, you also get filenames containing newlines correctly. Otherwise the result is a String and when there are several @@ -4240,7 +4437,7 @@ glob({expr} [, {nosuf} [, {list} [, {alllinks}]]]) *glob()* A name for a non-existing file is not included. A symbolic link is only included if it points to an existing file. However, when the {alllinks} argument is present and it is - non-zero then all symbolic links are included. + |TRUE| then all symbolic links are included. For most systems backticks can be used to get files names from any external command. Example: > @@ -4261,6 +4458,8 @@ glob2regpat({expr}) *glob2regpat()* if filename =~ '^Make.*\.mak$' < When {expr} is an empty string the result is "^$", match an empty string. + Note that the result depends on the system. On MS-Windows + a backslash usually means a patch separator. *globpath()* globpath({path}, {expr} [, {nosuf} [, {list} [, {allinks}]]]) @@ -4277,12 +4476,12 @@ globpath({path}, {expr} [, {nosuf} [, {list} [, {allinks}]]]) If the expansion fails for one of the directories, there is no error message. - Unless the optional {nosuf} argument is given and is non-zero, + Unless the optional {nosuf} argument is given and is |TRUE|, the 'suffixes' and 'wildignore' options apply: Names matching one of the patterns in 'wildignore' will be skipped and 'suffixes' affect the ordering of matches. - When {list} is present and it is non-zero the result is a List + When {list} is present and it is |TRUE| the result is a List with all matching files. The advantage of using a List is, you also get filenames containing newlines correctly. Otherwise the result is a String and when there are several matches, @@ -4310,9 +4509,8 @@ has_key({dict}, {key}) *has_key()* an entry with key {key}. Zero otherwise. haslocaldir([{winnr}[, {tabnr}]]) *haslocaldir()* - The result is a Number, which is 1 when the specified tabpage - or window has a local path set via |:lcd| or |:tcd|, and - 0 otherwise. + The result is a Number, which is 1 when the tabpage or window + has set a local path via |:tcd| or |:lcd|, otherwise 0. Tabs and windows are identified by their respective numbers, 0 means current tab or window. Missing argument implies 0. @@ -4320,7 +4518,9 @@ haslocaldir([{winnr}[, {tabnr}]]) *haslocaldir()* haslocaldir() haslocaldir(0) haslocaldir(0, 0) -< {winnr} can be the window number or the window ID. +< With {winnr} use that window in the current tabpage. + With {winnr} and {tabnr} use the window in that tabpage. + {winnr} can be the window number or the |window-ID|. If {winnr} is -1 it is ignored, only the tab is resolved. hasmapto({what} [, {mode} [, {abbr}]]) *hasmapto()* @@ -4328,7 +4528,7 @@ hasmapto({what} [, {mode} [, {abbr}]]) *hasmapto()* contains {what} in somewhere in the rhs (what it is mapped to) and this mapping exists in one of the modes indicated by {mode}. - When {abbr} is there and it is non-zero use abbreviations + When {abbr} is there and it is |TRUE| use abbreviations instead of mappings. Don't forget to specify Insert and/or Command-line mode. Both the global mappings and the mappings local to the current @@ -4359,6 +4559,7 @@ histadd({history}, {item}) *histadd()* "expr" or "=" typed expression history "input" or "@" input line history "debug" or ">" debug command history + empty the current or last used history The {history} string does not need to be the whole name, one character is sufficient. If {item} does already exist in the history, it will be @@ -4479,7 +4680,7 @@ index({list}, {expr} [, {start} [, {ic}]]) *index()* is not used here, case always matters. If {start} is given then start looking at the item with index {start} (may be negative for an item relative to the end). - When {ic} is given and it is non-zero, ignore case. Otherwise + When {ic} is given and it is |TRUE|, ignore case. Otherwise case must match. -1 is returned when {expr} is not found in {list}. Example: > @@ -4488,10 +4689,24 @@ index({list}, {expr} [, {start} [, {ic}]]) *index()* input({prompt} [, {text} [, {completion}]]) *input()* +input({opts}) The result is a String, which is whatever the user typed on the command-line. The {prompt} argument is either a prompt string, or a blank string (for no prompt). A '\n' can be used in the prompt to start a new line. + + In the second form it accepts a single dictionary with the + following keys, any of which may be omitted: + + Key Default Description ~ + prompt "" Same as {prompt} in the first form. + default "" Same as {text} in the first form. + completion nothing Same as {completion} in the first form. + cancelreturn "" Same as {cancelreturn} from + |inputdialog()|. Also works with + input(). + highlight nothing Highlight handler: |Funcref|. + The highlighting set with |:echohl| is used for the prompt. The input is entered just like a command-line, with the same editing commands and mappings. There is a separate history @@ -4513,7 +4728,60 @@ input({prompt} [, {text} [, {completion}]]) *input()* "-complete=" argument. Refer to |:command-completion| for more information. Example: > let fname = input("File: ", "", "file") + +< *input()-highlight* *E5400* *E5402* + The optional `highlight` key allows specifying function which + will be used for highlighting user input. This function + receives user input as its only argument and must return + a list of 3-tuples [hl_start_col, hl_end_col + 1, hl_group] + where + hl_start_col is the first highlighted column, + hl_end_col is the last highlighted column (+ 1!), + hl_group is |:hl| group used for highlighting. + *E5403* *E5404* *E5405* *E5406* + Both hl_start_col and hl_end_col + 1 must point to the start + of the multibyte character (highlighting must not break + multibyte characters), hl_end_col + 1 may be equal to the + input length. Start column must be in range [0, len(input)), + end column must be in range (hl_start_col, len(input)], + sections must be ordered so that next hl_start_col is greater + then or equal to previous hl_end_col. + + Example (try some input with parentheses): > + highlight RBP1 guibg=Red ctermbg=red + highlight RBP2 guibg=Yellow ctermbg=yellow + highlight RBP3 guibg=Green ctermbg=green + highlight RBP4 guibg=Blue ctermbg=blue + let g:rainbow_levels = 4 + function! RainbowParens(cmdline) + let ret = [] + let i = 0 + let lvl = 0 + while i < len(a:cmdline) + if a:cmdline[i] is# '(' + call add(ret, [i, i + 1, 'RBP' . ((lvl % g:rainbow_levels) + 1)]) + let lvl += 1 + elseif a:cmdline[i] is# ')' + let lvl -= 1 + call add(ret, [i, i + 1, 'RBP' . ((lvl % g:rainbow_levels) + 1)]) + endif + let i += 1 + endwhile + return ret + endfunction + call input({'prompt':'>','highlight':'RainbowParens'}) < + Highlight function is called at least once for each new + displayed input string, before command-line is redrawn. It is + expected that function is pure for the duration of one input() + call, i.e. it produces the same output for the same input, so + output may be memoized. Function is run like under |:silent| + modifier. If the function causes any errors, it will be + skipped for the duration of the current input() call. + + Currently coloring is disabled when command-line contains + arabic characters. + NOTE: This function must not be used in a startup file, for the versions that only run in GUI mode (e.g., the Win32 GUI). Note: When input() is called from within a mapping it will @@ -4533,6 +4801,7 @@ input({prompt} [, {text} [, {completion}]]) *input()* :endfunction inputdialog({prompt} [, {text} [, {cancelreturn}]]) *inputdialog()* +inputdialog({opts}) Like |input()|, but when the GUI is running and text dialogs are supported, a dialog window pops up to input the text. Example: > @@ -4544,7 +4813,6 @@ inputdialog({prompt} [, {text} [, {cancelreturn}]]) *inputdialog()* omitted an empty string is returned. Hitting <Enter> works like pressing the OK button. Hitting <Esc> works like pressing the Cancel button. - NOTE: Command-line completion is not supported. inputlist({textlist}) *inputlist()* {textlist} must be a |List| of strings. This |List| is @@ -4607,13 +4875,13 @@ invert({expr}) *invert()* :let bits = invert(bits) isdirectory({directory}) *isdirectory()* - The result is a Number, which is non-zero when a directory + The result is a Number, which is |TRUE| when a directory with the name {directory} exists. If {directory} doesn't - exist, or isn't a directory, the result is FALSE. {directory} + exist, or isn't a directory, the result is |FALSE|. {directory} is any expression, which is used as a String. islocked({expr}) *islocked()* *E786* - The result is a Number, which is non-zero when {expr} is the + The result is a Number, which is |TRUE| when {expr} is the name of a locked variable. {expr} must be the name of a variable, |List| item or |Dictionary| entry, not the variable itself! Example: > @@ -4625,6 +4893,22 @@ islocked({expr}) *islocked()* *E786* < When {expr} is a variable that does not exist you get an error message. Use |exists()| to check for existence. +id({expr}) *id()* + Returns a |String| which is a unique identifier of the + container type (|List|, |Dict| and |Partial|). It is + guaranteed that for the mentioned types `id(v1) ==# id(v2)` + returns true iff `type(v1) == type(v2) && v1 is v2` (note: + |v:_null_list| and |v:_null_dict| have the same `id()` with + different types because they are internally represented as + a NULL pointers). Currently `id()` returns a hexadecimal + representanion of the pointers to the containers (i.e. like + `0x994a40`), same as `printf("%p", {expr})`, but it is advised + against counting on exact format of return value. + + It is not guaranteed that `id(no_longer_existing_container)` + will not be equal to some other `id()`: new containers may + reuse identifiers of the garbage-collected ones. + items({dict}) *items()* Return a |List| with all the key-value pairs of {dict}. Each |List| item is a list with two items: the key of a {dict} @@ -4666,15 +4950,22 @@ jobstart({cmd}[, {opts}]) {Nvim} *jobstart()* Spawns {cmd} as a job. If {cmd} is a |List| it is run directly. If {cmd} is a |String| it is processed like this: > :call jobstart(split(&shell) + split(&shellcmdflag) + ['{cmd}']) -< NOTE: read |shell-unquoting| before constructing any lists - with 'shell' or 'shellcmdflag' options. The above call is - only written to show the idea, one needs to perform unquoting - and do split taking quotes into account. +< (Only shows the idea; see |shell-unquoting| for full details.) + + NOTE: on Windows if {cmd} is a List: + - cmd[0] must be an executable (not a "built-in"). If it is + in $PATH it can be called by name, without an extension: > + :call jobstart(['ping', 'neovim.io']) +< If it is a full or partial path, extension is required: > + :call jobstart(['System32\ping.exe', 'neovim.io']) +< - {cmd} is collapsed to a string of quoted args as expected + by CommandLineToArgvW https://msdn.microsoft.com/bb776391 + unless cmd[0] is some form of "cmd.exe". {opts} is a dictionary with these keys: - on_stdout: stdout event handler (function name or |Funcref|) - on_stderr: stderr event handler (function name or |Funcref|) - on_exit : exit event handler (function name or |Funcref|) + |on_stdout|: stdout event handler (function name or |Funcref|) + |on_stderr|: stderr event handler (function name or |Funcref|) + |on_exit| : exit event handler (function name or |Funcref|) cwd : Working directory of the job; defaults to |current-directory|. rpc : If set, |msgpack-rpc| will be used to communicate @@ -4758,8 +5049,8 @@ json_decode({expr}) *json_decode()* json_encode({expr}) *json_encode()* Convert {expr} into a JSON string. Accepts - |msgpack-special-dict| as the input. Will not convert |Funcref|s, - mappings with non-string keys (can be created as + |msgpack-special-dict| as the input. Will not convert + |Funcref|s, mappings with non-string keys (can be created as |msgpack-special-dict|), values with self-referencing containers, strings which contain non-UTF-8 characters, pseudo-UTF-8 strings which contain codepoints reserved for @@ -4910,30 +5201,51 @@ log10({expr}) *log10()* :echo log10(0.01) < -2.0 +luaeval({expr}[, {expr}]) + Evaluate Lua expression {expr} and return its result converted + to Vim data structures. See |lua-luaeval| for more details. -map({expr}, {string}) *map()* - {expr} must be a |List| or a |Dictionary|. - Replace each item in {expr} with the result of evaluating - {string}. - Inside {string} |v:val| has the value of the current item. - For a |Dictionary| |v:key| has the key of the current item - and for a |List| |v:key| has the index of the current item. +map({expr1}, {expr2}) *map()* + {expr1} must be a |List| or a |Dictionary|. + Replace each item in {expr1} with the result of evaluating + {expr2}. {expr2} must be a |string| or |Funcref|. + + If {expr2} is a |string|, inside {expr2} |v:val| has the value + of the current item. For a |Dictionary| |v:key| has the key + of the current item and for a |List| |v:key| has the index of + the current item. Example: > :call map(mylist, '"> " . v:val . " <"') < This puts "> " before and " <" after each item in "mylist". - Note that {string} is the result of an expression and is then + Note that {expr2} is the result of an expression and is then used as an expression again. Often it is good to use a |literal-string| to avoid having to double backslashes. You still have to double ' quotes + If {expr2} is a |Funcref| it is called with two arguments: + 1. The key or the index of the current item. + 2. the value of the current item. + The function must return the new value of the item. Example + that changes each value by "key-value": > + func KeyValue(key, val) + return a:key . '-' . a:val + endfunc + call map(myDict, function('KeyValue')) +< It is shorter when using a |lambda|: > + call map(myDict, {key, val -> key . '-' . val}) +< If you do not use "val" you can leave it out: > + call map(myDict, {key -> 'item: ' . key}) +< The operation is done in-place. If you want a |List| or |Dictionary| to remain unmodified make a copy first: > :let tlist = map(copy(mylist), ' v:val . "\t"') -< Returns {expr}, the |List| or |Dictionary| that was filtered. - When an error is encountered while evaluating {string} no - further items in {expr} are processed. +< Returns {expr1}, the |List| or |Dictionary| that was filtered. + When an error is encountered while evaluating {expr2} no + further items in {expr1} are processed. When {expr2} is a + Funcref errors inside a function are ignored, unless it was + defined with the "abort" flag. maparg({name}[, {mode} [, {abbr} [, {dict}]]]) *maparg()* @@ -4960,10 +5272,10 @@ maparg({name}[, {mode} [, {abbr} [, {dict}]]]) *maparg()* "" Normal, Visual and Operator-pending When {mode} is omitted, the modes for "" are used. - When {abbr} is there and it is non-zero use abbreviations + When {abbr} is there and it is |TRUE| use abbreviations instead of mappings. - When {dict} is there and it is non-zero return a dictionary + When {dict} is there and it is |TRUE| return a dictionary containing all the information of the mapping with the following items: "lhs" The {lhs} of the mapping. @@ -5130,7 +5442,8 @@ matchadd({group}, {pattern}[, {priority}[, {id} [, {dict}]]]) available from |getmatches()|. All matches can be deleted in one operation by |clearmatches()|. -matchaddpos({group}, {pos}[, {priority}[, {id}[, {dict}]]]) *matchaddpos()* + *matchaddpos()* +matchaddpos({group}, {pos}[, {priority}[, {id}[, {dict}]]]) Same as |matchadd()|, but requires a list of positions {pos} instead of a pattern. This command is faster than |matchadd()| because it does not require to handle regular expressions and @@ -5244,16 +5557,65 @@ matchstrpos({expr}, {pat}[, {start}[, {count}]]) *matchstrpos()* The type isn't changed, it's not necessarily a String. *max()* -max({list}) Return the maximum value of all items in {list}. - If {list} is not a list or one of the items in {list} cannot - be used as a Number this results in an error. - An empty |List| results in zero. +max({expr}) Return the maximum value of all items in {expr}. + {expr} can be a list or a dictionary. For a dictionary, + it returns the maximum of all values in the dictionary. + If {expr} is neither a list nor a dictionary, or one of the + items in {expr} cannot be used as a Number this results in + an error. An empty |List| or |Dictionary| results in zero. + +menu_get({path}, {modes}) *menu_get()* + Returns a |List| of |Dictionaries| describing |menus| (defined + by |:menu|, |:amenu|, etc.). + {path} limits the result to a subtree of the menu hierarchy + (empty string matches all menus). E.g. to get items in the + "File" menu subtree: > + :echo menu_get('File','') +< + {modes} is a string of zero or more modes (see |maparg()| or + |creating-menus| for the list of modes). "a" means "all". + + For example: > + nnoremenu &Test.Test inormal + inoremenu Test.Test insert + vnoremenu Test.Test x + echo menu_get("") +< + returns something like this: +> + [ { + "hidden": 0, + "name": "Test", + "priority": 500, + "shortcut": 84, + "submenus": [ { + "hidden": 0, + "mappings": { + i": { + "enabled": 1, + "noremap": 1, + "rhs": "insert", + "sid": 1, + "silent": 0 + }, + n": { ... }, + s": { ... }, + v": { ... } + }, + "name": "Test", + "priority": 500, + "shortcut": 0 + } ] + } ] +< *min()* -min({list}) Return the minimum value of all items in {list}. - If {list} is not a list or one of the items in {list} cannot - be used as a Number this results in an error. - An empty |List| results in zero. +min({expr}) Return the minimum value of all items in {expr}. + {expr} can be a list or a dictionary. For a dictionary, + it returns the minimum of all values in the dictionary. + If {expr} is neither a list nor a dictionary, or one of the + items in {expr} cannot be used as a Number this results in + an error. An empty |List| or |Dictionary| results in zero. *mkdir()* *E739* mkdir({name} [, {path} [, {prot}]]) @@ -5277,8 +5639,7 @@ mkdir({name} [, {path} [, {prot}]]) mode([expr]) Return a string that indicates the current mode. If [expr] is supplied and it evaluates to a non-zero Number or a non-empty String (|non-zero-arg|), then the full mode is - returned, otherwise only the first letter is returned. Note - that " " and "0" are also non-empty strings. + returned, otherwise only the first letter is returned. n Normal no Operator-pending @@ -5485,12 +5846,14 @@ printf({fmt}, {expr1} ...) *printf()* %04x hex number padded with zeros to at least 4 characters %X hex number using upper case letters %o octal number - %f floating point number in the form 123.456 - %e floating point number in the form 1.234e3 - %E floating point number in the form 1.234E3 + %f floating point number as 12.23, inf, -inf or nan + %F floating point number as 12.23, INF, -INF or NAN + %e floating point number as 1.23e3, inf, -inf or nan + %E floating point number as 1.23E3, INF, -INF or NAN %g floating point number, as %f or %e depending on value - %G floating point number, as %f or %E depending on value + %G floating point number, as %F or %E depending on value %% the % character itself + %p representation of the pointer to the container Conversion specifications start with '%' and end with the conversion type. All other characters are copied unchanged to @@ -5599,6 +5962,9 @@ printf({fmt}, {expr1} ...) *printf()* s The text of the String argument is used. If a precision is specified, no more bytes than the number specified are used. + If the argument is not a String type, it is + automatically converted to text with the same format + as ":echo". *printf-S* S The text of the String argument is used. If a precision is specified, no more display cells than the @@ -5611,8 +5977,9 @@ printf({fmt}, {expr1} ...) *printf()* digits after the decimal point. When the precision is zero the decimal point is omitted. When the precision is not specified 6 is used. A really big number - (out of range or dividing by zero) results in "inf". - "0.0 / 0.0" results in "nan". + (out of range or dividing by zero) results in "inf" + or "-inf" with %f (INF or -INF with %F). + "0.0 / 0.0" results in "nan" with %f (NAN with %F). Example: > echo printf("%.2f", 12.115) < 12.12 @@ -5700,9 +6067,9 @@ range({expr} [, {max} [, {stride}]]) *range()* *readfile()* readfile({fname} [, {binary} [, {max}]]) Read file {fname} and return a |List|, each line of the file - as an item. Lines broken at NL characters. Macintosh files - separated with CR will result in a single long line (unless a - NL appears somewhere). + as an item. Lines are broken at NL characters. Macintosh + files separated with CR will result in a single long line + (unless a NL appears somewhere). All NUL characters are replaced with a NL character. When {binary} contains "b" binary mode is used: - When the last line ends in a NL an extra empty list item is @@ -5945,7 +6312,7 @@ rpcstop({channel}) {Nvim} *rpcstop()* connecting to |v:servername|. screenattr(row, col) *screenattr()* - Like screenchar(), but return the attribute. This is a rather + Like |screenchar()|, but return the attribute. This is a rather arbitrary number that can only be used to compare to the attribute at other positions. @@ -5976,6 +6343,7 @@ screenrow() *screenrow()* The result is a Number, which is the current screen row of the cursor. The top line has number one. This function is mainly used for testing. + Alternatively you can use |winline()|. Note: Same restrictions as with |screencol()|. @@ -6219,11 +6587,32 @@ serverlist() *serverlist()* nvim --cmd "echo serverlist()" --cmd "q" < serverstart([{address}]) *serverstart()* - Opens a named pipe or TCP socket at {address} for clients to - connect to and returns {address}. If no address is given, it - is equivalent to: > + Opens a socket or named pipe at {address} and listens for + |RPC| messages. Clients can send |API| commands to the address + to control Nvim. Returns the address string. + + If {address} does not contain a colon ":" it is interpreted as + a named pipe or Unix domain socket path. + + Example: > + if has('win32') + call serverstart('\\.\pipe\nvim-pipe-1234') + else + call serverstart('nvim.sock') + endif +< + If {address} contains a colon ":" it is interpreted as a TCP + address where the last ":" separates the host and port. + Assigns a random port if it is empty or 0. Supports IPv4/IPv6. + + Example: > + :call serverstart('::1:12345') +< + If no address is given, it is equivalent to: > :call serverstart(tempname()) + < |$NVIM_LISTEN_ADDRESS| is set to {address} if not already set. + *--servername* The Vim command-line option `--servername` can be imitated: > nvim --cmd "let g:server_addr = serverstart('foo')" @@ -6318,18 +6707,20 @@ setline({lnum}, {text}) *setline()* :endfor < Note: The '[ and '] marks are not set. -setloclist({nr}, {list} [, {action}[, {title}]]) *setloclist()* +setloclist({nr}, {list} [, {action}[, {what}]]) *setloclist()* Create or replace or add to the location list for window {nr}. - {nr} can be the window number or the window ID. + {nr} can be the window number or the |window-ID|. When {nr} is zero the current window is used. For a location list window, the displayed location list is - modified. For an invalid window number {nr}, -1 is returned. If - {title} is given, it will be used to set |w:quickfix_title| - after opening the location window. + modified. For an invalid window number {nr}, -1 is returned. Otherwise, same as |setqflist()|. Also see |location-list|. + If the optional {what} dictionary argument is supplied, then + only the items listed in {what} are set. Refer to |setqflist()| + for the list of supported keys in {what}. + setmatches({list}) *setmatches()* Restores a list of matches saved by |getmatches()|. Returns 0 if successful, otherwise -1. All current matches are cleared @@ -6383,7 +6774,7 @@ setpos({expr}, {list}) |winrestview()|. -setqflist({list} [, {action}[, {title}]]) *setqflist()* +setqflist({list} [, {action}[, {what}]]) *setqflist()* Create or replace or add to the quickfix list using the items in {list}. Each item in {list} is a dictionary. Non-dictionary items in {list} are ignored. Each dictionary @@ -6431,6 +6822,20 @@ setqflist({list} [, {action}[, {title}]]) *setqflist()* If {title} is given, it will be used to set |w:quickfix_title| after opening the quickfix window. + If the optional {what} dictionary argument is supplied, then + only the items listed in {what} are set. The first {list} + argument is ignored. The following items can be specified in + {what}: + nr list number in the quickfix stack + title quickfix list title text + Unsupported keys in {what} are ignored. + If the "nr" item is not present, then the current quickfix list + is modified. + + Examples: > + :call setqflist([], 'r', {'title': 'My search'}) + :call setqflist([], 'r', {'nr': 2, 'title': 'Errors'}) +< Returns zero for success, -1 for failure. This function can be used to create a quickfix list @@ -6453,6 +6858,8 @@ setreg({regname}, {value} [, {options}]) used as the width of the selection - if it is not specified then the width of the block is set to the number of characters in the longest line (counting a <Tab> as 1 character). + If {options} contains "u" or '"', then the unnamed register is + set to point to register {regname}. If {options} contains no register settings, then the default is to use character mode unless {value} ends in a <NL> for @@ -6496,7 +6903,7 @@ settabwinvar({tabnr}, {winnr}, {varname}, {val}) *settabwinvar()* {val}. Tabs are numbered starting with one. For the current tabpage use |setwinvar()|. - {winnr} can be the window number or the window ID. + {winnr} can be the window number or the |window-ID|. When {winnr} is zero the current window is used. This also works for a global or local buffer option, but it doesn't work for a global or local buffer variable. @@ -6522,8 +6929,8 @@ shellescape({string} [, {special}]) *shellescape()* On Windows when 'shellslash' is not set, it will enclose {string} in double quotes and double all double quotes within {string}. - For other systems, it will enclose {string} in single quotes - and replace all "'" with "'\''". + Otherwise, it will enclose {string} in single quotes and + replace all "'" with "'\''". When the {special} argument is present and it's a non-zero Number or a non-empty String (|non-zero-arg|), then special items such as "!", "%", "#" and "<cword>" will be preceded by @@ -6597,6 +7004,21 @@ sinh({expr}) *sinh()* :echo sinh(-0.9) < -1.026517 +sockconnect({mode}, {address}, {opts}) *sockconnect()* + Connect a socket to an address. If {mode} is "pipe" then + {address} should be the path of a named pipe. If {mode} is + "tcp" then {address} should be of the form "host:port" where + the host should be an ip adderess or host name, and port the + port number. Currently only rpc sockets are supported, so + {opts} must be passed with "rpc" set to |TRUE|. + + {opts} is a dictionary with these keys: + rpc : If set, |msgpack-rpc| will be used to communicate + over the socket. + Returns: + - The channel ID on success, which is used by + |rpcnotify()| and |rpcrequest()| and |rpcstop()|. + - 0 on invalid arguments or connection failure. sort({list} [, {func} [, {dict}]]) *sort()* *E702* Sort the items in {list} in-place. Returns {list}. @@ -6802,7 +7224,7 @@ strcharpart({src}, {start}[, {len}]) *strcharpart()* Like |strpart()| but using character index and length instead of byte index and length. When a character index is used where a character does not - exist it is assumed to be one byte. For example: > + exist it is assumed to be one character. For example: > strcharpart('abc', -1, 2) < results in 'a'. @@ -6947,7 +7369,7 @@ strwidth({expr}) *strwidth()* Ambiguous, this function's return value depends on 'ambiwidth'. Also see |strlen()|, |strdisplaywidth()| and |strchars()|. -submatch({nr}[, {list}]) *submatch()* +submatch({nr}[, {list}]) *submatch()* *E935* Only for an expression in a |:substitute| command or substitute() function. Returns the {nr}'th submatch of the matched text. When {nr} @@ -6964,6 +7386,9 @@ submatch({nr}[, {list}]) *submatch()* |substitute()| this list will always contain one or zero items, since there are no real line breaks. + When substitute() is used recursively only the submatches in + the current (deepest) call can be obtained. + Example: > :s/\d\+/\=submatch(0) + 1/ < This finds the first number in the line and adds one to it. @@ -7002,6 +7427,14 @@ substitute({expr}, {pat}, {sub}, {flags}) *substitute()* :echo substitute(s, '%\(\x\x\)', \ '\=nr2char("0x" . submatch(1))', 'g') +< When {sub} is a Funcref that function is called, with one + optional argument. Example: > + :echo substitute(s, '%\(\x\x\)', SubNr, 'g') +< The optional argument is a list which contains the whole + matched string and up to nine submatches,like what + |submatch()| returns. Example: > + :echo substitute(s, '\(\x\x\)', {m -> '0x' . m[1]}, 'g') + synID({lnum}, {col}, {trans}) *synID()* The result is a Number, which is the syntax ID at the position {lnum} and {col} in the current window. @@ -7099,9 +7532,8 @@ synstack({lnum}, {col}) *synstack()* valid positions. system({cmd} [, {input}]) *system()* *E677* - Get the output of the shell command {cmd} as a |string|. {cmd} - will be run the same as in |jobstart()|. See |systemlist()| - to get the output as a |List|. + Get the output of {cmd} as a |string| (use |systemlist()| to + get a |List|). {cmd} is treated exactly as in |jobstart()|. Not to be used for interactive commands. If {input} is a string it is written to a pipe and passed as @@ -7155,16 +7587,16 @@ systemlist({cmd} [, {input} [, {keepempty}]]) *systemlist()* output separated by NL) with NULs transformed into NLs. Output is the same as |readfile()| will output with {binary} argument set to "b", except that a final newline is not preserved, - unless {keepempty} is present and it's non-zero. + unless {keepempty} is non-zero. + Note that on MS-Windows you may get trailing CR characters. - Returns an empty string on error, so be careful not to run - into |E706|. + Returns an empty string on error. tabpagebuflist([{arg}]) *tabpagebuflist()* The result is a |List|, where each item is the number of the buffer associated with each window in the current tab page. - {arg} specifies the number of tab page to be used. When + {arg} specifies the number of the tab page to be used. When omitted the current tab page is used. When {arg} is invalid the number zero is returned. To get a list of all buffers in all tabs use this: > @@ -7201,8 +7633,13 @@ tagfiles() Returns a |List| with the file names used to search for tags for the current buffer. This is the 'tags' option expanded. -taglist({expr}) *taglist()* +taglist({expr}[, {filename}]) *taglist()* Returns a list of tags matching the regular expression {expr}. + + If {filename} is passed it is used to prioritize the results + in the same way that |:tselect| does. See |tag-priority|. + {filename} should be the full path of the file. + Each list item is a dictionary with at least the following entries: name Name of the tag. @@ -7260,7 +7697,13 @@ termopen({cmd}[, {opts}]) {Nvim} *termopen()* and `$TERM` is set to "xterm-256color". Returns the same values as |jobstart()|. - See |terminal-emulator| for more information. + See |terminal| for more information. + +test_garbagecollect_now() *test_garbagecollect_now()* + Like garbagecollect(), but executed right away. This must + only be called directly to avoid any structure to exist + internally, and |v:testing| must have been set before calling + any function. tan({expr}) *tan()* Return the tangent of {expr}, measured in radians, as a |Float| @@ -7284,7 +7727,36 @@ tanh({expr}) *tanh()* < -0.761594 - *timer_start()* + *timer_info()* +timer_info([{id}]) + Return a list with information about timers. + When {id} is given only information about this timer is + returned. When timer {id} does not exist an empty list is + returned. + When {id} is omitted information about all timers is returned. + + For each timer the information is stored in a Dictionary with + these items: + "id" the timer ID + "time" time the timer was started with + "repeat" number of times the timer will still fire; + -1 means forever + "callback" the callback + +timer_pause({timer}, {paused}) *timer_pause()* + Pause or unpause a timer. A paused timer does not invoke its + callback when its time expires. Unpausing a timer may cause + the callback to be invoked almost immediately if enough time + has passed. + + Pausing a timer is useful to avoid the callback to be called + for a short time. + + If {paused} evaluates to a non-zero Number or a non-empty + String, then the timer is paused, otherwise it is unpaused. + See |non-zero-arg|. + + *timer_start()* *timer* *timers* timer_start({time}, {callback} [, {options}]) Create a timer and return the timer ID. @@ -7293,13 +7765,14 @@ timer_start({time}, {callback} [, {options}]) busy or Vim is not waiting for input the time will be longer. {callback} is the function to call. It can be the name of a - function or a Funcref. It is called with one argument, which + function or a |Funcref|. It is called with one argument, which is the timer ID. The callback is only invoked when Vim is waiting for input. {options} is a dictionary. Supported entries: "repeat" Number of times to repeat calling the - callback. -1 means forever. + callback. -1 means forever. When not present + the callback will be called once. Example: > func MyHandler(timer) @@ -7309,12 +7782,16 @@ timer_start({time}, {callback} [, {options}]) \ {'repeat': 3}) < This will invoke MyHandler() three times at 500 msec intervals. - {only available when compiled with the |+timers| feature} timer_stop({timer}) *timer_stop()* Stop a timer. The timer callback will no longer be invoked. {timer} is an ID returned by timer_start(), thus it must be a - Number. + Number. If {timer} does not exist there is no error. + +timer_stopall() *timer_stopall()* + Stop all timers. The timer callbacks will no longer be + invoked. Useful if some timers is misbehaving. If there are + no timers there is no error. tolower({expr}) *tolower()* The result is a copy of the String given, with all uppercase @@ -7353,16 +7830,18 @@ trunc({expr}) *trunc()* < 4.0 type({expr}) *type()* - The result is a Number, depending on the type of {expr}: - Number: 0 - String: 1 - Funcref: 2 - List: 3 - Dictionary: 4 - Float: 5 + The result is a Number representing the type of {expr}. + Instead of using the number directly, it is better to use the + v:t_ variable that has the value: + Number: 0 (|v:t_number|) + String: 1 (|v:t_string|) + Funcref: 2 (|v:t_func|) + List: 3 (|v:t_list|) + Dictionary: 4 (|v:t_dict|) + Float: 5 (|v:t_float|) Boolean: 6 (|v:true| and |v:false|) Null: 7 (|v:null|) - To avoid the magic numbers it should be used this way: > + For backward compatibility, this method can be used: > :if type(myvar) == type(0) :if type(myvar) == type("") :if type(myvar) == type(function("tr")) @@ -7373,6 +7852,8 @@ type({expr}) *type()* < In place of checking for |v:null| type it is better to check for |v:null| directly as it is the only value of this type: > :if myvar is v:null +< To check if the v:t_ variables exist use this: > + :if exists('v:t_number') undofile({name}) *undofile()* Return the name of the undo file that would be used for a file @@ -7495,16 +7976,12 @@ visualmode([expr]) *visualmode()* Visual mode that was used. If Visual mode is active, use |mode()| to get the Visual mode (e.g., in a |:vmap|). - *non-zero-arg* If [expr] is supplied and it evaluates to a non-zero Number or a non-empty String, then the Visual mode will be cleared and - the old value is returned. Note that " " and "0" are also - non-empty strings, thus cause the mode to be cleared. A List, - Dictionary or Float is not a Number or String, thus does not - cause the mode to be cleared. + the old value is returned. See |non-zero-arg|. wildmenumode() *wildmenumode()* - Returns non-zero when the wildmenu is active and zero + Returns |TRUE| when the wildmenu is active and |FALSE| otherwise. See 'wildmenu' and 'wildmode'. This can be used in mappings to handle the 'wildcharm' option gracefully. (Makes only sense with |mapmode-c| mappings). @@ -7516,11 +7993,11 @@ wildmenumode() *wildmenumode()* win_findbuf({bufnr}) *win_findbuf()* - Returns a list with window IDs for windows that contain buffer - {bufnr}. When there is none the list is empty. + Returns a list with |window-ID|s for windows that contain + buffer {bufnr}. When there is none the list is empty. win_getid([{win} [, {tab}]]) *win_getid()* - Get the window ID for the specified window. + Get the |window-ID| for the specified window. When {win} is missing use the current window. With {win} this is the window number. The top window has number 1. @@ -7545,7 +8022,7 @@ win_id2win({expr}) *win_id2win()* *winbufnr()* winbufnr({nr}) The result is a Number, which is the number of the buffer associated with window {nr}. {nr} can be the window number or - the window ID. + the |window-ID|. When {nr} is zero, the number of the buffer in the current window is returned. When window {nr} doesn't exist, -1 is returned. @@ -7559,7 +8036,7 @@ wincol() The result is a Number, which is the virtual column of the winheight({nr}) *winheight()* The result is a Number, which is the height of window {nr}. - {nr} can be the window number or the window ID. + {nr} can be the window number or the |window-ID|. When {nr} is zero, the height of the current window is returned. When window {nr} doesn't exist, -1 is returned. An existing window always has a height of zero or more. @@ -7585,7 +8062,7 @@ winnr([{arg}]) The result is a Number, which is the number of the current is returned. The number can be used with |CTRL-W_w| and ":wincmd w" |:wincmd|. - Also see |tabpagewinnr()|. + Also see |tabpagewinnr()| and |win_getid()|. *winrestcmd()* winrestcmd() Returns a sequence of |:resize| commands that should restore @@ -7639,7 +8116,7 @@ winsaveview() Returns a |Dictionary| that contains information to restore winwidth({nr}) *winwidth()* The result is a Number, which is the width of window {nr}. - {nr} can be the window number or the window ID. + {nr} can be the window number or the |window-ID|. When {nr} is zero, the width of the current window is returned. When window {nr} doesn't exist, -1 is returned. An existing window always has a width of zero or more. @@ -7648,7 +8125,10 @@ winwidth({nr}) *winwidth()* :if winwidth(0) <= 50 : exe "normal 50\<C-W>|" :endif -< +< For getting the terminal or screen size, see the 'columns' + option. + + wordcount() *wordcount()* The result is a dictionary of byte/chars/word statistics for the current buffer. This is the same info as provided by @@ -7684,6 +8164,12 @@ writefile({list}, {fname} [, {flags}]) appended to the file: > :call writefile(["foo"], "event.log", "a") :call writefile(["bar"], "event.log", "a") +< + When {flags} contains "S" fsync() call is not used, with "s" + it is used, 'fsync' option applies by default. No fsync() + means that writefile() will finish faster, but writes may be + left in OS buffers and not yet written to disk. Such changes + will disappear if system crashes before OS does writing. All NL characters are replaced with a NUL character. Inserting CR characters needs to be done before passing {list} @@ -7713,7 +8199,7 @@ There are four types of features: :if has("cindent") 2. Features that are only supported when certain conditions have been met. Example: > - :if has("gui_running") + :if has("win32") < *has-patch* 3. {Nvim} version. The "nvim-1.2.3" feature means that the Nvim version is 1.2.3 or later. Example: > @@ -7736,6 +8222,10 @@ There are four types of features: < Note that it's possible for patch 147 to be omitted even though 148 is included. +Hint: To find out if Vim supports backslashes in a file name (MS-Windows), +use: `if exists('+shellslash')` + + acl Compiled with |ACL| support. arabic Compiled with Arabic support |Arabic|. autocmd Compiled with autocommand support. |autocommand| @@ -7744,17 +8234,14 @@ browse Compiled with |:browse| support, and browse() will browsefilter Compiled with support for |browsefilter|. byte_offset Compiled with support for 'o' in 'statusline' cindent Compiled with 'cindent' support. -clientserver Compiled with remote invocation support |clientserver|. clipboard Compiled with 'clipboard' support. cmdline_compl Compiled with |cmdline-completion| support. cmdline_hist Compiled with |cmdline-history| support. cmdline_info Compiled with 'showcmd' and 'ruler' support. comments Compiled with |'comments'| support. -compatible Compiled to be very Vi compatible. cscope Compiled with |cscope| support. debug Compiled with "DEBUG" defined. dialog_con Compiled with console dialog support. -dialog_gui Compiled with GUI dialog support. digraphs Compiled with support for digraphs. eval Compiled with expression evaluation support. Always true, of course! @@ -7772,14 +8259,12 @@ fname_case Case in file names matters (for Windows this is not present). folding Compiled with |folding| support. gettext Compiled with message translation |multi-lang| -gui Compiled with GUI enabled. -gui_running Vim is running in the GUI, or it will start soon. -gui_win32 Compiled with MS Windows Win32 GUI. iconv Can use iconv() for conversion. insert_expand Compiled with support for CTRL-X expansion commands in Insert mode. jumplist Compiled with |jumplist| support. keymap Compiled with 'keymap' support. +lambda Compiled with |lambda| support. langmap Compiled with 'langmap' support. libcall Compiled with |libcall()| support. linebreak Compiled with 'linebreak', 'breakat', 'showbreak' and @@ -7788,8 +8273,7 @@ lispindent Compiled with support for lisp indenting. listcmds Compiled with commands for the buffer list |:files| and the argument list |arglist|. localmap Compiled with local mappings and abbr. |:map-local| -mac Macintosh version of Vim. -macunix Macintosh version of Vim, using Unix files (OS-X). +mac macOS version of Vim. menu Compiled with support for |:menu|. mksession Compiled with support for |:mksession|. modify_fname Compiled with file name modifiers. |filename-modifiers| @@ -7797,17 +8281,16 @@ mouse Compiled with support mouse. mouseshape Compiled with support for 'mouseshape'. multi_byte Compiled with support for 'encoding' multi_byte_encoding 'encoding' is set to a multi-byte encoding. -multi_byte_ime Compiled with support for IME input method. multi_lang Compiled with support for multiple languages. +num64 Compiled with 64-bit |Number| support. nvim This is Nvim. |has-patch| -ole Compiled with OLE automation support for Win32. path_extra Compiled with up/downwards search in 'path' and 'tags' persistent_undo Compiled with support for persistent undo history. postscript Compiled with PostScript file printing. printer Compiled with |:hardcopy| support. profile Compiled with |:profile| support. -python Compiled with Python 2.x interface. |has-python| -python3 Compiled with Python 3.x interface. |has-python| +python Legacy Vim Python 2.x API is available. |has-python| +python3 Legacy Vim Python 3.x API is available. |has-python| quickfix Compiled with |quickfix| support. reltime Compiled with |reltime()| support. rightleft Compiled with 'rightleft' support. @@ -7830,15 +8313,12 @@ tag_old_static Compiled with support for old static tags |tag-old-static|. tag_any_white Compiled with support for any white characters in tags files |tag-any-white|. -terminfo Compiled with terminfo instead of termcap. termresponse Compiled with support for |t_RV| and |v:termresponse|. textobjects Compiled with support for |text-objects|. -tgetent Compiled with tgetent support, able to use a termcap - or terminfo file. timers Compiled with |timer_start()| support. title Compiled with window title support |'title'|. -toolbar Compiled with support for |gui-toolbar|. unix Unix version of Vim. +unnamedplus Compiled with support for "unnamedplus" in 'clipboard' user_commands User-defined commands. vertsplit Compiled with vertically split windows |:vsplit|. vim_starting True while initial source'ing takes place. |startup| @@ -7851,17 +8331,9 @@ vreplace Compiled with |gR| and |gr| commands. wildignore Compiled with 'wildignore' option. wildmenu Compiled with 'wildmenu' option. win32 Windows version of Vim (32 or 64 bit). -win32unix Windows version of Vim, using Unix files (Cygwin). -win64 Windows version of Vim (64 bit). winaltkeys Compiled with 'winaltkeys' option. windows Compiled with support for more than one window. writebackup Compiled with 'writebackup' default on. -xfontset Compiled with X fontset support |xfontset|. -xim Compiled with X input method support |xim|. -xpm Compiled with pixmap support. -xpm_w32 Compiled with pixmap support for Win32. (Only for - backward compatibility. Use "xpm" instead.) -x11 Compiled with X11 support. *string-match* Matching a pattern in a String @@ -7931,7 +8403,7 @@ last defined. Example: > See |:verbose-cmd| for more information. *E124* *E125* *E853* *E884* -:fu[nction][!] {name}([arguments]) [range] [abort] [dict] +:fu[nction][!] {name}([arguments]) [range] [abort] [dict] [closure] Define a new function by the name {name}. The name must be made of alphanumeric characters and '_', and must start with a capital or "s:" (see above). Note @@ -7974,6 +8446,28 @@ See |:verbose-cmd| for more information. be invoked through an entry in a |Dictionary|. The local variable "self" will then be set to the dictionary. See |Dictionary-function|. + *:func-closure* *E932* + When the [closure] argument is added, the function + can access variables and arguments from the outer + scope. This is usually called a closure. In this + example Bar() uses "x" from the scope of Foo(). It + remains referenced even after Foo() returns: > + :function! Foo() + : let x = 0 + : function! Bar() closure + : let x += 1 + : return x + : endfunction + : return funcref('Bar') + :endfunction + + :let F = Foo() + :echo F() +< 1 > + :echo F() +< 2 > + :echo F() +< 3 *function-search-undo* The last used search pattern and the redo command "." @@ -7985,7 +8479,7 @@ See |:verbose-cmd| for more information. :endf[unction] The end of a function definition. Must be on a line by its own, without other commands. - *:delf* *:delfunction* *E130* *E131* + *:delf* *:delfunction* *E130* *E131* *E933* :delf[unction] {name} Delete function {name}. {name} can also be a |Dictionary| entry that is a |Funcref|: > @@ -8021,10 +8515,10 @@ can be 0). "a:000" is set to a |List| that contains these arguments. Note that "a:1" is the same as "a:000[0]". *E742* The a: scope and the variables in it cannot be changed, they are fixed. -However, if a |List| or |Dictionary| is used, you can change their contents. -Thus you can pass a |List| to a function and have the function add an item to -it. If you want to make sure the function cannot change a |List| or -|Dictionary| use |:lockvar|. +However, if a composite type is used, such as |List| or |Dictionary| , you can +change their contents. Thus you can pass a |List| to a function and have the +function add an item to it. If you want to make sure the function cannot +change a |List| or |Dictionary| use |:lockvar|. When not using "...", the number of arguments in a function call must be equal to the number of named arguments. When using "...", the number of arguments @@ -8036,9 +8530,8 @@ until the matching |:endfunction|. It is allowed to define another function inside a function body. *local-variables* -Inside a function variables can be used. These are local variables, which -will disappear when the function returns. Global variables need to be -accessed with "g:". +Inside a function local variables can be used. These will disappear when the +function returns. Global variables need to be accessed with "g:". Example: > :function Table(title, ...) @@ -8312,6 +8805,11 @@ This does NOT work: > value and the global value are changed. Example: > :let &path = &path . ',/usr/local/include' +< This also works for terminal codes in the form t_xx. + But only for alphanumerical names. Example: > + :let &t_k1 = "\<Esc>[234;" +< When the code does not exist yet it will be created as + a terminal key code, there is no error. :let &{option-name} .= {expr1} For a string option: Append {expr1} to the value. @@ -8419,9 +8917,12 @@ This does NOT work: > :lockvar v :let v = 'asdf' " fails! :unlet v -< *E741* +< *E741* *E940* If you try to change a locked variable you get an - error message: "E741: Value is locked: {name}" + error message: "E741: Value is locked: {name}". + If you try to lock or unlock a built-in variable you + will get an error message "E940: Cannot lock or unlock + variable {name}". [depth] is relevant when locking a |List| or |Dictionary|. It specifies how deep the locking goes: diff --git a/runtime/doc/farsi.txt b/runtime/doc/farsi.txt index b85c0a357c..a824c469b0 100644 --- a/runtime/doc/farsi.txt +++ b/runtime/doc/farsi.txt @@ -1,4 +1,4 @@ -*farsi.txt* For Vim version 7.4. Last change: 2010 Aug 07 +*farsi.txt* Nvim VIM REFERENCE MANUAL by Mortaza Ghassab Shiran diff --git a/runtime/doc/filetype.txt b/runtime/doc/filetype.txt index 336d9681ed..64d9c6daa9 100644 --- a/runtime/doc/filetype.txt +++ b/runtime/doc/filetype.txt @@ -1,4 +1,4 @@ -*filetype.txt* For Vim version 7.4. Last change: 2015 Dec 06 +*filetype.txt* Nvim VIM REFERENCE MANUAL by Bram Moolenaar @@ -6,12 +6,10 @@ Filetypes *filetype* *file-type* -1. Filetypes |filetypes| -2. Filetype plugin |filetype-plugins| -3. Docs for the default filetype plugins. |ftplugin-docs| - Also see |autocmd.txt|. + Type <M-]> to see the table of contents. + ============================================================================== 1. Filetypes *filetypes* *file-types* @@ -542,6 +540,7 @@ K or CTRL-] Jump to the manpage for the <cWORD> under the cursor. Takes a count for the section. CTRL-T Jump back to the location that the manpage was opened from. +META-] Show the manpage outline in the |location-list|. q :quit if invoked as $MANPAGER, otherwise :close. Variables: @@ -565,6 +564,17 @@ These maps can be disabled with > :let g:no_pdf_maps = 1 < +PYTHON *ft-python-plugin* *PEP8* + +By default the following options are set, in accordance with PEP8: > + + setlocal expandtab shiftwidth=4 softtabstop=4 tabstop=8 + +To disable this behaviour, set the following variable in your vimrc: > + + let g:python_recommended_style = 0 + + RPM SPEC *ft-spec-plugin* Since the text for this plugin is rather long it has been put in a separate diff --git a/runtime/doc/fold.txt b/runtime/doc/fold.txt index 680e3270f2..88dde9f61d 100644 --- a/runtime/doc/fold.txt +++ b/runtime/doc/fold.txt @@ -1,4 +1,4 @@ -*fold.txt* For Vim version 7.4. Last change: 2016 Jan 02 +*fold.txt* Nvim VIM REFERENCE MANUAL by Bram Moolenaar @@ -9,10 +9,7 @@ Folding *Folding* *folding* *folds* You can find an introduction on folding in chapter 28 of the user manual. |usr_28.txt| -1. Fold methods |fold-methods| -2. Fold commands |fold-commands| -3. Fold options |fold-options| -4. Behavior of folds |fold-behavior| + Type <M-]> to see the table of contents. ============================================================================== 1. Fold methods *fold-methods* diff --git a/runtime/doc/ft_ada.txt b/runtime/doc/ft_ada.txt index 1e81acff67..94d97b481a 100644 --- a/runtime/doc/ft_ada.txt +++ b/runtime/doc/ft_ada.txt @@ -1,4 +1,4 @@ -*ft_ada.txt* For Vim version 7.4. Last change: 2010 Jul 20 +*ft_ada.txt* Nvim ADA FILE TYPE PLUG-INS REFERENCE MANUAL~ diff --git a/runtime/doc/ft_sql.txt b/runtime/doc/ft_sql.txt index 75c55269ef..29268f5753 100644 --- a/runtime/doc/ft_sql.txt +++ b/runtime/doc/ft_sql.txt @@ -1,4 +1,4 @@ -*ft_sql.txt* For Vim version 7.4. Last change: 2013 May 15 +*ft_sql.txt* Nvim by David Fishburn diff --git a/runtime/doc/gui.txt b/runtime/doc/gui.txt index 1e8bb408d9..b66a60c860 100644 --- a/runtime/doc/gui.txt +++ b/runtime/doc/gui.txt @@ -1,4 +1,4 @@ -*gui.txt* For Vim version 7.4. Last change: 2014 Mar 08 +*gui.txt* Nvim VIM REFERENCE MANUAL by Bram Moolenaar @@ -6,34 +6,17 @@ Vim's Graphical User Interface *gui* *GUI* -1. Starting the GUI |gui-start| -2. Scrollbars |gui-scrollbars| -3. Mouse Control |gui-mouse| -4. Making GUI Selections |gui-selections| -5. Menus |menus| -6. Extras |gui-extras| - -Other GUI documentation: -|gui_w32.txt| For specific items of the Win32 GUI. + Type <M-]> to see the table of contents. ============================================================================== 1. Starting the GUI *gui-start* *E229* *E233* -First you must make sure you actually have a version of Vim with the GUI code -included. - -How to start the GUI depends on the system used. Mostly you can run the -GUI version of Vim with: - gvim [options] [files...] - *ginit.vim* *gui-init* *gvimrc* *$MYGVIMRC* The gvimrc file is where GUI-specific startup commands should be placed. It is always sourced after the |init.vim| file. If you have one then the $MYGVIMRC environment variable has its name. When the GUI starts up initializations are carried out, in this order: -- The 'term' option is set to "builtin_gui" and terminal options are reset to - their default value for the GUI |terminal-options|. - If the system menu file exists, it is sourced. The name of this file is normally "$VIMRUNTIME/menu.vim". You can check this with ":version". Also see |$VIMRUNTIME|. To skip loading the system menu include 'M' in @@ -83,28 +66,6 @@ Recommended place for your personal GUI initializations: The personal initialization files are searched in the order specified above and only the first one that is found is read. -There are a number of options which only have meaning in the GUI version of -Vim. These are 'guicursor', 'guifont', and 'guioptions'. They are -documented in |options.txt| with all the other options. - -Another way to set the colors for different occasions is with highlight -groups. The "Normal" group is used to set the background and foreground -colors. Example (which looks nice): > - - :highlight Normal guibg=grey90 - -The "guibg" and "guifg" settings override the normal background and -foreground settings. The other settings for the Normal highlight group are -not used. Use the 'guifont' option to set the font. - -Also check out the 'guicursor' option, to set the colors for the cursor in -various modes. - -Vim tries to make the window fit on the screen when it starts up. This avoids -that you can't see part of it. On the X Window System this requires a bit of -guesswork. You can change the height that is used for the window title and a -task bar with the 'guiheadroom' option. - *:winp* *:winpos* *E188* :winp[os] Display current position of the top left corner of the GUI vim @@ -114,8 +75,7 @@ task bar with the 'guiheadroom' option. :winp[os] {X} {Y} *E466* Put the GUI vim window at the given {X} and {Y} coordinates. The coordinates should specify the position in pixels of the - top left corner of the window. Does not work in all versions. - Does work in an (new) xterm |xterm-color|. + top left corner of the window. When the GUI window has not been opened yet, the values are remembered until the window is opened. The position is adjusted to make the window fit on the screen (if possible). @@ -124,21 +84,6 @@ task bar with the 'guiheadroom' option. :win[size] {width} {height} Set the window height to {width} by {height} characters. Obsolete, use ":set lines=11 columns=22". - If you get less lines than expected, check the 'guiheadroom' - option. - -If you are running the X Window System, you can get information about the -window Vim is running in with these commands: > - :!xwininfo -id $WINDOWID - :!xprop -id $WINDOWID - :execute '!xwininfo -id ' . v:windowid - :execute '!xprop -id ' . v:windowid -< - *gui-IME* *iBus* -Input methods for international characters in X that rely on the XIM -framework, most notably iBus, have been known to produce undesirable results -in gVim. These may include an inability to enter spaces, or long delays -between typing a character and it being recognized by the application. ============================================================================== 2. Scrollbars *gui-scrollbars* @@ -545,9 +490,6 @@ expression register: > :amenu Insert.foobar "='foobar'<CR>P -Note that the '<' and 'k' flags in 'cpoptions' also apply here (when -included they make the <> form and raw key codes not being recognized). - Note that <Esc> in Cmdline mode executes the command, like in a mapping. This is Vi compatible. Use CTRL-C to quit Cmdline mode. @@ -559,21 +501,13 @@ The ":set ic" will not be echoed when using this menu. Messages from the executed command are still given though. To shut them up too, add a ":silent" in the executed command: > :menu <silent> Search.Header :exe ":silent normal /Header\r"<CR> -"<silent>" may also appear just after "<special>" or "<script>". - - *:menu-<special>* *:menu-special* -Define a menu with <> notation for special keys, even though the "<" flag -may appear in 'cpoptions'. This is useful if the side effect of setting -'cpoptions' is not desired. Example: > - :menu <special> Search.Header /Header<CR> -"<special>" must appear as the very first argument to the ":menu" command or -just after "<silent>" or "<script>". +"<silent>" may also appear just after "<script>". *:menu-<script>* *:menu-script* The "to" part of the menu will be inspected for mappings. If you don't want this, use the ":noremenu" command (or the similar one for a specific mode). If you do want to use script-local mappings, add "<script>" as the very first -argument to the ":menu" command or just after "<silent>" or "<special>". +argument to the ":menu" command or just after "<silent>". *menu-priority* You can give a priority to a menu. Menus with a higher priority go more to @@ -909,30 +843,4 @@ This section describes other features which are related to the GUI. - In the GUI, several normal keys may have modifiers in mappings etc, these are <Space>, <Tab>, <NL>, <CR>, <Esc>. -- To check in a Vim script if the GUI is being used, you can use something - like this: > - - if has("gui_running") - echo "yes, we have a GUI" - else - echo "Boring old console" - endif -< *setting-guifont* -- When you use the same vimrc file on various systems, you can use something - like this to set options specifically for each type of GUI: > - - if has("gui_running") - if has("gui_gtk2") - :set guifont=Luxi\ Mono\ 12 - elseif has("x11") - " Also for GTK 1 - :set guifont=*-lucidatypewriter-medium-r-normal-*-*-180-*-*-m-*-* - elseif has("gui_win32") - :set guifont=Luxi_Mono:h12:cANSI - endif - endif - -A recommended Japanese font is MS Mincho. You can find info here: -http://www.lexikan.com/mincho.htm - vim:tw=78:sw=4:ts=8:ft=help:norl: diff --git a/runtime/doc/hebrew.txt b/runtime/doc/hebrew.txt index 7bc8f02e7f..642d80adc7 100644 --- a/runtime/doc/hebrew.txt +++ b/runtime/doc/hebrew.txt @@ -1,4 +1,4 @@ -*hebrew.txt* For Vim version 7.4. Last change: 2007 Jun 14 +*hebrew.txt* Nvim VIM REFERENCE MANUAL by Ron Aaron (and Avner Lottem) diff --git a/runtime/doc/help.txt b/runtime/doc/help.txt index a81d32831b..1eda111297 100644 --- a/runtime/doc/help.txt +++ b/runtime/doc/help.txt @@ -1,4 +1,4 @@ -*help.txt* For Vim version 7.4. Last change: 2016 Mar 31 +*help.txt* Nvim VIM - main help file k @@ -96,8 +96,7 @@ General subjects ~ |howto.txt| how to do the most common editing tasks |tips.txt| various tips on using Vim |message.txt| (error) messages and explanations -|quotes.txt| remarks from users of Vim -|develop.txt| development of Vim +|develop.txt| development of Nvim |debug.txt| debugging Vim itself |uganda.txt| Vim distribution conditions and what to do with your money @@ -135,7 +134,6 @@ Advanced editing ~ Special issues ~ |print.txt| printing |remote.txt| using Vim as a server or client -|term.txt| using different terminals and mice |digraph.txt| list of available digraphs |mbyte.txt| multi-byte text support |mlang.txt| non-English language support @@ -149,28 +147,22 @@ Special issues ~ GUI ~ |gui.txt| Graphical User Interface (GUI) -|gui_w32.txt| Win32 GUI Interfaces ~ |if_cscop.txt| using Cscope with Vim |if_pyth.txt| Python interface |if_ruby.txt| Ruby interface -|debugger.txt| Interface with a debugger |sign.txt| debugging signs Versions ~ |vim_diff.txt| Main differences between Nvim and Vim |vi_diff.txt| Main differences between Vim and Vi - *sys-file-list* -Remarks about specific systems ~ -|os_win32.txt| MS-Windows *standard-plugin-list* Standard plugins ~ |pi_gzip.txt| Reading and writing compressed files |pi_netrw.txt| Reading and writing files over a network |pi_paren.txt| Highlight matching parens |pi_tar.txt| Tar file explorer -|pi_vimball.txt| Create a self-installing Vim script |pi_zip.txt| Zip archive explorer LOCAL ADDITIONS: *local-additions* diff --git a/runtime/doc/helphelp.txt b/runtime/doc/helphelp.txt index ca341af200..5948b24667 100644 --- a/runtime/doc/helphelp.txt +++ b/runtime/doc/helphelp.txt @@ -1,4 +1,4 @@ -*helphelp.txt* For Vim version 7.4. Last change: 2016 Apr 01 +*helphelp.txt* Nvim VIM REFERENCE MANUAL by Bram Moolenaar @@ -6,9 +6,7 @@ Help on help files *helphelp* -1. Help commands |online-help| -2. Translated help files |help-translated| -3. Writing help files |help-writing| + Type <M-]> to see the table of contents. ============================================================================== 1. Help commands *online-help* @@ -25,12 +23,20 @@ Help on help files *helphelp* The 'helplang' option is used to select a language, if the main help file is available in several languages. + Type <M-]> to see the table of contents. + *{subject}* *E149* *E661* :h[elp] {subject} Like ":help", additionally jump to the tag {subject}. - {subject} can include wildcards like "*", "?" and + For example: > + :help options + +< {subject} can include wildcards such as "*", "?" and "[a-z]": :help z? jump to help for any "z" command :help z. jump to the help for "z." + But when a tag exists it is taken literally: + :help :? jump to help for ":?" + If there is no full match for the pattern, or there are several matches, the "best" match will be used. A sophisticated algorithm is used to decide which @@ -67,18 +73,19 @@ Help on help files *helphelp* example to find help for CTRL-V in Insert mode: > :help i^V < - To use a regexp |pattern|, first do ":help" and then + It is also possible to first do ":help" and then use ":tag {pattern}" in the help window. The ":tnext" command can then be used to jump to other matches, "tselect" to list matches and choose one. > - :help index| :tse z. + :help index + :tselect /.*mode < When there is no argument you will see matches for "help", to avoid listing all possible matches (that would be very slow). The number of matches displayed is limited to 300. - This command can be followed by '|' and another + The `:help` command can be followed by '|' and another command, but you don't need to escape the '|' inside a help command. So these both work: > :help | @@ -185,7 +192,7 @@ command: > < *:helpt* *:helptags* - *E154* *E150* *E151* *E152* *E153* *E670* + *E154* *E150* *E151* *E152* *E153* *E670* *E856* :helpt[ags] [++t] {dir} Generate the help tags file(s) for directory {dir}. When {dir} is ALL then all "doc" directories in diff --git a/runtime/doc/howto.txt b/runtime/doc/howto.txt index 03ae3dbd8d..33c8552463 100644 --- a/runtime/doc/howto.txt +++ b/runtime/doc/howto.txt @@ -1,4 +1,4 @@ -*howto.txt* For Vim version 7.4. Last change: 2006 Apr 02 +*howto.txt* Nvim VIM REFERENCE MANUAL by Bram Moolenaar diff --git a/runtime/doc/if_cscop.txt b/runtime/doc/if_cscop.txt index 7482f5eebb..831b2c9840 100644 --- a/runtime/doc/if_cscop.txt +++ b/runtime/doc/if_cscop.txt @@ -1,4 +1,4 @@ -*if_cscop.txt* For Vim version 7.4. Last change: 2011 Jun 12 +*if_cscop.txt* Nvim VIM REFERENCE MANUAL by Andy Kahn @@ -12,15 +12,7 @@ a cscope query is just like jumping to any tag; it is saved on the tag stack so that with the right keyboard mappings, you can jump back and forth between functions as you normally would with |tags|. -1. Cscope introduction |cscope-intro| -2. Cscope related commands |cscope-commands| -3. Cscope options |cscope-options| -4. How to use cscope in Vim |cscope-howtouse| -5. Limitations |cscope-limitations| -6. Suggested usage |cscope-suggestions| -7. Availability & Information |cscope-info| - -This is currently for Unix and Win32 only. + Type <M-]> to see the table of contents. ============================================================================== 1. Cscope introduction *cscope-intro* diff --git a/runtime/doc/if_lua.txt b/runtime/doc/if_lua.txt new file mode 100644 index 0000000000..c4efd57b45 --- /dev/null +++ b/runtime/doc/if_lua.txt @@ -0,0 +1,311 @@ +*if_lua.txt* Nvim + + + VIM REFERENCE MANUAL by Luis Carvalho + + +Lua Interface to Nvim *lua* *Lua* + + Type <M-]> to see the table of contents. + +============================================================================== +1. Importing modules *lua-require* + +Neovim lua interface automatically adjusts `package.path` and `package.cpath` +according to effective &runtimepath value. Adjustment happens after +'runtimepath' is changed. `package.path` is adjusted by simply appending +`/lua/?.lua` and `/lua/?/init.lua` to each directory from 'runtimepath' (`/` +is actually the first character of `package.config`). + +Similarly to `package.path`, modified directories from `runtimepath` are also +added to `package.cpath`. In this case, instead of appending `/lua/?.lua` and +`/lua/?/init.lua` to each runtimepath, all unique `?`-containing suffixes of +the existing `package.cpath` are used. Here is an example: + +1. Given that + - 'runtimepath' contains `/foo/bar,/xxx;yyy/baz,/abc`; + - initial (defined at compile time or derived from + `$LUA_CPATH`/`$LUA_INIT`) `package.cpath` contains + `./?.so;/def/ghi/a?d/j/g.elf;/def/?.so`. +2. It finds `?`-containing suffixes `/?.so`, `/a?d/j/g.elf` and `/?.so`, in + order: parts of the path starting from the first path component containing + question mark and preceding path separator. +3. The suffix of `/def/?.so`, namely `/?.so` is not unique, as itโs the same + as the suffix of the first path from `package.path` (i.e. `./?.so`). Which + leaves `/?.so` and `/a?d/j/g.elf`, in this order. +4. 'runtimepath' has three paths: `/foo/bar`, `/xxx;yyy/baz` and `/abc`. The + second one contains semicolon which is a paths separator so it is out, + leaving only `/foo/bar` and `/abc`, in order. +5. The cartesian product of paths from 4. and suffixes from 3. is taken, + giving four variants. In each variant `/lua` path segment is inserted + between path and suffix, leaving + + - `/foo/bar/lua/?.so` + - `/foo/bar/lua/a?d/j/g.elf` + - `/abc/lua/?.so` + - `/abc/lua/a?d/j/g.elf` + +6. New paths are prepended to the original `package.cpath`. + +The result will look like this: + + `/foo/bar,/xxx;yyy/baz,/abc` ('runtimepath') + ร `./?.so;/def/ghi/a?d/j/g.elf;/def/?.so` (`package.cpath`) + + = `/foo/bar/lua/?.so;/foo/bar/lua/a?d/j/g.elf;/abc/lua/?.so;/abc/lua/a?d/j/g.elf;./?.so;/def/ghi/a?d/j/g.elf;/def/?.so` + +Note: to keep up with 'runtimepath' updates paths added at previous update are +remembered and removed at the next update, while all paths derived from the +new 'runtimepath' are prepended as described above. This allows removing +paths when path is removed from 'runtimepath', adding paths when they are +added and reordering `package.path`/`package.cpath` content if 'runtimepath' +was reordered. + +Note 2: even though adjustments happens automatically Neovim does not track +current values of `package.path` or `package.cpath`. If you happened to +delete some paths from there you need to reset 'runtimepath' to make them +readded. Just running `let &runtimepath = &runtimepath` should work. + +Note 3: skipping paths from 'runtimepath' which contain semicolons applies +both to `package.path` and `package.cpath`. Given that there is a number of +badly written plugins using shell which will not work with paths containing +semicolons it is better to not have them in 'runtimepath' at all. + +------------------------------------------------------------------------------ +1.1. Example of the plugin which uses lua modules: *lua-require-example* + +The following example plugin adds a command `:MakeCharBlob` which transforms +current buffer into a long `unsigned char` array. Lua contains transformation +function in a module `lua/charblob.lua` which is imported in +`autoload/charblob.vim` (`require("charblob")`). Example plugin is supposed +to be put into any directory from 'runtimepath', e.g. `~/.config/nvim` (in +this case `lua/charblob.lua` means `~/.config/nvim/lua/charblob.lua`). + +autoload/charblob.vim: > + + function charblob#encode_buffer() + call setline(1, luaeval( + \ 'require("charblob").encode(unpack(_A))', + \ [getline(1, '$'), &textwidth, ' '])) + endfunction + +plugin/charblob.vim: > + + if exists('g:charblob_loaded') + finish + endif + let g:charblob_loaded = 1 + + command MakeCharBlob :call charblob#encode_buffer() + +lua/charblob.lua: > + + local function charblob_bytes_iter(lines) + local init_s = { + next_line_idx = 1, + next_byte_idx = 1, + lines = lines, + } + local function next(s, _) + if lines[s.next_line_idx] == nil then + return nil + end + if s.next_byte_idx > #(lines[s.next_line_idx]) then + s.next_line_idx = s.next_line_idx + 1 + s.next_byte_idx = 1 + return ('\n'):byte() + end + local ret = lines[s.next_line_idx]:byte(s.next_byte_idx) + if ret == ('\n'):byte() then + ret = 0 -- See :h NL-used-for-NUL. + end + s.next_byte_idx = s.next_byte_idx + 1 + return ret + end + return next, init_s, nil + end + + local function charblob_encode(lines, textwidth, indent) + local ret = { + 'const unsigned char blob[] = {', + indent, + } + for byte in charblob_bytes_iter(lines) do + -- .- space + number (width 3) + comma + if #(ret[#ret]) + 5 > textwidth then + ret[#ret + 1] = indent + else + ret[#ret] = ret[#ret] .. ' ' + end + ret[#ret] = ret[#ret] .. (('%3u,'):format(byte)) + end + ret[#ret + 1] = '};' + return ret + end + + return { + bytes_iter = charblob_bytes_iter, + encode = charblob_encode, + } + +============================================================================== +2. Commands *lua-commands* + + *:lua* +:[range]lua {chunk} + Execute Lua chunk {chunk}. + +Examples: +> + :lua vim.api.nvim_command('echo "Hello, Neovim!"') +< + +:[range]lua << {endmarker} +{script} +{endmarker} + Execute Lua script {script}. + Note: This command doesn't work when the Lua + feature wasn't compiled in. To avoid errors, see + |script-here|. + +{endmarker} must NOT be preceded by any white space. If {endmarker} is +omitted from after the "<<", a dot '.' must be used after {script}, like +for the |:append| and |:insert| commands. +This form of the |:lua| command is mainly useful for including Lua code +in Vim scripts. + +Example: +> + function! CurrentLineInfo() + lua << EOF + local linenr = vim.api.nvim_win_get_cursor(0)[1] + local curline = vim.api.nvim_buf_get_lines( + 0, linenr, linenr + 1, false)[1] + print(string.format("Current line [%d] has %d bytes", + linenr, #curline)) + EOF + endfunction + +Note that the variables are prefixed with `local`: they will disappear when +block finishes. This is not the case for globals. + +To see what version of Lua you have: > + :lua print(_VERSION) + +If you use LuaJIT you can also use this: > + :lua print(jit.version) +< + + *:luado* +:[range]luado {body} Execute Lua function "function (line, linenr) {body} + end" for each line in the [range], with the function + argument being set to the text of each line in turn, + without a trailing <EOL>, and the current line number. + If the value returned by the function is a string it + becomes the text of the line in the current turn. The + default for [range] is the whole file: "1,$". + +Examples: +> + :luado return string.format("%s\t%d", line:reverse(), #line) + + :lua require"lpeg" + :lua -- balanced parenthesis grammar: + :lua bp = lpeg.P{ "(" * ((1 - lpeg.S"()") + lpeg.V(1))^0 * ")" } + :luado if bp:match(line) then return "-->\t" .. line end +< + + *:luafile* +:[range]luafile {file} + Execute Lua script in {file}. + The whole argument is used as a single file name. + +Examples: +> + :luafile script.lua + :luafile % +< + +All these commands execute a Lua chunk from either the command line (:lua and +:luado) or a file (:luafile) with the given line [range]. Similarly to the Lua +interpreter, each chunk has its own scope and so only global variables are +shared between command calls. All Lua default libraries are available. In +addition, Lua "print" function has its output redirected to the Vim message +area, with arguments separated by a white space instead of a tab. + +Lua uses the "vim" module (see |lua-vim|) to issue commands to Neovim +and manage buffers (|lua-buffer|) and windows (|lua-window|). However, +procedures that alter buffer content, open new buffers, and change cursor +position are restricted when the command is executed in the |sandbox|. + + +============================================================================== +2. The vim module *lua-vim* + +Lua interfaces Vim through the "vim" module. Currently it only has `api` +submodule which is a table with all API functions. Descriptions of these +functions may be found in |api.txt|. + +============================================================================== +3. The luaeval function *lua-luaeval* *lua-eval* + *luaeval()* + +The (dual) equivalent of "vim.eval" for passing Lua values to Vim is +"luaeval". "luaeval" takes an expression string and an optional argument used +for _A inside expression and returns the result of the expression. It is +semantically equivalent in Lua to: +> + local chunkheader = "local _A = select(1, ...) return " + function luaeval (expstr, arg) + local chunk = assert(loadstring(chunkheader .. expstr, "luaeval")) + return chunk(arg) -- return typval + end + +Note that "_A" receives the argument to "luaeval". Lua nils, numbers, strings, +tables and booleans are converted to their Vim respective types. An error is +thrown if conversion of any of the remaining Lua types is attempted. + +Note 2: lua tables are used as both dictionaries and lists, thus making it +impossible to determine whether empty table is meant to be empty list or empty +dictionary. Additionally lua does not have integer numbers. To distinguish +between these cases there is the following agreement: + +0. Empty table is empty list. +1. Table with N incrementally growing integral numbers, starting from 1 and + ending with N is considered to be a list. +2. Table with string keys, none of which contains NUL byte, is considered to + be a dictionary. +3. Table with string keys, at least one of which contains NUL byte, is also + considered to be a dictionary, but this time it is converted to + a |msgpack-special-map|. +4. Table with `vim.type_idx` key may be a dictionary, a list or floating-point + value: + - `{[vim.type_idx]=vim.types.float, [vim.val_idx]=1}` is converted to + a floating-point 1.0. Note that by default integral lua numbers are + converted to |Number|s, non-integral are converted to |Float|s. This + variant allows integral |Float|s. + - `{[vim.type_idx]=vim.types.dictionary}` is converted to an empty + dictionary, `{[vim.type_idx]=vim.types.dictionary, [42]=1, a=2}` is + converted to a dictionary `{'a': 42}`: non-string keys are ignored. + Without `vim.type_idx` key tables with keys not fitting in 1., 2. or 3. + are errors. + - `{[vim.type_idx]=vim.types.list}` is converted to an empty list. As well + as `{[vim.type_idx]=vim.types.list, [42]=1}`: integral keys that do not + form a 1-step sequence from 1 to N are ignored, as well as all + non-integral keys. + +Examples: > + + :echo luaeval('math.pi') + :function Rand(x,y) " random uniform between x and y + : return luaeval('(_A.y-_A.x)*math.random()+_A.x', {'x':a:x,'y':a:y}) + : endfunction + :echo Rand(1,10) + +Note that currently second argument to `luaeval` undergoes VimL to lua +conversion, so changing containers in lua do not affect values in VimL. Return +value is also always converted. When converting, |msgpack-special-dict|s are +treated specially. + +============================================================================== + vim:tw=78:ts=8:noet:ft=help:norl: diff --git a/runtime/doc/if_pyth.txt b/runtime/doc/if_pyth.txt index b6fe234de4..8baa2d309b 100644 --- a/runtime/doc/if_pyth.txt +++ b/runtime/doc/if_pyth.txt @@ -1,4 +1,4 @@ -*if_pyth.txt* For Vim version 7.4. Last change: 2014 Jul 23 +*if_pyth.txt* Nvim VIM REFERENCE MANUAL by Paul Moore @@ -6,18 +6,10 @@ The Python Interface to Vim *python* *Python* -1. Commands |python-commands| -2. The vim module |python-vim| -3. Buffer objects |python-buffer| -4. Range objects |python-range| -5. Window objects |python-window| -6. Tab page objects |python-tabpage| -7. vim.bindeval objects |python-bindeval-objects| -8. pyeval(), py3eval() Vim functions |python-pyeval| -9. Python 3 |python3| - See |provider-python| for more information. {Nvim} + Type <M-]> to see the table of contents. + ============================================================================== 1. Commands *python-commands* @@ -48,7 +40,11 @@ Example: > print 'EAT ME' EOF endfunction -< + +To see what version of Python you have: > + :python import sys + :python print(sys.version) + Note: Python is very sensitive to the indenting. Make sure the "class" line and "EOF" do not have any indent. @@ -181,11 +177,6 @@ vim.eval(str) *python-eval* # string.atoi() to convert to # a number. - :py tagList = vim.eval('taglist("eval_expr")') -< The latter will return a python list of python dicts, for instance: - [{'cmd': '/^eval_expr(arg, nextcmd)$/', 'static': 0, 'name': - 'eval_expr', 'kind': 'f', 'filename': './src/eval.c'}] - vim.bindeval(str) *python-bindeval* Like |python-eval|, but returns special objects described in |python-bindeval-objects|. These python objects let you modify (|List| @@ -688,7 +679,7 @@ vim.Function object *python-Function* 8. pyeval() and py3eval() Vim functions *python-pyeval* To facilitate bi-directional interface, you can use |pyeval()| and |py3eval()| -functions to evaluate Python expressions and pass their values to VimL. +functions to evaluate Python expressions and pass their values to Vim script. ============================================================================== 9. Python 3 *python3* @@ -697,6 +688,10 @@ functions to evaluate Python expressions and pass their values to VimL. The `:py3` and `:python3` commands work similar to `:python`. A simple check if the `:py3` command is working: > :py3 print("Hello") + +To see what version of Python you have: > + :py3 import sys + :py3 print(sys.version) < *:py3file* The `:py3file` command works similar to `:pyfile`. *:py3do* diff --git a/runtime/doc/if_ruby.txt b/runtime/doc/if_ruby.txt index fdd63501ea..54d81a958d 100644 --- a/runtime/doc/if_ruby.txt +++ b/runtime/doc/if_ruby.txt @@ -1,22 +1,17 @@ -*if_ruby.txt* +*if_ruby.txt* Nvim VIM REFERENCE MANUAL by Shugo Maeda The Ruby Interface to Vim *ruby* *Ruby* - -1. Commands |ruby-commands| -2. The VIM module |ruby-vim| -3. VIM::Buffer objects |ruby-buffer| -4. VIM::Window objects |ruby-window| -5. Global variables |ruby-globals| - *E266* *E267* *E268* *E269* *E270* *E271* *E272* *E273* The home page for ruby is http://www.ruby-lang.org/. You can find links for downloading Ruby there. + Type <M-]> to see the table of contents. + ============================================================================== 1. Commands *ruby-commands* @@ -54,6 +49,9 @@ Example Vim script: > EOF endfunction < +To see what version of Ruby you have: > + :ruby print RUBY_VERSION +< *:rubydo* *:rubyd* *E265* :[range]rubyd[o] {cmd} Evaluate Ruby command {cmd} for each line in the diff --git a/runtime/doc/indent.txt b/runtime/doc/indent.txt index 6e96d9b816..8e17de3fb0 100644 --- a/runtime/doc/indent.txt +++ b/runtime/doc/indent.txt @@ -1,4 +1,4 @@ -*indent.txt* For Vim version 7.4. Last change: 2014 Dec 06 +*indent.txt* Nvim VIM REFERENCE MANUAL by Bram Moolenaar @@ -6,8 +6,7 @@ This file is about indenting C programs and other files. -1. Indenting C style programs |C-indenting| -2. Indenting by expression |indent-expression| + Type <M-]> to see the table of contents. ============================================================================== 1. Indenting C style programs *C-indenting* @@ -810,7 +809,7 @@ PHP indenting can be altered in several ways by modifying the values of some global variables: *php-comment* *PHP_autoformatcomment* -To not enable auto-formating of comments by default (if you want to use your +To not enable auto-formatting of comments by default (if you want to use your own 'formatoptions'): > :let g:PHP_autoformatcomment = 0 diff --git a/runtime/doc/index.txt b/runtime/doc/index.txt index 7388652f16..c15587cffd 100644 --- a/runtime/doc/index.txt +++ b/runtime/doc/index.txt @@ -1,4 +1,4 @@ -*index.txt* For Vim version 7.4. Last change: 2016 Jun 12 +*index.txt* Nvim VIM REFERENCE MANUAL by Bram Moolenaar @@ -10,22 +10,13 @@ short description. The lists are sorted on ASCII value. Tip: When looking for certain functionality, use a search command. E.g., to look for deleting something, use: "/delete". -1. Insert mode |insert-index| -2. Normal mode |normal-index| - 2.1. Text objects |objects| - 2.2. Window commands |CTRL-W| - 2.3. Square bracket commands |[| - 2.4. Commands starting with 'g' |g| - 2.5. Commands starting with 'z' |z| -3. Visual mode |visual-index| -4. Command-line editing |ex-edit-index| -5. EX commands |ex-cmd-index| - For an overview of options see help.txt |option-list|. For an overview of built-in functions see |functions|. For a list of Vim variables see |vim-variable|. For a complete listing of all help items see |help-tags|. + Type <M-]> to see the table of contents. + ============================================================================== 1. Insert mode *insert-index* @@ -982,7 +973,7 @@ tag command action in Command-line editing mode ~ |c_CTRL-E| CTRL-E cursor to end of command-line |'cedit'| CTRL-F default value for 'cedit': opens the command-line window; otherwise not used - CTRL-G not used +|c_CTRL-G| CTRL-G next match when 'incsearch' is active |c_<BS>| <BS> delete the character in front of the cursor |c_digraph| {char1} <BS> {char2} enter digraph when 'digraph' is on @@ -1000,7 +991,7 @@ tag command action in Command-line editing mode ~ |c_CTRL-L| CTRL-L do completion on the pattern in front of the cursor and insert the longest common part |c_<CR>| <CR> execute entered command -|c_<CR>| CTRL-M same as <CR> +|c_CTRL-M| CTRL-M same as <CR> |c_CTRL-N| CTRL-N after using 'wildchar' with multiple matches: go to next match, otherwise: same as <Down> CTRL-O not used @@ -1015,7 +1006,7 @@ tag command action in Command-line editing mode ~ insert the contents of a register or object under the cursor literally CTRL-S (used for terminal control flow) - CTRL-T not used +|c_CTRL-T| CTRL-T previous match when 'incsearch' is active |c_CTRL-U| CTRL-U remove all characters |c_CTRL-V| CTRL-V insert next non-digit literally, insert three digit decimal number as a single byte. @@ -1024,7 +1015,7 @@ tag command action in Command-line editing mode ~ CTRL-Y copy (yank) modeless selection CTRL-Z not used (reserved for suspend) |c_<Esc>| <Esc> abandon command-line without executing it -|c_<Esc>| CTRL-[ same as <Esc> +|c_CTRL-[| CTRL-[ same as <Esc> |c_CTRL-\_CTRL-N| CTRL-\ CTRL-N go to Normal mode, abandon command-line |c_CTRL-\_CTRL-G| CTRL-\ CTRL-G go to mode specified with 'insertmode', abandon command-line @@ -1152,6 +1143,7 @@ tag command action ~ |:chdir| :chd[ir] change directory |:checkpath| :che[ckpath] list included files |:checktime| :checkt[ime] check timestamp of loaded buffers +|:chistory| :chi[story] list the error lists |:clast| :cla[st] go to the specified error, default last one |:clearjumps| :cle[arjumps] clear the jump list |:clist| :cl[ist] list all errors @@ -1201,7 +1193,7 @@ tag command action ~ |:display| :di[splay] display registers |:djump| :dj[ump] jump to #define |:dl| :dl short for |:delete| with the 'l' flag -|:dl| :del[ete]l short for |:delete| with the 'l' flag +|:del| :del[ete]l short for |:delete| with the 'l' flag |:dlist| :dli[st] list #defines |:doautocmd| :do[autocmd] apply autocommands to current buffer |:doautoall| :doautoa[ll] apply autocommands for all loaded buffers @@ -1233,6 +1225,7 @@ tag command action ~ |:file| :f[ile] show or set the current file name |:files| :files list all files in the buffer list |:filetype| :filet[ype] switch file type detection on/off +|:filter| :filt[er] filter output of following command |:find| :fin[d] find file in 'path' and edit it |:finally| :fina[lly] part of a :try command |:finish| :fini[sh] quit sourcing a Vim script @@ -1313,6 +1306,7 @@ tag command action ~ |:lgrep| :lgr[ep] run 'grepprg' and jump to first match |:lgrepadd| :lgrepa[dd] like :grep, but append to current list |:lhelpgrep| :lh[elpgrep] like ":helpgrep" but uses location list +|:lhistory| :lhi[story] list the location lists |:ll| :ll go to specific location |:llast| :lla[st] go to the specified location, default last one |:llist| :lli[st] list all locations @@ -1337,6 +1331,9 @@ tag command action ~ |:ltag| :lt[ag] jump to tag and add matching tags to the location list |:lunmap| :lu[nmap] like ":unmap!" but includes Lang-Arg mode +|:lua| :lua execute Lua command +|:luado| :luad[o] execute Lua command for each line +|:luafile| :luaf[ile] execute Lua script file |:lvimgrep| :lv[imgrep] search for pattern in files |:lvimgrepadd| :lvimgrepa[dd] like :vimgrep, but append to current list |:lwindow| :lw[indow] open or close location window diff --git a/runtime/doc/insert.txt b/runtime/doc/insert.txt index a82e17c857..9219f45c83 100644 --- a/runtime/doc/insert.txt +++ b/runtime/doc/insert.txt @@ -1,4 +1,4 @@ -*insert.txt* For Vim version 7.4. Last change: 2016 Jan 31 +*insert.txt* Nvim VIM REFERENCE MANUAL by Bram Moolenaar @@ -13,20 +13,11 @@ commands for inserting text in other ways. An overview of the most often used commands can be found in chapter 24 of the user manual |usr_24.txt|. -1. Special keys |ins-special-keys| -2. Special special keys |ins-special-special| -3. 'textwidth' and 'wrapmargin' options |ins-textwidth| -4. 'expandtab', 'smarttab' and 'softtabstop' options |ins-expandtab| -5. Replace mode |Replace-mode| -6. Virtual Replace mode |Virtual-Replace-mode| -7. Insert mode completion |ins-completion| -8. Insert mode commands |inserting| -9. Ex insert commands |inserting-ex| -10. Inserting a file |inserting-file| - Also see 'virtualedit', for moving the cursor to positions where there is no character. Useful for editing a table. + Type <M-]> to see the table of contents. + ============================================================================== 1. Special keys *ins-special-keys* @@ -370,9 +361,6 @@ CTRL-G U don't break undo with next left/right cursor *i_CTRL-G_U* within same the line) ----------------------------------------------------------------------- -Note: If the cursor keys take you out of Insert mode, check the 'noesckeys' -option. - The CTRL-O command sometimes has a side effect: If the cursor was beyond the end of the line, it will be put on the last character in the line. In mappings it's often better to use <Esc> (first put an "x" in the text, <Esc> diff --git a/runtime/doc/intro.txt b/runtime/doc/intro.txt index 786097dd74..b9cc94ce5f 100644 --- a/runtime/doc/intro.txt +++ b/runtime/doc/intro.txt @@ -1,4 +1,4 @@ -*intro.txt* For Vim version 7.4. Last change: 2015 Jan 20 +*intro.txt* Nvim VIM REFERENCE MANUAL by Bram Moolenaar @@ -6,14 +6,7 @@ Introduction to Vim *ref* *reference* -1. Introduction |intro| -2. Vim on the internet |internet| -3. Credits |credits| -4. Notation |notation| -5. Modes, introduction |vim-modes-intro| -6. Switching from mode to mode |mode-switching| -7. The window contents |window-contents| -8. Definitions |definitions| + Type <M-]> to see the table of contents. ============================================================================== 1. Introduction *intro* @@ -34,11 +27,6 @@ It can be accessed from within Vim with the <Help> or <F1> key and with the is not located in the default place. You can jump to subjects like with tags: Use CTRL-] to jump to a subject under the cursor, use CTRL-T to jump back. -This manual refers to Vim on various machines. There may be small differences -between different computers and terminals. Besides the remarks given in this -document, there is a separate document for each supported system, see -|sys-file-list|. - *pronounce* Vim is pronounced as one word, like Jim, not vi-ai-em. It's written with a capital, since it's a name, again like Jim. @@ -92,21 +80,18 @@ mention that. *mail-list* *maillist* There are several mailing lists for Vim: -<vim@vim.org> +<vim@vim.org> *vim-use* *vim_use* For discussions about using existing versions of Vim: Useful mappings, questions, answers, where to get a specific version, etc. There are quite a few people watching this list and answering questions, also for beginners. Don't hesitate to ask your question here. -<vim-dev@vim.org> *vim-dev* *vimdev* +<vim-dev@vim.org> *vim-dev* *vim_dev* *vimdev* For discussions about changing Vim: New features, porting, patches, beta-test versions, etc. -<vim-announce@vim.org> *vim-announce* +<vim-announce@vim.org> *vim-announce* *vim_announce* Announcements about new versions of Vim; also for beta-test versions and ports to different systems. This is a read-only list. -<vim-multibyte@vim.org> *vim-multibyte* - For discussions about using and improving the multi-byte aspects of - Vim. -<vim-mac@vim.org> *vim-mac* +<vim-mac@vim.org> *vim-mac* *vim_mac* For discussions about using and improving the Macintosh version of Vim. @@ -131,10 +116,7 @@ http://www.vim.org/maillist.php Bug reports: *bugs* *bug-reports* *bugreport.vim* -Send bug reports to: Vim Developers <vim-dev@vim.org> -This is a maillist, you need to become a member first and many people will see -the message. If you don't want that, e.g. because it is a security issue, -send it to <bugs@vim.org>, this only goes to the Vim maintainer (that's Bram). +Report bugs on GitHub: https://github.com/neovim/neovim/issues Please be brief; all the time that is spent on answering mail is subtracted from the time that is spent on improving Vim! Always give a reproducible @@ -267,8 +249,7 @@ Vi "the original". Without further remarks this is the version of Vi that appeared in Sun OS 4.x. ":version" returns "Version 3.7, 6/7/85". Sometimes other versions are referred to. Only runs under Unix. Source code only available with a - license. More information on Vi can be found through: - http://vi-editor.org [doesn't currently work...] + license. *Nvi* Nvi The "New" Vi. The version of Vi that comes with BSD 4.4 and FreeBSD. Very good compatibility with the original Vi, with a few extensions. @@ -453,7 +434,6 @@ notation meaning equivalent decimal value(s) ~ <M-...> alt-key or meta-key *META* *meta* *alt* *<M-* <A-...> same as <M-...> *<A-* <D-...> command-key or "super" key *<D-* -<t_xx> key with "xx" entry in termcap ----------------------------------------------------------------------- Note: The shifted cursor keys, the help key, and the undo key are only @@ -461,8 +441,8 @@ available on a few terminals. Note: There are two codes for the delete key. 127 is the decimal ASCII value for the delete key, which is always recognized. Some delete keys send another -value, in which case this value is obtained from the termcap entry "kD". Both -values have the same effect. +value, in which case this value is obtained from the |terminfo| entry "key_dc". +Both values have the same effect. Note: The keypad keys are used in the same way as the corresponding "normal" keys. For example, <kHome> has the same effect as <Home>. If a keypad key @@ -488,7 +468,6 @@ the ":map" command. The rules are: <S-F11> Shifted function key 11 <M-a> Meta- a ('a' with bit 8 set) <M-A> Meta- A ('A' with bit 8 set) - <t_kd> "kd" termcap entry (cursor down key) The <> notation uses <lt> to escape the special meaning of key names. Using a backslash also works, but only when 'cpoptions' does not include the 'B' flag. @@ -509,7 +488,7 @@ examples and use them directly. Or type them literally, including the '<' and ============================================================================== 5. Modes, introduction *vim-modes-intro* *vim-modes* -Vim has six BASIC modes: +Vim has seven BASIC modes: *Normal* *Normal-mode* *command-mode* Normal mode In Normal mode you can enter all the normal editor @@ -545,6 +524,13 @@ Ex mode Like Command-line mode, but after entering a command you remain in Ex mode. Very limited editing of the command line. |Ex-mode| + *Terminal-mode* +Terminal mode In Terminal mode all input (except |c_CTRL-\_CTRL-N|) + is sent to the process running in the current + |terminal| buffer. + If the 'showmode' option is on "-- TERMINAL --" is shown + at the bottom of the window. + There are six ADDITIONAL modes. These are variants of the BASIC modes: *Operator-pending* *Operator-pending-mode* diff --git a/runtime/doc/job_control.txt b/runtime/doc/job_control.txt index 1aa7ce06d6..edbc1bca81 100644 --- a/runtime/doc/job_control.txt +++ b/runtime/doc/job_control.txt @@ -1,4 +1,4 @@ -*job_control.txt* For Nvim. {Nvim} +*job_control.txt* Nvim NVIM REFERENCE MANUAL by Thiago de Arruda @@ -6,8 +6,7 @@ Nvim's facilities for job control *job-control* -1. Introduction |job-control-intro| -2. Usage |job-control-usage| + Type <M-]> to see the table of contents. ============================================================================== 1. Introduction *job-control-intro* @@ -76,6 +75,7 @@ Here's what is happening: - The `JobHandler()` function is a callback passed to |jobstart()| to handle various job events. It takes care of displaying stdout/stderr received from the shells. + *on_stdout* *on_stderr* *on_exit* - The arguments passed to `JobHandler()` are: 0: The job id @@ -102,36 +102,30 @@ function. Here's a more object-oriented version of the above: > let Shell = {} - function Shell.on_stdout(job_id, data) dict - call append(line('$'), self.get_name().' stdout: '.join(a:data)) + function Shell.on_stdout(_job_id, data, event) + call append(line('$'), + \ printf('[%s] %s: %s', a:event, self.name, join(a:data[:-2]))) endfunction - function Shell.on_stderr(job_id, data) dict - call append(line('$'), self.get_name().' stderr: '.join(a:data)) - endfunction - - function Shell.on_exit(job_id, data) dict - call append(line('$'), self.get_name().' exited') - endfunction + let Shell.on_stderr = function(Shell.on_stdout) - function Shell.get_name() dict - return 'shell '.self.name + function Shell.on_exit(job_id, _data, event) + let msg = printf('job %d ("%s") finished', a:job_id, self.name) + call append(line('$'), printf('[%s] BOOM!', a:event)) + call append(line('$'), printf('[%s] %s!', a:event, msg)) endfunction - function Shell.new(name, ...) dict - let instance = extend(copy(g:Shell), {'name': a:name}) - let argv = ['bash'] - if a:0 > 0 - let argv += ['-c', a:1] - endif - let instance.id = jobstart(argv, instance) - return instance + function Shell.new(name, cmd) + let object = extend(copy(g:Shell), {'name': a:name}) + let object.cmd = ['sh', '-c', a:cmd] + let object.id = jobstart(object.cmd, object) + $ + return object endfunction - let s1 = Shell.new('1') - let s2 = Shell.new('2', 'for i in {1..10}; do echo hello $i!; sleep 1; done') - - + let instance = Shell.new('bomb', + \ 'for i in $(seq 9 -1 1); do echo $i 1>&$((i % 2 + 1)); sleep 1; done') +< To send data to the job's stdin, one can use the |jobsend()| function, like this: > diff --git a/runtime/doc/makehtml.awk b/runtime/doc/makehtml.awk index a1f77f5aba..216bb5fac1 100644 --- a/runtime/doc/makehtml.awk +++ b/runtime/doc/makehtml.awk @@ -185,12 +185,6 @@ FILENAME == "gui.txt" && asciiart == "no" \ asciicnt=0; } -FILENAME == "quotes.txt" && asciiart == "no" \ - && $0 ~ /In summary:/ { - asciiart= "yes"; - asciicnt=0; - } - FILENAME == "usr_20.txt" && asciiart == "no" \ && $0 ~ /an empty line at the end:/ { asciiart= "yes"; diff --git a/runtime/doc/map.txt b/runtime/doc/map.txt index 991ecf8fb2..944f7474be 100644 --- a/runtime/doc/map.txt +++ b/runtime/doc/map.txt @@ -1,4 +1,4 @@ -*map.txt* For Vim version 7.4. Last change: 2016 Jun 10 +*map.txt* Nvim VIM REFERENCE MANUAL by Bram Moolenaar @@ -9,21 +9,7 @@ Key mapping, abbreviations and user-defined commands. This subject is introduced in sections |05.3|, |24.7| and |40.1| of the user manual. -1. Key mapping |key-mapping| - 1.1 MAP COMMANDS |:map-commands| - 1.2 Special arguments |:map-arguments| - 1.3 Mapping and modes |:map-modes| - 1.4 Listing mappings |map-listing| - 1.5 Mapping special keys |:map-special-keys| - 1.6 Special characters |:map-special-chars| - 1.7 What keys to map |map-which-keys| - 1.8 Examples |map-examples| - 1.9 Using mappings |map-typing| - 1.10 Mapping alt-keys |:map-alt-keys| - 1.11 Mapping an operator |:map-operator| -2. Abbreviations |abbreviations| -3. Local mappings and functions |script-local| -4. User-defined commands |user-commands| + Type <M-]> to see the table of contents. ============================================================================== 1. Key mapping *key-mapping* *mapping* *macro* @@ -163,7 +149,7 @@ type "a", then "bar" will get inserted. 1.2 SPECIAL ARGUMENTS *:map-arguments* -"<buffer>", "<nowait>", "<silent>", "<special>", "<script>", "<expr>" and +"<buffer>", "<nowait>", "<silent>", "<script>", "<expr>" and "<unique>" can be used in any order. They must appear right after the command, before any other arguments. @@ -203,12 +189,6 @@ Prompts will still be given, e.g., for inputdialog(). Using "<silent>" for an abbreviation is possible, but will cause redrawing of the command line to fail. - *:map-<special>* *:map-special* -Define a mapping with <> notation for special keys, even though the "<" flag -may appear in 'cpoptions'. This is useful if the side effect of setting -'cpoptions' is not desired. Example: > - :map <special> <F12> /Header<CR> -< *:map-<script>* *:map-script* If the first argument to one of these commands is "<script>" and it is used to define a new mapping or abbreviation, the mapping will only remap characters @@ -437,6 +417,9 @@ with a space. Note: When using mappings for Visual mode, you can use the "'<" mark, which is the start of the last selected Visual area in the current buffer |'<|. +The |:filter| command can be used to select what mappings to list. The +pattern is matched against the {lhs} and {rhs} in the raw form. + *:map-verbose* When 'verbose' is non-zero, listing a key map will also display where it was last defined. Example: > @@ -450,42 +433,28 @@ See |:verbose-cmd| for more information. 1.5 MAPPING SPECIAL KEYS *:map-special-keys* -There are three ways to map a special key: +There are two ways to map a special key: 1. The Vi-compatible method: Map the key code. Often this is a sequence that starts with <Esc>. To enter a mapping like this you type ":map " and then you have to type CTRL-V before hitting the function key. Note that when - the key code for the key is in the termcap (the t_ options), it will - automatically be translated into the internal code and become the second - way of mapping (unless the 'k' flag is included in 'cpoptions'). + the key code for the key is in the |terminfo| entry, it will automatically + be translated into the internal code and become the second way of mapping. 2. The second method is to use the internal code for the function key. To enter such a mapping type CTRL-K and then hit the function key, or use the form "#1", "#2", .. "#9", "#0", "<Up>", "<S-Down>", "<S-F7>", etc. (see table of keys |key-notation|, all keys from <Up> can be used). The first ten function keys can be defined in two ways: Just the number, like "#2", and with "<F>", like "<F2>". Both stand for function key 2. "#0" - refers to function key 10, defined with option 't_f10', which may be - function key zero on some keyboards. The <> form cannot be used when - 'cpoptions' includes the '<' flag. -3. Use the termcap entry, with the form <t_xx>, where "xx" is the name of the - termcap entry. Any string entry can be used. For example: > - :map <t_F3> G -< Maps function key 13 to "G". This does not work if 'cpoptions' includes - the '<' flag. - -The advantage of the second and third method is that the mapping will work on -different terminals without modification (the function key will be -translated into the same internal code or the actual key code, no matter what -terminal you are using. The termcap must be correct for this to work, and you -must use the same mappings). + refers to function key 10. DETAIL: Vim first checks if a sequence from the keyboard is mapped. If it -isn't the terminal key codes are tried (see |terminal-options|). If a -terminal code is found it is replaced with the internal code. Then the check -for a mapping is done again (so you can map an internal code to something -else). What is written into the script file depends on what is recognized. -If the terminal key code was recognized as a mapping the key code itself is -written to the script file. If it was recognized as a terminal code the -internal code is written to the script file. +isn't the terminal key codes are tried. If a terminal code is found it is +replaced with the internal code. Then the check for a mapping is done again +(so you can map an internal code to something else). What is written into the +script file depends on what is recognized. If the terminal key code was +recognized as a mapping the key code itself is written to the script file. If +it was recognized as a terminal code the internal code is written to the +script file. 1.6 SPECIAL CHARACTERS *:map-special-chars* @@ -594,9 +563,9 @@ Since the '|' character is used to separate a map command from the next command, you will have to do something special to include a '|' in {rhs}. There are three methods: use works when example ~ - <Bar> '<' is not in 'cpoptions' :map _l :!ls <Bar> more^M + <Bar> always :map _l :!ls <Bar> more^M \| 'b' is not in 'cpoptions' :map _l :!ls \| more^M - ^V| always, in Vim and Vi :map _l :!ls ^V| more^M + ^V| always :map _l :!ls ^V| more^M (here ^V stands for CTRL-V; to get one CTRL-V you have to type it twice; you cannot use the <> notation "<C-V>" here). @@ -651,8 +620,7 @@ out about, ^D is CTRL-D). 1.8 EXAMPLES *map-examples* -A few examples (given as you type them, for "<CR>" you type four characters; -the '<' flag must not be present in 'cpoptions' for this to work). > +A few examples (as you type them: for "<CR>" you type four characters). > :map <F3> o#include :map <M-g> /foo<CR>cwbar<Esc> @@ -720,9 +688,6 @@ special key: > Don't type a real <Esc>, Vim will recognize the key code and replace it with <F1> anyway. -Another problem may be that when keeping ALT or Meta pressed the terminal -prepends ESC instead of setting the 8th bit. See |:map-alt-keys|. - *recursive_mapping* If you include the {lhs} in the {rhs} you have a recursive mapping. When {lhs} is typed, it will be replaced with {rhs}. When the {lhs} which is @@ -762,46 +727,14 @@ in the original Vi, you would get back the text before the first undo). 1.10 MAPPING ALT-KEYS *:map-alt-keys* -In the GUI Vim handles the Alt key itself, thus mapping keys with ALT should -always work. But in a terminal Vim gets a sequence of bytes and has to figure -out whether ALT was pressed or not. - -By default Vim assumes that pressing the ALT key sets the 8th bit of a typed -character. Most decent terminals can work that way, such as xterm, aterm and -rxvt. If your <A-k> mappings don't work it might be that the terminal is -prefixing the character with an ESC character. But you can just as well type -ESC before a character, thus Vim doesn't know what happened (except for -checking the delay between characters, which is not reliable). - -As of this writing, some mainstream terminals like gnome-terminal and konsole -use the ESC prefix. There doesn't appear a way to have them use the 8th bit -instead. Xterm should work well by default. Aterm and rxvt should work well -when started with the "--meta8" argument. You can also tweak resources like -"metaSendsEscape", "eightBitInput" and "eightBitOutput". - -On the Linux console, this behavior can be toggled with the "setmetamode" -command. Bear in mind that not using an ESC prefix could get you in trouble -with other programs. You should make sure that bash has the "convert-meta" -option set to "on" in order for your Meta keybindings to still work on it -(it's the default readline behavior, unless changed by specific system -configuration). For that, you can add the line: > - - set convert-meta on - -to your ~/.inputrc file. If you're creating the file, you might want to use: > - - $include /etc/inputrc - -as the first line, if that file exists on your system, to keep global options. -This may cause a problem for entering special characters, such as the umlaut. -Then you should use CTRL-V before that character. - -Bear in mind that convert-meta has been reported to have troubles when used in -UTF-8 locales. On terminals like xterm, the "metaSendsEscape" resource can be -toggled on the fly through the "Main Options" menu, by pressing Ctrl-LeftClick -on the terminal; that's a good last resource in case you want to send ESC when -using other applications but not when inside VIM. - +In the GUI Nvim handles the |ALT| key itself, thus mapping keys with ALT +should always work. But in a terminal Nvim gets a sequence of bytes and has +to figure out whether ALT was pressed. Terminals may use ESC to indicate that +ALT was pressed. If ESC is followed by a {key} within 'ttimeoutlen' +milliseconds, the ESC is interpreted as: + <ALT-{key}> +otherwise it is interpreted as two key presses: + <ESC> {key} 1.11 MAPPING AN OPERATOR *:map-operator* @@ -939,7 +872,6 @@ character is mostly ignored otherwise. It is possible to move the cursor after an abbreviation: > :iab if if ()<Left> -This does not work if 'cpoptions' includes the '<' flag. |<>| You can even do more complicated things. For example, to consume the space typed after an abbreviation: > @@ -1087,8 +1019,7 @@ functions used in one script use the same name as in other scripts. To avoid this, they can be made local to the script. *<SID>* *<SNR>* *E81* -The string "<SID>" can be used in a mapping or menu. This requires that the -'<' flag is not present in 'cpoptions'. +The string "<SID>" can be used in a mapping or menu. When executing the map command, Vim will replace "<SID>" with the special key code <SNR>, followed by a number that's unique for the script, and an underscore. Example: > @@ -1171,6 +1102,10 @@ scripts. " Command has the -register attribute b Command is local to current buffer (see below for details on attributes) + The list can be filtered on command name with + |:filter|, e.g., to list all commands with "Pyth" in + the name: > + filter Pyth command :com[mand] {cmd} List the user-defined commands that start with {cmd} @@ -1267,7 +1202,9 @@ completion can be enabled: -complete=locale locale names (as output of locale -a) -complete=mapping mapping name -complete=menu menus + -complete=messages |:messages| suboptions -complete=option options + -complete=packadd optional package |pack-add| names -complete=shellcmd Shell command -complete=sign |:sign| suboptions -complete=syntax syntax file names |'syntax'| @@ -1410,9 +1347,11 @@ The valid escape sequences are <mods> The command modifiers, if specified. Otherwise, expands to nothing. Supported modifiers are |:aboveleft|, |:belowright|, |:botright|, |:browse|, |:confirm|, |:hide|, |:keepalt|, - |:keepjumps|, |:keepmarks|, |:keeppatterns|, |:lockmarks|, - |:noswapfile|, |:silent|, |:tab|, |:topleft|, |:verbose|, and - |:vertical|. + |:keepjumps|, |:keepmarks|, |:keeppatterns|, |:leftabove|, + |:lockmarks|, |:noswapfile| |:rightbelow|, |:silent|, |:tab|, + |:topleft|, |:verbose|, and |:vertical|. + Note that these are not yet supported: |:noautocmd|, + |:sandbox| and |:unsilent|. Examples: > command! -nargs=+ -complete=file MyEdit \ for f in expand(<q-args>, 0, 1) | diff --git a/runtime/doc/mbyte.txt b/runtime/doc/mbyte.txt index 355a1da423..2e2ca92656 100644 --- a/runtime/doc/mbyte.txt +++ b/runtime/doc/mbyte.txt @@ -1,4 +1,4 @@ -*mbyte.txt* For Vim version 7.4. Last change: 2016 Jul 21 +*mbyte.txt* Nvim VIM REFERENCE MANUAL by Bram Moolenaar et al. @@ -14,26 +14,10 @@ For an introduction to the most common features, see |usr_45.txt| in the user manual. For changing the language of messages and menus see |mlang.txt|. -{not available when compiled without the |+multi_byte| feature} - - -1. Getting started |mbyte-first| -2. Locale |mbyte-locale| -3. Encoding |mbyte-encoding| -4. Using a terminal |mbyte-terminal| -5. Fonts on X11 |mbyte-fonts-X11| -6. Fonts on MS-Windows |mbyte-fonts-MSwin| -7. Input on X11 |mbyte-XIM| -8. Input on MS-Windows |mbyte-IME| -9. Input with a keymap |mbyte-keymap| -10. Using UTF-8 |mbyte-utf8| -11. Overview of options |mbyte-options| - -NOTE: This file contains UTF-8 characters. These may show up as strange -characters or boxes when using another encoding. + Type <M-]> to see the table of contents. ============================================================================== -1. Getting started *mbyte-first* +Getting started *mbyte-first* This is a summary of the multibyte features in Vim. If you are lucky it works as described and you can start using Vim without much trouble. If something @@ -89,8 +73,7 @@ be displayed and edited correctly. For the GUI you must select fonts that work with UTF-8. This is the difficult part. It depends on the system you are using, the locale and -a few other things. See the chapters on fonts: |mbyte-fonts-X11| for -X-Windows and |mbyte-fonts-MSwin| for MS-Windows. +a few other things. For X11 you can set the 'guifontset' option to a list of fonts that together cover the characters that are used. Example for Korean: > @@ -120,7 +103,7 @@ The options 'iminsert', 'imsearch' and 'imcmdline' can be used to chose the different input methods or disable them temporarily. ============================================================================== -2. Locale *mbyte-locale* +Locale *mbyte-locale* The easiest setup is when your whole system uses the locale you want to work in. But it's also possible to set the locale for one shell you are working @@ -209,7 +192,7 @@ Or specify $LANG when starting Vim: You could make a small shell script for this. ============================================================================== -3. Encoding *mbyte-encoding* +Encoding *mbyte-encoding* In Nvim UTF-8 is always used internally to encode characters. This applies to all the places where text is used, including buffers (files @@ -418,49 +401,7 @@ neither of them can be found Vim will still work but some conversions won't be possible. ============================================================================== -4. Using a terminal *mbyte-terminal* - -The GUI fully supports multi-byte characters. It is also possible in a -terminal, if the terminal supports the same encoding that Vim uses. Thus this -is less flexible. - -For example, you can run Vim in a xterm with added multi-byte support and/or -|XIM|. Examples are kterm (Kanji term) and hanterm (for Korean), Eterm -(Enlightened terminal) and rxvt. - -UTF-8 IN XFREE86 XTERM *UTF8-xterm* - -This is a short explanation of how to use UTF-8 character encoding in the -xterm that comes with XFree86 by Thomas Dickey (text by Markus Kuhn). - -Get the latest xterm version which has now UTF-8 support: - - http://invisible-island.net/xterm/xterm.html - -Compile it with "./configure --enable-wide-chars ; make" - -Also get the ISO 10646-1 version of various fonts, which is available on - - http://www.cl.cam.ac.uk/~mgk25/download/ucs-fonts.tar.gz - -and install the font as described in the README file. - -Now start xterm with > - - xterm -u8 -fn -misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso10646-1 -or, for bigger character: > - xterm -u8 -fn -misc-fixed-medium-r-normal--15-140-75-75-c-90-iso10646-1 - -and you will have a working UTF-8 terminal emulator. Try both > - - cat utf-8-demo.txt - vim utf-8-demo.txt - -with the demo text that comes with ucs-fonts.tar.gz in order to see -whether there are any problems with UTF-8 in your xterm. - -============================================================================== -5. Fonts on X11 *mbyte-fonts-X11* +Fonts on X11 *mbyte-fonts-X11* Unfortunately, using fonts in X11 is complicated. The name of a single-byte font is a long string. For multi-byte fonts we need several of these... @@ -596,20 +537,7 @@ Also make sure that you set 'guifontset' before setting fonts for highlight groups. ============================================================================== -6. Fonts on MS-Windows *mbyte-fonts-MSwin* - -The simplest is to use the font dialog to select fonts and try them out. You -can find this at the "Edit/Select Font..." menu. Once you find a font name -that works well you can use this command to see its name: > - - :set guifont - -Then add a command to your |ginit.vim| file to set 'guifont': > - - :set guifont=courier_new:h12 - -============================================================================== -7. Input on X11 *mbyte-XIM* +Input on X11 *mbyte-XIM* X INPUT METHOD (XIM) BACKGROUND *XIM* *xim* *x-input-method* @@ -768,7 +696,7 @@ For example, when you are using kinput2 as |IM-server| and sh, > < ============================================================================== -8. Input on MS-Windows *mbyte-IME* +Input on MS-Windows *mbyte-IME* (Windows IME support) *multibyte-ime* *IME* @@ -842,7 +770,7 @@ Cursor color when IME or XIM is on *CursorIM* status is on. ============================================================================== -9. Input with a keymap *mbyte-keymap* +Input with a keymap *mbyte-keymap* When the keyboard doesn't produce the characters you want to enter in your text, you can use the 'keymap' option. This will translate one or more @@ -1090,7 +1018,7 @@ Combining forms: ๏ญ 0xfb4f Xal alef-lamed ============================================================================== -10. Using UTF-8 *mbyte-utf8* *UTF-8* *utf-8* *utf8* +Using UTF-8 *mbyte-utf8* *UTF-8* *utf-8* *utf8* *Unicode* *unicode* The Unicode character set was designed to include all characters from other character sets. Therefore it is possible to write text in any language using @@ -1222,7 +1150,7 @@ not everybody is able to type a composing character. ============================================================================== -11. Overview of options *mbyte-options* +Overview of options *mbyte-options* These options are relevant for editing multi-byte files. Check the help in options.txt for detailed information. diff --git a/runtime/doc/message.txt b/runtime/doc/message.txt index fd66a5dafb..c6c6f49026 100644 --- a/runtime/doc/message.txt +++ b/runtime/doc/message.txt @@ -1,4 +1,4 @@ -*message.txt* For Vim version 7.4. Last change: 2016 Jul 14 +*message.txt* Nvim VIM REFERENCE MANUAL by Bram Moolenaar @@ -8,9 +8,7 @@ This file contains an alphabetical list of messages and error messages that Vim produces. You can use this if you don't understand what the message means. It is not complete though. -1. Old messages |:messages| -2. Error messages |error-messages| -3. Messages |messages| + Type <M-]> to see the table of contents. ============================================================================== 1. Old messages *:messages* *:mes* *message-history* @@ -39,10 +37,7 @@ back. Note: If the output has been stopped with "q" at the more prompt, it will only be displayed up to this point. The previous command output is cleared when another command produces output. - -If you are using translated messages, the first printed line tells who -maintains the messages or the translations. You can use this to contact the -maintainer when you spot a mistake. +The "g<" output is not redirected. If you want to find help on a specific (error) message, use the ID at the start of the message. For example, to get help on the message: > @@ -127,8 +122,9 @@ closed properly. Mostly harmless. Command too recursive This happens when an Ex command executes an Ex command that executes an Ex -command, etc. This is only allowed 200 times. When it's more there probably -is an endless loop. Probably a |:execute| or |:source| command is involved. +command, etc. The limit is 200 or the value of 'maxfuncdepth', whatever is +larger. When it's more there probably is an endless loop. Probably a +|:execute| or |:source| command is involved. *E254* > Cannot allocate color {name} @@ -668,7 +664,7 @@ Vim and restart it. *E931* > Buffer cannot be registered -Out of memory or a duplicate buffer number. May habben after W14. Looking up +Out of memory or a duplicate buffer number. May happen after W14. Looking up a buffer will not always work, better restart Vim. *E296* *E297* > diff --git a/runtime/doc/mlang.txt b/runtime/doc/mlang.txt index a2be3cfd49..717ec9530c 100644 --- a/runtime/doc/mlang.txt +++ b/runtime/doc/mlang.txt @@ -1,4 +1,4 @@ -*mlang.txt* For Vim version 7.4. Last change: 2016 Jan 16 +*mlang.txt* Nvim VIM REFERENCE MANUAL by Bram Moolenaar @@ -11,11 +11,7 @@ multi-byte text see |multibyte|. The basics are explained in the user manual: |usr_45.txt|. -1. Messages |multilang-messages| -2. Menus |multilang-menus| -3. Scripts |multilang-scripts| - -Also see |help-translated| for multi-language help. + Type <M-]> to see the table of contents. ============================================================================== 1. Messages *multilang-messages* diff --git a/runtime/doc/motion.txt b/runtime/doc/motion.txt index 606fd53fee..99aa76bfe5 100644 --- a/runtime/doc/motion.txt +++ b/runtime/doc/motion.txt @@ -1,4 +1,4 @@ -*motion.txt* For Vim version 7.4. Last change: 2016 Jul 12 +*motion.txt* Nvim VIM REFERENCE MANUAL by Bram Moolenaar @@ -10,16 +10,6 @@ These commands move the cursor position. If the new position is off of the screen, the screen is scrolled to show the cursor (see also 'scrolljump' and 'scrolloff' options). -1. Motions and operators |operator| -2. Left-right motions |left-right-motions| -3. Up-down motions |up-down-motions| -4. Word motions |word-motions| -5. Text object motions |object-motions| -6. Text object selection |object-select| -7. Marks |mark-motions| -8. Jumps |jump-motions| -9. Various motions |various-motions| - General remarks: If you want to know where you are in the file use the "CTRL-G" command @@ -36,6 +26,8 @@ The 'virtualedit' option can be set to make it possible to move the cursor to positions where there is no character or within a multi-column character (like a tab). + Type <M-]> to see the table of contents. + ============================================================================== 1. Motions and operators *operator* @@ -401,8 +393,7 @@ a range of folded lines. "b" and "B" move to the start of the first word or WORD before the fold. Special case: "cw" and "cW" are treated like "ce" and "cE" if the cursor is -on a non-blank. This is because "cw" is interpreted as change-word, and a -word does not include the following white space. +on a non-blank. This is Vi-compatible, see |cpo-_| to change the behavior. Another special case: When using the "w" motion in combination with an operator and the last word moved over is at the end of a line, the end of diff --git a/runtime/doc/msgpack_rpc.txt b/runtime/doc/msgpack_rpc.txt index c074eb43ff..856476c6ae 100644 --- a/runtime/doc/msgpack_rpc.txt +++ b/runtime/doc/msgpack_rpc.txt @@ -1,4 +1,4 @@ -*msgpack_rpc.txt* {Nvim} +*msgpack_rpc.txt* Nvim NVIM REFERENCE MANUAL by Thiago de Arruda @@ -6,12 +6,7 @@ RPC API for Nvim *RPC* *rpc* *msgpack-rpc* -1. Introduction |rpc-intro| -2. API mapping |rpc-api| -3. Connecting |rpc-connecting| -4. Clients |rpc-api-client| -5. Types |rpc-types| -6. Remote UIs |rpc-remote-ui| + Type <M-]> to see the table of contents. ============================================================================== 1. Introduction *rpc-intro* @@ -33,7 +28,7 @@ programs can: The RPC API is like a more powerful version of Vim's `clientserver` feature. ============================================================================== - 2. API mapping *rpc-api* +2. API mapping *rpc-api* The Nvim C |API| is automatically exposed to the RPC API by the build system, which parses headers at src/nvim/api/*. A dispatch function is generated which @@ -197,7 +192,7 @@ prefix is stripped off. 5. Types *rpc-types* The Nvim C API uses custom types for all functions. |api-types| -For the purpose of mapping to msgpack, the types can be split into two groups: +At the RPC layer, the types can be split into two groups: - Basic types that map natively to msgpack (and probably have a default representation in msgpack-supported programming languages) @@ -219,15 +214,16 @@ Special types (msgpack EXT) ~ Window -> enum value kObjectTypeWindow Tabpage -> enum value kObjectTypeTabpage -An API method expecting one of these types may be passed an integer instead, -although they are not interchangeable. For example, a Buffer may be passed as -an integer, but not a Window or Tabpage. +API functions expecting one of the special EXT types may be passed an integer +instead, but not another EXT type. E.g. Buffer may be passed as an integer but +not as a Window or Tabpage. The EXT object data is the object id encoded as +a msgpack integer: For buffers this is the |bufnr()| and for windows the +|window-ID|. For tabpages the id is an internal handle, not the tabpage +number. + +To determine the type codes of the special EXT types, inspect the `types` key +of the |api-metadata| at runtime. Example JSON representation: > -The most reliable way of determining the type codes for the special Nvim types -is to inspect the `types` key of metadata dictionary returned by the -`nvim_get_api_info` method at runtime. Here's a sample JSON representation of -the `types` object: -> "types": { "Buffer": { "id": 0, @@ -242,7 +238,7 @@ the `types` object: "prefix": "nvim_tabpage_" } } -< + Even for statically compiled clients it is good practice to avoid hardcoding the type codes, because a client may be built against one Nvim version but connect to another with different type codes. @@ -250,35 +246,38 @@ connect to another with different type codes. ============================================================================== 6. Remote UIs *rpc-remote-ui* -Nvim allows Graphical user interfaces to be implemented by separate processes -communicating with Nvim over the RPC API. Currently the ui model conists of a -terminal-like grid with one single, monospace font size, with a few elements -that could be drawn separately from the grid (for the momemnt only the popup -menu) - -After connecting to a nvim instance (typically a spawned, embedded instance) -use the |nvim_ui_attach|(width, height, options) API method to tell nvim that your -program wants to draw the nvim screen on a grid with "width" times -"height" cells. "options" should be a dictionary with the following (all -optional) keys: - `rgb`: Controls what color format to use. +GUIs can be implemented as external processes communicating with Nvim over the +RPC API. The UI model consists of a terminal-like grid with a single, +monospace font size. Some elements (UI "widgets") can be drawn separately from +the grid ("externalized"). + +After connecting to Nvim (usually a spawned, embedded instance) use the +|nvim_ui_attach| API method to tell Nvim that your program wants to draw the +Nvim screen on a grid of width ร height cells. `options` must be +a dictionary with these (optional) keys: + `rgb` Controls what color format to use. Set to true (default) to use 24-bit rgb colors. Set to false to use terminal color codes (at most 256 different colors). - `popupmenu_external`: Instead of drawing the completion popupmenu on - the grid, Nvim will send higher-level events to - the ui and let it draw the popupmenu. - Defaults to false. + `ext_popupmenu` Externalize the popupmenu. |ui-ext-popupmenu| + `ext_tabline` Externalize the tabline. |ui-ext-tabline| + Externalized widgets will not be drawn by + Nvim; only high-level data will be published + in new UI event kinds. Nvim will then send msgpack-rpc notifications, with the method name "redraw" -and a single argument, an array of screen updates (described below). -These should be processed in order. Preferably the user should only be able to -see the screen state after all updates are processed (not any intermediate -state after processing only a part of the array). +and a single argument, an array of screen updates (described below). These +should be processed in order. Preferably the user should only be able to see +the screen state after all updates in the same "redraw" event are processed +(not any intermediate state after processing only a part of the array). + +Future versions of Nvim may add new update kinds and may append new parameters +to existing update kinds. Clients must be prepared to ignore such extensions +to be forward-compatible. |api-contract| -Screen updates are arrays. The first element a string describing the kind -of update. +Screen updates are tuples whose first element is the string name of the update +kind. ["resize", width, height] The grid is resized to `width` and `height` cells. @@ -389,11 +388,33 @@ of update. ["update_menu"] The menu mappings changed. -["mode_change", mode] - The mode changed. Currently sent when "insert", "replace", "cmdline" and - "normal" modes are entered. A client could for instance change the cursor - shape. - +["mode_info_set", cursor_style_enabled, mode_info] +`cursor_style_enabled` is a boolean indicating if the UI should set the cursor +style. `mode_info` is a list of mode property maps. The current mode is given +by the `mode_idx` field of the `mode_change` event. + +Each mode property map may contain these keys: + KEY DESCRIPTION ~ + `cursor_shape`: "block", "horizontal", "vertical" + `cell_percentage`: Cell % occupied by the cursor. + `blinkwait`, `blinkon`, `blinkoff`: See |cursor-blinking|. + `hl_id`: Cursor highlight group. + `hl_lm`: Cursor highlight group if 'langmap' is active. + `short_name`: Mode code name, see 'guicursor'. + `name`: Mode descriptive name. + `mouse_shape`: (To be implemented.) + +Some keys are missing in some modes. + +["mode_change", mode, mode_idx] +The mode changed. The first parameter `mode` is a string representing the +current mode. `mode_idx` is an index into the array received in the +`mode_info_set` event. UIs should change the cursor style according to the +properties specified in the corresponding item. The set of modes reported will +change in new versions of Nvim, for instance more submodes and temporary +states might be represented as separate modes. + + *ui-ext-popupmenu* ["popupmenu_show", items, selected, row, col] When `popupmenu_external` is set to true, nvim will not draw the popupmenu on the grid, instead when the popupmenu is to be displayed @@ -413,5 +434,12 @@ of update. ["popupmenu_hide"] The popupmenu is hidden. + *ui-ext-tabline* +["tabline_update", curtab, tabs] + Tabline was updated. UIs should present this data in a custom tabline + widget. + curtab: Current Tabpage + tabs: List of Dicts [{ "tab": Tabpage, "name": String }, ...] + ============================================================================== vim:tw=78:ts=8:noet:ft=help:norl: diff --git a/runtime/doc/nvim.txt b/runtime/doc/nvim.txt index 7dfbbd0cf0..f3f4305ad5 100644 --- a/runtime/doc/nvim.txt +++ b/runtime/doc/nvim.txt @@ -1,26 +1,30 @@ -*nvim.txt* {Nvim} +*nvim.txt* Nvim NVIM REFERENCE MANUAL -Nvim *nvim* *nvim-intro* +Nvim *nvim* *nvim-intro* -If you are new to Vim (and Nvim) see |help.txt| or type ":Tutor". -If you already use Vim (but not Nvim) see |nvim-from-vim| for a quickstart. +Nvim is based on Vim by Bram Moolenaar. + +If you are new to Vim see |help.txt|, or type ":Tutor". +If you already use Vim see |nvim-from-vim| for a quickstart. Nvim is emphatically a fork of Vim, not a clone: compatibility with Vim is maintained where possible. See |vim_diff.txt| for the complete reference of differences from Vim. + Type <M-]> to see the table of contents. + ============================================================================== Transitioning from Vim *nvim-from-vim* -To start the transition, link your previous configuration so Nvim can use it: +To start the transition, create ~/.config/nvim/init.vim with these contents: > - mkdir ~/.config - ln -s ~/.vim ~/.config/nvim - ln -s ~/.vimrc ~/.config/nvim/init.vim + set runtimepath^=~/.vim runtimepath+=~/.vim/after + let &packpath = &runtimepath + source ~/.vimrc < Note: If your system sets `$XDG_CONFIG_HOME`, use that instead of `~/.config` in the code above. Nvim follows the XDG |base-directories| convention. diff --git a/runtime/doc/nvim_terminal_emulator.txt b/runtime/doc/nvim_terminal_emulator.txt index 8f7dc0dbf0..4527a14710 100644 --- a/runtime/doc/nvim_terminal_emulator.txt +++ b/runtime/doc/nvim_terminal_emulator.txt @@ -1,31 +1,27 @@ -*terminal_emulator.txt* {Nvim} +*terminal_emulator.txt* Nvim NVIM REFERENCE MANUAL by Thiago de Arruda -Embedded terminal emulator *terminal-emulator* +Terminal emulator *terminal* *terminal-emulator* -1. Introduction |terminal-emulator-intro| -2. Spawning |terminal-emulator-spawning| -3. Input |terminal-emulator-input| -4. Configuration |terminal-emulator-configuration| -5. Status Variables |terminal-emulator-status| +Nvim embeds a VT220/xterm terminal emulator based on libvterm. The terminal is +presented as a special buffer type, asynchronously updated from the virtual +terminal as data is received from the program connected to it. -============================================================================== -1. Introduction *terminal-emulator-intro* - -Nvim offers a mostly complete VT220/xterm terminal emulator. The terminal is -presented as a special buffer type, asynchronously updated to mirror the -virtual terminal display as data is received from the program connected to it. -For most purposes, terminal buffers behave a lot like normal buffers with -'nomodifiable' set. +Terminal buffers behave like normal buffers, except: +- With 'modifiable', lines can be edited but not deleted. +- 'scrollback' controls how many lines are kept. +- Output is followed if the cursor is on the last line. +- 'modified' is the default. You can set 'nomodified' to avoid a warning when + closing the terminal buffer. +- 'bufhidden' defaults to "hide". -The implementation is powered by libvterm, a powerful abstract terminal -emulation library. http://www.leonerd.org.uk/code/libvterm/ + Type <M-]> to see the table of contents. ============================================================================== -2. Spawning *terminal-emulator-spawning* +Start *terminal-start* There are 3 ways to create a terminal buffer: @@ -40,48 +36,44 @@ There are 3 ways to create a terminal buffer: Note: The "term://" pattern is handled by a BufReadCmd handler, so the |autocmd-nested| modifier is required to use it in an autocmd. > autocmd VimEnter * nested split term://sh -< This is only mentioned for reference; you should use the |:terminal| - command instead. +< This is only mentioned for reference; use |:terminal| instead. -When the terminal spawns the program, the buffer will start to mirror the -terminal display and change its name to `term://$CWD//$PID:$COMMAND`. -Note that |:mksession| will "save" the terminal buffers by restarting all -programs when the session is restored. +When the terminal starts, the buffer contents are updated and the buffer is +named in the form of `term://{cwd}//{pid}:{cmd}`. This naming scheme is used +by |:mksession| to restore a terminal buffer (by restarting the {cmd}). ============================================================================== -3. Input *terminal-emulator-input* - -Sending input is possible by entering terminal mode, which is achieved by -pressing any key that would enter insert mode in a normal buffer (|i| or |a| -for example). The |:terminal| ex command will automatically enter terminal -mode once it's spawned. While in terminal mode, Nvim will forward all keys to -the underlying program. The only exception is the <C-\><C-n> key combo, -which will exit back to normal mode. - -Terminal mode has its own namespace for mappings, which is accessed with the -"t" prefix. It's possible to use terminal mappings to customize interaction -with the terminal. For example, here's how to map <Esc> to exit terminal mode: -> +Input *terminal-input* + +To send input, enter |Terminal-mode| using any command that would enter "insert +mode" in a normal buffer, such as |i| or |:startinsert|. In this mode all keys +except <C-\><C-N> are sent to the underlying program. Use <C-\><C-N> to return +to normal-mode. |CTRL-\_CTRL-N| + +Terminal-mode has its own |:tnoremap| namespace for mappings, this can be used +to automate any terminal interaction. + +To map <Esc> to exit terminal-mode: > :tnoremap <Esc> <C-\><C-n> -< -Navigating to other windows is only possible by exiting to normal mode, which -can be cumbersome with <C-\><C-n> keys. To improve the navigation experience, -you could use the following mappings: -> - :tnoremap <A-h> <C-\><C-n><C-w>h - :tnoremap <A-j> <C-\><C-n><C-w>j - :tnoremap <A-k> <C-\><C-n><C-w>k - :tnoremap <A-l> <C-\><C-n><C-w>l + +To simulate |i_CTRL-R| in terminal-mode: > + :tnoremap <expr> <C-R> '<C-\><C-N>"'.nr2char(getchar()).'pi' + +To use `ALT+{h,j,k,l}` to navigate windows from any mode: > + :tnoremap <A-h> <C-\><C-N><C-w>h + :tnoremap <A-j> <C-\><C-N><C-w>j + :tnoremap <A-k> <C-\><C-N><C-w>k + :tnoremap <A-l> <C-\><C-N><C-w>l + :inoremap <A-h> <C-\><C-N><C-w>h + :inoremap <A-j> <C-\><C-N><C-w>j + :inoremap <A-k> <C-\><C-N><C-w>k + :inoremap <A-l> <C-\><C-N><C-w>l :nnoremap <A-h> <C-w>h :nnoremap <A-j> <C-w>j :nnoremap <A-k> <C-w>k :nnoremap <A-l> <C-w>l -< -This configuration allows using `Alt+{h,j,k,l}` to navigate between windows no -matter if they are displaying a normal buffer or a terminal buffer in terminal -mode. -Mouse input is also fully supported, and has the following behavior: +Mouse input has the following behavior: - If the program has enabled mouse events, the corresponding events will be forwarded to the program. @@ -93,28 +85,31 @@ Mouse input is also fully supported, and has the following behavior: the terminal wont lose focus and the hovered window will be scrolled. ============================================================================== -4. Configuration *terminal-emulator-configuration* +Configuration *terminal-configuration* + +Options: 'modified', 'scrollback' +Events: |TermOpen|, |TermClose| +Highlight groups: |hl-TermCursor|, |hl-TermCursorNC| -Terminal buffers can be customized through the following global/buffer-local -variables (set via the |TermOpen| autocmd): +Terminal sets local defaults for some options, which may differ from your +global configuration. -- `{g,b}:terminal_scrollback_buffer_size`: Scrollback buffer size, between 1 - and 100000 inclusive. The default is 1000. -- `{g,b}:terminal_color_$NUM`: The terminal color palette, where `$NUM` is the - color index, between 0 and 255 inclusive. This setting only affects UIs with - RGB capabilities; for normal terminals the color index is simply forwarded. +- 'list' is disabled +- 'wrap' is disabled +- 'relativenumber' is disabled in |Terminal-mode| (and cannot be enabled) -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. +You can change the defaults with a TermOpen autocommand: > + au TermOpen * setlocal list -There is also a corresponding |TermClose| event. +TERMINAL COLORS ~ -The terminal cursor can be highlighted via |hl-TermCursor| and -|hl-TermCursorNC|. +The `{g,b}:terminal_color_$NUM` variables control the terminal color palette, +where `$NUM` is the color index between 0 and 255 inclusive. This setting only +affects UIs with RGB capabilities; for normal terminals the color index is +just forwarded. The variables are read only during |TermOpen|. ============================================================================== -5. Status Variables *terminal-emulator-status* +Status Variables *terminal-status* Terminal buffers maintain some information about the terminal in buffer-local variables: @@ -127,11 +122,8 @@ variables: - *b:terminal_job_pid* The PID of the top-level process running in the terminal. -These variables will have a value by the time the TermOpen autocmd runs, and -will continue to have a value for the lifetime of the terminal buffer, making -them suitable for use in 'statusline'. For example, to show the terminal title -as the status line: -> +These variables are initialized before TermOpen, so you can use them in +a local 'statusline'. Example: > :autocmd TermOpen * setlocal statusline=%{b:term_title} < ============================================================================== diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index d332e0053a..c6965648ef 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -1,4 +1,4 @@ -*options.txt* For Vim version 7.4. Last change: 2016 Jul 12 +*options.txt* Nvim VIM REFERENCE MANUAL by Bram Moolenaar @@ -6,11 +6,7 @@ Options *options* -1. Setting options |set-option| -2. Automatically setting options |auto-setting| -3. Options summary |option-summary| - -For an overview of options see help.txt |option-list|. +For an overview of options see quickref.txt |option-list|. Vim has a number of internal variables and switches which can be set to achieve special effects. These options come in three forms: @@ -18,18 +14,15 @@ achieve special effects. These options come in three forms: number has a numeric value string has a string value + Type <M-]> to see the table of contents. + ============================================================================== 1. Setting options *set-option* *E764* *:se* *:set* :se[t] Show all options that differ from their default value. -:se[t] all Show all but terminal options. - -:se[t] termcap Show all terminal options. Note that in the GUI the - key codes are not shown, because they are generated - internally and can't be changed. Changing the terminal - codes in the GUI is not useful either... +:se[t] all Show all options. *E518* *E519* :se[t] {option}? Show value of {option}. @@ -130,39 +123,6 @@ A few special texts: Last set from error handler ~ Option was cleared when evaluating it resulted in an error. -{not available when compiled without the |+eval| feature} - - *:set-termcap* *E522* -For {option} the form "t_xx" may be used to set a terminal option. This will -override the value from the termcap. You can then use it in a mapping. If -the "xx" part contains special characters, use the <t_xx> form: > - :set <t_#4>=^[Ot -This can also be used to translate a special code for a normal key. For -example, if Alt-b produces <Esc>b, use this: > - :set <M-b>=^[b -(the ^[ is a real <Esc> here, use CTRL-V <Esc> to enter it) -The advantage over a mapping is that it works in all situations. - -You can define any key codes, e.g.: > - :set t_xy=^[foo; -There is no warning for using a name that isn't recognized. You can map these -codes as you like: > - :map <t_xy> something -< *E846* -When a key code is not set, it's like it does not exist. Trying to get its -value will result in an error: > - :set t_kb= - :set t_kb - E846: Key code not set: t_kb - -The t_xx options cannot be set from a |modeline| or in the |sandbox|, for -security reasons. - -The listing from ":set" looks different from Vi. Long string options are put -at the end of the list. The number of options is quite large. The output of -"set all" probably does not fit on the screen, causing Vim to give the -|more-prompt|. - *option-backslash* To include white space in a string option value it has to be preceded with a backslash. To include a backslash you have to use two. Effectively this @@ -398,20 +358,6 @@ command, not when assigning a value to an option with ":let". Note the maximum length of an expanded option is limited. How much depends on the system, mostly it is something like 256 or 1024 characters. - *Linux-backspace* - Note about Linux: By default the backspace key - produces CTRL-?, which is wrong. You can fix it by - putting this line in your rc.local: > - echo "keycode 14 = BackSpace" | loadkeys -< - *NetBSD-backspace* - Note about NetBSD: If your backspace doesn't produce - the right code, try this: > - xmodmap -e "keycode 22 = BackSpace" -< If this works, add this in your .Xmodmap file: > - keysym 22 = BackSpace -< You need to restart for this to take effect. - ============================================================================== 2. Automatically setting options *auto-setting* @@ -642,7 +588,7 @@ A jump table for the options with a short description can be found at |Q_op|. See Unicode Standard Annex #11 (http://www.unicode.org/reports/tr11). Vim may set this option automatically at startup time when Vim is - compiled with the |+termresponse| feature and if |t_u7| is set to the + compiled with the |+termresponse| feature and if t_u7 is set to the escape sequence to request cursor position report. *'autochdir'* *'acd'* *'noautochdir'* *'noacd'* @@ -979,7 +925,7 @@ A jump table for the options with a short description can be found at |Q_op|. 'balloonexpr' 'bexpr' Removed. {Nvim} *'belloff'* *'bo'* -'belloff' 'bo' string (default "") +'belloff' 'bo' string (default "all") global Specifies for which events the bell will not be rung. It is a comma separated list of items. For each item that is present, the bell @@ -1238,8 +1184,8 @@ A jump table for the options with a short description can be found at |Q_op|. Only non-printable keys are allowed. The key can be specified as a single character, but it is difficult to type. The preferred way is to use the <> notation. Examples: > - :set cedit=<C-Y> - :set cedit=<Esc> + :exe "set cedit=\<C-Y>" + :exe "set cedit=\<Esc>" < |Nvi| also has this option, but it only uses the first character. See |cmdwin|. @@ -1620,7 +1566,6 @@ A jump table for the options with a short description can be found at |Q_op|. results in X being mapped to: 'B' included: "\^[" (^[ is a real <Esc>) 'B' excluded: "<Esc>" (5 characters) - ('<' excluded in both cases) *cpo-c* c Searching continues at the end of any match at the cursor position, but not further than the start of the @@ -1670,15 +1615,6 @@ A jump table for the options with a short description can be found at |Q_op|. J A |sentence| has to be followed by two spaces after the '.', '!' or '?'. A <Tab> is not recognized as white space. - *cpo-k* - k Disable the recognition of raw key codes in - mappings, abbreviations, and the "to" part of menu - commands. For example, if <Key> sends ^[OA (where ^[ - is <Esc>), the command ":map X ^[OA" results in X - being mapped to: - 'k' included: "^[OA" (3 characters) - 'k' excluded: "<Key>" (one key code) - Also see the '<' flag below. *cpo-K* K Don't wait for a key code to complete when it is halfway through a mapping. This breaks mapping @@ -1812,14 +1748,6 @@ A jump table for the options with a short description can be found at |Q_op|. + When included, a ":write file" command will reset the 'modified' flag of the buffer, even though the buffer itself may still be different from its file. - *cpo-<* - < Disable the recognition of special key codes in |<>| - form in mappings, abbreviations, and the "to" part of - menu commands. For example, the command - ":map X <Tab>" results in X being mapped to: - '<' included: "<Tab>" (5 characters) - '<' excluded: "^I" (^I is a real <Tab>) - Also see the 'k' flag above. *cpo->* > When appending to a register, put a line break before the appended text. @@ -1829,6 +1757,9 @@ A jump table for the options with a short description can be found at |Q_op|. character, the cursor won't move. When not included, the cursor would skip over it and jump to the following occurrence. + *cpo-_* + _ When using |cw| on a word, do not include the + whitespace following the word in the motion. *'cscopepathcomp'* *'cspc'* 'cscopepathcomp' 'cspc' number (default 0) @@ -2103,7 +2034,7 @@ A jump table for the options with a short description can be found at |Q_op|. uhex Show unprintable characters hexadecimal as <xx> instead of using ^C and ~C. - When neither "lastline" or "truncate" is included, a last line that + When neither "lastline" nor "truncate" is included, a last line that doesn't fit is replaced with "@" lines. *'eadirection'* *'ead'* @@ -2183,9 +2114,8 @@ A jump table for the options with a short description can be found at |Q_op|. Ring the bell (beep or screen flash) for error messages. This only makes a difference for error messages, the bell will be used always for a lot of errors without a message (e.g., hitting <Esc> in Normal - mode). See 'visualbell' on how to make the bell behave like a beep, - screen flash or do nothing. See 'belloff' to finetune when to ring the - bell. + mode). See 'visualbell' to make the bell behave like a screen flash + or do nothing. See 'belloff' to finetune when to ring the bell. *'errorfile'* *'ef'* 'errorfile' 'ef' string (default: "errors.err") @@ -2209,18 +2139,6 @@ A jump table for the options with a short description can be found at |Q_op|. Scanf-like description of the format for the lines in the error file (see |errorformat|). - *'esckeys'* *'ek'* *'noesckeys'* *'noek'* -'esckeys' 'ek' boolean (Vim default: on, Vi default: off) - global - Function keys that start with an <Esc> are recognized in Insert - mode. When this option is off, the cursor and function keys cannot be - used in Insert mode if they start with an <Esc>. The advantage of - this is that the single <Esc> is recognized immediately, instead of - after one second. Instead of resetting this option, you might want to - try changing the values for 'timeoutlen' and 'ttimeoutlen'. Note that - when 'esckeys' is off, you can still map anything, but the cursor keys - won't work by default. - *'eventignore'* *'ei'* 'eventignore' 'ei' string (default "") global @@ -2243,10 +2161,15 @@ 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 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! + Enables the reading of .vimrc and .exrc in the current directory. + Setting this option is a potential security leak. E.g., consider + unpacking a package or fetching files from github, a .vimrc in there + might be a trojan horse. BETTER NOT SET THIS OPTION! + Instead, define an autocommand in your .vimrc to set options for a + matching directory. + + If you do switch this option on you should also consider setting the + 'secure' option (see |initialization|). This option cannot be set from a |modeline| or in the |sandbox|, for security reasons. Also see |init.vim| and |gui-init|. @@ -2741,7 +2664,7 @@ A jump table for the options with a short description can be found at |Q_op|. *'formatprg'* *'fp'* 'formatprg' 'fp' string (default "") - global + global or local to buffer |global-local| The name of an external program that will be used to format the lines selected with the |gq| operator. The program must take the input on stdin and produce the output on stdout. The Unix program "fmt" is @@ -2764,6 +2687,9 @@ A jump table for the options with a short description can be found at |Q_op|. mode, so it may be undesirable in some situations. Be warned that turning this off increases the chances of data loss after a crash. + Currently applies only to writing the buffer with e.g. |:w| and + |writefile()|. + *'gdefault'* *'gd'* *'nogdefault'* *'nogd'* 'gdefault' 'gd' boolean (default off) global @@ -2786,8 +2712,7 @@ A jump table for the options with a short description can be found at |Q_op|. *'grepprg'* *'gp'* 'grepprg' 'gp' string (default "grep -n ", - Unix: "grep -n $* /dev/null", - Win32: "findstr /n" or "grep -n") + Unix: "grep -n $* /dev/null") global or local to buffer |global-local| Program to use for the |:grep| command. This option may contain '%' and '#' characters, which are expanded like when used in a command- @@ -2802,33 +2727,24 @@ A jump table for the options with a short description can be found at |Q_op|. |:vimgrepadd| and |:lgrepadd| like |:lvimgrepadd|. See also the section |:make_makeprg|, since most of the comments there apply equally to 'grepprg'. - For Win32, the default is "findstr /n" if "findstr.exe" can be found, - otherwise it's "grep -n". This option cannot be set from a |modeline| or in the |sandbox|, for security reasons. *'guicursor'* *'gcr'* *E545* *E546* *E548* *E549* -'guicursor' 'gcr' string (default "n-v-c:block-Cursor/lCursor, - ve:ver35-Cursor, - o:hor50-Cursor, - i-ci:ver25-Cursor/lCursor, - r-cr:hor20-Cursor/lCursor, - sm:block-Cursor - -blinkwait175-blinkoff150-blinkon175", - for Windows console: - "n-v-c:block,o:hor50,i-ci:hor15, - r-cr:hor30,sm:block") - global - {only available when compiled with GUI enabled, and - for Windows console} - This option tells Vim what the cursor should look like in different - modes. It fully works in the GUI. In a Windows console, only - the height of the cursor can be changed. This can be done by - specifying a block cursor, or a percentage for a vertical or - horizontal cursor. - For a console the 't_SI' and 't_EI' escape sequences are used. - - The option is a comma separated list of parts. Each part consist of a +'guicursor' 'gcr' string (default "n-v-c-sm:block,i-ci-ve:ver25,r-cr-o:hor20") + global + Configures the cursor style for each mode. Works in the GUI and many + terminals. See |tui-cursor-shape|. + + To disable cursor-styling, reset the option: > + :set guicursor= + +< To enable mode shapes, "Cursor" highlight, and blinking: > + :set guicursor=n-v-c:block,i-ci-ve:ver25,r-cr:hor20,o:hor50 + \,a:blinkwait700-blinkoff400-blinkon250-Cursor/lCursor + \,sm:block-blinkwait175-blinkoff150-blinkon175 + +< The option is a comma separated list of parts. Each part consists of a mode-list and an argument-list: mode-list:argument-list,mode-list:argument-list,.. The mode-list is a dash separated list of these modes: @@ -2856,16 +2772,9 @@ A jump table for the options with a short description can be found at |Q_op|. the cursor starts blinking, blinkon is the time that the cursor is shown and blinkoff is the time that the cursor is not shown. The times are in msec. When one - of the numbers is zero, there is no blinking. The - default is: "blinkwait700-blinkon400-blinkoff250". - These numbers are used for a missing entry. This - means that blinking is enabled by default. To switch - blinking off you can use "blinkon0". The cursor only - blinks when Vim is waiting for input, not while - executing a command. - To make the cursor blink in an xterm, see - |xterm-blink|. - {group-name} + of the numbers is zero, there is no blinking. E.g.: > + :set guicursor=n:blinkon0 +< {group-name} a highlight group name, that sets the color and font for the cursor {group-name}/{group-name} @@ -3001,18 +2910,6 @@ A jump table for the options with a short description can be found at |Q_op|. If set and valid, 'guifontwide' is used for IME instead of 'guifont'. - *'guiheadroom'* *'ghr'* -'guiheadroom' 'ghr' number (default 50) - global - {only for X11 GUI} - The number of pixels subtracted from the screen height when fitting - the GUI window on the screen. Set this before the GUI is started, - e.g., in your |gvimrc| file. When zero, the whole screen height will - be used by the window. When positive, the specified number of pixel - lines will be left for window decorations and other items on the - screen. Set it to a negative value to allow windows taller than the - screen. - *'guioptions'* *'go'* 'guioptions' 'go' string (default "egmrLT" (MS-Windows)) global @@ -3196,84 +3093,9 @@ A jump table for the options with a short description can be found at |Q_op|. Think twice when using ":q!" or ":qa!". *'highlight'* *'hl'* -'highlight' 'hl' string (default (as a single string): - "8:SpecialKey,~:EndOfBuffer,z:TermCursor, - Z:TermCursorNC,@:NonText,d:Directory, - e:ErrorMsg,i:IncSearch,l:Search, - m:MoreMsg,M:ModeMsg,n:LineNr, - N:CursorLineNr,r:Question,s:StatusLine, - S:StatusLineNC,c:VertSplit,t:Title, - v:Visual,w:WarningMsg,W:WildMenu, - f:Folded,F:FoldColumn,A:DiffAdd, - C:DiffChange,D:DiffDelete,T:DiffText, - >:SignColumn,B:SpellBad,P:SpellCap, - R:SpellRare,L:SpellLocal,-:Conceal, - +:Pmenu,=:PmenuSel,x:PmenuSbar, - X:PmenuThumb") - global - This option can be used to set highlighting mode for various - occasions. It is a comma separated list of character pairs. The - first character in a pair gives the occasion, the second the mode to - use for that occasion. The occasions are: - |hl-SpecialKey| 8 Meta and special keys listed with ":map" - |hl-EndOfBuffer| ~ lines after the last line in the buffer - |hl-TermCursor| z Cursor in a focused terminal - |hl-TermCursorNC| Z Cursor in an unfocused terminal - |hl-NonText| @ '@' at the end of the window and - characters from 'showbreak' - |hl-Directory| d directories in CTRL-D listing and other special - things in listings - |hl-ErrorMsg| e error messages - |hl-IncSearch| i 'incsearch' highlighting - |hl-Search| l last search pattern highlighting (see 'hlsearch') - |hl-MoreMsg| m |more-prompt| - |hl-ModeMsg| M Mode (e.g., "-- INSERT --") - |hl-LineNr| n line number for ":number" and ":#" commands, and - when 'number' or 'relativenumber' option is set. - |hl-CursorLineNr| N like n for when 'cursorline' or 'relativenumber' is - set. - |hl-Question| r |hit-enter| prompt and yes/no questions - |hl-StatusLine| s status line of current window |status-line| - |hl-StatusLineNC| S status lines of not-current windows - |hl-Title| t Titles for output from ":set all", ":autocmd" etc. - |hl-VertSplit| c column used to separate vertically split windows - |hl-Visual| v Visual mode - |hl-WarningMsg| w warning messages - |hl-WildMenu| W wildcard matches displayed for 'wildmenu' - |hl-Folded| f line used for closed folds - |hl-FoldColumn| F 'foldcolumn' - |hl-DiffAdd| A added line in diff mode - |hl-DiffChange| C changed line in diff mode - |hl-DiffDelete| D deleted line in diff mode - |hl-DiffText| T inserted text in diff mode - |hl-SignColumn| > column used for |signs| - |hl-SpellBad| B misspelled word |spell| - |hl-SpellCap| P word that should start with capital |spell| - |hl-SpellRare| R rare word |spell| - |hl-SpellLocal| L word from other region |spell| - |hl-Conceal| - the placeholders used for concealed characters - (see 'conceallevel') - |hl-Pmenu| + popup menu normal line - |hl-PmenuSel| = popup menu normal line - |hl-PmenuSbar| x popup menu scrollbar - |hl-PmenuThumb| X popup menu scrollbar thumb - - The display modes are: - r reverse (termcap entry "mr" and "me") - i italic (termcap entry "ZH" and "ZR") - b bold (termcap entry "md" and "me") - s standout (termcap entry "so" and "se") - u underline (termcap entry "us" and "ue") - c undercurl (termcap entry "Cs" and "Ce") - n no highlighting - - no highlighting - : use a highlight group - The default is used for occasions that are not included. - When using the ':' display mode, this must be followed by the name of - a highlight group. A highlight group can be used to define any type - of highlighting, including using color. See |:highlight| on how to - define one. The default uses a different group for each occasion. - See |highlight-default| for the default highlight groups. +'highlight' 'hl' Removed. |vim-differences| + global + The builtin |highlight-groups| cannot be changed. *'hlsearch'* *'hls'* *'nohlsearch'* *'nohls'* 'hlsearch' 'hls' boolean (default on) @@ -3469,6 +3291,8 @@ A jump table for the options with a short description can be found at |Q_op|. original position when no match is found and when pressing <Esc>. You still need to finish the search command with <Enter> to move the cursor to the match. + You can use the CTRL-G and CTRL-T keys to move to the next and + previous match. |c_CTRL-G| |c_CTRL-T| Vim only searches for about half a second. With a complicated pattern and/or a lot of text the match may not be found. This is to avoid that Vim hangs while you are typing the pattern. @@ -3542,7 +3366,7 @@ A jump table for the options with a short description can be found at |Q_op|. if you want to use Vim as a modeless editor. These Insert mode commands will be useful: - Use the cursor keys to move around. - - Use CTRL-O to execute one Normal mode command |i_CTRL-O|). When + - Use CTRL-O to execute one Normal mode command |i_CTRL-O|. When this is a mapping, it is executed as if 'insertmode' was off. Normal mode remains active until the mapping is finished. - Use CTRL-L to execute a number of Normal mode commands, then use @@ -3732,6 +3556,8 @@ A jump table for the options with a short description can be found at |Q_op|. be able to execute Normal mode commands. This is the opposite of the 'keymap' option, where characters are mapped in Insert mode. + Also consider resetting 'langremap' to avoid 'langmap' applies to + characters resulting from a mapping. This option cannot be set from a |modeline| or in the |sandbox|, for security reasons. @@ -3786,12 +3612,12 @@ A jump table for the options with a short description can be found at |Q_op|. :source $VIMRUNTIME/menu.vim < Warning: This deletes all menus that you defined yourself! - *'langnoremap'* *'lnr'* -'langnoremap' 'lnr' boolean (default on) + *'langremap'* *'lrm'* *'nolangremap'* *'nolrm'* +'langremap' 'lrm' boolean (default off) global - When on, setting 'langmap' does not apply to characters resulting from + When off, setting 'langmap' does not apply to characters resulting from a mapping. If setting 'langmap' disables some of your mappings, make - sure this option is set. + sure this option is off. *'laststatus'* *'ls'* 'laststatus' 'ls' number (default 2) @@ -3840,9 +3666,6 @@ A jump table for the options with a short description can be found at |Q_op|. use this command to get the tallest window possible: > :set lines=999 < Minimum value is 2, maximum value is 1000. - If you get less lines than expected, check the 'guiheadroom' option. - When you set this option and Vim is unable to change the physical - number of lines of the display, the display may be messed up. *'linespace'* *'lsp'* 'linespace' 'lsp' number (default 0, 1 for Win32 GUI) @@ -3942,9 +3765,8 @@ A jump table for the options with a short description can be found at |Q_op|. :set lcs=tab:>-,trail:- :set lcs=tab:>-,eol:<,nbsp:% :set lcs=extends:>,precedes:< -< The "NonText" highlighting will be used for "eol", "extends" and - "precedes". "SpecialKey" for "nbsp", "space", "tab" and "trail". - |hl-NonText| |hl-SpecialKey| +< |hl-NonText| highlighting will be used for "eol", "extends" and + "precedes". |hl-Whitespace| for "nbsp", "space", "tab" and "trail". *'lpl'* *'nolpl'* *'loadplugins'* *'noloadplugins'* 'loadplugins' 'lpl' boolean (default on) @@ -3960,10 +3782,11 @@ A jump table for the options with a short description can be found at |Q_op|. global Changes the special characters that can be used in search patterns. See |pattern|. - NOTE: To avoid portability problems with using patterns, always keep - this option at the default "on". Only switch it off when working with - old Vi scripts. In any other situation write patterns that work when - 'magic' is on. Include "\M" when you want to |/\M|. + WARNING: Switching this option off most likely breaks plugins! That + is because many patterns assume it's on and will fail when it's off. + Only switch it off when working with old Vi scripts. In any other + situation write patterns that work when 'magic' is on. Include "\M" + when you want to |/\M|. *'makeef'* *'mef'* 'makeef' 'mef' string (default: "") @@ -4048,6 +3871,8 @@ A jump table for the options with a short description can be found at |Q_op|. catches endless recursion. When using a recursive function with more depth, set 'maxfuncdepth' to a bigger number. But this will use more memory, there is the danger of failing when memory is exhausted. + Increasing this limit above 200 also changes the maximum for Ex + command resursion, see |E169|. See also |:function|. *'maxmapdepth'* *'mmd'* *E223* @@ -4159,7 +3984,7 @@ A jump table for the options with a short description can be found at |Q_op|. local to buffer When off the buffer contents cannot be changed. The 'fileformat' and 'fileencoding' options also can't be changed. - Can be reset with the |-M| command line argument. + Can be reset on startup with the |-M| command line argument. *'modified'* *'mod'* *'nomodified'* *'nomod'* 'modified' 'mod' boolean (default off) @@ -4192,7 +4017,7 @@ A jump table for the options with a short description can be found at |Q_op|. listing continues until finished. *'mouse'* *E538* -'mouse' string (default "a") +'mouse' string (default "") global Enable the use of the mouse. Only works for certain terminals. @@ -4452,7 +4277,7 @@ A jump table for the options with a short description can be found at |Q_op|. *'paste'* *'nopaste'* 'paste' boolean (default off) global - You probably don't have to set this option: |bracketed-paste-mode|. + This option is obsolete; |bracketed-paste-mode| is built-in. Put Vim in Paste mode. This is useful if you want to cut or copy some text from one window and paste it in Vim. This will avoid @@ -4516,7 +4341,8 @@ A jump table for the options with a short description can be found at |Q_op|. Note that typing <F10> in paste mode inserts "<F10>", since in paste mode everything is inserted literally, except the 'pastetoggle' key sequence. - When the value has several bytes 'ttimeoutlen' applies. + No timeout is used, this means that a multi-key 'pastetoggle' can not + be triggered manually. *'pex'* *'patchexpr'* 'patchexpr' 'pex' string (default "") @@ -4730,6 +4556,7 @@ A jump table for the options with a short description can be found at |Q_op|. buffer, unless the 'Z' flag is in 'cpoptions'. When using the ":view" command the 'readonly' option is set for the newly edited buffer. + See 'modifiable' for disallowing changes to the buffer. *'redrawtime'* *'rdt'* 'redrawtime' 'rdt' number (default 2000) @@ -4831,10 +4658,8 @@ A jump table for the options with a short description can be found at |Q_op|. The 'rightleft' option must be set for 'rightleftcmd' to take effect. *'ruler'* *'ru'* *'noruler'* *'noru'* -'ruler' 'ru' boolean (default off) +'ruler' 'ru' boolean (default on) global - {not available when compiled without the - |+cmdline_info| feature} Show the line and column number of the cursor position, separated by a comma. When there is room, the relative position of the displayed text in the file is shown on the far right: @@ -4931,7 +4756,9 @@ A jump table for the options with a short description can be found at |Q_op|. ordering. This is for preferences to overrule or add to the distributed defaults or system-wide settings (rarely needed). - More entries are added when using |packages|. + More entries are added when using |packages|. If it gets very long + then `:set rtp` will be truncated, use `:echo &rtp` to see the full + string. Note that, unlike 'path', no wildcards like "**" are allowed. Normal wildcards are allowed, but can significantly slow down searching for @@ -4961,6 +4788,16 @@ A jump table for the options with a short description can be found at |Q_op|. be used as the new value for 'scroll'. Reset to half the window height with ":set scroll=0". + *'scrollback'* *'scbk'* +'scrollback' 'scbk' number (default: 1000 + in normal buffers: -1) + local to buffer + Maximum number of lines kept beyond the visible screen. Lines at the + top are deleted if new lines exceed this limit. + Only in |terminal| buffers. + -1 means "unlimited" for normal buffers, 100000 otherwise. + Minimum is 1. + *'scrollbind'* *'scb'* *'noscrollbind'* *'noscb'* 'scrollbind' 'scb' boolean (default off) local to window @@ -5064,6 +4901,8 @@ A jump table for the options with a short description can be found at |Q_op|. "inclusive" means that the last character of the selection is included in an operation. For example, when "x" is used to delete the selection. + When "old" is used and 'virtualedit' allows the cursor to move past + the end of line the line break still isn't included. Note that when "exclusive" is used and selecting from the end backwards, you cannot include the last character of a line, when starting in Normal mode and 'virtualedit' empty. @@ -5187,8 +5026,8 @@ A jump table for the options with a short description can be found at |Q_op|. saved. When not included, the value of 'history' is used. *shada-c* c Dummy option, kept for compatibility reasons. Has no actual - effect. Current encoding state is described in - |shada-encoding|. + effect: ShaDa always uses UTF-8 and 'encoding' value is fixed + to UTF-8 as well. *shada-f* f Whether file marks need to be stored. If zero, file marks ('0 to '9, 'A to 'Z) are not stored. When not present or when @@ -5200,10 +5039,10 @@ A jump table for the options with a short description can be found at |Q_op|. has been used since the last search command. *shada-n* n Name of the shada file. The name must immediately follow - the 'n'. Must be the last one! If the "-i" argument was - given when starting Vim, that file name overrides the one - given here with 'shada'. Environment variables are expanded - when opening the file, not when setting the option. + the 'n'. Must be at the end of the option! If the "-i" + argument was given when starting Vim, that file name overrides + the one given here with 'shada'. Environment variables are + expanded when opening the file, not when setting the option. *shada-r* r Removable media. The argument is a string (up to the next ','). This parameter can be given several times. Each @@ -5287,9 +5126,7 @@ A jump table for the options with a short description can be found at |Q_op|. security reasons. *'shellcmdflag'* *'shcf'* -'shellcmdflag' 'shcf' string (default: "-c"; - Windows, when 'shell' does not - contain "sh" somewhere: "/c") +'shellcmdflag' 'shcf' string (default: "-c"; Windows: "/c") global Flag passed to the shell to execute "!" and ":!" commands; e.g., "bash.exe -c ls" or "cmd.exe /c dir". For Windows @@ -5300,15 +5137,12 @@ A jump table for the options with a short description can be found at |Q_op|. See |option-backslash| about including spaces and backslashes. See |shell-unquoting| which talks about separating this option into multiple arguments. - Also see |dos-shell| for Windows. This option cannot be set from a |modeline| or in the |sandbox|, for security reasons. *'shellpipe'* *'sp'* 'shellpipe' 'sp' string (default ">", "| tee", "|& tee" or "2>&1| tee") global - {not available when compiled without the |+quickfix| - feature} String to be used to put the output of the ":make" command in the error file. See also |:make_makeprg|. See |option-backslash| about including spaces and backslashes. @@ -5350,7 +5184,7 @@ A jump table for the options with a short description can be found at |Q_op|. third-party shells on Windows systems, such as the MKS Korn Shell or bash, where it should be "\"". The default is adjusted according the value of 'shell', to reduce the need to set this option by the - user. See |dos-shell|. + user. This option cannot be set from a |modeline| or in the |sandbox|, for security reasons. @@ -5382,7 +5216,7 @@ A jump table for the options with a short description can be found at |Q_op|. *'shellslash'* *'ssl'* *'noshellslash'* *'nossl'* 'shellslash' 'ssl' boolean (default off) global - {only for MSDOS and MS-Windows} + {only for Windows} When set, a forward slash is used when expanding file names. This is useful when a Unix-like shell is used instead of command.com or cmd.exe. Backward slashes can still be typed, but they are changed to @@ -5399,10 +5233,7 @@ A jump table for the options with a short description can be found at |Q_op|. global When on, use temp files for shell commands. When off use a pipe. When using a pipe is not possible temp files are used anyway. - Currently a pipe is only supported on Unix and MS-Windows 2K and - later. You can check it with: > - :if has("filterpipe") -< The advantage of using a pipe is that nobody can read the temp file + The advantage of using a pipe is that nobody can read the temp file and the 'shell' command does not need to support redirection. The advantage of using a temp file is that the file type and encoding can be detected. @@ -5412,19 +5243,14 @@ A jump table for the options with a short description can be found at |Q_op|. |system()| does not respect this option, it always uses pipes. *'shellxescape'* *'sxe'* -'shellxescape' 'sxe' string (default: ""; - for Windows: "\"&|<>()@^") +'shellxescape' 'sxe' string (default: "") global When 'shellxquote' is set to "(" then the characters listed in this option will be escaped with a '^' character. This makes it possible to execute most external commands with cmd.exe. *'shellxquote'* *'sxq'* -'shellxquote' 'sxq' string (default: ""; - for Win32, when 'shell' is cmd.exe: "(" - for Win32, when 'shell' contains "sh" - somewhere: "\"" - for Unix, when using system(): "\"") +'shellxquote' 'sxq' string (default: "") global Quoting character(s), put around the command passed to the shell, for the "!" and ":!" commands. Includes the redirection. See @@ -5433,12 +5259,6 @@ A jump table for the options with a short description can be found at |Q_op|. When the value is '(' then ')' is appended. When the value is '"(' then ')"' is appended. When the value is '(' then also see 'shellxescape'. - This is an empty string by default on most systems, but is known to be - useful for on Win32 version, either for cmd.exe which automatically - strips off the first and last quote on a command, or 3rd-party shells - such as the MKS Korn Shell or bash, where it should be "\"". The - default is adjusted according the value of 'shell', to reduce the need - to set this option by the user. See |dos-shell|. This option cannot be set from a |modeline| or in the |sandbox|, for security reasons. @@ -5529,11 +5349,8 @@ A jump table for the options with a short description can be found at |Q_op|. "n" flag to 'cpoptions'. *'showcmd'* *'sc'* *'noshowcmd'* *'nosc'* -'showcmd' 'sc' boolean (Vim default: on (off for Unix), - Vi default: off) +'showcmd' 'sc' boolean (Vim default: on, Vi default: off) global - {not available when compiled without the - |+cmdline_info| feature} Show (partial) command in the last line of the screen. Set this option off if your terminal is slow. In Visual mode the size of the selected area is shown: @@ -6285,6 +6102,9 @@ A jump table for the options with a short description can be found at |Q_op|. By default, tag searches are case-sensitive. Case is ignored when 'ignorecase' is set and 'tagcase' is "followic", or when 'tagcase' is "ignore". + Also when 'tagcase' is "followscs" and 'smartcase' is set, or + 'tagcase' is "smart", and the pattern contains only lowercase + characters. When 'tagbsearch' is off, tags searching is slower when a full match exists, but faster when no full match exists. Tags in unsorted tags @@ -6302,8 +6122,10 @@ A jump table for the options with a short description can be found at |Q_op|. This option specifies how case is handled when searching the tags file: followic Follow the 'ignorecase' option + followscs Follow the 'smartcase' and 'ignorecase' options ignore Ignore case match Match case + smart Ignore case unless an upper case letter is used *'taglength'* *'tl'* 'taglength' 'tl' number (default 0) @@ -6423,7 +6245,7 @@ A jump table for the options with a short description can be found at |Q_op|. for any key that can follow <c-f> in a mapping. *'ttimeout'* *'nottimeout'* -'ttimeout' boolean (default off) +'ttimeout' boolean (default on) global This option and 'ttimeoutlen' determine the behavior when part of a key code sequence has been received by the terminal UI. For example, @@ -6438,7 +6260,7 @@ A jump table for the options with a short description can be found at |Q_op|. complete. *'ttimeoutlen'* *'ttm'* -'ttimeoutlen' 'ttm' number (default -1) +'ttimeoutlen' 'ttm' number (default 50) global The time in milliseconds that is waited for a key code sequence to complete. Also used for CTRL-\ CTRL-N and CTRL-\ CTRL-G @@ -6447,8 +6269,6 @@ A jump table for the options with a short description can be found at |Q_op|. *'title'* *'notitle'* 'title' boolean (default off, on when title can be restored) global - {not available when compiled without the |+title| - feature} When on, the title of the window will be set to the value of 'titlestring' (if it is not empty), or to: filename [+=-] (path) - VIM @@ -6460,16 +6280,10 @@ A jump table for the options with a short description can be found at |Q_op|. =+ indicates the file is read-only and modified (path) is the path of the file being edited - VIM the server name |v:servername| or "VIM" - Only works if the terminal supports setting window titles - (currently Win32 console, all GUI versions and terminals with a non- - empty 't_ts' option - this is Unix xterm by default, where 't_ts' is - taken from the builtin termcap). *'titlelen'* 'titlelen' number (default 85) global - {not available when compiled without the |+title| - feature} Gives the percentage of 'columns' to use for the length of the window title. When the title is longer, only the end of the path name is shown. A '<' character before the path name is used to indicate this. @@ -6483,8 +6297,6 @@ A jump table for the options with a short description can be found at |Q_op|. *'titleold'* 'titleold' string (default "Thanks for flying Vim") global - {only available when compiled with the |+title| - feature} This option will be used for the window title when exiting Vim if the original title cannot be restored. Only happens if 'title' is on or 'titlestring' is not empty. @@ -6493,13 +6305,8 @@ A jump table for the options with a short description can be found at |Q_op|. *'titlestring'* 'titlestring' string (default "") global - {not available when compiled without the |+title| - feature} When this option is not empty, it will be used for the title of the window. This happens only when the 'title' option is on. - Only works if the terminal supports setting window titles (currently - Win32 console, all GUI versions and terminals with a non-empty 't_ts' - option). When this option contains printf-style '%' items, they will be expanded according to the rules used for 'statusline'. Example: > @@ -6703,14 +6510,7 @@ A jump table for the options with a short description can be found at |Q_op|. *'visualbell'* *'vb'* *'novisualbell'* *'novb'* *beep* 'visualbell' 'vb' boolean (default off) global - Use visual bell instead of beeping. The terminal code to display the - visual bell is given with 't_vb'. When no beep or flash is wanted, - use ":set vb t_vb=". - Note: When the GUI starts, 't_vb' is reset to its default value. You - might want to set it again in your |gvimrc|. - In the GUI, 't_vb' defaults to "<Esc>|f", which inverts the display - for 20 msec. If you want to use a different time, use "<Esc>|40f", - where 40 is the time in msec. Also see 'errorbells'. + Use visual bell instead of beeping. Also see 'errorbells'. *'warn'* *'nowarn'* 'warn' boolean (default on) @@ -6945,6 +6745,24 @@ A jump table for the options with a short description can be found at |Q_op|. 'winheight' applies to the current window. Use 'winminheight' to set the minimal height for other windows. + *'winhighlight'* *'winhl'* +'winhighlight' 'winhl' string (default empty) + local to window + Window-local highlights. Comma-delimited list of |group-name| pairs + "{hl-builtin}:{hl-group},..." where each {hl-builtin} is a group (from + |highlight-groups|) to be overridden by {hl-group} in the window where + this option was set. Only builting ui highlights are supported, not + syntax highlighting. For that purpose, use |:ownsyntax|. + + Most highlights occuring within the frame of a window are supported. + Highlights of vertical separators are determined by the window to the + left of the separator. The highlight of a tabpage in |tabline| is + determined by the last focused window in the tabpage. Highlights of + the popupmenu are determined by the current window. Highlights in the + message area are not overridable. Example for overriding the + backgrond color: > + set winhighlight=Normal:MyNormal,NormalNC:MyNormalNC +< *'winfixheight'* *'wfh'* *'nowinfixheight'* *'nowfh'* 'winfixheight' 'wfh' boolean (default off) local to window @@ -7074,7 +6892,7 @@ A jump table for the options with a short description can be found at |Q_op|. *'writedelay'* *'wd'* 'writedelay' 'wd' number (default 0) global - The number of microseconds to wait for each character sent to the + The number of milliseconds to wait for each character sent to the screen. When non-zero, characters are sent to the terminal one by one. For debugging purposes. diff --git a/runtime/doc/os_win32.txt b/runtime/doc/os_win32.txt deleted file mode 100644 index 5dc276c9df..0000000000 --- a/runtime/doc/os_win32.txt +++ /dev/null @@ -1,206 +0,0 @@ -*os_win32.txt* For Vim version 7.4. Last change: 2016 Mar 05 - - - VIM REFERENCE MANUAL by George Reilly - - - *win32* *Win32* *MS-Windows* -This file documents the idiosyncrasies of the Win32 version of Vim. - -The Win32 version of Vim works on Windows XP, Vista and Windows 7. -There are both console and GUI versions. - -The 32 bit version also runs on 64 bit MS-Windows systems. - -1. Known problems |win32-problems| -2. Startup |win32-startup| -3. Using the mouse |win32-mouse| -4. Win32 mini FAQ |win32-faq| - -Additionally, there are a number of common Win32 and DOS items: -File locations |dos-locations| -Using backslashes |dos-backslash| -Standard mappings |dos-standard-mappings| -Screen output and colors |dos-colors| -File formats |dos-file-formats| -:cd command |dos-:cd| -Interrupting |dos-CTRL-Break| -Temp files |dos-temp-files| -Shell option default |dos-shell| - -Win32 GUI |gui-w32| - -Credits: -The Win32 version was written by George V. Reilly <george@reilly.org>. -The GUI version was made by George V. Reilly and Robert Webb. - -============================================================================== -1. Known problems *win32-problems* - -When doing file name completion, Vim also finds matches for the short file -name. But Vim will still find and use the corresponding long file name. For -example, if you have the long file name "this_is_a_test" with the short file -name "this_i~1", the command ":e *1" will start editing "this_is_a_test". - -============================================================================== -2. Startup *win32-startup* - -Current directory *win32-curdir* - -If Vim is started with a single file name argument, and it has a full path -(starts with "x:\"), Vim assumes it was started from the file explorer and -will set the current directory to where that file is. To avoid this when -typing a command to start Vim, use a forward slash instead of a backslash. -Example: > - - vim c:\text\files\foo.txt - -Will change to the "C:\text\files" directory. > - - vim c:/text\files\foo.txt - -Will use the current directory. - - -Term option *win32-term* - -The only kind of terminal type that the Win32 version of Vim understands is -"win32", which is built-in. If you set 'term' to anything else, you will -probably get very strange behavior from Vim. Therefore Vim does not obtain -the default value of 'term' from the environment variable "TERM". - -$PATH *win32-PATH* - -The directory of the Vim executable is appended to $PATH. This is mostly to -make "!xxd" work, as it is in the Tools menu. And it also means that when -executable() returns 1 the executable can actually be executed. - -Quotes in file names *win32-quotes* - -Quotes inside a file name (or any other command line argument) can be escaped -with a backslash. E.g. > - vim -c "echo 'foo\"bar'" - -Alternatively use three quotes to get one: > - vim -c "echo 'foo"""bar'" - -The quotation rules are: - -1. A `"` starts quotation. -2. Another `"` or `""` ends quotation. If the quotation ends with `""`, a `"` - is produced at the end of the quoted string. - -Examples, with [] around an argument: - "foo" -> [foo] - "foo"" -> [foo"] - "foo"bar -> [foobar] - "foo" bar -> [foo], [bar] - "foo""bar -> [foo"bar] - "foo"" bar -> [foo"], [bar] - "foo"""bar" -> [foo"bar] - - -============================================================================== -3. Using the mouse *win32-mouse* - -The Win32 version of Vim supports using the mouse. If you have a two-button -mouse, the middle button can be emulated by pressing both left and right -buttons simultaneously - but note that in the Win32 GUI, if you have the right -mouse button pop-up menu enabled (see 'mouse'), you should err on the side of -pressing the left button first. |mouse-using| - -When the mouse doesn't work, try disabling the "Quick Edit Mode" feature of -the console. - -============================================================================== -4. Win32 mini FAQ *win32-faq* - -Q. How do I change the font? -A. In the GUI version, you can use the 'guifont' option. Example: > - :set guifont=Lucida_Console:h15:cDEFAULT -< In the console version, you need to set the font of the console itself. - You cannot do this from within Vim. - -Q. I'm using Vim to edit a symbolically linked file on a Unix NFS file server. - When I write the file, Vim does not "write through" the symlink. Instead, - it deletes the symbolic link and creates a new file in its place. Why? -A. On Unix, Vim is prepared for links (symbolic or hard). A backup copy of - the original file is made and then the original file is overwritten. This - assures that all properties of the file remain the same. On non-Unix - systems, the original file is renamed and a new file is written. Only the - protection bits are set like the original file. However, this doesn't work - properly when working on an NFS-mounted file system where links and other - things exist. The only way to fix this in the current version is not - making a backup file, by ":set nobackup nowritebackup" |'writebackup'| - -Q. I'm using Vim to edit a file on a Unix file server through Samba. When I - write the file, the owner of the file is changed. Why? -A. When writing a file Vim renames the original file, this is a backup (in - case writing the file fails halfway). Then the file is written as a new - file. Samba then gives it the default owner for the file system, which may - differ from the original owner. - To avoid this set the 'backupcopy' option to "yes". Vim will then make a - copy of the file for the backup, and overwrite the original file. The - owner isn't changed then. - -Q. How do I get to see the output of ":make" while it's running? -A. Basically what you need is to put a tee program that will copy its input - (the output from make) to both stdout and to the errorfile. You can find a - copy of tee (and a number of other GNU tools) at - http://gnuwin32.sourceforge.net or http://unxutils.sourceforge.net - Alternatively, try the more recent Cygnus version of the GNU tools at - http://www.cygwin.com Other Unix-style tools for Win32 are listed at - http://directory.google.com/Top/Computers/Software/Operating_Systems/Unix/Win32/ - When you do get a copy of tee, you'll need to add > - :set shellpipe=\|\ tee -< to your _vimrc. - - *:!start* -Q. How can I run an external command or program asynchronously? -A. When using :! to run an external command, you can run it with "start": > - :!start winfile.exe<CR> -< Using "start" stops Vim switching to another screen, opening a new console, - or waiting for the program to complete; it indicates that you are running a - program that does not affect the files you are editing. Programs begun - with :!start do not get passed Vim's open file handles, which means they do - not have to be closed before Vim. - To avoid this special treatment, use ":! start". - There are two optional arguments (see the next Q): - /min the window will be minimized - /b no console window will be opened - You can use only one of these flags at a time. A second one will be - treated as the start of the command. - -Q. How do I avoid getting a window for programs that I run asynchronously? -A. You have two possible solutions depending on what you want: - 1) You may use the /min flag in order to run program in a minimized state - with no other changes. It will work equally for console and GUI - applications. - 2) You can use the /b flag to run console applications without creating a - console window for them (GUI applications are not affected). But you - should use this flag only if the application you run doesn't require any - input. Otherwise it will get an EOF error because its input stream - (stdin) would be redirected to \\.\NUL (stdout and stderr too). - - Example for a console application, run Exuberant ctags: > - :!start /min ctags -R . -< When it has finished you should see file named "tags" in your current - directory. You should notice the window title blinking on your taskbar. - This is more noticeable for commands that take longer. - Now delete the "tags" file and run this command: > - :!start /b ctags -R . -< You should have the same "tags" file, but this time there will be no - blinking on the taskbar. - Example for a GUI application: > - :!start /min notepad - :!start /b notepad -< The first command runs notepad minimized and the second one runs it - normally. - - *windows-icon* -Q. I don't like the Vim icon, can I change it? -A. Yes, place your favorite icon in bitmaps/vim.ico in a directory of - 'runtimepath'. For example ~/vimfiles/bitmaps/vim.ico. - - - vim:tw=78:fo=tcq2:ts=8:ft=help:norl: diff --git a/runtime/doc/pattern.txt b/runtime/doc/pattern.txt index f3f5bcbd66..f7f561dfa5 100644 --- a/runtime/doc/pattern.txt +++ b/runtime/doc/pattern.txt @@ -1,4 +1,4 @@ -*pattern.txt* For Vim version 7.4. Last change: 2016 Jun 08 +*pattern.txt* Nvim VIM REFERENCE MANUAL by Bram Moolenaar @@ -9,16 +9,7 @@ Patterns and search commands *pattern-searches* The very basics can be found in section |03.9| of the user manual. A few more explanations are in chapter 27 |usr_27.txt|. -1. Search commands |search-commands| -2. The definition of a pattern |search-pattern| -3. Magic |/magic| -4. Overview of pattern items |pattern-overview| -5. Multi items |pattern-multi-items| -6. Ordinary atoms |pattern-atoms| -7. Ignoring case in a pattern |/ignorecase| -8. Composing characters |patterns-composing| -9. Compare with Perl patterns |perl-patterns| -10. Highlighting matches |match-highlight| + Type <M-]> to see the table of contents. ============================================================================== 1. Search commands *search-commands* @@ -130,8 +121,7 @@ gD Goto global Declaration. When the cursor is on a ends before the cursor position. *CTRL-C* -CTRL-C Interrupt current (search) command. Use CTRL-Break on - Windows |dos-CTRL-Break|. +CTRL-C Interrupt current (search) command. In Normal mode, any pending command is aborted. *:noh* *:nohlsearch* @@ -354,8 +344,8 @@ For starters, read chapter 27 of the user manual |usr_27.txt|. */\%#=* *two-engines* *NFA* Vim includes two regexp engines: 1. An old, backtracking engine that supports everything. -2. A new, NFA engine that works much faster on some patterns, but does not - support everything. +2. A new, NFA engine that works much faster on some patterns, possibly slower + on some patterns. Vim will automatically select the right engine for you. However, if you run into a problem or want to specifically select one engine or the other, you can diff --git a/runtime/doc/pi_gzip.txt b/runtime/doc/pi_gzip.txt index df0ba5e52e..f024db1260 100644 --- a/runtime/doc/pi_gzip.txt +++ b/runtime/doc/pi_gzip.txt @@ -1,4 +1,4 @@ -*pi_gzip.txt* For Vim version 7.4. Last change: 2012 Jul 19 +*pi_gzip.txt* Nvim VIM REFERENCE MANUAL by Bram Moolenaar @@ -25,6 +25,8 @@ with these extensions: *.bz2 bzip2 *.lzma lzma *.xz xz + *.lz lzip + *.zst zstd That's actually the only thing you need to know. There are no options. diff --git a/runtime/doc/pi_health.txt b/runtime/doc/pi_health.txt index 69833103d1..8354c0470f 100644 --- a/runtime/doc/pi_health.txt +++ b/runtime/doc/pi_health.txt @@ -2,10 +2,7 @@ Author: TJ DeVries <devries.timothyj@gmail.com> -============================================================================== -1. Introduction |health.vim-intro| -2. Commands and functions |health.vim-manual| -3. Create a healthcheck |health.vim-dev| + Type <M-]> to see the table of contents. ============================================================================== Introduction *healthcheck* *health.vim-intro* @@ -100,15 +97,12 @@ health#{plugin}#check() function in autoload/health/{plugin}.vim. |:CheckHealth| automatically finds and invokes such functions. If your plugin is named "jslint", then its healthcheck function must be > - health#jslint#check() -< -defined in this file on 'runtimepath': > +defined in this file on 'runtimepath': > autoload/health/jslint.vim -< -Here's a sample to get started: > +Here's a sample to get started: > function! health#jslint#check() abort call health#report_start('sanity checks') " perform arbitrary checks @@ -121,7 +115,7 @@ Here's a sample to get started: > \ ['npm install --save jslint']) endif endfunction -< + ============================================================================== vim:tw=78:ts=8:ft=help:fdm=marker diff --git a/runtime/doc/pi_msgpack.txt b/runtime/doc/pi_msgpack.txt index d695ac42cb..e9f77e70b0 100644 --- a/runtime/doc/pi_msgpack.txt +++ b/runtime/doc/pi_msgpack.txt @@ -1,4 +1,4 @@ -*pi_msgpack.txt* For NeoVim version 0.1. +*pi_msgpack.txt* Nvim Author: Nikolay Pavlov <kp-pav@yandex.ru> Copyright: (c) 2015 by Nikolay Pavlov diff --git a/runtime/doc/pi_netrw.txt b/runtime/doc/pi_netrw.txt index f740143c61..3e19f0b4af 100644 --- a/runtime/doc/pi_netrw.txt +++ b/runtime/doc/pi_netrw.txt @@ -1,4 +1,4 @@ -*pi_netrw.txt* For Vim version 7.4. Last change: 2016 Apr 20 +*pi_netrw.txt* Nvim ------------------------------------------------ NETRW REFERENCE MANUAL by Charles E. Campbell @@ -530,7 +530,7 @@ variable (ex. scp uses the variable g:netrw_scp_cmd, which is defaulted to let g:netrw_sftp_cmd= '"c:\Program Files\PuTTY\psftp.exe"' < (note: it has been reported that windows 7 with putty v0.6's "-batch" option - doesn't work, so its best to leave it off for that system) + doesn't work, so it's best to leave it off for that system) See |netrw-p8| for more about putty, pscp, psftp, etc. @@ -1204,7 +1204,7 @@ The :NetrwMB command is available outside of netrw buffers (once netrw has been invoked in the session). The file ".netrwbook" holds bookmarks when netrw (and vim) is not active. By -default, its stored on the first directory on the user's |'runtimepath'|. +default, it's stored on the first directory on the user's |'runtimepath'|. Related Topics: |netrw-gb| how to return (go) to a bookmark @@ -1429,7 +1429,7 @@ be used in that count. *.netrwhist* See |g:netrw_dirhistmax| for how to control the quantity of history stack slots. The file ".netrwhist" holds history when netrw (and vim) is not -active. By default, its stored on the first directory on the user's +active. By default, it's stored on the first directory on the user's |'runtimepath'|. Related Topics: @@ -3269,7 +3269,7 @@ The user function is passed one argument; it resembles > fun! ExampleUserMapFunc(islocal) < -where a:islocal is 1 if its a local-directory system call or 0 when +where a:islocal is 1 if it's a local-directory system call or 0 when remote-directory system call. Use netrw#Expose("varname") to access netrw-internal (script-local) @@ -3593,7 +3593,7 @@ Example: Clear netrw's marked file list via a mapping on gu > *netrw-p16* P16. When editing remote files (ex. :e ftp://hostname/path/file), - under Windows I get an |E303| message complaining that its unable + under Windows I get an |E303| message complaining that it's unable to open a swap file. (romainl) It looks like you are starting Vim from a protected @@ -3647,7 +3647,7 @@ Example: Clear netrw's marked file list via a mapping on gu > P21. I've made a directory (or file) with an accented character, but netrw isn't letting me enter that directory/read that file: - Its likely that the shell or o/s is using a different encoding + It's likely that the shell or o/s is using a different encoding than you have vim (netrw) using. A patch to vim supporting "systemencoding" may address this issue in the future; for now, just have netrw use the proper encoding. For example: > diff --git a/runtime/doc/pi_paren.txt b/runtime/doc/pi_paren.txt index 534b3add29..4b425c6cbb 100644 --- a/runtime/doc/pi_paren.txt +++ b/runtime/doc/pi_paren.txt @@ -1,4 +1,4 @@ -*pi_paren.txt* For Vim version 7.4. Last change: 2013 May 08 +*pi_paren.txt* Nvim VIM REFERENCE MANUAL by Bram Moolenaar diff --git a/runtime/doc/pi_spec.txt b/runtime/doc/pi_spec.txt index 650d1d369b..f4949db2af 100644 --- a/runtime/doc/pi_spec.txt +++ b/runtime/doc/pi_spec.txt @@ -1,4 +1,4 @@ -*pi_spec.txt* For Vim version 7.4. Last change: 2006 Apr 24 +*pi_spec.txt* Nvim by Gustavo Niemeyer ~ diff --git a/runtime/doc/pi_tar.txt b/runtime/doc/pi_tar.txt index b2fab290b3..a189d006dd 100644 --- a/runtime/doc/pi_tar.txt +++ b/runtime/doc/pi_tar.txt @@ -1,4 +1,4 @@ -*pi_tar.txt* For Vim version 7.4. Last change: 2013 Apr 17 +*pi_tar.txt* Nvim +====================+ | Tar File Interface | diff --git a/runtime/doc/pi_zip.txt b/runtime/doc/pi_zip.txt index 0a081f24d3..c20bda1fa1 100644 --- a/runtime/doc/pi_zip.txt +++ b/runtime/doc/pi_zip.txt @@ -1,4 +1,4 @@ -*pi_zip.txt* For Vim version 7.4. Last change: 2013 Apr 17 +*pi_zip.txt* Nvim +====================+ | Zip File Interface | @@ -6,7 +6,7 @@ Author: Charles E. Campbell <NdrOchip@ScampbellPfamily.AbizM> (remove NOSPAM from Campbell's email first) -Copyright: Copyright (C) 2005-2012 Charles E Campbell *zip-copyright* +Copyright: Copyright (C) 2005-2015 Charles E Campbell *zip-copyright* The VIM LICENSE (see |copyright|) applies to the files in this package, including zipPlugin.vim, zip.vim, and pi_zip.vim. except use "zip.vim" instead of "VIM". Like anything else that's free, zip.vim @@ -33,6 +33,9 @@ Copyright: Copyright (C) 2005-2012 Charles E Campbell *zip-copyright* also write to the file. Currently, one may not make a new file in zip archives via the plugin. + *zip-x* + x : may extract a listed file when the cursor is atop it + OPTIONS *g:zip_nomax* @@ -61,6 +64,11 @@ Copyright: Copyright (C) 2005-2012 Charles E Campbell *zip-copyright* file; by default: > let g:zip_zipcmd= "zip" < + *g:zip_extractcmd* + This option specifies the program (and any options needed) used to + extract a file from a zip archive. By default, > + let g:zip_extractcmd= g:zip_unzipcmd +< PREVENTING LOADING~ If for some reason you do not wish to use vim to examine zipped files, @@ -83,8 +91,26 @@ Copyright: Copyright (C) 2005-2012 Charles E Campbell *zip-copyright* One can simply extend this line to accommodate additional extensions that should be treated as zip files. + Alternatively, one may change *g:zipPlugin_ext* in one's .vimrc. + Currently (11/30/15) it holds: > + + let g:zipPlugin_ext= '*.zip,*.jar,*.xpi,*.ja,*.war,*.ear,*.celzip, + \ *.oxt,*.kmz,*.wsz,*.xap,*.docx,*.docm,*.dotx,*.dotm,*.potx,*.potm, + \ *.ppsx,*.ppsm,*.pptx,*.pptm,*.ppam,*.sldx,*.thmx,*.xlam,*.xlsx,*.xlsm, + \ *.xlsb,*.xltx,*.xltm,*.xlam,*.crtx,*.vdw,*.glox,*.gcsx,*.gqsx,*.epub' + ============================================================================== 4. History *zip-history* {{{1 + v28 Oct 08, 2014 * changed the sanity checks for executables to reflect + the command actually to be attempted in zip#Read() + and zip#Write() + * added the extraction of a file capability + Nov 30, 2015 * added *.epub to the |g:zipPlugin_ext| list + Sep 13, 2016 * added *.apk to the |g:zipPlugin_ext| list and + sorted the suffices. + v27 Jul 02, 2013 * sanity check: zipfile must have "PK" as its first + two bytes. + * modified to allow zipfile: entries in quickfix lists v26 Nov 15, 2012 * (Jason Spiro) provided a lot of new extensions that are synonyms for .zip v25 Jun 27, 2011 * using keepj with unzip -Z diff --git a/runtime/doc/print.txt b/runtime/doc/print.txt index 7565d1e976..01de3a5290 100644 --- a/runtime/doc/print.txt +++ b/runtime/doc/print.txt @@ -1,4 +1,4 @@ -*print.txt* For Vim version 7.4. Last change: 2010 Jul 20 +*print.txt* Nvim VIM REFERENCE MANUAL by Bram Moolenaar @@ -6,14 +6,7 @@ Printing *printing* -1. Introduction |print-intro| -2. Print options |print-options| -3. PostScript Printing |postscript-printing| -4. PostScript Printing Encoding |postscript-print-encoding| -5. PostScript CJK Printing |postscript-cjk-printing| -6. PostScript Printing Troubleshooting |postscript-print-trouble| -7. PostScript Utilities |postscript-print-util| -8. Formfeed Characters |printing-formfeed| + Type <M-]> to see the table of contents. ============================================================================== 1. Introduction *print-intro* diff --git a/runtime/doc/provider.txt b/runtime/doc/provider.txt index 3cd53e3e50..50307ccbf3 100644 --- a/runtime/doc/provider.txt +++ b/runtime/doc/provider.txt @@ -1,4 +1,4 @@ -*provider.txt* {Nvim} +*provider.txt* Nvim NVIM REFERENCE MANUAL by Thiago de Arruda @@ -8,6 +8,8 @@ Providers *provider* Nvim delegates some features to dynamic "providers". + Type <M-]> to see the table of contents. + ============================================================================== Python integration *provider-python* @@ -49,7 +51,8 @@ Note: The `--upgrade` flag ensures you have the latest version even if PYTHON PROVIDER CONFIGURATION ~ *g:python_host_prog* *g:python3_host_prog* -Program to use for evaluating Python code. Setting this makes startup faster. > +Program to use for evaluating Python code. Setting this makes startup faster. +Also useful for working with virtualenvs. > let g:python_host_prog = '/path/to/python' let g:python3_host_prog = '/path/to/python3' < @@ -61,6 +64,23 @@ To disable Python 2 support: > To disable Python 3 support: > let g:loaded_python3_provider = 1 +PYTHON VIRTUALENVS ~ + +If you plan to use per-project virtualenvs often, you should assign +a virtualenv for Neovim and hard-code the interpreter path via +|g:python_host_prog| (or |g:python3_host_prog|) so that the "neovim" python +package is not required for each Environment. Example using pyenv: > + pyenv install 3.4.4 + pyenv virtualenv 3.4.4 py3neovim + pyenv activate py3neovim + pip install neovim + pyenv which python # Note the path + +The last command reports the interpreter path. Add it to your init.vim: > + let g:python3_host_prog = '/full/path/to/py3neovim/bin/python' + +More information: +https://github.com/zchee/deoplete-jedi/wiki/Setting-up-Python-for-Neovim ============================================================================== Ruby integration *provider-ruby* @@ -79,34 +99,65 @@ RUBY PROVIDER CONFIGURATION ~ *g:loaded_ruby_provider* To disable Ruby support: > let g:loaded_ruby_provider = 1 +< + *g:ruby_host_prog* +Command to start the Ruby host. By default this is `neovim-ruby-host`. For users +who use per-project Ruby versions with tools like RVM or rbenv, setting this can +prevent the need to install the `neovim` gem in every project. + +To use an absolute path (e.g. to an rbenv installation): > + let g:ruby_host_prog = '~/.rbenv/versions/2.4.1/bin/neovim-ruby-host' +< +To use the RVM "system" Ruby installation: > + let g:ruby_host_prog = 'rvm system do neovim-ruby-host' +< ============================================================================== Clipboard integration *provider-clipboard* *clipboard* -Nvim has no direct connection to the system clipboard. Instead it is -accessible through a |provider| which transparently uses shell commands for -communicating with the clipboard. +Nvim has no direct connection to the system clipboard. Instead it depends on +a |provider| which transparently uses shell commands to communicate with the +system clipboard or any other clipboard "backend". -Clipboard access is implicitly enabled if any of the following clipboard tools -are found in your `$PATH`. +To ALWAYS use the clipboard for ALL operations (instead of interacting with +the '+' and/or '*' registers explicitly): > + set clipboard+=unnamedplus +< +See 'clipboard' for details and options. + + *clipboard-tool* +The presence of a working clipboard tool implicitly enables the '+' and '*' +registers. Nvim looks for these clipboard tools, in order of priority: + + - |g:clipboard| + - pbcopy/pbpaste (macOS) - xclip - xsel (newer alternative to xclip) - - pbcopy/pbpaste (Mac OS X) - lemonade (for SSH) https://github.com/pocke/lemonade - doitclient (for SSH) http://www.chiark.greenend.org.uk/~sgtatham/doit/ - -The presence of a suitable clipboard tool implicitly enables the '+' and '*' -registers. - -If you want to ALWAYS use the clipboard for ALL operations (as opposed -to interacting with the '+' and/or '*' registers explicitly), set the -following option: -> - set clipboard+=unnamedplus -< -See 'clipboard' for details and more options. + - win32yank (Windows) + - tmux (if $TMUX is set) + + *g:clipboard* +To configure a custom clipboard tool, set `g:clipboard` to a dictionary: > + let g:clipboard = { + \ 'name': 'myClipboard', + \ 'copy': { + \ '+': 'tmux load-buffer -', + \ '*': 'tmux load-buffer -', + \ }, + \ 'paste': { + \ '+': 'tmux save-buffer -', + \ '*': 'tmux save-buffer -', + \ }, + \ 'cache_enabled': 1, + \ } + +If `cache_enabled` is |TRUE| then when a selection is copied, Nvim will cache +the selection until the copy command process dies. When pasting, if the copy +process has not died, the cached selection is applied. ============================================================================== X11 selection mechanism *clipboard-x11* *x11-selection* diff --git a/runtime/doc/quickfix.txt b/runtime/doc/quickfix.txt index e94723f337..cad5bf98b5 100644 --- a/runtime/doc/quickfix.txt +++ b/runtime/doc/quickfix.txt @@ -1,4 +1,4 @@ -*quickfix.txt* For Vim version 7.4. Last change: 2016 Jul 07 +*quickfix.txt* Nvim VIM REFERENCE MANUAL by Bram Moolenaar @@ -6,15 +6,7 @@ This subject is introduced in section |30.1| of the user manual. -1. Using QuickFix commands |quickfix| -2. The error window |quickfix-window| -3. Using more than one list of errors |quickfix-error-lists| -4. Using :make |:make_makeprg| -5. Using :grep |grep| -6. Selecting a compiler |compiler-select| -7. The error format |error-file-format| -8. The directory stack |quickfix-directory-stack| -9. Specific error file formats |errorformats| + Type <M-]> to see the table of contents. ============================================================================= 1. Using QuickFix commands *quickfix* *Quickfix* *E42* @@ -30,10 +22,14 @@ positions in files. For example, |:vimgrep| finds pattern matches. You can use the positions in a script with the |getqflist()| function. Thus you can do a lot more than the edit/compile/fix cycle! -You should save your compiler's error messages to a file and start vim with -"vim -q filename". An easy way to do this is with the |:make| command (see -below). The 'errorformat' option should be set to match the error messages -from your compiler (see |errorformat| below). +If you have the error messages in a file you can start Vim with: > + vim -q filename + +From inside Vim an easy way to run a command and handle the output is with the +|:make| command (see below). + +The 'errorformat' option should be set to match the error messages from your +compiler (see |errorformat| below). *location-list* *E776* A location list is similar to a quickfix list and contains a list of positions @@ -42,8 +38,8 @@ have a separate location list. A location list can be associated with only one window. The location list is independent of the quickfix list. When a window with a location list is split, the new window gets a copy of the -location list. When there are no references to a location list, the location -list is destroyed. +location list. When there are no longer any references to a location list, +the location list is destroyed. The following quickfix commands can be used. The location list commands are similar to the quickfix commands, replacing the 'c' prefix in the quickfix @@ -521,7 +517,7 @@ lists. They set one of the existing error lists as the current one. list, an error message is given. *:lolder* *:lol* -:lol[der] [count] Same as ":colder", except use the location list for +:lol[der] [count] Same as `:colder`, except use the location list for the current window instead of the quickfix list. *:cnewer* *:cnew* *E381* @@ -530,9 +526,20 @@ lists. They set one of the existing error lists as the current one. list, an error message is given. *:lnewer* *:lnew* -:lnew[er] [count] Same as ":cnewer", except use the location list for +:lnew[er] [count] Same as `:cnewer`, except use the location list for the current window instead of the quickfix list. + *:chistory* *:chi* +:chi[story] Show the list of error lists. The current list is + marked with ">". The output looks like: + error list 1 of 3; 43 errors ~ + > error list 2 of 3; 0 errors ~ + error list 3 of 3; 15 errors ~ + + *:lhistory* *:lhi* +:lhi[story] Show the list of location lists, otherwise like + `:chistory`. + When adding a new error list, it becomes the current list. When ":colder" has been used and ":make" or ":grep" is used to add a new error @@ -857,7 +864,7 @@ need to write down a "todo" list. The Vim plugins in the "compiler" directory will set options to use the -selected compiler. For ":compiler" local options are set, for ":compiler!" +selected compiler. For `:compiler` local options are set, for `:compiler!` global options. *current_compiler* To support older Vim versions, the plugins always use "current_compiler" and diff --git a/runtime/doc/quickref.txt b/runtime/doc/quickref.txt index 2b5ed33f06..c4c3dcad88 100644 --- a/runtime/doc/quickref.txt +++ b/runtime/doc/quickref.txt @@ -1,4 +1,4 @@ -*quickref.txt* For Vim version 7.4. Last change: 2016 Aug 12 +*quickref.txt* Nvim VIM REFERENCE MANUAL by Bram Moolenaar @@ -571,8 +571,7 @@ In Insert or Command-line mode: *Q_op* Options |:set| :se[t] show all modified options -|:set| :se[t] all show all non-termcap options -|:set| :se[t] termcap show all termcap options +|:set| :se[t] all show all options |:set| :se[t] {option} set boolean option (switch it on), show string or number option |:set| :se[t] no{option} reset boolean option (switch it off) @@ -678,7 +677,6 @@ Short explanation of each option: *option-list* 'errorbells' 'eb' ring the bell for error messages 'errorfile' 'ef' name of the errorfile for the QuickFix mode 'errorformat' 'efm' description of the lines in the error file -'esckeys' 'ek' recognize function keys in Insert mode 'eventignore' 'ei' autocommand events that are ignored 'expandtab' 'et' use spaces when <Tab> is inserted 'exrc' 'ex' read .nvimrc and .exrc in the current directory @@ -716,7 +714,6 @@ Short explanation of each option: *option-list* 'guifont' 'gfn' GUI: Name(s) of font(s) to be used 'guifontset' 'gfs' GUI: Names of multi-byte fonts to be used 'guifontwide' 'gfw' list of font names for double-wide characters -'guiheadroom' 'ghr' GUI: pixels room for window decorations 'guioptions' 'go' GUI: Which components and options are used 'guitablabel' 'gtl' GUI: custom label for a tab page 'guitabtooltip' 'gtt' GUI: custom tooltip for a tab page @@ -753,7 +750,7 @@ Short explanation of each option: *option-list* 'keywordprg' 'kp' program to use for the "K" command 'langmap' 'lmap' alphabetic characters for other language mode 'langmenu' 'lm' language to be used for the menus -'langnoremap' 'lnr' do not apply 'langmap' to mapped characters +'langremap' 'lrm' do apply 'langmap' to mapped characters 'laststatus' 'ls' tells when last window has status lines 'lazyredraw' 'lz' don't redraw while executing macros 'linebreak' 'lbr' wrap long lines at a blank @@ -813,6 +810,7 @@ Short explanation of each option: *option-list* 'printmbcharset' 'pmbcs' CJK character set to be used for :hardcopy 'printmbfont' 'pmbfn' font names to be used for CJK output of :hardcopy 'printoptions' 'popt' controls the format of :hardcopy output +'prompt' 'prompt' enable prompt in Ex mode 'pumheight' 'ph' maximum height of the popup menu 'pythondll' name of the Python 2 dynamic library 'pythonthreedll' name of the Python 3 dynamic library @@ -989,7 +987,6 @@ Short explanation of each option: *option-list* |g_CTRL-G| g CTRL-G show cursor column, line, and character position |CTRL-C| CTRL-C during searches: Interrupt the search -|dos-CTRL-Break| CTRL-Break Windows: during searches: Interrupt the search |<Del>| <Del> while entering a count: delete last character |:version| :ve[rsion] show version information |:normal| :norm[al][!] {commands} @@ -1028,6 +1025,8 @@ Short explanation of each option: *option-list* |c_<Up>| <Up>/<Down> recall older/newer command-line that starts with current command |c_<S-Up>| <S-Up>/<S-Down> recall older/newer command-line from history +|c_CTRL-G| CTRL-G next match when 'incsearch' is active +|c_CTRL-T| CTRL-T previous match when 'incsearch' is active |:history| :his[tory] show older command-lines Context-sensitive completion on the command-line: diff --git a/runtime/doc/recover.txt b/runtime/doc/recover.txt index e09138b2f5..2b49af1c96 100644 --- a/runtime/doc/recover.txt +++ b/runtime/doc/recover.txt @@ -1,4 +1,4 @@ -*recover.txt* For Vim version 7.4. Last change: 2014 Mar 27 +*recover.txt* Nvim VIM REFERENCE MANUAL by Bram Moolenaar @@ -15,8 +15,7 @@ You can recover most of your changes from the files that Vim uses to store the contents of the file. Mostly you can recover your work with one command: vim -r filename -1. The swap file |swap-file| -2. Recovery |recovery| + Type <M-]> to see the table of contents. ============================================================================== 1. The swap file *swap-file* diff --git a/runtime/doc/remote.txt b/runtime/doc/remote.txt index 933ab3a444..bdc763b85f 100644 --- a/runtime/doc/remote.txt +++ b/runtime/doc/remote.txt @@ -1,4 +1,4 @@ -*remote.txt* For Vim version 7.4. Last change: 2015 Mar 01 +*remote.txt* Nvim VIM REFERENCE MANUAL by Bram Moolenaar @@ -6,9 +6,7 @@ Vim client-server communication *client-server* -1. Common functionality |clientserver| -2. X11 specific items |x11-clientserver| -3. MS-Windows specific items |w32-clientserver| + Type <M-]> to see the table of contents. ============================================================================== 1. Common functionality *clientserver* diff --git a/runtime/doc/remote_plugin.txt b/runtime/doc/remote_plugin.txt index dddc021d68..cc2efd3d1f 100644 --- a/runtime/doc/remote_plugin.txt +++ b/runtime/doc/remote_plugin.txt @@ -1,4 +1,4 @@ -*remote_plugin.txt* For Nvim. {Nvim} +*remote_plugin.txt* Nvim NVIM REFERENCE MANUAL by Thiago de Arruda @@ -6,10 +6,7 @@ Nvim support for remote plugins *remote-plugin* -1. Introduction |remote-plugin-intro| -2. Plugin hosts |remote-plugin-hosts| -3. Example |remote-plugin-example| -4. Plugin manifest |remote-plugin-manifest| + Type <M-]> to see the table of contents. ============================================================================== 1. Introduction *remote-plugin-intro* diff --git a/runtime/doc/repeat.txt b/runtime/doc/repeat.txt index ef98556260..0b3edc9bba 100644 --- a/runtime/doc/repeat.txt +++ b/runtime/doc/repeat.txt @@ -1,4 +1,4 @@ -*repeat.txt* For Vim version 7.4. Last change: 2016 Jul 21 +*repeat.txt* Nvim VIM REFERENCE MANUAL by Bram Moolenaar @@ -8,14 +8,7 @@ Repeating commands, Vim scripts and debugging *repeating* Chapter 26 of the user manual introduces repeating |usr_26.txt|. -1. Single repeats |single-repeat| -2. Multiple repeats |multi-repeat| -3. Complex repeats |complex-repeat| -4. Using Vim scripts |using-scripts| -5. Using Vim packages |packages| -6. Creating Vim packages |package-create| -7. Debugging scripts |debug-scripts| -8. Profiling |profiling| + Type <M-]> to see the table of contents. ============================================================================== 1. Single repeats *single-repeat* @@ -152,7 +145,7 @@ q Stops recording. :[addr]@: Repeat last command-line. First set cursor at line [addr] (default is current line). - *:@@* +:[addr]@ *:@@* :[addr]@@ Repeat the previous :@{0-9a-z"}. First set cursor at line [addr] (default is current line). @@ -357,8 +350,7 @@ terminal-independent two character codes. This means that they can be used in the same way on different kinds of terminals. The first character of a key code is 0x80 or 128, shown on the screen as "~@". The second one can be found in the list |key-notation|. Any of these codes can also be entered -with CTRL-V followed by the three digit decimal code. This does NOT work for -the <t_xx> termcap codes, these can only be used in mappings. +with CTRL-V followed by the three digit decimal code. *:source_crnl* *W15* Windows: Files that are read with ":source" normally have <CR><NL> <EOL>s. @@ -369,12 +361,6 @@ something like ":map <F1> :help^M", where "^M" is a <CR>. If the first line ends in a <CR>, but following ones don't, you will get an error message, because the <CR> from the first lines will be lost. -Mac Classic: Files that are read with ":source" normally have <CR> <EOL>s. -These always work. If you are using a file with <NL> <EOL>s (for example, a -file made on Unix), this will be recognized if 'fileformats' is not empty and -the first line does not end in a <CR>. Be careful not to use a file with <NL> -linebreaks which has a <CR> in first line. - On other systems, Vim expects ":source"ed files to end in a <NL>. These always work. If you are using a file with <CR><NL> <EOL>s (for example, a file made on Windows), all lines will have a trailing <CR>. This may cause diff --git a/runtime/doc/rileft.txt b/runtime/doc/rileft.txt index e4e495bb18..ba9bb1eba7 100644 --- a/runtime/doc/rileft.txt +++ b/runtime/doc/rileft.txt @@ -1,4 +1,4 @@ -*rileft.txt* For Vim version 7.4. Last change: 2006 Apr 24 +*rileft.txt* Nvim VIM REFERENCE MANUAL by Avner Lottem diff --git a/runtime/doc/russian.txt b/runtime/doc/russian.txt index 36f3d0b715..e2c44ce54f 100644 --- a/runtime/doc/russian.txt +++ b/runtime/doc/russian.txt @@ -1,4 +1,4 @@ -*russian.txt* For Vim version 7.4. Last change: 2006 Apr 24 +*russian.txt* Nvim VIM REFERENCE MANUAL by Vassily Ragosin @@ -6,10 +6,7 @@ Russian language localization and support in Vim *russian* *Russian* -1. Introduction |russian-intro| -2. Russian keymaps |russian-keymap| -3. Localization |russian-l18n| -4. Known issues |russian-issues| + Type <M-]> to see the table of contents. =============================================================================== 1. Introduction *russian-intro* diff --git a/runtime/doc/scroll.txt b/runtime/doc/scroll.txt index f2a6f713e6..52e5cc9f0c 100644 --- a/runtime/doc/scroll.txt +++ b/runtime/doc/scroll.txt @@ -1,4 +1,4 @@ -*scroll.txt* For Vim version 7.4. Last change: 2006 Aug 27 +*scroll.txt* Nvim VIM REFERENCE MANUAL by Bram Moolenaar @@ -16,12 +16,7 @@ upwards in the buffer, the text in the window moves downwards on your screen. See section |03.7| of the user manual for an introduction. -1. Scrolling downwards |scroll-down| -2. Scrolling upwards |scroll-up| -3. Scrolling relative to cursor |scroll-cursor| -4. Scrolling horizontally |scroll-horizontal| -5. Scrolling synchronously |scroll-binding| -6. Scrolling with a mouse wheel |scroll-mouse-wheel| + Type <M-]> to see the table of contents. ============================================================================== 1. Scrolling downwards *scroll-down* @@ -108,7 +103,8 @@ z^ Without [count]: Redraw with the line just above the 3. Scrolling relative to cursor *scroll-cursor* The following commands reposition the edit window (the part of the buffer that -you see) while keeping the cursor on the same line: +you see) while keeping the cursor on the same line. Note that the 'scrolloff' +option may cause context lines to show above and below the cursor. *z<CR>* z<CR> Redraw, line [count] at top of window (default @@ -235,15 +231,9 @@ This allows quick adjustment of the relative offset of 'scrollbind' windows. ============================================================================== 6. Scrolling with a mouse wheel *scroll-mouse-wheel* -When your mouse has a scroll wheel, it should work with Vim in the GUI. How -it works depends on your system. It might also work in an xterm -|xterm-mouse-wheel|. By default only vertical scroll wheels are supported, -but some GUIs also support horizontal scroll wheels. - -For the Win32 GUI the scroll action is hard coded. It works just like -dragging the scrollbar of the current window. How many lines are scrolled -depends on your mouse driver. If the scroll action causes input focus -problems, see |intellimouse-wheel-problems|. +When your mouse has a scroll wheel, it should work with Nvim in the GUI and +any terminal that has mouse support. By default only vertical scroll wheels +are supported, but some GUIs also support horizontal scroll wheels. Note that horizontal scrolling only works if 'nowrap' is set. Also, unless the "h" flag in 'guioptions' is set, the cursor moves to the longest visible @@ -258,43 +248,4 @@ the scroll wheel move one line or half a page in Normal mode: > :map <S-ScrollWheelDown> <C-D> You can also use Alt and Ctrl modifiers. -This only works when Vim gets the scroll wheel events, of course. You can -check if this works with the "xev" program. - - *<MouseDown>* *<MouseUp>* -The keys <MouseDown> and <MouseUp> have been deprecated. Use <ScrollWheelUp> -instead of <MouseDown> and use <ScrollWheelDown> instead of <MouseUp>. - - *xterm-mouse-wheel* -To use the mouse wheel in a new xterm you only have to make the scroll wheel -work in your Xserver, as mentioned above. - -To use the mouse wheel in an older xterm you must do this: -1. Make it work in your Xserver, as mentioned above. -2. Add translations for the xterm, so that the xterm will pass a scroll event - to Vim as an escape sequence. -3. Add mappings in Vim, to interpret the escape sequences as <ScrollWheelDown> - or <ScrollWheelUp> keys. - -You can do the translations by adding this to your ~.Xdefaults file (or other -file where your X resources are kept): > - - XTerm*VT100.Translations: #override \n\ - s<Btn4Down>: string("0x9b") string("[64~") \n\ - s<Btn5Down>: string("0x9b") string("[65~") \n\ - <Btn4Down>: string("0x9b") string("[62~") \n\ - <Btn5Down>: string("0x9b") string("[63~") \n\ - <Btn4Up>: \n\ - <Btn5Up>: - -Add these mappings to your vimrc file: > - :map <M-Esc>[62~ <ScrollWheelUp> - :map! <M-Esc>[62~ <ScrollWheelUp> - :map <M-Esc>[63~ <ScrollWheelDown> - :map! <M-Esc>[63~ <ScrollWheelDown> - :map <M-Esc>[64~ <S-ScrollWheelUp> - :map! <M-Esc>[64~ <S-ScrollWheelUp> - :map <M-Esc>[65~ <S-ScrollWheelDown> - :map! <M-Esc>[65~ <S-ScrollWheelDown> -< vim:tw=78:ts=8:ft=help:norl: diff --git a/runtime/doc/sign.txt b/runtime/doc/sign.txt index fd1fe8dce3..ced0608e8a 100644 --- a/runtime/doc/sign.txt +++ b/runtime/doc/sign.txt @@ -1,4 +1,4 @@ -*sign.txt* For Vim version 7.4. Last change: 2016 Aug 12 +*sign.txt* Nvim VIM REFERENCE MANUAL by Gordon Prieur @@ -7,8 +7,7 @@ Sign Support Features *sign-support* -1. Introduction |sign-intro| -2. Commands |sign-commands| + Type <M-]> to see the table of contents. ============================================================================== 1. Introduction *sign-intro* *signs* @@ -188,7 +187,9 @@ JUMPING TO A SIGN *:sign-jump* *E157* If the file isn't displayed in window and the current file can not be |abandon|ed this fails. -:sign jump {id} buffer={nr} - Same, but use buffer {nr}. +:sign jump {id} buffer={nr} *E934* + Same, but use buffer {nr}. This fails if buffer {nr} does not + have a name. + vim:tw=78:ts=8:ft=help:norl: diff --git a/runtime/doc/spell.txt b/runtime/doc/spell.txt index 0902d5d10f..5c99db42ba 100644 --- a/runtime/doc/spell.txt +++ b/runtime/doc/spell.txt @@ -1,4 +1,4 @@ -*spell.txt* +*spell.txt* Nvim VIM REFERENCE MANUAL by Bram Moolenaar @@ -6,10 +6,7 @@ Spell checking *spell* -1. Quick start |spell-quickstart| -2. Remarks on spell checking |spell-remarks| -3. Generating a spell file |spell-mkspell| -4. Spell file format |spell-file-format| + Type <M-]> to see the table of contents. ============================================================================== 1. Quick start *spell-quickstart* *E756* diff --git a/runtime/doc/sponsor.txt b/runtime/doc/sponsor.txt index a99d66d843..cfdf21abea 100644 --- a/runtime/doc/sponsor.txt +++ b/runtime/doc/sponsor.txt @@ -1,4 +1,4 @@ -*sponsor.txt* For Vim version 7.4. Last change: 2008 Jun 21 +*sponsor.txt* Nvim VIM REFERENCE MANUAL by Bram Moolenaar diff --git a/runtime/doc/starting.txt b/runtime/doc/starting.txt index b58b3c7853..4cfc98d5b6 100644 --- a/runtime/doc/starting.txt +++ b/runtime/doc/starting.txt @@ -1,4 +1,4 @@ -*starting.txt* For Vim version 7.4. Last change: 2016 Jun 12 +*starting.txt* Nvim VIM REFERENCE MANUAL by Bram Moolenaar @@ -6,15 +6,7 @@ Starting Vim *starting* -1. Vim arguments |vim-arguments| -2. Initialization |initialization| -3. $VIM and $VIMRUNTIME |$VIM| -4. Suspending |suspend| -5. Exiting |exiting| -6. Saving settings |save-settings| -7. Views and Sessions |views-sessions| -8. The ShaDa file |shada-file| -9. Base Directories |base-directories| + Type <M-]> to see the table of contents. ============================================================================== 1. Vim arguments *vim-arguments* @@ -61,7 +53,7 @@ filename One or more file names. The first one will be the current < Starting in Ex mode: > nvim -e - nvim -E -< Start editing in silent mode. See |-s-ex|. +< Start editing in |silent-mode|. *-t* *-tag* -t {tag} A tag. "tag" is looked up in the tags file, the associated @@ -181,6 +173,7 @@ argument. the executable "view" has the same effect as the -R argument. The 'updatecount' option will be set to 10000, meaning that the swap file will not be updated automatically very often. + See |-M| for disallowing modifications. *-m* -m Modifications not allowed to be written. The 'write' option @@ -207,7 +200,7 @@ argument. *-E* -E Start Vim in improved Ex mode |gQ|. - *-s-ex* + *-s-ex* *silent-mode* -s Silent or batch mode. Only when "-s" is preceded by the "-e" argument. Otherwise see |-s|, which does take an argument while this use of "-s" doesn't. To be used when Vim is used @@ -221,14 +214,14 @@ argument. :set to display option values. When 'verbose' is non-zero messages are printed (for debugging, to stderr). - $TERM is not used. + |$TERM| is not used. If Vim appears to be stuck try typing "qa!<Enter>". You don't get a prompt thus you can't see Vim is waiting for you to type something. Initializations are skipped (except the ones given with the "-u" argument). Example: > - vim -e -s < thefilter thefile + vim -es < thefilter thefile < *-b* -b Binary mode. File I/O will only recognize <NL> to separate @@ -356,13 +349,17 @@ argument. *--api-info* --api-info Print msgpack-encoded |api-metadata| and exit. + *--headless* +--headless Do not start the built-in UI. + See also |silent-mode|, which does start a (limited) UI. + ============================================================================== 2. Initialization *initialization* *startup* At startup, Vim checks environment variables and files and sets values accordingly. Vim proceeds in this order: -1. Set the 'shell' option *SHELL* *COMSPEC* *TERM* +1. Set the 'shell' option *SHELL* *COMSPEC* The environment variable SHELL, if it exists, is used to set the 'shell' option. On Windows, the COMSPEC variable is used if SHELL is not set. @@ -425,7 +422,7 @@ accordingly. Vim proceeds in this order: - The environment variable EXINIT. The value of $EXINIT is used as an Ex command line. - c. If the 'exrc' option is on (which is not the default), the current + c. If the 'exrc' option is on (which is NOT the default), the current directory is searched for three files. The first that exists is used, the others are ignored. - The file ".nvimrc" (for Unix) @@ -457,6 +454,8 @@ accordingly. Vim proceeds in this order: searched for the "plugin" sub-directory and all files ending in ".vim" will be sourced (in alphabetical order per directory), also in subdirectories. + However, directories in 'runtimepath' ending in "after" are skipped + here and only loaded after packages, see below. Loading plugins won't be done when: - The 'loadplugins' option was reset in a vimrc file. - The |--noplugin| command line argument is used. @@ -464,13 +463,18 @@ accordingly. Vim proceeds in this order: - When Vim was compiled without the |+eval| feature. Note that using "-c 'set noloadplugins'" doesn't work, because the commands from the command line have not been executed yet. You can - use "--cmd 'set noloadplugins'" |--cmd|. + use "--cmd 'set noloadplugins'" or "--cmd 'set loadplugins'" |--cmd|. Packages are loaded. These are plugins, as above, but found in the "start" directory of each entry in 'packpath'. Every plugin directory found is added in 'runtimepath' and then the plugins are sourced. See |packages|. + The plugins scripts are loaded, as above, but now only the directories + ending in "after" are used. Note that 'runtimepath' will have changed + if packages have been found, but that should not add a directory + ending in "after". + 7. Set 'shellpipe' and 'shellredir' The 'shellpipe' and 'shellredir' options are set according to the value of the 'shell' option, unless they have been set before. @@ -511,7 +515,8 @@ accordingly. Vim proceeds in this order: The |v:vim_did_enter| variable is set to 1. The |VimEnter| autocommands are executed. -Some hints on using initializations: + +Some hints on using initializations ~ Standard setup: Create a vimrc file to set the default settings and mappings for all your edit @@ -533,17 +538,23 @@ the ":version" command. NOTE: System vimrc file needs specific compilation options (one needs to define SYS_VIMRC_FILE macros). If :version command does not show anything like this, consider contacting the nvim package maintainer. -Saving the current state of Vim to a file: + +Saving the current state of Vim to a file ~ + Whenever you have changed values of options or when you have created a mapping, then you may want to save them in a vimrc file for later use. See |save-settings| about saving the current state of settings to a file. -Avoiding setup problems for Vi users: + +Avoiding setup problems for Vi users ~ + Vi uses the variable EXINIT and the file "~/.exrc". So if you do not want to interfere with Vi, then use the variable VIMINIT and the file init.vim instead. -MS-DOS line separators: + +MS-DOS line separators: ~ + On Windows systems Vim assumes that all the vimrc files have <CR> <NL> pairs as line separators. This will give problems if you have a file with only <NL>s and have a line like ":map xx yy^M". The trailing ^M will be ignored. @@ -551,8 +562,10 @@ as line separators. This will give problems if you have a file with only The $MYVIMRC or $MYGVIMRC file will be set to the first found vimrc and/or gvimrc file. -Avoiding trojan horses: *trojan-horse* -While reading the vimrc or the exrc file in the current directory, some + +Avoiding trojan horses ~ + *trojan-horse* +While reading the "vimrc" or the "exrc" file in the current directory, some commands can be disabled for security reasons by setting the 'secure' option. This is always done when executing the command from a tags file. Otherwise it would be possible that you accidentally use a vimrc or tags file that somebody @@ -574,6 +587,8 @@ Be careful! part of the line in the tags file) is always done in secure mode. This works just like executing a command from a vimrc/exrc in the current directory. + +If Vim startup is slow ~ *slow-start* If Vim takes a long time to start up, use the |--startuptime| argument to find out what happens. @@ -583,6 +598,8 @@ while. You can find out if this is the problem by disabling ShaDa for a moment (use the Vim argument "-i NONE", |-i|). Try reducing the number of lines stored in a register with ":set shada='20,<50,s10". |shada-file|. + +Intro message ~ *:intro* When Vim starts without a file name, an introductory message is displayed (for those who don't know what Vim is). It is removed as soon as the display is @@ -657,15 +674,10 @@ is the order used to find the value of $VIMRUNTIME: 3. If "$VIM/runtime" exists, it is used. 4. The value of $VIM is used. This is for backwards compatibility with older versions. -5. When the 'helpfile' option is set and doesn't contain a '$', its value is +5. If "../share/nvim/runtime" exists relative to |v:progpath|, it is used. +6. When the 'helpfile' option is set and doesn't contain a '$', its value is used, with "doc/help.txt" removed from the end. -For Unix, when there is a compiled-in default for $VIMRUNTIME (check the -output of ":version"), steps 2, 3 and 4 are skipped, and the compiled-in -default is used after step 5. This means that the compiled-in default -overrules the value of $VIM. This is useful if $VIM is "/etc" and the runtime -files are in "/usr/share/vim/vim54". - Once Vim has done this once, it will set the $VIMRUNTIME environment variable. To change it later, use a ":let" command like this: > :let $VIMRUNTIME = "/home/piet/vim/vim54" @@ -719,7 +731,7 @@ There are several ways to exit Vim: - Use `:cquit`. Also when there are changes. When using `:cquit` or when there was an error message Vim exits with exit -code 1. Errors can be avoided by using `:silent!`. +code 1. Errors can be avoided by using `:silent!` or with `:catch`. ============================================================================== 6. Saving settings *save-settings* @@ -920,7 +932,7 @@ You might want to clean up your 'viewdir' directory now and then. To automatically save and restore views for *.c files: > au BufWinLeave *.c mkview - au BufWinEnter *.c silent loadview + au BufWinEnter *.c silent! loadview ============================================================================== 8. The ShaDa file *shada* *shada-file* @@ -1095,23 +1107,6 @@ SHADA FILE NAME *shada-file-name* default and the name given with 'shada' or "-i" (unless it's NONE). -CHARACTER ENCODING *shada-encoding* - -The text in the ShaDa file is UTF-8-encoded. Normally you will always work -with the same 'encoding' value, and this works just fine. However, if you -read the ShaDa file with value for 'encoding' different from utf-8 and -'encoding' used when writing ShaDa file, some of the text (non-ASCII -characters) may be invalid as Neovim always attempts to convert the text in -the ShaDa file from the UTF-8 to the current 'encoding' value. Filenames are -never converted, affected elements are: - -- history strings; -- variable values; -- register values; -- last used search and substitute patterns; -- last used substitute replacement string. - - MANUALLY READING AND WRITING *shada-read-write* Two commands can be used to read and write the ShaDa file manually. This @@ -1197,8 +1192,11 @@ running) you have additional options: *: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|. + afterwards with `:rshada!`. Also see |v:oldfiles|. The number can be used with |c_#<|. + The output can be filtered with |:filter|, e.g.: > + filter /\.vim/ oldfiles +< The filtering happens on the file name. :bro[wse] o[ldfiles][!] List file names as with |:oldfiles|, and then prompt @@ -1219,8 +1217,11 @@ exactly four MessagePack objects: 3. Third goes the length of the fourth entry. Unsigned integer as well, used for fast skipping without parsing. 4. Fourth is actual entry data. All currently used ShaDa entries use - containers to hold data: either map or array. Exact format depends on the - entry type: + containers to hold data: either map or array. All string values in those + containers are either binary (applies to filenames) or UTF-8, yet parser + needs to expect that invalid bytes may be present in a UTF-8 string. + + Exact format depends on the entry type: Entry type (name) Entry data ~ 1 (Header) Map containing data that describes the generator @@ -1284,29 +1285,32 @@ exactly four MessagePack objects: 5 (Register) Map describing one register (|registers|). If key value is equal to default then it is normally not present. Keys: - Key Type Def Description ~ - rt UInteger 0 Register type: - No Description ~ - 0 |characterwise-register| - 1 |linewise-register| - 2 |blockwise-register| - rw UInteger 0 Register width. Only valid - for |blockwise-register|s. - rc Array of binary N/A Register contents. Each - entry in the array - represents its own line. - NUL characters inside the - line should be represented - as NL according to - |NL-used-for-Nul|. - n UInteger N/A Register name: character - code in range [1, 255]. - Example: |quote0| register - has name 48 (ASCII code for - zero character). - * any none Other keys are allowed - for compatibility reasons, - see |shada-compatibility|. + Key Type Def Description ~ + rt UInteger 0 Register type: + No Description ~ + 0 |characterwise-register| + 1 |linewise-register| + 2 |blockwise-register| + rw UInteger 0 Register width. Only valid + for |blockwise-register|s. + rc Array of binary N/A Register contents. Each + entry in the array + represents its own line. + NUL characters inside the + line should be represented + as NL according to + |NL-used-for-Nul|. + ru Boolean false Unnamed register. Whether + the unnamed register had + pointed to this register. + n UInteger N/A Register name: character + code in range [1, 255]. + Example: |quote0| register + has name 48 (ASCII code for + zero character). + * any none Other keys are allowed + for compatibility reasons, + see |shada-compatibility|. 6 (Variable) Array containing two items: variable name (binary) and variable value (any object). Values are converted using the same code |msgpackparse()| uses when reading, @@ -1366,39 +1370,38 @@ file when reading and include: complete MessagePack object. ============================================================================== -9. Base Directories *base-directories* *xdg* - -Nvim conforms to the XDG Base Directory Specification for application -configuration and data file locations. This just means Nvim looks for some -optional settings and uses them if they exist, otherwise defaults are chosen. -https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html - -CONFIGURATION DIRECTORY *$XDG_CONFIG_HOME* +9. Standard Paths - Base directory default: - Unix: ~/.config - Windows: ~/AppData/Local +Nvim stores configuration and data in standard locations. Plugins are strongly +encouraged to follow this pattern also. - Nvim directory: - Unix: ~/.config/nvim/ - Windows: ~/AppData/Local/nvim/ - -DATA DIRECTORY *$XDG_DATA_HOME* - - Base directory default: - Unix: ~/.local/share - Windows: ~/AppData/Local - - Nvim directory: - Unix: ~/.local/share/nvim/ - Windows: ~/AppData/Local/nvim-data/ - -Note on Windows the configuration and data directory defaults are the same -(for lack of an alternative), but the sub-directory for data is named -"nvim-data" to separate it from the configuration sub-directory "nvim". - -Throughout other sections of the user manual, the defaults are used as generic -placeholders, e.g. where "~/.config" is mentioned it should be understood to -mean "$XDG_CONFIG_HOME or ~/.config". + *base-directories* *xdg* +The "base" (root) directories conform to the XDG Base Directory Specification. +https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html +The $XDG_CONFIG_HOME and $XDG_DATA_HOME environment variables are used if they +exist, otherwise default values (listed below) are used. + +Note: Throughout the user manual these defaults are used as placeholders, e.g. +"~/.config" is understood to mean "$XDG_CONFIG_HOME or ~/.config". + +CONFIG DIRECTORY *$XDG_CONFIG_HOME* + Base Nvim ~ +Unix: ~/.config ~/.config/nvim +Windows: ~/AppData/Local ~/AppData/Local/nvim + +DATA DIRECTORY *$XDG_DATA_HOME* + Base Nvim ~ +Unix: ~/.local/share ~/.local/share/nvim +Windows: ~/AppData/Local ~/AppData/Local/nvim-data + +STANDARD PATHS *standard-path* + + *$NVIM_LOG_FILE* +Besides 'debug' and 'verbose', Nvim has a low-level "log of last resort" that +is written directly to the filesystem. This log may also be used by plugins or +RPC clients for debugging. $NVIM_LOG_FILE contains the log file path: > + :echo $NVIM_LOG_FILE +Usually the file is ~/.local/share/nvim/log unless that path is inaccessible +or if $NVIM_LOG_FILE was set before |startup|. vim:tw=78:ts=8:ft=help:norl: diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt index e59f567826..fd17e3b381 100644 --- a/runtime/doc/syntax.txt +++ b/runtime/doc/syntax.txt @@ -1,4 +1,4 @@ -*syntax.txt* For Vim version 7.4. Last change: 2016 Aug 10 +*syntax.txt* Nvim VIM REFERENCE MANUAL by Bram Moolenaar @@ -20,24 +20,7 @@ In the User Manual: |usr_06.txt| introduces syntax highlighting. |usr_44.txt| introduces writing a syntax file. -1. Quick start |:syn-qstart| -2. Syntax files |:syn-files| -3. Syntax loading procedure |syntax-loading| -4. Syntax file remarks |:syn-file-remarks| -5. Defining a syntax |:syn-define| -6. :syntax arguments |:syn-arguments| -7. Syntax patterns |:syn-pattern| -8. Syntax clusters |:syn-cluster| -9. Including syntax files |:syn-include| -10. Synchronizing |:syn-sync| -11. Listing syntax items |:syntax| -12. Highlight command |:highlight| -13. Linking groups |:highlight-link| -14. Cleaning up |:syn-clear| -15. Highlighting tags |tag-highlight| -16. Window-local syntax |:ownsyntax| -17. Color xterms |xterm-color| -18. When syntax is slow |:syntime| + Type <M-]> to see the table of contents. ============================================================================== 1. Quick start *:syn-qstart* @@ -1472,7 +1455,7 @@ algorithm should work in the vast majority of cases. In some cases, such as a file that begins with 500 or more full-line comments, the script may incorrectly decide that the fortran code is in fixed form. If that happens, just add a non-comment statement beginning anywhere in the first five columns -of the first twenty five lines, save (:w) and then reload (:e!) the file. +of the first twenty-five lines, save (:w) and then reload (:e!) the file. Tabs in fortran files ~ Tabs are not recognized by the Fortran standards. Tabs are not a good idea in @@ -2656,68 +2639,103 @@ your vimrc: *g:filetype_r* RUBY *ruby.vim* *ft-ruby-syntax* -There are a number of options to the Ruby syntax highlighting. + Ruby: Operator highlighting |ruby_operators| + Ruby: Whitespace errors |ruby_space_errors| + Ruby: Folding |ruby_fold| |ruby_foldable_groups| + Ruby: Reducing expensive operations |ruby_no_expensive| |ruby_minlines| + Ruby: Spellchecking strings |ruby_spellcheck_strings| -By default, the "end" keyword is colorized according to the opening statement -of the block it closes. While useful, this feature can be expensive; if you -experience slow redrawing (or you are on a terminal with poor color support) -you may want to turn it off by defining the "ruby_no_expensive" variable: > + *ruby_operators* + Ruby: Operator highlighting ~ - :let ruby_no_expensive = 1 +Operators can be highlighted by defining "ruby_operators": > + + :let ruby_operators = 1 < -In this case the same color will be used for all control keywords. + *ruby_space_errors* + Ruby: Whitespace errors ~ -If you do want this feature enabled, but notice highlighting errors while -scrolling backwards, which are fixed when redrawing with CTRL-L, try setting -the "ruby_minlines" variable to a value larger than 50: > +Whitespace errors can be highlighted by defining "ruby_space_errors": > - :let ruby_minlines = 100 + :let ruby_space_errors = 1 < -Ideally, this value should be a number of lines large enough to embrace your -largest class or module. +This will highlight trailing whitespace and tabs preceded by a space character +as errors. This can be refined by defining "ruby_no_trail_space_error" and +"ruby_no_tab_space_error" which will ignore trailing whitespace and tabs after +spaces respectively. -Highlighting of special identifiers can be disabled by removing the -rubyIdentifier highlighting: > + *ruby_fold* *ruby_foldable_groups* + Ruby: Folding ~ + +Folding can be enabled by defining "ruby_fold": > - :hi link rubyIdentifier NONE + :let ruby_fold = 1 < -This will prevent highlighting of special identifiers like "ConstantName", -"$global_var", "@@class_var", "@instance_var", "| block_param |", and -":symbol". +This will set the value of 'foldmethod' to "syntax" locally to the current +buffer or window, which will enable syntax-based folding when editing Ruby +filetypes. + +Default folding is rather detailed, i.e., small syntax units like "if", "do", +"%w[]" may create corresponding fold levels. -Significant methods of Kernel, Module and Object are highlighted by default. -This can be disabled by defining "ruby_no_special_methods": > +You can set "ruby_foldable_groups" to restrict which groups are foldable: > - :let ruby_no_special_methods = 1 + :let ruby_foldable_groups = 'if case %' < -This will prevent highlighting of important methods such as "require", "attr", -"private", "raise" and "proc". +The value is a space-separated list of keywords: + + keyword meaning ~ + -------- ------------------------------------- ~ + ALL Most block syntax (default) + NONE Nothing + if "if" or "unless" block + def "def" block + class "class" block + module "module" block + do "do" block + begin "begin" block + case "case" block + for "for", "while", "until" loops + { Curly bracket block or hash literal + [ Array literal + % Literal with "%" notation, e.g.: %w(STRING), %!STRING! + / Regexp + string String and shell command output (surrounded by ', ", `) + : Symbol + # Multiline comment + << Here documents + __END__ Source code after "__END__" directive + + *ruby_no_expensive* + Ruby: Reducing expensive operations ~ -Ruby operators can be highlighted. This is enabled by defining -"ruby_operators": > +By default, the "end" keyword is colorized according to the opening statement +of the block it closes. While useful, this feature can be expensive; if you +experience slow redrawing (or you are on a terminal with poor color support) +you may want to turn it off by defining the "ruby_no_expensive" variable: > - :let ruby_operators = 1 + :let ruby_no_expensive = 1 < -Whitespace errors can be highlighted by defining "ruby_space_errors": > +In this case the same color will be used for all control keywords. - :let ruby_space_errors = 1 -< -This will highlight trailing whitespace and tabs preceded by a space character -as errors. This can be refined by defining "ruby_no_trail_space_error" and -"ruby_no_tab_space_error" which will ignore trailing whitespace and tabs after -spaces respectively. + *ruby_minlines* -Folding can be enabled by defining "ruby_fold": > +If you do want this feature enabled, but notice highlighting errors while +scrolling backwards, which are fixed when redrawing with CTRL-L, try setting +the "ruby_minlines" variable to a value larger than 50: > - :let ruby_fold = 1 + :let ruby_minlines = 100 < -This will set the 'foldmethod' option to "syntax" and allow folding of -classes, modules, methods, code blocks, heredocs and comments. +Ideally, this value should be a number of lines large enough to embrace your +largest class or module. + + *ruby_spellcheck_strings* + Ruby: Spellchecking strings ~ -Folding of multiline comments can be disabled by defining -"ruby_no_comment_fold": > +Ruby syntax will perform spellchecking of strings if you define +"ruby_spellcheck_strings": > - :let ruby_no_comment_fold = 1 + :let ruby_spellcheck_strings = 1 < SCHEME *scheme.vim* *ft-scheme-syntax* @@ -2815,9 +2833,11 @@ vimrc file: > (Adapted from the html.vim help text by Claudio Fleiner <claudio@fleiner.com>) -SH *sh.vim* *ft-sh-syntax* *ft-bash-syntax* *ft-ksh-syntax* + *ft-posix-synax* *ft-dash-syntax* +SH *sh.vim* *ft-sh-syntax* *ft-bash-syntax* *ft-ksh-syntax* -This covers the "normal" Unix (Bourne) sh, bash and the Korn shell. +This covers syntax highlighting for the older Unix (Bourne) sh, and newer +shells such as bash, dash, posix, and the Korn shells. Vim attempts to determine which shell type is in use by specifying that various filenames are of specific types: > @@ -2826,28 +2846,31 @@ various filenames are of specific types: > bash: .bashrc* bashrc bash.bashrc .bash_profile* *.bash < If none of these cases pertain, then the first line of the file is examined -(ex. /bin/sh /bin/ksh /bin/bash). If the first line specifies a shelltype, -then that shelltype is used. However some files (ex. .profile) are known to -be shell files but the type is not apparent. Furthermore, on many systems -sh is symbolically linked to "bash" (Linux, Windows+cygwin) or "ksh" (Posix). +(ex. looking for /bin/sh /bin/ksh /bin/bash). If the first line specifies a +shelltype, then that shelltype is used. However some files (ex. .profile) are +known to be shell files but the type is not apparent. Furthermore, on many +systems sh is symbolically linked to "bash" (Linux, Windows+cygwin) or "ksh" +(Posix). -One may specify a global default by instantiating one of the following three +One may specify a global default by instantiating one of the following variables in your vimrc: - ksh: > + ksh: > let g:is_kornshell = 1 -< posix: (using this is the same as setting is_kornshell to 1) > +< posix: (using this is the nearly the same as setting g:is_kornshell to 1) > let g:is_posix = 1 < bash: > let g:is_bash = 1 < sh: (default) Bourne shell > let g:is_sh = 1 +< (dash users should use posix) + If there's no "#! ..." line, and the user hasn't availed himself/herself of a default sh.vim syntax setting as just shown, then syntax/sh.vim will assume the Bourne shell syntax. No need to quote RFCs or market penetration statistics in error reports, please -- just select the default version of the -sh your system uses in your vimrc. +sh your system uses and install the associated "let..." in your <.vimrc>. The syntax/sh.vim file provides several levels of syntax-based folding: > @@ -2856,7 +2879,7 @@ The syntax/sh.vim file provides several levels of syntax-based folding: > let g:sh_fold_enabled= 2 (enable heredoc folding) let g:sh_fold_enabled= 4 (enable if/do/for folding) > -then various syntax items (HereDocuments and function bodies) become +then various syntax items (ie. HereDocuments and function bodies) become syntax-foldable (see |:syn-fold|). You also may add these together to get multiple types of folding: > @@ -2880,14 +2903,14 @@ reduce this, the "sh_maxlines" internal variable can be set. Example: > The default is to use the twice sh_minlines. Set it to a smaller number to speed up displaying. The disadvantage is that highlight errors may appear. - *g:sh_isk* *g:sh_noisk* -The shell languages appear to let "." be part of words, commands, etc; -consequently it should be in the isk for sh.vim. As of v116 of syntax/sh.vim, -syntax/sh.vim will append the "." to |'iskeyword'| by default; you may control -this behavior with: > - let g:sh_isk = '..whatever characters you want as part of iskeyword' - let g:sh_noisk= 1 " otherwise, if this exists, the isk will NOT chg +syntax/sh.vim tries to flag certain problems as errors; usually things like +extra ']'s, 'done's, 'fi's, etc. If you find the error handling problematic +for your purposes, you may suppress such error highlighting by putting +the following line in your .vimrc: > + + let g:sh_no_error= 1 < + *sh-embed* *sh-awk* Sh: EMBEDDING LANGUAGES~ @@ -3189,11 +3212,11 @@ syntax highlighting script handles this with the following logic: * If g:tex_stylish exists and is 1 then the file will be treated as a "sty" file, so the "_" will be allowed as part of keywords - (irregardless of g:tex_isk) + (regardless of g:tex_isk) * Else if the file's suffix is sty, cls, clo, dtx, or ltx, then the file will be treated as a "sty" file, so the "_" will be allowed as part of keywords - (irregardless of g:tex_isk) + (regardless of g:tex_isk) * If g:tex_isk exists, then it will be used for the local 'iskeyword' * Else the local 'iskeyword' will be set to 48-57,a-z,A-Z,192-255 @@ -3262,8 +3285,8 @@ Some folding is now supported with syntax/vim.vim: > g:vimsyn_folding =~ 'P' : fold python script < *g:vimsyn_noerror* -Not all error highlighting that syntax/vim.vim does may be correct; VimL is a -difficult language to highlight correctly. A way to suppress error +Not all error highlighting that syntax/vim.vim does may be correct; Vim script +is a difficult language to highlight correctly. A way to suppress error highlighting is to put the following line in your |vimrc|: > let g:vimsyn_noerror = 1 @@ -3421,6 +3444,8 @@ DEFINING CASE *:syn-case* *E390* "ignore". Note that any items before this are not affected, and all items until the next ":syntax case" command are affected. +:sy[ntax] case + Show either "syntax case match" or "syntax case ignore" (translated). SPELL CHECKING *:syn-spell* @@ -3438,6 +3463,11 @@ SPELL CHECKING *:syn-spell* To activate spell checking the 'spell' option must be set. +:sy[ntax] spell + Show either "syntax spell toplevel", "syntax spell notoplevel" or + "syntax spell default" (translated). + + SYNTAX ISKEYWORD SETTING *:syn-iskeyword* :sy[ntax] iskeyword [clear | {option}] @@ -3461,8 +3491,8 @@ SYNTAX ISKEYWORD SETTING *:syn-iskeyword* and also determines where |:syn-keyword| will be checked for a new match. - It is recommended when writing syntax files, to use this command - to the correct value for the specific syntax language and not change + It is recommended when writing syntax files, to use this command to + set the correct value for the specific syntax language and not change the 'iskeyword' option. DEFINING KEYWORDS *:syn-keyword* @@ -3520,7 +3550,11 @@ DEFINING KEYWORDS *:syn-keyword* DEFINING MATCHES *:syn-match* -:sy[ntax] match {group-name} [{options}] [excludenl] {pattern} [{options}] +:sy[ntax] match {group-name} [{options}] + [excludenl] + [keepend] + {pattern} + [{options}] This defines one match. @@ -3529,6 +3563,9 @@ DEFINING MATCHES *:syn-match* [excludenl] Don't make a pattern with the end-of-line "$" extend a containing match or region. Must be given before the pattern. |:syn-excludenl| + keepend Don't allow contained matches to go past a + match with the end pattern. See + |:syn-keepend|. {pattern} The search pattern that defines the match. See |:syn-pattern| below. Note that the pattern may match more than one @@ -3739,7 +3776,7 @@ Whether or not it is actually concealed depends on the value of the 'conceallevel' option. The 'concealcursor' option is used to decide whether concealable items in the current line are displayed unconcealed to be able to edit the line. -Another way to conceal text with with |matchadd()|. +Another way to conceal text is with |matchadd()|. concealends *:syn-concealends* @@ -4024,6 +4061,9 @@ IMPLICIT CONCEAL *:syn-conceal-implicit* off" returns to the normal state where the "conceal" flag must be given explicitly. +:sy[ntax] conceal + Show either "syntax conceal on" or "syntax conceal off" (translated). + ============================================================================== 7. Syntax patterns *:syn-pattern* *E401* *E402* @@ -4532,7 +4572,14 @@ in their own color. Doesn't work recursively, thus you can't use ":colorscheme" in a color scheme script. - After the color scheme has been loaded the + + To customize a colorscheme use another name, e.g. + "~/.vim/colors/mine.vim", and use `:runtime` to load + the original colorscheme: > + runtime colors/evening.vim + hi Statement ctermfg=Blue guifg=Blue + +< After the color scheme has been loaded the |ColorScheme| autocommand event is triggered. For info about writing a colorscheme file: > :edit $VIMRUNTIME/colors/README.txt @@ -4589,8 +4636,7 @@ mentioned for the default values. See |:verbose-cmd| for more information. *highlight-args* *E416* *E417* *E423* There are three types of terminals for highlighting: term a normal terminal (vt100, xterm) -cterm a color terminal (Windows console, color-xterm, these have the "Co" - termcap entry) +cterm a color terminal (Windows console, color-xterm) gui the GUI For each type the highlighting can be given. This makes it possible to use @@ -4630,21 +4676,12 @@ stop={term-list} *term-list* *highlight-stop* highlighted area. This should undo the "start" argument. Otherwise the screen will look messed up. - The {term-list} can have two forms: - - 1. A string with escape sequences. - This is any string of characters, except that it can't start with - "t_" and blanks are not allowed. The <> notation is recognized - here, so you can use things like "<Esc>" and "<Space>". Example: + {term-list} is a a string with escape sequences. This is any string of + characters, except that it can't start with "t_" and blanks are not + allowed. The <> notation is recognized here, so you can use things + like "<Esc>" and "<Space>". Example: start=<Esc>[27h;<Esc>[<Space>r; - 2. A list of terminal codes. - Each terminal code has the form "t_xx", where "xx" is the name of - the termcap entry. The codes have to be separated with commas. - White space is not allowed. Example: - start=t_C1,t_BL - The terminal codes must exist for this to work. - 2. highlight arguments for color terminals @@ -4659,7 +4696,7 @@ cterm={attr-list} *highlight-cterm* ctermfg={color-nr} *highlight-ctermfg* *E421* ctermbg={color-nr} *highlight-ctermbg* The {color-nr} argument is a color number. Its range is zero to - (not including) the number given by the termcap entry "Co". + (not including) the number of |tui-colors| available. The actual color with this number depends on the type of terminal and its settings. Sometimes the color also depends on the settings of "cterm". For example, on some systems "cterm=bold ctermfg=3" gives @@ -4669,7 +4706,7 @@ ctermbg={color-nr} *highlight-ctermbg* unpredictable. See your xterm documentation for the defaults. The colors for a color-xterm can be changed from the .Xdefaults file. Unfortunately this means that it's not possible to get the same colors - for each user. See |xterm-color| for info about color xterms. + for each user. The MSDOS standard colors are fixed (in a console window), so these have been used for the names. But the meaning of color names in X11 @@ -4731,9 +4768,8 @@ ctermbg={color-nr} *highlight-ctermbg* delete the "g:colors_name" variable when you don't want this. When you have set "ctermfg" or "ctermbg" for the Normal group, Vim - needs to reset the color when exiting. This is done with the "op" - termcap entry |t_op|. If this doesn't work correctly, try setting the - 't_op' option in your vimrc. + needs to reset the color when exiting. This is done with the + "orig_pair" |terminfo| entry. *E419* *E420* When Vim knows the normal foreground and background colors, "fg" and "bg" can be used as color names. This only works after setting the @@ -4803,10 +4839,7 @@ guisp={color-name} *highlight-guisp* Black White Orange Purple Violet - In the Win32 GUI version, additional system colors are available. See - |win32-colors|. - - You can also specify a color by its Red, Green and Blue values. + You can also specify a color by its RGB (red, green, blue) values. The format is "#rrggbb", where "rr" is the Red value "gg" is the Green value @@ -4815,10 +4848,9 @@ guisp={color-name} *highlight-guisp* :highlight Comment guifg=#11f0c3 guibg=#ff00ff < *highlight-groups* *highlight-default* -These are the default highlighting groups. These groups are used by the -'highlight' option default. Note that the highlighting depends on the value -of 'background'. You can see the current settings with the ":highlight" -command. +These are the builtin highlighting groups. Note that the highlighting depends +on the value of 'background'. You can see the current settings with the +":highlight" command. *hl-ColorColumn* ColorColumn used for the columns set with 'colorcolumn' *hl-Conceal* @@ -4888,6 +4920,8 @@ NonText '@' at the end of the window, characters from 'showbreak' fit at the end of the line). See also |hl-EndOfBuffer|. *hl-Normal* Normal normal text + *hl-NormalNC* +NormalNC normal text in non-current window *hl-Pmenu* Pmenu Popup menu: normal item. *hl-PmenuSel* @@ -4899,32 +4933,28 @@ PmenuThumb Popup menu: Thumb of the scrollbar. *hl-Question* Question |hit-enter| prompt and yes/no questions *hl-QuickFixLine* -QuickFixLine The selected |quickfix| item in the quickfix window. - |hl-CursorLine| is combined with this when the cursor is on - the currently selected quickfix item. +QuickFixLine Current |quickfix| item in the quickfix window. Combined with + |hl-CursorLine| when the cursor is there. *hl-Search* Search Last search pattern highlighting (see 'hlsearch'). - Also used for highlighting the current line in the quickfix - window and similar items that need to stand out. + Also used for similar items that need to stand out. *hl-SpecialKey* -SpecialKey Meta and special keys listed with ":map", also for text used - to show unprintable characters in the text, 'listchars'. - Generally: text that is displayed differently from what it - really is. +SpecialKey Unprintable characters: text displayed differently from what + it really is. But not 'listchars' whitespace. |hl-Whitespace| *hl-SpellBad* SpellBad Word that is not recognized by the spellchecker. |spell| - This will be combined with the highlighting used otherwise. + Combined with the highlighting used otherwise. *hl-SpellCap* SpellCap Word that should start with a capital. |spell| - This will be combined with the highlighting used otherwise. + Combined with the highlighting used otherwise. *hl-SpellLocal* SpellLocal Word that is recognized by the spellchecker as one that is used in another region. |spell| - This will be combined with the highlighting used otherwise. + Combined with the highlighting used otherwise. *hl-SpellRare* SpellRare Word that is recognized by the spellchecker as one that is hardly ever used. |spell| - This will be combined with the highlighting used otherwise. + Combined with the highlighting used otherwise. *hl-StatusLine* StatusLine status line of current window *hl-StatusLineNC* @@ -4941,8 +4971,12 @@ TabLineSel tab pages line, active tab page label Title titles for output from ":set all", ":autocmd" etc. *hl-Visual* Visual Visual mode selection + *hl-VisualNOS* +VisualNOS Visual mode selection when vim is "Not Owning the Selection". *hl-WarningMsg* WarningMsg warning messages + *hl-Whitespace* +Whitespace "nbsp", "space", "tab" and "trail" in 'listchars' *hl-WildMenu* WildMenu current match in 'wildmenu' completion @@ -5167,146 +5201,12 @@ When splitting the window, the new window will use the original syntax. ============================================================================== 17. Color xterms *xterm-color* *color-xterm* -Most color xterms have only eight colors. If you don't get colors with the -default setup, it should work with these lines in your vimrc: > - :if &term =~ "xterm" - : if has("terminfo") - : set t_Co=8 - : set t_Sf=<Esc>[3%p1%dm - : set t_Sb=<Esc>[4%p1%dm - : else - : set t_Co=8 - : set t_Sf=<Esc>[3%dm - : set t_Sb=<Esc>[4%dm - : endif - :endif -< [<Esc> is a real escape, type CTRL-V <Esc>] - -You might want to change the first "if" to match the name of your terminal, -e.g. "dtterm" instead of "xterm". - -Note: Do these settings BEFORE doing ":syntax on". Otherwise the colors may -be wrong. - *xiterm* *rxvt* -The above settings have been mentioned to work for xiterm and rxvt too. -But for using 16 colors in an rxvt these should work with terminfo: > - :set t_AB=<Esc>[%?%p1%{8}%<%t25;%p1%{40}%+%e5;%p1%{32}%+%;%dm - :set t_AF=<Esc>[%?%p1%{8}%<%t22;%p1%{30}%+%e1;%p1%{22}%+%;%dm -< *colortest.vim* To test your color setup, a file has been included in the Vim distribution. To use it, execute this command: > :runtime syntax/colortest.vim -Some versions of xterm (and other terminals, like the Linux console) can -output lighter foreground colors, even though the number of colors is defined -at 8. Therefore Vim sets the "cterm=bold" attribute for light foreground -colors, when 't_Co' is 8. - - *xfree-xterm* -To get 16 colors or more, get the newest xterm version (which should be -included with XFree86 3.3 and later). You can also find the latest version -at: > - http://invisible-island.net/xterm/xterm.html -Here is a good way to configure it. This uses 88 colors and enables the -termcap-query feature, which allows Vim to ask the xterm how many colors it -supports. > - ./configure --disable-bold-color --enable-88-color --enable-tcap-query -If you only get 8 colors, check the xterm compilation settings. -(Also see |UTF8-xterm| for using this xterm with UTF-8 character encoding). - -This xterm should work with these lines in your vimrc (for 16 colors): > - :if has("terminfo") - : set t_Co=16 - : set t_AB=<Esc>[%?%p1%{8}%<%t%p1%{40}%+%e%p1%{92}%+%;%dm - : set t_AF=<Esc>[%?%p1%{8}%<%t%p1%{30}%+%e%p1%{82}%+%;%dm - :else - : set t_Co=16 - : set t_Sf=<Esc>[3%dm - : set t_Sb=<Esc>[4%dm - :endif -< [<Esc> is a real escape, type CTRL-V <Esc>] - -Without |+terminfo|, Vim will recognize these settings, and automatically -translate cterm colors of 8 and above to "<Esc>[9%dm" and "<Esc>[10%dm". -Colors above 16 are also translated automatically. - -For 256 colors this has been reported to work: > - - :set t_AB=<Esc>[48;5;%dm - :set t_AF=<Esc>[38;5;%dm - -Or just set the TERM environment variable to "xterm-color" or "xterm-16color" -and try if that works. - -You probably want to use these X resources (in your ~/.Xdefaults file): - XTerm*color0: #000000 - XTerm*color1: #c00000 - XTerm*color2: #008000 - XTerm*color3: #808000 - XTerm*color4: #0000c0 - XTerm*color5: #c000c0 - XTerm*color6: #008080 - XTerm*color7: #c0c0c0 - XTerm*color8: #808080 - XTerm*color9: #ff6060 - XTerm*color10: #00ff00 - XTerm*color11: #ffff00 - XTerm*color12: #8080ff - XTerm*color13: #ff40ff - XTerm*color14: #00ffff - XTerm*color15: #ffffff - Xterm*cursorColor: Black - -[Note: The cursorColor is required to work around a bug, which changes the -cursor color to the color of the last drawn text. This has been fixed by a -newer version of xterm, but not everybody is using it yet.] - -To get these right away, reload the .Xdefaults file to the X Option database -Manager (you only need to do this when you just changed the .Xdefaults file): > - xrdb -merge ~/.Xdefaults -< - *xterm-blink* *xterm-blinking-cursor* -To make the cursor blink in an xterm, see tools/blink.c. Or use Thomas -Dickey's xterm above patchlevel 107 (see above for where to get it), with -these resources: - XTerm*cursorBlink: on - XTerm*cursorOnTime: 400 - XTerm*cursorOffTime: 250 - XTerm*cursorColor: White - - *hpterm-color* -These settings work (more or less) for an hpterm, which only supports 8 -foreground colors: > - :if has("terminfo") - : set t_Co=8 - : set t_Sf=<Esc>[&v%p1%dS - : set t_Sb=<Esc>[&v7S - :else - : set t_Co=8 - : set t_Sf=<Esc>[&v%dS - : set t_Sb=<Esc>[&v7S - :endif -< [<Esc> is a real escape, type CTRL-V <Esc>] - - *Eterm* *enlightened-terminal* -These settings have been reported to work for the Enlightened terminal -emulator, or Eterm. They might work for all xterm-like terminals that use the -bold attribute to get bright colors. Add an ":if" like above when needed. > - :set t_Co=16 - :set t_AF=^[[%?%p1%{8}%<%t3%p1%d%e%p1%{22}%+%d;1%;m - :set t_AB=^[[%?%p1%{8}%<%t4%p1%d%e%p1%{32}%+%d;1%;m -< - *TTpro-telnet* -These settings should work for TTpro telnet. Tera Term Pro is a freeware / -open-source program for MS-Windows. > - set t_Co=16 - set t_AB=^[[%?%p1%{8}%<%t%p1%{40}%+%e%p1%{32}%+5;%;%dm - set t_AF=^[[%?%p1%{8}%<%t%p1%{30}%+%e%p1%{22}%+1;%;%dm -Also make sure TTpro's Setup / Window / Full Color is enabled, and make sure -that Setup / Font / Enable Bold is NOT enabled. -(info provided by John Love-Jensen <eljay@Adobe.COM>) - +Nvim uses |256-color| and |true-color| terminal capabilities whereever possible. ============================================================================== 18. When syntax is slow *:syntime* diff --git a/runtime/doc/tabpage.txt b/runtime/doc/tabpage.txt index 4ab5b3c759..8f1eb9d8cd 100644 --- a/runtime/doc/tabpage.txt +++ b/runtime/doc/tabpage.txt @@ -1,4 +1,4 @@ -*tabpage.txt* For Vim version 7.4. Last change: 2015 Apr 18 +*tabpage.txt* Nvim VIM REFERENCE MANUAL by Bram Moolenaar @@ -10,11 +10,7 @@ The commands which have been added to use multiple tab pages are explained here. Additionally, there are explanations for commands that work differently when used in combination with more than one tab page. -1. Introduction |tab-page-intro| -2. Commands |tab-page-commands| -3. Other items |tab-page-other| -4. Setting 'tabline' |setting-tabline| -5. Setting 'guitablabel' |setting-guitablabel| + Type <M-]> to see the table of contents. ============================================================================== 1. Introduction *tab-page-intro* @@ -54,6 +50,8 @@ right of the labels. In the GUI tab pages line you can use the right mouse button to open menu. |tabline-menu|. +For the related autocommands see |tabnew-autocmd|. + :[count]tabe[dit] *:tabe* *:tabedit* *:tabnew* :[count]tabnew Open a new tab page with an empty window, after the current @@ -129,10 +127,14 @@ something else. :tabc[lose][!] {count} Close tab page {count}. Fails in the same way as `:tabclose` above. > - :-tabclose " close the previous tab page - :+tabclose " close the next tab page - :1tabclose " close the first tab page - :$tabclose " close the last tab page + :-tabclose " close the previous tab page + :+tabclose " close the next tab page + :1tabclose " close the first tab page + :$tabclose " close the last tab page + :tabclose -2 " close the two previous tab page + :tabclose + " close the next tab page + :tabclose 3 " close the third tab page + :tabclose $ " close the last tab page < *:tabo* *:tabonly* :tabo[nly][!] Close all other tab pages. @@ -145,13 +147,20 @@ something else. never abandoned, so changes cannot get lost. > :tabonly " close all tab pages except the current one -:{count}tabo[nly][!] - Close all tab pages except the {count}th one. > - :.tabonly " as above - :-tabonly " close all tab pages except the previous one - :+tabonly " close all tab pages except the next one - :1tabonly " close all tab pages except the first one - :$tabonly " close all tab pages except the last one. +:tabo[nly][!] {count} + Close all tab pages except {count} one. > + :.tabonly " as above + :-tabonly " close all tab pages except the previous + " one + :+tabonly " close all tab pages except the next one + :1tabonly " close all tab pages except the first one + :$tabonly " close all tab pages except the last one + :tabonly - " close all tab pages except the previous + " one + :tabonly +2 " close all tab pages except the two next + " one + :tabonly 1 " close all tab pages except the first one + :tabonly $ " close all tab pages except the last one SWITCHING TO ANOTHER TAB PAGE: @@ -166,7 +175,20 @@ gt *i_CTRL-<PageDown>* *i_<C-PageDown>* Go to the next tab page. Wraps around from the last to the first one. +:{count}tabn[ext] :tabn[ext] {count} + Go to tab page {count}. The first tab page has number one. > + :-tabnext " go to the previous tab page + :+tabnext " go to the next tab page + :+2tabnext " go to the two next tab page + :1tabnext " go to the first tab page + :$tabnext " go to the last tab page + :tabnext $ " as above + :tabnext - " go to the previous tab page + :tabnext -1 " as above + :tabnext + " go to the next tab page + :tabnext +1 " as above + {count}<C-PageDown> {count}gt Go to tab page {count}. The first tab page has number one. @@ -195,6 +217,12 @@ Other commands: :tabs List the tab pages and the windows they contain. Shows a ">" for the current window. Shows a "+" for modified buffers. + For example: + Tab page 1 ~ + + tabpage.txt ~ + ex_docmd.c ~ + Tab page 2 ~ + > main.c ~ REORDERING TAB PAGES: @@ -273,6 +301,7 @@ Variables local to a tab page start with "t:". |tabpage-variable| Currently there is only one option local to a tab page: 'cmdheight'. + *tabnew-autocmd* The TabLeave and TabEnter autocommand events can be used to do something when switching from one tab page to another. The exact order depends on what you are doing. When creating a new tab page this works as if you create a new diff --git a/runtime/doc/tagsrch.txt b/runtime/doc/tagsrch.txt index 75d820d072..d5a4f4e627 100644 --- a/runtime/doc/tagsrch.txt +++ b/runtime/doc/tagsrch.txt @@ -1,4 +1,4 @@ -*tagsrch.txt* For Vim version 7.4. Last change: 2013 Oct 01 +*tagsrch.txt* Nvim VIM REFERENCE MANUAL by Bram Moolenaar @@ -8,12 +8,7 @@ Tags and special searches *tags-and-searches* See section |29.1| of the user manual for an introduction. -1. Jump to a tag |tag-commands| -2. Tag stack |tag-stack| -3. Tag match list |tag-matchlist| -4. Tags details |tag-details| -5. Tags file format |tags-file-format| -6. Include file searches |include-search| + Type <M-]> to see the table of contents. ============================================================================== 1. Jump to a tag *tag-commands* @@ -83,14 +78,23 @@ Note that when the current file changes, the priority list is mostly not changed, to avoid confusion when using ":tnext". It is changed when using ":tag {ident}". -The ignore-case matches are not found for a ":tag" command when the -'ignorecase' option is off and 'tagcase' is "followic" or when 'tagcase' is -"match". They are found when a pattern is used (starting with a "/") and for -":tselect", also when 'ignorecase' is off and 'tagcase' is "followic" or when -'tagcase' is "match". Note that using ignore-case tag searching disables -binary searching in the tags file, which causes a slowdown. This can be -avoided by fold-case sorting the tag file. See the 'tagbsearch' option for an -explanation. +The ignore-case matches are not found for a ":tag" command when: +- the 'ignorecase' option is off and 'tagcase' is "followic" +- 'tagcase' is "match" +- 'tagcase' is "smart" and the pattern contains an upper case character. +- 'tagcase' is "followscs" and 'smartcase' option is on and the pattern + contains an upper case character. + +The ignore-case matches are found when: +- a pattern is used (starting with a "/") +- for ":tselect" +- when 'tagcase' is "followic" and 'ignorecase' is off +- when 'tagcase' is "match" +- when 'tagcase' is "followscs" and the 'smartcase' option is off + +Note that using ignore-case tag searching disables binary searching in the +tags file, which causes a slowdown. This can be avoided by fold-case sorting +the tag file. See the 'tagbsearch' option for an explanation. ============================================================================== 2. Tag stack *tag-stack* *tagstack* *E425* @@ -420,13 +424,18 @@ file "tags". It can also be used to access a common tags file. The next file in the list is not used when: - A matching static tag for the current buffer has been found. - A matching global tag has been found. -This also depends on whether case is ignored. Case is ignored when -'ignorecase' is set and 'tagcase' is "followic", or when 'tagcase' is -"ignore". If case is not ignored, and the tags file only has a match without -matching case, the next tags file is searched for a match with matching case. -If no tag with matching case is found, the first match without matching case -is used. If case is ignored, and a matching global tag with or without -matching case is found, this one is used, no further tags files are searched. +This also depends on whether case is ignored. Case is ignored when: +- 'tagcase' is "followic" and 'ignorecase' is set +- 'tagcase' is "ignore" +- 'tagcase' is "smart" and the pattern only contains lower case + characters. +- 'tagcase' is "followscs" and 'smartcase' is set and the pattern only + contains lower case characters. +If case is not ignored, and the tags file only has a match without matching +case, the next tags file is searched for a match with matching case. If no +tag with matching case is found, the first match without matching case is +used. If case is ignored, and a matching global tag with or without matching +case is found, this one is used, no further tags files are searched. When a tag file name starts with "./", the '.' is replaced with the path of the current file. This makes it possible to use a tags file in the directory @@ -789,24 +798,24 @@ CTRL-W d Open a new window, with the cursor on the first *:search-args* Common arguments for the commands above: -[!] When included, find matches in lines that are recognized as comments. - When excluded, a match is ignored when the line is recognized as a - comment (according to 'comments'), or the match is in a C comment (after - "//" or inside /* */). Note that a match may be missed if a line is - recognized as a comment, but the comment ends halfway through the line. - And if the line is a comment, but it is not recognized (according to - 'comments') a match may be found in it anyway. Example: > +[!] When included, find matches in lines that are recognized as comments. + When excluded, a match is ignored when the line is recognized as a + comment (according to 'comments'), or the match is in a C comment + (after "//" or inside /* */). Note that a match may be missed if a + line is recognized as a comment, but the comment ends halfway the line. + And if the line is a comment, but it is not recognized (according to + 'comments') a match may be found in it anyway. Example: > /* comment foobar */ -< A match for "foobar" is found, because this line is not recognized as a - comment (even though syntax highlighting does recognize it). - Note: Since a macro definition mostly doesn't look like a comment, the - [!] makes no difference for ":dlist", ":dsearch" and ":djump". -[/] A pattern can be surrounded by '/'. Without '/' only whole words are - matched, using the pattern "\<pattern\>". Only after the second '/' a - next command can be appended with '|'. Example: > +< A match for "foobar" is found, because this line is not recognized as + a comment (even though syntax highlighting does recognize it). + Note: Since a macro definition mostly doesn't look like a comment, the + [!] makes no difference for ":dlist", ":dsearch" and ":djump". +[/] A pattern can be surrounded by '/'. Without '/' only whole words are + matched, using the pattern "\<pattern\>". Only after the second '/' a + next command can be appended with '|'. Example: > :isearch /string/ | echo "the last one" -< For a ":djump", ":dsplit", ":dlist" and ":dsearch" command the pattern - is used as a literal string, not as a search pattern. +< For a ":djump", ":dsplit", ":dlist" and ":dsearch" command the pattern + is used as a literal string, not as a search pattern. vim:tw=78:ts=8:ft=help:norl: diff --git a/runtime/doc/term.txt b/runtime/doc/term.txt index 08ffee7a2f..39eb0673c4 100644 --- a/runtime/doc/term.txt +++ b/runtime/doc/term.txt @@ -1,78 +1,195 @@ -*term.txt* For Vim version 7.4. Last change: 2015 Nov 24 +*term.txt* Nvim - VIM REFERENCE MANUAL by Bram Moolenaar + NVIM REFERENCE MANUAL -Terminal information *terminal-info* +Terminal UI *tui* -Vim uses information about the terminal you are using to fill the screen and -recognize what keys you hit. If this information is not correct, the screen -may be messed up or keys may not be recognized. The actions which have to be -performed on the screen are accomplished by outputting a string of -characters. Special keys produce a string of characters. These strings are -stored in the terminal options, see |terminal-options|. +Nvim (except in |--headless| mode) uses information about the terminal you are +using to present a built-in UI. If that information is not correct, the +screen may be messed up or keys may not be recognized. -NOTE: Most of this is not used when running the |GUI|. - -1. Startup |startup-terminal| -2. Terminal options |terminal-options| -3. Window size |window-size| -4. Slow and fast terminals |slow-fast-terminal| -5. Using the mouse |mouse-using| + Type <M-]> to see the table of contents. ============================================================================== -1. Startup *startup-terminal* +Startup *startup-terminal* -When Vim is started a default terminal type is assumed. for MS-DOS this is -the pc terminal, for Unix an ansi terminal. +Nvim (except in |--headless| mode) guesses a terminal type when it starts. +|$TERM| is the primary hint that determines the terminal type. - *termcap* *terminfo* *E557* *E558* *E559* -On Unix the terminfo database or termcap file is used. This is referred to as -"termcap" in all the documentation. At compile time, when running configure, -the choice whether to use terminfo or termcap is done automatically. When -running Vim the output of ":version" will show |+terminfo| if terminfo is -used. Also see |xterm-screens|. + *terminfo* *E557* *E558* *E559* +The terminfo database is used if available. -Settings depending on terminal *term-dependent-settings* +The Unibilium library (used by Nvim to read terminfo) allows you to override +the system terminfo with one in $HOME/.terminfo/ directory, in part or in +whole. -If you want to set options or mappings, depending on the terminal name, you -can do this best in your vimrc. Example: > +Building your own terminfo is usually as simple as running this as +a non-superuser: +> + curl -LO http://invisible-island.net/datafiles/current/terminfo.src.gz + gunzip terminfo.src.gz + tic terminfo.src +< + *$TERM* +The $TERM environment variable must match the terminal you are using! +Otherwise Nvim cannot know what sequences your terminal expects, and weird +or sub-optimal behavior will result (scrolling quirks, wrong colors, etc.). + +$TERM is also important because it is mirrored by SSH to the remote session, +unlike other common client-end environment variables ($COLORTERM, +$XTERM_VERSION, $VTE_VERSION, $KONSOLE_PROFILE_NAME, $TERM_PROGRAM, ...). + + For this terminal Set $TERM to |builtin-terms| + ------------------------------------------------------------------------- + iTerm (original) iterm, iTerm.app N + iTerm2 (new capabilities) iterm2, iTerm2.app Y + anything libvte-based vte, vte-256color Y + (e.g. GNOME Terminal) (aliases: gnome, gnome-256color) + tmux tmux, tmux-256color Y + screen screen, screen-256color Y + PuTTY putty, putty-256color Y + Terminal.app nsterm N + Linux virtual terminal linux, linux-256color Y + + *builtin-terms* *builtin_terms* +If a |terminfo| database is not available, or no entry for the terminal type is +found in that database, Nvim will use a compiled-in mini-database of terminfo +entries for "xterm", "putty", "screen", "tmux", "rxvt", "iterm", "interix", +"linux", "st", "vte", "gnome", and "ansi". + +The lookup matches the initial portion of the terminal type, so (for example) +"putty-256color" and "putty" will both be mapped to the built-in "putty" +entry. The built-in terminfo entries describe the terminal as 256-colour +capable if possible. See |tui-colors|. + +If no built-in terminfo record matches the terminal type, the built-in "ansi" +terminfo record is used as a final fallback. + +The built-in mini-database is not combined with an external terminfo database, +nor can it be used in preference to one. You can thus entirely override any +omissions or out-of-date information in the built-in terminfo database by +supplying an external one with entries for the terminal type. - if &term == "xterm" - ... xterm maps and settings ... - elseif &term =~ "vt10." - ... vt100, vt102 maps and settings ... - endif +Settings depending on terminal *term-dependent-settings* + +If you want to set terminal-dependent options or mappings, you can do this in +your init.vim. Example: > + + if $TERM =~ '^\(rxvt\|screen\|interix\|putty\)\(-.*\)\?$' + set notermguicolors + elseif $TERM =~ '^\(tmux\|iterm\|vte\|gnome\)\(-.*\)\?$' + set termguicolors + elseif $TERM =~ '^\(xterm\)\(-.*\)\?$' + if $XTERM_VERSION != '' + set termguicolors + elseif $KONSOLE_PROFILE_NAME != '' + set termguicolors + elseif $VTE_VERSION != '' + set termguicolors + else + set notermguicolors + endif + elseif $TERM =~ ... + ... and so forth ... + endif < - *raw-terminal-mode* -For normal editing the terminal will be put into "raw" mode. The strings -defined with 't_ti' and 't_ks' will be sent to the terminal. Normally this -puts the terminal in a state where the termcap codes are valid and activates -the cursor and function keys. When Vim exits the terminal will be put back -into the mode it was before Vim started. The strings defined with 't_te' and -'t_ke' will be sent to the terminal. + *scroll-region* *xterm-scroll-region* +Where possible, Nvim will use the terminal's ability to set a scroll region in +order to redraw faster when a window is scrolled. If the terminal's terminfo +description describes an ability to set top and bottom scroll margins, that is +used. + +This will not speed up scrolling in a window that is not the full width of the +terminal. Xterm has an extra ability, not described by terminfo, to set left +and right scroll margins as well. If Nvim detects that the terminal is Xterm, +it will make use of this ability to speed up scrolling that is not the full +width of the terminal. + +This ability is only present in genuine Xterm, not in the many terminal +emulators that incorrectly describe themselves as xterm. Nvim's detection of +genuine Xterm will not work over an SSH connection, because the environment +variable, set by genuine Xterm, that it looks for is not automatically +replicated over an SSH login session. + + *tui-colors* +Nvim uses 256 colours by default, ignoring |terminfo| for most terminal types, +including "linux" (whose virtual terminals have had 256-colour support since +4.8) and anything claiming to be "xterm". Also when $COLORTERM or $TERM +contain the string "256". + +Nvim similarly assumes that any terminal emulator that sets $COLORTERM to any +value, is capable of at least 16-colour operation. + + *true-color* *xterm-true-color* +Nvim emits true (24-bit) colours in the terminal, if 'termguicolors' is set. + +It uses the "setrgbf" and "setrgbb" |terminfo| extensions (proposed by Rรผdiger +Sonderfeld in 2013). If your terminfo definition is missing them, then Nvim +will decide whether to add them to your terminfo definition, using the ISO +8613-6:1994/ITU T.416:1993 control sequences for setting RGB colours (but +modified to use semicolons instead of colons unless the terminal is known to +follow the standard). + +Another convention, pioneered in 2016 by tmux, is the "Tc" terminfo extension. +If terminfo has this flag, Nvim will add constructed "setrgbf" and "setrgbb" +capabilities as if they had been in the terminfo definition. + +If terminfo does not (yet) have this flag, Nvim will fall back to $TERM and +other environment variables. It will add constructed "setrgbf" and "setrgbb" +capabilities in the case of the the "rxvt", "linux", "st", "tmux", and "iterm" +terminal types, or when Konsole, genuine Xterm, a libvte terminal emulator +version 0.36 or later, or a terminal emulator that sets the COLORTERM +environment variable to "truecolor" is detected. + *xterm-resize* +Nvim can resize the terminal display on some terminals that implement an +extension pioneered by dtterm. |terminfo| does not have a flag for this +extension. So Nvim simply assumes that (all) "dtterm", "xterm", "teraterm", +"rxvt" terminal types, and Konsole, are capable of this. + + *tui-cursor-shape* +Nvim will adjust the shape of the cursor from a block to a line when in insert +mode (or as specified by the 'guicursor' option), on terminals that support +it. It uses the same |terminfo| extensions that were pioneered by tmux for +this: "Ss" and "Se". + +If your terminfo definition is missing them, then Nvim will decide whether to +add them to your terminfo definition, by looking at $TERM and other +environment variables. For the "rxvt", "putty", "linux", "screen", +"teraterm", and "iterm" terminal types, or when Konsole, a libvte-based +terminal emulator, or genuine Xterm are detected, it will add constructed +"Ss" and "Se" capabilities. + +Note: Sometimes it will appear that Nvim when run within tmux is not changing +the cursor, but in fact it is tmux receiving instructions from Nvim to change +the cursor and not knowing what to do in turn. tmux has to translate what it +receives from Nvim into whatever control sequence is appropriate for the +terminal that it is outputting to. It shares a common mechanism with Nvim, of +using the "Ss" and "Se" capabilities from terminfo (for the output terminal) +if they are present. Unlike Nvim, if they are not present in terminfo you +must add them by setting "terminal-overrides" in ~/.tmux.conf . + +See the tmux(1) manual page for the details of how and what to do in the tmux +configuration file. It will look something like: > + set -ga terminal-overrides '*:Ss=\E[%p1%d q:Se=\E[ q' +<or (alas!) for Konsole specifically, something more complex like: > + set -ga terminal-overrides 'xterm*:\E]50;CursorShape=%?%p1%{3}%<%t%{0}%e%{1}%;%d\007' +< *cs7-problem* Note: If the terminal settings are changed after running Vim, you might have an illegal combination of settings. This has been reported on Solaris 2.5 with "stty cs8 parenb", which is restored as "stty cs7 parenb". Use "stty cs8 -parenb -istrip" instead, this is restored correctly. -Some termcap entries are wrong in the sense that after sending 't_ks' the -cursor keys send codes different from the codes defined in the termcap. To -avoid this you can set 't_ks' (and 't_ke') to empty strings. This must be -done during initialization (see |initialization|), otherwise it's too late. - Many cursor key codes start with an <Esc>. Vim must find out if this is a single hit of the <Esc> key or the start of a cursor key sequence. It waits for a next character to arrive. If it does not arrive within one second a single <Esc> is assumed. On very slow systems this may fail, causing cursor keys not to work sometimes. If you discover this problem reset the 'timeout' option. Vim will wait for the next character to arrive after an <Esc>. If -you want to enter a single <Esc> you must type it twice. Resetting the -'esckeys' option avoids this problem in Insert mode, but you lose the -possibility to use cursor and function keys in Insert mode. +you want to enter a single <Esc> you must type it twice. Some terminals have confusing codes for the cursor keys. The televideo 925 is such a terminal. It sends a CTRL-H for cursor-left. This would make it @@ -94,368 +211,8 @@ them as a cursor key. When you type you normally are not that fast, so they are recognized as individual typed commands, even though Vim receives the same sequence of bytes. - *vt100-function-keys* *xterm-function-keys* -An xterm can send function keys F1 to F4 in two modes: vt100 compatible or -not. Because Vim may not know what the xterm is sending, both types of keys -are recognized. The same happens for the <Home> and <End> keys. - normal vt100 ~ - <F1> t_k1 <Esc>[11~ <xF1> <Esc>OP *<xF1>-xterm* - <F2> t_k2 <Esc>[12~ <xF2> <Esc>OQ *<xF2>-xterm* - <F3> t_k3 <Esc>[13~ <xF3> <Esc>OR *<xF3>-xterm* - <F4> t_k4 <Esc>[14~ <xF4> <Esc>OS *<xF4>-xterm* - <Home> t_kh <Esc>[7~ <xHome> <Esc>OH *<xHome>-xterm* - <End> t_@7 <Esc>[4~ <xEnd> <Esc>OF *<xEnd>-xterm* - -When Vim starts, <xF1> is mapped to <F1>, <xF2> to <F2> etc. This means that -by default both codes do the same thing. If you make a mapping for <xF2>, -because your terminal does have two keys, the default mapping is overwritten, -thus you can use the <F2> and <xF2> keys for something different. - - *xterm-shifted-keys* -Newer versions of xterm support shifted function keys and special keys. Vim -recognizes most of them. Use ":set termcap" to check which are supported and -what the codes are. Mostly these are not in a termcap, they are only -supported by the builtin_xterm termcap. - - *xterm-modifier-keys* -Newer versions of xterm support Alt and Ctrl for most function keys. To avoid -having to add all combinations of Alt, Ctrl and Shift for every key a special -sequence is recognized at the end of a termcap entry: ";*X". The "X" can be -any character, often '~' is used. The ";*" stands for an optional modifier -argument. ";2" is Shift, ";3" is Alt, ";5" is Ctrl and ";9" is Meta (when -it's different from Alt). They can be combined. Examples: > - :set <F8>=^[[19;*~ - :set <Home>=^[[1;*H -Another speciality about these codes is that they are not overwritten by -another code. That is to avoid that the codes obtained from xterm directly -|t_RV| overwrite them. - *xterm-scroll-region* -The default termcap entry for xterm on Sun and other platforms does not -contain the entry for scroll regions. Add ":cs=\E[%i%d;%dr:" to the xterm -entry in /etc/termcap and everything should work. - - *xterm-end-home-keys* -On some systems (at least on FreeBSD with XFree86 3.1.2) the codes that the -<End> and <Home> keys send contain a <Nul> character. To make these keys send -the proper key code, add these lines to your ~/.Xdefaults file: - -*VT100.Translations: #override \n\ - <Key>Home: string("0x1b") string("[7~") \n\ - <Key>End: string("0x1b") string("[8~") - - *xterm-8bit* *xterm-8-bit* -Xterm can be run in a mode where it uses 8-bit escape sequences. The CSI code -is used instead of <Esc>[. The advantage is that an <Esc> can quickly be -recognized in Insert mode, because it can't be confused with the start of a -special key. -For the builtin termcap entries, Vim checks if the 'term' option contains -"8bit" anywhere. It then uses 8-bit characters for the termcap entries, the -mouse and a few other things. You would normally set $TERM in your shell to -"xterm-8bit" and Vim picks this up and adjusts to the 8-bit setting -automatically. -When Vim receives a response to the |t_RV| (request version) sequence and it -starts with CSI, it assumes that the terminal is in 8-bit mode and will -convert all key sequences to their 8-bit variants. - ============================================================================== -2. Terminal options *terminal-options* *termcap-options* *E436* - -The terminal options can be set just like normal options. But they are not -shown with the ":set all" command. Instead use ":set termcap". - -It is always possible to change individual strings by setting the -appropriate option. For example: > - :set t_ce=^V^[[K (CTRL-V, <Esc>, [, K) - -The options are listed below. The associated termcap code is always equal to -the last two characters of the option name. Only one termcap code is -required: Cursor motion, 't_cm'. - -The options 't_da', 't_db', 't_ms', 't_xs' represent flags in the termcap. -When the termcap flag is present, the option will be set to "y". But any -non-empty string means that the flag is set. An empty string means that the -flag is not set. 't_CS' works like this too, but it isn't a termcap flag. - -OUTPUT CODES - option meaning ~ - - t_AB set background color (ANSI) *t_AB* *'t_AB'* - t_AF set foreground color (ANSI) *t_AF* *'t_AF'* - t_AL add number of blank lines *t_AL* *'t_AL'* - t_al add new blank line *t_al* *'t_al'* - t_bc backspace character *t_bc* *'t_bc'* - t_cd clear to end of screen *t_cd* *'t_cd'* - t_ce clear to end of line *t_ce* *'t_ce'* - t_cl clear screen *t_cl* *'t_cl'* - t_cm cursor motion (required!) *E437* *t_cm* *'t_cm'* - t_Co number of colors *t_Co* *'t_Co'* - t_CS if non-empty, cursor relative to scroll region *t_CS* *'t_CS'* - t_cs define scrolling region *t_cs* *'t_cs'* - t_CV define vertical scrolling region *t_CV* *'t_CV'* - t_da if non-empty, lines from above scroll down *t_da* *'t_da'* - t_db if non-empty, lines from below scroll up *t_db* *'t_db'* - t_DL delete number of lines *t_DL* *'t_DL'* - t_dl delete line *t_dl* *'t_dl'* - t_fs set window title end (from status line) *t_fs* *'t_fs'* - t_ke exit "keypad transmit" mode *t_ke* *'t_ke'* - t_ks start "keypad transmit" mode *t_ks* *'t_ks'* - t_le move cursor one char left *t_le* *'t_le'* - t_mb blinking mode *t_mb* *'t_mb'* - t_md bold mode *t_md* *'t_md'* - t_me Normal mode (undoes t_mr, t_mb, t_md and color) *t_me* *'t_me'* - t_mr reverse (invert) mode *t_mr* *'t_mr'* - *t_ms* *'t_ms'* - t_ms if non-empty, cursor can be moved in standout/inverse mode - t_nd non destructive space character *t_nd* *'t_nd'* - t_op reset to original color pair *t_op* *'t_op'* - t_RI cursor number of chars right *t_RI* *'t_RI'* - t_Sb set background color *t_Sb* *'t_Sb'* - t_Sf set foreground color *t_Sf* *'t_Sf'* - t_se standout end *t_se* *'t_se'* - t_so standout mode *t_so* *'t_so'* - t_sr scroll reverse (backward) *t_sr* *'t_sr'* - t_te out of "termcap" mode *t_te* *'t_te'* - t_ti put terminal in "termcap" mode *t_ti* *'t_ti'* - t_ts set window title start (to status line) *t_ts* *'t_ts'* - t_ue underline end *t_ue* *'t_ue'* - t_us underline mode *t_us* *'t_us'* - t_Ce undercurl end *t_Ce* *'t_Ce'* - t_Cs undercurl mode *t_Cs* *'t_Cs'* - t_ut clearing uses the current background color *t_ut* *'t_ut'* - t_vb visual bell *t_vb* *'t_vb'* - t_ve cursor visible *t_ve* *'t_ve'* - t_vi cursor invisible *t_vi* *'t_vi'* - t_vs cursor very visible *t_vs* *'t_vs'* - *t_xs* *'t_xs'* - t_xs if non-empty, standout not erased by overwriting (hpterm) - t_ZH italics mode *t_ZH* *'t_ZH'* - t_ZR italics end *t_ZR* *'t_ZR'* - -Added by Vim (there are no standard codes for these): - t_IS set icon text start *t_IS* *'t_IS'* - t_IE set icon text end *t_IE* *'t_IE'* - t_WP set window position (Y, X) in pixels *t_WP* *'t_WP'* - t_WS set window size (height, width) in characters *t_WS* *'t_WS'* - t_SI start insert mode (bar cursor shape) *t_SI* *'t_SI'* - t_EI end insert mode (block cursor shape) *t_EI* *'t_EI'* - |termcap-cursor-shape| - t_RV request terminal version string (for xterm) *t_RV* *'t_RV'* - |xterm-8bit| |v:termresponse| |xterm-codes| - t_u7 request cursor position (for xterm) *t_u7* *'t_u7'* - see |'ambiwidth'| - -KEY CODES -Note: Use the <> form if possible - - option name meaning ~ - - t_ku <Up> arrow up *t_ku* *'t_ku'* - t_kd <Down> arrow down *t_kd* *'t_kd'* - t_kr <Right> arrow right *t_kr* *'t_kr'* - t_kl <Left> arrow left *t_kl* *'t_kl'* - <xUp> alternate arrow up *<xUp>* - <xDown> alternate arrow down *<xDown>* - <xRight> alternate arrow right *<xRight>* - <xLeft> alternate arrow left *<xLeft>* - <S-Up> shift arrow up - <S-Down> shift arrow down - t_%i <S-Right> shift arrow right *t_%i* *'t_%i'* - t_#4 <S-Left> shift arrow left *t_#4* *'t_#4'* - t_k1 <F1> function key 1 *t_k1* *'t_k1'* - <xF1> alternate F1 *<xF1>* - t_k2 <F2> function key 2 *<F2>* *t_k2* *'t_k2'* - <xF2> alternate F2 *<xF2>* - t_k3 <F3> function key 3 *<F3>* *t_k3* *'t_k3'* - <xF3> alternate F3 *<xF3>* - t_k4 <F4> function key 4 *<F4>* *t_k4* *'t_k4'* - <xF4> alternate F4 *<xF4>* - t_k5 <F5> function key 5 *<F5>* *t_k5* *'t_k5'* - t_k6 <F6> function key 6 *<F6>* *t_k6* *'t_k6'* - t_k7 <F7> function key 7 *<F7>* *t_k7* *'t_k7'* - t_k8 <F8> function key 8 *<F8>* *t_k8* *'t_k8'* - t_k9 <F9> function key 9 *<F9>* *t_k9* *'t_k9'* - t_k; <F10> function key 10 *<F10>* *t_k;* *'t_k;'* - t_F1 <F11> function key 11 *<F11>* *t_F1* *'t_F1'* - t_F2 <F12> function key 12 *<F12>* *t_F2* *'t_F2'* - t_F3 <F13> function key 13 *<F13>* *t_F3* *'t_F3'* - t_F4 <F14> function key 14 *<F14>* *t_F4* *'t_F4'* - t_F5 <F15> function key 15 *<F15>* *t_F5* *'t_F5'* - t_F6 <F16> function key 16 *<F16>* *t_F6* *'t_F6'* - t_F7 <F17> function key 17 *<F17>* *t_F7* *'t_F7'* - t_F8 <F18> function key 18 *<F18>* *t_F8* *'t_F8'* - t_F9 <F19> function key 19 *<F19>* *t_F9* *'t_F9'* - <S-F1> shifted function key 1 - <S-xF1> alternate <S-F1> *<S-xF1>* - <S-F2> shifted function key 2 *<S-F2>* - <S-xF2> alternate <S-F2> *<S-xF2>* - <S-F3> shifted function key 3 *<S-F3>* - <S-xF3> alternate <S-F3> *<S-xF3>* - <S-F4> shifted function key 4 *<S-F4>* - <S-xF4> alternate <S-F4> *<S-xF4>* - <S-F5> shifted function key 5 *<S-F5>* - <S-F6> shifted function key 6 *<S-F6>* - <S-F7> shifted function key 7 *<S-F7>* - <S-F8> shifted function key 8 *<S-F8>* - <S-F9> shifted function key 9 *<S-F9>* - <S-F10> shifted function key 10 *<S-F10>* - <S-F11> shifted function key 11 *<S-F11>* - <S-F12> shifted function key 12 *<S-F12>* - t_%1 <Help> help key *t_%1* *'t_%1'* - t_&8 <Undo> undo key *t_&8* *'t_&8'* - t_kI <Insert> insert key *t_kI* *'t_kI'* - t_kD <Del> delete key *t_kD* *'t_kD'* - t_kb <BS> backspace key *t_kb* *'t_kb'* - t_kB <S-Tab> back-tab (shift-tab) *<S-Tab>* *t_kB* *'t_kB'* - t_kh <Home> home key *t_kh* *'t_kh'* - t_#2 <S-Home> shifted home key *<S-Home>* *t_#2* *'t_#2'* - <xHome> alternate home key *<xHome>* - t_@7 <End> end key *t_@7* *'t_@7'* - t_*7 <S-End> shifted end key *<S-End>* *t_star7* *'t_star7'* - <xEnd> alternate end key *<xEnd>* - t_kP <PageUp> page-up key *t_kP* *'t_kP'* - t_kN <PageDown> page-down key *t_kN* *'t_kN'* - t_K1 <kHome> keypad home key *t_K1* *'t_K1'* - t_K4 <kEnd> keypad end key *t_K4* *'t_K4'* - t_K3 <kPageUp> keypad page-up key *t_K3* *'t_K3'* - t_K5 <kPageDown> keypad page-down key *t_K5* *'t_K5'* - t_K6 <kPlus> keypad plus key *<kPlus>* *t_K6* *'t_K6'* - t_K7 <kMinus> keypad minus key *<kMinus>* *t_K7* *'t_K7'* - t_K8 <kDivide> keypad divide *<kDivide>* *t_K8* *'t_K8'* - t_K9 <kMultiply> keypad multiply *<kMultiply>* *t_K9* *'t_K9'* - t_KA <kEnter> keypad enter key *<kEnter>* *t_KA* *'t_KA'* - t_KB <kPoint> keypad decimal point *<kPoint>* *t_KB* *'t_KB'* - t_KC <k0> keypad 0 *<k0>* *t_KC* *'t_KC'* - t_KD <k1> keypad 1 *<k1>* *t_KD* *'t_KD'* - t_KE <k2> keypad 2 *<k2>* *t_KE* *'t_KE'* - t_KF <k3> keypad 3 *<k3>* *t_KF* *'t_KF'* - t_KG <k4> keypad 4 *<k4>* *t_KG* *'t_KG'* - t_KH <k5> keypad 5 *<k5>* *t_KH* *'t_KH'* - t_KI <k6> keypad 6 *<k6>* *t_KI* *'t_KI'* - t_KJ <k7> keypad 7 *<k7>* *t_KJ* *'t_KJ'* - t_KK <k8> keypad 8 *<k8>* *t_KK* *'t_KK'* - t_KL <k9> keypad 9 *<k9>* *t_KL* *'t_KL'* - <Mouse> leader of mouse code *<Mouse>* - -Note about t_so and t_mr: When the termcap entry "so" is not present the -entry for "mr" is used. And vice versa. The same is done for "se" and "me". -If your terminal supports both inversion and standout mode, you can see two -different modes. If your terminal supports only one of the modes, both will -look the same. - - *keypad-comma* -The keypad keys, when they are not mapped, behave like the equivalent normal -key. There is one exception: if you have a comma on the keypad instead of a -decimal point, Vim will use a dot anyway. Use these mappings to fix that: > - :noremap <kPoint> , - :noremap! <kPoint> , -< *xterm-codes* -There is a special trick to obtain the key codes which currently only works -for xterm. When |t_RV| is defined and a response is received which indicates -an xterm with patchlevel 141 or higher, Vim uses special escape sequences to -request the key codes directly from the xterm. The responses are used to -adjust the various t_ codes. This avoids the problem that the xterm can -produce different codes, depending on the mode it is in (8-bit, VT102, -VT220, etc.). The result is that codes like <xF1> are no longer needed. -Note: This is only done on startup. If the xterm options are changed after -Vim has started, the escape sequences may not be recognized anymore. - - *xterm-resize* -Window resizing with xterm only works if the allowWindowOps resource is -enabled. On some systems and versions of xterm it's disabled by default -because someone thought it would be a security issue. It's not clear if this -is actually the case. - -To overrule the default, put this line in your ~/.Xdefaults or -~/.Xresources: -> - XTerm*allowWindowOps: true - -And run "xrdb -merge .Xresources" to make it effective. You can check the -value with the context menu (right mouse button while CTRL key is pressed), -there should be a tick at allow-window-ops. - - *termcap-colors* -Note about colors: The 't_Co' option tells Vim the number of colors available. -When it is non-zero, the 't_AB' and 't_AF' options are used to set the color. -If one of these is not available, 't_Sb' and 't_Sf' are used. 't_me' is used -to reset to the default colors. - - *termcap-cursor-shape* *termcap-cursor-color* -When Vim enters Insert mode the 't_SI' escape sequence is sent. When leaving -Insert mode 't_EI' is used. But only if both are defined. This can be used -to change the shape or color of the cursor in Insert mode. These are not -standard termcap/terminfo entries, you need to set them yourself. -Example for an xterm, this changes the color of the cursor: > - if &term =~ "xterm" - let &t_SI = "\<Esc>]12;purple\x7" - let &t_EI = "\<Esc>]12;blue\x7" - endif -NOTE: When Vim exits the shape for Normal mode will remain. The shape from -before Vim started will not be restored. - - *termcap-title* -The 't_ts' and 't_fs' options are used to set the window title if the terminal -allows title setting via sending strings. They are sent before and after the -title string, respectively. Similar 't_IS' and 't_IE' are used to set the -icon text. These are Vim-internal extensions of the Unix termcap, so they -cannot be obtained from an external termcap. However, the builtin termcap -contains suitable entries for xterm, so you don't need to set them here. - *hpterm* -If inversion or other highlighting does not work correctly, try setting the -'t_xs' option to a non-empty string. This makes the 't_ce' code be used to -remove highlighting from a line. This is required for "hpterm". Setting the -'weirdinvert' option has the same effect as making 't_xs' non-empty, and vice -versa. - - *scroll-region* -Some termcaps do not include an entry for 'cs' (scroll region), although the -terminal does support it. For example: xterm on a Sun. You can use the -builtin_xterm or define t_cs yourself. For example: > - :set t_cs=^V^[[%i%d;%dr -Where ^V is CTRL-V and ^[ is <Esc>. - -The vertical scroll region t_CV is not a standard termcap code. Vim uses it -internally in the GUI. But it can also be defined for a terminal, if you can -find one that supports it. The two arguments are the left and right column of -the region which to restrict the scrolling to. Just like t_cs defines the top -and bottom lines. Defining t_CV will make scrolling in vertically split -windows a lot faster. Don't set t_CV when t_da or t_db is set (text isn't -cleared when scrolling). - -Unfortunately it is not possible to deduce from the termcap how cursor -positioning should be done when using a scrolling region: Relative to the -beginning of the screen or relative to the beginning of the scrolling region. -Most terminals use the first method. The 't_CS' option should be set to any -string when cursor positioning is relative to the start of the scrolling -region. It should be set to an empty string otherwise. - -Note for xterm users: The shifted cursor keys normally don't work. You can - make them work with the xmodmap command and some mappings in Vim. - - Give these commands in the xterm: - xmodmap -e "keysym Up = Up F13" - xmodmap -e "keysym Down = Down F16" - xmodmap -e "keysym Left = Left F18" - xmodmap -e "keysym Right = Right F19" - - And use these mappings in Vim: - :map <t_F3> <S-Up> - :map! <t_F3> <S-Up> - :map <t_F6> <S-Down> - :map! <t_F6> <S-Down> - :map <t_F8> <S-Left> - :map! <t_F8> <S-Left> - :map <t_F9> <S-Right> - :map! <t_F9> <S-Right> - -Instead of, say, <S-Up> you can use any other command that you want to use the -shift-cursor-up key for. (Note: To help people that have a Sun keyboard with -left side keys F14 is not used because it is confused with the undo key; F15 -is not used, because it does a window-to-front; F17 is not used, because it -closes the window. On other systems you can probably use them.) - -============================================================================== -3. Window size *window-size* +Window size *window-size* [This is about the size of the whole window Vim is using, not a window that is created with the ":split" command.] @@ -464,22 +221,15 @@ On Unix systems, three methods are tried to get the window size: - an ioctl call (TIOCGSIZE or TIOCGWINSZ, depends on your system) - the environment variables "LINES" and "COLUMNS" -- from the termcap entries "li" and "co" +- from the |terminfo| entries "lines" and "columns" If everything fails a default size of 24 lines and 80 columns is assumed. If a window-resize signal is received the size will be set again. If the window size is wrong you can use the 'lines' and 'columns' options to set the -correct values. - -One command can be used to set the screen size: - - *:mod* *:mode* -:mod[e] - -Detects the screen size and redraws the screen. +correct values. See |:mode|. ============================================================================== -4. Slow and fast terminals *slow-fast-terminal* +Slow and fast terminals *slow-fast-terminal* *slow-terminal* If you have a fast terminal you may like to set the 'ruler' option. The @@ -487,33 +237,30 @@ cursor position is shown in the status line. If you are using horizontal scrolling ('wrap' option off) consider setting 'sidescroll' to a small number. -If you have a slow terminal you may want to reset the 'showcmd' option. -The command characters will not be shown in the status line. If the terminal -scrolls very slowly, set the 'scrolljump' to 5 or so. If the cursor is moved -off the screen (e.g., with "j") Vim will scroll 5 lines at a time. Another -possibility is to reduce the number of lines that Vim uses with the command -"z{height}<CR>". +If you have a slow terminal you may want to reset the 'showcmd' and 'ruler' +options. The command characters and cursor positions will not be shown in the +status line (which involves a lot of cursor motions and attribute changes for +every keypress or movement). If the terminal scrolls very slowly, set the +'scrolljump' to 5 or so. If the cursor is moved off the screen (e.g., with +"j") Vim will scroll 5 lines at a time. Another possibility is to reduce the +number of lines that Vim uses with the command "z{height}<CR>". If the characters from the terminal are arriving with more than 1 second between them you might want to set the 'timeout' and/or 'ttimeout' option. See the "Options" chapter |options|. -If you are using a color terminal that is slow, use this command: > +If you are using a color terminal that is slow when displaying lines beyond +the end of a buffer, this is because Nvim is drawing the whitespace twice, in +two sets of colours and attributes. To prevent this, use this command: > hi NonText cterm=NONE ctermfg=NONE -This avoids that spaces are sent when they have different attributes. On most -terminals you can't see this anyway. - -If you are using Vim over a slow serial line, you might want to try running -Vim inside the "screen" program. Screen will optimize the terminal I/O quite -a bit. - -If you are testing termcap options, but you cannot see what is happening, -you might want to set the 'writedelay' option. When non-zero, one character -is sent to the terminal at a time (does not work for MS-DOS). This makes the -screen updating a lot slower, making it possible to see what is happening. +This draws the spaces with the default colours and attributes, which allows the +second pass of drawing to be optimized away. Note: Although in theory the +colours of whitespace are immaterial, in practice they change the colours of +cursors and selections that cross them. This may have a visible, but minor, +effect on some UIs. ============================================================================== -5. Using the mouse *mouse-using* +Using the mouse *mouse-using* This section is about using the mouse on a terminal or a terminal window. How to use the mouse in a GUI window is explained in |gui-mouse|. For scrolling @@ -590,17 +337,12 @@ before using the mouse: "g<RightMouse>" is "<C-RightMouse> ("CTRL-T") *bracketed-paste-mode* -Bracketed paste mode allows terminal emulators to distinguish between typed -text and pasted text. - -For terminal emulators that support it, this mode is enabled by default. Thus -you can paste text without Neovim giving any special meaning to it. Most -notably it won't try reindenting those lines. - -If your terminal emulator doesn't support it yet, you can get the old Vim -behaviour by enabling |'paste'| temporarily. +Bracketed paste mode allows terminal applications to distinguish between typed +text and pasted text. Thus you can paste text without Nvim trying to format or +indent the text. See also https://cirw.in/blog/bracketed-paste -NOTE: See https://cirw.in/blog/bracketed-paste for technical details. +Nvim enables bracketed paste by default. If it does not work in your terminal, +try the 'paste' option instead. *mouse-mode-table* *mouse-overview* A short overview of what the mouse buttons do, when 'mousemodel' is "extend": diff --git a/runtime/doc/tips.txt b/runtime/doc/tips.txt index 8032af7d0a..0ac9a8303d 100644 --- a/runtime/doc/tips.txt +++ b/runtime/doc/tips.txt @@ -1,4 +1,4 @@ -*tips.txt* For Vim version 7.4. Last change: 2009 Nov 07 +*tips.txt* Nvim VIM REFERENCE MANUAL by Bram Moolenaar @@ -13,22 +13,7 @@ http://www.vim.org Don't forget to browse the user manual, it also contains lots of useful tips |usr_toc.txt|. -Editing C programs |C-editing| -Finding where identifiers are used |ident-search| -Switching screens in an xterm |xterm-screens| -Scrolling in Insert mode |scroll-insert| -Smooth scrolling |scroll-smooth| -Correcting common typing mistakes |type-mistakes| -Counting words, lines, etc. |count-items| -Restoring the cursor position |restore-position| -Renaming files |rename-files| -Change a name in multiple files |change-name| -Speeding up external commands |speed-up| -Useful mappings |useful-mappings| -Compressing the help files |gzip-helpfile| -Hex editing |hex-editing| -Using <> notation in autocommands |autocmd-<>| -Highlighting matching parens |match-parens| + Type <M-]> to see the table of contents. ============================================================================== Editing C programs *C-editing* @@ -119,48 +104,6 @@ archive file on your closest gnu-ftp-mirror). [the idea for this comes from Andreas Kutschera] ============================================================================== -Switching screens in an xterm *xterm-screens* *xterm-save-screen* - -(From comp.editors, by Juergen Weigert, in reply to a question) - -:> Another question is that after exiting vim, the screen is left as it -:> was, i.e. the contents of the file I was viewing (editing) was left on -:> the screen. The output from my previous like "ls" were lost, -:> ie. no longer in the scrolling buffer. I know that there is a way to -:> restore the screen after exiting vim or other vi like editors, -:> I just don't know how. Helps are appreciated. Thanks. -: -:I imagine someone else can answer this. I assume though that vim and vi do -:the same thing as each other for a given xterm setup. - -They not necessarily do the same thing, as this may be a termcap vs. -terminfo problem. You should be aware that there are two databases for -describing attributes of a particular type of terminal: termcap and -terminfo. This can cause differences when the entries differ AND when of -the programs in question one uses terminfo and the other uses termcap -(also see |+terminfo|). - -In your particular problem, you are looking for the control sequences -^[[?47h and ^[[?47l. These switch between xterms alternate and main screen -buffer. As a quick workaround a command sequence like > - echo -n "^[[?47h"; vim ... ; echo -n "^[[?47l" -may do what you want. (My notation ^[ means the ESC character, further down -you'll see that the databases use \E instead). - -On startup, vim echoes the value of the termcap variable ti (terminfo: -smcup) to the terminal. When exiting, it echoes te (terminfo: rmcup). Thus -these two variables are the correct place where the above mentioned control -sequences should go. - -Compare your xterm termcap entry (found in /etc/termcap) with your xterm -terminfo entry (retrieved with "infocmp -C xterm"). Both should contain -entries similar to: > - :te=\E[2J\E[?47l\E8:ti=\E7\E[?47h: - -PS: If you find any difference, someone (your sysadmin?) should better check - the complete termcap and terminfo database for consistency. - -============================================================================== Scrolling in Insert mode *scroll-insert* If you are in insert mode and you want to see something that is just off the @@ -170,7 +113,6 @@ screen, you can use CTRL-X CTRL-E and CTRL-X CTRL-Y to scroll the screen. To make this easier, you could use these mappings: > :inoremap <C-E> <C-X><C-E> :inoremap <C-Y> <C-X><C-Y> -(Type this literally, make sure the '<' flag is not in 'cpoptions'). You then lose the ability to copy text from the line above/below the cursor |i_CTRL-E|. @@ -186,8 +128,6 @@ If you like the scrolling to go a bit smoother, you can use these mappings: > :map <C-U> <C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y> :map <C-D> <C-E><C-E><C-E><C-E><C-E><C-E><C-E><C-E><C-E><C-E><C-E><C-E><C-E><C-E><C-E><C-E> -(Type this literally, make sure the '<' flag is not in 'cpoptions'). - ============================================================================== Correcting common typing mistakes *type-mistakes* @@ -339,9 +279,7 @@ For Emacs-style editing on the command-line: > :cnoremap <Esc><C-B> <S-Left> " forward one word :cnoremap <Esc><C-F> <S-Right> - -NOTE: This requires that the '<' flag is excluded from 'cpoptions'. |<>| - +< *format-bullet-list* This mapping will format any bullet list. It requires that there is an empty line above and below each list entry. The expression commands are used to @@ -357,8 +295,7 @@ be able to give comments to the parts of the mapping. > :execute m |" define the mapping (<> notation |<>|. Note that this is all typed literally. ^W is "^" "W", not -CTRL-W. You can copy/paste this into Vim if '<' is not included in -'cpoptions'.) +CTRL-W.) Note that the last comment starts with |", because the ":execute" command doesn't accept a comment directly. @@ -400,7 +337,7 @@ when they are not in the same location as the compressed "doc" directory. See ============================================================================== Hex editing *hex-editing* *using-xxd* -See section |23.4| of the user manual. +See section |23.3| of the user manual. If one has a particular extension that one uses for binary files (such as exe, bin, etc), you may find it helpful to automate the process with the following diff --git a/runtime/doc/uganda.txt b/runtime/doc/uganda.txt index c228c65542..cdd677cbd5 100644 --- a/runtime/doc/uganda.txt +++ b/runtime/doc/uganda.txt @@ -1,4 +1,4 @@ -*uganda.txt* For Vim version 7.4. Last change: 2013 Jul 06 +*uganda.txt* Nvim VIM REFERENCE MANUAL by Bram Moolenaar diff --git a/runtime/doc/undo.txt b/runtime/doc/undo.txt index c6c70ab6d2..cbce868cec 100644 --- a/runtime/doc/undo.txt +++ b/runtime/doc/undo.txt @@ -1,4 +1,4 @@ -*undo.txt* For Vim version 7.4. Last change: 2014 May 24 +*undo.txt* Nvim VIM REFERENCE MANUAL by Bram Moolenaar @@ -8,12 +8,7 @@ Undo and redo *undo-redo* The basics are explained in section |02.5| of the user manual. -1. Undo and redo commands |undo-commands| -2. Two ways of undo |undo-two-ways| -3. Undo blocks |undo-blocks| -4. Undo branches |undo-branches| -5. Undo persistence |undo-persistence| -6. Remarks about undo |undo-remarks| + Type <M-]> to see the table of contents. ============================================================================== 1. Undo and redo commands *undo-commands* diff --git a/runtime/doc/usr_01.txt b/runtime/doc/usr_01.txt index 2fa15331df..f3a5728d72 100644 --- a/runtime/doc/usr_01.txt +++ b/runtime/doc/usr_01.txt @@ -1,4 +1,4 @@ -*usr_01.txt* For Vim version 7.4. Last change: 2010 Nov 03 +*usr_01.txt* Nvim VIM USER MANUAL - by Bram Moolenaar diff --git a/runtime/doc/usr_02.txt b/runtime/doc/usr_02.txt index c10643940d..b738cdc48b 100644 --- a/runtime/doc/usr_02.txt +++ b/runtime/doc/usr_02.txt @@ -1,4 +1,4 @@ -*usr_02.txt* For Vim version 7.4. Last change: 2016 Jan 16 +*usr_02.txt* Nvim VIM USER MANUAL - by Bram Moolenaar @@ -578,7 +578,7 @@ Summary: *help-summary* > register: > :help quote: -13) Vim Script (VimL) is available at > +13) Vim Script is available at > :help eval.txt < Certain aspects of the language are available at :h expr-X where "X" is a single letter. E.g. > @@ -588,10 +588,10 @@ Summary: *help-summary* > Also important is > :help function-list < to find a short description of all functions available. Help topics for - VimL functions always include the "()", so: > + Vim script functions always include the "()", so: > :help append() -< talks about the append VimL function rather than how to append text in the - current buffer. +< talks about the append Vim script function rather than how to append text + in the current buffer. 14) Mappings are talked about in the help page :h |map.txt|. Use > :help mapmode-i diff --git a/runtime/doc/usr_03.txt b/runtime/doc/usr_03.txt index 943d7b528c..5a7f0cb0e5 100644 --- a/runtime/doc/usr_03.txt +++ b/runtime/doc/usr_03.txt @@ -1,4 +1,4 @@ -*usr_03.txt* For Vim version 7.4. Last change: 2016 Jan 05 +*usr_03.txt* Nvim VIM USER MANUAL - by Bram Moolenaar @@ -182,7 +182,7 @@ the following: This tells you that you might want to fix something on line 33. So how do you find line 33? One way is to do "9999k" to go to the top of the file and "32j" -to go down thirty two lines. It is not a good way, but it works. A much +to go down thirty-two lines. It is not a good way, but it works. A much better way of doing things is to use the "G" command. With a count, this command positions you at the given line number. For example, "33G" puts you on line 33. (For a better way of going through a compiler's error list, see diff --git a/runtime/doc/usr_04.txt b/runtime/doc/usr_04.txt index 59ba0b3e73..e02a50e494 100644 --- a/runtime/doc/usr_04.txt +++ b/runtime/doc/usr_04.txt @@ -1,4 +1,4 @@ -*usr_04.txt* For Vim version 7.4. Last change: 2014 Aug 29 +*usr_04.txt* Nvim VIM USER MANUAL - by Bram Moolenaar diff --git a/runtime/doc/usr_05.txt b/runtime/doc/usr_05.txt index f920fd4591..cb7bf94ddc 100644 --- a/runtime/doc/usr_05.txt +++ b/runtime/doc/usr_05.txt @@ -1,4 +1,4 @@ -*usr_05.txt* For Vim version 7.4. Last change: 2016 Mar 28 +*usr_05.txt* Nvim VIM USER MANUAL - by Bram Moolenaar @@ -140,15 +140,13 @@ quite complicated things. Still, it is just a sequence of commands that are executed like you typed them. > - if &t_Co > 2 || has("gui_running") - syntax on - set hlsearch - endif - -This switches on syntax highlighting, but only if colors are available. And -the 'hlsearch' option tells Vim to highlight matches with the last used search -pattern. The "if" command is very useful to set options only when some -condition is met. More about that in |usr_41.txt|. + syntax on + set hlsearch + +This switches on syntax highlighting. And the 'hlsearch' option tells Vim to +highlight matches with the last used search pattern. The "if" command is very +useful to set options only when some condition is met. More about that in +|usr_41.txt|. *vimrc-filetype* > filetype plugin indent on diff --git a/runtime/doc/usr_06.txt b/runtime/doc/usr_06.txt index b4b495ff9f..48f672be78 100644 --- a/runtime/doc/usr_06.txt +++ b/runtime/doc/usr_06.txt @@ -1,4 +1,4 @@ -*usr_06.txt* For Vim version 7.4. Last change: 2009 Oct 28 +*usr_06.txt* Nvim VIM USER MANUAL - by Bram Moolenaar @@ -55,8 +55,7 @@ There can be a number of reasons why you don't see colors: - Your terminal does not support colors. Vim will use bold, italic and underlined text, but this doesn't look very nice. You probably will want to try to get a terminal with - colors. For Unix, I recommend the xterm from the XFree86 project: - |xfree-xterm|. + colors. - Your terminal does support colors, but Vim doesn't know this. Make sure your $TERM setting is correct. For example, when using an @@ -68,9 +67,7 @@ There can be a number of reasons why you don't see colors: TERM=xterm-color; export TERM -< The terminal name must match the terminal you are using. If it - still doesn't work, have a look at |xterm-color|, which shows a few - ways to make Vim display colors (not only for an xterm). +< The terminal name must match the terminal you are using. - The file type is not recognized. Vim doesn't know all file types, and sometimes it's near to impossible diff --git a/runtime/doc/usr_07.txt b/runtime/doc/usr_07.txt index 50e4781cd7..3fc600d977 100644 --- a/runtime/doc/usr_07.txt +++ b/runtime/doc/usr_07.txt @@ -1,4 +1,4 @@ -*usr_07.txt* For Vim version 7.4. Last change: 2006 Apr 24 +*usr_07.txt* Nvim VIM USER MANUAL - by Bram Moolenaar diff --git a/runtime/doc/usr_08.txt b/runtime/doc/usr_08.txt index d1f3fbd49d..575921fc4f 100644 --- a/runtime/doc/usr_08.txt +++ b/runtime/doc/usr_08.txt @@ -1,4 +1,4 @@ -*usr_08.txt* For Vim version 7.4. Last change: 2014 Jul 06 +*usr_08.txt* Nvim VIM USER MANUAL - by Bram Moolenaar diff --git a/runtime/doc/usr_09.txt b/runtime/doc/usr_09.txt index d68d734b8f..1ff3d93329 100644 --- a/runtime/doc/usr_09.txt +++ b/runtime/doc/usr_09.txt @@ -1,4 +1,4 @@ -*usr_09.txt* For Vim version 7.4. Last change: 2006 Apr 24 +*usr_09.txt* Nvim VIM USER MANUAL - by Bram Moolenaar diff --git a/runtime/doc/usr_10.txt b/runtime/doc/usr_10.txt index bf7ba18222..044cb1582b 100644 --- a/runtime/doc/usr_10.txt +++ b/runtime/doc/usr_10.txt @@ -1,4 +1,4 @@ -*usr_10.txt* For Vim version 7.4. Last change: 2006 Nov 05 +*usr_10.txt* Nvim VIM USER MANUAL - by Bram Moolenaar diff --git a/runtime/doc/usr_11.txt b/runtime/doc/usr_11.txt index 1a72c300d7..42009519df 100644 --- a/runtime/doc/usr_11.txt +++ b/runtime/doc/usr_11.txt @@ -1,4 +1,4 @@ -*usr_11.txt* For Vim version 7.4. Last change: 2010 Jul 20 +*usr_11.txt* Nvim VIM USER MANUAL - by Bram Moolenaar diff --git a/runtime/doc/usr_12.txt b/runtime/doc/usr_12.txt index f64a230576..9078f4748a 100644 --- a/runtime/doc/usr_12.txt +++ b/runtime/doc/usr_12.txt @@ -1,4 +1,4 @@ -*usr_12.txt* For Vim version 7.4. Last change: 2007 May 11 +*usr_12.txt* Nvim VIM USER MANUAL - by Bram Moolenaar diff --git a/runtime/doc/usr_20.txt b/runtime/doc/usr_20.txt index 5f0a660187..3b8eeae175 100644 --- a/runtime/doc/usr_20.txt +++ b/runtime/doc/usr_20.txt @@ -1,4 +1,4 @@ -*usr_20.txt* For Vim version 7.4. Last change: 2006 Apr 24 +*usr_20.txt* Nvim VIM USER MANUAL - by Bram Moolenaar diff --git a/runtime/doc/usr_21.txt b/runtime/doc/usr_21.txt index f99c3263d0..cfb8c90027 100644 --- a/runtime/doc/usr_21.txt +++ b/runtime/doc/usr_21.txt @@ -1,4 +1,4 @@ -*usr_21.txt* For Vim version 7.4. Last change: 2012 Nov 02 +*usr_21.txt* Nvim VIM USER MANUAL - by Bram Moolenaar diff --git a/runtime/doc/usr_22.txt b/runtime/doc/usr_22.txt index cff8e9db1e..255211f668 100644 --- a/runtime/doc/usr_22.txt +++ b/runtime/doc/usr_22.txt @@ -1,4 +1,4 @@ -*usr_22.txt* For Vim version 7.4. Last change: 2012 Nov 15 +*usr_22.txt* Nvim VIM USER MANUAL - by Bram Moolenaar @@ -93,7 +93,7 @@ browser. This is what you get: > o................Browsing with a Horizontal Split...........|netrw-o| p................Use Preview Window.........................|netrw-p| P................Edit in Previous Window....................|netrw-p| - q................Listing Bookmarks and History..............|netrw-q| + q................Listing Bookmarks and History..............|netrw-qb| r................Reversing Sorting Order....................|netrw-r| < (etc) diff --git a/runtime/doc/usr_23.txt b/runtime/doc/usr_23.txt index 4761203512..cb776d2b5c 100644 --- a/runtime/doc/usr_23.txt +++ b/runtime/doc/usr_23.txt @@ -1,4 +1,4 @@ -*usr_23.txt* For Vim version 7.4. Last change: 2006 Apr 24 +*usr_23.txt* Nvim VIM USER MANUAL - by Bram Moolenaar diff --git a/runtime/doc/usr_24.txt b/runtime/doc/usr_24.txt index ba9d083fe0..b74ed879e0 100644 --- a/runtime/doc/usr_24.txt +++ b/runtime/doc/usr_24.txt @@ -1,4 +1,4 @@ -*usr_24.txt* For Vim version 7.4. Last change: 2006 Jul 23 +*usr_24.txt* Nvim VIM USER MANUAL - by Bram Moolenaar diff --git a/runtime/doc/usr_25.txt b/runtime/doc/usr_25.txt index 24420353dd..ae3d3c4422 100644 --- a/runtime/doc/usr_25.txt +++ b/runtime/doc/usr_25.txt @@ -1,4 +1,4 @@ -*usr_25.txt* For Vim version 7.4. Last change: 2016 Mar 28 +*usr_25.txt* Nvim VIM USER MANUAL - by Bram Moolenaar diff --git a/runtime/doc/usr_26.txt b/runtime/doc/usr_26.txt index e381a1df12..7b0b940da2 100644 --- a/runtime/doc/usr_26.txt +++ b/runtime/doc/usr_26.txt @@ -1,4 +1,4 @@ -*usr_26.txt* For Vim version 7.4. Last change: 2006 Apr 24 +*usr_26.txt* Nvim VIM USER MANUAL - by Bram Moolenaar diff --git a/runtime/doc/usr_27.txt b/runtime/doc/usr_27.txt index d837610698..afea67bd0b 100644 --- a/runtime/doc/usr_27.txt +++ b/runtime/doc/usr_27.txt @@ -1,4 +1,4 @@ -*usr_27.txt* For Vim version 7.4. Last change: 2010 Mar 28 +*usr_27.txt* Nvim VIM USER MANUAL - by Bram Moolenaar diff --git a/runtime/doc/usr_28.txt b/runtime/doc/usr_28.txt index d29b384437..24e995d9ab 100644 --- a/runtime/doc/usr_28.txt +++ b/runtime/doc/usr_28.txt @@ -1,4 +1,4 @@ -*usr_28.txt* For Vim version 7.4. Last change: 2008 Jun 14 +*usr_28.txt* Nvim VIM USER MANUAL - by Bram Moolenaar diff --git a/runtime/doc/usr_29.txt b/runtime/doc/usr_29.txt index 9eb66ce83c..b0cb9d7e88 100644 --- a/runtime/doc/usr_29.txt +++ b/runtime/doc/usr_29.txt @@ -1,4 +1,4 @@ -*usr_29.txt* For Vim version 7.4. Last change: 2016 Feb 27 +*usr_29.txt* Nvim VIM USER MANUAL - by Bram Moolenaar diff --git a/runtime/doc/usr_30.txt b/runtime/doc/usr_30.txt index dbac440ecc..786f2d1800 100644 --- a/runtime/doc/usr_30.txt +++ b/runtime/doc/usr_30.txt @@ -1,4 +1,4 @@ -*usr_30.txt* For Vim version 7.4. Last change: 2007 Nov 10 +*usr_30.txt* Nvim VIM USER MANUAL - by Bram Moolenaar diff --git a/runtime/doc/usr_31.txt b/runtime/doc/usr_31.txt index 7bcf4d428a..2354e27b42 100644 --- a/runtime/doc/usr_31.txt +++ b/runtime/doc/usr_31.txt @@ -1,4 +1,4 @@ -*usr_31.txt* For Vim version 7.4. Last change: 2007 May 08 +*usr_31.txt* Nvim VIM USER MANUAL - by Bram Moolenaar diff --git a/runtime/doc/usr_32.txt b/runtime/doc/usr_32.txt index fd58f2d517..fca802872d 100644 --- a/runtime/doc/usr_32.txt +++ b/runtime/doc/usr_32.txt @@ -1,4 +1,4 @@ -*usr_32.txt* For Vim version 7.4. Last change: 2010 Jul 20 +*usr_32.txt* Nvim VIM USER MANUAL - by Bram Moolenaar diff --git a/runtime/doc/usr_40.txt b/runtime/doc/usr_40.txt index d3cc792c59..4092af703e 100644 --- a/runtime/doc/usr_40.txt +++ b/runtime/doc/usr_40.txt @@ -1,4 +1,4 @@ -*usr_40.txt* For Vim version 7.4. Last change: 2013 Aug 05 +*usr_40.txt* Nvim VIM USER MANUAL - by Bram Moolenaar diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt index b0e5386224..acb6fd0fa4 100644 --- a/runtime/doc/usr_41.txt +++ b/runtime/doc/usr_41.txt @@ -1,4 +1,4 @@ -*usr_41.txt* For Vim version 7.4. Last change: 2016 Aug 07 +*usr_41.txt* Nvim VIM USER MANUAL - by Bram Moolenaar @@ -611,6 +611,7 @@ String manipulation: *string-functions* byteidxcomp() like byteidx() but count composing characters repeat() repeat a string multiple times eval() evaluate a string expression + execute() execute an Ex command and get the output List manipulation: *list-functions* get() get an item without error for wrong index @@ -944,12 +945,15 @@ Various: *various-functions* shiftwidth() effective value of 'shiftwidth' + wordcount() get byte/word/char count of buffer + taglist() get list of matching tags tagfiles() get a list of tags files + luaeval() evaluate Lua expression py3eval() evaluate Python expression (|+python3|) pyeval() evaluate Python expression (|+python|) - wordcount() get byte/word/char count of buffer + pyxeval() evaluate |python_x| expression ============================================================================== *41.7* Defining a function diff --git a/runtime/doc/usr_42.txt b/runtime/doc/usr_42.txt index c8eac5f062..ad04555f8c 100644 --- a/runtime/doc/usr_42.txt +++ b/runtime/doc/usr_42.txt @@ -1,4 +1,4 @@ -*usr_42.txt* For Vim version 7.4. Last change: 2008 May 05 +*usr_42.txt* Nvim VIM USER MANUAL - by Bram Moolenaar diff --git a/runtime/doc/usr_43.txt b/runtime/doc/usr_43.txt index bab446af3c..765a525692 100644 --- a/runtime/doc/usr_43.txt +++ b/runtime/doc/usr_43.txt @@ -1,4 +1,4 @@ -*usr_43.txt* For Vim version 7.4. Last change: 2015 Oct 23 +*usr_43.txt* Nvim VIM USER MANUAL - by Bram Moolenaar diff --git a/runtime/doc/usr_44.txt b/runtime/doc/usr_44.txt index a91f92ff4e..fcd6b71219 100644 --- a/runtime/doc/usr_44.txt +++ b/runtime/doc/usr_44.txt @@ -1,4 +1,4 @@ -*usr_44.txt* For Vim version 7.4. Last change: 2008 Dec 28 +*usr_44.txt* Nvim VIM USER MANUAL - by Bram Moolenaar diff --git a/runtime/doc/usr_45.txt b/runtime/doc/usr_45.txt index 34b607cbd2..9bbbe82113 100644 --- a/runtime/doc/usr_45.txt +++ b/runtime/doc/usr_45.txt @@ -1,4 +1,4 @@ -*usr_45.txt* For Vim version 7.4. Last change: 2008 Nov 15 +*usr_45.txt* Nvim VIM USER MANUAL - by Bram Moolenaar diff --git a/runtime/doc/usr_toc.txt b/runtime/doc/usr_toc.txt index e021b806e3..ed14d78d22 100644 --- a/runtime/doc/usr_toc.txt +++ b/runtime/doc/usr_toc.txt @@ -1,4 +1,4 @@ -*usr_toc.txt* For Vim version 7.4. Last change: 2016 Mar 25 +*usr_toc.txt* Nvim VIM USER MANUAL - by Bram Moolenaar @@ -48,9 +48,8 @@ Tuning Vim Reference manual |reference_toc| More detailed information for all commands -The user manual is available as a single, ready to print HTML and PDF file -here: - http://vimdoc.sf.net +The user manual is online: + https://neovim.io/doc/user ============================================================================== Getting Started ~ diff --git a/runtime/doc/various.txt b/runtime/doc/various.txt index 3c1472446d..223a0135b2 100644 --- a/runtime/doc/various.txt +++ b/runtime/doc/various.txt @@ -1,4 +1,4 @@ -*various.txt* For Vim version 7.4. Last change: 2016 Mar 20 +*various.txt* Nvim VIM REFERENCE MANUAL by Bram Moolenaar @@ -6,8 +6,7 @@ Various commands *various* -1. Various commands |various-cmds| -2. Using Vim like less or more |less| + Type <M-]> to see the table of contents. ============================================================================== 1. Various commands *various-cmds* @@ -85,6 +84,8 @@ g8 Print the hex values of the bytes used in the on paper see |:hardcopy|. In the GUI you can use the File.Print menu entry. See |ex-flags| for [flags]. + The |:filter| command can be used to only show lines + matching a pattern. :[range]p[rint] {count} [flags] Print {count} lines, starting with [range] (default @@ -207,24 +208,21 @@ g8 Print the hex values of the bytes used in the :sh[ell] Removed. |vim-differences| {Nvim} *:terminal* *:te* -:te[rminal][!] {cmd} Spawns {cmd} using the current value of 'shell' and - 'shellcmdflag' in a new terminal buffer. This is - equivalent to: > - +:te[rminal][!] [{cmd}] Execute {cmd} with 'shell' in a new |terminal| buffer. + Equivalent to: > :enew :call termopen('{cmd}') - :startinsert < - If no {cmd} is given, 'shellcmdflag' will not be sent - to |termopen()|. + See |termopen()|. + + Without {cmd}, start an interactive shell. - Like |:enew|, it will fail if the current buffer is - modified, but can be forced with "!". See |termopen()| - and |terminal-emulator|. + Creating the terminal buffer fails when changes have been + made to the current buffer, unless 'hidden' is set. - To switch to terminal mode automatically: -> + To enter |Terminal-mode| automatically: > autocmd BufEnter term://* startinsert + autocmd BufLeave term://* stopinsert < *:!cmd* *:!* *E34* :!{cmd} Execute {cmd} with 'shell'. See also |:terminal|. @@ -277,6 +275,21 @@ g8 Print the hex values of the bytes used in the < The screen is not redrawn then, thus you have to use CTRL-L or ":redraw!" if the command did display something. + *:!start* +:!start {cmd} (Windows only). Special-case of |:!| which works + asynchronously, for running a program that does not + affect the files you are editing. + Optional arguments (can only use one at a time): + /min window will be minimized + /b no console window will be opened + Note: If the process requires input, /b will get an + EOF error because its input stream (stdin) would be + redirected to \\.\NUL (stdout and stderr too). + + Programs begun with :!start do not get passed Vim's + open file handles, which means they do not have to be + closed before Vim. To avoid this special treatment, + use ":! start". *:!!* :!! Repeat last ":!{cmd}". @@ -318,7 +331,6 @@ N *+comments* |'comments'| support B *+conceal* "conceal" support, see |conceal| |:syn-conceal| etc. B *+cscope* |cscope| support m *+cursorbind* |'cursorbind'| support -m *+cursorshape* |termcap-cursor-shape| support m *+debug* Compiled for debugging. N *+dialog_gui* Support for |:confirm| with GUI dialog. N *+dialog_con* Support for |:confirm| with console dialog. @@ -338,6 +350,7 @@ N *+gettext* message translations |multi-lang| N *+insert_expand* |insert_expand| Insert mode completion N *+jumplist* |jumplist| B *+keymap* |'keymap'| +N *+lambda* |lambda| and |closure| B *+langmap* |'langmap'| N *+libcall* |libcall()| N *+linebreak* |'linebreak'|, |'breakat'| and |'showbreak'| @@ -353,6 +366,7 @@ N *+mouseshape* |'mouseshape'| N *+multi_byte* 16 and 32 bit characters |multibyte| *+multi_byte_ime* Win32 input method for multibyte chars |multibyte-ime| N *+multi_lang* non-English language support |multi-lang| + *+num64* 64-bit Number support |Number| N *+path_extra* Up/downwards search in 'path' and 'tags' N *+persistent_undo* Persistent undo |undo-persistence| *+postscript* |:hardcopy| writes a PostScript file @@ -373,14 +387,12 @@ N *+statusline* Options 'statusline', 'rulerformat' and special formats of 'titlestring' and 'iconstring' N *+syntax* Syntax highlighting |syntax| N *+tablineat* 'tabline' option recognizing %@Func@ items. -N *+tag_binary* binary searching in tags file |tag-binary-search| +T *+tag_binary* binary searching in tags file |tag-binary-search| N *+tag_old_static* old method for static tags |tag-old-static| m *+tag_any_white* any white space allowed in tags file |tag-any-white| B *+termguicolors* 24-bit color in xterm-compatible terminals support - *+terminfo* uses |terminfo| instead of termcap N *+termresponse* support for |t_RV| and |v:termresponse| N *+textobjects* |text-objects| selection - *+tgetent* non-Unix only: able to use external termcap N *+timers* the |timer_start()| function N *+title* Setting the window 'title' and 'icon' N *+toolbar* |gui-toolbar| @@ -416,9 +428,12 @@ m *+xpm_w32* Win32 GUI only: pixmap support |w32-xpm-support| shown on the screen. When [!] is included, an existing file is overwritten. When [!] is omitted, and {file} exists, this command fails. + Only one ":redir" can be active at a time. Calls to ":redir" will close any active redirection before - starting redirection to the new target. + starting redirection to the new target. For recursive + use check out |execute()|. + To stop the messages and commands from being echoed to the screen, put the commands in a function and call it with ":silent call Function()". @@ -456,12 +471,37 @@ m *+xpm_w32* Win32 GUI only: pixmap support |w32-xpm-support| redirection starts, if the variable is removed or locked or the variable type is changed, then further command output messages will cause errors. + To get the output of one command the |execute()| + function can be used. :redi[r] =>> {var} Append messages to an existing variable. Only string variables can be used. :redi[r] END End redirecting messages. + *:filt* *:filter* +:filt[er][!] {pat} {command} +:filt[er][!] /{pat}/ {command} + Restrict the output of {command} to lines matching + with {pat}. For example, to list only xml files: > + :filter /\.xml$/ oldfiles +< If the [!] is given, restrict the output of {command} + to lines that do NOT match {pat}. + + {pat} is a Vim search pattern. Instead of enclosing + it in / any non-ID character (see |'isident'|) can be + used, so long as it does not appear in {pat}. Without + the enclosing character the pattern cannot include the + bar character. + + The pattern is matched against the relevant part of + the output, not necessarily the whole line. Only some + commands support filtering, try it out to check if it + works. + + Only normal messages are filtered, error messages are + not. + *:sil* *:silent* *:silent!* :sil[ent][!] {command} Execute {command} silently. Normal messages will not be given or added to the message history. diff --git a/runtime/doc/vi_diff.txt b/runtime/doc/vi_diff.txt index 54ef8fecb2..b8bfcaa586 100644 --- a/runtime/doc/vi_diff.txt +++ b/runtime/doc/vi_diff.txt @@ -1,4 +1,4 @@ -*vi_diff.txt* For Vim version 7.4. Last change: 2016 Feb 12 +*vi_diff.txt* Nvim VIM REFERENCE MANUAL by Bram Moolenaar @@ -6,8 +6,7 @@ Differences between Vim and Vi *vi-differences* -1. Limits |limits| -2. The most interesting additions |vim-additions| + Type <M-]> to see the table of contents. ============================================================================== 1. Limits *limits* @@ -60,7 +59,7 @@ Support for different systems. - Windows (XP SP 2 or greater) - OS X -Multi level undo. |undo| +Multi level persistent undo. |undo| 'u' goes backward in time, 'CTRL-R' goes forward again. Set option 'undolevels' to the number of changes to be remembered (default 1000). Set 'undolevels' to 0 for a Vi-compatible one level undo. Set it to @@ -71,6 +70,9 @@ Multi level undo. |undo| create a branch in the undo tree. This means you can go back to any state of the text, there is no risk of a change causing text to be lost forever. |undo-tree| + The undo information is stored in a file when the 'undofile' option is + set. This means you can exit Vim, start Vim on a previously edited + file and undo changes that were made before exiting Vim. Graphical User Interface (GUI). |gui| Included support for GUI: menu's, mouse, scrollbars, etc. You can @@ -124,6 +126,13 @@ Plugins. |add-plugin| right directory. That's an easy way to start using Vim scripts written by others. Plugins can be for all kind of files, or specifically for a filetype. + Packages make this even easier. |packages| + +Asynchronous communication and timers. |job-control| |timer| + Vim can exchange messages with other processes in the background. + Vim can start a job, communicate with it and stop it. |job-control| + Timers can fire once or repeatedly and invoke a function to do any + work. |timer| Repeat a series of commands. |q| "q{c}" starts recording typed characters into named register {c}. diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt index 7c9d383a01..eb3c4d50ce 100644 --- a/runtime/doc/vim_diff.txt +++ b/runtime/doc/vim_diff.txt @@ -1,4 +1,4 @@ -*vim_diff.txt* For Nvim. {Nvim} +*vim_diff.txt* Nvim NVIM REFERENCE MANUAL @@ -6,17 +6,10 @@ Differences between Nvim and Vim *vim-differences* -Throughout the help files, differences between Nvim and Vim are indicated via -the "{Nvim}" tag. This document is a complete and centralized list of all -these differences. - -1. Configuration |nvim-configuration| -2. Defaults |nvim-defaults| -3. New features |nvim-features| -4. Changed features |nvim-features-changed| -5. Missing legacy features |nvim-features-missing| -6. Removed features |nvim-features-removed| +Nvim differs from Vim in many ways, big and small. This document is +a complete and centralized reference of those differences. + Type <M-]> to see the table of contents. ============================================================================== 1. Configuration *nvim-configuration* @@ -37,6 +30,7 @@ these differences. - 'autoread' is set by default - 'backspace' defaults to "indent,eol,start" - 'backupdir' defaults to .,~/.local/share/nvim/backup (|xdg|) +- 'belloff' defaults to "all" - 'complete' doesn't include "i" - 'directory' defaults to ~/.local/share/nvim/swap// (|xdg|), auto-created - 'display' defaults to "lastline" @@ -44,13 +38,15 @@ these differences. - 'history' defaults to 10000 (the maximum) - 'hlsearch' is set by default - 'incsearch' is set by default -- 'langnoremap' is set by default +- 'langnoremap' is enabled by default +- 'langremap' is disabled by default - 'laststatus' defaults to 2 (statusline is always shown) - 'listchars' defaults to "tab:> ,trail:-,nbsp:+" -- 'mouse' defaults to "a" - 'nocompatible' is always set - 'nrformats' defaults to "bin,hex" +- 'ruler' is set by default - 'sessionoptions' doesn't include "options" +- 'showcmd' is set by default - 'smarttab' is set by default - 'tabpagemax' defaults to 50 - 'tags' defaults to "./tags;,tags" @@ -62,10 +58,9 @@ these differences. ============================================================================== 3. New Features *nvim-features* - MAJOR COMPONENTS ~ -Embedded terminal emulator |terminal-emulator| +Embedded terminal emulator |terminal| RPC API |RPC| Shared data |shada| XDG base directories |xdg| @@ -74,30 +69,38 @@ Remote plugins |remote-plugin| Python plugins |provider-python| Clipboard integration |provider-clipboard| - USER EXPERIENCE ~ -Working intuitively and consistently is a major goal of Nvim. Examples: +Working intuitively and consistently is a major goal of Nvim. -- Nvim does not have `-X`, a platform-specific option "sometimes" available in - Vim (with potential surprises: http://stackoverflow.com/q/14635295). Nvim - avoids features that cannot be provided on all platforms--instead that is - delegated to external plugins/extensions. + *feature-compile* +- Nvim always includes ALL features, in contrast to Vim (which ships with + various combinations of 100+ optional features). Think of it as a leaner + version of Vim's "HUGE" build. This reduces surface area for bugs, and + removes a common source of confusion and friction for users. -- Test-only globals and functions such as test_autochdir(), test_settime(), - etc., are not exposed (because they don't exist). +- Nvim avoids features that cannot be provided on all platforms; instead that + is delegated to external plugins/extensions. E.g. the `-X` platform-specific + option is "sometimes" available in Vim (with potential surprises: + http://stackoverflow.com/q/14635295). + +- Vim's internal test functions (test_autochdir(), test_settime(), etc.) are + not exposed (nor implemented); instead Nvim has a robust API. ARCHITECTURE ~ External plugins run in separate processes. |remote-plugin| This improves -stability and allows those plugins to perform tasks without blocking the -editor. Even "legacy" Python and Ruby plugins which use the old Vim interfaces -(|if_py| and |if_ruby|) run out-of-process. +stability and allows those plugins to work without blocking the editor. Even +"legacy" Python and Ruby plugins which use the old Vim interfaces (|if_py| and +|if_ruby|) run out-of-process. +Platform and I/O facilities are built upon libuv. Nvim benefits from libuv +features and bug fixes, and other projects benefit from improvements to libuv +by Nvim developers. FEATURES ~ -|bracketed-paste-mode| is built-in and enabled by default. +"Outline": Type <M-]> in |:Man| and |:help| pages to see a document outline. |META| (ALT) chords are recognized, even in the terminal. Any |<M-| mapping will work. Some examples: <M-1>, <M-2>, <M-BS>, <M-Del>, <M-Ins>, <M-/>, @@ -109,12 +112,18 @@ Some `CTRL-SHIFT-...` key chords are distinguished from `CTRL-...` variants <C-Tab>, <C-S-Tab>, <C-BS>, <C-S-BS>, <C-Enter>, <C-S-Enter> Options: - 'inccommand' shows results while typing a |:substitute| command + 'cpoptions' flags: |cpo-_| + 'guicursor' works in the terminal + 'inccommand' shows interactive results for |:substitute|-like commands + 'scrollback' 'statusline' supports unlimited alignment sections 'tabline' %@Func@foo%X can call any function on mouse-click + 'winhighlight' window-local highlights Variables: |v:event| + |v:exiting| + |v:progpath| is always absolute ("full") |v:windowid| is always available (for use by external UIs) Commands: @@ -125,10 +134,11 @@ Commands: Functions: |dictwatcheradd()| notifies a callback whenever a |Dict| is modified |dictwatcherdel()| - |execute()| works with |:redir| + |menu_get()| |msgpackdump()|, |msgpackparse()| provide msgpack de/serialization Events: + |DirChanged| |TabNewEntered| |TermClose| |TermOpen| @@ -139,6 +149,15 @@ Highlight groups: |hl-Substitute| |hl-TermCursor| |hl-TermCursorNC| + |hl-Whitespace| highlights 'listchars' whitespace + +UI: + *E5408* *E5409* *g:Nvim_color_expr* *g:Nvim_color_cmdline* + Command-line coloring is supported. Only |input()| and |inputdialog()| may + be colored. For testing purposes expressions (e.g. |i_CTRL-R_=|) and regular + command-line (|:|) are colored by callbacks defined in `g:Nvim_color_expr` + and `g:Nvim_color_cmdline` respectively (these callbacks are for testing + only, and will be removed in a future version). ============================================================================== 4. Changed features *nvim-features-changed* @@ -153,11 +172,22 @@ are always available and may be used simultaneously in separate plugins. The `neovim` pip package must be installed to use Python plugins in Nvim (see |provider-python|). +Because of general |256-color| usage whereever possible, Nvim will even use +256-colour capability on Linux virtual terminals. Vim uses only 8 colours +plus bright foreground on Linux VTs. + +Vim combines what is in its |builtin-terms| with what it reads from termcap, +and has a |ttybuiltin| setting to control how that combination works. Nvim +uses either one or the other of an external |terminfo| entry or the built-in +one. It does not attempt to mix data from the two. + |:!| does not support "interactive" commands. Use |:terminal| instead. (GUI Vim has a similar limitation, see ":help gui-pty" in Vim.) |system()| does not support writing/reading "backgrounded" commands. |E5677| +|:redir| nested in |execute()| works. + Nvim may throttle (skip) messages from shell commands (|:!|, |:grep|, |:make|) if there is too much output. No data is lost, this only affects display and makes things faster. |:terminal| output is never throttled. @@ -213,41 +243,58 @@ Additional differences: - |shada-c| has no effect. - |shada-s| now limits size of every item and not just registers. -- When reading ShaDa files items are merged according to the timestamp. - |shada-merging| - 'viminfo' option got renamed to 'shada'. Old option is kept as an alias for compatibility reasons. - |:wviminfo| was renamed to |:wshada|, |:rviminfo| to |:rshada|. Old commands are still kept. -- 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| - ShaDa file format was designed with forward and backward compatibility in mind. |shada-compatibility| - Some errors make ShaDa code keep temporary file in-place for user to decide what to do with it. Vim deletes temporary file in these cases. |shada-error-handling| -- Vim keeps no timestamps at all, neither in viminfo file nor in the instance - itself. - ShaDa file keeps search direction (|v:searchforward|), viminfo does not. +|printf()| returns something meaningful when used with `%p` argument: in Vim +it used to return useless address of the string (strings are copied to the +newly allocated memory all over the place) and fail on types which cannot be +coerced to strings. See |id()| for more details, currently it uses +`printf("%p", {expr})` internally. + +|c_CTRL-R| pasting a non-special register into |cmdline| omits the last <CR>. + +Lua interface (|if_lua.txt|): + +- `:lua print("a\0b")` will print `a^@b`, like with `:echomsg "a\nb"` . In Vim + that prints `a` and `b` on separate lines, exactly like + `:lua print("a\nb")` . +- `:lua error('TEST')` will print โTESTโ as the error in Vim and โE5105: Error + while calling lua chunk: [string "<VimL compiled string>"]:1: TESTโ in + Neovim. +- Lua has direct access to Nvim |API| via `vim.api`. +- Lua package.path and package.cpath are automatically updated according to + 'runtimepath': |lua-require|. + +|input()| and |inputdialog()| support for each otherโs features (return on +cancel and completion respectively) via dictionary argument (replaces all +other arguments if used). + +|input()| and |inputdialog()| support user-defined cmdline highlighting. + ============================================================================== 5. Missing legacy features *nvim-features-missing* - *if_lua* *if_perl* *if_mzscheme* *if_tcl* -These legacy Vim features may be implemented in the future, but they are not -planned for the current milestone. +Some legacy Vim features are not implemented: - |if_py|: vim.bindeval() and vim.Function() are not supported -- |if_lua| -- |if_perl| -- |if_mzscheme| -- |if_tcl| +- |if_lua|: the `vim` object is missing most legacy methods +- *if_perl* +- *if_mzscheme* +- *if_tcl* ============================================================================== 6. Removed features *nvim-features-removed* -These features are in Vim, but have been intentionally removed from Nvim. +These Vim features were intentionally removed from Nvim. *'cp'* *'nocompatible'* *'nocp'* *'compatible'* Nvim is always "non-compatible" with Vi. @@ -259,6 +306,27 @@ Ed-compatible mode: ":set noedcompatible" is ignored ":set edcompatible" is an error + *t_xx* *:set-termcap* *termcap-options* *t_AB* *t_Sb* *t_vb* *t_SI* +Nvim does not have special `t_XX` options nor <t_XX> keycodes to configure +terminal capabilities. Instead Nvim treats the terminal as any other UI. For +example, 'guicursor' sets the terminal cursor style if possible. + + *'term'* *E529* *E530* *E531* +The 'term' option has a fixed value, present only for script compatibility and +intentionally not the same as any known terminal type name. It should be a +rare case in Nvim where one needs |term-dependent-settings|. + + *termcap* +Nvim never uses the termcap database, only |terminfo| and |builtin-terms|. + + *xterm-8bit* *xterm-8-bit* +Xterm can be run in a mode where it uses true 8-bit CSI. Supporting this +requires autodetection of whether the terminal is in UTF-8 mode or non-UTF-8 +mode, as the 8-bit CSI character has to be written differently in each case. +Vim issues a "request version" sequence to the terminal at startup and looks +at how the terminal is sending CSI. Nvim does not issue such a sequence and +always uses 7-bit control sequences. + 'ttyfast': ":set ttyfast" is ignored ":set nottyfast" is an error @@ -271,9 +339,6 @@ MS-DOS support: 'bioskey' 'conskey' -Highlight groups: - |hl-VisualNOS| - Test functions: test_alloc_fail() test_autochdir() @@ -289,10 +354,12 @@ Test functions: Other options: 'antialias' - 'cpoptions' ("g", "w", "H", "*", "-", "j", and all POSIX flags were removed) + 'cpoptions' (g j k H w < * - and all POSIX flags were removed) 'encoding' ("utf-8" is always used) + 'esckeys' 'guioptions' "t" flag was removed *'guipty'* (Nvim uses pipes and PTYs consistently on all platforms.) + 'highlight' (the builtin |highlight-groups| cannot be changed) *'imactivatefunc'* *'imaf'* *'imactivatekey'* *'imak'* *'imstatusfunc'* *'imsf'* @@ -301,7 +368,6 @@ Other options: 'shelltype' *'shortname'* *'sn'* *'noshortname'* *'nosn'* *'swapsync'* *'sws'* - *'term'* *E529* *E530* *E531* *'termencoding'* *'tenc'* (Vim 7.4.852 also removed this for Windows) 'textauto' 'textmode' diff --git a/runtime/doc/visual.txt b/runtime/doc/visual.txt index 6810d50c11..cf804444e5 100644 --- a/runtime/doc/visual.txt +++ b/runtime/doc/visual.txt @@ -1,4 +1,4 @@ -*visual.txt* For Vim version 7.4. Last change: 2014 Mar 23 +*visual.txt* Nvim VIM REFERENCE MANUAL by Bram Moolenaar @@ -11,14 +11,7 @@ operator. It is the only way to select a block of text. This is introduced in section |04.4| of the user manual. -1. Using Visual mode |visual-use| -2. Starting and stopping Visual mode |visual-start| -3. Changing the Visual area |visual-change| -4. Operating on the Visual area |visual-operators| -5. Blockwise operators |blockwise-operators| -6. Repeating |visual-repeat| -7. Examples |visual-examples| -8. Select mode |Select-mode| + Type <M-]> to see the table of contents. ============================================================================== 1. Using Visual mode *visual-use* @@ -278,7 +271,7 @@ mode. For example, if you would like the "/" command not to extend the Visual area, but instead take the highlighted text and search for that: > :vmap / y/<C-R>"<CR> (In the <> notation |<>|, when typing it you should type it literally; you -need to remove the 'B' and '<' flags from 'cpoptions'.) +need to remove the 'B' flag from 'cpoptions'.) If you want to give a register name using the """ command, do this just before typing the operator character: "v{move-around}"xd". @@ -382,7 +375,7 @@ Here is an example, to replace the selected text with the output of "date": > :vmap _a <Esc>`>a<CR><Esc>`<i<CR><Esc>!!date<CR>kJJ (In the <> notation |<>|, when typing it you should type it literally; you -need to remove the 'B' and '<' flags from 'cpoptions') +need to remove the 'B' flag from 'cpoptions') What this does is: <Esc> stop Visual mode @@ -399,7 +392,7 @@ selected text: > :vmap X y/<C-R>"<CR> (In the <> notation |<>|, when typing it you should type it literally; you -need to remove the 'B' and '<' flags from 'cpoptions') +need to remove the 'B' flag from 'cpoptions') Note that special characters (like '.' and '*') will cause problems. diff --git a/runtime/doc/windows.txt b/runtime/doc/windows.txt index 5b94626e36..f5d5321a5e 100644 --- a/runtime/doc/windows.txt +++ b/runtime/doc/windows.txt @@ -1,4 +1,4 @@ -*windows.txt* For Vim version 7.4. Last change: 2016 Jun 10 +*windows.txt* Nvim VIM REFERENCE MANUAL by Bram Moolenaar @@ -13,18 +13,7 @@ differently when used in combination with more than one window. The basics are explained in chapter 7 and 8 of the user manual |usr_07.txt| |usr_08.txt|. -1. Introduction |windows-intro| -2. Starting Vim |windows-starting| -3. Opening and closing a window |opening-window| -4. Moving cursor to other windows |window-move-cursor| -5. Moving windows around |window-moving| -6. Window resizing |window-resize| -7. Argument and buffer list commands |buffer-list| -8. Do a command in all buffers or windows |list-repeat| -9. Tag or file name under the cursor |window-tag| -10. The preview window |preview-window| -11. Using hidden buffers |buffer-hidden| -12. Special kinds of buffers |special-buffers| + Type <M-]> to see the table of contents. ============================================================================== 1. Introduction *windows-intro* *window* @@ -69,7 +58,7 @@ places where a Normal mode command can't be used or is inconvenient. The main Vim window can hold several split windows. There are also tab pages |tab-page|, each of which can hold multiple windows. - + *window-ID* *winid* *windowid* Each window has a unique identifier called the window ID. This identifier will not change within a Vim session. The |win_getid()| and |win_id2tabwin()| functions can be used to convert between the window/tab number and the @@ -128,7 +117,7 @@ check if the 'highlight' option contains "si". In version 3.0, this meant to invert the status line. Now it should be "sr", reverse the status line, as "si" now stands for italic! If italic is not available on your terminal, the status line is inverted anyway; you will only see this problem on terminals -that have termcap codes for italics. +that have |terminfo| capabilities for italics. ============================================================================== 3. Opening and closing a window *opening-window* *E36* @@ -249,7 +238,7 @@ window will appear. far left and occupies the full height of the Vim window. Doesn't work for |:execute| and |:normal|. - *:botright* + *:bo* *:botright* :bo[tright] {cmd} Execute {cmd}. If it contains a command that splits a window, it will appear at the bottom and occupy the full width of the @@ -287,7 +276,7 @@ CTRL-W CTRL-Q *CTRL-W_CTRL-Q* :1quit " quit the first window :$quit " quit the last window :9quit " quit the last window - " if there are less than 9 windows opened + " if there are fewer than 9 windows opened :-quit " quit the previous window :+quit " quit the next window :+2quit " quit the second next window @@ -534,6 +523,9 @@ CTRL-W > Increase current window width by N (default 1). :vertical res[ize] [N] *:vertical-resize* *CTRL-W_bar* CTRL-W | Set current window width to N (default: widest possible). + *:mod* *:mode* +:mod[e] Detects the screen size and redraws the screen. + You can also resize a window by dragging a status line up or down with the mouse. Or by dragging a vertical separator line left or right. This only works if the version of Vim that is being used supports the mouse and the @@ -1026,6 +1018,10 @@ list of buffers. |unlisted-buffer| h+ hidden buffers which are modified a+ active buffers which are modified + When using |:filter| the pattern is matched against the + displayed buffer name, e.g.: > + filter /\.vim/ ls +< *: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 93886d5379..7d0f9cf779 100644 --- a/runtime/filetype.vim +++ b/runtime/filetype.vim @@ -1,7 +1,7 @@ " Vim support file to detect file types " " Maintainer: Bram Moolenaar <Bram@vim.org> -" Last Change: 2016 Jul 21 +" Last Change: 2017 Jan 06 " Listen very carefully, I will say this only once if exists("did_load_filetypes") @@ -305,7 +305,10 @@ au BufNewFile,BufRead *.bl setf blank au BufNewFile,BufRead */etc/blkid.tab,*/etc/blkid.tab.old setf xml " Bazel (http://bazel.io) -autocmd BufRead,BufNewFile *.bzl,BUILD,WORKSPACE setfiletype bzl +autocmd BufRead,BufNewFile *.bzl,WORKSPACE setfiletype bzl +if has("fname_case") + autocmd BufRead,BufNewFile BUILD setfiletype bzl +endif " C or lpc au BufNewFile,BufRead *.c call s:FTlpc() @@ -669,8 +672,17 @@ au BufNewFile,BufRead *.dtd setf dtd " DTS/DSTI (device tree files) au BufNewFile,BufRead *.dts,*.dtsi setf dts -" EDIF (*.edf,*.edif,*.edn,*.edo) -au BufNewFile,BufRead *.ed\(f\|if\|n\|o\) setf edif +" EDIF (*.edf,*.edif,*.edn,*.edo) or edn +au BufNewFile,BufRead *.ed\(f\|if\|o\) setf edif +au BufNewFile,BufRead *.edn + \ if getline(1) =~ '^\s*(\s*edif\>' | + \ setf edif | + \ else | + \ setf clojure | + \ endif + +" EditorConfig (close enough to dosini) +au BufNewFile,BufRead .editorconfig setf dosini " Embedix Component Description au BufNewFile,BufRead *.ecd setf ecd @@ -688,8 +700,8 @@ func! s:FTe() let n = 1 while n < 100 && n < line("$") if getline(n) =~ "^\\s*\\(<'\\|'>\\)\\s*$" - setf specman - return + setf specman + return endif let n = n + 1 endwhile @@ -775,8 +787,7 @@ au BufNewFile,BufRead *.mo,*.gdmo setf gdmo au BufNewFile,BufRead *.ged,lltxxxxx.txt setf gedcom " Git -au BufNewFile,BufRead COMMIT_EDITMSG setf gitcommit -au BufNewFile,BufRead MERGE_MSG setf gitcommit +au BufNewFile,BufRead COMMIT_EDITMSG,MERGE_MSG,TAG_EDITMSG setf gitcommit au BufNewFile,BufRead *.git/config,.gitconfig,.gitmodules setf gitconfig au BufNewFile,BufRead *.git/modules/*/config setf gitconfig au BufNewFile,BufRead */.config/git/config setf gitconfig @@ -803,6 +814,10 @@ au BufNewFile,BufRead *.gp,.gprc setf gp au BufNewFile,BufRead */.gnupg/options setf gpg au BufNewFile,BufRead */.gnupg/gpg.conf setf gpg au BufNewFile,BufRead */usr/*/gnupg/options.skel setf gpg +if !empty($GNUPGHOME) + au BufNewFile,BufRead $GNUPGHOME/options setf gpg + au BufNewFile,BufRead $GNUPGHOME/gpg.conf setf gpg +endif " gnash(1) configuration files au BufNewFile,BufRead gnashrc,.gnashrc,gnashpluginrc,.gnashpluginrc setf gnash @@ -852,7 +867,7 @@ au BufNewFile,BufRead *.ht setf haste au BufNewFile,BufRead *.htpp setf hastepreproc " Hercules -au BufNewFile,BufRead *.vc,*.ev,*.rs,*.sum,*.errsum setf hercules +au BufNewFile,BufRead *.vc,*.ev,*.sum,*.errsum setf hercules " HEX (Intel) au BufNewFile,BufRead *.hex,*.h32 setf hex @@ -1015,7 +1030,7 @@ au BufNewFile,BufRead *.jgr setf jgraph au BufNewFile,BufRead *.jov,*.j73,*.jovial setf jovial " JSON -au BufNewFile,BufRead *.json,*.jsonp setf json +au BufNewFile,BufRead *.json,*.jsonp,*.webmanifest setf json " Kixtart au BufNewFile,BufRead *.kix setf kix @@ -1750,6 +1765,9 @@ au BufNewFile,BufRead *.rb,*.rbw setf ruby " RubyGems au BufNewFile,BufRead *.gemspec setf ruby +" Rust +au BufNewFile,BufRead *.rs setf rust + " Rackup au BufNewFile,BufRead *.ru setf ruby @@ -1777,6 +1795,9 @@ au BufNewFile,BufRead *.sass setf sass " Sather au BufNewFile,BufRead *.sa setf sather +" Scala +au BufNewFile,BufRead *.scala setf scala + " Scilab au BufNewFile,BufRead *.sci,*.sce setf scilab @@ -2049,7 +2070,7 @@ func! s:FTRules() if line =~ s:ft_rules_udev_rules_pattern let udev_rules = substitute(line, s:ft_rules_udev_rules_pattern, '\1', "") if dir == udev_rules - setf udevrules + setf udevrules endif break endif @@ -2241,7 +2262,7 @@ func! s:FTtex() endfunc " ConTeXt -au BufNewFile,BufRead tex/context/*/*.tex,*.mkii,*.mkiv setf context +au BufNewFile,BufRead tex/context/*/*.tex,*.mkii,*.mkiv,*.mkvi setf context " Texinfo au BufNewFile,BufRead *.texinfo,*.texi,*.txi setf texinfo @@ -2301,7 +2322,7 @@ au BufNewFile,BufRead */etc/updatedb.conf setf updatedb au BufNewFile,BufRead */usr/share/upstart/*.conf setf upstart au BufNewFile,BufRead */usr/share/upstart/*.override setf upstart au BufNewFile,BufRead */etc/init/*.conf,*/etc/init/*.override setf upstart -au BufNewFile,BufRead */.init/*.conf,*/.init/*.override setf upstart +au BufNewFile,BufRead */.init/*.conf,*/.init/*.override setf upstart au BufNewFile,BufRead */.config/upstart/*.conf setf upstart au BufNewFile,BufRead */.config/upstart/*.override setf upstart @@ -2642,6 +2663,8 @@ au BufNewFile,BufRead [rR]akefile* call s:StarSetf('ruby') " Mail (also matches muttrc.vim, so this is below the other checks) au BufNewFile,BufRead mutt[[:alnum:]._-]\\\{6\} setf mail +au BufNewFile,BufRead reportbug-* call s:StarSetf('mail') + " Modconf au BufNewFile,BufRead */etc/modutils/* \ if executable(expand("<afile>")) != 1 @@ -2656,6 +2679,9 @@ au BufNewFile,BufRead mutt{ng,}rc*,Mutt{ng,}rc* call s:StarSetf('muttrc') " Nroff macros au BufNewFile,BufRead tmac.* call s:StarSetf('nroff') +" OpenBSD hostname.if +au BufNewFile,BufRead /etc/hostname.* call s:StarSetf('config') + " Pam conf au BufNewFile,BufRead */etc/pam.d/* call s:StarSetf('pamconf') diff --git a/runtime/ftplugin/awk.vim b/runtime/ftplugin/awk.vim new file mode 100644 index 0000000000..dcefc85ec3 --- /dev/null +++ b/runtime/ftplugin/awk.vim @@ -0,0 +1,18 @@ +" Vim filetype plugin +" Language: awk, nawk, gawk, mawk +" Maintainer: Antonio Colombo <azc100@gmail.com> +" Last Change: 2017 Feb 17 + +" This plugin was prepared by Mark Sikora + +" Only do this when not done yet for this buffer +if exists("b:did_ftplugin") + finish +endif + +" Don't load another plugin for this buffer +let b:did_ftplugin = 1 + +let b:undo_ftplugin = "setl commentstring<" + +setlocal commentstring=#\ %s diff --git a/runtime/ftplugin/context.vim b/runtime/ftplugin/context.vim index 1c7d678375..10f1ae1648 100644 --- a/runtime/ftplugin/context.vim +++ b/runtime/ftplugin/context.vim @@ -1,7 +1,8 @@ " Vim filetype plugin file -" Language: ConTeXt typesetting engine -" Maintainer: Nikolai Weibull <now@bitwi.se> -" Latest Revision: 2008-07-09 +" Language: ConTeXt typesetting engine +" Maintainer: Nicola Vitacolonna <nvitacolonna@gmail.com> +" Former Maintainers: Nikolai Weibull <now@bitwi.se> +" Latest Revision: 2016 Oct 30 if exists("b:did_ftplugin") finish @@ -11,16 +12,26 @@ let b:did_ftplugin = 1 let s:cpo_save = &cpo set cpo&vim -let b:undo_ftplugin = "setl com< cms< def< inc< sua< fo<" +if !exists('current_compiler') + compiler context +endif + +let b:undo_ftplugin = "setl com< cms< def< inc< sua< fo< ofu<" + \ . "| unlet! b:match_ignorecase b:match_words b:match_skip" -setlocal comments=b:%D,b:%C,b:%M,:% commentstring=%\ %s formatoptions+=tcroql +setlocal comments=b:%D,b:%C,b:%M,:% commentstring=%\ %s formatoptions+=tjcroql2 +if get(b:, 'context_metapost', get(g:, 'context_metapost', 1)) + setlocal omnifunc=contextcomplete#Complete + let g:omni_syntax_group_include_context = 'mf\w\+,mp\w\+' + let g:omni_syntax_group_exclude_context = 'mfTodoComment' +endif let &l:define='\\\%([egx]\|char\|mathchar\|count\|dimen\|muskip\|skip\|toks\)\=' \ . 'def\|\\font\|\\\%(future\)\=let' \ . '\|\\new\%(count\|dimen\|skip\|muskip\|box\|toks\|read\|write' \ . '\|fam\|insert\|if\)' -let &l:include = '^\s*\%(input\|component\)' +let &l:include = '^\s*\\\%(input\|component\|product\|project\|environment\)' setlocal suffixesadd=.tex @@ -31,5 +42,61 @@ if exists("loaded_matchit") \ '\\start\(\a\+\):\\stop\1' endif +let s:context_regex = { + \ 'beginsection' : '\\\%(start\)\=\%(\%(sub\)*section\|\%(sub\)*subject\|chapter\|part\|component\|product\|title\)\>', + \ 'endsection' : '\\\%(stop\)\=\%(\%(sub\)*section\|\%(sub\)*subject\|chapter\|part\|component\|product\|title\)\>', + \ 'beginblock' : '\\\%(start\|setup\|define\)', + \ 'endblock' : '\\\%(stop\|setup\|define\)' + \ } + +function! s:move_around(count, what, flags, visual) + if a:visual + exe "normal! gv" + endif + call search(s:context_regex[a:what], a:flags.'s') " 's' sets previous context mark + call map(range(2, a:count), 'search(s:context_regex[a:what], a:flags)') +endfunction + +" Move around macros. +nnoremap <silent><buffer> [[ :<C-U>call <SID>move_around(v:count1, "beginsection", "bW", v:false) <CR> +vnoremap <silent><buffer> [[ :<C-U>call <SID>move_around(v:count1, "beginsection", "bW", v:true) <CR> +nnoremap <silent><buffer> ]] :<C-U>call <SID>move_around(v:count1, "beginsection", "W", v:false) <CR> +vnoremap <silent><buffer> ]] :<C-U>call <SID>move_around(v:count1, "beginsection", "W", v:true) <CR> +nnoremap <silent><buffer> [] :<C-U>call <SID>move_around(v:count1, "endsection", "bW", v:false) <CR> +vnoremap <silent><buffer> [] :<C-U>call <SID>move_around(v:count1, "endsection", "bW", v:true) <CR> +nnoremap <silent><buffer> ][ :<C-U>call <SID>move_around(v:count1, "endsection", "W", v:false) <CR> +vnoremap <silent><buffer> ][ :<C-U>call <SID>move_around(v:count1, "endsection", "W", v:true) <CR> +nnoremap <silent><buffer> [{ :<C-U>call <SID>move_around(v:count1, "beginblock", "bW", v:false) <CR> +vnoremap <silent><buffer> [{ :<C-U>call <SID>move_around(v:count1, "beginblock", "bW", v:true) <CR> +nnoremap <silent><buffer> ]} :<C-U>call <SID>move_around(v:count1, "endblock", "W", v:false) <CR> +vnoremap <silent><buffer> ]} :<C-U>call <SID>move_around(v:count1, "endblock", "W", v:true) <CR> + +" Other useful mappings +if get(g:, 'context_mappings', 1) + let s:tp_regex = '?^$\|^\s*\\\(item\|start\|stop\|blank\|\%(sub\)*section\|chapter\|\%(sub\)*subject\|title\|part\)' + + fun! s:tp() + call cursor(search(s:tp_regex, 'bcW') + 1, 1) + normal! V + call cursor(search(s:tp_regex, 'W') - 1, 1) + endf + + " Reflow paragraphs with commands like gqtp ("gq TeX paragraph") + onoremap <silent><buffer> tp :<c-u>call <sid>tp()<cr> + " Select TeX paragraph + vnoremap <silent><buffer> tp <esc>:<c-u>call <sid>tp()<cr> + + " $...$ text object + onoremap <silent><buffer> i$ :<c-u>normal! T$vt$<cr> + onoremap <silent><buffer> a$ :<c-u>normal! F$vf$<cr> + vnoremap <buffer> i$ T$ot$ + vnoremap <buffer> a$ F$of$ +endif + +" Commands for asynchronous typesetting +command! -buffer -nargs=? -complete=file ConTeXt call context#typeset(<q-args>) +command! -nargs=0 ConTeXtJobStatus call context#job_status() +command! -nargs=0 ConTeXtStopJobs call context#stop_jobs() + let &cpo = s:cpo_save unlet s:cpo_save diff --git a/runtime/ftplugin/cucumber.vim b/runtime/ftplugin/cucumber.vim index 2ec1a5976f..f4848d1c60 100644 --- a/runtime/ftplugin/cucumber.vim +++ b/runtime/ftplugin/cucumber.vim @@ -1,7 +1,7 @@ " Vim filetype plugin " Language: Cucumber " Maintainer: Tim Pope <vimNOSPAM@tpope.org> -" Last Change: 2013 Jun 01 +" Last Change: 2016 Aug 29 " Only do this when not done yet for this buffer if (exists("b:did_ftplugin")) @@ -19,27 +19,23 @@ setlocal omnifunc=CucumberComplete let b:undo_ftplugin = "setl fo< com< cms< ofu<" let b:cucumber_root = expand('%:p:h:s?.*[\/]\%(features\|stories\)\zs[\/].*??') +if !exists("b:cucumber_steps_glob") + let b:cucumber_steps_glob = b:cucumber_root.'/**/*.rb' +endif if !exists("g:no_plugin_maps") && !exists("g:no_cucumber_maps") - nnoremap <silent><buffer> <C-]> :<C-U>exe <SID>jump('edit',v:count)<CR> - nnoremap <silent><buffer> [<C-D> :<C-U>exe <SID>jump('edit',v:count)<CR> - nnoremap <silent><buffer> ]<C-D> :<C-U>exe <SID>jump('edit',v:count)<CR> - nnoremap <silent><buffer> <C-W>] :<C-U>exe <SID>jump('split',v:count)<CR> - nnoremap <silent><buffer> <C-W><C-]> :<C-U>exe <SID>jump('split',v:count)<CR> - nnoremap <silent><buffer> <C-W>d :<C-U>exe <SID>jump('split',v:count)<CR> - nnoremap <silent><buffer> <C-W><C-D> :<C-U>exe <SID>jump('split',v:count)<CR> - nnoremap <silent><buffer> <C-W>} :<C-U>exe <SID>jump('pedit',v:count)<CR> - nnoremap <silent><buffer> [d :<C-U>exe <SID>jump('pedit',v:count)<CR> - nnoremap <silent><buffer> ]d :<C-U>exe <SID>jump('pedit',v:count)<CR> + cnoremap <SID>foldopen <Bar>if &foldopen =~# 'tag'<Bar>exe 'norm! zv'<Bar>endif + nnoremap <silent> <script> <buffer> [<C-D> :<C-U>exe <SID>jump('edit',v:count)<SID>foldopen<CR> + nnoremap <silent> <script> <buffer> ]<C-D> :<C-U>exe <SID>jump('edit',v:count)<SID>foldopen<CR> + nnoremap <silent> <script> <buffer> <C-W>d :<C-U>exe <SID>jump('split',v:count)<SID>foldopen<CR> + nnoremap <silent> <script> <buffer> <C-W><C-D> :<C-U>exe <SID>jump('split',v:count)<SID>foldopen<CR> + nnoremap <silent> <script> <buffer> [d :<C-U>exe <SID>jump('pedit',v:count)<CR> + nnoremap <silent> <script> <buffer> ]d :<C-U>exe <SID>jump('pedit',v:count)<CR> let b:undo_ftplugin .= - \ "|sil! nunmap <buffer> <C-]>" . \ "|sil! nunmap <buffer> [<C-D>" . \ "|sil! nunmap <buffer> ]<C-D>" . - \ "|sil! nunmap <buffer> <C-W>]" . - \ "|sil! nunmap <buffer> <C-W><C-]>" . \ "|sil! nunmap <buffer> <C-W>d" . \ "|sil! nunmap <buffer> <C-W><C-D>" . - \ "|sil! nunmap <buffer> <C-W>}" . \ "|sil! nunmap <buffer> [d" . \ "|sil! nunmap <buffer> ]d" endif @@ -59,7 +55,7 @@ endfunction function! s:allsteps() let step_pattern = '\C^\s*\K\k*\>\s*(\=\s*\zs\S.\{-\}\ze\s*)\=\s*\%(do\|{\)\s*\%(|[^|]*|\s*\)\=\%($\|#\)' let steps = [] - for file in split(glob(b:cucumber_root.'/**/*.rb'),"\n") + for file in split(glob(b:cucumber_steps_glob),"\n") let lines = readfile(file) let num = 0 for line in lines diff --git a/runtime/ftplugin/eruby.vim b/runtime/ftplugin/eruby.vim index 9bb8e86ff3..32f3fb868f 100644 --- a/runtime/ftplugin/eruby.vim +++ b/runtime/ftplugin/eruby.vim @@ -27,7 +27,7 @@ elseif !exists("b:eruby_subtype") let s:lines = getline(1)."\n".getline(2)."\n".getline(3)."\n".getline(4)."\n".getline(5)."\n".getline("$") let b:eruby_subtype = matchstr(s:lines,'eruby_subtype=\zs\w\+') if b:eruby_subtype == '' - let b:eruby_subtype = matchstr(substitute(expand("%:t"),'\c\%(\.erb\|\.eruby\|\.erubis\)\+$','',''),'\.\zs\w\+$') + let b:eruby_subtype = matchstr(substitute(expand("%:t"),'\c\%(\.erb\|\.eruby\|\.erubis\)\+$','',''),'\.\zs\w\+\%(\ze+\w\+\)\=$') endif if b:eruby_subtype == 'rhtml' let b:eruby_subtype = 'html' diff --git a/runtime/ftplugin/git.vim b/runtime/ftplugin/git.vim index 5fe5b2b0c3..b3d5cff804 100644 --- a/runtime/ftplugin/git.vim +++ b/runtime/ftplugin/git.vim @@ -1,7 +1,7 @@ " Vim filetype plugin " Language: generic git output " Maintainer: Tim Pope <vimNOSPAM@tpope.org> -" Last Change: 2013 May 30 +" Last Change: 2016 Aug 29 " Only do this when not done yet for this buffer if (exists("b:did_ftplugin")) @@ -12,6 +12,8 @@ let b:did_ftplugin = 1 if !exists('b:git_dir') if expand('%:p') =~# '[\/]\.git[\/]modules[\/]' " Stay out of the way + elseif expand('%:p') =~# '[\/]\.git[\/]worktrees' + let b:git_dir = matchstr(expand('%:p'),'.*\.git[\/]worktrees[\/][^\/]\+\>') elseif expand('%:p') =~# '\.git\>' let b:git_dir = matchstr(expand('%:p'),'.*\.git\>') elseif $GIT_DIR != '' diff --git a/runtime/ftplugin/gitcommit.vim b/runtime/ftplugin/gitcommit.vim index e8619004bf..6767ff719e 100644 --- a/runtime/ftplugin/gitcommit.vim +++ b/runtime/ftplugin/gitcommit.vim @@ -1,7 +1,7 @@ " Vim filetype plugin " Language: git commit file " Maintainer: Tim Pope <vimNOSPAM@tpope.org> -" Last Change: 2013 May 30 +" Last Change: 2016 Aug 29 " Only do this when not done yet for this buffer if (exists("b:did_ftplugin")) @@ -11,15 +11,10 @@ endif runtime! ftplugin/git.vim let b:did_ftplugin = 1 -setlocal nomodeline tabstop=8 formatoptions-=croq formatoptions+=tl - -let b:undo_ftplugin = 'setl modeline< tabstop< formatoptions<' - -if &textwidth == 0 - " make sure that log messages play nice with git-log on standard terminals - setlocal textwidth=72 - let b:undo_ftplugin .= "|setl tw<" -endif +setlocal comments=:# commentstring=#\ %s +setlocal nomodeline tabstop=8 formatoptions+=tl textwidth=72 +setlocal formatoptions-=c formatoptions-=r formatoptions-=o formatoptions-=q +let b:undo_ftplugin = 'setl modeline< tabstop< formatoptions< tw< com< cms<' if exists("g:no_gitcommit_commands") || v:version < 700 finish @@ -31,6 +26,8 @@ endif command! -bang -bar -buffer -complete=custom,s:diffcomplete -nargs=* DiffGitCached :call s:gitdiffcached(<bang>0,b:git_dir,<f-args>) +let b:undo_ftplugin = b:undo_ftplugin . "|delc DiffGitCached" + function! s:diffcomplete(A,L,P) let args = "" if a:P <= match(a:L." -- "," -- ")+3 diff --git a/runtime/ftplugin/gitrebase.vim b/runtime/ftplugin/gitrebase.vim index 0200ba1acc..6f73b5c499 100644 --- a/runtime/ftplugin/gitrebase.vim +++ b/runtime/ftplugin/gitrebase.vim @@ -1,7 +1,7 @@ " Vim filetype plugin " Language: git rebase --interactive " Maintainer: Tim Pope <vimNOSPAM@tpope.org> -" Last Change: 2010 May 21 +" Last Change: 2016 Aug 29 " Only do this when not done yet for this buffer if (exists("b:did_ftplugin")) @@ -12,10 +12,11 @@ runtime! ftplugin/git.vim let b:did_ftplugin = 1 setlocal comments=:# commentstring=#\ %s formatoptions-=t +setlocal nomodeline if !exists("b:undo_ftplugin") let b:undo_ftplugin = "" endif -let b:undo_ftplugin = b:undo_ftplugin."|setl com< cms< fo<" +let b:undo_ftplugin = b:undo_ftplugin."|setl com< cms< fo< ml<" function! s:choose(word) s/^\(\w\+\>\)\=\(\s*\)\ze\x\{4,40\}\>/\=(strlen(submatch(1)) == 1 ? a:word[0] : a:word) . substitute(submatch(2),'^$',' ','')/e diff --git a/runtime/ftplugin/haml.vim b/runtime/ftplugin/haml.vim index 654f1fca90..e74530b556 100644 --- a/runtime/ftplugin/haml.vim +++ b/runtime/ftplugin/haml.vim @@ -1,7 +1,7 @@ " Vim filetype plugin " Language: Haml " Maintainer: Tim Pope <vimNOSPAM@tpope.org> -" Last Change: 2013 Jun 01 +" Last Change: 2016 Aug 29 " Only do this when not done yet for this buffer if exists("b:did_ftplugin") diff --git a/runtime/ftplugin/help.vim b/runtime/ftplugin/help.vim index a0a0f292eb..9d2361b413 100644 --- a/runtime/ftplugin/help.vim +++ b/runtime/ftplugin/help.vim @@ -11,12 +11,87 @@ let b:did_ftplugin = 1 let s:cpo_save = &cpo set cpo&vim -let b:undo_ftplugin = "setl fo< tw< cole< cocu<" +let b:undo_ftplugin = "setl fo< tw< cole< cocu< keywordprg<" setlocal formatoptions+=tcroql textwidth=78 if has("conceal") setlocal cole=2 cocu=nc endif +" Prefer Vim help instead of manpages. +setlocal keywordprg=:help + +if !exists('g:no_plugin_maps') + function! s:show_toc() abort + let bufname = bufname('%') + let info = getloclist(0, {'winid': 1}) + if !empty(info) && getwinvar(info.winid, 'qf_toc') ==# bufname + lopen + return + endif + + let toc = [] + let lnum = 2 + let last_line = line('$') - 1 + let last_added = 0 + let has_section = 0 + let has_sub_section = 0 + + while lnum && lnum <= last_line + let level = 0 + let add_text = '' + let text = getline(lnum) + + if text =~# '^=\+$' && lnum + 1 < last_line + " A de-facto section heading. Other headings are inferred. + let has_section = 1 + let has_sub_section = 0 + let lnum = nextnonblank(lnum + 1) + let text = getline(lnum) + let add_text = text + while add_text =~# '\*[^*]\+\*\s*$' + let add_text = matchstr(add_text, '.*\ze\*[^*]\+\*\s*$') + endwhile + elseif text =~# '^[A-Z0-9][-A-ZA-Z0-9 .][-A-Z0-9 .():]*\%([ \t]\+\*.\+\*\)\?$' + " Any line that's yelling is important. + let has_sub_section = 1 + let level = has_section + let add_text = matchstr(text, '.\{-}\ze\s*\%([ \t]\+\*.\+\*\)\?$') + elseif text =~# '\~$' + \ && matchstr(text, '^\s*\zs.\{-}\ze\s*\~$') !~# '\t\|\s\{2,}' + \ && getline(lnum - 1) =~# '^\s*<\?$\|^\s*\*.*\*$' + \ && getline(lnum + 1) =~# '^\s*>\?$\|^\s*\*.*\*$' + " These lines could be headers or code examples. We only want the + " ones that have subsequent lines at the same indent or more. + let l = nextnonblank(lnum + 1) + if getline(l) =~# '\*[^*]\+\*$' + " Ignore tag lines + let l = nextnonblank(l + 1) + endif + + if indent(lnum) <= indent(l) + let level = has_section + has_sub_section + let add_text = matchstr(text, '\S.*') + endif + endif + + let add_text = substitute(add_text, '\s\+$', '', 'g') + if !empty(add_text) && last_added != lnum + let last_added = lnum + call add(toc, {'bufnr': bufnr('%'), 'lnum': lnum, + \ 'text': repeat(' ', level) . add_text}) + endif + let lnum = nextnonblank(lnum + 1) + endwhile + + call setloclist(0, toc, ' ') + call setloclist(0, [], 'a', {'title': 'Help TOC'}) + lopen + let w:qf_toc = bufname + endfunction + + nnoremap <silent><buffer> <M-]> :call <sid>show_toc()<cr> +endif + let &cpo = s:cpo_save unlet s:cpo_save diff --git a/runtime/ftplugin/man.vim b/runtime/ftplugin/man.vim index 5d83886f56..27c8b88e44 100644 --- a/runtime/ftplugin/man.vim +++ b/runtime/ftplugin/man.vim @@ -31,13 +31,14 @@ setlocal nolist setlocal nofoldenable if !exists('g:no_plugin_maps') && !exists('g:no_man_maps') + nnoremap <silent> <buffer> <M-]> :call man#show_toc()<CR> nnoremap <silent> <buffer> <C-]> :Man<CR> nnoremap <silent> <buffer> K :Man<CR> nnoremap <silent> <buffer> <C-T> :call man#pop_tag()<CR> if s:pager - nnoremap <silent> <buffer> <nowait> q :q<CR> + nnoremap <silent> <buffer> <nowait> q :lclose<CR>:q<CR> else - nnoremap <silent> <buffer> <nowait> q <C-W>c + nnoremap <silent> <buffer> <nowait> q :lclose<CR><C-W>c endif endif diff --git a/runtime/ftplugin/markdown.vim b/runtime/ftplugin/markdown.vim index 5d6ebecd8c..277ba94e8b 100644 --- a/runtime/ftplugin/markdown.vim +++ b/runtime/ftplugin/markdown.vim @@ -1,7 +1,7 @@ " Vim filetype plugin " Language: Markdown " Maintainer: Tim Pope <vimNOSPAM@tpope.org> -" Last Change: 2013 May 30 +" Last Change: 2016 Aug 29 if exists("b:did_ftplugin") finish @@ -11,7 +11,7 @@ runtime! ftplugin/html.vim ftplugin/html_*.vim ftplugin/html/*.vim setlocal comments=fb:*,fb:-,fb:+,n:> commentstring=>\ %s setlocal formatoptions+=tcqln formatoptions-=r formatoptions-=o -setlocal formatlistpat=^\\s*\\d\\+\\.\\s\\+\\\|^[-*+]\\s\\+ +setlocal formatlistpat=^\\s*\\d\\+\\.\\s\\+\\\|^[-*+]\\s\\+\\\|^\\[^\\ze[^\\]]\\+\\]: if exists('b:undo_ftplugin') let b:undo_ftplugin .= "|setl cms< com< fo< flp<" @@ -19,4 +19,32 @@ else let b:undo_ftplugin = "setl cms< com< fo< flp<" endif +function! MarkdownFold() + let line = getline(v:lnum) + + " Regular headers + let depth = match(line, '\(^#\+\)\@<=\( .*$\)\@=') + if depth > 0 + return ">" . depth + endif + + " Setext style headings + let nextline = getline(v:lnum + 1) + if (line =~ '^.\+$') && (nextline =~ '^=\+$') + return ">1" + endif + + if (line =~ '^.\+$') && (nextline =~ '^-\+$') + return ">2" + endif + + return "=" +endfunction + +if has("folding") && exists("g:markdown_folding") + setlocal foldexpr=MarkdownFold() + setlocal foldmethod=expr + let b:undo_ftplugin .= " foldexpr< foldmethod<" +endif + " vim:set sw=2: diff --git a/runtime/ftplugin/mf.vim b/runtime/ftplugin/mf.vim index fd1d3ce646..7c9a8a1283 100644 --- a/runtime/ftplugin/mf.vim +++ b/runtime/ftplugin/mf.vim @@ -1,7 +1,8 @@ " Vim filetype plugin file -" Language: MetaFont -" Maintainer: Nikolai Weibull <now@bitwi.se> -" Latest Revision: 2008-07-09 +" Language: METAFONT +" Maintainer: Nicola Vitacolonna <nvitacolonna@gmail.com> +" Former Maintainers: Nikolai Weibull <now@bitwi.se> +" Latest Revision: 2016 Oct 2 if exists("b:did_ftplugin") finish @@ -11,9 +12,59 @@ let b:did_ftplugin = 1 let s:cpo_save = &cpo set cpo&vim -let b:undo_ftplugin = "setl com< cms< fo<" +let b:undo_ftplugin = "setl com< cms< fo< sua< inc< def< ofu<" + \ . "| unlet! b:match_ignorecase b:match_words b:match_skip" -setlocal comments=:% commentstring=%\ %s formatoptions-=t formatoptions+=croql +setlocal comments=:% commentstring=%\ %s formatoptions-=t formatoptions+=cjroql2 +setlocal suffixesadd=.mf +let &l:include = '\<input\>' +let &l:define = '\<\%(let\|newinternal\|interim\|def\|vardef\)\>\|\<\%(primary\|secondary\|tertiary\)def\>\s*[^ .]\+' +setlocal omnifunc=syntaxcomplete#Complete +let g:omni_syntax_group_include_mf = 'mf\w\+' +let g:omni_syntax_group_exclude_mf = 'mfTodoComment' + +let s:mp_regex = { + \ 'beginsection' : '^\s*\%(\%(\|var\|primary\|secondary\|tertiary\)def\|beginchar\|beginlogochar\)\>', + \ 'endsection' : '^\s*\%(enddef\|endchar\)\>', + \ 'beginblock' : '^\s*\%(begingroup\|if\|for\%(\|suffixes\|ever\)\)\>', + \ 'endblock' : '^\s*\%(endgroup\|fi\|endfor\)\>' + \ } + +function! s:move_around(count, what, flags, visual) + if a:visual + exe "normal! gv" + endif + call search(s:mp_regex[a:what], a:flags.'s') " 's' sets previous context mark + call map(range(2, a:count), 'search(s:mp_regex[a:what], a:flags)') +endfunction + + +" Move around macros. +nnoremap <silent><buffer> [[ :<C-U>call <SID>move_around(v:count1, "beginsection", "bW", v:false) <CR> +vnoremap <silent><buffer> [[ :<C-U>call <SID>move_around(v:count1, "beginsection", "bW", v:true) <CR> +nnoremap <silent><buffer> ]] :<C-U>call <SID>move_around(v:count1, "beginsection", "W", v:false) <CR> +vnoremap <silent><buffer> ]] :<C-U>call <SID>move_around(v:count1, "beginsection", "W", v:true) <CR> +nnoremap <silent><buffer> [] :<C-U>call <SID>move_around(v:count1, "endsection", "bW", v:false) <CR> +vnoremap <silent><buffer> [] :<C-U>call <SID>move_around(v:count1, "endsection", "bW", v:true) <CR> +nnoremap <silent><buffer> ][ :<C-U>call <SID>move_around(v:count1, "endsection", "W", v:false) <CR> +vnoremap <silent><buffer> ][ :<C-U>call <SID>move_around(v:count1, "endsection", "W", v:true) <CR> +nnoremap <silent><buffer> [{ :<C-U>call <SID>move_around(v:count1, "beginblock", "bW", v:false) <CR> +vnoremap <silent><buffer> [{ :<C-U>call <SID>move_around(v:count1, "beginblock", "bW", v:true) <CR> +nnoremap <silent><buffer> ]} :<C-U>call <SID>move_around(v:count1, "endblock", "W", v:false) <CR> +vnoremap <silent><buffer> ]} :<C-U>call <SID>move_around(v:count1, "endblock", "W", v:true) <CR> + +if exists("loaded_matchit") + let b:match_ignorecase = 0 + let b:match_words = + \ '\<if\>:\<else\%[if]\>:\<fi\>,' . + \ '\<for\%(\|suffixes\|ever\)\>:\<exit\%(if\|unless\)\>:\<endfor\>,' . + \ '\<\%(\|var\|primary\|secondary\|tertiary\)def\>:\<enddef\>,' . + \ '\<begingroup\>:\<endgroup\>,' . + \ '\<begin\%(logo\)\?char\>:\<endchar\>' + " Ignore comments and strings + let b:match_skip = 'synIDattr(synID(line("."), col("."), 1), "name") + \ =~# "mf\\(Comment\\|String\\)$"' +endif let &cpo = s:cpo_save unlet s:cpo_save diff --git a/runtime/ftplugin/mp.vim b/runtime/ftplugin/mp.vim index 316fa9bb64..3a0a3d0298 100644 --- a/runtime/ftplugin/mp.vim +++ b/runtime/ftplugin/mp.vim @@ -1,7 +1,8 @@ " Vim filetype plugin file -" Language: MetaPost -" Maintainer: Nikolai Weibull <now@bitwi.se> -" Latest Revision: 2008-07-09 +" Language: MetaPost +" Maintainer: Nicola Vitacolonna <nvitacolonna@gmail.com> +" Former Maintainers: Nikolai Weibull <now@bitwi.se> +" Latest Revision: 2016 Oct 2 if exists("b:did_ftplugin") finish @@ -11,9 +12,16 @@ let b:did_ftplugin = 1 let s:cpo_save = &cpo set cpo&vim -let b:undo_ftplugin = "setl com< cms< fo<" +let b:undo_ftplugin = "setl com< cms< fo< sua< inc< def< ofu<" + \ . "| unlet! b:match_ignorecase b:match_words b:match_skip" -setlocal comments=:% commentstring=%\ %s formatoptions-=t formatoptions+=croql +setlocal comments=:% commentstring=%\ %s formatoptions-=t formatoptions+=cjroql2 +setlocal suffixesadd=.mp,.mpiv +let &l:include = '\<\%(input\|loadmodule\)\>' " loadmodule is in MetaFun +let &l:define = '\<\%(let\|newinternal\|interim\|def\|vardef\)\>\|\<\%(primary\|secondary\|tertiary\)def\>\s*[^ .]\+' +setlocal omnifunc=syntaxcomplete#Complete +let g:omni_syntax_group_include_mp = 'mf\w\+,mp\w\+' +let g:omni_syntax_group_exclude_mp = 'mfTodoComment' if exists(":FixBeginfigs") != 2 command -nargs=0 FixBeginfigs call s:fix_beginfigs() @@ -24,5 +32,51 @@ if exists(":FixBeginfigs") != 2 endfunction endif +let s:mp_regex = { + \ 'beginsection' : '^\s*\%(\%(\|var\|primary\|secondary\|tertiary\)def\|begin\%(fig\|char\|logochar\|glyph\|graph\)\)\>', + \ 'endsection' : '^\s*\%(enddef\|end\%(fig\|char\|glyph\|graph\)\)\>', + \ 'beginblock' : '^\s*\%(begingroup\|if\|for\%(\|suffixes\|ever\)\)\>', + \ 'endblock' : '^\s*\%(endgroup\|fi\|endfor\)\>' + \ } + +function! s:move_around(count, what, flags, visual) + if a:visual + exe "normal! gv" + endif + call search(s:mp_regex[a:what], a:flags.'s') " 's' sets previous context mark + call map(range(2, a:count), 'search(s:mp_regex[a:what], a:flags)') +endfunction + + +" Move around macros. +nnoremap <silent><buffer> [[ :<C-U>call <SID>move_around(v:count1, "beginsection", "bW", v:false) <CR> +vnoremap <silent><buffer> [[ :<C-U>call <SID>move_around(v:count1, "beginsection", "bW", v:true) <CR> +nnoremap <silent><buffer> ]] :<C-U>call <SID>move_around(v:count1, "beginsection", "W", v:false) <CR> +vnoremap <silent><buffer> ]] :<C-U>call <SID>move_around(v:count1, "beginsection", "W", v:true) <CR> +nnoremap <silent><buffer> [] :<C-U>call <SID>move_around(v:count1, "endsection", "bW", v:false) <CR> +vnoremap <silent><buffer> [] :<C-U>call <SID>move_around(v:count1, "endsection", "bW", v:true) <CR> +nnoremap <silent><buffer> ][ :<C-U>call <SID>move_around(v:count1, "endsection", "W", v:false) <CR> +vnoremap <silent><buffer> ][ :<C-U>call <SID>move_around(v:count1, "endsection", "W", v:true) <CR> +nnoremap <silent><buffer> [{ :<C-U>call <SID>move_around(v:count1, "beginblock", "bW", v:false) <CR> +vnoremap <silent><buffer> [{ :<C-U>call <SID>move_around(v:count1, "beginblock", "bW", v:true) <CR> +nnoremap <silent><buffer> ]} :<C-U>call <SID>move_around(v:count1, "endblock", "W", v:false) <CR> +vnoremap <silent><buffer> ]} :<C-U>call <SID>move_around(v:count1, "endblock", "W", v:true) <CR> + +if exists("loaded_matchit") + let b:match_ignorecase = 0 + let b:match_words = + \ '\<if\>:\<else\%[if]\>:\<fi\>,' . + \ '\<for\%(\|suffixes\|ever\)\>:\<exit\%(if\|unless\)\>:\<endfor\>,' . + \ '\<\%(\|var\|primary\|secondary\|tertiary\)def\>:\<enddef\>,' . + \ '\<beginfig\>:\<endfig\>,' . + \ '\<begingroup\>:\<endgroup\>,' . + \ '\<begin\%(logo\)\?char\>:\<endchar\>,' . + \ '\<beginglyph\>:\<endglyph\>,' . + \ '\<begingraph\>:\<endgraph\>' + " Ignore comments and strings + let b:match_skip = 'synIDattr(synID(line("."), col("."), 1), "name") + \ =~# "^mf\\%(Comment\\|String\\|\\)$\\|^mpTeXinsert$"' +endif + let &cpo = s:cpo_save unlet s:cpo_save diff --git a/runtime/ftplugin/python.vim b/runtime/ftplugin/python.vim index 9e2c5a763e..546e3bd560 100644 --- a/runtime/ftplugin/python.vim +++ b/runtime/ftplugin/python.vim @@ -2,7 +2,7 @@ " Language: python " Maintainer: James Sully <sullyj3@gmail.com> " Previous Maintainer: Johannes Zellner <johannes@zellner.org> -" Last Change: Fri, 10 June 2016 +" Last Change: Tue, 09 October 2016 " https://github.com/sullyj3/vim-ftplugin-python if exists("b:did_ftplugin") | finish | endif @@ -22,32 +22,54 @@ setlocal omnifunc=pythoncomplete#Complete set wildignore+=*.pyc -nnoremap <silent> <buffer> ]] :call <SID>Python_jump('/^\(class\\|def\)\>')<cr> -nnoremap <silent> <buffer> [[ :call <SID>Python_jump('?^\(class\\|def\)\>')<cr> -nnoremap <silent> <buffer> ]m :call <SID>Python_jump('/^\s*\(class\\|def\)\>')<cr> -nnoremap <silent> <buffer> [m :call <SID>Python_jump('?^\s*\(class\\|def\)\>')<cr> +let b:next_toplevel='\v%$\|^(class\|def\|async def)>' +let b:prev_toplevel='\v^(class\|def\|async def)>' +let b:next='\v%$\|^\s*(class\|def\|async def)>' +let b:prev='\v^\s*(class\|def\|async def)>' + +execute "nnoremap <silent> <buffer> ]] :call <SID>Python_jump('n', '". b:next_toplevel."', 'W')<cr>" +execute "nnoremap <silent> <buffer> [[ :call <SID>Python_jump('n', '". b:prev_toplevel."', 'Wb')<cr>" +execute "nnoremap <silent> <buffer> ]m :call <SID>Python_jump('n', '". b:next."', 'W')<cr>" +execute "nnoremap <silent> <buffer> [m :call <SID>Python_jump('n', '". b:prev."', 'Wb')<cr>" + +execute "onoremap <silent> <buffer> ]] :call <SID>Python_jump('o', '". b:next_toplevel."', 'W')<cr>" +execute "onoremap <silent> <buffer> [[ :call <SID>Python_jump('o', '". b:prev_toplevel."', 'Wb')<cr>" +execute "onoremap <silent> <buffer> ]m :call <SID>Python_jump('o', '". b:next."', 'W')<cr>" +execute "onoremap <silent> <buffer> [m :call <SID>Python_jump('o', '". b:prev."', 'Wb')<cr>" + +execute "xnoremap <silent> <buffer> ]] :call <SID>Python_jump('x', '". b:next_toplevel."', 'W')<cr>" +execute "xnoremap <silent> <buffer> [[ :call <SID>Python_jump('x', '". b:prev_toplevel."', 'Wb')<cr>" +execute "xnoremap <silent> <buffer> ]m :call <SID>Python_jump('x', '". b:next."', 'W')<cr>" +execute "xnoremap <silent> <buffer> [m :call <SID>Python_jump('x', '". b:prev."', 'Wb')<cr>" if !exists('*<SID>Python_jump') - fun! <SID>Python_jump(motion) range + fun! <SID>Python_jump(mode, motion, flags) range + if a:mode == 'x' + normal! gv + endif + + normal! 0 + let cnt = v:count1 - let save = @/ " save last search pattern mark ' while cnt > 0 - silent! exe a:motion - let cnt = cnt - 1 + call search(a:motion, a:flags) + let cnt = cnt - 1 endwhile - call histdel('/', -1) - let @/ = save " restore last search pattern + + normal! ^ endfun endif if has("browsefilter") && !exists("b:browsefilter") let b:browsefilter = "Python Files (*.py)\t*.py\n" . - \ "All Files (*.*)\t*.*\n" + \ "All Files (*.*)\t*.*\n" endif -" As suggested by PEP8. -setlocal expandtab shiftwidth=4 softtabstop=4 tabstop=8 +if !exists("g:python_recommended_style") || g:python_recommended_style != 0 + " As suggested by PEP8. + setlocal expandtab shiftwidth=4 softtabstop=4 tabstop=8 +endif " First time: try finding "pydoc". if !exists('g:pydoc_executable') diff --git a/runtime/ftplugin/qf.vim b/runtime/ftplugin/qf.vim index 98c8f932bc..80e86c4d16 100644 --- a/runtime/ftplugin/qf.vim +++ b/runtime/ftplugin/qf.vim @@ -14,3 +14,26 @@ let b:undo_ftplugin = "set stl<" " Display the command that produced the list in the quickfix window: setlocal stl=%t%{exists('w:quickfix_title')?\ '\ '.w:quickfix_title\ :\ ''}\ %=%-15(%l,%c%V%)\ %P + +function! s:setup_toc() abort + if get(w:, 'quickfix_title') !~# '\<TOC$' || &syntax != 'qf' + return + endif + + let list = getloclist(0) + if empty(list) + return + endif + + let bufnr = list[0].bufnr + setlocal modifiable + silent %delete _ + call setline(1, map(list, 'v:val.text')) + setlocal nomodifiable nomodified + let &syntax = getbufvar(bufnr, '&syntax') +endfunction + +augroup qf_toc + autocmd! + autocmd Syntax <buffer> call s:setup_toc() +augroup END diff --git a/runtime/ftplugin/rmd.vim b/runtime/ftplugin/rmd.vim index ec64a07675..8c092ac13f 100644 --- a/runtime/ftplugin/rmd.vim +++ b/runtime/ftplugin/rmd.vim @@ -1,9 +1,9 @@ " Vim filetype plugin file -" Language: R help file +" Language: R Markdown file " Maintainer: Jakson Alves de Aquino <jalvesaq@gmail.com> " Homepage: https://github.com/jalvesaq/R-Vim-runtime -" Last Change: Tue Apr 07, 2015 04:37PM -" Original work by Alex Zvoleff (adjusted for rmd by Michel Kuhlmann) +" Last Change: Mon Jun 06, 2016 09:41PM +" Original work by Alex Zvoleff (adjusted from R help for rmd by Michel Kuhlmann) " Only do this when not yet done for this buffer if exists("b:did_ftplugin") @@ -12,6 +12,16 @@ endif runtime! ftplugin/html.vim ftplugin/html_*.vim ftplugin/html/*.vim +" Nvim-R plugin needs this +if exists("*CompleteR") + if &omnifunc == "CompleteR" + let b:rplugin_nonr_omnifunc = "" + else + let b:rplugin_nonr_omnifunc = &omnifunc + endif + set omnifunc=CompleteR +endif + setlocal comments=fb:*,fb:-,fb:+,n:> commentstring=>\ %s setlocal formatoptions+=tcqln setlocal formatlistpat=^\\s*\\d\\+\\.\\s\\+\\\|^\\s*[-*+]\\s\\+ diff --git a/runtime/ftplugin/ruby.vim b/runtime/ftplugin/ruby.vim index 9630a940ab..84fb9930a4 100644 --- a/runtime/ftplugin/ruby.vim +++ b/runtime/ftplugin/ruby.vim @@ -28,12 +28,13 @@ if exists("loaded_matchit") && !exists("b:match_words") \ ':' . \ '\<\%(else\|elsif\|ensure\|when\|rescue\|break\|redo\|next\|retry\)\>' . \ ':' . - \ '\<end\>' . + \ '\%(^\|[^.\:@$]\)\@<=\<end\:\@!\>' . \ ',{:},\[:\],(:)' let b:match_skip = \ "synIDattr(synID(line('.'),col('.'),0),'name') =~ '" . \ "\\<ruby\\%(String\\|StringDelimiter\\|ASCIICode\\|Escape\\|" . + \ "Regexp\\|RegexpDelimiter\\|" . \ "Interpolation\\|NoInterpolation\\|Comment\\|Documentation\\|" . \ "ConditionalModifier\\|RepeatModifier\\|OptionalDo\\|" . \ "Function\\|BlockArgument\\|KeywordAsMethod\\|ClassVariable\\|" . @@ -43,7 +44,7 @@ endif setlocal formatoptions-=t formatoptions+=croql setlocal include=^\\s*\\<\\(load\\>\\\|require\\>\\\|autoload\\s*:\\=[\"']\\=\\h\\w*[\"']\\=,\\) -setlocal includeexpr=substitute(substitute(v:fname,'::','/','g'),'$','.rb','') +setlocal includeexpr=substitute(substitute(v:fname,'::','/','g'),'\%(\.rb\)\=$','.rb','') setlocal suffixesadd=.rb if exists("&ofu") && has("ruby") @@ -66,32 +67,32 @@ if !exists('g:ruby_version_paths') let g:ruby_version_paths = {} endif -function! s:query_path(root) +function! s:query_path(root) abort let code = "print $:.join %q{,}" - if &shell =~# 'sh' && $PATH !~# '\s' - let prefix = 'env PATH='.$PATH.' ' + if &shell =~# 'sh' + let prefix = 'env PATH='.shellescape($PATH).' ' else let prefix = '' endif if &shellxquote == "'" - let path_check = prefix.'ruby -e "' . code . '"' + let path_check = prefix.'ruby --disable-gems -e "' . code . '"' else - let path_check = prefix."ruby -e '" . code . "'" + let path_check = prefix."ruby --disable-gems -e '" . code . "'" endif let cd = haslocaldir() ? 'lcd' : 'cd' - let cwd = getcwd() + let cwd = fnameescape(getcwd()) try exe cd fnameescape(a:root) let path = split(system(path_check),',') - exe cd fnameescape(cwd) + exe cd cwd return path finally - exe cd fnameescape(cwd) + exe cd cwd endtry endfunction -function! s:build_path(path) +function! s:build_path(path) abort let path = join(map(copy(a:path), 'v:val ==# "." ? "" : v:val'), ',') if &g:path !~# '\v^\.%(,/%(usr|emx)/include)=,,$' let path = substitute(&g:path,',,$',',','') . ',' . path @@ -101,7 +102,7 @@ endfunction if !exists('b:ruby_version') && !exists('g:ruby_path') && isdirectory(expand('%:p:h')) let s:version_file = findfile('.ruby-version', '.;') - if !empty(s:version_file) + if !empty(s:version_file) && filereadable(s:version_file) let b:ruby_version = get(readfile(s:version_file, '', 1), '') if !has_key(g:ruby_version_paths, b:ruby_version) let g:ruby_version_paths[b:ruby_version] = s:query_path(fnamemodify(s:version_file, ':p:h')) @@ -135,7 +136,7 @@ if exists('s:ruby_paths') && stridx(&l:tags, join(map(copy(s:ruby_paths),'v:val. let &l:tags = &tags . ',' . join(map(copy(s:ruby_paths),'v:val."/tags"'),',') endif -if has("gui_win32") && !exists("b:browsefilter") +if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter") let b:browsefilter = "Ruby Source Files (*.rb)\t*.rb\n" . \ "All Files (*.*)\t*.*\n" endif @@ -145,7 +146,22 @@ let b:undo_ftplugin = "setl fo< inc< inex< sua< def< com< cms< path< tags< kp<" \."| if exists('&ofu') && has('ruby') | setl ofu< | endif" \."| if has('balloon_eval') && exists('+bexpr') | setl bexpr< | endif" +function! s:map(mode, flags, map) abort + let from = matchstr(a:map, '\S\+') + if empty(mapcheck(from, a:mode)) + exe a:mode.'map' '<buffer>'.(a:0 ? a:1 : '') a:map + let b:undo_ftplugin .= '|sil! '.a:mode.'unmap <buffer> '.from + endif +endfunction + +cmap <buffer><script><expr> <Plug><cword> substitute(RubyCursorIdentifier(),'^$',"\022\027",'') +cmap <buffer><script><expr> <Plug><cfile> substitute(RubyCursorFile(),'^$',"\022\006",'') +let b:undo_ftplugin .= "| sil! cunmap <buffer> <Plug><cword>| sil! cunmap <buffer> <Plug><cfile>" + if !exists("g:no_plugin_maps") && !exists("g:no_ruby_maps") + nmap <buffer><script> <SID>: :<C-U> + nmap <buffer><script> <SID>c: :<C-U><C-R>=v:count ? v:count : ''<CR> + nnoremap <silent> <buffer> [m :<C-U>call <SID>searchsyn('\<def\>','rubyDefine','b','n')<CR> nnoremap <silent> <buffer> ]m :<C-U>call <SID>searchsyn('\<def\>','rubyDefine','','n')<CR> nnoremap <silent> <buffer> [M :<C-U>call <SID>searchsyn('\<end\>','rubyDefine','b','n')<CR> @@ -168,7 +184,7 @@ if !exists("g:no_plugin_maps") && !exists("g:no_ruby_maps") \."| sil! exe 'unmap <buffer> [[' | sil! exe 'unmap <buffer> ]]' | sil! exe 'unmap <buffer> []' | sil! exe 'unmap <buffer> ]['" \."| sil! exe 'unmap <buffer> [m' | sil! exe 'unmap <buffer> ]m' | sil! exe 'unmap <buffer> [M' | sil! exe 'unmap <buffer> ]M'" - if maparg('im','n') == '' + if maparg('im','x') == '' && maparg('im','o') == '' && maparg('am','x') == '' && maparg('am','o') == '' onoremap <silent> <buffer> im :<C-U>call <SID>wrap_i('[m',']M')<CR> onoremap <silent> <buffer> am :<C-U>call <SID>wrap_a('[m',']M')<CR> xnoremap <silent> <buffer> im :<C-U>call <SID>wrap_i('[m',']M')<CR> @@ -178,7 +194,7 @@ if !exists("g:no_plugin_maps") && !exists("g:no_ruby_maps") \."| sil! exe 'xunmap <buffer> im' | sil! exe 'xunmap <buffer> am'" endif - if maparg('iM','n') == '' + if maparg('iM','x') == '' && maparg('iM','o') == '' && maparg('aM','x') == '' && maparg('aM','o') == '' onoremap <silent> <buffer> iM :<C-U>call <SID>wrap_i('[[','][')<CR> onoremap <silent> <buffer> aM :<C-U>call <SID>wrap_a('[[','][')<CR> xnoremap <silent> <buffer> iM :<C-U>call <SID>wrap_i('[[','][')<CR> @@ -188,33 +204,24 @@ if !exists("g:no_plugin_maps") && !exists("g:no_ruby_maps") \."| sil! exe 'xunmap <buffer> iM' | sil! exe 'xunmap <buffer> aM'" endif - if maparg("\<C-]>",'n') == '' - nnoremap <silent> <buffer> <C-]> :<C-U>exe v:count1."tag <C-R>=RubyCursorIdentifier()<CR>"<CR> - nnoremap <silent> <buffer> g<C-]> :<C-U>exe "tjump <C-R>=RubyCursorIdentifier()<CR>"<CR> - nnoremap <silent> <buffer> g] :<C-U>exe "tselect <C-R>=RubyCursorIdentifier()<CR>"<CR> - nnoremap <silent> <buffer> <C-W>] :<C-U>exe v:count1."stag <C-R>=RubyCursorIdentifier()<CR>"<CR> - nnoremap <silent> <buffer> <C-W><C-]> :<C-U>exe v:count1."stag <C-R>=RubyCursorIdentifier()<CR>"<CR> - nnoremap <silent> <buffer> <C-W>g<C-]> :<C-U>exe "stjump <C-R>=RubyCursorIdentifier()<CR>"<CR> - nnoremap <silent> <buffer> <C-W>g] :<C-U>exe "stselect <C-R>=RubyCursorIdentifier()<CR>"<CR> - nnoremap <silent> <buffer> <C-W>} :<C-U>exe "ptag <C-R>=RubyCursorIdentifier()<CR>"<CR> - nnoremap <silent> <buffer> <C-W>g} :<C-U>exe "ptjump <C-R>=RubyCursorIdentifier()<CR>"<CR> - let b:undo_ftplugin = b:undo_ftplugin - \."| sil! exe 'nunmap <buffer> <C-]>'| sil! exe 'nunmap <buffer> g<C-]>'| sil! exe 'nunmap <buffer> g]'" - \."| sil! exe 'nunmap <buffer> <C-W>]'| sil! exe 'nunmap <buffer> <C-W><C-]>'" - \."| sil! exe 'nunmap <buffer> <C-W>g<C-]>'| sil! exe 'nunmap <buffer> <C-W>g]'" - \."| sil! exe 'nunmap <buffer> <C-W>}'| sil! exe 'nunmap <buffer> <C-W>g}'" - endif - - if maparg("gf",'n') == '' - " By using findfile() rather than gf's normal behavior, we prevent - " erroneously editing a directory. - nnoremap <silent> <buffer> gf :<C-U>exe <SID>gf(v:count1,"gf",'edit')<CR> - nnoremap <silent> <buffer> <C-W>f :<C-U>exe <SID>gf(v:count1,"\<Lt>C-W>f",'split')<CR> - nnoremap <silent> <buffer> <C-W><C-F> :<C-U>exe <SID>gf(v:count1,"\<Lt>C-W>\<Lt>C-F>",'split')<CR> - nnoremap <silent> <buffer> <C-W>gf :<C-U>exe <SID>gf(v:count1,"\<Lt>C-W>gf",'tabedit')<CR> - let b:undo_ftplugin = b:undo_ftplugin - \."| sil! exe 'nunmap <buffer> gf' | sil! exe 'nunmap <buffer> <C-W>f' | sil! exe 'nunmap <buffer> <C-W><C-F>' | sil! exe 'nunmap <buffer> <C-W>gf'" - endif + call s:map('c', '', '<C-R><C-W> <Plug><cword>') + call s:map('c', '', '<C-R><C-F> <Plug><cfile>') + + cmap <buffer><script><expr> <SID>tagzv &foldopen =~# 'tag' ? '<Bar>norm! zv' : '' + call s:map('n', '<silent>', '<C-]> <SID>:exe v:count1."tag <Plug><cword>"<SID>tagzv<CR>') + call s:map('n', '<silent>', 'g<C-]> <SID>:exe "tjump <Plug><cword>"<SID>tagzv<CR>') + call s:map('n', '<silent>', 'g] <SID>:exe "tselect <Plug><cword>"<SID>tagzv<CR>') + call s:map('n', '<silent>', '<C-W>] <SID>:exe v:count1."stag <Plug><cword>"<SID>tagzv<CR>') + call s:map('n', '<silent>', '<C-W><C-]> <SID>:exe v:count1."stag <Plug><cword>"<SID>tagzv<CR>') + call s:map('n', '<silent>', '<C-W>g<C-]> <SID>:exe "stjump <Plug><cword>"<SID>tagzv<CR>') + call s:map('n', '<silent>', '<C-W>g] <SID>:exe "stselect <Plug><cword>"<SID>tagzv<CR>') + call s:map('n', '<silent>', '<C-W>} <SID>:exe v:count1."ptag <Plug><cword>"<CR>') + call s:map('n', '<silent>', '<C-W>g} <SID>:exe "ptjump <Plug><cword>"<CR>') + + call s:map('n', '<silent>', 'gf <SID>c:find <Plug><cfile><CR>') + call s:map('n', '<silent>', '<C-W>f <SID>c:sfind <Plug><cfile><CR>') + call s:map('n', '<silent>', '<C-W><C-F> <SID>c:sfind <Plug><cfile><CR>') + call s:map('n', '<silent>', '<C-W>gf <SID>c:tabfind <Plug><cfile><CR>') endif let &cpo = s:cpo_save @@ -225,7 +232,7 @@ if exists("g:did_ruby_ftplugin_functions") endif let g:did_ruby_ftplugin_functions = 1 -function! RubyBalloonexpr() +function! RubyBalloonexpr() abort if !exists('s:ri_found') let s:ri_found = executable('ri') endif @@ -274,13 +281,13 @@ function! RubyBalloonexpr() endif endfunction -function! s:searchsyn(pattern,syn,flags,mode) +function! s:searchsyn(pattern, syn, flags, mode) abort + let cnt = v:count1 norm! m' if a:mode ==# 'v' norm! gv endif let i = 0 - let cnt = v:count ? v:count : 1 while i < cnt let i = i + 1 let line = line('.') @@ -296,11 +303,11 @@ function! s:searchsyn(pattern,syn,flags,mode) endwhile endfunction -function! s:synname() +function! s:synname() abort return synIDattr(synID(line('.'),col('.'),0),'name') endfunction -function! s:wrap_i(back,forward) +function! s:wrap_i(back,forward) abort execute 'norm k'.a:forward let line = line('.') execute 'norm '.a:back @@ -310,7 +317,7 @@ function! s:wrap_i(back,forward) execute 'norm jV'.a:forward.'k' endfunction -function! s:wrap_a(back,forward) +function! s:wrap_a(back,forward) abort execute 'norm '.a:forward if line('.') < line('$') && getline(line('.')+1) ==# '' let after = 1 @@ -328,37 +335,55 @@ function! s:wrap_a(back,forward) endif endfunction -function! RubyCursorIdentifier() +function! RubyCursorIdentifier() abort let asciicode = '\%(\w\|[]})\"'."'".']\)\@<!\%(?\%(\\M-\\C-\|\\C-\\M-\|\\M-\\c\|\\c\\M-\|\\c\|\\C-\|\\M-\)\=\%(\\\o\{1,3}\|\\x\x\{1,2}\|\\\=\S\)\)' let number = '\%(\%(\w\|[]})\"'."'".']\s*\)\@<!-\)\=\%(\<[[:digit:]_]\+\%(\.[[:digit:]_]\+\)\=\%([Ee][[:digit:]_]\+\)\=\>\|\<0[xXbBoOdD][[:xdigit:]_]\+\>\)\|'.asciicode let operator = '\%(\[\]\|<<\|<=>\|[!<>]=\=\|===\=\|[!=]\~\|>>\|\*\*\|\.\.\.\=\|=>\|[~^&|*/%+-]\)' - let method = '\%(\<[_a-zA-Z]\w*\>\%([?!]\|\s*=>\@!\)\=\)' + let method = '\%(\.[_a-zA-Z]\w*\s*=>\@!\|\<[_a-zA-Z]\w*\>[?!]\=\)' let global = '$\%([!$&"'."'".'*+,./:;<=>?@\`~]\|-\=\w\+\>\)' let symbolizable = '\%(\%(@@\=\)\w\+\>\|'.global.'\|'.method.'\|'.operator.'\)' let pattern = '\C\s*\%('.number.'\|\%(:\@<!:\)\='.symbolizable.'\)' let [lnum, col] = searchpos(pattern,'bcn',line('.')) let raw = matchstr(getline('.')[col-1 : ],pattern) - let stripped = substitute(substitute(raw,'\s\+=$','=',''),'^\s*:\=','','') + let stripped = substitute(substitute(raw,'\s\+=$','=',''),'^\s*[:.]\=','','') return stripped == '' ? expand("<cword>") : stripped endfunction -function! s:gf(count,map,edit) abort - if getline('.') =~# '^\s*require_relative\s*\(["'']\).*\1\s*$' - let target = matchstr(getline('.'),'\(["'']\)\zs.\{-\}\ze\1') - return a:edit.' %:h/'.target.'.rb' - elseif getline('.') =~# '^\s*\%(require[( ]\|load[( ]\|autoload[( ]:\w\+,\)\s*\s*\%(::\)\=File\.expand_path(\(["'']\)\.\./.*\1,\s*__FILE__)\s*$' - let target = matchstr(getline('.'),'\(["'']\)\.\./\zs.\{-\}\ze\1') - return a:edit.' %:h/'.target.'.rb' +function! RubyCursorFile() abort + let isfname = &isfname + try + set isfname+=: + let cfile = expand('<cfile>') + finally + let isfname = &isfname + endtry + let pre = matchstr(strpart(getline('.'), 0, col('.')-1), '.*\f\@<!') + let post = matchstr(strpart(getline('.'), col('.')), '\f\@!.*') + let ext = getline('.') =~# '^\s*\%(require\%(_relative\)\=\|autoload\)\>' && cfile !~# '\.rb$' ? '.rb' : '' + if s:synname() ==# 'rubyConstant' + let cfile = substitute(cfile,'\.\w\+[?!=]\=$','','') + let cfile = substitute(cfile,'::','/','g') + let cfile = substitute(cfile,'\(\u\+\)\(\u\l\)','\1_\2', 'g') + let cfile = substitute(cfile,'\(\l\|\d\)\(\u\)','\1_\2', 'g') + return tolower(cfile) . '.rb' + elseif getline('.') =~# '^\s*require_relative\s*\(["'']\).*\1\s*$' + let cfile = expand('%:p:h') . '/' . matchstr(getline('.'),'\(["'']\)\zs.\{-\}\ze\1') . ext + elseif getline('.') =~# '^\s*\%(require[( ]\|load[( ]\|autoload[( ]:\w\+,\)\s*\%(::\)\=File\.expand_path(\(["'']\)\.\./.*\1,\s*__FILE__)\s*$' + let target = matchstr(getline('.'),'\(["'']\)\.\.\zs/.\{-\}\ze\1') + let cfile = expand('%:p:h') . target . ext elseif getline('.') =~# '^\s*\%(require \|load \|autoload :\w\+,\)\s*\(["'']\).*\1\s*$' - let target = matchstr(getline('.'),'\(["'']\)\zs.\{-\}\ze\1') + let cfile = matchstr(getline('.'),'\(["'']\)\zs.\{-\}\ze\1') . ext + elseif pre.post =~# '\<File.expand_path[( ].*[''"]\{2\}, *__FILE__\>' && cfile =~# '^\.\.' + let cfile = expand('%:p:h') . strpart(cfile, 2) else - let target = expand('<cfile>') + return substitute(cfile, '\C\v^(.*):(\d+)%(:in)=$', '+\2 \1', '') endif - let found = findfile(target, &path, a:count) - if found ==# '' - return 'norm! '.a:count.a:map + let cwdpat = '^\M' . substitute(getcwd(), '[\/]', '\\[\\/]', 'g').'\ze\[\/]' + let cfile = substitute(cfile, cwdpat, '.', '') + if fnameescape(cfile) !=# cfile + return '+ '.fnameescape(cfile) else - return a:edit.' '.fnameescape(found) + return cfile endif endfunction diff --git a/runtime/ftplugin/sass.vim b/runtime/ftplugin/sass.vim index 64232a0894..d6909e7ad5 100644 --- a/runtime/ftplugin/sass.vim +++ b/runtime/ftplugin/sass.vim @@ -1,7 +1,7 @@ " Vim filetype plugin " Language: Sass " Maintainer: Tim Pope <vimNOSPAM@tpope.org> -" Last Change: 2010 Jul 26 +" Last Change: 2016 Aug 29 " Only do this when not done yet for this buffer if exists("b:did_ftplugin") @@ -9,8 +9,9 @@ if exists("b:did_ftplugin") endif let b:did_ftplugin = 1 -let b:undo_ftplugin = "setl cms< def< inc< inex< ofu< sua<" +let b:undo_ftplugin = "setl com< cms< def< inc< inex< ofu< sua<" +setlocal comments=:// setlocal commentstring=//\ %s setlocal define=^\\s*\\%(@mixin\\\|=\\) setlocal includeexpr=substitute(v:fname,'\\%(.*/\\\|^\\)\\zs','_','') diff --git a/runtime/ftplugin/scala.vim b/runtime/ftplugin/scala.vim new file mode 100644 index 0000000000..18e16f1d5b --- /dev/null +++ b/runtime/ftplugin/scala.vim @@ -0,0 +1,35 @@ +" Vim filetype plugin file +" Language: Scala +" Maintainer: Derek Wyatt +" URL: https://github.com/derekwyatt/vim-scala +" License: Same as Vim +" Last Change: 02 August 2016 +" ---------------------------------------------------------------------------- + +if exists('b:did_ftplugin') || &cp + finish +endif +let b:did_ftplugin = 1 + +" j is fairly new in Vim, so don't complain if it's not there +setlocal formatoptions-=t formatoptions+=croqnl +silent! setlocal formatoptions+=j + +" Just like c.vim, but additionally doesn't wrap text onto /** line when +" formatting. Doesn't bungle bulleted lists when formatting. +if get(g:, 'scala_scaladoc_indent', 0) + setlocal comments=sO:*\ -,mO:*\ \ ,exO:*/,s2:/**,mb:*,ex:*/,s1:/*,mb:*,ex:*/,:// +else + setlocal comments=sO:*\ -,mO:*\ \ ,exO:*/,s1:/**,mb:*,ex:*/,s1:/*,mb:*,ex:*/,:// +endif +setlocal commentstring=//\ %s + +setlocal shiftwidth=2 softtabstop=2 expandtab + +setlocal include='^\s*import' +setlocal includeexpr='substitute(v:fname,"\\.","/","g")' + +setlocal path+=src/main/scala,src/test/scala +setlocal suffixesadd=.scala + +" vim:set sw=2 sts=2 ts=8 et: diff --git a/runtime/ftplugin/scss.vim b/runtime/ftplugin/scss.vim index 981fb1b881..287d298f4a 100644 --- a/runtime/ftplugin/scss.vim +++ b/runtime/ftplugin/scss.vim @@ -1,12 +1,13 @@ " Vim filetype plugin " Language: SCSS " Maintainer: Tim Pope <vimNOSPAM@tpope.org> -" Last Change: 2010 Jul 26 +" Last Change: 2016 Aug 29 if exists("b:did_ftplugin") finish endif runtime! ftplugin/sass.vim +setlocal comments=s1:/*,mb:*,ex:*/,:// " vim:set sw=2: diff --git a/runtime/ftplugin/tutor.vim b/runtime/ftplugin/tutor.vim index 1579753170..ec55472b78 100644 --- a/runtime/ftplugin/tutor.vim +++ b/runtime/ftplugin/tutor.vim @@ -19,27 +19,30 @@ setlocal noundofile setlocal keywordprg=:help setlocal iskeyword=@,-,_ -setlocal foldmethod=expr +" The user will have to enable the folds himself, but we provide the foldexpr +" function. +setlocal foldmethod=manual setlocal foldexpr=tutor#TutorFolds() -setlocal foldcolumn=1 setlocal foldlevel=4 -setlocal nowrap setlocal statusline=%{toupper(expand('%:t:r'))}\ tutorial%= setlocal statusline+=%{tutor#InfoText()} +" Load metadata if it exists: {{{1 +if filereadable(expand('%').'.json') + call tutor#LoadMetadata() +endif + " Mappings: {{{1 call tutor#SetNormalMappings() -call tutor#SetSampleTextMappings() " Checks: {{{1 sign define tutorok text=โ texthl=tutorOK sign define tutorbad text=โ texthl=tutorX -if !exists('g:tutor_debug') || g:tutor_debug == 0 - call tutor#PlaceXMarks() - autocmd! TextChanged <buffer> call tutor#OnTextChanged() - autocmd! TextChangedI <buffer> call tutor#OnTextChanged() +if !exists('g:tutor_debug') || g:tutor_debug == 0 + call tutor#ApplyMarks() + autocmd! TextChanged,TextChangedI <buffer> call tutor#ApplyMarksOnChanged() endif diff --git a/runtime/ftplugin/vim.vim b/runtime/ftplugin/vim.vim index f355d2837d..ba9ed76169 100644 --- a/runtime/ftplugin/vim.vim +++ b/runtime/ftplugin/vim.vim @@ -14,7 +14,7 @@ let b:did_ftplugin = 1 let s:cpo_save = &cpo set cpo-=C -let b:undo_ftplugin = "setl fo< isk< com< tw< commentstring<" +let b:undo_ftplugin = "setl fo< isk< com< tw< commentstring< keywordprg<" \ . "| unlet! b:match_ignorecase b:match_words b:match_skip" " Set 'formatoptions' to break comment lines but not other lines, @@ -36,6 +36,9 @@ endif " Comments start with a double quote setlocal commentstring=\"%s +" Prefer Vim help instead of manpages. +setlocal keywordprg=:help + " Move around functions. nnoremap <silent><buffer> [[ m':call search('^\s*fu\%[nction]\>', "bW")<CR> vnoremap <silent><buffer> [[ m':<C-U>exe "normal! gv"<Bar>call search('^\s*fu\%[nction]\>', "bW")<CR> diff --git a/runtime/indent/cdl.vim b/runtime/indent/cdl.vim index db2b9052b2..5ec2a7b21a 100644 --- a/runtime/indent/cdl.vim +++ b/runtime/indent/cdl.vim @@ -16,7 +16,7 @@ if exists("*CdlGetIndent") "finish endif -" find out if an "...=..." expresion its an asignment (or a conditional) +" find out if an "...=..." expresion is an assignment (or a conditional) " it scans 'line' first, and then the previos lines fun! CdlAsignment(lnum, line) let f = -1 diff --git a/runtime/indent/context.vim b/runtime/indent/context.vim new file mode 100644 index 0000000000..652479f7e2 --- /dev/null +++ b/runtime/indent/context.vim @@ -0,0 +1,36 @@ +" ConTeXt indent file +" Language: ConTeXt typesetting engine +" Maintainer: Nicola Vitacolonna <nvitacolonna@gmail.com> +" Last Change: 2016 Oct 15 + +if exists("b:did_indent") + finish +endif + +if !get(b:, 'context_metapost', get(g:, 'context_metapost', 1)) + finish +endif + +" Load MetaPost indentation script +runtime! indent/mp.vim + +let s:keepcpo= &cpo +set cpo&vim + +setlocal indentexpr=GetConTeXtIndent() + +let b:undo_indent = "setl indentexpr<" + +function! GetConTeXtIndent() + " Use MetaPost rules inside MetaPost graphic environments + if len(synstack(v:lnum, 1)) > 0 && + \ synIDattr(synstack(v:lnum, 1)[0], "name") ==# 'contextMPGraphic' + return GetMetaPostIndent() + endif + return -1 +endfunc + +let &cpo = s:keepcpo +unlet s:keepcpo + +" vim:sw=2 diff --git a/runtime/indent/cucumber.vim b/runtime/indent/cucumber.vim index 965c7786ed..999b8d6a76 100644 --- a/runtime/indent/cucumber.vim +++ b/runtime/indent/cucumber.vim @@ -1,7 +1,7 @@ " Vim indent file " Language: Cucumber " Maintainer: Tim Pope <vimNOSPAM@tpope.org> -" Last Change: 2013 May 30 +" Last Change: 2016 Aug 29 if exists("b:did_indent") finish @@ -27,6 +27,7 @@ function! GetCucumberIndent() let line = getline(prevnonblank(v:lnum-1)) let cline = getline(v:lnum) let nline = getline(nextnonblank(v:lnum+1)) + let sw = exists('*shiftwidth') ? shiftwidth() : &sw let syn = s:syn(prevnonblank(v:lnum-1)) let csyn = s:syn(v:lnum) let nsyn = s:syn(nextnonblank(v:lnum+1)) @@ -35,38 +36,38 @@ function! GetCucumberIndent() return 0 elseif csyn ==# 'cucumberExamples' || cline =~# '^\s*\%(Examples\|Scenarios\):' " examples heading - return 2 * &sw + return 2 * sw elseif csyn =~# '^cucumber\%(Background\|Scenario\|ScenarioOutline\)$' || cline =~# '^\s*\%(Background\|Scenario\|Scenario Outline\):' " background, scenario or outline heading - return &sw + return sw elseif syn ==# 'cucumberFeature' || line =~# '^\s*Feature:' " line after feature heading - return &sw + return sw elseif syn ==# 'cucumberExamples' || line =~# '^\s*\%(Examples\|Scenarios\):' " line after examples heading - return 3 * &sw + return 3 * sw elseif syn =~# '^cucumber\%(Background\|Scenario\|ScenarioOutline\)$' || line =~# '^\s*\%(Background\|Scenario\|Scenario Outline\):' " line after background, scenario or outline heading - return 2 * &sw + return 2 * sw elseif cline =~# '^\s*[@#]' && (nsyn == 'cucumberFeature' || nline =~# '^\s*Feature:' || indent(prevnonblank(v:lnum-1)) <= 0) " tag or comment before a feature heading return 0 elseif cline =~# '^\s*@' " other tags - return &sw + return sw elseif cline =~# '^\s*[#|]' && line =~# '^\s*|' " mid-table " preserve indent return indent(prevnonblank(v:lnum-1)) elseif cline =~# '^\s*|' && line =~# '^\s*[^|]' " first line of a table, relative indent - return indent(prevnonblank(v:lnum-1)) + &sw + return indent(prevnonblank(v:lnum-1)) + sw elseif cline =~# '^\s*[^|]' && line =~# '^\s*|' " line after a table, relative unindent - return indent(prevnonblank(v:lnum-1)) - &sw + return indent(prevnonblank(v:lnum-1)) - sw elseif cline =~# '^\s*#' && getline(v:lnum-1) =~ '^\s*$' && (nsyn =~# '^cucumber\%(Background\|Scenario\|ScenarioOutline\)$' || nline =~# '^\s*\%(Background\|Scenario\|Scenario Outline\):') " comments on scenarios - return &sw + return sw endif return indent(prevnonblank(v:lnum-1)) endfunction diff --git a/runtime/indent/eruby.vim b/runtime/indent/eruby.vim index 80cab7000e..afabd4fe5b 100644 --- a/runtime/indent/eruby.vim +++ b/runtime/indent/eruby.vim @@ -19,6 +19,9 @@ else endif unlet! b:did_indent +" Force HTML indent to not keep state. +let b:html_indent_usestate = 0 + if &l:indentexpr == '' if &l:cindent let &l:indentexpr = 'cindent(v:lnum)' @@ -38,7 +41,18 @@ if exists("*GetErubyIndent") finish endif +" this file uses line continuations +let s:cpo_sav = &cpo +set cpo&vim + function! GetErubyIndent(...) + " The value of a single shift-width + if exists('*shiftwidth') + let sw = shiftwidth() + else + let sw = &sw + endif + if a:0 && a:1 == '.' let v:lnum = line('.') elseif a:0 && a:1 =~ '^\d' @@ -52,31 +66,44 @@ function! GetErubyIndent(...) let ind = GetRubyIndent(v:lnum) else exe "let ind = ".b:eruby_subtype_indentexpr + + " Workaround for Andy Wokula's HTML indent. This should be removed after + " some time, since the newest version is fixed in a different way. + if b:eruby_subtype_indentexpr =~# '^HtmlIndent(' + \ && exists('b:indent') + \ && type(b:indent) == type({}) + \ && has_key(b:indent, 'lnum') + " Force HTML indent to not keep state + let b:indent.lnum = -1 + endif endif let lnum = prevnonblank(v:lnum-1) let line = getline(lnum) let cline = getline(v:lnum) if cline =~# '^\s*<%[-=]\=\s*\%(}\|end\|else\|\%(ensure\|rescue\|elsif\|when\).\{-\}\)\s*\%([-=]\=%>\|$\)' - let ind = ind - &sw + let ind = ind - sw endif if line =~# '\S\s*<%[-=]\=\s*\%(}\|end\).\{-\}\s*\%([-=]\=%>\|$\)' - let ind = ind - &sw + let ind = ind - sw endif if line =~# '\%({\|\<do\)\%(\s*|[^|]*|\)\=\s*[-=]\=%>' - let ind = ind + &sw + let ind = ind + sw elseif line =~# '<%[-=]\=\s*\%(module\|class\|def\|if\|for\|while\|until\|else\|elsif\|case\|when\|unless\|begin\|ensure\|rescue\)\>.*%>' - let ind = ind + &sw + let ind = ind + sw endif if line =~# '^\s*<%[=#-]\=\s*$' && cline !~# '^\s*end\>' - let ind = ind + &sw + let ind = ind + sw endif - if line !~# '^\s*<%' && line =~# '%>\s*$' - let ind = ind - &sw + if line !~# '^\s*<%' && line =~# '%>\s*$' && line !~# '^\s*end\>' + let ind = ind - sw endif if cline =~# '^\s*[-=]\=%>\s*$' - let ind = ind - &sw + let ind = ind - sw endif return ind endfunction +let &cpo = s:cpo_sav +unlet! s:cpo_sav + " vim:set sw=2 sts=2 ts=8 noet: diff --git a/runtime/indent/fortran.vim b/runtime/indent/fortran.vim index e19a19fb1f..2ba69e86df 100644 --- a/runtime/indent/fortran.vim +++ b/runtime/indent/fortran.vim @@ -1,11 +1,12 @@ " Vim indent file " Language: Fortran 2008 (and older: Fortran 2003, 95, 90, and 77) -" Version: 0.44 -" Last Change: 2016 Jan. 26 +" Version: 47 +" Last Change: 2016 Oct. 29 " Maintainer: Ajit J. Thakkar <ajit@unb.ca>; <http://www2.unb.ca/~ajit/> " Usage: For instructions, do :help fortran-indent from Vim " Credits: -" Useful suggestions were made by: Albert Oliver Serra and Takuya Fujiwara. +" Useful suggestions were made, in chronological order, by: +" Albert Oliver Serra, Takuya Fujiwara and Philipp Edelmann. " Only load this indent file when no other was loaded. if exists("b:did_indent") @@ -99,9 +100,9 @@ function FortranGetIndent(lnum) endif endif - "Add a shiftwidth to statements following if, else, else if, case, + "Add a shiftwidth to statements following if, else, else if, case, class, "where, else where, forall, type, interface and associate statements - if prevstat =~? '^\s*\(case\|else\|else\s*if\|else\s*where\)\>' + if prevstat =~? '^\s*\(case\|class\|else\|else\s*if\|else\s*where\)\>' \ ||prevstat=~? '^\s*\(type\|interface\|associate\|enum\)\>' \ ||prevstat=~?'^\s*\(\d\+\s\)\=\s*\(\a\w*\s*:\)\=\s*\(forall\|where\|block\)\>' \ ||prevstat=~? '^\s*\(\d\+\s\)\=\s*\(\a\w*\s*:\)\=\s*if\>' @@ -121,7 +122,8 @@ function FortranGetIndent(lnum) let prefix='\(\(pure\|impure\|elemental\|recursive\)\s\+\)\{,2}' let type='\(\(integer\|real\|double\s\+precision\|complex\|logical' \.'\|character\|type\|class\)\s*\S*\s\+\)\=' - if prevstat =~? '^\s*\(module\|contains\|program\)\>' + if prevstat =~? '^\s*\(contains\|submodule\|program\)\>' + \ ||prevstat =~? '^\s*'.'module\>\(\s*\procedure\)\@!' \ ||prevstat =~? '^\s*'.prefix.'subroutine\>' \ ||prevstat =~? '^\s*'.prefix.type.'function\>' \ ||prevstat =~? '^\s*'.type.prefix.'function\>' @@ -129,16 +131,16 @@ function FortranGetIndent(lnum) endif if getline(v:lnum) =~? '^\s*contains\>' \ ||getline(v:lnum)=~? '^\s*end\s*' - \ .'\(function\|subroutine\|module\|program\)\>' + \ .'\(function\|subroutine\|module\|submodule\|program\)\>' let ind = ind - shiftwidth() endif endif - "Subtract a shiftwidth from else, else if, elsewhere, case, end if, + "Subtract a shiftwidth from else, else if, elsewhere, case, class, end if, " end where, end select, end forall, end interface, end associate, - " end enum, and end type statements + " end enum, end type, end block and end type statements if getline(v:lnum) =~? '^\s*\(\d\+\s\)\=\s*' - \. '\(else\|else\s*if\|else\s*where\|case\|' + \. '\(else\|else\s*if\|else\s*where\|case\|class\|' \. 'end\s*\(if\|where\|select\|interface\|' \. 'type\|forall\|associate\|enum\|block\)\)\>' let ind = ind - shiftwidth() @@ -152,9 +154,6 @@ function FortranGetIndent(lnum) if prevstat =~ '&\s*$' && prev2stat !~ '&\s*$' let ind = ind + shiftwidth() endif - if prevstat =~ '&\s*$' && prevstat =~ '\<else\s*if\>' - let ind = ind - shiftwidth() - endif "Line after last continuation line if prevstat !~ '&\s*$' && prev2stat =~ '&\s*$' && prevstat !~? '\<then\>' let ind = ind - shiftwidth() diff --git a/runtime/indent/gitconfig.vim b/runtime/indent/gitconfig.vim index 7d5d44b779..480c96d1b9 100644 --- a/runtime/indent/gitconfig.vim +++ b/runtime/indent/gitconfig.vim @@ -1,7 +1,7 @@ " Vim indent file " Language: git config file " Maintainer: Tim Pope <vimNOSPAM@tpope.org> -" Last Change: 2013 May 30 +" Last Change: 2016 Aug 29 if exists("b:did_indent") finish @@ -20,17 +20,18 @@ if exists("*GetGitconfigIndent") endif function! GetGitconfigIndent() + let sw = exists('*shiftwidth') ? shiftwidth() : &sw let line = getline(prevnonblank(v:lnum-1)) let cline = getline(v:lnum) if line =~ '\\\@<!\%(\\\\\)*\\$' " odd number of slashes, in a line continuation - return 2 * &sw + return 2 * sw elseif cline =~ '^\s*\[' return 0 elseif cline =~ '^\s*\a' - return &sw + return sw elseif cline == '' && line =~ '^\[' - return &sw + return sw else return -1 endif diff --git a/runtime/indent/haml.vim b/runtime/indent/haml.vim index c47a8a59c7..c3935af9e9 100644 --- a/runtime/indent/haml.vim +++ b/runtime/indent/haml.vim @@ -1,7 +1,7 @@ " Vim indent file " Language: Haml " Maintainer: Tim Pope <vimNOSPAM@tpope.org> -" Last Change: 2013 May 30 +" Last Change: 2016 Aug 29 if exists("b:did_indent") finish @@ -37,10 +37,11 @@ function! GetHamlIndent() let line = substitute(line,'^\s\+','','') let indent = indent(lnum) let cindent = indent(v:lnum) + let sw = exists('*shiftwidth') ? shiftwidth() : &sw if cline =~# '\v^-\s*%(elsif|else|when)>' - let indent = cindent < indent ? cindent : indent - &sw + let indent = cindent < indent ? cindent : indent - sw endif - let increase = indent + &sw + let increase = indent + sw if indent == indent(lnum) let indent = cindent <= indent ? -1 : increase endif diff --git a/runtime/indent/html.vim b/runtime/indent/html.vim index 828bc3120b..57ba53ecd4 100644 --- a/runtime/indent/html.vim +++ b/runtime/indent/html.vim @@ -2,7 +2,7 @@ " Header: "{{{ " Maintainer: Bram Moolenaar " Original Author: Andy Wokula <anwoku@yahoo.de> -" Last Change: 2016 Mar 30 +" Last Change: 2017 Jan 17 " Version: 1.0 " Description: HTML indent script with cached state for faster indenting on a " range of lines. @@ -25,27 +25,22 @@ if exists("b:did_indent") "{{{ finish endif + +" Load the Javascript indent script first, it defines GetJavascriptIndent(). +" Undo the rest. +" Load base python indent. +if !exists('*GetJavascriptIndent') + runtime! indent/javascript.vim +endif let b:did_indent = 1 setlocal indentexpr=HtmlIndent() setlocal indentkeys=o,O,<Return>,<>>,{,},!^F -" "j1" is included to make cindent() work better with Javascript. -setlocal cino=j1 -" "J1" should be included, but it doen't work properly before 7.4.355. -if has("patch-7.4.355") - setlocal cino+=J1 -endif -" Before patch 7.4.355 indenting after "(function() {" does not work well, add -" )2 to limit paren search. -if !has("patch-7.4.355") - setlocal cino+=)2 -endif - " Needed for % to work when finding start/end of a tag. setlocal matchpairs+=<:> -let b:undo_indent = "setlocal inde< indk< cino<" +let b:undo_indent = "setlocal inde< indk<" " b:hi_indent keeps state to speed up indenting consecutive lines. let b:hi_indent = {"lnum": -1} @@ -596,7 +591,7 @@ func! s:Alien3() return eval(b:hi_js1indent) endif if b:hi_indent.scripttype == "javascript" - return cindent(v:lnum) + return GetJavascriptIndent() else return -1 endif @@ -749,7 +744,7 @@ func! s:CssPrevNonComment(lnum, stopline) while 1 let ccol = match(getline(lnum), '\*/') if ccol < 0 - " No comment end thus its something else. + " No comment end thus it's something else. return lnum endif call cursor(lnum, ccol + 1) diff --git a/runtime/indent/javascript.vim b/runtime/indent/javascript.vim index 3507e305ed..a6f1e1a8f8 100644 --- a/runtime/indent/javascript.vim +++ b/runtime/indent/javascript.vim @@ -1,8 +1,8 @@ " Vim indent file " Language: Javascript -" Maintainer: vim-javascript community +" Maintainer: Chris Paul ( https://github.com/bounceme ) " URL: https://github.com/pangloss/vim-javascript -" Last Change: August 12, 2016 +" Last Change: December 31, 2016 " Only load this indent file when no other was loaded. if exists('b:did_indent') @@ -12,11 +12,10 @@ let b:did_indent = 1 " Now, set up our indentation expression and keys that trigger it. setlocal indentexpr=GetJavascriptIndent() -setlocal nolisp -setlocal indentkeys=0{,0},0),0],:,!^F,o,O,e -setlocal cinoptions+=j1,J1 +setlocal autoindent nolisp nosmartindent +setlocal indentkeys+=0],0) -let b:undo_indent = 'setlocal indentexpr< indentkeys< cinoptions<' +let b:undo_indent = 'setlocal indentexpr< smartindent< autoindent< indentkeys<' " Only define the function once. if exists('*GetJavascriptIndent') @@ -37,156 +36,329 @@ else endfunction endif -let s:line_pre = '^\s*\%(\/\*.\{-}\*\/\s*\)*' -let s:expr_case = s:line_pre . '\%(\%(case\>.\+\)\|default\)\s*:' +" searchpair() wrapper +if has('reltime') + function s:GetPair(start,end,flags,skip,time,...) + return searchpair('\m'.a:start,'','\m'.a:end,a:flags,a:skip,max([prevnonblank(v:lnum) - 2000,0] + a:000),a:time) + endfunction +else + function s:GetPair(start,end,flags,skip,...) + return searchpair('\m'.a:start,'','\m'.a:end,a:flags,a:skip,max([prevnonblank(v:lnum) - 1000,get(a:000,1)])) + endfunction +endif + " Regex of syntax group names that are or delimit string or are comments. -let s:syng_strcom = '\%(s\%(tring\|pecial\)\|comment\|regex\|doc\|template\)' +let s:syng_strcom = 'string\|comment\|regex\|special\|doc\|template' +let s:syng_str = 'string\|template' +let s:syng_com = 'comment\|doc' +" Expression used to check whether we should skip a match with searchpair(). +let s:skip_expr = "synIDattr(synID(line('.'),col('.'),0),'name') =~? '".s:syng_strcom."'" -" Regex of syntax group names that are strings or documentation. -let s:syng_comment = '\%(comment\|doc\)' +function s:skip_func() + if !s:free || search('\m`\|\*\/','nW',s:looksyn) + let s:free = !eval(s:skip_expr) + let s:looksyn = s:free ? line('.') : s:looksyn + return !s:free + endif + let s:looksyn = line('.') + return (search('\m\/','nbW',s:looksyn) || search('\m[''"]\|\\$','nW',s:looksyn)) && eval(s:skip_expr) +endfunction -" Expression used to check whether we should skip a match with searchpair(). -let s:skip_expr = "line('.') < (prevnonblank(v:lnum) - 2000) ? dummy : synIDattr(synID(line('.'),col('.'),0),'name') =~? '".s:syng_strcom."'" +function s:alternatePair(stop) + let pos = getpos('.')[1:2] + while search('\m[][(){}]','bW',a:stop) + if !s:skip_func() + let idx = stridx('])}',s:looking_at()) + if idx + 1 + if !s:GetPair(['\[','(','{'][idx], '])}'[idx],'bW','s:skip_func()',2000,a:stop) + break + endif + else + return + endif + endif + endwhile + call call('cursor',pos) +endfunction -function s:lookForParens(start,end,flags,time) - if has('reltime') - return searchpair(a:start,'',a:end,a:flags,s:skip_expr,0,a:time) - else - return searchpair(a:start,'',a:end,a:flags,0,0) +function s:save_pos(f,...) + let l:pos = getpos('.')[1:2] + let ret = call(a:f,a:000) + call call('cursor',l:pos) + return ret +endfunction + +function s:syn_at(l,c) + return synIDattr(synID(a:l,a:c,0),'name') +endfunction + +function s:looking_at() + return getline('.')[col('.')-1] +endfunction + +function s:token() + return s:looking_at() =~ '\k' ? expand('<cword>') : s:looking_at() +endfunction + +function s:b_token() + if s:looking_at() =~ '\k' + call search('\m\<','cbW') endif + return search('\m\S','bW') endfunction -let s:line_term = '\%(\s*\%(\/\*.\{-}\*\/\s*\)\=\)\@>$' +function s:previous_token() + let l:n = line('.') + while s:b_token() + if (s:looking_at() == '/' || line('.') != l:n && search('\m\/\/','nbW', + \ line('.'))) && s:syn_at(line('.'),col('.')) =~? s:syng_com + call search('\m\_[^/]\zs\/[/*]','bW') + else + return s:token() + endif + endwhile + return '' +endfunction -" configurable regexes that define continuation lines, not including (, {, or [. -if !exists('g:javascript_opfirst') - let g:javascript_opfirst = '\%([<>,:?^%]\|\([-/.+]\)\%(\1\|\*\|\/\)\@!\|\*\/\@!\|=>\@!\||\|&\|in\%(stanceof\)\=\>\)' -endif -let g:javascript_opfirst = s:line_pre . g:javascript_opfirst +function s:others(p) + return "((line2byte(line('.')) + col('.')) <= ".(line2byte(a:p[0]) + a:p[1]).") || ".s:skip_expr +endfunction -if !exists('g:javascript_continuation') - let g:javascript_continuation = '\%([<*,.?:^%]\|+\@<!+\|-\@<!-\|=\@<!>\|\*\@<!\/\|=\||\|&\|\<in\%(stanceof\)\=\)' -endif -let g:javascript_continuation .= s:line_term +function s:tern_skip(p) + return s:GetPair('{','}','nbW',s:others(a:p),200,a:p[0]) > 0 +endfunction -function s:Onescope(lnum,text,add) - return a:text =~# '\%(\<else\|\<do\|=>' . (a:add ? '\|\<try\|\<finally' : '' ) . '\)' . s:line_term || - \ ((a:add && a:text =~ s:line_pre . '$' && search('\%' . s:PrevCodeLine(a:lnum - 1) . 'l.)' . s:line_term)) || - \ cursor(a:lnum, match(a:text, ')' . s:line_term)) > -1) && - \ s:lookForParens('(', ')', 'cbW', 100) > 0 && search((a:add ? - \ '\%(function\*\|[[:lower:][:upper:]_$][[:digit:][:lower:][:upper:]_$]*\)' : - \ '\<\%(for\%(\s\+each\)\=\|if\|let\|w\%(hile\|ith\)\)') . '\_s*\%#\C','bW') && - \ (a:add || (expand('<cword>') ==# 'while' ? !s:lookForParens('\<do\>\C', '\<while\>\C','bW',100) : 1)) +function s:tern_col(p) + return s:GetPair('?',':\@<!::\@!','nbW',s:others(a:p) + \ .' || s:tern_skip('.string(a:p).')',200,a:p[0]) > 0 endfunction -" Auxiliary Functions {{{2 +function s:label_col() + let pos = getpos('.')[1:2] + let [s:looksyn,s:free] = pos + call s:alternatePair(0) + if s:save_pos('s:IsBlock') + let poss = getpos('.')[1:2] + return call('cursor',pos) || !s:tern_col(poss) + elseif s:looking_at() == ':' + return !s:tern_col([0,0]) + endif +endfunction + +" configurable regexes that define continuation lines, not including (, {, or [. +let s:opfirst = '^' . get(g:,'javascript_opfirst', + \ '\%([<>=,?^%|*/&]\|\([-.:+]\)\1\@!\|!=\|in\%(stanceof\)\=\>\)') +let s:continuation = get(g:,'javascript_continuation', + \ '\%([<=,.~!?/*^%|&:]\|+\@<!+\|-\@<!-\|=\@<!>\|\<\%(typeof\|delete\|void\|in\|instanceof\)\)') . '$' -" strip line of comment -function s:StripLine(c) - return a:c !~# s:expr_case ? substitute(a:c, '\%(:\@<!\/\/.*\)$', '','') : a:c +function s:continues(ln,con) + return !cursor(a:ln, match(' '.a:con,s:continuation)) && + \ eval((['s:syn_at(line("."),col(".")) !~? "regex"'] + + \ repeat(['s:previous_token() != "."'],5) + [1])[ + \ index(split('/ typeof in instanceof void delete'),s:token())]) endfunction -" Find line above 'lnum' that isn't empty, in a comment, or in a string. +" get the line of code stripped of comments and move cursor to the last +" non-comment char. +function s:Trim(ln) + let pline = substitute(getline(a:ln),'\s*$','','') + let l:max = max([match(pline,'.*[^/]\zs\/[/*]'),0]) + while l:max && s:syn_at(a:ln, strlen(pline)) =~? s:syng_com + let pline = substitute(strpart(pline, 0, l:max),'\s*$','','') + let l:max = max([match(pline,'.*[^/]\zs\/[/*]'),0]) + endwhile + return cursor(a:ln,strlen(pline)) ? pline : pline +endfunction + +" Find line above 'lnum' that isn't empty or in a comment function s:PrevCodeLine(lnum) - let l:lnum = prevnonblank(a:lnum) - while l:lnum > 0 - if synIDattr(synID(l:lnum,matchend(getline(l:lnum), '^\s*[^''"]'),0),'name') !~? s:syng_strcom - break + let l:n = prevnonblank(a:lnum) + while l:n + if getline(l:n) =~ '^\s*\/[/*]' + if (stridx(getline(l:n),'`') > 0 || getline(l:n-1)[-1:] == '\') && + \ s:syn_at(l:n,1) =~? s:syng_str + return l:n + endif + let l:n = prevnonblank(l:n-1) + elseif s:syn_at(l:n,1) =~? s:syng_com + let l:n = s:save_pos('eval', + \ 'cursor('.l:n.',1) + search(''\m\/\*'',"bW")') + else + return l:n endif - let l:lnum = prevnonblank(l:lnum - 1) endwhile - return l:lnum endfunction " Check if line 'lnum' has a balanced amount of parentheses. function s:Balanced(lnum) - let open_0 = 0 - let open_2 = 0 - let open_4 = 0 + let l:open = 0 let l:line = getline(a:lnum) let pos = match(l:line, '[][(){}]', 0) while pos != -1 - if synIDattr(synID(a:lnum,pos + 1,0),'name') !~? s:syng_strcom - let idx = stridx('(){}[]', l:line[pos]) - if idx % 2 == 0 - let open_{idx} = open_{idx} + 1 - else - let open_{idx - 1} = open_{idx - 1} - 1 + if s:syn_at(a:lnum,pos + 1) !~? s:syng_strcom + let l:open += match(' ' . l:line[pos],'[[({]') + if l:open < 0 + return endif endif let pos = match(l:line, '[][(){}]', pos + 1) endwhile - return (!open_4 + !open_2 + !open_0) - 2 + return !l:open endfunction -" }}} -function GetJavascriptIndent() - if !exists('b:js_cache') - let b:js_cache = [0,0,0] +function s:OneScope(lnum) + let pline = s:Trim(a:lnum) + let kw = 'else do' + if pline[-1:] == ')' && s:GetPair('(', ')', 'bW', s:skip_expr, 100) > 0 + call s:previous_token() + let kw = 'for if let while with' + if index(split('await each'),s:token()) + 1 + call s:previous_token() + let kw = 'for' + endif + endif + return pline[-2:] == '=>' || index(split(kw),s:token()) + 1 && + \ s:save_pos('s:previous_token') != '.' +endfunction + +" returns braceless levels started by 'i' and above lines * &sw. 'num' is the +" lineNr which encloses the entire context, 'cont' if whether line 'i' + 1 is +" a continued expression, which could have started in a braceless context +function s:iscontOne(i,num,cont) + let [l:i, l:num, bL] = [a:i, a:num + !a:num, 0] + let pind = a:num ? indent(l:num) + s:W : 0 + let ind = indent(l:i) + (a:cont ? 0 : s:W) + while l:i >= l:num && (ind > pind || l:i == l:num) + if indent(l:i) < ind && s:OneScope(l:i) + let bL += s:W + let l:i = line('.') + elseif !a:cont || bL || ind < indent(a:i) + break + endif + let ind = min([ind, indent(l:i)]) + let l:i = s:PrevCodeLine(l:i - 1) + endwhile + return bL +endfunction + +" https://github.com/sweet-js/sweet.js/wiki/design#give-lookbehind-to-the-reader +function s:IsBlock() + if s:looking_at() == '{' + let l:n = line('.') + let char = s:previous_token() + let syn = char =~ '[{>/]' ? s:syn_at(line('.'),col('.')-(char == '{')) : '' + if syn =~? 'xml\|jsx' + return char != '{' + elseif char =~ '\k' + return index(split('return const let import export yield default delete var await void typeof throw case new in instanceof') + \ ,char) < (line('.') != l:n) || s:previous_token() == '.' + elseif char == '>' + return getline('.')[col('.')-2] == '=' || syn =~? '^jsflow' + elseif char == ':' + return getline('.')[col('.')-2] != ':' && s:label_col() + endif + return syn =~? 'regex' || char !~ '[-=~!<*+,/?^%|&([]' endif +endfunction + +function GetJavascriptIndent() + let b:js_cache = get(b:,'js_cache',[0,0,0]) " Get the current line. - let l:line = getline(v:lnum) - let syns = synIDattr(synID(v:lnum, 1, 0), 'name') + call cursor(v:lnum,1) + let l:line = getline('.') + let syns = s:syn_at(v:lnum, 1) - " start with strings,comments,etc.{{{2 - if (l:line !~ '^[''"`]' && syns =~? 'string\|template') || - \ (l:line !~ '^\s*[/*]' && syns =~? s:syng_comment) + " start with strings,comments,etc. + if syns =~? s:syng_com + if l:line =~ '^\s*\*' + return cindent(v:lnum) + elseif l:line !~ '^\s*\/[/*]' + return -1 + endif + elseif syns =~? s:syng_str && l:line !~ '^[''"]' + if b:js_cache[0] == v:lnum - 1 && s:Balanced(v:lnum-1) + let b:js_cache[0] = v:lnum + endif return -1 endif - if l:line !~ '^\%(\/\*\|\s*\/\/\)' && syns =~? s:syng_comment - return cindent(v:lnum) - endif let l:lnum = s:PrevCodeLine(v:lnum - 1) - if l:lnum == 0 - return 0 + if !l:lnum + return endif - if (l:line =~# s:expr_case) - let cpo_switch = &cpo - set cpo+=% - let ind = cindent(v:lnum) - let &cpo = cpo_switch - return ind + let l:line = substitute(l:line,'^\s*','','') + if l:line[:1] == '/*' + let l:line = substitute(l:line,'^\%(\/\*.\{-}\*\/\s*\)*','','') + endif + if l:line =~ '^\/[/*]' + let l:line = '' endif - "}}} - " the containing paren, bracket, curly. Memoize, last lineNr either has the - " same scope or starts a new one, unless if it closed a scope. - call cursor(v:lnum,1) - if b:js_cache[0] >= l:lnum && b:js_cache[0] <= v:lnum && b:js_cache[0] && - \ (b:js_cache[0] > l:lnum || s:Balanced(l:lnum) > 0) - let num = b:js_cache[1] - elseif syns != '' && l:line[0] =~ '\s' - let pattern = syns =~? 'block' ? ['{','}'] : syns =~? 'jsparen' ? ['(',')'] : - \ syns =~? 'jsbracket'? ['\[','\]'] : ['[({[]','[])}]'] - let num = s:lookForParens(pattern[0],pattern[1],'bW',2000) + " the containing paren, bracket, or curly. Many hacks for performance + let idx = strlen(l:line) ? stridx('])}',l:line[0]) : -1 + if b:js_cache[0] >= l:lnum && b:js_cache[0] < v:lnum && + \ (b:js_cache[0] > l:lnum || s:Balanced(l:lnum)) + call call('cursor',b:js_cache[1:]) else - let num = s:lookForParens('[({[]','[])}]','bW',2000) + let [s:looksyn, s:free, top] = [v:lnum - 1, 1, (!indent(l:lnum) && + \ s:syn_at(l:lnum,1) !~? s:syng_str) * l:lnum] + if idx + 1 + call s:GetPair(['\[','(','{'][idx], '])}'[idx],'bW','s:skip_func()',2000,top) + elseif indent(v:lnum) && syns =~? 'block' + call s:GetPair('{','}','bW','s:skip_func()',2000,top) + else + call s:alternatePair(top) + endif endif - let b:js_cache = [v:lnum,num,line('.') == v:lnum ? b:js_cache[2] : col('.')] - if l:line =~ s:line_pre . '[])}]' - return indent(num) + if idx + 1 || l:line[:1] == '|}' + if idx == 2 && search('\m\S','bW',line('.')) && s:looking_at() == ')' + call s:GetPair('(',')','bW',s:skip_expr,200) + endif + return indent('.') endif - let pline = s:StripLine(getline(l:lnum)) - let inb = num == 0 ? 1 : (s:Onescope(num, s:StripLine(strpart(getline(num),0,b:js_cache[2] - 1)),1) || - \ (l:line !~ s:line_pre . ',' && pline !~ ',' . s:line_term)) && num < l:lnum - let switch_offset = (!inb || num == 0) || expand("<cword>") !=# 'switch' ? 0 : &cino !~ ':' || !has('float') ? s:sw() : - \ float2nr(str2float(matchstr(&cino,'.*:\zs[-0-9.]*')) * (&cino =~# '.*:[^,]*s' ? s:sw() : 1)) - - " most significant, find the indent amount - if (inb && (l:line =~# g:javascript_opfirst || - \ (pline =~# g:javascript_continuation && pline !~# s:expr_case && (pline !~ ':' . s:line_term || l:line !~# - \ s:line_pre . '\%(d\%(o\|ebugger\)\|else\|f\%(or\|inally\)\|if\|let\|switch\|t\%(hrow\|ry\)\|w\%(hile\|ith\)\)\>')))) || - \ (num < l:lnum && s:Onescope(l:lnum,pline,0) && l:line !~ s:line_pre . '{') - return (num > 0 ? indent(num) : -s:sw()) + (s:sw() * 2) + switch_offset - elseif num > 0 - return indent(num) + s:sw() + switch_offset + let b:js_cache = [v:lnum] + (line('.') == v:lnum ? [0,0] : getpos('.')[1:2]) + let num = b:js_cache[1] + + let [s:W, isOp, bL, switch_offset] = [s:sw(),0,0,0] + if !num || s:IsBlock() + let pline = s:save_pos('s:Trim',l:lnum) + if num && s:looking_at() == ')' && s:GetPair('(', ')', 'bW', s:skip_expr, 100) > 0 + let num = line('.') + if s:previous_token() ==# 'switch' && s:previous_token() != '.' + if &cino !~ ':' || !has('float') + let switch_offset = s:W + else + let cinc = matchlist(&cino,'.*:\(-\)\=\([0-9.]*\)\(s\)\=\C') + let switch_offset = float2nr(str2float(cinc[1].(strlen(cinc[2]) ? cinc[2] : strlen(cinc[3]))) + \ * (strlen(cinc[3]) ? s:W : 1)) + endif + if pline[-1:] != '.' && l:line =~# '^\%(default\|case\)\>' + return indent(num) + switch_offset + endif + endif + endif + if pline[-1:] !~ '[{;]' + if pline =~# ':\@<!:$' + call cursor(l:lnum,strlen(pline)) + let isOp = s:tern_col(b:js_cache[1:2]) + else + let isOp = l:line =~# s:opfirst || s:continues(l:lnum,pline) + endif + let bL = s:iscontOne(l:lnum,num,isOp) + let bL -= (bL && l:line[0] == '{') * s:W + endif endif + " main return + if isOp + return (num ? indent(num) : -s:W) + (s:W * 2) + switch_offset + bL + elseif num + return indent(num) + s:W + switch_offset + bL + endif + return bL endfunction - let &cpo = s:cpo_save unlet s:cpo_save diff --git a/runtime/indent/liquid.vim b/runtime/indent/liquid.vim index 01e7223696..f8e1c83079 100644 --- a/runtime/indent/liquid.vim +++ b/runtime/indent/liquid.vim @@ -1,7 +1,7 @@ " Vim indent file " Language: Liquid " Maintainer: Tim Pope <vimNOSPAM@tpope.org> -" Last Change: 2013 May 30 +" Last Change: 2016 Aug 29 if exists('b:did_indent') finish @@ -54,9 +54,10 @@ function! GetLiquidIndent(...) let line = substitute(line,'\C^\%(\s*{%\s*end\w*\s*%}\)\+','','') let line .= matchstr(cline,'\C^\%(\s*{%\s*end\w*\s*%}\)\+') let cline = substitute(cline,'\C^\%(\s*{%\s*end\w*\s*%}\)\+','','') - let ind += &sw * s:count(line,'{%\s*\%(if\|elsif\|else\|unless\|ifchanged\|case\|when\|for\|empty\|tablerow\|capture\)\>') - let ind -= &sw * s:count(line,'{%\s*end\%(if\|unless\|ifchanged\|case\|for\|tablerow\|capture\)\>') - let ind -= &sw * s:count(cline,'{%\s*\%(elsif\|else\|when\|empty\)\>') - let ind -= &sw * s:count(cline,'{%\s*end\w*$') + let sw = exists('*shiftwidth') ? shiftwidth() : &sw + let ind += sw * s:count(line,'{%\s*\%(if\|elsif\|else\|unless\|ifchanged\|case\|when\|for\|empty\|tablerow\|capture\)\>') + let ind -= sw * s:count(line,'{%\s*end\%(if\|unless\|ifchanged\|case\|for\|tablerow\|capture\)\>') + let ind -= sw * s:count(cline,'{%\s*\%(elsif\|else\|when\|empty\)\>') + let ind -= sw * s:count(cline,'{%\s*end\w*$') return ind endfunction diff --git a/runtime/indent/mf.vim b/runtime/indent/mf.vim new file mode 100644 index 0000000000..88737f4e9f --- /dev/null +++ b/runtime/indent/mf.vim @@ -0,0 +1,6 @@ +" METAFONT indent file +" Language: METAFONT +" Maintainer: Nicola Vitacolonna <nvitacolonna@gmail.com> +" Last Change: 2016 Oct 1 + +runtime! indent/mp.vim diff --git a/runtime/indent/mp.vim b/runtime/indent/mp.vim index a118eb8b60..86fa2539c1 100644 --- a/runtime/indent/mp.vim +++ b/runtime/indent/mp.vim @@ -1,56 +1,19 @@ " MetaPost indent file -" Language: MetaPost -" Maintainer: Eugene Minkovskii <emin@mccme.ru> -" Last Change: 2012 May 18 -" Version: 0.1 -" ========================================================================== - -" Identation Rules: {{{1 -" First of all, MetaPost language don't expect any identation rules. -" This screept need for you only if you (not MetaPost) need to do -" exactly code. If you don't need to use indentation, see -" :help filetype-indent-off -" -" Note: Every rules of identation in MetaPost or TeX languages (and in some -" other of course) is very subjective. I can release only my vision of this -" promlem. -" -" .......................................................................... -" Example of correct (by me) identation {{{2 -" shiftwidth=4 -" ========================================================================== -" for i=0 upto 99: -" z[i] = (0,1u) rotated (i*360/100); -" endfor -" draw z0 -- z10 -- z20 -" withpen ... % <- 2sw because breaked line -" withcolor ...; % <- same as previous -" draw z0 for i=1 upto 99: -" -- z[i] % <- 1sw from left end of 'for' satement -" endfor withpen ... % <- 0sw from left end of 'for' satement -" withcolor ...; % <- 2sw because breaked line -" draw if One: % <- This is internal if (like 'for' above) -" one -" elsif Other: -" other -" fi withpen ...; -" if one: % <- This is external if -" draw one; -" elseif other: -" draw other; -" fi -" draw z0; draw z1; -" }}} -" }}} +" Language: MetaPost +" Maintainer: Nicola Vitacolonna <nvitacolonna@gmail.com> +" Former Maintainers: Eugene Minkovskii <emin@mccme.ru> +" Last Change: 2016 Oct 2, 4:13pm +" Version: 0.2 -" Only load this indent file when no other was loaded. if exists("b:did_indent") finish endif let b:did_indent = 1 setlocal indentexpr=GetMetaPostIndent() -setlocal indentkeys+=;,<:>,=if,=for,=def,=end,=else,=fi +setlocal indentkeys+==end,=else,=fi,=fill,0),0] + +let b:undo_indent = "setl indentkeys< indentexpr<" " Only define the function once. if exists("*GetMetaPostIndent") @@ -59,151 +22,337 @@ endif let s:keepcpo= &cpo set cpo&vim -" Auxiliary Definitions: {{{1 -function! MetaNextNonblankNoncomment(pos) - " Like nextnonblank() but ignore comment lines - let tmp = nextnonblank(a:pos) - while tmp && getline(tmp) =~ '^\s*%' - let tmp = nextnonblank(tmp+1) +function GetMetaPostIndent() + let ignorecase_save = &ignorecase + try + let &ignorecase = 0 + return GetMetaPostIndentIntern() + finally + let &ignorecase = ignorecase_save + endtry +endfunc + +" Regexps {{{ +" Note: the next three variables are made global so that a user may add +" further keywords. +" +" Example: +" +" Put these in ~/.vim/after/indent/mp.vim +" +" let g:mp_open_tag .= '\|\<begintest\>' +" let g:mp_close_tag .= '\|\<endtest\>' + +" Expressions starting indented blocks +let g:mp_open_tag = '' + \ . '\<if\>' + \ . '\|\<else\%[if]\>' + \ . '\|\<for\%(\|ever\|suffixes\)\>' + \ . '\|\<begingroup\>' + \ . '\|\<\%(\|var\|primary\|secondary\|tertiary\)def\>' + \ . '\|^\s*\<begin\%(fig\|graph\|glyph\|char\|logochar\)\>' + \ . '\|[([{]' + +" Expressions ending indented blocks +let g:mp_close_tag = '' + \ . '\<fi\>' + \ . '\|\<else\%[if]\>' + \ . '\|\<end\%(\|for\|group\|def\|fig\|char\|glyph\|graph\)\>' + \ . '\|[)\]}]' + +" Statements that may span multiple lines and are ended by a semicolon. To +" keep this list short, statements that are unlikely to be very long or are +" not very common (e.g., keywords like `interim` or `showtoken`) are not +" included. +" +" The regex for assignments and equations (the last branch) is tricky, because +" it must not match things like `for i :=`, `if a=b`, `def...=`, etc... It is +" not perfect, but it works reasonably well. +let g:mp_statement = '' + \ . '\<\%(\|un\|cut\)draw\>' + \ . '\|\<\%(\|un\)fill\%[draw]\>' + \ . '\|\<draw\%(dbl\)\=arrow\>' + \ . '\|\<clip\>' + \ . '\|\<addto\>' + \ . '\|\<save\>' + \ . '\|\<setbounds\>' + \ . '\|\<message\>' + \ . '\|\<errmessage\>' + \ . '\|\<errhelp\>' + \ . '\|\<fontmapline\>' + \ . '\|\<pickup\>' + \ . '\|\<show\>' + \ . '\|\<special\>' + \ . '\|\<write\>' + \ . '\|\%(^\|;\)\%([^;=]*\%('.g:mp_open_tag.'\)\)\@!.\{-}:\==' + +" A line ends with zero or more spaces, possibly followed by a comment. +let s:eol = '\s*\%($\|%\)' +" }}} + +" Auxiliary functions {{{ +" Returns 1 if (0-based) position immediately preceding `pos` in `line` is +" inside a string or a comment; returns 0 otherwise. + +" This is the function that is called more often when indenting, so it is +" critical that it is efficient. The method we use is significantly faster +" than using syntax attributes, and more general (it does not require +" syntax_items). It is also faster than using a single regex matching an even +" number of quotes. It helps that MetaPost strings cannot span more than one +" line and cannot contain escaped quotes. +function! s:CommentOrString(line, pos) + let in_string = 0 + let q = stridx(a:line, '"') + let c = stridx(a:line, '%') + while q >= 0 && q < a:pos + if c >= 0 && c < q + if in_string " Find next percent symbol + let c = stridx(a:line, '%', q + 1) + else " Inside comment + return 1 + endif + endif + let in_string = 1 - in_string + let q = stridx(a:line, '"', q + 1) " Find next quote endwhile - return tmp + return in_string || (c >= 0 && c <= a:pos) endfunction -function! MetaPrevNonblankNoncomment(pos) - " Like prevnonblank() but ignore comment lines - let tmp = prevnonblank(a:pos) - while tmp && getline(tmp) =~ '^\s*%' - let tmp = prevnonblank(tmp-1) +" Find the first non-comment non-blank line before the current line. +function! s:PrevNonBlankNonComment(lnum) + let l:lnum = prevnonblank(a:lnum - 1) + while getline(l:lnum) =~# '^\s*%' + let l:lnum = prevnonblank(l:lnum - 1) endwhile - return tmp + return l:lnum endfunction -function! MetaSearchNoncomment(pattern, ...) - " Like search() but ignore commented areas - if a:0 - let flags = a:1 - elseif &wrapscan - let flags = "w" - else - let flags = "W" - endif - let cl = line(".") - let cc = col(".") - let tmp = search(a:pattern, flags) - while tmp && synIDattr(synID(line("."), col("."), 1), "name") =~ - \ 'm[fp]\(Comment\|TeXinsert\|String\)' - let tmp = search(a:pattern, flags) +" Returns true if the last tag appearing in the line is an open tag; returns +" false otherwise. +function! s:LastTagIsOpen(line) + let o = s:LastValidMatchEnd(a:line, g:mp_open_tag, 0) + if o == - 1 | return v:false | endif + return s:LastValidMatchEnd(a:line, g:mp_close_tag, o) < 0 +endfunction + +" A simple, efficient and quite effective heuristics is used to test whether +" a line should cause the next line to be indented: count the "opening tags" +" (if, for, def, ...) in the line, count the "closing tags" (endif, endfor, +" ...) in the line, and compute the difference. We call the result the +" "weight" of the line. If the weight is positive, then the next line should +" most likely be indented. Note that `else` and `elseif` are both opening and +" closing tags, so they "cancel out" in almost all cases, the only exception +" being a leading `else[if]`, which is counted as an opening tag, but not as +" a closing tag (so that, for instance, a line containing a single `else:` +" will have weight equal to one, not zero). We do not treat a trailing +" `else[if]` in any special way, because lines ending with an open tag are +" dealt with separately before this function is called (see +" GetMetaPostIndentIntern()). +" +" Example: +" +" forsuffixes $=a,b: if x.$ = y.$ : draw else: fill fi +" % This line will be indented because |{forsuffixes,if,else}| > |{else,fi}| (3 > 2) +" endfor + +function! s:Weight(line) + let [o, i] = [0, s:ValidMatchEnd(a:line, g:mp_open_tag, 0)] + while i > 0 + let o += 1 + let i = s:ValidMatchEnd(a:line, g:mp_open_tag, i) + endwhile + let [c, i] = [0, matchend(a:line, '^\s*\<else\%[if]\>')] " Skip a leading else[if] + let i = s:ValidMatchEnd(a:line, g:mp_close_tag, i) + while i > 0 + let c += 1 + let i = s:ValidMatchEnd(a:line, g:mp_close_tag, i) + endwhile + return o - c +endfunction + +" Similar to matchend(), but skips strings and comments. +" line: a String +function! s:ValidMatchEnd(line, pat, start) + let i = matchend(a:line, a:pat, a:start) + while i > 0 && s:CommentOrString(a:line, i) + let i = matchend(a:line, a:pat, i) + endwhile + return i +endfunction + +" Like s:ValidMatchEnd(), but returns the end position of the last (i.e., +" rightmost) match. +function! s:LastValidMatchEnd(line, pat, start) + let last_found = -1 + let i = matchend(a:line, a:pat, a:start) + while i > 0 + if !s:CommentOrString(a:line, i) + let last_found = i + endif + let i = matchend(a:line, a:pat, i) endwhile - if !tmp - call cursor(cl,cc) + return last_found +endfunction + +function! s:DecreaseIndentOnClosingTag(curr_indent) + let cur_text = getline(v:lnum) + if cur_text =~# '^\s*\%('.g:mp_close_tag.'\)' + return max([a:curr_indent - shiftwidth(), 0]) endif - return tmp + return a:curr_indent endfunction " }}} -function! GetMetaPostIndent() - " not indent in comment ??? - if synIDattr(synID(line("."), col("."), 1), "name") =~ - \ 'm[fp]\(Comment\|TeXinsert\|String\)' +" Main function {{{ +" +" Note: Every rule of indentation in MetaPost is very subjective. We might get +" creative, but things get murky very soon (there are too many corner cases). +" So, we provide a means for the user to decide what to do when this script +" doesn't get it. We use a simple idea: use '%>', '%<' and '%=' to explicitly +" control indentation. The '<' and '>' symbols may be repeated many times +" (e.g., '%>>' will cause the next line to be indented twice). +" +" By using '%>...', '%<...' and '%=', the indentation the user wants is +" preserved by commands like gg=G, even if it does not follow the rules of +" this script. +" +" Example: +" +" def foo = +" makepen( +" subpath(T-n,t) of r %> +" shifted .5down %> +" --subpath(t,T) of r shifted .5up -- cycle %<<< +" ) +" withcolor black +" enddef +" +" The default indentation of the previous example would be: +" +" def foo = +" makepen( +" subpath(T-n,t) of r +" shifted .5down +" --subpath(t,T) of r shifted .5up -- cycle +" ) +" withcolor black +" enddef +" +" Personally, I prefer the latter, but anyway... +function! GetMetaPostIndentIntern() + " Do not touch indentation inside verbatimtex/btex.. etex blocks. + if synIDattr(synID(v:lnum, 1, 1), "name") =~# '^mpTeXinsert$\|^tex\|^Delimiter' return -1 endif - " Some RegExps: {{{1 - " end_of_item: all of end by ';' - " + all of end by :endfor, :enddef, :endfig, :endgroup, :fi - " + all of start by :beginfig(num), :begingroup - " + all of start by :for, :if, :else, :elseif and end by ':' - " + all of start by :def, :vardef and end by '=' - let end_of_item = '\(' . - \ ';\|' . - \ '\<\(end\(for\|def\|fig\|group\)\|fi\)\>\|' . - \ '\<begin\(group\>\|fig\s*(\s*\d\+\s*)\)\|' . - \ '\<\(for\|if\|else\(if\)\=\)\>.\+:\|' . - \ '\<\(var\)\=def\>.\+=' . '\)' - " }}} - " Save: current position {{{1 - let cl = line (".") - let cc = col (".") - let cs = getline(".") - " if it is :beginfig or :endfig use zero indent - if cs =~ '^\s*\(begin\|end\)fig\>' - return 0 - endif - " }}} - " Initialise: ind variable {{{1 - " search previous item not in current line - let p_semicol_l = MetaSearchNoncomment(end_of_item,"bW") - while p_semicol_l == cl - let p_semicol_l = MetaSearchNoncomment(end_of_item,"bW") - endwhile - " if this is first item in program use zero indent - if !p_semicol_l + + " This is the reference line relative to which the current line is indented + " (but see below). + let lnum = s:PrevNonBlankNonComment(v:lnum) + + " At the start of the file use zero indent. + if lnum == 0 return 0 endif - " if this is multiline item, remember first indent - if MetaNextNonblankNoncomment(p_semicol_l+1) < cl - let ind = indent(MetaNextNonblankNoncomment(p_semicol_l+1)) - " else --- search pre-previous item for search first line in previous item - else - " search pre-previous item not in current line - let pp_semicol_l = MetaSearchNoncomment(end_of_item,"bW") - while pp_semicol_l == p_semicol_l - let pp_semicol_l = MetaSearchNoncomment(end_of_item,"bW") - endwhile - " if we find pre-previous item, remember indent of previous item - " else --- remember zero - if pp_semicol_l - let ind = indent(MetaNextNonblankNoncomment(line(".")+1)) - else - let ind = 0 + + let prev_text = getline(lnum) + + " User-defined overrides take precedence over anything else. + " See above for an example. + let j = match(prev_text, '%[<>=]') + if j > 0 + let i = strlen(matchstr(prev_text, '%>\+', j)) - 1 + if i > 0 + return indent(lnum) + i * shiftwidth() + endif + + let i = strlen(matchstr(prev_text, '%<\+', j)) - 1 + if i > 0 + return max([indent(lnum) - i * shiftwidth(), 0]) + endif + + if match(prev_text, '%=', j) + return indent(lnum) endif endif - " }}} - " Increase Indent: {{{1 - " if it is an internal/external :for or :if statements {{{2 - let pnn_s = getline(MetaPrevNonblankNoncomment(cl-1)) - if pnn_s =~ '\<\(for\|if\)\>.\+:\s*\($\|%\)' - let ind = match(pnn_s, '\<\(for\|if\)\>.\+:\s*\($\|%\)') + &sw - " }}} - " if it is a :def, :vardef, :beginfig, :begingroup, :else, :elseif {{{2 - elseif pnn_s =~ '^\s*\(' . - \ '\(var\)\=def\|' . - \ 'begin\(group\|fig\s*(\s*\d\+\s*)\)\|' . - \ 'else\(if\)\=' . '\)\>' - let ind = ind + &sw - " }}} - " if it is a broken line {{{2 - elseif pnn_s !~ end_of_item.'\s*\($\|%\)' - let ind = ind + (2 * &sw) + + " If the reference line ends with an open tag, indent. + " + " Example: + " + " if c: + " 0 + " else: + " 1 + " fi if c2: % Note that this line has weight equal to zero. + " ... % This line will be indented + if s:LastTagIsOpen(prev_text) + return s:DecreaseIndentOnClosingTag(indent(lnum) + shiftwidth()) endif - " }}} - " }}} - " Decrease Indent: {{{1 - " if this is :endfor or :enddef statements {{{2 - " this is correct because :def cannot be inside :for - if cs =~ '\<end\(for\|def\)\=\>' - call MetaSearchNoncomment('\<for\>.\+:\s*\($\|%\)' . '\|' . - \ '^\s*\(var\)\=def\>',"bW") - if col(".") > 1 - let ind = col(".") - 1 + + " Lines with a positive weight are unbalanced and should likely be indented. + " + " Example: + " + " def f = enddef for i = 1 upto 5: if x[i] > 0: 1 else: 2 fi + " ... % This line will be indented (because of the unterminated `for`) + if s:Weight(prev_text) > 0 + return s:DecreaseIndentOnClosingTag(indent(lnum) + shiftwidth()) + endif + + " Unterminated statements cause indentation to kick in. + " + " Example: + " + " draw unitsquare + " withcolor black; % This line is indented because of `draw`. + " x := a + b + c + " + d + e; % This line is indented because of `:=`. + " + let i = s:LastValidMatchEnd(prev_text, g:mp_statement, 0) + if i >= 0 " Does the line contain a statement? + if s:ValidMatchEnd(prev_text, ';', i) < 0 " Is the statement unterminated? + return indent(lnum) + shiftwidth() else - let ind = indent(".") + return s:DecreaseIndentOnClosingTag(indent(lnum)) endif - " }}} - " if this is :fi, :else, :elseif statements {{{2 - elseif cs =~ '\<\(else\(if\)\=\|fi\)\>' - call MetaSearchNoncomment('\<if\>.\+:\s*\($\|%\)',"bW") - let ind = col(".") - 1 - " }}} - " if this is :endgroup statement {{{2 - elseif cs =~ '^\s*endgroup\>' - let ind = ind - &sw endif - " }}} - " }}} - return ind + " Deal with the special case of a statement spanning multiple lines. If the + " current reference line L ends with a semicolon, search backwards for + " another semicolon or a statement keyword. If the latter is found first, + " its line is used as the reference line for indenting the current line + " instead of L. + " + " Example: + " + " if cond: + " draw if a: z0 else: z1 fi + " shifted S + " scaled T; % L + " + " for i = 1 upto 3: % <-- Current line: this gets the same indent as `draw ...` + " + " NOTE: we get here only if L does not contain a statement (among those + " listed in g:mp_statement). + if s:ValidMatchEnd(prev_text, ';'.s:eol, 0) >= 0 " L ends with a semicolon + let stm_lnum = s:PrevNonBlankNonComment(lnum) + while stm_lnum > 0 + let prev_text = getline(stm_lnum) + let sc_pos = s:LastValidMatchEnd(prev_text, ';', 0) + let stm_pos = s:ValidMatchEnd(prev_text, g:mp_statement, sc_pos) + if stm_pos > sc_pos + let lnum = stm_lnum + break + elseif sc_pos > stm_pos + break + endif + let stm_lnum = s:PrevNonBlankNonComment(stm_lnum) + endwhile + endif + + return s:DecreaseIndentOnClosingTag(indent(lnum)) endfunction -" +" }}} let &cpo = s:keepcpo unlet s:keepcpo diff --git a/runtime/indent/rnoweb.vim b/runtime/indent/rnoweb.vim index 29fa5bc78f..8c11e85cb3 100644 --- a/runtime/indent/rnoweb.vim +++ b/runtime/indent/rnoweb.vim @@ -2,7 +2,7 @@ " Language: Rnoweb " Author: Jakson Alves de Aquino <jalvesaq@gmail.com> " Homepage: https://github.com/jalvesaq/R-Vim-runtime -" Last Change: Tue Apr 07, 2015 04:38PM +" Last Change: Fri Apr 15, 2016 10:58PM " Only load this indent file when no other was loaded. @@ -10,7 +10,17 @@ if exists("b:did_indent") finish endif runtime indent/tex.vim -let s:TeXIndent = function(substitute(&indentexpr, "()", "", "")) + +function! s:NoTeXIndent() + return indent(line(".")) +endfunction + +if &indentexpr == "" || &indentexpr == "GetRnowebIndent()" + let s:TeXIndent = function("s:NoTeXIndent") +else + let s:TeXIndent = function(substitute(&indentexpr, "()", "", "")) +endif + unlet b:did_indent runtime indent/r.vim let s:RIndent = function(substitute(&indentexpr, "()", "", "")) diff --git a/runtime/indent/ruby.vim b/runtime/indent/ruby.vim index 095b3a43c6..a97f4828d6 100644 --- a/runtime/indent/ruby.vim +++ b/runtime/indent/ruby.vim @@ -13,12 +13,23 @@ if exists("b:did_indent") endif let b:did_indent = 1 +if !exists('g:ruby_indent_access_modifier_style') + " Possible values: "normal", "indent", "outdent" + let g:ruby_indent_access_modifier_style = 'normal' +endif + +if !exists('g:ruby_indent_block_style') + " Possible values: "expression", "do" + let g:ruby_indent_block_style = 'expression' +endif + setlocal nosmartindent " Now, set up our indentation expression and keys that trigger it. setlocal indentexpr=GetRubyIndent(v:lnum) -setlocal indentkeys=0{,0},0),0],!^F,o,O,e +setlocal indentkeys=0{,0},0),0],!^F,o,O,e,:,. setlocal indentkeys+==end,=else,=elsif,=when,=ensure,=rescue,==begin,==end +setlocal indentkeys+==private,=protected,=public " Only define the function once. if exists("*GetRubyIndent") @@ -34,7 +45,7 @@ set cpo&vim " Regex of syntax group names that are or delimit strings/symbols or are comments. let s:syng_strcom = '\<ruby\%(Regexp\|RegexpDelimiter\|RegexpEscape' . \ '\|Symbol\|String\|StringDelimiter\|StringEscape\|ASCIICode' . - \ '\|Interpolation\|NoInterpolation\|Comment\|Documentation\)\>' + \ '\|Interpolation\|InterpolationDelimiter\|NoInterpolation\|Comment\|Documentation\)\>' " Regex of syntax group names that are strings. let s:syng_string = @@ -49,9 +60,10 @@ let s:skip_expr = \ "synIDattr(synID(line('.'),col('.'),1),'name') =~ '".s:syng_strcom."'" " Regex used for words that, at the start of a line, add a level of indent. -let s:ruby_indent_keywords = '^\s*\zs\<\%(module\|class\|def\|if\|for' . - \ '\|while\|until\|else\|elsif\|case\|when\|unless\|begin\|ensure' . - \ '\|rescue\):\@!\>' . +let s:ruby_indent_keywords = + \ '^\s*\zs\<\%(module\|class\|if\|for' . + \ '\|while\|until\|else\|elsif\|case\|when\|unless\|begin\|ensure\|rescue' . + \ '\|\%(public\|protected\|private\)\=\s*def\):\@!\>' . \ '\|\%([=,*/%+-]\|<<\|>>\|:\s\)\s*\zs' . \ '\<\%(if\|for\|while\|until\|case\|unless\|begin\):\@!\>' @@ -64,7 +76,8 @@ let s:ruby_deindent_keywords = " TODO: the do here should be restricted somewhat (only at end of line)? let s:end_start_regex = \ '\C\%(^\s*\|[=,*/%+\-|;{]\|<<\|>>\|:\s\)\s*\zs' . - \ '\<\%(module\|class\|def\|if\|for\|while\|until\|case\|unless\|begin\):\@!\>' . + \ '\<\%(module\|class\|if\|for\|while\|until\|case\|unless\|begin' . + \ '\|\%(public\|protected\|private\)\=\s*def\):\@!\>' . \ '\|\%(^\|[^.:@$]\)\@<=\<do:\@!\>' " Regex that defines the middle-match for the 'end' keyword. @@ -79,19 +92,39 @@ let s:end_skip_expr = s:skip_expr . \ ' && getline(".") =~ "^\\s*\\<\\(while\\|until\\|for\\):\\@!\\>")' " Regex that defines continuation lines, not including (, {, or [. -let s:non_bracket_continuation_regex = '\%([\\.,:*/%+]\|\<and\|\<or\|\%(<%\)\@<![=-]\|\W[|&?]\|||\|&&\)\s*\%(#.*\)\=$' +let s:non_bracket_continuation_regex = + \ '\%([\\.,:*/%+]\|\<and\|\<or\|\%(<%\)\@<![=-]\|:\@<![^[:alnum:]:][|&?]\|||\|&&\)\s*\%(#.*\)\=$' " Regex that defines continuation lines. -" TODO: this needs to deal with if ...: and so on let s:continuation_regex = - \ '\%(%\@<![({[\\.,:*/%+]\|\<and\|\<or\|\%(<%\)\@<![=-]\|\W[|&?]\|||\|&&\)\s*\%(#.*\)\=$' + \ '\%(%\@<![({[\\.,:*/%+]\|\<and\|\<or\|\%(<%\)\@<![=-]\|:\@<![^[:alnum:]:][|&?]\|||\|&&\)\s*\%(#.*\)\=$' + +" Regex that defines continuable keywords +let s:continuable_regex = + \ '\C\%(^\s*\|[=,*/%+\-|;{]\|<<\|>>\|:\s\)\s*\zs' . + \ '\<\%(if\|for\|while\|until\|unless\):\@!\>' " Regex that defines bracket continuations let s:bracket_continuation_regex = '%\@<!\%([({[]\)\s*\%(#.*\)\=$' +" Regex that defines dot continuations +let s:dot_continuation_regex = '%\@<!\.\s*\%(#.*\)\=$' + +" Regex that defines backslash continuations +let s:backslash_continuation_regex = '%\@<!\\\s*$' + +" Regex that defines end of bracket continuation followed by another continuation +let s:bracket_switch_continuation_regex = '^\([^(]\+\zs).\+\)\+'.s:continuation_regex + " Regex that defines the first part of a splat pattern let s:splat_regex = '[[,(]\s*\*\s*\%(#.*\)\=$' +" Regex that describes all indent access modifiers +let s:access_modifier_regex = '\C^\s*\%(public\|protected\|private\)\s*\%(#.*\)\=$' + +" Regex that describes the indent access modifiers (excludes public) +let s:indent_access_modifier_regex = '\C^\s*\%(protected\|private\)\s*\%(#.*\)\=$' + " Regex that defines blocks. " " Note that there's a slight problem with this regex and s:continuation_regex. @@ -102,10 +135,13 @@ let s:splat_regex = '[[,(]\s*\*\s*\%(#.*\)\=$' " The reason is that the pipe matches a hanging "|" operator. " let s:block_regex = - \ '\%(\<do:\@!\>\|%\@<!{\)\s*\%(|\s*(*\s*\%([*@&]\=\h\w*,\=\s*\)\%(,\s*(*\s*[*@&]\=\h\w*\s*)*\s*\)*|\)\=\s*\%(#.*\)\=$' + \ '\%(\<do:\@!\>\|%\@<!{\)\s*\%(|[^|]*|\)\=\s*\%(#.*\)\=$' let s:block_continuation_regex = '^\s*[^])}\t ].*'.s:block_regex +" Regex that describes a leading operator (only a method call's dot for now) +let s:leading_operator_regex = '^\s*[.]' + " 2. Auxiliary Functions {{{1 " ====================== @@ -165,7 +201,21 @@ function s:GetMSL(lnum) " Otherwise, terminate search as we have found our MSL already. let line = getline(lnum) - if s:Match(lnum, s:splat_regex) + if !s:Match(msl, s:backslash_continuation_regex) && + \ s:Match(lnum, s:backslash_continuation_regex) + " If the current line doesn't end in a backslash, but the previous one + " does, look for that line's msl + " + " Example: + " foo = "bar" \ + " "baz" + " + let msl = lnum + elseif s:Match(msl, s:leading_operator_regex) + " If the current line starts with a leading operator, keep its indent + " and keep looking for an MSL. + let msl = lnum + elseif s:Match(lnum, s:splat_regex) " If the above line looks like the "*" of a splat, use the current one's " indentation. " @@ -175,7 +225,7 @@ function s:GetMSL(lnum) " something " return msl - elseif s:Match(line, s:non_bracket_continuation_regex) && + elseif s:Match(lnum, s:non_bracket_continuation_regex) && \ s:Match(msl, s:non_bracket_continuation_regex) " If the current line is a non-bracket continuation and so is the " previous one, keep its indent and continue looking for an MSL. @@ -186,6 +236,18 @@ function s:GetMSL(lnum) " three " let msl = lnum + elseif s:Match(lnum, s:dot_continuation_regex) && + \ (s:Match(msl, s:bracket_continuation_regex) || s:Match(msl, s:block_continuation_regex)) + " If the current line is a bracket continuation or a block-starter, but + " the previous is a dot, keep going to see if the previous line is the + " start of another continuation. + " + " Example: + " parent. + " method_call { + " three + " + let msl = lnum elseif s:Match(lnum, s:non_bracket_continuation_regex) && \ (s:Match(msl, s:bracket_continuation_regex) || s:Match(msl, s:block_continuation_regex)) " If the current line is a bracket continuation or a block-starter, but @@ -299,18 +361,39 @@ function s:ExtraBrackets(lnum) endfunction function s:Match(lnum, regex) - let col = match(getline(a:lnum), '\C'.a:regex) + 1 - return col > 0 && !s:IsInStringOrComment(a:lnum, col) ? col : 0 + let line = getline(a:lnum) + let offset = match(line, '\C'.a:regex) + let col = offset + 1 + + while offset > -1 && s:IsInStringOrComment(a:lnum, col) + let offset = match(line, '\C'.a:regex, offset + 1) + let col = offset + 1 + endwhile + + if offset > -1 + return col + else + return 0 + endif endfunction -function s:MatchLast(lnum, regex) - let line = getline(a:lnum) - let col = match(line, '.*\zs' . a:regex) - while col != -1 && s:IsInStringOrComment(a:lnum, col) - let line = strpart(line, 0, col) - let col = match(line, '.*' . a:regex) +" Locates the containing class/module's definition line, ignoring nested classes +" along the way. +" +function! s:FindContainingClass() + let saved_position = getpos('.') + + while searchpair(s:end_start_regex, s:end_middle_regex, s:end_end_regex, 'bW', + \ s:end_skip_expr) > 0 + if expand('<cword>') =~# '\<class\|module\>' + let found_lnum = line('.') + call setpos('.', saved_position) + return found_lnum + endif endwhile - return col + 1 + + call setpos('.', saved_position) + return 0 endfunction " 3. GetRubyIndent Function {{{1 @@ -320,6 +403,13 @@ function GetRubyIndent(...) " 3.1. Setup {{{2 " ---------- + " The value of a single shift-width + if exists('*shiftwidth') + let sw = shiftwidth() + else + let sw = &sw + endif + " For the current line, use the first argument if given, else v:lnum let clnum = a:0 ? a:1 : v:lnum @@ -333,6 +423,24 @@ function GetRubyIndent(...) let line = getline(clnum) let ind = -1 + " If this line is an access modifier keyword, align according to the closest + " class declaration. + if g:ruby_indent_access_modifier_style == 'indent' + if s:Match(clnum, s:access_modifier_regex) + let class_line = s:FindContainingClass() + if class_line > 0 + return indent(class_line) + sw + endif + endif + elseif g:ruby_indent_access_modifier_style == 'outdent' + if s:Match(clnum, s:access_modifier_regex) + let class_line = s:FindContainingClass() + if class_line > 0 + return indent(class_line) + endif + endif + endif + " If we got a closing bracket on an empty line, find its match and indent " according to it. For parentheses we indent to its column - 1, for the " others we indent to the containing line's MSL's level. Return -1 if fail. @@ -343,7 +451,9 @@ function GetRubyIndent(...) if searchpair(escape(bs[0], '\['), '', bs[1], 'bW', s:skip_expr) > 0 if line[col-1]==')' && col('.') != col('$') - 1 let ind = virtcol('.') - 1 - else + elseif g:ruby_indent_block_style == 'do' + let ind = indent(line('.')) + else " g:ruby_indent_block_style == 'expression' let ind = indent(s:GetMSL(line('.'))) endif endif @@ -366,10 +476,17 @@ function GetRubyIndent(...) if strpart(line, 0, col('.') - 1) =~ '=\s*$' && \ strpart(line, col('.') - 1, 2) !~ 'do' + " assignment to case/begin/etc, on the same line, hanging indent let ind = virtcol('.') - 1 + elseif g:ruby_indent_block_style == 'do' + " align to line of the "do", not to the MSL + let ind = indent(line('.')) elseif getline(msl) =~ '=\s*\(#.*\)\=$' + " in the case of assignment to the MSL, align to the starting line, + " not to the MSL let ind = indent(line('.')) else + " align to the MSL let ind = indent(msl) endif endif @@ -389,6 +506,11 @@ function GetRubyIndent(...) return 0 endif + " If the current line starts with a leading operator, add a level of indent. + if s:Match(clnum, s:leading_operator_regex) + return indent(s:GetMSL(clnum)) + sw + endif + " 3.3. Work on the previous line. {{{2 " ------------------------------- @@ -409,14 +531,50 @@ function GetRubyIndent(...) let line = getline(lnum) let ind = indent(lnum) + if g:ruby_indent_access_modifier_style == 'indent' + " If the previous line was a private/protected keyword, add a + " level of indent. + if s:Match(lnum, s:indent_access_modifier_regex) + return indent(lnum) + sw + endif + elseif g:ruby_indent_access_modifier_style == 'outdent' + " If the previous line was a private/protected/public keyword, add + " a level of indent, since the keyword has been out-dented. + if s:Match(lnum, s:access_modifier_regex) + return indent(lnum) + sw + endif + endif + + if s:Match(lnum, s:continuable_regex) && s:Match(lnum, s:continuation_regex) + return indent(s:GetMSL(lnum)) + sw + sw + endif + " If the previous line ended with a block opening, add a level of indent. if s:Match(lnum, s:block_regex) - return indent(s:GetMSL(lnum)) + &sw + let msl = s:GetMSL(lnum) + + if g:ruby_indent_block_style == 'do' + " don't align to the msl, align to the "do" + let ind = indent(lnum) + sw + elseif getline(msl) =~ '=\s*\(#.*\)\=$' + " in the case of assignment to the msl, align to the starting line, + " not to the msl + let ind = indent(lnum) + sw + else + let ind = indent(msl) + sw + endif + return ind + endif + + " If the previous line started with a leading operator, use its MSL's level + " of indent + if s:Match(lnum, s:leading_operator_regex) + return indent(s:GetMSL(lnum)) endif " If the previous line ended with the "*" of a splat, add a level of indent if line =~ s:splat_regex - return indent(lnum) + &sw + return indent(lnum) + sw endif " If the previous line contained unclosed opening brackets and we are still @@ -431,22 +589,22 @@ function GetRubyIndent(...) if opening.pos != -1 if opening.type == '(' && searchpair('(', '', ')', 'bW', s:skip_expr) > 0 if col('.') + 1 == col('$') - return ind + &sw + return ind + sw else return virtcol('.') endif else let nonspace = matchend(line, '\S', opening.pos + 1) - 1 - return nonspace > 0 ? nonspace : ind + &sw + return nonspace > 0 ? nonspace : ind + sw endif elseif closing.pos != -1 call cursor(lnum, closing.pos + 1) normal! % if s:Match(line('.'), s:ruby_indent_keywords) - return indent('.') + &sw + return indent('.') + sw else - return indent('.') + return indent(s:GetMSL(line('.'))) endif else call cursor(clnum, vcol) @@ -473,7 +631,7 @@ function GetRubyIndent(...) let col = s:Match(lnum, s:ruby_indent_keywords) if col > 0 call cursor(lnum, col) - let ind = virtcol('.') - 1 + &sw + let ind = virtcol('.') - 1 + sw " TODO: make this better (we need to count them) (or, if a searchpair " fails, we know that something is lacking an end and thus we indent a " level @@ -490,10 +648,14 @@ function GetRubyIndent(...) let p_lnum = lnum let lnum = s:GetMSL(lnum) - " If the previous line wasn't a MSL and is continuation return its indent. - " TODO: the || s:IsInString() thing worries me a bit. + " If the previous line wasn't a MSL. if p_lnum != lnum - if s:Match(p_lnum, s:non_bracket_continuation_regex) || s:IsInString(p_lnum,strlen(line)) + " If previous line ends bracket and begins non-bracket continuation decrease indent by 1. + if s:Match(p_lnum, s:bracket_switch_continuation_regex) + return ind - 1 + " If previous line is a continuation return its indent. + " TODO: the || s:IsInString() thing worries me a bit. + elseif s:Match(p_lnum, s:non_bracket_continuation_regex) || s:IsInString(p_lnum,strlen(line)) return ind endif endif @@ -506,9 +668,9 @@ function GetRubyIndent(...) " TODO: this does not take into account contrived things such as " module Foo; class Bar; end if s:Match(lnum, s:ruby_indent_keywords) - let ind = msl_ind + &sw + let ind = msl_ind + sw if s:Match(lnum, s:end_end_regex) - let ind = ind - &sw + let ind = ind - sw endif return ind endif @@ -517,7 +679,7 @@ function GetRubyIndent(...) " closing bracket, indent one extra level. if s:Match(lnum, s:non_bracket_continuation_regex) && !s:Match(lnum, '^\s*\([\])}]\|end\)') if lnum == p_lnum - let ind = msl_ind + &sw + let ind = msl_ind + sw else let ind = msl_ind endif diff --git a/runtime/indent/sass.vim b/runtime/indent/sass.vim index b6e2e66e8a..d87b371fdd 100644 --- a/runtime/indent/sass.vim +++ b/runtime/indent/sass.vim @@ -1,7 +1,7 @@ " Vim indent file " Language: Sass " Maintainer: Tim Pope <vimNOSPAM@tpope.org> -" Last Change: 2013 May 30 +" Last Change: 2016 Aug 29 if exists("b:did_indent") finish @@ -29,9 +29,7 @@ function! GetSassIndent() let indent = indent(lnum) let cindent = indent(v:lnum) if line !~ s:property && line !~ s:extend && cline =~ s:property - return indent + &sw - "elseif line =~ s:property && cline !~ s:property - "return indent - &sw + return indent + (exists('*shiftwidth') ? shiftwidth() : &sw) else return -1 endif diff --git a/runtime/indent/scala.vim b/runtime/indent/scala.vim new file mode 100644 index 0000000000..f97c79bbab --- /dev/null +++ b/runtime/indent/scala.vim @@ -0,0 +1,609 @@ +" Vim indent file +" Language: Scala (http://scala-lang.org/) +" Original Author: Stefan Matthias Aust +" Modifications By: Derek Wyatt +" URL: https://github.com/derekwyatt/vim-scala +" Last Change: 2016 Aug 26 + +if exists("b:did_indent") + finish +endif +let b:did_indent = 1 + +setlocal autoindent +setlocal indentexpr=GetScalaIndent() +setlocal indentkeys=0{,0},0),!^F,<>>,o,O,e,=case,<CR> + +if exists("*GetScalaIndent") + finish +endif +let s:keepcpo= &cpo +set cpo&vim + +let s:defMatcher = '\%(\%(private\|protected\)\%(\[[^\]]*\]\)\?\s\+\|abstract\s\+\|override\s\+\)*\<def\>' +let s:funcNameMatcher = '\w\+' +let s:typeSpecMatcher = '\%(\s*\[\_[^\]]*\]\)' +let s:defArgMatcher = '\%((\_.\{-})\)' +let s:returnTypeMatcher = '\%(:\s*\w\+' . s:typeSpecMatcher . '\?\)' +let g:fullDefMatcher = '^\s*' . s:defMatcher . '\s\+' . s:funcNameMatcher . '\s*' . s:typeSpecMatcher . '\?\s*' . s:defArgMatcher . '\?\s*' . s:returnTypeMatcher . '\?\s*[={]' + +function! scala#ConditionalConfirm(msg) + if 0 + call confirm(a:msg) + endif +endfunction + +function! scala#GetLine(lnum) + let line = substitute(getline(a:lnum), '//.*$', '', '') + let line = substitute(line, '"\(.\|\\"\)\{-}"', '""', 'g') + return line +endfunction + +function! scala#CountBrackets(line, openBracket, closedBracket) + let line = substitute(a:line, '"\(.\|\\"\)\{-}"', '', 'g') + let open = substitute(line, '[^' . a:openBracket . ']', '', 'g') + let close = substitute(line, '[^' . a:closedBracket . ']', '', 'g') + return strlen(open) - strlen(close) +endfunction + +function! scala#CountParens(line) + return scala#CountBrackets(a:line, '(', ')') +endfunction + +function! scala#CountCurlies(line) + return scala#CountBrackets(a:line, '{', '}') +endfunction + +function! scala#LineEndsInIncomplete(line) + if a:line =~ '[.,]\s*$' + return 1 + else + return 0 + endif +endfunction + +function! scala#LineIsAClosingXML(line) + if a:line =~ '^\s*</\w' + return 1 + else + return 0 + endif +endfunction + +function! scala#LineCompletesXML(lnum, line) + let savedpos = getpos('.') + call setpos('.', [savedpos[0], a:lnum, 0, savedpos[3]]) + let tag = substitute(a:line, '^.*</\([^>]*\)>.*$', '\1', '') + let [lineNum, colnum] = searchpairpos('<' . tag . '>', '', '</' . tag . '>', 'Wbn') + call setpos('.', savedpos) + let pline = scala#GetLine(prevnonblank(lineNum - 1)) + if pline =~ '=\s*$' + return 1 + else + return 0 + endif +endfunction + +function! scala#IsParentCase() + let savedpos = getpos('.') + call setpos('.', [savedpos[0], savedpos[1], 0, savedpos[3]]) + let [l, c] = searchpos('^\s*\%(' . s:defMatcher . '\|\%(\<case\>\)\)', 'bnW') + let retvalue = -1 + if l != 0 && search('\%' . l . 'l\s*\<case\>', 'bnW') + let retvalue = l + endif + call setpos('.', savedpos) + return retvalue +endfunction + +function! scala#CurlyMatcher() + let matchline = scala#GetLineThatMatchesBracket('{', '}') + if scala#CountParens(scala#GetLine(matchline)) < 0 + let savedpos = getpos('.') + call setpos('.', [savedpos[0], matchline, 9999, savedpos[3]]) + call searchpos('{', 'Wbc') + call searchpos(')', 'Wb') + let [lnum, colnum] = searchpairpos('(', '', ')', 'Wbn') + call setpos('.', savedpos) + let line = scala#GetLine(lnum) + if line =~ '^\s*' . s:defMatcher + return lnum + else + return matchline + endif + else + return matchline + endif +endfunction + +function! scala#GetLineAndColumnThatMatchesCurly() + return scala#GetLineAndColumnThatMatchesBracket('{', '}') +endfunction + +function! scala#GetLineAndColumnThatMatchesParen() + return scala#GetLineAndColumnThatMatchesBracket('(', ')') +endfunction + +function! scala#GetLineAndColumnThatMatchesBracket(openBracket, closedBracket) + let savedpos = getpos('.') + let curline = scala#GetLine(line('.')) + if curline =~ a:closedBracket . '.*' . a:openBracket . '.*' . a:closedBracket + call setpos('.', [savedpos[0], savedpos[1], 0, savedpos[3]]) + call searchpos(a:closedBracket . '\ze[^' . a:closedBracket . a:openBracket . ']*' . a:openBracket, 'W') + else + call setpos('.', [savedpos[0], savedpos[1], 9999, savedpos[3]]) + call searchpos(a:closedBracket, 'Wbc') + endif + let [lnum, colnum] = searchpairpos(a:openBracket, '', a:closedBracket, 'Wbn') + call setpos('.', savedpos) + return [lnum, colnum] +endfunction + +function! scala#GetLineThatMatchesCurly() + return scala#GetLineThatMatchesBracket('{', '}') +endfunction + +function! scala#GetLineThatMatchesParen() + return scala#GetLineThatMatchesBracket('(', ')') +endfunction + +function! scala#GetLineThatMatchesBracket(openBracket, closedBracket) + let [lnum, colnum] = scala#GetLineAndColumnThatMatchesBracket(a:openBracket, a:closedBracket) + return lnum +endfunction + +function! scala#NumberOfBraceGroups(line) + let line = substitute(a:line, '[^()]', '', 'g') + if strlen(line) == 0 + return 0 + endif + let line = substitute(line, '^)*', '', 'g') + if strlen(line) == 0 + return 0 + endif + let line = substitute(line, '^(', '', 'g') + if strlen(line) == 0 + return 0 + endif + let c = 1 + let counter = 0 + let groupCount = 0 + while counter < strlen(line) + let char = strpart(line, counter, 1) + if char == '(' + let c = c + 1 + elseif char == ')' + let c = c - 1 + endif + if c == 0 + let groupCount = groupCount + 1 + endif + let counter = counter + 1 + endwhile + return groupCount +endfunction + +function! scala#MatchesIncompleteDefValr(line) + if a:line =~ '^\s*\%(' . s:defMatcher . '\|\<va[lr]\>\).*[=({]\s*$' + return 1 + else + return 0 + endif +endfunction + +function! scala#LineIsCompleteIf(line) + if scala#CountBrackets(a:line, '{', '}') == 0 && + \ scala#CountBrackets(a:line, '(', ')') == 0 && + \ a:line =~ '^\s*\<if\>\s*([^)]*)\s*\S.*$' + return 1 + else + return 0 + endif +endfunction + +function! scala#LineCompletesIfElse(lnum, line) + if a:line =~ '^\s*\%(\<if\>\|\%(}\s*\)\?\<else\>\)' + return 0 + endif + let result = search('^\%(\s*\<if\>\s*(.*).*\n\|\s*\<if\>\s*(.*)\s*\n.*\n\)\%(\s*\<else\>\s*\<if\>\s*(.*)\s*\n.*\n\)*\%(\s*\<else\>\s*\n\|\s*\<else\>[^{]*\n\)\?\%' . a:lnum . 'l', 'Wbn') + if result != 0 && scala#GetLine(prevnonblank(a:lnum - 1)) !~ '{\s*$' + return result + endif + return 0 +endfunction + +function! scala#GetPrevCodeLine(lnum) + " This needs to skip comment lines + return prevnonblank(a:lnum - 1) +endfunction + +function! scala#InvertBracketType(openBracket, closedBracket) + if a:openBracket == '(' + return [ '{', '}' ] + else + return [ '(', ')' ] + endif +endfunction + +function! scala#Testhelper(lnum, line, openBracket, closedBracket, iteration) + let bracketCount = scala#CountBrackets(a:line, a:openBracket, a:closedBracket) + " There are more '}' braces than '{' on this line so it may be completing the function definition + if bracketCount < 0 + let [matchedLNum, matchedColNum] = scala#GetLineAndColumnThatMatchesBracket(a:openBracket, a:closedBracket) + if matchedLNum == a:lnum + return -1 + endif + let matchedLine = scala#GetLine(matchedLNum) + if ! scala#MatchesIncompleteDefValr(matchedLine) + let bracketLine = substitute(substitute(matchedLine, '\%' . matchedColNum . 'c.*$', '', ''), '[^{}()]', '', 'g') + if bracketLine =~ '}$' + return scala#Testhelper(matchedLNum, matchedLine, '{', '}', a:iteration + 1) + elseif bracketLine =~ ')$' + return scala#Testhelper(matchedLNum, matchedLine, '(', ')', a:iteration + 1) + else + let prevCodeLNum = scala#GetPrevCodeLine(matchedLNum) + if scala#MatchesIncompleteDefValr(scala#GetLine(prevCodeLNum)) + return prevCodeLNum + else + return -1 + endif + endif + else + " return indent value instead + return matchedLNum + endif + " There's an equal number of '{' and '}' on this line so it may be a single line function definition + elseif bracketCount == 0 + if a:iteration == 0 + let otherBracketType = scala#InvertBracketType(a:openBracket, a:closedBracket) + return scala#Testhelper(a:lnum, a:line, otherBracketType[0], otherBracketType[1], a:iteration + 1) + else + let prevCodeLNum = scala#GetPrevCodeLine(a:lnum) + let prevCodeLine = scala#GetLine(prevCodeLNum) + if scala#MatchesIncompleteDefValr(prevCodeLine) && prevCodeLine !~ '{\s*$' + return prevCodeLNum + else + let possibleIfElse = scala#LineCompletesIfElse(a:lnum, a:line) + if possibleIfElse != 0 + let defValrLine = prevnonblank(possibleIfElse - 1) + let possibleDefValr = scala#GetLine(defValrLine) + if scala#MatchesIncompleteDefValr(possibleDefValr) && possibleDefValr =~ '^.*=\s*$' + return possibleDefValr + else + return -1 + endif + else + return -1 + endif + endif + endif + else + return -1 + endif +endfunction + +function! scala#Test(lnum, line, openBracket, closedBracket) + return scala#Testhelper(a:lnum, a:line, a:openBracket, a:closedBracket, 0) +endfunction + +function! scala#LineCompletesDefValr(lnum, line) + let bracketCount = scala#CountBrackets(a:line, '{', '}') + if bracketCount < 0 + let matchedBracket = scala#GetLineThatMatchesBracket('{', '}') + if ! scala#MatchesIncompleteDefValr(scala#GetLine(matchedBracket)) + let possibleDefValr = scala#GetLine(prevnonblank(matchedBracket - 1)) + if matchedBracket != -1 && scala#MatchesIncompleteDefValr(possibleDefValr) + return 1 + else + return 0 + endif + else + return 0 + endif + elseif bracketCount == 0 + let bracketCount = scala#CountBrackets(a:line, '(', ')') + if bracketCount < 0 + let matchedBracket = scala#GetLineThatMatchesBracket('(', ')') + if ! scala#MatchesIncompleteDefValr(scala#GetLine(matchedBracket)) + let possibleDefValr = scala#GetLine(prevnonblank(matchedBracket - 1)) + if matchedBracket != -1 && scala#MatchesIncompleteDefValr(possibleDefValr) + return 1 + else + return 0 + endif + else + return 0 + endif + elseif bracketCount == 0 + let possibleDefValr = scala#GetLine(prevnonblank(a:lnum - 1)) + if scala#MatchesIncompleteDefValr(possibleDefValr) && possibleDefValr =~ '^.*=\s*$' + return 1 + else + let possibleIfElse = scala#LineCompletesIfElse(a:lnum, a:line) + if possibleIfElse != 0 + let possibleDefValr = scala#GetLine(prevnonblank(possibleIfElse - 1)) + if scala#MatchesIncompleteDefValr(possibleDefValr) && possibleDefValr =~ '^.*=\s*$' + return 2 + else + return 0 + endif + else + return 0 + endif + endif + else + return 0 + endif + endif +endfunction + +function! scala#SpecificLineCompletesBrackets(lnum, openBracket, closedBracket) + let savedpos = getpos('.') + call setpos('.', [savedpos[0], a:lnum, 9999, savedpos[3]]) + let retv = scala#LineCompletesBrackets(a:openBracket, a:closedBracket) + call setpos('.', savedpos) + + return retv +endfunction + +function! scala#LineCompletesBrackets(openBracket, closedBracket) + let savedpos = getpos('.') + let offline = 0 + while offline == 0 + let [lnum, colnum] = searchpos(a:closedBracket, 'Wb') + let [lnumA, colnumA] = searchpairpos(a:openBracket, '', a:closedBracket, 'Wbn') + if lnum != lnumA + let [lnumB, colnumB] = searchpairpos(a:openBracket, '', a:closedBracket, 'Wbnr') + let offline = 1 + endif + endwhile + call setpos('.', savedpos) + if lnumA == lnumB && colnumA == colnumB + return lnumA + else + return -1 + endif +endfunction + +function! GetScalaIndent() + " Find a non-blank line above the current line. + let prevlnum = prevnonblank(v:lnum - 1) + + " Hit the start of the file, use zero indent. + if prevlnum == 0 + return 0 + endif + + let ind = indent(prevlnum) + let originalIndentValue = ind + let prevline = scala#GetLine(prevlnum) + let curlnum = v:lnum + let curline = scala#GetLine(curlnum) + if get(g:, 'scala_scaladoc_indent', 0) + let star_indent = 2 + else + let star_indent = 1 + end + + if prevline =~ '^\s*/\*\*' + if prevline =~ '\*/\s*$' + return ind + else + return ind + star_indent + endif + endif + + if curline =~ '^\s*\*' + return cindent(curlnum) + endif + + " If this line starts with a { then make it indent the same as the previous line + if curline =~ '^\s*{' + call scala#ConditionalConfirm("1") + " Unless, of course, the previous one is a { as well + if prevline !~ '^\s*{' + call scala#ConditionalConfirm("2") + return indent(prevlnum) + endif + endif + + " '.' continuations + if curline =~ '^\s*\.' + if prevline =~ '^\s*\.' + return ind + else + return ind + &shiftwidth + endif + endif + + " Indent html literals + if prevline !~ '/>\s*$' && prevline =~ '^\s*<[a-zA-Z][^>]*>\s*$' + call scala#ConditionalConfirm("3") + return ind + &shiftwidth + endif + + " assumes curly braces around try-block + if curline =~ '^\s*}\s*\<catch\>' + return ind - &shiftwidth + elseif curline =~ '^\s*\<catch\>' + return ind + endif + + " Add a 'shiftwidth' after lines that start a block + " If 'if', 'for' or 'while' end with ), this is a one-line block + " If 'val', 'var', 'def' end with =, this is a one-line block + if (prevline =~ '^\s*\<\%(\%(}\?\s*else\s\+\)\?if\|for\|while\)\>.*[)=]\s*$' && scala#NumberOfBraceGroups(prevline) <= 1) + \ || prevline =~ '^\s*' . s:defMatcher . '.*=\s*$' + \ || prevline =~ '^\s*\<va[lr]\>.*[=]\s*$' + \ || prevline =~ '^\s*\%(}\s*\)\?\<else\>\s*$' + \ || prevline =~ '=\s*$' + call scala#ConditionalConfirm("4") + let ind = ind + &shiftwidth + elseif prevline =~ '^\s*\<\%(}\?\s*else\s\+\)\?if\>' && curline =~ '^\s*}\?\s*\<else\>' + return ind + endif + + let lineCompletedBrackets = 0 + let bracketCount = scala#CountBrackets(prevline, '{', '}') + if bracketCount > 0 || prevline =~ '.*{\s*$' + call scala#ConditionalConfirm("5b") + let ind = ind + &shiftwidth + elseif bracketCount < 0 + call scala#ConditionalConfirm("6b") + " if the closing brace actually completes the braces entirely, then we + " have to indent to line that started the whole thing + let completeLine = scala#LineCompletesBrackets('{', '}') + if completeLine != -1 + call scala#ConditionalConfirm("8b") + let prevCompleteLine = scala#GetLine(prevnonblank(completeLine - 1)) + " However, what actually started this part looks like it was a function + " definition, so we need to indent to that line instead. This is + " actually pretty weak at the moment. + if prevCompleteLine =~ '=\s*$' + call scala#ConditionalConfirm("9b") + let ind = indent(prevnonblank(completeLine - 1)) + else + call scala#ConditionalConfirm("10b") + let ind = indent(completeLine) + endif + else + let lineCompletedBrackets = 1 + endif + endif + + if ind == originalIndentValue + let bracketCount = scala#CountBrackets(prevline, '(', ')') + if bracketCount > 0 || prevline =~ '.*(\s*$' + call scala#ConditionalConfirm("5a") + let ind = ind + &shiftwidth + elseif bracketCount < 0 + call scala#ConditionalConfirm("6a") + " if the closing brace actually completes the braces entirely, then we + " have to indent to line that started the whole thing + let completeLine = scala#LineCompletesBrackets('(', ')') + if completeLine != -1 && prevline !~ '^.*{\s*$' + call scala#ConditionalConfirm("8a") + let prevCompleteLine = scala#GetLine(prevnonblank(completeLine - 1)) + " However, what actually started this part looks like it was a function + " definition, so we need to indent to that line instead. This is + " actually pretty weak at the moment. + if prevCompleteLine =~ '=\s*$' + call scala#ConditionalConfirm("9a") + let ind = indent(prevnonblank(completeLine - 1)) + else + call scala#ConditionalConfirm("10a") + let ind = indent(completeLine) + endif + else + " This is the only part that's different from from the '{', '}' one below + " Yup... some refactoring is necessary at some point. + let ind = ind + (bracketCount * &shiftwidth) + let lineCompletedBrackets = 1 + endif + endif + endif + + if curline =~ '^\s*}\?\s*\<else\>\%(\s\+\<if\>\s*(.*)\)\?\s*{\?\s*$' && + \ ! scala#LineIsCompleteIf(prevline) && + \ prevline !~ '^.*}\s*$' + let ind = ind - &shiftwidth + endif + + " Subtract a 'shiftwidth' on '}' or html + let curCurlyCount = scala#CountCurlies(curline) + if curCurlyCount < 0 + call scala#ConditionalConfirm("14a") + let matchline = scala#CurlyMatcher() + return indent(matchline) + elseif curline =~ '^\s*</[a-zA-Z][^>]*>' + call scala#ConditionalConfirm("14c") + return ind - &shiftwidth + endif + + let prevParenCount = scala#CountParens(prevline) + if prevline =~ '^\s*\<for\>.*$' && prevParenCount > 0 + call scala#ConditionalConfirm("15") + let ind = indent(prevlnum) + 5 + endif + + let prevCurlyCount = scala#CountCurlies(prevline) + if prevCurlyCount == 0 && prevline =~ '^.*\%(=>\|โ\)\s*$' && prevline !~ '^\s*this\s*:.*\%(=>\|โ\)\s*$' && curline !~ '^\s*\<case\>' + call scala#ConditionalConfirm("16") + let ind = ind + &shiftwidth + endif + + if ind == originalIndentValue && curline =~ '^\s*\<case\>' + call scala#ConditionalConfirm("17") + let parentCase = scala#IsParentCase() + if parentCase != -1 + call scala#ConditionalConfirm("17a") + return indent(parentCase) + endif + endif + + if prevline =~ '^\s*\*/' + \ || prevline =~ '*/\s*$' + call scala#ConditionalConfirm("18") + let ind = ind - star_indent + endif + + if scala#LineEndsInIncomplete(prevline) + call scala#ConditionalConfirm("19") + return ind + endif + + if scala#LineIsAClosingXML(prevline) + if scala#LineCompletesXML(prevlnum, prevline) + call scala#ConditionalConfirm("20a") + return ind - &shiftwidth + else + call scala#ConditionalConfirm("20b") + return ind + endif + endif + + if ind == originalIndentValue + "let indentMultiplier = scala#LineCompletesDefValr(prevlnum, prevline) + "if indentMultiplier != 0 + " call scala#ConditionalConfirm("19a") + " let ind = ind - (indentMultiplier * &shiftwidth) + let defValrLine = scala#Test(prevlnum, prevline, '{', '}') + if defValrLine != -1 + call scala#ConditionalConfirm("21a") + let ind = indent(defValrLine) + elseif lineCompletedBrackets == 0 + call scala#ConditionalConfirm("21b") + if scala#GetLine(prevnonblank(prevlnum - 1)) =~ '^.*\<else\>\s*\%(//.*\)\?$' + call scala#ConditionalConfirm("21c") + let ind = ind - &shiftwidth + elseif scala#LineCompletesIfElse(prevlnum, prevline) + call scala#ConditionalConfirm("21d") + let ind = ind - &shiftwidth + elseif scala#CountParens(curline) < 0 && curline =~ '^\s*)' && scala#GetLine(scala#GetLineThatMatchesBracket('(', ')')) =~ '.*(\s*$' + " Handles situations that look like this: + " + " val a = func( + " 10 + " ) + " + " or + " + " val a = func( + " 10 + " ).somethingHere() + call scala#ConditionalConfirm("21e") + let ind = ind - &shiftwidth + endif + endif + endif + + call scala#ConditionalConfirm("returning " . ind) + + return ind +endfunction + +let &cpo = s:keepcpo +unlet s:keepcpo + +" vim:set sw=2 sts=2 ts=8 et: +" vim600:fdm=marker fdl=1 fdc=0: diff --git a/runtime/indent/sh.vim b/runtime/indent/sh.vim index d05bb3770f..aca110f504 100644 --- a/runtime/indent/sh.vim +++ b/runtime/indent/sh.vim @@ -3,9 +3,15 @@ " Maintainer: Christian Brabandt <cb@256bit.org> " Previous Maintainer: Peter Aronoff <telemachus@arpinum.org> " Original Author: Nikolai Weibull <now@bitwi.se> -" Latest Revision: 2016-02-15 +" Latest Revision: 2016-06-27 " License: Vim (see :h license) " Repository: https://github.com/chrisbra/vim-sh-indent +" Changelog: +" 20160627: - detect heredocs correctly +" 20160213: - detect function definition correctly +" 20160202: - use shiftwidth() function +" 20151215: - set b:undo_indent variable +" 20150728: - add foreach detection for zsh if exists("b:did_indent") finish @@ -102,6 +108,8 @@ function! GetShIndent() endif elseif s:is_case_break(line) let ind -= s:indent_value('case-breaks') + elseif s:is_here_doc(line) + let ind = 0 endif return ind @@ -160,6 +168,14 @@ function! s:is_case_break(line) return a:line =~ '^\s*;[;&]' endfunction +function! s:is_here_doc(line) + if a:line =~ '^\w\+$' + let here_pat = '<<-\?'. s:escape(a:line). '\$' + return search(here_pat, 'bnW') > 0 + endif + return 0 +endfunction + function! s:is_case_ended(line) return s:is_case_break(a:line) || a:line =~ ';[;&]\s*\%(#.*\)\=$' endfunction @@ -172,5 +188,9 @@ function! s:is_case_empty(line) endif endfunction +function! s:escape(pattern) + return '\V'. escape(a:pattern, '\\') +endfunction + let &cpo = s:cpo_save unlet s:cpo_save diff --git a/runtime/indent/teraterm.vim b/runtime/indent/teraterm.vim index ba24257b02..8467cefcc0 100644 --- a/runtime/indent/teraterm.vim +++ b/runtime/indent/teraterm.vim @@ -1,9 +1,9 @@ " Vim indent file " Language: Tera Term Language (TTL) -" Based on Tera Term Version 4.86 +" Based on Tera Term Version 4.92 " Maintainer: Ken Takata " URL: https://github.com/k-takata/vim-teraterm -" Last Change: 2015 Jun 4 +" Last Change: 2016 Aug 17 " Filenames: *.ttl " License: VIM License @@ -25,9 +25,7 @@ endif " The shiftwidth() function is relatively new. " Don't require it to exist. if exists('*shiftwidth') - function s:sw() abort - return shiftwidth() - endfunction + let s:sw = function('shiftwidth') else function s:sw() abort return &shiftwidth @@ -48,7 +46,7 @@ function! GetTeraTermIndent(lnum) let l:ind = l:previ - if l:prevl =~ '^\s*if\>.*\<then\s*$' + if l:prevl =~ '^\s*if\>.*\<then\>' " previous line opened a block let l:ind += s:sw() endif diff --git a/runtime/indent/vim.vim b/runtime/indent/vim.vim index 7ec7df849e..8ebfa12caf 100644 --- a/runtime/indent/vim.vim +++ b/runtime/indent/vim.vim @@ -1,7 +1,7 @@ " Vim indent file " Language: Vim script " Maintainer: Bram Moolenaar <Bram@vim.org> -" Last Change: 2016 Apr 19 +" Last Change: 2016 Jun 27 " Only load this indent file when no other was loaded. if exists("b:did_indent") @@ -60,7 +60,7 @@ function GetVimIndentIntern() else let ind = ind + shiftwidth() * 3 endif - elseif prev_text =~ '^\s*aug\%[roup]' && prev_text !~ '^\s*aug\%[roup]\s*!\=\s\+[eE][nN][dD]' + elseif prev_text =~ '^\s*aug\%[roup]\s\+' && prev_text !~ '^\s*aug\%[roup]\s\+[eE][nN][dD]\>' let ind = ind + shiftwidth() else " A line starting with :au does not increment/decrement indent. @@ -89,7 +89,7 @@ function GetVimIndentIntern() " Subtract a 'shiftwidth' on a :endif, :endwhile, :catch, :finally, :endtry, " :endfun, :else and :augroup END. - if cur_text =~ '^\s*\(ene\@!\|cat\|fina\|el\|aug\%[roup]\s*!\=\s\+[eE][nN][dD]\)' + if cur_text =~ '^\s*\(ene\@!\|cat\|fina\|el\|aug\%[roup]\s\+[eE][nN][dD]\)' let ind = ind - shiftwidth() endif diff --git a/runtime/indent/yaml.vim b/runtime/indent/yaml.vim index aa4906ce0a..3201462fbc 100644 --- a/runtime/indent/yaml.vim +++ b/runtime/indent/yaml.vim @@ -37,7 +37,7 @@ function s:FindPrevLessIndentedLine(lnum, ...) let curindent = a:0 ? a:1 : indent(a:lnum) while prevlnum \&& indent(prevlnum) >= curindent - \&& getline(prevlnum) !~# '^\s*#' + \&& getline(prevlnum) =~# '^\s*#' let prevlnum = prevnonblank(prevlnum-1) endwhile return prevlnum @@ -51,11 +51,33 @@ function s:FindPrevLEIndentedLineMatchingRegex(lnum, regex) return plilnum endfunction -let s:mapkeyregex='\v^\s*%(\''%([^'']|'''')*\'''. - \ '|\"%([^"\\]|\\.)*\"'. - \ '|%(%(\:\ )@!.)*)\:%(\ |$)' +let s:mapkeyregex='\v^\s*\#@!\S@=%(\''%([^'']|\''\'')*\'''. + \ '|\"%([^"\\]|\\.)*\"'. + \ '|%(%(\:\ )@!.)*)\:%(\ |$)' let s:liststartregex='\v^\s*%(\-%(\ |$))' +let s:c_ns_anchor_char = '\v%([\n\r\uFEFF \t,[\]{}]@!\p)' +let s:c_ns_anchor_name = s:c_ns_anchor_char.'+' +let s:c_ns_anchor_property = '\v\&'.s:c_ns_anchor_name + +let s:ns_word_char = '\v[[:alnum:]_\-]' +let s:ns_tag_char = '\v%(%\x\x|'.s:ns_word_char.'|[#/;?:@&=+$.~*''()])' +let s:c_named_tag_handle = '\v\!'.s:ns_word_char.'+\!' +let s:c_secondary_tag_handle = '\v\!\!' +let s:c_primary_tag_handle = '\v\!' +let s:c_tag_handle = '\v%('.s:c_named_tag_handle. + \ '|'.s:c_secondary_tag_handle. + \ '|'.s:c_primary_tag_handle.')' +let s:c_ns_shorthand_tag = '\v'.s:c_tag_handle . s:ns_tag_char.'+' +let s:c_non_specific_tag = '\v\!' +let s:ns_uri_char = '\v%(%\x\x|'.s:ns_word_char.'\v|[#/;?:@&=+$,.!~*''()[\]])' +let s:c_verbatim_tag = '\v\!\<'.s:ns_uri_char.'+\>' +let s:c_ns_tag_property = '\v'.s:c_verbatim_tag. + \ '\v|'.s:c_ns_shorthand_tag. + \ '\v|'.s:c_non_specific_tag + +let s:block_scalar_header = '\v[|>]%([+-]?[1-9]|[1-9]?[+-])?' + function GetYAMLIndent(lnum) if a:lnum == 1 || !prevnonblank(a:lnum-1) return 0 @@ -127,7 +149,10 @@ function GetYAMLIndent(lnum) " - List with " multiline scalar return previndent+2 - elseif prevline =~# s:mapkeyregex + elseif prevline =~# s:mapkeyregex . '\v\s*%(%('.s:c_ns_tag_property. + \ '\v|'.s:c_ns_anchor_property. + \ '\v|'.s:block_scalar_header. + \ '\v)%(\s+|\s*%(\#.*)?$))*' " Mapping with: value " that is multiline scalar return previndent+s:shiftwidth() diff --git a/runtime/keymap/armenian-eastern_utf-8.vim b/runtime/keymap/armenian-eastern_utf-8.vim index 7b03c5ac73..eaa60a77f8 100644 --- a/runtime/keymap/armenian-eastern_utf-8.vim +++ b/runtime/keymap/armenian-eastern_utf-8.vim @@ -1,5 +1,5 @@ " Maintainer: Benjamin Linskey <vim@benlinskey.com> -" Last Changed: 2016 July 20 +" Last Changed: 2016 December 5 " URL: https://github.com/blinskey/vim-armenian-keymaps let b:keymap_name = "hy" @@ -98,6 +98,8 @@ f ึ 7 . 8 ยซ 9 ยป +* ( +( ) \\ ' | ี diff --git a/runtime/keymap/armenian-western_utf-8.vim b/runtime/keymap/armenian-western_utf-8.vim index e02485ed8c..cf3efdc00f 100644 --- a/runtime/keymap/armenian-western_utf-8.vim +++ b/runtime/keymap/armenian-western_utf-8.vim @@ -1,5 +1,5 @@ " Maintainer: Benjamin Linskey <vim@benlinskey.com> -" Last Changed: 2016 July 20 +" Last Changed: 2016 December 5 " URL: https://github.com/blinskey/vim-armenian-keymaps let b:keymap_name = "hy" @@ -98,6 +98,8 @@ f ึ 7 . 8 ยซ 9 ยป +* ( +( ) \\ ' | ี diff --git a/runtime/keymap/kazakh-jcuken.vim b/runtime/keymap/kazakh-jcuken.vim new file mode 100644 index 0000000000..63d122d112 --- /dev/null +++ b/runtime/keymap/kazakh-jcuken.vim @@ -0,0 +1,102 @@ +" Vim Keymap file for kazakh characters, layout 'jcuken', classical variant + +" Derived from russian-jcuken.vim by Artem Chuprina <ran@ran.pp.ru> +" Maintainer: Darkhan Kubigenov <darkhanu@gmail.com> +" Last Changed: 2016 Oct 25 + +" All characters are given literally, conversion to another encoding (e.g., +" UTF-8) should work. +scriptencoding utf-8 + +let b:keymap_name = "kk" + +loadkeymap +~ ) CYRILLIC CAPITAL LETTER IO +` ( CYRILLIC SMALL LETTER IO +F ะ CYRILLIC CAPITAL LETTER A +< ะ CYRILLIC CAPITAL LETTER BE +D ะ CYRILLIC CAPITAL LETTER VE +U ะ CYRILLIC CAPITAL LETTER GHE +L ะ CYRILLIC CAPITAL LETTER DE +T ะ CYRILLIC CAPITAL LETTER IE +: ะ CYRILLIC CAPITAL LETTER ZHE +P ะ CYRILLIC CAPITAL LETTER ZE +B ะ CYRILLIC CAPITAL LETTER I +Q ะ CYRILLIC CAPITAL LETTER SHORT I +R ะ CYRILLIC CAPITAL LETTER KA +K ะ CYRILLIC CAPITAL LETTER EL +V ะ CYRILLIC CAPITAL LETTER EM +Y ะ CYRILLIC CAPITAL LETTER EN +J ะ CYRILLIC CAPITAL LETTER O +G ะ CYRILLIC CAPITAL LETTER PE +H ะ CYRILLIC CAPITAL LETTER ER +C ะก CYRILLIC CAPITAL LETTER ES +N ะข CYRILLIC CAPITAL LETTER TE +E ะฃ CYRILLIC CAPITAL LETTER U +A ะค CYRILLIC CAPITAL LETTER EF +{ ะฅ CYRILLIC CAPITAL LETTER HA +W ะฆ CYRILLIC CAPITAL LETTER TSE +X ะง CYRILLIC CAPITAL LETTER CHE +I ะจ CYRILLIC CAPITAL LETTER SHA +O ะฉ CYRILLIC CAPITAL LETTER SHCHA +} ะช CYRILLIC CAPITAL LETTER HARD SIGN +S ะซ CYRILLIC CAPITAL LETTER YERU +M ะฌ CYRILLIC CAPITAL LETTER SOFT SIGN +\" ะญ CYRILLIC CAPITAL LETTER E +> ะฎ CYRILLIC CAPITAL LETTER YU +Z ะฏ CYRILLIC CAPITAL LETTER YA +f ะฐ CYRILLIC SMALL LETTER A +, ะฑ CYRILLIC SMALL LETTER BE +d ะฒ CYRILLIC SMALL LETTER VE +u ะณ CYRILLIC SMALL LETTER GHE +l ะด CYRILLIC SMALL LETTER DE +t ะต CYRILLIC SMALL LETTER IE +; ะถ CYRILLIC SMALL LETTER ZHE +p ะท CYRILLIC SMALL LETTER ZE +b ะธ CYRILLIC SMALL LETTER I +q ะน CYRILLIC SMALL LETTER SHORT I +r ะบ CYRILLIC SMALL LETTER KA +k ะป CYRILLIC SMALL LETTER EL +v ะผ CYRILLIC SMALL LETTER EM +y ะฝ CYRILLIC SMALL LETTER EN +j ะพ CYRILLIC SMALL LETTER O +g ะฟ CYRILLIC SMALL LETTER PE +h ั CYRILLIC SMALL LETTER ER +c ั CYRILLIC SMALL LETTER ES +n ั CYRILLIC SMALL LETTER TE +e ั CYRILLIC SMALL LETTER U +a ั CYRILLIC SMALL LETTER EF +[ ั
CYRILLIC SMALL LETTER HA +w ั CYRILLIC SMALL LETTER TSE +x ั CYRILLIC SMALL LETTER CHE +i ั CYRILLIC SMALL LETTER SHA +o ั CYRILLIC SMALL LETTER SHCHA +] ั CYRILLIC SMALL LETTER HARD SIGN +s ั CYRILLIC SMALL LETTER YERU +m ั CYRILLIC SMALL LETTER SOFT SIGN +' ั CYRILLIC SMALL LETTER E +. ั CYRILLIC SMALL LETTER YU +z ั CYRILLIC SMALL LETTER YA +@ ำ CYRILLIC CAPITAL LETTER SCHWA +# ะ CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I +$ าข CYRILLIC CAPITAL LETTER EN WITH DESCENDER +% า CYRILLIC CAPITAL LETTER GHE WITH STROKE +^ ; +& : +* าฎ CYRILLIC CAPITAL LETTER STRAIGHT U +( าฐ CYRILLIC CAPITAL LETTER STRAIGHT U WITH STROKE +) า CYRILLIC CAPITAL LETTER KA WITH DESCENDER +_ ำจ CYRILLIC CAPITAL LETTER BARRED O ++ าบ CYRILLIC CAPITAL LETTER SHHA +1 " +2 ำ CYRILLIC SMALL LETTER SCHWA +3 ั CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I +4 าฃ CYRILLIC SMALL LETTER EN WITH DESCENDER +5 า CYRILLIC SMALL LETTER GHE WITH STROKE +6 , +7 . +8 าฏ CYRILLIC SMALL LETTER STRAIGHT U +9 าฑ CYRILLIC SMALL LETTER STRAIGHT U WITH STROKE +0 า CYRILLIC SMALL LETTER KA WITH DESCENDER +- ำฉ CYRILLIC SMALL LETTER BARRED O += าป CYRILLIC SMALL LETTER SHHA diff --git a/runtime/keymap/pinyin.vim b/runtime/keymap/pinyin.vim index 757850b83f..253814c753 100644 --- a/runtime/keymap/pinyin.vim +++ b/runtime/keymap/pinyin.vim @@ -1,5 +1,5 @@ " Vim Keymap file for Hanyu Pinyin tone marks through numbers. -" Maintainer: Fredrik Roubert <roubert@df.lth.se> +" Maintainer: Fredrik Roubert <fredrik@roubert.name> " Last Changed: February 15, 2004 " All characters are given literally. diff --git a/runtime/keymap/russian-jcukenmac.vim b/runtime/keymap/russian-jcukenmac.vim new file mode 100644 index 0000000000..e2120ca1d4 --- /dev/null +++ b/runtime/keymap/russian-jcukenmac.vim @@ -0,0 +1,94 @@ +" Vim Keymap file for russian characters, layout 'jcuken', Mac variant + +" Derived from russian-jcuken.vim by Artem Chuprina <ran@ran.pp.ru> +" Maintainer: Anton Fonarev <avfonarev@gmail.com> +" Last Changed: 2016 August 17 + +" All characters are given literally, conversion to another encoding (e.g., +" UTF-8) should work. + +scriptencoding utf-8 + +let b:keymap_name = "ru" + +loadkeymap + +\| ะ CYRILLIC CAPITAL LETTER IO +\\ ั CYRILLIC SMALL LETTER IO + +F ะ CYRILLIC CAPITAL LETTER A +< ะ CYRILLIC CAPITAL LETTER BE +D ะ CYRILLIC CAPITAL LETTER VE +U ะ CYRILLIC CAPITAL LETTER GHE +L ะ CYRILLIC CAPITAL LETTER DE +T ะ CYRILLIC CAPITAL LETTER IE +: ะ CYRILLIC CAPITAL LETTER ZHE +P ะ CYRILLIC CAPITAL LETTER ZE +B ะ CYRILLIC CAPITAL LETTER I +Q ะ CYRILLIC CAPITAL LETTER SHORT I +R ะ CYRILLIC CAPITAL LETTER KA +K ะ CYRILLIC CAPITAL LETTER EL +V ะ CYRILLIC CAPITAL LETTER EM +Y ะ CYRILLIC CAPITAL LETTER EN +J ะ CYRILLIC CAPITAL LETTER O +G ะ CYRILLIC CAPITAL LETTER PE +H ะ CYRILLIC CAPITAL LETTER ER +C ะก CYRILLIC CAPITAL LETTER ES +N ะข CYRILLIC CAPITAL LETTER TE +E ะฃ CYRILLIC CAPITAL LETTER U +A ะค CYRILLIC CAPITAL LETTER EF +{ ะฅ CYRILLIC CAPITAL LETTER HA +W ะฆ CYRILLIC CAPITAL LETTER TSE +X ะง CYRILLIC CAPITAL LETTER CHE +I ะจ CYRILLIC CAPITAL LETTER SHA +O ะฉ CYRILLIC CAPITAL LETTER SHCHA +} ะช CYRILLIC CAPITAL LETTER HARD SIGN +S ะซ CYRILLIC CAPITAL LETTER YERU +M ะฌ CYRILLIC CAPITAL LETTER SOFT SIGN +\" ะญ CYRILLIC CAPITAL LETTER E +> ะฎ CYRILLIC CAPITAL LETTER YU +Z ะฏ CYRILLIC CAPITAL LETTER YA +f ะฐ CYRILLIC SMALL LETTER A +, ะฑ CYRILLIC SMALL LETTER BE +d ะฒ CYRILLIC SMALL LETTER VE +u ะณ CYRILLIC SMALL LETTER GHE +l ะด CYRILLIC SMALL LETTER DE +t ะต CYRILLIC SMALL LETTER IE +; ะถ CYRILLIC SMALL LETTER ZHE +p ะท CYRILLIC SMALL LETTER ZE +b ะธ CYRILLIC SMALL LETTER I +q ะน CYRILLIC SMALL LETTER SHORT I +r ะบ CYRILLIC SMALL LETTER KA +k ะป CYRILLIC SMALL LETTER EL +v ะผ CYRILLIC SMALL LETTER EM +y ะฝ CYRILLIC SMALL LETTER EN +j ะพ CYRILLIC SMALL LETTER O +g ะฟ CYRILLIC SMALL LETTER PE +h ั CYRILLIC SMALL LETTER ER +c ั CYRILLIC SMALL LETTER ES +n ั CYRILLIC SMALL LETTER TE +e ั CYRILLIC SMALL LETTER U +a ั CYRILLIC SMALL LETTER EF +[ ั
CYRILLIC SMALL LETTER HA +w ั CYRILLIC SMALL LETTER TSE +x ั CYRILLIC SMALL LETTER CHE +i ั CYRILLIC SMALL LETTER SHA +o ั CYRILLIC SMALL LETTER SHCHA +] ั CYRILLIC SMALL LETTER HARD SIGN +s ั CYRILLIC SMALL LETTER YERU +m ั CYRILLIC SMALL LETTER SOFT SIGN +' ั CYRILLIC SMALL LETTER E +. ั CYRILLIC SMALL LETTER YU +z ั CYRILLIC SMALL LETTER YA + +ยง > +ยฑ < +@ " +# โ +$ % +% : +^ , +& . +* ; +` ] +~ [ diff --git a/runtime/keymap/vietnamese-telex_utf-8.vim b/runtime/keymap/vietnamese-telex_utf-8.vim new file mode 100644 index 0000000000..f9fd055d14 --- /dev/null +++ b/runtime/keymap/vietnamese-telex_utf-8.vim @@ -0,0 +1,196 @@ +" Vim Keymap file for Vietnamese through Telex method +" Maintainer: Raphael McSinyx <vn.mcsinyx@gmail.com> +" Last Change: 2016-06-13 + +scriptencoding utf-8 + +let b:keymap_name = "vi" + +loadkeymap + +A\\ A +AF ร +AS ร +AR แบข +AX ร +AJ แบ + +AW ฤ +AW\\ ฤ +AWF แบฐ +AWS แบฎ +AWR แบฒ +AWX แบด +AWJ แบถ + +AA ร +AA\\ ร +AAF แบฆ +AAS แบค +AAR แบจ +AAX แบช +AAJ แบฌ + +D\\ D +DD ฤ + +E E +E\\ E +EF ร +ES ร +ER แบบ +EX แบผ +EJ แบธ + +EE ร +EE\\ ร +EEF แป +EES แบพ +EER แป +EEX แป +EEJ แป + +I\\ I +IF ร +IS ร +IR แป +IX ฤจ +IJ แป + +O\\ O +OF ร +OS ร +OR แป +OX ร +OJ แป + +OO ร +OO\\ ร +OOF แป +OOS แป +OOR แป +OOX แป +OOJ แป + +OW ฦ +OW\\ ฦ +OWF แป +OWS แป +OWR แป +OWX แป +OWJ แปข + +U\\ U +UF ร +US ร +UR แปฆ +UX ลจ +UJ แปค + +UW ฦฏ +UW\\ ฦฏ +UWF แปช +UWS แปจ +UWR แปฌ +UWX แปฎ +UWJ แปฐ + +Y\\ Y +YF แปฒ +YS ร +YR แปถ +YX แปธ +YJ แปด + +a\\ a +af ร +as รก +ar แบฃ +ax รฃ +aj แบก + +aw ฤ +aw\\ ฤ +awf แบฑ +aws แบฏ +awr แบณ +awx แบต +awj แบท + +aa รข +aa\\ รข +aaf แบง +aas แบฅ +aar แบฉ +aax แบซ +aaj แบญ + +d\\ d +dd ฤ + +e\\ e +ef รจ +es รฉ +er แบป +ex แบฝ +ej แบน + +ee รช +ee\\ รช +eef แป +ees แบฟ +eer แป +eex แป
+eej แป + +i\\ i +if รฌ +is รญ +ir แป +ix ฤฉ +ij แป + +o\\ o +of รฒ +os รณ +or แป +ox รต +oj แป + +oo รด +oo\\ รด +oof แป +oos แป +oor แป +oox แป +ooj แป + +ow ฦก +ow\\ ฦก +owf แป +ows แป +owr แป +owx แปก +owj แปฃ + +u\\ u +uf รน +us รบ +ur แปง +ux ลฉ +uj แปฅ + +uw ฦฐ +uw\\ ฦฐ +uwf แปซ +uws แปฉ +uwr แปญ +uwx แปฏ +uwj แปฑ + +y\\ y +yf แปณ +ys รฝ +yr แปท +yx แปน +yj แปต diff --git a/runtime/keymap/vietnamese-vni_utf-8.vim b/runtime/keymap/vietnamese-vni_utf-8.vim new file mode 100644 index 0000000000..c9312c6854 --- /dev/null +++ b/runtime/keymap/vietnamese-vni_utf-8.vim @@ -0,0 +1,196 @@ +" Vim Keymap file for Vietnamese through VNI method +" Maintainer: Raphael McSinyx <vn.mcsinyx@gmail.com> +" Last Change: 2016-06-13 + +scriptencoding utf-8 + +let b:keymap_name = "vi" + +loadkeymap + +A\\ A +A1 ร +A2 ร +A3 แบข +A4 ร +A5 แบ + +A8 ฤ +A8\\ ฤ +A81 แบฎ +A82 แบฐ +A83 แบฒ +A84 แบด +A85 แบถ + +A6 ร +A6\\ ร +A61 แบค +A62 แบฆ +A63 แบจ +A64 แบช +A65 แบฌ + +D D +D\\ D +D9 ฤ + +E\\ E +E1 ร +E2 ร +E3 แบบ +E4 แบผ +E5 แบธ + +E6 ร +E6\\ ร +E61 แบพ +E62 แป +E63 แป +E64 แป +E65 แป + +I\\ I +I1 ร +I2 ร +I3 แป +I4 ฤจ +I5 แป + +O\\ O +O1 ร +O2 ร +O3 แป +O4 ร +O5 แป + +O6 ร +O6\\ ร +O61 แป +O62 แป +O63 แป +O64 แป +O65 แป + +O7 ฦ +O7\\ ฦ +O71 แป +O72 แป +O73 แป +O74 แป +O75 แปข + +U\\ U +U1 ร +U2 ร +U3 แปฆ +U4 ลจ +U5 แปค + +U7 ฦฏ +U7\\ ฦฏ +U71 แปจ +U72 แปช +U73 แปฌ +U74 แปฎ +U75 แปฐ + +Y\\ Y +Y1 ร +Y2 แปฒ +Y3 แปถ +Y4 แปธ +Y5 แปด + +a\\ a +a1 รก +a2 ร +a3 แบฃ +a4 รฃ +a5 แบก + +a8 ฤ +a8\\ ฤ +a81 แบฏ +a82 แบฑ +a83 แบณ +a84 แบต +a85 แบท + +a6 รข +a6\\ รข +a61 แบฅ +a62 แบง +a63 แบฉ +a64 แบซ +a65 แบญ + +d\\ d +d9 ฤ + +e\\ e +e1 รฉ +e2 รจ +e3 แบป +e4 แบฝ +e5 แบน + +e6 รช +e6\\ รช +e61 แบฟ +e62 แป +e63 แป +e64 แป
+e65 แป + +i\\ i +i1 รญ +i2 รฌ +i3 แป +i4 ฤฉ +i5 แป + +o\\ o +o1 รณ +o2 รฒ +o3 แป +o4 รต +o5 แป + +o6 รด +o6\\ รด +o61 แป +o62 แป +o63 แป +o64 แป +o65 แป + +o7 ฦก +o7\\ ฦก +o71 แป +o72 แป +o73 แป +o74 แปก +o75 แปฃ + +u\\ u +u1 รบ +u2 รน +u3 แปง +u4 ลฉ +u5 แปฅ + +u7 ฦฐ +u7\\ ฦฐ +u71 แปฉ +u72 แปซ +u73 แปญ +u74 แปฏ +u75 แปฑ + +y\\ y +y1 รฝ +y2 แปณ +y3 แปท +y4 แปน +y5 แปต diff --git a/runtime/menu.vim b/runtime/menu.vim index 5cbc0faabd..37e9d8733b 100644 --- a/runtime/menu.vim +++ b/runtime/menu.vim @@ -2,7 +2,7 @@ " You can also use this as a start for your own set of menus. " " Maintainer: Bram Moolenaar <Bram@vim.org> -" Last Change: 2014 May 22 +" Last Change: 2017 Feb 09 " Note that ":an" (short for ":anoremenu") is often used to make a menu work " in all modes and avoid side effects from mappings defined by the user. @@ -188,7 +188,7 @@ an 20.435 &Edit.Startup\ &Settings :call <SID>EditVimrc()<CR> fun! s:EditVimrc() if $MYVIMRC != '' let fname = $MYVIMRC - elseif has("win32") || has("dos32") || has("dos16") + elseif has("win32") if $HOME != '' let fname = $HOME . "/_vimrc" else @@ -475,7 +475,7 @@ if has("folding") an 40.340.130 &Tools.&Folding.C&lose\ more\ folds<Tab>zm zm an 40.340.140 &Tools.&Folding.&Close\ all\ folds<Tab>zM zM an 40.340.150 &Tools.&Folding.O&pen\ more\ folds<Tab>zr zr - an 40.340.160 &Tools.&Folding.&Open\ all\ folds<Tab>zR zR + an 40.340.160 &Tools.&Folding.&Open\ All\ Folds<Tab>zR zR " fold method an 40.340.200 &Tools.&Folding.-SEP1- <Nop> an 40.340.210 &Tools.&Folding.Fold\ Met&hod.M&anual :set fdm=manual<CR> @@ -552,7 +552,7 @@ endfun func! s:XxdFind() if !exists("g:xxdprogram") " On the PC xxd may not be in the path but in the install directory - if (has("win32") || has("dos32")) && !executable("xxd") + if has("win32") && !executable("xxd") let g:xxdprogram = $VIMRUNTIME . (&shellslash ? '/' : '\') . "xxd.exe" else let g:xxdprogram = "xxd" diff --git a/runtime/nvim.desktop b/runtime/nvim.desktop new file mode 100644 index 0000000000..be6a2eda82 --- /dev/null +++ b/runtime/nvim.desktop @@ -0,0 +1,81 @@ +[Desktop Entry] +Name=Neovim +GenericName=Text Editor +GenericName[de]=Texteditor +Comment=Edit text files +Comment[af]=Redigeer tekslรชers +Comment[am]=แจแฝแแ แแญแแฝ แซแตแฐแซแญแ +Comment[ar]=ุญุฑูุฑ ู
ููุงุช ูุตูุฉ +Comment[az]=Mษtn fayllarฤฑnฤฑ redaktษ edin +Comment[be]=ะ ัะดะฐะณะฐะฒะฐะฝัะฝะต ััะบััะฐะฒัั
ัะฐะนะปะฐั +Comment[bg]=ะ ะตะดะฐะบัะธัะฐะฝะต ะฝะฐ ัะตะบััะพะฒะธ ัะฐะนะปะพะฒะต +Comment[bn]=เฆเงเฆเงเฆธเงเฆ เฆซเฆพเฆเฆฒ เฆเฆกเฆฟเฆ เฆเฆฐเงเฆจ +Comment[bs]=Izmijeni tekstualne datoteke +Comment[ca]=Edita fitxers de text +Comment[cs]=รprava textovรฝch souborลฏ +Comment[cy]=Golygu ffeiliau testun +Comment[da]=Redigรฉr tekstfiler +Comment[de]=Textdateien bearbeiten +Comment[el]=ฮฯฮตฮพฮตฯฮณฮฑฯฮฏฮฑ ฮฑฯฯฮตฮฏฯฮฝ ฮบฮตฮนฮผฮญฮฝฮฟฯ
+Comment[en_CA]=Edit text files +Comment[en_GB]=Edit text files +Comment[es]=Edita archivos de texto +Comment[et]=Redigeeri tekstifaile +Comment[eu]=Editatu testu-fitxategiak +Comment[fa]=ูุฑุงุด ูพุฑููุฏูโูุง ู
ุชู +Comment[fi]=Muokkaa tekstitiedostoja +Comment[fr]=รdite des fichiers texte +Comment[ga]=Eagar comhad Tรฉacs +Comment[gu]=เชฒเชเชพเชฃ เชซเชพเชเชฒเซเชฎเชพเช เชซเซเชฐเชซเชพเชฐ เชเชฐเซ +Comment[he]=ืขืจืื ืงืืฆื ืืงืกื +Comment[hi]=เคชเคพเค เคซเคผเคพเคเคฒเฅเค เคธเคเคชเคพเคฆเคฟเคค เคเคฐเฅเค +Comment[hr]=Ureฤivanje tekstualne datoteke +Comment[hu]=Szรถvegfรกjlok szerkesztรฉse +Comment[id]=Edit file teks +Comment[it]=Modifica file di testo +Comment[ja]=ใใญในใใใกใคใซใ็ทจ้ใใพใ +Comment[kn]=เฒชเฒ เณเฒฏ เฒเฒกเฒคเฒเฒณเฒจเณเฒจเณ เฒธเฒเฒชเฒพเฒฆเฒฟเฒธเณ +Comment[ko]=ํ
์คํธ ํ์ผ์ ํธ์งํฉ๋๋ค +Comment[lt]=Redaguoti tekstines bylas +Comment[lv]=Rediฤฃฤt teksta failus +Comment[mk]=ะฃัะตะดะธ ัะตะบัััะฐะปะฝะธ ัะฐัะปะพะฒะธ +Comment[ml]=เดตเดพเดเด เดฐเดเดจเดเดณเต เดคเดฟเดฐเตเดคเตเดคเตเด +Comment[mn]=ะขะตะบัั ัะฐะนะป ะฑะพะปะพะฒััััะปะฐั
+Comment[mr]=เคเคฆเฅเคฏ เคซเคพเคเคฒ เคธเคเคชเคพเคฆเคฟเคค เคเคฐเคพ +Comment[ms]=Edit fail teks +Comment[nb]=Rediger tekstfiler +Comment[ne]=เคชเคพเค เคซเคพเคเคฒเคฒเคพเค เคธเคเคถเฅเคงเคจ เคเคฐเฅเคจเฅเคนเฅเคธเฅ +Comment[nl]=Tekstbestanden bewerken +Comment[nn]=Rediger tekstfiler +Comment[no]=Rediger tekstfiler +Comment[or]=เฌชเฌพเฌ เญเฌฏ เฌซเฌพเฌเฌฒเฌเญเฌกเฌผเฌฟเฌเญ เฌธเฌฎเญเฌชเฌพเฌฆเฌจ เฌเฌฐเฌจเญเฌคเญ +Comment[pa]=เจชเจพเจ เจซเจพเจเจฒเจพเจ เจธเฉฐเจชเจพเจฆเจจ +Comment[pl]=Edytor plikรณw tekstowych +Comment[pt]=Editar ficheiros de texto +Comment[pt_BR]=Edite arquivos de texto +Comment[ro]=Editare fiลiere text +Comment[ru]=ะ ะตะดะฐะบัะพั ัะตะบััะพะฒัั
ัะฐะนะปะพะฒ +Comment[sk]=รprava textovรฝch sรบborov +Comment[sl]=Urejanje datotek z besedili +Comment[sq]=Pรซrpuno files teksti +Comment[sr]=ะะทะผะตะฝะธ ัะตะบัััะฐะปะฝะต ะดะฐัะพัะตะบะต +Comment[sr@Latn]=Izmeni tekstualne datoteke +Comment[sv]=Redigera textfiler +Comment[ta]=เฎเฎฐเฏ เฎเฏเฎชเฏเฎชเฏเฎเฎณเฏ เฎคเฏเฎเฏเฎเฏเฎเฎตเฏเฎฎเฏ +Comment[th]=เนเธเนเนเธเนเธเนเธกเธเนเธญเธเธงเธฒเธก +Comment[tk]=Metin faรฝllary editle +Comment[tr]=Metin dosyalarฤฑnฤฑ dรผzenle +Comment[uk]=ะ ะตะดะฐะบัะพั ัะตะบััะพะฒะธั
ัะฐะนะปัะฒ +Comment[vi]=Soแบกn thแบฃo tแบญp tin vฤn bแบฃn +Comment[wa]=Asspougnรฎ des fitchรฎs tecses +Comment[zh_CN]=็ผ่พๆๆฌๆไปถ +Comment[zh_TW]=็ทจ่ผฏๆๅญๆช +TryExec=nvim +Exec=nvim %F +Terminal=true +Type=Application +Keywords=Text;editor; +Icon=nvim +Categories=Utility;TextEditor; +StartupNotify=false +MimeType=text/english;text/plain;text/x-makefile;text/x-c++hdr;text/x-c++src;text/x-chdr;text/x-csrc;text/x-java;text/x-moc;text/x-pascal;text/x-tcl;text/x-tex;application/x-shellscript;text/x-c;text/x-c++; diff --git a/runtime/nvim.png b/runtime/nvim.png Binary files differnew file mode 100644 index 0000000000..dbc65ef363 --- /dev/null +++ b/runtime/nvim.png diff --git a/runtime/optwin.vim b/runtime/optwin.vim index a7b94d73d4..5c883babc1 100644 --- a/runtime/optwin.vim +++ b/runtime/optwin.vim @@ -1,7 +1,7 @@ " These commands create the option window. " " Maintainer: Bram Moolenaar <Bram@vim.org> -" Last Change: 2016 Aug 12 +" Last Change: 2017 Jan 28 " If there already is an option window, jump to that one. if bufwinnr("option-window") > 0 @@ -524,8 +524,6 @@ endif call <SID>Header("terminal") -call append("$", "esckeys\trecognize keys that start with <Esc> in Insert mode") -call <SID>BinOptionG("ek", &ek) call append("$", "scrolljump\tminimal number of lines to scroll at a time") call append("$", " \tset sj=" . &sj) if has("gui") || has("msdos") || has("win32") @@ -591,8 +589,6 @@ if has("gui") call append("$", "toolbariconsize\tsize of toolbar icons") call <SID>OptionG("tbis", &tbis) endif - call append("$", "guiheadroom\troom (in pixels) left above/below the window") - call append("$", " \tset ghr=" . &ghr) endif if has("browse") call append("$", "browsedir\t\"last\", \"buffer\" or \"current\": which directory used for the file browser") @@ -1150,8 +1146,8 @@ endif if has("langmap") call append("$", "langmap\tlist of characters that are translated in Normal mode") call <SID>OptionG("lmap", &lmap) - call append("$", "langnoremap\tdon't apply 'langmap' to mapped characters") - call <SID>BinOptionG("lnr", &lnr) + call append("$", "langremap\tapply 'langmap' to mapped characters") + call <SID>BinOptionG("lrm", &lrm) endif if has("xim") call append("$", "imdisable\twhen set never use IM; overrules following IM options") diff --git a/runtime/pack/dist/opt/vimball/autoload/vimball.vim b/runtime/pack/dist/opt/vimball/autoload/vimball.vim index 1af6b19c88..9c7dcbda0f 100644 --- a/runtime/pack/dist/opt/vimball/autoload/vimball.vim +++ b/runtime/pack/dist/opt/vimball/autoload/vimball.vim @@ -347,7 +347,7 @@ fun! vimball#Vimball(really,...) " call Decho("exe tabn ".curtabnr) exe "tabn ".curtabnr - " set up help if its a doc/*.txt file + " set up help if it's a doc/*.txt file " call Decho("didhelp<".didhelp."> fname<".fname.">") if a:really && didhelp == "" && fname =~ 'doc/[^/]\+\.\(txt\|..x\)$' let didhelp= substitute(fname,'^\(.*\<doc\)[/\\][^.]*\.\(txt\|..x\)$','\1','') diff --git a/runtime/plugin/gui_shim.vim b/runtime/plugin/gui_shim.vim new file mode 100644 index 0000000000..575b826b5e --- /dev/null +++ b/runtime/plugin/gui_shim.vim @@ -0,0 +1,81 @@ +" A Neovim plugin that implements GUI helper commands +if !has('win32') || !has('nvim') || exists('g:GuiLoaded') + finish +endif +let g:GuiLoaded = 1 + +" Close the GUI +function! GuiClose() abort + call rpcnotify(0, 'Gui', 'Close') +endfunction + +" Notify the GUI when exiting Neovim +autocmd VimLeave * call GuiClose() + +" A replacement for foreground() +function! GuiForeground() abort + call rpcnotify(0, 'Gui', 'Foreground') +endfunction + +" Set maximized state for GUI window (1 is enabled, 0 disabled) +function! GuiWindowMaximized(enabled) abort + call rpcnotify(0, 'Gui', 'WindowMaximized', a:enabled) +endfunction + +" Set fullscreen state for GUI window (1 is enabled, 0 disabled) +function! GuiWindowFullScreen(enabled) abort + call rpcnotify(0, 'Gui', 'WindowFullScreen', a:enabled) +endfunction + +" Set GUI font +function! GuiFont(fname, ...) abort + let force = get(a:000, 0, 0) + call rpcnotify(0, 'Gui', 'Font', a:fname, force) +endfunction + +" Set additional linespace +function! GuiLinespace(height) abort + call rpcnotify(0, 'Gui', 'Linespace', a:height) +endfunction + +" Configure mouse hide behaviour (1 is enabled, 0 disabled) +function! GuiMousehide(enabled) abort + call rpcnotify(0, 'Gui', 'Mousehide', a:enabled) +endfunction + +" The GuiFont command. For compatibility there is also Guifont +function s:GuiFontCommand(fname, bang) abort + if a:fname ==# '' + if exists('g:GuiFont') + echo g:GuiFont + else + echo 'No GuiFont is set' + endif + else + call GuiFont(a:fname, a:bang ==# '!') + endif +endfunction +command! -nargs=? -bang Guifont call s:GuiFontCommand("<args>", "<bang>") +command! -nargs=? -bang GuiFont call s:GuiFontCommand("<args>", "<bang>") + +function s:GuiLinespaceCommand(height) abort + if a:height ==# '' + if exists('g:GuiLinespace') + echo g:GuiLinespace + else + echo 'No GuiLinespace is set' + endif + else + call GuiLinespace(a:height) + endif +endfunction +command! -nargs=? GuiLinespace call s:GuiLinespaceCommand("<args>") + +" GuiDrop('file1', 'file2', ...) is similar to :drop file1 file2 ... +" but it calls fnameescape() over all arguments +function GuiDrop(...) + let l:fnames = deepcopy(a:000) + let l:args = map(l:fnames, 'fnameescape(v:val)') + exec 'drop '.join(l:args, ' ') + doautocmd BufEnter +endfunction diff --git a/runtime/plugin/gzip.vim b/runtime/plugin/gzip.vim index edef149537..5e13b92d1e 100644 --- a/runtime/plugin/gzip.vim +++ b/runtime/plugin/gzip.vim @@ -1,6 +1,6 @@ " Vim plugin for editing compressed files. " Maintainer: Bram Moolenaar <Bram@vim.org> -" Last Change: 2010 Mar 10 +" Last Change: 2016 Oct 30 " Exit quickly when: " - this plugin was already loaded @@ -20,25 +20,33 @@ augroup gzip " " Set binary mode before reading the file. " Use "gzip -d", gunzip isn't always available. - autocmd BufReadPre,FileReadPre *.gz,*.bz2,*.Z,*.lzma,*.xz setlocal bin + autocmd BufReadPre,FileReadPre *.gz,*.bz2,*.Z,*.lzma,*.xz,*.lz,*.zst setlocal bin autocmd BufReadPost,FileReadPost *.gz call gzip#read("gzip -dn") autocmd BufReadPost,FileReadPost *.bz2 call gzip#read("bzip2 -d") autocmd BufReadPost,FileReadPost *.Z call gzip#read("uncompress") autocmd BufReadPost,FileReadPost *.lzma call gzip#read("lzma -d") autocmd BufReadPost,FileReadPost *.xz call gzip#read("xz -d") + autocmd BufReadPost,FileReadPost *.lz call gzip#read("lzip -d") + autocmd BufReadPost,FileReadPost *.zst call gzip#read("zstd -d --rm") autocmd BufWritePost,FileWritePost *.gz call gzip#write("gzip") autocmd BufWritePost,FileWritePost *.bz2 call gzip#write("bzip2") autocmd BufWritePost,FileWritePost *.Z call gzip#write("compress -f") autocmd BufWritePost,FileWritePost *.lzma call gzip#write("lzma -z") autocmd BufWritePost,FileWritePost *.xz call gzip#write("xz -z") + autocmd BufWritePost,FileWritePost *.lz call gzip#write("lzip") + autocmd BufWritePost,FileWritePost *.zst call gzip#write("zstd --rm") autocmd FileAppendPre *.gz call gzip#appre("gzip -dn") autocmd FileAppendPre *.bz2 call gzip#appre("bzip2 -d") autocmd FileAppendPre *.Z call gzip#appre("uncompress") autocmd FileAppendPre *.lzma call gzip#appre("lzma -d") autocmd FileAppendPre *.xz call gzip#appre("xz -d") + autocmd FileAppendPre *.lz call gzip#appre("lzip -d") + autocmd FileAppendPre *.zst call gzip#appre("zstd -d --rm") autocmd FileAppendPost *.gz call gzip#write("gzip") autocmd FileAppendPost *.bz2 call gzip#write("bzip2") autocmd FileAppendPost *.Z call gzip#write("compress -f") autocmd FileAppendPost *.lzma call gzip#write("lzma -z") autocmd FileAppendPost *.xz call gzip#write("xz -z") + autocmd FileAppendPost *.lz call gzip#write("lzip") + autocmd FileAppendPost *.zst call gzip#write("zstd --rm") augroup END diff --git a/runtime/plugin/matchit.vim b/runtime/plugin/matchit.vim index c0f1f08027..f275f7b36d 100644 --- a/runtime/plugin/matchit.vim +++ b/runtime/plugin/matchit.vim @@ -1,8 +1,10 @@ " matchit.vim: (global plugin) Extended "%" matching -" Last Change: Fri Jul 29 01:20 AM 2016 EST +" Last Change: 2016 Aug 21 " Maintainer: Benji Fisher PhD <benji@member.AMS.org> " Version: 1.13.2, for Vim 6.3+ " Fix from Tommy Allen included. +" Fix from Fernando Torres included. +" Improvement from Ken Takata included. " URL: http://www.vim.org/script.php?script_id=39 " Documentation: @@ -44,6 +46,7 @@ endif let loaded_matchit = 1 let s:last_mps = "" let s:last_words = ":" +let s:patBR = "" let s:save_cpo = &cpo set cpo&vim @@ -121,8 +124,8 @@ function! s:Match_wrapper(word, forward, mode) range execute "let match_words =" b:match_words endif " Thanks to Preben "Peppe" Guldberg and Bram Moolenaar for this suggestion! - if (match_words != s:last_words) || (&mps != s:last_mps) || - \ exists("b:match_debug") + if (match_words != s:last_words) || (&mps != s:last_mps) + \ || exists("b:match_debug") let s:last_mps = &mps " The next several lines were here before " BF started messing with this script. @@ -148,6 +151,10 @@ function! s:Match_wrapper(word, forward, mode) range if exists("b:match_debug") let b:match_pat = s:pat endif + " Reconstruct the version with unresolved backrefs. + let s:patBR = substitute(match_words.',', + \ s:notslash.'\zs[,:]*,[,:]*', ',', 'g') + let s:patBR = substitute(s:patBR, s:notslash.'\zs:\{2,}', ':', 'g') endif " Second step: set the following local variables: @@ -192,14 +199,10 @@ function! s:Match_wrapper(word, forward, mode) range " group = colon-separated list of patterns, one of which matches " = ini:mid:fin or ini:fin " - " Reconstruct the version with unresolved backrefs. - let patBR = substitute(match_words.',', - \ s:notslash.'\zs[,:]*,[,:]*', ',', 'g') - let patBR = substitute(patBR, s:notslash.'\zs:\{2,}', ':', 'g') " Now, set group and groupBR to the matching group: 'if:endif' or " 'while:endwhile' or whatever. A bit of a kluge: s:Choose() returns " group . "," . groupBR, and we pick it apart. - let group = s:Choose(s:pat, matchline, ",", ":", prefix, suffix, patBR) + let group = s:Choose(s:pat, matchline, ",", ":", prefix, suffix, s:patBR) let i = matchend(group, s:notslash . ",") let groupBR = strpart(group, i) let group = strpart(group, 0, i-1) @@ -656,6 +659,7 @@ fun! s:MultiMatch(spflag, mode) \ exists("b:match_debug") let s:last_words = match_words let s:last_mps = &mps + let match_words = match_words . (strlen(match_words) ? "," : "") . default if match_words !~ s:notslash . '\\\d' let s:do_BR = 0 let s:pat = match_words @@ -663,8 +667,8 @@ fun! s:MultiMatch(spflag, mode) let s:do_BR = 1 let s:pat = s:ParseWords(match_words) endif - let s:all = '\%(' . substitute(s:pat . (strlen(s:pat)?",":"") . default, - \ '[,:]\+','\\|','g') . '\)' + let s:all = '\%(' . substitute(s:pat . (strlen(s:pat) ? "," : "") . default, + \ '[,:]\+', '\\|', 'g') . '\)' if exists("b:match_debug") let b:match_pat = s:pat endif diff --git a/runtime/plugin/rplugin.vim b/runtime/plugin/rplugin.vim index b4b03032b3..ca15ec82d1 100644 --- a/runtime/plugin/rplugin.vim +++ b/runtime/plugin/rplugin.vim @@ -1,16 +1,61 @@ if exists('g:loaded_remote_plugins') finish endif -let g:loaded_remote_plugins = 1 +let g:loaded_remote_plugins = '/path/to/manifest' + +" Get the path to the rplugin manifest file. +function! s:GetManifestPath() abort + let manifest_base = '' + + if exists('$NVIM_RPLUGIN_MANIFEST') + return fnamemodify($NVIM_RPLUGIN_MANIFEST, ':p') + endif + + let dest = has('win32') ? '$LOCALAPPDATA' : '$XDG_DATA_HOME' + if !exists(dest) + let dest = has('win32') ? '~/AppData/Local' : '~/.local/share' + endif + + let dest = fnamemodify(expand(dest), ':p') + if !empty(dest) + let dest .= ('/' ==# dest[-1:] ? '' : '/') . 'nvim' + if !isdirectory(dest) + call mkdir(dest, 'p', 0700) + endif + let manifest_base = dest + endif + + return manifest_base.'/rplugin.vim' +endfunction + +" Old manifest file based on known script locations. +function! s:GetOldManifestPath() abort + let prefix = exists('$MYVIMRC') + \ ? $MYVIMRC + \ : matchstr(get(split(execute('scriptnames'), '\n'), 0, ''), '\f\+$') + return fnamemodify(expand(prefix, 1), ':h') + \.'/.'.fnamemodify(prefix, ':t').'-rplugin~' +endfunction + +function! s:GetManifest() abort + let manifest = s:GetManifestPath() + if !filereadable(manifest) + " Check if an old manifest file exists and move it to the new location. + let old_manifest = s:GetOldManifestPath() + if filereadable(old_manifest) + call rename(old_manifest, manifest) + endif + endif + return manifest +endfunction + +function! s:LoadRemotePlugins() abort + let g:loaded_remote_plugins = s:GetManifest() + if filereadable(g:loaded_remote_plugins) + execute 'source' fnameescape(g:loaded_remote_plugins) + endif +endfunction command! UpdateRemotePlugins call remote#host#UpdateRemotePlugins() -augroup nvim-rplugin - autocmd! - autocmd FuncUndefined * - \ call remote#host#LoadRemotePluginsEvent( - \ 'FuncUndefined', expand('<amatch>')) - autocmd CmdUndefined * - \ call remote#host#LoadRemotePluginsEvent( - \ 'CmdUndefined', expand('<amatch>')) -augroup END +call s:LoadRemotePlugins() diff --git a/runtime/plugin/zipPlugin.vim b/runtime/plugin/zipPlugin.vim index e9bd0dc4bd..c04d5344b1 100644 --- a/runtime/plugin/zipPlugin.vim +++ b/runtime/plugin/zipPlugin.vim @@ -1,9 +1,9 @@ " zipPlugin.vim: Handles browsing zipfiles " PLUGIN PORTION -" Date: Jun 07, 2013 +" Date: Sep 13, 2016 " Maintainer: Charles E Campbell <NdrOchip@ScampbellPfamily.AbizM-NOSPAM> " License: Vim License (see vim's :help license) -" Copyright: Copyright (C) 2005-2013 Charles E. Campbell {{{1 +" Copyright: Copyright (C) 2005-2016 Charles E. Campbell {{{1 " Permission is hereby granted to use and distribute this code, " with or without modifications, provided that this copyright " notice is copied with it. Like anything else that's free, @@ -20,14 +20,14 @@ if &cp || exists("g:loaded_zipPlugin") finish endif -let g:loaded_zipPlugin = "v27" +let g:loaded_zipPlugin = "v28" let s:keepcpo = &cpo set cpo&vim " --------------------------------------------------------------------- " Options: {{{1 if !exists("g:zipPlugin_ext") - let g:zipPlugin_ext= '*.zip,*.jar,*.xpi,*.ja,*.war,*.ear,*.celzip,*.oxt,*.kmz,*.wsz,*.xap,*.docx,*.docm,*.dotx,*.dotm,*.potx,*.potm,*.ppsx,*.ppsm,*.pptx,*.pptm,*.ppam,*.sldx,*.thmx,*.xlam,*.xlsx,*.xlsm,*.xlsb,*.xltx,*.xltm,*.xlam,*.crtx,*.vdw,*.glox,*.gcsx,*.gqsx' + let g:zipPlugin_ext='*.apk,*.celzip,*.crtx,*.docm,*.docx,*.dotm,*.dotx,*.ear,*.epub,*.gcsx,*.glox,*.gqsx,*.ja,*.jar,*.kmz,*.oxt,*.potm,*.potx,*.ppam,*.ppsm,*.ppsx,*.pptm,*.pptx,*.sldx,*.thmx,*.vdw,*.war,*.wsz,*.xap,*.xlam,*.xlam,*.xlsb,*.xlsm,*.xlsx,*.xltm,*.xltx,*.xpi,*.zip' endif " --------------------------------------------------------------------- diff --git a/runtime/synmenu.vim b/runtime/synmenu.vim index 01dad3c7f2..81e3667298 100644 --- a/runtime/synmenu.vim +++ b/runtime/synmenu.vim @@ -61,7 +61,6 @@ an 50.10.320 &Syntax.AB.Ascii\ Doc :cal SetSyn("asciidoc")<CR> an 50.10.330 &Syntax.AB.ASP\ with\ VBScript :cal SetSyn("aspvbs")<CR> an 50.10.340 &Syntax.AB.ASP\ with\ Perl :cal SetSyn("aspperl")<CR> an 50.10.350 &Syntax.AB.Assembly.680x0 :cal SetSyn("asm68k")<CR> -an 50.10.355 &Syntax.AB.Assembly.AVR :cal SetSyn("avra")<CR> an 50.10.360 &Syntax.AB.Assembly.Flat :cal SetSyn("fasm")<CR> an 50.10.370 &Syntax.AB.Assembly.GNU :cal SetSyn("asm")<CR> an 50.10.380 &Syntax.AB.Assembly.GNU\ H-8300 :cal SetSyn("asmh8300")<CR> @@ -162,31 +161,31 @@ an 50.30.290 &Syntax.DE.Doxygen.C\ with\ doxygen :cal SetSyn("c.doxygen")<CR> an 50.30.300 &Syntax.DE.Doxygen.C++\ with\ doxygen :cal SetSyn("cpp.doxygen")<CR> an 50.30.310 &Syntax.DE.Doxygen.IDL\ with\ doxygen :cal SetSyn("idl.doxygen")<CR> an 50.30.320 &Syntax.DE.Doxygen.Java\ with\ doxygen :cal SetSyn("java.doxygen")<CR> -an 50.30.320 &Syntax.DE.Doxygen.DataScript\ with\ doxygen :cal SetSyn("datascript.doxygen")<CR> -an 50.30.330 &Syntax.DE.Dracula :cal SetSyn("dracula")<CR> -an 50.30.340 &Syntax.DE.DSSSL :cal SetSyn("dsl")<CR> -an 50.30.350 &Syntax.DE.DTD :cal SetSyn("dtd")<CR> -an 50.30.360 &Syntax.DE.DTML\ (Zope) :cal SetSyn("dtml")<CR> -an 50.30.370 &Syntax.DE.DTrace :cal SetSyn("dtrace")<CR> -an 50.30.380 &Syntax.DE.Dts/dtsi :cal SetSyn("dts")<CR> -an 50.30.390 &Syntax.DE.Dylan.Dylan :cal SetSyn("dylan")<CR> -an 50.30.400 &Syntax.DE.Dylan.Dylan\ interface :cal SetSyn("dylanintr")<CR> -an 50.30.410 &Syntax.DE.Dylan.Dylan\ lid :cal SetSyn("dylanlid")<CR> -an 50.30.430 &Syntax.DE.EDIF :cal SetSyn("edif")<CR> -an 50.30.440 &Syntax.DE.Eiffel :cal SetSyn("eiffel")<CR> -an 50.30.450 &Syntax.DE.Elinks\ config :cal SetSyn("elinks")<CR> -an 50.30.460 &Syntax.DE.Elm\ filter\ rules :cal SetSyn("elmfilt")<CR> -an 50.30.470 &Syntax.DE.Embedix\ Component\ Description :cal SetSyn("ecd")<CR> -an 50.30.480 &Syntax.DE.ERicsson\ LANGuage :cal SetSyn("erlang")<CR> -an 50.30.490 &Syntax.DE.ESMTP\ rc :cal SetSyn("esmtprc")<CR> -an 50.30.500 &Syntax.DE.ESQL-C :cal SetSyn("esqlc")<CR> -an 50.30.510 &Syntax.DE.Essbase\ script :cal SetSyn("csc")<CR> -an 50.30.520 &Syntax.DE.Esterel :cal SetSyn("esterel")<CR> -an 50.30.530 &Syntax.DE.Eterm\ config :cal SetSyn("eterm")<CR> -an 50.30.540 &Syntax.DE.Eviews :cal SetSyn("eviews")<CR> -an 50.30.550 &Syntax.DE.Exim\ conf :cal SetSyn("exim")<CR> -an 50.30.560 &Syntax.DE.Expect :cal SetSyn("expect")<CR> -an 50.30.570 &Syntax.DE.Exports :cal SetSyn("exports")<CR> +an 50.30.330 &Syntax.DE.Doxygen.DataScript\ with\ doxygen :cal SetSyn("datascript.doxygen")<CR> +an 50.30.340 &Syntax.DE.Dracula :cal SetSyn("dracula")<CR> +an 50.30.350 &Syntax.DE.DSSSL :cal SetSyn("dsl")<CR> +an 50.30.360 &Syntax.DE.DTD :cal SetSyn("dtd")<CR> +an 50.30.370 &Syntax.DE.DTML\ (Zope) :cal SetSyn("dtml")<CR> +an 50.30.380 &Syntax.DE.DTrace :cal SetSyn("dtrace")<CR> +an 50.30.390 &Syntax.DE.Dts/dtsi :cal SetSyn("dts")<CR> +an 50.30.400 &Syntax.DE.Dylan.Dylan :cal SetSyn("dylan")<CR> +an 50.30.410 &Syntax.DE.Dylan.Dylan\ interface :cal SetSyn("dylanintr")<CR> +an 50.30.420 &Syntax.DE.Dylan.Dylan\ lid :cal SetSyn("dylanlid")<CR> +an 50.30.440 &Syntax.DE.EDIF :cal SetSyn("edif")<CR> +an 50.30.450 &Syntax.DE.Eiffel :cal SetSyn("eiffel")<CR> +an 50.30.460 &Syntax.DE.Elinks\ config :cal SetSyn("elinks")<CR> +an 50.30.470 &Syntax.DE.Elm\ filter\ rules :cal SetSyn("elmfilt")<CR> +an 50.30.480 &Syntax.DE.Embedix\ Component\ Description :cal SetSyn("ecd")<CR> +an 50.30.490 &Syntax.DE.ERicsson\ LANGuage :cal SetSyn("erlang")<CR> +an 50.30.500 &Syntax.DE.ESMTP\ rc :cal SetSyn("esmtprc")<CR> +an 50.30.510 &Syntax.DE.ESQL-C :cal SetSyn("esqlc")<CR> +an 50.30.520 &Syntax.DE.Essbase\ script :cal SetSyn("csc")<CR> +an 50.30.530 &Syntax.DE.Esterel :cal SetSyn("esterel")<CR> +an 50.30.540 &Syntax.DE.Eterm\ config :cal SetSyn("eterm")<CR> +an 50.30.550 &Syntax.DE.Eviews :cal SetSyn("eviews")<CR> +an 50.30.560 &Syntax.DE.Exim\ conf :cal SetSyn("exim")<CR> +an 50.30.570 &Syntax.DE.Expect :cal SetSyn("expect")<CR> +an 50.30.580 &Syntax.DE.Exports :cal SetSyn("exports")<CR> an 50.40.100 &Syntax.FG.Falcon :cal SetSyn("falcon")<CR> an 50.40.110 &Syntax.FG.Fantom :cal SetSyn("fan")<CR> an 50.40.120 &Syntax.FG.Fetchmail :cal SetSyn("fetchmail")<CR> @@ -328,7 +327,6 @@ an 50.70.270 &Syntax.M.Messages\ (/var/log) :cal SetSyn("messages")<CR> an 50.70.280 &Syntax.M.Metafont :cal SetSyn("mf")<CR> an 50.70.290 &Syntax.M.MetaPost :cal SetSyn("mp")<CR> an 50.70.300 &Syntax.M.MGL :cal SetSyn("mgl")<CR> -an 50.70.305 &Syntax.M.MIX :cal SetSyn("mix")<CR> an 50.70.310 &Syntax.M.MMIX :cal SetSyn("mmix")<CR> an 50.70.320 &Syntax.M.Modconf :cal SetSyn("modconf")<CR> an 50.70.330 &Syntax.M.Model :cal SetSyn("model")<CR> diff --git a/runtime/syntax/a65.vim b/runtime/syntax/a65.vim index 94198e6a42..b232e826cd 100644 --- a/runtime/syntax/a65.vim +++ b/runtime/syntax/a65.vim @@ -1,13 +1,10 @@ " Vim syntax file " Language: xa 6502 cross assembler " Maintainer: Clemens Kirchgatterer <clemens@1541.org> -" Last Change: 2014 Jan 05 +" Last Change: 2016 Aug 31 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -138,29 +135,19 @@ syn match a65End excludenl /end$/ contained syn match a65Continue "\\$" contained " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_a65_syntax_inits") - if version < 508 - let did_a65_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink a65Section Special - HiLink a65Address Special - HiLink a65Comment Comment - HiLink a65PreProc PreProc - HiLink a65Number Number - HiLink a65String String - HiLink a65Type Statement - HiLink a65Opcode Type - HiLink a65PC Error - HiLink a65Todo Todo - HiLink a65HiLo Number - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link a65Section Special +hi def link a65Address Special +hi def link a65Comment Comment +hi def link a65PreProc PreProc +hi def link a65Number Number +hi def link a65String String +hi def link a65Type Statement +hi def link a65Opcode Type +hi def link a65PC Error +hi def link a65Todo Todo +hi def link a65HiLo Number + let b:current_syntax = "a65" diff --git a/runtime/syntax/abap.vim b/runtime/syntax/abap.vim index 1d1f6afd0d..c2857a5f30 100644 --- a/runtime/syntax/abap.vim +++ b/runtime/syntax/abap.vim @@ -5,11 +5,8 @@ " Last Change: 2013 Jun 13 " Comment: Thanks to EPI-USE Labs for all your assistance. :) -" For version < 6.0: Clear all syntax items -" For version >= 6.0: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -43,11 +40,7 @@ syn match abapStringEscape contained "``" syn match abapNumber "\-\=\<\d\+\>" syn region abapHex matchgroup=abapHex start="X'" end="'" -if version >= 600 - setlocal iskeyword=48-57,_,A-Z,a-z,/ -else - set iskeyword=48-57,_,A-Z,a-z,/ -endif +setlocal iskeyword=48-57,_,A-Z,a-z,/ syn match abapNamespace "\</\w\+/" @@ -175,38 +168,28 @@ syn keyword abapTodo contained TODO NOTE syn match abapTodo "\#EC\W\+\w\+" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_abap_syntax_inits") - if version < 508 - let did_abap_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink abapError Error - HiLink abapComment Comment - HiLink abapInclude Include - HiLink abapStatement Statement - HiLink abapComplexStatement Statement - HiLink abapSpecial Special - HiLink abapNamespace Special - HiLink abapSpecialTables Special - HiLink abapSymbolOperator abapOperator - HiLink abapOperator Operator - HiLink abapCharString String - HiLink abapString String - HiLink abapFloat Float - HiLink abapTypes Type - HiLink abapSymbol Structure - HiLink abapStructure Structure - HiLink abapField Variable - HiLink abapNumber Number - HiLink abapHex Number - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link abapError Error +hi def link abapComment Comment +hi def link abapInclude Include +hi def link abapStatement Statement +hi def link abapComplexStatement Statement +hi def link abapSpecial Special +hi def link abapNamespace Special +hi def link abapSpecialTables Special +hi def link abapSymbolOperator abapOperator +hi def link abapOperator Operator +hi def link abapCharString String +hi def link abapString String +hi def link abapFloat Float +hi def link abapTypes Type +hi def link abapSymbol Structure +hi def link abapStructure Structure +hi def link abapField Variable +hi def link abapNumber Number +hi def link abapHex Number + let b:current_syntax = "abap" diff --git a/runtime/syntax/abaqus.vim b/runtime/syntax/abaqus.vim index cf4b0828fa..db2717f818 100644 --- a/runtime/syntax/abaqus.vim +++ b/runtime/syntax/abaqus.vim @@ -4,11 +4,8 @@ " Last Change: 2002 Feb 24 " Remark: Huge improvement in folding performance--see filetype plugin -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -25,24 +22,14 @@ syn match abaqusValue "=\s*[^,]*"lc=1 contained display syn match abaqusBadLine "^\s\+\*.*" display " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_abaqus_syn_inits") - if version < 508 - let did_abaqus_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - " The default methods for highlighting. Can be overridden later - HiLink abaqusComment Comment - HiLink abaqusKeyword Statement - HiLink abaqusParameter Identifier - HiLink abaqusValue Constant - HiLink abaqusBadLine Error - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +" The default methods for highlighting. Can be overridden later +hi def link abaqusComment Comment +hi def link abaqusKeyword Statement +hi def link abaqusParameter Identifier +hi def link abaqusValue Constant +hi def link abaqusBadLine Error + let b:current_syntax = "abaqus" diff --git a/runtime/syntax/abc.vim b/runtime/syntax/abc.vim index 3dc098e730..1a7b3bf4be 100644 --- a/runtime/syntax/abc.vim +++ b/runtime/syntax/abc.vim @@ -4,11 +4,8 @@ " URL: http://perun.hscs.wmin.ac.uk/~jra/vim/syntax/abc.vim " Last Change: 27th April 2001 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -36,28 +33,18 @@ syn match abcComment "%.*$" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_abc_syn_inits") - if version < 508 - let did_abc_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet + +hi def link abcComment Comment +hi def link abcHeadField Type +hi def link abcBodyField Special +hi def link abcBar Statement +hi def link abcTuple Statement +hi def link abcBroken Statement +hi def link abcTie Statement +hi def link abcGuitarChord Identifier +hi def link abcNote Constant - HiLink abcComment Comment - HiLink abcHeadField Type - HiLink abcBodyField Special - HiLink abcBar Statement - HiLink abcTuple Statement - HiLink abcBroken Statement - HiLink abcTie Statement - HiLink abcGuitarChord Identifier - HiLink abcNote Constant - - delcommand HiLink -endif let b:current_syntax = "abc" diff --git a/runtime/syntax/abel.vim b/runtime/syntax/abel.vim index 05e8dac913..67d7e4f786 100644 --- a/runtime/syntax/abel.vim +++ b/runtime/syntax/abel.vim @@ -3,11 +3,8 @@ " Maintainer: John Cook <johncook3@gmail.com> " Last Change: 2011 Dec 27 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -123,48 +120,38 @@ endif syn sync minlines=1 " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_abel_syn_inits") - if version < 508 - let did_abel_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - " The default highlighting. - HiLink abelHeader abelStatement - HiLink abelSection abelStatement - HiLink abelDeclaration abelStatement - HiLink abelLogicalOperator abelOperator - HiLink abelRangeOperator abelOperator - HiLink abelAlternateOperator abelOperator - HiLink abelArithmeticOperator abelOperator - HiLink abelRelationalOperator abelOperator - HiLink abelAssignmentOperator abelOperator - HiLink abelTruthTableOperator abelOperator - HiLink abelSpecifier abelStatement - HiLink abelOperator abelStatement - HiLink abelStatement Statement - HiLink abelIdentifier Identifier - HiLink abelTypeId abelType - HiLink abelTypeIdChar abelType - HiLink abelType Type - HiLink abelNumber abelString - HiLink abelString String - HiLink abelConstant Constant - HiLink abelComment Comment - HiLink abelExtension abelSpecial - HiLink abelSpecialChar abelSpecial - HiLink abelTypeIdEnd abelSpecial - HiLink abelSpecial Special - HiLink abelDirective PreProc - HiLink abelTodo Todo - HiLink abelError Error - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +" The default highlighting. +hi def link abelHeader abelStatement +hi def link abelSection abelStatement +hi def link abelDeclaration abelStatement +hi def link abelLogicalOperator abelOperator +hi def link abelRangeOperator abelOperator +hi def link abelAlternateOperator abelOperator +hi def link abelArithmeticOperator abelOperator +hi def link abelRelationalOperator abelOperator +hi def link abelAssignmentOperator abelOperator +hi def link abelTruthTableOperator abelOperator +hi def link abelSpecifier abelStatement +hi def link abelOperator abelStatement +hi def link abelStatement Statement +hi def link abelIdentifier Identifier +hi def link abelTypeId abelType +hi def link abelTypeIdChar abelType +hi def link abelType Type +hi def link abelNumber abelString +hi def link abelString String +hi def link abelConstant Constant +hi def link abelComment Comment +hi def link abelExtension abelSpecial +hi def link abelSpecialChar abelSpecial +hi def link abelTypeIdEnd abelSpecial +hi def link abelSpecial Special +hi def link abelDirective PreProc +hi def link abelTodo Todo +hi def link abelError Error + let b:current_syntax = "abel" diff --git a/runtime/syntax/acedb.vim b/runtime/syntax/acedb.vim index 114e4aba9e..2c2cd701b7 100644 --- a/runtime/syntax/acedb.vim +++ b/runtime/syntax/acedb.vim @@ -7,11 +7,8 @@ " Syntax file to handle all $ACEDB/wspec/*.wrm files, primarily models.wrm " AceDB software is available from http://www.acedb.org -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -86,35 +83,25 @@ syn region acedbString start=/"/ end=/"/ skip=/\\"/ oneline " Rest of syntax highlighting rules start here " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_acedb_syn_inits") - if version < 508 - let did_acedb_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink acedbMagic Special - HiLink acedbHyb Special - HiLink acedbType Type - HiLink acedbOption Type - HiLink acedbSubclass Type - HiLink acedbSubtag Include - HiLink acedbFlag Include - HiLink acedbTag Include - HiLink acedbClass Todo - HiLink acedbHelp Todo - HiLink acedbXref Identifier - HiLink acedbModifier Label - HiLink acedbComment Comment - HiLink acedbBlock ModeMsg - HiLink acedbNumber Number - HiLink acedbString String +hi def link acedbMagic Special +hi def link acedbHyb Special +hi def link acedbType Type +hi def link acedbOption Type +hi def link acedbSubclass Type +hi def link acedbSubtag Include +hi def link acedbFlag Include +hi def link acedbTag Include +hi def link acedbClass Todo +hi def link acedbHelp Todo +hi def link acedbXref Identifier +hi def link acedbModifier Label +hi def link acedbComment Comment +hi def link acedbBlock ModeMsg +hi def link acedbNumber Number +hi def link acedbString String - delcommand HiLink -endif let b:current_syntax = "acedb" diff --git a/runtime/syntax/aflex.vim b/runtime/syntax/aflex.vim index 592c98e4f3..aa8b5f84fe 100644 --- a/runtime/syntax/aflex.vim +++ b/runtime/syntax/aflex.vim @@ -7,21 +7,14 @@ " Comment: Replaced sourcing c.vim file by ada.vim and rename lex* " in aflex* -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif " Read the Ada syntax to start with -if version < 600 - so <sfile>:p:h/ada.vim -else - runtime! syntax/ada.vim - unlet b:current_syntax -endif +runtime! syntax/ada.vim +unlet b:current_syntax " --- AfLex stuff --- @@ -69,31 +62,20 @@ syn sync match aflexSyncPat groupthere aflexPatBlock "^<$" syn sync match aflexSyncPat groupthere aflexPatBlock "^%%$" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet - -if version >= 508 || !exists("did_aflex_syntax_inits") - if version < 508 - let did_aflex_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - HiLink aflexSlashQuote aflexPat - HiLink aflexBrace aflexPat - HiLink aflexAbbrvComment aflexPatComment - - HiLink aflexAbbrv SpecialChar - HiLink aflexAbbrvRegExp Macro - HiLink aflexCFunctions Function - HiLink aflexMorePat SpecialChar - HiLink aflexPat Function - HiLink aflexPatComment Comment - HiLink aflexPatString Function - HiLink aflexPatTag Special - HiLink aflexSep Delimiter - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet +hi def link aflexSlashQuote aflexPat +hi def link aflexBrace aflexPat +hi def link aflexAbbrvComment aflexPatComment + +hi def link aflexAbbrv SpecialChar +hi def link aflexAbbrvRegExp Macro +hi def link aflexCFunctions Function +hi def link aflexMorePat SpecialChar +hi def link aflexPat Function +hi def link aflexPatComment Comment +hi def link aflexPatString Function +hi def link aflexPatTag Special +hi def link aflexSep Delimiter let b:current_syntax = "aflex" diff --git a/runtime/syntax/ahdl.vim b/runtime/syntax/ahdl.vim index b1417c374d..664bd3837d 100644 --- a/runtime/syntax/ahdl.vim +++ b/runtime/syntax/ahdl.vim @@ -3,11 +3,8 @@ " Maintainer: John Cook <john.cook@kla-tencor.com> " Last Change: 2001 Apr 25 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -66,29 +63,19 @@ syn match ahdlSpecialChar "[\[\]().,;]" syn sync minlines=1 " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_ahdl_syn_inits") - if version < 508 - let did_ahdl_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - " The default highlighting. - HiLink ahdlNumber ahdlString - HiLink ahdlMegafunction ahdlIdentifier - HiLink ahdlSpecialChar SpecialChar - HiLink ahdlKeyword Statement - HiLink ahdlString String - HiLink ahdlComment Comment - HiLink ahdlIdentifier Identifier - HiLink ahdlOperator Operator - HiLink ahdlTodo Todo - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +" The default highlighting. +hi def link ahdlNumber ahdlString +hi def link ahdlMegafunction ahdlIdentifier +hi def link ahdlSpecialChar SpecialChar +hi def link ahdlKeyword Statement +hi def link ahdlString String +hi def link ahdlComment Comment +hi def link ahdlIdentifier Identifier +hi def link ahdlOperator Operator +hi def link ahdlTodo Todo + let b:current_syntax = "ahdl" " vim:ts=8 diff --git a/runtime/syntax/amiga.vim b/runtime/syntax/amiga.vim index 4ccab1950f..eab9f66169 100644 --- a/runtime/syntax/amiga.vim +++ b/runtime/syntax/amiga.vim @@ -1,15 +1,12 @@ " Vim syntax file " Language: AmigaDos " Maintainer: Charles E. Campbell <NdrOchipS@PcampbellAfamily.Mbiz> -" Last Change: Oct 23, 2014 -" Version: 7 +" Last Change: Aug 31, 2016 +" Version: 9 " URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_AMIGA -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -72,30 +69,20 @@ syn match amiComment ";.*$" contains=amiCommentGroup syn sync lines=50 " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_amiga_syn_inits") - if version < 508 - let did_amiga_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink amiAlias Type - HiLink amiComment Comment - HiLink amiDev Type - HiLink amiEcho String - HiLink amiElse Statement - HiLink amiError Error - HiLink amiKey Statement - HiLink amiNumber Number - HiLink amiString String - HiLink amiTest Special - - delcommand HiLink -endif +if !exists("skip_amiga_syntax_inits") + + hi def link amiAlias Type + hi def link amiComment Comment + hi def link amiDev Type + hi def link amiEcho String + hi def link amiElse Statement + hi def link amiError Error + hi def link amiKey Statement + hi def link amiNumber Number + hi def link amiString String + hi def link amiTest Special +endif let b:current_syntax = "amiga" " vim:ts=15 diff --git a/runtime/syntax/aml.vim b/runtime/syntax/aml.vim index 7cb16f1c1f..46621edbe9 100644 --- a/runtime/syntax/aml.vim +++ b/runtime/syntax/aml.vim @@ -9,11 +9,8 @@ " of [], in order to avoid -read highlighted, " or [quote] strings highlighted -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -123,35 +120,25 @@ syn region amlSkip matchgroup=amlOutput start="&typ" end="$" contains=amlVar syn region amlSkip matchgroup=amlOutput start="&type" end="$" contains=amlVar " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_aml_syntax_inits") - if version < 508 - let did_aml_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink amlComment Comment - HiLink amlNumber Number - HiLink amlQuote String - HiLink amlVar Identifier - HiLink amlVar2 Identifier - HiLink amlFunction PreProc - HiLink amlDir Statement - HiLink amlDir2 Statement - HiLink amlDirSym Statement - HiLink amlOutput Statement - HiLink amlArcCmd ModeMsg - HiLink amlFormedCmd amlArcCmd - HiLink amlTabCmd amlArcCmd - HiLink amlInfoCmd amlArcCmd - HiLink amlVtrCmd amlArcCmd - HiLink amlFormed amlArcCmd - HiLink amlTab amlArcCmd - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link amlComment Comment +hi def link amlNumber Number +hi def link amlQuote String +hi def link amlVar Identifier +hi def link amlVar2 Identifier +hi def link amlFunction PreProc +hi def link amlDir Statement +hi def link amlDir2 Statement +hi def link amlDirSym Statement +hi def link amlOutput Statement +hi def link amlArcCmd ModeMsg +hi def link amlFormedCmd amlArcCmd +hi def link amlTabCmd amlArcCmd +hi def link amlInfoCmd amlArcCmd +hi def link amlVtrCmd amlArcCmd +hi def link amlFormed amlArcCmd +hi def link amlTab amlArcCmd + let b:current_syntax = "aml" diff --git a/runtime/syntax/ampl.vim b/runtime/syntax/ampl.vim index 7f4dfa9942..ad78f7d729 100644 --- a/runtime/syntax/ampl.vim +++ b/runtime/syntax/ampl.vim @@ -3,9 +3,8 @@ " Last Change: 2003 May 11 -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -115,33 +114,24 @@ syn keyword amplTodo contained TODO FIXME XXX -if version >= 508 || !exists("did_ampl_syntax_inits") - if version < 508 - let did_ampl_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - " The default methods for highlighting. Can be overridden later. - HiLink amplEntityKeyword Keyword - HiLink amplType Type - HiLink amplStatement Statement - HiLink amplOperators Operator - HiLink amplBasicOperators Operator - HiLink amplConditional Conditional - HiLink amplRepeat Repeat - HiLink amplStrings String - HiLink amplNumerics Number - HiLink amplSetFunction Function - HiLink amplBuiltInFunction Function - HiLink amplRandomGenerator Function - HiLink amplComment Comment - HiLink amplDotSuffix Special - HiLink amplPiecewise Special +" The default methods for highlighting. Can be overridden later. +hi def link amplEntityKeyword Keyword +hi def link amplType Type +hi def link amplStatement Statement +hi def link amplOperators Operator +hi def link amplBasicOperators Operator +hi def link amplConditional Conditional +hi def link amplRepeat Repeat +hi def link amplStrings String +hi def link amplNumerics Number +hi def link amplSetFunction Function +hi def link amplBuiltInFunction Function +hi def link amplRandomGenerator Function +hi def link amplComment Comment +hi def link amplDotSuffix Special +hi def link amplPiecewise Special - delcommand HiLink -endif let b:current_syntax = "ampl" diff --git a/runtime/syntax/antlr.vim b/runtime/syntax/antlr.vim index 19000293fb..9b0b061ae1 100644 --- a/runtime/syntax/antlr.vim +++ b/runtime/syntax/antlr.vim @@ -4,11 +4,8 @@ " LastChange: 02 May 2001 " Original: Comes from JavaCC.vim -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -18,12 +15,8 @@ endif " Those files usually have the extension *.jj " source the java.vim file -if version < 600 - so <sfile>:p:h/java.vim -else - runtime! syntax/java.vim - unlet b:current_syntax -endif +runtime! syntax/java.vim +unlet b:current_syntax "remove catching errors caused by wrong parenthesis (does not work in antlr "files) (first define them in case they have not been defined in java) @@ -53,17 +46,8 @@ syn match antlrSep "[|:]\|\.\." syn keyword antlrActionToken TOKEN SKIP MORE SPECIAL_TOKEN syn keyword antlrError DEBUG IGNORE_IN_BNF -if version >= 508 || !exists("did_antlr_syntax_inits") - if version < 508 - let did_antlr_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - HiLink antlrSep Statement - HiLink antlrPackages Statement - delcommand HiLink -endif +hi def link antlrSep Statement +hi def link antlrPackages Statement let b:current_syntax = "antlr" diff --git a/runtime/syntax/apache.vim b/runtime/syntax/apache.vim index 85cda4095a..e2315db0d7 100644 --- a/runtime/syntax/apache.vim +++ b/runtime/syntax/apache.vim @@ -9,13 +9,9 @@ " make it really linewise? " + add `display' where appropriate -" Setup -if version >= 600 - if exists("b:current_syntax") - finish - endif -else - syntax clear +" quit when a syntax file was already loaded +if exists("b:current_syntax") + finish endif syn case ignore @@ -178,37 +174,28 @@ syn match apacheSection "<\/\=\(<IfVersion\)[^>]*>" contains=apacheAnything syn keyword apacheDeclaration VirtualDocumentRoot VirtualDocumentRootIP VirtualScriptAlias VirtualScriptAliasIP " Define the default highlighting -if version >= 508 || !exists("did_apache_syntax_inits") - if version < 508 - let did_apache_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - HiLink apacheAllowOverride apacheDeclaration - HiLink apacheAllowOverrideValue apacheOption - HiLink apacheAuthType apacheDeclaration - HiLink apacheAuthTypeValue apacheOption - HiLink apacheOptionOption apacheOption - HiLink apacheDeclaration Function - HiLink apacheAnything apacheOption - HiLink apacheOption Number - HiLink apacheComment Comment - HiLink apacheFixme Todo - HiLink apacheLimitSectionKeyword apacheLimitSection - HiLink apacheLimitSection apacheSection - HiLink apacheSection Label - HiLink apacheMethodOption Type - HiLink apacheAllowDeny Include - HiLink apacheAllowDenyValue Identifier - HiLink apacheOrder Special - HiLink apacheOrderValue String - HiLink apacheString String - HiLink apacheError Error - HiLink apacheUserID Number +hi def link apacheAllowOverride apacheDeclaration +hi def link apacheAllowOverrideValue apacheOption +hi def link apacheAuthType apacheDeclaration +hi def link apacheAuthTypeValue apacheOption +hi def link apacheOptionOption apacheOption +hi def link apacheDeclaration Function +hi def link apacheAnything apacheOption +hi def link apacheOption Number +hi def link apacheComment Comment +hi def link apacheFixme Todo +hi def link apacheLimitSectionKeyword apacheLimitSection +hi def link apacheLimitSection apacheSection +hi def link apacheSection Label +hi def link apacheMethodOption Type +hi def link apacheAllowDeny Include +hi def link apacheAllowDenyValue Identifier +hi def link apacheOrder Special +hi def link apacheOrderValue String +hi def link apacheString String +hi def link apacheError Error +hi def link apacheUserID Number - delcommand HiLink -endif let b:current_syntax = "apache" diff --git a/runtime/syntax/apachestyle.vim b/runtime/syntax/apachestyle.vim index 375fc70a9c..3695a11421 100644 --- a/runtime/syntax/apachestyle.vim +++ b/runtime/syntax/apachestyle.vim @@ -20,11 +20,8 @@ " </SubSection> " </Section> -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -41,25 +38,15 @@ syn match apTagOption contained / [-\/_\.:*a-zA-Z0-9]\+/ms=s+1 syn match apTagError contained /[^>]</ms=s+1 " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_apachestyle_syn_inits") - if version < 508 - let did_apachestyle_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink apComment Comment - HiLink apOption Keyword - "HiLink apLastValue Identifier ugly? - HiLink apTag Special - HiLink apTagOption Identifier - HiLink apTagError Error +hi def link apComment Comment +hi def link apOption Keyword +"hi def link apLastValue Identifier ugly? +hi def link apTag Special +hi def link apTagOption Identifier +hi def link apTagError Error - delcommand HiLink -endif let b:current_syntax = "apachestyle" " vim: ts=8 diff --git a/runtime/syntax/aptconf.vim b/runtime/syntax/aptconf.vim index 7a31b2d15e..8cb14321e2 100644 --- a/runtime/syntax/aptconf.vim +++ b/runtime/syntax/aptconf.vim @@ -3,12 +3,9 @@ " Maintainer: Yann Amar <quidame@poivron.org> " Last Change: 2015 Dec 22 -" For version 5.x: Clear all syntax items -" For version 6.x and 7.x: Quit when a syntax file was already loaded +" quit when a syntax file was already loaded if !exists("main_syntax") - if version < 600 - syntax clear - elseif exists("b:current_syntax") + if exists("b:current_syntax") finish endif let main_syntax = 'aptconf' diff --git a/runtime/syntax/arduino.vim b/runtime/syntax/arduino.vim index 14299a441a..4a4ef82072 100644 --- a/runtime/syntax/arduino.vim +++ b/runtime/syntax/arduino.vim @@ -10,20 +10,13 @@ " Thanks to Rik, Erik Nomitch, Adam Obeng and Graeme Cross for helpful feedback! -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif " Read the C syntax to start with -if version < 600 - so <sfile>:p:h/cpp.vim -else - runtime! syntax/cpp.vim -endif +runtime! syntax/cpp.vim syn keyword arduinoConstant HIGH LOW INPUT OUTPUT syn keyword arduinoConstant DEC BIN HEX OCT BYTE diff --git a/runtime/syntax/asm.vim b/runtime/syntax/asm.vim index e5f16c5bdc..492e3e8e92 100644 --- a/runtime/syntax/asm.vim +++ b/runtime/syntax/asm.vim @@ -7,11 +7,8 @@ " Thanks to Ori Avtalion for feedback on the comment markers! -" For version 5.x: Clear all syntax items -" For version 6.0 and later: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -103,37 +100,27 @@ syn match asmDirective "\.[A-Za-z][0-9A-Za-z-_]*" syn case match " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_asm_syntax_inits") - if version < 508 - let did_asm_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - " The default methods for highlighting. Can be overridden later - HiLink asmSection Special - HiLink asmLabel Label - HiLink asmComment Comment - HiLink asmTodo Todo - HiLink asmDirective Statement - - HiLink asmInclude Include - HiLink asmCond PreCondit - HiLink asmMacro Macro - - HiLink hexNumber Number - HiLink decNumber Number - HiLink octNumber Number - HiLink binNumber Number - - HiLink asmIdentifier Identifier - HiLink asmType Type - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +" The default methods for highlighting. Can be overridden later +hi def link asmSection Special +hi def link asmLabel Label +hi def link asmComment Comment +hi def link asmTodo Todo +hi def link asmDirective Statement + +hi def link asmInclude Include +hi def link asmCond PreCondit +hi def link asmMacro Macro + +hi def link hexNumber Number +hi def link decNumber Number +hi def link octNumber Number +hi def link binNumber Number + +hi def link asmIdentifier Identifier +hi def link asmType Type + let b:current_syntax = "asm" diff --git a/runtime/syntax/asm68k.vim b/runtime/syntax/asm68k.vim index cd23517cad..1607507909 100644 --- a/runtime/syntax/asm68k.vim +++ b/runtime/syntax/asm68k.vim @@ -8,11 +8,8 @@ " Feel free to contribute... " -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -328,63 +325,53 @@ syn match asm68kDirective "\<XREF\(\.S\)\=\s" syn case match " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_asm68k_syntax_inits") - if version < 508 - let did_asm68k_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - " The default methods for highlighting. Can be overridden later - " Comment Constant Error Identifier PreProc Special Statement Todo Type - " - " Constant Boolean Character Number String - " Identifier Function - " PreProc Define Include Macro PreCondit - " Special Debug Delimiter SpecialChar SpecialComment Tag - " Statement Conditional Exception Keyword Label Operator Repeat - " Type StorageClass Structure Typedef - - HiLink asm68kComment Comment - HiLink asm68kTodo Todo - - HiLink hexNumber Number " Constant - HiLink octNumber Number " Constant - HiLink binNumber Number " Constant - HiLink decNumber Number " Constant - HiLink floatNumber Number " Constant - HiLink floatExponent Number " Constant - HiLink floatE SpecialChar " Statement - "HiLink floatE Number " Constant - - HiLink asm68kImmediate SpecialChar " Statement - "HiLink asm68kSymbol Constant - - HiLink asm68kString String " Constant - HiLink asm68kCharError Error - HiLink asm68kStringError Error - - HiLink asm68kReg Identifier - HiLink asm68kOperator Identifier - - HiLink asm68kInclude Include " PreProc - HiLink asm68kMacro Macro " PreProc - HiLink asm68kMacroParam Keyword " Statement - - HiLink asm68kDirective Special - HiLink asm68kPreCond Special - - - HiLink asm68kOpcode Statement - HiLink asm68kCond Conditional " Statement - HiLink asm68kRepeat Repeat " Statement - - HiLink asm68kLabel Type - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +" The default methods for highlighting. Can be overridden later +" Comment Constant Error Identifier PreProc Special Statement Todo Type +" +" Constant Boolean Character Number String +" Identifier Function +" PreProc Define Include Macro PreCondit +" Special Debug Delimiter SpecialChar SpecialComment Tag +" Statement Conditional Exception Keyword Label Operator Repeat +" Type StorageClass Structure Typedef + +hi def link asm68kComment Comment +hi def link asm68kTodo Todo + +hi def link hexNumber Number " Constant +hi def link octNumber Number " Constant +hi def link binNumber Number " Constant +hi def link decNumber Number " Constant +hi def link floatNumber Number " Constant +hi def link floatExponent Number " Constant +hi def link floatE SpecialChar " Statement +"hi def link floatE Number " Constant + +hi def link asm68kImmediate SpecialChar " Statement +"hi def link asm68kSymbol Constant + +hi def link asm68kString String " Constant +hi def link asm68kCharError Error +hi def link asm68kStringError Error + +hi def link asm68kReg Identifier +hi def link asm68kOperator Identifier + +hi def link asm68kInclude Include " PreProc +hi def link asm68kMacro Macro " PreProc +hi def link asm68kMacroParam Keyword " Statement + +hi def link asm68kDirective Special +hi def link asm68kPreCond Special + + +hi def link asm68kOpcode Statement +hi def link asm68kCond Conditional " Statement +hi def link asm68kRepeat Repeat " Statement + +hi def link asm68kLabel Type let b:current_syntax = "asm68k" diff --git a/runtime/syntax/asmh8300.vim b/runtime/syntax/asmh8300.vim index 48699d89c5..8560fb7ae4 100644 --- a/runtime/syntax/asmh8300.vim +++ b/runtime/syntax/asmh8300.vim @@ -3,11 +3,8 @@ " Maintainer: Kevin Dahlhausen <kdahlhaus@yahoo.com> " Last Change: 2002 Sep 19 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -52,33 +49,19 @@ syn case match " Read the general asm syntax -if version < 600 - source <sfile>:p:h/asm.vim -else - runtime! syntax/asm.vim -endif +runtime! syntax/asm.vim " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_hitachi_syntax_inits") - if version < 508 - let did_hitachi_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink asmOpcode Statement - HiLink asmRegister Identifier +hi def link asmOpcode Statement +hi def link asmRegister Identifier - " My default-color overrides: - "hi asmOpcode ctermfg=yellow - "hi asmReg ctermfg=lightmagenta +" My default-color overrides: +"hi asmOpcode ctermfg=yellow +"hi asmReg ctermfg=lightmagenta - delcommand HiLink -endif let b:current_syntax = "asmh8300" diff --git a/runtime/syntax/asn.vim b/runtime/syntax/asn.vim index 28c8efba95..e90c7e079c 100644 --- a/runtime/syntax/asn.vim +++ b/runtime/syntax/asn.vim @@ -4,11 +4,8 @@ " URL: http://www.fleiner.com/vim/syntax/asn.vim " Last Change: 2012 Oct 05 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -50,34 +47,24 @@ syn match asnBraces "[{}]" syn sync ccomment asnComment " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_asn_syn_inits") - if version < 508 - let did_asn_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - HiLink asnDefinition Function - HiLink asnBraces Function - HiLink asnStructure Statement - HiLink asnBoolValue Boolean - HiLink asnSpecial Special - HiLink asnString String - HiLink asnCharacter Character - HiLink asnSpecialCharacter asnSpecial - HiLink asnNumber asnValue - HiLink asnComment Comment - HiLink asnLineComment asnComment - HiLink asnType Type - HiLink asnTypeInfo PreProc - HiLink asnValue Number - HiLink asnExternal Include - HiLink asnTagModifier Function - HiLink asnFieldOption Type - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet +hi def link asnDefinition Function +hi def link asnBraces Function +hi def link asnStructure Statement +hi def link asnBoolValue Boolean +hi def link asnSpecial Special +hi def link asnString String +hi def link asnCharacter Character +hi def link asnSpecialCharacter asnSpecial +hi def link asnNumber asnValue +hi def link asnComment Comment +hi def link asnLineComment asnComment +hi def link asnType Type +hi def link asnTypeInfo PreProc +hi def link asnValue Number +hi def link asnExternal Include +hi def link asnTagModifier Function +hi def link asnFieldOption Type let &cpo = s:cpo_save unlet s:cpo_save diff --git a/runtime/syntax/aspperl.vim b/runtime/syntax/aspperl.vim index 0f7ef46872..5a9abedb19 100644 --- a/runtime/syntax/aspperl.vim +++ b/runtime/syntax/aspperl.vim @@ -4,11 +4,8 @@ " URL: http://nim.dhs.org/~edh/aspperl.vim " Last Change: 2001 May 09 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -16,14 +13,9 @@ if !exists("main_syntax") let main_syntax = 'perlscript' endif -if version < 600 - so <sfile>:p:h/html.vim - syn include @AspPerlScript <sfile>:p:h/perl.vim -else - runtime! syntax/html.vim - unlet b:current_syntax - syn include @AspPerlScript syntax/perl.vim -endif +runtime! syntax/html.vim +unlet b:current_syntax +syn include @AspPerlScript syntax/perl.vim syn cluster htmlPreproc add=AspPerlScriptInsideHtmlTags diff --git a/runtime/syntax/aspvbs.vim b/runtime/syntax/aspvbs.vim index f1435cb04b..f0861d8b5a 100644 --- a/runtime/syntax/aspvbs.vim +++ b/runtime/syntax/aspvbs.vim @@ -11,10 +11,8 @@ " Thanks to Dean Hall <hall@apt7.com> for testing the use of classes in " VBScripts which I've been too scared to do. -" Quit when a syntax file was already loaded -if version < 600 - syn clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -22,11 +20,7 @@ if !exists("main_syntax") let main_syntax = 'aspvbs' endif -if version < 600 - source <sfile>:p:h/html.vim -else - runtime! syntax/html.vim -endif +runtime! syntax/html.vim unlet b:current_syntax syn cluster htmlPreProc add=AspVBScriptInsideHtmlTags @@ -163,31 +157,21 @@ syn sync match htmlHighlight grouphere htmlTag "%>" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_aspvbs_syn_inits") - if version < 508 - let did_aspvbs_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - "HiLink AspVBScript Special - HiLink AspVBSLineNumber Comment - HiLink AspVBSNumber Number - HiLink AspVBSError Error - HiLink AspVBSStatement Statement - HiLink AspVBSString String - HiLink AspVBSComment Comment - HiLink AspVBSTodo Todo - HiLink AspVBSFunction Identifier - HiLink AspVBSMethods PreProc - HiLink AspVBSEvents Special - HiLink AspVBSTypeSpecifier Type - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +"hi def link AspVBScript Special +hi def link AspVBSLineNumber Comment +hi def link AspVBSNumber Number +hi def link AspVBSError Error +hi def link AspVBSStatement Statement +hi def link AspVBSString String +hi def link AspVBSComment Comment +hi def link AspVBSTodo Todo +hi def link AspVBSFunction Identifier +hi def link AspVBSMethods PreProc +hi def link AspVBSEvents Special +hi def link AspVBSTypeSpecifier Type + let b:current_syntax = "aspvbs" diff --git a/runtime/syntax/asterisk.vim b/runtime/syntax/asterisk.vim index fd4ec39c91..4a922d3f11 100644 --- a/runtime/syntax/asterisk.vim +++ b/runtime/syntax/asterisk.vim @@ -5,10 +5,9 @@ " Updated for 1.2 by Tilghman Lesher (Corydon76) " Last Change: 2015 Feb 27 " version 0.4 -" -if version < 600 - syntax clear -elseif exists("b:current_syntax") + +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -57,42 +56,33 @@ syn match asteriskSetting "^port\s*=\s*\d\{1,5}\s*$" contains=aste syn match asteriskSetting "^host\s*=\s*\(dynamic\|\(\d\{1,3}\.\d\{1,3}\.\d\{1,3}\.\d\{1,3}\)\|\([[:alnum:]][[:alnum:]\-\.]*\.[[:alpha:]]{2,10}\)\)" contains=asteriskIP,asteriskHostname " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_conf_syntax_inits") - if version < 508 - let did_conf_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet + +hi def link asteriskComment Comment +hi def link asteriskExten String +hi def link asteriskContext Preproc +hi def link asteriskPattern Type +hi def link asteriskApp Statement +hi def link asteriskInclude Preproc +hi def link asteriskIncludeBad Error +hi def link asteriskPriority Preproc +hi def link asteriskLabel Type +hi def link asteriskVar String +hi def link asteriskVarLen Function +hi def link asteriskExp Type +hi def link asteriskCodecsPermit Preproc +hi def link asteriskCodecs String +hi def link asteriskType Statement +hi def link asteriskTypeType Type +hi def link asteriskAuth String +hi def link asteriskAuthType Type +hi def link asteriskIPRange Identifier +hi def link asteriskIP Identifier +hi def link asteriskPort Identifier +hi def link asteriskHostname Identifier +hi def link asteriskSetting Statement +hi def link asteriskError Error - HiLink asteriskComment Comment - HiLink asteriskExten String - HiLink asteriskContext Preproc - HiLink asteriskPattern Type - HiLink asteriskApp Statement - HiLink asteriskInclude Preproc - HiLink asteriskIncludeBad Error - HiLink asteriskPriority Preproc - HiLink asteriskLabel Type - HiLink asteriskVar String - HiLink asteriskVarLen Function - HiLink asteriskExp Type - HiLink asteriskCodecsPermit Preproc - HiLink asteriskCodecs String - HiLink asteriskType Statement - HiLink asteriskTypeType Type - HiLink asteriskAuth String - HiLink asteriskAuthType Type - HiLink asteriskIPRange Identifier - HiLink asteriskIP Identifier - HiLink asteriskPort Identifier - HiLink asteriskHostname Identifier - HiLink asteriskSetting Statement - HiLink asteriskError Error - delcommand HiLink -endif let b:current_syntax = "asterisk" " vim: ts=8 sw=2 diff --git a/runtime/syntax/asteriskvm.vim b/runtime/syntax/asteriskvm.vim index a6c9dba418..fa55af5451 100644 --- a/runtime/syntax/asteriskvm.vim +++ b/runtime/syntax/asteriskvm.vim @@ -3,10 +3,9 @@ " Maintainer: Tilghman Lesher (Corydon76) " Last Change: 2006 Mar 21 " version 0.2 -" -if version < 600 - syntax clear -elseif exists("b:current_syntax") + +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -33,28 +32,18 @@ syn match mailboxEmail ",\zs[^@=,]*@[[:alnum:]\-\.]\+\.[[:alpha syn match comma "[,|]" contained " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -:if version >= 508 || !exists("did_conf_syntax_inits") - if version < 508 - let did_conf_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink asteriskvmComment Comment - HiLink asteriskvmContext Identifier - HiLink asteriskvmZone Type - HiLink zoneName String - HiLink zoneDef String - HiLink asteriskvmSetting Type - HiLink asteriskvmSettingBool Type - - HiLink asteriskvmMailbox Statement - HiLink mailboxEmail String - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link asteriskvmComment Comment +hi def link asteriskvmContext Identifier +hi def link asteriskvmZone Type +hi def link zoneName String +hi def link zoneDef String +hi def link asteriskvmSetting Type +hi def link asteriskvmSettingBool Type + +hi def link asteriskvmMailbox Statement +hi def link mailboxEmail String let b:current_syntax = "asteriskvm" diff --git a/runtime/syntax/atlas.vim b/runtime/syntax/atlas.vim index b8fe4356b5..1cdceab4ce 100644 --- a/runtime/syntax/atlas.vim +++ b/runtime/syntax/atlas.vim @@ -3,11 +3,8 @@ " Maintainer: Inaki Saez <jisaez@sfe.indra.es> " Last Change: 2001 May 09 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -61,37 +58,27 @@ syn sync maxlines=100 " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_atlas_syntax_inits") - if version < 508 - let did_atlas_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink atlasConditional Conditional - HiLink atlasRepeat Repeat - HiLink atlasStatement Statement - HiLink atlasNumber Number - HiLink atlasHexNumber Number - HiLink atlasOctalNumber Number - HiLink atlasBinNumber Number - HiLink atlasDecimalNumber Float - HiLink atlasFormatString String - HiLink atlasString String - HiLink atlasComment Comment - HiLink atlasComment2 Comment - HiLink atlasInclude Include - HiLink atlasDefine Macro - HiLink atlasReserved PreCondit - HiLink atlasStorageClass StorageClass - HiLink atlasIdentifier NONE - HiLink atlasSpecial Special - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link atlasConditional Conditional +hi def link atlasRepeat Repeat +hi def link atlasStatement Statement +hi def link atlasNumber Number +hi def link atlasHexNumber Number +hi def link atlasOctalNumber Number +hi def link atlasBinNumber Number +hi def link atlasDecimalNumber Float +hi def link atlasFormatString String +hi def link atlasString String +hi def link atlasComment Comment +hi def link atlasComment2 Comment +hi def link atlasInclude Include +hi def link atlasDefine Macro +hi def link atlasReserved PreCondit +hi def link atlasStorageClass StorageClass +hi def link atlasIdentifier NONE +hi def link atlasSpecial Special + let b:current_syntax = "atlas" diff --git a/runtime/syntax/autohotkey.vim b/runtime/syntax/autohotkey.vim index 764f94b11a..3b826af6f5 100644 --- a/runtime/syntax/autohotkey.vim +++ b/runtime/syntax/autohotkey.vim @@ -1,8 +1,10 @@ " Vim syntax file " Language: AutoHotkey script file -" Maintainer: SungHyun Nam <goweol@gmail.com> -" Previous Maintainer: Nikolai Weibull <now@bitwi.se> -" Latest Revision: 2015-10-29 +" Maintainer: Michael Wong +" https://github.com/mmikeww/autohotkey.vim +" Latest Revision: 2017-01-23 +" Previous Maintainers: SungHyun Nam <goweol@gmail.com> +" Nikolai Weibull <now@bitwi.se> if exists("b:current_syntax") finish @@ -17,68 +19,11 @@ syn keyword autohotkeyTodo \ contained \ TODO FIXME XXX NOTE -syn cluster autohotkeyCommentGroup - \ contains= - \ autohotkeyTodo, - \ @Spell - -syn match autohotkeyComment - \ display - \ contains=@autohotkeyCommentGroup - \ '`\@<!;.*$' - -syn region autohotkeyComment - \ contains=@autohotkeyCommentGroup - \ matchgroup=autohotkeyCommentStart - \ start='/\*' - \ end='\*/' - +" only these chars are valid as escape sequences: ,%`;nrbtvaf +" https://autohotkey.com/docs/commands/_EscapeChar.htm syn match autohotkeyEscape \ display - \ '`.' - -syn match autohotkeyHotkey - \ contains=autohotkeyKey, - \ autohotkeyHotkeyDelimiter - \ display - \ '^.\{-}::' - -syn match autohotkeyKey - \ contained - \ display - \ '^.\{-}' - -syn match autohotkeyDelimiter - \ contained - \ display - \ '::' - -syn match autohotkeyHotstringDefinition - \ contains=autohotkeyHotstring, - \ autohotkeyHotstringDelimiter - \ display - \ '^:\%(B0\|C1\|K\d\+\|P\d\+\|S[IPE]\|Z\d\=\|[*?COR]\)*:.\{-}::' - -syn match autohotkeyHotstring - \ contained - \ display - \ '.\{-}' - -syn match autohotkeyHotstringDelimiter - \ contained - \ display - \ '::' - -syn match autohotkeyHotstringDelimiter - \ contains=autohotkeyHotstringOptions - \ contained - \ display - \ ':\%(B0\|C1\|K\d\+\|P\d\+\|S[IPE]\|Z\d\=\|[*?COR]\):' - -syn match autohotkeyHotstringOptions - \ contained - \ display - \ '\%(B0\|C1\|K\d\+\|P\d\+\|S[IPE]\|Z\d\=\|[*?COR]\)' + \ '`[,%`;nrbtvaf]' syn region autohotkeyString \ display @@ -88,39 +33,46 @@ syn region autohotkeyString \ end=+"+ \ contains=autohotkeyEscape -syn region autohotkeyVariable +syn match autohotkeyVariable \ display \ oneline \ contains=autohotkeyBuiltinVariable - \ matchgroup=autohotkeyVariableDelimiter - \ start="%" - \ end="%" \ keepend + \ '%\S\{-}%' syn keyword autohotkeyBuiltinVariable \ A_Space A_Tab - \ A_WorkingDir A_ScriptDir A_ScriptName A_ScriptFullPath A_LineNumber - \ A_LineFile A_AhkVersion A_AhkPAth A_IsCompiled A_ExitReason - \ A_YYYY A_MM A_DD A_MMMM A_MMM A_DDDD A_DDD A_WDay A_YWeek A_Hour A_Min + \ A_WorkingDir A_ScriptDir A_ScriptName A_ScriptFullPath A_ScriptHwnd A_LineNumber + \ A_LineFile A_ThisFunc A_ThisLabel A_AhkVersion A_AhkPath A_IsUnicode A_IsCompiled A_ExitReason + \ A_YYYY A_MM A_DD A_MMMM A_MMM A_DDDD A_DDD A_WDay A_YDay A_YWeek A_Hour A_Min + \ A_Mon A_Year A_MDay A_NumBatchLines \ A_Sec A_MSec A_Now A_NowUTC A_TickCount - \ A_IsSuspended A_BatchLines A_TitleMatchMode A_TitleMatchModeSpeed - \ A_DetectHiddenWindows A_DetectHiddenText A_AutoTrim A_STringCaseSense - \ A_FormatInteger A_FormatFloat A_KeyDelay A_WinDelay A_ControlDelay - \ A_MouseDelay A_DefaultMouseSpeed A_IconHidden A_IconTip A_IconFile + \ A_IsSuspended A_IsPaused A_IsCritical A_BatchLines A_TitleMatchMode A_TitleMatchModeSpeed + \ A_DetectHiddenWindows A_DetectHiddenText A_AutoTrim A_StringCaseSense + \ A_FileEncoding A_FormatInteger A_FormatFloat A_KeyDelay A_WinDelay A_ControlDelay + \ A_SendMode A_SendLevel A_StoreCapsLockMode A_KeyDelay A_KeyDelayDuration + \ A_KeyDelayPlay A_KeyDelayPlayDuration A_MouseDelayPlay + \ A_MouseDelay A_DefaultMouseSpeed A_RegView A_IconHidden A_IconTip A_IconFile + \ A_CoordModeToolTip A_CoordModePixel A_CoordModeMouse A_CoordModeCaret A_CoordModeMenu \ A_IconNumber - \ A_TimeIdle A_TimeIdlePhysical + \ A_TimeIdle A_TimeIdlePhysical A_DefaultGui A_DefaultListView A_DefaultTreeView \ A_Gui A_GuiControl A_GuiWidth A_GuiHeight A_GuiX A_GuiY A_GuiEvent \ A_GuiControlEvent A_EventInfo \ A_ThisMenuItem A_ThisMenu A_ThisMenuItemPos A_ThisHotkey A_PriorHotkey - \ A_TimeSinceThisHotkey A_TimeSincePriorHotkey A_EndChar + \ A_PriorKey A_TimeSinceThisHotkey A_TimeSincePriorHotkey A_EndChar \ ComSpec A_Temp A_OSType A_OSVersion A_Language A_ComputerName A_UserName + \ A_Is64BitOS A_PtrSize \ A_WinDir A_ProgramFiles ProgramFiles A_AppData A_AppDataCommon A_Desktop \ A_DesktopCommon A_StartMenu A_StartMenuCommon A_Programs \ A_ProgramsCommon A_Startup A_StartupCommon A_MyDocuments A_IsAdmin - \ A_ScreenWidth A_ScreenHeight A_IPAddress1 A_IPAddress2 A_IPAddress3 + \ A_ScreenWidth A_ScreenHeight A_ScreenDPI A_IPAddress1 A_IPAddress2 A_IPAddress3 \ A_IPAddress4 \ A_Cursor A_CaretX A_CaretY Clipboard ClipboardAll ErrorLevel A_LastError \ A_Index A_LoopFileName A_LoopRegName A_LoopReadLine A_LoopField + \ A_LoopFileExt A_LoopFileFullPath A_LoopFileLongPath A_LoopFileShortPath + \ A_LoopFileShortName A_LoopFileDir A_LoopFileTimeModified A_LoopFileTimeCreated + \ A_LoopFileTimeAccessed A_LoopFileAttrib A_LoopFileSize A_LoopFileSizeKB A_LoopFileSizeMB + \ A_LoopRegType A_LoopRegKey A_LoopRegSubKey A_LoopRegTimeModified syn match autohotkeyBuiltinVariable \ contained @@ -130,7 +82,7 @@ syn match autohotkeyBuiltinVariable syn keyword autohotkeyCommand \ ClipWait EnvGet EnvSet EnvUpdate \ Drive DriveGet DriveSpaceFree FileAppend FileCopy FileCopyDir - \ FileCreateDir FileCreateShortcut FileDelete FileGetAttrib + \ FileCreateDir FileCreateShortcut FileDelete FileGetAttrib FileEncoding \ FileGetShortcut FileGetSize FileGetTime FileGetVersion FileInstall \ FileMove FileMoveDir FileReadLine FileRead FileRecycle FileRecycleEmpty \ FileRemoveDir FileSelectFolder FileSelectFile FileSetAttrib FileSetTime @@ -153,7 +105,7 @@ syn keyword autohotkeyCommand \ SoundSetWaveVolume \ FormatTime IfInString IfNotInString Sort StringCaseSense StringGetPos \ StringLeft StringRight StringLower StringUpper StringMid StringReplace - \ StringSplit StringTrimLeft StringTrimRight + \ StringSplit StringTrimLeft StringTrimRight StringLen \ Control ControlClick ControlFocus ControlGet ControlGetFocus \ ControlGetPos ControlGetText ControlMove ControlSend ControlSendRaw \ ControlSetText Menu PostMessage SendMessage SetControlDelay @@ -164,12 +116,16 @@ syn keyword autohotkeyCommand \ WinGetText WinGetTitle WinHide WinKill WinMaximize WinMinimize \ WinMinimizeAll WinMinimizeAllUndo WinMove WinRestore WinSet \ WinSetTitle WinShow WinWait WinWaitActive WinWaitNotActive WinWaitClose + \ SetCapsLockState SetNumLockState SetScrollLockState syn keyword autohotkeyFunction \ InStr RegExMatch RegExReplace StrLen SubStr Asc Chr \ DllCall VarSetCapacity WinActive WinExist IsLabel OnMessage \ Abs Ceil Exp Floor Log Ln Mod Round Sqrt Sin Cos Tan ASin ACos ATan - \ FileExist GetKeyState + \ FileExist GetKeyState NumGet NumPut StrGet StrPut RegisterCallback + \ IsFunc Trim LTrim RTrim IsObject Object Array FileOpen + \ ComObjActive ComObjArray ComObjConnect ComObjCreate ComObjGet + \ ComObjError ComObjFlags ComObjQuery ComObjType ComObjValue ComObject syn keyword autohotkeyStatement \ Break Continue Exit ExitApp Gosub Goto OnExit Pause Return @@ -180,7 +136,9 @@ syn keyword autohotkeyRepeat syn keyword autohotkeyConditional \ IfExist IfNotExist If IfEqual IfLess IfGreater Else - \ IfWinExist IfWinNotExist + \ IfWinExist IfWinNotExist IfWinActive IfWinNotActive + \ IfNotEqual IfLessOrEqual IfGreaterOrEqual + \ while until for in syn match autohotkeyPreProcStart \ nextgroup= @@ -200,6 +158,7 @@ syn keyword autohotkeyPreProc \ HotkeyInterval HotKeyModifierTimeout \ Hotstring \ IfWinActive IfWinNotActive IfWinExist IfWinNotExist + \ If IfTimeout \ MaxHotkeysPerInterval MaxThreads MaxThreadsBuffer MaxThreadsPerHotkey \ UseHook InstallKeybdHook InstallMouseHook \ KeyHistory @@ -213,6 +172,10 @@ syn keyword autohotkeyPreProc \ MaxMem \ NoEnv \ Persistent + \ LTrim + \ InputLevel + \ MenuMaskKey + \ Warn syn keyword autohotkeyMatchClass \ ahk_group ahk_class ahk_id ahk_pid @@ -243,11 +206,74 @@ syn match autohotkeyFloat syn keyword autohotkeyType \ local \ global + \ static + \ byref syn keyword autohotkeyBoolean \ true \ false +syn match autohotkeyHotkey + \ contains=autohotkeyKey, + \ autohotkeyHotkeyDelimiter + \ display + \ '^.\{-}::' + +syn match autohotkeyKey + \ contained + \ display + \ '^.\{-}' + +syn match autohotkeyDelimiter + \ contained + \ display + \ '::' + +" allowable hotstring options: +" https://autohotkey.com/docs/Hotstrings.htm +syn match autohotkeyHotstringDefinition + \ contains=autohotkeyHotstring, + \ autohotkeyHotstringDelimiter + \ display + \ '^\s*:\%([*?]\|[BORZ]0\?\|C[01]\?\|K\d\+\|P\d\+\|S[IPE]\)*:.\{-}::' + +syn match autohotkeyHotstring + \ contained + \ display + \ '.\{-}' + +syn match autohotkeyHotstringDelimiter + \ contained + \ display + \ '::' + +syn match autohotkeyHotstringDelimiter + \ contains=autohotkeyHotstringOptions + \ contained + \ display + \ ':\%([*?]\|[BORZ]0\?\|C[01]\?\|K\d\+\|P\d\+\|S[IPE]\)*:' + +syn match autohotkeyHotstringOptions + \ contained + \ display + \ '\%([*?]\|[BORZ]0\?\|C[01]\?\|K\d\+\|P\d\+\|S[IPE]\)*' + +syn cluster autohotkeyCommentGroup + \ contains= + \ autohotkeyTodo, + \ @Spell + +syn match autohotkeyComment + \ display + \ contains=@autohotkeyCommentGroup + \ '\%(^;\|\s\+;\).*$' + +syn region autohotkeyComment + \ contains=@autohotkeyCommentGroup + \ matchgroup=autohotkeyCommentStart + \ start='^\s*/\*' + \ end='^\s*\*/' + " TODO: Shouldn't we look for g:, b:, variables before defaulting to " something? if exists("g:autohotkey_syntax_sync_minlines") diff --git a/runtime/syntax/automake.vim b/runtime/syntax/automake.vim index eea2a9f38c..2a215a9e04 100644 --- a/runtime/syntax/automake.vim +++ b/runtime/syntax/automake.vim @@ -18,18 +18,12 @@ " EXTRA_SOURCES. " Standard syntax initialization -if version < 600 - syntax clear -elseif exists("b:current_syntax") +if exists("b:current_syntax") finish endif " Read the Makefile syntax to start with -if version < 600 - source <sfile>:p:h/make.vim -else - runtime! syntax/make.vim -endif +runtime! syntax/make.vim syn match automakePrimary "^\w\+\(_PROGRAMS\|_LIBRARIES\|_LISP\|_PYTHON\|_JAVA\|_SCRIPTS\|_DATA\|_HEADERS\|_MANS\|_TEXINFOS\|_LTLIBRARIES\)\s*\ze+\==" syn match automakePrimary "^TESTS\s*\ze+\=="me=e-1 @@ -59,34 +53,24 @@ syn region automakeMakeSString start=+'+ skip=+\\'+ end=+'+ contains=makeIde syn region automakeMakeBString start=+`+ skip=+\\`+ end=+`+ contains=makeIdent,makeSString,makeDString,makeNextLine,automakeSubstitution " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_automake_syntax_inits") - if version < 508 - let did_automake_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink automakePrimary Statement - HiLink automakeSecondary Type - HiLink automakeExtra Special - HiLink automakeOptions Special - HiLink automakeClean Special - HiLink automakeSubdirs Statement - HiLink automakeConditional PreProc - HiLink automakeSubst PreProc - HiLink automakeComment1 makeComment - HiLink automakeComment2 makeComment - HiLink automakeMakeError makeError - HiLink automakeBadSubst makeError - HiLink automakeMakeDString makeDString - HiLink automakeMakeSString makeSString - HiLink automakeMakeBString makeBString +hi def link automakePrimary Statement +hi def link automakeSecondary Type +hi def link automakeExtra Special +hi def link automakeOptions Special +hi def link automakeClean Special +hi def link automakeSubdirs Statement +hi def link automakeConditional PreProc +hi def link automakeSubst PreProc +hi def link automakeComment1 makeComment +hi def link automakeComment2 makeComment +hi def link automakeMakeError makeError +hi def link automakeBadSubst makeError +hi def link automakeMakeDString makeDString +hi def link automakeMakeSString makeSString +hi def link automakeMakeBString makeBString - delcommand HiLink -endif let b:current_syntax = "automake" diff --git a/runtime/syntax/ave.vim b/runtime/syntax/ave.vim index 2a0a9d85af..e63e7d2c30 100644 --- a/runtime/syntax/ave.vim +++ b/runtime/syntax/ave.vim @@ -11,11 +11,8 @@ " I use some technologies to automatically load avenue scripts " into ArcView. -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -37,7 +34,7 @@ syn match aveNumber "[+-]\=\<[0-9]\+\>" " Operator syn keyword aveOperator or and max min xor mod by -" 'not' is a kind of a problem: Its an Operator as well as a method +" 'not' is a kind of a problem: It's an Operator as well as a method " 'not' is only marked as an Operator if not applied as method syn match aveOperator "[^\.]not[^a-zA-Z]" @@ -59,34 +56,24 @@ syn match aveTypos "==" syn match aveTypos "!=" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting+yet -if version >= 508 || !exists("did_ave_syn_inits") - if version < 508 - let did_ave_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting+yet - HiLink aveStatement Statement +hi def link aveStatement Statement - HiLink aveString String - HiLink aveNumber Number +hi def link aveString String +hi def link aveNumber Number - HiLink aveFixVariables Special - HiLink aveVariables Identifier - HiLink globalVariables Special - HiLink aveConst Special +hi def link aveFixVariables Special +hi def link aveVariables Identifier +hi def link globalVariables Special +hi def link aveConst Special - HiLink aveClassMethods Function +hi def link aveClassMethods Function - HiLink aveOperator Operator - HiLink aveComment Comment +hi def link aveOperator Operator +hi def link aveComment Comment - HiLink aveTypos Error +hi def link aveTypos Error - delcommand HiLink -endif let b:current_syntax = "ave" diff --git a/runtime/syntax/avra.vim b/runtime/syntax/avra.vim index ebf0aaff11..0e02bd8397 100644 --- a/runtime/syntax/avra.vim +++ b/runtime/syntax/avra.vim @@ -2,14 +2,12 @@ " Language: AVR Assembler (AVRA) " AVRA Home: http://avra.sourceforge.net/index.html " AVRA Version: 1.3.0 +" Last Update: 2016 Oct 7 " Maintainer: Marius Ghita <mhitza@gmail.com> let s:cpo_save = &cpo set cpo&vim -setlocal iskeyword=a-z,A-Z,48-57,.,_ -" 'isident' is a global option, better not set it -" setlocal isident=a-z,A-Z,48-57,.,_ syn case ignore syn keyword avraRegister r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 r13 r14 diff --git a/runtime/syntax/awk.vim b/runtime/syntax/awk.vim index ae0f217580..7c0682ce9f 100644 --- a/runtime/syntax/awk.vim +++ b/runtime/syntax/awk.vim @@ -1,7 +1,7 @@ " Vim syntax file " Language: awk, nawk, gawk, mawk " Maintainer: Antonio Colombo <azc100@gmail.com> -" Last Change: 2016 Jul 15 +" Last Change: 2016 Sep 05 " AWK ref. is: Alfred V. Aho, Brian W. Kernighan, Peter J. Weinberger " The AWK Programming Language, Addison-Wesley, 1988 @@ -71,6 +71,10 @@ syn keyword awkVariables ARGC ARGV ARGIND ENVIRON ERRNO FILENAME syn keyword awkVariables FNR NF FUNCTAB NR PROCINFO RLENGTH RSTART syn keyword awkVariables RT SYMTAB +" Arithmetic operators: +, and - take care of ++, and -- +syn match awkOperator "+\|-\|\*\|/\|%\|=" +syn match awkOperator "+=\|-=\|\*=\|/=\|%=" +syn match awkOperator "\^\|\^=" " Octal format character. syn match awkSpecialCharacter display contained "\\[0-7]\{1,3\}" @@ -124,11 +128,6 @@ syn case match "syn match awkIdentifier "\<[a-zA-Z_][a-zA-Z0-9_]*\>" -" Arithmetic operators: +, and - take care of ++, and -- -syn match awkOperator "+\|-\|\*\|/\|%\|=" -syn match awkOperator "+=\|-=\|\*=\|/=\|%=" -syn match awkOperator "^\|^=" - " Comparison expressions. syn match awkExpression "==\|>=\|=>\|<=\|=<\|\!=" syn match awkExpression "\~\|\!\~" @@ -167,7 +166,6 @@ syn region awkArray transparent start="\[" end="\]" contains=awkArray,awkArrayE syn sync ccomment awkArray maxlines=10 " Define the default highlighting. -" Only used when an item doesn't have highlighting yet hi def link awkConditional Conditional hi def link awkFunction Function hi def link awkRepeat Repeat diff --git a/runtime/syntax/ayacc.vim b/runtime/syntax/ayacc.vim index fedd0e80a0..6fb6aec85d 100644 --- a/runtime/syntax/ayacc.vim +++ b/runtime/syntax/ayacc.vim @@ -6,21 +6,14 @@ " Comment: Replaced sourcing c.vim file by ada.vim and rename yacc* " in ayacc* -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif " Read the Ada syntax to start with -if version < 600 - so <sfile>:p:h/ada.vim -else - runtime! syntax/ada.vim - unlet b:current_syntax -endif +runtime! syntax/ada.vim +unlet b:current_syntax let s:cpo_save = &cpo set cpo&vim @@ -54,35 +47,26 @@ syn match ayaccSep "^[ \t]*%}" syn match ayaccCurlyError "[{}]" syn region ayaccAction matchgroup=ayaccCurly start="{" end="}" contains=ALLBUT,@ayaccActionGroup -if version >= 508 || !exists("did_ayacc_syntax_inits") - if version < 508 - let did_ayacc_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - " Internal ayacc highlighting links - HiLink ayaccBrkt ayaccStmt - HiLink ayaccKey ayaccStmt - HiLink ayaccOper ayaccStmt - HiLink ayaccUnionStart ayaccKey +" Internal ayacc highlighting links +hi def link ayaccBrkt ayaccStmt +hi def link ayaccKey ayaccStmt +hi def link ayaccOper ayaccStmt +hi def link ayaccUnionStart ayaccKey - " External ayacc highlighting links - HiLink ayaccCurly Delimiter - HiLink ayaccCurlyError Error - HiLink ayaccDefinition Function - HiLink ayaccDelim Function - HiLink ayaccKeyActn Special - HiLink ayaccSectionSep Todo - HiLink ayaccSep Delimiter - HiLink ayaccStmt Statement - HiLink ayaccType Type +" External ayacc highlighting links +hi def link ayaccCurly Delimiter +hi def link ayaccCurlyError Error +hi def link ayaccDefinition Function +hi def link ayaccDelim Function +hi def link ayaccKeyActn Special +hi def link ayaccSectionSep Todo +hi def link ayaccSep Delimiter +hi def link ayaccStmt Statement +hi def link ayaccType Type - " since Bram doesn't like my Delimiter :| - HiLink Delimiter Type - delcommand HiLink -endif +" since Bram doesn't like my Delimiter :| +hi def link Delimiter Type let b:current_syntax = "ayacc" diff --git a/runtime/syntax/b.vim b/runtime/syntax/b.vim index b470ab9ef3..01532be75d 100644 --- a/runtime/syntax/b.vim +++ b/runtime/syntax/b.vim @@ -5,11 +5,8 @@ " LastChange: 8 Dec 2007 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -69,58 +66,48 @@ syn region bPreProc start="^\s*#\s*\(pragma\>\|line\>\|warning\>\|warn\>\|error syn sync ccomment bComment minlines=10 " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet - -if version >= 508 || !exists("did_b_syntax_inits") - if version < 508 - let did_b_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - " The default methods for highlighting. Can be overridden later - HiLink bLabel Label - HiLink bUserLabel Label - HiLink bConditional Conditional - HiLink bRepeat Repeat - HiLink bLogic Special - HiLink bCharacter Character - HiLink bSpecialCharacter bSpecial - HiLink bNumber Number - HiLink bFloat Float - HiLink bOctalError bError - HiLink bParenError bError -" HiLink bInParen bError - HiLink bCommentError bError - HiLink bBoolean Identifier - HiLink bConstant Identifier - HiLink bGuard Identifier - HiLink bOperator Operator - HiLink bKeywords Operator - HiLink bOps Identifier - HiLink bStructure Structure - HiLink bStorageClass StorageClass - HiLink bInclude Include - HiLink bPreProc PreProc - HiLink bDefine Macro - HiLink bIncluded bString - HiLink bError Error - HiLink bStatement Statement - HiLink bPreCondit PreCondit - HiLink bType Type - HiLink bCommentError bError - HiLink bCommentString bString - HiLink bComment2String bString - HiLink bCommentSkip bComment - HiLink bString String - HiLink bComment Comment - HiLink bSpecial SpecialChar - HiLink bTodo Todo - "hi link bIdentifier Identifier - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + + +" The default methods for highlighting. Can be overridden later +hi def link bLabel Label +hi def link bUserLabel Label +hi def link bConditional Conditional +hi def link bRepeat Repeat +hi def link bLogic Special +hi def link bCharacter Character +hi def link bSpecialCharacter bSpecial +hi def link bNumber Number +hi def link bFloat Float +hi def link bOctalError bError +hi def link bParenError bError +" hi def link bInParen bError +hi def link bCommentError bError +hi def link bBoolean Identifier +hi def link bConstant Identifier +hi def link bGuard Identifier +hi def link bOperator Operator +hi def link bKeywords Operator +hi def link bOps Identifier +hi def link bStructure Structure +hi def link bStorageClass StorageClass +hi def link bInclude Include +hi def link bPreProc PreProc +hi def link bDefine Macro +hi def link bIncluded bString +hi def link bError Error +hi def link bStatement Statement +hi def link bPreCondit PreCondit +hi def link bType Type +hi def link bCommentError bError +hi def link bCommentString bString +hi def link bComment2String bString +hi def link bCommentSkip bComment +hi def link bString String +hi def link bComment Comment +hi def link bSpecial SpecialChar +hi def link bTodo Todo +"hi link bIdentifier Identifier let b:current_syntax = "b" diff --git a/runtime/syntax/baan.vim b/runtime/syntax/baan.vim index 5009218b60..9a42a43918 100644 --- a/runtime/syntax/baan.vim +++ b/runtime/syntax/baan.vim @@ -4,15 +4,8 @@ " Originally owned by: Erwin Smit / Her van de Vliert " Last change: v1.17 2006/04/26 10:40:18 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -" -if version < 600 - syntax clear - if exists("baan_fold") - unlet baan_fold - endif -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -1894,40 +1887,30 @@ syn keyword baanBshell bclm.productidlicensed syn keyword baanBshell bclm.set.desktop " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_baan_syn_inits") - if version < 508 - let did_baan_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink baanConditional Conditional - HiLink baan3gl Statement - HiLink baan3glpre PreProc - HiLink baan4gl Statement - HiLink baan4glh Statement - HiLink baansql Statement - HiLink baansqlh Statement - HiLink baanDalHook Statement - HiLink baanNumber Number - HiLink baanString String - HiLink baanOpenStringError Error - HiLink baanConstant Constant - HiLink baanComment Comment - HiLink baanCommenth Comment - HiLink baanUncommented Comment - HiLink baanDLLUsage Comment - HiLink baanFunUsage Comment - HiLink baanIdentifier Normal - HiLink baanBshell Function - HiLink baanType Type - HiLink baanStorageClass StorageClass +hi def link baanConditional Conditional +hi def link baan3gl Statement +hi def link baan3glpre PreProc +hi def link baan4gl Statement +hi def link baan4glh Statement +hi def link baansql Statement +hi def link baansqlh Statement +hi def link baanDalHook Statement +hi def link baanNumber Number +hi def link baanString String +hi def link baanOpenStringError Error +hi def link baanConstant Constant +hi def link baanComment Comment +hi def link baanCommenth Comment +hi def link baanUncommented Comment +hi def link baanDLLUsage Comment +hi def link baanFunUsage Comment +hi def link baanIdentifier Normal +hi def link baanBshell Function +hi def link baanType Type +hi def link baanStorageClass StorageClass - delcommand HiLink -endif let b:current_syntax = "baan" diff --git a/runtime/syntax/basic.vim b/runtime/syntax/basic.vim index c72032da27..488ddc0ec4 100644 --- a/runtime/syntax/basic.vim +++ b/runtime/syntax/basic.vim @@ -8,11 +8,8 @@ " This syntax file not a complete implementation yet. Send suggestions to the " maintainer. -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -143,34 +140,24 @@ syn match basicFilenumber "#\d\+" syn match basicMathsOperator "-\|=\|[:<>+\*^/\\]\|AND\|OR" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_basic_syntax_inits") - if version < 508 - let did_basic_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink basicLabel Label - HiLink basicConditional Conditional - HiLink basicRepeat Repeat - HiLink basicLineNumber Comment - HiLink basicNumber Number - HiLink basicError Error - HiLink basicStatement Statement - HiLink basicString String - HiLink basicComment Comment - HiLink basicSpecial Special - HiLink basicTodo Todo - HiLink basicFunction Identifier - HiLink basicTypeSpecifier Type - HiLink basicFilenumber basicTypeSpecifier - "hi basicMathsOperator term=bold cterm=bold gui=bold +hi def link basicLabel Label +hi def link basicConditional Conditional +hi def link basicRepeat Repeat +hi def link basicLineNumber Comment +hi def link basicNumber Number +hi def link basicError Error +hi def link basicStatement Statement +hi def link basicString String +hi def link basicComment Comment +hi def link basicSpecial Special +hi def link basicTodo Todo +hi def link basicFunction Identifier +hi def link basicTypeSpecifier Type +hi def link basicFilenumber basicTypeSpecifier +"hi basicMathsOperator term=bold cterm=bold gui=bold - delcommand HiLink -endif let b:current_syntax = "basic" diff --git a/runtime/syntax/bc.vim b/runtime/syntax/bc.vim index 965afc35b1..4cd9d6388a 100644 --- a/runtime/syntax/bc.vim +++ b/runtime/syntax/bc.vim @@ -5,11 +5,8 @@ " (Dominique Pelle added @Spell) " Available on: www.gjh.sk/~vlado/bc.vim -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -53,27 +50,17 @@ syn match bcParenError ")" syn case match " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_bc_syntax_inits") - if version < 508 - let did_bc_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink bcKeyword Statement - HiLink bcType Type - HiLink bcConstant Constant - HiLink bcNumber Number - HiLink bcComment Comment - HiLink bcString String - HiLink bcSpecialChar SpecialChar - HiLink bcParenError Error - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link bcKeyword Statement +hi def link bcType Type +hi def link bcConstant Constant +hi def link bcNumber Number +hi def link bcComment Comment +hi def link bcString String +hi def link bcSpecialChar SpecialChar +hi def link bcParenError Error + let b:current_syntax = "bc" " vim: ts=8 diff --git a/runtime/syntax/bib.vim b/runtime/syntax/bib.vim index 8bd0528e1e..f2b99e961b 100644 --- a/runtime/syntax/bib.vim +++ b/runtime/syntax/bib.vim @@ -2,17 +2,14 @@ " Language: BibTeX (bibliographic database format for (La)TeX) " Maintainer: Bernd Feige <Bernd.Feige@gmx.net> " Filenames: *.bib -" Last Change: 2016 May 31 +" Last Change: 2016 Sep 12 " Thanks to those who pointed out problems with this file or supplied fixes! " Initialization " ============== -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -74,7 +71,7 @@ syn keyword bibNSEntryKw contained mrclass mrnumber mrreviewer fjournal coden " Clusters " ======== -syn cluster bibVarContents contains=bibUnescapedSpecial,bibBrace,bibParen +syn cluster bibVarContents contains=bibUnescapedSpecial,bibBrace,bibParen,bibMath " This cluster is empty but things can be added externally: "syn cluster bibCommentContents @@ -84,6 +81,7 @@ syn match bibUnescapedSpecial contained /[^\\][%&]/hs=s+1 syn match bibKey contained /\s*[^ \t}="]\+,/hs=s,he=e-1 nextgroup=bibField syn match bibVariable contained /[^{}," \t=]/ syn region bibComment start=/./ end=/^\s*@/me=e-1 contains=@bibCommentContents nextgroup=bibEntry +syn region bibMath contained start=/\$/ end=/\$/ skip=/\(\\\$\)/ syn region bibQuote contained start=/"/ end=/"/ skip=/\(\\"\)/ contains=@bibVarContents syn region bibBrace contained start=/{/ end=/}/ skip=/\(\\[{}]\)/ contains=@bibVarContents syn region bibParen contained start=/(/ end=/)/ skip=/\(\\[()]\)/ contains=@bibVarContents @@ -91,11 +89,7 @@ syn region bibField contained start="\S\+\s*=\s*" end=/[}),]/me=e-1 contains=bib syn region bibEntryData contained start=/[{(]/ms=e+1 end=/[})]/me=e-1 contains=bibKey,bibField " Actually, 5.8 <= Vim < 6.0 would ignore the `fold' keyword anyway, but Vim<5.8 would produce " an error, so we explicitly distinguish versions with and without folding functionality: -if version < 600 - syn region bibEntry start=/@\S\+\s*[{(]/ end=/^\s*[})]/ transparent contains=bibType,bibEntryData nextgroup=bibComment -else - syn region bibEntry start=/@\S\+\s*[{(]/ end=/^\s*[})]/ transparent fold contains=bibType,bibEntryData nextgroup=bibComment -endif +syn region bibEntry start=/@\S\+\s*[{(]/ end=/^\s*[})]/ transparent fold contains=bibType,bibEntryData nextgroup=bibComment syn region bibComment2 start=/@Comment\s*[{(]/ end=/^\s*[})]/me=e-1 contains=@bibCommentContents nextgroup=bibEntry " Synchronization @@ -107,25 +101,16 @@ syn sync minlines=50 " Highlighting defaults " ===================== " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_bib_syn_inits") - if version < 508 - let did_bib_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - HiLink bibType Identifier - HiLink bibEntryKw Statement - HiLink bibNSEntryKw PreProc - HiLink bibKey Special - HiLink bibVariable Constant - HiLink bibUnescapedSpecial Error - HiLink bibComment Comment - HiLink bibComment2 Comment - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link bibType Identifier +hi def link bibEntryKw Statement +hi def link bibNSEntryKw PreProc +hi def link bibKey Special +hi def link bibVariable Constant +hi def link bibUnescapedSpecial Error +hi def link bibComment Comment +hi def link bibComment2 Comment let b:current_syntax = "bib" diff --git a/runtime/syntax/bindzone.vim b/runtime/syntax/bindzone.vim index d599a85db2..df3c789d98 100644 --- a/runtime/syntax/bindzone.vim +++ b/runtime/syntax/bindzone.vim @@ -9,11 +9,8 @@ " " $Id: bindzone.vim 12 2011-07-16 21:09:57Z julian $ -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -70,40 +67,30 @@ syn region zoneParen contained start="(" end=")" contains=zoneSerial, syn match zoneComment /;.*/ " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_bind_zone_syn_inits") - if version < 508 - let did_bind_zone_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink zoneDirective Macro - - HiLink zoneUnknown Error - - HiLink zoneOrigin Statement - HiLink zoneOwnerName Statement - HiLink zoneDomain Identifier - - HiLink zoneSpecial Special - HiLink zoneTTL Constant - HiLink zoneClass Include - HiLink zoneRRType Type - - HiLink zoneIPAddr Number - HiLink zoneIP6Addr Number - HiLink zoneText String - HiLink zoneNumber Number - HiLink zoneSerial Special - - HiLink zoneErrParen Error - HiLink zoneComment Comment - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link zoneDirective Macro + +hi def link zoneUnknown Error + +hi def link zoneOrigin Statement +hi def link zoneOwnerName Statement +hi def link zoneDomain Identifier + +hi def link zoneSpecial Special +hi def link zoneTTL Constant +hi def link zoneClass Include +hi def link zoneRRType Type + +hi def link zoneIPAddr Number +hi def link zoneIP6Addr Number +hi def link zoneText String +hi def link zoneNumber Number +hi def link zoneSerial Special + +hi def link zoneErrParen Error +hi def link zoneComment Comment + let b:current_syntax = "bindzone" diff --git a/runtime/syntax/blank.vim b/runtime/syntax/blank.vim index 60251c966c..6d2e3fd7bd 100644 --- a/runtime/syntax/blank.vim +++ b/runtime/syntax/blank.vim @@ -3,11 +3,8 @@ " Maintainer: Rafal M. Sulejman <unefunge@friko2.onet.pl> " Last change: 2011 Dec 28 by Thilo Six -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -28,22 +25,12 @@ syn match blankNumber "\[[0-9]\+\]" syn case match " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_blank_syntax_inits") - if version < 508 - let did_blank_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink blankInstruction Statement - HiLink blankNumber Number - HiLink blankString String - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link blankInstruction Statement +hi def link blankNumber Number +hi def link blankString String + let b:current_syntax = "blank" diff --git a/runtime/syntax/bst.vim b/runtime/syntax/bst.vim index e7836d7811..5ebef16460 100644 --- a/runtime/syntax/bst.vim +++ b/runtime/syntax/bst.vim @@ -4,21 +4,12 @@ " Filenames: *.bst " $Id: bst.vim,v 1.2 2007/05/05 18:24:42 vimboss Exp $ -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif -if version < 600 - command -nargs=1 SetIsk set iskeyword=<args> -else - command -nargs=1 SetIsk setlocal iskeyword=<args> -endif -SetIsk 48-57,#,$,',.,A-Z,a-z -delcommand SetIsk +setlocal iskeyword=48-57,#,$,',.,A-Z,a-z syn case ignore @@ -62,27 +53,17 @@ syn keyword bstField title type syn keyword bstField volume year " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_bst_syn_inits") - if version < 508 - let did_bst_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink bstComment Comment - HiLink bstString String - HiLink bstCommand PreProc - HiLink bstBuiltIn Statement - HiLink bstField Special - HiLink bstNumber Number - HiLink bstType Type - HiLink bstIdentifier Identifier - HiLink bstError Error - delcommand HiLink -endif +hi def link bstComment Comment +hi def link bstString String +hi def link bstCommand PreProc +hi def link bstBuiltIn Statement +hi def link bstField Special +hi def link bstNumber Number +hi def link bstType Type +hi def link bstIdentifier Identifier +hi def link bstError Error let b:current_syntax = "bst" diff --git a/runtime/syntax/btm.vim b/runtime/syntax/btm.vim index 4fd5b2db99..4f9253ff9f 100644 --- a/runtime/syntax/btm.vim +++ b/runtime/syntax/btm.vim @@ -11,11 +11,8 @@ "//- After unary operators like "defined" can assume token type. "// Should there be more of these? -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -184,45 +181,35 @@ syn keyword btmCommand unlock unset ver verify vol syn keyword btmCommand vscrput y " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_btm_syntax_inits") - if version < 508 - let did_btm_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink btmLabel Special - HiLink btmLabelMark Special - HiLink btmCmdDivider Special - HiLink btmConditional btmStatement - HiLink btmDotBoolOp btmStatement - HiLink btmRepeat btmStatement - HiLink btmEchoCommand btmStatement - HiLink btmEchoParam btmStatement - HiLink btmStatement Statement - HiLink btmTodo Todo - HiLink btmString String - HiLink btmNumber Number - HiLink btmComment Comment - HiLink btmArgument Identifier - HiLink btmVariable Identifier - HiLink btmEcho String - HiLink btmBIFMatch btmStatement - HiLink btmBuiltInFunc btmStatement - HiLink btmBuiltInVar btmStatement - HiLink btmSpecialVar btmStatement - HiLink btmCommand btmStatement - - "optional highlighting - "HiLink btmShowTab Error - "HiLink btmShowTabc Error - "hiLink btmIdentifier Identifier - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link btmLabel Special +hi def link btmLabelMark Special +hi def link btmCmdDivider Special +hi def link btmConditional btmStatement +hi def link btmDotBoolOp btmStatement +hi def link btmRepeat btmStatement +hi def link btmEchoCommand btmStatement +hi def link btmEchoParam btmStatement +hi def link btmStatement Statement +hi def link btmTodo Todo +hi def link btmString String +hi def link btmNumber Number +hi def link btmComment Comment +hi def link btmArgument Identifier +hi def link btmVariable Identifier +hi def link btmEcho String +hi def link btmBIFMatch btmStatement +hi def link btmBuiltInFunc btmStatement +hi def link btmBuiltInVar btmStatement +hi def link btmSpecialVar btmStatement +hi def link btmCommand btmStatement + +"optional highlighting +"hi def link btmShowTab Error +"hi def link btmShowTabc Error +"hi def link btmIdentifier Identifier + let b:current_syntax = "btm" diff --git a/runtime/syntax/bzr.vim b/runtime/syntax/bzr.vim index ef5445bf45..43178b8a1a 100644 --- a/runtime/syntax/bzr.vim +++ b/runtime/syntax/bzr.vim @@ -11,11 +11,8 @@ " Gioele Barabucci " for idea of diff highlighting -" For version 5.x: Clear all syntax items. -" For version 6.x: Quit when a syntax file was already loaded. -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded. +if exists("b:current_syntax") finish endif @@ -40,24 +37,14 @@ syn sync clear syn sync match bzrSync grouphere bzrRegion "^-\{14} This line and the following will be ignored -\{14}$"me=s-1 " Define the default highlighting. -" For version 5.7 and earlier: only when not done already. -" For version 5.8 and later: only when an item doesn't have highlighting yet. -if version >= 508 || !exists("did_bzr_syn_inits") - if version <= 508 - let did_bzr_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink bzrRemoved Constant - HiLink bzrAdded Identifier - HiLink bzrModified Special - HiLink bzrRenamed Special - HiLink bzrUnchanged Special - HiLink bzrUnknown Special - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet. + +hi def link bzrRemoved Constant +hi def link bzrAdded Identifier +hi def link bzrModified Special +hi def link bzrRenamed Special +hi def link bzrUnchanged Special +hi def link bzrUnknown Special + let b:current_syntax = "bzr" diff --git a/runtime/syntax/c.vim b/runtime/syntax/c.vim index 3fe3256059..cc99f674a1 100644 --- a/runtime/syntax/c.vim +++ b/runtime/syntax/c.vim @@ -1,7 +1,7 @@ " Vim syntax file " Language: C " Maintainer: Bram Moolenaar <Bram@vim.org> -" Last Change: 2016 Apr 10 +" Last Change: 2016 Nov 17 " Quit when a (custom) syntax file was already loaded if exists("b:current_syntax") @@ -295,7 +295,7 @@ if !exists("c_no_ansi") || exists("c_ansi_constants") || exists("c_gnu") syn keyword cConstant SCHAR_MIN SINT_MIN SLONG_MIN SSHRT_MIN syn keyword cConstant SCHAR_MAX SINT_MAX SLONG_MAX SSHRT_MAX if !exists("c_no_c99") - syn keyword cConstant __func__ + syn keyword cConstant __func__ __VA_ARGS__ syn keyword cConstant LLONG_MIN LLONG_MAX ULLONG_MAX syn keyword cConstant INT8_MIN INT16_MIN INT32_MIN INT64_MIN syn keyword cConstant INT8_MAX INT16_MAX INT32_MAX INT64_MAX @@ -358,36 +358,36 @@ if !exists("c_no_c99") " ISO C99 endif " Accept %: for # (C99) -syn region cPreCondit start="^\s*\(%:\|#\)\s*\(if\|ifdef\|ifndef\|elif\)\>" skip="\\$" end="$" keepend contains=cComment,cCommentL,cCppString,cCharacter,cCppParen,cParenError,cNumbers,cCommentError,cSpaceError -syn match cPreConditMatch display "^\s*\(%:\|#\)\s*\(else\|endif\)\>" +syn region cPreCondit start="^\s*\zs\(%:\|#\)\s*\(if\|ifdef\|ifndef\|elif\)\>" skip="\\$" end="$" keepend contains=cComment,cCommentL,cCppString,cCharacter,cCppParen,cParenError,cNumbers,cCommentError,cSpaceError +syn match cPreConditMatch display "^\s*\zs\(%:\|#\)\s*\(else\|endif\)\>" if !exists("c_no_if0") syn cluster cCppOutInGroup contains=cCppInIf,cCppInElse,cCppInElse2,cCppOutIf,cCppOutIf2,cCppOutElse,cCppInSkip,cCppOutSkip - syn region cCppOutWrapper start="^\s*\(%:\|#\)\s*if\s\+0\+\s*\($\|//\|/\*\|&\)" end=".\@=\|$" contains=cCppOutIf,cCppOutElse,@NoSpell fold - syn region cCppOutIf contained start="0\+" matchgroup=cCppOutWrapper end="^\s*\(%:\|#\)\s*endif\>" contains=cCppOutIf2,cCppOutElse + syn region cCppOutWrapper start="^\s*\zs\(%:\|#\)\s*if\s\+0\+\s*\($\|//\|/\*\|&\)" end=".\@=\|$" contains=cCppOutIf,cCppOutElse,@NoSpell fold + syn region cCppOutIf contained start="0\+" matchgroup=cCppOutWrapper end="^\s*\zs\(%:\|#\)\s*endif\>" contains=cCppOutIf2,cCppOutElse if !exists("c_no_if0_fold") syn region cCppOutIf2 contained matchgroup=cCppOutWrapper start="0\+" end="^\s*\(%:\|#\)\s*\(else\>\|elif\s\+\(0\+\s*\($\|//\|/\*\|&\)\)\@!\|endif\>\)"me=s-1 contains=cSpaceError,cCppOutSkip,@Spell fold else syn region cCppOutIf2 contained matchgroup=cCppOutWrapper start="0\+" end="^\s*\(%:\|#\)\s*\(else\>\|elif\s\+\(0\+\s*\($\|//\|/\*\|&\)\)\@!\|endif\>\)"me=s-1 contains=cSpaceError,cCppOutSkip,@Spell endif - syn region cCppOutElse contained matchgroup=cCppOutWrapper start="^\s*\(%:\|#\)\s*\(else\|elif\)" end="^\s*\(%:\|#\)\s*endif\>"me=s-1 contains=TOP,cPreCondit - syn region cCppInWrapper start="^\s*\(%:\|#\)\s*if\s\+0*[1-9]\d*\s*\($\|//\|/\*\||\)" end=".\@=\|$" contains=cCppInIf,cCppInElse fold - syn region cCppInIf contained matchgroup=cCppInWrapper start="\d\+" end="^\s*\(%:\|#\)\s*endif\>" contains=TOP,cPreCondit + syn region cCppOutElse contained matchgroup=cCppOutWrapper start="^\s*\zs\(%:\|#\)\s*\(else\|elif\)" end="^\s*\zs\(%:\|#\)\s*endif\>"me=s-1 contains=TOP,cPreCondit + syn region cCppInWrapper start="^\s*\zs\(%:\|#\)\s*if\s\+0*[1-9]\d*\s*\($\|//\|/\*\||\)" end=".\@=\|$" contains=cCppInIf,cCppInElse fold + syn region cCppInIf contained matchgroup=cCppInWrapper start="\d\+" end="^\s*\zs\(%:\|#\)\s*endif\>" contains=TOP,cPreCondit if !exists("c_no_if0_fold") - syn region cCppInElse contained start="^\s*\(%:\|#\)\s*\(else\>\|elif\s\+\(0*[1-9]\d*\s*\($\|//\|/\*\||\)\)\@!\)" end=".\@=\|$" containedin=cCppInIf contains=cCppInElse2 fold + syn region cCppInElse contained start="^\s*\zs\(%:\|#\)\s*\(else\>\|elif\s\+\(0*[1-9]\d*\s*\($\|//\|/\*\||\)\)\@!\)" end=".\@=\|$" containedin=cCppInIf contains=cCppInElse2 fold else - syn region cCppInElse contained start="^\s*\(%:\|#\)\s*\(else\>\|elif\s\+\(0*[1-9]\d*\s*\($\|//\|/\*\||\)\)\@!\)" end=".\@=\|$" containedin=cCppInIf contains=cCppInElse2 + syn region cCppInElse contained start="^\s*\zs\(%:\|#\)\s*\(else\>\|elif\s\+\(0*[1-9]\d*\s*\($\|//\|/\*\||\)\)\@!\)" end=".\@=\|$" containedin=cCppInIf contains=cCppInElse2 endif - syn region cCppInElse2 contained matchgroup=cCppInWrapper start="^\s*\(%:\|#\)\s*\(else\|elif\)\([^/]\|/[^/*]\)*" end="^\s*\(%:\|#\)\s*endif\>"me=s-1 contains=cSpaceError,cCppOutSkip,@Spell - syn region cCppOutSkip contained start="^\s*\(%:\|#\)\s*\(if\>\|ifdef\>\|ifndef\>\)" skip="\\$" end="^\s*\(%:\|#\)\s*endif\>" contains=cSpaceError,cCppOutSkip - syn region cCppInSkip contained matchgroup=cCppInWrapper start="^\s*\(%:\|#\)\s*\(if\s\+\(\d\+\s*\($\|//\|/\*\||\|&\)\)\@!\|ifdef\>\|ifndef\>\)" skip="\\$" end="^\s*\(%:\|#\)\s*endif\>" containedin=cCppOutElse,cCppInIf,cCppInSkip contains=TOP,cPreProc + syn region cCppInElse2 contained matchgroup=cCppInWrapper start="^\s*\zs\(%:\|#\)\s*\(else\|elif\)\([^/]\|/[^/*]\)*" end="^\s*\zs\(%:\|#\)\s*endif\>"me=s-1 contains=cSpaceError,cCppOutSkip,@Spell + syn region cCppOutSkip contained start="^\s*\zs\(%:\|#\)\s*\(if\>\|ifdef\>\|ifndef\>\)" skip="\\$" end="^\s*\zs\(%:\|#\)\s*endif\>" contains=cSpaceError,cCppOutSkip + syn region cCppInSkip contained matchgroup=cCppInWrapper start="^\s*\zs\(%:\|#\)\s*\(if\s\+\(\d\+\s*\($\|//\|/\*\||\|&\)\)\@!\|ifdef\>\|ifndef\>\)" skip="\\$" end="^\s*\zs\(%:\|#\)\s*endif\>" containedin=cCppOutElse,cCppInIf,cCppInSkip contains=TOP,cPreProc endif syn region cIncluded display contained start=+"+ skip=+\\\\\|\\"+ end=+"+ syn match cIncluded display contained "<[^>]*>" -syn match cInclude display "^\s*\(%:\|#\)\s*include\>\s*["<]" contains=cIncluded +syn match cInclude display "^\s*\zs\(%:\|#\)\s*include\>\s*["<]" contains=cIncluded "syn match cLineSkip "\\$" syn cluster cPreProcGroup contains=cPreCondit,cIncluded,cInclude,cDefine,cErrInParen,cErrInBracket,cUserLabel,cSpecial,cOctalZero,cCppOutWrapper,cCppInWrapper,@cCppOutInGroup,cFormat,cNumber,cFloat,cOctal,cOctalError,cNumbersCom,cString,cCommentSkip,cCommentString,cComment2String,@cCommentGroup,cCommentStartError,cParen,cBracket,cMulti,cBadBlock -syn region cDefine start="^\s*\(%:\|#\)\s*\(define\|undef\)\>" skip="\\$" end="$" keepend contains=ALLBUT,@cPreProcGroup,@Spell -syn region cPreProc start="^\s*\(%:\|#\)\s*\(pragma\>\|line\>\|warning\>\|warn\>\|error\>\)" skip="\\$" end="$" keepend contains=ALLBUT,@cPreProcGroup,@Spell +syn region cDefine start="^\s*\zs\(%:\|#\)\s*\(define\|undef\)\>" skip="\\$" end="$" keepend contains=ALLBUT,@cPreProcGroup,@Spell +syn region cPreProc start="^\s*\zs\(%:\|#\)\s*\(pragma\>\|line\>\|warning\>\|warn\>\|error\>\)" skip="\\$" end="$" keepend contains=ALLBUT,@cPreProcGroup,@Spell " Highlight User Labels syn cluster cMultiGroup contains=cIncluded,cSpecial,cCommentSkip,cCommentString,cComment2String,@cCommentGroup,cCommentStartError,cUserCont,cUserLabel,cBitField,cOctalZero,cCppOutWrapper,cCppInWrapper,@cCppOutInGroup,cFormat,cNumber,cFloat,cOctal,cOctalError,cNumbersCom,cCppParen,cCppBracket,cCppString @@ -396,21 +396,21 @@ if s:ft ==# 'c' || exists("cpp_no_cpp11") endif " Avoid matching foo::bar() in C++ by requiring that the next char is not ':' syn cluster cLabelGroup contains=cUserLabel -syn match cUserCont display "^\s*\I\i*\s*:$" contains=@cLabelGroup -syn match cUserCont display ";\s*\I\i*\s*:$" contains=@cLabelGroup +syn match cUserCont display "^\s*\zs\I\i*\s*:$" contains=@cLabelGroup +syn match cUserCont display ";\s*\zs\I\i*\s*:$" contains=@cLabelGroup if s:ft ==# 'cpp' - syn match cUserCont display "^\s*\%(class\|struct\|enum\)\@!\I\i*\s*:[^:]"me=e-1 contains=@cLabelGroup - syn match cUserCont display ";\s*\%(class\|struct\|enum\)\@!\I\i*\s*:[^:]"me=e-1 contains=@cLabelGroup + syn match cUserCont display "^\s*\zs\%(class\|struct\|enum\)\@!\I\i*\s*:[^:]"me=e-1 contains=@cLabelGroup + syn match cUserCont display ";\s*\zs\%(class\|struct\|enum\)\@!\I\i*\s*:[^:]"me=e-1 contains=@cLabelGroup else - syn match cUserCont display "^\s*\I\i*\s*:[^:]"me=e-1 contains=@cLabelGroup - syn match cUserCont display ";\s*\I\i*\s*:[^:]"me=e-1 contains=@cLabelGroup + syn match cUserCont display "^\s*\zs\I\i*\s*:[^:]"me=e-1 contains=@cLabelGroup + syn match cUserCont display ";\s*\zs\I\i*\s*:[^:]"me=e-1 contains=@cLabelGroup endif syn match cUserLabel display "\I\i*" contained " Avoid recognizing most bitfields as labels -syn match cBitField display "^\s*\I\i*\s*:\s*[1-9]"me=e-1 contains=cType -syn match cBitField display ";\s*\I\i*\s*:\s*[1-9]"me=e-1 contains=cType +syn match cBitField display "^\s*\zs\I\i*\s*:\s*[1-9]"me=e-1 contains=cType +syn match cBitField display ";\s*\zs\I\i*\s*:\s*[1-9]"me=e-1 contains=cType if exists("c_minlines") let b:c_minlines = c_minlines diff --git a/runtime/syntax/cabal.vim b/runtime/syntax/cabal.vim index 4130bac894..6641294a31 100644 --- a/runtime/syntax/cabal.vim +++ b/runtime/syntax/cabal.vim @@ -18,11 +18,8 @@ " v1.0: Cabal syntax in vimball format " (thanks to Magnus Therning) -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -105,27 +102,17 @@ syn match cabalStatement "\ctype" syn match cabalStatement "\cversion" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_cabal_syn_inits") - if version < 508 - let did_cabal_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink cabalVersion Number - HiLink cabalTruth Boolean - HiLink cabalComment Comment - HiLink cabalStatement Statement - HiLink cabalCategory Type - HiLink cabalFunction Function - HiLink cabalConditional Conditional - HiLink cabalOperator Operator - HiLink cabalCompiler Constant - delcommand HiLink -endif +hi def link cabalVersion Number +hi def link cabalTruth Boolean +hi def link cabalComment Comment +hi def link cabalStatement Statement +hi def link cabalCategory Type +hi def link cabalFunction Function +hi def link cabalConditional Conditional +hi def link cabalOperator Operator +hi def link cabalCompiler Constant let b:current_syntax = "cabal" diff --git a/runtime/syntax/cf.vim b/runtime/syntax/cf.vim index 63d976d9ce..6310bc3bde 100644 --- a/runtime/syntax/cf.vim +++ b/runtime/syntax/cf.vim @@ -379,61 +379,58 @@ syn region cfqueryTag contained start=+<cfquery+ end=+>+ keepend contains=cfTagN syn region cfSqlregion start=+<cfquery\_[^>]*>+ keepend end=+</cfquery>+me=s-1 matchgroup=NONE contains=@cfSql,cfComment,@htmlTagNameCluster,cfqueryTag,cfHashRegion " Define the highlighting. -command -nargs=+ CfHiLink hi def link <args> if exists("d_noinclude_html") " The default html-style highlighting copied from html.vim. - CfHiLink htmlTag Function - CfHiLink htmlEndTag Identifier - CfHiLink htmlArg Type - CfHiLink htmlTagName htmlStatement - CfHiLink htmlValue String - CfHiLink htmlPreProc PreProc - CfHiLink htmlString String - CfHiLink htmlStatement Statement - CfHiLink htmlValue String - CfHiLink htmlTagError htmlError - CfHiLink htmlError Error + hi def link htmlTag Function + hi def link htmlEndTag Identifier + hi def link htmlArg Type + hi def link htmlTagName htmlStatement + hi def link htmlValue String + hi def link htmlPreProc PreProc + hi def link htmlString String + hi def link htmlStatement Statement + hi def link htmlValue String + hi def link htmlTagError htmlError + hi def link htmlError Error endif -CfHiLink cfTagName Statement -CfHiLink cfCustomTagName Statement -CfHiLink cfArg Type -CfHiLink cfFunctionName Function -CfHiLink cfHashRegion PreProc -CfHiLink cfComment Comment -CfHiLink cfCommentTodo Todo -CfHiLink cfOperator Operator -CfHiLink cfOperatorMatch Operator -CfHiLink cfScope Title -CfHiLink cfBool Constant - -CfHiLink cfscriptBlock Special -CfHiLink cfscriptTag htmlTag -CfHiLink cfSetRegion PreProc -CfHiLink cfSetLHSRegion htmlTag -CfHiLink cfSetTagEnd htmlTag - -CfHiLink cfScriptLineComment Comment -CfHiLink cfScriptComment Comment -CfHiLink cfScriptStringS String -CfHiLink cfScriptStringD String -CfHiLink cfScriptNumber cfScriptValue -CfHiLink cfScriptConditional Conditional -CfHiLink cfScriptRepeat Repeat -CfHiLink cfScriptBranch Conditional -CfHiLink cfScriptSpecial Type -CfHiLink cfScriptStatement Statement -CfHiLink cfScriptBraces Function -CfHiLink cfScriptKeyword Function -CfHiLink cfScriptError Error -CfHiLink cfDeprecatedTag Error -CfHiLink cfDeprecatedFunction Error -CfHiLink cfScrParenError cfScriptError - -CfHiLink cfqueryTag htmlTag - -delcommand CfHiLink +hi def link cfTagName Statement +hi def link cfCustomTagName Statement +hi def link cfArg Type +hi def link cfFunctionName Function +hi def link cfHashRegion PreProc +hi def link cfComment Comment +hi def link cfCommentTodo Todo +hi def link cfOperator Operator +hi def link cfOperatorMatch Operator +hi def link cfScope Title +hi def link cfBool Constant + +hi def link cfscriptBlock Special +hi def link cfscriptTag htmlTag +hi def link cfSetRegion PreProc +hi def link cfSetLHSRegion htmlTag +hi def link cfSetTagEnd htmlTag + +hi def link cfScriptLineComment Comment +hi def link cfScriptComment Comment +hi def link cfScriptStringS String +hi def link cfScriptStringD String +hi def link cfScriptNumber cfScriptValue +hi def link cfScriptConditional Conditional +hi def link cfScriptRepeat Repeat +hi def link cfScriptBranch Conditional +hi def link cfScriptSpecial Type +hi def link cfScriptStatement Statement +hi def link cfScriptBraces Function +hi def link cfScriptKeyword Function +hi def link cfScriptError Error +hi def link cfDeprecatedTag Error +hi def link cfDeprecatedFunction Error +hi def link cfScrParenError cfScriptError + +hi def link cfqueryTag htmlTag let b:current_syntax = "cf" diff --git a/runtime/syntax/cfg.vim b/runtime/syntax/cfg.vim index b82fb26fc0..a50297d418 100644 --- a/runtime/syntax/cfg.vim +++ b/runtime/syntax/cfg.vim @@ -3,11 +3,8 @@ " Maintainer: Igor N. Prischepoff (igor@tyumbit.ru, pri_igor@mail.ru) " Last change: 2012 Aug 11 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists ("b:current_syntax") +" quit when a syntax file was already loaded +if exists ("b:current_syntax") finish endif @@ -36,25 +33,16 @@ syn match CfgComment ";.*" syn match CfgComment "\/\/.*" " Define the default hightlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_cfg_syn_inits") - if version < 508 - let did_cfg_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - HiLink CfgOnOff Label - HiLink CfgComment Comment - HiLink CfgSection Type - HiLink CfgString String - HiLink CfgParams Keyword - HiLink CfgValues Constant - HiLink CfgDirectory Directory - HiLink UncPath Directory - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet +hi def link CfgOnOff Label +hi def link CfgComment Comment +hi def link CfgSection Type +hi def link CfgString String +hi def link CfgParams Keyword +hi def link CfgValues Constant +hi def link CfgDirectory Directory +hi def link UncPath Directory + + let b:current_syntax = "cfg" " vim:ts=8 diff --git a/runtime/syntax/ch.vim b/runtime/syntax/ch.vim index add7395093..61f475bc99 100644 --- a/runtime/syntax/ch.vim +++ b/runtime/syntax/ch.vim @@ -8,21 +8,14 @@ " Ch is a C/C++ interpreter with many high level extensions " -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif " Read the C syntax to start with -if version < 600 - so <sfile>:p:h/c.vim -else - runtime! syntax/c.vim - unlet b:current_syntax -endif +runtime! syntax/c.vim +unlet b:current_syntax " Ch extentions @@ -33,20 +26,12 @@ syn keyword chStructure class syn keyword chType string_t array " Default highlighting -if version >= 508 || !exists("did_ch_syntax_inits") - if version < 508 - let did_ch_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - HiLink chAccess chStatement - HiLink chExceptions Exception - HiLink chStatement Statement - HiLink chType Type - HiLink chStructure Structure - delcommand HiLink -endif + +hi def link chAccess chStatement +hi def link chExceptions Exception +hi def link chStatement Statement +hi def link chType Type +hi def link chStructure Structure let b:current_syntax = "ch" diff --git a/runtime/syntax/change.vim b/runtime/syntax/change.vim index e9bf88b9d6..a92767e903 100644 --- a/runtime/syntax/change.vim +++ b/runtime/syntax/change.vim @@ -7,11 +7,8 @@ " in the articles by Donald E. Knuth and Silvio Levy cited in "web.vim" and " "cweb.vim" respectively. -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syn clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -21,21 +18,11 @@ syn region changeFromMaterial start="^@x.*$"ms=e+1 end="^@y.*$"me=s-1 syn region changeToMaterial start="^@y.*$"ms=e+1 end="^@z.*$"me=s-1 " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_change_syntax_inits") - if version < 508 - let did_change_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink changeFromMaterial String - HiLink changeToMaterial Statement - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link changeFromMaterial String +hi def link changeToMaterial Statement + let b:current_syntax = "change" diff --git a/runtime/syntax/changelog.vim b/runtime/syntax/changelog.vim index 33d31ba466..cf9021ef05 100644 --- a/runtime/syntax/changelog.vim +++ b/runtime/syntax/changelog.vim @@ -4,11 +4,8 @@ " Maintainer: Corinna Vinschen <vinschen@redhat.com> " Last Change: June 1, 2003 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -28,17 +25,12 @@ endif syn match changelogText "^\s.*$" contains=changelogMail,changelogNumber,changelogMonth,changelogDay,changelogError syn match changelogHeader "^\S.*$" contains=changelogNumber,changelogMonth,changelogDay,changelogMail -if version < 600 - syn region changelogFiles start="^\s\+[+*]\s" end=":\s" end="^$" contains=changelogBullet,changelogColon,changelogError keepend - syn region changelogFiles start="^\s\+[([]" end=":\s" end="^$" contains=changelogBullet,changelogColon,changelogError keepend - syn match changelogColon contained ":\s" -else - syn region changelogFiles start="^\s\+[+*]\s" end=":" end="^$" contains=changelogBullet,changelogColon,changelogFuncs,changelogError keepend - syn region changelogFiles start="^\s\+[([]" end=":" end="^$" contains=changelogBullet,changelogColon,changelogFuncs,changelogError keepend - syn match changelogFuncs contained "(.\{-})" extend - syn match changelogFuncs contained "\[.\{-}]" extend - syn match changelogColon contained ":" -endif +syn region changelogFiles start="^\s\+[+*]\s" end=":" end="^$" contains=changelogBullet,changelogColon,changelogFuncs,changelogError keepend +syn region changelogFiles start="^\s\+[([]" end=":" end="^$" contains=changelogBullet,changelogColon,changelogFuncs,changelogError keepend +syn match changelogFuncs contained "(.\{-})" extend +syn match changelogFuncs contained "\[.\{-}]" extend +syn match changelogColon contained ":" + syn match changelogBullet contained "^\s\+[+*]\s" contains=changelogError syn match changelogMail contained "<[A-Za-z0-9\._:+-]\+@[A-Za-z0-9\._-]\+>" syn keyword changelogMonth contained jan feb mar apr may jun jul aug sep oct nov dec @@ -46,32 +38,20 @@ syn keyword changelogDay contained mon tue wed thu fri sat sun syn match changelogNumber contained "[.-]*[0-9]\+" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_changelog_syntax_inits") - if version < 508 - let did_changelog_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet + +hi def link changelogText Normal +hi def link changelogBullet Type +hi def link changelogColon Type +hi def link changelogFiles Comment +hi def link changelogFuncs Comment +hi def link changelogHeader Statement +hi def link changelogMail Special +hi def link changelogNumber Number +hi def link changelogMonth Number +hi def link changelogDay Number +hi def link changelogError Folded - HiLink changelogText Normal - HiLink changelogBullet Type - HiLink changelogColon Type - HiLink changelogFiles Comment - if version >= 600 - HiLink changelogFuncs Comment - endif - HiLink changelogHeader Statement - HiLink changelogMail Special - HiLink changelogNumber Number - HiLink changelogMonth Number - HiLink changelogDay Number - HiLink changelogError Folded - - delcommand HiLink -endif let b:current_syntax = "changelog" diff --git a/runtime/syntax/chaskell.vim b/runtime/syntax/chaskell.vim index 3f764d0e8a..4b1e8c53be 100644 --- a/runtime/syntax/chaskell.vim +++ b/runtime/syntax/chaskell.vim @@ -9,10 +9,6 @@ let b:hs_chs=1 " Include standard Haskell highlighting -if version < 600 - source <sfile>:p:h/haskell.vim -else - runtime! syntax/haskell.vim -endif +runtime! syntax/haskell.vim " vim: ts=8 diff --git a/runtime/syntax/cheetah.vim b/runtime/syntax/cheetah.vim index 7eb17567cf..9567ecbbca 100644 --- a/runtime/syntax/cheetah.vim +++ b/runtime/syntax/cheetah.vim @@ -8,11 +8,8 @@ " PSP-style tags: <% .. %> (obsoleted feature) " doc-strings and header comments (rarely used feature) -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -36,25 +33,15 @@ syn match cheetahComment "##.*$" display syn region cheetahMultiLineComment start="#\*" end="\*#" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_cheetah_syn_inits") - if version < 508 - let did_cheetah_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink cheetahPlaceHolder Identifier - HiLink cheetahDirective PreCondit - HiLink cheetahKeyword Define - HiLink cheetahContinuation Special - HiLink cheetahComment Comment - HiLink cheetahMultiLineComment Comment - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link cheetahPlaceHolder Identifier +hi def link cheetahDirective PreCondit +hi def link cheetahKeyword Define +hi def link cheetahContinuation Special +hi def link cheetahComment Comment +hi def link cheetahMultiLineComment Comment + let b:current_syntax = "cheetah" diff --git a/runtime/syntax/chill.vim b/runtime/syntax/chill.vim index e5200fe722..b95df68bc8 100644 --- a/runtime/syntax/chill.vim +++ b/runtime/syntax/chill.vim @@ -11,11 +11,8 @@ " & Communications LTd.) -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -124,67 +121,57 @@ endif exec "syn sync ccomment chillComment minlines=" . chill_minlines " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_ch_syntax_inits") - if version < 508 - let did_ch_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink chillLabel Label - HiLink chillUserLabel Label - HiLink chillConditional Conditional - " hi chillConditional term=bold ctermfg=red guifg=red gui=bold - - HiLink chillRepeat Repeat - HiLink chillProcess Repeat - HiLink chillSignal Repeat - HiLink chillCharacter Character - HiLink chillSpecialCharacter chillSpecial - HiLink chillNumber Number - HiLink chillFloat Float - HiLink chillOctalError chillError - HiLink chillParenError chillError - HiLink chillInParen chillError - HiLink chillCommentError chillError - HiLink chillSpaceError chillError - HiLink chillOperator Operator - HiLink chillStructure Structure - HiLink chillBlock Operator - HiLink chillScope Operator - "hi chillEDML term=underline ctermfg=DarkRed guifg=Red - HiLink chillEDML PreProc - "hi chillBoolConst term=bold ctermfg=brown guifg=brown - HiLink chillBoolConst Constant - "hi chillLogical term=bold ctermfg=brown guifg=brown - HiLink chillLogical Constant - HiLink chillStorageClass StorageClass - HiLink chillInclude Include - HiLink chillPreProc PreProc - HiLink chillDefine Macro - HiLink chillIncluded chillString - HiLink chillError Error - HiLink chillStatement Statement - HiLink chillPreCondit PreCondit - HiLink chillType Type - HiLink chillCommentError chillError - HiLink chillCommentString chillString - HiLink chillComment2String chillString - HiLink chillCommentSkip chillComment - HiLink chillString String - HiLink chillComment Comment - " hi chillComment term=None ctermfg=lightblue guifg=lightblue - HiLink chillSpecial SpecialChar - HiLink chillTodo Todo - HiLink chillBlock Statement - "HiLink chillIdentifier Identifier - HiLink chillBracket Delimiter - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link chillLabel Label +hi def link chillUserLabel Label +hi def link chillConditional Conditional +" hi def link chillConditional term=bold ctermfg=red guifg=red gui=bold + +hi def link chillRepeat Repeat +hi def link chillProcess Repeat +hi def link chillSignal Repeat +hi def link chillCharacter Character +hi def link chillSpecialCharacter chillSpecial +hi def link chillNumber Number +hi def link chillFloat Float +hi def link chillOctalError chillError +hi def link chillParenError chillError +hi def link chillInParen chillError +hi def link chillCommentError chillError +hi def link chillSpaceError chillError +hi def link chillOperator Operator +hi def link chillStructure Structure +hi def link chillBlock Operator +hi def link chillScope Operator +"hi def link chillEDML term=underline ctermfg=DarkRed guifg=Red +hi def link chillEDML PreProc +"hi def link chillBoolConst term=bold ctermfg=brown guifg=brown +hi def link chillBoolConst Constant +"hi def link chillLogical term=bold ctermfg=brown guifg=brown +hi def link chillLogical Constant +hi def link chillStorageClass StorageClass +hi def link chillInclude Include +hi def link chillPreProc PreProc +hi def link chillDefine Macro +hi def link chillIncluded chillString +hi def link chillError Error +hi def link chillStatement Statement +hi def link chillPreCondit PreCondit +hi def link chillType Type +hi def link chillCommentError chillError +hi def link chillCommentString chillString +hi def link chillComment2String chillString +hi def link chillCommentSkip chillComment +hi def link chillString String +hi def link chillComment Comment +" hi def link chillComment term=None ctermfg=lightblue guifg=lightblue +hi def link chillSpecial SpecialChar +hi def link chillTodo Todo +hi def link chillBlock Statement +"hi def link chillIdentifier Identifier +hi def link chillBracket Delimiter + let b:current_syntax = "chill" diff --git a/runtime/syntax/cl.vim b/runtime/syntax/cl.vim index 41c045fb09..b765682547 100644 --- a/runtime/syntax/cl.vim +++ b/runtime/syntax/cl.vim @@ -10,19 +10,12 @@ " Version: 6 " Last Change: Mar 06 2013 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif -if version >= 600 - setlocal iskeyword=@,48-57,_,- -else - set iskeyword=@,48-57,_,- -endif +setlocal iskeyword=@,48-57,_,- syn case ignore @@ -75,40 +68,30 @@ syn keyword clFunction asc asize chr name random slen srandom day getarg getcgi syn keyword clStatement clear clear_eol clear_eos close copy create unique with where empty define define ldefine delay_form delete escape exit_block exit_do exit_process field fork format get getfile getnext getprev goto head join maintain message no_join on_eop on_key on_exit on_delete openin openout openapp pause popenin popenout popenio print put range read redisplay refresh restart_block screen select sleep text unlock write and not or do " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_cl_syntax_inits") - if version < 508 - let did_cl_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink clifError Error - HiLink clSpaceError Error - HiLink clWhile Repeat - HiLink clConditional Conditional - HiLink clDebug Debug - HiLink clNeedsWork Todo - HiLink clTodo Todo - HiLink clComment Comment - HiLink clProcedure Procedure - HiLink clBreak Procedure - HiLink clInclude Include - HiLink clSetOption Statement - HiLink clSet Identifier - HiLink clPreProc PreProc - HiLink clOperator Operator - HiLink clNumber Number - HiLink clString String - HiLink clQuote Delimiter - HiLink clReserved Identifier - HiLink clFunction Function - HiLink clStatement Statement - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link clifError Error +hi def link clSpaceError Error +hi def link clWhile Repeat +hi def link clConditional Conditional +hi def link clDebug Debug +hi def link clNeedsWork Todo +hi def link clTodo Todo +hi def link clComment Comment +hi def link clProcedure Procedure +hi def link clBreak Procedure +hi def link clInclude Include +hi def link clSetOption Statement +hi def link clSet Identifier +hi def link clPreProc PreProc +hi def link clOperator Operator +hi def link clNumber Number +hi def link clString String +hi def link clQuote Delimiter +hi def link clReserved Identifier +hi def link clFunction Function +hi def link clStatement Statement + let b:current_syntax = "cl" diff --git a/runtime/syntax/clean.vim b/runtime/syntax/clean.vim index ea95aa209e..70bf654fb7 100644 --- a/runtime/syntax/clean.vim +++ b/runtime/syntax/clean.vim @@ -4,11 +4,8 @@ " Co-Author: Arthur van Leeuwen <arthurvl@sci.kun.nl> " Last Change: 2013 Oct 15 by Jurriรซn Stutterheim -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -52,49 +49,39 @@ syn match cleanFuncTypeDef "\([a-zA-Z].*\|(\=[-~@#$%^?!+*<>\/|&=:]\+)\=\)\s*\(in " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_clean_syntax_init") - if version < 508 - let did_clean_syntax_init = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - " Comments - HiLink cleanComment Comment - " Constants and denotations - HiLink cleanStringDenot String - HiLink cleanCharDenot Character - HiLink cleanIntegerDenot Number - HiLink cleanBoolDenot Boolean - HiLink cleanRealDenot Float - " Identifiers - " Statements - HiLink cleanTypeClass Keyword - HiLink cleanConditional Conditional - HiLink cleanLabel Label - HiLink cleanKeyword Keyword - " Generic Preprocessing - HiLink cleanIncludeKeyword Include - HiLink cleanModuleSystem PreProc - " Type - HiLink cleanBasicType Type - HiLink cleanSpecialType Type - HiLink cleanFuncTypeDef Typedef - " Special - HiLink cleanSpecial Special - HiLink cleanList Special - HiLink cleanArray Special - HiLink cleanRecord Special - HiLink cleanTuple Special - " Error - " Todo - HiLink cleanTodo Todo + " Comments + hi def link cleanComment Comment + " Constants and denotations + hi def link cleanStringDenot String + hi def link cleanCharDenot Character + hi def link cleanIntegerDenot Number + hi def link cleanBoolDenot Boolean + hi def link cleanRealDenot Float + " Identifiers + " Statements + hi def link cleanTypeClass Keyword + hi def link cleanConditional Conditional + hi def link cleanLabel Label + hi def link cleanKeyword Keyword + " Generic Preprocessing + hi def link cleanIncludeKeyword Include + hi def link cleanModuleSystem PreProc + " Type + hi def link cleanBasicType Type + hi def link cleanSpecialType Type + hi def link cleanFuncTypeDef Typedef + " Special + hi def link cleanSpecial Special + hi def link cleanList Special + hi def link cleanArray Special + hi def link cleanRecord Special + hi def link cleanTuple Special + " Error + " Todo + hi def link cleanTodo Todo - delcommand HiLink -endif let b:current_syntax = "clean" diff --git a/runtime/syntax/clipper.vim b/runtime/syntax/clipper.vim index 6ee3892845..38ba9a4fe9 100644 --- a/runtime/syntax/clipper.vim +++ b/runtime/syntax/clipper.vim @@ -4,11 +4,8 @@ " Some things based on c.vim by Bram Moolenaar and pascal.vim by Mario Eusebio " Last Change: 2011 Dec 29 by Thilo Six -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -114,32 +111,22 @@ syntax match clipperComment "^\*.*" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_clipper_syntax_inits") - if version < 508 - let did_clipper_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink clipperConditional Conditional - HiLink clipperRepeat Repeat - HiLink clipperNumber Number - HiLink clipperInclude Include - HiLink clipperComment Comment - HiLink clipperOperator Operator - HiLink clipperStorageClass StorageClass - HiLink clipperStatement Statement - HiLink clipperString String - HiLink clipperFunction Function - HiLink clipperLineContinuation Special - HiLink clipperDelimiters Delimiter - HiLink clipperUserVariable Identifier - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link clipperConditional Conditional +hi def link clipperRepeat Repeat +hi def link clipperNumber Number +hi def link clipperInclude Include +hi def link clipperComment Comment +hi def link clipperOperator Operator +hi def link clipperStorageClass StorageClass +hi def link clipperStatement Statement +hi def link clipperString String +hi def link clipperFunction Function +hi def link clipperLineContinuation Special +hi def link clipperDelimiters Delimiter +hi def link clipperUserVariable Identifier + let b:current_syntax = "clipper" diff --git a/runtime/syntax/cmake.vim b/runtime/syntax/cmake.vim index 4586940c5e..4cc21da8fe 100644 --- a/runtime/syntax/cmake.vim +++ b/runtime/syntax/cmake.vim @@ -12,11 +12,8 @@ " http://www.cmake.org/HTML/Copyright.html " This implies that distribution with Vim is allowed -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif let s:keepcpo= &cpo @@ -52,32 +49,22 @@ syn keyword cmakeTodo \ contained " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_cmake_syntax_inits") - if version < 508 - let did_cmake_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink cmakeStatement Statement - HiLink cmakeComment Comment - HiLink cmakeString String - HiLink cmakeVariableValue Type - HiLink cmakeRegistry Underlined - HiLink cmakeArguments Identifier - HiLink cmakeArgument Constant - HiLink cmakeEnvironment Special - HiLink cmakeOperators Operator - HiLink cmakeMacro PreProc - HiLink cmakeError Error - HiLink cmakeTodo TODO - HiLink cmakeEscaped Special +hi def link cmakeStatement Statement +hi def link cmakeComment Comment +hi def link cmakeString String +hi def link cmakeVariableValue Type +hi def link cmakeRegistry Underlined +hi def link cmakeArguments Identifier +hi def link cmakeArgument Constant +hi def link cmakeEnvironment Special +hi def link cmakeOperators Operator +hi def link cmakeMacro PreProc +hi def link cmakeError Error +hi def link cmakeTodo TODO +hi def link cmakeEscaped Special - delcommand HiLink -endif let b:current_syntax = "cmake" diff --git a/runtime/syntax/cobol.vim b/runtime/syntax/cobol.vim index 51ca3d8773..2d481bba0b 100644 --- a/runtime/syntax/cobol.vim +++ b/runtime/syntax/cobol.vim @@ -6,20 +6,13 @@ " James Mitchell <james_mitchell@acm.org>) " Last Change: 2015 Feb 13 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif " MOST important - else most of the keywords wont work! -if version < 600 - set isk=@,48-57,- -else - setlocal isk=@,48-57,- -endif +setlocal isk=@,48-57,- syn case ignore @@ -157,52 +150,42 @@ else endif " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_cobol_syntax_inits") - if version < 508 - let did_cobol_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink cobolBAD Error - HiLink cobolBadID Error - HiLink cobolBadLine Error - if exists("g:cobol_legacy_code") - HiLink cobolMarker Comment - else - HiLink cobolMarker Error - endif - HiLink cobolCALLs Function - HiLink cobolComment Comment - HiLink cobolKeys Comment - HiLink cobolAreaB Special - HiLink cobolCompiler PreProc - HiLink cobolCondFlow Special - HiLink cobolCopy PreProc - HiLink cobolDeclA cobolDecl - HiLink cobolDecl Type - HiLink cobolExtras Special - HiLink cobolGoTo Special - HiLink cobolConstant Constant - HiLink cobolNumber Constant - HiLink cobolPic Constant - HiLink cobolReserved Statement - HiLink cobolDivision Label - HiLink cobolSection Label - HiLink cobolParagraph Label - HiLink cobolDivisionName Keyword - HiLink cobolSectionName Keyword - HiLink cobolParagraphName Keyword - HiLink cobolString Constant - HiLink cobolTodo Todo - HiLink cobolWatch Special - HiLink cobolIndicator Special - - delcommand HiLink +" Only when an item doesn't have highlighting yet + +hi def link cobolBAD Error +hi def link cobolBadID Error +hi def link cobolBadLine Error +if exists("g:cobol_legacy_code") + hi def link cobolMarker Comment +else + hi def link cobolMarker Error endif +hi def link cobolCALLs Function +hi def link cobolComment Comment +hi def link cobolKeys Comment +hi def link cobolAreaB Special +hi def link cobolCompiler PreProc +hi def link cobolCondFlow Special +hi def link cobolCopy PreProc +hi def link cobolDeclA cobolDecl +hi def link cobolDecl Type +hi def link cobolExtras Special +hi def link cobolGoTo Special +hi def link cobolConstant Constant +hi def link cobolNumber Constant +hi def link cobolPic Constant +hi def link cobolReserved Statement +hi def link cobolDivision Label +hi def link cobolSection Label +hi def link cobolParagraph Label +hi def link cobolDivisionName Keyword +hi def link cobolSectionName Keyword +hi def link cobolParagraphName Keyword +hi def link cobolString Constant +hi def link cobolTodo Todo +hi def link cobolWatch Special +hi def link cobolIndicator Special + let b:current_syntax = "cobol" diff --git a/runtime/syntax/coco.vim b/runtime/syntax/coco.vim index 4094a55303..ae32348bcb 100644 --- a/runtime/syntax/coco.vim +++ b/runtime/syntax/coco.vim @@ -5,9 +5,8 @@ " Remark: Coco/R syntax partially implemented. " License: Vim license -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif diff --git a/runtime/syntax/config.vim b/runtime/syntax/config.vim index cd83b24352..c6d4e6b363 100644 --- a/runtime/syntax/config.vim +++ b/runtime/syntax/config.vim @@ -11,11 +11,8 @@ " script, so I wrote this quick and dirty patch. -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -37,28 +34,18 @@ syn region configstring matchgroup=configfunction start="AC_MSG_[A-Z]*\ze(\[" m syn region configstring matchgroup=configfunction start="AC_MSG_[A-Z]*\ze([^[]" matchgroup=configdelimiter end=")" contains=configdelimiter,@Spell " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_config_syntax_inits") - if version < 508 - let did_config_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet + +hi def link configdelimiter Delimiter +hi def link configoperator Operator +hi def link configcomment Comment +hi def link configDnl Comment +hi def link configfunction Function +hi def link confignumber Number +hi def link configkeyword Keyword +hi def link configspecial Special +hi def link configstring String - HiLink configdelimiter Delimiter - HiLink configoperator Operator - HiLink configcomment Comment - HiLink configDnl Comment - HiLink configfunction Function - HiLink confignumber Number - HiLink configkeyword Keyword - HiLink configspecial Special - HiLink configstring String - - delcommand HiLink -endif let b:current_syntax = "config" diff --git a/runtime/syntax/context.vim b/runtime/syntax/context.vim index 225cc6efc2..b29f256baa 100644 --- a/runtime/syntax/context.vim +++ b/runtime/syntax/context.vim @@ -1,7 +1,8 @@ " Vim syntax file -" Language: ConTeXt typesetting engine -" Maintainer: Nikolai Weibull <now@bitwi.se> -" Latest Revision: 2006-08-10 +" Language: ConTeXt typesetting engine +" Maintainer: Nicola Vitacolonna <nvitacolonna@gmail.com> +" Former Maintainers: Nikolai Weibull <now@bitwi.se> +" Latest Revision: 2016 Oct 16 if exists("b:current_syntax") finish @@ -13,65 +14,93 @@ unlet b:current_syntax let s:cpo_save = &cpo set cpo&vim -if !exists('g:context_include') - let g:context_include = ['mp', 'javascript', 'xml'] +" Dictionary of (filetype, group) pairs to highlight between \startGROUP \stopGROUP. +let s:context_include = get(b:, 'context_include', get(g:, 'context_include', {'xml': 'XML'})) + +" For backward compatibility (g:context_include used to be a List) +if type(s:context_include) ==# type([]) + let g:context_metapost = (index(s:context_include, 'mp') != -1) + let s:context_include = filter( + \ {'c': 'C', 'javascript': 'JS', 'ruby': 'Ruby', 'xml': 'XML'}, + \ { k,_ -> index(s:context_include, k) != -1 } + \ ) endif +syn iskeyword @,48-57,a-z,A-Z,192-255 + syn spell toplevel -syn match contextBlockDelim display '\\\%(start\|stop\)\a\+' - \ contains=@NoSpell +" ConTeXt options, i.e., [...] blocks +syn region contextOptions matchgroup=contextDelimiter start='\[' end=']\|\ze\\stop' skip='\\\[\|\\\]' contains=ALLBUT,contextBeginEndLua,@Spell + +" Highlight braces +syn match contextDelimiter '[{}]' -syn region contextEscaped display matchgroup=contextPreProc - \ start='\\type\z(\A\)' end='\z1' -syn region contextEscaped display matchgroup=contextPreProc - \ start='\\type\={' end='}' -syn region contextEscaped display matchgroup=contextPreProc - \ start='\\type\=<<' end='>>' +" Comments +syn match contextComment '\\\@<!\%(\\\\\)*\zs%.*$' display contains=initexTodo +syn match contextComment '^\s*%[CDM].*$' display contains=initexTodo + +syn match contextBlockDelim '\\\%(start\|stop\)\a\+' contains=@NoSpell + +syn region contextEscaped matchgroup=contextPreProc start='\\type\%(\s*\|\n\)*\z([^A-Za-z%]\)' end='\z1' +syn region contextEscaped matchgroup=contextPreProc start='\\type\=\%(\s\|\n\)*{' end='}' +syn region contextEscaped matchgroup=contextPreProc start='\\type\=\%(\s*\|\n\)*<<' end='>>' syn region contextEscaped matchgroup=contextPreProc \ start='\\start\z(\a*\%(typing\|typen\)\)' \ end='\\stop\z1' contains=plaintexComment keepend -syn region contextEscaped display matchgroup=contextPreProc - \ start='\\\h\+Type{' end='}' -syn region contextEscaped display matchgroup=contextPreProc - \ start='\\Typed\h\+{' end='}' +syn region contextEscaped matchgroup=contextPreProc start='\\\h\+Type\%(\s\|\n\)*{' end='}' +syn region contextEscaped matchgroup=contextPreProc start='\\Typed\h\+\%(\s\|\n\)*{' end='}' syn match contextBuiltin display contains=@NoSpell - \ '\\\%(unprotect\|protect\|unexpanded\)' + \ '\\\%(unprotect\|protect\|unexpanded\)\>' -syn match contextPreProc '^\s*\\\%(start\|stop\)\=\%(component\|environment\|project\|product\).*$' +syn match contextPreProc '^\s*\\\%(start\|stop\)\=\%(component\|environment\|project\|product\)\>' \ contains=@NoSpell -if index(g:context_include, 'mp') != -1 +if get(b:, 'context_metapost', get(g:, 'context_metapost', 1)) + let b:mp_metafun_macros = 1 " Highlight MetaFun keywords syn include @mpTop syntax/mp.vim unlet b:current_syntax - syn region contextMPGraphic transparent matchgroup=contextBlockDelim - \ start='\\start\z(\a*MPgraphic\|MP\%(page\|inclusions\|run\)\).*' + syn region contextMPGraphic matchgroup=contextBlockDelim + \ start='\\start\z(MP\%(clip\|code\|definitions\|drawing\|environment\|extensions\|inclusions\|initializations\|page\|\)\)\>.*$' + \ end='\\stop\z1' + \ contains=@mpTop,@NoSpell + syn region contextMPGraphic matchgroup=contextBlockDelim + \ start='\\start\z(\%(\%[re]usable\|use\|unique\|static\)MPgraphic\|staticMPfigure\|uniqueMPpagegraphic\)\>.*$' \ end='\\stop\z1' - \ contains=@mpTop + \ contains=@mpTop,@NoSpell endif -" TODO: also need to implement this for \\typeC or something along those -" lines. -function! s:include_syntax(name, group) - if index(g:context_include, a:name) != -1 - execute 'syn include @' . a:name . 'Top' 'syntax/' . a:name . '.vim' - unlet b:current_syntax - execute 'syn region context' . a:group . 'Code' - \ 'transparent matchgroup=contextBlockDelim' - \ 'start=+\\start' . a:group . '+ end=+\\stop' . a:group . '+' - \ 'contains=@' . a:name . 'Top' - endif -endfunction - -call s:include_syntax('c', 'C') -call s:include_syntax('ruby', 'Ruby') -call s:include_syntax('javascript', 'JS') -call s:include_syntax('xml', 'XML') - -syn match contextSectioning '\\chapter\>' contains=@NoSpell -syn match contextSectioning '\\\%(sub\)*section\>' contains=@NoSpell +if get(b:, 'context_lua', get(g:, 'context_lua', 1)) + syn include @luaTop syntax/lua.vim + unlet b:current_syntax + + syn region contextLuaCode matchgroup=contextBlockDelim + \ start='\\startluacode\>' + \ end='\\stopluacode\>' keepend + \ contains=@luaTop,@NoSpell + + syn match contextDirectLua "\\\%(directlua\|ctxlua\)\>\%(\s*%.*$\)\=" + \ nextgroup=contextBeginEndLua skipwhite skipempty + \ contains=initexComment + syn region contextBeginEndLua matchgroup=contextSpecial + \ start="{" end="}" skip="\\[{}]" + \ contained contains=@luaTop,@NoSpell +endif + +for synname in keys(s:context_include) + execute 'syn include @' . synname . 'Top' 'syntax/' . synname . '.vim' + unlet b:current_syntax + execute 'syn region context' . s:context_include[synname] . 'Code' + \ 'matchgroup=contextBlockDelim' + \ 'start=+\\start' . s:context_include[synname] . '+' + \ 'end=+\\stop' . s:context_include[synname] . '+' + \ 'contains=@' . synname . 'Top,@NoSpell' +endfor + +syn match contextSectioning '\\\%(start\|stop\)\=\%(\%(sub\)*section\|\%(sub\)*subject\|chapter\|part\|component\|product\|title\)\>' + \ contains=@NoSpell syn match contextSpecial '\\crlf\>\|\\par\>\|-\{2,3}\||[<>/]\=|' \ contains=@NoSpell @@ -92,15 +121,19 @@ syn match contextFont '\\\%(vi\{1,3}\|ix\|xi\{0,2}\)\>' syn match contextFont '\\\%(tf\|b[si]\|s[cl]\|os\)\%(xx\|[xabcd]\)\=\>' \ contains=@NoSpell +hi def link contextOptions Typedef +hi def link contextComment Comment hi def link contextBlockDelim Keyword hi def link contextBuiltin Keyword hi def link contextDelimiter Delimiter +hi def link contextEscaped String hi def link contextPreProc PreProc hi def link contextSectioning PreProc hi def link contextSpecial Special hi def link contextType Type hi def link contextStyle contextType hi def link contextFont contextType +hi def link contextDirectLua Keyword let b:current_syntax = "context" diff --git a/runtime/syntax/cpp.vim b/runtime/syntax/cpp.vim index c7a68388be..5a478fb77d 100644 --- a/runtime/syntax/cpp.vim +++ b/runtime/syntax/cpp.vim @@ -2,23 +2,16 @@ " Language: C++ " Current Maintainer: vim-jp (https://github.com/vim-jp/vim-cpp) " Previous Maintainer: Ken Shan <ccshan@post.harvard.edu> -" Last Change: 2015 Nov 10 +" Last Change: 2016 Oct 28 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif " Read the C syntax to start with -if version < 600 - so <sfile>:p:h/c.vim -else - runtime! syntax/c.vim - unlet b:current_syntax -endif +runtime! syntax/c.vim +unlet b:current_syntax " C++ extensions syn keyword cppStatement new delete this friend using @@ -38,7 +31,7 @@ syn keyword cppConstant __cplusplus " C++ 11 extensions if !exists("cpp_no_cpp11") syn keyword cppModifier override final - syn keyword cppType nullptr_t + syn keyword cppType nullptr_t auto syn keyword cppExceptions noexcept syn keyword cppStorageClass constexpr decltype thread_local syn keyword cppConstant nullptr @@ -53,35 +46,31 @@ endif " C++ 14 extensions if !exists("cpp_no_cpp14") - syn match cppNumber display "\<0b[01]\+\(u\=l\{0,2}\|ll\=u\)\>" + syn case ignore + syn match cppNumber display "\<0b[01]\('\=[01]\+\)*\(u\=l\{0,2}\|ll\=u\)\>" + syn match cppNumber display "\<[1-9]\('\=\d\+\)*\(u\=l\{0,2}\|ll\=u\)\>" + syn match cppNumber display "\<0x\x\('\=\x\+\)*\(u\=l\{0,2}\|ll\=u\)\>" + syn case match endif " The minimum and maximum operators in GNU C++ syn match cppMinMax "[<>]?" " Default highlighting -if version >= 508 || !exists("did_cpp_syntax_inits") - if version < 508 - let did_cpp_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - HiLink cppAccess cppStatement - HiLink cppCast cppStatement - HiLink cppExceptions Exception - HiLink cppOperator Operator - HiLink cppStatement Statement - HiLink cppModifier Type - HiLink cppType Type - HiLink cppStorageClass StorageClass - HiLink cppStructure Structure - HiLink cppBoolean Boolean - HiLink cppConstant Constant - HiLink cppRawStringDelimiter Delimiter - HiLink cppRawString String - delcommand HiLink -endif +hi def link cppAccess cppStatement +hi def link cppCast cppStatement +hi def link cppExceptions Exception +hi def link cppOperator Operator +hi def link cppStatement Statement +hi def link cppModifier Type +hi def link cppType Type +hi def link cppStorageClass StorageClass +hi def link cppStructure Structure +hi def link cppBoolean Boolean +hi def link cppConstant Constant +hi def link cppRawStringDelimiter Delimiter +hi def link cppRawString String +hi def link cppNumber Number let b:current_syntax = "cpp" diff --git a/runtime/syntax/crontab.vim b/runtime/syntax/crontab.vim index fd1c30023f..5e38ffaafe 100644 --- a/runtime/syntax/crontab.vim +++ b/runtime/syntax/crontab.vim @@ -10,11 +10,8 @@ " crontab line format: " Minutes Hours Days Months Days_of_Week Commands # comments -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -39,41 +36,31 @@ syntax match crontabCmnt "^\s*#.*" contains=@Spell syntax match crontabPercent "[^\\]%.*"lc=1 contained " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_crontab_syn_inits") - if version < 508 - let did_crontab_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink crontabMin Number - HiLink crontabHr PreProc - HiLink crontabDay Type - - HiLink crontabMnth Number - HiLink crontabMnth12 Number - HiLink crontabMnthS Number - HiLink crontabMnthN Number - - HiLink crontabDow PreProc - HiLink crontabDow7 PreProc - HiLink crontabDowS PreProc - HiLink crontabDowN PreProc - - HiLink crontabNick Special - HiLink crontabVar Identifier - HiLink crontabPercent Special +" Only when an item doesn't have highlighting yet + +hi def link crontabMin Number +hi def link crontabHr PreProc +hi def link crontabDay Type + +hi def link crontabMnth Number +hi def link crontabMnth12 Number +hi def link crontabMnthS Number +hi def link crontabMnthN Number + +hi def link crontabDow PreProc +hi def link crontabDow7 PreProc +hi def link crontabDowS PreProc +hi def link crontabDowN PreProc + +hi def link crontabNick Special +hi def link crontabVar Identifier +hi def link crontabPercent Special " comment out next line for to suppress unix commands coloring. - HiLink crontabCmd Statement +hi def link crontabCmd Statement - HiLink crontabCmnt Comment +hi def link crontabCmnt Comment - delcommand HiLink -endif let b:current_syntax = "crontab" diff --git a/runtime/syntax/csc.vim b/runtime/syntax/csc.vim index 5493b17f5f..6e5d8b9f37 100644 --- a/runtime/syntax/csc.vim +++ b/runtime/syntax/csc.vim @@ -3,11 +3,8 @@ " Maintainer: Raul Segura Acevedo <raulseguraaceved@netscape.net> " Last change: 2011 Dec 25 by Thilo Six -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -145,7 +142,7 @@ sy match cscBPMacro contained "!" sy match cscBPW "!\s*\a*" contains=cscBPmacro " when wanted, highlighting lhs members or erros in asignments (may lag the editing) -if version >= 600 && exists("csc_asignment") +if exists("csc_asignment") sy match cscEqError '\("[^"]*"\s*\|[^][\t !%()*+,--/:;<=>{}~]\+\s*\|->\s*\)*=\([^=]\@=\|$\)' sy region cscFormula transparent matchgroup=cscVarName start='\("[^"]*"\|[^][\t !%()*+,--/:;<=>{}~]\+\)\s*=\([^=]\@=\|\n\)' skip='"[^"]*"' end=';' contains=ALLBUT,cscFormula,cscFormulaIn,cscBPMacro,cscCondition sy region cscFormulaIn matchgroup=cscVarName transparent start='\("[^"]*"\|[^][\t !%()*+,--/:;<=>{}~]\+\)\(->\("[^"]*"\|[^][\t !%()*+,--/:;<=>{}~]\+\)\)*\s*=\([^=]\@=\|$\)' skip='"[^"]*"' end=';' contains=ALLBUT,cscFormula,cscFormulaIn,cscBPMacro,cscCondition contained @@ -158,44 +155,34 @@ endif exec "sy sync ccomment cscComment minlines=" . csc_minlines " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_csc_syntax_inits") - if version < 508 - let did_csc_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet + +hi cscVarName term=bold ctermfg=9 gui=bold guifg=blue + +hi def link cscNumber Number +hi def link cscOctal Number +hi def link cscFloat Float +hi def link cscParenE Error +hi def link cscCommentE Error +hi def link cscSpaceE Error +hi def link cscError Error +hi def link cscString String +hi def link cscComment Comment +hi def link cscTodo Todo +hi def link cscStatement Statement +hi def link cscIfError Error +hi def link cscEqError Error +hi def link cscFunction Statement +hi def link cscCondition Statement +hi def link cscWarn WarningMsg + +hi def link cscComE Error +hi def link cscCom Statement +hi def link cscComW WarningMsg + +hi def link cscBPMacro Identifier +hi def link cscBPW WarningMsg - hi cscVarName term=bold ctermfg=9 gui=bold guifg=blue - - HiLink cscNumber Number - HiLink cscOctal Number - HiLink cscFloat Float - HiLink cscParenE Error - HiLink cscCommentE Error - HiLink cscSpaceE Error - HiLink cscError Error - HiLink cscString String - HiLink cscComment Comment - HiLink cscTodo Todo - HiLink cscStatement Statement - HiLink cscIfError Error - HiLink cscEqError Error - HiLink cscFunction Statement - HiLink cscCondition Statement - HiLink cscWarn WarningMsg - - HiLink cscComE Error - HiLink cscCom Statement - HiLink cscComW WarningMsg - - HiLink cscBPMacro Identifier - HiLink cscBPW WarningMsg - - delcommand HiLink -endif let b:current_syntax = "csc" diff --git a/runtime/syntax/csh.vim b/runtime/syntax/csh.vim index 9dc2c4ef56..c134aa7ef3 100644 --- a/runtime/syntax/csh.vim +++ b/runtime/syntax/csh.vim @@ -1,15 +1,12 @@ " Vim syntax file " Language: C-shell (csh) " Maintainer: Charles E. Campbell <NdrOchipS@PcampbellAfamily.Mbiz> -" Last Change: Oct 23, 2014 -" Version: 11 +" Last Change: Aug 31, 2016 +" Version: 13 " URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_CSH -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -100,59 +97,45 @@ syn match cshNumber "-\=\<\d\+\>" "syn match cshIdentifier "\<[a-zA-Z._][a-zA-Z0-9._]*\>" " Shell Input Redirection (Here Documents) -if version < 600 - syn region cshHereDoc matchgroup=cshRedir start="<<-\=\s*\**END[a-zA-Z_0-9]*\**" matchgroup=cshRedir end="^END[a-zA-Z_0-9]*$" - syn region cshHereDoc matchgroup=cshRedir start="<<-\=\s*\**EOF\**" matchgroup=cshRedir end="^EOF$" -else - syn region cshHereDoc matchgroup=cshRedir start="<<-\=\s*\**\z(\h\w*\)\**" matchgroup=cshRedir end="^\z1$" -endif +syn region cshHereDoc matchgroup=cshRedir start="<<-\=\s*\**\z(\h\w*\)\**" matchgroup=cshRedir end="^\z1$" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_csh_syntax_inits") - if version < 508 - let did_csh_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink cshArgv cshVariables - HiLink cshBckQuote cshCommand - HiLink cshDblQuote cshString - HiLink cshExtVar cshVariables - HiLink cshHereDoc cshString - HiLink cshNoEndlineBQ cshNoEndline - HiLink cshNoEndlineDQ cshNoEndline - HiLink cshNoEndlineSQ cshNoEndline - HiLink cshQtyWord cshVariables - HiLink cshRedir cshOperator - HiLink cshSelector cshVariables - HiLink cshSetStmt cshStatement - HiLink cshSetVariables cshVariables - HiLink cshSnglQuote cshString - HiLink cshSubst cshVariables - - HiLink cshCommand Statement - HiLink cshComment Comment - HiLink cshConditional Conditional - HiLink cshIdentifier Error - HiLink cshModifier Special - HiLink cshNoEndline Error - HiLink cshNumber Number - HiLink cshOperator Operator - HiLink cshRedir Statement - HiLink cshRepeat Repeat - HiLink cshShellVariables Special - HiLink cshSpecial Special - HiLink cshStatement Statement - HiLink cshString String - HiLink cshSubstError Error - HiLink cshTodo Todo - HiLink cshVariables Type - - delcommand HiLink +if !exists("skip_csh_syntax_inits") + + hi def link cshArgv cshVariables + hi def link cshBckQuote cshCommand + hi def link cshDblQuote cshString + hi def link cshExtVar cshVariables + hi def link cshHereDoc cshString + hi def link cshNoEndlineBQ cshNoEndline + hi def link cshNoEndlineDQ cshNoEndline + hi def link cshNoEndlineSQ cshNoEndline + hi def link cshQtyWord cshVariables + hi def link cshRedir cshOperator + hi def link cshSelector cshVariables + hi def link cshSetStmt cshStatement + hi def link cshSetVariables cshVariables + hi def link cshSnglQuote cshString + hi def link cshSubst cshVariables + + hi def link cshCommand Statement + hi def link cshComment Comment + hi def link cshConditional Conditional + hi def link cshIdentifier Error + hi def link cshModifier Special + hi def link cshNoEndline Error + hi def link cshNumber Number + hi def link cshOperator Operator + hi def link cshRedir Statement + hi def link cshRepeat Repeat + hi def link cshShellVariables Special + hi def link cshSpecial Special + hi def link cshStatement Statement + hi def link cshString String + hi def link cshSubstError Error + hi def link cshTodo Todo + hi def link cshVariables Type + endif let b:current_syntax = "csh" diff --git a/runtime/syntax/csp.vim b/runtime/syntax/csp.vim index bd6213efd9..8001b1fe7e 100644 --- a/runtime/syntax/csp.vim +++ b/runtime/syntax/csp.vim @@ -15,11 +15,8 @@ " - The additional syntax for the RT-Tester (pseudo-comments) " should be optional. -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -149,46 +146,36 @@ syn match cspSdlRttComment "pragma\s\+SDL_MATCH\s\+" nextgroup=cspRttPragmaSdlAr syn sync lines=250 " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_csp_syn_inits") - if version < 508 - let did_csp_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - " The default methods for highlighting. Can be overridden later - " (For vim version <=5.7, the command groups are defined in - " $VIMRUNTIME/syntax/synload.vim ) - HiLink cspComment Comment - HiLink cspNumber Number - HiLink cspConditional Conditional - HiLink cspOperator Delimiter - HiLink cspKeyword Keyword - HiLink cspReserved SpecialChar - HiLink cspInclude Error - HiLink cspIncludeKeyword Include - HiLink cspIncludeArg Include - HiLink cspAssert PreCondit - HiLink cspType Type - HiLink cspProcess Function - HiLink cspTodo Todo - HiLink cspOldRttComment Define - HiLink cspRttPragmaKeyword Define - HiLink cspSdlRttComment Define - HiLink cspRttPragmaArg Define - HiLink cspRttPragmaSdlArg Define - HiLink cspRttPragmaSdlName Default - HiLink cspRttPragmaSdlTailArg Define - HiLink cspRttPragmaSdlTransName Default - HiLink cspRttPragmaSdlTransTailArg Define - HiLink cspReservedIdentifier Error - " (Currently unused vim method: Debug) - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +" The default methods for highlighting. Can be overridden later +" (For vim version <=5.7, the command groups are defined in +" $VIMRUNTIME/syntax/synload.vim ) +hi def link cspComment Comment +hi def link cspNumber Number +hi def link cspConditional Conditional +hi def link cspOperator Delimiter +hi def link cspKeyword Keyword +hi def link cspReserved SpecialChar +hi def link cspInclude Error +hi def link cspIncludeKeyword Include +hi def link cspIncludeArg Include +hi def link cspAssert PreCondit +hi def link cspType Type +hi def link cspProcess Function +hi def link cspTodo Todo +hi def link cspOldRttComment Define +hi def link cspRttPragmaKeyword Define +hi def link cspSdlRttComment Define +hi def link cspRttPragmaArg Define +hi def link cspRttPragmaSdlArg Define +hi def link cspRttPragmaSdlName Default +hi def link cspRttPragmaSdlTailArg Define +hi def link cspRttPragmaSdlTransName Default +hi def link cspRttPragmaSdlTransTailArg Define +hi def link cspReservedIdentifier Error +" (Currently unused vim method: Debug) + let b:current_syntax = "csp" diff --git a/runtime/syntax/css.vim b/runtime/syntax/css.vim index 51758ca98f..23db7b10e8 100644 --- a/runtime/syntax/css.vim +++ b/runtime/syntax/css.vim @@ -6,14 +6,12 @@ " Nikolai Weibull (Add CSS2 support) " Maintainer: Jules Wang <w.jq0722@gmail.com> " URL: https://github.com/JulesWang/css.vim -" Last Change: 2015 Apr.17 +" Last Change: 2017 Jan 14 +" cssClassName updated by Ryuichi Hayashida Jan 2016 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded +" quit when a syntax file was already loaded if !exists("main_syntax") - if version < 600 - syntax clear - elseif exists("b:current_syntax") + if exists("b:current_syntax") finish endif let main_syntax = 'css' @@ -59,7 +57,7 @@ syn match cssSelectorOp2 "[~|^$*]\?=" contained syn region cssAttributeSelector matchgroup=cssSelectorOp start="\[" end="]" contains=cssUnicodeEscape,cssSelectorOp2,cssStringQ,cssStringQQ " .class and #id -syn match cssClassName "\.[A-Za-z][A-Za-z0-9_-]\+" contains=cssClassNameDot +syn match cssClassName "\.-\=[A-Za-z_][A-Za-z0-9_-]*" contains=cssClassNameDot syn match cssClassNameDot contained '\.' try @@ -516,139 +514,129 @@ if main_syntax == "css" endif " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_css_syn_inits") - if version < 508 - let did_css_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink cssComment Comment - HiLink cssVendor Comment - HiLink cssHacks Comment - HiLink cssTagName Statement - HiLink cssDeprecated Error - HiLink cssSelectorOp Special - HiLink cssSelectorOp2 Special - HiLink cssAttrComma Special - - HiLink cssAnimationProp cssProp - HiLink cssBackgroundProp cssProp - HiLink cssBorderProp cssProp - HiLink cssBoxProp cssProp - HiLink cssColorProp cssProp - HiLink cssContentForPagedMediaProp cssProp - HiLink cssDimensionProp cssProp - HiLink cssFlexibleBoxProp cssProp - HiLink cssFontProp cssProp - HiLink cssGeneratedContentProp cssProp - HiLink cssGridProp cssProp - HiLink cssHyerlinkProp cssProp - HiLink cssLineboxProp cssProp - HiLink cssListProp cssProp - HiLink cssMarqueeProp cssProp - HiLink cssMultiColumnProp cssProp - HiLink cssPagedMediaProp cssProp - HiLink cssPositioningProp cssProp - HiLink cssPrintProp cssProp - HiLink cssRubyProp cssProp - HiLink cssSpeechProp cssProp - HiLink cssTableProp cssProp - HiLink cssTextProp cssProp - HiLink cssTransformProp cssProp - HiLink cssTransitionProp cssProp - HiLink cssUIProp cssProp - HiLink cssIEUIProp cssProp - HiLink cssAuralProp cssProp - HiLink cssRenderProp cssProp - HiLink cssMobileTextProp cssProp - - HiLink cssAnimationAttr cssAttr - HiLink cssBackgroundAttr cssAttr - HiLink cssBorderAttr cssAttr - HiLink cssBoxAttr cssAttr - HiLink cssContentForPagedMediaAttr cssAttr - HiLink cssDimensionAttr cssAttr - HiLink cssFlexibleBoxAttr cssAttr - HiLink cssFontAttr cssAttr - HiLink cssGeneratedContentAttr cssAttr - HiLink cssGridAttr cssAttr - HiLink cssHyerlinkAttr cssAttr - HiLink cssLineboxAttr cssAttr - HiLink cssListAttr cssAttr - HiLink cssMarginAttr cssAttr - HiLink cssMarqueeAttr cssAttr - HiLink cssMultiColumnAttr cssAttr - HiLink cssPaddingAttr cssAttr - HiLink cssPagedMediaAttr cssAttr - HiLink cssPositioningAttr cssAttr - HiLink cssGradientAttr cssAttr - HiLink cssPrintAttr cssAttr - HiLink cssRubyAttr cssAttr - HiLink cssSpeechAttr cssAttr - HiLink cssTableAttr cssAttr - HiLink cssTextAttr cssAttr - HiLink cssTransformAttr cssAttr - HiLink cssTransitionAttr cssAttr - HiLink cssUIAttr cssAttr - HiLink cssIEUIAttr cssAttr - HiLink cssAuralAttr cssAttr - HiLink cssRenderAttr cssAttr - HiLink cssCommonAttr cssAttr - - HiLink cssPseudoClassId PreProc - HiLink cssPseudoClassLang Constant - HiLink cssValueLength Number - HiLink cssValueInteger Number - HiLink cssValueNumber Number - HiLink cssValueAngle Number - HiLink cssValueTime Number - HiLink cssValueFrequency Number - HiLink cssFunction Constant - HiLink cssURL String - HiLink cssFunctionName Function - HiLink cssFunctionComma Function - HiLink cssColor Constant - HiLink cssIdentifier Function - HiLink cssInclude Include - HiLink cssIncludeKeyword atKeyword - HiLink cssImportant Special - HiLink cssBraces Function - HiLink cssBraceError Error - HiLink cssError Error - HiLink cssUnicodeEscape Special - HiLink cssStringQQ String - HiLink cssStringQ String - HiLink cssAttributeSelector String - HiLink cssMedia atKeyword - HiLink cssMediaType Special - HiLink cssMediaComma Normal - HiLink cssMediaKeyword Statement - HiLink cssMediaProp cssProp - HiLink cssMediaAttr cssAttr - HiLink cssPage atKeyword - HiLink cssPagePseudo PreProc - HiLink cssPageMargin atKeyword - HiLink cssPageProp cssProp - HiLink cssKeyFrame atKeyword - HiLink cssKeyFrameSelector Constant - HiLink cssFontDescriptor Special - HiLink cssFontDescriptorFunction Constant - HiLink cssFontDescriptorProp cssProp - HiLink cssFontDescriptorAttr cssAttr - HiLink cssUnicodeRange Constant - HiLink cssClassName Function - HiLink cssClassNameDot Function - HiLink cssProp StorageClass - HiLink cssAttr Constant - HiLink cssUnitDecorators Number - HiLink cssNoise Noise - HiLink atKeyword PreProc - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link cssComment Comment +hi def link cssVendor Comment +hi def link cssHacks Comment +hi def link cssTagName Statement +hi def link cssDeprecated Error +hi def link cssSelectorOp Special +hi def link cssSelectorOp2 Special +hi def link cssAttrComma Special + +hi def link cssAnimationProp cssProp +hi def link cssBackgroundProp cssProp +hi def link cssBorderProp cssProp +hi def link cssBoxProp cssProp +hi def link cssColorProp cssProp +hi def link cssContentForPagedMediaProp cssProp +hi def link cssDimensionProp cssProp +hi def link cssFlexibleBoxProp cssProp +hi def link cssFontProp cssProp +hi def link cssGeneratedContentProp cssProp +hi def link cssGridProp cssProp +hi def link cssHyerlinkProp cssProp +hi def link cssLineboxProp cssProp +hi def link cssListProp cssProp +hi def link cssMarqueeProp cssProp +hi def link cssMultiColumnProp cssProp +hi def link cssPagedMediaProp cssProp +hi def link cssPositioningProp cssProp +hi def link cssPrintProp cssProp +hi def link cssRubyProp cssProp +hi def link cssSpeechProp cssProp +hi def link cssTableProp cssProp +hi def link cssTextProp cssProp +hi def link cssTransformProp cssProp +hi def link cssTransitionProp cssProp +hi def link cssUIProp cssProp +hi def link cssIEUIProp cssProp +hi def link cssAuralProp cssProp +hi def link cssRenderProp cssProp +hi def link cssMobileTextProp cssProp + +hi def link cssAnimationAttr cssAttr +hi def link cssBackgroundAttr cssAttr +hi def link cssBorderAttr cssAttr +hi def link cssBoxAttr cssAttr +hi def link cssContentForPagedMediaAttr cssAttr +hi def link cssDimensionAttr cssAttr +hi def link cssFlexibleBoxAttr cssAttr +hi def link cssFontAttr cssAttr +hi def link cssGeneratedContentAttr cssAttr +hi def link cssGridAttr cssAttr +hi def link cssHyerlinkAttr cssAttr +hi def link cssLineboxAttr cssAttr +hi def link cssListAttr cssAttr +hi def link cssMarginAttr cssAttr +hi def link cssMarqueeAttr cssAttr +hi def link cssMultiColumnAttr cssAttr +hi def link cssPaddingAttr cssAttr +hi def link cssPagedMediaAttr cssAttr +hi def link cssPositioningAttr cssAttr +hi def link cssGradientAttr cssAttr +hi def link cssPrintAttr cssAttr +hi def link cssRubyAttr cssAttr +hi def link cssSpeechAttr cssAttr +hi def link cssTableAttr cssAttr +hi def link cssTextAttr cssAttr +hi def link cssTransformAttr cssAttr +hi def link cssTransitionAttr cssAttr +hi def link cssUIAttr cssAttr +hi def link cssIEUIAttr cssAttr +hi def link cssAuralAttr cssAttr +hi def link cssRenderAttr cssAttr +hi def link cssCommonAttr cssAttr + +hi def link cssPseudoClassId PreProc +hi def link cssPseudoClassLang Constant +hi def link cssValueLength Number +hi def link cssValueInteger Number +hi def link cssValueNumber Number +hi def link cssValueAngle Number +hi def link cssValueTime Number +hi def link cssValueFrequency Number +hi def link cssFunction Constant +hi def link cssURL String +hi def link cssFunctionName Function +hi def link cssFunctionComma Function +hi def link cssColor Constant +hi def link cssIdentifier Function +hi def link cssInclude Include +hi def link cssIncludeKeyword atKeyword +hi def link cssImportant Special +hi def link cssBraces Function +hi def link cssBraceError Error +hi def link cssError Error +hi def link cssUnicodeEscape Special +hi def link cssStringQQ String +hi def link cssStringQ String +hi def link cssAttributeSelector String +hi def link cssMedia atKeyword +hi def link cssMediaType Special +hi def link cssMediaComma Normal +hi def link cssMediaKeyword Statement +hi def link cssMediaProp cssProp +hi def link cssMediaAttr cssAttr +hi def link cssPage atKeyword +hi def link cssPagePseudo PreProc +hi def link cssPageMargin atKeyword +hi def link cssPageProp cssProp +hi def link cssKeyFrame atKeyword +hi def link cssKeyFrameSelector Constant +hi def link cssFontDescriptor Special +hi def link cssFontDescriptorFunction Constant +hi def link cssFontDescriptorProp cssProp +hi def link cssFontDescriptorAttr cssAttr +hi def link cssUnicodeRange Constant +hi def link cssClassName Function +hi def link cssClassNameDot Function +hi def link cssProp StorageClass +hi def link cssAttr Constant +hi def link cssUnitDecorators Number +hi def link cssNoise Noise +hi def link atKeyword PreProc let b:current_syntax = "css" diff --git a/runtime/syntax/cterm.vim b/runtime/syntax/cterm.vim index 139a0d5e17..1b6cb2893f 100644 --- a/runtime/syntax/cterm.vim +++ b/runtime/syntax/cterm.vim @@ -4,11 +4,8 @@ " Last Change: 2002 Apr 13 " Version Info: @(#)cterm.vim 1.7 97/12/15 09:23:14 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -142,48 +139,38 @@ syn match ctermCharacter "'[^\\]'" syn match ctermSpecialCharacter "'\\.'" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_cterm_syntax_inits") - if version < 508 - let did_cterm_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink ctermStatement Statement - HiLink ctermFunction Statement - HiLink ctermStrFunction Statement - HiLink ctermIntFunction Statement - HiLink ctermLabel Statement - HiLink ctermConditional Statement - HiLink ctermRepeat Statement - HiLink ctermLibFunc UserDefFunc - HiLink ctermType Type - HiLink ctermFuncArg PreCondit - - HiLink ctermPreVarRO PreCondit - HiLink ctermPreVarRW PreConditBold - HiLink ctermVar Type - - HiLink ctermComment Comment - - HiLink ctermCharacter SpecialChar - HiLink ctermSpecial Special - HiLink ctermSpecialCharacter SpecialChar - HiLink ctermSymbols Special - HiLink ctermString String - HiLink ctermTodo Todo - HiLink ctermOperator Statement - HiLink ctermNumber Number - - " redefine the colors - "hi PreConditBold term=bold ctermfg=1 cterm=bold guifg=Purple gui=bold - "hi Special term=bold ctermfg=6 guifg=SlateBlue gui=underline - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link ctermStatement Statement +hi def link ctermFunction Statement +hi def link ctermStrFunction Statement +hi def link ctermIntFunction Statement +hi def link ctermLabel Statement +hi def link ctermConditional Statement +hi def link ctermRepeat Statement +hi def link ctermLibFunc UserDefFunc +hi def link ctermType Type +hi def link ctermFuncArg PreCondit + +hi def link ctermPreVarRO PreCondit +hi def link ctermPreVarRW PreConditBold +hi def link ctermVar Type + +hi def link ctermComment Comment + +hi def link ctermCharacter SpecialChar +hi def link ctermSpecial Special +hi def link ctermSpecialCharacter SpecialChar +hi def link ctermSymbols Special +hi def link ctermString String +hi def link ctermTodo Todo +hi def link ctermOperator Statement +hi def link ctermNumber Number + +" redefine the colors +"hi PreConditBold term=bold ctermfg=1 cterm=bold guifg=Purple gui=bold +"hi Special term=bold ctermfg=6 guifg=SlateBlue gui=underline + let b:current_syntax = "cterm" diff --git a/runtime/syntax/cuda.vim b/runtime/syntax/cuda.vim index 77930e3fd4..cfc70b9ea8 100644 --- a/runtime/syntax/cuda.vim +++ b/runtime/syntax/cuda.vim @@ -3,20 +3,13 @@ " Maintainer: Timothy B. Terriberry <tterribe@users.sourceforge.net> " Last Change: 2007 Oct 13 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif " Read the C syntax to start with -if version < 600 - source <sfile>:p:h/c.vim -else - runtime! syntax/c.vim -endif +runtime! syntax/c.vim " CUDA extentions syn keyword cudaStorageClass __device__ __global__ __host__ diff --git a/runtime/syntax/cupl.vim b/runtime/syntax/cupl.vim index 545d873af2..5b93b0db93 100644 --- a/runtime/syntax/cupl.vim +++ b/runtime/syntax/cupl.vim @@ -3,11 +3,8 @@ " Maintainer: John Cook <johncook3@gmail.com> " Last Change: 2011 Dec 27 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -95,39 +92,29 @@ syn region cuplComment start=+/\*+ end=+\*/+ contains=cuplNumber,cuplTodo syn sync minlines=1 " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_cupl_syn_inits") - if version < 508 - let did_cupl_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - " The default highlighting. - HiLink cuplHeader cuplStatement - HiLink cuplLogicalOperator cuplOperator - HiLink cuplRangeOperator cuplOperator - HiLink cuplArithmeticOperator cuplOperator - HiLink cuplAssignmentOperator cuplOperator - HiLink cuplEqualityOperator cuplOperator - HiLink cuplTruthTableOperator cuplOperator - HiLink cuplOperator cuplStatement - HiLink cuplFunction cuplStatement - HiLink cuplStatement Statement - HiLink cuplNumberRange cuplNumber - HiLink cuplNumber cuplString - HiLink cuplString String - HiLink cuplComment Comment - HiLink cuplExtension cuplSpecial - HiLink cuplSpecialChar cuplSpecial - HiLink cuplSpecial Special - HiLink cuplDirective PreProc - HiLink cuplTodo Todo - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +" The default highlighting. +hi def link cuplHeader cuplStatement +hi def link cuplLogicalOperator cuplOperator +hi def link cuplRangeOperator cuplOperator +hi def link cuplArithmeticOperator cuplOperator +hi def link cuplAssignmentOperator cuplOperator +hi def link cuplEqualityOperator cuplOperator +hi def link cuplTruthTableOperator cuplOperator +hi def link cuplOperator cuplStatement +hi def link cuplFunction cuplStatement +hi def link cuplStatement Statement +hi def link cuplNumberRange cuplNumber +hi def link cuplNumber cuplString +hi def link cuplString String +hi def link cuplComment Comment +hi def link cuplExtension cuplSpecial +hi def link cuplSpecialChar cuplSpecial +hi def link cuplSpecial Special +hi def link cuplDirective PreProc +hi def link cuplTodo Todo + let b:current_syntax = "cupl" diff --git a/runtime/syntax/cuplsim.vim b/runtime/syntax/cuplsim.vim index 18a30ce256..36eb4c3555 100644 --- a/runtime/syntax/cuplsim.vim +++ b/runtime/syntax/cuplsim.vim @@ -3,21 +3,14 @@ " Maintainer: John Cook <john.cook@kla-tencor.com> " Last Change: 2001 Apr 25 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif " Read the CUPL syntax to start with -if version < 600 - source <sfile>:p:h/cupl.vim -else - runtime! syntax/cupl.vim - unlet b:current_syntax -endif +runtime! syntax/cupl.vim +unlet b:current_syntax " omit definition-specific stuff syn clear cuplStatement @@ -53,28 +46,18 @@ syn match cuplsimOutput +"\x\+"+ syn sync minlines=1 " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_cuplsim_syn_inits") - if version < 508 - let did_cuplsim_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - " append to the highlighting links in cupl.vim - " The default highlighting. - HiLink cuplsimOrder cuplStatement - HiLink cuplsimBase cuplStatement - HiLink cuplsimBaseType cuplStatement - HiLink cuplsimVectors cuplStatement - HiLink cuplsimStimulus cuplNumber - HiLink cuplsimOutput cuplNumber - HiLink cuplsimOrderFormat cuplNumber +" Only when an item doesn't have highlighting yet + +" append to the highlighting links in cupl.vim +" The default highlighting. +hi def link cuplsimOrder cuplStatement +hi def link cuplsimBase cuplStatement +hi def link cuplsimBaseType cuplStatement +hi def link cuplsimVectors cuplStatement +hi def link cuplsimStimulus cuplNumber +hi def link cuplsimOutput cuplNumber +hi def link cuplsimOrderFormat cuplNumber - delcommand HiLink -endif let b:current_syntax = "cuplsim" " vim:ts=8 diff --git a/runtime/syntax/cvs.vim b/runtime/syntax/cvs.vim index 94b2a809eb..3eac191637 100644 --- a/runtime/syntax/cvs.vim +++ b/runtime/syntax/cvs.vim @@ -4,11 +4,8 @@ " URL: http://www.zotikos.com/downloads/cvs.vim " Last Change: Sat Nov 24 23:25:11 CET 2001 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -20,24 +17,14 @@ syn region cvsCom start="Committing in" end="$" contains=cvsDir contained extend syn match cvsDir contained "\S\+$" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_cvs_syn_inits") - if version < 508 - let did_cvs_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink cvsLine Comment - HiLink cvsDir cvsFile - HiLink cvsFile Constant - HiLink cvsFiles cvsCom - HiLink cvsTag cvsCom - HiLink cvsCom Statement +hi def link cvsLine Comment +hi def link cvsDir cvsFile +hi def link cvsFile Constant +hi def link cvsFiles cvsCom +hi def link cvsTag cvsCom +hi def link cvsCom Statement - delcommand HiLink -endif let b:current_syntax = "cvs" diff --git a/runtime/syntax/cweb.vim b/runtime/syntax/cweb.vim index 39b593d2be..4e06b3646d 100644 --- a/runtime/syntax/cweb.vim +++ b/runtime/syntax/cweb.vim @@ -13,11 +13,8 @@ " TODO: names, and leaves C/C++ comments as such. (On the other hand, " TODO: switching to TeX mode in C/C++ comments might be colour overkill.) -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -25,12 +22,8 @@ endif " level in the CWEB syntax, e.g., in the preamble. In general, a CWEB source " code can be seen as a normal TeX document with some C/C++ material " interspersed in certain defined regions. -if version < 600 - source <sfile>:p:h/tex.vim -else - runtime! syntax/tex.vim - unlet b:current_syntax -endif +runtime! syntax/tex.vim +unlet b:current_syntax " Read the C/C++ syntax too; C/C++ syntax items are treated as such in the " C/C++ section of a CWEB chunk or in inner C/C++ context in "|...|" groups. @@ -63,20 +56,10 @@ syntax region webRestrictedTeX start="@[\^\.:t=q]" end="@>" oneline syntax match webIgnoredStuff "@@" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_cweb_syntax_inits") - if version < 508 - let did_cweb_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink webRestrictedTeX String - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link webRestrictedTeX String + let b:current_syntax = "cweb" diff --git a/runtime/syntax/cynlib.vim b/runtime/syntax/cynlib.vim index a9985074d6..24ad2a2e31 100644 --- a/runtime/syntax/cynlib.vim +++ b/runtime/syntax/cynlib.vim @@ -15,22 +15,15 @@ " Remove any old syntax stuff hanging around -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif " Read the C++ syntax to start with - this includes the C syntax -if version < 600 - source <sfile>:p:h/cpp.vim -else - runtime! syntax/cpp.vim -endif +runtime! syntax/cpp.vim unlet b:current_syntax " Cynlib extensions @@ -69,23 +62,13 @@ syn match cynlibOperator "<<=" syn keyword cynlibType In Out InST OutST Int Uint Const Cynclock " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_cynlib_syntax_inits") - if version < 508 - let did_cynlib_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink cynlibOperator Operator - HiLink cynlibMacro Statement - HiLink cynlibFunction Statement - HiLink cynlibppMacro Statement - HiLink cynlibType Type +hi def link cynlibOperator Operator +hi def link cynlibMacro Statement +hi def link cynlibFunction Statement +hi def link cynlibppMacro Statement +hi def link cynlibType Type - delcommand HiLink -endif let b:current_syntax = "cynlib" diff --git a/runtime/syntax/cynpp.vim b/runtime/syntax/cynpp.vim index b984bace35..3064b11a63 100644 --- a/runtime/syntax/cynpp.vim +++ b/runtime/syntax/cynpp.vim @@ -19,21 +19,13 @@ -" Remove any old syntax stuff hanging around -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif " Read the Cynlib syntax to start with - this includes the C++ syntax -if version < 600 - source <sfile>:p:h/cynlib.vim -else - runtime! syntax/cynlib.vim -endif +runtime! syntax/cynlib.vim unlet b:current_syntax @@ -49,20 +41,10 @@ syn keyword cynppMacro Thread EndThread syn keyword cynppMacro Instantiate " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_cynpp_syntax_inits") - if version < 508 - let did_cynpp_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink cLabel Label - HiLink cynppMacro Statement +hi def link cLabel Label +hi def link cynppMacro Statement - delcommand HiLink -endif let b:current_syntax = "cynpp" diff --git a/runtime/syntax/datascript.vim b/runtime/syntax/datascript.vim index a983b8e34c..7b686a144e 100644 --- a/runtime/syntax/datascript.vim +++ b/runtime/syntax/datascript.vim @@ -8,9 +8,8 @@ " " http://dstools.sourceforge.net/DataScriptLanguageOverview.html -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif let s:keepcpo= &cpo diff --git a/runtime/syntax/dcd.vim b/runtime/syntax/dcd.vim index a566745fbe..058d272375 100644 --- a/runtime/syntax/dcd.vim +++ b/runtime/syntax/dcd.vim @@ -3,11 +3,8 @@ " Maintainer: Christopher Shinn <christopher@lucent.com> " Last Change: 2003 Apr 25 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -40,25 +37,15 @@ syn keyword dcdSpecial PRV1 PRV2 PRV3 PRV4 PRV5 PRV6 PRV7 PRV8 syn region dcdComment start="\*" end="\;" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_dcd_syntax_inits") - if version < 508 - let did_dcd_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink dcdFunction Identifier - HiLink dcdLabel Constant - HiLink dcdConditional Conditional - HiLink dcdDisplay Type - HiLink dcdStatement Statement - HiLink dcdSpecial Special - HiLink dcdComment Comment +hi def link dcdFunction Identifier +hi def link dcdLabel Constant +hi def link dcdConditional Conditional +hi def link dcdDisplay Type +hi def link dcdStatement Statement +hi def link dcdSpecial Special +hi def link dcdComment Comment - delcommand HiLink -endif let b:current_syntax = "dcd" diff --git a/runtime/syntax/dcl.vim b/runtime/syntax/dcl.vim index 73bf577e3e..b973db3434 100644 --- a/runtime/syntax/dcl.vim +++ b/runtime/syntax/dcl.vim @@ -1,15 +1,12 @@ " Vim syntax file " Language: DCL (Digital Command Language - vms) " Maintainer: Charles E. Campbell <NdrOchipS@PcampbellAfamily.Mbiz> -" Last Change: May 02, 2016 -" Version: 9 +" Last Change: Aug 31, 2016 +" Version: 11 " URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_DCL -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -111,49 +108,40 @@ syn region dclFuncList matchgroup=Delimiter start="(" matchgroup=Delimiter end= syn match dclError ")" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_dcl_syntax_inits") - if version < 508 - let did_dcl_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink dclLogOper dclError - HiLink dclLogical dclOper - HiLink dclLogSep dclSep - - HiLink dclAssign Operator - HiLink dclCmdProc Special - HiLink dclCmdProcStart Operator - HiLink dclComment Comment - HiLink dclContinue Statement - HiLink dclDevice Identifier - HiLink dclDirPath Identifier - HiLink dclDirPath Identifier - HiLink dclDirSep Delimiter - HiLink dclError Error - HiLink dclExe Statement - HiLink dclFilename NONE - HiLink dclGotoLabel Label - HiLink dclInstr Statement - HiLink dclLexical Function - HiLink dclMdfy Type - HiLink dclMdfyBrkt Delimiter - HiLink dclMdfySep Delimiter - HiLink dclMdfySet Type - HiLink dclMdfySetString String - HiLink dclNumber Number - HiLink dclOper Operator - HiLink dclParam Special - HiLink dclSep Delimiter - HiLink dclStart Delimiter - HiLink dclString String - HiLink dclTodo Todo - - delcommand HiLink +if !exists("skip_dcl_syntax_inits") + + hi def link dclLogOper dclError + hi def link dclLogical dclOper + hi def link dclLogSep dclSep + + hi def link dclAssign Operator + hi def link dclCmdProc Special + hi def link dclCmdProcStart Operator + hi def link dclComment Comment + hi def link dclContinue Statement + hi def link dclDevice Identifier + hi def link dclDirPath Identifier + hi def link dclDirPath Identifier + hi def link dclDirSep Delimiter + hi def link dclError Error + hi def link dclExe Statement + hi def link dclFilename NONE + hi def link dclGotoLabel Label + hi def link dclInstr Statement + hi def link dclLexical Function + hi def link dclMdfy Type + hi def link dclMdfyBrkt Delimiter + hi def link dclMdfySep Delimiter + hi def link dclMdfySet Type + hi def link dclMdfySetString String + hi def link dclNumber Number + hi def link dclOper Operator + hi def link dclParam Special + hi def link dclSep Delimiter + hi def link dclStart Delimiter + hi def link dclString String + hi def link dclTodo Todo + endif let b:current_syntax = "dcl" diff --git a/runtime/syntax/debchangelog.vim b/runtime/syntax/debchangelog.vim index d0c658c75e..eb02aaf4af 100644 --- a/runtime/syntax/debchangelog.vim +++ b/runtime/syntax/debchangelog.vim @@ -3,13 +3,11 @@ " 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: 2016 Apr 24 +" Last Change: 2016 Nov 12 " URL: https://anonscm.debian.org/cgit/pkg-vim/vim.git/plain/runtime/syntax/debchangelog.vim " Standard syntax initialization -if version < 600 - syntax clear -elseif exists("b:current_syntax") +if exists("b:current_syntax") finish endif @@ -23,7 +21,7 @@ let binNMU='binary-only=yes' syn match debchangelogName contained "^[[:alnum:]][[:alnum:].+-]\+ " exe 'syn match debchangelogFirstKV contained "; \('.urgency.'\|'.binNMU.'\)"' exe 'syn match debchangelogOtherKV contained ", \('.urgency.'\|'.binNMU.'\)"' -syn match debchangelogTarget contained "\v %(frozen|unstable|sid|%(testing|%(old)=stable)%(-proposed-updates|-security)=|experimental|squeeze-%(backports%(-sloppy)=|volatile|lts|security)|wheezy-%(backports%(-sloppy)=|security)|jessie%(-backports|-security)=|stretch|%(devel|precise|trusty|vivid|wily|xenial|yakkety)%(-%(security|proposed|updates|backports|commercial|partner))=)+" +syn match debchangelogTarget contained "\v %(frozen|unstable|sid|%(testing|%(old)=stable)%(-proposed-updates|-security)=|experimental|squeeze-%(backports%(-sloppy)=|volatile|lts|security)|wheezy-%(backports%(-sloppy)=|security)|jessie%(-backports|-security)=|stretch|%(devel|precise|trusty|vivid|wily|xenial|yakkety|zesty)%(-%(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\+\)*" @@ -36,28 +34,17 @@ syn region debchangelogFooter start="^ [^ ]" end="$" contains=debchangelogEmail syn region debchangelogEntry start="^ " end="$" contains=debchangelogCloses,debchangelogLP oneline " Associate our matches and regions with pretty colours -if version >= 508 || !exists("did_debchangelog_syn_inits") - if version < 508 - let did_debchangelog_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink debchangelogHeader Error - HiLink debchangelogFooter Identifier - HiLink debchangelogEntry Normal - HiLink debchangelogCloses Statement - HiLink debchangelogLP Statement - HiLink debchangelogFirstKV Identifier - HiLink debchangelogOtherKV Identifier - HiLink debchangelogName Comment - HiLink debchangelogVersion Identifier - HiLink debchangelogTarget Identifier - HiLink debchangelogEmail Special - - delcommand HiLink -endif +hi def link debchangelogHeader Error +hi def link debchangelogFooter Identifier +hi def link debchangelogEntry Normal +hi def link debchangelogCloses Statement +hi def link debchangelogLP Statement +hi def link debchangelogFirstKV Identifier +hi def link debchangelogOtherKV Identifier +hi def link debchangelogName Comment +hi def link debchangelogVersion Identifier +hi def link debchangelogTarget Identifier +hi def link debchangelogEmail Special let b:current_syntax = "debchangelog" diff --git a/runtime/syntax/debcontrol.vim b/runtime/syntax/debcontrol.vim index 4fb53a55ca..b1bc9f8bfe 100644 --- a/runtime/syntax/debcontrol.vim +++ b/runtime/syntax/debcontrol.vim @@ -3,13 +3,11 @@ " Maintainer: Debian Vim Maintainers <pkg-vim-maintainers@lists.alioth.debian.org> " Former Maintainers: Gerfried Fuchs <alfie@ist.org> " Wichert Akkerman <wakkerma@debian.org> -" Last Change: 2015 Oct 24 +" Last Change: 2016 Aug 30 " URL: https://anonscm.debian.org/cgit/pkg-vim/vim.git/plain/runtime/syntax/debcontrol.vim " Standard syntax initialization -if version < 600 - syntax clear -elseif exists("b:current_syntax") +if exists("b:current_syntax") finish endif @@ -28,7 +26,7 @@ syn match debControlSpace " " let s:kernels = '\%(linux\|hurd\|kfreebsd\|knetbsd\|kopensolaris\|netbsd\)' let s:archs = '\%(alpha\|amd64\|armeb\|armel\|armhf\|arm64\|avr32\|hppa\|i386' - \ . '\|ia64\|lpia\|m32r\|m68k\|mipsel\|mips\|powerpcspe\|powerpc\|ppc64el' + \ . '\|ia64\|lpia\|m32r\|m68k\|mipsel\|mips64el\|mips\|powerpcspe\|powerpc\|ppc64el' \ . '\|ppc64\|s390x\|s390\|sh3eb\|sh3\|sh4eb\|sh4\|sh\|sparc64\|sparc\|x32\)' let s:pairs = 'hurd-i386\|kfreebsd-i386\|kfreebsd-amd64\|knetbsd-i386\|kopensolaris-i386\|netbsd-alpha\|netbsd-i386' @@ -40,7 +38,7 @@ unlet s:kernels s:archs s:pairs syn match debcontrolMultiArch contained "\%(no\|foreign\|allowed\|same\)" syn match debcontrolName contained "[a-z0-9][a-z0-9+.-]\+" syn match debcontrolPriority contained "\(extra\|important\|optional\|required\|standard\)" -syn match debcontrolSection contained "\v((contrib|non-free|non-US/main|non-US/contrib|non-US/non-free|restricted|universe|multiverse)/)?(admin|cli-mono|comm|database|debian-installer|debug|devel|doc|editors|education|electronics|embedded|fonts|games|gnome|gnustep|gnu-r|graphics|hamradio|haskell|httpd|interpreters|introspection|java|kde|kernel|libs|libdevel|lisp|localization|mail|math|metapackages|misc|net|news|ocaml|oldlibs|otherosfs|perl|php|python|ruby|science|shells|sound|text|tex|utils|vcs|video|web|x11|xfce|zope)" +syn match debcontrolSection contained "\v((contrib|non-free|non-US/main|non-US/contrib|non-US/non-free|restricted|universe|multiverse)/)?(admin|cli-mono|comm|database|debian-installer|debug|devel|doc|editors|education|electronics|embedded|fonts|games|gnome|gnustep|gnu-r|graphics|hamradio|haskell|httpd|interpreters|introspection|java|javascript|kde|kernel|libs|libdevel|lisp|localization|mail|math|metapackages|misc|net|news|ocaml|oldlibs|otherosfs|perl|php|python|ruby|rust|science|shells|sound|text|tex|utils|vcs|video|web|x11|xfce|zope)" syn match debcontrolPackageType contained "u\?deb" syn match debcontrolVariable contained "\${.\{-}}" syn match debcontrolDmUpload contained "\cyes" @@ -86,37 +84,26 @@ syn region debcontrolMultiField start="^\%(Build-\%(Conflicts\|Depends\)\%(-Inde syn region debcontrolMultiFieldSpell start="^\%(Description\):" skip="^ " end="^$"me=s-1 end="^[^ #]"me=s-1 contains=debcontrolKey,debcontrolEmail,debcontrolVariable,debcontrolComment,@Spell " Associate our matches and regions with pretty colours -if version >= 508 || !exists("did_debcontrol_syn_inits") - if version < 508 - let did_debcontrol_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink debcontrolKey Keyword - HiLink debcontrolField Normal - HiLink debcontrolStrictField Error - HiLink debcontrolDeprecatedKey Error - HiLink debcontrolMultiField Normal - HiLink debcontrolArchitecture Normal - HiLink debcontrolMultiArch Normal - HiLink debcontrolName Normal - HiLink debcontrolPriority Normal - HiLink debcontrolSection Normal - HiLink debcontrolPackageType Normal - HiLink debcontrolVariable Identifier - HiLink debcontrolEmail Identifier - HiLink debcontrolVcsSvn Identifier - HiLink debcontrolVcsCvs Identifier - HiLink debcontrolVcsGit Identifier - HiLink debcontrolHTTPUrl Identifier - HiLink debcontrolDmUpload Identifier - HiLink debcontrolComment Comment - HiLink debcontrolElse Special - - delcommand HiLink -endif +hi def link debcontrolKey Keyword +hi def link debcontrolField Normal +hi def link debcontrolStrictField Error +hi def link debcontrolDeprecatedKey Error +hi def link debcontrolMultiField Normal +hi def link debcontrolArchitecture Normal +hi def link debcontrolMultiArch Normal +hi def link debcontrolName Normal +hi def link debcontrolPriority Normal +hi def link debcontrolSection Normal +hi def link debcontrolPackageType Normal +hi def link debcontrolVariable Identifier +hi def link debcontrolEmail Identifier +hi def link debcontrolVcsSvn Identifier +hi def link debcontrolVcsCvs Identifier +hi def link debcontrolVcsGit Identifier +hi def link debcontrolHTTPUrl Identifier +hi def link debcontrolDmUpload Identifier +hi def link debcontrolComment Comment +hi def link debcontrolElse Special let b:current_syntax = "debcontrol" diff --git a/runtime/syntax/debsources.vim b/runtime/syntax/debsources.vim index d35e24729d..390c43035e 100644 --- a/runtime/syntax/debsources.vim +++ b/runtime/syntax/debsources.vim @@ -2,13 +2,11 @@ " Language: Debian sources.list " Maintainer: Debian Vim Maintainers <pkg-vim-maintainers@lists.alioth.debian.org> " Former Maintainer: Matthijs Mohlmann <matthijs@cacholong.nl> -" Last Change: 2016 Apr 24 +" Last Change: 2016 Nov 12 " URL: https://anonscm.debian.org/cgit/pkg-vim/vim.git/plain/runtime/syntax/debsources.vim " Standard syntax initialization -if version < 600 - syntax clear -elseif exists("b:current_syntax") +if exists("b:current_syntax") finish endif @@ -27,7 +25,7 @@ let s:supported = [ \ 'oldstable', 'stable', 'testing', 'unstable', 'experimental', \ 'squeeze', 'wheezy', 'jessie', 'stretch', 'sid', 'rc-buggy', \ - \ 'precise', 'trusty', 'wily', 'xenial', 'yakkety', 'devel' + \ 'precise', 'trusty', 'xenial', 'yakkety', 'zesty', 'devel' \ ] let s:unsupported = [ \ 'buzz', 'rex', 'bo', 'hamm', 'slink', 'potato', @@ -36,12 +34,12 @@ let s:unsupported = [ \ 'warty', 'hoary', 'breezy', 'dapper', 'edgy', 'feisty', \ 'gutsy', 'hardy', 'intrepid', 'jaunty', 'karmic', 'lucid', \ 'maverick', 'natty', 'oneiric', 'quantal', 'raring', 'saucy', - \ 'utopic', 'vivid' + \ 'utopic', 'vivid', 'wily' \ ] let &cpo=s:cpo " Match uri's -syn match debsourcesUri +\(http://\|ftp://\|[rs]sh://\|debtorrent://\|\(cdrom\|copy\|file\):\)[^' <>"]\++ +syn match debsourcesUri +\(https\?://\|ftp://\|[rs]sh://\|debtorrent://\|\(cdrom\|copy\|file\):\)[^' <>"]\++ exe 'syn match debsourcesDistrKeyword +\([[:alnum:]_./]*\)\('. join(s:supported, '\|'). '\)\([-[:alnum:]_./]*\)+' exe 'syn match debsourcesUnsupportedDistrKeyword +\([[:alnum:]_./]*\)\('. join(s:unsupported, '\|') .'\)\([-[:alnum:]_./]*\)+' diff --git a/runtime/syntax/def.vim b/runtime/syntax/def.vim index 5efb41bc43..a17714c41e 100644 --- a/runtime/syntax/def.vim +++ b/runtime/syntax/def.vim @@ -5,11 +5,8 @@ " Last Change: $Date: 2007/10/02 13:51:24 $ " $Revision: 1.2 $ -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -32,25 +29,15 @@ syn match defNumber "0x\x\+" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_def_syntax_inits") - if version < 508 - let did_def_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink defComment Comment - HiLink defKeyword Keyword - HiLink defStorage StorageClass - HiLink defString String - HiLink defNumber Number - HiLink defOrdinal Operator - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link defComment Comment +hi def link defKeyword Keyword +hi def link defStorage StorageClass +hi def link defString String +hi def link defNumber Number +hi def link defOrdinal Operator + let b:current_syntax = "def" diff --git a/runtime/syntax/desc.vim b/runtime/syntax/desc.vim index ca47176ff7..84b9cd0f34 100644 --- a/runtime/syntax/desc.vim +++ b/runtime/syntax/desc.vim @@ -3,11 +3,8 @@ " Maintainer: Renรฉ Rebe <rene@exactcode.de>, Piotr Esden-Tempski <esden@rocklinux.org> " Last Change: 2006 Aug 14 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -63,40 +60,29 @@ syn region descTagRegion start=/^\[\(F\|FLAG\)\]/ end=/$/ contains=descTag,descF syn region descTagRegion start=/^\[\(L\|LICENSE\)\]/ end=/$/ contains=descTag,descLicense -" For version 5.7 and earlier: only when not done already -" Define the default highlighting. -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_desc_syntax_inits") - if version < 508 - let did_desc_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink descFlag Identifier - HiLink descLicense Identifier - HiLink descCategory Identifier - - HiLink descTag Type - HiLink descUrl Underlined - HiLink descEmail Underlined - - " priority tag colors - HiLink descInstallX Boolean - HiLink descInstallO Type - HiLink descDash Operator - HiLink descDigit Number - HiLink descCompilePriority Number - - " download tag colors - HiLink descSum Number - HiLink descTarball Underlined - - " tag region colors - HiLink descText Comment - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link descFlag Identifier +hi def link descLicense Identifier +hi def link descCategory Identifier + +hi def link descTag Type +hi def link descUrl Underlined +hi def link descEmail Underlined + +" priority tag colors +hi def link descInstallX Boolean +hi def link descInstallO Type +hi def link descDash Operator +hi def link descDigit Number +hi def link descCompilePriority Number + +" download tag colors +hi def link descSum Number +hi def link descTarball Underlined + +" tag region colors +hi def link descText Comment + let b:current_syntax = "desc" diff --git a/runtime/syntax/desktop.vim b/runtime/syntax/desktop.vim index 27dac5c8ee..915107887a 100644 --- a/runtime/syntax/desktop.vim +++ b/runtime/syntax/desktop.vim @@ -7,11 +7,8 @@ " (added "Keywords") " Version Info: desktop.vim 0.9.4-1.2 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -79,41 +76,31 @@ syn match dtALocale /\[.\{-}\]\s*=\@=/ containedin=ALL " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_desktop_syntax_inits") - if version < 508 - let did_dosini_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink dtGroup Special - HiLink dtComment Comment - HiLink dtDelim String - - HiLink dtLocaleKey Type - HiLink dtLocaleName Identifier - HiLink dtXLocale Identifier - HiLink dtALocale Identifier - - HiLink dtNumericKey Type - - HiLink dtBooleanKey Type - HiLink dtBooleanValue Constant - - HiLink dtStringKey Type - - HiLink dtExecKey Type - HiLink dtExecParam Special - HiLink dtTypeKey Type - HiLink dtTypeValue Constant - HiLink dtNotStLabel Type - HiLink dtXAddKey Type - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link dtGroup Special +hi def link dtComment Comment +hi def link dtDelim String + +hi def link dtLocaleKey Type +hi def link dtLocaleName Identifier +hi def link dtXLocale Identifier +hi def link dtALocale Identifier + +hi def link dtNumericKey Type + +hi def link dtBooleanKey Type +hi def link dtBooleanValue Constant + +hi def link dtStringKey Type + +hi def link dtExecKey Type +hi def link dtExecParam Special +hi def link dtTypeKey Type +hi def link dtTypeValue Constant +hi def link dtNotStLabel Type +hi def link dtXAddKey Type + let b:current_syntax = "desktop" diff --git a/runtime/syntax/diva.vim b/runtime/syntax/diva.vim index 78668fd85a..127a0b4663 100644 --- a/runtime/syntax/diva.vim +++ b/runtime/syntax/diva.vim @@ -11,11 +11,7 @@ " Don't remove any old syntax stuff hanging around! We need stuff " from skill.vim. if !exists("did_skill_syntax_inits") - if version < 600 - so <sfile>:p:h/skill.vim - else - runtime! syntax/skill.vim - endif + runtime! syntax/skill.vim endif syn keyword divaDRCKeywords area enc notch ovlp sep width @@ -81,29 +77,19 @@ syn match divaGeomFunctions "(geom\u\a\+\(45\|90\)\=\>"hs=s+1 syn match divaGeomFunctions "\<geom\u\a\+\(45\|90\)\=("he=e-1 " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_diva_syntax_inits") - if version < 508 - let did_diva_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink divaDRCKeywords Statement - HiLink divaMeasKeywords Statement - HiLink divaCtrlFunctions Conditional - HiLink divaExtFunctions Function - HiLink divaDRCFunctions Function - HiLink divaFunctions Function - HiLink divaLayerFunctions Function - HiLink divaChkFunctions Function - HiLink divaLVSFunctions Function - HiLink divaGeomFunctions Function +hi def link divaDRCKeywords Statement +hi def link divaMeasKeywords Statement +hi def link divaCtrlFunctions Conditional +hi def link divaExtFunctions Function +hi def link divaDRCFunctions Function +hi def link divaFunctions Function +hi def link divaLayerFunctions Function +hi def link divaChkFunctions Function +hi def link divaLVSFunctions Function +hi def link divaGeomFunctions Function - delcommand HiLink -endif let b:current_syntax = "diva" diff --git a/runtime/syntax/django.vim b/runtime/syntax/django.vim index da315ac302..d3ca4de0e2 100644 --- a/runtime/syntax/django.vim +++ b/runtime/syntax/django.vim @@ -3,11 +3,8 @@ " Maintainer: Dave Hodder <dmh@dmh.org.uk> " Last Change: 2014 Jul 13 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -68,29 +65,19 @@ syn region djangoComment start="{%\s*comment\(\s\+.\{-}\)\?%}" end="{%\s*endcomm syn region djangoComBlock start="{#" end="#}" contains=djangoTodo " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_django_syn_inits") - if version < 508 - let did_django_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink djangoTagBlock PreProc - HiLink djangoVarBlock PreProc - HiLink djangoStatement Statement - HiLink djangoFilter Identifier - HiLink djangoArgument Constant - HiLink djangoTagError Error - HiLink djangoVarError Error - HiLink djangoError Error - HiLink djangoComment Comment - HiLink djangoComBlock Comment - HiLink djangoTodo Todo +hi def link djangoTagBlock PreProc +hi def link djangoVarBlock PreProc +hi def link djangoStatement Statement +hi def link djangoFilter Identifier +hi def link djangoArgument Constant +hi def link djangoTagError Error +hi def link djangoVarError Error +hi def link djangoError Error +hi def link djangoComment Comment +hi def link djangoComBlock Comment +hi def link djangoTodo Todo - delcommand HiLink -endif let b:current_syntax = "django" diff --git a/runtime/syntax/dnsmasq.vim b/runtime/syntax/dnsmasq.vim index 9fa32077b6..a4cc8b577b 100644 --- a/runtime/syntax/dnsmasq.vim +++ b/runtime/syntax/dnsmasq.vim @@ -20,10 +20,8 @@ " endif " -" For version 5.x: Clear all syntax items -if v:version < 600 - syntax clear -elseif exists("b:current_syntax") || &compatible +" quit when a syntax file was already loaded +if exists("b:current_syntax") || &compatible finish endif diff --git a/runtime/syntax/docbk.vim b/runtime/syntax/docbk.vim index fc679eecaf..809f2894e6 100644 --- a/runtime/syntax/docbk.vim +++ b/runtime/syntax/docbk.vim @@ -13,11 +13,8 @@ " http://www.open-oasis.org/docbook/ " -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -174,26 +171,15 @@ syn region docbkRemark start="<comment>"lc=9 end="</comment>"me=e-10 contains=x syn region docbkCite start="<citation>"lc=10 end="</citation>"me=e-11 contains=xmlRegion,xmlEntity,sgmlRegion,sgmlEntity keepend " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_docbk_syn_inits") - if version < 508 - let did_docbk_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - hi DocbkBold term=bold cterm=bold gui=bold - else - command -nargs=+ HiLink hi def link <args> - hi def DocbkBold term=bold cterm=bold gui=bold - endif +" Only when an item doesn't have highlighting yet +hi def DocbkBold term=bold cterm=bold gui=bold - HiLink docbkKeyword Statement - HiLink docbkRegion DocbkBold - HiLink docbkTitle Title - HiLink docbkRemark Comment - HiLink docbkCite Constant +hi def link docbkKeyword Statement +hi def link docbkRegion DocbkBold +hi def link docbkTitle Title +hi def link docbkRemark Comment +hi def link docbkCite Constant - delcommand HiLink -endif let b:current_syntax = "docbk" diff --git a/runtime/syntax/dosbatch.vim b/runtime/syntax/dosbatch.vim index d9b1aa6703..249e6f7c46 100644 --- a/runtime/syntax/dosbatch.vim +++ b/runtime/syntax/dosbatch.vim @@ -9,11 +9,8 @@ " dosbatch_cmdextversion - 1 = Windows NT, 2 = Windows 2000 [default] " -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -111,49 +108,39 @@ syn keyword dosbatchImplicit sort start subst time title tree type ver verify syn keyword dosbatchImplicit vol xcopy " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_dosbatch_syntax_inits") - if version < 508 - let did_dosbatch_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink dosbatchTodo Todo - - HiLink dosbatchStatement Statement - HiLink dosbatchCommands dosbatchStatement - HiLink dosbatchLabel Label - HiLink dosbatchConditional Conditional - HiLink dosbatchRepeat Repeat - - HiLink dosbatchOperator Operator - HiLink dosbatchEchoOperator dosbatchOperator - HiLink dosbatchIfOperator dosbatchOperator - - HiLink dosbatchArgument Identifier - HiLink dosbatchIdentifier Identifier - HiLink dosbatchVariable dosbatchIdentifier - - HiLink dosbatchSpecialChar SpecialChar - HiLink dosbatchString String - HiLink dosbatchNumber Number - HiLink dosbatchInteger dosbatchNumber - HiLink dosbatchHex dosbatchNumber - HiLink dosbatchBinary dosbatchNumber - HiLink dosbatchOctal dosbatchNumber - - HiLink dosbatchComment Comment - HiLink dosbatchImplicit Function - - HiLink dosbatchSwitch Special - - HiLink dosbatchCmd PreProc - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link dosbatchTodo Todo + +hi def link dosbatchStatement Statement +hi def link dosbatchCommands dosbatchStatement +hi def link dosbatchLabel Label +hi def link dosbatchConditional Conditional +hi def link dosbatchRepeat Repeat + +hi def link dosbatchOperator Operator +hi def link dosbatchEchoOperator dosbatchOperator +hi def link dosbatchIfOperator dosbatchOperator + +hi def link dosbatchArgument Identifier +hi def link dosbatchIdentifier Identifier +hi def link dosbatchVariable dosbatchIdentifier + +hi def link dosbatchSpecialChar SpecialChar +hi def link dosbatchString String +hi def link dosbatchNumber Number +hi def link dosbatchInteger dosbatchNumber +hi def link dosbatchHex dosbatchNumber +hi def link dosbatchBinary dosbatchNumber +hi def link dosbatchOctal dosbatchNumber + +hi def link dosbatchComment Comment +hi def link dosbatchImplicit Function + +hi def link dosbatchSwitch Special + +hi def link dosbatchCmd PreProc + let b:current_syntax = "dosbatch" diff --git a/runtime/syntax/dosini.vim b/runtime/syntax/dosini.vim index e474f21116..ccc5e86f1b 100644 --- a/runtime/syntax/dosini.vim +++ b/runtime/syntax/dosini.vim @@ -9,11 +9,8 @@ " Last Change: 2011 Nov 8 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -28,23 +25,13 @@ syn region dosiniHeader start="^\s*\[" end="\]" syn match dosiniComment "^[#;].*$" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_dosini_syntax_inits") - if version < 508 - let did_dosini_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink dosiniNumber Number - HiLink dosiniHeader Special - HiLink dosiniComment Comment - HiLink dosiniLabel Type - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link dosiniNumber Number +hi def link dosiniHeader Special +hi def link dosiniComment Comment +hi def link dosiniLabel Type + let b:current_syntax = "dosini" diff --git a/runtime/syntax/dot.vim b/runtime/syntax/dot.vim index 4cc6f4f21d..0fdd6ea080 100644 --- a/runtime/syntax/dot.vim +++ b/runtime/syntax/dot.vim @@ -6,11 +6,8 @@ " Last Change: 2011 May 17 - improved identifier matching + two new keywords " 2001 May 04 - initial version -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -74,36 +71,26 @@ syn sync minlines=50 syn sync maxlines=500 " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_dot_syntax_inits") - if version < 508 - let did_dot_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink dotParErr Error - HiLink dotBraceErr Error - HiLink dotBrackErr Error - - HiLink dotComment Comment - HiLink dotTodo Todo - - HiLink dotParEncl Keyword - HiLink dotBrackEncl Keyword - HiLink dotBraceEncl Keyword - - HiLink dotKeyword Keyword - HiLink dotType Type - HiLink dotKeyChar Keyword - - HiLink dotString String - HiLink dotIdentifier Identifier - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link dotParErr Error +hi def link dotBraceErr Error +hi def link dotBrackErr Error + +hi def link dotComment Comment +hi def link dotTodo Todo + +hi def link dotParEncl Keyword +hi def link dotBrackEncl Keyword +hi def link dotBraceEncl Keyword + +hi def link dotKeyword Keyword +hi def link dotType Type +hi def link dotKeyChar Keyword + +hi def link dotString String +hi def link dotIdentifier Identifier + let b:current_syntax = "dot" diff --git a/runtime/syntax/dracula.vim b/runtime/syntax/dracula.vim index 6a3806028e..a373dc200c 100644 --- a/runtime/syntax/dracula.vim +++ b/runtime/syntax/dracula.vim @@ -8,11 +8,8 @@ " the purposes of Design Rule Checking, Layout vs. Schematic " verification, and Layout Parameter Extraction. -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -61,24 +58,14 @@ syn match draculaPreProc "^#.*" syn sync lines=50 " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_dracula_syn_inits") - if version < 508 - let did_dracula_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink draculaIdentifier Identifier - HiLink draculaStatement Statement - HiLink draculaType Type - HiLink draculaComment Comment - HiLink draculaPreProc PreProc +hi def link draculaIdentifier Identifier +hi def link draculaStatement Statement +hi def link draculaType Type +hi def link draculaComment Comment +hi def link draculaPreProc PreProc - delcommand HiLink -endif let b:current_syntax = "dracula" diff --git a/runtime/syntax/dtd.vim b/runtime/syntax/dtd.vim index 001dbbddd3..ae0bd1288e 100644 --- a/runtime/syntax/dtd.vim +++ b/runtime/syntax/dtd.vim @@ -126,41 +126,31 @@ syn keyword dtdTodo contained TODO FIXME XXX syn sync lines=250 " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_dtd_syn_inits") - if version < 508 - let did_dtd_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - " The default highlighting. - HiLink dtdFunction Function - HiLink dtdTag Normal - HiLink dtdType Type - HiLink dtdAttrType dtdType - HiLink dtdAttrDef dtdType - HiLink dtdConstant Constant - HiLink dtdString dtdConstant - HiLink dtdEnum dtdConstant - HiLink dtdCard dtdFunction - - HiLink dtdEntity Statement - HiLink dtdEntityPunct dtdType - HiLink dtdParamEntityInst dtdConstant - HiLink dtdParamEntityPunct dtdType - HiLink dtdParamEntityDecl dtdType - HiLink dtdParamEntityDPunct dtdComment - - HiLink dtdComment Comment - HiLink dtdTagName Statement - HiLink dtdError Error - HiLink dtdTodo Todo - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +" The default highlighting. +hi def link dtdFunction Function +hi def link dtdTag Normal +hi def link dtdType Type +hi def link dtdAttrType dtdType +hi def link dtdAttrDef dtdType +hi def link dtdConstant Constant +hi def link dtdString dtdConstant +hi def link dtdEnum dtdConstant +hi def link dtdCard dtdFunction + +hi def link dtdEntity Statement +hi def link dtdEntityPunct dtdType +hi def link dtdParamEntityInst dtdConstant +hi def link dtdParamEntityPunct dtdType +hi def link dtdParamEntityDecl dtdType +hi def link dtdParamEntityDPunct dtdComment + +hi def link dtdComment Comment +hi def link dtdTagName Statement +hi def link dtdError Error +hi def link dtdTodo Todo + let &cpo = s:dtd_cpo_save unlet s:dtd_cpo_save diff --git a/runtime/syntax/dtml.vim b/runtime/syntax/dtml.vim index 7de722aabd..cb09de8091 100644 --- a/runtime/syntax/dtml.vim +++ b/runtime/syntax/dtml.vim @@ -9,20 +9,13 @@ " hacked out of the Zope Quick Reference in case someone finds something " sensible to do with them. I certainly haven't. -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif " First load the HTML syntax -if version < 600 - source <sfile>:p:h/html.vim -else - runtime! syntax/html.vim -endif +runtime! syntax/html.vim syn case match @@ -196,25 +189,15 @@ syn match htmlTagN contained +<\s*[-a-zA-Z0-9]\++hs=s+1 contains=htmlTagNa syn match htmlTagN contained +</\s*[-a-zA-Z0-9]\++hs=s+2 contains=htmlTagName,htmlSpecialTagName,dtmlIsTag,dtmlAttribute,dtmlMethod,@htmlTagNameCluster " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_dtml_syntax_inits") - if version < 508 - let did_dtml_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink dtmlIsTag PreProc - HiLink dtmlAttribute Identifier - HiLink dtmlMethod Function - HiLink dtmlComment Comment - HiLink dtmlTODO Todo - HiLink dtmlSpecialChar Special - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link dtmlIsTag PreProc +hi def link dtmlAttribute Identifier +hi def link dtmlMethod Function +hi def link dtmlComment Comment +hi def link dtmlTODO Todo +hi def link dtmlSpecialChar Special + let b:current_syntax = "dtml" diff --git a/runtime/syntax/dtrace.vim b/runtime/syntax/dtrace.vim index 493de1ed0f..7ed9766e77 100644 --- a/runtime/syntax/dtrace.vim +++ b/runtime/syntax/dtrace.vim @@ -10,19 +10,14 @@ " http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/lib/libdtrace/common/dt_lex.l " http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/lib/libdtrace/common/dt_grammar.y -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif " Read the C syntax to start with -if version < 600 - so <sfile>:p:h/c.vim -else - runtime! syntax/c.vim - unlet b:current_syntax -endif +runtime! syntax/c.vim +unlet b:current_syntax syn clear cCommentL " dtrace doesn't support // style comments diff --git a/runtime/syntax/dylan.vim b/runtime/syntax/dylan.vim index 14262d53d6..345e932e60 100644 --- a/runtime/syntax/dylan.vim +++ b/runtime/syntax/dylan.vim @@ -8,21 +8,14 @@ " syntax files. " Part 1: Syntax definition -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif syn case ignore -if version < 600 - set lisp -else - setlocal lisp -endif +setlocal lisp " Highlight special characters (those that have backslashes) differently syn match dylanSpecial display contained "\\\(x\x\+\|\o\{1,3}\|.\|$\)" @@ -67,42 +60,32 @@ syn region dylanPrecondit start="^\s*#\s*\(if\>\|else\>\|endif\>\)" skip="\\$" syn region dylanHeader start="^[Mm]odule:" end="^$" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_dylan_syntax_inits") - if version < 508 - let did_dylan_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink dylanBlock PreProc - HiLink dylanBoolean Boolean - HiLink dylanCharacter Character - HiLink dylanClass Structure - HiLink dylanClassMods StorageClass - HiLink dylanComment Comment - HiLink dylanConditional Conditional - HiLink dylanConstant Constant - HiLink dylanException Exception - HiLink dylanHeader Macro - HiLink dylanImport Include - HiLink dylanLabel Label - HiLink dylanMiscMods StorageClass - HiLink dylanNumber Number - HiLink dylanOther Keyword - HiLink dylanOperator Operator - HiLink dylanParamDefs Keyword - HiLink dylanPrecondit PreCondit - HiLink dylanRepeat Repeat - HiLink dylanSimpleDefs Keyword - HiLink dylanStatement Macro - HiLink dylanString String - HiLink dylanVariable Identifier +hi def link dylanBlock PreProc +hi def link dylanBoolean Boolean +hi def link dylanCharacter Character +hi def link dylanClass Structure +hi def link dylanClassMods StorageClass +hi def link dylanComment Comment +hi def link dylanConditional Conditional +hi def link dylanConstant Constant +hi def link dylanException Exception +hi def link dylanHeader Macro +hi def link dylanImport Include +hi def link dylanLabel Label +hi def link dylanMiscMods StorageClass +hi def link dylanNumber Number +hi def link dylanOther Keyword +hi def link dylanOperator Operator +hi def link dylanParamDefs Keyword +hi def link dylanPrecondit PreCondit +hi def link dylanRepeat Repeat +hi def link dylanSimpleDefs Keyword +hi def link dylanStatement Macro +hi def link dylanString String +hi def link dylanVariable Identifier - delcommand HiLink -endif let b:current_syntax = "dylan" diff --git a/runtime/syntax/dylanintr.vim b/runtime/syntax/dylanintr.vim index 11ef816681..692db34985 100644 --- a/runtime/syntax/dylanintr.vim +++ b/runtime/syntax/dylanintr.vim @@ -4,11 +4,8 @@ " Last Change: Fri Sep 29 13:53:27 PDT 2000 " -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -26,26 +23,16 @@ syn match dylanintrInclude "^\s*#\s*include\>\s*["<]" contains=intrIncluded "syn keyword intrMods pointer struct " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_dylan_intr_syntax_inits") - if version < 508 - let did_dylan_intr_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink dylanintrInfo Special - HiLink dylanintrInterface Operator - HiLink dylanintrMods Type - HiLink dylanintrClass StorageClass - HiLink dylanintrType Type - HiLink dylanintrIncluded String - HiLink dylanintrInclude Include - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link dylanintrInfo Special +hi def link dylanintrInterface Operator +hi def link dylanintrMods Type +hi def link dylanintrClass StorageClass +hi def link dylanintrType Type +hi def link dylanintrIncluded String +hi def link dylanintrInclude Include + let b:current_syntax = "dylanintr" diff --git a/runtime/syntax/dylanlid.vim b/runtime/syntax/dylanlid.vim index ec7b40114c..dae0bf94b1 100644 --- a/runtime/syntax/dylanlid.vim +++ b/runtime/syntax/dylanlid.vim @@ -5,11 +5,8 @@ " Last Change: Fri Sep 29 13:50:20 PDT 2000 " -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -21,21 +18,11 @@ syn region dylanlidEntry matchgroup=Statement start=":%" end="$" oneline syn sync lines=50 " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_dylan_lid_syntax_inits") - if version < 508 - let did_dylan_lid_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink dylanlidInfo Type - HiLink dylanlidEntry String - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link dylanlidInfo Type +hi def link dylanlidEntry String + let b:current_syntax = "dylanlid" diff --git a/runtime/syntax/ecd.vim b/runtime/syntax/ecd.vim index fff7a4b883..1276f2bd9d 100644 --- a/runtime/syntax/ecd.vim +++ b/runtime/syntax/ecd.vim @@ -8,10 +8,8 @@ " This syntax file was derived from apachestyle.vim " by Christian Hammers <ch@westend.com> -" Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -31,26 +29,16 @@ syn match ecdTagN contained +<[/\s]*[-a-zA-Z0-9_]\++ms=s+1 syn match ecdTagError contained "[^>]<"ms=s+1 " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_ecd_syn_inits") - if version < 508 - let did_ecd_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink ecdComment Comment - HiLink ecdAttr Type - HiLink ecdAttrN Statement - HiLink ecdAttrV Value - HiLink ecdTag Function - HiLink ecdTagN Statement - HiLink ecdTagError Error - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link ecdComment Comment +hi def link ecdAttr Type +hi def link ecdAttrN Statement +hi def link ecdAttrV Value +hi def link ecdTag Function +hi def link ecdTagN Statement +hi def link ecdTagError Error + let b:current_syntax = "ecd" " vim: ts=8 diff --git a/runtime/syntax/edif.vim b/runtime/syntax/edif.vim index 0c17834947..002c9f89e1 100644 --- a/runtime/syntax/edif.vim +++ b/runtime/syntax/edif.vim @@ -8,18 +8,12 @@ " IEC 61690-1 (EDIF Version 3 0 0) " IEC 61690-2 (EDIF Version 4 0 0) -" Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif -if version >= 600 - setlocal iskeyword=48-57,-,+,A-Z,a-z,_,& -else - set iskeyword=A-Z,a-z,_,& -endif +setlocal iskeyword=48-57,-,+,A-Z,a-z,_,& syn region edifList matchgroup=Delimiter start="(" end=")" contains=edifList,edifKeyword,edifString,edifNumber @@ -37,28 +31,15 @@ syn match edifKeyword "(\@<=\s*[a-zA-Z&][a-zA-Z_0-9]*\>" contained syn match edifError ")" " synchronization -if version < 600 - syntax sync maxlines=250 -else - syntax sync fromstart -endif +syntax sync fromstart " Define the default highlighting. -if version >= 508 || !exists("did_edif_syntax_inits") - if version < 508 - let did_edif_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - HiLink edifInString SpecialChar - HiLink edifKeyword Keyword - HiLink edifNumber Number - HiLink edifInStringError edifError - HiLink edifError Error - HiLink edifString String - delcommand HiLink -endif +hi def link edifInString SpecialChar +hi def link edifKeyword Keyword +hi def link edifNumber Number +hi def link edifInStringError edifError +hi def link edifError Error +hi def link edifString String let b:current_syntax = "edif" diff --git a/runtime/syntax/eiffel.vim b/runtime/syntax/eiffel.vim index a91f85d03e..c6634871cc 100644 --- a/runtime/syntax/eiffel.vim +++ b/runtime/syntax/eiffel.vim @@ -5,11 +5,8 @@ " Contributions from: Thilo Six " " URL: https://github.com/eiffelhub/vim-eiffel -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -141,68 +138,58 @@ endif syn sync lines=40 " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_eiffel_syntax_inits") - if version < 508 - let did_eiffel_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink eiffelKeyword Statement - HiLink eiffelProperty Statement - HiLink eiffelInheritClause Statement - HiLink eiffelStatement Statement - HiLink eiffelDeclaration Statement - HiLink eiffelAssertion Statement - HiLink eiffelDebug Statement - HiLink eiffelException Statement - HiLink eiffelGenericCreate Statement +hi def link eiffelKeyword Statement +hi def link eiffelProperty Statement +hi def link eiffelInheritClause Statement +hi def link eiffelStatement Statement +hi def link eiffelDeclaration Statement +hi def link eiffelAssertion Statement +hi def link eiffelDebug Statement +hi def link eiffelException Statement +hi def link eiffelGenericCreate Statement - HiLink eiffelAgent Statement - HiLink eiffelConvert Statement +hi def link eiffelAgent Statement +hi def link eiffelConvert Statement - HiLink eiffelTopStruct PreProc +hi def link eiffelTopStruct PreProc - HiLink eiffelAll Special - HiLink eiffelAnchored Special - HiLink eiffelBitType Special +hi def link eiffelAll Special +hi def link eiffelAnchored Special +hi def link eiffelBitType Special - HiLink eiffelBool Boolean - HiLink eiffelString String - HiLink eiffelCharacter Character - HiLink eiffelClassName Type - HiLink eiffelNumber Number +hi def link eiffelBool Boolean +hi def link eiffelString String +hi def link eiffelCharacter Character +hi def link eiffelClassName Type +hi def link eiffelNumber Number - HiLink eiffelStringEscape Special +hi def link eiffelStringEscape Special - HiLink eiffelOperator Special - HiLink eiffelArray Special - HiLink eiffelExport Special - HiLink eiffelCreation Special - HiLink eiffelBrackets Special - HiLink eiffelGeneric Special - HiLink eiffelGenericDecl Special - HiLink eiffelConstraint Special - HiLink eiffelCreate Special +hi def link eiffelOperator Special +hi def link eiffelArray Special +hi def link eiffelExport Special +hi def link eiffelCreation Special +hi def link eiffelBrackets Special +hi def link eiffelGeneric Special +hi def link eiffelGenericDecl Special +hi def link eiffelConstraint Special +hi def link eiffelCreate Special - HiLink eiffelPredefined Constant +hi def link eiffelPredefined Constant - HiLink eiffelComment Comment +hi def link eiffelComment Comment - HiLink eiffelError Error - HiLink eiffelBadConstant Error - HiLink eiffelStringError Error - HiLink eiffelParenError Error - HiLink eiffelBracketError Error +hi def link eiffelError Error +hi def link eiffelBadConstant Error +hi def link eiffelStringError Error +hi def link eiffelParenError Error +hi def link eiffelBracketError Error - HiLink eiffelTodo Todo +hi def link eiffelTodo Todo - delcommand HiLink -endif let b:current_syntax = "eiffel" diff --git a/runtime/syntax/elf.vim b/runtime/syntax/elf.vim index 621e063ff8..e695dbc79a 100644 --- a/runtime/syntax/elf.vim +++ b/runtime/syntax/elf.vim @@ -10,11 +10,8 @@ " This is the Applix Inc., Macro and Builder programming language. " It has nothing in common with the binary format called ELF. -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -63,32 +60,22 @@ syn match elfParens "[\[\]()]" syn match elfPunct "[,;]" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_elf_syn_inits") - if version < 508 - let did_elf_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - " The default methods for highlighting. Can be overridden later. - HiLink elfComment Comment - HiLink elfPPCom Include - HiLink elfKeyword Keyword - HiLink elfSpecial Special - HiLink elfEnvironment Special - HiLink elfBraceError Error - HiLink elfConditional Conditional - HiLink elfMacro Function - HiLink elfNumber Number - HiLink elfString String - HiLink elfParens Delimiter - HiLink elfPunct Delimiter - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +" The default methods for highlighting. Can be overridden later. +hi def link elfComment Comment +hi def link elfPPCom Include +hi def link elfKeyword Keyword +hi def link elfSpecial Special +hi def link elfEnvironment Special +hi def link elfBraceError Error +hi def link elfConditional Conditional +hi def link elfMacro Function +hi def link elfNumber Number +hi def link elfString String +hi def link elfParens Delimiter +hi def link elfPunct Delimiter + let b:current_syntax = "elf" diff --git a/runtime/syntax/elmfilt.vim b/runtime/syntax/elmfilt.vim index e7d5df22aa..ec97af038d 100644 --- a/runtime/syntax/elmfilt.vim +++ b/runtime/syntax/elmfilt.vim @@ -1,15 +1,12 @@ " Vim syntax file " Language: Elm Filter rules " Maintainer: Charles E. Campbell <NdrOchipS@PcampbellAfamily.Mbiz> -" Last Change: Oct 23, 2014 -" Version: 6 +" Last Change: Aug 31, 2016 +" Version: 8 " URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_ELMFILT -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -38,32 +35,23 @@ syn region elmfiltString contained start="'" skip="'\(\\\\\)*\\['%]" end="'" con syn match elmfiltSpaceError contained "\s.*$" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_elmfilt_syntax_inits") - if version < 508 - let did_elmfilt_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +if !exists("skip_elmfilt_syntax_inits") + + hi def link elmfiltAction Statement + hi def link elmfiltArg Special + hi def link elmfiltComment Comment + hi def link elmfiltCond Statement + hi def link elmfiltIf Statement + hi def link elmfiltMatch Special + hi def link elmfiltMatchError Error + hi def link elmfiltNumber Number + hi def link elmfiltOper Operator + hi def link elmfiltOperKey Type + hi def link elmfiltParenError Error + hi def link elmfiltSpaceError Error + hi def link elmfiltString String + hi def link elmfiltThenError Error - HiLink elmfiltAction Statement - HiLink elmfiltArg Special - HiLink elmfiltComment Comment - HiLink elmfiltCond Statement - HiLink elmfiltIf Statement - HiLink elmfiltMatch Special - HiLink elmfiltMatchError Error - HiLink elmfiltNumber Number - HiLink elmfiltOper Operator - HiLink elmfiltOperKey Type - HiLink elmfiltParenError Error - HiLink elmfiltSpaceError Error - HiLink elmfiltString String - HiLink elmfiltThenError Error - - delcommand HiLink endif let b:current_syntax = "elmfilt" diff --git a/runtime/syntax/erlang.vim b/runtime/syntax/erlang.vim index 02597e75f3..11b763409b 100644 --- a/runtime/syntax/erlang.vim +++ b/runtime/syntax/erlang.vim @@ -28,11 +28,8 @@ " " syn keyword erlangAttribute myattr1 myattr2 contained -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -42,9 +39,7 @@ set cpo&vim " Case sensitive syn case match -if version >= 600 - setlocal iskeyword+=$,@-@ -endif +setlocal iskeyword+=$,@-@ " Comments syn match erlangComment '%.*$' contains=erlangCommentAnnotation,erlangTodo @@ -147,116 +142,106 @@ let b:erlang_syntax_synced = 1 let s:old_style = (exists("g:erlang_old_style_highlight") && \g:erlang_old_style_highlight == 1) -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_erlang_inits") - if version < 508 - let did_erlang_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - " Comments - HiLink erlangComment Comment - HiLink erlangCommentAnnotation Special - HiLink erlangTodo Todo - HiLink erlangShebang Comment - - " Numbers - HiLink erlangNumberInteger Number - HiLink erlangNumberFloat Float - - " Strings, atoms, characters - HiLink erlangString String - - if s:old_style - HiLink erlangQuotedAtom Type - else - HiLink erlangQuotedAtom String - endif - - HiLink erlangStringModifier Special - HiLink erlangQuotedAtomModifier Special - HiLink erlangModifier Special - - " Operators, separators - HiLink erlangOperator Operator - HiLink erlangRightArrow Operator - if s:old_style - HiLink erlangBracket Normal - HiLink erlangPipe Normal - else - HiLink erlangBracket Delimiter - HiLink erlangPipe Delimiter - endif - - " Atoms, functions, variables, macros - if s:old_style - HiLink erlangAtom Normal - HiLink erlangLocalFuncCall Normal - HiLink erlangLocalFuncRef Normal - HiLink erlangGlobalFuncCall Function - HiLink erlangGlobalFuncRef Function - HiLink erlangVariable Normal - HiLink erlangMacro Normal - HiLink erlangRecord Normal - else - HiLink erlangAtom String - HiLink erlangLocalFuncCall Normal - HiLink erlangLocalFuncRef Normal - HiLink erlangGlobalFuncCall Normal - HiLink erlangGlobalFuncRef Normal - HiLink erlangVariable Identifier - HiLink erlangMacro Macro - HiLink erlangRecord Structure - endif - - " Bitstrings - if !s:old_style - HiLink erlangBitType Type - endif - - " Constants and Directives - if s:old_style - HiLink erlangAttribute Type - HiLink erlangMacroDef Type - HiLink erlangUnknownAttribute Normal - HiLink erlangInclude Type - HiLink erlangRecordDef Type - HiLink erlangDefine Type - HiLink erlangPreCondit Type - HiLink erlangType Type - else - HiLink erlangAttribute Keyword - HiLink erlangMacroDef Macro - HiLink erlangUnknownAttribute Normal - HiLink erlangInclude Include - HiLink erlangRecordDef Keyword - HiLink erlangDefine Define - HiLink erlangPreCondit PreCondit - HiLink erlangType Type - endif - - " Keywords - HiLink erlangKeyword Keyword - - " Build-in-functions (BIFs) - HiLink erlangBIF Function - - if s:old_style - HiLink erlangBoolean Statement - HiLink erlangExtra Statement - HiLink erlangSignal Statement - else - HiLink erlangBoolean Boolean - HiLink erlangExtra Statement - HiLink erlangSignal Statement - endif - - delcommand HiLink +" Only when an item doesn't have highlighting yet + +" Comments +hi def link erlangComment Comment +hi def link erlangCommentAnnotation Special +hi def link erlangTodo Todo +hi def link erlangShebang Comment + +" Numbers +hi def link erlangNumberInteger Number +hi def link erlangNumberFloat Float + +" Strings, atoms, characters +hi def link erlangString String + +if s:old_style +hi def link erlangQuotedAtom Type +else +hi def link erlangQuotedAtom String +endif + +hi def link erlangStringModifier Special +hi def link erlangQuotedAtomModifier Special +hi def link erlangModifier Special + +" Operators, separators +hi def link erlangOperator Operator +hi def link erlangRightArrow Operator +if s:old_style +hi def link erlangBracket Normal +hi def link erlangPipe Normal +else +hi def link erlangBracket Delimiter +hi def link erlangPipe Delimiter +endif + +" Atoms, functions, variables, macros +if s:old_style +hi def link erlangAtom Normal +hi def link erlangLocalFuncCall Normal +hi def link erlangLocalFuncRef Normal +hi def link erlangGlobalFuncCall Function +hi def link erlangGlobalFuncRef Function +hi def link erlangVariable Normal +hi def link erlangMacro Normal +hi def link erlangRecord Normal +else +hi def link erlangAtom String +hi def link erlangLocalFuncCall Normal +hi def link erlangLocalFuncRef Normal +hi def link erlangGlobalFuncCall Normal +hi def link erlangGlobalFuncRef Normal +hi def link erlangVariable Identifier +hi def link erlangMacro Macro +hi def link erlangRecord Structure endif +" Bitstrings +if !s:old_style +hi def link erlangBitType Type +endif + +" Constants and Directives +if s:old_style +hi def link erlangAttribute Type +hi def link erlangMacroDef Type +hi def link erlangUnknownAttribute Normal +hi def link erlangInclude Type +hi def link erlangRecordDef Type +hi def link erlangDefine Type +hi def link erlangPreCondit Type +hi def link erlangType Type +else +hi def link erlangAttribute Keyword +hi def link erlangMacroDef Macro +hi def link erlangUnknownAttribute Normal +hi def link erlangInclude Include +hi def link erlangRecordDef Keyword +hi def link erlangDefine Define +hi def link erlangPreCondit PreCondit +hi def link erlangType Type +endif + +" Keywords +hi def link erlangKeyword Keyword + +" Build-in-functions (BIFs) +hi def link erlangBIF Function + +if s:old_style +hi def link erlangBoolean Statement +hi def link erlangExtra Statement +hi def link erlangSignal Statement +else +hi def link erlangBoolean Boolean +hi def link erlangExtra Statement +hi def link erlangSignal Statement +endif + + let b:current_syntax = "erlang" let &cpo = s:cpo_save diff --git a/runtime/syntax/eruby.vim b/runtime/syntax/eruby.vim index c20b086ba5..4e175bcc25 100644 --- a/runtime/syntax/eruby.vim +++ b/runtime/syntax/eruby.vim @@ -22,7 +22,7 @@ elseif !exists("b:eruby_subtype") && main_syntax == 'eruby' let s:lines = getline(1)."\n".getline(2)."\n".getline(3)."\n".getline(4)."\n".getline(5)."\n".getline("$") let b:eruby_subtype = matchstr(s:lines,'eruby_subtype=\zs\w\+') if b:eruby_subtype == '' - let b:eruby_subtype = matchstr(substitute(expand("%:t"),'\c\%(\.erb\|\.eruby\|\.erubis\)\+$','',''),'\.\zs\w\+$') + let b:eruby_subtype = matchstr(substitute(expand("%:t"),'\c\%(\.erb\|\.eruby\|\.erubis\)\+$','',''),'\.\zs\w\+\%(\ze+\w\+\)\=$') endif if b:eruby_subtype == 'rhtml' let b:eruby_subtype = 'html' diff --git a/runtime/syntax/esmtprc.vim b/runtime/syntax/esmtprc.vim index b22b1a1416..81f074b59c 100644 --- a/runtime/syntax/esmtprc.vim +++ b/runtime/syntax/esmtprc.vim @@ -3,11 +3,8 @@ " Maintainer: Kornel Kielczewski <kornel@gazeta.pl> " Last Change: 16 Feb 2005 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif diff --git a/runtime/syntax/esqlc.vim b/runtime/syntax/esqlc.vim index 6ad167a7e6..792e5d37f3 100644 --- a/runtime/syntax/esqlc.vim +++ b/runtime/syntax/esqlc.vim @@ -3,20 +3,13 @@ " Maintainer: Jonathan A. George <jageorge@tel.gte.com> " Last Change: 2001 May 09 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif " Read the C++ syntax to start with -if version < 600 - source <sfile>:p:h/cpp.vim -else - runtime! syntax/cpp.vim -endif +runtime! syntax/cpp.vim " ESQL-C extentions @@ -52,24 +45,14 @@ syntax keyword esqlcStatement rename revoke rollback savepoint select set syntax keyword esqlcStatement truncate update " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_esqlc_syntax_inits") - if version < 508 - let did_esqlc_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink esqlcOperator Operator - HiLink esqlcStatement Statement - HiLink esqlcKeyword esqlcSpecial - HiLink esqlcSpecial Special - HiLink esqlcPreProc PreProc +hi def link esqlcOperator Operator +hi def link esqlcStatement Statement +hi def link esqlcKeyword esqlcSpecial +hi def link esqlcSpecial Special +hi def link esqlcPreProc PreProc - delcommand HiLink -endif let b:current_syntax = "esqlc" diff --git a/runtime/syntax/esterel.vim b/runtime/syntax/esterel.vim index d853e75208..b0105216d7 100644 --- a/runtime/syntax/esterel.vim +++ b/runtime/syntax/esterel.vim @@ -6,11 +6,8 @@ " Last Change: Tue May 6 13:29:56 CEST 2008 " Version: 0.8 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -65,26 +62,17 @@ syn match esterelNone "\<else\s\+if\>$" syn match esterelNone "\<else\s\+if\>\s" " Class Linking -if version >= 508 || !exists("did_esterel_syntax_inits") - if version < 508 - let did_esterel_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - HiLink esterelStatement Statement - HiLink esterelType Type - HiLink esterelComment Comment - HiLink esterelBoolean Number - HiLink esterelExpressions Number - HiLink esterelIO String - HiLink esterelOperator Type - HiLink esterelSysCall Type - HiLink esterelFunctions Type - HiLink esterelSpecial Special +hi def link esterelStatement Statement +hi def link esterelType Type +hi def link esterelComment Comment +hi def link esterelBoolean Number +hi def link esterelExpressions Number +hi def link esterelIO String +hi def link esterelOperator Type +hi def link esterelSysCall Type +hi def link esterelFunctions Type +hi def link esterelSpecial Special - delcommand HiLink -endif let b:current_syntax = "esterel" diff --git a/runtime/syntax/euphoria3.vim b/runtime/syntax/euphoria3.vim index 1254b96247..ece14027ba 100644 --- a/runtime/syntax/euphoria3.vim +++ b/runtime/syntax/euphoria3.vim @@ -5,10 +5,8 @@ " Remark: Euphoria has two syntax files, euphoria3.vim and euphoria4.vim; " For details see :help ft-euphoria-syntax -" Quit if a (custom) syntax file was already loaded (compatible with Vim 5.8): -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif diff --git a/runtime/syntax/euphoria4.vim b/runtime/syntax/euphoria4.vim index 53f5cea917..5e668a7d67 100644 --- a/runtime/syntax/euphoria4.vim +++ b/runtime/syntax/euphoria4.vim @@ -5,10 +5,8 @@ " Remark: Euphoria has two syntax files, euphoria3.vim and euphoria4.vim; " For details see :help ft-euphoria-syntax -" Quit if a (custom) syntax file was already loaded (compatible with Vim 5.8): -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif diff --git a/runtime/syntax/eviews.vim b/runtime/syntax/eviews.vim index aa65fda3ff..03cfb25e60 100644 --- a/runtime/syntax/eviews.vim +++ b/runtime/syntax/eviews.vim @@ -4,19 +4,12 @@ " Last Change: 2006 Apr 30 " Filenames: *.prg " URL: http://uosis.mif.vu.lt/~zemlys/vim-syntax/eviews.vim -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif -if version >= 600 - setlocal iskeyword=@,48-57,_,. -else - set iskeyword=@,48-57,_,. -endif +setlocal iskeyword=@,48-57,_,. syn case match @@ -69,35 +62,25 @@ syn match eCurlyError /[)\]]/ contained syn match eParenError /[\]}]/ contained " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_r_syn_inits") - if version < 508 - let did_r_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - HiLink eComment Comment - HiLink eConstant Identifier - HiLink eStringId Identifier - HiLink eCommand Type - HiLink eString String - HiLink eNumber Number - HiLink eBoolean Boolean - HiLink eFloat Float - HiLink eConditional Conditional - HiLink eProgLang Statement - HiLink eOVP Statement - HiLink eStdCmd Statement - HiLink eIdentifier Normal - HiLink eDelimiter Delimiter - HiLink eError Error - HiLink eBraceError Error - HiLink eCurlyError Error - HiLink eParenError Error - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet +hi def link eComment Comment +hi def link eConstant Identifier +hi def link eStringId Identifier +hi def link eCommand Type +hi def link eString String +hi def link eNumber Number +hi def link eBoolean Boolean +hi def link eFloat Float +hi def link eConditional Conditional +hi def link eProgLang Statement +hi def link eOVP Statement +hi def link eStdCmd Statement +hi def link eIdentifier Normal +hi def link eDelimiter Delimiter +hi def link eError Error +hi def link eBraceError Error +hi def link eCurlyError Error +hi def link eParenError Error let b:current_syntax="eviews" diff --git a/runtime/syntax/exim.vim b/runtime/syntax/exim.vim index ff8066f8af..4edc0d7948 100644 --- a/runtime/syntax/exim.vim +++ b/runtime/syntax/exim.vim @@ -6,12 +6,9 @@ " URL: http://trific.ath.cx/Ftp/vim/syntax/exim.vim " Setup -if version >= 600 - if exists("b:current_syntax") - finish - endif -else - syntax clear +" quit when a syntax file was already loaded +if exists("b:current_syntax") + finish endif syn case match @@ -91,27 +88,18 @@ syn keyword eximKeyword server_prompts server_condition client_send syn keyword eximKeyword server_secret client_name client_secret " Define the default highlighting -if version >= 508 || !exists("did_exim_syntax_inits") - if version < 508 - let did_exim_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - HiLink eximComment Comment - HiLink eximFixme Todo - HiLink eximEnd Keyword - HiLink eximNumber Number - HiLink eximDriverName Constant - HiLink eximConstant Constant - HiLink eximTime Constant - HiLink eximKeyword Type - HiLink eximSpecialChar Special - HiLink eximMacroName Preproc - HiLink eximTransport Identifier +hi def link eximComment Comment +hi def link eximFixme Todo +hi def link eximEnd Keyword +hi def link eximNumber Number +hi def link eximDriverName Constant +hi def link eximConstant Constant +hi def link eximTime Constant +hi def link eximKeyword Type +hi def link eximSpecialChar Special +hi def link eximMacroName Preproc +hi def link eximTransport Identifier - delcommand HiLink -endif let b:current_syntax = "exim" diff --git a/runtime/syntax/expect.vim b/runtime/syntax/expect.vim index 6ff7d4142c..75cbd3eddf 100644 --- a/runtime/syntax/expect.vim +++ b/runtime/syntax/expect.vim @@ -4,11 +4,8 @@ " Last Change: 2012 Jun 01 " (Dominique Pelle added @Spell) -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -81,35 +78,25 @@ syn match expectComment "#.*$" contains=@Spell,expectTodo syn match expectSharpBang "\%^#!.*" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_expect_syntax_inits") - if version < 508 - let did_expect_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink expectSharpBang PreProc - HiLink expectVariables Special - HiLink expectCommand Function - HiLink expectStatement Statement - HiLink expectConditional Conditional - HiLink expectRepeat Repeat - HiLink expectExpectOpts Keyword - HiLink expectOutVar Special - HiLink expectSpecial Special - HiLink expectNumber Number - - HiLink expectString String - - HiLink expectComment Comment - HiLink expectTodo Todo - "HiLink expectIdentifier Identifier - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link expectSharpBang PreProc +hi def link expectVariables Special +hi def link expectCommand Function +hi def link expectStatement Statement +hi def link expectConditional Conditional +hi def link expectRepeat Repeat +hi def link expectExpectOpts Keyword +hi def link expectOutVar Special +hi def link expectSpecial Special +hi def link expectNumber Number + +hi def link expectString String + +hi def link expectComment Comment +hi def link expectTodo Todo +"hi def link expectIdentifier Identifier + let b:current_syntax = "expect" diff --git a/runtime/syntax/exports.vim b/runtime/syntax/exports.vim index f695dc8d21..55efbb1e50 100644 --- a/runtime/syntax/exports.vim +++ b/runtime/syntax/exports.vim @@ -1,16 +1,13 @@ " Vim syntax file " Language: exports " Maintainer: Charles E. Campbell <NdrOchipS@PcampbellAfamily.Mbiz> -" Last Change: Oct 23, 2014 -" Version: 5 +" Last Change: Aug 31, 2016 +" Version: 7 " Notes: This file includes both SysV and BSD 'isms " URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_EXPORTS -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -39,31 +36,22 @@ syn match exportsSeparator "[,:]" syn match exportsComment "^\s*#.*$" contains=@Spell " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_exports_syntax_inits") - if version < 508 - let did_exports_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +if !exists("skip_exports_syntax_inits") - HiLink exportsKeyOptSet exportsKeySettings - HiLink exportsOptSet exportsSettings + hi def link exportsKeyOptSet exportsKeySettings + hi def link exportsOptSet exportsSettings - HiLink exportsComment Comment - HiLink exportsKeyOptions Type - HiLink exportsKeySettings Keyword - HiLink exportsOptions Constant - HiLink exportsSeparator Constant - HiLink exportsSettings Constant + hi def link exportsComment Comment + hi def link exportsKeyOptions Type + hi def link exportsKeySettings Keyword + hi def link exportsOptions Constant + hi def link exportsSeparator Constant + hi def link exportsSettings Constant - HiLink exportsOptError Error - HiLink exportsOptSetError Error - HiLink exportsSetError Error + hi def link exportsOptError Error + hi def link exportsOptSetError Error + hi def link exportsSetError Error - delcommand HiLink endif let b:current_syntax = "exports" diff --git a/runtime/syntax/falcon.vim b/runtime/syntax/falcon.vim index 1f6fefa9ff..e022c7a54a 100644 --- a/runtime/syntax/falcon.vim +++ b/runtime/syntax/falcon.vim @@ -163,34 +163,32 @@ syn sync minlines=10 maxlines=100 " Define the default highlighting if !exists("did_falcon_syn_inits") - command -nargs=+ HiLink hi def link <args> - - HiLink falconKeyword Keyword - HiLink falconCommentString String - HiLink falconTodo Todo - HiLink falconConditional Keyword - HiLink falconRepeat Repeat - HiLink falconcommentSkip Comment - HiLink falconComment Comment - HiLink falconCommentL Comment - HiLink falconConst Constant - HiLink falconConstants Constant - HiLink falconOperator Operator - HiLink falconSymbol Normal - HiLink falconSpaceError Error - HiLink falconHexadecimal Number - HiLink falconOctal Number - HiLink falconIntLiteral Number - HiLink falconFloatLiteral Float - HiLink falconStringEscape Special - HiLink falconStringDelimiter Delimiter - HiLink falconString String - HiLink falconBool Constant - HiLink falconSharpBang PreProc - HiLink falconInclude Include - HiLink falconSymbol Constant - HiLink falconSymbolOther Delimiter - delcommand HiLink + + hi def link falconKeyword Keyword + hi def link falconCommentString String + hi def link falconTodo Todo + hi def link falconConditional Keyword + hi def link falconRepeat Repeat + hi def link falconcommentSkip Comment + hi def link falconComment Comment + hi def link falconCommentL Comment + hi def link falconConst Constant + hi def link falconConstants Constant + hi def link falconOperator Operator + hi def link falconSymbol Normal + hi def link falconSpaceError Error + hi def link falconHexadecimal Number + hi def link falconOctal Number + hi def link falconIntLiteral Number + hi def link falconFloatLiteral Float + hi def link falconStringEscape Special + hi def link falconStringDelimiter Delimiter + hi def link falconString String + hi def link falconBool Constant + hi def link falconSharpBang PreProc + hi def link falconInclude Include + hi def link falconSymbol Constant + hi def link falconSymbolOther Delimiter endif let b:current_syntax = "falcon" diff --git a/runtime/syntax/fasm.vim b/runtime/syntax/fasm.vim index 696e05b4ca..172ba7c9b6 100644 --- a/runtime/syntax/fasm.vim +++ b/runtime/syntax/fasm.vim @@ -6,9 +6,8 @@ " FASM Home: http://flatassembler.net/ " FASM Version: 1.56 -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif diff --git a/runtime/syntax/fdcc.vim b/runtime/syntax/fdcc.vim index 38717ebfb8..f7b296b9c6 100644 --- a/runtime/syntax/fdcc.vim +++ b/runtime/syntax/fdcc.vim @@ -4,11 +4,8 @@ " Last Change: 2004 May 16 " Remarks: FDCC (Formal Definitions of Cultural Conventions) see ISO TR 14652 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -58,56 +55,46 @@ syn region fdccBlank matchgroup=fdccLCName start=/^LC_NAME$/ end=/^END LC_NAME$/ syn region fdccBlank matchgroup=fdccLCAddress start=/^LC_ADDRESS$/ end=/^END LC_ADDRESS$/ contains=fdccKeywordAddress,fdccString,fdccComment,fdccNumber -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_fdcc_syn_inits") - if version < 508 - let did_fdcc_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink fdccBlank Blank - - HiLink fdccTodo Todo - HiLink fdccComment Comment - HiLink fdccVariable Type - - HiLink fdccLCIdentification Statement - HiLink fdccLCCtype Statement - HiLink fdccLCCollate Statement - HiLink fdccLCMonetary Statement - HiLink fdccLCNumeric Statement - HiLink fdccLCTime Statement - HiLink fdccLCMessages Statement - HiLink fdccLCPaper Statement - HiLink fdccLCTelephone Statement - HiLink fdccLCMeasurement Statement - HiLink fdccLCName Statement - HiLink fdccLCAddress Statement - - HiLink fdccUnicodeInValid Error - HiLink fdccUnicodeValid String - HiLink fdccString String - HiLink fdccNumber Blank - - HiLink fdccKeywordIdentification fdccKeyword - HiLink fdccKeywordCtype fdccKeyword - HiLink fdccKeywordCollate fdccKeyword - HiLink fdccKeywordMonetary fdccKeyword - HiLink fdccKeywordNumeric fdccKeyword - HiLink fdccKeywordTime fdccKeyword - HiLink fdccKeywordMessages fdccKeyword - HiLink fdccKeywordPaper fdccKeyword - HiLink fdccKeywordTelephone fdccKeyword - HiLink fdccKeywordMeasurement fdccKeyword - HiLink fdccKeywordName fdccKeyword - HiLink fdccKeywordAddress fdccKeyword - HiLink fdccKeyword Identifier - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link fdccBlank Blank + +hi def link fdccTodo Todo +hi def link fdccComment Comment +hi def link fdccVariable Type + +hi def link fdccLCIdentification Statement +hi def link fdccLCCtype Statement +hi def link fdccLCCollate Statement +hi def link fdccLCMonetary Statement +hi def link fdccLCNumeric Statement +hi def link fdccLCTime Statement +hi def link fdccLCMessages Statement +hi def link fdccLCPaper Statement +hi def link fdccLCTelephone Statement +hi def link fdccLCMeasurement Statement +hi def link fdccLCName Statement +hi def link fdccLCAddress Statement + +hi def link fdccUnicodeInValid Error +hi def link fdccUnicodeValid String +hi def link fdccString String +hi def link fdccNumber Blank + +hi def link fdccKeywordIdentification fdccKeyword +hi def link fdccKeywordCtype fdccKeyword +hi def link fdccKeywordCollate fdccKeyword +hi def link fdccKeywordMonetary fdccKeyword +hi def link fdccKeywordNumeric fdccKeyword +hi def link fdccKeywordTime fdccKeyword +hi def link fdccKeywordMessages fdccKeyword +hi def link fdccKeywordPaper fdccKeyword +hi def link fdccKeywordTelephone fdccKeyword +hi def link fdccKeywordMeasurement fdccKeyword +hi def link fdccKeywordName fdccKeyword +hi def link fdccKeywordAddress fdccKeyword +hi def link fdccKeyword Identifier + let b:current_syntax = "fdcc" diff --git a/runtime/syntax/fgl.vim b/runtime/syntax/fgl.vim index 1b2fe19a88..1b75d137b6 100644 --- a/runtime/syntax/fgl.vim +++ b/runtime/syntax/fgl.vim @@ -7,11 +7,8 @@ " - Conditionally allow case insensitive keywords (Julian Bridle) " -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -119,28 +116,18 @@ syn match fglSpecial "--@" syn sync ccomment fglComment " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_fgl_syntax_inits") - if version < 508 - let did_fgl_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink fglComment Comment - "HiLink fglKeyword fglSpecial - HiLink fglKeyword fglStatement - HiLink fglNumber Number - HiLink fglOperator fglStatement - HiLink fglSpecial Special - HiLink fglStatement Statement - HiLink fglString String - HiLink fglType Type +hi def link fglComment Comment +"hi def link fglKeyword fglSpecial +hi def link fglKeyword fglStatement +hi def link fglNumber Number +hi def link fglOperator fglStatement +hi def link fglSpecial Special +hi def link fglStatement Statement +hi def link fglString String +hi def link fglType Type - delcommand HiLink -endif let b:current_syntax = "fgl" diff --git a/runtime/syntax/flexwiki.vim b/runtime/syntax/flexwiki.vim index 34f893d927..6b15ab2d90 100644 --- a/runtime/syntax/flexwiki.vim +++ b/runtime/syntax/flexwiki.vim @@ -14,10 +14,8 @@ " regexes, which use a different syntax than Vim (fewer \s). " The primary test case is FlexWiki\FormattingRules.wiki -" Quit if syntax file is already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif diff --git a/runtime/syntax/focexec.vim b/runtime/syntax/focexec.vim index 8be1b65cc4..a75aed47cb 100644 --- a/runtime/syntax/focexec.vim +++ b/runtime/syntax/focexec.vim @@ -11,11 +11,8 @@ " I think some of these things should get different hilights - " should MODIFY commands look different than TABLE? -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -69,32 +66,22 @@ syn match focexecNumber "\<\d\+\.\d*\>" syn match focexecComment "-\*.*" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_focexec_syntax_inits") - if version < 508 - let did_focexec_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink focexecString1 String - HiLink focexecString2 String - HiLink focexecNumber Number - HiLink focexecComment Comment - HiLink focexecTable Keyword - HiLink focexecModify Keyword - HiLink focexecNormal Keyword - HiLink focexecSet Keyword - HiLink focexecDash Keyword - HiLink focexecFileDef Keyword - HiLink focexecJoin Keyword - HiLink focexecAmperVar Identifier - HiLink focexecFuse Function +hi def link focexecString1 String +hi def link focexecString2 String +hi def link focexecNumber Number +hi def link focexecComment Comment +hi def link focexecTable Keyword +hi def link focexecModify Keyword +hi def link focexecNormal Keyword +hi def link focexecSet Keyword +hi def link focexecDash Keyword +hi def link focexecFileDef Keyword +hi def link focexecJoin Keyword +hi def link focexecAmperVar Identifier +hi def link focexecFuse Function - delcommand HiLink -endif let b:current_syntax = "focexec" diff --git a/runtime/syntax/form.vim b/runtime/syntax/form.vim index 19a47ed6b9..b8cb87c905 100644 --- a/runtime/syntax/form.vim +++ b/runtime/syntax/form.vim @@ -11,11 +11,8 @@ " This syntax file is still in development. Please send suggestions " to the maintainer. -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -109,49 +106,39 @@ syn match formDirective "^\=\.[a-zA-z][a-zA-Z0-9]*\>" syn sync ccomment formComment minlines=10 " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_form_syn_inits") - if version < 508 - let did_form_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink formConditional Conditional - HiLink formNumber Number - HiLink formStatement Statement - HiLink formComment Comment - HiLink formPreProc PreProc - HiLink formDirective PreProc - HiLink formType Type - HiLink formString String - HiLink formNestedString String - HiLink formReserved Error - HiLink formTodo Todo - HiLink formSpecial SpecialChar - - if !exists("form_enhanced_color") - HiLink formHeaderStatement Statement - else - " enhanced color mode - HiLink formHeaderStatement HeaderStatement - " dark and a light background for local types - if &background == "dark" - hi HeaderStatement term=underline ctermfg=LightGreen guifg=LightGreen gui=bold - else - hi HeaderStatement term=underline ctermfg=DarkGreen guifg=SeaGreen gui=bold - endif - " change slightly the default for dark gvim - if has("gui_running") && &background == "dark" - hi Conditional guifg=LightBlue gui=bold - hi Statement guifg=LightYellow - endif - endif - - delcommand HiLink +" Only when an item doesn't have highlighting yet + +hi def link formConditional Conditional +hi def link formNumber Number +hi def link formStatement Statement +hi def link formComment Comment +hi def link formPreProc PreProc +hi def link formDirective PreProc +hi def link formType Type +hi def link formString String +hi def link formNestedString String +hi def link formReserved Error +hi def link formTodo Todo +hi def link formSpecial SpecialChar + +if !exists("form_enhanced_color") +hi def link formHeaderStatement Statement +else +" enhanced color mode +hi def link formHeaderStatement HeaderStatement +" dark and a light background for local types +if &background == "dark" +hi HeaderStatement term=underline ctermfg=LightGreen guifg=LightGreen gui=bold +else +hi HeaderStatement term=underline ctermfg=DarkGreen guifg=SeaGreen gui=bold endif +" change slightly the default for dark gvim +if has("gui_running") && &background == "dark" +hi Conditional guifg=LightBlue gui=bold +hi Statement guifg=LightYellow +endif +endif + let b:current_syntax = "form" diff --git a/runtime/syntax/forth.vim b/runtime/syntax/forth.vim index 99e9400b95..35fafd4349 100644 --- a/runtime/syntax/forth.vim +++ b/runtime/syntax/forth.vim @@ -80,11 +80,8 @@ " -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -104,11 +101,7 @@ syn match forthTodo contained 'Copyright\(\s([Cc])\)\=\(\s[0-9]\{2,4}\)\=' " Characters allowed in keywords " I don't know if 128-255 are allowed in ANS-FORTH -if version >= 600 - setlocal iskeyword=!,@,33-35,%,$,38-64,A-Z,91-96,a-z,123-126,128-255 -else - set iskeyword=!,@,33-35,%,$,38-64,A-Z,91-96,a-z,123-126,128-255 -endif +setlocal iskeyword=!,@,33-35,%,$,38-64,A-Z,91-96,a-z,123-126,128-255 " when wanted, highlight trailing white space if exists("forth_space_errors") @@ -289,56 +282,46 @@ syn match forthLocals '{ }' " otherwise, at least two spaces between syn region forthDeprecated start='locals|' end='|' " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_forth_syn_inits") - if version < 508 - let did_forth_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet + +" The default methods for highlighting. Can be overridden later. +hi def link forthTodo Todo +hi def link forthOperators Operator +hi def link forthMath Number +hi def link forthInteger Number +hi def link forthFloat Float +hi def link forthStack Special +hi def link forthRstack Special +hi def link forthFStack Special +hi def link forthSP Special +hi def link forthMemory Function +hi def link forthAdrArith Function +hi def link forthMemBlks Function +hi def link forthCond Conditional +hi def link forthLoop Repeat +hi def link forthColonDef Define +hi def link forthEndOfColonDef Define +hi def link forthDefine Define +hi def link forthDebug Debug +hi def link forthAssembler Include +hi def link forthCharOps Character +hi def link forthConversion String +hi def link forthForth Statement +hi def link forthVocs Statement +hi def link forthString String +hi def link forthComment Comment +hi def link forthClassDef Define +hi def link forthEndOfClassDef Define +hi def link forthObjectDef Define +hi def link forthEndOfObjectDef Define +hi def link forthInclude Include +hi def link forthLocals Type " nothing else uses type and locals must stand out +hi def link forthDeprecated Error " if you must, change to Type +hi def link forthFileMode Function +hi def link forthFileWords Statement +hi def link forthBlocks Statement +hi def link forthSpaceError Error - " The default methods for highlighting. Can be overridden later. - HiLink forthTodo Todo - HiLink forthOperators Operator - HiLink forthMath Number - HiLink forthInteger Number - HiLink forthFloat Float - HiLink forthStack Special - HiLink forthRstack Special - HiLink forthFStack Special - HiLink forthSP Special - HiLink forthMemory Function - HiLink forthAdrArith Function - HiLink forthMemBlks Function - HiLink forthCond Conditional - HiLink forthLoop Repeat - HiLink forthColonDef Define - HiLink forthEndOfColonDef Define - HiLink forthDefine Define - HiLink forthDebug Debug - HiLink forthAssembler Include - HiLink forthCharOps Character - HiLink forthConversion String - HiLink forthForth Statement - HiLink forthVocs Statement - HiLink forthString String - HiLink forthComment Comment - HiLink forthClassDef Define - HiLink forthEndOfClassDef Define - HiLink forthObjectDef Define - HiLink forthEndOfObjectDef Define - HiLink forthInclude Include - HiLink forthLocals Type " nothing else uses type and locals must stand out - HiLink forthDeprecated Error " if you must, change to Type - HiLink forthFileMode Function - HiLink forthFileWords Statement - HiLink forthBlocks Statement - HiLink forthSpaceError Error - - delcommand HiLink -endif let b:current_syntax = "forth" diff --git a/runtime/syntax/fortran.vim b/runtime/syntax/fortran.vim index b470e56f60..4c26e78f16 100644 --- a/runtime/syntax/fortran.vim +++ b/runtime/syntax/fortran.vim @@ -1,16 +1,17 @@ " Vim syntax file " Language: Fortran 2008 (and older: Fortran 2003, 95, 90, and 77) -" Version: 0.97 -" Last Change: 2016 Feb. 26 +" Version: 100 +" Last Change: 2016 Oct. 29 " Maintainer: Ajit J. Thakkar <ajit@unb.ca>; <http://www2.unb.ca/~ajit/> " Usage: For instructions, do :help fortran-syntax from Vim " Credits: -" Version 0.1 (April 2000) was based on the fortran 77 syntax file by Mario Eusebio and -" Preben Guldberg. Since then, useful suggestions and contributions have been made, -" in chronological order, by: +" Version 0.1 (April 2000) for Fortran 95 was based on the Fortran 77 syntax file by +" Mario Eusebio and Preben Guldberg. Since then, useful suggestions and contributions +" have been made, in chronological order, by: " Andrej Panjkov, Bram Moolenaar, Thomas Olsen, Michael Sternberg, Christian Reile, " Walter Dieudonn้, Alexander Wagner, Roman Bertle, Charles Rendleman, -" Andrew Griffiths, Joe Krahn, Hendrik Merx, Matt Thompson, and Jan Hermann. +" Andrew Griffiths, Joe Krahn, Hendrik Merx, Matt Thompson, Jan Hermann, +" Stefano Zaghi, Vishnu V. Krishnan and Judica๋l Grasset if exists("b:current_syntax") finish @@ -108,6 +109,7 @@ syn match fortranUnitHeader "\<subroutine\>" syn keyword fortranCall call syn match fortranUnitHeader "\<function\>" syn match fortranUnitHeader "\<program\>" +syn match fortranUnitHeader "\<block\>" syn keyword fortranKeyword return stop syn keyword fortranConditional else then syn match fortranConditional "\<if\>" @@ -208,6 +210,7 @@ syn match fortranStorageClass "\<kind\s*="me=s+4 syn match fortranStorageClass "\<len\s*="me=s+3 syn match fortranUnitHeader "\<module\>" +syn match fortranUnitHeader "\<submodule\>" syn keyword fortranUnitHeader use only contains syn keyword fortranUnitHeader result operator assignment syn match fortranUnitHeader "\<interface\>" @@ -231,8 +234,10 @@ syn match fortranIntrinsic "\<kind\>\s*[(,]"me=s+4 syn match fortranUnitHeader "\<end\s*function" syn match fortranUnitHeader "\<end\s*interface" syn match fortranUnitHeader "\<end\s*module" +syn match fortranUnitHeader "\<end\s*submodule" syn match fortranUnitHeader "\<end\s*program" syn match fortranUnitHeader "\<end\s*subroutine" +syn match fortranUnitHeader "\<end\s*block" syn match fortranRepeat "\<end\s*do" syn match fortranConditional "\<end\s*where" syn match fortranConditional "\<select\s*case" @@ -267,6 +272,7 @@ syn match fortranRepeat "\<end\s*forall" syn keyword fortranIntrinsic null cpu_time syn match fortranType "\<elemental\>" syn match fortranType "\<pure\>" +syn match fortranType "\<impure\>" if exists("fortran_more_precise") syn match fortranConstructName "\(\<end\s*forall\s\+\)\@<=\a\w*\>" endif @@ -286,8 +292,9 @@ if b:fortran_dialect == "f08" syn keyword fortranReadWrite flush wait syn keyword fortranIO decimal round iomsg - syn keyword fortranType asynchronous nopass non_overridable pass protected volatile abstract extends import + syn keyword fortranType asynchronous nopass non_overridable pass protected volatile extends import syn keyword fortranType non_intrinsic value bind deferred generic final enumerator + syn match fortranType "\<abstract\>" syn match fortranType "\<class\>" syn match fortranType "\<associate\>" syn match fortranType "\<end\s*associate" @@ -305,6 +312,7 @@ if b:fortran_dialect == "f08" syn keyword fortranIntrinsic bge bgt ble blt dshiftl dshiftr findloc iall iany iparity image_index lcobound ucobound maskl maskr num_images parity popcnt poppar shifta shiftl shiftr this_image syn keyword fortranIO newunit syn keyword fortranType contiguous + syn keyword fortranRepeat concurrent " CUDA fortran syn match fortranTypeCUDA "\<attributes\>" @@ -360,6 +368,7 @@ else endif syn match fortranComment excludenl "!.*$" contains=@fortranCommentGroup,@spell +syn match fortranOpenMP excludenl "^\s*!\$\(OMP\)\=&\=\s.*$" "cpp is often used with Fortran syn match cPreProc "^\s*#\s*\(define\|ifdef\)\>.*" @@ -383,20 +392,24 @@ if exists("fortran_fold") if (b:fortran_fixed_source == 1) syn region fortranProgram transparent fold keepend start="^\s*program\s\+\z(\a\w*\)" skip="^\([!c*]\|\s*#\).*$" excludenl end="\<end\s*\(program\(\s\+\z1\>\)\=\|$\)" contains=ALLBUT,fortranModule + syn region fortranModule transparent fold keepend start="^\s*submodule\s\+(\a\w*\s*\(:\a\w*\s*\)*)\s*\z\(\a\w*\)" skip="^\([!c*]\|\s*#\).*$" excludenl end="\<end\s*\(submodule\(\s\+\z1\>\)\=\|$\)" contains=ALLBUT,fortranProgram,fortranModule syn region fortranModule transparent fold keepend start="^\s*module\s\+\(procedure\)\@!\z(\a\w*\)" skip="^\([!c*]\|\s*#\).*$" excludenl end="\<end\s*\(module\(\s\+\z1\>\)\=\|$\)" contains=ALLBUT,fortranProgram - syn region fortranFunction transparent fold keepend extend start="^\s*\(elemental \|pure \|recursive \)\=\s*\(\(\(real \|integer \|logical \|complex \|double \s*precision \)\s*\((\(\s*kind\s*=\)\=\s*\w\+\s*)\)\=\)\|type\s\+(\s*\w\+\s*) \|character \((\(\s*len\s*=\)\=\s*\d\+\s*)\|(\(\s*kind\s*=\)\=\s*\w\+\s*)\)\=\)\=\s*function\s\+\z(\a\w*\)" skip="^\([!c*]\|\s*#\).*$" excludenl end="\<end\s*\($\|function\(\s\+\z1\>\)\=\)" contains=ALLBUT,fortranProgram,fortranModule - syn region fortranSubroutine transparent fold keepend extend start="^\s*\(elemental \|pure \|recursive \)\=\s*subroutine\s\+\z(\a\w*\)" skip="^\([!c*]\|\s*#\).*$" excludenl end="\<end\s*\($\|subroutine\(\s\+\z1\>\)\=\)" contains=ALLBUT,fortranProgram,fortranModule + syn region fortranFunction transparent fold keepend extend start="^\s*\(elemental \|pure \|impure \|module \|recursive \)\=\s*\(\(\(real \|integer \|logical \|complex \|double \s*precision \)\s*\((\(\s*kind\s*=\)\=\s*\w\+\s*)\)\=\)\|type\s\+(\s*\w\+\s*) \|character \((\(\s*len\s*=\)\=\s*\d\+\s*)\|(\(\s*kind\s*=\)\=\s*\w\+\s*)\)\=\)\=\s*function\s\+\z(\a\w*\)" skip="^\([!c*]\|\s*#\).*$" excludenl end="\<end\s*\($\|function\(\s\+\z1\>\)\=\)" contains=ALLBUT,fortranProgram,fortranModule + syn region fortranSubroutine transparent fold keepend extend start="^\s*\(elemental \|pure \|impure \|module \|recursive \)\=\s*subroutine\s\+\z(\a\w*\)" skip="^\([!c*]\|\s*#\).*$" excludenl end="\<end\s*\($\|subroutine\(\s\+\z1\>\)\=\)" contains=ALLBUT,fortranProgram,fortranModule syn region fortranBlockData transparent fold keepend start="\<block\s*data\(\s\+\z(\a\w*\)\)\=" skip="^\([!c*]\|\s*#\).*$" excludenl end="\<end\s*\($\|block\s*data\(\s\+\z1\>\)\=\)" contains=ALLBUT,fortranProgram,fortranModule,fortranSubroutine,fortranFunction,fortran77Loop,fortranCase,fortran90Loop,fortranIfBlock - syn region fortranInterface transparent fold keepend extend start="^\s*interface\>" skip="^\([!c*]\|\s*#\).*$" excludenl end="\<end\s*interface\>" contains=ALLBUT,fortranProgram,fortranModule,fortran77Loop,fortranCase,fortran90Loop,fortranIfBlock - syn region fortranTypeDef transparent fold keepend extend start="^\s*type\s*\(,\s*\(public\|private\)\)\=\s*::" skip="^\([!c*]\|\s*#\).*$" excludenl end="\<end\s*type\>" contains=ALLBUT,fortranProgram,fortranModule,fortran77Loop,fortranCase,fortran90Loop,fortranIfBlock + syn region fortranAssociate transparent fold keepend start="^\s*\<associate\s\+" skip="^\([!c*]\|\s*#\).*$" excludenl end="\<end\s*associate" contains=ALLBUT,fortranProgram,fortranModule,fortranSubroutine,fortranFunction + syn region fortranInterface transparent fold keepend extend start="^\s*\(abstract \)\=\s*interface\>" skip="^\([!c*]\|\s*#\).*$" excludenl end="\<end\s*interface\>" contains=ALLBUT,fortranProgram,fortranModule,fortran77Loop,fortranCase,fortran90Loop,fortranIfBlock + syn region fortranTypeDef transparent fold keepend extend start="^\s*type\s*\(,\s*\(public\|private\|abstract\)\)\=\s*::" skip="^\([!c*]\|\s*#\).*$" excludenl end="\<end\s*type\>" contains=ALLBUT,fortranProgram,fortranModule,fortran77Loop,fortranCase,fortran90Loop,fortranIfBlock,fortranInterface else syn region fortranProgram transparent fold keepend start="^\s*program\s\+\z(\a\w*\)" skip="^\s*[!#].*$" excludenl end="\<end\s*\(program\(\s\+\z1\>\)\=\|$\)" contains=ALLBUT,fortranModule + syn region fortranModule transparent fold keepend start="^\s*submodule\s\+(\a\w*\s*\(:\a\w*\s*\)*)\s*\z\(\a\w*\)" skip="^\s*[!#].*$" excludenl end="\<end\s*\(submodule\(\s\+\z1\>\)\=\|$\)" contains=ALLBUT,fortranProgram,fortranModule syn region fortranModule transparent fold keepend start="^\s*module\s\+\(procedure\)\@!\z(\a\w*\)" skip="^\s*[!#].*$" excludenl end="\<end\s*\(module\(\s\+\z1\>\)\=\|$\)" contains=ALLBUT,fortranProgram - syn region fortranFunction transparent fold keepend extend start="^\s*\(elemental \|pure \|recursive \)\=\s*\(\(\(real \|integer \|logical \|complex \|double \s*precision \)\s*\((\(\s*kind\s*=\)\=\s*\w\+\s*)\)\=\)\|type\s\+(\s*\w\+\s*) \|character \((\(\s*len\s*=\)\=\s*\d\+\s*)\|(\(\s*kind\s*=\)\=\s*\w\+\s*)\)\=\)\=\s*function\s\+\z(\a\w*\)" skip="^\s*[!#].*$" excludenl end="\<end\s*\($\|function\(\s\+\z1\>\)\=\)" contains=ALLBUT,fortranProgram,fortranModule - syn region fortranSubroutine transparent fold keepend extend start="^\s*\(elemental \|pure \|recursive \)\=\s*subroutine\s\+\z(\a\w*\)" skip="^\s*[!#].*$" excludenl end="\<end\s*\($\|subroutine\(\s\+\z1\>\)\=\)" contains=ALLBUT,fortranProgram,fortranModule + syn region fortranFunction transparent fold keepend extend start="^\s*\(elemental \|pure \|impure \|module \|recursive \)\=\s*\(\(\(real \|integer \|logical \|complex \|double \s*precision \)\s*\((\(\s*kind\s*=\)\=\s*\w\+\s*)\)\=\)\|type\s\+(\s*\w\+\s*) \|character \((\(\s*len\s*=\)\=\s*\d\+\s*)\|(\(\s*kind\s*=\)\=\s*\w\+\s*)\)\=\)\=\s*function\s\+\z(\a\w*\)" skip="^\s*[!#].*$" excludenl end="\<end\s*\($\|function\(\s\+\z1\>\)\=\)" contains=ALLBUT,fortranProgram,fortranModule + syn region fortranSubroutine transparent fold keepend extend start="^\s*\(elemental \|pure \|impure \|module \|recursive \)\=\s*subroutine\s\+\z(\a\w*\)" skip="^\s*[!#].*$" excludenl end="\<end\s*\($\|subroutine\(\s\+\z1\>\)\=\)" contains=ALLBUT,fortranProgram,fortranModule syn region fortranBlockData transparent fold keepend start="\<block\s*data\(\s\+\z(\a\w*\)\)\=" skip="^\s*[!#].*$" excludenl end="\<end\s*\($\|block\s*data\(\s\+\z1\>\)\=\)" contains=ALLBUT,fortranProgram,fortranModule,fortranSubroutine,fortranFunction,fortran77Loop,fortranCase,fortran90Loop,fortranIfBlock - syn region fortranInterface transparent fold keepend extend start="^\s*interface\>" skip="^\s*[!#].*$" excludenl end="\<end\s*interface\>" contains=ALLBUT,fortranProgram,fortranModule,fortran77Loop,fortranCase,fortran90Loop,fortranIfBlock - syn region fortranTypeDef transparent fold keepend extend start="^\s*type\s*\(,\s*\(public\|private\)\)\=\s*::" skip="^\s*[!#].*$" excludenl end="\<end\s*type\>" contains=ALLBUT,fortranProgram,fortranModule,fortran77Loop,fortranCase,fortran90Loop,fortranIfBlock + syn region fortranAssociate transparent fold keepend start="^\s*\<associate\s\+" skip="^\s*[!#].*$" excludenl end="\<end\s*associate" contains=ALLBUT,fortranProgram,fortranModule,fortranSubroutine,fortranFunction + syn region fortranInterface transparent fold keepend extend start="^\s*\(abstract \)\=\s*interface\>" skip="^\s*[!#].*$" excludenl end="\<end\s*interface\>" contains=ALLBUT,fortranProgram,fortranModule,fortran77Loop,fortranCase,fortran90Loop,fortranIfBlock + syn region fortranTypeDef transparent fold keepend extend start="^\s*type\s*\(,\s*\(public\|private\|abstract\)\)\=\s*::" skip="^\s*[!#].*$" excludenl end="\<end\s*type\>" contains=ALLBUT,fortranProgram,fortranModule,fortran77Loop,fortranCase,fortran90Loop,fortranIfBlock,fortranInterface endif if exists("fortran_fold_conditionals") @@ -404,12 +417,12 @@ if exists("fortran_fold") syn region fortran77Loop transparent fold keepend start="\<do\s\+\z(\d\+\)" end="^\s*\z1\>" contains=ALLBUT,fortranUnitHeader,fortranStructure,fortranStorageClass,fortranType,fortranProgram,fortranModule,fortranSubroutine,fortranFunction,fortranBlockData syn region fortran90Loop transparent fold keepend extend start="\(\<end\s\+\)\@<!\<do\(\s\+\a\|\s*$\)" skip="^\([!c*]\|\s*#\).*$" excludenl end="\<end\s*do\>" contains=ALLBUT,fortranUnitHeader,fortranStructure,fortranStorageClass,fortranType,fortranProgram,fortranModule,fortranSubroutine,fortranFunction,fortranBlockData syn region fortranIfBlock transparent fold keepend extend start="\(\<e\(nd\|lse\)\s\+\)\@<!\<if\s*(.\+)\s*then\>" skip="^\([!c*]\|\s*#\).*$" end="\<end\s*if\>" contains=ALLBUT,fortranUnitHeader,fortranStructure,fortranStorageClass,fortranType,fortranProgram,fortranModule,fortranSubroutine,fortranFunction,fortranBlockData - syn region fortranCase transparent fold keepend extend start="\<select\s*case\>" skip="^\([!c*]\|\s*#\).*$" end="\<end\s*select\>" contains=ALLBUT,fortranUnitHeader,fortranStructure,fortranStorageClass,fortranType,fortranProgram,fortranModule,fortranSubroutine,fortranFunction,fortranBlockData + syn region fortranCase transparent fold keepend extend start="\<select\s*\(case\|type\)\>" skip="^\([!c*]\|\s*#\).*$" end="\<end\s*select\>" contains=ALLBUT,fortranUnitHeader,fortranStructure,fortranStorageClass,fortranType,fortranProgram,fortranModule,fortranSubroutine,fortranFunction,fortranBlockData else syn region fortran77Loop transparent fold keepend start="\<do\s\+\z(\d\+\)" end="^\s*\z1\>" contains=ALLBUT,fortranUnitHeader,fortranStructure,fortranStorageClass,fortranType,fortranProgram,fortranModule,fortranSubroutine,fortranFunction,fortranBlockData syn region fortran90Loop transparent fold keepend extend start="\(\<end\s\+\)\@<!\<do\(\s\+\a\|\s*$\)" skip="^\s*[!#].*$" excludenl end="\<end\s*do\>" contains=ALLBUT,fortranUnitHeader,fortranStructure,fortranStorageClass,fortranType,fortranProgram,fortranModule,fortranSubroutine,fortranFunction,fortranBlockData syn region fortranIfBlock transparent fold keepend extend start="\(\<e\(nd\|lse\)\s\+\)\@<!\<if\s*(\(.\|&\s*\n\)\+)\(\s\|&\s*\n\)*then\>" skip="^\s*[!#].*$" end="\<end\s*if\>" contains=ALLBUT,fortranUnitHeader,fortranStructure,fortranStorageClass,fortranType,fortranProgram,fortranModule,fortranSubroutine,fortranFunction,fortranBlockData - syn region fortranCase transparent fold keepend extend start="\<select\s*case\>" skip="^\s*[!#].*$" end="\<end\s*select\>" contains=ALLBUT,fortranUnitHeader,fortranStructure,fortranStorageClass,fortranType,fortranProgram,fortranModule,fortranSubroutine,fortranFunction,fortranBlockData + syn region fortranCase transparent fold keepend extend start="\<select\s*\(case\|type\)\>" skip="^\s*[!#].*$" end="\<end\s*select\>" contains=ALLBUT,fortranUnitHeader,fortranStructure,fortranStorageClass,fortranType,fortranProgram,fortranModule,fortranSubroutine,fortranFunction,fortranBlockData endif endif @@ -507,6 +520,7 @@ hi def link cIncluded fortranString hi def link cInclude Include hi def link cPreProc PreProc hi def link cPreCondit PreCondit +hi def link fortranOpenMP PreProc hi def link fortranParenError Error hi def link fortranComment Comment hi def link fortranSerialNumber Todo diff --git a/runtime/syntax/foxpro.vim b/runtime/syntax/foxpro.vim index ca5d7e2f9d..795859eac9 100644 --- a/runtime/syntax/foxpro.vim +++ b/runtime/syntax/foxpro.vim @@ -13,9 +13,8 @@ " corrected highlighting of comments at end of line (&&) " " -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -691,37 +690,27 @@ syn match foxproParenErr ")" syn sync minlines=1 maxlines=3 " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_foxpro_syn_inits") - if version < 508 - let did_foxpro_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink foxproSpecial Special - HiLink foxproAtSymbol Special - HiLink foxproAtCmd Statement - HiLink foxproPreProc PreProc - HiLink foxproFunc Identifier - HiLink foxproCmd Statement - HiLink foxproEnBlk Type - HiLink foxproSysVar String - HiLink foxproString String - HiLink foxproConst Constant - HiLink foxproNumber Number - HiLink foxproFloat Float - HiLink foxproComment Comment - HiLink foxproParenErr Error - HiLink foxproCBConst PreProc - HiLink foxproCBField Special - HiLink foxproCBVar Identifier - HiLink foxproCBWin Special - HiLink foxproCBObject Identifier +hi def link foxproSpecial Special +hi def link foxproAtSymbol Special +hi def link foxproAtCmd Statement +hi def link foxproPreProc PreProc +hi def link foxproFunc Identifier +hi def link foxproCmd Statement +hi def link foxproEnBlk Type +hi def link foxproSysVar String +hi def link foxproString String +hi def link foxproConst Constant +hi def link foxproNumber Number +hi def link foxproFloat Float +hi def link foxproComment Comment +hi def link foxproParenErr Error +hi def link foxproCBConst PreProc +hi def link foxproCBField Special +hi def link foxproCBVar Identifier +hi def link foxproCBWin Special +hi def link foxproCBObject Identifier - delcommand HiLink -endif let b:current_syntax = "foxpro" diff --git a/runtime/syntax/fstab.vim b/runtime/syntax/fstab.vim index 3006d21fea..39c1a00b39 100644 --- a/runtime/syntax/fstab.vim +++ b/runtime/syntax/fstab.vim @@ -19,9 +19,8 @@ " let fstab_unknown_device_errors = 0 " do not highlight unknown devices as errors -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -229,66 +228,57 @@ syn match fsFreqPass /\s\+.\{-}$/ contains=@fsFreqPassCluster,@fsGeneralCluster " Whole line comments syn match fsCommentLine /^#.*$/ contains=@Spell -if version >= 508 || !exists("did_config_syntax_inits") - if version < 508 - let did_config_syntax_inits = 1 - command! -nargs=+ HiLink hi link <args> - else - command! -nargs=+ HiLink hi def link <args> - endif - - HiLink fsOperator Operator - HiLink fsComment Comment - HiLink fsCommentLine Comment - - HiLink fsTypeKeyword Type - HiLink fsDeviceKeyword Identifier - HiLink fsDeviceLabel String - HiLink fsDeviceUUID String - HiLink fsDeviceSshfs String - HiLink fsFreqPassNumber Number - - if exists('fstab_unknown_fs_errors') && fstab_unknown_fs_errors == 1 - HiLink fsTypeUnknown Error - endif - - if !exists('fstab_unknown_device_errors') || fstab_unknown_device_errors == 1 - HiLink fsDeviceError Error - endif - - HiLink fsMountPointError Error - HiLink fsMountPointKeyword Keyword - HiLink fsFreqPassError Error - - HiLink fsOptionsGeneral Type - HiLink fsOptionsKeywords Keyword - HiLink fsOptionsNumber Number - HiLink fsOptionsNumberOctal Number - HiLink fsOptionsString String - HiLink fsOptionsSize Number - HiLink fsOptionsExt2Check String - HiLink fsOptionsExt2Errors String - HiLink fsOptionsExt3Journal String - HiLink fsOptionsExt3Data String - HiLink fsOptionsExt4Journal String - HiLink fsOptionsExt4Data String - HiLink fsOptionsExt4Barrier Number - HiLink fsOptionsFatCheck String - HiLink fsOptionsConv String - HiLink fsOptionsFatType Number - HiLink fsOptionsYesNo String - HiLink fsOptionsHpfsCase String - HiLink fsOptionsIsoMap String - HiLink fsOptionsReiserHash String - HiLink fsOptionsSshYesNoAsk String - HiLink fsOptionsUfsType String - HiLink fsOptionsUfsError String - - HiLink fsOptionsVfatShortname String - - delcommand HiLink + +hi def link fsOperator Operator +hi def link fsComment Comment +hi def link fsCommentLine Comment + +hi def link fsTypeKeyword Type +hi def link fsDeviceKeyword Identifier +hi def link fsDeviceLabel String +hi def link fsDeviceUUID String +hi def link fsDeviceSshfs String +hi def link fsFreqPassNumber Number + +if exists('fstab_unknown_fs_errors') && fstab_unknown_fs_errors == 1 +hi def link fsTypeUnknown Error endif +if !exists('fstab_unknown_device_errors') || fstab_unknown_device_errors == 1 +hi def link fsDeviceError Error +endif + +hi def link fsMountPointError Error +hi def link fsMountPointKeyword Keyword +hi def link fsFreqPassError Error + +hi def link fsOptionsGeneral Type +hi def link fsOptionsKeywords Keyword +hi def link fsOptionsNumber Number +hi def link fsOptionsNumberOctal Number +hi def link fsOptionsString String +hi def link fsOptionsSize Number +hi def link fsOptionsExt2Check String +hi def link fsOptionsExt2Errors String +hi def link fsOptionsExt3Journal String +hi def link fsOptionsExt3Data String +hi def link fsOptionsExt4Journal String +hi def link fsOptionsExt4Data String +hi def link fsOptionsExt4Barrier Number +hi def link fsOptionsFatCheck String +hi def link fsOptionsConv String +hi def link fsOptionsFatType Number +hi def link fsOptionsYesNo String +hi def link fsOptionsHpfsCase String +hi def link fsOptionsIsoMap String +hi def link fsOptionsReiserHash String +hi def link fsOptionsSshYesNoAsk String +hi def link fsOptionsUfsType String +hi def link fsOptionsUfsError String + +hi def link fsOptionsVfatShortname String + + let b:current_syntax = "fstab" let &cpo = s:cpo_save diff --git a/runtime/syntax/fvwm2m4.vim b/runtime/syntax/fvwm2m4.vim index 243da18fa7..e296273e31 100644 --- a/runtime/syntax/fvwm2m4.vim +++ b/runtime/syntax/fvwm2m4.vim @@ -5,12 +5,9 @@ " URI: http://physics.muni.cz/~yeti/download/syntax/fvwmm4.vim " Setup -if version >= 600 - if exists('b:current_syntax') - finish - endif -else - syntax clear +" quit when a syntax file was already loaded +if exists('b:current_syntax') + finish endif " Let included files know they are included @@ -19,19 +16,11 @@ if !exists('main_syntax') endif " Include M4 syntax -if version >= 600 - runtime! syntax/m4.vim -else - so <sfile>:p:h/m4.vim -endif +runtime! syntax/m4.vim unlet b:current_syntax " Include Fvwm2 syntax (Fvwm1 doesn't have M4 preprocessor) -if version >= 600 - runtime! syntax/fvwm.vim -else - so <sfile>:p:h/fvwm.vim -endif +runtime! syntax/fvwm.vim unlet b:current_syntax " That's all! diff --git a/runtime/syntax/gdb.vim b/runtime/syntax/gdb.vim index 64e89cce7f..25a21d184e 100644 --- a/runtime/syntax/gdb.vim +++ b/runtime/syntax/gdb.vim @@ -4,11 +4,8 @@ " URL: http://www.fleiner.com/vim/syntax/gdb.vim " Last Change: 2012 Oct 05 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -87,27 +84,17 @@ endif exec "syn sync ccomment gdbComment minlines=" . gdb_minlines " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_gdb_syn_inits") - if version < 508 - let did_gdb_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - HiLink gdbFuncDef Function - HiLink gdbComment Comment - HiLink gdbStatement Statement - HiLink gdbString String - HiLink gdbCharacter Character - HiLink gdbVariable Identifier - HiLink gdbSet Constant - HiLink gdbInfo Type - HiLink gdbDocument Special - HiLink gdbNumber Number - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet +hi def link gdbFuncDef Function +hi def link gdbComment Comment +hi def link gdbStatement Statement +hi def link gdbString String +hi def link gdbCharacter Character +hi def link gdbVariable Identifier +hi def link gdbSet Constant +hi def link gdbInfo Type +hi def link gdbDocument Special +hi def link gdbNumber Number let b:current_syntax = "gdb" diff --git a/runtime/syntax/gdmo.vim b/runtime/syntax/gdmo.vim index 86c6d5c76c..009f402ffa 100644 --- a/runtime/syntax/gdmo.vim +++ b/runtime/syntax/gdmo.vim @@ -5,11 +5,8 @@ " URL: http://classicalprogrammer.wikidot.com/local--files/vim-syntax-file-for-gdmo/gdmo.vim " Last change: 8th June, 2011 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -64,32 +61,22 @@ syn match gdmoBraces "[{}]" syn sync ccomment gdmoComment " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_gdmo_syntax_inits") - if version < 508 - let did_gdmo_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink gdmoCategory Structure - HiLink gdmoRelationship Macro - HiLink gdmoDefinition Statement - HiLink gdmoReference Type - HiLink gdmoExtension Operator - HiLink gdmoBraces Function - HiLink gdmoSpecial Special - HiLink gdmoString String - HiLink gdmoCharacter Character - HiLink gdmoSpecialCharacter gdmoSpecial - HiLink gdmoComment Comment - HiLink gdmoLineComment gdmoComment - HiLink gdmoType Type +hi def link gdmoCategory Structure +hi def link gdmoRelationship Macro +hi def link gdmoDefinition Statement +hi def link gdmoReference Type +hi def link gdmoExtension Operator +hi def link gdmoBraces Function +hi def link gdmoSpecial Special +hi def link gdmoString String +hi def link gdmoCharacter Character +hi def link gdmoSpecialCharacter gdmoSpecial +hi def link gdmoComment Comment +hi def link gdmoLineComment gdmoComment +hi def link gdmoType Type - delcommand HiLink -endif let b:current_syntax = "gdmo" diff --git a/runtime/syntax/gedcom.vim b/runtime/syntax/gedcom.vim index 98851cc942..cd09e0fa22 100644 --- a/runtime/syntax/gedcom.vim +++ b/runtime/syntax/gedcom.vim @@ -3,11 +3,8 @@ " Maintainer: Paul Johnson (pjcj@transeda.com) " Version 1.059 - 23rd December 1999 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -41,26 +38,16 @@ syntax match gedcom_date "\d\{1,2}\s\+\(jan\|feb\|mar\|apr\|may\|jun\|jul\|aug\| syntax match gedcom_date ".*" contained " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_gedcom_syntax_inits") - if version < 508 - let did_gedcom_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink gedcom_record Statement - HiLink gedcom_id Comment - HiLink gedcom_ii PreProc - HiLink gedcom_in Type - HiLink gedcom_name PreProc - HiLink gedcom_cname Type - HiLink gedcom_surname Identifier - HiLink gedcom_date Constant +hi def link gedcom_record Statement +hi def link gedcom_id Comment +hi def link gedcom_ii PreProc +hi def link gedcom_in Type +hi def link gedcom_name PreProc +hi def link gedcom_cname Type +hi def link gedcom_surname Identifier +hi def link gedcom_date Constant - delcommand HiLink -endif let b:current_syntax = "gedcom" diff --git a/runtime/syntax/gitcommit.vim b/runtime/syntax/gitcommit.vim index b0315a9465..5e0642fbcc 100644 --- a/runtime/syntax/gitcommit.vim +++ b/runtime/syntax/gitcommit.vim @@ -2,7 +2,7 @@ " Language: git commit file " Maintainer: Tim Pope <vimNOSPAM@tpope.org> " Filenames: *.git/COMMIT_EDITMSG -" Last Change: 2013 May 30 +" Last Change: 2016 Aug 29 if exists("b:current_syntax") finish @@ -39,9 +39,10 @@ syn region gitcommitDiscarded start=/^# Change\%(s not staged for commit\|d but syn region gitcommitSelected start=/^# Changes to be committed:/ end=/^#$\|^#\@!/ contains=gitcommitHeader,gitcommitHead,gitcommitSelectedType fold syn region gitcommitUnmerged start=/^# Unmerged paths:/ end=/^#$\|^#\@!/ contains=gitcommitHeader,gitcommitHead,gitcommitUnmergedType fold -syn match gitcommitDiscardedType "\t\@<=[a-z][a-z ]*[a-z]: "he=e-2 contained containedin=gitcommitComment nextgroup=gitcommitDiscardedFile skipwhite -syn match gitcommitSelectedType "\t\@<=[a-z][a-z ]*[a-z]: "he=e-2 contained containedin=gitcommitComment nextgroup=gitcommitSelectedFile skipwhite -syn match gitcommitUnmergedType "\t\@<=[a-z][a-z ]*[a-z]: "he=e-2 contained containedin=gitcommitComment nextgroup=gitcommitUnmergedFile skipwhite + +syn match gitcommitDiscardedType "\t\@<=[[:lower:]][^:]*[[:lower:]]: "he=e-2 contained containedin=gitcommitComment nextgroup=gitcommitDiscardedFile skipwhite +syn match gitcommitSelectedType "\t\@<=[[:lower:]][^:]*[[:lower:]]: "he=e-2 contained containedin=gitcommitComment nextgroup=gitcommitSelectedFile skipwhite +syn match gitcommitUnmergedType "\t\@<=[[:lower:]][^:]*[[:lower:]]: "he=e-2 contained containedin=gitcommitComment nextgroup=gitcommitUnmergedFile skipwhite syn match gitcommitDiscardedFile ".\{-\}\%($\| -> \)\@=" contained nextgroup=gitcommitDiscardedArrow syn match gitcommitSelectedFile ".\{-\}\%($\| -> \)\@=" contained nextgroup=gitcommitSelectedArrow syn match gitcommitUnmergedFile ".\{-\}\%($\| -> \)\@=" contained nextgroup=gitcommitSelectedArrow diff --git a/runtime/syntax/gitrebase.vim b/runtime/syntax/gitrebase.vim index a7460280d3..a944c14dd7 100644 --- a/runtime/syntax/gitrebase.vim +++ b/runtime/syntax/gitrebase.vim @@ -2,7 +2,7 @@ " Language: git rebase --interactive " Maintainer: Tim Pope <vimNOSPAM@tpope.org> " Filenames: git-rebase-todo -" Last Change: 2013 May 30 +" Last Change: 2016 Aug 29 if exists("b:current_syntax") finish @@ -18,6 +18,7 @@ syn match gitrebaseEdit "\v^e%(dit)=>" nextgroup=gitrebaseCommit skipwhite syn match gitrebaseSquash "\v^s%(quash)=>" nextgroup=gitrebaseCommit skipwhite syn match gitrebaseFixup "\v^f%(ixup)=>" nextgroup=gitrebaseCommit skipwhite syn match gitrebaseExec "\v^%(x|exec)>" nextgroup=gitrebaseCommand skipwhite +syn match gitrebaseDrop "\v^d%(rop)=>" nextgroup=gitrebaseCommit skipwhite syn match gitrebaseSummary ".*" contains=gitrebaseHash contained syn match gitrebaseCommand ".*" contained syn match gitrebaseComment "^#.*" contains=gitrebaseHash @@ -31,6 +32,7 @@ hi def link gitrebaseEdit PreProc hi def link gitrebaseSquash Type hi def link gitrebaseFixup Special hi def link gitrebaseExec Function +hi def link gitrebaseDrop Comment hi def link gitrebaseSummary String hi def link gitrebaseComment Comment hi def link gitrebaseSquashError Error diff --git a/runtime/syntax/gitsendemail.vim b/runtime/syntax/gitsendemail.vim index 8b938116fa..8fdf6839c8 100644 --- a/runtime/syntax/gitsendemail.vim +++ b/runtime/syntax/gitsendemail.vim @@ -1,14 +1,18 @@ " Vim syntax file " Language: git send-email message " Maintainer: Tim Pope -" Filenames: *.msg.[0-9]* (first line is "From ... # This line is ignored.") -" Last Change: 2010 May 21 +" Filenames: .gitsendemail.* +" Last Change: 2016 Aug 29 if exists("b:current_syntax") finish endif runtime! syntax/mail.vim +unlet! b:current_syntax +syn include @gitsendemailDiff syntax/diff.vim +syn region gitsendemailDiff start=/\%(^diff --\%(git\|cc\|combined\) \)\@=/ end=/^-- %/ fold contains=@gitsendemailDiff + syn case match syn match gitsendemailComment "\%^From.*#.*" diff --git a/runtime/syntax/gkrellmrc.vim b/runtime/syntax/gkrellmrc.vim index 6ce1238416..f005ca2dc8 100644 --- a/runtime/syntax/gkrellmrc.vim +++ b/runtime/syntax/gkrellmrc.vim @@ -6,19 +6,12 @@ " URL: http://trific.ath.cx/Ftp/vim/syntax/gkrellmrc.vim " Setup -if version >= 600 - if exists("b:current_syntax") - finish - endif -else - syntax clear +" quit when a syntax file was already loaded +if exists("b:current_syntax") + finish endif -if version >= 600 - setlocal iskeyword=_,-,a-z,A-Z,48-57 -else - set iskeyword=_,-,a-z,A-Z,48-57 -endif +setlocal iskeyword=_,-,a-z,A-Z,48-57 syn case match @@ -55,37 +48,28 @@ syn keyword gkrellmrcStyleCmd StyleMeter StyleChart StylePanel syn keyword gkrellmrcStyleItem textcolor alt_textcolor font alt_font transparency border label_position margin margins left_margin right_margin top_margin bottom_margin krell_depth krell_yoff krell_x_hot krell_expand krell_left_margin krell_right_margin " Define the default highlighting -if version >= 508 || !exists("did_gtkrc_syntax_inits") - if version < 508 - let did_gtkrc_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - HiLink gkrellmrcComment Comment - HiLink gkrellmrcFixme Todo +hi def link gkrellmrcComment Comment +hi def link gkrellmrcFixme Todo - HiLink gkrellmrcString gkrellmrcConstant - HiLink gkrellmrcNumber gkrellmrcConstant - HiLink gkrellmrcRGBColor gkrellmrcConstant - HiLink gkrellmrcExpandMode gkrellmrcConstant - HiLink gkrellmrcConstant Constant +hi def link gkrellmrcString gkrellmrcConstant +hi def link gkrellmrcNumber gkrellmrcConstant +hi def link gkrellmrcRGBColor gkrellmrcConstant +hi def link gkrellmrcExpandMode gkrellmrcConstant +hi def link gkrellmrcConstant Constant - HiLink gkrellmrcMeterName gkrellmrcClass - HiLink gkrellmrcChartName gkrellmrcClass - HiLink gkrellmrcSpecialClassName gkrellmrcClass - HiLink gkrellmrcClass Type +hi def link gkrellmrcMeterName gkrellmrcClass +hi def link gkrellmrcChartName gkrellmrcClass +hi def link gkrellmrcSpecialClassName gkrellmrcClass +hi def link gkrellmrcClass Type - HiLink gkrellmrcGlobal gkrellmrcItem - HiLink gkrellmrcBuiltinExt gkrellmrcItem - HiLink gkrellmrcStyleItem gkrellmrcItem - HiLink gkrellmrcItem Function +hi def link gkrellmrcGlobal gkrellmrcItem +hi def link gkrellmrcBuiltinExt gkrellmrcItem +hi def link gkrellmrcStyleItem gkrellmrcItem +hi def link gkrellmrcItem Function - HiLink gkrellmrcSetCmd Special - HiLink gkrellmrcStyleCmd Statement +hi def link gkrellmrcSetCmd Special +hi def link gkrellmrcStyleCmd Statement - delcommand HiLink -endif let b:current_syntax = "gkrellmrc" diff --git a/runtime/syntax/gnash.vim b/runtime/syntax/gnash.vim index f9e2b519a5..cce522dd86 100644 --- a/runtime/syntax/gnash.vim +++ b/runtime/syntax/gnash.vim @@ -15,11 +15,8 @@ " Vim is Charityware, see ":help Uganda" " -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") || &compatible +" quit when a syntax file was already loaded +if exists("b:current_syntax") || &compatible finish endif diff --git a/runtime/syntax/gnuplot.vim b/runtime/syntax/gnuplot.vim index d85932d401..7777cc9e46 100644 --- a/runtime/syntax/gnuplot.vim +++ b/runtime/syntax/gnuplot.vim @@ -20,9 +20,8 @@ " For vim version 5.x: Clear all syntax items " For vim version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -501,54 +500,44 @@ syn keyword gnuplotStatement shell splot spstats stats system test undefine syn keyword gnuplotStatement unset update " ---- Define the default highlighting ---- " -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_gnuplot_syntax_inits") - if version < 508 - let did_gnuplot_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - " ---- Comments ---- " - HiLink gnuplotComment Comment - - " ---- Constants ---- " - HiLink gnuplotString String - HiLink gnuplotNumber Number - HiLink gnuplotFloat Float - - " ---- Identifiers ---- " - HiLink gnuplotIdentifier Identifier - - " ---- Statements ---- " - HiLink gnuplotConditional Conditional - HiLink gnuplotRepeat Repeat - HiLink gnuplotKeyword Keyword - HiLink gnuplotOperator Operator - - " ---- PreProcs ---- " - HiLink gnuplotMacro Macro - - " ---- Types ---- " - HiLink gnuplotStatement Type - HiLink gnuplotFunc Identifier - - " ---- Specials ---- " - HiLink gnuplotSpecial Special - HiLink gnuplotUnit Special - HiLink gnuplotExternal Special - - " ---- Errors ---- " - HiLink gnuplotError Error - HiLink gnuplotOctalError Error - - " ---- Todos ---- " - HiLink gnuplotTodo Todo - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +" ---- Comments ---- " +hi def link gnuplotComment Comment + +" ---- Constants ---- " +hi def link gnuplotString String +hi def link gnuplotNumber Number +hi def link gnuplotFloat Float + +" ---- Identifiers ---- " +hi def link gnuplotIdentifier Identifier + +" ---- Statements ---- " +hi def link gnuplotConditional Conditional +hi def link gnuplotRepeat Repeat +hi def link gnuplotKeyword Keyword +hi def link gnuplotOperator Operator + +" ---- PreProcs ---- " +hi def link gnuplotMacro Macro + +" ---- Types ---- " +hi def link gnuplotStatement Type +hi def link gnuplotFunc Identifier + +" ---- Specials ---- " +hi def link gnuplotSpecial Special +hi def link gnuplotUnit Special +hi def link gnuplotExternal Special + +" ---- Errors ---- " +hi def link gnuplotError Error +hi def link gnuplotOctalError Error + +" ---- Todos ---- " +hi def link gnuplotTodo Todo + let b:current_syntax = "gnuplot" diff --git a/runtime/syntax/godoc.vim b/runtime/syntax/godoc.vim index 3a07903a77..0603f51c83 100644 --- a/runtime/syntax/godoc.vim +++ b/runtime/syntax/godoc.vim @@ -10,11 +10,9 @@ endif syn case match syn match godocTitle "^\([A-Z][A-Z ]*\)$" -command -nargs=+ HiLink hi def link <args> -HiLink godocTitle Title +hi def link godocTitle Title -delcommand HiLink let b:current_syntax = 'godoc' diff --git a/runtime/syntax/gp.vim b/runtime/syntax/gp.vim index f46a465215..aecf7df48b 100644 --- a/runtime/syntax/gp.vim +++ b/runtime/syntax/gp.vim @@ -4,9 +4,8 @@ " Last change: 2012 Jan 08 " URL: http://pari.math.u-bordeaux.fr -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -59,33 +58,24 @@ syntax region gpParen transparent start='(' end=')' contains=ALLBUT,gpParenErro syntax match gpParenError ")" syntax match gpInParen contained "[{}]" -if version >= 508 || !exists("did_gp_syn_inits") - if version < 508 - let did_gp_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - HiLink gpConditional Conditional - HiLink gpRepeat Repeat - HiLink gpError Error - HiLink gpParenError gpError - HiLink gpInParen gpError - HiLink gpStatement Statement - HiLink gpString String - HiLink gpComment Comment - HiLink gpInterface Type - HiLink gpInput Type - HiLink gpInterfaceKey Statement - HiLink gpFunction Function - HiLink gpScope Type - " contained ones - HiLink gpSpecial Special - HiLink gpTodo Todo - HiLink gpArgs Type - delcommand HiLink -endif +hi def link gpConditional Conditional +hi def link gpRepeat Repeat +hi def link gpError Error +hi def link gpParenError gpError +hi def link gpInParen gpError +hi def link gpStatement Statement +hi def link gpString String +hi def link gpComment Comment +hi def link gpInterface Type +hi def link gpInput Type +hi def link gpInterfaceKey Statement +hi def link gpFunction Function +hi def link gpScope Type +" contained ones +hi def link gpSpecial Special +hi def link gpTodo Todo +hi def link gpArgs Type let b:current_syntax = "gp" let &cpo = s:cpo_save diff --git a/runtime/syntax/grads.vim b/runtime/syntax/grads.vim index 0b88549d40..50be14bb22 100644 --- a/runtime/syntax/grads.vim +++ b/runtime/syntax/grads.vim @@ -7,11 +7,8 @@ " This syntax file defines highlighting for only very few features of " the GrADS scripting language. -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -53,34 +50,24 @@ syn match gradsComment "\*.*" " syn match gradsTypos "!=" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't hgs highlighting+yet -if version >= 508 || !exists("did_gs_syn_inits") - if version < 508 - let did_gs_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't hgs highlighting+yet - HiLink gradsStatement Statement +hi def link gradsStatement Statement - HiLink gradsString String - HiLink gradsNumber Number +hi def link gradsString String +hi def link gradsNumber Number - HiLink gradsFixVariables Special - HiLink gradsVariables Identifier - HiLink gradsglobalVariables Special - HiLink gradsConst Special +hi def link gradsFixVariables Special +hi def link gradsVariables Identifier +hi def link gradsglobalVariables Special +hi def link gradsConst Special - HiLink gradsClassMethods Function +hi def link gradsClassMethods Function - HiLink gradsOperator Operator - HiLink gradsComment Comment +hi def link gradsOperator Operator +hi def link gradsComment Comment - HiLink gradsTypos Error +hi def link gradsTypos Error - delcommand HiLink -endif let b:current_syntax = "grads" diff --git a/runtime/syntax/gretl.vim b/runtime/syntax/gretl.vim index 37299b894a..671142a9ea 100644 --- a/runtime/syntax/gretl.vim +++ b/runtime/syntax/gretl.vim @@ -4,20 +4,13 @@ " Last Change: 2006 Apr 30 " Filenames: *.inp *.gretl " URL: http://uosis.mif.vu.lt/~zemlys/vim-syntax/gretl.vim -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif -if version >= 600 - setlocal iskeyword=@,48-57,_,. -else - set iskeyword=@,48-57,_,. -endif +setlocal iskeyword=@,48-57,_,. syn case match @@ -68,34 +61,24 @@ syn match gBCend /\*)/ syn region gBlockComment matchgroup=gCommentStart start="(\*" end="\*)" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_r_syn_inits") - if version < 508 - let did_r_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - HiLink gComment Comment - HiLink gCommentStart Comment - HiLink gBlockComment Comment - HiLink gString String - HiLink gNumber Number - HiLink gBoolean Boolean - HiLink gFloat Float - HiLink gCommands Repeat - HiLink gGenrFunc Type - HiLink gDelimiter Delimiter - HiLink gError Error - HiLink gBraceError Error - HiLink gCurlyError Error - HiLink gParenError Error - HiLink gIdentifier Normal - HiLink gVariable Identifier - HiLink gArrow Repeat - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet +hi def link gComment Comment +hi def link gCommentStart Comment +hi def link gBlockComment Comment +hi def link gString String +hi def link gNumber Number +hi def link gBoolean Boolean +hi def link gFloat Float +hi def link gCommands Repeat +hi def link gGenrFunc Type +hi def link gDelimiter Delimiter +hi def link gError Error +hi def link gBraceError Error +hi def link gCurlyError Error +hi def link gParenError Error +hi def link gIdentifier Normal +hi def link gVariable Identifier +hi def link gArrow Repeat let b:current_syntax="gretl" diff --git a/runtime/syntax/groovy.vim b/runtime/syntax/groovy.vim index dc39677724..2245b79d04 100644 --- a/runtime/syntax/groovy.vim +++ b/runtime/syntax/groovy.vim @@ -44,11 +44,9 @@ " Let me know if you like it or send me patches, so that I can improve it " when I have time -" Quit when a syntax file was already loaded +" quit when a syntax file was already loaded if !exists("main_syntax") - if version < 600 - syntax clear - elseif exists("b:current_syntax") + if exists("b:current_syntax") finish endif " we define it here so that included files can test for it @@ -58,13 +56,6 @@ endif let s:cpo_save = &cpo set cpo&vim -" don't use standard HiLink, it will not work with included syntax files -if version < 508 - command! -nargs=+ GroovyHiLink hi link <args> -else - command! -nargs=+ GroovyHiLink hi def link <args> -endif - " ########################## " Java stuff taken from java.vim " some characters that cannot be in a groovy program (outside a string) @@ -144,9 +135,9 @@ if exists("groovy_highlight_groovy_lang_ids") || exists("groovy_highlight_groovy syn keyword groovyJavaLangObject clone equals finalize getClass hashCode syn keyword groovyJavaLangObject notify notifyAll toString wait - GroovyHiLink groovyLangClass groovyConstant - GroovyHiLink groovyJavaLangClass groovyExternal - GroovyHiLink groovyJavaLangObject groovyConstant + hi def link groovyLangClass groovyConstant + hi def link groovyJavaLangClass groovyExternal + hi def link groovyJavaLangObject groovyConstant syn cluster groovyTop add=groovyJavaLangObject,groovyJavaLangClass,groovyLangClass syn cluster groovyClasses add=groovyJavaLangClass,groovyLangClass endif @@ -220,9 +211,9 @@ syn region groovyComment start="/\*" end="\*/" contains=@groovyCommen syn match groovyCommentStar contained "^\s*\*[^/]"me=e-1 syn match groovyCommentStar contained "^\s*\*$" syn match groovyLineComment "//.*" contains=@groovyCommentSpecial2,groovyTodo,@Spell -GroovyHiLink groovyCommentString groovyString -GroovyHiLink groovyComment2String groovyString -GroovyHiLink groovyCommentCharacter groovyCharacter +hi def link groovyCommentString groovyString +hi def link groovyComment2String groovyString +hi def link groovyCommentCharacter groovyCharacter syn cluster groovyTop add=groovyComment,groovyLineComment @@ -263,12 +254,12 @@ endif " syn region groovyELExpr start=+${+ end=+}+ keepend contained syn match groovyELExpr /\${.\{-}}/ contained syn match groovyELExpr /\$[a-zA-Z_][a-zA-Z0-9_.]*/ contained -GroovyHiLink groovyELExpr Identifier +hi def link groovyELExpr Identifier " TODO: better matching. I am waiting to understand how it really works in groovy " syn region groovyClosureParamsBraces start=+|+ end=+|+ contains=groovyClosureParams " syn match groovyClosureParams "[ a-zA-Z0-9_*]\+" contained -" GroovyHiLink groovyClosureParams Identifier +" hi def link groovyClosureParams Identifier " next line disabled, it can cause a crash for a long line "syn match groovyStringError +"\([^"\\]\|\\.\)*$+ @@ -329,23 +320,21 @@ if exists("groovy_highlight_debug") syn cluster groovyTop add=groovyDebug - if version >= 508 || !exists("did_c_syn_inits") - GroovyHiLink groovyDebug Debug - GroovyHiLink groovyDebugString DebugString - GroovyHiLink groovyDebugStringError groovyError - GroovyHiLink groovyDebugType DebugType - GroovyHiLink groovyDebugBoolean DebugBoolean - GroovyHiLink groovyDebugNumber Debug - GroovyHiLink groovyDebugSpecial DebugSpecial - GroovyHiLink groovyDebugSpecialCharacter DebugSpecial - GroovyHiLink groovyDebugCharacter DebugString - GroovyHiLink groovyDebugParen Debug - - GroovyHiLink DebugString String - GroovyHiLink DebugSpecial Special - GroovyHiLink DebugBoolean Boolean - GroovyHiLink DebugType Type - endif + hi def link groovyDebug Debug + hi def link groovyDebugString DebugString + hi def link groovyDebugStringError groovyError + hi def link groovyDebugType DebugType + hi def link groovyDebugBoolean DebugBoolean + hi def link groovyDebugNumber Debug + hi def link groovyDebugSpecial DebugSpecial + hi def link groovyDebugSpecialCharacter DebugSpecial + hi def link groovyDebugCharacter DebugString + hi def link groovyDebugParen Debug + + hi def link DebugString String + hi def link DebugSpecial Special + hi def link DebugBoolean Boolean + hi def link DebugType Type endif " Match all Exception classes @@ -379,7 +368,7 @@ exec "syn sync ccomment groovyComment minlines=" . groovy_minlines if exists("groovy_mark_braces_in_parens_as_errors") syn match groovyInParen contained "[{}]" - GroovyHiLink groovyInParen groovyError + hi def link groovyInParen groovyError syn cluster groovyTop add=groovyInParen endif @@ -388,7 +377,7 @@ syn region groovyParenT transparent matchgroup=groovyParen start="(" end=")" syn region groovyParenT1 transparent matchgroup=groovyParen1 start="(" end=")" contains=@groovyTop,groovyParenT2 contained syn region groovyParenT2 transparent matchgroup=groovyParen2 start="(" end=")" contains=@groovyTop,groovyParenT contained syn match groovyParenError ")" -GroovyHiLink groovyParenError groovyError +hi def link groovyParenError groovyError " catch errors caused by wrong square parenthesis syn region groovyParenT transparent matchgroup=groovyParen start="\[" end="\]" contains=@groovyTop,groovyParenT1 @@ -398,61 +387,54 @@ syn match groovyParenError "\]" " ############################### " java.vim default highlighting -if version >= 508 || !exists("did_groovy_syn_inits") - if version < 508 - let did_groovy_syn_inits = 1 - endif - GroovyHiLink groovyFuncDef Function - GroovyHiLink groovyBraces Function - GroovyHiLink groovyBranch Conditional - GroovyHiLink groovyUserLabelRef groovyUserLabel - GroovyHiLink groovyLabel Label - GroovyHiLink groovyUserLabel Label - GroovyHiLink groovyConditional Conditional - GroovyHiLink groovyRepeat Repeat - GroovyHiLink groovyExceptions Exception - GroovyHiLink groovyAssert Statement - GroovyHiLink groovyStorageClass StorageClass - GroovyHiLink groovyMethodDecl groovyStorageClass - GroovyHiLink groovyClassDecl groovyStorageClass - GroovyHiLink groovyScopeDecl groovyStorageClass - GroovyHiLink groovyBoolean Boolean - GroovyHiLink groovySpecial Special - GroovyHiLink groovySpecialError Error - GroovyHiLink groovySpecialCharError Error - GroovyHiLink groovyString String - GroovyHiLink groovyRegexChar String - GroovyHiLink groovyCharacter Character - GroovyHiLink groovySpecialChar SpecialChar - GroovyHiLink groovyNumber Number - GroovyHiLink groovyError Error - GroovyHiLink groovyStringError Error - GroovyHiLink groovyStatement Statement - GroovyHiLink groovyOperator Operator - GroovyHiLink groovyComment Comment - GroovyHiLink groovyDocComment Comment - GroovyHiLink groovyLineComment Comment - GroovyHiLink groovyConstant Constant - GroovyHiLink groovyTypedef Typedef - GroovyHiLink groovyTodo Todo - - GroovyHiLink groovyCommentTitle SpecialComment - GroovyHiLink groovyDocTags Special - GroovyHiLink groovyDocParam Function - GroovyHiLink groovyCommentStar groovyComment - - GroovyHiLink groovyType Type - GroovyHiLink groovyExternal Include - - GroovyHiLink htmlComment Special - GroovyHiLink htmlCommentPart Special - GroovyHiLink groovySpaceError Error - GroovyHiLink groovyJDKBuiltin Special - GroovyHiLink groovyJDKOperOverl Operator - GroovyHiLink groovyJDKMethods Function -endif - -delcommand GroovyHiLink +hi def link groovyFuncDef Function +hi def link groovyBraces Function +hi def link groovyBranch Conditional +hi def link groovyUserLabelRef groovyUserLabel +hi def link groovyLabel Label +hi def link groovyUserLabel Label +hi def link groovyConditional Conditional +hi def link groovyRepeat Repeat +hi def link groovyExceptions Exception +hi def link groovyAssert Statement +hi def link groovyStorageClass StorageClass +hi def link groovyMethodDecl groovyStorageClass +hi def link groovyClassDecl groovyStorageClass +hi def link groovyScopeDecl groovyStorageClass +hi def link groovyBoolean Boolean +hi def link groovySpecial Special +hi def link groovySpecialError Error +hi def link groovySpecialCharError Error +hi def link groovyString String +hi def link groovyRegexChar String +hi def link groovyCharacter Character +hi def link groovySpecialChar SpecialChar +hi def link groovyNumber Number +hi def link groovyError Error +hi def link groovyStringError Error +hi def link groovyStatement Statement +hi def link groovyOperator Operator +hi def link groovyComment Comment +hi def link groovyDocComment Comment +hi def link groovyLineComment Comment +hi def link groovyConstant Constant +hi def link groovyTypedef Typedef +hi def link groovyTodo Todo + +hi def link groovyCommentTitle SpecialComment +hi def link groovyDocTags Special +hi def link groovyDocParam Function +hi def link groovyCommentStar groovyComment + +hi def link groovyType Type +hi def link groovyExternal Include + +hi def link htmlComment Special +hi def link htmlCommentPart Special +hi def link groovySpaceError Error +hi def link groovyJDKBuiltin Special +hi def link groovyJDKOperOverl Operator +hi def link groovyJDKMethods Function let b:current_syntax = "groovy" diff --git a/runtime/syntax/gsp.vim b/runtime/syntax/gsp.vim index e7b1b1632f..6270b2af64 100644 --- a/runtime/syntax/gsp.vim +++ b/runtime/syntax/gsp.vim @@ -5,11 +5,8 @@ " Filenames: *.gsp " URL: http://www.constructicon.com/~nharward/vim/syntax/gsp.vim -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -18,21 +15,13 @@ if !exists("main_syntax") endif " Source HTML syntax -if version < 600 - source <sfile>:p:h/html.vim -else - runtime! syntax/html.vim -endif +runtime! syntax/html.vim unlet b:current_syntax syn case match " Include Java syntax -if version < 600 - syn include @gspJava <sfile>:p:h/java.vim -else - syn include @gspJava syntax/java.vim -endif +syn include @gspJava syntax/java.vim let s:cpo_save = &cpo set cpo&vim diff --git a/runtime/syntax/gtkrc.vim b/runtime/syntax/gtkrc.vim index 57054a21d3..9c1bc2abb8 100644 --- a/runtime/syntax/gtkrc.vim +++ b/runtime/syntax/gtkrc.vim @@ -6,19 +6,12 @@ " URL: http://trific.ath.cx/Ftp/vim/syntax/gtkrc.vim " Setup -if version >= 600 - if exists("b:current_syntax") - finish - endif -else - syntax clear +" quit when a syntax file was already loaded +if exists("b:current_syntax") + finish endif -if version >= 600 - setlocal iskeyword=_,-,a-z,A-Z,48-57 -else - set iskeyword=_,-,a-z,A-Z,48-57 -endif +setlocal iskeyword=_,-,a-z,A-Z,48-57 syn case match @@ -86,57 +79,48 @@ syn sync minlines=50 syn sync match gtkrcSyncClass groupthere NONE "^\s*class\>" " Define the default highlighting -if version >= 508 || !exists("did_gtkrc_syntax_inits") - if version < 508 - let did_gtkrc_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink gtkrcComment Comment - HiLink gtkrcFixme Todo - - HiLink gtkrcInclude Preproc - - HiLink gtkrcACString gtkrcString - HiLink gtkrcBString gtkrcString - HiLink gtkrcString String - HiLink gtkrcNumber Number - HiLink gtkrcStateName gtkrcConstant - HiLink gtkrcPriorityName gtkrcConstant - HiLink gtkrcTextDirName gtkrcConstant - HiLink gtkrcSettingsName Function - HiLink gtkrcStockName Function - HiLink gtkrcConstant Constant - - HiLink gtkrcPathSpecial gtkrcSpecial - HiLink gtkrcWPathSpecial gtkrcSpecial - HiLink gtkrcRGBColor gtkrcSpecial - HiLink gtkrcKeyMod gtkrcSpecial - HiLink gtkrcSpecial Special - - HiLink gtkrcTop gtkrcKeyword - HiLink gtkrcPathSet gtkrcKeyword - HiLink gtkrcStyleKeyword gtkrcKeyword - HiLink gtkrcFunction gtkrcKeyword - HiLink gtkrcBind gtkrcKeyword - HiLink gtkrcKeyword Keyword - - HiLink gtkrcClassNameGnome gtkrcGtkClass - HiLink gtkrcClassName gtkrcGtkClass - HiLink gtkrcFunctionName gtkrcGtkClass - HiLink gtkrcGtkClass Type - - HiLink gtkrcImage gtkrcOtherword - HiLink gtkrcOtherword Function - - HiLink gtkrcParenError gtkrcError - HiLink gtkrcBraceError gtkrcError - HiLink gtkrcBracketError gtkrcError - HiLink gtkrcError Error - - delcommand HiLink -endif + +hi def link gtkrcComment Comment +hi def link gtkrcFixme Todo + +hi def link gtkrcInclude Preproc + +hi def link gtkrcACString gtkrcString +hi def link gtkrcBString gtkrcString +hi def link gtkrcString String +hi def link gtkrcNumber Number +hi def link gtkrcStateName gtkrcConstant +hi def link gtkrcPriorityName gtkrcConstant +hi def link gtkrcTextDirName gtkrcConstant +hi def link gtkrcSettingsName Function +hi def link gtkrcStockName Function +hi def link gtkrcConstant Constant + +hi def link gtkrcPathSpecial gtkrcSpecial +hi def link gtkrcWPathSpecial gtkrcSpecial +hi def link gtkrcRGBColor gtkrcSpecial +hi def link gtkrcKeyMod gtkrcSpecial +hi def link gtkrcSpecial Special + +hi def link gtkrcTop gtkrcKeyword +hi def link gtkrcPathSet gtkrcKeyword +hi def link gtkrcStyleKeyword gtkrcKeyword +hi def link gtkrcFunction gtkrcKeyword +hi def link gtkrcBind gtkrcKeyword +hi def link gtkrcKeyword Keyword + +hi def link gtkrcClassNameGnome gtkrcGtkClass +hi def link gtkrcClassName gtkrcGtkClass +hi def link gtkrcFunctionName gtkrcGtkClass +hi def link gtkrcGtkClass Type + +hi def link gtkrcImage gtkrcOtherword +hi def link gtkrcOtherword Function + +hi def link gtkrcParenError gtkrcError +hi def link gtkrcBraceError gtkrcError +hi def link gtkrcBracketError gtkrcError +hi def link gtkrcError Error + let b:current_syntax = "gtkrc" diff --git a/runtime/syntax/haml.vim b/runtime/syntax/haml.vim index bf7a073633..5369695c22 100644 --- a/runtime/syntax/haml.vim +++ b/runtime/syntax/haml.vim @@ -2,7 +2,7 @@ " Language: Haml " Maintainer: Tim Pope <vimNOSPAM@tpope.org> " Filenames: *.haml -" Last Change: 2010 Aug 09 +" Last Change: 2016 Aug 29 if exists("b:current_syntax") finish @@ -67,7 +67,7 @@ syn region hamlJavascriptFilter matchgroup=hamlFilter start="^\z(\s*\):javascri syn region hamlCSSFilter matchgroup=hamlFilter start="^\z(\s*\):css\s*$" end="^\%(\z1 \| *$\)\@!" contains=@htmlCss,hamlInterpolation keepend syn region hamlSassFilter matchgroup=hamlFilter start="^\z(\s*\):sass\s*$" end="^\%(\z1 \| *$\)\@!" contains=@hamlSassTop -syn region hamlJavascriptBlock start="^\z(\s*\)%script" nextgroup=@hamlComponent,hamlError end="^\%(\z1 \| *$\)\@!" contains=@hamlTop,@htmlJavaScript keepend +syn region hamlJavascriptBlock start="^\z(\s*\)%script\%((type=[\"']text/javascript[\"'])\)\=\s*$" nextgroup=@hamlComponent,hamlError end="^\%(\z1 \| *$\)\@!" contains=@hamlTop,@htmlJavaScript keepend syn region hamlCssBlock start="^\z(\s*\)%style" nextgroup=@hamlComponent,hamlError end="^\%(\z1 \| *$\)\@!" contains=@hamlTop,@htmlCss keepend syn match hamlError "\$" contained diff --git a/runtime/syntax/hamster.vim b/runtime/syntax/hamster.vim index bd52300ca0..64d9598a71 100644 --- a/runtime/syntax/hamster.vim +++ b/runtime/syntax/hamster.vim @@ -12,10 +12,8 @@ " for news and mail, a build-in script language, the GUI allows translation to " other languages, it can be used in a network and that's not all features... " -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -358,24 +356,14 @@ syn cluster hamsterComment contains=hamsterHashComment syn sync ccomment hamsterHashComment " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_hamster_syn_inits") - if version < 508 - let did_hamster_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink hamsterHashComment Comment - HiLink hamsterSpecial Special - HiLink hamsterStatement Statement - HiLink hamsterString String - HiLink hamsterFunction Function +hi def link hamsterHashComment Comment +hi def link hamsterSpecial Special +hi def link hamsterStatement Statement +hi def link hamsterString String +hi def link hamsterFunction Function - delcommand HiLink -endif let b:current_syntax = "hamster" diff --git a/runtime/syntax/haskell.vim b/runtime/syntax/haskell.vim index 8afca048cc..11f4c35a58 100644 --- a/runtime/syntax/haskell.vim +++ b/runtime/syntax/haskell.vim @@ -32,10 +32,8 @@ " to attribution of work. " 2008 Dec 15: Added comments as contained element in import statements -" Remove any old syntax stuff hanging around -if version < 600 - syn clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -127,67 +125,57 @@ syntax match cCommentStartError display "/\*"me=e-1 contained syn region cCppString start=+L\="+ skip=+\\\\\|\\"\|\\$+ excludenl end=+"+ end='$' contains=cSpecial contained " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_hs_syntax_inits") - if version < 508 - let did_hs_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink hsModule hsStructure - HiLink hsImport Include - HiLink hsImportMod hsImport - HiLink hsInfix PreProc - HiLink hsStructure Structure - HiLink hsStatement Statement - HiLink hsConditional Conditional - HiLink hsSpecialChar SpecialChar - HiLink hsTypedef Typedef - HiLink hsVarSym hsOperator - HiLink hsConSym hsOperator - HiLink hsOperator Operator - if exists("hs_highlight_delimiters") - " Some people find this highlighting distracting. - HiLink hsDelimiter Delimiter - endif - HiLink hsSpecialCharError Error - HiLink hsString String - HiLink hsCharacter Character - HiLink hsNumber Number - HiLink hsFloat Float - HiLink hsConditional Conditional - HiLink hsLiterateComment hsComment - HiLink hsBlockComment hsComment - HiLink hsLineComment hsComment - HiLink hsComment Comment - HiLink hsPragma SpecialComment - HiLink hsBoolean Boolean - HiLink hsType Type - HiLink hsMaybe hsEnumConst - HiLink hsOrdering hsEnumConst - HiLink hsEnumConst Constant - HiLink hsDebug Debug - - HiLink cCppString hsString - HiLink cCommentStart hsComment - HiLink cCommentError hsError - HiLink cCommentStartError hsError - HiLink cInclude Include - HiLink cPreProc PreProc - HiLink cDefine Macro - HiLink cIncluded hsString - HiLink cError Error - HiLink cPreCondit PreCondit - HiLink cComment Comment - HiLink cCppSkip cCppOut - HiLink cCppOut2 cCppOut - HiLink cCppOut Comment - - delcommand HiLink +" Only when an item doesn't have highlighting yet + +hi def link hsModule hsStructure +hi def link hsImport Include +hi def link hsImportMod hsImport +hi def link hsInfix PreProc +hi def link hsStructure Structure +hi def link hsStatement Statement +hi def link hsConditional Conditional +hi def link hsSpecialChar SpecialChar +hi def link hsTypedef Typedef +hi def link hsVarSym hsOperator +hi def link hsConSym hsOperator +hi def link hsOperator Operator +if exists("hs_highlight_delimiters") +" Some people find this highlighting distracting. +hi def link hsDelimiter Delimiter endif +hi def link hsSpecialCharError Error +hi def link hsString String +hi def link hsCharacter Character +hi def link hsNumber Number +hi def link hsFloat Float +hi def link hsConditional Conditional +hi def link hsLiterateComment hsComment +hi def link hsBlockComment hsComment +hi def link hsLineComment hsComment +hi def link hsComment Comment +hi def link hsPragma SpecialComment +hi def link hsBoolean Boolean +hi def link hsType Type +hi def link hsMaybe hsEnumConst +hi def link hsOrdering hsEnumConst +hi def link hsEnumConst Constant +hi def link hsDebug Debug + +hi def link cCppString hsString +hi def link cCommentStart hsComment +hi def link cCommentError hsError +hi def link cCommentStartError hsError +hi def link cInclude Include +hi def link cPreProc PreProc +hi def link cDefine Macro +hi def link cIncluded hsString +hi def link cError Error +hi def link cPreCondit PreCondit +hi def link cComment Comment +hi def link cCppSkip cCppOut +hi def link cCppOut2 cCppOut +hi def link cCppOut Comment + let b:current_syntax = "haskell" diff --git a/runtime/syntax/haste.vim b/runtime/syntax/haste.vim index b889c5c594..79e9f5ec56 100644 --- a/runtime/syntax/haste.vim +++ b/runtime/syntax/haste.vim @@ -12,11 +12,8 @@ if exists("b:current_syntax") finish endif -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif diff --git a/runtime/syntax/hastepreproc.vim b/runtime/syntax/hastepreproc.vim index 3fcb8ddd31..f08bf3fbf3 100644 --- a/runtime/syntax/hastepreproc.vim +++ b/runtime/syntax/hastepreproc.vim @@ -5,24 +5,13 @@ " files " Version: 0.5 -" HASTE +" quit when a syntax file was already loaded if exists("b:current_syntax") - finish -endif -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") finish endif -" Read the C syntax to start with -if version < 600 - so <sfile>:p:h/haste.vim -else - runtime! syntax/haste.vim - unlet b:current_syntax -endif +" Read the haste syntax to start with +runtime! syntax/haste.vim +unlet b:current_syntax " case is significant syn case match diff --git a/runtime/syntax/hb.vim b/runtime/syntax/hb.vim index d4de3ff1e1..7bff1df9fb 100644 --- a/runtime/syntax/hb.vim +++ b/runtime/syntax/hb.vim @@ -4,11 +4,8 @@ " URL: http://bachue.com/hb/vim/syntax/hb.vim " Last Change: 2012 Jan 08 by Thilo Six -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -63,31 +60,21 @@ syn region HBText matchgroup=HBDirectiveKeyword start=/^:\(set\|out\)\s*\S\+.*$/ syn match HBComment "^#.*$" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_hb_syntax_inits") - if version < 508 - let did_hb_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink HBhtmlString String - HiLink HBhtmlTagN Function - HiLink htmlSpecialChar String - - HiLink HBInvalidLine Error - HiLink HBFoobar Comment - hi HBFileName guibg=lightgray guifg=black - HiLink HBDirectiveError Error - HiLink HBDirectiveBlockEnd HBDirectiveKeyword - hi HBDirectiveKeyword guibg=lightgray guifg=darkgreen - HiLink HBComment Comment - HiLink HBhtmlTagSk Statement - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link HBhtmlString String +hi def link HBhtmlTagN Function +hi def link htmlSpecialChar String + +hi def link HBInvalidLine Error +hi def link HBFoobar Comment +hi HBFileName guibg=lightgray guifg=black +hi def link HBDirectiveError Error +hi def link HBDirectiveBlockEnd HBDirectiveKeyword +hi HBDirectiveKeyword guibg=lightgray guifg=darkgreen +hi def link HBComment Comment +hi def link HBhtmlTagSk Statement + syn sync match Normal grouphere NONE "^:\s*$" syn sync match Normal grouphere NONE "^:\s*lib\s\+[^ \t]\+$" diff --git a/runtime/syntax/help.vim b/runtime/syntax/help.vim index 41bb0b1938..98ab7f4b23 100644 --- a/runtime/syntax/help.vim +++ b/runtime/syntax/help.vim @@ -1,7 +1,7 @@ " Vim syntax file " Language: Vim help file " Maintainer: Bram Moolenaar (Bram@vim.org) -" Last Change: 2016 Apr 01 +" Last Change: 2016 Sep 02 " Quit when a (custom) syntax file was already loaded if exists("b:current_syntax") @@ -50,6 +50,7 @@ else syn match helpIgnore "." contained endif syn keyword helpNote note Note NOTE note: Note: NOTE: Notes Notes: +syn keyword helpWarning WARNING: Warning: syn match helpSpecial "\<N\>" syn match helpSpecial "\<N\.$"me=e-1 syn match helpSpecial "\<N\.\s"me=e-2 @@ -86,6 +87,8 @@ syn match helpSpecial "CTRL-PageDown" syn match helpSpecial "CTRL-Insert" syn match helpSpecial "CTRL-Del" syn match helpSpecial "CTRL-{char}" +syn match helpSpecial "META-." +syn match helpSpecial "ALT-." " Highlight group items in their own color. syn match helpComment "\t[* ]Comment\t\+[a-z].*" @@ -161,6 +164,7 @@ hi def link helpExample Comment hi def link helpOption Type hi def link helpSpecial Special hi def link helpNote Todo +hi def link helpWarning Todo hi def link helpComment Comment hi def link helpConstant Constant diff --git a/runtime/syntax/hercules.vim b/runtime/syntax/hercules.vim index 02d8e9bb78..d305707662 100644 --- a/runtime/syntax/hercules.vim +++ b/runtime/syntax/hercules.vim @@ -7,11 +7,8 @@ " that an IC's physical design matches its logical design and " satisfies manufacturing rules. -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -101,32 +98,21 @@ syn match herculesOutput "error\s*=\s*(.*)" syn sync lines=100 " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_hercules_syntax_inits") - if version < 508 - let did_hercules_syntax_inits = 1 - " Default methods for highlighting. - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink herculesStatement Statement - HiLink herculesType Type - HiLink herculesComment Comment - HiLink herculesPreProc PreProc - HiLink herculesTodo Todo - HiLink herculesOutput Include - HiLink herculesCmdCmnt Identifier - HiLink herculesNumber Number - HiLink herculesBraceError herculesError - HiLink herculesCurlyError herculesError - HiLink herculesParenError herculesError - HiLink herculesError Error - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link herculesStatement Statement +hi def link herculesType Type +hi def link herculesComment Comment +hi def link herculesPreProc PreProc +hi def link herculesTodo Todo +hi def link herculesOutput Include +hi def link herculesCmdCmnt Identifier +hi def link herculesNumber Number +hi def link herculesBraceError herculesError +hi def link herculesCurlyError herculesError +hi def link herculesParenError herculesError +hi def link herculesError Error + let b:current_syntax = "hercules" diff --git a/runtime/syntax/hex.vim b/runtime/syntax/hex.vim index 40f7f0dd10..35edf08e9f 100644 --- a/runtime/syntax/hex.vim +++ b/runtime/syntax/hex.vim @@ -25,11 +25,8 @@ " States in parentheses in the upper format description indicate that they " should not appear in a valid file. -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -68,34 +65,24 @@ syn match hexChecksum "[0-9a-fA-F]\{2}$" contained syn region hexExtAdrBlock start="^:[0-9a-fA-F]\{7}[24]" skip="^:[0-9a-fA-F]\{7}0" end="^:"me=s-1 fold transparent " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_hex_syntax_inits") - if version < 508 - let did_hex_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - " The default methods for highlighting. Can be overridden later - HiLink hexRecStart hexRecType - HiLink hexDataByteCount Constant - hi def hexAddressFieldUnknown term=italic cterm=italic gui=italic - HiLink hexDataAddress Comment - HiLink hexNoAddress DiffAdd - HiLink hexRecTypeUnknown hexRecType - HiLink hexRecType WarningMsg - hi def hexDataFieldUnknown term=italic cterm=italic gui=italic - hi def hexDataOdd term=bold cterm=bold gui=bold - hi def hexDataEven term=NONE cterm=NONE gui=NONE - HiLink hexDataUnexpected Error - HiLink hexExtendedAddress hexDataAddress - HiLink hexStartAddress hexDataAddress - HiLink hexChecksum DiffChange +" The default methods for highlighting. Can be overridden later +hi def link hexRecStart hexRecType +hi def link hexDataByteCount Constant +hi def hexAddressFieldUnknown term=italic cterm=italic gui=italic +hi def link hexDataAddress Comment +hi def link hexNoAddress DiffAdd +hi def link hexRecTypeUnknown hexRecType +hi def link hexRecType WarningMsg +hi def hexDataFieldUnknown term=italic cterm=italic gui=italic +hi def hexDataOdd term=bold cterm=bold gui=bold +hi def hexDataEven term=NONE cterm=NONE gui=NONE +hi def link hexDataUnexpected Error +hi def link hexExtendedAddress hexDataAddress +hi def link hexStartAddress hexDataAddress +hi def link hexChecksum DiffChange - delcommand HiLink -endif let b:current_syntax = "hex" diff --git a/runtime/syntax/hog.vim b/runtime/syntax/hog.vim index f37f7ae899..7206815202 100644 --- a/runtime/syntax/hog.vim +++ b/runtime/syntax/hog.vim @@ -4,9 +4,8 @@ " Last Change: 2015 Oct 24 -> Rename syntax items from Snort -> Hog " 2012 Oct 24 -> Originalish release -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif diff --git a/runtime/syntax/hostsaccess.vim b/runtime/syntax/hostsaccess.vim index 8a9f02eff5..7201816f48 100644 --- a/runtime/syntax/hostsaccess.vim +++ b/runtime/syntax/hostsaccess.vim @@ -15,12 +15,8 @@ if exists("b:current_syntax") endif " For a starter we just use conf.vim for highlighting -if version < 600 - so <sfile>:p:h/conf.vim -else - runtime! syntax/conf.vim - unlet b:current_syntax -endif +runtime! syntax/conf.vim +unlet b:current_syntax let b:current_syntax = "hostsaccess" diff --git a/runtime/syntax/html.vim b/runtime/syntax/html.vim index ab1f9b3c13..49d3ab4adb 100644 --- a/runtime/syntax/html.vim +++ b/runtime/syntax/html.vim @@ -1,18 +1,16 @@ " Vim syntax file -" Language: HTML -" Maintainer: Claudio Fleiner <claudio@fleiner.com> -" URL: http://www.fleiner.com/vim/syntax/html.vim -" Last Change: 2015 Jan 07 -" included patch from David Felix +" Language: HTML +" Maintainer: Jorge Maldonado Ventura <jorgesumle@freakspot.net> +" Previous Maintainer: Claudio Fleiner <claudio@fleiner.com> +" Repository: https://notabug.org/jorgesumle/vim-html-syntax +" Last Change: 2017 Jan 21 +" included patch from Jorge Maldonado Ventura " Please check :help html.vim for some comments and a description of the options -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded +" quit when a syntax file was already loaded if !exists("main_syntax") - if version < 600 - syntax clear - elseif exists("b:current_syntax") + if exists("b:current_syntax") finish endif let main_syntax = 'html' @@ -21,13 +19,6 @@ endif let s:cpo_save = &cpo set cpo&vim -" don't use standard HiLink, it will not work with included syntax files -if version < 508 - command! -nargs=+ HtmlHiLink hi link <args> -else - command! -nargs=+ HtmlHiLink hi def link <args> -endif - syntax spell toplevel syn case ignore @@ -63,6 +54,14 @@ syn keyword htmlTagName contained abbr acronym bdo button col label syn keyword htmlTagName contained colgroup del fieldset iframe ins legend syn keyword htmlTagName contained object optgroup q s tbody tfoot thead +" new html 5 tags +syn keyword htmlTagName contained article aside audio bdi canvas data +syn keyword htmlTagName contained datalist details embed figcaption figure +syn keyword htmlTagName contained footer header hgroup keygen main mark +syn keyword htmlTagName contained menuitem meter nav output picture +syn keyword htmlTagName contained progress rb rp rt rtc ruby section +syn keyword htmlTagName contained slot source template time track video wbr + " legal arg names syn keyword htmlArg contained action syn keyword htmlArg contained align alink alt archive background bgcolor @@ -97,6 +96,19 @@ syn keyword htmlArg contained multiple nohref nowrap object profile readonly syn keyword htmlArg contained rules scheme scope span standby style syn keyword htmlArg contained summary tabindex valuetype version +" html 5 arg names +syn keyword htmlArg contained allowfullscreen async autocomplete autofocus +syn keyword htmlArg contained autoplay challenge contenteditable contextmenu +syn keyword htmlArg contained controls crossorigin default dirname download +syn keyword htmlArg contained draggable dropzone form formaction formenctype +syn keyword htmlArg contained formmethod formnovalidate formtarget hidden +syn keyword htmlArg contained high icon inputmode keytype kind list loop low +syn keyword htmlArg contained max min minlength muted nonce novalidate open +syn keyword htmlArg contained optimum pattern placeholder poster preload +syn keyword htmlArg contained radiogroup required reversed sandbox spellcheck +syn keyword htmlArg contained sizes srcset srcdoc srclang step title translate +syn keyword htmlArg contained typemustmatch + " special characters syn match htmlSpecialChar "&#\=[0-9A-Za-z]\{1,8};" @@ -171,7 +183,7 @@ if main_syntax != 'java' || exists("java_javascript") unlet b:current_syntax syn region javaScript start=+<script\_[^>]*>+ keepend end=+</script\_[^>]*>+me=s-1 contains=@htmlJavaScript,htmlCssStyleComment,htmlScriptTag,@htmlPreproc syn region htmlScriptTag contained start=+<script+ end=+>+ fold contains=htmlTagN,htmlString,htmlArg,htmlValue,htmlTagError,htmlEvent - HtmlHiLink htmlScriptTag htmlTag + hi def link htmlScriptTag htmlTag " html events (i.e. arguments that include javascript commands) if exists("html_extended_events") @@ -183,8 +195,8 @@ if main_syntax != 'java' || exists("java_javascript") endif syn region htmlEventSQ contained start=+'+ms=s+1 end=+'+me=s-1 contains=@htmlJavaScript syn region htmlEventDQ contained start=+"+ms=s+1 end=+"+me=s-1 contains=@htmlJavaScript - HtmlHiLink htmlEventSQ htmlEvent - HtmlHiLink htmlEventDQ htmlEvent + hi def link htmlEventSQ htmlEvent + hi def link htmlEventDQ htmlEvent " a javascript expression is used as an arg value syn region javaScriptExpression contained start=+&{+ keepend end=+};+ contains=@htmlJavaScript,@htmlPreproc @@ -207,7 +219,7 @@ if main_syntax != 'java' || exists("java_css") syn region cssStyle start=+<style+ keepend end=+</style>+ contains=@htmlCss,htmlTag,htmlEndTag,htmlCssStyleComment,@htmlPreproc syn match htmlCssStyleComment contained "\(<!--\|-->\)" syn region htmlCssDefinition matchgroup=htmlArg start='style="' keepend matchgroup=htmlString end='"' contains=css.*Attr,css.*Prop,cssComment,cssLength,cssColor,cssURL,cssImportant,cssError,cssString,@htmlPreproc - HtmlHiLink htmlStyleArg htmlString + hi def link htmlStyleArg htmlString endif if main_syntax == "html" @@ -221,73 +233,66 @@ if main_syntax == "html" endif " The default highlighting. -if version >= 508 || !exists("did_html_syn_inits") - if version < 508 - let did_html_syn_inits = 1 - endif - HtmlHiLink htmlTag Function - HtmlHiLink htmlEndTag Identifier - HtmlHiLink htmlArg Type - HtmlHiLink htmlTagName htmlStatement - HtmlHiLink htmlSpecialTagName Exception - HtmlHiLink htmlValue String - HtmlHiLink htmlSpecialChar Special - - if !exists("html_no_rendering") - HtmlHiLink htmlH1 Title - HtmlHiLink htmlH2 htmlH1 - HtmlHiLink htmlH3 htmlH2 - HtmlHiLink htmlH4 htmlH3 - HtmlHiLink htmlH5 htmlH4 - HtmlHiLink htmlH6 htmlH5 - HtmlHiLink htmlHead PreProc - HtmlHiLink htmlTitle Title - HtmlHiLink htmlBoldItalicUnderline htmlBoldUnderlineItalic - HtmlHiLink htmlUnderlineBold htmlBoldUnderline - HtmlHiLink htmlUnderlineItalicBold htmlBoldUnderlineItalic - HtmlHiLink htmlUnderlineBoldItalic htmlBoldUnderlineItalic - HtmlHiLink htmlItalicUnderline htmlUnderlineItalic - HtmlHiLink htmlItalicBold htmlBoldItalic - HtmlHiLink htmlItalicBoldUnderline htmlBoldUnderlineItalic - HtmlHiLink htmlItalicUnderlineBold htmlBoldUnderlineItalic - HtmlHiLink htmlLink Underlined - HtmlHiLink htmlLeadingSpace None - if !exists("html_my_rendering") - hi def htmlBold term=bold cterm=bold gui=bold - hi def htmlBoldUnderline term=bold,underline cterm=bold,underline gui=bold,underline - hi def htmlBoldItalic term=bold,italic cterm=bold,italic gui=bold,italic - hi def htmlBoldUnderlineItalic term=bold,italic,underline cterm=bold,italic,underline gui=bold,italic,underline - hi def htmlUnderline term=underline cterm=underline gui=underline - hi def htmlUnderlineItalic term=italic,underline cterm=italic,underline gui=italic,underline - hi def htmlItalic term=italic cterm=italic gui=italic - endif +hi def link htmlTag Function +hi def link htmlEndTag Identifier +hi def link htmlArg Type +hi def link htmlTagName htmlStatement +hi def link htmlSpecialTagName Exception +hi def link htmlValue String +hi def link htmlSpecialChar Special + +if !exists("html_no_rendering") + hi def link htmlH1 Title + hi def link htmlH2 htmlH1 + hi def link htmlH3 htmlH2 + hi def link htmlH4 htmlH3 + hi def link htmlH5 htmlH4 + hi def link htmlH6 htmlH5 + hi def link htmlHead PreProc + hi def link htmlTitle Title + hi def link htmlBoldItalicUnderline htmlBoldUnderlineItalic + hi def link htmlUnderlineBold htmlBoldUnderline + hi def link htmlUnderlineItalicBold htmlBoldUnderlineItalic + hi def link htmlUnderlineBoldItalic htmlBoldUnderlineItalic + hi def link htmlItalicUnderline htmlUnderlineItalic + hi def link htmlItalicBold htmlBoldItalic + hi def link htmlItalicBoldUnderline htmlBoldUnderlineItalic + hi def link htmlItalicUnderlineBold htmlBoldUnderlineItalic + hi def link htmlLink Underlined + hi def link htmlLeadingSpace None + if !exists("html_my_rendering") + hi def htmlBold term=bold cterm=bold gui=bold + hi def htmlBoldUnderline term=bold,underline cterm=bold,underline gui=bold,underline + hi def htmlBoldItalic term=bold,italic cterm=bold,italic gui=bold,italic + hi def htmlBoldUnderlineItalic term=bold,italic,underline cterm=bold,italic,underline gui=bold,italic,underline + hi def htmlUnderline term=underline cterm=underline gui=underline + hi def htmlUnderlineItalic term=italic,underline cterm=italic,underline gui=italic,underline + hi def htmlItalic term=italic cterm=italic gui=italic endif - - HtmlHiLink htmlPreStmt PreProc - HtmlHiLink htmlPreError Error - HtmlHiLink htmlPreProc PreProc - HtmlHiLink htmlPreAttr String - HtmlHiLink htmlPreProcAttrName PreProc - HtmlHiLink htmlPreProcAttrError Error - HtmlHiLink htmlSpecial Special - HtmlHiLink htmlSpecialChar Special - HtmlHiLink htmlString String - HtmlHiLink htmlStatement Statement - HtmlHiLink htmlComment Comment - HtmlHiLink htmlCommentPart Comment - HtmlHiLink htmlValue String - HtmlHiLink htmlCommentError htmlError - HtmlHiLink htmlTagError htmlError - HtmlHiLink htmlEvent javaScript - HtmlHiLink htmlError Error - - HtmlHiLink javaScript Special - HtmlHiLink javaScriptExpression javaScript - HtmlHiLink htmlCssStyleComment Comment - HtmlHiLink htmlCssDefinition Special endif -delcommand HtmlHiLink +hi def link htmlPreStmt PreProc +hi def link htmlPreError Error +hi def link htmlPreProc PreProc +hi def link htmlPreAttr String +hi def link htmlPreProcAttrName PreProc +hi def link htmlPreProcAttrError Error +hi def link htmlSpecial Special +hi def link htmlSpecialChar Special +hi def link htmlString String +hi def link htmlStatement Statement +hi def link htmlComment Comment +hi def link htmlCommentPart Comment +hi def link htmlValue String +hi def link htmlCommentError htmlError +hi def link htmlTagError htmlError +hi def link htmlEvent javaScript +hi def link htmlError Error + +hi def link javaScript Special +hi def link javaScriptExpression javaScript +hi def link htmlCssStyleComment Comment +hi def link htmlCssDefinition Special let b:current_syntax = "html" diff --git a/runtime/syntax/htmlcheetah.vim b/runtime/syntax/htmlcheetah.vim index f57df90dea..0721c76b44 100644 --- a/runtime/syntax/htmlcheetah.vim +++ b/runtime/syntax/htmlcheetah.vim @@ -3,11 +3,8 @@ " Maintainer: Max Ischenko <mfi@ukr.net> " Last Change: 2003-05-11 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -15,14 +12,9 @@ if !exists("main_syntax") let main_syntax = 'html' endif -if version < 600 - so <sfile>:p:h/cheetah.vim - so <sfile>:p:h/html.vim -else - runtime! syntax/cheetah.vim - runtime! syntax/html.vim - unlet b:current_syntax -endif +runtime! syntax/cheetah.vim +runtime! syntax/html.vim +unlet b:current_syntax syntax cluster htmlPreproc add=cheetahPlaceHolder syntax cluster htmlString add=cheetahPlaceHolder diff --git a/runtime/syntax/htmldjango.vim b/runtime/syntax/htmldjango.vim index 58afd1b62d..07b1c375e8 100644 --- a/runtime/syntax/htmldjango.vim +++ b/runtime/syntax/htmldjango.vim @@ -3,11 +3,8 @@ " Maintainer: Dave Hodder <dmh@dmh.org.uk> " Last Change: 2014 Jul 13 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -15,14 +12,9 @@ if !exists("main_syntax") let main_syntax = 'html' endif -if version < 600 - so <sfile>:p:h/django.vim - so <sfile>:p:h/html.vim -else - runtime! syntax/django.vim - runtime! syntax/html.vim - unlet b:current_syntax -endif +runtime! syntax/django.vim +runtime! syntax/html.vim +unlet b:current_syntax syn cluster djangoBlocks add=djangoTagBlock,djangoVarBlock,djangoComment,djangoComBlock diff --git a/runtime/syntax/htmlm4.vim b/runtime/syntax/htmlm4.vim index 3119d2d1ad..ee1f06e5f4 100644 --- a/runtime/syntax/htmlm4.vim +++ b/runtime/syntax/htmlm4.vim @@ -4,11 +4,8 @@ " URL: http://www.fleiner.com/vim/syntax/htmlm4.vim " Last Change: 2001 Apr 30 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -17,19 +14,12 @@ if !exists("main_syntax") let main_syntax='htmlm4' endif -if version < 600 - so <sfile>:p:h/html.vim -else - runtime! syntax/html.vim -endif +runtime! syntax/html.vim unlet b:current_syntax syn case match -if version < 600 - so <sfile>:p:h/m4.vim -else - runtime! syntax/m4.vim -endif +runtime! syntax/m4.vim + unlet b:current_syntax syn cluster htmlPreproc add=@m4Top syn cluster m4StringContents add=htmlTag,htmlEndTag diff --git a/runtime/syntax/htmlos.vim b/runtime/syntax/htmlos.vim index f31b9f6543..b54ca7a921 100644 --- a/runtime/syntax/htmlos.vim +++ b/runtime/syntax/htmlos.vim @@ -6,11 +6,8 @@ " Last Change: 2003 May 11 " -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -18,12 +15,8 @@ if !exists("main_syntax") let main_syntax = 'htmlos' endif -if version < 600 - so <sfile>:p:h/html.vim -else - runtime! syntax/html.vim - unlet b:current_syntax -endif +runtime! syntax/html.vim +unlet b:current_syntax syn cluster htmlPreproc add=htmlosRegion @@ -121,42 +114,32 @@ else endif " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_htmlos_syn_inits") - if version < 508 - let did_htmlos_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - " The default methods for highlighting. Can be overridden later - HiLink htmlosSpecialIdentifier Operator - HiLink htmlosIdentifier Identifier - HiLink htmlosStorageClass StorageClass - HiLink htmlosComment Comment - HiLink htmlosBoolean Boolean - HiLink htmlosStringSingle String - HiLink htmlosStringDouble String - HiLink htmlosNumber Number - HiLink htmlosFloat Float - HiLink htmlosFunctions Function - HiLink htmlosRepeat Repeat - HiLink htmlosConditional Conditional - HiLink htmlosLabel Label - HiLink htmlosStatement Statement - HiLink htmlosKeyword Statement - HiLink htmlosType Type - HiLink htmlosDefine Define - HiLink htmlosParent Delimiter - HiLink htmlosError Error - HiLink htmlosTodo Todo - HiLink htmlosOperator Operator - HiLink htmlosRelation Operator - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +" The default methods for highlighting. Can be overridden later +hi def link htmlosSpecialIdentifier Operator +hi def link htmlosIdentifier Identifier +hi def link htmlosStorageClass StorageClass +hi def link htmlosComment Comment +hi def link htmlosBoolean Boolean +hi def link htmlosStringSingle String +hi def link htmlosStringDouble String +hi def link htmlosNumber Number +hi def link htmlosFloat Float +hi def link htmlosFunctions Function +hi def link htmlosRepeat Repeat +hi def link htmlosConditional Conditional +hi def link htmlosLabel Label +hi def link htmlosStatement Statement +hi def link htmlosKeyword Statement +hi def link htmlosType Type +hi def link htmlosDefine Define +hi def link htmlosParent Delimiter +hi def link htmlosError Error +hi def link htmlosTodo Todo +hi def link htmlosOperator Operator +hi def link htmlosRelation Operator + let b:current_syntax = "htmlos" if main_syntax == 'htmlos' diff --git a/runtime/syntax/ia64.vim b/runtime/syntax/ia64.vim index ebfdc95bae..544fcd402c 100644 --- a/runtime/syntax/ia64.vim +++ b/runtime/syntax/ia64.vim @@ -6,11 +6,8 @@ " File Version: 0.7 " Last Change: 2006 Sep 08 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -19,11 +16,7 @@ endif syn case ignore " Identifier Keyword characters (defines \k) -if version >= 600 - setlocal iskeyword=@,48-57,#,$,.,:,?,@-@,_,~ -else - set iskeyword=@,48-57,#,$,.,:,?,@-@,_,~ -endif +setlocal iskeyword=@,48-57,#,$,.,:,?,@-@,_,~ syn sync minlines=5 @@ -268,43 +261,33 @@ syn match ia64data "real\([48]\|1[06]\)\(\(\(\.ua\)\=\(\.msb\|\.lsb\)\=\)\|\(\(\ syn match ia64data "stringz\=\(\(\(\.ua\)\=\(\.msb\|\.lsb\)\=\)\|\(\(\.msb\|\.lsb\)\=\(\.ua\)\=\)\)\=\>" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_ia64_syn_inits") - if version < 508 - let did_ia64_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - "put masm groups with our groups - HiLink masmOperator ia64operator - HiLink masmDirective ia64Directive - HiLink masmOpcode ia64Opcode - HiLink masmIdentifier ia64Identifier - HiLink masmFloat ia64Float +"put masm groups with our groups +hi def link masmOperator ia64operator +hi def link masmDirective ia64Directive +hi def link masmOpcode ia64Opcode +hi def link masmIdentifier ia64Identifier +hi def link masmFloat ia64Float - "ia64 specific stuff - HiLink ia64Label Define - HiLink ia64Comment Comment - HiLink ia64Directive Type - HiLink ia64opcode Statement - HiLink ia64registers Operator - HiLink ia64string String - HiLink ia64Hex Number - HiLink ia64Binary Number - HiLink ia64Octal Number - HiLink ia64Float Float - HiLink ia64Decimal Number - HiLink ia64Identifier Identifier - HiLink ia64data Type - HiLink ia64delimiter Delimiter - HiLink ia64operator Operator - HiLink ia64Todo Todo +"ia64 specific stuff +hi def link ia64Label Define +hi def link ia64Comment Comment +hi def link ia64Directive Type +hi def link ia64opcode Statement +hi def link ia64registers Operator +hi def link ia64string String +hi def link ia64Hex Number +hi def link ia64Binary Number +hi def link ia64Octal Number +hi def link ia64Float Float +hi def link ia64Decimal Number +hi def link ia64Identifier Identifier +hi def link ia64data Type +hi def link ia64delimiter Delimiter +hi def link ia64operator Operator +hi def link ia64Todo Todo - delcommand HiLink -endif let b:current_syntax = "ia64" diff --git a/runtime/syntax/icemenu.vim b/runtime/syntax/icemenu.vim index d3a733d579..6513287dfc 100644 --- a/runtime/syntax/icemenu.vim +++ b/runtime/syntax/icemenu.vim @@ -6,10 +6,8 @@ " Comment: Icewm is a lightweight window manager. This adds syntax " highlighting when editing your user's menu file (~/.icewm/menu). -" clear existing syntax -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif diff --git a/runtime/syntax/icon.vim b/runtime/syntax/icon.vim index 1a73c43d8f..179d75cd28 100644 --- a/runtime/syntax/icon.vim +++ b/runtime/syntax/icon.vim @@ -4,11 +4,8 @@ " URL: ftp://ftp.halcyon.com/pub/users/wturner/icon.vim " Last Change: 2003 May 11 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -157,56 +154,46 @@ exec "syn sync ccomment iconComment minlines=" . icon_minlines " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting -if version >= 508 || !exists("did_icon_syn_inits") - if version < 508 - let did_icon_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - " The default methods for highlighting. Can be overridden later - - " HiLink iconSpecialCharacter iconSpecial - - HiLink iconOctalError iconError - HiLink iconParenError iconError - HiLink iconInParen iconError - HiLink iconCommentError iconError - HiLink iconSpaceError iconError - HiLink iconCommentError iconError - HiLink iconIncluded iconString - HiLink iconCommentString iconString - HiLink iconComment2String iconString - HiLink iconCommentSkip iconComment - - HiLink iconUserLabel Label - HiLink iconCharacter Character - HiLink iconNumber Number - HiLink iconRadix Number - HiLink iconFloat Float - HiLink iconInclude Include - HiLink iconPreProc PreProc - HiLink iconDefine Macro - HiLink iconError Error - HiLink iconStatement Statement - HiLink iconPreCondit PreCondit - HiLink iconString String - HiLink iconCset String - HiLink iconComment Comment - HiLink iconSpecial SpecialChar - HiLink iconTodo Todo - HiLink iconStorageClass StorageClass - HiLink iconFunction Statement - HiLink iconReserved Label - HiLink iconKeyword Operator - - "HiLink iconIdentifier Identifier - - delcommand HiLink -endif +" Only when an item doesn't have highlighting + +" The default methods for highlighting. Can be overridden later + +" hi def link iconSpecialCharacter iconSpecial + +hi def link iconOctalError iconError +hi def link iconParenError iconError +hi def link iconInParen iconError +hi def link iconCommentError iconError +hi def link iconSpaceError iconError +hi def link iconCommentError iconError +hi def link iconIncluded iconString +hi def link iconCommentString iconString +hi def link iconComment2String iconString +hi def link iconCommentSkip iconComment + +hi def link iconUserLabel Label +hi def link iconCharacter Character +hi def link iconNumber Number +hi def link iconRadix Number +hi def link iconFloat Float +hi def link iconInclude Include +hi def link iconPreProc PreProc +hi def link iconDefine Macro +hi def link iconError Error +hi def link iconStatement Statement +hi def link iconPreCondit PreCondit +hi def link iconString String +hi def link iconCset String +hi def link iconComment Comment +hi def link iconSpecial SpecialChar +hi def link iconTodo Todo +hi def link iconStorageClass StorageClass +hi def link iconFunction Statement +hi def link iconReserved Label +hi def link iconKeyword Operator + +"hi def link iconIdentifier Identifier + let b:current_syntax = "icon" diff --git a/runtime/syntax/idl.vim b/runtime/syntax/idl.vim index c51850b13a..6a4ce7e087 100644 --- a/runtime/syntax/idl.vim +++ b/runtime/syntax/idl.vim @@ -222,100 +222,98 @@ try if !exists("did_idl_syntax_inits") let did_idl_syntax_inits = 1 " The default methods for highlighting. Can be overridden later - command -nargs=+ HiLink hi def link <args> - - HiLink idlInclude Include - HiLink idlPreProc PreProc - HiLink idlPreCondit PreCondit - HiLink idlDefine Macro - HiLink idlIncluded String - HiLink idlString String - HiLink idlComment Comment - HiLink idlTodo Todo - HiLink idlLiteral Number - HiLink idlUuid Number - HiLink idlType Type - HiLink idlVariantType idlType - - HiLink idlModule Keyword - HiLink idlInterface Keyword - HiLink idlEnum Keyword - HiLink idlStruct Keyword - HiLink idlUnion Keyword - HiLink idlTypedef Keyword - HiLink idlException Keyword - HiLink idlTypedefOtherTypeQualifier keyword - - HiLink idlModuleName Typedef - HiLink idlInterfaceName Typedef - HiLink idlEnumName Typedef - HiLink idlStructName Typedef - HiLink idlUnionName Typedef - - HiLink idlBaseTypeInt idlType - HiLink idlBaseType idlType - HiLink idlSeqType idlType - HiLink idlD1 Paren - HiLink idlD2 Paren - HiLink idlD3 Paren - HiLink idlD4 Paren - "HiLink idlArraySize Paren - "HiLink idlArraySize1 Paren - HiLink idlModuleContent Paren - HiLink idlUnionContent Paren - HiLink idlStructContent Paren - HiLink idlEnumContents Paren - HiLink idlInterfaceContent Paren - - HiLink idlSimpDecl Identifier - HiLink idlROAttr StorageClass - HiLink idlAttr Keyword - HiLink idlConst StorageClass - - HiLink idlOneWayOp StorageClass - HiLink idlOp idlType - HiLink idlParmType idlType - HiLink idlOpName Function - HiLink idlOpParms SpecialComment - HiLink idlParmName Identifier - HiLink idlInheritFrom Identifier - HiLink idlAttribute SpecialComment - - HiLink idlId Constant - "HiLink idlCase Keyword - HiLink idlCaseLabel Constant - - HiLink idlErrorBracket Error - HiLink idlErrorBrace Error - HiLink idlErrorSquareBracket Error - - HiLink idlImport Keyword - HiLink idlImportString idlString - HiLink idlCoclassAttribute StorageClass - HiLink idlLibrary Keyword - HiLink idlImportlib Keyword - HiLink idlCoclass Keyword - HiLink idlLibraryName Typedef - HiLink idlCoclassName Typedef - " hi idlLibraryContent guifg=red - HiLink idlTypedefDecl Typedef - HiLink idlDefEnum Keyword - HiLink idlDefv1Enum Keyword - HiLink idlDefEnumName Typedef - HiLink idlDefEnumContents Paren - HiLink idlDefBaseTypeInt idlType - HiLink idlDefBaseType idlType - HiLink idlDefSeqType idlType - HiLink idlInterfaceSections Label + + hi def link idlInclude Include + hi def link idlPreProc PreProc + hi def link idlPreCondit PreCondit + hi def link idlDefine Macro + hi def link idlIncluded String + hi def link idlString String + hi def link idlComment Comment + hi def link idlTodo Todo + hi def link idlLiteral Number + hi def link idlUuid Number + hi def link idlType Type + hi def link idlVariantType idlType + + hi def link idlModule Keyword + hi def link idlInterface Keyword + hi def link idlEnum Keyword + hi def link idlStruct Keyword + hi def link idlUnion Keyword + hi def link idlTypedef Keyword + hi def link idlException Keyword + hi def link idlTypedefOtherTypeQualifier keyword + + hi def link idlModuleName Typedef + hi def link idlInterfaceName Typedef + hi def link idlEnumName Typedef + hi def link idlStructName Typedef + hi def link idlUnionName Typedef + + hi def link idlBaseTypeInt idlType + hi def link idlBaseType idlType + hi def link idlSeqType idlType + hi def link idlD1 Paren + hi def link idlD2 Paren + hi def link idlD3 Paren + hi def link idlD4 Paren + "hi def link idlArraySize Paren + "hi def link idlArraySize1 Paren + hi def link idlModuleContent Paren + hi def link idlUnionContent Paren + hi def link idlStructContent Paren + hi def link idlEnumContents Paren + hi def link idlInterfaceContent Paren + + hi def link idlSimpDecl Identifier + hi def link idlROAttr StorageClass + hi def link idlAttr Keyword + hi def link idlConst StorageClass + + hi def link idlOneWayOp StorageClass + hi def link idlOp idlType + hi def link idlParmType idlType + hi def link idlOpName Function + hi def link idlOpParms SpecialComment + hi def link idlParmName Identifier + hi def link idlInheritFrom Identifier + hi def link idlAttribute SpecialComment + + hi def link idlId Constant + "hi def link idlCase Keyword + hi def link idlCaseLabel Constant + + hi def link idlErrorBracket Error + hi def link idlErrorBrace Error + hi def link idlErrorSquareBracket Error + + hi def link idlImport Keyword + hi def link idlImportString idlString + hi def link idlCoclassAttribute StorageClass + hi def link idlLibrary Keyword + hi def link idlImportlib Keyword + hi def link idlCoclass Keyword + hi def link idlLibraryName Typedef + hi def link idlCoclassName Typedef + " hi def link idlLibraryContent guifg=red + hi def link idlTypedefDecl Typedef + hi def link idlDefEnum Keyword + hi def link idlDefv1Enum Keyword + hi def link idlDefEnumName Typedef + hi def link idlDefEnumContents Paren + hi def link idlDefBaseTypeInt idlType + hi def link idlDefBaseType idlType + hi def link idlDefSeqType idlType + hi def link idlInterfaceSections Label if exists("idlsyntax_showerror") if exists("idlsyntax_showerror_soft") hi default idlError guibg=#d0ffd0 else - HiLink idlError Error + hi def link idlError Error endif endif - delcommand HiLink endif let b:current_syntax = "idl" diff --git a/runtime/syntax/idlang.vim b/runtime/syntax/idlang.vim index 670d080a7d..14e976ce05 100644 --- a/runtime/syntax/idlang.vim +++ b/runtime/syntax/idlang.vim @@ -4,11 +4,8 @@ " Created by: Hermann Rochholz <Hermann.Rochholz AT gmx.de> " Remove any old syntax stuff hanging around -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -219,35 +216,25 @@ syn keyword idlangRoutine XSQ_TEST XSURFACE XVAREDIT XVOLUME XVOLUME_ROTATE syn keyword idlangRoutine XVOLUME_WRITE_IMAGE XYOUTS ZOOM ZOOM_24 " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_idlang_syn_inits") - if version < 508 - let did_idlang_syn_inits = 1 - command -nargs=+ HiLink hi link <args> -else - command -nargs=+ HiLink hi def link <args> -endif +" Only when an item doesn't have highlighting yet + +hi def link idlangConditional Conditional +hi def link idlangRoutine Type +hi def link idlangStatement Statement +hi def link idlangContinueLine Todo +hi def link idlangRealNumber Float +hi def link idlangNumber Number +hi def link idlangString String +hi def link idlangOperator Operator +hi def link idlangComment Comment +hi def link idlangTodo Todo +hi def link idlangPreCondit Identifier +hi def link idlangDblCommaError Error +hi def link idlangStop Error +hi def link idlangStrucvar PreProc +hi def link idlangSystem Identifier +hi def link idlangKeyword Special - HiLink idlangConditional Conditional - HiLink idlangRoutine Type - HiLink idlangStatement Statement - HiLink idlangContinueLine Todo - HiLink idlangRealNumber Float - HiLink idlangNumber Number - HiLink idlangString String - HiLink idlangOperator Operator - HiLink idlangComment Comment - HiLink idlangTodo Todo - HiLink idlangPreCondit Identifier - HiLink idlangDblCommaError Error - HiLink idlangStop Error - HiLink idlangStrucvar PreProc - HiLink idlangSystem Identifier - HiLink idlangKeyword Special - - delcommand HiLink -endif let b:current_syntax = "idlang" " vim: ts=18 diff --git a/runtime/syntax/inform.vim b/runtime/syntax/inform.vim index d8ba43dcee..e3e1b3e1f0 100644 --- a/runtime/syntax/inform.vim +++ b/runtime/syntax/inform.vim @@ -4,10 +4,8 @@ " URL: http://www.gowarthomas.com/informvim " Last Change: 2006 April 20 -" Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -294,13 +292,8 @@ endif " Handling for different versions of VIM. -if version >= 600 - setlocal iskeyword+=$ - command -nargs=+ SynDisplay syntax <args> display -else - set iskeyword+=$ - command -nargs=+ SynDisplay syntax <args> -endif +setlocal iskeyword+=$ +command -nargs=+ SynDisplay syntax <args> display " Grammar sections. @@ -347,61 +340,52 @@ syn sync maxlines=500 delcommand SynDisplay " The default highlighting. -if version >= 508 || !exists("did_inform_syn_inits") - if version < 508 - let did_inform_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink informDefine Define - HiLink informType Type - HiLink informInclude Include - HiLink informPreCondit PreCondit - HiLink informPreProc PreProc - HiLink informGramPreProc PreProc - HiLink informAsm Special - if !exists("inform_suppress_obsolete") - HiLink informAsmObsolete informError - HiLink informKeywordObsolete informError - else - HiLink informAsmObsolete Special - HiLink informKeywordObsolete Keyword - endif - HiLink informPredicate Operator - HiLink informSysFunc Identifier - HiLink informSysConst Identifier - HiLink informConditional Conditional - HiLink informRepeat Repeat - HiLink informStatement Statement - HiLink informOperator Operator - HiLink informKeyword Keyword - HiLink informGrammar Keyword - HiLink informDictString String - HiLink informNumber Number - HiLink informError Error - HiLink informString String - HiLink informComment Comment - HiLink informAccent Special - HiLink informStringUnicode Special - HiLink informStringCode Special - HiLink informTodo Todo - if !exists("inform_highlight_simple") - HiLink informLibAttrib Identifier - HiLink informLibProp Identifier - HiLink informLibObj Identifier - HiLink informLibRoutine Identifier - HiLink informLibVariable Identifier - HiLink informLibConst Identifier - HiLink informLibAction Identifier - endif - HiLink informBadDictString informError - HiLink informBadAccent informError - HiLink informBadStrUnicode informError - delcommand HiLink +hi def link informDefine Define +hi def link informType Type +hi def link informInclude Include +hi def link informPreCondit PreCondit +hi def link informPreProc PreProc +hi def link informGramPreProc PreProc +hi def link informAsm Special +if !exists("inform_suppress_obsolete") +hi def link informAsmObsolete informError +hi def link informKeywordObsolete informError +else +hi def link informAsmObsolete Special +hi def link informKeywordObsolete Keyword endif +hi def link informPredicate Operator +hi def link informSysFunc Identifier +hi def link informSysConst Identifier +hi def link informConditional Conditional +hi def link informRepeat Repeat +hi def link informStatement Statement +hi def link informOperator Operator +hi def link informKeyword Keyword +hi def link informGrammar Keyword +hi def link informDictString String +hi def link informNumber Number +hi def link informError Error +hi def link informString String +hi def link informComment Comment +hi def link informAccent Special +hi def link informStringUnicode Special +hi def link informStringCode Special +hi def link informTodo Todo +if !exists("inform_highlight_simple") +hi def link informLibAttrib Identifier +hi def link informLibProp Identifier +hi def link informLibObj Identifier +hi def link informLibRoutine Identifier +hi def link informLibVariable Identifier +hi def link informLibConst Identifier +hi def link informLibAction Identifier +endif +hi def link informBadDictString informError +hi def link informBadAccent informError +hi def link informBadStrUnicode informError + let b:current_syntax = "inform" diff --git a/runtime/syntax/inittab.vim b/runtime/syntax/inittab.vim index b7472f9e0f..82bf660105 100644 --- a/runtime/syntax/inittab.vim +++ b/runtime/syntax/inittab.vim @@ -6,12 +6,9 @@ " URL: http://physics.muni.cz/~yeti/download/syntax/inittab.vim " Setup -if version >= 600 - if exists("b:current_syntax") - finish - endif -else - syntax clear +" quit when a syntax file was already loaded +if exists("b:current_syntax") + finish endif syn case match @@ -45,31 +42,22 @@ syn match inittabProcessPlus "+" contained nextgroup=inittabProcess,inittabError syn region inittabProcess start="/" end="$" transparent oneline contained contains=@inittabSh,inittabComment " Define the default highlighting -if version >= 508 || !exists("did_inittab_syntax_inits") - if version < 508 - let did_inittab_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - HiLink inittabComment Comment - HiLink inittabFixme Todo - HiLink inittabActionName Type - HiLink inittabError Error - HiLink inittabId Identifier - HiLink inittabRunLevels Special +hi def link inittabComment Comment +hi def link inittabFixme Todo +hi def link inittabActionName Type +hi def link inittabError Error +hi def link inittabId Identifier +hi def link inittabRunLevels Special - HiLink inittabColonProcess inittabColon - HiLink inittabColonAction inittabColon - HiLink inittabColonRunLevels inittabColon - HiLink inittabColon PreProc +hi def link inittabColonProcess inittabColon +hi def link inittabColonAction inittabColon +hi def link inittabColonRunLevels inittabColon +hi def link inittabColon PreProc - HiLink inittabShString String - HiLink inittabShOption Special - HiLink inittabShCommand Statement +hi def link inittabShString String +hi def link inittabShOption Special +hi def link inittabShCommand Statement - delcommand HiLink -endif let b:current_syntax = "inittab" diff --git a/runtime/syntax/ipfilter.vim b/runtime/syntax/ipfilter.vim index db99812852..a7b7df2bac 100644 --- a/runtime/syntax/ipfilter.vim +++ b/runtime/syntax/ipfilter.vim @@ -9,11 +9,8 @@ " not correctly identified. " Please send comments to hendrik@scholz.net -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif diff --git a/runtime/syntax/ishd.vim b/runtime/syntax/ishd.vim index 1c011f1b92..3c468e361f 100644 --- a/runtime/syntax/ishd.vim +++ b/runtime/syntax/ishd.vim @@ -3,11 +3,8 @@ " Maintainer: Robert M. Cortopassi <cortopar@mindspring.com> " Last Change: 2001 May 09 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -387,35 +384,25 @@ syn cluster ishdPreProcGroup contains=ishdPreCondit,ishdIncluded,ishdInclude,ish syn region ishdDefine start="^\s*#\s*\(define\|undef\)\>" end="$" contains=ALLBUT,@ishdPreProcGroup " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_is_syntax_inits") - if version < 508 - let did_is_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink ishdNumber Number - HiLink ishdError Error - HiLink ishdStatement Statement - HiLink ishdString String - HiLink ishdComment Comment - HiLink ishdTodo Todo - HiLink ishdFunction Identifier - HiLink ishdConstant PreProc - HiLink ishdType Type - HiLink ishdInclude Include - HiLink ishdDefine Macro - HiLink ishdIncluded String - HiLink ishdPreCondit PreCondit - HiLink ishdHashIf0Skip ishdHashIf0 - HiLink ishdHashIf0End ishdHashIf0 - HiLink ishdHashIf0 Comment +hi def link ishdNumber Number +hi def link ishdError Error +hi def link ishdStatement Statement +hi def link ishdString String +hi def link ishdComment Comment +hi def link ishdTodo Todo +hi def link ishdFunction Identifier +hi def link ishdConstant PreProc +hi def link ishdType Type +hi def link ishdInclude Include +hi def link ishdDefine Macro +hi def link ishdIncluded String +hi def link ishdPreCondit PreCondit +hi def link ishdHashIf0Skip ishdHashIf0 +hi def link ishdHashIf0End ishdHashIf0 +hi def link ishdHashIf0 Comment - delcommand HiLink -endif let b:current_syntax = "ishd" diff --git a/runtime/syntax/iss.vim b/runtime/syntax/iss.vim index 26d9150b5a..e58c618b7f 100644 --- a/runtime/syntax/iss.vim +++ b/runtime/syntax/iss.vim @@ -9,11 +9,8 @@ " - Pascal scripting syntax is not recognized. " - Embedded double quotes confuse string matches. e.g. "asfd""asfa" -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -105,44 +102,34 @@ syn keyword issTasksFlags checkedonce dontinheritcheck exclusive restart uncheck " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_iss_syntax_inits") - if version < 508 - let did_iss_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - " The default methods for highlighting. Can be overridden later - HiLink issSection Special - HiLink issComment Comment - HiLink issDirective Type - HiLink issParam Type - HiLink issFolder Special - HiLink issString String - HiLink issURL Include - HiLink issPreProc PreProc - - HiLink issDirsFlags Keyword - HiLink issFilesCopyMode Keyword - HiLink issFilesAttribs Keyword - HiLink issFilesPermissions Keyword - HiLink issFilesFlags Keyword - HiLink issIconsFlags Keyword - HiLink issINIFlags Keyword - HiLink issRegRootKey Keyword - HiLink issRegValueType Keyword - HiLink issRegFlags Keyword - HiLink issRunFlags Keyword - HiLink issTypesFlags Keyword - HiLink issComponentsFlags Keyword - HiLink issInstallDeleteType Keyword - HiLink issTasksFlags Keyword - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +" The default methods for highlighting. Can be overridden later +hi def link issSection Special +hi def link issComment Comment +hi def link issDirective Type +hi def link issParam Type +hi def link issFolder Special +hi def link issString String +hi def link issURL Include +hi def link issPreProc PreProc + +hi def link issDirsFlags Keyword +hi def link issFilesCopyMode Keyword +hi def link issFilesAttribs Keyword +hi def link issFilesPermissions Keyword +hi def link issFilesFlags Keyword +hi def link issIconsFlags Keyword +hi def link issINIFlags Keyword +hi def link issRegRootKey Keyword +hi def link issRegValueType Keyword +hi def link issRegFlags Keyword +hi def link issRunFlags Keyword +hi def link issTypesFlags Keyword +hi def link issComponentsFlags Keyword +hi def link issInstallDeleteType Keyword +hi def link issTasksFlags Keyword + let b:current_syntax = "iss" diff --git a/runtime/syntax/ist.vim b/runtime/syntax/ist.vim index 131d833cbc..e34edac272 100644 --- a/runtime/syntax/ist.vim +++ b/runtime/syntax/ist.vim @@ -3,22 +3,15 @@ " Maintainer: Peter Meszaros <pmeszaros@effice.hu> " Last Change: 2012 Jan 08 by Thilo Six -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif let s:cpo_save = &cpo set cpo&vim -if version >= 600 - setlocal iskeyword=$,@,48-57,_ -else - set iskeyword=$,@,48-57,_ -endif +setlocal iskeyword=$,@,48-57,_ syn case ignore syn keyword IstInpSpec actual arg_close arg_open encap escape @@ -45,28 +38,18 @@ syn match IstSpecial "\\\\\|{\|}\|#\|\\n" contained syn match IstTodo "DEBUG\|TODO" contained " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_dummy_syn_inits") - if version < 508 - let did_dummy_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink IstInpSpec Type - HiLink IstOutSpec Identifier - HiLink IstString String - HiLink IstNumber Number - HiLink IstComment Comment - HiLink IstTodo Todo - HiLink IstSpecial Special - HiLink IstDoubleQuote Label - HiLink IstCharacter Label +" Only when an item doesn't have highlighting yet + +hi def link IstInpSpec Type +hi def link IstOutSpec Identifier +hi def link IstString String +hi def link IstNumber Number +hi def link IstComment Comment +hi def link IstTodo Todo +hi def link IstSpecial Special +hi def link IstDoubleQuote Label +hi def link IstCharacter Label - delcommand HiLink -endif let b:current_syntax = "ist" diff --git a/runtime/syntax/jal.vim b/runtime/syntax/jal.vim index d0ba672851..460bc01752 100644 --- a/runtime/syntax/jal.vim +++ b/runtime/syntax/jal.vim @@ -9,11 +9,8 @@ " " TODO test. -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -171,77 +168,67 @@ endif " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_jal_syn_inits") -if version < 508 - let did_jal_syn_inits = 1 - command -nargs=+ HiLink hi link <args> -else - command -nargs=+ HiLink hi def link <args> -endif +" Only when an item doesn't have highlighting yet + +hi def link jalAcces jalStatement +hi def link jalBoolean Boolean +hi def link jalBit Boolean +hi def link jalComment Comment +hi def link jalConditional Conditional +hi def link jalConstant Constant +hi def link jalDelimiter Identifier +hi def link jalDirective PreProc +hi def link jalException Exception +hi def link jalFloat Float +hi def link jalFunction Function +hi def link jalPsudoVarsKey Function +hi def link jalLabel Label +hi def link jalMatrixDelimiter Identifier +hi def link jalModifier Type +hi def link jalNumber Number +hi def link jalBinNumber Number +hi def link jalHexNumber Number +hi def link jalOperator Operator +hi def link jalPredefined Constant +hi def link jalPreProc PreProc +hi def link jalRepeat Repeat +hi def link jalStatement Statement +hi def link jalString String +hi def link jalStringEscape Special +hi def link jalStringEscapeGPC Special +hi def link jalStringError Error +hi def link jalStruct jalStatement +hi def link jalSymbolOperator jalOperator +hi def link jalTodo Todo +hi def link jalType Type +hi def link jalUnclassified Statement +hi def link jalAsm Assembler +hi def link jalError Error +hi def link jalAsmKey Statement +hi def link jalPIC Statement + +hi def link jalShowTab Error + +hi def link picTodo Todo +hi def link picComment Comment +hi def link picDirective Statement +hi def link picLabel Label +hi def link picString String + +hi def link picOpcode Keyword +hi def link picRegister Structure +hi def link picRegisterPart Special +hi def link picPinDir SPecial +hi def link picPortDir SPecial + +hi def link picASCII String +hi def link picBinary Number +hi def link picDecimal Number +hi def link picHexadecimal Number +hi def link picOctal Number + +hi def link picIdentifier Identifier - HiLink jalAcces jalStatement - HiLink jalBoolean Boolean - HiLink jalBit Boolean - HiLink jalComment Comment - HiLink jalConditional Conditional - HiLink jalConstant Constant - HiLink jalDelimiter Identifier - HiLink jalDirective PreProc - HiLink jalException Exception - HiLink jalFloat Float - HiLink jalFunction Function - HiLink jalPsudoVarsKey Function - HiLink jalLabel Label - HiLink jalMatrixDelimiter Identifier - HiLink jalModifier Type - HiLink jalNumber Number - HiLink jalBinNumber Number - HiLink jalHexNumber Number - HiLink jalOperator Operator - HiLink jalPredefined Constant - HiLink jalPreProc PreProc - HiLink jalRepeat Repeat - HiLink jalStatement Statement - HiLink jalString String - HiLink jalStringEscape Special - HiLink jalStringEscapeGPC Special - HiLink jalStringError Error - HiLink jalStruct jalStatement - HiLink jalSymbolOperator jalOperator - HiLink jalTodo Todo - HiLink jalType Type - HiLink jalUnclassified Statement - HiLink jalAsm Assembler - HiLink jalError Error - HiLink jalAsmKey Statement - HiLink jalPIC Statement - - HiLink jalShowTab Error - - HiLink picTodo Todo - HiLink picComment Comment - HiLink picDirective Statement - HiLink picLabel Label - HiLink picString String - - HiLink picOpcode Keyword - HiLink picRegister Structure - HiLink picRegisterPart Special - HiLink picPinDir SPecial - HiLink picPortDir SPecial - - HiLink picASCII String - HiLink picBinary Number - HiLink picDecimal Number - HiLink picHexadecimal Number - HiLink picOctal Number - - HiLink picIdentifier Identifier - - delcommand HiLink -endif let b:current_syntax = "jal" diff --git a/runtime/syntax/jam.vim b/runtime/syntax/jam.vim index cbd99bb9ce..fc7f49d1f0 100644 --- a/runtime/syntax/jam.vim +++ b/runtime/syntax/jam.vim @@ -3,22 +3,15 @@ " Maintainer: Ralf Lemke (ralflemk@t-online.de) " Last change: 2012 Jan 08 by Thilo Six -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif let s:cpo_save = &cpo set cpo&vim -if version >= 600 - setlocal iskeyword=@,48-57,_,- -else - set iskeyword=@,48-57,_,- -endif +setlocal iskeyword=@,48-57,_,- " A bunch of useful jam keywords syn keyword jamStatement break call dbms flush global include msg parms proc public receive return send unload vars @@ -167,88 +160,78 @@ syntax match jamCommentError "\*/" syntax match jamOperator3Error "*/" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_jam_syn_inits") - if version < 508 - let did_jam_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink jamCommentL jamComment - HiLink jamCommentL2 jamComment - HiLink jamOperator3Error jamError - HiLink jamConditional Conditional - HiLink jamRepeat Repeat - HiLink jamCharacter Character - HiLink jamSpecialCharacter jamSpecial - HiLink jamNumber Number - HiLink jamParenError jamError - HiLink jamErrInParen jamError - HiLink jamErrInBracket jamError - HiLink jamCommentError jamError - HiLink jamSpaceError jamError - HiLink jamSpecialError jamError - HiLink jamOperator1 jamOperator - HiLink jamOperator2 jamOperator - HiLink jamOperator3 jamOperator - HiLink jamOperator4 jamOperator - HiLink jamOperator5 jamOperator - HiLink jamOperator6 jamOperator - HiLink jamOperator7 jamOperator - HiLink jamOperator8 jamOperator - HiLink jamOperator9 jamOperator - HiLink jamOperator10 jamOperator - HiLink jamOperator11 jamOperator - HiLink jamOperator12 jamOperator - HiLink jamOperator13 jamOperator - HiLink jamOperator14 jamOperator - HiLink jamError Error - HiLink jamStatement Statement - HiLink jamPreCondit PreCondit - HiLink jamCommentError jamError - HiLink jamCommentString jamString - HiLink jamComment2String jamString - HiLink jamCommentSkip jamComment - HiLink jamString String - HiLink jamComment Comment - HiLink jamSpecial SpecialChar - HiLink jamTodo Todo - HiLink jamCppSkip jamCppOut - HiLink jamCppOut2 jamCppOut - HiLink jamCppOut Comment - HiLink jamDBState1 Identifier - HiLink jamDBState2 Identifier - HiLink jamSQLState1 jamSQL - HiLink jamSQLState2 jamSQL - HiLink jamLibFunc1 jamLibFunc - HiLink jamLibFunc2 jamLibFunc - HiLink jamLibFunc3 jamLibFunc - HiLink jamLibFunc4 jamLibFunc - HiLink jamLibFunc5 jamLibFunc - HiLink jamLibFunc6 jamLibFunc - HiLink jamLibFunc7 jamLibFunc - HiLink jamLibFunc8 jamLibFunc - HiLink jamLibFunc9 jamLibFunc - HiLink jamVariable1 jamVariablen - HiLink jamVariable2 jamVariablen - HiLink jamVariable3 jamVariablen - HiLink jamVariable4 jamVariablen - HiLink jamVariable5 jamVariablen - HiLink jamVariable6 jamVariablen - HiLink jamVariable7 jamVariablen - HiLink jamVariable8 jamVariablen - HiLink jamVariable9 jamVariablen - HiLink jamVariable10 jamVariablen - HiLink jamVariablen Constant - HiLink jamSQL Type - HiLink jamLibFunc PreProc - HiLink jamOperator Special - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link jamCommentL jamComment +hi def link jamCommentL2 jamComment +hi def link jamOperator3Error jamError +hi def link jamConditional Conditional +hi def link jamRepeat Repeat +hi def link jamCharacter Character +hi def link jamSpecialCharacter jamSpecial +hi def link jamNumber Number +hi def link jamParenError jamError +hi def link jamErrInParen jamError +hi def link jamErrInBracket jamError +hi def link jamCommentError jamError +hi def link jamSpaceError jamError +hi def link jamSpecialError jamError +hi def link jamOperator1 jamOperator +hi def link jamOperator2 jamOperator +hi def link jamOperator3 jamOperator +hi def link jamOperator4 jamOperator +hi def link jamOperator5 jamOperator +hi def link jamOperator6 jamOperator +hi def link jamOperator7 jamOperator +hi def link jamOperator8 jamOperator +hi def link jamOperator9 jamOperator +hi def link jamOperator10 jamOperator +hi def link jamOperator11 jamOperator +hi def link jamOperator12 jamOperator +hi def link jamOperator13 jamOperator +hi def link jamOperator14 jamOperator +hi def link jamError Error +hi def link jamStatement Statement +hi def link jamPreCondit PreCondit +hi def link jamCommentError jamError +hi def link jamCommentString jamString +hi def link jamComment2String jamString +hi def link jamCommentSkip jamComment +hi def link jamString String +hi def link jamComment Comment +hi def link jamSpecial SpecialChar +hi def link jamTodo Todo +hi def link jamCppSkip jamCppOut +hi def link jamCppOut2 jamCppOut +hi def link jamCppOut Comment +hi def link jamDBState1 Identifier +hi def link jamDBState2 Identifier +hi def link jamSQLState1 jamSQL +hi def link jamSQLState2 jamSQL +hi def link jamLibFunc1 jamLibFunc +hi def link jamLibFunc2 jamLibFunc +hi def link jamLibFunc3 jamLibFunc +hi def link jamLibFunc4 jamLibFunc +hi def link jamLibFunc5 jamLibFunc +hi def link jamLibFunc6 jamLibFunc +hi def link jamLibFunc7 jamLibFunc +hi def link jamLibFunc8 jamLibFunc +hi def link jamLibFunc9 jamLibFunc +hi def link jamVariable1 jamVariablen +hi def link jamVariable2 jamVariablen +hi def link jamVariable3 jamVariablen +hi def link jamVariable4 jamVariablen +hi def link jamVariable5 jamVariablen +hi def link jamVariable6 jamVariablen +hi def link jamVariable7 jamVariablen +hi def link jamVariable8 jamVariablen +hi def link jamVariable9 jamVariablen +hi def link jamVariable10 jamVariablen +hi def link jamVariablen Constant +hi def link jamSQL Type +hi def link jamLibFunc PreProc +hi def link jamOperator Special + let b:current_syntax = "jam" diff --git a/runtime/syntax/jargon.vim b/runtime/syntax/jargon.vim index 25a88bc981..415f2bc972 100644 --- a/runtime/syntax/jargon.vim +++ b/runtime/syntax/jargon.vim @@ -3,11 +3,8 @@ " Maintainer: <rms@poczta.onet.pl> " Last Change: 2001 May 26 " -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -17,20 +14,10 @@ syn match jargonUrl +\(http\|ftp\)://[^\t )"]*+ syn match jargonMark /{[^}]*}/ " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_jargon_syntax_inits") - if version < 508 - let did_jargon_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - HiLink jargonChaptTitle Title - HiLink jargonEmailAddr Comment - HiLink jargonUrl Comment - HiLink jargonMark Label - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet +hi def link jargonChaptTitle Title +hi def link jargonEmailAddr Comment +hi def link jargonUrl Comment +hi def link jargonMark Label let b:current_syntax = "jargon" diff --git a/runtime/syntax/java.vim b/runtime/syntax/java.vim index e113a904c3..89320597f1 100644 --- a/runtime/syntax/java.vim +++ b/runtime/syntax/java.vim @@ -6,11 +6,9 @@ " Please check :help java.vim for comments on some of the options available. -" Quit when a syntax file was already loaded +" quit when a syntax file was already loaded if !exists("main_syntax") - if version < 600 - syntax clear - elseif exists("b:current_syntax") + if exists("b:current_syntax") finish endif " we define it here so that included files can test for it @@ -21,13 +19,6 @@ endif let s:cpo_save = &cpo set cpo&vim -" don't use standard HiLink, it will not work with included syntax files -if version < 508 - command! -nargs=+ JavaHiLink hi link <args> -else - command! -nargs=+ JavaHiLink hi def link <args> -endif - " some characters that cannot be in a java program (outside a string) syn match javaError "[\\@`]" syn match javaError "<<<\|\.\.\|=>\|||=\|&&=\|\*\/" @@ -36,7 +27,7 @@ syn match javaOK "\.\.\." " use separate name so that it can be deleted in javacc.vim syn match javaError2 "#\|=<" -JavaHiLink javaError2 javaError +hi def link javaError2 javaError @@ -79,32 +70,32 @@ if exists("java_highlight_all") || exists("java_highlight_java") || exists("ja syn keyword javaR_JavaLang NegativeArraySizeException ArrayStoreException IllegalStateException RuntimeException IndexOutOfBoundsException UnsupportedOperationException ArrayIndexOutOfBoundsException ArithmeticException ClassCastException EnumConstantNotPresentException StringIndexOutOfBoundsException IllegalArgumentException IllegalMonitorStateException IllegalThreadStateException NumberFormatException NullPointerException TypeNotPresentException SecurityException syn cluster javaTop add=javaR_JavaLang syn cluster javaClasses add=javaR_JavaLang - JavaHiLink javaR_JavaLang javaR_Java + hi def link javaR_JavaLang javaR_Java syn keyword javaC_JavaLang Process RuntimePermission StringKeySet CharacterData01 Class ThreadLocal ThreadLocalMap CharacterData0E Package Character StringCoding Long ProcessImpl ProcessEnvironment Short AssertionStatusDirectives 1PackageInfoProxy UnicodeBlock InheritableThreadLocal AbstractStringBuilder StringEnvironment ClassLoader ConditionalSpecialCasing CharacterDataPrivateUse StringBuffer StringDecoder Entry StringEntry WrappedHook StringBuilder StrictMath State ThreadGroup Runtime CharacterData02 MethodArray Object CharacterDataUndefined Integer Gate Boolean Enum Variable Subset StringEncoder Void Terminator CharsetSD IntegerCache CharacterCache Byte CharsetSE Thread SystemClassLoaderAction CharacterDataLatin1 StringValues StackTraceElement Shutdown ShortCache String ConverterSD ByteCache Lock EnclosingMethodInfo Math Float Value Double SecurityManager LongCache ProcessBuilder StringEntrySet Compiler Number UNIXProcess ConverterSE ExternalData CaseInsensitiveComparator CharacterData00 NativeLibrary syn cluster javaTop add=javaC_JavaLang syn cluster javaClasses add=javaC_JavaLang - JavaHiLink javaC_JavaLang javaC_Java + hi def link javaC_JavaLang javaC_Java syn keyword javaE_JavaLang IncompatibleClassChangeError InternalError UnknownError ClassCircularityError AssertionError ThreadDeath IllegalAccessError NoClassDefFoundError ClassFormatError UnsupportedClassVersionError NoSuchFieldError VerifyError ExceptionInInitializerError InstantiationError LinkageError NoSuchMethodError Error UnsatisfiedLinkError StackOverflowError AbstractMethodError VirtualMachineError OutOfMemoryError syn cluster javaTop add=javaE_JavaLang syn cluster javaClasses add=javaE_JavaLang - JavaHiLink javaE_JavaLang javaE_Java + hi def link javaE_JavaLang javaE_Java syn keyword javaX_JavaLang CloneNotSupportedException Exception NoSuchMethodException IllegalAccessException NoSuchFieldException Throwable InterruptedException ClassNotFoundException InstantiationException syn cluster javaTop add=javaX_JavaLang syn cluster javaClasses add=javaX_JavaLang - JavaHiLink javaX_JavaLang javaX_Java + hi def link javaX_JavaLang javaX_Java - JavaHiLink javaR_Java javaR_ - JavaHiLink javaC_Java javaC_ - JavaHiLink javaE_Java javaE_ - JavaHiLink javaX_Java javaX_ - JavaHiLink javaX_ javaExceptions - JavaHiLink javaR_ javaExceptions - JavaHiLink javaE_ javaExceptions - JavaHiLink javaC_ javaConstant + hi def link javaR_Java javaR_ + hi def link javaC_Java javaC_ + hi def link javaE_Java javaE_ + hi def link javaX_Java javaX_ + hi def link javaX_ javaExceptions + hi def link javaR_ javaExceptions + hi def link javaE_ javaExceptions + hi def link javaC_ javaConstant syn keyword javaLangObject clone equals finalize getClass hashCode syn keyword javaLangObject notify notifyAll toString wait - JavaHiLink javaLangObject javaConstant + hi def link javaLangObject javaConstant syn cluster javaTop add=javaLangObject endif @@ -147,9 +138,9 @@ syn region javaComment start="/\*" end="\*/" contains=@javaCommentSpecial,ja syn match javaCommentStar contained "^\s*\*[^/]"me=e-1 syn match javaCommentStar contained "^\s*\*$" syn match javaLineComment "//.*" contains=@javaCommentSpecial2,javaTodo,@Spell -JavaHiLink javaCommentString javaString -JavaHiLink javaComment2String javaString -JavaHiLink javaCommentCharacter javaCharacter +hi def link javaCommentString javaString +hi def link javaComment2String javaString +hi def link javaCommentCharacter javaCharacter syn cluster javaTop add=javaComment,javaLineComment @@ -242,28 +233,26 @@ if exists("java_highlight_debug") syn cluster javaTop add=javaDebug - if version >= 508 || !exists("did_c_syn_inits") - JavaHiLink javaDebug Debug - JavaHiLink javaDebugString DebugString - JavaHiLink javaDebugStringError javaError - JavaHiLink javaDebugType DebugType - JavaHiLink javaDebugBoolean DebugBoolean - JavaHiLink javaDebugNumber Debug - JavaHiLink javaDebugSpecial DebugSpecial - JavaHiLink javaDebugSpecialCharacter DebugSpecial - JavaHiLink javaDebugCharacter DebugString - JavaHiLink javaDebugParen Debug - - JavaHiLink DebugString String - JavaHiLink DebugSpecial Special - JavaHiLink DebugBoolean Boolean - JavaHiLink DebugType Type - endif + hi def link javaDebug Debug + hi def link javaDebugString DebugString + hi def link javaDebugStringError javaError + hi def link javaDebugType DebugType + hi def link javaDebugBoolean DebugBoolean + hi def link javaDebugNumber Debug + hi def link javaDebugSpecial DebugSpecial + hi def link javaDebugSpecialCharacter DebugSpecial + hi def link javaDebugCharacter DebugString + hi def link javaDebugParen Debug + + hi def link DebugString String + hi def link DebugSpecial Special + hi def link DebugBoolean Boolean + hi def link DebugType Type endif if exists("java_mark_braces_in_parens_as_errors") syn match javaInParen contained "[{}]" - JavaHiLink javaInParen javaError + hi def link javaInParen javaError syn cluster javaTop add=javaInParen endif @@ -278,7 +267,7 @@ syn region javaParenT1 transparent matchgroup=javaParen1 start="\[" end="\]" co syn region javaParenT2 transparent matchgroup=javaParen2 start="\[" end="\]" contains=@javaTop,javaParenT contained syn match javaParenError "\]" -JavaHiLink javaParenError javaError +hi def link javaParenError javaError if exists("java_highlight_functions") syn match javaLambdaDef "([a-zA-Z0-9_<>\[\], \t]*)\s*->" @@ -291,61 +280,54 @@ endif exec "syn sync ccomment javaComment minlines=" . java_minlines " The default highlighting. -if version >= 508 || !exists("did_java_syn_inits") - if version < 508 - let did_java_syn_inits = 1 - endif - JavaHiLink javaLambdaDef Function - JavaHiLink javaFuncDef Function - JavaHiLink javaVarArg Function - JavaHiLink javaBraces Function - JavaHiLink javaBranch Conditional - JavaHiLink javaUserLabelRef javaUserLabel - JavaHiLink javaLabel Label - JavaHiLink javaUserLabel Label - JavaHiLink javaConditional Conditional - JavaHiLink javaRepeat Repeat - JavaHiLink javaExceptions Exception - JavaHiLink javaAssert Statement - JavaHiLink javaStorageClass StorageClass - JavaHiLink javaMethodDecl javaStorageClass - JavaHiLink javaClassDecl javaStorageClass - JavaHiLink javaScopeDecl javaStorageClass - JavaHiLink javaBoolean Boolean - JavaHiLink javaSpecial Special - JavaHiLink javaSpecialError Error - JavaHiLink javaSpecialCharError Error - JavaHiLink javaString String - JavaHiLink javaCharacter Character - JavaHiLink javaSpecialChar SpecialChar - JavaHiLink javaNumber Number - JavaHiLink javaError Error - JavaHiLink javaStringError Error - JavaHiLink javaStatement Statement - JavaHiLink javaOperator Operator - JavaHiLink javaComment Comment - JavaHiLink javaDocComment Comment - JavaHiLink javaLineComment Comment - JavaHiLink javaConstant Constant - JavaHiLink javaTypedef Typedef - JavaHiLink javaTodo Todo - JavaHiLink javaAnnotation PreProc - - JavaHiLink javaCommentTitle SpecialComment - JavaHiLink javaDocTags Special - JavaHiLink javaDocParam Function - JavaHiLink javaDocSeeTagParam Function - JavaHiLink javaCommentStar javaComment - - JavaHiLink javaType Type - JavaHiLink javaExternal Include - - JavaHiLink htmlComment Special - JavaHiLink htmlCommentPart Special - JavaHiLink javaSpaceError Error -endif - -delcommand JavaHiLink +hi def link javaLambdaDef Function +hi def link javaFuncDef Function +hi def link javaVarArg Function +hi def link javaBraces Function +hi def link javaBranch Conditional +hi def link javaUserLabelRef javaUserLabel +hi def link javaLabel Label +hi def link javaUserLabel Label +hi def link javaConditional Conditional +hi def link javaRepeat Repeat +hi def link javaExceptions Exception +hi def link javaAssert Statement +hi def link javaStorageClass StorageClass +hi def link javaMethodDecl javaStorageClass +hi def link javaClassDecl javaStorageClass +hi def link javaScopeDecl javaStorageClass +hi def link javaBoolean Boolean +hi def link javaSpecial Special +hi def link javaSpecialError Error +hi def link javaSpecialCharError Error +hi def link javaString String +hi def link javaCharacter Character +hi def link javaSpecialChar SpecialChar +hi def link javaNumber Number +hi def link javaError Error +hi def link javaStringError Error +hi def link javaStatement Statement +hi def link javaOperator Operator +hi def link javaComment Comment +hi def link javaDocComment Comment +hi def link javaLineComment Comment +hi def link javaConstant Constant +hi def link javaTypedef Typedef +hi def link javaTodo Todo +hi def link javaAnnotation PreProc + +hi def link javaCommentTitle SpecialComment +hi def link javaDocTags Special +hi def link javaDocParam Function +hi def link javaDocSeeTagParam Function +hi def link javaCommentStar javaComment + +hi def link javaType Type +hi def link javaExternal Include + +hi def link htmlComment Special +hi def link htmlCommentPart Special +hi def link javaSpaceError Error let b:current_syntax = "java" diff --git a/runtime/syntax/javacc.vim b/runtime/syntax/javacc.vim index 5458de754e..a80572d510 100644 --- a/runtime/syntax/javacc.vim +++ b/runtime/syntax/javacc.vim @@ -7,11 +7,8 @@ " Uses java.vim, and adds a few special things for JavaCC Parser files. " Those files usually have the extension *.jj -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -19,11 +16,7 @@ let s:cpo_save = &cpo set cpo&vim " source the java.vim file -if version < 600 - source <sfile>:p:h/java.vim -else - runtime! syntax/java.vim -endif +runtime! syntax/java.vim unlet b:current_syntax "remove catching errors caused by wrong parenthesis (does not work in javacc @@ -58,22 +51,12 @@ syn keyword javaccActionToken TOKEN SKIP MORE SPECIAL_TOKEN syn keyword javaccError DEBUG IGNORE_IN_BNF " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_css_syn_inits") - if version < 508 - let did_css_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - HiLink javaccSpecToken Statement - HiLink javaccActionToken Type - HiLink javaccPackages javaScopeDecl - HiLink javaccToken String - HiLink javaccError Error - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet +hi def link javaccSpecToken Statement +hi def link javaccActionToken Type +hi def link javaccPackages javaScopeDecl +hi def link javaccToken String +hi def link javaccError Error let b:current_syntax = "javacc" let &cpo = s:cpo_save diff --git a/runtime/syntax/javascript.vim b/runtime/syntax/javascript.vim index 1b20f987d9..9589b1938f 100644 --- a/runtime/syntax/javascript.vim +++ b/runtime/syntax/javascript.vim @@ -10,15 +10,12 @@ " Last Change: 2012 Oct 05 " 2013 Jun 12: adjusted javaScriptRegexpString (Kevin Locke) -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded " tuning parameters: " unlet javaScript_fold if !exists("main_syntax") - if version < 600 - syntax clear - elseif exists("b:current_syntax") + " quit when a syntax file was already loaded + if exists("b:current_syntax") finish endif let main_syntax = 'javascript' @@ -29,11 +26,6 @@ endif let s:cpo_save = &cpo set cpo&vim -" Drop fold if it set but vim doesn't support it. -if version < 600 && exists("javaScript_fold") - unlet javaScript_fold -endif - syn keyword javaScriptCommentTodo TODO FIXME XXX TBD contained syn match javaScriptLineComment "\/\/.*" contains=@Spell,javaScriptCommentTodo @@ -87,51 +79,41 @@ if main_syntax == "javascript" endif " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_javascript_syn_inits") - if version < 508 - let did_javascript_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - HiLink javaScriptComment Comment - HiLink javaScriptLineComment Comment - HiLink javaScriptCommentTodo Todo - HiLink javaScriptSpecial Special - HiLink javaScriptStringS String - HiLink javaScriptStringD String - HiLink javaScriptCharacter Character - HiLink javaScriptSpecialCharacter javaScriptSpecial - HiLink javaScriptNumber javaScriptValue - HiLink javaScriptConditional Conditional - HiLink javaScriptRepeat Repeat - HiLink javaScriptBranch Conditional - HiLink javaScriptOperator Operator - HiLink javaScriptType Type - HiLink javaScriptStatement Statement - HiLink javaScriptFunction Function - HiLink javaScriptBraces Function - HiLink javaScriptError Error - HiLink javaScrParenError javaScriptError - HiLink javaScriptNull Keyword - HiLink javaScriptBoolean Boolean - HiLink javaScriptRegexpString String - - HiLink javaScriptIdentifier Identifier - HiLink javaScriptLabel Label - HiLink javaScriptException Exception - HiLink javaScriptMessage Keyword - HiLink javaScriptGlobal Keyword - HiLink javaScriptMember Keyword - HiLink javaScriptDeprecated Exception - HiLink javaScriptReserved Keyword - HiLink javaScriptDebug Debug - HiLink javaScriptConstant Label - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet +hi def link javaScriptComment Comment +hi def link javaScriptLineComment Comment +hi def link javaScriptCommentTodo Todo +hi def link javaScriptSpecial Special +hi def link javaScriptStringS String +hi def link javaScriptStringD String +hi def link javaScriptCharacter Character +hi def link javaScriptSpecialCharacter javaScriptSpecial +hi def link javaScriptNumber javaScriptValue +hi def link javaScriptConditional Conditional +hi def link javaScriptRepeat Repeat +hi def link javaScriptBranch Conditional +hi def link javaScriptOperator Operator +hi def link javaScriptType Type +hi def link javaScriptStatement Statement +hi def link javaScriptFunction Function +hi def link javaScriptBraces Function +hi def link javaScriptError Error +hi def link javaScrParenError javaScriptError +hi def link javaScriptNull Keyword +hi def link javaScriptBoolean Boolean +hi def link javaScriptRegexpString String + +hi def link javaScriptIdentifier Identifier +hi def link javaScriptLabel Label +hi def link javaScriptException Exception +hi def link javaScriptMessage Keyword +hi def link javaScriptGlobal Keyword +hi def link javaScriptMember Keyword +hi def link javaScriptDeprecated Exception +hi def link javaScriptReserved Keyword +hi def link javaScriptDebug Debug +hi def link javaScriptConstant Label + let b:current_syntax = "javascript" if main_syntax == 'javascript' diff --git a/runtime/syntax/jess.vim b/runtime/syntax/jess.vim index 243bab351e..67d3715a30 100644 --- a/runtime/syntax/jess.vim +++ b/runtime/syntax/jess.vim @@ -4,19 +4,12 @@ " Last change: September 14, 2000 " Based on lisp.vim by : Dr. Charles E. Campbell, Jr. -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif -if version < 600 - set iskeyword=42,43,45,47-58,60-62,64-90,97-122,_ -else - setlocal iskeyword=42,43,45,47-58,60-62,64-90,97-122,_ -endif +setlocal iskeyword=42,43,45,47-58,60-62,64-90,97-122,_ " Lists syn match jessSymbol ![^()'`,"; \t]\+! contained @@ -125,36 +118,26 @@ syn match jessComment ";.*$" syn sync lines=100 " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_jess_syntax_inits") - if version < 508 - let did_jess_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink jessAtomNmbr jessNumber - HiLink jessAtomMark jessMark - - HiLink jessAtom Identifier - HiLink jessAtomBarSymbol Special - HiLink jessBarSymbol Special - HiLink jessComment Comment - HiLink jessConcat Statement - HiLink jessDeclaration Statement - HiLink jessFunc Statement - HiLink jessKey Type - HiLink jessMark Delimiter - HiLink jessNumber Number - HiLink jessParenError Error - HiLink jessSpecial Type - HiLink jessString String - HiLink jessVar Identifier - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link jessAtomNmbr jessNumber +hi def link jessAtomMark jessMark + +hi def link jessAtom Identifier +hi def link jessAtomBarSymbol Special +hi def link jessBarSymbol Special +hi def link jessComment Comment +hi def link jessConcat Statement +hi def link jessDeclaration Statement +hi def link jessFunc Statement +hi def link jessKey Type +hi def link jessMark Delimiter +hi def link jessNumber Number +hi def link jessParenError Error +hi def link jessSpecial Type +hi def link jessString String +hi def link jessVar Identifier + let b:current_syntax = "jess" diff --git a/runtime/syntax/jgraph.vim b/runtime/syntax/jgraph.vim index 7ecd5afaec..a29a21a73b 100644 --- a/runtime/syntax/jgraph.vim +++ b/runtime/syntax/jgraph.vim @@ -5,11 +5,8 @@ " this syntax file is not yet complete -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -36,23 +33,13 @@ syn match jgraphNumber "\-\=\.\d\+\>" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_jgraph_syn_inits") - if version < 508 - let did_jgraph_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink jgraphComment Comment - HiLink jgraphCmd Identifier - HiLink jgraphType Type - HiLink jgraphNumber Number - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link jgraphComment Comment +hi def link jgraphCmd Identifier +hi def link jgraphType Type +hi def link jgraphNumber Number + let b:current_syntax = "jgraph" diff --git a/runtime/syntax/jproperties.vim b/runtime/syntax/jproperties.vim index 9343bd292b..628c03097f 100644 --- a/runtime/syntax/jproperties.vim +++ b/runtime/syntax/jproperties.vim @@ -43,11 +43,8 @@ endif " ============================================================================= -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -120,28 +117,18 @@ syn match jpropertiesComment "^\s*[#!].*$" contains=jpropertiesTODO syn keyword jpropertiesTodo TODO FIXME XXX contained " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_jproperties_syntax_inits") - if version < 508 - let did_jproperties_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink jpropertiesComment Comment - HiLink jpropertiesTodo Todo - HiLink jpropertiesIdentifier Identifier - HiLink jpropertiesString String - HiLink jpropertiesExtendString String - HiLink jpropertiesCharacter Character - HiLink jpropertiesSpecial Special - HiLink jpropertiesSpecialChar SpecialChar - HiLink jpropertiesError Error - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link jpropertiesComment Comment +hi def link jpropertiesTodo Todo +hi def link jpropertiesIdentifier Identifier +hi def link jpropertiesString String +hi def link jpropertiesExtendString String +hi def link jpropertiesCharacter Character +hi def link jpropertiesSpecial Special +hi def link jpropertiesSpecialChar SpecialChar +hi def link jpropertiesError Error + let b:current_syntax = "jproperties" diff --git a/runtime/syntax/json.vim b/runtime/syntax/json.vim index 1fdfea2d09..d80af84312 100644 --- a/runtime/syntax/json.vim +++ b/runtime/syntax/json.vim @@ -5,9 +5,8 @@ " Version: 0.12 if !exists("main_syntax") - if version < 600 - syntax clear - elseif exists("b:current_syntax") + " quit when a syntax file was already loaded + if exists("b:current_syntax") finish endif let main_syntax = 'json' @@ -93,39 +92,29 @@ syn region jsonFold matchgroup=jsonBraces start="{" end=/}\(\_s\+\ze\("\|{\)\)\ syn region jsonFold matchgroup=jsonBraces start="\[" end=/]\(\_s\+\ze"\)\@!/ transparent fold " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_json_syn_inits") - if version < 508 - let did_json_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - HiLink jsonPadding Operator - HiLink jsonString String - HiLink jsonTest Label - HiLink jsonEscape Special - HiLink jsonNumber Number - HiLink jsonBraces Delimiter - HiLink jsonNull Function - HiLink jsonBoolean Boolean - HiLink jsonKeyword Label - - if (!exists("g:vim_json_warnings") || g:vim_json_warnings==1) - HiLink jsonNumError Error - HiLink jsonCommentError Error - HiLink jsonSemicolonError Error - HiLink jsonTrailingCommaError Error - HiLink jsonMissingCommaError Error - HiLink jsonStringSQError Error - HiLink jsonNoQuotesError Error - HiLink jsonTripleQuotesError Error - endif - HiLink jsonQuote Quote - HiLink jsonNoise Noise - delcommand HiLink +" Only when an item doesn't have highlighting yet +hi def link jsonPadding Operator +hi def link jsonString String +hi def link jsonTest Label +hi def link jsonEscape Special +hi def link jsonNumber Number +hi def link jsonBraces Delimiter +hi def link jsonNull Function +hi def link jsonBoolean Boolean +hi def link jsonKeyword Label + +if (!exists("g:vim_json_warnings") || g:vim_json_warnings==1) +hi def link jsonNumError Error +hi def link jsonCommentError Error +hi def link jsonSemicolonError Error +hi def link jsonTrailingCommaError Error +hi def link jsonMissingCommaError Error +hi def link jsonStringSQError Error +hi def link jsonNoQuotesError Error +hi def link jsonTripleQuotesError Error endif +hi def link jsonQuote Quote +hi def link jsonNoise Noise let b:current_syntax = "json" if main_syntax == 'json' diff --git a/runtime/syntax/jsp.vim b/runtime/syntax/jsp.vim index 9766657596..1c3cc35a31 100644 --- a/runtime/syntax/jsp.vim +++ b/runtime/syntax/jsp.vim @@ -6,11 +6,8 @@ " Credits : Patch by Darren Greaves (recognizes <jsp:...> tags) " Patch by Thomas Kimpton (recognizes jspExpr inside HTML tags) -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -19,11 +16,7 @@ if !exists("main_syntax") endif " Source HTML syntax -if version < 600 - source <sfile>:p:h/html.vim -else - runtime! syntax/html.vim -endif +runtime! syntax/html.vim unlet b:current_syntax " Next syntax items are case-sensitive @@ -52,29 +45,19 @@ syn clear htmlTag syn region htmlTag start=+<[^/%]+ end=+>+ contains=htmlTagN,htmlString,htmlArg,htmlValue,htmlTagError,htmlEvent,htmlCssDefinition,@htmlPreproc,@htmlArgCluster,jspExpr,javaScript " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_jsp_syn_inits") - if version < 508 - let did_jsp_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - " java.vim has redefined htmlComment highlighting - HiLink htmlComment Comment - HiLink htmlCommentPart Comment - " Be consistent with html highlight settings - HiLink jspComment htmlComment - HiLink jspTag htmlTag - HiLink jspDirective jspTag - HiLink jspDirName htmlTagName - HiLink jspDirArg htmlArg - HiLink jspCommand jspTag - HiLink jspCommandName htmlTagName - HiLink jspCommandArg htmlArg - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet +" java.vim has redefined htmlComment highlighting +hi def link htmlComment Comment +hi def link htmlCommentPart Comment +" Be consistent with html highlight settings +hi def link jspComment htmlComment +hi def link jspTag htmlTag +hi def link jspDirective jspTag +hi def link jspDirName htmlTagName +hi def link jspDirArg htmlArg +hi def link jspCommand jspTag +hi def link jspCommandName htmlTagName +hi def link jspCommandArg htmlArg if main_syntax == 'jsp' unlet main_syntax diff --git a/runtime/syntax/kix.vim b/runtime/syntax/kix.vim index 800e286042..8efe02baee 100644 --- a/runtime/syntax/kix.vim +++ b/runtime/syntax/kix.vim @@ -19,10 +19,8 @@ " Work out how to error too many "(", i.e. (() should be an error. " Similarly, "if" without "endif" and similar constructs should error. -" Clear legacy syntax rules for version 5.x, exit if already processed for version 6+ -if version < 600 - syn clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -130,52 +128,42 @@ syn match kixExpression "<\|>\|<=\|>=\|<>" " Default highlighting. -" Version < 5.8 set default highlight if file not already processed. -" Version >= 5.8 set default highlight only if it doesn't already have a value. -if version > 508 || !exists("did_kix_syn_inits") - if version < 508 - let did_kix_syn_inits=1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink kixDoubleString String - HiLink kixSingleString String - HiLink kixStatement Statement - HiLink kixRepeat Repeat - HiLink kixComment Comment - HiLink kixBuiltin Function - HiLink kixLocalVar Special - HiLink kixMacro Special - HiLink kixEnvVar Special - HiLink kixLabel Type - HiLink kixFunction Function - HiLink kixInteger Number - HiLink kixHex Number - HiLink kixFloat Number - HiLink kixOperator Operator - HiLink kixExpression Operator - - HiLink kixParenCloseError Error - HiLink kixBrackCloseError Error - HiLink kixStringError Error - - HiLink kixWhileError Error - HiLink kixWhileOK Conditional - HiLink kixDoError Error - HiLink kixDoOK Conditional - HiLink kixIfError Error - HiLink kixIfOK Conditional - HiLink kixSelectError Error - HiLink kixSelectOK Conditional - HiLink kixForNextError Error - HiLink kixForNextOK Conditional - HiLink kixForEachError Error - HiLink kixForEachOK Conditional - - delcommand HiLink -endif +" Set default highlight only if it doesn't already have a value. + +hi def link kixDoubleString String +hi def link kixSingleString String +hi def link kixStatement Statement +hi def link kixRepeat Repeat +hi def link kixComment Comment +hi def link kixBuiltin Function +hi def link kixLocalVar Special +hi def link kixMacro Special +hi def link kixEnvVar Special +hi def link kixLabel Type +hi def link kixFunction Function +hi def link kixInteger Number +hi def link kixHex Number +hi def link kixFloat Number +hi def link kixOperator Operator +hi def link kixExpression Operator + +hi def link kixParenCloseError Error +hi def link kixBrackCloseError Error +hi def link kixStringError Error + +hi def link kixWhileError Error +hi def link kixWhileOK Conditional +hi def link kixDoError Error +hi def link kixDoOK Conditional +hi def link kixIfError Error +hi def link kixIfOK Conditional +hi def link kixSelectError Error +hi def link kixSelectOK Conditional +hi def link kixForNextError Error +hi def link kixForNextOK Conditional +hi def link kixForEachError Error +hi def link kixForEachOK Conditional + let b:current_syntax = "kix" diff --git a/runtime/syntax/kscript.vim b/runtime/syntax/kscript.vim index cefbe39a29..e6776208d4 100644 --- a/runtime/syntax/kscript.vim +++ b/runtime/syntax/kscript.vim @@ -4,11 +4,8 @@ " URL: http://aquila.rezel.enst.fr/thomas/vim/kscript.vim " CVS: $Id: kscript.vim,v 1.1 2004/06/13 17:40:02 vimboss Exp $ -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -37,33 +34,23 @@ syn region kscriptString start=+"""+ end=+"""+ syn region kscriptString start=+'''+ end=+'''+ " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_kscript_syntax_inits") - if version < 508 - let did_kscript_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet + +hi def link kscriptConditional Conditional +hi def link kscriptRepeat Repeat +hi def link kscriptExceptions Statement +hi def link kscriptFunction Function +hi def link kscriptConst Constant +hi def link kscriptStatement Statement +hi def link kscriptLabel Label +hi def link kscriptStorageClass StorageClass +hi def link kscriptType Type +hi def link kscriptTodo Todo +hi def link kscriptComment Comment +hi def link kscriptString String +hi def link kscriptPreCondit PreCondit +hi def link kscriptHardCoded Statement - HiLink kscriptConditional Conditional - HiLink kscriptRepeat Repeat - HiLink kscriptExceptions Statement - HiLink kscriptFunction Function - HiLink kscriptConst Constant - HiLink kscriptStatement Statement - HiLink kscriptLabel Label - HiLink kscriptStorageClass StorageClass - HiLink kscriptType Type - HiLink kscriptTodo Todo - HiLink kscriptComment Comment - HiLink kscriptString String - HiLink kscriptPreCondit PreCondit - HiLink kscriptHardCoded Statement - - delcommand HiLink -endif let b:current_syntax = "kscript" diff --git a/runtime/syntax/kwt.vim b/runtime/syntax/kwt.vim index 4c2c9d9dc0..ecda5bb985 100644 --- a/runtime/syntax/kwt.vim +++ b/runtime/syntax/kwt.vim @@ -3,21 +3,14 @@ " Maintainer: Michael Piefel <entwurf@piefel.de> " Last Change: 2 May 2001 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif " Read the C++ syntax to start with -if version < 600 - source <sfile>:p:h/cpp.vim -else - runtime! syntax/cpp.vim - unlet b:current_syntax -endif +runtime! syntax/cpp.vim +unlet b:current_syntax " kimwitu++ extentions @@ -58,27 +51,17 @@ syn region kwtUnpBody transparent keepend extend fold start="->\s*\[" start="^\ syn region kwtRewBody transparent keepend extend fold start="->\s*<" start="^\s*<" end="\s>\s\=;\=$" end="^>\s\=;\=$" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_kwt_syn_inits") - if version < 508 - let did_kwt_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink kwtStatement cppStatement - HiLink kwtDecl cppStatement - HiLink kwtCast cppStatement - HiLink kwtSep Delimiter - HiLink kwtViews Label - HiLink kwtPhylum Type - HiLink kwtOption PreProc - "HiLink cText Comment - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link kwtStatement cppStatement +hi def link kwtDecl cppStatement +hi def link kwtCast cppStatement +hi def link kwtSep Delimiter +hi def link kwtViews Label +hi def link kwtPhylum Type +hi def link kwtOption PreProc +"hi def link cText Comment + syn sync lines=300 diff --git a/runtime/syntax/lace.vim b/runtime/syntax/lace.vim index 9e64eea7d1..9a83851f2b 100644 --- a/runtime/syntax/lace.vim +++ b/runtime/syntax/lace.vim @@ -9,11 +9,8 @@ " it to the maintainer at <utilities@eiffel.com> -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -85,50 +82,40 @@ syn region laceParen transparent start="(" end=")" contains=ALLBUT,laceParenErr syn sync lines=40 " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_lace_syntax_inits") - if version < 508 - let did_lace_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink laceTopStruct PreProc - - HiLink laceOptionClause Statement - HiLink laceOptionMark Constant - HiLink laceClusterProp Label - HiLink laceAdaptClassName Label - HiLink laceExternal Statement - HiLink laceCluster ModeMsg - - HiLink laceEscape Special - - HiLink laceBool Boolean - HiLink laceString String - HiLink laceCharacter Character - HiLink laceClassName Type - HiLink laceNumber Number - - HiLink laceOperator Special - HiLink laceArray Special - HiLink laceExport Special - HiLink laceCreation Special - HiLink laceBrackets Special - HiLink laceConstraint Special - - HiLink laceComment Comment - - HiLink laceError Error - HiLink laceStringError Error - HiLink laceParenError Error - HiLink laceBracketError Error - HiLink laceTodo Todo - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link laceTopStruct PreProc + +hi def link laceOptionClause Statement +hi def link laceOptionMark Constant +hi def link laceClusterProp Label +hi def link laceAdaptClassName Label +hi def link laceExternal Statement +hi def link laceCluster ModeMsg + +hi def link laceEscape Special + +hi def link laceBool Boolean +hi def link laceString String +hi def link laceCharacter Character +hi def link laceClassName Type +hi def link laceNumber Number + +hi def link laceOperator Special +hi def link laceArray Special +hi def link laceExport Special +hi def link laceCreation Special +hi def link laceBrackets Special +hi def link laceConstraint Special + +hi def link laceComment Comment + +hi def link laceError Error +hi def link laceStringError Error +hi def link laceParenError Error +hi def link laceBracketError Error +hi def link laceTodo Todo + let b:current_syntax = "lace" diff --git a/runtime/syntax/latte.vim b/runtime/syntax/latte.vim index e2a8729f3f..e30ae42e38 100644 --- a/runtime/syntax/latte.vim +++ b/runtime/syntax/latte.vim @@ -7,11 +7,8 @@ " I based this on the TeX and Scheme syntax files (but mostly scheme). " See http://www.latte.org for info on the language. -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -20,11 +17,7 @@ syn match latteOther "\\{" syn match latteOther "\\}" syn match latteOther "\\\\" -if version < 600 - set iskeyword=33,43,45,48-57,63,65-90,95,97-122,_ -else - setlocal iskeyword=33,43,45,48-57,63,65-90,95,97-122,_ -endif +setlocal iskeyword=33,43,45,48-57,63,65-90,95,97-122,_ syn region latteVar matchgroup=SpecialChar start=!\\[A-Za-z_]!rs=s+1 end=![^A-Za-z0-9?!+_-]!me=e-1 contains=ALLBUT,latteNumber,latteOther syn region latteVar matchgroup=SpecialChar start=!\\[=\&][A-Za-z_]!rs=s+2 end=![^A-Za-z0-9?!+_-]!me=e-1 contains=ALLBUT,latteNumber,latteOther @@ -70,29 +63,19 @@ syn sync match matchPlace grouphere NONE "^[^ \t]" " ... i.e. synchronize on a line that starts at the left margin " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_latte_syntax_inits") - if version < 508 - let did_latte_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink latteSyntax Statement - HiLink latteVar Function +hi def link latteSyntax Statement +hi def link latteVar Function - HiLink latteString String - HiLink latteQuote String +hi def link latteString String +hi def link latteQuote String - HiLink latteDelimiter Delimiter - HiLink latteOperator Operator +hi def link latteDelimiter Delimiter +hi def link latteOperator Operator - HiLink latteComment Comment - HiLink latteError Error +hi def link latteComment Comment +hi def link latteError Error - delcommand HiLink -endif let b:current_syntax = "latte" diff --git a/runtime/syntax/ldif.vim b/runtime/syntax/ldif.vim index 9f67b57f51..576e4c023d 100644 --- a/runtime/syntax/ldif.vim +++ b/runtime/syntax/ldif.vim @@ -3,9 +3,8 @@ " Maintainer: Zak Johnson <zakj@nox.cx> " Last Change: 2003-12-30 -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -21,23 +20,14 @@ syn region ldifFileValue matchgroup=ldifPunctuation start=/:< / end=/\_$/ skip syn region ldifComment start=/^#/ end=/\_$/ skip=/\n / -if version >= 508 || !exists("did_ldif_syn_inits") - if version < 508 - let did_ldif_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink ldifAttribute Type - HiLink ldifOption Identifier - HiLink ldifPunctuation Normal - HiLink ldifStringValue String - HiLink ldifBase64Value Special - HiLink ldifFileValue Special - HiLink ldifComment Comment - - delcommand HiLink -endif + +hi def link ldifAttribute Type +hi def link ldifOption Identifier +hi def link ldifPunctuation Normal +hi def link ldifStringValue String +hi def link ldifBase64Value Special +hi def link ldifFileValue Special +hi def link ldifComment Comment + let b:current_syntax = "ldif" diff --git a/runtime/syntax/lex.vim b/runtime/syntax/lex.vim index b7aff34d6b..560aa44be3 100644 --- a/runtime/syntax/lex.vim +++ b/runtime/syntax/lex.vim @@ -1,18 +1,15 @@ " Vim syntax file " Language: Lex " Maintainer: Charles E. Campbell <NdrOchipS@PcampbellAfamily.Mbiz> -" Last Change: Nov 14, 2012 -" Version: 14 -" URL: http://mysite.verizon.net/astronaut/vim/index.html#vimlinks_syntax +" Last Change: Aug 31, 2016 +" Version: 16 +" URL: http://mysite.verizon.net/astronaut/vim/index.html#SYNTAX_LEX " " Option: " lex_uses_cpp : if this variable exists, then C++ is loaded rather than C -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -122,22 +119,24 @@ syn sync match lexSyncPat groupthere lexPatBlock "^<$" syn sync match lexSyncPat groupthere lexPatBlock "^%%$" " The default highlighting. -hi def link lexAbbrvComment lexPatComment -hi def link lexAbbrvRegExp Macro -hi def link lexAbbrv SpecialChar -hi def link lexBrace lexPat -hi def link lexCFunctions Function -hi def link lexCstruct cStructure -hi def link lexMorePat SpecialChar -hi def link lexOptions PreProc -hi def link lexPatComment Comment -hi def link lexPat Function -hi def link lexPatString Function -hi def link lexPatTag Special -hi def link lexPatTagZone lexPatTag -hi def link lexSep Delimiter -hi def link lexSlashQuote lexPat -hi def link lexStartState Statement +if !exists("skip_lex_syntax_inits") + hi def link lexAbbrvComment lexPatComment + hi def link lexAbbrvRegExp Macro + hi def link lexAbbrv SpecialChar + hi def link lexBrace lexPat + hi def link lexCFunctions Function + hi def link lexCstruct cStructure + hi def link lexMorePat SpecialChar + hi def link lexOptions PreProc + hi def link lexPatComment Comment + hi def link lexPat Function + hi def link lexPatString Function + hi def link lexPatTag Special + hi def link lexPatTagZone lexPatTag + hi def link lexSep Delimiter + hi def link lexSlashQuote lexPat + hi def link lexStartState Statement +endif let b:current_syntax = "lex" diff --git a/runtime/syntax/lhaskell.vim b/runtime/syntax/lhaskell.vim index 077549a0c8..0a8a076ff4 100644 --- a/runtime/syntax/lhaskell.vim +++ b/runtime/syntax/lhaskell.vim @@ -36,11 +36,8 @@ " -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -84,15 +81,10 @@ endif " If user wants us to highlight TeX syntax or guess thinks it's TeX, read it. if b:lhs_markup == "tex" - if version < 600 - source <sfile>:p:h/tex.vim - set isk+=_ - else - runtime! syntax/tex.vim - unlet b:current_syntax - " Tex.vim removes "_" from 'iskeyword', but we need it for Haskell. - setlocal isk+=_ - endif + runtime! syntax/tex.vim + unlet b:current_syntax + " Tex.vim removes "_" from 'iskeyword', but we need it for Haskell. + setlocal isk+=_ syntax cluster lhsTeXContainer contains=tex.*Zone,texAbstract else syntax cluster lhsTeXContainer contains=.* @@ -100,11 +92,7 @@ endif " Literate Haskell is Haskell in between text, so at least read Haskell " highlighting -if version < 600 - syntax include @haskellTop <sfile>:p:h/haskell.vim -else - syntax include @haskellTop syntax/haskell.vim -endif +syntax include @haskellTop syntax/haskell.vim syntax region lhsHaskellBirdTrack start="^>" end="\%(^[^>]\)\@=" contains=@haskellTop,lhsBirdTrack containedin=@lhsTeXContainer syntax region lhsHaskellBeginEndBlock start="^\\begin{code}\s*$" matchgroup=NONE end="\%(^\\end{code}.*$\)\@=" contains=@haskellTop,beginCodeBegin containedin=@lhsTeXContainer @@ -115,23 +103,13 @@ syntax match beginCodeBegin "^\\begin" nextgroup=beginCodeCode contained syntax region beginCodeCode matchgroup=texDelimiter start="{" end="}" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_tex_syntax_inits") - if version < 508 - let did_tex_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink lhsBirdTrack Comment - - HiLink beginCodeBegin texCmdName - HiLink beginCodeCode texSection - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link lhsBirdTrack Comment + +hi def link beginCodeBegin texCmdName +hi def link beginCodeCode texSection + " Restore cursor to original position, as it may have been disturbed " by the searches in our guessing code diff --git a/runtime/syntax/lifelines.vim b/runtime/syntax/lifelines.vim index f8bea015bd..ff4692888e 100644 --- a/runtime/syntax/lifelines.vim +++ b/runtime/syntax/lifelines.vim @@ -11,9 +11,8 @@ " For version 5.x: Clear all syntax items " For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -110,9 +109,7 @@ syn match lifelinesNumber "-\=\<\d\+\.\d*\>" syn match lifelinesNumber "-\=\.\d\+\>" " folding using {} -if version >= 600 - syn region lifelinesFoldBlock start="{" end="}" transparent fold -endif +syn region lifelinesFoldBlock start="{" end="}" transparent fold "catch errors caused by wrong parenthesis "adapted from original c.vim written by Bram Moolenaar @@ -123,44 +120,34 @@ syn match lifelinesParenError ")" syn match lifelinesErrInParen contained "[{}]" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet - -if version >= 508 || !exists("did_lifelines_syn_inits") - if version < 508 - let did_lifelines_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink lifelinesConditional Conditional - HiLink lifelinesArithm Operator - HiLink lifelinesLogical Conditional - HiLink lifelinesInclude Include - HiLink lifelinesComment Comment - HiLink lifelinesStatement Statement - HiLink lifelinesUser Statement - HiLink lifelinesFunct Statement - HiLink lifelinesTable Statement - HiLink lifelinesGedcom Statement - HiLink lifelinesList Statement - HiLink lifelinesRepeat Repeat - HiLink lifelinesFam Statement - HiLink lifelinesIndi Statement - HiLink lifelinesProc Statement - HiLink lifelinesDef Statement - HiLink lifelinesString String - HiLink lifelinesSpecial Special - HiLink lifelinesNumber Number - HiLink lifelinesParenError Error - HiLink lifelinesErrInParen Error - HiLink lifelinesError Error - HiLink lifelinesTodo Todo - HiLink lifelinesDecl PreProc - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + + +hi def link lifelinesConditional Conditional +hi def link lifelinesArithm Operator +hi def link lifelinesLogical Conditional +hi def link lifelinesInclude Include +hi def link lifelinesComment Comment +hi def link lifelinesStatement Statement +hi def link lifelinesUser Statement +hi def link lifelinesFunct Statement +hi def link lifelinesTable Statement +hi def link lifelinesGedcom Statement +hi def link lifelinesList Statement +hi def link lifelinesRepeat Repeat +hi def link lifelinesFam Statement +hi def link lifelinesIndi Statement +hi def link lifelinesProc Statement +hi def link lifelinesDef Statement +hi def link lifelinesString String +hi def link lifelinesSpecial Special +hi def link lifelinesNumber Number +hi def link lifelinesParenError Error +hi def link lifelinesErrInParen Error +hi def link lifelinesError Error +hi def link lifelinesTodo Todo +hi def link lifelinesDecl PreProc + let b:current_syntax = "lifelines" diff --git a/runtime/syntax/lilo.vim b/runtime/syntax/lilo.vim index 3e9459267b..a87dafb734 100644 --- a/runtime/syntax/lilo.vim +++ b/runtime/syntax/lilo.vim @@ -5,21 +5,12 @@ " Last Change: 2010-02-03 " Setup -if version >= 600 - if exists("b:current_syntax") - finish - endif -else - syntax clear +" quit when a syntax file was already loaded +if exists("b:current_syntax") + finish endif -if version >= 600 - command -nargs=1 SetIsk setlocal iskeyword=<args> -else - command -nargs=1 SetIsk set iskeyword=<args> -endif -SetIsk @,48-57,.,-,_ -delcommand SetIsk +setlocal iskeyword=@,48-57,.,-,_ syn case ignore @@ -128,65 +119,56 @@ syn match liloDecNumberPListComment "#.*$" contained nextgroup=liloDecNumberPLis syn match liloAnythingComment "#.*$" contained nextgroup=liloAnything,liloAnythingComment,liloError skipwhite skipempty " Define the default highlighting -if version >= 508 || !exists("did_lilo_syntax_inits") - if version < 508 - let did_lilo_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink liloEqPath liloEquals - HiLink liloEqWord liloEquals - HiLink liloEqVga liloEquals - HiLink liloEqDecNumber liloEquals - HiLink liloEqHexNumber liloEquals - HiLink liloEqNumber liloEquals - HiLink liloEqString liloEquals - HiLink liloEqAnything liloEquals - HiLink liloEquals Special - - HiLink liloError Error - - HiLink liloEqPathComment liloComment - HiLink liloEqVgaComment liloComment - HiLink liloEqDecNumberComment liloComment - HiLink liloEqHexNumberComment liloComment - HiLink liloEqStringComment liloComment - HiLink liloEqAnythingComment liloComment - HiLink liloPathComment liloComment - HiLink liloVgaComment liloComment - HiLink liloDecNumberComment liloComment - HiLink liloHexNumberComment liloComment - HiLink liloNumberComment liloComment - HiLink liloStringComment liloComment - HiLink liloAnythingComment liloComment - HiLink liloComment Comment - - HiLink liloDiskOpt liloOption - HiLink liloKernelOpt liloOption - HiLink liloImageOpt liloOption - HiLink liloOption Keyword - - HiLink liloDecNumber liloNumber - HiLink liloHexNumber liloNumber - HiLink liloDecNumberP liloNumber - HiLink liloNumber Number - HiLink liloString String - HiLink liloPath Constant - - HiLink liloSpecial Special - HiLink liloLabel Title - HiLink liloDecNumberList Special - HiLink liloDecNumberPList Special - HiLink liloAnything Normal - HiLink liloEnviron Identifier - HiLink liloVgaKeyword Identifier - HiLink liloImage Type - HiLink liloChRules Preproc - HiLink liloDisk Preproc - - delcommand HiLink -endif + +hi def link liloEqPath liloEquals +hi def link liloEqWord liloEquals +hi def link liloEqVga liloEquals +hi def link liloEqDecNumber liloEquals +hi def link liloEqHexNumber liloEquals +hi def link liloEqNumber liloEquals +hi def link liloEqString liloEquals +hi def link liloEqAnything liloEquals +hi def link liloEquals Special + +hi def link liloError Error + +hi def link liloEqPathComment liloComment +hi def link liloEqVgaComment liloComment +hi def link liloEqDecNumberComment liloComment +hi def link liloEqHexNumberComment liloComment +hi def link liloEqStringComment liloComment +hi def link liloEqAnythingComment liloComment +hi def link liloPathComment liloComment +hi def link liloVgaComment liloComment +hi def link liloDecNumberComment liloComment +hi def link liloHexNumberComment liloComment +hi def link liloNumberComment liloComment +hi def link liloStringComment liloComment +hi def link liloAnythingComment liloComment +hi def link liloComment Comment + +hi def link liloDiskOpt liloOption +hi def link liloKernelOpt liloOption +hi def link liloImageOpt liloOption +hi def link liloOption Keyword + +hi def link liloDecNumber liloNumber +hi def link liloHexNumber liloNumber +hi def link liloDecNumberP liloNumber +hi def link liloNumber Number +hi def link liloString String +hi def link liloPath Constant + +hi def link liloSpecial Special +hi def link liloLabel Title +hi def link liloDecNumberList Special +hi def link liloDecNumberPList Special +hi def link liloAnything Normal +hi def link liloEnviron Identifier +hi def link liloVgaKeyword Identifier +hi def link liloImage Type +hi def link liloChRules Preproc +hi def link liloDisk Preproc + let b:current_syntax = "lilo" diff --git a/runtime/syntax/lisp.vim b/runtime/syntax/lisp.vim index a402452389..b02eb09d0a 100644 --- a/runtime/syntax/lisp.vim +++ b/runtime/syntax/lisp.vim @@ -2,7 +2,7 @@ " Language: Lisp " Maintainer: Charles E. Campbell <NdrOchipS@PcampbellAfamily.Mbiz> " Last Change: May 02, 2016 -" Version: 25 +" Version: 26 " URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_LISP " " Thanks to F Xavier Noria for a list of 978 Common Lisp symbols taken from HyperSpec @@ -561,31 +561,28 @@ syn sync lines=100 " --------------------------------------------------------------------- " Define Highlighting: {{{1 -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 - command -nargs=+ HiLink hi def link <args> +if !exists("skip_lisp_syntax_inits") - HiLink lispCommentRegion lispComment - HiLink lispAtomNmbr lispNumber - HiLink lispAtomMark lispMark - HiLink lispInStringString lispString + hi def link lispCommentRegion lispComment + hi def link lispAtomNmbr lispNumber + hi def link lispAtomMark lispMark + hi def link lispInStringString lispString - HiLink lispAtom Identifier - HiLink lispAtomBarSymbol Special - HiLink lispBarSymbol Special - HiLink lispComment Comment - HiLink lispConcat Statement - HiLink lispDecl Statement - HiLink lispFunc Statement - HiLink lispKey Type - HiLink lispMark Delimiter - HiLink lispNumber Number - HiLink lispParenError Error - HiLink lispEscapeSpecial Type - HiLink lispString String - HiLink lispTodo Todo - HiLink lispVar Statement + hi def link lispAtom Identifier + hi def link lispAtomBarSymbol Special + hi def link lispBarSymbol Special + hi def link lispComment Comment + hi def link lispConcat Statement + hi def link lispDecl Statement + hi def link lispFunc Statement + hi def link lispKey Type + hi def link lispMark Delimiter + hi def link lispNumber Number + hi def link lispParenError Error + hi def link lispEscapeSpecial Type + hi def link lispString String + hi def link lispTodo Todo + hi def link lispVar Statement if exists("g:lisp_rainbow") && g:lisp_rainbow != 0 if &bg == "dark" @@ -613,7 +610,6 @@ if version >= 508 endif endif - delcommand HiLink endif let b:current_syntax = "lisp" diff --git a/runtime/syntax/lite.vim b/runtime/syntax/lite.vim index 8abc51dea1..a8d26892d4 100644 --- a/runtime/syntax/lite.vim +++ b/runtime/syntax/lite.vim @@ -8,11 +8,8 @@ " Options lite_sql_query = 1 for SQL syntax highligthing inside strings " lite_minlines = x to sync at least x lines backwards -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -138,39 +135,29 @@ if main_syntax == 'lite' endif " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_lite_syn_inits") - if version < 508 - let did_lite_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet + +hi def link liteComment Comment +hi def link liteString String +hi def link liteNumber Number +hi def link liteFloat Float +hi def link liteIdentifier Identifier +hi def link liteGlobalIdentifier Identifier +hi def link liteIntVar Identifier +hi def link liteFunctions Function +hi def link liteRepeat Repeat +hi def link liteConditional Conditional +hi def link liteStatement Statement +hi def link liteType Type +hi def link liteInclude Include +hi def link liteDefine Define +hi def link liteSpecialChar SpecialChar +hi def link liteParentError liteError +hi def link liteError Error +hi def link liteTodo Todo +hi def link liteOperator Operator +hi def link liteRelation Operator - HiLink liteComment Comment - HiLink liteString String - HiLink liteNumber Number - HiLink liteFloat Float - HiLink liteIdentifier Identifier - HiLink liteGlobalIdentifier Identifier - HiLink liteIntVar Identifier - HiLink liteFunctions Function - HiLink liteRepeat Repeat - HiLink liteConditional Conditional - HiLink liteStatement Statement - HiLink liteType Type - HiLink liteInclude Include - HiLink liteDefine Define - HiLink liteSpecialChar SpecialChar - HiLink liteParentError liteError - HiLink liteError Error - HiLink liteTodo Todo - HiLink liteOperator Operator - HiLink liteRelation Operator - - delcommand HiLink -endif let b:current_syntax = "lite" diff --git a/runtime/syntax/logtalk.vim b/runtime/syntax/logtalk.vim index be34c7ed74..532f83d3bf 100644 --- a/runtime/syntax/logtalk.vim +++ b/runtime/syntax/logtalk.vim @@ -5,11 +5,8 @@ " Last Change: February 4, 2012 -" Quit when a syntax file was already loaded: - -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -389,59 +386,47 @@ syn sync ccomment logtalkBlockComment maxlines=50 " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet - -if version >= 508 || !exists("did_logtalk_syn_inits") - if version < 508 - let did_logtalk_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink logtalkBlockComment Comment - HiLink logtalkLineComment Comment +hi def link logtalkBlockComment Comment +hi def link logtalkLineComment Comment - HiLink logtalkOpenEntityDir Normal - HiLink logtalkOpenEntityDirTag PreProc +hi def link logtalkOpenEntityDir Normal +hi def link logtalkOpenEntityDirTag PreProc - HiLink logtalkIfContainer PreProc - HiLink logtalkIf PreProc - HiLink logtalkElseIf PreProc - HiLink logtalkElse PreProc +hi def link logtalkIfContainer PreProc +hi def link logtalkIf PreProc +hi def link logtalkElseIf PreProc +hi def link logtalkElse PreProc - HiLink logtalkEntity Normal +hi def link logtalkEntity Normal - HiLink logtalkEntityRel Normal - HiLink logtalkEntityRelTag PreProc +hi def link logtalkEntityRel Normal +hi def link logtalkEntityRelTag PreProc - HiLink logtalkCloseEntityDir PreProc +hi def link logtalkCloseEntityDir PreProc - HiLink logtalkDir Normal - HiLink logtalkDirTag PreProc +hi def link logtalkDir Normal +hi def link logtalkDirTag PreProc - HiLink logtalkAtom String - HiLink logtalkString String - HiLink logtalkEscapeSequence SpecialChar +hi def link logtalkAtom String +hi def link logtalkString String +hi def link logtalkEscapeSequence SpecialChar - HiLink logtalkNumber Number +hi def link logtalkNumber Number - HiLink logtalkKeyword Keyword +hi def link logtalkKeyword Keyword - HiLink logtalkBuiltIn Keyword - HiLink logtalkBuiltInMethod Keyword +hi def link logtalkBuiltIn Keyword +hi def link logtalkBuiltInMethod Keyword - HiLink logtalkOperator Operator +hi def link logtalkOperator Operator - HiLink logtalkExtCall Normal - HiLink logtalkExtCallTag Operator +hi def link logtalkExtCall Normal +hi def link logtalkExtCallTag Operator - HiLink logtalkVariable Identifier +hi def link logtalkVariable Identifier - delcommand HiLink - -endif let b:current_syntax = "logtalk" diff --git a/runtime/syntax/lotos.vim b/runtime/syntax/lotos.vim index 3cd83c4d86..8262e1d9ef 100644 --- a/runtime/syntax/lotos.vim +++ b/runtime/syntax/lotos.vim @@ -7,11 +7,8 @@ " I'm not sure I understand all of the syntax highlight language, " but this file seems to do the job for standard LOTOS. -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -56,26 +53,16 @@ syn keyword lotosType using syn sync lines=250 " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_lotos_syntax_inits") - if version < 508 - let did_lotos_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink lotosStatement Statement - HiLink lotosProcess Label - HiLink lotosOperator Operator - HiLink lotosSort Function - HiLink lotosType Type - HiLink lotosComment Comment - HiLink lotosDelimiter String +hi def link lotosStatement Statement +hi def link lotosProcess Label +hi def link lotosOperator Operator +hi def link lotosSort Function +hi def link lotosType Type +hi def link lotosComment Comment +hi def link lotosDelimiter String - delcommand HiLink -endif let b:current_syntax = "lotos" diff --git a/runtime/syntax/lout.vim b/runtime/syntax/lout.vim index 9a34328ac3..30c87fce51 100644 --- a/runtime/syntax/lout.vim +++ b/runtime/syntax/lout.vim @@ -16,11 +16,8 @@ " See the discussion at http://thread.gmane.org/gmane.editors.vim.devel/32151 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -36,11 +33,7 @@ syn sync lines=1000 " Characters allowed in keywords " I don't know if 128-255 are allowed in ANS-FORHT -if version >= 600 - setlocal iskeyword=@,48-57,.,@-@,_,192-255 -else - set iskeyword=@,48-57,.,@-@,_,192-255 -endif +setlocal iskeyword=@,48-57,.,@-@,_,192-255 " Some special keywords syn keyword loutTodo contained TODO lout Lout LOUT @@ -106,44 +99,33 @@ syn region loutBoldItalic matchgroup=loutBIBraces start='@BI\s*{' matchgroup=lou syn region loutHeadings matchgroup=loutHeads start='@\(\(Title\)\|\(Caption\)\)\s*{' matchgroup=loutHeads end='}' contains=ALLBUT,loutBraceError " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_lout_syn_inits") - if version < 508 - let did_lout_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - " The default methods for highlighting. Can be overrriden later. - HiLink loutTodo Todo - HiLink loutDefine Define - HiLink loutEOmlDef Define - HiLink loutFunction Function - HiLink loutBraceError Error - HiLink loutNULL Special - HiLink loutComment Comment - HiLink loutSpecial Special - HiLink loutSymbols Character - HiLink loutInclude Include - HiLink loutKeyword Keyword - HiLink loutTag Tag - HiLink loutMath Number - - " HiLink Not really needed here, but I think it is more consistent. - HiLink loutMBraces loutMath - hi loutItalic term=italic cterm=italic gui=italic - HiLink loutIBraces loutItalic - hi loutBold term=bold cterm=bold gui=bold - HiLink loutBBraces loutBold - hi loutBoldItalic term=bold,italic cterm=bold,italic gui=bold,italic - HiLink loutBIBraces loutBoldItalic - hi loutHeadings term=bold cterm=bold guifg=indianred - HiLink loutHeads loutHeadings - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +" The default methods for highlighting. Can be overrriden later. +hi def link loutTodo Todo +hi def link loutDefine Define +hi def link loutEOmlDef Define +hi def link loutFunction Function +hi def link loutBraceError Error +hi def link loutNULL Special +hi def link loutComment Comment +hi def link loutSpecial Special +hi def link loutSymbols Character +hi def link loutInclude Include +hi def link loutKeyword Keyword +hi def link loutTag Tag +hi def link loutMath Number + +hi def link loutMBraces loutMath +hi loutItalic term=italic cterm=italic gui=italic +hi def link loutIBraces loutItalic +hi loutBold term=bold cterm=bold gui=bold +hi def link loutBBraces loutBold +hi loutBoldItalic term=bold,italic cterm=bold,italic gui=bold,italic +hi def link loutBIBraces loutBoldItalic +hi loutHeadings term=bold cterm=bold guifg=indianred +hi def link loutHeads loutHeadings + let b:current_syntax = "lout" diff --git a/runtime/syntax/lpc.vim b/runtime/syntax/lpc.vim index e948f3d70c..7d85fce8e2 100644 --- a/runtime/syntax/lpc.vim +++ b/runtime/syntax/lpc.vim @@ -2,18 +2,15 @@ " Language: LPC " Maintainer: Shizhu Pan <poet@mudbuilder.net> " URL: http://poet.tomud.com/pub/lpc.vim.bz2 -" Last Change: 2011 Dec 10 by Thilo Six +" Last Change: 2016 Aug 31 " Comments: If you are using Vim 6.2 or later, see :h lpc.vim for " file type recognizing, if not, you had to use modeline. " Nodule: This is the start nodule. {{{1 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -360,94 +357,84 @@ endif " Nodule: Highlight links {{{1 " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_lpc_syn_inits") - if version < 508 - let did_lpc_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet + +hi def link lpcModifier lpcStorageClass + +hi def link lpcQuotedFmt lpcFormat +hi def link lpcFormat lpcSpecial +hi def link lpcCppString lpcString " Cpp means + " C Pre-Processor +hi def link lpcCommentL lpcComment +hi def link lpcCommentStart lpcComment +hi def link lpcUserLabel lpcLabel +hi def link lpcSpecialCharacter lpcSpecial +hi def link lpcOctal lpcPreProc +hi def link lpcOctalZero lpcSpecial " LPC will treat octal numbers + " as decimals, programmers should + " be aware of that. +hi def link lpcEfunError lpcError +hi def link lpcKeywdError lpcError +hi def link lpcOctalError lpcError +hi def link lpcParenError lpcError +hi def link lpcErrInParen lpcError +hi def link lpcErrInBracket lpcError +hi def link lpcCommentError lpcError +hi def link lpcCommentStartError lpcError +hi def link lpcSpaceError lpcError +hi def link lpcSpecialError lpcError +hi def link lpcErrFunc lpcError - HiLink lpcModifier lpcStorageClass - - HiLink lpcQuotedFmt lpcFormat - HiLink lpcFormat lpcSpecial - HiLink lpcCppString lpcString " Cpp means - " C Pre-Processor - HiLink lpcCommentL lpcComment - HiLink lpcCommentStart lpcComment - HiLink lpcUserLabel lpcLabel - HiLink lpcSpecialCharacter lpcSpecial - HiLink lpcOctal lpcPreProc - HiLink lpcOctalZero lpcSpecial " LPC will treat octal numbers - " as decimals, programmers should - " be aware of that. - HiLink lpcEfunError lpcError - HiLink lpcKeywdError lpcError - HiLink lpcOctalError lpcError - HiLink lpcParenError lpcError - HiLink lpcErrInParen lpcError - HiLink lpcErrInBracket lpcError - HiLink lpcCommentError lpcError - HiLink lpcCommentStartError lpcError - HiLink lpcSpaceError lpcError - HiLink lpcSpecialError lpcError - HiLink lpcErrFunc lpcError - - if exists("lpc_pre_v22") - HiLink lpcOldEfuns lpc_efuns - HiLink lpcNewEfuns lpcError - else - HiLink lpcOldEfuns lpcReserved - HiLink lpcNewEfuns lpc_efuns - endif - HiLink lpc_efuns lpcFunction - - HiLink lpcReserved lpcPreProc - HiLink lpcTextString lpcString " This should be preprocessors, but - HiLink lpcArrayString lpcPreProc " let's make some difference - " between text and array - - HiLink lpcIncluded lpcString - HiLink lpcCommentString lpcString - HiLink lpcComment2String lpcString - HiLink lpcCommentSkip lpcComment - HiLink lpcCommentFunc lpcComment - - HiLink lpcCppSkip lpcCppOut - HiLink lpcCppOut2 lpcCppOut - HiLink lpcCppOut lpcComment - - " Standard type below - HiLink lpcApplies Special - HiLink lpcCharacter Character - HiLink lpcComment Comment - HiLink lpcConditional Conditional - HiLink lpcConstant Constant - HiLink lpcDefine Macro - HiLink lpcError Error - HiLink lpcFloat Float - HiLink lpcFunction Function - HiLink lpcIdentifier Identifier - HiLink lpcInclude Include - HiLink lpcLabel Label - HiLink lpcNumber Number - HiLink lpcOperator Operator - HiLink lpcPreCondit PreCondit - HiLink lpcPreProc PreProc - HiLink lpcRepeat Repeat - HiLink lpcStatement Statement - HiLink lpcStorageClass StorageClass - HiLink lpcString String - HiLink lpcStructure Structure - HiLink lpcSpecial LineNr - HiLink lpcTodo Todo - HiLink lpcType Type - - delcommand HiLink +if exists("lpc_pre_v22") + hi def link lpcOldEfuns lpc_efuns + hi def link lpcNewEfuns lpcError +else + hi def link lpcOldEfuns lpcReserved + hi def link lpcNewEfuns lpc_efuns endif +hi def link lpc_efuns lpcFunction + +hi def link lpcReserved lpcPreProc +hi def link lpcTextString lpcString " This should be preprocessors, but +hi def link lpcArrayString lpcPreProc " let's make some difference + " between text and array + +hi def link lpcIncluded lpcString +hi def link lpcCommentString lpcString +hi def link lpcComment2String lpcString +hi def link lpcCommentSkip lpcComment +hi def link lpcCommentFunc lpcComment + +hi def link lpcCppSkip lpcCppOut +hi def link lpcCppOut2 lpcCppOut +hi def link lpcCppOut lpcComment + +" Standard type below +hi def link lpcApplies Special +hi def link lpcCharacter Character +hi def link lpcComment Comment +hi def link lpcConditional Conditional +hi def link lpcConstant Constant +hi def link lpcDefine Macro +hi def link lpcError Error +hi def link lpcFloat Float +hi def link lpcFunction Function +hi def link lpcIdentifier Identifier +hi def link lpcInclude Include +hi def link lpcLabel Label +hi def link lpcNumber Number +hi def link lpcOperator Operator +hi def link lpcPreCondit PreCondit +hi def link lpcPreProc PreProc +hi def link lpcRepeat Repeat +hi def link lpcStatement Statement +hi def link lpcStorageClass StorageClass +hi def link lpcString String +hi def link lpcStructure Structure +hi def link lpcSpecial LineNr +hi def link lpcTodo Todo +hi def link lpcType Type + " Nodule: This is the end nodule. {{{1 diff --git a/runtime/syntax/lprolog.vim b/runtime/syntax/lprolog.vim index 086c00fd5d..85c3537fed 100644 --- a/runtime/syntax/lprolog.vim +++ b/runtime/syntax/lprolog.vim @@ -7,11 +7,8 @@ " 2001 Apr 26 - Upgraded for new Vim version " 2000 Jun 5 - Initial release -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -96,41 +93,31 @@ syn sync maxlines=500 " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_lprolog_syntax_inits") - if version < 508 - let did_lprolog_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink lprologComment Comment - HiLink lprologTodo Todo - - HiLink lprologKeyword Keyword - HiLink lprologSpecial Special - HiLink lprologOperator Operator - HiLink lprologIdentifier Normal - - HiLink lprologInteger Number - HiLink lprologReal Number - HiLink lprologString String - - HiLink lprologCommentErr Error - HiLink lprologBrackErr Error - HiLink lprologParenErr Error - - HiLink lprologModuleName Special - HiLink lprologTypeName Identifier - - HiLink lprologVariable Keyword - HiLink lprologAtom Normal - HiLink lprologClause Type - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link lprologComment Comment +hi def link lprologTodo Todo + +hi def link lprologKeyword Keyword +hi def link lprologSpecial Special +hi def link lprologOperator Operator +hi def link lprologIdentifier Normal + +hi def link lprologInteger Number +hi def link lprologReal Number +hi def link lprologString String + +hi def link lprologCommentErr Error +hi def link lprologBrackErr Error +hi def link lprologParenErr Error + +hi def link lprologModuleName Special +hi def link lprologTypeName Identifier + +hi def link lprologVariable Keyword +hi def link lprologAtom Normal +hi def link lprologClause Type + let b:current_syntax = "lprolog" diff --git a/runtime/syntax/lscript.vim b/runtime/syntax/lscript.vim index 648a0ebeab..3c4a0fffda 100644 --- a/runtime/syntax/lscript.vim +++ b/runtime/syntax/lscript.vim @@ -9,11 +9,8 @@ " and b) I'm not so crash hot at LotusScript either. If you see any problems " feel free to email me with them. -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -179,34 +176,24 @@ syn region lscriptLineNumber start="^\d" end="\s" syn match lscriptTypeSpecifier "[a-zA-Z0-9][\$%&!#]"ms=s+1 " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_lscript_syntax_inits") - if version < 508 - let did_lscript_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - hi lscriptNotesType term=underline ctermfg=DarkGreen guifg=SeaGreen gui=bold - - HiLink lscriptNotesConst lscriptNotesType - HiLink lscriptLineNumber Comment - HiLink lscriptDatatype Type - HiLink lscriptNumber Number - HiLink lscriptError Error - HiLink lscriptStatement Statement - HiLink lscriptString String - HiLink lscriptComment Comment - HiLink lscriptTodo Todo - HiLink lscriptFunction Identifier - HiLink lscriptMethods PreProc - HiLink lscriptEvents Special - HiLink lscriptTypeSpecifier Type - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi lscriptNotesType term=underline ctermfg=DarkGreen guifg=SeaGreen gui=bold + +hi def link lscriptNotesConst lscriptNotesType +hi def link lscriptLineNumber Comment +hi def link lscriptDatatype Type +hi def link lscriptNumber Number +hi def link lscriptError Error +hi def link lscriptStatement Statement +hi def link lscriptString String +hi def link lscriptComment Comment +hi def link lscriptTodo Todo +hi def link lscriptFunction Identifier +hi def link lscriptMethods PreProc +hi def link lscriptEvents Special +hi def link lscriptTypeSpecifier Type + let b:current_syntax = "lscript" diff --git a/runtime/syntax/lss.vim b/runtime/syntax/lss.vim index 6620707f92..6ee717bcb4 100644 --- a/runtime/syntax/lss.vim +++ b/runtime/syntax/lss.vim @@ -3,11 +3,8 @@ " Maintainer: Scott Bigham <dsb@killerbunnies.org> " Last Change: 2004 Oct 06 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -70,64 +67,57 @@ syn case match syn match lssComment "#.*$" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_lss_syntax_inits") - if version < 508 - let did_lss_syntax_inits = 1 - endif - - hi def link lssComment Comment - hi def link lssElement Identifier - - hi def lssBold term=bold cterm=bold - hi def lssReverse term=reverse cterm=reverse - hi def lssUnderline term=underline cterm=underline - hi def lssStandout term=standout cterm=standout - - hi def lssRedFg ctermfg=red - hi def lssBlueFg ctermfg=blue - hi def lssGreenFg ctermfg=green - hi def lssBrownFg ctermfg=brown - hi def lssMagentaFg ctermfg=magenta - hi def lssCyanFg ctermfg=cyan - hi def lssGrayFg ctermfg=gray - if $COLORTERM == "rxvt" - " On rxvt's, bright colors are activated by setting the bold attribute. - hi def lssLightgrayFg ctermfg=gray cterm=bold - hi def lssBrightredFg ctermfg=red cterm=bold - hi def lssBrightgreenFg ctermfg=green cterm=bold - hi def lssYellowFg ctermfg=yellow cterm=bold - hi def lssBrightblueFg ctermfg=blue cterm=bold - hi def lssBrightmagentaFg ctermfg=magenta cterm=bold - hi def lssBrightcyanFg ctermfg=cyan cterm=bold - else - hi def lssLightgrayFg ctermfg=lightgray - hi def lssBrightredFg ctermfg=lightred - hi def lssBrightgreenFg ctermfg=lightgreen - hi def lssYellowFg ctermfg=yellow - hi def lssBrightblueFg ctermfg=lightblue - hi def lssBrightmagentaFg ctermfg=lightmagenta - hi def lssBrightcyanFg ctermfg=lightcyan - endif - - hi def lssRedBg ctermbg=red - hi def lssBlueBg ctermbg=blue - hi def lssGreenBg ctermbg=green - hi def lssBrownBg ctermbg=brown - hi def lssMagentaBg ctermbg=magenta - hi def lssCyanBg ctermbg=cyan - hi def lssLightgrayBg ctermbg=lightgray - hi def lssGrayBg ctermbg=gray - hi def lssBrightredBg ctermbg=lightred - hi def lssBrightgreenBg ctermbg=lightgreen - hi def lssYellowBg ctermbg=yellow - hi def lssBrightblueBg ctermbg=lightblue - hi def lssBrightmagentaBg ctermbg=lightmagenta - hi def lssBrightcyanBg ctermbg=lightcyan - hi def lssWhiteBg ctermbg=white ctermfg=black +" Only when an item doesn't have highlighting yet +hi def link lssComment Comment +hi def link lssElement Identifier + +hi def lssBold term=bold cterm=bold +hi def lssReverse term=reverse cterm=reverse +hi def lssUnderline term=underline cterm=underline +hi def lssStandout term=standout cterm=standout + +hi def lssRedFg ctermfg=red +hi def lssBlueFg ctermfg=blue +hi def lssGreenFg ctermfg=green +hi def lssBrownFg ctermfg=brown +hi def lssMagentaFg ctermfg=magenta +hi def lssCyanFg ctermfg=cyan +hi def lssGrayFg ctermfg=gray +if $COLORTERM == "rxvt" + " On rxvt's, bright colors are activated by setting the bold attribute. + hi def lssLightgrayFg ctermfg=gray cterm=bold + hi def lssBrightredFg ctermfg=red cterm=bold + hi def lssBrightgreenFg ctermfg=green cterm=bold + hi def lssYellowFg ctermfg=yellow cterm=bold + hi def lssBrightblueFg ctermfg=blue cterm=bold + hi def lssBrightmagentaFg ctermfg=magenta cterm=bold + hi def lssBrightcyanFg ctermfg=cyan cterm=bold +else + hi def lssLightgrayFg ctermfg=lightgray + hi def lssBrightredFg ctermfg=lightred + hi def lssBrightgreenFg ctermfg=lightgreen + hi def lssYellowFg ctermfg=yellow + hi def lssBrightblueFg ctermfg=lightblue + hi def lssBrightmagentaFg ctermfg=lightmagenta + hi def lssBrightcyanFg ctermfg=lightcyan endif +hi def lssRedBg ctermbg=red +hi def lssBlueBg ctermbg=blue +hi def lssGreenBg ctermbg=green +hi def lssBrownBg ctermbg=brown +hi def lssMagentaBg ctermbg=magenta +hi def lssCyanBg ctermbg=cyan +hi def lssLightgrayBg ctermbg=lightgray +hi def lssGrayBg ctermbg=gray +hi def lssBrightredBg ctermbg=lightred +hi def lssBrightgreenBg ctermbg=lightgreen +hi def lssYellowBg ctermbg=yellow +hi def lssBrightblueBg ctermbg=lightblue +hi def lssBrightmagentaBg ctermbg=lightmagenta +hi def lssBrightcyanBg ctermbg=lightcyan +hi def lssWhiteBg ctermbg=white ctermfg=black + let b:current_syntax = "lss" " vim: ts=8 diff --git a/runtime/syntax/lua.vim b/runtime/syntax/lua.vim index 3ff80b1ebe..f313c14e7a 100644 --- a/runtime/syntax/lua.vim +++ b/runtime/syntax/lua.vim @@ -7,11 +7,8 @@ " lua_subversion = 0 (4.0, 5.0) or 1 (5.1) or 2 (5.2) " default 5.2 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -325,40 +322,30 @@ elseif lua_version == 5 endif " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_lua_syntax_inits") - if version < 508 - let did_lua_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink luaStatement Statement - HiLink luaRepeat Repeat - HiLink luaFor Repeat - HiLink luaString String - HiLink luaString2 String - HiLink luaNumber Number - HiLink luaOperator Operator - HiLink luaIn Operator - HiLink luaConstant Constant - HiLink luaCond Conditional - HiLink luaElse Conditional - HiLink luaFunction Function - HiLink luaComment Comment - HiLink luaTodo Todo - HiLink luaTable Structure - HiLink luaError Error - HiLink luaParenError Error - HiLink luaBraceError Error - HiLink luaSpecial SpecialChar - HiLink luaFunc Identifier - HiLink luaLabel Label +hi def link luaStatement Statement +hi def link luaRepeat Repeat +hi def link luaFor Repeat +hi def link luaString String +hi def link luaString2 String +hi def link luaNumber Number +hi def link luaOperator Operator +hi def link luaIn Operator +hi def link luaConstant Constant +hi def link luaCond Conditional +hi def link luaElse Conditional +hi def link luaFunction Function +hi def link luaComment Comment +hi def link luaTodo Todo +hi def link luaTable Structure +hi def link luaError Error +hi def link luaParenError Error +hi def link luaBraceError Error +hi def link luaSpecial SpecialChar +hi def link luaFunc Identifier +hi def link luaLabel Label - delcommand HiLink -endif let b:current_syntax = "lua" diff --git a/runtime/syntax/m4.vim b/runtime/syntax/m4.vim index ba7a294d14..6f229ea1ab 100644 --- a/runtime/syntax/m4.vim +++ b/runtime/syntax/m4.vim @@ -8,15 +8,12 @@ " capital letters and have at least one argument (i.e. the '(' " must be there). Let me know if this is a problem. -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded +" quit when a syntax file was already loaded if !exists("main_syntax") - if version < 600 - syntax clear - elseif exists("b:current_syntax") - finish -endif -" we define it here so that included files can test for it + if exists("b:current_syntax") + finish + endif + " we define it here so that included files can test for it let main_syntax='m4' endif @@ -39,30 +36,20 @@ syn region m4String start="`" end="'" contained contains=@m4Top,@m4StringConte syn cluster m4Top contains=m4Comment,m4Constants,m4Special,m4Variable,m4String,m4Paren,m4Command,m4Statement,m4Function " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_m4_syn_inits") - if version < 508 - let did_m4_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - HiLink m4Delimiter Delimiter - HiLink m4Comment Comment - HiLink m4Function Function - HiLink m4Keyword Keyword - HiLink m4Special Special - HiLink m4String String - HiLink m4Statement Statement - HiLink m4Preproc PreProc - HiLink m4Type Type - HiLink m4Special Special - HiLink m4Variable Special - HiLink m4Constants Constant - HiLink m4Builtin Statement - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet +hi def link m4Delimiter Delimiter +hi def link m4Comment Comment +hi def link m4Function Function +hi def link m4Keyword Keyword +hi def link m4Special Special +hi def link m4String String +hi def link m4Statement Statement +hi def link m4Preproc PreProc +hi def link m4Type Type +hi def link m4Special Special +hi def link m4Variable Special +hi def link m4Constants Constant +hi def link m4Builtin Statement let b:current_syntax = "m4" diff --git a/runtime/syntax/make.vim b/runtime/syntax/make.vim index 35b09341a6..7072bab988 100644 --- a/runtime/syntax/make.vim +++ b/runtime/syntax/make.vim @@ -4,11 +4,8 @@ " URL: http://www.fleiner.com/vim/syntax/make.vim " Last Change: 2015 Feb 28 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -101,40 +98,30 @@ syn sync match makeCommandSync groupthere makeCommands "^[A-Za-z0-9_./$()%-][A-Z syn sync match makeCommandSync groupthere makeCommands "^[A-Za-z0-9_./$()%-][A-Za-z0-9_./\t $()%-]*:\{1,2}\s*$" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_make_syn_inits") - if version < 508 - let did_make_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink makeNextLine makeSpecial - HiLink makeCmdNextLine makeSpecial - HiLink makeSpecTarget Statement - if !exists("make_no_commands") - HiLink makeCommands Number - endif - HiLink makeImplicit Function - HiLink makeTarget Function - HiLink makeInclude Include - HiLink makePreCondit PreCondit - HiLink makeStatement Statement - HiLink makeIdent Identifier - HiLink makeSpecial Special - HiLink makeComment Comment - HiLink makeDString String - HiLink makeSString String - HiLink makeBString Function - HiLink makeError Error - HiLink makeTodo Todo - HiLink makeDefine Define - HiLink makeCommandError Error - HiLink makeConfig PreCondit - delcommand HiLink +" Only when an item doesn't have highlighting yet + +hi def link makeNextLine makeSpecial +hi def link makeCmdNextLine makeSpecial +hi def link makeSpecTarget Statement +if !exists("make_no_commands") +hi def link makeCommands Number endif +hi def link makeImplicit Function +hi def link makeTarget Function +hi def link makeInclude Include +hi def link makePreCondit PreCondit +hi def link makeStatement Statement +hi def link makeIdent Identifier +hi def link makeSpecial Special +hi def link makeComment Comment +hi def link makeDString String +hi def link makeSString String +hi def link makeBString Function +hi def link makeError Error +hi def link makeTodo Todo +hi def link makeDefine Define +hi def link makeCommandError Error +hi def link makeConfig PreCondit let b:current_syntax = "make" diff --git a/runtime/syntax/man.vim b/runtime/syntax/man.vim index 819b2adc31..0975b160ae 100644 --- a/runtime/syntax/man.vim +++ b/runtime/syntax/man.vim @@ -18,6 +18,11 @@ highlight default link manOptionDesc Constant highlight default link manReference PreProc highlight default link manSubHeading Function +if &filetype != 'man' + " May have been included by some other filetype. + finish +endif + if !exists('b:man_sect') call man#init_pager() endif diff --git a/runtime/syntax/maple.vim b/runtime/syntax/maple.vim index 77b1507b36..1261ff5a47 100644 --- a/runtime/syntax/maple.vim +++ b/runtime/syntax/maple.vim @@ -1,8 +1,8 @@ " Vim syntax file " Language: Maple V (based on release 4) " Maintainer: Charles E. Campbell <NdrOchipS@PcampbellAfamily.Mbiz> -" Last Change: May 02, 2016 -" Version: 13 +" Last Change: Aug 31, 2016 +" Version: 15 " URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_MAPLE " " Package Function Selection: {{{1 @@ -21,11 +21,8 @@ " but only the contents of packages of Maple V Release 4, and the top-level " routines of Release 4. <Jacques Carette - carette@mcmaster.ca> -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -551,81 +548,73 @@ endif " ===================================================================== " Highlighting: Define the default highlighting. {{{1 -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_maplev_syntax_inits") - if version < 508 - let did_maplev_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet +if !exists("skip_maplev_syntax_inits") " Maple->Maple Links {{{2 - HiLink mvBraceError mvError - HiLink mvCurlyError mvError - HiLink mvDebug mvTodo - HiLink mvParenError mvError - HiLink mvPkg_DEtools mvPkgFunc - HiLink mvPkg_Galois mvPkgFunc - HiLink mvPkg_GaussInt mvPkgFunc - HiLink mvPkg_LREtools mvPkgFunc - HiLink mvPkg_combinat mvPkgFunc - HiLink mvPkg_combstruct mvPkgFunc - HiLink mvPkg_difforms mvPkgFunc - HiLink mvPkg_finance mvPkgFunc - HiLink mvPkg_genfunc mvPkgFunc - HiLink mvPkg_geometry mvPkgFunc - HiLink mvPkg_grobner mvPkgFunc - HiLink mvPkg_group mvPkgFunc - HiLink mvPkg_inttrans mvPkgFunc - HiLink mvPkg_liesymm mvPkgFunc - HiLink mvPkg_linalg mvPkgFunc - HiLink mvPkg_logic mvPkgFunc - HiLink mvPkg_networks mvPkgFunc - HiLink mvPkg_numapprox mvPkgFunc - HiLink mvPkg_numtheory mvPkgFunc - HiLink mvPkg_orthopoly mvPkgFunc - HiLink mvPkg_padic mvPkgFunc - HiLink mvPkg_plots mvPkgFunc - HiLink mvPkg_plottools mvPkgFunc - HiLink mvPkg_powseries mvPkgFunc - HiLink mvPkg_process mvPkgFunc - HiLink mvPkg_simplex mvPkgFunc - HiLink mvPkg_stats mvPkgFunc - HiLink mvPkg_student mvPkgFunc - HiLink mvPkg_sumtools mvPkgFunc - HiLink mvPkg_tensor mvPkgFunc - HiLink mvPkg_totorder mvPkgFunc - HiLink mvRange mvOper - HiLink mvSemiError mvError - HiLink mvDelim Delimiter + hi def link mvBraceError mvError + hi def link mvCurlyError mvError + hi def link mvDebug mvTodo + hi def link mvParenError mvError + hi def link mvPkg_DEtools mvPkgFunc + hi def link mvPkg_Galois mvPkgFunc + hi def link mvPkg_GaussInt mvPkgFunc + hi def link mvPkg_LREtools mvPkgFunc + hi def link mvPkg_combinat mvPkgFunc + hi def link mvPkg_combstruct mvPkgFunc + hi def link mvPkg_difforms mvPkgFunc + hi def link mvPkg_finance mvPkgFunc + hi def link mvPkg_genfunc mvPkgFunc + hi def link mvPkg_geometry mvPkgFunc + hi def link mvPkg_grobner mvPkgFunc + hi def link mvPkg_group mvPkgFunc + hi def link mvPkg_inttrans mvPkgFunc + hi def link mvPkg_liesymm mvPkgFunc + hi def link mvPkg_linalg mvPkgFunc + hi def link mvPkg_logic mvPkgFunc + hi def link mvPkg_networks mvPkgFunc + hi def link mvPkg_numapprox mvPkgFunc + hi def link mvPkg_numtheory mvPkgFunc + hi def link mvPkg_orthopoly mvPkgFunc + hi def link mvPkg_padic mvPkgFunc + hi def link mvPkg_plots mvPkgFunc + hi def link mvPkg_plottools mvPkgFunc + hi def link mvPkg_powseries mvPkgFunc + hi def link mvPkg_process mvPkgFunc + hi def link mvPkg_simplex mvPkgFunc + hi def link mvPkg_stats mvPkgFunc + hi def link mvPkg_student mvPkgFunc + hi def link mvPkg_sumtools mvPkgFunc + hi def link mvPkg_tensor mvPkgFunc + hi def link mvPkg_totorder mvPkgFunc + hi def link mvRange mvOper + hi def link mvSemiError mvError + hi def link mvDelim Delimiter " Maple->Standard Links {{{2 - HiLink mvAssign Delimiter - HiLink mvBool Boolean - HiLink mvComma Delimiter - HiLink mvComment Comment - HiLink mvCond Conditional - HiLink mvConstant Number - HiLink mvDelayEval Label - HiLink mvDcolon Delimiter - HiLink mvError Error - HiLink mvLibrary Statement - HiLink mvNumber Number - HiLink mvOper Operator - HiLink mvAssign Delimiter - HiLink mvPackage Type - HiLink mvPkgFunc Function - HiLink mvPktOption Special - HiLink mvRepeat Repeat - HiLink mvSpecial Special - HiLink mvStatement Statement - HiLink mvName String - HiLink mvString String - HiLink mvTodo Todo - - delcommand HiLink + hi def link mvAssign Delimiter + hi def link mvBool Boolean + hi def link mvComma Delimiter + hi def link mvComment Comment + hi def link mvCond Conditional + hi def link mvConstant Number + hi def link mvDelayEval Label + hi def link mvDcolon Delimiter + hi def link mvError Error + hi def link mvLibrary Statement + hi def link mvNumber Number + hi def link mvOper Operator + hi def link mvAssign Delimiter + hi def link mvPackage Type + hi def link mvPkgFunc Function + hi def link mvPktOption Special + hi def link mvRepeat Repeat + hi def link mvSpecial Special + hi def link mvStatement Statement + hi def link mvName String + hi def link mvString String + hi def link mvTodo Todo + endif " Current Syntax: {{{1 diff --git a/runtime/syntax/markdown.vim b/runtime/syntax/markdown.vim index 068115e92d..1955a7443e 100644 --- a/runtime/syntax/markdown.vim +++ b/runtime/syntax/markdown.vim @@ -2,7 +2,7 @@ " Language: Markdown " Maintainer: Tim Pope <vimNOSPAM@tpope.org> " Filenames: *.markdown -" Last Change: 2013 May 30 +" Last Change: 2016 Aug 29 if exists("b:current_syntax") finish @@ -70,29 +70,34 @@ syn region markdownUrlTitle matchgroup=markdownUrlTitleDelimiter start=+"+ end=+ syn region markdownUrlTitle matchgroup=markdownUrlTitleDelimiter start=+'+ end=+'+ keepend contained syn region markdownUrlTitle matchgroup=markdownUrlTitleDelimiter start=+(+ end=+)+ keepend contained -syn region markdownLinkText matchgroup=markdownLinkTextDelimiter start="!\=\[\%(\_[^]]*]\%( \=[[(]\)\)\@=" end="\]\%( \=[[(]\)\@=" keepend nextgroup=markdownLink,markdownId skipwhite contains=@markdownInline,markdownLineStart +syn region markdownLinkText matchgroup=markdownLinkTextDelimiter start="!\=\[\%(\_[^]]*]\%( \=[[(]\)\)\@=" end="\]\%( \=[[(]\)\@=" nextgroup=markdownLink,markdownId skipwhite contains=@markdownInline,markdownLineStart syn region markdownLink matchgroup=markdownLinkDelimiter start="(" end=")" contains=markdownUrl keepend contained syn region markdownId matchgroup=markdownIdDelimiter start="\[" end="\]" keepend contained syn region markdownAutomaticLink matchgroup=markdownUrlDelimiter start="<\%(\w\+:\|[[:alnum:]_+-]\+@\)\@=" end=">" keepend oneline -syn region markdownItalic start="\S\@<=\*\|\*\S\@=" end="\S\@<=\*\|\*\S\@=" keepend contains=markdownLineStart -syn region markdownItalic start="\S\@<=_\|_\S\@=" end="\S\@<=_\|_\S\@=" keepend contains=markdownLineStart -syn region markdownBold start="\S\@<=\*\*\|\*\*\S\@=" end="\S\@<=\*\*\|\*\*\S\@=" keepend contains=markdownLineStart,markdownItalic -syn region markdownBold start="\S\@<=__\|__\S\@=" end="\S\@<=__\|__\S\@=" keepend contains=markdownLineStart,markdownItalic -syn region markdownBoldItalic start="\S\@<=\*\*\*\|\*\*\*\S\@=" end="\S\@<=\*\*\*\|\*\*\*\S\@=" keepend contains=markdownLineStart -syn region markdownBoldItalic start="\S\@<=___\|___\S\@=" end="\S\@<=___\|___\S\@=" keepend contains=markdownLineStart +let s:concealends = has('conceal') ? ' concealends' : '' +exe 'syn region markdownItalic matchgroup=markdownItalicDelimiter start="\S\@<=\*\|\*\S\@=" end="\S\@<=\*\|\*\S\@=" keepend contains=markdownLineStart' . s:concealends +exe 'syn region markdownItalic matchgroup=markdownItalicDelimiter start="\S\@<=_\|_\S\@=" end="\S\@<=_\|_\S\@=" keepend contains=markdownLineStart' . s:concealends +exe 'syn region markdownBold matchgroup=markdownBoldDelimiter start="\S\@<=\*\*\|\*\*\S\@=" end="\S\@<=\*\*\|\*\*\S\@=" keepend contains=markdownLineStart,markdownItalic' . s:concealends +exe 'syn region markdownBold matchgroup=markdownBoldDelimiter start="\S\@<=__\|__\S\@=" end="\S\@<=__\|__\S\@=" keepend contains=markdownLineStart,markdownItalic' . s:concealends +exe 'syn region markdownBoldItalic matchgroup=markdownBoldItalicDelimiter start="\S\@<=\*\*\*\|\*\*\*\S\@=" end="\S\@<=\*\*\*\|\*\*\*\S\@=" keepend contains=markdownLineStart' . s:concealends +exe 'syn region markdownBoldItalic matchgroup=markdownBoldItalicDelimiter start="\S\@<=___\|___\S\@=" end="\S\@<=___\|___\S\@=" keepend contains=markdownLineStart' . s:concealends + syn region markdownCode matchgroup=markdownCodeDelimiter start="`" end="`" keepend contains=markdownLineStart syn region markdownCode matchgroup=markdownCodeDelimiter start="`` \=" end=" \=``" keepend contains=markdownLineStart syn region markdownCode matchgroup=markdownCodeDelimiter start="^\s*```.*$" end="^\s*```\ze\s*$" keepend +syn match markdownFootnote "\[^[^\]]\+\]" +syn match markdownFootnoteDefinition "^\[^[^\]]\+\]:" + if main_syntax ==# 'markdown' for s:type in g:markdown_fenced_languages - exe 'syn region markdownHighlight'.substitute(matchstr(s:type,'[^=]*$'),'\..*','','').' matchgroup=markdownCodeDelimiter start="^\s*```'.matchstr(s:type,'[^=]*').'\>.*$" end="^\s*```\ze\s*$" keepend contains=@markdownHighlight'.substitute(matchstr(s:type,'[^=]*$'),'\.','','g') + exe 'syn region markdownHighlight'.substitute(matchstr(s:type,'[^=]*$'),'\..*','','').' matchgroup=markdownCodeDelimiter start="^\s*```\s*'.matchstr(s:type,'[^=]*').'\>.*$" end="^\s*```\ze\s*$" keepend contains=@markdownHighlight'.substitute(matchstr(s:type,'[^=]*$'),'\.','','g') endfor unlet! s:type endif -syn match markdownEscape "\\[][\\`*_{}()#+.!-]" +syn match markdownEscape "\\[][\\`*_{}()<>#+.!-]" syn match markdownError "\w\@<=_\w\@=" hi def link markdownH1 htmlH1 @@ -108,6 +113,9 @@ hi def link markdownListMarker htmlTagName hi def link markdownBlockquote Comment hi def link markdownRule PreProc +hi def link markdownFootnote Typedef +hi def link markdownFootnoteDefinition Typedef + hi def link markdownLinkText htmlLink hi def link markdownIdDeclaration Typedef hi def link markdownId Type @@ -119,8 +127,11 @@ hi def link markdownUrlDelimiter htmlTag hi def link markdownUrlTitleDelimiter Delimiter hi def link markdownItalic htmlItalic +hi def link markdownItalicDelimiter markdownItalic hi def link markdownBold htmlBold +hi def link markdownBoldDelimiter markdownBold hi def link markdownBoldItalic htmlBoldItalic +hi def link markdownBoldItalicDelimiter markdownBoldItalic hi def link markdownCodeDelimiter Delimiter hi def link markdownEscape Special diff --git a/runtime/syntax/mason.vim b/runtime/syntax/mason.vim index 40bdb0eaa4..6789e11aef 100644 --- a/runtime/syntax/mason.vim +++ b/runtime/syntax/mason.vim @@ -13,12 +13,8 @@ " - Fix <%text> blocks to show HTML tags but ignore Mason tags. " -" Clear previous syntax settings unless this is v6 or above, in which case just -" exit without doing anything. -" -if version < 600 - syn clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -30,22 +26,14 @@ endif " First pull in the HTML syntax. " -if version < 600 - so <sfile>:p:h/html.vim -else - runtime! syntax/html.vim - unlet b:current_syntax -endif +runtime! syntax/html.vim +unlet b:current_syntax syn cluster htmlPreproc add=@masonTop " Now pull in the Perl syntax. " -if version < 600 - syn include @perlTop <sfile>:p:h/perl.vim -else - syn include @perlTop syntax/perl.vim -endif +syn include @perlTop syntax/perl.vim " It's hard to reduce down to the correct sub-set of Perl to highlight in some " of these cases so I've taken the safe option of just using perlTop in all of @@ -78,19 +66,7 @@ syn cluster masonTop contains=masonLine,masonExpr,masonPerl,masonComp,masonArgs, " Set up default highlighting. Almost all of this is done in the included " syntax files. -" -if version >= 508 || !exists("did_mason_syn_inits") - if version < 508 - let did_mason_syn_inits = 1 - com -nargs=+ HiLink hi link <args> - else - com -nargs=+ HiLink hi def link <args> - endif - - HiLink masonDoc Comment - - delc HiLink -endif +hi def link masonDoc Comment let b:current_syntax = "mason" diff --git a/runtime/syntax/master.vim b/runtime/syntax/master.vim index 40d644eef9..f89c5b2f1c 100644 --- a/runtime/syntax/master.vim +++ b/runtime/syntax/master.vim @@ -8,11 +8,8 @@ " this is a very simple syntax file - I will be improving it " add entire DEFINE syntax -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -28,22 +25,12 @@ syn region masterString start=+'+ end=+'+ syn match masterComment "\$.*" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_master_syntax_inits") - if version < 508 - let did_master_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink masterKeyword Keyword - HiLink masterComment Comment - HiLink masterString String - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link masterKeyword Keyword +hi def link masterComment Comment +hi def link masterString String + let b:current_syntax = "master" diff --git a/runtime/syntax/matlab.vim b/runtime/syntax/matlab.vim index 3828f3e8a8..5228bb5c43 100644 --- a/runtime/syntax/matlab.vim +++ b/runtime/syntax/matlab.vim @@ -1,18 +1,17 @@ " Vim syntax file " Language: Matlab -" Maintainer: Maurizio Tranchero - maurizio(.)tranchero(@)gmail(.)com +" Maintainer: Alex Burka <vim@alexburka.com> " Credits: Preben 'Peppe' Guldberg <peppe-vim@wielders.org> +" Maurizio Tranchero - maurizio(.)tranchero(@)gmail(.)com " Original author: Mario Eusebio -" Last Change: Wed Jan 13 11:12:34 CET 2010 -" sinh added to matlab implicit commands +" Last Change: Mon Jan 23 2017 +" added support for cell mode " Change History: +" - now highlights cell-mode separator comments " - 'global' and 'persistent' keyword are now recognized -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -63,6 +62,7 @@ syn match matlabComment "%.*$" contains=matlabTodo,matlabTab " MT_ADDON - correctly highlights words after '...' as comments syn match matlabComment "\.\.\..*$" contains=matlabTodo,matlabTab syn region matlabMultilineComment start=+%{+ end=+%}+ contains=matlabTodo,matlabTab +syn match matlabCellComment "^%%.*$" syn keyword matlabOperator break zeros default margin round ones rand syn keyword matlabOperator ceil floor size clear zeros eye mean std cov @@ -76,49 +76,40 @@ syn match matlabError "-\=\<\d\+\.\d\+\.[^*/\\^]" syn match matlabError "-\=\<\d\+\.\d\+[eEdD][-+]\=\d\+\.\([^*/\\^]\)" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_matlab_syntax_inits") - if version < 508 - let did_matlab_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink matlabTransposeOperator matlabOperator - HiLink matlabOperator Operator - HiLink matlabLineContinuation Special - HiLink matlabLabel Label - HiLink matlabConditional Conditional - HiLink matlabExceptions Conditional - HiLink matlabRepeat Repeat - HiLink matlabTodo Todo - HiLink matlabString String - HiLink matlabDelimiter Identifier - HiLink matlabTransposeOther Identifier - HiLink matlabNumber Number - HiLink matlabFloat Float - HiLink matlabFunction Function - HiLink matlabError Error - HiLink matlabImplicit matlabStatement - HiLink matlabStatement Statement - HiLink matlabOO Statement - HiLink matlabSemicolon SpecialChar - HiLink matlabComment Comment - HiLink matlabMultilineComment Comment - HiLink matlabScope Type - - HiLink matlabArithmeticOperator matlabOperator - HiLink matlabRelationalOperator matlabOperator - HiLink matlabLogicalOperator matlabOperator +" Only when an item doesn't have highlighting yet + +hi def link matlabTransposeOperator matlabOperator +hi def link matlabOperator Operator +hi def link matlabLineContinuation Special +hi def link matlabLabel Label +hi def link matlabConditional Conditional +hi def link matlabExceptions Conditional +hi def link matlabRepeat Repeat +hi def link matlabTodo Todo +hi def link matlabString String +hi def link matlabDelimiter Identifier +hi def link matlabTransposeOther Identifier +hi def link matlabNumber Number +hi def link matlabFloat Float +hi def link matlabFunction Function +hi def link matlabError Error +hi def link matlabImplicit matlabStatement +hi def link matlabStatement Statement +hi def link matlabOO Statement +hi def link matlabSemicolon SpecialChar +hi def link matlabComment Comment +hi def link matlabMultilineComment Comment +hi def link matlabCellComment Todo +hi def link matlabScope Type + +hi def link matlabArithmeticOperator matlabOperator +hi def link matlabRelationalOperator matlabOperator +hi def link matlabLogicalOperator matlabOperator "optional highlighting - "HiLink matlabIdentifier Identifier - "HiLink matlabTab Error +"hi def link matlabIdentifier Identifier +"hi def link matlabTab Error - delcommand HiLink -endif let b:current_syntax = "matlab" diff --git a/runtime/syntax/maxima.vim b/runtime/syntax/maxima.vim index 27dcc18842..46e1e4ff84 100644 --- a/runtime/syntax/maxima.vim +++ b/runtime/syntax/maxima.vim @@ -6,11 +6,8 @@ " Adapted mostly from xmath.vim " Number formats adapted from r.vim " -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -234,41 +231,31 @@ syn sync match maximaSyncComment grouphere maximaCommentBlock "/*" syn sync match maximaSyncComment groupthere NONE "*/" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_maxima_syntax_inits") - if version < 508 - let did_maxima_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink maximaBraceError maximaError - HiLink maximaCmd maximaStatement - HiLink maximaCurlyError maximaError - HiLink maximaFuncCmd maximaStatement - HiLink maximaParenError maximaError +hi def link maximaBraceError maximaError +hi def link maximaCmd maximaStatement +hi def link maximaCurlyError maximaError +hi def link maximaFuncCmd maximaStatement +hi def link maximaParenError maximaError - " The default methods for highlighting. Can be overridden later - HiLink maximaCharacter Character - HiLink maximaComma Function - HiLink maximaCommentBlock Comment - HiLink maximaConditional Conditional - HiLink maximaError Error - HiLink maximaFunc Delimiter - HiLink maximaOp Delimiter - HiLink maximaLabel PreProc - HiLink maximaNumber Number - HiLink maximaFloat Float - HiLink maximaRepeat Repeat - HiLink maximaSpecial Type - HiLink maximaSpecialChar SpecialChar - HiLink maximaStatement Statement - HiLink maximaString String - HiLink maximaTodo Todo +" The default methods for highlighting. Can be overridden later +hi def link maximaCharacter Character +hi def link maximaComma Function +hi def link maximaCommentBlock Comment +hi def link maximaConditional Conditional +hi def link maximaError Error +hi def link maximaFunc Delimiter +hi def link maximaOp Delimiter +hi def link maximaLabel PreProc +hi def link maximaNumber Number +hi def link maximaFloat Float +hi def link maximaRepeat Repeat +hi def link maximaSpecial Type +hi def link maximaSpecialChar SpecialChar +hi def link maximaStatement Statement +hi def link maximaString String +hi def link maximaTodo Todo - delcommand HiLink -endif let b:current_syntax = "maxima" diff --git a/runtime/syntax/mel.vim b/runtime/syntax/mel.vim index a668e70378..ea6e75fa22 100644 --- a/runtime/syntax/mel.vim +++ b/runtime/syntax/mel.vim @@ -4,11 +4,8 @@ " Last Change: May 27 1999 " Based on: Bram Moolenaar <Bram@vim.org> C syntax file -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -77,45 +74,35 @@ endif exec "sy sync ccomment melComment minlines=" . mel_minlines " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_mel_syntax_inits") - if version < 508 - let did_mel_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink melBoolean Boolean - HiLink melFunction Function - HiLink melIdentifier Identifier - HiLink melStatement Statement - HiLink melConditional Conditional - HiLink melRepeat Repeat - HiLink melLabel Label - HiLink melOperator Operator - HiLink melKeyword Keyword - HiLink melException Exception - HiLink melInclude Include - HiLink melType Type - HiLink melStorageClass StorageClass - HiLink melDebug Debug - HiLink melTodo Todo - HiLink melCharSpecial SpecialChar - HiLink melString String - HiLink melInteger Number - HiLink melFloat Float - HiLink melMatrixVector Float - HiLink melComment Comment - HiLink melError Error - HiLink melSpaceError melError - HiLink melCharError melError - HiLink melParenError melError - HiLink melInParen melError - HiLink melCommentError melError - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link melBoolean Boolean +hi def link melFunction Function +hi def link melIdentifier Identifier +hi def link melStatement Statement +hi def link melConditional Conditional +hi def link melRepeat Repeat +hi def link melLabel Label +hi def link melOperator Operator +hi def link melKeyword Keyword +hi def link melException Exception +hi def link melInclude Include +hi def link melType Type +hi def link melStorageClass StorageClass +hi def link melDebug Debug +hi def link melTodo Todo +hi def link melCharSpecial SpecialChar +hi def link melString String +hi def link melInteger Number +hi def link melFloat Float +hi def link melMatrixVector Float +hi def link melComment Comment +hi def link melError Error +hi def link melSpaceError melError +hi def link melCharError melError +hi def link melParenError melError +hi def link melInParen melError +hi def link melCommentError melError + let b:current_syntax = "mel" diff --git a/runtime/syntax/mf.vim b/runtime/syntax/mf.vim index 8bc48fee46..3589e4db3c 100644 --- a/runtime/syntax/mf.vim +++ b/runtime/syntax/mf.vim @@ -1,197 +1,295 @@ " Vim syntax file -" Language: Metafont -" Maintainer: Andreas Scherer <andreas.scherer@pobox.com> -" Last Change: April 25, 2001 - -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syn clear -elseif exists("b:current_syntax") +" Language: METAFONT +" Maintainer: Nicola Vitacolonna <nvitacolonna@gmail.com> +" Former Maintainers: Andreas Scherer <andreas.scherer@pobox.com> +" Last Change: 2016 Oct 1 + +if exists("b:current_syntax") finish endif -" Metafont 'primitives' as defined in chapter 25 of 'The METAFONTbook' +syn iskeyword @,_ + +" METAFONT 'primitives' as defined in chapter 25 of 'The METAFONTbook' " Page 210: 'boolean expressions' -syn keyword mfBoolExp true false known unknown odd charexists not and or +syn keyword mfBoolExp and charexists false known not odd or true unknown " Page 210: 'numeric expression' -syn keyword mfNumExp normaldeviate length ASCII oct hex angle turningnumber -syn keyword mfNumExp totalweight directiontime xpart ypart xxpart xypart -syn keyword mfNumExp yxpart yypart sqrt sind cosd mlog mexp floor -syn keyword mfNumExp uniformdeviate +syn keyword mfNumExp ASCII angle cosd directiontime floor hex length +syn keyword mfNumExp mexp mlog normaldeviate oct sind sqrt totalweight +syn keyword mfNumExp turningnumber uniformdeviate xpart xxpart xypart +syn keyword mfNumExp ypart yxpart yypart " Page 211: 'internal quantities' -syn keyword mfInternal tracingtitles tracingequations tracingcapsules -syn keyword mfInternal tracingchoices tracingspecs tracingpens -syn keyword mfInternal tracingcommands tracingrestores tracingmacros -syn keyword mfInternal tracingedges tracingoutput tracingonline tracingstats -syn keyword mfInternal pausing showstopping fontmaking proofing -syn keyword mfInternal turningcheck warningcheck smoothing autorounding -syn keyword mfInternal granularity fillin year month day time -syn keyword mfInternal charcode charext charwd charht chardp charic -syn keyword mfInternal chardx chardy designsize hppp vppp xoffset yoffset -syn keyword mfInternal boundarychar +syn keyword mfInternal autorounding boundarychar charcode chardp chardx +syn keyword mfInternal chardy charext charht charic charwd day designsize +syn keyword mfInternal fillin fontmaking granularity hppp jobname month +syn keyword mfInternal pausing proofing showstopping smoothing time +syn keyword mfInternal tracingcapsules tracingchoices tracingcommands +syn keyword mfInternal tracingedges tracingequations tracingmacros +syn keyword mfInternal tracingonline tracingoutput tracingpens +syn keyword mfInternal tracingrestores tracingspecs tracingstats +syn keyword mfInternal tracingtitles turningcheck vppp warningcheck +syn keyword mfInternal xoffset year yoffset " Page 212: 'pair expressions' -syn keyword mfPairExp point of precontrol postcontrol penoffset rotated -syn keyword mfPairExp scaled shifted slanted transformed xscaled yscaled -syn keyword mfPairExp zscaled +syn keyword mfPairExp of penoffset point postcontrol precontrol rotated +syn keyword mfPairExp scaled shifted slanted transformed xscaled yscaled +syn keyword mfPairExp zscaled " Page 213: 'path expressions' -syn keyword mfPathExp makepath reverse subpath curl tension atleast -syn keyword mfPathExp controls cycle +syn keyword mfPathExp atleast controls curl cycle makepath reverse +syn keyword mfPathExp subpath tension " Page 214: 'pen expressions' -syn keyword mfPenExp nullpen pencircle makepen +syn keyword mfPenExp makepen nullpen pencircle -" Page 214: 'picutre expressions' -syn keyword mfPicExp nullpicture +" Page 214: 'picture expressions' +syn keyword mfPicExp nullpicture " Page 214: 'string expressions' -syn keyword mfStringExp jobname readstring str char decimal substring +syn keyword mfStringExp char decimal readstring str substring " Page 217: 'commands and statements' -syn keyword mfCommand end dump save interim newinternal randomseed let -syn keyword mfCommand delimiters outer everyjob show showvariable showtoken -syn keyword mfCommand showdependencies showstats message errmessage errhelp -syn keyword mfCommand batchmode nonstopmode scrollmode errorstopmode -syn keyword mfCommand addto also contour doublepath withpen withweight cull -syn keyword mfCommand keeping dropping display inwindow openwindow at from to -syn keyword mfCommand shipout special numspecial +syn keyword mfCommand addto also at batchmode contour cull delimiters +syn keyword mfCommand display doublepath dropping dump end errhelp +syn keyword mfCommand errmessage errorstopmode everyjob from interim +syn keyword mfCommand inwindow keeping let message newinternal +syn keyword mfCommand nonstopmode numspecial openwindow outer randomseed +syn keyword mfCommand save scrollmode shipout show showdependencies +syn keyword mfCommand showstats showtoken showvariable special to withpen +syn keyword mfCommand withweight " Page 56: 'types' -syn keyword mfType boolean numeric pair path pen picture string transform +syn keyword mfType boolean numeric pair path pen picture string +syn keyword mfType transform " Page 155: 'grouping' -syn keyword mfStatement begingroup endgroup +syn keyword mfStatement begingroup endgroup " Page 165: 'definitions' -syn keyword mfDefinition enddef def expr suffix text primary secondary -syn keyword mfDefinition tertiary vardef primarydef secondarydef tertiarydef +syn keyword mfDefinition def enddef expr primary primarydef secondary +syn keyword mfDefinition secondarydef suffix tertiary tertiarydef text +syn keyword mfDefinition vardef " Page 169: 'conditions and loops' -syn keyword mfCondition if fi else elseif endfor for forsuffixes forever -syn keyword mfCondition step until exitif +syn keyword mfCondition else elseif endfor exitif fi for forever +syn keyword mfCondition forsuffixes if step until " Other primitives listed in the index -syn keyword mfPrimitive charlist endinput expandafter extensible -syn keyword mfPrimitive fontdimen headerbyte inner input intersectiontimes -syn keyword mfPrimitive kern ligtable quote scantokens skipto +syn keyword mfPrimitive charlist endinput expandafter extensible fontdimen +syn keyword mfPrimitive headerbyte inner input intersectiontimes kern +syn keyword mfPrimitive ligtable quote scantokens skipto + +" Implicit suffix parameters +syn match mfSuffixParam "@#\|#@\|@" + +" These are just tags, but given their special status, we +" highlight them as variables +syn keyword mfVariable x y " Keywords defined by plain.mf (defined on pp.262-278) -if !exists("plain_mf_macros") - let plain_mf_macros = 1 " Set this to '0' if your source gets too colourful - " metapost.vim does so to turn off Metafont macros +if get(g:, "plain_mf_macros", 1) + syn keyword mfDef addto_currentpicture beginchar capsule_def + syn keyword mfDef change_width clear_pen_memory clearit clearpen + syn keyword mfDef clearxy culldraw cullit cutdraw + syn keyword mfDef define_blacker_pixels define_corrected_pixels + syn keyword mfDef define_good_x_pixels define_good_y_pixels + syn keyword mfDef define_horizontal_corrected_pixels define_pixels + syn keyword mfDef define_whole_blacker_pixels define_whole_pixels + syn keyword mfDef define_whole_vertical_blacker_pixels + syn keyword mfDef define_whole_vertical_pixels downto draw drawdot + syn keyword mfDef endchar erase exitunless fill filldraw fix_units + syn keyword mfDef flex font_coding_scheme font_extra_space + syn keyword mfDef font_identifier font_normal_shrink + syn keyword mfDef font_normal_space font_normal_stretch font_quad + syn keyword mfDef font_size font_slant font_x_height gfcorners gobble + syn keyword mfDef hide imagerules interact italcorr killtext + syn keyword mfDef loggingall lowres_fix makebox makegrid maketicks + syn keyword mfDef mode_def mode_setup nodisplays notransforms numtok + syn keyword mfDef openit penrazor pensquare penstroke pickup + syn keyword mfDef proofoffset proofrule range reflectedabout + syn keyword mfDef rotatedaround screenchars screenrule screenstrokes + syn keyword mfDef shipit showit smode stop superellipse takepower + syn keyword mfDef tracingall tracingnone undraw undrawdot unfill + syn keyword mfDef unfilldraw upto z + syn match mfDef "???" + syn keyword mfVardef bot byte ceiling counterclockwise cutoff decr dir + syn keyword mfVardef direction directionpoint grayfont hround incr + syn keyword mfVardef interpath inverse labelfont labels lft magstep + " Note: nodot is not a vardef, it is used as in makelabel.lft.nodot("5",z5) + " (METAFONT only) + syn keyword mfVardef makelabel max min nodot penlabels penpos + syn keyword mfVardef proofrulethickness round rt savepen slantfont solve + syn keyword mfVardef tensepath titlefont top unitvector vround whatever + syn match mpVardef "\<good\.\%(x\|y\|lft\|rt\|top\|bot\)\>" + syn keyword mfPrimaryDef div dotprod gobbled mod + syn keyword mfSecondaryDef intersectionpoint + syn keyword mfTertiaryDef softjoin thru + syn keyword mfNewInternal blacker currentwindow displaying eps epsilon + syn keyword mfNewInternal infinity join_radius number_of_modes o_correction + syn keyword mfNewInternal pen_bot pen_lft pen_rt pen_top pixels_per_inch + syn keyword mfNewInternal screen_cols screen_rows tolerance + " Predefined constants + syn keyword mfConstant base_name base_version blankpicture ditto down + syn keyword mfConstant fullcircle halfcircle identity left lowres origin + syn keyword mfConstant penspeck proof quartercircle right rulepen smoke + syn keyword mfConstant unitpixel unitsquare up + " Other predefined variables + syn keyword mfVariable aspect_ratio currentpen extra_beginchar + syn keyword mfVariable extra_endchar currentpen_path currentpicture + syn keyword mfVariable currenttransform d extra_setup h localfont mag mode + syn keyword mfVariable mode_name w + " let statements: + syn keyword mfnumExp abs + syn keyword mfPairExp rotatedabout + syn keyword mfCommand bye relax endif -if plain_mf_macros - syn keyword mfMacro abs addto_currentpicture aspect_ratio base_name - syn keyword mfMacro base_version beginchar blacker blankpicture bot bye byte - syn keyword mfMacro capsule_def ceiling change_width clear_pen_memory clearit - syn keyword mfMacro clearpen clearxy counterclockwise culldraw cullit - syn keyword mfMacro currentpen currentpen_path currentpicture - syn keyword mfMacro currenttransform currentwindow cutdraw cutoff d decr - syn keyword mfMacro define_blacker_pixels define_corrected_pixels - syn keyword mfMacro define_good_x_pixels define_good_y_pixels - syn keyword mfMacro define_horizontal_corrected_pixels define_pixels - syn keyword mfMacro define_whole_blacker_pixels define_whole_pixels - syn keyword mfMacro define_whole_vertical_blacker_pixels - syn keyword mfMacro define_whole_vertical_pixels dir direction directionpoint - syn keyword mfMacro displaying ditto div dotprod down downto draw drawdot - syn keyword mfMacro endchar eps epsilon extra_beginchar extra_endchar - syn keyword mfMacro extra_setup erase exitunless fill filldraw fix_units flex - syn keyword mfMacro font_coding_scheme font_extra_space font_identifier - syn keyword mfMacro font_normal_shrink font_normal_space font_normal_stretch - syn keyword mfMacro font_quad font_setup font_size font_slant font_x_height - syn keyword mfMacro fullcircle generate gfcorners gobble gobbled grayfont h - syn keyword mfMacro halfcircle hide hround identity image_rules incr infinity - syn keyword mfMacro interact interpath intersectionpoint inverse italcorr - syn keyword mfMacro join_radius killtext labelfont labels left lft localfont - syn keyword mfMacro loggingall lowres lowres_fix mag magstep makebox makegrid - syn keyword mfMacro makelabel maketicks max min mod mode mode_def mode_name - syn keyword mfMacro mode_setup nodisplays notransforms number_of_modes numtok - syn keyword mfMacro o_correction openit origin pen_bot pen_lft pen_rt pen_top - syn keyword mfMacro penlabels penpos penrazor penspeck pensquare penstroke - syn keyword mfMacro pickup pixels_per_inch proof proofoffset proofrule - syn keyword mfMacro proofrulethickness quartercircle range reflectedabout - syn keyword mfMacro relax right rotatedabout rotatedaround round rt rulepen - syn keyword mfMacro savepen screenchars screen_rows screen_cols screenrule - syn keyword mfMacro screenstrokes shipit showit slantfont smode smoke softjoin - syn keyword mfMacro solve stop superellipse takepower tensepath titlefont - syn keyword mfMacro tolerance top tracingall tracingnone undraw undrawdot - syn keyword mfMacro unfill unfilldraw unitpixel unitsquare unitvector up upto - syn keyword mfMacro vround w whatever + +" By default, METAFONT loads modes.mf, too +if get(g:, "plain_mf_modes", 1) + syn keyword mfConstant APSSixMed AgfaFourZeroZero AgfaThreeFourZeroZero + syn keyword mfConstant AtariNineFive AtariNineSix AtariSLMEightZeroFour + syn keyword mfConstant AtariSMOneTwoFour CItohEightFiveOneZero + syn keyword mfConstant CItohThreeOneZero CanonBJCSixZeroZero CanonCX + syn keyword mfConstant CanonEX CanonLBPLX CanonLBPTen CanonSX ChelgraphIBX + syn keyword mfConstant CompugraphicEightSixZeroZero + syn keyword mfConstant CompugraphicNineSixZeroZero DD DEClarge DECsmall + syn keyword mfConstant DataDiscNew EightThree EpsonAction + syn keyword mfConstant EpsonLQFiveZeroZeroLo EpsonLQFiveZeroZeroMed + syn keyword mfConstant EpsonMXFX EpsonSQEightSevenZero EpsonStylusPro + syn keyword mfConstant EpsonStylusProHigh EpsonStylusProLow + syn keyword mfConstant EpsonStylusProMed FourFour GThreefax HPDeskJet + syn keyword mfConstant HPLaserJetIIISi IBMFourTwoFiveZero IBMFourTwoOneSix + syn keyword mfConstant IBMFourTwoThreeZero IBMFourZeroOneNine + syn keyword mfConstant IBMFourZeroThreeNine IBMFourZeroTwoNine + syn keyword mfConstant IBMProPrinter IBMSixOneFiveFour IBMSixSixSevenZero + syn keyword mfConstant IBMThreeEightOneTwo IBMThreeEightTwoZero + syn keyword mfConstant IBMThreeOneNineThree IBMThreeOneSevenNine + syn keyword mfConstant IBMUlfHolleberg LASevenFive LNOthreR LNOthree + syn keyword mfConstant LNZeroOne LNZeroThree LPSFourZero LPSTwoZero + syn keyword mfConstant LexmarkFourZeroThreeNine LexmarkOptraR + syn keyword mfConstant LexmarkOptraS LinotypeLThreeThreeZero + syn keyword mfConstant LinotypeOneZeroZero LinotypeOneZeroZeroLo + syn keyword mfConstant LinotypeThreeZeroZeroHi MacTrueSize NeXTprinter + syn keyword mfConstant NeXTscreen NecTwoZeroOne Newgen NineOne + syn keyword mfConstant OCESixSevenFiveZeroPS OneTwoZero OneZeroZero + syn keyword mfConstant PrintwareSevenTwoZeroIQ Prism QMSOneSevenTwoFive + syn keyword mfConstant QMSOneSevenZeroZero QMSTwoFourTwoFive RicohA + syn keyword mfConstant RicohFortyEighty RicohFourZeroEightZero RicohLP + syn keyword mfConstant SparcPrinter StarNLOneZero VAXstation VTSix + syn keyword mfConstant VarityperFiveZeroSixZeroW + syn keyword mfConstant VarityperFourThreeZeroZeroHi + syn keyword mfConstant VarityperFourThreeZeroZeroLo + syn keyword mfConstant VarityperFourTwoZeroZero VarityperSixZeroZero + syn keyword mfConstant XeroxDocutech XeroxEightSevenNineZero + syn keyword mfConstant XeroxFourZeroFiveZero XeroxNineSevenZeroZero + syn keyword mfConstant XeroxPhaserSixTwoZeroZeroDP XeroxThreeSevenZeroZero + syn keyword mfConstant Xerox_world agfafzz agfatfzz amiga aps apssixhi + syn keyword mfConstant aselect atariezf atarinf atarins atariotf bitgraph + syn keyword mfConstant bjtenex bjtzzex bjtzzl bjtzzs boise canonbjc + syn keyword mfConstant canonex canonlbp cg cgl cgnszz citohtoz corona crs + syn keyword mfConstant cthreeten cx datadisc declarge decsmall deskjet + syn keyword mfConstant docutech dover dp dpdfezzz eighthre elvira epscszz + syn keyword mfConstant epsdraft epsdrft epsdrftl epsfast epsfastl epshi + syn keyword mfConstant epslo epsmed epsmedl epson epsonact epsonfx epsonl + syn keyword mfConstant epsonlo epsonlol epsonlq epsonsq epstylus epstylwr + syn keyword mfConstant epstyplo epstypmd epstypml epstypro epswlo epswlol + syn keyword mfConstant esphi fourfour gpx gtfax gtfaxhi gtfaxl gtfaxlo + syn keyword mfConstant gtfaxlol help hifax highfax hplaser hprugged ibm_a + syn keyword mfConstant ibmd ibmega ibmegal ibmfzon ibmfztn ibmpp ibmppl + syn keyword mfConstant ibmsoff ibmteot ibmtetz ibmtont ibmtosn ibmtosnl + syn keyword mfConstant ibmvga ibx imagen imagewriter itoh itohl itohtoz + syn keyword mfConstant itohtozl iw jetiiisi kyocera laserjet laserjetfive + syn keyword mfConstant laserjetfivemp laserjetfour laserjetfourthousand + syn keyword mfConstant laserjetfourzerozerozero laserjethi laserjetlo + syn keyword mfConstant laserjettwoonezerozero + syn keyword mfConstant laserjettwoonezerozerofastres lasermaster + syn keyword mfConstant laserwriter lasf lexmarkr lexmarks lexmarku + syn keyword mfConstant linohalf linohi linolo linolttz linoone linosuper + syn keyword mfConstant linothree linothreelo linotzzh ljfive ljfivemp + syn keyword mfConstant ljfour ljfzzz ljfzzzfr ljlo ljtozz ljtozzfr lmaster + syn keyword mfConstant lnotr lnzo lps lpstz lqhires lqlores lqmed lqmedl + syn keyword mfConstant lqmedres lview lviewl lwpro macmag mactrue modes_mf + syn keyword mfConstant ncd nec nechi neclm nectzo newdd newddl nexthi + syn keyword mfConstant nextscreen nextscrn nineone nullmode ocessfz + syn keyword mfConstant okidata okidatal okifourten okifte okihi onetz + syn keyword mfConstant onezz pcprevw pcscreen phaser phaserfs phasertf + syn keyword mfConstant phasertfl phasertl pixpt printware prntware + syn keyword mfConstant proprinter qms qmsesz qmsostf qmsoszz qmstftf ricoh + syn keyword mfConstant ricoha ricohlp ricohsp sherpa sparcptr starnlt + syn keyword mfConstant starnltl styletwo stylewr stylewri stylewriter sun + syn keyword mfConstant supre swtwo toshiba ultre varityper vs vtftzz + syn keyword mfConstant vtftzzhi vtftzzlo vtfzszw vtszz xpstzz xpstzzl + syn keyword mfConstant xrxesnz xrxfzfz xrxnszz xrxtszz + syn keyword mfDef BCPL_string coding_scheme font_face_byte + syn keyword mfDef font_family landscape + syn keyword mfDef mode_extra_info mode_help mode_param + syn keyword mfNewInternal blacker_min endif " Some other basic macro names, e.g., from cmbase, logo, etc. -if !exists("other_mf_macros") - let other_mf_macros = 1 " Set this to '0' if your code gets too colourful - " metapost.vim does so to turn off Metafont macros -endif -if other_mf_macros - syn keyword mfMacro beginlogochar +if get(g:, "other_mf_macros", 1) + syn keyword mfDef beginlogochar + syn keyword mfDef font_setup + syn keyword mfPrimitive generate endif " Numeric tokens -syn match mfNumeric "[-]\=\d\+" -syn match mfNumeric "[-]\=\.\d\+" -syn match mfNumeric "[-]\=\d\+\.\d\+" +syn match mfNumeric "[-]\=\d\+" +syn match mfNumeric "[-]\=\.\d\+" +syn match mfNumeric "[-]\=\d\+\.\d\+" -" Metafont lengths -syn match mfLength "\<\(bp\|cc\|cm\|dd\|in\|mm\|pc\|pt\)\>" -syn match mfLength "\<[-]\=\d\+\(bp\|cc\|cm\|dd\|in\|mm\|pc\|pt\)\#\=\>" -syn match mfLength "\<[-]\=\.\d\+\(bp\|cc\|cm\|dd\|in\|mm\|pc\|pt\)\#\=\>" -syn match mfLength "\<[-]\=\d\+\.\d\+\(bp\|cc\|cm\|dd\|in\|mm\|pc\|pt\)\#\=\>" - -" Metafont coordinates and points -syn match mfCoord "\<[xy]\d\+\>" -syn match mfPoint "\<z\d\+\>" +" METAFONT lengths +syn match mfLength "\<\(bp\|cc\|cm\|dd\|in\|mm\|pc\|pt\)\>" +syn match mfLength "[-]\=\d\+\(bp\|cc\|cm\|dd\|in\|mm\|pc\|pt\)\#\=" +syn match mfLength "[-]\=\.\d\+\(bp\|cc\|cm\|dd\|in\|mm\|pc\|pt\)\#\=" +syn match mfLength "[-]\=\d\+\.\d\+\(bp\|cc\|cm\|dd\|in\|mm\|pc\|pt\)\#\=" " String constants -syn region mfString start=+"+ end=+"+ +syn match mfOpenString /"[^"]*/ +syn region mfString oneline keepend start=+"+ end=+"+ " Comments: -syn match mfComment "%.*$" +syn keyword mfTodoComment contained TODO FIXME XXX DEBUG NOTE +syn match mfComment "%.*$" contains=mfTodoComment,@Spell " synchronizing syn sync maxlines=50 " Define the default highlighting -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_mf_syntax_inits") - if version < 508 - let did_mf_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink mfBoolExp Statement - HiLink mfNumExp Statement - HiLink mfInternal Identifier - HiLink mfPairExp Statement - HiLink mfPathExp Statement - HiLink mfPenExp Statement - HiLink mfPicExp Statement - HiLink mfStringExp Statement - HiLink mfCommand Statement - HiLink mfType Type - HiLink mfStatement Statement - HiLink mfDefinition Statement - HiLink mfCondition Conditional - HiLink mfPrimitive Statement - HiLink mfMacro Macro - HiLink mfCoord Identifier - HiLink mfPoint Identifier - HiLink mfNumeric Number - HiLink mfLength Number - HiLink mfComment Comment - HiLink mfString String - - delcommand HiLink -endif +hi def link mfBoolExp Statement +hi def link mfNumExp Statement +hi def link mfPairExp Statement +hi def link mfPathExp Statement +hi def link mfPenExp Statement +hi def link mfPicExp Statement +hi def link mfStringExp Statement +hi def link mfInternal Identifier +hi def link mfCommand Statement +hi def link mfType Type +hi def link mfStatement Statement +hi def link mfDefinition Statement +hi def link mfCondition Conditional +hi def link mfPrimitive Statement +hi def link mfDef Function +hi def link mfVardef mfDef +hi def link mfPrimaryDef mfDef +hi def link mfSecondaryDef mfDef +hi def link mfTertiaryDef mfDef +hi def link mfCoord Identifier +hi def link mfPoint Identifier +hi def link mfNumeric Number +hi def link mfLength Number +hi def link mfComment Comment +hi def link mfString String +hi def link mfOpenString Todo +hi def link mfSuffixParam Label +hi def link mfNewInternal mfInternal +hi def link mfVariable Identifier +hi def link mfConstant Constant +hi def link mfTodoComment Todo let b:current_syntax = "mf" -" vim: ts=8 +" vim:sw=2 diff --git a/runtime/syntax/mgl.vim b/runtime/syntax/mgl.vim index 55ae137f2f..f7bc617f5a 100644 --- a/runtime/syntax/mgl.vim +++ b/runtime/syntax/mgl.vim @@ -6,9 +6,8 @@ " " $Id: mgl.vim,v 1.1 2006/02/21 22:08:20 vimboss Exp $ " -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -84,43 +83,33 @@ syn keyword mglPredefined exception " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_mgl_syn_inits") - if version < 508 - let did_mgl_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink mglBoolean Boolean - HiLink mglComment Comment - HiLink mglConditional Conditional - HiLink mglConstant Constant - HiLink mglException Exception - HiLink mglFunction Function - HiLink mglLabel Label - HiLink mglMatrixDelimiter Identifier - HiLink mglNumber Number - HiLink mglHexNumber Number - HiLink mglCharacter Number - HiLink mglIpAddr Number - HiLink mglOperator Operator - HiLink mglPredefined mglFunction - HiLink mglPreProc PreProc - HiLink mglRepeat Repeat - HiLink mglStatement Statement - HiLink mglString String - HiLink mglStringEscape Special - HiLink mglStringEscapeGPC Special - HiLink mglStringError Error - HiLink mglStruct mglStatement - HiLink mglSymbolOperator mglOperator - HiLink mglType Type - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link mglBoolean Boolean +hi def link mglComment Comment +hi def link mglConditional Conditional +hi def link mglConstant Constant +hi def link mglException Exception +hi def link mglFunction Function +hi def link mglLabel Label +hi def link mglMatrixDelimiter Identifier +hi def link mglNumber Number +hi def link mglHexNumber Number +hi def link mglCharacter Number +hi def link mglIpAddr Number +hi def link mglOperator Operator +hi def link mglPredefined mglFunction +hi def link mglPreProc PreProc +hi def link mglRepeat Repeat +hi def link mglStatement Statement +hi def link mglString String +hi def link mglStringEscape Special +hi def link mglStringEscapeGPC Special +hi def link mglStringError Error +hi def link mglStruct mglStatement +hi def link mglSymbolOperator mglOperator +hi def link mglType Type + let b:current_syntax = "mgl" diff --git a/runtime/syntax/mgp.vim b/runtime/syntax/mgp.vim index 76b96612e2..7227804550 100644 --- a/runtime/syntax/mgp.vim +++ b/runtime/syntax/mgp.vim @@ -10,11 +10,8 @@ " SPAM is _NOT_ welcome - be ready to be reported! -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syn clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -48,36 +45,25 @@ syn match mgpNoDefault +^%nodefault$+ " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_mgp_syn_inits") - let did_mgp_syn_inits = 1 - if version < 508 - let did_mgp_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink mgpLineSkip Special +hi def link mgpLineSkip Special - HiLink mgpHash mgpComment - HiLink mgpPercent mgpComment - HiLink mgpComment Comment +hi def link mgpHash mgpComment +hi def link mgpPercent mgpComment +hi def link mgpComment Comment - HiLink mgpCommand Identifier +hi def link mgpCommand Identifier - HiLink mgpLine Type +hi def link mgpLine Type - HiLink mgpFile String - HiLink mgpSize Number - HiLink mgpValue Number +hi def link mgpFile String +hi def link mgpSize Number +hi def link mgpValue Number - HiLink mgpPage mgpDefine - HiLink mgpNoDefault mgpDefine - HiLink mgpDefine Define +hi def link mgpPage mgpDefine +hi def link mgpNoDefault mgpDefine +hi def link mgpDefine Define - delcommand HiLink -endif let b:current_syntax = "mgp" diff --git a/runtime/syntax/mma.vim b/runtime/syntax/mma.vim index c63beb1195..0683adc573 100644 --- a/runtime/syntax/mma.vim +++ b/runtime/syntax/mma.vim @@ -35,9 +35,8 @@ " fix nesting " finish populating popular symbols -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -283,47 +282,38 @@ syntax sync fromstart "set foldnestmax=1 "set foldminlines=15 -if version >= 508 || !exists("did_mma_syn_inits") - if version < 508 - let did_mma_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - " NOTE - the following links are not guaranteed to - " look good under all colorschemes. You might need to - " :so $VIMRUNTIME/syntax/hitest.vim and tweak these to - " look good in yours - - - HiLink mmaComment Comment - HiLink mmaCommentStar Comment - HiLink mmaFunctionComment Comment - HiLink mmaLooseQuote Comment - HiLink mmaGenericFunction Function - HiLink mmaVariable Identifier -" HiLink mmaSymbol Identifier - HiLink mmaOperator Operator - HiLink mmaPatternOp Operator - HiLink mmaPureFunction Operator - HiLink mmaString String - HiLink mmaCommentString String - HiLink mmaUnicode String - HiLink mmaMessage Type - HiLink mmaNumber Type - HiLink mmaPattern Type - HiLink mmaError Error - HiLink mmaFixme Error - HiLink mmaPatternError Error - HiLink mmaTodo Todo - HiLink mmaemPHAsis Special - HiLink mmaFunctionTitle Special - HiLink mmaMessageType Special - HiLink mmaItem Preproc - - delcommand HiLink -endif + +" NOTE - the following links are not guaranteed to +" look good under all colorschemes. You might need to +" :so $VIMRUNTIME/syntax/hitest.vim and tweak these to +" look good in yours + + +hi def link mmaComment Comment +hi def link mmaCommentStar Comment +hi def link mmaFunctionComment Comment +hi def link mmaLooseQuote Comment +hi def link mmaGenericFunction Function +hi def link mmaVariable Identifier +" hi def link mmaSymbol Identifier +hi def link mmaOperator Operator +hi def link mmaPatternOp Operator +hi def link mmaPureFunction Operator +hi def link mmaString String +hi def link mmaCommentString String +hi def link mmaUnicode String +hi def link mmaMessage Type +hi def link mmaNumber Type +hi def link mmaPattern Type +hi def link mmaError Error +hi def link mmaFixme Error +hi def link mmaPatternError Error +hi def link mmaTodo Todo +hi def link mmaemPHAsis Special +hi def link mmaFunctionTitle Special +hi def link mmaMessageType Special +hi def link mmaItem Preproc + let b:current_syntax = "mma" diff --git a/runtime/syntax/mmix.vim b/runtime/syntax/mmix.vim index 79ca781402..39e209336e 100644 --- a/runtime/syntax/mmix.vim +++ b/runtime/syntax/mmix.vim @@ -9,9 +9,8 @@ " Limitations: Comments must start with either % or // " (preferably %, Knuth-Style) -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -119,44 +118,34 @@ syn match mmixRegister "r[A-Z]" syn keyword mmixRegister rBB rTT rWW rXX rYY rZZ " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_mmix_syntax_inits") - if version < 508 - let did_mmix_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - " The default methods for highlighting. Can be overridden later - HiLink mmixAt Type - HiLink mmixPseudo Type - HiLink mmixRegister Special - HiLink mmixSegments Type - - HiLink mmixLabel Special - HiLink mmixComment Comment - HiLink mmixOpcode Keyword - - HiLink hexNumber Number - HiLink decNumber Number - HiLink octNumber Number - - HiLink mmixString String - HiLink mmixChar String - - HiLink mmixType Type - HiLink mmixIdentifier Normal - HiLink mmixSpecialComment Comment - - " My default color overrides: - " hi mmixSpecialComment ctermfg=red - "hi mmixLabel ctermfg=lightcyan - " hi mmixType ctermbg=black ctermfg=brown - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +" The default methods for highlighting. Can be overridden later +hi def link mmixAt Type +hi def link mmixPseudo Type +hi def link mmixRegister Special +hi def link mmixSegments Type + +hi def link mmixLabel Special +hi def link mmixComment Comment +hi def link mmixOpcode Keyword + +hi def link hexNumber Number +hi def link decNumber Number +hi def link octNumber Number + +hi def link mmixString String +hi def link mmixChar String + +hi def link mmixType Type +hi def link mmixIdentifier Normal +hi def link mmixSpecialComment Comment + +" My default color overrides: +" hi mmixSpecialComment ctermfg=red +"hi mmixLabel ctermfg=lightcyan +" hi mmixType ctermbg=black ctermfg=brown + let b:current_syntax = "mmix" diff --git a/runtime/syntax/mmp.vim b/runtime/syntax/mmp.vim index 0117e77925..d0b9f7cfb5 100644 --- a/runtime/syntax/mmp.vim +++ b/runtime/syntax/mmp.vim @@ -5,11 +5,8 @@ " URL: http://ronware.org/wiki/vim/mmp " Filetypes: *.mmp -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -34,8 +31,7 @@ syn match mmpNumber "0x\x\+" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet +" Only when an item doesn't have highlighting yet if !exists("did_mmp_syntax_inits") let did_mmp_syntax_inits=1 diff --git a/runtime/syntax/modsim3.vim b/runtime/syntax/modsim3.vim index 04e9ab9ab6..ce35033402 100644 --- a/runtime/syntax/modsim3.vim +++ b/runtime/syntax/modsim3.vim @@ -12,10 +12,8 @@ " " very basic things only (based on the modula2 and c files). -if version < 600 - " Remove any old syntax stuff hanging around - syn clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -77,31 +75,21 @@ syn region modsim3String start=+"+ end=+"+ syn match modsim3Literal "'[^']'\|''''" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_modsim3_syntax_inits") - if version < 508 - let did_modsim3_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - " The default methods for highlighting. Can be overridden later - HiLink modsim3Keyword Statement - HiLink modsim3Block Statement - HiLink modsim3Comment1 Comment - HiLink modsim3Comment2 Comment - HiLink modsim3String String - HiLink modsim3Literal Character - HiLink modsim3Include Statement - HiLink modsim3Type Type - HiLink modsim3ParenError Error - HiLink modsim3Builtin Function - HiLink modsim3BuiltinNoParen Function - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +" The default methods for highlighting. Can be overridden later +hi def link modsim3Keyword Statement +hi def link modsim3Block Statement +hi def link modsim3Comment1 Comment +hi def link modsim3Comment2 Comment +hi def link modsim3String String +hi def link modsim3Literal Character +hi def link modsim3Include Statement +hi def link modsim3Type Type +hi def link modsim3ParenError Error +hi def link modsim3Builtin Function +hi def link modsim3BuiltinNoParen Function + let b:current_syntax = "modsim3" diff --git a/runtime/syntax/modula2.vim b/runtime/syntax/modula2.vim index 3018900e80..4a14cf1f6f 100644 --- a/runtime/syntax/modula2.vim +++ b/runtime/syntax/modula2.vim @@ -4,11 +4,8 @@ " based on original work of Bram Moolenaar <Bram@vim.org> " Last Change: 2001 May 09 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -54,32 +51,22 @@ syn region modula2String start="'" end="'" syn region modula2Set start="{" end="}" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_modula2_syntax_inits") - if version < 508 - let did_modula2_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink modula2Ident Identifier - HiLink modula2StdConst Boolean - HiLink modula2Type Identifier - HiLink modula2StdFunc Identifier - HiLink modula2Header Type - HiLink modula2Keyword Statement - HiLink modula2AttKeyword PreProc - HiLink modula2Comment Comment - " The following is just a matter of taste (you want to try this instead): - " hi modula2Comment term=bold ctermfg=DarkBlue guifg=Blue gui=bold - HiLink modula2Todo Todo - HiLink modula2String String - HiLink modula2Set String +hi def link modula2Ident Identifier +hi def link modula2StdConst Boolean +hi def link modula2Type Identifier +hi def link modula2StdFunc Identifier +hi def link modula2Header Type +hi def link modula2Keyword Statement +hi def link modula2AttKeyword PreProc +hi def link modula2Comment Comment +" The following is just a matter of taste (you want to try this instead): +" hi modula2Comment term=bold ctermfg=DarkBlue guifg=Blue gui=bold +hi def link modula2Todo Todo +hi def link modula2String String +hi def link modula2Set String - delcommand HiLink -endif let b:current_syntax = "modula2" diff --git a/runtime/syntax/modula3.vim b/runtime/syntax/modula3.vim index d6f72afbca..d9b89ca7ce 100644 --- a/runtime/syntax/modula3.vim +++ b/runtime/syntax/modula3.vim @@ -6,11 +6,8 @@ " Basic things only... " Based on the modula 2 syntax file -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -46,24 +43,14 @@ syn region modula3String start=+"+ end=+"+ syn region modula3String start=+'+ end=+'+ " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_modula3_syntax_inits") - if version < 508 - let did_modula3_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - " The default methods for highlighting. Can be overridden later - HiLink modula3Keyword Statement - HiLink modula3Block PreProc - HiLink modula3Comment Comment - HiLink modula3String String +" The default methods for highlighting. Can be overridden later +hi def link modula3Keyword Statement +hi def link modula3Block PreProc +hi def link modula3Comment Comment +hi def link modula3String String - delcommand HiLink -endif let b:current_syntax = "modula3" diff --git a/runtime/syntax/monk.vim b/runtime/syntax/monk.vim index afe2b56190..3af810173a 100644 --- a/runtime/syntax/monk.vim +++ b/runtime/syntax/monk.vim @@ -21,11 +21,8 @@ " Initializing: -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -60,11 +57,7 @@ syn region monkUnquote matchgroup=Delimiter start=",@#(" end=")" contains=ALLBUT " R5RS Scheme Functions and Syntax: -if version < 600 - set iskeyword=33,35-39,42-58,60-90,94,95,97-122,126,_ -else - setlocal iskeyword=33,35-39,42-58,60-90,94,95,97-122,126,_ -endif +setlocal iskeyword=33,35-39,42-58,60-90,94,95,97-122,126,_ syn keyword monkSyntax lambda and or if cond case define let let* letrec syn keyword monkSyntax begin do delay set! else => @@ -201,32 +194,22 @@ syn sync match matchPlace grouphere NONE "^[^ \t]" " ... i.e. synchronize on a line that starts at the left margin " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_monk_syntax_inits") - if version < 508 - let did_monk_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink monkSyntax Statement - HiLink monkFunc Function - - HiLink monkString String - HiLink monkChar Character - HiLink monkNumber Number - HiLink monkBoolean Boolean - - HiLink monkDelimiter Delimiter - HiLink monkConstant Constant - - HiLink monkComment Comment - HiLink monkError Error - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link monkSyntax Statement +hi def link monkFunc Function + +hi def link monkString String +hi def link monkChar Character +hi def link monkNumber Number +hi def link monkBoolean Boolean + +hi def link monkDelimiter Delimiter +hi def link monkConstant Constant + +hi def link monkComment Comment +hi def link monkError Error + let b:current_syntax = "monk" diff --git a/runtime/syntax/moo.vim b/runtime/syntax/moo.vim index 10c5d3b4bc..617058f8e3 100644 --- a/runtime/syntax/moo.vim +++ b/runtime/syntax/moo.vim @@ -4,8 +4,8 @@ " Last Change: 2001 Oct 06 " Note: Requires Vim 6.0 or above -" Quit when a syntax file was already loaded -if version < 600 || exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif diff --git a/runtime/syntax/mp.vim b/runtime/syntax/mp.vim index c0fd60b3da..a8fa36fe0a 100644 --- a/runtime/syntax/mp.vim +++ b/runtime/syntax/mp.vim @@ -1,132 +1,769 @@ " Vim syntax file -" Language: MetaPost -" Maintainer: Andreas Scherer <andreas.scherer@pobox.com> -" Last Change: April 30, 2001 - -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syn clear -elseif exists("b:current_syntax") +" Language: MetaPost +" Maintainer: Nicola Vitacolonna <nvitacolonna@gmail.com> +" Former Maintainers: Andreas Scherer <andreas.scherer@pobox.com> +" Last Change: 2016 Oct 14 + +if exists("b:current_syntax") finish endif -let plain_mf_macros = 0 " plain.mf has no special meaning for MetaPost -let other_mf_macros = 0 " cmbase.mf, logo.mf, ... neither +let s:cpo_sav = &cpo +set cpo&vim + +if exists("g:plain_mf_macros") + let s:plain_mf_macros = g:plain_mf_macros +endif +if exists("g:plain_mf_modes") + let s:plain_mf_modes = g:plain_mf_modes +endif +if exists("g:other_mf_macros") + let s:other_mf_macros = g:other_mf_macros +endif + +let g:plain_mf_macros = 0 " plain.mf has no special meaning for MetaPost +let g:plain_mf_modes = 0 " No METAFONT modes +let g:other_mf_macros = 0 " cmbase.mf, logo.mf, ... neither -" Read the Metafont syntax to start with -if version < 600 - source <sfile>:p:h/mf.vim +" Read the METAFONT syntax to start with +runtime! syntax/mf.vim +unlet b:current_syntax " Necessary for syn include below + +" Restore the value of existing global variables +if exists("s:plain_mf_macros") + let g:plain_mf_macros = s:plain_mf_macros +else + unlet g:plain_mf_macros +endif +if exists("s:plain_mf_modes") + let g:plain_mf_modes = s:plain_mf_modes +else + unlet g:plain_mf_modes +endif +if exists("s:other_mf_macros") + let g:other_mf_macros = s:other_mf_macros else - runtime! syntax/mf.vim + unlet g:other_mf_macros endif -" MetaPost has TeX inserts for typeset labels -" verbatimtex, btex, and etex will be treated as keywords -syn match mpTeXbegin "\(verbatimtex\|btex\)" -syn match mpTeXend "etex" -syn region mpTeXinsert start="\(verbatimtex\|btex\)"hs=e+1 end="etex"he=s-1 contains=mpTeXbegin,mpTeXend keepend +" Use TeX highlighting inside verbatimtex/btex... etex +syn include @MPTeX syntax/tex.vim +unlet b:current_syntax +" These are defined as keywords rather than using matchgroup +" in order to make them available to syntaxcomplete. +syn keyword mpTeXdelim btex etex verbatimtex contained +syn region mpTeXinsert + \ start=/\<verbatimtex\>\|\<btex\>/rs=e+1 + \ end=/\<etex\>/re=s-1 keepend + \ contains=@MPTeX,mpTeXdelim -" MetaPost primitives not found in Metafont -syn keyword mpInternal bluepart clip color dashed fontsize greenpart infont -syn keyword mpInternal linecap linejoin llcorner lrcorner miterlimit mpxbreak -syn keyword mpInternal prologues redpart setbounds tracinglostchars -syn keyword mpInternal truecorners ulcorner urcorner withcolor +" iskeyword must be set after the syn include above, because tex.vim sets `syn +" iskeyword`. Note that keywords do not contain numbers (numbers are +" subscripts) +syntax iskeyword @,_ -" Metafont primitives not found in MetaPost -syn keyword notDefined autorounding chardx chardy fillin granularity hppp -syn keyword notDefined proofing smoothing tracingedges tracingpens -syn keyword notDefined turningcheck vppp xoffset yoffset +" MetaPost primitives not found in METAFONT +syn keyword mpBoolExp bounded clipped filled stroked textual arclength +syn keyword mpNumExp arctime blackpart bluepart colormodel cyanpart +syn keyword mpNumExp fontsize greenpart greypart magentapart redpart +syn keyword mpPairExp yellowpart llcorner lrcorner ulcorner urcorner +" envelope is seemingly undocumented, but it exists since mpost 1.003. +" The syntax is: envelope <polygonal pen> of <path primary>. For example, +" path p; +" p := envelope pensquare of (up--left); +" (Thanks to Daniel H. Luecking for the example!) +syn keyword mpPathExp envelope pathpart +syn keyword mpPenExp penpart +syn keyword mpPicExp dashpart glyph infont +syn keyword mpStringExp fontpart readfrom textpart +syn keyword mpType cmykcolor color rgbcolor +" Other MetaPost primitives listed in the manual +syn keyword mpPrimitive mpxbreak within +" Internal quantities not found in METAFONT +" (Table 6 in MetaPost: A User's Manual) +syn keyword mpInternal defaultcolormodel hour minute linecap linejoin +syn keyword mpInternal miterlimit mpprocset mpversion numberprecision +syn keyword mpInternal numbersystem outputfilename outputformat +syn keyword mpInternal outputformatoptions outputtemplate prologues +syn keyword mpInternal restoreclipcolor tracinglostchars troffmode +syn keyword mpInternal truecorners +" List of commands not found in METAFONT (from MetaPost: A User's Manual) +syn keyword mpCommand clip closefrom dashed filenametemplate fontmapfile +syn keyword mpCommand fontmapline setbounds withcmykcolor withcolor +syn keyword mpCommand withgreyscale withoutcolor withpostscript +syn keyword mpCommand withprescript withrgbcolor write +" METAFONT internal variables not found in MetaPost +syn keyword notDefined autorounding chardx chardy fillin granularity +syn keyword notDefined proofing smoothing tracingedges tracingpens +syn keyword notDefined turningcheck xoffset yoffset +" Suffix defined only in METAFONT: +syn keyword notDefined nodot +" Other not implemented primitives (see MetaPost: A User's Manual, ยงC.1) +syn keyword notDefined cull display openwindow numspecial totalweight +syn keyword notDefined withweight " Keywords defined by plain.mp -if !exists("plain_mp_macros") - let plain_mp_macros = 1 " Set this to '0' if your source gets too colourful -endif -if plain_mp_macros - syn keyword mpMacro ahangle ahlength background bbox bboxmargin beginfig - syn keyword mpMacro beveled black blue buildcycle butt center cutafter - syn keyword mpMacro cutbefore cuttings dashpattern defaultfont defaultpen - syn keyword mpMacro defaultscale dotlabel dotlabels drawarrow drawdblarrow - syn keyword mpMacro drawoptions endfig evenly extra_beginfig extra_endfig - syn keyword mpMacro green label labeloffset mitered red rounded squared - syn keyword mpMacro thelabel white base_name base_version - syn keyword mpMacro upto downto exitunless relax gobble gobbled - syn keyword mpMacro interact loggingall tracingall tracingnone - syn keyword mpMacro eps epsilon infinity right left up down origin - syn keyword mpMacro quartercircle halfcircle fullcircle unitsquare identity - syn keyword mpMacro blankpicture withdots ditto EOF pensquare penrazor - syn keyword mpMacro penspeck whatever abs round ceiling byte dir unitvector - syn keyword mpMacro inverse counterclockwise tensepath mod div dotprod - syn keyword mpMacro takepower direction directionpoint intersectionpoint - syn keyword mpMacro softjoin incr decr reflectedabout rotatedaround - syn keyword mpMacro rotatedabout min max flex superellipse interpath - syn keyword mpMacro magstep currentpen currentpen_path currentpicture - syn keyword mpMacro fill draw filldraw drawdot unfill undraw unfilldraw - syn keyword mpMacro undrawdot erase cutdraw image pickup numeric_pickup - syn keyword mpMacro pen_lft pen_rt pen_top pen_bot savepen clearpen - syn keyword mpMacro clear_pen_memory lft rt top bot ulft urt llft lrt - syn keyword mpMacro penpos penstroke arrowhead makelabel labels penlabel - syn keyword mpMacro range numtok thru clearxy clearit clearpen pickup - syn keyword mpMacro shipit bye hide stop solve +if get(g:, "plain_mp_macros", 1) || get(g:, "mp_metafun_macros", 0) + syn keyword mpDef beginfig clear_pen_memory clearit clearpen clearpen + syn keyword mpDef clearxy colorpart cutdraw downto draw drawarrow + syn keyword mpDef drawdblarrow drawdot drawoptions endfig erase + syn keyword mpDef exitunless fill filldraw flex gobble hide interact + syn keyword mpDef label loggingall makelabel numtok penstroke pickup + syn keyword mpDef range reflectedabout rotatedaround shipit + syn keyword mpDef stop superellipse takepower tracingall tracingnone + syn keyword mpDef undraw undrawdot unfill unfilldraw upto + syn match mpDef "???" + syn keyword mpVardef arrowhead bbox bot buildcycle byte ceiling center + syn keyword mpVardef counterclockwise decr dir direction directionpoint + syn keyword mpVardef dotlabel dotlabels image incr interpath inverse + syn keyword mpVardef labels lft magstep max min penlabels penpos round + syn keyword mpVardef rt savepen solve tensepath thelabel top unitvector + syn keyword mpVardef whatever z + syn keyword mpPrimaryDef div dotprod gobbled mod + syn keyword mpSecondaryDef intersectionpoint + syn keyword mpTertiaryDef cutafter cutbefore softjoin thru + syn keyword mpNewInternal ahangle ahlength bboxmargin beveled butt defaultpen + syn keyword mpNewInternal defaultscale dotlabeldiam eps epsilon infinity + syn keyword mpNewInternal join_radius labeloffset mitered pen_bot pen_lft + syn keyword mpNewInternal pen_rt pen_top rounded squared tolerance + " Predefined constants + syn keyword mpConstant EOF background base_name base_version black + syn keyword mpConstant blankpicture blue ditto down evenly fullcircle + syn keyword mpConstant green halfcircle identity left origin penrazor + syn keyword mpConstant penspeck pensquare quartercircle red right + syn keyword mpConstant unitsquare up white withdots + " Other predefined variables + syn keyword mpVariable currentpen currentpen_path currentpicture cuttings + syn keyword mpVariable defaultfont extra_beginfig extra_endfig + syn match mpVariable /\<\%(laboff\|labxf\|labyf\)\>/ + syn match mpVariable /\<\%(laboff\|labxf\|labyf\)\.\%(lft\|rt\|bot\|top\|ulft\|urt\|llft\|lrt\)\>/ + " let statements: + syn keyword mpnumExp abs + syn keyword mpDef rotatedabout + syn keyword mpCommand bye relax + " on and off are not technically keywords, but it is nice to highlight them + " inside dashpattern(). + syn keyword mpOnOff off on contained + syn keyword mpDash dashpattern contained + syn region mpDashPattern + \ start="dashpattern\s*" + \ end=")"he=e-1 + \ contains=mfNumeric,mfLength,mpOnOff,mpDash endif " Keywords defined by mfplain.mp -if !exists("mfplain_mp_macros") - let mfplain_mp_macros = 0 " Set this to '1' to include these macro names -endif -if mfplain_mp_macros - syn keyword mpMacro beginchar blacker capsule_def change_width - syn keyword mpMacro define_blacker_pixels define_corrected_pixels - syn keyword mpMacro define_good_x_pixels define_good_y_pixels - syn keyword mpMacro define_horizontal_corrected_pixels - syn keyword mpMacro define_pixels define_whole_blacker_pixels - syn keyword mpMacro define_whole_vertical_blacker_pixels - syn keyword mpMacro define_whole_vertical_pixels endchar - syn keyword mpMacro extra_beginchar extra_endchar extra_setup - syn keyword mpMacro font_coding_scheme font_extra_space font_identifier - syn keyword mpMacro font_normal_shrink font_normal_space - syn keyword mpMacro font_normal_stretch font_quad font_size - syn keyword mpMacro font_slant font_x_height italcorr labelfont - syn keyword mpMacro makebox makegrid maketicks mode_def mode_setup - syn keyword mpMacro o_correction proofrule proofrulethickness rulepen smode - +if get(g:, "mfplain_mp_macros", 0) + syn keyword mpDef beginchar capsule_def change_width + syn keyword mpDef define_blacker_pixels define_corrected_pixels + syn keyword mpDef define_good_x_pixels define_good_y_pixels + syn keyword mpDef define_horizontal_corrected_pixels define_pixels + syn keyword mpDef define_whole_blacker_pixels define_whole_pixels + syn keyword mpDef define_whole_vertical_blacker_pixels + syn keyword mpDef define_whole_vertical_pixels endchar + syn keyword mpDef font_coding_scheme font_extra_space font_identifier + syn keyword mpDef font_normal_shrink font_normal_space + syn keyword mpDef font_normal_stretch font_quad font_size font_slant + syn keyword mpDef font_x_height italcorr labelfont lowres_fix makebox + syn keyword mpDef makegrid maketicks mode_def mode_setup proofrule + syn keyword mpDef smode + syn keyword mpVardef hround proofrulethickness vround + syn keyword mpNewInternal blacker o_correction + syn keyword mpVariable extra_beginchar extra_endchar extra_setup rulepen " plus some no-ops, also from mfplain.mp - syn keyword mpMacro cullit currenttransform gfcorners grayfont hround - syn keyword mpMacro imagerules lowres_fix nodisplays notransforms openit - syn keyword mpMacro proofoffset screenchars screenrule screenstrokes - syn keyword mpMacro showit slantfont titlefont unitpixel vround + syn keyword mpDef cull cullit gfcorners imagerules nodisplays + syn keyword mpDef notransforms openit proofoffset screenchars + syn keyword mpDef screenrule screenstrokes showit + syn keyword mpVardef grayfont slantfont titlefont + syn keyword mpVariable currenttransform + syn keyword mpConstant unitpixel + " These are not listed in the MetaPost manual, and some are ignored by + " MetaPost, but are nonetheless defined in mfplain.mp + syn keyword mpDef killtext + syn match mpVardef "\<good\.\%(x\|y\|lft\|rt\|top\|bot\)\>" + syn keyword mpVariable aspect_ratio localfont mag mode mode_name + syn keyword mpVariable proofcolor + syn keyword mpConstant lowres proof smoke + syn keyword mpNewInternal autorounding bp_per_pixel granularity + syn keyword mpNewInternal number_of_modes proofing smoothing turningcheck endif -" Keywords defined by other macro packages, e.g., boxes.mp -if !exists("other_mp_macros") - let other_mp_macros = 1 " Set this to '0' if your source gets too colourful -endif -if other_mp_macros - syn keyword mpMacro circmargin defaultdx defaultdy - syn keyword mpMacro boxit boxjoin bpath circleit drawboxed drawboxes - syn keyword mpMacro drawunboxed fixpos fixsize pic +" Keywords defined by all base macro packages: +" - (r)boxes.mp +" - format.mp +" - graph.mp +" - marith.mp +" - sarith.mp +" - string.mp +" - TEX.mp +if get(g:, "other_mp_macros", 1) + " boxes and rboxes + syn keyword mpDef boxjoin drawboxed drawboxes drawunboxed + syn keyword mpNewInternal circmargin defaultdx defaultdy rbox_radius + syn keyword mpVardef boxit bpath circleit fixpos fixsize generic_declare + syn keyword mpVardef generic_redeclare generisize pic rboxit str_prefix + " format + syn keyword mpVardef Mformat format init_numbers roundd + syn keyword mpVariable Fe_base Fe_plus + syn keyword mpConstant Ten_to + " graph + syn keyword mpDef Gfor Gxyscale OUT auto begingraph endgraph gdata + syn keyword mpDef gdraw gdrawarrow gdrawdblarrow gfill plot + syn keyword mpVardef augment autogrid frame gdotlabel glabel grid itick + syn keyword mpVardef otick + syn keyword mpVardef Mreadpath setcoords setrange + syn keyword mpNewInternal Gmarks Gminlog Gpaths linear log + syn keyword mpVariable Autoform Gemarks Glmarks Gumarks + syn keyword mpConstant Gtemplate + syn match mpVariable /Gmargin\.\%(low\|high\)/ + " marith + syn keyword mpVardef Mabs Meform Mexp Mexp_str Mlog Mlog_Str Mlog_str + syn keyword mpPrimaryDef Mdiv Mmul + syn keyword mpSecondaryDef Madd Msub + syn keyword mpTertiaryDef Mleq + syn keyword mpNewInternal Mten Mzero + " sarith + syn keyword mpVardef Sabs Scvnum + syn keyword mpPrimaryDef Sdiv Smul + syn keyword mpSecondaryDef Sadd Ssub + syn keyword mpTertiaryDef Sleq Sneq + " string + syn keyword mpVardef cspan isdigit loptok + " TEX + syn keyword mpVardef TEX TEXPOST TEXPRE endif +" Up to date as of 23-Sep-2016. +if get(b:, 'mp_metafun_macros', get(g:, 'mp_metafun_macros', 0)) + " Highlight TeX keywords (for use in ConTeXt documents) + syn match mpTeXKeyword '\\[a-zA-Z@]\+' + + " These keywords have been added manually. + syn keyword mpPrimitive runscript + + " The following MetaFun keywords have been extracted automatically from + " ConTeXt source code. They include all "public" macros (where a macro is + " considered public if and only if it does not start with _, mfun_, mlib_, or + " do_, and it does not end with _), all "public" unsaved variables, and all + " `let` statements. + + " mp-abck.mpiv + syn keyword mpDef abck_grid_line anchor_box box_found boxfilloptions + syn keyword mpDef boxgridoptions boxlineoptions draw_multi_pars + syn keyword mpDef draw_multi_side draw_multi_side_path freeze_box + syn keyword mpDef initialize_box initialize_box_pos + syn keyword mpDef multi_side_draw_options show_multi_kind + syn keyword mpDef show_multi_pars + syn keyword mpVardef abck_baseline_grid abck_draw_path abck_graphic_grid + syn keyword mpVariable boxdashtype boxfilloffset boxfilltype + syn keyword mpVariable boxgriddirection boxgriddistance boxgridshift + syn keyword mpVariable boxgridtype boxgridwidth boxlineoffset + syn keyword mpVariable boxlineradius boxlinetype boxlinewidth multikind + syn keyword mpConstant context_abck + " mp-apos.mpiv + syn keyword mpDef anch_sidebars_draw boxfilloptions boxlineoptions + syn keyword mpDef connect_positions + syn keyword mpConstant context_apos + " mp-asnc.mpiv + syn keyword mpDef FlushSyncTasks ProcessSyncTask ResetSyncTasks + syn keyword mpDef SetSyncColor SetSyncThreshold SyncTask + syn keyword mpVardef PrepareSyncTasks SyncBox TheSyncColor + syn keyword mpVardef TheSyncThreshold + syn keyword mpVariable CurrentSyncClass NOfSyncPaths SyncColor + syn keyword mpVariable SyncLeftOffset SyncPaths SyncTasks SyncThreshold + syn keyword mpVariable SyncThresholdMethod SyncWidth + syn keyword mpConstant context_asnc + " mp-back.mpiv + syn keyword mpDef some_double_back some_hash + syn keyword mpVariable back_nillcolor + syn keyword mpConstant context_back + " mp-bare.mpiv + syn keyword mpVardef colordecimals rawtextext + syn keyword mpPrimaryDef infont + syn keyword mpConstant context_bare + " mp-base.mpiv + " This is essentially plain.mp with only a few keywords added + syn keyword mpNumExp graypart + syn keyword mpType graycolor greycolor + syn keyword mpConstant cyan magenta yellow + " mp-butt.mpiv + syn keyword mpDef predefinedbutton some_button + syn keyword mpConstant context_butt + " mp-char.mpiv + syn keyword mpDef flow_begin_chart flow_begin_sub_chart + syn keyword mpDef flow_chart_draw_comment flow_chart_draw_exit + syn keyword mpDef flow_chart_draw_label flow_chart_draw_text + syn keyword mpDef flow_clip_chart flow_collapse_points + syn keyword mpDef flow_connect_bottom_bottom flow_connect_bottom_left + syn keyword mpDef flow_connect_bottom_right flow_connect_bottom_top + syn keyword mpDef flow_connect_left_bottom flow_connect_left_left + syn keyword mpDef flow_connect_left_right flow_connect_left_top + syn keyword mpDef flow_connect_right_bottom flow_connect_right_left + syn keyword mpDef flow_connect_right_right flow_connect_right_top + syn keyword mpDef flow_connect_top_bottom flow_connect_top_left + syn keyword mpDef flow_connect_top_right flow_connect_top_top + syn keyword mpDef flow_draw_connection flow_draw_connection_point + syn keyword mpDef flow_draw_midpoint flow_draw_shape + syn keyword mpDef flow_draw_test_area flow_draw_test_shape + syn keyword mpDef flow_draw_test_shapes flow_end_chart + syn keyword mpDef flow_end_sub_chart flow_flush_connections + syn keyword mpDef flow_flush_picture flow_flush_pictures + syn keyword mpDef flow_flush_shape flow_flush_shapes + syn keyword mpDef flow_initialize_grid flow_new_chart flow_new_shape + syn keyword mpDef flow_scaled_to_grid flow_show_connection + syn keyword mpDef flow_show_connections flow_show_shapes + syn keyword mpDef flow_xy_offset flow_y_pos + syn keyword mpVardef flow_connection_path flow_down_on_grid + syn keyword mpVardef flow_down_to_grid flow_i_point flow_left_on_grid + syn keyword mpVardef flow_left_to_grid flow_offset + syn keyword mpVardef flow_points_initialized flow_right_on_grid + syn keyword mpVardef flow_right_to_grid flow_smooth_connection + syn keyword mpVardef flow_trim_points flow_trimmed flow_up_on_grid + syn keyword mpVardef flow_up_to_grid flow_valid_connection + syn keyword mpVardef flow_x_on_grid flow_xy_bottom flow_xy_left + syn keyword mpVardef flow_xy_on_grid flow_xy_right flow_xy_top + syn keyword mpVardef flow_y_on_grid + syn keyword mpVariable flow_arrowtip flow_chart_background_color + syn keyword mpVariable flow_chart_offset flow_comment_offset + syn keyword mpVariable flow_connection_arrow_size + syn keyword mpVariable flow_connection_dash_size + syn keyword mpVariable flow_connection_line_color + syn keyword mpVariable flow_connection_line_width + syn keyword mpVariable flow_connection_smooth_size flow_connections + syn keyword mpVariable flow_cpath flow_dash_pattern flow_dashline + syn keyword mpVariable flow_exit_offset flow_forcevalid flow_grid_height + syn keyword mpVariable flow_grid_width flow_label_offset flow_max_x + syn keyword mpVariable flow_max_y flow_peepshape flow_reverse_connection + syn keyword mpVariable flow_reverse_y flow_shape_action flow_shape_archive + syn keyword mpVariable flow_shape_decision flow_shape_down + syn keyword mpVariable flow_shape_fill_color flow_shape_height + syn keyword mpVariable flow_shape_left flow_shape_line_color + syn keyword mpVariable flow_shape_line_width flow_shape_loop + syn keyword mpVariable flow_shape_multidocument flow_shape_node + syn keyword mpVariable flow_shape_procedure flow_shape_product + syn keyword mpVariable flow_shape_right flow_shape_singledocument + syn keyword mpVariable flow_shape_subprocedure flow_shape_up + syn keyword mpVariable flow_shape_wait flow_shape_width + syn keyword mpVariable flow_show_all_points flow_show_con_points + syn keyword mpVariable flow_show_mid_points flow_showcrossing flow_smooth + syn keyword mpVariable flow_touchshape flow_xypoint flow_zfactor + syn keyword mpConstant context_flow + " mp-chem.mpiv + syn keyword mpDef chem_init_all chem_reset chem_start_structure + syn keyword mpDef chem_transformed + syn keyword mpVardef chem_ad chem_adj chem_align chem_arrow chem_au + syn keyword mpVardef chem_b chem_bb chem_bd chem_bw chem_c chem_cc + syn keyword mpVardef chem_ccd chem_cd chem_crz chem_cz chem_dash chem_db + syn keyword mpVardef chem_diff chem_dir chem_do chem_dr chem_draw + syn keyword mpVardef chem_drawarrow chem_eb chem_ed chem_ep chem_er + syn keyword mpVardef chem_es chem_et chem_fill chem_hb chem_init_some + syn keyword mpVardef chem_label chem_ldb chem_ldd chem_line chem_lr + syn keyword mpVardef chem_lrb chem_lrbd chem_lrd chem_lrh chem_lrn + syn keyword mpVardef chem_lrt chem_lrz chem_lsr chem_lsub chem_mark + syn keyword mpVardef chem_marked chem_mid chem_mids chem_midz chem_mir + syn keyword mpVardef chem_mov chem_move chem_number chem_oe chem_off + syn keyword mpVardef chem_pb chem_pe chem_r chem_r_fragment chem_rb + syn keyword mpVardef chem_rbd chem_rd chem_rdb chem_rdd chem_restore + syn keyword mpVardef chem_rh chem_rm chem_rn chem_rot chem_rr chem_rrb + syn keyword mpVardef chem_rrbd chem_rrd chem_rrh chem_rrn chem_rrt + syn keyword mpVardef chem_rrz chem_rsr chem_rsub chem_rt chem_rz chem_s + syn keyword mpVardef chem_save chem_sb chem_sd chem_set chem_sr chem_ss + syn keyword mpVardef chem_start_component chem_stop_component + syn keyword mpVardef chem_stop_structure chem_sub chem_symbol chem_tb + syn keyword mpVardef chem_text chem_z chem_zln chem_zlt chem_zn chem_zrn + syn keyword mpVardef chem_zrt chem_zt + syn keyword mpVariable chem_mark_pair chem_stack_mirror chem_stack_origin + syn keyword mpVariable chem_stack_p chem_stack_previous + syn keyword mpVariable chem_stack_rotation chem_trace_boundingbox + syn keyword mpVariable chem_trace_nesting chem_trace_text + syn keyword mpConstant context_chem + " mp-core.mpiv + syn keyword mpDef FlushSyncTasks ProcessSyncTask + syn keyword mpDef RegisterLocalTextArea RegisterPlainTextArea + syn keyword mpDef RegisterRegionTextArea RegisterTextArea + syn keyword mpDef ResetLocalTextArea ResetSyncTasks ResetTextAreas + syn keyword mpDef SaveTextAreas SetSyncColor SetSyncThreshold + syn keyword mpDef SyncTask anchor_box box_found boxfilloptions + syn keyword mpDef boxgridoptions boxlineoptions collapse_multi_pars + syn keyword mpDef draw_box draw_multi_pars draw_par freeze_box + syn keyword mpDef initialize_area initialize_area_par initialize_box + syn keyword mpDef initialize_box_pos initialize_par + syn keyword mpDef prepare_multi_pars relocate_multipars save_multipar + syn keyword mpDef set_par_line_height show_multi_pars show_par + syn keyword mpDef simplify_multi_pars sort_multi_pars + syn keyword mpVardef InsideSavedTextArea InsideSomeSavedTextArea + syn keyword mpVardef InsideSomeTextArea InsideTextArea PrepareSyncTasks + syn keyword mpVardef SyncBox TextAreaH TextAreaW TextAreaWH TextAreaX + syn keyword mpVardef TextAreaXY TextAreaY TheSyncColor TheSyncThreshold + syn keyword mpVardef baseline_grid graphic_grid multi_par_at_top + syn keyword mpVariable CurrentSyncClass NOfSavedTextAreas + syn keyword mpVariable NOfSavedTextColumns NOfSyncPaths NOfTextAreas + syn keyword mpVariable NOfTextColumns PlainTextArea RegionTextArea + syn keyword mpVariable SavedTextColumns SyncColor SyncLeftOffset SyncPaths + syn keyword mpVariable SyncTasks SyncThreshold SyncThresholdMethod + syn keyword mpVariable SyncWidth TextAreas TextColumns + syn keyword mpVariable auto_multi_par_hsize boxdashtype boxfilloffset + syn keyword mpVariable boxfilltype boxgriddirection boxgriddistance + syn keyword mpVariable boxgridshift boxgridtype boxgridwidth boxlineradius + syn keyword mpVariable boxlinetype boxlinewidth check_multi_par_chain + syn keyword mpVariable compensate_multi_par_topskip + syn keyword mpVariable enable_multi_par_fallback force_multi_par_chain + syn keyword mpVariable ignore_multi_par_page last_multi_par_shift lefthang + syn keyword mpVariable local_multi_par_area multi_column_first_page_hack + syn keyword mpVariable multi_par_pages multiloc multilocs multipar + syn keyword mpVariable multipars multiref multirefs nofmultipars + syn keyword mpVariable obey_multi_par_hang obey_multi_par_more + syn keyword mpVariable one_piece_multi_par par_hang_after par_hang_indent + syn keyword mpVariable par_indent par_left_skip par_line_height + syn keyword mpVariable par_right_skip par_start_pos par_stop_pos + syn keyword mpVariable par_strut_depth par_strut_height ppos righthang + syn keyword mpVariable snap_multi_par_tops somehang span_multi_column_pars + syn keyword mpVariable use_multi_par_region + syn keyword mpConstant context_core + syn keyword LET anchor_area anchor_par draw_area + " mp-cows.mpiv + syn keyword mpConstant context_cows cow + " mp-crop.mpiv + syn keyword mpDef page_marks_add_color page_marks_add_lines + syn keyword mpDef page_marks_add_marking page_marks_add_number + syn keyword mpVardef crop_color crop_gray crop_marks_cmyk + syn keyword mpVardef crop_marks_cmykrgb crop_marks_gray crop_marks_lines + syn keyword mpVariable crop_colors more page + syn keyword mpConstant context_crop + " mp-figs.mpiv + syn keyword mpDef naturalfigure registerfigure + syn keyword mpVardef figuredimensions figureheight figuresize + syn keyword mpVardef figurewidth + syn keyword mpConstant context_figs + " mp-fobg.mpiv + syn keyword mpDef DrawFoFrame + syn keyword mpVardef equalpaths + syn keyword mpPrimaryDef inset outset + syn keyword mpVariable FoBackground FoBackgroundColor FoFrame FoLineColor + syn keyword mpVariable FoLineStyle FoLineWidth FoSplit + syn keyword mpConstant FoAll FoBottom FoDash FoDotted FoDouble FoGroove + syn keyword mpConstant FoHidden FoInset FoLeft FoMedium FoNoColor FoNone + syn keyword mpConstant FoOutset FoRidge FoRight FoSolid FoThick FoThin + syn keyword mpConstant FoTop context_fobg + " mp-form.mpiv + syn keyword mpConstant context_form + " mp-func.mpiv + syn keyword mpDef constructedfunction constructedpairs + syn keyword mpDef constructedpath curvedfunction curvedpairs + syn keyword mpDef curvedpath function pathconnectors straightfunction + syn keyword mpDef straightpairs straightpath + syn keyword mpConstant context_func + " mp-grap.mpiv + syn keyword mpDef Gfor OUT auto begingraph circles crosses diamonds + syn keyword mpDef downtriangles endgraph gdata gdraw gdrawarrow + syn keyword mpDef gdrawdblarrow gfill graph_addto + syn keyword mpDef graph_addto_currentpicture graph_comma + syn keyword mpDef graph_coordinate_multiplication graph_draw + syn keyword mpDef graph_draw_label graph_errorbar_text graph_fill + syn keyword mpDef graph_generate_exponents + syn keyword mpDef graph_generate_label_position + syn keyword mpDef graph_generate_numbers graph_label_location + syn keyword mpDef graph_scan_mark graph_scan_marks graph_setbounds + syn keyword mpDef graph_suffix graph_tick_label + syn keyword mpDef graph_with_pen_and_color graph_withlist + syn keyword mpDef graph_xyscale lefttriangles makefunctionpath plot + syn keyword mpDef plotsymbol points rainbow righttriangles smoothpath + syn keyword mpDef squares stars uptriangles witherrorbars + syn keyword mpVardef addtopath augment autogrid constant_fit + syn keyword mpVardef constant_function det escaped_format exp + syn keyword mpVardef exponential_fit exponential_function format + syn keyword mpVardef formatted frame functionpath gaussian_fit + syn keyword mpVardef gaussian_function gdotlabel glabel graph_Feform + syn keyword mpVardef graph_Meform graph_arrowhead_extent graph_bounds + syn keyword mpVardef graph_clear_bounds + syn keyword mpVardef graph_convert_user_path_to_internal graph_cspan + syn keyword mpVardef graph_draw_arrowhead graph_error graph_errorbars + syn keyword mpVardef graph_exp graph_factor_and_exponent_to_string + syn keyword mpVardef graph_gridline_picture graph_is_null + syn keyword mpVardef graph_label_convert_user_to_internal graph_loptok + syn keyword mpVardef graph_match_exponents graph_mlog + syn keyword mpVardef graph_modified_exponent_ypart graph_pair_adjust + syn keyword mpVardef graph_picture_conversion graph_post_draw + syn keyword mpVardef graph_read_line graph_readpath graph_remap + syn keyword mpVardef graph_scan_path graph_select_exponent_mark + syn keyword mpVardef graph_select_mark graph_set_bounds + syn keyword mpVardef graph_set_default_bounds graph_shapesize + syn keyword mpVardef graph_stash_label graph_tick_mark_spacing + syn keyword mpVardef graph_unknown_pair_bbox grid isdigit itick + syn keyword mpVardef linear_fit linear_function ln logten lorentzian_fit + syn keyword mpVardef lorentzian_function otick polynomial_fit + syn keyword mpVardef polynomial_function power_law_fit + syn keyword mpVardef power_law_function powten setcoords setrange + syn keyword mpVardef sortpath strfmt tick varfmt + syn keyword mpNewInternal Mzero doubleinfinity graph_log_minimum + syn keyword mpNewInternal graph_minimum_number_of_marks largestmantissa + syn keyword mpNewInternal linear lntwo log mlogten singleinfinity + syn keyword mpVariable Autoform determinant fit_chi_squared + syn keyword mpVariable graph_errorbar_picture graph_exp_marks + syn keyword mpVariable graph_frame_pair_a graph_frame_pair_b + syn keyword mpVariable graph_lin_marks graph_log_marks graph_modified_bias + syn keyword mpVariable graph_modified_higher graph_modified_lower + syn keyword mpVariable graph_shape r_s resistance_color resistance_name + syn keyword mpConstant context_grap + " mp-grid.mpiv + syn keyword mpDef hlingrid hloggrid vlingrid vloggrid + syn keyword mpVardef hlinlabel hlintext hlogtext linlin linlinpath + syn keyword mpVardef linlog linlogpath loglin loglinpath loglog + syn keyword mpVardef loglogpath processpath vlinlabel vlintext vlogtext + syn keyword mpVariable fmt_initialize fmt_pictures fmt_precision + syn keyword mpVariable fmt_separator fmt_zerocheck grid_eps + syn keyword mpConstant context_grid + " mp-grph.mpiv + syn keyword mpDef beginfig begingraphictextfig data_mpo_file + syn keyword mpDef data_mpy_file doloadfigure draw endfig + syn keyword mpDef endgraphictextfig fill fixedplace graphictext + syn keyword mpDef loadfigure new_graphictext normalwithshade number + syn keyword mpDef old_graphictext outlinefill protectgraphicmacros + syn keyword mpDef resetfig reversefill withdrawcolor withfillcolor + syn keyword mpDef withshade + syn keyword mpVariable currentgraphictext figureshift + syn keyword mpConstant context_grph + " mp-idea.mpiv + syn keyword mpVardef bcomponent ccomponent gcomponent mcomponent + syn keyword mpVardef rcomponent somecolor ycomponent + " mp-luas.mpiv + syn keyword mpDef luacall message + syn keyword mpVardef MP lua lualist + syn keyword mpConstant context_luas + " mp-mlib.mpiv + syn keyword mpDef autoalign bitmapimage circular_shade cmyk comment + syn keyword mpDef defineshade eofill eofillup externalfigure figure + syn keyword mpDef fillup label linear_shade multitonecolor namedcolor + syn keyword mpDef nofill onlayer passarrayvariable passvariable + syn keyword mpDef plain_label register resolvedcolor scantokens + syn keyword mpDef set_circular_vector set_linear_vector shaded + syn keyword mpDef spotcolor startpassingvariable stoppassingvariable + syn keyword mpDef thelabel transparent[] usemetafunlabels + syn keyword mpDef useplainlabels withcircularshade withlinearshade + syn keyword mpDef withmask withproperties withshadecenter + syn keyword mpDef withshadecolors withshadedirection withshadedomain + syn keyword mpDef withshadefactor withshadefraction withshadeorigin + syn keyword mpDef withshaderadius withshadestep withshadetransform + syn keyword mpDef withshadevector withtransparency + syn keyword mpVardef anchored checkbounds checkedbounds + syn keyword mpVardef define_circular_shade define_linear_shade dotlabel + syn keyword mpVardef escaped_format fmttext fontsize format formatted + syn keyword mpVardef installlabel onetimefmttext onetimetextext + syn keyword mpVardef outlinetext plain_thelabel properties rawfmttext + syn keyword mpVardef rawtexbox rawtextext rule strfmt strut texbox + syn keyword mpVardef textext thefmttext thelabel thetexbox thetextext + syn keyword mpVardef tostring transparency_alternative_to_number + syn keyword mpVardef validtexbox varfmt verbatim + syn keyword mpPrimaryDef asgroup infont normalinfont shadedinto + syn keyword mpPrimaryDef shownshadecenter shownshadedirection + syn keyword mpPrimaryDef shownshadeorigin shownshadevector withshade + syn keyword mpPrimaryDef withshademethod + syn keyword mpNewInternal colorburntransparent colordodgetransparent + syn keyword mpNewInternal colortransparent darkentransparent + syn keyword mpNewInternal differencetransparent exclusiontransparent + syn keyword mpNewInternal hardlighttransparent huetransparent + syn keyword mpNewInternal lightentransparent luminositytransparent + syn keyword mpNewInternal multiplytransparent normaltransparent + syn keyword mpNewInternal overlaytransparent saturationtransparent + syn keyword mpNewInternal screentransparent shadefactor softlighttransparent + syn keyword mpNewInternal textextoffset + syn keyword mpType property transparency + syn keyword mpVariable currentoutlinetext shadeddown shadedleft + syn keyword mpVariable shadedright shadedup shadeoffset trace_shades + syn keyword mpConstant context_mlib + " mp-page.mpiv + syn keyword mpDef BoundCoverAreas BoundPageAreas Enlarged FakeRule + syn keyword mpDef FakeWord LoadPageState OverlayBox RuleColor + syn keyword mpDef SetAreaVariables SetPageArea SetPageBackPage + syn keyword mpDef SetPageCoverPage SetPageField SetPageFrontPage + syn keyword mpDef SetPageHsize SetPageHstep SetPageLocation + syn keyword mpDef SetPagePage SetPageSpine SetPageVariables + syn keyword mpDef SetPageVsize SetPageVstep StartCover StartPage + syn keyword mpDef StopCover StopPage SwapPageState innerenlarged + syn keyword mpDef llEnlarged lrEnlarged outerenlarged ulEnlarged + syn keyword mpDef urEnlarged + syn keyword mpVardef BackPageHeight BackPageWidth BackSpace BaseLineSkip + syn keyword mpVardef BodyFontSize BottomDistance BottomHeight + syn keyword mpVardef BottomSpace CoverHeight CoverWidth CurrentColumn + syn keyword mpVardef CurrentHeight CurrentWidth CutSpace EmWidth + syn keyword mpVardef ExHeight FooterDistance FooterHeight + syn keyword mpVardef FrontPageHeight FrontPageWidth HSize HeaderDistance + syn keyword mpVardef HeaderHeight InPageBody InnerEdgeDistance + syn keyword mpVardef InnerEdgeWidth InnerMarginDistance InnerMarginWidth + syn keyword mpVardef InnerSpaceWidth LastPageNumber LayoutColumnDistance + syn keyword mpVardef LayoutColumnWidth LayoutColumns LeftEdgeDistance + syn keyword mpVardef LeftEdgeWidth LeftMarginDistance LeftMarginWidth + syn keyword mpVardef LineHeight MakeupHeight MakeupWidth NOfColumns + syn keyword mpVardef NOfPages OnOddPage OnRightPage OuterEdgeDistance + syn keyword mpVardef OuterEdgeWidth OuterMarginDistance OuterMarginWidth + syn keyword mpVardef OuterSpaceWidth OverlayDepth OverlayHeight + syn keyword mpVardef OverlayLineWidth OverlayOffset OverlayWidth + syn keyword mpVardef PageDepth PageFraction PageNumber PageOffset + syn keyword mpVardef PaperBleed PaperHeight PaperWidth PrintPaperHeight + syn keyword mpVardef PrintPaperWidth RealPageNumber RightEdgeDistance + syn keyword mpVardef RightEdgeWidth RightMarginDistance RightMarginWidth + syn keyword mpVardef SpineHeight SpineWidth StrutDepth StrutHeight + syn keyword mpVardef TextHeight TextWidth TopDistance TopHeight TopSkip + syn keyword mpVardef TopSpace VSize defaultcolormodel + syn keyword mpVariable Area BackPage CoverPage CurrentLayout Field + syn keyword mpVariable FrontPage HorPos Hsize Hstep Location Page + syn keyword mpVariable PageStateAvailable RuleDepth RuleDirection + syn keyword mpVariable RuleFactor RuleH RuleHeight RuleOffset RuleOption + syn keyword mpVariable RuleThickness RuleV RuleWidth Spine VerPos Vsize + syn keyword mpVariable Vstep + syn keyword mpConstant context_page + " mp-shap.mpiv + syn keyword mpDef drawline drawshape some_shape + syn keyword mpDef start_predefined_shape_definition + syn keyword mpDef stop_predefined_shape_definition + syn keyword mpVardef drawpredefinedline drawpredefinedshape + syn keyword mpVardef some_shape_path + syn keyword mpVariable predefined_shapes predefined_shapes_xradius + syn keyword mpVariable predefined_shapes_xxradius + syn keyword mpVariable predefined_shapes_yradius + syn keyword mpVariable predefined_shapes_yyradius + syn keyword mpConstant context_shap + " mp-step.mpiv + syn keyword mpDef initialize_step_variables midbottomboundary + syn keyword mpDef midtopboundary step_begin_cell step_begin_chart + syn keyword mpDef step_cell_ali step_cell_bot step_cell_top + syn keyword mpDef step_cells step_end_cell step_end_chart + syn keyword mpDef step_text_bot step_text_mid step_text_top + syn keyword mpDef step_texts + syn keyword mpVariable cell_distance_x cell_distance_y cell_fill_color + syn keyword mpVariable cell_line_color cell_line_width cell_offset + syn keyword mpVariable chart_align chart_category chart_vertical + syn keyword mpVariable line_distance line_height line_line_color + syn keyword mpVariable line_line_width line_offset nofcells + syn keyword mpVariable text_distance_set text_fill_color text_line_color + syn keyword mpVariable text_line_width text_offset + syn keyword mpConstant context_cell + " mp-symb.mpiv + syn keyword mpDef finishglyph prepareglyph + syn keyword mpConstant lefttriangle midbar onebar righttriangle sidebar + syn keyword mpConstant sublefttriangle subrighttriangle twobar + " mp-text.mpiv + syn keyword mpDef build_parshape + syn keyword mpVardef found_point + syn keyword mpVariable trace_parshape + syn keyword mpConstant context_text + " mp-tool.mpiv + syn keyword mpCommand dump + syn keyword mpDef addbackground b_color beginglyph break centerarrow + syn keyword mpDef clearxy condition data_mpd_file detaileddraw + syn keyword mpDef detailpaths dowithpath draw drawboundary + syn keyword mpDef drawboundingbox drawcontrollines drawcontrolpoints + syn keyword mpDef drawfill draworigin drawpath drawpathonly + syn keyword mpDef drawpathwithpoints drawpoint drawpointlabels + syn keyword mpDef drawpoints drawticks drawwholepath drawxticks + syn keyword mpDef drawyticks endglyph fill finishsavingdata g_color + syn keyword mpDef inner_boundingbox job_name leftarrow loadmodule + syn keyword mpDef midarrowhead naturalizepaths newboolean newcolor + syn keyword mpDef newnumeric newpair newpath newpicture newstring + syn keyword mpDef newtransform normalcolors normaldraw normalfill + syn keyword mpDef normalwithcolor outer_boundingbox pop_boundingbox + syn keyword mpDef popboundingbox popcurrentpicture push_boundingbox + syn keyword mpDef pushboundingbox pushcurrentpicture r_color readfile + syn keyword mpDef recolor redraw refill register_dirty_chars + syn keyword mpDef remapcolor remapcolors remappedcolor reprocess + syn keyword mpDef resetarrows resetcolormap resetdrawoptions + syn keyword mpDef resolvedcolor restroke retext rightarrow savedata + syn keyword mpDef saveoptions scale_currentpicture set_ahlength + syn keyword mpDef set_grid showgrid startplaincompatibility + syn keyword mpDef startsavingdata stopplaincompatibility + syn keyword mpDef stopsavingdata stripe_path_a stripe_path_n undashed + syn keyword mpDef undrawfill untext visualizeddraw visualizedfill + syn keyword mpDef visualizepaths withcolor withgray + syn keyword mpDef xscale_currentpicture xshifted + syn keyword mpDef xyscale_currentpicture yscale_currentpicture + syn keyword mpDef yshifted + syn keyword mpVardef acos acosh anglebetween area arrowhead + syn keyword mpVardef arrowheadonpath arrowpath asciistring asin asinh + syn keyword mpVardef atan basiccolors bbheight bbwidth bcomponent + syn keyword mpVardef blackcolor bottomboundary boundingbox c_phantom + syn keyword mpVardef ccomponent center cleanstring colorcircle + syn keyword mpVardef colordecimals colordecimalslist colorlike colorpart + syn keyword mpVardef colortype complementary complemented copylist cos + syn keyword mpVardef cosh cot cotd curved ddddecimal dddecimal ddecimal + syn keyword mpVardef decorated drawarrowpath epsed exp freedotlabel + syn keyword mpVardef freelabel gcomponent getunstringed grayed greyed + syn keyword mpVardef hsvtorgb infinite innerboundingbox interpolated inv + syn keyword mpVardef invcos inverted invsin invtan laddered leftboundary + syn keyword mpVardef leftpath leftrightpath listsize listtocurves + syn keyword mpVardef listtolines ln log mcomponent new_on_grid + syn keyword mpVardef outerboundingbox paired pen_size penpoint phantom + syn keyword mpVardef pointarrow pow punked rangepath rcomponent + syn keyword mpVardef redecorated repathed rightboundary rightpath + syn keyword mpVardef rotation roundedsquare set_inner_boundingbox + syn keyword mpVardef set_outer_boundingbox setunstringed shapedlist + syn keyword mpVardef simplified sin sinh sortlist sqr straightpath tan + syn keyword mpVardef tand tanh tensecircle thefreelabel topboundary + syn keyword mpVardef tripled undecorated unitvector unspiked unstringed + syn keyword mpVardef whitecolor ycomponent + syn keyword mpPrimaryDef along blownup bottomenlarged cornered crossed + syn keyword mpPrimaryDef enlarged enlonged leftenlarged llenlarged llmoved + syn keyword mpPrimaryDef lrenlarged lrmoved on paralleled randomized + syn keyword mpPrimaryDef randomizedcontrols randomshifted rightenlarged + syn keyword mpPrimaryDef shortened sized smoothed snapped softened squeezed + syn keyword mpPrimaryDef stretched superellipsed topenlarged ulenlarged + syn keyword mpPrimaryDef ulmoved uncolored urenlarged urmoved xsized + syn keyword mpPrimaryDef xstretched xyscaled xysized ysized ystretched zmod + syn keyword mpSecondaryDef anglestriped intersection_point numberstriped + syn keyword mpSecondaryDef peepholed + syn keyword mpTertiaryDef cutends + syn keyword mpNewInternal ahdimple ahvariant anglelength anglemethod + syn keyword mpNewInternal angleoffset charscale cmykcolormodel graycolormodel + syn keyword mpNewInternal greycolormodel maxdimensions metapostversion + syn keyword mpNewInternal nocolormodel rgbcolormodel striped_normal_inner + syn keyword mpNewInternal striped_normal_outer striped_reverse_inner + syn keyword mpNewInternal striped_reverse_outer + syn keyword mpType grayscale greyscale quadruplet triplet + syn keyword mpVariable ahfactor collapse_data color_map drawoptionsfactor + syn keyword mpVariable freedotlabelsize freelabeloffset grid grid_full + syn keyword mpVariable grid_h grid_left grid_nx grid_ny grid_w grid_x + syn keyword mpVariable grid_y intersection_found originlength + syn keyword mpVariable plain_compatibility_data pointlabelfont + syn keyword mpVariable pointlabelscale refillbackground savingdata + syn keyword mpVariable savingdatadone swappointlabels ticklength tickstep + syn keyword mpConstant CRLF DQUOTE PERCENT SPACE bcircle context_tool crlf + syn keyword mpConstant darkblue darkcyan darkgray darkgreen darkmagenta + syn keyword mpConstant darkred darkyellow downtriangle dquote freesquare + syn keyword mpConstant fulldiamond fullsquare fulltriangle lcircle + syn keyword mpConstant lefttriangle lightgray llcircle lltriangle lrcircle + syn keyword mpConstant lrtriangle mpversion nocolor noline oddly + syn keyword mpConstant originpath percent rcircle righttriangle space + syn keyword mpConstant tcircle triangle ulcircle ultriangle unitcircle + syn keyword mpConstant unitdiamond unittriangle uptriangle urcircle + syn keyword mpConstant urtriangle +endif " MetaFun macros + " Define the default highlighting -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_mp_syntax_inits") - if version < 508 - let did_mp_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink mpTeXinsert String - HiLink mpTeXbegin Statement - HiLink mpTeXend Statement - HiLink mpInternal mfInternal - HiLink mpMacro Macro - - delcommand HiLink -endif +hi def link mpTeXdelim mpPrimitive +hi def link mpBoolExp mfBoolExp +hi def link mpNumExp mfNumExp +hi def link mpPairExp mfPairExp +hi def link mpPathExp mfPathExp +hi def link mpPenExp mfPenExp +hi def link mpPicExp mfPicExp +hi def link mpStringExp mfStringExp +hi def link mpInternal mfInternal +hi def link mpCommand mfCommand +hi def link mpType mfType +hi def link mpPrimitive mfPrimitive +hi def link mpDef mfDef +hi def link mpVardef mpDef +hi def link mpPrimaryDef mpDef +hi def link mpSecondaryDef mpDef +hi def link mpTertiaryDef mpDef +hi def link mpNewInternal mpInternal +hi def link mpVariable mfVariable +hi def link mpConstant mfConstant +hi def link mpOnOff mpPrimitive +hi def link mpDash mpPrimitive +hi def link mpTeXKeyword Identifier let b:current_syntax = "mp" -" vim: ts=8 +let &cpo = s:cpo_sav +unlet! s:cpo_sav + +" vim:sw=2 diff --git a/runtime/syntax/msidl.vim b/runtime/syntax/msidl.vim index 79585bebc6..57eaecaa4f 100644 --- a/runtime/syntax/msidl.vim +++ b/runtime/syntax/msidl.vim @@ -3,11 +3,8 @@ " Maintainer: Vadim Zeitlin <vadim@wxwindows.org> " Last Change: 2012 Feb 12 by Thilo Six -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -56,39 +53,29 @@ syn region msidlSafeArray start="SAFEARRAY(" end=")" contains=msidlStandar syn sync lines=50 " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_msidl_syntax_inits") - if version < 508 - let did_msidl_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink msidlInclude Include - HiLink msidlPreProc PreProc - HiLink msidlPreCondit PreCondit - HiLink msidlDefine Macro - HiLink msidlIncluded String - HiLink msidlString String - HiLink msidlComment Comment - HiLink msidlTodo Todo - HiLink msidlSpecial SpecialChar - HiLink msidlLiteral Number - HiLink msidlUUID Number - - HiLink msidlImport Include - HiLink msidlEnum StorageClass - HiLink msidlStruct Structure - HiLink msidlTypedef Typedef - HiLink msidlAttribute StorageClass - - HiLink msidlStandardType Type - HiLink msidlSafeArray Type - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link msidlInclude Include +hi def link msidlPreProc PreProc +hi def link msidlPreCondit PreCondit +hi def link msidlDefine Macro +hi def link msidlIncluded String +hi def link msidlString String +hi def link msidlComment Comment +hi def link msidlTodo Todo +hi def link msidlSpecial SpecialChar +hi def link msidlLiteral Number +hi def link msidlUUID Number + +hi def link msidlImport Include +hi def link msidlEnum StorageClass +hi def link msidlStruct Structure +hi def link msidlTypedef Typedef +hi def link msidlAttribute StorageClass + +hi def link msidlStandardType Type +hi def link msidlSafeArray Type + let b:current_syntax = "msidl" diff --git a/runtime/syntax/msmessages.vim b/runtime/syntax/msmessages.vim index 60588571c9..5faee978b4 100644 --- a/runtime/syntax/msmessages.vim +++ b/runtime/syntax/msmessages.vim @@ -7,11 +7,8 @@ " See format description at <http://msdn2.microsoft.com/en-us/library/aa385646.aspx> " This file is based on the rc.vim and c.vim -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif diff --git a/runtime/syntax/msql.vim b/runtime/syntax/msql.vim index 0716fbb1f6..60e75a7ef6 100644 --- a/runtime/syntax/msql.vim +++ b/runtime/syntax/msql.vim @@ -8,11 +8,8 @@ " Options msql_sql_query = 1 for SQL syntax highligthing inside strings " msql_minlines = x to sync at least x lines backwards -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -20,12 +17,8 @@ if !exists("main_syntax") let main_syntax = 'msql' endif -if version < 600 - so <sfile>:p:h/html.vim -else - runtime! syntax/html.vim - unlet b:current_syntax -endif +runtime! syntax/html.vim +unlet b:current_syntax syn cluster htmlPreproc add=msqlRegion @@ -57,39 +50,29 @@ else endif " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_msql_syn_inits") - if version < 508 - let did_msql_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink msqlComment Comment - HiLink msqlString String - HiLink msqlNumber Number - HiLink msqlFloat Float - HiLink msqlIdentifier Identifier - HiLink msqlGlobalIdentifier Identifier - HiLink msqlIntVar Identifier - HiLink msqlEnvVar Identifier - HiLink msqlFunctions Function - HiLink msqlRepeat Repeat - HiLink msqlConditional Conditional - HiLink msqlStatement Statement - HiLink msqlType Type - HiLink msqlInclude Include - HiLink msqlDefine Define - HiLink msqlSpecialChar SpecialChar - HiLink msqlParentError Error - HiLink msqlTodo Todo - HiLink msqlOperator Operator - HiLink msqlRelation Operator - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link msqlComment Comment +hi def link msqlString String +hi def link msqlNumber Number +hi def link msqlFloat Float +hi def link msqlIdentifier Identifier +hi def link msqlGlobalIdentifier Identifier +hi def link msqlIntVar Identifier +hi def link msqlEnvVar Identifier +hi def link msqlFunctions Function +hi def link msqlRepeat Repeat +hi def link msqlConditional Conditional +hi def link msqlStatement Statement +hi def link msqlType Type +hi def link msqlInclude Include +hi def link msqlDefine Define +hi def link msqlSpecialChar SpecialChar +hi def link msqlParentError Error +hi def link msqlTodo Todo +hi def link msqlOperator Operator +hi def link msqlRelation Operator + let b:current_syntax = "msql" diff --git a/runtime/syntax/mupad.vim b/runtime/syntax/mupad.vim index 109f880ee1..55ea9c4e43 100644 --- a/runtime/syntax/mupad.vim +++ b/runtime/syntax/mupad.vim @@ -5,11 +5,8 @@ " Date: 6/30/2004 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -268,28 +265,19 @@ syn keyword mupadIdentifier Tubular " graphics meta-documentation Attributes syn keyword mupadIdentifier objectGroupsListed -if version >= 508 || !exists("did_mupad_syntax_inits") - if version < 508 - let did_mupad_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - HiLink mupadComment Comment - HiLink mupadString String - HiLink mupadOperator Operator - HiLink mupadSpecial Special - HiLink mupadStatement Statement - HiLink mupadUnderlined Underlined - HiLink mupadConditional Conditional - HiLink mupadRepeat Repeat - HiLink mupadFunction Function - HiLink mupadType Type - HiLink mupadDefine Define - HiLink mupadIdentifier Identifier +hi def link mupadComment Comment +hi def link mupadString String +hi def link mupadOperator Operator +hi def link mupadSpecial Special +hi def link mupadStatement Statement +hi def link mupadUnderlined Underlined +hi def link mupadConditional Conditional +hi def link mupadRepeat Repeat +hi def link mupadFunction Function +hi def link mupadType Type +hi def link mupadDefine Define +hi def link mupadIdentifier Identifier - delcommand HiLink -endif " TODO More comprehensive listing. diff --git a/runtime/syntax/mush.vim b/runtime/syntax/mush.vim index 0645f33565..efaae50ae3 100644 --- a/runtime/syntax/mush.vim +++ b/runtime/syntax/mush.vim @@ -3,11 +3,8 @@ " Based on vim Syntax file by: Bek Oberin <gossamer@tertius.net.au> " Last Updated: Fri Nov 04 20:28:15 2005 " -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -185,42 +182,33 @@ syntax keyword mushAttribute use va vb vc vd ve vf vg vh vi vj vk vl vm vn syntax keyword mushAttribute vo vp vq vr vs vt vu vv vw vx vy vz -if version >= 508 || !exists("did_mush_syntax_inits") - if version < 508 - let did_mush_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - " The default methods for highlighting. Can be overridden later - HiLink mushAttribute Constant - HiLink mushCommand Function - HiLink mushNumber Number - HiLink mushSetting PreProc - HiLink mushFunction Statement - HiLink mushVariable Identifier - HiLink mushSpecial Special - HiLink mushTodo Todo - HiLink mushFlag Special - HiLink mushIdentifier Identifier - HiLink mushDefine Macro - HiLink mushPreProc PreProc - HiLink mushPreProcGroup PreProc - HiLink mushPreCondit PreCondit - HiLink mushIncluded cString - HiLink mushInclude Include + +" The default methods for highlighting. Can be overridden later +hi def link mushAttribute Constant +hi def link mushCommand Function +hi def link mushNumber Number +hi def link mushSetting PreProc +hi def link mushFunction Statement +hi def link mushVariable Identifier +hi def link mushSpecial Special +hi def link mushTodo Todo +hi def link mushFlag Special +hi def link mushIdentifier Identifier +hi def link mushDefine Macro +hi def link mushPreProc PreProc +hi def link mushPreProcGroup PreProc +hi def link mushPreCondit PreCondit +hi def link mushIncluded cString +hi def link mushInclude Include " Comments - HiLink mushCommentStart mushComment - HiLink mushComment Comment - HiLink mushCommentString mushString +hi def link mushCommentStart mushComment +hi def link mushComment Comment +hi def link mushCommentString mushString - delcommand HiLink -endif let b:current_syntax = "mush" diff --git a/runtime/syntax/muttrc.vim b/runtime/syntax/muttrc.vim index abe9bfd76b..e4395fdf59 100644 --- a/runtime/syntax/muttrc.vim +++ b/runtime/syntax/muttrc.vim @@ -2,16 +2,12 @@ " Language: Mutt setup files " Original: Preben 'Peppe' Guldberg <peppe-vim@wielders.org> " Maintainer: Kyle Wheeler <kyle-muttrc.vim@memoryhole.net> -" Last Change: 2 Feb 2012 +" Last Change: 18 August 2016 -" This file covers mutt version 1.5.21 (and most of the mercurial tip) -" Included are also a few features from 1.4.2.1 +" This file covers mutt version 1.7.0 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -19,11 +15,7 @@ let s:cpo_save = &cpo set cpo&vim " Set the keyword characters -if version < 600 - set isk=@,48-57,_,- -else - setlocal isk=@,48-57,_,- -endif +setlocal isk=@,48-57,_,- " handling optional variables if !exists("use_mutt_sidebar") @@ -98,7 +90,7 @@ syn match muttrcSetNumAssignment contained skipwhite /=\s*'\d\+'/hs=s+1 nextgrou " Now catch some email addresses and headers (purified version from mail.vim) syn match muttrcEmail "[a-zA-Z0-9._-]\+@[a-zA-Z0-9./-]\+" -syn match muttrcHeader "\<\%(From\|To\|C[Cc]\|B[Cc][Cc]\|Reply-To\|Subject\|Return-Path\|Received\|Date\|Replied\|Attach\)\>:\=" +syn match muttrcHeader "\<\c\%(From\|To\|C[Cc]\|B[Cc][Cc]\|Reply-To\|Subject\|Return-Path\|Received\|Date\|Replied\|Attach\)\>:\=" syn match muttrcKeySpecial contained +\%(\\[Cc'"]\|\^\|\\[01]\d\{2}\)+ syn match muttrcKey contained "\S\+" contains=muttrcKeySpecial,muttrcKeyName @@ -109,143 +101,146 @@ syn match muttrcKeyName contained "\\[trne]" syn match muttrcKeyName contained "\c<\%(BackSpace\|BackTab\|Delete\|Down\|End\|Enter\|Esc\|Home\|Insert\|Left\|PageDown\|PageUp\|Return\|Right\|Space\|Tab\|Up\)>" syn match muttrcKeyName contained "<F[0-9]\+>" -syn keyword muttrcVarBool skipwhite contained allow_8bit allow_ansi arrow_cursor ascii_chars askbcc askcc attach_split auto_tag autoedit beep beep_new nextgroup=muttrcSetBoolAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained bounce_delivered braille_friendly check_new check_mbox_size nextgroup=muttrcSetBoolAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained collapse_unread confirmappend confirmcreate crypt_autoencrypt nextgroup=muttrcSetBoolAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained crypt_autopgp crypt_autosign crypt_autosmime crypt_replyencrypt nextgroup=muttrcSetBoolAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained crypt_replysign crypt_replysignencrypted crypt_timestamp nextgroup=muttrcSetBoolAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained crypt_use_gpgme crypt_use_pka delete_untag digest_collapse duplicate_threads nextgroup=muttrcSetBoolAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained edit_hdrs edit_headers encode_from envelope_from fast_reply nextgroup=muttrcSetBoolAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained fcc_clear followup_to force_name forw_decode nextgroup=muttrcSetBoolAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained forw_decrypt forw_quote forward_decode forward_decrypt nextgroup=muttrcSetBoolAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained forward_quote hdrs header help hidden_host hide_limited nextgroup=muttrcSetBoolAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained hide_missing hide_thread_subject hide_top_limited nextgroup=muttrcSetBoolAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained hide_top_missing honor_disposition ignore_linear_white_space ignore_list_reply_to imap_check_subscribed nextgroup=muttrcSetBoolAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained imap_list_subscribed imap_passive imap_peek imap_servernoise nextgroup=muttrcSetBoolAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained implicit_autoview include_onlyfirst keep_flagged nextgroup=muttrcSetBoolAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained mailcap_sanitize maildir_header_cache_verify maildir_trash nextgroup=muttrcSetBoolAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained mark_old markers menu_move_off menu_scroll message_cache_clean meta_key nextgroup=muttrcSetBoolAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained metoo mh_purge mime_forward_decode narrow_tree pager_stop nextgroup=muttrcSetBoolAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained pgp_auto_decode pgp_auto_traditional pgp_autoencrypt nextgroup=muttrcSetBoolAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained pgp_autoinline pgp_autosign pgp_check_exit nextgroup=muttrcSetBoolAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained pgp_create_traditional pgp_ignore_subkeys pgp_long_ids nextgroup=muttrcSetBoolAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained pgp_replyencrypt pgp_replyinline pgp_replysign nextgroup=muttrcSetBoolAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained pgp_replysignencrypted pgp_retainable_sigs pgp_show_unusable nextgroup=muttrcSetBoolAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained pgp_strict_enc pgp_use_gpg_agent pipe_decode pipe_split nextgroup=muttrcSetBoolAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained pop_auth_try_all pop_last print_decode print_split nextgroup=muttrcSetBoolAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained prompt_after read_only reply_self resolve reverse_alias nextgroup=muttrcSetBoolAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained reverse_name reverse_realname rfc2047_parameters save_address nextgroup=muttrcSetBoolAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained save_empty save_name score sig_dashes sig_on_top nextgroup=muttrcSetBoolAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained smart_wrap smime_ask_cert_label smime_decrypt_use_default_key nextgroup=muttrcSetBoolAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained smime_is_default sort_re ssl_force_tls ssl_use_sslv2 nextgroup=muttrcSetBoolAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained ssl_use_sslv3 ssl_use_tlsv1 ssl_usesystemcerts ssl_verify_dates ssl_verify_host status_on_top nextgroup=muttrcSetBoolAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained strict_mime strict_threads suspend text_flowed thorough_search nextgroup=muttrcSetBoolAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained thread_received tilde uncollapse_jump use_8bitmime nextgroup=muttrcSetBoolAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained use_domain use_envelope_from use_from use_idn use_ipv6 nextgroup=muttrcSetBoolAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained user_agent wait_key weed wrap_search write_bcc nextgroup=muttrcSetBoolAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr - -syn keyword muttrcVarBool skipwhite contained noallow_8bit noallow_ansi noarrow_cursor noascii_chars noaskbcc nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained noaskcc noattach_split noauto_tag noautoedit nobeep nobeep_new nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained nobounce_delivered nobraille_friendly nocheck_new nocollapse_unread nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained noconfirmappend noconfirmcreate nocrypt_autoencrypt nocrypt_autopgp nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained nocrypt_autosign nocrypt_autosmime nocrypt_replyencrypt nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained nocrypt_replysign nocrypt_replysignencrypted nocrypt_timestamp nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained nocrypt_use_gpgme nodelete_untag nodigest_collapse noduplicate_threads nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained noedit_hdrs noedit_headers noencode_from noenvelope_from nofast_reply nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained nofcc_clear nofollowup_to noforce_name noforw_decode nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained noforw_decrypt noforw_quote noforward_decode noforward_decrypt nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained noforward_quote nohdrs noheader nohelp nohidden_host nohide_limited nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained nohide_missing nohide_thread_subject nohide_top_limited nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained nohide_top_missing nohonor_disposition noignore_list_reply_to noimap_check_subscribed nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained noimap_list_subscribed noimap_passive noimap_peek noimap_servernoise nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained noimplicit_autoview noinclude_onlyfirst nokeep_flagged nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained nomailcap_sanitize nomaildir_header_cache_verify nomaildir_trash nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained nomark_old nomarkers nomenu_move_off nomenu_scroll nometa_key nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained nometoo nomh_purge nomime_forward_decode nonarrow_tree nopager_stop nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained nopgp_auto_decode nopgp_auto_traditional nopgp_autoencrypt nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained nopgp_autoinline nopgp_autosign nopgp_check_exit nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained nopgp_create_traditional nopgp_ignore_subkeys nopgp_long_ids nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained nopgp_replyencrypt nopgp_replyinline nopgp_replysign nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained nopgp_replysignencrypted nopgp_retainable_sigs nopgp_show_unusable nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained nopgp_strict_enc nopgp_use_gpg_agent nopipe_decode nopipe_split nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained nopop_auth_try_all nopop_last noprint_decode noprint_split nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained noprompt_after noread_only noreply_self noresolve noreverse_alias nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained noreverse_name noreverse_realname norfc2047_parameters nosave_address nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained nosave_empty nosave_name noscore nosig_dashes nosig_on_top nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained nosmart_wrap nosmime_ask_cert_label nosmime_decrypt_use_default_key nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained nosmime_is_default nosort_re nossl_force_tls nossl_use_sslv2 nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained nossl_use_sslv3 nossl_use_tlsv1 nossl_usesystemcerts nostatus_on_top nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained nostrict_threads nosuspend notext_flowed nothorough_search nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained nothread_received notilde nouncollapse_jump nouse_8bitmime nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained nouse_domain nouse_envelope_from nouse_from nouse_idn nouse_ipv6 nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained nouser_agent nowait_key noweed nowrap_search nowrite_bcc nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr - -syn keyword muttrcVarBool skipwhite contained invallow_8bit invallow_ansi invarrow_cursor invascii_chars invaskbcc nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained invaskcc invattach_split invauto_tag invautoedit invbeep invbeep_new nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained invbounce_delivered invbraille_friendly invcheck_new invcollapse_unread nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained invconfirmappend invconfirmcreate invcrypt_autoencrypt invcrypt_autopgp nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained invcrypt_autosign invcrypt_autosmime invcrypt_replyencrypt nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained invcrypt_replysign invcrypt_replysignencrypted invcrypt_timestamp nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained invcrypt_use_gpgme invdelete_untag invdigest_collapse invduplicate_threads nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained invedit_hdrs invedit_headers invencode_from invenvelope_from invfast_reply nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained invfcc_clear invfollowup_to invforce_name invforw_decode nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained invforw_decrypt invforw_quote invforward_decode invforward_decrypt nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained invforward_quote invhdrs invheader invhelp invhidden_host invhide_limited nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained invhide_missing invhide_thread_subject invhide_top_limited nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained invhide_top_missing invhonor_disposition invignore_list_reply_to invimap_check_subscribed nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained invimap_list_subscribed invimap_passive invimap_peek invimap_servernoise nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained invimplicit_autoview invinclude_onlyfirst invkeep_flagged nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained invmailcap_sanitize invmaildir_header_cache_verify invmaildir_trash nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained invmark_old invmarkers invmenu_move_off invmenu_scroll invmeta_key nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained invmetoo invmh_purge invmime_forward_decode invnarrow_tree invpager_stop nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained invpgp_auto_decode invpgp_auto_traditional invpgp_autoencrypt nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained invpgp_autoinline invpgp_autosign invpgp_check_exit nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained invpgp_create_traditional invpgp_ignore_subkeys invpgp_long_ids nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained invpgp_replyencrypt invpgp_replyinline invpgp_replysign nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained invpgp_replysignencrypted invpgp_retainable_sigs invpgp_show_unusable nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained invpgp_strict_enc invpgp_use_gpg_agent invpipe_decode invpipe_split nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained invpop_auth_try_all invpop_last invprint_decode invprint_split nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained invprompt_after invread_only invreply_self invresolve invreverse_alias nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained invreverse_name invreverse_realname invrfc2047_parameters invsave_address nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained invsave_empty invsave_name invscore invsig_dashes invsig_on_top nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained invsmart_wrap invsmime_ask_cert_label invsmime_decrypt_use_default_key nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained invsmime_is_default invsort_re invssl_force_tls invssl_use_sslv2 nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained invssl_use_sslv3 invssl_use_tlsv1 invssl_usesystemcerts invstatus_on_top nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained invstrict_threads invsuspend invtext_flowed invthorough_search nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained invthread_received invtilde invuncollapse_jump invuse_8bitmime nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained invuse_domain invuse_envelope_from invuse_from invuse_idn invuse_ipv6 nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarBool skipwhite contained invuser_agent invwait_key invweed invwrap_search invwrite_bcc nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -if use_mutt_sidebar == 1 - syn keyword muttrcVarBool skipwhite contained sidebar_visible sidebar_sort nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -endif - -syn keyword muttrcVarQuad skipwhite contained abort_nosubject abort_unmodified bounce copy nextgroup=muttrcSetQuadAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarQuad skipwhite contained crypt_verify_sig delete fcc_attach forward_edit honor_followup_to nextgroup=muttrcSetQuadAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarQuad skipwhite contained include mime_forward mime_forward_rest mime_fwd move nextgroup=muttrcSetQuadAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarQuad skipwhite contained pgp_mime_auto pgp_verify_sig pop_delete pop_reconnect nextgroup=muttrcSetQuadAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarQuad skipwhite contained postpone print quit recall reply_to ssl_starttls nextgroup=muttrcSetQuadAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr - -syn keyword muttrcVarQuad skipwhite contained noabort_nosubject noabort_unmodified nobounce nocopy nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarQuad skipwhite contained nocrypt_verify_sig nodelete nofcc_attach noforward_edit nohonor_followup_to nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarQuad skipwhite contained noinclude nomime_forward nomime_forward_rest nomime_fwd nomove nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarQuad skipwhite contained nopgp_mime_auto nopgp_verify_sig nopop_delete nopop_reconnect nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarQuad skipwhite contained nopostpone noprint noquit norecall noreply_to nossl_starttls nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr - -syn keyword muttrcVarQuad skipwhite contained invabort_nosubject invabort_unmodified invbounce invcopy nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarQuad skipwhite contained invcrypt_verify_sig invdelete invfcc_attach invforward_edit invhonor_followup_to nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarQuad skipwhite contained invinclude invmime_forward invmime_forward_rest invmime_fwd invmove nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarQuad skipwhite contained invpgp_mime_auto invpgp_verify_sig invpop_delete invpop_reconnect nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarQuad skipwhite contained invpostpone invprint invquit invrecall invreply_to invssl_starttls nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr - -syn keyword muttrcVarNum skipwhite contained connect_timeout history imap_keepalive imap_pipeline_depth mail_check nextgroup=muttrcSetNumAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarNum skipwhite contained menu_context net_inc pager_context pager_index_lines pgp_timeout nextgroup=muttrcSetNumAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarNum skipwhite contained pop_checkinterval read_inc save_history score_threshold_delete nextgroup=muttrcSetNumAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarNum skipwhite contained score_threshold_flag score_threshold_read search_context sendmail_wait sleep_time nextgroup=muttrcSetNumAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarNum skipwhite contained smime_timeout ssl_min_dh_prime_bits timeout time_inc wrap wrapmargin nextgroup=muttrcSetNumAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarNum skipwhite contained write_inc nextgroup=muttrcSetNumAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -if use_mutt_sidebar == 1 - syn keyword muttrcVarNum skipwhite contained sidebar_width nextgroup=muttrcSetNumAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -endif +syn keyword muttrcVarBool skipwhite contained + \ allow_8bit allow_ansi arrow_cursor ascii_chars askbcc askcc attach_split + \ auto_tag autoedit beep beep_new bounce_delivered braille_friendly + \ check_mbox_size check_new collapse_unread confirmappend confirmcreate + \ crypt_autoencrypt crypt_autopgp crypt_autosign crypt_autosmime + \ crypt_confirmhook crypt_opportunistic_encrypt crypt_replyencrypt + \ crypt_replysign crypt_replysignencrypted crypt_timestamp crypt_use_gpgme + \ crypt_use_pka delete_untag digest_collapse duplicate_threads edit_hdrs + \ edit_headers encode_from envelope_from fast_reply fcc_clear followup_to + \ force_name forw_decode forw_decrypt forw_quote forward_decode forward_decrypt + \ forward_quote hdrs header help hidden_host hide_limited hide_missing + \ hide_thread_subject hide_top_limited hide_top_missing honor_disposition + \ idn_decode idn_encode ignore_linear_white_space ignore_list_reply_to + \ imap_check_subscribed imap_list_subscribed imap_passive imap_peek + \ imap_servernoise implicit_autoview include_onlyfirst keep_flagged + \ mail_check_recent mail_check_stats mailcap_sanitize maildir_check_cur + \ maildir_header_cache_verify maildir_trash mark_old markers menu_move_off + \ menu_scroll message_cache_clean meta_key metoo mh_purge mime_forward_decode + \ narrow_tree pager_stop pgp_auto_decode pgp_auto_traditional pgp_autoencrypt + \ pgp_autoinline pgp_autosign pgp_check_exit pgp_create_traditional + \ pgp_ignore_subkeys pgp_long_ids pgp_replyencrypt pgp_replyinline pgp_replysign + \ pgp_replysignencrypted pgp_retainable_sigs pgp_show_unusable pgp_strict_enc + \ pgp_use_gpg_agent pipe_decode pipe_split pop_auth_try_all pop_last + \ postpone_encrypt postpone_encrypt_as print_decode print_split prompt_after + \ read_only reflow_space_quotes reflow_text reflow_wrap reply_self resolve + \ resume_draft_files resume_edited_draft_files reverse_alias reverse_name + \ reverse_realname rfc2047_parameters save_address save_empty save_name score + \ sidebar_folder_indent sidebar_new_mail_only sidebar_next_new_wrap + \ sidebar_short_path sidebar_sort sidebar_visible sig_dashes sig_on_top + \ smart_wrap smime_ask_cert_label smime_decrypt_use_default_key smime_is_default + \ sort_re ssl_force_tls ssl_use_sslv2 ssl_use_sslv3 ssl_use_tlsv1 + \ ssl_usesystemcerts ssl_verify_dates ssl_verify_host status_on_top strict_mime + \ strict_threads suspend text_flowed thorough_search thread_received tilde + \ ts_enabled uncollapse_jump use_8bitmime use_domain use_envelope_from use_from + \ use_idn use_ipv6 user_agent wait_key weed wrap_search write_bcc + \ nextgroup=muttrcSetBoolAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr + +syn keyword muttrcVarBool skipwhite contained + \ noallow_8bit noallow_ansi noarrow_cursor noascii_chars noaskbcc noaskcc noattach_split + \ noauto_tag noautoedit nobeep nobeep_new nobounce_delivered nobraille_friendly + \ nocheck_mbox_size nocheck_new nocollapse_unread noconfirmappend noconfirmcreate + \ nocrypt_autoencrypt nocrypt_autopgp nocrypt_autosign nocrypt_autosmime + \ nocrypt_confirmhook nocrypt_opportunistic_encrypt nocrypt_replyencrypt + \ nocrypt_replysign nocrypt_replysignencrypted nocrypt_timestamp nocrypt_use_gpgme + \ nocrypt_use_pka nodelete_untag nodigest_collapse noduplicate_threads noedit_hdrs + \ noedit_headers noencode_from noenvelope_from nofast_reply nofcc_clear nofollowup_to + \ noforce_name noforw_decode noforw_decrypt noforw_quote noforward_decode noforward_decrypt + \ noforward_quote nohdrs noheader nohelp nohidden_host nohide_limited nohide_missing + \ nohide_thread_subject nohide_top_limited nohide_top_missing nohonor_disposition + \ noidn_decode noidn_encode noignore_linear_white_space noignore_list_reply_to + \ noimap_check_subscribed noimap_list_subscribed noimap_passive noimap_peek + \ noimap_servernoise noimplicit_autoview noinclude_onlyfirst nokeep_flagged + \ nomail_check_recent nomail_check_stats nomailcap_sanitize nomaildir_check_cur + \ nomaildir_header_cache_verify nomaildir_trash nomark_old nomarkers nomenu_move_off + \ nomenu_scroll nomessage_cache_clean nometa_key nometoo nomh_purge nomime_forward_decode + \ nonarrow_tree nopager_stop nopgp_auto_decode nopgp_auto_traditional nopgp_autoencrypt + \ nopgp_autoinline nopgp_autosign nopgp_check_exit nopgp_create_traditional + \ nopgp_ignore_subkeys nopgp_long_ids nopgp_replyencrypt nopgp_replyinline nopgp_replysign + \ nopgp_replysignencrypted nopgp_retainable_sigs nopgp_show_unusable nopgp_strict_enc + \ nopgp_use_gpg_agent nopipe_decode nopipe_split nopop_auth_try_all nopop_last + \ nopostpone_encrypt nopostpone_encrypt_as noprint_decode noprint_split noprompt_after + \ noread_only noreflow_space_quotes noreflow_text noreflow_wrap noreply_self noresolve + \ noresume_draft_files noresume_edited_draft_files noreverse_alias noreverse_name + \ noreverse_realname norfc2047_parameters nosave_address nosave_empty nosave_name noscore + \ nosidebar_folder_indent nosidebar_new_mail_only nosidebar_next_new_wrap + \ nosidebar_short_path nosidebar_sort nosidebar_visible nosig_dashes nosig_on_top + \ nosmart_wrap nosmime_ask_cert_label nosmime_decrypt_use_default_key nosmime_is_default + \ nosort_re nossl_force_tls nossl_use_sslv2 nossl_use_sslv3 nossl_use_tlsv1 + \ nossl_usesystemcerts nossl_verify_dates nossl_verify_host nostatus_on_top nostrict_mime + \ nostrict_threads nosuspend notext_flowed nothorough_search nothread_received notilde + \ nots_enabled nouncollapse_jump nouse_8bitmime nouse_domain nouse_envelope_from nouse_from + \ nouse_idn nouse_ipv6 nouser_agent nowait_key noweed nowrap_search nowrite_bcc + \ nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr + +syn keyword muttrcVarBool skipwhite contained + \ invallow_8bit invallow_ansi invarrow_cursor invascii_chars invaskbcc invaskcc invattach_split + \ invauto_tag invautoedit invbeep invbeep_new invbounce_delivered invbraille_friendly + \ invcheck_mbox_size invcheck_new invcollapse_unread invconfirmappend invconfirmcreate + \ invcrypt_autoencrypt invcrypt_autopgp invcrypt_autosign invcrypt_autosmime + \ invcrypt_confirmhook invcrypt_opportunistic_encrypt invcrypt_replyencrypt + \ invcrypt_replysign invcrypt_replysignencrypted invcrypt_timestamp invcrypt_use_gpgme + \ invcrypt_use_pka invdelete_untag invdigest_collapse invduplicate_threads invedit_hdrs + \ invedit_headers invencode_from invenvelope_from invfast_reply invfcc_clear invfollowup_to + \ invforce_name invforw_decode invforw_decrypt invforw_quote invforward_decode invforward_decrypt + \ invforward_quote invhdrs invheader invhelp invhidden_host invhide_limited invhide_missing + \ invhide_thread_subject invhide_top_limited invhide_top_missing invhonor_disposition + \ invidn_decode invidn_encode invignore_linear_white_space invignore_list_reply_to + \ invimap_check_subscribed invimap_list_subscribed invimap_passive invimap_peek + \ invimap_servernoise invimplicit_autoview invinclude_onlyfirst invkeep_flagged + \ invmail_check_recent invmail_check_stats invmailcap_sanitize invmaildir_check_cur + \ invmaildir_header_cache_verify invmaildir_trash invmark_old invmarkers invmenu_move_off + \ invmenu_scroll invmessage_cache_clean invmeta_key invmetoo invmh_purge invmime_forward_decode + \ invnarrow_tree invpager_stop invpgp_auto_decode invpgp_auto_traditional invpgp_autoencrypt + \ invpgp_autoinline invpgp_autosign invpgp_check_exit invpgp_create_traditional + \ invpgp_ignore_subkeys invpgp_long_ids invpgp_replyencrypt invpgp_replyinline invpgp_replysign + \ invpgp_replysignencrypted invpgp_retainable_sigs invpgp_show_unusable invpgp_strict_enc + \ invpgp_use_gpg_agent invpipe_decode invpipe_split invpop_auth_try_all invpop_last + \ invpostpone_encrypt invpostpone_encrypt_as invprint_decode invprint_split invprompt_after + \ invread_only invreflow_space_quotes invreflow_text invreflow_wrap invreply_self invresolve + \ invresume_draft_files invresume_edited_draft_files invreverse_alias invreverse_name + \ invreverse_realname invrfc2047_parameters invsave_address invsave_empty invsave_name invscore + \ invsidebar_folder_indent invsidebar_new_mail_only invsidebar_next_new_wrap + \ invsidebar_short_path invsidebar_sort invsidebar_visible invsig_dashes invsig_on_top + \ invsmart_wrap invsmime_ask_cert_label invsmime_decrypt_use_default_key invsmime_is_default + \ invsort_re invssl_force_tls invssl_use_sslv2 invssl_use_sslv3 invssl_use_tlsv1 + \ invssl_usesystemcerts invssl_verify_dates invssl_verify_host invstatus_on_top invstrict_mime + \ invstrict_threads invsuspend invtext_flowed invthorough_search invthread_received invtilde + \ invts_enabled invuncollapse_jump invuse_8bitmime invuse_domain invuse_envelope_from invuse_from + \ invuse_idn invuse_ipv6 invuser_agent invwait_key invweed invwrap_search invwrite_bcc + \ nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr + +syn keyword muttrcVarQuad skipwhite contained + \ abort_nosubject abort_unmodified bounce copy crypt_verify_sig delete + \ fcc_attach forward_edit honor_followup_to include mime_forward + \ mime_forward_rest mime_fwd move pgp_mime_auto pgp_verify_sig pop_delete + \ pop_reconnect postpone print quit recall reply_to ssl_starttls + \ nextgroup=muttrcSetQuadAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr + +syn keyword muttrcVarQuad skipwhite contained + \ noabort_nosubject noabort_unmodified nobounce nocopy nocrypt_verify_sig nodelete + \ nofcc_attach noforward_edit nohonor_followup_to noinclude nomime_forward + \ nomime_forward_rest nomime_fwd nomove nopgp_mime_auto nopgp_verify_sig nopop_delete + \ nopop_reconnect nopostpone noprint noquit norecall noreply_to nossl_starttls + \ nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr + +syn keyword muttrcVarQuad skipwhite contained + \ invabort_nosubject invabort_unmodified invbounce invcopy invcrypt_verify_sig invdelete + \ invfcc_attach invforward_edit invhonor_followup_to invinclude invmime_forward + \ invmime_forward_rest invmime_fwd invmove invpgp_mime_auto invpgp_verify_sig invpop_delete + \ invpop_reconnect invpostpone invprint invquit invrecall invreply_to invssl_starttls + \ nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr + +syn keyword muttrcVarNum skipwhite contained + \ connect_timeout history imap_keepalive imap_pipeline_depth mail_check + \ mail_check_stats_interval menu_context net_inc pager_context pager_index_lines + \ pgp_timeout pop_checkinterval read_inc save_history score_threshold_delete + \ score_threshold_flag score_threshold_read search_context sendmail_wait + \ sidebar_width sleep_time smime_timeout ssl_min_dh_prime_bits time_inc timeout + \ wrap wrap_headers wrapmargin write_inc + \ nextgroup=muttrcSetNumAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr syn match muttrcFormatErrors contained /%./ @@ -349,7 +344,7 @@ syn keyword muttrcVarStr contained skipwhite query_format nextgroup=muttrcVarEqu syn match muttrcVarEqualsQueryFmt contained skipwhite "=" nextgroup=muttrcQueryFormatStr syn keyword muttrcVarStr contained skipwhite pgp_decode_command pgp_verify_command pgp_decrypt_command pgp_clearsign_command pgp_sign_command pgp_encrypt_sign_command pgp_encrypt_only_command pgp_import_command pgp_export_command pgp_verify_key_command pgp_list_secring_command pgp_list_pubring_command nextgroup=muttrcVarEqualsPGPCmdFmt syn match muttrcVarEqualsPGPCmdFmt contained skipwhite "=" nextgroup=muttrcPGPCmdFormatStr -syn keyword muttrcVarStr contained skipwhite status_format nextgroup=muttrcVarEqualsStatusFmt +syn keyword muttrcVarStr contained skipwhite ts_icon_format ts_status_format status_format nextgroup=muttrcVarEqualsStatusFmt syn match muttrcVarEqualsStatusFmt contained skipwhite "=" nextgroup=muttrcStatusFormatStr syn keyword muttrcVarStr contained skipwhite pgp_getkeys_command nextgroup=muttrcVarEqualsPGPGetKeysFmt syn match muttrcVarEqualsPGPGetKeysFmt contained skipwhite "=" nextgroup=muttrcPGPGetKeysFormatStr @@ -361,34 +356,29 @@ syn match muttrcVarEqualsStrftimeFmt contained skipwhite "=" nextgroup=muttrcStr syn match muttrcVPrefix contained /[?&]/ nextgroup=muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr syn match muttrcVarStr contained skipwhite 'my_[a-zA-Z0-9_]\+' nextgroup=muttrcSetStrAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarStr contained skipwhite alias_file assumed_charset attach_charset attach_sep nextgroup=muttrcSetStrAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarStr contained skipwhite certificate_file charset config_charset content_type nextgroup=muttrcSetStrAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarStr contained skipwhite default_hook display_filter dotlock_program dsn_notify nextgroup=muttrcSetStrAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarStr contained skipwhite dsn_return editor entropy_file envelope_from_address escape folder nextgroup=muttrcSetStrAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarStr contained skipwhite forw_format forward_format from gecos_mask hdr_format nextgroup=muttrcSetStrAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarStr contained skipwhite header_cache header_cache_compress header_cache_pagesize nextgroup=muttrcSetStrAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarStr contained skipwhite history_file hostname imap_authenticators nextgroup=muttrcSetStrAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarStr contained skipwhite imap_delim_chars imap_headers imap_idle imap_login imap_pass nextgroup=muttrcSetStrAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarStr contained skipwhite imap_user indent_str indent_string ispell locale mailcap_path nextgroup=muttrcSetStrAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarStr contained skipwhite mask mbox mbox_type message_cachedir mh_seq_flagged mh_seq_replied nextgroup=muttrcSetStrAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarStr contained skipwhite mh_seq_unseen mixmaster msg_format pager nextgroup=muttrcSetStrAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarStr contained skipwhite pgp_good_sign nextgroup=muttrcSetStrAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarStr contained skipwhite pgp_mime_signature_filename nextgroup=muttrcSetStrAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarStr contained skipwhite pgp_mime_signature_description pgp_sign_as nextgroup=muttrcSetStrAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarStr contained skipwhite pgp_sort_keys nextgroup=muttrcSetStrAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarStr contained skipwhite pipe_sep pop_authenticators pop_host pop_pass pop_user post_indent_str nextgroup=muttrcSetStrAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarStr contained skipwhite post_indent_string postponed preconnect print_cmd print_command nextgroup=muttrcSetStrAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarStr contained skipwhite query_command quote_regexp realname record reply_regexp send_charset nextgroup=muttrcSetStrAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarStr contained skipwhite sendmail shell signature simple_search smileys smime_ca_location nextgroup=muttrcSetStrAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarStr contained skipwhite smime_certificates smime_default_key nextgroup=muttrcSetStrAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarStr contained skipwhite smime_encrypt_with nextgroup=muttrcSetStrAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarStr contained skipwhite smime_keys smime_sign_as nextgroup=muttrcSetStrAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarStr contained skipwhite smtp_url smtp_authenticators smtp_pass sort sort_alias sort_aux nextgroup=muttrcSetStrAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarStr contained skipwhite sort_browser spam_separator spoolfile ssl_ca_certificates_file ssl_client_cert nextgroup=muttrcSetStrAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syn keyword muttrcVarStr contained skipwhite status_chars tmpdir to_chars tunnel visual nextgroup=muttrcSetStrAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -if use_mutt_sidebar == 1 - syn keyword muttrcVarStr skipwhite contained sidebar_delim nextgroup=muttrcSetStrAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -endif +syn keyword muttrcVarStr contained skipwhite + \ alias_file assumed_charset attach_charset attach_sep certificate_file charset + \ config_charset content_type default_hook display_filter dotlock_program + \ dsn_notify dsn_return editor entropy_file envelope_from_address escape folder + \ forw_format forward_format from gecos_mask hdr_format header_cache + \ header_cache_compress header_cache_pagesize history_file hostname + \ imap_authenticators imap_delim_chars imap_headers imap_idle imap_login + \ imap_pass imap_user indent_str indent_string ispell locale mailcap_path mask + \ mbox mbox_type message_cachedir mh_seq_flagged mh_seq_replied mh_seq_unseen + \ mixmaster msg_format pager pgp_decryption_okay pgp_good_sign + \ pgp_mime_signature_description pgp_mime_signature_filename pgp_sign_as + \ pgp_sort_keys pipe_sep pop_authenticators pop_host pop_pass pop_user + \ post_indent_str post_indent_string postpone_encrypt_as postponed preconnect + \ print_cmd print_command query_command quote_regexp realname record + \ reply_regexp send_charset sendmail shell sidebar_delim sidebar_delim_chars + \ sidebar_divider_char sidebar_format sidebar_indent_string sidebar_sort_method + \ signature simple_search smileys smime_ca_location smime_certificates + \ smime_default_key smime_encrypt_with smime_keys smime_sign_as + \ smime_sign_digest_alg smtp_authenticators smtp_pass smtp_url sort sort_alias + \ sort_aux sort_browser spam_separator spoolfile ssl_ca_certificates_file + \ ssl_ciphers ssl_client_cert status_chars tmpdir to_chars trash ts_icon_format + \ ts_status_format tunnel visual + \ nextgroup=muttrcSetStrAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr " Present in 1.4.2.1 (pgp_create_traditional was a bool then) syn keyword muttrcVarBool contained skipwhite imap_force_ssl noimap_force_ssl invimap_force_ssl nextgroup=muttrcSetBoolAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr @@ -401,12 +391,11 @@ syn match muttrcMenuCommas /,/ contained syn keyword muttrcHooks contained skipwhite account-hook charset-hook iconv-hook message-hook folder-hook mbox-hook save-hook fcc-hook fcc-save-hook send-hook send2-hook reply-hook crypt-hook -syn keyword muttrcCommand auto_view alternative_order exec unalternative_order -syn keyword muttrcCommand hdr_order iconv-hook ignore mailboxes my_hdr unmailboxes -syn keyword muttrcCommand pgp-hook push score source unauto_view unhdr_order -syn keyword muttrcCommand unignore unmono unmy_hdr unscore -syn keyword muttrcCommand mime_lookup unmime_lookup ungroup -syn keyword muttrcCommand unalternative_order +syn keyword muttrcCommand skipwhite + \ alternative_order auto_view exec hdr_order iconv-hook ignore mailboxes + \ mailto_allow mime_lookup my_hdr pgp-hook push score sidebar_whitelist source + \ unalternative_order unalternative_order unauto_view ungroup unhdr_order + \ unignore unmailboxes unmailto_allow unmime_lookup unmono unmy_hdr unscore syn keyword muttrcCommand skipwhite charset-hook nextgroup=muttrcRXString syn keyword muttrcCommand skipwhite unhook nextgroup=muttrcHooks @@ -441,7 +430,7 @@ syn match muttrcVariableInner contained "\$[a-zA-Z_-]\+" syn match muttrcEscapedVariable contained "\\\$[a-zA-Z_-]\+" syn match muttrcBadAction contained "[^<>]\+" contains=muttrcEmail -syn match muttrcFunction contained "\<\%(attach\|bounce\|copy\|delete\|display\|flag\|forward\|parent\|pipe\|postpone\|print\|recall\|resend\|save\|send\|tag\|undelete\)-message\>" +syn match muttrcFunction contained "\<\%(attach\|bounce\|copy\|delete\|display\|flag\|forward\|parent\|pipe\|postpone\|print\|purge\|recall\|resend\|save\|send\|tag\|undelete\)-message\>" syn match muttrcFunction contained "\<\%(delete\|next\|previous\|read\|tag\|break\|undelete\)-thread\>" syn match muttrcFunction contained "\<link-threads\>" syn match muttrcFunction contained "\<\%(backward\|capitalize\|downcase\|forward\|kill\|upcase\)-word\>" @@ -465,11 +454,13 @@ syn match muttrcFunction contained "\<show-\%(limit\|version\)\>" syn match muttrcFunction contained "\<sort-\%(mailbox\|reverse\)\>" syn match muttrcFunction contained "\<tag-\%(pattern\|\%(sub\)\?thread\|prefix\%(-cond\)\?\)\>" syn match muttrcFunction contained "\<end-cond\>" +syn match muttrcFunction contained "\<sidebar-\%(next\|next-new\|open\|page-down\|page-up\|prev\|prev-new\|toggle-visible\)\>" syn match muttrcFunction contained "\<toggle-\%(mailboxes\|new\|quoted\|subscribed\|unlink\|write\)\>" syn match muttrcFunction contained "\<undelete-\%(pattern\|subthread\)\>" syn match muttrcFunction contained "\<collapse-\%(parts\|thread\|all\)\>" syn match muttrcFunction contained "\<view-\%(attach\|attachments\|file\|mailcap\|name\|text\)\>" syn match muttrcFunction contained "\<\%(backspace\|backward-char\|bol\|bottom\|bottom-page\|buffy-cycle\|clear-flag\|complete\%(-query\)\?\|copy-file\|create-alias\|detach-file\|eol\|exit\|extract-keys\|\%(imap-\)\?fetch-mail\|forget-passphrase\|forward-char\|group-reply\|help\|ispell\|jump\|limit\|list-reply\|mail\|mail-key\|mark-as-new\|middle-page\|new-mime\|noop\|pgp-menu\|query\|query-append\|quit\|quote-char\|read-subthread\|redraw-screen\|refresh\|rename-file\|reply\|select-new\|set-flag\|shell-escape\|skip-quoted\|sort\|subscribe\|sync-mailbox\|top\|top-page\|transpose-chars\|unsubscribe\|untag-pattern\|verify-key\|what-key\|write-fcc\)\>" +syn keyword muttrcFunction contained imap-logout-all if use_mutt_sidebar == 1 syn match muttrcFunction contained "\<sidebar-\%(prev\|next\|open\|scroll-up\|scroll-down\)" endif @@ -578,7 +569,11 @@ syn match muttrcColorMatchCount contained "[0-9]\+" syn match muttrcColorMatchCountNL contained skipwhite skipnl "\s*\\$" nextgroup=muttrcColorMatchCount,muttrcColorMatchCountNL syn region muttrcColorRXPat contained start=+\s*'+ skip=+\\'+ end=+'\s*+ keepend skipwhite contains=muttrcRXString2 nextgroup=muttrcColorMatchCount,muttrcColorMatchCountNL syn region muttrcColorRXPat contained start=+\s*"+ skip=+\\"+ end=+"\s*+ keepend skipwhite contains=muttrcRXString2 nextgroup=muttrcColorMatchCount,muttrcColorMatchCountNL -syn keyword muttrcColorField contained attachment body bold error hdrdefault header index indicator markers message normal quoted search signature status tilde tree underline +syn keyword muttrcColorField skipwhite contained + \ attachment body bold error hdrdefault header index indicator markers message + \ normal prompt quoted search sidebar-divider sidebar-flagged sidebar-highlight + \ sidebar-indicator sidebar-new sidebar-spoolfile signature status tilde tree + \ underline syn match muttrcColorField contained "\<quoted\d\=\>" if use_mutt_sidebar == 1 syn keyword muttrcColorField contained sidebar_new @@ -634,160 +629,150 @@ syn keyword muttrcMono contained mono skipwhite nextgroup=muttrcColorField syn match muttrcMonoLine "^\s*mono\s\+\S\+" skipwhite nextgroup=muttrcMonoAttrib contains=muttrcMono " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_muttrc_syntax_inits") - if version < 508 - let did_muttrc_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink muttrcComment Comment - HiLink muttrcEscape SpecialChar - HiLink muttrcRXChars SpecialChar - HiLink muttrcString String - HiLink muttrcRXString String - HiLink muttrcRXString2 String - HiLink muttrcSpecial Special - HiLink muttrcHooks Type - HiLink muttrcGroupFlag Type - HiLink muttrcGroupDef Macro - HiLink muttrcAddrDef muttrcGroupFlag - HiLink muttrcRXDef muttrcGroupFlag - HiLink muttrcRXPat String - HiLink muttrcAliasGroupName Macro - HiLink muttrcAliasKey Identifier - HiLink muttrcUnAliasKey Identifier - HiLink muttrcAliasEncEmail Identifier - HiLink muttrcAliasParens Type - HiLink muttrcSetNumAssignment Number - HiLink muttrcSetBoolAssignment Boolean - HiLink muttrcSetQuadAssignment Boolean - HiLink muttrcSetStrAssignment String - HiLink muttrcEmail Special - HiLink muttrcVariableInner Special - HiLink muttrcEscapedVariable String - HiLink muttrcHeader Type - HiLink muttrcKeySpecial SpecialChar - HiLink muttrcKey Type - HiLink muttrcKeyName SpecialChar - HiLink muttrcVarBool Identifier - HiLink muttrcVarQuad Identifier - HiLink muttrcVarNum Identifier - HiLink muttrcVarStr Identifier - HiLink muttrcMenu Identifier - HiLink muttrcCommand Keyword - HiLink muttrcMacroDescr String - HiLink muttrcAction Macro - HiLink muttrcBadAction Error - HiLink muttrcBindFunction Error - HiLink muttrcBindMenuList Error - HiLink muttrcFunction Macro - HiLink muttrcGroupKeyword muttrcCommand - HiLink muttrcGroupLine Error - HiLink muttrcSubscribeKeyword muttrcCommand - HiLink muttrcSubscribeLine Error - HiLink muttrcListsKeyword muttrcCommand - HiLink muttrcListsLine Error - HiLink muttrcAlternateKeyword muttrcCommand - HiLink muttrcAlternatesLine Error - HiLink muttrcAttachmentsLine muttrcCommand - HiLink muttrcAttachmentsFlag Type - HiLink muttrcAttachmentsMimeType String - HiLink muttrcColorLine Error - HiLink muttrcColorContext Error - HiLink muttrcColorContextI Identifier - HiLink muttrcColorContextH Identifier - HiLink muttrcColorKeyword muttrcCommand - HiLink muttrcColorKeywordI muttrcColorKeyword - HiLink muttrcColorKeywordH muttrcColorKeyword - HiLink muttrcColorField Identifier - HiLink muttrcColor Type - HiLink muttrcColorFG Error - HiLink muttrcColorFGI Error - HiLink muttrcColorFGH Error - HiLink muttrcColorBG Error - HiLink muttrcColorBGI Error - HiLink muttrcColorBGH Error - HiLink muttrcMonoAttrib muttrcColor - HiLink muttrcMono muttrcCommand - HiLink muttrcSimplePat Identifier - HiLink muttrcSimplePatString Macro - HiLink muttrcSimplePatMetas Special - HiLink muttrcPattern Error - HiLink muttrcUnColorLine Error - HiLink muttrcUnColorKeyword muttrcCommand - HiLink muttrcUnColorIndex Identifier - HiLink muttrcShellString muttrcEscape - HiLink muttrcRXHooks muttrcCommand - HiLink muttrcRXHookNot Type - HiLink muttrcPatHooks muttrcCommand - HiLink muttrcPatHookNot Type - HiLink muttrcFormatConditionals2 Type - HiLink muttrcIndexFormatStr muttrcString - HiLink muttrcIndexFormatEscapes muttrcEscape - HiLink muttrcIndexFormatConditionals muttrcFormatConditionals2 - HiLink muttrcAliasFormatStr muttrcString - HiLink muttrcAliasFormatEscapes muttrcEscape - HiLink muttrcAttachFormatStr muttrcString - HiLink muttrcAttachFormatEscapes muttrcEscape - HiLink muttrcAttachFormatConditionals muttrcFormatConditionals2 - HiLink muttrcComposeFormatStr muttrcString - HiLink muttrcComposeFormatEscapes muttrcEscape - HiLink muttrcFolderFormatStr muttrcString - HiLink muttrcFolderFormatEscapes muttrcEscape - HiLink muttrcFolderFormatConditionals muttrcFormatConditionals2 - HiLink muttrcMixFormatStr muttrcString - HiLink muttrcMixFormatEscapes muttrcEscape - HiLink muttrcMixFormatConditionals muttrcFormatConditionals2 - HiLink muttrcPGPFormatStr muttrcString - HiLink muttrcPGPFormatEscapes muttrcEscape - HiLink muttrcPGPFormatConditionals muttrcFormatConditionals2 - HiLink muttrcPGPCmdFormatStr muttrcString - HiLink muttrcPGPCmdFormatEscapes muttrcEscape - HiLink muttrcPGPCmdFormatConditionals muttrcFormatConditionals2 - HiLink muttrcStatusFormatStr muttrcString - HiLink muttrcStatusFormatEscapes muttrcEscape - HiLink muttrcStatusFormatConditionals muttrcFormatConditionals2 - HiLink muttrcPGPGetKeysFormatStr muttrcString - HiLink muttrcPGPGetKeysFormatEscapes muttrcEscape - HiLink muttrcSmimeFormatStr muttrcString - HiLink muttrcSmimeFormatEscapes muttrcEscape - HiLink muttrcSmimeFormatConditionals muttrcFormatConditionals2 - HiLink muttrcTimeEscapes muttrcEscape - HiLink muttrcPGPTimeEscapes muttrcEscape - HiLink muttrcStrftimeEscapes Type - HiLink muttrcStrftimeFormatStr muttrcString - HiLink muttrcFormatErrors Error - - HiLink muttrcBindFunctionNL SpecialChar - HiLink muttrcBindKeyNL SpecialChar - HiLink muttrcBindMenuListNL SpecialChar - HiLink muttrcMacroDescrNL SpecialChar - HiLink muttrcMacroBodyNL SpecialChar - HiLink muttrcMacroKeyNL SpecialChar - HiLink muttrcMacroMenuListNL SpecialChar - HiLink muttrcColorMatchCountNL SpecialChar - HiLink muttrcColorNL SpecialChar - HiLink muttrcColorRXNL SpecialChar - HiLink muttrcColorBGNL SpecialChar - HiLink muttrcColorFGNL SpecialChar - HiLink muttrcAliasNameNL SpecialChar - HiLink muttrcAliasENNL SpecialChar - HiLink muttrcAliasNL SpecialChar - HiLink muttrcUnAliasNL SpecialChar - HiLink muttrcAliasGroupDefNL SpecialChar - HiLink muttrcAliasEncEmailNL SpecialChar - HiLink muttrcPatternNL SpecialChar - HiLink muttrcUnColorPatNL SpecialChar - HiLink muttrcUnColorAPNL SpecialChar - HiLink muttrcUnColorIndexNL SpecialChar - HiLink muttrcStringNL SpecialChar - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link muttrcComment Comment +hi def link muttrcEscape SpecialChar +hi def link muttrcRXChars SpecialChar +hi def link muttrcString String +hi def link muttrcRXString String +hi def link muttrcRXString2 String +hi def link muttrcSpecial Special +hi def link muttrcHooks Type +hi def link muttrcGroupFlag Type +hi def link muttrcGroupDef Macro +hi def link muttrcAddrDef muttrcGroupFlag +hi def link muttrcRXDef muttrcGroupFlag +hi def link muttrcRXPat String +hi def link muttrcAliasGroupName Macro +hi def link muttrcAliasKey Identifier +hi def link muttrcUnAliasKey Identifier +hi def link muttrcAliasEncEmail Identifier +hi def link muttrcAliasParens Type +hi def link muttrcSetNumAssignment Number +hi def link muttrcSetBoolAssignment Boolean +hi def link muttrcSetQuadAssignment Boolean +hi def link muttrcSetStrAssignment String +hi def link muttrcEmail Special +hi def link muttrcVariableInner Special +hi def link muttrcEscapedVariable String +hi def link muttrcHeader Type +hi def link muttrcKeySpecial SpecialChar +hi def link muttrcKey Type +hi def link muttrcKeyName SpecialChar +hi def link muttrcVarBool Identifier +hi def link muttrcVarQuad Identifier +hi def link muttrcVarNum Identifier +hi def link muttrcVarStr Identifier +hi def link muttrcMenu Identifier +hi def link muttrcCommand Keyword +hi def link muttrcMacroDescr String +hi def link muttrcAction Macro +hi def link muttrcBadAction Error +hi def link muttrcBindFunction Error +hi def link muttrcBindMenuList Error +hi def link muttrcFunction Macro +hi def link muttrcGroupKeyword muttrcCommand +hi def link muttrcGroupLine Error +hi def link muttrcSubscribeKeyword muttrcCommand +hi def link muttrcSubscribeLine Error +hi def link muttrcListsKeyword muttrcCommand +hi def link muttrcListsLine Error +hi def link muttrcAlternateKeyword muttrcCommand +hi def link muttrcAlternatesLine Error +hi def link muttrcAttachmentsLine muttrcCommand +hi def link muttrcAttachmentsFlag Type +hi def link muttrcAttachmentsMimeType String +hi def link muttrcColorLine Error +hi def link muttrcColorContext Error +hi def link muttrcColorContextI Identifier +hi def link muttrcColorContextH Identifier +hi def link muttrcColorKeyword muttrcCommand +hi def link muttrcColorKeywordI muttrcColorKeyword +hi def link muttrcColorKeywordH muttrcColorKeyword +hi def link muttrcColorField Identifier +hi def link muttrcColor Type +hi def link muttrcColorFG Error +hi def link muttrcColorFGI Error +hi def link muttrcColorFGH Error +hi def link muttrcColorBG Error +hi def link muttrcColorBGI Error +hi def link muttrcColorBGH Error +hi def link muttrcMonoAttrib muttrcColor +hi def link muttrcMono muttrcCommand +hi def link muttrcSimplePat Identifier +hi def link muttrcSimplePatString Macro +hi def link muttrcSimplePatMetas Special +hi def link muttrcPattern Error +hi def link muttrcUnColorLine Error +hi def link muttrcUnColorKeyword muttrcCommand +hi def link muttrcUnColorIndex Identifier +hi def link muttrcShellString muttrcEscape +hi def link muttrcRXHooks muttrcCommand +hi def link muttrcRXHookNot Type +hi def link muttrcPatHooks muttrcCommand +hi def link muttrcPatHookNot Type +hi def link muttrcFormatConditionals2 Type +hi def link muttrcIndexFormatStr muttrcString +hi def link muttrcIndexFormatEscapes muttrcEscape +hi def link muttrcIndexFormatConditionals muttrcFormatConditionals2 +hi def link muttrcAliasFormatStr muttrcString +hi def link muttrcAliasFormatEscapes muttrcEscape +hi def link muttrcAttachFormatStr muttrcString +hi def link muttrcAttachFormatEscapes muttrcEscape +hi def link muttrcAttachFormatConditionals muttrcFormatConditionals2 +hi def link muttrcComposeFormatStr muttrcString +hi def link muttrcComposeFormatEscapes muttrcEscape +hi def link muttrcFolderFormatStr muttrcString +hi def link muttrcFolderFormatEscapes muttrcEscape +hi def link muttrcFolderFormatConditionals muttrcFormatConditionals2 +hi def link muttrcMixFormatStr muttrcString +hi def link muttrcMixFormatEscapes muttrcEscape +hi def link muttrcMixFormatConditionals muttrcFormatConditionals2 +hi def link muttrcPGPFormatStr muttrcString +hi def link muttrcPGPFormatEscapes muttrcEscape +hi def link muttrcPGPFormatConditionals muttrcFormatConditionals2 +hi def link muttrcPGPCmdFormatStr muttrcString +hi def link muttrcPGPCmdFormatEscapes muttrcEscape +hi def link muttrcPGPCmdFormatConditionals muttrcFormatConditionals2 +hi def link muttrcStatusFormatStr muttrcString +hi def link muttrcStatusFormatEscapes muttrcEscape +hi def link muttrcStatusFormatConditionals muttrcFormatConditionals2 +hi def link muttrcPGPGetKeysFormatStr muttrcString +hi def link muttrcPGPGetKeysFormatEscapes muttrcEscape +hi def link muttrcSmimeFormatStr muttrcString +hi def link muttrcSmimeFormatEscapes muttrcEscape +hi def link muttrcSmimeFormatConditionals muttrcFormatConditionals2 +hi def link muttrcTimeEscapes muttrcEscape +hi def link muttrcPGPTimeEscapes muttrcEscape +hi def link muttrcStrftimeEscapes Type +hi def link muttrcStrftimeFormatStr muttrcString +hi def link muttrcFormatErrors Error + +hi def link muttrcBindFunctionNL SpecialChar +hi def link muttrcBindKeyNL SpecialChar +hi def link muttrcBindMenuListNL SpecialChar +hi def link muttrcMacroDescrNL SpecialChar +hi def link muttrcMacroBodyNL SpecialChar +hi def link muttrcMacroKeyNL SpecialChar +hi def link muttrcMacroMenuListNL SpecialChar +hi def link muttrcColorMatchCountNL SpecialChar +hi def link muttrcColorNL SpecialChar +hi def link muttrcColorRXNL SpecialChar +hi def link muttrcColorBGNL SpecialChar +hi def link muttrcColorFGNL SpecialChar +hi def link muttrcAliasNameNL SpecialChar +hi def link muttrcAliasENNL SpecialChar +hi def link muttrcAliasNL SpecialChar +hi def link muttrcUnAliasNL SpecialChar +hi def link muttrcAliasGroupDefNL SpecialChar +hi def link muttrcAliasEncEmailNL SpecialChar +hi def link muttrcPatternNL SpecialChar +hi def link muttrcUnColorPatNL SpecialChar +hi def link muttrcUnColorAPNL SpecialChar +hi def link muttrcUnColorIndexNL SpecialChar +hi def link muttrcStringNL SpecialChar + let b:current_syntax = "muttrc" diff --git a/runtime/syntax/mysql.vim b/runtime/syntax/mysql.vim index d7cf74710d..8bd7b6459a 100644 --- a/runtime/syntax/mysql.vim +++ b/runtime/syntax/mysql.vim @@ -6,11 +6,8 @@ " URL: ftp://cedar-solutions.com/software/mysql.vim " Note: The definitions below are taken from the mysql user manual as of April 2002, for version 3.23 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -273,29 +270,19 @@ syn region mysqlFunction start="weekday(" end=")" contains=ALL syn region mysqlFunction start="yearweek(" end=")" contains=ALL " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_mysql_syn_inits") - if version < 508 - let did_mysql_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink mysqlKeyword Statement - HiLink mysqlSpecial Special - HiLink mysqlString String - HiLink mysqlNumber Number - HiLink mysqlVariable Identifier - HiLink mysqlComment Comment - HiLink mysqlType Type - HiLink mysqlOperator Statement - HiLink mysqlFlow Statement - HiLink mysqlFunction Function +hi def link mysqlKeyword Statement +hi def link mysqlSpecial Special +hi def link mysqlString String +hi def link mysqlNumber Number +hi def link mysqlVariable Identifier +hi def link mysqlComment Comment +hi def link mysqlType Type +hi def link mysqlOperator Statement +hi def link mysqlFlow Statement +hi def link mysqlFunction Function - delcommand HiLink -endif let b:current_syntax = "mysql" diff --git a/runtime/syntax/named.vim b/runtime/syntax/named.vim index faec5f68e5..a5757d5eb9 100644 --- a/runtime/syntax/named.vim +++ b/runtime/syntax/named.vim @@ -11,25 +11,16 @@ " This file could do with a lot of improvements, so comments are welcome. " Please submit the named.conf (segment) with any comments. " -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif syn case match -if version >= 600 - setlocal iskeyword=.,-,48-58,A-Z,a-z,_ -else - set iskeyword=.,-,48-58,A-Z,a-z,_ -endif +setlocal iskeyword=.,-,48-58,A-Z,a-z,_ -if version >= 600 - syn sync match namedSync grouphere NONE "^(zone|controls|acl|key)" -endif +syn sync match namedSync grouphere NONE "^(zone|controls|acl|key)" let s:save_cpo = &cpo set cpo-=C @@ -197,48 +188,38 @@ syn match namedEParenError contained +{+ syn match namedParenError +}\([^;]\|$\)+ " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_named_syn_inits") - if version < 508 - let did_named_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink namedComment Comment - HiLink namedInclude Include - HiLink namedKeyword Keyword - HiLink namedIntKeyword Keyword - HiLink namedIdentifier Identifier - HiLink namedIntIdent Identifier - - HiLink namedString String - HiLink namedBool Type - HiLink namedNotBool Error - HiLink namedNumber Number - HiLink namedNotNumber Error - - HiLink namedOption namedKeyword - HiLink namedLogOption namedKeyword - HiLink namedCNOption namedKeyword - HiLink namedQSKeywords Type - HiLink namedCNKeywords Type - HiLink namedLogCategory Type - HiLink namedIPaddr Number - HiLink namedDomain Identifier - HiLink namedZoneOpt namedKeyword - HiLink namedZoneType Type - HiLink namedParenError Error - HiLink namedEParenError Error - HiLink namedIllegalDom Error - HiLink namedIPerror Error - HiLink namedSpareDot Error - HiLink namedError Error - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link namedComment Comment +hi def link namedInclude Include +hi def link namedKeyword Keyword +hi def link namedIntKeyword Keyword +hi def link namedIdentifier Identifier +hi def link namedIntIdent Identifier + +hi def link namedString String +hi def link namedBool Type +hi def link namedNotBool Error +hi def link namedNumber Number +hi def link namedNotNumber Error + +hi def link namedOption namedKeyword +hi def link namedLogOption namedKeyword +hi def link namedCNOption namedKeyword +hi def link namedQSKeywords Type +hi def link namedCNKeywords Type +hi def link namedLogCategory Type +hi def link namedIPaddr Number +hi def link namedDomain Identifier +hi def link namedZoneOpt namedKeyword +hi def link namedZoneType Type +hi def link namedParenError Error +hi def link namedEParenError Error +hi def link namedIllegalDom Error +hi def link namedIPerror Error +hi def link namedSpareDot Error +hi def link namedError Error + let &cpo = s:save_cpo unlet s:save_cpo diff --git a/runtime/syntax/nasm.vim b/runtime/syntax/nasm.vim index a6ed056650..4f70a0f334 100644 --- a/runtime/syntax/nasm.vim +++ b/runtime/syntax/nasm.vim @@ -1,18 +1,17 @@ " Vim syntax file " Language: NASM - The Netwide Assembler (v0.98) -" Maintainer: Andriy Sokolov <andriy145@gmail.com> +" Maintainer: Andrii Sokolov <andriy145@gmail.com> " Original Author: Manuel M.H. Stol <Manuel.Stol@allieddata.nl> " Former Maintainer: Manuel M.H. Stol <Manuel.Stol@allieddata.nl> -" Last Change: 2012 Feb 7 +" Contributors: Leonard Kรถnig <leonard.r.koenig@gmail.com> (C string highlighting) +" Last Change: 2017 Jan 23 " NASM Home: http://www.nasm.us/ " Setup Syntax: -" Clear old syntax settings -if version < 600 - syn clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif " Assembler syntax is case insensetive @@ -21,18 +20,10 @@ syn case ignore " Vim search and movement commands on identifers -if version < 600 - " Comments at start of a line inside which to skip search for indentifiers - set comments=:; - " Identifier Keyword characters (defines \k) - set iskeyword=@,48-57,#,$,.,?,@-@,_,~ -else - " Comments at start of a line inside which to skip search for indentifiers - setlocal comments=:; - " Identifier Keyword characters (defines \k) - setlocal iskeyword=@,48-57,#,$,.,?,@-@,_,~ -endif - +" Comments at start of a line inside which to skip search for indentifiers +setlocal comments=:; +" Identifier Keyword characters (defines \k) +setlocal iskeyword=@,48-57,#,$,.,?,@-@,_,~ " Comments: @@ -77,8 +68,23 @@ syn match nasmLabelError "\<\~\s*\(\k*\s*:\|\$\=\.\k*\)" " Constants: -syn match nasmStringError +["']+ +syn match nasmStringError +["'`]+ +" NASM is case sensitive here: eg. u-prefix allows for 4-digit, U-prefix for +" 8-digit Unicode characters +syn case match +" one-char escape-sequences +syn match nasmCStringEscape display contained "\\[โ"โ\\\?abtnvfre]" +" hex and octal numbers +syn match nasmCStringEscape display contained "\\\(x\x\{2}\|\o\{1,3}\)" +" Unicode characters +syn match nasmCStringEscape display contained "\\\(u\x\{4}\|U\x\{8}\)" +" ISO C99 format strings (copied from cFormat in runtime/syntax/c.vim) +syn match nasmCStringFormat display "%\(\d\+\$\)\=[-+' #0*]*\(\d*\|\*\|\*\d\+\$\)\(\.\(\d*\|\*\|\*\d\+\$\)\)\=\([hlLjzt]\|ll\|hh\)\=\([aAbdiuoxXDOUfFeEgGcCsSpn]\|\[\^\=.[^]]*\]\)" contained +syn match nasmCStringFormat display "%%" contained syn match nasmString +\("[^"]\{-}"\|'[^']\{-}'\)+ +" Highlight C escape- and format-sequences within ``-strings +syn match nasmCString +\(`[^`]\{-}`\)+ contains=nasmCStringEscape,nasmCStringFormat extend +syn case ignore syn match nasmBinNumber "\<[0-1]\+b\>" syn match nasmBinNumber "\<\~[0-1]\+b\>"lc=1 syn match nasmOctNumber "\<\o\+q\>" @@ -431,96 +437,89 @@ syn sync match nasmSync grouphere NONE "^\s*%endmacro\>" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later : only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_nasm_syntax_inits") - if version < 508 - let did_nasm_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet + +" Sub Links: +hi def link nasmInMacDirective nasmDirective +hi def link nasmInMacLabel nasmLocalLabel +hi def link nasmInMacLblWarn nasmLabelWarn +hi def link nasmInMacMacro nasmMacro +hi def link nasmInMacParam nasmMacro +hi def link nasmInMacParamNum nasmDecNumber +hi def link nasmInMacPreCondit nasmPreCondit +hi def link nasmInMacPreProc nasmPreProc +hi def link nasmInPreCondit nasmPreCondit +hi def link nasmInStructure nasmStructure +hi def link nasmStructureLabel nasmStructure + +" Comment Group: +hi def link nasmComment Comment +hi def link nasmSpecialComment SpecialComment +hi def link nasmInCommentTodo Todo + +" Constant Group: +hi def link nasmString String +hi def link nasmCString String +hi def link nasmStringError Error +hi def link nasmCStringEscape SpecialChar +hi def link nasmCStringFormat SpecialChar +hi def link nasmBinNumber Number +hi def link nasmOctNumber Number +hi def link nasmDecNumber Number +hi def link nasmHexNumber Number +hi def link nasmFltNumber Float +hi def link nasmNumberError Error + +" Identifier Group: +hi def link nasmLabel Identifier +hi def link nasmLocalLabel Identifier +hi def link nasmSpecialLabel Special +hi def link nasmLabelError Error +hi def link nasmLabelWarn Todo + +" PreProc Group: +hi def link nasmPreProc PreProc +hi def link nasmDefine Define +hi def link nasmInclude Include +hi def link nasmMacro Macro +hi def link nasmPreCondit PreCondit +hi def link nasmPreProcError Error +hi def link nasmPreProcWarn Todo + +" Type Group: +hi def link nasmType Type +hi def link nasmStorage StorageClass +hi def link nasmStructure Structure +hi def link nasmTypeError Error + +" Directive Group: +hi def link nasmConstant Constant +hi def link nasmInstrModifier Operator +hi def link nasmRepeat Repeat +hi def link nasmDirective Keyword +hi def link nasmStdDirective Operator +hi def link nasmFmtDirective Keyword + +" Register Group: +hi def link nasmCtrlRegister Special +hi def link nasmDebugRegister Debug +hi def link nasmTestRegister Special +hi def link nasmRegisterError Error +hi def link nasmMemRefError Error + +" Instruction Group: +hi def link nasmStdInstruction Statement +hi def link nasmSysInstruction Statement +hi def link nasmDbgInstruction Debug +hi def link nasmFpuInstruction Statement +hi def link nasmMmxInstruction Statement +hi def link nasmSseInstruction Statement +hi def link nasmNowInstruction Statement +hi def link nasmAmdInstruction Special +hi def link nasmCrxInstruction Special +hi def link nasmUndInstruction Todo +hi def link nasmInstructnError Error - " Sub Links: - HiLink nasmInMacDirective nasmDirective - HiLink nasmInMacLabel nasmLocalLabel - HiLink nasmInMacLblWarn nasmLabelWarn - HiLink nasmInMacMacro nasmMacro - HiLink nasmInMacParam nasmMacro - HiLink nasmInMacParamNum nasmDecNumber - HiLink nasmInMacPreCondit nasmPreCondit - HiLink nasmInMacPreProc nasmPreProc - HiLink nasmInPreCondit nasmPreCondit - HiLink nasmInStructure nasmStructure - HiLink nasmStructureLabel nasmStructure - - " Comment Group: - HiLink nasmComment Comment - HiLink nasmSpecialComment SpecialComment - HiLink nasmInCommentTodo Todo - - " Constant Group: - HiLink nasmString String - HiLink nasmStringError Error - HiLink nasmBinNumber Number - HiLink nasmOctNumber Number - HiLink nasmDecNumber Number - HiLink nasmHexNumber Number - HiLink nasmFltNumber Float - HiLink nasmNumberError Error - - " Identifier Group: - HiLink nasmLabel Identifier - HiLink nasmLocalLabel Identifier - HiLink nasmSpecialLabel Special - HiLink nasmLabelError Error - HiLink nasmLabelWarn Todo - - " PreProc Group: - HiLink nasmPreProc PreProc - HiLink nasmDefine Define - HiLink nasmInclude Include - HiLink nasmMacro Macro - HiLink nasmPreCondit PreCondit - HiLink nasmPreProcError Error - HiLink nasmPreProcWarn Todo - - " Type Group: - HiLink nasmType Type - HiLink nasmStorage StorageClass - HiLink nasmStructure Structure - HiLink nasmTypeError Error - - " Directive Group: - HiLink nasmConstant Constant - HiLink nasmInstrModifier Operator - HiLink nasmRepeat Repeat - HiLink nasmDirective Keyword - HiLink nasmStdDirective Operator - HiLink nasmFmtDirective Keyword - - " Register Group: - HiLink nasmCtrlRegister Special - HiLink nasmDebugRegister Debug - HiLink nasmTestRegister Special - HiLink nasmRegisterError Error - HiLink nasmMemRefError Error - - " Instruction Group: - HiLink nasmStdInstruction Statement - HiLink nasmSysInstruction Statement - HiLink nasmDbgInstruction Debug - HiLink nasmFpuInstruction Statement - HiLink nasmMmxInstruction Statement - HiLink nasmSseInstruction Statement - HiLink nasmNowInstruction Statement - HiLink nasmAmdInstruction Special - HiLink nasmCrxInstruction Special - HiLink nasmUndInstruction Todo - HiLink nasmInstructnError Error - - delcommand HiLink -endif let b:current_syntax = "nasm" diff --git a/runtime/syntax/nastran.vim b/runtime/syntax/nastran.vim index f7927693fa..239fd6e49d 100644 --- a/runtime/syntax/nastran.vim +++ b/runtime/syntax/nastran.vim @@ -6,11 +6,8 @@ " Since DMAP shares some traits with fortran, this syntax file " is based on the fortran.vim syntax file. "---------------------------------------------------------------------- -" Remove any old syntax stuff hanging around -"syn clear -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif " DMAP is not case dependent @@ -156,37 +153,28 @@ syn region nastranBulkData start=+ *[Bb][Uu][Ll][Kk] *$+ end=+^ [Ee][Nn][Dd] *[D syn keyword nastranUtilCard ECHOON ECHOOFF INCLUDE PARAM -if version >= 508 || !exists("did_nastran_syntax_inits") - if version < 508 - let did_nastran_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi link <args> - endif - " The default methods for highlighting. Can be overridden later - HiLink nastranDmapexecmod Statement - HiLink nastranDmapType Type - HiLink nastranDmapPreCondit Error - HiLink nastranDmapUtilmod PreProc - HiLink nastranDmapMatmod nastranDmapUtilmod - HiLink nastranDmapString String - HiLink nastranDmapNumber Constant - HiLink nastranDmapFloat nastranDmapNumber - HiLink nastranDmapInitTab nastranDmapNumber - HiLink nastranDmapTab nastranDmapNumber - HiLink nastranDmapLogical nastranDmapExecmod - HiLink nastranDmapImplicit Identifier - HiLink nastranDmapComment Comment - HiLink nastranDmapRepeat nastranDmapexecmod - HiLink nastranNastranCard nastranDmapPreCondit - HiLink nastranECSCard nastranDmapUtilmod - HiLink nastranFMSCard nastranNastranCard - HiLink nastranCC nastranDmapexecmod - HiLink nastranDelimiter Special - HiLink nastranBulkData nastranDmapType - HiLink nastranUtilCard nastranDmapexecmod - delcommand HiLink -endif +" The default methods for highlighting. Can be overridden later +hi def link nastranDmapexecmod Statement +hi def link nastranDmapType Type +hi def link nastranDmapPreCondit Error +hi def link nastranDmapUtilmod PreProc +hi def link nastranDmapMatmod nastranDmapUtilmod +hi def link nastranDmapString String +hi def link nastranDmapNumber Constant +hi def link nastranDmapFloat nastranDmapNumber +hi def link nastranDmapInitTab nastranDmapNumber +hi def link nastranDmapTab nastranDmapNumber +hi def link nastranDmapLogical nastranDmapExecmod +hi def link nastranDmapImplicit Identifier +hi def link nastranDmapComment Comment +hi def link nastranDmapRepeat nastranDmapexecmod +hi def link nastranNastranCard nastranDmapPreCondit +hi def link nastranECSCard nastranDmapUtilmod +hi def link nastranFMSCard nastranNastranCard +hi def link nastranCC nastranDmapexecmod +hi def link nastranDelimiter Special +hi def link nastranBulkData nastranDmapType +hi def link nastranUtilCard nastranDmapexecmod let b:current_syntax = "nastran" diff --git a/runtime/syntax/natural.vim b/runtime/syntax/natural.vim index 4fbc916be2..be529f2d85 100644 --- a/runtime/syntax/natural.vim +++ b/runtime/syntax/natural.vim @@ -6,16 +6,11 @@ " Last Changed: 2012-02-05 18:50:43 " Support: http://www.von-oppen.com/ -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when this syntax file was already loaded -if v:version < 600 - syntax clear - set iskeyword+=-,*,#,+,_,/ -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish -else - setlocal iskeyword+=-,*,#,+,_,/ endif +setlocal iskeyword+=-,*,#,+,_,/ let s:cpo_save = &cpo set cpo&vim @@ -153,59 +148,50 @@ if v:version >= 600 endif -if v:version >= 508 || !exists("did_natural_syntax_inits") - if v:version < 508 - let did_natural_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - " The default methods for highlighting. Can be overridden later - - " Constants - HiLink naturalFormat Constant - HiLink naturalAttribute Constant - HiLink naturalNumber Number - HiLink naturalString String - HiLink naturalBoolean Boolean - - " All kinds of keywords - HiLink naturalConditional Conditional - HiLink naturalRepeat Repeat - HiLink naturalLoop Repeat - HiLink naturalFlow Keyword - HiLink naturalError Keyword - HiLink naturalKeyword Keyword - HiLink naturalOperator Operator - HiLink naturalParGui Operator - - " Labels - HiLink naturalLabel Label - HiLink naturalRefLabel Label - - " Comments - HiLink naturalPComment Comment - HiLink naturalComment Comment - HiLink naturalTodo Todo - HiLink naturalCommentMark PreProc - - HiLink naturalInclude Include - HiLink naturalSysVar Identifier - HiLink naturalLineNo LineNr - HiLink naturalLineRef Error - HiLink naturalSpecial Special - HiLink naturalComKey Todo - - " illegal things - HiLink naturalRMKeyword Error - HiLink naturalLegalIdent Error - - HiLink naturalType Type - HiLink naturalFunction Function - HiLink naturalObjName PreProc - - delcommand HiLink -endif +" The default methods for highlighting. Can be overridden later + +" Constants +hi def link naturalFormat Constant +hi def link naturalAttribute Constant +hi def link naturalNumber Number +hi def link naturalString String +hi def link naturalBoolean Boolean + +" All kinds of keywords +hi def link naturalConditional Conditional +hi def link naturalRepeat Repeat +hi def link naturalLoop Repeat +hi def link naturalFlow Keyword +hi def link naturalError Keyword +hi def link naturalKeyword Keyword +hi def link naturalOperator Operator +hi def link naturalParGui Operator + +" Labels +hi def link naturalLabel Label +hi def link naturalRefLabel Label + +" Comments +hi def link naturalPComment Comment +hi def link naturalComment Comment +hi def link naturalTodo Todo +hi def link naturalCommentMark PreProc + +hi def link naturalInclude Include +hi def link naturalSysVar Identifier +hi def link naturalLineNo LineNr +hi def link naturalLineRef Error +hi def link naturalSpecial Special +hi def link naturalComKey Todo + +" illegal things +hi def link naturalRMKeyword Error +hi def link naturalLegalIdent Error + +hi def link naturalType Type +hi def link naturalFunction Function +hi def link naturalObjName PreProc + let b:current_syntax = "natural" diff --git a/runtime/syntax/ncf.vim b/runtime/syntax/ncf.vim index 2019c03723..0027fd4ef8 100644 --- a/runtime/syntax/ncf.vim +++ b/runtime/syntax/ncf.vim @@ -4,10 +4,8 @@ " Last Change: Tue, 04 Sep 2001 16:20:33 CDT " $Id: ncf.vim,v 1.1 2004/06/13 16:31:58 vimboss Exp $ -" Remove any old syntax stuff hanging around -if version < 600 - syn clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -217,42 +215,33 @@ if exists("ncf_highlight_unknowns") syn match Error "[^ \t]*" contains=ALL endif -if version >= 508 || !exists("did_ncf_syntax_inits") - if version < 508 - let did_ncf_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - " The default methods for highlighting. Can be overridden later - HiLink ncfCommands Statement - HiLink ncfSetCommands ncfCommands - HiLink ncfLogins ncfCommands - HiLink ncfString String - HiLink ncfContString ncfString - HiLink ncfComment Comment - HiLink ncfImplicit Type - HiLink ncfBoolean Boolean - HiLink ncfScript Identifier - HiLink ncfNumber Number - HiLink ncfIPAddr ncfNumber - HiLink ncfHexNumber ncfNumber - HiLink ncfTime ncfNumber - HiLink ncfDSTTime ncfNumber - HiLink ncfPath Constant - HiLink ncfServerName Special - HiLink ncfIPXNet ncfServerName - HiLink ncfTimeTypes Constant - HiLink ncfSetCommandsNum ncfSetCommands - HiLink ncfSetCommandsBool ncfSetCommands - HiLink ncfSetCommandsStr ncfSetCommands - HiLink ncfSetCommandsTime ncfSetCommands - HiLink ncfSetCommandsTimeDate ncfSetCommands - HiLink ncfSetCommandsBindCon ncfSetCommands +" The default methods for highlighting. Can be overridden later +hi def link ncfCommands Statement +hi def link ncfSetCommands ncfCommands +hi def link ncfLogins ncfCommands +hi def link ncfString String +hi def link ncfContString ncfString +hi def link ncfComment Comment +hi def link ncfImplicit Type +hi def link ncfBoolean Boolean +hi def link ncfScript Identifier +hi def link ncfNumber Number +hi def link ncfIPAddr ncfNumber +hi def link ncfHexNumber ncfNumber +hi def link ncfTime ncfNumber +hi def link ncfDSTTime ncfNumber +hi def link ncfPath Constant +hi def link ncfServerName Special +hi def link ncfIPXNet ncfServerName +hi def link ncfTimeTypes Constant +hi def link ncfSetCommandsNum ncfSetCommands +hi def link ncfSetCommandsBool ncfSetCommands +hi def link ncfSetCommandsStr ncfSetCommands +hi def link ncfSetCommandsTime ncfSetCommands +hi def link ncfSetCommandsTimeDate ncfSetCommands +hi def link ncfSetCommandsBindCon ncfSetCommands - delcommand HiLink -endif let b:current_syntax = "ncf" diff --git a/runtime/syntax/netrw.vim b/runtime/syntax/netrw.vim index 718cee1429..3d3aa993bd 100644 --- a/runtime/syntax/netrw.vim +++ b/runtime/syntax/netrw.vim @@ -5,9 +5,8 @@ " --------------------------------------------------------------------- " Syntax Clearing: {{{1 -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif diff --git a/runtime/syntax/nqc.vim b/runtime/syntax/nqc.vim index 0a3cd6bc73..d09c106f98 100644 --- a/runtime/syntax/nqc.vim +++ b/runtime/syntax/nqc.vim @@ -6,11 +6,8 @@ " URL: http://www.enotes.de/twiki/pub/Home/LegoMindstorms/nqc.vim " Filenames: .nqc -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -326,52 +323,42 @@ endif exec "syn sync ccomment nqcComment minlines=" . nqc_minlines " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_nqc_syn_inits") - if version < 508 - let did_nqc_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet + +" The default methods for highlighting. Can be overridden later +hi def link nqcLabel Label +hi def link nqcConditional Conditional +hi def link nqcRepeat Repeat +hi def link nqcCharacter Character +hi def link nqcNumber Number +hi def link nqcFloat Float +hi def link nqcFunction Function +hi def link nqcParenError nqcError +hi def link nqcErrInParen nqcError +hi def link nqcErrInBracket nqcError +hi def link nqcCommentL nqcComment +hi def link nqcCommentStart nqcComment +hi def link nqcCommentError nqcError +hi def link nqcCommentStartError nqcError +hi def link nqcSpaceError nqcError +hi def link nqcStorageClass StorageClass +hi def link nqcInclude Include +hi def link nqcPreProc PreProc +hi def link nqcDefine Macro +hi def link nqcIncluded String +hi def link nqcError Error +hi def link nqcStatement Statement +hi def link nqcEvents Statement +hi def link nqcPreCondit PreCondit +hi def link nqcType Type +hi def link nqcConstant Constant +hi def link nqcCommentSkip nqcComment +hi def link nqcComment Comment +hi def link nqcTodo Todo +hi def link nqcCppSkip nqcCppOut +hi def link nqcCppOut2 nqcCppOut +hi def link nqcCppOut Comment - " The default methods for highlighting. Can be overridden later - HiLink nqcLabel Label - HiLink nqcConditional Conditional - HiLink nqcRepeat Repeat - HiLink nqcCharacter Character - HiLink nqcNumber Number - HiLink nqcFloat Float - HiLink nqcFunction Function - HiLink nqcParenError nqcError - HiLink nqcErrInParen nqcError - HiLink nqcErrInBracket nqcError - HiLink nqcCommentL nqcComment - HiLink nqcCommentStart nqcComment - HiLink nqcCommentError nqcError - HiLink nqcCommentStartError nqcError - HiLink nqcSpaceError nqcError - HiLink nqcStorageClass StorageClass - HiLink nqcInclude Include - HiLink nqcPreProc PreProc - HiLink nqcDefine Macro - HiLink nqcIncluded String - HiLink nqcError Error - HiLink nqcStatement Statement - HiLink nqcEvents Statement - HiLink nqcPreCondit PreCondit - HiLink nqcType Type - HiLink nqcConstant Constant - HiLink nqcCommentSkip nqcComment - HiLink nqcComment Comment - HiLink nqcTodo Todo - HiLink nqcCppSkip nqcCppOut - HiLink nqcCppOut2 nqcCppOut - HiLink nqcCppOut Comment - - delcommand HiLink -endif let b:current_syntax = "nqc" diff --git a/runtime/syntax/nroff.vim b/runtime/syntax/nroff.vim index 280ba9e7d9..3a8cf95856 100644 --- a/runtime/syntax/nroff.vim +++ b/runtime/syntax/nroff.vim @@ -22,12 +22,9 @@ " " {{{1 Start syntax highlighting. " -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded +" quit when a syntax file was already loaded " -if version < 600 - syntax clear -elseif exists("b:current_syntax") +if exists("b:current_syntax") finish endif @@ -197,65 +194,53 @@ syn keyword nroffTodo TODO XXX FIXME contained " " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet +" Only when an item doesn't have highlighting yet " -if version >= 508 || !exists("did_nroff_syn_inits") - - if version < 508 - let did_nroff_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink nroffEscChar nroffSpecialChar - HiLink nroffEscCharAr nroffSpecialChar - HiLink nroffSpecialChar SpecialChar - HiLink nroffSpace Delimiter - - HiLink nroffEscRegArg2 nroffEscRegArg - HiLink nroffEscRegArg nroffIdent - - HiLink nroffEscArg2 nroffEscArg - HiLink nroffEscPar nroffEscape - - HiLink nroffEscRegPar nroffEscape - HiLink nroffEscArg nroffEscape - HiLink nroffSize nroffEscape - HiLink nroffEscape Preproc - - HiLink nroffIgnore Comment - HiLink nroffComment Comment - HiLink nroffTodo Todo - - HiLink nroffReqLeader nroffRequest - HiLink nroffReqName nroffRequest - HiLink nroffRequest Statement - HiLink nroffCond PreCondit - HiLink nroffDefIdent nroffIdent - HiLink nroffIdent Identifier - - HiLink nroffEquation PreProc - HiLink nroffTable PreProc - HiLink nroffPicture PreProc - HiLink nroffRefer PreProc - HiLink nroffGrap PreProc - HiLink nroffGremlin PreProc - - HiLink nroffNumber Number - HiLink nroffBadChar nroffError - HiLink nroffSpaceError nroffError - HiLink nroffError Error - - HiLink nroffPreserve String - HiLink nroffString String - HiLink nroffDefinition String - HiLink nroffDefSpecial Special - - delcommand HiLink -endif +hi def link nroffEscChar nroffSpecialChar +hi def link nroffEscCharAr nroffSpecialChar +hi def link nroffSpecialChar SpecialChar +hi def link nroffSpace Delimiter + +hi def link nroffEscRegArg2 nroffEscRegArg +hi def link nroffEscRegArg nroffIdent + +hi def link nroffEscArg2 nroffEscArg +hi def link nroffEscPar nroffEscape + +hi def link nroffEscRegPar nroffEscape +hi def link nroffEscArg nroffEscape +hi def link nroffSize nroffEscape +hi def link nroffEscape Preproc + +hi def link nroffIgnore Comment +hi def link nroffComment Comment +hi def link nroffTodo Todo + +hi def link nroffReqLeader nroffRequest +hi def link nroffReqName nroffRequest +hi def link nroffRequest Statement +hi def link nroffCond PreCondit +hi def link nroffDefIdent nroffIdent +hi def link nroffIdent Identifier + +hi def link nroffEquation PreProc +hi def link nroffTable PreProc +hi def link nroffPicture PreProc +hi def link nroffRefer PreProc +hi def link nroffGrap PreProc +hi def link nroffGremlin PreProc + +hi def link nroffNumber Number +hi def link nroffBadChar nroffError +hi def link nroffSpaceError nroffError +hi def link nroffError Error + +hi def link nroffPreserve String +hi def link nroffString String +hi def link nroffDefinition String +hi def link nroffDefSpecial Special + let b:current_syntax = "nroff" diff --git a/runtime/syntax/nsis.vim b/runtime/syntax/nsis.vim index d6d803714e..3a343dd430 100644 --- a/runtime/syntax/nsis.vim +++ b/runtime/syntax/nsis.vim @@ -3,11 +3,8 @@ " Maintainer: Alex Jakushev <Alex.Jakushev@kemek.lt> " Last Change: 2004 May 12 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -224,48 +221,36 @@ syn keyword nsisError UninstallExeName " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_nsis_syn_inits") - - if version < 508 - let did_nsys_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - - HiLink nsisInstruction Function - HiLink nsisComment Comment - HiLink nsisLocalLabel Label - HiLink nsisGlobalLabel Label - HiLink nsisStatement Statement - HiLink nsisString String - HiLink nsisBoolean Boolean - HiLink nsisAttribOptions Constant - HiLink nsisExecShell Constant - HiLink nsisFileAttrib Constant - HiLink nsisMessageBox Constant - HiLink nsisRegistry Identifier - HiLink nsisNumber Number - HiLink nsisError Error - HiLink nsisUserVar Identifier - HiLink nsisSysVar Identifier - HiLink nsisAttribute Type - HiLink nsisCompiler Type - HiLink nsisTodo Todo - HiLink nsisCallback Operator - " preprocessor commands - HiLink nsisPreprocSubst PreProc - HiLink nsisDefine Define - HiLink nsisMacro Macro - HiLink nsisPreCondit PreCondit - HiLink nsisInclude Include - HiLink nsisSystem PreProc - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link nsisInstruction Function +hi def link nsisComment Comment +hi def link nsisLocalLabel Label +hi def link nsisGlobalLabel Label +hi def link nsisStatement Statement +hi def link nsisString String +hi def link nsisBoolean Boolean +hi def link nsisAttribOptions Constant +hi def link nsisExecShell Constant +hi def link nsisFileAttrib Constant +hi def link nsisMessageBox Constant +hi def link nsisRegistry Identifier +hi def link nsisNumber Number +hi def link nsisError Error +hi def link nsisUserVar Identifier +hi def link nsisSysVar Identifier +hi def link nsisAttribute Type +hi def link nsisCompiler Type +hi def link nsisTodo Todo +hi def link nsisCallback Operator +" preprocessor commands +hi def link nsisPreprocSubst PreProc +hi def link nsisDefine Define +hi def link nsisMacro Macro +hi def link nsisPreCondit PreCondit +hi def link nsisInclude Include +hi def link nsisSystem PreProc + let b:current_syntax = "nsis" diff --git a/runtime/syntax/obj.vim b/runtime/syntax/obj.vim index 66cd6c2bde..df4dbca5d7 100644 --- a/runtime/syntax/obj.vim +++ b/runtime/syntax/obj.vim @@ -4,11 +4,8 @@ " File Types: .obj (used in 3D) " Last Change: 2010 May 18 " -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -62,34 +59,24 @@ syn match objInt "\d\+" syn match objIndex "\d\+\/\d*\/\d*" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_cabal_syn_inits") - if version < 508 - let did_cabal_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink objError Error - HiLink objComment Comment - HiLink objInclude PreProc - HiLink objFloat Float - HiLink objInt Number - HiLink objGroup Structure - HiLink objIndex Constant - HiLink objMaterial Label +hi def link objError Error +hi def link objComment Comment +hi def link objInclude PreProc +hi def link objFloat Float +hi def link objInt Number +hi def link objGroup Structure +hi def link objIndex Constant +hi def link objMaterial Label - HiLink objVertex Keyword - HiLink objNormale Keyword - HiLink objVertice Keyword - HiLink objFace Keyword - HiLink objKeywords Keyword +hi def link objVertex Keyword +hi def link objNormale Keyword +hi def link objVertice Keyword +hi def link objFace Keyword +hi def link objKeywords Keyword - delcommand HiLink -endif let b:current_syntax = "obj" diff --git a/runtime/syntax/objcpp.vim b/runtime/syntax/objcpp.vim index e80eed900d..f11e307444 100644 --- a/runtime/syntax/objcpp.vim +++ b/runtime/syntax/objcpp.vim @@ -4,23 +4,15 @@ " Ex-Maintainer: Anthony Hodsdon <ahodsdon@fastmail.fm> " Last Change: 2007 Oct 29 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif " Read in C++ and ObjC syntax files -if version < 600 - so <sfile>:p:h/cpp.vim - so <sfile>:p:h/objc.vim -else - runtime! syntax/cpp.vim - unlet b:current_syntax - runtime! syntax/objc.vim -endif +runtime! syntax/cpp.vim +unlet b:current_syntax +runtime! syntax/objc.vim syn keyword objCppNonStructure class template namespace transparent contained syn keyword objCppNonStatement new delete friend using transparent contained diff --git a/runtime/syntax/ocaml.vim b/runtime/syntax/ocaml.vim index 24116f0e02..68c1feddae 100644 --- a/runtime/syntax/ocaml.vim +++ b/runtime/syntax/ocaml.vim @@ -13,11 +13,8 @@ " can be distinguished from begin/end, which is used for indentation, " and folding. (David Baelde) -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") && b:current_syntax == "ocaml" +" quit when a syntax file was already loaded +if exists("b:current_syntax") && b:current_syntax == "ocaml" finish endif @@ -253,78 +250,68 @@ syn sync match ocamlSigSync grouphere ocamlSig "\<sig\>" syn sync match ocamlSigSync groupthere ocamlSig "\<end\>" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_ocaml_syntax_inits") - if version < 508 - let did_ocaml_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink ocamlBraceErr Error - HiLink ocamlBrackErr Error - HiLink ocamlParenErr Error - HiLink ocamlArrErr Error - - HiLink ocamlCommentErr Error - - HiLink ocamlCountErr Error - HiLink ocamlDoErr Error - HiLink ocamlDoneErr Error - HiLink ocamlEndErr Error - HiLink ocamlThenErr Error - - HiLink ocamlCharErr Error - - HiLink ocamlErr Error - - HiLink ocamlComment Comment - - HiLink ocamlModPath Include - HiLink ocamlObject Include - HiLink ocamlModule Include - HiLink ocamlModParam1 Include - HiLink ocamlModType Include - HiLink ocamlMPRestr3 Include - HiLink ocamlFullMod Include - HiLink ocamlModTypeRestr Include - HiLink ocamlWith Include - HiLink ocamlMTDef Include - - HiLink ocamlScript Include - - HiLink ocamlConstructor Constant - - HiLink ocamlVal Keyword - HiLink ocamlModPreRHS Keyword - HiLink ocamlMPRestr2 Keyword - HiLink ocamlKeyword Keyword - HiLink ocamlMethod Include - HiLink ocamlFunDef Keyword - HiLink ocamlRefAssign Keyword - HiLink ocamlKeyChar Keyword - HiLink ocamlAnyVar Keyword - HiLink ocamlTopStop Keyword - HiLink ocamlOperator Keyword - - HiLink ocamlBoolean Boolean - HiLink ocamlCharacter Character - HiLink ocamlNumber Number - HiLink ocamlFloat Float - HiLink ocamlString String - - HiLink ocamlLabel Identifier - - HiLink ocamlType Type - - HiLink ocamlTodo Todo - - HiLink ocamlEncl Keyword - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link ocamlBraceErr Error +hi def link ocamlBrackErr Error +hi def link ocamlParenErr Error +hi def link ocamlArrErr Error + +hi def link ocamlCommentErr Error + +hi def link ocamlCountErr Error +hi def link ocamlDoErr Error +hi def link ocamlDoneErr Error +hi def link ocamlEndErr Error +hi def link ocamlThenErr Error + +hi def link ocamlCharErr Error + +hi def link ocamlErr Error + +hi def link ocamlComment Comment + +hi def link ocamlModPath Include +hi def link ocamlObject Include +hi def link ocamlModule Include +hi def link ocamlModParam1 Include +hi def link ocamlModType Include +hi def link ocamlMPRestr3 Include +hi def link ocamlFullMod Include +hi def link ocamlModTypeRestr Include +hi def link ocamlWith Include +hi def link ocamlMTDef Include + +hi def link ocamlScript Include + +hi def link ocamlConstructor Constant + +hi def link ocamlVal Keyword +hi def link ocamlModPreRHS Keyword +hi def link ocamlMPRestr2 Keyword +hi def link ocamlKeyword Keyword +hi def link ocamlMethod Include +hi def link ocamlFunDef Keyword +hi def link ocamlRefAssign Keyword +hi def link ocamlKeyChar Keyword +hi def link ocamlAnyVar Keyword +hi def link ocamlTopStop Keyword +hi def link ocamlOperator Keyword + +hi def link ocamlBoolean Boolean +hi def link ocamlCharacter Character +hi def link ocamlNumber Number +hi def link ocamlFloat Float +hi def link ocamlString String + +hi def link ocamlLabel Identifier + +hi def link ocamlType Type + +hi def link ocamlTodo Todo + +hi def link ocamlEncl Keyword + let b:current_syntax = "ocaml" diff --git a/runtime/syntax/occam.vim b/runtime/syntax/occam.vim index 1c84bf00f6..01d139bd09 100644 --- a/runtime/syntax/occam.vim +++ b/runtime/syntax/occam.vim @@ -4,9 +4,8 @@ " Maintainer: Mario Schweigler <ms44@kent.ac.uk> " Last Change: 24 May 2003 -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -86,41 +85,32 @@ syn match occamCDString /<\|>\|=\|(\|)/ contained syn region occamCDirective start=/#\(USE\|INCLUDE\|PRAGMA\|DEFINE\|UNDEFINE\|UNDEF\|IF\|ELIF\|ELSE\|ENDIF\|WARNING\|ERROR\|RELAX\)\>/ end=/$/ contains=occamString,occamComment,occamCDString -if version >= 508 || !exists("did_occam_syn_inits") - if version < 508 - let did_occam_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink occamType Type - HiLink occamKeyword Keyword - HiLink occamComment Comment - HiLink occamCommentTitle PreProc - HiLink occamTodo Todo - HiLink occamNote Todo - HiLink occamString String - HiLink occamCharString String - HiLink occamNumber Number - HiLink occamCDirective PreProc - HiLink occamCDString String - HiLink occamPPIdentifier PreProc - HiLink occamBoolean Boolean - HiLink occamSpecialChar SpecialChar - HiLink occamChar Character - HiLink occamStructure Structure - HiLink occamIdentifier Identifier - HiLink occamConstant Constant - HiLink occamOperator Operator - HiLink occamFunction Ignore - HiLink occamRepeat Repeat - HiLink occamConditional Conditional - HiLink occamBrackets Type - HiLink occamParantheses Delimiter - - delcommand HiLink -endif + +hi def link occamType Type +hi def link occamKeyword Keyword +hi def link occamComment Comment +hi def link occamCommentTitle PreProc +hi def link occamTodo Todo +hi def link occamNote Todo +hi def link occamString String +hi def link occamCharString String +hi def link occamNumber Number +hi def link occamCDirective PreProc +hi def link occamCDString String +hi def link occamPPIdentifier PreProc +hi def link occamBoolean Boolean +hi def link occamSpecialChar SpecialChar +hi def link occamChar Character +hi def link occamStructure Structure +hi def link occamIdentifier Identifier +hi def link occamConstant Constant +hi def link occamOperator Operator +hi def link occamFunction Ignore +hi def link occamRepeat Repeat +hi def link occamConditional Conditional +hi def link occamBrackets Type +hi def link occamParantheses Delimiter + let b:current_syntax = "occam" diff --git a/runtime/syntax/omnimark.vim b/runtime/syntax/omnimark.vim index 698b3c09fb..6294945ffb 100644 --- a/runtime/syntax/omnimark.vim +++ b/runtime/syntax/omnimark.vim @@ -3,19 +3,12 @@ " Maintainer: Paul Terray <mailto:terray@4dconcept.fr> " Last Change: 11 Oct 2000 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif -if version < 600 - set iskeyword=@,48-57,_,128-167,224-235,- -else - setlocal iskeyword=@,48-57,_,128-167,224-235,- -endif +setlocal iskeyword=@,48-57,_,128-167,224-235,- syn keyword omnimarkKeywords ACTIVATE AGAIN syn keyword omnimarkKeywords CATCH CLEAR CLOSE COPY COPY-CLEAR CROSS-TRANSLATE @@ -96,26 +89,16 @@ syn match omnimarkEscape contained +%[0-9][0-9]#+ syn sync minlines=2000 " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_omnimark_syntax_inits") - if version < 508 - let did_omnimark_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink omnimarkCommands Statement - HiLink omnimarkKeywords Identifier - HiLink omnimarkString String - HiLink omnimarkPatterns Macro -" HiLink omnimarkNumber Number - HiLink omnimarkComment Comment - HiLink omnimarkEscape Special +hi def link omnimarkCommands Statement +hi def link omnimarkKeywords Identifier +hi def link omnimarkString String +hi def link omnimarkPatterns Macro +" hi def link omnimarkNumber Number +hi def link omnimarkComment Comment +hi def link omnimarkEscape Special - delcommand HiLink -endif let b:current_syntax = "omnimark" diff --git a/runtime/syntax/openroad.vim b/runtime/syntax/openroad.vim index 3f9a78d552..e09f233647 100644 --- a/runtime/syntax/openroad.vim +++ b/runtime/syntax/openroad.vim @@ -3,12 +3,8 @@ " Maintainer: Luis Moreno <lmoreno@eresmas.net> " Last change: 2001 Jun 12 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -" -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -235,32 +231,22 @@ else endif " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet +" Only when an item doesn't have highlighting yet " -if version >= 508 || !exists("did_openroad_syntax_inits") - if version < 508 - let did_openroad_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - HiLink openroadKeyword Statement - HiLink openroadNumber Number - HiLink openroadString String - HiLink openroadComment Comment - HiLink openroadOperator Operator - HiLink openroadType Type - HiLink openroadFunc Special - HiLink openroadClass Type - HiLink openroadEvent Statement - HiLink openroadConst Constant - HiLink openroadVar Identifier - HiLink openroadIdent Identifier - HiLink openroadTodo Todo +hi def link openroadKeyword Statement +hi def link openroadNumber Number +hi def link openroadString String +hi def link openroadComment Comment +hi def link openroadOperator Operator +hi def link openroadType Type +hi def link openroadFunc Special +hi def link openroadClass Type +hi def link openroadEvent Statement +hi def link openroadConst Constant +hi def link openroadVar Identifier +hi def link openroadIdent Identifier +hi def link openroadTodo Todo - delcommand HiLink -endif let b:current_syntax = "openroad" diff --git a/runtime/syntax/opl.vim b/runtime/syntax/opl.vim index 1b07e3596c..8b66a5b345 100644 --- a/runtime/syntax/opl.vim +++ b/runtime/syntax/opl.vim @@ -6,11 +6,8 @@ " Open Psion Language... (EPOC16/EPOC32) -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -75,25 +72,15 @@ syn region OPLComment start="REM[\t ]" end="$" syn match OPLMathsOperator "-\|=\|[:<>+\*^/\\]" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_OPL_syntax_inits") - if version < 508 - let did_OPL_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink OPLStatement Statement - HiLink OPLNumber Number - HiLink OPLString String - HiLink OPLComment Comment - HiLink OPLMathsOperator Conditional -" HiLink OPLError Error +hi def link OPLStatement Statement +hi def link OPLNumber Number +hi def link OPLString String +hi def link OPLComment Comment +hi def link OPLMathsOperator Conditional +" hi def link OPLError Error - delcommand HiLink -endif let b:current_syntax = "opl" diff --git a/runtime/syntax/ora.vim b/runtime/syntax/ora.vim index bf5d3220a0..99034793f2 100644 --- a/runtime/syntax/ora.vim +++ b/runtime/syntax/ora.vim @@ -11,10 +11,8 @@ " sqlnet-ora and tnsnames.ora; since will not cause(?) problems " is easier to follow separately each file's keywords) -" Remove any old syntax stuff hanging around, if needed -if version < 600 - syn clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -437,35 +435,23 @@ syn cluster oraAll add=oraValue,oraModifier,oraString,oraSpecial,oraComment "============================================================================== " highlighting -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_ora_syn_inits") - - if version < 508 - let did_ora_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink oraKeyword Statement "usual keywords - HiLink oraKeywordGroup Type "keywords which group other keywords - HiLink oraKeywordPref oraKeywordGroup "keywords which act as prefixes - HiLink oraKeywordObs Todo "obsolete keywords - HiLink oraKeywordUnd PreProc "undocumented keywords - HiLink oraKeywordUndObs oraKeywordObs "undocumented obsolete keywords - HiLink oraValue Identifier "values, like true or false - HiLink oraModifier oraValue "modifies values - HiLink oraString String "strings - - HiLink oraSpecial Special "special characters - HiLink oraError Error "errors - HiLink oraParenError oraError "errors caused by mismatching parantheses - - HiLink oraComment Comment "comments - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link oraKeyword Statement "usual keywords +hi def link oraKeywordGroup Type "keywords which group other keywords +hi def link oraKeywordPref oraKeywordGroup "keywords which act as prefixes +hi def link oraKeywordObs Todo "obsolete keywords +hi def link oraKeywordUnd PreProc "undocumented keywords +hi def link oraKeywordUndObs oraKeywordObs "undocumented obsolete keywords +hi def link oraValue Identifier "values, like true or false +hi def link oraModifier oraValue "modifies values +hi def link oraString String "strings + +hi def link oraSpecial Special "special characters +hi def link oraError Error "errors +hi def link oraParenError oraError "errors caused by mismatching parantheses + +hi def link oraComment Comment "comments diff --git a/runtime/syntax/papp.vim b/runtime/syntax/papp.vim index d86dce603f..5b65f05cf4 100644 --- a/runtime/syntax/papp.vim +++ b/runtime/syntax/papp.vim @@ -14,41 +14,24 @@ " pod is, btw, allowed everywhere, which is actually wrong :( -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif " source is basically xml, with included html (this is common) and perl bits -if version < 600 - so <sfile>:p:h/xml.vim -else - runtime! syntax/xml.vim -endif +runtime! syntax/xml.vim unlet b:current_syntax if exists("papp_include_html") - if version < 600 - syn include @PAppHtml <sfile>:p:h/html.vim - else - syn include @PAppHtml syntax/html.vim - endif + syn include @PAppHtml syntax/html.vim unlet b:current_syntax syntax spell default " added by Bram endif -if version < 600 - syn include @PAppPerl <sfile>:p:h/perl.vim -else - syn include @PAppPerl syntax/perl.vim -endif +syn include @PAppPerl syntax/perl.vim -if v:version >= 600 - syn cluster xmlFoldCluster add=papp_perl,papp_xperl,papp_phtml,papp_pxml,papp_perlPOD -endif +syn cluster xmlFoldCluster add=papp_perl,papp_xperl,papp_phtml,papp_pxml,papp_perlPOD " preprocessor commands syn region papp_prep matchgroup=papp_prep start="^#\s*\(if\|elsif\)" end="$" keepend contains=@perlExpr contained diff --git a/runtime/syntax/pascal.vim b/runtime/syntax/pascal.vim index d2b6060acc..2a58ee43f6 100644 --- a/runtime/syntax/pascal.vim +++ b/runtime/syntax/pascal.vim @@ -12,11 +12,8 @@ " Austin Ziegler <austin@halostatue.ca>, " Markus Koenig <markus@stber-koenig.de> -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -320,52 +317,42 @@ if !exists("pascal_traditional") endif " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_pascal_syn_inits") - if version < 508 - let did_pascal_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet + +hi def link pascalAcces pascalStatement +hi def link pascalBoolean Boolean +hi def link pascalComment Comment +hi def link pascalConditional Conditional +hi def link pascalConstant Constant +hi def link pascalDelimiter Identifier +hi def link pascalDirective pascalStatement +hi def link pascalException Exception +hi def link pascalFloat Float +hi def link pascalFunction Function +hi def link pascalLabel Label +hi def link pascalMatrixDelimiter Identifier +hi def link pascalModifier Type +hi def link pascalNumber Number +hi def link pascalOperator Operator +hi def link pascalPredefined pascalStatement +hi def link pascalPreProc PreProc +hi def link pascalRepeat Repeat +hi def link pascalSpaceError Error +hi def link pascalStatement Statement +hi def link pascalString String +hi def link pascalStringEscape Special +hi def link pascalStringEscapeGPC Special +hi def link pascalStringError Error +hi def link pascalStruct pascalStatement +hi def link pascalSymbolOperator pascalOperator +hi def link pascalTodo Todo +hi def link pascalType Type +hi def link pascalUnclassified pascalStatement +" hi def link pascalAsm Assembler +hi def link pascalError Error +hi def link pascalAsmKey pascalStatement +hi def link pascalShowTab Error - HiLink pascalAcces pascalStatement - HiLink pascalBoolean Boolean - HiLink pascalComment Comment - HiLink pascalConditional Conditional - HiLink pascalConstant Constant - HiLink pascalDelimiter Identifier - HiLink pascalDirective pascalStatement - HiLink pascalException Exception - HiLink pascalFloat Float - HiLink pascalFunction Function - HiLink pascalLabel Label - HiLink pascalMatrixDelimiter Identifier - HiLink pascalModifier Type - HiLink pascalNumber Number - HiLink pascalOperator Operator - HiLink pascalPredefined pascalStatement - HiLink pascalPreProc PreProc - HiLink pascalRepeat Repeat - HiLink pascalSpaceError Error - HiLink pascalStatement Statement - HiLink pascalString String - HiLink pascalStringEscape Special - HiLink pascalStringEscapeGPC Special - HiLink pascalStringError Error - HiLink pascalStruct pascalStatement - HiLink pascalSymbolOperator pascalOperator - HiLink pascalTodo Todo - HiLink pascalType Type - HiLink pascalUnclassified pascalStatement - " HiLink pascalAsm Assembler - HiLink pascalError Error - HiLink pascalAsmKey pascalStatement - HiLink pascalShowTab Error - - delcommand HiLink -endif let b:current_syntax = "pascal" diff --git a/runtime/syntax/pcap.vim b/runtime/syntax/pcap.vim index 17d0d42c0b..e0eed633c1 100644 --- a/runtime/syntax/pcap.vim +++ b/runtime/syntax/pcap.vim @@ -4,20 +4,13 @@ " Modified by Bram " Last Change: 2003 May 11 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif "define keywords -if version < 600 - set isk=@,46-57,_,-,#,=,192-255 -else - setlocal isk=@,46-57,_,-,#,=,192-255 -endif +setlocal isk=@,46-57,_,-,#,=,192-255 "first all the bad guys syn match pcapBad '^.\+$' "define any line as bad @@ -43,22 +36,12 @@ syn sync minlines=50 " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_pcap_syntax_inits") - if version < 508 - let did_pcap_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink pcapBad WarningMsg - HiLink pcapBadword WarningMsg - HiLink pcapComment Comment +hi def link pcapBad WarningMsg +hi def link pcapBadword WarningMsg +hi def link pcapComment Comment - delcommand HiLink -endif let b:current_syntax = "pcap" diff --git a/runtime/syntax/pccts.vim b/runtime/syntax/pccts.vim index 8341f5bd43..780035798b 100644 --- a/runtime/syntax/pccts.vim +++ b/runtime/syntax/pccts.vim @@ -3,20 +3,13 @@ " Maintainer: Scott Bigham <dsb@killerbunnies.org> " Last Change: 10 Aug 1999 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif " Read the C++ syntax to start with -if version < 600 - syn include @cppTopLevel <sfile>:p:h/cpp.vim -else - syn include @cppTopLevel syntax/cpp.vim -endif +syn include @cppTopLevel syntax/cpp.vim syn region pcctsAction matchgroup=pcctsDelim start="<<" end=">>?\=" contains=@cppTopLevel,pcctsRuleRef @@ -72,34 +65,24 @@ syn sync match pcctsSyncRule grouphere pcctsRule "\<[a-z][A-Za-z0-9_]*\>\s*\[[^] syn sync match pcctsSyncRule grouphere pcctsRule "\<[a-z][A-Za-z0-9_]*\>\(\s*\[[^]]*\]\)\=\s*>\s*\[[^]]*\]\s*:" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_pccts_syntax_inits") - if version < 508 - let did_pccts_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink pcctsDelim Special - HiLink pcctsTokenName Identifier - HiLink pcctsRuleName Statement - HiLink pcctsLabelHack Label - HiLink pcctsDirective PreProc - HiLink pcctsString String - HiLink pcctsComment Comment - HiLink pcctsClass Statement - HiLink pcctsClassName Identifier - HiLink pcctsException Statement - HiLink pcctsExceptionHandler Keyword - HiLink pcctsExceptionRuleRef pcctsDelim - HiLink pcctsExceptionID Identifier - HiLink pcctsRuleRef Identifier - HiLink pcctsSpecialChar SpecialChar - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link pcctsDelim Special +hi def link pcctsTokenName Identifier +hi def link pcctsRuleName Statement +hi def link pcctsLabelHack Label +hi def link pcctsDirective PreProc +hi def link pcctsString String +hi def link pcctsComment Comment +hi def link pcctsClass Statement +hi def link pcctsClassName Identifier +hi def link pcctsException Statement +hi def link pcctsExceptionHandler Keyword +hi def link pcctsExceptionRuleRef pcctsDelim +hi def link pcctsExceptionID Identifier +hi def link pcctsRuleRef Identifier +hi def link pcctsSpecialChar SpecialChar + let b:current_syntax = "pccts" diff --git a/runtime/syntax/perl.vim b/runtime/syntax/perl.vim index c09373a5cd..6ab6cd83a2 100644 --- a/runtime/syntax/perl.vim +++ b/runtime/syntax/perl.vim @@ -435,121 +435,119 @@ else syn sync minlines=0 endif -command -nargs=+ HiLink hi def link <args> " NOTE: If you're linking new highlight groups to perlString, please also put " them into b:match_skip in ftplugin/perl.vim. " The default highlighting. -HiLink perlSharpBang PreProc -HiLink perlControl PreProc -HiLink perlInclude Include -HiLink perlSpecial Special -HiLink perlString String -HiLink perlCharacter Character -HiLink perlNumber Number -HiLink perlFloat Float -HiLink perlType Type -HiLink perlIdentifier Identifier -HiLink perlLabel Label -HiLink perlStatement Statement -HiLink perlConditional Conditional -HiLink perlRepeat Repeat -HiLink perlOperator Operator -HiLink perlFunction Keyword -HiLink perlSubName Function -HiLink perlSubPrototype Type -HiLink perlSubAttributes PreProc -HiLink perlSubAttributesCont perlSubAttributes -HiLink perlComment Comment -HiLink perlTodo Todo +hi def link perlSharpBang PreProc +hi def link perlControl PreProc +hi def link perlInclude Include +hi def link perlSpecial Special +hi def link perlString String +hi def link perlCharacter Character +hi def link perlNumber Number +hi def link perlFloat Float +hi def link perlType Type +hi def link perlIdentifier Identifier +hi def link perlLabel Label +hi def link perlStatement Statement +hi def link perlConditional Conditional +hi def link perlRepeat Repeat +hi def link perlOperator Operator +hi def link perlFunction Keyword +hi def link perlSubName Function +hi def link perlSubPrototype Type +hi def link perlSubAttributes PreProc +hi def link perlSubAttributesCont perlSubAttributes +hi def link perlComment Comment +hi def link perlTodo Todo if exists("perl_string_as_statement") - HiLink perlStringStartEnd perlStatement + hi def link perlStringStartEnd perlStatement else - HiLink perlStringStartEnd perlString + hi def link perlStringStartEnd perlString endif -HiLink perlVStringV perlStringStartEnd -HiLink perlList perlStatement -HiLink perlMisc perlStatement -HiLink perlVarPlain perlIdentifier -HiLink perlVarPlain2 perlIdentifier -HiLink perlArrow perlIdentifier -HiLink perlFiledescRead perlIdentifier -HiLink perlFiledescStatement perlIdentifier -HiLink perlVarSimpleMember perlIdentifier -HiLink perlVarSimpleMemberName perlString -HiLink perlVarNotInMatches perlIdentifier -HiLink perlVarSlash perlIdentifier -HiLink perlQQ perlString -HiLink perlHereDoc perlString -HiLink perlStringUnexpanded perlString -HiLink perlSubstitutionSQ perlString -HiLink perlSubstitutionGQQ perlString -HiLink perlTranslationGQ perlString -HiLink perlMatch perlString -HiLink perlMatchStartEnd perlStatement -HiLink perlFormatName perlIdentifier -HiLink perlFormatField perlString -HiLink perlPackageDecl perlType -HiLink perlStorageClass perlType -HiLink perlPackageRef perlType -HiLink perlStatementPackage perlStatement -HiLink perlStatementStorage perlStatement -HiLink perlStatementControl perlStatement -HiLink perlStatementScalar perlStatement -HiLink perlStatementRegexp perlStatement -HiLink perlStatementNumeric perlStatement -HiLink perlStatementList perlStatement -HiLink perlStatementHash perlStatement -HiLink perlStatementIOfunc perlStatement -HiLink perlStatementFiledesc perlStatement -HiLink perlStatementVector perlStatement -HiLink perlStatementFiles perlStatement -HiLink perlStatementFlow perlStatement -HiLink perlStatementInclude perlStatement -HiLink perlStatementProc perlStatement -HiLink perlStatementSocket perlStatement -HiLink perlStatementIPC perlStatement -HiLink perlStatementNetwork perlStatement -HiLink perlStatementPword perlStatement -HiLink perlStatementTime perlStatement -HiLink perlStatementMisc perlStatement -HiLink perlStatementIndirObj perlStatement -HiLink perlFunctionName perlIdentifier -HiLink perlMethod perlIdentifier -HiLink perlFunctionPRef perlType -HiLink perlPOD perlComment -HiLink perlShellCommand perlString -HiLink perlSpecialAscii perlSpecial -HiLink perlSpecialDollar perlSpecial -HiLink perlSpecialString perlSpecial -HiLink perlSpecialStringU perlSpecial -HiLink perlSpecialMatch perlSpecial -HiLink perlDATA perlComment +hi def link perlVStringV perlStringStartEnd +hi def link perlList perlStatement +hi def link perlMisc perlStatement +hi def link perlVarPlain perlIdentifier +hi def link perlVarPlain2 perlIdentifier +hi def link perlArrow perlIdentifier +hi def link perlFiledescRead perlIdentifier +hi def link perlFiledescStatement perlIdentifier +hi def link perlVarSimpleMember perlIdentifier +hi def link perlVarSimpleMemberName perlString +hi def link perlVarNotInMatches perlIdentifier +hi def link perlVarSlash perlIdentifier +hi def link perlQQ perlString +hi def link perlHereDoc perlString +hi def link perlStringUnexpanded perlString +hi def link perlSubstitutionSQ perlString +hi def link perlSubstitutionGQQ perlString +hi def link perlTranslationGQ perlString +hi def link perlMatch perlString +hi def link perlMatchStartEnd perlStatement +hi def link perlFormatName perlIdentifier +hi def link perlFormatField perlString +hi def link perlPackageDecl perlType +hi def link perlStorageClass perlType +hi def link perlPackageRef perlType +hi def link perlStatementPackage perlStatement +hi def link perlStatementStorage perlStatement +hi def link perlStatementControl perlStatement +hi def link perlStatementScalar perlStatement +hi def link perlStatementRegexp perlStatement +hi def link perlStatementNumeric perlStatement +hi def link perlStatementList perlStatement +hi def link perlStatementHash perlStatement +hi def link perlStatementIOfunc perlStatement +hi def link perlStatementFiledesc perlStatement +hi def link perlStatementVector perlStatement +hi def link perlStatementFiles perlStatement +hi def link perlStatementFlow perlStatement +hi def link perlStatementInclude perlStatement +hi def link perlStatementProc perlStatement +hi def link perlStatementSocket perlStatement +hi def link perlStatementIPC perlStatement +hi def link perlStatementNetwork perlStatement +hi def link perlStatementPword perlStatement +hi def link perlStatementTime perlStatement +hi def link perlStatementMisc perlStatement +hi def link perlStatementIndirObj perlStatement +hi def link perlFunctionName perlIdentifier +hi def link perlMethod perlIdentifier +hi def link perlFunctionPRef perlType +hi def link perlPOD perlComment +hi def link perlShellCommand perlString +hi def link perlSpecialAscii perlSpecial +hi def link perlSpecialDollar perlSpecial +hi def link perlSpecialString perlSpecial +hi def link perlSpecialStringU perlSpecial +hi def link perlSpecialMatch perlSpecial +hi def link perlDATA perlComment " NOTE: Due to a bug in Vim (or more likely, a misunderstanding on my part), " I had to remove the transparent property from the following regions " in order to get them to highlight correctly. Feel free to remove " these and reinstate the transparent property if you know how. -HiLink perlParensSQ perlString -HiLink perlBracketsSQ perlString -HiLink perlBracesSQ perlString -HiLink perlAnglesSQ perlString +hi def link perlParensSQ perlString +hi def link perlBracketsSQ perlString +hi def link perlBracesSQ perlString +hi def link perlAnglesSQ perlString -HiLink perlParensDQ perlString -HiLink perlBracketsDQ perlString -HiLink perlBracesDQ perlString -HiLink perlAnglesDQ perlString +hi def link perlParensDQ perlString +hi def link perlBracketsDQ perlString +hi def link perlBracesDQ perlString +hi def link perlAnglesDQ perlString -HiLink perlSpecialStringU2 perlString +hi def link perlSpecialStringU2 perlString " Possible errors -HiLink perlNotEmptyLine Error -HiLink perlElseIfError Error -HiLink perlSubPrototypeError Error -HiLink perlSubError Error +hi def link perlNotEmptyLine Error +hi def link perlElseIfError Error +hi def link perlSubPrototypeError Error +hi def link perlSubError Error -delcommand HiLink " Syncing to speed up processing " diff --git a/runtime/syntax/perl6.vim b/runtime/syntax/perl6.vim index 3d82ced89f..3bcd9ff0e9 100644 --- a/runtime/syntax/perl6.vim +++ b/runtime/syntax/perl6.vim @@ -61,11 +61,8 @@ " unlet perl6_extended_q " unlet perl6_extended_all -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif let s:keepcpo= &cpo @@ -2063,176 +2060,166 @@ syn region p6PodFormatFrench \ contains=p6PodFormatAnglesFrench,p6PodFormatFrench,p6PodFormatOne,p6PodFormatTwo,p6PodFormatThree,p6PodVerticalBar,p6PodSemiColon,p6PodComma " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_perl6_syntax_inits") - if version < 508 - let did_perl6_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet + +hi def link p6EscOctOld p6Error +hi def link p6PackageTwigil p6Twigil +hi def link p6StringAngle p6String +hi def link p6StringFrench p6String +hi def link p6StringAngles p6String +hi def link p6StringSQ p6String +hi def link p6StringDQ p6String +hi def link p6StringQ p6String +hi def link p6RxStringSQ p6String +hi def link p6RxStringDQ p6String +hi def link p6Substitution p6String +hi def link p6Transliteration p6String +hi def link p6StringAuto p6String +hi def link p6StringP5Auto p6String +hi def link p6Key p6String +hi def link p6Match p6String +hi def link p6RegexBlock p6String +hi def link p6RxP5CharClass p6String +hi def link p6RxP5QuoteMeta p6String +hi def link p6RxCharClass p6String +hi def link p6RxQuoteWords p6String +hi def link p6ReduceOp p6Operator +hi def link p6ReverseCrossOp p6Operator +hi def link p6HyperOp p6Operator +hi def link p6QuoteQ p6Operator +hi def link p6RxRange p6StringSpecial +hi def link p6RxAnchor p6StringSpecial +hi def link p6RxP5Anchor p6StringSpecial +hi def link p6CodePoint p6StringSpecial +hi def link p6RxMeta p6StringSpecial +hi def link p6RxP5Range p6StringSpecial +hi def link p6RxP5CPId p6StringSpecial +hi def link p6RxP5Posix p6StringSpecial +hi def link p6RxP5Mod p6StringSpecial +hi def link p6RxP5HexSeq p6StringSpecial +hi def link p6RxP5OctSeq p6StringSpecial +hi def link p6RxP5WriteRefId p6StringSpecial +hi def link p6HexSequence p6StringSpecial +hi def link p6OctSequence p6StringSpecial +hi def link p6RxP5Named p6StringSpecial +hi def link p6RxP5PropId p6StringSpecial +hi def link p6RxP5Quantifier p6StringSpecial +hi def link p6RxP5CountId p6StringSpecial +hi def link p6RxP5Verb p6StringSpecial +hi def link p6Escape p6StringSpecial2 +hi def link p6EscNull p6StringSpecial2 +hi def link p6EscHash p6StringSpecial2 +hi def link p6EscQQ p6StringSpecial2 +hi def link p6EscQuote p6StringSpecial2 +hi def link p6EscDoubleQuote p6StringSpecial2 +hi def link p6EscBackTick p6StringSpecial2 +hi def link p6EscForwardSlash p6StringSpecial2 +hi def link p6EscVerticalBar p6StringSpecial2 +hi def link p6EscExclamation p6StringSpecial2 +hi def link p6EscDollar p6StringSpecial2 +hi def link p6EscOpenCurly p6StringSpecial2 +hi def link p6EscCloseCurly p6StringSpecial2 +hi def link p6EscCloseBracket p6StringSpecial2 +hi def link p6EscCloseAngle p6StringSpecial2 +hi def link p6EscCloseFrench p6StringSpecial2 +hi def link p6EscBackSlash p6StringSpecial2 +hi def link p6RxEscape p6StringSpecial2 +hi def link p6RxCapture p6StringSpecial2 +hi def link p6RxAlternation p6StringSpecial2 +hi def link p6RxP5 p6StringSpecial2 +hi def link p6RxP5ReadRef p6StringSpecial2 +hi def link p6RxP5Oct p6StringSpecial2 +hi def link p6RxP5Hex p6StringSpecial2 +hi def link p6RxP5EscMeta p6StringSpecial2 +hi def link p6RxP5Meta p6StringSpecial2 +hi def link p6RxP5Escape p6StringSpecial2 +hi def link p6RxP5CodePoint p6StringSpecial2 +hi def link p6RxP5WriteRef p6StringSpecial2 +hi def link p6RxP5Prop p6StringSpecial2 + +hi def link p6Property Tag +hi def link p6Attention Todo +hi def link p6Type Type +hi def link p6Error Error +hi def link p6BlockLabel Label +hi def link p6Float Float +hi def link p6Normal Normal +hi def link p6Package Normal +hi def link p6PackageScope Normal +hi def link p6Number Number +hi def link p6VersionNum Number +hi def link p6String String +hi def link p6Repeat Repeat +hi def link p6Keyword Keyword +hi def link p6Pragma Keyword +hi def link p6Module Keyword +hi def link p6DeclareRoutine Keyword +hi def link p6VarStorage Special +hi def link p6FlowControl Special +hi def link p6NumberBase Special +hi def link p6Twigil Special +hi def link p6StringSpecial2 Special +hi def link p6VersionDot Special +hi def link p6Comment Comment +hi def link p6Include Include +hi def link p6Shebang PreProc +hi def link p6ClosureTrait PreProc +hi def link p6Routine Function +hi def link p6Operator Operator +hi def link p6Version Operator +hi def link p6Context Operator +hi def link p6Quote Delimiter +hi def link p6TypeConstraint PreCondit +hi def link p6Exception Exception +hi def link p6Placeholder Identifier +hi def link p6Variable Identifier +hi def link p6VarSlash Identifier +hi def link p6VarNum Identifier +hi def link p6VarExclam Identifier +hi def link p6VarMatch Identifier +hi def link p6VarName Identifier +hi def link p6MatchVar Identifier +hi def link p6RxP5ReadRefId Identifier +hi def link p6RxP5ModDef Identifier +hi def link p6RxP5ModName Identifier +hi def link p6Conditional Conditional +hi def link p6StringSpecial SpecialChar + +hi def link p6PodAbbr p6Pod +hi def link p6PodAbbrEOF p6Pod +hi def link p6PodAbbrNoCode p6Pod +hi def link p6PodAbbrCode p6PodCode +hi def link p6PodPara p6Pod +hi def link p6PodParaEOF p6Pod +hi def link p6PodParaNoCode p6Pod +hi def link p6PodParaCode p6PodCode +hi def link p6PodDelim p6Pod +hi def link p6PodDelimEOF p6Pod +hi def link p6PodDelimNoCode p6Pod +hi def link p6PodDelimCode p6PodCode +hi def link p6PodImplicitCode p6PodCode +hi def link p6PodExtraConfig p6PodPrefix +hi def link p6PodVerticalBar p6PodFormatCode +hi def link p6PodColon p6PodFormatCode +hi def link p6PodSemicolon p6PodFormatCode +hi def link p6PodComma p6PodFormatCode +hi def link p6PodFormatOne p6PodFormat +hi def link p6PodFormatTwo p6PodFormat +hi def link p6PodFormatThree p6PodFormat +hi def link p6PodFormatFrench p6PodFormat + +hi def link p6PodType Type +hi def link p6PodConfigOption String +hi def link p6PodCode PreProc +hi def link p6Pod Comment +hi def link p6PodComment Comment +hi def link p6PodAutoQuote Operator +hi def link p6PodConfigOperator Operator +hi def link p6PodPrefix Statement +hi def link p6PodName Identifier +hi def link p6PodFormatCode SpecialChar +hi def link p6PodFormat SpecialComment - HiLink p6EscOctOld p6Error - HiLink p6PackageTwigil p6Twigil - HiLink p6StringAngle p6String - HiLink p6StringFrench p6String - HiLink p6StringAngles p6String - HiLink p6StringSQ p6String - HiLink p6StringDQ p6String - HiLink p6StringQ p6String - HiLink p6RxStringSQ p6String - HiLink p6RxStringDQ p6String - HiLink p6Substitution p6String - HiLink p6Transliteration p6String - HiLink p6StringAuto p6String - HiLink p6StringP5Auto p6String - HiLink p6Key p6String - HiLink p6Match p6String - HiLink p6RegexBlock p6String - HiLink p6RxP5CharClass p6String - HiLink p6RxP5QuoteMeta p6String - HiLink p6RxCharClass p6String - HiLink p6RxQuoteWords p6String - HiLink p6ReduceOp p6Operator - HiLink p6ReverseCrossOp p6Operator - HiLink p6HyperOp p6Operator - HiLink p6QuoteQ p6Operator - HiLink p6RxRange p6StringSpecial - HiLink p6RxAnchor p6StringSpecial - HiLink p6RxP5Anchor p6StringSpecial - HiLink p6CodePoint p6StringSpecial - HiLink p6RxMeta p6StringSpecial - HiLink p6RxP5Range p6StringSpecial - HiLink p6RxP5CPId p6StringSpecial - HiLink p6RxP5Posix p6StringSpecial - HiLink p6RxP5Mod p6StringSpecial - HiLink p6RxP5HexSeq p6StringSpecial - HiLink p6RxP5OctSeq p6StringSpecial - HiLink p6RxP5WriteRefId p6StringSpecial - HiLink p6HexSequence p6StringSpecial - HiLink p6OctSequence p6StringSpecial - HiLink p6RxP5Named p6StringSpecial - HiLink p6RxP5PropId p6StringSpecial - HiLink p6RxP5Quantifier p6StringSpecial - HiLink p6RxP5CountId p6StringSpecial - HiLink p6RxP5Verb p6StringSpecial - HiLink p6Escape p6StringSpecial2 - HiLink p6EscNull p6StringSpecial2 - HiLink p6EscHash p6StringSpecial2 - HiLink p6EscQQ p6StringSpecial2 - HiLink p6EscQuote p6StringSpecial2 - HiLink p6EscDoubleQuote p6StringSpecial2 - HiLink p6EscBackTick p6StringSpecial2 - HiLink p6EscForwardSlash p6StringSpecial2 - HiLink p6EscVerticalBar p6StringSpecial2 - HiLink p6EscExclamation p6StringSpecial2 - HiLink p6EscDollar p6StringSpecial2 - HiLink p6EscOpenCurly p6StringSpecial2 - HiLink p6EscCloseCurly p6StringSpecial2 - HiLink p6EscCloseBracket p6StringSpecial2 - HiLink p6EscCloseAngle p6StringSpecial2 - HiLink p6EscCloseFrench p6StringSpecial2 - HiLink p6EscBackSlash p6StringSpecial2 - HiLink p6RxEscape p6StringSpecial2 - HiLink p6RxCapture p6StringSpecial2 - HiLink p6RxAlternation p6StringSpecial2 - HiLink p6RxP5 p6StringSpecial2 - HiLink p6RxP5ReadRef p6StringSpecial2 - HiLink p6RxP5Oct p6StringSpecial2 - HiLink p6RxP5Hex p6StringSpecial2 - HiLink p6RxP5EscMeta p6StringSpecial2 - HiLink p6RxP5Meta p6StringSpecial2 - HiLink p6RxP5Escape p6StringSpecial2 - HiLink p6RxP5CodePoint p6StringSpecial2 - HiLink p6RxP5WriteRef p6StringSpecial2 - HiLink p6RxP5Prop p6StringSpecial2 - - HiLink p6Property Tag - HiLink p6Attention Todo - HiLink p6Type Type - HiLink p6Error Error - HiLink p6BlockLabel Label - HiLink p6Float Float - HiLink p6Normal Normal - HiLink p6Package Normal - HiLink p6PackageScope Normal - HiLink p6Number Number - HiLink p6VersionNum Number - HiLink p6String String - HiLink p6Repeat Repeat - HiLink p6Keyword Keyword - HiLink p6Pragma Keyword - HiLink p6Module Keyword - HiLink p6DeclareRoutine Keyword - HiLink p6VarStorage Special - HiLink p6FlowControl Special - HiLink p6NumberBase Special - HiLink p6Twigil Special - HiLink p6StringSpecial2 Special - HiLink p6VersionDot Special - HiLink p6Comment Comment - HiLink p6Include Include - HiLink p6Shebang PreProc - HiLink p6ClosureTrait PreProc - HiLink p6Routine Function - HiLink p6Operator Operator - HiLink p6Version Operator - HiLink p6Context Operator - HiLink p6Quote Delimiter - HiLink p6TypeConstraint PreCondit - HiLink p6Exception Exception - HiLink p6Placeholder Identifier - HiLink p6Variable Identifier - HiLink p6VarSlash Identifier - HiLink p6VarNum Identifier - HiLink p6VarExclam Identifier - HiLink p6VarMatch Identifier - HiLink p6VarName Identifier - HiLink p6MatchVar Identifier - HiLink p6RxP5ReadRefId Identifier - HiLink p6RxP5ModDef Identifier - HiLink p6RxP5ModName Identifier - HiLink p6Conditional Conditional - HiLink p6StringSpecial SpecialChar - - HiLink p6PodAbbr p6Pod - HiLink p6PodAbbrEOF p6Pod - HiLink p6PodAbbrNoCode p6Pod - HiLink p6PodAbbrCode p6PodCode - HiLink p6PodPara p6Pod - HiLink p6PodParaEOF p6Pod - HiLink p6PodParaNoCode p6Pod - HiLink p6PodParaCode p6PodCode - HiLink p6PodDelim p6Pod - HiLink p6PodDelimEOF p6Pod - HiLink p6PodDelimNoCode p6Pod - HiLink p6PodDelimCode p6PodCode - HiLink p6PodImplicitCode p6PodCode - HiLink p6PodExtraConfig p6PodPrefix - HiLink p6PodVerticalBar p6PodFormatCode - HiLink p6PodColon p6PodFormatCode - HiLink p6PodSemicolon p6PodFormatCode - HiLink p6PodComma p6PodFormatCode - HiLink p6PodFormatOne p6PodFormat - HiLink p6PodFormatTwo p6PodFormat - HiLink p6PodFormatThree p6PodFormat - HiLink p6PodFormatFrench p6PodFormat - - HiLink p6PodType Type - HiLink p6PodConfigOption String - HiLink p6PodCode PreProc - HiLink p6Pod Comment - HiLink p6PodComment Comment - HiLink p6PodAutoQuote Operator - HiLink p6PodConfigOperator Operator - HiLink p6PodPrefix Statement - HiLink p6PodName Identifier - HiLink p6PodFormatCode SpecialChar - HiLink p6PodFormat SpecialComment - - delcommand HiLink -endif " Syncing to speed up processing "syn sync match p6SyncPod groupthere p6PodAbbrRegion "^=\K\k*\>" diff --git a/runtime/syntax/pf.vim b/runtime/syntax/pf.vim index 1a8f34bbba..81add10e7e 100644 --- a/runtime/syntax/pf.vim +++ b/runtime/syntax/pf.vim @@ -2,30 +2,22 @@ " Language: OpenBSD packet filter configuration (pf.conf) " Original Author: Camiel Dobbelaar <cd@sentia.nl> " Maintainer: Lauri Tirkkonen <lotheac@iki.fi> -" Last Change: 2013 Apr 02 +" Last Change: 2016 Jul 06 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +if exists("b:current_syntax") finish endif setlocal foldmethod=syntax +syn iskeyword @,48-57,_,-,+ syn sync fromstart syn cluster pfNotLS contains=pfTodo,pfVarAssign -syn keyword pfCmd altq anchor antispoof binat nat pass -syn keyword pfCmd queue rdr scrub table set -syn keyword pfService auth bgp domain finger ftp http https ident -syn keyword pfService imap irc isakmp kerberos mail nameserver nfs -syn keyword pfService nntp ntp pop3 portmap pptp rpcbind rsync smtp -syn keyword pfService snmp snmptrap socks ssh sunrpc syslog telnet -syn keyword pfService tftp www +syn keyword pfCmd anchor antispoof block include match pass queue +syn keyword pfCmd queue set table +syn match pfCmd /^\s*load\sanchor\>/ syn keyword pfTodo TODO XXX contained syn keyword pfWildAddr all any -syn match pfCmd /block\s/ syn match pfComment /#.*$/ contains=pfTodo syn match pfCont /\\$/ syn match pfErrClose /}/ @@ -34,43 +26,81 @@ syn match pfIPv6 /[a-fA-F0-9:]*::[a-fA-F0-9:.]*/ syn match pfIPv6 /[a-fA-F0-9:]\+:[a-fA-F0-9:]\+:[a-fA-F0-9:.]\+/ syn match pfNetmask /\/\d\+/ syn match pfNum /[a-zA-Z0-9_:.]\@<!\d\+[a-zA-Z0-9_:.]\@!/ -syn match pfTable /<\s*[a-zA-Z][a-zA-Z0-9_]*\s*>/ +syn match pfTable /<\s*[a-zA-Z0-9_:][a-zA-Z0-9_:.-]*\s*>/ syn match pfVar /$[a-zA-Z][a-zA-Z0-9_]*/ syn match pfVarAssign /^\s*[a-zA-Z][a-zA-Z0-9_]*\s*=/me=e-1 syn region pfFold1 start=/^#\{1}>/ end=/^#\{1,3}>/me=s-1 transparent fold syn region pfFold2 start=/^#\{2}>/ end=/^#\{2,3}>/me=s-1 transparent fold syn region pfFold3 start=/^#\{3}>/ end=/^#\{3}>/me=s-1 transparent fold syn region pfList start=/{/ end=/}/ transparent contains=ALLBUT,pfErrClose,@pfNotLS -syn region pfString start=/"/ end=/"/ transparent contains=ALLBUT,pfString,@pfNotLS -syn region pfString start=/'/ end=/'/ transparent contains=ALLBUT,pfString,@pfNotLS +syn region pfString start=/"/ skip=/\\"/ end=/"/ contains=pfIPv4,pfIPv6,pfNetmask,pfTable,pfVar +syn region pfString start=/'/ skip=/\\'/ end=/'/ contains=pfIPv4,pfIPv6,pfNetmask,pfTable,pfVar -" Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_c_syn_inits") - if version < 508 - let did_c_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +syn keyword pfService 802-11-iapp Microsoft-SQL-Monitor +syn keyword pfService Microsoft-SQL-Server NeXTStep NextStep +syn keyword pfService afpovertcp afs3-bos afs3-callback afs3-errors +syn keyword pfService afs3-fileserver afs3-kaserver afs3-prserver +syn keyword pfService afs3-rmtsys afs3-update afs3-vlserver +syn keyword pfService afs3-volser amt-redir-tcp amt-redir-tls +syn keyword pfService amt-soap-http amt-soap-https asf-rmcp at-echo +syn keyword pfService at-nbp at-rtmp at-zis auth authentication +syn keyword pfService bfd-control bfd-echo bftp bgp bgpd biff bootpc +syn keyword pfService bootps canna cddb cddbp chargen chat cmd +syn keyword pfService cmip-agent cmip-man comsat conference +syn keyword pfService conserver courier csnet-ns cso-ns cvspserver +syn keyword pfService daap datametrics daytime dhcpd-sync +syn keyword pfService dhcpv6-client dhcpv6-server discard domain +syn keyword pfService echo efs eklogin ekshell ekshell2 epmap eppc +syn keyword pfService exec finger ftp ftp-data git gopher hostname +syn keyword pfService hostnames hprop http https hunt hylafax iapp +syn keyword pfService icb ident imap imap2 imap3 imaps ingreslock +syn keyword pfService ipp iprop ipsec-msft ipsec-nat-t ipx irc +syn keyword pfService isakmp iscsi isisd iso-tsap kauth kdc kerberos +syn keyword pfService kerberos-adm kerberos-iv kerberos-sec +syn keyword pfService kerberos_master kf kip klogin kpasswd kpop +syn keyword pfService krb524 krb_prop krbupdate krcmd kreg kshell kx +syn keyword pfService l2tp ldap ldaps ldp link login mail mdns +syn keyword pfService mdnsresponder microsoft-ds ms-sql-m ms-sql-s +syn keyword pfService msa msp mtp mysql name nameserver netbios-dgm +syn keyword pfService netbios-ns netbios-ssn netnews netplan netrjs +syn keyword pfService netstat netwall newdate nextstep nfs nfsd +syn keyword pfService nicname nnsp nntp ntalk ntp null openwebnet +syn keyword pfService ospf6d ospfapi ospfd photuris pop2 pop3 pop3pw +syn keyword pfService pop3s poppassd portmap postgresql postoffice +syn keyword pfService pptp presence printer prospero prospero-np +syn keyword pfService puppet pwdgen qotd quote radacct radius +syn keyword pfService radius-acct rdp readnews remotefs resource rfb +syn keyword pfService rfe rfs rfs_server ripd ripng rje rkinit rlp +syn keyword pfService routed router rpc rpcbind rsync rtelnet rtsp +syn keyword pfService sa-msg-port sane-port sftp shell sieve silc +syn keyword pfService sink sip smtp smtps smux snmp snmp-trap +syn keyword pfService snmptrap snpp socks source spamd spamd-cfg +syn keyword pfService spamd-sync spooler spop3 ssdp ssh submission +syn keyword pfService sunrpc supdup supfiledbg supfilesrv support +syn keyword pfService svn svrloc swat syslog syslog-tls systat +syn keyword pfService tacacs tacas+ talk tap tcpmux telnet tempo +syn keyword pfService tftp time timed timeserver timserver tsap +syn keyword pfService ttylink ttytst ub-dns-control ulistserv untp +syn keyword pfService usenet users uucp uucp-path uucpd vnc vxlan +syn keyword pfService wais webster who whod whois www x400 x400-snd +syn keyword pfService xcept xdmcp xmpp-bosh xmpp-client xmpp-server +syn keyword pfService z3950 zabbix-agent zabbix-trapper zebra +syn keyword pfService zebrasrv - HiLink pfCmd Statement - HiLink pfComment Comment - HiLink pfCont Statement - HiLink pfErrClose Error - HiLink pfIPv4 Type - HiLink pfIPv6 Type - HiLink pfNetmask Constant - HiLink pfNum Constant - HiLink pfService Constant - HiLink pfTable Identifier - HiLink pfTodo Todo - HiLink pfVar Identifier - HiLink pfVarAssign Identifier - HiLink pfWildAddr Type - - delcommand HiLink -endif +hi def link pfCmd Statement +hi def link pfComment Comment +hi def link pfCont Statement +hi def link pfErrClose Error +hi def link pfIPv4 Type +hi def link pfIPv6 Type +hi def link pfNetmask Constant +hi def link pfNum Constant +hi def link pfService Constant +hi def link pfString String +hi def link pfTable Identifier +hi def link pfTodo Todo +hi def link pfVar Identifier +hi def link pfVarAssign Identifier +hi def link pfWildAddr Type let b:current_syntax = "pf" diff --git a/runtime/syntax/pfmain.vim b/runtime/syntax/pfmain.vim index 32ed6975c0..af58da70ef 100644 --- a/runtime/syntax/pfmain.vim +++ b/runtime/syntax/pfmain.vim @@ -7,17 +7,12 @@ " URL: http://cern.ch/fuji/vim/syntax/pfmain.vim " Comment: Based on Postfix 2.12/3.0 postconf.5.html. -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif -if version >= 600 - setlocal iskeyword=@,48-57,_,- -else - set iskeyword=@,48-57,_,- -endif +setlocal iskeyword=@,48-57,_,- syntax case match syntax sync minlines=1 @@ -1816,33 +1811,24 @@ syntax match pfmainSpecial "\<smtpd\>" syntax match pfmainSpecial "\<trace\>" syntax match pfmainSpecial "\<verify\>" -if version >= 508 || !exists("pfmain_syntax_init") - if version < 508 - let pfmain_syntax_init = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - HiLink pfmainConf Statement - HiLink pfmainRef PreProc - HiLink pfmainWord identifier +hi def link pfmainConf Statement +hi def link pfmainRef PreProc +hi def link pfmainWord identifier - HiLink pfmainDict Type - HiLink pfmainQueueDir Constant - HiLink pfmainTransport Constant - HiLink pfmainLock Constant - HiLink pfmainAnswer Constant +hi def link pfmainDict Type +hi def link pfmainQueueDir Constant +hi def link pfmainTransport Constant +hi def link pfmainLock Constant +hi def link pfmainAnswer Constant - HiLink pfmainComment Comment - HiLink pfmainNumber Number - HiLink pfmainTime Number - HiLink pfmainIP Number - HiLink pfmainVariable Error - HiLink pfmainSpecial Special +hi def link pfmainComment Comment +hi def link pfmainNumber Number +hi def link pfmainTime Number +hi def link pfmainIP Number +hi def link pfmainVariable Error +hi def link pfmainSpecial Special - delcommand HiLink -endif let b:current_syntax = "pfmain" diff --git a/runtime/syntax/php.vim b/runtime/syntax/php.vim index fc257418d0..278fc1358c 100644 --- a/runtime/syntax/php.vim +++ b/runtime/syntax/php.vim @@ -1,7 +1,7 @@ " Vim syntax file -" Language: php PHP 3/4/5 +" Language: php PHP 3/4/5/7 " Maintainer: Jason Woofenden <jason@jasonwoof.com> -" Last Change: Apr 18, 2016 +" Last Change: Dec 11, 2016 " URL: https://jasonwoof.com/gitweb/?p=vim-syntax.git;a=blob;f=php.vim;hb=HEAD " Former Maintainers: Peter Hodge <toomuchphp-vim@yahoo.com> " Debian VIM Maintainers <pkg-vim-maintainers@lists.alioth.debian.org> @@ -55,11 +55,8 @@ " ii) Same problem if you are setting php_folding = 2 with a closing " } inside an string on the first line of this string. -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -67,16 +64,8 @@ if !exists("main_syntax") let main_syntax = 'php' endif -if version < 600 - unlet! php_folding - if exists("php_sync_method") && !php_sync_method - let php_sync_method=-1 - endif - so <sfile>:p:h/html.vim -else - runtime! syntax/html.vim - unlet b:current_syntax -endif +runtime! syntax/html.vim +unlet b:current_syntax " accept old options if !exists("php_sync_method") @@ -94,11 +83,7 @@ endif syn cluster htmlPreproc add=phpRegion,phpRegionAsp,phpRegionSc -if version < 600 - syn include @sqlTop <sfile>:p:h/sql.vim -else - syn include @sqlTop syntax/sql.vim -endif +syn include @sqlTop syntax/sql.vim syn sync clear unlet b:current_syntax syn cluster sqlTop remove=sqlString,sqlComment @@ -377,50 +362,41 @@ syn keyword phpTodo todo fixme xxx contained " Comment if exists("php_parent_error_open") - syn region phpComment start="/\*" end="\*/" contained contains=phpTodo + syn region phpComment start="/\*" end="\*/" contained contains=phpTodo,@Spell else - syn region phpComment start="/\*" end="\*/" contained contains=phpTodo extend -endif -if version >= 600 - syn match phpComment "#.\{-}\(?>\|$\)\@=" contained contains=phpTodo - syn match phpComment "//.\{-}\(?>\|$\)\@=" contained contains=phpTodo -else - syn match phpComment "#.\{-}$" contained contains=phpTodo - syn match phpComment "#.\{-}?>"me=e-2 contained contains=phpTodo - syn match phpComment "//.\{-}$" contained contains=phpTodo - syn match phpComment "//.\{-}?>"me=e-2 contained contains=phpTodo + syn region phpComment start="/\*" end="\*/" contained contains=phpTodo,@Spell extend endif +syn match phpComment "#.\{-}\(?>\|$\)\@=" contained contains=phpTodo,@Spell +syn match phpComment "//.\{-}\(?>\|$\)\@=" contained contains=phpTodo,@Spell " String if exists("php_parent_error_open") - syn region phpStringDouble matchgroup=phpStringDouble start=+"+ skip=+\\\\\|\\"+ end=+"+ contains=@phpAddStrings,phpBackslashSequences,phpBackslashDoubleQuote,@phpInterpDouble contained keepend + syn region phpStringDouble matchgroup=phpStringDouble start=+"+ skip=+\\\\\|\\"+ end=+"+ contains=@phpAddStrings,phpBackslashSequences,phpBackslashDoubleQuote,@phpInterpDouble,@Spell contained keepend syn region phpBacktick matchgroup=phpBacktick start=+`+ skip=+\\\\\|\\"+ end=+`+ contains=@phpAddStrings,phpIdentifier,phpBackslashSequences,phpIdentifierSimply,phpIdentifierComplex contained keepend - syn region phpStringSingle matchgroup=phpStringSingle start=+'+ skip=+\\\\\|\\'+ end=+'+ contains=@phpAddStrings,phpBackslashSingleQuote contained keepend + syn region phpStringSingle matchgroup=phpStringSingle start=+'+ skip=+\\\\\|\\'+ end=+'+ contains=@phpAddStrings,phpBackslashSingleQuote,@Spell contained keepend else - syn region phpStringDouble matchgroup=phpStringDouble start=+"+ skip=+\\\\\|\\"+ end=+"+ contains=@phpAddStrings,phpBackslashSequences,phpBackslashDoubleQuote,@phpInterpDouble contained extend keepend + syn region phpStringDouble matchgroup=phpStringDouble start=+"+ skip=+\\\\\|\\"+ end=+"+ contains=@phpAddStrings,phpBackslashSequences,phpBackslashDoubleQuote,@phpInterpDouble,@Spell contained extend keepend syn region phpBacktick matchgroup=phpBacktick start=+`+ skip=+\\\\\|\\"+ end=+`+ contains=@phpAddStrings,phpIdentifier,phpBackslashSequences,phpIdentifierSimply,phpIdentifierComplex contained extend keepend - syn region phpStringSingle matchgroup=phpStringSingle start=+'+ skip=+\\\\\|\\'+ end=+'+ contains=@phpAddStrings,phpBackslashSingleQuote contained keepend extend + syn region phpStringSingle matchgroup=phpStringSingle start=+'+ skip=+\\\\\|\\'+ end=+'+ contains=@phpAddStrings,phpBackslashSingleQuote,@Spell contained keepend extend endif " HereDoc and NowDoc -if version >= 600 - syn case match +syn case match - " HereDoc - syn region phpHereDoc matchgroup=Delimiter start="\(<<<\)\@<=\(\"\=\)\z(\I\i*\)\2$" end="^\z1\(;\=$\)\@=" contained contains=phpIdentifier,phpIdentifierSimply,phpIdentifierComplex,phpBackslashSequences,phpMethodsVar keepend extend +" HereDoc +syn region phpHereDoc matchgroup=Delimiter start="\(<<<\)\@<=\(\"\=\)\z(\I\i*\)\2$" end="^\z1\(;\=$\)\@=" contained contains=phpIdentifier,phpIdentifierSimply,phpIdentifierComplex,phpBackslashSequences,phpMethodsVar,@Spell keepend extend " including HTML,JavaScript,SQL even if not enabled via options - syn region phpHereDoc matchgroup=Delimiter start="\(<<<\)\@<=\(\"\=\)\z(\(\I\i*\)\=\(html\)\c\(\i*\)\)\2$" end="^\z1\(;\=$\)\@=" contained contains=@htmlTop,phpIdentifier,phpIdentifierSimply,phpIdentifierComplex,phpBackslashSequences,phpMethodsVar keepend extend - syn region phpHereDoc matchgroup=Delimiter start="\(<<<\)\@<=\(\"\=\)\z(\(\I\i*\)\=\(sql\)\c\(\i*\)\)\2$" end="^\z1\(;\=$\)\@=" contained contains=@sqlTop,phpIdentifier,phpIdentifierSimply,phpIdentifierComplex,phpBackslashSequences,phpMethodsVar keepend extend - syn region phpHereDoc matchgroup=Delimiter start="\(<<<\)\@<=\(\"\=\)\z(\(\I\i*\)\=\(javascript\)\c\(\i*\)\)\2$" end="^\z1\(;\=$\)\@=" contained contains=@htmlJavascript,phpIdentifierSimply,phpIdentifier,phpIdentifierComplex,phpBackslashSequences,phpMethodsVar keepend extend +syn region phpHereDoc matchgroup=Delimiter start="\(<<<\)\@<=\(\"\=\)\z(\(\I\i*\)\=\(html\)\c\(\i*\)\)\2$" end="^\z1\(;\=$\)\@=" contained contains=@htmlTop,phpIdentifier,phpIdentifierSimply,phpIdentifierComplex,phpBackslashSequences,phpMethodsVar,@Spell keepend extend +syn region phpHereDoc matchgroup=Delimiter start="\(<<<\)\@<=\(\"\=\)\z(\(\I\i*\)\=\(sql\)\c\(\i*\)\)\2$" end="^\z1\(;\=$\)\@=" contained contains=@sqlTop,phpIdentifier,phpIdentifierSimply,phpIdentifierComplex,phpBackslashSequences,phpMethodsVar,@Spell keepend extend +syn region phpHereDoc matchgroup=Delimiter start="\(<<<\)\@<=\(\"\=\)\z(\(\I\i*\)\=\(javascript\)\c\(\i*\)\)\2$" end="^\z1\(;\=$\)\@=" contained contains=@htmlJavascript,phpIdentifierSimply,phpIdentifier,phpIdentifierComplex,phpBackslashSequences,phpMethodsVar,@Spell keepend extend - " NowDoc - syn region phpNowDoc matchgroup=Delimiter start="\(<<<\)\@<='\z(\I\i*\)'$" end="^\z1\(;\=$\)\@=" contained keepend extend +" NowDoc +syn region phpNowDoc matchgroup=Delimiter start="\(<<<\)\@<='\z(\I\i*\)'$" end="^\z1\(;\=$\)\@=" contained contains=@Spell keepend extend " including HTML,JavaScript,SQL even if not enabled via options - syn region phpNowDoc matchgroup=Delimiter start="\(<<<\)\@<='\z(\(\I\i*\)\=\(html\)\c\(\i*\)\)'$" end="^\z1\(;\=$\)\@=" contained contains=@htmlTop keepend extend - syn region phpNowDoc matchgroup=Delimiter start="\(<<<\)\@<='\z(\(\I\i*\)\=\(sql\)\c\(\i*\)\)'$" end="^\z1\(;\=$\)\@=" contained contains=@sqlTop keepend extend - syn region phpNowDoc matchgroup=Delimiter start="\(<<<\)\@<='\z(\(\I\i*\)\=\(javascript\)\c\(\i*\)\)'$" end="^\z1\(;\=$\)\@=" contained contains=@htmlJavascript keepend extend - syn case ignore -endif +syn region phpNowDoc matchgroup=Delimiter start="\(<<<\)\@<='\z(\(\I\i*\)\=\(html\)\c\(\i*\)\)'$" end="^\z1\(;\=$\)\@=" contained contains=@htmlTop,@Spell keepend extend +syn region phpNowDoc matchgroup=Delimiter start="\(<<<\)\@<='\z(\(\I\i*\)\=\(sql\)\c\(\i*\)\)'$" end="^\z1\(;\=$\)\@=" contained contains=@sqlTop,@Spell keepend extend +syn region phpNowDoc matchgroup=Delimiter start="\(<<<\)\@<='\z(\(\I\i*\)\=\(javascript\)\c\(\i*\)\)'$" end="^\z1\(;\=$\)\@=" contained contains=@htmlJavascript,@Spell keepend extend +syn case ignore " Parent if exists("php_parent_error_close") || exists("php_parent_error_open") @@ -519,7 +495,7 @@ syntax keyword phpSpecialFunction containedin=ALLBUT,phpComment,phpStringDouble, " Highlighting for __autoload slightly different from line above syntax keyword phpSpecialFunction containedin=ALLBUT,phpComment,phpStringDouble,phpStringSingle,phpIdentifier,phpMethodsVar \ __autoload -highlight link phpSpecialFunction phpOperator +hi def link phpSpecialFunction phpOperator " Highlighting for PHP5's built-in classes " - built-in classes harvested from get_declared_classes() in 5.1.4 @@ -542,14 +518,14 @@ syntax keyword phpClasses containedin=ALLBUT,phpComment,phpStringDouble,phpStrin \ DOMCharacterData DOMAttr DOMElement DOMText DOMComment DOMTypeinfo DOMUserDataHandler \ DOMLocator DOMConfiguration DOMCdataSection DOMDocumentType DOMNotation DOMEntity \ DOMEntityReference DOMProcessingInstruction DOMStringExtend DOMXPath -highlight link phpClasses phpFunctions +hi def link phpClasses phpFunctions " Highlighting for PHP5's built-in interfaces " - built-in classes harvested from get_declared_interfaces() in 5.1.4 syntax keyword phpInterfaces containedin=ALLBUT,phpComment,phpStringDouble,phpStringSingle,phpIdentifier,phpMethodsVar \ Iterator IteratorAggregate RecursiveIterator OuterIterator SeekableIterator \ Traversable ArrayAccess Serializable Countable SplObserver SplSubject Reflector -highlight link phpInterfaces phpConstant +hi def link phpInterfaces phpConstant " option defaults: if ! exists('php_special_functions') @@ -577,7 +553,7 @@ endif if php_alt_assignByReference " special highlighting for '=&' operator syntax match phpAssignByRef /=\s*&/ containedin=ALLBUT,phpComment,phpStringDouble,phpStringSingle - highlight link phpAssignByRef Type + hi def link phpAssignByRef Type endif if php_alt_comparisons @@ -589,7 +565,7 @@ if php_alt_comparisons syntax case ignore syntax keyword phpComparison instanceof contained containedin=phpRegion - hi link phpComparison Statement + hi def link phpComparison Statement endif " ================================================================ @@ -621,82 +597,72 @@ syntax match phpDocTags "@\(abstract\|access\|author\|category\|copyright\|dep syntax match phpDocTodo "@\(todo\|fixme\|xxx\)\(\s\+\)\?" containedin=phpComment " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_php_syn_inits") - if version < 508 - let did_php_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink phpConstant Constant - HiLink phpCoreConstant Constant - HiLink phpComment Comment - HiLink phpDocTags PreProc - HiLink phpDocCustomTags Type - HiLink phpException Exception - HiLink phpBoolean Boolean - HiLink phpStorageClass StorageClass - HiLink phpSCKeyword StorageClass - HiLink phpFCKeyword Define - HiLink phpStructure Structure - HiLink phpStringSingle String - HiLink phpStringDouble String - HiLink phpBacktick String - HiLink phpNumber Number - HiLink phpFloat Float - HiLink phpMethods Function - HiLink phpFunctions Function - HiLink phpBaselib Function - HiLink phpRepeat Repeat - HiLink phpConditional Conditional - HiLink phpLabel Label - HiLink phpStatement Statement - HiLink phpKeyword Statement - HiLink phpType Type - HiLink phpInclude Include - HiLink phpDefine Define - HiLink phpBackslashSequences SpecialChar - HiLink phpBackslashDoubleQuote SpecialChar - HiLink phpBackslashSingleQuote SpecialChar - HiLink phpParent Delimiter - HiLink phpBrackets Delimiter - HiLink phpIdentifierConst Delimiter - HiLink phpParentError Error - HiLink phpOctalError Error - HiLink phpInterpSimpleError Error - HiLink phpInterpBogusDollarCurley Error - HiLink phpInterpDollarCurly1 Error - HiLink phpInterpDollarCurly2 Error - HiLink phpInterpSimpleBracketsInner String - HiLink phpInterpSimpleCurly Delimiter - HiLink phpInterpVarname Identifier - HiLink phpTodo Todo - HiLink phpDocTodo Todo - HiLink phpMemberSelector Structure - if exists("php_oldStyle") - hi phpIntVar guifg=Red ctermfg=DarkRed - hi phpEnvVar guifg=Red ctermfg=DarkRed - hi phpOperator guifg=SeaGreen ctermfg=DarkGreen - hi phpVarSelector guifg=SeaGreen ctermfg=DarkGreen - hi phpRelation guifg=SeaGreen ctermfg=DarkGreen - hi phpIdentifier guifg=DarkGray ctermfg=Brown - hi phpIdentifierSimply guifg=DarkGray ctermfg=Brown - else - HiLink phpIntVar Identifier - HiLink phpEnvVar Identifier - HiLink phpOperator Operator - HiLink phpVarSelector Operator - HiLink phpRelation Operator - HiLink phpIdentifier Identifier - HiLink phpIdentifierSimply Identifier - endif - - delcommand HiLink +" Only when an item doesn't have highlighting yet + +hi def link phpConstant Constant +hi def link phpCoreConstant Constant +hi def link phpComment Comment +hi def link phpDocTags PreProc +hi def link phpDocCustomTags Type +hi def link phpException Exception +hi def link phpBoolean Boolean +hi def link phpStorageClass StorageClass +hi def link phpSCKeyword StorageClass +hi def link phpFCKeyword Define +hi def link phpStructure Structure +hi def link phpStringSingle String +hi def link phpStringDouble String +hi def link phpBacktick String +hi def link phpNumber Number +hi def link phpFloat Float +hi def link phpMethods Function +hi def link phpFunctions Function +hi def link phpBaselib Function +hi def link phpRepeat Repeat +hi def link phpConditional Conditional +hi def link phpLabel Label +hi def link phpStatement Statement +hi def link phpKeyword Statement +hi def link phpType Type +hi def link phpInclude Include +hi def link phpDefine Define +hi def link phpBackslashSequences SpecialChar +hi def link phpBackslashDoubleQuote SpecialChar +hi def link phpBackslashSingleQuote SpecialChar +hi def link phpParent Delimiter +hi def link phpBrackets Delimiter +hi def link phpIdentifierConst Delimiter +hi def link phpParentError Error +hi def link phpOctalError Error +hi def link phpInterpSimpleError Error +hi def link phpInterpBogusDollarCurley Error +hi def link phpInterpDollarCurly1 Error +hi def link phpInterpDollarCurly2 Error +hi def link phpInterpSimpleBracketsInner String +hi def link phpInterpSimpleCurly Delimiter +hi def link phpInterpVarname Identifier +hi def link phpTodo Todo +hi def link phpDocTodo Todo +hi def link phpMemberSelector Structure +if exists("php_oldStyle") + hi def phpIntVar guifg=Red ctermfg=DarkRed + hi def phpEnvVar guifg=Red ctermfg=DarkRed + hi def phpOperator guifg=SeaGreen ctermfg=DarkGreen + hi def phpVarSelector guifg=SeaGreen ctermfg=DarkGreen + hi def phpRelation guifg=SeaGreen ctermfg=DarkGreen + hi def phpIdentifier guifg=DarkGray ctermfg=Brown + hi def phpIdentifierSimply guifg=DarkGray ctermfg=Brown +else + hi def link phpIntVar Identifier + hi def link phpEnvVar Identifier + hi def link phpOperator Operator + hi def link phpVarSelector Operator + hi def link phpRelation Operator + hi def link phpIdentifier Identifier + hi def link phpIdentifierSimply Identifier endif + let b:current_syntax = "php" if main_syntax == 'php' diff --git a/runtime/syntax/pic.vim b/runtime/syntax/pic.vim index adc964ea96..bcb01f4dbd 100644 --- a/runtime/syntax/pic.vim +++ b/runtime/syntax/pic.vim @@ -5,11 +5,8 @@ " URL: http://galeb.etf.bg.ac.yu/~alexa/vim/syntax/pic.vim " Revision: 1.01 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -91,36 +88,26 @@ syn match picDirective "#\=DEFINE" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_pic16f84_syntax_inits") - if version < 508 - let did_pic16f84_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink picTodo Todo - HiLink picComment Comment - HiLink picDirective Statement - HiLink picLabel Label - HiLink picString String - - "HiLink picOpcode Keyword - "HiLink picRegister Structure - "HiLink picRegisterPart Special - - HiLink picASCII String - HiLink picBinary Number - HiLink picDecimal Number - HiLink picHexadecimal Number - HiLink picOctal Number - - HiLink picIdentifier Identifier - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link picTodo Todo +hi def link picComment Comment +hi def link picDirective Statement +hi def link picLabel Label +hi def link picString String + +"hi def link picOpcode Keyword +"hi def link picRegister Structure +"hi def link picRegisterPart Special + +hi def link picASCII String +hi def link picBinary Number +hi def link picDecimal Number +hi def link picHexadecimal Number +hi def link picOctal Number + +hi def link picIdentifier Identifier + let b:current_syntax = "pic" diff --git a/runtime/syntax/pike.vim b/runtime/syntax/pike.vim index efbafd5d82..ccd122c46c 100644 --- a/runtime/syntax/pike.vim +++ b/runtime/syntax/pike.vim @@ -3,11 +3,8 @@ " Maintainer: Francesco Chemolli <kinkie@kame.usr.dsi.unimi.it> " Last Change: 2001 May 10 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -104,51 +101,41 @@ syn match pikeBitField ";\s*\I\i*\s*:\s*[1-9]"me=e-1 syn sync ccomment pikeComment minlines=10 " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_pike_syntax_inits") - if version < 508 - let did_pike_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink pikeLabel Label - HiLink pikeUserLabel Label - HiLink pikeConditional Conditional - HiLink pikeRepeat Repeat - HiLink pikeCharacter Character - HiLink pikeSpecialCharacter pikeSpecial - HiLink pikeNumber Number - HiLink pikeFloat Float - HiLink pikeOctalError pikeError - HiLink pikeParenError pikeError - HiLink pikeInParen pikeError - HiLink pikeCommentError pikeError - HiLink pikeOperator Operator - HiLink pikeInclude Include - HiLink pikePreProc PreProc - HiLink pikeDefine Macro - HiLink pikeIncluded pikeString - HiLink pikeError Error - HiLink pikeStatement Statement - HiLink pikePreCondit PreCondit - HiLink pikeType Type - HiLink pikeCommentError pikeError - HiLink pikeCommentString pikeString - HiLink pikeComment2String pikeString - HiLink pikeCommentSkip pikeComment - HiLink pikeString String - HiLink pikeComment Comment - HiLink pikeSpecial SpecialChar - HiLink pikeTodo Todo - HiLink pikeException pikeStatement - HiLink pikeCompoundType Constant - "HiLink pikeIdentifier Identifier - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link pikeLabel Label +hi def link pikeUserLabel Label +hi def link pikeConditional Conditional +hi def link pikeRepeat Repeat +hi def link pikeCharacter Character +hi def link pikeSpecialCharacter pikeSpecial +hi def link pikeNumber Number +hi def link pikeFloat Float +hi def link pikeOctalError pikeError +hi def link pikeParenError pikeError +hi def link pikeInParen pikeError +hi def link pikeCommentError pikeError +hi def link pikeOperator Operator +hi def link pikeInclude Include +hi def link pikePreProc PreProc +hi def link pikeDefine Macro +hi def link pikeIncluded pikeString +hi def link pikeError Error +hi def link pikeStatement Statement +hi def link pikePreCondit PreCondit +hi def link pikeType Type +hi def link pikeCommentError pikeError +hi def link pikeCommentString pikeString +hi def link pikeComment2String pikeString +hi def link pikeCommentSkip pikeComment +hi def link pikeString String +hi def link pikeComment Comment +hi def link pikeSpecial SpecialChar +hi def link pikeTodo Todo +hi def link pikeException pikeStatement +hi def link pikeCompoundType Constant +"hi def link pikeIdentifier Identifier + let b:current_syntax = "pike" diff --git a/runtime/syntax/pilrc.vim b/runtime/syntax/pilrc.vim index 86d5611589..f0e5f9bbc7 100644 --- a/runtime/syntax/pilrc.vim +++ b/runtime/syntax/pilrc.vim @@ -4,10 +4,8 @@ " Last change: 2003 May 11 " Available on: http://www.schau.com/pilrcvim/pilrc.vim -" Remove any old syntax -if version < 600 - syn clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -119,30 +117,20 @@ syn region pilrcInclude start="public class" end="}" syn sync ccomment pilrcComment -if version >= 508 || !exists("did_pilrc_syntax_inits") - if version < 508 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - let did_pilrc_syntax_inits = 1 - - " The default methods for highlighting - HiLink pilrcKeyword Statement - HiLink pilrcType Type - HiLink pilrcError Error - HiLink pilrcCountry SpecialChar - HiLink pilrcLanguage SpecialChar - HiLink pilrcString SpecialChar - HiLink pilrcNumber Number - HiLink pilrcComment Comment - HiLink pilrcConstant Constant - HiLink pilrcFunction Function - HiLink pilrcInclude SpecialChar - HiLink pilrcIdentifier Number - - delcommand HiLink -endif + +" The default methods for highlighting +hi def link pilrcKeyword Statement +hi def link pilrcType Type +hi def link pilrcError Error +hi def link pilrcCountry SpecialChar +hi def link pilrcLanguage SpecialChar +hi def link pilrcString SpecialChar +hi def link pilrcNumber Number +hi def link pilrcComment Comment +hi def link pilrcConstant Constant +hi def link pilrcFunction Function +hi def link pilrcInclude SpecialChar +hi def link pilrcIdentifier Number + let b:current_syntax = "pilrc" diff --git a/runtime/syntax/pine.vim b/runtime/syntax/pine.vim index 4c64b9bbc7..aadf50be15 100644 --- a/runtime/syntax/pine.vim +++ b/runtime/syntax/pine.vim @@ -3,19 +3,12 @@ " Maintainer: David Pascoe <pascoedj@spamcop.net> " Last Change: Thu Feb 27 10:18:48 WST 2003, update for pine 4.53 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif -if version >= 600 - setlocal iskeyword=@,48-57,_,128-167,224-235,- -else - set iskeyword=@,48-57,_,128-167,224-235,- -endif +setlocal iskeyword=@,48-57,_,128-167,224-235,- syn keyword pineConfig addrbook-sort-rule syn keyword pineConfig address-book @@ -351,21 +344,11 @@ syn keyword pineOption vertical-folder-list syn match pineComment "^#.*$" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_pine_syn_inits") - if version < 508 - let did_pine_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink pineConfig Type - HiLink pineComment Comment - HiLink pineOption Macro - delcommand HiLink -endif +hi def link pineConfig Type +hi def link pineComment Comment +hi def link pineOption Macro let b:current_syntax = "pine" diff --git a/runtime/syntax/pli.vim b/runtime/syntax/pli.vim index f8d7e51cf3..a274cc40bf 100644 --- a/runtime/syntax/pli.vim +++ b/runtime/syntax/pli.vim @@ -3,9 +3,8 @@ " using keywords from http://www.kednos.com/pli/docs/reference_manual/6291pro_contents.html " 2012-11-13 Alan Thompson -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -222,57 +221,46 @@ endif syn sync minlines=10 maxlines=100 " Define the default highlighting. -" For version 5.x and earlier, only when not done already. -" For version 5.8 and later, only when and item doesn't have highlighting -" yet. -if version >= 508 || !exists("did_pl1_syn_inits") - if version < 508 - let did_pl1_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when and item doesn't have highlighting yet. - HiLink pl1Attribute Macro - HiLink pl1BlockError Error - HiLink pl1BooleanLiteral Boolean - HiLink pl1CharLiteral Character - HiLink pl1Comment Comment - HiLink pl1CommentL Comment - HiLink pl1Conditional Conditional - HiLink pl1Error Error - HiLink pl1ErrInBracket Error - HiLink pl1ErrInBlock Error - HiLink pl1ErrInParen Error - HiLink pl1Exception Function - HiLink pl1FloatLiteral Float - HiLink pl1Function Function - HiLink pl1Garbage Error - HiLink pl1HostIdentifier Label - HiLink pl1Identifier Normal - HiLink pl1IntLiteral Number - HiLink pl1Operator Operator - HiLink pl1Paren Normal - HiLink pl1ParenError Error - HiLink pl1SpaceError Error - HiLink pl1Pseudo PreProc - HiLink pl1PreProc PreProc - HiLink pl1PreProcSym PreProc - HiLink pl1Keyword Keyword - HiLink pl1Other Keyword - HiLink pl1Repeat Repeat - HiLink pl1Statement Keyword - HiLink pl1Storage StorageClass - HiLink pl1StringError Error - HiLink pl1StringLiteral String - HiLink pl1CommentString String - HiLink pl1Comment2String String - HiLink pl1Symbol Normal - HiLink pl1Trigger Function - HiLink pl1TypeAttribute StorageClass - HiLink pl1Todo Todo +hi def link pl1Attribute Macro +hi def link pl1BlockError Error +hi def link pl1BooleanLiteral Boolean +hi def link pl1CharLiteral Character +hi def link pl1Comment Comment +hi def link pl1CommentL Comment +hi def link pl1Conditional Conditional +hi def link pl1Error Error +hi def link pl1ErrInBracket Error +hi def link pl1ErrInBlock Error +hi def link pl1ErrInParen Error +hi def link pl1Exception Function +hi def link pl1FloatLiteral Float +hi def link pl1Function Function +hi def link pl1Garbage Error +hi def link pl1HostIdentifier Label +hi def link pl1Identifier Normal +hi def link pl1IntLiteral Number +hi def link pl1Operator Operator +hi def link pl1Paren Normal +hi def link pl1ParenError Error +hi def link pl1SpaceError Error +hi def link pl1Pseudo PreProc +hi def link pl1PreProc PreProc +hi def link pl1PreProcSym PreProc +hi def link pl1Keyword Keyword +hi def link pl1Other Keyword +hi def link pl1Repeat Repeat +hi def link pl1Statement Keyword +hi def link pl1Storage StorageClass +hi def link pl1StringError Error +hi def link pl1StringLiteral String +hi def link pl1CommentString String +hi def link pl1Comment2String String +hi def link pl1Symbol Normal +hi def link pl1Trigger Function +hi def link pl1TypeAttribute StorageClass +hi def link pl1Todo Todo - delcommand HiLink -endif let b:current_syntax = "pl1" diff --git a/runtime/syntax/plm.vim b/runtime/syntax/plm.vim index bf7c32fd1c..c6618adacb 100644 --- a/runtime/syntax/plm.vim +++ b/runtime/syntax/plm.vim @@ -3,11 +3,8 @@ " Maintainer: Philippe Coulonges <cphil@cphil.net> " Last change: 2003 May 11 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -103,43 +100,33 @@ syn keyword plm386w16BuiltIn SETD SKIPD SKIPRD syn sync lines=50 " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_plm_syntax_inits") - if version < 508 - let did_plm_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - " The default methods for highlighting. Can be overridden later -" HiLink plmLabel Label -" HiLink plmConditional Conditional -" HiLink plmRepeat Repeat - HiLink plmTodo Todo - HiLink plmNumber Number - HiLink plmOperator Operator - HiLink plmDelimiter Operator - "HiLink plmShowTab Error - "HiLink plmShowTabc Error - HiLink plmIdentifier Identifier - HiLink plmBuiltIn Statement - HiLink plm286BuiltIn Statement - HiLink plm386BuiltIn Statement - HiLink plm386w16BuiltIn Statement - HiLink plmReserved Statement - HiLink plm386Reserved Statement - HiLink plmPreProc PreProc - HiLink plmCommentError plmError - HiLink plmCommentString plmString - HiLink plmComment2String plmString - HiLink plmCommentSkip plmComment - HiLink plmString String - HiLink plmComment Comment - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +" The default methods for highlighting. Can be overridden later +" hi def link plmLabel Label +" hi def link plmConditional Conditional +" hi def link plmRepeat Repeat +hi def link plmTodo Todo +hi def link plmNumber Number +hi def link plmOperator Operator +hi def link plmDelimiter Operator +"hi def link plmShowTab Error +"hi def link plmShowTabc Error +hi def link plmIdentifier Identifier +hi def link plmBuiltIn Statement +hi def link plm286BuiltIn Statement +hi def link plm386BuiltIn Statement +hi def link plm386w16BuiltIn Statement +hi def link plmReserved Statement +hi def link plm386Reserved Statement +hi def link plmPreProc PreProc +hi def link plmCommentError plmError +hi def link plmCommentString plmString +hi def link plmComment2String plmString +hi def link plmCommentSkip plmComment +hi def link plmString String +hi def link plmComment Comment + let b:current_syntax = "plm" diff --git a/runtime/syntax/plp.vim b/runtime/syntax/plp.vim index f59702d3b5..48dc4b249e 100644 --- a/runtime/syntax/plp.vim +++ b/runtime/syntax/plp.vim @@ -7,11 +7,8 @@ " Add to filetype.vim the following line (without quote sign): " au BufNewFile,BufRead *.plp setf plp -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -19,14 +16,9 @@ if !exists("main_syntax") let main_syntax = 'perlscript' endif -if version < 600 - so <sfile>:p:h/html.vim - syn include @PLPperl <sfile>:p:h/perl.vim -else - runtime! syntax/html.vim - unlet b:current_syntax - syn include @PLPperl syntax/perl.vim -endif +runtime! syntax/html.vim +unlet b:current_syntax +syn include @PLPperl syntax/perl.vim syn cluster htmlPreproc add=PLPperlblock diff --git a/runtime/syntax/plsql.vim b/runtime/syntax/plsql.vim index 6e513660f8..1868c9cb16 100644 --- a/runtime/syntax/plsql.vim +++ b/runtime/syntax/plsql.vim @@ -9,11 +9,8 @@ " Austin Ziegler (austin at halostatue dot ca) " Added 8i+ features. " -" For version 5.x, clear all syntax items. -" For version 6.x, quit when a syntax file was already loaded. -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -223,54 +220,44 @@ endif syn sync minlines=10 maxlines=100 " Define the default highlighting. -" For version 5.x and earlier, only when not done already. -" For version 5.8 and later, only when an item doesn't have highlighting yet. -if version >= 508 || !exists("did_plsql_syn_inits") - if version < 508 - let did_plsql_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet. - HiLink plsqlAttribute Macro - HiLink plsqlBlockError Error - HiLink plsqlBooleanLiteral Boolean - HiLink plsqlCharLiteral Character - HiLink plsqlComment Comment - HiLink plsqlCommentL Comment - HiLink plsqlConditional Conditional - HiLink plsqlError Error - HiLink plsqlErrInBracket Error - HiLink plsqlErrInBlock Error - HiLink plsqlErrInParen Error - HiLink plsqlException Function - HiLink plsqlFloatLiteral Float - HiLink plsqlFunction Function - HiLink plsqlGarbage Error - HiLink plsqlHostIdentifier Label - HiLink plsqlIdentifier Normal - HiLink plsqlIntLiteral Number - HiLink plsqlOperator Operator - HiLink plsqlParen Normal - HiLink plsqlParenError Error - HiLink plsqlSpaceError Error - HiLink plsqlPseudo PreProc - HiLink plsqlKeyword Keyword - HiLink plsqlRepeat Repeat - HiLink plsqlStorage StorageClass - HiLink plsqlSQLKeyword Function - HiLink plsqlStringError Error - HiLink plsqlStringLiteral String - HiLink plsqlCommentString String - HiLink plsqlComment2String String - HiLink plsqlSymbol Normal - HiLink plsqlTrigger Function - HiLink plsqlTypeAttribute StorageClass - HiLink plsqlTodo Todo +hi def link plsqlAttribute Macro +hi def link plsqlBlockError Error +hi def link plsqlBooleanLiteral Boolean +hi def link plsqlCharLiteral Character +hi def link plsqlComment Comment +hi def link plsqlCommentL Comment +hi def link plsqlConditional Conditional +hi def link plsqlError Error +hi def link plsqlErrInBracket Error +hi def link plsqlErrInBlock Error +hi def link plsqlErrInParen Error +hi def link plsqlException Function +hi def link plsqlFloatLiteral Float +hi def link plsqlFunction Function +hi def link plsqlGarbage Error +hi def link plsqlHostIdentifier Label +hi def link plsqlIdentifier Normal +hi def link plsqlIntLiteral Number +hi def link plsqlOperator Operator +hi def link plsqlParen Normal +hi def link plsqlParenError Error +hi def link plsqlSpaceError Error +hi def link plsqlPseudo PreProc +hi def link plsqlKeyword Keyword +hi def link plsqlRepeat Repeat +hi def link plsqlStorage StorageClass +hi def link plsqlSQLKeyword Function +hi def link plsqlStringError Error +hi def link plsqlStringLiteral String +hi def link plsqlCommentString String +hi def link plsqlComment2String String +hi def link plsqlSymbol Normal +hi def link plsqlTrigger Function +hi def link plsqlTypeAttribute StorageClass +hi def link plsqlTodo Todo - delcommand HiLink -endif let b:current_syntax = "plsql" diff --git a/runtime/syntax/po.vim b/runtime/syntax/po.vim index 2ab13ac0b1..15d09b18bd 100644 --- a/runtime/syntax/po.vim +++ b/runtime/syntax/po.vim @@ -6,11 +6,8 @@ " Leonardo Fontenelle (Spell checking) " Nam SungHyun <namsh@kldp.org> (Original maintainer) -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif let s:keepcpo= &cpo @@ -82,61 +79,51 @@ syn match poAcceleratorStr contained "[^&_~][&_~]\(\a\|\d\)[^:]"ms=s+1,me=e-1 c syn match poVariable contained "%\d" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_po_syn_inits") - if version < 508 - let did_po_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink poCommentSources PreProc - HiLink poComment Comment - 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 - HiLink poStatementMsgstr Statement - HiLink poStatementMsgidplural Statement - HiLink poStatementMsgCTxt Statement - HiLink poPluralCaseN Constant - - HiLink poStringCTxt Comment - HiLink poStringID String - HiLink poStringSTR String - HiLink poCommentKDE Comment - HiLink poCommentKDEError Error - HiLink poPluralKDE Comment - HiLink poPluralKDEError Error - HiLink poHeaderItem Identifier - HiLink poHeaderUndefined Todo - HiLink poKDEdesktopFile Identifier - - HiLink poHtml Identifier - HiLink poHtmlNot String - HiLink poHtmlTranslatables String - HiLink poLineBreak String - - HiLink poFormat poSpecial - HiLink poSpecial Special - HiLink poAcceleratorId Special - HiLink poAcceleratorStr Special - HiLink poVariable Special - - HiLink poMsguniqError Special - HiLink poMsguniqErrorMarkers Comment - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link poCommentSources PreProc +hi def link poComment Comment +hi def link poCommentAutomatic Comment +hi def link poCommentTranslator Comment +hi def link poCommentFlags Special +hi def link poCommentDiff Comment +hi def link poCopyrightUnset Todo +hi def link poFlagFuzzy Todo +hi def link poDiffOld Todo +hi def link poDiffNew Special +hi def link poObsolete Comment + +hi def link poStatementMsgid Statement +hi def link poStatementMsgstr Statement +hi def link poStatementMsgidplural Statement +hi def link poStatementMsgCTxt Statement +hi def link poPluralCaseN Constant + +hi def link poStringCTxt Comment +hi def link poStringID String +hi def link poStringSTR String +hi def link poCommentKDE Comment +hi def link poCommentKDEError Error +hi def link poPluralKDE Comment +hi def link poPluralKDEError Error +hi def link poHeaderItem Identifier +hi def link poHeaderUndefined Todo +hi def link poKDEdesktopFile Identifier + +hi def link poHtml Identifier +hi def link poHtmlNot String +hi def link poHtmlTranslatables String +hi def link poLineBreak String + +hi def link poFormat poSpecial +hi def link poSpecial Special +hi def link poAcceleratorId Special +hi def link poAcceleratorStr Special +hi def link poVariable Special + +hi def link poMsguniqError Special +hi def link poMsguniqErrorMarkers Comment + let b:current_syntax = "po" diff --git a/runtime/syntax/pod.vim b/runtime/syntax/pod.vim index b9f2e0854f..7c65a8433f 100644 --- a/runtime/syntax/pod.vim +++ b/runtime/syntax/pod.vim @@ -19,11 +19,8 @@ " Remove any old syntax stuff hanging around (this is suppressed " automatically by ":syn include" if necessary). -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -67,28 +64,18 @@ syn match podEscape "\I\i*>"me=e-1 contained contains=@NoSpell syn match podEscape2 "\d\+>"me=e-1 contained contains=@NoSpell " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_pod_syntax_inits") - if version < 508 - let did_pod_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet + +hi def link podCommand Statement +hi def link podCmdText String +hi def link podOverIndent Number +hi def link podForKeywd Identifier +hi def link podFormat Identifier +hi def link podVerbatimLine PreProc +hi def link podSpecial Identifier +hi def link podEscape String +hi def link podEscape2 Number - HiLink podCommand Statement - HiLink podCmdText String - HiLink podOverIndent Number - HiLink podForKeywd Identifier - HiLink podFormat Identifier - HiLink podVerbatimLine PreProc - HiLink podSpecial Identifier - HiLink podEscape String - HiLink podEscape2 Number - - delcommand HiLink -endif if exists("perl_pod_spellcheck_headings") " Spell-check headings diff --git a/runtime/syntax/postscr.vim b/runtime/syntax/postscr.vim index 8b051d33b3..d5dc9a22d6 100644 --- a/runtime/syntax/postscr.vim +++ b/runtime/syntax/postscr.vim @@ -13,11 +13,8 @@ " postscr_encodings - highlight encoding names (there are a lot) " postscr_andornot_binary - highlight and, or, and not as binary operators (not logical) " -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -25,11 +22,7 @@ endif syn case match " Keyword characters - all 7-bit ASCII bar PS delimiters and ws -if version >= 600 - setlocal iskeyword=33-127,^(,^),^<,^>,^[,^],^{,^},^/,^% -else - set iskeyword=33-127,^(,^),^<,^>,^[,^],^{,^},^/,^% -endif +setlocal iskeyword=33-127,^(,^),^<,^>,^[,^],^{,^},^/,^% " Yer trusty old TODO highlghter! syn keyword postscrTodo contained TODO @@ -730,68 +723,58 @@ if exists("postscr_ghostscript") endif " GhostScript highlighting " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_postscr_syntax_inits") - if version < 508 - let did_postscr_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink postscrComment Comment - - HiLink postscrConstant Constant - HiLink postscrString String - HiLink postscrASCIIString postscrString - HiLink postscrHexString postscrString - HiLink postscrASCII85String postscrString - HiLink postscrNumber Number - HiLink postscrInteger postscrNumber - HiLink postscrHex postscrNumber - HiLink postscrRadix postscrNumber - HiLink postscrFloat Float - HiLink postscrBoolean Boolean - - HiLink postscrIdentifier Identifier - HiLink postscrProcedure Function - - HiLink postscrName Statement - HiLink postscrConditional Conditional - HiLink postscrRepeat Repeat - HiLink postscrL2Repeat postscrRepeat - HiLink postscrOperator Operator - HiLink postscrL1Operator postscrOperator - HiLink postscrL2Operator postscrOperator - HiLink postscrL3Operator postscrOperator - HiLink postscrMathOperator postscrOperator - HiLink postscrLogicalOperator postscrOperator - HiLink postscrBinaryOperator postscrOperator - - HiLink postscrDSCComment SpecialComment - HiLink postscrSpecialChar SpecialChar - - HiLink postscrTodo Todo - - HiLink postscrError Error - HiLink postscrSpecialCharError postscrError - HiLink postscrASCII85CharError postscrError - HiLink postscrHexCharError postscrError - HiLink postscrASCIIStringError postscrError - HiLink postscrIdentifierError postscrError - - if exists("postscr_ghostscript") - HiLink postscrGSOperator postscrOperator - HiLink postscrGSMathOperator postscrMathOperator - else - HiLink postscrGSOperator postscrError - HiLink postscrGSMathOperator postscrError - endif - - delcommand HiLink +" Only when an item doesn't have highlighting yet + +hi def link postscrComment Comment + +hi def link postscrConstant Constant +hi def link postscrString String +hi def link postscrASCIIString postscrString +hi def link postscrHexString postscrString +hi def link postscrASCII85String postscrString +hi def link postscrNumber Number +hi def link postscrInteger postscrNumber +hi def link postscrHex postscrNumber +hi def link postscrRadix postscrNumber +hi def link postscrFloat Float +hi def link postscrBoolean Boolean + +hi def link postscrIdentifier Identifier +hi def link postscrProcedure Function + +hi def link postscrName Statement +hi def link postscrConditional Conditional +hi def link postscrRepeat Repeat +hi def link postscrL2Repeat postscrRepeat +hi def link postscrOperator Operator +hi def link postscrL1Operator postscrOperator +hi def link postscrL2Operator postscrOperator +hi def link postscrL3Operator postscrOperator +hi def link postscrMathOperator postscrOperator +hi def link postscrLogicalOperator postscrOperator +hi def link postscrBinaryOperator postscrOperator + +hi def link postscrDSCComment SpecialComment +hi def link postscrSpecialChar SpecialChar + +hi def link postscrTodo Todo + +hi def link postscrError Error +hi def link postscrSpecialCharError postscrError +hi def link postscrASCII85CharError postscrError +hi def link postscrHexCharError postscrError +hi def link postscrASCIIStringError postscrError +hi def link postscrIdentifierError postscrError + +if exists("postscr_ghostscript") +hi def link postscrGSOperator postscrOperator +hi def link postscrGSMathOperator postscrMathOperator +else +hi def link postscrGSOperator postscrError +hi def link postscrGSMathOperator postscrError endif + let b:current_syntax = "postscr" " vim: ts=8 diff --git a/runtime/syntax/pov.vim b/runtime/syntax/pov.vim index 4c1fd9624a..8595bcb151 100644 --- a/runtime/syntax/pov.vim +++ b/runtime/syntax/pov.vim @@ -5,14 +5,8 @@ " Required Vim Version: 6.0 " Setup -if version >= 600 - " Quit when a syntax file was already loaded - if exists("b:current_syntax") - finish - endif -else - " Croak when an old Vim is sourcing us. - echo "Sorry, but this syntax file relies on Vim 6 features. Either upgrade Vim or use a version of " . expand("<sfile>:t:r") . " syntax file appropriate for Vim " . version/100 . "." . version %100 . "." +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif diff --git a/runtime/syntax/povini.vim b/runtime/syntax/povini.vim index 726fe1fc74..ac1f87875e 100644 --- a/runtime/syntax/povini.vim +++ b/runtime/syntax/povini.vim @@ -5,14 +5,8 @@ " Required Vim Version: 6.0 " Setup -if version >= 600 - " Quit when a syntax file was already loaded - if exists("b:current_syntax") - finish - endif -else - " Croak when an old Vim is sourcing us. - echo "Sorry, but this syntax file relies on Vim 6 features. Either upgrade Vim or usea version of " . expand("<sfile>:t:r") . " syntax file appropriate for Vim " . version/100 . "." . version %100 . "." +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif diff --git a/runtime/syntax/ppd.vim b/runtime/syntax/ppd.vim index 192f70c05d..da67e1f39f 100644 --- a/runtime/syntax/ppd.vim +++ b/runtime/syntax/ppd.vim @@ -3,11 +3,8 @@ " Maintainer: Bjoern Jacke <bjacke@suse.de> " Last Change: 2001-10-06 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -21,27 +18,17 @@ syn match ppdGUIText "/.*:" syn match ppdContraints "^*UIConstraints:" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_ahdl_syn_inits") - if version < 508 - let did_ahdl_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - - HiLink ppdComment Comment - HiLink ppdDefine Statement - HiLink ppdUI Function - HiLink ppdUIGroup Function - HiLink ppdDef String - HiLink ppdGUIText Type - HiLink ppdContraints Special - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + + +hi def link ppdComment Comment +hi def link ppdDefine Statement +hi def link ppdUI Function +hi def link ppdUIGroup Function +hi def link ppdDef String +hi def link ppdGUIText Type +hi def link ppdContraints Special + let b:current_syntax = "ppd" diff --git a/runtime/syntax/ppwiz.vim b/runtime/syntax/ppwiz.vim index d3d7b3a17a..514f8f36cc 100644 --- a/runtime/syntax/ppwiz.vim +++ b/runtime/syntax/ppwiz.vim @@ -6,11 +6,8 @@ " Filename: ppwiz.vim " Remove old syntax stuff -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -63,33 +60,23 @@ syn match ppwizInteger "\d\+" contained syn cluster ppwizArgVal add=ppwizString,ppwizInteger " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_ppwiz_syn_inits") - if version < 508 - let did_ppwiz_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink ppwizSpecial Special - HiLink ppwizEqual ppwizSpecial - HiLink ppwizOperator ppwizSpecial - HiLink ppwizComment Comment - HiLink ppwizDef PreProc - HiLink ppwizMacro Statement - HiLink ppwizArg Identifier - HiLink ppwizStdVar Identifier - HiLink ppwizRexxVar Identifier - HiLink ppwizString Constant - HiLink ppwizInteger Constant - HiLink ppwizCont ppwizSpecial - HiLink ppwizError Error - HiLink ppwizHTML Type +hi def link ppwizSpecial Special +hi def link ppwizEqual ppwizSpecial +hi def link ppwizOperator ppwizSpecial +hi def link ppwizComment Comment +hi def link ppwizDef PreProc +hi def link ppwizMacro Statement +hi def link ppwizArg Identifier +hi def link ppwizStdVar Identifier +hi def link ppwizRexxVar Identifier +hi def link ppwizString Constant +hi def link ppwizInteger Constant +hi def link ppwizCont ppwizSpecial +hi def link ppwizError Error +hi def link ppwizHTML Type - delcommand HiLink -endif let b:current_syntax = "ppwiz" diff --git a/runtime/syntax/prescribe.vim b/runtime/syntax/prescribe.vim index d89ee35253..cd5ddbeedd 100644 --- a/runtime/syntax/prescribe.vim +++ b/runtime/syntax/prescribe.vim @@ -4,11 +4,8 @@ " URL: http://www.hampft.de/vim/syntax/prescribe.vim " Last Change: 2005 Mar 04 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -44,25 +41,15 @@ syn region prescribeString start=+'+ end=+'+ skip=+\\'+ syn region prescribeComment start=+CMNT+ end=+;+ " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_prescribe_syn_inits") - if version < 508 - let did_prescribe_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink prescribeSpecial PreProc - HiLink prescribeStatement Statement - HiLink prescribeNumber Number - HiLink prescribeCSETArg String - HiLink prescribeFRPOArg String - HiLink prescribeComment Comment +hi def link prescribeSpecial PreProc +hi def link prescribeStatement Statement +hi def link prescribeNumber Number +hi def link prescribeCSETArg String +hi def link prescribeFRPOArg String +hi def link prescribeComment Comment - delcommand HiLink -endif let b:current_syntax = "prescribe" diff --git a/runtime/syntax/procmail.vim b/runtime/syntax/procmail.vim index c2ffa39883..93f50fe9ef 100644 --- a/runtime/syntax/procmail.vim +++ b/runtime/syntax/procmail.vim @@ -4,11 +4,8 @@ " Last Change: 2003 Aug 14 " Author: Sonia Heimann -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -33,34 +30,24 @@ syn region procmailActionNested start=+^\s*{+ end=+^\s*}+ contains=procmailRecip syn region procmailRecipe start=+^\s*:.*$+ end=+^\s*\($\|}\)+me=e-1 contains=procmailComment,procmailCondition,procmailActionFolder,procmailActionVariable,procmailActionForward,procmailActionPipe,procmailActionNested,procmailVarDeclRegion " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_procmail_syntax_inits") - if version < 508 - let did_procmail_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink procmailComment Comment - HiLink procmailTodo Todo +hi def link procmailComment Comment +hi def link procmailTodo Todo - HiLink procmailRecipe Statement - "HiLink procmailCondition Statement +hi def link procmailRecipe Statement +"hi def link procmailCondition Statement - HiLink procmailActionFolder procmailAction - HiLink procmailActionVariable procmailAction - HiLink procmailActionForward procmailAction - HiLink procmailActionPipe procmailAction - HiLink procmailAction Function - HiLink procmailVar Identifier - HiLink procmailVarDecl Identifier +hi def link procmailActionFolder procmailAction +hi def link procmailActionVariable procmailAction +hi def link procmailActionForward procmailAction +hi def link procmailActionPipe procmailAction +hi def link procmailAction Function +hi def link procmailVar Identifier +hi def link procmailVarDecl Identifier - HiLink procmailString String +hi def link procmailString String - delcommand HiLink -endif let b:current_syntax = "procmail" diff --git a/runtime/syntax/progress.vim b/runtime/syntax/progress.vim index 85a54a6505..5e7cfef299 100644 --- a/runtime/syntax/progress.vim +++ b/runtime/syntax/progress.vim @@ -11,22 +11,15 @@ " Version: 13 " Last Change: Nov 11 2012 -" For version 5.x: Clear all syntax item -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif let s:cpo_save = &cpo set cpo&vim -if version >= 600 - setlocal iskeyword=@,48-57,_,-,!,#,$,% -else - set iskeyword=@,48-57,_,-,!,#,$,% -endif +setlocal iskeyword=@,48-57,_,-,!,#,$,% " The Progress editor doesn't cope with tabs very well. set expandtab @@ -282,44 +275,34 @@ syn keyword ProgressType char[acter] int[eger] int64 dec[imal] log[ical] da[te] syn sync lines=800 " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_progress_syntax_inits") - if version < 508 - let did_progress_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - " The default methods for highlighting. Can be overridden later. - HiLink ProgressByte Number - HiLink ProgressCase Repeat - HiLink ProgressComment Comment - HiLink ProgressConditional Conditional - HiLink ProgressDebug Debug - HiLink ProgressDo Repeat - HiLink ProgressEndError Error - HiLink ProgressFor Repeat - HiLink ProgressFunction Procedure - HiLink ProgressIdentifier Identifier - HiLink ProgressInclude Include - HiLink ProgressMatrixDelimiter Identifier - HiLink ProgressNumber Number - HiLink ProgressOperator Operator - HiLink ProgressPreProc PreProc - HiLink ProgressProcedure Procedure - HiLink ProgressQuote Delimiter - HiLink ProgressRepeat Repeat - HiLink ProgressReserved Statement - HiLink ProgressSpaceError Error - HiLink ProgressString String - HiLink ProgressTodo Todo - HiLink ProgressType Statement - HiLink ProgressShowTab Error +" The default methods for highlighting. Can be overridden later. +hi def link ProgressByte Number +hi def link ProgressCase Repeat +hi def link ProgressComment Comment +hi def link ProgressConditional Conditional +hi def link ProgressDebug Debug +hi def link ProgressDo Repeat +hi def link ProgressEndError Error +hi def link ProgressFor Repeat +hi def link ProgressFunction Procedure +hi def link ProgressIdentifier Identifier +hi def link ProgressInclude Include +hi def link ProgressMatrixDelimiter Identifier +hi def link ProgressNumber Number +hi def link ProgressOperator Operator +hi def link ProgressPreProc PreProc +hi def link ProgressProcedure Procedure +hi def link ProgressQuote Delimiter +hi def link ProgressRepeat Repeat +hi def link ProgressReserved Statement +hi def link ProgressSpaceError Error +hi def link ProgressString String +hi def link ProgressTodo Todo +hi def link ProgressType Statement +hi def link ProgressShowTab Error - delcommand HiLink -endif let b:current_syntax = "progress" diff --git a/runtime/syntax/prolog.vim b/runtime/syntax/prolog.vim index f5f0e673ec..3b09bb3548 100644 --- a/runtime/syntax/prolog.vim +++ b/runtime/syntax/prolog.vim @@ -1,17 +1,17 @@ " Vim syntax file " Language: PROLOG -" Maintainers: Thomas Koehler <jean-luc@picard.franken.de> -" Last Change: 2013 May 23 +" Maintainer: Thomas Koehler <jean-luc@picard.franken.de> +" Please be aware: I'm often slow to answer email due to a high +" non-computer related workload (sometimes 4-8 weeks) +" Last Change: 2016 September 6 " URL: http://gott-gehabt.de/800_wer_wir_sind/thomas/Homepage/Computer/vim/syntax/prolog.vim " There are two sets of highlighting in here: " If the "prolog_highlighting_clean" variable exists, it is rather sparse. " Otherwise you get more highlighting. -" Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -78,46 +78,36 @@ syn sync maxlines=50 " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_prolog_syn_inits") - if version < 508 - let did_prolog_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - " The default highlighting. - HiLink prologComment Comment - HiLink prologCComment Comment - HiLink prologCharCode Special - - if exists ("prolog_highlighting_clean") - - HiLink prologKeyword Statement - HiLink prologClauseHead Statement - HiLink prologClause Normal - - else - - HiLink prologKeyword Keyword - HiLink prologClauseHead Constant - HiLink prologClause Normal - HiLink prologQuestion PreProc - HiLink prologSpecialCharacter Special - HiLink prologNumber Number - HiLink prologAsIs Normal - HiLink prologCommentError Error - HiLink prologAtom String - HiLink prologString String - HiLink prologOperator Operator - - endif - - delcommand HiLink +" Only when an item doesn't have highlighting yet + +" The default highlighting. +hi def link prologComment Comment +hi def link prologCComment Comment +hi def link prologCharCode Special + +if exists ("prolog_highlighting_clean") + +hi def link prologKeyword Statement +hi def link prologClauseHead Statement +hi def link prologClause Normal + +else + +hi def link prologKeyword Keyword +hi def link prologClauseHead Constant +hi def link prologClause Normal +hi def link prologQuestion PreProc +hi def link prologSpecialCharacter Special +hi def link prologNumber Number +hi def link prologAsIs Normal +hi def link prologCommentError Error +hi def link prologAtom String +hi def link prologString String +hi def link prologOperator Operator + endif + let b:current_syntax = "prolog" " vim: ts=8 diff --git a/runtime/syntax/promela.vim b/runtime/syntax/promela.vim index e812bc2749..add4514561 100644 --- a/runtime/syntax/promela.vim +++ b/runtime/syntax/promela.vim @@ -5,11 +5,8 @@ " Last Change: Thu Aug 7 21:22:48 CEST 2008 " Version: 0.5 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif diff --git a/runtime/syntax/proto.vim b/runtime/syntax/proto.vim index 4d6a77e84a..4615e0ca0e 100644 --- a/runtime/syntax/proto.vim +++ b/runtime/syntax/proto.vim @@ -22,9 +22,8 @@ " " http://code.google.com/p/protobuf/ -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif diff --git a/runtime/syntax/psf.vim b/runtime/syntax/psf.vim index 2b376f94cc..0971fe96bf 100644 --- a/runtime/syntax/psf.vim +++ b/runtime/syntax/psf.vim @@ -4,10 +4,8 @@ " Maintainer: Rex Barzee <rex_barzee@hp.com> " Last change: 25 Apr 2001 -if version < 600 - " Remove any old syntax stuff hanging around - syn clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -73,27 +71,17 @@ syn match psfComment "#.*$" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_psf_syntax_inits") - if version < 508 - let did_psf_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink psfObject Statement - HiLink psfAttrib Type - HiLink psfQuotString String - HiLink psfObjTag Identifier - HiLink psfAttAbbrev PreProc - HiLink psfObjTags Identifier - - HiLink psfComment Comment - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link psfObject Statement +hi def link psfAttrib Type +hi def link psfQuotString String +hi def link psfObjTag Identifier +hi def link psfAttAbbrev PreProc +hi def link psfObjTags Identifier + +hi def link psfComment Comment + " Long descriptions and copyrights confuse the syntax highlighting, so " force vim to backup at least 100 lines before the top visible line diff --git a/runtime/syntax/ptcap.vim b/runtime/syntax/ptcap.vim index 45590cf61b..1ebeb5227b 100644 --- a/runtime/syntax/ptcap.vim +++ b/runtime/syntax/ptcap.vim @@ -4,11 +4,8 @@ " URL: http://folk.uio.no/hakonrk/vim/syntax/ptcap.vim " Last Change: 2001 May 15 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syn clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -73,34 +70,25 @@ syn region ptcapField start=":" skip="[^\\]\(\\\\\)*\\$" end="[^\\]\(\\\\\)* syn region ptcapString matchgroup=ptcapOperator start="=" skip="[^\\]\(\\\\\)*\\:" matchgroup=ptcapDelimiter end=":"me=e-1 matchgroup=NONE end="[^\\]\(\\\\\)*[^\\]$" end="^$" contains=ptcapEscapedChar,ptcapLineCont keepend contained syn region ptcapComment start="^\s*#" end="$" contains=ptcapLeadBlank -if version >= 508 || !exists("did_ptcap_syntax_inits") - if version < 508 - let did_ptcap_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink ptcapComment Comment - HiLink ptcapDelimiter Delimiter - " The highlighting of "ptcapEntry" should always be overridden by - " its contents, so I use Todo highlighting to indicate that there - " is work to be done with the syntax file if you can see it :-) - HiLink ptcapEntry Todo - HiLink ptcapError Error - HiLink ptcapEscapedChar SpecialChar - HiLink ptcapField Type - HiLink ptcapLeadBlank NONE - HiLink ptcapLineCont Special - HiLink ptcapNames Label - HiLink ptcapNumber NONE - HiLink ptcapNumberError Error - HiLink ptcapOperator Operator - HiLink ptcapSpecialCap Type - HiLink ptcapString NONE - - delcommand HiLink -endif + +hi def link ptcapComment Comment +hi def link ptcapDelimiter Delimiter +" The highlighting of "ptcapEntry" should always be overridden by +" its contents, so I use Todo highlighting to indicate that there +" is work to be done with the syntax file if you can see it :-) +hi def link ptcapEntry Todo +hi def link ptcapError Error +hi def link ptcapEscapedChar SpecialChar +hi def link ptcapField Type +hi def link ptcapLeadBlank NONE +hi def link ptcapLineCont Special +hi def link ptcapNames Label +hi def link ptcapNumber NONE +hi def link ptcapNumberError Error +hi def link ptcapOperator Operator +hi def link ptcapSpecialCap Type +hi def link ptcapString NONE + let b:current_syntax = "ptcap" diff --git a/runtime/syntax/purifylog.vim b/runtime/syntax/purifylog.vim index 8bcfb4b006..2143d9fe28 100644 --- a/runtime/syntax/purifylog.vim +++ b/runtime/syntax/purifylog.vim @@ -3,11 +3,8 @@ " Maintainer: Gautam H. Mudunuri <gmudunur@informatica.com> " Last Change: 2003 May 11 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -57,62 +54,52 @@ syn match purifyLogZPR "^ZPR:.*$" syn match purifyLogZPW "^ZPW:.*$" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_purifyLog_syntax_inits") - if version < 508 - let did_purifyLog_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink purifyLogFIU purifyLogInformational - HiLink purifyLogMAF purifyLogInformational - HiLink purifyLogMIU purifyLogInformational - HiLink purifyLogSIG purifyLogInformational - HiLink purifyLogWPF purifyLogInformational - HiLink purifyLogWPM purifyLogInformational - HiLink purifyLogWPN purifyLogInformational - HiLink purifyLogWPR purifyLogInformational - HiLink purifyLogWPW purifyLogInformational - HiLink purifyLogWPX purifyLogInformational +hi def link purifyLogFIU purifyLogInformational +hi def link purifyLogMAF purifyLogInformational +hi def link purifyLogMIU purifyLogInformational +hi def link purifyLogSIG purifyLogInformational +hi def link purifyLogWPF purifyLogInformational +hi def link purifyLogWPM purifyLogInformational +hi def link purifyLogWPN purifyLogInformational +hi def link purifyLogWPR purifyLogInformational +hi def link purifyLogWPW purifyLogInformational +hi def link purifyLogWPX purifyLogInformational - HiLink purifyLogABR purifyLogWarning - HiLink purifyLogBSR purifyLogWarning - HiLink purifyLogBSW purifyLogWarning - HiLink purifyLogFMR purifyLogWarning - HiLink purifyLogMLK purifyLogWarning - HiLink purifyLogMSE purifyLogWarning - HiLink purifyLogPAR purifyLogWarning - HiLink purifyLogPLK purifyLogWarning - HiLink purifyLogSBR purifyLogWarning - HiLink purifyLogSOF purifyLogWarning - HiLink purifyLogUMC purifyLogWarning - HiLink purifyLogUMR purifyLogWarning +hi def link purifyLogABR purifyLogWarning +hi def link purifyLogBSR purifyLogWarning +hi def link purifyLogBSW purifyLogWarning +hi def link purifyLogFMR purifyLogWarning +hi def link purifyLogMLK purifyLogWarning +hi def link purifyLogMSE purifyLogWarning +hi def link purifyLogPAR purifyLogWarning +hi def link purifyLogPLK purifyLogWarning +hi def link purifyLogSBR purifyLogWarning +hi def link purifyLogSOF purifyLogWarning +hi def link purifyLogUMC purifyLogWarning +hi def link purifyLogUMR purifyLogWarning - HiLink purifyLogABW purifyLogCorrupting - HiLink purifyLogBRK purifyLogCorrupting - HiLink purifyLogFMW purifyLogCorrupting - HiLink purifyLogFNH purifyLogCorrupting - HiLink purifyLogFUM purifyLogCorrupting - HiLink purifyLogMRE purifyLogCorrupting - HiLink purifyLogSBW purifyLogCorrupting +hi def link purifyLogABW purifyLogCorrupting +hi def link purifyLogBRK purifyLogCorrupting +hi def link purifyLogFMW purifyLogCorrupting +hi def link purifyLogFNH purifyLogCorrupting +hi def link purifyLogFUM purifyLogCorrupting +hi def link purifyLogMRE purifyLogCorrupting +hi def link purifyLogSBW purifyLogCorrupting - HiLink purifyLogCOR purifyLogFatal - HiLink purifyLogNPR purifyLogFatal - HiLink purifyLogNPW purifyLogFatal - HiLink purifyLogZPR purifyLogFatal - HiLink purifyLogZPW purifyLogFatal +hi def link purifyLogCOR purifyLogFatal +hi def link purifyLogNPR purifyLogFatal +hi def link purifyLogNPW purifyLogFatal +hi def link purifyLogZPR purifyLogFatal +hi def link purifyLogZPW purifyLogFatal - HiLink purifyLogHeader Comment - HiLink purifyLogInformational PreProc - HiLink purifyLogWarning Type - HiLink purifyLogCorrupting Error - HiLink purifyLogFatal Error +hi def link purifyLogHeader Comment +hi def link purifyLogInformational PreProc +hi def link purifyLogWarning Type +hi def link purifyLogCorrupting Error +hi def link purifyLogFatal Error - delcommand HiLink -endif let b:current_syntax = "purifylog" diff --git a/runtime/syntax/pyrex.vim b/runtime/syntax/pyrex.vim index 7dc9b955b0..b860658975 100644 --- a/runtime/syntax/pyrex.vim +++ b/runtime/syntax/pyrex.vim @@ -4,21 +4,14 @@ " URL: http://marcobari.altervista.org/pyrex_vim.html " Last Change: 2009 Nov 09 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif " Read the Python syntax to start with -if version < 600 - so <sfile>:p:h/python.vim -else - runtime! syntax/python.vim - unlet b:current_syntax -endif +runtime! syntax/python.vim +unlet b:current_syntax " Pyrex extentions syn keyword pyrexStatement cdef typedef ctypedef sizeof @@ -44,24 +37,15 @@ syn match pythonInclude "from" syn match pyrexForFrom "\(for[^:]*\)\@<=from" " Default highlighting -if version >= 508 || !exists("did_pyrex_syntax_inits") - if version < 508 - let did_pyrex_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - HiLink pyrexStatement Statement - HiLink pyrexType Type - HiLink pyrexStructure Structure - HiLink pyrexInclude PreCondit - HiLink pyrexAccess pyrexStatement - if exists("python_highlight_builtins") || exists("pyrex_highlight_builtins") - HiLink pyrexBuiltin Function - endif - HiLink pyrexForFrom Statement - - delcommand HiLink +hi def link pyrexStatement Statement +hi def link pyrexType Type +hi def link pyrexStructure Structure +hi def link pyrexInclude PreCondit +hi def link pyrexAccess pyrexStatement +if exists("python_highlight_builtins") || exists("pyrex_highlight_builtins") +hi def link pyrexBuiltin Function endif +hi def link pyrexForFrom Statement + let b:current_syntax = "pyrex" diff --git a/runtime/syntax/python.vim b/runtime/syntax/python.vim index fa42b3e2d2..5aec2fe3d2 100644 --- a/runtime/syntax/python.vim +++ b/runtime/syntax/python.vim @@ -1,7 +1,7 @@ " Vim syntax file " Language: Python " Maintainer: Zvezdan Petkovic <zpetkovic@acm.org> -" Last Change: 2016 Jul 21 +" Last Change: 2016 Oct 29 " Credits: Neil Schemenauer <nas@python.ca> " Dmitry Vasiliev " @@ -36,11 +36,8 @@ " let python_highlight_all = 1 " -" For version 5.x: Clear all syntax items. -" For version 6.x: Quit when a syntax file was already loaded. -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded. +if exists("b:current_syntax") finish endif @@ -49,6 +46,29 @@ endif let s:cpo_save = &cpo set cpo&vim +if exists("python_no_doctest_highlight") + let python_no_doctest_code_highlight = 1 +endif + +if exists("python_highlight_all") + if exists("python_no_builtin_highlight") + unlet python_no_builtin_highlight + endif + if exists("python_no_doctest_code_highlight") + unlet python_no_doctest_code_highlight + endif + if exists("python_no_doctest_highlight") + unlet python_no_doctest_highlight + endif + if exists("python_no_exception_highlight") + unlet python_no_exception_highlight + endif + if exists("python_no_number_highlight") + unlet python_no_number_highlight + endif + let python_space_error_highlight = 1 +endif + " Keep Python keywords in alphabetical order inside groups for easy " comparison with the table in the 'Python Language Reference' " https://docs.python.org/2/reference/lexical_analysis.html#keywords, @@ -84,14 +104,31 @@ syn keyword pythonInclude from import syn keyword pythonAsync async await " Decorators (new in Python 2.4) -syn match pythonDecorator "@" display nextgroup=pythonFunction skipwhite -" The zero-length non-grouping match before the function name is -" extremely important in pythonFunction. Without it, everything is -" interpreted as a function inside the contained environment of -" doctests. " A dot must be allowed because of @MyClass.myfunc decorators. -syn match pythonFunction - \ "\%(\%(def\s\|class\s\|@\)\s*\)\@<=\h\%(\w\|\.\)*" contained +syn match pythonDecorator "@" display contained +syn match pythonDecoratorName "@\s*\h\%(\w\|\.\)*" display contains=pythonDecorator + +" Python 3.5 introduced the use of the same symbol for matrix multiplication: +" https://www.python.org/dev/peps/pep-0465/. We now have to exclude the +" symbol from highlighting when used in that context. +" Single line multiplication. +syn match pythonMatrixMultiply + \ "\%(\w\|[])]\)\s*@" + \ contains=ALLBUT,pythonDecoratorName,pythonDecorator,pythonFunction,pythonDoctestValue + \ transparent +" Multiplication continued on the next line after backslash. +syn match pythonMatrixMultiply + \ "[^\\]\\\s*\n\%(\s*\.\.\.\s\)\=\s\+@" + \ contains=ALLBUT,pythonDecoratorName,pythonDecorator,pythonFunction,pythonDoctestValue + \ transparent +" Multiplication in a parenthesized expression over multiple lines with @ at +" the start of each continued line; very similar to decorators and complex. +syn match pythonMatrixMultiply + \ "^\s*\%(\%(>>>\|\.\.\.\)\s\+\)\=\zs\%(\h\|\%(\h\|[[(]\).\{-}\%(\w\|[])]\)\)\s*\n\%(\s*\.\.\.\s\)\=\s\+@\%(.\{-}\n\%(\s*\.\.\.\s\)\=\s\+@\)*" + \ contains=ALLBUT,pythonDecoratorName,pythonDecorator,pythonFunction,pythonDoctestValue + \ transparent + +syn match pythonFunction "\h\w*" display contained syn match pythonComment "#.*$" contains=pythonTodo,@Spell syn keyword pythonTodo FIXME NOTE NOTES TODO XXX contained @@ -118,25 +155,6 @@ syn match pythonEscape "\%(\\u\x\{4}\|\\U\x\{8}\)" contained syn match pythonEscape "\\N{\a\+\%(\s\a\+\)*}" contained syn match pythonEscape "\\$" -if exists("python_highlight_all") - if exists("python_no_builtin_highlight") - unlet python_no_builtin_highlight - endif - if exists("python_no_doctest_code_highlight") - unlet python_no_doctest_code_highlight - endif - if exists("python_no_doctest_highlight") - unlet python_no_doctest_highlight - endif - if exists("python_no_exception_highlight") - unlet python_no_exception_highlight - endif - if exists("python_no_number_highlight") - unlet python_no_number_highlight - endif - let python_space_error_highlight = 1 -endif - " It is very important to understand all details before changing the " regular expressions below or their order. " The word boundaries are *not* the floating-point number boundaries @@ -200,7 +218,9 @@ if !exists("python_no_builtin_highlight") " non-essential built-in functions; Python 2 only syn keyword pythonBuiltin apply buffer coerce intern " avoid highlighting attributes as builtins - syn match pythonAttribute /\.\h\w*/hs=s+1 contains=ALLBUT,pythonBuiltin transparent + syn match pythonAttribute /\.\h\w*/hs=s+1 + \ contains=ALLBUT,pythonBuiltin,pythonFunction,pythonAsync + \ transparent endif " From the 'Python Library Reference' class hierarchy at the bottom. @@ -262,7 +282,7 @@ if !exists("python_no_doctest_highlight") if !exists("python_no_doctest_code_highlight") syn region pythonDoctest \ start="^\s*>>>\s" end="^\s*$" - \ contained contains=ALLBUT,pythonDoctest,@Spell + \ contained contains=ALLBUT,pythonDoctest,pythonFunction,@Spell syn region pythonDoctestValue \ start=+^\s*\%(>>>\s\|\.\.\.\s\|"""\|'''\)\@!\S\++ end="$" \ contained @@ -274,51 +294,41 @@ if !exists("python_no_doctest_highlight") endif " Sync at the beginning of class, function, or method definition. -syn sync match pythonSync grouphere NONE "^\s*\%(def\|class\)\s\+\h\w*\s*(" - -if version >= 508 || !exists("did_python_syn_inits") - if version <= 508 - let did_python_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +syn sync match pythonSync grouphere NONE "^\%(def\|class\)\s\+\h\w*\s*[(:]" - " The default highlight links. Can be overridden later. - HiLink pythonStatement Statement - HiLink pythonConditional Conditional - HiLink pythonRepeat Repeat - HiLink pythonOperator Operator - HiLink pythonException Exception - HiLink pythonInclude Include - HiLink pythonAsync Statement - HiLink pythonDecorator Define - HiLink pythonFunction Function - HiLink pythonComment Comment - HiLink pythonTodo Todo - HiLink pythonString String - HiLink pythonRawString String - HiLink pythonQuotes String - HiLink pythonTripleQuotes pythonQuotes - HiLink pythonEscape Special - if !exists("python_no_number_highlight") - HiLink pythonNumber Number - endif - if !exists("python_no_builtin_highlight") - HiLink pythonBuiltin Function - endif - if !exists("python_no_exception_highlight") - HiLink pythonExceptions Structure - endif - if exists("python_space_error_highlight") - HiLink pythonSpaceError Error - endif - if !exists("python_no_doctest_highlight") - HiLink pythonDoctest Special - HiLink pythonDoctestValue Define - endif - - delcommand HiLink +" The default highlight links. Can be overridden later. +hi def link pythonStatement Statement +hi def link pythonConditional Conditional +hi def link pythonRepeat Repeat +hi def link pythonOperator Operator +hi def link pythonException Exception +hi def link pythonInclude Include +hi def link pythonAsync Statement +hi def link pythonDecorator Define +hi def link pythonDecoratorName Function +hi def link pythonFunction Function +hi def link pythonComment Comment +hi def link pythonTodo Todo +hi def link pythonString String +hi def link pythonRawString String +hi def link pythonQuotes String +hi def link pythonTripleQuotes pythonQuotes +hi def link pythonEscape Special +if !exists("python_no_number_highlight") + hi def link pythonNumber Number +endif +if !exists("python_no_builtin_highlight") + hi def link pythonBuiltin Function +endif +if !exists("python_no_exception_highlight") + hi def link pythonExceptions Structure +endif +if exists("python_space_error_highlight") + hi def link pythonSpaceError Error +endif +if !exists("python_no_doctest_highlight") + hi def link pythonDoctest Special + hi def link pythonDoctestValue Define endif let b:current_syntax = "python" diff --git a/runtime/syntax/r.vim b/runtime/syntax/r.vim index d96bf96acb..30a5b23f84 100644 --- a/runtime/syntax/r.vim +++ b/runtime/syntax/r.vim @@ -5,7 +5,7 @@ " Tom Payne <tom@tompayne.org> " Contributor: Johannes Ranke <jranke@uni-bremen.de> " Homepage: https://github.com/jalvesaq/R-Vim-runtime -" Last Change: Thu Mar 10, 2016 12:26PM +" Last Change: Thu Aug 25, 2016 08:52PM " Filenames: *.R *.r *.Rhistory *.Rt " " NOTE: The highlighting of R functions is defined in @@ -26,7 +26,7 @@ if exists("b:current_syntax") finish endif -setlocal iskeyword=@,48-57,_,. +syn iskeyword @,48-57,_,. if exists("g:r_syntax_folding") && g:r_syntax_folding setlocal foldmethod=syntax @@ -174,8 +174,6 @@ endif if g:R_hi_fun " Nvim-R: runtime R/functions.vim - " Vim-R-plugin: - runtime r-plugin/functions.vim endif syn match rDollar display contained "\$" diff --git a/runtime/syntax/radiance.vim b/runtime/syntax/radiance.vim index 461b708f0e..c49e339a28 100644 --- a/runtime/syntax/radiance.vim +++ b/runtime/syntax/radiance.vim @@ -18,20 +18,13 @@ " comments, external command names and the null-modifier "void". -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif " all printing characters except '#' and '!' are valid in names. -if version >= 600 - setlocal iskeyword=\",$-~ -else - set iskeyword=\",$-~ -endif +setlocal iskeyword=\",$-~ " The null-modifier syn keyword radianceKeyword void @@ -130,29 +123,19 @@ syn keyword radianceTodo contained TODO XXX syn match radianceComment "#.*$" contains=radianceTodo " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_radiance_syn_inits") - if version < 508 - let did_radiance_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - HiLink radianceKeyword Keyword - HiLink radianceExtraType Type - HiLink radianceSurfType Type - HiLink radianceLightType Type - HiLink radianceMatType Type - HiLink radiancePatType Type - HiLink radianceTexType Type - HiLink radianceMixType Type - HiLink radianceComment Comment - HiLink radianceCommand Function - HiLink radianceID String - HiLink radianceTodo Todo - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet +hi def link radianceKeyword Keyword +hi def link radianceExtraType Type +hi def link radianceSurfType Type +hi def link radianceLightType Type +hi def link radianceMatType Type +hi def link radiancePatType Type +hi def link radianceTexType Type +hi def link radianceMixType Type +hi def link radianceComment Comment +hi def link radianceCommand Function +hi def link radianceID String +hi def link radianceTodo Todo let b:current_syntax = "radiance" diff --git a/runtime/syntax/ratpoison.vim b/runtime/syntax/ratpoison.vim index 9fc59bec0d..af8676c43d 100644 --- a/runtime/syntax/ratpoison.vim +++ b/runtime/syntax/ratpoison.vim @@ -5,11 +5,8 @@ " Last Change: 2011 Apr 11 " Previous Maintainer: Doug Kearns <djkea2@gus.gscit.monash.edu.au> -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -247,33 +244,23 @@ syn match ratpoisonVoidCommand "^\s*\zsvsplit\ze\s*$" syn match ratpoisonVoidCommand "^\s*\zswindows\ze\s*$" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_ratpoison_syn_inits") - if version < 508 - let did_ratpoison_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink ratpoisonBooleanArg Boolean - HiLink ratpoisonCommandArg Keyword - HiLink ratpoisonComment Comment - HiLink ratpoisonDefCommand Identifier - HiLink ratpoisonGravityArg Constant - HiLink ratpoisonKeySeqArg Special - HiLink ratpoisonNumberArg Number - HiLink ratpoisonSetArg Keyword - HiLink ratpoisonStringCommand Identifier - HiLink ratpoisonTodo Todo - HiLink ratpoisonVoidCommand Identifier - HiLink ratpoisonWinFmtArg Special - HiLink ratpoisonWinNameArg Constant - HiLink ratpoisonWinListArg Constant +hi def link ratpoisonBooleanArg Boolean +hi def link ratpoisonCommandArg Keyword +hi def link ratpoisonComment Comment +hi def link ratpoisonDefCommand Identifier +hi def link ratpoisonGravityArg Constant +hi def link ratpoisonKeySeqArg Special +hi def link ratpoisonNumberArg Number +hi def link ratpoisonSetArg Keyword +hi def link ratpoisonStringCommand Identifier +hi def link ratpoisonTodo Todo +hi def link ratpoisonVoidCommand Identifier +hi def link ratpoisonWinFmtArg Special +hi def link ratpoisonWinNameArg Constant +hi def link ratpoisonWinListArg Constant - delcommand HiLink -endif let b:current_syntax = "ratpoison" diff --git a/runtime/syntax/rc.vim b/runtime/syntax/rc.vim index a2d5824d3e..4c6856bc83 100644 --- a/runtime/syntax/rc.vim +++ b/runtime/syntax/rc.vim @@ -8,11 +8,8 @@ " This file is based on the c.vim -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -148,55 +145,45 @@ syn region rcPreProc start="^\s*#\s*\(pragma\>\|line\>\|warning\>\|warn\>\|erro syn sync ccomment rcComment minlines=10 " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_rc_syntax_inits") - if version < 508 - let did_rc_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink rcCharacter Character - HiLink rcSpecialCharacter rcSpecial - HiLink rcNumber Number - HiLink rcFloat Float - HiLink rcOctalError rcError - HiLink rcParenError rcError - HiLink rcInParen rcError - HiLink rcCommentError rcError - HiLink rcInclude Include - HiLink rcPreProc PreProc - HiLink rcDefine Macro - HiLink rcIncluded rcString - HiLink rcError Error - HiLink rcPreCondit PreCondit - HiLink rcCommentString rcString - HiLink rcComment2String rcString - HiLink rcCommentSkip rcComment - HiLink rcString String - HiLink rcComment Comment - HiLink rcSpecial SpecialChar - HiLink rcTodo Todo - - HiLink rcAttribute rcCommonAttribute - HiLink rcStdId rcStatement - HiLink rcStatement Statement - - " Default color overrides - hi def rcLanguage term=reverse ctermbg=Red ctermfg=Yellow guibg=Red guifg=Yellow - hi def rcMainObject term=underline ctermfg=Blue guifg=Blue - hi def rcSubObject ctermfg=Green guifg=Green - hi def rcCaptionParam term=underline ctermfg=DarkGreen guifg=Green - hi def rcParam ctermfg=DarkGreen guifg=DarkGreen - hi def rcStatement ctermfg=DarkGreen guifg=DarkGreen - hi def rcCommonAttribute ctermfg=Brown guifg=Brown - - "HiLink rcIdentifier Identifier - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link rcCharacter Character +hi def link rcSpecialCharacter rcSpecial +hi def link rcNumber Number +hi def link rcFloat Float +hi def link rcOctalError rcError +hi def link rcParenError rcError +hi def link rcInParen rcError +hi def link rcCommentError rcError +hi def link rcInclude Include +hi def link rcPreProc PreProc +hi def link rcDefine Macro +hi def link rcIncluded rcString +hi def link rcError Error +hi def link rcPreCondit PreCondit +hi def link rcCommentString rcString +hi def link rcComment2String rcString +hi def link rcCommentSkip rcComment +hi def link rcString String +hi def link rcComment Comment +hi def link rcSpecial SpecialChar +hi def link rcTodo Todo + +hi def link rcAttribute rcCommonAttribute +hi def link rcStdId rcStatement +hi def link rcStatement Statement + +" Default color overrides +hi def rcLanguage term=reverse ctermbg=Red ctermfg=Yellow guibg=Red guifg=Yellow +hi def rcMainObject term=underline ctermfg=Blue guifg=Blue +hi def rcSubObject ctermfg=Green guifg=Green +hi def rcCaptionParam term=underline ctermfg=DarkGreen guifg=Green +hi def rcParam ctermfg=DarkGreen guifg=DarkGreen +hi def rcStatement ctermfg=DarkGreen guifg=DarkGreen +hi def rcCommonAttribute ctermfg=Brown guifg=Brown + +"hi def link rcIdentifier Identifier + let b:current_syntax = "rc" diff --git a/runtime/syntax/rcs.vim b/runtime/syntax/rcs.vim index e45d5fdbb6..5a34802ada 100644 --- a/runtime/syntax/rcs.vim +++ b/runtime/syntax/rcs.vim @@ -9,11 +9,8 @@ " Options: " rcs_folding = 1 For folding strings -" For version 5.x: Clear all syntax items. -" For version 6.x: Quit when a syntax file was already loaded. -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded. +if exists("b:current_syntax") finish endif @@ -52,25 +49,15 @@ else endif " Define the default highlighting. -" For version 5.7 and earlier: only when not done already. -" For version 5.8 and later: only when an item doesn't have highlighting yet. -if version >= 508 || !exists("did_rcs_syn_inits") - if version <= 508 - let did_rcs_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet. - HiLink rcsKeyword Keyword - HiLink rcsNumber Identifier - HiLink rcsString String - HiLink rcsTextStr String - HiLink rcsSpecial Special - HiLink rcsDiffLines Special - HiLink rcsEOFError Error +hi def link rcsKeyword Keyword +hi def link rcsNumber Identifier +hi def link rcsString String +hi def link rcsTextStr String +hi def link rcsSpecial Special +hi def link rcsDiffLines Special +hi def link rcsEOFError Error - delcommand HiLink -endif let b:current_syntax = "rcs" diff --git a/runtime/syntax/rcslog.vim b/runtime/syntax/rcslog.vim index acacfa124b..18f4593c77 100644 --- a/runtime/syntax/rcslog.vim +++ b/runtime/syntax/rcslog.vim @@ -3,11 +3,8 @@ " Maintainer: Joe Karthauser <joe@freebsd.org> " Last Change: 2001 May 09 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -16,22 +13,12 @@ syn match rcslogFile "^RCS file:.*" syn match rcslogDate "^date: .*$" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_rcslog_syntax_inits") - if version < 508 - let did_rcslog_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink rcslogFile Type - HiLink rcslogRevision Constant - HiLink rcslogDate Identifier +hi def link rcslogFile Type +hi def link rcslogRevision Constant +hi def link rcslogDate Identifier - delcommand HiLink -endif let b:current_syntax = "rcslog" diff --git a/runtime/syntax/rebol.vim b/runtime/syntax/rebol.vim index e6395758f3..a5d50c4ab1 100644 --- a/runtime/syntax/rebol.vim +++ b/runtime/syntax/rebol.vim @@ -6,11 +6,8 @@ " URL: http://www.eandem.co.uk/mrw/vim " -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -18,11 +15,7 @@ endif syn case ignore " As per current users documentation -if version < 600 - set isk=@,48-57,?,!,.,',+,-,*,&,\|,=,_,~ -else - setlocal isk=@,48-57,?,!,.,',+,-,*,&,\|,=,_,~ -endif +setlocal isk=@,48-57,?,!,.,',+,-,*,&,\|,=,_,~ " Yer TODO highlighter syn keyword rebolTodo contained TODO @@ -145,65 +138,55 @@ syn keyword rebolConstant none " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_rebol_syntax_inits") - if version < 508 - let did_rebol_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet + +hi def link rebolTodo Todo + +hi def link rebolStatement Statement +hi def link rebolLabel Label +hi def link rebolConditional Conditional +hi def link rebolRepeat Repeat + +hi def link rebolOperator Operator +hi def link rebolLogicOperator rebolOperator +hi def link rebolLogicFunction rebolLogicOperator +hi def link rebolMathOperator rebolOperator +hi def link rebolMathFunction rebolMathOperator +hi def link rebolBinaryOperator rebolOperator +hi def link rebolBinaryFunction rebolBinaryOperator + +hi def link rebolType Type +hi def link rebolTypeFunction rebolOperator + +hi def link rebolWord Identifier +hi def link rebolWordPath rebolWord +hi def link rebolFunction Function + +hi def link rebolCharacter Character +hi def link rebolSpecialCharacter SpecialChar +hi def link rebolString String + +hi def link rebolNumber Number +hi def link rebolInteger rebolNumber +hi def link rebolDecimal rebolNumber +hi def link rebolTime rebolNumber +hi def link rebolDate rebolNumber +hi def link rebolMoney rebolNumber +hi def link rebolBinary rebolNumber +hi def link rebolEmail rebolString +hi def link rebolFile rebolString +hi def link rebolURL rebolString +hi def link rebolIssue rebolNumber +hi def link rebolTuple rebolNumber +hi def link rebolFloat Float +hi def link rebolBoolean Boolean + +hi def link rebolConstant Constant + +hi def link rebolComment Comment + +hi def link rebolError Error - HiLink rebolTodo Todo - - HiLink rebolStatement Statement - HiLink rebolLabel Label - HiLink rebolConditional Conditional - HiLink rebolRepeat Repeat - - HiLink rebolOperator Operator - HiLink rebolLogicOperator rebolOperator - HiLink rebolLogicFunction rebolLogicOperator - HiLink rebolMathOperator rebolOperator - HiLink rebolMathFunction rebolMathOperator - HiLink rebolBinaryOperator rebolOperator - HiLink rebolBinaryFunction rebolBinaryOperator - - HiLink rebolType Type - HiLink rebolTypeFunction rebolOperator - - HiLink rebolWord Identifier - HiLink rebolWordPath rebolWord - HiLink rebolFunction Function - - HiLink rebolCharacter Character - HiLink rebolSpecialCharacter SpecialChar - HiLink rebolString String - - HiLink rebolNumber Number - HiLink rebolInteger rebolNumber - HiLink rebolDecimal rebolNumber - HiLink rebolTime rebolNumber - HiLink rebolDate rebolNumber - HiLink rebolMoney rebolNumber - HiLink rebolBinary rebolNumber - HiLink rebolEmail rebolString - HiLink rebolFile rebolString - HiLink rebolURL rebolString - HiLink rebolIssue rebolNumber - HiLink rebolTuple rebolNumber - HiLink rebolFloat Float - HiLink rebolBoolean Boolean - - HiLink rebolConstant Constant - - HiLink rebolComment Comment - - HiLink rebolError Error - - delcommand HiLink -endif if exists("my_rebol_file") if file_readable(expand(my_rebol_file)) diff --git a/runtime/syntax/redif.vim b/runtime/syntax/redif.vim index 1a44a9f479..725067fd32 100644 --- a/runtime/syntax/redif.vim +++ b/runtime/syntax/redif.vim @@ -7,10 +7,8 @@ " File Extension: rdf " Note: The ReDIF format is used by RePEc. -" To be compatible with Vim 5.8 use: -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif diff --git a/runtime/syntax/registry.vim b/runtime/syntax/registry.vim index 4524247a08..67b5e49bcb 100644 --- a/runtime/syntax/registry.vim +++ b/runtime/syntax/registry.vim @@ -6,11 +6,8 @@ " Included patch from Alexander A. Ulitin " clear any unwanted syntax defs -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -85,29 +82,20 @@ syn match registryHex "^\s*\([0-9a-fA-F]\{2},\)\{0,999}\([0-9a-fA-F]\{2}\|\\\)$ " Dword (32 bits) syn match registryDword "dword:[0-9a-fA-F]\{8}$" contains=registrySpecial -if version >= 508 || !exists("did_registry_syntax_inits") - if version < 508 - let did_registry_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif " The default methods for highlighting. Can be overridden later - HiLink registryComment Comment - HiLink registryHead Constant - HiLink registryHKEY Constant - HiLink registryPath Special - HiLink registryRemove PreProc - HiLink registryGUID Identifier - HiLink registrySpecial Special - HiLink registrySubKey Type - HiLink registryString String - HiLink registryHex Number - HiLink registryDword Number - - delcommand HiLink -endif +hi def link registryComment Comment +hi def link registryHead Constant +hi def link registryHKEY Constant +hi def link registryPath Special +hi def link registryRemove PreProc +hi def link registryGUID Identifier +hi def link registrySpecial Special +hi def link registrySubKey Type +hi def link registryString String +hi def link registryHex Number +hi def link registryDword Number + let b:current_syntax = "registry" diff --git a/runtime/syntax/remind.vim b/runtime/syntax/remind.vim index 98064e043a..9e7ff22e14 100644 --- a/runtime/syntax/remind.vim +++ b/runtime/syntax/remind.vim @@ -13,9 +13,8 @@ " version 0.7: updated email and link " version 0.6: added THROUGH keyword (courtesy of Ben Orchard) -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -48,35 +47,26 @@ syn match remindDates "'[0-9]\{4}[/-][0-9]\{1,2}[/-][0-9]\{1,2}\(@[0-9]\{1,2}[: syn match remindWarning display excludenl "\S\s\+$"ms=s+1 -if version >= 508 || !exists("did_remind_syn_inits") - if version < 508 - let did_remind_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - HiLink remindCommands Function - HiLink remindExpiry Repeat - HiLink remindTag Label - HiLink remindTimed Statement - HiLink remindMove Statement - HiLink remindSpecial Include - HiLink remindRun Function - HiLink remindConditional Conditional - HiLink remindComment Comment - HiLink remindTimes String - HiLink remindString String - HiLink remindDebug Debug - HiLink remindVar Identifier - HiLink remindSubst Constant - HiLink remindAdvanceNumber Number - HiLink remindDateSeparators Comment - HiLink remindDates String - HiLink remindWarning Error +hi def link remindCommands Function +hi def link remindExpiry Repeat +hi def link remindTag Label +hi def link remindTimed Statement +hi def link remindMove Statement +hi def link remindSpecial Include +hi def link remindRun Function +hi def link remindConditional Conditional +hi def link remindComment Comment +hi def link remindTimes String +hi def link remindString String +hi def link remindDebug Debug +hi def link remindVar Identifier +hi def link remindSubst Constant +hi def link remindAdvanceNumber Number +hi def link remindDateSeparators Comment +hi def link remindDates String +hi def link remindWarning Error - delcommand HiLink -endif let b:current_syntax = "remind" diff --git a/runtime/syntax/resolv.vim b/runtime/syntax/resolv.vim index 06d6885c1c..a879116a5f 100644 --- a/runtime/syntax/resolv.vim +++ b/runtime/syntax/resolv.vim @@ -9,9 +9,8 @@ " David Necas (Yeti) <yeti@physics.muni.cz> " Stefano Zacchiroli <zack@debian.org> -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -50,38 +49,29 @@ syn match resolvOption /\<\%(ndots\|timeout\|attempts\):\d\+\>/ contained contai " Additional errors syn match resolvError /^search .\{257,}/ -if version >= 508 || !exists("did_config_syntax_inits") - if version < 508 - let did_config_syntax_inits = 1 - command! -nargs=+ HiLink hi link <args> - else - command! -nargs=+ HiLink hi def link <args> - endif - - HiLink resolvIP Number - HiLink resolvIPNetmask Number - HiLink resolvHostname String - HiLink resolvOption String - - HiLink resolvIPNameserver Number - HiLink resolvHostnameSearch String - HiLink resolvIPNetmaskSortList Number - - HiLink resolvNameServer Identifier - HiLink resolvLwserver Identifier - HiLink resolvDomain Identifier - HiLink resolvSearch Identifier - HiLink resolvSortList Identifier - HiLink resolvOptions Identifier - - HiLink resolvComment Comment - HiLink resolvOperator Operator - HiLink resolvError Error - HiLink resolvIPError Error - HiLink resolvIPSpecial Special - - delcommand HiLink -endif + +hi def link resolvIP Number +hi def link resolvIPNetmask Number +hi def link resolvHostname String +hi def link resolvOption String + +hi def link resolvIPNameserver Number +hi def link resolvHostnameSearch String +hi def link resolvIPNetmaskSortList Number + +hi def link resolvNameServer Identifier +hi def link resolvLwserver Identifier +hi def link resolvDomain Identifier +hi def link resolvSearch Identifier +hi def link resolvSortList Identifier +hi def link resolvOptions Identifier + +hi def link resolvComment Comment +hi def link resolvOperator Operator +hi def link resolvError Error +hi def link resolvIPError Error +hi def link resolvIPSpecial Special + let b:current_syntax = "resolv" diff --git a/runtime/syntax/reva.vim b/runtime/syntax/reva.vim index 03dfc9d4c3..f605992190 100644 --- a/runtime/syntax/reva.vim +++ b/runtime/syntax/reva.vim @@ -7,13 +7,8 @@ " Filetypes: *.rf *.frt " NOTE: You should also have the ftplugin/reva.vim file to set 'isk' -" For version 5.x: Clear all syntax items and don't load -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear - echo "Reva syntax file requires version 6.0 or later of vim!" - finish -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif diff --git a/runtime/syntax/rexx.vim b/runtime/syntax/rexx.vim index ef698a5351..360fc8ff9f 100644 --- a/runtime/syntax/rexx.vim +++ b/runtime/syntax/rexx.vim @@ -6,11 +6,8 @@ " Special Thanks to Dan Sharp <dwsharp@hotmail.com> and Rony G. Flatscher " <Rony.Flatscher@wu-wien.ac.at> for comments and additions -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -244,87 +241,77 @@ syn sync linecont "\(,\|-\ze-\@!\)\ze\s*\(--.*\|\/\*.*\)*$" exec "syn sync fromstart" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_rexx_syn_inits") - if version < 508 - let did_rexx_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - " make binary and hex strings stand out - hi rexxStringConstant term=bold,underline ctermfg=5 cterm=bold guifg=darkMagenta gui=bold - - HiLink rexxLabel2 Function - HiLink doLoopSelectLabelRegion rexxKeyword - HiLink endIterateLeaveLabelRegion rexxKeyword - HiLink rexxLoopKeywords rexxKeyword " Todo - - HiLink rexxNumber Normal "DiffChange -" HiLink rexxIdentifier DiffChange - - HiLink rexxRegularCallSignal Statement - HiLink rexxExceptionHandling Statement - - HiLink rexxLabel Function - HiLink rexxCharacter Character - HiLink rexxParenError rexxError - HiLink rexxInParen rexxError - HiLink rexxCommentError rexxError - HiLink rexxError Error - HiLink rexxKeyword Statement - HiLink rexxKeywordStatements Statement - - HiLink rexxFunction Function - HiLink rexxString String - HiLink rexxComment Comment - HiLink rexxTodo Todo - HiLink rexxSpecialVariable Special - HiLink rexxConditional rexxKeyword - - HiLink rexxOperator Operator - HiLink rexxMessageOperator rexxOperator - HiLink rexxLineComment Comment - - HiLink rexxLineContinue WildMenu - - HiLink rexxDirective rexxKeyword - HiLink rexxClassDirective Type - HiLink rexxMethodDirective rexxFunction - HiLink rexxAttributeDirective rexxFunction - HiLink rexxRequiresDirective Include - HiLink rexxRoutineDirective rexxFunction +" Only when an item doesn't have highlighting yet + +" make binary and hex strings stand out +hi rexxStringConstant term=bold,underline ctermfg=5 cterm=bold guifg=darkMagenta gui=bold + +hi def link rexxLabel2 Function +hi def link doLoopSelectLabelRegion rexxKeyword +hi def link endIterateLeaveLabelRegion rexxKeyword +hi def link rexxLoopKeywords rexxKeyword " Todo + +hi def link rexxNumber Normal "DiffChange +" hi def link rexxIdentifier DiffChange + +hi def link rexxRegularCallSignal Statement +hi def link rexxExceptionHandling Statement + +hi def link rexxLabel Function +hi def link rexxCharacter Character +hi def link rexxParenError rexxError +hi def link rexxInParen rexxError +hi def link rexxCommentError rexxError +hi def link rexxError Error +hi def link rexxKeyword Statement +hi def link rexxKeywordStatements Statement + +hi def link rexxFunction Function +hi def link rexxString String +hi def link rexxComment Comment +hi def link rexxTodo Todo +hi def link rexxSpecialVariable Special +hi def link rexxConditional rexxKeyword + +hi def link rexxOperator Operator +hi def link rexxMessageOperator rexxOperator +hi def link rexxLineComment Comment + +hi def link rexxLineContinue WildMenu + +hi def link rexxDirective rexxKeyword +hi def link rexxClassDirective Type +hi def link rexxMethodDirective rexxFunction +hi def link rexxAttributeDirective rexxFunction +hi def link rexxRequiresDirective Include +hi def link rexxRoutineDirective rexxFunction " rgf, 2012-09-09 - HiLink rexxOptionsDirective rexxFunction - HiLink rexxOptionsDirective2 rexxOptionsDirective - HiLink rexxOptionsDirective3 Normal " rexxOptionsDirective +hi def link rexxOptionsDirective rexxFunction +hi def link rexxOptionsDirective2 rexxOptionsDirective +hi def link rexxOptionsDirective3 Normal " rexxOptionsDirective - HiLink rexxConstantDirective rexxFunction +hi def link rexxConstantDirective rexxFunction - HiLink rexxConst Constant - HiLink rexxTypeSpecifier Type - HiLink rexxBuiltinClass rexxTypeSpecifier +hi def link rexxConst Constant +hi def link rexxTypeSpecifier Type +hi def link rexxBuiltinClass rexxTypeSpecifier - HiLink rexxEnvironmentSymbol rexxConst - HiLink rexxMessage rexxFunction +hi def link rexxEnvironmentSymbol rexxConst +hi def link rexxMessage rexxFunction - HiLink rexxParse rexxKeyword - HiLink rexxParse2 rexxParse +hi def link rexxParse rexxKeyword +hi def link rexxParse2 rexxParse - HiLink rexxGuard rexxKeyword - HiLink rexxTrace rexxKeyword +hi def link rexxGuard rexxKeyword +hi def link rexxTrace rexxKeyword - HiLink rexxRaise rexxKeyword - HiLink rexxRaise2 rexxRaise +hi def link rexxRaise rexxKeyword +hi def link rexxRaise2 rexxRaise - HiLink rexxForward rexxKeyword - HiLink rexxForward2 rexxForward +hi def link rexxForward rexxKeyword +hi def link rexxForward2 rexxForward - delcommand HiLink -endif let b:current_syntax = "rexx" diff --git a/runtime/syntax/rhelp.vim b/runtime/syntax/rhelp.vim index 47c764e296..8cac585bb0 100644 --- a/runtime/syntax/rhelp.vim +++ b/runtime/syntax/rhelp.vim @@ -3,7 +3,7 @@ " Maintainer: Jakson Aquino <jalvesaq@gmail.com> " Former Maintainer: Johannes Ranke <jranke@uni-bremen.de> " Homepage: https://github.com/jalvesaq/R-Vim-runtime -" Last Change: Sat Feb 06, 2016 11:34AM +" Last Change: Tue Jun 28, 2016 08:53AM " Remarks: - Includes R syntax highlighting in the appropriate " sections if an r.vim file is in the same directory or in the " default debian location. @@ -17,7 +17,6 @@ if exists("b:current_syntax") endif scriptencoding utf-8 -setlocal iskeyword=@,48-57,_,. syn case match diff --git a/runtime/syntax/rib.vim b/runtime/syntax/rib.vim index 6b9f2b0bd4..0ee607122f 100644 --- a/runtime/syntax/rib.vim +++ b/runtime/syntax/rib.vim @@ -4,10 +4,8 @@ " Last Change: 2003 May 11 " -" Remove any old syntax stuff hanging around -if version < 600 - syn clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -46,26 +44,17 @@ syn match ribFloat display contained "[-]\=\.\d\+\(e[-+]\=\d\+\)\=\>" syn match ribFloat display contained "[-]\=\d\+e[-+]\d\+\>" syn case match -if version >= 508 || !exists("did_rib_syntax_inits") - if version < 508 - let did_rib_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - HiLink ribStructure Structure - HiLink ribCommand Statement +hi def link ribStructure Structure +hi def link ribCommand Statement - HiLink ribStructureComment SpecialComment - HiLink ribLineComment Comment +hi def link ribStructureComment SpecialComment +hi def link ribLineComment Comment - HiLink ribString String - HiLink ribNumber Number - HiLink ribFloat Float +hi def link ribString String +hi def link ribNumber Number +hi def link ribFloat Float - delcommand HiLink -end let b:current_syntax = "rib" diff --git a/runtime/syntax/rmd.vim b/runtime/syntax/rmd.vim index 4cde7441d3..48fb5e079c 100644 --- a/runtime/syntax/rmd.vim +++ b/runtime/syntax/rmd.vim @@ -1,7 +1,7 @@ " markdown Text with R statements " Language: markdown with R code chunks " Homepage: https://github.com/jalvesaq/R-Vim-runtime -" Last Change: Sat Feb 06, 2016 06:45AM +" Last Change: Tue Jun 28, 2016 10:09AM " " CONFIGURATION: " To highlight chunk headers as R code, put in your vimrc: @@ -72,8 +72,6 @@ if rmdIsPandoc == 0 hi def link rmdLaTeXRegDelim Special endif -setlocal iskeyword=@,48-57,_,. - syn sync match rmdSyncChunk grouphere rmdChunk "^[ \t]*``` *{r" hi def link rmdChunkDelim Special diff --git a/runtime/syntax/robots.vim b/runtime/syntax/robots.vim index 066628bb3c..396bf52b25 100644 --- a/runtime/syntax/robots.vim +++ b/runtime/syntax/robots.vim @@ -5,11 +5,8 @@ " URL: http://www.mggen.com/vim/syntax/robots.zip " Last change: 2001 May 09 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -41,26 +38,17 @@ syn match robotsUrl "http[s]\=://\S*" syn match robotsMail "\S*@\S*" syn region robotsString start=+L\="+ skip=+\\\\\|\\"+ end=+"+ -if version >= 508 || !exists("did_robos_syntax_inits") - if version < 508 - let did_robots_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink robotsComment Comment - HiLink robotsAgent Type - HiLink robotsDisallow Statement - HiLink robotsLine Special - HiLink robotsStar Operator - HiLink robotsDelimiter Delimiter - HiLink robotsUrl String - HiLink robotsMail String - HiLink robotsString String - - delcommand HiLink -endif + +hi def link robotsComment Comment +hi def link robotsAgent Type +hi def link robotsDisallow Statement +hi def link robotsLine Special +hi def link robotsStar Operator +hi def link robotsDelimiter Delimiter +hi def link robotsUrl String +hi def link robotsMail String +hi def link robotsString String + let b:current_syntax = "robots" diff --git a/runtime/syntax/rpcgen.vim b/runtime/syntax/rpcgen.vim index 85036dc049..08183d43a4 100644 --- a/runtime/syntax/rpcgen.vim +++ b/runtime/syntax/rpcgen.vim @@ -1,8 +1,8 @@ " Vim syntax file " Language: rpcgen " Maintainer: Charles E. Campbell <NdrOchipS@PcampbellAfamily.Mbiz> -" Last Change: Jan 13, 2015 -" Version: 10 +" Last Change: Aug 31, 2016 +" Version: 12 " URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_RPCGEN if exists("b:current_syntax") @@ -10,11 +10,7 @@ if exists("b:current_syntax") endif " Read the C syntax to start with -if version < 600 - source <sfile>:p:h/c.vim -else - runtime! syntax/c.vim -endif +runtime! syntax/c.vim syn keyword rpcProgram program skipnl skipwhite nextgroup=rpcProgName syn match rpcProgName contained "\<\i\I*\>" skipnl skipwhite nextgroup=rpcProgZone @@ -28,30 +24,21 @@ syn match rpcProgNmbrErr contained "=\s*0x[^23]\x*"ms=s+1 syn match rpcPassThru "^\s*%.*$" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_rpcgen_syntax_inits") - if version < 508 - let did_rpcgen_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink rpcProgName rpcName - HiLink rpcProgram rpcStatement - HiLink rpcVersName rpcName - HiLink rpcVersion rpcStatement - - HiLink rpcDecl cType - HiLink rpcPassThru cComment - - HiLink rpcName Special - HiLink rpcProcNmbr Delimiter - HiLink rpcProgNmbrErr Error - HiLink rpcStatement Statement - - delcommand HiLink +if !exists("skip_rpcgen_syntax_inits") + + hi def link rpcProgName rpcName + hi def link rpcProgram rpcStatement + hi def link rpcVersName rpcName + hi def link rpcVersion rpcStatement + + hi def link rpcDecl cType + hi def link rpcPassThru cComment + + hi def link rpcName Special + hi def link rpcProcNmbr Delimiter + hi def link rpcProgNmbrErr Error + hi def link rpcStatement Statement + endif let b:current_syntax = "rpcgen" diff --git a/runtime/syntax/rpl.vim b/runtime/syntax/rpl.vim index 6457803a06..f339f7ae6e 100644 --- a/runtime/syntax/rpl.vim +++ b/runtime/syntax/rpl.vim @@ -6,11 +6,8 @@ " URL: http://www.makalis.fr/~bertrand/rpl2/download/vim/indent/rpl.vim " Credits: Nothing -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -417,77 +414,67 @@ syntax region rplString start=+\(^\|\s\+\)"+ end=+"\ze\($\|\s\+\)+ contains=rplS syntax match rplTab "\t" transparent " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_rpl_syntax_inits") - if version < 508 - let did_rpl_syntax_inits = 1 - command -nargs=+ HiLink highlight link <args> - else - command -nargs=+ HiLink highlight default link <args> - endif - - " The default highlighting. - - HiLink rplControl Statement - HiLink rplStatement Statement - HiLink rplAlgConditional Conditional - HiLink rplConditional Repeat - HiLink rplConditionalError Error - HiLink rplRepeat Repeat - HiLink rplCycle Repeat - HiLink rplUntil Repeat - HiLink rplIntrinsic Special - HiLink rplStorage StorageClass - HiLink rplStorageExpr StorageClass - HiLink rplStorageError Error - HiLink rplReadWrite rplIntrinsic - - HiLink rplOperator Operator - - HiLink rplList Special - HiLink rplArray Special - HiLink rplConstant Identifier - HiLink rplExpr Type - - HiLink rplString String - HiLink rplStringGuilles String - HiLink rplStringAntislash String - - HiLink rplBinary Boolean - HiLink rplOctal Boolean - HiLink rplDecimal Boolean - HiLink rplHexadecimal Boolean - HiLink rplInteger Number - HiLink rplFloat Float - HiLink rplComplex Float - HiLink rplBoolean Identifier - - HiLink rplObsolete Todo - - HiLink rplPreCondit PreCondit - HiLink rplInclude Include - HiLink rplIncluded rplString - HiLink rplInclude Include - HiLink rplExecPath Include - HiLink rplPreProc PreProc - HiLink rplComment Comment - HiLink rplCommentLine Comment - HiLink rplCommentString Comment - HiLink rplSubDelimitor rplStorage - HiLink rplCommentError Error - HiLink rplParenError Error - HiLink rplSubError Error - HiLink rplArrayError Error - HiLink rplListError Error - HiLink rplTab Error - HiLink rplBinaryError Error - HiLink rplOctalError Error - HiLink rplDecimalError Error - HiLink rplHexadecimalError Error - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +" The default highlighting. + +hi def link rplControl Statement +hi def link rplStatement Statement +hi def link rplAlgConditional Conditional +hi def link rplConditional Repeat +hi def link rplConditionalError Error +hi def link rplRepeat Repeat +hi def link rplCycle Repeat +hi def link rplUntil Repeat +hi def link rplIntrinsic Special +hi def link rplStorage StorageClass +hi def link rplStorageExpr StorageClass +hi def link rplStorageError Error +hi def link rplReadWrite rplIntrinsic + +hi def link rplOperator Operator + +hi def link rplList Special +hi def link rplArray Special +hi def link rplConstant Identifier +hi def link rplExpr Type + +hi def link rplString String +hi def link rplStringGuilles String +hi def link rplStringAntislash String + +hi def link rplBinary Boolean +hi def link rplOctal Boolean +hi def link rplDecimal Boolean +hi def link rplHexadecimal Boolean +hi def link rplInteger Number +hi def link rplFloat Float +hi def link rplComplex Float +hi def link rplBoolean Identifier + +hi def link rplObsolete Todo + +hi def link rplPreCondit PreCondit +hi def link rplInclude Include +hi def link rplIncluded rplString +hi def link rplInclude Include +hi def link rplExecPath Include +hi def link rplPreProc PreProc +hi def link rplComment Comment +hi def link rplCommentLine Comment +hi def link rplCommentString Comment +hi def link rplSubDelimitor rplStorage +hi def link rplCommentError Error +hi def link rplParenError Error +hi def link rplSubError Error +hi def link rplArrayError Error +hi def link rplListError Error +hi def link rplTab Error +hi def link rplBinaryError Error +hi def link rplOctalError Error +hi def link rplDecimalError Error +hi def link rplHexadecimalError Error + let b:current_syntax = "rpl" diff --git a/runtime/syntax/rrst.vim b/runtime/syntax/rrst.vim index 24d3844df0..b643af3285 100644 --- a/runtime/syntax/rrst.vim +++ b/runtime/syntax/rrst.vim @@ -2,7 +2,7 @@ " Language: reST with R code chunks " Maintainer: Alex Zvoleff, azvoleff@mail.sdsu.edu " Homepage: https://github.com/jalvesaq/R-Vim-runtime -" Last Change: Sat Feb 06, 2016 06:45AM +" Last Change: Tue Jun 28, 2016 08:53AM " " CONFIGURATION: " To highlight chunk headers as R code, put in your vimrc: @@ -19,8 +19,6 @@ unlet b:current_syntax " load all of the r syntax highlighting rules into @R syntax include @R syntax/r.vim -setlocal iskeyword=@,48-57,_,. - " highlight R chunks if exists("g:rrst_syn_hl_chunk") " highlight R code inside chunk header diff --git a/runtime/syntax/rst.vim b/runtime/syntax/rst.vim index b3c89f8352..232d2a7de3 100644 --- a/runtime/syntax/rst.vim +++ b/runtime/syntax/rst.vim @@ -2,7 +2,8 @@ " Language: reStructuredText documentation format " Maintainer: Marshall Ward <marshall.ward@gmail.com> " Previous Maintainer: Nikolai Weibull <now@bitwi.se> -" Latest Revision: 2016-01-05 +" Website: https://github.com/marshallward/vim-restructuredtext +" Latest Revision: 2016-08-18 if exists("b:current_syntax") finish @@ -89,7 +90,7 @@ function! s:DefineOneInlineMarkup(name, start, middle, end, char_left, char_righ \ ' start=+' . a:char_left . '\zs' . a:start . \ '\ze[^[:space:]' . a:char_right . a:start[strlen(a:start) - 1] . ']+' . \ a:middle . - \ ' end=+\S' . a:end . '\ze\%($\|\s\|[''")\]}>/:.,;!?\\-]\)+' + \ ' end=+\S' . a:end . '\ze\%($\|\s\|[''"โ)\]}>/:.,;!?\\-]\)+' endfunction function! s:DefineInlineMarkup(name, start, middle, end) @@ -103,6 +104,8 @@ function! s:DefineInlineMarkup(name, start, middle, end) call s:DefineOneInlineMarkup(a:name, a:start, middle, a:end, '\[', '\]') call s:DefineOneInlineMarkup(a:name, a:start, middle, a:end, '{', '}') call s:DefineOneInlineMarkup(a:name, a:start, middle, a:end, '<', '>') + call s:DefineOneInlineMarkup(a:name, a:start, middle, a:end, 'โ', 'โ') + " TODO: Additional Unicode Pd, Po, Pi, Pf, Ps characters call s:DefineOneInlineMarkup(a:name, a:start, middle, a:end, '\%(^\|\s\|[/:]\)', '') @@ -137,7 +140,7 @@ syn match rstStandaloneHyperlink contains=@NoSpell \ "\<\%(\%(\%(https\=\|file\|ftp\|gopher\)://\|\%(mailto\|news\):\)[^[:space:]'\"<>]\+\|www[[:alnum:]_-]*\.[[:alnum:]_-]\+\.[^[:space:]'\"<>]\+\)[[:alnum:]/]" syn region rstCodeBlock contained matchgroup=rstDirective - \ start=+\%(sourcecode\|code\%(-block\)\=\)::\_s*\n\ze\z(\s\+\)+ + \ start=+\%(sourcecode\|code\%(-block\)\=\)::\s\+\w*\_s*\n\ze\z(\s\+\)+ \ skip=+^$+ \ end=+^\z1\@!+ \ contains=@NoSpell @@ -153,10 +156,11 @@ for code in g:rst_syntax_code_list " guard against setting 'isk' option which might cause problems (issue #108) let prior_isk = &l:iskeyword exe 'syn include @rst'.code.' syntax/'.code.'.vim' - exe 'syn region rstDirective'.code.' matchgroup=rstDirective fold ' - \.'start=#\%(sourcecode\|code\%(-block\)\=\)::\s\+'.code.'\_s*\n\ze\z(\s\+\)# ' - \.'skip=#^$# ' - \.'end=#^\z1\@!# contains=@NoSpell,@rst'.code + exe 'syn region rstDirective'.code.' matchgroup=rstDirective fold' + \.' start=#\%(sourcecode\|code\%(-block\)\=\)::\s\+'.code.'\_s*\n\ze\z(\s\+\)#' + \.' skip=#^$#' + \.' end=#^\z1\@!#' + \.' contains=@NoSpell,@rst'.code exe 'syn cluster rstDirectives add=rstDirective'.code " reset 'isk' setting, if it has been changed if &l:iskeyword !=# prior_isk @@ -185,10 +189,8 @@ hi def link rstHyperlinkTarget String hi def link rstExDirective String hi def link rstSubstitutionDefinition rstDirective hi def link rstDelimiter Delimiter -" TODO: I dunno... -hi def rstEmphasis term=italic cterm=italic gui=italic -hi def link rstStrongEmphasis Special -"term=bold cterm=bold gui=bold +hi def rstEmphasis ctermfg=13 term=italic cterm=italic gui=italic +hi def rstStrongEmphasis ctermfg=1 term=bold cterm=bold gui=bold hi def link rstInterpretedTextOrHyperlinkReference Identifier hi def link rstInlineLiteral String hi def link rstSubstitutionReference PreProc diff --git a/runtime/syntax/rtf.vim b/runtime/syntax/rtf.vim index 8f5ea71a36..c856f9ffcf 100644 --- a/runtime/syntax/rtf.vim +++ b/runtime/syntax/rtf.vim @@ -13,11 +13,8 @@ " TODO: render underline, italic, bold -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -52,35 +49,25 @@ syn match rtfBlue "\\blue[0-9][0-9]*" syn match rtfFootNote "[#$K+]{\\footnote.*}" contains=rtfControlWord,rtfNewControlWord " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_rtf_syntax_inits") - if version < 508 - let did_rtf_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - - HiLink rtfControlWord Statement - HiLink rtfNewControlWord Special - HiLink rtfControlSymbol Constant - HiLink rtfCharacter Character - HiLink rtfUnicodeCharacter SpecialChar - HiLink rtfFootNote Comment - - " Define colors for the syntax file - hi rtfRed term=underline cterm=underline ctermfg=DarkRed gui=underline guifg=DarkRed - hi rtfGreen term=underline cterm=underline ctermfg=DarkGreen gui=underline guifg=DarkGreen - hi rtfBlue term=underline cterm=underline ctermfg=DarkBlue gui=underline guifg=DarkBlue - - HiLink rtfRed rtfRed - HiLink rtfGreen rtfGreen - HiLink rtfBlue rtfBlue - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + + +hi def link rtfControlWord Statement +hi def link rtfNewControlWord Special +hi def link rtfControlSymbol Constant +hi def link rtfCharacter Character +hi def link rtfUnicodeCharacter SpecialChar +hi def link rtfFootNote Comment + +" Define colors for the syntax file +hi rtfRed term=underline cterm=underline ctermfg=DarkRed gui=underline guifg=DarkRed +hi rtfGreen term=underline cterm=underline ctermfg=DarkGreen gui=underline guifg=DarkGreen +hi rtfBlue term=underline cterm=underline ctermfg=DarkBlue gui=underline guifg=DarkBlue + +hi def link rtfRed rtfRed +hi def link rtfGreen rtfGreen +hi def link rtfBlue rtfBlue + let b:current_syntax = "rtf" diff --git a/runtime/syntax/ruby.vim b/runtime/syntax/ruby.vim index 28f553decb..ca7f51b1ea 100644 --- a/runtime/syntax/ruby.vim +++ b/runtime/syntax/ruby.vim @@ -9,16 +9,45 @@ " Thanks to perl.vim authors, and to Reimer Behrends. :-) (MN) " ---------------------------------------------------------------------------- +" Prelude {{{1 if exists("b:current_syntax") finish endif +" this file uses line continuations +let s:cpo_sav = &cpo +set cpo&vim + +" Folding Config {{{1 if has("folding") && exists("ruby_fold") setlocal foldmethod=syntax endif +let s:foldable_groups = split( + \ get( + \ b:, + \ 'ruby_foldable_groups', + \ get(g:, 'ruby_foldable_groups', 'ALL') + \ ) + \ ) + +function! s:foldable(...) abort + if index(s:foldable_groups, 'ALL') > -1 + return 1 + endif + + for l:i in a:000 + if index(s:foldable_groups, l:i) > -1 + return 1 + endif + endfor + + return 0 +endfunction " }}} + syn cluster rubyNotTop contains=@rubyExtendedStringSpecial,@rubyRegexpSpecial,@rubyDeclaration,rubyConditional,rubyExceptional,rubyMethodExceptional,rubyTodo +" Whitespace Errors {{{1 if exists("ruby_space_errors") if !exists("ruby_no_trail_space_error") syn match rubySpaceError display excludenl "\s\+$" @@ -28,14 +57,14 @@ if exists("ruby_space_errors") endif endif -" Operators +" Operators {{{1 if exists("ruby_operators") - syn match rubyOperator "[~!^&|*/%+-]\|\%(class\s*\)\@<!<<\|<=>\|<=\|\%(<\|\<class\s\+\u\w*\s*\)\@<!<[^<]\@=\|===\|==\|=\~\|>>\|>=\|=\@<!>\|\*\*\|\.\.\.\|\.\.\|::" + syn match rubyOperator "[~!^|*/%+-]\|&\.\@!\|\%(class\s*\)\@<!<<\|<=>\|<=\|\%(<\|\<class\s\+\u\w*\s*\)\@<!<[^<]\@=\|===\|==\|=\~\|>>\|>=\|=\@1<!>\|\*\*\|\.\.\.\|\.\.\|::" syn match rubyOperator "->\|-=\|/=\|\*\*=\|\*=\|&&=\|&=\|&&\|||=\||=\|||\|%=\|+=\|!\~\|!=" - syn region rubyBracketOperator matchgroup=rubyOperator start="\%(\w[?!]\=\|[]})]\)\@<=\[\s*" end="\s*]" contains=ALLBUT,@rubyNotTop + syn region rubyBracketOperator matchgroup=rubyOperator start="\%(\w[?!]\=\|[]})]\)\@2<=\[\s*" end="\s*]" contains=ALLBUT,@rubyNotTop endif -" Expression Substitution and Backslash Notation +" Expression Substitution and Backslash Notation {{{1 syn match rubyStringEscape "\\\\\|\\[abefnrstv]\|\\\o\{1,3}\|\\x\x\{1,2}" contained display syn match rubyStringEscape "\%(\\M-\\C-\|\\C-\\M-\|\\M-\\c\|\\c\\M-\|\\c\|\\C-\|\\M-\)\%(\\\o\{1,3}\|\\x\x\{1,2}\|\\\=\S\)" contained display syn match rubyQuoteEscape "\\[\\']" contained display @@ -45,18 +74,19 @@ syn match rubyInterpolation "#\%(\$\|@@\=\)\w\+" display contained con syn match rubyInterpolationDelimiter "#\ze\%(\$\|@@\=\)\w\+" display contained syn match rubyInterpolation "#\$\%(-\w\|\W\)" display contained contains=rubyInterpolationDelimiter,rubyPredefinedVariable,rubyInvalidVariable syn match rubyInterpolationDelimiter "#\ze\$\%(-\w\|\W\)" display contained -syn region rubyNoInterpolation start="\\#{" end="}" contained +syn region rubyNoInterpolation start="\\#{" end="}" contained syn match rubyNoInterpolation "\\#{" display contained syn match rubyNoInterpolation "\\#\%(\$\|@@\=\)\w\+" display contained syn match rubyNoInterpolation "\\#\$\W" display contained -syn match rubyDelimEscape "\\[(<{\[)>}\]]" transparent display contained contains=NONE +syn match rubyDelimiterEscape "\\[(<{\[)>}\]]" transparent display contained contains=NONE syn region rubyNestedParentheses start="(" skip="\\\\\|\\)" matchgroup=rubyString end=")" transparent contained syn region rubyNestedCurlyBraces start="{" skip="\\\\\|\\}" matchgroup=rubyString end="}" transparent contained syn region rubyNestedAngleBrackets start="<" skip="\\\\\|\\>" matchgroup=rubyString end=">" transparent contained syn region rubyNestedSquareBrackets start="\[" skip="\\\\\|\\\]" matchgroup=rubyString end="\]" transparent contained +" Regular Expression Metacharacters {{{1 " These are mostly Oniguruma ready syn region rubyRegexpComment matchgroup=rubyRegexpSpecial start="(?#" skip="\\)" end=")" contained syn region rubyRegexpParens matchgroup=rubyRegexpSpecial start="(\(?:\|?<\=[=!]\|?>\|?<[a-z_]\w*>\|?[imx]*-[imx]*:\=\|\%(?#\)\@!\)" skip="\\)" end=")" contained transparent contains=@rubyRegexpSpecial @@ -79,36 +109,40 @@ syn cluster rubyStringSpecial contains=rubyInterpolation,rubyNoInterpolati syn cluster rubyExtendedStringSpecial contains=@rubyStringSpecial,rubyNestedParentheses,rubyNestedCurlyBraces,rubyNestedAngleBrackets,rubyNestedSquareBrackets syn cluster rubyRegexpSpecial contains=rubyInterpolation,rubyNoInterpolation,rubyStringEscape,rubyRegexpSpecial,rubyRegexpEscape,rubyRegexpBrackets,rubyRegexpCharClass,rubyRegexpDot,rubyRegexpQuantifier,rubyRegexpAnchor,rubyRegexpParens,rubyRegexpComment -" Numbers and ASCII Codes -syn match rubyASCIICode "\%(\w\|[]})\"'/]\)\@<!\%(?\%(\\M-\\C-\|\\C-\\M-\|\\M-\\c\|\\c\\M-\|\\c\|\\C-\|\\M-\)\=\%(\\\o\{1,3}\|\\x\x\{1,2}\|\\\=\S\)\)" -syn match rubyInteger "\%(\%(\w\|[]})\"']\s*\)\@<!-\)\=\<0[xX]\x\+\%(_\x\+\)*\>" display -syn match rubyInteger "\%(\%(\w\|[]})\"']\s*\)\@<!-\)\=\<\%(0[dD]\)\=\%(0\|[1-9]\d*\%(_\d\+\)*\)\>" display -syn match rubyInteger "\%(\%(\w\|[]})\"']\s*\)\@<!-\)\=\<0[oO]\=\o\+\%(_\o\+\)*\>" display -syn match rubyInteger "\%(\%(\w\|[]})\"']\s*\)\@<!-\)\=\<0[bB][01]\+\%(_[01]\+\)*\>" display -syn match rubyFloat "\%(\%(\w\|[]})\"']\s*\)\@<!-\)\=\<\%(0\|[1-9]\d*\%(_\d\+\)*\)\.\d\+\%(_\d\+\)*\>" display -syn match rubyFloat "\%(\%(\w\|[]})\"']\s*\)\@<!-\)\=\<\%(0\|[1-9]\d*\%(_\d\+\)*\)\%(\.\d\+\%(_\d\+\)*\)\=\%([eE][-+]\=\d\+\%(_\d\+\)*\)\>" display +" Numbers and ASCII Codes {{{1 +syn match rubyASCIICode "\%(\w\|[]})\"'/]\)\@1<!\%(?\%(\\M-\\C-\|\\C-\\M-\|\\M-\\c\|\\c\\M-\|\\c\|\\C-\|\\M-\)\=\%(\\\o\{1,3}\|\\x\x\{1,2}\|\\\=\S\)\)" +syn match rubyInteger "\%(\%(\w\|[]})\"']\s*\)\@<!-\)\=\<0[xX]\x\+\%(_\x\+\)*r\=i\=\>" display +syn match rubyInteger "\%(\%(\w\|[]})\"']\s*\)\@<!-\)\=\<\%(0[dD]\)\=\%(0\|[1-9]\d*\%(_\d\+\)*\)r\=i\=\>" display +syn match rubyInteger "\%(\%(\w\|[]})\"']\s*\)\@<!-\)\=\<0[oO]\=\o\+\%(_\o\+\)*r\=i\=\>" display +syn match rubyInteger "\%(\%(\w\|[]})\"']\s*\)\@<!-\)\=\<0[bB][01]\+\%(_[01]\+\)*r\=i\=\>" display +syn match rubyFloat "\%(\%(\w\|[]})\"']\s*\)\@<!-\)\=\<\%(0\|[1-9]\d*\%(_\d\+\)*\)\.\d\+\%(_\d\+\)*r\=i\=\>" display +syn match rubyFloat "\%(\%(\w\|[]})\"']\s*\)\@<!-\)\=\<\%(0\|[1-9]\d*\%(_\d\+\)*\)\%(\.\d\+\%(_\d\+\)*\)\=\%([eE][-+]\=\d\+\%(_\d\+\)*\)r\=i\=\>" display -" Identifiers +" Identifiers {{{1 syn match rubyLocalVariableOrMethod "\<[_[:lower:]][_[:alnum:]]*[?!=]\=" contains=NONE display transparent syn match rubyBlockArgument "&[_[:lower:]][_[:alnum:]]" contains=NONE display transparent -syn match rubyConstant "\%(\%([.@$]\@<!\.\)\@<!\<\|::\)\_s*\zs\u\w*\%(\>\|::\)\@=\%(\s*(\)\@!" +syn match rubyConstant "\%(\%(^\|[^.]\)\.\s*\)\@<!\<\u\%(\w\|[^\x00-\x7F]\)*\>\%(\s*(\)\@!" syn match rubyClassVariable "@@\%(\h\|[^\x00-\x7F]\)\%(\w\|[^\x00-\x7F]\)*" display -syn match rubyInstanceVariable "@\%(\h\|[^\x00-\x7F]\)\%(\w\|[^\x00-\x7F]\)*" display +syn match rubyInstanceVariable "@\%(\h\|[^\x00-\x7F]\)\%(\w\|[^\x00-\x7F]\)*" display syn match rubyGlobalVariable "$\%(\%(\h\|[^\x00-\x7F]\)\%(\w\|[^\x00-\x7F]\)*\|-.\)" -syn match rubySymbol "[]})\"':]\@<!:\%(\^\|\~\|<<\|<=>\|<=\|<\|===\|[=!]=\|[=!]\~\|!\|>>\|>=\|>\||\|-@\|-\|/\|\[]=\|\[]\|\*\*\|\*\|&\|%\|+@\|+\|`\)" -syn match rubySymbol "[]})\"':]\@<!:\$\%(-.\|[`~<=>_,;:!?/.'"@$*\&+0]\)" -syn match rubySymbol "[]})\"':]\@<!:\%(\$\|@@\=\)\=\%(\h\|[^\x00-\x7F]\)\%(\w\|[^\x00-\x7F]\)*" -syn match rubySymbol "[]})\"':]\@<!:\%(\h\|[^\x00-\x7F]\)\%(\w\|[^\x00-\x7F]\)*\%([?!=]>\@!\)\=" -syn match rubySymbol "\%([{(,]\_s*\)\@<=\l\w*[!?]\=::\@!"he=e-1 -syn match rubySymbol "[]})\"':]\@<!\%(\h\|[^\x00-\x7F]\)\%(\w\|[^\x00-\x7F]\)*[!?]\=:\s\@="he=e-1 -syn match rubySymbol "\%([{(,]\_s*\)\@<=[[:space:],{]\l\w*[!?]\=::\@!"hs=s+1,he=e-1 -syn match rubySymbol "[[:space:],{]\%(\h\|[^\x00-\x7F]\)\%(\w\|[^\x00-\x7F]\)*[!?]\=:\s\@="hs=s+1,he=e-1 -syn region rubySymbol start="[]})\"':]\@<!:'" end="'" skip="\\\\\|\\'" contains=rubyQuoteEscape fold -syn region rubySymbol start="[]})\"':]\@<!:\"" end="\"" skip="\\\\\|\\\"" contains=@rubyStringSpecial fold +syn match rubySymbol "[]})\"':]\@1<!:\%(\^\|\~@\|\~\|<<\|<=>\|<=\|<\|===\|[=!]=\|[=!]\~\|!@\|!\|>>\|>=\|>\||\|-@\|-\|/\|\[]=\|\[]\|\*\*\|\*\|&\|%\|+@\|+\|`\)" +syn match rubySymbol "[]})\"':]\@1<!:\$\%(-.\|[`~<=>_,;:!?/.'"@$*\&+0]\)" +syn match rubySymbol "[]})\"':]\@1<!:\%(\$\|@@\=\)\=\%(\h\|[^\x00-\x7F]\)\%(\w\|[^\x00-\x7F]\)*" +syn match rubySymbol "[]})\"':]\@1<!:\%(\h\|[^\x00-\x7F]\)\%(\w\|[^\x00-\x7F]\)*\%([?!=]>\@!\)\=" + +if s:foldable(':') + syn region rubySymbol start="[]})\"':]\@1<!:'" end="'" skip="\\\\\|\\'" contains=rubyQuoteEscape fold + syn region rubySymbol start="[]})\"':]\@1<!:\"" end="\"" skip="\\\\\|\\\"" contains=@rubyStringSpecial fold +else + syn region rubySymbol start="[]})\"':]\@1<!:'" end="'" skip="\\\\\|\\'" contains=rubyQuoteEscape + syn region rubySymbol start="[]})\"':]\@1<!:\"" end="\"" skip="\\\\\|\\\"" contains=@rubyStringSpecial +endif + +syn match rubyCapitalizedMethod "\%(\%(^\|[^.]\)\.\s*\)\@<!\<\u\%(\w\|[^\x00-\x7F]\)*\>\%(\s*(\)*\s*(\@=" syn match rubyBlockParameter "\%(\h\|[^\x00-\x7F]\)\%(\w\|[^\x00-\x7F]\)*" contained -syn region rubyBlockParameterList start="\%(\%(\<do\>\|{\)\s*\)\@<=|" end="|" oneline display contains=rubyBlockParameter +syn region rubyBlockParameterList start="\%(\%(\<do\>\|{\)\_s*\)\@32<=|" end="|" oneline display contains=rubyBlockParameter syn match rubyInvalidVariable "$[^ A-Za-z_-]" syn match rubyPredefinedVariable #$[!$&"'*+,./0:;<=>?@\`~]# @@ -117,93 +151,187 @@ syn match rubyPredefinedVariable "$_\>" display syn match rubyPredefinedVariable "$-[0FIKadilpvw]\>" display syn match rubyPredefinedVariable "$\%(deferr\|defout\|stderr\|stdin\|stdout\)\>" display syn match rubyPredefinedVariable "$\%(DEBUG\|FILENAME\|KCODE\|LOADED_FEATURES\|LOAD_PATH\|PROGRAM_NAME\|SAFE\|VERBOSE\)\>" display -syn match rubyPredefinedConstant "\%(\%(\.\@<!\.\)\@<!\|::\)\_s*\zs\%(MatchingData\|ARGF\|ARGV\|ENV\)\>\%(\s*(\)\@!" -syn match rubyPredefinedConstant "\%(\%(\.\@<!\.\)\@<!\|::\)\_s*\zs\%(DATA\|FALSE\|NIL\)\>\%(\s*(\)\@!" -syn match rubyPredefinedConstant "\%(\%(\.\@<!\.\)\@<!\|::\)\_s*\zs\%(STDERR\|STDIN\|STDOUT\|TOPLEVEL_BINDING\|TRUE\)\>\%(\s*(\)\@!" -syn match rubyPredefinedConstant "\%(\%(\.\@<!\.\)\@<!\|::\)\_s*\zs\%(RUBY_\%(VERSION\|RELEASE_DATE\|PLATFORM\|PATCHLEVEL\|REVISION\|DESCRIPTION\|COPYRIGHT\|ENGINE\)\)\>\%(\s*(\)\@!" - -" Normal Regular Expression -syn region rubyRegexp matchgroup=rubyRegexpDelimiter start="\%(\%(^\|\<\%(and\|or\|while\|until\|unless\|if\|elsif\|when\|not\|then\|else\)\|[;\~=!|&(,[<>?:*+-]\)\s*\)\@<=/" end="/[iomxneus]*" skip="\\\\\|\\/" contains=@rubyRegexpSpecial fold -syn region rubyRegexp matchgroup=rubyRegexpDelimiter start="\%(\h\k*\s\+\)\@<=/[ \t=]\@!" end="/[iomxneus]*" skip="\\\\\|\\/" contains=@rubyRegexpSpecial fold - -" Generalized Regular Expression -syn region rubyRegexp matchgroup=rubyRegexpDelimiter start="%r\z([~`!@#$%^&*_\-+=|\:;"',.? /]\)" end="\z1[iomxneus]*" skip="\\\\\|\\\z1" contains=@rubyRegexpSpecial fold -syn region rubyRegexp matchgroup=rubyRegexpDelimiter start="%r{" end="}[iomxneus]*" skip="\\\\\|\\}" contains=@rubyRegexpSpecial fold -syn region rubyRegexp matchgroup=rubyRegexpDelimiter start="%r<" end=">[iomxneus]*" skip="\\\\\|\\>" contains=@rubyRegexpSpecial,rubyNestedAngleBrackets,rubyDelimEscape fold -syn region rubyRegexp matchgroup=rubyRegexpDelimiter start="%r\[" end="\][iomxneus]*" skip="\\\\\|\\\]" contains=@rubyRegexpSpecial fold -syn region rubyRegexp matchgroup=rubyRegexpDelimiter start="%r(" end=")[iomxneus]*" skip="\\\\\|\\)" contains=@rubyRegexpSpecial fold - -" Normal String and Shell Command Output -syn region rubyString matchgroup=rubyStringDelimiter start="\"" end="\"" skip="\\\\\|\\\"" contains=@rubyStringSpecial,@Spell fold -syn region rubyString matchgroup=rubyStringDelimiter start="'" end="'" skip="\\\\\|\\'" contains=rubyQuoteEscape,@Spell fold -syn region rubyString matchgroup=rubyStringDelimiter start="`" end="`" skip="\\\\\|\\`" contains=@rubyStringSpecial fold - -" Generalized Single Quoted String, Symbol and Array of Strings -syn region rubyString matchgroup=rubyStringDelimiter start="%[qwi]\z([~`!@#$%^&*_\-+=|\:;"',.?/]\)" end="\z1" skip="\\\\\|\\\z1" fold -syn region rubyString matchgroup=rubyStringDelimiter start="%[qwi]{" end="}" skip="\\\\\|\\}" fold contains=rubyNestedCurlyBraces,rubyDelimEscape -syn region rubyString matchgroup=rubyStringDelimiter start="%[qwi]<" end=">" skip="\\\\\|\\>" fold contains=rubyNestedAngleBrackets,rubyDelimEscape -syn region rubyString matchgroup=rubyStringDelimiter start="%[qwi]\[" end="\]" skip="\\\\\|\\\]" fold contains=rubyNestedSquareBrackets,rubyDelimEscape -syn region rubyString matchgroup=rubyStringDelimiter start="%[qwi](" end=")" skip="\\\\\|\\)" fold contains=rubyNestedParentheses,rubyDelimEscape -syn region rubyString matchgroup=rubyStringDelimiter start="%q " end=" " skip="\\\\\|\\)" fold -syn region rubySymbol matchgroup=rubySymbolDelimiter start="%s\z([~`!@#$%^&*_\-+=|\:;"',.? /]\)" end="\z1" skip="\\\\\|\\\z1" fold -syn region rubySymbol matchgroup=rubySymbolDelimiter start="%s{" end="}" skip="\\\\\|\\}" fold contains=rubyNestedCurlyBraces,rubyDelimEscape -syn region rubySymbol matchgroup=rubySymbolDelimiter start="%s<" end=">" skip="\\\\\|\\>" fold contains=rubyNestedAngleBrackets,rubyDelimEscape -syn region rubySymbol matchgroup=rubySymbolDelimiter start="%s\[" end="\]" skip="\\\\\|\\\]" fold contains=rubyNestedSquareBrackets,rubyDelimEscape -syn region rubySymbol matchgroup=rubySymbolDelimiter start="%s(" end=")" skip="\\\\\|\\)" fold contains=rubyNestedParentheses,rubyDelimEscape - -" Generalized Double Quoted String and Array of Strings and Shell Command Output +syn match rubyPredefinedConstant "\%(\%(^\|[^.]\)\.\s*\)\@<!\<\%(ARGF\|ARGV\|ENV\|DATA\|FALSE\|NIL\|STDERR\|STDIN\|STDOUT\|TOPLEVEL_BINDING\|TRUE\)\>\%(\s*(\)\@!" +syn match rubyPredefinedConstant "\%(\%(^\|[^.]\)\.\s*\)\@<!\<\%(RUBY_\%(VERSION\|RELEASE_DATE\|PLATFORM\|PATCHLEVEL\|REVISION\|DESCRIPTION\|COPYRIGHT\|ENGINE\)\)\>\%(\s*(\)\@!" + +" Normal Regular Expression {{{1 +if s:foldable('/') + syn region rubyRegexp matchgroup=rubyRegexpDelimiter start="\%(\%(^\|\<\%(and\|or\|while\|until\|unless\|if\|elsif\|when\|not\|then\|else\)\|[;\~=!|&(,{[<>?:*+-]\)\s*\)\@<=/" end="/[iomxneus]*" skip="\\\\\|\\/" contains=@rubyRegexpSpecial fold + syn region rubyRegexp matchgroup=rubyRegexpDelimiter start="\%(\h\k*\s\+\)\@<=/[ \t=]\@!" end="/[iomxneus]*" skip="\\\\\|\\/" contains=@rubyRegexpSpecial fold +else + syn region rubyRegexp matchgroup=rubyRegexpDelimiter start="\%(\%(^\|\<\%(and\|or\|while\|until\|unless\|if\|elsif\|when\|not\|then\|else\)\|[;\~=!|&(,{[<>?:*+-]\)\s*\)\@<=/" end="/[iomxneus]*" skip="\\\\\|\\/" contains=@rubyRegexpSpecial + syn region rubyRegexp matchgroup=rubyRegexpDelimiter start="\%(\h\k*\s\+\)\@<=/[ \t=]\@!" end="/[iomxneus]*" skip="\\\\\|\\/" contains=@rubyRegexpSpecial +endif + +" Generalized Regular Expression {{{1 +if s:foldable('%') + syn region rubyRegexp matchgroup=rubyRegexpDelimiter start="%r\z([~`!@#$%^&*_\-+=|\:;"',.?/]\)" end="\z1[iomxneus]*" skip="\\\\\|\\\z1" contains=@rubyRegexpSpecial fold + syn region rubyRegexp matchgroup=rubyRegexpDelimiter start="%r{" end="}[iomxneus]*" skip="\\\\\|\\}" contains=@rubyRegexpSpecial fold + syn region rubyRegexp matchgroup=rubyRegexpDelimiter start="%r<" end=">[iomxneus]*" skip="\\\\\|\\>" contains=@rubyRegexpSpecial,rubyNestedAngleBrackets,rubyDelimiterEscape fold + syn region rubyRegexp matchgroup=rubyRegexpDelimiter start="%r\[" end="\][iomxneus]*" skip="\\\\\|\\\]" contains=@rubyRegexpSpecial fold + syn region rubyRegexp matchgroup=rubyRegexpDelimiter start="%r(" end=")[iomxneus]*" skip="\\\\\|\\)" contains=@rubyRegexpSpecial fold + syn region rubyRegexp matchgroup=rubyRegexpDelimiter start="%r\z(\s\)" end="\z1[iomxneus]*" skip="\\\\\|\\\z1" contains=@rubyRegexpSpecial fold +else + syn region rubyRegexp matchgroup=rubyRegexpDelimiter start="%r\z([~`!@#$%^&*_\-+=|\:;"',.?/]\)" end="\z1[iomxneus]*" skip="\\\\\|\\\z1" contains=@rubyRegexpSpecial + syn region rubyRegexp matchgroup=rubyRegexpDelimiter start="%r{" end="}[iomxneus]*" skip="\\\\\|\\}" contains=@rubyRegexpSpecial + syn region rubyRegexp matchgroup=rubyRegexpDelimiter start="%r<" end=">[iomxneus]*" skip="\\\\\|\\>" contains=@rubyRegexpSpecial,rubyNestedAngleBrackets,rubyDelimiterEscape + syn region rubyRegexp matchgroup=rubyRegexpDelimiter start="%r\[" end="\][iomxneus]*" skip="\\\\\|\\\]" contains=@rubyRegexpSpecial + syn region rubyRegexp matchgroup=rubyRegexpDelimiter start="%r(" end=")[iomxneus]*" skip="\\\\\|\\)" contains=@rubyRegexpSpecial + syn region rubyRegexp matchgroup=rubyRegexpDelimiter start="%r\z(\s\)" end="\z1[iomxneus]*" skip="\\\\\|\\\z1" contains=@rubyRegexpSpecial +endif + +" Normal String {{{1 +let s:spell_cluster = exists('ruby_spellcheck_strings') ? ',@Spell' : '' +exe 'syn region rubyString matchgroup=rubyStringDelimiter start="\"" end="\"" skip="\\\\\|\\\"" ' . + \ (s:foldable('%') ? 'fold' : '') . ' contains=@rubyStringSpecial' . s:spell_cluster +exe 'syn region rubyString matchgroup=rubyStringDelimiter start="''" end="''" skip="\\\\\|\\''" ' . + \ (s:foldable('%') ? 'fold' : '') . ' contains=rubyQuoteEscape' . s:spell_cluster + +" Shell Command Output {{{1 +if s:foldable('%') + syn region rubyString matchgroup=rubyStringDelimiter start="`" end="`" skip="\\\\\|\\`" contains=@rubyStringSpecial fold +else + syn region rubyString matchgroup=rubyStringDelimiter start="`" end="`" skip="\\\\\|\\`" contains=@rubyStringSpecial +endif + +" Generalized Single Quoted String, Symbol and Array of Strings {{{1 +if s:foldable('%') + syn region rubyString matchgroup=rubyStringDelimiter start="%[qw]\z([~`!@#$%^&*_\-+=|\:;"',.?/]\)" end="\z1" skip="\\\\\|\\\z1" fold + syn region rubyString matchgroup=rubyStringDelimiter start="%[qw]{" end="}" skip="\\\\\|\\}" fold contains=rubyNestedCurlyBraces,rubyDelimiterEscape + syn region rubyString matchgroup=rubyStringDelimiter start="%[qw]<" end=">" skip="\\\\\|\\>" fold contains=rubyNestedAngleBrackets,rubyDelimiterEscape + syn region rubyString matchgroup=rubyStringDelimiter start="%[qw]\[" end="\]" skip="\\\\\|\\\]" fold contains=rubyNestedSquareBrackets,rubyDelimiterEscape + syn region rubyString matchgroup=rubyStringDelimiter start="%[qw](" end=")" skip="\\\\\|\\)" fold contains=rubyNestedParentheses,rubyDelimiterEscape + syn region rubyString matchgroup=rubyStringDelimiter start="%q\z(\s\)" end="\z1" skip="\\\\\|\\\z1" fold + syn region rubySymbol matchgroup=rubySymbolDelimiter start="%s\z([~`!@#$%^&*_\-+=|\:;"',.?/]\)" end="\z1" skip="\\\\\|\\\z1" fold + syn region rubySymbol matchgroup=rubySymbolDelimiter start="%s{" end="}" skip="\\\\\|\\}" fold contains=rubyNestedCurlyBraces,rubyDelimiterEscape + syn region rubySymbol matchgroup=rubySymbolDelimiter start="%s<" end=">" skip="\\\\\|\\>" fold contains=rubyNestedAngleBrackets,rubyDelimiterEscape + syn region rubySymbol matchgroup=rubySymbolDelimiter start="%s\[" end="\]" skip="\\\\\|\\\]" fold contains=rubyNestedSquareBrackets,rubyDelimiterEscape + syn region rubySymbol matchgroup=rubySymbolDelimiter start="%s(" end=")" skip="\\\\\|\\)" fold contains=rubyNestedParentheses,rubyDelimiterEscape + syn region rubyString matchgroup=rubyStringDelimiter start="%s\z(\s\)" end="\z1" skip="\\\\\|\\\z1" fold +else + syn region rubyString matchgroup=rubyStringDelimiter start="%[qw]\z([~`!@#$%^&*_\-+=|\:;"',.?/]\)" end="\z1" skip="\\\\\|\\\z1" + syn region rubyString matchgroup=rubyStringDelimiter start="%[qw]{" end="}" skip="\\\\\|\\}" contains=rubyNestedCurlyBraces,rubyDelimiterEscape + syn region rubyString matchgroup=rubyStringDelimiter start="%[qw]<" end=">" skip="\\\\\|\\>" contains=rubyNestedAngleBrackets,rubyDelimiterEscape + syn region rubyString matchgroup=rubyStringDelimiter start="%[qw]\[" end="\]" skip="\\\\\|\\\]" contains=rubyNestedSquareBrackets,rubyDelimiterEscape + syn region rubyString matchgroup=rubyStringDelimiter start="%[qw](" end=")" skip="\\\\\|\\)" contains=rubyNestedParentheses,rubyDelimiterEscape + syn region rubyString matchgroup=rubyStringDelimiter start="%q\z(\s\)" end="\z1" skip="\\\\\|\\\z1" + syn region rubySymbol matchgroup=rubySymbolDelimiter start="%s\z([~`!@#$%^&*_\-+=|\:;"',.?/]\)" end="\z1" skip="\\\\\|\\\z1" + syn region rubySymbol matchgroup=rubySymbolDelimiter start="%s{" end="}" skip="\\\\\|\\}" contains=rubyNestedCurlyBraces,rubyDelimiterEscape + syn region rubySymbol matchgroup=rubySymbolDelimiter start="%s<" end=">" skip="\\\\\|\\>" contains=rubyNestedAngleBrackets,rubyDelimiterEscape + syn region rubySymbol matchgroup=rubySymbolDelimiter start="%s\[" end="\]" skip="\\\\\|\\\]" contains=rubyNestedSquareBrackets,rubyDelimiterEscape + syn region rubySymbol matchgroup=rubySymbolDelimiter start="%s(" end=")" skip="\\\\\|\\)" contains=rubyNestedParentheses,rubyDelimiterEscape + syn region rubyString matchgroup=rubyStringDelimiter start="%s\z(\s\)" end="\z1" skip="\\\\\|\\\z1" +endif + +" Generalized Double Quoted String and Array of Strings and Shell Command Output {{{1 " Note: %= is not matched here as the beginning of a double quoted string -syn region rubyString matchgroup=rubyStringDelimiter start="%\z([~`!@#$%^&*_\-+|\:;"',.?/]\)" end="\z1" skip="\\\\\|\\\z1" contains=@rubyStringSpecial fold -syn region rubyString matchgroup=rubyStringDelimiter start="%[QWIx]\z([~`!@#$%^&*_\-+=|\:;"',.?/]\)" end="\z1" skip="\\\\\|\\\z1" contains=@rubyStringSpecial fold -syn region rubyString matchgroup=rubyStringDelimiter start="%[QWIx]\={" end="}" skip="\\\\\|\\}" contains=@rubyStringSpecial,rubyNestedCurlyBraces,rubyDelimEscape fold -syn region rubyString matchgroup=rubyStringDelimiter start="%[QWIx]\=<" end=">" skip="\\\\\|\\>" contains=@rubyStringSpecial,rubyNestedAngleBrackets,rubyDelimEscape fold -syn region rubyString matchgroup=rubyStringDelimiter start="%[QWIx]\=\[" end="\]" skip="\\\\\|\\\]" contains=@rubyStringSpecial,rubyNestedSquareBrackets,rubyDelimEscape fold -syn region rubyString matchgroup=rubyStringDelimiter start="%[QWIx]\=(" end=")" skip="\\\\\|\\)" contains=@rubyStringSpecial,rubyNestedParentheses,rubyDelimEscape fold -syn region rubyString matchgroup=rubyStringDelimiter start="%[Qx] " end=" " skip="\\\\\|\\)" contains=@rubyStringSpecial fold - -" Here Document -syn region rubyHeredocStart matchgroup=rubyStringDelimiter start=+\%(\%(class\s*\|\%([]})"'.]\|::\)\)\_s*\|\w\)\@<!<<-\=\zs\%(\%(\h\|[^\x00-\x7F]\)\%(\w\|[^\x00-\x7F]\)*\)+ end=+$+ oneline contains=ALLBUT,@rubyNotTop -syn region rubyHeredocStart matchgroup=rubyStringDelimiter start=+\%(\%(class\s*\|\%([]})"'.]\|::\)\)\_s*\|\w\)\@<!<<-\=\zs"\%([^"]*\)"+ end=+$+ oneline contains=ALLBUT,@rubyNotTop -syn region rubyHeredocStart matchgroup=rubyStringDelimiter start=+\%(\%(class\s*\|\%([]})"'.]\|::\)\)\_s*\|\w\)\@<!<<-\=\zs'\%([^']*\)'+ end=+$+ oneline contains=ALLBUT,@rubyNotTop -syn region rubyHeredocStart matchgroup=rubyStringDelimiter start=+\%(\%(class\s*\|\%([]})"'.]\|::\)\)\_s*\|\w\)\@<!<<-\=\zs`\%([^`]*\)`+ end=+$+ oneline contains=ALLBUT,@rubyNotTop - -syn region rubyString start=+\%(\%(class\|::\)\_s*\|\%([]})"'.]\)\s\|\w\)\@<!<<\z(\%(\h\|[^\x00-\x7F]\)\%(\w\|[^\x00-\x7F]\)*\)\ze\%(.*<<-\=['`"]\=\h\)\@!+hs=s+2 matchgroup=rubyStringDelimiter end=+^\z1$+ contains=rubyHeredocStart,rubyHeredoc,@rubyStringSpecial fold keepend -syn region rubyString start=+\%(\%(class\|::\)\_s*\|\%([]})"'.]\)\s\|\w\)\@<!<<"\z([^"]*\)"\ze\%(.*<<-\=['`"]\=\h\)\@!+hs=s+2 matchgroup=rubyStringDelimiter end=+^\z1$+ contains=rubyHeredocStart,rubyHeredoc,@rubyStringSpecial fold keepend -syn region rubyString start=+\%(\%(class\|::\)\_s*\|\%([]})"'.]\)\s\|\w\)\@<!<<'\z([^']*\)'\ze\%(.*<<-\=['`"]\=\h\)\@!+hs=s+2 matchgroup=rubyStringDelimiter end=+^\z1$+ contains=rubyHeredocStart,rubyHeredoc fold keepend -syn region rubyString start=+\%(\%(class\|::\)\_s*\|\%([]})"'.]\)\s\|\w\)\@<!<<`\z([^`]*\)`\ze\%(.*<<-\=['`"]\=\h\)\@!+hs=s+2 matchgroup=rubyStringDelimiter end=+^\z1$+ contains=rubyHeredocStart,rubyHeredoc,@rubyStringSpecial fold keepend - -syn region rubyString start=+\%(\%(class\|::\)\_s*\|\%([]}).]\)\s\|\w\)\@<!<<-\z(\%(\h\|[^\x00-\x7F]\)\%(\w\|[^\x00-\x7F]\)*\)\ze\%(.*<<-\=['`"]\=\h\)\@!+hs=s+3 matchgroup=rubyStringDelimiter end=+^\s*\zs\z1$+ contains=rubyHeredocStart,@rubyStringSpecial fold keepend -syn region rubyString start=+\%(\%(class\|::\)\_s*\|\%([]}).]\)\s\|\w\)\@<!<<-"\z([^"]*\)"\ze\%(.*<<-\=['`"]\=\h\)\@!+hs=s+3 matchgroup=rubyStringDelimiter end=+^\s*\zs\z1$+ contains=rubyHeredocStart,@rubyStringSpecial fold keepend -syn region rubyString start=+\%(\%(class\|::\)\_s*\|\%([]}).]\)\s\|\w\)\@<!<<-'\z([^']*\)'\ze\%(.*<<-\=['`"]\=\h\)\@!+hs=s+3 matchgroup=rubyStringDelimiter end=+^\s*\zs\z1$+ contains=rubyHeredocStart fold keepend -syn region rubyString start=+\%(\%(class\|::\)\_s*\|\%([]}).]\)\s\|\w\)\@<!<<-`\z([^`]*\)`\ze\%(.*<<-\=['`"]\=\h\)\@!+hs=s+3 matchgroup=rubyStringDelimiter end=+^\s*\zs\z1$+ contains=rubyHeredocStart,@rubyStringSpecial fold keepend +if s:foldable('%') + syn region rubyString matchgroup=rubyStringDelimiter start="%\z([~`!@#$%^&*_\-+|\:;"',.?/]\)" end="\z1" skip="\\\\\|\\\z1" contains=@rubyStringSpecial fold + syn region rubyString matchgroup=rubyStringDelimiter start="%[QWx]\z([~`!@#$%^&*_\-+=|\:;"',.?/]\)" end="\z1" skip="\\\\\|\\\z1" contains=@rubyStringSpecial fold + syn region rubyString matchgroup=rubyStringDelimiter start="%[QWx]\={" end="}" skip="\\\\\|\\}" contains=@rubyStringSpecial,rubyNestedCurlyBraces,rubyDelimiterEscape fold + syn region rubyString matchgroup=rubyStringDelimiter start="%[QWx]\=<" end=">" skip="\\\\\|\\>" contains=@rubyStringSpecial,rubyNestedAngleBrackets,rubyDelimiterEscape fold + syn region rubyString matchgroup=rubyStringDelimiter start="%[QWx]\=\[" end="\]" skip="\\\\\|\\\]" contains=@rubyStringSpecial,rubyNestedSquareBrackets,rubyDelimiterEscape fold + syn region rubyString matchgroup=rubyStringDelimiter start="%[QWx]\=(" end=")" skip="\\\\\|\\)" contains=@rubyStringSpecial,rubyNestedParentheses,rubyDelimiterEscape fold + syn region rubyString matchgroup=rubyStringDelimiter start="%[Qx]\z(\s\)" end="\z1" skip="\\\\\|\\\z1" contains=@rubyStringSpecial fold +else + syn region rubyString matchgroup=rubyStringDelimiter start="%\z([~`!@#$%^&*_\-+|\:;"',.?/]\)" end="\z1" skip="\\\\\|\\\z1" contains=@rubyStringSpecial + syn region rubyString matchgroup=rubyStringDelimiter start="%[QWx]\z([~`!@#$%^&*_\-+=|\:;"',.?/]\)" end="\z1" skip="\\\\\|\\\z1" contains=@rubyStringSpecial + syn region rubyString matchgroup=rubyStringDelimiter start="%[QWx]\={" end="}" skip="\\\\\|\\}" contains=@rubyStringSpecial,rubyNestedCurlyBraces,rubyDelimiterEscape + syn region rubyString matchgroup=rubyStringDelimiter start="%[QWx]\=<" end=">" skip="\\\\\|\\>" contains=@rubyStringSpecial,rubyNestedAngleBrackets,rubyDelimiterEscape + syn region rubyString matchgroup=rubyStringDelimiter start="%[QWx]\=\[" end="\]" skip="\\\\\|\\\]" contains=@rubyStringSpecial,rubyNestedSquareBrackets,rubyDelimiterEscape + syn region rubyString matchgroup=rubyStringDelimiter start="%[QWx]\=(" end=")" skip="\\\\\|\\)" contains=@rubyStringSpecial,rubyNestedParentheses,rubyDelimiterEscape + syn region rubyString matchgroup=rubyStringDelimiter start="%[Qx]\z(\s\)" end="\z1" skip="\\\\\|\\\z1" contains=@rubyStringSpecial +endif + +" Array of Symbols {{{1 +if s:foldable('%') + " Array of Symbols + syn region rubySymbol matchgroup=rubySymbolDelimiter start="%i\z([~`!@#$%^&*_\-+=|\:;"',.?/]\)" end="\z1" skip="\\\\\|\\\z1" fold + syn region rubySymbol matchgroup=rubySymbolDelimiter start="%i{" end="}" skip="\\\\\|\\}" fold contains=rubyNestedCurlyBraces,rubyDelimiterEscape + syn region rubySymbol matchgroup=rubySymbolDelimiter start="%i<" end=">" skip="\\\\\|\\>" fold contains=rubyNestedAngleBrackets,rubyDelimiterEscape + syn region rubySymbol matchgroup=rubySymbolDelimiter start="%i\[" end="\]" skip="\\\\\|\\\]" fold contains=rubyNestedSquareBrackets,rubyDelimiterEscape + syn region rubySymbol matchgroup=rubySymbolDelimiter start="%i(" end=")" skip="\\\\\|\\)" fold contains=rubyNestedParentheses,rubyDelimiterEscape + + " Array of interpolated Symbols + syn region rubySymbol matchgroup=rubySymbolDelimiter start="%I\z([~`!@#$%^&*_\-+=|\:;"',.?/]\)" end="\z1" skip="\\\\\|\\\z1" contains=@rubyStringSpecial fold + syn region rubySymbol matchgroup=rubySymbolDelimiter start="%I{" end="}" skip="\\\\\|\\}" contains=@rubyStringSpecial,rubyNestedCurlyBraces,rubyDelimiterEscape fold + syn region rubySymbol matchgroup=rubySymbolDelimiter start="%I<" end=">" skip="\\\\\|\\>" contains=@rubyStringSpecial,rubyNestedAngleBrackets,rubyDelimiterEscape fold + syn region rubySymbol matchgroup=rubySymbolDelimiter start="%I\[" end="\]" skip="\\\\\|\\\]" contains=@rubyStringSpecial,rubyNestedSquareBrackets,rubyDelimiterEscape fold + syn region rubySymbol matchgroup=rubySymbolDelimiter start="%I(" end=")" skip="\\\\\|\\)" contains=@rubyStringSpecial,rubyNestedParentheses,rubyDelimiterEscape fold +else + " Array of Symbols + syn region rubySymbol matchgroup=rubySymbolDelimiter start="%i\z([~`!@#$%^&*_\-+=|\:;"',.?/]\)" end="\z1" skip="\\\\\|\\\z1" + syn region rubySymbol matchgroup=rubySymbolDelimiter start="%i{" end="}" skip="\\\\\|\\}" contains=rubyNestedCurlyBraces,rubyDelimiterEscape + syn region rubySymbol matchgroup=rubySymbolDelimiter start="%i<" end=">" skip="\\\\\|\\>" contains=rubyNestedAngleBrackets,rubyDelimiterEscape + syn region rubySymbol matchgroup=rubySymbolDelimiter start="%i\[" end="\]" skip="\\\\\|\\\]" contains=rubyNestedSquareBrackets,rubyDelimiterEscape + syn region rubySymbol matchgroup=rubySymbolDelimiter start="%i(" end=")" skip="\\\\\|\\)" contains=rubyNestedParentheses,rubyDelimiterEscape + + " Array of interpolated Symbols + syn region rubySymbol matchgroup=rubySymbolDelimiter start="%I\z([~`!@#$%^&*_\-+=|\:;"',.?/]\)" end="\z1" skip="\\\\\|\\\z1" contains=@rubyStringSpecial + syn region rubySymbol matchgroup=rubySymbolDelimiter start="%I{" end="}" skip="\\\\\|\\}" contains=@rubyStringSpecial,rubyNestedCurlyBraces,rubyDelimiterEscape + syn region rubySymbol matchgroup=rubySymbolDelimiter start="%I<" end=">" skip="\\\\\|\\>" contains=@rubyStringSpecial,rubyNestedAngleBrackets,rubyDelimiterEscape + syn region rubySymbol matchgroup=rubySymbolDelimiter start="%I\[" end="\]" skip="\\\\\|\\\]" contains=@rubyStringSpecial,rubyNestedSquareBrackets,rubyDelimiterEscape + syn region rubySymbol matchgroup=rubySymbolDelimiter start="%I(" end=")" skip="\\\\\|\\)" contains=@rubyStringSpecial,rubyNestedParentheses,rubyDelimiterEscape +endif + +" Here Document {{{1 +syn region rubyHeredocStart matchgroup=rubyStringDelimiter start=+\%(\%(class\s*\|\%([]})"'.]\|::\)\)\_s*\|\w\)\@<!<<[-~]\=\zs\%(\%(\h\|[^\x00-\x7F]\)\%(\w\|[^\x00-\x7F]\)*\)+ end=+$+ oneline contains=ALLBUT,@rubyNotTop +syn region rubyHeredocStart matchgroup=rubyStringDelimiter start=+\%(\%(class\s*\|\%([]})"'.]\|::\)\)\_s*\|\w\)\@<!<<[-~]\=\zs"\%([^"]*\)"+ end=+$+ oneline contains=ALLBUT,@rubyNotTop +syn region rubyHeredocStart matchgroup=rubyStringDelimiter start=+\%(\%(class\s*\|\%([]})"'.]\|::\)\)\_s*\|\w\)\@<!<<[-~]\=\zs'\%([^']*\)'+ end=+$+ oneline contains=ALLBUT,@rubyNotTop +syn region rubyHeredocStart matchgroup=rubyStringDelimiter start=+\%(\%(class\s*\|\%([]})"'.]\|::\)\)\_s*\|\w\)\@<!<<[-~]\=\zs`\%([^`]*\)`+ end=+$+ oneline contains=ALLBUT,@rubyNotTop + +if s:foldable('<<') + syn region rubyString start=+\%(\%(class\|::\)\_s*\|\%([]})"'.]\)\s\|\w\)\@<!<<\z(\%(\h\|[^\x00-\x7F]\)\%(\w\|[^\x00-\x7F]\)*\)\ze\%(.*<<[-~]\=['`"]\=\h\)\@!+hs=s+2 matchgroup=rubyStringDelimiter end=+^\z1$+ contains=rubyHeredocStart,rubyHeredoc,@rubyStringSpecial fold keepend + syn region rubyString start=+\%(\%(class\|::\)\_s*\|\%([]})"'.]\)\s\|\w\)\@<!<<"\z([^"]*\)"\ze\%(.*<<[-~]\=['`"]\=\h\)\@!+hs=s+2 matchgroup=rubyStringDelimiter end=+^\z1$+ contains=rubyHeredocStart,rubyHeredoc,@rubyStringSpecial fold keepend + syn region rubyString start=+\%(\%(class\|::\)\_s*\|\%([]})"'.]\)\s\|\w\)\@<!<<'\z([^']*\)'\ze\%(.*<<[-~]\=['`"]\=\h\)\@!+hs=s+2 matchgroup=rubyStringDelimiter end=+^\z1$+ contains=rubyHeredocStart,rubyHeredoc fold keepend + syn region rubyString start=+\%(\%(class\|::\)\_s*\|\%([]})"'.]\)\s\|\w\)\@<!<<`\z([^`]*\)`\ze\%(.*<<[-~]\=['`"]\=\h\)\@!+hs=s+2 matchgroup=rubyStringDelimiter end=+^\z1$+ contains=rubyHeredocStart,rubyHeredoc,@rubyStringSpecial fold keepend + + syn region rubyString start=+\%(\%(class\|::\)\_s*\|\%([]}).]\)\s\|\w\)\@<!<<[-~]\z(\%(\h\|[^\x00-\x7F]\)\%(\w\|[^\x00-\x7F]\)*\)\ze\%(.*<<[-~]\=['`"]\=\h\)\@!+hs=s+3 matchgroup=rubyStringDelimiter end=+^\s*\zs\z1$+ contains=rubyHeredocStart,@rubyStringSpecial fold keepend + syn region rubyString start=+\%(\%(class\|::\)\_s*\|\%([]}).]\)\s\|\w\)\@<!<<[-~]"\z([^"]*\)"\ze\%(.*<<[-~]\=['`"]\=\h\)\@!+hs=s+3 matchgroup=rubyStringDelimiter end=+^\s*\zs\z1$+ contains=rubyHeredocStart,@rubyStringSpecial fold keepend + syn region rubyString start=+\%(\%(class\|::\)\_s*\|\%([]}).]\)\s\|\w\)\@<!<<[-~]'\z([^']*\)'\ze\%(.*<<[-~]\=['`"]\=\h\)\@!+hs=s+3 matchgroup=rubyStringDelimiter end=+^\s*\zs\z1$+ contains=rubyHeredocStart fold keepend + syn region rubyString start=+\%(\%(class\|::\)\_s*\|\%([]}).]\)\s\|\w\)\@<!<<[-~]`\z([^`]*\)`\ze\%(.*<<[-~]\=['`"]\=\h\)\@!+hs=s+3 matchgroup=rubyStringDelimiter end=+^\s*\zs\z1$+ contains=rubyHeredocStart,@rubyStringSpecial fold keepend +else + syn region rubyString start=+\%(\%(class\|::\)\_s*\|\%([]})"'.]\)\s\|\w\)\@<!<<\z(\%(\h\|[^\x00-\x7F]\)\%(\w\|[^\x00-\x7F]\)*\)\ze\%(.*<<[-~]\=['`"]\=\h\)\@!+hs=s+2 matchgroup=rubyStringDelimiter end=+^\z1$+ contains=rubyHeredocStart,rubyHeredoc,@rubyStringSpecial keepend + syn region rubyString start=+\%(\%(class\|::\)\_s*\|\%([]})"'.]\)\s\|\w\)\@<!<<"\z([^"]*\)"\ze\%(.*<<[-~]\=['`"]\=\h\)\@!+hs=s+2 matchgroup=rubyStringDelimiter end=+^\z1$+ contains=rubyHeredocStart,rubyHeredoc,@rubyStringSpecial keepend + syn region rubyString start=+\%(\%(class\|::\)\_s*\|\%([]})"'.]\)\s\|\w\)\@<!<<'\z([^']*\)'\ze\%(.*<<[-~]\=['`"]\=\h\)\@!+hs=s+2 matchgroup=rubyStringDelimiter end=+^\z1$+ contains=rubyHeredocStart,rubyHeredoc keepend + syn region rubyString start=+\%(\%(class\|::\)\_s*\|\%([]})"'.]\)\s\|\w\)\@<!<<`\z([^`]*\)`\ze\%(.*<<[-~]\=['`"]\=\h\)\@!+hs=s+2 matchgroup=rubyStringDelimiter end=+^\z1$+ contains=rubyHeredocStart,rubyHeredoc,@rubyStringSpecial keepend + + syn region rubyString start=+\%(\%(class\|::\)\_s*\|\%([]}).]\)\s\|\w\)\@<!<<[-~]\z(\%(\h\|[^\x00-\x7F]\)\%(\w\|[^\x00-\x7F]\)*\)\ze\%(.*<<[-~]\=['`"]\=\h\)\@!+hs=s+3 matchgroup=rubyStringDelimiter end=+^\s*\zs\z1$+ contains=rubyHeredocStart,@rubyStringSpecial keepend + syn region rubyString start=+\%(\%(class\|::\)\_s*\|\%([]}).]\)\s\|\w\)\@<!<<[-~]"\z([^"]*\)"\ze\%(.*<<[-~]\=['`"]\=\h\)\@!+hs=s+3 matchgroup=rubyStringDelimiter end=+^\s*\zs\z1$+ contains=rubyHeredocStart,@rubyStringSpecial keepend + syn region rubyString start=+\%(\%(class\|::\)\_s*\|\%([]}).]\)\s\|\w\)\@<!<<[-~]'\z([^']*\)'\ze\%(.*<<[-~]\=['`"]\=\h\)\@!+hs=s+3 matchgroup=rubyStringDelimiter end=+^\s*\zs\z1$+ contains=rubyHeredocStart keepend + syn region rubyString start=+\%(\%(class\|::\)\_s*\|\%([]}).]\)\s\|\w\)\@<!<<[-~]`\z([^`]*\)`\ze\%(.*<<[-~]\=['`"]\=\h\)\@!+hs=s+3 matchgroup=rubyStringDelimiter end=+^\s*\zs\z1$+ contains=rubyHeredocStart,@rubyStringSpecial keepend +endif +" eRuby Config {{{1 if exists('main_syntax') && main_syntax == 'eruby' let b:ruby_no_expensive = 1 end +" Module, Class, Method and Alias Declarations {{{1 syn match rubyAliasDeclaration "[^[:space:];#.()]\+" contained contains=rubySymbol,rubyGlobalVariable,rubyPredefinedVariable nextgroup=rubyAliasDeclaration2 skipwhite syn match rubyAliasDeclaration2 "[^[:space:];#.()]\+" contained contains=rubySymbol,rubyGlobalVariable,rubyPredefinedVariable syn match rubyMethodDeclaration "[^[:space:];#(]\+" contained contains=rubyConstant,rubyBoolean,rubyPseudoVariable,rubyInstanceVariable,rubyClassVariable,rubyGlobalVariable syn match rubyClassDeclaration "[^[:space:];#<]\+" contained contains=rubyConstant,rubyOperator syn match rubyModuleDeclaration "[^[:space:];#<]\+" contained contains=rubyConstant,rubyOperator syn match rubyFunction "\<[_[:alpha:]][_[:alnum:]]*[?!=]\=[[:alnum:]_.:?!=]\@!" contained containedin=rubyMethodDeclaration -syn match rubyFunction "\%(\s\|^\)\@<=[_[:alpha:]][_[:alnum:]]*[?!=]\=\%(\s\|$\)\@=" contained containedin=rubyAliasDeclaration,rubyAliasDeclaration2 -syn match rubyFunction "\%([[:space:].]\|^\)\@<=\%(\[\]=\=\|\*\*\|[+-]@\=\|[*/%|&^~]\|<<\|>>\|[<>]=\=\|<=>\|===\|[=!]=\|[=!]\~\|!\|`\)\%([[:space:];#(]\|$\)\@=" contained containedin=rubyAliasDeclaration,rubyAliasDeclaration2,rubyMethodDeclaration +syn match rubyFunction "\%(\s\|^\)\@1<=[_[:alpha:]][_[:alnum:]]*[?!=]\=\%(\s\|$\)\@=" contained containedin=rubyAliasDeclaration,rubyAliasDeclaration2 +syn match rubyFunction "\%([[:space:].]\|^\)\@2<=\%(\[\]=\=\|\*\*\|[-+!~]@\=\|[*/%|&^~]\|<<\|>>\|[<>]=\=\|<=>\|===\|[=!]=\|[=!]\~\|!\|`\)\%([[:space:];#(]\|$\)\@=" contained containedin=rubyAliasDeclaration,rubyAliasDeclaration2,rubyMethodDeclaration syn cluster rubyDeclaration contains=rubyAliasDeclaration,rubyAliasDeclaration2,rubyMethodDeclaration,rubyModuleDeclaration,rubyClassDeclaration,rubyFunction,rubyBlockParameter -" Keywords +" Keywords {{{1 " Note: the following keywords have already been defined: " begin case class def do end for if module unless until while syn match rubyControl "\<\%(and\|break\|in\|next\|not\|or\|redo\|rescue\|retry\|return\)\>[?!]\@!" syn match rubyOperator "\<defined?" display syn match rubyKeyword "\<\%(super\|yield\)\>[?!]\@!" syn match rubyBoolean "\<\%(true\|false\)\>[?!]\@!" -syn match rubyPseudoVariable "\<\%(nil\|self\|__ENCODING__\|__FILE__\|__LINE__\|__callee__\|__method__\)\>[?!]\@!" " TODO: reorganise +syn match rubyPseudoVariable "\<\%(nil\|self\|__ENCODING__\|__dir__\|__FILE__\|__LINE__\|__callee__\|__method__\)\>[?!]\@!" " TODO: reorganise syn match rubyBeginEnd "\<\%(BEGIN\|END\)\>[?!]\@!" -" Expensive Mode - match 'end' with the appropriate opening keyword for syntax -" based folding and special highlighting of module/class/method definitions +" Expensive Mode {{{1 +" Match 'end' with the appropriate opening keyword for syntax based folding +" and special highlighting of module/class/method definitions if !exists("b:ruby_no_expensive") && !exists("ruby_no_expensive") syn match rubyDefine "\<alias\>" nextgroup=rubyAliasDeclaration skipwhite skipnl syn match rubyDefine "\<def\>" nextgroup=rubyMethodDeclaration skipwhite skipnl @@ -211,23 +339,66 @@ if !exists("b:ruby_no_expensive") && !exists("ruby_no_expensive") syn match rubyClass "\<class\>" nextgroup=rubyClassDeclaration skipwhite skipnl syn match rubyModule "\<module\>" nextgroup=rubyModuleDeclaration skipwhite skipnl - syn region rubyMethodBlock start="\<def\>" matchgroup=rubyDefine end="\%(\<def\_s\+\)\@<!\<end\>" contains=ALLBUT,@rubyNotTop fold - syn region rubyBlock start="\<class\>" matchgroup=rubyClass end="\<end\>" contains=ALLBUT,@rubyNotTop fold - syn region rubyBlock start="\<module\>" matchgroup=rubyModule end="\<end\>" contains=ALLBUT,@rubyNotTop fold + if s:foldable('def') + syn region rubyMethodBlock start="\<def\>" matchgroup=rubyDefine end="\%(\<def\_s\+\)\@<!\<end\>" contains=ALLBUT,@rubyNotTop fold + else + syn region rubyMethodBlock start="\<def\>" matchgroup=rubyDefine end="\%(\<def\_s\+\)\@<!\<end\>" contains=ALLBUT,@rubyNotTop + endif + + if s:foldable('class') + syn region rubyBlock start="\<class\>" matchgroup=rubyClass end="\<end\>" contains=ALLBUT,@rubyNotTop fold + else + syn region rubyBlock start="\<class\>" matchgroup=rubyClass end="\<end\>" contains=ALLBUT,@rubyNotTop + endif + + if s:foldable('module') + syn region rubyBlock start="\<module\>" matchgroup=rubyModule end="\<end\>" contains=ALLBUT,@rubyNotTop fold + else + syn region rubyBlock start="\<module\>" matchgroup=rubyModule end="\<end\>" contains=ALLBUT,@rubyNotTop + endif " modifiers - syn match rubyConditionalModifier "\<\%(if\|unless\)\>" display - syn match rubyRepeatModifier "\<\%(while\|until\)\>" display + syn match rubyLineContinuation "\\$" nextgroup=rubyConditionalModifier,rubyRepeatModifier skipwhite skipnl + syn match rubyConditionalModifier "\<\%(if\|unless\)\>" + syn match rubyRepeatModifier "\<\%(while\|until\)\>" + + if s:foldable('do') + syn region rubyDoBlock matchgroup=rubyControl start="\<do\>" end="\<end\>" contains=ALLBUT,@rubyNotTop fold + else + syn region rubyDoBlock matchgroup=rubyControl start="\<do\>" end="\<end\>" contains=ALLBUT,@rubyNotTop + endif - syn region rubyDoBlock matchgroup=rubyControl start="\<do\>" end="\<end\>" contains=ALLBUT,@rubyNotTop fold " curly bracket block or hash literal - syn region rubyCurlyBlock matchgroup=rubyCurlyBlockDelimiter start="{" end="}" contains=ALLBUT,@rubyNotTop fold - syn region rubyArrayLiteral matchgroup=rubyArrayDelimiter start="\%(\w\|[\]})]\)\@<!\[" end="]" contains=ALLBUT,@rubyNotTop fold + if s:foldable('{') + syn region rubyCurlyBlock matchgroup=rubyCurlyBlockDelimiter start="{" end="}" contains=ALLBUT,@rubyNotTop fold + else + syn region rubyCurlyBlock matchgroup=rubyCurlyBlockDelimiter start="{" end="}" contains=ALLBUT,@rubyNotTop + endif + + if s:foldable('[') + syn region rubyArrayLiteral matchgroup=rubyArrayDelimiter start="\%(\w\|[\]})]\)\@<!\[" end="]" contains=ALLBUT,@rubyNotTop fold + else + syn region rubyArrayLiteral matchgroup=rubyArrayDelimiter start="\%(\w\|[\]})]\)\@<!\[" end="]" contains=ALLBUT,@rubyNotTop + endif " statements without 'do' - syn region rubyBlockExpression matchgroup=rubyControl start="\<begin\>" end="\<end\>" contains=ALLBUT,@rubyNotTop fold - syn region rubyCaseExpression matchgroup=rubyConditional start="\<case\>" end="\<end\>" contains=ALLBUT,@rubyNotTop fold - syn region rubyConditionalExpression matchgroup=rubyConditional start="\%(\%(^\|\.\.\.\=\|[{:,;([<>~\*/%&^|+=-]\|\%(\<[_[:lower:]][_[:alnum:]]*\)\@<![?!]\)\s*\)\@<=\%(if\|unless\)\>" end="\%(\%(\%(\.\@<!\.\)\|::\)\s*\)\@<!\<end\>" contains=ALLBUT,@rubyNotTop fold + if s:foldable('begin') + syn region rubyBlockExpression matchgroup=rubyControl start="\<begin\>" end="\<end\>" contains=ALLBUT,@rubyNotTop fold + else + syn region rubyBlockExpression matchgroup=rubyControl start="\<begin\>" end="\<end\>" contains=ALLBUT,@rubyNotTop + endif + + if s:foldable('case') + syn region rubyCaseExpression matchgroup=rubyConditional start="\<case\>" end="\<end\>" contains=ALLBUT,@rubyNotTop fold + else + syn region rubyCaseExpression matchgroup=rubyConditional start="\<case\>" end="\<end\>" contains=ALLBUT,@rubyNotTop + endif + + if s:foldable('if') + syn region rubyConditionalExpression matchgroup=rubyConditional start="\%(\%(^\|\.\.\.\=\|[{:,;([<>~\*%&^|+=-]\|\%(\<[_[:lower:]][_[:alnum:]]*\)\@<![?!]\)\s*\)\@<=\%(if\|unless\)\>" end="\%(\%(\%(\.\@1<!\.\)\|::\)\s*\)\@<!\<end\>" contains=ALLBUT,@rubyNotTop fold + else + syn region rubyConditionalExpression matchgroup=rubyConditional start="\%(\%(^\|\.\.\.\=\|[{:,;([<>~\*%&^|+=-]\|\%(\<[_[:lower:]][_[:alnum:]]*\)\@<![?!]\)\s*\)\@<=\%(if\|unless\)\>" end="\%(\%(\%(\.\@1<!\.\)\|::\)\s*\)\@<!\<end\>" contains=ALLBUT,@rubyNotTop + endif syn match rubyConditional "\<\%(then\|else\|when\)\>[?!]\@!" contained containedin=rubyCaseExpression syn match rubyConditional "\<\%(then\|else\|elsif\)\>[?!]\@!" contained containedin=rubyConditionalExpression @@ -237,7 +408,12 @@ if !exists("b:ruby_no_expensive") && !exists("ruby_no_expensive") " statements with optional 'do' syn region rubyOptionalDoLine matchgroup=rubyRepeat start="\<for\>[?!]\@!" start="\%(\%(^\|\.\.\.\=\|[{:,;([<>~\*/%&^|+-]\|\%(\<[_[:lower:]][_[:alnum:]]*\)\@<![!=?]\)\s*\)\@<=\<\%(until\|while\)\>" matchgroup=rubyOptionalDo end="\%(\<do\>\)" end="\ze\%(;\|$\)" oneline contains=ALLBUT,@rubyNotTop - syn region rubyRepeatExpression start="\<for\>[?!]\@!" start="\%(\%(^\|\.\.\.\=\|[{:,;([<>~\*/%&^|+-]\|\%(\<[_[:lower:]][_[:alnum:]]*\)\@<![!=?]\)\s*\)\@<=\<\%(until\|while\)\>" matchgroup=rubyRepeat end="\<end\>" contains=ALLBUT,@rubyNotTop nextgroup=rubyOptionalDoLine fold + + if s:foldable('for') + syn region rubyRepeatExpression start="\<for\>[?!]\@!" start="\%(\%(^\|\.\.\.\=\|[{:,;([<>~\*/%&^|+-]\|\%(\<[_[:lower:]][_[:alnum:]]*\)\@<![!=?]\)\s*\)\@<=\<\%(until\|while\)\>" matchgroup=rubyRepeat end="\<end\>" contains=ALLBUT,@rubyNotTop nextgroup=rubyOptionalDoLine fold + else + syn region rubyRepeatExpression start="\<for\>[?!]\@!" start="\%(\%(^\|\.\.\.\=\|[{:,;([<>~\*/%&^|+-]\|\%(\<[_[:lower:]][_[:alnum:]]*\)\@<![!=?]\)\s*\)\@<=\<\%(until\|while\)\>" matchgroup=rubyRepeat end="\<end\>" contains=ALLBUT,@rubyNotTop nextgroup=rubyOptionalDoLine + endif if !exists("ruby_minlines") let ruby_minlines = 500 @@ -252,7 +428,7 @@ else syn match rubyKeyword "\<\%(alias\|undef\)\>[?!]\@!" endif -" Special Methods +" Special Methods {{{1 if !exists("ruby_no_special_methods") syn keyword rubyAccess public protected private public_class_method private_class_method public_constant private_constant module_function " attr is a common variable name @@ -263,40 +439,40 @@ if !exists("ruby_no_special_methods") syn keyword rubyException raise fail catch throw " false positive with 'include?' syn match rubyInclude "\<include\>[?!]\@!" - syn keyword rubyInclude autoload extend load prepend require require_relative + syn keyword rubyInclude autoload extend load prepend refine require require_relative using syn keyword rubyKeyword callcc caller lambda proc endif -" Comments and Documentation +" Comments and Documentation {{{1 syn match rubySharpBang "\%^#!.*" display -syn keyword rubyTodo FIXME NOTE TODO OPTIMIZE XXX todo contained +syn keyword rubyTodo FIXME NOTE TODO OPTIMIZE HACK REVIEW XXX todo contained syn match rubyComment "#.*" contains=rubySharpBang,rubySpaceError,rubyTodo,@Spell -if !exists("ruby_no_comment_fold") - syn region rubyMultilineComment start="\%(\%(^\s*#.*\n\)\@<!\%(^\s*#.*\n\)\)\%(\(^\s*#.*\n\)\{1,}\)\@=" end="\%(^\s*#.*\n\)\@<=\%(^\s*#.*\n\)\%(^\s*#\)\@!" contains=rubyComment transparent fold keepend +if !exists("ruby_no_comment_fold") && s:foldable('#') + syn region rubyMultilineComment start="^\s*#.*\n\%(^\s*#\)\@=" end="^\s*#.*\n\%(^\s*#\)\@!" contains=rubyComment transparent fold keepend syn region rubyDocumentation start="^=begin\ze\%(\s.*\)\=$" end="^=end\%(\s.*\)\=$" contains=rubySpaceError,rubyTodo,@Spell fold else syn region rubyDocumentation start="^=begin\s*$" end="^=end\s*$" contains=rubySpaceError,rubyTodo,@Spell endif +" Keyword Nobbling {{{1 " Note: this is a hack to prevent 'keywords' being highlighted as such when called as methods with an explicit receiver -syn match rubyKeywordAsMethod "\%(\%(\.\@<!\.\)\|::\)\_s*\%(alias\|and\|begin\|break\|case\|class\|def\|defined\|do\|else\)\>" transparent contains=NONE -syn match rubyKeywordAsMethod "\%(\%(\.\@<!\.\)\|::\)\_s*\%(elsif\|end\|ensure\|false\|for\|if\|in\|module\|next\|nil\)\>" transparent contains=NONE -syn match rubyKeywordAsMethod "\%(\%(\.\@<!\.\)\|::\)\_s*\%(not\|or\|redo\|rescue\|retry\|return\|self\|super\|then\|true\)\>" transparent contains=NONE -syn match rubyKeywordAsMethod "\%(\%(\.\@<!\.\)\|::\)\_s*\%(undef\|unless\|until\|when\|while\|yield\|BEGIN\|END\|__FILE__\|__LINE__\)\>" transparent contains=NONE - -syn match rubyKeywordAsMethod "\<\%(alias\|begin\|case\|class\|def\|do\|end\)[?!]" transparent contains=NONE -syn match rubyKeywordAsMethod "\<\%(if\|module\|undef\|unless\|until\|while\)[?!]" transparent contains=NONE - -syn match rubyKeywordAsMethod "\%(\%(\.\@<!\.\)\|::\)\_s*\%(abort\|at_exit\|attr\|attr_accessor\|attr_reader\)\>" transparent contains=NONE -syn match rubyKeywordAsMethod "\%(\%(\.\@<!\.\)\|::\)\_s*\%(attr_writer\|autoload\|callcc\|catch\|caller\)\>" transparent contains=NONE -syn match rubyKeywordAsMethod "\%(\%(\.\@<!\.\)\|::\)\_s*\%(eval\|class_eval\|instance_eval\|module_eval\|exit\)\>" transparent contains=NONE -syn match rubyKeywordAsMethod "\%(\%(\.\@<!\.\)\|::\)\_s*\%(extend\|fail\|fork\|include\|lambda\)\>" transparent contains=NONE -syn match rubyKeywordAsMethod "\%(\%(\.\@<!\.\)\|::\)\_s*\%(load\|loop\|prepend\|private\|proc\|protected\)\>" transparent contains=NONE -syn match rubyKeywordAsMethod "\%(\%(\.\@<!\.\)\|::\)\_s*\%(public\|require\|require_relative\|raise\|throw\|trap\)\>" transparent contains=NONE - -" __END__ Directive -syn region rubyData matchgroup=rubyDataDirective start="^__END__$" end="\%$" fold +syn match rubyKeywordAsMethod "\%(\%(\.\@1<!\.\)\|::\)\_s*\%([_[:lower:]][_[:alnum:]]*\|\<\%(BEGIN\|END\)\>\)" transparent contains=NONE +syn match rubyKeywordAsMethod "\(defined?\|exit!\)\@!\<[_[:lower:]][_[:alnum:]]*[?!]" transparent contains=NONE + +" More Symbols {{{1 +syn match rubySymbol "\%([{(,]\_s*\)\zs\l\w*[!?]\=::\@!"he=e-1 +syn match rubySymbol "[]})\"':]\@1<!\%(\h\|[^\x00-\x7F]\)\%(\w\|[^\x00-\x7F]\)*[!?]\=:[[:space:],]\@="he=e-1 +syn match rubySymbol "\%([{(,]\_s*\)\zs[[:space:],{]\l\w*[!?]\=::\@!"hs=s+1,he=e-1 +syn match rubySymbol "[[:space:],{(]\%(\h\|[^\x00-\x7F]\)\%(\w\|[^\x00-\x7F]\)*[!?]\=:[[:space:],]\@="hs=s+1,he=e-1 + +" __END__ Directive {{{1 +if s:foldable('__END__') + syn region rubyData matchgroup=rubyDataDirective start="^__END__$" end="\%$" fold +else + syn region rubyData matchgroup=rubyDataDirective start="^__END__$" end="\%$" +endif +" Default Highlighting {{{1 hi def link rubyClass rubyDefine hi def link rubyModule rubyDefine hi def link rubyMethodExceptional rubyDefine @@ -336,6 +512,7 @@ hi def link rubyAccess Statement hi def link rubyAttribute Statement hi def link rubyEval Statement hi def link rubyPseudoVariable Constant +hi def link rubyCapitalizedMethod rubyLocalVariableOrMethod hi def link rubyComment Comment hi def link rubyData Comment @@ -349,7 +526,7 @@ hi def link rubyInterpolationDelimiter Delimiter hi def link rubyNoInterpolation rubyString hi def link rubySharpBang PreProc hi def link rubyRegexpDelimiter rubyStringDelimiter -hi def link rubySymbolDelimiter rubyStringDelimiter +hi def link rubySymbolDelimiter rubySymbol hi def link rubyStringDelimiter Delimiter hi def link rubyHeredoc rubyString hi def link rubyString String @@ -366,6 +543,10 @@ hi def link rubyInvalidVariable Error hi def link rubyError Error hi def link rubySpaceError rubyError +" Postscript {{{1 let b:current_syntax = "ruby" -" vim: nowrap sw=2 sts=2 ts=8 noet: +let &cpo = s:cpo_sav +unlet! s:cpo_sav + +" vim: nowrap sw=2 sts=2 ts=8 noet fdm=marker: diff --git a/runtime/syntax/samba.vim b/runtime/syntax/samba.vim index 93029cc202..5b866cc6d9 100644 --- a/runtime/syntax/samba.vim +++ b/runtime/syntax/samba.vim @@ -8,11 +8,8 @@ " " Don't forget to run your config file through testparm(1)! -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -107,24 +104,14 @@ syn keyword sambaKeyword contained shutdown signing special spnego syn keyword sambaKeyword contained store unknown unwriteable " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_samba_syn_inits") - if version < 508 - let did_samba_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - HiLink sambaParameter Normal - HiLink sambaKeyword Type - HiLink sambaSection Statement - HiLink sambaMacro PreProc - HiLink sambaComment Comment - HiLink sambaContinue Operator - HiLink sambaBoolean Constant - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet +hi def link sambaParameter Normal +hi def link sambaKeyword Type +hi def link sambaSection Statement +hi def link sambaMacro PreProc +hi def link sambaComment Comment +hi def link sambaContinue Operator +hi def link sambaBoolean Constant let b:current_syntax = "samba" diff --git a/runtime/syntax/sas.vim b/runtime/syntax/sas.vim index dc70e1fd90..90d411dc8b 100644 --- a/runtime/syntax/sas.vim +++ b/runtime/syntax/sas.vim @@ -12,11 +12,8 @@ " Attempted to match SAS default syntax colors; " Changed syncing so it doesn't lose colors on large blocks; " Much thanks to Bob Heckel for knowledgeable tweaking. -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -44,7 +41,7 @@ syn region sasComment start=";\s*\*"hs=s+1 end=";" contains=sasTodo " Comments with * starting after a semicolon (Paulo Tanimoto) syn region sasComment start="^\s*\*" end=";" contains=sasTodo -" This line defines macro variables in code. HiLink at end of file +" This line defines macro variables in code. "hi def link" at end of file " defines the color scheme. Begin region with ampersand and end with " any non-word character offset by -1; put ampersand in the skip list " just in case it is used to concatenate macro variable values. @@ -52,11 +49,7 @@ syn region sasComment start="^\s*\*" end=";" contains=sasTodo " Thanks to ronald h๖llwarth for this fix to an intra-versioning " problem with this little feature -if version < 600 - syn region sasMacroVar start="\&" skip="[_&]" end="\W"he=e-1 -else " for the older Vim's just do it their way ... - syn region sasMacroVar start="&" skip="[_&]" end="\W"he=e-1 -endif +syn region sasMacroVar start="&" skip="[_&]" end="\W"he=e-1 " I dont think specific PROCs need to be listed if use this line (Bob Heckel). @@ -218,62 +211,52 @@ syn keyword sasUnderscore _ALL_ _AUTOMATIC_ _CHARACTER_ _INFILE_ _N_ _NAME_ _NUL " End of SAS Functions " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet - -if version >= 508 || !exists("did_sas_syntax_inits") - if version < 508 - let did_sas_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - " Default sas enhanced editor color syntax - hi sComment term=bold cterm=NONE ctermfg=Green ctermbg=Black gui=NONE guifg=DarkGreen guibg=White - hi sCard term=bold cterm=NONE ctermfg=Black ctermbg=Yellow gui=NONE guifg=Black guibg=LightYellow - hi sDate_Time term=NONE cterm=bold ctermfg=Green ctermbg=Black gui=bold guifg=SeaGreen guibg=White - hi sKeyword term=NONE cterm=NONE ctermfg=Blue ctermbg=Black gui=NONE guifg=Blue guibg=White - hi sFmtInfmt term=NONE cterm=NONE ctermfg=LightGreen ctermbg=Black gui=NONE guifg=SeaGreen guibg=White - hi sString term=NONE cterm=NONE ctermfg=Magenta ctermbg=Black gui=NONE guifg=Purple guibg=White - hi sText term=NONE cterm=NONE ctermfg=White ctermbg=Black gui=bold guifg=Black guibg=White - hi sNumber term=NONE cterm=bold ctermfg=Green ctermbg=Black gui=bold guifg=SeaGreen guibg=White - hi sProc term=NONE cterm=bold ctermfg=Blue ctermbg=Black gui=bold guifg=Navy guibg=White - hi sSection term=NONE cterm=bold ctermfg=Blue ctermbg=Black gui=bold guifg=Navy guibg=White - hi mDefine term=NONE cterm=bold ctermfg=White ctermbg=Black gui=bold guifg=Black guibg=White - hi mKeyword term=NONE cterm=NONE ctermfg=Blue ctermbg=Black gui=NONE guifg=Blue guibg=White - hi mReference term=NONE cterm=bold ctermfg=White ctermbg=Black gui=bold guifg=Blue guibg=White - hi mSection term=NONE cterm=NONE ctermfg=Blue ctermbg=Black gui=bold guifg=Navy guibg=White - hi mText term=NONE cterm=NONE ctermfg=White ctermbg=Black gui=bold guifg=Black guibg=White +" Only when an item doesn't have highlighting yet + + +" Default sas enhanced editor color syntax +hi sComment term=bold cterm=NONE ctermfg=Green ctermbg=Black gui=NONE guifg=DarkGreen guibg=White +hi sCard term=bold cterm=NONE ctermfg=Black ctermbg=Yellow gui=NONE guifg=Black guibg=LightYellow +hi sDate_Time term=NONE cterm=bold ctermfg=Green ctermbg=Black gui=bold guifg=SeaGreen guibg=White +hi sKeyword term=NONE cterm=NONE ctermfg=Blue ctermbg=Black gui=NONE guifg=Blue guibg=White +hi sFmtInfmt term=NONE cterm=NONE ctermfg=LightGreen ctermbg=Black gui=NONE guifg=SeaGreen guibg=White +hi sString term=NONE cterm=NONE ctermfg=Magenta ctermbg=Black gui=NONE guifg=Purple guibg=White +hi sText term=NONE cterm=NONE ctermfg=White ctermbg=Black gui=bold guifg=Black guibg=White +hi sNumber term=NONE cterm=bold ctermfg=Green ctermbg=Black gui=bold guifg=SeaGreen guibg=White +hi sProc term=NONE cterm=bold ctermfg=Blue ctermbg=Black gui=bold guifg=Navy guibg=White +hi sSection term=NONE cterm=bold ctermfg=Blue ctermbg=Black gui=bold guifg=Navy guibg=White +hi mDefine term=NONE cterm=bold ctermfg=White ctermbg=Black gui=bold guifg=Black guibg=White +hi mKeyword term=NONE cterm=NONE ctermfg=Blue ctermbg=Black gui=NONE guifg=Blue guibg=White +hi mReference term=NONE cterm=bold ctermfg=White ctermbg=Black gui=bold guifg=Blue guibg=White +hi mSection term=NONE cterm=NONE ctermfg=Blue ctermbg=Black gui=bold guifg=Navy guibg=White +hi mText term=NONE cterm=NONE ctermfg=White ctermbg=Black gui=bold guifg=Black guibg=White " Colors that closely match SAS log colors for default color scheme - hi lError term=NONE cterm=NONE ctermfg=Red ctermbg=Black gui=none guifg=Red guibg=White - hi lWarning term=NONE cterm=NONE ctermfg=Green ctermbg=Black gui=none guifg=Green guibg=White - hi lNote term=NONE cterm=NONE ctermfg=Cyan ctermbg=Black gui=none guifg=Blue guibg=White - - - " Special hilighting for the SAS proc section - - HiLink sasComment sComment - HiLink sasConditional sKeyword - HiLink sasStep sSection - HiLink sasFunction sKeyword - HiLink sasMacro mKeyword - HiLink sasMacroVar NonText - HiLink sasNumber sNumber - HiLink sasStatement sKeyword - HiLink sasString sString - HiLink sasProc sProc - " (Bob Heckel) - HiLink sasTodo Todo - HiLink sasErrMsg lError - HiLink sasWarnMsg lWarning - HiLink sasLogMsg lNote - HiLink sasCards sCard - " (Bob Heckel) - HiLink sasUnderscore PreProc - delcommand HiLink -endif +hi lError term=NONE cterm=NONE ctermfg=Red ctermbg=Black gui=none guifg=Red guibg=White +hi lWarning term=NONE cterm=NONE ctermfg=Green ctermbg=Black gui=none guifg=Green guibg=White +hi lNote term=NONE cterm=NONE ctermfg=Cyan ctermbg=Black gui=none guifg=Blue guibg=White + + +" Special hilighting for the SAS proc section + +hi def link sasComment sComment +hi def link sasConditional sKeyword +hi def link sasStep sSection +hi def link sasFunction sKeyword +hi def link sasMacro mKeyword +hi def link sasMacroVar NonText +hi def link sasNumber sNumber +hi def link sasStatement sKeyword +hi def link sasString sString +hi def link sasProc sProc +" (Bob Heckel) +hi def link sasTodo Todo +hi def link sasErrMsg lError +hi def link sasWarnMsg lWarning +hi def link sasLogMsg lNote +hi def link sasCards sCard +" (Bob Heckel) +hi def link sasUnderscore PreProc " Syncronize from beginning to keep large blocks from losing " syntax coloring while moving through code. diff --git a/runtime/syntax/sass.vim b/runtime/syntax/sass.vim index 2ea0722696..d075c8736e 100644 --- a/runtime/syntax/sass.vim +++ b/runtime/syntax/sass.vim @@ -2,7 +2,7 @@ " Language: Sass " Maintainer: Tim Pope <vimNOSPAM@tpope.org> " Filenames: *.sass -" Last Change: 2013 May 30 +" Last Change: 2016 Aug 29 if exists("b:current_syntax") finish @@ -13,7 +13,7 @@ runtime! syntax/css.vim syn case ignore syn cluster sassCssProperties contains=cssFontProp,cssFontDescriptorProp,cssColorProp,cssTextProp,cssBoxProp,cssGeneratedContentProp,cssPagingProp,cssUIProp,cssRenderProp,cssAuralProp,cssTableProp -syn cluster sassCssAttributes contains=css.*Attr,scssComment,cssValue.*,cssColor,cssURL,sassDefault,cssImportant,cssError,cssStringQ,cssStringQQ,cssFunction,cssUnicodeEscape,cssRenderProp +syn cluster sassCssAttributes contains=css.*Attr,sassEndOfLineComment,scssComment,cssValue.*,cssColor,cssURL,sassDefault,cssImportant,cssError,cssStringQ,cssStringQQ,cssFunction,cssUnicodeEscape,cssRenderProp syn region sassDefinition matchgroup=cssBraces start="{" end="}" contains=TOP @@ -58,6 +58,9 @@ syn match sassAmpersand "&" " TODO: Attribute namespaces " TODO: Arithmetic (including strings and concatenation) +syn region sassMediaQuery matchgroup=sassMedia start="@media" end="[{};]\@=\|$" contains=sassMediaOperators +syn keyword sassMediaOperators and not only contained +syn region sassCharset start="@charset" end=";\|$" contains=scssComment,cssStringQ,cssStringQQ,cssURL,cssUnicodeEscape,cssMediaType syn region sassInclude start="@import" end=";\|$" contains=scssComment,cssStringQ,cssStringQQ,cssURL,cssUnicodeEscape,cssMediaType syn region sassDebugLine end=";\|$" matchgroup=sassDebug start="@debug\>" contains=@sassCssAttributes,sassVariable,sassFunction syn region sassWarnLine end=";\|$" matchgroup=sassWarn start="@warn\>" contains=@sassCssAttributes,sassVariable,sassFunction @@ -67,7 +70,9 @@ syn keyword sassFor from to through in contained syn keyword sassTodo FIXME NOTE TODO OPTIMIZE XXX contained syn region sassComment start="^\z(\s*\)//" end="^\%(\z1 \)\@!" contains=sassTodo,@Spell syn region sassCssComment start="^\z(\s*\)/\*" end="^\%(\z1 \)\@!" contains=sassTodo,@Spell +syn match sassEndOfLineComment "//.*" contains=sassComment,sassTodo,@Spell +hi def link sassEndOfLineComment sassComment hi def link sassCssComment sassComment hi def link sassComment Comment hi def link sassDefault cssImportant @@ -80,6 +85,9 @@ hi def link sassExtend PreProc hi def link sassFunctionDecl PreProc hi def link sassReturn PreProc hi def link sassTodo Todo +hi def link sassCharset PreProc +hi def link sassMedia PreProc +hi def link sassMediaOperators PreProc hi def link sassInclude Include hi def link sassDebug sassControl hi def link sassWarn sassControl diff --git a/runtime/syntax/sather.vim b/runtime/syntax/sather.vim index 103cf0b8cd..baa3a825d8 100644 --- a/runtime/syntax/sather.vim +++ b/runtime/syntax/sather.vim @@ -9,11 +9,8 @@ " Homepage: http://www.icsi.berkeley.edu/~sather " Sather files use .sa as suffix -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -61,44 +58,34 @@ syn match satherComment "--.*" contains=satherComment2String,satherCharacter syn sync ccomment satherComment " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_sather_syn_inits") - if version < 508 - let did_sather_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink satherBranch satherStatement - HiLink satherLabel satherStatement - HiLink satherConditional satherStatement - HiLink satherSynchronize satherStatement - HiLink satherRepeat satherStatement - HiLink satherExceptions satherStatement - HiLink satherStorageClass satherDeclarative - HiLink satherMethodDecl satherDeclarative - HiLink satherClassDecl satherDeclarative - HiLink satherScopeDecl satherDeclarative - HiLink satherBoolValue satherValue - HiLink satherSpecial satherValue - HiLink satherString satherValue - HiLink satherCharacter satherValue - HiLink satherSpecialCharacter satherValue - HiLink satherNumber satherValue - HiLink satherStatement Statement - HiLink satherOperator Statement - HiLink satherComment Comment - HiLink satherType Type - HiLink satherValue String - HiLink satherString String - HiLink satherSpecial String - HiLink satherCharacter String - HiLink satherDeclarative Type - HiLink satherExternal PreCondit - delcommand HiLink -endif +hi def link satherBranch satherStatement +hi def link satherLabel satherStatement +hi def link satherConditional satherStatement +hi def link satherSynchronize satherStatement +hi def link satherRepeat satherStatement +hi def link satherExceptions satherStatement +hi def link satherStorageClass satherDeclarative +hi def link satherMethodDecl satherDeclarative +hi def link satherClassDecl satherDeclarative +hi def link satherScopeDecl satherDeclarative +hi def link satherBoolValue satherValue +hi def link satherSpecial satherValue +hi def link satherString satherValue +hi def link satherCharacter satherValue +hi def link satherSpecialCharacter satherValue +hi def link satherNumber satherValue +hi def link satherStatement Statement +hi def link satherOperator Statement +hi def link satherComment Comment +hi def link satherType Type +hi def link satherValue String +hi def link satherString String +hi def link satherSpecial String +hi def link satherCharacter String +hi def link satherDeclarative Type +hi def link satherExternal PreCondit let b:current_syntax = "sather" diff --git a/runtime/syntax/scala.vim b/runtime/syntax/scala.vim new file mode 100644 index 0000000000..7779c43996 --- /dev/null +++ b/runtime/syntax/scala.vim @@ -0,0 +1,230 @@ +" Vim syntax file +" Language: Scala +" Maintainer: Derek Wyatt +" URL: https://github.com/derekwyatt/vim-scala +" License: Same as Vim +" Last Change: 20 May 2016 +" ---------------------------------------------------------------------------- + +if !exists('main_syntax') + " quit when a syntax file was already loaded + if exists("b:current_syntax") + finish + endif + let main_syntax = 'scala' +endif + +scriptencoding utf-8 + +let b:current_syntax = "scala" + +" Allows for embedding, see #59; main_syntax convention instead? Refactor TOP +" +" The @Spell here is a weird hack, it means *exclude* if the first group is +" TOP. Otherwise we get spelling errors highlighted on code elements that +" match scalaBlock, even with `syn spell notoplevel`. +function! s:ContainedGroup() + try + silent syn list @scala + return '@scala,@NoSpell' + catch /E392/ + return 'TOP,@Spell' + endtry +endfunction + +unlet! b:current_syntax + +syn case match +syn sync minlines=200 maxlines=1000 + +syn keyword scalaKeyword catch do else final finally for forSome if +syn keyword scalaKeyword match return throw try while yield macro +syn keyword scalaKeyword class trait object extends with nextgroup=scalaInstanceDeclaration skipwhite +syn keyword scalaKeyword case nextgroup=scalaKeyword,scalaCaseFollowing skipwhite +syn keyword scalaKeyword val nextgroup=scalaNameDefinition,scalaQuasiQuotes skipwhite +syn keyword scalaKeyword def var nextgroup=scalaNameDefinition skipwhite +hi link scalaKeyword Keyword + +exe 'syn region scalaBlock start=/{/ end=/}/ contains=' . s:ContainedGroup() . ' fold' + +syn keyword scalaAkkaSpecialWord when goto using startWith initialize onTransition stay become unbecome +hi link scalaAkkaSpecialWord PreProc + +syn keyword scalatestSpecialWord shouldBe +syn match scalatestShouldDSLA /^\s\+\zsit should/ +syn match scalatestShouldDSLB /\<should\>/ +hi link scalatestSpecialWord PreProc +hi link scalatestShouldDSLA PreProc +hi link scalatestShouldDSLB PreProc + +syn match scalaSymbol /'[_A-Za-z0-9$]\+/ +hi link scalaSymbol Number + +syn match scalaChar /'.'/ +syn match scalaChar /'\\[\\"'ntbrf]'/ contains=scalaEscapedChar +syn match scalaChar /'\\u[A-Fa-f0-9]\{4}'/ contains=scalaUnicodeChar +syn match scalaEscapedChar /\\[\\"'ntbrf]/ +syn match scalaUnicodeChar /\\u[A-Fa-f0-9]\{4}/ +hi link scalaChar Character +hi link scalaEscapedChar Function +hi link scalaUnicodeChar Special + +syn match scalaOperator "||" +syn match scalaOperator "&&" +hi link scalaOperator Special + +syn match scalaNameDefinition /\<[_A-Za-z0-9$]\+\>/ contained nextgroup=scalaPostNameDefinition,scalaVariableDeclarationList +syn match scalaNameDefinition /`[^`]\+`/ contained nextgroup=scalaPostNameDefinition +syn match scalaVariableDeclarationList /\s*,\s*/ contained nextgroup=scalaNameDefinition +syn match scalaPostNameDefinition /\_s*:\_s*/ contained nextgroup=scalaTypeDeclaration +hi link scalaNameDefinition Function + +syn match scalaInstanceDeclaration /\<[_\.A-Za-z0-9$]\+\>/ contained nextgroup=scalaInstanceHash +syn match scalaInstanceDeclaration /`[^`]\+`/ contained +syn match scalaInstanceHash /#/ contained nextgroup=scalaInstanceDeclaration +hi link scalaInstanceDeclaration Special +hi link scalaInstanceHash Type + +syn match scalaUnimplemented /???/ +hi link scalaUnimplemented ERROR + +syn match scalaCapitalWord /\<[A-Z][A-Za-z0-9$]*\>/ +hi link scalaCapitalWord Special + +" Handle type declarations specially +syn region scalaTypeStatement matchgroup=Keyword start=/\<type\_s\+\ze/ end=/$/ contains=scalaTypeTypeDeclaration,scalaSquareBrackets,scalaTypeTypeEquals,scalaTypeStatement + +" Ugh... duplication of all the scalaType* stuff to handle special highlighting +" of `type X =` declarations +syn match scalaTypeTypeDeclaration /(/ contained nextgroup=scalaTypeTypeExtension,scalaTypeTypeEquals contains=scalaRoundBrackets skipwhite +syn match scalaTypeTypeDeclaration /\%(โ\|=>\)\ze/ contained nextgroup=scalaTypeTypeDeclaration contains=scalaTypeTypeExtension skipwhite +syn match scalaTypeTypeDeclaration /\<[_\.A-Za-z0-9$]\+\>/ contained nextgroup=scalaTypeTypeExtension,scalaTypeTypeEquals skipwhite +syn match scalaTypeTypeEquals /=\ze[^>]/ contained nextgroup=scalaTypeTypePostDeclaration skipwhite +syn match scalaTypeTypeExtension /)\?\_s*\zs\%(โ\|=>\|<:\|:>\|=:=\|::\|#\)/ contained nextgroup=scalaTypeTypeDeclaration skipwhite +syn match scalaTypeTypePostDeclaration /\<[_\.A-Za-z0-9$]\+\>/ contained nextgroup=scalaTypeTypePostExtension skipwhite +syn match scalaTypeTypePostExtension /\%(โ\|=>\|<:\|:>\|=:=\|::\)/ contained nextgroup=scalaTypeTypePostDeclaration skipwhite +hi link scalaTypeTypeDeclaration Type +hi link scalaTypeTypeExtension Keyword +hi link scalaTypeTypePostDeclaration Special +hi link scalaTypeTypePostExtension Keyword + +syn match scalaTypeDeclaration /(/ contained nextgroup=scalaTypeExtension contains=scalaRoundBrackets skipwhite +syn match scalaTypeDeclaration /\%(โ\|=>\)\ze/ contained nextgroup=scalaTypeDeclaration contains=scalaTypeExtension skipwhite +syn match scalaTypeDeclaration /\<[_\.A-Za-z0-9$]\+\>/ contained nextgroup=scalaTypeExtension skipwhite +syn match scalaTypeExtension /)\?\_s*\zs\%(โ\|=>\|<:\|:>\|=:=\|::\|#\)/ contained nextgroup=scalaTypeDeclaration skipwhite +hi link scalaTypeDeclaration Type +hi link scalaTypeExtension Keyword +hi link scalaTypePostExtension Keyword + +syn match scalaTypeAnnotation /\%([_a-zA-Z0-9$\s]:\_s*\)\ze[_=(\.A-Za-z0-9$]\+/ skipwhite nextgroup=scalaTypeDeclaration contains=scalaRoundBrackets +syn match scalaTypeAnnotation /)\_s*:\_s*\ze[_=(\.A-Za-z0-9$]\+/ skipwhite nextgroup=scalaTypeDeclaration +hi link scalaTypeAnnotation Normal + +syn match scalaCaseFollowing /\<[_\.A-Za-z0-9$]\+\>/ contained +syn match scalaCaseFollowing /`[^`]\+`/ contained +hi link scalaCaseFollowing Special + +syn keyword scalaKeywordModifier abstract override final lazy implicit implicitly private protected sealed null require super +hi link scalaKeywordModifier Function + +syn keyword scalaSpecial this true false ne eq +syn keyword scalaSpecial new nextgroup=scalaInstanceDeclaration skipwhite +syn match scalaSpecial "\%(=>\|โ\|<-\|โ\|->\|โ\)" +syn match scalaSpecial /`[^`]\+`/ " Backtick literals +hi link scalaSpecial PreProc + +syn keyword scalaExternal package import +hi link scalaExternal Include + +syn match scalaStringEmbeddedQuote /\\"/ contained +syn region scalaString start=/"/ end=/"/ contains=scalaStringEmbeddedQuote,scalaEscapedChar,scalaUnicodeChar +hi link scalaString String +hi link scalaStringEmbeddedQuote String + +syn region scalaIString matchgroup=scalaInterpolationBrackets start=/\<[a-zA-Z][a-zA-Z0-9_]*"/ skip=/\\"/ end=/"/ contains=scalaInterpolation,scalaInterpolationB,scalaEscapedChar,scalaUnicodeChar +syn region scalaTripleIString matchgroup=scalaInterpolationBrackets start=/\<[a-zA-Z][a-zA-Z0-9_]*"""/ end=/"""\%([^"]\|$\)/ contains=scalaInterpolation,scalaInterpolationB,scalaEscapedChar,scalaUnicodeChar +hi link scalaIString String +hi link scalaTripleIString String + +syn match scalaInterpolation /\$[a-zA-Z0-9_$]\+/ contained +exe 'syn region scalaInterpolationB matchgroup=scalaInterpolationBoundary start=/\${/ end=/}/ contained contains=' . s:ContainedGroup() +hi link scalaInterpolation Function +hi link scalaInterpolationB Normal + +syn region scalaFString matchgroup=scalaInterpolationBrackets start=/f"/ skip=/\\"/ end=/"/ contains=scalaFInterpolation,scalaFInterpolationB,scalaEscapedChar,scalaUnicodeChar +syn match scalaFInterpolation /\$[a-zA-Z0-9_$]\+\(%[-A-Za-z0-9\.]\+\)\?/ contained +exe 'syn region scalaFInterpolationB matchgroup=scalaInterpolationBoundary start=/${/ end=/}\(%[-A-Za-z0-9\.]\+\)\?/ contained contains=' . s:ContainedGroup() +hi link scalaFString String +hi link scalaFInterpolation Function +hi link scalaFInterpolationB Normal + +syn region scalaTripleString start=/"""/ end=/"""\%([^"]\|$\)/ contains=scalaEscapedChar,scalaUnicodeChar +syn region scalaTripleFString matchgroup=scalaInterpolationBrackets start=/f"""/ end=/"""\%([^"]\|$\)/ contains=scalaFInterpolation,scalaFInterpolationB,scalaEscapedChar,scalaUnicodeChar +hi link scalaTripleString String +hi link scalaTripleFString String + +hi link scalaInterpolationBrackets Special +hi link scalaInterpolationBoundary Function + +syn match scalaNumber /\<0[dDfFlL]\?\>/ " Just a bare 0 +syn match scalaNumber /\<[1-9]\d*[dDfFlL]\?\>/ " A multi-digit number - octal numbers with leading 0's are deprecated in Scala +syn match scalaNumber /\<0[xX][0-9a-fA-F]\+[dDfFlL]\?\>/ " Hex number +syn match scalaNumber /\%(\<\d\+\.\d*\|\.\d\+\)\%([eE][-+]\=\d\+\)\=[fFdD]\=/ " exponential notation 1 +syn match scalaNumber /\<\d\+[eE][-+]\=\d\+[fFdD]\=\>/ " exponential notation 2 +syn match scalaNumber /\<\d\+\%([eE][-+]\=\d\+\)\=[fFdD]\>/ " exponential notation 3 +hi link scalaNumber Number + +syn region scalaRoundBrackets start="(" end=")" skipwhite contained contains=scalaTypeDeclaration,scalaSquareBrackets,scalaRoundBrackets + +syn region scalaSquareBrackets matchgroup=scalaSquareBracketsBrackets start="\[" end="\]" skipwhite nextgroup=scalaTypeExtension contains=scalaTypeDeclaration,scalaSquareBrackets,scalaTypeOperator,scalaTypeAnnotationParameter +syn match scalaTypeOperator /[-+=:<>]\+/ contained +syn match scalaTypeAnnotationParameter /@\<[`_A-Za-z0-9$]\+\>/ contained +hi link scalaSquareBracketsBrackets Type +hi link scalaTypeOperator Keyword +hi link scalaTypeAnnotationParameter Function + +syn match scalaShebang "\%^#!.*" display +syn region scalaMultilineComment start="/\*" end="\*/" contains=scalaMultilineComment,scalaDocLinks,scalaParameterAnnotation,scalaCommentAnnotation,scalaTodo,scalaCommentCodeBlock,@Spell keepend fold +syn match scalaCommentAnnotation "@[_A-Za-z0-9$]\+" contained +syn match scalaParameterAnnotation "\%(@tparam\|@param\|@see\)" nextgroup=scalaParamAnnotationValue skipwhite contained +syn match scalaParamAnnotationValue /[.`_A-Za-z0-9$]\+/ contained +syn region scalaDocLinks start="\[\[" end="\]\]" contained +syn region scalaCommentCodeBlock matchgroup=Keyword start="{{{" end="}}}" contained +syn match scalaTodo "\vTODO|FIXME|XXX" contained +hi link scalaShebang Comment +hi link scalaMultilineComment Comment +hi link scalaDocLinks Function +hi link scalaParameterAnnotation Function +hi link scalaParamAnnotationValue Keyword +hi link scalaCommentAnnotation Function +hi link scalaCommentCodeBlockBrackets String +hi link scalaCommentCodeBlock String +hi link scalaTodo Todo + +syn match scalaAnnotation /@\<[`_A-Za-z0-9$]\+\>/ +hi link scalaAnnotation PreProc + +syn match scalaTrailingComment "//.*$" contains=scalaTodo,@Spell +hi link scalaTrailingComment Comment + +syn match scalaAkkaFSM /goto([^)]*)\_s\+\<using\>/ contains=scalaAkkaFSMGotoUsing +syn match scalaAkkaFSM /stay\_s\+using/ +syn match scalaAkkaFSM /^\s*stay\s*$/ +syn match scalaAkkaFSM /when\ze([^)]*)/ +syn match scalaAkkaFSM /startWith\ze([^)]*)/ +syn match scalaAkkaFSM /initialize\ze()/ +syn match scalaAkkaFSM /onTransition/ +syn match scalaAkkaFSM /onTermination/ +syn match scalaAkkaFSM /whenUnhandled/ +syn match scalaAkkaFSMGotoUsing /\<using\>/ +syn match scalaAkkaFSMGotoUsing /\<goto\>/ +hi link scalaAkkaFSM PreProc +hi link scalaAkkaFSMGotoUsing PreProc + +let b:current_syntax = 'scala' + +if main_syntax ==# 'scala' + unlet main_syntax +endif + +" vim:set sw=2 sts=2 ts=8 et: diff --git a/runtime/syntax/scheme.vim b/runtime/syntax/scheme.vim index c59e09cd17..af9a659e07 100644 --- a/runtime/syntax/scheme.vim +++ b/runtime/syntax/scheme.vim @@ -14,11 +14,8 @@ " Initializing: -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -64,11 +61,7 @@ syn region schemeUnquote matchgroup=Delimiter start=",@#\[" end="\]" contains=AL " R5RS Scheme Functions and Syntax: -if version < 600 - set iskeyword=33,35-39,42-58,60-90,94,95,97-122,126,_ -else - setlocal iskeyword=33,35-39,42-58,60-90,94,95,97-122,126,_ -endif +setlocal iskeyword=33,35-39,42-58,60-90,94,95,97-122,126,_ syn keyword schemeSyntax lambda and or if cond case define let let* letrec syn keyword schemeSyntax begin do delay set! else => @@ -306,38 +299,28 @@ syn sync match matchPlace grouphere NONE "^[^ \t]" " ... i.e. synchronize on a line that starts at the left margin " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_scheme_syntax_inits") - if version < 508 - let did_scheme_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink schemeSyntax Statement - HiLink schemeFunc Function +hi def link schemeSyntax Statement +hi def link schemeFunc Function - HiLink schemeString String - HiLink schemeCharacter Character - HiLink schemeNumber Number - HiLink schemeBoolean Boolean +hi def link schemeString String +hi def link schemeCharacter Character +hi def link schemeNumber Number +hi def link schemeBoolean Boolean - HiLink schemeDelimiter Delimiter - HiLink schemeConstant Constant +hi def link schemeDelimiter Delimiter +hi def link schemeConstant Constant - HiLink schemeComment Comment - HiLink schemeMultilineComment Comment - HiLink schemeError Error +hi def link schemeComment Comment +hi def link schemeMultilineComment Comment +hi def link schemeError Error - HiLink schemeExtSyntax Type - HiLink schemeExtFunc PreProc +hi def link schemeExtSyntax Type +hi def link schemeExtFunc PreProc - HiLink schemeLang PreProc +hi def link schemeLang PreProc - delcommand HiLink -endif let b:current_syntax = "scheme" diff --git a/runtime/syntax/scilab.vim b/runtime/syntax/scilab.vim index 1bfc003678..03e123b058 100644 --- a/runtime/syntax/scilab.vim +++ b/runtime/syntax/scilab.vim @@ -9,11 +9,8 @@ " -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -66,49 +63,39 @@ syn match scilabOverload "%[A-Za-z0-9?!_#$]\+_[A-Za-z0-9?!_#$]\+" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_scilab_syntax_inits") - if version < 508 - let did_scilab_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink scilabStatement Statement - HiLink scilabFunction Keyword - HiLink scilabPredicate Keyword - HiLink scilabKeyword Keyword - HiLink scilabDebug Debug - HiLink scilabRepeat Repeat - HiLink scilabConditional Conditional - HiLink scilabMultiplex Conditional - - HiLink scilabConstant Constant - HiLink scilabBoolean Boolean - - HiLink scilabDelimiter Delimiter - HiLink scilabMlistAccess Delimiter - HiLink scilabComparison Operator - HiLink scilabLogical Operator - HiLink scilabAssignment Operator - HiLink scilabArithmetic Operator - HiLink scilabRange Operator - HiLink scilabLineContinuation Underlined - HiLink scilabTransposition Operator - - HiLink scilabTodo Todo - HiLink scilabComment Comment - - HiLink scilabNumber Number - HiLink scilabString String - - HiLink scilabIdentifier Identifier - HiLink scilabOverload Special - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link scilabStatement Statement +hi def link scilabFunction Keyword +hi def link scilabPredicate Keyword +hi def link scilabKeyword Keyword +hi def link scilabDebug Debug +hi def link scilabRepeat Repeat +hi def link scilabConditional Conditional +hi def link scilabMultiplex Conditional + +hi def link scilabConstant Constant +hi def link scilabBoolean Boolean + +hi def link scilabDelimiter Delimiter +hi def link scilabMlistAccess Delimiter +hi def link scilabComparison Operator +hi def link scilabLogical Operator +hi def link scilabAssignment Operator +hi def link scilabArithmetic Operator +hi def link scilabRange Operator +hi def link scilabLineContinuation Underlined +hi def link scilabTransposition Operator + +hi def link scilabTodo Todo +hi def link scilabComment Comment + +hi def link scilabNumber Number +hi def link scilabString String + +hi def link scilabIdentifier Identifier +hi def link scilabOverload Special + let b:current_syntax = "scilab" diff --git a/runtime/syntax/sd.vim b/runtime/syntax/sd.vim index 7fa0e04492..b497ba5eaa 100644 --- a/runtime/syntax/sd.vim +++ b/runtime/syntax/sd.vim @@ -5,9 +5,8 @@ " URL: http://netstudent.polito.it/vim_syntax/ " Last Change: 2012 Feb 03 by Thilo Six -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -51,29 +50,20 @@ syn keyword sdSpecial TRUE FALSE NULL syn keyword sdDelimiter STREAM STREAM_END syn match sdError /^search .\{257,}/ -if version >= 508 || !exists("did_config_syntax_inits") - if version < 508 - let did_config_syntax_inits = 1 - command! -nargs=+ HiLink hi link <args> - else - command! -nargs=+ HiLink hi def link <args> - endif - HiLink sdIP Number - HiLink sdHostname Type - HiLink sdEncoding Identifier - HiLink sdCoding Identifier - HiLink sdSource Identifier - HiLink sdComment Comment - HiLink sdIPError Error - HiLink sdError Error - HiLink sdStatement Statement - HiLink sdIPSpecial Special - HiLink sdSpecial Special - HiLink sdDelimiter Delimiter +hi def link sdIP Number +hi def link sdHostname Type +hi def link sdEncoding Identifier +hi def link sdCoding Identifier +hi def link sdSource Identifier +hi def link sdComment Comment +hi def link sdIPError Error +hi def link sdError Error +hi def link sdStatement Statement +hi def link sdIPSpecial Special +hi def link sdSpecial Special +hi def link sdDelimiter Delimiter - delcommand HiLink -endif let b:current_syntax = "sd" diff --git a/runtime/syntax/sdl.vim b/runtime/syntax/sdl.vim index b524b72266..7df38d1955 100644 --- a/runtime/syntax/sdl.vim +++ b/runtime/syntax/sdl.vim @@ -3,11 +3,8 @@ " Maintainer: Michael Piefel <entwurf@piefel.de> " Last Change: 2 May 2001 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -129,38 +126,27 @@ syn keyword sdlType STRING OBJECT IDENTIFIER NULL syn sync ccomment sdlComment " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_sdl_syn_inits") - if version < 508 - let did_sdl_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - command -nargs=+ Hi hi <args> - else - command -nargs=+ HiLink hi def link <args> - command -nargs=+ Hi hi def <args> - endif - - HiLink sdlException Label - HiLink sdlConditional sdlStatement - HiLink sdlVirtual sdlStatement - HiLink sdlExported sdlFlag - HiLink sdlCommentError sdlError - HiLink sdlOperator Operator - HiLink sdlStructure sdlType - Hi sdlStatement term=bold ctermfg=4 guifg=Blue - Hi sdlFlag term=bold ctermfg=4 guifg=Blue gui=italic - Hi sdlNewState term=italic ctermfg=2 guifg=Magenta gui=underline - Hi sdlInput term=bold guifg=Red - HiLink sdlType Type - HiLink sdlString String - HiLink sdlComment Comment - HiLink sdlSpecial Special - HiLink sdlError Error - - delcommand HiLink - delcommand Hi -endif +" Only when an item doesn't have highlighting yet +command -nargs=+ Hi hi def <args> + +hi def link sdlException Label +hi def link sdlConditional sdlStatement +hi def link sdlVirtual sdlStatement +hi def link sdlExported sdlFlag +hi def link sdlCommentError sdlError +hi def link sdlOperator Operator +hi def link sdlStructure sdlType +Hi sdlStatement term=bold ctermfg=4 guifg=Blue +Hi sdlFlag term=bold ctermfg=4 guifg=Blue gui=italic +Hi sdlNewState term=italic ctermfg=2 guifg=Magenta gui=underline +Hi sdlInput term=bold guifg=Red +hi def link sdlType Type +hi def link sdlString String +hi def link sdlComment Comment +hi def link sdlSpecial Special +hi def link sdlError Error + +delcommand Hi let b:current_syntax = "sdl" diff --git a/runtime/syntax/sed.vim b/runtime/syntax/sed.vim index f0f80300d6..63b39db81f 100644 --- a/runtime/syntax/sed.vim +++ b/runtime/syntax/sed.vim @@ -4,11 +4,8 @@ " URL: http://folk.uio.no/hakonrk/vim/syntax/sed.vim " Last Change: 2010 May 29 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syn clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -49,8 +46,12 @@ syn match sedReplaceMeta "&\|\\\($\|.\)" contains=sedTab contained " Metacharacters: $ * . \ ^ [ ~ " @ is used as delimiter and treated on its own below let __at = char2nr("@") -let __sed_i = char2nr(" ") " ASCII: 32 -let __sed_last = 126 +let __sed_i = char2nr(" ") " ASCII: 32, EBCDIC: 64 +if has("ebcdic") + let __sed_last = 255 +else + let __sed_last = 126 +endif let __sed_metacharacters = '$*.\^[~' while __sed_i <= __sed_last let __sed_delimiter = escape(nr2char(__sed_i), __sed_metacharacters) @@ -71,45 +72,36 @@ syn region sedReplacement64 matchgroup=Special start=+@\(\\\\\|\\@\)*+ skip=+[^\ " (y) does not allow any flags. To save memory, I ignore this problem. syn match sedST "[sy]" nextgroup=sedRegexp\d\+ -if version >= 508 || !exists("did_sed_syntax_inits") - if version < 508 - let did_sed_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink sedAddress Macro - HiLink sedACI NONE - HiLink sedBranch Label - HiLink sedComment Comment - HiLink sedDelete Function - HiLink sedError Error - HiLink sedFlag Type - HiLink sedFlagwrite Constant - HiLink sedFunction Function - HiLink sedLabel Label - HiLink sedLineCont Special - HiLink sedPutHoldspc Function - HiLink sedReplaceMeta Special - HiLink sedRegexpMeta Special - HiLink sedRW Constant - HiLink sedSemicolon Special - HiLink sedST Function - HiLink sedSpecial Special - HiLink sedWhitespace NONE - if exists("highlight_sedtabs") - HiLink sedTab Todo - endif - let __sed_i = char2nr(" ") " ASCII: 32 - while __sed_i <= __sed_last - exe "HiLink sedRegexp".__sed_i "Macro" - exe "HiLink sedReplacement".__sed_i "NONE" - let __sed_i = __sed_i + 1 - endwhile - delcommand HiLink +hi def link sedAddress Macro +hi def link sedACI NONE +hi def link sedBranch Label +hi def link sedComment Comment +hi def link sedDelete Function +hi def link sedError Error +hi def link sedFlag Type +hi def link sedFlagwrite Constant +hi def link sedFunction Function +hi def link sedLabel Label +hi def link sedLineCont Special +hi def link sedPutHoldspc Function +hi def link sedReplaceMeta Special +hi def link sedRegexpMeta Special +hi def link sedRW Constant +hi def link sedSemicolon Special +hi def link sedST Function +hi def link sedSpecial Special +hi def link sedWhitespace NONE +if exists("highlight_sedtabs") +hi def link sedTab Todo endif +let __sed_i = char2nr(" ") " ASCII: 32, EBCDIC: 64 +while __sed_i <= __sed_last +exe "hi def link sedRegexp".__sed_i "Macro" +exe "hi def link sedReplacement".__sed_i "NONE" +let __sed_i = __sed_i + 1 +endwhile + unlet __sed_i __sed_last __sed_delimiter __sed_metacharacters diff --git a/runtime/syntax/sendpr.vim b/runtime/syntax/sendpr.vim index 6cf9395fe9..2e07802047 100644 --- a/runtime/syntax/sendpr.vim +++ b/runtime/syntax/sendpr.vim @@ -5,11 +5,8 @@ " " http://raisdorf.net/files/misc/send-pr.vim -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif diff --git a/runtime/syntax/sgml.vim b/runtime/syntax/sgml.vim index c0c3643dd2..d60040c5d9 100644 --- a/runtime/syntax/sgml.vim +++ b/runtime/syntax/sgml.vim @@ -5,11 +5,8 @@ " Filenames: *.sgml,*.sgm " $Id: sgml.vim,v 1.1 2004/06/13 17:52:57 vimboss Exp $ -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif diff --git a/runtime/syntax/sgmldecl.vim b/runtime/syntax/sgmldecl.vim index 13551b21c1..6c1cde15ae 100644 --- a/runtime/syntax/sgmldecl.vim +++ b/runtime/syntax/sgmldecl.vim @@ -5,11 +5,8 @@ " You can modify and maintain this file, in other case send comments " the maintainer email address. -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif let s:keepcpo= &cpo @@ -52,30 +49,20 @@ syn sync lines=250 " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_sgmldecl_syntax_init") - if version < 508 - let did_sgmldecl_syntax_init = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink sgmldeclDeclKeys Keyword - HiLink sgmldeclTypes Type - HiLink sgmldeclConst Constant - HiLink sgmldeclNConst Constant - HiLink sgmldeclString String - HiLink sgmldeclDeclBlock Normal - HiLink sgmldeclBool Boolean - HiLink sgmldeclSpecial Special - HiLink sgmldeclComment Comment - HiLink sgmldeclStatem Statement - HiLink sgmldeclVariables Type - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link sgmldeclDeclKeys Keyword +hi def link sgmldeclTypes Type +hi def link sgmldeclConst Constant +hi def link sgmldeclNConst Constant +hi def link sgmldeclString String +hi def link sgmldeclDeclBlock Normal +hi def link sgmldeclBool Boolean +hi def link sgmldeclSpecial Special +hi def link sgmldeclComment Comment +hi def link sgmldeclStatem Statement +hi def link sgmldeclVariables Type + let b:current_syntax = "sgmldecl" diff --git a/runtime/syntax/sgmllnx.vim b/runtime/syntax/sgmllnx.vim index 28224f601e..ccd78f494a 100644 --- a/runtime/syntax/sgmllnx.vim +++ b/runtime/syntax/sgmllnx.vim @@ -3,11 +3,8 @@ " Maintainer: SungHyun Nam <goweol@gmail.com> " Last Change: 2013 May 13 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -36,31 +33,21 @@ syn region sgmllnxComment start=+<!--+ end=+-->+ syn region sgmllnxDocType start=+<!doctype+ end=+>+ " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_sgmllnx_syn_inits") - if version < 508 - let did_sgmllnx_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet + +hi def link sgmllnxTag2 Function +hi def link sgmllnxTagN2 Function +hi def link sgmllnxTag Special +hi def link sgmllnxEndTag Special +hi def link sgmllnxParen Special +hi def link sgmllnxEntity Type +hi def link sgmllnxDocEnt Type +hi def link sgmllnxTagName Statement +hi def link sgmllnxComment Comment +hi def link sgmllnxSpecial Special +hi def link sgmllnxDocType PreProc +hi def link sgmllnxTagError Error - HiLink sgmllnxTag2 Function - HiLink sgmllnxTagN2 Function - HiLink sgmllnxTag Special - HiLink sgmllnxEndTag Special - HiLink sgmllnxParen Special - HiLink sgmllnxEntity Type - HiLink sgmllnxDocEnt Type - HiLink sgmllnxTagName Statement - HiLink sgmllnxComment Comment - HiLink sgmllnxSpecial Special - HiLink sgmllnxDocType PreProc - HiLink sgmllnxTagError Error - - delcommand HiLink -endif let b:current_syntax = "sgmllnx" diff --git a/runtime/syntax/sh.vim b/runtime/syntax/sh.vim index c51bd9aa45..f97299cdeb 100644 --- a/runtime/syntax/sh.vim +++ b/runtime/syntax/sh.vim @@ -2,17 +2,14 @@ " Language: shell (sh) Korn shell (ksh) bash (sh) " Maintainer: Charles E. Campbell <NdrOchipS@PcampbellAfamily.Mbiz> " Previous Maintainer: Lennart Schultz <Lennart.Schultz@ecmwf.int> -" Last Change: May 02, 2016 -" Version: 151 +" Last Change: Jan 30, 2017 +" Version: 168 " URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_SH " For options and settings, please use: :help ft-sh-syntax " This file includes many ideas from Eric Brunet (eric.brunet@ens.fr) -" For version 5.x: Clear all syntax items {{{1 -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded {{{1 +if exists("b:current_syntax") finish endif @@ -127,19 +124,19 @@ syn cluster shErrorList contains=shDoError,shIfError,shInError,shCaseError,shEsa if exists("b:is_kornshell") syn cluster ErrorList add=shDTestError endif -syn cluster shArithParenList contains=shArithmetic,shCaseEsac,shComment,shDeref,shDo,shDerefSimple,shEcho,shEscape,shNumber,shOperator,shPosnParm,shExSingleQuote,shExDoubleQuote,shRedir,shSingleQuote,shDoubleQuote,shStatement,shVariable,shAlias,shTest,shCtrlSeq,shSpecial,shParen,bashSpecialVariables,bashStatement,shIf,shFor +syn cluster shArithParenList contains=shArithmetic,shCaseEsac,shComment,shDeref,shDo,shDerefSimple,shEcho,shEscape,shNumber,shOperator,shPosnParm,shExSingleQuote,shExDoubleQuote,shHereString,shRedir,shSingleQuote,shDoubleQuote,shStatement,shVariable,shAlias,shTest,shCtrlSeq,shSpecial,shParen,bashSpecialVariables,bashStatement,shIf,shFor syn cluster shArithList contains=@shArithParenList,shParenError syn cluster shCaseEsacList contains=shCaseStart,shCase,shCaseBar,shCaseIn,shComment,shDeref,shDerefSimple,shCaseCommandSub,shCaseExSingleQuote,shCaseSingleQuote,shCaseDoubleQuote,shCtrlSeq,@shErrorList,shStringSpecial,shCaseRange -syn cluster shCaseList contains=@shCommandSubList,shCaseEsac,shColon,shCommandSub,shComment,shDo,shEcho,shExpr,shFor,shHereDoc,shIf,shRedir,shSetList,shSource,shStatement,shVariable,shCtrlSeq -syn cluster shCommandSubList contains=shAlias,shArithmetic,shComment,shCmdParenRegion,shCtrlSeq,shDeref,shDerefSimple,shDoubleQuote,shEcho,shEscape,shExDoubleQuote,shExpr,shExSingleQuote,shNumber,shOperator,shOption,shPosnParm,shSingleQuote,shSpecial,shStatement,shSubSh,shTest,shVariable +syn cluster shCaseList contains=@shCommandSubList,shCaseEsac,shColon,shCommandSub,shComment,shDo,shEcho,shExpr,shFor,shHereDoc,shIf,shHereString,shRedir,shSetList,shSource,shStatement,shVariable,shCtrlSeq +syn cluster shCommandSubList contains=shAlias,shArithmetic,shComment,shCmdParenRegion,shCtrlSeq,shDeref,shDerefSimple,shDoubleQuote,shEcho,shEscape,shExDoubleQuote,shExpr,shExSingleQuote,shHereDoc,shNumber,shOperator,shOption,shPosnParm,shHereString,shRedir,shSingleQuote,shSpecial,shStatement,shSubSh,shTest,shVariable syn cluster shCurlyList contains=shNumber,shComma,shDeref,shDerefSimple,shDerefSpecial syn cluster shDblQuoteList contains=shCommandSub,shDeref,shDerefSimple,shEscape,shPosnParm,shCtrlSeq,shSpecial syn cluster shDerefList contains=shDeref,shDerefSimple,shDerefVar,shDerefSpecial,shDerefWordError,shDerefPSR,shDerefPPS -syn cluster shDerefVarList contains=shDerefOp,shDerefVarArray,shDerefOpError +syn cluster shDerefVarList contains=shDerefOff,shDerefOp,shDerefVarArray,shDerefOpError syn cluster shEchoList contains=shArithmetic,shCommandSub,shDeref,shDerefSimple,shEscape,shExpr,shExSingleQuote,shExDoubleQuote,shSingleQuote,shDoubleQuote,shCtrlSeq,shEchoQuote syn cluster shExprList1 contains=shCharClass,shNumber,shOperator,shExSingleQuote,shExDoubleQuote,shSingleQuote,shDoubleQuote,shExpr,shDblBrace,shDeref,shDerefSimple,shCtrlSeq syn cluster shExprList2 contains=@shExprList1,@shCaseList,shTest -syn cluster shFunctionList contains=@shCommandSubList,shCaseEsac,shColon,shCommandSub,shComment,shDo,shEcho,shExpr,shFor,shHereDoc,shIf,shOption,shRedir,shSetList,shSource,shStatement,shVariable,shOperator,shCtrlSeq +syn cluster shFunctionList contains=@shCommandSubList,shCaseEsac,shColon,shCommandSub,shComment,shDo,shEcho,shExpr,shFor,shHereDoc,shIf,shOption,shHereString,shRedir,shSetList,shSource,shStatement,shVariable,shOperator,shCtrlSeq if exists("b:is_kornshell") || exists("b:is_bash") syn cluster shFunctionList add=shRepeat syn cluster shFunctionList add=shDblBrace,shDblParen @@ -147,11 +144,11 @@ endif syn cluster shHereBeginList contains=@shCommandSubList syn cluster shHereList contains=shBeginHere,shHerePayload syn cluster shHereListDQ contains=shBeginHere,@shDblQuoteList,shHerePayload -syn cluster shIdList contains=shCommandSub,shWrapLineOperator,shSetOption,shDeref,shDerefSimple,shRedir,shExSingleQuote,shExDoubleQuote,shSingleQuote,shDoubleQuote,shExpr,shCtrlSeq,shStringSpecial,shAtExpr +syn cluster shIdList contains=shCommandSub,shWrapLineOperator,shSetOption,shDeref,shDerefSimple,shHereString,shRedir,shExSingleQuote,shExDoubleQuote,shSingleQuote,shDoubleQuote,shExpr,shCtrlSeq,shStringSpecial,shAtExpr syn cluster shIfList contains=@shLoopList,shDblBrace,shDblParen,shFunctionKey,shFunctionOne,shFunctionTwo syn cluster shLoopList contains=@shCaseList,@shErrorList,shCaseEsac,shConditional,shDblBrace,shExpr,shFor,shForPP,shIf,shOption,shSet,shTest,shTestOpr,shTouch syn cluster shPPSRightList contains=shComment,shDeref,shDerefSimple,shEscape,shPosnParm -syn cluster shSubShList contains=@shCommandSubList,shCaseEsac,shColon,shCommandSub,shComment,shDo,shEcho,shExpr,shFor,shIf,shRedir,shSetList,shSource,shStatement,shVariable,shCtrlSeq,shOperator +syn cluster shSubShList contains=@shCommandSubList,shCaseEsac,shColon,shCommandSub,shComment,shDo,shEcho,shExpr,shFor,shIf,shHereString,shRedir,shSetList,shSource,shStatement,shVariable,shCtrlSeq,shOperator syn cluster shTestList contains=shCharClass,shCommandSub,shCtrlSeq,shDeref,shDerefSimple,shDoubleQuote,shExDoubleQuote,shExpr,shExSingleQuote,shNumber,shOperator,shSingleQuote,shTest,shTestOpr " Echo: {{{1 @@ -173,7 +170,7 @@ if exists("b:is_kornshell") || exists("b:is_bash") " Touch: {{{1 " ===== - syn match shTouch '\<touch\>[^;#]*' skipwhite nextgroup=shTouchList contains=shTouchCmd + syn match shTouch '\<touch\>[^;#]*' skipwhite nextgroup=shComment contains=shTouchCmd,shDoubleQuote,shSingleQuote,shDeref,shDerefSimple syn match shTouchCmd '\<touch\>' contained endif @@ -216,14 +213,14 @@ syn match shPattern "\<\S\+\())\)\@=" contained contains=shExSingleQuote,shSin " Subshells: {{{1 " ========== -syn region shExpr transparent matchgroup=shExprRegion start="{" end="}" contains=@shExprList2 nextgroup=shMoreSpecial -syn region shSubSh transparent matchgroup=shSubShRegion start="[^(]\zs(" end=")" contains=@shSubShList nextgroup=shMoreSpecial +syn region shExpr transparent matchgroup=shExprRegion start="{" end="}" contains=@shExprList2 nextgroup=shSpecialNxt +syn region shSubSh transparent matchgroup=shSubShRegion start="[^(]\zs(" end=")" contains=@shSubShList nextgroup=shSpecialNxt " Tests: {{{1 "======= syn region shExpr matchgroup=shRange start="\[" skip=+\\\\\|\\$\|\[+ end="\]" contains=@shTestList,shSpecial syn region shTest transparent matchgroup=shStatement start="\<test\s" skip=+\\\\\|\\$+ matchgroup=NONE end="[;&|]"me=e-1 end="$" contains=@shExprList1 -syn region shNoQuote start='\S' skip='\%(\\\\\)*\\.' end='\ze\s' contained +syn region shNoQuote start='\S' skip='\%(\\\\\)*\\.' end='\ze\s' contained contains=shDerefSimple,shDeref syn match shAstQuote contained '\*\ze"' nextgroup=shString syn match shTestOpr contained '[^-+/%]\zs=' skipwhite nextgroup=shTestDoubleQuote,shTestSingleQuote,shTestPattern syn match shTestOpr contained "<=\|>=\|!=\|==\|=\~\|-.\>\|-\(nt\|ot\|ef\|eq\|ne\|lt\|le\|gt\|ge\)\>\|[!<>]" @@ -308,7 +305,7 @@ if exists("b:is_bash") syn cluster shCommandSubList add=bashSpecialVariables,bashStatement syn cluster shCaseList add=bashAdminStatement,bashStatement syn keyword bashSpecialVariables contained auto_resume BASH BASH_ALIASES BASH_ALIASES BASH_ARGC BASH_ARGC BASH_ARGV BASH_ARGV BASH_CMDS BASH_CMDS BASH_COMMAND BASH_COMMAND BASH_ENV BASH_EXECUTION_STRING BASH_EXECUTION_STRING BASH_LINENO BASH_LINENO BASHOPTS BASHOPTS BASHPID BASHPID BASH_REMATCH BASH_REMATCH BASH_SOURCE BASH_SOURCE BASH_SUBSHELL BASH_SUBSHELL BASH_VERSINFO BASH_VERSION BASH_XTRACEFD BASH_XTRACEFD CDPATH COLUMNS COLUMNS COMP_CWORD COMP_CWORD COMP_KEY COMP_KEY COMP_LINE COMP_LINE COMP_POINT COMP_POINT COMPREPLY COMPREPLY COMP_TYPE COMP_TYPE COMP_WORDBREAKS COMP_WORDBREAKS COMP_WORDS COMP_WORDS COPROC COPROC DIRSTACK EMACS EMACS ENV ENV EUID FCEDIT FIGNORE FUNCNAME FUNCNAME FUNCNEST FUNCNEST GLOBIGNORE GROUPS histchars HISTCMD HISTCONTROL HISTFILE HISTFILESIZE HISTIGNORE HISTSIZE HISTTIMEFORMAT HISTTIMEFORMAT HOME HOSTFILE HOSTNAME HOSTTYPE IFS IGNOREEOF INPUTRC LANG LC_ALL LC_COLLATE LC_CTYPE LC_CTYPE LC_MESSAGES LC_NUMERIC LC_NUMERIC LINENO LINES LINES MACHTYPE MAIL MAILCHECK MAILPATH MAPFILE MAPFILE OLDPWD OPTARG OPTERR OPTIND OSTYPE PATH PIPESTATUS POSIXLY_CORRECT POSIXLY_CORRECT PPID PROMPT_COMMAND PS1 PS2 PS3 PS4 PWD RANDOM READLINE_LINE READLINE_LINE READLINE_POINT READLINE_POINT REPLY SECONDS SHELL SHELL SHELLOPTS SHLVL TIMEFORMAT TIMEOUT TMPDIR TMPDIR UID - syn keyword bashStatement chmod clear complete du egrep expr fgrep find gnufind gnugrep grep less ls mkdir mv rm rmdir rpm sed sleep sort strip tail + syn keyword bashStatement chmod clear complete du egrep expr fgrep find gnufind gnugrep grep less ls mkdir mv rm rmdir rpm sed sleep sort strip tail syn keyword bashAdminStatement daemon killall killproc nice reload restart start status stop syn keyword bashStatement command compgen endif @@ -332,30 +329,37 @@ endif " String And Character Constants: {{{1 "================================ syn match shNumber "\<\d\+\>#\=" -syn match shNumber "-\=\.\=\d\+\>#\=" -syn match shCtrlSeq "\\\d\d\d\|\\[abcfnrtv0]" contained +syn match shNumber "\<-\=\.\=\d\+\>#\=" +syn match shCtrlSeq "\\\d\d\d\|\\[abcfnrtv0]" contained if exists("b:is_bash") - syn match shSpecial "\\\o\o\o\|\\x\x\x\|\\c[^"]\|\\[abefnrtv]" contained + syn match shSpecial "[^\\]\(\\\\\)*\zs\\\o\o\o\|\\x\x\x\|\\c[^"]\|\\[abefnrtv]" contained + syn match shSpecial "^\(\\\\\)*\zs\\\o\o\o\|\\x\x\x\|\\c[^"]\|\\[abefnrtv]" contained endif if exists("b:is_bash") - syn region shExSingleQuote matchgroup=shQuote start=+\$'+ skip=+\\\\\|\\.+ end=+'+ contains=shStringSpecial,shSpecial - syn region shExDoubleQuote matchgroup=shQuote start=+\$"+ skip=+\\\\\|\\.\|\\"+ end=+"+ contains=@shDblQuoteList,shStringSpecial,shSpecial + syn region shExSingleQuote matchgroup=shQuote start=+\$'+ skip=+\\\\\|\\.+ end=+'+ contains=shStringSpecial,shSpecial nextgroup=shSpecialNxt + syn region shExDoubleQuote matchgroup=shQuote start=+\$"+ skip=+\\\\\|\\.\|\\"+ end=+"+ contains=@shDblQuoteList,shStringSpecial,shSpecial nextgroup=shSpecialNxt elseif !exists("g:sh_no_error") syn region shExSingleQuote matchGroup=Error start=+\$'+ skip=+\\\\\|\\.+ end=+'+ contains=shStringSpecial syn region shExDoubleQuote matchGroup=Error start=+\$"+ skip=+\\\\\|\\.+ end=+"+ contains=shStringSpecial endif syn region shSingleQuote matchgroup=shQuote start=+'+ end=+'+ contains=@Spell syn region shDoubleQuote matchgroup=shQuote start=+\%(\%(\\\\\)*\\\)\@<!"+ skip=+\\"+ end=+"+ contains=@shDblQuoteList,shStringSpecial,@Spell -syn match shStringSpecial "[^[:print:] \t]" contained -syn match shStringSpecial "\%(\\\\\)*\\[\\"'`$()#]" +syn match shStringSpecial "[^[:print:] \t]" contained +syn match shStringSpecial "[^\\]\zs\%(\\\\\)*\\[\\"'`$()#]" syn match shSpecial "[^\\]\zs\%(\\\\\)*\\[\\"'`$()#]" syn match shSpecial "^\%(\\\\\)*\\[\\"'`$()#]" -syn match shMoreSpecial "\%(\\\\\)*\\[\\"'`$()#]" nextgroup=shMoreSpecial contained +syn match shSpecialNxt contained "\\[\\"'`$()#]" +syn region shBkslshSnglQuote contained matchgroup=shQuote start=+'+ end=+'+ contains=@Spell +syn region shBkslshDblQuote contained matchgroup=shQuote start=+"+ skip=+\\"+ end=+"+ contains=@shDblQuoteList,shStringSpecial,@Spell " Comments: {{{1 "========== syn cluster shCommentGroup contains=shTodo,@Spell -syn keyword shTodo contained COMBAK FIXME TODO XXX +if exists("b:is_bash") + syn match shTodo contained "\<\%(COMBAK\|FIXME\|TODO\|XXX\)\ze:\=\>" +else + syn keyword shTodo contained COMBAK FIXME TODO XXX +endif syn match shComment "^\s*\zs#.*$" contains=@shCommentGroup syn match shComment "\s\zs#.*$" contains=@shCommentGroup syn match shComment contained "#.*$" contains=@shCommentGroup @@ -363,37 +367,27 @@ syn match shQuickComment contained "#.*$" " Here Documents: {{{1 " ========================================= -if version < 600 - syn region shHereDoc matchgroup=shHereDoc01 start="<<\s*\**END[a-zA-Z_0-9]*\**" matchgroup=shHereDoc01 end="^END[a-zA-Z_0-9]*$" contains=@shDblQuoteList - syn region shHereDoc matchgroup=shHereDoc02 start="<<-\s*\**END[a-zA-Z_0-9]*\**" matchgroup=shHereDoc02 end="^\s*END[a-zA-Z_0-9]*$" contains=@shDblQuoteList - syn region shHereDoc matchgroup=shHereDoc03 start="<<\s*\**EOF\**" matchgroup=shHereDoc03 end="^EOF$" contains=@shDblQuoteList - syn region shHereDoc matchgroup=shHereDoc04 start="<<-\s*\**EOF\**" matchgroup=shHereDoc04 end="^\s*EOF$" contains=@shDblQuoteList - syn region shHereDoc matchgroup=shHereDoc05 start="<<\s*\**\.\**" matchgroup=shHereDoc05 end="^\.$" contains=@shDblQuoteList - syn region shHereDoc matchgroup=shHereDoc06 start="<<-\s*\**\.\**" matchgroup=shHereDoc06 end="^\s*\.$" contains=@shDblQuoteList - -else - ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc07 start="<<\s*\\\=\z([^ \t|]\+\)" matchgroup=shHereDoc07 end="^\z1\s*$" contains=@shDblQuoteList - ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc08 start="<<\s*\"\z([^ \t|]\+\)\"" matchgroup=shHereDoc08 end="^\z1\s*$" - ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc09 start="<<-\s*\z([^ \t|]\+\)" matchgroup=shHereDoc09 end="^\s*\z1\s*$" contains=@shDblQuoteList - ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc10 start="<<-\s*'\z([^ \t|]\+\)'" matchgroup=shHereDoc10 end="^\s*\z1\s*$" - ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc11 start="<<\s*'\z([^ \t|]\+\)'" matchgroup=shHereDoc11 end="^\z1\s*$" - ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc12 start="<<-\s*\"\z([^ \t|]\+\)\"" matchgroup=shHereDoc12 end="^\s*\z1\s*$" - ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc13 start="<<\s*\\\_$\_s*\z([^ \t|]\+\)" matchgroup=shHereDoc13 end="^\z1\s*$" contains=@shDblQuoteList - ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc14 start="<<\s*\\\_$\_s*'\z([^ \t|]\+\)'" matchgroup=shHereDoc14 end="^\z1\s*$" - ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc15 start="<<\s*\\\_$\_s*\"\z([^ \t|]\+\)\"" matchgroup=shHereDoc15 end="^\z1\s*$" - ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc16 start="<<-\s*\\\_$\_s*\z([^ \t|]\+\)" matchgroup=shHereDoc16 end="^\s*\z1\s*$" - ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc17 start="<<-\s*\\\_$\_s*\\\z([^ \t|]\+\)" matchgroup=shHereDoc17 end="^\s*\z1\s*$" - ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc18 start="<<-\s*\\\_$\_s*'\z([^ \t|]\+\)'" matchgroup=shHereDoc18 end="^\s*\z1\s*$" - ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc19 start="<<-\s*\\\_$\_s*\"\z([^ \t|]\+\)\"" matchgroup=shHereDoc19 end="^\s*\z1\s*$" - ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc20 start="<<\\\z([^ \t|]\+\)" matchgroup=shHereDoc20 end="^\z1\s*$" - ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc21 start="<<-\s*\\\z([^ \t|]\+\)" matchgroup=shHereDoc21 end="^\s*\z1\s*$" -endif +ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc01 start="<<\s*\\\=\z([^ \t|>]\+\)" matchgroup=shHereDoc01 end="^\z1\s*$" contains=@shDblQuoteList +ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc02 start="<<\s*\"\z([^ \t|>]\+\)\"" matchgroup=shHereDoc02 end="^\z1\s*$" +ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc03 start="<<-\s*\z([^ \t|>]\+\)" matchgroup=shHereDoc03 end="^\s*\z1\s*$" contains=@shDblQuoteList +ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc04 start="<<-\s*'\z([^ \t|>]\+\)'" matchgroup=shHereDoc04 end="^\s*\z1\s*$" +ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc05 start="<<\s*'\z([^ \t|>]\+\)'" matchgroup=shHereDoc05 end="^\z1\s*$" +ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc06 start="<<-\s*\"\z([^ \t|>]\+\)\"" matchgroup=shHereDoc06 end="^\s*\z1\s*$" +ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc07 start="<<\s*\\\_$\_s*\z([^ \t|>]\+\)" matchgroup=shHereDoc07 end="^\z1\s*$" contains=@shDblQuoteList +ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc08 start="<<\s*\\\_$\_s*'\z([^ \t|>]\+\)'" matchgroup=shHereDoc08 end="^\z1\s*$" +ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc09 start="<<\s*\\\_$\_s*\"\z([^ \t|>]\+\)\"" matchgroup=shHereDoc09 end="^\z1\s*$" +ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc10 start="<<-\s*\\\_$\_s*\z([^ \t|>]\+\)" matchgroup=shHereDoc10 end="^\s*\z1\s*$" +ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc11 start="<<-\s*\\\_$\_s*\\\z([^ \t|>]\+\)" matchgroup=shHereDoc11 end="^\s*\z1\s*$" +ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc12 start="<<-\s*\\\_$\_s*'\z([^ \t|>]\+\)'" matchgroup=shHereDoc12 end="^\s*\z1\s*$" +ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc13 start="<<-\s*\\\_$\_s*\"\z([^ \t|>]\+\)\"" matchgroup=shHereDoc13 end="^\s*\z1\s*$" +ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc14 start="<<\\\z([^ \t|>]\+\)" matchgroup=shHereDoc14 end="^\z1\s*$" +ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc15 start="<<-\s*\\\z([^ \t|>]\+\)" matchgroup=shHereDoc15 end="^\s*\z1\s*$" " Here Strings: {{{1 " ============= " available for: bash; ksh (really should be ksh93 only) but not if its a posix -if exists("b:is_bash") || (exists("b:is_kornshell") && !exists("g:is_posix")) - syn match shRedir "<<<" skipwhite nextgroup=shCmdParenRegion +if exists("b:is_bash") || (exists("b:is_kornshell") && !exists("b:is_posix")) + syn match shHereString "<<<" skipwhite nextgroup=shCmdParenRegion endif " Identifiers: {{{1 @@ -413,7 +407,7 @@ else endif " Functions: {{{1 -if !exists("g:is_posix") +if !exists("b:is_posix") syn keyword shFunctionKey function skipwhite skipnl nextgroup=shFunctionTwo endif @@ -434,10 +428,11 @@ endif if !exists("g:sh_no_error") syn match shDerefWordError "[^}$[~]" contained endif -syn match shDerefSimple "\$\%(\k\+\|\d\)" +syn match shDerefSimple "\$\%(\h\w*\|\d\)" syn region shDeref matchgroup=PreProc start="\${" end="}" contains=@shDerefList,shDerefVarArray syn match shDerefSimple "\$[-#*@!?]" syn match shDerefSimple "\$\$" +syn match shDerefSimple "\${\d}" if exists("b:is_bash") || exists("b:is_kornshell") syn region shDeref matchgroup=PreProc start="\${##\=" end="}" contains=@shDerefList syn region shDeref matchgroup=PreProc start="\${\$\$" end="}" contains=@shDerefList @@ -452,18 +447,19 @@ endif " bash: ${!prefix*} and ${#parameter}: {{{1 " ==================================== if exists("b:is_bash") - syn region shDeref matchgroup=PreProc start="\${!" end="\*\=}" contains=@shDerefList,shDerefOp - syn match shDerefVar contained "{\@<=!\k\+" nextgroup=@shDerefVarList + syn region shDeref matchgroup=PreProc start="\${!" end="\*\=}" contains=@shDerefList,shDerefOff + syn match shDerefVar contained "{\@<=!\h\w*" nextgroup=@shDerefVarList endif if exists("b:is_kornshell") - syn match shDerefVar contained "{\@<=!\k[[:alnum:]_.]*" nextgroup=@shDerefVarList + syn match shDerefVar contained "{\@<=!\h\w*[[:alnum:]_.]*" nextgroup=@shDerefVarList endif syn match shDerefSpecial contained "{\@<=[-*@?0]" nextgroup=shDerefOp,shDerefOpError syn match shDerefSpecial contained "\({[#!]\)\@<=[[:alnum:]*@_]\+" nextgroup=@shDerefVarList,shDerefOp -syn match shDerefVar contained "{\@<=\k\+" nextgroup=@shDerefVarList +syn match shDerefVar contained "{\@<=\h\w*" nextgroup=@shDerefVarList +syn match shDerefVar contained '\d' nextgroup=@shDerefVarList if exists("b:is_kornshell") - syn match shDerefVar contained "{\@<=\k[[:alnum:]_.]*" nextgroup=@shDerefVarList + syn match shDerefVar contained "{\@<=\h\w*[[:alnum:]_.]*" nextgroup=@shDerefVarList endif " sh ksh bash : ${var[... ]...} array reference: {{{1 @@ -489,24 +485,25 @@ endif syn match shDerefOp contained ":\=[-=?]" nextgroup=@shDerefPatternList syn match shDerefOp contained ":\=+" nextgroup=@shDerefPatternList if exists("b:is_bash") || exists("b:is_kornshell") - syn match shDerefOp contained "#\{1,2}" nextgroup=@shDerefPatternList - syn match shDerefOp contained "%\{1,2}" nextgroup=@shDerefPatternList - syn match shDerefPattern contained "[^{}]\+" contains=shDeref,shDerefSimple,shDerefPattern,shDerefString,shCommandSub,shDerefEscape nextgroup=shDerefPattern + syn match shDerefOp contained "#\{1,2}" nextgroup=@shDerefPatternList + syn match shDerefOp contained "%\{1,2}" nextgroup=@shDerefPatternList + syn match shDerefPattern contained "[^{}]\+" contains=shDeref,shDerefSimple,shDerefPattern,shDerefString,shCommandSub,shDerefEscape nextgroup=shDerefPattern syn region shDerefPattern contained start="{" end="}" contains=shDeref,shDerefSimple,shDerefString,shCommandSub nextgroup=shDerefPattern syn match shDerefEscape contained '\%(\\\\\)*\\.' endif if exists("b:is_bash") syn match shDerefOp contained "[,^]\{1,2}" nextgroup=@shDerefPatternList endif -syn region shDerefString contained matchgroup=shDerefDelim start=+\%(\\\)\@<!'+ end=+'+ contains=shStringSpecial +syn region shDerefString contained matchgroup=shDerefDelim start=+\%(\\\)\@<!'+ end=+'+ contains=shStringSpecial syn region shDerefString contained matchgroup=shDerefDelim start=+\%(\\\)\@<!"+ skip=+\\"+ end=+"+ contains=@shDblQuoteList,shStringSpecial syn match shDerefString contained "\\["']" nextgroup=shDerefPattern if exists("b:is_bash") " bash : ${parameter:offset} " bash : ${parameter:offset:length} - syn region shDerefOp contained start=":[$[:alnum:]_]"me=e-1 end=":"me=e-1 end="}"me=e-1 contains=@shCommandSubList nextgroup=shDerefPOL - syn match shDerefPOL contained ":[^}]\+" contains=@shCommandSubList + syn region shDerefOff contained start=':' end='\ze:' end='\ze}' contains=shDeref,shDerefSimple,shDerefEscape nextgroup=shDerefLen,shDeref,shDerefSimple + syn region shDerefOff contained start=':\s-' end='\ze:' end='\ze}' contains=shDeref,shDerefSimple,shDerefEscape nextgroup=shDerefLen,shDeref,shDerefSimple + syn match shDerefLen contained ":[^}]\+" contains=shDeref,shDerefSimple " bash : ${parameter//pattern/string} " bash : ${parameter//pattern} @@ -536,7 +533,7 @@ endif " ==================== if exists("b:is_kornshell") || exists("b:is_bash") syn keyword shStatement autoload bg false fc fg functions getopts hash history integer jobs let nohup printf r stop suspend times true type unalias whence - if exists("g:is_posix") + if exists("b:is_posix") syn keyword shStatement command else syn keyword shStatement time @@ -545,7 +542,7 @@ if exists("b:is_kornshell") || exists("b:is_bash") " Useful bash Keywords: {{{1 " ===================== if exists("b:is_bash") - syn keyword shStatement bind builtin dirs disown enable help local logout popd pushd shopt source + syn keyword shStatement bind builtin dirs disown enable help logout popd pushd shopt source else syn keyword shStatement login newgrp endif @@ -580,134 +577,134 @@ syn sync match shWhileSync grouphere shRepeat "\<while\>" " Default Highlighting: {{{1 " ===================== -hi def link shArithRegion shShellVariables -hi def link shAstQuote shDoubleQuote -hi def link shAtExpr shSetList -hi def link shBeginHere shRedir -hi def link shCaseBar shConditional -hi def link shCaseCommandSub shCommandSub -hi def link shCaseDoubleQuote shDoubleQuote -hi def link shCaseIn shConditional -hi def link shQuote shOperator -hi def link shCaseSingleQuote shSingleQuote -hi def link shCaseStart shConditional -hi def link shCmdSubRegion shShellVariables -hi def link shColon shComment -hi def link shDerefOp shOperator -hi def link shDerefPOL shDerefOp -hi def link shDerefPPS shDerefOp -hi def link shDerefPSR shDerefOp -hi def link shDeref shShellVariables -hi def link shDerefDelim shOperator -hi def link shDerefSimple shDeref -hi def link shDerefSpecial shDeref -hi def link shDerefString shDoubleQuote -hi def link shDerefVar shDeref -hi def link shDoubleQuote shString -hi def link shEcho shString -hi def link shEchoDelim shOperator -hi def link shEchoQuote shString -hi def link shForPP shLoop -hi def link shEmbeddedEcho shString -hi def link shEscape shCommandSub -hi def link shExDoubleQuote shDoubleQuote -hi def link shExSingleQuote shSingleQuote -hi def link shHereDoc shString -hi def link shHerePayload shHereDoc -hi def link shLoop shStatement -hi def link shMoreSpecial shSpecial -hi def link shNoQuote shDoubleQuote -hi def link shOption shCommandSub -hi def link shPattern shString -hi def link shParen shArithmetic -hi def link shPosnParm shShellVariables -hi def link shQuickComment shComment -hi def link shRange shOperator -hi def link shRedir shOperator -hi def link shSetListDelim shOperator -hi def link shSetOption shOption -hi def link shSingleQuote shString -hi def link shSource shOperator -hi def link shStringSpecial shSpecial -hi def link shSubShRegion shOperator -hi def link shTestOpr shConditional -hi def link shTestPattern shString -hi def link shTestDoubleQuote shString -hi def link shTestSingleQuote shString -hi def link shTouchCmd shStatement -hi def link shVariable shSetList -hi def link shWrapLineOperator shOperator +if !exists("skip_sh_syntax_inits") + hi def link shArithRegion shShellVariables + hi def link shAstQuote shDoubleQuote + hi def link shAtExpr shSetList + hi def link shBeginHere shRedir + hi def link shCaseBar shConditional + hi def link shCaseCommandSub shCommandSub + hi def link shCaseDoubleQuote shDoubleQuote + hi def link shCaseIn shConditional + hi def link shQuote shOperator + hi def link shCaseSingleQuote shSingleQuote + hi def link shCaseStart shConditional + hi def link shCmdSubRegion shShellVariables + hi def link shColon shComment + hi def link shDerefOp shOperator + hi def link shDerefPOL shDerefOp + hi def link shDerefPPS shDerefOp + hi def link shDerefPSR shDerefOp + hi def link shDeref shShellVariables + hi def link shDerefDelim shOperator + hi def link shDerefSimple shDeref + hi def link shDerefSpecial shDeref + hi def link shDerefString shDoubleQuote + hi def link shDerefVar shDeref + hi def link shDoubleQuote shString + hi def link shEcho shString + hi def link shEchoDelim shOperator + hi def link shEchoQuote shString + hi def link shForPP shLoop + hi def link shFunction Function + hi def link shEmbeddedEcho shString + hi def link shEscape shCommandSub + hi def link shExDoubleQuote shDoubleQuote + hi def link shExSingleQuote shSingleQuote + hi def link shHereDoc shString + hi def link shHereString shRedir + hi def link shHerePayload shHereDoc + hi def link shLoop shStatement + hi def link shSpecialNxt shSpecial + hi def link shNoQuote shDoubleQuote + hi def link shOption shCommandSub + hi def link shPattern shString + hi def link shParen shArithmetic + hi def link shPosnParm shShellVariables + hi def link shQuickComment shComment + hi def link shRange shOperator + hi def link shRedir shOperator + hi def link shSetListDelim shOperator + hi def link shSetOption shOption + hi def link shSingleQuote shString + hi def link shSource shOperator + hi def link shStringSpecial shSpecial + hi def link shSubShRegion shOperator + hi def link shTestOpr shConditional + hi def link shTestPattern shString + hi def link shTestDoubleQuote shString + hi def link shTestSingleQuote shString + hi def link shTouchCmd shStatement + hi def link shVariable shSetList + hi def link shWrapLineOperator shOperator -if exists("b:is_bash") - hi def link bashAdminStatement shStatement - hi def link bashSpecialVariables shShellVariables - hi def link bashStatement shStatement - hi def link shCharClass shSpecial -endif -if exists("b:is_kornshell") - hi def link kshSpecialVariables shShellVariables - hi def link kshStatement shStatement -endif - -if !exists("g:sh_no_error") - hi def link shCaseError Error - hi def link shCondError Error - hi def link shCurlyError Error - hi def link shDerefOpError Error - hi def link shDerefWordError Error - hi def link shDoError Error - hi def link shEsacError Error - hi def link shIfError Error - hi def link shInError Error - hi def link shParenError Error - hi def link shTestError Error + if exists("b:is_bash") + hi def link bashAdminStatement shStatement + hi def link bashSpecialVariables shShellVariables + hi def link bashStatement shStatement + hi def link shCharClass shSpecial + hi def link shDerefOff shDerefOp + hi def link shDerefLen shDerefOff + endif if exists("b:is_kornshell") - hi def link shDTestError Error + hi def link kshSpecialVariables shShellVariables + hi def link kshStatement shStatement endif -endif -hi def link shArithmetic Special -hi def link shCharClass Identifier -hi def link shSnglCase Statement -hi def link shCommandSub Special -hi def link shComment Comment -hi def link shConditional Conditional -hi def link shCtrlSeq Special -hi def link shExprRegion Delimiter -hi def link shFunctionKey Function -hi def link shFunctionName Function -hi def link shNumber Number -hi def link shOperator Operator -hi def link shRepeat Repeat -hi def link shSet Statement -hi def link shSetList Identifier -hi def link shShellVariables PreProc -hi def link shSpecial Special -hi def link shStatement Statement -hi def link shString String -hi def link shTodo Todo -hi def link shAlias Identifier -hi def link shHereDoc01 shRedir -hi def link shHereDoc02 shRedir -hi def link shHereDoc03 shRedir -hi def link shHereDoc04 shRedir -hi def link shHereDoc05 shRedir -hi def link shHereDoc06 shRedir -hi def link shHereDoc07 shRedir -hi def link shHereDoc08 shRedir -hi def link shHereDoc09 shRedir -hi def link shHereDoc10 shRedir -hi def link shHereDoc11 shRedir -hi def link shHereDoc12 shRedir -hi def link shHereDoc13 shRedir -hi def link shHereDoc14 shRedir -hi def link shHereDoc15 shRedir -hi def link shHereDoc16 shRedir -hi def link shHereDoc17 shRedir -hi def link shHereDoc18 shRedir -hi def link shHereDoc19 shRedir -hi def link shHereDoc20 shRedir -hi def link shHereDoc21 shRedir + if !exists("g:sh_no_error") + hi def link shCaseError Error + hi def link shCondError Error + hi def link shCurlyError Error + hi def link shDerefOpError Error + hi def link shDerefWordError Error + hi def link shDoError Error + hi def link shEsacError Error + hi def link shIfError Error + hi def link shInError Error + hi def link shParenError Error + hi def link shTestError Error + if exists("b:is_kornshell") + hi def link shDTestError Error + endif + endif + + hi def link shArithmetic Special + hi def link shCharClass Identifier + hi def link shSnglCase Statement + hi def link shCommandSub Special + hi def link shComment Comment + hi def link shConditional Conditional + hi def link shCtrlSeq Special + hi def link shExprRegion Delimiter + hi def link shFunctionKey Function + hi def link shFunctionName Function + hi def link shNumber Number + hi def link shOperator Operator + hi def link shRepeat Repeat + hi def link shSet Statement + hi def link shSetList Identifier + hi def link shShellVariables PreProc + hi def link shSpecial Special + hi def link shStatement Statement + hi def link shString String + hi def link shTodo Todo + hi def link shAlias Identifier + hi def link shHereDoc01 shRedir + hi def link shHereDoc02 shRedir + hi def link shHereDoc03 shRedir + hi def link shHereDoc04 shRedir + hi def link shHereDoc05 shRedir + hi def link shHereDoc06 shRedir + hi def link shHereDoc07 shRedir + hi def link shHereDoc08 shRedir + hi def link shHereDoc09 shRedir + hi def link shHereDoc10 shRedir + hi def link shHereDoc11 shRedir + hi def link shHereDoc12 shRedir + hi def link shHereDoc13 shRedir + hi def link shHereDoc14 shRedir + hi def link shHereDoc15 shRedir +endif " Delete shell folding commands {{{1 " ============================= diff --git a/runtime/syntax/sicad.vim b/runtime/syntax/sicad.vim index 7e32451bed..20eb14cba1 100644 --- a/runtime/syntax/sicad.vim +++ b/runtime/syntax/sicad.vim @@ -4,28 +4,17 @@ " Last Change: 2003 May 11 " URL: http://lmark.mgx.hu:81/download/vim/sicad.vim -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif " use SQL highlighting after 'sql' command -if version >= 600 - syn include @SQL syntax/sql.vim -else - syn include @SQL <sfile>:p:h/sql.vim -endif +syn include @SQL syntax/sql.vim unlet b:current_syntax " spaces are used in (auto)indents since sicad hates tabulator characters -if version >= 600 - setlocal expandtab -else - set expandtab -endif +setlocal expandtab " ignore case syn case ignore @@ -369,44 +358,32 @@ syn keyword sicadStatement zparbn zparf zparfn zparfw zparfwn syn keyword sicadStatement zparp zparpn zwinkp zwinkpn " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_sicad_syntax_inits") - - if version < 508 - let did_sicad_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink sicadLabel PreProc - HiLink sicadLabel1 sicadLabel - HiLink sicadLabel2 sicadLabel - HiLink sicadConditional Conditional - HiLink sicadBoolean Boolean - HiLink sicadNumber Number - HiLink sicadFloat Float - HiLink sicadOperator Operator - HiLink sicadStatement Statement - HiLink sicadParameter sicadStatement - HiLink sicadGoto sicadStatement - HiLink sicadLineCont sicadStatement - HiLink sicadString String - HiLink sicadComment Comment - HiLink sicadSpecial Special - HiLink sicadIdentifier Type -" HiLink sicadIdentifier Identifier - HiLink sicadError Error - HiLink sicadParenError sicadError - HiLink sicadApostropheError sicadError - HiLink sicadStringError sicadError - HiLink sicadCommentError sicadError -" HiLink sqlStatement Special " modified highlight group in sql.vim +hi def link sicadLabel PreProc +hi def link sicadLabel1 sicadLabel +hi def link sicadLabel2 sicadLabel +hi def link sicadConditional Conditional +hi def link sicadBoolean Boolean +hi def link sicadNumber Number +hi def link sicadFloat Float +hi def link sicadOperator Operator +hi def link sicadStatement Statement +hi def link sicadParameter sicadStatement +hi def link sicadGoto sicadStatement +hi def link sicadLineCont sicadStatement +hi def link sicadString String +hi def link sicadComment Comment +hi def link sicadSpecial Special +hi def link sicadIdentifier Type +" hi def link sicadIdentifier Identifier +hi def link sicadError Error +hi def link sicadParenError sicadError +hi def link sicadApostropheError sicadError +hi def link sicadStringError sicadError +hi def link sicadCommentError sicadError +" hi def link sqlStatement Special " modified highlight group in sql.vim - delcommand HiLink - -endif let b:current_syntax = "sicad" diff --git a/runtime/syntax/simula.vim b/runtime/syntax/simula.vim index e952ee26c3..82f66d049e 100644 --- a/runtime/syntax/simula.vim +++ b/runtime/syntax/simula.vim @@ -4,11 +4,8 @@ " URL: http://folk.uio.no/hakonrk/vim/syntax/simula.vim " Last Change: 2001 May 15 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syn clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -58,42 +55,33 @@ syn match simulaReal "-\=\<\d\+\(\.\d\+\)\=\(&&\=[+-]\=\d\+\)\=\>" " Real starting with a `.', optional exponent syn match simulaReal "-\=\.\d\+\(&&\=[+-]\=\d\+\)\=\>" -if version >= 508 || !exists("did_simula_syntax_inits") - if version < 508 - let did_simula_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - HiLink simulaAssigned Identifier - HiLink simulaBoolean Boolean - HiLink simulaCharacter Character - HiLink simulaCharError Error - HiLink simulaComment Comment - HiLink simulaCompound Statement - HiLink simulaConditional Conditional - HiLink simulaConstant Constant - HiLink simulaFunction Function - HiLink simulaNumber Number - HiLink simulaOperator Operator - HiLink simulaReal Float - HiLink simulaReferenceType Type - HiLink simulaRepeat Repeat - HiLink simulaReserved Error - HiLink simulaSemicolon Statement - HiLink simulaSpecial Special - HiLink simulaSpecialChar SpecialChar - HiLink simulaSpecialCharErr Error - HiLink simulaStatement Statement - HiLink simulaStorageClass StorageClass - HiLink simulaString String - HiLink simulaStructure Structure - HiLink simulaTodo Todo - HiLink simulaType Type +hi def link simulaAssigned Identifier +hi def link simulaBoolean Boolean +hi def link simulaCharacter Character +hi def link simulaCharError Error +hi def link simulaComment Comment +hi def link simulaCompound Statement +hi def link simulaConditional Conditional +hi def link simulaConstant Constant +hi def link simulaFunction Function +hi def link simulaNumber Number +hi def link simulaOperator Operator +hi def link simulaReal Float +hi def link simulaReferenceType Type +hi def link simulaRepeat Repeat +hi def link simulaReserved Error +hi def link simulaSemicolon Statement +hi def link simulaSpecial Special +hi def link simulaSpecialChar SpecialChar +hi def link simulaSpecialCharErr Error +hi def link simulaStatement Statement +hi def link simulaStorageClass StorageClass +hi def link simulaString String +hi def link simulaStructure Structure +hi def link simulaTodo Todo +hi def link simulaType Type - delcommand HiLink -endif let b:current_syntax = "simula" " vim: sts=4 sw=4 ts=8 diff --git a/runtime/syntax/sinda.vim b/runtime/syntax/sinda.vim index 2bde267c2f..a6e5b45fcd 100644 --- a/runtime/syntax/sinda.vim +++ b/runtime/syntax/sinda.vim @@ -8,11 +8,8 @@ -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -32,11 +29,7 @@ syn case ignore let fortran_free_source=1 " Load FORTRAN syntax file -if version < 600 - source <sfile>:p:h/fortran.vim -else - runtime! syntax/fortran.vim -endif +runtime! syntax/fortran.vim unlet b:current_syntax @@ -106,39 +99,29 @@ endif " Define the default highlighting -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_sinda_syntax_inits") - if version < 508 - let did_sinda_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink sindaMacro Macro - HiLink sindaOptions Special - HiLink sindaRoutine Type - HiLink sindaControl Special - HiLink sindaSubRoutine Function - HiLink sindaIdentifier Identifier - - HiLink sindaFortran PreProc - HiLink sindaMotran PreProc - - HiLink sindaComment Comment - HiLink sindaHeader Typedef - HiLink sindaIncludeFile Type - HiLink sindaInteger Number - HiLink sindaFloat Float - HiLink sindaScientific Float - - HiLink sindaEndData Macro - - HiLink sindaTodo Todo - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link sindaMacro Macro +hi def link sindaOptions Special +hi def link sindaRoutine Type +hi def link sindaControl Special +hi def link sindaSubRoutine Function +hi def link sindaIdentifier Identifier + +hi def link sindaFortran PreProc +hi def link sindaMotran PreProc + +hi def link sindaComment Comment +hi def link sindaHeader Typedef +hi def link sindaIncludeFile Type +hi def link sindaInteger Number +hi def link sindaFloat Float +hi def link sindaScientific Float + +hi def link sindaEndData Macro + +hi def link sindaTodo Todo + let b:current_syntax = "sinda" diff --git a/runtime/syntax/sindacmp.vim b/runtime/syntax/sindacmp.vim index 87b483409a..88373eb285 100644 --- a/runtime/syntax/sindacmp.vim +++ b/runtime/syntax/sindacmp.vim @@ -8,11 +8,8 @@ -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -45,28 +42,18 @@ syn match sindacmpFloat "-\=\<[0-9]*\.[0-9]*" " Define the default highlighting -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_sindacmp_syntax_inits") - if version < 508 - let did_sindacmp_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink sindacmpTitle Type - HiLink sindacmpUnit PreProc +hi def link sindacmpTitle Type +hi def link sindacmpUnit PreProc - HiLink sindacmpLabel Statement +hi def link sindacmpLabel Statement - HiLink sindacmpHeader sindaHeader +hi def link sindacmpHeader sindaHeader - HiLink sindacmpInteger Number - HiLink sindacmpFloat Special +hi def link sindacmpInteger Number +hi def link sindacmpFloat Special - delcommand HiLink -endif let b:current_syntax = "sindacmp" diff --git a/runtime/syntax/sindaout.vim b/runtime/syntax/sindaout.vim index b557e017eb..c362f19467 100644 --- a/runtime/syntax/sindaout.vim +++ b/runtime/syntax/sindaout.vim @@ -8,11 +8,8 @@ -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -24,11 +21,7 @@ syn case match " Load SINDA syntax file -if version < 600 - source <sfile>:p:h/sinda.vim -else - runtime! syntax/sinda.vim -endif +runtime! syntax/sinda.vim unlet b:current_syntax @@ -66,33 +59,23 @@ syn match sindaoutError "<<< Error >>>" " Define the default highlighting -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_sindaout_syntax_inits") - if version < 508 - let did_sindaout_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - hi sindaHeaderDelim ctermfg=Black ctermbg=Green guifg=Black guibg=Green - - HiLink sindaoutPos Statement - HiLink sindaoutNeg PreProc - HiLink sindaoutTitle Type - HiLink sindaoutFile sindaIncludeFile - HiLink sindaoutInteger sindaInteger - - HiLink sindaoutSectionDelim Delimiter - HiLink sindaoutSectionTitle Exception - HiLink sindaoutHeaderDelim SpecialComment - HiLink sindaoutLabel Identifier - - HiLink sindaoutError Error - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi sindaHeaderDelim ctermfg=Black ctermbg=Green guifg=Black guibg=Green + +hi def link sindaoutPos Statement +hi def link sindaoutNeg PreProc +hi def link sindaoutTitle Type +hi def link sindaoutFile sindaIncludeFile +hi def link sindaoutInteger sindaInteger + +hi def link sindaoutSectionDelim Delimiter +hi def link sindaoutSectionTitle Exception +hi def link sindaoutHeaderDelim SpecialComment +hi def link sindaoutLabel Identifier + +hi def link sindaoutError Error + let b:current_syntax = "sindaout" diff --git a/runtime/syntax/sisu.vim b/runtime/syntax/sisu.vim index 0e0f2dbe0a..83d2a17245 100644 --- a/runtime/syntax/sisu.vim +++ b/runtime/syntax/sisu.vim @@ -6,11 +6,9 @@ " <http://git.sisudoc.org/gitweb/?p=code/sisu.git;a=blob_plain;f=data/sisu/conf/editor-syntax-etc/vim/syntax/sisu.vim;hb=HEAD> "(originally looked at Ruby Vim by Mirko Nasato) -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish -else endif let s:cpo_save = &cpo set cpo&vim diff --git a/runtime/syntax/skill.vim b/runtime/syntax/skill.vim index 8b960441f6..47afffc0a9 100644 --- a/runtime/syntax/skill.vim +++ b/runtime/syntax/skill.vim @@ -9,11 +9,8 @@ " database. This file also defines syntax highlighting for " certain Design Framework II interface functions. -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -525,37 +522,27 @@ syn match skillCommentError "\*/" syn sync ccomment skillComment minlines=10 " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_skill_syntax_inits") - if version < 508 - let did_skill_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink skillcdfFunctions Function - HiLink skillgeFunctions Function - HiLink skillhiFunctions Function - HiLink skillleFunctions Function - HiLink skilldbefFunctions Function - HiLink skillddFunctions Function - HiLink skillpcFunctions Function - HiLink skilltechFunctions Function - HiLink skillConstants Constant - HiLink skillFunction Function - HiLink skillKeywords Statement - HiLink skillConditional Conditional - HiLink skillRepeat Repeat - HiLink skillString String - HiLink skillTodo Todo - HiLink skillNote Todo - HiLink skillComment Comment - HiLink skillCommentError Error +hi def link skillcdfFunctions Function +hi def link skillgeFunctions Function +hi def link skillhiFunctions Function +hi def link skillleFunctions Function +hi def link skilldbefFunctions Function +hi def link skillddFunctions Function +hi def link skillpcFunctions Function +hi def link skilltechFunctions Function +hi def link skillConstants Constant +hi def link skillFunction Function +hi def link skillKeywords Statement +hi def link skillConditional Conditional +hi def link skillRepeat Repeat +hi def link skillString String +hi def link skillTodo Todo +hi def link skillNote Todo +hi def link skillComment Comment +hi def link skillCommentError Error - delcommand HiLink -endif let b:current_syntax = "skill" diff --git a/runtime/syntax/sl.vim b/runtime/syntax/sl.vim index fa3bca06dd..1f6c847353 100644 --- a/runtime/syntax/sl.vim +++ b/runtime/syntax/sl.vim @@ -3,11 +3,8 @@ " Maintainer: Dan Piponi <dan@tanelorn.demon.co.uk> " Last Change: 2001 May 09 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -75,45 +72,35 @@ syn keyword slVariable dtime dPdtime syn sync ccomment slComment minlines=10 " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_sl_syntax_inits") - if version < 508 - let did_sl_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink slLabel Label - HiLink slUserLabel Label - HiLink slConditional Conditional - HiLink slRepeat Repeat - HiLink slCharacter Character - HiLink slSpecialCharacter slSpecial - HiLink slNumber Number - HiLink slFloat Float - HiLink slParenError slError - HiLink slInParen slError - HiLink slCommentError slError - HiLink slOperator Operator - HiLink slStorageClass StorageClass - HiLink slError Error - HiLink slStatement Statement - HiLink slType Type - HiLink slCommentError slError - HiLink slCommentString slString - HiLink slComment2String slString - HiLink slCommentSkip slComment - HiLink slString String - HiLink slComment Comment - HiLink slSpecial SpecialChar - HiLink slTodo Todo - HiLink slVariable Identifier - "HiLink slIdentifier Identifier +hi def link slLabel Label +hi def link slUserLabel Label +hi def link slConditional Conditional +hi def link slRepeat Repeat +hi def link slCharacter Character +hi def link slSpecialCharacter slSpecial +hi def link slNumber Number +hi def link slFloat Float +hi def link slParenError slError +hi def link slInParen slError +hi def link slCommentError slError +hi def link slOperator Operator +hi def link slStorageClass StorageClass +hi def link slError Error +hi def link slStatement Statement +hi def link slType Type +hi def link slCommentError slError +hi def link slCommentString slString +hi def link slComment2String slString +hi def link slCommentSkip slComment +hi def link slString String +hi def link slComment Comment +hi def link slSpecial SpecialChar +hi def link slTodo Todo +hi def link slVariable Identifier +"hi def link slIdentifier Identifier - delcommand HiLink -endif let b:current_syntax = "sl" diff --git a/runtime/syntax/slang.vim b/runtime/syntax/slang.vim index 9fa89b4d61..53ede4dc5a 100644 --- a/runtime/syntax/slang.vim +++ b/runtime/syntax/slang.vim @@ -3,11 +3,8 @@ " Maintainer: Jan Hlavacek <lahvak@math.ohio-state.edu> " Last Change: 980216 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -55,47 +52,37 @@ syn keyword slangOperator sizeof syn region slangPreCondit start="^\s*#\s*\(ifdef\>\|ifndef\>\|iftrue\>\|ifnfalse\>\|iffalse\>\|ifntrue\>\|if\$\|ifn\$\|\|elif\>\|else\>\|endif\>\)" skip="\\$" end="$" contains=cComment,slangString,slangCharacter,slangNumber " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_slang_syntax_inits") - if version < 508 - let did_slang_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink slangDefinition Type - HiLink slangBlock slangDefinition - HiLink slangLabel Label - HiLink slangConditional Conditional - HiLink slangRepeat Repeat - HiLink slangCharacter Character - HiLink slangFloat Float - HiLink slangImaginary Float - HiLink slangDecimal slangNumber - HiLink slangOctal slangNumber - HiLink slangHex slangNumber - HiLink slangNumber Number - HiLink slangParenError Error - HiLink slangOctalError Error - HiLink slangOperator Operator - HiLink slangStructure Structure - HiLink slangInclude Include - HiLink slangPreCondit PreCondit - HiLink slangError Error - HiLink slangStatement Statement - HiLink slangType Type - HiLink slangString String - HiLink slangConstant Constant - HiLink slangRangeArray slangConstant - HiLink slangComment Comment - HiLink slangSpecial SpecialChar - HiLink slangTodo Todo - HiLink slangDelim Delimiter +hi def link slangDefinition Type +hi def link slangBlock slangDefinition +hi def link slangLabel Label +hi def link slangConditional Conditional +hi def link slangRepeat Repeat +hi def link slangCharacter Character +hi def link slangFloat Float +hi def link slangImaginary Float +hi def link slangDecimal slangNumber +hi def link slangOctal slangNumber +hi def link slangHex slangNumber +hi def link slangNumber Number +hi def link slangParenError Error +hi def link slangOctalError Error +hi def link slangOperator Operator +hi def link slangStructure Structure +hi def link slangInclude Include +hi def link slangPreCondit PreCondit +hi def link slangError Error +hi def link slangStatement Statement +hi def link slangType Type +hi def link slangString String +hi def link slangConstant Constant +hi def link slangRangeArray slangConstant +hi def link slangComment Comment +hi def link slangSpecial SpecialChar +hi def link slangTodo Todo +hi def link slangDelim Delimiter - delcommand HiLink -endif let b:current_syntax = "slang" diff --git a/runtime/syntax/slice.vim b/runtime/syntax/slice.vim index 4e2f9a8604..3a57ece913 100644 --- a/runtime/syntax/slice.vim +++ b/runtime/syntax/slice.vim @@ -3,11 +3,8 @@ " Maintainer: Morel Bodin <slice06@nym.hush.com> " Last Change: 2005 Dec 03 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -58,33 +55,23 @@ syn match sliceComment "//.*" syn sync ccomment sliceComment " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_slice_syn_inits") - if version < 508 - let did_slice_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink sliceComment Comment - HiLink sliceConstruct Keyword - HiLink sliceType Type - HiLink sliceString String - HiLink sliceIncluded String - HiLink sliceQualifier Keyword - HiLink sliceInclude Include - HiLink sliceGuard PreProc - HiLink sliceBoolean Boolean - HiLink sliceFloat Number - HiLink sliceNumber Number - HiLink sliceOctal Number - HiLink sliceOctalZero Special - HiLink sliceNumberError Special +hi def link sliceComment Comment +hi def link sliceConstruct Keyword +hi def link sliceType Type +hi def link sliceString String +hi def link sliceIncluded String +hi def link sliceQualifier Keyword +hi def link sliceInclude Include +hi def link sliceGuard PreProc +hi def link sliceBoolean Boolean +hi def link sliceFloat Number +hi def link sliceNumber Number +hi def link sliceOctal Number +hi def link sliceOctalZero Special +hi def link sliceNumberError Special - delcommand HiLink -endif let b:current_syntax = "slice" diff --git a/runtime/syntax/slrnrc.vim b/runtime/syntax/slrnrc.vim index 038b62e166..cf0734ae85 100644 --- a/runtime/syntax/slrnrc.vim +++ b/runtime/syntax/slrnrc.vim @@ -3,11 +3,8 @@ " Maintainer: Preben 'Peppe' Guldberg <peppe-vim@wielders.org> " Last Change: 23 April 2006 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -150,44 +147,34 @@ syn match slrnrcSetkey "^\s*setkey\>" skipwhite nextgroup=slrnrcSetkeyArt,slrn syn match slrnrcUnsetkey '^\s*unsetkey\s\+\("\)\=\(article\|group\|readline\)\>\1' skipwhite nextgroup=slrnrcKey contains=slrnrcSetkeyObj\(Str\)\= " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_slrnrc_syntax_inits") - if version < 508 - let did_slrnrc_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink slrnrcTodo Todo - HiLink slrnrcSpaceError Error - HiLink slrnrcNumber Number - HiLink slrnrcSpecKey SpecialChar - HiLink slrnrcKey String - HiLink slrnrcSpecChar SpecialChar - HiLink slrnrcString String - HiLink slrnSlangPreCondit Special - HiLink slrnrcComment Comment - HiLink slrnrcVarInt Identifier - HiLink slrnrcVarStr Identifier - HiLink slrnrcCmd slrnrcSet - HiLink slrnrcSet Operator - HiLink slrnrcColor Keyword - HiLink slrnrcColorObj Identifier - HiLink slrnrcColorVal String - HiLink slrnrcMono Keyword - HiLink slrnrcMonoObj Identifier - HiLink slrnrcMonoVal String - HiLink slrnrcFunArt Macro - HiLink slrnrcFunGroup Macro - HiLink slrnrcFunRead Macro - HiLink slrnrcSetkeyObj Identifier - HiLink slrnrcSetkey Keyword - HiLink slrnrcUnsetkey slrnrcSetkey - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link slrnrcTodo Todo +hi def link slrnrcSpaceError Error +hi def link slrnrcNumber Number +hi def link slrnrcSpecKey SpecialChar +hi def link slrnrcKey String +hi def link slrnrcSpecChar SpecialChar +hi def link slrnrcString String +hi def link slrnSlangPreCondit Special +hi def link slrnrcComment Comment +hi def link slrnrcVarInt Identifier +hi def link slrnrcVarStr Identifier +hi def link slrnrcCmd slrnrcSet +hi def link slrnrcSet Operator +hi def link slrnrcColor Keyword +hi def link slrnrcColorObj Identifier +hi def link slrnrcColorVal String +hi def link slrnrcMono Keyword +hi def link slrnrcMonoObj Identifier +hi def link slrnrcMonoVal String +hi def link slrnrcFunArt Macro +hi def link slrnrcFunGroup Macro +hi def link slrnrcFunRead Macro +hi def link slrnrcSetkeyObj Identifier +hi def link slrnrcSetkey Keyword +hi def link slrnrcUnsetkey slrnrcSetkey + let b:current_syntax = "slrnrc" diff --git a/runtime/syntax/slrnsc.vim b/runtime/syntax/slrnsc.vim index 838af6ad1c..9f51cad380 100644 --- a/runtime/syntax/slrnsc.vim +++ b/runtime/syntax/slrnsc.vim @@ -3,20 +3,13 @@ " Maintainer: Preben 'Peppe' Guldberg <peppe@wielders.org> " Last Change: 8 Oct 2004 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif " characters in newsgroup names -if version < 600 - set isk=@,48-57,.,-,_,+ -else - setlocal isk=@,48-57,.,-,_,+ -endif +setlocal isk=@,48-57,.,-,_,+ syn match slrnscComment "%.*$" syn match slrnscSectionCom ".].*"lc=2 @@ -51,34 +44,24 @@ syn match slrnscScoreIdent contained "%.*" syn match slrnScoreLine "^\s*Score::\=\s\+=\=[-+]\=\d\+\s*\(%.*\)\=$" skipempty nextgroup=slrnscScoreItem contains=slrnscScore,slrnscDelim,slrnscOper,slrnscNumber,slrnscScoreIdent " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_slrnsc_syntax_inits") - if version < 508 - let did_slrnsc_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink slrnscComment Comment - HiLink slrnscSectionCom slrnscComment - HiLink slrnscGroup String - HiLink slrnscNumber Number - HiLink slrnscDate Special - HiLink slrnscDelim Delimiter - HiLink slrnscComma SpecialChar - HiLink slrnscOper SpecialChar - HiLink slrnscEsc String - HiLink slrnscSectionStd Type - HiLink slrnscSectionNot Delimiter - HiLink slrnscItem Statement - HiLink slrnscScore Keyword - HiLink slrnscScoreIdent Identifier - HiLink slrnscInclude Keyword +hi def link slrnscComment Comment +hi def link slrnscSectionCom slrnscComment +hi def link slrnscGroup String +hi def link slrnscNumber Number +hi def link slrnscDate Special +hi def link slrnscDelim Delimiter +hi def link slrnscComma SpecialChar +hi def link slrnscOper SpecialChar +hi def link slrnscEsc String +hi def link slrnscSectionStd Type +hi def link slrnscSectionNot Delimiter +hi def link slrnscItem Statement +hi def link slrnscScore Keyword +hi def link slrnscScoreIdent Identifier +hi def link slrnscInclude Keyword - delcommand HiLink -endif let b:current_syntax = "slrnsc" diff --git a/runtime/syntax/sm.vim b/runtime/syntax/sm.vim index 8fdc14b71a..0ecc96875f 100644 --- a/runtime/syntax/sm.vim +++ b/runtime/syntax/sm.vim @@ -1,10 +1,9 @@ " Vim syntax file " Language: sendmail " Maintainer: Charles E. Campbell <NdrOchipS@PcampbellAfamily.Mbiz> -" Last Change: Oct 23, 2014 -" Version: 7 +" Last Change: Oct 25, 2016 +" Version: 8 " URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_SM - if exists("b:current_syntax") finish endif @@ -56,36 +55,25 @@ syn match smClauseCont contained "^\t" syn region smClause matchgroup=Delimiter start="\$?." matchgroup=Delimiter end="\$\." contains=smElse,smClause,smVar,smClauseCont " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_smil_syntax_inits") - if version < 508 - let did_smil_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink smClause Special - HiLink smClauseError Error - HiLink smComment Comment - HiLink smDefine Statement - HiLink smElse Delimiter - HiLink smHeader Statement - HiLink smHeaderSep String - HiLink smMesg Special - HiLink smPrecedence Number - HiLink smRewrite Statement - HiLink smRewriteComment Comment - HiLink smRewriteLhsToken String - HiLink smRewriteLhsUser Statement - HiLink smRewriteRhsToken String - HiLink smRuleset Preproc - HiLink smTrusted Special - HiLink smVar String - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link smClause Special +hi def link smClauseError Error +hi def link smComment Comment +hi def link smDefine Statement +hi def link smElse Delimiter +hi def link smHeader Statement +hi def link smHeaderSep String +hi def link smMesg Special +hi def link smPrecedence Number +hi def link smRewrite Statement +hi def link smRewriteComment Comment +hi def link smRewriteLhsToken String +hi def link smRewriteLhsUser Statement +hi def link smRewriteRhsToken String +hi def link smRuleset Preproc +hi def link smTrusted Special +hi def link smVar String let b:current_syntax = "sm" diff --git a/runtime/syntax/smarty.vim b/runtime/syntax/smarty.vim index 6dda366ba2..a39c290abe 100644 --- a/runtime/syntax/smarty.vim +++ b/runtime/syntax/smarty.vim @@ -8,11 +8,10 @@ " For version 5.x: Clear all syntax items " For version 6.x: Quit when a syntax file was already loaded if !exists("main_syntax") - if version < 600 - syntax clear - elseif exists("b:current_syntax") - finish -endif + " quit when a syntax file was already loaded + if exists("b:current_syntax") + finish + endif let main_syntax = 'smarty' endif @@ -57,25 +56,16 @@ syn region htmlString contained start=+'+ end=+'+ contains=htmlSpecialChar,ja syn region htmlLink start="<a\>\_[^>]*\<href\>" end="</a>"me=e-4 contains=@Spell,htmlTag,htmlEndTag,htmlSpecialChar,htmlPreProc,htmlComment,javaScript,@htmlPreproc,smartyZone -if version >= 508 || !exists("did_smarty_syn_inits") - if version < 508 - let did_smarty_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - HiLink smartyTagName Identifier - HiLink smartyProperty Constant - " if you want the text inside the braces to be colored, then - " remove the comment in from of the next statement - "HiLink smartyZone Include - HiLink smartyInFunc Function - HiLink smartyBlock Constant - HiLink smartyDot SpecialChar - HiLink smartyModifier Function - delcommand HiLink -endif +hi def link smartyTagName Identifier +hi def link smartyProperty Constant +" if you want the text inside the braces to be colored, then +" remove the comment in from of the next statement +"hi def link smartyZone Include +hi def link smartyInFunc Function +hi def link smartyBlock Constant +hi def link smartyDot SpecialChar +hi def link smartyModifier Function let b:current_syntax = "smarty" diff --git a/runtime/syntax/smcl.vim b/runtime/syntax/smcl.vim index d9afba6de5..a5baa47e96 100644 --- a/runtime/syntax/smcl.vim +++ b/runtime/syntax/smcl.vim @@ -10,9 +10,8 @@ " check for 'b:current_syntax', removed 'did_smcl_syntax_inits' " 26apr2006 changed 'stata_smcl' to 'smcl' -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif diff --git a/runtime/syntax/smil.vim b/runtime/syntax/smil.vim index 6b5a002868..4cf6e84710 100644 --- a/runtime/syntax/smil.vim +++ b/runtime/syntax/smil.vim @@ -7,11 +7,8 @@ " To learn more about SMIL, please refer to http://www.w3.org/AudioVideo/ " and to http://www.helio.org/products/smil/tutorial/ -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -115,38 +112,28 @@ endif syn region smilComment start=+<!DOCTYPE+ keepend end=+>+ " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_smil_syntax_inits") - if version < 508 - let did_smil_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink smilTag Function - HiLink smilEndTag Identifier - HiLink smilArg Type - HiLink smilTagName smilStatement - HiLink smilSpecialTagName Exception - HiLink smilValue Value - HiLink smilSpecialChar Special - - HiLink smilSpecial Special - HiLink smilSpecialChar Special - HiLink smilString String - HiLink smilStatement Statement - HiLink smilComment Comment - HiLink smilCommentPart Comment - HiLink smilPreProc PreProc - HiLink smilValue String - HiLink smilCommentError smilError - HiLink smilTagError smilError - HiLink smilError Error - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link smilTag Function +hi def link smilEndTag Identifier +hi def link smilArg Type +hi def link smilTagName smilStatement +hi def link smilSpecialTagName Exception +hi def link smilValue Value +hi def link smilSpecialChar Special + +hi def link smilSpecial Special +hi def link smilSpecialChar Special +hi def link smilString String +hi def link smilStatement Statement +hi def link smilComment Comment +hi def link smilCommentPart Comment +hi def link smilPreProc PreProc +hi def link smilValue String +hi def link smilCommentError smilError +hi def link smilTagError smilError +hi def link smilError Error + let b:current_syntax = "smil" diff --git a/runtime/syntax/smith.vim b/runtime/syntax/smith.vim index e05ce69683..b045d3b963 100644 --- a/runtime/syntax/smith.vim +++ b/runtime/syntax/smith.vim @@ -3,11 +3,8 @@ " Maintainer: Rafal M. Sulejman <rms@poczta.onet.pl> " Last Change: 21.07.2000 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -28,24 +25,14 @@ syn region smithString start=+"+ skip=+\\\\\|\\"+ end=+"+ syn case match " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_smith_syntax_inits") - if version < 508 - let did_smith_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink smithRegister Identifier - HiLink smithKeyword Keyword - HiLink smithComment Comment - HiLink smithString String - HiLink smithNumber Number - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link smithRegister Identifier +hi def link smithKeyword Keyword +hi def link smithComment Comment +hi def link smithString String +hi def link smithNumber Number + let b:current_syntax = "smith" diff --git a/runtime/syntax/sml.vim b/runtime/syntax/sml.vim index aa7d64a33a..fa4524f93d 100644 --- a/runtime/syntax/sml.vim +++ b/runtime/syntax/sml.vim @@ -8,11 +8,8 @@ " 2002 Jun 02 - Fixed small typo (MM) " 2001 Nov 20 - Fixed small highlighting bug with modules (MM) -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -168,62 +165,52 @@ syn sync match smlSigSync grouphere smlSig "\<sig\>" syn sync match smlSigSync groupthere smlSig "\<end\>" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_sml_syntax_inits") - if version < 508 - let did_sml_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink smlBraceErr Error - HiLink smlBrackErr Error - HiLink smlParenErr Error - - HiLink smlCommentErr Error - - HiLink smlEndErr Error - HiLink smlThenErr Error - - HiLink smlCharErr Error - - HiLink smlComment Comment - - HiLink smlModPath Include - HiLink smlModule Include - HiLink smlModParam1 Include - HiLink smlModType Include - HiLink smlMPRestr3 Include - HiLink smlFullMod Include - HiLink smlModTypeRestr Include - HiLink smlWith Include - HiLink smlMTDef Include - - HiLink smlConstructor Constant - - HiLink smlModPreRHS Keyword - HiLink smlMPRestr2 Keyword - HiLink smlKeyword Keyword - HiLink smlFunDef Keyword - HiLink smlRefAssign Keyword - HiLink smlKeyChar Keyword - HiLink smlAnyVar Keyword - HiLink smlTopStop Keyword - HiLink smlOperator Keyword - - HiLink smlBoolean Boolean - HiLink smlCharacter Character - HiLink smlNumber Number - HiLink smlReal Float - HiLink smlString String - HiLink smlType Type - HiLink smlTodo Todo - HiLink smlEncl Keyword - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link smlBraceErr Error +hi def link smlBrackErr Error +hi def link smlParenErr Error + +hi def link smlCommentErr Error + +hi def link smlEndErr Error +hi def link smlThenErr Error + +hi def link smlCharErr Error + +hi def link smlComment Comment + +hi def link smlModPath Include +hi def link smlModule Include +hi def link smlModParam1 Include +hi def link smlModType Include +hi def link smlMPRestr3 Include +hi def link smlFullMod Include +hi def link smlModTypeRestr Include +hi def link smlWith Include +hi def link smlMTDef Include + +hi def link smlConstructor Constant + +hi def link smlModPreRHS Keyword +hi def link smlMPRestr2 Keyword +hi def link smlKeyword Keyword +hi def link smlFunDef Keyword +hi def link smlRefAssign Keyword +hi def link smlKeyChar Keyword +hi def link smlAnyVar Keyword +hi def link smlTopStop Keyword +hi def link smlOperator Keyword + +hi def link smlBoolean Boolean +hi def link smlCharacter Character +hi def link smlNumber Number +hi def link smlReal Float +hi def link smlString String +hi def link smlType Type +hi def link smlTodo Todo +hi def link smlEncl Keyword + let b:current_syntax = "sml" diff --git a/runtime/syntax/snnsnet.vim b/runtime/syntax/snnsnet.vim index 6b24de5634..9dc9e06e78 100644 --- a/runtime/syntax/snnsnet.vim +++ b/runtime/syntax/snnsnet.vim @@ -8,9 +8,8 @@ " SNNS http://www-ra.informatik.uni-tuebingen.de/SNNS/ " is a simulator for neural networks. -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -54,23 +53,14 @@ syn match snnsnetNumbers "\d" contained syn match snnsnetComment "#.*$" contains=snnsnetTodo syn keyword snnsnetTodo TODO XXX FIXME contained -if version >= 508 || !exists("did_snnsnet_syn_inits") - if version < 508 - let did_snnsnet_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - HiLink snnsnetType Type - HiLink snnsnetComment Comment - HiLink snnsnetNumbers Number - HiLink snnsnetSection Statement - HiLink snnsnetTitle Label - HiLink snnsnetTodo Todo +hi def link snnsnetType Type +hi def link snnsnetComment Comment +hi def link snnsnetNumbers Number +hi def link snnsnetSection Statement +hi def link snnsnetTitle Label +hi def link snnsnetTodo Todo - delcommand HiLink -endif let b:current_syntax = "snnsnet" diff --git a/runtime/syntax/snnspat.vim b/runtime/syntax/snnspat.vim index 5bfa48e624..cb6e9c5bd1 100644 --- a/runtime/syntax/snnspat.vim +++ b/runtime/syntax/snnspat.vim @@ -8,9 +8,8 @@ " SNNS http://www-ra.informatik.uni-tuebingen.de/SNNS/ " is a simulator for neural networks. -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -44,26 +43,17 @@ syn match snnspatNumbers "\d" contained syn match snnspatComment "#.*$" contains=snnspatTodo syn keyword snnspatTodo TODO XXX FIXME contained -if version >= 508 || !exists("did_snnspat_syn_inits") - if version < 508 - let did_snnspat_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - HiLink snnspatGen Statement - HiLink snnspatHeader Error - HiLink snnspatNoHeader Define - HiLink snnspatNumbers Number - HiLink snnspatComment Comment - HiLink snnspatError Error - HiLink snnspatTodo Todo - HiLink snnspatAccepted NONE - HiLink snnspatBrac NONE +hi def link snnspatGen Statement +hi def link snnspatHeader Error +hi def link snnspatNoHeader Define +hi def link snnspatNumbers Number +hi def link snnspatComment Comment +hi def link snnspatError Error +hi def link snnspatTodo Todo +hi def link snnspatAccepted NONE +hi def link snnspatBrac NONE - delcommand HiLink -endif let b:current_syntax = "snnspat" diff --git a/runtime/syntax/snnsres.vim b/runtime/syntax/snnsres.vim index 4c1d596009..2f19b67dbe 100644 --- a/runtime/syntax/snnsres.vim +++ b/runtime/syntax/snnsres.vim @@ -8,9 +8,8 @@ " SNNS http://www-ra.informatik.uni-tuebingen.de/SNNS/ " is a simulator for neural networks. -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -37,23 +36,14 @@ syn match snnsresNumbers "\d" contained syn match snnsresComment "#.*$" contains=snnsresTodo syn keyword snnsresTodo TODO XXX FIXME contained -if version >= 508 || !exists("did_snnsres_syn_inits") - if version < 508 - let did_snnsres_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink snnsresGen Statement - HiLink snnsresHeader Statement - HiLink snnsresNoHeader Define - HiLink snnsresNumbers Number - HiLink snnsresComment Comment - HiLink snnsresTodo Todo - - delcommand HiLink -endif + +hi def link snnsresGen Statement +hi def link snnsresHeader Statement +hi def link snnsresNoHeader Define +hi def link snnsresNumbers Number +hi def link snnsresComment Comment +hi def link snnsresTodo Todo + let b:current_syntax = "snnsres" diff --git a/runtime/syntax/snobol4.vim b/runtime/syntax/snobol4.vim index 07eb63dec7..a14f15eef4 100644 --- a/runtime/syntax/snobol4.vim +++ b/runtime/syntax/snobol4.vim @@ -10,11 +10,8 @@ " - one character labels weren't displayed correctly. " - nonexistent Snobol4 keywords displayed as errors. -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -79,47 +76,37 @@ syn match snobol4ErrInBracket display contained "[){}]\|<%\|%>" " syn match snobol4Comment "^\#\!.*$" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_snobol4_syntax_inits") - if version < 508 - let did_snobol4_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink snobol4Constant Constant - HiLink snobol4Label Label - HiLink snobol4Goto Repeat - HiLink snobol4Conditional Conditional - HiLink snobol4Repeat Repeat - HiLink snobol4Number Number - HiLink snobol4Error Error - HiLink snobol4Statement PreProc - HiLink snobol4BogusStatement snobol4Error - HiLink snobol4String String - HiLink snobol4Comment Comment - HiLink snobol4Special Special - HiLink snobol4Todo Todo - HiLink snobol4Keyword Keyword - HiLink snobol4Function Function - HiLink snobol4MathsOperator Operator - HiLink snobol4ParenError snobol4Error - HiLink snobol4ErrInParen snobol4Error - HiLink snobol4ErrInBracket snobol4Error - HiLink snobol4SysVar Keyword - HiLink snobol4BogusSysVar snobol4Error - if exists("snobol4_strict_mode") - HiLink snobol4ExtSysVar WarningMsg - HiLink snobol4ExtKeyword WarningMsg - else - HiLink snobol4ExtSysVar snobol4SysVar - HiLink snobol4ExtKeyword snobol4Keyword - endif - - delcommand HiLink +hi def link snobol4Constant Constant +hi def link snobol4Label Label +hi def link snobol4Goto Repeat +hi def link snobol4Conditional Conditional +hi def link snobol4Repeat Repeat +hi def link snobol4Number Number +hi def link snobol4Error Error +hi def link snobol4Statement PreProc +hi def link snobol4BogusStatement snobol4Error +hi def link snobol4String String +hi def link snobol4Comment Comment +hi def link snobol4Special Special +hi def link snobol4Todo Todo +hi def link snobol4Keyword Keyword +hi def link snobol4Function Function +hi def link snobol4MathsOperator Operator +hi def link snobol4ParenError snobol4Error +hi def link snobol4ErrInParen snobol4Error +hi def link snobol4ErrInBracket snobol4Error +hi def link snobol4SysVar Keyword +hi def link snobol4BogusSysVar snobol4Error +if exists("snobol4_strict_mode") +hi def link snobol4ExtSysVar WarningMsg +hi def link snobol4ExtKeyword WarningMsg +else +hi def link snobol4ExtSysVar snobol4SysVar +hi def link snobol4ExtKeyword snobol4Keyword endif + let b:current_syntax = "snobol4" " vim: ts=8 diff --git a/runtime/syntax/spec.vim b/runtime/syntax/spec.vim index 9952bd2548..3a7dc9e422 100644 --- a/runtime/syntax/spec.vim +++ b/runtime/syntax/spec.vim @@ -5,11 +5,8 @@ " Former Maintainer: Donovan Rebbechi elflord@panix.com (until March 2014) " Last Change: Sat Apr 9 15:30 2016 Filip Szymaลski -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -159,78 +156,68 @@ syn sync match shCaseEsacSync grouphere shCaseEsac "\<case\>" syn sync match shCaseEsacSync groupthere shCaseEsac "\<esac\>" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_spec_syntax_inits") - if version < 508 - let did_spec_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - "main types color definitions - HiLink specSection Structure - HiLink specSectionMacro Macro - HiLink specWWWlink PreProc - HiLink specOpts Operator - - "yes, it's ugly, but white is sooo cool - if &background == "dark" - hi def specGlobalMacro ctermfg=white - else - HiLink specGlobalMacro Identifier - endif - - "sh colors - HiLink shComment Comment - HiLink shIf Statement - HiLink shOperator Special - HiLink shQuote1 String - HiLink shQuote2 String - HiLink shQuoteDelim Statement - - "spec colors - HiLink specBlock Function - HiLink specColon Special - HiLink specCommand Statement - HiLink specCommandOpts specOpts - HiLink specCommandSpecial Special - HiLink specComment Comment - HiLink specConfigure specCommand - HiLink specDate String - HiLink specDescriptionOpts specOpts - HiLink specEmail specWWWlink - HiLink specError Error - HiLink specFilesDirective specSectionMacro - HiLink specFilesOpts specOpts - HiLink specLicense String - HiLink specMacroNameLocal specGlobalMacro - HiLink specMacroNameOther specGlobalMacro - HiLink specManpageFile NONE - HiLink specMonth specDate - HiLink specNoNumberHilite NONE - HiLink specNumber Number - HiLink specPackageOpts specOpts - HiLink specPercent Special - HiLink specSpecialChar Special - HiLink specSpecialVariables specGlobalMacro - HiLink specSpecialVariablesNames specGlobalMacro - HiLink specTarCommand specCommand - HiLink specURL specWWWlink - HiLink specURLMacro specWWWlink - HiLink specVariables Identifier - HiLink specWeekday specDate - HiLink specListedFilesBin Statement - HiLink specListedFilesDoc Statement - HiLink specListedFilesEtc Statement - HiLink specListedFilesLib Statement - HiLink specListedFilesPrefix Statement - HiLink specListedFilesShare Statement - - delcommand HiLink +" Only when an item doesn't have highlighting yet + +"main types color definitions +hi def link specSection Structure +hi def link specSectionMacro Macro +hi def link specWWWlink PreProc +hi def link specOpts Operator + +"yes, it's ugly, but white is sooo cool +if &background == "dark" +hi def specGlobalMacro ctermfg=white +else +hi def link specGlobalMacro Identifier endif +"sh colors +hi def link shComment Comment +hi def link shIf Statement +hi def link shOperator Special +hi def link shQuote1 String +hi def link shQuote2 String +hi def link shQuoteDelim Statement + +"spec colors +hi def link specBlock Function +hi def link specColon Special +hi def link specCommand Statement +hi def link specCommandOpts specOpts +hi def link specCommandSpecial Special +hi def link specComment Comment +hi def link specConfigure specCommand +hi def link specDate String +hi def link specDescriptionOpts specOpts +hi def link specEmail specWWWlink +hi def link specError Error +hi def link specFilesDirective specSectionMacro +hi def link specFilesOpts specOpts +hi def link specLicense String +hi def link specMacroNameLocal specGlobalMacro +hi def link specMacroNameOther specGlobalMacro +hi def link specManpageFile NONE +hi def link specMonth specDate +hi def link specNoNumberHilite NONE +hi def link specNumber Number +hi def link specPackageOpts specOpts +hi def link specPercent Special +hi def link specSpecialChar Special +hi def link specSpecialVariables specGlobalMacro +hi def link specSpecialVariablesNames specGlobalMacro +hi def link specTarCommand specCommand +hi def link specURL specWWWlink +hi def link specURLMacro specWWWlink +hi def link specVariables Identifier +hi def link specWeekday specDate +hi def link specListedFilesBin Statement +hi def link specListedFilesDoc Statement +hi def link specListedFilesEtc Statement +hi def link specListedFilesLib Statement +hi def link specListedFilesPrefix Statement +hi def link specListedFilesShare Statement + + let b:current_syntax = "spec" " vim: ts=8 diff --git a/runtime/syntax/specman.vim b/runtime/syntax/specman.vim index 93fb4a86c6..9387925ef2 100644 --- a/runtime/syntax/specman.vim +++ b/runtime/syntax/specman.vim @@ -10,11 +10,8 @@ "--------------------------------------------------------- " Remove any old syntax stuff hanging around -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -137,46 +134,36 @@ syn region specmanString start=+"+ end=+"+ syn sync lines=50 " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_specman_syn_inits") - if version < 508 - let did_specman_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - " The default methods for highlighting. Can be overridden later - HiLink specmanConditional Conditional - HiLink specmanConstraint Conditional - HiLink specmanRepeat Repeat - HiLink specmanString String - HiLink specmanComment Comment - HiLink specmanConstant Macro - HiLink specmanNumber Number - HiLink specmanCompare Operator - HiLink specmanOperator Operator - HiLink specmanLogical Operator - HiLink specmanStatement Statement - HiLink specmanHDL SpecialChar - HiLink specmanMethod Function - HiLink specmanInclude Include - HiLink specmanStructure Structure - HiLink specmanBoolean Boolean - HiLink specmanFSM Label - HiLink specmanSpecial Special - HiLink specmanType Type - HiLink specmanTemporal Type - HiLink specmanFile Include - HiLink specmanPreCondit Include - HiLink specmanDefine Typedef - HiLink specmanLabel Label - HiLink specmanPacking keyword - HiLink specmanTodo Todo - HiLink specmanParenError Error - HiLink specmanErrInParen Error - HiLink specmanErrInBracket Error - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet +" The default methods for highlighting. Can be overridden later +hi def link specmanConditional Conditional +hi def link specmanConstraint Conditional +hi def link specmanRepeat Repeat +hi def link specmanString String +hi def link specmanComment Comment +hi def link specmanConstant Macro +hi def link specmanNumber Number +hi def link specmanCompare Operator +hi def link specmanOperator Operator +hi def link specmanLogical Operator +hi def link specmanStatement Statement +hi def link specmanHDL SpecialChar +hi def link specmanMethod Function +hi def link specmanInclude Include +hi def link specmanStructure Structure +hi def link specmanBoolean Boolean +hi def link specmanFSM Label +hi def link specmanSpecial Special +hi def link specmanType Type +hi def link specmanTemporal Type +hi def link specmanFile Include +hi def link specmanPreCondit Include +hi def link specmanDefine Typedef +hi def link specmanLabel Label +hi def link specmanPacking keyword +hi def link specmanTodo Todo +hi def link specmanParenError Error +hi def link specmanErrInParen Error +hi def link specmanErrInBracket Error let b:current_syntax = "specman" diff --git a/runtime/syntax/spice.vim b/runtime/syntax/spice.vim index 200e1aaea4..306039bc74 100644 --- a/runtime/syntax/spice.vim +++ b/runtime/syntax/spice.vim @@ -7,11 +7,8 @@ " This is based on sh.vim by Lennart Schultz " but greatly simplified -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -53,28 +50,18 @@ syn match spiceParenError ")" syn sync minlines=50 " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_spice_syntax_inits") - if version < 508 - let did_spice_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink spiceTodo Todo - HiLink spiceWrapLineOperator spiceOperator - HiLink spiceSinglequote spiceExpr - HiLink spiceExpr Function - HiLink spiceParenError Error - HiLink spiceStatement Statement - HiLink spiceNumber Number - HiLink spiceComment Comment - HiLink spiceOperator Operator - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link spiceTodo Todo +hi def link spiceWrapLineOperator spiceOperator +hi def link spiceSinglequote spiceExpr +hi def link spiceExpr Function +hi def link spiceParenError Error +hi def link spiceStatement Statement +hi def link spiceNumber Number +hi def link spiceComment Comment +hi def link spiceOperator Operator + let b:current_syntax = "spice" diff --git a/runtime/syntax/splint.vim b/runtime/syntax/splint.vim index dc09d8b9d6..8eba57d288 100644 --- a/runtime/syntax/splint.vim +++ b/runtime/syntax/splint.vim @@ -15,20 +15,13 @@ " in your vimrc file or filetype.vim -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif " Read the C syntax to start with -if version < 600 - so <sfile>:p:h/c.vim -else - runtime! syntax/c.vim -endif +runtime! syntax/c.vim " FIXME: uses and changes several clusters defined in c.vim @@ -199,61 +192,51 @@ syn cluster cPreProcGroup add=@splintAllStuff syn cluster cMultiGroup add=@splintAllStuff " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_splint_syntax_inits") - if version < 508 - let did_splint_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink splintShortAnn splintAnnotation - HiLink splintAnnotation Comment - HiLink splintAnnError splintError - HiLink splintAnnError2 splintError - HiLink splintFlag SpecialComment - HiLink splintGlobalFlag splintError - HiLink splintSpecialAnnot splintAnnKey - HiLink splintStateAnnot splintAnnKey - HiLink splintSpecTag splintAnnKey - HiLink splintModifies splintAnnKey - HiLink splintRequires splintAnnKey - HiLink splintGlobals splintAnnKey - HiLink splintGlobitem Constant - HiLink splintGlobannot splintAnnKey - HiLink splintWarning splintAnnKey - HiLink splintModitem Constant - HiLink splintIter splintAnnKey - HiLink splintConst splintAnnKey - HiLink splintAlt splintAnnKey - HiLink splintType splintAnnKey - HiLink splintGlobalType splintAnnKey - HiLink splintMemMgm splintAnnKey - HiLink splintAlias splintAnnKey - HiLink splintExposure splintAnnKey - HiLink splintDefState splintAnnKey - HiLink splintGlobState splintAnnKey - HiLink splintNullState splintAnnKey - HiLink splintNullPred splintAnnKey - HiLink splintExit splintAnnKey - HiLink splintExec splintAnnKey - HiLink splintSef splintAnnKey - HiLink splintDecl splintAnnKey - HiLink splintCase splintAnnKey - HiLink splintBreak splintAnnKey - HiLink splintUnreach splintAnnKey - HiLink splintSpecFunc splintAnnKey - HiLink splintErrSupp splintAnnKey - HiLink splintTypeAcc splintAnnKey - HiLink splintMacro splintAnnKey - HiLink splintSpecType splintAnnKey - HiLink splintAnnKey Type - HiLink splintError Error +" Only when an item doesn't have highlighting yet + +hi def link splintShortAnn splintAnnotation +hi def link splintAnnotation Comment +hi def link splintAnnError splintError +hi def link splintAnnError2 splintError +hi def link splintFlag SpecialComment +hi def link splintGlobalFlag splintError +hi def link splintSpecialAnnot splintAnnKey +hi def link splintStateAnnot splintAnnKey +hi def link splintSpecTag splintAnnKey +hi def link splintModifies splintAnnKey +hi def link splintRequires splintAnnKey +hi def link splintGlobals splintAnnKey +hi def link splintGlobitem Constant +hi def link splintGlobannot splintAnnKey +hi def link splintWarning splintAnnKey +hi def link splintModitem Constant +hi def link splintIter splintAnnKey +hi def link splintConst splintAnnKey +hi def link splintAlt splintAnnKey +hi def link splintType splintAnnKey +hi def link splintGlobalType splintAnnKey +hi def link splintMemMgm splintAnnKey +hi def link splintAlias splintAnnKey +hi def link splintExposure splintAnnKey +hi def link splintDefState splintAnnKey +hi def link splintGlobState splintAnnKey +hi def link splintNullState splintAnnKey +hi def link splintNullPred splintAnnKey +hi def link splintExit splintAnnKey +hi def link splintExec splintAnnKey +hi def link splintSef splintAnnKey +hi def link splintDecl splintAnnKey +hi def link splintCase splintAnnKey +hi def link splintBreak splintAnnKey +hi def link splintUnreach splintAnnKey +hi def link splintSpecFunc splintAnnKey +hi def link splintErrSupp splintAnnKey +hi def link splintTypeAcc splintAnnKey +hi def link splintMacro splintAnnKey +hi def link splintSpecType splintAnnKey +hi def link splintAnnKey Type +hi def link splintError Error - delcommand HiLink -endif let b:current_syntax = "splint" diff --git a/runtime/syntax/spup.vim b/runtime/syntax/spup.vim index 8d7a9e525c..743c7b5711 100644 --- a/runtime/syntax/spup.vim +++ b/runtime/syntax/spup.vim @@ -17,11 +17,8 @@ " If you encounter problems or have questions or suggestions, mail me " Remove old syntax stuff -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -206,74 +203,64 @@ syn sync match spupSyncTitle grouphere spupTitle "^TITLE" syn sync match spupSyncUnit grouphere spupUnit "^UNIT" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_spup_syn_inits") - if version < 508 - let did_spup_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink spupCdi spupSection - HiLink spupConditions spupSection - HiLink spupDeclare spupSection - HiLink spupEstimation spupSection - HiLink spupExternal spupSection - HiLink spupFlowsheet spupSection - HiLink spupFunction spupSection - HiLink spupGlobal spupSection - HiLink spupHomotopy spupSection - HiLink spupMacro spupSection - HiLink spupModel spupSection - HiLink spupOperation spupSection - HiLink spupOptions spupSection - HiLink spupProcedure spupSection - HiLink spupProfiles spupSection - HiLink spupReport spupSection - HiLink spupTitle spupConstant " this is correct, truly ;) - HiLink spupUnit spupSection +hi def link spupCdi spupSection +hi def link spupConditions spupSection +hi def link spupDeclare spupSection +hi def link spupEstimation spupSection +hi def link spupExternal spupSection +hi def link spupFlowsheet spupSection +hi def link spupFunction spupSection +hi def link spupGlobal spupSection +hi def link spupHomotopy spupSection +hi def link spupMacro spupSection +hi def link spupModel spupSection +hi def link spupOperation spupSection +hi def link spupOptions spupSection +hi def link spupProcedure spupSection +hi def link spupProfiles spupSection +hi def link spupReport spupSection +hi def link spupTitle spupConstant " this is correct, truly ;) +hi def link spupUnit spupSection - HiLink spupCdiSubs spupSubs - HiLink spupConditionsSubs spupSubs - HiLink spupDeclareSubs spupSubs - HiLink spupEstimationSubs spupSubs - HiLink spupExternalSubs spupSubs - HiLink spupFlowsheetSubs spupSubs - HiLink spupFunctionSubs spupSubs - HiLink spupHomotopySubs spupSubs - HiLink spupMacroSubs spupSubs - HiLink spupModelSubs spupSubs - HiLink spupOperationSubs spupSubs - HiLink spupOptionsSubs spupSubs - HiLink spupProcedureSubs spupSubs - HiLink spupReportSubs spupSubs - HiLink spupUnitSubs spupSubs +hi def link spupCdiSubs spupSubs +hi def link spupConditionsSubs spupSubs +hi def link spupDeclareSubs spupSubs +hi def link spupEstimationSubs spupSubs +hi def link spupExternalSubs spupSubs +hi def link spupFlowsheetSubs spupSubs +hi def link spupFunctionSubs spupSubs +hi def link spupHomotopySubs spupSubs +hi def link spupMacroSubs spupSubs +hi def link spupModelSubs spupSubs +hi def link spupOperationSubs spupSubs +hi def link spupOptionsSubs spupSubs +hi def link spupProcedureSubs spupSubs +hi def link spupReportSubs spupSubs +hi def link spupUnitSubs spupSubs - HiLink spupCode Normal - HiLink spupComment Comment - HiLink spupComment2 spupComment - HiLink spupConditional Statement - HiLink spupConstant Constant - HiLink spupError Error - HiLink spupHelp Normal - HiLink spupIdentifier Identifier - HiLink spupNumber Constant - HiLink spupOperator Special - HiLink spupOpenBrace spupError - HiLink spupSection Statement - HiLink spupSpecial spupTextprocGeneric - HiLink spupStreams Type - HiLink spupString Constant - HiLink spupSubs Statement - HiLink spupSymbol Special - HiLink spupTextprocError Normal - HiLink spupTextprocGeneric PreProc - HiLink spupTypes Type +hi def link spupCode Normal +hi def link spupComment Comment +hi def link spupComment2 spupComment +hi def link spupConditional Statement +hi def link spupConstant Constant +hi def link spupError Error +hi def link spupHelp Normal +hi def link spupIdentifier Identifier +hi def link spupNumber Constant +hi def link spupOperator Special +hi def link spupOpenBrace spupError +hi def link spupSection Statement +hi def link spupSpecial spupTextprocGeneric +hi def link spupStreams Type +hi def link spupString Constant +hi def link spupSubs Statement +hi def link spupSymbol Special +hi def link spupTextprocError Normal +hi def link spupTextprocGeneric PreProc +hi def link spupTypes Type - delcommand HiLink -endif let b:current_syntax = "spup" diff --git a/runtime/syntax/spyce.vim b/runtime/syntax/spyce.vim index e76cb1a1a2..169de199dc 100644 --- a/runtime/syntax/spyce.vim +++ b/runtime/syntax/spyce.vim @@ -4,11 +4,8 @@ " URL: http://spyce.sourceforge.net " Last Change: 2009 Nov 11 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -20,13 +17,9 @@ endif " Read the HTML syntax to start with let b:did_indent = 1 " don't perform HTML indentation! let html_no_rendering = 1 " do not render <b>,<i>, etc... -if version < 600 - so <sfile>:p:h/html.vim -else - runtime! syntax/html.vim - unlet b:current_syntax - syntax spell default " added by Bram -endif +runtime! syntax/html.vim +unlet b:current_syntax +syntax spell default " added by Bram " include python syn include @Python <sfile>:p:h/python.vim diff --git a/runtime/syntax/sql.vim b/runtime/syntax/sql.vim index 7ba20f3446..6de3f4a5c0 100644 --- a/runtime/syntax/sql.vim +++ b/runtime/syntax/sql.vim @@ -10,11 +10,8 @@ " If the above exist, it will source the type specified. " If none exist, it will source the default sql.vim file. " -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif diff --git a/runtime/syntax/sqlanywhere.vim b/runtime/syntax/sqlanywhere.vim index 05b05c9f4f..e91a99de65 100644 --- a/runtime/syntax/sqlanywhere.vim +++ b/runtime/syntax/sqlanywhere.vim @@ -12,11 +12,8 @@ " Updated to Adaptive Server Anywhere 9.0.1 " Updated to Adaptive Server Anywhere 9.0.0 " -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif diff --git a/runtime/syntax/sqlforms.vim b/runtime/syntax/sqlforms.vim index 055b2ae870..6077dd1e94 100644 --- a/runtime/syntax/sqlforms.vim +++ b/runtime/syntax/sqlforms.vim @@ -7,21 +7,14 @@ " " TODO Find a new maintainer who knows SQL*Forms. - " For version 5.x, clear all syntax items. - " For version 6.x, quit when a syntax file was already loaded. -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif syntax case ignore -if version >= 600 - setlocal iskeyword=a-z,A-Z,48-57,_,.,-,> -else - set iskeyword=a-z,A-Z,48-57,_,.,-,> -endif +setlocal iskeyword=a-z,A-Z,48-57,_,.,-,> " The SQL reserved words, defined as keywords. @@ -138,30 +131,21 @@ syntax match sqlNumber "-\=\<[0-9]*\.\=[0-9_]\>" syntax sync ccomment sqlComment -if version >= 508 || !exists("did_sqlforms_syn_inits") - if version < 508 - let did_sqlforms_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink sqlComment Comment - HiLink sqlKeyword Statement - HiLink sqlNumber Number - HiLink sqlOperator Statement - HiLink sqlProcedure Statement - HiLink sqlFunction Statement - HiLink sqlSystem Identifier - HiLink sqlSpecial Special - HiLink sqlStatement Statement - HiLink sqlString String - HiLink sqlType Type - HiLink sqlCodes Identifier - HiLink sqlTriggers PreProc - - delcommand HiLink -endif + +hi def link sqlComment Comment +hi def link sqlKeyword Statement +hi def link sqlNumber Number +hi def link sqlOperator Statement +hi def link sqlProcedure Statement +hi def link sqlFunction Statement +hi def link sqlSystem Identifier +hi def link sqlSpecial Special +hi def link sqlStatement Statement +hi def link sqlString String +hi def link sqlType Type +hi def link sqlCodes Identifier +hi def link sqlTriggers PreProc + let b:current_syntax = "sqlforms" diff --git a/runtime/syntax/sqlhana.vim b/runtime/syntax/sqlhana.vim index 1410e99eb4..2e334bb56e 100644 --- a/runtime/syntax/sqlhana.vim +++ b/runtime/syntax/sqlhana.vim @@ -7,11 +7,8 @@ " Description: Updated to SAP HANA SP4 " -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif diff --git a/runtime/syntax/sqlinformix.vim b/runtime/syntax/sqlinformix.vim index b4d023600c..e01912bc40 100644 --- a/runtime/syntax/sqlinformix.vim +++ b/runtime/syntax/sqlinformix.vim @@ -4,11 +4,8 @@ " Maintainer: Dean Hill <dhill@hotmail.com> " Last Change: 2004 Aug 30 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -154,43 +151,33 @@ syn keyword sqlTodo TODO FIXME XXX DEBUG NOTE " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_sql_syn_inits") - if version < 508 - let did_sql_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - - " === Comment syntax group === - HiLink sqlComment Comment - - " === Constant syntax group === - HiLink sqlNumber Number - HiLink sqlBoolean Boolean - HiLink sqlString String - - " === Statment syntax group === - HiLink sqlStatement Statement - HiLink sqlConditional Conditional - HiLink sqlRepeat Repeat - HiLink sqlKeyword Keyword - HiLink sqlOperator Operator - HiLink sqlException Exception - - " === Identifier syntax group === - HiLink sqlFunction Function - - " === Type syntax group === - HiLink sqlType Type - - " === Todo syntax group === - HiLink sqlTodo Todo - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + + +" === Comment syntax group === +hi def link sqlComment Comment + +" === Constant syntax group === +hi def link sqlNumber Number +hi def link sqlBoolean Boolean +hi def link sqlString String + +" === Statment syntax group === +hi def link sqlStatement Statement +hi def link sqlConditional Conditional +hi def link sqlRepeat Repeat +hi def link sqlKeyword Keyword +hi def link sqlOperator Operator +hi def link sqlException Exception + +" === Identifier syntax group === +hi def link sqlFunction Function + +" === Type syntax group === +hi def link sqlType Type + +" === Todo syntax group === +hi def link sqlTodo Todo + let b:current_syntax = "sqlinformix" diff --git a/runtime/syntax/sqlj.vim b/runtime/syntax/sqlj.vim index 51398ef9c2..c901145c3c 100644 --- a/runtime/syntax/sqlj.vim +++ b/runtime/syntax/sqlj.vim @@ -8,10 +8,8 @@ " au BufNewFile,BufRead *.sqlj so $VIM/syntax/sqlj.vim -" Remove any old syntax stuff hanging around -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -76,27 +74,18 @@ syn match sqlComment "--.*" syn sync ccomment sqljComment -if version >= 508 || !exists("did_sqlj_syn_inits") - if version < 508 - let did_sqlj_syn_inits = 1 - command! -nargs=+ HiLink hi link <args> - else - command! -nargs=+ HiLink hi def link <args> - endif - - " The default methods for highlighting. Can be overridden later. - HiLink sqljComment Comment - HiLink sqljKeyword sqljSpecial - HiLink sqljNumber Number - HiLink sqljOperator sqljStatement - HiLink sqljSpecial Special - HiLink sqljStatement Statement - HiLink sqljString String - HiLink sqljType Type - HiLink sqljPre PreProc - - delcommand HiLink -endif + +" The default methods for highlighting. Can be overridden later. +hi def link sqljComment Comment +hi def link sqljKeyword sqljSpecial +hi def link sqljNumber Number +hi def link sqljOperator sqljStatement +hi def link sqljSpecial Special +hi def link sqljStatement Statement +hi def link sqljString String +hi def link sqljType Type +hi def link sqljPre PreProc + let b:current_syntax = "sqlj" diff --git a/runtime/syntax/sqloracle.vim b/runtime/syntax/sqloracle.vim index f9e24af98c..bf2862f497 100644 --- a/runtime/syntax/sqloracle.vim +++ b/runtime/syntax/sqloracle.vim @@ -128,19 +128,17 @@ syn keyword sqlFunction xmlparse xmlpatch xmlpi xmlquery xmlroot xmlsequence xml syn keyword sqlTodo TODO FIXME XXX DEBUG NOTE contained " Define the default highlighting. -command -nargs=+ HiLink hi def link <args> -HiLink Quote Special -HiLink sqlComment Comment -HiLink sqlFunction Function -HiLink sqlKeyword sqlSpecial -HiLink sqlNumber Number -HiLink sqlOperator sqlStatement -HiLink sqlSpecial Special -HiLink sqlStatement Statement -HiLink sqlString String -HiLink sqlType Type -HiLink sqlTodo Todo - -delcommand HiLink +hi def link Quote Special +hi def link sqlComment Comment +hi def link sqlFunction Function +hi def link sqlKeyword sqlSpecial +hi def link sqlNumber Number +hi def link sqlOperator sqlStatement +hi def link sqlSpecial Special +hi def link sqlStatement Statement +hi def link sqlString String +hi def link sqlType Type +hi def link sqlTodo Todo + let b:current_syntax = "sql" " vim: ts=8 diff --git a/runtime/syntax/sqr.vim b/runtime/syntax/sqr.vim index 8c9e7b49e4..40b48358c6 100644 --- a/runtime/syntax/sqr.vim +++ b/runtime/syntax/sqr.vim @@ -16,19 +16,12 @@ " http://lanzarotta.tripod.com/vim.html " jefflanzarotta at yahoo dot com -" For version 5.x, clear all syntax items. -" For version 6.x, quit when a syntax file was already loaded. -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif -if version >= 600 - setlocal iskeyword=@,48-57,_,-,#,$,{,} -else - set iskeyword=@,48-57,_,-,#,$,{,} -endif +setlocal iskeyword=@,48-57,_,-,#,$,{,} syn case ignore @@ -220,75 +213,49 @@ syn match sqrNumber /-\=\<\d*\.\=[0-9_]\>/ syn keyword sqrTodo TODO FIXME XXX DEBUG NOTE ### syn match sqrTodo /???/ -if version >= 600 - " See also the sqrString section above for handling of ! characters - " inside of strings. (Those patterns override the ones below.) - syn match sqrComment /!\@<!!\([^!=].*\|$\)/ contains=sqrTodo - " the ! can't be preceded by another !, - " and must be followed by at least one - " character other than ! or =, or immediately - " by the end-of-line - syn match sqrComment /^!=.*/ contains=sqrTodo - syn match sqrComment /^!!.*/ contains=sqrTodo - syn match sqrError /^\s\+\zs!=.*/ - " it's an error to have "!=" preceded by - " just whitespace on the line ("!=" - " preceded by non-whitespace is treated - " as neither a comment nor an error, since - " it is often correct, i.e. - " if #count != 7 - syn match sqrError /.\+\zs!!.*/ - " a "!!" anywhere but at the beginning of - " the line is always an error -else "For versions before 6.0, same idea as above but we are limited - "to simple patterns only. Also, the sqrString patterns above - "don't seem to take precedence in v5 as they do in v6, so - "we split the last rule to ignore comments found inside of - "string literals. - syn match sqrComment /!\([^!=].*\|$\)/ contains=sqrTodo - syn match sqrComment /^!=.*/ contains=sqrTodo - syn match sqrComment /^!!.*/ contains=sqrTodo - syn match sqrError /^\s\+!=.*/ - syn match sqrError /^[^'!]\+!!/ - " flag !! on lines that don't have ! or ' - syn match sqrError /^\([^!']*'[^']*'[^!']*\)\+!!/ - " flag !! found after matched ' ' chars - " (that aren't also commented) -endif +" See also the sqrString section above for handling of ! characters +" inside of strings. (Those patterns override the ones below.) +syn match sqrComment /!\@<!!\([^!=].*\|$\)/ contains=sqrTodo +" the ! can't be preceded by another !, +" and must be followed by at least one +" character other than ! or =, or immediately +" by the end-of-line +syn match sqrComment /^!=.*/ contains=sqrTodo +syn match sqrComment /^!!.*/ contains=sqrTodo +syn match sqrError /^\s\+\zs!=.*/ +" it's an error to have "!=" preceded by +" just whitespace on the line ("!=" +" preceded by non-whitespace is treated +" as neither a comment nor an error, since +" it is often correct, i.e. +" if #count != 7 +syn match sqrError /.\+\zs!!.*/ +" a "!!" anywhere but at the beginning of +" the line is always an error " Define the default highlighting. -" For version 5.7 and earlier, only when not done already. -" For version 5.8 and later, only when an item doesn't have highlighting yet. -if version >= 508 || !exists("did_sqr_syn_inits") - if version < 508 - let did_sqr_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink sqrSection Statement - HiLink sqrParagraph Statement - HiLink sqrReserved Statement - HiLink sqrParameter Statement - HiLink sqrPreProc PreProc - HiLink sqrSubstVar PreProc - HiLink sqrCommand Statement - HiLink sqrParam Type - HiLink sqrFunction Special - - HiLink sqrString String - HiLink sqrStrOpen Todo - HiLink sqrNumber Number - HiLink sqrVariable Identifier - - HiLink sqrComment Comment - HiLink sqrTodo Todo - HiLink sqrError Error - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet. + +hi def link sqrSection Statement +hi def link sqrParagraph Statement +hi def link sqrReserved Statement +hi def link sqrParameter Statement +hi def link sqrPreProc PreProc +hi def link sqrSubstVar PreProc +hi def link sqrCommand Statement +hi def link sqrParam Type +hi def link sqrFunction Special + +hi def link sqrString String +hi def link sqrStrOpen Todo +hi def link sqrNumber Number +hi def link sqrVariable Identifier + +hi def link sqrComment Comment +hi def link sqrTodo Todo +hi def link sqrError Error + let b:current_syntax = "sqr" diff --git a/runtime/syntax/squid.vim b/runtime/syntax/squid.vim index a8462bbdce..a8abd180a0 100644 --- a/runtime/syntax/squid.vim +++ b/runtime/syntax/squid.vim @@ -7,11 +7,8 @@ " Michael Dotzler <Michael.Dotzler@leoni.com> -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -123,30 +120,20 @@ syn match squidRegexOpt contained "\(^\s*acl\s\+\S\+\s\+\S\+\(_regex\|_mime_type syn sync minlines=3 " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_squid_syntax_inits") - if version < 508 - let did_squid_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink squidTodo Todo - HiLink squidComment Comment - HiLink squidTag Special - HiLink squidConf Keyword - HiLink squidOpt Constant - HiLink squidAction String - HiLink squidNumber Number - HiLink squidIP Number - HiLink squidAcl Keyword - HiLink squidStr String - HiLink squidRegexOpt Special +hi def link squidTodo Todo +hi def link squidComment Comment +hi def link squidTag Special +hi def link squidConf Keyword +hi def link squidOpt Constant +hi def link squidAction String +hi def link squidNumber Number +hi def link squidIP Number +hi def link squidAcl Keyword +hi def link squidStr String +hi def link squidRegexOpt Special - delcommand HiLink -endif let b:current_syntax = "squid" diff --git a/runtime/syntax/srec.vim b/runtime/syntax/srec.vim index 19b6d97426..6ac22d9062 100644 --- a/runtime/syntax/srec.vim +++ b/runtime/syntax/srec.vim @@ -24,11 +24,8 @@ " States in parentheses in the upper format description indicate that they " should not appear in a valid file. -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -63,33 +60,23 @@ syn match srecDataUnexpected "[0-9a-fA-F]\{2}" contained nextgroup=srecDataUnexp syn match srecChecksum "[0-9a-fA-F]\{2}$" contained " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_srec_syntax_inits") - if version < 508 - let did_srec_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - " The default methods for highlighting. Can be overridden later - HiLink srecRecStart srecRecType - HiLink srecRecTypeUnknown srecRecType - HiLink srecRecType WarningMsg - HiLink srecByteCount Constant - hi def srecAddressFieldUnknown term=italic cterm=italic gui=italic - HiLink srecNoAddress DiffAdd - HiLink srecDataAddress Comment - HiLink srecRecCount srecNoAddress - HiLink srecStartAddress srecDataAddress - hi def srecDataOdd term=bold cterm=bold gui=bold - hi def srecDataEven term=NONE cterm=NONE gui=NONE - HiLink srecDataUnexpected Error - HiLink srecChecksum DiffChange +" The default methods for highlighting. Can be overridden later +hi def link srecRecStart srecRecType +hi def link srecRecTypeUnknown srecRecType +hi def link srecRecType WarningMsg +hi def link srecByteCount Constant +hi def srecAddressFieldUnknown term=italic cterm=italic gui=italic +hi def link srecNoAddress DiffAdd +hi def link srecDataAddress Comment +hi def link srecRecCount srecNoAddress +hi def link srecStartAddress srecDataAddress +hi def srecDataOdd term=bold cterm=bold gui=bold +hi def srecDataEven term=NONE cterm=NONE gui=NONE +hi def link srecDataUnexpected Error +hi def link srecChecksum DiffChange - delcommand HiLink -endif let b:current_syntax = "srec" diff --git a/runtime/syntax/sshconfig.vim b/runtime/syntax/sshconfig.vim index 302d073f1e..755d08e768 100644 --- a/runtime/syntax/sshconfig.vim +++ b/runtime/syntax/sshconfig.vim @@ -5,24 +5,17 @@ " Contributor: Leonard Ehrenfried <leonard.ehrenfried@web.de> " Contributor: Karsten Hopp <karsten@redhat.com> " Contributor: Dean, Adam Kenneth <adam.ken.dean@hpe.com> -" Last Change: 2016 Aug 11 -" SSH Version: 7.3p1 +" Last Change: 2016 Dec 28 +" SSH Version: 7.4p1 " " Setup -if version >= 600 - if exists("b:current_syntax") - finish - endif -else - syntax clear +" quit when a syntax file was already loaded +if exists("b:current_syntax") + finish endif -if version >= 600 - setlocal iskeyword=_,-,a-z,A-Z,48-57 -else - set iskeyword=_,-,a-z,A-Z,48-57 -endif +setlocal iskeyword=_,-,a-z,A-Z,48-57 " case on @@ -188,6 +181,7 @@ syn keyword sshconfigKeyword IPQoS syn keyword sshconfigKeyword IdentitiesOnly syn keyword sshconfigKeyword IdentityFile syn keyword sshconfigKeyword IgnoreUnknown +syn keyword sshconfigKeyword Include syn keyword sshconfigKeyword IPQoS syn keyword sshconfigKeyword KbdInteractiveAuthentication syn keyword sshconfigKeyword KbdInteractiveDevices @@ -233,40 +227,31 @@ syn keyword sshconfigKeyword VisualHostKey syn keyword sshconfigKeyword XAuthLocation " Define the default highlighting -if version >= 508 || !exists("did_sshconfig_syntax_inits") - if version < 508 - let did_sshconfig_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - HiLink sshconfigComment Comment - HiLink sshconfigTodo Todo - HiLink sshconfigHostPort sshconfigConstant - HiLink sshconfigNumber sshconfigConstant - HiLink sshconfigConstant Constant - HiLink sshconfigYesNo sshconfigEnum - HiLink sshconfigCipher sshconfigEnum - HiLink sshconfigCiphers sshconfigEnum - HiLink sshconfigMAC sshconfigEnum - HiLink sshconfigHostKeyAlgo sshconfigEnum - HiLink sshconfigLogLevel sshconfigEnum - HiLink sshconfigSysLogFacility sshconfigEnum - HiLink sshconfigAddressFamily sshconfigEnum - HiLink sshconfigIPQoS sshconfigEnum - HiLink sshconfigKbdInteractive sshconfigEnum - HiLink sshconfigKexAlgo sshconfigEnum - HiLink sshconfigTunnel sshconfigEnum - HiLink sshconfigPreferredAuth sshconfigEnum - HiLink sshconfigVar sshconfigEnum - HiLink sshconfigEnum Identifier - HiLink sshconfigSpecial Special - HiLink sshconfigKeyword Keyword - HiLink sshconfigHostSect Type - HiLink sshconfigMatch Type - delcommand HiLink -endif +hi def link sshconfigComment Comment +hi def link sshconfigTodo Todo +hi def link sshconfigHostPort sshconfigConstant +hi def link sshconfigNumber sshconfigConstant +hi def link sshconfigConstant Constant +hi def link sshconfigYesNo sshconfigEnum +hi def link sshconfigCipher sshconfigEnum +hi def link sshconfigCiphers sshconfigEnum +hi def link sshconfigMAC sshconfigEnum +hi def link sshconfigHostKeyAlgo sshconfigEnum +hi def link sshconfigLogLevel sshconfigEnum +hi def link sshconfigSysLogFacility sshconfigEnum +hi def link sshconfigAddressFamily sshconfigEnum +hi def link sshconfigIPQoS sshconfigEnum +hi def link sshconfigKbdInteractive sshconfigEnum +hi def link sshconfigKexAlgo sshconfigEnum +hi def link sshconfigTunnel sshconfigEnum +hi def link sshconfigPreferredAuth sshconfigEnum +hi def link sshconfigVar sshconfigEnum +hi def link sshconfigEnum Identifier +hi def link sshconfigSpecial Special +hi def link sshconfigKeyword Keyword +hi def link sshconfigHostSect Type +hi def link sshconfigMatch Type let b:current_syntax = "sshconfig" diff --git a/runtime/syntax/sshdconfig.vim b/runtime/syntax/sshdconfig.vim index 6b7b98d893..c3abfff632 100644 --- a/runtime/syntax/sshdconfig.vim +++ b/runtime/syntax/sshdconfig.vim @@ -6,24 +6,17 @@ " Contributor: Leonard Ehrenfried <leonard.ehrenfried@web.de> " Contributor: Karsten Hopp <karsten@redhat.com> " Originally: 2009-07-09 -" Last Change: 2016 Mar 1 -" SSH Version: 7.2 +" Last Change: 2016 Dec 28 +" SSH Version: 7.4p1 " " Setup -if version >= 600 - if exists("b:current_syntax") - finish - endif -else - syntax clear +" quit when a syntax file was already loaded +if exists("b:current_syntax") + finish endif -if version >= 600 - setlocal iskeyword=_,-,a-z,A-Z,48-57 -else - set iskeyword=_,-,a-z,A-Z,48-57 -endif +setlocal iskeyword=_,-,a-z,A-Z,48-57 " case on @@ -168,6 +161,7 @@ syn keyword sshdconfigKeyword Compression syn keyword sshdconfigKeyword DebianBanner syn keyword sshdconfigKeyword DenyGroups syn keyword sshdconfigKeyword DenyUsers +syn keyword sshdconfigKeyword DisableForwarding syn keyword sshdconfigKeyword ForceCommand syn keyword sshdconfigKeyword GSSAPIAuthentication syn keyword sshdconfigKeyword GSSAPICleanupCredentials @@ -239,43 +233,34 @@ syn keyword sshdconfigKeyword XAuthLocation " Define the default highlighting -if version >= 508 || !exists("did_sshdconfig_syntax_inits") - if version < 508 - let did_sshdconfig_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink sshdconfigComment Comment - HiLink sshdconfigTodo Todo - HiLink sshdconfigHostPort sshdconfigConstant - HiLink sshdconfigTime sshdconfigConstant - HiLink sshdconfigNumber sshdconfigConstant - HiLink sshdconfigConstant Constant - HiLink sshdconfigYesNo sshdconfigEnum - HiLink sshdconfigAddressFamily sshdconfigEnum - HiLink sshdconfigPrivilegeSeparation sshdconfigEnum - HiLink sshdconfigTcpForwarding sshdconfigEnum - HiLink sshdconfigRootLogin sshdconfigEnum - HiLink sshdconfigCiphers sshdconfigEnum - HiLink sshdconfigMAC sshdconfigEnum - HiLink sshdconfigHostKeyAlgo sshdconfigEnum - HiLink sshdconfigRootLogin sshdconfigEnum - HiLink sshdconfigLogLevel sshdconfigEnum - HiLink sshdconfigSysLogFacility sshdconfigEnum - HiLink sshdconfigVar sshdconfigEnum - HiLink sshdconfigCompression sshdconfigEnum - HiLink sshdconfigIPQoS sshdconfigEnum - HiLink sshdconfigKexAlgo sshdconfigEnum - HiLink sshdconfigTunnel sshdconfigEnum - HiLink sshdconfigSubsystem sshdconfigEnum - HiLink sshdconfigEnum Function - HiLink sshdconfigSpecial Special - HiLink sshdconfigKeyword Keyword - HiLink sshdconfigMatch Type - delcommand HiLink -endif + +hi def link sshdconfigComment Comment +hi def link sshdconfigTodo Todo +hi def link sshdconfigHostPort sshdconfigConstant +hi def link sshdconfigTime sshdconfigConstant +hi def link sshdconfigNumber sshdconfigConstant +hi def link sshdconfigConstant Constant +hi def link sshdconfigYesNo sshdconfigEnum +hi def link sshdconfigAddressFamily sshdconfigEnum +hi def link sshdconfigPrivilegeSeparation sshdconfigEnum +hi def link sshdconfigTcpForwarding sshdconfigEnum +hi def link sshdconfigRootLogin sshdconfigEnum +hi def link sshdconfigCiphers sshdconfigEnum +hi def link sshdconfigMAC sshdconfigEnum +hi def link sshdconfigHostKeyAlgo sshdconfigEnum +hi def link sshdconfigRootLogin sshdconfigEnum +hi def link sshdconfigLogLevel sshdconfigEnum +hi def link sshdconfigSysLogFacility sshdconfigEnum +hi def link sshdconfigVar sshdconfigEnum +hi def link sshdconfigCompression sshdconfigEnum +hi def link sshdconfigIPQoS sshdconfigEnum +hi def link sshdconfigKexAlgo sshdconfigEnum +hi def link sshdconfigTunnel sshdconfigEnum +hi def link sshdconfigSubsystem sshdconfigEnum +hi def link sshdconfigEnum Function +hi def link sshdconfigSpecial Special +hi def link sshdconfigKeyword Keyword +hi def link sshdconfigMatch Type let b:current_syntax = "sshdconfig" diff --git a/runtime/syntax/st.vim b/runtime/syntax/st.vim index 47aa07de5d..8160c7704a 100644 --- a/runtime/syntax/st.vim +++ b/runtime/syntax/st.vim @@ -3,11 +3,8 @@ " Maintainer: Arndt Hesse <hesse@self.de> " Last Change: 2012 Feb 12 by Thilo Six -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -77,30 +74,20 @@ hi link stBlockError stError syn sync minlines=50 " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_st_syntax_inits") - if version < 508 - let did_st_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink stKeyword Statement - HiLink stMethod Statement - HiLink stComment Comment - HiLink stCharacter Constant - HiLink stString Constant - HiLink stSymbol Special - HiLink stNumber Type - HiLink stFloat Type - HiLink stError Error - HiLink stLocalVariables Identifier - HiLink stBlockVariable Identifier - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link stKeyword Statement +hi def link stMethod Statement +hi def link stComment Comment +hi def link stCharacter Constant +hi def link stString Constant +hi def link stSymbol Special +hi def link stNumber Type +hi def link stFloat Type +hi def link stError Error +hi def link stLocalVariables Identifier +hi def link stBlockVariable Identifier + let b:current_syntax = "st" diff --git a/runtime/syntax/stata.vim b/runtime/syntax/stata.vim index e1f19c84fc..29f5052ebe 100644 --- a/runtime/syntax/stata.vim +++ b/runtime/syntax/stata.vim @@ -12,9 +12,8 @@ " 26apr2006 fixed brace confusion in stataErrInParen and stataErrInBracket " fixed paren/bracket confusion in stataFuncGroup -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif diff --git a/runtime/syntax/stp.vim b/runtime/syntax/stp.vim index f4f0f3b615..2992d8be47 100644 --- a/runtime/syntax/stp.vim +++ b/runtime/syntax/stp.vim @@ -4,11 +4,8 @@ " URL: http://lanzarotta.tripod.com/vim/syntax/stp.vim.zip " Last Change: March 05, 2002 -" For version 5.x, clear all syntax items. -" For version 6.x, quit when a syntax file was already loaded. -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -131,36 +128,26 @@ syn match stpParenError ")" syn sync minlines=10 maxlines=100 " Define the default highlighting. -" For version 5.x and earlier, only when not done already. -" For version 5.8 and later, only when and item doesn't have highlighting yet. -if version >= 508 || !exists("did_stp_syn_inits") - if version < 508 - let did_stp_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink stpConditional Conditional - HiLink stpComment Comment - HiLink stpKeyword Keyword - HiLink stpNumber Number - HiLink stpOperator Operator - HiLink stpSpecial Special - HiLink stpStatement Statement - HiLink stpString String - HiLink stpStringError Error - HiLink stpType Type - HiLink stpTodo Todo - HiLink stpFunction Function - HiLink stpGlobals Macro - HiLink stpParen Normal - HiLink stpParenError Error - HiLink stpSQLKeyword Function - HiLink stpRepeat Repeat - - delcommand HiLink -endif +" Only when and item doesn't have highlighting yet. + +hi def link stpConditional Conditional +hi def link stpComment Comment +hi def link stpKeyword Keyword +hi def link stpNumber Number +hi def link stpOperator Operator +hi def link stpSpecial Special +hi def link stpStatement Statement +hi def link stpString String +hi def link stpStringError Error +hi def link stpType Type +hi def link stpTodo Todo +hi def link stpFunction Function +hi def link stpGlobals Macro +hi def link stpParen Normal +hi def link stpParenError Error +hi def link stpSQLKeyword Function +hi def link stpRepeat Repeat + let b:current_syntax = "stp" diff --git a/runtime/syntax/strace.vim b/runtime/syntax/strace.vim index 0f686fd808..206c58919e 100644 --- a/runtime/syntax/strace.vim +++ b/runtime/syntax/strace.vim @@ -5,12 +5,9 @@ " Last Change: 2015-01-16 " Setup -if version >= 600 - if exists("b:current_syntax") - finish - endif -else - syntax clear +" quit when a syntax file was already loaded +if exists("b:current_syntax") + finish endif syn case match @@ -35,31 +32,22 @@ syn match straceOperator "[-+=*/!%&|:,]" syn region straceComment start="/\*" end="\*/" oneline " Define the default highlighting -if version >= 508 || !exists("did_strace_syntax_inits") - if version < 508 - let did_strace_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - HiLink straceComment Comment - HiLink straceVerbosed Comment - HiLink stracePID PreProc - HiLink straceNumber Number - HiLink straceNumberRHS Type - HiLink straceOtherRHS Type - HiLink straceString String - HiLink straceConstant Function - HiLink straceEquals Type - HiLink straceSysCallEmbed straceSysCall - HiLink straceSysCall Statement - HiLink straceParenthesis Statement - HiLink straceOperator Normal - HiLink straceSpecialChar Special - HiLink straceOtherPID PreProc +hi def link straceComment Comment +hi def link straceVerbosed Comment +hi def link stracePID PreProc +hi def link straceNumber Number +hi def link straceNumberRHS Type +hi def link straceOtherRHS Type +hi def link straceString String +hi def link straceConstant Function +hi def link straceEquals Type +hi def link straceSysCallEmbed straceSysCall +hi def link straceSysCall Statement +hi def link straceParenthesis Statement +hi def link straceOperator Normal +hi def link straceSpecialChar Special +hi def link straceOtherPID PreProc - delcommand HiLink -endif let b:current_syntax = "strace" diff --git a/runtime/syntax/svn.vim b/runtime/syntax/svn.vim index 6536d6d11c..6239790f12 100644 --- a/runtime/syntax/svn.vim +++ b/runtime/syntax/svn.vim @@ -15,11 +15,8 @@ " Myk Taylor " Stefano Zacchiroli -" For version 5.x: Clear all syntax items. -" For version 6.x: Quit when a syntax file was already loaded. -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded. +if exists("b:current_syntax") finish endif @@ -42,28 +39,18 @@ syn sync clear syn sync match svnSync grouphere svnRegion "^--.*--$"me=s-1 " Define the default highlighting. -" For version 5.7 and earlier: only when not done already. -" For version 5.8 and later: only when an item doesn't have highlighting yet. -if version >= 508 || !exists("did_svn_syn_inits") - if version <= 508 - let did_svn_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet. - HiLink svnSummary Keyword - HiLink svnBlank Error +hi def link svnSummary Keyword +hi def link svnBlank Error - HiLink svnRegion Comment - HiLink svnDelimiter NonText - HiLink svnRemoved Constant - HiLink svnAdded Identifier - HiLink svnModified Special - HiLink svnProperty Special - HiLink svnRenamed Special +hi def link svnRegion Comment +hi def link svnDelimiter NonText +hi def link svnRemoved Constant +hi def link svnAdded Identifier +hi def link svnModified Special +hi def link svnProperty Special +hi def link svnRenamed Special - delcommand HiLink -endif let b:current_syntax = "svn" diff --git a/runtime/syntax/synload.vim b/runtime/syntax/synload.vim index 6183f33a59..ab918c645b 100644 --- a/runtime/syntax/synload.vim +++ b/runtime/syntax/synload.vim @@ -1,6 +1,6 @@ " Vim syntax support file " Maintainer: Bram Moolenaar <Bram@vim.org> -" Last Change: 2012 Sep 25 +" Last Change: 2016 Nov 04 " This file sets up for syntax highlighting. " It is loaded from "syntax.vim" and "manual.vim". @@ -69,8 +69,11 @@ au Syntax c,cpp,cs,idl,java,php,datascript " Source the user-specified syntax highlighting file -if exists("mysyntaxfile") && filereadable(expand(mysyntaxfile)) - execute "source " . mysyntaxfile +if exists("mysyntaxfile") + let s:fname = expand(mysyntaxfile) + if filereadable(s:fname) + execute "source " . fnameescape(s:fname) + endif endif " Restore 'cpoptions' diff --git a/runtime/syntax/systemverilog.vim b/runtime/syntax/systemverilog.vim index 5bf2935078..f99ea8d889 100644 --- a/runtime/syntax/systemverilog.vim +++ b/runtime/syntax/systemverilog.vim @@ -3,21 +3,14 @@ " Maintainer: kocha <kocha.lsifrontend@gmail.com> " Last Change: 12-Aug-2013. -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif " Read in Verilog syntax files -if version < 600 - so <sfile>:p:h/verilog.vim -else - runtime! syntax/verilog.vim - unlet b:current_syntax -endif +runtime! syntax/verilog.vim +unlet b:current_syntax " IEEE1800-2005 syn keyword systemverilogStatement always_comb always_ff always_latch @@ -76,25 +69,16 @@ syn keyword systemverilogStatement implements syn keyword systemverilogStatement interconnect soft nettype " Define the default highlighting. -if version >= 508 || !exists("did_systemverilog_syn_inits") - if version < 508 - let did_systemverilog_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - " The default highlighting. - HiLink systemverilogStatement Statement - HiLink systemverilogTypeDef TypeDef - HiLink systemverilogConditional Conditional - HiLink systemverilogRepeat Repeat - HiLink systemverilogLabel Label - HiLink systemverilogGlobal Define - HiLink systemverilogNumber Number +" The default highlighting. +hi def link systemverilogStatement Statement +hi def link systemverilogTypeDef TypeDef +hi def link systemverilogConditional Conditional +hi def link systemverilogRepeat Repeat +hi def link systemverilogLabel Label +hi def link systemverilogGlobal Define +hi def link systemverilogNumber Number - delcommand HiLink -endif let b:current_syntax = "systemverilog" diff --git a/runtime/syntax/tads.vim b/runtime/syntax/tads.vim index 260ff360f7..23a65b99ec 100644 --- a/runtime/syntax/tads.vim +++ b/runtime/syntax/tads.vim @@ -13,11 +13,8 @@ " Actually, should cvtstr etc. be functions?! (change tadsFunction) " Make global etc. into Identifiers, since we don't have regular variables? -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -122,57 +119,47 @@ endif execute "syn sync maxlines=" . tads_sync_dist " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_tads_syn_inits") - if version < 508 - let did_tads_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - " The default methods for highlighting. Can be overridden later - HiLink tadsFunctionDef Function - HiLink tadsFunction Structure - HiLink tadsClass Structure - HiLink tadsClassDef Identifier - HiLink tadsObjectDef Identifier +" Only when an item doesn't have highlighting yet + +" The default methods for highlighting. Can be overridden later +hi def link tadsFunctionDef Function +hi def link tadsFunction Structure +hi def link tadsClass Structure +hi def link tadsClassDef Identifier +hi def link tadsObjectDef Identifier " no highlight for tadsEmbedded, so it prints as normal text w/in the string - HiLink tadsOperator Operator - HiLink tadsStructure Structure - HiLink tadsTodo Todo - HiLink tadsLabel Label - HiLink tadsConditional Conditional - HiLink tadsRepeat Repeat - HiLink tadsException Exception - HiLink tadsStatement Statement - HiLink tadsStorageClass StorageClass - HiLink tadsKeyWord Keyword - HiLink tadsSpecial SpecialChar - HiLink tadsNumber Number - HiLink tadsBoolean Boolean - HiLink tadsDoubleString tadsString - HiLink tadsSingleString tadsString - - HiLink tadsOctalError tadsError - HiLink tadsCommentError tadsError - HiLink tadsBraceError tadsError - HiLink tadsInBrace tadsError - HiLink tadsError Error - - HiLink tadsInclude Include - HiLink tadsPreProc PreProc - HiLink tadsDefine Macro - HiLink tadsIncluded tadsString - HiLink tadsPreCondit PreCondit - - HiLink tadsString String - HiLink tadsComment Comment - - delcommand HiLink -endif +hi def link tadsOperator Operator +hi def link tadsStructure Structure +hi def link tadsTodo Todo +hi def link tadsLabel Label +hi def link tadsConditional Conditional +hi def link tadsRepeat Repeat +hi def link tadsException Exception +hi def link tadsStatement Statement +hi def link tadsStorageClass StorageClass +hi def link tadsKeyWord Keyword +hi def link tadsSpecial SpecialChar +hi def link tadsNumber Number +hi def link tadsBoolean Boolean +hi def link tadsDoubleString tadsString +hi def link tadsSingleString tadsString + +hi def link tadsOctalError tadsError +hi def link tadsCommentError tadsError +hi def link tadsBraceError tadsError +hi def link tadsInBrace tadsError +hi def link tadsError Error + +hi def link tadsInclude Include +hi def link tadsPreProc PreProc +hi def link tadsDefine Macro +hi def link tadsIncluded tadsString +hi def link tadsPreCondit PreCondit + +hi def link tadsString String +hi def link tadsComment Comment + let b:current_syntax = "tads" diff --git a/runtime/syntax/tags.vim b/runtime/syntax/tags.vim index c86f17a618..f34696d4b0 100644 --- a/runtime/syntax/tags.vim +++ b/runtime/syntax/tags.vim @@ -1,47 +1,31 @@ " Language: tags " Maintainer: Charles E. Campbell <NdrOchip@PcampbellAfamily.Mbiz> -" Last Change: Oct 23, 2014 -" Version: 4 +" Last Change: Oct 26, 2016 +" Version: 7 " URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_TAGS -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif -syn match tagName "^[^\t]\+" skipwhite nextgroup=tagPath -syn match tagPath "[^\t]\+" contained skipwhite nextgroup=tagAddr contains=tagBaseFile +syn match tagName "^[^\t]\+" skipwhite nextgroup=tagPath +syn match tagPath "[^\t]\+" contained skipwhite nextgroup=tagAddr contains=tagBaseFile syn match tagBaseFile "[a-zA-Z_]\+[\.a-zA-Z_0-9]*\t"me=e-1 contained -syn match tagAddr "\d*" contained skipwhite nextgroup=tagComment -syn region tagAddr matchgroup=tagDelim start="/" skip="\(\\\\\)*\\/" matchgroup=tagDelim end="$\|/" oneline contained skipwhite nextgroup=tagComment -syn match tagComment ";.*$" contained contains=tagField +syn match tagAddr "\d*" contained skipwhite nextgroup=tagComment +syn region tagAddr matchgroup=tagDelim start="/" skip="\(\\\\\)*\\/" matchgroup=tagDelim end="$\|/" oneline contained skipwhite nextgroup=tagComment +syn match tagComment ";.*$" contained contains=tagField syn match tagComment "^!_TAG_.*$" -syn match tagField contained "[a-z]*:" +syn match tagField contained "[a-z]*:" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_drchip_tags_inits") - if version < 508 - let did_drchip_tags_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink tagBaseFile PreProc - HiLink tagComment Comment - HiLink tagDelim Delimiter - HiLink tagField Number - HiLink tagName Identifier - HiLink tagPath PreProc - - delcommand HiLink +if !exists("skip_drchip_tags_inits") + hi def link tagBaseFile PreProc + hi def link tagComment Comment + hi def link tagDelim Delimiter + hi def link tagField Number + hi def link tagName Identifier + hi def link tagPath PreProc endif let b:current_syntax = "tags" - -" vim: ts=12 diff --git a/runtime/syntax/tak.vim b/runtime/syntax/tak.vim index 20186db143..7a8fceb860 100644 --- a/runtime/syntax/tak.vim +++ b/runtime/syntax/tak.vim @@ -8,11 +8,8 @@ -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -32,11 +29,7 @@ syn case ignore let fortran_free_source=1 " Load FORTRAN syntax file -if version < 600 - source <sfile>:p:h/fortran.vim -else - runtime! syntax/fortran.vim -endif +runtime! syntax/fortran.vim unlet b:current_syntax @@ -95,40 +88,30 @@ endif " Define the default highlighting -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_tak_syntax_inits") - if version < 508 - let did_tak_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink takMacro Macro - HiLink takOptions Special - HiLink takRoutine Type - HiLink takControl Special - HiLink takSolids Special - HiLink takSolidsArg Statement - HiLink takIdentifier Identifier - - HiLink takFortran PreProc - HiLink takMotran PreProc - - HiLink takComment Comment - HiLink takHeader Typedef - HiLink takIncludeFile Type - HiLink takInteger Number - HiLink takFloat Float - HiLink takScientific Float - - HiLink takEndData Macro - - HiLink takTodo Todo - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link takMacro Macro +hi def link takOptions Special +hi def link takRoutine Type +hi def link takControl Special +hi def link takSolids Special +hi def link takSolidsArg Statement +hi def link takIdentifier Identifier + +hi def link takFortran PreProc +hi def link takMotran PreProc + +hi def link takComment Comment +hi def link takHeader Typedef +hi def link takIncludeFile Type +hi def link takInteger Number +hi def link takFloat Float +hi def link takScientific Float + +hi def link takEndData Macro + +hi def link takTodo Todo + let b:current_syntax = "tak" diff --git a/runtime/syntax/takcmp.vim b/runtime/syntax/takcmp.vim index a94609b325..9426e02223 100644 --- a/runtime/syntax/takcmp.vim +++ b/runtime/syntax/takcmp.vim @@ -8,11 +8,8 @@ -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -51,30 +48,20 @@ syn case ignore " Define the default highlighting -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_takcmp_syntax_inits") - if version < 508 - let did_takcmp_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink takcmpTitle Type - HiLink takcmpUnit PreProc +hi def link takcmpTitle Type +hi def link takcmpUnit PreProc - HiLink takcmpLabel Statement +hi def link takcmpLabel Statement - HiLink takcmpHeader takHeader +hi def link takcmpHeader takHeader - HiLink takcmpDate Identifier - HiLink takcmpTime Identifier - HiLink takcmpInteger Number - HiLink takcmpFloat Special +hi def link takcmpDate Identifier +hi def link takcmpTime Identifier +hi def link takcmpInteger Number +hi def link takcmpFloat Special - delcommand HiLink -endif let b:current_syntax = "takcmp" diff --git a/runtime/syntax/takout.vim b/runtime/syntax/takout.vim index 774353942a..5e5d360767 100644 --- a/runtime/syntax/takout.vim +++ b/runtime/syntax/takout.vim @@ -8,11 +8,8 @@ -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -24,11 +21,7 @@ syn case match " Load TAK syntax file -if version < 600 - source <sfile>:p:h/tak.vim -else - runtime! syntax/tak.vim -endif +runtime! syntax/tak.vim unlet b:current_syntax @@ -70,31 +63,21 @@ syn match takoutError "<<< Error >>>" " Define the default highlighting -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_takout_syntax_inits") - if version < 508 - let did_takout_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink takoutPos Statement - HiLink takoutNeg PreProc - HiLink takoutTitle Type - HiLink takoutFile takIncludeFile - HiLink takoutInteger takInteger - - HiLink takoutSectionDelim Delimiter - HiLink takoutSectionTitle Exception - HiLink takoutHeaderDelim SpecialComment - HiLink takoutLabel Identifier - - HiLink takoutError Error - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link takoutPos Statement +hi def link takoutNeg PreProc +hi def link takoutTitle Type +hi def link takoutFile takIncludeFile +hi def link takoutInteger takInteger + +hi def link takoutSectionDelim Delimiter +hi def link takoutSectionTitle Exception +hi def link takoutHeaderDelim SpecialComment +hi def link takoutLabel Identifier + +hi def link takoutError Error + let b:current_syntax = "takout" diff --git a/runtime/syntax/taskdata.vim b/runtime/syntax/taskdata.vim index b37c70cc1f..63a8284adf 100644 --- a/runtime/syntax/taskdata.vim +++ b/runtime/syntax/taskdata.vim @@ -4,11 +4,8 @@ " Updated: Wed Jul 8 19:46:20 EDT 2009 -" For version 5.x: Clear all syntax items. -" For version 6.x: Quit when a syntax file was already loaded. -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded. +if exists("b:current_syntax") finish endif let s:keepcpo= &cpo diff --git a/runtime/syntax/taskedit.vim b/runtime/syntax/taskedit.vim index 170153c0ee..d33ca78650 100644 --- a/runtime/syntax/taskedit.vim +++ b/runtime/syntax/taskedit.vim @@ -4,11 +4,8 @@ " Updated: Wed Jul 8 19:46:32 EDT 2009 -" For version 5.x: Clear all syntax items. -" For version 6.x: Quit when a syntax file was already loaded. -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded. +if exists("b:current_syntax") finish endif let s:keepcpo= &cpo diff --git a/runtime/syntax/tasm.vim b/runtime/syntax/tasm.vim index 2f8559610e..c9fc8186d0 100644 --- a/runtime/syntax/tasm.vim +++ b/runtime/syntax/tasm.vim @@ -3,11 +3,8 @@ " Maintaner: FooLman of United Force <foolman@bigfoot.com> " Last Change: 2012 Feb 03 by Thilo Six -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -95,32 +92,22 @@ syn match tasmOct "\<[0-7]\+O\>" syn match tasmBin "\<[01]\+B\>" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_tasm_syntax_inits") - if version < 508 - let did_tasm_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink tasmString String - HiLink tasmDec Number - HiLink tasmHex Number - HiLink tasmOct Number - HiLink tasmBin Number - HiLink tasmInstruction Keyword - HiLink tasmCoprocInstr Keyword - HiLink tasmMMXInst Keyword - HiLink tasmDirective PreProc - HiLink tasmRegister Identifier - HiLink tasmProctype PreProc - HiLink tasmComment Comment - HiLink tasmLabel Label +hi def link tasmString String +hi def link tasmDec Number +hi def link tasmHex Number +hi def link tasmOct Number +hi def link tasmBin Number +hi def link tasmInstruction Keyword +hi def link tasmCoprocInstr Keyword +hi def link tasmMMXInst Keyword +hi def link tasmDirective PreProc +hi def link tasmRegister Identifier +hi def link tasmProctype PreProc +hi def link tasmComment Comment +hi def link tasmLabel Label - delcommand HiLink -endif let b:curret_syntax = "tasm" diff --git a/runtime/syntax/tcl.vim b/runtime/syntax/tcl.vim index 06629d077f..64efd6fec4 100644 --- a/runtime/syntax/tcl.vim +++ b/runtime/syntax/tcl.vim @@ -10,11 +10,8 @@ " Version: 1.14 " URL: http://bitbucket.org/taylor_venable/metasyntax/src/tip/Config/vim/syntax/tcl.vim -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -238,49 +235,39 @@ syn region tclComment start=/;\s*\#/hs=s+1 skip="\\$" end="$" contains=tclTodo "syn sync ccomment tclComment " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_tcl_syntax_inits") - if version < 508 - let did_tcl_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink tcltkSwitch Special - HiLink tclExpand Special - HiLink tclLabel Label - HiLink tclConditional Conditional - HiLink tclRepeat Repeat - HiLink tclNumber Number - HiLink tclError Error - HiLink tclCommand Statement - HiLink tclProcCommand Type - HiLink tclString String - HiLink tclComment Comment - HiLink tclSpecial Special - HiLink tclTodo Todo - " Below here are the commands and their options. - HiLink tcltkCommandColor Statement - HiLink tcltkWidgetColor Structure - HiLink tclLineContinue WarningMsg +" Only when an item doesn't have highlighting yet + +hi def link tcltkSwitch Special +hi def link tclExpand Special +hi def link tclLabel Label +hi def link tclConditional Conditional +hi def link tclRepeat Repeat +hi def link tclNumber Number +hi def link tclError Error +hi def link tclCommand Statement +hi def link tclProcCommand Type +hi def link tclString String +hi def link tclComment Comment +hi def link tclSpecial Special +hi def link tclTodo Todo +" Below here are the commands and their options. +hi def link tcltkCommandColor Statement +hi def link tcltkWidgetColor Structure +hi def link tclLineContinue WarningMsg if exists('g:tcl_warn_continuation') - HiLink tclNotLineContinue ErrorMsg -endif - HiLink tcltkStringSwitch Special - HiLink tcltkArraySwitch Special - HiLink tcltkLsortSwitch Special - HiLink tcltkPackSwitch Special - HiLink tcltkPackConfSwitch Special - HiLink tcltkMaths Special - HiLink tcltkNamespaceSwitch Special - HiLink tcltkWidgetSwitch Special - HiLink tcltkPackConfColor Identifier - HiLink tclVarRef Identifier - - delcommand HiLink +hi def link tclNotLineContinue ErrorMsg endif +hi def link tcltkStringSwitch Special +hi def link tcltkArraySwitch Special +hi def link tcltkLsortSwitch Special +hi def link tcltkPackSwitch Special +hi def link tcltkPackConfSwitch Special +hi def link tcltkMaths Special +hi def link tcltkNamespaceSwitch Special +hi def link tcltkWidgetSwitch Special +hi def link tcltkPackConfColor Identifier +hi def link tclVarRef Identifier + let b:current_syntax = "tcl" diff --git a/runtime/syntax/teraterm.vim b/runtime/syntax/teraterm.vim index 521331d8ce..1924996738 100644 --- a/runtime/syntax/teraterm.vim +++ b/runtime/syntax/teraterm.vim @@ -1,9 +1,9 @@ " Vim syntax file " Language: Tera Term Language (TTL) -" Based on Tera Term Version 4.86 +" Based on Tera Term Version 4.92 " Maintainer: Ken Takata " URL: https://github.com/k-takata/vim-teraterm -" Last Change: 2015 Jun 24 +" Last Change: 2016 Aug 17 " Filenames: *.ttl " License: VIM License @@ -33,7 +33,7 @@ syn keyword ttlOperator and or xor not syn match ttlVar "\<groupmatchstr\d\>" syn match ttlVar "\<param\d\>" -syn keyword ttlVar inputstr matchstr paramcnt result timeout mtimeout +syn keyword ttlVar inputstr matchstr paramcnt params result timeout mtimeout syn match ttlLine nextgroup=ttlStatement "^" diff --git a/runtime/syntax/tex.vim b/runtime/syntax/tex.vim index 9d91402bc8..ab19da329b 100644 --- a/runtime/syntax/tex.vim +++ b/runtime/syntax/tex.vim @@ -1,8 +1,8 @@ " Vim syntax file " Language: TeX " Maintainer: Charles E. Campbell <NdrchipO@ScampbellPfamily.AbizM> -" Last Change: May 02, 2016 -" Version: 95 +" Last Change: Jan 31, 2017 +" Version: 103 " URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_TEX " " Notes: {{{1 @@ -40,29 +40,14 @@ " using conceal mode :help tex-conceal " Version Clears: {{{1 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif let s:keepcpo= &cpo set cpo&vim scriptencoding utf-8 -" Define the default highlighting. {{{1 -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_tex_syntax_inits") - let did_tex_syntax_inits = 1 - if version < 508 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif -endif - " by default, enable all region-based highlighting let s:tex_fast= "bcmMprsSvV" if exists("g:tex_fast") @@ -83,12 +68,12 @@ else let s:tex_conceal= g:tex_conceal endif if !exists("g:tex_superscripts") - let s:tex_superscripts= "[0-9a-zA-W.,:;+-<>/()=]" + let s:tex_superscripts= '[0-9a-zA-W.,:;+-<>/()=]' else let s:tex_superscripts= g:tex_superscripts endif if !exists("g:tex_subscripts") - let s:tex_subscripts= "[0-9aehijklmnoprstuvx,+-/().]" + let s:tex_subscripts= '[0-9aehijklmnoprstuvx,+-/().]' else let s:tex_subscripts= g:tex_subscripts endif @@ -132,14 +117,20 @@ endif " One may override this iskeyword setting by providing " g:tex_isk if exists("g:tex_isk") - exe "setlocal isk=".g:tex_isk -elseif !has("patch-7.4.1142") - setl isk=48-57,a-z,A-Z,192-255 + if b:tex_stylish && g:tex_isk !~ '@' + let b:tex_isk= '@,'.g:tex_isk + else + let b:tex_isk= g:tex_isk + endif +elseif b:tex_stylish + let b:tex_isk="@,48-57,a-z,A-Z,192-255" else - syn iskeyword 48-57,a-z,A-Z,192-255 + let b:tex_isk="48-57,a-z,A-Z,192-255" endif -if b:tex_stylish - setlocal isk+=@-@ +if v:version > 704 || (v:version == 704 && has("patch-7.4.1142")) + exe "syn iskeyword ".b:tex_isk +else + exe "setl isk=".b:tex_isk endif if exists("g:tex_no_error") && g:tex_no_error let s:tex_no_error= 1 @@ -159,7 +150,7 @@ endif " Clusters: {{{1 " -------- -syn cluster texCmdGroup contains=texCmdBody,texComment,texDefParm,texDelimiter,texDocType,texInput,texLength,texLigature,texMathDelim,texMathOper,texNewCmd,texNewEnv,texRefZone,texSection,texBeginEnd,texBeginEndName,texSpecialChar,texStatement,texString,texTypeSize,texTypeStyle +syn cluster texCmdGroup contains=texCmdBody,texComment,texDefParm,texDelimiter,texDocType,texInput,texLength,texLigature,texMathDelim,texMathOper,texNewCmd,texNewEnv,texRefZone,texSection,texBeginEnd,texBeginEndName,texSpecialChar,texStatement,texString,texTypeSize,texTypeStyle,@texMathZones if !s:tex_no_error syn cluster texCmdGroup add=texMathError endif @@ -169,15 +160,17 @@ syn cluster texBoldGroup contains=texAccent,texBadMath,texComment,texDefCmd,tex syn cluster texItalGroup contains=texAccent,texBadMath,texComment,texDefCmd,texDelimiter,texDocType,texInput,texInputFile,texLength,texLigature,texMatcher,texMathZoneV,texMathZoneW,texMathZoneX,texMathZoneY,texMathZoneZ,texNewCmd,texNewEnv,texOnlyMath,texOption,texParen,texRefZone,texSection,texBeginEnd,texSectionZone,texSpaceCode,texSpecialChar,texStatement,texString,texTypeSize,texTypeStyle,texZone,@texMathZones,texTitle,texAbstract,texItalStyle,texItalBoldStyle,texNoSpell if !s:tex_nospell syn cluster texMatchGroup contains=texAccent,texBadMath,texComment,texDefCmd,texDelimiter,texDocType,texInput,texLength,texLigature,texMatcher,texNewCmd,texNewEnv,texOnlyMath,texParen,texRefZone,texSection,texSpecialChar,texStatement,texString,texTypeSize,texTypeStyle,texZone,texInputFile,texOption,@Spell + syn cluster texMatchNMGroup contains=texAccent,texBadMath,texComment,texDefCmd,texDelimiter,texDocType,texInput,texLength,texLigature,texMatcherNM,texNewCmd,texNewEnv,texOnlyMath,texParen,texRefZone,texSection,texSpecialChar,texStatement,texString,texTypeSize,texTypeStyle,texZone,texInputFile,texOption,@Spell syn cluster texStyleGroup contains=texAccent,texBadMath,texComment,texDefCmd,texDelimiter,texDocType,texInput,texLength,texLigature,texNewCmd,texNewEnv,texOnlyMath,texParen,texRefZone,texSection,texSpecialChar,texStatement,texString,texTypeSize,texTypeStyle,texZone,texInputFile,texOption,texStyleStatement,@Spell,texStyleMatcher else syn cluster texMatchGroup contains=texAccent,texBadMath,texComment,texDefCmd,texDelimiter,texDocType,texInput,texLength,texLigature,texMatcher,texNewCmd,texNewEnv,texOnlyMath,texParen,texRefZone,texSection,texSpecialChar,texStatement,texString,texTypeSize,texTypeStyle,texZone,texInputFile,texOption + syn cluster texMatchNMGroup contains=texAccent,texBadMath,texComment,texDefCmd,texDelimiter,texDocType,texInput,texLength,texLigature,texMatcherNM,texNewCmd,texNewEnv,texOnlyMath,texParen,texRefZone,texSection,texSpecialChar,texStatement,texString,texTypeSize,texTypeStyle,texZone,texInputFile,texOption syn cluster texStyleGroup contains=texAccent,texBadMath,texComment,texDefCmd,texDelimiter,texDocType,texInput,texLength,texLigature,texNewCmd,texNewEnv,texOnlyMath,texParen,texRefZone,texSection,texSpecialChar,texStatement,texString,texTypeSize,texTypeStyle,texZone,texInputFile,texOption,texStyleStatement,texStyleMatcher endif -syn cluster texPreambleMatchGroup contains=texAccent,texBadMath,texComment,texDefCmd,texDelimiter,texDocType,texInput,texLength,texLigature,texMatcher,texNewCmd,texNewEnv,texOnlyMath,texParen,texRefZone,texSection,texSpecialChar,texStatement,texString,texTitle,texTypeSize,texTypeStyle,texZone,texInputFile,texOption,texMathZoneZ +syn cluster texPreambleMatchGroup contains=texAccent,texBadMath,texComment,texDefCmd,texDelimiter,texDocType,texInput,texLength,texLigature,texMatcherNM,texNewCmd,texNewEnv,texOnlyMath,texParen,texRefZone,texSection,texSpecialChar,texStatement,texString,texTitle,texTypeSize,texTypeStyle,texZone,texInputFile,texOption,texMathZoneZ syn cluster texRefGroup contains=texMatcher,texComment,texDelimiter if !exists("g:tex_no_math") - syn cluster texPreambleMatchGroup contains=texAccent,texBadMath,texComment,texDefCmd,texDelimiter,texDocType,texInput,texLength,texLigature,texMatcher,texNewCmd,texNewEnv,texOnlyMath,texParen,texRefZone,texSection,texSpecialChar,texStatement,texString,texTitle,texTypeSize,texTypeStyle,texZone,texInputFile,texOption,texMathZoneZ + syn cluster texPreambleMatchGroup contains=texAccent,texBadMath,texComment,texDefCmd,texDelimiter,texDocType,texInput,texLength,texLigature,texMatcherNM,texNewCmd,texNewEnv,texOnlyMath,texParen,texRefZone,texSection,texSpecialChar,texStatement,texString,texTitle,texTypeSize,texTypeStyle,texZone,texInputFile,texOption,texMathZoneZ syn cluster texMathZones contains=texMathZoneV,texMathZoneW,texMathZoneX,texMathZoneY,texMathZoneZ syn cluster texMatchGroup add=@texMathZones syn cluster texMathDelimGroup contains=texMathDelimBad,texMathDelimKey,texMathDelimSet1,texMathDelimSet2 @@ -206,16 +199,20 @@ endif " Try to flag {} and () mismatches: {{{1 if s:tex_fast =~# 'm' if !s:tex_no_error - syn region texMatcher matchgroup=Delimiter start="{" skip="\\\\\|\\[{}]" end="}" transparent contains=@texMatchGroup,texError - syn region texMatcher matchgroup=Delimiter start="\[" end="]" transparent contains=@texMatchGroup,texError,@NoSpell + syn region texMatcher matchgroup=Delimiter start="{" skip="\\\\\|\\[{}]" end="}" transparent contains=@texMatchGroup,texError + syn region texMatcher matchgroup=Delimiter start="\[" end="]" transparent contains=@texMatchGroup,texError,@NoSpell + syn region texMatcherNM matchgroup=Delimiter start="{" skip="\\\\\|\\[{}]" end="}" transparent contains=@texMatchNMGroup,texError + syn region texMatcherNM matchgroup=Delimiter start="\[" end="]" transparent contains=@texMatchNMGroup,texError,@NoSpell else - syn region texMatcher matchgroup=Delimiter start="{" skip="\\\\\|\\[{}]" end="}" transparent contains=@texMatchGroup - syn region texMatcher matchgroup=Delimiter start="\[" end="]" transparent contains=@texMatchGroup + syn region texMatcher matchgroup=Delimiter start="{" skip="\\\\\|\\[{}]" end="}" transparent contains=@texMatchGroup + syn region texMatcher matchgroup=Delimiter start="\[" end="]" transparent contains=@texMatchGroup + syn region texMatcherNM matchgroup=Delimiter start="{" skip="\\\\\|\\[{}]" end="}" transparent contains=@texMatchNMGroup + syn region texMatcherNM matchgroup=Delimiter start="\[" end="]" transparent contains=@texMatchNMGroup endif if !s:tex_nospell - syn region texParen start="(" end=")" transparent contains=@texMatchGroup,@Spell + syn region texParen start="(" end=")" transparent contains=@texMatchGroup,@Spell else - syn region texParen start="(" end=")" transparent contains=@texMatchGroup + syn region texParen start="(" end=")" transparent contains=@texMatchGroup endif endif if !s:tex_no_error @@ -266,7 +263,7 @@ syn match texLigature "\\\([ijolL]\|ae\|oe\|ss\|AA\|AE\|OE\)$" syn match texBeginEnd "\\begin\>\|\\end\>" nextgroup=texBeginEndName if s:tex_fast =~# 'm' syn region texBeginEndName matchgroup=Delimiter start="{" end="}" contained nextgroup=texBeginEndModifier contains=texComment - syn region texBeginEndModifier matchgroup=Delimiter start="\[" end="]" contained contains=texComment,@NoSpell + syn region texBeginEndModifier matchgroup=Delimiter start="\[" end="]" contained contains=texComment,@texMathZones,@NoSpell endif " \documentclass, \documentstyle, \usepackage: {{{1 @@ -408,7 +405,7 @@ if !exists("g:tex_no_math") " TexNewMathZone: function creates a mathzone with the given suffix and mathzone name. {{{2 " Starred forms are created if starform is true. Starred " forms have syntax group and synchronization groups with a - " "S" appended. Handles: cluster, syntax, sync, and HiLink. + " "S" appended. Handles: cluster, syntax, sync, and highlighting. fun! TexNewMathZone(sfx,mathzone,starform) let grpname = "texMathZone".a:sfx let syncname = "texSyncMathZone".a:sfx @@ -447,9 +444,8 @@ if !exists("g:tex_no_math") call TexNewMathZone("G","gather",1) call TexNewMathZone("H","math",1) call TexNewMathZone("I","multline",1) - call TexNewMathZone("J","subequations",0) - call TexNewMathZone("K","xalignat",1) - call TexNewMathZone("L","xxalignat",0) + call TexNewMathZone("J","xalignat",1) + call TexNewMathZone("K","xxalignat",0) " Inline Math Zones: {{{2 if s:tex_fast =~# 'M' @@ -481,8 +477,9 @@ if !exists("g:tex_no_math") " \left..something.. and \right..something.. support: {{{2 syn match texMathDelimBad contained "\S" if has("conceal") && &enc == 'utf-8' && s:tex_conceal =~# 'm' - syn match texMathDelim contained "\\left\\{\>" skipwhite nextgroup=texMathDelimSet1,texMathDelimSet2,texMathDelimBad contains=texMathSymbol cchar={ - syn match texMathDelim contained "\\right\\}\>" skipwhite nextgroup=texMathDelimSet1,texMathDelimSet2,texMathDelimBad contains=texMathSymbol cchar=} + syn match texMathDelim contained "\\left\[" + syn match texMathDelim contained "\\left\\{" skipwhite nextgroup=texMathDelimSet1,texMathDelimSet2,texMathDelimBad contains=texMathSymbol cchar={ + syn match texMathDelim contained "\\right\\}" skipwhite nextgroup=texMathDelimSet1,texMathDelimSet2,texMathDelimBad contains=texMathSymbol cchar=} let s:texMathDelimList=[ \ ['<' , '<'] , \ ['>' , '>'] , @@ -497,13 +494,11 @@ if !exists("g:tex_no_math") \ ['\\backslash' , '\'] , \ ['\\downarrow' , 'โ'] , \ ['\\Downarrow' , 'โ'] , - \ ['\\langle' , '<'] , \ ['\\lbrace' , '['] , \ ['\\lceil' , 'โ'] , \ ['\\lfloor' , 'โ'] , \ ['\\lgroup' , 'โ'] , \ ['\\lmoustache' , 'โ'] , - \ ['\\rangle' , '>'] , \ ['\\rbrace' , ']'] , \ ['\\rceil' , 'โ'] , \ ['\\rfloor' , 'โ'] , @@ -513,6 +508,15 @@ if !exists("g:tex_no_math") \ ['\\Uparrow' , 'โ'] , \ ['\\updownarrow', 'โ'] , \ ['\\Updownarrow', 'โ']] + if &ambw == "double" || exists("g:tex_usedblwidth") + let s:texMathDelimList= s:texMathDelimList + [ + \ ['\\langle' , 'ใ'] , + \ ['\\rangle' , 'ใ']] + else + let s:texMathDelimList= s:texMathDelimList + [ + \ ['\\langle' , '<'] , + \ ['\\rangle' , '>']] + endif syn match texMathDelim '\\[bB]igg\=[lr]' contained nextgroup=texMathDelimBad for texmath in s:texMathDelimList exe "syn match texMathDelim '\\\\[bB]igg\\=[lr]\\=".texmath[0]."' contained conceal cchar=".texmath[1] @@ -590,29 +594,17 @@ endif if s:tex_fast =~# 'v' if exists("g:tex_verbspell") && g:tex_verbspell syn region texZone start="\\begin{[vV]erbatim}" end="\\end{[vV]erbatim}\|%stopzone\>" contains=@Spell - " listings package: - syn region texZone start="\\begin{lstlisting}" end="\\end{lstlisting}\|%stopzone\>" contains=@Spell - if version < 600 - syn region texZone start="\\verb\*\=`" end="`\|%stopzone\>" contains=@Spell - syn region texZone start="\\verb\*\=#" end="#\|%stopzone\>" contains=@Spell + if b:tex_stylish + syn region texZone start="\\verb\*\=\z([^\ta-zA-Z@]\)" end="\z1\|%stopzone\>" contains=@Spell else - if b:tex_stylish - syn region texZone start="\\verb\*\=\z([^\ta-zA-Z@]\)" end="\z1\|%stopzone\>" contains=@Spell - else - syn region texZone start="\\verb\*\=\z([^\ta-zA-Z]\)" end="\z1\|%stopzone\>" contains=@Spell - endif + syn region texZone start="\\verb\*\=\z([^\ta-zA-Z]\)" end="\z1\|%stopzone\>" contains=@Spell endif else syn region texZone start="\\begin{[vV]erbatim}" end="\\end{[vV]erbatim}\|%stopzone\>" - if version < 600 - syn region texZone start="\\verb\*\=`" end="`\|%stopzone\>" - syn region texZone start="\\verb\*\=#" end="#\|%stopzone\>" + if b:tex_stylish + syn region texZone start="\\verb\*\=\z([^\ta-zA-Z@]\)" end="\z1\|%stopzone\>" else - if b:tex_stylish - syn region texZone start="\\verb\*\=\z([^\ta-zA-Z@]\)" end="\z1\|%stopzone\>" - else - syn region texZone start="\\verb\*\=\z([^\ta-zA-Z]\)" end="\z1\|%stopzone\>" - endif + syn region texZone start="\\verb\*\=\z([^\ta-zA-Z]\)" end="\z1\|%stopzone\>" endif endif endif @@ -693,6 +685,7 @@ if has("conceal") && &enc == 'utf-8' \ ['backslash' , 'โ'], \ ['barwedge' , 'โผ'], \ ['because' , 'โต'], + \ ['beth' , ''], \ ['between' , 'โฌ'], \ ['bigcap' , 'โฉ'], \ ['bigcirc' , 'โ'], @@ -712,6 +705,7 @@ if has("conceal") && &enc == 'utf-8' \ ['boxminus' , 'โ'], \ ['boxplus' , 'โ'], \ ['boxtimes' , 'โ '], + \ ['Box' , 'โ'], \ ['bullet' , 'โข'], \ ['bumpeq' , 'โ'], \ ['Bumpeq' , 'โ'], @@ -761,6 +755,7 @@ if has("conceal") && &enc == 'utf-8' \ ['eqslantgtr' , 'โช'], \ ['eqslantless' , 'โช'], \ ['equiv' , 'โก'], + \ ['eth' , 'รฐ'], \ ['exists' , 'โ'], \ ['fallingdotseq' , 'โ'], \ ['flat' , 'โญ'], @@ -770,6 +765,7 @@ if has("conceal") && &enc == 'utf-8' \ ['geq' , 'โฅ'], \ ['geqq' , 'โง'], \ ['gets' , 'โ'], + \ ['gimel' , 'โท'], \ ['gg' , 'โซ'], \ ['gneqq' , 'โฉ'], \ ['gtrdot' , 'โ'], @@ -780,13 +776,17 @@ if has("conceal") && &enc == 'utf-8' \ ['heartsuit' , 'โก'], \ ['hookleftarrow' , 'โฉ'], \ ['hookrightarrow' , 'โช'], + \ ['iff' , 'โ'], \ ['iiint' , 'โญ'], \ ['iint' , 'โฌ'], \ ['Im' , 'โ'], \ ['imath' , 'ษฉ'], + \ ['implies' , 'โ'], \ ['in' , 'โ'], \ ['infty' , 'โ'], \ ['int' , 'โซ'], + \ ['jmath' , '๐ฅ'], + \ ['land' , 'โง'], \ ['lceil' , 'โ'], \ ['ldots' , 'โฆ'], \ ['le' , 'โค'], @@ -813,6 +813,7 @@ if has("conceal") && &enc == 'utf-8' \ ['ll' , 'โช'], \ ['lmoustache' , 'โญ'], \ ['lneqq' , 'โจ'], + \ ['lor' , 'โจ'], \ ['ltimes' , 'โ'], \ ['mapsto' , 'โฆ'], \ ['measuredangle' , 'โก'], @@ -839,6 +840,7 @@ if has("conceal") && &enc == 'utf-8' \ ['nless' , 'โฎ'], \ ['nmid' , 'โค'], \ ['notin' , 'โ'], + \ ['nparallel' , 'โฆ'], \ ['nprec' , 'โ'], \ ['nrightarrow' , 'โ'], \ ['nRightarrow' , 'โ'], @@ -940,10 +942,12 @@ if has("conceal") && &enc == 'utf-8' \ ['trianglerighteq', 'โต'], \ ['twoheadleftarrow', 'โ'], \ ['twoheadrightarrow', 'โ '], + \ ['ulcorner' , 'โ'], \ ['uparrow' , 'โ'], \ ['Uparrow' , 'โ'], \ ['updownarrow' , 'โ'], \ ['Updownarrow' , 'โ'], + \ ['urcorner' , 'โ'], \ ['varnothing' , 'โ
'], \ ['vartriangle' , 'โ'], \ ['vdash' , 'โข'], @@ -959,6 +963,15 @@ if has("conceal") && &enc == 'utf-8' " \ ['jmath' , 'X'] " \ ['uminus' , 'X'] " \ ['uplus' , 'X'] + if &ambw == "double" || exists("g:tex_usedblwidth") + let s:texMathList= s:texMathList + [ + \ ['right\\rangle' , 'ใ'], + \ ['left\\langle' , 'ใ']] + else + let s:texMathList= s:texMathList + [ + \ ['right\\rangle' , '>'], + \ ['left\\langle' , '<']] + endif for texmath in s:texMathList if texmath[0] =~# '\w$' exe "syn match texMathSymbol '\\\\".texmath[0]."\\>' contained conceal cchar=".texmath[1] @@ -1136,9 +1149,21 @@ if has("conceal") && &enc == 'utf-8' call s:SuperSub('texSubscript','_','9','โ') call s:SuperSub('texSubscript','_','a','โ') call s:SuperSub('texSubscript','_','e','โ') + call s:SuperSub('texSubscript','_','h','โ') call s:SuperSub('texSubscript','_','i','แตข') + call s:SuperSub('texSubscript','_','j','โฑผ') + call s:SuperSub('texSubscript','_','k','โ') + call s:SuperSub('texSubscript','_','l','โ') + call s:SuperSub('texSubscript','_','m','โ') + call s:SuperSub('texSubscript','_','n','โ') call s:SuperSub('texSubscript','_','o','โ') + call s:SuperSub('texSubscript','_','p','โ') + call s:SuperSub('texSubscript','_','r','แตฃ') + call s:SuperSub('texSubscript','_','s','โ') + call s:SuperSub('texSubscript','_','t','โ') call s:SuperSub('texSubscript','_','u','แตค') + call s:SuperSub('texSubscript','_','v','แตฅ') + call s:SuperSub('texSubscript','_','x','โ') call s:SuperSub('texSubscript','_',',','๏ธ') call s:SuperSub('texSubscript','_','+','โ') call s:SuperSub('texSubscript','_','-','โ') @@ -1154,6 +1179,7 @@ if has("conceal") && &enc == 'utf-8' call s:SuperSub('texSubscript','_','\\phi\>' ,'แตฉ') call s:SuperSub('texSubscript','_','\\gamma\>','แตง') call s:SuperSub('texSubscript','_','\\chi\>' ,'แตช') + delfun s:SuperSub endif @@ -1260,86 +1286,87 @@ endif " --------------------------------------------------------------------- " Highlighting: {{{1 -if did_tex_syntax_inits == 1 - let did_tex_syntax_inits= 2 + +" Define the default highlighting. {{{1 +if !exists("skip_tex_syntax_inits") + " TeX highlighting groups which should share similar highlighting if !exists("g:tex_no_error") if !exists("g:tex_no_math") - HiLink texBadMath texError - HiLink texMathDelimBad texError - HiLink texMathError texError + hi def link texBadMath texError + hi def link texMathDelimBad texError + hi def link texMathError texError if !b:tex_stylish - HiLink texOnlyMath texError + hi def link texOnlyMath texError endif endif - HiLink texError Error + hi def link texError Error endif hi texBoldStyle gui=bold cterm=bold hi texItalStyle gui=italic cterm=italic hi texBoldItalStyle gui=bold,italic cterm=bold,italic hi texItalBoldStyle gui=bold,italic cterm=bold,italic - HiLink texCite texRefZone - HiLink texDefCmd texDef - HiLink texDefName texDef - HiLink texDocType texCmdName - HiLink texDocTypeArgs texCmdArgs - HiLink texInputFileOpt texCmdArgs - HiLink texInputCurlies texDelimiter - HiLink texLigature texSpecialChar + hi def link texCite texRefZone + hi def link texDefCmd texDef + hi def link texDefName texDef + hi def link texDocType texCmdName + hi def link texDocTypeArgs texCmdArgs + hi def link texInputFileOpt texCmdArgs + hi def link texInputCurlies texDelimiter + hi def link texLigature texSpecialChar if !exists("g:tex_no_math") - HiLink texMathDelimSet1 texMathDelim - HiLink texMathDelimSet2 texMathDelim - HiLink texMathDelimKey texMathDelim - HiLink texMathMatcher texMath - HiLink texAccent texStatement - HiLink texGreek texStatement - HiLink texSuperscript texStatement - HiLink texSubscript texStatement - HiLink texSuperscripts texSuperscript - HiLink texSubscripts texSubscript - HiLink texMathSymbol texStatement - HiLink texMathZoneV texMath - HiLink texMathZoneW texMath - HiLink texMathZoneX texMath - HiLink texMathZoneY texMath - HiLink texMathZoneV texMath - HiLink texMathZoneZ texMath + hi def link texMathDelimSet1 texMathDelim + hi def link texMathDelimSet2 texMathDelim + hi def link texMathDelimKey texMathDelim + hi def link texMathMatcher texMath + hi def link texAccent texStatement + hi def link texGreek texStatement + hi def link texSuperscript texStatement + hi def link texSubscript texStatement + hi def link texSuperscripts texSuperscript + hi def link texSubscripts texSubscript + hi def link texMathSymbol texStatement + hi def link texMathZoneV texMath + hi def link texMathZoneW texMath + hi def link texMathZoneX texMath + hi def link texMathZoneY texMath + hi def link texMathZoneV texMath + hi def link texMathZoneZ texMath endif - HiLink texBeginEnd texCmdName - HiLink texBeginEndName texSection - HiLink texSpaceCode texStatement - HiLink texStyleStatement texStatement - HiLink texTypeSize texType - HiLink texTypeStyle texType + hi def link texBeginEnd texCmdName + hi def link texBeginEndName texSection + hi def link texSpaceCode texStatement + hi def link texStyleStatement texStatement + hi def link texTypeSize texType + hi def link texTypeStyle texType " Basic TeX highlighting groups - HiLink texCmdArgs Number - HiLink texCmdName Statement - HiLink texComment Comment - HiLink texDef Statement - HiLink texDefParm Special - HiLink texDelimiter Delimiter - HiLink texInput Special - HiLink texInputFile Special - HiLink texLength Number - HiLink texMath Special - HiLink texMathDelim Statement - HiLink texMathOper Operator - HiLink texNewCmd Statement - HiLink texNewEnv Statement - HiLink texOption Number - HiLink texRefZone Special - HiLink texSection PreCondit - HiLink texSpaceCodeChar Special - HiLink texSpecialChar SpecialChar - HiLink texStatement Statement - HiLink texString String - HiLink texTodo Todo - HiLink texType Type - HiLink texZone PreCondit + hi def link texCmdArgs Number + hi def link texCmdName Statement + hi def link texComment Comment + hi def link texDef Statement + hi def link texDefParm Special + hi def link texDelimiter Delimiter + hi def link texInput Special + hi def link texInputFile Special + hi def link texLength Number + hi def link texMath Special + hi def link texMathDelim Statement + hi def link texMathOper Operator + hi def link texNewCmd Statement + hi def link texNewEnv Statement + hi def link texOption Number + hi def link texRefZone Special + hi def link texSection PreCondit + hi def link texSpaceCodeChar Special + hi def link texSpecialChar SpecialChar + hi def link texStatement Statement + hi def link texString String + hi def link texTodo Todo + hi def link texType Type + hi def link texZone PreCondit - delcommand HiLink endif " Cleanup: {{{1 diff --git a/runtime/syntax/texinfo.vim b/runtime/syntax/texinfo.vim index 134fc6763c..a4b7689707 100644 --- a/runtime/syntax/texinfo.vim +++ b/runtime/syntax/texinfo.vim @@ -9,10 +9,8 @@ " since @ can have special meanings, everything is 'match'-ed and 'region'-ed " (including @ in 'iskeyword' option has unexpected effects) -" Remove any old syntax stuff hanging around, if needed -if version < 600 - syn clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -356,48 +354,37 @@ syn cluster texinfoReducedAll contains=texinfoSpecialChar,texinfoBrcPrmAtCmd "============================================================================== " highlighting -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_texinfo_syn_inits") - - if version < 508 - let did_texinfo_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink texinfoSpecialChar Special - HiLink texinfoHFSpecialChar Special - - HiLink texinfoError Error - HiLink texinfoIdent Identifier - HiLink texinfoAssignment Identifier - HiLink texinfoSinglePar Identifier - HiLink texinfoIndexPar Identifier - HiLink texinfoSIPar Identifier - HiLink texinfoDIEPar Identifier - HiLink texinfoTexCmd PreProc - - - HiLink texinfoAtCmd Statement "@-command - HiLink texinfoPrmAtCmd String "@-command in one line with unknown nr. of parameters - "is String because is found as a region and is 'matchgroup'-ed - "to texinfoAtCmd - HiLink texinfoBrcPrmAtCmd String "@-command with parameter(s) in braces ({}) - "is String because is found as a region and is 'matchgroup'-ed to texinfoAtCmd - HiLink texinfoMltlnAtCmdFLine texinfoAtCmd "repeated embedded First lines in @-commands - HiLink texinfoMltlnAtCmd String "@-command in multiple lines - "is String because is found as a region and is 'matchgroup'-ed to texinfoAtCmd - HiLink texinfoMltln2AtCmd PreProc "@-command in multiple lines (same as texinfoMltlnAtCmd, just with other colors) - HiLink texinfoMltlnDMAtCmd PreProc "@-command in multiple lines (same as texinfoMltlnAtCmd, just with other colors; used for @detailmenu, which can be included in @menu) - HiLink texinfoMltlnNAtCmd Normal "@-command in multiple lines (same as texinfoMltlnAtCmd, just with other colors) - HiLink texinfoThisAtCmd Statement "@-command used in headers and footers (@this... series) - - HiLink texinfoComment Comment - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link texinfoSpecialChar Special +hi def link texinfoHFSpecialChar Special + +hi def link texinfoError Error +hi def link texinfoIdent Identifier +hi def link texinfoAssignment Identifier +hi def link texinfoSinglePar Identifier +hi def link texinfoIndexPar Identifier +hi def link texinfoSIPar Identifier +hi def link texinfoDIEPar Identifier +hi def link texinfoTexCmd PreProc + + +hi def link texinfoAtCmd Statement "@-command +hi def link texinfoPrmAtCmd String "@-command in one line with unknown nr. of parameters + "is String because is found as a region and is 'matchgroup'-ed + "to texinfoAtCmd +hi def link texinfoBrcPrmAtCmd String "@-command with parameter(s) in braces ({}) + "is String because is found as a region and is 'matchgroup'-ed to texinfoAtCmd +hi def link texinfoMltlnAtCmdFLine texinfoAtCmd "repeated embedded First lines in @-commands +hi def link texinfoMltlnAtCmd String "@-command in multiple lines + "is String because is found as a region and is 'matchgroup'-ed to texinfoAtCmd +hi def link texinfoMltln2AtCmd PreProc "@-command in multiple lines (same as texinfoMltlnAtCmd, just with other colors) +hi def link texinfoMltlnDMAtCmd PreProc "@-command in multiple lines (same as texinfoMltlnAtCmd, just with other colors; used for @detailmenu, which can be included in @menu) +hi def link texinfoMltlnNAtCmd Normal "@-command in multiple lines (same as texinfoMltlnAtCmd, just with other colors) +hi def link texinfoThisAtCmd Statement "@-command used in headers and footers (@this... series) + +hi def link texinfoComment Comment + let b:current_syntax = "texinfo" diff --git a/runtime/syntax/texmf.vim b/runtime/syntax/texmf.vim index 7b91168f08..d1268faff7 100644 --- a/runtime/syntax/texmf.vim +++ b/runtime/syntax/texmf.vim @@ -6,12 +6,9 @@ " URL: http://physics.muni.cz/~yeti/download/syntax/texmf.vim " Setup -if version >= 600 - if exists("b:current_syntax") - finish - endif -else - syntax clear +" quit when a syntax file was already loaded +if exists("b:current_syntax") + finish endif syn case match @@ -45,42 +42,33 @@ syn region texmfBrace matchgroup=texmfBraceBrace start="{" end="}" contains=ALLB syn match texmfBraceError "}" " Define the default highlighting -if version >= 508 || !exists("did_texmf_syntax_inits") - if version < 508 - let did_texmf_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - HiLink texmfComment Comment - HiLink texmfTodo Todo +hi def link texmfComment Comment +hi def link texmfTodo Todo - HiLink texmfPassedParameter texmfVariable - HiLink texmfVariable Identifier +hi def link texmfPassedParameter texmfVariable +hi def link texmfVariable Identifier - HiLink texmfNumber Number - HiLink texmfString String +hi def link texmfNumber Number +hi def link texmfString String - HiLink texmfLHSStart texmfLHS - HiLink texmfLHSVariable texmfLHS - HiLink texmfLHSDot texmfLHS - HiLink texmfLHS Type +hi def link texmfLHSStart texmfLHS +hi def link texmfLHSVariable texmfLHS +hi def link texmfLHSDot texmfLHS +hi def link texmfLHS Type - HiLink texmfEquals Normal +hi def link texmfEquals Normal - HiLink texmfBraceBrace texmfDelimiter - HiLink texmfComma texmfDelimiter - HiLink texmfColons texmfDelimiter - HiLink texmfDelimiter Preproc +hi def link texmfBraceBrace texmfDelimiter +hi def link texmfComma texmfDelimiter +hi def link texmfColons texmfDelimiter +hi def link texmfDelimiter Preproc - HiLink texmfDoubleExclam Statement - HiLink texmfSpecial Special +hi def link texmfDoubleExclam Statement +hi def link texmfSpecial Special - HiLink texmfBraceError texmfError - HiLink texmfError Error +hi def link texmfBraceError texmfError +hi def link texmfError Error - delcommand HiLink -endif let b:current_syntax = "texmf" diff --git a/runtime/syntax/tf.vim b/runtime/syntax/tf.vim index 2a9a999883..47775b8637 100644 --- a/runtime/syntax/tf.vim +++ b/runtime/syntax/tf.vim @@ -9,11 +9,8 @@ " Remove any old syntax stuff hanging around -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -161,44 +158,34 @@ else endif " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_tf_syn_inits") - if version < 508 - let did_tf_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink tfComment Comment - HiLink tfString String - HiLink tfNumber Number - HiLink tfFloat Float - HiLink tfIdentifier Identifier - HiLink tfVar Identifier - HiLink tfWorld Identifier - HiLink tfReadonly Identifier - HiLink tfHook Identifier - HiLink tfFunctions Function - HiLink tfRepeat Repeat - HiLink tfConditional Conditional - HiLink tfLabel Label - HiLink tfStatement Statement - HiLink tfType Type - HiLink tfInclude Include - HiLink tfDefine Define - HiLink tfSpecialChar SpecialChar - HiLink tfSpecialCharEsc SpecialChar - HiLink tfParentError Error - HiLink tfTodo Todo - HiLink tfEndCommand Delimiter - HiLink tfJoinLines Delimiter - HiLink tfOperator Operator - HiLink tfRelation Operator - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link tfComment Comment +hi def link tfString String +hi def link tfNumber Number +hi def link tfFloat Float +hi def link tfIdentifier Identifier +hi def link tfVar Identifier +hi def link tfWorld Identifier +hi def link tfReadonly Identifier +hi def link tfHook Identifier +hi def link tfFunctions Function +hi def link tfRepeat Repeat +hi def link tfConditional Conditional +hi def link tfLabel Label +hi def link tfStatement Statement +hi def link tfType Type +hi def link tfInclude Include +hi def link tfDefine Define +hi def link tfSpecialChar SpecialChar +hi def link tfSpecialCharEsc SpecialChar +hi def link tfParentError Error +hi def link tfTodo Todo +hi def link tfEndCommand Delimiter +hi def link tfJoinLines Delimiter +hi def link tfOperator Operator +hi def link tfRelation Operator + let b:current_syntax = "tf" diff --git a/runtime/syntax/tli.vim b/runtime/syntax/tli.vim index 5685a6cbf2..b96d4a2119 100644 --- a/runtime/syntax/tli.vim +++ b/runtime/syntax/tli.vim @@ -4,11 +4,8 @@ " Last Change: 2001 May 10 " Version: 1.0 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -44,27 +41,17 @@ syn match tliComment "#.*" syn case match " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_tli_syntax_inits") - if version < 508 - let did_tli_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink tliNumber Number - HiLink tliString String - HiLink tliComment Comment - HiLink tliSpecial SpecialChar - HiLink tliIdentifier Identifier - HiLink tliObject Statement - HiLink tliField Type - HiLink tliStyle PreProc - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link tliNumber Number +hi def link tliString String +hi def link tliComment Comment +hi def link tliSpecial SpecialChar +hi def link tliIdentifier Identifier +hi def link tliObject Statement +hi def link tliField Type +hi def link tliStyle PreProc + let b:current_syntax = "tli" diff --git a/runtime/syntax/tpp.vim b/runtime/syntax/tpp.vim index 050a2ba78d..1244b97f08 100644 --- a/runtime/syntax/tpp.vim +++ b/runtime/syntax/tpp.vim @@ -17,11 +17,8 @@ " the latest version of this file. " SPAM is _NOT_ welcome - be ready to be reported! -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -51,11 +48,7 @@ syn region tppAbstractOption start="^--\%(author\|title\|date\|footer\)" end="$" if main_syntax != 'sh' " shell command - if version < 600 - syn include @tppShExec <sfile>:p:h/sh.vim - else - syn include @tppShExec syntax/sh.vim - endif + syn include @tppShExec syntax/sh.vim unlet b:current_syntax syn region shExec matchgroup=tppPageLocalOptionKey start='^--exec *' keepend end='$' contains=@tppShExec @@ -65,35 +58,25 @@ endif syn match tppComment "^--##.*$" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_tpp_syn_inits") - if version < 508 - let did_tpp_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink tppAbstractOptionKey Special - HiLink tppPageLocalOptionKey Keyword - HiLink tppPageLocalSwitchKey Keyword - HiLink tppColorOptionKey Keyword - HiLink tppTimeOptionKey Comment - HiLink tppNewPageOptionKey PreProc - HiLink tppString String - HiLink tppColor String - HiLink tppTime Number - HiLink tppComment Comment - HiLink tppAbstractOption Error - HiLink tppPageLocalOption Error - HiLink tppPageLocalSwitch Error - HiLink tppColorOption Error - HiLink tppNewPageOption Error - HiLink tppTimeOption Error +hi def link tppAbstractOptionKey Special +hi def link tppPageLocalOptionKey Keyword +hi def link tppPageLocalSwitchKey Keyword +hi def link tppColorOptionKey Keyword +hi def link tppTimeOptionKey Comment +hi def link tppNewPageOptionKey PreProc +hi def link tppString String +hi def link tppColor String +hi def link tppTime Number +hi def link tppComment Comment +hi def link tppAbstractOption Error +hi def link tppPageLocalOption Error +hi def link tppPageLocalSwitch Error +hi def link tppColorOption Error +hi def link tppNewPageOption Error +hi def link tppTimeOption Error - delcommand HiLink -endif let b:current_syntax = "tpp" diff --git a/runtime/syntax/trasys.vim b/runtime/syntax/trasys.vim index cfecc1c1fd..d52b5eeb47 100644 --- a/runtime/syntax/trasys.vim +++ b/runtime/syntax/trasys.vim @@ -8,11 +8,8 @@ -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -21,11 +18,7 @@ endif let fortran_free_source=1 " Load FORTRAN syntax file -if version < 600 - source <sfile>:p:h/fortran.vim -else - runtime! syntax/fortran.vim -endif +runtime! syntax/fortran.vim unlet b:current_syntax @@ -136,40 +129,30 @@ syn sync match trasysSync grouphere trasysComment "^HEADER DOCUMENTATION DATA" " Define the default highlighting -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_trasys_syntax_inits") - if version < 508 - let did_trasys_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink trasysOptions Special - HiLink trasysSurface Special - HiLink trasysSurfaceType Constant - HiLink trasysSurfaceArgs Constant - HiLink trasysArgs Constant - HiLink trasysOperations Statement - HiLink trasysSubRoutine Statement - HiLink trassyPrcsrSegm PreProc - HiLink trasysIdentifier Identifier - HiLink trasysComment Comment - HiLink trasysHeader Typedef - HiLink trasysMacro Macro - HiLink trasysInteger Number - HiLink trasysFloat Float - HiLink trasysScientific Float - - HiLink trasysBlank SpecialChar - - HiLink trasysEndData Macro - - HiLink trasysTodo Todo - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link trasysOptions Special +hi def link trasysSurface Special +hi def link trasysSurfaceType Constant +hi def link trasysSurfaceArgs Constant +hi def link trasysArgs Constant +hi def link trasysOperations Statement +hi def link trasysSubRoutine Statement +hi def link trassyPrcsrSegm PreProc +hi def link trasysIdentifier Identifier +hi def link trasysComment Comment +hi def link trasysHeader Typedef +hi def link trasysMacro Macro +hi def link trasysInteger Number +hi def link trasysFloat Float +hi def link trasysScientific Float + +hi def link trasysBlank SpecialChar + +hi def link trasysEndData Macro + +hi def link trasysTodo Todo + let b:current_syntax = "trasys" diff --git a/runtime/syntax/trustees.vim b/runtime/syntax/trustees.vim index 4bc8874772..6c58d3983d 100644 --- a/runtime/syntax/trustees.vim +++ b/runtime/syntax/trustees.vim @@ -3,9 +3,8 @@ " Maintainer: Nima Talebi <nima@it.net.au> " Last Change: 2005-10-12 -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif diff --git a/runtime/syntax/tsalt.vim b/runtime/syntax/tsalt.vim index 887d6b75e7..8dd2a24df9 100644 --- a/runtime/syntax/tsalt.vim +++ b/runtime/syntax/tsalt.vim @@ -4,11 +4,8 @@ " Last Change: 2012 Feb 03 by Thilo Six " Version Info: @(#)tsalt.vim 1.5 97/12/16 08:11:15 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -171,46 +168,36 @@ syn sync ccomment tsaltComment " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_tsalt_syntax_inits") - if version < 508 - let did_tsalt_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink tsaltFunction Statement - HiLink tsaltSysVar Type - "HiLink tsaltLibFunc UserDefFunc - "HiLink tsaltConstants Type - "HiLink tsaltFuncArg Type - "HiLink tsaltOperator Operator - "HiLink tsaltLabel Label - "HiLink tsaltUserLabel Label - HiLink tsaltConditional Conditional - HiLink tsaltRepeat Repeat - HiLink tsaltCharacter SpecialChar - HiLink tsaltSpecialCharacter SpecialChar - HiLink tsaltNumber Number - HiLink tsaltFloat Float - HiLink tsaltCommentError tsaltError - HiLink tsaltInclude Include - HiLink tsaltPreProc PreProc - HiLink tsaltDefine Macro - HiLink tsaltIncluded tsaltString - HiLink tsaltError Error - HiLink tsaltStatement Statement - HiLink tsaltPreCondit PreCondit - HiLink tsaltType Type - HiLink tsaltString String - HiLink tsaltComment Comment - HiLink tsaltSpecial Special - HiLink tsaltTodo Todo - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link tsaltFunction Statement +hi def link tsaltSysVar Type +"hi def link tsaltLibFunc UserDefFunc +"hi def link tsaltConstants Type +"hi def link tsaltFuncArg Type +"hi def link tsaltOperator Operator +"hi def link tsaltLabel Label +"hi def link tsaltUserLabel Label +hi def link tsaltConditional Conditional +hi def link tsaltRepeat Repeat +hi def link tsaltCharacter SpecialChar +hi def link tsaltSpecialCharacter SpecialChar +hi def link tsaltNumber Number +hi def link tsaltFloat Float +hi def link tsaltCommentError tsaltError +hi def link tsaltInclude Include +hi def link tsaltPreProc PreProc +hi def link tsaltDefine Macro +hi def link tsaltIncluded tsaltString +hi def link tsaltError Error +hi def link tsaltStatement Statement +hi def link tsaltPreCondit PreCondit +hi def link tsaltType Type +hi def link tsaltString String +hi def link tsaltComment Comment +hi def link tsaltSpecial Special +hi def link tsaltTodo Todo + let b:current_syntax = "tsalt" diff --git a/runtime/syntax/tsscl.vim b/runtime/syntax/tsscl.vim index 3fc18c6847..fd2a5e2ba9 100644 --- a/runtime/syntax/tsscl.vim +++ b/runtime/syntax/tsscl.vim @@ -8,11 +8,8 @@ -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -179,37 +176,27 @@ syn match tssclScientific "-\=\<[0-9]*\.[0-9]*E[-+]\=[0-9]\+\>" " Define the default highlighting -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_tsscl_syntax_inits") - if version < 508 - let did_tsscl_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink tssclCommand Statement - HiLink tssclKeyword Special - HiLink tssclEnd Macro - HiLink tssclUnits Special - - HiLink tssclComment Comment - HiLink tssclDirective Statement - HiLink tssclConditional Conditional - HiLink tssclContChar Macro - HiLink tssclQualifier Typedef - HiLink tssclSymbol Identifier - HiLink tssclSymbol2 Symbol - HiLink tssclString String - HiLink tssclOper Operator - - HiLink tssclInteger Number - HiLink tssclFloat Number - HiLink tssclScientific Number - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link tssclCommand Statement +hi def link tssclKeyword Special +hi def link tssclEnd Macro +hi def link tssclUnits Special + +hi def link tssclComment Comment +hi def link tssclDirective Statement +hi def link tssclConditional Conditional +hi def link tssclContChar Macro +hi def link tssclQualifier Typedef +hi def link tssclSymbol Identifier +hi def link tssclSymbol2 Symbol +hi def link tssclString String +hi def link tssclOper Operator + +hi def link tssclInteger Number +hi def link tssclFloat Number +hi def link tssclScientific Number + let b:current_syntax = "tsscl" diff --git a/runtime/syntax/tssgm.vim b/runtime/syntax/tssgm.vim index b8182d48ea..8ca7962e81 100644 --- a/runtime/syntax/tssgm.vim +++ b/runtime/syntax/tssgm.vim @@ -8,11 +8,8 @@ -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -75,35 +72,25 @@ syn match tssgmScientific "-\=\<[0-9]*\.[0-9]*E[-+]\=[0-9]\+\>" " Define the default highlighting -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_tssgm_syntax_inits") - if version < 508 - let did_tssgm_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink tssgmParam Statement - HiLink tssgmSurfType Type - HiLink tssgmArgs Special - HiLink tssgmDelim Typedef - HiLink tssgmEnd Macro - HiLink tssgmUnits Special - - HiLink tssgmDefault SpecialComment - HiLink tssgmComment Statement - HiLink tssgmCommentString Comment - HiLink tssgmSurfIdent Identifier - HiLink tssgmString Delimiter - - HiLink tssgmInteger Number - HiLink tssgmFloat Float - HiLink tssgmScientific Float - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link tssgmParam Statement +hi def link tssgmSurfType Type +hi def link tssgmArgs Special +hi def link tssgmDelim Typedef +hi def link tssgmEnd Macro +hi def link tssgmUnits Special + +hi def link tssgmDefault SpecialComment +hi def link tssgmComment Statement +hi def link tssgmCommentString Comment +hi def link tssgmSurfIdent Identifier +hi def link tssgmString Delimiter + +hi def link tssgmInteger Number +hi def link tssgmFloat Float +hi def link tssgmScientific Float + let b:current_syntax = "tssgm" diff --git a/runtime/syntax/tssop.vim b/runtime/syntax/tssop.vim index d416df054c..6a775b2358 100644 --- a/runtime/syntax/tssop.vim +++ b/runtime/syntax/tssop.vim @@ -8,11 +8,8 @@ -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -56,30 +53,20 @@ syn match tssopScientific "-\=\<[0-9]*\.[0-9]*E[-+]\=[0-9]\+\>" " Define the default highlighting -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_tssop_syntax_inits") - if version < 508 - let did_tssop_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink tssopParam Statement - HiLink tssopProp Identifier - HiLink tssopArgs Special - - HiLink tssopComment Statement - HiLink tssopCommentString Comment - HiLink tssopPropName Typedef - - HiLink tssopInteger Number - HiLink tssopFloat Float - HiLink tssopScientific Float - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link tssopParam Statement +hi def link tssopProp Identifier +hi def link tssopArgs Special + +hi def link tssopComment Statement +hi def link tssopCommentString Comment +hi def link tssopPropName Typedef + +hi def link tssopInteger Number +hi def link tssopFloat Float +hi def link tssopScientific Float + let b:current_syntax = "tssop" diff --git a/runtime/syntax/tutor.vim b/runtime/syntax/tutor.vim index bce9189660..fbf159582a 100644 --- a/runtime/syntax/tutor.vim +++ b/runtime/syntax/tutor.vim @@ -31,26 +31,20 @@ syn keyword tutorMarks TODO NOTE IMPORTANT TIP ATTENTION EXERCISE syn keyword tutorMarks todo note tip attention exercise syn keyword tutorMarks Todo Note Tip Excersise -syn match tutorTextMark /\\\@<!--->/ conceal cchar=โ -syn region tutorSampleText start=/^\(--->\)\@=/ end=/$/ keepend contains=@SPELL -syn match tutorSampleTextMark /^--->/ contained containedin=tutorSampleText conceal cchar=โ -syn match tutorSampleTextExpect /\}\@<! {expect:.\+}\s*$/ contained containedin=tutorSampleText conceal -syn match tutorSampleTextExpect /|\@<! |expect:.\+|\s*$/ contained containedin=tutorSampleText conceal - syn region tutorCodeblock matchgroup=Delimiter start=/^\~\{3}.*$/ end=/^\~\{3}/ -syn region tutorShell matchgroup=Delimiter start=/^\~\{3} sh\s*$/ end=/^\~\{3}/ keepend contains=@TUTORSHELL concealends +syn region tutorShell matchgroup=Delimiter start=/^\~\{3} sh\s*$/ end=/^\~\{3}/ keepend contains=@TUTORSHELL syn match tutorShellPrompt /\(^\s*\)\@<=[$#]/ contained containedin=tutorShell -syn region tutorInlineCode matchgroup=Delimiter start=/\\\@<!`/ end=/\\\@<!\(`{\@!\|`\s\)/ concealends +syn region tutorInlineCode matchgroup=Delimiter start=/\\\@<!`/ end=/\\\@<!\(`{\@!\|`\s\)/ -syn region tutorCommand matchgroup=Delimiter start=/^\~\{3} cmd\( :\)\?\s*$/ end=/^\~\{3}/ keepend contains=@VIM concealends -syn region tutorInlineCommand matchgroup=Delimiter start=/\\\@<!`\(.*{vim}\)\@=/ end=/\\\@<!`\({vim}\)\@=/ nextgroup=tutorInlineType contains=@VIM concealends +syn region tutorCommand matchgroup=Delimiter start=/^\~\{3} cmd\( :\)\?\s*$/ end=/^\~\{3}/ keepend contains=@VIM +syn region tutorInlineCommand matchgroup=Delimiter start=/\\\@<!`\(.*{vim}\)\@=/ end=/\\\@<!`\({vim}\)\@=/ nextgroup=tutorInlineType contains=@VIM -syn region tutorNormal matchgroup=Delimiter start=/^\~\{3} norm\(al\?\)\?\s*$/ end=/^\~\{3}/ contains=@VIMNORMAL concealends -syn region tutorInlineNormal matchgroup=Delimiter start=/\\\@<!`\(\S*{normal}\)\@=/ end=/\\\@<!`\({normal}\)\@=/ nextgroup=tutorInlineType contains=@VIMNORMAL concealends +syn region tutorNormal matchgroup=Delimiter start=/^\~\{3} norm\(al\?\)\?\s*$/ end=/^\~\{3}/ contains=@VIMNORMAL +syn region tutorInlineNormal matchgroup=Delimiter start=/\\\@<!`\(\S*{normal}\)\@=/ end=/\\\@<!`\({normal}\)\@=/ nextgroup=tutorInlineType contains=@VIMNORMAL -syn match tutorInlineType /{\(normal\|vim\)}/ contained conceal +syn match tutorInlineType /{\(normal\|vim\)}/ contained syn match tutorInlineOK /โ/ syn match tutorInlineX /โ/ @@ -72,7 +66,7 @@ hi! tutorMarks cterm=bold gui=bold hi! tutorEmphasis gui=italic cterm=italic hi! tutorBold gui=bold cterm=bold -hi! link tutorSampleText Special +hi! link tutorExpect Special hi! tutorOK ctermfg=green guifg=#00ff88 cterm=bold gui=bold hi! tutorX ctermfg=red guifg=#ff2000 cterm=bold gui=bold hi! link tutorInlineOK tutorOK diff --git a/runtime/syntax/uc.vim b/runtime/syntax/uc.vim index 7eab1d48ae..90d33396c5 100644 --- a/runtime/syntax/uc.vim +++ b/runtime/syntax/uc.vim @@ -7,11 +7,8 @@ " Please check :help uc.vim for comments on some of the options available. -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -110,64 +107,54 @@ endif exec "syn sync ccomment ucComment minlines=" . uc_minlines " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_uc_syntax_inits") - if version < 508 - let did_uc_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink ucFuncDef Conditional - HiLink ucEventDef Conditional - HiLink ucBraces Function - HiLink ucBranch Conditional - HiLink ucLabel Label - HiLink ucUserLabel Label - HiLink ucConditional Conditional - HiLink ucRepeat Repeat - HiLink ucStorageClass StorageClass - HiLink ucMethodDecl ucStorageClass - HiLink ucClassDecl ucStorageClass - HiLink ucScopeDecl ucStorageClass - HiLink ucBoolean Boolean - HiLink ucSpecial Special - HiLink ucSpecialError Error - HiLink ucSpecialCharError Error - HiLink ucString String - HiLink ucCharacter Character - HiLink ucSpecialChar SpecialChar - HiLink ucNumber Number - HiLink ucError Error - HiLink ucStringError Error - HiLink ucStatement Statement - HiLink ucOperator Operator - HiLink ucOverLoaded Operator - HiLink ucComment Comment - HiLink ucDocComment Comment - HiLink ucLineComment Comment - HiLink ucConstant ucBoolean - HiLink ucTypedef Typedef - HiLink ucTodo Todo - - HiLink ucCommentTitle SpecialComment - HiLink ucDocTags Special - HiLink ucDocParam Function - HiLink ucCommentStar ucComment - - HiLink ucType Type - HiLink ucExternal Include - - HiLink ucClassKeys Conditional - HiLink ucClassLabel Conditional - - HiLink htmlComment Special - HiLink htmlCommentPart Special - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link ucFuncDef Conditional +hi def link ucEventDef Conditional +hi def link ucBraces Function +hi def link ucBranch Conditional +hi def link ucLabel Label +hi def link ucUserLabel Label +hi def link ucConditional Conditional +hi def link ucRepeat Repeat +hi def link ucStorageClass StorageClass +hi def link ucMethodDecl ucStorageClass +hi def link ucClassDecl ucStorageClass +hi def link ucScopeDecl ucStorageClass +hi def link ucBoolean Boolean +hi def link ucSpecial Special +hi def link ucSpecialError Error +hi def link ucSpecialCharError Error +hi def link ucString String +hi def link ucCharacter Character +hi def link ucSpecialChar SpecialChar +hi def link ucNumber Number +hi def link ucError Error +hi def link ucStringError Error +hi def link ucStatement Statement +hi def link ucOperator Operator +hi def link ucOverLoaded Operator +hi def link ucComment Comment +hi def link ucDocComment Comment +hi def link ucLineComment Comment +hi def link ucConstant ucBoolean +hi def link ucTypedef Typedef +hi def link ucTodo Todo + +hi def link ucCommentTitle SpecialComment +hi def link ucDocTags Special +hi def link ucDocParam Function +hi def link ucCommentStar ucComment + +hi def link ucType Type +hi def link ucExternal Include + +hi def link ucClassKeys Conditional +hi def link ucClassLabel Conditional + +hi def link htmlComment Special +hi def link htmlCommentPart Special + let b:current_syntax = "uc" diff --git a/runtime/syntax/uil.vim b/runtime/syntax/uil.vim index b5421bcfdb..088a0f6c86 100644 --- a/runtime/syntax/uil.vim +++ b/runtime/syntax/uil.vim @@ -1,13 +1,13 @@ " Vim syntax file " Language: Motif UIL (User Interface Language) " Maintainer: Thomas Koehler <jean-luc@picard.franken.de> -" Last Change: 2013 May 23 +" Please be aware: I'm often slow to answer email due to a high +" non-computer related workload (sometimes 4-8 weeks) +" Last Change: 2016 September 6 " URL: http://gott-gehabt.de/800_wer_wir_sind/thomas/Homepage/Computer/vim/syntax/uil.vim -" Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -47,37 +47,27 @@ syn region uilDefine start="^#\s*\(define\>\|undef\>\)" end="$" contains=uilLin syn sync ccomment uilComment " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_uil_syn_inits") - if version < 508 - let did_uil_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - " The default highlighting. - HiLink uilCharacter uilString - HiLink uilSpecialCharacter uilSpecial - HiLink uilNumber uilString - HiLink uilCommentError uilError - HiLink uilInclude uilPreCondit - HiLink uilDefine uilPreCondit - HiLink uilIncluded uilString - HiLink uilSpecialFunction uilRessource - HiLink uilRessource Identifier - HiLink uilSpecialStatement Keyword - HiLink uilError Error - HiLink uilPreCondit PreCondit - HiLink uilType Type - HiLink uilString String - HiLink uilComment Comment - HiLink uilSpecial Special - HiLink uilTodo Todo +" The default highlighting. +hi def link uilCharacter uilString +hi def link uilSpecialCharacter uilSpecial +hi def link uilNumber uilString +hi def link uilCommentError uilError +hi def link uilInclude uilPreCondit +hi def link uilDefine uilPreCondit +hi def link uilIncluded uilString +hi def link uilSpecialFunction uilRessource +hi def link uilRessource Identifier +hi def link uilSpecialStatement Keyword +hi def link uilError Error +hi def link uilPreCondit PreCondit +hi def link uilType Type +hi def link uilString String +hi def link uilComment Comment +hi def link uilSpecial Special +hi def link uilTodo Todo - delcommand HiLink -endif let b:current_syntax = "uil" diff --git a/runtime/syntax/upstart.vim b/runtime/syntax/upstart.vim index b3f2b9e637..140cd174e0 100644 --- a/runtime/syntax/upstart.vim +++ b/runtime/syntax/upstart.vim @@ -10,9 +10,8 @@ " It is inspired by the initng syntax file and includes sh.vim to do the " highlighting of script blocks. -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif diff --git a/runtime/syntax/vb.vim b/runtime/syntax/vb.vim index 0c05b35fbd..8ddb1efac3 100644 --- a/runtime/syntax/vb.vim +++ b/runtime/syntax/vb.vim @@ -11,11 +11,8 @@ " VIM and VIM-DEV mailing lists. It is by no means complete. " Send comments, suggestions and requests to the maintainer. -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -338,40 +335,30 @@ syn match vbTypeSpecifier "[a-zA-Z0-9][\$%&!#]"ms=s+1 syn match vbTypeSpecifier "#[a-zA-Z0-9]"me=e-1 " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_vb_syntax_inits") - if version < 508 - let did_vb_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink vbBoolean Boolean - HiLink vbLineNumber Comment - HiLink vbComment Comment - HiLink vbConditional Conditional - HiLink vbConst Constant - HiLink vbDefine Constant - HiLink vbError Error - HiLink vbFunction Identifier - HiLink vbIdentifier Identifier - HiLink vbNumber Number - HiLink vbFloat Float - HiLink vbMethods PreProc - HiLink vbOperator Operator - HiLink vbRepeat Repeat - HiLink vbString String - HiLink vbStatement Statement - HiLink vbKeyword Statement - HiLink vbEvents Special - HiLink vbTodo Todo - HiLink vbTypes Type - HiLink vbTypeSpecifier Type +hi def link vbBoolean Boolean +hi def link vbLineNumber Comment +hi def link vbComment Comment +hi def link vbConditional Conditional +hi def link vbConst Constant +hi def link vbDefine Constant +hi def link vbError Error +hi def link vbFunction Identifier +hi def link vbIdentifier Identifier +hi def link vbNumber Number +hi def link vbFloat Float +hi def link vbMethods PreProc +hi def link vbOperator Operator +hi def link vbRepeat Repeat +hi def link vbString String +hi def link vbStatement Statement +hi def link vbKeyword Statement +hi def link vbEvents Special +hi def link vbTodo Todo +hi def link vbTypes Type +hi def link vbTypeSpecifier Type - delcommand HiLink -endif let b:current_syntax = "vb" diff --git a/runtime/syntax/vera.vim b/runtime/syntax/vera.vim index b8e25cf346..b41c0a6cbf 100644 --- a/runtime/syntax/vera.vim +++ b/runtime/syntax/vera.vim @@ -10,11 +10,8 @@ " (change the value for guibg to any color you like) -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -287,74 +284,64 @@ endif exec "syn sync ccomment veraComment minlines=" . b:vera_minlines " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_vera_syn_inits") - if version < 508 - let did_vera_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet + +hi def link veraClass Identifier +hi def link veraObject Identifier +hi def link veraUserMethod Function +hi def link veraTask Keyword +hi def link veraModifier Tag +hi def link veraDeprecated veraError +hi def link veraMethods Statement +" hi def link veraInterface Label +hi def link veraInterface Function + +hi def link veraFormat veraSpecial +hi def link veraCppString veraString +hi def link veraCommentL veraComment +hi def link veraCommentStart veraComment +hi def link veraLabel Label +hi def link veraUserLabel Label +hi def link veraConditional Conditional +hi def link veraRepeat Repeat +hi def link veraCharacter Character +hi def link veraSpecialCharacter veraSpecial +hi def link veraNumber Number +hi def link veraOctal Number +hi def link veraOctalZero PreProc " link this to Error if you want +hi def link veraFloat Float +hi def link veraOctalError veraError +hi def link veraParenError veraError +hi def link veraErrInParen veraError +hi def link veraErrInBracket veraError +hi def link veraCommentError veraError +hi def link veraCommentStartError veraError +hi def link veraSpaceError SpaceError +hi def link veraSpecialError veraError +hi def link veraOperator Operator +hi def link veraStructure Structure +hi def link veraInclude Include +hi def link veraPreProc PreProc +hi def link veraDefine Macro +hi def link veraIncluded veraString +hi def link veraError Error +hi def link veraStatement Statement +hi def link veraPreCondit PreCondit +hi def link veraType Type +" hi def link veraConstant Constant +hi def link veraConstant Keyword +hi def link veraUserConstant Constant +hi def link veraCommentString veraString +hi def link veraComment2String veraString +hi def link veraCommentSkip veraComment +hi def link veraString String +hi def link veraComment Comment +hi def link veraSpecial SpecialChar +hi def link veraTodo Todo +hi def link veraCppSkip veraCppOut +hi def link veraCppOut2 veraCppOut +hi def link veraCppOut Comment - HiLink veraClass Identifier - HiLink veraObject Identifier - HiLink veraUserMethod Function - HiLink veraTask Keyword - HiLink veraModifier Tag - HiLink veraDeprecated veraError - HiLink veraMethods Statement - " HiLink veraInterface Label - HiLink veraInterface Function - - HiLink veraFormat veraSpecial - HiLink veraCppString veraString - HiLink veraCommentL veraComment - HiLink veraCommentStart veraComment - HiLink veraLabel Label - HiLink veraUserLabel Label - HiLink veraConditional Conditional - HiLink veraRepeat Repeat - HiLink veraCharacter Character - HiLink veraSpecialCharacter veraSpecial - HiLink veraNumber Number - HiLink veraOctal Number - HiLink veraOctalZero PreProc " link this to Error if you want - HiLink veraFloat Float - HiLink veraOctalError veraError - HiLink veraParenError veraError - HiLink veraErrInParen veraError - HiLink veraErrInBracket veraError - HiLink veraCommentError veraError - HiLink veraCommentStartError veraError - HiLink veraSpaceError SpaceError - HiLink veraSpecialError veraError - HiLink veraOperator Operator - HiLink veraStructure Structure - HiLink veraInclude Include - HiLink veraPreProc PreProc - HiLink veraDefine Macro - HiLink veraIncluded veraString - HiLink veraError Error - HiLink veraStatement Statement - HiLink veraPreCondit PreCondit - HiLink veraType Type - " HiLink veraConstant Constant - HiLink veraConstant Keyword - HiLink veraUserConstant Constant - HiLink veraCommentString veraString - HiLink veraComment2String veraString - HiLink veraCommentSkip veraComment - HiLink veraString String - HiLink veraComment Comment - HiLink veraSpecial SpecialChar - HiLink veraTodo Todo - HiLink veraCppSkip veraCppOut - HiLink veraCppOut2 veraCppOut - HiLink veraCppOut Comment - - delcommand HiLink -endif let b:current_syntax = "vera" diff --git a/runtime/syntax/verilog.vim b/runtime/syntax/verilog.vim index f4d21d0739..bbaca491a7 100644 --- a/runtime/syntax/verilog.vim +++ b/runtime/syntax/verilog.vim @@ -3,22 +3,15 @@ " Maintainer: Mun Johl <Mun.Johl@emulex.com> " Last Update: Wed Jul 20 16:04:19 PDT 2011 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif " Set the local value of the 'iskeyword' option. " NOTE: '?' was added so that verilogNumber would be processed correctly when " '?' is the last character of the number. -if version >= 600 - setlocal iskeyword=@,48-57,63,_,192-255 -else - set iskeyword=@,48-57,63,_,192-255 -endif +setlocal iskeyword=@,48-57,63,_,192-255 " A bunch of useful Verilog keywords @@ -102,34 +95,24 @@ syn region verilogDirective start="//\s*\$s dc_script_begin\>" end="//\s*\$s syn sync minlines=50 " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_verilog_syn_inits") - if version < 508 - let did_verilog_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - " The default highlighting. - HiLink verilogCharacter Character - HiLink verilogConditional Conditional - HiLink verilogRepeat Repeat - HiLink verilogString String - HiLink verilogTodo Todo - HiLink verilogComment Comment - HiLink verilogConstant Constant - HiLink verilogLabel Label - HiLink verilogNumber Number - HiLink verilogOperator Special - HiLink verilogStatement Statement - HiLink verilogGlobal Define - HiLink verilogDirective SpecialComment - HiLink verilogEscape Special - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +" The default highlighting. +hi def link verilogCharacter Character +hi def link verilogConditional Conditional +hi def link verilogRepeat Repeat +hi def link verilogString String +hi def link verilogTodo Todo +hi def link verilogComment Comment +hi def link verilogConstant Constant +hi def link verilogLabel Label +hi def link verilogNumber Number +hi def link verilogOperator Special +hi def link verilogStatement Statement +hi def link verilogGlobal Define +hi def link verilogDirective SpecialComment +hi def link verilogEscape Special + let b:current_syntax = "verilog" diff --git a/runtime/syntax/verilogams.vim b/runtime/syntax/verilogams.vim index d16e4bffb4..7551b681a8 100644 --- a/runtime/syntax/verilogams.vim +++ b/runtime/syntax/verilogams.vim @@ -9,20 +9,13 @@ " Minor reserved keyword updates. " Last Update: Thursday September 15 15:36:03 CST 2005 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif " Set the local value of the 'iskeyword' option -if version >= 600 - setlocal iskeyword=@,48-57,_,192-255 -else - set iskeyword=@,48-57,_,192-255 -endif +setlocal iskeyword=@,48-57,_,192-255 " Annex B.1 'All keywords' syn keyword verilogamsStatement above abs absdelay acos acosh ac_stim @@ -113,36 +106,26 @@ syn match verilogamsEscape "\\\o\o\=\o\=" contained syn sync lines=50 " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_verilogams_syn_inits") - if version < 508 - let did_verilogams_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - " The default highlighting. - HiLink verilogamsCharacter Character - HiLink verilogamsConditional Conditional - HiLink verilogamsRepeat Repeat - HiLink verilogamsString String - HiLink verilogamsTodo Todo - HiLink verilogamsComment Comment - HiLink verilogamsConstant Constant - HiLink verilogamsLabel Label - HiLink verilogamsNumber Number - HiLink verilogamsOperator Special - HiLink verilogamsStatement Statement - HiLink verilogamsGlobal Define - HiLink verilogamsDirective SpecialComment - HiLink verilogamsEscape Special - HiLink verilogamsType Type - HiLink verilogamsSystask Function +" The default highlighting. +hi def link verilogamsCharacter Character +hi def link verilogamsConditional Conditional +hi def link verilogamsRepeat Repeat +hi def link verilogamsString String +hi def link verilogamsTodo Todo +hi def link verilogamsComment Comment +hi def link verilogamsConstant Constant +hi def link verilogamsLabel Label +hi def link verilogamsNumber Number +hi def link verilogamsOperator Special +hi def link verilogamsStatement Statement +hi def link verilogamsGlobal Define +hi def link verilogamsDirective SpecialComment +hi def link verilogamsEscape Special +hi def link verilogamsType Type +hi def link verilogamsSystask Function - delcommand HiLink -endif let b:current_syntax = "verilogams" diff --git a/runtime/syntax/vhdl.vim b/runtime/syntax/vhdl.vim index 32503823ee..f4b11ff5dd 100644 --- a/runtime/syntax/vhdl.vim +++ b/runtime/syntax/vhdl.vim @@ -5,9 +5,8 @@ " Credits: Stephan Hegel <stephan.hegel@snc.siemens.com.cn> " Last Changed: 2016 Mar 05 by Daniel Kho -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -234,35 +233,25 @@ syn match vhdlPreProc "\(^\|\s\)--\s*synopsys\s\+translate_\(on\|off\)\s*" syn sync minlines=600 " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_vhdl_syntax_inits") - if version < 508 - let did_vhdl_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - 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 vhdlError Error - HiLink vhdlAttribute Special - HiLink vhdlPreProc PreProc - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link vhdlSpecial Special +hi def link vhdlStatement Statement +hi def link vhdlCharacter Character +hi def link vhdlString String +hi def link vhdlVector Number +hi def link vhdlBoolean Number +hi def link vhdlTodo Todo +hi def link vhdlFixme Fixme +hi def link vhdlComment Comment +hi def link vhdlNumber Number +hi def link vhdlTime Number +hi def link vhdlType Type +hi def link vhdlOperator Operator +hi def link vhdlError Error +hi def link vhdlAttribute Special +hi def link vhdlPreProc PreProc + let b:current_syntax = "vhdl" diff --git a/runtime/syntax/vim.vim b/runtime/syntax/vim.vim index 63618e902e..7025ee5369 100644 --- a/runtime/syntax/vim.vim +++ b/runtime/syntax/vim.vim @@ -21,7 +21,7 @@ syn keyword vimTodo contained COMBAK FIXME TODO XXX syn cluster vimCommentGroup contains=vimTodo,@Spell " Special and plugin vim commands {{{2 -syn match vimCommand contained "\<z[-+^.=]\=" +syn match vimCommand contained "\<z[-+^.=]\=\>" syn keyword vimOnlyCommand contained fix[del] op[en] sh[ell] P[rint] syn keyword vimStdPlugin contained DiffOrig Man N[ext] S TOhtml XMLent XMLns @@ -53,10 +53,10 @@ syn case ignore syn keyword vimGroup contained Comment Constant String Character Number Boolean Float Identifier Function Statement Conditional Repeat Label Operator Keyword Exception PreProc Include Define Macro PreCondit Type StorageClass Structure Typedef Special SpecialChar Tag Delimiter SpecialComment Debug Underlined Ignore Error Todo " Default highlighting groups {{{2 -syn keyword vimHLGroup contained ColorColumn Cursor CursorColumn CursorIM CursorLine CursorLineNr DiffAdd DiffChange DiffDelete DiffText Directory ErrorMsg FoldColumn Folded IncSearch LineNr MatchParen Menu ModeMsg MoreMsg NonText Normal Pmenu PmenuSbar PmenuSel PmenuThumb Question Scrollbar Search SignColumn SpecialKey SpellBad SpellCap SpellLocal SpellRare StatusLine StatusLineNC TabLine TabLineFill TabLineSel Title Tooltip VertSplit Visual WarningMsg WildMenu +syn keyword vimHLGroup contained ColorColumn Cursor CursorColumn CursorIM CursorLine CursorLineNr DiffAdd DiffChange DiffDelete DiffText Directory EndOfBuffer ErrorMsg FoldColumn Folded IncSearch LineNr MatchParen Menu ModeMsg MoreMsg NonText Normal Pmenu PmenuSbar PmenuSel PmenuThumb Question Scrollbar Search SignColumn SpecialKey SpellBad SpellCap SpellLocal SpellRare StatusLine StatusLineNC TabLine TabLineFill TabLineSel Title Tooltip VertSplit Visual WarningMsg WildMenu syn match vimHLGroup contained "Conceal" syn keyword vimOnlyHLGroup contained VisualNOS -syn keyword nvimHLGroup contained EndOfBuffer Substitute TermCursor TermCursorNC QuickFixLine +syn keyword nvimHLGroup contained Substitute TermCursor TermCursorNC QuickFixLine "}}}2 syn case match " Special Vim Highlighting (not automatic) {{{1 @@ -133,14 +133,15 @@ endif syn match vimNumber "\<\d\+\%(\.\d\+\%([eE][+-]\=\d\+\)\=\)\=" skipwhite nextgroup=vimGlobal,vimSubst,vimCommand syn match vimNumber "-\d\+\%(\.\d\+\%([eE][+-]\=\d\+\)\=\)\=" skipwhite nextgroup=vimGlobal,vimSubst,vimCommand syn match vimNumber "\<0[xX]\x\+" +syn match vimNumber "\<0[bB][01]\+" syn match vimNumber "\%(^\|[^a-zA-Z]\)\zs#\x\{6}" " All vimCommands are contained by vimIsCommands. {{{2 syn match vimCmdSep "[:|]\+" skipwhite nextgroup=vimAddress,vimAutoCmd,vimIsCommand,vimExtCmd,vimFilter,vimLet,vimMap,vimMark,vimSet,vimSyntax,vimUserCmd syn match vimIsCommand "\<\h\w*\>" contains=vimCommand syn match vimVar contained "\<\h[a-zA-Z0-9#_]*\>" -syn match vimVar "\<[bwglsav]:\h[a-zA-Z0-9#_]*\>" -syn match vimFBVar contained "\<[bwglsav]:\h[a-zA-Z0-9#_]*\>" +syn match vimVar "\<[bwglstav]:\h[a-zA-Z0-9#_]*\>" +syn match vimFBVar contained "\<[bwglstav]:\h[a-zA-Z0-9#_]*\>" syn keyword vimCommand contained in " Insertions And Appends: insert append {{{2 @@ -194,7 +195,7 @@ endif " Functions : Tag is provided for those who wish to highlight tagged functions {{{2 " ========= syn cluster vimFuncList contains=vimCommand,vimFunctionError,vimFuncKey,Tag,vimFuncSID -syn cluster vimFuncBodyList contains=vimAbb,vimAddress,vimAugroupKey,vimAutoCmd,vimCmplxRepeat,vimComment,vimComment,vimContinue,vimCtrlChar,vimEcho,vimEchoHL,vimExecute,vimIf,vimIsCommand,vimFBVar,vimFunc,vimFunction,vimFuncVar,vimGlobal,vimHighlight,vimIsCommand,vimLet,vimLineComment,vimMap,vimMark,vimNorm,vimNotation,vimNotFunc,vimNumber,vimOper,vimOperParen,vimRegion,vimRegister,vimSet,vimSpecFile,vimString,vimSubst,vimSynLine,vimUnmap,vimUserCommand,nvimUnmap,nvimMap +syn cluster vimFuncBodyList contains=vimAbb,vimAddress,vimAugroupKey,vimAutoCmd,vimCmplxRepeat,vimComment,vimContinue,vimCtrlChar,vimEcho,vimEchoHL,vimExecute,vimIf,vimIsCommand,vimFBVar,vimFunc,vimFunction,vimFuncVar,vimGlobal,vimHighlight,vimIsCommand,vimLet,vimLineComment,vimMap,vimMark,vimNorm,vimNotation,vimNotFunc,vimNumber,vimOper,vimOperParen,vimRegion,vimRegister,vimSet,vimSpecFile,vimString,vimSubst,vimSynLine,vimUnmap,vimUserCommand syn match vimFunction "\<fu\%[nction]!\=\s\+\%(<[sS][iI][dD]>\|[sSgGbBwWtTlL]:\)\=\%(\i\|[#.]\|{.\{-1,}}\)*\ze\s*(" contains=@vimFuncList nextgroup=vimFuncBody if exists("g:vimsyn_folding") && g:vimsyn_folding =~# 'f' @@ -238,7 +239,7 @@ if !exists("g:vimsyn_noerror") && !exists("g:vimsyn_nousercmderror") endif syn case ignore syn keyword vimUserAttrbKey contained bar ban[g] cou[nt] ra[nge] com[plete] n[args] re[gister] -syn keyword vimUserAttrbCmplt contained augroup buffer color command compiler cscope dir environment event expression file file_in_path filetype function help highlight locale mapping menu option shellcmd sign syntax tag tag_listfiles var +syn keyword vimUserAttrbCmplt contained augroup buffer behave color command compiler cscope dir environment event expression file file_in_path filetype function help highlight history locale mapping menu option packadd shellcmd sign syntax syntime tag tag_listfiles user var syn keyword vimUserAttrbCmplt contained custom customlist nextgroup=vimUserAttrbCmpltFunc,vimUserCmdError syn match vimUserAttrbCmpltFunc contained ",\%([sS]:\|<[sS][iI][dD]>\)\=\%(\h\w*\%(#\h\w*\)\+\|\h\w*\)"hs=s+1 nextgroup=vimUserCmdError @@ -390,7 +391,7 @@ syn match vimNotation "\(\\\|<lt>\)\=<\([scamd]-\)\{0,4}x\=\(f\d\{1,2}\|[^ \t:]\ syn match vimNotation "\(\\\|<lt>\)\=<\([scam2-4]-\)\{0,4}\(right\|left\|middle\)\(mouse\)\=\(drag\|release\)\=>" contains=vimBracket syn match vimNotation "\(\\\|<lt>\)\=<\(bslash\|plug\|sid\|space\|bar\|nop\|nul\|lt\)>" contains=vimBracket syn match vimNotation '\(\\\|<lt>\)\=<C-R>[0-9a-z"%#:.\-=]'he=e-1 contains=vimBracket -syn match vimNotation '\(\\\|<lt>\)\=<\%(q-\)\=\(line[12]\|count\|bang\|reg\|args\|f-args\|lt\)>' contains=vimBracket +syn match vimNotation '\(\\\|<lt>\)\=<\%(q-\)\=\(line[12]\|count\|bang\|reg\|args\|mods\|f-args\|f-mods\|lt\)>' contains=vimBracket syn match vimNotation "\(\\\|<lt>\)\=<\([cas]file\|abuf\|amatch\|cword\|cWORD\|client\)>" contains=vimBracket syn match vimBracket contained "[\\<>]" syn case match @@ -470,7 +471,7 @@ syn cluster vimFuncBodyList add=vimSynType syn cluster vimSynMtchGroup contains=vimMtchComment,vimSynContains,vimSynError,vimSynMtchOpt,vimSynNextgroup,vimSynRegPat,vimNotation syn keyword vimSynType contained match skipwhite nextgroup=vimSynMatchRegion syn region vimSynMatchRegion contained keepend matchgroup=vimGroupName start="\h\w*" matchgroup=vimSep end="|\|$" contains=@vimSynMtchGroup -syn match vimSynMtchOpt contained "\<\(conceal\|transparent\|contained\|excludenl\|skipempty\|skipwhite\|display\|extend\|skipnl\|fold\)\>" +syn match vimSynMtchOpt contained "\<\(conceal\|transparent\|contained\|excludenl\|keepend\|skipempty\|skipwhite\|display\|extend\|skipnl\|fold\)\>" if has("conceal") syn match vimSynMtchOpt contained "\<cchar=" nextgroup=vimSynMtchCchar syn match vimSynMtchCchar contained "\S" @@ -772,171 +773,169 @@ syn sync match vimAugroupSyncA groupthere NONE "\<aug\%[roup]\>\s\+[eE][nN][dD]" " Highlighting Settings {{{2 " ==================== -if !exists("g:vimsyn_noerror") - hi def link vimBehaveError vimError - hi def link vimCollClassErr vimError - hi def link vimErrSetting vimError - hi def link vimEmbedError vimError - hi def link vimFTError vimError - hi def link vimFunctionError vimError - hi def link vimFunc vimError - hi def link vimHiAttribList vimError - hi def link vimHiCtermError vimError - hi def link vimHiKeyError vimError - hi def link vimKeyCodeError vimError - hi def link vimMapModErr vimError - hi def link vimSubstFlagErr vimError - hi def link vimSynCaseError vimError - hi def link vimBufnrWarn vimWarn -endif - -hi def link vimAbb vimCommand -hi def link vimAddress vimMark -hi def link vimAugroupError vimError -hi def link vimAugroupKey vimCommand -hi def link vimAuHighlight vimHighlight -hi def link vimAutoCmdOpt vimOption -hi def link vimAutoCmd vimCommand -hi def link vimAutoEvent Type -hi def link nvimAutoEvent vimAutoEvent -hi def link vimAutoSet vimCommand -hi def link vimBehaveModel vimBehave -hi def link vimBehave vimCommand -hi def link vimBracket Delimiter -hi def link vimCmplxRepeat SpecialChar -hi def link vimCommand Statement -hi def link vimComment Comment -hi def link vimCommentString vimString -hi def link vimCommentTitle PreProc -hi def link vimCondHL vimCommand -hi def link vimContinue Special -hi def link vimCtrlChar SpecialChar -hi def link vimEchoHLNone vimGroup -hi def link vimEchoHL vimCommand -hi def link vimElseIfErr Error -hi def link vimElseif vimCondHL -hi def link vimEnvvar PreProc -hi def link vimError Error -hi def link vimFBVar vimVar -hi def link vimFgBgAttrib vimHiAttrib -hi def link vimFold Folded -hi def link vimFTCmd vimCommand -hi def link vimFTOption vimSynType -hi def link vimFuncKey vimCommand -hi def link vimFuncName Function -hi def link vimFuncSID Special -hi def link vimFuncVar Identifier -hi def link vimGroupAdd vimSynOption -hi def link vimGroupName vimGroup -hi def link vimGroupRem vimSynOption -hi def link vimGroupSpecial Special -hi def link vimGroup Type -hi def link vimHiAttrib PreProc -hi def link vimHiClear vimHighlight -hi def link vimHiCtermFgBg vimHiTerm -hi def link vimHiCTerm vimHiTerm -hi def link vimHighlight vimCommand -hi def link vimHiGroup vimGroupName -hi def link vimHiGuiFgBg vimHiTerm -hi def link vimHiGuiFont vimHiTerm -hi def link vimHiGuiRgb vimNumber -hi def link vimHiGui vimHiTerm -hi def link vimHiNmbr Number -hi def link vimHiStartStop vimHiTerm -hi def link vimHiTerm Type -hi def link vimHLGroup vimGroup -hi def link nvimHLGroup vimHLGroup -hi def link vimHLMod PreProc -hi def link vimInsert vimString -hi def link vimIskSep Delimiter -hi def link vimKeyCode vimSpecFile -hi def link vimKeyword Statement -hi def link vimLet vimCommand -hi def link vimLineComment vimComment -hi def link vimMapBang vimCommand -hi def link vimMapModKey vimFuncSID -hi def link vimMapMod vimBracket -hi def link vimMap vimCommand -hi def link nvimMap vimMap -hi def link vimMark Number -hi def link vimMarkNumber vimNumber -hi def link vimMenuMod vimMapMod -hi def link vimMenuNameMore vimMenuName -hi def link vimMenuName PreProc -hi def link vimMtchComment vimComment -hi def link vimNorm vimCommand -hi def link vimNotation Special -hi def link vimNotFunc vimCommand -hi def link vimNotPatSep vimString -hi def link vimNumber Number -hi def link vimOperError Error -hi def link vimOper Operator -hi def link vimOption PreProc -hi def link vimParenSep Delimiter -hi def link vimPatSepErr vimPatSep -hi def link vimPatSepR vimPatSep -hi def link vimPatSep SpecialChar -hi def link vimPatSepZone vimString -hi def link vimPatSepZ vimPatSep -hi def link vimPattern Type -hi def link vimPlainMark vimMark -hi def link vimPlainRegister vimRegister -hi def link vimRegister SpecialChar -hi def link vimScriptDelim Comment -hi def link vimSearchDelim Statement -hi def link vimSearch vimString -hi def link vimSep Delimiter -hi def link vimSetMod vimOption -hi def link vimSetSep Statement -hi def link vimSetString vimString -hi def link vimSpecFile Identifier -hi def link vimSpecFileMod vimSpecFile -hi def link vimSpecial Type -hi def link vimStatement Statement -hi def link vimStringCont vimString -hi def link vimString String -hi def link vimSubst1 vimSubst -hi def link vimSubstDelim Delimiter -hi def link vimSubstFlags Special -hi def link vimSubstSubstr SpecialChar -hi def link vimSubstTwoBS vimString -hi def link vimSubst vimCommand -hi def link vimSynCaseError Error -hi def link vimSynCase Type -hi def link vimSyncC Type -hi def link vimSyncError Error -hi def link vimSyncGroupName vimGroupName -hi def link vimSyncGroup vimGroupName -hi def link vimSyncKey Type -hi def link vimSyncNone Type -hi def link vimSynContains vimSynOption -hi def link vimSynError Error -hi def link vimSynKeyContainedin vimSynContains -hi def link vimSynKeyOpt vimSynOption -hi def link vimSynMtchGrp vimSynOption -hi def link vimSynMtchOpt vimSynOption -hi def link vimSynNextgroup vimSynOption -hi def link vimSynNotPatRange vimSynRegPat -hi def link vimSynOption Special -hi def link vimSynPatRange vimString -hi def link vimSynRegOpt vimSynOption -hi def link vimSynRegPat vimString -hi def link vimSynReg Type -hi def link vimSyntax vimCommand -hi def link vimSynType vimSpecial -hi def link vimTodo Todo -hi def link vimUnmap vimMap -hi def link nvimUnmap vimMap -hi def link vimUserAttrbCmpltFunc Special -hi def link vimUserAttrbCmplt vimSpecial -hi def link vimUserAttrbKey vimOption -hi def link vimUserAttrb vimSpecial -hi def link vimUserAttrbError Error -hi def link vimUserCmdError Error -hi def link vimUserCommand vimCommand -hi def link vimUserFunc Normal -hi def link vimVar Identifier -hi def link vimWarn WarningMsg +if !exists("skip_vim_syntax_inits") + if !exists("g:vimsyn_noerror") + hi def link vimBehaveError vimError + hi def link vimCollClassErr vimError + hi def link vimErrSetting vimError + hi def link vimEmbedError vimError + hi def link vimFTError vimError + hi def link vimFunctionError vimError + hi def link vimFunc vimError + hi def link vimHiAttribList vimError + hi def link vimHiCtermError vimError + hi def link vimHiKeyError vimError + hi def link vimKeyCodeError vimError + hi def link vimMapModErr vimError + hi def link vimSubstFlagErr vimError + hi def link vimSynCaseError vimError + hi def link vimBufnrWarn vimWarn + endif + + hi def link vimAbb vimCommand + hi def link vimAddress vimMark + hi def link vimAugroupError vimError + hi def link vimAugroupKey vimCommand + hi def link vimAuHighlight vimHighlight + hi def link vimAutoCmdOpt vimOption + hi def link vimAutoCmd vimCommand + hi def link vimAutoEvent Type + hi def link vimAutoSet vimCommand + hi def link vimBehaveModel vimBehave + hi def link vimBehave vimCommand + hi def link vimBracket Delimiter + hi def link vimCmplxRepeat SpecialChar + hi def link vimCommand Statement + hi def link vimComment Comment + hi def link vimCommentString vimString + hi def link vimCommentTitle PreProc + hi def link vimCondHL vimCommand + hi def link vimContinue Special + hi def link vimCtrlChar SpecialChar + hi def link vimEchoHLNone vimGroup + hi def link vimEchoHL vimCommand + hi def link vimElseIfErr Error + hi def link vimElseif vimCondHL + hi def link vimEnvvar PreProc + hi def link vimError Error + hi def link vimFBVar vimVar + hi def link vimFgBgAttrib vimHiAttrib + hi def link vimFold Folded + hi def link vimFTCmd vimCommand + hi def link vimFTOption vimSynType + hi def link vimFuncKey vimCommand + hi def link vimFuncName Function + hi def link vimFuncSID Special + hi def link vimFuncVar Identifier + hi def link vimGroupAdd vimSynOption + hi def link vimGroupName vimGroup + hi def link vimGroupRem vimSynOption + hi def link vimGroupSpecial Special + hi def link vimGroup Type + hi def link vimHiAttrib PreProc + hi def link vimHiClear vimHighlight + hi def link vimHiCtermFgBg vimHiTerm + hi def link vimHiCTerm vimHiTerm + hi def link vimHighlight vimCommand + hi def link vimHiGroup vimGroupName + hi def link vimHiGuiFgBg vimHiTerm + hi def link vimHiGuiFont vimHiTerm + hi def link vimHiGuiRgb vimNumber + hi def link vimHiGui vimHiTerm + hi def link vimHiNmbr Number + hi def link vimHiStartStop vimHiTerm + hi def link vimHiTerm Type + hi def link vimHLGroup vimGroup + hi def link vimHLMod PreProc + hi def link vimInsert vimString + hi def link vimIskSep Delimiter + hi def link vimKeyCode vimSpecFile + hi def link vimKeyword Statement + hi def link vimLet vimCommand + hi def link vimLineComment vimComment + hi def link vimMapBang vimCommand + hi def link vimMapModKey vimFuncSID + hi def link vimMapMod vimBracket + hi def link vimMap vimCommand + hi def link vimMark Number + hi def link vimMarkNumber vimNumber + hi def link vimMenuMod vimMapMod + hi def link vimMenuNameMore vimMenuName + hi def link vimMenuName PreProc + hi def link vimMtchComment vimComment + hi def link vimNorm vimCommand + hi def link vimNotation Special + hi def link vimNotFunc vimCommand + hi def link vimNotPatSep vimString + hi def link vimNumber Number + hi def link vimOperError Error + hi def link vimOper Operator + hi def link vimOption PreProc + hi def link vimParenSep Delimiter + hi def link vimPatSepErr vimPatSep + hi def link vimPatSepR vimPatSep + hi def link vimPatSep SpecialChar + hi def link vimPatSepZone vimString + hi def link vimPatSepZ vimPatSep + hi def link vimPattern Type + hi def link vimPlainMark vimMark + hi def link vimPlainRegister vimRegister + hi def link vimRegister SpecialChar + hi def link vimScriptDelim Comment + hi def link vimSearchDelim Statement + hi def link vimSearch vimString + hi def link vimSep Delimiter + hi def link vimSetMod vimOption + hi def link vimSetSep Statement + hi def link vimSetString vimString + hi def link vimSpecFile Identifier + hi def link vimSpecFileMod vimSpecFile + hi def link vimSpecial Type + hi def link vimStatement Statement + hi def link vimStringCont vimString + hi def link vimString String + hi def link vimSubst1 vimSubst + hi def link vimSubstDelim Delimiter + hi def link vimSubstFlags Special + hi def link vimSubstSubstr SpecialChar + hi def link vimSubstTwoBS vimString + hi def link vimSubst vimCommand + hi def link vimSynCaseError Error + hi def link vimSynCase Type + hi def link vimSyncC Type + hi def link vimSyncError Error + hi def link vimSyncGroupName vimGroupName + hi def link vimSyncGroup vimGroupName + hi def link vimSyncKey Type + hi def link vimSyncNone Type + hi def link vimSynContains vimSynOption + hi def link vimSynError Error + hi def link vimSynKeyContainedin vimSynContains + hi def link vimSynKeyOpt vimSynOption + hi def link vimSynMtchGrp vimSynOption + hi def link vimSynMtchOpt vimSynOption + hi def link vimSynNextgroup vimSynOption + hi def link vimSynNotPatRange vimSynRegPat + hi def link vimSynOption Special + hi def link vimSynPatRange vimString + hi def link vimSynRegOpt vimSynOption + hi def link vimSynRegPat vimString + hi def link vimSynReg Type + hi def link vimSyntax vimCommand + hi def link vimSynType vimSpecial + hi def link vimTodo Todo + hi def link vimUnmap vimMap + hi def link vimUserAttrbCmpltFunc Special + hi def link vimUserAttrbCmplt vimSpecial + hi def link vimUserAttrbKey vimOption + hi def link vimUserAttrb vimSpecial + hi def link vimUserAttrbError Error + hi def link vimUserCmdError Error + hi def link vimUserCommand vimCommand + hi def link vimUserFunc Normal + hi def link vimVar Identifier + hi def link vimWarn WarningMsg +endif " Current Syntax Variable: {{{2 let b:current_syntax = "vim" diff --git a/runtime/syntax/virata.vim b/runtime/syntax/virata.vim index e597b8e31c..0ed54fa899 100644 --- a/runtime/syntax/virata.vim +++ b/runtime/syntax/virata.vim @@ -13,10 +13,8 @@ " Setup Syntax: -if version < 600 - " Clear old syntax settings - syn clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif " Virata syntax is case insensitive (mostly) @@ -156,63 +154,53 @@ syn sync minlines=50 "for multiple region nesting " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later : only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_virata_syntax_inits") - if version < 508 - let did_virata_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - " Sub Links: - HiLink virataDefSubstError virataPreProcError - HiLink virataDefSubst virataPreProc - HiLink virataInAlter virataOperator - HiLink virataInExec virataOperator - HiLink virataInExport virataOperator - HiLink virataInImport virataOperator - HiLink virataInInstance virataOperator - HiLink virataInMake virataOperator - HiLink virataInModule virataOperator - HiLink virataInProcess virataOperator - HiLink virataInMacAddr virataHexNumber - - " Comment Group: - HiLink virataComment Comment - HiLink virataSpclComment SpecialComment - HiLink virataInCommentTodo Todo - - " Constant Group: - HiLink virataString String - HiLink virataStringError Error - HiLink virataCharacter Character - HiLink virataSpclChar Special - HiLink virataDecNumber Number - HiLink virataHexNumber Number - HiLink virataSizeNumber Number - HiLink virataNumberError Error - - " Identifier Group: - HiLink virataIdentError Error - - " PreProc Group: - HiLink virataPreProc PreProc - HiLink virataDefine Define - HiLink virataInclude Include - HiLink virataPreCondit PreCondit - HiLink virataPreProcError Error - HiLink virataPreProcWarn Todo - - " Directive Group: - HiLink virataStatement Statement - HiLink virataCfgStatement Statement - HiLink virataOperator Operator - HiLink virataDirective Keyword - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +" Sub Links: +hi def link virataDefSubstError virataPreProcError +hi def link virataDefSubst virataPreProc +hi def link virataInAlter virataOperator +hi def link virataInExec virataOperator +hi def link virataInExport virataOperator +hi def link virataInImport virataOperator +hi def link virataInInstance virataOperator +hi def link virataInMake virataOperator +hi def link virataInModule virataOperator +hi def link virataInProcess virataOperator +hi def link virataInMacAddr virataHexNumber + +" Comment Group: +hi def link virataComment Comment +hi def link virataSpclComment SpecialComment +hi def link virataInCommentTodo Todo + +" Constant Group: +hi def link virataString String +hi def link virataStringError Error +hi def link virataCharacter Character +hi def link virataSpclChar Special +hi def link virataDecNumber Number +hi def link virataHexNumber Number +hi def link virataSizeNumber Number +hi def link virataNumberError Error + +" Identifier Group: +hi def link virataIdentError Error + +" PreProc Group: +hi def link virataPreProc PreProc +hi def link virataDefine Define +hi def link virataInclude Include +hi def link virataPreCondit PreCondit +hi def link virataPreProcError Error +hi def link virataPreProcWarn Todo + +" Directive Group: +hi def link virataStatement Statement +hi def link virataCfgStatement Statement +hi def link virataOperator Operator +hi def link virataDirective Keyword + let b:current_syntax = "virata" diff --git a/runtime/syntax/vmasm.vim b/runtime/syntax/vmasm.vim index 85d0441258..c5cbb1e3a2 100644 --- a/runtime/syntax/vmasm.vim +++ b/runtime/syntax/vmasm.vim @@ -6,11 +6,8 @@ " This is incomplete. Feel free to contribute... " -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -196,55 +193,45 @@ syn match vmasmDirective "\.\(signed_\)\=word\>" syn case match " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_macro_syntax_inits") - if version < 508 - let did_macro_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - " The default methods for highlighting. Can be overridden later - " Comment Constant Error Identifier PreProc Special Statement Todo Type - " - " Constant Boolean Character Number String - " Identifier Function - " PreProc Define Include Macro PreCondit - " Special Debug Delimiter SpecialChar SpecialComment Tag - " Statement Conditional Exception Keyword Label Operator Repeat - " Type StorageClass Structure Typedef - - HiLink vmasmComment Comment - HiLink vmasmTodo Todo - - HiLink vmasmhexNumber Number " Constant - HiLink vmasmoctNumber Number " Constant - HiLink vmasmbinNumber Number " Constant - HiLink vmasmdecNumber Number " Constant - HiLink vmasmfloatNumber Number " Constant - -" HiLink vmasmString String " Constant - - HiLink vmasmReg Identifier - HiLink vmasmOperator Identifier - - HiLink vmasmInclude Include " PreProc - HiLink vmasmMacro Macro " PreProc - " HiLink vmasmMacroParam Keyword " Statement - - HiLink vmasmDirective Special - HiLink vmasmPreCond Special - - - HiLink vmasmOpcode Statement - HiLink vmasmCond Conditional " Statement - HiLink vmasmRepeat Repeat " Statement - - HiLink vmasmLabel Type - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +" The default methods for highlighting. Can be overridden later +" Comment Constant Error Identifier PreProc Special Statement Todo Type +" +" Constant Boolean Character Number String +" Identifier Function +" PreProc Define Include Macro PreCondit +" Special Debug Delimiter SpecialChar SpecialComment Tag +" Statement Conditional Exception Keyword Label Operator Repeat +" Type StorageClass Structure Typedef + +hi def link vmasmComment Comment +hi def link vmasmTodo Todo + +hi def link vmasmhexNumber Number " Constant +hi def link vmasmoctNumber Number " Constant +hi def link vmasmbinNumber Number " Constant +hi def link vmasmdecNumber Number " Constant +hi def link vmasmfloatNumber Number " Constant + +" hi def link vmasmString String " Constant + +hi def link vmasmReg Identifier +hi def link vmasmOperator Identifier + +hi def link vmasmInclude Include " PreProc +hi def link vmasmMacro Macro " PreProc +" hi def link vmasmMacroParam Keyword " Statement + +hi def link vmasmDirective Special +hi def link vmasmPreCond Special + + +hi def link vmasmOpcode Statement +hi def link vmasmCond Conditional " Statement +hi def link vmasmRepeat Repeat " Statement + +hi def link vmasmLabel Type let b:current_syntax = "vmasm" diff --git a/runtime/syntax/vrml.vim b/runtime/syntax/vrml.vim index 44814aad86..2474493c94 100644 --- a/runtime/syntax/vrml.vim +++ b/runtime/syntax/vrml.vim @@ -5,11 +5,8 @@ " Former Maintainer: Gregory Seidman <gsslist+vim@anthropohedron.net> " Last change: 2006 May 03 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -168,11 +165,9 @@ syn keyword VRMLProtos contained EXTERNPROTO PROTO IS syn keyword VRMLRoutes contained ROUTE TO -if version >= 502 "containment! - syn include @jscript $VIMRUNTIME/syntax/javascript.vim - syn region VRMLjScriptString contained start=+"\(\(javascript\)\|\(vrmlscript\)\|\(ecmascript\)\):+ms=e+1 skip=+\\\\\|\\"+ end=+"+me=e-1 contains=@jscript -endif +syn include @jscript $VIMRUNTIME/syntax/javascript.vim +syn region VRMLjScriptString contained start=+"\(\(javascript\)\|\(vrmlscript\)\|\(ecmascript\)\):+ms=e+1 skip=+\\\\\|\\"+ end=+"+me=e-1 contains=@jscript " match definitions. syn match VRMLSpecial contained "\\[0-9][0-9][0-9]\|\\." @@ -192,47 +187,35 @@ syn region VRMLInstName start="USE\>"hs=e+1 skip="USE\(,\|\s\)*" end="[A-Za-z syn keyword VRMLInstances contained DEF USE syn sync minlines=1 -if version >= 600 "FOLDS! - syn sync fromstart - "setlocal foldmethod=syntax - syn region braceFold start="{" end="}" transparent fold contains=TOP - syn region bracketFold start="\[" end="]" transparent fold contains=TOP - syn region VRMLString start=+"+ skip=+\\\\\|\\"+ end=+"+ fold contains=VRMLSpecial,VRMLjScriptString -endif +syn sync fromstart +"setlocal foldmethod=syntax +syn region braceFold start="{" end="}" transparent fold contains=TOP +syn region bracketFold start="\[" end="]" transparent fold contains=TOP +syn region VRMLString start=+"+ skip=+\\\\\|\\"+ end=+"+ fold contains=VRMLSpecial,VRMLjScriptString " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_VRML_syntax_inits") - if version < 508 - let did_VRML_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink VRMLCharacter VRMLString - HiLink VRMLSpecialCharacter VRMLSpecial - HiLink VRMLNumber VRMLString - HiLink VRMLValues VRMLString - HiLink VRMLString String - HiLink VRMLSpecial Special - HiLink VRMLComment Comment - HiLink VRMLNodes Statement - HiLink VRMLFields Type - HiLink VRMLEvents Type - HiLink VRMLfTypes LineNr +" Only when an item doesn't have highlighting yet + +hi def link VRMLCharacter VRMLString +hi def link VRMLSpecialCharacter VRMLSpecial +hi def link VRMLNumber VRMLString +hi def link VRMLValues VRMLString +hi def link VRMLString String +hi def link VRMLSpecial Special +hi def link VRMLComment Comment +hi def link VRMLNodes Statement +hi def link VRMLFields Type +hi def link VRMLEvents Type +hi def link VRMLfTypes LineNr " hi VRMLfTypes ctermfg=6 guifg=Brown - HiLink VRMLInstances PreCondit - HiLink VRMLRoutes PreCondit - HiLink VRMLProtos PreProc - HiLink VRMLRouteNode Identifier - HiLink VRMLInstName Identifier - HiLink VRMLTypes Identifier - - delcommand HiLink -endif +hi def link VRMLInstances PreCondit +hi def link VRMLRoutes PreCondit +hi def link VRMLProtos PreProc +hi def link VRMLRouteNode Identifier +hi def link VRMLInstName Identifier +hi def link VRMLTypes Identifier + let b:current_syntax = "vrml" diff --git a/runtime/syntax/vroom.vim b/runtime/syntax/vroom.vim index 0cd6ccce1d..0509e30b17 100644 --- a/runtime/syntax/vroom.vim +++ b/runtime/syntax/vroom.vim @@ -3,11 +3,8 @@ " Maintainer: David Barnett (https://github.com/google/vim-ft-vroom) " Last Change: 2014 Jul 23 -" For version 5.x: Clear all syntax items. -" For version 6.x and later: Quit when a syntax file was already loaded. -if v:version < 600 - syntax clear -elseif exists('b:current_syntax') +" quit when a syntax file was already loaded +if exists('b:current_syntax') finish endif diff --git a/runtime/syntax/vsejcl.vim b/runtime/syntax/vsejcl.vim index f4f00c65ea..f329836236 100644 --- a/runtime/syntax/vsejcl.vim +++ b/runtime/syntax/vsejcl.vim @@ -4,11 +4,8 @@ " URL: " Last change: 2001 May 10 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -23,26 +20,16 @@ syn match vsejclString /'.\{-}'/ syn match vsejclParms /(.\{-})/ contained " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_vsejcl_syntax") - if version < 508 - let did_vsejcl_syntax = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink vsejclComment Comment - HiLink vsejclField Type - HiLink vsejclKeyword Statement - HiLink vsejclObject Constant - HiLink vsejclString Constant - HiLink vsejclMisc Special - HiLink vsejclParms Constant +hi def link vsejclComment Comment +hi def link vsejclField Type +hi def link vsejclKeyword Statement +hi def link vsejclObject Constant +hi def link vsejclString Constant +hi def link vsejclMisc Special +hi def link vsejclParms Constant - delcommand HiLink -endif let b:current_syntax = "vsejcl" diff --git a/runtime/syntax/wdiff.vim b/runtime/syntax/wdiff.vim index 9cd0611819..d0afadff2f 100644 --- a/runtime/syntax/wdiff.vim +++ b/runtime/syntax/wdiff.vim @@ -9,11 +9,8 @@ " SPAM is _NOT_ welcome - be ready to be reported! -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syn clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -23,21 +20,10 @@ syn region wdiffNew start="{+" end="+}" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_wdiff_syn_inits") - let did_wdiff_syn_inits = 1 - if version < 508 - let did_wdiff_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink wdiffOld Special - HiLink wdiffNew Identifier - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link wdiffOld Special +hi def link wdiffNew Identifier + let b:current_syntax = "wdiff" diff --git a/runtime/syntax/web.vim b/runtime/syntax/web.vim index f7a7fdfdc2..54eebda399 100644 --- a/runtime/syntax/web.vim +++ b/runtime/syntax/web.vim @@ -8,11 +8,8 @@ " the standard WEB distribution, available for anonymous ftp at " ftp://labrea.stanford.edu/pub/tex/web/. -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -20,12 +17,8 @@ endif " we base this syntax file on the modern superset, CWEB. Note: This shortcut " may introduce some illegal constructs, e.g., CWEB's "@c" does _not_ start a " code section in WEB. Anyway, I'm not a WEB programmer. -if version < 600 - source <sfile>:p:h/cweb.vim -else - runtime! syntax/cweb.vim - unlet b:current_syntax -endif +runtime! syntax/cweb.vim +unlet b:current_syntax " Replace C/C++ syntax by Pascal syntax. syntax include @webIncludedC <sfile>:p:h/pascal.vim diff --git a/runtime/syntax/webmacro.vim b/runtime/syntax/webmacro.vim index 3b863f7c37..fb1fff6d3d 100644 --- a/runtime/syntax/webmacro.vim +++ b/runtime/syntax/webmacro.vim @@ -11,21 +11,16 @@ " For version 5.x: Clear all syntax items " For version 6.x: Quit when a syntax file was already loaded if !exists("main_syntax") - if version < 600 - syntax clear - elseif exists("b:current_syntax") + " quit when a syntax file was already loaded + if exists("b:current_syntax") finish endif let main_syntax = 'webmacro' endif -if version < 600 - source <sfile>:p:h/html.vim -else - runtime! syntax/html.vim - unlet b:current_syntax -endif +runtime! syntax/html.vim +unlet b:current_syntax syn cluster htmlPreProc add=webmacroIf,webmacroUse,webmacroBraces,webmacroParse,webmacroInclude,webmacroSet,webmacroForeach,webmacroComment @@ -49,31 +44,21 @@ syn match webmacroComment "##.*$" syn match webmacroHash "[#{}\$]" contained " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_webmacro_syn_inits") - if version < 508 - let did_webmacro_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink webmacroComment CommentTitle - HiLink webmacroVariable PreProc - HiLink webmacroIf webmacroStatement - HiLink webmacroForeach webmacroStatement - HiLink webmacroSet webmacroStatement - HiLink webmacroInclude webmacroStatement - HiLink webmacroParse webmacroStatement - HiLink webmacroStatement Function - HiLink webmacroNumber Number - HiLink webmacroBoolean Boolean - HiLink webmacroSpecial Special - HiLink webmacroString String - HiLink webmacroBracesError Error - delcommand HiLink -endif +hi def link webmacroComment CommentTitle +hi def link webmacroVariable PreProc +hi def link webmacroIf webmacroStatement +hi def link webmacroForeach webmacroStatement +hi def link webmacroSet webmacroStatement +hi def link webmacroInclude webmacroStatement +hi def link webmacroParse webmacroStatement +hi def link webmacroStatement Function +hi def link webmacroNumber Number +hi def link webmacroBoolean Boolean +hi def link webmacroSpecial Special +hi def link webmacroString String +hi def link webmacroBracesError Error let b:current_syntax = "webmacro" diff --git a/runtime/syntax/winbatch.vim b/runtime/syntax/winbatch.vim index aea2cdebcb..15ea0fc77b 100644 --- a/runtime/syntax/winbatch.vim +++ b/runtime/syntax/winbatch.vim @@ -4,11 +4,8 @@ " URL: http://www.mggen.com/vim/syntax/winbatch.zip " Last change: 2001 May 10 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -158,29 +155,19 @@ syn keyword winbatchImplicit xgetchildhwnd xgetelapsed xhex xmemcompact xmessage syn keyword winbatchImplicit xsendmessage xverifyccard yield " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_winbatch_syntax_inits") - if version < 508 - let did_winbatch_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink winbatchLabel PreProc - HiLink winbatchCtl Operator - HiLink winbatchStatement Statement - HiLink winbatchTodo Todo - HiLink winbatchString String - HiLink winbatchVar Type - HiLink winbatchComment Comment - HiLink winbatchImplicit Special - HiLink winbatchNumber Number - HiLink winbatchConstant StorageClass +hi def link winbatchLabel PreProc +hi def link winbatchCtl Operator +hi def link winbatchStatement Statement +hi def link winbatchTodo Todo +hi def link winbatchString String +hi def link winbatchVar Type +hi def link winbatchComment Comment +hi def link winbatchImplicit Special +hi def link winbatchNumber Number +hi def link winbatchConstant StorageClass - delcommand HiLink -endif let b:current_syntax = "winbatch" diff --git a/runtime/syntax/wml.vim b/runtime/syntax/wml.vim index 5957930c8e..73bf822e40 100644 --- a/runtime/syntax/wml.vim +++ b/runtime/syntax/wml.vim @@ -16,21 +16,14 @@ " vim-package around your corner :) -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syn clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif " A lot of the web stuff looks like HTML so we load that first -if version < 600 - so <sfile>:p:h/html.vim -else - runtime! syntax/html.vim -endif +runtime! syntax/html.vim unlet b:current_syntax if !exists("main_syntax") @@ -108,11 +101,7 @@ syn region htmlTagName start="\<\(define-tag\|define-region\)" end="\>" cont " The perl include stuff if main_syntax != 'perl' " Perl script - if version < 600 - syn include @wmlPerlScript <sfile>:p:h/perl.vim - else - syn include @wmlPerlScript syntax/perl.vim - endif + syn include @wmlPerlScript syntax/perl.vim unlet b:current_syntax syn region perlScript start=+<perl>+ keepend end=+</perl>+ contains=@wmlPerlScript,wmlPerlTag @@ -140,33 +129,22 @@ if main_syntax == "html" endif " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_wml_syn_inits") - let did_wml_syn_inits = 1 - if version < 508 - let did_wml_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink wmlNextLine Special - HiLink wmlUse Include - HiLink wmlUsed String - HiLink wmlBody Special - HiLink wmlDiverted Label - HiLink wmlDivert Delimiter - HiLink wmlDivertEnd Delimiter - HiLink wmlLocationId Label - HiLink wmlLocation Delimiter -" HiLink wmlLocationed Delimiter - HiLink wmlDefineName String - HiLink wmlComment Comment - HiLink wmlInclude Include - HiLink wmlSharpBang PreProc - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link wmlNextLine Special +hi def link wmlUse Include +hi def link wmlUsed String +hi def link wmlBody Special +hi def link wmlDiverted Label +hi def link wmlDivert Delimiter +hi def link wmlDivertEnd Delimiter +hi def link wmlLocationId Label +hi def link wmlLocation Delimiter +" hi def link wmlLocationed Delimiter +hi def link wmlDefineName String +hi def link wmlComment Comment +hi def link wmlInclude Include +hi def link wmlSharpBang PreProc + let b:current_syntax = "wml" diff --git a/runtime/syntax/wsml.vim b/runtime/syntax/wsml.vim index 2a92a0d548..d01294caac 100644 --- a/runtime/syntax/wsml.vim +++ b/runtime/syntax/wsml.vim @@ -4,10 +4,8 @@ " URL: none " Last Change: 2006 Apr 30 -" Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -78,47 +76,37 @@ syn match wsmlSpecial "\\u\d\{4\}" syn cluster wsmlTop add=wsmlString,wsmlCharacter,wsmlNumber,wsmlSpecial,wsmlStringError " Define the default highlighting. -" " For version 5.7 and earlier: only when not done already -" " For version 5.8 and later: only when an item doesn't have highlighting yet - if version >= 508 || !exists("did_wsml_syn_inits") - if version < 508 - let did_wsml_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - HiLink wsmlHeader TypeDef - HiLink wsmlNamespace TypeDef - HiLink wsmlOntology Statement - HiLink wsmlAxiom TypeDef - HiLink wsmlService TypeDef - HiLink wsmlNFP TypeDef - HiLink wsmlTopLevel TypeDef - HiLink wsmlMediation TypeDef - HiLink wsmlBehavioral TypeDef - HiLink wsmlChoreographyPri TypeDef - HiLink wsmlChoreographySec Operator - HiLink wsmlChoreographyTer Special - HiLink wsmlString String - HiLink wsmlIdentifier Normal - HiLink wsmlSqName Normal - HiLink wsmlVariable Define - HiLink wsmlKeywordsInsideLEs Operator - HiLink wsmlOperator Operator - HiLink wsmlBrace Operator - HiLink wsmlCharacter Character - HiLink wsmlNumber Number - HiLink wsmlDataTypes Special - HiLink wsmlComment Comment - HiLink wsmlDocComment Comment - HiLink wsmlLineComment Comment - HiLink wsmlTodo Todo - HiLink wsmlFixMe Error - HiLink wsmlCommentTitle SpecialComment - HiLink wsmlCommentStar wsmlComment - endif +" Only when an item doesn't have highlighting yet +hi def link wsmlHeader TypeDef +hi def link wsmlNamespace TypeDef +hi def link wsmlOntology Statement +hi def link wsmlAxiom TypeDef +hi def link wsmlService TypeDef +hi def link wsmlNFP TypeDef +hi def link wsmlTopLevel TypeDef +hi def link wsmlMediation TypeDef +hi def link wsmlBehavioral TypeDef +hi def link wsmlChoreographyPri TypeDef +hi def link wsmlChoreographySec Operator +hi def link wsmlChoreographyTer Special +hi def link wsmlString String +hi def link wsmlIdentifier Normal +hi def link wsmlSqName Normal +hi def link wsmlVariable Define +hi def link wsmlKeywordsInsideLEs Operator +hi def link wsmlOperator Operator +hi def link wsmlBrace Operator +hi def link wsmlCharacter Character +hi def link wsmlNumber Number +hi def link wsmlDataTypes Special +hi def link wsmlComment Comment +hi def link wsmlDocComment Comment +hi def link wsmlLineComment Comment +hi def link wsmlTodo Todo +hi def link wsmlFixMe Error +hi def link wsmlCommentTitle SpecialComment +hi def link wsmlCommentStar wsmlComment -delcommand HiLink let b:current_syntax = "wsml" let b:spell_options="contained" diff --git a/runtime/syntax/xdefaults.vim b/runtime/syntax/xdefaults.vim index 5e38952a75..7da5969cde 100644 --- a/runtime/syntax/xdefaults.vim +++ b/runtime/syntax/xdefaults.vim @@ -10,11 +10,8 @@ " xrdb manual page " xrdb source: ftp://ftp.x.org/pub/R6.4/xc/programs/xrdb/xrdb.c -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -109,36 +106,26 @@ syn keyword xdefaultsSymbol contained X_RESOLUTION syn keyword xdefaultsSymbol contained Y_RESOLUTION " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_xdefaults_syntax_inits") - if version < 508 - let did_xdefaults_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - HiLink xdefaultsLabel Type - HiLink xdefaultsValue Constant - HiLink xdefaultsComment Comment - HiLink xdefaultsCommentH xdefaultsComment - HiLink xdefaultsPreProc PreProc - HiLink xdefaultsInclude xdefaultsPreProc - HiLink xdefaultsCppSkip xdefaultsCppOut - HiLink xdefaultsCppOut2 xdefaultsCppOut - HiLink xdefaultsCppOut Comment - HiLink xdefaultsIncluded String - HiLink xdefaultsDefine Macro - HiLink xdefaultsSymbol Statement - HiLink xdefaultsSpecial Statement - HiLink xdefaultsErrorLine Error - HiLink xdefaultsCommentError Error - HiLink xdefaultsPunct Normal - HiLink xdefaultsLineEnd Special - HiLink xdefaultsTodo Todo - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet +hi def link xdefaultsLabel Type +hi def link xdefaultsValue Constant +hi def link xdefaultsComment Comment +hi def link xdefaultsCommentH xdefaultsComment +hi def link xdefaultsPreProc PreProc +hi def link xdefaultsInclude xdefaultsPreProc +hi def link xdefaultsCppSkip xdefaultsCppOut +hi def link xdefaultsCppOut2 xdefaultsCppOut +hi def link xdefaultsCppOut Comment +hi def link xdefaultsIncluded String +hi def link xdefaultsDefine Macro +hi def link xdefaultsSymbol Statement +hi def link xdefaultsSpecial Statement +hi def link xdefaultsErrorLine Error +hi def link xdefaultsCommentError Error +hi def link xdefaultsPunct Normal +hi def link xdefaultsLineEnd Special +hi def link xdefaultsTodo Todo + let b:current_syntax = "xdefaults" diff --git a/runtime/syntax/xf86conf.vim b/runtime/syntax/xf86conf.vim index 62784d2285..545eda7db0 100644 --- a/runtime/syntax/xf86conf.vim +++ b/runtime/syntax/xf86conf.vim @@ -10,12 +10,8 @@ " to force XFree86 3.x or 4.x XF86Config syntax " Setup -if version >= 600 - if exists("b:current_syntax") - finish - endif -else - echo "Sorry, but this syntax file relies on Vim 6 features. Either upgrade Vim or usea version of " . expand("<sfile>:t:r") . " syntax file appropriate for Vim " . version/100 . "." . version %100 . "." +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif diff --git a/runtime/syntax/xkb.vim b/runtime/syntax/xkb.vim index ff9bfd0dae..59fc497e62 100644 --- a/runtime/syntax/xkb.vim +++ b/runtime/syntax/xkb.vim @@ -6,12 +6,9 @@ " URL: http://trific.ath.cx/Ftp/vim/syntax/xkb.vim " Setup -if version >= 600 - if exists("b:current_syntax") - finish - endif -else - syntax clear +" quit when a syntax file was already loaded +if exists("b:current_syntax") + finish endif syn case match @@ -50,42 +47,33 @@ syn keyword xkbTModif default hidden partial virtual syn keyword xkbSect alphanumeric_keys alternate_group function_keys keypad_keys modifier_keys xkb_compatibility xkb_geometry xkb_keycodes xkb_keymap xkb_semantics xkb_symbols xkb_types " Define the default highlighting -if version >= 508 || !exists("did_xkb_syntax_inits") - if version < 508 - let did_xkb_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink xkbModif xkbPreproc - HiLink xkbTModif xkbPreproc - HiLink xkbPreproc Preproc - - HiLink xkbIdentifier Keyword - HiLink xkbFunction Function - HiLink xkbSect Type - HiLink xkbPhysicalKey Identifier - HiLink xkbKeyword Keyword - - HiLink xkbComment Comment - HiLink xkbTodo Todo - - HiLink xkbConstant Constant - HiLink xkbString String - - HiLink xkbSpecialChar xkbSpecial - HiLink xkbSpecial Special - - HiLink xkbParenError xkbBalancingError - HiLink xkbBraceError xkbBalancingError - HiLink xkbBraketError xkbBalancingError - HiLink xkbBalancingError xkbError - HiLink xkbCommentStartError xkbCommentError - HiLink xkbCommentError xkbError - HiLink xkbError Error - - delcommand HiLink -endif + +hi def link xkbModif xkbPreproc +hi def link xkbTModif xkbPreproc +hi def link xkbPreproc Preproc + +hi def link xkbIdentifier Keyword +hi def link xkbFunction Function +hi def link xkbSect Type +hi def link xkbPhysicalKey Identifier +hi def link xkbKeyword Keyword + +hi def link xkbComment Comment +hi def link xkbTodo Todo + +hi def link xkbConstant Constant +hi def link xkbString String + +hi def link xkbSpecialChar xkbSpecial +hi def link xkbSpecial Special + +hi def link xkbParenError xkbBalancingError +hi def link xkbBraceError xkbBalancingError +hi def link xkbBraketError xkbBalancingError +hi def link xkbBalancingError xkbError +hi def link xkbCommentStartError xkbCommentError +hi def link xkbCommentError xkbError +hi def link xkbError Error + let b:current_syntax = "xkb" diff --git a/runtime/syntax/xmath.vim b/runtime/syntax/xmath.vim index 5434f928c7..22b3e85dae 100644 --- a/runtime/syntax/xmath.vim +++ b/runtime/syntax/xmath.vim @@ -1,15 +1,13 @@ " Vim syntax file " Language: xmath (a simulation tool) " Maintainer: Charles E. Campbell <NdrOchipS@PcampbellAfamily.Mbiz> -" Last Change: Sep 11, 2006 -" Version: 7 +" Last Change: Aug 31, 2016 +" Version: 9 " URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_XMATH " For version 5.x: Clear all syntax items " For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +if exists("b:current_syntax") finish endif @@ -194,41 +192,32 @@ syn sync match xmathSyncComment grouphere xmathCommentBlock "#{" syn sync match xmathSyncComment groupthere NONE "}#" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_xmath_syntax_inits") - if version < 508 - let did_xmath_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink xmathBraceError xmathError - HiLink xmathCmd xmathStatement - HiLink xmathCommentBlock xmathComment - HiLink xmathCurlyError xmathError - HiLink xmathFuncCmd xmathStatement - HiLink xmathParenError xmathError +if !exists("skip_xmath_syntax_inits") + + hi def link xmathBraceError xmathError + hi def link xmathCmd xmathStatement + hi def link xmathCommentBlock xmathComment + hi def link xmathCurlyError xmathError + hi def link xmathFuncCmd xmathStatement + hi def link xmathParenError xmathError " The default methods for highlighting. Can be overridden later - HiLink xmathCharacter Character - HiLink xmathComma Delimiter - HiLink xmathComment Comment - HiLink xmathCommentBlock Comment - HiLink xmathConditional Conditional - HiLink xmathError Error - HiLink xmathFunc Function - HiLink xmathLabel PreProc - HiLink xmathNumber Number - HiLink xmathRepeat Repeat - HiLink xmathSpecial Type - HiLink xmathSpecialChar SpecialChar - HiLink xmathStatement Statement - HiLink xmathString String - HiLink xmathTodo Todo - - delcommand HiLink + hi def link xmathCharacter Character + hi def link xmathComma Delimiter + hi def link xmathComment Comment + hi def link xmathCommentBlock Comment + hi def link xmathConditional Conditional + hi def link xmathError Error + hi def link xmathFunc Function + hi def link xmathLabel PreProc + hi def link xmathNumber Number + hi def link xmathRepeat Repeat + hi def link xmathSpecial Type + hi def link xmathSpecialChar SpecialChar + hi def link xmathStatement Statement + hi def link xmathString String + hi def link xmathTodo Todo + endif let b:current_syntax = "xmath" diff --git a/runtime/syntax/xpm.vim b/runtime/syntax/xpm.vim index 3cbc1b54fd..0667ca28ad 100644 --- a/runtime/syntax/xpm.vim +++ b/runtime/syntax/xpm.vim @@ -1,14 +1,12 @@ " Vim syntax file " Language: X Pixmap " Maintainer: Ronald Schild <rs@scutum.de> -" Last Change: 2008 May 28 +" Last Change: 2017 Feb 01 " Version: 5.4n.1 +" Jemma Nelson added termguicolors support -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -18,7 +16,7 @@ syn keyword xpmTodo TODO FIXME XXX contained syn region xpmComment start="/\*" end="\*/" contains=xpmTodo syn region xpmPixelString start=+"+ skip=+\\\\\|\\"+ end=+"+ contains=@xpmColors -if has("gui_running") +if has("gui_running") || has("termguicolors") && &termguicolors let color = "" let chars = "" @@ -123,27 +121,17 @@ endwhile unlet color chars colors cpp n i s -endif " has("gui_running") +endif " has("gui_running") || has("termguicolors") && &termguicolors " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_xpm_syntax_inits") - if version < 508 - let did_xpm_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink xpmType Type - HiLink xpmStorageClass StorageClass - HiLink xpmTodo Todo - HiLink xpmComment Comment - HiLink xpmPixelString String - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link xpmType Type +hi def link xpmStorageClass StorageClass +hi def link xpmTodo Todo +hi def link xpmComment Comment +hi def link xpmPixelString String + let b:current_syntax = "xpm" diff --git a/runtime/syntax/xpm2.vim b/runtime/syntax/xpm2.vim index 74b3c66af2..dfa6945a31 100644 --- a/runtime/syntax/xpm2.vim +++ b/runtime/syntax/xpm2.vim @@ -1,17 +1,15 @@ " Vim syntax file " Language: X Pixmap v2 " Maintainer: Steve Wall (hitched97@velnet.com) -" Last Change: 2012 Jun 01 +" Last Change: 2017 Feb 01 " (Dominique Pelle added @Spell) " Version: 5.8 +" Jemma Nelson added termguicolors support " " Made from xpm.vim by Ronald Schild <rs@scutum.de> -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -23,15 +21,9 @@ syn keyword xpm2Todo TODO FIXME XXX contained syn match xpm2Comment "\!.*$" contains=@Spell,xpm2Todo -if version < 508 - command -nargs=+ HiLink hi link <args> - command -nargs=+ Hi hi <args> -else - command -nargs=+ HiLink hi def link <args> - command -nargs=+ Hi hi def <args> -endif +command -nargs=+ Hi hi def <args> -if has("gui_running") +if has("gui_running") || has("termguicolors") && &termguicolors let color = "" let chars = "" @@ -63,7 +55,7 @@ if has("gui_running") if s !~ '/' exe 'syn match xpm2Values /' . s . '/' endif - HiLink xpm2Values Statement + hi def link xpm2Values Statement let n = 1 " n = color index @@ -112,11 +104,11 @@ if has("gui_running") " now create syntax items " highlight the color string as normal string (no pixel string) exe 'syn match xpm2Col'.n.'Def /'.s.'/ contains=xpm2Col'.n.'inDef' - exe 'HiLink xpm2Col'.n.'Def Constant' + exe 'hi def link xpm2Col'.n.'Def Constant' " but highlight the first whitespace after chars in its color exe 'syn match xpm2Col'.n.'inDef /^'.chars.'/hs=s+'.(cpp).' contained' - exe 'HiLink xpm2Col'.n.'inDef xpm2Color'.n + exe 'hi def link xpm2Col'.n.'inDef xpm2Color'.n " remove the following whitespace from chars let chars = substitute(chars, '\\s\\+$', '', '') @@ -141,24 +133,17 @@ if has("gui_running") unlet color chars colors cpp n i s -endif " has("gui_running") +endif " has("gui_running") || has("termguicolors") && &termguicolors " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_xpm2_syntax_inits") - if version < 508 - let did_xpm2_syntax_inits = 1 - endif - - " The default highlighting. - HiLink xpm2Type Type - HiLink xpm2StorageClass StorageClass - HiLink xpm2Todo Todo - HiLink xpm2Comment Comment - HiLink xpm2PixelString String -endif -delcommand HiLink +" Only when an item doesn't have highlighting yet +" The default highlighting. +hi def link xpm2Type Type +hi def link xpm2StorageClass StorageClass +hi def link xpm2Todo Todo +hi def link xpm2Comment Comment +hi def link xpm2PixelString String + delcommand Hi let b:current_syntax = "xpm2" diff --git a/runtime/syntax/xs.vim b/runtime/syntax/xs.vim index 6fd0a468f9..d4ac9d1bc7 100644 --- a/runtime/syntax/xs.vim +++ b/runtime/syntax/xs.vim @@ -5,20 +5,13 @@ " Previous: Vincent Pit <perl@profvince.com> " Last Change: 2013-05-12 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif " Read the C syntax to start with -if version < 600 - source <sfile>:p:h/c.vim -else - runtime! syntax/c.vim -endif +runtime! syntax/c.vim let xs_superseded = 1 " mark C functions superseded by Perl replacements let xs_not_core = 1 " mark private core functions @@ -3249,29 +3242,19 @@ syn keyword xsMacro what_len_TRICKYFOLD_safe whichsig write xio_any xio_dirp syn keyword xsMacro xiv_iv xuv_uv yystype " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_xs_syntax_inits") - if version < 508 - let did_xs_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +" Only when an item doesn't have highlighting yet - HiLink xsPrivate Error - HiLink xsSuperseded Error - HiLink xsType Type - HiLink xsString String - HiLink xsConstant Constant - HiLink xsException Exception - HiLink xsKeyword Keyword - HiLink xsFunction Function - HiLink xsVariable Identifier - HiLink xsMacro Macro +hi def link xsPrivate Error +hi def link xsSuperseded Error +hi def link xsType Type +hi def link xsString String +hi def link xsConstant Constant +hi def link xsException Exception +hi def link xsKeyword Keyword +hi def link xsFunction Function +hi def link xsVariable Identifier +hi def link xsMacro Macro - delcommand HiLink -endif let b:current_syntax = "xs" diff --git a/runtime/syntax/xxd.vim b/runtime/syntax/xxd.vim index b2b1e44603..f3c43e816c 100644 --- a/runtime/syntax/xxd.vim +++ b/runtime/syntax/xxd.vim @@ -1,16 +1,13 @@ " Vim syntax file " Language: bin using xxd " Maintainer: Charles E. Campbell <NdrOchipS@PcampbellAfamily.Mbiz> -" Last Change: Oct 23, 2014 -" Version: 8 +" Last Change: Aug 31, 2016 +" Version: 10 " Notes: use :help xxd to see how to invoke it " URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_XXD -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -20,21 +17,12 @@ syn match xxdAscii " .\{,16\}\r\=$"hs=s+2 contains=xxdDot syn match xxdDot contained "[.\r]" " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_xxd_syntax_inits") - if version < 508 - let did_xxd_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif +if !exists("skip_xxd_syntax_inits") - HiLink xxdAddress Constant - HiLink xxdSep Identifier - HiLink xxdAscii Statement + hi def link xxdAddress Constant + hi def link xxdSep Identifier + hi def link xxdAscii Statement - delcommand HiLink endif let b:current_syntax = "xxd" diff --git a/runtime/syntax/yacc.vim b/runtime/syntax/yacc.vim index 977ffa75e4..8d5eb13071 100644 --- a/runtime/syntax/yacc.vim +++ b/runtime/syntax/yacc.vim @@ -1,18 +1,15 @@ " Vim syntax file " Language: Yacc " Maintainer: Charles E. Campbell <NdrOchipS@PcampbellAfamily.Mbiz> -" Last Change: Apr 02, 2015 -" Version: 13 -" URL: http://mysite.verizon.net/astronaut/vim/index.html#vimlinks_syntax +" Last Change: Aug 31, 2016 +" Version: 15 +" URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_YACC " " Options: {{{1 " g:yacc_uses_cpp : if this variable exists, then C++ is loaded rather than C " --------------------------------------------------------------------- " this version of syntax/yacc.vim requires 6.0 or later -if version < 600 - finish -endif if exists("b:current_syntax") syntax clear endif @@ -90,7 +87,7 @@ syn sync fromstart " --------------------------------------------------------------------- " Define the default highlighting. {{{1 -if !exists("did_yacc_syn_inits") +if !exists("skip_yacc_syn_inits") hi def link yaccBrkt yaccStmt hi def link yaccComment Comment hi def link yaccCurly Delimiter diff --git a/runtime/syntax/z8a.vim b/runtime/syntax/z8a.vim index a3a8a2bbdf..6809eb98cd 100644 --- a/runtime/syntax/z8a.vim +++ b/runtime/syntax/z8a.vim @@ -3,11 +3,8 @@ " Maintainer: Milan Pikula <www@fornax.elf.stuba.sk> " Last Change: 2003 May 11 -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") +" quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -85,30 +82,20 @@ syn match z8aComment ";.*" syn case match " Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_z8a_syntax_inits") - if version < 508 - let did_z8a_syntax_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink z8aSection Special - HiLink z8aLabel Label - HiLink z8aSpecialLabel Label - HiLink z8aComment Comment - HiLink z8aInstruction Statement - HiLink z8aSpecInst Statement - HiLink z8aInclude Include - HiLink z8aPreCondit PreCondit - HiLink z8aPreProc PreProc - HiLink z8aNumber Number - HiLink z8aString String - - delcommand HiLink -endif +" Only when an item doesn't have highlighting yet + +hi def link z8aSection Special +hi def link z8aLabel Label +hi def link z8aSpecialLabel Label +hi def link z8aComment Comment +hi def link z8aInstruction Statement +hi def link z8aSpecInst Statement +hi def link z8aInclude Include +hi def link z8aPreCondit PreCondit +hi def link z8aPreProc PreProc +hi def link z8aNumber Number +hi def link z8aString String + let b:current_syntax = "z8a" " vim: ts=8 diff --git a/runtime/tutor/en/vim-01-beginner.tutor b/runtime/tutor/en/vim-01-beginner.tutor index 47d4ed06a1..fee7de21d2 100644 --- a/runtime/tutor/en/vim-01-beginner.tutor +++ b/runtime/tutor/en/vim-01-beginner.tutor @@ -18,10 +18,10 @@ be saved. Don't worry about messing things up; just remember that pressing [<Esc>](<Esc>) and then [u](u) will undo the latest change. This tutorial is interactive, and there are a few things you should know. -Pressing [<Enter>](<Enter>) over text highlighted [like this](holy-grail) will take you to some relevant -help (hopefully), and pressing K over any word will try to do so too. Sometimes -you will be required to modify text like ----> this here {expect:this here} +Pressing [<Enter>](<Enter>) over text highlighted [like this](holy-grail) will take you to some +relevant help (hopefully), and pressing K over any word will try to do so too. +Sometimes you will be required to modify text like +this here Once you have done the changes correctly, the โ sign at the left will change to โ. I imagine you can already see how neat Vim can be ;) Other times, you'll be prompted to run a command (I'll explain this later): @@ -99,7 +99,7 @@ NOTE: [:q!](:q) <Enter> discards any changes you made. In a few lessons you 4. Repeat steps 2 through 4 until the sentence is correct. ----> The ccow jumpedd ovverr thhe mooon. {expect:The cow jumped over the moon.} +The ccow jumpedd ovverr thhe mooon. 5. Now that the line is correct, go on to Lesson 1.4. @@ -119,8 +119,8 @@ NOTE: As you go through this tutor, do not try to memorize, learn by usage. 4. As each error is fixed press <Esc> to return to Normal mode. Repeat steps 2 through 4 to correct the sentence. ----> There is text misng this . {expect:There is some text missing from this line.} ----> There is some text missing from this line. {expect:There is some text missing from this line.} +There is text misng this . +There is some text missing from this line. 5. When you are comfortable inserting text move to lesson 1.5. @@ -138,10 +138,10 @@ NOTE: As you go through this tutor, do not try to memorize, learn by usage. 4. Move the cursor to the second line marked ---> and repeat steps 2 and 3 to correct this sentence. ----> There is some text missing from th {expect:There is some text missing from this line.} ----> There is some text missing from this line. {expect:There is some text missing from this line.} ----> There is also some text miss {expect:There is also some text missing here.} ----> There is also some text missing here. {expect:There is also some text missing here.} +There is some text missing from th +There is some text missing from this line. +There is also some text miss +There is also some text missing here. 5. When you are comfortable appending text move to lesson 1.6. @@ -212,7 +212,7 @@ Now continue with Lesson 2. 4. Type [d](d)[w](w) to make the word disappear. ----> There are a some words fun that don't belong paper in this sentence. {expect:There are some words that don't belong in this sentence.} +There are a some words fun that don't belong paper in this sentence. 5. Repeat steps 3 and 4 until the sentence is correct and go to Lesson 2.2. @@ -228,7 +228,7 @@ Now continue with Lesson 2. 4. Type `d$`{normal} to delete to the end of the line. ----> Somebody typed the end of this line twice. end of this line twice. {expect:ANYTHING} +Somebody typed the end of this line twice. end of this line twice. 5. Move on to Lesson 2.3 to understand what is happening. @@ -268,7 +268,7 @@ NOTE: Pressing just the motion while in Normal mode without an operator will 5. Repeat steps 2 and 3 with different numbers. ----> This is just a line with words you can move around in. {expect:ANYTHING} +This is just a line with words you can move around in. 6. Move on to Lesson 2.5. @@ -287,7 +287,7 @@ insert a count before the motion to delete more: 3. Repeat steps 1 and 2 with a different count to delete the consecutive UPPER CASE words with one command ----> this ABC DE line FGHI JK LMN OP of words is Q RS TUV cleaned up. {expect:this line of words is cleaned up.} +this ABC DE line FGHI JK LMN OP of words is Q RS TUV cleaned up. # Lesson 2.6: OPERATING ON LINES @@ -301,13 +301,13 @@ insert a count before the motion to delete more: 3. Now move to the fourth line. 4. Type `2dd`{normal} to delete two lines. ----> 1) Roses are red, {expect:ANYTHING} ----> 2) Mud is fun, {expect:ANYTHING} ----> 3) Violets are blue, {expect:ANYTHING} ----> 4) I have a car, {expect:ANYTHING} ----> 5) Clocks tell time, {expect:ANYTHING} ----> 6) Sugar is sweet {expect:ANYTHING} ----> 7) And so are you. {expect:ANYTHING} +1) Roses are red, +2) Mud is fun, +3) Violets are blue, +4) I have a car, +5) Clocks tell time, +6) Sugar is sweet +7) And so are you. # Lesson 2.7: THE UNDO COMMAND @@ -322,7 +322,7 @@ insert a count before the motion to delete more: 6. Now type `u`{normal} a few times to undo the U and preceding commands. 7. Now type `<Ctrl-r>`{normal} a few times to redo the commands (undo the undo's). ----> Fiix the errors oon thhis line and reeplace them witth undo. {expect:Fix the errors on this line and replace them with undo.} +Fiix the errors oon thhis line and reeplace them witth undo. 8. These are very useful commands. Now move on to the Lesson 2 Summary. @@ -362,10 +362,10 @@ insert a count before the motion to delete more: 5. Repeat steps 2 through 4 to put all the lines in correct order. ----> d) Can you learn too? {expect:ANYTHING} ----> b) Violets are blue, {expect:ANYTHING} ----> c) Intelligence is learned, {expect:ANYTHING} ----> a) Roses are red, {expect:ANYTHING} +d) Can you learn too? +b) Violets are blue, +c) Intelligence is learned, +a) Roses are red, # Lesson 3.2: THE REPLACE COMMAND @@ -379,8 +379,8 @@ insert a count before the motion to delete more: 4. Repeat steps 2 and 3 until the first line is equal to the second one. ----> Whan this lime was tuoed in, someone presswd some wrojg keys! {expect:When this line was typed in, someone pressed some wrong keys!} ----> When this line was typed in, someone pressed some wrong keys! {expect:When this line was typed in, someone pressed some wrong keys!} +Whan this lime was tuoed in, someone presswd some wrojg keys! +When this line was typed in, someone pressed some wrong keys! 5. Now move on to Lesson 3.3. @@ -400,8 +400,8 @@ NOTE: Remember that you should be learning by doing, not memorization. 5. Repeat steps 3 and 4 until the first sentence is the same as the second. ----> This lubw has a few wptfd that mrrf changing usf the change operator. {expect:This line has a few words that need changing using the change operator.} ----> This line has a few words that need changing using the change operator. {expect:This line has a few words that need changing using the change operator.} +This lubw has a few wptfd that mrrf changing usf the change operator. +This line has a few words that need changing using the change operator. Notice that [c](c)e deletes the word and places you in Insert mode. @@ -421,8 +421,8 @@ Notice that [c](c)e deletes the word and places you in Insert mode. 5. Type `c$`{normal} and type the rest of the line like the second and press `<Esc>`{normal}. ----> The end of this line needs some help to make it like the second. {expect:The end of this line needs to be corrected using the c$ command.} ----> The end of this line needs to be corrected using the c$ command. {expect:The end of this line needs to be corrected using the c$ command.} +The end of this line needs some help to make it like the second. +The end of this line needs to be corrected using the c$ command. NOTE: You can use the Backspace key to correct mistakes while typing. @@ -484,7 +484,7 @@ NOTE: You may see the cursor position in the lower right corner of the screen 5. To go back to where you came from press `<Ctrl-o>`{normal} (Keep Ctrl down while pressing the letter o). Repeat to go back further. `<Ctrl-i>`{normal} goes forward. ----> "errroor" is not the way to spell error; errroor is an error. {expect:ANYTHING} +"errroor" is not the way to spell error; errroor is an error. NOTE: When the search reaches the end of the file it will continue at the start, unless the ['wrapscan']('wrapscan') option has been reset. @@ -503,7 +503,7 @@ NOTE: When the search reaches the end of the file it will continue at the 5. Move the cursor to another (,),[,],{ or } and see what `%`{normal} does. ----> This ( is a test line with ('s, ['s ] and {'s } in it. )) {expect:ANYTHING} +This ( is a test line with ('s, ['s ] and {'s } in it. )) NOTE: This is very useful in debugging a program with unmatched parentheses! @@ -528,7 +528,7 @@ NOTE: This is very useful in debugging a program with unmatched parentheses! Adding the g [flag](:s_flags) means to substitute globally in the line, change all occurrences of "thee" in the line. ----> thee best time to see thee flowers is in thee spring. {expect:the best time to see the flowers is in the spring.} +thee best time to see thee flowers is in thee spring. 4. To change every occurrence of a character string between two lines, type ~~~ cmd @@ -719,12 +719,12 @@ NOTE: You can also read the output of an external command. For example, 3. Now type some text and press `<Esc>`{normal} to exit Insert mode. ----> After typing o the cursor is placed on the open line in Insert mode. {expect:ANYTHING} +After typing o the cursor is placed on the open line in Insert mode. 4. To open up a line ABOVE the cursor, simply type a [capital O](O), rather than a lowercase `o`{normal}. Try this on the line below. ----> Open up a line above this by typing O while the cursor is on this line. {expect:ANYTHING} +Open up a line above this by typing O while the cursor is on this line. # Lesson 6.2: THE APPEND COMMAND @@ -741,8 +741,8 @@ NOTE: You can also read the output of an external command. For example, 5. Use `e`{normal} to move to the next incomplete word and repeat steps 3 and 4. ----> This li will allow you to pract appendi text to a line. {expect:This line will allow you to practice appending text to a line.} ----> This line will allow you to practice appending text to a line. {expect:This line will allow you to practice appending text to a line.} +This li will allow you to pract appendi text to a line. +This line will allow you to practice appending text to a line. NOTE: [a](a), [i](i) and [A](A) all go to the same Insert mode, the only difference is where the characters are inserted. @@ -762,8 +762,8 @@ NOTE: [a](a), [i](i) and [A](A) all go to the same Insert mode, the only differ 4. Repeat the steps to replace the remaining "xxx". ----> Adding 123 to xxx gives you xxx. {expect:Adding 123 to 456 gives you 579.} ----> Adding 123 to 456 gives you 579. {expect:Adding 123 to 456 gives you 579.} +Adding 123 to xxx gives you xxx. +Adding 123 to 456 gives you 579. NOTE: Replace mode is like Insert mode, but every typed character deletes an existing character. @@ -785,8 +785,8 @@ NOTE: Replace mode is like Insert mode, but every typed character deletes an 6. Use Visual mode to select " item.", yank it with `y`{normal}, move to the end of the next line with `j$`{normal} and put the text there with `p`{normal}. ----> a) this is the first item. ----> b) {expect: b) this is the second item} +a) this is the first item. + b) NOTE: you can also use `y`{normal} as an operator; `yw`{normal} yanks one word. @@ -947,8 +947,10 @@ There are many resources online to learn more about vim. Here's a bunch of them: - Vim Video-Tutorials by Derek Wyatt: http://derekwyatt.org/vim/tutorials/ - *Learn Vimscript the Hard Way*: http://learnvimscriptthehardway.stevelosh.com/ - *7 Habits of Effective Text Editing*: http://www.moolenaar.net/habits.html +- *vim-galore*: https://github.com/mhinz/vim-galore -If you prefer a book, *Practival Vim* by Drew Neil is recommended often. +If you prefer a book, *Practical Vim* by Drew Neil is recommended often (the sequel, *Modern +Vim*, includes material specific to nvim!). This tutorial was written by Michael C. Pierce and Robert K. Ware, Colorado School of Mines using ideas supplied by Charles Smith, Colorado State diff --git a/runtime/tutor/en/vim-01-beginner.tutor.json b/runtime/tutor/en/vim-01-beginner.tutor.json new file mode 100644 index 0000000000..3f55971a09 --- /dev/null +++ b/runtime/tutor/en/vim-01-beginner.tutor.json @@ -0,0 +1,45 @@ +{ + "expect": { + "24": -1, + "102": "The cow jumped over the moon.", + "122": "There is some text missing from this line.", + "123": "There is some text missing from this line.", + "141": "There is some text missing from this line.", + "142": "There is some text missing from this line.", + "143": "There is also some text missing here.", + "144": "There is also some text missing here.", + "215": "There are some words that don't belong in this sentence.", + "231": "Somebody typed the end of this line twice.", + "271": -1, + "290": "this line of words is cleaned up.", + "304": -1, + "305": -1, + "306": -1, + "307": -1, + "308": -1, + "309": -1, + "310": -1, + "325": "Fix the errors on this line and replace them with undo.", + "365": -1, + "366": -1, + "367": -1, + "368": -1, + "382": "When this line was typed in, someone pressed some wrong keys!", + "383": "When this line was typed in, someone pressed some wrong keys!", + "403": "This line has a few words that need changing using the change operator.", + "404": "This line has a few words that need changing using the change operator.", + "424": "The end of this line needs to be corrected using the c$ command.", + "425": "The end of this line needs to be corrected using the c$ command.", + "487": -1, + "506": -1, + "531": "the best time to see the flowers is in the spring.", + "722": -1, + "727": -1, + "744": "This line will allow you to practice appending text to a line.", + "745": "This line will allow you to practice appending text to a line.", + "765": "Adding 123 to 456 gives you 579.", + "766": "Adding 123 to 456 gives you 579.", + "788": "a) this is the first item.", + "789": " b) this is the second item." + } +} diff --git a/runtime/tutor/tutor.tutor b/runtime/tutor/tutor.tutor index 1ad64a18ff..c937bd686a 100644 --- a/runtime/tutor/tutor.tutor +++ b/runtime/tutor/tutor.tutor @@ -60,27 +60,27 @@ is displayed like 1. Format the line below so it becomes a lesson description: ----> This is text with important information {expect:This is text with **important information**} ----> This is text with **important information** {expect:This is text with **important information**} +This is text with important information +This is text with **important information** Note: Some words (e.g., NOTE, IMPORTANT, tip, ATTENTION, etc.) will also be highlighted. You don't need to mark them specially. 2. Turn the line below into a TODO item: ----> Document '&variable' {expect:TODO: Document '&variable'} ----> TODO: Document '&variable' {expect:TODO: Document '&variable'} +Document '&variable' +TODO: Document '&variable' ### Headers *headers* 3. Practice fixing the lines below: ----> This is a level 1 header {expect:# This is a level 1 header} ----> # This is a level 1 header {expect:# This is a level 1 header} ----> This is a level 3 header {expect:### This is a level 3 header} ----> ### This is a level 3 header {expect:### This is a level 3 header} ----> This is a header with a label {expect:# This is a header with a label {*label*}} ----> # This is a header with a label {*label*} {expect:# This is a header with a label {*label*}} +This is a level 1 header +# This is a level 1 header +This is a level 3 header +### This is a level 3 header +This is a header with a label +# This is a header with a label {*label*} 4. Now, create a 4th level section here, and add a label like in the previous exercise: @@ -105,8 +105,8 @@ If the target of a link matches a help topic, opening it will open it. 5. Fix the following line: ----> A link to help for the 'breakindent' option {expect:A link to help for the ['breakindent']('breakindent') option} ----> A link to help for the ['breakindent']('breakindent') option {expect:A link to help for the ['breakindent']('breakindent') option} +A link to help for the 'breakindent' option +A link to help for the ['breakindent']('breakindent') option #### Anchor links @@ -120,8 +120,8 @@ and are hidden by default. Links to them look like 6. Add the appropiate link: ----> A link to the Links section {expect:A link to the [Links](*links*) section} ----> A link to the [Links](*links*) section {expect:A link to the [Links](*links*) section} +A link to the Links section +A link to the [Links](*links*) section 7. Now, create a link to the section you created on exercise 4 above. @@ -136,8 +136,8 @@ You can also have links to other tutorials. For this, you'll write the anchor in 7. Create a link to this tutorial: ----> A link to the vim-tutor-mode tutorial {expect:A link to [the vim-tutor-mode tutorial](@tutor:tutor)} ----> A link to [the vim-tutor-mode tutorial](@tutor:tutor) {expect:A link to [the vim-tutor-mode tutorial](@tutor:tutor)} +A link to the vim-tutor-mode tutorial +A link to [the vim-tutor-mode tutorial](@tutor:tutor) ### Codeblocks *codeblocks* @@ -154,13 +154,13 @@ echom "hello" 8. Copy the viml section below ----> {expect:~~~ viml} ----> {expect:echom "the value of &number is".string(&number)} ----> {expect:~~~} ----> ~~~ viml {expect:~~~ viml} ----> echom "the value of &number is".string(&number) {expect:echom "the value of &number is".string(&number)} ----> ~~~ {expect:~~~} + + + +~~~ viml +echom 'the value of &number is'.string(&number) +~~~ You can inline viml code using "\`" and "\`{vim}": @@ -185,13 +185,13 @@ Note: you can also write `norm` or `normal`. 9. Copy the normal section below ----> {expect:~~~ normal} ----> {expect:d2w} ----> {expect:~~~} ----> ~~~ normal {expect:~~~ normal} ----> d2w {expect:d2w} ----> ~~~ {expect:~~~} + + + +~~~ normal +d2w +~~~ You can also inline normal commands by using "\`" and "\`{normal}": @@ -203,10 +203,11 @@ is displayed: 10. Complete the line as shown ----> d {expect:ยซd2wยป} ----> ยซd2wยป {expect:ยซd2wยป} +d +`d2w`{normal} -Commands to run in the system shell can be highlighted by indenting a line starting with "$". +Commands to run in the system shell can be highlighted by indenting a line +starting with "$". ~~~ sh $ vim --version @@ -215,45 +216,32 @@ Commands to run in the system shell can be highlighted by indenting a line start ## INTERACTIVE ELEMENTS *interactive* As visible in this very document, vim-tutor-mode includes some interactive -elements, to provide feedback to the user about his progress. These elements -all have the syntax - - \---> TEXT {CLAUSE} - -where \---> must start at the beginning of the line. If TEXT satisfies CLAUSE, -a โ sign will appear to the left. A โ sign is displayed otherwise. The CLAUSE -itself is hidden unless debug mode is set or ['conceallevel']('conceallevel') -is 2. +elements to provide feedback to the user about his progress. If the text in +these elements satisfies some set condition, a โ sign will appear in the gutter +to the left. Otherwise, a โ sign is displayed. ### expect *expect* -The basic clause is "expect", which is satisfied if TEXT is the same as the -content of the clause. For example - - \---> TEXT {expect:TEXT} - -is satisfied, but - - \---> OTHER TEXT {expect:TEXT} - -is not. +"expect" lines check that the contents of the line are identical to some preset text +(like in the exercises above). -13. Make both lines the same: +These elements are specified in separate JSON files like this ----> this is not right {expect:---> this is right} |expect:---> this is right {expect:---> this is right}| ----> ---> this is right {expect:---> this is right} |expect:---> this is right {expect:---> this is right}| - - -If the content of a expect clause is ANYTHING, no checks will be performed. This is -useful to create a line that is highlighted you want the user to play with. - - \---> TEXT {expect:ANYTHING} - -is displayed +~~~ json +{ + "expect": { + "1": "This is how this line should look.", + "2": "This is how this line should look.", + "3": -1 + } +} +~~~ ----> this is free text {expect:ANYTHING} +These files contain an "expect" dictionary, for which the keys are line numbers and +the values are the expected text. A value of -1 means that the condition for the line +will always be satisfied, no matter what (this is useful for letting the user play a bit). -14. Turn the line below into free text: +This is an "expect" line that is always satisfied. Try changing it. ----> this is some text |expect:---> this is some text {expect:ANYTHING}| ----> ---> this is some text {expect:ANYTHING} |expect:---> this is some text {expect:ANYTHING}| +These files conventionally have the same name as the tutorial document with the `.json` +extension appended (for a full example, see the file that corresponds to this tutorial). diff --git a/runtime/tutor/tutor.tutor.json b/runtime/tutor/tutor.tutor.json new file mode 100644 index 0000000000..bf3eae8586 --- /dev/null +++ b/runtime/tutor/tutor.tutor.json @@ -0,0 +1,35 @@ +{ + "expect": { + "63": "This is text with **important information**", + "64": "This is text with **important information**", + "71": "Document '&variable'", + "72": "Document '&variable'", + "78": "# This is a level 1 header", + "79": "# This is a level 1 header", + "80": "### This is a level 3 header", + "81": "### This is a level 3 header", + "82": "# This is a header with a label {*label*}", + "83": "# This is a header with a label {*label*}", + "108": "A link to help for the ['breakindent']('breakindent') option", + "109": "A link to help for the ['breakindent']('breakindent') option", + "123": "A link to the [Links](*links*) section", + "124": "A link to the [Links](*links*) section", + "139": "A link to [the vim-tutor-mode tutorial](@tutor:tutor)", + "140": "A link to [the vim-tutor-mode tutorial](@tutor:tutor)", + "157": "~~~ viml", + "158": "echom 'the value of &number is'.string(&number)", + "159": "~~~", + "161": "~~~ viml", + "162": "echom 'the value of &number is'.string(&number)", + "163": "~~~", + "188": "~~~ normal", + "189": "d2w", + "190": "~~~", + "192": "~~~ normal", + "193": "d2w", + "194": "~~~", + "206": "`d2w`{normal}", + "207": "`d2w`{normal}", + "244": -1 + } +} diff --git a/scripts/check-includes.py b/scripts/check-includes.py new file mode 100755 index 0000000000..21308a21aa --- /dev/null +++ b/scripts/check-includes.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python + +import sys +import re +import os + +from subprocess import Popen, PIPE +from argparse import ArgumentParser + + +GENERATED_INCLUDE_RE = re.compile( + r'^\s*#\s*include\s*"([/a-z_0-9.]+\.generated\.h)"(\s+//.*)?$') + + +def main(argv): + argparser = ArgumentParser() + argparser.add_argument('--generated-includes-dir', action='append', + help='Directory where generated includes are located.') + argparser.add_argument('--file', type=open, help='File to check.') + argparser.add_argument('iwyu_args', nargs='*', + help='IWYU arguments, must go after --.') + args = argparser.parse_args(argv) + + with args.file: + include_dirs = [] + + iwyu = Popen(['include-what-you-use', '-xc'] + args.iwyu_args + ['/dev/stdin'], + stdin=PIPE, stdout=PIPE, stderr=PIPE) + + for line in args.file: + match = GENERATED_INCLUDE_RE.match(line) + if match: + for d in args.generated_includes_dir: + try: + f = open(os.path.join(d, match.group(1))) + except IOError: + continue + else: + with f: + for generated_line in f: + iwyu.stdin.write(generated_line) + break + else: + raise IOError('Failed to find {0}'.format(match.group(1))) + else: + iwyu.stdin.write(line) + + iwyu.stdin.close() + + out = iwyu.stdout.read() + err = iwyu.stderr.read() + + ret = iwyu.wait() + + if ret != 2: + print('IWYU failed with exit code {0}:'.format(ret)) + print('{0} stdout {0}'.format('=' * ((80 - len(' stdout ')) // 2))) + print(out) + print('{0} stderr {0}'.format('=' * ((80 - len(' stderr ')) // 2))) + print(err) + return 1 + return 0 + + +if __name__ == '__main__': + raise SystemExit(main(sys.argv[1:])) diff --git a/scripts/download-unicode-files.sh b/scripts/download-unicode-files.sh index 54fc32550c..5f38d0589a 100755 --- a/scripts/download-unicode-files.sh +++ b/scripts/download-unicode-files.sh @@ -22,7 +22,7 @@ UNIDIR=${1:-$UNIDIR_DEFAULT} DOWNLOAD_URL_BASE=${2:-$DOWNLOAD_URL_BASE_DEFAULT} for filename in $data_files ; do - curl -o "$UNIDIR/$filename" "$DOWNLOAD_URL_BASE/UNIDATA/$filename" + curl -L -o "$UNIDIR/$filename" "$DOWNLOAD_URL_BASE/UNIDATA/$filename" ( cd "$UNIDIR" git add $filename @@ -30,7 +30,7 @@ for filename in $data_files ; do done for filename in $emoji_files ; do - curl -o "$UNIDIR/$filename" "$DOWNLOAD_URL_BASE/emoji/3.0/$filename" + curl -L -o "$UNIDIR/$filename" "$DOWNLOAD_URL_BASE/emoji/latest/$filename" ( cd "$UNIDIR" git add $filename diff --git a/scripts/gen_api_vimdoc.py b/scripts/gen_api_vimdoc.py index d7165187f4..4dcb42d685 100644 --- a/scripts/gen_api_vimdoc.py +++ b/scripts/gen_api_vimdoc.py @@ -38,12 +38,9 @@ import subprocess from xml.dom import minidom -# Text at the top of the doc file. -preamble = ''' -Note: This documentation is generated from Neovim's API source code. -''' - -doc_filename = 'api-funcs.txt' +doc_filename = 'api.txt' +# String used to find the start of the generated part of the doc. +section_start_token = '*api-global*' # Section name overrides. section_name = { @@ -63,6 +60,11 @@ param_exclude = ( 'channel_id', ) +# Annotations are displayed as line items after API function descriptions. +annotation_map = { + 'FUNC_API_ASYNC': '{async}', +} + text_width = 78 script_path = os.path.abspath(__file__) base_dir = os.path.dirname(os.path.dirname(script_path)) @@ -278,6 +280,12 @@ def parse_source_xml(filename): parts = return_type.strip('_').split('_') return_type = '%s(%s)' % (parts[0], ', '.join(parts[1:])) + annotations = get_text(get_child(member, 'argsstring')) + if annotations and ')' in annotations: + annotations = annotations.rsplit(')', 1)[-1].strip() + annotations = filter(None, map(lambda x: annotation_map.get(x), + annotations.split())) + name = get_text(get_child(member, 'name')) vimtag = '*%s()*' % name @@ -336,6 +344,16 @@ def parse_source_xml(filename): if not doc: doc = 'TODO: Documentation' + annotations = '\n'.join(annotations) + if annotations: + annotations = ('\n\nAttributes:~\n' + + textwrap.indent(annotations, ' ')) + i = doc.rfind('Parameters:~') + if i == -1: + doc += annotations + else: + doc = doc[:i] + annotations + '\n\n' + doc[i:] + if 'INCLUDE_C_DECL' in os.environ: doc += '\n\nC Declaration:~\n>\n' doc += c_decl @@ -355,6 +373,19 @@ def parse_source_xml(filename): return '\n\n'.join(functions), '\n\n'.join(deprecated_functions) +def delete_lines_below(filename, tokenstr): + """Deletes all lines below the line containing `tokenstr`, the line itself, + and one line above it. + """ + lines = open(filename).readlines() + i = 0 + for i, line in enumerate(lines, 1): + if tokenstr in line: + break + i = max(0, i - 2) + with open(filename, 'wt') as fp: + fp.writelines(lines[0:i]) + def gen_docs(config): """Generate documentation. @@ -366,7 +397,6 @@ def gen_docs(config): if p.returncode: sys.exit(p.returncode) - title_length = 0 sections = {} sep = '=' * text_width @@ -404,26 +434,13 @@ def gen_docs(config): name = section_name.get(filename, name) title = '%s Functions' % name helptag = '*api-%s*' % name.lower() - title_length = max(title_length, len(title)) sections[filename] = (title, helptag, doc) if not sections: return - title_left = '*%s*' % doc_filename - title_center = 'Neovim API Function Reference' - title_right = '{Nvim}' - margin = max(len(title_left), len(title_right)) - head = (title_left.ljust(margin) + - title_center.center(text_width - margin * 2) + - title_right.rjust(margin)) + '\n' - - head += '\n%s\n\n' % doc_wrap(preamble, width=text_width) - head += 'Contents:\n\n' - docs = '' - title_length += len(str(len(section_order))) + 2 i = 0 for filename in section_order: if filename not in sections: @@ -432,9 +449,6 @@ def gen_docs(config): i += 1 docs += sep - title = '%d. %s' % (i, title) - head += (title.ljust(title_length) + ' ' + - helptag.replace('*', '|') + '\n') docs += '\n%s%s' % (title, helptag.rjust(text_width - len(title))) docs += section_doc docs += '\n\n\n' @@ -444,21 +458,17 @@ def gen_docs(config): for title, helptag, section_doc in sections.values(): i += 1 docs += sep - title = '%d. %s' % (i, title) - head += (title.ljust(title_length) + ' ' + - helptag.replace('*', '|') + '\n') docs += '\n%s%s' % (title, helptag.rjust(text_width - len(title))) docs += section_doc docs += '\n\n\n' - docs = '%s\n%s' % (head, docs) docs = docs.rstrip() + '\n\n' docs += ' vim:tw=78:ts=8:ft=help:norl:' doc_file = os.path.join(base_dir, 'runtime/doc', doc_filename) - with open(doc_file, 'wb') as fp: + delete_lines_below(doc_file, section_start_token) + with open(doc_file, 'ab') as fp: fp.write(docs.encode('utf8')) - shutil.rmtree(out_dir) diff --git a/scripts/genappimage.sh b/scripts/genappimage.sh new file mode 100755 index 0000000000..a73ccd86c7 --- /dev/null +++ b/scripts/genappimage.sh @@ -0,0 +1,83 @@ +#!/bin/bash + +######################################################################## +# Package the binaries built as an AppImage +# By Simon Peter 2016 +# For more information, see http://appimage.org/ +######################################################################## + +# App arch, used by generate_appimage. +if [ -z "$ARCH" ]; then + export ARCH="$(arch)" +fi + +# App name, used by generate_appimage. +APP=nvim + +ROOT_DIR="$(git rev-parse --show-toplevel)" +APP_BUILD_DIR="$ROOT_DIR/build" +APP_DIR="$APP.AppDir" + +######################################################################## +# Compile nvim and install it into AppDir +######################################################################## + +# Build and install nvim into the AppImage +make CMAKE_BUILD_TYPE=RelWithDebInfo CMAKE_EXTRA_FLAGS="-DCMAKE_INSTALL_PREFIX=${APP_DIR}/usr -DCMAKE_INSTALL_MANDIR=man" +make install + +######################################################################## +# Get helper functions and move to AppDir +######################################################################## + +# App version, used by generate_appimage. +VERSION=$("$ROOT_DIR"/build/bin/nvim --version | head -n 1 | grep -o 'v.*') + +cd "$APP_BUILD_DIR" + +curl -Lo "$APP_BUILD_DIR"/appimage_functions.sh https://github.com/probonopd/AppImages/raw/master/functions.sh +. ./appimage_functions.sh + +# Copy desktop and icon file to AppDir for AppRun to pick them up. +# get_apprun +# get_desktop +cp "$ROOT_DIR/runtime/nvim.desktop" "$APP_DIR/" +cp "$ROOT_DIR/runtime/nvim.png" "$APP_DIR/" + +cd "$APP_DIR" + +# copy dependencies +copy_deps +# Move the libraries to usr/bin +move_lib + +# Delete stuff that should not go into the AppImage. +# Delete dangerous libraries; see +# https://github.com/probonopd/AppImages/blob/master/excludelist +delete_blacklisted + +######################################################################## +# AppDir complete. Now package it as an AppImage. +######################################################################## + +# No need for a fancy script. AppRun can just be a symlink to nvim. +ln -s usr/bin/nvim AppRun + +cd "$APP_BUILD_DIR" # Get out of AppImage directory. + +# Generate AppImage. +# - Expects: $ARCH, $APP, $VERSION env vars +# - Expects: ./$APP.AppDir/ directory +# - Produces: ../out/$APP-$VERSION.glibc$GLIBC_NEEDED-$ARCH.AppImage +generate_appimage + +# NOTE: There is currently a bug in the `generate_appimage` function (see +# https://github.com/probonopd/AppImages/issues/228) that causes repeated builds +# that result in the same name to fail. +# Moving the final executable to a different folder gets around this issue. + +mv "$ROOT_DIR"/out/*.AppImage "$ROOT_DIR"/build/bin +# Remove the (now empty) folder the AppImage was built in +rmdir "$ROOT_DIR"/out + +echo 'genappimage.sh: finished' diff --git a/scripts/pvscheck.sh b/scripts/pvscheck.sh new file mode 100755 index 0000000000..e4536b3dce --- /dev/null +++ b/scripts/pvscheck.sh @@ -0,0 +1,449 @@ +#!/bin/sh + +# Assume that "local" is available. +# shellcheck disable=SC2039 + +set -e +# Note: -u causes problems with posh, it barks at โundefinedโ $@ when no +# arguments provided. +test -z "$POSH_VERSION" && set -u + +get_jobs_num() { + if [ -n "${TRAVIS:-}" ] ; then + # HACK: /proc/cpuinfo on Travis CI is misleading, so hardcode 1. + echo 1 + else + echo $(( $(grep -c "^processor" /proc/cpuinfo) + 1 )) + fi +} + +help() { + echo 'Usage:' + echo ' pvscheck.sh [--pvs URL] [--deps] [--environment-cc]' + echo ' [target-directory [branch]]' + echo ' pvscheck.sh [--pvs URL] [--recheck] [--environment-cc]' + echo ' [target-directory]' + echo ' pvscheck.sh [--pvs URL] --only-analyse [target-directory]' + echo ' pvscheck.sh [--pvs URL] --pvs-install {target-directory}' + echo ' pvscheck.sh --patch [--only-build]' + echo + echo ' --pvs: Use the specified URL as a path to pvs-studio archive.' + echo ' By default latest tested version is used.' + echo + echo ' May use "--pvs detect" to try detecting latest version.' + echo ' That assumes certain viva64.com site properties and' + echo ' may be broken by the site update.' + echo + echo ' --deps: (for regular run) Use top-level Makefile and build deps.' + echo ' Without this it assumes all dependencies are already' + echo ' installed.' + echo + echo ' --environment-cc: (for regular run and --recheck) Do not export' + echo ' CC=clang. Build is still run with CFLAGS=-O0.' + echo + echo ' --only-build: (for --patch) Only patch files in ./build directory.' + echo + echo ' --pvs-install: Only install PVS-studio to the specified location.' + echo + echo ' --patch: patch sources in the current directory.' + echo ' Does not patch already patched files.' + echo ' Does not run analysis.' + echo + echo ' --recheck: run analysis on a prepared target directory.' + echo + echo ' --only-analyse: run analysis on a prepared target directory ' + echo ' without building Neovim.' + echo + echo ' target-directory: Directory where build should occur.' + echo ' Default: ../neovim-pvs' + echo + echo ' branch: Branch to check.' + echo ' Default: master.' +} + +getopts_error() { + local msg="$1" ; shift + local do_help= + if test "$msg" = "--help" ; then + msg="$1" ; shift + do_help=1 + fi + printf '%s\n' "$msg" >&2 + if test -n "$do_help" ; then + printf '\n' >&2 + help >&2 + fi + echo 'return 1' + return 1 +} + +# Usage `eval "$(getopts_long long_defs -- positionals_defs -- "$@")"` +# +# long_defs: list of pairs of arguments like `longopt action`. +# positionals_defs: list of arguments like `action`. +# +# `action` is a space-separated commands: +# +# store_const [const] [varname] [default] +# Store constant [const] (default 1) (note: evalโed) if argument is present +# (long options only). Assumes long option accepts no arguments. +# store [varname] [default] +# Store value. Assumes long option needs an argument. +# run {func} [varname] [default] +# Run function {func} and store its output to the [varname]. Assumes no +# arguments accepted (long options only). +# modify {func} [varname] [default] +# Like run, but assumes a single argument, passed to function {func} as $1. +# +# All actions stores empty value if neither [varname] nor [default] are +# present. [default] is evaled by top-level `eval`, so be careful. Also note +# that no arguments may contain spaces, including [default] and [const]. +getopts_long() { + local positional= + local opt_bases="" + while test $# -gt 0 ; do + local arg="$1" ; shift + local opt_base= + local act= + local opt_name= + if test -z "$positional" ; then + if test "$arg" = "--" ; then + positional=0 + continue + fi + act="$1" ; shift + opt_name="$(echo "$arg" | tr '-' '_')" + opt_base="longopt_$opt_name" + else + if test "$arg" = "--" ; then + break + fi + : $(( positional+=1 )) + act="$arg" + opt_name="arg_$positional" + opt_base="positional_$positional" + fi + opt_bases="$opt_bases $opt_base" + eval "local varname_$opt_base=$opt_name" + local i=0 + for act_subarg in $act ; do + eval "local act_$(( i+=1 ))_$opt_base=\"\$act_subarg\"" + done + done + # Process options + local positional=0 + local force_positional= + while test $# -gt 0 ; do + local argument="$1" ; shift + local opt_base= + local has_equal= + local equal_arg= + local is_positional= + if test "$argument" = "--" ; then + force_positional=1 + continue + elif test -z "$force_positional" && test "${argument#--}" != "$argument" + then + local opt_name="${argument#--}" + local opt_name_striparg="${opt_name%%=*}" + if test "$opt_name" = "$opt_name_striparg" ; then + has_equal=0 + else + has_equal=1 + equal_arg="${argument#*=}" + opt_name="$opt_name_striparg" + fi + # Use trailing x to prevent stripping newlines + opt_name="$(printf '%sx' "$opt_name" | tr '-' '_')" + opt_name="${opt_name%x}" + if test -n "$(printf '%sx' "$opt_name" | tr -d 'a-z_')" ; then + getopts_error "Option contains invalid characters: $opt_name" + fi + opt_base="longopt_$opt_name" + else + : $(( positional+=1 )) + opt_base="positional_$positional" + is_positional=1 + fi + if test -n "$opt_base" ; then + eval "local occurred_$opt_base=1" + + eval "local act_1=\"\${act_1_$opt_base:-}\"" + eval "local varname=\"\${varname_$opt_base:-}\"" + local need_val= + local func= + case "$act_1" in + (store_const) + eval "local const=\"\${act_2_${opt_base}:-1}\"" + eval "local varname=\"\${act_3_${opt_base}:-$varname}\"" + printf 'local %s=%s\n' "$varname" "$const" + ;; + (store) + eval "varname=\"\${act_2_${opt_base}:-$varname}\"" + need_val=1 + ;; + (run) + eval "func=\"\${act_2_${opt_base}}\"" + eval "varname=\"\${act_3_${opt_base}:-$varname}\"" + printf 'local %s="$(%s)"\n' "$varname" "$func" + ;; + (modify) + eval "func=\"\${act_2_${opt_base}}\"" + eval "varname=\"\${act_3_${opt_base}:-$varname}\"" + need_val=1 + ;; + ("") + getopts_error --help "Wrong argument: $argument" + ;; + esac + if test -n "$need_val" ; then + local val= + if test -z "$is_positional" ; then + if test $has_equal = 1 ; then + val="$equal_arg" + else + if test $# -eq 0 ; then + getopts_error "Missing argument for $opt_name" + fi + val="$1" ; shift + fi + else + val="$argument" + fi + local escaped_val="'$(printf "%s" "$val" | sed "s/'/'\\\\''/g")'" + case "$act_1" in + (store) + printf 'local %s=%s\n' "$varname" "$escaped_val" + ;; + (modify) + printf 'local %s="$(%s %s)"\n' "$varname" "$func" "$escaped_val" + ;; + esac + fi + fi + done + # Print default values when no values were provided + local opt_base= + for opt_base in $opt_bases ; do + eval "local occurred=\"\${occurred_$opt_base:-}\"" + if test -n "$occurred" ; then + continue + fi + eval "local act_1=\"\$act_1_$opt_base\"" + eval "local varname=\"\$varname_$opt_base\"" + case "$act_1" in + (store) + eval "local varname=\"\${act_2_${opt_base}:-$varname}\"" + eval "local default=\"\${act_3_${opt_base}:-}\"" + printf 'local %s=%s\n' "$varname" "$default" + ;; + (store_const|run|modify) + eval "local varname=\"\${act_3_${opt_base}:-$varname}\"" + eval "local default=\"\${act_4_${opt_base}:-}\"" + printf 'local %s=%s\n' "$varname" "$default" + ;; + esac + done +} + +get_pvs_comment() { + local tgt="$1" ; shift + + cat > "$tgt/pvs-comment" << EOF +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + +EOF +} + +install_pvs() {( + local tgt="$1" ; shift + local pvs_url="$1" ; shift + + cd "$tgt" + + mkdir pvs-studio + cd pvs-studio + + curl -L -o pvs-studio.tar.gz "$pvs_url" + tar xzf pvs-studio.tar.gz + rm pvs-studio.tar.gz + local pvsdir="$(find . -maxdepth 1 -mindepth 1)" + find "$pvsdir" -maxdepth 1 -mindepth 1 -exec mv '{}' . \; + rmdir "$pvsdir" +)} + +create_compile_commands() {( + local tgt="$1" ; shift + local deps="$1" ; shift + local environment_cc="$1" ; shift + + if test -z "$environment_cc" ; then + export CC=clang + fi + export CFLAGS=' -O0 ' + + if test -z "$deps" ; then + mkdir -p "$tgt/build" + ( + cd "$tgt/build" + + cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX="$PWD/root" + make -j"$(get_jobs_num)" + ) + else + ( + cd "$tgt" + + make -j"$(get_jobs_num)" CMAKE_EXTRA_FLAGS=" -DCMAKE_INSTALL_PREFIX=$PWD/root -DCMAKE_BUILD_TYPE=Debug " + ) + fi + find "$tgt/build/src/nvim/auto" -name '*.test-include.c' -delete +)} + +# Warning: realdir below only cares about directories unlike realpath. +# +# realpath is not available in Ubuntu trusty yet. +realdir() {( + local dir="$1" + cd "$dir" + printf '%s\n' "$PWD" +)} + +patch_sources() {( + local tgt="$1" ; shift + local only_bulid="${1}" ; shift + + get_pvs_comment "$tgt" + + local sh_script=' + pvs_comment="$(cat pvs-comment ; echo -n EOS)" + filehead="$(head -c $(( ${#pvs_comment} - 3 )) "$1" ; echo -n EOS)" + if test "x$filehead" != "x$pvs_comment" ; then + cat pvs-comment "$1" > "$1.tmp" + mv "$1.tmp" "$1" + fi + ' + + cd "$tgt" + + if test "$only_build" != "--only-build" ; then + find \ + src/nvim test/functional/fixtures test/unit/fixtures \ + -name '*.c' \ + -exec /bin/sh -c "$sh_script" - '{}' \; + fi + + find \ + build/src/nvim/auto build/config \ + -name '*.c' -not -name '*.test-include.c' \ + -exec /bin/sh -c "$sh_script" - '{}' \; + + rm pvs-comment +)} + +run_analysis() {( + local tgt="$1" ; shift + + cd "$tgt" + + pvs-studio-analyzer \ + analyze \ + --threads "$(get_jobs_num)" \ + --output-file PVS-studio.log \ + --verbose \ + --file build/compile_commands.json \ + --sourcetree-root . + + plog-converter -t xml -o PVS-studio.xml PVS-studio.log + plog-converter -t errorfile -o PVS-studio.err PVS-studio.log + plog-converter -t tasklist -o PVS-studio.tsk PVS-studio.log +)} + +do_check() { + local tgt="$1" ; shift + local branch="$1" ; shift + local pvs_url="$1" ; shift + local deps="$1" ; shift + local environment_cc="$1" ; shift + + git clone --branch="$branch" . "$tgt" + + install_pvs "$tgt" "$pvs_url" + + do_recheck "$tgt" "$deps" "$environment_cc" +} + +do_recheck() { + local tgt="$1" ; shift + local deps="$1" ; shift + local environment_cc="$1" ; shift + + create_compile_commands "$tgt" "$deps" "$environment_cc" + + do_analysis "$tgt" +} + +do_analysis() { + local tgt="$1" ; shift + + if test -d "$tgt/pvs-studio" ; then + local saved_pwd="$PWD" + cd "$tgt/pvs-studio" + export PATH="$PWD/bin${PATH+:}${PATH}" + cd "$saved_pwd" + fi + + run_analysis "$tgt" +} + +detect_url() { + local url="${1:-detect}" + if test "$url" = detect ; then + curl -L 'https://www.viva64.com/en/pvs-studio-download-linux/' \ + | grep -o 'https\{0,1\}://[^"<>]\{1,\}/pvs-studio[^/"<>]*\.tgz' + else + printf '%s' "$url" + fi +} + +main() { + local def_pvs_url="http://files.viva64.com/pvs-studio-6.15.21741.1-x86_64.tgz" + eval "$( + getopts_long \ + help store_const \ + pvs 'modify detect_url pvs_url "${def_pvs_url}"' \ + patch store_const \ + only-build 'store_const --only-build' \ + recheck store_const \ + only-analyse store_const \ + pvs-install store_const \ + deps store_const \ + environment-cc store_const \ + -- \ + 'modify realdir tgt "$PWD/../neovim-pvs"' \ + 'store branch master' \ + -- "$@" + )" + + if test -n "$help" ; then + help + return 0 + fi + + set -x + + if test -n "$patch" ; then + patch_sources "$tgt" "$only_build" + elif test -n "$pvs_install" ; then + install_pvs "$tgt" "$pvs_url" + elif test -n "$recheck" ; then + do_recheck "$tgt" "$deps" "$environment_cc" + elif test -n "$only_analyse" ; then + do_analysis "$tgt" + else + do_check "$tgt" "$branch" "$pvs_url" "$deps" "$environment_cc" + fi +} + +main "$@" diff --git a/scripts/release.sh b/scripts/release.sh index 93f9fa3d35..692b46e921 100755 --- a/scripts/release.sh +++ b/scripts/release.sh @@ -18,6 +18,8 @@ set -e set -u set -o pipefail +USE_CURRENT_COMMIT=${1:-no} + __sed=$( [ "$(uname)" = Darwin ] && echo 'sed -E' || echo 'sed -r' ) cd "$(git rev-parse --show-toplevel)" @@ -31,6 +33,8 @@ __VERSION_MINOR=$(grep 'set(NVIM_VERSION_MINOR' CMakeLists.txt\ __VERSION_PATCH=$(grep 'set(NVIM_VERSION_PATCH' CMakeLists.txt\ |$__sed 's/.*NVIM_VERSION_PATCH ([[:digit:]]).*/\1/') __VERSION="${__VERSION_MAJOR}.${__VERSION_MINOR}.${__VERSION_PATCH}" +__API_LEVEL=$(grep 'set(NVIM_API_LEVEL ' CMakeLists.txt\ + |$__sed 's/.*NVIM_API_LEVEL ([[:digit:]]).*/\1/') { [ -z "$__VERSION_MAJOR" ] || [ -z "$__VERSION_MINOR" ] || [ -z "$__VERSION_PATCH" ]; } \ && { echo "ERROR: version parse failed: '${__VERSION}'"; exit 1; } __RELEASE_MSG="NVIM v${__VERSION} @@ -47,12 +51,20 @@ __BUMP_MSG="version bump" echo "Most recent tag: ${__LAST_TAG}" echo "Release version: ${__VERSION}" $__sed -i.bk 's/(NVIM_VERSION_PRERELEASE) "-dev"/\1 ""/' CMakeLists.txt -$__sed -i.bk 's/(NVIM_API_PRERELEASE) true/\1 false/' CMakeLists.txt -echo "Building changelog since ${__LAST_TAG}..." -__CHANGELOG="$(./scripts/git-log-pretty-since.sh "$__LAST_TAG" 'vim-patch:\S')" +if grep '(NVIM_API_PRERELEASE true)' CMakeLists.txt > /dev/null; then + $__sed -i.bk 's/(NVIM_API_PRERELEASE) true/\1 false/' CMakeLists.txt + build/bin/nvim --api-info > test/functional/fixtures/api_level_$__API_LEVEL.mpack + git add test/functional/fixtures/api_level_$__API_LEVEL.mpack +fi + +if ! test "$USE_CURRENT_COMMIT" = 'use-current-commit' ; then + echo "Building changelog since ${__LAST_TAG}..." + __CHANGELOG="$(./scripts/git-log-pretty-since.sh "$__LAST_TAG" 'vim-patch:\S')" + + git add CMakeLists.txt + git commit --edit -m "${__RELEASE_MSG} ${__CHANGELOG}" +fi -git add CMakeLists.txt -git commit --edit -m "${__RELEASE_MSG} ${__CHANGELOG}" git tag --sign -a v"${__VERSION}" -m "NVIM v${__VERSION}" $__sed -i.bk 's/(NVIM_VERSION_PRERELEASE) ""/\1 "-dev"/' CMakeLists.txt diff --git a/scripts/vim-patch.sh b/scripts/vim-patch.sh index 88fb3cae04..5ebb6a38b3 100755 --- a/scripts/vim-patch.sh +++ b/scripts/vim-patch.sh @@ -109,7 +109,7 @@ assign_commit_details() { local strip_commit_line=true else # Interpret parameter as commit hash. - vim_version="${1:0:7}" + vim_version="${1:0:12}" vim_commit=$(cd "${VIM_SOURCE_DIR}" \ && git log -1 --format="%H" "${vim_version}") local strip_commit_line=false @@ -135,17 +135,20 @@ preprocess_patch() { local na_src='proto\|Make*\|gui_*\|if_lua\|if_mzsch\|if_olepp\|if_ole\|if_perl\|if_py\|if_ruby\|if_tcl\|if_xcmdsrv' 2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/src/\S*\<\%('${na_src}'\)@norm! d/\v(^diff)|%$
' +w +q "$file" - # Remove channel.txt, netbeans.txt, os_*.txt, todo.txt, version*.txt, tags - local na_doc='channel\.txt\|netbeans\.txt\|os_\w\+\.txt\|todo\.txt\|version\d\.txt\|tags' - 2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/runtime/doc/\%('${na_doc}'\)@norm! d/\v(^diff)|%$
' +w +q "$file" + # Remove channel.txt, netbeans.txt, os_*.txt, term.txt, todo.txt, version*.txt, tags + local na_doc='channel\.txt\|netbeans\.txt\|os_\w\+\.txt\|term\.txt\|todo\.txt\|version\d\.txt\|tags' + 2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/runtime/doc/\<\%('${na_doc}'\)\>@norm! d/\v(^diff)|%$
' +w +q "$file" + + # Remove "Last change ..." changes in doc files. + 2>/dev/null $nvim --cmd 'set dir=/tmp' +'%s/^@@.*\n.*For Vim version.*Last change.*\n.*For Vim version.*Last change.*//' +w +q "$file" # Remove some testdir/Make_*.mak files local na_src_testdir='Make_amiga.mak\|Make_dos.mak\|Make_ming.mak\|Make_vms.mms' - 2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/src/testdir/\%('${na_src_testdir}'\)@norm! d/\v(^diff)|%$
' +w +q "$file" + 2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/src/testdir/\<\%('${na_src_testdir}'\)\>@norm! d/\v(^diff)|%$
' +w +q "$file" # Remove some *.po files. #5622 local na_po='sjiscorr.c\|ja.sjis.po\|ko.po\|pl.cp1250.po\|pl.po\|ru.cp1251.po\|uk.cp1251.po\|zh_CN.cp936.po\|zh_CN.po\|zh_TW.po' - 2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/src/po/\%('${na_po}'\)@norm! d/\v(^diff)|%$
' +w +q "$file" + 2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/src/po/\<\%('${na_po}'\)\>@norm! d/\v(^diff)|%$
' +w +q "$file" # Rename src/ paths to src/nvim/ LC_ALL=C sed -e 's/\( [ab]\/src\)/\1\/nvim/g' \ @@ -277,7 +280,7 @@ submit_pr() { echo "Pushing to 'origin/${checked_out_branch}'." output="$(git push origin "${checked_out_branch}" 2>&1)" && echo "โ ${output}" || - (echo "โ ${output}"; git reset --soft HEAD^1; false) + (echo "โ ${output}"; false) echo fi @@ -305,9 +308,9 @@ list_vim_patches() { printf "\nVim patches missing from Neovim:\n" - # Get commits since 7.4.602. + # Get missing Vim commits local vim_commits - vim_commits="$(cd "${VIM_SOURCE_DIR}" && git log --reverse --format='%H' v7.4.602..HEAD)" + vim_commits="$(cd "${VIM_SOURCE_DIR}" && git log --reverse --format='%H' v8.0.0000..HEAD)" local vim_commit for vim_commit in ${vim_commits}; do @@ -317,8 +320,9 @@ list_vim_patches() { vim_tag="$(cd "${VIM_SOURCE_DIR}" && git describe --tags --exact-match "${vim_commit}" 2>/dev/null)" || true if [[ -n "${vim_tag}" ]]; then local patch_number="${vim_tag:5}" # Remove prefix like "v7.4." + patch_number="$(echo ${patch_number} | sed 's/^0*//g')" # Remove prefix "0" # Tagged Vim patch, check version.c: - is_missing="$(sed -n '/static int included_patches/,/}/p' "${NVIM_SOURCE_DIR}/src/nvim/version.c" | + is_missing="$(sed -n '/static const int included_patches/,/}/p' "${NVIM_SOURCE_DIR}/src/nvim/version.c" | grep -x -e "[[:space:]]*//[[:space:]]${patch_number} NA.*" -e "[[:space:]]*${patch_number}," >/dev/null && echo "false" || echo "true")" vim_commit="${vim_tag#v}" if (cd "${VIM_SOURCE_DIR}" && git --no-pager show --color=never --name-only "v${vim_commit}" 2>/dev/null) | grep -q ^runtime; then @@ -379,8 +383,6 @@ review_commit() { assign_commit_details "${vim_version}" - local vim_patch_url="${vim_commit_url}.patch" - local expected_commit_message expected_commit_message="$(commit_message)" local message_length @@ -403,8 +405,7 @@ review_commit() { echo "โ Saved pull request diff to '${NVIM_SOURCE_DIR}/n${patch_file}'." CREATED_FILES+=("${NVIM_SOURCE_DIR}/n${patch_file}") - curl -Ssfo "${NVIM_SOURCE_DIR}/${patch_file}" "${vim_patch_url}" - echo "โ Saved Vim diff to '${NVIM_SOURCE_DIR}/${patch_file}'." + get_vim_patch "${vim_version}" CREATED_FILES+=("${NVIM_SOURCE_DIR}/${patch_file}") echo diff --git a/src/.asan-blacklist b/src/.asan-blacklist index 7636f8fa82..928d81bd5a 100644 --- a/src/.asan-blacklist +++ b/src/.asan-blacklist @@ -1,3 +1,3 @@ # multiqueue.h pointer arithmetic is not accepted by asan fun:multiqueue_node_data -fun:dictwatcher_node_data +fun:tv_dict_watcher_node_data diff --git a/src/.valgrind.supp b/src/.valgrind.supp index 8b630fcaaf..cce22bd632 100644 --- a/src/.valgrind.supp +++ b/src/.valgrind.supp @@ -10,7 +10,7 @@ Memcheck:Leak fun:malloc fun:uv_spawn - fun:pipe_process_spawn + fun:libuv_process_spawn fun:process_spawn fun:job_start } diff --git a/src/clint.py b/src/clint.py index e0f4d3eec5..4a41650ec4 100755 --- a/src/clint.py +++ b/src/clint.py @@ -182,6 +182,7 @@ _ERROR_CATEGORIES = [ 'build/include_order', 'build/printf_format', 'build/storage_class', + 'build/useless_fattr', 'readability/alt_tokens', 'readability/bool', 'readability/braces', @@ -571,7 +572,8 @@ class _CppLintState(object): for category, count in self.errors_by_category.items(): sys.stderr.write('Category \'%s\' errors found: %d\n' % (category, count)) - sys.stderr.write('Total errors found: %d\n' % self.error_count) + if self.error_count: + sys.stderr.write('Total errors found: %d\n' % self.error_count) def SuppressErrorsFrom(self, fname): """Open file and read a list of suppressed errors from it""" @@ -1224,6 +1226,10 @@ def CheckForHeaderGuard(filename, lines, error): lines: An array of strings, each representing a line of the file. error: The function to call with any errors found. """ + if filename.endswith('.c.h') or FileInfo(filename).RelativePath() in set(( + 'func_attr.h', + )): + return cppvar = GetHeaderGuardCPPVariable(filename) @@ -2268,11 +2274,14 @@ def CheckSpacing(filename, clean_lines, linenum, nesting_state, error): # //!< Header comment # or they begin with multiple slashes followed by a space: # //////// Header comment + # or they are Vim {{{ fold markers match = (Search(r'[=/-]{4,}\s*$', line[commentend:]) or Search(r'^/$', line[commentend:]) or Search(r'^!< ', line[commentend:]) or Search(r'^/< ', line[commentend:]) or - Search(r'^/+ ', line[commentend:])) + Search(r'^/+ ', line[commentend:]) or + Search(r'^(?:\{{3}|\}{3})\d*(?: |$)', + line[commentend:])) if not match: error(filename, linenum, 'whitespace/comments', 4, 'Should have a space between // and comment') @@ -2520,6 +2529,8 @@ def CheckSpacing(filename, clean_lines, linenum, nesting_state, error): r'(?<!\bklist_t)' r'(?<!\bkliter_t)' r'(?<!\bkhash_t)' + r'(?<!\bkbtree_t)' + r'(?<!\bkbitr_t)' r'\((?:const )?(?:struct )?[a-zA-Z_]\w*(?: *\*(?:const)?)*\)' r' +' r'-?(?:\*+|&)?(?:\w+|\+\+|--|\()', cast_line) @@ -2591,16 +2602,24 @@ def CheckBraces(filename, clean_lines, linenum, error): else: func_start_linenum = end_linenum + 1 while not clean_lines.lines[func_start_linenum] == '{': - if not Match(r'^(?:\s*\b(?:FUNC_ATTR|REAL_FATTR)_\w+\b(?:\(\d+(, \d+)*\))?)+$', - clean_lines.lines[func_start_linenum]): - if clean_lines.lines[func_start_linenum].endswith('{'): + attrline = Match(r'^((?!# *define).*?)(?:FUNC_ATTR|FUNC_API|REAL_FATTR)_\w+(?:\(\d+(, \d+)*\))?', + clean_lines.lines[func_start_linenum]) + if attrline: + if len(attrline.group(1)) != 2: + error(filename, func_start_linenum, + 'whitespace/indent', 5, + 'Function attribute line should have 2-space ' + 'indent') + + func_start_linenum += 1 + else: + func_start = clean_lines.lines[func_start_linenum] + if not func_start.startswith('enum ') and func_start.endswith('{'): error(filename, func_start_linenum, 'readability/braces', 5, 'Brace starting function body must be placed ' 'after the function signature') break - else: - func_start_linenum += 1 # An else clause should be on the same line as the preceding closing brace. # If there is no preceding closing brace, there should be one. @@ -3166,11 +3185,20 @@ def CheckLanguage(filename, clean_lines, linenum, file_extension, # Check if some verboten C functions are being used. if Search(r'\bsprintf\b', line): error(filename, linenum, 'runtime/printf', 5, - 'Never use sprintf. Use snprintf instead.') - match = Search(r'\b(strcpy|strcat)\b', line) + 'Use snprintf instead of sprintf.') + match = Search(r'\b(strncpy|STRNCPY)\b', line) + if match: + error(filename, linenum, 'runtime/printf', 4, + 'Use xstrlcpy or snprintf instead of %s (unless this is from Vim)' + % match.group(1)) + match = Search(r'\b(strcpy)\b', line) + if match: + error(filename, linenum, 'runtime/printf', 4, + 'Use xstrlcpy or snprintf instead of %s' % match.group(1)) + match = Search(r'\b(STRNCAT|strncat|strcat|vim_strcat)\b', line) if match: error(filename, linenum, 'runtime/printf', 4, - 'Almost always, snprintf is better than %s' % match.group(1)) + 'Use xstrlcat or snprintf instead of %s' % match.group(1)) # Check for suspicious usage of "if" like # } if (a == b) { @@ -3434,8 +3462,9 @@ def ProcessFile(filename, vlevel, extra_check_functions=[]): # When reading from stdin, the extension is unknown, so no cpplint tests # should rely on the extension. if filename != '-' and file_extension not in _valid_extensions: - sys.stderr.write('Ignoring %s; not a valid file name ' - '(%s)\n' % (filename, ', '.join(_valid_extensions))) + sys.stderr.write('Ignoring {}; only linting {} files\n'.format( + filename, + ', '.join('.{}'.format(ext) for ext in _valid_extensions))) else: ProcessFileData(filename, file_extension, lines, Error, extra_check_functions) @@ -3565,7 +3594,7 @@ def main(): if __name__ == '__main__': main() -# vim: ts=4 sts=4 sw=4 +# vim: ts=4 sts=4 sw=4 foldmarker=โถ,โฒ # Ignore "too complex" warnings when using pymode. # pylama:ignore=C901 diff --git a/src/coverity-model.c b/src/coverity-model.c new file mode 100644 index 0000000000..3c38e4ae4d --- /dev/null +++ b/src/coverity-model.c @@ -0,0 +1,70 @@ +// Coverity Scan model +// +// This is a modeling file for Coverity Scan. Modeling helps to avoid false +// positives. +// +// - A model file can't import any header files. +// - Therefore only some built-in primitives like int, char and void are +// available but not wchar_t, NULL etc. +// - Modeling doesn't need full structs and typedefs. Rudimentary structs +// and similar types are sufficient. +// - An uninitialized local pointer is not an error. It signifies that the +// variable could be either NULL or have some data. +// +// Coverity Scan doesn't pick up modifications automatically. The model file +// must be uploaded by an admin in the analysis settings of +// http://scan.coverity.com/projects/neovim-neovim +// + +// Issue 105985 +// +// Teach coverity that uv_pipe_open saves fd on success (0 return value) +// and doesn't save it on failure (return value != 0). + +struct uv_pipe_s { + int something; +}; + +int uv_pipe_open(struct uv_pipe_s *handle, int fd) +{ + int result; + if (result == 0) { + __coverity_escape__(fd); + } + return result; +} + +// Issue 2422 +// +// Teach coverity about jemalloc functions, so that it understands +// they are equivalent to malloc ones. + +void *je_malloc(size_t size) +{ + return __coverity_alloc__(size); +} + +void je_free(void *ptr) +{ + __coverity_free__(ptr); +} + +void *je_calloc(size_t count, size_t size) +{ + return je_malloc(count * size); +} + +void *je_realloc(void *ptr, size_t size) +{ + je_free(ptr); + return je_malloc(size); +} + +// Hint Coverity that adding item to d avoids losing track +// of the memory allocated for item. +typedef struct {} dictitem_T; +typedef struct {} dict_T; +int tv_dict_add(dict_T *const d, dictitem_T *const item) +{ + __coverity_escape__(item); +} diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index f2b75dca2a..e2f1f16635 100644 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -10,44 +10,72 @@ if(USE_GCOV) endif() endif() +if(WIN32) + # tell MinGW compiler to enable wmain + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -municode") +endif() + +set(TOUCHES_DIR ${PROJECT_BINARY_DIR}/touches) +set(GENERATOR_DIR ${CMAKE_CURRENT_LIST_DIR}/generators) set(GENERATED_DIR ${PROJECT_BINARY_DIR}/src/nvim/auto) -set(DISPATCH_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/gendispatch.lua) -file(GLOB API_HEADERS api/*.h) -file(GLOB MSGPACK_RPC_HEADERS msgpack_rpc/*.h) +set(API_DISPATCH_GENERATOR ${GENERATOR_DIR}/gen_api_dispatch.lua) +set(API_UI_EVENTS_GENERATOR ${GENERATOR_DIR}/gen_api_ui_events.lua) set(API_METADATA ${PROJECT_BINARY_DIR}/api_metadata.mpack) set(FUNCS_DATA ${PROJECT_BINARY_DIR}/funcs_data.mpack) -set(HEADER_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/gendeclarations.lua) +set(MSGPACK_LUA_C_BINDINGS ${GENERATED_DIR}/msgpack_lua_c_bindings.generated.c) +set(HEADER_GENERATOR ${GENERATOR_DIR}/gen_declarations.lua) set(GENERATED_INCLUDES_DIR ${PROJECT_BINARY_DIR}/include) set(GENERATED_API_DISPATCH ${GENERATED_DIR}/api/private/dispatch_wrappers.generated.h) set(GENERATED_FUNCS_METADATA ${GENERATED_DIR}/api/private/funcs_metadata.generated.h) +set(GENERATED_UI_EVENTS ${GENERATED_DIR}/ui_events.generated.h) +set(GENERATED_UI_EVENTS_CALL ${GENERATED_DIR}/ui_events_call.generated.h) +set(GENERATED_UI_EVENTS_REMOTE ${GENERATED_DIR}/ui_events_remote.generated.h) +set(GENERATED_UI_EVENTS_BRIDGE ${GENERATED_DIR}/ui_events_bridge.generated.h) +set(GENERATED_UI_EVENTS_METADATA ${GENERATED_DIR}/api/private/ui_events_metadata.generated.h) set(GENERATED_EX_CMDS_ENUM ${GENERATED_INCLUDES_DIR}/ex_cmds_enum.generated.h) set(GENERATED_EX_CMDS_DEFS ${GENERATED_DIR}/ex_cmds_defs.generated.h) -set(GENERATED_FUNCS_HASH_INPUT ${GENERATED_DIR}/funcs.generated.h.gperf) set(GENERATED_FUNCS ${GENERATED_DIR}/funcs.generated.h) set(GENERATED_EVENTS_ENUM ${GENERATED_INCLUDES_DIR}/auevents_enum.generated.h) set(GENERATED_EVENTS_NAMES_MAP ${GENERATED_DIR}/auevents_name_map.generated.h) set(GENERATED_OPTIONS ${GENERATED_DIR}/options.generated.h) -set(EX_CMDS_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/genex_cmds.lua) -set(FUNCS_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/geneval.lua) -set(EVENTS_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/gen_events.lua) -set(OPTIONS_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/genoptions.lua) -set(EVENTS_LIST_FILE ${PROJECT_SOURCE_DIR}/src/nvim/auevents.lua) -set(EX_CMDS_DEFS_FILE ${PROJECT_SOURCE_DIR}/src/nvim/ex_cmds.lua) -set(EVAL_DEFS_FILE ${PROJECT_SOURCE_DIR}/src/nvim/eval.lua) -set(OPTIONS_LIST_FILE ${PROJECT_SOURCE_DIR}/src/nvim/options.lua) -set(UNICODE_TABLES_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/genunicodetables.lua) +set(EX_CMDS_GENERATOR ${GENERATOR_DIR}/gen_ex_cmds.lua) +set(FUNCS_GENERATOR ${GENERATOR_DIR}/gen_eval.lua) +set(EVENTS_GENERATOR ${GENERATOR_DIR}/gen_events.lua) +set(OPTIONS_GENERATOR ${GENERATOR_DIR}/gen_options.lua) +set(UNICODE_TABLES_GENERATOR ${GENERATOR_DIR}/gen_unicode_tables.lua) set(UNICODE_DIR ${PROJECT_SOURCE_DIR}/unicode) -file(GLOB UNICODE_FILES ${UNICODE_DIR}/*.txt) set(GENERATED_UNICODE_TABLES ${GENERATED_DIR}/unicode_tables.generated.h) +set(VIM_MODULE_FILE ${GENERATED_DIR}/lua/vim_module.generated.h) +set(VIM_MODULE_SOURCE ${PROJECT_SOURCE_DIR}/src/nvim/lua/vim.lua) +set(CHAR_BLOB_GENERATOR ${GENERATOR_DIR}/gen_char_blob.lua) +set(LINT_SUPPRESS_FILE ${PROJECT_BINARY_DIR}/errors.json) +set(LINT_SUPPRESS_URL_BASE "https://raw.githubusercontent.com/neovim/doc/gh-pages/reports/clint") +set(LINT_SUPPRESS_URL "${LINT_SUPPRESS_URL_BASE}/errors.json") +set(LINT_PRG ${PROJECT_SOURCE_DIR}/src/clint.py) +set(DOWNLOAD_SCRIPT ${PROJECT_SOURCE_DIR}/cmake/Download.cmake) +set(LINT_SUPPRESSES_ROOT ${PROJECT_BINARY_DIR}/errors) +set(LINT_SUPPRESSES_URL "${LINT_SUPPRESS_URL_BASE}/errors.tar.gz") +set(LINT_SUPPRESSES_ARCHIVE ${LINT_SUPPRESSES_ROOT}/errors.tar.gz) +set(LINT_SUPPRESSES_TOUCH_FILE "${TOUCHES_DIR}/unpacked-clint-errors-archive") +set(LINT_SUPPRESSES_INSTALL_SCRIPT "${PROJECT_SOURCE_DIR}/cmake/InstallClintErrors.cmake") + +file(GLOB UNICODE_FILES ${UNICODE_DIR}/*.txt) +file(GLOB API_HEADERS api/*.h) +list(REMOVE_ITEM API_HEADERS ${CMAKE_CURRENT_LIST_DIR}/api/ui_events.in.h) +file(GLOB MSGPACK_RPC_HEADERS msgpack_rpc/*.h) include_directories(${GENERATED_DIR}) include_directories(${CACHED_GENERATED_DIR}) include_directories(${GENERATED_INCLUDES_DIR}) +file(MAKE_DIRECTORY ${TOUCHES_DIR}) file(MAKE_DIRECTORY ${GENERATED_DIR}) file(MAKE_DIRECTORY ${GENERATED_INCLUDES_DIR}) +file(MAKE_DIRECTORY ${LINT_SUPPRESSES_ROOT}) +file(MAKE_DIRECTORY ${LINT_SUPPRESSES_ROOT}/src) -file(GLOB NEOVIM_SOURCES *.c) +file(GLOB NVIM_SOURCES *.c) +file(GLOB NVIM_HEADERS *.h) foreach(subdir os @@ -57,6 +85,7 @@ foreach(subdir tui event eval + lua ) if(${subdir} MATCHES "tui" AND NOT FEAT_TUI) continue() @@ -65,18 +94,21 @@ foreach(subdir file(MAKE_DIRECTORY ${GENERATED_DIR}/${subdir}) file(MAKE_DIRECTORY ${GENERATED_INCLUDES_DIR}/${subdir}) file(GLOB sources ${subdir}/*.c) - list(APPEND NEOVIM_SOURCES ${sources}) + file(GLOB headers ${subdir}/*.h) + list(APPEND NVIM_SOURCES ${sources}) + list(APPEND NVIM_HEADERS ${headers}) endforeach() -file(GLOB_RECURSE NEOVIM_HEADERS *.h) file(GLOB UNIT_TEST_FIXTURES ${PROJECT_SOURCE_DIR}/test/unit/fixtures/*.c) # Sort file lists to ensure generated files are created in the same order from # build to build. -list(SORT NEOVIM_SOURCES) -list(SORT NEOVIM_HEADERS) +list(SORT NVIM_SOURCES) +list(SORT NVIM_HEADERS) + +list(APPEND LINT_NVIM_SOURCES ${NVIM_SOURCES} ${NVIM_HEADERS}) -foreach(sfile ${NEOVIM_SOURCES}) +foreach(sfile ${NVIM_SOURCES}) get_filename_component(f ${sfile} NAME) if(${f} MATCHES "^(regexp_nfa.c)$") list(APPEND to_remove ${sfile}) @@ -84,13 +116,15 @@ foreach(sfile ${NEOVIM_SOURCES}) if(WIN32 AND ${f} MATCHES "^(pty_process_unix.c)$") list(APPEND to_remove ${sfile}) endif() + if(NOT WIN32 AND ${f} MATCHES "^(pty_process_win.c)$") + list(APPEND to_remove ${sfile}) + endif() endforeach() -list(REMOVE_ITEM NEOVIM_SOURCES ${to_remove}) +list(REMOVE_ITEM NVIM_SOURCES ${to_remove}) # Legacy files that do not yet pass -Wconversion. set(CONV_SOURCES - buffer.c diff.c edit.c eval.c @@ -105,12 +139,13 @@ set(CONV_SOURCES screen.c search.c spell.c + spellfile.c syntax.c tag.c window.c) foreach(sfile ${CONV_SOURCES}) - if(NOT EXISTS "${PROJECT_SOURCE_DIR}/src/nvim/${sfile}") + if(NOT EXISTS "${CMAKE_CURRENT_LIST_DIR}/${sfile}") message(FATAL_ERROR "${sfile} doesn't exist (it was added to CONV_SOURCES)") endif() endforeach() @@ -144,7 +179,7 @@ if(CLANG_ASAN_UBSAN OR CLANG_MSAN OR CLANG_TSAN) endif() get_directory_property(gen_includes INCLUDE_DIRECTORIES) -foreach(gen_include ${gen_includes}) +foreach(gen_include ${gen_includes} ${LUA_PREFERRED_INCLUDE_DIRS}) list(APPEND gen_cflags "-I${gen_include}") endforeach() string(TOUPPER "${CMAKE_BUILD_TYPE}" build_type) @@ -152,12 +187,28 @@ separate_arguments(C_FLAGS_ARRAY UNIX_COMMAND ${CMAKE_C_FLAGS}) separate_arguments(C_FLAGS_${build_type}_ARRAY UNIX_COMMAND ${CMAKE_C_FLAGS_${build_type}}) set(gen_cflags ${gen_cflags} ${C_FLAGS_${build_type}_ARRAY} ${C_FLAGS_ARRAY}) -foreach(sfile ${NEOVIM_SOURCES} - "${PROJECT_SOURCE_DIR}/src/nvim/regexp_nfa.c" - ${GENERATED_API_DISPATCH}) +function(get_preproc_output varname iname) + if(MSVC) + set(${varname} /P /Fi${iname} PARENT_SCOPE) + else() + set(${varname} -E -o ${iname} PARENT_SCOPE) + endif() +endfunction() + +# NVIM_GENERATED_FOR_HEADERS: generated headers to be included in headers +# NVIM_GENERATED_FOR_SOURCES: generated headers to be included in sources +# NVIM_GENERATED_SOURCES: generated source files +# These lists must be mutually exclusive. +foreach(sfile ${NVIM_SOURCES} + "${CMAKE_CURRENT_LIST_DIR}/regexp_nfa.c" + ${GENERATED_API_DISPATCH} + "${GENERATED_UI_EVENTS_CALL}" + "${GENERATED_UI_EVENTS_REMOTE}" + "${GENERATED_UI_EVENTS_BRIDGE}" + ) get_filename_component(full_d ${sfile} PATH) - file(RELATIVE_PATH d "${PROJECT_SOURCE_DIR}/src/nvim" "${full_d}") - if(${d} MATCHES "^([.][.]|auto/)") + file(RELATIVE_PATH d "${CMAKE_CURRENT_LIST_DIR}" "${full_d}") + if(${d} MATCHES "^[.][.]|auto/") file(RELATIVE_PATH d "${GENERATED_DIR}" "${full_d}") endif() get_filename_component(f ${sfile} NAME) @@ -166,26 +217,22 @@ foreach(sfile ${NEOVIM_SOURCES} set(f "${d}/${f}") set(r "${d}/${r}") endif() - set(gf1 "${GENERATED_DIR}/${r}.c.generated.h") - set(gf2 "${GENERATED_INCLUDES_DIR}/${r}.h.generated.h") - set(gf3 "${GENERATED_DIR}/${r}.i") + set(gf_c_h "${GENERATED_DIR}/${r}.c.generated.h") + set(gf_h_h "${GENERATED_INCLUDES_DIR}/${r}.h.generated.h") + set(gf_i "${GENERATED_DIR}/${r}.i") - if(MSVC) - set(PREPROC_OUTPUT /P /Fi${gf3}) - else() - set(PREPROC_OUTPUT -E -o ${gf3}) - endif() + get_preproc_output(PREPROC_OUTPUT ${gf_i}) add_custom_command( - OUTPUT "${gf1}" "${gf2}" + OUTPUT "${gf_c_h}" "${gf_h_h}" COMMAND ${CMAKE_C_COMPILER} ${sfile} ${PREPROC_OUTPUT} ${gen_cflags} ${C_FLAGS_ARRAY} - COMMAND "${LUA_PRG}" "${HEADER_GENERATOR}" "${sfile}" "${gf1}" "${gf2}" "${gf3}" + COMMAND "${LUA_PRG}" "${HEADER_GENERATOR}" "${sfile}" "${gf_c_h}" "${gf_h_h}" "${gf_i}" DEPENDS "${HEADER_GENERATOR}" "${sfile}" ) - list(APPEND NEOVIM_GENERATED_SOURCES "${gf1}") - list(APPEND NEOVIM_GENERATED_SOURCES "${gf2}") + list(APPEND NVIM_GENERATED_FOR_SOURCES "${gf_c_h}") + list(APPEND NVIM_GENERATED_FOR_HEADERS "${gf_h_h}") if(${d} MATCHES "^api$" AND NOT ${f} MATCHES "^api/helpers.c$") - list(APPEND API_HEADERS ${gf2}) + list(APPEND API_HEADERS ${gf_h_h}) endif() endforeach() @@ -198,33 +245,74 @@ add_custom_command(OUTPUT ${GENERATED_UNICODE_TABLES} ${UNICODE_FILES} ) -add_custom_command(OUTPUT ${GENERATED_API_DISPATCH} ${GENERATED_FUNCS_METADATA} - ${API_METADATA} - COMMAND ${LUA_PRG} ${DISPATCH_GENERATOR} ${CMAKE_CURRENT_LIST_DIR} - ${API_HEADERS} ${GENERATED_API_DISPATCH} +add_custom_command( + OUTPUT ${GENERATED_API_DISPATCH} ${GENERATED_FUNCS_METADATA} + ${API_METADATA} ${MSGPACK_LUA_C_BINDINGS} + COMMAND ${LUA_PRG} ${API_DISPATCH_GENERATOR} ${CMAKE_CURRENT_LIST_DIR} + ${GENERATED_API_DISPATCH} ${GENERATED_FUNCS_METADATA} ${API_METADATA} + ${MSGPACK_LUA_C_BINDINGS} + ${API_HEADERS} DEPENDS ${API_HEADERS} ${MSGPACK_RPC_HEADERS} - ${DISPATCH_GENERATOR} + ${API_DISPATCH_GENERATOR} ${CMAKE_CURRENT_LIST_DIR}/api/dispatch_deprecated.lua ) -list(APPEND NEOVIM_GENERATED_SOURCES - "${PROJECT_BINARY_DIR}/config/auto/pathdef.c" - "${GENERATED_API_DISPATCH}" +add_custom_command( + OUTPUT ${VIM_MODULE_FILE} + COMMAND ${LUA_PRG} ${CHAR_BLOB_GENERATOR} ${VIM_MODULE_SOURCE} + ${VIM_MODULE_FILE} vim_module + DEPENDS + ${CHAR_BLOB_GENERATOR} + ${VIM_MODULE_SOURCE} +) + +list(APPEND NVIM_GENERATED_SOURCES + "${MSGPACK_LUA_C_BINDINGS}" +) + +add_custom_command( + OUTPUT ${GENERATED_UI_EVENTS} + ${GENERATED_UI_EVENTS_CALL} + ${GENERATED_UI_EVENTS_REMOTE} + ${GENERATED_UI_EVENTS_BRIDGE} + ${GENERATED_UI_EVENTS_METADATA} + COMMAND ${LUA_PRG} ${API_UI_EVENTS_GENERATOR} ${CMAKE_CURRENT_LIST_DIR} + ${CMAKE_CURRENT_LIST_DIR}/api/ui_events.in.h + ${GENERATED_UI_EVENTS} + ${GENERATED_UI_EVENTS_CALL} + ${GENERATED_UI_EVENTS_REMOTE} + ${GENERATED_UI_EVENTS_BRIDGE} + ${GENERATED_UI_EVENTS_METADATA} + DEPENDS + ${API_UI_EVENTS_GENERATOR} + ${CMAKE_CURRENT_LIST_DIR}/api/ui_events.in.h +) + +list(APPEND NVIM_GENERATED_FOR_HEADERS "${GENERATED_EX_CMDS_ENUM}" - "${GENERATED_EX_CMDS_DEFS}" "${GENERATED_EVENTS_ENUM}" +) + +list(APPEND NVIM_GENERATED_FOR_SOURCES + "${GENERATED_API_DISPATCH}" + "${GENERATED_EX_CMDS_DEFS}" "${GENERATED_EVENTS_NAMES_MAP}" "${GENERATED_OPTIONS}" "${GENERATED_UNICODE_TABLES}" + "${VIM_MODULE_FILE}" +) + +list(APPEND NVIM_GENERATED_SOURCES + "${PROJECT_BINARY_DIR}/config/auto/pathdef.c" ) add_custom_command(OUTPUT ${GENERATED_EX_CMDS_ENUM} ${GENERATED_EX_CMDS_DEFS} COMMAND ${LUA_PRG} ${EX_CMDS_GENERATOR} - ${PROJECT_SOURCE_DIR}/src/nvim ${GENERATED_INCLUDES_DIR} ${GENERATED_DIR} - DEPENDS ${EX_CMDS_GENERATOR} ${EX_CMDS_DEFS_FILE} + ${CMAKE_CURRENT_LIST_DIR} ${GENERATED_INCLUDES_DIR} ${GENERATED_DIR} + DEPENDS ${EX_CMDS_GENERATOR} ${CMAKE_CURRENT_LIST_DIR}/ex_cmds.lua ) if(NOT GPERF_PRG) @@ -232,26 +320,34 @@ if(NOT GPERF_PRG) endif() add_custom_command(OUTPUT ${GENERATED_FUNCS} ${FUNCS_DATA} COMMAND ${LUA_PRG} ${FUNCS_GENERATOR} - ${PROJECT_SOURCE_DIR}/src/nvim ${GENERATED_DIR} ${API_METADATA} ${FUNCS_DATA} + ${CMAKE_CURRENT_LIST_DIR} ${GENERATED_DIR} ${API_METADATA} ${FUNCS_DATA} COMMAND ${GPERF_PRG} - ${GENERATED_FUNCS_HASH_INPUT} --output-file=${GENERATED_FUNCS} - DEPENDS ${FUNCS_GENERATOR} ${EVAL_DEFS_FILE} ${API_METADATA} + ${GENERATED_DIR}/funcs.generated.h.gperf --output-file=${GENERATED_FUNCS} + DEPENDS ${FUNCS_GENERATOR} ${CMAKE_CURRENT_LIST_DIR}/eval.lua ${API_METADATA} ) -list(APPEND NEOVIM_GENERATED_SOURCES +list(APPEND NVIM_GENERATED_FOR_SOURCES "${GENERATED_FUNCS}") add_custom_command(OUTPUT ${GENERATED_EVENTS_ENUM} ${GENERATED_EVENTS_NAMES_MAP} COMMAND ${LUA_PRG} ${EVENTS_GENERATOR} - ${PROJECT_SOURCE_DIR}/src/nvim ${GENERATED_EVENTS_ENUM} ${GENERATED_EVENTS_NAMES_MAP} - DEPENDS ${EVENTS_GENERATOR} ${EVENTS_LIST_FILE} + ${CMAKE_CURRENT_LIST_DIR} ${GENERATED_EVENTS_ENUM} ${GENERATED_EVENTS_NAMES_MAP} + DEPENDS ${EVENTS_GENERATOR} ${CMAKE_CURRENT_LIST_DIR}/auevents.lua ) add_custom_command(OUTPUT ${GENERATED_OPTIONS} COMMAND ${LUA_PRG} ${OPTIONS_GENERATOR} - ${PROJECT_SOURCE_DIR}/src/nvim ${GENERATED_OPTIONS} - DEPENDS ${OPTIONS_GENERATOR} ${OPTIONS_LIST_FILE} + ${CMAKE_CURRENT_LIST_DIR} ${GENERATED_OPTIONS} + DEPENDS ${OPTIONS_GENERATOR} ${CMAKE_CURRENT_LIST_DIR}/options.lua ) +# NVIM_GENERATED_FOR_SOURCES and NVIM_GENERATED_FOR_HEADERS must be mutually exclusive. +foreach(hfile ${NVIM_GENERATED_FOR_HEADERS}) + list(FIND NVIM_GENERATED_FOR_SOURCES ${hfile} hfile_idx) + if(NOT ${hfile_idx} EQUAL -1) + message(FATAL_ERROR "File included in both NVIM_GENERATED_FOR_HEADERS and NVIM_GENERATED_FOR_SOURCES") + endif() +endforeach() + # Our dependencies come first. if (LibIntl_FOUND) @@ -262,6 +358,10 @@ if(Iconv_LIBRARIES) list(APPEND NVIM_LINK_LIBRARIES ${Iconv_LIBRARIES}) endif() +if(WIN32) + list(APPEND NVIM_LINK_LIBRARIES ${WINPTY_LIBRARIES}) +endif() + # Put these last on the link line, since multiple things may depend on them. list(APPEND NVIM_LINK_LIBRARIES ${LIBUV_LIBRARIES} @@ -279,31 +379,120 @@ if(UNIX) ) endif() -set(NVIM_EXEC_LINK_LIBRARIES ${NVIM_LINK_LIBRARIES}) +set(NVIM_EXEC_LINK_LIBRARIES ${NVIM_LINK_LIBRARIES} ${LUA_PREFERRED_LIBRARIES}) + +if(CMAKE_VERSION VERSION_LESS "2.8.8") + # Use include_directories() because INCLUDE_DIRECTORIES target property + # is not supported + include_directories(${LUA_PREFERRED_INCLUDE_DIRS}) +endif() # Don't use jemalloc in the unit test library. if(JEMALLOC_FOUND) list(APPEND NVIM_EXEC_LINK_LIBRARIES ${JEMALLOC_LIBRARIES}) endif() -add_executable(nvim ${NEOVIM_GENERATED_SOURCES} ${NEOVIM_SOURCES} - ${NEOVIM_HEADERS}) +add_executable(nvim ${NVIM_GENERATED_FOR_SOURCES} ${NVIM_GENERATED_FOR_HEADERS} + ${NVIM_GENERATED_SOURCES} ${NVIM_SOURCES} ${NVIM_HEADERS}) target_link_libraries(nvim ${NVIM_EXEC_LINK_LIBRARIES}) install_helper(TARGETS nvim) +set_property(TARGET nvim APPEND PROPERTY + INCLUDE_DIRECTORIES ${LUA_PREFERRED_INCLUDE_DIRS}) + if(WIN32) - # Copy DLLs to bin/ and install them along with nvim - add_custom_target(nvim_dll_deps ALL DEPENDS nvim + # Copy DLLs and third-party tools to bin/ and install them along with nvim + add_custom_target(nvim_runtime_deps ALL + COMMAND ${CMAKE_COMMAND} -E copy_directory ${PROJECT_BINARY_DIR}/windows_runtime_deps/ + ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) + install(DIRECTORY ${PROJECT_BINARY_DIR}/windows_runtime_deps/ + DESTINATION ${CMAKE_INSTALL_BINDIR}) + + add_custom_target(nvim_dll_deps DEPENDS nvim COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_BINARY_DIR}/windows_runtime_deps COMMAND ${CMAKE_COMMAND} "-DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH}" -DBINARY="${PROJECT_BINARY_DIR}/bin/nvim${CMAKE_EXECUTABLE_SUFFIX}" -DDST=${PROJECT_BINARY_DIR}/windows_runtime_deps - -P ${PROJECT_SOURCE_DIR}/cmake/WindowsDllCopy.cmake - COMMAND ${CMAKE_COMMAND} -E copy_directory ${PROJECT_BINARY_DIR}/windows_runtime_deps/ - ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) - install(DIRECTORY ${PROJECT_BINARY_DIR}/windows_runtime_deps/ - DESTINATION ${CMAKE_INSTALL_BINDIR}) + -P ${PROJECT_SOURCE_DIR}/cmake/WindowsDllCopy.cmake) + add_dependencies(nvim_runtime_deps nvim_dll_deps) + + add_custom_target(external_blobs + COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_BINARY_DIR}/windows_runtime_deps/platforms + + COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/ca-bundle.crt" ${PROJECT_BINARY_DIR}/windows_runtime_deps/ + COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/cat.exe" ${PROJECT_BINARY_DIR}/windows_runtime_deps/ + COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/curl.exe" ${PROJECT_BINARY_DIR}/windows_runtime_deps/ + COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/diff.exe" ${PROJECT_BINARY_DIR}/windows_runtime_deps/ + COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/tee.exe" ${PROJECT_BINARY_DIR}/windows_runtime_deps/ + COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/tidy.exe" ${PROJECT_BINARY_DIR}/windows_runtime_deps/ + COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/win32yank.exe" ${PROJECT_BINARY_DIR}/windows_runtime_deps/ + COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/winpty-agent.exe" ${PROJECT_BINARY_DIR}/windows_runtime_deps/ + + COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/D3Dcompiler_47.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/ + COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/libEGL.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/ + COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/libgcc_s_dw2-1.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/ + COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/libGLESV2.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/ + COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/libstdc++-6.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/ + COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/libwinpthread-1.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/ + COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/nvim-qt.exe" ${PROJECT_BINARY_DIR}/windows_runtime_deps/ + COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/Qt5Core.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/ + COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/Qt5Gui.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/ + COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/Qt5Network.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/ + COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/Qt5Svg.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/ + COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/Qt5Widgets.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/ + COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/winpty.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/ + + COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/platforms/qwindows.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/platforms/ + ) + add_dependencies(nvim_runtime_deps external_blobs) +endif() + +add_library( + libnvim + STATIC + EXCLUDE_FROM_ALL + ${NVIM_SOURCES} ${NVIM_GENERATED_SOURCES} + ${NVIM_HEADERS} ${NVIM_GENERATED_FOR_SOURCES} ${NVIM_GENERATED_FOR_HEADERS} +) +set_property(TARGET libnvim APPEND PROPERTY + INCLUDE_DIRECTORIES ${LUA_PREFERRED_INCLUDE_DIRS}) +set_target_properties( + libnvim + PROPERTIES + POSITION_INDEPENDENT_CODE ON + OUTPUT_NAME nvim +) +set_property( + TARGET libnvim + APPEND_STRING PROPERTY COMPILE_FLAGS " -DMAKE_LIB " +) + +if(LUAJIT_FOUND) + set(NVIM_TEST_LINK_LIBRARIES ${NVIM_LINK_LIBRARIES} ${LUAJIT_LIBRARIES}) + add_library( + nvim-test + MODULE + EXCLUDE_FROM_ALL + ${NVIM_SOURCES} ${NVIM_GENERATED_SOURCES} + ${NVIM_HEADERS} ${NVIM_GENERATED_FOR_SOURCES} ${NVIM_GENERATED_FOR_HEADERS} + ${UNIT_TEST_FIXTURES} + ) + target_link_libraries(nvim-test ${NVIM_TEST_LINK_LIBRARIES}) + target_link_libraries(libnvim ${NVIM_TEST_LINK_LIBRARIES}) + set_property( + TARGET nvim-test + APPEND PROPERTY INCLUDE_DIRECTORIES ${LUAJIT_INCLUDE_DIRS} + ) + set_target_properties( + nvim-test + PROPERTIES + POSITION_INDEPENDENT_CODE ON + ) + set_property( + TARGET nvim-test + APPEND_STRING PROPERTY COMPILE_FLAGS " -DUNIT_TESTING " + ) endif() if(CLANG_ASAN_UBSAN) @@ -330,17 +519,111 @@ elseif(CLANG_TSAN) set_property(TARGET nvim APPEND_STRING PROPERTY LINK_FLAGS "-fsanitize=thread ") endif() -add_library(libnvim STATIC EXCLUDE_FROM_ALL ${NEOVIM_GENERATED_SOURCES} - ${NEOVIM_SOURCES} ${NEOVIM_HEADERS}) -target_link_libraries(libnvim ${NVIM_LINK_LIBRARIES}) -set_target_properties(libnvim PROPERTIES - POSITION_INDEPENDENT_CODE ON - OUTPUT_NAME nvim) -set_property(TARGET libnvim APPEND_STRING PROPERTY COMPILE_FLAGS " -DMAKE_LIB ") - -add_library(nvim-test MODULE EXCLUDE_FROM_ALL ${NEOVIM_GENERATED_SOURCES} - ${NEOVIM_SOURCES} ${UNIT_TEST_FIXTURES} ${NEOVIM_HEADERS}) -target_link_libraries(nvim-test ${NVIM_LINK_LIBRARIES}) -set_property(TARGET nvim-test APPEND_STRING PROPERTY COMPILE_FLAGS -DUNIT_TESTING) +function(get_test_target prefix sfile relative_path_var target_var) + get_filename_component(full_d "${sfile}" PATH) + file(RELATIVE_PATH d "${PROJECT_SOURCE_DIR}/src/nvim" "${full_d}") + if(d MATCHES "^[.][.]") + file(RELATIVE_PATH d "${GENERATED_DIR}" "${full_d}") + endif() + get_filename_component(r "${sfile}" NAME) + if(NOT d MATCHES "^[.]?$") + set(r "${d}/${r}") + endif() + string(REGEX REPLACE "[/.]" "-" suffix "${r}") + set(${relative_path_var} ${r} PARENT_SCOPE) + if(prefix STREQUAL "") + set(${target_var} "${suffix}" PARENT_SCOPE) + else() + set(${target_var} "${prefix}-${suffix}" PARENT_SCOPE) + endif() +endfunction() + +set(NO_SINGLE_CHECK_HEADERS + os/win_defs.h + os/pty_process_win.h + regexp_defs.h + syntax_defs.h + terminal.h + undo.h + undo_defs.h +) +foreach(hfile ${NVIM_HEADERS}) + get_test_target(test-includes "${hfile}" relative_path texe) + + if(NOT ${hfile} MATCHES "[.](c|in)[.]h$") + set(tsource "${GENERATED_DIR}/${relative_path}.test-include.c") + write_file("${tsource}" "#include \"${hfile}\"\nint main(int argc, char **argv) { return 0; }") + add_executable( + ${texe} + EXCLUDE_FROM_ALL + ${tsource} ${NVIM_HEADERS} ${NVIM_GENERATED_FOR_HEADERS}) + set_property( + TARGET ${texe} + APPEND PROPERTY INCLUDE_DIRECTORIES ${LUA_PREFERRED_INCLUDE_DIRS} + ) + + list(FIND NO_SINGLE_CHECK_HEADERS "${relative_path}" hfile_exclude_idx) + if(${hfile_exclude_idx} EQUAL -1) + list(APPEND HEADER_CHECK_TARGETS ${texe}) + endif() + endif() +endforeach() +add_custom_target(check-single-includes DEPENDS ${HEADER_CHECK_TARGETS}) + +function(add_download output url allow_failure) + add_custom_command( + OUTPUT "${output}" + COMMAND + ${CMAKE_COMMAND} + -DURL=${url} -DFILE=${output} + -DALLOW_FAILURE=${allow_failure} + -P ${DOWNLOAD_SCRIPT} + DEPENDS ${DOWNLOAD_SCRIPT} + ) +endfunction() + +add_download(${LINT_SUPPRESSES_ARCHIVE} ${LINT_SUPPRESSES_URL} off) + +add_custom_command( + OUTPUT ${LINT_SUPPRESSES_TOUCH_FILE} + WORKING_DIRECTORY ${LINT_SUPPRESSES_ROOT}/src + COMMAND ${CMAKE_COMMAND} -E tar xfz ${LINT_SUPPRESSES_ARCHIVE} + COMMAND + ${CMAKE_COMMAND} + -DTARGET=${LINT_SUPPRESSES_ROOT} + -P ${LINT_SUPPRESSES_INSTALL_SCRIPT} + COMMAND ${CMAKE_COMMAND} -E touch ${LINT_SUPPRESSES_TOUCH_FILE} + DEPENDS + ${LINT_SUPPRESSES_ARCHIVE} ${LINT_SUPPRESSES_INSTALL_SCRIPT} +) + +add_download(${LINT_SUPPRESS_FILE} ${LINT_SUPPRESS_URL} off) + +set(LINT_NVIM_REL_SOURCES) +foreach(sfile ${LINT_NVIM_SOURCES}) + get_test_target("" "${sfile}" r suffix) + set(suppress_file ${LINT_SUPPRESSES_ROOT}/${suffix}.json) + set(suppress_url "${LINT_SUPPRESS_URL_BASE}/${suffix}.json") + set(rsfile src/nvim/${r}) + set(touch_file "${TOUCHES_DIR}/ran-clint-${suffix}") + add_custom_command( + OUTPUT ${touch_file} + COMMAND ${LINT_PRG} --suppress-errors=${suppress_file} ${rsfile} + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} + COMMAND ${CMAKE_COMMAND} -E touch ${touch_file} + DEPENDS ${LINT_PRG} ${sfile} ${LINT_SUPPRESSES_TOUCH_FILE} + ) + list(APPEND LINT_TARGETS ${touch_file}) + list(APPEND LINT_NVIM_REL_SOURCES ${rsfile}) +endforeach() +add_custom_target(clint DEPENDS ${LINT_TARGETS}) + +add_custom_target( + clint-full + COMMAND + ${LINT_PRG} --suppress-errors=${LINT_SUPPRESS_FILE} ${LINT_NVIM_REL_SOURCES} + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} + DEPENDS ${LINT_PRG} ${LINT_NVIM_SOURCES} ${LINT_SUPPRESS_FILE} +) add_subdirectory(po) diff --git a/src/nvim/README.md b/src/nvim/README.md index f16c6de12f..0caf71e2c5 100644 --- a/src/nvim/README.md +++ b/src/nvim/README.md @@ -1,23 +1,43 @@ -## Source code overview +Nvim core source +================ -Since Neovim has inherited most code from Vim, some information in [its -README](https://raw.githubusercontent.com/vim/vim/master/src/README.txt) still -applies. +Module-specific details are documented at the top of each module (`terminal.c`, +`screen.c`, ...). -This document aims to give a high level overview of how Neovim works internally, -focusing on parts that are different from Vim. Currently this is still a work in -progress, especially because I have avoided adding too many details about parts -that are constantly changing. As the code becomes more organized and stable, -this document will be updated to reflect the changes. +See `:help development` for more guidelines. -If you are looking for module-specific details, it is best to read the source -code. Some files are extensively commented at the top (e.g. terminal.c, -screen.c). +Logs +---- -### Top-level program loops +Low-level log messages sink to `$NVIM_LOG_FILE`. -First let's understand what a Vim-like program does by analyzing the workflow of -a typical editing session: +You can use `LOG_CALLSTACK();` anywhere in the source to log the current +stacktrace. To log in an alternate file, e.g. stderr, use +`LOG_CALLSTACK_TO_FILE(FILE*)`. (Currently Linux-only.) + +UI events are logged at level 0 (`DEBUG_LOG_LEVEL`). + + rm -rf build/ + make CMAKE_EXTRA_FLAGS="-DMIN_LOG_LEVEL=0" + +Filename conventions +-------------------- + +The source files use extensions to hint about their purpose. + +- `*.c`, `*.generated.c` - full C files, with all includes, etc. +- `*.c.h` - parametrized C files, contain all necessary includes, but require + defining macros before actually using. Example: `typval_encode.c.h` +- `*.h` - full headers, with all includes. Does *not* apply to `*.generated.h`. +- `*.h.generated.h` - exported functionsโ declarations. +- `*.c.generated.h` - static functionsโ declarations. + +Nvim lifecycle +-------------- + +Following describes how Nvim processes input. + +Consider a typical Vim-like editing session: 01. Vim dispays the welcome screen 02. User types: `:` @@ -41,16 +61,14 @@ a typical editing session: 21. User types: `word<ESC>` 22. Vim inserts "word" at the beginning and returns to normal mode -Note that we have split user actions into sequences of inputs that change the -state of the editor. While there's no documentation about a "g command -mode" (step 16), internally it is implemented similarly to "operator-pending -mode". +Note that we split user actions into sequences of inputs that change the state +of the editor. While there's no documentation about a "g command mode" (step +16), internally it is implemented similarly to "operator-pending mode". -From this we can see that Vim has the behavior of a input-driven state -machine (more specifically, a pushdown automaton since it requires a stack for +From this we can see that Vim has the behavior of an input-driven state machine +(more specifically, a pushdown automaton since it requires a stack for transitioning back from states). Assuming each state has a callback responsible -for handling keys, this pseudocode (a python-like language) shows a good -representation of the main program loop: +for handling keys, this pseudocode represents the main program loop: ```py def state_enter(state_callback, data): @@ -126,12 +144,11 @@ def insert_state(data, key): return true ``` -While the actual code is much more complicated, the above gives an idea of how -Neovim is organized internally. Some states like the `g_command_state` or -`get_operator_count_state` do not have a dedicated `state_enter` callback, but -are implicitly embedded into other states (this will change later as we continue -the refactoring effort). To start reading the actual code, here's the -recommended order: +The above gives an idea of how Nvim is organized internally. Some states like +the `g_command_state` or `get_operator_count_state` do not have a dedicated +`state_enter` callback, but are implicitly embedded into other states (this +will change later as we continue the refactoring effort). To start reading the +actual code, here's the recommended order: 1. `state_enter()` function (state.c). This is the actual program loop, note that a `VimState` structure is used, which contains function pointers @@ -152,16 +169,17 @@ modes managed by the `state_enter` loop: - insert mode: `insert_{enter,check,execute}()`(`edit.c`) - terminal mode: `terminal_{enter,execute}()`(`terminal.c`) -### Async event support +Async event support +------------------- -One of the features Neovim added is the support for handling arbitrary +One of the features Nvim added is the support for handling arbitrary asynchronous events, which can include: -- msgpack-rpc requests +- RPC requests - job control callbacks -- timers (not implemented yet but the support code is already there) +- timers -Neovim implements this functionality by entering another event loop while +Nvim implements this functionality by entering another event loop while waiting for characters, so instead of: ```py @@ -171,7 +189,7 @@ def state_enter(state_callback, data): while state_callback(data, key) # invoke the callback for the current state ``` -Neovim program loop is more like: +Nvim program loop is more like: ```py def state_enter(state_callback, data): @@ -182,9 +200,9 @@ def state_enter(state_callback, data): where `event` is something the operating system delivers to us, including (but not limited to) user input. The `read_next_event()` part is internally -implemented by libuv, the platform layer used by Neovim. +implemented by libuv, the platform layer used by Nvim. -Since Neovim inherited its code from Vim, the states are not prepared to receive +Since Nvim inherited its code from Vim, the states are not prepared to receive "arbitrary events", so we use a special key to represent those (When a state receives an "arbitrary event", it normally doesn't do anything other update the screen). diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index eaaae943d2..82de8fd4a2 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + // Much of this code was adapted from 'if_py_both.h' from the original // vim source #include <stdbool.h> @@ -32,6 +35,7 @@ /// @param[out] err Error details, if any /// @return Line count Integer nvim_buf_line_count(Buffer buffer, Error *err) + FUNC_API_SINCE(1) { buf_T *buf = find_buffer_by_handle(buffer, err); @@ -61,7 +65,7 @@ String buffer_get_line(Buffer buffer, Integer index, Error *err) index = convert_index(index); Array slice = nvim_buf_get_lines(0, buffer, index, index+1, true, err); - if (!err->set && slice.size) { + if (!ERROR_SET(err) && slice.size) { rv = slice.items[0].data.string; } @@ -132,7 +136,6 @@ ArrayOf(String) buffer_get_line_slice(Buffer buffer, return nvim_buf_get_lines(0, buffer, start , end, false, err); } - /// Retrieves a line range from the buffer /// /// Indexing is zero-based, end-exclusive. Negative indices are interpreted @@ -154,6 +157,7 @@ ArrayOf(String) nvim_buf_get_lines(uint64_t channel_id, Integer end, Boolean strict_indexing, Error *err) + FUNC_API_SINCE(1) { Array rv = ARRAY_DICT_INIT; buf_T *buf = find_buffer_by_handle(buffer, err); @@ -167,7 +171,7 @@ ArrayOf(String) nvim_buf_get_lines(uint64_t channel_id, end = normalize_index(buf, end, &oob); if (strict_indexing && oob) { - api_set_error(err, Validation, _("Index out of bounds")); + api_set_error(err, kErrorTypeValidation, "Index out of bounds"); return rv; } @@ -183,7 +187,7 @@ ArrayOf(String) nvim_buf_get_lines(uint64_t channel_id, int64_t lnum = start + (int64_t)i; if (lnum > LONG_MAX) { - api_set_error(err, Validation, _("Line index is too high")); + api_set_error(err, kErrorTypeValidation, "Line index is too high"); goto end; } @@ -191,7 +195,7 @@ ArrayOf(String) nvim_buf_get_lines(uint64_t channel_id, Object str = STRING_OBJ(cstr_to_string(bufstr)); // Vim represents NULs as NLs, but this may confuse clients. - if (channel_id != INTERNAL_CALL) { + if (channel_id != VIML_INTERNAL_CALL) { strchrsub(str.data.string.data, '\n', '\0'); } @@ -199,7 +203,7 @@ ArrayOf(String) nvim_buf_get_lines(uint64_t channel_id, } end: - if (err->set) { + if (ERROR_SET(err)) { for (size_t i = 0; i < rv.size; i++) { xfree(rv.items[i].data.string.data); } @@ -266,6 +270,7 @@ void nvim_buf_set_lines(uint64_t channel_id, Boolean strict_indexing, ArrayOf(String) replacement, // NOLINT Error *err) + FUNC_API_SINCE(1) { buf_T *buf = find_buffer_by_handle(buffer, err); @@ -278,54 +283,58 @@ void nvim_buf_set_lines(uint64_t channel_id, end = normalize_index(buf, end, &oob); if (strict_indexing && oob) { - api_set_error(err, Validation, _("Index out of bounds")); + api_set_error(err, kErrorTypeValidation, "Index out of bounds"); return; } if (start > end) { api_set_error(err, - Validation, - _("Argument \"start\" is higher than \"end\"")); + kErrorTypeValidation, + "Argument \"start\" is higher than \"end\""); return; } - buf_T *save_curbuf = NULL; + for (size_t i = 0; i < replacement.size; i++) { + if (replacement.items[i].type != kObjectTypeString) { + api_set_error(err, + kErrorTypeValidation, + "All items in the replacement array must be strings"); + return; + } + // Disallow newlines in the middle of the line. + if (channel_id != VIML_INTERNAL_CALL) { + const String l = replacement.items[i].data.string; + if (memchr(l.data, NL, l.size)) { + api_set_error(err, kErrorTypeValidation, + "String cannot contain newlines"); + return; + } + } + } + win_T *save_curwin = NULL; tabpage_T *save_curtab = NULL; size_t new_len = replacement.size; size_t old_len = (size_t)(end - start); - ssize_t extra = 0; // lines added to text, can be negative + ptrdiff_t extra = 0; // lines added to text, can be negative char **lines = (new_len != 0) ? xcalloc(new_len, sizeof(char *)) : NULL; for (size_t i = 0; i < new_len; i++) { - if (replacement.items[i].type != kObjectTypeString) { - api_set_error(err, - Validation, - _("All items in the replacement array must be strings")); - goto end; - } - - String l = replacement.items[i].data.string; + const String l = replacement.items[i].data.string; - // Fill lines[i] with l's contents. Disallow newlines in the middle of a - // line and convert NULs to newlines to avoid truncation. - lines[i] = xmallocz(l.size); - for (size_t j = 0; j < l.size; j++) { - if (l.data[j] == '\n' && channel_id != INTERNAL_CALL) { - api_set_error(err, Exception, _("string cannot contain newlines")); - new_len = i + 1; - goto end; - } - lines[i][j] = (char) (l.data[j] == '\0' ? '\n' : l.data[j]); - } + // Fill lines[i] with l's contents. Convert NULs to newlines as required by + // NL-used-for-NUL. + lines[i] = xmemdupz(l.data, l.size); + memchrsub(lines[i], NUL, NL, l.size); } try_start(); + bufref_T save_curbuf = { NULL, 0, 0 }; switch_to_win_for_buf(buf, &save_curwin, &save_curtab, &save_curbuf); if (u_save((linenr_T)(start - 1), (linenr_T)end) == FAIL) { - api_set_error(err, Exception, _("Failed to save undo information")); + api_set_error(err, kErrorTypeException, "Failed to save undo information"); goto end; } @@ -335,13 +344,13 @@ void nvim_buf_set_lines(uint64_t channel_id, size_t to_delete = (new_len < old_len) ? (size_t)(old_len - new_len) : 0; for (size_t i = 0; i < to_delete; i++) { if (ml_delete((linenr_T)start, false) == FAIL) { - api_set_error(err, Exception, _("Failed to delete line")); + api_set_error(err, kErrorTypeException, "Failed to delete line"); goto end; } } - if ((ssize_t)to_delete > 0) { - extra -= (ssize_t)to_delete; + if (to_delete > 0) { + extra -= (ptrdiff_t)to_delete; } // For as long as possible, replace the existing old_len with the @@ -352,12 +361,12 @@ void nvim_buf_set_lines(uint64_t channel_id, int64_t lnum = start + (int64_t)i; if (lnum > LONG_MAX) { - api_set_error(err, Validation, _("Index value is too high")); + api_set_error(err, kErrorTypeValidation, "Index value is too high"); goto end; } if (ml_replace((linenr_T)lnum, (char_u *)lines[i], false) == FAIL) { - api_set_error(err, Exception, _("Failed to replace line")); + api_set_error(err, kErrorTypeException, "Failed to replace line"); goto end; } // Mark lines that haven't been passed to the buffer as they need @@ -370,12 +379,12 @@ void nvim_buf_set_lines(uint64_t channel_id, int64_t lnum = start + (int64_t)i - 1; if (lnum > LONG_MAX) { - api_set_error(err, Validation, _("Index value is too high")); + api_set_error(err, kErrorTypeValidation, "Index value is too high"); goto end; } if (ml_append((linenr_T)lnum, (char_u *)lines[i], 0, false) == FAIL) { - api_set_error(err, Exception, _("Failed to insert line")); + api_set_error(err, kErrorTypeException, "Failed to insert line"); goto end; } @@ -389,14 +398,14 @@ void nvim_buf_set_lines(uint64_t channel_id, // changed range, and move any in the remainder of the buffer. // Only adjust marks if we managed to switch to a window that holds // the buffer, otherwise line numbers will be invalid. - if (save_curbuf == NULL) { - mark_adjust((linenr_T)start, (linenr_T)(end - 1), MAXLNUM, extra); + if (save_curbuf.br_buf == NULL) { + mark_adjust((linenr_T)start, (linenr_T)(end - 1), MAXLNUM, extra, false); } - changed_lines((linenr_T)start, 0, (linenr_T)end, extra); + changed_lines((linenr_T)start, 0, (linenr_T)end, (long)extra); - if (buf == curbuf) { - fix_cursor((linenr_T)start, (linenr_T)end, extra); + if (save_curbuf.br_buf == NULL) { + fix_cursor((linenr_T)start, (linenr_T)end, (linenr_T)extra); } end: @@ -405,7 +414,7 @@ end: } xfree(lines); - restore_win_for_buf(save_curwin, save_curtab, save_curbuf); + restore_win_for_buf(save_curwin, save_curtab, &save_curbuf); try_end(err); } @@ -416,6 +425,7 @@ end: /// @param[out] err Error details, if any /// @return Variable value Object nvim_buf_get_var(Buffer buffer, String name, Error *err) + FUNC_API_SINCE(1) { buf_T *buf = find_buffer_by_handle(buffer, err); @@ -426,6 +436,43 @@ Object nvim_buf_get_var(Buffer buffer, String name, Error *err) return dict_get_value(buf->b_vars, name, err); } +/// Gets a changed tick of a buffer +/// +/// @param[in] buffer Buffer handle. +/// +/// @return `b:changedtick` value. +Integer nvim_buf_get_changedtick(Buffer buffer, Error *err) + FUNC_API_SINCE(2) +{ + const buf_T *const buf = find_buffer_by_handle(buffer, err); + + if (!buf) { + return -1; + } + + return buf->b_changedtick; +} + +/// Get a list of dictionaries describing buffer-local mappings +/// Note that the buffer key in the dictionary will represent the buffer +/// handle where the mapping is present +/// +/// @param mode The abbreviation for the mode +/// @param buffer_id Buffer handle +/// @param[out] err Error details, if any +/// @returns An array of maparg() like dictionaries describing mappings +ArrayOf(Dictionary) nvim_buf_get_keymap(Buffer buffer, String mode, Error *err) + FUNC_API_SINCE(3) +{ + buf_T *buf = find_buffer_by_handle(buffer, err); + + if (!buf) { + return (Array)ARRAY_DICT_INIT; + } + + return keymap_array(mode, buf); +} + /// Sets a buffer-scoped (b:) variable /// /// @param buffer Buffer handle @@ -433,6 +480,7 @@ Object nvim_buf_get_var(Buffer buffer, String name, Error *err) /// @param value Variable value /// @param[out] err Error details, if any void nvim_buf_set_var(Buffer buffer, String name, Object value, Error *err) + FUNC_API_SINCE(1) { buf_T *buf = find_buffer_by_handle(buffer, err); @@ -440,7 +488,7 @@ void nvim_buf_set_var(Buffer buffer, String name, Object value, Error *err) return; } - dict_set_value(buf->b_vars, name, value, false, false, err); + dict_set_var(buf->b_vars, name, value, false, false, err); } /// Removes a buffer-scoped (b:) variable @@ -449,6 +497,7 @@ void nvim_buf_set_var(Buffer buffer, String name, Object value, Error *err) /// @param name Variable name /// @param[out] err Error details, if any void nvim_buf_del_var(Buffer buffer, String name, Error *err) + FUNC_API_SINCE(1) { buf_T *buf = find_buffer_by_handle(buffer, err); @@ -456,7 +505,7 @@ void nvim_buf_del_var(Buffer buffer, String name, Error *err) return; } - dict_set_value(buf->b_vars, name, NIL, true, false, err); + dict_set_var(buf->b_vars, name, NIL, true, false, err); } /// Sets a buffer-scoped (b:) variable @@ -479,7 +528,7 @@ Object buffer_set_var(Buffer buffer, String name, Object value, Error *err) return (Object) OBJECT_INIT; } - return dict_set_value(buf->b_vars, name, value, false, true, err); + return dict_set_var(buf->b_vars, name, value, false, true, err); } /// Removes a buffer-scoped (b:) variable @@ -498,7 +547,7 @@ Object buffer_del_var(Buffer buffer, String name, Error *err) return (Object) OBJECT_INIT; } - return dict_set_value(buf->b_vars, name, NIL, true, true, err); + return dict_set_var(buf->b_vars, name, NIL, true, true, err); } @@ -509,6 +558,7 @@ Object buffer_del_var(Buffer buffer, String name, Error *err) /// @param[out] err Error details, if any /// @return Option value Object nvim_buf_get_option(Buffer buffer, String name, Error *err) + FUNC_API_SINCE(1) { buf_T *buf = find_buffer_by_handle(buffer, err); @@ -527,6 +577,7 @@ Object nvim_buf_get_option(Buffer buffer, String name, Error *err) /// @param value Option value /// @param[out] err Error details, if any void nvim_buf_set_option(Buffer buffer, String name, Object value, Error *err) + FUNC_API_SINCE(1) { buf_T *buf = find_buffer_by_handle(buffer, err); @@ -539,10 +590,15 @@ void nvim_buf_set_option(Buffer buffer, String name, Object value, Error *err) /// Gets the buffer number /// +/// @deprecated The buffer number now is equal to the object id, +/// so there is no need to use this function. +/// /// @param buffer Buffer handle /// @param[out] err Error details, if any /// @return Buffer number Integer nvim_buf_get_number(Buffer buffer, Error *err) + FUNC_API_SINCE(1) + FUNC_API_DEPRECATED_SINCE(2) { Integer rv = 0; buf_T *buf = find_buffer_by_handle(buffer, err); @@ -560,6 +616,7 @@ Integer nvim_buf_get_number(Buffer buffer, Error *err) /// @param[out] err Error details, if any /// @return Buffer name String nvim_buf_get_name(Buffer buffer, Error *err) + FUNC_API_SINCE(1) { String rv = STRING_INIT; buf_T *buf = find_buffer_by_handle(buffer, err); @@ -577,6 +634,7 @@ String nvim_buf_get_name(Buffer buffer, Error *err) /// @param name Buffer name /// @param[out] err Error details, if any void nvim_buf_set_name(Buffer buffer, String name, Error *err) + FUNC_API_SINCE(1) { buf_T *buf = find_buffer_by_handle(buffer, err); @@ -597,7 +655,7 @@ void nvim_buf_set_name(Buffer buffer, String name, Error *err) } if (ren_ret == FAIL) { - api_set_error(err, Exception, _("Failed to rename buffer")); + api_set_error(err, kErrorTypeException, "Failed to rename buffer"); } } @@ -606,9 +664,12 @@ void nvim_buf_set_name(Buffer buffer, String name, Error *err) /// @param buffer Buffer handle /// @return true if the buffer is valid, false otherwise Boolean nvim_buf_is_valid(Buffer buffer) + FUNC_API_SINCE(1) { Error stub = ERROR_INIT; - return find_buffer_by_handle(buffer, &stub) != NULL; + Boolean ret = find_buffer_by_handle(buffer, &stub) != NULL; + api_clear_error(&stub); + return ret; } /// Inserts a sequence of lines to a buffer at a certain index @@ -637,6 +698,7 @@ void buffer_insert(Buffer buffer, /// @param[out] err Error details, if any /// @return (row, col) tuple ArrayOf(Integer, 2) nvim_buf_get_mark(Buffer buffer, String name, Error *err) + FUNC_API_SINCE(1) { Array rv = ARRAY_DICT_INIT; buf_T *buf = find_buffer_by_handle(buffer, err); @@ -646,25 +708,26 @@ ArrayOf(Integer, 2) nvim_buf_get_mark(Buffer buffer, String name, Error *err) } if (name.size != 1) { - api_set_error(err, Validation, _("Mark name must be a single character")); + api_set_error(err, kErrorTypeValidation, + "Mark name must be a single character"); return rv; } pos_T *posp; - buf_T *savebuf; char mark = *name.data; try_start(); - switch_buffer(&savebuf, buf); + bufref_T save_buf; + switch_buffer(&save_buf, buf); posp = getmark(mark, false); - restore_buffer(savebuf); + restore_buffer(&save_buf); if (try_end(err)) { return rv; } if (posp == NULL) { - api_set_error(err, Validation, _("Invalid mark name")); + api_set_error(err, kErrorTypeValidation, "Invalid mark name"); return rv; } @@ -711,6 +774,7 @@ Integer nvim_buf_add_highlight(Buffer buffer, Integer col_start, Integer col_end, Error *err) + FUNC_API_SINCE(1) { buf_T *buf = find_buffer_by_handle(buffer, err); if (!buf) { @@ -718,11 +782,11 @@ Integer nvim_buf_add_highlight(Buffer buffer, } if (line < 0 || line >= MAXLNUM) { - api_set_error(err, Validation, _("Line number outside range")); + api_set_error(err, kErrorTypeValidation, "Line number outside range"); return 0; } if (col_start < 0 || col_start > MAXCOL) { - api_set_error(err, Validation, _("Column value outside range")); + api_set_error(err, kErrorTypeValidation, "Column value outside range"); return 0; } if (col_end < 0 || col_end > MAXCOL) { @@ -751,6 +815,7 @@ void nvim_buf_clear_highlight(Buffer buffer, Integer line_start, Integer line_end, Error *err) + FUNC_API_SINCE(1) { buf_T *buf = find_buffer_by_handle(buffer, err); if (!buf) { @@ -758,7 +823,7 @@ void nvim_buf_clear_highlight(Buffer buffer, } if (line_start < 0 || line_start >= MAXLNUM) { - api_set_error(err, Validation, _("Line number outside range")); + api_set_error(err, kErrorTypeValidation, "Line number outside range"); return; } if (line_end < 0 || line_end > MAXLNUM) { diff --git a/src/nvim/api/private/defs.h b/src/nvim/api/private/defs.h index 223aab09dc..2144c80d6a 100644 --- a/src/nvim/api/private/defs.h +++ b/src/nvim/api/private/defs.h @@ -5,12 +5,16 @@ #include <stdbool.h> #include <string.h> +#include "nvim/func_attr.h" + #define ARRAY_DICT_INIT {.size = 0, .capacity = 0, .items = NULL} #define STRING_INIT {.data = NULL, .size = 0} #define OBJECT_INIT { .type = kObjectTypeNil } -#define ERROR_INIT { .set = false } +#define ERROR_INIT { .type = kErrorTypeNone, .msg = NULL } #define REMOTE_TYPE(type) typedef handle_T type +#define ERROR_SET(e) ((e)->type != kErrorTypeNone) + #ifdef INCLUDE_GENERATED_DECLARATIONS # define ArrayOf(...) Array # define DictionaryOf(...) Dictionary @@ -20,6 +24,7 @@ typedef int handle_T; // Basic types typedef enum { + kErrorTypeNone = -1, kErrorTypeException, kErrorTypeValidation } ErrorType; @@ -33,13 +38,31 @@ typedef enum { /// Used as the message ID of notifications. #define NO_RESPONSE UINT64_MAX -/// Used as channel_id when the call is local. -#define INTERNAL_CALL UINT64_MAX +/// Mask for all internal calls +#define INTERNAL_CALL_MASK (((uint64_t)1) << (sizeof(uint64_t) * 8 - 1)) + +/// Internal call from VimL code +#define VIML_INTERNAL_CALL INTERNAL_CALL_MASK + +/// Internal call from lua code +#define LUA_INTERNAL_CALL (VIML_INTERNAL_CALL + 1) + +static inline bool is_internal_call(uint64_t channel_id) + REAL_FATTR_ALWAYS_INLINE REAL_FATTR_CONST; + +/// Check whether call is internal +/// +/// @param[in] channel_id Channel id. +/// +/// @return true if channel_id refers to internal channel. +static inline bool is_internal_call(const uint64_t channel_id) +{ + return !!(channel_id & INTERNAL_CALL_MASK); +} typedef struct { ErrorType type; - char msg[1024]; - bool set; + char *msg; } Error; typedef bool Boolean; @@ -76,16 +99,17 @@ typedef struct { } Dictionary; typedef enum { - kObjectTypeBuffer, - kObjectTypeWindow, - kObjectTypeTabpage, - kObjectTypeNil, + kObjectTypeNil = 0, kObjectTypeBoolean, kObjectTypeInteger, kObjectTypeFloat, kObjectTypeString, kObjectTypeArray, kObjectTypeDictionary, + // EXT types, cannot be split or reordered, see #EXT_OBJECT_TYPE_SHIFT + kObjectTypeBuffer, + kObjectTypeWindow, + kObjectTypeTabpage, } ObjectType; struct object { diff --git a/src/nvim/api/private/dispatch.c b/src/nvim/api/private/dispatch.c index 9b3bcc380a..f8eebcdb10 100644 --- a/src/nvim/api/private/dispatch.c +++ b/src/nvim/api/private/dispatch.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #include <inttypes.h> #include <stdbool.h> #include <stdint.h> diff --git a/src/nvim/api/private/handle.c b/src/nvim/api/private/handle.c index acb0fb332a..eb96192af2 100644 --- a/src/nvim/api/private/handle.c +++ b/src/nvim/api/private/handle.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #include <assert.h> #include <stdint.h> diff --git a/src/nvim/api/private/handle.h b/src/nvim/api/private/handle.h index 30bbfbee1b..26e9dc3314 100644 --- a/src/nvim/api/private/handle.h +++ b/src/nvim/api/private/handle.h @@ -10,8 +10,11 @@ void handle_register_##name(type *name); \ void handle_unregister_##name(type *name); +// handle_get_buffer handle_register_buffer, handle_unregister_buffer HANDLE_DECLS(buf_T, buffer) +// handle_get_window handle_register_window, handle_unregister_window HANDLE_DECLS(win_T, window) +// handle_get_tabpage handle_register_tabpage, handle_unregister_tabpage HANDLE_DECLS(tabpage_T, tabpage) void handle_init(void); diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index 7daa4d7207..e736e29e2d 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #include <assert.h> #include <inttypes.h> #include <stdbool.h> @@ -14,12 +17,14 @@ #include "nvim/window.h" #include "nvim/memory.h" #include "nvim/eval.h" +#include "nvim/eval/typval.h" #include "nvim/map_defs.h" #include "nvim/map.h" #include "nvim/option.h" #include "nvim/option_defs.h" #include "nvim/version.h" #include "nvim/lib/kvec.h" +#include "nvim/getchar.h" /// Helper structure for vim_to_object typedef struct { @@ -29,9 +34,75 @@ typedef struct { #ifdef INCLUDE_GENERATED_DECLARATIONS # include "api/private/helpers.c.generated.h" # include "api/private/funcs_metadata.generated.h" +# include "api/private/ui_events_metadata.generated.h" #endif +/// Start block that may cause VimL exceptions while evaluating another code +/// +/// Used when caller is supposed to be operating when other VimL code is being +/// processed and that โother VimL codeโ must not be affected. +/// +/// @param[out] tstate Location where try state should be saved. +void try_enter(TryState *const tstate) +{ + *tstate = (TryState) { + .current_exception = current_exception, + .msg_list = (const struct msglist *const *)msg_list, + .private_msg_list = NULL, + .trylevel = trylevel, + .got_int = got_int, + .did_throw = did_throw, + .need_rethrow = need_rethrow, + .did_emsg = did_emsg, + }; + msg_list = &tstate->private_msg_list; + current_exception = NULL; + trylevel = 1; + got_int = false; + did_throw = false; + need_rethrow = false; + did_emsg = false; +} + +/// End try block, set the error message if any and restore previous state +/// +/// @warning Return is consistent with most functions (false on error), not with +/// try_end (true on error). +/// +/// @param[in] tstate Previous state to restore. +/// @param[out] err Location where error should be saved. +/// +/// @return false if error occurred, true otherwise. +bool try_leave(const TryState *const tstate, Error *const err) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ + const bool ret = !try_end(err); + assert(trylevel == 0); + assert(!need_rethrow); + assert(!got_int); + assert(!did_throw); + assert(!did_emsg); + assert(msg_list == &tstate->private_msg_list); + assert(*msg_list == NULL); + assert(current_exception == NULL); + msg_list = (struct msglist **)tstate->msg_list; + current_exception = tstate->current_exception; + trylevel = tstate->trylevel; + got_int = tstate->got_int; + did_throw = tstate->did_throw; + need_rethrow = tstate->need_rethrow; + did_emsg = tstate->did_emsg; + return ret; +} + /// Start block that may cause vimscript exceptions +/// +/// Each try_start() call should be mirrored by try_end() call. +/// +/// To be used as a replacement of `:try โฆ catch โฆ endtry` in C code, in cases +/// when error flag could not already be set. If there may be pending error +/// state at the time try_start() is executed which needs to be preserved, +/// try_enter()/try_leave() pair should be used instead. void try_start(void) { ++trylevel; @@ -44,7 +115,9 @@ void try_start(void) /// @return true if an error occurred bool try_end(Error *err) { - --trylevel; + // Note: all globals manipulated here should be saved/restored in + // try_enter/try_leave. + trylevel--; // Without this it stops processing all subsequent VimL commands and // generates strange error messages if I e.g. try calling Test() in a @@ -57,7 +130,7 @@ bool try_end(Error *err) discard_current_exception(); } - api_set_error(err, Exception, _("Keyboard interrupt")); + api_set_error(err, kErrorTypeException, "Keyboard interrupt"); got_int = false; } else if (msg_list != NULL && *msg_list != NULL) { int should_free; @@ -65,19 +138,18 @@ bool try_end(Error *err) ET_ERROR, NULL, &should_free); - xstrlcpy(err->msg, msg, sizeof(err->msg)); - err->set = true; + api_set_error(err, kErrorTypeException, "%s", msg); free_global_msglist(); if (should_free) { xfree(msg); } } else if (did_throw) { - api_set_error(err, Exception, "%s", current_exception->value); + api_set_error(err, kErrorTypeException, "%s", current_exception->value); discard_current_exception(); } - return err->set; + return ERROR_SET(err); } /// Recursively expands a vimscript value in a dict @@ -87,18 +159,17 @@ bool try_end(Error *err) /// @param[out] err Details of an error that may have occurred Object dict_get_value(dict_T *dict, String key, Error *err) { - hashitem_T *hi = hash_find(&dict->dv_hashtab, (uint8_t *) key.data); + dictitem_T *const di = tv_dict_find(dict, key.data, (ptrdiff_t)key.size); - if (HASHITEM_EMPTY(hi)) { - api_set_error(err, Validation, _("Key not found")); - return (Object) OBJECT_INIT; + if (di == NULL) { + api_set_error(err, kErrorTypeValidation, "Key '%s' not found", key.data); + return (Object)OBJECT_INIT; } - dictitem_T *di = dict_lookup(hi); return vim_to_object(&di->di_tv); } -/// Set a value in a dict. Objects are recursively expanded into their +/// Set a value in a scope dict. Objects are recursively expanded into their /// vimscript equivalents. /// /// @param dict The vimscript dict @@ -109,42 +180,55 @@ Object dict_get_value(dict_T *dict, String key, Error *err) /// @param retval If true the old value will be converted and returned. /// @param[out] err Details of an error that may have occurred /// @return The old value if `retval` is true and the key was present, else NIL -Object dict_set_value(dict_T *dict, String key, Object value, bool del, - bool retval, Error *err) +Object dict_set_var(dict_T *dict, String key, Object value, bool del, + bool retval, Error *err) { Object rv = OBJECT_INIT; if (dict->dv_lock) { - api_set_error(err, Exception, _("Dictionary is locked")); + api_set_error(err, kErrorTypeException, "Dictionary is locked"); return rv; } if (key.size == 0) { - api_set_error(err, Validation, _("Empty dictionary keys aren't allowed")); + api_set_error(err, kErrorTypeValidation, + "Empty variable names aren't allowed"); return rv; } if (key.size > INT_MAX) { - api_set_error(err, Validation, _("Key length is too high")); + api_set_error(err, kErrorTypeValidation, "Key length is too high"); return rv; } - dictitem_T *di = dict_find(dict, (uint8_t *)key.data, (int)key.size); + dictitem_T *di = tv_dict_find(dict, key.data, (ptrdiff_t)key.size); + + if (di != NULL) { + if (di->di_flags & DI_FLAGS_RO) { + api_set_error(err, kErrorTypeException, "Key is read-only: %s", key.data); + return rv; + } else if (di->di_flags & DI_FLAGS_FIX) { + api_set_error(err, kErrorTypeException, "Key is fixed: %s", key.data); + return rv; + } else if (di->di_flags & DI_FLAGS_LOCK) { + api_set_error(err, kErrorTypeException, "Key is locked: %s", key.data); + return rv; + } + } if (del) { // Delete the key if (di == NULL) { // Doesn't exist, fail - api_set_error(err, Validation, _("Key \"%s\" doesn't exist"), key.data); + api_set_error(err, kErrorTypeValidation, "Key does not exist: %s", + key.data); } else { // Return the old value if (retval) { rv = vim_to_object(&di->di_tv); } // Delete the entry - hashitem_T *hi = hash_find(&dict->dv_hashtab, di->di_key); - hash_remove(&dict->dv_hashtab, hi); - dictitem_free(di); + tv_dict_item_remove(dict, di); } } else { // Update the key @@ -157,20 +241,20 @@ Object dict_set_value(dict_T *dict, String key, Object value, bool del, if (di == NULL) { // Need to create an entry - di = dictitem_alloc((uint8_t *) key.data); - dict_add(dict, di); + di = tv_dict_item_alloc_len(key.data, key.size); + tv_dict_add(dict, di); } else { // Return the old value if (retval) { rv = vim_to_object(&di->di_tv); } - clear_tv(&di->di_tv); + tv_clear(&di->di_tv); } // Update the value - copy_tv(&tv, &di->di_tv); + tv_copy(&tv, &di->di_tv); // Clear the temporary variable - clear_tv(&tv); + tv_clear(&tv); } return rv; @@ -189,7 +273,7 @@ Object get_option_from(void *from, int type, String name, Error *err) Object rv = OBJECT_INIT; if (name.size == 0) { - api_set_error(err, Validation, _("Empty option name")); + api_set_error(err, kErrorTypeValidation, "Empty option name"); return rv; } @@ -201,8 +285,8 @@ Object get_option_from(void *from, int type, String name, Error *err) if (!flags) { api_set_error(err, - Validation, - _("Invalid option name \"%s\""), + kErrorTypeValidation, + "Invalid option name \"%s\"", name.data); return rv; } @@ -220,14 +304,14 @@ Object get_option_from(void *from, int type, String name, Error *err) rv.data.string.size = strlen(stringval); } else { api_set_error(err, - Exception, - _("Unable to get value for option \"%s\""), + kErrorTypeException, + "Unable to get value for option \"%s\"", name.data); } } else { api_set_error(err, - Exception, - _("Unknown type for option \"%s\""), + kErrorTypeException, + "Unknown type for option \"%s\"", name.data); } @@ -244,7 +328,7 @@ Object get_option_from(void *from, int type, String name, Error *err) void set_option_to(void *to, int type, String name, Object value, Error *err) { if (name.size == 0) { - api_set_error(err, Validation, _("Empty option name")); + api_set_error(err, kErrorTypeValidation, "Empty option name"); return; } @@ -252,8 +336,8 @@ void set_option_to(void *to, int type, String name, Object value, Error *err) if (flags == 0) { api_set_error(err, - Validation, - _("Invalid option name \"%s\""), + kErrorTypeValidation, + "Invalid option name \"%s\"", name.data); return; } @@ -261,15 +345,15 @@ void set_option_to(void *to, int type, String name, Object value, Error *err) if (value.type == kObjectTypeNil) { if (type == SREQ_GLOBAL) { api_set_error(err, - Exception, - _("Unable to unset option \"%s\""), + kErrorTypeException, + "Unable to unset option \"%s\"", name.data); return; } else if (!(flags & SOPT_GLOBAL)) { api_set_error(err, - Exception, - _("Cannot unset option \"%s\" " - "because it doesn't have a global value"), + kErrorTypeException, + "Cannot unset option \"%s\" " + "because it doesn't have a global value", name.data); return; } else { @@ -278,13 +362,13 @@ void set_option_to(void *to, int type, String name, Object value, Error *err) } } - int opt_flags = (type ? OPT_LOCAL : OPT_GLOBAL); + int opt_flags = (type == SREQ_GLOBAL) ? OPT_GLOBAL : OPT_LOCAL; if (flags & SOPT_BOOL) { if (value.type != kObjectTypeBoolean) { api_set_error(err, - Validation, - _("Option \"%s\" requires a boolean value"), + kErrorTypeValidation, + "Option \"%s\" requires a boolean value", name.data); return; } @@ -294,16 +378,16 @@ void set_option_to(void *to, int type, String name, Object value, Error *err) } else if (flags & SOPT_NUM) { if (value.type != kObjectTypeInteger) { api_set_error(err, - Validation, - _("Option \"%s\" requires an integer value"), + kErrorTypeValidation, + "Option \"%s\" requires an integer value", name.data); return; } if (value.data.integer > INT_MAX || value.data.integer < INT_MIN) { api_set_error(err, - Validation, - _("Value for option \"%s\" is outside range"), + kErrorTypeValidation, + "Value for option \"%s\" is outside range", name.data); return; } @@ -313,8 +397,8 @@ void set_option_to(void *to, int type, String name, Object value, Error *err) } else { if (value.type != kObjectTypeString) { api_set_error(err, - Validation, - _("Option \"%s\" requires a string value"), + kErrorTypeValidation, + "Option \"%s\" requires a string value", name.data); return; } @@ -338,7 +422,7 @@ void set_option_to(void *to, int type, String name, Object value, Error *err) #define TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER TYPVAL_ENCODE_CONV_NUMBER #define TYPVAL_ENCODE_CONV_FLOAT(tv, flt) \ - kv_push(edata->stack, FLOATING_OBJ((Float)(flt))) + kv_push(edata->stack, FLOAT_OBJ((Float)(flt))) #define TYPVAL_ENCODE_CONV_STRING(tv, str, len) \ do { \ @@ -380,7 +464,7 @@ static inline void typval_encode_list_start(EncodedData *const edata, kv_push(edata->stack, ARRAY_OBJ(((Array) { .capacity = len, .size = 0, - .items = xmalloc(len * sizeof(*((Object *)NULL)->data.array.items)), + .items = xmalloc(len * sizeof(*((Object)OBJECT_INIT).data.array.items)), }))); } @@ -422,7 +506,8 @@ static inline void typval_encode_dict_start(EncodedData *const edata, kv_push(edata->stack, DICTIONARY_OBJ(((Dictionary) { .capacity = len, .size = 0, - .items = xmalloc(len * sizeof(*((Object *)NULL)->data.dictionary.items)), + .items = xmalloc(len * sizeof( + *((Object)OBJECT_INIT).data.dictionary.items)), }))); } @@ -546,13 +631,13 @@ buf_T *find_buffer_by_handle(Buffer buffer, Error *err) buf_T *rv = handle_get_buffer(buffer); if (!rv) { - api_set_error(err, Validation, _("Invalid buffer id")); + api_set_error(err, kErrorTypeValidation, "Invalid buffer id"); } return rv; } -win_T * find_window_by_handle(Window window, Error *err) +win_T *find_window_by_handle(Window window, Error *err) { if (window == 0) { return curwin; @@ -561,13 +646,13 @@ win_T * find_window_by_handle(Window window, Error *err) win_T *rv = handle_get_window(window); if (!rv) { - api_set_error(err, Validation, _("Invalid window id")); + api_set_error(err, kErrorTypeValidation, "Invalid window id"); } return rv; } -tabpage_T * find_tab_by_handle(Tabpage tabpage, Error *err) +tabpage_T *find_tab_by_handle(Tabpage tabpage, Error *err) { if (tabpage == 0) { return curtab; @@ -576,7 +661,7 @@ tabpage_T * find_tab_by_handle(Tabpage tabpage, Error *err) tabpage_T *rv = handle_get_tabpage(tabpage); if (!rv) { - api_set_error(err, Validation, _("Invalid tabpage id")); + api_set_error(err, kErrorTypeValidation, "Invalid tabpage id"); } return rv; @@ -613,7 +698,7 @@ String cstr_as_string(char *str) FUNC_ATTR_PURE if (str == NULL) { return (String) STRING_INIT; } - return (String) {.data = str, .size = strlen(str)}; + return (String) { .data = str, .size = strlen(str) }; } /// Converts from type Object to a VimL value. @@ -644,7 +729,7 @@ bool object_to_vim(Object obj, typval_T *tv, Error *err) case kObjectTypeInteger: if (obj.data.integer > VARNUMBER_MAX || obj.data.integer < VARNUMBER_MIN) { - api_set_error(err, Validation, _("Integer value outside range")); + api_set_error(err, kErrorTypeValidation, "Integer value outside range"); return false; } @@ -668,20 +753,20 @@ bool object_to_vim(Object obj, typval_T *tv, Error *err) break; case kObjectTypeArray: { - list_T *list = list_alloc(); + list_T *const list = tv_list_alloc(); for (uint32_t i = 0; i < obj.data.array.size; i++) { Object item = obj.data.array.items[i]; - listitem_T *li = listitem_alloc(); + listitem_T *li = tv_list_item_alloc(); if (!object_to_vim(item, &li->li_tv, err)) { // cleanup - listitem_free(li); - list_free(list); + tv_list_item_free(li); + tv_list_free(list); return false; } - list_append(list, li); + tv_list_append(list, li); } list->lv_refcount++; @@ -691,30 +776,30 @@ bool object_to_vim(Object obj, typval_T *tv, Error *err) } case kObjectTypeDictionary: { - dict_T *dict = dict_alloc(); + dict_T *const dict = tv_dict_alloc(); for (uint32_t i = 0; i < obj.data.dictionary.size; i++) { KeyValuePair item = obj.data.dictionary.items[i]; String key = item.key; if (key.size == 0) { - api_set_error(err, Validation, - _("Empty dictionary keys aren't allowed")); + api_set_error(err, kErrorTypeValidation, + "Empty dictionary keys aren't allowed"); // cleanup - dict_free(dict); + tv_dict_free(dict); return false; } - dictitem_T *di = dictitem_alloc((uint8_t *)key.data); + dictitem_T *const di = tv_dict_item_alloc(key.data); if (!object_to_vim(item.value, &di->di_tv, err)) { // cleanup - dictitem_free(di); - dict_free(dict); + tv_dict_item_free(di); + tv_dict_free(dict); return false; } - dict_add(dict, di); + tv_dict_add(dict, di); } dict->dv_refcount++; @@ -786,6 +871,17 @@ void api_free_dictionary(Dictionary value) xfree(value.items); } +void api_clear_error(Error *value) + FUNC_ATTR_NONNULL_ALL +{ + if (!ERROR_SET(value)) { + return; + } + xfree(value->msg); + value->msg = NULL; + value->type = kErrorTypeNone; +} + Dictionary api_metadata(void) { static Dictionary metadata = ARRAY_DICT_INIT; @@ -793,6 +889,7 @@ Dictionary api_metadata(void) if (!metadata.size) { PUT(metadata, "version", DICTIONARY_OBJ(version_dict())); init_function_metadata(&metadata); + init_ui_event_metadata(&metadata); init_error_type_metadata(&metadata); init_type_metadata(&metadata); } @@ -816,6 +913,22 @@ static void init_function_metadata(Dictionary *metadata) PUT(*metadata, "functions", functions); } +static void init_ui_event_metadata(Dictionary *metadata) +{ + msgpack_unpacked unpacked; + msgpack_unpacked_init(&unpacked); + if (msgpack_unpack_next(&unpacked, + (const char *)ui_events_metadata, + sizeof(ui_events_metadata), + NULL) != MSGPACK_UNPACK_SUCCESS) { + abort(); + } + Object ui_events; + msgpack_rpc_to_object(&unpacked.data, &ui_events); + msgpack_unpacked_destroy(&unpacked); + PUT(*metadata, "ui_events", ui_events); +} + static void init_error_type_metadata(Dictionary *metadata) { Dictionary types = ARRAY_DICT_INIT; @@ -837,15 +950,18 @@ static void init_type_metadata(Dictionary *metadata) Dictionary types = ARRAY_DICT_INIT; Dictionary buffer_metadata = ARRAY_DICT_INIT; - PUT(buffer_metadata, "id", INTEGER_OBJ(kObjectTypeBuffer)); + PUT(buffer_metadata, "id", + INTEGER_OBJ(kObjectTypeBuffer - EXT_OBJECT_TYPE_SHIFT)); PUT(buffer_metadata, "prefix", STRING_OBJ(cstr_to_string("nvim_buf_"))); Dictionary window_metadata = ARRAY_DICT_INIT; - PUT(window_metadata, "id", INTEGER_OBJ(kObjectTypeWindow)); + PUT(window_metadata, "id", + INTEGER_OBJ(kObjectTypeWindow - EXT_OBJECT_TYPE_SHIFT)); PUT(window_metadata, "prefix", STRING_OBJ(cstr_to_string("nvim_win_"))); Dictionary tabpage_metadata = ARRAY_DICT_INIT; - PUT(tabpage_metadata, "id", INTEGER_OBJ(kObjectTypeTabpage)); + PUT(tabpage_metadata, "id", + INTEGER_OBJ(kObjectTypeTabpage - EXT_OBJECT_TYPE_SHIFT)); PUT(tabpage_metadata, "prefix", STRING_OBJ(cstr_to_string("nvim_tabpage_"))); PUT(types, "Buffer", DICTIONARY_OBJ(buffer_metadata)); @@ -855,6 +971,24 @@ static void init_type_metadata(Dictionary *metadata) PUT(*metadata, "types", DICTIONARY_OBJ(types)); } +String copy_string(String str) +{ + if (str.data != NULL) { + return (String){ .data = xmemdupz(str.data, str.size), .size = str.size }; + } else { + return (String)STRING_INIT; + } +} + +Array copy_array(Array array) +{ + Array rv = ARRAY_DICT_INIT; + for (size_t i = 0; i < array.size; i++) { + ADD(rv, copy_object(array.items[i])); + } + return rv; +} + /// Creates a deep clone of an object Object copy_object(Object obj) { @@ -866,15 +1000,10 @@ Object copy_object(Object obj) return obj; case kObjectTypeString: - return STRING_OBJ(cstr_to_string(obj.data.string.data)); + return STRING_OBJ(copy_string(obj.data.string)); - case kObjectTypeArray: { - Array rv = ARRAY_DICT_INIT; - for (size_t i = 0; i < obj.data.array.size; i++) { - ADD(rv, copy_object(obj.data.array.items[i])); - } - return ARRAY_OBJ(rv); - } + case kObjectTypeArray: + return ARRAY_OBJ(copy_array(obj.data.array)); case kObjectTypeDictionary: { Dictionary rv = ARRAY_DICT_INIT; @@ -899,7 +1028,7 @@ static void set_option_value_for(char *key, { win_T *save_curwin = NULL; tabpage_T *save_curtab = NULL; - buf_T *save_curbuf = NULL; + bufref_T save_curbuf = { NULL, 0, 0 }; try_start(); switch (opt_type) @@ -912,8 +1041,8 @@ static void set_option_value_for(char *key, return; } api_set_error(err, - Exception, - _("Problem while switching windows")); + kErrorTypeException, + "Problem while switching windows"); return; } set_option_value_err(key, numval, stringval, opt_flags, err); @@ -922,14 +1051,14 @@ static void set_option_value_for(char *key, case SREQ_BUF: switch_buffer(&save_curbuf, (buf_T *)from); set_option_value_err(key, numval, stringval, opt_flags, err); - restore_buffer(save_curbuf); + restore_buffer(&save_curbuf); break; case SREQ_GLOBAL: set_option_value_err(key, numval, stringval, opt_flags, err); break; } - if (err->set) { + if (ERROR_SET(err)) { return; } @@ -945,15 +1074,69 @@ static void set_option_value_err(char *key, { char *errmsg; - if ((errmsg = (char *)set_option_value((uint8_t *)key, - numval, - (uint8_t *)stringval, - opt_flags))) - { + if ((errmsg = set_option_value(key, numval, stringval, opt_flags))) { if (try_end(err)) { return; } - api_set_error(err, Exception, "%s", errmsg); + api_set_error(err, kErrorTypeException, "%s", errmsg); } } + +void api_set_error(Error *err, ErrorType errType, const char *format, ...) + FUNC_ATTR_NONNULL_ALL +{ + assert(kErrorTypeNone != errType); + va_list args1; + va_list args2; + va_start(args1, format); + va_copy(args2, args1); + int len = vsnprintf(NULL, 0, format, args1); + va_end(args1); + assert(len >= 0); + // Limit error message to 1 MB. + size_t bufsize = MIN((size_t)len + 1, 1024 * 1024); + err->msg = xmalloc(bufsize); + vsnprintf(err->msg, bufsize, format, args2); + va_end(args2); + + err->type = errType; +} + +/// Get an array containing dictionaries describing mappings +/// based on mode and buffer id +/// +/// @param mode The abbreviation for the mode +/// @param buf The buffer to get the mapping array. NULL for global +/// @returns An array of maparg() like dictionaries describing mappings +ArrayOf(Dictionary) keymap_array(String mode, buf_T *buf) +{ + Array mappings = ARRAY_DICT_INIT; + dict_T *const dict = tv_dict_alloc(); + + // Convert the string mode to the integer mode + // that is stored within each mapblock + char_u *p = (char_u *)mode.data; + int int_mode = get_map_mode(&p, 0); + + // Determine the desired buffer value + long buffer_value = (buf == NULL) ? 0 : buf->handle; + + for (int i = 0; i < MAX_MAPHASH; i++) { + for (const mapblock_T *current_maphash = get_maphash(i, buf); + current_maphash; + current_maphash = current_maphash->m_next) { + // Check for correct mode + if (int_mode & current_maphash->m_mode) { + mapblock_fill_dict(dict, current_maphash, buffer_value, false); + ADD(mappings, vim_to_object( + (typval_T[]) { { .v_type = VAR_DICT, .vval.v_dict = dict } })); + + tv_dict_clear(dict); + } + } + } + tv_dict_free(dict); + + return mappings; +} diff --git a/src/nvim/api/private/helpers.h b/src/nvim/api/private/helpers.h index 9fe8c351cf..87f334ac30 100644 --- a/src/nvim/api/private/helpers.h +++ b/src/nvim/api/private/helpers.h @@ -6,17 +6,9 @@ #include "nvim/api/private/defs.h" #include "nvim/vim.h" #include "nvim/memory.h" +#include "nvim/ex_eval.h" #include "nvim/lib/kvec.h" -#define api_set_error(err, errtype, ...) \ - do { \ - snprintf((err)->msg, \ - sizeof((err)->msg), \ - __VA_ARGS__); \ - (err)->set = true; \ - (err)->type = kErrorType##errtype; \ - } while (0) - #define OBJECT_OBJ(o) o #define BOOLEAN_OBJ(b) ((Object) { \ @@ -27,7 +19,7 @@ .type = kObjectTypeInteger, \ .data.integer = i }) -#define FLOATING_OBJ(f) ((Object) { \ +#define FLOAT_OBJ(f) ((Object) { \ .type = kObjectTypeFloat, \ .data.floating = f }) @@ -91,6 +83,21 @@ #define api_free_window(value) #define api_free_tabpage(value) +/// Structure used for saving state for :try +/// +/// Used when caller is supposed to be operating when other VimL code is being +/// processed and that โother VimL codeโ must not be affected. +typedef struct { + except_T *current_exception; + struct msglist *private_msg_list; + const struct msglist *const *msg_list; + int trylevel; + int got_int; + int did_throw; + int need_rethrow; + int did_emsg; +} TryState; + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "api/private/helpers.h.generated.h" #endif diff --git a/src/nvim/api/tabpage.c b/src/nvim/api/tabpage.c index 9e61ec1871..b6830d9fcf 100644 --- a/src/nvim/api/tabpage.c +++ b/src/nvim/api/tabpage.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #include <stdbool.h> #include <stdint.h> #include <stdlib.h> @@ -15,6 +18,7 @@ /// @param[out] err Error details, if any /// @return List of windows in `tabpage` ArrayOf(Window) nvim_tabpage_list_wins(Tabpage tabpage, Error *err) + FUNC_API_SINCE(1) { Array rv = ARRAY_DICT_INIT; tabpage_T *tab = find_tab_by_handle(tabpage, err); @@ -44,6 +48,7 @@ ArrayOf(Window) nvim_tabpage_list_wins(Tabpage tabpage, Error *err) /// @param[out] err Error details, if any /// @return Variable value Object nvim_tabpage_get_var(Tabpage tabpage, String name, Error *err) + FUNC_API_SINCE(1) { tabpage_T *tab = find_tab_by_handle(tabpage, err); @@ -64,6 +69,7 @@ void nvim_tabpage_set_var(Tabpage tabpage, String name, Object value, Error *err) + FUNC_API_SINCE(1) { tabpage_T *tab = find_tab_by_handle(tabpage, err); @@ -71,7 +77,7 @@ void nvim_tabpage_set_var(Tabpage tabpage, return; } - dict_set_value(tab->tp_vars, name, value, false, false, err); + dict_set_var(tab->tp_vars, name, value, false, false, err); } /// Removes a tab-scoped (t:) variable @@ -80,6 +86,7 @@ void nvim_tabpage_set_var(Tabpage tabpage, /// @param name Variable name /// @param[out] err Error details, if any void nvim_tabpage_del_var(Tabpage tabpage, String name, Error *err) + FUNC_API_SINCE(1) { tabpage_T *tab = find_tab_by_handle(tabpage, err); @@ -87,7 +94,7 @@ void nvim_tabpage_del_var(Tabpage tabpage, String name, Error *err) return; } - dict_set_value(tab->tp_vars, name, NIL, true, false, err); + dict_set_var(tab->tp_vars, name, NIL, true, false, err); } /// Sets a tab-scoped (t:) variable @@ -110,7 +117,7 @@ Object tabpage_set_var(Tabpage tabpage, String name, Object value, Error *err) return (Object) OBJECT_INIT; } - return dict_set_value(tab->tp_vars, name, value, false, true, err); + return dict_set_var(tab->tp_vars, name, value, false, true, err); } /// Removes a tab-scoped (t:) variable @@ -129,7 +136,7 @@ Object tabpage_del_var(Tabpage tabpage, String name, Error *err) return (Object) OBJECT_INIT; } - return dict_set_value(tab->tp_vars, name, NIL, true, true, err); + return dict_set_var(tab->tp_vars, name, NIL, true, true, err); } /// Gets the current window in a tabpage @@ -138,6 +145,7 @@ Object tabpage_del_var(Tabpage tabpage, String name, Error *err) /// @param[out] err Error details, if any /// @return Window handle Window nvim_tabpage_get_win(Tabpage tabpage, Error *err) + FUNC_API_SINCE(1) { Window rv = 0; tabpage_T *tab = find_tab_by_handle(tabpage, err); @@ -165,6 +173,7 @@ Window nvim_tabpage_get_win(Tabpage tabpage, Error *err) /// @param[out] err Error details, if any /// @return Tabpage number Integer nvim_tabpage_get_number(Tabpage tabpage, Error *err) + FUNC_API_SINCE(1) { Integer rv = 0; tabpage_T *tab = find_tab_by_handle(tabpage, err); @@ -181,8 +190,11 @@ Integer nvim_tabpage_get_number(Tabpage tabpage, Error *err) /// @param tabpage Tabpage handle /// @return true if the tabpage is valid, false otherwise Boolean nvim_tabpage_is_valid(Tabpage tabpage) + FUNC_API_SINCE(1) { Error stub = ERROR_INIT; - return find_tab_by_handle(tabpage, &stub) != NULL; + Boolean ret = find_tab_by_handle(tabpage, &stub) != NULL; + api_clear_error(&stub); + return ret; } diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index 9178538110..573be23d8e 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #include <assert.h> #include <stddef.h> #include <stdint.h> @@ -12,9 +15,11 @@ #include "nvim/api/private/defs.h" #include "nvim/api/private/helpers.h" #include "nvim/popupmnu.h" +#include "nvim/cursor_shape.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "api/ui.c.generated.h" +# include "ui_events_remote.generated.h" #endif typedef struct { @@ -25,13 +30,13 @@ typedef struct { static PMap(uint64_t) *connected_uis = NULL; void remote_ui_init(void) - FUNC_API_NOEXPORT + FUNC_API_NOEXPORT { connected_uis = pmap_new(uint64_t)(); } void remote_ui_disconnect(uint64_t channel_id) - FUNC_API_NOEXPORT + FUNC_API_NOEXPORT { UI *ui = pmap_get(uint64_t)(connected_uis, channel_id); if (!ui) { @@ -48,27 +53,27 @@ void remote_ui_disconnect(uint64_t channel_id) void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height, Dictionary options, Error *err) - FUNC_API_NOEVAL + FUNC_API_SINCE(1) FUNC_API_REMOTE_ONLY { if (pmap_has(uint64_t)(connected_uis, channel_id)) { - api_set_error(err, Exception, _("UI already attached for channel")); + api_set_error(err, kErrorTypeException, "UI already attached for channel"); return; } if (width <= 0 || height <= 0) { - api_set_error(err, Validation, - _("Expected width > 0 and height > 0")); + api_set_error(err, kErrorTypeValidation, + "Expected width > 0 and height > 0"); return; } UI *ui = xcalloc(1, sizeof(UI)); ui->width = (int)width; ui->height = (int)height; ui->rgb = true; - ui->pum_external = false; ui->resize = remote_ui_resize; ui->clear = remote_ui_clear; ui->eol_clear = remote_ui_eol_clear; ui->cursor_goto = remote_ui_cursor_goto; + ui->mode_info_set = remote_ui_mode_info_set; ui->update_menu = remote_ui_update_menu; ui->busy_start = remote_ui_busy_start; ui->busy_stop = remote_ui_busy_stop; @@ -90,9 +95,11 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height, ui->set_icon = remote_ui_set_icon; ui->event = remote_ui_event; + memset(ui->ui_ext, 0, sizeof(ui->ui_ext)); + for (size_t i = 0; i < options.size; i++) { ui_set_option(ui, options.items[i].key, options.items[i].value, err); - if (err->set) { + if (ERROR_SET(err)) { xfree(ui); return; } @@ -118,10 +125,10 @@ void ui_attach(uint64_t channel_id, Integer width, Integer height, } void nvim_ui_detach(uint64_t channel_id, Error *err) - FUNC_API_NOEVAL + FUNC_API_SINCE(1) FUNC_API_REMOTE_ONLY { if (!pmap_has(uint64_t)(connected_uis, channel_id)) { - api_set_error(err, Exception, _("UI is not attached for channel")); + api_set_error(err, kErrorTypeException, "UI is not attached for channel"); return; } remote_ui_disconnect(channel_id); @@ -130,16 +137,16 @@ void nvim_ui_detach(uint64_t channel_id, Error *err) void nvim_ui_try_resize(uint64_t channel_id, Integer width, Integer height, Error *err) - FUNC_API_NOEVAL + FUNC_API_SINCE(1) FUNC_API_REMOTE_ONLY { if (!pmap_has(uint64_t)(connected_uis, channel_id)) { - api_set_error(err, Exception, _("UI is not attached for channel")); + api_set_error(err, kErrorTypeException, "UI is not attached for channel"); return; } if (width <= 0 || height <= 0) { - api_set_error(err, Validation, - _("Expected width > 0 and height > 0")); + api_set_error(err, kErrorTypeValidation, + "Expected width > 0 and height > 0"); return; } @@ -151,37 +158,61 @@ void nvim_ui_try_resize(uint64_t channel_id, Integer width, void nvim_ui_set_option(uint64_t channel_id, String name, Object value, Error *error) - FUNC_API_NOEVAL + FUNC_API_SINCE(1) FUNC_API_REMOTE_ONLY { if (!pmap_has(uint64_t)(connected_uis, channel_id)) { - api_set_error(error, Exception, _("UI is not attached for channel")); + api_set_error(error, kErrorTypeException, "UI is not attached for channel"); return; } UI *ui = pmap_get(uint64_t)(connected_uis, channel_id); ui_set_option(ui, name, value, error); - if (!error->set) { + if (!ERROR_SET(error)) { ui_refresh(); } } -static void ui_set_option(UI *ui, String name, Object value, Error *error) { - if (strcmp(name.data, "rgb") == 0) { +static void ui_set_option(UI *ui, String name, Object value, Error *error) +{ +#define UI_EXT_OPTION(o, e) \ + do { \ + if (strequal(name.data, #o)) { \ + if (value.type != kObjectTypeBoolean) { \ + api_set_error(error, kErrorTypeValidation, #o " must be a Boolean"); \ + return; \ + } \ + ui->ui_ext[(e)] = value.data.boolean; \ + return; \ + } \ + } while (0) + + if (strequal(name.data, "rgb")) { if (value.type != kObjectTypeBoolean) { - api_set_error(error, Validation, _("rgb must be a Boolean")); + api_set_error(error, kErrorTypeValidation, "rgb must be a Boolean"); return; } ui->rgb = value.data.boolean; - } else if (strcmp(name.data, "popupmenu_external") == 0) { + return; + } + + UI_EXT_OPTION(ext_cmdline, kUICmdline); + UI_EXT_OPTION(ext_popupmenu, kUIPopupmenu); + UI_EXT_OPTION(ext_tabline, kUITabline); + UI_EXT_OPTION(ext_wildmenu, kUIWildmenu); + + if (strequal(name.data, "popupmenu_external")) { + // LEGACY: Deprecated option, use `ui_ext` instead. if (value.type != kObjectTypeBoolean) { - api_set_error(error, Validation, - _("popupmenu_external must be a Boolean")); + api_set_error(error, kErrorTypeValidation, + "popupmenu_external must be a Boolean"); return; } - ui->pum_external = value.data.boolean; - } else { - api_set_error(error, Validation, _("No such ui option")); + ui->ui_ext[kUIPopupmenu] = value.data.boolean; + return; } + + api_set_error(error, kErrorTypeValidation, "No such ui option"); +#undef UI_EXT_OPTION } static void push_call(UI *ui, char *name, Array args) @@ -206,97 +237,6 @@ static void push_call(UI *ui, char *name, Array args) kv_A(data->buffer, kv_size(data->buffer) - 1).data.array = call; } -static void remote_ui_resize(UI *ui, int width, int height) -{ - Array args = ARRAY_DICT_INIT; - ADD(args, INTEGER_OBJ(width)); - ADD(args, INTEGER_OBJ(height)); - push_call(ui, "resize", args); -} - -static void remote_ui_clear(UI *ui) -{ - Array args = ARRAY_DICT_INIT; - push_call(ui, "clear", args); -} - -static void remote_ui_eol_clear(UI *ui) -{ - Array args = ARRAY_DICT_INIT; - push_call(ui, "eol_clear", args); -} - -static void remote_ui_cursor_goto(UI *ui, int row, int col) -{ - Array args = ARRAY_DICT_INIT; - ADD(args, INTEGER_OBJ(row)); - ADD(args, INTEGER_OBJ(col)); - push_call(ui, "cursor_goto", args); -} - -static void remote_ui_update_menu(UI *ui) -{ - Array args = ARRAY_DICT_INIT; - push_call(ui, "update_menu", args); -} - -static void remote_ui_busy_start(UI *ui) -{ - Array args = ARRAY_DICT_INIT; - push_call(ui, "busy_start", args); -} - -static void remote_ui_busy_stop(UI *ui) -{ - Array args = ARRAY_DICT_INIT; - push_call(ui, "busy_stop", args); -} - -static void remote_ui_mouse_on(UI *ui) -{ - Array args = ARRAY_DICT_INIT; - push_call(ui, "mouse_on", args); -} - -static void remote_ui_mouse_off(UI *ui) -{ - Array args = ARRAY_DICT_INIT; - push_call(ui, "mouse_off", args); -} - -static void remote_ui_mode_change(UI *ui, int mode) -{ - Array args = ARRAY_DICT_INIT; - if (mode == INSERT) { - ADD(args, STRING_OBJ(cstr_to_string("insert"))); - } else if (mode == REPLACE) { - ADD(args, STRING_OBJ(cstr_to_string("replace"))); - } else if (mode == CMDLINE) { - ADD(args, STRING_OBJ(cstr_to_string("cmdline"))); - } else { - assert(mode == NORMAL); - ADD(args, STRING_OBJ(cstr_to_string("normal"))); - } - push_call(ui, "mode_change", args); -} - -static void remote_ui_set_scroll_region(UI *ui, int top, int bot, int left, - int right) -{ - Array args = ARRAY_DICT_INIT; - ADD(args, INTEGER_OBJ(top)); - ADD(args, INTEGER_OBJ(bot)); - ADD(args, INTEGER_OBJ(left)); - ADD(args, INTEGER_OBJ(right)); - push_call(ui, "set_scroll_region", args); -} - -static void remote_ui_scroll(UI *ui, int count) -{ - Array args = ARRAY_DICT_INIT; - ADD(args, INTEGER_OBJ(count)); - push_call(ui, "scroll", args); -} static void remote_ui_highlight_set(UI *ui, HlAttrs attrs) { @@ -339,72 +279,13 @@ static void remote_ui_highlight_set(UI *ui, HlAttrs attrs) push_call(ui, "highlight_set", args); } -static void remote_ui_put(UI *ui, uint8_t *data, size_t size) -{ - Array args = ARRAY_DICT_INIT; - String str = { .data = xmemdupz(data, size), .size = size }; - ADD(args, STRING_OBJ(str)); - push_call(ui, "put", args); -} - -static void remote_ui_bell(UI *ui) -{ - Array args = ARRAY_DICT_INIT; - push_call(ui, "bell", args); -} - -static void remote_ui_visual_bell(UI *ui) -{ - Array args = ARRAY_DICT_INIT; - push_call(ui, "visual_bell", args); -} - -static void remote_ui_update_fg(UI *ui, int fg) -{ - Array args = ARRAY_DICT_INIT; - ADD(args, INTEGER_OBJ(fg)); - push_call(ui, "update_fg", args); -} - -static void remote_ui_update_bg(UI *ui, int bg) -{ - Array args = ARRAY_DICT_INIT; - ADD(args, INTEGER_OBJ(bg)); - push_call(ui, "update_bg", args); -} - -static void remote_ui_update_sp(UI *ui, int sp) -{ - Array args = ARRAY_DICT_INIT; - ADD(args, INTEGER_OBJ(sp)); - push_call(ui, "update_sp", args); -} - static void remote_ui_flush(UI *ui) { UIData *data = ui->data; - channel_send_event(data->channel_id, "redraw", data->buffer); - data->buffer = (Array)ARRAY_DICT_INIT; -} - -static void remote_ui_suspend(UI *ui) -{ - Array args = ARRAY_DICT_INIT; - push_call(ui, "suspend", args); -} - -static void remote_ui_set_title(UI *ui, char *title) -{ - Array args = ARRAY_DICT_INIT; - ADD(args, STRING_OBJ(cstr_to_string(title))); - push_call(ui, "set_title", args); -} - -static void remote_ui_set_icon(UI *ui, char *icon) -{ - Array args = ARRAY_DICT_INIT; - ADD(args, STRING_OBJ(cstr_to_string(icon))); - push_call(ui, "set_icon", args); + if (data->buffer.size > 0) { + channel_send_event(data->channel_id, "redraw", data->buffer); + data->buffer = (Array)ARRAY_DICT_INIT; + } } static void remote_ui_event(UI *ui, char *name, Array args, bool *args_consumed) diff --git a/src/nvim/api/ui_events.in.h b/src/nvim/api/ui_events.in.h new file mode 100644 index 0000000000..1b5d17584f --- /dev/null +++ b/src/nvim/api/ui_events.in.h @@ -0,0 +1,71 @@ +#ifndef NVIM_API_UI_EVENTS_IN_H +#define NVIM_API_UI_EVENTS_IN_H + +// This file is not compiled, just parsed for definitons +#ifdef INCLUDE_GENERATED_DECLARATIONS +# error "don't include this file, include nvim/ui.h" +#endif + +#include "nvim/api/private/defs.h" +#include "nvim/func_attr.h" +#include "nvim/ui.h" + +void resize(Integer rows, Integer columns) + FUNC_API_SINCE(3); +void clear(void) + FUNC_API_SINCE(3); +void eol_clear(void) + FUNC_API_SINCE(3); +void cursor_goto(Integer row, Integer col) + FUNC_API_SINCE(3); +void mode_info_set(Boolean enabled, Array cursor_styles) + FUNC_API_SINCE(3); +void update_menu(void) + FUNC_API_SINCE(3); +void busy_start(void) + FUNC_API_SINCE(3); +void busy_stop(void) + FUNC_API_SINCE(3); +void mouse_on(void) + FUNC_API_SINCE(3); +void mouse_off(void) + FUNC_API_SINCE(3); +void mode_change(String mode, Integer mode_idx) + FUNC_API_SINCE(3); +void set_scroll_region(Integer top, Integer bot, Integer left, Integer right) + FUNC_API_SINCE(3); +void scroll(Integer count) + FUNC_API_SINCE(3); +void highlight_set(HlAttrs attrs) + FUNC_API_SINCE(3) FUNC_API_REMOTE_IMPL FUNC_API_BRIDGE_IMPL; +void put(String str) + FUNC_API_SINCE(3); +void bell(void) + FUNC_API_SINCE(3); +void visual_bell(void) + FUNC_API_SINCE(3); +void flush(void) + FUNC_API_SINCE(3) FUNC_API_REMOTE_IMPL; +void update_fg(Integer fg) + FUNC_API_SINCE(3); +void update_bg(Integer bg) + FUNC_API_SINCE(3); +void update_sp(Integer sp) + FUNC_API_SINCE(3); +void suspend(void) + FUNC_API_SINCE(3) FUNC_API_BRIDGE_IMPL; +void set_title(String title) + FUNC_API_SINCE(3); +void set_icon(String icon) + FUNC_API_SINCE(3); + +void popupmenu_show(Array items, Integer selected, Integer row, Integer col) + FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; +void popupmenu_hide(void) + FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; +void popupmenu_select(Integer selected) + FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; +void tabline_update(Tabpage current, Array tabs) + FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; + +#endif // NVIM_API_UI_EVENTS_IN_H diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index b17b59f7a6..cfbe34b848 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #include <assert.h> #include <stdint.h> #include <inttypes.h> @@ -10,8 +13,10 @@ #include "nvim/ascii.h" #include "nvim/api/private/helpers.h" #include "nvim/api/private/defs.h" +#include "nvim/api/private/dispatch.h" #include "nvim/api/buffer.h" #include "nvim/msgpack_rpc/channel.h" +#include "nvim/lua/executor.h" #include "nvim/vim.h" #include "nvim/buffer.h" #include "nvim/file_search.h" @@ -22,7 +27,9 @@ #include "nvim/memory.h" #include "nvim/message.h" #include "nvim/eval.h" +#include "nvim/eval/typval.h" #include "nvim/option.h" +#include "nvim/state.h" #include "nvim/syntax.h" #include "nvim/getchar.h" #include "nvim/os/input.h" @@ -39,6 +46,7 @@ /// @param command Ex-command string /// @param[out] err Error details (including actual VimL error), if any void nvim_command(String command, Error *err) + FUNC_API_SINCE(1) { // Run the command try_start(); @@ -56,6 +64,7 @@ void nvim_command(String command, Error *err) /// @see feedkeys() /// @see vim_strsave_escape_csi void nvim_feedkeys(String keys, String mode, Boolean escape_csi) + FUNC_API_SINCE(1) { bool remap = true; bool insert = false; @@ -122,43 +131,44 @@ void nvim_feedkeys(String keys, String mode, Boolean escape_csi) /// @return Number of bytes actually written (can be fewer than /// requested if the buffer becomes full). Integer nvim_input(String keys) - FUNC_API_ASYNC + FUNC_API_SINCE(1) FUNC_API_ASYNC { return (Integer)input_enqueue(keys); } -/// Replaces any terminal codes with the internal representation +/// Replaces terminal codes and |keycodes| (<CR>, <Esc>, ...) in a string with +/// the internal representation. /// +/// @param str String to be converted. +/// @param from_part Legacy Vim parameter. Usually true. +/// @param do_lt Also translate <lt>. Ignored if `special` is false. +/// @param special Replace |keycodes|, e.g. <CR> becomes a "\n" char. /// @see replace_termcodes /// @see cpoptions String nvim_replace_termcodes(String str, Boolean from_part, Boolean do_lt, Boolean special) + FUNC_API_SINCE(1) { if (str.size == 0) { // Empty string - return str; + return (String) { .data = NULL, .size = 0 }; } char *ptr = NULL; - // Set 'cpoptions' the way we want it. - // FLAG_CPO_BSLASH set - backslashes are *not* treated specially - // FLAG_CPO_KEYCODE set - keycodes are *not* reverse-engineered - // FLAG_CPO_SPECI unset - <Key> sequences *are* interpreted - // The third from end parameter of replace_termcodes() is true so that the - // <lt> sequence is recognised - needed for a real backslash. replace_termcodes((char_u *)str.data, str.size, (char_u **)&ptr, from_part, do_lt, special, CPO_TO_CPO_FLAGS); return cstr_as_string(ptr); } String nvim_command_output(String str, Error *err) + FUNC_API_SINCE(1) { do_cmdline_cmd("redir => v:command_output"); nvim_command(str, err); do_cmdline_cmd("redir END"); - if (err->set) { - return (String) STRING_INIT; + if (ERROR_SET(err)) { + return (String)STRING_INIT; } return cstr_to_string((char *)get_vim_var_str(VV_COMMAND_OUTPUT)); @@ -172,27 +182,30 @@ String nvim_command_output(String str, Error *err) /// @param[out] err Error details, if any /// @return Evaluation result or expanded object Object nvim_eval(String expr, Error *err) + FUNC_API_SINCE(1) { Object rv = OBJECT_INIT; // Evaluate the expression try_start(); - typval_T *expr_result = eval_expr((char_u *)expr.data, NULL); - if (!expr_result) { - api_set_error(err, Exception, _("Failed to evaluate expression")); + typval_T rettv; + if (eval0((char_u *)expr.data, &rettv, NULL, true) == FAIL) { + api_set_error(err, kErrorTypeException, "Failed to evaluate expression"); } if (!try_end(err)) { // No errors, convert the result - rv = vim_to_object(expr_result); + rv = vim_to_object(&rettv); } - // Free the vim object - free_tv(expr_result); + // Free the Vim object + tv_clear(&rettv); + return rv; } -/// Calls a VimL function with the given arguments. +/// Calls a VimL function with the given arguments +/// /// On VimL error: Returns a generic error; v:errmsg is not updated. /// /// @param fname Function to call @@ -200,11 +213,12 @@ Object nvim_eval(String expr, Error *err) /// @param[out] err Error details, if any /// @return Result of the function call Object nvim_call_function(String fname, Array args, Error *err) + FUNC_API_SINCE(1) { Object rv = OBJECT_INIT; if (args.size > MAX_FUNC_ARGS) { - api_set_error(err, Validation, - _("Function called with too many arguments.")); + api_set_error(err, kErrorTypeValidation, + "Function called with too many arguments."); return rv; } @@ -221,27 +235,45 @@ Object nvim_call_function(String fname, Array args, Error *err) // Call the function typval_T rettv; int dummy; - int r = call_func((char_u *) fname.data, (int) fname.size, - &rettv, (int) args.size, vim_args, + int r = call_func((char_u *)fname.data, (int)fname.size, + &rettv, (int)args.size, vim_args, NULL, curwin->w_cursor.lnum, curwin->w_cursor.lnum, &dummy, - true, - NULL, NULL); + true, NULL, NULL); if (r == FAIL) { - api_set_error(err, Exception, _("Error calling function.")); + api_set_error(err, kErrorTypeException, "Error calling function."); } if (!try_end(err)) { rv = vim_to_object(&rettv); } - clear_tv(&rettv); + tv_clear(&rettv); free_vim_args: while (i > 0) { - clear_tv(&vim_args[--i]); + tv_clear(&vim_args[--i]); } return rv; } +/// Execute lua code. Parameters might be passed, they are available inside +/// the chunk as `...`. The chunk can return a value. +/// +/// To evaluate an expression, it must be prefixed with "return ". For +/// instance, to call a lua function with arguments sent in and get its +/// return value back, use the code "return my_function(...)". +/// +/// @param code lua code to execute +/// @param args Arguments to the code +/// @param[out] err Details of an error encountered while parsing +/// or executing the lua code. +/// +/// @return Return value of lua code if present or NIL. +Object nvim_execute_lua(String code, Array args, Error *err) + FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY +{ + return executor_exec_lua_api(code, args, err); +} + /// Calculates the number of display cells occupied by `text`. /// <Tab> counts as one cell. /// @@ -249,9 +281,10 @@ free_vim_args: /// @param[out] err Error details, if any /// @return Number of cells Integer nvim_strwidth(String str, Error *err) + FUNC_API_SINCE(1) { if (str.size > INT_MAX) { - api_set_error(err, Validation, _("String length is too high")); + api_set_error(err, kErrorTypeValidation, "String length is too high"); return 0; } @@ -262,9 +295,10 @@ Integer nvim_strwidth(String str, Error *err) /// /// @return List of paths ArrayOf(String) nvim_list_runtime_paths(void) + FUNC_API_SINCE(1) { Array rv = ARRAY_DICT_INIT; - uint8_t *rtp = p_rtp; + char_u *rtp = p_rtp; if (*rtp == NUL) { // No paths @@ -278,13 +312,14 @@ ArrayOf(String) nvim_list_runtime_paths(void) } rtp++; } + rv.size++; // Allocate memory for the copies - rv.items = xmalloc(sizeof(Object) * rv.size); + rv.items = xmalloc(sizeof(*rv.items) * rv.size); // Reset the position rtp = p_rtp; // Start copying - for (size_t i = 0; i < rv.size && *rtp != NUL; i++) { + for (size_t i = 0; i < rv.size; i++) { rv.items[i].type = kObjectTypeString; rv.items[i].data.string.data = xmalloc(MAXPATHL); // Copy the path from 'runtimepath' to rv.items[i] @@ -303,21 +338,22 @@ ArrayOf(String) nvim_list_runtime_paths(void) /// @param dir Directory path /// @param[out] err Error details, if any void nvim_set_current_dir(String dir, Error *err) + FUNC_API_SINCE(1) { if (dir.size >= MAXPATHL) { - api_set_error(err, Validation, _("Directory string is too long")); + api_set_error(err, kErrorTypeValidation, "Directory string is too long"); return; } char string[MAXPATHL]; - strncpy(string, dir.data, dir.size); + memcpy(string, dir.data, dir.size); string[dir.size] = NUL; try_start(); - if (vim_chdir((char_u *)string)) { + if (vim_chdir((char_u *)string, kCdScopeGlobal)) { if (!try_end(err)) { - api_set_error(err, Exception, _("Failed to change directory")); + api_set_error(err, kErrorTypeException, "Failed to change directory"); } return; } @@ -331,6 +367,7 @@ void nvim_set_current_dir(String dir, Error *err) /// @param[out] err Error details, if any /// @return Current line string String nvim_get_current_line(Error *err) + FUNC_API_SINCE(1) { return buffer_get_line(curbuf->handle, curwin->w_cursor.lnum - 1, err); } @@ -340,6 +377,7 @@ String nvim_get_current_line(Error *err) /// @param line Line contents /// @param[out] err Error details, if any void nvim_set_current_line(String line, Error *err) + FUNC_API_SINCE(1) { buffer_set_line(curbuf->handle, curwin->w_cursor.lnum - 1, line, err); } @@ -348,6 +386,7 @@ void nvim_set_current_line(String line, Error *err) /// /// @param[out] err Error details, if any void nvim_del_current_line(Error *err) + FUNC_API_SINCE(1) { buffer_del_line(curbuf->handle, curwin->w_cursor.lnum - 1, err); } @@ -358,6 +397,7 @@ void nvim_del_current_line(Error *err) /// @param[out] err Error details, if any /// @return Variable value Object nvim_get_var(String name, Error *err) + FUNC_API_SINCE(1) { return dict_get_value(&globvardict, name, err); } @@ -368,8 +408,9 @@ Object nvim_get_var(String name, Error *err) /// @param value Variable value /// @param[out] err Error details, if any void nvim_set_var(String name, Object value, Error *err) + FUNC_API_SINCE(1) { - dict_set_value(&globvardict, name, value, false, false, err); + dict_set_var(&globvardict, name, value, false, false, err); } /// Removes a global (g:) variable @@ -377,8 +418,9 @@ void nvim_set_var(String name, Object value, Error *err) /// @param name Variable name /// @param[out] err Error details, if any void nvim_del_var(String name, Error *err) + FUNC_API_SINCE(1) { - dict_set_value(&globvardict, name, NIL, true, false, err); + dict_set_var(&globvardict, name, NIL, true, false, err); } /// Sets a global variable @@ -394,7 +436,7 @@ void nvim_del_var(String name, Error *err) /// or if previous value was `v:null`. Object vim_set_var(String name, Object value, Error *err) { - return dict_set_value(&globvardict, name, value, false, true, err); + return dict_set_var(&globvardict, name, value, false, true, err); } /// Removes a global variable @@ -406,7 +448,7 @@ Object vim_set_var(String name, Object value, Error *err) /// @return Old value Object vim_del_var(String name, Error *err) { - return dict_set_value(&globvardict, name, NIL, true, true, err); + return dict_set_var(&globvardict, name, NIL, true, true, err); } /// Gets a v: variable @@ -415,6 +457,7 @@ Object vim_del_var(String name, Error *err) /// @param[out] err Error details, if any /// @return Variable value Object nvim_get_vvar(String name, Error *err) + FUNC_API_SINCE(1) { return dict_get_value(&vimvardict, name, err); } @@ -423,8 +466,9 @@ Object nvim_get_vvar(String name, Error *err) /// /// @param name Option name /// @param[out] err Error details, if any -/// @return Option value +/// @return Option value (global) Object nvim_get_option(String name, Error *err) + FUNC_API_SINCE(1) { return get_option_from(NULL, SREQ_GLOBAL, name, err); } @@ -435,32 +479,38 @@ Object nvim_get_option(String name, Error *err) /// @param value New option value /// @param[out] err Error details, if any void nvim_set_option(String name, Object value, Error *err) + FUNC_API_SINCE(1) { set_option_to(NULL, SREQ_GLOBAL, name, value, err); } -/// Writes a message to vim output buffer +/// Writes a message to the Vim output buffer. Does not append "\n", the +/// message is buffered (won't display) until a linefeed is written. /// /// @param str Message void nvim_out_write(String str) + FUNC_API_SINCE(1) { write_msg(str, false); } -/// Writes a message to vim error buffer +/// Writes a message to the Vim error buffer. Does not append "\n", the +/// message is buffered (won't display) until a linefeed is written. /// /// @param str Message void nvim_err_write(String str) + FUNC_API_SINCE(1) { write_msg(str, true); } -/// Writes a message to vim error buffer. Appends a linefeed to ensure all -/// contents are written. +/// Writes a message to the Vim error buffer. Appends "\n", so the buffer is +/// flushed (and displayed). /// /// @param str Message /// @see nvim_err_write() void nvim_err_writeln(String str) + FUNC_API_SINCE(1) { nvim_err_write(str); nvim_err_write((String) { .data = "\n", .size = 1 }); @@ -470,6 +520,7 @@ void nvim_err_writeln(String str) /// /// @return List of buffer handles ArrayOf(Buffer) nvim_list_bufs(void) + FUNC_API_SINCE(1) { Array rv = ARRAY_DICT_INIT; @@ -491,6 +542,7 @@ ArrayOf(Buffer) nvim_list_bufs(void) /// /// @return Buffer handle Buffer nvim_get_current_buf(void) + FUNC_API_SINCE(1) { return curbuf->handle; } @@ -500,6 +552,7 @@ Buffer nvim_get_current_buf(void) /// @param id Buffer handle /// @param[out] err Error details, if any void nvim_set_current_buf(Buffer buffer, Error *err) + FUNC_API_SINCE(1) { buf_T *buf = find_buffer_by_handle(buffer, err); @@ -511,8 +564,8 @@ void nvim_set_current_buf(Buffer buffer, Error *err) int result = do_buffer(DOBUF_GOTO, DOBUF_FIRST, FORWARD, buf->b_fnum, 0); if (!try_end(err) && result == FAIL) { api_set_error(err, - Exception, - _("Failed to switch to buffer %d"), + kErrorTypeException, + "Failed to switch to buffer %d", buffer); } } @@ -521,6 +574,7 @@ void nvim_set_current_buf(Buffer buffer, Error *err) /// /// @return List of window handles ArrayOf(Window) nvim_list_wins(void) + FUNC_API_SINCE(1) { Array rv = ARRAY_DICT_INIT; @@ -542,6 +596,7 @@ ArrayOf(Window) nvim_list_wins(void) /// /// @return Window handle Window nvim_get_current_win(void) + FUNC_API_SINCE(1) { return curwin->handle; } @@ -550,6 +605,7 @@ Window nvim_get_current_win(void) /// /// @param handle Window handle void nvim_set_current_win(Window window, Error *err) + FUNC_API_SINCE(1) { win_T *win = find_window_by_handle(window, err); @@ -561,8 +617,8 @@ void nvim_set_current_win(Window window, Error *err) goto_tabpage_win(win_find_tabpage(win), win); if (!try_end(err) && win != curwin) { api_set_error(err, - Exception, - _("Failed to switch to window %d"), + kErrorTypeException, + "Failed to switch to window %d", window); } } @@ -571,6 +627,7 @@ void nvim_set_current_win(Window window, Error *err) /// /// @return List of tabpage handles ArrayOf(Tabpage) nvim_list_tabpages(void) + FUNC_API_SINCE(1) { Array rv = ARRAY_DICT_INIT; @@ -592,6 +649,7 @@ ArrayOf(Tabpage) nvim_list_tabpages(void) /// /// @return Tabpage handle Tabpage nvim_get_current_tabpage(void) + FUNC_API_SINCE(1) { return curtab->handle; } @@ -601,6 +659,7 @@ Tabpage nvim_get_current_tabpage(void) /// @param handle Tabpage handle /// @param[out] err Error details, if any void nvim_set_current_tabpage(Tabpage tabpage, Error *err) + FUNC_API_SINCE(1) { tabpage_T *tp = find_tab_by_handle(tabpage, err); @@ -612,8 +671,8 @@ void nvim_set_current_tabpage(Tabpage tabpage, Error *err) goto_tabpage_tp(tp, true, true); if (!try_end(err) && tp != curtab) { api_set_error(err, - Exception, - _("Failed to switch to tabpage %d"), + kErrorTypeException, + "Failed to switch to tabpage %d", tabpage); } } @@ -623,7 +682,7 @@ void nvim_set_current_tabpage(Tabpage tabpage, Error *err) /// @param channel_id Channel id (passed automatically by the dispatcher) /// @param event Event type string void nvim_subscribe(uint64_t channel_id, String event) - FUNC_API_NOEVAL + FUNC_API_SINCE(1) FUNC_API_REMOTE_ONLY { size_t length = (event.size < METHOD_MAXLEN ? event.size : METHOD_MAXLEN); char e[METHOD_MAXLEN + 1]; @@ -637,7 +696,7 @@ void nvim_subscribe(uint64_t channel_id, String event) /// @param channel_id Channel id (passed automatically by the dispatcher) /// @param event Event type string void nvim_unsubscribe(uint64_t channel_id, String event) - FUNC_API_NOEVAL + FUNC_API_SINCE(1) FUNC_API_REMOTE_ONLY { size_t length = (event.size < METHOD_MAXLEN ? event.size : @@ -649,11 +708,13 @@ void nvim_unsubscribe(uint64_t channel_id, String event) } Integer nvim_get_color_by_name(String name) + FUNC_API_SINCE(1) { - return name_to_color((uint8_t *)name.data); + return name_to_color((char_u *)name.data); } Dictionary nvim_get_color_map(void) + FUNC_API_SINCE(1) { Dictionary colors = ARRAY_DICT_INIT; @@ -665,8 +726,37 @@ Dictionary nvim_get_color_map(void) } +/// Gets the current mode. +/// mode: Mode string. |mode()| +/// blocking: true if Nvim is waiting for input. +/// +/// @returns Dictionary { "mode": String, "blocking": Boolean } +Dictionary nvim_get_mode(void) + FUNC_API_SINCE(2) FUNC_API_ASYNC +{ + Dictionary rv = ARRAY_DICT_INIT; + char *modestr = get_mode(); + bool blocked = input_blocking(); + + PUT(rv, "mode", STRING_OBJ(cstr_as_string(modestr))); + PUT(rv, "blocking", BOOLEAN_OBJ(blocked)); + + return rv; +} + +/// Get a list of dictionaries describing global (i.e. non-buffer) mappings +/// Note that the "buffer" key will be 0 to represent false. +/// +/// @param mode The abbreviation for the mode +/// @returns An array of maparg() like dictionaries describing mappings +ArrayOf(Dictionary) nvim_get_keymap(String mode) + FUNC_API_SINCE(3) +{ + return keymap_array(mode, NULL); +} + Array nvim_get_api_info(uint64_t channel_id) - FUNC_API_ASYNC FUNC_API_NOEVAL + FUNC_API_SINCE(1) FUNC_API_ASYNC FUNC_API_REMOTE_ONLY { Array rv = ARRAY_DICT_INIT; @@ -699,7 +789,7 @@ Array nvim_get_api_info(uint64_t channel_id) /// which resulted in an error, the error type and the error message. If an /// error ocurred, the values from all preceding calls will still be returned. Array nvim_call_atomic(uint64_t channel_id, Array calls, Error *err) - FUNC_API_NOEVAL + FUNC_API_SINCE(1) FUNC_API_REMOTE_ONLY { Array rv = ARRAY_DICT_INIT; Array results = ARRAY_DICT_INIT; @@ -709,30 +799,30 @@ Array nvim_call_atomic(uint64_t channel_id, Array calls, Error *err) for (i = 0; i < calls.size; i++) { if (calls.items[i].type != kObjectTypeArray) { api_set_error(err, - Validation, - _("All items in calls array must be arrays")); + kErrorTypeValidation, + "All items in calls array must be arrays"); goto validation_error; } Array call = calls.items[i].data.array; if (call.size != 2) { api_set_error(err, - Validation, - _("All items in calls array must be arrays of size 2")); + kErrorTypeValidation, + "All items in calls array must be arrays of size 2"); goto validation_error; } if (call.items[0].type != kObjectTypeString) { api_set_error(err, - Validation, - _("name must be String")); + kErrorTypeValidation, + "Name must be String"); goto validation_error; } String name = call.items[0].data.string; if (call.items[1].type != kObjectTypeArray) { api_set_error(err, - Validation, - _("args must be Array")); + kErrorTypeValidation, + "Args must be Array"); goto validation_error; } Array args = call.items[1].data.array; @@ -740,7 +830,7 @@ Array nvim_call_atomic(uint64_t channel_id, Array calls, Error *err) MsgpackRpcRequestHandler handler = msgpack_rpc_get_handler_for(name.data, name.size); Object result = handler.fn(channel_id, args, &nested_error); - if (nested_error.set) { + if (ERROR_SET(&nested_error)) { // error handled after loop break; } @@ -749,7 +839,7 @@ Array nvim_call_atomic(uint64_t channel_id, Array calls, Error *err) } ADD(rv, ARRAY_OBJ(results)); - if (nested_error.set) { + if (ERROR_SET(&nested_error)) { Array errval = ARRAY_DICT_INIT; ADD(errval, INTEGER_OBJ((Integer)i)); ADD(errval, INTEGER_OBJ(nested_error.type)); @@ -758,10 +848,12 @@ Array nvim_call_atomic(uint64_t channel_id, Array calls, Error *err) } else { ADD(rv, NIL); } - return rv; + goto theend; validation_error: api_free_array(results); +theend: + api_clear_error(&nested_error); return rv; } @@ -780,7 +872,7 @@ static void write_msg(String message, bool to_err) #define PUSH_CHAR(i, pos, line_buf, msg) \ if (message.data[i] == NL || pos == LINE_BUFFER_SIZE - 1) { \ line_buf[pos] = NUL; \ - msg((uint8_t *)line_buf); \ + msg((char_u *)line_buf); \ pos = 0; \ continue; \ } \ @@ -798,3 +890,57 @@ static void write_msg(String message, bool to_err) --no_wait_return; msg_end(); } + +// Functions used for testing purposes + +/// Returns object given as argument +/// +/// This API function is used for testing. One should not rely on its presence +/// in plugins. +/// +/// @param[in] obj Object to return. +/// +/// @return its argument. +Object nvim__id(Object obj) +{ + return copy_object(obj); +} + +/// Returns array given as argument +/// +/// This API function is used for testing. One should not rely on its presence +/// in plugins. +/// +/// @param[in] arr Array to return. +/// +/// @return its argument. +Array nvim__id_array(Array arr) +{ + return copy_object(ARRAY_OBJ(arr)).data.array; +} + +/// Returns dictionary given as argument +/// +/// This API function is used for testing. One should not rely on its presence +/// in plugins. +/// +/// @param[in] dct Dictionary to return. +/// +/// @return its argument. +Dictionary nvim__id_dictionary(Dictionary dct) +{ + return copy_object(DICTIONARY_OBJ(dct)).data.dictionary; +} + +/// Returns floating-point value given as argument +/// +/// This API function is used for testing. One should not rely on its presence +/// in plugins. +/// +/// @param[in] flt Value to return. +/// +/// @return its argument. +Float nvim__id_float(Float flt) +{ + return flt; +} diff --git a/src/nvim/api/window.c b/src/nvim/api/window.c index 1f555a6a05..9bc91ef8fb 100644 --- a/src/nvim/api/window.c +++ b/src/nvim/api/window.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #include <stdbool.h> #include <stdint.h> #include <stdlib.h> @@ -19,6 +22,7 @@ /// @param[out] err Error details, if any /// @return Buffer handle Buffer nvim_win_get_buf(Window window, Error *err) + FUNC_API_SINCE(1) { win_T *win = find_window_by_handle(window, err); @@ -35,6 +39,7 @@ Buffer nvim_win_get_buf(Window window, Error *err) /// @param[out] err Error details, if any /// @return (row, col) tuple ArrayOf(Integer, 2) nvim_win_get_cursor(Window window, Error *err) + FUNC_API_SINCE(1) { Array rv = ARRAY_DICT_INIT; win_T *win = find_window_by_handle(window, err); @@ -53,18 +58,19 @@ ArrayOf(Integer, 2) nvim_win_get_cursor(Window window, Error *err) /// @param pos (row, col) tuple representing the new position /// @param[out] err Error details, if any void nvim_win_set_cursor(Window window, ArrayOf(Integer, 2) pos, Error *err) + FUNC_API_SINCE(1) { win_T *win = find_window_by_handle(window, err); - if (pos.size != 2 || pos.items[0].type != kObjectTypeInteger - || pos.items[1].type != kObjectTypeInteger) { - api_set_error(err, - Validation, - _("Argument \"pos\" must be a [row, col] array")); + if (!win) { return; } - if (!win) { + if (pos.size != 2 || pos.items[0].type != kObjectTypeInteger + || pos.items[1].type != kObjectTypeInteger) { + api_set_error(err, + kErrorTypeValidation, + "Argument \"pos\" must be a [row, col] array"); return; } @@ -72,12 +78,12 @@ void nvim_win_set_cursor(Window window, ArrayOf(Integer, 2) pos, Error *err) int64_t col = pos.items[1].data.integer; if (row <= 0 || row > win->w_buffer->b_ml.ml_line_count) { - api_set_error(err, Validation, _("Cursor position outside buffer")); + api_set_error(err, kErrorTypeValidation, "Cursor position outside buffer"); return; } if (col > MAXCOL || col < 0) { - api_set_error(err, Validation, _("Column value outside range")); + api_set_error(err, kErrorTypeValidation, "Column value outside range"); return; } @@ -99,6 +105,7 @@ void nvim_win_set_cursor(Window window, ArrayOf(Integer, 2) pos, Error *err) /// @param[out] err Error details, if any /// @return Height as a count of rows Integer nvim_win_get_height(Window window, Error *err) + FUNC_API_SINCE(1) { win_T *win = find_window_by_handle(window, err); @@ -116,6 +123,7 @@ Integer nvim_win_get_height(Window window, Error *err) /// @param height Height as a count of rows /// @param[out] err Error details, if any void nvim_win_set_height(Window window, Integer height, Error *err) + FUNC_API_SINCE(1) { win_T *win = find_window_by_handle(window, err); @@ -124,7 +132,7 @@ void nvim_win_set_height(Window window, Integer height, Error *err) } if (height > INT_MAX || height < INT_MIN) { - api_set_error(err, Validation, _("Height value outside range")); + api_set_error(err, kErrorTypeValidation, "Height value outside range"); return; } @@ -142,6 +150,7 @@ void nvim_win_set_height(Window window, Integer height, Error *err) /// @param[out] err Error details, if any /// @return Width as a count of columns Integer nvim_win_get_width(Window window, Error *err) + FUNC_API_SINCE(1) { win_T *win = find_window_by_handle(window, err); @@ -159,6 +168,7 @@ Integer nvim_win_get_width(Window window, Error *err) /// @param width Width as a count of columns /// @param[out] err Error details, if any void nvim_win_set_width(Window window, Integer width, Error *err) + FUNC_API_SINCE(1) { win_T *win = find_window_by_handle(window, err); @@ -167,7 +177,7 @@ void nvim_win_set_width(Window window, Integer width, Error *err) } if (width > INT_MAX || width < INT_MIN) { - api_set_error(err, Validation, _("Width value outside range")); + api_set_error(err, kErrorTypeValidation, "Width value outside range"); return; } @@ -186,6 +196,7 @@ void nvim_win_set_width(Window window, Integer width, Error *err) /// @param[out] err Error details, if any /// @return Variable value Object nvim_win_get_var(Window window, String name, Error *err) + FUNC_API_SINCE(1) { win_T *win = find_window_by_handle(window, err); @@ -203,6 +214,7 @@ Object nvim_win_get_var(Window window, String name, Error *err) /// @param value Variable value /// @param[out] err Error details, if any void nvim_win_set_var(Window window, String name, Object value, Error *err) + FUNC_API_SINCE(1) { win_T *win = find_window_by_handle(window, err); @@ -210,7 +222,7 @@ void nvim_win_set_var(Window window, String name, Object value, Error *err) return; } - dict_set_value(win->w_vars, name, value, false, false, err); + dict_set_var(win->w_vars, name, value, false, false, err); } /// Removes a window-scoped (w:) variable @@ -219,6 +231,7 @@ void nvim_win_set_var(Window window, String name, Object value, Error *err) /// @param name Variable name /// @param[out] err Error details, if any void nvim_win_del_var(Window window, String name, Error *err) + FUNC_API_SINCE(1) { win_T *win = find_window_by_handle(window, err); @@ -226,7 +239,7 @@ void nvim_win_del_var(Window window, String name, Error *err) return; } - dict_set_value(win->w_vars, name, NIL, true, false, err); + dict_set_var(win->w_vars, name, NIL, true, false, err); } /// Sets a window-scoped (w:) variable @@ -249,7 +262,7 @@ Object window_set_var(Window window, String name, Object value, Error *err) return (Object) OBJECT_INIT; } - return dict_set_value(win->w_vars, name, value, false, true, err); + return dict_set_var(win->w_vars, name, value, false, true, err); } /// Removes a window-scoped (w:) variable @@ -268,7 +281,7 @@ Object window_del_var(Window window, String name, Error *err) return (Object) OBJECT_INIT; } - return dict_set_value(win->w_vars, name, NIL, true, true, err); + return dict_set_var(win->w_vars, name, NIL, true, true, err); } /// Gets a window option value @@ -278,6 +291,7 @@ Object window_del_var(Window window, String name, Error *err) /// @param[out] err Error details, if any /// @return Option value Object nvim_win_get_option(Window window, String name, Error *err) + FUNC_API_SINCE(1) { win_T *win = find_window_by_handle(window, err); @@ -296,6 +310,7 @@ Object nvim_win_get_option(Window window, String name, Error *err) /// @param value Option value /// @param[out] err Error details, if any void nvim_win_set_option(Window window, String name, Object value, Error *err) + FUNC_API_SINCE(1) { win_T *win = find_window_by_handle(window, err); @@ -312,6 +327,7 @@ void nvim_win_set_option(Window window, String name, Object value, Error *err) /// @param[out] err Error details, if any /// @return (row, col) tuple with the window position ArrayOf(Integer, 2) nvim_win_get_position(Window window, Error *err) + FUNC_API_SINCE(1) { Array rv = ARRAY_DICT_INIT; win_T *win = find_window_by_handle(window, err); @@ -330,6 +346,7 @@ ArrayOf(Integer, 2) nvim_win_get_position(Window window, Error *err) /// @param[out] err Error details, if any /// @return Tabpage that contains the window Tabpage nvim_win_get_tabpage(Window window, Error *err) + FUNC_API_SINCE(1) { Tabpage rv = 0; win_T *win = find_window_by_handle(window, err); @@ -347,6 +364,7 @@ Tabpage nvim_win_get_tabpage(Window window, Error *err) /// @param[out] err Error details, if any /// @return Window number Integer nvim_win_get_number(Window window, Error *err) + FUNC_API_SINCE(1) { int rv = 0; win_T *win = find_window_by_handle(window, err); @@ -366,8 +384,11 @@ Integer nvim_win_get_number(Window window, Error *err) /// @param window Window handle /// @return true if the window is valid, false otherwise Boolean nvim_win_is_valid(Window window) + FUNC_API_SINCE(1) { Error stub = ERROR_INIT; - return find_window_by_handle(window, &stub) != NULL; + Boolean ret = find_window_by_handle(window, &stub) != NULL; + api_clear_error(&stub); + return ret; } diff --git a/src/nvim/arabic.c b/src/nvim/arabic.c index db97bd9dc4..1ef51d2a2a 100644 --- a/src/nvim/arabic.c +++ b/src/nvim/arabic.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + /// @file arabic.c /// /// Functions for Arabic language. diff --git a/src/nvim/ascii.h b/src/nvim/ascii.h index 44ff540b40..adde91f9ec 100644 --- a/src/nvim/ascii.h +++ b/src/nvim/ascii.h @@ -8,9 +8,11 @@ // Definitions of various common control characters. -#define CharOrd(x) ((x) < 'a' ? (x) - 'A' : (x) - 'a') -#define CharOrdLow(x) ((x) - 'a') -#define CharOrdUp(x) ((x) - 'A') +#define CharOrd(x) ((uint8_t)(x) < 'a' \ + ? (uint8_t)(x) - 'A'\ + : (uint8_t)(x) - 'a') +#define CharOrdLow(x) ((uint8_t)(x) - 'a') +#define CharOrdUp(x) ((uint8_t)(x) - 'A') #define ROT13(c, a) (((((c) - (a)) + 13) % 26) + (a)) #define NUL '\000' @@ -18,15 +20,14 @@ #define BS '\010' #define TAB '\011' #define NL '\012' -#define NL_STR (char_u *)"\012" +#define NL_STR "\012" #define FF '\014' #define CAR '\015' /* CR is used by Mac OS X */ #define ESC '\033' -#define ESC_STR (char_u *)"\033" -#define ESC_STR_nc "\033" +#define ESC_STR "\033" #define DEL 0x7f -#define DEL_STR (char_u *)"\177" -#define CSI 0x9b /* Control Sequence Introducer */ +#define DEL_STR "\177" +#define CSI 0x9b // Control Sequence Introducer #define CSI_STR "\233" #define DCS 0x90 /* Device Control String */ #define STERM 0x9c /* String Terminator */ diff --git a/src/nvim/auevents.lua b/src/nvim/auevents.lua index 8d891effae..68a47c244f 100644 --- a/src/nvim/auevents.lua +++ b/src/nvim/auevents.lua @@ -28,6 +28,7 @@ return { 'CursorHoldI', -- idem, in Insert mode 'CursorMoved', -- cursor was moved 'CursorMovedI', -- cursor was moved in Insert mode + 'DirChanged', -- directory changed 'EncodingChanged', -- after changing the 'encoding' option 'FileAppendCmd', -- append to a file using command 'FileAppendPost', -- after appending to a file @@ -89,6 +90,7 @@ return { 'VimLeave', -- before exiting Vim 'VimLeavePre', -- before exiting Vim and writing ShaDa file 'VimResized', -- after Vim window was resized + 'WinNew', -- when entering a new window 'WinEnter', -- after entering a window 'WinLeave', -- before leaving a window }, @@ -101,6 +103,7 @@ return { -- List of neovim-specific events or aliases for the purpose of generating -- syntax file neovim_specific = { + DirChanged=true, TabClosed=true, TabNew=true, TabNewEntered=true, diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index d9fdc80c60..724a8578ac 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + /* * buffer.c: functions for dealing with the buffer structure */ @@ -21,6 +24,7 @@ #include <inttypes.h> #include "nvim/api/private/handle.h" +#include "nvim/api/private/helpers.h" #include "nvim/ascii.h" #include "nvim/assert.h" #include "nvim/vim.h" @@ -70,6 +74,12 @@ #include "nvim/os/time.h" #include "nvim/os/input.h" +typedef enum { + kBLSUnchanged = 0, + kBLSChanged = 1, + kBLSDeleted = 2, +} BufhlLineStatus; + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "buffer.c.generated.h" #endif @@ -78,6 +88,60 @@ static char *msg_loclist = N_("[Location List]"); static char *msg_qflist = N_("[Quickfix List]"); static char *e_auabort = N_("E855: Autocommands caused command to abort"); +// Number of times free_buffer() was called. +static int buf_free_count = 0; + +// Read data from buffer for retrying. +static int +read_buffer( + int read_stdin, // read file from stdin, otherwise fifo + exarg_T *eap, // for forced 'ff' and 'fenc' or NULL + int flags) // extra flags for readfile() +{ + int retval = OK; + linenr_T line_count; + + // + // Read from the buffer which the text is already filled in and append at + // the end. This makes it possible to retry when 'fileformat' or + // 'fileencoding' was guessed wrong. + // + line_count = curbuf->b_ml.ml_line_count; + retval = readfile( + read_stdin ? NULL : curbuf->b_ffname, + read_stdin ? NULL : curbuf->b_fname, + (linenr_T)line_count, (linenr_T)0, (linenr_T)MAXLNUM, eap, + flags | READ_BUFFER); + if (retval == OK) { + // Delete the binary lines. + while (--line_count >= 0) { + ml_delete((linenr_T)1, false); + } + } else { + // Delete the converted lines. + while (curbuf->b_ml.ml_line_count > line_count) { + ml_delete(line_count, false); + } + } + // Put the cursor on the first line. + curwin->w_cursor.lnum = 1; + curwin->w_cursor.col = 0; + + if (read_stdin) { + // Set or reset 'modified' before executing autocommands, so that + // it can be changed there. + if (!readonlymode && !bufempty()) { + changed(); + } else if (retval != FAIL) { + unchanged(curbuf, false); + } + + apply_autocmds_retval(EVENT_STDINREADPOST, NULL, NULL, false, + curbuf, &retval); + } + return retval; +} + /* * Open current buffer, that is: open the memfile and read the file into * memory. @@ -91,8 +155,9 @@ open_buffer ( ) { int retval = OK; - buf_T *old_curbuf; + bufref_T old_curbuf; long old_tw = curbuf->b_p_tw; + int read_fifo = false; /* * The 'readonly' flag is only set when BF_NEVERLOADED is being reset. @@ -133,23 +198,55 @@ open_buffer ( return FAIL; } - /* The autocommands in readfile() may change the buffer, but only AFTER - * reading the file. */ - old_curbuf = curbuf; - modified_was_set = FALSE; + // The autocommands in readfile() may change the buffer, but only AFTER + // reading the file. + set_bufref(&old_curbuf, curbuf); + modified_was_set = false; /* mark cursor position as being invalid */ curwin->w_valid = 0; if (curbuf->b_ffname != NULL) { int old_msg_silent = msg_silent; +#ifdef UNIX + int save_bin = curbuf->b_p_bin; + int perm; + + perm = os_getperm((const char *)curbuf->b_ffname); + if (perm >= 0 && (0 +# ifdef S_ISFIFO + || S_ISFIFO(perm) +# endif +# ifdef S_ISSOCK + || S_ISSOCK(perm) +# endif +# ifdef OPEN_CHR_FILES + || (S_ISCHR(perm) + && is_dev_fd_file(curbuf->b_ffname)) +# endif + ) + ) { + read_fifo = true; + } + if (read_fifo) { + curbuf->b_p_bin = true; + } +#endif if (shortmess(SHM_FILEINFO)) { msg_silent = 1; } retval = readfile(curbuf->b_ffname, curbuf->b_fname, (linenr_T)0, (linenr_T)0, (linenr_T)MAXLNUM, eap, - flags | READ_NEW); + flags | READ_NEW | (read_fifo ? READ_FIFO : 0)); +#ifdef UNIX + if (read_fifo) { + curbuf->b_p_bin = save_bin; + if (retval == OK) { + retval = read_buffer(false, eap, flags); + } + } +#endif msg_silent = old_msg_silent; // Help buffer is filtered. @@ -158,7 +255,6 @@ open_buffer ( } } else if (read_stdin) { int save_bin = curbuf->b_p_bin; - linenr_T line_count; /* * First read the text in binary mode into the buffer. @@ -172,56 +268,31 @@ open_buffer ( flags | (READ_NEW + READ_STDIN)); curbuf->b_p_bin = save_bin; if (retval == OK) { - line_count = curbuf->b_ml.ml_line_count; - retval = readfile(NULL, NULL, (linenr_T)line_count, - (linenr_T)0, (linenr_T)MAXLNUM, eap, - flags | READ_BUFFER); - if (retval == OK) { - /* Delete the binary lines. */ - while (--line_count >= 0) - ml_delete((linenr_T)1, FALSE); - } else { - /* Delete the converted lines. */ - while (curbuf->b_ml.ml_line_count > line_count) - ml_delete(line_count, FALSE); - } - /* Put the cursor on the first line. */ - curwin->w_cursor.lnum = 1; - curwin->w_cursor.col = 0; - - /* Set or reset 'modified' before executing autocommands, so that - * it can be changed there. */ - if (!readonlymode && !bufempty()) - changed(); - else if (retval != FAIL) - unchanged(curbuf, FALSE); - apply_autocmds_retval(EVENT_STDINREADPOST, NULL, NULL, FALSE, - curbuf, &retval); + retval = read_buffer(true, eap, flags); } } /* if first time loading this buffer, init b_chartab[] */ if (curbuf->b_flags & BF_NEVERLOADED) { - (void)buf_init_chartab(curbuf, FALSE); + (void)buf_init_chartab(curbuf, false); parse_cino(curbuf); } - /* - * Set/reset the Changed flag first, autocmds may change the buffer. - * Apply the automatic commands, before processing the modelines. - * So the modelines have priority over auto commands. - */ - /* When reading stdin, the buffer contents always needs writing, so set - * the changed flag. Unless in readonly mode: "ls | nvim -R -". - * When interrupted and 'cpoptions' contains 'i' set changed flag. */ + // Set/reset the Changed flag first, autocmds may change the buffer. + // Apply the automatic commands, before processing the modelines. + // So the modelines have priority over auto commands. + + // When reading stdin, the buffer contents always needs writing, so set + // the changed flag. Unless in readonly mode: "ls | nvim -R -". + // When interrupted and 'cpoptions' contains 'i' set changed flag. if ((got_int && vim_strchr(p_cpo, CPO_INTMOD) != NULL) - || modified_was_set /* ":set modified" used in autocmd */ - || (aborting() && vim_strchr(p_cpo, CPO_INTMOD) != NULL) - ) + || modified_was_set // ":set modified" used in autocmd + || (aborting() && vim_strchr(p_cpo, CPO_INTMOD) != NULL)) { changed(); - else if (retval != FAIL && !read_stdin) - unchanged(curbuf, FALSE); - save_file_ff(curbuf); /* keep this fileformat */ + } else if (retval != FAIL && !read_stdin && !read_fifo) { + unchanged(curbuf, false); + } + save_file_ff(curbuf); // keep this fileformat /* require "!" to overwrite the file, because it wasn't read completely */ if (aborting()) @@ -246,11 +317,11 @@ open_buffer ( * The autocommands may have changed the current buffer. Apply the * modelines to the correct buffer, if it still exists and is loaded. */ - if (buf_valid(old_curbuf) && old_curbuf->b_ml.ml_mfp != NULL) { + if (bufref_valid(&old_curbuf) && old_curbuf.br_buf->b_ml.ml_mfp != NULL) { aco_save_T aco; - /* Go to the buffer that was opened. */ - aucmd_prepbuf(&aco, old_curbuf); + // Go to the buffer that was opened. + aucmd_prepbuf(&aco, old_curbuf.br_buf); do_modelines(0); curbuf->b_flags &= ~(BF_CHECK_RO | BF_NEVERLOADED); @@ -264,14 +335,45 @@ open_buffer ( return retval; } -/// Check that "buf" points to a valid buffer (in the buffer list). +/// Store "buf" in "bufref" and set the free count. +/// +/// @param bufref Reference to be used for the buffer. +/// @param buf The buffer to reference. +void set_bufref(bufref_T *bufref, buf_T *buf) +{ + bufref->br_buf = buf; + bufref->br_fnum = buf->b_fnum; + bufref->br_buf_free_count = buf_free_count; +} + +/// Return true if "bufref->br_buf" points to the same buffer as when +/// set_bufref() was called and it is a valid buffer. +/// Only goes through the buffer list if buf_free_count changed. +/// Also checks if b_fnum is still the same, a :bwipe followed by :new might get +/// the same allocated memory, but it's a different buffer. +/// +/// @param bufref Buffer reference to check for. +bool bufref_valid(bufref_T *bufref) +{ + return bufref->br_buf_free_count == buf_free_count + ? true + : buf_valid(bufref->br_buf) && bufref->br_fnum == bufref->br_buf->b_fnum; +} + +/// Check that "buf" points to a valid buffer in the buffer list. +/// +/// Can be slow if there are many buffers, prefer using bufref_valid(). +/// +/// @param buf The buffer to check for. bool buf_valid(buf_T *buf) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT { if (buf == NULL) { return false; } - FOR_ALL_BUFFERS(bp) { + // Assume that we more often have a recent buffer, + // start with the last one. + for (buf_T *bp = lastbuf; bp != NULL; bp = bp->b_prev) { if (bp == buf) { return true; } @@ -303,6 +405,10 @@ void close_buffer(win_T *win, buf_T *buf, int action, int abort_if_last) bool del_buf = (action == DOBUF_DEL || action == DOBUF_WIPE); bool wipe_buf = (action == DOBUF_WIPE); + bool is_curwin = (curwin != NULL && curwin->w_buffer == buf); + win_T *the_curwin = curwin; + tabpage_T *the_curtab = curtab; + // Force unloading or deleting when 'bufhidden' says so, but not for terminal // buffers. // The caller must take care of NOT deleting/freeing when 'bufhidden' is @@ -326,6 +432,13 @@ void close_buffer(win_T *win, buf_T *buf, int action, int abort_if_last) wipe_buf = true; } + // Disallow deleting the buffer when it is locked (already being closed or + // halfway a command that relies on it). Unloading is allowed. + if (buf->b_locked > 0 && (del_buf || wipe_buf)) { + EMSG(_("E937: Attempt to delete a buffer that is in use")); + return; + } + if (win_valid_any_tab(win)) { // Set b_last_cursor when closing the last window for the buffer. // Remember the last cursor position and window options of the buffer. @@ -339,35 +452,36 @@ void close_buffer(win_T *win, buf_T *buf, int action, int abort_if_last) win->w_cursor.col, TRUE); } + bufref_T bufref; + set_bufref(&bufref, buf); + /* When the buffer is no longer in a window, trigger BufWinLeave */ if (buf->b_nwindows == 1) { - buf->b_closing = true; - apply_autocmds(EVENT_BUFWINLEAVE, buf->b_fname, buf->b_fname, - FALSE, buf); - if (!buf_valid(buf)) { - /* Autocommands deleted the buffer. */ + buf->b_locked++; + if (apply_autocmds(EVENT_BUFWINLEAVE, buf->b_fname, buf->b_fname, false, + buf) && !bufref_valid(&bufref)) { + // Autocommands deleted the buffer. EMSG(_(e_auabort)); return; } - buf->b_closing = false; + buf->b_locked--; if (abort_if_last && one_window()) { /* Autocommands made this the only window. */ EMSG(_(e_auabort)); return; } - /* When the buffer becomes hidden, but is not unloaded, trigger - * BufHidden */ + // When the buffer becomes hidden, but is not unloaded, trigger + // BufHidden if (!unload_buf) { - buf->b_closing = true; - apply_autocmds(EVENT_BUFHIDDEN, buf->b_fname, buf->b_fname, - FALSE, buf); - if (!buf_valid(buf)) { - /* Autocommands deleted the buffer. */ + buf->b_locked++; + if (apply_autocmds(EVENT_BUFHIDDEN, buf->b_fname, buf->b_fname, false, + buf) && !bufref_valid(&bufref)) { + // Autocommands deleted the buffer. EMSG(_(e_auabort)); return; } - buf->b_closing = false; + buf->b_locked--; if (abort_if_last && one_window()) { /* Autocommands made this the only window. */ EMSG(_(e_auabort)); @@ -377,6 +491,16 @@ void close_buffer(win_T *win, buf_T *buf, int action, int abort_if_last) if (aborting()) /* autocmds may abort script processing */ return; } + + // If the buffer was in curwin and the window has changed, go back to that + // window, if it still exists. This avoids that ":edit x" triggering a + // "tabnext" BufUnload autocmd leaves a window behind without a buffer. + if (is_curwin && curwin != the_curwin && win_valid_any_tab(the_curwin)) { + block_autocmds(); + goto_tabpage_win(the_curtab, the_curwin); + unblock_autocmds(); + } + int nwindows = buf->b_nwindows; /* decrease the link count from windows (unless not in any window) */ @@ -390,7 +514,7 @@ void close_buffer(win_T *win, buf_T *buf, int action, int abort_if_last) if (buf->terminal) { terminal_close(buf->terminal, NULL); - } + } /* Always remove the buffer when there is no file name. */ if (buf->b_ffname == NULL) @@ -403,23 +527,29 @@ void close_buffer(win_T *win, buf_T *buf, int action, int abort_if_last) /* Remember if we are closing the current buffer. Restore the number of * windows, so that autocommands in buf_freeall() don't get confused. */ bool is_curbuf = (buf == curbuf); + + // When closing the current buffer stop Visual mode before freeing + // anything. + if (is_curbuf && VIsual_active +#if defined(EXITFREE) + && !entered_free_all_mem +#endif + ) { + end_visual_mode(); + } + buf->b_nwindows = nwindows; buf_freeall(buf, (del_buf ? BFA_DEL : 0) + (wipe_buf ? BFA_WIPE : 0)); - if (win_valid_any_tab(win) && win->w_buffer == buf) { - win->w_buffer = NULL; // make sure we don't use the buffer now - } - /* Autocommands may have deleted the buffer. */ - if (!buf_valid(buf)) + if (!bufref_valid(&bufref)) { + // Autocommands may have deleted the buffer. return; - if (aborting()) /* autocmds may abort script processing */ + } + if (aborting()) { + // Autocmds may abort script processing. return; - - /* Autocommands may have opened or closed windows for this buffer. - * Decrement the count for the close we do here. */ - if (buf->b_nwindows > 0) - --buf->b_nwindows; + } /* * It's possible that autocommands change curbuf to the one being deleted. @@ -431,6 +561,16 @@ void close_buffer(win_T *win, buf_T *buf, int action, int abort_if_last) if (buf == curbuf && !is_curbuf) return; + if (win_valid_any_tab(win) && win->w_buffer == buf) { + win->w_buffer = NULL; // make sure we don't use the buffer now + } + + // Autocommands may have opened or closed windows for this buffer. + // Decrement the count for the close we do here. + if (buf->b_nwindows > 0) { + buf->b_nwindows--; + } + /* Change directories when the 'acd' option is set. */ do_autochdir(); @@ -508,25 +648,32 @@ void buf_freeall(buf_T *buf, int flags) tabpage_T *the_curtab = curtab; // Make sure the buffer isn't closed by autocommands. - buf->b_closing = true; - if (buf->b_ml.ml_mfp != NULL) { - apply_autocmds(EVENT_BUFUNLOAD, buf->b_fname, buf->b_fname, false, buf); - if (!buf_valid(buf)) { // autocommands may delete the buffer - return; - } + buf->b_locked++; + + bufref_T bufref; + set_bufref(&bufref, buf); + + if ((buf->b_ml.ml_mfp != NULL) + && apply_autocmds(EVENT_BUFUNLOAD, buf->b_fname, buf->b_fname, false, buf) + && !bufref_valid(&bufref)) { + // Autocommands deleted the buffer. + return; } - if ((flags & BFA_DEL) && buf->b_p_bl) { - apply_autocmds(EVENT_BUFDELETE, buf->b_fname, buf->b_fname, FALSE, buf); - if (!buf_valid(buf)) /* autocommands may delete the buffer */ - return; + if ((flags & BFA_DEL) + && buf->b_p_bl + && apply_autocmds(EVENT_BUFDELETE, buf->b_fname, buf->b_fname, false, buf) + && !bufref_valid(&bufref)) { + // Autocommands may delete the buffer. + return; } - if (flags & BFA_WIPE) { - apply_autocmds(EVENT_BUFWIPEOUT, buf->b_fname, buf->b_fname, - FALSE, buf); - if (!buf_valid(buf)) /* autocommands may delete the buffer */ - return; + if ((flags & BFA_WIPE) + && apply_autocmds(EVENT_BUFWIPEOUT, buf->b_fname, buf->b_fname, false, + buf) + && !bufref_valid(&bufref)) { + // Autocommands may delete the buffer. + return; } - buf->b_closing = false; + buf->b_locked--; // If the buffer was in curwin and the window has changed, go back to that // window, if it still exists. This avoids that ":edit x" triggering a @@ -548,10 +695,11 @@ void buf_freeall(buf_T *buf, int flags) */ if (buf == curbuf && !is_curbuf) return; - diff_buf_delete(buf); /* Can't use 'diff' for unloaded buffer. */ - /* Remove any ownsyntax, unless exiting. */ - if (firstwin != NULL && curwin->w_buffer == buf) + diff_buf_delete(buf); // Can't use 'diff' for unloaded buffer. + // Remove any ownsyntax, unless exiting. + if (curwin != NULL && curwin->w_buffer == buf) { reset_synblock(curwin); + } /* No folds in an empty buffer. */ FOR_ALL_TAB_WINDOWS(tp, win) { @@ -577,10 +725,11 @@ void buf_freeall(buf_T *buf, int flags) static void free_buffer(buf_T *buf) { handle_unregister_buffer(buf); - free_buffer_stuff(buf, TRUE); + buf_free_count++; + free_buffer_stuff(buf, true); unref_var_dict(buf->b_vars); aubuflocal_remove(buf); - dict_unref(buf->additional_data); + tv_dict_unref(buf->additional_data); clear_fmark(&buf->b_last_cursor); clear_fmark(&buf->b_last_insert); clear_fmark(&buf->b_last_change); @@ -616,8 +765,18 @@ free_buffer_stuff ( free_buf_options(buf, true); ga_clear(&buf->b_s.b_langp); } + { + // Avoid loosing b:changedtick when deleting buffer: clearing variables + // implies using clear_tv() on b:changedtick and that sets changedtick to + // zero. + hashitem_T *const changedtick_hi = hash_find( + &buf->b_vars->dv_hashtab, (const char_u *)"changedtick"); + assert(changedtick_hi != NULL); + hash_remove(&buf->b_vars->dv_hashtab, changedtick_hi); + } vars_clear(&buf->b_vars->dv_hashtab); // free all internal variables hash_init(&buf->b_vars->dv_hashtab); + buf_init_changedtick(buf); uc_clear(&buf->b_ucmds); // clear local user commands buf_delete_signs(buf); // delete any signs bufhl_clear_all(buf); // delete any highligts @@ -650,11 +809,13 @@ static void clear_wininfo(buf_T *buf) */ void goto_buffer(exarg_T *eap, int start, int dir, int count) { - (void)do_buffer(*eap->cmd == 's' ? DOBUF_SPLIT : DOBUF_GOTO, - start, dir, count, eap->forceit); - buf_T *old_curbuf = curbuf; + bufref_T old_curbuf; + set_bufref(&old_curbuf, curbuf); swap_exists_action = SEA_DIALOG; + (void)do_buffer(*eap->cmd == 's' ? DOBUF_SPLIT : DOBUF_GOTO, + start, dir, count, eap->forceit); + if (swap_exists_action == SEA_QUIT && *eap->cmd == 's') { cleanup_T cs; @@ -671,18 +832,20 @@ void goto_buffer(exarg_T *eap, int start, int dir, int count) * new aborting error, interrupt, or uncaught exception. */ leave_cleanup(&cs); } else { - handle_swap_exists(old_curbuf); + handle_swap_exists(&old_curbuf); } } -/* - * Handle the situation of swap_exists_action being set. - * It is allowed for "old_curbuf" to be NULL or invalid. - */ -void handle_swap_exists(buf_T *old_curbuf) +/// Handle the situation of swap_exists_action being set. +/// +/// It is allowed for "old_curbuf" to be NULL or invalid. +/// +/// @param old_curbuf The buffer to check for. +void handle_swap_exists(bufref_T *old_curbuf) { cleanup_T cs; long old_tw = curbuf->b_p_tw; + buf_T *buf; if (swap_exists_action == SEA_QUIT) { /* Reset the error/interrupt/exception state here so that @@ -695,13 +858,18 @@ void handle_swap_exists(buf_T *old_curbuf) swap_exists_action = SEA_NONE; // don't want it again swap_exists_did_quit = true; close_buffer(curwin, curbuf, DOBUF_UNLOAD, false); - if (!buf_valid(old_curbuf) || old_curbuf == curbuf) { - old_curbuf = buflist_new(NULL, NULL, 1L, BLN_CURBUF | BLN_LISTED); + if (old_curbuf == NULL + || !bufref_valid(old_curbuf) + || old_curbuf->br_buf == curbuf) { + buf = buflist_new(NULL, NULL, 1L, BLN_CURBUF | BLN_LISTED); + } else { + buf = old_curbuf->br_buf; } - if (old_curbuf != NULL) { - enter_buffer(old_curbuf); - if (old_tw != curbuf->b_p_tw) + if (buf != NULL) { + enter_buffer(buf); + if (old_tw != curbuf->b_p_tw) { check_colorcolumn(curwin); + } } /* If "old_curbuf" is NULL we are in big trouble here... */ @@ -724,7 +892,7 @@ void handle_swap_exists(buf_T *old_curbuf) * new aborting error, interrupt, or uncaught exception. */ leave_cleanup(&cs); } - swap_exists_action = SEA_NONE; + swap_exists_action = SEA_NONE; // -V519 } /* @@ -852,6 +1020,9 @@ static int empty_curbuf(int close_others, int forceit, int action) return FAIL; } + bufref_T bufref; + set_bufref(&bufref, buf); + if (close_others) { /* Close any other windows on this buffer, then make it empty. */ close_windows(buf, TRUE); @@ -861,15 +1032,17 @@ static int empty_curbuf(int close_others, int forceit, int action) retval = do_ecmd(0, NULL, NULL, NULL, ECMD_ONE, forceit ? ECMD_FORCEIT : 0, curwin); - /* - * do_ecmd() may create a new buffer, then we have to delete - * the old one. But do_ecmd() may have done that already, check - * if the buffer still exists. - */ - if (buf != curbuf && buf_valid(buf) && buf->b_nwindows == 0) - close_buffer(NULL, buf, action, FALSE); - if (!close_others) - need_fileinfo = FALSE; + // do_ecmd() may create a new buffer, then we have to delete + // the old one. But do_ecmd() may have done that already, check + // if the buffer still exists. + if (buf != curbuf && bufref_valid(&bufref) && buf->b_nwindows == 0) { + close_buffer(NULL, buf, action, false); + } + + if (!close_others) { + need_fileinfo = false; + } + return retval; } /* @@ -971,6 +1144,8 @@ do_buffer ( */ if (unload) { int forward; + bufref_T bufref; + set_bufref(&bufref, buf); /* When unloading or deleting a buffer that's already unloaded and * unlisted: fail silently. */ @@ -979,15 +1154,16 @@ do_buffer ( if (!forceit && (buf->terminal || bufIsChanged(buf))) { if ((p_confirm || cmdmod.confirm) && p_write && !buf->terminal) { - dialog_changed(buf, FALSE); - if (!buf_valid(buf)) - /* Autocommand deleted buffer, oops! It's not changed - * now. */ + dialog_changed(buf, false); + if (!bufref_valid(&bufref)) { + // Autocommand deleted buffer, oops! It's not changed now. return FAIL; - /* If it's still changed fail silently, the dialog already - * mentioned why it fails. */ - if (bufIsChanged(buf)) + } + // If it's still changed fail silently, the dialog already + // mentioned why it fails. + if (bufIsChanged(buf)) { return FAIL; + } } else { if (buf->terminal) { EMSG2(_("E89: %s will be killed(add ! to override)"), @@ -1001,6 +1177,11 @@ do_buffer ( } } + // When closing the current buffer stop Visual mode. + if (buf == curbuf && VIsual_active) { + end_visual_mode(); + } + /* * If deleting the last (listed) buffer, make it empty. * The last (listed) buffer cannot be unloaded. @@ -1021,9 +1202,9 @@ do_buffer ( * a window with this buffer. */ while (buf == curbuf - && !(curwin->w_closing || curwin->w_buffer->b_closing) - && (firstwin != lastwin || first_tabpage->tp_next != NULL)) { - if (win_close(curwin, FALSE) == FAIL) + && !(curwin->w_closing || curwin->w_buffer->b_locked > 0) + && (!ONE_WINDOW || first_tabpage->tp_next != NULL)) { + if (win_close(curwin, false) == FAIL) break; } @@ -1031,27 +1212,26 @@ do_buffer ( * If the buffer to be deleted is not the current one, delete it here. */ if (buf != curbuf) { - close_windows(buf, FALSE); - if (buf != curbuf && buf_valid(buf) && buf->b_nwindows <= 0) - close_buffer(NULL, buf, action, FALSE); + close_windows(buf, false); + if (buf != curbuf && bufref_valid(&bufref) && buf->b_nwindows <= 0) { + close_buffer(NULL, buf, action, false); + } return OK; } - /* - * Deleting the current buffer: Need to find another buffer to go to. - * There should be another, otherwise it would have been handled - * above. However, autocommands may have deleted all buffers. - * First use au_new_curbuf, if it is valid. - * Then prefer the buffer we most recently visited. - * Else try to find one that is loaded, after the current buffer, - * then before the current buffer. - * Finally use any buffer. - */ - buf = NULL; /* selected buffer */ - bp = NULL; /* used when no loaded buffer found */ - if (au_new_curbuf != NULL && buf_valid(au_new_curbuf)) - buf = au_new_curbuf; - else if (curwin->w_jumplistlen > 0) { + // Deleting the current buffer: Need to find another buffer to go to. + // There should be another, otherwise it would have been handled + // above. However, autocommands may have deleted all buffers. + // First use au_new_curbuf.br_buf, if it is valid. + // Then prefer the buffer we most recently visited. + // Else try to find one that is loaded, after the current buffer, + // then before the current buffer. + // Finally use any buffer. + buf = NULL; // Selected buffer. + bp = NULL; // Used when no loaded buffer found. + if (au_new_curbuf.br_buf != NULL && bufref_valid(&au_new_curbuf)) { + buf = au_new_curbuf.br_buf; + } else if (curwin->w_jumplistlen > 0) { int jumpidx; jumpidx = curwin->w_jumplistidx - 1; @@ -1156,10 +1336,13 @@ do_buffer ( */ if (action == DOBUF_GOTO && !can_abandon(curbuf, forceit)) { if ((p_confirm || cmdmod.confirm) && p_write) { - dialog_changed(curbuf, FALSE); - if (!buf_valid(buf)) - /* Autocommand deleted buffer, oops! */ + bufref_T bufref; + set_bufref(&bufref, buf); + dialog_changed(curbuf, false); + if (!bufref_valid(&bufref)) { + // Autocommand deleted buffer, oops! return FAIL; + } } if (bufIsChanged(curbuf)) { EMSG(_(e_nowrtmsg)); @@ -1207,14 +1390,18 @@ void set_curbuf(buf_T *buf, int action) /* close_windows() or apply_autocmds() may change curbuf */ prevbuf = curbuf; + bufref_T bufref; + set_bufref(&bufref, prevbuf); - apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, FALSE, curbuf); - if (buf_valid(prevbuf) && !aborting()) { - if (prevbuf == curwin->w_buffer) + if (!apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, false, curbuf) + || (bufref_valid(&bufref) && !aborting())) { + if (prevbuf == curwin->w_buffer) { reset_synblock(curwin); - if (unload) - close_windows(prevbuf, FALSE); - if (buf_valid(prevbuf) && !aborting()) { + } + if (unload) { + close_windows(prevbuf, false); + } + if (bufref_valid(&bufref) && !aborting()) { win_T *previouswin = curwin; if (prevbuf == curbuf) u_sync(FALSE); @@ -1278,7 +1465,9 @@ void enter_buffer(buf_T *buf) curwin->w_valid = 0; if (buf->terminal) { - terminal_resize(buf->terminal, curwin->w_width, curwin->w_height); + terminal_resize(buf->terminal, + (uint16_t)curwin->w_width, + (uint16_t)curwin->w_height); } /* Make sure the buffer is loaded. */ @@ -1344,6 +1533,26 @@ void do_autochdir(void) static int top_file_num = 1; ///< highest file number +/// Initialize b:changedtick and changedtick_val attribute +/// +/// @param[out] buf Buffer to intialize for. +static inline void buf_init_changedtick(buf_T *const buf) + FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ALL +{ + STATIC_ASSERT(sizeof("changedtick") <= sizeof(buf->changedtick_di.di_key), + "buf->changedtick_di cannot hold large enough keys"); + buf->changedtick_di = (ChangedtickDictItem) { + .di_flags = DI_FLAGS_RO|DI_FLAGS_FIX, // Must not include DI_FLAGS_ALLOC. + .di_tv = (typval_T) { + .v_type = VAR_NUMBER, + .v_lock = VAR_FIXED, + .vval.v_number = buf->b_changedtick, + }, + .di_key = "changedtick", + }; + tv_dict_add(buf->b_vars, (dictitem_T *)&buf->changedtick_di); +} + /// Add a file name to the buffer list. /// If the same file name already exists return a pointer to that buffer. /// If it does not exist, or if fname == NULL, a new entry is created. @@ -1351,6 +1560,8 @@ static int top_file_num = 1; ///< highest file number /// If (flags & BLN_LISTED) is TRUE, add new buffer to buffer list. /// If (flags & BLN_DUMMY) is TRUE, don't count it as a real buffer. /// If (flags & BLN_NEW) is TRUE, don't use an existing buffer. +/// If (flags & BLN_NOOPT) is TRUE, don't copy options from the current buffer +/// if the buffer already exists. /// This is the ONLY way to create a new buffer. /// /// @param ffname full path of fname or relative @@ -1364,7 +1575,7 @@ buf_T * buflist_new(char_u *ffname, char_u *sfname, linenr_T lnum, int flags) { buf_T *buf; - fname_expand(curbuf, &ffname, &sfname); /* will allocate ffname */ + fname_expand(curbuf, &ffname, &sfname); // will allocate ffname /* * If file name already exists in the list, update the entry. @@ -1378,16 +1589,20 @@ buf_T * buflist_new(char_u *ffname, char_u *sfname, linenr_T lnum, int flags) && (buf = buflist_findname_file_id(ffname, &file_id, file_id_valid)) != NULL) { xfree(ffname); - if (lnum != 0) - buflist_setfpos(buf, curwin, lnum, (colnr_T)0, FALSE); - /* copy the options now, if 'cpo' doesn't have 's' and not done - * already */ - buf_copy_options(buf, 0); + if (lnum != 0) { + buflist_setfpos(buf, curwin, lnum, (colnr_T)0, false); + } + if ((flags & BLN_NOOPT) == 0) { + // Copy the options now, if 'cpo' doesn't have 's' and not done already. + buf_copy_options(buf, 0); + } if ((flags & BLN_LISTED) && !buf->b_p_bl) { - buf->b_p_bl = TRUE; + buf->b_p_bl = true; + bufref_T bufref; + set_bufref(&bufref, buf); if (!(flags & BLN_DUMMY)) { - apply_autocmds(EVENT_BUFADD, NULL, NULL, FALSE, buf); - if (!buf_valid(buf)) { + if (apply_autocmds(EVENT_BUFADD, NULL, NULL, false, buf) + && !bufref_valid(&bufref)) { return NULL; } } @@ -1427,8 +1642,9 @@ buf_T * buflist_new(char_u *ffname, char_u *sfname, linenr_T lnum, int flags) if (buf != curbuf || curbuf == NULL) { buf = xcalloc(1, sizeof(buf_T)); // init b: variables - buf->b_vars = dict_alloc(); + buf->b_vars = tv_dict_alloc(); init_var_dict(buf->b_vars, &buf->b_bufvar, VAR_SCOPE); + buf_init_changedtick(buf); } if (ffname != NULL) { @@ -1520,18 +1736,21 @@ buf_T * buflist_new(char_u *ffname, char_u *sfname, linenr_T lnum, int flags) // Tricky: these autocommands may change the buffer list. They could also // split the window with re-using the one empty buffer. This may result in // unexpectedly losing the empty buffer. - apply_autocmds(EVENT_BUFNEW, NULL, NULL, FALSE, buf); - if (!buf_valid(buf)) { + bufref_T bufref; + set_bufref(&bufref, buf); + if (apply_autocmds(EVENT_BUFNEW, NULL, NULL, false, buf) + && !bufref_valid(&bufref)) { return NULL; } - if (flags & BLN_LISTED) { - apply_autocmds(EVENT_BUFADD, NULL, NULL, FALSE, buf); - if (!buf_valid(buf)) { - return NULL; - } + if ((flags & BLN_LISTED) + && apply_autocmds(EVENT_BUFADD, NULL, NULL, false, buf) + && !bufref_valid(&bufref)) { + return NULL; } - if (aborting()) /* autocmds may abort script processing */ + if (aborting()) { + // Autocmds may abort script processing. return NULL; + } } return buf; @@ -1555,6 +1774,7 @@ void free_buf_options(buf_T *buf, int free_p_ff) clear_string_option(&buf->b_p_inex); clear_string_option(&buf->b_p_inde); clear_string_option(&buf->b_p_indk); + clear_string_option(&buf->b_p_fp); clear_string_option(&buf->b_p_fex); clear_string_option(&buf->b_p_kp); clear_string_option(&buf->b_p_mps); @@ -1597,16 +1817,15 @@ void free_buf_options(buf_T *buf, int free_p_ff) clear_string_option(&buf->b_p_bkc); } -/* - * get alternate file n - * set linenr to lnum or altfpos.lnum if lnum == 0 - * also set cursor column to altfpos.col if 'startofline' is not set. - * if (options & GETF_SETMARK) call setpcmark() - * if (options & GETF_ALT) we are jumping to an alternate file. - * if (options & GETF_SWITCH) respect 'switchbuf' settings when jumping - * - * return FAIL for failure, OK for success - */ + +/// Get alternate file "n". +/// Set linenr to "lnum" or altfpos.lnum if "lnum" == 0. +/// Also set cursor column to altfpos.col if 'startofline' is not set. +/// if (options & GETF_SETMARK) call setpcmark() +/// if (options & GETF_ALT) we are jumping to an alternate file. +/// if (options & GETF_SWITCH) respect 'switchbuf' settings when jumping +/// +/// Return FAIL for failure, OK for success. int buflist_getfile(int n, linenr_T lnum, int options, int forceit) { buf_T *buf; @@ -1687,9 +1906,7 @@ int buflist_getfile(int n, linenr_T lnum, int options, int forceit) return FAIL; } -/* - * go to the last know line number for the current buffer - */ +// Go to the last known line number for the current buffer. void buflist_getfpos(void) { pos_T *fpos; @@ -1754,7 +1971,8 @@ buf_T *buflist_findname(char_u *ffname) static buf_T *buflist_findname_file_id(char_u *ffname, FileID *file_id, bool file_id_valid) { - FOR_ALL_BUFFERS(buf) { + // Start at the last buffer, expect to find a match sooner. + FOR_ALL_BUFFERS_BACKWARDS(buf) { if ((buf->b_flags & BF_DUMMY) == 0 && !otherfile_buf(buf, ffname, file_id, file_id_valid)) { return buf; @@ -1828,7 +2046,7 @@ int buflist_findpat( return -1; } - FOR_ALL_BUFFERS(buf) { + FOR_ALL_BUFFERS_BACKWARDS(buf) { if (buf->b_p_bl == find_listed && (!diffmode || diff_mode_buf(buf)) && buflist_match(®match, buf, false) != NULL) { @@ -1942,7 +2160,7 @@ int ExpandBufnames(char_u *pat, int *num_file, char_u ***file, int options) if (count == 0) /* no match found, break here */ break; if (round == 1) { - *file = xmalloc(count * sizeof(**file)); + *file = xmalloc((size_t)count * sizeof(**file)); } } vim_regfree(regmatch.regprog); @@ -1997,21 +2215,14 @@ static char_u *fname_match(regmatch_T *rmp, char_u *name, bool ignore_case) return match; } -/* - * find file in buffer list by number - */ +/// Find a file in the buffer list by buffer number. buf_T *buflist_findnr(int nr) { if (nr == 0) { nr = curwin->w_alt_fnum; } - FOR_ALL_BUFFERS(buf) { - if (buf->b_fnum == nr) { - return buf; - } - } - return NULL; + return handle_get_buffer((handle_T)nr); } /* @@ -2169,7 +2380,7 @@ void get_winopts(buf_T *buf) /* Set 'foldlevel' to 'foldlevelstart' if it's not negative. */ if (p_fdls >= 0) curwin->w_p_fdl = p_fdls; - check_colorcolumn(curwin); + didset_window_options(curwin); } /* @@ -2193,9 +2404,7 @@ linenr_T buflist_findlnum(buf_T *buf) return buflist_findfpos(buf)->lnum; } -/* - * List all know file names (for :files and :buffers command). - */ +// List all known file names (for :files and :buffers command). void buflist_list(exarg_T *eap) { buf_T *buf; @@ -2220,12 +2429,17 @@ void buflist_list(exarg_T *eap) && (buf == curbuf || curwin->w_alt_fnum != buf->b_fnum))) { continue; } - msg_putchar('\n'); - if (buf_spname(buf) != NULL) + if (buf_spname(buf) != NULL) { STRLCPY(NameBuff, buf_spname(buf), MAXPATHL); - else - home_replace(buf, buf->b_fname, NameBuff, MAXPATHL, TRUE); + } else { + home_replace(buf, buf->b_fname, NameBuff, MAXPATHL, true); + } + if (message_filtered(NameBuff)) { + continue; + } + + msg_putchar('\n'); len = vim_snprintf((char *)IObuff, IOSIZE - 20, "%3d%c%c%c%c%c \"%s\"", buf->b_fnum, buf->b_p_bl ? ' ' : 'u', @@ -2579,7 +2793,7 @@ fileinfo ( else name = curbuf->b_ffname; home_replace(shorthelp ? curbuf : NULL, name, p, - (int)(IOSIZE - (p - buffer)), TRUE); + (size_t)(IOSIZE - (p - buffer)), true); } vim_snprintf_add((char *)buffer, IOSIZE, "\"%s%s%s%s%s%s", @@ -2689,9 +2903,10 @@ void maketitle(void) if (p_title) { if (p_titlelen > 0) { - maxlen = p_titlelen * Columns / 100; - if (maxlen < 10) + maxlen = (int)(p_titlelen * Columns / 100); + if (maxlen < 10) { maxlen = 10; + } } t_str = buf; @@ -2743,7 +2958,7 @@ void maketitle(void) buf[off++] = ' '; buf[off++] = '('; home_replace(curbuf, curbuf->b_ffname, - buf + off, SPACE_FOR_DIR - off, TRUE); + buf + off, (size_t)(SPACE_FOR_DIR - off), true); #ifdef BACKSLASH_IN_FILENAME /* avoid "c:/name" to be reduced to "c" */ if (isalpha(buf[off]) && buf[off + 1] == ':') @@ -2850,13 +3065,13 @@ static bool ti_change(char_u *str, char_u **last) return false; } -/* - * Put current window title back (used after calling a shell) - */ + +/// Set current window title void resettitle(void) { - ui_set_title((char *)lasttitle); - ui_set_icon((char *)lasticon); + ui_call_set_title(cstr_as_string((char *)lasttitle)); + ui_call_set_icon(cstr_as_string((char *)lasticon)); + ui_flush(); } # if defined(EXITFREE) @@ -2908,13 +3123,13 @@ int build_stl_str_hl( size_t outlen, char_u *fmt, int use_sandbox, - int fillchar, + char_u fillchar, int maxwidth, struct stl_hlrec *hltab, StlClickRecord *tabtab ) { - int groupitem[STL_MAX_ITEM]; + int groupitems[STL_MAX_ITEM]; struct stl_item { // Where the item starts in the status line output buffer char_u *start; @@ -2934,7 +3149,7 @@ int build_stl_str_hl( ClickFunc, Trunc } type; - } item[STL_MAX_ITEM]; + } items[STL_MAX_ITEM]; #define TMPLEN 70 char_u tmp[TMPLEN]; char_u *usefmt = fmt; @@ -3036,16 +3251,16 @@ int build_stl_str_hl( if (groupdepth > 0) { continue; } - item[curitem].type = Separate; - item[curitem++].start = out_p; + items[curitem].type = Separate; + items[curitem++].start = out_p; continue; } // 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 = out_p; + items[curitem].type = Trunc; + items[curitem++].start = out_p; continue; } @@ -3061,7 +3276,7 @@ int build_stl_str_hl( // 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; + char_u *t = items[groupitems[groupdepth]].start; *out_p = NUL; long group_len = vim_strsize(t); @@ -3071,11 +3286,11 @@ int build_stl_str_hl( // 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) { + if (curitem > groupitems[groupdepth] + 1 + && items[groupitems[groupdepth]].minwid == 0) { bool has_normal_items = false; - for (long n = groupitem[groupdepth] + 1; n < curitem; n++) { - if (item[n].type == Normal || item[n].type == Highlight) { + for (long n = groupitems[groupdepth] + 1; n < curitem; n++) { + if (items[n].type == Normal || items[n].type == Highlight) { has_normal_items = true; break; } @@ -3089,18 +3304,18 @@ int build_stl_str_hl( // 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) { + if (group_len > items[groupitems[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 (group_len >= item[groupitem[groupdepth]].maxwid) { + while (group_len >= items[groupitems[groupdepth]].maxwid) { group_len -= ptr2cells(t + n); n += (*mb_ptr2len)(t + n); } } else { - n = (long)(out_p - t) - item[groupitem[groupdepth]].maxwid + 1; + n = (long)(out_p - t) - items[groupitems[groupdepth]].maxwid + 1; } // } @@ -3110,25 +3325,26 @@ int build_stl_str_hl( // { 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 (++group_len < item[groupitem[groupdepth]].minwid) + // Fill up space left over by half a double-wide char. + while (++group_len < items[groupitems[groupdepth]].minwid) { *out_p++ = fillchar; + } // } - /* correct the start of the items for the truncation */ - for (int idx = groupitem[groupdepth] + 1; idx < curitem; idx++) { + // correct the start of the items for the truncation + for (int idx = groupitems[groupdepth] + 1; idx < curitem; idx++) { // Shift everything back by the number of removed bytes - item[idx].start -= n; + items[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; + if (items[idx].start < t) { + items[idx].start = t; } } // 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; + } else if (abs(items[groupitems[groupdepth]].minwid) > group_len) { + long min_group_width = items[groupitems[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; @@ -3147,8 +3363,8 @@ int build_stl_str_hl( // } // Adjust item start positions - for (int n = groupitem[groupdepth] + 1; n < curitem; n++) { - item[n].start += group_len; + for (int n = groupitems[groupdepth] + 1; n < curitem; n++) { + items[n].start += group_len; } // Prepend the fill characters @@ -3186,9 +3402,9 @@ int build_stl_str_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 = out_p; - item[curitem].minwid = minwid > 9 ? 1 : minwid; + items[curitem].type = Highlight; + items[curitem].start = out_p; + items[curitem].minwid = minwid > 9 ? 1 : minwid; fmt_p++; curitem++; continue; @@ -3220,20 +3436,21 @@ int build_stl_str_hl( 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 (long n = curitem - 1; n >= 0; --n) - if (item[n].type == TabPage && item[n].minwid >= 0) { - minwid = item[n].minwid; + // %X ends the close label, go back to the previous tab label nr. + for (long n = curitem - 1; n >= 0; n--) { + if (items[n].type == TabPage && items[n].minwid >= 0) { + minwid = items[n].minwid; break; } - } else - /* close nrs are stored as negative values */ + } + } else { + // close nrs are stored as negative values minwid = -minwid; + } } - item[curitem].type = TabPage; - item[curitem].start = out_p; - item[curitem].minwid = minwid; + items[curitem].type = TabPage; + items[curitem].start = out_p; + items[curitem].minwid = minwid; fmt_p++; curitem++; continue; @@ -3248,10 +3465,10 @@ int build_stl_str_hl( if (*fmt_p != STL_CLICK_FUNC) { break; } - item[curitem].type = ClickFunc; - item[curitem].start = out_p; - item[curitem].cmd = xmemdupz(t, (size_t) (((char *) fmt_p - t))); - item[curitem].minwid = minwid; + items[curitem].type = ClickFunc; + items[curitem].start = out_p; + items[curitem].cmd = xmemdupz(t, (size_t)(((char *)fmt_p - t))); + items[curitem].minwid = minwid; fmt_p++; curitem++; continue; @@ -3274,11 +3491,11 @@ int build_stl_str_hl( // Denotes the start of a new group if (*fmt_p == '(') { - groupitem[groupdepth++] = curitem; - item[curitem].type = Group; - item[curitem].start = out_p; - item[curitem].minwid = minwid; - item[curitem].maxwid = maxwid; + groupitems[groupdepth++] = curitem; + items[curitem].type = Group; + items[curitem].start = out_p; + items[curitem].minwid = minwid; + items[curitem].maxwid = maxwid; fmt_p++; curitem++; continue; @@ -3305,7 +3522,7 @@ int build_stl_str_hl( case STL_FULLPATH: case STL_FILENAME: { - // Set fillable to false to that ' ' in the filename will not + // Set fillable to false so that ' ' in the filename will not // get replaced with the fillchar fillable = false; if (buf_spname(wp->w_buffer) != NULL) { @@ -3358,7 +3575,7 @@ int build_stl_str_hl( curbuf = o_curbuf; // Remove the variable we just stored - do_unlet((char_u *)"g:actual_curbuf", true); + do_unlet(S_LEN("g:actual_curbuf"), true); // } @@ -3440,7 +3657,7 @@ int build_stl_str_hl( case STL_KEYMAP: fillable = false; - if (get_keymap_str(wp, tmp, TMPLEN)) + if (get_keymap_str(wp, (char_u *)"<%s>", tmp, TMPLEN)) str = tmp; break; case STL_PAGENUM: @@ -3453,6 +3670,7 @@ int build_stl_str_hl( case STL_OFFSET_X: base = kNumBaseHexadecimal; + // fallthrough case STL_OFFSET: { long l = ml_find_line_or_offset(wp->w_buffer, wp->w_cursor.lnum, NULL); @@ -3463,6 +3681,7 @@ int build_stl_str_hl( } case STL_BYTEVAL_X: base = kNumBaseHexadecimal; + // fallthrough case STL_BYTEVAL: num = byteval; if (num == NL) @@ -3510,7 +3729,7 @@ int build_stl_str_hl( wp->w_buffer->b_p_ft); // Uppercase the file extension for (char_u *t = tmp; *t != 0; t++) { - *t = TOUPPER_LOC(*t); + *t = (char_u)TOUPPER_LOC(*t); } str = tmp; } @@ -3557,9 +3776,9 @@ int build_stl_str_hl( // Create a highlight item based on the name if (*fmt_p == '#') { - item[curitem].type = Highlight; - item[curitem].start = out_p; - item[curitem].minwid = -syn_namen2id(t, (int)(fmt_p - t)); + items[curitem].type = Highlight; + items[curitem].start = out_p; + items[curitem].minwid = -syn_namen2id(t, (int)(fmt_p - t)); curitem++; fmt_p++; } @@ -3570,8 +3789,8 @@ int build_stl_str_hl( // 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; + items[curitem].start = out_p; + items[curitem].type = Normal; // Copy the item string into the output buffer if (str != NULL && *str) { @@ -3687,7 +3906,8 @@ int build_stl_str_hl( } // } - size_t remaining_buf_len = (out_end_p - out_p) + 1; + assert(out_end_p >= out_p); + size_t remaining_buf_len = (size_t)(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. @@ -3702,7 +3922,7 @@ int build_stl_str_hl( // { Reduce the number by base^n while (num_chars-- > maxwid) { - num /= base; + num /= (long)base; } // } @@ -3727,7 +3947,7 @@ int build_stl_str_hl( // Otherwise, there was nothing to print so mark the item as empty } else { - item[curitem].type = Empty; + items[curitem].type = Empty; } // Only free the string buffer if we allocated it. @@ -3752,8 +3972,7 @@ int build_stl_str_hl( } // We have now processed the entire statusline format string. - // What follows is post-processing to handle alignment and - // highlighting factors. + // What follows is post-processing to handle alignment and highlighting. int width = vim_strsize(out); if (maxwidth > 0 && width > maxwidth) { @@ -3768,16 +3987,17 @@ int build_stl_str_hl( // Otherwise, look for the truncation item } else { // Default to truncating at the first item - trunc_p = item[0].start; + trunc_p = items[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; + for (int i = 0; i < itemcnt; i++) { + if (items[i].type == Trunc) { + // Truncate at %< items. + trunc_p = items[i].start; item_idx = i; break; } + } } // If the truncation point we found is beyond the maximum @@ -3807,7 +4027,7 @@ int build_stl_str_hl( // 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) { + if (items[i].start > trunc_p) { itemcnt = i; break; } @@ -3862,12 +4082,12 @@ int build_stl_str_hl( 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; + if (items[i].start >= trunc_end_p) { + items[i].start -= item_offset; // Anything inside the truncated area is set to start // at the `<` truncation character. } else { - item[i].start = trunc_p; + items[i].start = trunc_p; } } // } @@ -3878,12 +4098,12 @@ int build_stl_str_hl( // add characters at the separate marker (if there is one) to // fill up the available space. } else if (width < maxwidth - && STRLEN(out) + maxwidth - width + 1 < outlen) { + && STRLEN(out) + (size_t)(maxwidth - width) + 1 < outlen) { // Find how many separators there are, which we will use when // figuring out how many groups there are. int num_separators = 0; for (int i = 0; i < itemcnt; i++) { - if (item[i].type == Separate) { + if (items[i].type == Separate) { num_separators++; } } @@ -3895,7 +4115,7 @@ int build_stl_str_hl( int separator_locations[STL_MAX_ITEM]; int index = 0; for (int i = 0; i < itemcnt; i++) { - if (item[i].type == Separate) { + if (items[i].type == Separate) { separator_locations[index] = i; index++; } @@ -3906,18 +4126,18 @@ int build_stl_str_hl( standard_spaces * (num_separators - 1); for (int i = 0; i < num_separators; i++) { - int dislocation = (i == (num_separators - 1)) ? - final_spaces : standard_spaces; - char_u *sep_loc = item[separator_locations[i]].start + dislocation; - STRMOVE(sep_loc, item[separator_locations[i]].start); - for (char_u *s = item[separator_locations[i]].start; s < sep_loc; s++) { + int dislocation = (i == (num_separators - 1)) + ? final_spaces : standard_spaces; + char_u *seploc = items[separator_locations[i]].start + dislocation; + STRMOVE(seploc, items[separator_locations[i]].start); + for (char_u *s = items[separator_locations[i]].start; s < seploc; s++) { *s = fillchar; } for (int item_idx = separator_locations[i] + 1; item_idx < itemcnt; item_idx++) { - item[item_idx].start += dislocation; + items[item_idx].start += dislocation; } } @@ -3929,9 +4149,9 @@ int build_stl_str_hl( if (hltab != NULL) { 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; + if (items[l].type == Highlight) { + sp->start = items[l].start; + sp->userhl = items[l].minwid; sp++; } } @@ -3943,14 +4163,14 @@ int build_stl_str_hl( if (tabtab != NULL) { StlClickRecord *cur_tab_rec = tabtab; for (long l = 0; l < itemcnt; l++) { - if (item[l].type == TabPage) { - cur_tab_rec->start = (char *) item[l].start; - if (item[l].minwid == 0) { + if (items[l].type == TabPage) { + cur_tab_rec->start = (char *)items[l].start; + if (items[l].minwid == 0) { cur_tab_rec->def.type = kStlClickDisabled; cur_tab_rec->def.tabnr = 0; } else { - int tabnr = item[l].minwid; - if (item[l].minwid > 0) { + int tabnr = items[l].minwid; + if (items[l].minwid > 0) { cur_tab_rec->def.type = kStlClickTabSwitch; } else { cur_tab_rec->def.type = kStlClickTabClose; @@ -3960,11 +4180,11 @@ int build_stl_str_hl( } cur_tab_rec->def.func = NULL; cur_tab_rec++; - } else if (item[l].type == ClickFunc) { - cur_tab_rec->start = (char *) item[l].start; + } else if (items[l].type == ClickFunc) { + cur_tab_rec->start = (char *)items[l].start; cur_tab_rec->def.type = kStlClickFuncRun; - cur_tab_rec->def.tabnr = item[l].minwid; - cur_tab_rec->def.func = item[l].cmd; + cur_tab_rec->def.tabnr = items[l].minwid; + cur_tab_rec->def.func = items[l].cmd; cur_tab_rec++; } } @@ -4059,14 +4279,12 @@ void fname_expand(buf_T *buf, char_u **ffname, char_u **sfname) #ifdef WIN32 if (!buf->b_p_bin) { - char_u *rfname; - // If the file name is a shortcut file, use the file it links to. - rfname = os_resolve_shortcut(*ffname); + char *rfname = os_resolve_shortcut((const char *)(*ffname)); if (rfname != NULL) { xfree(*ffname); - *ffname = rfname; - *sfname = rfname; + *ffname = (char_u *)rfname; + *sfname = (char_u *)rfname; } } #endif @@ -4116,6 +4334,8 @@ do_arg_all ( win_T *new_curwin = NULL; tabpage_T *new_curtab = NULL; + assert(firstwin != NULL); // satisfy coverity + if (ARGCOUNT <= 0) { /* Don't give an error message. We don't want it when the ":all" * command is in the .vimrc. */ @@ -4124,7 +4344,7 @@ do_arg_all ( setpcmark(); opened_len = ARGCOUNT; - opened = xcalloc(opened_len, 1); + opened = xcalloc((size_t)opened_len, 1); /* Autocommands may do anything to the argument list. Make sure it's not * freed while we are working here by "locking" it. We still have to @@ -4198,24 +4418,27 @@ do_arg_all ( || !bufIsChanged(buf)) { /* If the buffer was changed, and we would like to hide it, * try autowriting. */ - if (!P_HID(buf) && buf->b_nwindows <= 1 - && bufIsChanged(buf)) { - (void)autowrite(buf, FALSE); - /* check if autocommands removed the window */ - if (!win_valid(wp) || !buf_valid(buf)) { - wpnext = firstwin; /* start all over... */ + if (!P_HID(buf) && buf->b_nwindows <= 1 && bufIsChanged(buf)) { + bufref_T bufref; + set_bufref(&bufref, buf); + (void)autowrite(buf, false); + // Check if autocommands removed the window. + if (!win_valid(wp) || !bufref_valid(&bufref)) { + wpnext = firstwin; // Start all over... continue; } } - /* don't close last window */ - if (firstwin == lastwin - && (first_tabpage->tp_next == NULL || !had_tab)) - use_firstwin = TRUE; - else { + // don't close last window + if (ONE_WINDOW + && (first_tabpage->tp_next == NULL || !had_tab)) { + use_firstwin = true; + } else { win_close(wp, !P_HID(buf) && !bufIsChanged(buf)); - /* check if autocommands removed the next window */ - if (!win_valid(wpnext)) - wpnext = firstwin; /* start all over... */ + // check if autocommands removed the next window + if (!win_valid(wpnext)) { + // start all over... + wpnext = firstwin; + } } } } @@ -4306,19 +4529,23 @@ do_arg_all ( /* Remove the "lock" on the argument list. */ alist_unlink(alist); - --autocmd_no_enter; - /* restore last referenced tabpage's curwin */ + autocmd_no_enter--; + // restore last referenced tabpage's curwin if (last_curtab != new_curtab) { - if (valid_tabpage(last_curtab)) - goto_tabpage_tp(last_curtab, TRUE, TRUE); - if (win_valid(last_curwin)) + if (valid_tabpage(last_curtab)) { + goto_tabpage_tp(last_curtab, true, true); + } + if (win_valid(last_curwin)) { win_enter(last_curwin, false); + } + } + // to window with first arg + if (valid_tabpage(new_curtab)) { + goto_tabpage_tp(new_curtab, true, true); } - /* to window with first arg */ - if (valid_tabpage(new_curtab)) - goto_tabpage_tp(new_curtab, TRUE, TRUE); - if (win_valid(new_curwin)) + if (win_valid(new_curwin)) { win_enter(new_curwin, false); + } --autocmd_no_leave; xfree(opened); @@ -4335,8 +4562,8 @@ void ex_buffer_all(exarg_T *eap) bool p_ea_save; int open_wins = 0; int r; - int count; /* Maximum number of windows to open. */ - int all; /* When TRUE also load inactive buffers. */ + long count; // Maximum number of windows to open. + int all; // When TRUE also load inactive buffers. int had_tab = cmdmod.tab; tabpage_T *tpnext; @@ -4367,9 +4594,9 @@ void ex_buffer_all(exarg_T *eap) ? wp->w_height + wp->w_status_height < Rows - p_ch - tabline_height() : wp->w_width != Columns) - || (had_tab > 0 && wp != firstwin) - ) && firstwin != lastwin - && !(wp->w_closing || wp->w_buffer->b_closing) + || (had_tab > 0 && wp != firstwin)) + && !ONE_WINDOW + && !(wp->w_closing || wp->w_buffer->b_locked > 0) ) { win_close(wp, FALSE); wpnext = firstwin; /* just in case an autocommand does @@ -4417,7 +4644,9 @@ void ex_buffer_all(exarg_T *eap) } if (wp == NULL && split_ret == OK) { - /* Split the window and put the buffer in it */ + bufref_T bufref; + set_bufref(&bufref, buf); + // Split the window and put the buffer in it. p_ea_save = p_ea; p_ea = true; /* use space from all windows */ split_ret = win_split(0, WSP_ROOM | WSP_BELOW); @@ -4429,7 +4658,8 @@ void ex_buffer_all(exarg_T *eap) /* Open the buffer in this window. */ swap_exists_action = SEA_DIALOG; set_curbuf(buf, DOBUF_GOTO); - if (!buf_valid(buf)) { /* autocommands deleted the buffer!!! */ + if (!bufref_valid(&bufref)) { + // Autocommands deleted the buffer. swap_exists_action = SEA_NONE; break; } @@ -4857,7 +5087,7 @@ int buf_findsign( for (sign = buf->b_signlist; sign != NULL; sign = sign->next) { if (sign->id == id) { - return sign->lnum; + return (int)sign->lnum; } } @@ -4971,6 +5201,30 @@ void sign_mark_adjust(linenr_T line1, linenr_T line2, long amount, long amount_a // bufhl: plugin highlights associated with a buffer +/// Get reference to line in kbtree_t +/// +/// @param b the three +/// @param line the linenumber to lookup +/// @param put if true, put a new line when not found +/// if false, return NULL when not found +BufhlLine *bufhl_tree_ref(BufhlInfo *b, linenr_T line, bool put) +{ + BufhlLine t = BUFHLLINE_INIT(line); + + // kp_put() only works if key is absent, try get first + BufhlLine **pp = kb_get(bufhl, b, &t); + if (pp) { + return *pp; + } else if (!put) { + return NULL; + } + + BufhlLine *p = xmalloc(sizeof(*p)); + *p = (BufhlLine)BUFHLLINE_INIT(line); + kb_put(bufhl, b, p); + return p; +} + /// Adds a highlight to buffer. /// /// Unlike matchaddpos() highlights follow changes to line numbering (as lines @@ -5008,13 +5262,10 @@ int bufhl_add_hl(buf_T *buf, // no highlight group or invalid line, just return src_id return src_id; } - if (!buf->b_bufhl_info) { - buf->b_bufhl_info = map_new(linenr_T, bufhl_vec_T)(); - } - bufhl_vec_T* lineinfo = map_ref(linenr_T, bufhl_vec_T)(buf->b_bufhl_info, - lnum, true); - bufhl_hl_item_T *hlentry = kv_pushp(*lineinfo); + BufhlLine *lineinfo = bufhl_tree_ref(&buf->b_bufhl_info, lnum, true); + + BufhlItem *hlentry = kv_pushp(lineinfo->items); hlentry->src_id = src_id; hlentry->hl_id = hl_id; hlentry->start = col_start; @@ -5036,20 +5287,24 @@ int bufhl_add_hl(buf_T *buf, void bufhl_clear_line_range(buf_T *buf, int src_id, linenr_T line_start, - linenr_T line_end) { - if (!buf->b_bufhl_info) { - return; - } - linenr_T line; + linenr_T line_end) +{ linenr_T first_changed = MAXLNUM, last_changed = -1; - // In the case line_start - line_end << bufhl_info->size - // it might be better to reverse this, i e loop over the lines - // to clear on. - bufhl_vec_T unused; - map_foreach(buf->b_bufhl_info, line, unused, { - (void)unused; + + kbitr_t(bufhl) itr; + BufhlLine *l, t = BUFHLLINE_INIT(line_start); + if (!kb_itr_get(bufhl, &buf->b_bufhl_info, &t, &itr)) { + kb_itr_next(bufhl, &buf->b_bufhl_info, &itr); + } + for (; kb_itr_valid(&itr); kb_itr_next(bufhl, &buf->b_bufhl_info, &itr)) { + l = kb_itr_key(&itr); + linenr_T line = l->line; + if (line > line_end) { + break; + } if (line_start <= line && line <= line_end) { - if (bufhl_clear_line(buf->b_bufhl_info, src_id, line)) { + BufhlLineStatus status = bufhl_clear_line(l, src_id, line); + if (status != kBLSUnchanged) { if (line > last_changed) { last_changed = line; } @@ -5057,8 +5312,12 @@ void bufhl_clear_line_range(buf_T *buf, first_changed = line; } } + if (status == kBLSDeleted) { + kb_del_itr(bufhl, &buf->b_bufhl_info, &itr); + xfree(l); + } } - }) + } if (last_changed != -1) { changed_lines_buf(buf, first_changed, last_changed+1, 0); @@ -5071,40 +5330,40 @@ void bufhl_clear_line_range(buf_T *buf, /// @param bufhl_info The highlight info for the buffer /// @param src_id Highlight source group to clear, or -1 to clear all groups. /// @param lnum Linenr where the highlight should be cleared -static bool bufhl_clear_line(bufhl_info_T *bufhl_info, int src_id, int lnum) { - bufhl_vec_T* lineinfo = map_ref(linenr_T, bufhl_vec_T)(bufhl_info, - lnum, false); - size_t oldsize = kv_size(*lineinfo); +static BufhlLineStatus bufhl_clear_line(BufhlLine *lineinfo, int src_id, + linenr_T lnum) +{ + size_t oldsize = kv_size(lineinfo->items); if (src_id < 0) { - kv_size(*lineinfo) = 0; + kv_size(lineinfo->items) = 0; } else { - size_t newind = 0; - for (size_t i = 0; i < kv_size(*lineinfo); i++) { - if (kv_A(*lineinfo, i).src_id != src_id) { - if (i != newind) { - kv_A(*lineinfo, newind) = kv_A(*lineinfo, i); + size_t newidx = 0; + for (size_t i = 0; i < kv_size(lineinfo->items); i++) { + if (kv_A(lineinfo->items, i).src_id != src_id) { + if (i != newidx) { + kv_A(lineinfo->items, newidx) = kv_A(lineinfo->items, i); } - newind++; + newidx++; } } - kv_size(*lineinfo) = newind; + kv_size(lineinfo->items) = newidx; } - if (kv_size(*lineinfo) == 0) { - kv_destroy(*lineinfo); - map_del(linenr_T, bufhl_vec_T)(bufhl_info, lnum); + if (kv_size(lineinfo->items) == 0) { + kv_destroy(lineinfo->items); + return kBLSDeleted; } - return kv_size(*lineinfo) != oldsize; + return kv_size(lineinfo->items) != oldsize ? kBLSChanged : kBLSUnchanged; } /// Remove all highlights and free the highlight data -void bufhl_clear_all(buf_T* buf) { - if (!buf->b_bufhl_info) { - return; - } +void bufhl_clear_all(buf_T *buf) +{ bufhl_clear_line_range(buf, -1, 1, MAXLNUM); - map_free(linenr_T, bufhl_vec_T)(buf->b_bufhl_info); - buf->b_bufhl_info = NULL; + kb_destroy(bufhl, (&buf->b_bufhl_info)); + kb_init(&buf->b_bufhl_info); + kv_destroy(buf->b_bufhl_move_space); + kv_init(buf->b_bufhl_move_space); } /// Adjust a placed highlight for inserted/deleted lines. @@ -5112,29 +5371,49 @@ void bufhl_mark_adjust(buf_T* buf, linenr_T line1, linenr_T line2, long amount, - long amount_after) { - if (!buf->b_bufhl_info) { + long amount_after, + bool end_temp) +{ + kbitr_t(bufhl) itr; + BufhlLine *l, t = BUFHLLINE_INIT(line1); + if (end_temp && amount < 0) { + // Move all items from b_bufhl_move_space to the btree. + for (size_t i = 0; i < kv_size(buf->b_bufhl_move_space); i++) { + l = kv_A(buf->b_bufhl_move_space, i); + l->line += amount; + kb_put(bufhl, &buf->b_bufhl_info, l); + } + kv_size(buf->b_bufhl_move_space) = 0; return; } - bufhl_info_T *newmap = map_new(linenr_T, bufhl_vec_T)(); - linenr_T line; - bufhl_vec_T lineinfo; - map_foreach(buf->b_bufhl_info, line, lineinfo, { - if (line >= line1 && line <= line2) { + if (!kb_itr_get(bufhl, &buf->b_bufhl_info, &t, &itr)) { + kb_itr_next(bufhl, &buf->b_bufhl_info, &itr); + } + for (; kb_itr_valid(&itr); kb_itr_next(bufhl, &buf->b_bufhl_info, &itr)) { + l = kb_itr_key(&itr); + if (l->line >= line1 && l->line <= line2) { + if (end_temp && amount > 0) { + kb_del_itr(bufhl, &buf->b_bufhl_info, &itr); + kv_push(buf->b_bufhl_move_space, l); + } if (amount == MAXLNUM) { - bufhl_clear_line(buf->b_bufhl_info, -1, line); - continue; + if (bufhl_clear_line(l, -1, l->line) == kBLSDeleted) { + kb_del_itr(bufhl, &buf->b_bufhl_info, &itr); + xfree(l); + } else { + assert(false); + } } else { - line += amount; + l->line += amount; } - } else if (line > line2) { - line += amount_after; + } else if (l->line > line2) { + if (amount_after == 0) { + break; + } + l->line += amount_after; } - map_put(linenr_T, bufhl_vec_T)(newmap, line, lineinfo); - }); - map_free(linenr_T, bufhl_vec_T)(buf->b_bufhl_info); - buf->b_bufhl_info = newmap; + } } @@ -5144,13 +5423,14 @@ void bufhl_mark_adjust(buf_T* buf, /// @param lnum The line number /// @param[out] info The highligts for the line /// @return true if there was highlights to display -bool bufhl_start_line(buf_T *buf, linenr_T lnum, bufhl_lineinfo_T *info) { - if (!buf->b_bufhl_info) { +bool bufhl_start_line(buf_T *buf, linenr_T lnum, BufhlLineInfo *info) +{ + BufhlLine *lineinfo = bufhl_tree_ref(&buf->b_bufhl_info, lnum, false); + if (!lineinfo) { return false; } - info->valid_to = -1; - info->entries = map_get(linenr_T, bufhl_vec_T)(buf->b_bufhl_info, lnum); + info->entries = lineinfo->items; return kv_size(info->entries) > 0; } @@ -5164,14 +5444,15 @@ bool bufhl_start_line(buf_T *buf, linenr_T lnum, bufhl_lineinfo_T *info) { /// @param info The info returned by bufhl_start_line /// @param col The column to get the attr for /// @return The highilight attr to display at the column -int bufhl_get_attr(bufhl_lineinfo_T *info, colnr_T col) { +int bufhl_get_attr(BufhlLineInfo *info, colnr_T col) +{ if (col <= info->valid_to) { return info->current; } int attr = 0; info->valid_to = MAXCOL; for (size_t i = 0; i < kv_size(info->entries); i++) { - bufhl_hl_item_T entry = kv_A(info->entries, i); + BufhlItem entry = kv_A(info->entries, i); if (entry.start <= col && col <= entry.stop) { int entry_attr = syn_id2attr(entry.hl_id); attr = hl_combine_attr(attr, entry_attr); @@ -5286,8 +5567,8 @@ void buf_open_scratch(handle_T bufnr, char *bufname) { (void)do_ecmd((int)bufnr, NULL, NULL, NULL, ECMD_ONE, ECMD_HIDE, NULL); (void)setfname(curbuf, (char_u *)bufname, NULL, true); - set_option_value((char_u *)"bh", 0L, (char_u *)"hide", OPT_LOCAL); - set_option_value((char_u *)"bt", 0L, (char_u *)"nofile", OPT_LOCAL); - set_option_value((char_u *)"swf", 0L, NULL, OPT_LOCAL); + set_option_value("bh", 0L, "hide", OPT_LOCAL); + set_option_value("bt", 0L, "nofile", OPT_LOCAL); + set_option_value("swf", 0L, NULL, OPT_LOCAL); RESET_BINDING(curwin); } diff --git a/src/nvim/buffer.h b/src/nvim/buffer.h index 36cbec7e60..faeeed121c 100644 --- a/src/nvim/buffer.h +++ b/src/nvim/buffer.h @@ -1,10 +1,14 @@ #ifndef NVIM_BUFFER_H #define NVIM_BUFFER_H +#include "nvim/vim.h" #include "nvim/window.h" #include "nvim/pos.h" // for linenr_T #include "nvim/ex_cmds_defs.h" // for exarg_T #include "nvim/screen.h" // for StlClickRecord +#include "nvim/func_attr.h" +#include "nvim/eval.h" +#include "nvim/macros.h" // Values for buflist_getfile() enum getf_values { @@ -15,9 +19,11 @@ enum getf_values { // Values for buflist_new() flags enum bln_values { - BLN_CURBUF = 1, // May re-use curbuf for new buffer - BLN_LISTED = 2, // Put new buffer in buffer list - BLN_DUMMY = 4, // Allocating dummy buffer + BLN_CURBUF = 1, // May re-use curbuf for new buffer + BLN_LISTED = 2, // Put new buffer in buffer list + BLN_DUMMY = 4, // Allocating dummy buffer + // TODO(mhinz): merge patch that introduces BLN_NEW + BLN_NOOPT = 16, // Don't copy options to existing buffer }; // Values for action argument for do_buffer() @@ -55,35 +61,64 @@ enum bfa_values { static inline void switch_to_win_for_buf(buf_T *buf, win_T **save_curwinp, tabpage_T **save_curtabp, - buf_T **save_curbufp) + bufref_T *save_curbuf) { win_T *wp; tabpage_T *tp; if (!find_win_for_buf(buf, &wp, &tp) - || switch_win(save_curwinp, save_curtabp, wp, tp, true) == FAIL) - switch_buffer(save_curbufp, buf); + || switch_win(save_curwinp, save_curtabp, wp, tp, true) == FAIL) { + switch_buffer(save_curbuf, buf); + } } static inline void restore_win_for_buf(win_T *save_curwin, tabpage_T *save_curtab, - buf_T *save_curbuf) + bufref_T *save_curbuf) { - if (save_curbuf == NULL) { + if (save_curbuf->br_buf == NULL) { restore_win(save_curwin, save_curtab, true); } else { restore_buffer(save_curbuf); } } +static inline void buf_set_changedtick(buf_T *const buf, + const varnumber_T changedtick) + REAL_FATTR_NONNULL_ALL REAL_FATTR_ALWAYS_INLINE; + +/// Set b_changedtick and corresponding variable +/// +/// @param[out] buf Buffer to set changedtick in. +/// @param[in] changedtick New value. +static inline void buf_set_changedtick(buf_T *const buf, + const varnumber_T changedtick) +{ +#ifndef NDEBUG + dictitem_T *const changedtick_di = tv_dict_find( + buf->b_vars, S_LEN("changedtick")); + assert(changedtick_di != NULL); + assert(changedtick_di->di_tv.v_type == VAR_NUMBER); + assert(changedtick_di->di_tv.v_lock == VAR_FIXED); + // For some reason formatc does not like the below. +# ifndef UNIT_TESTING_LUA_PREPROCESSING + assert(changedtick_di->di_flags == (DI_FLAGS_RO|DI_FLAGS_FIX)); +# endif + assert(changedtick_di == (dictitem_T *)&buf->changedtick_di); + assert(&buf->b_changedtick // -V501 + == &buf->changedtick_di.di_tv.vval.v_number); +#endif + buf->b_changedtick = changedtick; +} + #define WITH_BUFFER(b, code) \ do { \ - buf_T *save_curbuf = NULL; \ win_T *save_curwin = NULL; \ tabpage_T *save_curtab = NULL; \ + bufref_T save_curbuf = { NULL, 0, 0 }; \ switch_to_win_for_buf(b, &save_curwin, &save_curtab, &save_curbuf); \ code; \ - restore_win_for_buf(save_curwin, save_curtab, save_curbuf); \ + restore_win_for_buf(save_curwin, save_curtab, &save_curbuf); \ } while (0) diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index 2b66a07f48..559dffb945 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -8,14 +8,22 @@ typedef struct file_buffer buf_T; // Forward declaration +// Reference to a buffer that stores the value of buf_free_count. +// bufref_valid() only needs to check "buf" when the count differs. +typedef struct { + buf_T *br_buf; + int br_fnum; + int br_buf_free_count; +} bufref_T; + // for garray_T #include "nvim/garray.h" +// for HLF_COUNT +#include "nvim/highlight_defs.h" // for pos_T, lpos_T and linenr_T #include "nvim/pos.h" // for the number window-local and buffer-local options #include "nvim/option_defs.h" -// for optional iconv support -#include "nvim/iconv.h" // for jump list and tag stack sizes in a buffer and mark types #include "nvim/mark_defs.h" // for u_header_T; needs buf_T. @@ -23,7 +31,7 @@ typedef struct file_buffer buf_T; // Forward declaration // for hashtab_T #include "nvim/hashtab.h" // for dict_T -#include "nvim/eval_defs.h" +#include "nvim/eval/typval.h" // for proftime_T #include "nvim/profile.h" // for String @@ -31,7 +39,7 @@ typedef struct file_buffer buf_T; // Forward declaration // for Map(K, V) #include "nvim/map.h" -#define MODIFIABLE(buf) (!buf->terminal && buf->b_p_ma) +#define MODIFIABLE(buf) (buf->b_p_ma) /* * Flags for w_valid. @@ -83,36 +91,23 @@ typedef struct file_buffer buf_T; // Forward declaration typedef struct window_S win_T; typedef struct wininfo_S wininfo_T; typedef struct frame_S frame_T; -typedef int scid_T; /* script ID */ // for struct memline (it needs memfile_T) #include "nvim/memline_defs.h" - // for struct memfile, bhdr_T, blocknr_T... (it needs buf_T) #include "nvim/memfile_defs.h" -/* - * This is here because regexp_defs.h needs win_T and buf_T. regprog_T is - * used below. - */ +// for regprog_T. Needs win_T and buf_T. #include "nvim/regexp_defs.h" - -// for synstate_T (needs reg_extmatch_T, win_T and buf_T) +// for synstate_T (needs reg_extmatch_T, win_T, buf_T) #include "nvim/syntax_defs.h" - // for signlist_T #include "nvim/sign_defs.h" - // for bufhl_*_T #include "nvim/bufhl_defs.h" -typedef Map(linenr_T, bufhl_vec_T) bufhl_info_T; - -// for FileID -#include "nvim/os/fs_defs.h" - -// for Terminal -#include "nvim/terminal.h" +#include "nvim/os/fs_defs.h" // for FileID +#include "nvim/terminal.h" // for Terminal /* * The taggy struct is used to store the information about a :tag command. @@ -239,6 +234,8 @@ typedef struct { # define w_p_crb_save w_onebuf_opt.wo_crb_save char_u *wo_scl; # define w_p_scl w_onebuf_opt.wo_scl // 'signcolumn' + char_u *wo_winhl; +# define w_p_winhl w_onebuf_opt.wo_winhl // 'winhighlight' int wo_scriptID[WV_COUNT]; /* SIDs for window-local options */ # define w_p_scriptID w_onebuf_opt.wo_scriptID @@ -325,25 +322,6 @@ typedef struct { } tasave_T; /* - * Used for conversion of terminal I/O and script files. - */ -typedef struct { - int vc_type; /* zero or one of the CONV_ values */ - int vc_factor; /* max. expansion factor */ -# ifdef USE_ICONV - iconv_t vc_fd; /* for CONV_ICONV */ -# endif - bool vc_fail; /* fail for invalid char, don't use '?' */ -} vimconv_T; - -#define CONV_NONE 0 -#define CONV_TO_UTF8 1 -#define CONV_9_TO_UTF8 2 -#define CONV_TO_LATIN1 3 -#define CONV_TO_LATIN9 4 -#define CONV_ICONV 5 - -/* * Structure used for mappings and abbreviations. */ typedef struct mapblock mapblock_T; @@ -453,6 +431,16 @@ typedef struct { char_u *b_syn_isk; // iskeyword option } synblock_T; +/// Type used for changedtick_di member in buf_T +/// +/// Primary exists so that literals of relevant type can be made. +typedef TV_DICTITEM_STRUCT(sizeof("changedtick")) ChangedtickDictItem; + +#define BUF_HAS_QF_ENTRY 1 +#define BUF_HAS_LL_ENTRY 2 + +// Maximum number of maphash blocks we will have +#define MAX_MAPHASH 256 /* * buffer: structure that holds information about one file @@ -473,9 +461,9 @@ struct file_buffer { int b_nwindows; /* nr of windows open on this buffer */ - int b_flags; /* various BF_ flags */ - bool b_closing; /* buffer is being closed, don't let - autocommands close it too. */ + int b_flags; // various BF_ flags + int b_locked; // Buffer is being closed or referenced, don't + // let autocommands wipe it out. /* * b_ffname has the full path of the file (NULL for no name). @@ -492,7 +480,9 @@ struct file_buffer { int b_changed; // 'modified': Set to true if something in the // file has been changed and not written out. - int b_changedtick; // incremented for each change, also for undo +/// Change identifier incremented for each change, including undo +#define b_changedtick changedtick_di.di_tv.vval.v_number + ChangedtickDictItem changedtick_di; // b:changedtick dictionary item. bool b_saving; /* Set to true if we are in the middle of saving the buffer. */ @@ -540,8 +530,8 @@ struct file_buffer { */ uint64_t b_chartab[4]; - /* Table used for mappings local to a buffer. */ - mapblock_T *(b_maphash[256]); + // Table used for mappings local to a buffer. + mapblock_T *(b_maphash[MAX_MAPHASH]); /* First abbreviation local to a buffer. */ mapblock_T *b_first_abbr; @@ -611,7 +601,7 @@ struct file_buffer { int b_p_bomb; ///< 'bomb' char_u *b_p_bh; ///< 'bufhidden' char_u *b_p_bt; ///< 'buftype' - bool b_has_qf_entry; ///< quickfix exists for buffer + int b_has_qf_entry; ///< quickfix exists for buffer int b_p_bl; ///< 'buflisted' int b_p_cin; ///< 'cindent' char_u *b_p_cino; ///< 'cinoptions' @@ -641,6 +631,7 @@ struct file_buffer { char_u *b_p_inde; ///< 'indentexpr' uint32_t b_p_inde_flags; ///< flags for 'indentexpr' char_u *b_p_indk; ///< 'indentkeys' + char_u *b_p_fp; ///< 'formatprg' char_u *b_p_fex; ///< 'formatexpr' uint32_t b_p_fex_flags; ///< flags for 'formatexpr' char_u *b_p_kp; ///< 'keywordprg' @@ -654,6 +645,7 @@ struct file_buffer { char_u *b_p_qe; ///< 'quoteescape' int b_p_ro; ///< 'readonly' long b_p_sw; ///< 'shiftwidth' + long b_p_scbk; ///< 'scrollback' int b_p_si; ///< 'smartindent' long b_p_sts; ///< 'softtabstop' long b_p_sts_nopaste; ///< b_p_sts saved for paste mode @@ -734,8 +726,8 @@ struct file_buffer { int b_bad_char; /* "++bad=" argument when edit started or 0 */ int b_start_bomb; /* 'bomb' when it was read */ - dictitem_T b_bufvar; /* variable for "b:" Dictionary */ - dict_T *b_vars; /* internal variables, local to buffer */ + ScopeDictDictItem b_bufvar; ///< Variable for "b:" Dictionary. + dict_T *b_vars; ///< b: scope dictionary. /* When a buffer is created, it starts without a swap file. b_may_swap is * then set to indicate that a swap file may be opened later. It is reset @@ -768,7 +760,9 @@ struct file_buffer { int b_mapped_ctrl_c; // modes where CTRL-C is mapped - bufhl_info_T *b_bufhl_info; // buffer stored highlights + BufhlInfo b_bufhl_info; // buffer stored highlights + + kvec_t(BufhlLine *) b_bufhl_move_space; // temporary space for highlights }; /* @@ -823,10 +817,9 @@ struct tabpage_S { buf_T *(tp_diffbuf[DB_COUNT]); int tp_diff_invalid; ///< list of diffs is outdated frame_T *(tp_snapshot[SNAP_COUNT]); ///< window layout snapshots - dictitem_T tp_winvar; ///< variable for "t:" Dictionary - dict_T *tp_vars; ///< internal variables, local to tab page - char_u *localdir; ///< Absolute path of local directory or - ///< NULL + ScopeDictDictItem tp_winvar; ///< Variable for "t:" Dictionary. + dict_T *tp_vars; ///< Internal variables, local to tab page. + char_u *tp_localdir; ///< Absolute path of local cwd or NULL. }; /* @@ -945,6 +938,14 @@ struct window_S { synblock_T *w_s; /* for :ownsyntax */ + int w_hl_id_normal; ///< 'winhighlight' normal id + int w_hl_attr_normal; ///< 'winhighlight' normal final attrs + + int w_hl_ids[HLF_COUNT]; ///< 'winhighlight' id + int w_hl_attrs[HLF_COUNT]; ///< 'winhighlight' final attrs + + int w_hl_needs_update; ///< attrs need to be recalculated + win_T *w_prev; /* link to previous window */ win_T *w_next; /* link to next window */ bool w_closing; /* window is being closed, don't let @@ -1118,8 +1119,8 @@ struct window_S { long w_scbind_pos; - dictitem_T w_winvar; /* variable for "w:" Dictionary */ - dict_T *w_vars; /* internal variables, local to window */ + ScopeDictDictItem w_winvar; ///< Variable for "w:" dictionary. + dict_T *w_vars; ///< Dictionary with w: variables. int w_farsi; /* for the window dependent Farsi functions */ @@ -1174,4 +1175,9 @@ struct window_S { qf_info_T *w_llist_ref; }; +static inline int win_hl_attr(win_T *wp, int hlf) +{ + return wp->w_hl_attrs[hlf]; +} + #endif // NVIM_BUFFER_DEFS_H diff --git a/src/nvim/bufhl_defs.h b/src/nvim/bufhl_defs.h index e47bb2a238..14b1afa7d9 100644 --- a/src/nvim/bufhl_defs.h +++ b/src/nvim/bufhl_defs.h @@ -3,23 +3,32 @@ #include "nvim/pos.h" #include "nvim/lib/kvec.h" +#include "nvim/lib/kbtree.h" + // bufhl: buffer specific highlighting -struct bufhl_hl_item -{ +typedef struct { int src_id; int hl_id; // highlight group colnr_T start; // first column to highlight colnr_T stop; // last column to highlight -}; -typedef struct bufhl_hl_item bufhl_hl_item_T; +} BufhlItem; -typedef kvec_t(struct bufhl_hl_item) bufhl_vec_T; +typedef kvec_t(BufhlItem) BufhlItemVec; + +typedef struct { + linenr_T line; + BufhlItemVec items; +} BufhlLine; +#define BUFHLLINE_INIT(l) { l, KV_INITIAL_VALUE } typedef struct { - bufhl_vec_T entries; + BufhlItemVec entries; int current; colnr_T valid_to; -} bufhl_lineinfo_T; +} BufhlLineInfo; +#define BUFHL_CMP(a, b) ((int)(((a)->line - (b)->line))) +KBTREE_INIT(bufhl, BufhlLine *, BUFHL_CMP, 10) // -V512 +typedef kbtree_t(bufhl) BufhlInfo; #endif // NVIM_BUFHL_DEFS_H diff --git a/src/nvim/charset.c b/src/nvim/charset.c index 4d150c3230..403ef65c4f 100644 --- a/src/nvim/charset.c +++ b/src/nvim/charset.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + /// @file charset.c /// /// Code related to character sets. @@ -15,6 +18,7 @@ #include "nvim/func_attr.h" #include "nvim/indent.h" #include "nvim/main.h" +#include "nvim/mark.h" #include "nvim/mbyte.h" #include "nvim/memline.h" #include "nvim/memory.h" @@ -41,8 +45,10 @@ static bool chartab_initialized = false; (buf)->b_chartab[(unsigned)(c) >> 6] |= (1ull << ((c) & 0x3f)) #define RESET_CHARTAB(buf, c) \ (buf)->b_chartab[(unsigned)(c) >> 6] &= ~(1ull << ((c) & 0x3f)) +#define GET_CHARTAB_TAB(chartab, c) \ + ((chartab)[(unsigned)(c) >> 6] & (1ull << ((c) & 0x3f))) #define GET_CHARTAB(buf, c) \ - ((buf)->b_chartab[(unsigned)(c) >> 6] & (1ull << ((c) & 0x3f))) + GET_CHARTAB_TAB((buf)->b_chartab, c) // Table used below, see init_chartab() for an explanation static char_u g_chartab[256]; @@ -88,7 +94,6 @@ int buf_init_chartab(buf_T *buf, int global) { int c; int c2; - char_u *p; int i; bool tilde; bool do_isalpha; @@ -142,7 +147,8 @@ int buf_init_chartab(buf_T *buf, int global) // Walk through the 'isident', 'iskeyword', 'isfname' and 'isprint' // options Each option is a list of characters, character numbers or // ranges, separated by commas, e.g.: "200-210,x,#-178,-" - for (i = global ? 0 : 3; i <= 3; ++i) { + for (i = global ? 0 : 3; i <= 3; i++) { + const char_u *p; if (i == 0) { // first round: 'isident' p = p_isi; @@ -167,7 +173,7 @@ int buf_init_chartab(buf_T *buf, int global) } if (ascii_isdigit(*p)) { - c = getdigits_int(&p); + c = getdigits_int((char_u **)&p); } else { c = mb_ptr2char_adv(&p); } @@ -177,7 +183,7 @@ int buf_init_chartab(buf_T *buf, int global) ++p; if (ascii_isdigit(*p)) { - c2 = getdigits_int(&p); + c2 = getdigits_int((char_u **)&p); } else { c2 = mb_ptr2char_adv(&p); } @@ -210,8 +216,8 @@ int buf_init_chartab(buf_T *buf, int global) // work properly when 'encoding' is "latin1" and the locale is // "C". if (!do_isalpha - || vim_islower(c) - || vim_isupper(c) + || mb_islower(c) + || mb_isupper(c) || (p_altkeymap && (F_isalpha(c) || F_isdigit(c)))) { if (i == 0) { // (re)set ID flag @@ -415,11 +421,11 @@ char_u* str_foldcase(char_u *str, int orglen, char_u *buf, int buflen) while (STR_CHAR(i) != NUL) { int c = utf_ptr2char(STR_PTR(i)); int olen = utf_ptr2len(STR_PTR(i)); - int lc = utf_tolower(c); + int lc = mb_tolower(c); // Only replace the character when it is not an invalid // sequence (ASCII character or more than one byte) and - // utf_tolower() doesn't return the original character. + // mb_tolower() doesn't return the original character. if (((c < 0x80) || (olen > 1)) && (c != lc)) { int nlen = utf_char2len(lc); @@ -486,7 +492,8 @@ char_u* transchar(int c) c = K_SECOND(c); } - if ((!chartab_initialized && (((c >= ' ') && (c <= '~')) || F_ischar(c))) + if ((!chartab_initialized && (((c >= ' ') && (c <= '~')) + || (p_altkeymap && F_ischar(c)))) || ((c < 256) && vim_isprintc_strict(c))) { // printable character transchar_buf[i] = (char_u)c; @@ -538,18 +545,8 @@ void transchar_nonprint(char_u *buf, int c) buf[1] = (char_u)(c ^ 0x40); buf[2] = NUL; - } else if (c >= 0x80) { - transchar_hex(buf, c); - } else if ((c >= ' ' + 0x80) && (c <= '~' + 0x80)) { - // 0xa0 - 0xfe - buf[0] = '|'; - buf[1] = (char_u)(c - 0x80); - buf[2] = NUL; } else { - // 0x80 - 0x9f and 0xff - buf[0] = '~'; - buf[1] = (char_u)((c - 0x80) ^ 0x40); - buf[2] = NUL; + transchar_hex(buf, c); } } @@ -633,7 +630,7 @@ int char2cells(int c) /// @param p /// /// @return number of display cells. -int ptr2cells(char_u *p) +int ptr2cells(const char_u *p) { // For UTF-8 we need to look at more bytes if the first byte is >= 0x80. if (*p >= 0x80) { @@ -775,6 +772,20 @@ bool vim_iswordc(int c) return vim_iswordc_buf(c, curbuf); } +/// Check that "c" is a keyword character +/// Letters and characters from 'iskeyword' option for given buffer. +/// For multi-byte characters mb_get_class() is used (builtin rules). +/// +/// @param[in] c Character to check. +/// @param[in] chartab Buffer chartab. +bool vim_iswordc_tab(const int c, const uint64_t *const chartab) + FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL +{ + return (c >= 0x100 + ? (utf_class(c) >= 2) + : (c > 0 && GET_CHARTAB_TAB(chartab, c) != 0)); +} + /// Check that "c" is a keyword character: /// Letters and characters from 'iskeyword' option for given buffer. /// For multi-byte characters mb_get_class() is used (builtin rules). @@ -784,10 +795,7 @@ bool vim_iswordc(int c) bool vim_iswordc_buf(int c, buf_T *buf) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ARG(2) { - if (c >= 0x100) { - return utf_class(c) >= 2; - } - return c > 0 && c < 0x100 && GET_CHARTAB(buf, c) != 0; + return vim_iswordc_tab(c, buf->b_chartab); } /// Just like vim_iswordc() but uses a pointer to the (multi-byte) character. @@ -973,10 +981,8 @@ int win_lbr_chartabsize(win_T *wp, char_u *line, char_u *s, colnr_T col, int *he mb_ptr_adv(s); c = *s; - if (!((c != NUL) - && (vim_isbreak(c) - || (!vim_isbreak(c) - && ((col2 == col) || !vim_isbreak(*ps)))))) { + if (!(c != NUL + && (vim_isbreak(c) || col2 == col || !vim_isbreak(*ps)))) { break; } @@ -1159,7 +1165,13 @@ void getvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, // continue until the NUL posptr = NULL; } else { + // Special check for an empty line, which can happen on exit, when + // ml_get_buf() always returns an empty string. + if (*ptr == NUL) { + pos->col = 0; + } posptr = ptr + pos->col; + posptr -= utf_head_off(line, posptr); } // This function is used very often, do some speed optimizations. @@ -1346,7 +1358,7 @@ void getvcols(win_T *wp, pos_T *pos1, pos_T *pos2, colnr_T *left, colnr_T to1; colnr_T to2; - if (ltp(pos1, pos2)) { + if (lt(*pos1, *pos2)) { getvvcol(wp, pos1, &from1, NULL, &to1); getvvcol(wp, pos2, &from2, NULL, &to2); } else { @@ -1373,32 +1385,35 @@ void getvcols(win_T *wp, pos_T *pos1, pos_T *pos2, colnr_T *left, /// skipwhite: skip over ' ' and '\t'. /// -/// @param q +/// @param[in] q String to skip in. /// /// @return Pointer to character after the skipped whitespace. -char_u* skipwhite(char_u *q) +char_u *skipwhite(const char_u *q) + FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL + FUNC_ATTR_NONNULL_RET { - char_u *p = q; + const char_u *p = q; while (ascii_iswhite(*p)) { - // skip to next non-white p++; } - return p; + return (char_u *)p; } -/// skip over digits +/// Skip over digits /// -/// @param q +/// @param[in] q String to skip digits in. /// /// @return Pointer to the character after the skipped digits. -char_u* skipdigits(char_u *q) +char_u *skipdigits(const char_u *q) + FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL + FUNC_ATTR_NONNULL_RET { - char_u *p = q; + const char_u *p = q; while (ascii_isdigit(*p)) { // skip to next non-digit p++; } - return p; + return (char_u *)p; } /// skip over binary digits @@ -1483,78 +1498,17 @@ char_u* skiptohex(char_u *q) return p; } -// Vim's own character class functions. These exist because many library -// islower()/toupper() etc. do not work properly: they crash when used with -// invalid values or can't handle latin1 when the locale is C. -// Speed is most important here. - -/// Check that the character is lower-case -/// -/// @param c character to check -bool vim_islower(int c) - FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT -{ - if (c <= '@') { - return false; - } - - if (c >= 0x80) { - return utf_islower(c); - } - return islower(c); -} - -/// Check that the character is upper-case +/// Skip over text until ' ' or '\t' or NUL /// -/// @param c character to check -bool vim_isupper(int c) - FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT -{ - if (c <= '@') { - return false; - } - - if (c >= 0x80) { - return utf_isupper(c); - } - return isupper(c); -} - -int vim_toupper(int c) -{ - if (c <= '@') { - return c; - } - - if (c >= 0x80) { - return utf_toupper(c); - } - return TOUPPER_LOC(c); -} - -int vim_tolower(int c) -{ - if (c <= '@') { - return c; - } - - if (c >= 0x80) { - return utf_tolower(c); - } - return TOLOWER_LOC(c); -} - -/// skiptowhite: skip over text until ' ' or '\t' or NUL. -/// -/// @param p +/// @param[in] p Text to skip over. /// /// @return Pointer to the next whitespace or NUL character. -char_u* skiptowhite(char_u *p) +char_u *skiptowhite(const char_u *p) { while (*p != ' ' && *p != '\t' && *p != NUL) { p++; } - return p; + return (char_u *)p; } /// skiptowhite_esc: Like skiptowhite(), but also skip escaped chars @@ -1665,13 +1619,13 @@ bool vim_isblankline(char_u *lbuf) /// @param unptr Returns the unsigned result. /// @param maxlen Max length of string to check. void vim_str2nr(const char_u *const start, int *const prep, int *const len, - const int what, long *const nptr, unsigned long *const unptr, - const int maxlen) + const int what, varnumber_T *const nptr, + uvarnumber_T *const unptr, const int maxlen) { const char_u *ptr = start; int pre = 0; // default is decimal bool negative = false; - unsigned long un = 0; + uvarnumber_T un = 0; if (ptr[0] == '-') { negative = true; @@ -1727,7 +1681,12 @@ void vim_str2nr(const char_u *const start, int *const prep, int *const len, n += 2; // skip over "0b" } while ('0' <= *ptr && *ptr <= '1') { - un = 2 * un + (unsigned long)(*ptr - '0'); + // avoid ubsan error for overflow + if (un < UVARNUMBER_MAX / 2) { + un = 2 * un + (uvarnumber_T)(*ptr - '0'); + } else { + un = UVARNUMBER_MAX; + } ptr++; if (n++ == maxlen) { break; @@ -1736,7 +1695,12 @@ void vim_str2nr(const char_u *const start, int *const prep, int *const len, } else if ((pre == '0') || what == STR2NR_OCT + STR2NR_FORCE) { // octal while ('0' <= *ptr && *ptr <= '7') { - un = 8 * un + (unsigned long)(*ptr - '0'); + // avoid ubsan error for overflow + if (un < UVARNUMBER_MAX / 8) { + un = 8 * un + (uvarnumber_T)(*ptr - '0'); + } else { + un = UVARNUMBER_MAX; + } ptr++; if (n++ == maxlen) { break; @@ -1749,7 +1713,12 @@ void vim_str2nr(const char_u *const start, int *const prep, int *const len, n += 2; // skip over "0x" } while (ascii_isxdigit(*ptr)) { - un = 16 * un + (unsigned long)hex2nr(*ptr); + // avoid ubsan error for overflow + if (un < UVARNUMBER_MAX / 16) { + un = 16 * un + (uvarnumber_T)hex2nr(*ptr); + } else { + un = UVARNUMBER_MAX; + } ptr++; if (n++ == maxlen) { break; @@ -1758,7 +1727,12 @@ void vim_str2nr(const char_u *const start, int *const prep, int *const len, } else { // decimal while (ascii_isdigit(*ptr)) { - un = 10 * un + (unsigned long)(*ptr - '0'); + // avoid ubsan error for overflow + if (un < UVARNUMBER_MAX / 10) { + un = 10 * un + (uvarnumber_T)(*ptr - '0'); + } else { + un = UVARNUMBER_MAX; + } ptr++; if (n++ == maxlen) { break; @@ -1775,11 +1749,18 @@ void vim_str2nr(const char_u *const start, int *const prep, int *const len, } if (nptr != NULL) { - if (negative) { - // account for leading '-' for decimal numbers - *nptr = -(long)un; + if (negative) { // account for leading '-' for decimal numbers + // avoid ubsan error for overflow + if (un > VARNUMBER_MAX) { + *nptr = VARNUMBER_MIN; + } else { + *nptr = -(varnumber_T)un; + } } else { - *nptr = (long)un; + if (un > VARNUMBER_MAX) { + un = VARNUMBER_MAX; + } + *nptr = (varnumber_T)un; } } diff --git a/src/nvim/charset.h b/src/nvim/charset.h index 78d6f2a76c..c69582c4c6 100644 --- a/src/nvim/charset.h +++ b/src/nvim/charset.h @@ -1,6 +1,20 @@ #ifndef NVIM_CHARSET_H #define NVIM_CHARSET_H +#include "nvim/types.h" +#include "nvim/pos.h" +#include "nvim/buffer_defs.h" + +/// Return the folded-case equivalent of the given character +/// +/// @param[in] c Character to transform. +/// +/// @return Folded variant. +#define CH_FOLD(c) \ + utf_fold((sizeof(c) == sizeof(char)) \ + ?((int)(uint8_t)(c)) \ + :((int)(c))) + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "charset.h.generated.h" #endif diff --git a/src/nvim/cursor.c b/src/nvim/cursor.c index 3ba9da34f2..60002f3cea 100644 --- a/src/nvim/cursor.c +++ b/src/nvim/cursor.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #include <stdbool.h> #include <inttypes.h> @@ -12,6 +15,7 @@ #include "nvim/state.h" #include "nvim/vim.h" #include "nvim/ascii.h" +#include "nvim/mark.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "cursor.c.generated.h" @@ -227,9 +231,10 @@ static int coladvance2( } } - /* prevent from moving onto a trail byte */ - if (has_mbyte) - mb_adjustpos(curbuf, pos); + // Prevent from moving onto a trail byte. + if (has_mbyte) { + mark_mb_adjustpos(curbuf, pos); + } if (col < wcol) return FAIL; @@ -294,6 +299,26 @@ linenr_T get_cursor_rel_lnum(win_T *wp, linenr_T lnum) return (lnum < cursor) ? -retval : retval; } +// Make sure "pos.lnum" and "pos.col" are valid in "buf". +// This allows for the col to be on the NUL byte. +void check_pos(buf_T *buf, pos_T *pos) +{ + char_u *line; + colnr_T len; + + if (pos->lnum > buf->b_ml.ml_line_count) { + pos->lnum = buf->b_ml.ml_line_count; + } + + if (pos->col > 0) { + line = ml_get_buf(buf, pos->lnum, false); + len = (colnr_T)STRLEN(line); + if (pos->col > len) { + pos->col = len; + } + } +} + /* * Make sure curwin->w_cursor.lnum is valid. */ @@ -318,9 +343,8 @@ void check_cursor_col(void) check_cursor_col_win(curwin); } -/* - * Make sure win->w_cursor.col is valid. - */ +/// Make sure win->w_cursor.col is valid. Special handling of insert-mode. +/// @see mb_check_adjust_col void check_cursor_col_win(win_T *win) { colnr_T len; @@ -342,9 +366,10 @@ void check_cursor_col_win(win_T *win) win->w_cursor.col = len; } else { win->w_cursor.col = len - 1; - /* Move the cursor to the head byte. */ - if (has_mbyte) - mb_adjustpos(win->w_buffer, &win->w_cursor); + // Move the cursor to the head byte. + if (has_mbyte) { + mark_mb_adjustpos(win->w_buffer, &win->w_cursor); + } } } else if (win->w_cursor.col < 0) { win->w_cursor.col = 0; diff --git a/src/nvim/cursor_shape.c b/src/nvim/cursor_shape.c index b50462664c..97fc3a3ca3 100644 --- a/src/nvim/cursor_shape.c +++ b/src/nvim/cursor_shape.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #include <assert.h> #include <stdint.h> #include "nvim/vim.h" @@ -7,40 +10,75 @@ #include "nvim/charset.h" #include "nvim/strings.h" #include "nvim/syntax.h" +#include "nvim/api/private/helpers.h" +#include "nvim/ui.h" -/* - * Handling of cursor and mouse pointer shapes in various modes. - */ - -static cursorentry_T shape_table[SHAPE_IDX_COUNT] = +/// Handling of cursor and mouse pointer shapes in various modes. +cursorentry_T shape_table[SHAPE_IDX_COUNT] = { - /* The values will be filled in from the 'guicursor' and 'mouseshape' - * defaults when Vim starts. - * Adjust the SHAPE_IDX_ defines when making changes! */ - {0, 0, 0, 700L, 400L, 250L, 0, 0, "n", SHAPE_CURSOR+SHAPE_MOUSE}, - {0, 0, 0, 700L, 400L, 250L, 0, 0, "v", SHAPE_CURSOR+SHAPE_MOUSE}, - {0, 0, 0, 700L, 400L, 250L, 0, 0, "i", SHAPE_CURSOR+SHAPE_MOUSE}, - {0, 0, 0, 700L, 400L, 250L, 0, 0, "r", SHAPE_CURSOR+SHAPE_MOUSE}, - {0, 0, 0, 700L, 400L, 250L, 0, 0, "c", SHAPE_CURSOR+SHAPE_MOUSE}, - {0, 0, 0, 700L, 400L, 250L, 0, 0, "ci", SHAPE_CURSOR+SHAPE_MOUSE}, - {0, 0, 0, 700L, 400L, 250L, 0, 0, "cr", SHAPE_CURSOR+SHAPE_MOUSE}, - {0, 0, 0, 700L, 400L, 250L, 0, 0, "o", SHAPE_CURSOR+SHAPE_MOUSE}, - {0, 0, 0, 700L, 400L, 250L, 0, 0, "ve", SHAPE_CURSOR+SHAPE_MOUSE}, - {0, 0, 0, 0L, 0L, 0L, 0, 0, "e", SHAPE_MOUSE}, - {0, 0, 0, 0L, 0L, 0L, 0, 0, "s", SHAPE_MOUSE}, - {0, 0, 0, 0L, 0L, 0L, 0, 0, "sd", SHAPE_MOUSE}, - {0, 0, 0, 0L, 0L, 0L, 0, 0, "vs", SHAPE_MOUSE}, - {0, 0, 0, 0L, 0L, 0L, 0, 0, "vd", SHAPE_MOUSE}, - {0, 0, 0, 0L, 0L, 0L, 0, 0, "m", SHAPE_MOUSE}, - {0, 0, 0, 0L, 0L, 0L, 0, 0, "ml", SHAPE_MOUSE}, - {0, 0, 0, 100L, 100L, 100L, 0, 0, "sm", SHAPE_CURSOR}, + // Values are set by 'guicursor' and 'mouseshape'. + // Adjust the SHAPE_IDX_ defines when changing this! + { "normal", 0, 0, 0, 700L, 400L, 250L, 0, 0, "n", SHAPE_CURSOR+SHAPE_MOUSE }, + { "visual", 0, 0, 0, 700L, 400L, 250L, 0, 0, "v", SHAPE_CURSOR+SHAPE_MOUSE }, + { "insert", 0, 0, 0, 700L, 400L, 250L, 0, 0, "i", SHAPE_CURSOR+SHAPE_MOUSE }, + { "replace", 0, 0, 0, 700L, 400L, 250L, 0, 0, "r", SHAPE_CURSOR+SHAPE_MOUSE }, + { "cmdline_normal", 0, 0, 0, 700L, 400L, 250L, 0, 0, "c", SHAPE_CURSOR+SHAPE_MOUSE }, + { "cmdline_insert", 0, 0, 0, 700L, 400L, 250L, 0, 0, "ci", SHAPE_CURSOR+SHAPE_MOUSE }, + { "cmdline_replace", 0, 0, 0, 700L, 400L, 250L, 0, 0, "cr", SHAPE_CURSOR+SHAPE_MOUSE }, + { "operator", 0, 0, 0, 700L, 400L, 250L, 0, 0, "o", SHAPE_CURSOR+SHAPE_MOUSE }, + { "visual_select", 0, 0, 0, 700L, 400L, 250L, 0, 0, "ve", SHAPE_CURSOR+SHAPE_MOUSE }, + { "cmdline_hover", 0, 0, 0, 0L, 0L, 0L, 0, 0, "e", SHAPE_MOUSE }, + { "statusline_hover", 0, 0, 0, 0L, 0L, 0L, 0, 0, "s", SHAPE_MOUSE }, + { "statusline_drag", 0, 0, 0, 0L, 0L, 0L, 0, 0, "sd", SHAPE_MOUSE }, + { "vsep_hover", 0, 0, 0, 0L, 0L, 0L, 0, 0, "vs", SHAPE_MOUSE }, + { "vsep_drag", 0, 0, 0, 0L, 0L, 0L, 0, 0, "vd", SHAPE_MOUSE }, + { "more", 0, 0, 0, 0L, 0L, 0L, 0, 0, "m", SHAPE_MOUSE }, + { "more_lastline", 0, 0, 0, 0L, 0L, 0L, 0, 0, "ml", SHAPE_MOUSE }, + { "showmatch", 0, 0, 0, 100L, 100L, 100L, 0, 0, "sm", SHAPE_CURSOR }, }; -/* - * Parse the 'guicursor' option ("what" is SHAPE_CURSOR) or 'mouseshape' - * ("what" is SHAPE_MOUSE). - * Returns error message for an illegal option, NULL otherwise. - */ +/// Converts cursor_shapes into an Array of Dictionaries +/// @return Array of the form {[ "cursor_shape": ... ], ...} +Array mode_style_array(void) +{ + Array all = ARRAY_DICT_INIT; + + for (int i = 0; i < SHAPE_IDX_COUNT; i++) { + Dictionary dic = ARRAY_DICT_INIT; + cursorentry_T *cur = &shape_table[i]; + if (cur->used_for & SHAPE_MOUSE) { + PUT(dic, "mouse_shape", INTEGER_OBJ(cur->mshape)); + } + if (cur->used_for & SHAPE_CURSOR) { + String shape_str; + switch (cur->shape) { + case SHAPE_BLOCK: shape_str = cstr_to_string("block"); break; + case SHAPE_VER: shape_str = cstr_to_string("vertical"); break; + case SHAPE_HOR: shape_str = cstr_to_string("horizontal"); break; + default: shape_str = cstr_to_string("unknown"); + } + PUT(dic, "cursor_shape", STRING_OBJ(shape_str)); + PUT(dic, "cell_percentage", INTEGER_OBJ(cur->percentage)); + PUT(dic, "blinkwait", INTEGER_OBJ(cur->blinkwait)); + PUT(dic, "blinkon", INTEGER_OBJ(cur->blinkon)); + PUT(dic, "blinkoff", INTEGER_OBJ(cur->blinkoff)); + PUT(dic, "hl_id", INTEGER_OBJ(cur->id)); + PUT(dic, "id_lm", INTEGER_OBJ(cur->id_lm)); + } + PUT(dic, "name", STRING_OBJ(cstr_to_string(cur->full_name))); + PUT(dic, "short_name", STRING_OBJ(cstr_to_string(cur->name))); + + ADD(all, DICTIONARY_OBJ(dic)); + } + + return all; +} + +/// Parse the 'guicursor' option +/// +/// @param what SHAPE_CURSOR or SHAPE_MOUSE ('mouseshape') +/// +/// @returns error message for an illegal option, NULL otherwise. char_u *parse_shape_opt(int what) { char_u *modep; @@ -55,14 +93,13 @@ char_u *parse_shape_opt(int what) int found_ve = false; /* found "ve" flag */ int round; - /* - * First round: check for errors; second round: do it for real. - */ - for (round = 1; round <= 2; ++round) { - /* - * Repeat for all comma separated parts. - */ + // First round: check for errors; second round: do it for real. + for (round = 1; round <= 2; round++) { + // Repeat for all comma separated parts. modep = p_guicursor; + if (*p_guicursor == NUL) { + modep = (char_u *)"a:block-blinkon0"; + } while (*modep != NUL) { colonp = vim_strchr(modep, ':'); if (colonp == NULL) @@ -71,19 +108,18 @@ char_u *parse_shape_opt(int what) return (char_u *)N_("E546: Illegal mode"); commap = vim_strchr(modep, ','); - /* - * Repeat for all mode's before the colon. - * For the 'a' mode, we loop to handle all the modes. - */ + // Repeat for all modes before the colon. + // For the 'a' mode, we loop to handle all the modes. all_idx = -1; assert(modep < colonp); while (modep < colonp || all_idx >= 0) { if (all_idx < 0) { - /* Find the mode. */ - if (modep[1] == '-' || modep[1] == ':') + // Find the mode + if (modep[1] == '-' || modep[1] == ':') { len = 1; - else + } else { len = 2; + } if (len == 1 && TOLOWER_ASC(modep[0]) == 'a') { all_idx = SHAPE_IDX_COUNT - 1; @@ -100,15 +136,15 @@ char_u *parse_shape_opt(int what) modep += len + 1; } - if (all_idx >= 0) + if (all_idx >= 0) { idx = all_idx--; - else if (round == 2) { + } else if (round == 2) { { - /* Set the defaults, for the missing parts */ + // Set the defaults, for the missing parts shape_table[idx].shape = SHAPE_BLOCK; - shape_table[idx].blinkwait = 700L; - shape_table[idx].blinkon = 400L; - shape_table[idx].blinkoff = 250L; + shape_table[idx].blinkwait = 0L; + shape_table[idx].blinkon = 0L; + shape_table[idx].blinkoff = 0L; } } @@ -208,6 +244,55 @@ char_u *parse_shape_opt(int what) shape_table[SHAPE_IDX_VE].id_lm = shape_table[SHAPE_IDX_V].id_lm; } } - + ui_mode_info_set(); return NULL; } + + +/// Map cursor mode from string to integer +/// +/// @param mode Fullname of the mode whose id we are looking for +/// @return -1 in case of failure, else the matching SHAPE_ID* integer +int cursor_mode_str2int(const char *mode) +{ + for (int current_mode = 0; current_mode < SHAPE_IDX_COUNT; current_mode++) { + if (strcmp(shape_table[current_mode].full_name, mode) == 0) { + return current_mode; + } + } + WLOG("Unknown mode %s", mode); + return -1; +} + + +/// Return the index into shape_table[] for the current mode. +int cursor_get_mode_idx(void) +{ + if (State == SHOWMATCH) { + return SHAPE_IDX_SM; + } else if (State & VREPLACE_FLAG) { + return SHAPE_IDX_R; + } else if (State & REPLACE_FLAG) { + return SHAPE_IDX_R; + } else if (State & INSERT) { + return SHAPE_IDX_I; + } else if (State & CMDLINE) { + if (cmdline_at_end()) { + return SHAPE_IDX_C; + } else if (cmdline_overstrike()) { + return SHAPE_IDX_CR; + } else { + return SHAPE_IDX_CI; + } + } else if (finish_op) { + return SHAPE_IDX_O; + } else if (VIsual_active) { + if (*p_sel == 'e') { + return SHAPE_IDX_VE; + } else { + return SHAPE_IDX_V; + } + } else { + return SHAPE_IDX_N; + } +} diff --git a/src/nvim/cursor_shape.h b/src/nvim/cursor_shape.h index 9ce1b6e0a0..2c466603f0 100644 --- a/src/nvim/cursor_shape.h +++ b/src/nvim/cursor_shape.h @@ -1,32 +1,37 @@ #ifndef NVIM_CURSOR_SHAPE_H #define NVIM_CURSOR_SHAPE_H -/* - * struct to store values from 'guicursor' and 'mouseshape' - */ -/* Indexes in shape_table[] */ -#define SHAPE_IDX_N 0 /* Normal mode */ -#define SHAPE_IDX_V 1 /* Visual mode */ -#define SHAPE_IDX_I 2 /* Insert mode */ -#define SHAPE_IDX_R 3 /* Replace mode */ -#define SHAPE_IDX_C 4 /* Command line Normal mode */ -#define SHAPE_IDX_CI 5 /* Command line Insert mode */ -#define SHAPE_IDX_CR 6 /* Command line Replace mode */ -#define SHAPE_IDX_O 7 /* Operator-pending mode */ -#define SHAPE_IDX_VE 8 /* Visual mode with 'selection' exclusive */ -#define SHAPE_IDX_CLINE 9 /* On command line */ -#define SHAPE_IDX_STATUS 10 /* A status line */ -#define SHAPE_IDX_SDRAG 11 /* dragging a status line */ -#define SHAPE_IDX_VSEP 12 /* A vertical separator line */ -#define SHAPE_IDX_VDRAG 13 /* dragging a vertical separator line */ -#define SHAPE_IDX_MORE 14 /* Hit-return or More */ -#define SHAPE_IDX_MOREL 15 /* Hit-return or More in last line */ -#define SHAPE_IDX_SM 16 /* showing matching paren */ -#define SHAPE_IDX_COUNT 17 - -#define SHAPE_BLOCK 0 /* block cursor */ -#define SHAPE_HOR 1 /* horizontal bar cursor */ -#define SHAPE_VER 2 /* vertical bar cursor */ +#include "nvim/types.h" +#include "nvim/api/private/defs.h" + +/// struct to store values from 'guicursor' and 'mouseshape' +/// Indexes in shape_table[] +typedef enum { +SHAPE_IDX_N = 0, ///< Normal mode +SHAPE_IDX_V = 1, ///< Visual mode +SHAPE_IDX_I = 2, ///< Insert mode +SHAPE_IDX_R = 3, ///< Replace mode +SHAPE_IDX_C = 4, ///< Command line Normal mode +SHAPE_IDX_CI = 5, ///< Command line Insert mode +SHAPE_IDX_CR = 6, ///< Command line Replace mode +SHAPE_IDX_O = 7, ///< Operator-pending mode +SHAPE_IDX_VE = 8, ///< Visual mode with 'selection' exclusive +SHAPE_IDX_CLINE = 9, ///< On command line +SHAPE_IDX_STATUS = 10, ///< On status line +SHAPE_IDX_SDRAG = 11, ///< dragging a status line +SHAPE_IDX_VSEP = 12, ///< On vertical separator line +SHAPE_IDX_VDRAG = 13, ///< dragging a vertical separator line +SHAPE_IDX_MORE = 14, ///< Hit-return or More +SHAPE_IDX_MOREL = 15, ///< Hit-return or More in last line +SHAPE_IDX_SM = 16, ///< showing matching paren +SHAPE_IDX_COUNT = 17 +} ModeShape; + +typedef enum { +SHAPE_BLOCK = 0, ///< block cursor +SHAPE_HOR = 1, ///< horizontal bar cursor +SHAPE_VER = 2 ///< vertical bar cursor +} CursorShape; #define MSHAPE_NUMBERED 1000 /* offset for shapes identified by number */ #define MSHAPE_HIDE 1 /* hide mouse pointer */ @@ -35,18 +40,20 @@ #define SHAPE_CURSOR 2 /* used for text cursor shape */ typedef struct cursor_entry { - int shape; /* one of the SHAPE_ defines */ - int mshape; /* one of the MSHAPE defines */ - int percentage; /* percentage of cell for bar */ - long blinkwait; /* blinking, wait time before blinking starts */ - long blinkon; /* blinking, on time */ - long blinkoff; /* blinking, off time */ - int id; /* highlight group ID */ - int id_lm; /* highlight group ID for :lmap mode */ - char *name; /* mode name (fixed) */ - char used_for; /* SHAPE_MOUSE and/or SHAPE_CURSOR */ + char *full_name; ///< mode description + CursorShape shape; ///< cursor shape: one of the SHAPE_ defines + int mshape; ///< mouse shape: one of the MSHAPE defines + int percentage; ///< percentage of cell for bar + long blinkwait; ///< blinking, wait time before blinking starts + long blinkon; ///< blinking, on time + long blinkoff; ///< blinking, off time + int id; ///< highlight group ID + int id_lm; ///< highlight group ID for :lmap mode + char *name; ///< mode short name + char used_for; ///< SHAPE_MOUSE and/or SHAPE_CURSOR } cursorentry_T; +extern cursorentry_T shape_table[SHAPE_IDX_COUNT]; #ifdef INCLUDE_GENERATED_DECLARATIONS # include "cursor_shape.h.generated.h" diff --git a/src/nvim/diff.c b/src/nvim/diff.c index f7b96ba3e1..17de4284ce 100644 --- a/src/nvim/diff.c +++ b/src/nvim/diff.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + /// @file diff.c /// /// Code for diff'ing two, three or four buffers. @@ -129,7 +132,7 @@ void diff_buf_add(buf_T *buf) } } - EMSGN(_("E96: Can not diff more than %" PRId64 " buffers"), DB_COUNT); + EMSGN(_("E96: Cannot diff more than %" PRId64 " buffers"), DB_COUNT); } /// Find buffer "buf" in the list of diff buffers for the current tab page. @@ -1004,7 +1007,12 @@ theend: void ex_diffsplit(exarg_T *eap) { win_T *old_curwin = curwin; - buf_T *old_curbuf = curbuf; + bufref_T old_curbuf; + set_bufref(&old_curbuf, curbuf); + + // Need to compute w_fraction when no redraw happened yet. + validate_cursor(); + set_fraction(curwin); // don't use a new tab page, each tab page has its own diffs cmdmod.tab = 0; @@ -1022,15 +1030,15 @@ void ex_diffsplit(exarg_T *eap) if (win_valid(old_curwin)) { diff_win_options(old_curwin, true); - if (buf_valid(old_curbuf)) { + if (bufref_valid(&old_curbuf)) { // Move the cursor position to that of the old window. curwin->w_cursor.lnum = diff_get_corresponding_line( - old_curbuf, - old_curwin->w_cursor.lnum, - curbuf, - curwin->w_cursor.lnum); + old_curbuf.br_buf, old_curwin->w_cursor.lnum); } } + // Now that lines are folded scroll to show the cursor at the same + // relative position. + scroll_to_fraction(curwin, curwin->w_height); } } } @@ -1068,8 +1076,8 @@ void diff_win_options(win_T *wp, int addbuf) if (!wp->w_p_diff) { wp->w_p_wrap_save = wp->w_p_wrap; } - wp->w_p_wrap = FALSE; - curwin = wp; + wp->w_p_wrap = false; + curwin = wp; // -V519 curbuf = curwin->w_buffer; if (!wp->w_p_diff) { @@ -1153,10 +1161,13 @@ void ex_diffoff(exarg_T *eap) } foldUpdateAll(wp); - - // make sure topline is not halfway through a fold - changed_window_setting_win(wp); } + // remove filler lines + wp->w_topfill = 0; + + // make sure topline is not halfway a fold and cursor is + // invalidated + changed_window_setting_win(wp); // Note: 'sbo' is not restored, it's a global option. diff_buf_adjust(wp); @@ -1575,7 +1586,7 @@ static int diff_cmp(char_u *s1, char_u *s2) } if ((diff_flags & DIFF_ICASE) && !(diff_flags & DIFF_IWHITE)) { - return mb_stricmp(s1, s2); + return mb_stricmp((const char *)s1, (const char *)s2); } // Ignore white space changes and possibly ignore case. @@ -2297,7 +2308,7 @@ void ex_diffgetput(exarg_T *eap) // Adjust marks. This will change the following entries! if (added != 0) { - mark_adjust(lnum, lnum + count - 1, (long)MAXLNUM, (long)added); + mark_adjust(lnum, lnum + count - 1, (long)MAXLNUM, (long)added, false); if (curwin->w_cursor.lnum >= lnum) { // Adjust the cursor position if it's in/after the changed // lines. @@ -2449,25 +2460,17 @@ int diff_move_to(int dir, long count) return OK; } -/// Finds the corresponding line in a diff. -/// -/// @param buf1 -/// @param lnum1 -/// @param buf2 -/// @param lnum3 -/// -/// @return The corresponding line. -linenr_T diff_get_corresponding_line(buf_T *buf1, linenr_T lnum1, buf_T *buf2, - linenr_T lnum3) +/// Return the line number in the current window that is closest to "lnum1" in +/// "buf1" in diff mode. +static linenr_T diff_get_corresponding_line_int(buf_T *buf1, linenr_T lnum1) { int idx1; int idx2; diff_T *dp; int baseline = 0; - linenr_T lnum2; idx1 = diff_buf_idx(buf1); - idx2 = diff_buf_idx(buf2); + idx2 = diff_buf_idx(curbuf); if ((idx1 == DB_COUNT) || (idx2 == DB_COUNT) @@ -2487,15 +2490,9 @@ linenr_T diff_get_corresponding_line(buf_T *buf1, linenr_T lnum1, buf_T *buf2, for (dp = curtab->tp_first_diff; dp != NULL; dp = dp->df_next) { if (dp->df_lnum[idx1] > lnum1) { - lnum2 = lnum1 - baseline; - - // don't end up past the end of the file - if (lnum2 > buf2->b_ml.ml_line_count) { - lnum2 = buf2->b_ml.ml_line_count; - } - - return lnum2; - } else if ((dp->df_lnum[idx1] + dp->df_count[idx1]) > lnum1) { + return lnum1 - baseline; + } + if ((dp->df_lnum[idx1] + dp->df_count[idx1]) > lnum1) { // Inside the diffblock baseline = lnum1 - dp->df_lnum[idx1]; @@ -2504,30 +2501,42 @@ linenr_T diff_get_corresponding_line(buf_T *buf1, linenr_T lnum1, buf_T *buf2, } return dp->df_lnum[idx2] + baseline; - } else if ((dp->df_lnum[idx1] == lnum1) - && (dp->df_count[idx1] == 0) - && (dp->df_lnum[idx2] <= lnum3) - && ((dp->df_lnum[idx2] + dp->df_count[idx2]) > lnum3)) { + } + if ((dp->df_lnum[idx1] == lnum1) + && (dp->df_count[idx1] == 0) + && (dp->df_lnum[idx2] <= curwin->w_cursor.lnum) + && ((dp->df_lnum[idx2] + dp->df_count[idx2]) + > curwin->w_cursor.lnum)) { // Special case: if the cursor is just after a zero-count // block (i.e. all filler) and the target cursor is already // inside the corresponding block, leave the target cursor // unmoved. This makes repeated CTRL-W W operations work // as expected. - return lnum3; + return curwin->w_cursor.lnum; } baseline = (dp->df_lnum[idx1] + dp->df_count[idx1]) - - (dp->df_lnum[idx2] + dp->df_count[idx2]); + - (dp->df_lnum[idx2] + dp->df_count[idx2]); } // If we get here then the cursor is after the last diff - lnum2 = lnum1 - baseline; + return lnum1 - baseline; +} + +/// Finds the corresponding line in a diff. +/// +/// @param buf1 +/// @param lnum1 +/// +/// @return The corresponding line. +linenr_T diff_get_corresponding_line(buf_T *buf1, linenr_T lnum1) +{ + linenr_T lnum = diff_get_corresponding_line_int(buf1, lnum1); // don't end up past the end of the file - if (lnum2 > buf2->b_ml.ml_line_count) { - lnum2 = buf2->b_ml.ml_line_count; + if (lnum > curbuf->b_ml.ml_line_count) { + return curbuf->b_ml.ml_line_count; } - - return lnum2; + return lnum; } /// For line "lnum" in the current window find the equivalent lnum in window diff --git a/src/nvim/diff.h b/src/nvim/diff.h index f6cef1cafd..3624ce29bb 100644 --- a/src/nvim/diff.h +++ b/src/nvim/diff.h @@ -1,6 +1,9 @@ #ifndef NVIM_DIFF_H #define NVIM_DIFF_H +#include "nvim/pos.h" +#include "nvim/ex_cmds_defs.h" + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "diff.h.generated.h" #endif diff --git a/src/nvim/digraph.c b/src/nvim/digraph.c index 6ba6e659a6..bfb1b94738 100644 --- a/src/nvim/digraph.c +++ b/src/nvim/digraph.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + /// @file digraph.c /// /// code for digraphs @@ -790,6 +793,7 @@ static digr_T digraphdefault[] = { '/', '-', 0x2020 }, { '/', '=', 0x2021 }, { '.', '.', 0x2025 }, + { ',', '.', 0x2026 }, { '%', '0', 0x2030 }, { '1', '\'', 0x2032 }, { '2', '\'', 0x2033 }, @@ -1448,10 +1452,8 @@ int get_digraph(int cmdline) { int cc; no_mapping++; - allow_keys++; int c = plain_vgetc(); no_mapping--; - allow_keys--; if (c != ESC) { // ESC cancels CTRL-K @@ -1468,10 +1470,8 @@ int get_digraph(int cmdline) add_to_showcmd(c); } no_mapping++; - allow_keys++; cc = plain_vgetc(); no_mapping--; - allow_keys--; if (cc != ESC) { // ESC cancels CTRL-K @@ -1573,7 +1573,8 @@ int getdigraph(int char1, int char2, int meta_char) if (((retval = getexactdigraph(char1, char2, meta_char)) == char2) && (char1 != char2) - && ((retval = getexactdigraph(char2, char1, meta_char)) == char1)) { + && ((retval = getexactdigraph(char2, char1, meta_char)) // -V764 + == char1)) { return char2; } return retval; @@ -1679,11 +1680,7 @@ static void printdigraph(digr_T *dp) int list_width; - if ((dy_flags & DY_UHEX) || has_mbyte) { - list_width = 13; - } else { - list_width = 11; - } + list_width = 13; if (dp->result != 0) { if (msg_col > Columns - list_width) { @@ -1704,15 +1701,11 @@ static void printdigraph(digr_T *dp) *p++ = dp->char2; *p++ = ' '; - if (has_mbyte) { - // add a space to draw a composing char on - if (enc_utf8 && utf_iscomposing(dp->result)) { - *p++ = ' '; - } - p += (*mb_char2bytes)(dp->result, p); - } else { - *p++ = (char_u)dp->result; + // add a space to draw a composing char on + if (utf_iscomposing(dp->result)) { + *p++ = ' '; } + p += (*mb_char2bytes)(dp->result, p); if (char2cells(dp->result) == 1) { *p++ = ' '; diff --git a/src/nvim/digraph.h b/src/nvim/digraph.h index b623969e08..1b73ccaf3f 100644 --- a/src/nvim/digraph.h +++ b/src/nvim/digraph.h @@ -1,6 +1,9 @@ #ifndef NVIM_DIGRAPH_H #define NVIM_DIGRAPH_H +#include "nvim/types.h" +#include "nvim/ex_cmds_defs.h" + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "digraph.h.generated.h" #endif diff --git a/src/nvim/edit.c b/src/nvim/edit.c index bb946337b5..17f0b8ef82 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + /* * edit.c: functions for Insert mode */ @@ -15,6 +18,7 @@ #include "nvim/cursor.h" #include "nvim/digraph.h" #include "nvim/eval.h" +#include "nvim/eval/typval.h" #include "nvim/ex_docmd.h" #include "nvim/ex_getln.h" #include "nvim/farsi.h" @@ -458,7 +462,7 @@ static void insert_enter(InsertState *s) // Always update o_lnum, so that a "CTRL-O ." that adds a line // still puts the cursor back after the inserted text. - if (ins_at_eol && gchar_cursor() == NUL) { + if (ins_at_eol) { o_lnum = curwin->w_cursor.lnum; } @@ -689,11 +693,9 @@ static int insert_execute(VimState *state, int key) if (s->c == Ctrl_BSL) { // may need to redraw when no more chars available now ins_redraw(false); - ++no_mapping; - ++allow_keys; + no_mapping++; s->c = plain_vgetc(); - --no_mapping; - --allow_keys; + no_mapping--; if (s->c != Ctrl_N && s->c != Ctrl_G && s->c != Ctrl_O) { // it's something else vungetc(s->c); @@ -800,9 +802,9 @@ static int insert_handle_key(InsertState *s) if (!p_im) { goto normalchar; // insert CTRL-Z as normal char } - stuffReadbuff((char_u *)":st\r"); - s->c = Ctrl_O; - // FALLTHROUGH + do_cmdline_cmd("stop"); + ui_cursor_shape(); // may need to update cursor shape + break; case Ctrl_O: // execute one command if (ctrl_x_mode == CTRL_X_OMNI) { @@ -844,6 +846,11 @@ static int insert_handle_key(InsertState *s) return 0; // exit insert mode + case ' ': + if (mod_mask != 4) { + goto normalchar; + } + // FALLTHROUGH case K_ZERO: // Insert the previously inserted text. case NUL: case Ctrl_A: @@ -1419,7 +1426,7 @@ static void ins_ctrl_v(void) edit_putchar('^', TRUE); did_putchar = TRUE; } - AppendToRedobuff((char_u *)CTRL_V_STR); /* CTRL-V */ + AppendToRedobuff(CTRL_V_STR); add_to_showcmd_c(Ctrl_V); @@ -1859,8 +1866,9 @@ static bool check_compl_option(bool dict_opt) : (*curbuf->b_p_tsr == NUL && *p_tsr == NUL)) { ctrl_x_mode = 0; edit_submode = NULL; - msg_attr(dict_opt ? (char_u *)_("'dictionary' option is empty") - : (char_u *)_("'thesaurus' option is empty"), hl_attr(HLF_E)); + msg_attr((dict_opt + ? _("'dictionary' option is empty") + : _("'thesaurus' option is empty")), hl_attr(HLF_E)); if (emsg_silent == 0) { vim_beep(BO_COMPL); setcursor(); @@ -1972,7 +1980,6 @@ static bool ins_compl_accept_char(int c) */ int ins_compl_add_infercase(char_u *str, int len, int icase, char_u *fname, int dir, int flags) { - char_u *p; int i, c; int actual_len; /* Take multi-byte characters */ int actual_compl_length; /* into account. */ @@ -1982,11 +1989,11 @@ int ins_compl_add_infercase(char_u *str, int len, int icase, char_u *fname, int int was_letter = FALSE; if (p_ic && curbuf->b_p_inf && len > 0) { - /* Infer case of completed part. */ + // Infer case of completed part. - /* Find actual length of completion. */ + // Find actual length of completion. if (has_mbyte) { - p = str; + const char_u *p = str; actual_len = 0; while (*p != NUL) { mb_ptr_adv(p); @@ -1997,7 +2004,7 @@ int ins_compl_add_infercase(char_u *str, int len, int icase, char_u *fname, int /* Find actual length of original text. */ if (has_mbyte) { - p = compl_orig_text; + const char_u *p = compl_orig_text; actual_compl_length = 0; while (*p != NUL) { mb_ptr_adv(p); @@ -2013,27 +2020,35 @@ int ins_compl_add_infercase(char_u *str, int len, int icase, char_u *fname, int /* Allocate wide character array for the completion and fill it. */ wca = xmalloc(actual_len * sizeof(*wca)); - p = str; - for (i = 0; i < actual_len; ++i) - if (has_mbyte) - wca[i] = mb_ptr2char_adv(&p); - else - wca[i] = *(p++); + { + const char_u *p = str; + for (i = 0; i < actual_len; i++) { + if (has_mbyte) { + wca[i] = mb_ptr2char_adv(&p); + } else { + wca[i] = *(p++); + } + } + } - /* Rule 1: Were any chars converted to lower? */ - p = compl_orig_text; - for (i = 0; i < min_len; ++i) { - if (has_mbyte) - c = mb_ptr2char_adv(&p); - else - c = *(p++); - if (vim_islower(c)) { - has_lower = TRUE; - if (vim_isupper(wca[i])) { - /* Rule 1 is satisfied. */ - for (i = actual_compl_length; i < actual_len; ++i) - wca[i] = vim_tolower(wca[i]); - break; + // Rule 1: Were any chars converted to lower? + { + const char_u *p = compl_orig_text; + for (i = 0; i < min_len; i++) { + if (has_mbyte) { + c = mb_ptr2char_adv(&p); + } else { + c = *(p++); + } + if (mb_islower(c)) { + has_lower = true; + if (mb_isupper(wca[i])) { + // Rule 1 is satisfied. + for (i = actual_compl_length; i < actual_len; i++) { + wca[i] = mb_tolower(wca[i]); + } + break; + } } } } @@ -2043,84 +2058,110 @@ int ins_compl_add_infercase(char_u *str, int len, int icase, char_u *fname, int * upper case. */ if (!has_lower) { - p = compl_orig_text; - for (i = 0; i < min_len; ++i) { - if (has_mbyte) + const char_u *p = compl_orig_text; + for (i = 0; i < min_len; i++) { + if (has_mbyte) { c = mb_ptr2char_adv(&p); - else + } else { c = *(p++); - if (was_letter && vim_isupper(c) && vim_islower(wca[i])) { - /* Rule 2 is satisfied. */ - for (i = actual_compl_length; i < actual_len; ++i) - wca[i] = vim_toupper(wca[i]); + } + if (was_letter && mb_isupper(c) && mb_islower(wca[i])) { + // Rule 2 is satisfied. + for (i = actual_compl_length; i < actual_len; i++) { + wca[i] = mb_toupper(wca[i]); + } break; } - was_letter = vim_islower(c) || vim_isupper(c); + was_letter = mb_islower(c) || mb_isupper(c); } } - /* Copy the original case of the part we typed. */ - p = compl_orig_text; - for (i = 0; i < min_len; ++i) { - if (has_mbyte) - c = mb_ptr2char_adv(&p); - else - c = *(p++); - if (vim_islower(c)) - wca[i] = vim_tolower(wca[i]); - else if (vim_isupper(c)) - wca[i] = vim_toupper(wca[i]); + // Copy the original case of the part we typed. + { + const char_u *p = compl_orig_text; + for (i = 0; i < min_len; i++) { + if (has_mbyte) { + c = mb_ptr2char_adv(&p); + } else { + c = *(p++); + } + if (mb_islower(c)) { + wca[i] = mb_tolower(wca[i]); + } else if (mb_isupper(c)) { + wca[i] = mb_toupper(wca[i]); + } + } } - /* - * Generate encoding specific output from wide character array. - * Multi-byte characters can occupy up to five bytes more than - * ASCII characters, and we also need one byte for NUL, so stay - * six bytes away from the edge of IObuff. - */ - p = IObuff; - i = 0; - while (i < actual_len && (p - IObuff + 6) < IOSIZE) - if (has_mbyte) - p += (*mb_char2bytes)(wca[i++], p); - else - *(p++) = wca[i++]; - *p = NUL; + // Generate encoding specific output from wide character array. + // Multi-byte characters can occupy up to five bytes more than + // ASCII characters, and we also need one byte for NUL, so stay + // six bytes away from the edge of IObuff. + { + char_u *p = IObuff; + i = 0; + while (i < actual_len && (p - IObuff + 6) < IOSIZE) { + if (has_mbyte) { + p += (*mb_char2bytes)(wca[i++], p); + } else { + *(p++) = wca[i++]; + } + } + *p = NUL; + } xfree(wca); - return ins_compl_add(IObuff, len, icase, fname, NULL, dir, - flags, FALSE); + return ins_compl_add(IObuff, len, icase, fname, NULL, false, dir, flags, + false); } - return ins_compl_add(str, len, icase, fname, NULL, dir, flags, FALSE); + return ins_compl_add(str, len, icase, fname, NULL, false, dir, flags, false); } -/* - * Add a match to the list of matches. - * If the given string is already in the list of completions, then return - * NOTDONE, otherwise add it to the list and return OK. If there is an error - * then FAIL is returned. - */ -static int -ins_compl_add ( - char_u *str, - int len, - int icase, - char_u *fname, - char_u **cptext, /* extra text for popup menu or NULL */ - int cdir, - int flags, - int adup /* accept duplicate match */ -) +/// Add a match to the list of matches +/// +/// @param[in] str Match to add. +/// @param[in] len Match length, -1 to use #STRLEN. +/// @param[in] icase Whether case is to be ignored. +/// @param[in] fname File name match comes from. May be NULL. +/// @param[in] cptext Extra text for popup menu. May be NULL. If not NULL, +/// must have exactly #CPT_COUNT items. +/// @param[in] cptext_allocated If true, will not copy cptext strings. +/// +/// @note Will free strings in case of error. +/// cptext itself will not be freed. +/// @param[in] cdir Completion direction. +/// @param[in] adup True if duplicate matches are to be accepted. +/// +/// @return NOTDONE if the given string is already in the list of completions, +/// otherwise it is added to the list and OK is returned. FAIL will be +/// returned in case of error. +static int ins_compl_add(char_u *const str, int len, + const bool icase, char_u *const fname, + char_u *const *const cptext, + const bool cptext_allocated, + const Direction cdir, int flags, const bool adup) + FUNC_ATTR_NONNULL_ARG(1) { compl_T *match; - int dir = (cdir == 0 ? compl_direction : cdir); + int dir = (cdir == kDirectionNotSet ? compl_direction : cdir); os_breakcheck(); - if (got_int) +#define FREE_CPTEXT(cptext, cptext_allocated) \ + do { \ + if (cptext != NULL && cptext_allocated) { \ + for (size_t i = 0; i < CPT_COUNT; i++) { \ + xfree(cptext[i]); \ + } \ + } \ + } while (0) + if (got_int) { + FREE_CPTEXT(cptext, cptext_allocated); return FAIL; - if (len < 0) + } + if (len < 0) { len = (int)STRLEN(str); + } /* * If the same match is already present, don't add it. @@ -2128,10 +2169,12 @@ ins_compl_add ( if (compl_first_match != NULL && !adup) { match = compl_first_match; do { - if ( !(match->cp_flags & ORIGINAL_TEXT) - && STRNCMP(match->cp_str, str, len) == 0 - && match->cp_str[len] == NUL) + if (!(match->cp_flags & ORIGINAL_TEXT) + && STRNCMP(match->cp_str, str, len) == 0 + && match->cp_str[len] == NUL) { + FREE_CPTEXT(cptext, cptext_allocated); return NOTDONE; + } match = match->cp_next; } while (match != NULL && match != compl_first_match); } @@ -2162,16 +2205,26 @@ ins_compl_add ( else if (fname != NULL) { match->cp_fname = vim_strsave(fname); flags |= FREE_FNAME; - } else + } else { match->cp_fname = NULL; + } match->cp_flags = flags; if (cptext != NULL) { int i; - for (i = 0; i < CPT_COUNT; ++i) - if (cptext[i] != NULL && *cptext[i] != NUL) - match->cp_text[i] = vim_strsave(cptext[i]); + for (i = 0; i < CPT_COUNT; i++) { + if (cptext[i] == NULL) { + continue; + } + if (*cptext[i] != NUL) { + match->cp_text[i] = (cptext_allocated + ? cptext[i] + : (char_u *)xstrdup((char *)cptext[i])); + } else if (cptext_allocated) { + xfree(cptext[i]); + } + } } /* @@ -2252,9 +2305,10 @@ static void ins_compl_longest_match(compl_T *match) c1 = *p; c2 = *s; } - if (match->cp_icase ? (vim_tolower(c1) != vim_tolower(c2)) - : (c1 != c2)) + if (match->cp_icase ? (mb_tolower(c1) != mb_tolower(c2)) + : (c1 != c2)) { break; + } if (has_mbyte) { mb_ptr_adv(p); mb_ptr_adv(s); @@ -2294,9 +2348,10 @@ static void ins_compl_add_matches(int num_matches, char_u **matches, int icase) for (i = 0; i < num_matches && add_r != FAIL; i++) if ((add_r = ins_compl_add(matches[i], -1, icase, - NULL, NULL, dir, 0, FALSE)) == OK) - /* if dir was BACKWARD then honor it just once */ + NULL, NULL, false, dir, 0, false)) == OK) { + // If dir was BACKWARD then honor it just once. dir = FORWARD; + } FreeWild(num_matches, matches); } @@ -2351,6 +2406,7 @@ void set_completion(colnr_T startcol, list_T *list) ins_compl_prep(' '); } ins_compl_clear(); + ins_compl_free(); compl_direction = FORWARD; if (startcol > curwin->w_cursor.col) @@ -2360,8 +2416,8 @@ void set_completion(colnr_T startcol, list_T *list) /* compl_pattern doesn't need to be set */ compl_orig_text = vim_strnsave(get_cursor_line_ptr() + compl_col, compl_length); - if (ins_compl_add(compl_orig_text, -1, p_ic, NULL, NULL, 0, - ORIGINAL_TEXT, FALSE) != OK) { + if (ins_compl_add(compl_orig_text, -1, p_ic, NULL, NULL, false, 0, + ORIGINAL_TEXT, false) != OK) { return; } @@ -2373,6 +2429,7 @@ void set_completion(colnr_T startcol, list_T *list) compl_used_match = TRUE; compl_cont_status = 0; int save_w_wrow = curwin->w_wrow; + int save_w_leftcol = curwin->w_leftcol; compl_curr_match = compl_first_match; if (compl_no_insert || compl_no_select) { @@ -2387,7 +2444,7 @@ void set_completion(colnr_T startcol, list_T *list) // Lazily show the popup menu, unless we got interrupted. if (!compl_interrupted) { - show_pum(save_w_wrow); + show_pum(save_w_wrow, save_w_leftcol); } ui_flush(); @@ -2882,7 +2939,7 @@ static void ins_compl_clear(void) compl_orig_text = NULL; compl_enter_selects = FALSE; // clear v:completed_item - set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc()); + set_vim_var_dict(VV_COMPLETED_ITEM, tv_dict_alloc()); } /// Check that Insert completion is active. @@ -2907,11 +2964,14 @@ static int ins_compl_bs(void) p = line + curwin->w_cursor.col; mb_ptr_back(line, p); - /* Stop completion when the whole word was deleted. For Omni completion - * allow the word to be deleted, we won't match everything. */ + // Stop completion when the whole word was deleted. For Omni completion + // allow the word to be deleted, we won't match everything. + // Respect the 'backspace' option. if ((int)(p - line) - (int)compl_col < 0 || ((int)(p - line) - (int)compl_col == 0 - && ctrl_x_mode != CTRL_X_OMNI) || ctrl_x_mode == CTRL_X_EVAL) { + && ctrl_x_mode != CTRL_X_OMNI) || ctrl_x_mode == CTRL_X_EVAL + || (!can_bs(BS_START) && (int)(p - line) - (int)compl_col + - compl_length < 0)) { return K_BS; } @@ -3000,6 +3060,9 @@ static void ins_compl_addleader(int c) { int cc; + if (stop_arrow() == FAIL) { + return; + } if (has_mbyte && (cc = (*mb_char2len)(c)) > 1) { char_u buf[MB_MAXBYTES + 1]; @@ -3368,10 +3431,10 @@ static void ins_compl_fixRedoBufForLeader(char_u *ptr_arg) len -= (*mb_head_off)(p, p + len); for (p += len; *p != NUL; mb_ptr_adv(p)) AppendCharToRedobuff(K_BS); - } else + } else { len = 0; - if (ptr != NULL) - AppendToRedobuffLit(ptr + len, -1); + } + AppendToRedobuffLit(ptr + len, -1); } /* @@ -3421,7 +3484,6 @@ expand_by_function ( { list_T *matchlist = NULL; dict_T *matchdict = NULL; - char_u *args[2]; char_u *funcname; pos_T pos; win_T *curwin_save; @@ -3432,9 +3494,8 @@ expand_by_function ( if (*funcname == NUL) return; - /* Call 'completefunc' to obtain the list of matches. */ - args[0] = (char_u *)"0"; - args[1] = base; + // Call 'completefunc' to obtain the list of matches. + const char_u *const args[2] = { (char_u *)"0", base }; pos = curwin->w_cursor; curwin_save = curwin; @@ -3450,8 +3511,8 @@ expand_by_function ( matchdict = rettv.vval.v_dict; break; default: - /* TODO: Give error message? */ - clear_tv(&rettv); + // TODO(brammool): Give error message? + tv_clear(&rettv); break; } } @@ -3473,10 +3534,12 @@ expand_by_function ( ins_compl_add_dict(matchdict); theend: - if (matchdict != NULL) - dict_unref(matchdict); - if (matchlist != NULL) - list_unref(matchlist); + if (matchdict != NULL) { + tv_dict_unref(matchdict); + } + if (matchlist != NULL) { + tv_list_unref(matchlist); + } } /* @@ -3505,53 +3568,60 @@ static void ins_compl_add_dict(dict_T *dict) dictitem_T *di_refresh; dictitem_T *di_words; - /* Check for optional "refresh" item. */ - compl_opt_refresh_always = FALSE; - di_refresh = dict_find(dict, (char_u *)"refresh", 7); + // Check for optional "refresh" item. + compl_opt_refresh_always = false; + di_refresh = tv_dict_find(dict, S_LEN("refresh")); if (di_refresh != NULL && di_refresh->di_tv.v_type == VAR_STRING) { - char_u *v = di_refresh->di_tv.vval.v_string; + const char *v = (const char *)di_refresh->di_tv.vval.v_string; - if (v != NULL && STRCMP(v, (char_u *)"always") == 0) - compl_opt_refresh_always = TRUE; + if (v != NULL && strcmp(v, "always") == 0) { + compl_opt_refresh_always = true; + } } - /* Add completions from a "words" list. */ - di_words = dict_find(dict, (char_u *)"words", 5); - if (di_words != NULL && di_words->di_tv.v_type == VAR_LIST) + // Add completions from a "words" list. + di_words = tv_dict_find(dict, S_LEN("words")); + if (di_words != NULL && di_words->di_tv.v_type == VAR_LIST) { ins_compl_add_list(di_words->di_tv.vval.v_list); + } } -/* - * Add a match to the list of matches from a typeval_T. - * If the given string is already in the list of completions, then return - * NOTDONE, otherwise add it to the list and return OK. If there is an error - * then FAIL is returned. - */ -int ins_compl_add_tv(typval_T *tv, int dir) -{ - char_u *word; - int icase = FALSE; - int adup = FALSE; - int aempty = FALSE; - char_u *(cptext[CPT_COUNT]); +/// Add a match to the list of matches from VimL object +/// +/// @param[in] tv Object to get matches from. +/// @param[in] dir Completion direction. +/// +/// @return NOTDONE if the given string is already in the list of completions, +/// otherwise it is added to the list and OK is returned. FAIL will be +/// returned in case of error. +int ins_compl_add_tv(typval_T *const tv, const Direction dir) + FUNC_ATTR_NONNULL_ALL +{ + const char *word; + bool icase = false; + bool adup = false; + bool aempty = false; + char *(cptext[CPT_COUNT]); if (tv->v_type == VAR_DICT && tv->vval.v_dict != NULL) { - word = get_dict_string(tv->vval.v_dict, "word", false); - cptext[CPT_ABBR] = get_dict_string(tv->vval.v_dict, "abbr", false); - cptext[CPT_MENU] = get_dict_string(tv->vval.v_dict, "menu", false); - cptext[CPT_KIND] = get_dict_string(tv->vval.v_dict, "kind", false); - cptext[CPT_INFO] = get_dict_string(tv->vval.v_dict, "info", false); - - icase = get_dict_number(tv->vval.v_dict, "icase"); - adup = get_dict_number(tv->vval.v_dict, "dup"); - aempty = get_dict_number(tv->vval.v_dict, "empty"); + word = tv_dict_get_string(tv->vval.v_dict, "word", false); + cptext[CPT_ABBR] = tv_dict_get_string(tv->vval.v_dict, "abbr", true); + cptext[CPT_MENU] = tv_dict_get_string(tv->vval.v_dict, "menu", true); + cptext[CPT_KIND] = tv_dict_get_string(tv->vval.v_dict, "kind", true); + cptext[CPT_INFO] = tv_dict_get_string(tv->vval.v_dict, "info", true); + + icase = (bool)tv_dict_get_number(tv->vval.v_dict, "icase"); + adup = (bool)tv_dict_get_number(tv->vval.v_dict, "dup"); + aempty = (bool)tv_dict_get_number(tv->vval.v_dict, "empty"); } else { - word = get_tv_string_chk(tv); + word = (const char *)tv_get_string_chk(tv); memset(cptext, 0, sizeof(cptext)); } - if (word == NULL || (!aempty && *word == NUL)) + if (word == NULL || (!aempty && *word == NUL)) { return FAIL; - return ins_compl_add(word, -1, icase, NULL, cptext, dir, 0, adup); + } + return ins_compl_add((char_u *)word, -1, icase, NULL, + (char_u **)cptext, true, dir, 0, adup); } /* @@ -3847,13 +3917,11 @@ static int ins_compl_get_exp(pos_T *ini) if ((compl_cont_status & CONT_ADDING) && len == compl_length) { if (pos->lnum < ins_buf->b_ml.ml_line_count) { - /* Try next line, if any. the new word will be - * "join" as if the normal command "J" was used. - * IOSIZE is always greater than - * compl_length, so the next STRNCPY always - * works -- Acevedo */ + // Try next line, if any. the new word will be "join" as if the + // normal command "J" was used. IOSIZE is always greater than + // compl_length, so the next STRNCPY always works -- Acevedo STRNCPY(IObuff, ptr, len); - ptr = ml_get_buf(ins_buf, pos->lnum + 1, FALSE); + ptr = ml_get_buf(ins_buf, pos->lnum + 1, false); tmp_ptr = ptr = skipwhite(ptr); /* Find start of next word. */ tmp_ptr = find_word_start(tmp_ptr); @@ -3968,7 +4036,7 @@ static void ins_compl_delete(void) // causes flicker, thus we can't do that. changed_cline_bef_curs(); // clear v:completed_item - set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc()); + set_vim_var_dict(VV_COMPLETED_ITEM, tv_dict_alloc()); } // Insert the new text being completed. @@ -3983,17 +4051,21 @@ static void ins_compl_insert(int in_compl_func) // Set completed item. // { word, abbr, menu, kind, info } - dict_T *dict = dict_alloc(); - dict_add_nr_str(dict, "word", 0L, - EMPTY_IF_NULL(compl_shown_match->cp_str)); - dict_add_nr_str(dict, "abbr", 0L, - EMPTY_IF_NULL(compl_shown_match->cp_text[CPT_ABBR])); - dict_add_nr_str(dict, "menu", 0L, - EMPTY_IF_NULL(compl_shown_match->cp_text[CPT_MENU])); - dict_add_nr_str(dict, "kind", 0L, - EMPTY_IF_NULL(compl_shown_match->cp_text[CPT_KIND])); - dict_add_nr_str(dict, "info", 0L, - EMPTY_IF_NULL(compl_shown_match->cp_text[CPT_INFO])); + dict_T *dict = tv_dict_alloc(); + tv_dict_add_str(dict, S_LEN("word"), + (const char *)EMPTY_IF_NULL(compl_shown_match->cp_str)); + tv_dict_add_str( + dict, S_LEN("abbr"), + (const char *)EMPTY_IF_NULL(compl_shown_match->cp_text[CPT_ABBR])); + tv_dict_add_str( + dict, S_LEN("menu"), + (const char *)EMPTY_IF_NULL(compl_shown_match->cp_text[CPT_MENU])); + tv_dict_add_str( + dict, S_LEN("kind"), + (const char *)EMPTY_IF_NULL(compl_shown_match->cp_text[CPT_KIND])); + tv_dict_add_str( + dict, S_LEN("info"), + (const char *)EMPTY_IF_NULL(compl_shown_match->cp_text[CPT_INFO])); set_vim_var_dict(VV_COMPLETED_ITEM, dict); if (!in_compl_func) { compl_curr_match = compl_shown_match; @@ -4331,7 +4403,9 @@ static int ins_complete(int c, bool enable_pum) colnr_T curs_col; /* cursor column */ int n; int save_w_wrow; + int save_w_leftcol; int insert_match; + int save_did_ai = did_ai; compl_direction = ins_compl_key2dir(c); insert_match = ins_compl_use_match(c); @@ -4533,7 +4607,6 @@ static int ins_complete(int c, bool enable_pum) * Call user defined function 'completefunc' with "a:findstart" * set to 1 to obtain the length of text to use for completion. */ - char_u *args[2]; int col; char_u *funcname; pos_T pos; @@ -4547,11 +4620,12 @@ static int ins_complete(int c, bool enable_pum) if (*funcname == NUL) { EMSG2(_(e_notset), ctrl_x_mode == CTRL_X_FUNCTION ? "completefunc" : "omnifunc"); + // restore did_ai, so that adding comment leader works + did_ai = save_did_ai; return FAIL; } - args[0] = (char_u *)"1"; - args[1] = NULL; + const char_u *const args[2] = { (char_u *)"1", NULL }; pos = curwin->w_cursor; curwin_save = curwin; curbuf_save = curbuf; @@ -4651,8 +4725,8 @@ static int ins_complete(int c, bool enable_pum) /* Always add completion for the original text. */ xfree(compl_orig_text); compl_orig_text = vim_strnsave(line + compl_col, compl_length); - if (ins_compl_add(compl_orig_text, -1, p_ic, NULL, NULL, 0, - ORIGINAL_TEXT, FALSE) != OK) { + if (ins_compl_add(compl_orig_text, -1, p_ic, NULL, NULL, false, 0, + ORIGINAL_TEXT, false) != OK) { xfree(compl_pattern); compl_pattern = NULL; xfree(compl_orig_text); @@ -4680,6 +4754,7 @@ static int ins_complete(int c, bool enable_pum) * Find next match (and following matches). */ save_w_wrow = curwin->w_wrow; + save_w_leftcol = curwin->w_leftcol; n = ins_compl_next(true, ins_compl_key2count(c), insert_match, false); /* may undisplay the popup menu */ @@ -4803,9 +4878,9 @@ static int ins_complete(int c, bool enable_pum) if (!shortmess(SHM_COMPLETIONMENU)) { if (edit_submode_extra != NULL) { if (!p_smd) { - msg_attr(edit_submode_extra, - edit_submode_highl < HLF_COUNT - ? hl_attr(edit_submode_highl) : 0); + msg_attr((const char *)edit_submode_extra, + (edit_submode_highl < HLF_COUNT + ? hl_attr(edit_submode_highl) : 0)); } } else { msg_clr_cmdline(); // necessary for "noshowmode" @@ -4814,7 +4889,7 @@ static int ins_complete(int c, bool enable_pum) // Show the popup menu, unless we got interrupted. if (enable_pum && !compl_interrupted) { - show_pum(save_w_wrow); + show_pum(save_w_wrow, save_w_leftcol); } compl_was_interrupted = compl_interrupted; compl_interrupted = FALSE; @@ -4840,14 +4915,17 @@ static unsigned quote_meta(char_u *dest, char_u *src, int len) if (ctrl_x_mode == CTRL_X_DICTIONARY || ctrl_x_mode == CTRL_X_THESAURUS) break; + // fallthrough case '~': if (!p_magic) /* quote these only if magic is set */ break; + // fallthrough case '\\': if (ctrl_x_mode == CTRL_X_DICTIONARY || ctrl_x_mode == CTRL_X_THESAURUS) break; - case '^': /* currently it's not needed. */ + // fallthrough + case '^': // currently it's not needed. case '$': m++; if (dest != NULL) @@ -5730,15 +5808,16 @@ comp_textwidth ( */ static void redo_literal(int c) { - char_u buf[10]; + char buf[10]; - /* Only digits need special treatment. Translate them into a string of - * three digits. */ + // Only digits need special treatment. Translate them into a string of + // three digits. if (ascii_isdigit(c)) { - vim_snprintf((char *)buf, sizeof(buf), "%03d", c); + vim_snprintf(buf, sizeof(buf), "%03d", c); AppendToRedobuff(buf); - } else + } else { AppendCharToRedobuff(c); + } } // start_arrow() is called when an arrow key is used in insert mode. @@ -5767,8 +5846,8 @@ static void start_arrow_common(pos_T *end_insert_pos, bool end_change) { if (!arrow_used && end_change) { // something has been inserted AppendToRedobuff(ESC_STR); - stop_insert(end_insert_pos, FALSE, FALSE); - arrow_used = TRUE; /* this means we stopped the current insert */ + stop_insert(end_insert_pos, false, false); + arrow_used = true; // This means we stopped the current insert. } check_spell_redraw(); } @@ -5825,7 +5904,7 @@ int stop_arrow(void) vr_lines_changed = 1; } ResetRedobuff(); - AppendToRedobuff((char_u *)"1i"); /* pretend we start an insertion */ + AppendToRedobuff("1i"); // Pretend we start an insertion. new_insert_skip = 2; } else if (ins_need_undo) { if (u_save_cursor() == OK) @@ -6290,12 +6369,13 @@ stuff_inserted ( } do { - stuffReadbuff(ptr); - /* a trailing "0" is inserted as "<C-V>048", "^" as "<C-V>^" */ - if (last) - stuffReadbuff((char_u *)(last == '0' - ? "\026\060\064\070" - : "\026^")); + stuffReadbuff((const char *)ptr); + // A trailing "0" is inserted as "<C-V>048", "^" as "<C-V>^". + if (last) { + stuffReadbuff((last == '0' + ? "\026\060\064\070" + : "\026^")); + } } while (--count > 0); if (last) @@ -7052,8 +7132,8 @@ static void ins_ctrl_g(void) */ static void ins_ctrl_hat(void) { - if (map_to_exists_mode((char_u *)"", LANGMAP, FALSE)) { - /* ":lmap" mappings exists, Toggle use of ":lmap" mappings. */ + if (map_to_exists_mode("", LANGMAP, false)) { + // ":lmap" mappings exists, Toggle use of ":lmap" mappings. if (State & LANGMAP) { curbuf->b_p_iminsert = B_IMODE_NONE; State &= ~LANGMAP; @@ -7088,13 +7168,12 @@ static bool ins_esc(long *count, int cmdchar, bool nomove) disabled_redraw = false; } if (!arrow_used) { - /* - * Don't append the ESC for "r<CR>" and "grx". - * When 'insertmode' is set only CTRL-L stops Insert mode. Needed for - * when "count" is non-zero. - */ - if (cmdchar != 'r' && cmdchar != 'v') - AppendToRedobuff(p_im ? (char_u *)"\014" : ESC_STR); + // Don't append the ESC for "r<CR>" and "grx". + // When 'insertmode' is set only CTRL-L stops Insert mode. Needed for + // when "count" is non-zero. + if (cmdchar != 'r' && cmdchar != 'v') { + AppendToRedobuff(p_im ? "\014" : ESC_STR); + } /* * Repeating insert may take a long time. Check for @@ -7248,7 +7327,8 @@ static bool ins_start_select(int c) // Execute the key in (insert) Select mode. stuffcharReadbuff(Ctrl_O); if (mod_mask) { - char_u buf[4] = { K_SPECIAL, KS_MODIFIER, mod_mask, NUL }; + const char buf[] = { (char)K_SPECIAL, (char)KS_MODIFIER, + (char)(uint8_t)mod_mask, NUL }; stuffReadbuff(buf); } stuffcharReadbuff(c); @@ -8056,11 +8136,11 @@ static bool ins_tab(void) return true; } - did_ai = FALSE; - did_si = FALSE; - can_si = FALSE; - can_si_back = FALSE; - AppendToRedobuff((char_u *)"\t"); + did_ai = false; + did_si = false; + can_si = false; + can_si_back = false; + AppendToRedobuff("\t"); if (p_sta && ind) { // insert tab in indent, use "shiftwidth" temp = get_sw_value(curbuf); @@ -8287,17 +8367,16 @@ static int ins_digraph(void) } - /* don't map the digraph chars. This also prevents the - * mode message to be deleted when ESC is hit */ - ++no_mapping; - ++allow_keys; + // don't map the digraph chars. This also prevents the + // mode message to be deleted when ESC is hit + no_mapping++; c = plain_vgetc(); - --no_mapping; - --allow_keys; - if (did_putchar) - /* when the line fits in 'columns' the '?' is at the start of the next - * line and will not be removed by the redraw */ + no_mapping--; + if (did_putchar) { + // when the line fits in 'columns' the '?' is at the start of the next + // line and will not be removed by the redraw edit_unputchar(); + } if (IS_SPECIAL(c) || mod_mask) { /* special key */ clear_showcmd(); @@ -8317,18 +8396,17 @@ static int ins_digraph(void) } add_to_showcmd_c(c); } - ++no_mapping; - ++allow_keys; + no_mapping++; cc = plain_vgetc(); - --no_mapping; - --allow_keys; - if (did_putchar) - /* when the line fits in 'columns' the '?' is at the start of the - * next line and will not be removed by a redraw */ + no_mapping--; + if (did_putchar) { + // when the line fits in 'columns' the '?' is at the start of the + // next line and will not be removed by a redraw edit_unputchar(); + } if (cc != ESC) { - AppendToRedobuff((char_u *)CTRL_V_STR); - c = getdigraph(c, cc, TRUE); + AppendToRedobuff(CTRL_V_STR); + c = getdigraph(c, cc, true); clear_showcmd(); return c; } @@ -8390,12 +8468,13 @@ static int ins_ctrl_ey(int tc) if (c != NUL) { long tw_save; - /* The character must be taken literally, insert like it - * was typed after a CTRL-V, and pretend 'textwidth' - * wasn't set. Digits, 'o' and 'x' are special after a - * CTRL-V, don't use it for these. */ - if (c < 256 && !isalnum(c)) - AppendToRedobuff((char_u *)CTRL_V_STR); /* CTRL-V */ + // The character must be taken literally, insert like it + // was typed after a CTRL-V, and pretend 'textwidth' + // wasn't set. Digits, 'o' and 'x' are special after a + // CTRL-V, don't use it for these. + if (c < 256 && !isalnum(c)) { + AppendToRedobuff(CTRL_V_STR); + } tw_save = curbuf->b_p_tw; curbuf->b_p_tw = -1; insert_special(c, TRUE, FALSE); @@ -8542,15 +8621,16 @@ static char_u *do_insert_char_pre(int c) return res; } -static void show_pum(int save_w_wrow) +static void show_pum(int prev_w_wrow, int prev_w_leftcol) { // RedrawingDisabled may be set when invoked through complete(). int n = RedrawingDisabled; RedrawingDisabled = 0; - // If the cursor moved we need to remove the pum first. + // If the cursor moved or the display scrolled we need to remove the pum + // first. setcursor(); - if (save_w_wrow != curwin->w_wrow) { + if (prev_w_wrow != curwin->w_wrow || prev_w_leftcol != curwin->w_leftcol) { ins_compl_del_pum(); } diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 17e89e5757..d6ee13857a 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -1,8 +1,12 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + /* * eval.c: Expression evaluation. */ #include <assert.h> +#include <float.h> #include <inttypes.h> #include <stdarg.h> #include <string.h> @@ -30,6 +34,7 @@ #include "nvim/ex_eval.h" #include "nvim/ex_getln.h" #include "nvim/fileio.h" +#include "nvim/os/fileio.h" #include "nvim/func_attr.h" #include "nvim/fold.h" #include "nvim/getchar.h" @@ -42,6 +47,7 @@ #include "nvim/mbyte.h" #include "nvim/memline.h" #include "nvim/memory.h" +#include "nvim/menu.h" #include "nvim/message.h" #include "nvim/misc1.h" #include "nvim/keymap.h" @@ -93,7 +99,13 @@ #include "nvim/lib/kvec.h" #include "nvim/lib/khash.h" #include "nvim/lib/queue.h" -#include "nvim/eval/typval_encode.h" +#include "nvim/lua/executor.h" +#include "nvim/eval/typval.h" +#include "nvim/eval/executor.h" +#include "nvim/eval/gc.h" +#include "nvim/macros.h" + +// TODO(ZyX-I): Remove DICT_MAXNEST, make users be non-recursive instead #define DICT_MAXNEST 100 /* maximum nesting of lists and dicts */ @@ -131,31 +143,28 @@ * "newkey" is the key for the new item. */ typedef struct lval_S { - char_u *ll_name; /* start of variable name (can be NULL) */ - char_u *ll_exp_name; /* NULL or expanded name in allocated memory. */ - typval_T *ll_tv; /* Typeval of item being used. If "newkey" - isn't NULL it's the Dict to which to add - the item. */ - listitem_T *ll_li; /* The list item or NULL. */ - list_T *ll_list; /* The list or NULL. */ - int ll_range; /* TRUE when a [i:j] range was used */ - long ll_n1; /* First index for list */ - long ll_n2; /* Second index for list range */ - int ll_empty2; /* Second index is empty: [i:] */ - dict_T *ll_dict; /* The Dictionary or NULL */ - dictitem_T *ll_di; /* The dictitem or NULL */ - char_u *ll_newkey; /* New key for Dict in alloc. mem or NULL. */ + const char *ll_name; ///< Start of variable name (can be NULL). + size_t ll_name_len; ///< Length of the .ll_name. + char *ll_exp_name; ///< NULL or expanded name in allocated memory. + typval_T *ll_tv; ///< Typeval of item being used. If "newkey" + ///< isn't NULL it's the Dict to which to add the item. + listitem_T *ll_li; ///< The list item or NULL. + list_T *ll_list; ///< The list or NULL. + int ll_range; ///< TRUE when a [i:j] range was used. + long ll_n1; ///< First index for list. + long ll_n2; ///< Second index for list range. + int ll_empty2; ///< Second index is empty: [i:]. + dict_T *ll_dict; ///< The Dictionary or NULL. + dictitem_T *ll_di; ///< The dictitem or NULL. + char_u *ll_newkey; ///< New key for Dict in allocated memory or NULL. } lval_T; static char *e_letunexp = N_("E18: Unexpected characters in :let"); -static char *e_listidx = N_("E684: list index out of range: %" PRId64); -static char *e_undefvar = N_("E121: Undefined variable: %s"); static char *e_missbrac = N_("E111: Missing ']'"); static char *e_listarg = N_("E686: Argument of %s must be a List"); static char *e_listdictarg = N_( "E712: Argument of %s must be a List or Dictionary"); -static char *e_emptykey = N_("E713: Cannot use empty key for Dictionary"); static char *e_listreq = N_("E714: List required"); static char *e_dictreq = N_("E715: Dictionary required"); static char *e_stringreq = N_("E928: String required"); @@ -166,15 +175,20 @@ static char *e_funcexts = N_( static char *e_funcdict = N_("E717: Dictionary entry already exists"); static char *e_funcref = N_("E718: Funcref required"); static char *e_dictrange = N_("E719: Cannot use [:] with a Dictionary"); -static char *e_letwrong = N_("E734: Wrong variable type for %s="); static char *e_nofunc = N_("E130: Unknown function: %s"); static char *e_illvar = N_("E461: Illegal variable name: %s"); -static char *e_float_as_string = N_("E806: using Float as a String"); +static const char *e_readonlyvar = N_( + "E46: Cannot change read-only variable \"%.*s\""); + +// TODO(ZyX-I): move to eval/executor +static char *e_letwrong = N_("E734: Wrong variable type for %s="); -static char_u * const empty_string = (char_u *)""; static char_u * const namespace_char = (char_u *)"abglstvw"; -static dictitem_T globvars_var; /* variable used for g: */ +/// Variable used for g: +static ScopeDictDictItem globvars_var; + +/// g: value #define globvarht globvardict.dv_hashtab /* @@ -185,12 +199,15 @@ static hashtab_T compat_hashtab; hashtab_T func_hashtab; +// Used for checking if local variables or arguments used in a lambda. +static int *eval_lavars_used = NULL; + /* * Array to hold the hashtab with variables local to each sourced script. * Each item holds a variable (nameless) that points to the dict_T. */ typedef struct { - dictitem_T sv_var; + ScopeDictDictItem sv_var; dict_T sv_dict; } scriptvar_T; @@ -200,61 +217,72 @@ static garray_T ga_scripts = {0, 0, sizeof(scriptvar_T *), 4, NULL}; static int echo_attr = 0; /* attributes used for ":echo" */ -/* Values for trans_function_name() argument: */ -#define TFN_INT 1 /* internal function name OK */ -#define TFN_QUIET 2 /* no error messages */ -#define TFN_NO_AUTOLOAD 4 /* do not use script autoloading */ - -/* Values for get_lval() flags argument: */ -#define GLV_QUIET TFN_QUIET /* no error messages */ -#define GLV_NO_AUTOLOAD TFN_NO_AUTOLOAD /* do not use script autoloading */ - -/* 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" */ - -/* The names of packages that once were loaded are remembered. */ -static garray_T ga_loaded = {0, 0, sizeof(char_u *), 4, NULL}; - -// List heads for garbage collection. Although there can be a reference loop -// from partial to dict to partial, we don't need to keep track of the partial, -// since it will get freed when the dict is unused and gets freed. -static dict_T *first_dict = NULL; // list of all dicts -static list_T *first_list = NULL; // list of all lists +/// trans_function_name() flags +typedef enum { + TFN_INT = 1, ///< May use internal function name + TFN_QUIET = 2, ///< Do not emit error messages. + TFN_NO_AUTOLOAD = 4, ///< Do not use script autoloading. + TFN_NO_DEREF = 8, ///< Do not dereference a Funcref. + TFN_READ_ONLY = 16, ///< Will not change the variable. +} TransFunctionNameFlags; + +/// get_lval() flags +typedef enum { + GLV_QUIET = TFN_QUIET, ///< Do not emit error messages. + GLV_NO_AUTOLOAD = TFN_NO_AUTOLOAD, ///< Do not use script autoloading. + GLV_READ_ONLY = TFN_READ_ONLY, ///< Indicates that caller will not change + ///< the value (prevents error message). +} GetLvalFlags; + +// function flags +#define FC_ABORT 0x01 // abort function on error +#define FC_RANGE 0x02 // function accepts range +#define FC_DICT 0x04 // Dict function, uses "self" +#define FC_CLOSURE 0x08 // closure, uses outer scope variables +#define FC_DELETED 0x10 // :delfunction used while uf_refcount > 0 +#define FC_REMOVED 0x20 // function redefined while uf_refcount > 0 + +// The names of packages that once were loaded are remembered. +static garray_T ga_loaded = { 0, 0, sizeof(char_u *), 4, NULL }; #define FUNCARG(fp, j) ((char_u **)(fp->uf_args.ga_data))[j] #define FUNCLINE(fp, j) ((char_u **)(fp->uf_lines.ga_data))[j] -#define VAR_SHORT_LEN 20 /* short variable name length */ -#define FIXVAR_CNT 12 /* number of fixed variables */ - -/* structure to hold info for a function that is currently being executed. */ -typedef struct funccall_S funccall_T; +/// Short variable name length +#define VAR_SHORT_LEN 20 +/// Number of fixed variables used for arguments +#define FIXVAR_CNT 12 struct funccall_S { - ufunc_T *func; /* function being called */ - int linenr; /* next line to be executed */ - int returned; /* ":return" used */ - struct /* fixed variables for arguments */ - { - dictitem_T var; /* variable (without room for name) */ - char_u room[VAR_SHORT_LEN]; /* room for the name */ - } fixvar[FIXVAR_CNT]; - dict_T l_vars; /* l: local function variables */ - dictitem_T l_vars_var; /* variable for l: scope */ - dict_T l_avars; /* a: argument variables */ - dictitem_T l_avars_var; /* variable for a: scope */ - list_T l_varlist; /* list for a:000 */ - listitem_T l_listitems[MAX_FUNC_ARGS]; /* listitems for a:000 */ - typval_T *rettv; /* return value */ - linenr_T breakpoint; /* next line with breakpoint or zero */ - int dbg_tick; /* debug_tick when breakpoint was set */ - int level; /* top nesting level of executed function */ - proftime_T prof_child; /* time spent in a child */ - funccall_T *caller; /* calling function or NULL */ + ufunc_T *func; ///< Function being called. + int linenr; ///< Next line to be executed. + int returned; ///< ":return" used. + /// Fixed variables for arguments. + TV_DICTITEM_STRUCT(VAR_SHORT_LEN + 1) fixvar[FIXVAR_CNT]; + dict_T l_vars; ///< l: local function variables. + ScopeDictDictItem l_vars_var; ///< Variable for l: scope. + dict_T l_avars; ///< a: argument variables. + ScopeDictDictItem l_avars_var; ///< Variable for a: scope. + list_T l_varlist; ///< List for a:000. + listitem_T l_listitems[MAX_FUNC_ARGS]; ///< List items for a:000. + typval_T *rettv; ///< Return value. + linenr_T breakpoint; ///< Next line with breakpoint or zero. + int dbg_tick; ///< Debug_tick when breakpoint was set. + int level; ///< Top nesting level of executed function. + proftime_T prof_child; ///< Time spent in a child. + funccall_T *caller; ///< Calling function or NULL. + int fc_refcount; ///< Number of user functions that reference this funccall. + int fc_copyID; ///< CopyID used for garbage collection. + garray_T fc_funcs; ///< List of ufunc_T* which keep a reference to "func". }; +///< Structure used by trans_function_name() +typedef struct { + dict_T *fd_dict; ///< Dictionary used. + char_u *fd_newkey; ///< New key in "dict" in allocated memory. + dictitem_T *fd_di; ///< Dictionary item used. +} funcdict_T; + /* * Info used by a ":for" loop. */ @@ -266,15 +294,6 @@ typedef struct { } forinfo_T; /* - * Struct used by trans_function_name() - */ -typedef struct { - dict_T *fd_dict; /* Dictionary used */ - char_u *fd_newkey; /* new key in "dict" in allocated memory */ - dictitem_T *fd_di; /* Dictionary item used */ -} funcdict_T; - -/* * enum used by var_flavour() */ typedef enum { @@ -305,8 +324,8 @@ typedef enum { // variables with the VV_ defines. static struct vimvar { char *vv_name; ///< Name of the variable, without v:. - dictitem16_T vv_di; ///< Value and name for key (max 16 chars) - char vv_flags; ///< Flags: #VV_COMPAT, #VV_RO, #VV_RO_SBX. + TV_DICTITEM_STRUCT(17) vv_di; ///< Value and name for key (max 16 chars). + char vv_flags; ///< Flags: #VV_COMPAT, #VV_RO, #VV_RO_SBX. } vimvars[] = { // VV_ tails differing from upcased string literals: @@ -389,6 +408,7 @@ static struct vimvar { VV(VV__NULL_LIST, "_null_list", VAR_LIST, VV_RO), VV(VV__NULL_DICT, "_null_dict", VAR_DICT, VV_RO), VV(VV_VIM_DID_ENTER, "vim_did_enter", VAR_NUMBER, VV_RO), + VV(VV_TESTING, "testing", VAR_NUMBER, 0), VV(VV_TYPE_NUMBER, "t_number", VAR_NUMBER, VV_RO), VV(VV_TYPE_STRING, "t_string", VAR_NUMBER, VV_RO), VV(VV_TYPE_FUNC, "t_func", VAR_NUMBER, VV_RO), @@ -410,23 +430,11 @@ static struct vimvar { #define vv_dict vv_di.di_tv.vval.v_dict #define vv_tv vv_di.di_tv -static dictitem_T vimvars_var; // variable used for v: -#define vimvarht vimvardict.dv_hashtab +/// Variable used for v: +static ScopeDictDictItem vimvars_var; -typedef enum { - kCallbackNone, - kCallbackFuncref, - kCallbackPartial, -} CallbackType; - -typedef struct { - union { - char_u *funcref; - partial_T *partial; - } data; - CallbackType type; -} Callback; -#define CALLBACK_NONE ((Callback){ .type = kCallbackNone }) +/// v: hashtab +#define vimvarht vimvardict.dv_hashtab typedef struct { union { @@ -440,18 +448,11 @@ typedef struct { bool rpc; int refcount; Callback on_stdout, on_stderr, on_exit; - int *status_ptr; + varnumber_T *status_ptr; uint64_t id; MultiQueue *events; } TerminalJobData; -typedef struct dict_watcher { - Callback callback; - char *key_pattern; - QUEUE node; - bool busy; // prevent recursion if the dict is changed in the callback -} DictWatcher; - typedef struct { TerminalJobData *data; Callback *callback; @@ -467,6 +468,7 @@ typedef struct { int refcount; long timeout; bool stopped; + bool paused; Callback callback; } timer_T; @@ -486,6 +488,24 @@ typedef struct fst { KHASH_MAP_INIT_STR(functions, VimLFuncDef) +/// Type of assert_* check being performed +typedef enum +{ + ASSERT_EQUAL, + ASSERT_NOTEQUAL, + ASSERT_MATCH, + ASSERT_NOTMATCH, + ASSERT_INRANGE, + ASSERT_OTHER, +} assert_type_T; + +/// Type for dict_list function +typedef enum { + kDictListKeys, ///< List dictionary keys. + kDictListValues, ///< List dictionary values. + kDictListItems, ///< List dictionary contents: [keys, values]. +} DictListType; + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "eval.c.generated.h" #endif @@ -498,6 +518,14 @@ static PMap(uint64_t) *jobs = NULL; static uint64_t last_timer_id = 0; static PMap(uint64_t) *timers = NULL; +/// Dummy va_list for passing to vim_snprintf +/// +/// Used because: +/// - passing a NULL pointer doesn't work when va_list isn't a pointer +/// - locally in the function results in a "used before set" warning +/// - using va_start() to initialize it gives "function with fixed args" error +static va_list dummy_ap; + static const char *const msgpack_type_names[] = { [kMPNil] = "nil", [kMPBoolean] = "boolean", @@ -558,19 +586,19 @@ void eval_init(void) } vimvars[VV_VERSION].vv_nr = VIM_VERSION_100; - dict_T *const msgpack_types_dict = dict_alloc(); + dict_T *const msgpack_types_dict = tv_dict_alloc(); for (size_t i = 0; i < ARRAY_SIZE(msgpack_type_names); i++) { - list_T *const type_list = list_alloc(); + list_T *const type_list = tv_list_alloc(); type_list->lv_lock = VAR_FIXED; type_list->lv_refcount = 1; - dictitem_T *const di = dictitem_alloc((char_u *) msgpack_type_names[i]); - di->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX; + dictitem_T *const di = tv_dict_item_alloc(msgpack_type_names[i]); + di->di_flags |= DI_FLAGS_RO|DI_FLAGS_FIX; di->di_tv = (typval_T) { .v_type = VAR_LIST, .vval = { .v_list = type_list, }, }; eval_msgpack_type_lists[i] = type_list; - if (dict_add(msgpack_types_dict, di) == FAIL) { + if (tv_dict_add(msgpack_types_dict, di) == FAIL) { // There must not be duplicate items in this dictionary by definition. assert(false); } @@ -578,12 +606,12 @@ void eval_init(void) msgpack_types_dict->dv_lock = VAR_FIXED; set_vim_var_dict(VV_MSGPACK_TYPES, msgpack_types_dict); - set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc()); + set_vim_var_dict(VV_COMPLETED_ITEM, tv_dict_alloc()); - dict_T *v_event = dict_alloc(); + dict_T *v_event = tv_dict_alloc(); v_event->dv_lock = VAR_FIXED; set_vim_var_dict(VV_EVENT, v_event); - set_vim_var_list(VV_ERRORS, list_alloc()); + set_vim_var_list(VV_ERRORS, tv_list_alloc()); set_vim_var_nr(VV_SEARCHFORWARD, 1L); set_vim_var_nr(VV_HLSEARCH, 1L); set_vim_var_nr(VV_COUNT1, 1); @@ -614,7 +642,7 @@ void eval_clear(void) xfree(p->vv_str); p->vv_str = NULL; } else if (p->vv_di.di_tv.v_type == VAR_LIST) { - list_unref(p->vv_list); + tv_list_unref(p->vv_list); p->vv_list = NULL; } } @@ -640,12 +668,11 @@ void eval_clear(void) xfree(SCRIPT_SV(i)); ga_clear(&ga_scripts); - /* unreferenced lists and dicts */ - (void)garbage_collect(); + // unreferenced lists and dicts + (void)garbage_collect(false); - /* functions */ + // functions free_all_functions(); - hash_clear(&func_hashtab); } #endif @@ -703,18 +730,17 @@ int current_func_returned(void) */ void set_internal_string_var(char_u *name, char_u *value) { - char_u *val = vim_strsave(value); - typval_T *tvp = xcalloc(1, sizeof(typval_T)); + const typval_T tv = { + .v_type = VAR_STRING, + .vval.v_string = value, + }; - tvp->v_type = VAR_STRING; - tvp->vval.v_string = val; - set_var(name, tvp, FALSE); - free_tv(tvp); + set_var((const char *)name, STRLEN(name), (typval_T *)&tv, true); } static lval_T *redir_lval = NULL; -static garray_T redir_ga; /* only valid when redir_lval is not NULL */ -static char_u *redir_endp = NULL; +static garray_T redir_ga; // Only valid when redir_lval is not NULL. +static char_u *redir_endp = NULL; static char_u *redir_varname = NULL; /* @@ -745,11 +771,11 @@ var_redir_start ( /* The output is stored in growarray "redir_ga" until redirection ends. */ ga_init(&redir_ga, (int)sizeof(char), 500); - /* Parse the variable name (can be a dict or list entry). */ - redir_endp = get_lval(redir_varname, NULL, redir_lval, FALSE, FALSE, 0, - FNE_CHECK_START); - if (redir_endp == NULL || redir_lval->ll_name == NULL || *redir_endp != - NUL) { + // Parse the variable name (can be a dict or list entry). + redir_endp = (char_u *)get_lval(redir_varname, NULL, redir_lval, false, false, + 0, FNE_CHECK_START); + if (redir_endp == NULL || redir_lval->ll_name == NULL + || *redir_endp != NUL) { clear_lval(redir_lval); if (redir_endp != NULL && *redir_endp != NUL) /* Trailing characters are present after the variable name */ @@ -823,12 +849,13 @@ void var_redir_stop(void) ga_append(&redir_ga, NUL); /* Append the trailing NUL. */ tv.v_type = VAR_STRING; tv.vval.v_string = redir_ga.ga_data; - /* Call get_lval() again, if it's inside a Dict or List it may - * have changed. */ - redir_endp = get_lval(redir_varname, NULL, redir_lval, - FALSE, FALSE, 0, FNE_CHECK_START); - if (redir_endp != NULL && redir_lval->ll_name != NULL) - set_var_lval(redir_lval, redir_endp, &tv, FALSE, (char_u *)"."); + // Call get_lval() again, if it's inside a Dict or List it may + // have changed. + redir_endp = (char_u *)get_lval(redir_varname, NULL, redir_lval, + false, false, 0, FNE_CHECK_START); + if (redir_endp != NULL && redir_lval->ll_name != NULL) { + set_var_lval(redir_lval, redir_endp, &tv, false, (char_u *)"."); + } clear_lval(redir_lval); } @@ -846,7 +873,7 @@ void var_redir_stop(void) int eval_charconvert(const char *const enc_from, const char *const enc_to, const char *const fname_from, const char *const fname_to) { - int err = false; + bool err = false; set_vim_var_string(VV_CC_FROM, enc_from, -1); set_vim_var_string(VV_CC_TO, enc_to, -1); @@ -868,7 +895,7 @@ int eval_charconvert(const char *const enc_from, const char *const enc_to, int eval_printexpr(const char *const fname, const char *const args) { - int err = false; + bool err = false; set_vim_var_string(VV_FNAME_IN, fname, -1); set_vim_var_string(VV_CMDARG, args, -1); @@ -888,7 +915,7 @@ int eval_printexpr(const char *const fname, const char *const args) void eval_diff(const char *const origfile, const char *const newfile, const char *const outfile) { - int err = FALSE; + bool err = false; set_vim_var_string(VV_FNAME_IN, origfile, -1); set_vim_var_string(VV_FNAME_NEW, newfile, -1); @@ -902,7 +929,7 @@ void eval_diff(const char *const origfile, const char *const newfile, void eval_patch(const char *const origfile, const char *const difffile, const char *const outfile) { - int err; + bool err = false; set_vim_var_string(VV_FNAME_IN, origfile, -1); set_vim_var_string(VV_FNAME_DIFF, difffile, -1); @@ -921,56 +948,61 @@ void eval_patch(const char *const origfile, const char *const difffile, int eval_to_bool ( char_u *arg, - int *error, + bool *error, char_u **nextcmd, int skip /* only parse, don't execute */ ) { typval_T tv; - int retval = FALSE; + bool retval = false; - if (skip) - ++emsg_skip; - if (eval0(arg, &tv, nextcmd, !skip) == FAIL) - *error = TRUE; - else { - *error = FALSE; + if (skip) { + emsg_skip++; + } + if (eval0(arg, &tv, nextcmd, !skip) == FAIL) { + *error = true; + } else { + *error = false; if (!skip) { - retval = (get_tv_number_chk(&tv, error) != 0); - clear_tv(&tv); + retval = (tv_get_number_chk(&tv, error) != 0); + tv_clear(&tv); } } - if (skip) - --emsg_skip; + if (skip) { + emsg_skip--; + } return retval; } -/* - * Top level evaluation function, returning a string. If "skip" is TRUE, - * only parsing to "nextcmd" is done, without reporting errors. Return - * pointer to allocated memory, or NULL for failure or when "skip" is TRUE. - */ -char_u * -eval_to_string_skip ( - char_u *arg, - char_u **nextcmd, - int skip /* only parse, don't execute */ -) +/// Top level evaluation function, returning a string +/// +/// @param[in] arg String to evaluate. +/// @param nextcmd Pointer to the start of the next Ex command. +/// @param[in] skip If true, only do parsing to nextcmd without reporting +/// errors or actually evaluating anything. +/// +/// @return [allocated] string result of evaluation or NULL in case of error or +/// when skipping. +char *eval_to_string_skip(const char *arg, const char **nextcmd, + const bool skip) + FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ARG(1) FUNC_ATTR_WARN_UNUSED_RESULT { typval_T tv; - char_u *retval; + char *retval; - if (skip) - ++emsg_skip; - if (eval0(arg, &tv, nextcmd, !skip) == FAIL || skip) + if (skip) { + emsg_skip++; + } + if (eval0((char_u *)arg, &tv, (char_u **)nextcmd, !skip) == FAIL || skip) { retval = NULL; - else { - retval = vim_strsave(get_tv_string(&tv)); - clear_tv(&tv); + } else { + retval = xstrdup(tv_get_string(&tv)); + tv_clear(&tv); + } + if (skip) { + emsg_skip--; } - if (skip) - --emsg_skip; return retval; } @@ -996,31 +1028,33 @@ int skip_expr(char_u **pp) char_u *eval_to_string(char_u *arg, char_u **nextcmd, int convert) { typval_T tv; - char_u *retval; + char *retval; garray_T ga; - char_u numbuf[NUMBUFLEN]; - if (eval0(arg, &tv, nextcmd, TRUE) == FAIL) + if (eval0(arg, &tv, nextcmd, true) == FAIL) { retval = NULL; - else { + } else { if (convert && tv.v_type == VAR_LIST) { ga_init(&ga, (int)sizeof(char), 80); if (tv.vval.v_list != NULL) { - list_join(&ga, tv.vval.v_list, "\n"); - if (tv.vval.v_list->lv_len > 0) + tv_list_join(&ga, tv.vval.v_list, "\n"); + if (tv.vval.v_list->lv_len > 0) { ga_append(&ga, NL); + } } ga_append(&ga, NUL); - retval = (char_u *)ga.ga_data; + retval = (char *)ga.ga_data; } else if (convert && tv.v_type == VAR_FLOAT) { - vim_snprintf((char *)numbuf, NUMBUFLEN, "%g", tv.vval.v_float); - retval = vim_strsave(numbuf); - } else - retval = vim_strsave(get_tv_string(&tv)); - clear_tv(&tv); + char numbuf[NUMBUFLEN]; + vim_snprintf(numbuf, NUMBUFLEN, "%g", tv.vval.v_float); + retval = xstrdup(numbuf); + } else { + retval = xstrdup(tv_get_string(&tv)); + } + tv_clear(&tv); } - return retval; + return (char_u *)retval; } /* @@ -1049,19 +1083,19 @@ char_u *eval_to_string_safe(char_u *arg, char_u **nextcmd, int use_sandbox) * Evaluates "expr" silently. * Returns -1 for an error. */ -int eval_to_number(char_u *expr) +varnumber_T eval_to_number(char_u *expr) { typval_T rettv; - int retval; + varnumber_T retval; char_u *p = skipwhite(expr); ++emsg_off; - if (eval1(&p, &rettv, TRUE) == FAIL) + if (eval1(&p, &rettv, true) == FAIL) { retval = -1; - else { - retval = get_tv_number_chk(&rettv, NULL); - clear_tv(&rettv); + } else { + retval = tv_get_number_chk(&rettv, NULL); + tv_clear(&rettv); } --emsg_off; @@ -1118,11 +1152,12 @@ list_T *eval_spell_expr(char_u *badword, char_u *expr) if (p_verbose == 0) ++emsg_off; - if (eval1(&p, &rettv, TRUE) == OK) { - if (rettv.v_type != VAR_LIST) - clear_tv(&rettv); - else + if (eval1(&p, &rettv, true) == OK) { + if (rettv.v_type != VAR_LIST) { + tv_clear(&rettv); + } else { list = rettv.vval.v_list; + } } if (p_verbose == 0) @@ -1138,54 +1173,39 @@ list_T *eval_spell_expr(char_u *badword, char_u *expr) * Return -1 if anything isn't right. * Used to get the good word and score from the eval_spell_expr() result. */ -int get_spellword(list_T *list, char_u **pp) +int get_spellword(list_T *list, const char **pp) { listitem_T *li; li = list->lv_first; - if (li == NULL) + if (li == NULL) { return -1; - *pp = get_tv_string(&li->li_tv); + } + *pp = tv_get_string(&li->li_tv); li = li->li_next; - if (li == NULL) + if (li == NULL) { return -1; - return get_tv_number(&li->li_tv); -} - -/* - * Top level evaluation function. - * Returns an allocated typval_T with the result. - * Returns NULL when there is an error. - */ -typval_T *eval_expr(char_u *arg, char_u **nextcmd) -{ - typval_T *tv = xmalloc(sizeof(typval_T)); - - if (eval0(arg, tv, nextcmd, TRUE) == FAIL) { - xfree(tv); - return NULL; } - - return tv; + return tv_get_number(&li->li_tv); } -// Call some vimL function and return the result in "*rettv". +// Call some vim script function and return the result in "*rettv". // Uses argv[argc] for the function arguments. Only Number and String // arguments are currently supported. // // Return OK or FAIL. int call_vim_function( - char_u *func, + const char_u *func, int argc, - char_u **argv, + const char_u *const *const argv, int safe, // use the sandbox int str_arg_only, // all arguments are strings typval_T *rettv ) { - long n; + varnumber_T n; int len; int doesrange; void *save_funccalp = NULL; @@ -1212,7 +1232,7 @@ int call_vim_function( argvars[i].vval.v_number = n; } else { argvars[i].v_type = VAR_STRING; - argvars[i].vval.v_string = argv[i]; + argvars[i].vval.v_string = (char_u *)argv[i]; } } @@ -1221,8 +1241,8 @@ int call_vim_function( ++sandbox; } - rettv->v_type = VAR_UNKNOWN; /* clear_tv() uses this */ - ret = call_func(func, (int)STRLEN(func), rettv, argc, argvars, + rettv->v_type = VAR_UNKNOWN; // tv_clear() uses this. + ret = call_func(func, (int)STRLEN(func), rettv, argc, argvars, NULL, curwin->w_cursor.lnum, curwin->w_cursor.lnum, &doesrange, true, NULL, NULL); if (safe) { @@ -1232,74 +1252,72 @@ int call_vim_function( xfree(argvars); if (ret == FAIL) { - clear_tv(rettv); + tv_clear(rettv); } return ret; } -/* - * Call vimL function "func" and return the result as a number. - * Returns -1 when calling the function fails. - * Uses argv[argc] for the function arguments. - */ -long -call_func_retnr ( - char_u *func, - int argc, - char_u **argv, - int safe /* use the sandbox */ -) +/// Call Vim script function and return the result as a number +/// +/// @param[in] func Function name. +/// @param[in] argc Number of arguments. +/// @param[in] argv Array with string arguments. +/// @param[in] safe Use with sandbox. +/// +/// @return -1 when calling function fails, result of function otherwise. +varnumber_T call_func_retnr(char_u *func, int argc, + const char_u *const *const argv, int safe) { typval_T rettv; - long retval; + varnumber_T retval; /* All arguments are passed as strings, no conversion to number. */ if (call_vim_function(func, argc, argv, safe, TRUE, &rettv) == FAIL) return -1; - retval = get_tv_number_chk(&rettv, NULL); - clear_tv(&rettv); + retval = tv_get_number_chk(&rettv, NULL); + tv_clear(&rettv); return retval; } -/* - * Call vimL function "func" and return the result as a string. - * Returns NULL when calling the function fails. - * Uses argv[argc] for the function arguments. - */ -void * -call_func_retstr ( - char_u *func, - int argc, - char_u **argv, - int safe /* use the sandbox */ -) +/// Call Vim script function and return the result as a string +/// +/// @param[in] func Function name. +/// @param[in] argc Number of arguments. +/// @param[in] argv Array with string arguments. +/// @param[in] safe Use the sandbox. +/// +/// @return [allocated] NULL when calling function fails, allocated string +/// otherwise. +char *call_func_retstr(const char *const func, const int argc, + const char_u *const *const argv, + const bool safe) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_MALLOC { typval_T rettv; - char_u *retval; - - /* All arguments are passed as strings, no conversion to number. */ - if (call_vim_function(func, argc, argv, safe, TRUE, &rettv) == FAIL) + // All arguments are passed as strings, no conversion to number. + if (call_vim_function((const char_u *)func, argc, argv, safe, true, &rettv) + == FAIL) { return NULL; + } - retval = vim_strsave(get_tv_string(&rettv)); - clear_tv(&rettv); + char *const retval = xstrdup(tv_get_string(&rettv)); + tv_clear(&rettv); return retval; } -/* - * Call vimL function "func" and return the result as a List. - * Uses argv[argc] for the function arguments. - * Returns NULL when there is something wrong. - */ -void * -call_func_retlist ( - char_u *func, - int argc, - char_u **argv, - int safe /* use the sandbox */ -) +/// Call Vim script function and return the result as a List +/// +/// @param[in] func Function name. +/// @param[in] argc Number of arguments. +/// @param[in] argv Array with string arguments. +/// @param[in] safe Use the sandbox. +/// +/// @return [allocated] NULL when calling function fails or return tv is not a +/// List, allocated List otherwise. +void *call_func_retlist(char_u *func, int argc, const char_u *const *const argv, + int safe) { typval_T rettv; @@ -1308,7 +1326,7 @@ call_func_retlist ( return NULL; if (rettv.v_type != VAR_LIST) { - clear_tv(&rettv); + tv_clear(&rettv); return NULL; } @@ -1380,7 +1398,7 @@ void prof_child_exit(proftime_T *tm /* where waittime was stored */ int eval_foldexpr(char_u *arg, int *cp) { typval_T tv; - int retval; + varnumber_T retval; char_u *s; int use_sandbox = was_set_insecurely((char_u *)"foldexpr", OPT_LOCAL); @@ -1406,14 +1424,14 @@ int eval_foldexpr(char_u *arg, int *cp) *cp = *s++; retval = atol((char *)s); } - clear_tv(&tv); + tv_clear(&tv); } --emsg_off; if (use_sandbox) --sandbox; --textlock; - return retval; + return (int)retval; } /* @@ -1437,22 +1455,24 @@ void ex_let(exarg_T *eap) char_u *argend; int first = TRUE; - argend = skip_var_list(arg, &var_count, &semicolon); - if (argend == NULL) + argend = (char_u *)skip_var_list(arg, &var_count, &semicolon); + if (argend == NULL) { return; - if (argend > arg && argend[-1] == '.') /* for var.='str' */ - --argend; + } + if (argend > arg && argend[-1] == '.') { // For var.='str'. + argend--; + } expr = skipwhite(argend); if (*expr != '=' && !(vim_strchr((char_u *)"+-.", *expr) != NULL && expr[1] == '=')) { // ":let" without "=": list variables - if (*arg == '[') + if (*arg == '[') { EMSG(_(e_invarg)); - else if (!ends_excmd(*arg)) - /* ":let var1 var2" */ - arg = list_arg_vars(eap, arg, &first); - else if (!eap->skip) { - /* ":let" */ + } else if (!ends_excmd(*arg)) { + // ":let var1 var2" + arg = (char_u *)list_arg_vars(eap, (const char *)arg, &first); + } else if (!eap->skip) { + // ":let" list_glob_vars(&first); list_buf_vars(&first); list_win_vars(&first); @@ -1478,13 +1498,13 @@ void ex_let(exarg_T *eap) ++emsg_skip; i = eval0(expr, &rettv, &eap->nextcmd, !eap->skip); if (eap->skip) { - if (i != FAIL) - clear_tv(&rettv); - --emsg_skip; + if (i != FAIL) { + tv_clear(&rettv); + } + emsg_skip--; } else if (i != FAIL) { - (void)ex_let_vars(eap->arg, &rettv, FALSE, semicolon, var_count, - op); - clear_tv(&rettv); + (void)ex_let_vars(eap->arg, &rettv, false, semicolon, var_count, op); + tv_clear(&rettv); } } } @@ -1507,7 +1527,7 @@ ex_let_vars ( char_u *nextchars ) { - char_u *arg = arg_start; + char_u *arg = arg_start; list_T *l; int i; listitem_T *item; @@ -1530,7 +1550,7 @@ ex_let_vars ( return FAIL; } - i = list_len(l); + i = tv_list_len(l); if (semicolon == 0 && var_count < i) { EMSG(_("E687: Less targets than List items")); return FAIL; @@ -1552,9 +1572,9 @@ ex_let_vars ( if (*arg == ';') { /* Put the rest of the list (may be empty) in the var after ';'. * Create a new list for this. */ - l = list_alloc(); + l = tv_list_alloc(); while (item != NULL) { - list_append_tv(l, &item->li_tv); + tv_list_append_tv(l, &item->li_tv); item = item->li_next; } @@ -1563,11 +1583,12 @@ ex_let_vars ( ltv.vval.v_list = l; l->lv_refcount = 1; - arg = ex_let_one(skipwhite(arg + 1), <v, FALSE, - (char_u *)"]", nextchars); - clear_tv(<v); - if (arg == NULL) + arg = ex_let_one(skipwhite(arg + 1), <v, false, + (char_u *)"]", nextchars); + tv_clear(<v); + if (arg == NULL) { return FAIL; + } break; } else if (*arg != ',' && *arg != ']') { EMSG2(_(e_intern2), "ex_let_vars()"); @@ -1585,9 +1606,11 @@ ex_let_vars ( * for "[var, var; var]" set "semicolon". * Return NULL for an error. */ -static char_u *skip_var_list(char_u *arg, int *var_count, int *semicolon) +static const char_u *skip_var_list(const char_u *arg, int *var_count, + int *semicolon) { - char_u *p, *s; + const char_u *p; + const char_u *s; if (*arg == '[') { /* "[var, var]": find the matching ']'. */ @@ -1624,7 +1647,7 @@ static char_u *skip_var_list(char_u *arg, int *var_count, int *semicolon) * Skip one (assignable) variable name, including @r, $VAR, &option, d.key, * l[idx]. */ -static char_u *skip_var_one(char_u *arg) +static const char_u *skip_var_one(const char_u *arg) { if (*arg == '@' && arg[1] != NUL) return arg + 2; @@ -1636,7 +1659,8 @@ static char_u *skip_var_one(char_u *arg) * List variables for hashtab "ht" with prefix "prefix". * If "empty" is TRUE also list NULL strings as empty strings. */ -static void list_hashtable_vars(hashtab_T *ht, char_u *prefix, int empty, int *first) +static void list_hashtable_vars(hashtab_T *ht, const char *prefix, int empty, + int *first) { hashitem_T *hi; dictitem_T *di; @@ -1645,11 +1669,12 @@ static void list_hashtable_vars(hashtab_T *ht, char_u *prefix, int empty, int *f todo = (int)ht->ht_used; for (hi = ht->ht_array; todo > 0 && !got_int; ++hi) { if (!HASHITEM_EMPTY(hi)) { - --todo; - di = HI2DI(hi); + todo--; + di = TV_DICT_HI2DI(hi); if (empty || di->di_tv.v_type != VAR_STRING - || di->di_tv.vval.v_string != NULL) + || di->di_tv.vval.v_string != NULL) { list_one_var(di, prefix, first); + } } } } @@ -1659,7 +1684,7 @@ static void list_hashtable_vars(hashtab_T *ht, char_u *prefix, int empty, int *f */ static void list_glob_vars(int *first) { - list_hashtable_vars(&globvarht, (char_u *)"", TRUE, first); + list_hashtable_vars(&globvarht, "", true, first); } /* @@ -1667,14 +1692,7 @@ static void list_glob_vars(int *first) */ static void list_buf_vars(int *first) { - char_u numbuf[NUMBUFLEN]; - - list_hashtable_vars(&curbuf->b_vars->dv_hashtab, (char_u *)"b:", - TRUE, first); - - sprintf((char *)numbuf, "%" PRId64, (int64_t)curbuf->b_changedtick); - list_one_var_a((char_u *)"b:", (char_u *)"changedtick", VAR_NUMBER, - numbuf, first); + list_hashtable_vars(&curbuf->b_vars->dv_hashtab, "b:", true, first); } /* @@ -1682,8 +1700,7 @@ static void list_buf_vars(int *first) */ static void list_win_vars(int *first) { - list_hashtable_vars(&curwin->w_vars->dv_hashtab, - (char_u *)"w:", TRUE, first); + list_hashtable_vars(&curwin->w_vars->dv_hashtab, "w:", true, first); } /* @@ -1691,8 +1708,7 @@ static void list_win_vars(int *first) */ static void list_tab_vars(int *first) { - list_hashtable_vars(&curtab->tp_vars->dv_hashtab, - (char_u *)"t:", TRUE, first); + list_hashtable_vars(&curtab->tp_vars->dv_hashtab, "t:", true, first); } /* @@ -1700,7 +1716,7 @@ static void list_tab_vars(int *first) */ static void list_vim_vars(int *first) { - list_hashtable_vars(&vimvarht, (char_u *)"v:", FALSE, first); + list_hashtable_vars(&vimvarht, "v:", false, first); } /* @@ -1708,9 +1724,9 @@ static void list_vim_vars(int *first) */ static void list_script_vars(int *first) { - if (current_SID > 0 && current_SID <= ga_scripts.ga_len) - list_hashtable_vars(&SCRIPT_VARS(current_SID), - (char_u *)"s:", FALSE, first); + if (current_SID > 0 && current_SID <= ga_scripts.ga_len) { + list_hashtable_vars(&SCRIPT_VARS(current_SID), "s:", false, first); + } } /* @@ -1718,36 +1734,37 @@ static void list_script_vars(int *first) */ static void list_func_vars(int *first) { - if (current_funccal != NULL) - list_hashtable_vars(¤t_funccal->l_vars.dv_hashtab, - (char_u *)"l:", FALSE, first); + if (current_funccal != NULL) { + list_hashtable_vars(¤t_funccal->l_vars.dv_hashtab, "l:", false, + first); + } } /* * List variables in "arg". */ -static char_u *list_arg_vars(exarg_T *eap, char_u *arg, int *first) +static const char *list_arg_vars(exarg_T *eap, const char *arg, int *first) { int error = FALSE; int len; - char_u *name; - char_u *name_start; - char_u *arg_subsc; - char_u *tofree; + const char *name; + const char *name_start; typval_T tv; while (!ends_excmd(*arg) && !got_int) { if (error || eap->skip) { - arg = find_name_end(arg, NULL, NULL, FNE_INCL_BR | FNE_CHECK_START); + arg = (const char *)find_name_end((char_u *)arg, NULL, NULL, + FNE_INCL_BR | FNE_CHECK_START); if (!ascii_iswhite(*arg) && !ends_excmd(*arg)) { emsg_severe = TRUE; EMSG(_(e_trailing)); break; } } else { - /* get_name_len() takes care of expanding curly braces */ + // get_name_len() takes care of expanding curly braces name_start = name = arg; - len = get_name_len(&arg, &tofree, TRUE, TRUE); + char *tofree; + len = get_name_len(&arg, &tofree, true, true); if (len <= 0) { /* This is mainly to keep test 49 working: when expanding * curly braces fails overrule the exception error message. */ @@ -1761,14 +1778,15 @@ static char_u *list_arg_vars(exarg_T *eap, char_u *arg, int *first) if (tofree != NULL) { name = tofree; } - if (get_var_tv(name, len, &tv, NULL, true, false) == FAIL) { + if (get_var_tv((const char *)name, len, &tv, NULL, true, false) + == FAIL) { error = true; } else { // handle d.key, l[idx], f(expr) - arg_subsc = arg; - if (handle_subscript(&arg, &tv, TRUE, TRUE) == FAIL) - error = TRUE; - else { + const char *const arg_subsc = arg; + if (handle_subscript(&arg, &tv, true, true) == FAIL) { + error = true; + } else { if (arg == arg_subsc && len == 2 && name[1] == ':') { switch (*name) { case 'g': list_glob_vars(first); break; @@ -1782,20 +1800,18 @@ static char_u *list_arg_vars(exarg_T *eap, char_u *arg, int *first) EMSG2(_("E738: Can't list variables for %s"), name); } } else { - int c; - - char_u *s = (char_u *) encode_tv2echo(&tv, NULL); - c = *arg; - *arg = NUL; - list_one_var_a((char_u *)"", - arg == arg_subsc ? name : name_start, - tv.v_type, - s == NULL ? (char_u *)"" : s, - first); - *arg = c; + char *const s = encode_tv2echo(&tv, NULL); + const char *const used_name = (arg == arg_subsc + ? name + : name_start); + const ptrdiff_t name_size = (used_name == tofree + ? (ptrdiff_t)strlen(used_name) + : (arg - used_name)); + list_one_var_a("", used_name, name_size, + tv.v_type, s == NULL ? "" : s, first); xfree(s); } - clear_tv(&tv); + tv_clear(&tv); } } } @@ -1803,152 +1819,153 @@ static char_u *list_arg_vars(exarg_T *eap, char_u *arg, int *first) xfree(tofree); } - arg = skipwhite(arg); + arg = (const char *)skipwhite((const char_u *)arg); } return arg; } -/* - * Set one item of ":let var = expr" or ":let [v1, v2] = list" to its value. - * Returns a pointer to the char just after the var name. - * Returns NULL if there is an error. - */ -static char_u * -ex_let_one ( - char_u *arg, /* points to variable name */ - typval_T *tv, /* value to assign to variable */ - int copy, /* copy value from "tv" */ - char_u *endchars, /* valid chars after variable name or NULL */ - char_u *op /* "+", "-", "." or NULL*/ -) -{ - int c1; - char_u *name; - char_u *p; - char_u *arg_end = NULL; +// TODO(ZyX-I): move to eval/ex_cmds + +/// Set one item of `:let var = expr` or `:let [v1, v2] = list` to its value +/// +/// @param[in] arg Start of the variable name. +/// @param[in] tv Value to assign to the variable. +/// @param[in] copy If true, copy value from `tv`. +/// @param[in] endchars Valid characters after variable name or NULL. +/// @param[in] op Operation performed: *op is `+`, `-`, `.` for `+=`, etc. +/// NULL for `=`. +/// +/// @return a pointer to the char just after the var name or NULL in case of +/// error. +static char_u *ex_let_one(char_u *arg, typval_T *const tv, + const bool copy, const char_u *const endchars, + const char_u *const op) + FUNC_ATTR_NONNULL_ARG(1, 2) FUNC_ATTR_WARN_UNUSED_RESULT +{ + char_u *arg_end = NULL; int len; int opt_flags; - char_u *tofree = NULL; + char_u *tofree = NULL; /* * ":let $VAR = expr": Set environment variable. */ if (*arg == '$') { - /* Find the end of the name. */ - ++arg; - name = arg; - len = get_env_len(&arg); - if (len == 0) + // Find the end of the name. + arg++; + char *name = (char *)arg; + len = get_env_len((const char_u **)&arg); + if (len == 0) { EMSG2(_(e_invarg2), name - 1); - else { - if (op != NULL && (*op == '+' || *op == '-')) + } else { + if (op != NULL && (*op == '+' || *op == '-')) { EMSG2(_(e_letwrong), op); - else if (endchars != NULL - && vim_strchr(endchars, *skipwhite(arg)) == NULL) + } else if (endchars != NULL + && vim_strchr(endchars, *skipwhite(arg)) == NULL) { EMSG(_(e_letunexp)); - else if (!check_secure()) { - c1 = name[len]; + } else if (!check_secure()) { + const char c1 = name[len]; name[len] = NUL; - p = get_tv_string_chk(tv); + const char *p = tv_get_string_chk(tv); if (p != NULL && op != NULL && *op == '.') { - char *s = vim_getenv((char *)name); + char *s = vim_getenv(name); if (s != NULL) { - p = tofree = concat_str((char_u *)s, p); + tofree = concat_str((const char_u *)s, (const char_u *)p); + p = (const char *)tofree; xfree(s); } } if (p != NULL) { - vim_setenv((char *)name, (char *)p); - if (STRICMP(name, "HOME") == 0) + vim_setenv(name, p); + if (STRICMP(name, "HOME") == 0) { init_homedir(); - else if (didset_vim && STRICMP(name, "VIM") == 0) - didset_vim = FALSE; - else if (didset_vimruntime - && STRICMP(name, "VIMRUNTIME") == 0) - didset_vimruntime = FALSE; + } else if (didset_vim && STRICMP(name, "VIM") == 0) { + didset_vim = false; + } else if (didset_vimruntime + && STRICMP(name, "VIMRUNTIME") == 0) { + didset_vimruntime = false; + } arg_end = arg; } name[len] = c1; xfree(tofree); } } - } - /* - * ":let &option = expr": Set option value. - * ":let &l:option = expr": Set local option value. - * ":let &g:option = expr": Set global option value. - */ - else if (*arg == '&') { - /* Find the end of the name. */ - p = find_option_end(&arg, &opt_flags); - if (p == NULL || (endchars != NULL - && vim_strchr(endchars, *skipwhite(p)) == NULL)) + // ":let &option = expr": Set option value. + // ":let &l:option = expr": Set local option value. + // ":let &g:option = expr": Set global option value. + } else if (*arg == '&') { + // Find the end of the name. + char *const p = (char *)find_option_end((const char **)&arg, &opt_flags); + if (p == NULL + || (endchars != NULL + && vim_strchr(endchars, *skipwhite((const char_u *)p)) == NULL)) { EMSG(_(e_letunexp)); - else { - long n; + } else { int opt_type; long numval; - char_u *stringval = NULL; - char_u *s; + char *stringval = NULL; - c1 = *p; + const char c1 = *p; *p = NUL; - n = get_tv_number(tv); - s = get_tv_string_chk(tv); /* != NULL if number or string */ + varnumber_T n = tv_get_number(tv); + const char *s = tv_get_string_chk(tv); // != NULL if number or string. if (s != NULL && op != NULL && *op != '=') { - opt_type = get_option_value(arg, &numval, - &stringval, opt_flags); + opt_type = get_option_value(arg, &numval, (char_u **)&stringval, + opt_flags); if ((opt_type == 1 && *op == '.') - || (opt_type == 0 && *op != '.')) + || (opt_type == 0 && *op != '.')) { EMSG2(_(e_letwrong), op); - else { - if (opt_type == 1) { /* number */ - if (*op == '+') + } else { + if (opt_type == 1) { // number + if (*op == '+') { n = numval + n; - else + } else { n = numval - n; - } else if (opt_type == 0 && stringval != NULL) { /* string */ - s = concat_str(stringval, s); - xfree(stringval); - stringval = s; + } + } else if (opt_type == 0 && stringval != NULL) { // string + char *const oldstringval = stringval; + stringval = (char *)concat_str((const char_u *)stringval, + (const char_u *)s); + xfree(oldstringval); + s = stringval; } } } if (s != NULL) { - set_option_value(arg, n, s, opt_flags); - arg_end = p; + set_option_value((const char *)arg, n, s, opt_flags); + arg_end = (char_u *)p; } *p = c1; xfree(stringval); } - } - /* - * ":let @r = expr": Set register contents. - */ - else if (*arg == '@') { - ++arg; - if (op != NULL && (*op == '+' || *op == '-')) - EMSG2(_(e_letwrong), op); - else if (endchars != NULL - && vim_strchr(endchars, *skipwhite(arg + 1)) == NULL) - EMSG(_(e_letunexp)); - else { - char_u *ptofree = NULL; + // ":let @r = expr": Set register contents. + } else if (*arg == '@') { + arg++; + if (op != NULL && (*op == '+' || *op == '-')) { + emsgf(_(e_letwrong), op); + } else if (endchars != NULL + && vim_strchr(endchars, *skipwhite(arg + 1)) == NULL) { + emsgf(_(e_letunexp)); + } else { char_u *s; - p = get_tv_string_chk(tv); + char_u *ptofree = NULL; + const char *p = tv_get_string_chk(tv); if (p != NULL && op != NULL && *op == '.') { s = get_reg_contents(*arg == '@' ? '"' : *arg, kGRegExprSrc); if (s != NULL) { - p = ptofree = concat_str(s, p); + ptofree = concat_str(s, (const char_u *)p); + p = (const char *)ptofree; xfree(s); } } if (p != NULL) { - write_reg_contents(*arg == '@' ? '"' : *arg, p, STRLEN(p), false); + write_reg_contents(*arg == '@' ? '"' : *arg, + (const char_u *)p, STRLEN(p), false); arg_end = arg + 1; } xfree(ptofree); @@ -1961,11 +1978,11 @@ ex_let_one ( else if (eval_isnamec1(*arg) || *arg == '{') { lval_T lv; - p = get_lval(arg, tv, &lv, FALSE, FALSE, 0, FNE_CHECK_START); + char_u *const p = get_lval(arg, tv, &lv, false, false, 0, FNE_CHECK_START); if (p != NULL && lv.ll_name != NULL) { - if (endchars != NULL && vim_strchr(endchars, *skipwhite(p)) == NULL) + if (endchars != NULL && vim_strchr(endchars, *skipwhite(p)) == NULL) { EMSG(_(e_letunexp)); - else { + } else { set_var_lval(&lv, p, tv, copy, op); arg_end = p; } @@ -1977,57 +1994,41 @@ ex_let_one ( return arg_end; } -/* - * If "arg" is equal to "b:changedtick" give an error and return TRUE. - */ -static int check_changedtick(char_u *arg) -{ - if (STRNCMP(arg, "b:changedtick", 13) == 0 && !eval_isnamec(arg[13])) { - EMSG2(_(e_readonlyvar), arg); - return TRUE; - } - return FALSE; -} +// TODO(ZyX-I): move to eval/executor -/* - * Get an lval: variable, Dict item or List item that can be assigned a value - * to: "name", "na{me}", "name[expr]", "name[expr:expr]", "name[expr][expr]", - * "name.key", "name.key[expr]" etc. - * Indexing only works if "name" is an existing List or Dictionary. - * "name" points to the start of the name. - * If "rettv" is not NULL it points to the value to be assigned. - * "unlet" is TRUE for ":unlet": slightly different behavior when something is - * wrong; must end in space or cmd separator. - * - * flags: - * GLV_QUIET: do not give error messages - * GLV_NO_AUTOLOAD: do not use script autoloading - * - * Returns a pointer to just after the name, including indexes. - * When an evaluation error occurs "lp->ll_name" is NULL; - * Returns NULL for a parsing error. Still need to free items in "lp"! - */ -static char_u * -get_lval ( - char_u *name, - typval_T *rettv, - lval_T *lp, - int unlet, - int skip, - int flags, /* GLV_ values */ - int fne_flags /* flags for find_name_end() */ -) +/// Get an lvalue +/// +/// Lvalue may be +/// - variable: "name", "na{me}" +/// - dictionary item: "dict.key", "dict['key']" +/// - list item: "list[expr]" +/// - list slice: "list[expr:expr]" +/// +/// Indexing only works if trying to use it with an existing List or Dictionary. +/// +/// @param[in] name Name to parse. +/// @param rettv Pointer to the value to be assigned or NULL. +/// @param[out] lp Lvalue definition. When evaluation errors occur `->ll_name` +/// is NULL. +/// @param[in] unlet True if using `:unlet`. This results in slightly +/// different behaviour when something is wrong; must end in +/// space or cmd separator. +/// @param[in] skip True when skipping. +/// @param[in] flags @see GetLvalFlags. +/// @param[in] fne_flags Flags for find_name_end(). +/// +/// @return A pointer to just after the name, including indexes. Returns NULL +/// for a parsing error, but it is still needed to free items in lp. +static char_u *get_lval(char_u *const name, typval_T *const rettv, + lval_T *const lp, const bool unlet, const bool skip, + const int flags, const int fne_flags) + FUNC_ATTR_NONNULL_ARG(1, 3) { - char_u *p; - char_u *expr_start, *expr_end; - int cc; dictitem_T *v; typval_T var1; typval_T var2; int empty1 = FALSE; listitem_T *ni; - char_u *key = NULL; - int len; hashtab_T *ht; int quiet = flags & GLV_QUIET; @@ -2035,13 +2036,19 @@ get_lval ( memset(lp, 0, sizeof(lval_T)); if (skip) { - /* When skipping just find the end of the name. */ - lp->ll_name = name; - return find_name_end(name, NULL, NULL, FNE_INCL_BR | fne_flags); + // When skipping just find the end of the name. + lp->ll_name = (const char *)name; + return (char_u *)find_name_end((const char_u *)name, NULL, NULL, + FNE_INCL_BR | fne_flags); } - /* Find the end of the name. */ - p = find_name_end(name, &expr_start, &expr_end, fne_flags); + // Find the end of the name. + char_u *expr_start; + char_u *expr_end; + char_u *p = (char_u *)find_name_end(name, + (const char_u **)&expr_start, + (const char_u **)&expr_end, + fne_flags); if (expr_start != NULL) { /* Don't expand the name when we already know there is an error. */ if (unlet && !ascii_iswhite(*p) && !ends_excmd(*p) @@ -2050,7 +2057,9 @@ get_lval ( return NULL; } - lp->ll_exp_name = make_expanded_name(name, expr_start, expr_end, p); + lp->ll_exp_name = (char *)make_expanded_name(name, expr_start, expr_end, + (char_u *)p); + lp->ll_name = lp->ll_exp_name; if (lp->ll_exp_name == NULL) { /* Report an invalid expression in braces, unless the * expression evaluation has been cancelled due to an @@ -2060,23 +2069,28 @@ get_lval ( EMSG2(_(e_invarg2), name); return NULL; } + lp->ll_name_len = 0; + } else { + lp->ll_name_len = strlen(lp->ll_name); } - lp->ll_name = lp->ll_exp_name; - } else - lp->ll_name = name; + } else { + lp->ll_name = (const char *)name; + lp->ll_name_len = (size_t)((const char *)p - lp->ll_name); + } - /* Without [idx] or .key we are done. */ - if ((*p != '[' && *p != '.') || lp->ll_name == NULL) + // Without [idx] or .key we are done. + if ((*p != '[' && *p != '.') || lp->ll_name == NULL) { return p; + } - cc = *p; - *p = NUL; - v = find_var(lp->ll_name, &ht, flags & GLV_NO_AUTOLOAD); - if (v == NULL && !quiet) - EMSG2(_(e_undefvar), lp->ll_name); - *p = cc; - if (v == NULL) + v = find_var(lp->ll_name, lp->ll_name_len, &ht, flags & GLV_NO_AUTOLOAD); + if (v == NULL && !quiet) { + emsgf(_("E121: Undefined variable: %.*s"), + (int)lp->ll_name_len, lp->ll_name); + } + if (v == NULL) { return NULL; + } /* * Loop until no more [idx] or .key is following. @@ -2096,29 +2110,32 @@ get_lval ( return NULL; } - len = -1; + int len = -1; + char_u *key = NULL; if (*p == '.') { key = p + 1; - for (len = 0; ASCII_ISALNUM(key[len]) || key[len] == '_'; ++len) - ; + for (len = 0; ASCII_ISALNUM(key[len]) || key[len] == '_'; len++) { + } if (len == 0) { - if (!quiet) - EMSG(_(e_emptykey)); + if (!quiet) { + EMSG(_("E713: Cannot use empty key after .")); + } return NULL; } p = key + len; } else { /* Get the index [expr] or the first index [expr: ]. */ p = skipwhite(p + 1); - if (*p == ':') - empty1 = TRUE; - else { - empty1 = FALSE; - if (eval1(&p, &var1, TRUE) == FAIL) /* recursive! */ + if (*p == ':') { + empty1 = true; + } else { + empty1 = false; + if (eval1(&p, &var1, true) == FAIL) { // Recursive! return NULL; - if (get_tv_string_chk(&var1) == NULL) { - /* not a number or string */ - clear_tv(&var1); + } + if (!tv_check_str(&var1)) { + // Not a number or string. + tv_clear(&var1); return NULL; } } @@ -2126,35 +2143,41 @@ get_lval ( /* Optionally get the second index [ :expr]. */ if (*p == ':') { if (lp->ll_tv->v_type == VAR_DICT) { - if (!quiet) + if (!quiet) { EMSG(_(e_dictrange)); - if (!empty1) - clear_tv(&var1); + } + if (!empty1) { + tv_clear(&var1); + } return NULL; } if (rettv != NULL && (rettv->v_type != VAR_LIST || rettv->vval.v_list == NULL)) { - if (!quiet) - EMSG(_("E709: [:] requires a List value")); - if (!empty1) - clear_tv(&var1); + if (!quiet) { + emsgf(_("E709: [:] requires a List value")); + } + if (!empty1) { + tv_clear(&var1); + } return NULL; } p = skipwhite(p + 1); - if (*p == ']') - lp->ll_empty2 = TRUE; - else { - lp->ll_empty2 = FALSE; - if (eval1(&p, &var2, TRUE) == FAIL) { /* recursive! */ - if (!empty1) - clear_tv(&var1); + if (*p == ']') { + lp->ll_empty2 = true; + } else { + lp->ll_empty2 = false; + if (eval1(&p, &var2, true) == FAIL) { // Recursive! + if (!empty1) { + tv_clear(&var1); + } return NULL; } - if (get_tv_string_chk(&var2) == NULL) { - /* not a number or string */ - if (!empty1) - clear_tv(&var1); - clear_tv(&var2); + if (!tv_check_str(&var2)) { + // Not a number or string. + if (!empty1) { + tv_clear(&var1); + } + tv_clear(&var2); return NULL; } } @@ -2163,12 +2186,15 @@ get_lval ( lp->ll_range = FALSE; if (*p != ']') { - if (!quiet) - EMSG(_(e_missbrac)); - if (!empty1) - clear_tv(&var1); - if (lp->ll_range && !lp->ll_empty2) - clear_tv(&var2); + if (!quiet) { + emsgf(_(e_missbrac)); + } + if (!empty1) { + tv_clear(&var1); + } + if (lp->ll_range && !lp->ll_empty2) { + tv_clear(&var2); + } return NULL; } @@ -2179,15 +2205,15 @@ get_lval ( if (lp->ll_tv->v_type == VAR_DICT) { if (len == -1) { // "[key]": get key from "var1" - key = get_tv_string_chk(&var1); // is number or string + key = (char_u *)tv_get_string(&var1); // is number or string if (key == NULL) { - clear_tv(&var1); + tv_clear(&var1); return NULL; } } lp->ll_list = NULL; lp->ll_dict = lp->ll_tv->vval.v_dict; - lp->ll_di = dict_find(lp->ll_dict, key, len); + lp->ll_di = tv_dict_find(lp->ll_dict, (const char *)key, len); /* When assigning to a scope dictionary check that a function and * variable name is valid (only variable name unless it is l: or @@ -2199,16 +2225,19 @@ get_lval ( if (len != -1) { prevval = key[len]; key[len] = NUL; - } else - prevval = 0; /* avoid compiler warning */ - wrong = (lp->ll_dict->dv_scope == VAR_DEF_SCOPE - && rettv->v_type == VAR_FUNC - && var_check_func_name(key, lp->ll_di == NULL)) - || !valid_varname(key); - if (len != -1) + } else { + prevval = 0; // Avoid compiler warning. + } + wrong = ((lp->ll_dict->dv_scope == VAR_DEF_SCOPE + && tv_is_func(*rettv) + && !var_check_func_name((const char *)key, lp->ll_di == NULL)) + || !valid_varname((const char *)key)); + if (len != -1) { key[len] = prevval; - if (wrong) + } + if (wrong) { return NULL; + } } if (lp->ll_di == NULL) { @@ -2220,51 +2249,61 @@ get_lval ( /* Key does not exist in dict: may need to add it. */ if (*p == '[' || *p == '.' || unlet) { - if (!quiet) - EMSG2(_(e_dictkey), key); - if (len == -1) - clear_tv(&var1); + if (!quiet) { + emsgf(_(e_dictkey), key); + } + if (len == -1) { + tv_clear(&var1); + } return NULL; } - if (len == -1) + if (len == -1) { lp->ll_newkey = vim_strsave(key); - else + } else { lp->ll_newkey = vim_strnsave(key, len); - if (len == -1) - clear_tv(&var1); + } + if (len == -1) { + tv_clear(&var1); + } break; - } else if (var_check_ro(lp->ll_di->di_flags, name, false)) { - // existing variable, need to check if it can be changed + // existing variable, need to check if it can be changed + } else if (!(flags & GLV_READ_ONLY) && var_check_ro(lp->ll_di->di_flags, + (const char *)name, + (size_t)(p - name))) { + if (len == -1) { + tv_clear(&var1); + } return NULL; } - if (len == -1) - clear_tv(&var1); + if (len == -1) { + tv_clear(&var1); + } lp->ll_tv = &lp->ll_di->di_tv; } else { - /* - * Get the number and item for the only or first index of the List. - */ - if (empty1) + // Get the number and item for the only or first index of the List. + if (empty1) { lp->ll_n1 = 0; - else { - lp->ll_n1 = get_tv_number(&var1); /* is number or string */ - clear_tv(&var1); + } else { + lp->ll_n1 = (long)tv_get_number(&var1); // Is number or string. + tv_clear(&var1); } lp->ll_dict = NULL; lp->ll_list = lp->ll_tv->vval.v_list; - lp->ll_li = list_find(lp->ll_list, lp->ll_n1); + lp->ll_li = tv_list_find(lp->ll_list, lp->ll_n1); if (lp->ll_li == NULL) { if (lp->ll_n1 < 0) { lp->ll_n1 = 0; - lp->ll_li = list_find(lp->ll_list, lp->ll_n1); + lp->ll_li = tv_list_find(lp->ll_list, lp->ll_n1); } } if (lp->ll_li == NULL) { - if (lp->ll_range && !lp->ll_empty2) - clear_tv(&var2); - if (!quiet) + if (lp->ll_range && !lp->ll_empty2) { + tv_clear(&var2); + } + if (!quiet) { EMSGN(_(e_listidx), lp->ll_n1); + } return NULL; } @@ -2275,24 +2314,26 @@ get_lval ( * Otherwise "lp->ll_n2" is set to the second index. */ if (lp->ll_range && !lp->ll_empty2) { - lp->ll_n2 = get_tv_number(&var2); /* is number or string */ - clear_tv(&var2); + lp->ll_n2 = (long)tv_get_number(&var2); // Is number or string. + tv_clear(&var2); if (lp->ll_n2 < 0) { - ni = list_find(lp->ll_list, lp->ll_n2); + ni = tv_list_find(lp->ll_list, lp->ll_n2); if (ni == NULL) { if (!quiet) EMSGN(_(e_listidx), lp->ll_n2); return NULL; } - lp->ll_n2 = list_idx_of_item(lp->ll_list, ni); + lp->ll_n2 = tv_list_idx_of_item(lp->ll_list, ni); } - /* Check that lp->ll_n2 isn't before lp->ll_n1. */ - if (lp->ll_n1 < 0) - lp->ll_n1 = list_idx_of_item(lp->ll_list, lp->ll_li); + // Check that lp->ll_n2 isn't before lp->ll_n1. + if (lp->ll_n1 < 0) { + lp->ll_n1 = tv_list_idx_of_item(lp->ll_list, lp->ll_li); + } if (lp->ll_n2 < lp->ll_n1) { - if (!quiet) + if (!quiet) { EMSGN(_(e_listidx), lp->ll_n2); + } return NULL; } } @@ -2304,6 +2345,8 @@ get_lval ( return p; } +// TODO(ZyX-I): move to eval/executor + /* * Clear lval "lp" that was filled by get_lval(). */ @@ -2313,44 +2356,48 @@ static void clear_lval(lval_T *lp) xfree(lp->ll_newkey); } +// TODO(ZyX-I): move to eval/executor + /* * Set a variable that was parsed by get_lval() to "rettv". * "endp" points to just after the parsed name. * "op" is NULL, "+" for "+=", "-" for "-=", "." for ".=" or "=" for "=". */ -static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, int copy, char_u *op) +static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, + int copy, const char_u *op) { int cc; listitem_T *ri; dictitem_T *di; if (lp->ll_tv == NULL) { - if (!check_changedtick(lp->ll_name)) { - cc = *endp; - *endp = NUL; - if (op != NULL && *op != '=') { - typval_T tv; - - // handle +=, -= and .= - di = NULL; - if (get_var_tv(lp->ll_name, (int)STRLEN(lp->ll_name), - &tv, &di, true, false) == OK) { - if ((di == NULL - || (!var_check_ro(di->di_flags, lp->ll_name, false) - && !tv_check_lock(di->di_tv.v_lock, lp->ll_name, false))) - && tv_op(&tv, rettv, op) == OK) { - set_var(lp->ll_name, &tv, false); - } - clear_tv(&tv); + cc = *endp; + *endp = NUL; + if (op != NULL && *op != '=') { + typval_T tv; + + // handle +=, -= and .= + di = NULL; + if (get_var_tv((const char *)lp->ll_name, (int)STRLEN(lp->ll_name), + &tv, &di, true, false) == OK) { + if ((di == NULL + || (!var_check_ro(di->di_flags, (const char *)lp->ll_name, + TV_CSTRING) + && !tv_check_lock(di->di_tv.v_lock, (const char *)lp->ll_name, + TV_CSTRING))) + && eexe_mod_op(&tv, rettv, (const char *)op) == OK) { + set_var(lp->ll_name, lp->ll_name_len, &tv, false); } - } else - set_var(lp->ll_name, rettv, copy); - *endp = cc; + tv_clear(&tv); + } + } else { + set_var(lp->ll_name, lp->ll_name_len, rettv, copy); } + *endp = cc; } else if (tv_check_lock(lp->ll_newkey == NULL ? lp->ll_tv->v_lock : lp->ll_tv->vval.v_dict->dv_lock, - lp->ll_name, false)) { + (const char *)lp->ll_name, TV_CSTRING)) { } else if (lp->ll_range) { listitem_T *ll_li = lp->ll_li; int ll_n1 = lp->ll_n1; @@ -2358,7 +2405,8 @@ static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, int copy, ch // Check whether any of the list items is locked for (listitem_T *ri = rettv->vval.v_list->lv_first; ri != NULL && ll_li != NULL; ) { - if (tv_check_lock(ll_li->li_tv.v_lock, lp->ll_name, false)) { + if (tv_check_lock(ll_li->li_tv.v_lock, (const char *)lp->ll_name, + TV_CSTRING)) { return; } ri = ri->li_next; @@ -2373,18 +2421,18 @@ static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, int copy, ch * Assign the List values to the list items. */ for (ri = rettv->vval.v_list->lv_first; ri != NULL; ) { - if (op != NULL && *op != '=') - tv_op(&lp->ll_li->li_tv, &ri->li_tv, op); - else { - clear_tv(&lp->ll_li->li_tv); - copy_tv(&ri->li_tv, &lp->ll_li->li_tv); + if (op != NULL && *op != '=') { + eexe_mod_op(&lp->ll_li->li_tv, &ri->li_tv, (const char *)op); + } else { + tv_clear(&lp->ll_li->li_tv); + tv_copy(&ri->li_tv, &lp->ll_li->li_tv); } ri = ri->li_next; if (ri == NULL || (!lp->ll_empty2 && lp->ll_n2 == lp->ll_n1)) break; if (lp->ll_li->li_next == NULL) { - /* Need to add an empty item. */ - list_append_number(lp->ll_list, 0); + // Need to add an empty item. + tv_list_append_number(lp->ll_list, 0); assert(lp->ll_li->li_next); } lp->ll_li = lp->ll_li->li_next; @@ -2397,198 +2445,60 @@ 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; + typval_T oldtv = TV_INITIAL_VALUE; dict_T *dict = lp->ll_dict; - bool watched = is_watched(dict); + bool watched = tv_dict_is_watched(dict); - if (watched) { - init_tv(&oldtv); - } - - /* - * Assign to a List or Dictionary item. - */ + // Assign to a List or Dictionary item. if (lp->ll_newkey != NULL) { if (op != NULL && *op != '=') { EMSG2(_(e_letwrong), op); return; } - /* Need to add an item to the Dictionary. */ - di = dictitem_alloc(lp->ll_newkey); - if (dict_add(lp->ll_tv->vval.v_dict, di) == FAIL) { + // Need to add an item to the Dictionary. + di = tv_dict_item_alloc((const char *)lp->ll_newkey); + if (tv_dict_add(lp->ll_tv->vval.v_dict, di) == FAIL) { xfree(di); return; } lp->ll_tv = &di->di_tv; } else { if (watched) { - copy_tv(lp->ll_tv, &oldtv); + tv_copy(lp->ll_tv, &oldtv); } if (op != NULL && *op != '=') { - tv_op(lp->ll_tv, rettv, op); + eexe_mod_op(lp->ll_tv, rettv, (const char *)op); goto notify; } else { - clear_tv(lp->ll_tv); + tv_clear(lp->ll_tv); } } // Assign the value to the variable or list item. if (copy) { - copy_tv(rettv, lp->ll_tv); + tv_copy(rettv, lp->ll_tv); } else { *lp->ll_tv = *rettv; lp->ll_tv->v_lock = 0; - init_tv(rettv); + tv_init(rettv); } notify: if (watched) { if (oldtv.v_type == VAR_UNKNOWN) { - dictwatcher_notify(dict, (char *)lp->ll_newkey, lp->ll_tv, NULL); + tv_dict_watcher_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); - } - } - } -} - -/* - * Handle "tv1 += tv2", "tv1 -= tv2" and "tv1 .= tv2" - * Returns OK or FAIL. - */ -static int tv_op(typval_T *tv1, typval_T *tv2, char_u *op) -{ - long n; - char_u numbuf[NUMBUFLEN]; - char_u *s; - - // Can't do anything with a Funcref, a Dict or special value on the right. - if (tv2->v_type != VAR_FUNC && tv2->v_type != VAR_DICT) { - switch (tv1->v_type) { - case VAR_DICT: - case VAR_FUNC: - case VAR_PARTIAL: - case VAR_SPECIAL: - break; - - case VAR_LIST: - if (*op != '+' || tv2->v_type != VAR_LIST) - break; - /* List += List */ - if (tv1->vval.v_list != NULL && tv2->vval.v_list != NULL) - list_extend(tv1->vval.v_list, tv2->vval.v_list, NULL); - return OK; - - case VAR_NUMBER: - case VAR_STRING: - if (tv2->v_type == VAR_LIST) - break; - if (*op == '+' || *op == '-') { - /* nr += nr or nr -= nr*/ - n = get_tv_number(tv1); - if (tv2->v_type == VAR_FLOAT) { - float_T f = n; - - if (*op == '+') - f += tv2->vval.v_float; - else - f -= tv2->vval.v_float; - clear_tv(tv1); - tv1->v_type = VAR_FLOAT; - tv1->vval.v_float = f; - } else { - if (*op == '+') - n += get_tv_number(tv2); - else - n -= get_tv_number(tv2); - clear_tv(tv1); - tv1->v_type = VAR_NUMBER; - tv1->vval.v_number = n; - } - } else { - if (tv2->v_type == VAR_FLOAT) - break; - - /* str .= str */ - s = get_tv_string(tv1); - s = concat_str(s, get_tv_string_buf(tv2, numbuf)); - clear_tv(tv1); - tv1->v_type = VAR_STRING; - tv1->vval.v_string = s; + tv_dict_watcher_notify(dict, (char *)di->di_key, lp->ll_tv, &oldtv); + tv_clear(&oldtv); } - return OK; - - case VAR_FLOAT: - { - float_T f; - - if (*op == '.' || (tv2->v_type != VAR_FLOAT - && tv2->v_type != VAR_NUMBER - && tv2->v_type != VAR_STRING)) - break; - if (tv2->v_type == VAR_FLOAT) - f = tv2->vval.v_float; - else - f = get_tv_number(tv2); - if (*op == '+') - tv1->vval.v_float += f; - else - tv1->vval.v_float -= f; - } - return OK; - - case VAR_UNKNOWN: - assert(false); } } - - EMSG2(_(e_letwrong), op); - return FAIL; } -/* - * Add a watcher to a list. - */ -void list_add_watch(list_T *l, listwatch_T *lw) -{ - lw->lw_next = l->lv_watch; - l->lv_watch = lw; -} - -/* - * Remove a watcher from a list. - * No warning when it isn't found... - */ -void list_rem_watch(list_T *l, listwatch_T *lwrem) -{ - listwatch_T *lw, **lwp; - - lwp = &l->lv_watch; - for (lw = l->lv_watch; lw != NULL; lw = lw->lw_next) { - if (lw == lwrem) { - *lwp = lw->lw_next; - break; - } - lwp = &lw->lw_next; - } -} - -/* - * Just before removing an item from a list: advance watchers to the next - * item. - */ -static void list_fix_watch(list_T *l, listitem_T *item) -{ - listwatch_T *lw; - - for (lw = l->lv_watch; lw != NULL; lw = lw->lw_next) - if (lw->lw_item == item) - lw->lw_item = item->li_next; -} +// TODO(ZyX-I): move to eval/ex_cmds /* * Evaluate the expression used in a ":for var in expr" command. @@ -2596,14 +2506,14 @@ static void list_fix_watch(list_T *l, listitem_T *item) * Set "*errp" to TRUE for an error, FALSE otherwise; * Return a pointer that holds the info. Null when there is an error. */ -void *eval_for_line(char_u *arg, int *errp, char_u **nextcmdp, int skip) +void *eval_for_line(const char_u *arg, bool *errp, char_u **nextcmdp, int skip) { forinfo_T *fi = xcalloc(1, sizeof(forinfo_T)); - char_u *expr; + const char_u *expr; typval_T tv; list_T *l; - *errp = TRUE; /* default: there is an error */ + *errp = true; // Default: there is an error. expr = skip_var_list(arg, &fi->fi_varcount, &fi->fi_semicolon); if (expr == NULL) @@ -2618,20 +2528,20 @@ void *eval_for_line(char_u *arg, int *errp, char_u **nextcmdp, int skip) if (skip) ++emsg_skip; if (eval0(skipwhite(expr + 2), &tv, nextcmdp, !skip) == OK) { - *errp = FALSE; + *errp = false; if (!skip) { l = tv.vval.v_list; if (tv.v_type != VAR_LIST) { EMSG(_(e_listreq)); - clear_tv(&tv); + tv_clear(&tv); } else if (l == NULL) { // a null list is like an empty list: do nothing - clear_tv(&tv); + tv_clear(&tv); } else { /* No need to increment the refcount, it's already set for the * list being used in "tv". */ fi->fi_list = l; - list_add_watch(l, &fi->fi_lw); + tv_list_watch_add(l, &fi->fi_lw); fi->fi_lw.lw_item = l->lv_first; } } @@ -2642,6 +2552,8 @@ void *eval_for_line(char_u *arg, int *errp, char_u **nextcmdp, int skip) return fi; } +// TODO(ZyX-I): move to eval/ex_cmds + /* * Use the first item in a ":for" list. Advance to the next. * Assign the values to the variable (list). "arg" points to the first one. @@ -2665,6 +2577,8 @@ int next_for_item(void *fi_void, char_u *arg) return result; } +// TODO(ZyX-I): move to eval/ex_cmds + /* * Free the structure used to store info used by ":for". */ @@ -2673,8 +2587,8 @@ void free_for_info(void *fi_void) forinfo_T *fi = (forinfo_T *)fi_void; if (fi != NULL && fi->fi_list != NULL) { - list_rem_watch(fi->fi_list, &fi->fi_lw); - list_unref(fi->fi_list); + tv_list_watch_remove(fi->fi_list, &fi->fi_lw); + tv_list_unref(fi->fi_list); } xfree(fi); } @@ -2762,6 +2676,7 @@ void set_context_for_expression(expand_T *xp, char_u *arg, cmdidx_T cmdidx) xp->xp_pattern = arg; } +// TODO(ZyX-I): move to eval/ex_cmds /* * ":1,25call func(arg1, arg2)" function call. @@ -2781,13 +2696,14 @@ void ex_call(exarg_T *eap) partial_T *partial = NULL; if (eap->skip) { - /* trans_function_name() doesn't work well when skipping, use eval0() - * instead to skip to any following command, e.g. for: - * :if 0 | call dict.foo().bar() | endif */ - ++emsg_skip; - if (eval0(eap->arg, &rettv, &eap->nextcmd, FALSE) != FAIL) - clear_tv(&rettv); - --emsg_skip; + // trans_function_name() doesn't work well when skipping, use eval0() + // instead to skip to any following command, e.g. for: + // :if 0 | call dict.foo().bar() | endif. + emsg_skip++; + if (eval0(eap->arg, &rettv, &eap->nextcmd, false) != FAIL) { + tv_clear(&rettv); + } + emsg_skip--; return; } @@ -2809,13 +2725,13 @@ void ex_call(exarg_T *eap) // contents. For VAR_PARTIAL get its partial, unless we already have one // from trans_function_name(). len = (int)STRLEN(tofree); - name = deref_func_name(tofree, &len, + name = deref_func_name((const char *)tofree, &len, partial != NULL ? NULL : &partial, false); /* Skip white space to allow ":call func ()". Not good, but required for * backward compatibility. */ startarg = skipwhite(arg); - rettv.v_type = VAR_UNKNOWN; /* clear_tv() uses this */ + rettv.v_type = VAR_UNKNOWN; // tv_clear() uses this. if (*startarg != '(') { EMSG2(_("E107: Missing parentheses: %s"), eap->arg); @@ -2829,12 +2745,13 @@ void ex_call(exarg_T *eap) * call, and the loop is broken. */ if (eap->skip) { - ++emsg_skip; - lnum = eap->line2; /* do it once, also with an invalid range */ - } else + emsg_skip++; + lnum = eap->line2; // Do it once, also with an invalid range. + } else { lnum = eap->line1; - for (; lnum <= eap->line2; ++lnum) { - if (!eap->skip && eap->addr_count > 0) { + } + for (; lnum <= eap->line2; lnum++) { + if (!eap->skip && eap->addr_count > 0) { // -V560 curwin->w_cursor.lnum = lnum; curwin->w_cursor.col = 0; curwin->w_cursor.coladd = 0; @@ -2847,15 +2764,17 @@ void ex_call(exarg_T *eap) break; } - /* Handle a function returning a Funcref, Dictionary or List. */ - if (handle_subscript(&arg, &rettv, !eap->skip, TRUE) == FAIL) { - failed = TRUE; + // Handle a function returning a Funcref, Dictionary or List. + if (handle_subscript((const char **)&arg, &rettv, !eap->skip, true) + == FAIL) { + failed = true; break; } - clear_tv(&rettv); - if (doesrange || eap->skip) + tv_clear(&rettv); + if (doesrange || eap->skip) { // -V560 break; + } /* Stop when immediately aborting on error, or when an interrupt * occurred or an exception was thrown but not caught. @@ -2877,10 +2796,12 @@ void ex_call(exarg_T *eap) } end: - dict_unref(fudi.fd_dict); + tv_dict_unref(fudi.fd_dict); xfree(tofree); } +// TODO(ZyX-I): move to eval/ex_cmds + /* * ":unlet[!] var1 ... " command. */ @@ -2889,6 +2810,8 @@ void ex_unlet(exarg_T *eap) ex_unletlock(eap, eap->arg, 0); } +// TODO(ZyX-I): move to eval/ex_cmds + /* * ":lockvar" and ":unlockvar" commands */ @@ -2907,22 +2830,25 @@ void ex_lockvar(exarg_T *eap) ex_unletlock(eap, arg, deep); } +// TODO(ZyX-I): move to eval/ex_cmds + /* * ":unlet", ":lockvar" and ":unlockvar" are quite similar. */ static void ex_unletlock(exarg_T *eap, char_u *argstart, int deep) { char_u *arg = argstart; - char_u *name_end; - int error = FALSE; + bool error = false; lval_T lv; do { - /* Parse the name and find the end. */ - name_end = get_lval(arg, NULL, &lv, TRUE, eap->skip || error, 0, - FNE_CHECK_START); - if (lv.ll_name == NULL) - error = TRUE; /* error but continue parsing */ + // Parse the name and find the end. + char_u *const name_end = (char_u *)get_lval(arg, NULL, &lv, true, + eap->skip || error, + 0, FNE_CHECK_START); + if (lv.ll_name == NULL) { + error = true; // error, but continue parsing. + } if (name_end == NULL || (!ascii_iswhite(*name_end) && !ends_excmd(*name_end))) { if (name_end != NULL) { @@ -2940,8 +2866,9 @@ static void ex_unletlock(exarg_T *eap, char_u *argstart, int deep) error = TRUE; } else { if (do_lock_var(&lv, name_end, deep, - eap->cmdidx == CMD_lockvar) == FAIL) - error = TRUE; + eap->cmdidx == CMD_lockvar) == FAIL) { + error = true; + } } } @@ -2954,7 +2881,9 @@ static void ex_unletlock(exarg_T *eap, char_u *argstart, int deep) eap->nextcmd = check_nextcmd(arg); } -static int do_unlet_var(lval_T *lp, char_u *name_end, int forceit) +// TODO(ZyX-I): move to eval/ex_cmds + +static int do_unlet_var(lval_T *const lp, char_u *const name_end, int forceit) { int ret = OK; int cc; @@ -2963,16 +2892,18 @@ static int do_unlet_var(lval_T *lp, char_u *name_end, int forceit) cc = *name_end; *name_end = NUL; - /* Normal name or expanded name. */ - if (check_changedtick(lp->ll_name)) - ret = FAIL; - else if (do_unlet(lp->ll_name, forceit) == FAIL) + // Normal name or expanded name. + if (do_unlet(lp->ll_name, lp->ll_name_len, forceit) == FAIL) { ret = FAIL; + } *name_end = cc; } else if ((lp->ll_list != NULL - && tv_check_lock(lp->ll_list->lv_lock, lp->ll_name, false)) + && tv_check_lock(lp->ll_list->lv_lock, (const char *)lp->ll_name, + lp->ll_name_len)) || (lp->ll_dict != NULL - && tv_check_lock(lp->ll_dict->dv_lock, lp->ll_name, false))) { + && tv_check_lock(lp->ll_dict->dv_lock, + (const char *)lp->ll_name, + lp->ll_name_len))) { return FAIL; } else if (lp->ll_range) { listitem_T *li; @@ -2981,7 +2912,8 @@ static int do_unlet_var(lval_T *lp, char_u *name_end, int forceit) while (ll_li != NULL && (lp->ll_empty2 || lp->ll_n2 >= ll_n1)) { li = ll_li->li_next; - if (tv_check_lock(ll_li->li_tv.v_lock, lp->ll_name, false)) { + if (tv_check_lock(ll_li->li_tv.v_lock, (const char *)lp->ll_name, + lp->ll_name_len)) { return false; } ll_li = li; @@ -2991,33 +2923,33 @@ static int do_unlet_var(lval_T *lp, char_u *name_end, int forceit) /* Delete a range of List items. */ while (lp->ll_li != NULL && (lp->ll_empty2 || lp->ll_n2 >= lp->ll_n1)) { li = lp->ll_li->li_next; - listitem_remove(lp->ll_list, lp->ll_li); + tv_list_item_remove(lp->ll_list, lp->ll_li); lp->ll_li = li; ++lp->ll_n1; } } else { if (lp->ll_list != NULL) { // unlet a List item. - listitem_remove(lp->ll_list, lp->ll_li); + tv_list_item_remove(lp->ll_list, lp->ll_li); } else { // unlet a Dictionary item. dict_T *d = lp->ll_dict; dictitem_T *di = lp->ll_di; - bool watched = is_watched(d); + bool watched = tv_dict_is_watched(d); char *key = NULL; typval_T oldtv; if (watched) { - copy_tv(&di->di_tv, &oldtv); + tv_copy(&di->di_tv, &oldtv); // need to save key because dictitem_remove will free it key = xstrdup((char *)di->di_key); } - dictitem_remove(d, di); + tv_dict_item_remove(d, di); if (watched) { - dictwatcher_notify(d, key, NULL, &oldtv); - clear_tv(&oldtv); + tv_dict_watcher_notify(d, key, NULL, &oldtv); + tv_clear(&oldtv); xfree(key); } } @@ -3026,21 +2958,24 @@ static int do_unlet_var(lval_T *lp, char_u *name_end, int forceit) return ret; } -/* - * "unlet" a variable. Return OK if it existed, FAIL if not. - * When "forceit" is TRUE don't complain if the variable doesn't exist. - */ -int do_unlet(char_u *name, int forceit) +// TODO(ZyX-I): move to eval/ex_cmds + +/// unlet a variable +/// +/// @param[in] name Variable name to unlet. +/// @param[in] name_len Variable name length. +/// @param[in] fonceit If true, do not complain if variable doesnโt exist. +/// +/// @return OK if it existed, FAIL otherwise. +int do_unlet(const char *const name, const size_t name_len, const int forceit) + FUNC_ATTR_NONNULL_ALL { - hashtab_T *ht; - hashitem_T *hi; - char_u *varname; - dict_T *d; - dictitem_T *di; + const char *varname; dict_T *dict; - ht = find_var_ht_dict(name, &varname, &dict); + hashtab_T *ht = find_var_ht_dict(name, name_len, &varname, &dict); if (ht != NULL && *varname != NUL) { + dict_T *d; if (ht == &globvarht) { d = &globvardict; } else if (current_funccal != NULL @@ -3049,38 +2984,41 @@ int do_unlet(char_u *name, int forceit) } else if (ht == &compat_hashtab) { d = &vimvardict; } else { - di = find_var_in_ht(ht, *name, (char_u *)"", false); + dictitem_T *const di = find_var_in_ht(ht, *name, "", 0, false); d = di->di_tv.vval.v_dict; } if (d == NULL) { EMSG2(_(e_intern2), "do_unlet()"); return FAIL; } - hi = hash_find(ht, varname); - if (!HASHITEM_EMPTY(hi)) { - di = HI2DI(hi); - if (var_check_fixed(di->di_flags, name, false) - || var_check_ro(di->di_flags, name, false) - || tv_check_lock(d->dv_lock, name, false)) { + hashitem_T *hi = hash_find(ht, (const char_u *)varname); + if (HASHITEM_EMPTY(hi)) { + hi = find_hi_in_scoped_ht((const char *)name, &ht); + } + if (hi != NULL && !HASHITEM_EMPTY(hi)) { + dictitem_T *const di = TV_DICT_HI2DI(hi); + if (var_check_fixed(di->di_flags, (const char *)name, TV_CSTRING) + || var_check_ro(di->di_flags, (const char *)name, TV_CSTRING) + || tv_check_lock(d->dv_lock, (const char *)name, TV_CSTRING)) { return FAIL; } - if (d == NULL || tv_check_lock(d->dv_lock, name, false)) { + if (tv_check_lock(d->dv_lock, (const char *)name, TV_CSTRING)) { return FAIL; } typval_T oldtv; - bool watched = is_watched(dict); + bool watched = tv_dict_is_watched(dict); if (watched) { - copy_tv(&di->di_tv, &oldtv); + tv_copy(&di->di_tv, &oldtv); } delete_var(ht, hi); if (watched) { - dictwatcher_notify(dict, (char *)varname, NULL, &oldtv); - clear_tv(&oldtv); + tv_dict_watcher_notify(dict, varname, NULL, &oldtv); + tv_clear(&oldtv); } return OK; } @@ -3091,162 +3029,74 @@ int do_unlet(char_u *name, int forceit) return FAIL; } +// TODO(ZyX-I): move to eval/ex_cmds + /* * Lock or unlock variable indicated by "lp". * "deep" is the levels to go (-1 for unlimited); * "lock" is TRUE for ":lockvar", FALSE for ":unlockvar". */ -static int do_lock_var(lval_T *lp, char_u *name_end, int deep, int lock) +static int do_lock_var(lval_T *lp, char_u *const name_end, const int deep, + const bool lock) { int ret = OK; - int cc; - dictitem_T *di; - if (deep == 0) /* nothing to do */ + if (deep == 0) { // Nothing to do. return OK; + } if (lp->ll_tv == NULL) { - cc = *name_end; - *name_end = NUL; - - /* Normal name or expanded name. */ - if (check_changedtick(lp->ll_name)) + // Normal name or expanded name. + dictitem_T *const di = find_var( + (const char *)lp->ll_name, lp->ll_name_len, NULL, + true); + if (di == NULL) { ret = FAIL; - else { - di = find_var(lp->ll_name, NULL, TRUE); - if (di == NULL) - ret = FAIL; - else { - if (lock) - di->di_flags |= DI_FLAGS_LOCK; - else - di->di_flags &= ~DI_FLAGS_LOCK; - item_lock(&di->di_tv, deep, lock); + } else if ((di->di_flags & DI_FLAGS_FIX) + && di->di_tv.v_type != VAR_DICT + && di->di_tv.v_type != VAR_LIST) { + // For historical reasons this error is not given for Lists and + // Dictionaries. E.g. b: dictionary may be locked/unlocked. + emsgf(_("E940: Cannot lock or unlock variable %s"), lp->ll_name); + } else { + if (lock) { + di->di_flags |= DI_FLAGS_LOCK; + } else { + di->di_flags &= ~DI_FLAGS_LOCK; } + tv_item_lock(&di->di_tv, deep, lock); } - *name_end = cc; } else if (lp->ll_range) { listitem_T *li = lp->ll_li; /* (un)lock a range of List items. */ while (li != NULL && (lp->ll_empty2 || lp->ll_n2 >= lp->ll_n1)) { - item_lock(&li->li_tv, deep, lock); + tv_item_lock(&li->li_tv, deep, lock); li = li->li_next; ++lp->ll_n1; } } else if (lp->ll_list != NULL) { // (un)lock a List item. - item_lock(&lp->ll_li->li_tv, deep, lock); + tv_item_lock(&lp->ll_li->li_tv, deep, lock); } else { // (un)lock a Dictionary item. - item_lock(&lp->ll_di->di_tv, deep, lock); + tv_item_lock(&lp->ll_di->di_tv, deep, lock); } return ret; } /* - * Lock or unlock an item. "deep" is nr of levels to go. - */ -static void item_lock(typval_T *tv, int deep, int lock) -{ - static int recurse = 0; - list_T *l; - listitem_T *li; - dict_T *d; - hashitem_T *hi; - int todo; - - if (recurse >= DICT_MAXNEST) { - EMSG(_("E743: variable nested too deep for (un)lock")); - return; - } - if (deep == 0) - return; - ++recurse; - - /* lock/unlock the item itself */ - if (lock) - tv->v_lock |= VAR_LOCKED; - else - tv->v_lock &= ~VAR_LOCKED; - - switch (tv->v_type) { - case VAR_LIST: - if ((l = tv->vval.v_list) != NULL) { - if (lock) - l->lv_lock |= VAR_LOCKED; - else - l->lv_lock &= ~VAR_LOCKED; - if (deep < 0 || deep > 1) - /* recursive: lock/unlock the items the List contains */ - for (li = l->lv_first; li != NULL; li = li->li_next) - item_lock(&li->li_tv, deep - 1, lock); - } - break; - case VAR_DICT: - if ((d = tv->vval.v_dict) != NULL) { - if (lock) - d->dv_lock |= VAR_LOCKED; - else - d->dv_lock &= ~VAR_LOCKED; - if (deep < 0 || deep > 1) { - /* recursive: lock/unlock the items the List contains */ - todo = (int)d->dv_hashtab.ht_used; - for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi) { - if (!HASHITEM_EMPTY(hi)) { - --todo; - item_lock(&HI2DI(hi)->di_tv, deep - 1, lock); - } - } - } - } - break; - case VAR_NUMBER: - case VAR_FLOAT: - case VAR_STRING: - case VAR_FUNC: - case VAR_PARTIAL: - case VAR_SPECIAL: - break; - case VAR_UNKNOWN: - assert(false); - } - --recurse; -} - -/* - * Return TRUE if typeval "tv" is locked: Either that value is locked itself - * or it refers to a List or Dictionary that is locked. - */ -static int tv_islocked(typval_T *tv) -{ - return (tv->v_lock & VAR_LOCKED) - || (tv->v_type == VAR_LIST - && tv->vval.v_list != NULL - && (tv->vval.v_list->lv_lock & VAR_LOCKED)) - || (tv->v_type == VAR_DICT - && tv->vval.v_dict != NULL - && (tv->vval.v_dict->dv_lock & VAR_LOCKED)); -} - -/* * Delete all "menutrans_" variables. */ void del_menutrans_vars(void) { - hashitem_T *hi; - int todo; - hash_lock(&globvarht); - todo = (int)globvarht.ht_used; - for (hi = globvarht.ht_array; todo > 0 && !got_int; ++hi) { - if (!HASHITEM_EMPTY(hi)) { - --todo; - if (STRNCMP(HI2DI(hi)->di_key, "menutrans_", 10) == 0) - delete_var(&globvarht, hi); + HASHTAB_ITER(&globvarht, hi, { + if (STRNCMP(hi->hi_key, "menutrans_", 10) == 0) { + delete_var(&globvarht, hi); } - } + }); hash_unlock(&globvarht); } @@ -3322,10 +3172,6 @@ char_u *get_user_var_name(expand_T *xp, int idx) ++hi; return cat_prefix_varname('b', hi->hi_key); } - if (bdone == ht->ht_used) { - ++bdone; - return (char_u *)"b:changedtick"; - } /* w: variables */ ht = &curwin->w_vars->dv_hashtab; @@ -3362,6 +3208,7 @@ char_u *get_user_var_name(expand_T *xp, int idx) return NULL; } +// TODO(ZyX-I): move to eval/expressions /// Return TRUE if "pat" matches "text". /// Does not use 'cpo' and always uses 'magic'. @@ -3398,6 +3245,8 @@ typedef enum { , TYPE_NOMATCH /* !~ */ } exptype_T; +// TODO(ZyX-I): move to eval/expressions + /* * The "evaluate" argument: When FALSE, the argument is only parsed but not * executed. The function may return OK, but the rettv will be of type @@ -3411,7 +3260,7 @@ typedef enum { * Note: "rettv.v_lock" is not set. * Return OK or FAIL. */ -static int eval0(char_u *arg, typval_T *rettv, char_u **nextcmd, int evaluate) +int eval0(char_u *arg, typval_T *rettv, char_u **nextcmd, int evaluate) { int ret; char_u *p; @@ -3419,15 +3268,15 @@ static int eval0(char_u *arg, typval_T *rettv, char_u **nextcmd, int evaluate) p = skipwhite(arg); ret = eval1(&p, rettv, evaluate); if (ret == FAIL || !ends_excmd(*p)) { - if (ret != FAIL) - clear_tv(rettv); - /* - * Report the invalid expression unless the expression evaluation has - * been cancelled due to an aborting error, an interrupt, or an - * exception. - */ - if (!aborting()) - EMSG2(_(e_invexpr2), arg); + if (ret != FAIL) { + tv_clear(rettv); + } + // Report the invalid expression unless the expression evaluation has + // been cancelled due to an aborting error, an interrupt, or an + // exception. + if (!aborting()) { + emsgf(_(e_invexpr2), arg); + } ret = FAIL; } if (nextcmd != NULL) @@ -3436,6 +3285,8 @@ static int eval0(char_u *arg, typval_T *rettv, char_u **nextcmd, int evaluate) return ret; } +// TODO(ZyX-I): move to eval/expressions + /* * Handle top level expression: * expr2 ? expr1 : expr1 @@ -3461,13 +3312,15 @@ static int eval1(char_u **arg, typval_T *rettv, int evaluate) if ((*arg)[0] == '?') { result = FALSE; if (evaluate) { - int error = FALSE; + bool error = false; - if (get_tv_number_chk(rettv, &error) != 0) - result = TRUE; - clear_tv(rettv); - if (error) + if (tv_get_number_chk(rettv, &error) != 0) { + result = true; + } + tv_clear(rettv); + if (error) { return FAIL; + } } /* @@ -3481,9 +3334,10 @@ static int eval1(char_u **arg, typval_T *rettv, int evaluate) * Check for the ":". */ if ((*arg)[0] != ':') { - EMSG(_("E109: Missing ':' after '?'")); - if (evaluate && result) - clear_tv(rettv); + emsgf(_("E109: Missing ':' after '?'")); + if (evaluate && result) { + tv_clear(rettv); + } return FAIL; } @@ -3491,9 +3345,10 @@ static int eval1(char_u **arg, typval_T *rettv, int evaluate) * Get the third variable. */ *arg = skipwhite(*arg + 1); - if (eval1(arg, &var2, evaluate && !result) == FAIL) { /* recursive! */ - if (evaluate && result) - clear_tv(rettv); + if (eval1(arg, &var2, evaluate && !result) == FAIL) { // Recursive! + if (evaluate && result) { + tv_clear(rettv); + } return FAIL; } if (evaluate && !result) @@ -3503,6 +3358,8 @@ static int eval1(char_u **arg, typval_T *rettv, int evaluate) return OK; } +// TODO(ZyX-I): move to eval/expressions + /* * Handle first level expression: * expr2 || expr2 || expr2 logical OR @@ -3517,7 +3374,7 @@ static int eval2(char_u **arg, typval_T *rettv, int evaluate) typval_T var2; long result; int first; - int error = FALSE; + bool error = false; /* * Get the first variable. @@ -3532,12 +3389,14 @@ static int eval2(char_u **arg, typval_T *rettv, int evaluate) result = FALSE; while ((*arg)[0] == '|' && (*arg)[1] == '|') { if (evaluate && first) { - if (get_tv_number_chk(rettv, &error) != 0) - result = TRUE; - clear_tv(rettv); - if (error) + if (tv_get_number_chk(rettv, &error) != 0) { + result = true; + } + tv_clear(rettv); + if (error) { return FAIL; - first = FALSE; + } + first = false; } /* @@ -3551,11 +3410,13 @@ static int eval2(char_u **arg, typval_T *rettv, int evaluate) * Compute the result. */ if (evaluate && !result) { - if (get_tv_number_chk(&var2, &error) != 0) - result = TRUE; - clear_tv(&var2); - if (error) + if (tv_get_number_chk(&var2, &error) != 0) { + result = true; + } + tv_clear(&var2); + if (error) { return FAIL; + } } if (evaluate) { rettv->v_type = VAR_NUMBER; @@ -3566,6 +3427,8 @@ static int eval2(char_u **arg, typval_T *rettv, int evaluate) return OK; } +// TODO(ZyX-I): move to eval/expressions + /* * Handle second level expression: * expr3 && expr3 && expr3 logical AND @@ -3580,7 +3443,7 @@ static int eval3(char_u **arg, typval_T *rettv, int evaluate) typval_T var2; long result; int first; - int error = FALSE; + bool error = false; /* * Get the first variable. @@ -3595,12 +3458,14 @@ static int eval3(char_u **arg, typval_T *rettv, int evaluate) result = TRUE; while ((*arg)[0] == '&' && (*arg)[1] == '&') { if (evaluate && first) { - if (get_tv_number_chk(rettv, &error) == 0) - result = FALSE; - clear_tv(rettv); - if (error) + if (tv_get_number_chk(rettv, &error) == 0) { + result = false; + } + tv_clear(rettv); + if (error) { return FAIL; - first = FALSE; + } + first = false; } /* @@ -3614,11 +3479,13 @@ static int eval3(char_u **arg, typval_T *rettv, int evaluate) * Compute the result. */ if (evaluate && result) { - if (get_tv_number_chk(&var2, &error) == 0) - result = FALSE; - clear_tv(&var2); - if (error) + if (tv_get_number_chk(&var2, &error) == 0) { + result = false; + } + tv_clear(&var2); + if (error) { return FAIL; + } } if (evaluate) { rettv->v_type = VAR_NUMBER; @@ -3629,6 +3496,8 @@ static int eval3(char_u **arg, typval_T *rettv, int evaluate) return OK; } +// TODO(ZyX-I): move to eval/expressions + /* * Handle third level expression: * var1 == var2 @@ -3655,9 +3524,7 @@ static int eval4(char_u **arg, typval_T *rettv, int evaluate) exptype_T type = TYPE_UNKNOWN; int type_is = FALSE; /* TRUE for "is" and "isnot" */ int len = 2; - long n1, n2; - char_u *s1, *s2; - char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN]; + varnumber_T n1, n2; int ic; /* @@ -3725,7 +3592,7 @@ static int eval4(char_u **arg, typval_T *rettv, int evaluate) */ *arg = skipwhite(p + len); if (eval5(arg, &var2, evaluate) == FAIL) { - clear_tv(rettv); + tv_clear(rettv); return FAIL; } @@ -3747,15 +3614,15 @@ static int eval4(char_u **arg, typval_T *rettv, int evaluate) } else { EMSG(_("E692: Invalid operation for List")); } - clear_tv(rettv); - clear_tv(&var2); + tv_clear(rettv); + tv_clear(&var2); return FAIL; } else { - /* Compare two Lists for being equal or unequal. */ - n1 = list_equal(rettv->vval.v_list, var2.vval.v_list, - ic, FALSE); - if (type == TYPE_NEQUAL) + // Compare two Lists for being equal or unequal. + n1 = tv_list_equal(rettv->vval.v_list, var2.vval.v_list, ic, false); + if (type == TYPE_NEQUAL) { n1 = !n1; + } } } else if (rettv->v_type == VAR_DICT || var2.v_type == VAR_DICT) { if (type_is) { @@ -3769,23 +3636,22 @@ static int eval4(char_u **arg, typval_T *rettv, int evaluate) EMSG(_("E735: Can only compare Dictionary with Dictionary")); else EMSG(_("E736: Invalid operation for Dictionary")); - clear_tv(rettv); - clear_tv(&var2); + tv_clear(rettv); + tv_clear(&var2); return FAIL; } else { - /* Compare two Dictionaries for being equal or unequal. */ - n1 = dict_equal(rettv->vval.v_dict, var2.vval.v_dict, - ic, FALSE); - if (type == TYPE_NEQUAL) + // Compare two Dictionaries for being equal or unequal. + n1 = tv_dict_equal(rettv->vval.v_dict, var2.vval.v_dict, + ic, false); + if (type == TYPE_NEQUAL) { n1 = !n1; + } } - } else if (rettv->v_type == VAR_FUNC || var2.v_type == VAR_FUNC - || rettv->v_type == VAR_PARTIAL - || var2.v_type == VAR_PARTIAL) { + } else if (tv_is_func(*rettv) || tv_is_func(var2)) { if (type != TYPE_EQUAL && type != TYPE_NEQUAL) { EMSG(_("E694: Invalid operation for Funcrefs")); - clear_tv(rettv); - clear_tv(&var2); + tv_clear(rettv); + tv_clear(&var2); return FAIL; } if ((rettv->v_type == VAR_PARTIAL @@ -3820,25 +3686,27 @@ static int eval4(char_u **arg, typval_T *rettv, int evaluate) && type != TYPE_MATCH && type != TYPE_NOMATCH) { float_T f1, f2; - if (rettv->v_type == VAR_FLOAT) + if (rettv->v_type == VAR_FLOAT) { f1 = rettv->vval.v_float; - else - f1 = get_tv_number(rettv); - if (var2.v_type == VAR_FLOAT) + } else { + f1 = tv_get_number(rettv); + } + if (var2.v_type == VAR_FLOAT) { f2 = var2.vval.v_float; - else - f2 = get_tv_number(&var2); - n1 = FALSE; + } else { + f2 = tv_get_number(&var2); + } + n1 = false; switch (type) { - case TYPE_EQUAL: n1 = (f1 == f2); break; - case TYPE_NEQUAL: n1 = (f1 != f2); break; - case TYPE_GREATER: n1 = (f1 > f2); break; - case TYPE_GEQUAL: n1 = (f1 >= f2); break; - case TYPE_SMALLER: n1 = (f1 < f2); break; - case TYPE_SEQUAL: n1 = (f1 <= f2); break; - case TYPE_UNKNOWN: - case TYPE_MATCH: - case TYPE_NOMATCH: break; /* avoid gcc warning */ + case TYPE_EQUAL: n1 = (f1 == f2); break; + case TYPE_NEQUAL: n1 = (f1 != f2); break; + case TYPE_GREATER: n1 = (f1 > f2); break; + case TYPE_GEQUAL: n1 = (f1 >= f2); break; + case TYPE_SMALLER: n1 = (f1 < f2); break; + case TYPE_SEQUAL: n1 = (f1 <= f2); break; + case TYPE_UNKNOWN: + case TYPE_MATCH: + case TYPE_NOMATCH: break; } } /* @@ -3847,48 +3715,51 @@ static int eval4(char_u **arg, typval_T *rettv, int evaluate) */ else if ((rettv->v_type == VAR_NUMBER || var2.v_type == VAR_NUMBER) && type != TYPE_MATCH && type != TYPE_NOMATCH) { - n1 = get_tv_number(rettv); - n2 = get_tv_number(&var2); + n1 = tv_get_number(rettv); + n2 = tv_get_number(&var2); switch (type) { - case TYPE_EQUAL: n1 = (n1 == n2); break; - case TYPE_NEQUAL: n1 = (n1 != n2); break; - case TYPE_GREATER: n1 = (n1 > n2); break; - case TYPE_GEQUAL: n1 = (n1 >= n2); break; - case TYPE_SMALLER: n1 = (n1 < n2); break; - case TYPE_SEQUAL: n1 = (n1 <= n2); break; - case TYPE_UNKNOWN: - case TYPE_MATCH: - case TYPE_NOMATCH: break; /* avoid gcc warning */ + case TYPE_EQUAL: n1 = (n1 == n2); break; + case TYPE_NEQUAL: n1 = (n1 != n2); break; + case TYPE_GREATER: n1 = (n1 > n2); break; + case TYPE_GEQUAL: n1 = (n1 >= n2); break; + case TYPE_SMALLER: n1 = (n1 < n2); break; + case TYPE_SEQUAL: n1 = (n1 <= n2); break; + case TYPE_UNKNOWN: + case TYPE_MATCH: + case TYPE_NOMATCH: break; } } else { - s1 = get_tv_string_buf(rettv, buf1); - s2 = get_tv_string_buf(&var2, buf2); - if (type != TYPE_MATCH && type != TYPE_NOMATCH) - i = ic ? mb_stricmp(s1, s2) : STRCMP(s1, s2); - else + char buf1[NUMBUFLEN]; + char buf2[NUMBUFLEN]; + const char *const s1 = tv_get_string_buf(rettv, buf1); + const char *const s2 = tv_get_string_buf(&var2, buf2); + if (type != TYPE_MATCH && type != TYPE_NOMATCH) { + i = mb_strcmp_ic((bool)ic, s1, s2); + } else { i = 0; - n1 = FALSE; + } + n1 = false; switch (type) { - case TYPE_EQUAL: n1 = (i == 0); break; - case TYPE_NEQUAL: n1 = (i != 0); break; - case TYPE_GREATER: n1 = (i > 0); break; - case TYPE_GEQUAL: n1 = (i >= 0); break; - case TYPE_SMALLER: n1 = (i < 0); break; - case TYPE_SEQUAL: n1 = (i <= 0); break; - - case TYPE_MATCH: - case TYPE_NOMATCH: - n1 = pattern_match(s2, s1, ic); - if (type == TYPE_NOMATCH) { - n1 = !n1; + case TYPE_EQUAL: n1 = (i == 0); break; + case TYPE_NEQUAL: n1 = (i != 0); break; + case TYPE_GREATER: n1 = (i > 0); break; + case TYPE_GEQUAL: n1 = (i >= 0); break; + case TYPE_SMALLER: n1 = (i < 0); break; + case TYPE_SEQUAL: n1 = (i <= 0); break; + + case TYPE_MATCH: + case TYPE_NOMATCH: { + n1 = pattern_match((char_u *)s2, (char_u *)s1, ic); + if (type == TYPE_NOMATCH) { + n1 = !n1; + } + break; } - break; - - case TYPE_UNKNOWN: break; /* avoid gcc warning */ + case TYPE_UNKNOWN: break; // Avoid gcc warning. } } - clear_tv(rettv); - clear_tv(&var2); + tv_clear(rettv); + tv_clear(&var2); rettv->v_type = VAR_NUMBER; rettv->vval.v_number = n1; } @@ -3897,6 +3768,8 @@ static int eval4(char_u **arg, typval_T *rettv, int evaluate) return OK; } +// TODO(ZyX-I): move to eval/expressions + /* * Handle fourth level expression: * + number addition @@ -3913,10 +3786,8 @@ static int eval5(char_u **arg, typval_T *rettv, int evaluate) typval_T var2; typval_T var3; int op; - long n1, n2; + varnumber_T n1, n2; float_T f1 = 0, f2 = 0; - char_u *s1, *s2; - char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN]; char_u *p; /* @@ -3934,17 +3805,16 @@ static int eval5(char_u **arg, typval_T *rettv, int evaluate) break; if ((op != '+' || rettv->v_type != VAR_LIST) - && (op == '.' || rettv->v_type != VAR_FLOAT) - ) { - /* For "list + ...", an illegal use of the first operand as - * a number cannot be determined before evaluating the 2nd - * operand: if this is also a list, all is ok. - * For "something . ...", "something - ..." or "non-list + ...", - * we know that the first operand needs to be a string or number - * without evaluating the 2nd operand. So check before to avoid - * side effects after an error. */ - if (evaluate && get_tv_string_chk(rettv) == NULL) { - clear_tv(rettv); + && (op == '.' || rettv->v_type != VAR_FLOAT)) { + // For "list + ...", an illegal use of the first operand as + // a number cannot be determined before evaluating the 2nd + // operand: if this is also a list, all is ok. + // For "something . ...", "something - ..." or "non-list + ...", + // we know that the first operand needs to be a string or number + // without evaluating the 2nd operand. So check before to avoid + // side effects after an error. + if (evaluate && !tv_check_str(rettv)) { + tv_clear(rettv); return FAIL; } } @@ -3954,7 +3824,7 @@ static int eval5(char_u **arg, typval_T *rettv, int evaluate) */ *arg = skipwhite(*arg + 1); if (eval6(arg, &var2, evaluate, op == '.') == FAIL) { - clear_tv(rettv); + tv_clear(rettv); return FAIL; } @@ -3963,41 +3833,44 @@ static int eval5(char_u **arg, typval_T *rettv, int evaluate) * Compute the result. */ if (op == '.') { - s1 = get_tv_string_buf(rettv, buf1); /* already checked */ - s2 = get_tv_string_buf_chk(&var2, buf2); - if (s2 == NULL) { /* type error ? */ - clear_tv(rettv); - clear_tv(&var2); + char buf1[NUMBUFLEN]; + char buf2[NUMBUFLEN]; + // s1 already checked + const char *const s1 = tv_get_string_buf(rettv, buf1); + const char *const s2 = tv_get_string_buf_chk(&var2, buf2); + if (s2 == NULL) { // Type error? + tv_clear(rettv); + tv_clear(&var2); return FAIL; } - p = concat_str(s1, s2); - clear_tv(rettv); + p = concat_str((const char_u *)s1, (const char_u *)s2); + tv_clear(rettv); rettv->v_type = VAR_STRING; rettv->vval.v_string = p; } else if (op == '+' && rettv->v_type == VAR_LIST && var2.v_type == VAR_LIST) { - /* concatenate Lists */ - if (list_concat(rettv->vval.v_list, var2.vval.v_list, - &var3) == FAIL) { - clear_tv(rettv); - clear_tv(&var2); + // Concatenate Lists. + if (tv_list_concat(rettv->vval.v_list, var2.vval.v_list, &var3) + == FAIL) { + tv_clear(rettv); + tv_clear(&var2); return FAIL; } - clear_tv(rettv); + tv_clear(rettv); *rettv = var3; } else { - int error = FALSE; + bool error = false; if (rettv->v_type == VAR_FLOAT) { f1 = rettv->vval.v_float; n1 = 0; } else { - n1 = get_tv_number_chk(rettv, &error); + n1 = tv_get_number_chk(rettv, &error); if (error) { /* This can only happen for "list + non-list". For * "non-list + ..." or "something - ...", we returned * before evaluating the 2nd operand. */ - clear_tv(rettv); + tv_clear(rettv); return FAIL; } if (var2.v_type == VAR_FLOAT) @@ -4007,16 +3880,16 @@ static int eval5(char_u **arg, typval_T *rettv, int evaluate) f2 = var2.vval.v_float; n2 = 0; } else { - n2 = get_tv_number_chk(&var2, &error); + n2 = tv_get_number_chk(&var2, &error); if (error) { - clear_tv(rettv); - clear_tv(&var2); + tv_clear(rettv); + tv_clear(&var2); return FAIL; } if (rettv->v_type == VAR_FLOAT) f2 = n2; } - clear_tv(rettv); + tv_clear(rettv); /* If there is a float on either side the result is a float. */ if (rettv->v_type == VAR_FLOAT || var2.v_type == VAR_FLOAT) { @@ -4035,37 +3908,36 @@ static int eval5(char_u **arg, typval_T *rettv, int evaluate) rettv->vval.v_number = n1; } } - clear_tv(&var2); + tv_clear(&var2); } } return OK; } -/* - * Handle fifth level expression: - * * number multiplication - * / number division - * % number modulo - * - * "arg" must point to the first non-white of the expression. - * "arg" is advanced to the next non-white after the recognized expression. - * - * Return OK or FAIL. - */ -static int -eval6 ( - char_u **arg, - typval_T *rettv, - int evaluate, - int want_string /* after "." operator */ -) +// TODO(ZyX-I): move to eval/expressions + +/// Handle fifth level expression: +/// - * number multiplication +/// - / number division +/// - % number modulo +/// +/// @param[in,out] arg Points to the first non-whitespace character of the +/// expression. Is advanced to the next non-whitespace +/// character after the recognized expression. +/// @param[out] rettv Location where result is saved. +/// @param[in] evaluate If not true, rettv is not populated. +/// @param[in] want_string True if "." is string_concatenation, otherwise +/// float +/// @return OK or FAIL. +static int eval6(char_u **arg, typval_T *rettv, int evaluate, int want_string) + FUNC_ATTR_NO_SANITIZE_UNDEFINED { typval_T var2; int op; - long n1, n2; - int use_float = FALSE; + varnumber_T n1, n2; + bool use_float = false; float_T f1 = 0, f2; - int error = FALSE; + bool error = false; /* * Get the first variable. @@ -4084,15 +3956,18 @@ eval6 ( if (evaluate) { if (rettv->v_type == VAR_FLOAT) { f1 = rettv->vval.v_float; - use_float = TRUE; + use_float = true; n1 = 0; - } else - n1 = get_tv_number_chk(rettv, &error); - clear_tv(rettv); - if (error) + } else { + n1 = tv_get_number_chk(rettv, &error); + } + tv_clear(rettv); + if (error) { return FAIL; - } else + } + } else { n1 = 0; + } /* * Get the second variable. @@ -4105,17 +3980,19 @@ eval6 ( if (var2.v_type == VAR_FLOAT) { if (!use_float) { f1 = n1; - use_float = TRUE; + use_float = true; } f2 = var2.vval.v_float; n2 = 0; } else { - n2 = get_tv_number_chk(&var2, &error); - clear_tv(&var2); - if (error) + n2 = tv_get_number_chk(&var2, &error); + tv_clear(&var2); + if (error) { return FAIL; - if (use_float) + } + if (use_float) { f2 = n2; + } } /* @@ -4146,18 +4023,20 @@ eval6 ( rettv->v_type = VAR_FLOAT; rettv->vval.v_float = f1; } else { - if (op == '*') + if (op == '*') { n1 = n1 * n2; - else if (op == '/') { - if (n2 == 0) { /* give an error message? */ - if (n1 == 0) - n1 = -0x7fffffffL - 1L; /* similar to NaN */ - else if (n1 < 0) - n1 = -0x7fffffffL; - else - n1 = 0x7fffffffL; - } else + } else if (op == '/') { + if (n2 == 0) { // give an error message? + if (n1 == 0) { + n1 = VARNUMBER_MIN; // similar to NaN + } else if (n1 < 0) { + n1 = -VARNUMBER_MAX; + } else { + n1 = VARNUMBER_MAX; + } + } else { n1 = n1 / n2; + } } else { if (n2 == 0) /* give an error message? */ n1 = 0; @@ -4173,6 +4052,8 @@ eval6 ( return OK; } +// TODO(ZyX-I): move to eval/expressions + // Handle sixth level expression: // number number constant // "string" string constant @@ -4204,18 +4085,18 @@ static int eval7( int want_string // after "." operator ) { - long n; + varnumber_T n; int len; char_u *s; char_u *start_leader, *end_leader; int ret = OK; char_u *alias; - // Initialise variable so that clear_tv() can't mistake this for a + // Initialise variable so that tv_clear() can't mistake this for a // string and free a string that isn't there. rettv->v_type = VAR_UNKNOWN; - // Skip '!' and '-' characters. They are handled later. + // Skip '!', '-' and '+' characters. They are handled later. start_leader = *arg; while (**arg == '!' || **arg == '-' || **arg == '+') { *arg = skipwhite(*arg + 1); @@ -4292,14 +4173,19 @@ static int eval7( case '[': ret = get_list_tv(arg, rettv, evaluate); break; + // Lambda: {arg, arg -> expr} // Dictionary: {key: val, key: val} - case '{': ret = get_dict_tv(arg, rettv, evaluate); + case '{': ret = get_lambda_tv(arg, rettv, evaluate); + if (ret == NOTDONE) { + ret = get_dict_tv(arg, rettv, evaluate); + } break; // Option value: &name - case '&': ret = get_option_tv(arg, rettv, evaluate); + case '&': { + ret = get_option_tv((const char **)arg, rettv, evaluate); break; - + } // Environment variable: $VAR. case '$': ret = get_env_tv(arg, rettv, evaluate); break; @@ -4322,7 +4208,7 @@ static int eval7( ++*arg; } else if (ret == OK) { EMSG(_("E110: Missing ')'")); - clear_tv(rettv); + tv_clear(rettv); ret = FAIL; } break; @@ -4335,7 +4221,7 @@ static int eval7( // Must be a variable or function name. // Can also be a curly-braces kind of name: {expr}. s = *arg; - len = get_name_len(arg, &alias, evaluate, true); + len = get_name_len((const char **)arg, (char **)&alias, evaluate, true); if (alias != NULL) { s = alias; } @@ -4345,20 +4231,31 @@ static int eval7( } else { if (**arg == '(') { // recursive! partial_T *partial; + + if (!evaluate) { + check_vars((const char *)s, len); + } + // If "s" is the name of a variable of type VAR_FUNC // use its contents. - s = deref_func_name(s, &len, &partial, !evaluate); + s = deref_func_name((const char *)s, &len, &partial, !evaluate); + + // Need to make a copy, in case evaluating the arguments makes + // the name invalid. + s = xmemdupz(s, len); // Invoke the function. ret = get_func_tv(s, len, rettv, arg, curwin->w_cursor.lnum, curwin->w_cursor.lnum, &len, evaluate, partial, NULL); + xfree(s); + // If evaluate is false rettv->v_type was not set in // get_func_tv, but it's needed in handle_subscript() to parse // what follows. So set it here. if (rettv->v_type == VAR_UNKNOWN && !evaluate && **arg == '(') { - rettv->vval.v_string = empty_string; + rettv->vval.v_string = (char_u *)tv_empty_string; rettv->v_type = VAR_FUNC; } @@ -4367,13 +4264,14 @@ static int eval7( // an exception was thrown but not caught. if (aborting()) { if (ret == OK) { - clear_tv(rettv); + tv_clear(rettv); } ret = FAIL; } } else if (evaluate) { - ret = get_var_tv(s, len, rettv, NULL, true, false); + ret = get_var_tv((const char *)s, len, rettv, NULL, true, false); } else { + check_vars((const char *)s, len); ret = OK; } } @@ -4385,22 +4283,22 @@ static int eval7( // Handle following '[', '(' and '.' for expr[expr], expr.name, // expr(expr). if (ret == OK) { - ret = handle_subscript(arg, rettv, evaluate, true); + ret = handle_subscript((const char **)arg, rettv, evaluate, true); } // Apply logical NOT and unary '-', from right to left, ignore '+'. if (ret == OK && evaluate && end_leader > start_leader) { - int error = false; - int val = 0; + bool error = false; + varnumber_T val = 0; float_T f = 0.0; if (rettv->v_type == VAR_FLOAT) { f = rettv->vval.v_float; } else { - val = get_tv_number_chk(rettv, &error); + val = tv_get_number_chk(rettv, &error); } if (error) { - clear_tv(rettv); + tv_clear(rettv); ret = FAIL; } else { while (end_leader > start_leader) { @@ -4420,10 +4318,10 @@ static int eval7( } } if (rettv->v_type == VAR_FLOAT) { - clear_tv(rettv); + tv_clear(rettv); rettv->vval.v_float = f; } else { - clear_tv(rettv); + tv_clear(rettv); rettv->v_type = VAR_NUMBER; rettv->vval.v_number = val; } @@ -4433,6 +4331,8 @@ static int eval7( return ret; } +// TODO(ZyX-I): move to eval/expressions + /* * Evaluate an "[expr]" or "[expr:expr]" index. Also "dict.key". * "*arg" points to the '[' or '.'. @@ -4446,12 +4346,11 @@ eval_index ( int verbose /* give error messages */ ) { - int empty1 = FALSE, empty2 = FALSE; - typval_T var1, var2; + bool empty1 = false; + bool empty2 = false; long n1, n2 = 0; - long len = -1; - int range = FALSE; - char_u *s; + ptrdiff_t len = -1; + int range = false; char_u *key = NULL; switch (rettv->v_type) { @@ -4488,8 +4387,8 @@ eval_index ( } } - init_tv(&var1); - init_tv(&var2); + typval_T var1 = TV_INITIAL_VALUE; + typval_T var2 = TV_INITIAL_VALUE; if (**arg == '.') { /* * dict.name @@ -4507,13 +4406,13 @@ eval_index ( * Get the (first) variable from inside the []. */ *arg = skipwhite(*arg + 1); - if (**arg == ':') - empty1 = TRUE; - else if (eval1(arg, &var1, evaluate) == FAIL) /* recursive! */ + if (**arg == ':') { + empty1 = true; + } else if (eval1(arg, &var1, evaluate) == FAIL) { // Recursive! return FAIL; - else if (evaluate && get_tv_string_chk(&var1) == NULL) { - /* not a number or string */ - clear_tv(&var1); + } else if (evaluate && !tv_check_str(&var1)) { + // Not a number or string. + tv_clear(&var1); return FAIL; } @@ -4523,28 +4422,32 @@ eval_index ( if (**arg == ':') { range = TRUE; *arg = skipwhite(*arg + 1); - if (**arg == ']') - empty2 = TRUE; - else if (eval1(arg, &var2, evaluate) == FAIL) { /* recursive! */ - if (!empty1) - clear_tv(&var1); + if (**arg == ']') { + empty2 = true; + } else if (eval1(arg, &var2, evaluate) == FAIL) { // Recursive! + if (!empty1) { + tv_clear(&var1); + } return FAIL; - } else if (evaluate && get_tv_string_chk(&var2) == NULL) { - /* not a number or string */ - if (!empty1) - clear_tv(&var1); - clear_tv(&var2); + } else if (evaluate && !tv_check_str(&var2)) { + // Not a number or string. + if (!empty1) { + tv_clear(&var1); + } + tv_clear(&var2); return FAIL; } } /* Check for the ']'. */ if (**arg != ']') { - if (verbose) - EMSG(_(e_missbrac)); - clear_tv(&var1); - if (range) - clear_tv(&var2); + if (verbose) { + emsgf(_(e_missbrac)); + } + tv_clear(&var1); + if (range) { + tv_clear(&var2); + } return FAIL; } *arg = skipwhite(*arg + 1); /* skip the ']' */ @@ -4553,168 +4456,181 @@ eval_index ( if (evaluate) { n1 = 0; if (!empty1 && rettv->v_type != VAR_DICT) { - n1 = get_tv_number(&var1); - clear_tv(&var1); + n1 = tv_get_number(&var1); + tv_clear(&var1); } if (range) { - if (empty2) + if (empty2) { n2 = -1; - else { - n2 = get_tv_number(&var2); - clear_tv(&var2); + } else { + n2 = tv_get_number(&var2); + tv_clear(&var2); } } switch (rettv->v_type) { - case VAR_NUMBER: - case VAR_STRING: - s = get_tv_string(rettv); - len = (long)STRLEN(s); - if (range) { - /* The resulting variable is a substring. If the indexes - * are out of range the result is empty. */ + case VAR_NUMBER: + case VAR_STRING: { + const char *const s = tv_get_string(rettv); + char *v; + len = (ptrdiff_t)strlen(s); + if (range) { + // The resulting variable is a substring. If the indexes + // are out of range the result is empty. + if (n1 < 0) { + n1 = len + n1; + if (n1 < 0) { + n1 = 0; + } + } + if (n2 < 0) { + n2 = len + n2; + } else if (n2 >= len) { + n2 = len; + } + if (n1 >= len || n2 < 0 || n1 > n2) { + v = NULL; + } else { + v = xmemdupz(s + n1, (size_t)(n2 - n1 + 1)); + } + } else { + // The resulting variable is a string of a single + // character. If the index is too big or negative the + // result is empty. + if (n1 >= len || n1 < 0) { + v = NULL; + } else { + v = xmemdupz(s + n1, 1); + } + } + tv_clear(rettv); + rettv->v_type = VAR_STRING; + rettv->vval.v_string = (char_u *)v; + break; + } + case VAR_LIST: { + len = tv_list_len(rettv->vval.v_list); if (n1 < 0) { n1 = len + n1; - if (n1 < 0) - n1 = 0; } - if (n2 < 0) - n2 = len + n2; - else if (n2 >= len) - n2 = len; - if (n1 >= len || n2 < 0 || n1 > n2) - s = NULL; - else - s = vim_strnsave(s + n1, (int)(n2 - n1 + 1)); - } else { - /* The resulting variable is a string of a single - * character. If the index is too big or negative the - * result is empty. */ - if (n1 >= len || n1 < 0) - s = NULL; - else - s = vim_strnsave(s + n1, 1); - } - clear_tv(rettv); - rettv->v_type = VAR_STRING; - rettv->vval.v_string = s; - break; - - case VAR_LIST: - len = list_len(rettv->vval.v_list); - if (n1 < 0) - n1 = len + n1; - if (!empty1 && (n1 < 0 || n1 >= len)) { - /* For a range we allow invalid values and return an empty - * list. A list index out of range is an error. */ - if (!range) { - if (verbose) - EMSGN(_(e_listidx), n1); - return FAIL; + if (!empty1 && (n1 < 0 || n1 >= len)) { + // For a range we allow invalid values and return an empty + // list. A list index out of range is an error. + if (!range) { + if (verbose) { + EMSGN(_(e_listidx), n1); + } + return FAIL; + } + n1 = len; } - n1 = len; - } - if (range) { - list_T *l; - listitem_T *item; - - if (n2 < 0) - n2 = len + n2; - else if (n2 >= len) - n2 = len - 1; - if (!empty2 && (n2 < 0 || n2 + 1 < n1)) - n2 = -1; - l = list_alloc(); - item = list_find(rettv->vval.v_list, n1); - while (n1++ <= n2) { - list_append_tv(l, &item->li_tv); - item = item->li_next; + if (range) { + list_T *l; + listitem_T *item; + + if (n2 < 0) { + n2 = len + n2; + } else if (n2 >= len) { + n2 = len - 1; + } + if (!empty2 && (n2 < 0 || n2 + 1 < n1)) { + n2 = -1; + } + l = tv_list_alloc(); + item = tv_list_find(rettv->vval.v_list, n1); + while (n1++ <= n2) { + tv_list_append_tv(l, &item->li_tv); + item = item->li_next; + } + tv_clear(rettv); + rettv->v_type = VAR_LIST; + rettv->vval.v_list = l; + l->lv_refcount++; + } else { + tv_copy(&tv_list_find(rettv->vval.v_list, n1)->li_tv, &var1); + tv_clear(rettv); + *rettv = var1; } - clear_tv(rettv); - rettv->v_type = VAR_LIST; - rettv->vval.v_list = l; - ++l->lv_refcount; - } else { - copy_tv(&list_find(rettv->vval.v_list, n1)->li_tv, &var1); - clear_tv(rettv); - *rettv = var1; - } - break; - - case VAR_DICT: - if (range) { - if (verbose) - EMSG(_(e_dictrange)); - if (len == -1) - clear_tv(&var1); - return FAIL; + break; } - { - dictitem_T *item; + case VAR_DICT: { + if (range) { + if (verbose) { + emsgf(_(e_dictrange)); + } + if (len == -1) { + tv_clear(&var1); + } + return FAIL; + } if (len == -1) { - key = get_tv_string_chk(&var1); + key = (char_u *)tv_get_string_chk(&var1); if (key == NULL) { - clear_tv(&var1); + tv_clear(&var1); return FAIL; } } - item = dict_find(rettv->vval.v_dict, key, (int)len); + dictitem_T *const item = tv_dict_find(rettv->vval.v_dict, + (const char *)key, len); - if (item == NULL && verbose) - EMSG2(_(e_dictkey), key); - if (len == -1) - clear_tv(&var1); - if (item == NULL) + if (item == NULL && verbose) { + emsgf(_(e_dictkey), key); + } + if (len == -1) { + tv_clear(&var1); + } + if (item == NULL) { return FAIL; + } - copy_tv(&item->di_tv, &var1); - clear_tv(rettv); + tv_copy(&item->di_tv, &var1); + tv_clear(rettv); *rettv = var1; + break; + } + case VAR_SPECIAL: + case VAR_FUNC: + case VAR_FLOAT: + case VAR_PARTIAL: + case VAR_UNKNOWN: { + break; // Not evaluating, skipping over subscript } - break; - case VAR_SPECIAL: - case VAR_FUNC: - case VAR_PARTIAL: - case VAR_FLOAT: - case VAR_UNKNOWN: - break; // Not evaluating, skipping over subscript } } return OK; } -/* - * Get an option value. - * "arg" points to the '&' or '+' before the option name. - * "arg" is advanced to character after the option name. - * Return OK or FAIL. - */ -static int -get_option_tv ( - char_u **arg, - typval_T *rettv, /* when NULL, only check if option exists */ - int evaluate -) +// TODO(ZyX-I): move to eval/executor + +/// Get an option value +/// +/// @param[in,out] arg Points to the '&' or '+' before the option name. Is +/// advanced to the character after the option name. +/// @param[out] rettv Location where result is saved. +/// @param[in] evaluate If not true, rettv is not populated. +/// +/// @return OK or FAIL. +static int get_option_tv(const char **const arg, typval_T *const rettv, + const bool evaluate) + FUNC_ATTR_NONNULL_ARG(1) { - char_u *option_end; long numval; char_u *stringval; int opt_type; int c; - int working = (**arg == '+'); /* has("+option") */ + bool working = (**arg == '+'); // has("+option") int ret = OK; int opt_flags; - /* - * Isolate the option name and find its value. - */ - option_end = find_option_end(arg, &opt_flags); + // Isolate the option name and find its value. + char *option_end = (char *)find_option_end(arg, &opt_flags); if (option_end == NULL) { - if (rettv != NULL) + if (rettv != NULL) { EMSG2(_("E112: Option name missing: %s"), *arg); + } return FAIL; } @@ -4725,8 +4641,8 @@ get_option_tv ( c = *option_end; *option_end = NUL; - opt_type = get_option_value(*arg, &numval, - rettv == NULL ? NULL : &stringval, opt_flags); + opt_type = get_option_value((char_u *)(*arg), &numval, + rettv == NULL ? NULL : &stringval, opt_flags); if (opt_type == -3) { /* invalid name */ if (rettv != NULL) @@ -4856,7 +4772,7 @@ static int get_string_tv(char_u **arg, typval_T *rettv, int evaluate) // Special key, e.g.: "\<C-W>" case '<': - extra = trans_special((const char_u **) &p, STRLEN(p), name, true); + extra = trans_special((const char_u **)&p, STRLEN(p), name, true, true); if (extra != 0) { name += extra; break; @@ -4871,7 +4787,10 @@ static int get_string_tv(char_u **arg, typval_T *rettv, int evaluate) } *name = NUL; - *arg = p + 1; + if (*p != NUL) { // just in case + p++; + } + *arg = p; return OK; } @@ -4930,18 +4849,35 @@ static int get_lit_string_tv(char_u **arg, typval_T *rettv, int evaluate) return OK; } +/// @return the function name of the partial. +char_u *partial_name(partial_T *pt) +{ + if (pt->pt_name != NULL) { + return pt->pt_name; + } + return pt->pt_func->uf_name; +} + +// TODO(ZyX-I): Move to eval/typval.h + static void partial_free(partial_T *pt) { for (int i = 0; i < pt->pt_argc; i++) { - clear_tv(&pt->pt_argv[i]); + tv_clear(&pt->pt_argv[i]); } xfree(pt->pt_argv); - dict_unref(pt->pt_dict); - func_unref(pt->pt_name); - xfree(pt->pt_name); + tv_dict_unref(pt->pt_dict); + if (pt->pt_name != NULL) { + func_unref(pt->pt_name); + xfree(pt->pt_name); + } else { + func_ptr_unref(pt->pt_func); + } xfree(pt); } +// TODO(ZyX-I): Move to eval/typval.h + /// Unreference a closure: decrement the reference count and free it when it /// becomes zero. void partial_unref(partial_T *pt) @@ -4960,7 +4896,7 @@ static int get_list_tv(char_u **arg, typval_T *rettv, int evaluate) listitem_T *item; if (evaluate) { - l = list_alloc(); + l = tv_list_alloc(); } *arg = skipwhite(*arg + 1); @@ -4968,10 +4904,10 @@ static int get_list_tv(char_u **arg, typval_T *rettv, int evaluate) if (eval1(arg, &tv, evaluate) == FAIL) /* recursive! */ goto failret; if (evaluate) { - item = listitem_alloc(); + item = tv_list_item_alloc(); item->li_tv = tv; item->li_tv.v_lock = 0; - list_append(l, item); + tv_list_append(l, item); } if (**arg == ']') @@ -4987,7 +4923,7 @@ static int get_list_tv(char_u **arg, typval_T *rettv, int evaluate) EMSG2(_("E697: Missing end of List ']': %s"), *arg); failret: if (evaluate) { - list_free(l); + tv_list_free(l); } return FAIL; } @@ -5002,196 +4938,7 @@ failret: return OK; } -/* - * Allocate an empty header for a list. - * Caller should take care of the reference count. - */ -list_T *list_alloc(void) FUNC_ATTR_NONNULL_RET -{ - list_T *list = xcalloc(1, sizeof(list_T)); - - /* Prepend the list to the list of lists for garbage collection. */ - if (first_list != NULL) - first_list->lv_used_prev = list; - list->lv_used_prev = NULL; - list->lv_used_next = first_list; - first_list = list; - return list; -} - -/* - * Allocate an empty list for a return value. - */ -static list_T *rettv_list_alloc(typval_T *rettv) -{ - list_T *l = list_alloc(); - rettv->vval.v_list = l; - rettv->v_type = VAR_LIST; - rettv->v_lock = VAR_UNLOCKED; - l->lv_refcount++; - return l; -} - -/// Unreference a list: decrement the reference count and free it when it -/// becomes zero. -void list_unref(list_T *l) { - if (l != NULL && --l->lv_refcount <= 0) { - list_free(l); - } -} - -/// Free a list, including all items it points to. -/// Ignores the reference count. -static void list_free_contents(list_T *l) { - listitem_T *item; - - for (item = l->lv_first; item != NULL; item = l->lv_first) { - // Remove the item before deleting it. - l->lv_first = item->li_next; - clear_tv(&item->li_tv); - xfree(item); - } -} - -static void list_free_list(list_T *l) { - // Remove the list from the list of lists for garbage collection. - if (l->lv_used_prev == NULL) { - first_list = l->lv_used_next; - } else { - l->lv_used_prev->lv_used_next = l->lv_used_next; - } - if (l->lv_used_next != NULL) { - l->lv_used_next->lv_used_prev = l->lv_used_prev; - } - - xfree(l); -} - -void list_free(list_T *l) { - if (!in_free_unref_items) { - list_free_contents(l); - list_free_list(l); - } -} - -/* - * Allocate a list item. - * It is not initialized, don't forget to set v_lock. - */ -listitem_T *listitem_alloc(void) FUNC_ATTR_NONNULL_RET -{ - return xmalloc(sizeof(listitem_T)); -} - -/* - * Free a list item. Also clears the value. Does not notify watchers. - */ -void listitem_free(listitem_T *item) -{ - clear_tv(&item->li_tv); - xfree(item); -} - -/* - * Remove a list item from a List and free it. Also clears the value. - */ -void listitem_remove(list_T *l, listitem_T *item) -{ - vim_list_remove(l, item, item); - listitem_free(item); -} - -/* - * Get the number of items in a list. - */ -static long list_len(list_T *l) -{ - if (l == NULL) - return 0L; - return l->lv_len; -} - -/* - * Return TRUE when two lists have exactly the same values. - */ -static int -list_equal ( - list_T *l1, - list_T *l2, - int ic, /* ignore case for strings */ - int recursive /* TRUE when used recursively */ -) -{ - listitem_T *item1, *item2; - - if (l1 == NULL || l2 == NULL) - return FALSE; - if (l1 == l2) - return TRUE; - if (list_len(l1) != list_len(l2)) - return FALSE; - - for (item1 = l1->lv_first, item2 = l2->lv_first; - item1 != NULL && item2 != NULL; - item1 = item1->li_next, item2 = item2->li_next) - if (!tv_equal(&item1->li_tv, &item2->li_tv, ic, recursive)) - return FALSE; - return item1 == NULL && item2 == NULL; -} - -/* - * Return the dictitem that an entry in a hashtable points to. - */ -dictitem_T *dict_lookup(hashitem_T *hi) -{ - return HI2DI(hi); -} - -/* - * Return TRUE when two dictionaries have exactly the same key/values. - */ -static int -dict_equal ( - dict_T *d1, - dict_T *d2, - int ic, /* ignore case for strings */ - int recursive /* TRUE when used recursively */ -) -{ - hashitem_T *hi; - dictitem_T *item2; - int todo; - - if (d1 == NULL && d2 == NULL) { - return true; - } - if (d1 == NULL || d2 == NULL) { - return false; - } - if (d1 == d2) { - return true; - } - if (dict_len(d1) != dict_len(d2)) { - return false; - } - - todo = (int)d1->dv_hashtab.ht_used; - for (hi = d1->dv_hashtab.ht_array; todo > 0; ++hi) { - if (!HASHITEM_EMPTY(hi)) { - item2 = dict_find(d2, hi->hi_key, -1); - if (item2 == NULL) - return FALSE; - if (!tv_equal(&HI2DI(hi)->di_tv, &item2->di_tv, ic, recursive)) - return FALSE; - --todo; - } - } - return TRUE; -} - -static int tv_equal_recurse_limit; - -static bool func_equal( +bool func_equal( typval_T *tv1, typval_T *tv2, bool ic // ignore case @@ -5202,12 +4949,12 @@ static bool func_equal( // empty and NULL function name considered the same s1 = tv1->v_type == VAR_FUNC ? tv1->vval.v_string - : tv1->vval.v_partial->pt_name; + : partial_name(tv1->vval.v_partial); if (s1 != NULL && *s1 == NUL) { s1 = NULL; } s2 = tv2->v_type == VAR_FUNC ? tv2->vval.v_string - : tv2->vval.v_partial->pt_name; + : partial_name(tv2->vval.v_partial); if (s2 != NULL && *s2 == NUL) { s2 = NULL; } @@ -5226,7 +4973,7 @@ static bool func_equal( if (d1 != d2) { return false; } - } else if (!dict_equal(d1, d2, ic, true)) { + } else if (!tv_dict_equal(d1, d2, ic, true)) { return false; } @@ -5245,550 +4992,6 @@ static bool func_equal( return true; } -/* - * Return TRUE if "tv1" and "tv2" have the same value. - * Compares the items just like "==" would compare them, but strings and - * numbers are different. Floats and numbers are also different. - */ -static int -tv_equal ( - typval_T *tv1, - typval_T *tv2, - int ic, /* ignore case */ - int recursive /* TRUE when used recursively */ -) -{ - char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN]; - char_u *s1, *s2; - static int recursive_cnt = 0; /* catch recursive loops */ - int r; - - /* Catch lists and dicts that have an endless loop by limiting - * recursiveness to a limit. We guess they are equal then. - * A fixed limit has the problem of still taking an awful long time. - * Reduce the limit every time running into it. That should work fine for - * deeply linked structures that are not recursively linked and catch - * recursiveness quickly. */ - if (!recursive) - tv_equal_recurse_limit = 1000; - if (recursive_cnt >= tv_equal_recurse_limit) { - --tv_equal_recurse_limit; - return TRUE; - } - - // For VAR_FUNC and VAR_PARTIAL only compare the function name. - if ((tv1->v_type == VAR_FUNC - || (tv1->v_type == VAR_PARTIAL && tv1->vval.v_partial != NULL)) - && (tv2->v_type == VAR_FUNC - || (tv2->v_type == VAR_PARTIAL && tv2->vval.v_partial != NULL))) { - recursive_cnt++; - r = func_equal(tv1, tv2, ic); - recursive_cnt--; - return r; - } - if (tv1->v_type != tv2->v_type) { - return false; - } - - switch (tv1->v_type) { - case VAR_LIST: - ++recursive_cnt; - r = list_equal(tv1->vval.v_list, tv2->vval.v_list, ic, TRUE); - --recursive_cnt; - return r; - - case VAR_DICT: - ++recursive_cnt; - r = dict_equal(tv1->vval.v_dict, tv2->vval.v_dict, ic, TRUE); - --recursive_cnt; - return r; - - case VAR_NUMBER: - return tv1->vval.v_number == tv2->vval.v_number; - - case VAR_FLOAT: - return tv1->vval.v_float == tv2->vval.v_float; - - case VAR_STRING: - s1 = get_tv_string_buf(tv1, buf1); - s2 = get_tv_string_buf(tv2, buf2); - return (ic ? mb_stricmp(s1, s2) : STRCMP(s1, s2)) == 0; - - case VAR_SPECIAL: - return tv1->vval.v_special == tv2->vval.v_special; - - case VAR_FUNC: - case VAR_PARTIAL: - case VAR_UNKNOWN: - // VAR_UNKNOWN can be the result of an invalid expression, letโs say it does - // not equal anything, not even self. - return false; - } - - assert(false); - return false; -} - -/* - * Locate item with index "n" in list "l" and return it. - * A negative index is counted from the end; -1 is the last item. - * Returns NULL when "n" is out of range. - */ -listitem_T *list_find(list_T *l, long n) -{ - listitem_T *item; - long idx; - - if (l == NULL) - return NULL; - - /* Negative index is relative to the end. */ - if (n < 0) - n = l->lv_len + n; - - /* Check for index out of range. */ - if (n < 0 || n >= l->lv_len) - return NULL; - - /* When there is a cached index may start search from there. */ - if (l->lv_idx_item != NULL) { - if (n < l->lv_idx / 2) { - /* closest to the start of the list */ - item = l->lv_first; - idx = 0; - } else if (n > (l->lv_idx + l->lv_len) / 2) { - /* closest to the end of the list */ - item = l->lv_last; - idx = l->lv_len - 1; - } else { - /* closest to the cached index */ - item = l->lv_idx_item; - idx = l->lv_idx; - } - } else { - if (n < l->lv_len / 2) { - /* closest to the start of the list */ - item = l->lv_first; - idx = 0; - } else { - /* closest to the end of the list */ - item = l->lv_last; - idx = l->lv_len - 1; - } - } - - while (n > idx) { - /* search forward */ - item = item->li_next; - ++idx; - } - while (n < idx) { - /* search backward */ - item = item->li_prev; - --idx; - } - - /* cache the used index */ - l->lv_idx = idx; - l->lv_idx_item = item; - - return item; -} - -/* - * Get list item "l[idx]" as a number. - */ -static long -list_find_nr ( - list_T *l, - long idx, - int *errorp /* set to TRUE when something wrong */ -) -{ - listitem_T *li; - - li = list_find(l, idx); - if (li == NULL) { - if (errorp != NULL) - *errorp = TRUE; - return -1L; - } - return get_tv_number_chk(&li->li_tv, errorp); -} - -/* - * Get list item "l[idx - 1]" as a string. Returns NULL for failure. - */ -char_u *list_find_str(list_T *l, long idx) -{ - listitem_T *li; - - li = list_find(l, idx - 1); - if (li == NULL) { - EMSGN(_(e_listidx), idx); - return NULL; - } - return get_tv_string(&li->li_tv); -} - -/* - * Locate "item" list "l" and return its index. - * Returns -1 when "item" is not in the list. - */ -static long list_idx_of_item(list_T *l, listitem_T *item) -{ - long idx = 0; - listitem_T *li; - - if (l == NULL) - return -1; - idx = 0; - for (li = l->lv_first; li != NULL && li != item; li = li->li_next) - ++idx; - if (li == NULL) - return -1; - return idx; -} - -/* - * Append item "item" to the end of list "l". - */ -void list_append(list_T *l, listitem_T *item) -{ - if (l->lv_last == NULL) { - /* empty list */ - l->lv_first = item; - l->lv_last = item; - item->li_prev = NULL; - } else { - l->lv_last->li_next = item; - item->li_prev = l->lv_last; - l->lv_last = item; - } - ++l->lv_len; - item->li_next = NULL; -} - -/* - * Append typval_T "tv" to the end of list "l". - */ -void list_append_tv(list_T *l, typval_T *tv) -{ - listitem_T *li = listitem_alloc(); - copy_tv(tv, &li->li_tv); - list_append(l, li); -} - -/* - * Add a list to a list. - */ -void list_append_list(list_T *list, list_T *itemlist) -{ - listitem_T *li = listitem_alloc(); - - li->li_tv.v_type = VAR_LIST; - li->li_tv.v_lock = 0; - li->li_tv.vval.v_list = itemlist; - list_append(list, li); - ++itemlist->lv_refcount; -} - -/* - * Add a dictionary to a list. Used by getqflist(). - */ -void list_append_dict(list_T *list, dict_T *dict) -{ - listitem_T *li = listitem_alloc(); - - li->li_tv.v_type = VAR_DICT; - li->li_tv.v_lock = 0; - li->li_tv.vval.v_dict = dict; - list_append(list, li); - ++dict->dv_refcount; -} - -/// Make a copy of "str" and append it as an item to list "l" -/// -/// @param[out] l List to append to. -/// @param[in] str String to append. -/// @param[in] len Length of the appended string. May be negative, in this -/// case string is considered to be usual zero-terminated -/// string. -void list_append_string(list_T *l, const char_u *str, int len) - FUNC_ATTR_NONNULL_ARG(1) -{ - if (str == NULL) { - list_append_allocated_string(l, NULL); - } else { - list_append_allocated_string(l, (len >= 0 - ? xmemdupz((char *) str, len) - : xstrdup((char *) str))); - } -} - -/// Append given string to the list -/// -/// Unlike list_append_string this function does not copy the string. -/// -/// @param[out] l List to append to. -/// @param[in] str String to append. -void list_append_allocated_string(list_T *l, char *const str) - FUNC_ATTR_NONNULL_ARG(1) -{ - listitem_T *li = listitem_alloc(); - - list_append(l, li); - li->li_tv.v_type = VAR_STRING; - li->li_tv.v_lock = 0; - li->li_tv.vval.v_string = (char_u *) str; -} - -/* - * Append "n" to list "l". - */ -void list_append_number(list_T *l, varnumber_T n) -{ - listitem_T *li = listitem_alloc(); - li->li_tv.v_type = VAR_NUMBER; - li->li_tv.v_lock = 0; - li->li_tv.vval.v_number = n; - list_append(l, li); -} - -/* - * Insert typval_T "tv" in list "l" before "item". - * If "item" is NULL append at the end. - */ -void list_insert_tv(list_T *l, typval_T *tv, listitem_T *item) -{ - listitem_T *ni = listitem_alloc(); - - copy_tv(tv, &ni->li_tv); - list_insert(l, ni, item); -} - -void list_insert(list_T *l, listitem_T *ni, listitem_T *item) -{ - if (item == NULL) - /* Append new item at end of list. */ - list_append(l, ni); - else { - /* Insert new item before existing item. */ - ni->li_prev = item->li_prev; - ni->li_next = item; - if (item->li_prev == NULL) { - l->lv_first = ni; - ++l->lv_idx; - } else { - item->li_prev->li_next = ni; - l->lv_idx_item = NULL; - } - item->li_prev = ni; - ++l->lv_len; - } -} - -/* - * Extend "l1" with "l2". - * If "bef" is NULL append at the end, otherwise insert before this item. - */ -static void list_extend(list_T *l1, list_T *l2, listitem_T *bef) -{ - listitem_T *item; - int todo = l2->lv_len; - - /* We also quit the loop when we have inserted the original item count of - * the list, avoid a hang when we extend a list with itself. */ - for (item = l2->lv_first; item != NULL && --todo >= 0; item = item->li_next) { - list_insert_tv(l1, &item->li_tv, bef); - } -} - -/* - * Concatenate lists "l1" and "l2" into a new list, stored in "tv". - * Return FAIL on failure to copy. - */ -static int list_concat(list_T *l1, list_T *l2, typval_T *tv) -{ - list_T *l; - - if (l1 == NULL || l2 == NULL) - return FAIL; - - /* make a copy of the first list. */ - l = list_copy(NULL, l1, false, 0); - if (l == NULL) - return FAIL; - tv->v_type = VAR_LIST; - tv->vval.v_list = l; - - /* append all items from the second list */ - list_extend(l, l2, NULL); - return OK; -} - -/// Make a copy of list -/// -/// @param[in] conv If non-NULL, then all internal strings will be converted. -/// @param[in] orig Original list to copy. -/// @param[in] deep If false, then shallow copy will be done. -/// @param[in] copyID See var_item_copy(). -/// -/// @return Copied list. May be NULL in case original list is NULL or some -/// failure happens. The refcount of the new list is set to 1. -static list_T *list_copy(const vimconv_T *const conv, - list_T *const orig, - const bool deep, - const int copyID) - FUNC_ATTR_WARN_UNUSED_RESULT -{ - listitem_T *item; - listitem_T *ni; - - if (orig == NULL) - return NULL; - - list_T *copy = list_alloc(); - if (copyID != 0) { - /* Do this before adding the items, because one of the items may - * refer back to this list. */ - orig->lv_copyID = copyID; - orig->lv_copylist = copy; - } - for (item = orig->lv_first; item != NULL && !got_int; - item = item->li_next) { - ni = listitem_alloc(); - if (deep) { - if (var_item_copy(conv, &item->li_tv, &ni->li_tv, deep, copyID) == FAIL) { - xfree(ni); - break; - } - } else - copy_tv(&item->li_tv, &ni->li_tv); - list_append(copy, ni); - } - ++copy->lv_refcount; - if (item != NULL) { - list_unref(copy); - copy = NULL; - } - - return copy; -} - -/// Remove items "item" to "item2" from list "l". -/// @warning Does not free the listitem or the value! -void vim_list_remove(list_T *l, listitem_T *item, listitem_T *item2) -{ - // notify watchers - for (listitem_T *ip = item; ip != NULL; ip = ip->li_next) { - --l->lv_len; - list_fix_watch(l, ip); - if (ip == item2) { - break; - } - } - - if (item2->li_next == NULL) { - l->lv_last = item->li_prev; - } else { - item2->li_next->li_prev = item->li_prev; - } - if (item->li_prev == NULL) { - l->lv_first = item2->li_next; - } else { - item->li_prev->li_next = item2->li_next; - } - l->lv_idx_item = NULL; -} - -typedef struct join_S { - char_u *s; - char_u *tofree; -} join_T; - -/// Join list into a string, helper function -/// -/// @param[out] gap Garray where result will be saved. -/// @param[in] l List to join. -/// @param[in] sep Used separator. -/// @param[in] join_gap Garray to keep each list item string. -/// -/// @return OK in case of success, FAIL otherwise. -static int list_join_inner(garray_T *const gap, list_T *const l, - const char *const sep, garray_T *const join_gap) - FUNC_ATTR_NONNULL_ALL -{ - int sumlen = 0; - bool first = true; - listitem_T *item; - - /* Stringify each item in the list. */ - for (item = l->lv_first; item != NULL && !got_int; item = item->li_next) { - char *s; - size_t len; - s = encode_tv2echo(&item->li_tv, &len); - if (s == NULL) { - return FAIL; - } - - sumlen += (int) len; - - join_T *const p = GA_APPEND_VIA_PTR(join_T, join_gap); - p->tofree = p->s = (char_u *) s; - - line_breakcheck(); - } - - /* Allocate result buffer with its total size, avoid re-allocation and - * multiple copy operations. Add 2 for a tailing ']' and NUL. */ - if (join_gap->ga_len >= 2) - sumlen += (int)STRLEN(sep) * (join_gap->ga_len - 1); - ga_grow(gap, sumlen + 2); - - for (int i = 0; i < join_gap->ga_len && !got_int; ++i) { - if (first) { - first = false; - } else { - ga_concat(gap, (const char_u *) sep); - } - const join_T *const p = ((const join_T *)join_gap->ga_data) + i; - - if (p->s != NULL) - ga_concat(gap, p->s); - line_breakcheck(); - } - - return OK; -} - -/// Join list into a string using given separator -/// -/// @param[out] gap Garray where result will be saved. -/// @param[in] l Joined list. -/// @param[in] sep Separator. -/// -/// @return OK in case of success, FAIL otherwise. -static int list_join(garray_T *const gap, list_T *const l, - const char *const sep) - FUNC_ATTR_NONNULL_ALL -{ - if (l->lv_len < 1) { - return OK; - } - - garray_T join_ga; - int retval; - - ga_init(&join_ga, (int)sizeof(join_T), l->lv_len); - retval = list_join_inner(gap, l, sep, &join_ga); - -# define FREE_JOIN_TOFREE(join) xfree((join)->tofree) - GA_DEEP_CLEAR(&join_ga, join_T, FREE_JOIN_TOFREE); - - return retval; -} - /// Get next (unique) copy ID /// /// Used for traversing nested structures e.g. when serializing them or garbage @@ -5805,6 +5008,9 @@ int get_copyID(void) return current_copyID; } +// Used by get_func_tv() +static garray_T funcargs = GA_EMPTY_INIT_VALUE; + /* * Garbage collection for lists and dictionaries. * @@ -5827,19 +5033,22 @@ int get_copyID(void) /// Do garbage collection for lists and dicts. /// +/// @param testing true if called from test_garbagecollect_now(). /// @returns true if some memory was freed. -bool garbage_collect(void) +bool garbage_collect(bool testing) { bool abort = false; #define ABORTING(func) abort = abort || func - // Only do this once. - want_garbage_collect = false; - may_garbage_collect = false; - garbage_collect_at_exit = false; + if (!testing) { + // Only do this once. + want_garbage_collect = false; + may_garbage_collect = false; + garbage_collect_at_exit = false; + } - // We advance by two because we add one for items referenced through - // previous_funccal. + // We advance by two (COPYID_INC) because we add one for items referenced + // through previous_funccal. const int copyID = get_copyID(); // 1. Go through all accessible variables and mark all lists and dicts @@ -5849,6 +5058,7 @@ bool garbage_collect(void) // referenced through previous_funccal. This must be first, because if // the item is referenced elsewhere the funccal must not be freed. for (funccall_T *fc = previous_funccal; fc != NULL; fc = fc->caller) { + fc->fc_copyID = copyID + 1; ABORTING(set_ref_in_ht)(&fc->l_vars.dv_hashtab, copyID + 1, NULL); ABORTING(set_ref_in_ht)(&fc->l_avars.dv_hashtab, copyID + 1, NULL); } @@ -5894,7 +5104,8 @@ bool garbage_collect(void) do { yankreg_T reg; char name = NUL; - reg_iter = op_register_iter(reg_iter, &name, ®); + bool is_unnamed = false; + reg_iter = op_register_iter(reg_iter, &name, ®, &is_unnamed); if (name != NUL) { ABORTING(set_ref_dict)(reg.additional_data, copyID); } @@ -5924,10 +5135,14 @@ bool garbage_collect(void) // function-local variables for (funccall_T *fc = current_funccal; fc != NULL; fc = fc->caller) { + fc->fc_copyID = copyID; ABORTING(set_ref_in_ht)(&fc->l_vars.dv_hashtab, copyID, NULL); ABORTING(set_ref_in_ht)(&fc->l_avars.dv_hashtab, copyID, NULL); } + // named functions (matters for closures) + ABORTING(set_ref_in_functions(copyID)); + // Jobs { TerminalJobData *data; @@ -5946,6 +5161,12 @@ bool garbage_collect(void) }) } + // function call arguments, if v:testing is set. + for (int i = 0; i < funcargs.ga_len; i++) { + ABORTING(set_ref_in_item)(((typval_T **)funcargs.ga_data)[i], + copyID, NULL, NULL); + } + // v: vars ABORTING(set_ref_in_ht)(&vimvarht, copyID, NULL); @@ -6000,7 +5221,7 @@ bool garbage_collect(void) if (did_free_funccal) { // When a funccal was freed some more items might be garbage // collected, so run again. - (void)garbage_collect(); + (void)garbage_collect(testing); } } else if (p_verbose > 0) { verb_msg((char_u *)_( @@ -6012,7 +5233,7 @@ bool garbage_collect(void) /// Free lists and dictionaries that are no longer referenced. /// -/// Note: This function may only be called from garbage_collect(). +/// @note This function may only be called from garbage_collect(). /// /// @param copyID Free lists/dictionaries that don't have this ID. /// @return true, if something was freed. @@ -6025,19 +5246,19 @@ static int free_unref_items(int copyID) // Let all "free" functions know that we are here. This means no // dictionaries, lists, or jobs are to be freed, because we will // do that here. - in_free_unref_items = true; + tv_in_free_unref_items = true; // PASS 1: free the contents of the items. We don't free the items // themselves yet, so that it is possible to decrement refcount counters. // Go through the list of dicts and free items without the copyID. // Don't free dicts that are referenced internally. - for (dict_T *dd = first_dict; dd != NULL; dd = dd->dv_used_next) { + for (dict_T *dd = gc_first_dict; dd != NULL; dd = dd->dv_used_next) { if ((dd->dv_copyID & COPYID_MASK) != (copyID & COPYID_MASK)) { // Free the Dictionary and ordinary items it contains, but don't // recurse into Lists and Dictionaries, they will be in the list // of dicts or list of lists. - dict_free_contents(dd); + tv_dict_free_contents(dd); did_free = true; } } @@ -6045,36 +5266,36 @@ static int free_unref_items(int copyID) // Go through the list of lists and free items without the copyID. // But don't free a list that has a watcher (used in a for loop), these // are not referenced anywhere. - for (list_T *ll = first_list; ll != NULL; ll = ll->lv_used_next) { + for (list_T *ll = gc_first_list; ll != NULL; ll = ll->lv_used_next) { if ((ll->lv_copyID & COPYID_MASK) != (copyID & COPYID_MASK) && ll->lv_watch == NULL) { // Free the List and ordinary items it contains, but don't recurse // into Lists and Dictionaries, they will be in the list of dicts // or list of lists. - list_free_contents(ll); + tv_list_free_contents(ll); did_free = true; } } // PASS 2: free the items themselves. - for (dd = first_dict; dd != NULL; dd = dd_next) { + for (dd = gc_first_dict; dd != NULL; dd = dd_next) { dd_next = dd->dv_used_next; if ((dd->dv_copyID & COPYID_MASK) != (copyID & COPYID_MASK)) { - dict_free_dict(dd); + tv_dict_free_dict(dd); } } - for (ll = first_list; ll != NULL; ll = ll_next) { + for (ll = gc_first_list; ll != NULL; ll = ll_next) { ll_next = ll->lv_used_next; if ((ll->lv_copyID & COPYID_MASK) != (copyID & COPYID_MASK) && ll->lv_watch == NULL) { // Free the List and ordinary items it contains, but don't recurse // into Lists and Dictionaries, they will be in the list of dicts // or list of lists. - list_free_list(ll); + tv_list_free_list(ll); } } - in_free_unref_items = false; + tv_in_free_unref_items = false; return did_free; } @@ -6097,14 +5318,10 @@ bool set_ref_in_ht(hashtab_T *ht, int copyID, list_stack_T **list_stack) // Mark each item in the hashtab. If the item contains a hashtab // it is added to ht_stack, if it contains a list it is added to // list_stack. - int todo = (int)cur_ht->ht_used; - for (hashitem_T *hi = cur_ht->ht_array; todo > 0; ++hi) { - if (!HASHITEM_EMPTY(hi)) { - --todo; - abort = abort || set_ref_in_item(&HI2DI(hi)->di_tv, copyID, &ht_stack, - list_stack); - } - } + HASHTAB_ITER(cur_ht, hi, { + abort = abort || set_ref_in_item( + &TV_DICT_HI2DI(hi)->di_tv, copyID, &ht_stack, list_stack); + }); } if (ht_stack == NULL) { @@ -6196,21 +5413,10 @@ bool set_ref_in_item(typval_T *tv, int copyID, ht_stack_T **ht_stack, QUEUE *w = NULL; DictWatcher *watcher = NULL; QUEUE_FOREACH(w, &dd->watchers) { - watcher = dictwatcher_node_data(w); + watcher = tv_dict_watcher_node_data(w); set_ref_in_callback(&watcher->callback, copyID, ht_stack, list_stack); } } - if (tv->v_type == VAR_PARTIAL) { - partial_T *pt = tv->vval.v_partial; - int i; - - if (pt != NULL) { - for (i = 0; i < pt->pt_argc; i++) { - abort = abort || set_ref_in_item(&pt->pt_argv[i], copyID, - ht_stack, list_stack); - } - } - } break; } @@ -6240,6 +5446,7 @@ bool set_ref_in_item(typval_T *tv, int copyID, ht_stack_T **ht_stack, // A partial does not have a copyID, because it cannot contain itself. if (pt != NULL) { + abort = set_ref_in_func(pt->pt_name, pt->pt_func, copyID); if (pt->pt_dict != NULL) { typval_T dtv; @@ -6256,6 +5463,8 @@ bool set_ref_in_item(typval_T *tv, int copyID, ht_stack_T **ht_stack, break; } case VAR_FUNC: + abort = set_ref_in_func(tv->vval.v_string, NULL, copyID); + break; case VAR_UNKNOWN: case VAR_SPECIAL: case VAR_FLOAT: @@ -6267,6 +5476,29 @@ bool set_ref_in_item(typval_T *tv, int copyID, ht_stack_T **ht_stack, return abort; } +/// Set "copyID" in all functions available by name. +bool set_ref_in_functions(int copyID) +{ + int todo; + hashitem_T *hi = NULL; + bool abort = false; + ufunc_T *fp; + + todo = (int)func_hashtab.ht_used; + for (hi = func_hashtab.ht_array; todo > 0 && !got_int; hi++) { + if (!HASHITEM_EMPTY(hi)) { + todo--; + fp = HI2UF(hi); + if (!func_name_refcount(fp->uf_name)) { + abort = abort || set_ref_in_func(NULL, fp, copyID); + } + } + } + return abort; +} + + + /// Mark all lists and dicts referenced in given mark /// /// @returns true if setting references failed somehow. @@ -6313,447 +5545,17 @@ static inline bool set_ref_dict(dict_T *dict, int copyID) return false; } -/* - * Allocate an empty header for a dictionary. - */ -dict_T *dict_alloc(void) FUNC_ATTR_NONNULL_RET -{ - dict_T *d = xmalloc(sizeof(dict_T)); - - /* Add the dict to the list of dicts for garbage collection. */ - if (first_dict != NULL) - first_dict->dv_used_prev = d; - d->dv_used_next = first_dict; - d->dv_used_prev = NULL; - first_dict = d; - - hash_init(&d->dv_hashtab); - d->dv_lock = 0; - d->dv_scope = 0; - d->dv_refcount = 0; - d->dv_copyID = 0; - QUEUE_INIT(&d->watchers); - - return d; -} - -/* - * Allocate an empty dict for a return value. - */ -static void rettv_dict_alloc(typval_T *rettv) -{ - dict_T *d = dict_alloc(); - - rettv->vval.v_dict = d; - rettv->v_type = VAR_DICT; - rettv->v_lock = VAR_UNLOCKED; - d->dv_refcount++; -} - -/// Clear all the keys of a Dictionary. "d" remains a valid empty Dictionary. -/// -/// @param d The Dictionary to clear -void dict_clear(dict_T *d) - FUNC_ATTR_NONNULL_ALL -{ - hash_lock(&d->dv_hashtab); - assert(d->dv_hashtab.ht_locked > 0); - - size_t todo = d->dv_hashtab.ht_used; - for (hashitem_T *hi = d->dv_hashtab.ht_array; todo > 0; hi++) { - if (!HASHITEM_EMPTY(hi)) { - dictitem_free(HI2DI(hi)); - hash_remove(&d->dv_hashtab, hi); - todo--; - } - } - - hash_unlock(&d->dv_hashtab); -} - - -/* - * Unreference a Dictionary: decrement the reference count and free it when it - * becomes zero. - */ -void dict_unref(dict_T *d) -{ - if (d != NULL && --d->dv_refcount <= 0) { - dict_free(d); - } -} - -/// Free a Dictionary, including all items it contains. -/// Ignores the reference count. -static void dict_free_contents(dict_T *d) { - int todo; - hashitem_T *hi; - dictitem_T *di; - - - /* Lock the hashtab, we don't want it to resize while freeing items. */ - hash_lock(&d->dv_hashtab); - assert(d->dv_hashtab.ht_locked > 0); - todo = (int)d->dv_hashtab.ht_used; - for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi) { - if (!HASHITEM_EMPTY(hi)) { - /* Remove the item before deleting it, just in case there is - * something recursive causing trouble. */ - di = HI2DI(hi); - hash_remove(&d->dv_hashtab, hi); - clear_tv(&di->di_tv); - xfree(di); - --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); -} - -static void dict_free_dict(dict_T *d) { - // Remove the dict from the list of dicts for garbage collection. - if (d->dv_used_prev == NULL) { - first_dict = d->dv_used_next; - } else { - d->dv_used_prev->dv_used_next = d->dv_used_next; - } - if (d->dv_used_next != NULL) { - d->dv_used_next->dv_used_prev = d->dv_used_prev; - } - - xfree(d); -} - -void dict_free(dict_T *d) { - if (!in_free_unref_items) { - dict_free_contents(d); - dict_free_dict(d); - } -} - -/* - * Allocate a Dictionary item. - * The "key" is copied to the new item. - * Note that the value of the item "di_tv" still needs to be initialized! - */ -dictitem_T *dictitem_alloc(char_u *key) FUNC_ATTR_NONNULL_RET -{ - dictitem_T *di = xmalloc(offsetof(dictitem_T, di_key) + STRLEN(key) + 1); -#ifndef __clang_analyzer__ - STRCPY(di->di_key, key); -#endif - di->di_flags = DI_FLAGS_ALLOC; - return di; -} - -/* - * Make a copy of a Dictionary item. - */ -static dictitem_T *dictitem_copy(dictitem_T *org) FUNC_ATTR_NONNULL_RET -{ - dictitem_T *di = xmalloc(sizeof(dictitem_T) + STRLEN(org->di_key)); - - STRCPY(di->di_key, org->di_key); - di->di_flags = DI_FLAGS_ALLOC; - copy_tv(&org->di_tv, &di->di_tv); - - return di; -} - -/* - * Remove item "item" from Dictionary "dict" and free it. - */ -static void dictitem_remove(dict_T *dict, dictitem_T *item) +static bool set_ref_in_funccal(funccall_T *fc, int copyID) { - hashitem_T *hi; - - hi = hash_find(&dict->dv_hashtab, item->di_key); - if (HASHITEM_EMPTY(hi)) { - EMSG2(_(e_intern2), "dictitem_remove()"); - } else { - hash_remove(&dict->dv_hashtab, hi); - } - dictitem_free(item); -} - -/* - * Free a dict item. Also clears the value. - */ -void dictitem_free(dictitem_T *item) -{ - clear_tv(&item->di_tv); - if (item->di_flags & DI_FLAGS_ALLOC) { - xfree(item); - } -} - -/// Make a copy of dictionary -/// -/// @param[in] conv If non-NULL, then all internal strings will be converted. -/// @param[in] orig Original dictionary to copy. -/// @param[in] deep If false, then shallow copy will be done. -/// @param[in] copyID See var_item_copy(). -/// -/// @return Copied dictionary. May be NULL in case original dictionary is NULL -/// or some failure happens. The refcount of the new dictionary is set -/// to 1. -static dict_T *dict_copy(const vimconv_T *const conv, - dict_T *const orig, - const bool deep, - const int copyID) -{ - dictitem_T *di; - int todo; - hashitem_T *hi; - - if (orig == NULL) - return NULL; - - dict_T *copy = dict_alloc(); - { - if (copyID != 0) { - orig->dv_copyID = copyID; - orig->dv_copydict = copy; - } - todo = (int)orig->dv_hashtab.ht_used; - for (hi = orig->dv_hashtab.ht_array; todo > 0 && !got_int; ++hi) { - if (!HASHITEM_EMPTY(hi)) { - --todo; - - if (conv == NULL || conv->vc_type == CONV_NONE) { - di = dictitem_alloc(hi->hi_key); - } else { - char *const key = (char *) string_convert((vimconv_T *) conv, - hi->hi_key, NULL); - if (key == NULL) { - di = dictitem_alloc(hi->hi_key); - } else { - di = dictitem_alloc((char_u *) key); - xfree(key); - } - } - if (deep) { - if (var_item_copy(conv, &HI2DI(hi)->di_tv, &di->di_tv, deep, - copyID) == FAIL) { - xfree(di); - break; - } - } else - copy_tv(&HI2DI(hi)->di_tv, &di->di_tv); - if (dict_add(copy, di) == FAIL) { - dictitem_free(di); - break; - } - } - } - - ++copy->dv_refcount; - if (todo > 0) { - dict_unref(copy); - copy = NULL; - } - } - - return copy; -} - -/* - * Add item "item" to Dictionary "d". - * Returns FAIL when key already exists. - */ -int dict_add(dict_T *d, dictitem_T *item) -{ - return hash_add(&d->dv_hashtab, item->di_key); -} - -/* - * Add a number or string entry to dictionary "d". - * When "str" is NULL use number "nr", otherwise use "str". - * Returns FAIL when key already exists. - */ -int dict_add_nr_str(dict_T *d, char *key, long nr, char_u *str) -{ - dictitem_T *item; - - item = dictitem_alloc((char_u *)key); - item->di_tv.v_lock = 0; - if (str == NULL) { - item->di_tv.v_type = VAR_NUMBER; - item->di_tv.vval.v_number = nr; - } else { - item->di_tv.v_type = VAR_STRING; - item->di_tv.vval.v_string = vim_strsave(str); - } - if (dict_add(d, item) == FAIL) { - dictitem_free(item); - return FAIL; - } - return OK; -} - -/* - * Add a list entry to dictionary "d". - * Returns FAIL when key already exists. - */ -int dict_add_list(dict_T *d, char *key, list_T *list) -{ - dictitem_T *item = dictitem_alloc((char_u *)key); - - item->di_tv.v_lock = 0; - item->di_tv.v_type = VAR_LIST; - item->di_tv.vval.v_list = list; - if (dict_add(d, item) == FAIL) { - dictitem_free(item); - return FAIL; - } - ++list->lv_refcount; - return OK; -} - -/// Add a dict entry to dictionary "d". -/// Returns FAIL when out of memory and when key already exists. -int dict_add_dict(dict_T *d, char *key, dict_T *dict) -{ - dictitem_T *item = dictitem_alloc((char_u *)key); - - item->di_tv.v_lock = 0; - item->di_tv.v_type = VAR_DICT; - item->di_tv.vval.v_dict = dict; - if (dict_add(d, item) == FAIL) { - dictitem_free(item); - return FAIL; - } - dict->dv_refcount++; - return OK; -} - -/// Set all existing keys in "dict" as read-only. -/// -/// This does not protect against adding new keys to the Dictionary. -/// -/// @param dict The dict whose keys should be frozen -void dict_set_keys_readonly(dict_T *dict) - FUNC_ATTR_NONNULL_ALL -{ - size_t todo = dict->dv_hashtab.ht_used; - for (hashitem_T *hi = dict->dv_hashtab.ht_array; todo > 0 ; hi++) { - if (HASHITEM_EMPTY(hi)) { - continue; - } - todo--; - HI2DI(hi)->di_flags |= DI_FLAGS_RO | DI_FLAGS_FIX; - } -} - -/* - * Get the number of items in a Dictionary. - */ -static long dict_len(dict_T *d) -{ - if (d == NULL) - return 0L; - return (long)d->dv_hashtab.ht_used; -} - -/* - * Find item "key[len]" in Dictionary "d". - * If "len" is negative use strlen(key). - * Returns NULL when not found. - */ -dictitem_T *dict_find(dict_T *d, char_u *key, int len) -{ -#define AKEYLEN 200 - char_u buf[AKEYLEN]; - char_u *akey; - char_u *tofree = NULL; - hashitem_T *hi; - - if (d == NULL) { - return NULL; - } - if (len < 0) { - akey = key; - } else if (len >= AKEYLEN) { - tofree = akey = vim_strnsave(key, len); - } else { - /* Avoid a malloc/free by using buf[]. */ - STRLCPY(buf, key, len + 1); - akey = buf; - } - - hi = hash_find(&d->dv_hashtab, akey); - xfree(tofree); - if (HASHITEM_EMPTY(hi)) - return NULL; - return HI2DI(hi); -} - -/// Get a function from a dictionary -/// @param[out] result The address where a pointer to the wanted callback -/// will be left. -/// @return true/false on success/failure. -static bool get_dict_callback(dict_T *d, char *key, Callback *result) -{ - dictitem_T *di = dict_find(d, (uint8_t *)key, -1); - - if (di == NULL) { - result->type = kCallbackNone; - return true; - } - - if (di->di_tv.v_type != VAR_FUNC && di->di_tv.v_type != VAR_STRING - && di->di_tv.v_type != VAR_PARTIAL) { - EMSG(_("Argument is not a function or function name")); - result->type = kCallbackNone; - return false; - } - - typval_T tv; - copy_tv(&di->di_tv, &tv); - set_selfdict(&tv, d); - bool res = callback_from_typval(result, &tv); - clear_tv(&tv); - return res; -} - -/// Get a string item from a dictionary. -/// -/// @param save whether memory should be allocated for the return value -/// -/// @return the entry or NULL if the entry doesn't exist. -char_u *get_dict_string(dict_T *d, char *key, bool save) -{ - dictitem_T *di; - char_u *s; - - di = dict_find(d, (char_u *)key, -1); - if (di == NULL) { - return NULL; - } - s = get_tv_string(&di->di_tv); - if (save) { - s = vim_strsave(s); - } - return s; -} + bool abort = false; -/// Get a number item from a dictionary. -/// -/// @return the entry or 0 if the entry doesn't exist. -long get_dict_number(dict_T *d, char *key) -{ - dictitem_T *di = dict_find(d, (char_u *)key, -1); - if (di == NULL) { - return 0; + if (fc->fc_copyID != copyID) { + fc->fc_copyID = copyID; + abort = abort || set_ref_in_ht(&fc->l_vars.dv_hashtab, copyID, NULL); + abort = abort || set_ref_in_ht(&fc->l_avars.dv_hashtab, copyID, NULL); + abort = abort || set_ref_in_func(NULL, fc->func, copyID); } - return get_tv_number(&di->di_tv); + return abort; } /* @@ -6768,7 +5570,7 @@ static int get_dict_tv(char_u **arg, typval_T *rettv, int evaluate) char_u *key = NULL; dictitem_T *item; char_u *start = skipwhite(*arg + 1); - char_u buf[NUMBUFLEN]; + char buf[NUMBUFLEN]; /* * First check if it's not a curly-braces thing: {expr}. @@ -6785,7 +5587,7 @@ static int get_dict_tv(char_u **arg, typval_T *rettv, int evaluate) } if (evaluate) { - d = dict_alloc(); + d = tv_dict_alloc(); } tvkey.v_type = VAR_UNKNOWN; tv.v_type = VAR_UNKNOWN; @@ -6796,38 +5598,39 @@ static int get_dict_tv(char_u **arg, typval_T *rettv, int evaluate) goto failret; if (**arg != ':') { EMSG2(_("E720: Missing colon in Dictionary: %s"), *arg); - clear_tv(&tvkey); + tv_clear(&tvkey); goto failret; } if (evaluate) { - key = get_tv_string_buf_chk(&tvkey, buf); + key = (char_u *)tv_get_string_buf_chk(&tvkey, buf); if (key == NULL) { - // "key" is NULL when get_tv_string_buf_chk() gave an errmsg - clear_tv(&tvkey); + // "key" is NULL when tv_get_string_buf_chk() gave an errmsg + tv_clear(&tvkey); goto failret; } } *arg = skipwhite(*arg + 1); - if (eval1(arg, &tv, evaluate) == FAIL) { /* recursive! */ - if (evaluate) - clear_tv(&tvkey); + if (eval1(arg, &tv, evaluate) == FAIL) { // Recursive! + if (evaluate) { + tv_clear(&tvkey); + } goto failret; } if (evaluate) { - item = dict_find(d, key, -1); + item = tv_dict_find(d, (const char *)key, -1); if (item != NULL) { EMSG2(_("E721: Duplicate key in Dictionary: \"%s\""), key); - clear_tv(&tvkey); - clear_tv(&tv); + tv_clear(&tvkey); + tv_clear(&tv); goto failret; } - item = dictitem_alloc(key); - clear_tv(&tvkey); + item = tv_dict_item_alloc((const char *)key); + tv_clear(&tvkey); item->di_tv = tv; item->di_tv.v_lock = 0; - if (dict_add(d, item) == FAIL) { - dictitem_free(item); + if (tv_dict_add(d, item) == FAIL) { + tv_dict_item_free(item); } } @@ -6844,7 +5647,7 @@ static int get_dict_tv(char_u **arg, typval_T *rettv, int evaluate) EMSG2(_("E723: Missing end of Dictionary '}': %s"), *arg); failret: if (evaluate) { - dict_free(d); + tv_dict_free(d); } return FAIL; } @@ -6859,6 +5662,232 @@ failret: return OK; } +/// Get function arguments. +static int get_function_args(char_u **argp, char_u endchar, garray_T *newargs, + int *varargs, bool skip) +{ + bool mustend = false; + char_u *arg = *argp; + char_u *p = arg; + int c; + int i; + + if (newargs != NULL) { + ga_init(newargs, (int)sizeof(char_u *), 3); + } + + if (varargs != NULL) { + *varargs = false; + } + + // Isolate the arguments: "arg1, arg2, ...)" + while (*p != endchar) { + if (p[0] == '.' && p[1] == '.' && p[2] == '.') { + if (varargs != NULL) { + *varargs = true; + } + p += 3; + mustend = true; + } else { + arg = p; + while (ASCII_ISALNUM(*p) || *p == '_') { + p++; + } + if (arg == p || isdigit(*arg) + || (p - arg == 9 && STRNCMP(arg, "firstline", 9) == 0) + || (p - arg == 8 && STRNCMP(arg, "lastline", 8) == 0)) { + if (!skip) { + EMSG2(_("E125: Illegal argument: %s"), arg); + } + break; + } + if (newargs != NULL) { + ga_grow(newargs, 1); + c = *p; + *p = NUL; + arg = vim_strsave(arg); + if (arg == NULL) { + *p = c; + goto err_ret; + } + + // Check for duplicate argument name. + for (i = 0; i < newargs->ga_len; i++) { + if (STRCMP(((char_u **)(newargs->ga_data))[i], arg) == 0) { + EMSG2(_("E853: Duplicate argument name: %s"), arg); + xfree(arg); + goto err_ret; + } + } + ((char_u **)(newargs->ga_data))[newargs->ga_len] = arg; + newargs->ga_len++; + + *p = c; + } + if (*p == ',') { + p++; + } else { + mustend = true; + } + } + p = skipwhite(p); + if (mustend && *p != endchar) { + if (!skip) { + EMSG2(_(e_invarg2), *argp); + } + break; + } + } + if (*p != endchar) { + goto err_ret; + } + p++; // skip "endchar" + + *argp = p; + return OK; + +err_ret: + if (newargs != NULL) { + ga_clear_strings(newargs); + } + return FAIL; +} + +/// Register function "fp" as using "current_funccal" as its scope. +static void register_closure(ufunc_T *fp) +{ + if (fp->uf_scoped == current_funccal) { + // no change + return; + } + funccal_unref(fp->uf_scoped, fp, false); + fp->uf_scoped = current_funccal; + current_funccal->fc_refcount++; + ga_grow(¤t_funccal->fc_funcs, 1); + ((ufunc_T **)current_funccal->fc_funcs.ga_data) + [current_funccal->fc_funcs.ga_len++] = fp; +} + +/// Parse a lambda expression and get a Funcref from "*arg". +/// +/// @return OK or FAIL. Returns NOTDONE for dict or {expr}. +static int get_lambda_tv(char_u **arg, typval_T *rettv, bool evaluate) +{ + garray_T newargs = GA_EMPTY_INIT_VALUE; + garray_T *pnewargs; + ufunc_T *fp = NULL; + int varargs; + int ret; + char_u *start = skipwhite(*arg + 1); + char_u *s, *e; + static int lambda_no = 0; + int *old_eval_lavars = eval_lavars_used; + int eval_lavars = false; + + // First, check if this is a lambda expression. "->" must exists. + ret = get_function_args(&start, '-', NULL, NULL, true); + if (ret == FAIL || *start != '>') { + return NOTDONE; + } + + // Parse the arguments again. + if (evaluate) { + pnewargs = &newargs; + } else { + pnewargs = NULL; + } + *arg = skipwhite(*arg + 1); + ret = get_function_args(arg, '-', pnewargs, &varargs, false); + if (ret == FAIL || **arg != '>') { + goto errret; + } + + // Set up a flag for checking local variables and arguments. + if (evaluate) { + eval_lavars_used = &eval_lavars; + } + + // Get the start and the end of the expression. + *arg = skipwhite(*arg + 1); + s = *arg; + ret = skip_expr(arg); + if (ret == FAIL) { + goto errret; + } + e = *arg; + *arg = skipwhite(*arg); + if (**arg != '}') { + goto errret; + } + (*arg)++; + + if (evaluate) { + int len, flags = 0; + char_u *p; + char_u name[20]; + partial_T *pt; + garray_T newlines; + + lambda_no++; + snprintf((char *)name, sizeof(name), "<lambda>%d", lambda_no); + + fp = (ufunc_T *)xcalloc(1, sizeof(ufunc_T) + STRLEN(name)); + pt = (partial_T *)xcalloc(1, sizeof(partial_T)); + if (pt == NULL) { + xfree(fp); + goto errret; + } + + ga_init(&newlines, (int)sizeof(char_u *), 1); + ga_grow(&newlines, 1); + + // Add "return " before the expression. + len = 7 + e - s + 1; + p = (char_u *)xmalloc(len); + ((char_u **)(newlines.ga_data))[newlines.ga_len++] = p; + STRCPY(p, "return "); + STRLCPY(p + 7, s, e - s + 1); + + fp->uf_refcount = 1; + STRCPY(fp->uf_name, name); + hash_add(&func_hashtab, UF2HIKEY(fp)); + fp->uf_args = newargs; + fp->uf_lines = newlines; + if (current_funccal != NULL && eval_lavars) { + flags |= FC_CLOSURE; + register_closure(fp); + } else { + fp->uf_scoped = NULL; + } + + fp->uf_tml_count = NULL; + fp->uf_tml_total = NULL; + fp->uf_tml_self = NULL; + fp->uf_profiling = false; + if (prof_def_func()) { + func_do_profile(fp); + } + fp->uf_varargs = true; + fp->uf_flags = flags; + fp->uf_calls = 0; + fp->uf_script_ID = current_SID; + + pt->pt_func = fp; + pt->pt_refcount = 1; + rettv->vval.v_partial = pt; + rettv->v_type = VAR_PARTIAL; + } + + eval_lavars_used = old_eval_lavars; + return OK; + +errret: + ga_clear_strings(&newargs); + xfree(fp); + eval_lavars_used = old_eval_lavars; + return FAIL; +} + /// Convert the string to a floating point number /// /// This uses strtod(). setlocale(LC_NUMERIC, "C") has been used earlier to @@ -6873,6 +5902,19 @@ size_t string2float(const char *const text, float_T *const ret_value) { char *s = NULL; + // MS-Windows does not deal with "inf" and "nan" properly + if (STRNICMP(text, "inf", 3) == 0) { + *ret_value = INFINITY; + return 3; + } + if (STRNICMP(text, "-inf", 3) == 0) { + *ret_value = -INFINITY; + return 4; + } + if (STRNICMP(text, "nan", 3) == 0) { + *ret_value = NAN; + return 3; + } *ret_value = strtod(text, &s); return (size_t) (s - text); } @@ -6893,7 +5935,7 @@ static int get_env_tv(char_u **arg, typval_T *rettv, int evaluate) ++*arg; name = *arg; - len = get_env_len(arg); + len = get_env_len((const char_u **)arg); if (evaluate) { if (len == 0) { @@ -6981,64 +6023,67 @@ char_u *get_expr_name(expand_T *xp, int idx) return get_user_var_name(xp, ++intidx); } - - - /// Find internal function in hash functions /// /// @param[in] name Name of the function. /// /// Returns pointer to the function definition or NULL if not found. -static VimLFuncDef *find_internal_func(const char *const name) +static const VimLFuncDef *find_internal_func(const char *const name) FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE FUNC_ATTR_NONNULL_ALL { size_t len = strlen(name); return find_internal_func_gperf(name, len); } -/// Check if "name" is a variable of type VAR_FUNC. If so, return the function -/// name it contains, otherwise return "name". -/// If "partialp" is not NULL, and "name" is of type VAR_PARTIAL also set -/// "partialp". -static char_u *deref_func_name( - char_u *name, int *lenp, - partial_T **partialp, bool no_autoload -) +/// Return name of the function corresponding to `name` +/// +/// If `name` points to variable that is either a function or partial then +/// corresponding function name is returned. Otherwise it returns `name` itself. +/// +/// @param[in] name Function name to check. +/// @param[in,out] lenp Location where length of the returned name is stored. +/// Must be set to the length of the `name` argument. +/// @param[out] partialp Location where partial will be stored if found +/// function appears to be a partial. May be NULL if this +/// is not needed. +/// @param[in] no_autoload If true, do not source autoload scripts if function +/// was not found. +/// +/// @return name of the function. +static char_u *deref_func_name(const char *name, int *lenp, + partial_T **const partialp, bool no_autoload) + FUNC_ATTR_NONNULL_ARG(1, 2) { - dictitem_T *v; - int cc; if (partialp != NULL) { *partialp = NULL; } - cc = name[*lenp]; - name[*lenp] = NUL; - v = find_var(name, NULL, no_autoload); - name[*lenp] = cc; + dictitem_T *const v = find_var(name, (size_t)(*lenp), NULL, no_autoload); if (v != NULL && v->di_tv.v_type == VAR_FUNC) { - if (v->di_tv.vval.v_string == NULL) { + if (v->di_tv.vval.v_string == NULL) { // just in case *lenp = 0; - return (char_u *)""; /* just in case */ + return (char_u *)""; } *lenp = (int)STRLEN(v->di_tv.vval.v_string); return v->di_tv.vval.v_string; } if (v != NULL && v->di_tv.v_type == VAR_PARTIAL) { - partial_T *pt = v->di_tv.vval.v_partial; + partial_T *const pt = v->di_tv.vval.v_partial; - if (pt == NULL) { + if (pt == NULL) { // just in case *lenp = 0; - return (char_u *)""; // just in case + return (char_u *)""; } if (partialp != NULL) { *partialp = pt; } - *lenp = (int)STRLEN(pt->pt_name); - return pt->pt_name; + char_u *s = partial_name(pt); + *lenp = (int)STRLEN(s); + return s; } - return name; + return (char_u *)name; } /* @@ -7087,9 +6132,24 @@ get_func_tv ( ret = FAIL; if (ret == OK) { - ret = call_func(name, len, rettv, argcount, argvars, + int i = 0; + + if (get_vim_var_nr(VV_TESTING)) { + // Prepare for calling garbagecollect_for_testing(), need to know + // what variables are used on the call stack. + if (funcargs.ga_itemsize == 0) { + ga_init(&funcargs, (int)sizeof(typval_T *), 50); + } + for (i = 0; i < argcount; i++) { + ga_grow(&funcargs, 1); + ((typval_T **)funcargs.ga_data)[funcargs.ga_len++] = &argvars[i]; + } + } + ret = call_func(name, len, rettv, argcount, argvars, NULL, firstline, lastline, doesrange, evaluate, partial, selfdict); + + funcargs.ga_len -= i; } else if (!aborting()) { if (argcount == MAX_FUNC_ARGS) { emsg_funcname(N_("E740: Too many arguments for function %s"), name); @@ -7098,40 +6158,57 @@ get_func_tv ( } } - while (--argcount >= 0) - clear_tv(&argvars[argcount]); + while (--argcount >= 0) { + tv_clear(&argvars[argcount]); + } *arg = skipwhite(argp); return ret; } -#define ERROR_UNKNOWN 0 -#define ERROR_TOOMANY 1 -#define ERROR_TOOFEW 2 -#define ERROR_SCRIPT 3 -#define ERROR_DICT 4 -#define ERROR_NONE 5 -#define ERROR_OTHER 6 -#define ERROR_BOTH 7 +typedef enum { + ERROR_UNKNOWN = 0, + ERROR_TOOMANY, + ERROR_TOOFEW, + ERROR_SCRIPT, + ERROR_DICT, + ERROR_NONE, + ERROR_OTHER, + ERROR_BOTH, + ERROR_DELETED, +} FnameTransError; + #define FLEN_FIXED 40 -/// In a script change <SID>name() and s:name() to K_SNR 123_name(). -/// Change <SNR>123_name() to K_SNR 123_name(). -/// Use "fname_buf[FLEN_FIXED + 1]" when it fits, otherwise allocate memory -/// (slow). -static char_u * -fname_trans_sid(char_u *name, char_u *fname_buf, char_u **tofree, int *error) { - int llen; +/// In a script transform script-local names into actually used names +/// +/// Transforms "<SID>" and "s:" prefixes to `K_SNR {N}` (e.g. K_SNR "123") and +/// "<SNR>" prefix to `K_SNR`. Uses `fname_buf` buffer that is supposed to have +/// #FLEN_FIXED + 1 length when it fits, otherwise it allocates memory. +/// +/// @param[in] name Name to transform. +/// @param fname_buf Buffer to save resulting function name to, if it fits. +/// Must have at least #FLEN_FIXED + 1 length. +/// @param[out] tofree Location where pointer to an allocated memory is saved +/// in case result does not fit into fname_buf. +/// @param[out] error Location where error type is saved, @see +/// FnameTransError. +/// +/// @return transformed name: either `fname_buf` or a pointer to an allocated +/// memory. +static char_u *fname_trans_sid(const char_u *const name, + char_u *const fname_buf, + char_u **const tofree, int *const error) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ char_u *fname; - int i; - - llen = eval_fname_script(name); + const int llen = eval_fname_script((const char *)name); if (llen > 0) { fname_buf[0] = K_SPECIAL; fname_buf[1] = KS_EXTRA; fname_buf[2] = (int)KE_SNR; - i = 3; - if (eval_fname_sid(name)) { // "<SID>" or "s:" + int i = 3; + if (eval_fname_sid((const char *)name)) { // "<SID>" or "s:" if (current_SID <= 0) { *error = ERROR_SCRIPT; } else { @@ -7154,23 +6231,60 @@ fname_trans_sid(char_u *name, char_u *fname_buf, char_u **tofree, int *error) { } } } else { - fname = name; + fname = (char_u *)name; } return fname; } +/// Mark all lists and dicts referenced through function "name" with "copyID". +/// "list_stack" is used to add lists to be marked. Can be NULL. +/// "ht_stack" is used to add hashtabs to be marked. Can be NULL. +/// +/// @return true if setting references failed somehow. +bool set_ref_in_func(char_u *name, ufunc_T *fp_in, int copyID) +{ + ufunc_T *fp = fp_in; + funccall_T *fc; + int error = ERROR_NONE; + char_u fname_buf[FLEN_FIXED + 1]; + char_u *tofree = NULL; + char_u *fname; + bool abort = false; + if (name == NULL && fp_in == NULL) { + return false; + } + + if (fp_in == NULL) { + fname = fname_trans_sid(name, fname_buf, &tofree, &error); + fp = find_func(fname); + } + if (fp != NULL) { + for (fc = fp->uf_scoped; fc != NULL; fc = fc->func->uf_scoped) { + abort = abort || set_ref_in_funccal(fc, copyID); + } + } + xfree(tofree); + return abort; +} + /// Call a function with its resolved parameters +/// +/// "argv_func", when not NULL, can be used to fill in arguments only when the +/// invoked function uses them. It is called like this: +/// new_argcount = argv_func(current_argcount, argv, called_func_argcount) +/// /// Return FAIL when the function can't be called, OK otherwise. /// Also returns OK when an error was encountered while executing the function. int call_func( - char_u *funcname, // name of the function + const char_u *funcname, // name of the function int len, // length of "name" typval_T *rettv, // return value goes here int argcount_in, // number of "argvars" typval_T *argvars_in, // vars for arguments, must have "argcount" // PLUS ONE elements! + ArgvFunc argv_func, // function to fill in argvars linenr_T firstline, // first line of range linenr_T lastline, // last line of range int *doesrange, // return: function handled range @@ -7213,7 +6327,7 @@ call_func( } if (error == ERROR_NONE && partial->pt_argc > 0) { for (argv_clear = 0; argv_clear < partial->pt_argc; argv_clear++) { - copy_tv(&partial->pt_argv[argv_clear], &argv[argv_clear]); + tv_copy(&partial->pt_argv[argv_clear], &argv[argv_clear]); } for (int i = 0; i < argcount_in; i++) { argv[i + argv_clear] = argvars_in[i]; @@ -7237,44 +6351,53 @@ call_func( rettv->vval.v_number = 0; error = ERROR_UNKNOWN; - if (!builtin_function(rfname, -1)) { - /* - * User defined function. - */ - fp = find_func(rfname); + if (!builtin_function((const char *)rfname, -1)) { + // User defined function. + if (partial != NULL && partial->pt_func != NULL) { + fp = partial->pt_func; + } else { + fp = find_func(rfname); + } - /* Trigger FuncUndefined event, may load the function. */ + // Trigger FuncUndefined event, may load the function. if (fp == NULL && apply_autocmds(EVENT_FUNCUNDEFINED, rfname, rfname, TRUE, NULL) && !aborting()) { /* executed an autocommand, search for the function again */ fp = find_func(rfname); } - /* Try loading a package. */ - if (fp == NULL && script_autoload(rfname, TRUE) && !aborting()) { - /* loaded a package, search for the function again */ + // Try loading a package. + if (fp == NULL && script_autoload((const char *)rfname, STRLEN(rfname), + true) && !aborting()) { + // Loaded a package, search for the function again. fp = find_func(rfname); } - if (fp != NULL) { - if (fp->uf_flags & FC_RANGE) - *doesrange = TRUE; - if (argcount < fp->uf_args.ga_len) + if (fp != NULL && (fp->uf_flags & FC_DELETED)) { + error = ERROR_DELETED; + } else if (fp != NULL) { + if (argv_func != NULL) { + argcount = argv_func(argcount, argvars, fp->uf_args.ga_len); + } + if (fp->uf_flags & FC_RANGE) { + *doesrange = true; + } + if (argcount < fp->uf_args.ga_len) { error = ERROR_TOOFEW; - else if (!fp->uf_varargs && argcount > fp->uf_args.ga_len) + } else if (!fp->uf_varargs && argcount > fp->uf_args.ga_len) { error = ERROR_TOOMANY; - else if ((fp->uf_flags & FC_DICT) && selfdict == NULL) + } else if ((fp->uf_flags & FC_DICT) && selfdict == NULL) { error = ERROR_DICT; - else { + } else { // Call the user function. call_user_func(fp, argcount, argvars, rettv, firstline, lastline, - (fp->uf_flags & FC_DICT) ? selfdict : NULL); + (fp->uf_flags & FC_DICT) ? selfdict : NULL); error = ERROR_NONE; } } } else { // Find the function name in the table, call its implementation. - VimLFuncDef *const fdef = find_internal_func((char *)fname); + const VimLFuncDef *const fdef = find_internal_func((const char *)fname); if (fdef != NULL) { if (argcount < fdef->min_argc) { error = ERROR_TOOFEW; @@ -7311,6 +6434,9 @@ call_func( case ERROR_UNKNOWN: emsg_funcname(N_("E117: Unknown function: %s"), name); break; + case ERROR_DELETED: + emsg_funcname(N_("E933: Function was deleted: %s"), name); + break; case ERROR_TOOMANY: emsg_funcname(e_toomanyarg, name); break; @@ -7330,7 +6456,7 @@ call_func( } while (argv_clear > 0) { - clear_tv(&argv[--argv_clear]); + tv_clear(&argv[--argv_clear]); } xfree(tofree); xfree(name); @@ -7360,11 +6486,13 @@ static void emsg_funcname(char *ermsg, char_u *name) */ static int non_zero_arg(typval_T *argvars) { - return (argvars[0].v_type == VAR_NUMBER - && argvars[0].vval.v_number != 0) - || (argvars[0].v_type == VAR_STRING - && argvars[0].vval.v_string != NULL - && *argvars[0].vval.v_string != NUL); + return ((argvars[0].v_type == VAR_NUMBER + && argvars[0].vval.v_number != 0) + || (argvars[0].v_type == VAR_SPECIAL + && argvars[0].vval.v_special == kSpecialVarTrue) + || (argvars[0].v_type == VAR_STRING + && argvars[0].vval.v_string != NULL + && *argvars[0].vval.v_string != NUL)); } /********************************************* @@ -7372,24 +6500,6 @@ static int non_zero_arg(typval_T *argvars) */ -/* - * Get the float value of "argvars[0]" into "f". - * Returns FAIL when the argument is not a Number or Float. - */ -static inline int get_float_arg(typval_T *argvars, float_T *f) -{ - if (argvars[0].v_type == VAR_FLOAT) { - *f = argvars[0].vval.v_float; - return OK; - } - if (argvars[0].v_type == VAR_NUMBER) { - *f = (float_T)argvars[0].vval.v_number; - return OK; - } - EMSG(_("E808: Number or Float required")); - return FAIL; -} - // Apply a floating point C function on a typval with one float_T. // // Some versions of glibc on i386 have an optimization that makes it harder to @@ -7401,7 +6511,7 @@ static void float_op_wrapper(typval_T *argvars, typval_T *rettv, FunPtr fptr) float_T (*function)(float_T) = (float_T (*)(float_T))fptr; rettv->v_type = VAR_FLOAT; - if (get_float_arg(argvars, &f) == OK) { + if (tv_get_float_chk(argvars, &f)) { rettv->vval.v_float = function(f); } else { rettv->vval.v_float = 0.0; @@ -7419,9 +6529,9 @@ static void api_wrapper(typval_T *argvars, typval_T *rettv, FunPtr fptr) } Error err = ERROR_INIT; - Object result = fn(INTERNAL_CALL, args, &err); + Object result = fn(VIML_INTERNAL_CALL, args, &err); - if (err.set) { + if (ERROR_SET(&err)) { nvim_err_writeln(cstr_as_string(err.msg)); goto end; } @@ -7433,6 +6543,7 @@ static void api_wrapper(typval_T *argvars, typval_T *rettv, FunPtr fptr) end: api_free_array(args); api_free_object(result); + api_clear_error(&err); } /* @@ -7444,15 +6555,16 @@ static void f_abs(typval_T *argvars, typval_T *rettv, FunPtr fptr) float_op_wrapper(argvars, rettv, (FunPtr)&fabs); } else { varnumber_T n; - int error = FALSE; + bool error = false; - n = get_tv_number_chk(&argvars[0], &error); - if (error) + n = tv_get_number_chk(&argvars[0], &error); + if (error) { rettv->vval.v_number = -1; - else if (n > 0) + } else if (n > 0) { rettv->vval.v_number = n; - else + } else { rettv->vval.v_number = -n; + } } } @@ -7466,13 +6578,13 @@ static void f_add(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_number = 1; /* Default: Failed */ if (argvars[0].v_type == VAR_LIST) { if ((l = argvars[0].vval.v_list) != NULL - && !tv_check_lock(l->lv_lock, - (char_u *)N_("add() argument"), true)) { - list_append_tv(l, &argvars[1]); - copy_tv(&argvars[0], rettv); + && !tv_check_lock(l->lv_lock, "add() argument", TV_TRANSLATE)) { + tv_list_append_tv(l, &argvars[1]); + tv_copy(&argvars[0], rettv); } - } else + } else { EMSG(_(e_listreq)); + } } /* @@ -7480,8 +6592,8 @@ static void f_add(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_and(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - rettv->vval.v_number = get_tv_number_chk(&argvars[0], NULL) - & get_tv_number_chk(&argvars[1], NULL); + rettv->vval.v_number = tv_get_number_chk(&argvars[0], NULL) + & tv_get_number_chk(&argvars[1], NULL); } @@ -7499,7 +6611,6 @@ static void f_api_info(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_append(typval_T *argvars, typval_T *rettv, FunPtr fptr) { long lnum; - char_u *line; list_T *l = NULL; listitem_T *li = NULL; typval_T *tv; @@ -7512,7 +6623,7 @@ static void f_append(typval_T *argvars, typval_T *rettv, FunPtr fptr) u_sync(TRUE); } - lnum = get_tv_lnum(argvars); + lnum = tv_get_lnum(argvars); if (lnum >= 0 && lnum <= curbuf->b_ml.ml_line_count && u_save(lnum, lnum + 1) == OK) { @@ -7523,21 +6634,23 @@ static void f_append(typval_T *argvars, typval_T *rettv, FunPtr fptr) li = l->lv_first; } for (;; ) { - if (l == NULL) - tv = &argvars[1]; /* append a string */ - else if (li == NULL) - break; /* end of list */ - else - tv = &li->li_tv; /* append item from list */ - line = get_tv_string_chk(tv); - if (line == NULL) { /* type error */ - rettv->vval.v_number = 1; /* Failed */ + if (l == NULL) { + tv = &argvars[1]; // Append a string. + } else if (li == NULL) { + break; // End of list. + } else { + tv = &li->li_tv; // Append item from list. + } + const char *const line = tv_get_string_chk(tv); + if (line == NULL) { // Type error. + rettv->vval.v_number = 1; // Failed. break; } - ml_append(lnum + added, line, (colnr_T)0, FALSE); - ++added; - if (l == NULL) + ml_append(lnum + added, (char_u *)line, (colnr_T)0, false); + added++; + if (l == NULL) { break; + } li = li->li_next; } @@ -7582,16 +6695,19 @@ static void f_argv(typval_T *argvars, typval_T *rettv, FunPtr fptr) int idx; if (argvars[0].v_type != VAR_UNKNOWN) { - idx = get_tv_number_chk(&argvars[0], NULL); - if (idx >= 0 && idx < ARGCOUNT) - rettv->vval.v_string = vim_strsave(alist_name(&ARGLIST[idx])); - else + idx = (int)tv_get_number_chk(&argvars[0], NULL); + if (idx >= 0 && idx < ARGCOUNT) { + rettv->vval.v_string = (char_u *)xstrdup( + (const char *)alist_name(&ARGLIST[idx])); + } else { rettv->vval.v_string = NULL; + } rettv->v_type = VAR_STRING; } else { - rettv_list_alloc(rettv); - for (idx = 0; idx < ARGCOUNT; ++idx) { - list_append_string(rettv->vval.v_list, alist_name(&ARGLIST[idx]), -1); + tv_list_alloc_ret(rettv); + for (idx = 0; idx < ARGCOUNT; idx++) { + tv_list_append_string(rettv->vval.v_list, + (const char *)alist_name(&ARGLIST[idx]), -1); } } } @@ -7663,10 +6779,10 @@ static void assert_error(garray_T *gap) if (vp->vv_type != VAR_LIST || vimvars[VV_ERRORS].vv_list == NULL) { // Make sure v:errors is a list. - set_vim_var_list(VV_ERRORS, list_alloc()); + set_vim_var_list(VV_ERRORS, tv_list_alloc()); } - list_append_string(vimvars[VV_ERRORS].vv_list, - gap->ga_data, gap->ga_len); + tv_list_append_string(vimvars[VV_ERRORS].vv_list, + (const char *)gap->ga_data, (ptrdiff_t)gap->ga_len); } static void assert_equal_common(typval_T *argvars, assert_type_T atype) @@ -7695,12 +6811,23 @@ static void f_assert_notequal(typval_T *argvars, typval_T *rettv, FunPtr fptr) assert_equal_common(argvars, ASSERT_NOTEQUAL); } +/// "assert_report(msg) +static void f_assert_report(typval_T *argvars, typval_T *rettv, FunPtr fptr) +{ + garray_T ga; + + prepare_assert_error(&ga); + ga_concat(&ga, (const char_u *)tv_get_string(&argvars[0])); + assert_error(&ga); + ga_clear(&ga); +} + /// "assert_exception(string[, msg])" function static void f_assert_exception(typval_T *argvars, typval_T *rettv, FunPtr fptr) { garray_T ga; - char *error = (char *)get_tv_string_chk(&argvars[0]); + const char *const error = tv_get_string_chk(&argvars[0]); if (vimvars[VV_EXCEPTION].vv_str == NULL) { prepare_assert_error(&ga); ga_concat(&ga, (char_u *)"v:exception is not set"); @@ -7719,22 +6846,22 @@ static void f_assert_exception(typval_T *argvars, typval_T *rettv, FunPtr fptr) /// "assert_fails(cmd [, error])" function static void f_assert_fails(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *cmd = get_tv_string_chk(&argvars[0]); + const char *const cmd = tv_get_string_chk(&argvars[0]); garray_T ga; called_emsg = false; suppress_errthrow = true; emsg_silent = true; - do_cmdline_cmd((char *)cmd); + do_cmdline_cmd(cmd); if (!called_emsg) { prepare_assert_error(&ga); - ga_concat(&ga, (char_u *)"command did not fail: "); - ga_concat(&ga, cmd); + ga_concat(&ga, (const char_u *)"command did not fail: "); + ga_concat(&ga, (const char_u *)cmd); assert_error(&ga); ga_clear(&ga); } else if (argvars[1].v_type != VAR_UNKNOWN) { - char_u buf[NUMBUFLEN]; - char *error = (char *)get_tv_string_buf_chk(&argvars[1], buf); + char buf[NUMBUFLEN]; + const char *const error = tv_get_string_buf_chk(&argvars[1], buf); if (error == NULL || strstr((char *)vimvars[VV_ERRMSG].vv_str, error) == NULL) { @@ -7753,14 +6880,39 @@ static void f_assert_fails(typval_T *argvars, typval_T *rettv, FunPtr fptr) set_vim_var_string(VV_ERRMSG, NULL, 0); } +void assert_inrange(typval_T *argvars) +{ + bool error = false; + const varnumber_T lower = tv_get_number_chk(&argvars[0], &error); + const varnumber_T upper = tv_get_number_chk(&argvars[1], &error); + const varnumber_T actual = tv_get_number_chk(&argvars[2], &error); + + if (error) { + return; + } + if (actual < lower || actual > upper) { + garray_T ga; + prepare_assert_error(&ga); + + char msg[55]; + vim_snprintf(msg, sizeof(msg), + "range %" PRIdVARNUMBER " - %" PRIdVARNUMBER ",", + lower, upper); + fill_assert_error(&ga, &argvars[3], (char_u *)msg, NULL, &argvars[2], + ASSERT_INRANGE); + assert_error(&ga); + ga_clear(&ga); + } +} + // Common for assert_true() and assert_false(). static void assert_bool(typval_T *argvars, bool is_true) { - int error = (int)false; + bool error = false; garray_T ga; if ((argvars[0].v_type != VAR_NUMBER - || (get_tv_number_chk(&argvars[0], &error) == 0) == is_true + || (tv_get_number_chk(&argvars[0], &error) == 0) == is_true || error) && (argvars[0].v_type != VAR_SPECIAL || (argvars[0].vval.v_special @@ -7784,14 +6936,15 @@ static void f_assert_false(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void assert_match_common(typval_T *argvars, assert_type_T atype) { - char_u buf1[NUMBUFLEN]; - char_u buf2[NUMBUFLEN]; - char_u *pat = get_tv_string_buf_chk(&argvars[0], buf1); - char_u *text = get_tv_string_buf_chk(&argvars[1], buf2); + char buf1[NUMBUFLEN]; + char buf2[NUMBUFLEN]; + const char *const pat = tv_get_string_buf_chk(&argvars[0], buf1); + const char *const text = tv_get_string_buf_chk(&argvars[1], buf2); if (pat == NULL || text == NULL) { EMSG(_(e_invarg)); - } else if (pattern_match(pat, text, false) != (atype == ASSERT_MATCH)) { + } else if (pattern_match((char_u *)pat, (char_u *)text, false) + != (atype == ASSERT_MATCH)) { garray_T ga; prepare_assert_error(&ga); fill_assert_error(&ga, &argvars[2], NULL, &argvars[0], &argvars[1], atype); @@ -7800,6 +6953,12 @@ static void assert_match_common(typval_T *argvars, assert_type_T atype) } } +/// "assert_inrange(lower, upper[, msg])" function +static void f_assert_inrange(typval_T *argvars, typval_T *rettv, FunPtr fptr) +{ + assert_inrange(argvars); +} + /// "assert_match(pattern, actual[, msg])" function static void f_assert_match(typval_T *argvars, typval_T *rettv, FunPtr fptr) { @@ -7823,14 +6982,15 @@ static void f_assert_true(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_atan2(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - float_T fx, fy; + float_T fx; + float_T fy; rettv->v_type = VAR_FLOAT; - if (get_float_arg(argvars, &fx) == OK - && get_float_arg(&argvars[1], &fy) == OK) + if (tv_get_float_chk(argvars, &fx) && tv_get_float_chk(&argvars[1], &fy)) { rettv->vval.v_float = atan2(fx, fy); - else + } else { rettv->vval.v_float = 0.0; + } } /* @@ -7954,17 +7114,17 @@ static buf_T *get_buf_tv(typval_T *tv, int curtab_only) */ static void f_bufname(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - buf_T *buf; - - (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */ - ++emsg_off; - buf = get_buf_tv(&argvars[0], FALSE); rettv->v_type = VAR_STRING; - if (buf != NULL && buf->b_fname != NULL) - rettv->vval.v_string = vim_strsave(buf->b_fname); - else - rettv->vval.v_string = NULL; - --emsg_off; + rettv->vval.v_string = NULL; + if (!tv_check_str_or_nr(&argvars[0])) { + return; + } + emsg_off++; + const buf_T *const buf = get_buf_tv(&argvars[0], false); + emsg_off--; + if (buf != NULL && buf->b_fname != NULL) { + rettv->vval.v_string = (char_u *)xstrdup((char *)buf->b_fname); + } } /* @@ -7972,36 +7132,36 @@ static void f_bufname(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_bufnr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - buf_T *buf; - int error = FALSE; - char_u *name; + bool error = false; - (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */ - ++emsg_off; - buf = get_buf_tv(&argvars[0], FALSE); - --emsg_off; + rettv->vval.v_number = -1; + if (!tv_check_str_or_nr(&argvars[0])) { + return; + } + emsg_off++; + const buf_T *buf = get_buf_tv(&argvars[0], false); + emsg_off--; - /* If the buffer isn't found and the second argument is not zero create a - * new buffer. */ + // If the buffer isn't found and the second argument is not zero create a + // new buffer. + const char *name; if (buf == NULL && argvars[1].v_type != VAR_UNKNOWN - && get_tv_number_chk(&argvars[1], &error) != 0 + && tv_get_number_chk(&argvars[1], &error) != 0 && !error - && (name = get_tv_string_chk(&argvars[0])) != NULL - && !error) - buf = buflist_new(name, NULL, (linenr_T)1, 0); + && (name = tv_get_string_chk(&argvars[0])) != NULL + && !error) { + buf = buflist_new((char_u *)name, NULL, 1, 0); + } - if (buf != NULL) + if (buf != NULL) { rettv->vval.v_number = buf->b_fnum; - else - rettv->vval.v_number = -1; + } } static void buf_win_common(typval_T *argvars, typval_T *rettv, bool get_nr) { - int error = false; - (void)get_tv_number_chk(&argvars[0], &error); // issue errmsg if type error - if (error) { // the argument has an invalid type + if (!tv_check_str_or_nr(&argvars[0])) { rettv->vval.v_number = -1; return; } @@ -8045,36 +7205,34 @@ static void f_bufwinnr(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_byte2line(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - long boff = 0; - - boff = get_tv_number(&argvars[0]) - 1; /* boff gets -1 on type error */ - if (boff < 0) + long boff = tv_get_number(&argvars[0]) - 1; + if (boff < 0) { rettv->vval.v_number = -1; - else - rettv->vval.v_number = ml_find_line_or_offset(curbuf, - (linenr_T)0, &boff); + } else { + rettv->vval.v_number = (varnumber_T)ml_find_line_or_offset(curbuf, 0, + &boff); + } } static void byteidx(typval_T *argvars, typval_T *rettv, int comp) { - char_u *t; - char_u *str; - long idx; - - str = get_tv_string_chk(&argvars[0]); - idx = get_tv_number_chk(&argvars[1], NULL); + const char *const str = tv_get_string_chk(&argvars[0]); + varnumber_T idx = tv_get_number_chk(&argvars[1], NULL); rettv->vval.v_number = -1; - if (str == NULL || idx < 0) + if (str == NULL || idx < 0) { return; + } - t = str; + const char *t = str; for (; idx > 0; idx--) { - if (*t == NUL) /* EOL reached */ + if (*t == NUL) { // EOL reached. return; - if (enc_utf8 && comp) - t += utf_ptr2len(t); - else - t += (*mb_ptr2len)(t); + } + if (enc_utf8 && comp) { + t += utf_ptr2len((const char_u *)t); + } else { + t += (*mb_ptr2len)((const char_u *)t); + } } rettv->vval.v_number = (varnumber_T)(t - str); } @@ -8113,18 +7271,19 @@ int func_call(char_u *name, typval_T *args, partial_T *partial, /* Make a copy of each argument. This is needed to be able to set * v_lock to VAR_FIXED in the copy without changing the original list. */ - copy_tv(&item->li_tv, &argv[argc++]); + tv_copy(&item->li_tv, &argv[argc++]); } if (item == NULL) { - r = call_func(name, (int)STRLEN(name), rettv, argc, argv, + r = call_func(name, (int)STRLEN(name), rettv, argc, argv, NULL, curwin->w_cursor.lnum, curwin->w_cursor.lnum, &dummy, true, partial, selfdict); } - /* Free the arguments. */ - while (argc > 0) - clear_tv(&argv[--argc]); + // Free the arguments. + while (argc > 0) { + tv_clear(&argv[--argc]); + } return r; } @@ -8132,24 +7291,24 @@ int func_call(char_u *name, typval_T *args, partial_T *partial, /// "call(func, arglist [, dict])" function static void f_call(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *func; - partial_T *partial = NULL; - dict_T *selfdict = NULL; - if (argvars[1].v_type != VAR_LIST) { EMSG(_(e_listreq)); return; } - if (argvars[1].vval.v_list == NULL) + if (argvars[1].vval.v_list == NULL) { return; + } + char_u *func; + partial_T *partial = NULL; + dict_T *selfdict = NULL; if (argvars[0].v_type == VAR_FUNC) { func = argvars[0].vval.v_string; } else if (argvars[0].v_type == VAR_PARTIAL) { partial = argvars[0].vval.v_partial; - func = partial->pt_name; + func = partial_name(partial); } else { - func = get_tv_string(&argvars[0]); + func = (char_u *)tv_get_string(&argvars[0]); } if (*func == NUL) { return; // type error or empty name @@ -8179,18 +7338,14 @@ static void f_changenr(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_char2nr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - if (has_mbyte) { - int utf8 = 0; - - if (argvars[1].v_type != VAR_UNKNOWN) - utf8 = get_tv_number_chk(&argvars[1], NULL); + if (argvars[1].v_type != VAR_UNKNOWN) { + if (!tv_check_num(&argvars[1])) { + return; + } + } - if (utf8) - rettv->vval.v_number = (*utf_ptr2char)(get_tv_string(&argvars[0])); - else - rettv->vval.v_number = (*mb_ptr2char)(get_tv_string(&argvars[0])); - } else - rettv->vval.v_number = get_tv_string(&argvars[0])[0]; + rettv->vval.v_number = utf_ptr2char( + (const char_u *)tv_get_string(&argvars[0])); } /* @@ -8202,7 +7357,7 @@ static void f_cindent(typval_T *argvars, typval_T *rettv, FunPtr fptr) linenr_T lnum; pos = curwin->w_cursor; - lnum = get_tv_lnum(argvars); + lnum = tv_get_lnum(argvars); if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count) { curwin->w_cursor.lnum = lnum; rettv->vval.v_number = get_c_indent(); @@ -8261,8 +7416,6 @@ static void f_col(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_complete(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - int startcol; - if ((State & INSERT) == 0) { EMSG(_("E785: complete() can only be used in Insert mode")); return; @@ -8278,9 +7431,10 @@ static void f_complete(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; } - startcol = get_tv_number_chk(&argvars[0], NULL); - if (startcol <= 0) + const colnr_T startcol = tv_get_number_chk(&argvars[0], NULL); + if (startcol <= 0) { return; + } set_completion(startcol - 1, argvars[1].vval.v_list); } @@ -8311,47 +7465,51 @@ static void f_complete_check(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_confirm(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *message; - char_u *buttons = NULL; - char_u buf[NUMBUFLEN]; - char_u buf2[NUMBUFLEN]; + char buf[NUMBUFLEN]; + char buf2[NUMBUFLEN]; + const char *message; + const char *buttons = NULL; int def = 1; int type = VIM_GENERIC; - char_u *typestr; - int error = FALSE; + const char *typestr; + bool error = false; - message = get_tv_string_chk(&argvars[0]); - if (message == NULL) - error = TRUE; + message = tv_get_string_chk(&argvars[0]); + if (message == NULL) { + error = true; + } if (argvars[1].v_type != VAR_UNKNOWN) { - buttons = get_tv_string_buf_chk(&argvars[1], buf); - if (buttons == NULL) - error = TRUE; + buttons = tv_get_string_buf_chk(&argvars[1], buf); + if (buttons == NULL) { + error = true; + } if (argvars[2].v_type != VAR_UNKNOWN) { - def = get_tv_number_chk(&argvars[2], &error); + def = tv_get_number_chk(&argvars[2], &error); if (argvars[3].v_type != VAR_UNKNOWN) { - typestr = get_tv_string_buf_chk(&argvars[3], buf2); - if (typestr == NULL) - error = TRUE; - else { + typestr = tv_get_string_buf_chk(&argvars[3], buf2); + if (typestr == NULL) { + error = true; + } else { switch (TOUPPER_ASC(*typestr)) { - case 'E': type = VIM_ERROR; break; - case 'Q': type = VIM_QUESTION; break; - case 'I': type = VIM_INFO; break; - case 'W': type = VIM_WARNING; break; - case 'G': type = VIM_GENERIC; break; + case 'E': type = VIM_ERROR; break; + case 'Q': type = VIM_QUESTION; break; + case 'I': type = VIM_INFO; break; + case 'W': type = VIM_WARNING; break; + case 'G': type = VIM_GENERIC; break; } } } } } - if (buttons == NULL || *buttons == NUL) - buttons = (char_u *)_("&Ok"); + if (buttons == NULL || *buttons == NUL) { + buttons = _("&Ok"); + } - if (!error) - rettv->vval.v_number = do_dialog(type, NULL, message, buttons, - def, NULL, FALSE); + if (!error) { + rettv->vval.v_number = do_dialog( + type, NULL, (char_u *)message, (char_u *)buttons, def, NULL, false); + } } /* @@ -8378,15 +7536,16 @@ static void f_count(typval_T *argvars, typval_T *rettv, FunPtr fptr) if ((l = argvars[0].vval.v_list) != NULL) { li = l->lv_first; if (argvars[2].v_type != VAR_UNKNOWN) { - int error = FALSE; + bool error = false; - ic = get_tv_number_chk(&argvars[2], &error); + ic = tv_get_number_chk(&argvars[2], &error); if (argvars[3].v_type != VAR_UNKNOWN) { - idx = get_tv_number_chk(&argvars[3], &error); + idx = tv_get_number_chk(&argvars[3], &error); if (!error) { - li = list_find(l, idx); - if (li == NULL) + li = tv_list_find(l, idx); + if (li == NULL) { EMSGN(_(e_listidx), idx); + } } } if (error) @@ -8403,20 +7562,22 @@ static void f_count(typval_T *argvars, typval_T *rettv, FunPtr fptr) hashitem_T *hi; if ((d = argvars[0].vval.v_dict) != NULL) { - int error = FALSE; + bool error = false; if (argvars[2].v_type != VAR_UNKNOWN) { - ic = get_tv_number_chk(&argvars[2], &error); - if (argvars[3].v_type != VAR_UNKNOWN) + ic = tv_get_number_chk(&argvars[2], &error); + if (argvars[3].v_type != VAR_UNKNOWN) { EMSG(_(e_invarg)); + } } todo = error ? 0 : (int)d->dv_hashtab.ht_used; for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi) { if (!HASHITEM_EMPTY(hi)) { - --todo; - if (tv_equal(&HI2DI(hi)->di_tv, &argvars[1], ic, FALSE)) - ++n; + todo--; + if (tv_equal(&TV_DICT_HI2DI(hi)->di_tv, &argvars[1], ic, false)) { + n++; + } } } } @@ -8433,19 +7594,21 @@ static void f_count(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_cscope_connection(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int num = 0; - char_u *dbpath = NULL; - char_u *prepend = NULL; - char_u buf[NUMBUFLEN]; + const char *dbpath = NULL; + const char *prepend = NULL; + char buf[NUMBUFLEN]; if (argvars[0].v_type != VAR_UNKNOWN && argvars[1].v_type != VAR_UNKNOWN) { - num = (int)get_tv_number(&argvars[0]); - dbpath = get_tv_string(&argvars[1]); - if (argvars[2].v_type != VAR_UNKNOWN) - prepend = get_tv_string_buf(&argvars[2], buf); + num = (int)tv_get_number(&argvars[0]); + dbpath = tv_get_string(&argvars[1]); + if (argvars[2].v_type != VAR_UNKNOWN) { + prepend = tv_get_string_buf(&argvars[2], buf); + } } - rettv->vval.v_number = cs_connection(num, dbpath, prepend); + rettv->vval.v_number = cs_connection(num, (char_u *)dbpath, + (char_u *)prepend); } /// "cursor(lnum, col)" function, or @@ -8478,10 +7641,10 @@ static void f_cursor(typval_T *argvars, typval_T *rettv, FunPtr fptr) set_curswant = false; } } else { - line = get_tv_lnum(argvars); - col = get_tv_number_chk(&argvars[1], NULL); + line = tv_get_lnum(argvars); + col = (long)tv_get_number_chk(&argvars[1], NULL); if (argvars[2].v_type != VAR_UNKNOWN) { - coladd = get_tv_number_chk(&argvars[2], NULL); + coladd = (long)tv_get_number_chk(&argvars[2], NULL); } } if (line < 0 || col < 0 @@ -8514,10 +7677,11 @@ static void f_deepcopy(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int noref = 0; - if (argvars[1].v_type != VAR_UNKNOWN) - noref = get_tv_number_chk(&argvars[1], NULL); + if (argvars[1].v_type != VAR_UNKNOWN) { + noref = tv_get_number_chk(&argvars[1], NULL); + } if (noref < 0 || noref > 1) { - EMSG(_(e_invarg)); + emsgf(_(e_invarg)); } else { var_item_copy(NULL, &argvars[0], rettv, true, (noref == 0 ? get_copyID() @@ -8528,34 +7692,32 @@ static void f_deepcopy(typval_T *argvars, typval_T *rettv, FunPtr fptr) // "delete()" function static void f_delete(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u nbuf[NUMBUFLEN]; - char_u *name; - char_u *flags; - rettv->vval.v_number = -1; if (check_restricted() || check_secure()) { return; } - name = get_tv_string(&argvars[0]); + const char *const name = tv_get_string(&argvars[0]); if (name == NULL || *name == NUL) { EMSG(_(e_invarg)); return; } + char nbuf[NUMBUFLEN]; + const char *flags; if (argvars[1].v_type != VAR_UNKNOWN) { - flags = get_tv_string_buf(&argvars[1], nbuf); + flags = tv_get_string_buf(&argvars[1], nbuf); } else { - flags = (char_u *)""; + flags = ""; } if (*flags == NUL) { // delete a file - rettv->vval.v_number = os_remove((char *)name) == 0 ? 0 : -1; - } else if (STRCMP(flags, "d") == 0) { + rettv->vval.v_number = os_remove(name) == 0 ? 0 : -1; + } else if (strcmp(flags, "d") == 0) { // delete an empty directory - rettv->vval.v_number = os_rmdir((char *)name) == 0 ? 0 : -1; - } else if (STRCMP(flags, "rf") == 0) { + rettv->vval.v_number = os_rmdir(name) == 0 ? 0 : -1; + } else if (strcmp(flags, "rf") == 0) { // delete a directory recursively rettv->vval.v_number = delete_recursive(name); } else { @@ -8571,39 +7733,34 @@ static void f_dictwatcheradd(typval_T *argvars, typval_T *rettv, FunPtr fptr) } if (argvars[0].v_type != VAR_DICT) { - EMSG2(e_invarg2, "dict"); + emsgf(_(e_invarg2), "dict"); return; - } - - if (argvars[1].v_type != VAR_STRING && argvars[1].v_type != VAR_NUMBER) { - EMSG2(e_invarg2, "key"); + } else if (argvars[0].vval.v_dict == NULL) { + const char *const arg_errmsg = _("dictwatcheradd() argument"); + const size_t arg_errmsg_len = strlen(arg_errmsg); + emsgf(_(e_readonlyvar), (int)arg_errmsg_len, arg_errmsg); return; } - if (argvars[2].v_type != VAR_FUNC && argvars[2].v_type != VAR_STRING) { - EMSG2(e_invarg2, "funcref"); + if (argvars[1].v_type != VAR_STRING && argvars[1].v_type != VAR_NUMBER) { + emsgf(_(e_invarg2), "key"); 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)); + const char *const key_pattern = tv_get_string_chk(argvars + 1); + if (key_pattern == NULL) { return; } + const size_t key_pattern_len = strlen(key_pattern); Callback callback; if (!callback_from_typval(&callback, &argvars[2])) { + emsgf(_(e_invarg2), "funcref"); return; } - DictWatcher *watcher = xmalloc(sizeof(DictWatcher)); - watcher->key_pattern = xmemdupz(key_pattern, key_len); - watcher->callback = callback; - watcher->busy = false; - QUEUE_INSERT_TAIL(&argvars[0].vval.v_dict->watchers, &watcher->node); + tv_dict_watcher_add(argvars[0].vval.v_dict, key_pattern, key_pattern_len, + callback); } // dictwatcherdel(dict, key, funcref) function @@ -8614,26 +7771,17 @@ static void f_dictwatcherdel(typval_T *argvars, typval_T *rettv, FunPtr fptr) } 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"); + emsgf(_(e_invarg2), "dict"); return; } if (argvars[2].v_type != VAR_FUNC && argvars[2].v_type != VAR_STRING) { - EMSG2(e_invarg2, "funcref"); + emsgf(_(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)); + const char *const key_pattern = tv_get_string_chk(argvars + 1); + if (key_pattern == NULL) { return; } @@ -8642,28 +7790,12 @@ static void f_dictwatcherdel(typval_T *argvars, typval_T *rettv, FunPtr fptr) 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 (callback_equal(&watcher->callback, &callback) - && !strcmp(watcher->key_pattern, key_pattern)) { - matched = true; - break; - } - } - - callback_free(&callback); - - if (!matched) { + if (!tv_dict_watcher_remove(argvars[0].vval.v_dict, key_pattern, + strlen(key_pattern), callback)) { EMSG("Couldn't find a watcher matching key and callback"); - return; } - QUEUE_REMOVE(w); - dictwatcher_free(watcher); + callback_free(&callback); } /* @@ -8679,7 +7811,7 @@ static void f_did_filetype(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_diff_filler(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - rettv->vval.v_number = diff_check_fill(curwin, get_tv_lnum(argvars)); + rettv->vval.v_number = diff_check_fill(curwin, tv_get_lnum(argvars)); } /* @@ -8687,7 +7819,7 @@ static void f_diff_filler(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_diff_hlID(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - linenr_T lnum = get_tv_lnum(argvars); + linenr_T lnum = tv_get_lnum(argvars); static linenr_T prev_lnum = 0; static int changedtick = 0; static int fnum = 0; @@ -8722,11 +7854,12 @@ static void f_diff_hlID(typval_T *argvars, typval_T *rettv, FunPtr fptr) } if (hlID == HLF_CHD || hlID == HLF_TXD) { - col = get_tv_number(&argvars[1]) - 1; /* ignore type error in {col} */ - if (col >= change_start && col <= change_end) - hlID = HLF_TXD; /* changed text */ - else - hlID = HLF_CHD; /* changed line */ + col = tv_get_number(&argvars[1]) - 1; // Ignore type error in {col}. + if (col >= change_start && col <= change_end) { + hlID = HLF_TXD; // Changed text. + } else { + hlID = HLF_CHD; // Changed line. + } } rettv->vval.v_number = hlID == (hlf_T)0 ? 0 : (int)hlID; } @@ -8777,10 +7910,11 @@ static void f_empty(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_escape(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u buf[NUMBUFLEN]; + char buf[NUMBUFLEN]; - rettv->vval.v_string = vim_strsave_escaped(get_tv_string(&argvars[0]), - get_tv_string_buf(&argvars[1], buf)); + rettv->vval.v_string = vim_strsave_escaped( + (const char_u *)tv_get_string(&argvars[0]), + (const char_u *)tv_get_string_buf(&argvars[1], buf)); rettv->v_type = VAR_STRING; } @@ -8789,16 +7923,15 @@ static void f_escape(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_eval(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *s; - - s = get_tv_string_chk(&argvars[0]); - if (s != NULL) - s = skipwhite(s); + const char *s = tv_get_string_chk(&argvars[0]); + if (s != NULL) { + s = (const char *)skipwhite((const char_u *)s); + } - char_u *p = s; - if (s == NULL || eval1(&s, rettv, TRUE) == FAIL) { - if (p != NULL && !aborting()) { - EMSG2(_(e_invexpr2), p); + const char *const expr_start = s; + if (s == NULL || eval1((char_u **)&s, rettv, true) == FAIL) { + if (expr_start != NULL && !aborting()) { + EMSG2(_(e_invexpr2), expr_start); } need_clr_eos = FALSE; rettv->v_type = VAR_NUMBER; @@ -8821,91 +7954,92 @@ static void f_eventhandler(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_executable(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *name = get_tv_string(&argvars[0]); + const char *name = tv_get_string(&argvars[0]); // Check in $PATH and also check directly if there is a directory name - rettv->vval.v_number = os_can_exe(name, NULL, true) - || (gettail_dir(name) != name && os_can_exe(name, NULL, false)); + rettv->vval.v_number = ( + os_can_exe((const char_u *)name, NULL, true) + || (gettail_dir(name) != name + && os_can_exe((const char_u *)name, NULL, false))); } -static char_u * get_list_line(int c, void *cookie, int indent) +static char_u *get_list_line(int c, void *cookie, int indent) { - listitem_T **p = (listitem_T **)cookie; - listitem_T *item = *p; - char_u buf[NUMBUFLEN]; - char_u *s; + const listitem_T **const p = (const listitem_T **)cookie; + const listitem_T *item = *p; if (item == NULL) { return NULL; } - s = get_tv_string_buf_chk(&item->li_tv, buf); + char buf[NUMBUFLEN]; + const char *const s = tv_get_string_buf_chk(&item->li_tv, buf); *p = item->li_next; - return s == NULL ? NULL : vim_strsave(s); + return (char_u *)(s == NULL ? NULL : xstrdup(s)); } // "execute(command)" function static void f_execute(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - int save_msg_silent = msg_silent; - int save_emsg_silent = emsg_silent; - bool save_emsg_noredir = emsg_noredir; - garray_T *save_capture_ga = capture_ga; + const int save_msg_silent = msg_silent; + const int save_emsg_silent = emsg_silent; + const bool save_emsg_noredir = emsg_noredir; + garray_T *const save_capture_ga = capture_ga; - if (check_secure()) { - return; - } + if (check_secure()) { + return; + } - if (argvars[1].v_type != VAR_UNKNOWN) { - char_u buf[NUMBUFLEN]; - char_u *s = get_tv_string_buf_chk(&argvars[1], buf); + if (argvars[1].v_type != VAR_UNKNOWN) { + char buf[NUMBUFLEN]; + const char *const s = tv_get_string_buf_chk(&argvars[1], buf); - if (s == NULL) { - return; - } - if (STRNCMP(s, "silent", 6) == 0) { - msg_silent++; - } - if (STRCMP(s, "silent!") == 0) { - emsg_silent = true; - emsg_noredir = true; - } - } else { + if (s == NULL) { + return; + } + if (strncmp(s, "silent", 6) == 0) { msg_silent++; } - - garray_T capture_local; - ga_init(&capture_local, (int)sizeof(char), 80); - capture_ga = &capture_local; - - if (argvars[0].v_type != VAR_LIST) { - do_cmdline_cmd((char *)get_tv_string(&argvars[0])); - } else if (argvars[0].vval.v_list != NULL) { - list_T *list = argvars[0].vval.v_list; - list->lv_refcount++; - listitem_T *item = list->lv_first; - do_cmdline(NULL, get_list_line, (void *)&item, - DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT|DOCMD_KEYTYPED); - list->lv_refcount--; + if (strcmp(s, "silent!") == 0) { + emsg_silent = true; + emsg_noredir = true; } - msg_silent = save_msg_silent; - emsg_silent = save_emsg_silent; - emsg_noredir = save_emsg_noredir; + } else { + msg_silent++; + } - ga_append(capture_ga, NUL); - rettv->v_type = VAR_STRING; - rettv->vval.v_string = vim_strsave(capture_ga->ga_data); - ga_clear(capture_ga); + garray_T capture_local; + ga_init(&capture_local, (int)sizeof(char), 80); + capture_ga = &capture_local; - capture_ga = save_capture_ga; + if (argvars[0].v_type != VAR_LIST) { + do_cmdline_cmd(tv_get_string(&argvars[0])); + } else if (argvars[0].vval.v_list != NULL) { + list_T *const list = argvars[0].vval.v_list; + list->lv_refcount++; + listitem_T *const item = list->lv_first; + do_cmdline(NULL, get_list_line, (void *)&item, + DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT|DOCMD_KEYTYPED); + list->lv_refcount--; + } + msg_silent = save_msg_silent; + emsg_silent = save_emsg_silent; + emsg_noredir = save_emsg_noredir; + + ga_append(capture_ga, NUL); + rettv->v_type = VAR_STRING; + rettv->vval.v_string = vim_strsave(capture_ga->ga_data); + ga_clear(capture_ga); + + capture_ga = save_capture_ga; } /// "exepath()" function static void f_exepath(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *arg = get_tv_string(&argvars[0]); + const char *arg = tv_get_string(&argvars[0]); char_u *path = NULL; - (void)os_can_exe(arg, &path, true); + (void)os_can_exe((const char_u *)arg, &path, true); rettv->v_type = VAR_STRING; rettv->vval.v_string = path; @@ -8916,53 +8050,55 @@ static void f_exepath(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_exists(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *p; - char_u *name; - int n = FALSE; + int n = false; int len = 0; - p = get_tv_string(&argvars[0]); - if (*p == '$') { /* environment variable */ - /* first try "normal" environment variables (fast) */ - if (os_getenv((char *)(p + 1)) != NULL) - n = TRUE; - else { - /* try expanding things like $VIM and ${HOME} */ - p = expand_env_save(p); - if (p != NULL && *p != '$') - n = TRUE; - xfree(p); + const char *p = tv_get_string(&argvars[0]); + if (*p == '$') { // Environment variable. + // First try "normal" environment variables (fast). + if (os_getenv(p + 1) != NULL) { + n = true; + } else { + // Try expanding things like $VIM and ${HOME}. + char_u *const exp = expand_env_save((char_u *)p); + if (exp != NULL && *exp != '$') { + n = true; + } + xfree(exp); + } + } else if (*p == '&' || *p == '+') { // Option. + n = (get_option_tv(&p, NULL, true) == OK); + if (*skipwhite((const char_u *)p) != NUL) { + n = false; // Trailing garbage. } - } else if (*p == '&' || *p == '+') { /* option */ - n = (get_option_tv(&p, NULL, TRUE) == OK); - if (*skipwhite(p) != NUL) - n = FALSE; /* trailing garbage */ - } else if (*p == '*') { /* internal or user defined function */ - n = function_exists(p + 1); + } else if (*p == '*') { // Internal or user defined function. + n = function_exists(p + 1, false); } else if (*p == ':') { n = cmd_exists(p + 1); } else if (*p == '#') { - if (p[1] == '#') + if (p[1] == '#') { n = autocmd_supported(p + 2); - else + } else { n = au_exists(p + 1); - } else { /* internal variable */ - char_u *tofree; + } + } else { // Internal variable. typval_T tv; - /* get_name_len() takes care of expanding curly braces */ - name = p; - len = get_name_len(&p, &tofree, TRUE, FALSE); + // get_name_len() takes care of expanding curly braces + const char *name = p; + char *tofree; + len = get_name_len((const char **)&p, &tofree, true, false); if (len > 0) { if (tofree != NULL) { name = tofree; } n = (get_var_tv(name, len, &tv, NULL, false, true) == OK); if (n) { - /* handle d.key, l[idx], f(expr) */ - n = (handle_subscript(&p, &tv, TRUE, FALSE) == OK); - if (n) - clear_tv(&tv); + // Handle d.key, l[idx], f(expr). + n = (handle_subscript(&p, &tv, true, false) == OK); + if (n) { + tv_clear(&tv); + } } } if (*p != NUL) @@ -8979,32 +8115,31 @@ static void f_exists(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_expand(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *s; size_t len; char_u *errormsg; int options = WILD_SILENT|WILD_USE_NL|WILD_LIST_NOTFOUND; expand_T xpc; - int error = FALSE; - char_u *result; + bool error = false; + char_u *result; rettv->v_type = VAR_STRING; if (argvars[1].v_type != VAR_UNKNOWN && argvars[2].v_type != VAR_UNKNOWN - && get_tv_number_chk(&argvars[2], &error) + && tv_get_number_chk(&argvars[2], &error) && !error) { rettv->v_type = VAR_LIST; rettv->vval.v_list = NULL; } - s = get_tv_string(&argvars[0]); + const char *s = tv_get_string(&argvars[0]); if (*s == '%' || *s == '#' || *s == '<') { - ++emsg_off; - result = eval_vars(s, s, &len, NULL, &errormsg, NULL); - --emsg_off; + emsg_off++; + result = eval_vars((char_u *)s, (char_u *)s, &len, NULL, &errormsg, NULL); + emsg_off--; if (rettv->v_type == VAR_LIST) { - rettv_list_alloc(rettv); + tv_list_alloc_ret(rettv); if (result != NULL) { - list_append_string(rettv->vval.v_list, result, -1); + tv_list_append_string(rettv->vval.v_list, (const char *)result, -1); } } else rettv->vval.v_string = result; @@ -9012,94 +8147,44 @@ static void f_expand(typval_T *argvars, typval_T *rettv, FunPtr fptr) /* When the optional second argument is non-zero, don't remove matches * for 'wildignore' and don't put matches for 'suffixes' at the end. */ if (argvars[1].v_type != VAR_UNKNOWN - && get_tv_number_chk(&argvars[1], &error)) + && tv_get_number_chk(&argvars[1], &error)) { options |= WILD_KEEP_ALL; + } if (!error) { ExpandInit(&xpc); xpc.xp_context = EXPAND_FILES; - if (p_wic) + if (p_wic) { options += WILD_ICASE; - if (rettv->v_type == VAR_STRING) - rettv->vval.v_string = ExpandOne(&xpc, s, NULL, - options, WILD_ALL); - else { - rettv_list_alloc(rettv); - ExpandOne(&xpc, s, NULL, options, WILD_ALL_KEEP); + } + if (rettv->v_type == VAR_STRING) { + rettv->vval.v_string = ExpandOne(&xpc, (char_u *)s, NULL, options, + WILD_ALL); + } else { + tv_list_alloc_ret(rettv); + ExpandOne(&xpc, (char_u *)s, NULL, options, WILD_ALL_KEEP); for (int i = 0; i < xpc.xp_numfiles; i++) { - list_append_string(rettv->vval.v_list, xpc.xp_files[i], -1); + tv_list_append_string(rettv->vval.v_list, + (const char *)xpc.xp_files[i], -1); } ExpandCleanup(&xpc); } - } else + } else { rettv->vval.v_string = NULL; + } } } -/* - * Go over all entries in "d2" and add them to "d1". - * When "action" is "error" then a duplicate key is an error. - * When "action" is "force" then a duplicate key is overwritten. - * Otherwise duplicate keys are ignored ("action" is "keep"). - */ -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); - char_u *arg_errmsg = (char_u *)N_("extend() argument"); - - todo = (int)d2->dv_hashtab.ht_used; - for (hi2 = d2->dv_hashtab.ht_array; todo > 0; ++hi2) { - if (!HASHITEM_EMPTY(hi2)) { - --todo; - di1 = dict_find(d1, hi2->hi_key, -1); - if (d1->dv_scope != 0) { - /* Disallow replacing a builtin function in l: and g:. - * Check the key to be valid when adding to any - * scope. */ - if (d1->dv_scope == VAR_DEF_SCOPE - && HI2DI(hi2)->di_tv.v_type == VAR_FUNC - && var_check_func_name(hi2->hi_key, - di1 == NULL)) - break; - if (!valid_varname(hi2->hi_key)) - break; - } - if (di1 == NULL) { - di1 = dictitem_copy(HI2DI(hi2)); - 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 (tv_check_lock(di1->di_tv.v_lock, arg_errmsg, true) - || var_check_ro(di1->di_flags, arg_errmsg, true)) { - break; - } - 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); - } - } - } +/// "menu_get(path [, modes])" function +static void f_menu_get(typval_T *argvars, typval_T *rettv, FunPtr fptr) +{ + tv_list_alloc_ret(rettv); + int modes = MENU_ALL_MODES; + if (argvars[1].v_type == VAR_STRING) { + const char_u *const strmodes = (char_u *)tv_get_string(&argvars[1]); + modes = get_menu_cmd_modes(strmodes, false, NULL, NULL); } + menu_get((char_u *)tv_get_string(&argvars[0]), modes, rettv->vval.v_list); } /* @@ -9108,27 +8193,33 @@ void dict_extend(dict_T *d1, dict_T *d2, char_u *action) */ static void f_extend(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *arg_errmsg = (char_u *)N_("extend() argument"); + const char *const arg_errmsg = N_("extend() argument"); if (argvars[0].v_type == VAR_LIST && argvars[1].v_type == VAR_LIST) { - list_T *l1, *l2; - listitem_T *item; long before; - int error = FALSE; - - l1 = argvars[0].vval.v_list; - l2 = argvars[1].vval.v_list; - if (l1 != NULL && !tv_check_lock(l1->lv_lock, arg_errmsg, true) - && l2 != NULL) { + bool error = false; + + list_T *const l1 = argvars[0].vval.v_list; + list_T *const l2 = argvars[1].vval.v_list; + if (l1 == NULL) { + const bool locked = tv_check_lock(VAR_FIXED, arg_errmsg, TV_TRANSLATE); + (void)locked; + assert(locked == true); + } else if (l2 == NULL) { + // Do nothing + tv_copy(&argvars[0], rettv); + } else if (!tv_check_lock(l1->lv_lock, arg_errmsg, TV_TRANSLATE)) { + listitem_T *item; if (argvars[2].v_type != VAR_UNKNOWN) { - before = get_tv_number_chk(&argvars[2], &error); - if (error) - return; /* type error; errmsg already given */ + before = (long)tv_get_number_chk(&argvars[2], &error); + if (error) { + return; // Type error; errmsg already given. + } - if (before == l1->lv_len) + if (before == l1->lv_len) { item = NULL; - else { - item = list_find(l1, before); + } else { + item = tv_list_find(l1, before); if (item == NULL) { EMSGN(_(e_listidx), before); return; @@ -9136,43 +8227,50 @@ static void f_extend(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } else item = NULL; - list_extend(l1, l2, item); + tv_list_extend(l1, l2, item); - copy_tv(&argvars[0], rettv); + tv_copy(&argvars[0], rettv); } } else if (argvars[0].v_type == VAR_DICT && argvars[1].v_type == VAR_DICT) { - dict_T *d1, *d2; - char_u *action; - int i; - - d1 = argvars[0].vval.v_dict; - d2 = argvars[1].vval.v_dict; - if (d1 != NULL && !tv_check_lock(d1->dv_lock, arg_errmsg, true) - && d2 != NULL) { - /* Check the third argument. */ + dict_T *const d1 = argvars[0].vval.v_dict; + dict_T *const d2 = argvars[1].vval.v_dict; + if (d1 == NULL) { + const bool locked = tv_check_lock(VAR_FIXED, arg_errmsg, TV_TRANSLATE); + (void)locked; + assert(locked == true); + } else if (d2 == NULL) { + // Do nothing + tv_copy(&argvars[0], rettv); + } else if (!tv_check_lock(d1->dv_lock, arg_errmsg, TV_TRANSLATE)) { + const char *action = "force"; + // Check the third argument. if (argvars[2].v_type != VAR_UNKNOWN) { - static char *(av[]) = {"keep", "force", "error"}; + const char *const av[] = { "keep", "force", "error" }; - action = get_tv_string_chk(&argvars[2]); - if (action == NULL) - return; /* type error; errmsg already given */ - for (i = 0; i < 3; ++i) - if (STRCMP(action, av[i]) == 0) + action = tv_get_string_chk(&argvars[2]); + if (action == NULL) { + return; // Type error; error message already given. + } + size_t i; + for (i = 0; i < ARRAY_SIZE(av); i++) { + if (strcmp(action, av[i]) == 0) { break; + } + } if (i == 3) { EMSG2(_(e_invarg2), action); return; } - } else - action = (char_u *)"force"; + } - dict_extend(d1, d2, action); + tv_dict_extend(d1, d2, action); - copy_tv(&argvars[0], rettv); + tv_copy(&argvars[0], rettv); } - } else + } else { EMSG2(_(e_listdictarg), "extend()"); + } } /* @@ -9180,19 +8278,18 @@ static void f_extend(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_feedkeys(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *keys, *flags = NULL; - char_u nbuf[NUMBUFLEN]; - - /* This is not allowed in the sandbox. If the commands would still be - * executed in the sandbox it would be OK, but it probably happens later, - * when "sandbox" is no longer set. */ - if (check_secure()) + // This is not allowed in the sandbox. If the commands would still be + // executed in the sandbox it would be OK, but it probably happens later, + // when "sandbox" is no longer set. + if (check_secure()) { return; + } - keys = get_tv_string(&argvars[0]); - + const char *const keys = tv_get_string(&argvars[0]); + char nbuf[NUMBUFLEN]; + const char *flags = NULL; if (argvars[1].v_type != VAR_UNKNOWN) { - flags = get_tv_string_buf(&argvars[1], nbuf); + flags = tv_get_string_buf(&argvars[1], nbuf); } nvim_feedkeys(cstr_as_string((char *)keys), @@ -9202,9 +8299,9 @@ static void f_feedkeys(typval_T *argvars, typval_T *rettv, FunPtr fptr) /// "filereadable()" function static void f_filereadable(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *p = get_tv_string(&argvars[0]); + const char *const p = tv_get_string(&argvars[0]); rettv->vval.v_number = - (*p && !os_isdir(p) && os_file_is_readable((char*)p)); + (*p && !os_isdir((const char_u *)p) && os_file_is_readable(p)); } /* @@ -9213,60 +8310,60 @@ static void f_filereadable(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_filewritable(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char *filename = (char *)get_tv_string(&argvars[0]); + const char *filename = tv_get_string(&argvars[0]); rettv->vval.v_number = os_file_is_writable(filename); } static void findfilendir(typval_T *argvars, typval_T *rettv, int find_what) { - char_u *fname; - char_u *fresult = NULL; - char_u *path = *curbuf->b_p_path == NUL ? p_path : curbuf->b_p_path; - char_u *p; - char_u pathbuf[NUMBUFLEN]; + char_u *fresult = NULL; + char_u *path = *curbuf->b_p_path == NUL ? p_path : curbuf->b_p_path; int count = 1; - int first = TRUE; - int error = FALSE; + bool first = true; + bool error = false; rettv->vval.v_string = NULL; rettv->v_type = VAR_STRING; - fname = get_tv_string(&argvars[0]); + const char *fname = tv_get_string(&argvars[0]); + char pathbuf[NUMBUFLEN]; if (argvars[1].v_type != VAR_UNKNOWN) { - p = get_tv_string_buf_chk(&argvars[1], pathbuf); - if (p == NULL) - error = TRUE; - else { - if (*p != NUL) - path = p; + const char *p = tv_get_string_buf_chk(&argvars[1], pathbuf); + if (p == NULL) { + error = true; + } else { + if (*p != NUL) { + path = (char_u *)p; + } - if (argvars[2].v_type != VAR_UNKNOWN) - count = get_tv_number_chk(&argvars[2], &error); + if (argvars[2].v_type != VAR_UNKNOWN) { + count = tv_get_number_chk(&argvars[2], &error); + } } } if (count < 0) { - rettv_list_alloc(rettv); + tv_list_alloc_ret(rettv); } if (*fname != NUL && !error) { do { if (rettv->v_type == VAR_STRING || rettv->v_type == VAR_LIST) xfree(fresult); - fresult = find_file_in_path_option(first ? fname : NULL, - first ? STRLEN(fname) : 0, + fresult = find_file_in_path_option(first ? (char_u *)fname : NULL, + first ? strlen(fname) : 0, 0, first, path, find_what, curbuf->b_ffname, (find_what == FINDFILE_DIR ? (char_u *)"" : curbuf->b_p_sua)); - first = FALSE; - - if (fresult != NULL && rettv->v_type == VAR_LIST) - list_append_string(rettv->vval.v_list, fresult, -1); + first = false; + if (fresult != NULL && rettv->v_type == VAR_LIST) { + tv_list_append_string(rettv->vval.v_list, (const char *)fresult, -1); + } } while ((rettv->v_type == VAR_LIST || --count > 0) && fresult != NULL); } @@ -9280,8 +8377,7 @@ static void findfilendir(typval_T *argvars, typval_T *rettv, int find_what) */ static void filter_map(typval_T *argvars, typval_T *rettv, int map) { - char_u buf[NUMBUFLEN]; - char_u *expr; + typval_T *expr; listitem_T *li, *nli; list_T *l = NULL; dictitem_T *di; @@ -9292,20 +8388,21 @@ static void filter_map(typval_T *argvars, typval_T *rettv, int map) typval_T save_key; int rem = false; int todo; - char_u *ermsg = (char_u *)(map ? "map()" : "filter()"); - char_u *arg_errmsg = (char_u *)(map ? N_("map() argument") - : N_("filter() argument")); + char_u *ermsg = (char_u *)(map ? "map()" : "filter()"); + const char *const arg_errmsg = (map + ? N_("map() argument") + : N_("filter() argument")); int save_did_emsg; int idx = 0; if (argvars[0].v_type == VAR_LIST) { if ((l = argvars[0].vval.v_list) == NULL - || (!map && tv_check_lock(l->lv_lock, arg_errmsg, true))) { + || (!map && tv_check_lock(l->lv_lock, arg_errmsg, TV_TRANSLATE))) { return; } } else if (argvars[0].v_type == VAR_DICT) { if ((d = argvars[0].vval.v_dict) == NULL - || (!map && tv_check_lock(d->dv_lock, arg_errmsg, true))) { + || (!map && tv_check_lock(d->dv_lock, arg_errmsg, TV_TRANSLATE))) { return; } } else { @@ -9313,16 +8410,15 @@ static void filter_map(typval_T *argvars, typval_T *rettv, int map) return; } - expr = get_tv_string_buf_chk(&argvars[1], buf); - /* On type errors, the preceding call has already displayed an error - * message. Avoid a misleading error message for an empty string that - * was not passed as argument. */ - if (expr != NULL) { + expr = &argvars[1]; + // On type errors, the preceding call has already displayed an error + // message. Avoid a misleading error message for an empty string that + // was not passed as argument. + if (expr->v_type != VAR_UNKNOWN) { prepare_vimvar(VV_VAL, &save_val); - expr = skipwhite(expr); - /* We reset "did_emsg" to be able to detect whether an error - * occurred during evaluation of the expression. */ + // We reset "did_emsg" to be able to detect whether an error + // occurred during evaluation of the expression. save_did_emsg = did_emsg; did_emsg = FALSE; @@ -9337,24 +8433,25 @@ static void filter_map(typval_T *argvars, typval_T *rettv, int map) if (!HASHITEM_EMPTY(hi)) { --todo; - di = HI2DI(hi); + di = TV_DICT_HI2DI(hi); if (map - && (tv_check_lock(di->di_tv.v_lock, arg_errmsg, true) - || var_check_ro(di->di_flags, arg_errmsg, true))) { + && (tv_check_lock(di->di_tv.v_lock, arg_errmsg, TV_TRANSLATE) + || var_check_ro(di->di_flags, arg_errmsg, TV_TRANSLATE))) { break; } vimvars[VV_KEY].vv_str = vim_strsave(di->di_key); int r = filter_map_one(&di->di_tv, expr, map, &rem); - clear_tv(&vimvars[VV_KEY].vv_tv); - if (r == FAIL || did_emsg) + tv_clear(&vimvars[VV_KEY].vv_tv); + if (r == FAIL || did_emsg) { break; + } if (!map && rem) { - if (var_check_fixed(di->di_flags, arg_errmsg, true) - || var_check_ro(di->di_flags, arg_errmsg, true)) { + if (var_check_fixed(di->di_flags, arg_errmsg, TV_TRANSLATE) + || var_check_ro(di->di_flags, arg_errmsg, TV_TRANSLATE)) { break; } - dictitem_remove(d, di); + tv_dict_item_remove(d, di); } } } @@ -9363,7 +8460,8 @@ static void filter_map(typval_T *argvars, typval_T *rettv, int map) vimvars[VV_KEY].vv_type = VAR_NUMBER; for (li = l->lv_first; li != NULL; li = nli) { - if (map && tv_check_lock(li->li_tv.v_lock, arg_errmsg, true)) { + if (map + && tv_check_lock(li->li_tv.v_lock, arg_errmsg, TV_TRANSLATE)) { break; } nli = li->li_next; @@ -9371,9 +8469,10 @@ static void filter_map(typval_T *argvars, typval_T *rettv, int map) if (filter_map_one(&li->li_tv, expr, map, &rem) == FAIL || did_emsg) break; - if (!map && rem) - listitem_remove(l, li); - ++idx; + if (!map && rem) { + tv_list_item_remove(l, li); + } + idx++; } } @@ -9383,43 +8482,69 @@ static void filter_map(typval_T *argvars, typval_T *rettv, int map) did_emsg |= save_did_emsg; } - copy_tv(&argvars[0], rettv); + tv_copy(&argvars[0], rettv); } -static int filter_map_one(typval_T *tv, char_u *expr, int map, int *remp) +static int filter_map_one(typval_T *tv, typval_T *expr, int map, int *remp) { typval_T rettv; - char_u *s; + typval_T argv[3]; int retval = FAIL; + int dummy; - copy_tv(tv, &vimvars[VV_VAL].vv_tv); - s = expr; - if (eval1(&s, &rettv, TRUE) == FAIL) - goto theend; - if (*s != NUL) { /* check for trailing chars after expr */ - EMSG2(_(e_invexpr2), s); - clear_tv(&rettv); - goto theend; + tv_copy(tv, &vimvars[VV_VAL].vv_tv); + argv[0] = vimvars[VV_KEY].vv_tv; + argv[1] = vimvars[VV_VAL].vv_tv; + if (expr->v_type == VAR_FUNC) { + const char_u *const s = expr->vval.v_string; + if (call_func(s, (int)STRLEN(s), &rettv, 2, argv, NULL, + 0L, 0L, &dummy, true, NULL, NULL) == FAIL) { + goto theend; + } + } else if (expr->v_type == VAR_PARTIAL) { + partial_T *partial = expr->vval.v_partial; + + const char_u *const s = partial_name(partial); + if (call_func(s, (int)STRLEN(s), &rettv, 2, argv, NULL, + 0L, 0L, &dummy, true, partial, NULL) == FAIL) { + goto theend; + } + } else { + char buf[NUMBUFLEN]; + const char *s = tv_get_string_buf_chk(expr, buf); + if (s == NULL) { + goto theend; + } + s = (const char *)skipwhite((const char_u *)s); + if (eval1((char_u **)&s, &rettv, true) == FAIL) { + goto theend; + } + + if (*s != NUL) { // check for trailing chars after expr + emsgf(_(e_invexpr2), s); + goto theend; + } } if (map) { - /* map(): replace the list item value */ - clear_tv(tv); + // map(): replace the list item value. + tv_clear(tv); rettv.v_lock = 0; *tv = rettv; } else { - int error = FALSE; - - /* filter(): when expr is zero remove the item */ - *remp = (get_tv_number_chk(&rettv, &error) == 0); - clear_tv(&rettv); - /* On type error, nothing has been removed; return FAIL to stop the - * loop. The error message was given by get_tv_number_chk(). */ - if (error) + bool error = false; + + // filter(): when expr is zero remove the item + *remp = (tv_get_number_chk(&rettv, &error) == 0); + tv_clear(&rettv); + // On type error, nothing has been removed; return FAIL to stop the + // loop. The error message was given by tv_get_number_chk(). + if (error) { goto theend; + } } retval = OK; theend: - clear_tv(&vimvars[VV_VAL].vv_tv); + tv_clear(&vimvars[VV_VAL].vv_tv); return retval; } @@ -9454,13 +8579,14 @@ static void f_float2nr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { float_T f; - if (get_float_arg(argvars, &f) == OK) { - if (f < -0x7fffffff) - rettv->vval.v_number = -0x7fffffff; - else if (f > 0x7fffffff) - rettv->vval.v_number = 0x7fffffff; - else + if (tv_get_float_chk(argvars, &f)) { + if (f <= -VARNUMBER_MAX + DBL_EPSILON) { + rettv->vval.v_number = -VARNUMBER_MAX; + } else if (f >= VARNUMBER_MAX - DBL_EPSILON) { + rettv->vval.v_number = VARNUMBER_MAX; + } else { rettv->vval.v_number = (varnumber_T)f; + } } } @@ -9469,14 +8595,15 @@ static void f_float2nr(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_fmod(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - float_T fx, fy; + float_T fx; + float_T fy; rettv->v_type = VAR_FLOAT; - if (get_float_arg(argvars, &fx) == OK - && get_float_arg(&argvars[1], &fy) == OK) + if (tv_get_float_chk(argvars, &fx) && tv_get_float_chk(&argvars[1], &fy)) { rettv->vval.v_float = fmod(fx, fy); - else + } else { rettv->vval.v_float = 0.0; + } } /* @@ -9484,8 +8611,8 @@ static void f_fmod(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_fnameescape(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - rettv->vval.v_string = vim_strsave_fnameescape( - get_tv_string(&argvars[0]), FALSE); + rettv->vval.v_string = (char_u *)vim_strsave_fnameescape( + tv_get_string(&argvars[0]), false); rettv->v_type = VAR_STRING; } @@ -9494,27 +8621,26 @@ static void f_fnameescape(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_fnamemodify(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *fname; - char_u *mods; - size_t usedlen = 0; + char_u *fbuf = NULL; size_t len; - char_u *fbuf = NULL; - char_u buf[NUMBUFLEN]; - - fname = get_tv_string_chk(&argvars[0]); - mods = get_tv_string_buf_chk(&argvars[1], buf); - if (fname == NULL || mods == NULL) + char buf[NUMBUFLEN]; + const char *fname = tv_get_string_chk(&argvars[0]); + const char *const mods = tv_get_string_buf_chk(&argvars[1], buf); + if (fname == NULL || mods == NULL) { fname = NULL; - else { - len = STRLEN(fname); - (void)modify_fname(mods, &usedlen, &fname, &fbuf, &len); + } else { + len = strlen(fname); + size_t usedlen = 0; + (void)modify_fname((char_u *)mods, &usedlen, (char_u **)&fname, &fbuf, + &len); } rettv->v_type = VAR_STRING; - if (fname == NULL) + if (fname == NULL) { rettv->vval.v_string = NULL; - else - rettv->vval.v_string = vim_strnsave(fname, len); + } else { + rettv->vval.v_string = (char_u *)xmemdupz(fname, len); + } xfree(fbuf); } @@ -9524,16 +8650,16 @@ static void f_fnamemodify(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void foldclosed_both(typval_T *argvars, typval_T *rettv, int end) { - linenr_T lnum; - linenr_T first, last; - - lnum = get_tv_lnum(argvars); + const linenr_T lnum = tv_get_lnum(argvars); if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count) { - if (hasFoldingWin(curwin, lnum, &first, &last, FALSE, NULL)) { - if (end) + linenr_T first; + linenr_T last; + if (hasFoldingWin(curwin, lnum, &first, &last, false, NULL)) { + if (end) { rettv->vval.v_number = (varnumber_T)last; - else + } else { rettv->vval.v_number = (varnumber_T)first; + } return; } } @@ -9561,11 +8687,10 @@ static void f_foldclosedend(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_foldlevel(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - linenr_T lnum; - - lnum = get_tv_lnum(argvars); - if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count) + const linenr_T lnum = tv_get_lnum(argvars); + if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count) { rettv->vval.v_number = foldLevel(lnum); + } } /* @@ -9573,24 +8698,28 @@ static void f_foldlevel(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_foldtext(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - linenr_T lnum; + linenr_T foldstart; + linenr_T foldend; + char_u *dashes; + linenr_T lnum; char_u *s; char_u *r; - int len; + int len; char *txt; rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; - if ((linenr_T)vimvars[VV_FOLDSTART].vv_nr > 0 - && (linenr_T)vimvars[VV_FOLDEND].vv_nr - <= curbuf->b_ml.ml_line_count - && vimvars[VV_FOLDDASHES].vv_str != NULL) { + + foldstart = (linenr_T)get_vim_var_nr(VV_FOLDSTART); + foldend = (linenr_T)get_vim_var_nr(VV_FOLDEND); + dashes = get_vim_var_str(VV_FOLDDASHES); + if (foldstart > 0 && foldend <= curbuf->b_ml.ml_line_count + && dashes != NULL) { /* Find first non-empty line in the fold. */ - lnum = (linenr_T)vimvars[VV_FOLDSTART].vv_nr; - while (lnum < (linenr_T)vimvars[VV_FOLDEND].vv_nr) { - if (!linewhite(lnum)) + for (lnum = foldstart; lnum < foldend; ++lnum) { + if (!linewhite(lnum)) { break; - ++lnum; + } } /* Find interesting text in this line. */ @@ -9598,21 +8727,19 @@ static void f_foldtext(typval_T *argvars, typval_T *rettv, FunPtr fptr) /* skip C comment-start */ if (s[0] == '/' && (s[1] == '*' || s[1] == '/')) { s = skipwhite(s + 2); - if (*skipwhite(s) == NUL - && lnum + 1 < (linenr_T)vimvars[VV_FOLDEND].vv_nr) { + if (*skipwhite(s) == NUL && lnum + 1 < foldend) { s = skipwhite(ml_get(lnum + 1)); if (*s == '*') s = skipwhite(s + 1); } } - txt = _("+-%s%3ld lines: "); + unsigned long count = (unsigned long)(foldend - foldstart + 1); + txt = ngettext("+-%s%3ld line: ", "+-%s%3ld lines: ", count); r = xmalloc(STRLEN(txt) - + STRLEN(vimvars[VV_FOLDDASHES].vv_str) // for %s - + 20 // for %3ld - + STRLEN(s)); // concatenated - sprintf((char *)r, txt, vimvars[VV_FOLDDASHES].vv_str, - (long)((linenr_T)vimvars[VV_FOLDEND].vv_nr - - (linenr_T)vimvars[VV_FOLDSTART].vv_nr + 1)); + + STRLEN(dashes) // for %s + + 20 // for %3ld + + STRLEN(s)); // concatenated + sprintf((char *)r, txt, dashes, count); len = (int)STRLEN(r); STRCAT(r, s); /* remove 'foldmarker' and 'commentstring' */ @@ -9626,24 +8753,24 @@ static void f_foldtext(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_foldtextresult(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - linenr_T lnum; char_u *text; - char_u buf[51]; + char_u buf[FOLD_TEXT_LEN]; foldinfo_T foldinfo; int fold_count; rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; - lnum = get_tv_lnum(argvars); - /* treat illegal types and illegal string values for {lnum} the same */ - if (lnum < 0) + linenr_T lnum = tv_get_lnum(argvars); + // Treat illegal types and illegal string values for {lnum} the same. + if (lnum < 0) { lnum = 0; + } fold_count = foldedCount(curwin, lnum, &foldinfo); if (fold_count > 0) { - text = get_foldtext(curwin, lnum, lnum + fold_count - 1, - &foldinfo, buf); - if (text == buf) + text = get_foldtext(curwin, lnum, lnum + fold_count - 1, &foldinfo, buf); + if (text == buf) { text = vim_strsave(text); + } rettv->vval.v_string = text; } } @@ -9655,15 +8782,14 @@ static void f_foreground(typval_T *argvars, typval_T *rettv, FunPtr fptr) { } -/* - * "function()" function - */ -static void f_function(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void common_function(typval_T *argvars, typval_T *rettv, + bool is_funcref, FunPtr fptr) { char_u *s; char_u *name; bool use_string = false; partial_T *arg_pt = NULL; + char_u *trans_name = NULL; if (argvars[0].v_type == VAR_FUNC) { // function(MyFunc, [arg], dict) @@ -9672,18 +8798,31 @@ static void f_function(typval_T *argvars, typval_T *rettv, FunPtr fptr) && argvars[0].vval.v_partial != NULL) { // function(dict.MyFunc, [arg]) arg_pt = argvars[0].vval.v_partial; - s = arg_pt->pt_name; + s = partial_name(arg_pt); } else { // function('MyFunc', [arg], dict) - s = get_tv_string(&argvars[0]); + s = (char_u *)tv_get_string(&argvars[0]); use_string = true; } - if (s == NULL || *s == NUL || (use_string && ascii_isdigit(*s))) { - EMSG2(_(e_invarg2), s); - } else if (use_string && vim_strchr(s, AUTOLOAD_CHAR) == NULL - && !function_exists(s)) { + if ((use_string && vim_strchr(s, AUTOLOAD_CHAR) == NULL) || is_funcref) { + name = s; + trans_name = trans_function_name(&name, false, + TFN_INT | TFN_QUIET | TFN_NO_AUTOLOAD + | TFN_NO_DEREF, NULL, NULL); + if (*name != NUL) { + s = NULL; + } + } + if (s == NULL || *s == NUL || (use_string && ascii_isdigit(*s)) + || (is_funcref && trans_name == NULL)) { + emsgf(_(e_invarg2), (use_string + ? tv_get_string(&argvars[0]) + : (const char *)s)); // Don't check an autoload name for existence here. + } else if (trans_name != NULL + && (is_funcref ? find_func(trans_name) == NULL + : !translated_function_exists((const char *)trans_name))) { EMSG2(_("E700: Unknown function: %s"), s); } else { int dict_idx = 0; @@ -9724,7 +8863,7 @@ static void f_function(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (argvars[dict_idx].v_type != VAR_DICT) { EMSG(_("E922: expected a dict")); xfree(name); - return; + goto theend; } if (argvars[dict_idx].vval.v_dict == NULL) { dict_idx = 0; @@ -9735,7 +8874,7 @@ static void f_function(typval_T *argvars, typval_T *rettv, FunPtr fptr) EMSG(_("E923: Second argument of function() must be " "a list or a dict")); xfree(name); - return; + goto theend; } list = argvars[arg_idx].vval.v_list; if (list == NULL || list->lv_len == 0) { @@ -9743,61 +8882,64 @@ static void f_function(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } } - if (dict_idx > 0 || arg_idx > 0 || arg_pt != NULL) { - partial_T *pt = (partial_T *)xcalloc(1, sizeof(partial_T)); + if (dict_idx > 0 || arg_idx > 0 || arg_pt != NULL || is_funcref) { + partial_T *const pt = xcalloc(1, sizeof(*pt)); // result is a VAR_PARTIAL - if (pt != NULL) { - if (arg_idx > 0 || (arg_pt != NULL && arg_pt->pt_argc > 0)) { - listitem_T *li; - int i = 0; - int arg_len = 0; - int lv_len = 0; - - if (arg_pt != NULL) { - arg_len = arg_pt->pt_argc; - } - if (list != NULL) { - lv_len = list->lv_len; - } - pt->pt_argc = arg_len + lv_len; - pt->pt_argv = (typval_T *)xmalloc(sizeof(typval_T) * pt->pt_argc); - if (pt->pt_argv == NULL) { - xfree(pt); - xfree(name); - return; - } else { - for (i = 0; i < arg_len; i++) { - copy_tv(&arg_pt->pt_argv[i], &pt->pt_argv[i]); - } - if (lv_len > 0) { - for (li = list->lv_first; li != NULL; li = li->li_next) { - copy_tv(&li->li_tv, &pt->pt_argv[i++]); - } - } + if (arg_idx > 0 || (arg_pt != NULL && arg_pt->pt_argc > 0)) { + const int arg_len = (arg_pt == NULL ? 0 : arg_pt->pt_argc); + const int lv_len = (list == NULL ? 0 : list->lv_len); + + pt->pt_argc = arg_len + lv_len; + pt->pt_argv = xmalloc(sizeof(pt->pt_argv[0]) * pt->pt_argc); + if (pt->pt_argv == NULL) { + xfree(pt); + xfree(name); + goto theend; + } + int i = 0; + for (; i < arg_len; i++) { + tv_copy(&arg_pt->pt_argv[i], &pt->pt_argv[i]); + } + if (lv_len > 0) { + for (listitem_T *li = list->lv_first; + li != NULL; + li = li->li_next) { + tv_copy(&li->li_tv, &pt->pt_argv[i++]); } } + } - // For "function(dict.func, [], dict)" and "func" is a partial - // use "dict". That is backwards compatible. - if (dict_idx > 0) { - // The dict is bound explicitly, pt_auto is false - pt->pt_dict = argvars[dict_idx].vval.v_dict; + // For "function(dict.func, [], dict)" and "func" is a partial + // use "dict". That is backwards compatible. + if (dict_idx > 0) { + // The dict is bound explicitly, pt_auto is false + pt->pt_dict = argvars[dict_idx].vval.v_dict; + (pt->pt_dict->dv_refcount)++; + } else if (arg_pt != NULL) { + // If the dict was bound automatically the result is also + // bound automatically. + pt->pt_dict = arg_pt->pt_dict; + pt->pt_auto = arg_pt->pt_auto; + if (pt->pt_dict != NULL) { (pt->pt_dict->dv_refcount)++; - } else if (arg_pt != NULL) { - // If the dict was bound automatically the result is also - // bound automatically. - pt->pt_dict = arg_pt->pt_dict; - pt->pt_auto = arg_pt->pt_auto; - if (pt->pt_dict != NULL) { - (pt->pt_dict->dv_refcount)++; - } } + } - pt->pt_refcount = 1; + pt->pt_refcount = 1; + if (arg_pt != NULL && arg_pt->pt_func != NULL) { + pt->pt_func = arg_pt->pt_func; + func_ptr_ref(pt->pt_func); + xfree(name); + } else if (is_funcref) { + pt->pt_func = find_func(trans_name); + func_ptr_ref(pt->pt_func); + xfree(name); + } else { pt->pt_name = name; - func_ref(pt->pt_name); + func_ref(name); } + rettv->v_type = VAR_PARTIAL; rettv->vval.v_partial = pt; } else { @@ -9807,17 +8949,30 @@ static void f_function(typval_T *argvars, typval_T *rettv, FunPtr fptr) func_ref(name); } } +theend: + xfree(trans_name); +} + +static void f_funcref(typval_T *argvars, typval_T *rettv, FunPtr fptr) +{ + common_function(argvars, rettv, true, fptr); +} + +static void f_function(typval_T *argvars, typval_T *rettv, FunPtr fptr) +{ + common_function(argvars, rettv, false, fptr); } /// "garbagecollect()" function static void f_garbagecollect(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - /* This is postponed until we are back at the toplevel, because we may be - * using Lists and Dicts internally. E.g.: ":echo [garbagecollect()]". */ - want_garbage_collect = TRUE; + // This is postponed until we are back at the toplevel, because we may be + // using Lists and Dicts internally. E.g.: ":echo [garbagecollect()]". + want_garbage_collect = true; - if (argvars[0].v_type != VAR_UNKNOWN && get_tv_number(&argvars[0]) == 1) - garbage_collect_at_exit = TRUE; + if (argvars[0].v_type != VAR_UNKNOWN && tv_get_number(&argvars[0]) == 1) { + garbage_collect_at_exit = true; + } } /* @@ -9833,20 +8988,21 @@ static void f_get(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (argvars[0].v_type == VAR_LIST) { if ((l = argvars[0].vval.v_list) != NULL) { - int error = FALSE; + bool error = false; - li = list_find(l, get_tv_number_chk(&argvars[1], &error)); - if (!error && li != NULL) + li = tv_list_find(l, tv_get_number_chk(&argvars[1], &error)); + if (!error && li != NULL) { tv = &li->li_tv; + } } } else if (argvars[0].v_type == VAR_DICT) { if ((d = argvars[0].vval.v_dict) != NULL) { - di = dict_find(d, get_tv_string(&argvars[1]), -1); - if (di != NULL) + di = tv_dict_find(d, tv_get_string(&argvars[1]), -1); + if (di != NULL) { tv = &di->di_tv; + } } - } else if (argvars[0].v_type == VAR_PARTIAL - || argvars[0].v_type == VAR_FUNC) { + } else if (tv_is_func(argvars[0])) { partial_T *pt; partial_T fref_pt; @@ -9859,26 +9015,27 @@ static void f_get(typval_T *argvars, typval_T *rettv, FunPtr fptr) } if (pt != NULL) { - char_u *what = get_tv_string(&argvars[1]); + const char *const what = tv_get_string(&argvars[1]); - if (STRCMP(what, "func") == 0 || STRCMP(what, "name") == 0) { + if (strcmp(what, "func") == 0 || strcmp(what, "name") == 0) { rettv->v_type = (*what == 'f' ? VAR_FUNC : VAR_STRING); - if (pt->pt_name != NULL) { - rettv->vval.v_string = vim_strsave(pt->pt_name); + const char *const n = (const char *)partial_name(pt); + assert(n != NULL); + rettv->vval.v_string = (char_u *)xstrdup(n); + if (rettv->v_type == VAR_FUNC) { + func_ref(rettv->vval.v_string); } - } else if (STRCMP(what, "dict") == 0) { + } else if (strcmp(what, "dict") == 0) { rettv->v_type = VAR_DICT; rettv->vval.v_dict = pt->pt_dict; if (pt->pt_dict != NULL) { (pt->pt_dict->dv_refcount)++; } - } else if (STRCMP(what, "args") == 0) { + } else if (strcmp(what, "args") == 0) { rettv->v_type = VAR_LIST; - if (rettv_list_alloc(rettv) != NULL) { - int i; - - for (i = 0; i < pt->pt_argc; i++) { - list_append_tv(rettv->vval.v_list, &pt->pt_argv[i]); + if (tv_list_alloc_ret(rettv) != NULL) { + for (int i = 0; i < pt->pt_argc; i++) { + tv_list_append_tv(rettv->vval.v_list, &pt->pt_argv[i]); } } } else { @@ -9891,60 +9048,63 @@ static void f_get(typval_T *argvars, typval_T *rettv, FunPtr fptr) } if (tv == NULL) { - if (argvars[2].v_type != VAR_UNKNOWN) - copy_tv(&argvars[2], rettv); - } else - copy_tv(tv, rettv); + if (argvars[2].v_type != VAR_UNKNOWN) { + tv_copy(&argvars[2], rettv); + } + } else { + tv_copy(tv, rettv); + } } /// Returns information about signs placed in a buffer as list of dicts. static void get_buffer_signs(buf_T *buf, list_T *l) { for (signlist_T *sign = buf->b_signlist; sign; sign = sign->next) { - dict_T *d = dict_alloc(); + dict_T *const d = tv_dict_alloc(); - dict_add_nr_str(d, "id", sign->id, NULL); - dict_add_nr_str(d, "lnum", sign->lnum, NULL); - dict_add_nr_str(d, "name", 0L, sign_typenr2name(sign->typenr)); + tv_dict_add_nr(d, S_LEN("id"), sign->id); + tv_dict_add_nr(d, S_LEN("lnum"), sign->lnum); + tv_dict_add_str(d, S_LEN("name"), + (const char *)sign_typenr2name(sign->typenr)); - list_append_dict(l, d); + tv_list_append_dict(l, d); } } /// Returns buffer options, variables and other attributes in a dictionary. static dict_T *get_buffer_info(buf_T *buf) { - dict_T *dict = dict_alloc(); - - dict_add_nr_str(dict, "bufnr", buf->b_fnum, NULL); - dict_add_nr_str(dict, "name", 0L, - buf->b_ffname != NULL ? buf->b_ffname : (char_u *)""); - dict_add_nr_str(dict, "lnum", buflist_findlnum(buf), NULL); - dict_add_nr_str(dict, "loaded", buf->b_ml.ml_mfp != NULL, NULL); - dict_add_nr_str(dict, "listed", buf->b_p_bl, NULL); - dict_add_nr_str(dict, "changed", bufIsChanged(buf), NULL); - dict_add_nr_str(dict, "changedtick", buf->b_changedtick, NULL); - dict_add_nr_str(dict, "hidden", - buf->b_ml.ml_mfp != NULL && buf->b_nwindows == 0, - NULL); + dict_T *const dict = tv_dict_alloc(); + + tv_dict_add_nr(dict, S_LEN("bufnr"), buf->b_fnum); + tv_dict_add_str(dict, S_LEN("name"), + buf->b_ffname != NULL ? (const char *)buf->b_ffname : ""); + tv_dict_add_nr(dict, S_LEN("lnum"), + buf == curbuf ? curwin->w_cursor.lnum : buflist_findlnum(buf)); + tv_dict_add_nr(dict, S_LEN("loaded"), buf->b_ml.ml_mfp != NULL); + tv_dict_add_nr(dict, S_LEN("listed"), buf->b_p_bl); + tv_dict_add_nr(dict, S_LEN("changed"), bufIsChanged(buf)); + tv_dict_add_nr(dict, S_LEN("changedtick"), buf->b_changedtick); + tv_dict_add_nr(dict, S_LEN("hidden"), + buf->b_ml.ml_mfp != NULL && buf->b_nwindows == 0); // Get a reference to buffer variables - dict_add_dict(dict, "variables", buf->b_vars); + tv_dict_add_dict(dict, S_LEN("variables"), buf->b_vars); // List of windows displaying this buffer - list_T *windows = list_alloc(); + list_T *const windows = tv_list_alloc(); FOR_ALL_TAB_WINDOWS(tp, wp) { if (wp->w_buffer == buf) { - list_append_number(windows, (varnumber_T)wp->handle); + tv_list_append_number(windows, (varnumber_T)wp->handle); } } - dict_add_list(dict, "windows", windows); + tv_dict_add_list(dict, S_LEN("windows"), windows); if (buf->b_signlist != NULL) { // List of signs placed in this buffer - list_T *signs = list_alloc(); + list_T *const signs = tv_list_alloc(); get_buffer_signs(buf, signs); - dict_add_list(dict, "signs", signs); + tv_dict_add_list(dict, S_LEN("signs"), signs); } return dict; @@ -9958,7 +9118,7 @@ static void f_getbufinfo(typval_T *argvars, typval_T *rettv, FunPtr fptr) bool sel_buflisted = false; bool sel_bufloaded = false; - rettv_list_alloc(rettv); + tv_list_alloc_ret(rettv); // List of all the buffers or selected buffers if (argvars[0].v_type == VAR_DICT) { @@ -9969,24 +9129,25 @@ static void f_getbufinfo(typval_T *argvars, typval_T *rettv, FunPtr fptr) filtered = true; - di = dict_find(sel_d, (char_u *)"buflisted", -1); - if (di != NULL && get_tv_number(&di->di_tv)) { + di = tv_dict_find(sel_d, S_LEN("buflisted")); + if (di != NULL && tv_get_number(&di->di_tv)) { sel_buflisted = true; } - di = dict_find(sel_d, (char_u *)"bufloaded", -1); - if (di != NULL && get_tv_number(&di->di_tv)) { + di = tv_dict_find(sel_d, S_LEN("bufloaded")); + if (di != NULL && tv_get_number(&di->di_tv)) { sel_bufloaded = true; } } } else if (argvars[0].v_type != VAR_UNKNOWN) { // Information about one buffer. Argument specifies the buffer - (void)get_tv_number(&argvars[0]); // issue errmsg if type error - emsg_off++; - argbuf = get_buf_tv(&argvars[0], false); - emsg_off--; - if (argbuf == NULL) { - return; + if (tv_check_num(&argvars[0])) { // issue errmsg if type error + emsg_off++; + argbuf = get_buf_tv(&argvars[0], false); + emsg_off--; + if (argbuf == NULL) { + return; + } } } @@ -10000,9 +9161,9 @@ static void f_getbufinfo(typval_T *argvars, typval_T *rettv, FunPtr fptr) continue; } - dict_T *d = get_buffer_info(buf); + dict_T *const d = get_buffer_info(buf); if (d != NULL) { - list_append_dict(rettv->vval.v_list, d); + tv_list_append_dict(rettv->vval.v_list, d); } if (argbuf != NULL) { return; @@ -10023,7 +9184,7 @@ static void get_buffer_lines(buf_T *buf, linenr_T start, linenr_T end, int retli rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; if (retlist) { - rettv_list_alloc(rettv); + tv_list_alloc_ret(rettv); } if (buf == NULL || buf->b_ml.ml_mfp == NULL || start < 0) @@ -10044,33 +9205,54 @@ static void get_buffer_lines(buf_T *buf, linenr_T start, linenr_T end, int retli if (end > buf->b_ml.ml_line_count) end = buf->b_ml.ml_line_count; while (start <= end) { - list_append_string( - rettv->vval.v_list, ml_get_buf(buf, start++, FALSE), -1); + tv_list_append_string(rettv->vval.v_list, + (const char *)ml_get_buf(buf, start++, false), -1); } } } +/// Get the line number from VimL object +/// +/// @note Unlike tv_get_lnum(), this one supports only "$" special string. +/// +/// @param[in] tv Object to get value from. Is expected to be a number or +/// a special string "$". +/// @param[in] buf Buffer to take last line number from in case tv is "$". May +/// be NULL, in this case "$" results in zero return. +/// +/// @return Line number or 0 in case of error. +static linenr_T tv_get_lnum_buf(const typval_T *const tv, + const buf_T *const buf) + FUNC_ATTR_NONNULL_ARG(1) FUNC_ATTR_WARN_UNUSED_RESULT +{ + if (tv->v_type == VAR_STRING + && tv->vval.v_string != NULL + && tv->vval.v_string[0] == '$' + && buf != NULL) { + return buf->b_ml.ml_line_count; + } + return tv_get_number_chk(tv, NULL); +} + /* * "getbufline()" function */ static void f_getbufline(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - linenr_T lnum; - linenr_T end; - buf_T *buf; + buf_T *buf = NULL; - (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */ - ++emsg_off; - buf = get_buf_tv(&argvars[0], FALSE); - --emsg_off; + if (tv_check_str_or_nr(&argvars[0])) { + emsg_off++; + buf = get_buf_tv(&argvars[0], false); + emsg_off--; + } - lnum = get_tv_lnum_buf(&argvars[1], buf); - if (argvars[2].v_type == VAR_UNKNOWN) - end = lnum; - else - end = get_tv_lnum_buf(&argvars[2], buf); + const linenr_T lnum = tv_get_lnum_buf(&argvars[1], buf); + const linenr_T end = (argvars[2].v_type == VAR_UNKNOWN + ? lnum + : tv_get_lnum_buf(&argvars[2], buf)); - get_buffer_lines(buf, lnum, end, TRUE, rettv); + get_buffer_lines(buf, lnum, end, true, rettv); } /* @@ -10078,26 +9260,25 @@ static void f_getbufline(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_getbufvar(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - buf_T *buf; - buf_T *save_curbuf; - char_u *varname; - dictitem_T *v; - int done = FALSE; - - (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */ - varname = get_tv_string_chk(&argvars[1]); - ++emsg_off; - buf = get_buf_tv(&argvars[0], FALSE); + bool done = false; rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; + if (!tv_check_str_or_nr(&argvars[0])) { + goto f_getbufvar_end; + } + + const char *varname = tv_get_string_chk(&argvars[1]); + emsg_off++; + buf_T *const buf = get_buf_tv(&argvars[0], false); + if (buf != NULL && varname != NULL) { - /* set curbuf to be our buf, temporarily */ - save_curbuf = curbuf; + // set curbuf to be our buf, temporarily + buf_T *const save_curbuf = curbuf; curbuf = buf; - if (*varname == '&') { // buffer-local-option + if (*varname == '&') { // buffer-local-option if (varname[1] == NUL) { // get all buffer-local options in a dict dict_T *opts = get_winbuf_options(true); @@ -10112,30 +9293,27 @@ static void f_getbufvar(typval_T *argvars, typval_T *rettv, FunPtr fptr) // buffer-local-option done = true; } - } else if (STRCMP(varname, "changedtick") == 0) { - rettv->v_type = VAR_NUMBER; - rettv->vval.v_number = curbuf->b_changedtick; - done = true; } else { - /* Look up the variable. */ - /* Let getbufvar({nr}, "") return the "b:" dictionary. */ - v = find_var_in_ht(&curbuf->b_vars->dv_hashtab, - 'b', varname, FALSE); + // Look up the variable. + // Let getbufvar({nr}, "") return the "b:" dictionary. + dictitem_T *const v = find_var_in_ht(&curbuf->b_vars->dv_hashtab, 'b', + varname, strlen(varname), false); if (v != NULL) { - copy_tv(&v->di_tv, rettv); - done = TRUE; + tv_copy(&v->di_tv, rettv); + done = true; } } - /* restore previous notion of curbuf */ + // restore previous notion of curbuf curbuf = save_curbuf; } + emsg_off--; - if (!done && argvars[2].v_type != VAR_UNKNOWN) - /* use the default value */ - copy_tv(&argvars[2], rettv); - - --emsg_off; +f_getbufvar_end: + if (!done && argvars[2].v_type != VAR_UNKNOWN) { + // use the default value + tv_copy(&argvars[2], rettv); + } } /* @@ -10144,10 +9322,9 @@ static void f_getbufvar(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_getchar(typval_T *argvars, typval_T *rettv, FunPtr fptr) { varnumber_T n; - int error = FALSE; + bool error = false; - ++no_mapping; - ++allow_keys; + no_mapping++; for (;; ) { // Position the cursor. Needed after a message that ends in a space, // or if event processing caused a redraw. @@ -10165,7 +9342,7 @@ static void f_getchar(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } n = safe_vgetc(); - } else if (get_tv_number_chk(&argvars[0], &error) == 1) { + } else if (tv_get_number_chk(&argvars[0], &error) == 1) { // getchar(1): only check if char avail n = vpeekc_any(); } else if (error || vpeekc_any() == NUL) { @@ -10176,12 +9353,12 @@ static void f_getchar(typval_T *argvars, typval_T *rettv, FunPtr fptr) n = safe_vgetc(); } - if (n == K_IGNORE) + if (n == K_IGNORE) { continue; + } break; } - --no_mapping; - --allow_keys; + no_mapping--; vimvars[VV_MOUSE_WIN].vv_nr = 0; vimvars[VV_MOUSE_WINID].vv_nr = 0; @@ -10248,13 +9425,13 @@ static void f_getcharmod(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_getcharsearch(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - rettv_dict_alloc(rettv); + tv_dict_alloc_ret(rettv); dict_T *dict = rettv->vval.v_dict; - dict_add_nr_str(dict, "char", 0L, last_csearch()); - dict_add_nr_str(dict, "forward", last_csearch_forward(), NULL); - dict_add_nr_str(dict, "until", last_csearch_until(), NULL); + tv_dict_add_str(dict, S_LEN("char"), last_csearch()); + tv_dict_add_nr(dict, S_LEN("forward"), last_csearch_forward()); + tv_dict_add_nr(dict, S_LEN("until"), last_csearch_until()); } /* @@ -10305,7 +9482,7 @@ static void f_getcompletion(typval_T *argvars, typval_T *rettv, FunPtr fptr) | WILD_NO_BEEP; if (argvars[2].v_type != VAR_UNKNOWN) { - filtered = get_tv_number_chk(&argvars[2], NULL); + filtered = (bool)tv_get_number_chk(&argvars[2], NULL); } if (p_wic) { @@ -10317,41 +9494,51 @@ static void f_getcompletion(typval_T *argvars, typval_T *rettv, FunPtr fptr) options |= WILD_KEEP_ALL; } + if (argvars[0].v_type != VAR_STRING || argvars[1].v_type != VAR_STRING) { + EMSG(_(e_invarg)); + return; + } + + if (strcmp(tv_get_string(&argvars[1]), "cmdline") == 0) { + set_one_cmd_context(&xpc, tv_get_string(&argvars[0])); + xpc.xp_pattern_len = (int)STRLEN(xpc.xp_pattern); + goto theend; + } + ExpandInit(&xpc); - xpc.xp_pattern = get_tv_string(&argvars[0]); - xpc.xp_pattern_len = STRLEN(xpc.xp_pattern); - xpc.xp_context = cmdcomplete_str_to_type(get_tv_string(&argvars[1])); + xpc.xp_pattern = (char_u *)tv_get_string(&argvars[0]); + xpc.xp_pattern_len = (int)STRLEN(xpc.xp_pattern); + xpc.xp_context = cmdcomplete_str_to_type( + (char_u *)tv_get_string(&argvars[1])); if (xpc.xp_context == EXPAND_NOTHING) { - if (argvars[1].v_type == VAR_STRING) { - EMSG2(_(e_invarg2), argvars[1].vval.v_string); - } else { - EMSG(_(e_invarg)); - } + EMSG2(_(e_invarg2), argvars[1].vval.v_string); return; } if (xpc.xp_context == EXPAND_MENUS) { set_context_in_menu_cmd(&xpc, (char_u *)"menu", xpc.xp_pattern, false); - xpc.xp_pattern_len = STRLEN(xpc.xp_pattern); + xpc.xp_pattern_len = (int)STRLEN(xpc.xp_pattern); } if (xpc.xp_context == EXPAND_CSCOPE) { - set_context_in_cscope_cmd(&xpc, xpc.xp_pattern, CMD_cscope); - xpc.xp_pattern_len = STRLEN(xpc.xp_pattern); + set_context_in_cscope_cmd(&xpc, (const char *)xpc.xp_pattern, CMD_cscope); + xpc.xp_pattern_len = (int)STRLEN(xpc.xp_pattern); } if (xpc.xp_context == EXPAND_SIGN) { set_context_in_sign_cmd(&xpc, xpc.xp_pattern); - xpc.xp_pattern_len = STRLEN(xpc.xp_pattern); + xpc.xp_pattern_len = (int)STRLEN(xpc.xp_pattern); } +theend: pat = addstar(xpc.xp_pattern, xpc.xp_pattern_len, xpc.xp_context); - rettv_list_alloc(rettv); + tv_list_alloc_ret(rettv); if (pat != NULL) { ExpandOne(&xpc, pat, NULL, options, WILD_ALL_KEEP); for (int i = 0; i < xpc.xp_numfiles; i++) { - list_append_string(rettv->vval.v_list, xpc.xp_files[i], -1); + tv_list_append_string(rettv->vval.v_list, (const char *)xpc.xp_files[i], + -1); } } xfree(pat); @@ -10452,13 +9639,15 @@ static void f_getcwd(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (from) { break; } - case kCdScopeTab: // FALLTHROUGH + // fallthrough + case kCdScopeTab: assert(tp); - from = tp->localdir; + from = tp->tp_localdir; if (from) { break; } - case kCdScopeGlobal: // FALLTHROUGH + // fallthrough + case kCdScopeGlobal: if (globaldir) { // `globaldir` is not always set. from = globaldir; } else if (os_dirname(cwd, MAXPATHL) == FAIL) { // Get the OS CWD. @@ -10495,20 +9684,21 @@ static void f_getfontname(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_getfperm(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *perm = NULL; + char *perm = NULL; char_u flags[] = "rwx"; - char_u *filename = get_tv_string(&argvars[0]); + const char *filename = tv_get_string(&argvars[0]); int32_t file_perm = os_getperm(filename); if (file_perm >= 0) { - perm = vim_strsave((char_u *)"---------"); + perm = xstrdup("---------"); for (int i = 0; i < 9; i++) { - if (file_perm & (1 << (8 - i))) + if (file_perm & (1 << (8 - i))) { perm[i] = flags[i % 3]; + } } } rettv->v_type = VAR_STRING; - rettv->vval.v_string = perm; + rettv->vval.v_string = (char_u *)perm; } /* @@ -10516,16 +9706,16 @@ static void f_getfperm(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_getfsize(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char *fname = (char *)get_tv_string(&argvars[0]); + const char *fname = tv_get_string(&argvars[0]); rettv->v_type = VAR_NUMBER; FileInfo file_info; if (os_fileinfo(fname, &file_info)) { uint64_t filesize = os_fileinfo_size(&file_info); - if (os_isdir((char_u *)fname)) + if (os_isdir((const char_u *)fname)) { rettv->vval.v_number = 0; - else { + } else { rettv->vval.v_number = (varnumber_T)filesize; /* non-perfect check for overflow */ @@ -10543,7 +9733,7 @@ static void f_getfsize(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_getftime(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char *fname = (char *)get_tv_string(&argvars[0]); + const char *fname = tv_get_string(&argvars[0]); FileInfo file_info; if (os_fileinfo(fname, &file_info)) { @@ -10558,15 +9748,14 @@ static void f_getftime(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_getftype(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *fname; char_u *type = NULL; char *t; - fname = get_tv_string(&argvars[0]); + const char *fname = tv_get_string(&argvars[0]); rettv->v_type = VAR_STRING; FileInfo file_info; - if (os_fileinfo_link((char *)fname, &file_info)) { + if (os_fileinfo_link(fname, &file_info)) { uint64_t mode = file_info.stat.st_mode; #ifdef S_ISREG if (S_ISREG(mode)) @@ -10618,10 +9807,11 @@ static void f_getftype(typval_T *argvars, typval_T *rettv, FunPtr fptr) default: t = "other"; } # else - if (os_isdir(fname)) + if (os_isdir((const char_u *)fname)) { t = "dir"; - else + } else { t = "file"; + } # endif #endif type = vim_strsave((char_u *)t); @@ -10634,22 +9824,52 @@ static void f_getftype(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_getline(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - linenr_T lnum; linenr_T end; - int retlist; + bool retlist; - lnum = get_tv_lnum(argvars); + const linenr_T lnum = tv_get_lnum(argvars); if (argvars[1].v_type == VAR_UNKNOWN) { end = 0; - retlist = FALSE; + retlist = false; } else { - end = get_tv_lnum(&argvars[1]); - retlist = TRUE; + end = tv_get_lnum(&argvars[1]); + retlist = true; } get_buffer_lines(curbuf, lnum, end, retlist, rettv); } +static void get_qf_loc_list(int is_qf, win_T *wp, typval_T *what_arg, + typval_T *rettv) +{ + if (what_arg->v_type == VAR_UNKNOWN) { + tv_list_alloc_ret(rettv); + if (is_qf || wp != NULL) { + (void)get_errorlist(wp, -1, rettv->vval.v_list); + } + } else { + tv_dict_alloc_ret(rettv); + if (is_qf || wp != NULL) { + if (what_arg->v_type == VAR_DICT) { + dict_T *d = what_arg->vval.v_dict; + + if (d != NULL) { + get_errorlist_properties(wp, d, rettv->vval.v_dict); + } + } else { + EMSG(_(e_dictreq)); + } + } + } +} + +/// "getloclist()" function +static void f_getloclist(typval_T *argvars, typval_T *rettv, FunPtr fptr) +{ + win_T *wp = find_win_by_nr(&argvars[0], NULL); + get_qf_loc_list(false, wp, &argvars[1], rettv); +} + /* * "getmatches()" function */ @@ -10658,43 +9878,45 @@ static void f_getmatches(typval_T *argvars, typval_T *rettv, FunPtr fptr) matchitem_T *cur = curwin->w_match_head; int i; - rettv_list_alloc(rettv); + tv_list_alloc_ret(rettv); while (cur != NULL) { - dict_T *dict = dict_alloc(); + dict_T *dict = tv_dict_alloc(); if (cur->match.regprog == NULL) { // match added with matchaddpos() for (i = 0; i < MAXPOSMATCH; ++i) { llpos_T *llpos; - char buf[6]; + char buf[6]; llpos = &cur->pos.pos[i]; if (llpos->lnum == 0) { break; } - list_T *l = list_alloc(); - list_append_number(l, (varnumber_T)llpos->lnum); + list_T *l = tv_list_alloc(); + tv_list_append_number(l, (varnumber_T)llpos->lnum); if (llpos->col > 0) { - list_append_number(l, (varnumber_T)llpos->col); - list_append_number(l, (varnumber_T)llpos->len); + tv_list_append_number(l, (varnumber_T)llpos->col); + tv_list_append_number(l, (varnumber_T)llpos->len); } - sprintf(buf, "pos%d", i + 1); - dict_add_list(dict, buf, l); + int len = snprintf(buf, sizeof(buf), "pos%d", i + 1); + assert((size_t)len < sizeof(buf)); + tv_dict_add_list(dict, buf, (size_t)len, l); } } else { - dict_add_nr_str(dict, "pattern", 0L, cur->pattern); + tv_dict_add_str(dict, S_LEN("pattern"), (const char *)cur->pattern); } - dict_add_nr_str(dict, "group", 0L, syn_id2name(cur->hlg_id)); - dict_add_nr_str(dict, "priority", (long)cur->priority, NULL); - dict_add_nr_str(dict, "id", (long)cur->id, NULL); + tv_dict_add_str(dict, S_LEN("group"), + (const char *)syn_id2name(cur->hlg_id)); + tv_dict_add_nr(dict, S_LEN("priority"), (varnumber_T)cur->priority); + tv_dict_add_nr(dict, S_LEN("id"), (varnumber_T)cur->id); if (cur->conceal_char) { - char_u buf[MB_MAXBYTES + 1]; + char buf[MB_MAXBYTES + 1]; - buf[(*mb_char2bytes)((int)cur->conceal_char, buf)] = NUL; - dict_add_nr_str(dict, "conceal", 0L, (char_u *)&buf); + buf[(*mb_char2bytes)((int)cur->conceal_char, (char_u *)buf)] = NUL; + tv_dict_add_str(dict, S_LEN("conceal"), buf); } - list_append_dict(rettv->vval.v_list, dict); + tv_list_append_dict(rettv->vval.v_list, dict); cur = cur->next; } } @@ -10718,20 +9940,22 @@ static void getpos_both(typval_T *argvars, typval_T *rettv, bool getcurpos) fp = var2fpos(&argvars[0], true, &fnum); } - list_T *l = rettv_list_alloc(rettv); - list_append_number(l, (fnum != -1) ? (varnumber_T)fnum : (varnumber_T)0); - list_append_number(l, (fp != NULL) ? (varnumber_T)fp->lnum : (varnumber_T)0); - list_append_number(l, - (fp != NULL) - ? (varnumber_T)(fp->col == MAXCOL ? MAXCOL : fp->col + 1) - : (varnumber_T)0); - list_append_number(l, - (fp != NULL) ? (varnumber_T)fp->coladd : (varnumber_T)0); + list_T *l = tv_list_alloc_ret(rettv); + tv_list_append_number(l, (fnum != -1) ? (varnumber_T)fnum : (varnumber_T)0); + tv_list_append_number(l, ((fp != NULL) + ? (varnumber_T)fp->lnum + : (varnumber_T)0)); + tv_list_append_number( + l, ((fp != NULL) + ? (varnumber_T)(fp->col == MAXCOL ? MAXCOL : fp->col + 1) + : (varnumber_T)0)); + tv_list_append_number( + l, (fp != NULL) ? (varnumber_T)fp->coladd : (varnumber_T)0); if (getcurpos) { update_curswant(); - list_append_number(l, curwin->w_curswant == MAXCOL + tv_list_append_number(l, (curwin->w_curswant == MAXCOL ? (varnumber_T)MAXCOL - : (varnumber_T)curwin->w_curswant + 1); + : (varnumber_T)curwin->w_curswant + 1)); } } @@ -10751,58 +9975,48 @@ static void f_getpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) getpos_both(argvars, rettv, false); } -/* - * "getqflist()" and "getloclist()" functions - */ +/// "getqflist()" functions static void f_getqflist(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - rettv_list_alloc(rettv); - win_T *wp = NULL; - if (argvars[0].v_type != VAR_UNKNOWN) { /* getloclist() */ - wp = find_win_by_nr(&argvars[0], NULL); - if (wp == NULL) { - return; - } - } - (void)get_errorlist(wp, rettv->vval.v_list); + get_qf_loc_list(true, NULL, &argvars[0], rettv); } /// "getreg()" function static void f_getreg(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *strregname; - int regname; + const char *strregname; int arg2 = false; bool return_list = false; - int error = false; + bool error = false; if (argvars[0].v_type != VAR_UNKNOWN) { - strregname = get_tv_string_chk(&argvars[0]); + strregname = tv_get_string_chk(&argvars[0]); error = strregname == NULL; if (argvars[1].v_type != VAR_UNKNOWN) { - arg2 = get_tv_number_chk(&argvars[1], &error); + arg2 = tv_get_number_chk(&argvars[1], &error); if (!error && argvars[2].v_type != VAR_UNKNOWN) { - return_list = get_tv_number_chk(&argvars[2], &error); + return_list = tv_get_number_chk(&argvars[2], &error); } } } else { - strregname = vimvars[VV_REG].vv_str; + strregname = (const char *)vimvars[VV_REG].vv_str; } if (error) { return; } - regname = (strregname == NULL ? '"' : *strregname); - if (regname == 0) + int regname = (uint8_t)(strregname == NULL ? '"' : *strregname); + if (regname == 0) { regname = '"'; + } if (return_list) { rettv->v_type = VAR_LIST; rettv->vval.v_list = get_reg_contents(regname, (arg2 ? kGRegExprSrc : 0) | kGRegList); if (rettv->vval.v_list == NULL) { - rettv->vval.v_list = list_alloc(); + rettv->vval.v_list = tv_list_alloc(); } rettv->vval.v_list->lv_refcount++; } else { @@ -10816,23 +10030,24 @@ static void f_getreg(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_getregtype(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *strregname; - int regname; + const char *strregname; if (argvars[0].v_type != VAR_UNKNOWN) { - strregname = get_tv_string_chk(&argvars[0]); - if (strregname == NULL) { /* type error; errmsg already given */ + strregname = tv_get_string_chk(&argvars[0]); + if (strregname == NULL) { // Type error; errmsg already given. rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; return; } - } else - /* Default to v:register */ - strregname = vimvars[VV_REG].vv_str; + } else { + // Default to v:register. + strregname = (const char *)vimvars[VV_REG].vv_str; + } - regname = (strregname == NULL ? '"' : *strregname); - if (regname == 0) + int regname = (uint8_t)(strregname == NULL ? '"' : *strregname); + if (regname == 0) { regname = '"'; + } colnr_T reglen = 0; char buf[NUMBUFLEN + 2]; @@ -10847,18 +10062,18 @@ static void f_getregtype(typval_T *argvars, typval_T *rettv, FunPtr fptr) /// as a dictionary. static dict_T *get_tabpage_info(tabpage_T *tp, int tp_idx) { - dict_T *dict = dict_alloc(); + dict_T *const dict = tv_dict_alloc(); - dict_add_nr_str(dict, "tabnr", tp_idx, NULL); + tv_dict_add_nr(dict, S_LEN("tabnr"), tp_idx); - list_T *l = list_alloc(); + list_T *const l = tv_list_alloc(); FOR_ALL_WINDOWS_IN_TAB(wp, tp) { - list_append_number(l, (varnumber_T)wp->handle); + tv_list_append_number(l, (varnumber_T)wp->handle); } - dict_add_list(dict, "windows", l); + tv_dict_add_list(dict, S_LEN("windows"), l); // Make a reference to tabpage variables - dict_add_dict(dict, "variables", tp->tp_vars); + tv_dict_add_dict(dict, S_LEN("variables"), tp->tp_vars); return dict; } @@ -10868,11 +10083,11 @@ static void f_gettabinfo(typval_T *argvars, typval_T *rettv, FunPtr fptr) { tabpage_T *tparg = NULL; - rettv_list_alloc(rettv); + tv_list_alloc_ret(rettv); if (argvars[0].v_type != VAR_UNKNOWN) { // Information about one tab page - tparg = find_tabpage((int)get_tv_number_chk(&argvars[0], NULL)); + tparg = find_tabpage((int)tv_get_number_chk(&argvars[0], NULL)); if (tparg == NULL) { return; } @@ -10885,9 +10100,9 @@ static void f_gettabinfo(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (tparg != NULL && tp != tparg) { continue; } - dict_T *d = get_tabpage_info(tp, tpnr); + dict_T *const d = get_tabpage_info(tp, tpnr); if (d != NULL) { - list_append_dict(rettv->vval.v_list, d); + tv_list_append_dict(rettv->vval.v_list, d); } if (tparg != NULL) { return; @@ -10903,14 +10118,13 @@ static void f_gettabvar(typval_T *argvars, typval_T *rettv, FunPtr fptr) win_T *oldcurwin; tabpage_T *tp, *oldtabpage; dictitem_T *v; - char_u *varname; bool done = false; rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; - varname = get_tv_string_chk(&argvars[1]); - tp = find_tabpage((int)get_tv_number_chk(&argvars[0], NULL)); + const char *const varname = tv_get_string_chk(&argvars[1]); + tp = find_tabpage((int)tv_get_number_chk(&argvars[0], NULL)); if (tp != NULL && varname != NULL) { // Set tp to be our tabpage, temporarily. Also set the window to the // first window in the tabpage, otherwise the window is not valid. @@ -10918,9 +10132,10 @@ static void f_gettabvar(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (switch_win(&oldcurwin, &oldtabpage, window, tp, true) == OK) { // look up the variable // Let gettabvar({nr}, "") return the "t:" dictionary. - v = find_var_in_ht(&tp->tp_vars->dv_hashtab, 't', varname, FALSE); + v = find_var_in_ht(&tp->tp_vars->dv_hashtab, 't', + varname, strlen(varname), false); if (v != NULL) { - copy_tv(&v->di_tv, rettv); + tv_copy(&v->di_tv, rettv); done = true; } } @@ -10930,7 +10145,7 @@ static void f_gettabvar(typval_T *argvars, typval_T *rettv, FunPtr fptr) } if (!done && argvars[2].v_type != VAR_UNKNOWN) { - copy_tv(&argvars[2], rettv); + tv_copy(&argvars[2], rettv); } } @@ -10945,22 +10160,21 @@ static void f_gettabwinvar(typval_T *argvars, typval_T *rettv, FunPtr fptr) /// Returns information about a window as a dictionary. static dict_T *get_win_info(win_T *wp, int16_t tpnr, int16_t winnr) { - dict_T *dict = dict_alloc(); + dict_T *const dict = tv_dict_alloc(); - dict_add_nr_str(dict, "tabnr", tpnr, NULL); - dict_add_nr_str(dict, "winnr", winnr, NULL); - dict_add_nr_str(dict, "winid", wp->handle, NULL); - dict_add_nr_str(dict, "height", wp->w_height, NULL); - dict_add_nr_str(dict, "width", wp->w_width, NULL); - dict_add_nr_str(dict, "bufnr", wp->w_buffer->b_fnum, NULL); + tv_dict_add_nr(dict, S_LEN("tabnr"), tpnr); + tv_dict_add_nr(dict, S_LEN("winnr"), winnr); + tv_dict_add_nr(dict, S_LEN("winid"), wp->handle); + tv_dict_add_nr(dict, S_LEN("height"), wp->w_height); + tv_dict_add_nr(dict, S_LEN("width"), wp->w_width); + tv_dict_add_nr(dict, S_LEN("bufnr"), wp->w_buffer->b_fnum); - dict_add_nr_str(dict, "quickfix", bt_quickfix(wp->w_buffer), NULL); - dict_add_nr_str(dict, "loclist", - (bt_quickfix(wp->w_buffer) && wp->w_llist_ref != NULL), - NULL); + tv_dict_add_nr(dict, S_LEN("quickfix"), bt_quickfix(wp->w_buffer)); + tv_dict_add_nr(dict, S_LEN("loclist"), + (bt_quickfix(wp->w_buffer) && wp->w_llist_ref != NULL)); // Add a reference to window variables - dict_add_dict(dict, "variables", wp->w_vars); + tv_dict_add_dict(dict, S_LEN("variables"), wp->w_vars); return dict; } @@ -10970,7 +10184,7 @@ static void f_getwininfo(typval_T *argvars, typval_T *rettv, FunPtr fptr) { win_T *wparg = NULL; - rettv_list_alloc(rettv); + tv_list_alloc_ret(rettv); if (argvars[0].v_type != VAR_UNKNOWN) { wparg = win_id2wp(argvars); @@ -10990,9 +10204,9 @@ static void f_getwininfo(typval_T *argvars, typval_T *rettv, FunPtr fptr) continue; } winnr++; - dict_T *d = get_win_info(wp, tabnr, winnr); + dict_T *const d = get_win_info(wp, tabnr, winnr); if (d != NULL) { - list_append_dict(rettv->vval.v_list, d); + tv_list_append_dict(rettv->vval.v_list, d); } if (wparg != NULL) { // found information about a specific window @@ -11027,7 +10241,7 @@ find_win_by_nr ( tabpage_T *tp /* NULL for current tab page */ ) { - int nr = get_tv_number_chk(vp, NULL); + int nr = (int)tv_get_number_chk(vp, NULL); if (nr < 0) { return NULL; @@ -11062,7 +10276,7 @@ static win_T *find_tabwin(typval_T *wvp, typval_T *tvp) if (wvp->v_type != VAR_UNKNOWN) { if (tvp->v_type != VAR_UNKNOWN) { - long n = get_tv_number(tvp); + long n = tv_get_number(tvp); if (n >= 0) { tp = find_tabpage(n); } @@ -11097,23 +10311,23 @@ getwinvar ( ) { win_T *win, *oldcurwin; - char_u *varname; dictitem_T *v; tabpage_T *tp = NULL; tabpage_T *oldtabpage = NULL; bool done = false; - if (off == 1) - tp = find_tabpage((int)get_tv_number_chk(&argvars[0], NULL)); - else + if (off == 1) { + tp = find_tabpage((int)tv_get_number_chk(&argvars[0], NULL)); + } else { tp = curtab; + } win = find_win_by_nr(&argvars[off], tp); - varname = get_tv_string_chk(&argvars[off + 1]); - ++emsg_off; + const char *varname = tv_get_string_chk(&argvars[off + 1]); rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; + emsg_off++; if (win != NULL && varname != NULL) { // Set curwin to be our win, temporarily. Also set the tabpage, // otherwise the window is not valid. Only do this when needed, @@ -11139,9 +10353,10 @@ getwinvar ( } else { // Look up the variable. // Let getwinvar({nr}, "") return the "w:" dictionary. - v = find_var_in_ht(&win->w_vars->dv_hashtab, 'w', varname, FALSE); + v = find_var_in_ht(&win->w_vars->dv_hashtab, 'w', varname, + strlen(varname), false); if (v != NULL) { - copy_tv(&v->di_tv, rettv); + tv_copy(&v->di_tv, rettv); done = true; } } @@ -11152,12 +10367,12 @@ getwinvar ( restore_win(oldcurwin, oldtabpage, true); } } + emsg_off--; - if (!done && argvars[off + 2].v_type != VAR_UNKNOWN) - /* use the default return value */ - copy_tv(&argvars[off + 2], rettv); - - --emsg_off; + if (!done && argvars[off + 2].v_type != VAR_UNKNOWN) { + // use the default return value + tv_copy(&argvars[off + 2], rettv); + } } /* @@ -11167,21 +10382,22 @@ static void f_glob(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int options = WILD_SILENT|WILD_USE_NL; expand_T xpc; - int error = FALSE; + bool error = false; /* When the optional second argument is non-zero, don't remove matches * for 'wildignore' and don't put matches for 'suffixes' at the end. */ rettv->v_type = VAR_STRING; if (argvars[1].v_type != VAR_UNKNOWN) { - if (get_tv_number_chk(&argvars[1], &error)) + if (tv_get_number_chk(&argvars[1], &error)) { options |= WILD_KEEP_ALL; + } if (argvars[2].v_type != VAR_UNKNOWN) { - if (get_tv_number_chk(&argvars[2], &error)) { + if (tv_get_number_chk(&argvars[2], &error)) { rettv->v_type = VAR_LIST; rettv->vval.v_list = NULL; } if (argvars[3].v_type != VAR_UNKNOWN - && get_tv_number_chk(&argvars[3], &error)) { + && tv_get_number_chk(&argvars[3], &error)) { options |= WILD_ALLLINKS; } } @@ -11191,14 +10407,16 @@ static void f_glob(typval_T *argvars, typval_T *rettv, FunPtr fptr) xpc.xp_context = EXPAND_FILES; if (p_wic) options += WILD_ICASE; - if (rettv->v_type == VAR_STRING) - rettv->vval.v_string = ExpandOne(&xpc, get_tv_string(&argvars[0]), - NULL, options, WILD_ALL); - else { - rettv_list_alloc(rettv); - ExpandOne(&xpc, get_tv_string(&argvars[0]), NULL, options, WILD_ALL_KEEP); + if (rettv->v_type == VAR_STRING) { + rettv->vval.v_string = ExpandOne( + &xpc, (char_u *)tv_get_string(&argvars[0]), NULL, options, WILD_ALL); + } else { + tv_list_alloc_ret(rettv); + ExpandOne(&xpc, (char_u *)tv_get_string(&argvars[0]), NULL, options, + WILD_ALL_KEEP); for (int i = 0; i < xpc.xp_numfiles; i++) { - list_append_string(rettv->vval.v_list, xpc.xp_files[i], -1); + tv_list_append_string(rettv->vval.v_list, (const char *)xpc.xp_files[i], + -1); } ExpandCleanup(&xpc); } @@ -11210,7 +10428,7 @@ static void f_glob(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_globpath(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int flags = 0; // Flags for globpath. - int error = false; + bool error = false; // Return a string, or a list if the optional third argument is non-zero. rettv->v_type = VAR_STRING; @@ -11218,36 +10436,36 @@ static void f_globpath(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (argvars[2].v_type != VAR_UNKNOWN) { // When the optional second argument is non-zero, don't remove matches // for 'wildignore' and don't put matches for 'suffixes' at the end. - if (get_tv_number_chk(&argvars[2], &error)) { + if (tv_get_number_chk(&argvars[2], &error)) { flags |= WILD_KEEP_ALL; } if (argvars[3].v_type != VAR_UNKNOWN) { - if (get_tv_number_chk(&argvars[3], &error)) { + if (tv_get_number_chk(&argvars[3], &error)) { rettv->v_type = VAR_LIST; rettv->vval.v_list = NULL; } if (argvars[4].v_type != VAR_UNKNOWN - && get_tv_number_chk(&argvars[4], &error)) { + && tv_get_number_chk(&argvars[4], &error)) { flags |= WILD_ALLLINKS; } } } - char_u buf1[NUMBUFLEN]; - char_u *file = get_tv_string_buf_chk(&argvars[1], buf1); + char buf1[NUMBUFLEN]; + const char *const file = tv_get_string_buf_chk(&argvars[1], buf1); if (file != NULL && !error) { garray_T ga; ga_init(&ga, (int)sizeof(char_u *), 10); - globpath(get_tv_string(&argvars[0]), file, &ga, flags); + globpath((char_u *)tv_get_string(&argvars[0]), (char_u *)file, &ga, flags); if (rettv->v_type == VAR_STRING) { rettv->vval.v_string = ga_concat_strings_sep(&ga, "\n"); } else { - rettv_list_alloc(rettv); + tv_list_alloc_ret(rettv); for (int i = 0; i < ga.ga_len; i++) { - list_append_string(rettv->vval.v_list, - ((char_u **)(ga.ga_data))[i], -1); + tv_list_append_string(rettv->vval.v_list, + ((const char **)(ga.ga_data))[i], -1); } } @@ -11260,18 +10478,19 @@ static void f_globpath(typval_T *argvars, typval_T *rettv, FunPtr fptr) // "glob2regpat()" function static void f_glob2regpat(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *pat = get_tv_string_chk(&argvars[0]); // NULL on type error + const char *const pat = tv_get_string_chk(&argvars[0]); // NULL on type error rettv->v_type = VAR_STRING; - rettv->vval.v_string = (pat == NULL) - ? NULL - : file_pat_to_reg_pat(pat, NULL, NULL, false); + rettv->vval.v_string = ((pat == NULL) + ? NULL + : file_pat_to_reg_pat((char_u *)pat, NULL, NULL, + false)); } /// "has()" function static void f_has(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - static char *(has_list[]) = { + static const char *const has_list[] = { #ifdef UNIX "unix", #endif @@ -11322,6 +10541,7 @@ static void f_has(typval_T *argvars, typval_T *rettv, FunPtr fptr) "insert_expand", "jumplist", "keymap", + "lambda", "langmap", "libcall", "linebreak", @@ -11338,6 +10558,7 @@ static void f_has(typval_T *argvars, typval_T *rettv, FunPtr fptr) "mouse", "multi_byte", "multi_lang", + "num64", "packages", "path_extra", "persistent_undo", @@ -11381,13 +10602,11 @@ static void f_has(typval_T *argvars, typval_T *rettv, FunPtr fptr) "winaltkeys", "writebackup", "nvim", - NULL }; bool n = false; - char *name = (char *)get_tv_string(&argvars[0]); - - for (int i = 0; has_list[i] != NULL; i++) { + const char *const name = tv_get_string(&argvars[0]); + for (size_t i = 0; i < ARRAY_SIZE(has_list); i++) { if (STRICMP(name, has_list[i]) == 0) { n = true; break; @@ -11426,6 +10645,10 @@ static void f_has(typval_T *argvars, typval_T *rettv, FunPtr fptr) #endif } else if (STRICMP(name, "syntax_items") == 0) { n = syntax_present(curwin); +#ifdef UNIX + } else if (STRICMP(name, "unnamedplus") == 0) { + n = eval_has_provider("clipboard"); +#endif } } @@ -11448,8 +10671,9 @@ static void f_has_key(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (argvars[0].vval.v_dict == NULL) return; - rettv->vval.v_number = dict_find(argvars[0].vval.v_dict, - get_tv_string(&argvars[1]), -1) != NULL; + rettv->vval.v_number = tv_dict_find(argvars[0].vval.v_dict, + tv_get_string(&argvars[1]), + -1) != NULL; } /// `haslocaldir([{win}[, {tab}]])` function @@ -11541,7 +10765,7 @@ static void f_haslocaldir(typval_T *argvars, typval_T *rettv, FunPtr fptr) break; case kCdScopeTab: assert(tp); - rettv->vval.v_number = tp->localdir ? 1 : 0; + rettv->vval.v_number = tp->tp_localdir ? 1 : 0; break; case kCdScopeGlobal: // The global scope never has a local directory @@ -11558,24 +10782,24 @@ static void f_haslocaldir(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_hasmapto(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *name; - char_u *mode; - char_u buf[NUMBUFLEN]; - int abbr = FALSE; - - name = get_tv_string(&argvars[0]); - if (argvars[1].v_type == VAR_UNKNOWN) - mode = (char_u *)"nvo"; - else { - mode = get_tv_string_buf(&argvars[1], buf); - if (argvars[2].v_type != VAR_UNKNOWN) - abbr = get_tv_number(&argvars[2]); + const char *mode; + const char *const name = tv_get_string(&argvars[0]); + bool abbr = false; + char buf[NUMBUFLEN]; + if (argvars[1].v_type == VAR_UNKNOWN) { + mode = "nvo"; + } else { + mode = tv_get_string_buf(&argvars[1], buf); + if (argvars[2].v_type != VAR_UNKNOWN) { + abbr = tv_get_number(&argvars[2]); + } } - if (map_to_exists(name, mode, abbr)) - rettv->vval.v_number = TRUE; - else - rettv->vval.v_number = FALSE; + if (map_to_exists(name, mode, abbr)) { + rettv->vval.v_number = true; + } else { + rettv->vval.v_number = false; + } } /* @@ -11584,20 +10808,19 @@ static void f_hasmapto(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_histadd(typval_T *argvars, typval_T *rettv, FunPtr fptr) { HistoryType histype; - char_u *str; - char_u buf[NUMBUFLEN]; rettv->vval.v_number = false; if (check_restricted() || check_secure()) { return; } - str = get_tv_string_chk(&argvars[0]); // NULL on type error - histype = str != NULL ? get_histtype(str, STRLEN(str), false) : HIST_INVALID; + const char *str = tv_get_string_chk(&argvars[0]); // NULL on type error + histype = str != NULL ? get_histtype(str, strlen(str), false) : HIST_INVALID; if (histype != HIST_INVALID) { - str = get_tv_string_buf(&argvars[1], buf); + char buf[NUMBUFLEN]; + str = tv_get_string_buf(&argvars[1], buf); if (*str != NUL) { init_history(); - add_to_history(histype, str, false, NUL); + add_to_history(histype, (char_u *)str, false, NUL); rettv->vval.v_number = true; return; } @@ -11610,23 +10833,21 @@ static void f_histadd(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_histdel(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int n; - char_u buf[NUMBUFLEN]; - char_u *str; - - str = get_tv_string_chk(&argvars[0]); // NULL on type error + const char *const str = tv_get_string_chk(&argvars[0]); // NULL on type error if (str == NULL) { n = 0; } else if (argvars[1].v_type == VAR_UNKNOWN) { // only one argument: clear entire history - n = clr_history(get_histtype(str, STRLEN(str), false)); + n = clr_history(get_histtype(str, strlen(str), false)); } else if (argvars[1].v_type == VAR_NUMBER) { // index given: remove that entry - n = del_history_idx(get_histtype(str, STRLEN(str), false), - (int) get_tv_number(&argvars[1])); + n = del_history_idx(get_histtype(str, strlen(str), false), + (int)tv_get_number(&argvars[1])); } else { // string given: remove all matching entries - n = del_history_entry(get_histtype(str, STRLEN(str), false), - get_tv_string_buf(&argvars[1], buf)); + char buf[NUMBUFLEN]; + n = del_history_entry(get_histtype(str, strlen(str), false), + (char_u *)tv_get_string_buf(&argvars[1], buf)); } rettv->vval.v_number = n; } @@ -11638,17 +10859,16 @@ static void f_histget(typval_T *argvars, typval_T *rettv, FunPtr fptr) { HistoryType type; int idx; - char_u *str; - str = get_tv_string_chk(&argvars[0]); // NULL on type error + const char *const str = tv_get_string_chk(&argvars[0]); // NULL on type error if (str == NULL) { rettv->vval.v_string = NULL; } else { - type = get_histtype(str, STRLEN(str), false); + type = get_histtype(str, strlen(str), false); if (argvars[1].v_type == VAR_UNKNOWN) { idx = get_history_idx(type); } else { - idx = (int)get_tv_number_chk(&argvars[1], NULL); + idx = (int)tv_get_number_chk(&argvars[1], NULL); } // -1 on type error rettv->vval.v_string = vim_strsave(get_history_entry(type, idx)); @@ -11663,9 +10883,9 @@ static void f_histnr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int i; - char_u *history = get_tv_string_chk(&argvars[0]); + const char *const history = tv_get_string_chk(&argvars[0]); - i = history == NULL ? HIST_CMD - 1 : get_histtype(history, STRLEN(history), + i = history == NULL ? HIST_CMD - 1 : get_histtype(history, strlen(history), false); if (i != HIST_INVALID) { i = get_history_idx(i); @@ -11680,7 +10900,8 @@ static void f_histnr(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_hlID(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - rettv->vval.v_number = syn_name2id(get_tv_string(&argvars[0])); + rettv->vval.v_number = syn_name2id( + (const char_u *)tv_get_string(&argvars[0])); } /* @@ -11688,7 +10909,8 @@ static void f_hlID(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_hlexists(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - rettv->vval.v_number = highlight_exists(get_tv_string(&argvars[0])); + rettv->vval.v_number = highlight_exists( + (const char_u *)tv_get_string(&argvars[0])); } /* @@ -11708,25 +10930,27 @@ static void f_hostname(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_iconv(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u buf1[NUMBUFLEN]; - char_u buf2[NUMBUFLEN]; - char_u *from, *to, *str; vimconv_T vimconv; rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; - str = get_tv_string(&argvars[0]); - from = enc_canonize(enc_skip(get_tv_string_buf(&argvars[1], buf1))); - to = enc_canonize(enc_skip(get_tv_string_buf(&argvars[2], buf2))); + const char *const str = tv_get_string(&argvars[0]); + char buf1[NUMBUFLEN]; + char_u *const from = enc_canonize(enc_skip( + (char_u *)tv_get_string_buf(&argvars[1], buf1))); + char buf2[NUMBUFLEN]; + char_u *const to = enc_canonize(enc_skip( + (char_u *)tv_get_string_buf(&argvars[2], buf2))); vimconv.vc_type = CONV_NONE; convert_setup(&vimconv, from, to); - /* If the encodings are equal, no conversion needed. */ - if (vimconv.vc_type == CONV_NONE) - rettv->vval.v_string = vim_strsave(str); - else - rettv->vval.v_string = string_convert(&vimconv, str, NULL); + // If the encodings are equal, no conversion needed. + if (vimconv.vc_type == CONV_NONE) { + rettv->vval.v_string = (char_u *)xstrdup(str); + } else { + rettv->vval.v_string = string_convert(&vimconv, (char_u *)str, NULL); + } convert_setup(&vimconv, NULL, NULL); xfree(from); @@ -11738,13 +10962,12 @@ static void f_iconv(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_indent(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - linenr_T lnum; - - lnum = get_tv_lnum(argvars); - if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count) + const linenr_T lnum = tv_get_lnum(argvars); + if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count) { rettv->vval.v_number = get_indent_lnum(lnum); - else + } else { rettv->vval.v_number = -1; + } } /* @@ -11766,16 +10989,18 @@ static void f_index(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (l != NULL) { item = l->lv_first; if (argvars[2].v_type != VAR_UNKNOWN) { - int error = FALSE; + bool error = false; - /* Start at specified item. Use the cached index that list_find() - * sets, so that a negative number also works. */ - item = list_find(l, get_tv_number_chk(&argvars[2], &error)); + // Start at specified item. Use the cached index that tv_list_find() + // sets, so that a negative number also works. + item = tv_list_find(l, tv_get_number_chk(&argvars[2], &error)); idx = l->lv_idx; - if (argvars[3].v_type != VAR_UNKNOWN) - ic = get_tv_number_chk(&argvars[3], &error); - if (error) + if (argvars[3].v_type != VAR_UNKNOWN) { + ic = tv_get_number_chk(&argvars[3], &error); + } + if (error) { item = NULL; + } } for (; item != NULL; item = item->li_next, ++idx) @@ -11795,85 +11020,131 @@ static int inputsecret_flag = 0; * prompt. The third argument to f_inputdialog() specifies the value to return * when the user cancels the prompt. */ -static void get_user_input(typval_T *argvars, typval_T *rettv, int inputdialog) +void get_user_input(const typval_T *const argvars, + typval_T *const rettv, const bool inputdialog) + FUNC_ATTR_NONNULL_ALL { - char_u *prompt = get_tv_string_chk(&argvars[0]); - char_u *p = NULL; - int c; - char_u buf[NUMBUFLEN]; - int cmd_silent_save = cmd_silent; - char_u *defstr = (char_u *)""; - int xp_type = EXPAND_NOTHING; - char_u *xp_arg = NULL; - rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; - cmd_silent = FALSE; /* Want to see the prompt. */ - if (prompt != NULL) { - /* Only the part of the message after the last NL is considered as - * prompt for the command line */ - p = vim_strrchr(prompt, '\n'); - if (p == NULL) - p = prompt; - else { - ++p; - c = *p; - *p = NUL; - msg_start(); - msg_clr_eos(); - msg_puts_attr(prompt, echo_attr); - msg_didout = FALSE; - msg_starthere(); - *p = c; + const char *prompt = ""; + const char *defstr = ""; + const char *cancelreturn = NULL; + const char *xp_name = NULL; + Callback input_callback = { .type = kCallbackNone }; + char prompt_buf[NUMBUFLEN]; + char defstr_buf[NUMBUFLEN]; + char cancelreturn_buf[NUMBUFLEN]; + char xp_name_buf[NUMBUFLEN]; + if (argvars[0].v_type == VAR_DICT) { + if (argvars[1].v_type != VAR_UNKNOWN) { + emsgf(_("E5050: {opts} must be the only argument")); + return; + } + dict_T *const dict = argvars[0].vval.v_dict; + prompt = tv_dict_get_string_buf_chk(dict, S_LEN("prompt"), prompt_buf, ""); + if (prompt == NULL) { + return; + } + defstr = tv_dict_get_string_buf_chk(dict, S_LEN("default"), defstr_buf, ""); + if (defstr == NULL) { + return; + } + char def[1] = { 0 }; + cancelreturn = tv_dict_get_string_buf_chk(dict, S_LEN("cancelreturn"), + cancelreturn_buf, def); + if (cancelreturn == NULL) { // error + return; + } + if (*cancelreturn == NUL) { + cancelreturn = NULL; + } + xp_name = tv_dict_get_string_buf_chk(dict, S_LEN("completion"), + xp_name_buf, def); + if (xp_name == NULL) { // error + return; + } + if (xp_name == def) { // default to NULL + xp_name = NULL; + } + if (!tv_dict_get_callback(dict, S_LEN("highlight"), &input_callback)) { + return; + } + } else { + prompt = tv_get_string_buf_chk(&argvars[0], prompt_buf); + if (prompt == NULL) { + return; } - cmdline_row = msg_row; - if (argvars[1].v_type != VAR_UNKNOWN) { - defstr = get_tv_string_buf_chk(&argvars[1], buf); - if (defstr != NULL) - stuffReadbuffSpec(defstr); - - if (!inputdialog && argvars[2].v_type != VAR_UNKNOWN) { - char_u *xp_name; - int xp_namelen; - uint32_t argt; - - /* input() with a third argument: completion */ - rettv->vval.v_string = NULL; - - xp_name = get_tv_string_buf_chk(&argvars[2], buf); - if (xp_name == NULL) - return; - - xp_namelen = (int)STRLEN(xp_name); - - if (parse_compl_arg(xp_name, xp_namelen, &xp_type, &argt, - &xp_arg) == FAIL) + defstr = tv_get_string_buf_chk(&argvars[1], defstr_buf); + if (defstr == NULL) { + return; + } + if (argvars[2].v_type != VAR_UNKNOWN) { + const char *const arg2 = tv_get_string_buf_chk(&argvars[2], + cancelreturn_buf); + if (arg2 == NULL) { return; + } + if (inputdialog) { + cancelreturn = arg2; + } else { + xp_name = arg2; + } } } + } - if (defstr != NULL) { - int save_ex_normal_busy = ex_normal_busy; - ex_normal_busy = 0; - rettv->vval.v_string = - getcmdline_prompt(inputsecret_flag ? NUL : '@', p, echo_attr, - xp_type, xp_arg); - ex_normal_busy = save_ex_normal_busy; + int xp_type = EXPAND_NOTHING; + char *xp_arg = NULL; + if (xp_name != NULL) { + // input() with a third argument: completion + const int xp_namelen = (int)strlen(xp_name); + + uint32_t argt; + if (parse_compl_arg((char_u *)xp_name, xp_namelen, &xp_type, + &argt, (char_u **)&xp_arg) == FAIL) { + return; } - if (inputdialog && rettv->vval.v_string == NULL - && argvars[1].v_type != VAR_UNKNOWN - && argvars[2].v_type != VAR_UNKNOWN) - rettv->vval.v_string = vim_strsave(get_tv_string_buf( - &argvars[2], buf)); + } - xfree(xp_arg); + int cmd_silent_save = cmd_silent; - /* since the user typed this, no need to wait for return */ - need_wait_return = FALSE; - msg_didout = FALSE; + cmd_silent = false; // Want to see the prompt. + // Only the part of the message after the last NL is considered as + // prompt for the command line. + const char *p = strrchr(prompt, '\n'); + if (p == NULL) { + p = prompt; + } else { + p++; + msg_start(); + msg_clr_eos(); + msg_puts_attr_len(prompt, p - prompt, echo_attr); + msg_didout = false; + msg_starthere(); + } + cmdline_row = msg_row; + + stuffReadbuffSpec(defstr); + + const int save_ex_normal_busy = ex_normal_busy; + ex_normal_busy = 0; + rettv->vval.v_string = + (char_u *)getcmdline_prompt(inputsecret_flag ? NUL : '@', p, echo_attr, + xp_type, xp_arg, input_callback); + ex_normal_busy = save_ex_normal_busy; + callback_free(&input_callback); + + if (rettv->vval.v_string == NULL && cancelreturn != NULL) { + rettv->vval.v_string = (char_u *)xstrdup(cancelreturn); } + + xfree(xp_arg); + + // Since the user typed this, no need to wait for return. + need_wait_return = false; + msg_didout = false; cmd_silent = cmd_silent_save; } @@ -11915,7 +11186,7 @@ static void f_inputlist(typval_T *argvars, typval_T *rettv, FunPtr fptr) msg_clr_eos(); for (li = argvars[0].vval.v_list->lv_first; li != NULL; li = li->li_next) { - msg_puts(get_tv_string(&li->li_tv)); + msg_puts(tv_get_string(&li->li_tv)); msg_putchar('\n'); } @@ -11973,36 +11244,34 @@ static void f_inputsecret(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_insert(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - long before = 0; - listitem_T *item; - list_T *l; - int error = FALSE; + list_T *l; + bool error = false; if (argvars[0].v_type != VAR_LIST) { EMSG2(_(e_listarg), "insert()"); } else if ((l = argvars[0].vval.v_list) != NULL - && !tv_check_lock(l->lv_lock, - (char_u *)N_("insert() argument"), true)) { + && !tv_check_lock(l->lv_lock, N_("insert() argument"), + TV_TRANSLATE)) { + long before = 0; if (argvars[2].v_type != VAR_UNKNOWN) { - before = get_tv_number_chk(&argvars[2], &error); + before = tv_get_number_chk(&argvars[2], &error); } if (error) { // type error; errmsg already given return; } - if (before == l->lv_len) - item = NULL; - else { - item = list_find(l, before); + listitem_T *item = NULL; + if (before != l->lv_len) { + item = tv_list_find(l, before); if (item == NULL) { EMSGN(_(e_listidx), before); l = NULL; } } if (l != NULL) { - list_insert_tv(l, &argvars[1], item); - copy_tv(&argvars[0], rettv); + tv_list_insert_tv(l, &argvars[1], item); + tv_copy(&argvars[0], rettv); } } } @@ -12012,7 +11281,7 @@ static void f_insert(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_invert(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - rettv->vval.v_number = ~get_tv_number_chk(&argvars[0], NULL); + rettv->vval.v_number = ~tv_get_number_chk(&argvars[0], NULL); } /* @@ -12020,7 +11289,7 @@ static void f_invert(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_isdirectory(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - rettv->vval.v_number = os_isdir(get_tv_string(&argvars[0])); + rettv->vval.v_number = os_isdir((const char_u *)tv_get_string(&argvars[0])); } /* @@ -12029,41 +11298,39 @@ static void f_isdirectory(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_islocked(typval_T *argvars, typval_T *rettv, FunPtr fptr) { lval_T lv; - char_u *end; dictitem_T *di; rettv->vval.v_number = -1; - end = get_lval(get_tv_string(&argvars[0]), NULL, &lv, FALSE, FALSE, - GLV_NO_AUTOLOAD, FNE_CHECK_START); + const char_u *const end = get_lval((char_u *)tv_get_string(&argvars[0]), + NULL, + &lv, false, false, + GLV_NO_AUTOLOAD|GLV_READ_ONLY, + FNE_CHECK_START); if (end != NULL && lv.ll_name != NULL) { - if (*end != NUL) + if (*end != NUL) { EMSG(_(e_trailing)); - else { + } else { if (lv.ll_tv == NULL) { - if (check_changedtick(lv.ll_name)) - rettv->vval.v_number = 1; /* always locked */ - else { - di = find_var(lv.ll_name, NULL, TRUE); - if (di != NULL) { - /* Consider a variable locked when: - * 1. the variable itself is locked - * 2. the value of the variable is locked. - * 3. the List or Dict value is locked. - */ - rettv->vval.v_number = ((di->di_flags & DI_FLAGS_LOCK) - || tv_islocked(&di->di_tv)); - } + di = find_var((const char *)lv.ll_name, lv.ll_name_len, NULL, true); + if (di != NULL) { + // Consider a variable locked when: + // 1. the variable itself is locked + // 2. the value of the variable is locked. + // 3. the List or Dict value is locked. + rettv->vval.v_number = ((di->di_flags & DI_FLAGS_LOCK) + || tv_islocked(&di->di_tv)); } - } else if (lv.ll_range) + } else if (lv.ll_range) { EMSG(_("E786: Range not allowed")); - else if (lv.ll_newkey != NULL) + } else if (lv.ll_newkey != NULL) { EMSG2(_(e_dictkey), lv.ll_newkey); - else if (lv.ll_list != NULL) - /* List item. */ + } else if (lv.ll_list != NULL) { + // List item. rettv->vval.v_number = tv_islocked(&lv.ll_li->li_tv); - else - /* Dictionary item. */ + } else { + // Dictionary item. rettv->vval.v_number = tv_islocked(&lv.ll_di->di_tv); + } } } @@ -12071,68 +11338,71 @@ static void f_islocked(typval_T *argvars, typval_T *rettv, FunPtr fptr) } -/* - * Turn a dict into a list: - * "what" == 0: list of keys - * "what" == 1: list of values - * "what" == 2: list of items - */ -static void dict_list(typval_T *argvars, typval_T *rettv, int what) -{ - list_T *l2; - dictitem_T *di; - hashitem_T *hi; - listitem_T *li; - listitem_T *li2; - dict_T *d; - int todo; - - if (argvars[0].v_type != VAR_DICT) { - EMSG(_(e_dictreq)); +/// Turn a dictionary into a list +/// +/// @param[in] tv Dictionary to convert. Is checked for actually being +/// a dictionary, will give an error if not. +/// @param[out] rettv Location where result will be saved. +/// @param[in] what What to save in rettv. +static void dict_list(typval_T *const tv, typval_T *const rettv, + const DictListType what) +{ + if (tv->v_type != VAR_DICT) { + emsgf(_(e_dictreq)); return; } - if ((d = argvars[0].vval.v_dict) == NULL) + if (tv->vval.v_dict == NULL) { return; + } - rettv_list_alloc(rettv); - - todo = (int)d->dv_hashtab.ht_used; - for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi) { - if (!HASHITEM_EMPTY(hi)) { - --todo; - di = HI2DI(hi); + tv_list_alloc_ret(rettv); - li = listitem_alloc(); - list_append(rettv->vval.v_list, li); + TV_DICT_ITER(tv->vval.v_dict, di, { + listitem_T *const li = tv_list_item_alloc(); + tv_list_append(rettv->vval.v_list, li); - if (what == 0) { - /* keys() */ + switch (what) { + case kDictListKeys: { li->li_tv.v_type = VAR_STRING; - li->li_tv.v_lock = 0; + li->li_tv.v_lock = VAR_UNLOCKED; li->li_tv.vval.v_string = vim_strsave(di->di_key); - } else if (what == 1) { - /* values() */ - copy_tv(&di->di_tv, &li->li_tv); - } else { - /* items() */ - l2 = list_alloc(); + break; + } + case kDictListValues: { + tv_copy(&di->di_tv, &li->li_tv); + break; + } + case kDictListItems: { + // items() + list_T *const sub_l = tv_list_alloc(); li->li_tv.v_type = VAR_LIST; - li->li_tv.v_lock = 0; - li->li_tv.vval.v_list = l2; - ++l2->lv_refcount; - - li2 = listitem_alloc(); - list_append(l2, li2); - li2->li_tv.v_type = VAR_STRING; - li2->li_tv.v_lock = 0; - li2->li_tv.vval.v_string = vim_strsave(di->di_key); - - li2 = listitem_alloc(); - list_append(l2, li2); - copy_tv(&di->di_tv, &li2->li_tv); + li->li_tv.v_lock = VAR_UNLOCKED; + li->li_tv.vval.v_list = sub_l; + sub_l->lv_refcount++; + + listitem_T *sub_li = tv_list_item_alloc(); + tv_list_append(sub_l, sub_li); + sub_li->li_tv.v_type = VAR_STRING; + sub_li->li_tv.v_lock = VAR_UNLOCKED; + sub_li->li_tv.vval.v_string = vim_strsave(di->di_key); + + sub_li = tv_list_item_alloc(); + tv_list_append(sub_l, sub_li); + tv_copy(&di->di_tv, &sub_li->li_tv); + break; } } - } + }); +} + +/// "id()" function +static void f_id(typval_T *argvars, typval_T *rettv, FunPtr fptr) + FUNC_ATTR_NONNULL_ALL +{ + const int len = vim_vsnprintf(NULL, 0, "%p", dummy_ap, argvars); + rettv->v_type = VAR_STRING; + rettv->vval.v_string = xmalloc(len + 1); + vim_vsnprintf((char *)rettv->vval.v_string, len + 1, "%p", dummy_ap, argvars); } /* @@ -12263,8 +11533,8 @@ static void f_jobsend(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; } - ssize_t input_len; - char *input = (char *) save_tv_as_string(&argvars[1], &input_len, false); + ptrdiff_t input_len = 0; + char *input = save_tv_as_string(&argvars[1], &input_len, false); if (!input) { // Either the error has been handled by save_tv_as_string(), or there is no // input to send. @@ -12309,10 +11579,10 @@ static void f_jobresize(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_number = 1; } -static char **tv_to_argv(typval_T *cmd_tv, char **cmd, bool *executable) +static char **tv_to_argv(typval_T *cmd_tv, const char **cmd, bool *executable) { if (cmd_tv->v_type == VAR_STRING) { - char *cmd_str = (char *)get_tv_string(cmd_tv); + const char *cmd_str = tv_get_string(cmd_tv); if (cmd) { *cmd = cmd_str; } @@ -12333,8 +11603,8 @@ static char **tv_to_argv(typval_T *cmd_tv, char **cmd, bool *executable) assert(argl->lv_first); - const char_u *exe = get_tv_string_chk(&argl->lv_first->li_tv); - if (!exe || !os_can_exe(exe, NULL, true)) { + const char *exe = tv_get_string_chk(&argl->lv_first->li_tv); + if (!exe || !os_can_exe((const char_u *)exe, NULL, true)) { if (exe && executable) { *executable = false; } @@ -12342,16 +11612,16 @@ static char **tv_to_argv(typval_T *cmd_tv, char **cmd, bool *executable) } if (cmd) { - *cmd = (char *)exe; + *cmd = exe; } // Build the argument vector int i = 0; char **argv = xcalloc(argc + 1, sizeof(char *)); for (listitem_T *arg = argl->lv_first; arg != NULL; arg = arg->li_next) { - char *a = (char *)get_tv_string_chk(&arg->li_tv); + const char *a = tv_get_string_chk(&arg->li_tv); if (!a) { - // Did emsg in get_tv_string; just deallocate argv. + // Did emsg in tv_get_string_chk; just deallocate argv. shell_free_argv(argv); return NULL; } @@ -12387,23 +11657,26 @@ static void f_jobstart(typval_T *argvars, typval_T *rettv, FunPtr fptr) dict_T *job_opts = NULL; - bool detach = false, rpc = false, pty = false; - Callback on_stdout = CALLBACK_NONE, on_stderr = CALLBACK_NONE, - on_exit = CALLBACK_NONE; + bool detach = false; + bool rpc = false; + bool pty = false; + Callback on_stdout = CALLBACK_NONE; + Callback on_stderr = CALLBACK_NONE; + Callback on_exit = CALLBACK_NONE; char *cwd = NULL; if (argvars[1].v_type == VAR_DICT) { job_opts = argvars[1].vval.v_dict; - detach = get_dict_number(job_opts, "detach") != 0; - rpc = get_dict_number(job_opts, "rpc") != 0; - pty = get_dict_number(job_opts, "pty") != 0; + detach = tv_dict_get_number(job_opts, "detach") != 0; + rpc = tv_dict_get_number(job_opts, "rpc") != 0; + pty = tv_dict_get_number(job_opts, "pty") != 0; if (pty && rpc) { EMSG2(_(e_invarg2), "job cannot have both 'pty' and 'rpc' options set"); shell_free_argv(argv); return; } - char *new_cwd = (char *)get_dict_string(job_opts, "cwd", false); + char *new_cwd = tv_dict_get_string(job_opts, "cwd", false); if (new_cwd && strlen(new_cwd) > 0) { cwd = new_cwd; // The new cwd must be a directory. @@ -12425,15 +11698,15 @@ static void f_jobstart(typval_T *argvars, typval_T *rettv, FunPtr fptr) Process *proc = (Process *)&data->proc; if (pty) { - uint16_t width = get_dict_number(job_opts, "width"); + uint16_t width = (uint16_t)tv_dict_get_number(job_opts, "width"); if (width > 0) { data->proc.pty.width = width; } - uint16_t height = get_dict_number(job_opts, "height"); + uint16_t height = (uint16_t)tv_dict_get_number(job_opts, "height"); if (height > 0) { data->proc.pty.height = height; } - char *term = (char *)get_dict_string(job_opts, "TERM", true); + char *term = tv_dict_get_string(job_opts, "TERM", true); if (term) { data->proc.pty.term_name = term; } @@ -12493,7 +11766,7 @@ static void f_jobwait(typval_T *argvars, typval_T *rettv, FunPtr fptr) } list_T *args = argvars[0].vval.v_list; - list_T *rv = list_alloc(); + list_T *rv = tv_list_alloc(); ui_busy_start(); MultiQueue *waiting_jobs = multiqueue_new_parent(loop_on_put, &main_loop); @@ -12504,11 +11777,11 @@ static void f_jobwait(typval_T *argvars, typval_T *rettv, FunPtr fptr) TerminalJobData *data = NULL; if (arg->li_tv.v_type != VAR_NUMBER || !(data = find_job(arg->li_tv.vval.v_number))) { - list_append_number(rv, -3); + tv_list_append_number(rv, -3); } else { // append the list item and set the status pointer so we'll collect the // status code when the job exits - list_append_number(rv, -1); + tv_list_append_number(rv, -1); data->status_ptr = &rv->lv_last->li_tv.vval.v_number; // Process any pending events for the job because we'll temporarily // replace the parent queue @@ -12589,50 +11862,49 @@ static void f_jobwait(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_join(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - garray_T ga; - char_u *sep; - if (argvars[0].v_type != VAR_LIST) { EMSG(_(e_listreq)); return; } - if (argvars[0].vval.v_list == NULL) + if (argvars[0].vval.v_list == NULL) { return; - if (argvars[1].v_type == VAR_UNKNOWN) - sep = (char_u *)" "; - else - sep = get_tv_string_chk(&argvars[1]); + } + const char *const sep = (argvars[1].v_type == VAR_UNKNOWN + ? " " + : tv_get_string_chk(&argvars[1])); rettv->v_type = VAR_STRING; if (sep != NULL) { + garray_T ga; ga_init(&ga, (int)sizeof(char), 80); - list_join(&ga, argvars[0].vval.v_list, (char *) sep); + tv_list_join(&ga, argvars[0].vval.v_list, sep); ga_append(&ga, NUL); rettv->vval.v_string = (char_u *)ga.ga_data; - } else + } else { rettv->vval.v_string = NULL; + } } /// json_decode() function static void f_json_decode(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char numbuf[NUMBUFLEN]; - char *s = NULL; + const char *s = NULL; char *tofree = NULL; size_t len; if (argvars[0].v_type == VAR_LIST) { - if (!encode_vim_list_to_buf(argvars[0].vval.v_list, &len, &s)) { + if (!encode_vim_list_to_buf(argvars[0].vval.v_list, &len, &tofree)) { EMSG(_("E474: Failed to convert list to string")); return; } - tofree = s; + s = tofree; if (s == NULL) { assert(len == 0); s = ""; } } else { - s = (char *) get_tv_string_buf_chk(&argvars[0], (char_u *) numbuf); + s = tv_get_string_buf_chk(&argvars[0], numbuf); if (s) { len = strlen(s); } else { @@ -12685,24 +11957,28 @@ static void f_last_buffer_nr(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_len(typval_T *argvars, typval_T *rettv, FunPtr fptr) { switch (argvars[0].v_type) { - case VAR_STRING: - case VAR_NUMBER: - rettv->vval.v_number = (varnumber_T)STRLEN( - get_tv_string(&argvars[0])); - break; - case VAR_LIST: - rettv->vval.v_number = list_len(argvars[0].vval.v_list); - break; - case VAR_DICT: - rettv->vval.v_number = dict_len(argvars[0].vval.v_dict); - break; - case VAR_UNKNOWN: - case VAR_SPECIAL: - case VAR_FLOAT: - case VAR_FUNC: - case VAR_PARTIAL: - EMSG(_("E701: Invalid type for len()")); - break; + case VAR_STRING: + case VAR_NUMBER: { + rettv->vval.v_number = (varnumber_T)strlen( + tv_get_string(&argvars[0])); + break; + } + case VAR_LIST: { + rettv->vval.v_number = tv_list_len(argvars[0].vval.v_list); + break; + } + case VAR_DICT: { + rettv->vval.v_number = tv_dict_len(argvars[0].vval.v_dict); + break; + } + case VAR_UNKNOWN: + case VAR_SPECIAL: + case VAR_FLOAT: + case VAR_PARTIAL: + case VAR_FUNC: { + EMSG(_("E701: Invalid type for len()")); + break; + } } } @@ -12787,15 +12063,15 @@ static void f_line(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_line2byte(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - linenr_T lnum; - - lnum = get_tv_lnum(argvars); - if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count + 1) + const linenr_T lnum = tv_get_lnum(argvars); + if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count + 1) { rettv->vval.v_number = -1; - else + } else { rettv->vval.v_number = ml_find_line_or_offset(curbuf, lnum, NULL); - if (rettv->vval.v_number >= 0) - ++rettv->vval.v_number; + } + if (rettv->vval.v_number >= 0) { + rettv->vval.v_number++; + } } /* @@ -12803,17 +12079,15 @@ static void f_line2byte(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_lispindent(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - pos_T pos; - linenr_T lnum; - - pos = curwin->w_cursor; - lnum = get_tv_lnum(argvars); + const pos_T pos = curwin->w_cursor; + const linenr_T lnum = tv_get_lnum(argvars); if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count) { curwin->w_cursor.lnum = lnum; rettv->vval.v_number = get_lisp_indent(); curwin->w_cursor = pos; - } else + } else { rettv->vval.v_number = -1; + } } /* @@ -12827,71 +12101,117 @@ static void f_localtime(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void get_maparg(typval_T *argvars, typval_T *rettv, int exact) { - char_u *keys; - char_u *which; - char_u buf[NUMBUFLEN]; - char_u *keys_buf = NULL; - char_u *rhs; + char_u *keys_buf = NULL; + char_u *rhs; int mode; int abbr = FALSE; int get_dict = FALSE; mapblock_T *mp; int buffer_local; - /* return empty string for failure */ + // Return empty string for failure. rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; - keys = get_tv_string(&argvars[0]); - if (*keys == NUL) + char_u *keys = (char_u *)tv_get_string(&argvars[0]); + if (*keys == NUL) { return; + } + char buf[NUMBUFLEN]; + const char *which; if (argvars[1].v_type != VAR_UNKNOWN) { - which = get_tv_string_buf_chk(&argvars[1], buf); + which = tv_get_string_buf_chk(&argvars[1], buf); if (argvars[2].v_type != VAR_UNKNOWN) { - abbr = get_tv_number(&argvars[2]); - if (argvars[3].v_type != VAR_UNKNOWN) - get_dict = get_tv_number(&argvars[3]); + abbr = tv_get_number(&argvars[2]); + if (argvars[3].v_type != VAR_UNKNOWN) { + get_dict = tv_get_number(&argvars[3]); + } } - } else - which = (char_u *)""; - if (which == NULL) + } else { + which = ""; + } + if (which == NULL) { return; + } - mode = get_map_mode(&which, 0); + mode = get_map_mode((char_u **)&which, 0); - keys = replace_termcodes(keys, STRLEN(keys), &keys_buf, true, true, false, + keys = replace_termcodes(keys, STRLEN(keys), &keys_buf, true, true, true, CPO_TO_CPO_FLAGS); rhs = check_map(keys, mode, exact, false, abbr, &mp, &buffer_local); xfree(keys_buf); if (!get_dict) { - /* Return a string. */ - if (rhs != NULL) - rettv->vval.v_string = str2special_save(rhs, FALSE); + // Return a string. + if (rhs != NULL) { + rettv->vval.v_string = (char_u *)str2special_save( + (const char *)rhs, false, false); + } } else { - rettv_dict_alloc(rettv); + tv_dict_alloc_ret(rettv); if (rhs != NULL) { // Return a dictionary. - char_u *lhs = str2special_save(mp->m_keys, TRUE); - char_u *mapmode = map_mode_to_chars(mp->m_mode); - dict_T *dict = rettv->vval.v_dict; + mapblock_fill_dict(rettv->vval.v_dict, mp, buffer_local, true); + } + } +} + +/// luaeval() function implementation +static void f_luaeval(typval_T *argvars, typval_T *rettv, FunPtr fptr) + FUNC_ATTR_NONNULL_ALL +{ + const char *const str = (const char *)tv_get_string_chk(&argvars[0]); + if (str == NULL) { + return; + } - dict_add_nr_str(dict, "lhs", 0L, lhs); - dict_add_nr_str(dict, "rhs", 0L, mp->m_orig_str); - dict_add_nr_str(dict, "noremap", mp->m_noremap ? 1L : 0L, NULL); - dict_add_nr_str(dict, "expr", mp->m_expr ? 1L : 0L, NULL); - dict_add_nr_str(dict, "silent", mp->m_silent ? 1L : 0L, NULL); - dict_add_nr_str(dict, "sid", (long)mp->m_script_ID, NULL); - dict_add_nr_str(dict, "buffer", (long)buffer_local, NULL); - dict_add_nr_str(dict, "nowait", mp->m_nowait ? 1L : 0L, NULL); - dict_add_nr_str(dict, "mode", 0L, mapmode); + executor_eval_lua(cstr_as_string((char *)str), &argvars[1], rettv); +} - xfree(lhs); - xfree(mapmode); - } +/// Fill a dictionary with all applicable maparg() like dictionaries +/// +/// @param dict The dictionary to be filled +/// @param mp The maphash that contains the mapping information +/// @param buffer_value The "buffer" value +/// @param compatible True for compatible with old maparg() dict +void mapblock_fill_dict(dict_T *const dict, + const mapblock_T *const mp, + long buffer_value, + bool compatible) + FUNC_ATTR_NONNULL_ALL +{ + char *const lhs = str2special_save((const char *)mp->m_keys, + compatible, !compatible); + char *const mapmode = map_mode_to_chars(mp->m_mode); + varnumber_T noremap_value; + + if (compatible) { + // Keep old compatible behavior + // This is unable to determine whether a mapping is a <script> mapping + noremap_value = !!mp->m_noremap; + } else { + // Distinguish between <script> mapping + // If it's not a <script> mapping, check if it's a noremap + noremap_value = mp->m_noremap == REMAP_SCRIPT ? 2 : !!mp->m_noremap; } + + if (compatible) { + tv_dict_add_str(dict, S_LEN("rhs"), (const char *)mp->m_orig_str); + } else { + tv_dict_add_allocated_str(dict, S_LEN("rhs"), + str2special_save((const char *)mp->m_str, false, + true)); + } + tv_dict_add_allocated_str(dict, S_LEN("lhs"), lhs); + tv_dict_add_nr(dict, S_LEN("noremap"), noremap_value); + tv_dict_add_nr(dict, S_LEN("expr"), mp->m_expr ? 1 : 0); + tv_dict_add_nr(dict, S_LEN("silent"), mp->m_silent ? 1 : 0); + tv_dict_add_nr(dict, S_LEN("sid"), (varnumber_T)mp->m_script_ID); + tv_dict_add_nr(dict, S_LEN("buffer"), (varnumber_T)buffer_value); + tv_dict_add_nr(dict, S_LEN("nowait"), mp->m_nowait ? 1 : 0); + tv_dict_add_allocated_str(dict, S_LEN("mode"), mapmode); } /* @@ -12924,9 +12244,7 @@ static void find_some_match(typval_T *argvars, typval_T *rettv, int type) char_u *str = NULL; long len = 0; char_u *expr = NULL; - char_u *pat; regmatch_T regmatch; - char_u patbuf[NUMBUFLEN]; char_u *save_cpo; long start = 0; long nth = 1; @@ -12945,12 +12263,12 @@ static void find_some_match(typval_T *argvars, typval_T *rettv, int type) if (type == 3 || type == 4) { // type 3: return empty list when there are no matches. // type 4: return ["", -1, -1, -1] - rettv_list_alloc(rettv); + tv_list_alloc_ret(rettv); if (type == 4) { - list_append_string(rettv->vval.v_list, (char_u *)"", 0); - list_append_number(rettv->vval.v_list, (varnumber_T)-1); - list_append_number(rettv->vval.v_list, (varnumber_T)-1); - list_append_number(rettv->vval.v_list, (varnumber_T)-1); + tv_list_append_string(rettv->vval.v_list, "", 0); + tv_list_append_number(rettv->vval.v_list, -1); + tv_list_append_number(rettv->vval.v_list, -1); + tv_list_append_number(rettv->vval.v_list, -1); } } else if (type == 2) { rettv->v_type = VAR_STRING; @@ -12962,25 +12280,29 @@ static void find_some_match(typval_T *argvars, typval_T *rettv, int type) goto theend; li = l->lv_first; } else { - expr = str = get_tv_string(&argvars[0]); + expr = str = (char_u *)tv_get_string(&argvars[0]); len = (long)STRLEN(str); } - pat = get_tv_string_buf_chk(&argvars[1], patbuf); - if (pat == NULL) + char patbuf[NUMBUFLEN]; + const char *const pat = tv_get_string_buf_chk(&argvars[1], patbuf); + if (pat == NULL) { goto theend; + } if (argvars[2].v_type != VAR_UNKNOWN) { - int error = FALSE; + bool error = false; - start = get_tv_number_chk(&argvars[2], &error); - if (error) + start = tv_get_number_chk(&argvars[2], &error); + if (error) { goto theend; + } if (l != NULL) { - li = list_find(l, start); - if (li == NULL) + li = tv_list_find(l, start); + if (li == NULL) { goto theend; - idx = l->lv_idx; /* use the cached index */ + } + idx = l->lv_idx; // Use the cached index. } else { if (start < 0) start = 0; @@ -12997,13 +12319,15 @@ static void find_some_match(typval_T *argvars, typval_T *rettv, int type) } } - if (argvars[3].v_type != VAR_UNKNOWN) - nth = get_tv_number_chk(&argvars[3], &error); - if (error) + if (argvars[3].v_type != VAR_UNKNOWN) { + nth = tv_get_number_chk(&argvars[3], &error); + } + if (error) { goto theend; + } } - regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING); + regmatch.regprog = vim_regcomp((char_u *)pat, RE_MAGIC + RE_STRING); if (regmatch.regprog != NULL) { regmatch.rm_ic = p_ic; @@ -13062,29 +12386,32 @@ static void find_some_match(typval_T *argvars, typval_T *rettv, int type) /* return list with matched string and submatches */ for (i = 0; i < NSUBEXP; ++i) { if (regmatch.endp[i] == NULL) { - list_append_string(rettv->vval.v_list, (char_u *)"", 0); + tv_list_append_string(rettv->vval.v_list, NULL, 0); } else { - list_append_string(rettv->vval.v_list, - regmatch.startp[i], - (int)(regmatch.endp[i] - regmatch.startp[i])); + tv_list_append_string(rettv->vval.v_list, + (const char *)regmatch.startp[i], + (regmatch.endp[i] - regmatch.startp[i])); } } } else if (type == 2) { - /* return matched string */ - if (l != NULL) - copy_tv(&li->li_tv, rettv); - else - rettv->vval.v_string = vim_strnsave(regmatch.startp[0], - (int)(regmatch.endp[0] - regmatch.startp[0])); - } else if (l != NULL) + // Return matched string. + if (l != NULL) { + tv_copy(&li->li_tv, rettv); + } else { + rettv->vval.v_string = (char_u *)xmemdupz( + (const char *)regmatch.startp[0], + (size_t)(regmatch.endp[0] - regmatch.startp[0])); + } + } else if (l != NULL) { rettv->vval.v_number = idx; - else { - if (type != 0) + } else { + if (type != 0) { rettv->vval.v_number = (varnumber_T)(regmatch.startp[0] - str); - else + } else { rettv->vval.v_number = (varnumber_T)(regmatch.endp[0] - str); + } rettv->vval.v_number += (varnumber_T)(str - expr); } } @@ -13093,7 +12420,8 @@ static void find_some_match(typval_T *argvars, typval_T *rettv, int type) if (type == 4 && l == NULL) { // matchstrpos() without a list: drop the second item - listitem_remove(rettv->vval.v_list, rettv->vval.v_list->lv_first->li_next); + tv_list_item_remove(rettv->vval.v_list, + rettv->vval.v_list->lv_first->li_next); } theend: @@ -13114,40 +12442,42 @@ static void f_match(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_matchadd(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u buf[NUMBUFLEN]; - char_u *grp = get_tv_string_buf_chk(&argvars[0], buf); /* group */ - char_u *pat = get_tv_string_buf_chk(&argvars[1], buf); /* pattern */ - int prio = 10; /* default priority */ + char grpbuf[NUMBUFLEN]; + char patbuf[NUMBUFLEN]; + const char *const grp = tv_get_string_buf_chk(&argvars[0], grpbuf); + const char *const pat = tv_get_string_buf_chk(&argvars[1], patbuf); + int prio = 10; int id = -1; - int error = false; - char_u *conceal_char = NULL; + bool error = false; + const char *conceal_char = NULL; rettv->vval.v_number = -1; - if (grp == NULL || pat == NULL) + if (grp == NULL || pat == NULL) { return; + } if (argvars[2].v_type != VAR_UNKNOWN) { - prio = get_tv_number_chk(&argvars[2], &error); + prio = tv_get_number_chk(&argvars[2], &error); if (argvars[3].v_type != VAR_UNKNOWN) { - id = get_tv_number_chk(&argvars[3], &error); + id = tv_get_number_chk(&argvars[3], &error); if (argvars[4].v_type != VAR_UNKNOWN) { if (argvars[4].v_type != VAR_DICT) { EMSG(_(e_dictreq)); return; } - if (dict_find(argvars[4].vval.v_dict, - (char_u *)"conceal", -1) != NULL) { - conceal_char = get_dict_string(argvars[4].vval.v_dict, - "conceal", false); + dictitem_T *di; + if ((di = tv_dict_find(argvars[4].vval.v_dict, S_LEN("conceal"))) + != NULL) { + conceal_char = tv_get_string(&di->di_tv); } } } } - if (error == true) { + if (error) { return; } if (id >= 1 && id <= 3) { - EMSGN("E798: ID is reserved for \":match\": %" PRId64, id); + EMSGN(_("E798: ID is reserved for \":match\": %" PRId64), id); return; } @@ -13158,10 +12488,9 @@ static void f_matchadd(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_matchaddpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = -1; - - char_u buf[NUMBUFLEN]; - char_u *group; - group = get_tv_string_buf_chk(&argvars[0], buf); + + char buf[NUMBUFLEN]; + const char *const group = tv_get_string_buf_chk(&argvars[0], buf); if (group == NULL) { return; } @@ -13177,24 +12506,24 @@ static void f_matchaddpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; } - int error = false; + bool error = false; int prio = 10; int id = -1; - char_u *conceal_char = NULL; + const char *conceal_char = NULL; if (argvars[2].v_type != VAR_UNKNOWN) { - prio = get_tv_number_chk(&argvars[2], &error); + prio = tv_get_number_chk(&argvars[2], &error); if (argvars[3].v_type != VAR_UNKNOWN) { - id = get_tv_number_chk(&argvars[3], &error); + id = tv_get_number_chk(&argvars[3], &error); if (argvars[4].v_type != VAR_UNKNOWN) { if (argvars[4].v_type != VAR_DICT) { EMSG(_(e_dictreq)); return; } - if (dict_find(argvars[4].vval.v_dict, - (char_u *)"conceal", -1) != NULL) { - conceal_char = get_dict_string(argvars[4].vval.v_dict, - "conceal", false); + dictitem_T *di; + if ((di = tv_dict_find(argvars[4].vval.v_dict, S_LEN("conceal"))) + != NULL) { + conceal_char = tv_get_string(&di->di_tv); } } } @@ -13205,7 +12534,7 @@ static void f_matchaddpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) // id == 3 is ok because matchaddpos() is supposed to substitute :3match if (id == 1 || id == 2) { - EMSGN("E798: ID is reserved for \"match\": %" PRId64, id); + EMSGN(_("E798: ID is reserved for \"match\": %" PRId64), id); return; } @@ -13218,19 +12547,20 @@ static void f_matchaddpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_matcharg(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - rettv_list_alloc(rettv); + tv_list_alloc_ret(rettv); - int id = get_tv_number(&argvars[0]); + int id = tv_get_number(&argvars[0]); if (id >= 1 && id <= 3) { matchitem_T *m; if ((m = (matchitem_T *)get_match(curwin, id)) != NULL) { - list_append_string(rettv->vval.v_list, syn_id2name(m->hlg_id), -1); - list_append_string(rettv->vval.v_list, m->pattern, -1); + tv_list_append_string(rettv->vval.v_list, + (const char *)syn_id2name(m->hlg_id), -1); + tv_list_append_string(rettv->vval.v_list, (const char *)m->pattern, -1); } else { - list_append_string(rettv->vval.v_list, NULL, -1); - list_append_string(rettv->vval.v_list, NULL, -1); + tv_list_append_string(rettv->vval.v_list, NULL, 0); + tv_list_append_string(rettv->vval.v_list, NULL, 0); } } } @@ -13241,7 +12571,7 @@ static void f_matcharg(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_matchdelete(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = match_delete(curwin, - (int)get_tv_number(&argvars[0]), TRUE); + (int)tv_get_number(&argvars[0]), true); } /* @@ -13274,54 +12604,53 @@ static void f_matchstrpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) find_some_match(argvars, rettv, 4); } -static void max_min(typval_T *argvars, typval_T *rettv, int domax) +/// Get maximal/minimal number value in a list or dictionary +/// +/// @param[in] tv List or dictionary to work with. If it contains something +/// that is not an integer number (or cannot be coerced to +/// it) error is given. +/// @param[out] rettv Location where result will be saved. Only assigns +/// vval.v_number, type is not touched. Returns zero for +/// empty lists/dictionaries. +/// @param[in] domax Determines whether maximal or minimal value is desired. +static void max_min(const typval_T *const tv, typval_T *const rettv, + const bool domax) + FUNC_ATTR_NONNULL_ALL { - long n = 0; - long i; - int error = FALSE; + varnumber_T n = 0; + bool error = false; - if (argvars[0].v_type == VAR_LIST) { - list_T *l; - listitem_T *li; - - l = argvars[0].vval.v_list; - if (l != NULL) { - li = l->lv_first; - if (li != NULL) { - n = get_tv_number_chk(&li->li_tv, &error); - for (;; ) { - li = li->li_next; - if (li == NULL) - break; - i = get_tv_number_chk(&li->li_tv, &error); - if (domax ? i > n : i < n) - n = i; + if (tv->v_type == VAR_LIST) { + const list_T *const l = tv->vval.v_list; + if (tv_list_len(l) != 0) { + n = tv_get_number_chk(&l->lv_first->li_tv, &error); + for (const listitem_T *li = l->lv_first->li_next; li != NULL && !error; + li = li->li_next) { + const varnumber_T i = tv_get_number_chk(&li->li_tv, &error); + if (domax ? i > n : i < n) { + n = i; } } } - } else if (argvars[0].v_type == VAR_DICT) { - dict_T *d; - int first = TRUE; - hashitem_T *hi; - int todo; - - d = argvars[0].vval.v_dict; - if (d != NULL) { - todo = (int)d->dv_hashtab.ht_used; - for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi) { - if (!HASHITEM_EMPTY(hi)) { - --todo; - i = get_tv_number_chk(&HI2DI(hi)->di_tv, &error); - if (first) { - n = i; - first = FALSE; - } else if (domax ? i > n : i < n) - n = i; + } else if (tv->v_type == VAR_DICT) { + if (tv->vval.v_dict != NULL) { + bool first = true; + TV_DICT_ITER(tv->vval.v_dict, di, { + const varnumber_T i = tv_get_number_chk(&di->di_tv, &error); + if (error) { + break; } - } + if (first) { + n = i; + first = true; + } else if (domax ? i > n : i < n) { + n = i; + } + }); } - } else - EMSG(_(e_listdictarg)); + } else { + EMSG2(_(e_listdictarg), domax ? "max()" : "min()"); + } rettv->vval.v_number = error ? 0 : n; } @@ -13346,28 +12675,29 @@ static void f_min(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_mkdir(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *dir; - char_u buf[NUMBUFLEN]; - int prot = 0755; + int prot = 0755; // -V536 rettv->vval.v_number = FAIL; if (check_restricted() || check_secure()) return; - dir = get_tv_string_buf(&argvars[0], buf); - if (*dir == NUL) + char buf[NUMBUFLEN]; + const char *const dir = tv_get_string_buf(&argvars[0], buf); + if (*dir == NUL) { rettv->vval.v_number = FAIL; - else { - if (*path_tail(dir) == NUL) - /* remove trailing slashes */ - *path_tail_with_sep(dir) = NUL; + } else { + if (*path_tail((char_u *)dir) == NUL) { + // Remove trailing slashes. + *path_tail_with_sep((char_u *)dir) = NUL; + } if (argvars[1].v_type != VAR_UNKNOWN) { - if (argvars[2].v_type != VAR_UNKNOWN) - prot = get_tv_number_chk(&argvars[2], NULL); - if (prot != -1 && STRCMP(get_tv_string(&argvars[1]), "p") == 0) { + if (argvars[2].v_type != VAR_UNKNOWN) { + prot = tv_get_number_chk(&argvars[2], NULL); + } + if (prot != -1 && strcmp(tv_get_string(&argvars[1]), "p") == 0) { char *failed_dir; - int ret = os_mkdir_recurse((char *) dir, prot, &failed_dir); + int ret = os_mkdir_recurse(dir, prot, &failed_dir); if (ret != 0) { EMSG3(_(e_mkdir), failed_dir, os_strerror(ret)); xfree(failed_dir); @@ -13383,59 +12713,18 @@ static void f_mkdir(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -/* - * "mode()" function - */ +/// "mode()" function static void f_mode(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u buf[3]; - - buf[1] = NUL; - buf[2] = NUL; + char *mode = get_mode(); - if (VIsual_active) { - if (VIsual_select) - buf[0] = VIsual_mode + 's' - 'v'; - else - buf[0] = VIsual_mode; - } else if (State == HITRETURN || State == ASKMORE || State == SETWSIZE - || State == CONFIRM) { - buf[0] = 'r'; - if (State == ASKMORE) - buf[1] = 'm'; - else if (State == CONFIRM) - buf[1] = '?'; - } else if (State == EXTERNCMD) - buf[0] = '!'; - else if (State & INSERT) { - if (State & VREPLACE_FLAG) { - buf[0] = 'R'; - buf[1] = 'v'; - } else if (State & REPLACE_FLAG) - buf[0] = 'R'; - else - buf[0] = 'i'; - } else if (State & CMDLINE) { - buf[0] = 'c'; - if (exmode_active) - buf[1] = 'v'; - } else if (exmode_active) { - buf[0] = 'c'; - buf[1] = 'e'; - } else if (State & TERM_FOCUS) { - buf[0] = 't'; - } else { - buf[0] = 'n'; - if (finish_op) - buf[1] = 'o'; + // Clear out the minor mode when the argument is not a non-zero number or + // non-empty string. + if (!non_zero_arg(&argvars[0])) { + mode[1] = NUL; } - /* Clear out the minor mode when the argument is not a non-zero number or - * non-empty string. */ - if (!non_zero_arg(&argvars[0])) - buf[1] = NUL; - - rettv->vval.v_string = vim_strsave(buf); + rettv->vval.v_string = (char_u *)mode; rettv->v_type = VAR_STRING; } @@ -13447,7 +12736,7 @@ static void f_msgpackdump(typval_T *argvars, typval_T *rettv, FunPtr fptr) EMSG2(_(e_listarg), "msgpackdump()"); return; } - list_T *ret_list = rettv_list_alloc(rettv); + list_T *ret_list = tv_list_alloc_ret(rettv); const list_T *list = argvars[0].vval.v_list; if (list == NULL) { return; @@ -13475,7 +12764,7 @@ static void f_msgpackparse(typval_T *argvars, typval_T *rettv, FunPtr fptr) EMSG2(_(e_listarg), "msgpackparse()"); return; } - list_T *ret_list = rettv_list_alloc(rettv); + list_T *ret_list = tv_list_alloc_ret(rettv); const list_T *list = argvars[0].vval.v_list; if (list == NULL || list->lv_first == NULL) { return; @@ -13520,9 +12809,9 @@ static void f_msgpackparse(typval_T *argvars, typval_T *rettv, FunPtr fptr) goto f_msgpackparse_exit; } if (result == MSGPACK_UNPACK_SUCCESS) { - listitem_T *li = listitem_alloc(); + listitem_T *li = tv_list_item_alloc(); li->li_tv.v_type = VAR_UNKNOWN; - list_append(ret_list, li); + tv_list_append(ret_list, li); if (msgpack_to_vim(unpacked.data, &li->li_tv) == FAIL) { EMSG2(_(e_invarg2), "Failed to convert msgpack string"); goto f_msgpackparse_exit; @@ -13553,13 +12842,14 @@ static void f_nextnonblank(typval_T *argvars, typval_T *rettv, FunPtr fptr) { linenr_T lnum; - for (lnum = get_tv_lnum(argvars);; ++lnum) { + for (lnum = tv_get_lnum(argvars);; lnum++) { if (lnum < 0 || lnum > curbuf->b_ml.ml_line_count) { lnum = 0; break; } - if (*skipwhite(ml_get(lnum)) != NUL) + if (*skipwhite(ml_get(lnum)) != NUL) { break; + } } rettv->vval.v_number = lnum; } @@ -13569,23 +12859,32 @@ static void f_nextnonblank(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_nr2char(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u buf[NUMBUFLEN]; - - if (has_mbyte) { - int utf8 = 0; + if (argvars[1].v_type != VAR_UNKNOWN) { + if (!tv_check_num(&argvars[1])) { + return; + } + } - if (argvars[1].v_type != VAR_UNKNOWN) - utf8 = get_tv_number_chk(&argvars[1], NULL); - if (utf8) - buf[(*utf_char2bytes)((int)get_tv_number(&argvars[0]), buf)] = NUL; - else - buf[(*mb_char2bytes)((int)get_tv_number(&argvars[0]), buf)] = NUL; - } else { - buf[0] = (char_u)get_tv_number(&argvars[0]); - buf[1] = NUL; + bool error = false; + const varnumber_T num = tv_get_number_chk(&argvars[0], &error); + if (error) { + return; } + if (num < 0) { + emsgf(_("E5070: Character number must not be less than zero")); + return; + } + if (num > INT_MAX) { + emsgf(_("E5071: Character number must not be greater than INT_MAX (%i)"), + INT_MAX); + return; + } + + char buf[MB_MAXBYTES]; + const int len = utf_char2bytes((int)num, (char_u *)buf); + rettv->v_type = VAR_STRING; - rettv->vval.v_string = vim_strsave(buf); + rettv->vval.v_string = xmemdupz(buf, (size_t)len); } /* @@ -13593,8 +12892,8 @@ static void f_nr2char(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_or(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - rettv->vval.v_number = get_tv_number_chk(&argvars[0], NULL) - | get_tv_number_chk(&argvars[1], NULL); + rettv->vval.v_number = tv_get_number_chk(&argvars[0], NULL) + | tv_get_number_chk(&argvars[1], NULL); } /* @@ -13603,11 +12902,11 @@ static void f_or(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_pathshorten(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_STRING; - rettv->vval.v_string = get_tv_string_chk(&argvars[0]); - if (!rettv->vval.v_string) { + const char *const s = tv_get_string_chk(&argvars[0]); + if (!s) { return; } - rettv->vval.v_string = shorten_dir(vim_strsave(rettv->vval.v_string)); + rettv->vval.v_string = shorten_dir((char_u *)xstrdup(s)); } /* @@ -13615,14 +12914,15 @@ static void f_pathshorten(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_pow(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - float_T fx, fy; + float_T fx; + float_T fy; rettv->v_type = VAR_FLOAT; - if (get_float_arg(argvars, &fx) == OK - && get_float_arg(&argvars[1], &fy) == OK) + if (tv_get_float_chk(argvars, &fx) && tv_get_float_chk(&argvars[1], &fy)) { rettv->vval.v_float = pow(fx, fy); - else + } else { rettv->vval.v_float = 0.0; + } } /* @@ -13630,23 +12930,17 @@ static void f_pow(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_prevnonblank(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - linenr_T lnum; - - lnum = get_tv_lnum(argvars); - if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count) + linenr_T lnum = tv_get_lnum(argvars); + if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count) { lnum = 0; - else - while (lnum >= 1 && *skipwhite(ml_get(lnum)) == NUL) - --lnum; + } else { + while (lnum >= 1 && *skipwhite(ml_get(lnum)) == NUL) { + lnum--; + } + } rettv->vval.v_number = lnum; } -/* This dummy va_list is here because: - * - passing a NULL pointer doesn't work when va_list isn't a pointer - * - locally in the function results in a "used before set" warning - * - using va_start() to initialize it gives "function with fixed args" error */ -static va_list ap; - /* * "printf()" function */ @@ -13655,19 +12949,18 @@ static void f_printf(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; { - char_u buf[NUMBUFLEN]; int len; int saved_did_emsg = did_emsg; - char *fmt; - /* Get the required length, allocate the buffer and do it for real. */ - did_emsg = FALSE; - fmt = (char *)get_tv_string_buf(&argvars[0], buf); - len = vim_vsnprintf(NULL, 0, fmt, ap, argvars + 1); + // Get the required length, allocate the buffer and do it for real. + did_emsg = false; + char buf[NUMBUFLEN]; + const char *fmt = tv_get_string_buf(&argvars[0], buf); + len = vim_vsnprintf(NULL, 0, fmt, dummy_ap, argvars + 1); if (!did_emsg) { char *s = xmalloc(len + 1); rettv->vval.v_string = (char_u *)s; - (void)vim_vsnprintf(s, len + 1, fmt, ap, argvars + 1); + (void)vim_vsnprintf(s, len + 1, fmt, dummy_ap, argvars + 1); } did_emsg |= saved_did_emsg; } @@ -13703,32 +12996,34 @@ static void f_py3eval(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_range(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - long start; - long end; - long stride = 1; - long i; - int error = FALSE; + varnumber_T start; + varnumber_T end; + varnumber_T stride = 1; + varnumber_T i; + bool error = false; - start = get_tv_number_chk(&argvars[0], &error); + start = tv_get_number_chk(&argvars[0], &error); if (argvars[1].v_type == VAR_UNKNOWN) { end = start - 1; start = 0; } else { - end = get_tv_number_chk(&argvars[1], &error); - if (argvars[2].v_type != VAR_UNKNOWN) - stride = get_tv_number_chk(&argvars[2], &error); + end = tv_get_number_chk(&argvars[1], &error); + if (argvars[2].v_type != VAR_UNKNOWN) { + stride = tv_get_number_chk(&argvars[2], &error); + } } - if (error) - return; /* type error; errmsg already given */ - if (stride == 0) - EMSG(_("E726: Stride is zero")); - else if (stride > 0 ? end + 1 < start : end - 1 > start) - EMSG(_("E727: Start past end")); - else { - rettv_list_alloc(rettv); + if (error) { + return; // Type error; errmsg already given. + } + if (stride == 0) { + emsgf(_("E726: Stride is zero")); + } else if (stride > 0 ? end + 1 < start : end - 1 > start) { + emsgf(_("E727: Start past end")); + } else { + tv_list_alloc_ret(rettv); for (i = start; stride > 0 ? i <= end : i >= end; i += stride) { - list_append_number(rettv->vval.v_list, (varnumber_T)i); + tv_list_append_number(rettv->vval.v_list, (varnumber_T)i); } } } @@ -13738,8 +13033,7 @@ static void f_range(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_readfile(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - int binary = FALSE; - char_u *fname; + bool binary = false; FILE *fd; char_u buf[(IOSIZE/256)*256]; /* rounded to avoid odd + 1 */ int io_size = sizeof(buf); @@ -13753,19 +13047,21 @@ static void f_readfile(typval_T *argvars, typval_T *rettv, FunPtr fptr) char_u *start; /* start of current line */ if (argvars[1].v_type != VAR_UNKNOWN) { - if (STRCMP(get_tv_string(&argvars[1]), "b") == 0) - binary = TRUE; - if (argvars[2].v_type != VAR_UNKNOWN) - maxline = get_tv_number(&argvars[2]); + if (strcmp(tv_get_string(&argvars[1]), "b") == 0) { + binary = true; + } + if (argvars[2].v_type != VAR_UNKNOWN) { + maxline = tv_get_number(&argvars[2]); + } } - rettv_list_alloc(rettv); + tv_list_alloc_ret(rettv); - /* Always open the file in binary mode, library functions have a mind of - * their own about CR-LF conversion. */ - fname = get_tv_string(&argvars[0]); - if (*fname == NUL || (fd = mch_fopen((char *)fname, READBIN)) == NULL) { - EMSG2(_(e_notopen), *fname == NUL ? (char_u *)_("<empty>") : fname); + // Always open the file in binary mode, library functions have a mind of + // their own about CR-LF conversion. + const char *const fname = tv_get_string(&argvars[0]); + if (*fname == NUL || (fd = mch_fopen(fname, READBIN)) == NULL) { + EMSG2(_(e_notopen), *fname == NUL ? _("<empty>") : fname); return; } @@ -13808,11 +13104,11 @@ static void f_readfile(typval_T *argvars, typval_T *rettv, FunPtr fptr) prevlen = prevsize = 0; } - li = listitem_alloc(); + li = tv_list_item_alloc(); li->li_tv.v_type = VAR_STRING; li->li_tv.v_lock = 0; li->li_tv.vval.v_string = s; - list_append(rettv->vval.v_list, li); + tv_list_append(rettv->vval.v_list, li); start = p + 1; /* step over newline */ if ((++cnt >= maxline && maxline >= 0) || readlen <= 0) @@ -13842,8 +13138,9 @@ static void f_readfile(typval_T *argvars, typval_T *rettv, FunPtr fptr) /* have to shuffle buf to close gap */ int adjust_prevlen = 0; - if (dest < buf) { - adjust_prevlen = (int)(buf - dest); /* must be 1 or 2 */ + if (dest < buf) { // -V782 + adjust_prevlen = (int)(buf - dest); // -V782 + // adjust_prevlen must be 1 or 2. dest = buf; } if (readlen > p - buf + 1) @@ -13887,8 +13184,8 @@ static void f_readfile(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ if (maxline < 0) while (cnt > -maxline) { - listitem_remove(rettv->vval.v_list, rettv->vval.v_list->lv_first); - --cnt; + tv_list_item_remove(rettv->vval.v_list, rettv->vval.v_list->lv_first); + cnt--; } xfree(prev); @@ -13910,9 +13207,9 @@ static int list2proftime(typval_T *arg, proftime_T *tm) FUNC_ATTR_NONNULL_ALL return FAIL; } - int error = false; - varnumber_T n1 = list_find_nr(arg->vval.v_list, 0L, &error); - varnumber_T n2 = list_find_nr(arg->vval.v_list, 1L, &error); + bool error = false; + varnumber_T n1 = tv_list_find_nr(arg->vval.v_list, 0L, &error); + varnumber_T n2 = tv_list_find_nr(arg->vval.v_list, 1L, &error); if (error) { return FAIL; } @@ -13920,7 +13217,7 @@ static int list2proftime(typval_T *arg, proftime_T *tm) FUNC_ATTR_NONNULL_ALL // in f_reltime() we split up the 64-bit proftime_T into two 32-bit // values, now we combine them again. union { - struct { varnumber_T low, high; } split; + struct { int32_t low, high; } split; proftime_T prof; } u = { .split.high = n1, .split.low = n2 }; @@ -13961,7 +13258,7 @@ static void f_reltime(typval_T *argvars, typval_T *rettv, FunPtr fptr) // (varnumber_T is defined as int). For all our supported platforms, int's // are at least 32-bits wide. So we'll use two 32-bit values to store it. union { - struct { varnumber_T low, high; } split; + struct { int32_t low, high; } split; proftime_T prof; } u = { .prof = res }; @@ -13971,9 +13268,9 @@ static void f_reltime(typval_T *argvars, typval_T *rettv, FunPtr fptr) STATIC_ASSERT(sizeof(u.prof) == sizeof(u) && sizeof(u.split) == sizeof(u), "type punning will produce incorrect results on this platform"); - rettv_list_alloc(rettv); - list_append_number(rettv->vval.v_list, u.split.high); - list_append_number(rettv->vval.v_list, u.split.low); + tv_list_alloc_ret(rettv); + tv_list_append_number(rettv->vval.v_list, u.split.high); + tv_list_append_number(rettv->vval.v_list, u.split.low); } /// f_reltimestr - return a string that represents the value of {time} @@ -14003,28 +13300,27 @@ static void f_remove(typval_T *argvars, typval_T *rettv, FunPtr fptr) listitem_T *li; long idx; long end; - char_u *key; dict_T *d; dictitem_T *di; - char_u *arg_errmsg = (char_u *)N_("remove() argument"); + const char *const arg_errmsg = N_("remove() argument"); if (argvars[0].v_type == VAR_DICT) { if (argvars[2].v_type != VAR_UNKNOWN) { EMSG2(_(e_toomanyarg), "remove()"); } else if ((d = argvars[0].vval.v_dict) != NULL - && !tv_check_lock(d->dv_lock, arg_errmsg, true)) { - key = get_tv_string_chk(&argvars[1]); + && !tv_check_lock(d->dv_lock, arg_errmsg, TV_TRANSLATE)) { + const char *key = tv_get_string_chk(&argvars[1]); if (key != NULL) { - di = dict_find(d, key, -1); + di = tv_dict_find(d, key, -1); if (di == NULL) { EMSG2(_(e_dictkey), key); - } else if (!var_check_fixed(di->di_flags, arg_errmsg, true) - && !var_check_ro(di->di_flags, arg_errmsg, true)) { + } else if (!var_check_fixed(di->di_flags, arg_errmsg, TV_TRANSLATE) + && !var_check_ro(di->di_flags, arg_errmsg, TV_TRANSLATE)) { *rettv = di->di_tv; - init_tv(&di->di_tv); - dictitem_remove(d, di); - if (is_watched(d)) { - dictwatcher_notify(d, (char *)key, NULL, rettv); + di->di_tv = TV_INITIAL_VALUE; + tv_dict_item_remove(d, di); + if (tv_dict_is_watched(d)) { + tv_dict_watcher_notify(d, key, NULL, rettv); } } } @@ -14032,28 +13328,28 @@ static void f_remove(typval_T *argvars, typval_T *rettv, FunPtr fptr) } else if (argvars[0].v_type != VAR_LIST) { EMSG2(_(e_listdictarg), "remove()"); } else if ((l = argvars[0].vval.v_list) != NULL - && !tv_check_lock(l->lv_lock, arg_errmsg, true)) { - int error = (int)false; + && !tv_check_lock(l->lv_lock, arg_errmsg, TV_TRANSLATE)) { + bool error = false; - idx = get_tv_number_chk(&argvars[1], &error); - if (error) - ; /* type error: do nothing, errmsg already given */ - else if ((item = list_find(l, idx)) == NULL) + idx = tv_get_number_chk(&argvars[1], &error); + if (error) { + // Type error: do nothing, errmsg already given. + } else if ((item = tv_list_find(l, idx)) == NULL) { EMSGN(_(e_listidx), idx); - else { + } else { if (argvars[2].v_type == VAR_UNKNOWN) { // Remove one item, return its value. - vim_list_remove(l, item, item); + tv_list_remove_items(l, item, item); *rettv = item->li_tv; xfree(item); } else { - /* Remove range of items, return list with values. */ - end = get_tv_number_chk(&argvars[2], &error); - if (error) - ; /* type error: do nothing */ - else if ((item2 = list_find(l, end)) == NULL) + // Remove range of items, return list with values. + end = tv_get_number_chk(&argvars[2], &error); + if (error) { + // Type error: do nothing. + } else if ((item2 = tv_list_find(l, end)) == NULL) { EMSGN(_(e_listidx), end); - else { + } else { int cnt = 0; for (li = item; li != NULL; li = li->li_next) { @@ -14061,11 +13357,11 @@ static void f_remove(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (li == item2) break; } - if (li == NULL) /* didn't find "item2" after "item" */ - EMSG(_(e_invrange)); - else { - vim_list_remove(l, item, item2); - l = rettv_list_alloc(rettv); + if (li == NULL) { // Didn't find "item2" after "item". + emsgf(_(e_invrange)); + } else { + tv_list_remove_items(l, item, item2); + l = tv_list_alloc_ret(rettv); l->lv_first = item; l->lv_last = item2; item->li_prev = NULL; @@ -14083,13 +13379,14 @@ static void f_remove(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_rename(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u buf[NUMBUFLEN]; - - if (check_restricted() || check_secure()) + if (check_restricted() || check_secure()) { rettv->vval.v_number = -1; - else - rettv->vval.v_number = vim_rename(get_tv_string(&argvars[0]), - get_tv_string_buf(&argvars[1], buf)); + } else { + char buf[NUMBUFLEN]; + rettv->vval.v_number = vim_rename( + (const char_u *)tv_get_string(&argvars[0]), + (const char_u *)tv_get_string_buf(&argvars[1], buf)); + } } /* @@ -14097,32 +13394,37 @@ static void f_rename(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_repeat(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *p; - int n; - - n = get_tv_number(&argvars[1]); + varnumber_T n = tv_get_number(&argvars[1]); if (argvars[0].v_type == VAR_LIST) { - rettv_list_alloc(rettv); - if (argvars[0].vval.v_list != NULL) { - while (n-- > 0) { - list_extend(rettv->vval.v_list, argvars[0].vval.v_list, NULL); - } + tv_list_alloc_ret(rettv); + while (n-- > 0) { + tv_list_extend(rettv->vval.v_list, argvars[0].vval.v_list, NULL); } } else { - p = get_tv_string(&argvars[0]); rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; + if (n <= 0) { + return; + } - int slen = (int)STRLEN(p); - int len = slen * n; - if (len <= 0) + const char *const p = tv_get_string(&argvars[0]); + + const size_t slen = strlen(p); + if (slen == 0) { + return; + } + const size_t len = slen * n; + // Detect overflow. + if (len / n != slen) { return; + } - char_u *r = xmallocz(len); - for (int i = 0; i < n; i++) - memmove(r + i * slen, p, (size_t)slen); + char *const r = xmallocz(len); + for (varnumber_T i = 0; i < n; i++) { + memmove(r + i * slen, p, slen); + } - rettv->vval.v_string = r; + rettv->vval.v_string = (char_u *)r; } } @@ -14131,61 +13433,49 @@ static void f_repeat(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_resolve(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *p; -#ifdef HAVE_READLINK - char_u *buf = NULL; -#endif - - p = get_tv_string(&argvars[0]); + rettv->v_type = VAR_STRING; + const char *fname = tv_get_string(&argvars[0]); #ifdef WIN32 - { - char_u *v = NULL; - - v = os_resolve_shortcut(p); - if (v != NULL) { - rettv->vval.v_string = v; - } else { - rettv->vval.v_string = vim_strsave(p); - } - } + char *const v = os_resolve_shortcut(fname); + rettv->vval.v_string = (char_u *)(v == NULL ? xstrdup(fname) : v); #else # ifdef HAVE_READLINK { - char_u *cpy; - int len; - char_u *remain = NULL; - char_u *q; - int is_relative_to_current = FALSE; - int has_trailing_pathsep = FALSE; + bool is_relative_to_current = false; + bool has_trailing_pathsep = false; int limit = 100; - p = vim_strsave(p); + char *p = xstrdup(fname); if (p[0] == '.' && (vim_ispathsep(p[1]) - || (p[1] == '.' && (vim_ispathsep(p[2]))))) - is_relative_to_current = TRUE; + || (p[1] == '.' && (vim_ispathsep(p[2]))))) { + is_relative_to_current = true; + } - len = STRLEN(p); - if (len > 0 && after_pathsep((char *)p, (char *)p + len)) { - has_trailing_pathsep = TRUE; - p[len - 1] = NUL; /* the trailing slash breaks readlink() */ + ptrdiff_t len = (ptrdiff_t)strlen(p); + if (len > 0 && after_pathsep(p, p + len)) { + has_trailing_pathsep = true; + p[len - 1] = NUL; // The trailing slash breaks readlink(). } - q = path_next_component(p); + char *q = (char *)path_next_component(p); + char *remain = NULL; if (*q != NUL) { - /* Separate the first path component in "p", and keep the - * remainder (beginning with the path separator). */ - remain = vim_strsave(q - 1); + // Separate the first path component in "p", and keep the + // remainder (beginning with the path separator). + remain = xstrdup(q - 1); q[-1] = NUL; } - buf = xmallocz(MAXPATHL); + char *const buf = xmallocz(MAXPATHL); + char *cpy; for (;; ) { for (;; ) { - len = readlink((char *)p, (char *)buf, MAXPATHL); - if (len <= 0) + len = readlink(p, buf, MAXPATHL); + if (len <= 0) { break; + } buf[len] = NUL; if (limit-- == 0) { @@ -14193,66 +13483,72 @@ static void f_resolve(typval_T *argvars, typval_T *rettv, FunPtr fptr) xfree(remain); EMSG(_("E655: Too many symbolic links (cycle?)")); rettv->vval.v_string = NULL; - goto fail; + xfree(buf); + return; } - /* Ensure that the result will have a trailing path separator - * if the argument has one. */ - if (remain == NULL && has_trailing_pathsep) - add_pathsep((char *)buf); + // Ensure that the result will have a trailing path separator + // if the argument has one. */ + if (remain == NULL && has_trailing_pathsep) { + add_pathsep(buf); + } - /* Separate the first path component in the link value and - * concatenate the remainders. */ - q = path_next_component(vim_ispathsep(*buf) ? buf + 1 : buf); + // Separate the first path component in the link value and + // concatenate the remainders. */ + q = (char *)path_next_component(vim_ispathsep(*buf) ? buf + 1 : buf); if (*q != NUL) { cpy = remain; - remain = remain ? - concat_str(q - 1, remain) : (char_u *) xstrdup((char *)q - 1); + remain = (remain + ? (char *)concat_str((char_u *)q - 1, (char_u *)remain) + : xstrdup(q - 1)); xfree(cpy); q[-1] = NUL; } - q = path_tail(p); + q = (char *)path_tail((char_u *)p); if (q > p && *q == NUL) { - /* Ignore trailing path separator. */ + // Ignore trailing path separator. q[-1] = NUL; - q = path_tail(p); + q = (char *)path_tail((char_u *)p); } - if (q > p && !path_is_absolute_path(buf)) { - /* symlink is relative to directory of argument */ - cpy = xmalloc(STRLEN(p) + STRLEN(buf) + 1); - STRCPY(cpy, p); - STRCPY(path_tail(cpy), buf); - xfree(p); - p = cpy; + if (q > p && !path_is_absolute_path((const char_u *)buf)) { + // Symlink is relative to directory of argument. Replace the + // symlink with the resolved name in the same directory. + const size_t p_len = strlen(p); + const size_t buf_len = strlen(buf); + p = xrealloc(p, p_len + buf_len + 1); + memcpy(path_tail((char_u *)p), buf, buf_len + 1); } else { xfree(p); - p = vim_strsave(buf); + p = xstrdup(buf); } } - if (remain == NULL) + if (remain == NULL) { break; + } - /* Append the first path component of "remain" to "p". */ - q = path_next_component(remain + 1); + // Append the first path component of "remain" to "p". + q = (char *)path_next_component(remain + 1); len = q - remain - (*q != NUL); - cpy = vim_strnsave(p, STRLEN(p) + len); - STRNCAT(cpy, remain, len); + const size_t p_len = strlen(p); + cpy = xmallocz(p_len + len); + memcpy(cpy, p, p_len + 1); + xstrlcat(cpy + p_len, remain, len + 1); xfree(p); p = cpy; - /* Shorten "remain". */ - if (*q != NUL) + // Shorten "remain". + if (*q != NUL) { STRMOVE(remain, q - 1); - else { + } else { xfree(remain); remain = NULL; } } - /* If the result is a relative path name, make it explicitly relative to - * the current directory if and only if the argument had this form. */ + // If the result is a relative path name, make it explicitly relative to + // the current directory if and only if the argument had this form. if (!vim_ispathsep(*p)) { if (is_relative_to_current && *p != NUL @@ -14262,42 +13558,40 @@ static void f_resolve(typval_T *argvars, typval_T *rettv, FunPtr fptr) || (p[1] == '.' && (p[2] == NUL || vim_ispathsep(p[2])))))) { - /* Prepend "./". */ - cpy = concat_str((char_u *)"./", p); + // Prepend "./". + cpy = (char *)concat_str((const char_u *)"./", (const char_u *)p); xfree(p); p = cpy; } else if (!is_relative_to_current) { - /* Strip leading "./". */ + // Strip leading "./". q = p; - while (q[0] == '.' && vim_ispathsep(q[1])) + while (q[0] == '.' && vim_ispathsep(q[1])) { q += 2; - if (q > p) + } + if (q > p) { STRMOVE(p, p + 2); + } } } - /* Ensure that the result will have no trailing path separator - * if the argument had none. But keep "/" or "//". */ + // Ensure that the result will have no trailing path separator + // if the argument had none. But keep "/" or "//". if (!has_trailing_pathsep) { - q = p + STRLEN(p); - if (after_pathsep((char *)p, (char *)q)) - *path_tail_with_sep(p) = NUL; + q = p + strlen(p); + if (after_pathsep(p, q)) { + *path_tail_with_sep((char_u *)p) = NUL; + } } - rettv->vval.v_string = p; + rettv->vval.v_string = (char_u *)p; + xfree(buf); } # else - rettv->vval.v_string = vim_strsave(p); + rettv->vval.v_string = (char_u *)xstrdup(p); # endif #endif simplify_filename(rettv->vval.v_string); - -#ifdef HAVE_READLINK -fail: - xfree(buf); -#endif - rettv->v_type = VAR_STRING; } /* @@ -14305,25 +13599,23 @@ fail: */ static void f_reverse(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - list_T *l; - listitem_T *li, *ni; - + list_T *l; if (argvars[0].v_type != VAR_LIST) { EMSG2(_(e_listarg), "reverse()"); } else if ((l = argvars[0].vval.v_list) != NULL - && !tv_check_lock(l->lv_lock, - (char_u *)N_("reverse() argument"), true)) { - li = l->lv_last; + && !tv_check_lock(l->lv_lock, N_("reverse() argument"), + TV_TRANSLATE)) { + listitem_T *li = l->lv_last; l->lv_first = l->lv_last = NULL; l->lv_len = 0; while (li != NULL) { - ni = li->li_prev; - list_append(l, li); + listitem_T *const ni = li->li_prev; + tv_list_append(l, li); li = ni; } rettv->vval.v_list = l; rettv->v_type = VAR_LIST; - ++l->lv_refcount; + l->lv_refcount++; l->lv_idx = l->lv_len - l->lv_idx - 1; } } @@ -14345,40 +13637,45 @@ static void f_reverse(typval_T *argvars, typval_T *rettv, FunPtr fptr) static int get_search_arg(typval_T *varp, int *flagsp) { int dir = FORWARD; - char_u *flags; - char_u nbuf[NUMBUFLEN]; int mask; if (varp->v_type != VAR_UNKNOWN) { - flags = get_tv_string_buf_chk(varp, nbuf); - if (flags == NULL) - return 0; /* type error; errmsg already given */ + char nbuf[NUMBUFLEN]; + const char *flags = tv_get_string_buf_chk(varp, nbuf); + if (flags == NULL) { + return 0; // Type error; errmsg already given. + } while (*flags != NUL) { switch (*flags) { - case 'b': dir = BACKWARD; break; - case 'w': p_ws = true; break; - case 'W': p_ws = false; break; - default: mask = 0; - if (flagsp != NULL) - switch (*flags) { - case 'c': mask = SP_START; break; - case 'e': mask = SP_END; break; - case 'm': mask = SP_RETCOUNT; break; - case 'n': mask = SP_NOMOVE; break; - case 'p': mask = SP_SUBPAT; break; - case 'r': mask = SP_REPEAT; break; - case 's': mask = SP_SETPCMARK; break; - case 'z': mask = SP_COLUMN; break; + case 'b': dir = BACKWARD; break; + case 'w': p_ws = true; break; + case 'W': p_ws = false; break; + default: { + mask = 0; + if (flagsp != NULL) { + switch (*flags) { + case 'c': mask = SP_START; break; + case 'e': mask = SP_END; break; + case 'm': mask = SP_RETCOUNT; break; + case 'n': mask = SP_NOMOVE; break; + case 'p': mask = SP_SUBPAT; break; + case 'r': mask = SP_REPEAT; break; + case 's': mask = SP_SETPCMARK; break; + case 'z': mask = SP_COLUMN; break; + } } - if (mask == 0) { - EMSG2(_(e_invarg2), flags); - dir = 0; - } else - *flagsp |= mask; + if (mask == 0) { + emsgf(_(e_invarg2), flags); + dir = 0; + } else { + *flagsp |= mask; + } + } } - if (dir == 0) + if (dir == 0) { break; - ++flags; + } + flags++; } } return dir; @@ -14388,7 +13685,6 @@ static int get_search_arg(typval_T *varp, int *flagsp) static int search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp) { int flags; - char_u *pat; pos_T pos; pos_T save_cursor; bool save_p_ws = p_ws; @@ -14400,10 +13696,11 @@ static int search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp) int options = SEARCH_KEEP; int subpatnum; - pat = get_tv_string(&argvars[0]); - dir = get_search_arg(&argvars[1], flagsp); /* may set p_ws */ - if (dir == 0) + const char *const pat = tv_get_string(&argvars[0]); + dir = get_search_arg(&argvars[1], flagsp); // May set p_ws. + if (dir == 0) { goto theend; + } flags = *flagsp; if (flags & SP_START) { options |= SEARCH_START; @@ -14417,13 +13714,15 @@ static int search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp) /* Optional arguments: line number to stop searching and timeout. */ if (argvars[1].v_type != VAR_UNKNOWN && argvars[2].v_type != VAR_UNKNOWN) { - lnum_stop = get_tv_number_chk(&argvars[2], NULL); - if (lnum_stop < 0) + lnum_stop = tv_get_number_chk(&argvars[2], NULL); + if (lnum_stop < 0) { goto theend; + } if (argvars[3].v_type != VAR_UNKNOWN) { - time_limit = get_tv_number_chk(&argvars[3], NULL); - if (time_limit < 0) + time_limit = tv_get_number_chk(&argvars[3], NULL); + if (time_limit < 0) { goto theend; + } } } @@ -14438,13 +13737,13 @@ static int search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp) */ if (((flags & (SP_REPEAT | SP_RETCOUNT)) != 0) || ((flags & SP_NOMOVE) && (flags & SP_SETPCMARK))) { - EMSG2(_(e_invarg2), get_tv_string(&argvars[1])); + EMSG2(_(e_invarg2), tv_get_string(&argvars[1])); goto theend; } pos = save_cursor = curwin->w_cursor; - subpatnum = searchit(curwin, curbuf, &pos, dir, pat, 1L, - options, RE_SEARCH, (linenr_T)lnum_stop, &tm); + subpatnum = searchit(curwin, curbuf, &pos, dir, (char_u *)pat, 1, + options, RE_SEARCH, (linenr_T)lnum_stop, &tm); if (subpatnum != FAIL) { if (flags & SP_SUBPAT) retval = subpatnum; @@ -14501,7 +13800,7 @@ static void f_rpcnotify(typval_T *argvars, typval_T *rettv, FunPtr fptr) } if (!channel_send_event((uint64_t)argvars[0].vval.v_number, - (char *)get_tv_string(&argvars[1]), + tv_get_string(&argvars[1]), args)) { EMSG2(_(e_invarg2), "Channel doesn't exist"); return; @@ -14568,7 +13867,7 @@ static void f_rpcrequest(typval_T *argvars, typval_T *rettv, FunPtr fptr) Error err = ERROR_INIT; Object result = channel_send_call((uint64_t)argvars[0].vval.v_number, - (char *)get_tv_string(&argvars[1]), + tv_get_string(&argvars[1]), args, &err); @@ -14583,7 +13882,7 @@ static void f_rpcrequest(typval_T *argvars, typval_T *rettv, FunPtr fptr) restore_funccal(save_funccalp); } - if (err.set) { + if (ERROR_SET(&err)) { nvim_err_writeln(cstr_as_string(err.msg)); goto end; } @@ -14594,6 +13893,7 @@ static void f_rpcrequest(typval_T *argvars, typval_T *rettv, FunPtr fptr) end: api_free_object(result); + api_clear_error(&err); } // "rpcstart()" function (DEPRECATED) @@ -14643,7 +13943,7 @@ static void f_rpcstart(typval_T *argvars, typval_T *rettv, FunPtr fptr) // Copy arguments to the vector if (argsl > 0) { for (listitem_T *arg = args->lv_first; arg != NULL; arg = arg->li_next) { - argv[i++] = xstrdup((char *) get_tv_string(&arg->li_tv)); + argv[i++] = xstrdup(tv_get_string(&arg->li_tv)); } } @@ -14685,17 +13985,16 @@ static void f_rpcstop(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_screenattr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - int row; - int col; int c; - row = get_tv_number_chk(&argvars[0], NULL) - 1; - col = get_tv_number_chk(&argvars[1], NULL) - 1; + const int row = (int)tv_get_number_chk(&argvars[0], NULL) - 1; + const int col = (int)tv_get_number_chk(&argvars[1], NULL) - 1; if (row < 0 || row >= screen_Rows - || col < 0 || col >= screen_Columns) + || col < 0 || col >= screen_Columns) { c = -1; - else + } else { c = ScreenAttrs[LineOffset[row] + col]; + } rettv->vval.v_number = c; } @@ -14704,17 +14003,15 @@ static void f_screenattr(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_screenchar(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - int row; - int col; int off; int c; - row = get_tv_number_chk(&argvars[0], NULL) - 1; - col = get_tv_number_chk(&argvars[1], NULL) - 1; + const int row = tv_get_number_chk(&argvars[0], NULL) - 1; + const int col = tv_get_number_chk(&argvars[1], NULL) - 1; if (row < 0 || row >= screen_Rows - || col < 0 || col >= screen_Columns) + || col < 0 || col >= screen_Columns) { c = -1; - else { + } else { off = LineOffset[row] + col; if (enc_utf8 && ScreenLinesUC[off] != 0) c = ScreenLinesUC[off]; @@ -14759,19 +14056,21 @@ static void f_searchdecl(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int locally = 1; int thisblock = 0; - int error = FALSE; + bool error = false; rettv->vval.v_number = 1; /* default: FAIL */ - char_u *name = get_tv_string_chk(&argvars[0]); + const char *const name = tv_get_string_chk(&argvars[0]); if (argvars[1].v_type != VAR_UNKNOWN) { - locally = get_tv_number_chk(&argvars[1], &error) == 0; - if (!error && argvars[2].v_type != VAR_UNKNOWN) - thisblock = get_tv_number_chk(&argvars[2], &error) != 0; + locally = tv_get_number_chk(&argvars[1], &error) == 0; + if (!error && argvars[2].v_type != VAR_UNKNOWN) { + thisblock = tv_get_number_chk(&argvars[2], &error) != 0; + } } - if (!error && name != NULL) - rettv->vval.v_number = find_decl(name, STRLEN(name), locally, + if (!error && name != NULL) { + rettv->vval.v_number = find_decl((char_u *)name, strlen(name), locally, thisblock, SEARCH_KEEP) == FAIL; + } } /* @@ -14779,65 +14078,70 @@ static void f_searchdecl(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static int searchpair_cmn(typval_T *argvars, pos_T *match_pos) { - char_u *spat, *mpat, *epat; - char_u *skip; bool save_p_ws = p_ws; int dir; int flags = 0; - char_u nbuf1[NUMBUFLEN]; - char_u nbuf2[NUMBUFLEN]; - char_u nbuf3[NUMBUFLEN]; - int retval = 0; /* default: FAIL */ + int retval = 0; // default: FAIL long lnum_stop = 0; long time_limit = 0; - /* Get the three pattern arguments: start, middle, end. */ - spat = get_tv_string_chk(&argvars[0]); - mpat = get_tv_string_buf_chk(&argvars[1], nbuf1); - epat = get_tv_string_buf_chk(&argvars[2], nbuf2); - if (spat == NULL || mpat == NULL || epat == NULL) - goto theend; /* type error */ + // Get the three pattern arguments: start, middle, end. + char nbuf1[NUMBUFLEN]; + char nbuf2[NUMBUFLEN]; + char nbuf3[NUMBUFLEN]; + const char *spat = tv_get_string_chk(&argvars[0]); + const char *mpat = tv_get_string_buf_chk(&argvars[1], nbuf1); + const char *epat = tv_get_string_buf_chk(&argvars[2], nbuf2); + if (spat == NULL || mpat == NULL || epat == NULL) { + goto theend; // Type error. + } - /* Handle the optional fourth argument: flags */ - dir = get_search_arg(&argvars[3], &flags); /* may set p_ws */ - if (dir == 0) + // Handle the optional fourth argument: flags. + dir = get_search_arg(&argvars[3], &flags); // may set p_ws. + if (dir == 0) { goto theend; + } - /* Don't accept SP_END or SP_SUBPAT. - * Only one of the SP_NOMOVE or SP_SETPCMARK flags can be set. - */ + // Don't accept SP_END or SP_SUBPAT. + // Only one of the SP_NOMOVE or SP_SETPCMARK flags can be set. if ((flags & (SP_END | SP_SUBPAT)) != 0 || ((flags & SP_NOMOVE) && (flags & SP_SETPCMARK))) { - EMSG2(_(e_invarg2), get_tv_string(&argvars[3])); + EMSG2(_(e_invarg2), tv_get_string(&argvars[3])); goto theend; } - /* Using 'r' implies 'W', otherwise it doesn't work. */ - if (flags & SP_REPEAT) + // Using 'r' implies 'W', otherwise it doesn't work. + if (flags & SP_REPEAT) { p_ws = false; + } - /* Optional fifth argument: skip expression */ + // Optional fifth argument: skip expression. + const char *skip; if (argvars[3].v_type == VAR_UNKNOWN - || argvars[4].v_type == VAR_UNKNOWN) - skip = (char_u *)""; - else { - skip = get_tv_string_buf_chk(&argvars[4], nbuf3); + || argvars[4].v_type == VAR_UNKNOWN) { + skip = ""; + } else { + skip = tv_get_string_buf_chk(&argvars[4], nbuf3); + if (skip == NULL) { + goto theend; // Type error. + } if (argvars[5].v_type != VAR_UNKNOWN) { - lnum_stop = get_tv_number_chk(&argvars[5], NULL); - if (lnum_stop < 0) + lnum_stop = tv_get_number_chk(&argvars[5], NULL); + if (lnum_stop < 0) { goto theend; + } if (argvars[6].v_type != VAR_UNKNOWN) { - time_limit = get_tv_number_chk(&argvars[6], NULL); - if (time_limit < 0) + time_limit = tv_get_number_chk(&argvars[6], NULL); + if (time_limit < 0) { goto theend; + } } } } - if (skip == NULL) - goto theend; /* type error */ - retval = do_searchpair(spat, mpat, epat, dir, skip, flags, - match_pos, lnum_stop, time_limit); + retval = do_searchpair( + (char_u *)spat, (char_u *)mpat, (char_u *)epat, dir, (char_u *)skip, + flags, match_pos, lnum_stop, time_limit); theend: p_ws = save_p_ws; @@ -14862,15 +14166,15 @@ static void f_searchpairpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) int lnum = 0; int col = 0; - rettv_list_alloc(rettv); + tv_list_alloc_ret(rettv); if (searchpair_cmn(argvars, &match_pos) > 0) { lnum = match_pos.lnum; col = match_pos.col; } - list_append_number(rettv->vval.v_list, (varnumber_T)lnum); - list_append_number(rettv->vval.v_list, (varnumber_T)col); + tv_list_append_number(rettv->vval.v_list, (varnumber_T)lnum); + tv_list_append_number(rettv->vval.v_list, (varnumber_T)col); } /* @@ -14902,9 +14206,10 @@ do_searchpair ( int n; int r; int nest = 1; - int err; int options = SEARCH_KEEP; proftime_T tm; + size_t pat2_len; + size_t pat3_len; /* Make 'cpoptions' empty, the 'l' flag should not be used here. */ save_cpo = p_cpo; @@ -14913,18 +14218,22 @@ do_searchpair ( /* Set the time limit, if there is one. */ tm = profile_setlimit(time_limit); - /* Make two search patterns: start/end (pat2, for in nested pairs) and - * start/middle/end (pat3, for the top pair). */ - pat2 = xmalloc(STRLEN(spat) + STRLEN(epat) + 15); - pat3 = xmalloc(STRLEN(spat) + STRLEN(mpat) + STRLEN(epat) + 23); - sprintf((char *)pat2, "\\(%s\\m\\)\\|\\(%s\\m\\)", spat, epat); - if (*mpat == NUL) + // Make two search patterns: start/end (pat2, for in nested pairs) and + // start/middle/end (pat3, for the top pair). + pat2_len = STRLEN(spat) + STRLEN(epat) + 17; + pat2 = xmalloc(pat2_len); + pat3_len = STRLEN(spat) + STRLEN(mpat) + STRLEN(epat) + 25; + pat3 = xmalloc(pat3_len); + snprintf((char *)pat2, pat2_len, "\\m\\(%s\\m\\)\\|\\(%s\\m\\)", spat, epat); + if (*mpat == NUL) { STRCPY(pat3, pat2); - else - sprintf((char *)pat3, "\\(%s\\m\\)\\|\\(%s\\m\\)\\|\\(%s\\m\\)", - spat, epat, mpat); - if (flags & SP_START) + } else { + snprintf((char *)pat3, pat3_len, + "\\m\\(%s\\m\\)\\|\\(%s\\m\\)\\|\\(%s\\m\\)", spat, epat, mpat); + } + if (flags & SP_START) { options |= SEARCH_START; + } save_cursor = curwin->w_cursor; pos = curwin->w_cursor; @@ -14958,7 +14267,8 @@ do_searchpair ( if (*skip != NUL) { save_pos = curwin->w_cursor; curwin->w_cursor = pos; - r = eval_to_bool(skip, &err, NULL, FALSE); + bool err; + r = eval_to_bool(skip, &err, NULL, false); curwin->w_cursor = save_pos; if (err) { /* Evaluating {skip} caused an error, break here. */ @@ -15029,7 +14339,7 @@ static void f_searchpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) int n; int flags = 0; - rettv_list_alloc(rettv); + tv_list_alloc_ret(rettv); n = search_cmn(argvars, &match_pos, &flags); if (n > 0) { @@ -15037,10 +14347,11 @@ static void f_searchpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) col = match_pos.col; } - list_append_number(rettv->vval.v_list, (varnumber_T)lnum); - list_append_number(rettv->vval.v_list, (varnumber_T)col); - if (flags & SP_SUBPAT) - list_append_number(rettv->vval.v_list, (varnumber_T)n); + tv_list_append_number(rettv->vval.v_list, (varnumber_T)lnum); + tv_list_append_number(rettv->vval.v_list, (varnumber_T)col); + if (flags & SP_SUBPAT) { + tv_list_append_number(rettv->vval.v_list, (varnumber_T)n); + } } /// "serverlist()" function @@ -15050,13 +14361,13 @@ static void f_serverlist(typval_T *argvars, typval_T *rettv, FunPtr fptr) char **addrs = server_address_list(&n); // Copy addrs into a linked list. - list_T *l = rettv_list_alloc(rettv); + list_T *l = tv_list_alloc_ret(rettv); for (size_t i = 0; i < n; i++) { - listitem_T *li = listitem_alloc(); + listitem_T *li = tv_list_item_alloc(); li->li_tv.v_type = VAR_STRING; li->li_tv.v_lock = 0; - li->li_tv.vval.v_string = (char_u *) addrs[i]; - list_append(l, li); + li->li_tv.vval.v_string = (char_u *)addrs[i]; + tv_list_append(l, li); } xfree(addrs); } @@ -15071,22 +14382,39 @@ static void f_serverstart(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; } + char *address; // If the user supplied an address, use it, otherwise use a temp. if (argvars[0].v_type != VAR_UNKNOWN) { if (argvars[0].v_type != VAR_STRING) { EMSG(_(e_invarg)); return; } else { - rettv->vval.v_string = vim_strsave(get_tv_string(argvars)); + address = xstrdup(tv_get_string(argvars)); } } else { - rettv->vval.v_string = (char_u *)server_address_new(); + address = server_address_new(); } - int result = server_start((char *) rettv->vval.v_string); + int result = server_start(address); + xfree(address); + if (result != 0) { - EMSG2("Failed to start server: %s", uv_strerror(result)); + EMSG2("Failed to start server: %s", + result > 0 ? "Unknown system error" : uv_strerror(result)); + return; + } + + // Since it's possible server_start adjusted the given {address} (e.g., + // "localhost:" will now have a port), return the final value to the user. + size_t n; + char **addrs = server_address_list(&n); + rettv->vval.v_string = (char_u *)addrs[n - 1]; + + n--; + for (size_t i = 0; i < n; i++) { + xfree(addrs[i]); } + xfree(addrs); } /// "serverstop()" function @@ -15096,7 +14424,7 @@ static void f_serverstop(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; } - if (argvars[0].v_type == VAR_UNKNOWN || argvars[0].v_type != VAR_STRING) { + if (argvars[0].v_type != VAR_STRING) { EMSG(_(e_invarg)); return; } @@ -15111,44 +14439,43 @@ static void f_serverstop(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_setbufvar(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - buf_T *buf; - char_u *varname, *bufvarname; - typval_T *varp; - char_u nbuf[NUMBUFLEN]; - - if (check_restricted() || check_secure()) + if (check_restricted() + || check_secure() + || !tv_check_str_or_nr(&argvars[0])) { return; - (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */ - varname = get_tv_string_chk(&argvars[1]); - buf = get_buf_tv(&argvars[0], FALSE); - varp = &argvars[2]; + } + const char *varname = tv_get_string_chk(&argvars[1]); + buf_T *const buf = get_buf_tv(&argvars[0], false); + typval_T *varp = &argvars[2]; - if (buf != NULL && varname != NULL && varp != NULL) { + if (buf != NULL && varname != NULL) { if (*varname == '&') { long numval; - char_u *strval; - int error = false; - aco_save_T aco; + bool error = false; + aco_save_T aco; // set curbuf to be our buf, temporarily aucmd_prepbuf(&aco, buf); - ++varname; - numval = get_tv_number_chk(varp, &error); - strval = get_tv_string_buf_chk(varp, nbuf); - if (!error && strval != NULL) + varname++; + numval = tv_get_number_chk(varp, &error); + char nbuf[NUMBUFLEN]; + const char *const strval = tv_get_string_buf_chk(varp, nbuf); + if (!error && strval != NULL) { set_option_value(varname, numval, strval, OPT_LOCAL); + } // reset notion of buffer aucmd_restbuf(&aco); } else { buf_T *save_curbuf = curbuf; - bufvarname = xmalloc(STRLEN(varname) + 3); + const size_t varname_len = STRLEN(varname); + char *const bufvarname = xmalloc(varname_len + 3); curbuf = buf; - STRCPY(bufvarname, "b:"); - STRCPY(bufvarname + 2, varname); - set_var(bufvarname, varp, TRUE); + memcpy(bufvarname, "b:", 2); + memcpy(bufvarname + 2, varname, varname_len + 1); + set_var(bufvarname, varname_len + 2, varp, true); xfree(bufvarname); curbuf = save_curbuf; } @@ -15159,7 +14486,6 @@ static void f_setcharsearch(typval_T *argvars, typval_T *rettv, FunPtr fptr) { dict_T *d; dictitem_T *di; - char_u *csearch; if (argvars[0].v_type != VAR_DICT) { EMSG(_(e_dictreq)); @@ -15167,7 +14493,7 @@ static void f_setcharsearch(typval_T *argvars, typval_T *rettv, FunPtr fptr) } if ((d = argvars[0].vval.v_dict) != NULL) { - csearch = get_dict_string(d, "char", false); + char_u *const csearch = (char_u *)tv_dict_get_string(d, "char", false); if (csearch != NULL) { if (enc_utf8) { int pcc[MAX_MCO]; @@ -15179,13 +14505,15 @@ static void f_setcharsearch(typval_T *argvars, typval_T *rettv, FunPtr fptr) csearch, MB_PTR2LEN(csearch)); } - di = dict_find(d, (char_u *)"forward", -1); - if (di != NULL) - set_csearch_direction(get_tv_number(&di->di_tv) ? FORWARD : BACKWARD); + di = tv_dict_find(d, S_LEN("forward")); + if (di != NULL) { + set_csearch_direction(tv_get_number(&di->di_tv) ? FORWARD : BACKWARD); + } - di = dict_find(d, (char_u *)"until", -1); - if (di != NULL) - set_csearch_until(!!get_tv_number(&di->di_tv)); + di = tv_dict_find(d, S_LEN("until")); + if (di != NULL) { + set_csearch_until(!!tv_get_number(&di->di_tv)); + } } } @@ -15194,10 +14522,11 @@ static void f_setcharsearch(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_setcmdpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - int pos = (int)get_tv_number(&argvars[0]) - 1; + const int pos = (int)tv_get_number(&argvars[0]) - 1; - if (pos >= 0) + if (pos >= 0) { rettv->vval.v_number = set_cmdline_pos(pos); + } } @@ -15206,17 +14535,17 @@ static void f_setfperm(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = 0; - char_u *fname = get_tv_string_chk(&argvars[0]); + const char *const fname = tv_get_string_chk(&argvars[0]); if (fname == NULL) { return; } - char_u modebuf[NUMBUFLEN]; - char_u *mode_str = get_tv_string_buf_chk(&argvars[1], modebuf); + char modebuf[NUMBUFLEN]; + const char *const mode_str = tv_get_string_buf_chk(&argvars[1], modebuf); if (mode_str == NULL) { return; } - if (STRLEN(mode_str) != 9) { + if (strlen(mode_str) != 9) { EMSG2(_(e_invarg2), mode_str); return; } @@ -15237,27 +14566,28 @@ static void f_setfperm(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_setline(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - linenr_T lnum; - char_u *line = NULL; list_T *l = NULL; listitem_T *li = NULL; long added = 0; linenr_T lcount = curbuf->b_ml.ml_line_count; - lnum = get_tv_lnum(&argvars[0]); + linenr_T lnum = tv_get_lnum(&argvars[0]); + const char *line = NULL; if (argvars[1].v_type == VAR_LIST) { l = argvars[1].vval.v_list; li = l->lv_first; - } else - line = get_tv_string_chk(&argvars[1]); + } else { + line = tv_get_string_chk(&argvars[1]); + } /* default result is zero == OK */ for (;; ) { if (l != NULL) { - /* list argument, get next string */ - if (li == NULL) + // List argument, get next string. + if (li == NULL) { break; - line = get_tv_string_chk(&li->li_tv); + } + line = tv_get_string_chk(&li->li_tv); li = li->li_next; } @@ -15273,18 +14603,20 @@ static void f_setline(typval_T *argvars, typval_T *rettv, FunPtr fptr) } if (lnum <= curbuf->b_ml.ml_line_count) { - /* existing line, replace it */ - if (u_savesub(lnum) == OK && ml_replace(lnum, line, TRUE) == OK) { + // Existing line, replace it. + if (u_savesub(lnum) == OK + && ml_replace(lnum, (char_u *)line, true) == OK) { changed_bytes(lnum, 0); if (lnum == curwin->w_cursor.lnum) check_cursor_col(); rettv->vval.v_number = 0; /* OK */ } } else if (added > 0 || u_save(lnum - 1, lnum) == OK) { - /* lnum is one past the last line, append the line */ - ++added; - if (ml_append(lnum - 1, line, (colnr_T)0, FALSE) == OK) - rettv->vval.v_number = 0; /* OK */ + // lnum is one past the last line, append the line. + added++; + if (ml_append(lnum - 1, (char_u *)line, 0, false) == OK) { + rettv->vval.v_number = 0; // OK + } } if (l == NULL) /* only one string argument */ @@ -15299,7 +14631,7 @@ static void f_setline(typval_T *argvars, typval_T *rettv, FunPtr fptr) /// Create quickfix/location list from VimL values /// /// Used by `setqflist()` and `setloclist()` functions. Accepts invalid -/// list_arg, action_arg and title_arg arguments in which case errors out, +/// list_arg, action_arg and what_arg arguments in which case errors out, /// including VAR_UNKNOWN parameters. /// /// @param[in,out] wp Window to create location list for. May be NULL in @@ -15313,9 +14645,10 @@ static void set_qf_ll_list(win_T *wp, typval_T *args, typval_T *rettv) FUNC_ATTR_NONNULL_ARG(2, 3) { static char *e_invact = N_("E927: Invalid action: '%s'"); - char_u *title = NULL; + const char *title = NULL; int action = ' '; rettv->vval.v_number = -1; + dict_T *d = NULL; typval_T *list_arg = &args[0]; if (list_arg->v_type != VAR_LIST) { @@ -15331,7 +14664,7 @@ static void set_qf_ll_list(win_T *wp, typval_T *args, typval_T *rettv) EMSG(_(e_stringreq)); return; } - char_u *act = get_tv_string_chk(action_arg); + const char *const act = tv_get_string_chk(action_arg); if ((*act == 'a' || *act == 'r' || *act == ' ') && act[1] == NUL) { action = *act; } else { @@ -15343,20 +14676,26 @@ static void set_qf_ll_list(win_T *wp, typval_T *args, typval_T *rettv) if (title_arg->v_type == VAR_UNKNOWN) { // Option argument was not given. goto skip_args; - } - title = get_tv_string_chk(title_arg); - if (!title) { - // Type error. Error already printed by get_tv_string_chk(). + } else if (title_arg->v_type == VAR_STRING) { + title = tv_get_string_chk(title_arg); + if (!title) { + // Type error. Error already printed by tv_get_string_chk(). + return; + } + } else if (title_arg->v_type == VAR_DICT) { + d = title_arg->vval.v_dict; + } else { + emsgf(_(e_dictreq)); return; } skip_args: if (!title) { - title = (char_u*)(wp ? "setloclist()" : "setqflist()"); + title = (wp ? "setloclist()" : "setqflist()"); } list_T *l = list_arg->vval.v_list; - if (l && set_errorlist(wp, l, action, title) == OK) { + if (l && set_errorlist(wp, l, action, (char_u *)title, d) == OK) { rettv->vval.v_number = 0; } } @@ -15402,11 +14741,11 @@ static void f_setmatches(typval_T *argvars, typval_T *rettv, FunPtr fptr) EMSG(_(e_invarg)); return; } - if (!(dict_find(d, (char_u *)"group", -1) != NULL - && (dict_find(d, (char_u *)"pattern", -1) != NULL - || dict_find(d, (char_u *)"pos1", -1) != NULL) - && dict_find(d, (char_u *)"priority", -1) != NULL - && dict_find(d, (char_u *)"id", -1) != NULL)) { + if (!(tv_dict_find(d, S_LEN("group")) != NULL + && (tv_dict_find(d, S_LEN("pattern")) != NULL + || tv_dict_find(d, S_LEN("pos1")) != NULL) + && tv_dict_find(d, S_LEN("priority")) != NULL + && tv_dict_find(d, S_LEN("id")) != NULL)) { EMSG(_(e_invarg)); return; } @@ -15415,29 +14754,31 @@ static void f_setmatches(typval_T *argvars, typval_T *rettv, FunPtr fptr) clear_matches(curwin); li = l->lv_first; + bool match_add_failed = false; while (li != NULL) { int i = 0; - char_u buf[5]; - dictitem_T *di; d = li->li_tv.vval.v_dict; - if (dict_find(d, (char_u *)"pattern", -1) == NULL) { + dictitem_T *const di = tv_dict_find(d, S_LEN("pattern")); + if (di == NULL) { if (s == NULL) { - s = list_alloc(); + s = tv_list_alloc(); if (s == NULL) { return; } } // match from matchaddpos() - for (i = 1; i < 9; ++i) { - snprintf((char *)buf, sizeof(buf), (char *)"pos%d", i); - if ((di = dict_find(d, (char_u *)buf, -1)) != NULL) { - if (di->di_tv.v_type != VAR_LIST) { + for (i = 1; i < 9; i++) { + char buf[5]; + snprintf(buf, sizeof(buf), "pos%d", i); + dictitem_T *const pos_di = tv_dict_find(d, buf, -1); + if (pos_di != NULL) { + if (pos_di->di_tv.v_type != VAR_LIST) { return; } - list_append_tv(s, &di->di_tv); + tv_list_append_tv(s, &pos_di->di_tv); s->lv_refcount++; } else { break; @@ -15445,25 +14786,39 @@ static void f_setmatches(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } - char_u *group = get_dict_string(d, "group", false); - int priority = get_dict_number(d, "priority"); - int id = get_dict_number(d, "id"); - char_u *conceal = dict_find(d, (char_u *)"conceal", -1) != NULL - ? get_dict_string(d, "conceal", - false) - : NULL; + // Note: there are three number buffers involved: + // - group_buf below. + // - numbuf in tv_dict_get_string(). + // - mybuf in tv_get_string(). + // + // If you change this code make sure that buffers will not get + // accidentally reused. + char group_buf[NUMBUFLEN]; + const char *const group = tv_dict_get_string_buf(d, "group", group_buf); + const int priority = (int)tv_dict_get_number(d, "priority"); + const int id = (int)tv_dict_get_number(d, "id"); + dictitem_T *const conceal_di = tv_dict_find(d, S_LEN("conceal")); + const char *const conceal = (conceal_di != NULL + ? tv_get_string(&conceal_di->di_tv) + : NULL); if (i == 0) { - match_add(curwin, group, - get_dict_string(d, "pattern", false), - priority, id, NULL, conceal); + if (match_add(curwin, group, + tv_dict_get_string(d, "pattern", false), + priority, id, NULL, conceal) != id) { + match_add_failed = true; + } } else { - match_add(curwin, group, NULL, priority, id, s, conceal); - list_unref(s); + if (match_add(curwin, group, NULL, priority, id, s, conceal) != id) { + match_add_failed = true; + } + tv_list_unref(s); s = NULL; } li = li->li_next; } - rettv->vval.v_number = 0; + if (!match_add_failed) { + rettv->vval.v_number = 0; + } } } @@ -15474,11 +14829,10 @@ static void f_setpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) { pos_T pos; int fnum; - char_u *name; colnr_T curswant = -1; rettv->vval.v_number = -1; - name = get_tv_string_chk(argvars); + const char *const name = tv_get_string_chk(argvars); if (name != NULL) { if (list2fpos(&argvars[1], &pos, &fnum, &curswant) == OK) { if (--pos.col < 0) { @@ -15499,7 +14853,7 @@ static void f_setpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } else if (name[0] == '\'' && name[1] != NUL && name[2] == NUL) { // set mark - if (setmark_pos(name[1], &pos, fnum) == OK) { + if (setmark_pos((uint8_t)name[1], &pos, fnum) == OK) { rettv->vval.v_number = 0; } } else { @@ -15523,8 +14877,6 @@ static void f_setqflist(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_setreg(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int regname; - char_u *strregname; - char_u *stropt; bool append = false; MotionType yank_type; long block_len; @@ -15532,39 +14884,52 @@ static void f_setreg(typval_T *argvars, typval_T *rettv, FunPtr fptr) block_len = -1; yank_type = kMTUnknown; - strregname = get_tv_string_chk(argvars); - rettv->vval.v_number = 1; /* FAIL is default */ + rettv->vval.v_number = 1; // FAIL is default. - if (strregname == NULL) - return; /* type error; errmsg already given */ - regname = *strregname; - if (regname == 0 || regname == '@') + const char *const strregname = tv_get_string_chk(argvars); + if (strregname == NULL) { + return; // Type error; errmsg already given. + } + regname = (uint8_t)(*strregname); + if (regname == 0 || regname == '@') { regname = '"'; + } + bool set_unnamed = false; if (argvars[2].v_type != VAR_UNKNOWN) { - stropt = get_tv_string_chk(&argvars[2]); - if (stropt == NULL) - return; /* type error */ - for (; *stropt != NUL; ++stropt) + const char *stropt = tv_get_string_chk(&argvars[2]); + if (stropt == NULL) { + return; // Type error. + } + for (; *stropt != NUL; stropt++) { switch (*stropt) { - case 'a': case 'A': // append - append = true; - break; - case 'v': case 'c': // character-wise selection - yank_type = kMTCharWise; - break; - case 'V': case 'l': // line-wise selection - yank_type = kMTLineWise; - break; - case 'b': case Ctrl_V: // block-wise selection - yank_type = kMTBlockWise; - if (ascii_isdigit(stropt[1])) { - ++stropt; - block_len = getdigits_long(&stropt) - 1; - --stropt; + case 'a': case 'A': { // append + append = true; + break; + } + case 'v': case 'c': { // character-wise selection + yank_type = kMTCharWise; + break; + } + case 'V': case 'l': { // line-wise selection + yank_type = kMTLineWise; + break; + } + case 'b': case Ctrl_V: { // block-wise selection + yank_type = kMTBlockWise; + if (ascii_isdigit(stropt[1])) { + stropt++; + block_len = getdigits_long((char_u **)&stropt) - 1; + stropt--; + } + break; + } + case 'u': case '"': { // unnamed register + set_unnamed = true; + break; } - break; } + } } if (argvars[1].v_type == VAR_LIST) { @@ -15574,45 +14939,52 @@ static void f_setreg(typval_T *argvars, typval_T *rettv, FunPtr fptr) // First half: use for pointers to result lines; second half: use for // pointers to allocated copies. - char_u **lstval = xmalloc(sizeof(char_u *) * ((len + 1) * 2)); - char_u **curval = lstval; - char_u **allocval = lstval + len + 2; - char_u **curallocval = allocval; + char **lstval = xmalloc(sizeof(char *) * ((len + 1) * 2)); + const char **curval = (const char **)lstval; + char **allocval = lstval + len + 2; + char **curallocval = allocval; - char_u buf[NUMBUFLEN]; for (listitem_T *li = ll == NULL ? NULL : ll->lv_first; li != NULL; li = li->li_next) { - char_u *strval = get_tv_string_buf_chk(&li->li_tv, buf); - if (strval == NULL) { + char buf[NUMBUFLEN]; + *curval = tv_get_string_buf_chk(&li->li_tv, buf); + if (*curval == NULL) { goto free_lstval; } - if (strval == buf) { + if (*curval == buf) { // Need to make a copy, - // next get_tv_string_buf_chk() will overwrite the string. - strval = vim_strsave(buf); - *curallocval++ = strval; + // next tv_get_string_buf_chk() will overwrite the string. + *curallocval = xstrdup(*curval); + *curval = *curallocval; + curallocval++; } - *curval++ = strval; + curval++; } *curval++ = NULL; - write_reg_contents_lst(regname, lstval, STRLEN(lstval), - append, yank_type, block_len); + write_reg_contents_lst(regname, (char_u **)lstval, append, yank_type, + block_len); free_lstval: - while (curallocval > allocval) - xfree(*--curallocval); + while (curallocval > allocval) { + xfree(*--curallocval); + } xfree(lstval); } else { - char_u *strval = get_tv_string_chk(&argvars[1]); + const char *strval = tv_get_string_chk(&argvars[1]); if (strval == NULL) { return; } - write_reg_contents_ex(regname, strval, STRLEN(strval), + write_reg_contents_ex(regname, (const char_u *)strval, STRLEN(strval), append, yank_type, block_len); } rettv->vval.v_number = 0; + + if (set_unnamed) { + // Discard the result. We already handle the error case. + if (op_register_set_previous(regname)) { } + } } /* @@ -15620,35 +14992,31 @@ free_lstval: */ static void f_settabvar(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - tabpage_T *save_curtab; - tabpage_T *tp; - char_u *varname, *tabvarname; - typval_T *varp; - rettv->vval.v_number = 0; - if (check_restricted() || check_secure()) + if (check_restricted() || check_secure()) { return; + } - tp = find_tabpage((int)get_tv_number_chk(&argvars[0], NULL)); - varname = get_tv_string_chk(&argvars[1]); - varp = &argvars[2]; + tabpage_T *const tp = find_tabpage((int)tv_get_number_chk(&argvars[0], NULL)); + const char *const varname = tv_get_string_chk(&argvars[1]); + typval_T *const varp = &argvars[2]; - if (varname != NULL && varp != NULL - && tp != NULL - ) { - save_curtab = curtab; - goto_tabpage_tp(tp, FALSE, FALSE); + if (varname != NULL && tp != NULL) { + tabpage_T *const save_curtab = curtab; + goto_tabpage_tp(tp, false, false); - tabvarname = xmalloc(STRLEN(varname) + 3); - STRCPY(tabvarname, "t:"); - STRCPY(tabvarname + 2, varname); - set_var(tabvarname, varp, TRUE); + const size_t varname_len = strlen(varname); + char *const tabvarname = xmalloc(varname_len + 3); + memcpy(tabvarname, "t:", 2); + memcpy(tabvarname + 2, varname, varname_len + 1); + set_var(tabvarname, varname_len + 2, varp, true); xfree(tabvarname); - /* Restore current tabpage */ - if (valid_tabpage(save_curtab)) - goto_tabpage_tp(save_curtab, FALSE, FALSE); + // Restore current tabpage. + if (valid_tabpage(save_curtab)) { + goto_tabpage_tp(save_curtab, false, false); + } } } @@ -15674,45 +15042,43 @@ static void f_setwinvar(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void setwinvar(typval_T *argvars, typval_T *rettv, int off) { - win_T *win; - win_T *save_curwin; - tabpage_T *save_curtab; - char_u *varname, *winvarname; - typval_T *varp; - char_u nbuf[NUMBUFLEN]; - tabpage_T *tp = NULL; - - if (check_restricted() || check_secure()) + if (check_restricted() || check_secure()) { return; + } - if (off == 1) - tp = find_tabpage((int)get_tv_number_chk(&argvars[0], NULL)); - else + tabpage_T *tp = NULL; + if (off == 1) { + tp = find_tabpage((int)tv_get_number_chk(&argvars[0], NULL)); + } else { tp = curtab; - win = find_win_by_nr(&argvars[off], tp); - varname = get_tv_string_chk(&argvars[off + 1]); - varp = &argvars[off + 2]; + } + win_T *const win = find_win_by_nr(&argvars[off], tp); + const char *varname = tv_get_string_chk(&argvars[off + 1]); + typval_T *varp = &argvars[off + 2]; if (win != NULL && varname != NULL && varp != NULL) { + win_T *save_curwin; + tabpage_T *save_curtab; bool need_switch_win = tp != curtab || win != curwin; if (!need_switch_win || switch_win(&save_curwin, &save_curtab, win, tp, true) == OK) { if (*varname == '&') { long numval; - char_u *strval; - int error = false; + bool error = false; - ++varname; - numval = get_tv_number_chk(varp, &error); - strval = get_tv_string_buf_chk(varp, nbuf); + varname++; + numval = tv_get_number_chk(varp, &error); + char nbuf[NUMBUFLEN]; + const char *const strval = tv_get_string_buf_chk(varp, nbuf); if (!error && strval != NULL) { set_option_value(varname, numval, strval, OPT_LOCAL); } } else { - winvarname = xmalloc(STRLEN(varname) + 3); - STRCPY(winvarname, "w:"); - STRCPY(winvarname + 2, varname); - set_var(winvarname, varp, true); + const size_t varname_len = strlen(varname); + char *const winvarname = xmalloc(varname_len + 3); + memcpy(winvarname, "w:", 2); + memcpy(winvarname + 2, varname, varname_len + 1); + set_var(winvarname, varname_len + 2, varp, true); xfree(winvarname); } } @@ -15725,11 +15091,11 @@ static void setwinvar(typval_T *argvars, typval_T *rettv, int off) /// f_sha256 - sha256({string}) function static void f_sha256(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *p = get_tv_string(&argvars[0]); - const char_u *hash = sha256_bytes(p, (int) STRLEN(p) , NULL, 0); + const char *p = tv_get_string(&argvars[0]); + const char *hash = sha256_bytes((const uint8_t *)p, strlen(p) , NULL, 0); // make a copy of the hash (sha256_bytes returns a static buffer) - rettv->vval.v_string = (char_u *) xstrdup((char *) hash); + rettv->vval.v_string = (char_u *)xstrdup(hash); rettv->v_type = VAR_STRING; } @@ -15739,7 +15105,8 @@ static void f_sha256(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_shellescape(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_string = vim_strsave_shellescape( - get_tv_string(&argvars[0]), non_zero_arg(&argvars[1]), true); + (const char_u *)tv_get_string(&argvars[0]), non_zero_arg(&argvars[1]), + true); rettv->v_type = VAR_STRING; } @@ -15756,14 +15123,61 @@ static void f_shiftwidth(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_simplify(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *p; - - p = get_tv_string(&argvars[0]); - rettv->vval.v_string = vim_strsave(p); - simplify_filename(rettv->vval.v_string); /* simplify in place */ + const char *const p = tv_get_string(&argvars[0]); + rettv->vval.v_string = (char_u *)xstrdup(p); + simplify_filename(rettv->vval.v_string); // Simplify in place. rettv->v_type = VAR_STRING; } +/// "sockconnect()" function +static void f_sockconnect(typval_T *argvars, typval_T *rettv, FunPtr fptr) +{ + if (argvars[0].v_type != VAR_STRING || argvars[1].v_type != VAR_STRING) { + EMSG(_(e_invarg)); + return; + } + if (argvars[2].v_type != VAR_DICT && argvars[2].v_type != VAR_UNKNOWN) { + // Wrong argument types + EMSG2(_(e_invarg2), "expected dictionary"); + return; + } + + const char *mode = tv_get_string(&argvars[0]); + const char *address = tv_get_string(&argvars[1]); + + bool tcp; + if (strcmp(mode, "tcp") == 0) { + tcp = true; + } else if (strcmp(mode, "pipe") == 0) { + tcp = false; + } else { + EMSG2(_(e_invarg2), "invalid mode"); + return; + } + + bool rpc = false; + if (argvars[2].v_type == VAR_DICT) { + dict_T *opts = argvars[2].vval.v_dict; + rpc = tv_dict_get_number(opts, "rpc") != 0; + } + + if (!rpc) { + EMSG2(_(e_invarg2), "rpc option must be true"); + return; + } + + const char *error = NULL; + eval_format_source_name_line((char *)IObuff, sizeof(IObuff)); + uint64_t id = channel_connect(tcp, address, 50, (char *)IObuff, &error); + + if (error) { + EMSG2(_("connection failed: %s"), error); + } + + rettv->vval.v_number = (varnumber_T)id; + rettv->v_type = VAR_NUMBER; +} + /// struct used in the array that's given to qsort() typedef struct { listitem_T *item; @@ -15776,10 +15190,10 @@ typedef struct { bool item_compare_numeric; bool item_compare_numbers; bool item_compare_float; - char_u *item_compare_func; + const char *item_compare_func; partial_T *item_compare_partial; dict_T *item_compare_selfdict; - int item_compare_func_err; + bool item_compare_func_err; } sortinfo_T; static sortinfo_T *sortinfo = NULL; @@ -15790,58 +15204,61 @@ static sortinfo_T *sortinfo = NULL; */ static int item_compare(const void *s1, const void *s2, bool keep_zero) { - sortItem_T *si1, *si2; - char_u *p1; - char_u *p2; - char_u *tofree1 = NULL; - char_u *tofree2 = NULL; - int res; + sortItem_T *const si1 = (sortItem_T *)s1; + sortItem_T *const si2 = (sortItem_T *)s2; - si1 = (sortItem_T *)s1; - si2 = (sortItem_T *)s2; - typval_T *tv1 = &si1->item->li_tv; - typval_T *tv2 = &si2->item->li_tv; + typval_T *const tv1 = &si1->item->li_tv; + typval_T *const tv2 = &si2->item->li_tv; + + int res; if (sortinfo->item_compare_numbers) { - long v1 = get_tv_number(tv1); - long v2 = get_tv_number(tv2); + const varnumber_T v1 = tv_get_number(tv1); + const varnumber_T v2 = tv_get_number(tv2); - return v1 == v2 ? 0 : v1 > v2 ? 1 : -1; + res = v1 == v2 ? 0 : v1 > v2 ? 1 : -1; + goto item_compare_end; } if (sortinfo->item_compare_float) { - float_T v1 = get_tv_float(tv1); - float_T v2 = get_tv_float(tv2); + const float_T v1 = tv_get_float(tv1); + const float_T v2 = tv_get_float(tv2); - return v1 == v2 ? 0 : v1 > v2 ? 1 : -1; + res = v1 == v2 ? 0 : v1 > v2 ? 1 : -1; + goto item_compare_end; } + char *tofree1 = NULL; + char *tofree2 = NULL; + char *p1; + char *p2; + // encode_tv2string() puts quotes around a string and allocates memory. Don't // do that for string variables. Use a single quote when comparing with // a non-string to do what the docs promise. if (tv1->v_type == VAR_STRING) { if (tv2->v_type != VAR_STRING || sortinfo->item_compare_numeric) { - p1 = (char_u *)"'"; + p1 = "'"; } else { - p1 = tv1->vval.v_string; + p1 = (char *)tv1->vval.v_string; } } else { - tofree1 = p1 = (char_u *) encode_tv2string(tv1, NULL); + tofree1 = p1 = encode_tv2string(tv1, NULL); } if (tv2->v_type == VAR_STRING) { if (tv1->v_type != VAR_STRING || sortinfo->item_compare_numeric) { - p2 = (char_u *)"'"; + p2 = "'"; } else { - p2 = tv2->vval.v_string; + p2 = (char *)tv2->vval.v_string; } } else { - tofree2 = p2 = (char_u *) encode_tv2string(tv2, NULL); + tofree2 = p2 = encode_tv2string(tv2, NULL); } if (p1 == NULL) { - p1 = (char_u *)""; + p1 = ""; } if (p2 == NULL) { - p2 = (char_u *)""; + p2 = ""; } if (!sortinfo->item_compare_numeric) { if (sortinfo->item_compare_ic) { @@ -15851,19 +15268,20 @@ static int item_compare(const void *s1, const void *s2, bool keep_zero) } } else { double n1, n2; - n1 = strtod((char *)p1, (char **)&p1); - n2 = strtod((char *)p2, (char **)&p2); + n1 = strtod(p1, &p1); + n2 = strtod(p2, &p2); res = n1 == n2 ? 0 : n1 > n2 ? 1 : -1; } + xfree(tofree1); + xfree(tofree2); + +item_compare_end: // When the result would be zero, compare the item indexes. Makes the // sort stable. if (res == 0 && !keep_zero) { res = si1->idx > si2->idx ? 1 : -1; } - - xfree(tofree1); - xfree(tofree2); return res; } @@ -15884,7 +15302,7 @@ static int item_compare2(const void *s1, const void *s2, bool keep_zero) typval_T rettv; typval_T argv[3]; int dummy; - char_u *func_name; + const char *func_name; partial_T *partial = sortinfo->item_compare_partial; // shortcut after failure in previous call; compare all items equal @@ -15898,30 +15316,31 @@ static int item_compare2(const void *s1, const void *s2, bool keep_zero) if (partial == NULL) { func_name = sortinfo->item_compare_func; } else { - func_name = partial->pt_name; + func_name = (const char *)partial_name(partial); } + // Copy the values. This is needed to be able to set v_lock to VAR_FIXED // in the copy without changing the original list items. - copy_tv(&si1->item->li_tv, &argv[0]); - copy_tv(&si2->item->li_tv, &argv[1]); + tv_copy(&si1->item->li_tv, &argv[0]); + tv_copy(&si2->item->li_tv, &argv[1]); - rettv.v_type = VAR_UNKNOWN; // clear_tv() uses this - res = call_func(func_name, + rettv.v_type = VAR_UNKNOWN; // tv_clear() uses this + res = call_func((const char_u *)func_name, (int)STRLEN(func_name), - &rettv, 2, argv, 0L, 0L, &dummy, true, + &rettv, 2, argv, NULL, 0L, 0L, &dummy, true, partial, sortinfo->item_compare_selfdict); - clear_tv(&argv[0]); - clear_tv(&argv[1]); + tv_clear(&argv[0]); + tv_clear(&argv[1]); if (res == FAIL) { res = ITEM_COMPARE_FAIL; } else { - res = get_tv_number_chk(&rettv, &sortinfo->item_compare_func_err); + res = tv_get_number_chk(&rettv, &sortinfo->item_compare_func_err); } if (sortinfo->item_compare_func_err) { res = ITEM_COMPARE_FAIL; // return value has wrong type } - clear_tv(&rettv); + tv_clear(&rettv); // When the result would be zero, compare the pointers themselves. Makes // the sort stable. @@ -15959,23 +15378,22 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort) sortinfo_T *old_sortinfo = sortinfo; sortinfo = &info; + const char *const arg_errmsg = (sort + ? N_("sort() argument") + : N_("uniq() argument")); + if (argvars[0].v_type != VAR_LIST) { EMSG2(_(e_listarg), sort ? "sort()" : "uniq()"); } else { l = argvars[0].vval.v_list; - if (l == NULL - || tv_check_lock(l->lv_lock, - (char_u *)(sort - ? N_("sort() argument") - : N_("uniq() argument")), - true)) { + if (l == NULL || tv_check_lock(l->lv_lock, arg_errmsg, TV_TRANSLATE)) { goto theend; } rettv->vval.v_list = l; rettv->v_type = VAR_LIST; ++l->lv_refcount; - len = list_len(l); + len = tv_list_len(l); if (len <= 1) { goto theend; // short list sorts pretty quickly } @@ -15991,20 +15409,20 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort) if (argvars[1].v_type != VAR_UNKNOWN) { /* optional second argument: {func} */ if (argvars[1].v_type == VAR_FUNC) { - info.item_compare_func = argvars[1].vval.v_string; + info.item_compare_func = (const char *)argvars[1].vval.v_string; } else if (argvars[1].v_type == VAR_PARTIAL) { info.item_compare_partial = argvars[1].vval.v_partial; } else { - int error = FALSE; + bool error = false; - i = get_tv_number_chk(&argvars[1], &error); + i = tv_get_number_chk(&argvars[1], &error); if (error) { goto theend; // type error; errmsg already given } if (i == 1) { info.item_compare_ic = true; } else if (argvars[1].v_type != VAR_NUMBER) { - info.item_compare_func = get_tv_string(&argvars[1]); + info.item_compare_func = tv_get_string(&argvars[1]); } else if (i != 0) { EMSG(_(e_invarg)); goto theend; @@ -16013,16 +15431,16 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort) if (*info.item_compare_func == NUL) { // empty string means default sort info.item_compare_func = NULL; - } else if (STRCMP(info.item_compare_func, "n") == 0) { + } else if (strcmp(info.item_compare_func, "n") == 0) { info.item_compare_func = NULL; info.item_compare_numeric = true; - } else if (STRCMP(info.item_compare_func, "N") == 0) { + } else if (strcmp(info.item_compare_func, "N") == 0) { info.item_compare_func = NULL; info.item_compare_numbers = true; - } else if (STRCMP(info.item_compare_func, "f") == 0) { + } else if (strcmp(info.item_compare_func, "f") == 0) { info.item_compare_func = NULL; info.item_compare_float = true; - } else if (STRCMP(info.item_compare_func, "i") == 0) { + } else if (strcmp(info.item_compare_func, "i") == 0) { info.item_compare_func = NULL; info.item_compare_ic = true; } @@ -16074,7 +15492,7 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort) l->lv_len = 0; for (i = 0; i < len; i++) { - list_append(l, ptrs[i].item); + tv_list_append(l, ptrs[i].item); } } } @@ -16110,8 +15528,8 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort) } else { l->lv_last = ptrs[i].item; } - list_fix_watch(l, li); - listitem_free(li); + tv_list_watch_fix(l, li); + tv_list_item_free(li); l->lv_len--; } } @@ -16156,11 +15574,9 @@ static void f_reltimefloat(typval_T *argvars , typval_T *rettv, FunPtr fptr) */ static void f_soundfold(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *s; - rettv->v_type = VAR_STRING; - s = get_tv_string(&argvars[0]); - rettv->vval.v_string = eval_soundfold(s); + const char *const s = tv_get_string(&argvars[0]); + rettv->vval.v_string = (char_u *)eval_soundfold(s); } /* @@ -16168,25 +15584,26 @@ static void f_soundfold(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_spellbadword(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *word = (char_u *)""; + const char *word = ""; hlf_T attr = HLF_COUNT; size_t len = 0; - rettv_list_alloc(rettv); + tv_list_alloc_ret(rettv); if (argvars[0].v_type == VAR_UNKNOWN) { - /* Find the start and length of the badly spelled word. */ - len = spell_move_to(curwin, FORWARD, TRUE, TRUE, &attr); - if (len != 0) - word = get_cursor_pos_ptr(); + // Find the start and length of the badly spelled word. + len = spell_move_to(curwin, FORWARD, true, true, &attr); + if (len != 0) { + word = (char *)get_cursor_pos_ptr(); + } } else if (curwin->w_p_spell && *curbuf->b_s.b_p_spl != NUL) { - char_u *str = get_tv_string_chk(&argvars[0]); + const char *str = tv_get_string_chk(&argvars[0]); int capcol = -1; if (str != NULL) { - /* Check the argument for spelling. */ + // Check the argument for spelling. while (*str != NUL) { - len = spell_check(curwin, str, &attr, &capcol, false); + len = spell_check(curwin, (char_u *)str, &attr, &capcol, false); if (attr != HLF_COUNT) { word = str; break; @@ -16197,14 +15614,13 @@ static void f_spellbadword(typval_T *argvars, typval_T *rettv, FunPtr fptr) } assert(len <= INT_MAX); - list_append_string(rettv->vval.v_list, word, (int)len); - list_append_string(rettv->vval.v_list, - (char_u *)(attr == HLF_SPB ? "bad" : - attr == HLF_SPR ? "rare" : - attr == HLF_SPL ? "local" : - attr == HLF_SPC ? "caps" : - ""), - -1); + tv_list_append_string(rettv->vval.v_list, word, len); + tv_list_append_string(rettv->vval.v_list, + (attr == HLF_SPB ? "bad" + : attr == HLF_SPR ? "rare" + : attr == HLF_SPL ? "local" + : attr == HLF_SPC ? "caps" + : NULL), -1); } /* @@ -16212,39 +15628,40 @@ static void f_spellbadword(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_spellsuggest(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *str; - int typeerr = FALSE; + bool typeerr = false; int maxcount; garray_T ga; listitem_T *li; bool need_capital = false; - rettv_list_alloc(rettv); + tv_list_alloc_ret(rettv); if (curwin->w_p_spell && *curwin->w_s->b_p_spl != NUL) { - str = get_tv_string(&argvars[0]); + const char *const str = tv_get_string(&argvars[0]); if (argvars[1].v_type != VAR_UNKNOWN) { - maxcount = get_tv_number_chk(&argvars[1], &typeerr); - if (maxcount <= 0) + maxcount = tv_get_number_chk(&argvars[1], &typeerr); + if (maxcount <= 0) { return; + } if (argvars[2].v_type != VAR_UNKNOWN) { - need_capital = get_tv_number_chk(&argvars[2], &typeerr); - if (typeerr) + need_capital = tv_get_number_chk(&argvars[2], &typeerr); + if (typeerr) { return; + } } } else maxcount = 25; - spell_suggest_list(&ga, str, maxcount, need_capital, false); + spell_suggest_list(&ga, (char_u *)str, maxcount, need_capital, false); - for (int i = 0; i < ga.ga_len; ++i) { - str = ((char_u **)ga.ga_data)[i]; + for (int i = 0; i < ga.ga_len; i++) { + char *p = ((char **)ga.ga_data)[i]; - li = listitem_alloc(); + li = tv_list_item_alloc(); li->li_tv.v_type = VAR_STRING; li->li_tv.v_lock = 0; - li->li_tv.vval.v_string = str; - list_append(rettv->vval.v_list, li); + li->li_tv.vval.v_string = (char_u *)p; + tv_list_append(rettv->vval.v_list, li); } ga_clear(&ga); } @@ -16252,64 +15669,69 @@ static void f_spellsuggest(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_split(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *str; - char_u *end; - char_u *pat = NULL; regmatch_T regmatch; - char_u patbuf[NUMBUFLEN]; char_u *save_cpo; int match; colnr_T col = 0; - int keepempty = FALSE; - int typeerr = FALSE; + bool keepempty = false; + bool typeerr = false; /* Make 'cpoptions' empty, the 'l' flag should not be used here. */ save_cpo = p_cpo; p_cpo = (char_u *)""; - str = get_tv_string(&argvars[0]); + const char *str = tv_get_string(&argvars[0]); + const char *pat = NULL; + char patbuf[NUMBUFLEN]; if (argvars[1].v_type != VAR_UNKNOWN) { - pat = get_tv_string_buf_chk(&argvars[1], patbuf); - if (pat == NULL) - typeerr = TRUE; - if (argvars[2].v_type != VAR_UNKNOWN) - keepempty = get_tv_number_chk(&argvars[2], &typeerr); + pat = tv_get_string_buf_chk(&argvars[1], patbuf); + if (pat == NULL) { + typeerr = true; + } + if (argvars[2].v_type != VAR_UNKNOWN) { + keepempty = (bool)tv_get_number_chk(&argvars[2], &typeerr); + } + } + if (pat == NULL || *pat == NUL) { + pat = "[\\x01- ]\\+"; } - if (pat == NULL || *pat == NUL) - pat = (char_u *)"[\\x01- ]\\+"; - rettv_list_alloc(rettv); + tv_list_alloc_ret(rettv); if (typeerr) return; - regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING); + regmatch.regprog = vim_regcomp((char_u *)pat, RE_MAGIC + RE_STRING); if (regmatch.regprog != NULL) { regmatch.rm_ic = FALSE; while (*str != NUL || keepempty) { - if (*str == NUL) - match = FALSE; /* empty item at the end */ - else - match = vim_regexec_nl(®match, str, col); - if (match) - end = regmatch.startp[0]; - else - end = str + STRLEN(str); + if (*str == NUL) { + match = false; // Empty item at the end. + } else { + match = vim_regexec_nl(®match, (char_u *)str, col); + } + const char *end; + if (match) { + end = (const char *)regmatch.startp[0]; + } else { + end = str + strlen(str); + } if (keepempty || end > str || (rettv->vval.v_list->lv_len > 0 - && *str != NUL && match && end < - regmatch.endp[0])) { - list_append_string(rettv->vval.v_list, str, (int)(end - str)); + && *str != NUL + && match + && end < (const char *)regmatch.endp[0])) { + tv_list_append_string(rettv->vval.v_list, str, end - str); } if (!match) break; - /* Advance to just after the match. */ - if (regmatch.endp[0] > str) + // Advance to just after the match. + if (regmatch.endp[0] > (char_u *)str) { col = 0; - else { - /* Don't get stuck at the same match. */ + } else { + // Don't get stuck at the same match. col = (*mb_ptr2len)(regmatch.endp[0]); } - str = regmatch.endp[0]; + str = (const char *)regmatch.endp[0]; } vim_regfree(regmatch.regprog); @@ -16323,11 +15745,16 @@ static void f_split(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_str2float(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *p = skipwhite(get_tv_string(&argvars[0])); + char_u *p = skipwhite((const char_u *)tv_get_string(&argvars[0])); + bool isneg = (*p == '-'); - if (*p == '+') + if (*p == '+' || *p == '-') { p = skipwhite(p + 1); - (void) string2float((char *) p, &rettv->vval.v_float); + } + (void)string2float((char *)p, &rettv->vval.v_float); + if (isneg) { + rettv->vval.v_float *= -1; + } rettv->v_type = VAR_FLOAT; } @@ -16335,37 +15762,45 @@ static void f_str2float(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_str2nr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int base = 10; - char_u *p; - long n; + varnumber_T n; int what; if (argvars[1].v_type != VAR_UNKNOWN) { - base = get_tv_number(&argvars[1]); + base = tv_get_number(&argvars[1]); if (base != 2 && base != 8 && base != 10 && base != 16) { EMSG(_(e_invarg)); return; } } - p = skipwhite(get_tv_string(&argvars[0])); - if (*p == '+') { + char_u *p = skipwhite((const char_u *)tv_get_string(&argvars[0])); + bool isneg = (*p == '-'); + if (*p == '+' || *p == '-') { p = skipwhite(p + 1); } switch (base) { - case 2: - what = STR2NR_BIN + STR2NR_FORCE; + case 2: { + what = STR2NR_BIN | STR2NR_FORCE; break; - case 8: - what = STR2NR_OCT + STR2NR_FORCE; + } + case 8: { + what = STR2NR_OCT | STR2NR_FORCE; break; - case 16: - what = STR2NR_HEX + STR2NR_FORCE; + } + case 16: { + what = STR2NR_HEX | STR2NR_FORCE; break; - default: + } + default: { what = 0; + } } vim_str2nr(p, NULL, NULL, what, &n, NULL, 0); - rettv->vval.v_number = n; + if (isneg) { + rettv->vval.v_number = -n; + } else { + rettv->vval.v_number = n; + } } /* @@ -16373,17 +15808,16 @@ static void f_str2nr(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_strftime(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u result_buf[256]; time_t seconds; - char_u *p; rettv->v_type = VAR_STRING; - p = get_tv_string(&argvars[0]); - if (argvars[1].v_type == VAR_UNKNOWN) + char *p = (char *)tv_get_string(&argvars[0]); + if (argvars[1].v_type == VAR_UNKNOWN) { seconds = time(NULL); - else - seconds = (time_t)get_tv_number(&argvars[1]); + } else { + seconds = (time_t)tv_get_number(&argvars[1]); + } struct tm curtime; struct tm *curtime_ptr = os_localtime_r(&seconds, &curtime); @@ -16397,23 +15831,27 @@ static void f_strftime(typval_T *argvars, typval_T *rettv, FunPtr fptr) conv.vc_type = CONV_NONE; enc = enc_locale(); convert_setup(&conv, p_enc, enc); - if (conv.vc_type != CONV_NONE) - p = string_convert(&conv, p, NULL); - if (p != NULL) - (void)strftime((char *)result_buf, sizeof(result_buf), - (char *)p, curtime_ptr); - else + if (conv.vc_type != CONV_NONE) { + p = (char *)string_convert(&conv, (char_u *)p, NULL); + } + char result_buf[256]; + if (p != NULL) { + (void)strftime(result_buf, sizeof(result_buf), p, curtime_ptr); + } else { result_buf[0] = NUL; + } - if (conv.vc_type != CONV_NONE) + if (conv.vc_type != CONV_NONE) { xfree(p); + } convert_setup(&conv, enc, p_enc); - if (conv.vc_type != CONV_NONE) - rettv->vval.v_string = string_convert(&conv, result_buf, NULL); - else - rettv->vval.v_string = vim_strsave(result_buf); + if (conv.vc_type != CONV_NONE) { + rettv->vval.v_string = string_convert(&conv, (char_u *)result_buf, NULL); + } else { + rettv->vval.v_string = (char_u *)xstrdup(result_buf); + } - /* Release conversion descriptors */ + // Release conversion descriptors. convert_setup(&conv, NULL, NULL); xfree(enc); } @@ -16422,33 +15860,28 @@ static void f_strftime(typval_T *argvars, typval_T *rettv, FunPtr fptr) // "strgetchar()" function static void f_strgetchar(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *str; - int len; - int error = false; - int charidx; - rettv->vval.v_number = -1; - str = get_tv_string_chk(&argvars[0]); + + const char *const str = tv_get_string_chk(&argvars[0]); if (str == NULL) { return; } - len = (int)STRLEN(str); - charidx = get_tv_number_chk(&argvars[1], &error); + bool error = false; + varnumber_T charidx = tv_get_number_chk(&argvars[1], &error); if (error) { return; } - { - int byteidx = 0; + const size_t len = STRLEN(str); + size_t byteidx = 0; - while (charidx >= 0 && byteidx < len) { - if (charidx == 0) { - rettv->vval.v_number = mb_ptr2char(str + byteidx); - break; - } - charidx--; - byteidx += mb_cptr2len(str + byteidx); + while (charidx >= 0 && byteidx < len) { + if (charidx == 0) { + rettv->vval.v_number = mb_ptr2char((const char_u *)str + byteidx); + break; } + charidx--; + byteidx += MB_CPTR2LEN((const char_u *)str + byteidx); } } @@ -16457,32 +15890,33 @@ static void f_strgetchar(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_stridx(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u buf[NUMBUFLEN]; - char_u *needle; - char_u *haystack; - char_u *save_haystack; - char_u *pos; - int start_idx; - - needle = get_tv_string_chk(&argvars[1]); - save_haystack = haystack = get_tv_string_buf_chk(&argvars[0], buf); rettv->vval.v_number = -1; - if (needle == NULL || haystack == NULL) - return; /* type error; errmsg already given */ + + char buf[NUMBUFLEN]; + const char *const needle = tv_get_string_chk(&argvars[1]); + const char *haystack = tv_get_string_buf_chk(&argvars[0], buf); + const char *const haystack_start = haystack; + if (needle == NULL || haystack == NULL) { + return; // Type error; errmsg already given. + } if (argvars[2].v_type != VAR_UNKNOWN) { - int error = FALSE; + bool error = false; - start_idx = get_tv_number_chk(&argvars[2], &error); - if (error || start_idx >= (int)STRLEN(haystack)) + const ptrdiff_t start_idx = (ptrdiff_t)tv_get_number_chk(&argvars[2], + &error); + if (error || start_idx >= (ptrdiff_t)strlen(haystack)) { return; - if (start_idx >= 0) + } + if (start_idx >= 0) { haystack += start_idx; + } } - pos = (char_u *)strstr((char *)haystack, (char *)needle); - if (pos != NULL) - rettv->vval.v_number = (varnumber_T)(pos - save_haystack); + const char *pos = strstr(haystack, needle); + if (pos != NULL) { + rettv->vval.v_number = (varnumber_T)(pos - haystack_start); + } } /* @@ -16499,8 +15933,7 @@ static void f_string(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_strlen(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - rettv->vval.v_number = (varnumber_T)(STRLEN( - get_tv_string(&argvars[0]))); + rettv->vval.v_number = (varnumber_T)strlen(tv_get_string(&argvars[0])); } /* @@ -16508,21 +15941,21 @@ static void f_strlen(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_strchars(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *s = get_tv_string(&argvars[0]); + const char *s = tv_get_string(&argvars[0]); int skipcc = 0; varnumber_T len = 0; - int (*func_mb_ptr2char_adv)(char_u **pp); + int (*func_mb_ptr2char_adv)(const char_u **pp); if (argvars[1].v_type != VAR_UNKNOWN) { - skipcc = get_tv_number_chk(&argvars[1], NULL); + skipcc = tv_get_number_chk(&argvars[1], NULL); } if (skipcc < 0 || skipcc > 1) { EMSG(_(e_invarg)); } else { func_mb_ptr2char_adv = skipcc ? mb_ptr2char_adv : mb_cptr2char_adv; while (*s != NUL) { - func_mb_ptr2char_adv(&s); - ++len; + func_mb_ptr2char_adv((const char_u **)&s); + len++; } rettv->vval.v_number = len; } @@ -16533,13 +15966,14 @@ static void f_strchars(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_strdisplaywidth(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *s = get_tv_string(&argvars[0]); + const char *const s = tv_get_string(&argvars[0]); int col = 0; - if (argvars[1].v_type != VAR_UNKNOWN) - col = get_tv_number(&argvars[1]); + if (argvars[1].v_type != VAR_UNKNOWN) { + col = tv_get_number(&argvars[1]); + } - rettv->vval.v_number = (varnumber_T)(linetabsize_col(col, s) - col); + rettv->vval.v_number = (varnumber_T)(linetabsize_col(col, (char_u *)s) - col); } /* @@ -16547,44 +15981,40 @@ static void f_strdisplaywidth(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_strwidth(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *s = get_tv_string(&argvars[0]); + const char *const s = tv_get_string(&argvars[0]); - rettv->vval.v_number = (varnumber_T) mb_string2cells(s); + rettv->vval.v_number = (varnumber_T)mb_string2cells((const char_u *)s); } // "strcharpart()" function -static void f_strcharpart(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *p; - int nchar; - int nbyte = 0; - int charlen; - int len = 0; - int slen; - int error = false; - - p = get_tv_string(&argvars[0]); - slen = (int)STRLEN(p); +static void f_strcharpart(typval_T *argvars, typval_T *rettv, FunPtr fptr) +{ + const char *const p = tv_get_string(&argvars[0]); + const size_t slen = STRLEN(p); - nchar = get_tv_number_chk(&argvars[1], &error); + int nbyte = 0; + bool error = false; + varnumber_T nchar = tv_get_number_chk(&argvars[1], &error); if (!error) { if (nchar > 0) { - while (nchar > 0 && nbyte < slen) { - nbyte += mb_cptr2len(p + nbyte); + while (nchar > 0 && (size_t)nbyte < slen) { + nbyte += MB_CPTR2LEN((const char_u *)p + nbyte); nchar--; } } else { nbyte = nchar; } } + int len = 0; if (argvars[2].v_type != VAR_UNKNOWN) { - charlen = get_tv_number(&argvars[2]); - while (charlen > 0 && nbyte + len < slen) { + int charlen = tv_get_number(&argvars[2]); + while (charlen > 0 && nbyte + len < (int)slen) { int off = nbyte + len; if (off < 0) { len += 1; } else { - len += mb_cptr2len(p + off); + len += (size_t)MB_CPTR2LEN((const char_u *)p + off); } charlen--; } @@ -16597,17 +16027,17 @@ static void f_strcharpart(typval_T *argvars, typval_T *rettv, FunPtr fptr) { if (nbyte < 0) { len += nbyte; nbyte = 0; - } else if (nbyte > slen) { + } else if ((size_t)nbyte > slen) { nbyte = slen; } if (len < 0) { len = 0; - } else if (nbyte + len > slen) { + } else if (nbyte + len > (int)slen) { len = slen - nbyte; } rettv->v_type = VAR_STRING; - rettv->vval.v_string = vim_strnsave(p + nbyte, len); + rettv->vval.v_string = (char_u *)xstrndup(p + nbyte, (size_t)len); } /* @@ -16615,39 +16045,37 @@ static void f_strcharpart(typval_T *argvars, typval_T *rettv, FunPtr fptr) { */ static void f_strpart(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *p; - int n; - int len; - int slen; - int error = FALSE; + bool error = false; - p = get_tv_string(&argvars[0]); - slen = (int)STRLEN(p); + const char *const p = tv_get_string(&argvars[0]); + const size_t slen = strlen(p); - n = get_tv_number_chk(&argvars[1], &error); - if (error) + varnumber_T n = tv_get_number_chk(&argvars[1], &error); + varnumber_T len; + if (error) { len = 0; - else if (argvars[2].v_type != VAR_UNKNOWN) - len = get_tv_number(&argvars[2]); - else - len = slen - n; /* default len: all bytes that are available. */ + } else if (argvars[2].v_type != VAR_UNKNOWN) { + len = tv_get_number(&argvars[2]); + } else { + len = slen - n; // Default len: all bytes that are available. + } - /* - * Only return the overlap between the specified part and the actual - * string. - */ + // Only return the overlap between the specified part and the actual + // string. if (n < 0) { len += n; n = 0; - } else if (n > slen) + } else if (n > (varnumber_T)slen) { n = slen; - if (len < 0) + } + if (len < 0) { len = 0; - else if (n + len > slen) + } else if (n + len > (varnumber_T)slen) { len = slen - n; + } rettv->v_type = VAR_STRING; - rettv->vval.v_string = vim_strnsave(p + n, len); + rettv->vval.v_string = (char_u *)xmemdupz(p + n, (size_t)len); } /* @@ -16655,45 +16083,46 @@ static void f_strpart(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_strridx(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u buf[NUMBUFLEN]; - char_u *needle; - char_u *haystack; - char_u *rest; - char_u *lastmatch = NULL; - int haystack_len, end_idx; - - needle = get_tv_string_chk(&argvars[1]); - haystack = get_tv_string_buf_chk(&argvars[0], buf); + char buf[NUMBUFLEN]; + const char *const needle = tv_get_string_chk(&argvars[1]); + const char *const haystack = tv_get_string_buf_chk(&argvars[0], buf); rettv->vval.v_number = -1; - if (needle == NULL || haystack == NULL) - return; /* type error; errmsg already given */ + if (needle == NULL || haystack == NULL) { + return; // Type error; errmsg already given. + } - haystack_len = (int)STRLEN(haystack); + const size_t haystack_len = STRLEN(haystack); + ptrdiff_t end_idx; if (argvars[2].v_type != VAR_UNKNOWN) { - /* Third argument: upper limit for index */ - end_idx = get_tv_number_chk(&argvars[2], NULL); - if (end_idx < 0) - return; /* can never find a match */ - } else - end_idx = haystack_len; + // Third argument: upper limit for index. + end_idx = (ptrdiff_t)tv_get_number_chk(&argvars[2], NULL); + if (end_idx < 0) { + return; // Can never find a match. + } + } else { + end_idx = (ptrdiff_t)haystack_len; + } + const char *lastmatch = NULL; if (*needle == NUL) { - /* Empty string matches past the end. */ + // Empty string matches past the end. lastmatch = haystack + end_idx; } else { - for (rest = haystack; *rest != NUL; ++rest) { - rest = (char_u *)strstr((char *)rest, (char *)needle); - if (rest == NULL || rest > haystack + end_idx) + for (const char *rest = haystack; *rest != NUL; rest++) { + rest = strstr(rest, needle); + if (rest == NULL || rest > haystack + end_idx) { break; + } lastmatch = rest; } } - if (lastmatch == NULL) + if (lastmatch == NULL) { rettv->vval.v_number = -1; - else + } else { rettv->vval.v_number = (varnumber_T)(lastmatch - haystack); + } } /* @@ -16702,7 +16131,7 @@ static void f_strridx(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_strtrans(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_STRING; - rettv->vval.v_string = transstr(get_tv_string(&argvars[0])); + rettv->vval.v_string = transstr((char_u *)tv_get_string(&argvars[0])); } /* @@ -16710,18 +16139,22 @@ static void f_strtrans(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_submatch(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - int error = FALSE; - int no = (int)get_tv_number_chk(&argvars[0], &error); + bool error = false; + int no = (int)tv_get_number_chk(&argvars[0], &error); if (error) { return; } + if (no < 0 || no >= NSUBEXP) { + EMSGN(_("E935: invalid submatch number: %d"), no); + return; + } int retList = 0; if (argvars[1].v_type != VAR_UNKNOWN) { - retList = get_tv_number_chk(&argvars[1], &error); + retList = tv_get_number_chk(&argvars[1], &error); if (error) { - return; + return; } } @@ -16739,40 +16172,47 @@ static void f_submatch(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_substitute(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u patbuf[NUMBUFLEN]; - char_u subbuf[NUMBUFLEN]; - char_u flagsbuf[NUMBUFLEN]; + char patbuf[NUMBUFLEN]; + char subbuf[NUMBUFLEN]; + char flagsbuf[NUMBUFLEN]; + + const char *const str = tv_get_string_chk(&argvars[0]); + const char *const pat = tv_get_string_buf_chk(&argvars[1], patbuf); + const char *sub = NULL; + const char *const flg = tv_get_string_buf_chk(&argvars[3], flagsbuf); - char_u *str = get_tv_string_chk(&argvars[0]); - char_u *pat = get_tv_string_buf_chk(&argvars[1], patbuf); - char_u *sub = get_tv_string_buf_chk(&argvars[2], subbuf); - char_u *flg = get_tv_string_buf_chk(&argvars[3], flagsbuf); + typval_T *expr = NULL; + if (tv_is_func(argvars[2])) { + expr = &argvars[2]; + } else { + sub = tv_get_string_buf_chk(&argvars[2], subbuf); + } rettv->v_type = VAR_STRING; - if (str == NULL || pat == NULL || sub == NULL || flg == NULL) + if (str == NULL || pat == NULL || (sub == NULL && expr == NULL) + || flg == NULL) { rettv->vval.v_string = NULL; - else - rettv->vval.v_string = do_string_sub(str, pat, sub, flg); + } else { + rettv->vval.v_string = do_string_sub((char_u *)str, (char_u *)pat, + (char_u *)sub, expr, (char_u *)flg); + } } -/* - * "synID(lnum, col, trans)" function - */ +/// "synID(lnum, col, trans)" function static void f_synID(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - int id = 0; - long lnum; - long col; - int trans; - int transerr = FALSE; + // -1 on type error (both) + const linenr_T lnum = tv_get_lnum(argvars); + const colnr_T col = (colnr_T)tv_get_number(&argvars[1]) - 1; - lnum = get_tv_lnum(argvars); /* -1 on type error */ - col = get_tv_number(&argvars[1]) - 1; /* -1 on type error */ - trans = get_tv_number_chk(&argvars[2], &transerr); + bool transerr = false; + const int trans = tv_get_number_chk(&argvars[2], &transerr); + int id = 0; if (!transerr && lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count - && col >= 0 && col < (long)STRLEN(ml_get(lnum))) - id = syn_get_id(curwin, lnum, (colnr_T)col, trans, NULL, FALSE); + && col >= 0 && (size_t)col < STRLEN(ml_get(lnum))) { + id = syn_get_id(curwin, lnum, col, trans, NULL, false); + } rettv->vval.v_number = id; } @@ -16782,20 +16222,16 @@ static void f_synID(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_synIDattr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *p = NULL; - int id; - char_u *what; - char_u *mode; - char_u modebuf[NUMBUFLEN]; + const int id = (int)tv_get_number(&argvars[0]); + const char *const what = tv_get_string(&argvars[1]); int modec; - - id = get_tv_number(&argvars[0]); - what = get_tv_string(&argvars[1]); if (argvars[2].v_type != VAR_UNKNOWN) { - mode = get_tv_string_buf(&argvars[2], modebuf); + char modebuf[NUMBUFLEN]; + const char *const mode = tv_get_string_buf(&argvars[2], modebuf); modec = TOLOWER_ASC(mode[0]); - if (modec != 'c' && modec != 'g') - modec = 0; /* replace invalid with current */ + if (modec != 'c' && modec != 'g') { + modec = 0; // Replace invalid with current. + } } else if (ui_rgb_attached()) { modec = 'g'; } else { @@ -16803,54 +16239,56 @@ static void f_synIDattr(typval_T *argvars, typval_T *rettv, FunPtr fptr) } + const char *p = NULL; switch (TOLOWER_ASC(what[0])) { - case 'b': - if (TOLOWER_ASC(what[1]) == 'g') /* bg[#] */ + case 'b': { + if (TOLOWER_ASC(what[1]) == 'g') { // bg[#] + p = highlight_color(id, what, modec); + } else { // bold + p = highlight_has_attr(id, HL_BOLD, modec); + } + break; + } + case 'f': { // fg[#] or font p = highlight_color(id, what, modec); - else /* bold */ - p = highlight_has_attr(id, HL_BOLD, modec); - break; - - case 'f': /* fg[#] or font */ - p = highlight_color(id, what, modec); - break; - - case 'i': - if (TOLOWER_ASC(what[1]) == 'n') /* inverse */ + break; + } + case 'i': { + if (TOLOWER_ASC(what[1]) == 'n') { // inverse + p = highlight_has_attr(id, HL_INVERSE, modec); + } else { // italic + p = highlight_has_attr(id, HL_ITALIC, modec); + } + break; + } + case 'n': { // name + p = get_highlight_name(NULL, id - 1); + break; + } + case 'r': { // reverse p = highlight_has_attr(id, HL_INVERSE, modec); - else /* italic */ - p = highlight_has_attr(id, HL_ITALIC, modec); - break; - - case 'n': /* name */ - p = get_highlight_name(NULL, id - 1); - break; - - case 'r': /* reverse */ - p = highlight_has_attr(id, HL_INVERSE, modec); - break; - - case 's': - if (TOLOWER_ASC(what[1]) == 'p') /* sp[#] */ - p = highlight_color(id, what, modec); - else /* standout */ - p = highlight_has_attr(id, HL_STANDOUT, modec); - break; - - case 'u': - if (STRLEN(what) <= 5 || TOLOWER_ASC(what[5]) != 'c') - /* underline */ - p = highlight_has_attr(id, HL_UNDERLINE, modec); - else - /* undercurl */ - p = highlight_has_attr(id, HL_UNDERCURL, modec); - break; + break; + } + case 's': { + if (TOLOWER_ASC(what[1]) == 'p') { // sp[#] + p = highlight_color(id, what, modec); + } else { // standout + p = highlight_has_attr(id, HL_STANDOUT, modec); + } + break; + } + case 'u': { + if (STRLEN(what) <= 5 || TOLOWER_ASC(what[5]) != 'c') { // underline + p = highlight_has_attr(id, HL_UNDERLINE, modec); + } else { // undercurl + p = highlight_has_attr(id, HL_UNDERCURL, modec); + } + break; + } } - if (p != NULL) - p = vim_strsave(p); rettv->v_type = VAR_STRING; - rettv->vval.v_string = p; + rettv->vval.v_string = (char_u *)(p == NULL ? p : xstrdup(p)); } /* @@ -16858,14 +16296,13 @@ static void f_synIDattr(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_synIDtrans(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - int id; + int id = tv_get_number(&argvars[0]); - id = get_tv_number(&argvars[0]); - - if (id > 0) + if (id > 0) { id = syn_get_final_id(id); - else + } else { id = 0; + } rettv->vval.v_number = id; } @@ -16875,8 +16312,6 @@ static void f_synIDtrans(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_synconcealed(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - long lnum; - long col; int syntax_flags = 0; int cchar; int matchid = 0; @@ -16885,15 +16320,16 @@ static void f_synconcealed(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->v_type = VAR_LIST; rettv->vval.v_list = NULL; - lnum = get_tv_lnum(argvars); /* -1 on type error */ - col = get_tv_number(&argvars[1]) - 1; /* -1 on type error */ + // -1 on type error (both) + const linenr_T lnum = tv_get_lnum(argvars); + const colnr_T col = (colnr_T)tv_get_number(&argvars[1]) - 1; memset(str, NUL, sizeof(str)); - rettv_list_alloc(rettv); + tv_list_alloc_ret(rettv); if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count && col >= 0 - && col <= (long)STRLEN(ml_get(lnum)) && curwin->w_p_cole > 0) { - (void)syn_get_id(curwin, lnum, col, FALSE, NULL, FALSE); + && (size_t)col <= STRLEN(ml_get(lnum)) && curwin->w_p_cole > 0) { + (void)syn_get_id(curwin, lnum, col, false, NULL, false); syntax_flags = get_syntax_info(&matchid); // get the conceal character @@ -16911,10 +16347,10 @@ static void f_synconcealed(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } - list_append_number(rettv->vval.v_list, (syntax_flags & HL_CONCEAL) != 0); + tv_list_append_number(rettv->vval.v_list, (syntax_flags & HL_CONCEAL) != 0); // -1 to auto-determine strlen - list_append_string(rettv->vval.v_list, str, -1); - list_append_number(rettv->vval.v_list, matchid); + tv_list_append_string(rettv->vval.v_list, (const char *)str, -1); + tv_list_append_number(rettv->vval.v_list, matchid); } /* @@ -16922,56 +16358,35 @@ static void f_synconcealed(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_synstack(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - long lnum; - long col; - rettv->v_type = VAR_LIST; rettv->vval.v_list = NULL; - lnum = get_tv_lnum(argvars); /* -1 on type error */ - col = get_tv_number(&argvars[1]) - 1; /* -1 on type error */ + // -1 on type error (both) + const linenr_T lnum = tv_get_lnum(argvars); + const colnr_T col = (colnr_T)tv_get_number(&argvars[1]) - 1; if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count && col >= 0 - && col <= (long)STRLEN(ml_get(lnum))) { - rettv_list_alloc(rettv); - (void)syn_get_id(curwin, lnum, (colnr_T)col, FALSE, NULL, TRUE); + && (size_t)col <= STRLEN(ml_get(lnum))) { + tv_list_alloc_ret(rettv); + (void)syn_get_id(curwin, lnum, col, false, NULL, true); int id; int i = 0; while ((id = syn_get_stack_item(i++)) >= 0) { - list_append_number(rettv->vval.v_list, id); + tv_list_append_number(rettv->vval.v_list, id); } } } -static list_T* string_to_list(char_u *str, size_t len, bool keepempty) +static list_T *string_to_list(const char *str, size_t len, const bool keepempty) { - list_T *list = list_alloc(); - - // Copy each line to a list element using NL as the delimiter. - for (size_t i = 0; i < len; i++) { - char_u *start = str + i; - size_t line_len = (char_u *) xmemscan(start, NL, len - i) - start; - i += line_len; - - // Don't use a str function to copy res as it may contains NULs. - char_u *s = xmemdupz(start, line_len); - memchrsub(s, NUL, NL, line_len); // Replace NUL with NL to avoid truncation - - listitem_T *li = listitem_alloc(); - li->li_tv.v_type = VAR_STRING; - li->li_tv.v_lock = 0; - li->li_tv.vval.v_string = s; - list_append(list, li); - } - - // Optionally retain final newline, if present - if (keepempty && str[len-1] == NL) { - list_append_string(list, (char_u*)"", 0); + if (!keepempty && str[len - 1] == NL) { + len--; } - + list_T *const list = tv_list_alloc(); + encode_list_write(list, str, len); return list; } @@ -16986,16 +16401,20 @@ static void get_system_output_as_rettv(typval_T *argvars, typval_T *rettv, } // get input to the shell command (if any), and its length - ssize_t input_len; - char *input = (char *) save_tv_as_string(&argvars[1], &input_len, false); + ptrdiff_t input_len; + char *input = save_tv_as_string(&argvars[1], &input_len, false); if (input_len < 0) { assert(input == NULL); return; } // get shell command to execute - char **argv = tv_to_argv(&argvars[0], NULL, NULL); + bool executable = true; + char **argv = tv_to_argv(&argvars[0], NULL, &executable); if (!argv) { + if (!executable) { + set_vim_var_nr(VV_SHELL_ERROR, (long)-1); + } xfree(input); return; // Already did emsg. } @@ -17012,7 +16431,7 @@ static void get_system_output_as_rettv(typval_T *argvars, typval_T *rettv, if (res == NULL) { if (retlist) { // return an empty list when there's no output - rettv_list_alloc(rettv); + tv_list_alloc_ret(rettv); } else { rettv->vval.v_string = (char_u *) xstrdup(""); } @@ -17022,9 +16441,9 @@ static void get_system_output_as_rettv(typval_T *argvars, typval_T *rettv, if (retlist) { int keepempty = 0; if (argvars[1].v_type != VAR_UNKNOWN && argvars[2].v_type != VAR_UNKNOWN) { - keepempty = get_tv_number(&argvars[2]); + keepempty = tv_get_number(&argvars[2]); } - rettv->vval.v_list = string_to_list((char_u *) res, nread, keepempty != 0); + rettv->vval.v_list = string_to_list(res, nread, (bool)keepempty); rettv->vval.v_list->lv_refcount++; rettv->v_type = VAR_LIST; @@ -17067,20 +16486,20 @@ static void f_systemlist(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_tabpagebuflist(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - tabpage_T *tp; win_T *wp = NULL; - if (argvars[0].v_type == VAR_UNKNOWN) + if (argvars[0].v_type == VAR_UNKNOWN) { wp = firstwin; - else { - tp = find_tabpage((int)get_tv_number(&argvars[0])); - if (tp != NULL) + } else { + tabpage_T *const tp = find_tabpage((int)tv_get_number(&argvars[0])); + if (tp != NULL) { wp = (tp == curtab) ? firstwin : tp->tp_firstwin; + } } if (wp != NULL) { - rettv_list_alloc(rettv); + tv_list_alloc_ret(rettv); while (wp != NULL) { - list_append_number(rettv->vval.v_list, wp->w_buffer->b_fnum); + tv_list_append_number(rettv->vval.v_list, wp->w_buffer->b_fnum); wp = wp->w_next; } } @@ -17093,19 +16512,20 @@ static void f_tabpagebuflist(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_tabpagenr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int nr = 1; - char_u *arg; if (argvars[0].v_type != VAR_UNKNOWN) { - arg = get_tv_string_chk(&argvars[0]); + const char *const arg = tv_get_string_chk(&argvars[0]); nr = 0; if (arg != NULL) { - if (STRCMP(arg, "$") == 0) + if (strcmp(arg, "$") == 0) { nr = tabpage_index(NULL) - 1; - else + } else { EMSG2(_(e_invexpr2), arg); + } } - } else + } else { nr = tabpage_index(curtab); + } rettv->vval.v_number = nr; } @@ -17119,19 +16539,19 @@ static int get_winnr(tabpage_T *tp, typval_T *argvar) win_T *twin; int nr = 1; win_T *wp; - char_u *arg; twin = (tp == curtab) ? curwin : tp->tp_curwin; if (argvar->v_type != VAR_UNKNOWN) { - arg = get_tv_string_chk(argvar); - if (arg == NULL) - nr = 0; /* type error; errmsg already given */ - else if (STRCMP(arg, "$") == 0) + const char *const arg = tv_get_string_chk(argvar); + if (arg == NULL) { + nr = 0; // Type error; errmsg already given. + } else if (strcmp(arg, "$") == 0) { twin = (tp == curtab) ? lastwin : tp->tp_lastwin; - else if (STRCMP(arg, "#") == 0) { + } else if (strcmp(arg, "#") == 0) { twin = (tp == curtab) ? prevwin : tp->tp_prevwin; - if (twin == NULL) + if (twin == NULL) { nr = 0; + } } else { EMSG2(_(e_invexpr2), arg); nr = 0; @@ -17157,13 +16577,12 @@ static int get_winnr(tabpage_T *tp, typval_T *argvar) static void f_tabpagewinnr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int nr = 1; - tabpage_T *tp; - - tp = find_tabpage((int)get_tv_number(&argvars[0])); - if (tp == NULL) + tabpage_T *const tp = find_tabpage((int)tv_get_number(&argvars[0])); + if (tp == NULL) { nr = 0; - else + } else { nr = get_winnr(tp, &argvars[1]); + } rettv->vval.v_number = nr; } @@ -17173,16 +16592,16 @@ static void f_tabpagewinnr(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_tagfiles(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *fname; + char *fname; tagname_T tn; - rettv_list_alloc(rettv); + tv_list_alloc_ret(rettv); fname = xmalloc(MAXPATHL); - int first = TRUE; - while (get_tagfname(&tn, first, fname) == OK) { - list_append_string(rettv->vval.v_list, fname, -1); - first = FALSE; + bool first = true; + while (get_tagfname(&tn, first, (char_u *)fname) == OK) { + tv_list_append_string(rettv->vval.v_list, fname, -1); + first = false; } tagname_free(&tn); @@ -17194,15 +16613,19 @@ static void f_tagfiles(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_taglist(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *tag_pattern; - - tag_pattern = get_tv_string(&argvars[0]); + const char *const tag_pattern = tv_get_string(&argvars[0]); - rettv->vval.v_number = FALSE; - if (*tag_pattern == NUL) + rettv->vval.v_number = false; + if (*tag_pattern == NUL) { return; + } - (void)get_tags(rettv_list_alloc(rettv), tag_pattern); + const char *fname = NULL; + if (argvars[1].v_type != VAR_UNKNOWN) { + fname = tv_get_string(&argvars[1]); + } + (void)get_tags(tv_list_alloc_ret(rettv), (char_u *)tag_pattern, + (char_u *)fname); } /* @@ -17226,7 +16649,7 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; } - char *cmd; + const char *cmd; bool executable = true; char **argv = tv_to_argv(&argvars[0], &cmd, &executable); if (!argv) { @@ -17244,15 +16667,15 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, FunPtr fptr) Callback on_stdout = CALLBACK_NONE, on_stderr = CALLBACK_NONE, on_exit = CALLBACK_NONE; dict_T *job_opts = NULL; - char *cwd = "."; + const char *cwd = "."; if (argvars[1].v_type == VAR_DICT) { job_opts = argvars[1].vval.v_dict; - char *new_cwd = (char *)get_dict_string(job_opts, "cwd", false); - if (new_cwd && strlen(new_cwd) > 0) { + const char *const new_cwd = tv_dict_get_string(job_opts, "cwd", false); + if (new_cwd && *new_cwd != NUL) { cwd = new_cwd; // The new cwd must be a directory. - if (!os_isdir((char_u *)cwd)) { + if (!os_isdir((const char_u *)cwd)) { EMSG2(_(e_invarg2), "expected valid directory"); shell_free_argv(argv); return; @@ -17289,13 +16712,15 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, FunPtr fptr) // at this point the buffer has no terminal instance associated yet, so unset // the 'swapfile' option to ensure no swap file will be created curbuf->b_p_swf = false; - (void)setfname(curbuf, (uint8_t *)buf, NULL, true); + (void)setfname(curbuf, (char_u *)buf, NULL, true); // Save the job id and pid in b:terminal_job_{id,pid} - Error err; - dict_set_value(curbuf->b_vars, cstr_as_string("terminal_job_id"), - INTEGER_OBJ(rettv->vval.v_number), false, false, &err); - dict_set_value(curbuf->b_vars, cstr_as_string("terminal_job_pid"), - INTEGER_OBJ(pid), false, false, &err); + Error err = ERROR_INIT; + dict_set_var(curbuf->b_vars, cstr_as_string("terminal_job_id"), + INTEGER_OBJ(rettv->vval.v_number), false, false, &err); + api_clear_error(&err); + dict_set_var(curbuf->b_vars, cstr_as_string("terminal_job_pid"), + INTEGER_OBJ(pid), false, false, &err); + api_clear_error(&err); Terminal *term = terminal_open(topts); data->term = term; @@ -17304,7 +16729,17 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; } -static bool callback_from_typval(Callback *callback, typval_T *arg) +// "test_garbagecollect_now()" function +static void f_test_garbagecollect_now(typval_T *argvars, + typval_T *rettv, FunPtr fptr) +{ + // This is dangerous, any Lists and Dicts used internally may be freed + // while still in use. + garbage_collect(true); +} + +bool callback_from_typval(Callback *const callback, typval_T *const arg) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT { if (arg->v_type == VAR_PARTIAL && arg->vval.v_partial != NULL) { callback->data.partial = arg->vval.v_partial; @@ -17324,53 +16759,33 @@ static bool callback_from_typval(Callback *callback, typval_T *arg) return true; } - /// Unref/free callback -static void callback_free(Callback *callback) +void callback_free(Callback *const callback) + FUNC_ATTR_NONNULL_ALL { switch (callback->type) { - case kCallbackFuncref: + case kCallbackFuncref: { func_unref(callback->data.funcref); xfree(callback->data.funcref); break; - - case kCallbackPartial: + } + case kCallbackPartial: { partial_unref(callback->data.partial); break; - - case kCallbackNone: + } + case kCallbackNone: { break; - - default: + } + default: { abort(); + } } callback->type = kCallbackNone; } -static bool callback_equal(Callback *cb1, Callback *cb2) -{ - if (cb1->type != cb2->type) { - return false; - } - switch (cb1->type) { - case kCallbackFuncref: - return STRCMP(cb1->data.funcref, cb2->data.funcref) == 0; - - case kCallbackPartial: - // FIXME: this is inconsistent with tv_equal but is needed for precision - // maybe change dictwatcheradd to return a watcher id instead? - return cb1->data.partial == cb2->data.partial; - - case kCallbackNone: - return true; - - default: - abort(); - } -} - -static bool callback_call(Callback *callback, int argcount_in, - typval_T *argvars_in, typval_T *rettv) +bool callback_call(Callback *const callback, const int argcount_in, + typval_T *const argvars_in, typval_T *const rettv) + FUNC_ATTR_NONNULL_ALL { partial_T *partial; char_u *name; @@ -17382,7 +16797,7 @@ static bool callback_call(Callback *callback, int argcount_in, case kCallbackPartial: partial = callback->data.partial; - name = partial->pt_name; + name = partial_name(partial); break; case kCallbackNone: @@ -17395,7 +16810,7 @@ static bool callback_call(Callback *callback, int argcount_in, int dummy; return call_func(name, (int)STRLEN(name), rettv, argcount_in, argvars_in, - curwin->w_cursor.lnum, curwin->w_cursor.lnum, &dummy, + NULL, curwin->w_cursor.lnum, curwin->w_cursor.lnum, &dummy, true, partial, NULL); } @@ -17422,11 +16837,82 @@ static bool set_ref_in_callback(Callback *callback, int copyID, return false; } +static void add_timer_info(typval_T *rettv, timer_T *timer) +{ + list_T *list = rettv->vval.v_list; + dict_T *dict = tv_dict_alloc(); + + tv_list_append_dict(list, dict); + tv_dict_add_nr(dict, S_LEN("id"), timer->timer_id); + tv_dict_add_nr(dict, S_LEN("time"), timer->timeout); + tv_dict_add_nr(dict, S_LEN("paused"), timer->paused); + + tv_dict_add_nr(dict, S_LEN("repeat"), + (timer->repeat_count < 0 ? -1 : timer->repeat_count)); + + dictitem_T *di = tv_dict_item_alloc("callback"); + if (tv_dict_add(dict, di) == FAIL) { + xfree(di); + return; + } + + if (timer->callback.type == kCallbackPartial) { + di->di_tv.v_type = VAR_PARTIAL; + di->di_tv.vval.v_partial = timer->callback.data.partial; + timer->callback.data.partial->pt_refcount++; + } else if (timer->callback.type == kCallbackFuncref) { + di->di_tv.v_type = VAR_FUNC; + di->di_tv.vval.v_string = vim_strsave(timer->callback.data.funcref); + } + di->di_tv.v_lock = 0; +} + +static void add_timer_info_all(typval_T *rettv) +{ + timer_T *timer; + map_foreach_value(timers, timer, { + if (!timer->stopped) { + add_timer_info(rettv, timer); + } + }) +} + +/// "timer_info([timer])" function +static void f_timer_info(typval_T *argvars, typval_T *rettv, FunPtr fptr) +{ + tv_list_alloc_ret(rettv); + if (argvars[0].v_type != VAR_UNKNOWN) { + if (argvars[0].v_type != VAR_NUMBER) { + EMSG(_(e_number_exp)); + return; + } + timer_T *timer = pmap_get(uint64_t)(timers, tv_get_number(&argvars[0])); + if (timer != NULL && !timer->stopped) { + add_timer_info(rettv, timer); + } + } else { + add_timer_info_all(rettv); + } +} + +/// "timer_pause(timer, paused)" function +static void f_timer_pause(typval_T *argvars, typval_T *unused, FunPtr fptr) +{ + if (argvars[0].v_type != VAR_NUMBER) { + EMSG(_(e_number_exp)); + return; + } + int paused = (bool)tv_get_number(&argvars[1]); + timer_T *timer = pmap_get(uint64_t)(timers, tv_get_number(&argvars[0])); + if (timer != NULL) { + timer->paused = paused; + } +} /// "timer_start(timeout, callback, opts)" function static void f_timer_start(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - long timeout = get_tv_number(&argvars[0]); + const long timeout = tv_get_number(&argvars[0]); timer_T *timer; int repeat = 1; dict_T *dict; @@ -17436,11 +16922,12 @@ static void f_timer_start(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (argvars[2].v_type != VAR_UNKNOWN) { if (argvars[2].v_type != VAR_DICT || (dict = argvars[2].vval.v_dict) == NULL) { - EMSG2(_(e_invarg2), get_tv_string(&argvars[2])); + EMSG2(_(e_invarg2), tv_get_string(&argvars[2])); return; } - if (dict_find(dict, (char_u *)"repeat", -1) != NULL) { - repeat = get_dict_number(dict, "repeat"); + dictitem_T *const di = tv_dict_find(dict, S_LEN("repeat")); + if (di != NULL) { + repeat = tv_get_number(&di->di_tv); if (repeat == 0) { repeat = 1; } @@ -17455,6 +16942,7 @@ static void f_timer_start(typval_T *argvars, typval_T *rettv, FunPtr fptr) timer = xmalloc(sizeof *timer); timer->refcount = 1; timer->stopped = false; + timer->paused = false; timer->repeat_count = repeat; timer->timeout = timeout; timer->timer_id = last_timer_id++; @@ -17464,8 +16952,7 @@ static void f_timer_start(typval_T *argvars, typval_T *rettv, FunPtr fptr) timer->tw.events = multiqueue_new_child(main_loop.events); // if main loop is blocked, don't queue up multiple events timer->tw.blockable = true; - time_watcher_start(&timer->tw, timer_due_cb, timeout, - timeout * (repeat != 1)); + time_watcher_start(&timer->tw, timer_due_cb, timeout, timeout); pmap_put(uint64_t)(timers, timer->timer_id, timer); rettv->vval.v_number = timer->timer_id; @@ -17480,7 +16967,7 @@ static void f_timer_stop(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; } - timer_T *timer = pmap_get(uint64_t)(timers, get_tv_number(&argvars[0])); + timer_T *timer = pmap_get(uint64_t)(timers, tv_get_number(&argvars[0])); if (timer == NULL) { return; @@ -17489,28 +16976,32 @@ static void f_timer_stop(typval_T *argvars, typval_T *rettv, FunPtr fptr) timer_stop(timer); } +static void f_timer_stopall(typval_T *argvars, typval_T *unused, FunPtr fptr) +{ + timer_stop_all(); +} + // invoked on the main loop static void timer_due_cb(TimeWatcher *tw, void *data) { timer_T *timer = (timer_T *)data; - if (timer->stopped) { + if (timer->stopped || timer->paused) { return; } + timer->refcount++; // if repeat was negative repeat forever if (timer->repeat_count >= 0 && --timer->repeat_count == 0) { timer_stop(timer); } - typval_T argv[2]; - init_tv(argv); + typval_T argv[2] = { TV_INITIAL_VALUE, TV_INITIAL_VALUE }; argv[0].v_type = VAR_NUMBER; argv[0].vval.v_number = timer->timer_id; - typval_T rettv; + typval_T rettv = TV_INITIAL_VALUE; - init_tv(&rettv); callback_call(&timer->callback, 1, argv, &rettv); - clear_tv(&rettv); + tv_clear(&rettv); if (!timer->stopped && timer->timeout == 0) { // special case: timeout=0 means the callback will be @@ -17550,7 +17041,7 @@ static void timer_decref(timer_T *timer) } } -void timer_teardown(void) +static void timer_stop_all(void) { timer_T *timer; map_foreach_value(timers, timer, { @@ -17558,35 +17049,19 @@ void timer_teardown(void) }) } +void timer_teardown(void) +{ + timer_stop_all(); +} + /* * "tolower(string)" function */ static void f_tolower(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *p = vim_strsave(get_tv_string(&argvars[0])); rettv->v_type = VAR_STRING; - rettv->vval.v_string = p; - - while (*p != NUL) { - int l; - - if (enc_utf8) { - int c, lc; - - c = utf_ptr2char(p); - lc = utf_tolower(c); - l = utf_ptr2len(p); - /* TODO: reallocate string when byte count changes. */ - if (utf_char2len(lc) == l) - utf_char2bytes(lc, p); - p += l; - } else if (has_mbyte && (l = (*mb_ptr2len)(p)) > 1) - p += l; /* skip multi-byte character */ - else { - *p = TOLOWER_LOC(*p); /* note that tolower() can be a macro */ - ++p; - } - } + rettv->vval.v_string = (char_u *)strcase_save(tv_get_string(&argvars[0]), + false); } /* @@ -17595,7 +17070,8 @@ static void f_tolower(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_toupper(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_STRING; - rettv->vval.v_string = strup_save(get_tv_string(&argvars[0])); + rettv->vval.v_string = (char_u *)strcase_save(tv_get_string(&argvars[0]), + true); } /* @@ -17603,77 +17079,71 @@ static void f_toupper(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_tr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *in_str; - char_u *fromstr; - char_u *tostr; - char_u *p; - int inlen; - int fromlen; - int tolen; - int idx; - char_u *cpstr; - int cplen; - int first = TRUE; - char_u buf[NUMBUFLEN]; - char_u buf2[NUMBUFLEN]; - garray_T ga; + char buf[NUMBUFLEN]; + char buf2[NUMBUFLEN]; - in_str = get_tv_string(&argvars[0]); - fromstr = get_tv_string_buf_chk(&argvars[1], buf); - tostr = get_tv_string_buf_chk(&argvars[2], buf2); + const char *in_str = tv_get_string(&argvars[0]); + const char *fromstr = tv_get_string_buf_chk(&argvars[1], buf); + const char *tostr = tv_get_string_buf_chk(&argvars[2], buf2); - /* Default return value: empty string. */ + // Default return value: empty string. rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; - if (fromstr == NULL || tostr == NULL) - return; /* type error; errmsg already given */ + if (fromstr == NULL || tostr == NULL) { + return; // Type error; errmsg already given. + } + garray_T ga; ga_init(&ga, (int)sizeof(char), 80); - if (!has_mbyte) - /* not multi-byte: fromstr and tostr must be the same length */ - if (STRLEN(fromstr) != STRLEN(tostr)) { -error: - EMSG2(_(e_invarg2), fromstr); - ga_clear(&ga); - return; + if (!has_mbyte) { + // Not multi-byte: fromstr and tostr must be the same length. + if (strlen(fromstr) != strlen(tostr)) { + goto error; } + } - /* fromstr and tostr have to contain the same number of chars */ + // fromstr and tostr have to contain the same number of chars. + bool first = true; while (*in_str != NUL) { if (has_mbyte) { - inlen = (*mb_ptr2len)(in_str); - cpstr = in_str; - cplen = inlen; - idx = 0; - for (p = fromstr; *p != NUL; p += fromlen) { - fromlen = (*mb_ptr2len)(p); + const char *cpstr = in_str; + const int inlen = (*mb_ptr2len)((const char_u *)in_str); + int cplen = inlen; + int idx = 0; + int fromlen; + for (const char *p = fromstr; *p != NUL; p += fromlen) { + fromlen = (*mb_ptr2len)((const char_u *)p); if (fromlen == inlen && STRNCMP(in_str, p, inlen) == 0) { + int tolen; for (p = tostr; *p != NUL; p += tolen) { - tolen = (*mb_ptr2len)(p); + tolen = (*mb_ptr2len)((const char_u *)p); if (idx-- == 0) { cplen = tolen; - cpstr = p; + cpstr = (char *)p; break; } } - if (*p == NUL) /* tostr is shorter than fromstr */ + if (*p == NUL) { // tostr is shorter than fromstr. goto error; + } break; } - ++idx; + idx++; } if (first && cpstr == in_str) { - /* Check that fromstr and tostr have the same number of - * (multi-byte) characters. Done only once when a character - * of in_str doesn't appear in fromstr. */ - first = FALSE; - for (p = tostr; *p != NUL; p += tolen) { - tolen = (*mb_ptr2len)(p); - --idx; + // Check that fromstr and tostr have the same number of + // (multi-byte) characters. Done only once when a character + // of in_str doesn't appear in fromstr. + first = false; + int tolen; + for (const char *p = tostr; *p != NUL; p += tolen) { + tolen = (*mb_ptr2len)((const char_u *)p); + idx--; } - if (idx != 0) + if (idx != 0) { goto error; + } } ga_grow(&ga, cplen); @@ -17682,13 +17152,14 @@ error: in_str += inlen; } else { - /* When not using multi-byte chars we can do it faster. */ - p = vim_strchr(fromstr, *in_str); - if (p != NULL) + // When not using multi-byte chars we can do it faster. + const char *const p = strchr(fromstr, *in_str); + if (p != NULL) { ga_append(&ga, tostr[p - fromstr]); - else + } else { ga_append(&ga, *in_str); - ++in_str; + } + in_str++; } } @@ -17696,6 +17167,11 @@ error: ga_append(&ga, NUL); rettv->vval.v_string = ga.ga_data; + return; +error: + EMSG2(_(e_invarg2), fromstr); + ga_clear(&ga); + return; } /* @@ -17741,20 +17217,18 @@ static void f_type(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_undofile(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_STRING; - { - char_u *fname = get_tv_string(&argvars[0]); + const char *const fname = tv_get_string(&argvars[0]); - if (*fname == NUL) { - /* If there is no file name there will be no undo file. */ - rettv->vval.v_string = NULL; - } else { - char *ffname = FullName_save((char *)fname, false); + if (*fname == NUL) { + // If there is no file name there will be no undo file. + rettv->vval.v_string = NULL; + } else { + char *ffname = FullName_save(fname, false); - if (ffname != NULL) { - rettv->vval.v_string = (char_u *)u_get_undo_file_name(ffname, false); - } - xfree(ffname); + if (ffname != NULL) { + rettv->vval.v_string = (char_u *)u_get_undo_file_name(ffname, false); } + xfree(ffname); } } @@ -17763,22 +17237,22 @@ static void f_undofile(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_undotree(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - rettv_dict_alloc(rettv); + tv_dict_alloc_ret(rettv); dict_T *dict = rettv->vval.v_dict; list_T *list; - dict_add_nr_str(dict, "synced", (long)curbuf->b_u_synced, NULL); - dict_add_nr_str(dict, "seq_last", curbuf->b_u_seq_last, NULL); - dict_add_nr_str(dict, "save_last", - (long)curbuf->b_u_save_nr_last, NULL); - dict_add_nr_str(dict, "seq_cur", curbuf->b_u_seq_cur, NULL); - dict_add_nr_str(dict, "time_cur", (long)curbuf->b_u_time_cur, NULL); - dict_add_nr_str(dict, "save_cur", (long)curbuf->b_u_save_nr_cur, NULL); + tv_dict_add_nr(dict, S_LEN("synced"), (varnumber_T)curbuf->b_u_synced); + tv_dict_add_nr(dict, S_LEN("seq_last"), (varnumber_T)curbuf->b_u_seq_last); + tv_dict_add_nr(dict, S_LEN("save_last"), + (varnumber_T)curbuf->b_u_save_nr_last); + tv_dict_add_nr(dict, S_LEN("seq_cur"), (varnumber_T)curbuf->b_u_seq_cur); + tv_dict_add_nr(dict, S_LEN("time_cur"), (varnumber_T)curbuf->b_u_time_cur); + tv_dict_add_nr(dict, S_LEN("save_cur"), (varnumber_T)curbuf->b_u_save_nr_cur); - list = list_alloc(); + list = tv_list_alloc(); u_eval_tree(curbuf->b_u_oldhead, list); - dict_add_list(dict, "entries", list); + tv_dict_add_list(dict, S_LEN("entries"), list); } /* @@ -17837,7 +17311,7 @@ static void f_wildmenumode(typval_T *argvars, typval_T *rettv, FunPtr fptr) /// "win_findbuf()" function static void f_win_findbuf(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - rettv_list_alloc(rettv); + tv_list_alloc_ret(rettv); win_findbuf(argvars, rettv->vval.v_list); } @@ -17856,7 +17330,7 @@ static void f_win_gotoid(typval_T *argvars, typval_T *rettv, FunPtr fptr) /// "win_id2tabwin()" function static void f_win_id2tabwin(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - rettv_list_alloc(rettv); + tv_list_alloc_ret(rettv); win_id2tabwin(argvars, rettv->vval.v_list); } @@ -17951,36 +17425,37 @@ static void f_winrestcmd(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_winrestview(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - dict_T *dict; + dict_T *dict; if (argvars[0].v_type != VAR_DICT - || (dict = argvars[0].vval.v_dict) == NULL) - EMSG(_(e_invarg)); - else { - if (dict_find(dict, (char_u *)"lnum", -1) != NULL) { - curwin->w_cursor.lnum = get_dict_number(dict, "lnum"); + || (dict = argvars[0].vval.v_dict) == NULL) { + emsgf(_(e_invarg)); + } else { + dictitem_T *di; + if ((di = tv_dict_find(dict, S_LEN("lnum"))) != NULL) { + curwin->w_cursor.lnum = tv_get_number(&di->di_tv); } - if (dict_find(dict, (char_u *)"col", -1) != NULL) { - curwin->w_cursor.col = get_dict_number(dict, "col"); + if ((di = tv_dict_find(dict, S_LEN("col"))) != NULL) { + curwin->w_cursor.col = tv_get_number(&di->di_tv); } - if (dict_find(dict, (char_u *)"coladd", -1) != NULL) { - curwin->w_cursor.coladd = get_dict_number(dict, "coladd"); + if ((di = tv_dict_find(dict, S_LEN("coladd"))) != NULL) { + curwin->w_cursor.coladd = tv_get_number(&di->di_tv); } - if (dict_find(dict, (char_u *)"curswant", -1) != NULL) { - curwin->w_curswant = get_dict_number(dict, "curswant"); + if ((di = tv_dict_find(dict, S_LEN("curswant"))) != NULL) { + curwin->w_curswant = tv_get_number(&di->di_tv); curwin->w_set_curswant = false; } - if (dict_find(dict, (char_u *)"topline", -1) != NULL) { - set_topline(curwin, get_dict_number(dict, "topline")); + if ((di = tv_dict_find(dict, S_LEN("topline"))) != NULL) { + set_topline(curwin, tv_get_number(&di->di_tv)); } - if (dict_find(dict, (char_u *)"topfill", -1) != NULL) { - curwin->w_topfill = get_dict_number(dict, "topfill"); + if ((di = tv_dict_find(dict, S_LEN("topfill"))) != NULL) { + curwin->w_topfill = tv_get_number(&di->di_tv); } - if (dict_find(dict, (char_u *)"leftcol", -1) != NULL) { - curwin->w_leftcol = get_dict_number(dict, "leftcol"); + if ((di = tv_dict_find(dict, S_LEN("leftcol"))) != NULL) { + curwin->w_leftcol = tv_get_number(&di->di_tv); } - if (dict_find(dict, (char_u *)"skipcol", -1) != NULL) { - curwin->w_skipcol = get_dict_number(dict, "skipcol"); + if ((di = tv_dict_find(dict, S_LEN("skipcol"))) != NULL) { + curwin->w_skipcol = tv_get_number(&di->di_tv); } check_cursor(); @@ -18003,45 +17478,103 @@ static void f_winsaveview(typval_T *argvars, typval_T *rettv, FunPtr fptr) { dict_T *dict; - rettv_dict_alloc(rettv); + tv_dict_alloc_ret(rettv); dict = rettv->vval.v_dict; - dict_add_nr_str(dict, "lnum", (long)curwin->w_cursor.lnum, NULL); - dict_add_nr_str(dict, "col", (long)curwin->w_cursor.col, NULL); - dict_add_nr_str(dict, "coladd", (long)curwin->w_cursor.coladd, NULL); + tv_dict_add_nr(dict, S_LEN("lnum"), (varnumber_T)curwin->w_cursor.lnum); + tv_dict_add_nr(dict, S_LEN("col"), (varnumber_T)curwin->w_cursor.col); + tv_dict_add_nr(dict, S_LEN("coladd"), (varnumber_T)curwin->w_cursor.coladd); update_curswant(); - dict_add_nr_str(dict, "curswant", (long)curwin->w_curswant, NULL); + tv_dict_add_nr(dict, S_LEN("curswant"), (varnumber_T)curwin->w_curswant); - dict_add_nr_str(dict, "topline", (long)curwin->w_topline, NULL); - dict_add_nr_str(dict, "topfill", (long)curwin->w_topfill, NULL); - dict_add_nr_str(dict, "leftcol", (long)curwin->w_leftcol, NULL); - dict_add_nr_str(dict, "skipcol", (long)curwin->w_skipcol, NULL); + tv_dict_add_nr(dict, S_LEN("topline"), (varnumber_T)curwin->w_topline); + tv_dict_add_nr(dict, S_LEN("topfill"), (varnumber_T)curwin->w_topfill); + tv_dict_add_nr(dict, S_LEN("leftcol"), (varnumber_T)curwin->w_leftcol); + tv_dict_add_nr(dict, S_LEN("skipcol"), (varnumber_T)curwin->w_skipcol); } /// Writes list of strings to file -static bool write_list(FILE *fd, list_T *list, bool binary) +/// +/// @param fp File to write to. +/// @param[in] list List to write. +/// @param[in] binary Whether to write in binary mode. +/// +/// @return true in case of success, false otherwise. +static bool write_list(FileDescriptor *const fp, const list_T *const list, + const bool binary) { - int ret = true; - - for (listitem_T *li = list->lv_first; li != NULL; li = li->li_next) { - for (char_u *s = get_tv_string(&li->li_tv); *s != NUL; ++s) { - if (putc(*s == '\n' ? NUL : *s, fd) == EOF) { - ret = false; - break; + int error = 0; + for (const listitem_T *li = list->lv_first; li != NULL; li = li->li_next) { + const char *const s = tv_get_string_chk(&li->li_tv); + if (s == NULL) { + return false; + } + const char *hunk_start = s; + for (const char *p = hunk_start;; p++) { + if (*p == NUL || *p == NL) { + if (p != hunk_start) { + const ptrdiff_t written = file_write(fp, hunk_start, + (size_t)(p - hunk_start)); + if (written < 0) { + error = (int)written; + goto write_list_error; + } + } + if (*p == NUL) { + break; + } else { + hunk_start = p + 1; + const ptrdiff_t written = file_write(fp, (char[]){ NUL }, 1); + if (written < 0) { + error = (int)written; + break; + } + } } } if (!binary || li->li_next != NULL) { - if (putc('\n', fd) == EOF) { - ret = false; - break; + const ptrdiff_t written = file_write(fp, "\n", 1); + if (written < 0) { + error = (int)written; + goto write_list_error; } } - if (ret == false) { - EMSG(_(e_write)); - break; + } + if ((error = file_flush(fp)) != 0) { + goto write_list_error; + } + return true; +write_list_error: + emsgf(_("E80: Error while writing: %s"), os_strerror(error)); + return false; +} + +/// Initializes a static list with 10 items. +void init_static_list(staticList10_T *sl) +{ + list_T *l = &sl->sl_list; + + memset(sl, 0, sizeof(staticList10_T)); + l->lv_first = &sl->sl_items[0]; + l->lv_last = &sl->sl_items[9]; + l->lv_refcount = DO_NOT_FREE_CNT; + l->lv_lock = VAR_FIXED; + sl->sl_list.lv_len = 10; + + for (int i = 0; i < 10; i++) { + listitem_T *li = &sl->sl_items[i]; + + if (i == 0) { + li->li_prev = NULL; + } else { + li->li_prev = li - 1; + } + if (i == 9) { + li->li_next = NULL; + } else { + li->li_next = li + 1; } } - return ret; } /// Saves a typval_T as a string. @@ -18053,7 +17586,7 @@ static bool write_list(FILE *fd, list_T *list, bool binary) /// @param[in] endnl If true, the output will end in a newline (if a list). /// @returns an allocated string if `tv` represents a VimL string, list, or /// number; NULL otherwise. -static char_u *save_tv_as_string(typval_T *tv, ssize_t *len, bool endnl) +static char *save_tv_as_string(typval_T *tv, ptrdiff_t *const len, bool endnl) FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL { if (tv->v_type == VAR_UNKNOWN) { @@ -18061,34 +17594,33 @@ static char_u *save_tv_as_string(typval_T *tv, ssize_t *len, bool endnl) return NULL; } - // For types other than list, let get_tv_string_buf_chk() get the value or + // For types other than list, let tv_get_string_buf_chk() get the value or // print an error. if (tv->v_type != VAR_LIST) { - char_u *ret = get_tv_string_chk(tv); - if (ret && (*len = STRLEN(ret))) { - ret = vim_strsave(ret); + const char *ret = tv_get_string_chk(tv); + if (ret && (*len = strlen(ret))) { + return xmemdupz(ret, (size_t)(*len)); } else { - ret = NULL; *len = -1; + return NULL; } - return ret; } // Pre-calculate the resulting length. *len = 0; list_T *list = tv->vval.v_list; for (listitem_T *li = list->lv_first; li != NULL; li = li->li_next) { - *len += STRLEN(get_tv_string(&li->li_tv)) + 1; + *len += strlen(tv_get_string(&li->li_tv)) + 1; } if (*len == 0) { return NULL; } - char_u *ret = xmalloc(*len + endnl); - char_u *end = ret; + char *ret = xmalloc(*len + endnl); + char *end = ret; for (listitem_T *li = list->lv_first; li != NULL; li = li->li_next) { - for (char_u *s = get_tv_string(&li->li_tv); *s != NUL; s++) { + for (const char *s = tv_get_string(&li->li_tv); *s != NUL; s++) { *end++ = (*s == '\n') ? NUL : *s; } if (endnl || li->li_next != NULL) { @@ -18117,7 +17649,7 @@ static void f_winwidth(typval_T *argvars, typval_T *rettv, FunPtr fptr) /// "wordcount()" function static void f_wordcount(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - rettv_dict_alloc(rettv); + tv_dict_alloc_ret(rettv); cursor_pos_info(rettv->vval.v_dict); } @@ -18140,28 +17672,50 @@ static void f_writefile(typval_T *argvars, typval_T *rettv, FunPtr fptr) bool binary = false; bool append = false; + bool do_fsync = !!p_fs; if (argvars[2].v_type != VAR_UNKNOWN) { - if (vim_strchr(get_tv_string(&argvars[2]), 'b')) { - binary = true; + const char *const flags = tv_get_string_chk(&argvars[2]); + if (flags == NULL) { + return; } - if (vim_strchr(get_tv_string(&argvars[2]), 'a')) { - append = true; + for (const char *p = flags; *p; p++) { + switch (*p) { + case 'b': { binary = true; break; } + case 'a': { append = true; break; } + case 's': { do_fsync = true; break; } + case 'S': { do_fsync = false; break; } + default: { + // Using %s, p and not %c, *p to preserve multibyte characters + emsgf(_("E5060: Unknown flag: %s"), p); + return; + } + } } } - // Always open the file in binary mode, library functions have a mind of - // their own about CR-LF conversion. - char_u *fname = get_tv_string(&argvars[1]); - FILE *fd; - if (*fname == NUL || (fd = mch_fopen((char *)fname, - append ? APPENDBIN : WRITEBIN)) == NULL) { - EMSG2(_(e_notcreate), *fname == NUL ? (char_u *)_("<empty>") : fname); - rettv->vval.v_number = -1; + char buf[NUMBUFLEN]; + const char *const fname = tv_get_string_buf_chk(&argvars[1], buf); + if (fname == NULL) { + return; + } + FileDescriptor fp; + int error; + rettv->vval.v_number = -1; + if (*fname == NUL) { + EMSG(_("E482: Can't open file with an empty name")); + } else if ((error = file_open(&fp, fname, + ((append ? kFileAppend : kFileTruncate) + | kFileCreate), 0666)) != 0) { + emsgf(_("E482: Can't open file %s for writing: %s"), + fname, os_strerror(error)); } else { - if (write_list(fd, argvars[0].vval.v_list, binary) == false) { - rettv->vval.v_number = -1; + if (write_list(&fp, argvars[0].vval.v_list, binary)) { + rettv->vval.v_number = 0; + } + if ((error = file_close(&fp, do_fsync)) != 0) { + emsgf(_("E80: Error when closing file %s: %s"), + fname, os_strerror(error)); } - fclose(fd); } } /* @@ -18169,82 +17723,96 @@ static void f_writefile(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_xor(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - rettv->vval.v_number = get_tv_number_chk(&argvars[0], NULL) - ^ get_tv_number_chk(&argvars[1], NULL); + rettv->vval.v_number = tv_get_number_chk(&argvars[0], NULL) + ^ tv_get_number_chk(&argvars[1], NULL); } -/* - * Translate a String variable into a position. - * Returns NULL when there is an error. - */ -static pos_T * -var2fpos ( - typval_T *varp, - int dollar_lnum, /* TRUE when $ is last line */ - int *fnum /* set to fnum for '0, 'A, etc. */ -) +/// Translate a VimL object into a position +/// +/// Accepts VAR_LIST and VAR_STRING objects. Does not give an error for invalid +/// type. +/// +/// @param[in] tv Object to translate. +/// @param[in] dollar_lnum True when "$" is last line. +/// @param[out] ret_fnum Set to fnum for marks. +/// +/// @return Pointer to position or NULL in case of error (e.g. invalid type). +pos_T *var2fpos(const typval_T *const tv, const int dollar_lnum, + int *const ret_fnum) + FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL { - char_u *name; static pos_T pos; pos_T *pp; - /* Argument can be [lnum, col, coladd]. */ - if (varp->v_type == VAR_LIST) { + // Argument can be [lnum, col, coladd]. + if (tv->v_type == VAR_LIST) { list_T *l; int len; - int error = FALSE; - listitem_T *li; + bool error = false; + listitem_T *li; - l = varp->vval.v_list; - if (l == NULL) + l = tv->vval.v_list; + if (l == NULL) { return NULL; + } - /* Get the line number */ - pos.lnum = list_find_nr(l, 0L, &error); - if (error || pos.lnum <= 0 || pos.lnum > curbuf->b_ml.ml_line_count) - return NULL; /* invalid line number */ + // Get the line number. + pos.lnum = tv_list_find_nr(l, 0L, &error); + if (error || pos.lnum <= 0 || pos.lnum > curbuf->b_ml.ml_line_count) { + // Invalid line number. + return NULL; + } - /* Get the column number */ - pos.col = list_find_nr(l, 1L, &error); - if (error) + // Get the column number. + pos.col = tv_list_find_nr(l, 1L, &error); + if (error) { return NULL; + } len = (long)STRLEN(ml_get(pos.lnum)); - /* We accept "$" for the column number: last column. */ - li = list_find(l, 1L); + // We accept "$" for the column number: last column. + li = tv_list_find(l, 1L); if (li != NULL && li->li_tv.v_type == VAR_STRING && li->li_tv.vval.v_string != NULL - && STRCMP(li->li_tv.vval.v_string, "$") == 0) + && STRCMP(li->li_tv.vval.v_string, "$") == 0) { pos.col = len + 1; + } - /* Accept a position up to the NUL after the line. */ - if (pos.col == 0 || (int)pos.col > len + 1) - return NULL; /* invalid column number */ - --pos.col; + // Accept a position up to the NUL after the line. + if (pos.col == 0 || (int)pos.col > len + 1) { + // Invalid column number. + return NULL; + } + pos.col--; - /* Get the virtual offset. Defaults to zero. */ - pos.coladd = list_find_nr(l, 2L, &error); - if (error) + // Get the virtual offset. Defaults to zero. + pos.coladd = tv_list_find_nr(l, 2L, &error); + if (error) { pos.coladd = 0; + } return &pos; } - name = get_tv_string_chk(varp); - if (name == NULL) + const char *const name = tv_get_string_chk(tv); + if (name == NULL) { return NULL; - if (name[0] == '.') /* cursor */ + } + if (name[0] == '.') { // Cursor. return &curwin->w_cursor; - if (name[0] == 'v' && name[1] == NUL) { /* Visual start */ - if (VIsual_active) + } + if (name[0] == 'v' && name[1] == NUL) { // Visual start. + if (VIsual_active) { return &VIsual; + } return &curwin->w_cursor; } - if (name[0] == '\'') { /* mark */ - pp = getmark_buf_fnum(curbuf, name[1], FALSE, fnum); - if (pp == NULL || pp == (pos_T *)-1 || pp->lnum <= 0) + if (name[0] == '\'') { // Mark. + pp = getmark_buf_fnum(curbuf, (uint8_t)name[1], false, ret_fnum); + if (pp == NULL || pp == (pos_T *)-1 || pp->lnum <= 0) { return NULL; + } return pp; } @@ -18297,32 +17865,37 @@ static int list2fpos(typval_T *arg, pos_T *posp, int *fnump, colnr_T *curswantp) return FAIL; if (fnump != NULL) { - n = list_find_nr(l, i++, NULL); /* fnum */ - if (n < 0) + n = tv_list_find_nr(l, i++, NULL); // fnum + if (n < 0) { return FAIL; - if (n == 0) - n = curbuf->b_fnum; /* current buffer */ + } + if (n == 0) { + n = curbuf->b_fnum; // Current buffer. + } *fnump = n; } - n = list_find_nr(l, i++, NULL); /* lnum */ - if (n < 0) + n = tv_list_find_nr(l, i++, NULL); // lnum + if (n < 0) { return FAIL; + } posp->lnum = n; - n = list_find_nr(l, i++, NULL); /* col */ - if (n < 0) + n = tv_list_find_nr(l, i++, NULL); // col + if (n < 0) { return FAIL; + } posp->col = n; - n = list_find_nr(l, i, NULL); // off - if (n < 0) + n = tv_list_find_nr(l, i, NULL); // off + if (n < 0) { posp->coladd = 0; - else + } else { posp->coladd = n; + } if (curswantp != NULL) { - *curswantp = list_find_nr(l, i + 1, NULL); // curswant + *curswantp = tv_list_find_nr(l, i + 1, NULL); // curswant } return OK; @@ -18333,15 +17906,16 @@ static int list2fpos(typval_T *arg, pos_T *posp, int *fnump, colnr_T *curswantp) * Advance "arg" to the first character after the name. * Return 0 for error. */ -static int get_env_len(char_u **arg) +static int get_env_len(const char_u **arg) { - char_u *p; int len; - for (p = *arg; vim_isIDc(*p); ++p) - ; - if (p == *arg) /* no name found */ + const char_u *p; + for (p = *arg; vim_isIDc(*p); p++) { + } + if (p == *arg) { // No name found. return 0; + } len = (int)(p - *arg); *arg = p; @@ -18351,11 +17925,12 @@ static int get_env_len(char_u **arg) // Get the length of the name of a function or internal variable. // "arg" is advanced to the first non-white character after the name. // Return 0 if something is wrong. -static int get_id_len(char_u **arg) { - char_u *p; +static int get_id_len(const char **const arg) +{ int len; // Find the end of the name. + const char *p; for (p = *arg; eval_isnamec(*p); p++) { if (*p == ':') { // "s:" is start of "s:var", but "n:" is not and can be used in @@ -18372,7 +17947,7 @@ static int get_id_len(char_u **arg) { } len = (int)(p - *arg); - *arg = skipwhite(p); + *arg = (const char *)skipwhite((const char_u *)p); return len; } @@ -18386,18 +17961,18 @@ static int get_id_len(char_u **arg) { * If the name contains 'magic' {}'s, expand them and return the * expanded name in an allocated string via 'alias' - caller must free. */ -static int get_name_len(char_u **arg, char_u **alias, int evaluate, int verbose) +static int get_name_len(const char **const arg, + char **alias, + int evaluate, + int verbose) { int len; - char_u *p; - char_u *expr_start; - char_u *expr_end; *alias = NULL; /* default to no alias */ - if ((*arg)[0] == K_SPECIAL && (*arg)[1] == KS_EXTRA - && (*arg)[2] == (int)KE_SNR) { - /* hard coded <SNR>, already translated */ + if ((*arg)[0] == (char)K_SPECIAL && (*arg)[1] == (char)KS_EXTRA + && (*arg)[2] == (char)KE_SNR) { + // Hard coded <SNR>, already translated. *arg += 3; return get_id_len(arg) + 3; } @@ -18407,17 +17982,17 @@ static int get_name_len(char_u **arg, char_u **alias, int evaluate, int verbose) *arg += len; } - /* - * Find the end of the name; check for {} construction. - */ - p = find_name_end(*arg, &expr_start, &expr_end, - len > 0 ? 0 : FNE_CHECK_START); + // Find the end of the name; check for {} construction. + char_u *expr_start; + char_u *expr_end; + const char *p = (const char *)find_name_end((char_u *)(*arg), + (const char_u **)&expr_start, + (const char_u **)&expr_end, + len > 0 ? 0 : FNE_CHECK_START); if (expr_start != NULL) { - char_u *temp_string; - if (!evaluate) { len += (int)(p - *arg); - *arg = skipwhite(p); + *arg = (const char *)skipwhite((const char_u *)p); return len; } @@ -18425,11 +18000,13 @@ static int get_name_len(char_u **arg, char_u **alias, int evaluate, int verbose) * Include any <SID> etc in the expanded string: * Thus the -len here. */ - temp_string = make_expanded_name(*arg - len, expr_start, expr_end, p); - if (temp_string == NULL) + char_u *temp_string = make_expanded_name((char_u *)(*arg) - len, expr_start, + expr_end, (char_u *)p); + if (temp_string == NULL) { return -1; - *alias = temp_string; - *arg = skipwhite(p); + } + *alias = (char *)temp_string; + *arg = (const char *)skipwhite((const char_u *)p); return (int)STRLEN(temp_string); } @@ -18446,12 +18023,11 @@ static int get_name_len(char_u **arg, char_u **alias, int evaluate, int verbose) // "flags" can have FNE_INCL_BR and FNE_CHECK_START. // Return a pointer to just after the name. Equal to "arg" if there is no // valid name. -static char_u *find_name_end(char_u *arg, char_u **expr_start, - char_u **expr_end, int flags) +static const char_u *find_name_end(const char_u *arg, const char_u **expr_start, + const char_u **expr_end, int flags) { int mb_nest = 0; int br_nest = 0; - char_u *p; int len; if (expr_start != NULL) { @@ -18464,6 +18040,7 @@ static char_u *find_name_end(char_u *arg, char_u **expr_start, return arg; } + const char_u *p; for (p = arg; *p != NUL && (eval_isnamec(*p) || *p == '{' @@ -18535,7 +18112,8 @@ static char_u *find_name_end(char_u *arg, char_u **expr_start, * Returns a new allocated string, which the caller must free. * Returns NULL for failure. */ -static char_u *make_expanded_name(char_u *in_start, char_u *expr_start, char_u *expr_end, char_u *in_end) +static char_u *make_expanded_name(const char_u *in_start, char_u *expr_start, + char_u *expr_end, char_u *in_end) { char_u c1; char_u *retval = NULL; @@ -18564,7 +18142,9 @@ static char_u *make_expanded_name(char_u *in_start, char_u *expr_start, char_u * *expr_end = '}'; if (retval != NULL) { - temp_result = find_name_end(retval, &expr_start, &expr_end, 0); + temp_result = (char_u *)find_name_end(retval, + (const char_u **)&expr_start, + (const char_u **)&expr_end, 0); if (expr_start != NULL) { /* Further expansion! */ temp_result = make_expanded_name(retval, expr_start, @@ -18598,7 +18178,7 @@ static int eval_isnamec1(int c) /* * Get number v: variable value. */ -long get_vim_var_nr(int idx) FUNC_ATTR_PURE +varnumber_T get_vim_var_nr(int idx) FUNC_ATTR_PURE { return vimvars[idx].vv_nr; } @@ -18608,7 +18188,7 @@ long get_vim_var_nr(int idx) FUNC_ATTR_PURE */ char_u *get_vim_var_str(int idx) FUNC_ATTR_PURE FUNC_ATTR_NONNULL_RET { - return get_tv_string(&vimvars[idx].vv_tv); + return (char_u *)tv_get_string(&vimvars[idx].vv_tv); } /* @@ -18661,7 +18241,7 @@ void set_vcount(long count, long count1, int set_prevcount) /// @param[in] val Value to set to. void set_vim_var_nr(const VimVarIndex idx, const varnumber_T val) { - clear_tv(&vimvars[idx].vv_tv); + tv_clear(&vimvars[idx].vv_tv); vimvars[idx].vv_type = VAR_NUMBER; vimvars[idx].vv_nr = val; } @@ -18672,7 +18252,7 @@ void set_vim_var_nr(const VimVarIndex idx, const varnumber_T val) /// @param[in] val Value to set to. void set_vim_var_special(const VimVarIndex idx, const SpecialVarValue val) { - clear_tv(&vimvars[idx].vv_tv); + tv_clear(&vimvars[idx].vv_tv); vimvars[idx].vv_type = VAR_SPECIAL; vimvars[idx].vv_special = val; } @@ -18686,7 +18266,7 @@ void set_vim_var_special(const VimVarIndex idx, const SpecialVarValue val) void set_vim_var_string(const VimVarIndex idx, const char *const val, const ptrdiff_t len) { - clear_tv(&vimvars[idx].vv_di.di_tv); + tv_clear(&vimvars[idx].vv_di.di_tv); vimvars[idx].vv_type = VAR_STRING; if (val == NULL) { vimvars[idx].vv_str = NULL; @@ -18703,7 +18283,7 @@ void set_vim_var_string(const VimVarIndex idx, const char *const val, /// @param[in,out] val Value to set to. Reference count will be incremented. void set_vim_var_list(const VimVarIndex idx, list_T *const val) { - clear_tv(&vimvars[idx].vv_di.di_tv); + tv_clear(&vimvars[idx].vv_di.di_tv); vimvars[idx].vv_type = VAR_LIST; vimvars[idx].vv_list = val; if (val != NULL) { @@ -18718,14 +18298,14 @@ void set_vim_var_list(const VimVarIndex idx, list_T *const val) /// Also keys of the dictionary will be made read-only. void set_vim_var_dict(const VimVarIndex idx, dict_T *const val) { - clear_tv(&vimvars[idx].vv_di.di_tv); + tv_clear(&vimvars[idx].vv_di.di_tv); vimvars[idx].vv_type = VAR_DICT; vimvars[idx].vv_dict = val; if (val != NULL) { val->dv_refcount++; // Set readonly - dict_set_keys_readonly(val); + tv_dict_set_keys_readonly(val); } } @@ -18843,9 +18423,8 @@ char_u *set_cmdarg(exarg_T *eap, char_u *oldarg) * Get the value of internal variable "name". * Return OK or FAIL. */ -static int -get_var_tv ( - char_u *name, +static int get_var_tv( + const char *name, int len, // length of "name" typval_T *rettv, // NULL when only checking existence dictitem_T **dip, // non-NULL when typval's dict item is needed @@ -18855,55 +18434,52 @@ get_var_tv ( { int ret = OK; typval_T *tv = NULL; - typval_T atv; dictitem_T *v; - int cc; - - /* truncate the name, so that we can use strcmp() */ - cc = name[len]; - name[len] = NUL; - /* - * Check for "b:changedtick". - */ - if (STRCMP(name, "b:changedtick") == 0) { - atv.v_type = VAR_NUMBER; - atv.vval.v_number = curbuf->b_changedtick; - tv = &atv; - } - /* - * Check for user-defined variables. - */ - else { - v = find_var(name, NULL, no_autoload); - if (v != NULL) { - tv = &v->di_tv; - if (dip != NULL) { - *dip = v; - } + v = find_var(name, (size_t)len, NULL, no_autoload); + if (v != NULL) { + tv = &v->di_tv; + if (dip != NULL) { + *dip = v; } } if (tv == NULL) { - if (rettv != NULL && verbose) - EMSG2(_(e_undefvar), name); + if (rettv != NULL && verbose) { + emsgf(_("E121: Undefined variable: %.*s"), len, name); + } ret = FAIL; - } else if (rettv != NULL) - copy_tv(tv, rettv); - - name[len] = cc; + } else if (rettv != NULL) { + tv_copy(tv, rettv); + } return ret; } -/* - * Handle expr[expr], expr[expr:expr] subscript and .name lookup. - * Also handle function call with Funcref variable: func(expr) - * Can all be combined: dict.func(expr)[idx]['func'](expr) - */ -static int -handle_subscript ( - char_u **arg, +/// Check if variable "name[len]" is a local variable or an argument. +/// If so, "*eval_lavars_used" is set to TRUE. +static void check_vars(const char *name, size_t len) +{ + if (eval_lavars_used == NULL) { + return; + } + + const char *varname; + hashtab_T *ht = find_var_ht(name, len, &varname); + + if (ht == get_funccal_local_ht() || ht == get_funccal_args_ht()) { + if (find_var(name, len, NULL, true) != NULL) { + *eval_lavars_used = true; + } + } +} + +/// Handle expr[expr], expr[expr:expr] subscript and .name lookup. +/// Also handle function call with Funcref variable: func(expr) +/// Can all be combined: dict.func(expr)[idx]['func'](expr) +static int +handle_subscript( + const char **const arg, typval_T *rettv, int evaluate, /* do more than finding the end */ int verbose /* give error messages */ @@ -18918,8 +18494,7 @@ handle_subscript ( while (ret == OK && (**arg == '[' || (**arg == '.' && rettv->v_type == VAR_DICT) - || (**arg == '(' && (!evaluate || rettv->v_type == VAR_FUNC - || rettv->v_type == VAR_PARTIAL))) + || (**arg == '(' && (!evaluate || tv_is_func(*rettv)))) && !ascii_iswhite(*(*arg - 1))) { if (**arg == '(') { partial_T *pt = NULL; @@ -18931,59 +18506,59 @@ handle_subscript ( // Invoke the function. Recursive! if (functv.v_type == VAR_PARTIAL) { pt = functv.vval.v_partial; - s = pt->pt_name; + s = partial_name(pt); } else { s = functv.vval.v_string; } } else { s = (char_u *)""; } - ret = get_func_tv(s, (int)STRLEN(s), rettv, arg, + ret = get_func_tv(s, (int)STRLEN(s), rettv, (char_u **)arg, curwin->w_cursor.lnum, curwin->w_cursor.lnum, &len, evaluate, pt, selfdict); - /* Clear the funcref afterwards, so that deleting it while - * evaluating the arguments is possible (see test55). */ - if (evaluate) - clear_tv(&functv); + // Clear the funcref afterwards, so that deleting it while + // evaluating the arguments is possible (see test55). + if (evaluate) { + tv_clear(&functv); + } /* Stop the expression evaluation when immediately aborting on * error, or when an interrupt occurred or an exception was thrown * but not caught. */ if (aborting()) { - if (ret == OK) - clear_tv(rettv); + if (ret == OK) { + tv_clear(rettv); + } ret = FAIL; } - dict_unref(selfdict); + tv_dict_unref(selfdict); selfdict = NULL; - } else { /* **arg == '[' || **arg == '.' */ - dict_unref(selfdict); + } else { // **arg == '[' || **arg == '.' + tv_dict_unref(selfdict); if (rettv->v_type == VAR_DICT) { selfdict = rettv->vval.v_dict; if (selfdict != NULL) ++selfdict->dv_refcount; } else selfdict = NULL; - if (eval_index(arg, rettv, evaluate, verbose) == FAIL) { - clear_tv(rettv); + if (eval_index((char_u **)arg, rettv, evaluate, verbose) == FAIL) { + tv_clear(rettv); ret = FAIL; } } } // Turn "dict.Func" into a partial for "Func" bound to "dict". - if (selfdict != NULL - && (rettv->v_type == VAR_FUNC - || rettv->v_type == VAR_PARTIAL)) { + if (selfdict != NULL && tv_is_func(*rettv)) { set_selfdict(rettv, selfdict); } - dict_unref(selfdict); + tv_dict_unref(selfdict); return ret; } -static void set_selfdict(typval_T *rettv, dict_T *selfdict) +void set_selfdict(typval_T *rettv, dict_T *selfdict) { // Don't do this when "dict.Func" is already a partial that was bound // explicitly (pt_auto is false). @@ -18991,19 +18566,23 @@ static void set_selfdict(typval_T *rettv, dict_T *selfdict) && rettv->vval.v_partial->pt_dict != NULL) { return; } - char_u *fname = rettv->v_type == VAR_FUNC || rettv->v_type == VAR_STRING - ? rettv->vval.v_string - : rettv->vval.v_partial->pt_name; + char_u *fname; char_u *tofree = NULL; ufunc_T *fp; char_u fname_buf[FLEN_FIXED + 1]; int error; - // Translate "s:func" to the stored function name. - fname = fname_trans_sid(fname, fname_buf, &tofree, &error); - - fp = find_func(fname); - xfree(tofree); + if (rettv->v_type == VAR_PARTIAL && rettv->vval.v_partial->pt_func != NULL) { + fp = rettv->vval.v_partial->pt_func; + } else { + fname = rettv->v_type == VAR_FUNC || rettv->v_type == VAR_STRING + ? rettv->vval.v_string + : rettv->vval.v_partial->pt_name; + // Translate "s:func" to the stored function name. + fname = fname_trans_sid(fname, fname_buf, &tofree, &error); + fp = find_func(fname); + xfree(tofree); + } // Turn "dict.Func" into a partial for "Func" with "dict". if (fp != NULL && (fp->uf_flags & FC_DICT)) { @@ -19024,8 +18603,13 @@ static void set_selfdict(typval_T *rettv, dict_T *selfdict) // Partial: copy the function name, use selfdict and copy // args. Can't take over name or args, the partial might // be referenced elsewhere. - pt->pt_name = vim_strsave(ret_pt->pt_name); - func_ref(pt->pt_name); + if (ret_pt->pt_name != NULL) { + pt->pt_name = vim_strsave(ret_pt->pt_name); + func_ref(pt->pt_name); + } else { + pt->pt_func = ret_pt->pt_func; + func_ptr_ref(pt->pt_func); + } if (ret_pt->pt_argc > 0) { size_t arg_size = sizeof(typval_T) * ret_pt->pt_argc; pt->pt_argv = (typval_T *)xmalloc(arg_size); @@ -19035,7 +18619,7 @@ static void set_selfdict(typval_T *rettv, dict_T *selfdict) } else { pt->pt_argc = ret_pt->pt_argc; for (i = 0; i < pt->pt_argc; i++) { - copy_tv(&ret_pt->pt_argv[i], &pt->pt_argv[i]); + tv_copy(&ret_pt->pt_argv[i], &pt->pt_argv[i]); } } } @@ -19047,546 +18631,90 @@ static void set_selfdict(typval_T *rettv, dict_T *selfdict) } } -/* - * Free the memory for a variable type-value. - */ -void free_tv(typval_T *varp) +// Find variable "name" in the list of variables. +// Return a pointer to it if found, NULL if not found. +// Careful: "a:0" variables don't have a name. +// When "htp" is not NULL we are writing to the variable, set "htp" to the +// hashtab_T used. +static dictitem_T *find_var(const char *const name, const size_t name_len, + hashtab_T **htp, int no_autoload) { - if (varp != NULL) { - switch (varp->v_type) { - case VAR_FUNC: - func_unref(varp->vval.v_string); - // FALLTHROUGH - case VAR_STRING: - xfree(varp->vval.v_string); - break; - case VAR_PARTIAL: - partial_unref(varp->vval.v_partial); - break; - case VAR_LIST: - list_unref(varp->vval.v_list); - break; - case VAR_DICT: - dict_unref(varp->vval.v_dict); - break; - case VAR_SPECIAL: - case VAR_NUMBER: - case VAR_FLOAT: - case VAR_UNKNOWN: - break; - } - xfree(varp); + const char *varname; + hashtab_T *const ht = find_var_ht(name, name_len, &varname); + if (htp != NULL) { + *htp = ht; } -} - -#define TYPVAL_ENCODE_ALLOW_SPECIALS false - -#define TYPVAL_ENCODE_CONV_NIL(tv) \ - do { \ - tv->vval.v_special = kSpecialVarFalse; \ - tv->v_lock = VAR_UNLOCKED; \ - } while (0) - -#define TYPVAL_ENCODE_CONV_BOOL(tv, num) \ - TYPVAL_ENCODE_CONV_NIL(tv) - -#define TYPVAL_ENCODE_CONV_NUMBER(tv, num) \ - do { \ - (void)num; \ - tv->vval.v_number = 0; \ - tv->v_lock = VAR_UNLOCKED; \ - } while (0) - -#define TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER(tv, num) - -#define TYPVAL_ENCODE_CONV_FLOAT(tv, flt) \ - do { \ - tv->vval.v_float = 0; \ - tv->v_lock = VAR_UNLOCKED; \ - } while (0) - -#define TYPVAL_ENCODE_CONV_STRING(tv, buf, len) \ - do { \ - xfree(buf); \ - tv->vval.v_string = NULL; \ - tv->v_lock = VAR_UNLOCKED; \ - } while (0) - -#define TYPVAL_ENCODE_CONV_STR_STRING(tv, buf, len) - -#define TYPVAL_ENCODE_CONV_EXT_STRING(tv, buf, len, type) - -static inline int _nothing_conv_func_start(typval_T *const tv, - char_u *const fun) - FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ARG(1) -{ - tv->v_lock = VAR_UNLOCKED; - if (tv->v_type == VAR_PARTIAL) { - partial_T *const pt_ = tv->vval.v_partial; - if (pt_ != NULL && pt_->pt_refcount > 1) { - pt_->pt_refcount--; - tv->vval.v_partial = NULL; - return OK; - } - } else { - func_unref(fun); - if (fun != empty_string) { - xfree(fun); - } - tv->vval.v_string = NULL; + if (ht == NULL) { + return NULL; } - return NOTDONE; -} -#define TYPVAL_ENCODE_CONV_FUNC_START(tv, fun) \ - do { \ - if (_nothing_conv_func_start(tv, fun) != NOTDONE) { \ - return OK; \ - } \ - } while (0) - -#define TYPVAL_ENCODE_CONV_FUNC_BEFORE_ARGS(tv, len) -#define TYPVAL_ENCODE_CONV_FUNC_BEFORE_SELF(tv, len) - -static inline void _nothing_conv_func_end(typval_T *const tv, const int copyID) - FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ALL -{ - if (tv->v_type == VAR_PARTIAL) { - partial_T *const pt = tv->vval.v_partial; - if (pt == NULL) { - return; - } - // Dictionary should already be freed by the time. - // If it was not freed then it is a part of the reference cycle. - assert(pt->pt_dict == NULL || pt->pt_dict->dv_copyID == copyID); - pt->pt_dict = NULL; - // As well as all arguments. - pt->pt_argc = 0; - assert(pt->pt_refcount <= 1); - partial_unref(pt); - tv->vval.v_partial = NULL; - assert(tv->v_lock == VAR_UNLOCKED); - } -} -#define TYPVAL_ENCODE_CONV_FUNC_END(tv) _nothing_conv_func_end(tv, copyID) - -#define TYPVAL_ENCODE_CONV_EMPTY_LIST(tv) \ - do { \ - list_unref(tv->vval.v_list); \ - tv->vval.v_list = NULL; \ - tv->v_lock = VAR_UNLOCKED; \ - } while (0) - -#define TYPVAL_ENCODE_CONV_EMPTY_DICT(tv, dict) \ - do { \ - assert((void *)&dict != (void *)&TYPVAL_ENCODE_NODICT_VAR); \ - dict_unref((dict_T *)dict); \ - *((dict_T **)&dict) = NULL; \ - if (tv != NULL) { \ - ((typval_T *)tv)->v_lock = VAR_UNLOCKED; \ - } \ - } while (0) - -static inline int _nothing_conv_real_list_after_start( - typval_T *const tv, MPConvStackVal *const mpsv) - FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_WARN_UNUSED_RESULT -{ - assert(tv != NULL); - tv->v_lock = VAR_UNLOCKED; - if (tv->vval.v_list->lv_refcount > 1) { - tv->vval.v_list->lv_refcount--; - tv->vval.v_list = NULL; - mpsv->data.l.li = NULL; - return OK; + dictitem_T *const ret = find_var_in_ht(ht, *name, + varname, + name_len - (size_t)(varname - name), + no_autoload || htp != NULL); + if (ret != NULL) { + return ret; } - return NOTDONE; -} -#define TYPVAL_ENCODE_CONV_LIST_START(tv, len) - -#define TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START(tv, mpsv) \ - do { \ - if (_nothing_conv_real_list_after_start(tv, &mpsv) != NOTDONE) { \ - goto typval_encode_stop_converting_one_item; \ - } \ - } while (0) -#define TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS(tv) - -static inline void _nothing_conv_list_end(typval_T *const tv) - FUNC_ATTR_ALWAYS_INLINE -{ - if (tv == NULL) { - return; - } - assert(tv->v_type == VAR_LIST); - list_T *const list = tv->vval.v_list; - list_unref(list); - tv->vval.v_list = NULL; + // Search in parent scope for lambda + return find_var_in_scoped_ht(name, name_len, no_autoload || htp != NULL); } -#define TYPVAL_ENCODE_CONV_LIST_END(tv) _nothing_conv_list_end(tv) -static inline int _nothing_conv_real_dict_after_start( - typval_T *const tv, dict_T **const dictp, const void *const nodictvar, - MPConvStackVal *const mpsv) - FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_WARN_UNUSED_RESULT -{ - if (tv != NULL) { - tv->v_lock = VAR_UNLOCKED; - } - if ((const void *)dictp != nodictvar && (*dictp)->dv_refcount > 1) { - (*dictp)->dv_refcount--; - *dictp = NULL; - mpsv->data.d.todo = 0; - return OK; - } - return NOTDONE; -} -#define TYPVAL_ENCODE_CONV_DICT_START(tv, dict, len) - -#define TYPVAL_ENCODE_CONV_REAL_DICT_AFTER_START(tv, dict, mpsv) \ - do { \ - if (_nothing_conv_real_dict_after_start( \ - tv, (dict_T **)&dict, (void *)&TYPVAL_ENCODE_NODICT_VAR, \ - &mpsv) != NOTDONE) { \ - goto typval_encode_stop_converting_one_item; \ - } \ - } while (0) - -#define TYPVAL_ENCODE_SPECIAL_DICT_KEY_CHECK(tv, dict) -#define TYPVAL_ENCODE_CONV_DICT_AFTER_KEY(tv, dict) -#define TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS(tv, dict) - -static inline void _nothing_conv_dict_end(typval_T *const tv, - dict_T **const dictp, - const void *const nodictvar) - FUNC_ATTR_ALWAYS_INLINE -{ - if ((const void *)dictp != nodictvar) { - dict_unref(*dictp); - *dictp = NULL; - } -} -#define TYPVAL_ENCODE_CONV_DICT_END(tv, dict) \ - _nothing_conv_dict_end(tv, (dict_T **)&dict, \ - (void *)&TYPVAL_ENCODE_NODICT_VAR) - -#define TYPVAL_ENCODE_CONV_RECURSE(val, conv_type) - -#define TYPVAL_ENCODE_SCOPE static -#define TYPVAL_ENCODE_NAME nothing -#define TYPVAL_ENCODE_FIRST_ARG_TYPE const void *const -#define TYPVAL_ENCODE_FIRST_ARG_NAME ignored -#include "nvim/eval/typval_encode.c.h" -#undef TYPVAL_ENCODE_SCOPE -#undef TYPVAL_ENCODE_NAME -#undef TYPVAL_ENCODE_FIRST_ARG_TYPE -#undef TYPVAL_ENCODE_FIRST_ARG_NAME - -#undef TYPVAL_ENCODE_ALLOW_SPECIALS -#undef TYPVAL_ENCODE_CONV_NIL -#undef TYPVAL_ENCODE_CONV_BOOL -#undef TYPVAL_ENCODE_CONV_NUMBER -#undef TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER -#undef TYPVAL_ENCODE_CONV_FLOAT -#undef TYPVAL_ENCODE_CONV_STRING -#undef TYPVAL_ENCODE_CONV_STR_STRING -#undef TYPVAL_ENCODE_CONV_EXT_STRING -#undef TYPVAL_ENCODE_CONV_FUNC_START -#undef TYPVAL_ENCODE_CONV_FUNC_BEFORE_ARGS -#undef TYPVAL_ENCODE_CONV_FUNC_BEFORE_SELF -#undef TYPVAL_ENCODE_CONV_FUNC_END -#undef TYPVAL_ENCODE_CONV_EMPTY_LIST -#undef TYPVAL_ENCODE_CONV_EMPTY_DICT -#undef TYPVAL_ENCODE_CONV_LIST_START -#undef TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START -#undef TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS -#undef TYPVAL_ENCODE_CONV_LIST_END -#undef TYPVAL_ENCODE_CONV_DICT_START -#undef TYPVAL_ENCODE_CONV_REAL_DICT_AFTER_START -#undef TYPVAL_ENCODE_SPECIAL_DICT_KEY_CHECK -#undef TYPVAL_ENCODE_CONV_DICT_AFTER_KEY -#undef TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS -#undef TYPVAL_ENCODE_CONV_DICT_END -#undef TYPVAL_ENCODE_CONV_RECURSE - -/// Free memory for a variable value and set the value to NULL or 0 +/// Find variable in hashtab /// -/// @param[in,out] varp Value to free. -void clear_tv(typval_T *varp) -{ - if (varp != NULL && varp->v_type != VAR_UNKNOWN) { - const int evn_ret = encode_vim_to_nothing(varp, varp, "clear_tv argument"); - (void)evn_ret; - assert(evn_ret == OK); - } -} - -/* - * Set the value of a variable to NULL without freeing items. - */ -static void init_tv(typval_T *varp) -{ - if (varp != NULL) - memset(varp, 0, sizeof(typval_T)); -} - -/* - * Get the number value of a variable. - * If it is a String variable, uses vim_str2nr(). - * For incompatible types, return 0. - * get_tv_number_chk() is similar to get_tv_number(), but informs the - * caller of incompatible types: it sets *denote to TRUE if "denote" - * is not NULL or returns -1 otherwise. - */ -long get_tv_number(typval_T *varp) -{ - int error = FALSE; - - return get_tv_number_chk(varp, &error); /* return 0L on error */ -} - -long get_tv_number_chk(typval_T *varp, int *denote) -{ - long n = 0L; - - switch (varp->v_type) { - case VAR_NUMBER: - return (long)(varp->vval.v_number); - case VAR_FLOAT: - EMSG(_("E805: Using a Float as a Number")); - break; - case VAR_FUNC: - case VAR_PARTIAL: - EMSG(_("E703: Using a Funcref as a Number")); - break; - case VAR_STRING: - if (varp->vval.v_string != NULL) { - vim_str2nr(varp->vval.v_string, NULL, NULL, - STR2NR_ALL, &n, NULL, 0); - } - return n; - case VAR_LIST: - EMSG(_("E745: Using a List as a Number")); - break; - case VAR_DICT: - EMSG(_("E728: Using a Dictionary as a Number")); - break; - case VAR_SPECIAL: - switch (varp->vval.v_special) { - case kSpecialVarTrue: { - return 1; - } - case kSpecialVarFalse: - case kSpecialVarNull: { - return 0; - } - } - break; - case VAR_UNKNOWN: - EMSG2(_(e_intern2), "get_tv_number(UNKNOWN)"); - break; - } - if (denote == NULL) { - // useful for values that must be unsigned - n = -1; - } else { - *denote = true; - } - return n; -} - -static float_T get_tv_float(typval_T *varp) -{ - switch (varp->v_type) { - case VAR_NUMBER: - return (float_T)(varp->vval.v_number); - case VAR_FLOAT: - return varp->vval.v_float; - break; - case VAR_FUNC: - case VAR_PARTIAL: - EMSG(_("E891: Using a Funcref as a Float")); - break; - case VAR_STRING: - EMSG(_("E892: Using a String as a Float")); - break; - case VAR_LIST: - EMSG(_("E893: Using a List as a Float")); - break; - case VAR_DICT: - EMSG(_("E894: Using a Dictionary as a Float")); - break; - default: - EMSG2(_(e_intern2), "get_tv_float()"); - break; - } - return 0; -} - -/* - * Get the lnum from the first argument. - * Also accepts ".", "$", etc., but that only works for the current buffer. - * Returns -1 on error. - */ -static linenr_T get_tv_lnum(typval_T *argvars) -{ - typval_T rettv; - linenr_T lnum; - - lnum = get_tv_number_chk(&argvars[0], NULL); - if (lnum == 0) { /* no valid number, try using line() */ - rettv.v_type = VAR_NUMBER; - f_line(argvars, &rettv, NULL); - lnum = rettv.vval.v_number; - clear_tv(&rettv); - } - return lnum; -} - -/* - * Get the lnum from the first argument. - * Also accepts "$", then "buf" is used. - * Returns 0 on error. - */ -static linenr_T get_tv_lnum_buf(typval_T *argvars, buf_T *buf) -{ - if (argvars[0].v_type == VAR_STRING - && argvars[0].vval.v_string != NULL - && argvars[0].vval.v_string[0] == '$' - && buf != NULL) - return buf->b_ml.ml_line_count; - return get_tv_number_chk(&argvars[0], NULL); -} - -/* - * Get the string value of a variable. - * If it is a Number variable, the number is converted into a string. - * get_tv_string() uses a single, static buffer. YOU CAN ONLY USE IT ONCE! - * get_tv_string_buf() uses a given buffer. - * If the String variable has never been set, return an empty string. - * Never returns NULL; - * get_tv_string_chk() and get_tv_string_buf_chk() are similar, but return - * NULL on error. - */ -static char_u *get_tv_string(const typval_T *varp) - FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET -{ - static char_u mybuf[NUMBUFLEN]; - - return get_tv_string_buf(varp, mybuf); -} - -static char_u *get_tv_string_buf(const typval_T *varp, char_u *buf) - FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET -{ - char_u *res = get_tv_string_buf_chk(varp, buf); - - return res != NULL ? res : (char_u *)""; -} - -/// Careful: This uses a single, static buffer. YOU CAN ONLY USE IT ONCE! -char_u *get_tv_string_chk(const typval_T *varp) - FUNC_ATTR_NONNULL_ALL -{ - static char_u mybuf[NUMBUFLEN]; - - return get_tv_string_buf_chk(varp, mybuf); -} - -static char_u *get_tv_string_buf_chk(const typval_T *varp, char_u *buf) - FUNC_ATTR_NONNULL_ALL -{ - switch (varp->v_type) { - case VAR_NUMBER: - sprintf((char *)buf, "%" PRId64, (int64_t)varp->vval.v_number); - return buf; - case VAR_FUNC: - case VAR_PARTIAL: - EMSG(_("E729: using Funcref as a String")); - break; - case VAR_LIST: - EMSG(_("E730: using List as a String")); - break; - case VAR_DICT: - EMSG(_("E731: using Dictionary as a String")); - break; - case VAR_FLOAT: - EMSG(_(e_float_as_string)); - break; - case VAR_STRING: - if (varp->vval.v_string != NULL) - return varp->vval.v_string; - return (char_u *)""; - case VAR_SPECIAL: - STRCPY(buf, encode_special_var_names[varp->vval.v_special]); - return buf; - case VAR_UNKNOWN: - EMSG(_("E908: using an invalid value as a String")); - break; - } - return NULL; -} - -/* - * Find variable "name" in the list of variables. - * Return a pointer to it if found, NULL if not found. - * Careful: "a:0" variables don't have a name. - * When "htp" is not NULL we are writing to the variable, set "htp" to the - * hashtab_T used. - */ -static dictitem_T *find_var(char_u *name, hashtab_T **htp, int no_autoload) -{ - char_u *varname; - hashtab_T *ht; - - ht = find_var_ht(name, &varname); - if (htp != NULL) - *htp = ht; - if (ht == NULL) - return NULL; - return find_var_in_ht(ht, *name, varname, no_autoload || htp != NULL); -} - -/// Find variable "varname" in hashtab "ht" with name "htname". -/// Returns NULL if not found. -static dictitem_T *find_var_in_ht(hashtab_T *ht, int htname, - char_u *varname, bool no_autoload) +/// @param[in] ht Hashtab to find variable in. +/// @param[in] htname Hashtab name (first character). +/// @param[in] varname Variable name. +/// @param[in] varname_len Variable name length. +/// @param[in] no_autoload If true then autoload scripts will not be sourced +/// if autoload variable was not found. +/// +/// @return pointer to the dictionary item with the found variable or NULL if it +/// was not found. +static dictitem_T *find_var_in_ht(hashtab_T *const ht, + int htname, + const char *const varname, + const size_t varname_len, + int no_autoload) + FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL { hashitem_T *hi; - if (*varname == NUL) { - /* Must be something like "s:", otherwise "ht" would be NULL. */ + if (varname_len == 0) { + // Must be something like "s:", otherwise "ht" would be NULL. switch (htname) { - case 's': return &SCRIPT_SV(current_SID)->sv_var; - case 'g': return &globvars_var; - case 'v': return &vimvars_var; - case 'b': return &curbuf->b_bufvar; - case 'w': return &curwin->w_winvar; - case 't': return &curtab->tp_winvar; - case 'l': return current_funccal == NULL - ? NULL : ¤t_funccal->l_vars_var; - case 'a': return current_funccal == NULL - ? NULL : ¤t_funccal->l_avars_var; + case 's': return (dictitem_T *)&SCRIPT_SV(current_SID)->sv_var; + case 'g': return (dictitem_T *)&globvars_var; + case 'v': return (dictitem_T *)&vimvars_var; + case 'b': return (dictitem_T *)&curbuf->b_bufvar; + case 'w': return (dictitem_T *)&curwin->w_winvar; + case 't': return (dictitem_T *)&curtab->tp_winvar; + case 'l': return (current_funccal == NULL + ? NULL : (dictitem_T *)¤t_funccal->l_vars_var); + case 'a': return (current_funccal == NULL + ? NULL : (dictitem_T *)¤t_funccal->l_avars_var); } return NULL; } - hi = hash_find(ht, varname); + hi = hash_find_len(ht, varname, varname_len); if (HASHITEM_EMPTY(hi)) { - /* For global variables we may try auto-loading the script. If it - * worked find the variable again. Don't auto-load a script if it was - * loaded already, otherwise it would be loaded every time when - * checking if a function name is a Funcref variable. */ + // For global variables we may try auto-loading the script. If it + // worked find the variable again. Don't auto-load a script if it was + // loaded already, otherwise it would be loaded every time when + // checking if a function name is a Funcref variable. if (ht == &globvarht && !no_autoload) { - /* Note: script_autoload() may make "hi" invalid. It must either - * be obtained again or not used. */ - if (!script_autoload(varname, FALSE) || aborting()) + // Note: script_autoload() may make "hi" invalid. It must either + // be obtained again or not used. + if (!script_autoload(varname, varname_len, false) || aborting()) { return NULL; - hi = hash_find(ht, varname); + } + hi = hash_find_len(ht, varname, varname_len); } - if (HASHITEM_EMPTY(hi)) + if (HASHITEM_EMPTY(hi)) { return NULL; + } } - return HI2DI(hi); + return TV_DICT_HI2DI(hi); } // Get function call environment based on backtrace debug level @@ -19608,17 +18736,45 @@ static funccall_T *get_funccal(void) return funccal; } -// 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) +/// Return the hashtable used for argument in the current funccal. +/// Return NULL if there is no current funccal. +static hashtab_T *get_funccal_args_ht(void) { - hashitem_T *hi; + if (current_funccal == NULL) { + return NULL; + } + return &get_funccal()->l_avars.dv_hashtab; +} + +/// Return the hashtable used for local variables in the current funccal. +/// Return NULL if there is no current funccal. +static hashtab_T *get_funccal_local_ht(void) +{ + if (current_funccal == NULL) { + return NULL; + } + return &get_funccal()->l_vars.dv_hashtab; +} + +/// Find the dict and hashtable used for a variable +/// +/// @param[in] name Variable name, possibly with scope prefix. +/// @param[in] name_len Variable name length. +/// @param[out] varname Will be set to the start of the name without scope +/// prefix. +/// @param[out] d Scope dictionary. +/// +/// @return Scope hashtab, NULL if name is not valid. +static hashtab_T *find_var_ht_dict(const char *name, const size_t name_len, + const char **varname, dict_T **d) +{ + hashitem_T *hi; *d = NULL; - if (name[0] == NUL) { + if (name_len == 0) { return NULL; } - if (name[1] != ':') { + if (name_len == 1 || (name_len >= 2 && name[1] != ':')) { // name has implicit scope if (name[0] == ':' || name[0] == AUTOLOAD_CHAR) { // The name must not start with a colon or #. @@ -19627,7 +18783,7 @@ static hashtab_T *find_var_ht_dict(char_u *name, uint8_t **varname, dict_T **d) *varname = name; // "version" is "v:version" in all scopes - hi = hash_find(&compat_hashtab, name); + hi = hash_find_len(&compat_hashtab, name, name_len); if (!HASHITEM_EMPTY(hi)) { return &compat_hashtab; } @@ -19643,26 +18799,27 @@ static hashtab_T *find_var_ht_dict(char_u *name, uint8_t **varname, dict_T **d) *varname = name + 2; if (*name == 'g') { // global variable *d = &globvardict; - } else if (vim_strchr(name + 2, ':') != NULL - || vim_strchr(name + 2, AUTOLOAD_CHAR) != NULL) { + } else if (name_len > 2 + && (memchr(name + 2, ':', name_len - 2) != NULL + || memchr(name + 2, AUTOLOAD_CHAR, name_len - 2) != NULL)) { // There must be no ':' or '#' in the rest of the name if g: was not used return NULL; } - if (*name == 'b') { // buffer variable + if (*name == 'b') { // buffer variable *d = curbuf->b_vars; - } else if (*name == 'w') { // window variable + } else if (*name == 'w') { // window variable *d = curwin->w_vars; - } else if (*name == 't') { // tab page variable + } else if (*name == 't') { // tab page variable *d = curtab->tp_vars; - } else if (*name == 'v') { // v: variable + } else if (*name == 'v') { // v: variable *d = &vimvardict; } else if (*name == 'a' && current_funccal != NULL) { // function argument *d = &get_funccal()->l_avars; } else if (*name == 'l' && current_funccal != NULL) { // local variable *d = &get_funccal()->l_vars; - } else if (*name == 's' // script variable - && current_SID > 0 && current_SID <= ga_scripts.ga_len) { + } else if (*name == 's' // script variable + && current_SID > 0 && current_SID <= ga_scripts.ga_len) { *d = &SCRIPT_SV(current_SID)->sv_dict; } @@ -19670,28 +18827,35 @@ end: return *d ? &(*d)->dv_hashtab : NULL; } -// Find the hashtab used for a variable name. -// Return NULL if the name is not valid. -// Set "varname" to the start of name without ':'. -static hashtab_T *find_var_ht(uint8_t *name, uint8_t **varname) +/// Find the hashtable used for a variable +/// +/// @param[in] name Variable name, possibly with scope prefix. +/// @param[in] name_len Variable name length. +/// @param[out] varname Will be set to the start of the name without scope +/// prefix. +/// +/// @return Scope hashtab, NULL if name is not valid. +static hashtab_T *find_var_ht(const char *name, const size_t name_len, + const char **varname) { dict_T *d; - return find_var_ht_dict(name, varname, &d); + return find_var_ht_dict(name, name_len, varname, &d); } /* * Get the string value of a (global/local) variable. - * Note: see get_tv_string() for how long the pointer remains valid. + * Note: see tv_get_string() for how long the pointer remains valid. * Returns NULL when it doesn't exist. */ -char_u *get_var_value(char_u *name) +char_u *get_var_value(const char *const name) { dictitem_T *v; - v = find_var(name, NULL, FALSE); - if (v == NULL) + v = find_var(name, strlen(name), NULL, false); + if (v == NULL) { return NULL; - return get_tv_string(&v->di_tv); + } + return (char_u *)tv_get_string(&v->di_tv); } /* @@ -19728,10 +18892,10 @@ void new_script_vars(scid_T id) * Initialize dictionary "dict" as a scope and set variable "dict_var" to * point to it. */ -void init_var_dict(dict_T *dict, dictitem_T *dict_var, int scope) +void init_var_dict(dict_T *dict, ScopeDictDictItem *dict_var, int scope) { hash_init(&dict->dv_hashtab); - dict->dv_lock = 0; + dict->dv_lock = VAR_UNLOCKED; dict->dv_scope = scope; dict->dv_refcount = DO_NOT_FREE_CNT; dict->dv_copyID = 0; @@ -19751,7 +18915,7 @@ void unref_var_dict(dict_T *dict) /* Now the dict needs to be freed if no one else is using it, go back to * normal reference counting. */ dict->dv_refcount -= DO_NOT_FREE_CNT - 1; - dict_unref(dict); + tv_dict_unref(dict); } /* @@ -19782,9 +18946,9 @@ static void vars_clear_ext(hashtab_T *ht, int free_val) // Free the variable. Don't remove it from the hashtab, // ht_array might change then. hash_clear() takes care of it // later. - v = HI2DI(hi); + v = TV_DICT_HI2DI(hi); if (free_val) { - clear_tv(&v->di_tv); + tv_clear(&v->di_tv); } if (v->di_flags & DI_FLAGS_ALLOC) { xfree(v); @@ -19801,38 +18965,37 @@ static void vars_clear_ext(hashtab_T *ht, int free_val) */ static void delete_var(hashtab_T *ht, hashitem_T *hi) { - dictitem_T *di = HI2DI(hi); + dictitem_T *di = TV_DICT_HI2DI(hi); hash_remove(ht, hi); - clear_tv(&di->di_tv); + tv_clear(&di->di_tv); xfree(di); } /* * List the value of one internal variable. */ -static void list_one_var(dictitem_T *v, char_u *prefix, int *first) +static void list_one_var(dictitem_T *v, const char *prefix, int *first) { - char_u *s = (char_u *) encode_tv2echo(&v->di_tv, NULL); - list_one_var_a(prefix, v->di_key, v->di_tv.v_type, - s == NULL ? (char_u *)"" : s, first); + char *const s = encode_tv2echo(&v->di_tv, NULL); + list_one_var_a(prefix, (const char *)v->di_key, STRLEN(v->di_key), + v->di_tv.v_type, (s == NULL ? "" : s), first); xfree(s); } -static void -list_one_var_a ( - char_u *prefix, - char_u *name, - int type, - char_u *string, - int *first /* when TRUE clear rest of screen and set to FALSE */ -) +/// @param[in] name_len Length of the name. May be -1, in this case strlen() +/// will be used. +/// @param[in,out] first When true clear rest of screen and set to false. +static void list_one_var_a(const char *prefix, const char *name, + const ptrdiff_t name_len, const int type, + const char *string, int *first) { - /* don't use msg() or msg_attr() to avoid overwriting "v:statusmsg" */ + // don't use msg() or msg_attr() to avoid overwriting "v:statusmsg" msg_start(); msg_puts(prefix); - if (name != NULL) /* "a:" vars don't have a name stored */ - msg_puts(name); + if (name != NULL) { // "a:" vars don't have a name stored + msg_puts_attr_len(name, name_len, 0); + } msg_putchar(' '); msg_advance(22); if (type == VAR_NUMBER) { @@ -19850,10 +19013,10 @@ list_one_var_a ( } else msg_putchar(' '); - msg_outtrans(string); + msg_outtrans((char_u *)string); if (type == VAR_FUNC || type == VAR_PARTIAL) { - msg_puts((char_u *)"()"); + msg_puts("()"); } if (*first) { msg_clr_eos(); @@ -19861,46 +19024,47 @@ list_one_var_a ( } } -/* - * Set variable "name" to value in "tv". - * If the variable already exists, the value is updated. - * Otherwise the variable is created. - */ -static void -set_var ( - char_u *name, - typval_T *tv, - int copy /* make copy of value in "tv" */ -) +/// Set variable to the given value +/// +/// If the variable already exists, the value is updated. Otherwise the variable +/// is created. +/// +/// @param[in] name Variable name to set. +/// @param[in] name_len Length of the variable name. +/// @param tv Variable value. +/// @param[in] copy True if value in tv is to be copied. +static void set_var(const char *name, const size_t name_len, typval_T *const tv, + const bool copy) + FUNC_ATTR_NONNULL_ALL { 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); - } + const char *varname; + ht = find_var_ht_dict(name, name_len, &varname, &dict); + const bool watched = tv_dict_is_watched(dict); if (ht == NULL || *varname == NUL) { EMSG2(_(e_illvar), name); return; } - v = find_var_in_ht(ht, 0, varname, TRUE); + v = find_var_in_ht(ht, 0, varname, name_len - (size_t)(varname - name), true); - if ((tv->v_type == VAR_FUNC || tv->v_type == VAR_PARTIAL) - && var_check_func_name(name, v == NULL)) { + // Search in parent scope which is possible to reference from lambda + if (v == NULL) { + v = find_var_in_scoped_ht((const char *)name, name_len, true); + } + + if (tv_is_func(*tv) && !var_check_func_name(name, v == NULL)) { return; } + typval_T oldtv = TV_INITIAL_VALUE; if (v != NULL) { // existing variable, need to clear the value - if (var_check_ro(v->di_flags, name, false) - || tv_check_lock(v->di_tv.v_lock, name, false)) { + if (var_check_ro(v->di_flags, name, name_len) + || tv_check_lock(v->di_tv.v_lock, name, name_len)) { return; } @@ -19909,19 +19073,19 @@ set_var ( if (ht == &vimvarht) { if (v->di_tv.v_type == VAR_STRING) { xfree(v->di_tv.vval.v_string); - if (copy || tv->v_type != VAR_STRING) - v->di_tv.vval.v_string = vim_strsave(get_tv_string(tv)); - else { + if (copy || tv->v_type != VAR_STRING) { + v->di_tv.vval.v_string = (char_u *)xstrdup(tv_get_string(tv)); + } else { // Take over the string to avoid an extra alloc/free. v->di_tv.vval.v_string = tv->vval.v_string; tv->vval.v_string = NULL; } return; } else if (v->di_tv.v_type == VAR_NUMBER) { - v->di_tv.vval.v_number = get_tv_number(tv); - if (STRCMP(varname, "searchforward") == 0) + v->di_tv.vval.v_number = tv_get_number(tv); + if (strcmp(varname, "searchforward") == 0) { set_search_direction(v->di_tv.vval.v_number ? '/' : '?'); - else if (STRCMP(varname, "hlsearch") == 0) { + } else if (strcmp(varname, "hlsearch") == 0) { no_hlsearch = !v->di_tv.vval.v_number; redraw_all_later(SOME_VALID); } @@ -19932,23 +19096,24 @@ set_var ( } if (watched) { - copy_tv(&v->di_tv, &oldtv); + tv_copy(&v->di_tv, &oldtv); } - clear_tv(&v->di_tv); - } else { /* add a new variable */ - /* Can't add "v:" variable. */ + tv_clear(&v->di_tv); + } else { // Add a new variable. + // Can't add "v:" variable. if (ht == &vimvarht) { - EMSG2(_(e_illvar), name); + emsgf(_(e_illvar), name); return; } - /* Make sure the variable name is valid. */ - if (!valid_varname(varname)) + // Make sure the variable name is valid. + if (!valid_varname(varname)) { return; + } - v = xmalloc(sizeof(dictitem_T) + STRLEN(varname)); + v = xmalloc(sizeof(dictitem_T) + strlen(varname)); STRCPY(v->di_key, varname); - if (hash_add(ht, DI2HIKEY(v)) == FAIL) { + if (tv_dict_add(dict, v) == FAIL) { xfree(v); return; } @@ -19956,167 +19121,153 @@ set_var ( } if (copy || tv->v_type == VAR_NUMBER || tv->v_type == VAR_FLOAT) { - copy_tv(tv, &v->di_tv); + tv_copy(tv, &v->di_tv); } else { v->di_tv = *tv; v->di_tv.v_lock = 0; - init_tv(tv); + tv_init(tv); } if (watched) { if (oldtv.v_type == VAR_UNKNOWN) { - dictwatcher_notify(dict, (char *)v->di_key, &v->di_tv, NULL); + tv_dict_watcher_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); + tv_dict_watcher_notify(dict, (char *)v->di_key, &v->di_tv, &oldtv); + tv_clear(&oldtv); } } } -// Return true if di_flags "flags" indicates variable "name" is read-only. -// Also give an error message. -static bool var_check_ro(int flags, char_u *name, bool use_gettext) +/// Check whether variable is read-only (DI_FLAGS_RO, DI_FLAGS_RO_SBX) +/// +/// Also gives an error message. +/// +/// @param[in] flags di_flags attribute value. +/// @param[in] name Variable name, for use in error message. +/// @param[in] name_len Variable name length. Use #TV_TRANSLATE to translate +/// variable name and compute the length. Use #TV_CSTRING +/// to compute the length with strlen() without +/// translating. +/// +/// Both #TV_โฆ values are used for optimization purposes: +/// variable name with its length is needed only in case +/// of error, when no error occurs computing them is +/// a waste of CPU resources. This especially applies to +/// gettext. +/// +/// @return True if variable is read-only: either always or in sandbox when +/// sandbox is enabled, false otherwise. +bool var_check_ro(const int flags, const char *name, + size_t name_len) + FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL { + const char *error_message = NULL; if (flags & DI_FLAGS_RO) { - EMSG2(_(e_readonlyvar), use_gettext ? (char_u *)_(name) : name); - return true; + error_message = N_(e_readonlyvar); + } else if ((flags & DI_FLAGS_RO_SBX) && sandbox) { + error_message = N_("E794: Cannot set variable in the sandbox: \"%.*s\""); } - if ((flags & DI_FLAGS_RO_SBX) && sandbox) { - EMSG2(_(e_readonlysbx), use_gettext ? (char_u *)_(name) : name); - return true; + + if (error_message == NULL) { + return false; } - return false; + if (name_len == TV_TRANSLATE) { + name = _(name); + name_len = strlen(name); + } else if (name_len == TV_CSTRING) { + name_len = strlen(name); + } + + emsgf(_(error_message), (int)name_len, name); + + return true; } -// Return true if di_flags "flags" indicates variable "name" is fixed. -// Also give an error message. -static bool var_check_fixed(int flags, char_u *name, bool use_gettext) +/// Check whether variable is fixed (DI_FLAGS_FIX) +/// +/// Also gives an error message. +/// +/// @param[in] flags di_flags attribute value. +/// @param[in] name Variable name, for use in error message. +/// @param[in] name_len Variable name length. Use #TV_TRANSLATE to translate +/// variable name and compute the length. Use #TV_CSTRING +/// to compute the length with strlen() without +/// translating. +/// +/// Both #TV_โฆ values are used for optimization purposes: +/// variable name with its length is needed only in case +/// of error, when no error occurs computing them is +/// a waste of CPU resources. This especially applies to +/// gettext. +/// +/// @return True if variable is fixed, false otherwise. +static bool var_check_fixed(const int flags, const char *name, + size_t name_len) + FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL { if (flags & DI_FLAGS_FIX) { - EMSG2(_("E795: Cannot delete variable %s"), - use_gettext ? (char_u *)_(name) : name); + if (name_len == TV_TRANSLATE) { + name = _(name); + name_len = strlen(name); + } else if (name_len == TV_CSTRING) { + name_len = strlen(name); + } + emsgf(_("E795: Cannot delete variable %.*s"), (int)name_len, name); return true; } return false; } -/* - * Check if a funcref is assigned to a valid variable name. - * Return TRUE and give an error if not. - */ -static int -var_check_func_name ( - char_u *name, /* points to start of variable name */ - int new_var /* TRUE when creating the variable */ -) +// TODO(ZyX-I): move to eval/expressions + +/// Check if name is a valid name to assign funcref to +/// +/// @param[in] name Possible function/funcref name. +/// @param[in] new_var True if it is a name for a variable. +/// +/// @return false in case of error, true in case of success. Also gives an +/// error message if appropriate. +bool var_check_func_name(const char *const name, const bool new_var) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT { // Allow for w: b: s: and t:. if (!(vim_strchr((char_u *)"wbst", name[0]) != NULL && name[1] == ':') && !ASCII_ISUPPER((name[0] != NUL && name[1] == ':') ? name[2] : name[0])) { EMSG2(_("E704: Funcref variable name must start with a capital: %s"), name); - return TRUE; + return false; } - /* Don't allow hiding a function. When "v" is not NULL we might be - * assigning another function to the same var, the type is checked - * below. */ - if (new_var && function_exists(name)) { + // Don't allow hiding a function. When "v" is not NULL we might be + // assigning another function to the same var, the type is checked + // below. + if (new_var && function_exists((const char *)name, false)) { EMSG2(_("E705: Variable name conflicts with existing function: %s"), - name); - return TRUE; + name); + return false; } - return FALSE; + return true; } -/* - * Check if a variable name is valid. - * Return FALSE and give an error if not. - */ -static int valid_varname(char_u *varname) -{ - char_u *p; +// TODO(ZyX-I): move to eval/expressions - for (p = varname; *p != NUL; ++p) - if (!eval_isnamec1(*p) && (p == varname || !ascii_isdigit(*p)) +/// Check if a variable name is valid +/// +/// @param[in] varname Variable name to check. +/// +/// @return false when variable name is not valid, true when it is. Also gives +/// an error message if appropriate. +bool valid_varname(const char *varname) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ + for (const char *p = varname; *p != NUL; p++) { + if (!eval_isnamec1((int)(uint8_t)(*p)) + && (p == varname || !ascii_isdigit(*p)) && *p != AUTOLOAD_CHAR) { - EMSG2(_(e_illvar), varname); - return FALSE; + emsgf(_(e_illvar), varname); + return false; } - return TRUE; -} - -// Return true if typeval "tv" is set to be locked (immutable). -// Also give an error message, using "name" or _("name") when use_gettext is -// true. -static bool tv_check_lock(int lock, char_u *name, bool use_gettext) -{ - if (lock & VAR_LOCKED) { - EMSG2(_("E741: Value is locked: %s"), - name == NULL - ? (char_u *)_("Unknown") - : use_gettext ? (char_u *)_(name) - : name); - return true; - } - if (lock & VAR_FIXED) { - EMSG2(_("E742: Cannot change value of %s"), - name == NULL - ? (char_u *)_("Unknown") - : use_gettext ? (char_u *)_(name) - : name); - return true; - } - return false; -} - -/* - * Copy the values from typval_T "from" to typval_T "to". - * When needed allocates string or increases reference count. - * Does not make a copy of a list or dict but copies the reference! - * It is OK for "from" and "to" to point to the same item. This is used to - * make a copy later. - */ -void copy_tv(typval_T *from, typval_T *to) -{ - to->v_type = from->v_type; - to->v_lock = 0; - memmove(&to->vval, &from->vval, sizeof(to->vval)); - switch (from->v_type) { - case VAR_NUMBER: - case VAR_FLOAT: - case VAR_SPECIAL: - break; - case VAR_STRING: - case VAR_FUNC: - if (from->vval.v_string != NULL) { - to->vval.v_string = vim_strsave(from->vval.v_string); - if (from->v_type == VAR_FUNC) { - func_ref(to->vval.v_string); - } - } - break; - case VAR_PARTIAL: - if (from->vval.v_partial == NULL) { - to->vval.v_partial = NULL; - } else { - to->vval.v_partial = from->vval.v_partial; - (to->vval.v_partial->pt_refcount)++; - } - break; - case VAR_LIST: - if (from->vval.v_list != NULL) { - to->vval.v_list->lv_refcount++; - } - break; - case VAR_DICT: - if (from->vval.v_dict != NULL) { - to->vval.v_dict->dv_refcount++; - } - break; - case VAR_UNKNOWN: - EMSG2(_(e_intern2), "copy_tv(UNKNOWN)"); - break; } + return true; } /// Make a copy of an item @@ -20134,7 +19285,7 @@ void copy_tv(typval_T *from, typval_T *to) /// list[1]`) var_item_copy with zero copyID will emit /// a copy with (`copy[0] isnot copy[1]`), with non-zero it /// will emit a copy with (`copy[0] is copy[1]`) like in the -/// original list. Not use when deep is false. +/// original list. Not used when deep is false. int var_item_copy(const vimconv_T *const conv, typval_T *const from, typval_T *const to, @@ -20157,11 +19308,12 @@ int var_item_copy(const vimconv_T *const conv, case VAR_FUNC: case VAR_PARTIAL: case VAR_SPECIAL: - copy_tv(from, to); + tv_copy(from, to); break; case VAR_STRING: - if (conv == NULL || conv->vc_type == CONV_NONE) { - copy_tv(from, to); + if (conv == NULL || conv->vc_type == CONV_NONE + || from->vval.v_string == NULL) { + tv_copy(from, to); } else { to->v_type = VAR_STRING; to->v_lock = 0; @@ -20183,10 +19335,11 @@ int var_item_copy(const vimconv_T *const conv, to->vval.v_list = from->vval.v_list->lv_copylist; ++to->vval.v_list->lv_refcount; } else { - to->vval.v_list = list_copy(conv, from->vval.v_list, deep, copyID); + to->vval.v_list = tv_list_copy(conv, from->vval.v_list, deep, copyID); } - if (to->vval.v_list == NULL) + if (to->vval.v_list == NULL && from->vval.v_list != NULL) { ret = FAIL; + } break; case VAR_DICT: to->v_type = VAR_DICT; @@ -20198,10 +19351,11 @@ int var_item_copy(const vimconv_T *const conv, to->vval.v_dict = from->vval.v_dict->dv_copydict; ++to->vval.v_dict->dv_refcount; } else { - to->vval.v_dict = dict_copy(conv, from->vval.v_dict, deep, copyID); + to->vval.v_dict = tv_dict_copy(conv, from->vval.v_dict, deep, copyID); } - if (to->vval.v_dict == NULL) + if (to->vval.v_dict == NULL && from->vval.v_dict != NULL) { ret = FAIL; + } break; case VAR_UNKNOWN: EMSG2(_(e_intern2), "var_item_copy(UNKNOWN)"); @@ -20220,7 +19374,6 @@ void ex_echo(exarg_T *eap) { char_u *arg = eap->arg; typval_T rettv; - char_u *p; bool needclr = true; bool atstart = true; @@ -20231,19 +19384,20 @@ void ex_echo(exarg_T *eap) * still need to be cleared. E.g., "echo 22,44". */ need_clr_eos = needclr; - p = arg; - if (eval1(&arg, &rettv, !eap->skip) == FAIL) { - /* - * Report the invalid expression unless the expression evaluation - * has been cancelled due to an aborting error, an interrupt, or an - * exception. - */ - if (!aborting()) - EMSG2(_(e_invexpr2), p); - need_clr_eos = FALSE; - break; + { + char_u *p = arg; + if (eval1(&arg, &rettv, !eap->skip) == FAIL) { + // Report the invalid expression unless the expression evaluation + // has been cancelled due to an aborting error, an interrupt, or an + // exception. + if (!aborting()) { + EMSG2(_(e_invexpr2), p); + } + need_clr_eos = false; + break; + } + need_clr_eos = false; } - need_clr_eos = FALSE; if (!eap->skip) { if (atstart) { @@ -20257,9 +19411,11 @@ void ex_echo(exarg_T *eap) msg_sb_eol(); msg_start(); } - } else if (eap->cmdidx == CMD_echo) - msg_puts_attr((char_u *)" ", echo_attr); - char_u *tofree = p = (char_u *) encode_tv2echo(&rettv, NULL); + } else if (eap->cmdidx == CMD_echo) { + msg_puts_attr(" ", echo_attr); + } + char *tofree = encode_tv2echo(&rettv, NULL); + const char *p = tofree; if (p != NULL) { for (; *p != NUL && !got_int; ++p) { if (*p == '\n' || *p == '\r' || *p == TAB) { @@ -20268,21 +19424,22 @@ void ex_echo(exarg_T *eap) msg_clr_eos(); needclr = false; } - msg_putchar_attr(*p, echo_attr); + msg_putchar_attr((uint8_t)(*p), echo_attr); } else { if (has_mbyte) { - int i = (*mb_ptr2len)(p); + int i = (*mb_ptr2len)((const char_u *)p); - (void)msg_outtrans_len_attr(p, i, echo_attr); + (void)msg_outtrans_len_attr((char_u *)p, i, echo_attr); p += i - 1; - } else - (void)msg_outtrans_len_attr(p, 1, echo_attr); + } else { + (void)msg_outtrans_len_attr((char_u *)p, 1, echo_attr); + } } } } xfree(tofree); } - clear_tv(&rettv); + tv_clear(&rettv); arg = skipwhite(arg); } eap->nextcmd = check_nextcmd(arg); @@ -20326,7 +19483,6 @@ void ex_execute(exarg_T *eap) int ret = OK; char_u *p; garray_T ga; - int len; int save_did_emsg; ga_init(&ga, 1, 80); @@ -20348,16 +19504,17 @@ void ex_execute(exarg_T *eap) } if (!eap->skip) { - p = get_tv_string(&rettv); - len = (int)STRLEN(p); + const char *const argstr = tv_get_string(&rettv); + const size_t len = strlen(argstr); ga_grow(&ga, len + 2); - if (!GA_EMPTY(&ga)) + if (!GA_EMPTY(&ga)) { ((char_u *)(ga.ga_data))[ga.ga_len++] = ' '; - STRCPY((char_u *)(ga.ga_data) + ga.ga_len, p); + } + memcpy((char_u *)(ga.ga_data) + ga.ga_len, argstr, len + 1); ga.ga_len += len; } - clear_tv(&rettv); + tv_clear(&rettv); arg = skipwhite(arg); } @@ -20390,9 +19547,9 @@ void ex_execute(exarg_T *eap) * Returns NULL when no option name found. Otherwise pointer to the char * after the option name. */ -static char_u *find_option_end(char_u **arg, int *opt_flags) +static const char *find_option_end(const char **const arg, int *const opt_flags) { - char_u *p = *arg; + const char *p = *arg; ++p; if (*p == 'g' && p[1] == ':') { @@ -20401,18 +19558,22 @@ static char_u *find_option_end(char_u **arg, int *opt_flags) } else if (*p == 'l' && p[1] == ':') { *opt_flags = OPT_LOCAL; p += 2; - } else + } else { *opt_flags = 0; + } - if (!ASCII_ISALPHA(*p)) + if (!ASCII_ISALPHA(*p)) { return NULL; + } *arg = p; - if (p[0] == 't' && p[1] == '_' && p[2] != NUL && p[3] != NUL) - p += 4; /* termcap option */ - else - while (ASCII_ISALPHA(*p)) - ++p; + if (p[0] == 't' && p[1] == '_' && p[2] != NUL && p[3] != NUL) { + p += 4; // t_xx/termcap option + } else { + while (ASCII_ISALPHA(*p)) { + p++; + } + } return p; } @@ -20431,10 +19592,10 @@ void ex_function(exarg_T *eap) char_u *line_arg = NULL; garray_T newargs; garray_T newlines; - int varargs = FALSE; - int mustend = FALSE; + int varargs = false; int flags = 0; ufunc_T *fp; + bool overwrite = false; int indent; int nesting; char_u *skip_until = NULL; @@ -20457,8 +19618,9 @@ void ex_function(exarg_T *eap) if (!HASHITEM_EMPTY(hi)) { --todo; fp = HI2UF(hi); - if (!isdigit(*fp->uf_name)) - list_func_head(fp, FALSE); + if (!func_name_refcount(fp->uf_name)) { + list_func_head(fp, false); + } } } } @@ -20524,8 +19686,9 @@ void ex_function(exarg_T *eap) * interrupt, or an exception. */ if (!aborting()) { - if (!eap->skip && fudi.fd_newkey != NULL) + if (fudi.fd_newkey != NULL) { EMSG2(_(e_dictkey), fudi.fd_newkey); + } xfree(fudi.fd_newkey); return; } else @@ -20567,7 +19730,7 @@ void ex_function(exarg_T *eap) } if (!got_int) { msg_putchar('\n'); - msg_puts((char_u *)" endfunction"); + msg_puts(" endfunction"); } } else emsg_funcname(N_("E123: Undefined function: %s"), name); @@ -20600,9 +19763,7 @@ void ex_function(exarg_T *eap) arg = name; else arg = fudi.fd_newkey; - if (arg != NULL && (fudi.fd_di == NULL - || (fudi.fd_di->di_tv.v_type != VAR_FUNC - && fudi.fd_di->di_tv.v_type != VAR_PARTIAL))) { + if (arg != NULL && (fudi.fd_di == NULL || !tv_is_func(fudi.fd_di->di_tv))) { int j = (*arg == K_SPECIAL) ? 3 : 0; while (arg[j] != NUL && (j == 0 ? eval_isnamec1(arg[j]) : eval_isnamec(arg[j]))) @@ -20615,59 +19776,11 @@ void ex_function(exarg_T *eap) EMSG(_("E862: Cannot use g: here")); } - /* - * Isolate the arguments: "arg1, arg2, ...)" - */ - while (*p != ')') { - if (p[0] == '.' && p[1] == '.' && p[2] == '.') { - varargs = TRUE; - p += 3; - mustend = TRUE; - } else { - arg = p; - while (ASCII_ISALNUM(*p) || *p == '_') - ++p; - if (arg == p || isdigit(*arg) - || (p - arg == 9 && STRNCMP(arg, "firstline", 9) == 0) - || (p - arg == 8 && STRNCMP(arg, "lastline", 8) == 0)) { - if (!eap->skip) - EMSG2(_("E125: Illegal argument: %s"), arg); - break; - } - ga_grow(&newargs, 1); - c = *p; - *p = NUL; - arg = vim_strsave(arg); - - /* Check for duplicate argument name. */ - for (int i = 0; i < newargs.ga_len; ++i) - if (STRCMP(((char_u **)(newargs.ga_data))[i], arg) == 0) { - EMSG2(_("E853: Duplicate argument name: %s"), arg); - xfree(arg); - goto erret; - } - - ((char_u **)(newargs.ga_data))[newargs.ga_len] = arg; - *p = c; - newargs.ga_len++; - if (*p == ',') - ++p; - else - mustend = TRUE; - } - p = skipwhite(p); - if (mustend && *p != ')') { - if (!eap->skip) - EMSG2(_(e_invarg2), eap->arg); - break; - } - } - if (*p != ')') { - goto erret; + if (get_function_args(&p, ')', &newargs, &varargs, eap->skip) == FAIL) { + goto errret_2; } - ++p; // skip the ')' - /* find extra arguments "range", "dict" and "abort" */ + // find extra arguments "range", "dict", "abort" and "closure" for (;; ) { p = skipwhite(p); if (STRNCMP(p, "range", 5) == 0) { @@ -20679,16 +19792,28 @@ void ex_function(exarg_T *eap) } else if (STRNCMP(p, "abort", 5) == 0) { flags |= FC_ABORT; p += 5; - } else + } else if (STRNCMP(p, "closure", 7) == 0) { + flags |= FC_CLOSURE; + p += 7; + if (current_funccal == NULL) { + emsg_funcname(N_ + ("E932: Closure function should not be at top level: %s"), + name == NULL ? (char_u *)"" : name); + goto erret; + } + } else { break; + } } /* When there is a line break use what follows for the function body. * Makes 'exe "func Test()\n...\nendfunc"' work. */ - if (*p == '\n') + const char *const end = (const char *)p + STRLEN(p); + if (*p == '\n') { line_arg = p + 1; - else if (*p != NUL && *p != '"' && !eap->skip && !did_emsg) - EMSG(_(e_trailing)); + } else if (*p != NUL && *p != '"' && !eap->skip && !did_emsg) { + emsgf(_(e_trailing)); + } /* * Read the body of the function, until ":endfunction" is found. @@ -20762,8 +19887,30 @@ void ex_function(exarg_T *eap) /* Check for "endfunction". */ if (checkforcmd(&p, "endfunction", 4) && nesting-- == 0) { - if (line_arg == NULL) + if (*p == '!') { + p++; + } + const char *const comment_start = strchr((const char *)p, '"'); + const char *const endfunc_end = (comment_start + ? strchr(comment_start, '\n') + : strpbrk((const char *)p, "\n|")); + p = (endfunc_end + ? (char_u *)endfunc_end + : p + STRLEN(p)); + if (*p == '|') { + emsgf(_(e_trailing2), p); + if (line_arg == NULL) { + xfree(theline); + } + goto erret; + } + if (line_arg == NULL) { xfree(theline); + } else { + if ((const char *)p < end) { + eap->nextcmd = p + 1; + } + } break; } @@ -20782,7 +19929,7 @@ void ex_function(exarg_T *eap) if (*p == '!') { p = skipwhite(p + 1); } - p += eval_fname_script(p); + p += eval_fname_script((const char *)p); xfree(trans_function_name(&p, true, 0, NULL, NULL)); if (*skipwhite(p) == '(') { nesting++; @@ -20790,9 +19937,15 @@ void ex_function(exarg_T *eap) } } - /* Check for ":append" or ":insert". */ + // Check for ":append", ":change", ":insert". p = skip_range(p, NULL); if ((p[0] == 'a' && (!ASCII_ISALPHA(p[1]) || p[1] == 'p')) + || (p[0] == 'c' + && (!ASCII_ISALPHA(p[1]) + || (p[1] == 'h' && (!ASCII_ISALPHA(p[2]) + || (p[2] == 'a' + && (STRNCMP(&p[3], "nge", 3) != 0 + || !ASCII_ISALPHA(p[6]))))))) || (p[0] == 'i' && (!ASCII_ISALPHA(p[1]) || (p[1] == 'n' && (!ASCII_ISALPHA(p[2]) @@ -20857,7 +20010,7 @@ void ex_function(exarg_T *eap) * If there are no errors, add the function */ if (fudi.fd_dict == NULL) { - v = find_var(name, &ht, FALSE); + v = find_var((const char *)name, STRLEN(name), &ht, false); if (v != NULL && v->di_tv.v_type == VAR_FUNC) { emsg_funcname(N_("E707: Function name conflicts with variable: %s"), name); @@ -20870,16 +20023,25 @@ void ex_function(exarg_T *eap) emsg_funcname(e_funcexts, name); goto erret; } - if (fp->uf_refcount > 1 || fp->uf_calls > 0) { + if (fp->uf_calls > 0) { emsg_funcname(N_("E127: Cannot redefine function %s: It is in use"), name); goto erret; } - /* redefine existing function */ - ga_clear_strings(&(fp->uf_args)); - ga_clear_strings(&(fp->uf_lines)); - xfree(name); - name = NULL; + if (fp->uf_refcount > 1) { + // This function is referenced somewhere, don't redefine it but + // create a new one. + (fp->uf_refcount)--; + fp->uf_flags |= FC_REMOVED; + fp = NULL; + overwrite = true; + } else { + // redefine existing function + ga_clear_strings(&(fp->uf_args)); + ga_clear_strings(&(fp->uf_lines)); + xfree(name); + name = NULL; + } } } else { char numbuf[20]; @@ -20890,11 +20052,13 @@ void ex_function(exarg_T *eap) goto erret; } if (fudi.fd_di == NULL) { - if (tv_check_lock(fudi.fd_dict->dv_lock, eap->arg, false)) { + if (tv_check_lock(fudi.fd_dict->dv_lock, (const char *)eap->arg, + TV_CSTRING)) { // Can't add a function to a locked dictionary goto erret; } - } else if (tv_check_lock(fudi.fd_di->di_tv.v_lock, eap->arg, false)) { + } else if (tv_check_lock(fudi.fd_di->di_tv.v_lock, (const char *)eap->arg, + TV_CSTRING)) { // Can't change an existing function if it is locked goto erret; } @@ -20914,7 +20078,7 @@ void ex_function(exarg_T *eap) /* Check that the autoload name matches the script name. */ int j = FAIL; if (sourcing_name != NULL) { - scriptname = autoload_name(name); + scriptname = (char_u *)autoload_name((const char *)name, STRLEN(name)); p = vim_strchr(scriptname, '/'); plen = (int)STRLEN(p); slen = (int)STRLEN(sourcing_name); @@ -20931,20 +20095,21 @@ void ex_function(exarg_T *eap) } } - fp = xmalloc(sizeof(ufunc_T) + STRLEN(name)); + fp = xcalloc(1, sizeof(ufunc_T) + STRLEN(name)); if (fudi.fd_dict != NULL) { if (fudi.fd_di == NULL) { - /* add new dict entry */ - fudi.fd_di = dictitem_alloc(fudi.fd_newkey); - if (dict_add(fudi.fd_dict, fudi.fd_di) == FAIL) { + // Add new dict entry + fudi.fd_di = tv_dict_item_alloc((const char *)fudi.fd_newkey); + if (tv_dict_add(fudi.fd_dict, fudi.fd_di) == FAIL) { xfree(fudi.fd_di); xfree(fp); goto erret; } - } else - /* overwrite existing dict entry */ - clear_tv(&fudi.fd_di->di_tv); + } else { + // Overwrite existing dict entry. + tv_clear(&fudi.fd_di->di_tv); + } fudi.fd_di->di_tv.v_type = VAR_FUNC; fudi.fd_di->di_tv.v_lock = 0; fudi.fd_di->di_tv.vval.v_string = vim_strsave(name); @@ -20955,14 +20120,22 @@ void ex_function(exarg_T *eap) /* insert the new function in the function list */ STRCPY(fp->uf_name, name); - if (hash_add(&func_hashtab, UF2HIKEY(fp)) == FAIL) { - xfree(fp); - goto erret; + if (overwrite) { + hi = hash_find(&func_hashtab, name); + hi->hi_key = UF2HIKEY(fp); + } else if (hash_add(&func_hashtab, UF2HIKEY(fp)) == FAIL) { + xfree(fp); + goto erret; } + fp->uf_refcount = 1; } - fp->uf_refcount = 1; fp->uf_args = newargs; fp->uf_lines = newlines; + if ((flags & FC_CLOSURE) != 0) { + register_closure(fp); + } else { + fp->uf_scoped = NULL; + } fp->uf_tml_count = NULL; fp->uf_tml_total = NULL; fp->uf_tml_self = NULL; @@ -20977,6 +20150,7 @@ void ex_function(exarg_T *eap) erret: ga_clear_strings(&newargs); +errret_2: ga_clear_strings(&newlines); ret_free: xfree(skip_until); @@ -20986,30 +20160,29 @@ ret_free: need_wait_return |= saved_wait_return; } -/* - * Get a function name, translating "<SID>" and "<SNR>". - * Also handles a Funcref in a List or Dictionary. - * Returns the function name in allocated memory, or NULL for failure. - * flags: - * TFN_INT: internal function name OK - * TFN_QUIET: be quiet - * TFN_NO_AUTOLOAD: do not use script autoloading - * Advances "pp" to just after the function name (if no error). - */ +/// Get a function name, translating "<SID>" and "<SNR>". +/// Also handles a Funcref in a List or Dictionary. +/// flags: +/// TFN_INT: internal function name OK +/// TFN_QUIET: be quiet +/// TFN_NO_AUTOLOAD: do not use script autoloading +/// TFN_NO_DEREF: do not dereference a Funcref +/// Advances "pp" to just after the function name (if no error). +/// +/// @return the function name in allocated memory, or NULL for failure. static char_u * -trans_function_name ( +trans_function_name( char_u **pp, - int skip, /* only find the end, don't evaluate */ + int skip, // only find the end, don't evaluate int flags, funcdict_T *fdp, // return: info about dictionary used partial_T **partial // return: partial of a FuncRef ) { char_u *name = NULL; - char_u *start; - char_u *end; + const char_u *start; + const char_u *end; int lead; - char_u sid_buf[20]; int len; lval_T lv; @@ -21022,19 +20195,20 @@ trans_function_name ( if ((*pp)[0] == K_SPECIAL && (*pp)[1] == KS_EXTRA && (*pp)[2] == (int)KE_SNR) { *pp += 3; - len = get_id_len(pp) + 3; - return vim_strnsave(start, len); + len = get_id_len((const char **)pp) + 3; + return (char_u *)xmemdupz(start, len); } /* A name starting with "<SID>" or "<SNR>" is local to a script. But * don't skip over "s:", get_lval() needs it for "s:dict.func". */ - lead = eval_fname_script(start); - if (lead > 2) + lead = eval_fname_script((const char *)start); + if (lead > 2) { start += lead; + } - /* Note that TFN_ flags use the same values as GLV_ flags. */ - end = get_lval(start, NULL, &lv, FALSE, skip, flags, - lead > 2 ? 0 : FNE_CHECK_START); + // Note that TFN_ flags use the same values as GLV_ flags. + end = get_lval((char_u *)start, NULL, &lv, false, skip, flags, + lead > 2 ? 0 : FNE_CHECK_START); if (end == start) { if (!skip) EMSG(_("E129: Function name required")); @@ -21047,10 +20221,12 @@ trans_function_name ( * interrupt, or an exception. */ if (!aborting()) { - if (end != NULL) - EMSG2(_(e_invarg2), start); - } else - *pp = find_name_end(start, NULL, NULL, FNE_INCL_BR); + if (end != NULL) { + emsgf(_(e_invarg2), start); + } + } else { + *pp = (char_u *)find_name_end(start, NULL, NULL, FNE_INCL_BR); + } goto theend; } @@ -21063,11 +20239,11 @@ trans_function_name ( } if (lv.ll_tv->v_type == VAR_FUNC && lv.ll_tv->vval.v_string != NULL) { name = vim_strsave(lv.ll_tv->vval.v_string); - *pp = end; + *pp = (char_u *)end; } else if (lv.ll_tv->v_type == VAR_PARTIAL && lv.ll_tv->vval.v_partial != NULL) { - name = vim_strsave(lv.ll_tv->vval.v_partial->pt_name); - *pp = end; + name = vim_strsave(partial_name(lv.ll_tv->vval.v_partial)); + *pp = (char_u *)end; if (partial != NULL) { *partial = lv.ll_tv->vval.v_partial; } @@ -21077,7 +20253,7 @@ trans_function_name ( || fdp->fd_newkey == NULL)) { EMSG(_(e_funcref)); } else { - *pp = end; + *pp = (char_u *)end; } name = NULL; } @@ -21085,29 +20261,30 @@ trans_function_name ( } if (lv.ll_name == NULL) { - /* Error found, but continue after the function name. */ - *pp = end; + // Error found, but continue after the function name. + *pp = (char_u *)end; goto theend; } /* Check if the name is a Funcref. If so, use the value. */ if (lv.ll_exp_name != NULL) { - len = (int)STRLEN(lv.ll_exp_name); + len = (int)strlen(lv.ll_exp_name); name = deref_func_name(lv.ll_exp_name, &len, partial, flags & TFN_NO_AUTOLOAD); - if (name == lv.ll_exp_name) { + if ((const char *)name == lv.ll_exp_name) { name = NULL; } - } else { + } else if (!(flags & TFN_NO_DEREF)) { len = (int)(end - *pp); - name = deref_func_name(*pp, &len, partial, flags & TFN_NO_AUTOLOAD); + name = deref_func_name((const char *)(*pp), &len, partial, + flags & TFN_NO_AUTOLOAD); if (name == *pp) { name = NULL; } } if (name != NULL) { name = vim_strsave(name); - *pp = end; + *pp = (char_u *)end; if (strncmp((char *)name, "<SNR>", 5) == 0) { // Change "<SNR>" to the byte sequence. name[0] = K_SPECIAL; @@ -21119,12 +20296,13 @@ trans_function_name ( } if (lv.ll_exp_name != NULL) { - len = (int)STRLEN(lv.ll_exp_name); + len = (int)strlen(lv.ll_exp_name); if (lead <= 2 && lv.ll_name == lv.ll_exp_name - && STRNCMP(lv.ll_name, "s:", 2) == 0) { - /* When there was "s:" already or the name expanded to get a - * leading "s:" then remove it. */ + && lv.ll_name_len >= 2 && memcmp(lv.ll_name, "s:", 2) == 0) { + // When there was "s:" already or the name expanded to get a + // leading "s:" then remove it. lv.ll_name += 2; + lv.ll_name_len -= 2; len -= 2; lead = 2; } @@ -21132,37 +20310,41 @@ trans_function_name ( // Skip over "s:" and "g:". if (lead == 2 || (lv.ll_name[0] == 'g' && lv.ll_name[1] == ':')) { lv.ll_name += 2; + lv.ll_name_len -= 2; } - len = (int)(end - lv.ll_name); + len = (int)((const char *)end - lv.ll_name); } - /* - * Copy the function name to allocated memory. - * Accept <SID>name() inside a script, translate into <SNR>123_name(). - * Accept <SNR>123_name() outside a script. - */ - if (skip) - lead = 0; /* do nothing */ - else if (lead > 0) { + size_t sid_buf_len = 0; + char sid_buf[20]; + + // Copy the function name to allocated memory. + // Accept <SID>name() inside a script, translate into <SNR>123_name(). + // Accept <SNR>123_name() outside a script. + if (skip) { + lead = 0; // do nothing + } else if (lead > 0) { lead = 3; if ((lv.ll_exp_name != NULL && eval_fname_sid(lv.ll_exp_name)) - || eval_fname_sid(*pp)) { - /* It's "s:" or "<SID>" */ + || eval_fname_sid((const char *)(*pp))) { + // It's "s:" or "<SID>". if (current_SID <= 0) { EMSG(_(e_usingsid)); goto theend; } - sprintf((char *)sid_buf, "%" PRId64 "_", (int64_t)current_SID); - lead += (int)STRLEN(sid_buf); + sid_buf_len = snprintf(sid_buf, sizeof(sid_buf), + "%" PRIdSCID "_", current_SID); + lead += sid_buf_len; } - } else if (!(flags & TFN_INT) && builtin_function(lv.ll_name, len)) { + } else if (!(flags & TFN_INT) + && builtin_function(lv.ll_name, lv.ll_name_len)) { EMSG2(_("E128: Function name must start with a capital or \"s:\": %s"), start); goto theend; } - if (!skip && !(flags & TFN_QUIET)) { - char_u *cp = vim_strchr(lv.ll_name, ':'); + if (!skip && !(flags & TFN_QUIET) && !(flags & TFN_NO_DEREF)) { + char_u *cp = xmemrchr(lv.ll_name, ':', lv.ll_name_len); if (cp != NULL && cp < end) { EMSG2(_("E884: Function name cannot contain a colon: %s"), start); @@ -21175,12 +20357,13 @@ trans_function_name ( name[0] = K_SPECIAL; name[1] = KS_EXTRA; name[2] = (int)KE_SNR; - if (lead > 3) /* If it's "<SID>" */ - STRCPY(name + 3, sid_buf); + if (sid_buf_len > 0) { // If it's "<SID>" + memcpy(name + 3, sid_buf, sid_buf_len); + } } - memmove(name + lead, lv.ll_name, (size_t)len); + memmove(name + lead, lv.ll_name, len); name[lead + len] = NUL; - *pp = end; + *pp = (char_u *)end; theend: clear_lval(&lv); @@ -21192,12 +20375,13 @@ theend: * Return 2 if "p" starts with "s:". * Return 0 otherwise. */ -static int eval_fname_script(char_u *p) +static int eval_fname_script(const char *const p) { - // Use mb_stricmp() because in Turkish comparing the "I" may not work with + // Use mb_strnicmp() because in Turkish comparing the "I" may not work with // the standard library function. - if (p[0] == '<' && (mb_strnicmp(p + 1, (char_u *)"SID>", 4) == 0 - || mb_strnicmp(p + 1, (char_u *)"SNR>", 4) == 0)) { + if (p[0] == '<' + && (mb_strnicmp((char_u *)p + 1, (char_u *)"SID>", 4) == 0 + || mb_strnicmp((char_u *)p + 1, (char_u *)"SNR>", 4) == 0)) { return 5; } if (p[0] == 's' && p[1] == ':') { @@ -21206,13 +20390,19 @@ static int eval_fname_script(char_u *p) return 0; } -/* - * Return TRUE if "p" starts with "<SID>" or "s:". - * Only works if eval_fname_script() returned non-zero for "p"! - */ -static int eval_fname_sid(char_u *p) +/// Check whether function name starts with <SID> or s: +/// +/// @warning Only works for names previously checked by eval_fname_script(), if +/// it returned non-zero. +/// +/// @param[in] name Name to check. +/// +/// @return true if it starts with <SID> or s:, false otherwise. +static inline bool eval_fname_sid(const char *const name) + FUNC_ATTR_PURE FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_WARN_UNUSED_RESULT + FUNC_ATTR_NONNULL_ALL { - return *p == 's' || TOUPPER_ASC(p[2]) == 'I'; + return *name == 's' || TOUPPER_ASC(name[2]) == 'I'; } /* @@ -21226,38 +20416,45 @@ static void list_func_head(ufunc_T *fp, int indent) MSG_PUTS("function "); if (fp->uf_name[0] == K_SPECIAL) { MSG_PUTS_ATTR("<SNR>", hl_attr(HLF_8)); - msg_puts(fp->uf_name + 3); - } else - msg_puts(fp->uf_name); + msg_puts((const char *)fp->uf_name + 3); + } else { + msg_puts((const char *)fp->uf_name); + } msg_putchar('('); int j; - for (j = 0; j < fp->uf_args.ga_len; ++j) { - if (j) - MSG_PUTS(", "); - msg_puts(FUNCARG(fp, j)); + for (j = 0; j < fp->uf_args.ga_len; j++) { + if (j) { + msg_puts(", "); + } + msg_puts((const char *)FUNCARG(fp, j)); } if (fp->uf_varargs) { - if (j) - MSG_PUTS(", "); - MSG_PUTS("..."); + if (j) { + msg_puts(", "); + } + msg_puts("..."); } msg_putchar(')'); - if (fp->uf_flags & FC_ABORT) - MSG_PUTS(" abort"); - if (fp->uf_flags & FC_RANGE) - MSG_PUTS(" range"); - if (fp->uf_flags & FC_DICT) - MSG_PUTS(" dict"); + if (fp->uf_flags & FC_ABORT) { + msg_puts(" abort"); + } + if (fp->uf_flags & FC_RANGE) { + msg_puts(" range"); + } + if (fp->uf_flags & FC_DICT) { + msg_puts(" dict"); + } + if (fp->uf_flags & FC_CLOSURE) { + msg_puts(" closure"); + } msg_clr_eos(); if (p_verbose > 0) last_set_msg(fp->uf_script_ID); } -/* - * Find a function by name, return pointer to it in ufuncs. - * Return NULL for unknown function. - */ -static ufunc_T *find_func(char_u *name) +/// Find a function by name, return pointer to it in ufuncs. +/// @return NULL for unknown function. +static ufunc_T *find_func(const char_u *name) { hashitem_T *hi; @@ -21271,61 +20468,118 @@ static ufunc_T *find_func(char_u *name) void free_all_functions(void) { hashitem_T *hi; + ufunc_T *fp; + uint64_t skipped = 0; + uint64_t todo = 1; + uint64_t used; + + // First clear what the functions contain. Since this may lower the + // reference count of a function, it may also free a function and change + // the hash table. Restart if that happens. + while (todo > 0) { + todo = func_hashtab.ht_used; + for (hi = func_hashtab.ht_array; todo > 0; hi++) { + if (!HASHITEM_EMPTY(hi)) { + // Only free functions that are not refcounted, those are + // supposed to be freed when no longer referenced. + fp = HI2UF(hi); + if (func_name_refcount(fp->uf_name)) { + skipped++; + } else { + used = func_hashtab.ht_used; + func_clear(fp, true); + if (used != func_hashtab.ht_used) { + skipped = 0; + break; + } + } + todo--; + } + } + } - /* Need to start all over every time, because func_free() may change the - * hash table. */ - while (func_hashtab.ht_used > 0) - for (hi = func_hashtab.ht_array;; ++hi) + // Now actually free the functions. Need to start all over every time, + // because func_free() may change the hash table. + skipped = 0; + while (func_hashtab.ht_used > skipped) { + todo = func_hashtab.ht_used; + for (hi = func_hashtab.ht_array; todo > 0; hi++) { if (!HASHITEM_EMPTY(hi)) { - func_free(HI2UF(hi)); - break; + todo--; + // Only free functions that are not refcounted, those are + // supposed to be freed when no longer referenced. + fp = HI2UF(hi); + if (func_name_refcount(fp->uf_name)) { + skipped++; + } else { + func_free(fp); + skipped = 0; + break; + } } + } + } + if (skipped == 0) { + hash_clear(&func_hashtab); + } } #endif -int translated_function_exists(char_u *name) +bool translated_function_exists(const char *name) { if (builtin_function(name, -1)) { return find_internal_func((char *)name) != NULL; } - return find_func(name) != NULL; + return find_func((const char_u *)name) != NULL; } -/* - * Return TRUE if a function "name" exists. - */ -static int function_exists(char_u *name) +/// Check whether function with the given name exists +/// +/// @param[in] name Function name. +/// @param[in] no_deref Whether to dereference a Funcref. +/// +/// @return True if it exists, false otherwise. +static bool function_exists(const char *const name, bool no_deref) { - char_u *nm = name; - char_u *p; - int n = FALSE; + const char_u *nm = (const char_u *)name; + bool n = false; + int flag = TFN_INT | TFN_QUIET | TFN_NO_AUTOLOAD; - p = trans_function_name(&nm, false, TFN_INT|TFN_QUIET|TFN_NO_AUTOLOAD, - NULL, NULL); + if (no_deref) { + flag |= TFN_NO_DEREF; + } + char *const p = (char *)trans_function_name((char_u **)&nm, false, flag, NULL, + NULL); nm = skipwhite(nm); /* Only accept "funcname", "funcname ", "funcname (..." and * "funcname(...", not "funcname!...". */ - if (p != NULL && (*nm == NUL || *nm == '(')) + if (p != NULL && (*nm == NUL || *nm == '(')) { n = translated_function_exists(p); + } xfree(p); return n; } -/// Return TRUE if "name" looks like a builtin function name: starts with a +/// Checks if a builtin function with the given name exists. +/// +/// @param[in] name name of the builtin function to check. +/// @param[in] len length of "name", or -1 for NUL terminated. +/// +/// @return true if "name" looks like a builtin function name: starts with a /// lower case letter and doesn't contain AUTOLOAD_CHAR. -/// "len" is the length of "name", or -1 for NUL terminated. -static bool builtin_function(char_u *name, int len) +static bool builtin_function(const char *name, int len) { if (!ASCII_ISLOWER(name[0])) { - return FALSE; + return false; } - char_u *p = vim_strchr(name, AUTOLOAD_CHAR); + const char *p = (len == -1 + ? strchr(name, AUTOLOAD_CHAR) + : memchr(name, AUTOLOAD_CHAR, (size_t)len)); - return p == NULL - || (len > 0 && p > name + len); + return p == NULL; } /* @@ -21491,44 +20745,45 @@ static int prof_self_cmp(const void *s1, const void *s2) } -/* - * If "name" has a package name try autoloading the script for it. - * Return TRUE if a package was loaded. - */ -static int -script_autoload ( - char_u *name, - int reload /* load script again when already loaded */ -) +/// If name has a package name try autoloading the script for it +/// +/// @param[in] name Variable/function name. +/// @param[in] name_len Name length. +/// @param[in] reload If true, load script again when already loaded. +/// +/// @return true if a package was loaded. +static bool script_autoload(const char *const name, const size_t name_len, + const bool reload) { - char_u *p; - char_u *scriptname, *tofree; - int ret = FALSE; - int i; - - /* If there is no '#' after name[0] there is no package name. */ - p = vim_strchr(name, AUTOLOAD_CHAR); - if (p == NULL || p == name) - return FALSE; + // If there is no '#' after name[0] there is no package name. + const char *p = memchr(name, AUTOLOAD_CHAR, name_len); + if (p == NULL || p == name) { + return false; + } - tofree = scriptname = autoload_name(name); + bool ret = false; + char *tofree = autoload_name(name, name_len); + char *scriptname = tofree; - /* Find the name in the list of previously loaded package names. Skip - * "autoload/", it's always the same. */ - for (i = 0; i < ga_loaded.ga_len; ++i) - if (STRCMP(((char_u **)ga_loaded.ga_data)[i] + 9, scriptname + 9) == 0) + // Find the name in the list of previously loaded package names. Skip + // "autoload/", it's always the same. + int i = 0; + for (; i < ga_loaded.ga_len; i++) { + if (STRCMP(((char **)ga_loaded.ga_data)[i] + 9, scriptname + 9) == 0) { break; - if (!reload && i < ga_loaded.ga_len) - ret = FALSE; /* was loaded already */ - else { - /* Remember the name if it wasn't loaded already. */ + } + } + if (!reload && i < ga_loaded.ga_len) { + ret = false; // Was loaded already. + } else { + // Remember the name if it wasn't loaded already. if (i == ga_loaded.ga_len) { - GA_APPEND(char_u *, &ga_loaded, scriptname); + GA_APPEND(char *, &ga_loaded, scriptname); tofree = NULL; } // Try loading the package from $VIMRUNTIME/autoload/<name>.vim - if (source_runtime(scriptname, 0) == OK) { + if (source_runtime((char_u *)scriptname, 0) == OK) { ret = true; } } @@ -21537,21 +20792,29 @@ script_autoload ( return ret; } -/* - * Return the autoload script name for a function or variable name. - */ -static char_u *autoload_name(char_u *name) +/// Return the autoload script name for a function or variable name +/// +/// @param[in] name Variable/function name. +/// @param[in] name_len Name length. +/// +/// @return [allocated] autoload script name. +static char *autoload_name(const char *const name, const size_t name_len) + FUNC_ATTR_MALLOC FUNC_ATTR_WARN_UNUSED_RESULT { - /* Get the script file name: replace '#' with '/', append ".vim". */ - char_u *scriptname = xmalloc(STRLEN(name) + 14); - STRCPY(scriptname, "autoload/"); - STRCAT(scriptname, name); - *vim_strrchr(scriptname, AUTOLOAD_CHAR) = NUL; - STRCAT(scriptname, ".vim"); - - char_u *p; - while ((p = vim_strchr(scriptname, AUTOLOAD_CHAR)) != NULL) - *p = '/'; + // Get the script file name: replace '#' with '/', append ".vim". + char *const scriptname = xmalloc(name_len + sizeof("autoload/.vim")); + memcpy(scriptname, "autoload/", sizeof("autoload/") - 1); + memcpy(scriptname + sizeof("autoload/") - 1, name, name_len); + size_t auchar_idx = 0; + for (size_t i = sizeof("autoload/") - 1; + i - sizeof("autoload/") + 1 < name_len; + i++) { + if (scriptname[i] == AUTOLOAD_CHAR) { + scriptname[i] = '/'; + auchar_idx = i; + } + } + memcpy(scriptname + auchar_idx, ".vim", sizeof(".vim")); return scriptname; } @@ -21579,8 +20842,10 @@ char_u *get_user_func_name(expand_T *xp, int idx) ++hi; fp = HI2UF(hi); - if (fp->uf_flags & FC_DICT) - return (char_u *)""; /* don't show dict functions */ + if ((fp->uf_flags & FC_DICT) + || STRNCMP(fp->uf_name, "<lambda>", 8) == 0) { + return (char_u *)""; // don't show dict and lambda functions + } if (STRLEN(fp->uf_name) + 4 >= IOSIZE) return fp->uf_name; /* prevents overflow */ @@ -21611,9 +20876,18 @@ static void cat_func_name(char_u *buf, ufunc_T *fp) STRCPY(buf, fp->uf_name); } -/* - * ":delfunction {name}" - */ +/// There are two kinds of function names: +/// 1. ordinary names, function defined with :function +/// 2. numbered functions and lambdas +/// For the first we only count the name stored in func_hashtab as a reference, +/// using function() does not count as a reference, because the function is +/// looked up by name. +static bool func_name_refcount(char_u *name) +{ + return isdigit(*name) || *name == '<'; +} + +/// ":delfunction {name}" void ex_delfunction(exarg_T *eap) { ufunc_T *fp = NULL; @@ -21660,102 +20934,172 @@ void ex_delfunction(exarg_T *eap) } if (fudi.fd_dict != NULL) { - /* Delete the dict item that refers to the function, it will - * invoke func_unref() and possibly delete the function. */ - dictitem_remove(fudi.fd_dict, fudi.fd_di); - } else - func_free(fp); + // Delete the dict item that refers to the function, it will + // invoke func_unref() and possibly delete the function. + tv_dict_item_remove(fudi.fd_dict, fudi.fd_di); + } else { + // A normal function (not a numbered function or lambda) has a + // refcount of 1 for the entry in the hashtable. When deleting + // it and the refcount is more than one, it should be kept. + // A numbered function or lambda should be kept if the refcount is + // one or more. + if (fp->uf_refcount > (func_name_refcount(fp->uf_name) ? 0 : 1)) { + // Function is still referenced somewhere. Don't free it but + // do remove it from the hashtable. + if (func_remove(fp)) { + fp->uf_refcount--; + } + fp->uf_flags |= FC_DELETED; + } else { + func_clear_free(fp, false); + } + } } } -/* - * Free a function and remove it from the list of functions. - */ -static void func_free(ufunc_T *fp) +/// Remove the function from the function hashtable. If the function was +/// deleted while it still has references this was already done. +/// +/// @return true if the entry was deleted, false if it wasn't found. +static bool func_remove(ufunc_T *fp) { - hashitem_T *hi; + hashitem_T *hi = hash_find(&func_hashtab, UF2HIKEY(fp)); + + if (!HASHITEM_EMPTY(hi)) { + hash_remove(&func_hashtab, hi); + return true; + } + + return false; +} - /* clear this function */ +/// Free all things that a function contains. Does not free the function +/// itself, use func_free() for that. +/// +/// param[in] force When true, we are exiting. +static void func_clear(ufunc_T *fp, bool force) +{ + if (fp->uf_cleared) { + return; + } + fp->uf_cleared = true; + + // clear this function ga_clear_strings(&(fp->uf_args)); ga_clear_strings(&(fp->uf_lines)); xfree(fp->uf_tml_count); xfree(fp->uf_tml_total); xfree(fp->uf_tml_self); + funccal_unref(fp->uf_scoped, fp, force); +} - /* remove the function from the function hashtable */ - hi = hash_find(&func_hashtab, UF2HIKEY(fp)); - if (HASHITEM_EMPTY(hi)) - EMSG2(_(e_intern2), "func_free()"); - else - hash_remove(&func_hashtab, hi); - +/// Free a function and remove it from the list of functions. Does not free +/// what a function contains, call func_clear() first. +/// +/// param[in] fp The function to free. +static void func_free(ufunc_T *fp) +{ + // only remove it when not done already, otherwise we would remove a newer + // version of the function + if ((fp->uf_flags & (FC_DELETED | FC_REMOVED)) == 0) { + func_remove(fp); + } xfree(fp); } +/// Free all things that a function contains and free the function itself. +/// +/// param[in] force When true, we are exiting. +static void func_clear_free(ufunc_T *fp, bool force) +{ + func_clear(fp, force); + func_free(fp); +} + /* * Unreference a Function: decrement the reference count and free it when it - * becomes zero. Only for numbered functions. + * becomes zero. */ void func_unref(char_u *name) { - ufunc_T *fp; + ufunc_T *fp = NULL; - if (name != NULL && isdigit(*name)) { - fp = find_func(name); - if (fp == NULL) { + if (name == NULL || !func_name_refcount(name)) { + return; + } + + fp = find_func(name); + if (fp == NULL && isdigit(*name)) { #ifdef EXITFREE - if (!entered_free_all_mem) { - EMSG2(_(e_intern2), "func_unref()"); - } + if (!entered_free_all_mem) { + EMSG2(_(e_intern2), "func_unref()"); + abort(); + } #else EMSG2(_(e_intern2), "func_unref()"); + abort(); #endif - } else { - user_func_unref(fp); - } } + func_ptr_unref(fp); } -static void user_func_unref(ufunc_T *fp) +/// Unreference a Function: decrement the reference count and free it when it +/// becomes zero. +/// Unreference user function, freeing it if needed +/// +/// Decrements the reference count and frees when it becomes zero. +/// +/// @param fp Function to unreference. +void func_ptr_unref(ufunc_T *fp) { - if (--fp->uf_refcount <= 0) { - // Only delete it when it's not being used. Otherwise it's done + if (fp != NULL && --fp->uf_refcount <= 0) { + // Only delete it when it's not being used. Otherwise it's done // when "uf_calls" becomes zero. if (fp->uf_calls == 0) { - func_free(fp); + func_clear_free(fp, false); } } } -/* - * Count a reference to a Function. - */ +/// Count a reference to a Function. void func_ref(char_u *name) { ufunc_T *fp; - if (name != NULL && isdigit(*name)) { - fp = find_func(name); - if (fp == NULL) - EMSG2(_(e_intern2), "func_ref()"); - else - ++fp->uf_refcount; + if (name == NULL || !func_name_refcount(name)) { + return; + } + fp = find_func(name); + if (fp != NULL) { + (fp->uf_refcount)++; + } else if (isdigit(*name)) { + // Only give an error for a numbered function. + // Fail silently, when named or lambda function isn't found. + EMSG2(_(e_intern2), "func_ref()"); } } -/* - * Call a user function. - */ -static void -call_user_func ( - ufunc_T *fp, /* pointer to function */ - int argcount, /* nr of args */ - typval_T *argvars, /* arguments */ - typval_T *rettv, /* return value */ - linenr_T firstline, /* first line of range */ - linenr_T lastline, /* last line of range */ - dict_T *selfdict /* Dictionary for "self" */ -) +/// Count a reference to a Function. +void func_ptr_ref(ufunc_T *fp) +{ + if (fp != NULL) { + (fp->uf_refcount)++; + } +} + +/// Call a user function +/// +/// @param fp Function to call. +/// @param[in] argcount Number of arguments. +/// @param argvars Arguments. +/// @param[out] rettv Return value. +/// @param[in] firstline First line of range. +/// @param[in] lastline Last line of range. +/// @param selfdict Dictionary for "self" for dictionary functions. +void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, + typval_T *rettv, linenr_T firstline, linenr_T lastline, + dict_T *selfdict) + FUNC_ATTR_NONNULL_ARG(1, 3, 4) { char_u *save_sourcing_name; linenr_T save_sourcing_lnum; @@ -21766,6 +21110,7 @@ call_user_func ( dictitem_T *v; int fixvar_idx = 0; /* index in fixvar[] */ int ai; + bool islambda = false; char_u numbuf[NUMBUFLEN]; char_u *name; proftime_T wait_start; @@ -21803,25 +21148,32 @@ call_user_func ( fc->breakpoint = dbg_find_breakpoint(FALSE, fp->uf_name, (linenr_T)0); fc->dbg_tick = debug_tick; - /* - * Note about using fc->fixvar[]: This is an array of FIXVAR_CNT variables - * with names up to VAR_SHORT_LEN long. This avoids having to alloc/free - * each argument variable and saves a lot of time. - */ - /* - * Init l: variables. - */ + // Set up fields for closure. + fc->fc_refcount = 0; + fc->fc_copyID = 0; + ga_init(&fc->fc_funcs, sizeof(ufunc_T *), 1); + func_ptr_ref(fp); + + if (STRNCMP(fp->uf_name, "<lambda>", 8) == 0) { + islambda = true; + } + + // Note about using fc->fixvar[]: This is an array of FIXVAR_CNT variables + // with names up to VAR_SHORT_LEN long. This avoids having to alloc/free + // each argument variable and saves a lot of time. + // + // Init l: variables. init_var_dict(&fc->l_vars, &fc->l_vars_var, VAR_DEF_SCOPE); if (selfdict != NULL) { - /* Set l:self to "selfdict". Use "name" to avoid a warning from - * some compiler that checks the destination size. */ - v = &fc->fixvar[fixvar_idx++].var; + // Set l:self to "selfdict". Use "name" to avoid a warning from + // some compiler that checks the destination size. + v = (dictitem_T *)&fc->fixvar[fixvar_idx++]; #ifndef __clang_analyzer__ name = v->di_key; STRCPY(name, "self"); #endif v->di_flags = DI_FLAGS_RO + DI_FLAGS_FIX; - hash_add(&fc->l_vars.dv_hashtab, DI2HIKEY(v)); + tv_dict_add(&fc->l_vars, v); v->di_tv.v_type = VAR_DICT; v->di_tv.v_lock = 0; v->di_tv.vval.v_dict = selfdict; @@ -21834,17 +21186,17 @@ call_user_func ( * Set a:000 to a list with room for the "..." arguments. */ init_var_dict(&fc->l_avars, &fc->l_avars_var, VAR_SCOPE); - add_nr_var(&fc->l_avars, &fc->fixvar[fixvar_idx++].var, "0", - (varnumber_T)(argcount - fp->uf_args.ga_len)); - /* Use "name" to avoid a warning from some compiler that checks the - * destination size. */ - v = &fc->fixvar[fixvar_idx++].var; + add_nr_var(&fc->l_avars, (dictitem_T *)&fc->fixvar[fixvar_idx++], "0", + (varnumber_T)(argcount - fp->uf_args.ga_len)); + // Use "name" to avoid a warning from some compiler that checks the + // destination size. + v = (dictitem_T *)&fc->fixvar[fixvar_idx++]; #ifndef __clang_analyzer__ name = v->di_key; STRCPY(name, "000"); #endif v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX; - hash_add(&fc->l_avars.dv_hashtab, DI2HIKEY(v)); + tv_dict_add(&fc->l_avars, v); v->di_tv.v_type = VAR_LIST; v->di_tv.v_lock = VAR_FIXED; v->di_tv.vval.v_list = &fc->l_varlist; @@ -21852,42 +21204,53 @@ call_user_func ( fc->l_varlist.lv_refcount = DO_NOT_FREE_CNT; fc->l_varlist.lv_lock = VAR_FIXED; - /* - * Set a:firstline to "firstline" and a:lastline to "lastline". - * Set a:name to named arguments. - * Set a:N to the "..." arguments. - */ - add_nr_var(&fc->l_avars, &fc->fixvar[fixvar_idx++].var, "firstline", - (varnumber_T)firstline); - add_nr_var(&fc->l_avars, &fc->fixvar[fixvar_idx++].var, "lastline", - (varnumber_T)lastline); - for (int i = 0; i < argcount; ++i) { + // Set a:firstline to "firstline" and a:lastline to "lastline". + // Set a:name to named arguments. + // Set a:N to the "..." arguments. + add_nr_var(&fc->l_avars, (dictitem_T *)&fc->fixvar[fixvar_idx++], + "firstline", (varnumber_T)firstline); + add_nr_var(&fc->l_avars, (dictitem_T *)&fc->fixvar[fixvar_idx++], + "lastline", (varnumber_T)lastline); + for (int i = 0; i < argcount; i++) { + bool addlocal = false; + ai = i - fp->uf_args.ga_len; - if (ai < 0) - /* named argument a:name */ + if (ai < 0) { + // named argument a:name name = FUNCARG(fp, i); - else { - /* "..." argument a:1, a:2, etc. */ - sprintf((char *)numbuf, "%d", ai + 1); + if (islambda) { + addlocal = true; + } + } else { + // "..." argument a:1, a:2, etc. + snprintf((char *)numbuf, sizeof(numbuf), "%d", ai + 1); name = numbuf; } if (fixvar_idx < FIXVAR_CNT && STRLEN(name) <= VAR_SHORT_LEN) { - v = &fc->fixvar[fixvar_idx++].var; + v = (dictitem_T *)&fc->fixvar[fixvar_idx++]; v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX; } else { v = xmalloc(sizeof(dictitem_T) + STRLEN(name)); v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX | DI_FLAGS_ALLOC; } STRCPY(v->di_key, name); - hash_add(&fc->l_avars.dv_hashtab, DI2HIKEY(v)); - /* Note: the values are copied directly to avoid alloc/free. - * "argvars" must have VAR_FIXED for v_lock. */ + // Note: the values are copied directly to avoid alloc/free. + // "argvars" must have VAR_FIXED for v_lock. v->di_tv = argvars[i]; v->di_tv.v_lock = VAR_FIXED; + if (addlocal) { + // Named arguments can be accessed without the "a:" prefix in lambda + // expressions. Add to the l: dict. + tv_copy(&v->di_tv, &v->di_tv); + tv_dict_add(&fc->l_vars, v); + } else { + tv_dict_add(&fc->l_avars, v); + } + if (ai >= 0 && ai < MAX_FUNC_ARGS) { - list_append(&fc->l_varlist, &fc->l_listitems[ai]); + tv_list_append(&fc->l_varlist, &fc->l_listitems[ai]); fc->l_listitems[ai].li_tv = argvars[i]; fc->l_listitems[ai].li_tv.v_lock = VAR_FIXED; } @@ -21925,24 +21288,24 @@ call_user_func ( smsg(_("calling %s"), sourcing_name); if (p_verbose >= 14) { - char_u buf[MSG_BUF_LEN]; - - msg_puts((char_u *)"("); - for (int i = 0; i < argcount; ++i) { + msg_puts("("); + for (int i = 0; i < argcount; i++) { if (i > 0) { - msg_puts((char_u *)", "); + msg_puts(", "); } if (argvars[i].v_type == VAR_NUMBER) { msg_outnum((long)argvars[i].vval.v_number); } else { // Do not want errors such as E724 here. emsg_off++; - char_u *s = (char_u *) encode_tv2string(&argvars[i], NULL); - char_u *tofree = s; + char *tofree = encode_tv2string(&argvars[i], NULL); emsg_off--; - if (s != NULL) { - if (vim_strsize(s) > MSG_BUF_CLEN) { - trunc_string(s, buf, MSG_BUF_CLEN, MSG_BUF_LEN); + if (tofree != NULL) { + char *s = tofree; + char buf[MSG_BUF_LEN]; + if (vim_strsize((char_u *)s) > MSG_BUF_CLEN) { + trunc_string((char_u *)s, (char_u *)buf, MSG_BUF_CLEN, + sizeof(buf)); s = buf; } msg_puts(s); @@ -21950,9 +21313,9 @@ call_user_func ( } } } - msg_puts((char_u *)")"); + msg_puts(")"); } - msg_puts((char_u *)"\n"); /* don't overwrite this either */ + msg_puts("\n"); // don't overwrite this either verbose_leave_scroll(); --no_wait_return; @@ -21995,14 +21358,14 @@ call_user_func ( // when the function was aborted because of an error, return -1 if ((did_emsg && (fp->uf_flags & FC_ABORT)) || rettv->v_type == VAR_UNKNOWN) { - clear_tv(rettv); + tv_clear(rettv); rettv->v_type = VAR_NUMBER; rettv->vval.v_number = -1; } if (func_or_func_caller_profiling) { call_start = profile_end(call_start); - call_start = profile_sub_wait(wait_start, call_start); + call_start = profile_sub_wait(wait_start, call_start); // -V614 fp->uf_tm_total = profile_add(fp->uf_tm_total, call_start); fp->uf_tm_self = profile_self(fp->uf_tm_self, call_start, fp->uf_tm_children); @@ -22043,7 +21406,7 @@ call_user_func ( xfree(tofree); } } - msg_puts((char_u *)"\n"); /* don't overwrite this either */ + msg_puts("\n"); // don't overwrite this either verbose_leave_scroll(); --no_wait_return; @@ -22061,7 +21424,7 @@ call_user_func ( verbose_enter_scroll(); smsg(_("continuing in %s"), sourcing_name); - msg_puts((char_u *)"\n"); /* don't overwrite this either */ + msg_puts("\n"); // don't overwrite this either verbose_leave_scroll(); --no_wait_return; @@ -22071,41 +21434,35 @@ call_user_func ( current_funccal = fc->caller; --depth; - /* If the a:000 list and the l: and a: dicts are not referenced we can - * free the funccall_T and what's in it. */ + // If the a:000 list and the l: and a: dicts are not referenced and there + // is no closure using it, we can free the funccall_T and what's in it. if (fc->l_varlist.lv_refcount == DO_NOT_FREE_CNT && fc->l_vars.dv_refcount == DO_NOT_FREE_CNT - && fc->l_avars.dv_refcount == DO_NOT_FREE_CNT) { - free_funccal(fc, FALSE); + && fc->l_avars.dv_refcount == DO_NOT_FREE_CNT + && fc->fc_refcount <= 0) { + free_funccal(fc, false); } else { - hashitem_T *hi; - listitem_T *li; - int todo; - - /* "fc" is still in use. This can happen when returning "a:000" or - * assigning "l:" to a global variable. - * Link "fc" in the list for garbage collection later. */ + // "fc" is still in use. This can happen when returning "a:000", + // assigning "l:" to a global variable or defining a closure. + // Link "fc" in the list for garbage collection later. fc->caller = previous_funccal; previous_funccal = fc; - /* Make a copy of the a: variables, since we didn't do that above. */ - todo = (int)fc->l_avars.dv_hashtab.ht_used; - for (hi = fc->l_avars.dv_hashtab.ht_array; todo > 0; ++hi) { - if (!HASHITEM_EMPTY(hi)) { - --todo; - v = HI2DI(hi); - copy_tv(&v->di_tv, &v->di_tv); - } - } + // Make a copy of the a: variables, since we didn't do that above. + TV_DICT_ITER(&fc->l_avars, di, { + tv_copy(&di->di_tv, &di->di_tv); + }); - /* Make a copy of the a:000 items, since we didn't do that above. */ - for (li = fc->l_varlist.lv_first; li != NULL; li = li->li_next) - copy_tv(&li->li_tv, &li->li_tv); + // Make a copy of the a:000 items, since we didn't do that above. + for (listitem_T *li = fc->l_varlist.lv_first; li != NULL; + li = li->li_next) { + tv_copy(&li->li_tv, &li->li_tv); + } } - if (--fp->uf_calls <= 0 && isdigit(*fp->uf_name) && fp->uf_refcount <= 0) { + if (--fp->uf_calls <= 0 && fp->uf_refcount <= 0) { // Function was unreferenced while being used, free it now. - func_free(fp); + func_clear_free(fp, false); } // restore search patterns and redo buffer if (did_save_redo) { @@ -22114,15 +21471,46 @@ call_user_func ( restore_search_patterns(); } -/* - * Return TRUE if items in "fc" do not have "copyID". That means they are not - * referenced from anywhere that is in use. - */ +/// Unreference "fc": decrement the reference count and free it when it +/// becomes zero. "fp" is detached from "fc". +/// +/// @param[in] force When true, we are exiting. +static void funccal_unref(funccall_T *fc, ufunc_T *fp, bool force) +{ + funccall_T **pfc; + int i; + + if (fc == NULL) { + return; + } + + if (--fc->fc_refcount <= 0 && (force || ( + fc->l_varlist.lv_refcount == DO_NOT_FREE_CNT + && fc->l_vars.dv_refcount == DO_NOT_FREE_CNT + && fc->l_avars.dv_refcount == DO_NOT_FREE_CNT))) { + for (pfc = &previous_funccal; *pfc != NULL; pfc = &(*pfc)->caller) { + if (fc == *pfc) { + *pfc = fc->caller; + free_funccal(fc, true); + return; + } + } + } + for (i = 0; i < fc->fc_funcs.ga_len; i++) { + if (((ufunc_T **)(fc->fc_funcs.ga_data))[i] == fp) { + ((ufunc_T **)(fc->fc_funcs.ga_data))[i] = NULL; + } + } +} + +/// @return true if items in "fc" do not have "copyID". That means they are not +/// referenced from anywhere that is in use. static int can_free_funccal(funccall_T *fc, int copyID) { return fc->l_varlist.lv_copyID != copyID && fc->l_vars.dv_copyID != copyID - && fc->l_avars.dv_copyID != copyID; + && fc->l_avars.dv_copyID != copyID + && fc->fc_copyID != copyID; } /* @@ -22136,18 +21524,34 @@ free_funccal ( { listitem_T *li; - /* The a: variables typevals may not have been allocated, only free the - * allocated variables. */ + for (int i = 0; i < fc->fc_funcs.ga_len; i++) { + ufunc_T *fp = ((ufunc_T **)(fc->fc_funcs.ga_data))[i]; + + // When garbage collecting a funccall_T may be freed before the + // function that references it, clear its uf_scoped field. + // The function may have been redefined and point to another + // funccal_T, don't clear it then. + if (fp != NULL && fp->uf_scoped == fc) { + fp->uf_scoped = NULL; + } + } + ga_clear(&fc->fc_funcs); + + // The a: variables typevals may not have been allocated, only free the + // allocated variables. vars_clear_ext(&fc->l_avars.dv_hashtab, free_val); /* free all l: variables */ vars_clear(&fc->l_vars.dv_hashtab); - /* Free the a:000 variables if they were allocated. */ - if (free_val) - for (li = fc->l_varlist.lv_first; li != NULL; li = li->li_next) - clear_tv(&li->li_tv); + // Free the a:000 variables if they were allocated. + if (free_val) { + for (li = fc->l_varlist.lv_first; li != NULL; li = li->li_next) { + tv_clear(&li->li_tv); + } + } + func_ptr_unref(fc->func); xfree(fc); } @@ -22160,7 +21564,7 @@ static void add_nr_var(dict_T *dp, dictitem_T *v, char *name, varnumber_T nr) STRCPY(v->di_key, name); #endif v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX; - hash_add(&dp->dv_hashtab, DI2HIKEY(v)); + tv_dict_add(dp, v); v->di_tv.v_type = VAR_NUMBER; v->di_tv.v_lock = VAR_FIXED; v->di_tv.vval.v_number = nr; @@ -22186,10 +21590,11 @@ void ex_return(exarg_T *eap) eap->nextcmd = NULL; if ((*arg != NUL && *arg != '|' && *arg != '\n') && eval0(arg, &rettv, &eap->nextcmd, !eap->skip) != FAIL) { - if (!eap->skip) - returning = do_return(eap, FALSE, TRUE, &rettv); - else - clear_tv(&rettv); + if (!eap->skip) { + returning = do_return(eap, false, true, &rettv); + } else { + tv_clear(&rettv); + } } /* It's safer to return also on error. */ else if (!eap->skip) { @@ -22276,7 +21681,7 @@ int do_return(exarg_T *eap, int reanimate, int is_cmd, void *rettv) * a return immediately after reanimation, the value is already * there. */ if (!reanimate && rettv != NULL) { - clear_tv(current_funccal->rettv); + tv_clear(current_funccal->rettv); *current_funccal->rettv = *(typval_T *)rettv; if (!is_cmd) xfree(rettv); @@ -22287,14 +21692,6 @@ int do_return(exarg_T *eap, int reanimate, int is_cmd, void *rettv) } /* - * Free the variable with a pending return value. - */ -void discard_pending_return(void *rettv) -{ - free_tv((typval_T *)rettv); -} - -/* * Generate a return command for producing the value of "rettv". The result * is an allocated string. Used by report_pending() for verbose messages. */ @@ -22311,7 +21708,7 @@ char_u *get_return_cmd(void *rettv) } STRCPY(IObuff, ":return "); - STRNCPY(IObuff + 8, s, IOSIZE - 8); + STRLCPY(IObuff + 8, s, IOSIZE - 8); if (STRLEN(s) + 8 >= IOSIZE) STRCPY(IObuff + IOSIZE - 4, "..."); xfree(tofree); @@ -22466,6 +21863,72 @@ static var_flavour_T var_flavour(char_u *varname) } } +/// Search hashitem in parent scope. +hashitem_T *find_hi_in_scoped_ht(const char *name, hashtab_T **pht) +{ + if (current_funccal == NULL || current_funccal->func->uf_scoped == NULL) { + return NULL; + } + + funccall_T *old_current_funccal = current_funccal; + hashitem_T *hi = NULL; + const size_t namelen = strlen(name); + const char *varname; + + // Search in parent scope which is possible to reference from lambda + current_funccal = current_funccal->func->uf_scoped; + while (current_funccal != NULL) { + hashtab_T *ht = find_var_ht(name, namelen, &varname); + if (ht != NULL && *varname != NUL) { + hi = hash_find_len(ht, varname, namelen - (varname - name)); + if (!HASHITEM_EMPTY(hi)) { + *pht = ht; + break; + } + } + if (current_funccal == current_funccal->func->uf_scoped) { + break; + } + current_funccal = current_funccal->func->uf_scoped; + } + current_funccal = old_current_funccal; + + return hi; +} + +/// Search variable in parent scope. +dictitem_T *find_var_in_scoped_ht(const char *name, const size_t namelen, + int no_autoload) +{ + if (current_funccal == NULL || current_funccal->func->uf_scoped == NULL) { + return NULL; + } + + dictitem_T *v = NULL; + funccall_T *old_current_funccal = current_funccal; + const char *varname; + + // Search in parent scope which is possible to reference from lambda + current_funccal = current_funccal->func->uf_scoped; + while (current_funccal) { + hashtab_T *ht = find_var_ht(name, namelen, &varname); + if (ht != NULL && *varname != NUL) { + v = find_var_in_ht(ht, *name, varname, + namelen - (size_t)(varname - name), no_autoload); + if (v != NULL) { + break; + } + } + if (current_funccal == current_funccal->func->uf_scoped) { + break; + } + current_funccal = current_funccal->func->uf_scoped; + } + current_funccal = old_current_funccal; + + return v; +} + /// Iterate over global variables /// /// @warning No modifications to global variable dictionary must be performed @@ -22489,7 +21952,7 @@ const void *var_shada_iter(const void *const iter, const char **const name, hi = globvarht.ht_array; while ((size_t) (hi - hifirst) < hinum && (HASHITEM_EMPTY(hi) - || var_flavour(HI2DI(hi)->di_key) != VAR_FLAVOUR_SHADA)) { + || var_flavour(hi->hi_key) != VAR_FLAVOUR_SHADA)) { hi++; } if ((size_t) (hi - hifirst) == hinum) { @@ -22498,11 +21961,10 @@ const void *var_shada_iter(const void *const iter, const char **const name, } else { hi = (const hashitem_T *) iter; } - *name = (char *) HI2DI(hi)->di_key; - copy_tv(&(HI2DI(hi)->di_tv), rettv); - while ((size_t) (++hi - hifirst) < hinum) { - if (!HASHITEM_EMPTY(hi) - && var_flavour(HI2DI(hi)->di_key) == VAR_FLAVOUR_SHADA) { + *name = (char *)TV_DICT_HI2DI(hi)->di_key; + tv_copy(&TV_DICT_HI2DI(hi)->di_tv, rettv); + while ((size_t)(++hi - hifirst) < hinum) { + if (!HASHITEM_EMPTY(hi) && var_flavour(hi->hi_key) == VAR_FLAVOUR_SHADA) { return hi; } } @@ -22513,62 +21975,55 @@ void var_set_global(const char *const name, typval_T vartv) { funccall_T *const saved_current_funccal = current_funccal; current_funccal = NULL; - set_var((char_u *) name, &vartv, false); + set_var(name, strlen(name), &vartv, false); current_funccal = saved_current_funccal; } int store_session_globals(FILE *fd) { - hashitem_T *hi; - dictitem_T *this_var; - int todo; - char_u *p, *t; - - todo = (int)globvarht.ht_used; - for (hi = globvarht.ht_array; todo > 0; ++hi) { - if (!HASHITEM_EMPTY(hi)) { - --todo; - this_var = HI2DI(hi); - if ((this_var->di_tv.v_type == VAR_NUMBER - || this_var->di_tv.v_type == VAR_STRING) - && var_flavour(this_var->di_key) == VAR_FLAVOUR_SESSION) { - /* Escape special characters with a backslash. Turn a LF and - * CR into \n and \r. */ - p = vim_strsave_escaped(get_tv_string(&this_var->di_tv), - (char_u *)"\\\"\n\r"); - for (t = p; *t != NUL; ++t) - if (*t == '\n') - *t = 'n'; - else if (*t == '\r') - *t = 'r'; - if ((fprintf(fd, "let %s = %c%s%c", - this_var->di_key, - (this_var->di_tv.v_type == VAR_STRING) ? '"' - : ' ', - p, - (this_var->di_tv.v_type == VAR_STRING) ? '"' - : ' ') < 0) - || put_eol(fd) == FAIL) { - xfree(p); - return FAIL; + TV_DICT_ITER(&globvardict, this_var, { + if ((this_var->di_tv.v_type == VAR_NUMBER + || this_var->di_tv.v_type == VAR_STRING) + && var_flavour(this_var->di_key) == VAR_FLAVOUR_SESSION) { + // Escape special characters with a backslash. Turn a LF and + // CR into \n and \r. + char_u *const p = vim_strsave_escaped( + (const char_u *)tv_get_string(&this_var->di_tv), + (const char_u *)"\\\"\n\r"); + for (char_u *t = p; *t != NUL; t++) { + if (*t == '\n') { + *t = 'n'; + } else if (*t == '\r') { + *t = 'r'; } + } + if ((fprintf(fd, "let %s = %c%s%c", + this_var->di_key, + ((this_var->di_tv.v_type == VAR_STRING) ? '"' + : ' '), + p, + ((this_var->di_tv.v_type == VAR_STRING) ? '"' + : ' ')) < 0) + || put_eol(fd) == FAIL) { xfree(p); - } else if (this_var->di_tv.v_type == VAR_FLOAT - && var_flavour(this_var->di_key) == VAR_FLAVOUR_SESSION) { - float_T f = this_var->di_tv.vval.v_float; - int sign = ' '; - - if (f < 0) { - f = -f; - sign = '-'; - } - if ((fprintf(fd, "let %s = %c%f", - this_var->di_key, sign, f) < 0) - || put_eol(fd) == FAIL) - return FAIL; + return FAIL; + } + xfree(p); + } else if (this_var->di_tv.v_type == VAR_FLOAT + && var_flavour(this_var->di_key) == VAR_FLAVOUR_SESSION) { + float_T f = this_var->di_tv.vval.v_float; + int sign = ' '; + + if (f < 0) { + f = -f; + sign = '-'; + } + if ((fprintf(fd, "let %s = %c%f", this_var->di_key, sign, f) < 0) + || put_eol(fd) == FAIL) { + return FAIL; } } - } + }); return OK; } @@ -22588,51 +22043,6 @@ void last_set_msg(scid_T scriptID) } } -/* - * List v:oldfiles in a nice way. - */ -void ex_oldfiles(exarg_T *eap) -{ - list_T *l = get_vim_var_list(VV_OLDFILES); - listitem_T *li; - long nr = 0; - - if (l == NULL) - msg((char_u *)_("No old files")); - else { - msg_start(); - msg_scroll = TRUE; - for (li = l->lv_first; li != NULL && !got_int; li = li->li_next) { - msg_outnum(++nr); - MSG_PUTS(": "); - msg_outtrans(get_tv_string(&li->li_tv)); - msg_putchar('\n'); - ui_flush(); /* output one line at a time */ - os_breakcheck(); - } - /* Assume "got_int" was set to truncate the listing. */ - got_int = FALSE; - - // File selection prompt on ":browse oldfiles" - if (cmdmod.browse) { - 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); - } - } - } -} - // reset v:option_new, v:option_old and v:option_type void reset_v_option_vars(void) { @@ -22865,7 +22275,7 @@ repeat: sub = vim_strnsave(s, (int)(p - s)); str = vim_strnsave(*fnamep, *fnamelen); *usedlen = (size_t)(p + 1 - src); - s = do_string_sub(str, pat, sub, flags); + s = do_string_sub(str, pat, sub, NULL, flags); *fnamep = s; *fnamelen = STRLEN(s); xfree(*bufp); @@ -22901,12 +22311,12 @@ repeat: return valid; } -/* - * Perform a substitution on "str" with pattern "pat" and substitute "sub". - * "flags" can be "g" to do a global substitute. - * Returns an allocated string, NULL for error. - */ -char_u *do_string_sub(char_u *str, char_u *pat, char_u *sub, char_u *flags) +/// Perform a substitution on "str" with pattern "pat" and substitute "sub". +/// When "sub" is NULL "expr" is used, must be a VAR_FUNC or VAR_PARTIAL. +/// "flags" can be "g" to do a global substitute. +/// Returns an allocated string, NULL for error. +char_u *do_string_sub(char_u *str, char_u *pat, char_u *sub, + typval_T *expr, char_u *flags) { int sublen; regmatch_T regmatch; @@ -22944,23 +22354,21 @@ char_u *do_string_sub(char_u *str, char_u *pat, char_u *sub, char_u *flags) zero_width = regmatch.startp[0]; } - /* - * Get some space for a temporary buffer to do the substitution - * into. It will contain: - * - The text up to where the match is. - * - The substituted text. - * - The text after the match. - */ - sublen = vim_regsub(®match, sub, tail, FALSE, TRUE, FALSE); + // Get some space for a temporary buffer to do the substitution + // into. It will contain: + // - The text up to where the match is. + // - The substituted text. + // - The text after the match. + sublen = vim_regsub(®match, sub, expr, tail, false, true, false); ga_grow(&ga, (int)((end - tail) + sublen - (regmatch.endp[0] - regmatch.startp[0]))); /* copy the text up to where the match is */ int i = (int)(regmatch.startp[0] - tail); memmove((char_u *)ga.ga_data + ga.ga_len, tail, (size_t)i); - /* add the substituted text */ - (void)vim_regsub(®match, sub, (char_u *)ga.ga_data - + ga.ga_len + i, TRUE, TRUE, FALSE); + // add the substituted text + (void)vim_regsub(®match, sub, expr, (char_u *)ga.ga_data + + ga.ga_len + i, true, true, false); ga.ga_len += i + sublen - 1; tail = regmatch.endp[0]; if (*tail == NUL) @@ -22977,11 +22385,12 @@ char_u *do_string_sub(char_u *str, char_u *pat, char_u *sub, char_u *flags) char_u *ret = vim_strsave(ga.ga_data == NULL ? str : (char_u *)ga.ga_data); ga_clear(&ga); - if (p_cpo == empty_option) + if (p_cpo == empty_option) { p_cpo = save_cpo; - else - /* Darn, evaluating {sub} expression changed the value. */ + } else { + // Darn, evaluating {sub} expression or {expr} changed the value. free_string_option(save_cpo); + } return ret; } @@ -22993,7 +22402,7 @@ static inline TerminalJobData *common_job_init(char **argv, bool pty, bool rpc, bool detach, - char *cwd) + const char *cwd) { TerminalJobData *data = xcalloc(1, sizeof(TerminalJobData)); data->stopped = false; @@ -23027,9 +22436,9 @@ static inline TerminalJobData *common_job_init(char **argv, static inline bool common_job_callbacks(dict_T *vopts, Callback *on_stdout, Callback *on_stderr, Callback *on_exit) { - if (get_dict_callback(vopts, "on_stdout", on_stdout) - && get_dict_callback(vopts, "on_stderr", on_stderr) - && get_dict_callback(vopts, "on_exit", on_exit)) { + if (tv_dict_get_callback(vopts, S_LEN("on_stdout"), on_stdout) + &&tv_dict_get_callback(vopts, S_LEN("on_stderr"), on_stderr) + && tv_dict_get_callback(vopts, S_LEN("on_exit"), on_exit)) { vopts->dv_refcount++; return true; } @@ -23056,8 +22465,9 @@ static inline bool common_job_start(TerminalJobData *data, typval_T *rettv) data->refcount++; char *cmd = xstrdup(proc->argv[0]); - if (!process_spawn(proc)) { - EMSG2(_(e_jobspawn), cmd); + int status = process_spawn(proc); + if (status) { + EMSG3(_(e_jobspawn), os_strerror(status), cmd); xfree(cmd); if (proc->type == kProcessTypePty) { xfree(data->proc.pty.term_name); @@ -23070,8 +22480,9 @@ static inline bool common_job_start(TerminalJobData *data, typval_T *rettv) if (data->rpc) { - // the rpc channel takes over the in and out streams - channel_from_process(proc, data->id); + eval_format_source_name_line((char *)IObuff, sizeof(IObuff)); + // RPC channel takes over the in/out streams. + channel_from_process(proc, data->id, (char *)IObuff); } else { wstream_init(proc->in, 0); if (proc->out) { @@ -23115,7 +22526,7 @@ static inline void process_job_event(TerminalJobData *data, Callback *callback, JobEvent event_data; event_data.received = NULL; if (buf) { - event_data.received = list_alloc(); + event_data.received = tv_list_alloc(); char *ptr = buf; size_t remaining = count; size_t off = 0; @@ -23123,7 +22534,7 @@ static inline void process_job_event(TerminalJobData *data, Callback *callback, while (off < remaining) { // append the line if (ptr[off] == NL) { - list_append_string(event_data.received, (uint8_t *)ptr, off); + tv_list_append_string(event_data.received, ptr, off); size_t skip = off + 1; ptr += skip; remaining -= skip; @@ -23136,7 +22547,7 @@ static inline void process_job_event(TerminalJobData *data, Callback *callback, } off++; } - list_append_string(event_data.received, (uint8_t *)ptr, off); + tv_list_append_string(event_data.received, ptr, off); } else { event_data.status = status; } @@ -23179,11 +22590,10 @@ static void on_job_output(Stream *stream, TerminalJobData *data, RBuffer *buf, terminal_receive(data->term, ptr, count); } + rbuffer_consumed(buf, count); if (callback->type != kCallbackNone) { process_job_event(data, callback, type, ptr, count, 0); } - - rbuffer_consumed(buf, count); } static void eval_job_process_exit_cb(Process *proc, int status, void *d) @@ -23283,10 +22693,9 @@ static void on_job_event(JobEvent *ev) argv[2].v_lock = 0; argv[2].vval.v_string = (uint8_t *)ev->type; - typval_T rettv; - init_tv(&rettv); + typval_T rettv = TV_INITIAL_VALUE; callback_call(ev->callback, 3, argv, &rettv); - clear_tv(&rettv); + tv_clear(&rettv); } static TerminalJobData *find_job(uint64_t id) @@ -23309,8 +22718,8 @@ static void script_host_eval(char *name, typval_T *argvars, typval_T *rettv) return; } - list_T *args = list_alloc(); - list_append_string(args, argvars[0].vval.v_string, -1); + list_T *args = tv_list_alloc(); + tv_list_append_string(args, (const char *)argvars[0].vval.v_string, -1); *rettv = eval_call_provider(name, "eval", args); } @@ -23342,11 +22751,12 @@ typval_T eval_call_provider(char *provider, char *method, list_T *arguments) arguments->lv_refcount++; int dummy; - (void)call_func((uint8_t *)func, + (void)call_func((const char_u *)func, name_len, &rettv, 2, argvars, + NULL, curwin->w_cursor.lnum, curwin->w_cursor.lnum, &dummy, @@ -23354,7 +22764,7 @@ typval_T eval_call_provider(char *provider, char *method, list_T *arguments) NULL, NULL); - list_unref(arguments); + tv_list_unref(arguments); // Restore caller scope information restore_funccal(provider_caller_scope.funccalp); provider_caller_scope = saved_provider_caller_scope; @@ -23363,14 +22773,16 @@ typval_T eval_call_provider(char *provider, char *method, list_T *arguments) return rettv; } -bool eval_has_provider(char *name) +bool eval_has_provider(const char *name) { -#define check_provider(name) \ +#define CHECK_PROVIDER(name) \ if (has_##name == -1) { \ - has_##name = !!find_func((uint8_t *)"provider#" #name "#Call"); \ + has_##name = !!find_func((char_u *)"provider#" #name "#Call"); \ if (!has_##name) { \ - script_autoload((uint8_t *)"provider#" #name "#Call", false); \ - has_##name = !!find_func((uint8_t *)"provider#" #name "#Call"); \ + script_autoload("provider#" #name "#Call", \ + sizeof("provider#" #name "#Call") - 1, \ + false); \ + has_##name = !!find_func((char_u *)"provider#" #name "#Call"); \ } \ } @@ -23379,107 +22791,27 @@ bool eval_has_provider(char *name) static int has_python3 = -1; static int has_ruby = -1; - if (!strcmp(name, "clipboard")) { - check_provider(clipboard); + if (strequal(name, "clipboard")) { + CHECK_PROVIDER(clipboard); return has_clipboard; - } else if (!strcmp(name, "python3")) { - check_provider(python3); + } else if (strequal(name, "python3")) { + CHECK_PROVIDER(python3); return has_python3; - } else if (!strcmp(name, "python")) { - check_provider(python); + } else if (strequal(name, "python")) { + CHECK_PROVIDER(python); return has_python; - } else if (!strcmp(name, "ruby")) { - check_provider(ruby); + } else if (strequal(name, "ruby")) { + CHECK_PROVIDER(ruby); return has_ruby; } return false; } -// Compute the `DictWatcher` address from a QUEUE node. This only exists for -// .asan-blacklist (ASAN doesn't handle QUEUE_DATA pointer arithmetic). -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[4]; - 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; - callback_call(&watcher->callback, 3, argv, &rettv); - 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 -{ - callback_free(&watcher->callback); - xfree(watcher->key_pattern); - xfree(watcher); -} - -// Check if `d` has at least one watcher. -static bool is_watched(dict_T *d) +/// Writes "<sourcing_name>:<sourcing_lnum>" to `buf[bufsize]`. +void eval_format_source_name_line(char *buf, size_t bufsize) { - return d && !QUEUE_EMPTY(&d->watchers); + snprintf(buf, bufsize, "%s:%" PRIdLINENR, + (sourcing_name ? sourcing_name : (char_u *)"?"), + (sourcing_name ? sourcing_lnum : 0)); } diff --git a/src/nvim/eval.h b/src/nvim/eval.h index 630e309442..070bc35bd5 100644 --- a/src/nvim/eval.h +++ b/src/nvim/eval.h @@ -1,11 +1,12 @@ #ifndef NVIM_EVAL_H #define NVIM_EVAL_H -#include "nvim/profile.h" #include "nvim/hashtab.h" // For hashtab_T -#include "nvim/garray.h" // For garray_T -#include "nvim/buffer_defs.h" // For scid_T +#include "nvim/buffer_defs.h" #include "nvim/ex_cmds_defs.h" // For exarg_T +#include "nvim/eval/typval.h" +#include "nvim/profile.h" +#include "nvim/garray.h" #define COPYID_INC 2 #define COPYID_MASK (~0x1) @@ -13,42 +14,10 @@ // 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 HIKEY2UF(p) ((ufunc_T *)(p - offsetof(ufunc_T, uf_name))) #define HI2UF(hi) HIKEY2UF((hi)->hi_key) /// Defines for Vim variables @@ -127,6 +96,7 @@ typedef enum { VV__NULL_LIST, // List with NULL value. For test purposes only. VV__NULL_DICT, // Dictionary with NULL value. For test purposes only. VV_VIM_DID_ENTER, + VV_TESTING, VV_TYPE_NUMBER, VV_TYPE_STRING, VV_TYPE_FUNC, @@ -156,8 +126,8 @@ extern const list_T *eval_msgpack_type_lists[LAST_MSGPACK_TYPE + 1]; #undef LAST_MSGPACK_TYPE -/// Maximum number of function arguments -#define MAX_FUNC_ARGS 20 +typedef int (*ArgvFunc)(int current_argcount, typval_T *argv, + int called_func_argcount); #ifdef INCLUDE_GENERATED_DECLARATIONS # include "eval.h.generated.h" diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua index e0b72feb19..0e359fb61c 100644 --- a/src/nvim/eval.lua +++ b/src/nvim/eval.lua @@ -2,10 +2,10 @@ -- -- Keys: -- --- args Number of arguments, list with maximum and minimum number of arguments --- or list with a minimum number of arguments only. Defaults to zero +-- args Number of arguments, list with maximum and minimum number of arguments +-- or list with a minimum number of arguments only. Defaults to zero -- arguments. --- func Name of the C function which implements the VimL function. Defaults to +-- func Name of the C function which implements the VimL function. Defaults to -- `f_{funcname}`. local varargs = function(nr) @@ -29,9 +29,11 @@ return { assert_exception={args={1, 2}}, assert_fails={args={1, 2}}, assert_false={args={1, 2}}, + assert_inrange={args={3, 4}}, assert_match={args={2, 3}}, assert_notequal={args={2, 3}}, assert_notmatch={args={2, 3}}, + assert_report={args=1}, assert_true={args={1, 2}}, atan={args=1, func="float_op_wrapper", data="&atan"}, atan2={args=2}, @@ -103,6 +105,7 @@ return { foldtext={}, foldtextresult={args=1}, foreground={}, + funcref={args={1, 3}}, ['function']={args={1, 3}}, garbagecollect={args={0, 1}}, get={args={2, 3}}, @@ -125,11 +128,11 @@ return { getftime={args=1}, getftype={args=1}, getline={args={1, 2}}, - getloclist={args=1, func='f_getqflist'}, + getloclist={args={1, 2}}, getmatches={}, getpid={}, getpos={args=1}, - getqflist={}, + getqflist={args={0, 1}}, getreg={args={0, 3}}, getregtype={args={0, 1}}, gettabinfo={args={0, 1}}, @@ -168,6 +171,7 @@ return { invert={args=1}, isdirectory={args=1}, islocked={args=1}, + id={args=1}, items={args=1}, jobclose={args={1, 2}}, jobpid={args=1}, @@ -190,6 +194,7 @@ return { localtime={}, log={args=1, func="float_op_wrapper", data="&log"}, log10={args=1, func="float_op_wrapper", data="&log10"}, + luaeval={args={1, 2}}, map={args=2}, maparg={args={1, 4}}, mapcheck={args={1, 3}}, @@ -203,6 +208,7 @@ return { matchstr={args={2, 4}}, matchstrpos={args={2,4}}, max={args=1}, + menu_get={args={1, 2}}, min={args=1}, mkdir={args={1, 3}}, mode={args={0, 1}}, @@ -264,6 +270,7 @@ return { simplify={args=1}, sin={args=1, func="float_op_wrapper", data="&sin"}, sinh={args=1, func="float_op_wrapper", data="&sinh"}, + sockconnect={args={2,3}}, sort={args={1, 3}}, soundfold={args=1}, spellbadword={args={0, 1}}, @@ -297,13 +304,17 @@ return { tabpagenr={args={0, 1}}, tabpagewinnr={args={1, 2}}, tagfiles={}, - taglist={args=1}, + taglist={args={1, 2}}, tan={args=1, func="float_op_wrapper", data="&tan"}, tanh={args=1, func="float_op_wrapper", data="&tanh"}, tempname={}, termopen={args={1, 2}}, + test_garbagecollect_now={}, + timer_info={args={0,1}}, + timer_pause={args=2}, timer_start={args={2,3}}, timer_stop={args=1}, + timer_stopall={args=0}, tolower={args=1}, toupper={args=1}, tr={args=3}, diff --git a/src/nvim/eval/decode.c b/src/nvim/eval/decode.c index 43e9f76c0f..9c9c2c2dc8 100644 --- a/src/nvim/eval/decode.c +++ b/src/nvim/eval/decode.c @@ -1,12 +1,17 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #include <stddef.h> #include <msgpack.h> -#include "nvim/eval_defs.h" +#include "nvim/eval/typval.h" #include "nvim/eval.h" #include "nvim/eval/encode.h" #include "nvim/ascii.h" +#include "nvim/macros.h" #include "nvim/message.h" +#include "nvim/globals.h" #include "nvim/charset.h" // vim_str2nr #include "nvim/lib/kvec.h" #include "nvim/vim.h" // OK, FAIL @@ -51,16 +56,16 @@ static inline void create_special_dict(typval_T *const rettv, typval_T val) FUNC_ATTR_NONNULL_ALL { - dict_T *const dict = dict_alloc(); - dictitem_T *const type_di = dictitem_alloc((char_u *) "_TYPE"); + dict_T *const dict = tv_dict_alloc(); + dictitem_T *const type_di = tv_dict_item_alloc_len(S_LEN("_TYPE")); type_di->di_tv.v_type = VAR_LIST; type_di->di_tv.v_lock = VAR_UNLOCKED; type_di->di_tv.vval.v_list = (list_T *) eval_msgpack_type_lists[type]; type_di->di_tv.vval.v_list->lv_refcount++; - dict_add(dict, type_di); - dictitem_T *const val_di = dictitem_alloc((char_u *) "_VAL"); + tv_dict_add(dict, type_di); + dictitem_T *const val_di = tv_dict_item_alloc_len(S_LEN("_VAL")); val_di->di_tv = val; - dict_add(dict, val_di); + tv_dict_add(dict, val_di); dict->dv_refcount++; *rettv = (typval_T) { .v_type = VAR_DICT, @@ -118,18 +123,18 @@ static inline int json_decoder_pop(ValuesStackItem obj, if (last_container.container.vval.v_list->lv_len != 0 && !obj.didcomma) { EMSG2(_("E474: Expected comma before list item: %s"), val_location); - clear_tv(&obj.val); + tv_clear(&obj.val); return FAIL; } assert(last_container.special_val == NULL); - listitem_T *obj_li = listitem_alloc(); + listitem_T *obj_li = tv_list_item_alloc(); obj_li->li_tv = obj.val; - list_append(last_container.container.vval.v_list, obj_li); + tv_list_append(last_container.container.vval.v_list, obj_li); } else if (last_container.stack_index == kv_size(*stack) - 2) { if (!obj.didcolon) { EMSG2(_("E474: Expected colon before dictionary value: %s"), val_location); - clear_tv(&obj.val); + tv_clear(&obj.val); return FAIL; } ValuesStackItem key = kv_pop(*stack); @@ -138,34 +143,35 @@ static inline int json_decoder_pop(ValuesStackItem obj, assert(!(key.is_special_string || key.val.vval.v_string == NULL || *key.val.vval.v_string == NUL)); - dictitem_T *obj_di = dictitem_alloc(key.val.vval.v_string); - clear_tv(&key.val); - if (dict_add(last_container.container.vval.v_dict, obj_di) + dictitem_T *const obj_di = tv_dict_item_alloc( + (const char *)key.val.vval.v_string); + tv_clear(&key.val); + if (tv_dict_add(last_container.container.vval.v_dict, obj_di) == FAIL) { assert(false); } obj_di->di_tv = obj.val; } else { - list_T *const kv_pair = list_alloc(); - list_append_list(last_container.special_val, kv_pair); - listitem_T *const key_li = listitem_alloc(); + list_T *const kv_pair = tv_list_alloc(); + tv_list_append_list(last_container.special_val, kv_pair); + listitem_T *const key_li = tv_list_item_alloc(); key_li->li_tv = key.val; - list_append(kv_pair, key_li); - listitem_T *const val_li = listitem_alloc(); + tv_list_append(kv_pair, key_li); + listitem_T *const val_li = tv_list_item_alloc(); val_li->li_tv = obj.val; - list_append(kv_pair, val_li); + tv_list_append(kv_pair, val_li); } } else { // Object with key only if (!obj.is_special_string && obj.val.v_type != VAR_STRING) { EMSG2(_("E474: Expected string key: %s"), *pp); - clear_tv(&obj.val); + tv_clear(&obj.val); return FAIL; } else if (!obj.didcomma && (last_container.special_val == NULL && (DICT_LEN(last_container.container.vval.v_dict) != 0))) { EMSG2(_("E474: Expected comma before dictionary key: %s"), val_location); - clear_tv(&obj.val); + tv_clear(&obj.val); return FAIL; } // Handle empty key and key represented as special dictionary @@ -173,16 +179,16 @@ static inline int json_decoder_pop(ValuesStackItem obj, && (obj.is_special_string || obj.val.vval.v_string == NULL || *obj.val.vval.v_string == NUL - || dict_find(last_container.container.vval.v_dict, - obj.val.vval.v_string, -1))) { - clear_tv(&obj.val); + || tv_dict_find(last_container.container.vval.v_dict, + (const char *)obj.val.vval.v_string, -1))) { + tv_clear(&obj.val); // Restart (void) kv_pop(*container_stack); ValuesStackItem last_container_val = kv_A(*stack, last_container.stack_index); while (kv_size(*stack) > last_container.stack_index) { - clear_tv(&(kv_pop(*stack).val)); + tv_clear(&(kv_pop(*stack).val)); } *pp = last_container.s; *didcomma = last_container_val.didcomma; @@ -218,10 +224,80 @@ static inline int json_decoder_pop(ValuesStackItem obj, } \ } while (0) +/// Create a new special dictionary that ought to represent a MAP +/// +/// @param[out] ret_tv Address where new special dictionary is saved. +/// +/// @return [allocated] list which should contain key-value pairs. Return value +/// may be safely ignored. +list_T *decode_create_map_special_dict(typval_T *const ret_tv) + FUNC_ATTR_NONNULL_ALL +{ + list_T *const list = tv_list_alloc(); + list->lv_refcount++; + create_special_dict(ret_tv, kMPMap, ((typval_T) { + .v_type = VAR_LIST, + .v_lock = VAR_UNLOCKED, + .vval = { .v_list = list }, + })); + return list; +} + +/// Convert char* string to typval_T +/// +/// Depending on whether string has (no) NUL bytes, it may use a special +/// dictionary or decode string to VAR_STRING. +/// +/// @param[in] s String to decode. +/// @param[in] len String length. +/// @param[in] hasnul Whether string has NUL byte, not or it was not yet +/// determined. +/// @param[in] binary If true, save special string type as kMPBinary, +/// otherwise kMPString. +/// @param[in] s_allocated If true, then `s` was allocated and can be saved in +/// a returned structure. If it is not saved there, it +/// will be freed. +/// +/// @return Decoded string. +typval_T decode_string(const char *const s, const size_t len, + const TriState hasnul, const bool binary, + const bool s_allocated) + FUNC_ATTR_WARN_UNUSED_RESULT +{ + assert(s != NULL || len == 0); + const bool really_hasnul = (hasnul == kNone + ? memchr(s, NUL, len) != NULL + : (bool)hasnul); + if (really_hasnul) { + list_T *const list = tv_list_alloc(); + list->lv_refcount++; + typval_T tv; + create_special_dict(&tv, binary ? kMPBinary : kMPString, ((typval_T) { + .v_type = VAR_LIST, + .v_lock = VAR_UNLOCKED, + .vval = { .v_list = list }, + })); + const int elw_ret = encode_list_write((void *)list, s, len); + if (s_allocated) { + xfree((void *)s); + } + if (elw_ret == -1) { + tv_clear(&tv); + return (typval_T) { .v_type = VAR_UNKNOWN, .v_lock = VAR_UNLOCKED }; + } + return tv; + } else { + return (typval_T) { + .v_type = VAR_STRING, + .v_lock = VAR_UNLOCKED, + .vval = { .v_string = (char_u *)( + s_allocated ? (char *)s : xmemdupz(s, len)) }, + }; + } +} + /// Parse JSON double-quoted string /// -/// @param[in] conv Defines conversion necessary to convert UTF-8 string to -/// &encoding. /// @param[in] buf Buffer being converted. /// @param[in] buf_len Length of the buffer. /// @param[in,out] pp Pointer to the start of the string. Must point to '"'. @@ -238,8 +314,7 @@ static inline int json_decoder_pop(ValuesStackItem obj, /// value when decoder is restarted, otherwise unused. /// /// @return OK in case of success, FAIL in case of error. -static inline int parse_json_string(vimconv_T *const conv, - const char *const buf, const size_t buf_len, +static inline int parse_json_string(const char *const buf, const size_t buf_len, const char **const pp, ValuesStack *const stack, ContainerStack *const container_stack, @@ -360,8 +435,8 @@ static inline int parse_json_string(vimconv_T *const conv, case 'u': { const char ubuf[] = { t[1], t[2], t[3], t[4] }; t += 4; - unsigned long ch; - vim_str2nr((char_u *) ubuf, NULL, NULL, + uvarnumber_T ch; + vim_str2nr((char_u *)ubuf, NULL, NULL, STR2NR_HEX | STR2NR_FORCE, NULL, &ch, 4); if (ch == 0) { hasnul = true; @@ -414,43 +489,13 @@ static inline int parse_json_string(vimconv_T *const conv, } PUT_FST_IN_PAIR(fst_in_pair, str_end); #undef PUT_FST_IN_PAIR - if (conv->vc_type != CONV_NONE) { - size_t str_len = (size_t) (str_end - str); - char *const new_str = (char *) string_convert(conv, (char_u *) str, - &str_len); - if (new_str == NULL) { - emsgf(_("E474: Failed to convert string \"%.*s\" from UTF-8"), - (int) str_len, str); - xfree(str); - goto parse_json_string_fail; - } - xfree(str); - str = new_str; - str_end = new_str + str_len; - } - if (hasnul) { - typval_T obj; - list_T *const list = list_alloc(); - list->lv_refcount++; - create_special_dict(&obj, kMPString, ((typval_T) { - .v_type = VAR_LIST, - .v_lock = VAR_UNLOCKED, - .vval = { .v_list = list }, - })); - if (encode_list_write((void *) list, str, (size_t) (str_end - str)) - == -1) { - clear_tv(&obj); - goto parse_json_string_fail; - } - xfree(str); - POP(obj, true); - } else { - *str_end = NUL; - POP(((typval_T) { - .v_type = VAR_STRING, - .vval = { .v_string = (char_u *) str }, - }), false); + *str_end = NUL; + typval_T obj = decode_string( + str, (size_t)(str_end - str), hasnul ? kTrue : kFalse, false, true); + if (obj.v_type == VAR_UNKNOWN) { + goto parse_json_string_fail; } + POP(obj, obj.v_type != VAR_STRING); goto parse_json_string_ret; parse_json_string_fail: ret = FAIL; @@ -564,7 +609,7 @@ parse_json_number_check: tv.v_type = VAR_FLOAT; } else { // Convert integer - long nr; + varnumber_T nr; int num_len; vim_str2nr((char_u *) s, NULL, &num_len, 0, &nr, NULL, (int) (p - s)); if ((int) exp_num_len != num_len) { @@ -572,7 +617,7 @@ parse_json_number_check: "to integer vim_str2nr consumed %i bytes in place of %zu"), (int) exp_num_len, s, num_len, exp_num_len); } - tv.vval.v_number = (varnumber_T) nr; + tv.vval.v_number = nr; } if (json_decoder_pop(OBJ(tv, false, *didcomma, *didcolon), stack, container_stack, @@ -624,9 +669,6 @@ int json_decode_string(const char *const buf, const size_t buf_len, EMSG(_("E474: Attempt to decode a blank string")); return FAIL; } - vimconv_T conv = { .vc_type = CONV_NONE }; - convert_setup(&conv, (char_u *) "utf-8", p_enc); - conv.vc_fail = true; int ret = OK; ValuesStack stack = KV_INITIAL_VALUE; ContainerStack container_stack = KV_INITIAL_VALUE; @@ -772,7 +814,7 @@ json_decode_string_cycle_start: break; } case '"': { - if (parse_json_string(&conv, buf, buf_len, &p, &stack, &container_stack, + if (parse_json_string(buf, buf_len, &p, &stack, &container_stack, &next_map_special, &didcomma, &didcolon) == FAIL) { // Error message was already given @@ -806,7 +848,7 @@ json_decode_string_cycle_start: break; } case '[': { - list_T *list = list_alloc(); + list_T *list = tv_list_alloc(); list->lv_refcount++; typval_T tv = { .v_type = VAR_LIST, @@ -827,15 +869,9 @@ json_decode_string_cycle_start: list_T *val_list = NULL; if (next_map_special) { next_map_special = false; - val_list = list_alloc(); - val_list->lv_refcount++; - create_special_dict(&tv, kMPMap, ((typval_T) { - .v_type = VAR_LIST, - .v_lock = VAR_UNLOCKED, - .vval = { .v_list = val_list }, - })); + val_list = decode_create_map_special_dict(&tv); } else { - dict_T *dict = dict_alloc(); + dict_T *dict = tv_dict_alloc(); dict->dv_refcount++; tv = (typval_T) { .v_type = VAR_DICT, @@ -887,7 +923,7 @@ json_decode_string_after_cycle: json_decode_string_fail: ret = FAIL; while (kv_size(stack)) { - clear_tv(&(kv_pop(stack).val)); + tv_clear(&(kv_pop(stack).val)); } json_decode_string_ret: kv_destroy(stack); @@ -933,7 +969,7 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv) .vval = { .v_number = (varnumber_T) mobj.via.u64 }, }; } else { - list_T *const list = list_alloc(); + list_T *const list = tv_list_alloc(); list->lv_refcount++; create_special_dict(rettv, kMPInteger, ((typval_T) { .v_type = VAR_LIST, @@ -941,10 +977,10 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv) .vval = { .v_list = list }, })); uint64_t n = mobj.via.u64; - list_append_number(list, 1); - list_append_number(list, (varnumber_T) ((n >> 62) & 0x3)); - list_append_number(list, (varnumber_T) ((n >> 31) & 0x7FFFFFFF)); - list_append_number(list, (varnumber_T) (n & 0x7FFFFFFF)); + tv_list_append_number(list, 1); + tv_list_append_number(list, (varnumber_T)((n >> 62) & 0x3)); + tv_list_append_number(list, (varnumber_T)((n >> 31) & 0x7FFFFFFF)); + tv_list_append_number(list, (varnumber_T)(n & 0x7FFFFFFF)); } break; } @@ -956,22 +992,28 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv) .vval = { .v_number = (varnumber_T) mobj.via.i64 }, }; } else { - list_T *const list = list_alloc(); + list_T *const list = tv_list_alloc(); list->lv_refcount++; create_special_dict(rettv, kMPInteger, ((typval_T) { .v_type = VAR_LIST, .v_lock = VAR_UNLOCKED, .vval = { .v_list = list }, })); - uint64_t n = -((uint64_t) mobj.via.i64); - list_append_number(list, -1); - list_append_number(list, (varnumber_T) ((n >> 62) & 0x3)); - list_append_number(list, (varnumber_T) ((n >> 31) & 0x7FFFFFFF)); - list_append_number(list, (varnumber_T) (n & 0x7FFFFFFF)); + uint64_t n = -((uint64_t)mobj.via.i64); + tv_list_append_number(list, -1); + tv_list_append_number(list, (varnumber_T)((n >> 62) & 0x3)); + tv_list_append_number(list, (varnumber_T)((n >> 31) & 0x7FFFFFFF)); + tv_list_append_number(list, (varnumber_T)(n & 0x7FFFFFFF)); } break; } - case MSGPACK_OBJECT_FLOAT: { +#ifdef NVIM_MSGPACK_HAS_FLOAT32 + case MSGPACK_OBJECT_FLOAT32: + case MSGPACK_OBJECT_FLOAT64: +#else + case MSGPACK_OBJECT_FLOAT: +#endif + { *rettv = (typval_T) { .v_type = VAR_FLOAT, .v_lock = VAR_UNLOCKED, @@ -980,43 +1022,23 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv) break; } case MSGPACK_OBJECT_STR: { - list_T *const list = list_alloc(); - list->lv_refcount++; - create_special_dict(rettv, kMPString, ((typval_T) { - .v_type = VAR_LIST, - .v_lock = VAR_UNLOCKED, - .vval = { .v_list = list }, - })); - if (encode_list_write((void *) list, mobj.via.str.ptr, mobj.via.str.size) - == -1) { + *rettv = decode_string(mobj.via.bin.ptr, mobj.via.bin.size, kTrue, false, + false); + if (rettv->v_type == VAR_UNKNOWN) { return FAIL; } break; } case MSGPACK_OBJECT_BIN: { - if (memchr(mobj.via.bin.ptr, NUL, mobj.via.bin.size) == NULL) { - *rettv = (typval_T) { - .v_type = VAR_STRING, - .v_lock = VAR_UNLOCKED, - .vval = { .v_string = xmemdupz(mobj.via.bin.ptr, mobj.via.bin.size) }, - }; - break; - } - list_T *const list = list_alloc(); - list->lv_refcount++; - create_special_dict(rettv, kMPBinary, ((typval_T) { - .v_type = VAR_LIST, - .v_lock = VAR_UNLOCKED, - .vval = { .v_list = list }, - })); - if (encode_list_write((void *) list, mobj.via.bin.ptr, mobj.via.bin.size) - == -1) { + *rettv = decode_string(mobj.via.bin.ptr, mobj.via.bin.size, kNone, true, + false); + if (rettv->v_type == VAR_UNKNOWN) { return FAIL; } break; } case MSGPACK_OBJECT_ARRAY: { - list_T *const list = list_alloc(); + list_T *const list = tv_list_alloc(); list->lv_refcount++; *rettv = (typval_T) { .v_type = VAR_LIST, @@ -1024,9 +1046,9 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv) .vval = { .v_list = list }, }; for (size_t i = 0; i < mobj.via.array.size; i++) { - listitem_T *const li = listitem_alloc(); + listitem_T *const li = tv_list_item_alloc(); li->li_tv.v_type = VAR_UNKNOWN; - list_append(list, li); + tv_list_append(list, li); if (msgpack_to_vim(mobj.via.array.ptr[i], &li->li_tv) == FAIL) { return FAIL; } @@ -1042,7 +1064,7 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv) goto msgpack_to_vim_generic_map; } } - dict_T *const dict = dict_alloc(); + dict_T *const dict = tv_dict_alloc(); dict->dv_refcount++; *rettv = (typval_T) { .v_type = VAR_DICT, @@ -1055,9 +1077,9 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv) memcpy(&di->di_key[0], mobj.via.map.ptr[i].key.via.str.ptr, mobj.via.map.ptr[i].key.via.str.size); di->di_tv.v_type = VAR_UNKNOWN; - if (dict_add(dict, di) == FAIL) { + if (tv_dict_add(dict, di) == FAIL) { // Duplicate key: fallback to generic map - clear_tv(rettv); + tv_clear(rettv); xfree(di); goto msgpack_to_vim_generic_map; } @@ -1067,22 +1089,16 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv) } break; msgpack_to_vim_generic_map: {} - list_T *const list = list_alloc(); - list->lv_refcount++; - create_special_dict(rettv, kMPMap, ((typval_T) { - .v_type = VAR_LIST, - .v_lock = VAR_UNLOCKED, - .vval = { .v_list = list }, - })); + list_T *const list = decode_create_map_special_dict(rettv); for (size_t i = 0; i < mobj.via.map.size; i++) { - list_T *const kv_pair = list_alloc(); - list_append_list(list, kv_pair); - listitem_T *const key_li = listitem_alloc(); + list_T *const kv_pair = tv_list_alloc(); + tv_list_append_list(list, kv_pair); + listitem_T *const key_li = tv_list_item_alloc(); key_li->li_tv.v_type = VAR_UNKNOWN; - list_append(kv_pair, key_li); - listitem_T *const val_li = listitem_alloc(); + tv_list_append(kv_pair, key_li); + listitem_T *const val_li = tv_list_item_alloc(); val_li->li_tv.v_type = VAR_UNKNOWN; - list_append(kv_pair, val_li); + tv_list_append(kv_pair, val_li); if (msgpack_to_vim(mobj.via.map.ptr[i].key, &key_li->li_tv) == FAIL) { return FAIL; } @@ -1093,11 +1109,11 @@ msgpack_to_vim_generic_map: {} break; } case MSGPACK_OBJECT_EXT: { - list_T *const list = list_alloc(); + list_T *const list = tv_list_alloc(); list->lv_refcount++; - list_append_number(list, mobj.via.ext.type); - list_T *const ext_val_list = list_alloc(); - list_append_list(list, ext_val_list); + tv_list_append_number(list, mobj.via.ext.type); + list_T *const ext_val_list = tv_list_alloc(); + tv_list_append_list(list, ext_val_list); create_special_dict(rettv, kMPExt, ((typval_T) { .v_type = VAR_LIST, .v_lock = VAR_UNLOCKED, diff --git a/src/nvim/eval/decode.h b/src/nvim/eval/decode.h index 5c25a64f7a..77fc4c78c2 100644 --- a/src/nvim/eval/decode.h +++ b/src/nvim/eval/decode.h @@ -5,7 +5,8 @@ #include <msgpack.h> -#include "nvim/eval_defs.h" +#include "nvim/eval/typval.h" +#include "nvim/globals.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "eval/decode.h.generated.h" diff --git a/src/nvim/eval/encode.c b/src/nvim/eval/encode.c index ee66b7cf09..ef647b3ee4 100644 --- a/src/nvim/eval/encode.c +++ b/src/nvim/eval/encode.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + /// @file encode.c /// /// File containing functions for encoding and decoding VimL values. @@ -11,9 +14,9 @@ #include <math.h> #include "nvim/eval/encode.h" -#include "nvim/buffer_defs.h" // vimconv_T +#include "nvim/buffer_defs.h" #include "nvim/eval.h" -#include "nvim/eval_defs.h" +#include "nvim/eval/typval.h" #include "nvim/garray.h" #include "nvim/mbyte.h" #include "nvim/message.h" @@ -29,10 +32,6 @@ #define utf_ptr2char(b) utf_ptr2char((char_u *)b) #define utf_ptr2len(b) ((size_t)utf_ptr2len((char_u *)b)) #define utf_char2len(b) ((size_t)utf_char2len(b)) -#define string_convert(a, b, c) \ - ((char *)string_convert((vimconv_T *)a, (char_u *)b, c)) -#define convert_setup(vcp, from, to) \ - (convert_setup(vcp, (char_u *)from, (char_u *)to)) const char *const encode_special_var_names[] = { [kSpecialVarNull] = "null", @@ -45,7 +44,8 @@ const char *const encode_special_var_names[] = { #endif /// Msgpack callback for writing to readfile()-style list -int encode_list_write(void *data, const char *buf, size_t len) +int encode_list_write(void *const data, const char *const buf, const size_t len) + FUNC_ATTR_NONNULL_ARG(1) { if (len == 0) { return 0; @@ -80,11 +80,11 @@ int encode_list_write(void *data, const char *buf, size_t len) str = xmemdupz(line_start, line_length); memchrsub(str, NUL, NL, line_length); } - list_append_allocated_string(list, str); + tv_list_append_allocated_string(list, str); line_end++; } if (line_end == end) { - list_append_allocated_string(list, NULL); + tv_list_append_allocated_string(list, NULL); } return 0; } @@ -182,9 +182,9 @@ static int conv_error(const char *const msg, const MPConvStack *const mpstack, } } } - EMSG3(msg, objname, (kv_size(*mpstack) == 0 - ? _("itself") - : (char *) msg_ga.ga_data)); + emsgf(msg, _(objname), (kv_size(*mpstack) == 0 + ? _("itself") + : (char *)msg_ga.ga_data)); ga_clear(&msg_ga); return FAIL; } @@ -253,9 +253,11 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, char *const buf_end = buf + nbuf; char *p = buf; while (p < buf_end) { + assert(state->li_length == 0 || state->li->li_tv.vval.v_string != NULL); for (size_t i = state->offset; i < state->li_length && p < buf_end; i++) { - const char ch = (char) state->li->li_tv.vval.v_string[state->offset++]; - *p++ = (char) ((char) ch == (char) NL ? (char) NUL : (char) ch); + assert(state->li->li_tv.vval.v_string != NULL); + const char ch = (char)state->li->li_tv.vval.v_string[state->offset++]; + *p++ = (char)((char)ch == (char)NL ? (char)NUL : (char)ch); } if (p < buf_end) { state->li = state->li->li_next; @@ -536,17 +538,6 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, } \ } while (0) -/// Last used p_enc value -/// -/// Generic pointer: it is not used as a string, only pointer comparisons are -/// performed. Must not be freed. -static const void *last_p_enc = NULL; - -/// Conversion setup for converting from last_p_enc to UTF-8 -static vimconv_T p_enc_conv = { - .vc_type = CONV_NONE, -}; - /// Escape sequences used in JSON static const char escapes[][3] = { [BS] = "\\b", @@ -578,33 +569,15 @@ static inline int convert_to_json_string(garray_T *const gap, } else { size_t utf_len = len; char *tofree = NULL; - if (last_p_enc != (const void *) p_enc) { - p_enc_conv.vc_type = CONV_NONE; - convert_setup(&p_enc_conv, p_enc, "utf-8"); - p_enc_conv.vc_fail = true; - last_p_enc = p_enc; - } - if (p_enc_conv.vc_type != CONV_NONE) { - tofree = string_convert(&p_enc_conv, buf, &utf_len); - if (tofree == NULL) { - emsgf(_("E474: Failed to convert string \"%.*s\" to UTF-8"), - utf_len, utf_buf); - return FAIL; - } - utf_buf = tofree; - } size_t str_len = 0; - // Encode character as \u0000 if - // 1. It is an ASCII control character (0x0 .. 0x1F, 0x7F). - // 2. &encoding is not UTF-8 and code point is above 0x7F. - // 3. &encoding is UTF-8 and code point is not printable according to - // utf_printable(). - // This is done to make it possible to :echo values when &encoding is not - // UTF-8. -#define ENCODE_RAW(p_enc_conv, ch) \ - (ch >= 0x20 && (p_enc_conv.vc_type == CONV_NONE \ - ? utf_printable(ch) \ - : ch < 0x7F)) + // Encode character as \uNNNN if + // 1. It is an ASCII control character (0x0 .. 0x1F; 0x7F not + // utf_printable and thus not checked specially). + // 2. Code point is not printable according to utf_printable(). + // This is done to make resulting values displayable on screen also not from + // Neovim. +#define ENCODE_RAW(ch) \ + (ch >= 0x20 && utf_printable(ch)) for (size_t i = 0; i < utf_len;) { const int ch = utf_ptr2char(utf_buf + i); const size_t shift = (ch == 0? 1: utf_ptr2len(utf_buf + i)); @@ -635,7 +608,7 @@ static inline int convert_to_json_string(garray_T *const gap, utf_len - (i - shift), utf_buf + i - shift); xfree(tofree); return FAIL; - } else if (ENCODE_RAW(p_enc_conv, ch)) { + } else if (ENCODE_RAW(ch)) { str_len += shift; } else { str_len += ((sizeof("\\u1234") - 1) @@ -665,7 +638,7 @@ static inline int convert_to_json_string(garray_T *const gap, break; } default: { - if (ENCODE_RAW(p_enc_conv, ch)) { + if (ENCODE_RAW(ch)) { ga_concat_len(gap, utf_buf + i, shift); } else if (ch < SURROGATE_FIRST_CHAR) { ga_concat_len(gap, ((const char[]) { @@ -743,11 +716,11 @@ bool encode_check_json_key(const typval_T *const tv) } const dictitem_T *type_di; const dictitem_T *val_di; - if ((type_di = dict_find((dict_T *) spdict, (char_u *) "_TYPE", -1)) == NULL + if ((type_di = tv_dict_find(spdict, S_LEN("_TYPE"))) == NULL || type_di->di_tv.v_type != VAR_LIST || (type_di->di_tv.vval.v_list != eval_msgpack_type_lists[kMPString] && type_di->di_tv.vval.v_list != eval_msgpack_type_lists[kMPBinary]) - || (val_di = dict_find((dict_T *) spdict, (char_u *) "_VAL", -1)) == NULL + || (val_di = tv_dict_find(spdict, S_LEN("_VAL"))) == NULL || val_di->di_tv.v_type != VAR_LIST) { return false; } @@ -822,7 +795,7 @@ char *encode_tv2string(typval_T *tv, size_t *len) garray_T ga; ga_init(&ga, (int)sizeof(char), 80); const int evs_ret = encode_vim_to_string(&ga, tv, - "encode_tv2string() argument"); + N_("encode_tv2string() argument")); (void)evs_ret; assert(evs_ret == OK); did_echo_string_emsg = false; @@ -850,7 +823,7 @@ char *encode_tv2echo(typval_T *tv, size_t *len) ga_concat(&ga, tv->vval.v_string); } } else { - const int eve_ret = encode_vim_to_echo(&ga, tv, ":echo argument"); + const int eve_ret = encode_vim_to_echo(&ga, tv, N_(":echo argument")); (void)eve_ret; assert(eve_ret == OK); } @@ -873,7 +846,8 @@ char *encode_tv2json(typval_T *tv, size_t *len) { garray_T ga; ga_init(&ga, (int)sizeof(char), 80); - const int evj_ret = encode_vim_to_json(&ga, tv, "encode_tv2json() argument"); + const int evj_ret = encode_vim_to_json(&ga, tv, + N_("encode_tv2json() argument")); if (!evj_ret) { ga_clear(&ga); } diff --git a/src/nvim/eval/executor.c b/src/nvim/eval/executor.c new file mode 100644 index 0000000000..99298cbbcf --- /dev/null +++ b/src/nvim/eval/executor.c @@ -0,0 +1,118 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + +#include "nvim/eval/typval.h" +#include "nvim/eval/executor.h" +#include "nvim/eval.h" +#include "nvim/message.h" +#include "nvim/vim.h" +#include "nvim/globals.h" + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "eval/executor.c.generated.h" +#endif + +static char *e_letwrong = N_("E734: Wrong variable type for %s="); + +char *e_listidx = N_("E684: list index out of range: %" PRId64); + +/// Hanle tv1 += tv2, -=, .= +/// +/// @param[in,out] tv1 First operand, modified typval. +/// @param[in] tv2 Second operand. +/// @param[in] op Used operator. +/// +/// @return OK or FAIL. +int eexe_mod_op(typval_T *const tv1, const typval_T *const tv2, + const char *const op) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NO_SANITIZE_UNDEFINED +{ + // Can't do anything with a Funcref, a Dict or special value on the right. + if (tv2->v_type != VAR_FUNC && tv2->v_type != VAR_DICT) { + switch (tv1->v_type) { + case VAR_DICT: + case VAR_FUNC: + case VAR_PARTIAL: + case VAR_SPECIAL: { + break; + } + case VAR_LIST: { + if (*op != '+' || tv2->v_type != VAR_LIST) { + break; + } + // List += List + if (tv1->vval.v_list != NULL && tv2->vval.v_list != NULL) { + tv_list_extend(tv1->vval.v_list, tv2->vval.v_list, NULL); + } + return OK; + } + case VAR_NUMBER: + case VAR_STRING: { + if (tv2->v_type == VAR_LIST) { + break; + } + if (*op == '+' || *op == '-') { + // nr += nr or nr -= nr + varnumber_T n = tv_get_number(tv1); + if (tv2->v_type == VAR_FLOAT) { + float_T f = (float_T)n; + + if (*op == '+') { + f += tv2->vval.v_float; + } else { + f -= tv2->vval.v_float; + } + tv_clear(tv1); + tv1->v_type = VAR_FLOAT; + tv1->vval.v_float = f; + } else { + if (*op == '+') { + n += tv_get_number(tv2); + } else { + n -= tv_get_number(tv2); + } + tv_clear(tv1); + tv1->v_type = VAR_NUMBER; + tv1->vval.v_number = n; + } + } else { + // str .= str + if (tv2->v_type == VAR_FLOAT) { + break; + } + const char *tvs = tv_get_string(tv1); + char numbuf[NUMBUFLEN]; + char *const s = (char *)concat_str( + (const char_u *)tvs, (const char_u *)tv_get_string_buf(tv2, + numbuf)); + tv_clear(tv1); + tv1->v_type = VAR_STRING; + tv1->vval.v_string = (char_u *)s; + } + return OK; + } + case VAR_FLOAT: { + if (*op == '.' || (tv2->v_type != VAR_FLOAT + && tv2->v_type != VAR_NUMBER + && tv2->v_type != VAR_STRING)) { + break; + } + const float_T f = (tv2->v_type == VAR_FLOAT + ? tv2->vval.v_float + : (float_T)tv_get_number(tv2)); + if (*op == '+') { + tv1->vval.v_float += f; + } else { + tv1->vval.v_float -= f; + } + return OK; + } + case VAR_UNKNOWN: { + assert(false); + } + } + } + + EMSG2(_(e_letwrong), op); + return FAIL; +} diff --git a/src/nvim/eval/executor.h b/src/nvim/eval/executor.h new file mode 100644 index 0000000000..3d789f76a5 --- /dev/null +++ b/src/nvim/eval/executor.h @@ -0,0 +1,11 @@ +#ifndef NVIM_EVAL_EXECUTOR_H +#define NVIM_EVAL_EXECUTOR_H + +#include "nvim/eval/typval.h" + +extern char *e_listidx; + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "eval/executor.h.generated.h" +#endif +#endif // NVIM_EVAL_EXECUTOR_H diff --git a/src/nvim/eval/gc.c b/src/nvim/eval/gc.c new file mode 100644 index 0000000000..2bbf78d827 --- /dev/null +++ b/src/nvim/eval/gc.c @@ -0,0 +1,14 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + +#include "nvim/eval/typval.h" +#include "nvim/eval/gc.h" + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "eval/gc.c.generated.h" +#endif + +/// Head of list of all dictionaries +dict_T *gc_first_dict = NULL; +/// Head of list of all lists +list_T *gc_first_list = NULL; diff --git a/src/nvim/eval/gc.h b/src/nvim/eval/gc.h new file mode 100644 index 0000000000..c2e862e469 --- /dev/null +++ b/src/nvim/eval/gc.h @@ -0,0 +1,12 @@ +#ifndef NVIM_EVAL_GC_H +#define NVIM_EVAL_GC_H + +#include "nvim/eval/typval.h" + +extern dict_T *gc_first_dict; +extern list_T *gc_first_list; + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "eval/gc.h.generated.h" +#endif +#endif // NVIM_EVAL_GC_H diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c new file mode 100644 index 0000000000..c339a5cdd2 --- /dev/null +++ b/src/nvim/eval/typval.c @@ -0,0 +1,2627 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + +#include <stdio.h> +#include <stddef.h> +#include <string.h> +#include <assert.h> +#include <stdbool.h> + +#include "nvim/lib/queue.h" +#include "nvim/eval/typval.h" +#include "nvim/eval/gc.h" +#include "nvim/eval/executor.h" +#include "nvim/eval/encode.h" +#include "nvim/eval/typval_encode.h" +#include "nvim/eval.h" +#include "nvim/types.h" +#include "nvim/assert.h" +#include "nvim/memory.h" +#include "nvim/globals.h" +#include "nvim/hashtab.h" +#include "nvim/vim.h" +#include "nvim/ascii.h" +#include "nvim/pos.h" +#include "nvim/charset.h" +#include "nvim/garray.h" +#include "nvim/gettext.h" +#include "nvim/macros.h" +#include "nvim/mbyte.h" +#include "nvim/message.h" +// TODO(ZyX-I): Move line_breakcheck out of misc1 +#include "nvim/misc1.h" // For line_breakcheck + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "eval/typval.c.generated.h" +#endif + +bool tv_in_free_unref_items = false; + +// TODO(ZyX-I): Remove DICT_MAXNEST, make users be non-recursive instead + +#define DICT_MAXNEST 100 + +const char *const tv_empty_string = ""; + +//{{{1 Lists +//{{{2 List item + +/// Allocate a list item +/// +/// @warning Allocated item is not initialized, do not forget to initialize it +/// and specifically set lv_lock. +/// +/// @return [allocated] new list item. +listitem_T *tv_list_item_alloc(void) + FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC +{ + return xmalloc(sizeof(listitem_T)); +} + +/// Free a list item +/// +/// Also clears the value. Does not touch watchers. +/// +/// @param[out] item Item to free. +void tv_list_item_free(listitem_T *const item) + FUNC_ATTR_NONNULL_ALL +{ + tv_clear(&item->li_tv); + xfree(item); +} + +/// Remove a list item from a List and free it +/// +/// Also clears the value. +/// +/// @param[out] l List to remove item from. +/// @param[in,out] item Item to remove. +void tv_list_item_remove(list_T *const l, listitem_T *const item) + FUNC_ATTR_NONNULL_ALL +{ + tv_list_remove_items(l, item, item); + tv_list_item_free(item); +} + +//{{{2 List watchers + +/// Add a watcher to a list +/// +/// @param[out] l List to add watcher to. +/// @param[in] lw Watcher to add. +void tv_list_watch_add(list_T *const l, listwatch_T *const lw) + FUNC_ATTR_NONNULL_ALL +{ + lw->lw_next = l->lv_watch; + l->lv_watch = lw; +} + +/// Remove a watcher from a list +/// +/// Does not give a warning if watcher was not found. +/// +/// @param[out] l List to remove watcher from. +/// @param[in] lwrem Watcher to remove. +void tv_list_watch_remove(list_T *const l, listwatch_T *const lwrem) + FUNC_ATTR_NONNULL_ALL +{ + listwatch_T **lwp = &l->lv_watch; + for (listwatch_T *lw = l->lv_watch; lw != NULL; lw = lw->lw_next) { + if (lw == lwrem) { + *lwp = lw->lw_next; + break; + } + lwp = &lw->lw_next; + } +} + +/// Advance watchers to the next item +/// +/// Used just before removing an item from a list. +/// +/// @param[out] l List from which item is removed. +/// @param[in] item List item being removed. +void tv_list_watch_fix(list_T *const l, const listitem_T *const item) + FUNC_ATTR_NONNULL_ALL +{ + for (listwatch_T *lw = l->lv_watch; lw != NULL; lw = lw->lw_next) { + if (lw->lw_item == item) { + lw->lw_item = item->li_next; + } + } +} + +//{{{2 Alloc/free + +/// Allocate an empty list +/// +/// Caller should take care of the reference count. +/// +/// @return [allocated] new list. +list_T *tv_list_alloc(void) + FUNC_ATTR_NONNULL_RET +{ + list_T *const list = xcalloc(1, sizeof(list_T)); + + // Prepend the list to the list of lists for garbage collection. + if (gc_first_list != NULL) { + gc_first_list->lv_used_prev = list; + } + list->lv_used_prev = NULL; + list->lv_used_next = gc_first_list; + gc_first_list = list; + return list; +} + +/// Free items contained in a list +/// +/// @param[in,out] l List to clear. +void tv_list_free_contents(list_T *const l) + FUNC_ATTR_NONNULL_ALL +{ + for (listitem_T *item = l->lv_first; item != NULL; item = l->lv_first) { + // Remove the item before deleting it. + l->lv_first = item->li_next; + tv_clear(&item->li_tv); + xfree(item); + } + l->lv_len = 0; + l->lv_idx_item = NULL; + l->lv_last = NULL; + assert(l->lv_watch == NULL); +} + +/// Free a list itself, ignoring items it contains +/// +/// Ignores the reference count. +/// +/// @param[in,out] l List to free. +void tv_list_free_list(list_T *const l) + FUNC_ATTR_NONNULL_ALL +{ + // Remove the list from the list of lists for garbage collection. + if (l->lv_used_prev == NULL) { + gc_first_list = l->lv_used_next; + } else { + l->lv_used_prev->lv_used_next = l->lv_used_next; + } + if (l->lv_used_next != NULL) { + l->lv_used_next->lv_used_prev = l->lv_used_prev; + } + + xfree(l); +} + +/// Free a list, including all items it points to +/// +/// Ignores the reference count. Does not do anything if +/// tv_in_free_unref_items is true. +/// +/// @param[in,out] l List to free. +void tv_list_free(list_T *const l) + FUNC_ATTR_NONNULL_ALL +{ + if (!tv_in_free_unref_items) { + tv_list_free_contents(l); + tv_list_free_list(l); + } +} + +/// Unreference a list +/// +/// Decrements the reference count and frees when it becomes zero or less. +/// +/// @param[in,out] l List to unreference. +void tv_list_unref(list_T *const l) +{ + if (l != NULL && --l->lv_refcount <= 0) { + tv_list_free(l); + } +} + +//{{{2 Add/remove + +/// Remove items "item" to "item2" from list "l". +/// +/// @warning Does not free the listitem or the value! +/// +/// @param[out] l List to remove from. +/// @param[in] item First item to remove. +/// @param[in] item2 Last item to remove. +void tv_list_remove_items(list_T *const l, listitem_T *const item, + listitem_T *const item2) + FUNC_ATTR_NONNULL_ALL +{ + // Notify watchers. + for (listitem_T *ip = item; ip != item2->li_next; ip = ip->li_next) { + l->lv_len--; + tv_list_watch_fix(l, ip); + } + + if (item2->li_next == NULL) { + l->lv_last = item->li_prev; + } else { + item2->li_next->li_prev = item->li_prev; + } + if (item->li_prev == NULL) { + l->lv_first = item2->li_next; + } else { + item->li_prev->li_next = item2->li_next; + } + l->lv_idx_item = NULL; +} + +/// Insert list item +/// +/// @param[out] l List to insert to. +/// @param[in,out] ni Item to insert. +/// @param[in] item Item to insert before. If NULL, inserts at the end of the +/// list. +void tv_list_insert(list_T *const l, listitem_T *const ni, + listitem_T *const item) + FUNC_ATTR_NONNULL_ARG(1, 2) +{ + if (item == NULL) { + // Append new item at end of list. + tv_list_append(l, ni); + } else { + // Insert new item before existing item. + ni->li_prev = item->li_prev; + ni->li_next = item; + if (item->li_prev == NULL) { + l->lv_first = ni; + l->lv_idx++; + } else { + item->li_prev->li_next = ni; + l->lv_idx_item = NULL; + } + item->li_prev = ni; + l->lv_len++; + } +} + +/// Insert VimL value into a list +/// +/// @param[out] l List to insert to. +/// @param[in,out] tv Value to insert. Is copied (@see tv_copy()) to an +/// allocated listitem_T and inserted. +/// @param[in] item Item to insert before. If NULL, inserts at the end of the +/// list. +void tv_list_insert_tv(list_T *const l, typval_T *const tv, + listitem_T *const item) +{ + listitem_T *const ni = tv_list_item_alloc(); + + tv_copy(tv, &ni->li_tv); + tv_list_insert(l, ni, item); +} + +/// Append item to the end of list +/// +/// @param[out] l List to append to. +/// @param[in,out] item Item to append. +void tv_list_append(list_T *const l, listitem_T *const item) + FUNC_ATTR_NONNULL_ALL +{ + if (l->lv_last == NULL) { + // empty list + l->lv_first = item; + l->lv_last = item; + item->li_prev = NULL; + } else { + l->lv_last->li_next = item; + item->li_prev = l->lv_last; + l->lv_last = item; + } + l->lv_len++; + item->li_next = NULL; +} + +/// Append VimL value to the end of list +/// +/// @param[out] l List to append to. +/// @param[in,out] tv Value to append. Is copied (@see tv_copy()) to an +/// allocated listitem_T. +void tv_list_append_tv(list_T *const l, typval_T *const tv) + FUNC_ATTR_NONNULL_ALL +{ + listitem_T *const li = tv_list_item_alloc(); + tv_copy(tv, &li->li_tv); + tv_list_append(l, li); +} + +/// Append a list to a list as one item +/// +/// @param[out] l List to append to. +/// @param[in,out] itemlist List to append. Reference count is increased. +void tv_list_append_list(list_T *const list, list_T *const itemlist) + FUNC_ATTR_NONNULL_ARG(1) +{ + listitem_T *const li = tv_list_item_alloc(); + + li->li_tv.v_type = VAR_LIST; + li->li_tv.v_lock = VAR_UNLOCKED; + li->li_tv.vval.v_list = itemlist; + tv_list_append(list, li); + if (itemlist != NULL) { + itemlist->lv_refcount++; + } +} + +/// Append a dictionary to a list +/// +/// @param[out] l List to append to. +/// @param[in,out] dict Dictionary to append. Reference count is increased. +void tv_list_append_dict(list_T *const list, dict_T *const dict) + FUNC_ATTR_NONNULL_ARG(1) +{ + listitem_T *const li = tv_list_item_alloc(); + + li->li_tv.v_type = VAR_DICT; + li->li_tv.v_lock = VAR_UNLOCKED; + li->li_tv.vval.v_dict = dict; + tv_list_append(list, li); + if (dict != NULL) { + dict->dv_refcount++; + } +} + +/// Make a copy of "str" and append it as an item to list "l" +/// +/// @param[out] l List to append to. +/// @param[in] str String to append. +/// @param[in] len Length of the appended string. May be -1, in this +/// case string is considered to be usual zero-terminated +/// string or NULL โemptyโ string. +void tv_list_append_string(list_T *const l, const char *const str, + const ptrdiff_t len) + FUNC_ATTR_NONNULL_ARG(1) +{ + if (str == NULL) { + assert(len == 0 || len == -1); + tv_list_append_allocated_string(l, NULL); + } else { + tv_list_append_allocated_string(l, (len >= 0 + ? xmemdupz(str, (size_t)len) + : xstrdup(str))); + } +} + +/// Append given string to the list +/// +/// Unlike list_append_string this function does not copy the string. +/// +/// @param[out] l List to append to. +/// @param[in] str String to append. +void tv_list_append_allocated_string(list_T *const l, char *const str) + FUNC_ATTR_NONNULL_ARG(1) +{ + listitem_T *const li = tv_list_item_alloc(); + + tv_list_append(l, li); + li->li_tv.v_type = VAR_STRING; + li->li_tv.v_lock = VAR_UNLOCKED; + li->li_tv.vval.v_string = (char_u *)str; +} + +/// Append number to the list +/// +/// @param[out] l List to append to. +/// @param[in] n Number to append. Will be recorded in the allocated +/// listitem_T. +void tv_list_append_number(list_T *const l, const varnumber_T n) +{ + listitem_T *const li = tv_list_item_alloc(); + li->li_tv.v_type = VAR_NUMBER; + li->li_tv.v_lock = VAR_UNLOCKED; + li->li_tv.vval.v_number = n; + tv_list_append(l, li); +} + +//{{{2 Operations on the whole list + +/// Make a copy of list +/// +/// @param[in] conv If non-NULL, then all internal strings will be converted. +/// Only used when `deep` is true. +/// @param[in] orig Original list to copy. +/// @param[in] deep If false, then shallow copy will be done. +/// @param[in] copyID See var_item_copy(). +/// +/// @return Copied list. May be NULL in case original list is NULL or some +/// failure happens. The refcount of the new list is set to 1. +list_T *tv_list_copy(const vimconv_T *const conv, list_T *const orig, + const bool deep, const int copyID) + FUNC_ATTR_WARN_UNUSED_RESULT +{ + if (orig == NULL) { + return NULL; + } + + list_T *copy = tv_list_alloc(); + if (copyID != 0) { + // Do this before adding the items, because one of the items may + // refer back to this list. + orig->lv_copyID = copyID; + orig->lv_copylist = copy; + } + listitem_T *item; + for (item = orig->lv_first; item != NULL && !got_int; + item = item->li_next) { + listitem_T *const ni = tv_list_item_alloc(); + if (deep) { + if (var_item_copy(conv, &item->li_tv, &ni->li_tv, deep, copyID) == FAIL) { + xfree(ni); + break; + } + } else { + tv_copy(&item->li_tv, &ni->li_tv); + } + tv_list_append(copy, ni); + } + copy->lv_refcount++; + if (item != NULL) { + tv_list_unref(copy); + copy = NULL; + } + + return copy; +} + +/// Extend first list with the second +/// +/// @param[out] l1 List to extend. +/// @param[in] l2 List to extend with. +/// @param[in] bef If not NULL, extends before this item. +void tv_list_extend(list_T *const l1, list_T *const l2, + listitem_T *const bef) + FUNC_ATTR_NONNULL_ARG(1, 2) +{ + int todo = l2->lv_len; + listitem_T *const befbef = (bef == NULL ? NULL : bef->li_prev); + listitem_T *const saved_next = (befbef == NULL ? NULL : befbef->li_next); + // We also quit the loop when we have inserted the original item count of + // the list, avoid a hang when we extend a list with itself. + for (listitem_T *item = l2->lv_first + ; item != NULL && --todo >= 0 + ; item = (item == befbef ? saved_next : item->li_next)) { + tv_list_insert_tv(l1, &item->li_tv, bef); + } +} + +/// Concatenate lists into a new list +/// +/// @param[in] l1 First list. +/// @param[in] l2 Second list. +/// @param[out] ret_tv Location where new list is saved. +/// +/// @return OK or FAIL. +int tv_list_concat(list_T *const l1, list_T *const l2, typval_T *const tv) + FUNC_ATTR_WARN_UNUSED_RESULT +{ + list_T *l; + + tv->v_type = VAR_LIST; + + if (l1 == NULL && l2 == NULL) { + l = NULL; + } else if (l1 == NULL) { + l = tv_list_copy(NULL, l2, false, 0); + } else { + l = tv_list_copy(NULL, l1, false, 0); + if (l != NULL && l2 != NULL) { + tv_list_extend(l, l2, NULL); + } + } + if (l == NULL && !(l1 == NULL && l2 == NULL)) { + return FAIL; + } + + tv->vval.v_list = l; + return OK; +} + +typedef struct { + char_u *s; + char_u *tofree; +} Join; + +/// Join list into a string, helper function +/// +/// @param[out] gap Garray where result will be saved. +/// @param[in] l List to join. +/// @param[in] sep Used separator. +/// @param[in] join_gap Garray to keep each list item string. +/// +/// @return OK in case of success, FAIL otherwise. +static int list_join_inner(garray_T *const gap, list_T *const l, + const char *const sep, garray_T *const join_gap) + FUNC_ATTR_NONNULL_ALL +{ + size_t sumlen = 0; + bool first = true; + listitem_T *item; + + // Stringify each item in the list. + for (item = l->lv_first; item != NULL && !got_int; item = item->li_next) { + char *s; + size_t len; + s = encode_tv2echo(&item->li_tv, &len); + if (s == NULL) { + return FAIL; + } + + sumlen += len; + + Join *const p = GA_APPEND_VIA_PTR(Join, join_gap); + p->tofree = p->s = (char_u *)s; + + line_breakcheck(); + } + + // Allocate result buffer with its total size, avoid re-allocation and + // multiple copy operations. Add 2 for a tailing ']' and NUL. + if (join_gap->ga_len >= 2) { + sumlen += strlen(sep) * (size_t)(join_gap->ga_len - 1); + } + ga_grow(gap, (int)sumlen + 2); + + for (int i = 0; i < join_gap->ga_len && !got_int; i++) { + if (first) { + first = false; + } else { + ga_concat(gap, (const char_u *)sep); + } + const Join *const p = ((const Join *)join_gap->ga_data) + i; + + if (p->s != NULL) { + ga_concat(gap, p->s); + } + line_breakcheck(); + } + + return OK; +} + +/// Join list into a string using given separator +/// +/// @param[out] gap Garray where result will be saved. +/// @param[in] l Joined list. +/// @param[in] sep Separator. +/// +/// @return OK in case of success, FAIL otherwise. +int tv_list_join(garray_T *const gap, list_T *const l, const char *const sep) + FUNC_ATTR_NONNULL_ALL +{ + if (l->lv_len < 1) { + return OK; + } + + garray_T join_ga; + int retval; + + ga_init(&join_ga, (int)sizeof(Join), l->lv_len); + retval = list_join_inner(gap, l, sep, &join_ga); + +#define FREE_JOIN_TOFREE(join) xfree((join)->tofree) + GA_DEEP_CLEAR(&join_ga, Join, FREE_JOIN_TOFREE); +#undef FREE_JOIN_TOFREE + + return retval; +} + +/// Chech whether two lists are equal +/// +/// @param[in] l1 First list to compare. +/// @param[in] l2 Second list to compare. +/// @param[in] ic True if case is to be ignored. +/// @param[in] recursive True when used recursively. +/// +/// @return True if lists are equal, false otherwise. +bool tv_list_equal(list_T *const l1, list_T *const l2, const bool ic, + const bool recursive) + FUNC_ATTR_WARN_UNUSED_RESULT +{ + if (l1 == l2) { + return true; + } + if (l1 == NULL || l2 == NULL) { + return false; + } + if (tv_list_len(l1) != tv_list_len(l2)) { + return false; + } + + listitem_T *item1 = l1->lv_first; + listitem_T *item2 = l2->lv_first; + for (; item1 != NULL && item2 != NULL + ; item1 = item1->li_next, item2 = item2->li_next) { + if (!tv_equal(&item1->li_tv, &item2->li_tv, ic, recursive)) { + return false; + } + } + assert(item1 == NULL && item2 == NULL); + return true; +} + +//{{{2 Indexing/searching + +/// Locate item with a given index in a list and return it +/// +/// @param[in] l List to index. +/// @param[in] n Index. Negative index is counted from the end, -1 is the last +/// item. +/// +/// @return Item at the given index or NULL if `n` is out of range. +listitem_T *tv_list_find(list_T *const l, int n) + FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT +{ + STATIC_ASSERT(sizeof(n) == sizeof(l->lv_idx), + "n and lv_idx sizes do not match"); + if (l == NULL) { + return NULL; + } + + // Negative index is relative to the end. + if (n < 0) { + n = l->lv_len + n; + } + + // Check for index out of range. + if (n < 0 || n >= l->lv_len) { + return NULL; + } + + int idx; + listitem_T *item; + + // When there is a cached index may start search from there. + if (l->lv_idx_item != NULL) { + if (n < l->lv_idx / 2) { + // Closest to the start of the list. + item = l->lv_first; + idx = 0; + } else if (n > (l->lv_idx + l->lv_len) / 2) { + // Closest to the end of the list. + item = l->lv_last; + idx = l->lv_len - 1; + } else { + // Closest to the cached index. + item = l->lv_idx_item; + idx = l->lv_idx; + } + } else { + if (n < l->lv_len / 2) { + // Closest to the start of the list. + item = l->lv_first; + idx = 0; + } else { + // Closest to the end of the list. + item = l->lv_last; + idx = l->lv_len - 1; + } + } + + while (n > idx) { + // Search forward. + item = item->li_next; + idx++; + } + while (n < idx) { + // Search backward. + item = item->li_prev; + idx--; + } + + assert(idx == n); + // Cache the used index. + l->lv_idx = idx; + l->lv_idx_item = item; + + return item; +} + +/// Get list item l[n] as a number +/// +/// @param[in] l List to index. +/// @param[in] n Index in a list. +/// @param[out] ret_error Location where 1 will be saved if index was not +/// found. May be NULL. If everything is OK, +/// `*ret_error` is not touched. +/// +/// @return Integer value at the given index or -1. +varnumber_T tv_list_find_nr(list_T *const l, const int n, bool *const ret_error) + FUNC_ATTR_WARN_UNUSED_RESULT +{ + const listitem_T *const li = tv_list_find(l, n); + if (li == NULL) { + if (ret_error != NULL) { + *ret_error = true; + } + return -1; + } + return tv_get_number_chk(&li->li_tv, ret_error); +} + +/// Get list item l[n] as a string +/// +/// @param[in] l List to index. +/// @param[in] n Index in a list. +/// +/// @return List item string value or NULL in case of error. +const char *tv_list_find_str(list_T *const l, const int n) + FUNC_ATTR_WARN_UNUSED_RESULT +{ + const listitem_T *const li = tv_list_find(l, n); + if (li == NULL) { + emsgf(_(e_listidx), (int64_t)n); + return NULL; + } + return tv_get_string(&li->li_tv); +} + +/// Locate item in a list and return its index +/// +/// @param[in] l List to search. +/// @param[in] item Item to search for. +/// +/// @return Index of an item or -1 if item is not in the list. +long tv_list_idx_of_item(const list_T *const l, const listitem_T *const item) + FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE +{ + if (l == NULL) { + return -1; + } + long idx = 0; + const listitem_T *li; + for (li = l->lv_first; li != NULL && li != item; li = li->li_next) { + idx++; + } + if (li == NULL) { + return -1; + } + return idx; +} + +//{{{1 Dictionaries +//{{{2 Dictionary watchers + +/// Perform all necessary cleanup for a `DictWatcher` instance +/// +/// @param watcher Watcher to free. +static void tv_dict_watcher_free(DictWatcher *watcher) + FUNC_ATTR_NONNULL_ALL +{ + callback_free(&watcher->callback); + xfree(watcher->key_pattern); + xfree(watcher); +} + +/// Add watcher to a dictionary +/// +/// @param[in] dict Dictionary to add watcher to. +/// @param[in] key_pattern Pattern to watch for. +/// @param[in] key_pattern_len Key pattern length. +/// @param callback Function to be called on events. +void tv_dict_watcher_add(dict_T *const dict, const char *const key_pattern, + const size_t key_pattern_len, Callback callback) + FUNC_ATTR_NONNULL_ARG(2) +{ + if (dict == NULL) { + return; + } + DictWatcher *const watcher = xmalloc(sizeof(DictWatcher)); + watcher->key_pattern = xmemdupz(key_pattern, key_pattern_len); + watcher->key_pattern_len = key_pattern_len; + watcher->callback = callback; + watcher->busy = false; + QUEUE_INSERT_TAIL(&dict->watchers, &watcher->node); +} + +/// Check whether two callbacks are equal +/// +/// @param[in] cb1 First callback to check. +/// @param[in] cb2 Second callback to check. +/// +/// @return True if they are equal, false otherwise. +bool tv_callback_equal(const Callback *const cb1, const Callback *const cb2) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ + if (cb1->type != cb2->type) { + return false; + } + switch (cb1->type) { + case kCallbackFuncref: { + return STRCMP(cb1->data.funcref, cb2->data.funcref) == 0; + } + case kCallbackPartial: { + // FIXME: this is inconsistent with tv_equal but is needed for precision + // maybe change dictwatcheradd to return a watcher id instead? + return cb1->data.partial == cb2->data.partial; + } + case kCallbackNone: { + return true; + } + } + assert(false); + return false; +} + +/// Remove watcher from a dictionary +/// +/// @param dict Dictionary to remove watcher from. +/// @param[in] key_pattern Pattern to remove watcher for. +/// @param[in] key_pattern_len Pattern length. +/// @param callback Callback to remove watcher for. +/// +/// @return True on success, false if relevant watcher was not found. +bool tv_dict_watcher_remove(dict_T *const dict, const char *const key_pattern, + const size_t key_pattern_len, + Callback callback) + FUNC_ATTR_NONNULL_ARG(2) +{ + if (dict == NULL) { + return false; + } + + QUEUE *w = NULL; + DictWatcher *watcher = NULL; + bool matched = false; + QUEUE_FOREACH(w, &dict->watchers) { + watcher = tv_dict_watcher_node_data(w); + if (tv_callback_equal(&watcher->callback, &callback) + && watcher->key_pattern_len == key_pattern_len + && memcmp(watcher->key_pattern, key_pattern, key_pattern_len) == 0) { + matched = true; + break; + } + } + + if (!matched) { + return false; + } + + QUEUE_REMOVE(w); + tv_dict_watcher_free(watcher); + return true; +} + +/// Test if `key` matches with with `watcher->key_pattern` +/// +/// @param[in] watcher Watcher to check key pattern from. +/// @param[in] key Key to check. +/// +/// @return true if key matches, false otherwise. +static bool tv_dict_watcher_matches(DictWatcher *watcher, const char *const key) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE +{ + // 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. + const size_t len = watcher->key_pattern_len; + if (len && watcher->key_pattern[len - 1] == '*') { + return strncmp(key, watcher->key_pattern, len - 1) == 0; + } else { + return strcmp(key, watcher->key_pattern) == 0; + } +} + +/// Send a change notification to all dictionary watchers that match given key +/// +/// @param[in] dict Dictionary which was modified. +/// @param[in] key Key which was modified. +/// @param[in] newtv New key value. +/// @param[in] oldtv Old key value. +void tv_dict_watcher_notify(dict_T *const dict, const char *const key, + typval_T *const newtv, typval_T *const oldtv) + FUNC_ATTR_NONNULL_ARG(1, 2) +{ + typval_T argv[3]; + + argv[0].v_type = VAR_DICT; + argv[0].v_lock = VAR_UNLOCKED; + argv[0].vval.v_dict = dict; + argv[1].v_type = VAR_STRING; + argv[1].v_lock = VAR_UNLOCKED; + argv[1].vval.v_string = (char_u *)xstrdup(key); + argv[2].v_type = VAR_DICT; + argv[2].v_lock = VAR_UNLOCKED; + argv[2].vval.v_dict = tv_dict_alloc(); + argv[2].vval.v_dict->dv_refcount++; + + if (newtv) { + dictitem_T *const v = tv_dict_item_alloc_len(S_LEN("new")); + tv_copy(newtv, &v->di_tv); + tv_dict_add(argv[2].vval.v_dict, v); + } + + if (oldtv) { + dictitem_T *const v = tv_dict_item_alloc_len(S_LEN("old")); + tv_copy(oldtv, &v->di_tv); + tv_dict_add(argv[2].vval.v_dict, v); + } + + typval_T rettv; + + QUEUE *w; + QUEUE_FOREACH(w, &dict->watchers) { + DictWatcher *watcher = tv_dict_watcher_node_data(w); + if (!watcher->busy && tv_dict_watcher_matches(watcher, key)) { + rettv = TV_INITIAL_VALUE; + watcher->busy = true; + callback_call(&watcher->callback, 3, argv, &rettv); + watcher->busy = false; + tv_clear(&rettv); + } + } + + for (size_t i = 1; i < ARRAY_SIZE(argv); i++) { + tv_clear(argv + i); + } +} + +//{{{2 Dictionary item + +/// Allocate a dictionary item +/// +/// @note that the value of the item (->di_tv) still needs to be initialized. +/// +/// @param[in] key Key, is copied to the new item. +/// @param[in] key_len Key length. +/// +/// @return [allocated] new dictionary item. +dictitem_T *tv_dict_item_alloc_len(const char *const key, const size_t key_len) + FUNC_ATTR_NONNULL_RET FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT + FUNC_ATTR_MALLOC +{ + dictitem_T *const di = xmalloc(offsetof(dictitem_T, di_key) + key_len + 1); + memcpy(di->di_key, key, key_len); + di->di_key[key_len] = NUL; + di->di_flags = DI_FLAGS_ALLOC; + return di; +} + +/// Allocate a dictionary item +/// +/// @note that the value of the item (->di_tv) still needs to be initialized. +/// +/// @param[in] key Key, is copied to the new item. +/// +/// @return [allocated] new dictionary item. +dictitem_T *tv_dict_item_alloc(const char *const key) + FUNC_ATTR_NONNULL_RET FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT + FUNC_ATTR_MALLOC +{ + return tv_dict_item_alloc_len(key, strlen(key)); +} + +/// Free a dictionary item, also clearing the value +/// +/// @param item Item to free. +void tv_dict_item_free(dictitem_T *const item) + FUNC_ATTR_NONNULL_ALL +{ + tv_clear(&item->di_tv); + if (item->di_flags & DI_FLAGS_ALLOC) { + xfree(item); + } +} + +/// Make a copy of a dictionary item +/// +/// @param[in] di Item to copy. +/// +/// @return [allocated] new dictionary item. +static dictitem_T *tv_dict_item_copy(dictitem_T *const di) + FUNC_ATTR_NONNULL_RET FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ + dictitem_T *const new_di = tv_dict_item_alloc((const char *)di->di_key); + tv_copy(&di->di_tv, &new_di->di_tv); + return new_di; +} + +/// Remove item from dictionary and free it +/// +/// @param dict Dictionary to remove item from. +/// @param item Item to remove. +void tv_dict_item_remove(dict_T *const dict, dictitem_T *const item) + FUNC_ATTR_NONNULL_ALL +{ + hashitem_T *const hi = hash_find(&dict->dv_hashtab, item->di_key); + if (HASHITEM_EMPTY(hi)) { + emsgf(_(e_intern2), "tv_dict_item_remove()"); + } else { + hash_remove(&dict->dv_hashtab, hi); + } + tv_dict_item_free(item); +} + +//{{{2 Alloc/free + +/// Allocate an empty dictionary +/// +/// @return [allocated] new dictionary. +dict_T *tv_dict_alloc(void) + FUNC_ATTR_NONNULL_RET FUNC_ATTR_WARN_UNUSED_RESULT +{ + dict_T *const d = xmalloc(sizeof(dict_T)); + + // Add the dict to the list of dicts for garbage collection. + if (gc_first_dict != NULL) { + gc_first_dict->dv_used_prev = d; + } + d->dv_used_next = gc_first_dict; + d->dv_used_prev = NULL; + gc_first_dict = d; + + hash_init(&d->dv_hashtab); + d->dv_lock = VAR_UNLOCKED; + d->dv_scope = VAR_NO_SCOPE; + d->dv_refcount = 0; + d->dv_copyID = 0; + QUEUE_INIT(&d->watchers); + + return d; +} + +/// Free items contained in a dictionary +/// +/// @param[in,out] d Dictionary to clear. +void tv_dict_free_contents(dict_T *const d) + FUNC_ATTR_NONNULL_ALL +{ + // Lock the hashtab, we don't want it to resize while freeing items. + hash_lock(&d->dv_hashtab); + assert(d->dv_hashtab.ht_locked > 0); + HASHTAB_ITER(&d->dv_hashtab, hi, { + // Remove the item before deleting it, just in case there is + // something recursive causing trouble. + dictitem_T *const di = TV_DICT_HI2DI(hi); + hash_remove(&d->dv_hashtab, hi); + tv_dict_item_free(di); + }); + + while (!QUEUE_EMPTY(&d->watchers)) { + QUEUE *w = QUEUE_HEAD(&d->watchers); + QUEUE_REMOVE(w); + DictWatcher *watcher = tv_dict_watcher_node_data(w); + tv_dict_watcher_free(watcher); + } + + hash_clear(&d->dv_hashtab); + d->dv_hashtab.ht_locked--; + hash_init(&d->dv_hashtab); +} + +/// Free a dictionary itself, ignoring items it contains +/// +/// Ignores the reference count. +/// +/// @param[in,out] d Dictionary to free. +void tv_dict_free_dict(dict_T *const d) + FUNC_ATTR_NONNULL_ALL +{ + // Remove the dict from the list of dicts for garbage collection. + if (d->dv_used_prev == NULL) { + gc_first_dict = d->dv_used_next; + } else { + d->dv_used_prev->dv_used_next = d->dv_used_next; + } + if (d->dv_used_next != NULL) { + d->dv_used_next->dv_used_prev = d->dv_used_prev; + } + + xfree(d); +} + +/// Free a dictionary, including all items it contains +/// +/// Ignores the reference count. +/// +/// @param d Dictionary to free. +void tv_dict_free(dict_T *const d) + FUNC_ATTR_NONNULL_ALL +{ + if (!tv_in_free_unref_items) { + tv_dict_free_contents(d); + tv_dict_free_dict(d); + } +} + + +/// Unreference a dictionary +/// +/// Decrements the reference count and frees dictionary when it becomes zero. +/// +/// @param[in] d Dictionary to operate on. +void tv_dict_unref(dict_T *const d) +{ + if (d != NULL && --d->dv_refcount <= 0) { + tv_dict_free(d); + } +} + +//{{{2 Indexing/searching + +/// Find item in dictionary +/// +/// @param[in] d Dictionary to check. +/// @param[in] key Dictionary key. +/// @param[in] len Key length. If negative, then strlen(key) is used. +/// +/// @return found item or NULL if nothing was found. +dictitem_T *tv_dict_find(const dict_T *const d, const char *const key, + const ptrdiff_t len) + FUNC_ATTR_NONNULL_ARG(2) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT +{ + if (d == NULL) { + return NULL; + } + hashitem_T *const hi = (len < 0 + ? hash_find(&d->dv_hashtab, (const char_u *)key) + : hash_find_len(&d->dv_hashtab, key, (size_t)len)); + if (HASHITEM_EMPTY(hi)) { + return NULL; + } + return TV_DICT_HI2DI(hi); +} + +/// Get a number item from a dictionary +/// +/// Returns 0 if the entry does not exist. +/// +/// @param[in] d Dictionary to get item from. +/// @param[in] key Key to find in dictionary. +/// +/// @return Dictionary item. +varnumber_T tv_dict_get_number(const dict_T *const d, const char *const key) + FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT +{ + dictitem_T *const di = tv_dict_find(d, key, -1); + if (di == NULL) { + return 0; + } + return tv_get_number(&di->di_tv); +} + +/// Get a string item from a dictionary +/// +/// @param[in] d Dictionary to get item from. +/// @param[in] key Dictionary key. +/// @param[in] save If true, returned string will be placed in the allocated +/// memory. +/// +/// @return NULL if key does not exist, empty string in case of type error, +/// string item value otherwise. If returned value is not NULL, it may +/// be allocated depending on `save` argument. +char *tv_dict_get_string(const dict_T *const d, const char *const key, + const bool save) + FUNC_ATTR_WARN_UNUSED_RESULT +{ + static char numbuf[NUMBUFLEN]; + const char *const s = tv_dict_get_string_buf(d, key, numbuf); + if (save && s != NULL) { + return xstrdup(s); + } + return (char *)s; +} + +/// Get a string item from a dictionary +/// +/// @param[in] d Dictionary to get item from. +/// @param[in] key Dictionary key. +/// @param[in] numbuf Buffer for non-string items converted to strings, at +/// least of #NUMBUFLEN length. +/// +/// @return NULL if key does not exist, empty string in case of type error, +/// string item value otherwise. +const char *tv_dict_get_string_buf(const dict_T *const d, const char *const key, + char *const numbuf) + FUNC_ATTR_WARN_UNUSED_RESULT +{ + const dictitem_T *const di = tv_dict_find(d, key, -1); + if (di == NULL) { + return NULL; + } + return tv_get_string_buf(&di->di_tv, numbuf); +} + +/// Get a string item from a dictionary +/// +/// @param[in] d Dictionary to get item from. +/// @param[in] key Dictionary key. +/// @param[in] key_len Key length. +/// @param[in] numbuf Buffer for non-string items converted to strings, at +/// least of #NUMBUFLEN length. +/// @param[in] def Default return when key does not exist. +/// +/// @return `def` when key does not exist, +/// NULL in case of type error, +/// string item value in case of success. +const char *tv_dict_get_string_buf_chk(const dict_T *const d, + const char *const key, + const ptrdiff_t key_len, + char *const numbuf, + const char *const def) + FUNC_ATTR_WARN_UNUSED_RESULT +{ + const dictitem_T *const di = tv_dict_find(d, key, key_len); + if (di == NULL) { + return def; + } + return tv_get_string_buf_chk(&di->di_tv, numbuf); +} + +/// Get a function from a dictionary +/// +/// @param[in] d Dictionary to get callback from. +/// @param[in] key Dictionary key. +/// @param[in] key_len Key length, may be -1 to use strlen(). +/// @param[out] result The address where a pointer to the wanted callback +/// will be left. +/// +/// @return true/false on success/failure. +bool tv_dict_get_callback(dict_T *const d, + const char *const key, const ptrdiff_t key_len, + Callback *const result) + FUNC_ATTR_NONNULL_ARG(2, 4) FUNC_ATTR_WARN_UNUSED_RESULT +{ + result->type = kCallbackNone; + + dictitem_T *const di = tv_dict_find(d, key, key_len); + + if (di == NULL) { + return true; + } + + if (!tv_is_func(di->di_tv) && di->di_tv.v_type != VAR_STRING) { + emsgf(_("E6000: Argument is not a function or function name")); + return false; + } + + typval_T tv; + tv_copy(&di->di_tv, &tv); + set_selfdict(&tv, d); + const bool res = callback_from_typval(result, &tv); + tv_clear(&tv); + return res; +} + +//{{{2 dict_add* + +/// Add item to dictionary +/// +/// @param[out] d Dictionary to add to. +/// @param[in] item Item to add. +/// +/// @return FAIL if key already exists. +int tv_dict_add(dict_T *const d, dictitem_T *const item) + FUNC_ATTR_NONNULL_ALL +{ + return hash_add(&d->dv_hashtab, item->di_key); +} + +/// Add a list entry to dictionary +/// +/// @param[out] d Dictionary to add entry to. +/// @param[in] key Key to add. +/// @param[in] key_len Key length. +/// @param list List to add. Will have reference count incremented. +/// +/// @return OK in case of success, FAIL when key already exists. +int tv_dict_add_list(dict_T *const d, const char *const key, + const size_t key_len, list_T *const list) + FUNC_ATTR_NONNULL_ALL +{ + dictitem_T *const item = tv_dict_item_alloc_len(key, key_len); + + item->di_tv.v_lock = VAR_UNLOCKED; + item->di_tv.v_type = VAR_LIST; + item->di_tv.vval.v_list = list; + list->lv_refcount++; + if (tv_dict_add(d, item) == FAIL) { + tv_dict_item_free(item); + return FAIL; + } + return OK; +} + +/// Add a dictionary entry to dictionary +/// +/// @param[out] d Dictionary to add entry to. +/// @param[in] key Key to add. +/// @param[in] key_len Key length. +/// @param dict Dictionary to add. Will have reference count incremented. +/// +/// @return OK in case of success, FAIL when key already exists. +int tv_dict_add_dict(dict_T *const d, const char *const key, + const size_t key_len, dict_T *const dict) + FUNC_ATTR_NONNULL_ALL +{ + dictitem_T *const item = tv_dict_item_alloc_len(key, key_len); + + item->di_tv.v_lock = VAR_UNLOCKED; + item->di_tv.v_type = VAR_DICT; + item->di_tv.vval.v_dict = dict; + dict->dv_refcount++; + if (tv_dict_add(d, item) == FAIL) { + tv_dict_item_free(item); + return FAIL; + } + return OK; +} + +/// Add a number entry to dictionary +/// +/// @param[out] d Dictionary to add entry to. +/// @param[in] key Key to add. +/// @param[in] key_len Key length. +/// @param[in] nr Number to add. +/// +/// @return OK in case of success, FAIL when key already exists. +int tv_dict_add_nr(dict_T *const d, const char *const key, + const size_t key_len, const varnumber_T nr) +{ + dictitem_T *const item = tv_dict_item_alloc_len(key, key_len); + + item->di_tv.v_lock = VAR_UNLOCKED; + item->di_tv.v_type = VAR_NUMBER; + item->di_tv.vval.v_number = nr; + if (tv_dict_add(d, item) == FAIL) { + tv_dict_item_free(item); + return FAIL; + } + return OK; +} + +/// Add a string entry to dictionary +/// +/// @param[out] d Dictionary to add entry to. +/// @param[in] key Key to add. +/// @param[in] key_len Key length. +/// @param[in] val String to add. +/// +/// @return OK in case of success, FAIL when key already exists. +int tv_dict_add_str(dict_T *const d, + const char *const key, const size_t key_len, + const char *const val) + FUNC_ATTR_NONNULL_ALL +{ + return tv_dict_add_allocated_str(d, key, key_len, xstrdup(val)); +} + +/// Add a string entry to dictionary +/// +/// Unlike tv_dict_add_str() saves val to the new dictionary item in place of +/// creating a new copy. +/// +/// @warning String will be freed even in case addition fails. +/// +/// @param[out] d Dictionary to add entry to. +/// @param[in] key Key to add. +/// @param[in] key_len Key length. +/// @param[in] val String to add. +/// +/// @return OK in case of success, FAIL when key already exists. +int tv_dict_add_allocated_str(dict_T *const d, + const char *const key, const size_t key_len, + char *const val) + FUNC_ATTR_NONNULL_ALL +{ + dictitem_T *const item = tv_dict_item_alloc_len(key, key_len); + + item->di_tv.v_lock = VAR_UNLOCKED; + item->di_tv.v_type = VAR_STRING; + item->di_tv.vval.v_string = (char_u *)val; + if (tv_dict_add(d, item) == FAIL) { + tv_dict_item_free(item); + return FAIL; + } + return OK; +} + +//{{{2 Operations on the whole dict + +/// Clear all the keys of a Dictionary. "d" remains a valid empty Dictionary. +/// +/// @param d The Dictionary to clear +void tv_dict_clear(dict_T *const d) + FUNC_ATTR_NONNULL_ALL +{ + hash_lock(&d->dv_hashtab); + assert(d->dv_hashtab.ht_locked > 0); + + HASHTAB_ITER(&d->dv_hashtab, hi, { + tv_dict_item_free(TV_DICT_HI2DI(hi)); + hash_remove(&d->dv_hashtab, hi); + }); + + hash_unlock(&d->dv_hashtab); +} + +/// Extend dictionary with items from another dictionary +/// +/// @param d1 Dictionary to extend. +/// @param[in] d2 Dictionary to extend with. +/// @param[in] action "error", "force", "keep": +/// +/// e*, including "error": duplicate key gives an error. +/// f*, including "force": duplicate d2 keys override d1. +/// other, including "keep": duplicate d2 keys ignored. +void tv_dict_extend(dict_T *const d1, dict_T *const d2, + const char *const action) + FUNC_ATTR_NONNULL_ALL +{ + const bool watched = tv_dict_is_watched(d1); + const char *const arg_errmsg = _("extend() argument"); + const size_t arg_errmsg_len = strlen(arg_errmsg); + + TV_DICT_ITER(d2, di2, { + dictitem_T *const di1 = tv_dict_find(d1, (const char *)di2->di_key, -1); + if (d1->dv_scope != VAR_NO_SCOPE) { + // Disallow replacing a builtin function in l: and g:. + // Check the key to be valid when adding to any scope. + if (d1->dv_scope == VAR_DEF_SCOPE + && tv_is_func(di2->di_tv) + && !var_check_func_name((const char *)di2->di_key, di1 == NULL)) { + break; + } + if (!valid_varname((const char *)di2->di_key)) { + break; + } + } + if (di1 == NULL) { + dictitem_T *const new_di = tv_dict_item_copy(di2); + if (tv_dict_add(d1, new_di) == FAIL) { + tv_dict_item_free(new_di); + } else if (watched) { + tv_dict_watcher_notify(d1, (const char *)new_di->di_key, &new_di->di_tv, + NULL); + } + } else if (*action == 'e') { + emsgf(_("E737: Key already exists: %s"), di2->di_key); + break; + } else if (*action == 'f' && di2 != di1) { + typval_T oldtv; + + if (tv_check_lock(di1->di_tv.v_lock, arg_errmsg, arg_errmsg_len) + || var_check_ro(di1->di_flags, arg_errmsg, arg_errmsg_len)) { + break; + } + + if (watched) { + tv_copy(&di1->di_tv, &oldtv); + } + + tv_clear(&di1->di_tv); + tv_copy(&di2->di_tv, &di1->di_tv); + + if (watched) { + tv_dict_watcher_notify(d1, (const char *)di1->di_key, &di1->di_tv, + &oldtv); + tv_clear(&oldtv); + } + } + }); +} + +/// Compare two dictionaries +/// +/// @param[in] d1 First dictionary. +/// @param[in] d2 Second dictionary. +/// @param[in] ic True if case is to be ignored. +/// @param[in] recursive True when used recursively. +bool tv_dict_equal(dict_T *const d1, dict_T *const d2, + const bool ic, const bool recursive) + FUNC_ATTR_WARN_UNUSED_RESULT +{ + if (d1 == d2) { + return true; + } + if (d1 == NULL || d2 == NULL) { + return false; + } + if (tv_dict_len(d1) != tv_dict_len(d2)) { + return false; + } + + TV_DICT_ITER(d1, di1, { + dictitem_T *const di2 = tv_dict_find(d2, (const char *)di1->di_key, -1); + if (di2 == NULL) { + return false; + } + if (!tv_equal(&di1->di_tv, &di2->di_tv, ic, recursive)) { + return false; + } + }); + return true; +} + +/// Make a copy of dictionary +/// +/// @param[in] conv If non-NULL, then all internal strings will be converted. +/// @param[in] orig Original dictionary to copy. +/// @param[in] deep If false, then shallow copy will be done. +/// @param[in] copyID See var_item_copy(). +/// +/// @return Copied dictionary. May be NULL in case original dictionary is NULL +/// or some failure happens. The refcount of the new dictionary is set +/// to 1. +dict_T *tv_dict_copy(const vimconv_T *const conv, + dict_T *const orig, + const bool deep, + const int copyID) +{ + if (orig == NULL) { + return NULL; + } + + dict_T *copy = tv_dict_alloc(); + if (copyID != 0) { + orig->dv_copyID = copyID; + orig->dv_copydict = copy; + } + TV_DICT_ITER(orig, di, { + if (got_int) { + break; + } + dictitem_T *new_di; + if (conv == NULL || conv->vc_type == CONV_NONE) { + new_di = tv_dict_item_alloc((const char *)di->di_key); + } else { + size_t len = STRLEN(di->di_key); + char *const key = (char *)string_convert(conv, di->di_key, &len); + if (key == NULL) { + new_di = tv_dict_item_alloc_len((const char *)di->di_key, len); + } else { + new_di = tv_dict_item_alloc_len(key, len); + xfree(key); + } + } + if (deep) { + if (var_item_copy(conv, &di->di_tv, &new_di->di_tv, deep, + copyID) == FAIL) { + xfree(new_di); + break; + } + } else { + tv_copy(&di->di_tv, &new_di->di_tv); + } + if (tv_dict_add(copy, new_di) == FAIL) { + tv_dict_item_free(new_di); + break; + } + }); + + copy->dv_refcount++; + if (got_int) { + tv_dict_unref(copy); + copy = NULL; + } + + return copy; +} + +/// Set all existing keys in "dict" as read-only. +/// +/// This does not protect against adding new keys to the Dictionary. +/// +/// @param dict The dict whose keys should be frozen. +void tv_dict_set_keys_readonly(dict_T *const dict) + FUNC_ATTR_NONNULL_ALL +{ + TV_DICT_ITER(dict, di, { + di->di_flags |= DI_FLAGS_RO | DI_FLAGS_FIX; + }); +} + +//{{{1 Generic typval operations +//{{{2 Init/alloc/clear +//{{{3 Alloc + +/// Allocate an empty list for a return value +/// +/// Also sets reference count. +/// +/// @param[out] ret_tv Structure where list is saved. +/// +/// @return [allocated] pointer to the created list. +list_T *tv_list_alloc_ret(typval_T *const ret_tv) + FUNC_ATTR_NONNULL_ALL +{ + list_T *const l = tv_list_alloc(); + ret_tv->vval.v_list = l; + ret_tv->v_type = VAR_LIST; + ret_tv->v_lock = VAR_UNLOCKED; + l->lv_refcount++; + return l; +} + +/// Allocate an empty dictionary for a return value +/// +/// Also sets reference count. +/// +/// @param[out] ret_tv Structure where dictionary is saved. +void tv_dict_alloc_ret(typval_T *const ret_tv) + FUNC_ATTR_NONNULL_ALL +{ + dict_T *const d = tv_dict_alloc(); + ret_tv->vval.v_dict = d; + ret_tv->v_type = VAR_DICT; + ret_tv->v_lock = VAR_UNLOCKED; + d->dv_refcount++; +} + +//{{{3 Clear +#define TYPVAL_ENCODE_ALLOW_SPECIALS false + +#define TYPVAL_ENCODE_CONV_NIL(tv) \ + do { \ + tv->vval.v_special = kSpecialVarFalse; \ + tv->v_lock = VAR_UNLOCKED; \ + } while (0) + +#define TYPVAL_ENCODE_CONV_BOOL(tv, num) \ + TYPVAL_ENCODE_CONV_NIL(tv) + +#define TYPVAL_ENCODE_CONV_NUMBER(tv, num) \ + do { \ + (void)num; \ + tv->vval.v_number = 0; \ + tv->v_lock = VAR_UNLOCKED; \ + } while (0) + +#define TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER(tv, num) + +#define TYPVAL_ENCODE_CONV_FLOAT(tv, flt) \ + do { \ + tv->vval.v_float = 0; \ + tv->v_lock = VAR_UNLOCKED; \ + } while (0) + +#define TYPVAL_ENCODE_CONV_STRING(tv, buf, len) \ + do { \ + xfree(buf); \ + tv->vval.v_string = NULL; \ + tv->v_lock = VAR_UNLOCKED; \ + } while (0) + +#define TYPVAL_ENCODE_CONV_STR_STRING(tv, buf, len) + +#define TYPVAL_ENCODE_CONV_EXT_STRING(tv, buf, len, type) + +static inline int _nothing_conv_func_start(typval_T *const tv, + char_u *const fun) + FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ARG(1) +{ + tv->v_lock = VAR_UNLOCKED; + if (tv->v_type == VAR_PARTIAL) { + partial_T *const pt_ = tv->vval.v_partial; + if (pt_ != NULL && pt_->pt_refcount > 1) { + pt_->pt_refcount--; + tv->vval.v_partial = NULL; + return OK; + } + } else { + func_unref(fun); + if ((const char *)fun != tv_empty_string) { + xfree(fun); + } + tv->vval.v_string = NULL; + } + return NOTDONE; +} +#define TYPVAL_ENCODE_CONV_FUNC_START(tv, fun) \ + do { \ + if (_nothing_conv_func_start(tv, fun) != NOTDONE) { \ + return OK; \ + } \ + } while (0) + +#define TYPVAL_ENCODE_CONV_FUNC_BEFORE_ARGS(tv, len) +#define TYPVAL_ENCODE_CONV_FUNC_BEFORE_SELF(tv, len) + +static inline void _nothing_conv_func_end(typval_T *const tv, const int copyID) + FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ALL +{ + if (tv->v_type == VAR_PARTIAL) { + partial_T *const pt = tv->vval.v_partial; + if (pt == NULL) { + return; + } + // Dictionary should already be freed by the time. + // If it was not freed then it is a part of the reference cycle. + assert(pt->pt_dict == NULL || pt->pt_dict->dv_copyID == copyID); + pt->pt_dict = NULL; + // As well as all arguments. + pt->pt_argc = 0; + assert(pt->pt_refcount <= 1); + partial_unref(pt); + tv->vval.v_partial = NULL; + assert(tv->v_lock == VAR_UNLOCKED); + } +} +#define TYPVAL_ENCODE_CONV_FUNC_END(tv) _nothing_conv_func_end(tv, copyID) + +#define TYPVAL_ENCODE_CONV_EMPTY_LIST(tv) \ + do { \ + tv_list_unref(tv->vval.v_list); \ + tv->vval.v_list = NULL; \ + tv->v_lock = VAR_UNLOCKED; \ + } while (0) + +#define TYPVAL_ENCODE_CONV_EMPTY_DICT(tv, dict) \ + do { \ + assert((void *)&dict != (void *)&TYPVAL_ENCODE_NODICT_VAR); \ + tv_dict_unref((dict_T *)dict); \ + *((dict_T **)&dict) = NULL; \ + if (tv != NULL) { \ + ((typval_T *)tv)->v_lock = VAR_UNLOCKED; \ + } \ + } while (0) + +static inline int _nothing_conv_real_list_after_start( + typval_T *const tv, MPConvStackVal *const mpsv) + FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_WARN_UNUSED_RESULT +{ + assert(tv != NULL); + tv->v_lock = VAR_UNLOCKED; + if (tv->vval.v_list->lv_refcount > 1) { + tv->vval.v_list->lv_refcount--; + tv->vval.v_list = NULL; + mpsv->data.l.li = NULL; + return OK; + } + return NOTDONE; +} +#define TYPVAL_ENCODE_CONV_LIST_START(tv, len) + +#define TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START(tv, mpsv) \ + do { \ + if (_nothing_conv_real_list_after_start(tv, &mpsv) != NOTDONE) { \ + goto typval_encode_stop_converting_one_item; \ + } \ + } while (0) + +#define TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS(tv) + +static inline void _nothing_conv_list_end(typval_T *const tv) + FUNC_ATTR_ALWAYS_INLINE +{ + if (tv == NULL) { + return; + } + assert(tv->v_type == VAR_LIST); + list_T *const list = tv->vval.v_list; + tv_list_unref(list); + tv->vval.v_list = NULL; +} +#define TYPVAL_ENCODE_CONV_LIST_END(tv) _nothing_conv_list_end(tv) + +static inline int _nothing_conv_real_dict_after_start( + typval_T *const tv, dict_T **const dictp, const void *const nodictvar, + MPConvStackVal *const mpsv) + FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_WARN_UNUSED_RESULT +{ + if (tv != NULL) { + tv->v_lock = VAR_UNLOCKED; + } + if ((const void *)dictp != nodictvar && (*dictp)->dv_refcount > 1) { + (*dictp)->dv_refcount--; + *dictp = NULL; + mpsv->data.d.todo = 0; + return OK; + } + return NOTDONE; +} +#define TYPVAL_ENCODE_CONV_DICT_START(tv, dict, len) + +#define TYPVAL_ENCODE_CONV_REAL_DICT_AFTER_START(tv, dict, mpsv) \ + do { \ + if (_nothing_conv_real_dict_after_start( \ + tv, (dict_T **)&dict, (void *)&TYPVAL_ENCODE_NODICT_VAR, \ + &mpsv) != NOTDONE) { \ + goto typval_encode_stop_converting_one_item; \ + } \ + } while (0) + +#define TYPVAL_ENCODE_SPECIAL_DICT_KEY_CHECK(tv, dict) +#define TYPVAL_ENCODE_CONV_DICT_AFTER_KEY(tv, dict) +#define TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS(tv, dict) + +static inline void _nothing_conv_dict_end(typval_T *const tv, + dict_T **const dictp, + const void *const nodictvar) + FUNC_ATTR_ALWAYS_INLINE +{ + if ((const void *)dictp != nodictvar) { + tv_dict_unref(*dictp); + *dictp = NULL; + } +} +#define TYPVAL_ENCODE_CONV_DICT_END(tv, dict) \ + _nothing_conv_dict_end(tv, (dict_T **)&dict, \ + (void *)&TYPVAL_ENCODE_NODICT_VAR) + +#define TYPVAL_ENCODE_CONV_RECURSE(val, conv_type) + +#define TYPVAL_ENCODE_SCOPE static +#define TYPVAL_ENCODE_NAME nothing +#define TYPVAL_ENCODE_FIRST_ARG_TYPE const void *const +#define TYPVAL_ENCODE_FIRST_ARG_NAME ignored +#define TYPVAL_ENCODE_TRANSLATE_OBJECT_NAME +#include "nvim/eval/typval_encode.c.h" +#undef TYPVAL_ENCODE_SCOPE +#undef TYPVAL_ENCODE_NAME +#undef TYPVAL_ENCODE_FIRST_ARG_TYPE +#undef TYPVAL_ENCODE_FIRST_ARG_NAME +#undef TYPVAL_ENCODE_TRANSLATE_OBJECT_NAME + +#undef TYPVAL_ENCODE_ALLOW_SPECIALS +#undef TYPVAL_ENCODE_CONV_NIL +#undef TYPVAL_ENCODE_CONV_BOOL +#undef TYPVAL_ENCODE_CONV_NUMBER +#undef TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER +#undef TYPVAL_ENCODE_CONV_FLOAT +#undef TYPVAL_ENCODE_CONV_STRING +#undef TYPVAL_ENCODE_CONV_STR_STRING +#undef TYPVAL_ENCODE_CONV_EXT_STRING +#undef TYPVAL_ENCODE_CONV_FUNC_START +#undef TYPVAL_ENCODE_CONV_FUNC_BEFORE_ARGS +#undef TYPVAL_ENCODE_CONV_FUNC_BEFORE_SELF +#undef TYPVAL_ENCODE_CONV_FUNC_END +#undef TYPVAL_ENCODE_CONV_EMPTY_LIST +#undef TYPVAL_ENCODE_CONV_EMPTY_DICT +#undef TYPVAL_ENCODE_CONV_LIST_START +#undef TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START +#undef TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS +#undef TYPVAL_ENCODE_CONV_LIST_END +#undef TYPVAL_ENCODE_CONV_DICT_START +#undef TYPVAL_ENCODE_CONV_REAL_DICT_AFTER_START +#undef TYPVAL_ENCODE_SPECIAL_DICT_KEY_CHECK +#undef TYPVAL_ENCODE_CONV_DICT_AFTER_KEY +#undef TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS +#undef TYPVAL_ENCODE_CONV_DICT_END +#undef TYPVAL_ENCODE_CONV_RECURSE + +/// Free memory for a variable value and set the value to NULL or 0 +/// +/// @param[in,out] tv Value to free. +void tv_clear(typval_T *const tv) +{ + if (tv != NULL && tv->v_type != VAR_UNKNOWN) { + // WARNING: do not translate the string here, gettext is slow and function + // is used *very* often. At the current state encode_vim_to_nothing() does + // not error out and does not use the argument anywhere. + // + // If situation changes and this argument will be used, translate it in the + // place where it is used. + const int evn_ret = encode_vim_to_nothing(NULL, tv, "tv_clear() argument"); + (void)evn_ret; + assert(evn_ret == OK); + } +} + +//{{{3 Free + +/// Free allocated VimL object and value stored inside +/// +/// @param tv Object to free. +void tv_free(typval_T *tv) +{ + if (tv != NULL) { + switch (tv->v_type) { + case VAR_PARTIAL: { + partial_unref(tv->vval.v_partial); + break; + } + case VAR_FUNC: { + func_unref(tv->vval.v_string); + FALLTHROUGH; + } + case VAR_STRING: { + xfree(tv->vval.v_string); + break; + } + case VAR_LIST: { + tv_list_unref(tv->vval.v_list); + break; + } + case VAR_DICT: { + tv_dict_unref(tv->vval.v_dict); + break; + } + case VAR_SPECIAL: + case VAR_NUMBER: + case VAR_FLOAT: + case VAR_UNKNOWN: { + break; + } + } + xfree(tv); + } +} + +//{{{3 Copy + +/// Copy typval from one location to another +/// +/// When needed allocates string or increases reference count. Does not make +/// a copy of a container, but copies its reference! +/// +/// It is OK for `from` and `to` to point to the same location; this is used to +/// make a copy later. +/// +/// @param[in] from Location to copy from. +/// @param[out] to Location to copy to. +void tv_copy(typval_T *const from, typval_T *const to) +{ + to->v_type = from->v_type; + to->v_lock = VAR_UNLOCKED; + memmove(&to->vval, &from->vval, sizeof(to->vval)); + switch (from->v_type) { + case VAR_NUMBER: + case VAR_FLOAT: + case VAR_SPECIAL: { + break; + } + case VAR_STRING: + case VAR_FUNC: { + if (from->vval.v_string != NULL) { + to->vval.v_string = vim_strsave(from->vval.v_string); + if (from->v_type == VAR_FUNC) { + func_ref(to->vval.v_string); + } + } + break; + } + case VAR_PARTIAL: { + if (to->vval.v_partial != NULL) { + to->vval.v_partial->pt_refcount++; + } + break; + } + case VAR_LIST: { + if (from->vval.v_list != NULL) { + to->vval.v_list->lv_refcount++; + } + break; + } + case VAR_DICT: { + if (from->vval.v_dict != NULL) { + to->vval.v_dict->dv_refcount++; + } + break; + } + case VAR_UNKNOWN: { + emsgf(_(e_intern2), "tv_copy(UNKNOWN)"); + break; + } + } +} + +//{{{2 Locks + +/// Lock or unlock an item +/// +/// @param[out] tv Item to (un)lock. +/// @param[in] deep Levels to (un)lock, -1 to (un)lock everything. +/// @param[in] lock True if it is needed to lock an item, false to unlock. +void tv_item_lock(typval_T *const tv, const int deep, const bool lock) + FUNC_ATTR_NONNULL_ALL +{ + // TODO(ZyX-I): Make this not recursive + static int recurse = 0; + + if (recurse >= DICT_MAXNEST) { + emsgf(_("E743: variable nested too deep for (un)lock")); + return; + } + if (deep == 0) { + return; + } + recurse++; + + // lock/unlock the item itself +#define CHANGE_LOCK(lock, var) \ + do { \ + var = ((VarLockStatus[]) { \ + [VAR_UNLOCKED] = (lock ? VAR_LOCKED : VAR_UNLOCKED), \ + [VAR_LOCKED] = (lock ? VAR_LOCKED : VAR_UNLOCKED), \ + [VAR_FIXED] = VAR_FIXED, \ + })[var]; \ + } while (0) + CHANGE_LOCK(lock, tv->v_lock); + + switch (tv->v_type) { + case VAR_LIST: { + list_T *const l = tv->vval.v_list; + if (l != NULL) { + CHANGE_LOCK(lock, l->lv_lock); + if (deep < 0 || deep > 1) { + // Recursive: lock/unlock the items the List contains. + for (listitem_T *li = l->lv_first; li != NULL; li = li->li_next) { + tv_item_lock(&li->li_tv, deep - 1, lock); + } + } + } + break; + } + case VAR_DICT: { + dict_T *const d = tv->vval.v_dict; + if (d != NULL) { + CHANGE_LOCK(lock, d->dv_lock); + if (deep < 0 || deep > 1) { + // recursive: lock/unlock the items the List contains + TV_DICT_ITER(d, di, { + tv_item_lock(&di->di_tv, deep - 1, lock); + }); + } + } + break; + } + case VAR_NUMBER: + case VAR_FLOAT: + case VAR_STRING: + case VAR_FUNC: + case VAR_PARTIAL: + case VAR_SPECIAL: { + break; + } + case VAR_UNKNOWN: { + assert(false); + } + } +#undef CHANGE_LOCK + recurse--; +} + +/// Check whether VimL value is locked itself or refers to a locked container +/// +/// @param[in] tv Value to check. +/// +/// @return True if value is locked, false otherwise. +bool tv_islocked(const typval_T *const tv) + FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL +{ + return ((tv->v_lock == VAR_LOCKED) + || (tv->v_type == VAR_LIST + && tv->vval.v_list != NULL + && (tv->vval.v_list->lv_lock == VAR_LOCKED)) + || (tv->v_type == VAR_DICT + && tv->vval.v_dict != NULL + && (tv->vval.v_dict->dv_lock == VAR_LOCKED))); +} + +/// Return true if typval is locked +/// +/// Also gives an error message when typval is locked. +/// +/// @param[in] lock Lock status. +/// @param[in] name Variable name, used in the error message. +/// @param[in] name_len Variable name length. Use #TV_TRANSLATE to translate +/// variable name and compute the length. Use #TV_CSTRING +/// to compute the length with strlen() without +/// translating. +/// +/// Both #TV_โฆ values are used for optimization purposes: +/// variable name with its length is needed only in case +/// of error, when no error occurs computing them is +/// a waste of CPU resources. This especially applies to +/// gettext. +/// +/// @return true if variable is locked, false otherwise. +bool tv_check_lock(const VarLockStatus lock, const char *name, + size_t name_len) + FUNC_ATTR_WARN_UNUSED_RESULT +{ + const char *error_message = NULL; + switch (lock) { + case VAR_UNLOCKED: { + return false; + } + case VAR_LOCKED: { + error_message = N_("E741: Value is locked: %.*s"); + break; + } + case VAR_FIXED: { + error_message = N_("E742: Cannot change value of %.*s"); + break; + } + } + assert(error_message != NULL); + + if (name == NULL) { + name = _("Unknown"); + name_len = strlen(name); + } else if (name_len == TV_TRANSLATE) { + name = _(name); + name_len = strlen(name); + } else if (name_len == TV_CSTRING) { + name_len = strlen(name); + } + + emsgf(_(error_message), (int)name_len, name); + + return true; +} + +//{{{2 Comparison + +static int tv_equal_recurse_limit; + +/// Compare two VimL values +/// +/// Like "==", but strings and numbers are different, as well as floats and +/// numbers. +/// +/// @warning Too nested structures may be considered equal even if they are not. +/// +/// @param[in] tv1 First value to compare. +/// @param[in] tv2 Second value to compare. +/// @param[in] ic True if case is to be ignored. +/// @param[in] recursive True when used recursively. +/// +/// @return true if values are equal. +bool tv_equal(typval_T *const tv1, typval_T *const tv2, const bool ic, + const bool recursive) + FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL +{ + // TODO(ZyX-I): Make this not recursive + static int recursive_cnt = 0; // Catch recursive loops. + + if (!(tv_is_func(*tv1) && tv_is_func(*tv2)) && tv1->v_type != tv2->v_type) { + return false; + } + + // Catch lists and dicts that have an endless loop by limiting + // recursiveness to a limit. We guess they are equal then. + // A fixed limit has the problem of still taking an awful long time. + // Reduce the limit every time running into it. That should work fine for + // deeply linked structures that are not recursively linked and catch + // recursiveness quickly. + if (!recursive) { + tv_equal_recurse_limit = 1000; + } + if (recursive_cnt >= tv_equal_recurse_limit) { + tv_equal_recurse_limit--; + return true; + } + + switch (tv1->v_type) { + case VAR_LIST: { + recursive_cnt++; + const bool r = tv_list_equal(tv1->vval.v_list, tv2->vval.v_list, ic, + true); + recursive_cnt--; + return r; + } + case VAR_DICT: { + recursive_cnt++; + const bool r = tv_dict_equal(tv1->vval.v_dict, tv2->vval.v_dict, ic, + true); + recursive_cnt--; + return r; + } + case VAR_PARTIAL: + case VAR_FUNC: { + if ((tv1->v_type == VAR_PARTIAL && tv1->vval.v_partial == NULL) + || (tv2->v_type == VAR_PARTIAL && tv2->vval.v_partial == NULL)) { + return false; + } + recursive_cnt++; + const bool r = func_equal(tv1, tv2, ic); + recursive_cnt--; + return r; + } + case VAR_NUMBER: { + return tv1->vval.v_number == tv2->vval.v_number; + } + case VAR_FLOAT: { + return tv1->vval.v_float == tv2->vval.v_float; + } + case VAR_STRING: { + char buf1[NUMBUFLEN]; + char buf2[NUMBUFLEN]; + const char *s1 = tv_get_string_buf(tv1, buf1); + const char *s2 = tv_get_string_buf(tv2, buf2); + return mb_strcmp_ic((bool)ic, s1, s2) == 0; + } + case VAR_SPECIAL: { + return tv1->vval.v_special == tv2->vval.v_special; + } + case VAR_UNKNOWN: { + // VAR_UNKNOWN can be the result of an invalid expression, letโs say it + // does not equal anything, not even self. + return false; + } + } + + assert(false); + return false; +} + +//{{{2 Type checks + +/// Check that given value is a number or string +/// +/// Error messages are compatible with tv_get_number() previously used for the +/// same purpose in buf*() functions. Special values are not accepted (previous +/// behaviour: silently fail to find buffer). +/// +/// @param[in] tv Value to check. +/// +/// @return true if everything is OK, false otherwise. +bool tv_check_str_or_nr(const typval_T *const tv) + FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL +{ + switch (tv->v_type) { + case VAR_NUMBER: + case VAR_STRING: { + return true; + } + case VAR_FLOAT: { + emsgf(_("E805: Expected a Number or a String, Float found")); + return false; + } + case VAR_PARTIAL: + case VAR_FUNC: { + emsgf(_("E703: Expected a Number or a String, Funcref found")); + return false; + } + case VAR_LIST: { + emsgf(_("E745: Expected a Number or a String, List found")); + return false; + } + case VAR_DICT: { + emsgf(_("E728: Expected a Number or a String, Dictionary found")); + return false; + } + case VAR_SPECIAL: { + emsgf(_("E5300: Expected a Number or a String")); + return false; + } + case VAR_UNKNOWN: { + emsgf(_(e_intern2), "tv_check_str_or_nr(UNKNOWN)"); + return false; + } + } + assert(false); + return false; +} + +#define FUNC_ERROR "E703: Using a Funcref as a Number" + +static const char *const num_errors[] = { + [VAR_PARTIAL]=N_(FUNC_ERROR), + [VAR_FUNC]=N_(FUNC_ERROR), + [VAR_LIST]=N_("E745: Using a List as a Number"), + [VAR_DICT]=N_("E728: Using a Dictionary as a Number"), + [VAR_FLOAT]=N_("E805: Using a Float as a Number"), + [VAR_UNKNOWN]=N_("E685: using an invalid value as a Number"), +}; + +#undef FUNC_ERROR + +/// Check that given value is a number or can be converted to it +/// +/// Error messages are compatible with tv_get_number_chk() previously used for +/// the same purpose. +/// +/// @param[in] tv Value to check. +/// +/// @return true if everything is OK, false otherwise. +bool tv_check_num(const typval_T *const tv) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ + switch (tv->v_type) { + case VAR_NUMBER: + case VAR_SPECIAL: + case VAR_STRING: { + return true; + } + case VAR_FUNC: + case VAR_PARTIAL: + case VAR_LIST: + case VAR_DICT: + case VAR_FLOAT: + case VAR_UNKNOWN: { + emsgf(_(num_errors[tv->v_type])); + return false; + } + } + assert(false); + return false; +} + +#define FUNC_ERROR "E729: using Funcref as a String" + +static const char *const str_errors[] = { + [VAR_PARTIAL]=N_(FUNC_ERROR), + [VAR_FUNC]=N_(FUNC_ERROR), + [VAR_LIST]=N_("E730: using List as a String"), + [VAR_DICT]=N_("E731: using Dictionary as a String"), + [VAR_FLOAT]=((const char *)e_float_as_string), + [VAR_UNKNOWN]=N_("E908: using an invalid value as a String"), +}; + +#undef FUNC_ERROR + +/// Check that given value is a string or can be converted to it +/// +/// Error messages are compatible with tv_get_string_chk() previously used for +/// the same purpose. +/// +/// @param[in] tv Value to check. +/// +/// @return true if everything is OK, false otherwise. +bool tv_check_str(const typval_T *const tv) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ + switch (tv->v_type) { + case VAR_NUMBER: + case VAR_SPECIAL: + case VAR_STRING: { + return true; + } + case VAR_PARTIAL: + case VAR_FUNC: + case VAR_LIST: + case VAR_DICT: + case VAR_FLOAT: + case VAR_UNKNOWN: { + emsgf(_(str_errors[tv->v_type])); + return false; + } + } + assert(false); + return false; +} + +//{{{2 Get + +/// Get the number value of a VimL object +/// +/// @note Use tv_get_number_chk() if you need to determine whether there was an +/// error. +/// +/// @param[in] tv Object to get value from. +/// +/// @return Number value: vim_str2nr() output for VAR_STRING objects, value +/// for VAR_NUMBER objects, -1 for other types. +varnumber_T tv_get_number(const typval_T *const tv) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ + bool error = false; + return tv_get_number_chk(tv, &error); +} + +/// Get the number value of a VimL object +/// +/// @param[in] tv Object to get value from. +/// @param[out] ret_error If type error occurred then `true` will be written +/// to this location. Otherwise it is not touched. +/// +/// @note Needs to be initialized to `false` to be +/// useful. +/// +/// @return Number value: vim_str2nr() output for VAR_STRING objects, value +/// for VAR_NUMBER objects, -1 (ret_error == NULL) or 0 (otherwise) for +/// other types. +varnumber_T tv_get_number_chk(const typval_T *const tv, bool *const ret_error) + FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ARG(1) +{ + switch (tv->v_type) { + case VAR_FUNC: + case VAR_PARTIAL: + case VAR_LIST: + case VAR_DICT: + case VAR_FLOAT: { + emsgf(_(num_errors[tv->v_type])); + break; + } + case VAR_NUMBER: { + return tv->vval.v_number; + } + case VAR_STRING: { + varnumber_T n = 0; + if (tv->vval.v_string != NULL) { + vim_str2nr(tv->vval.v_string, NULL, NULL, STR2NR_ALL, &n, NULL, 0); + } + return n; + } + case VAR_SPECIAL: { + switch (tv->vval.v_special) { + case kSpecialVarTrue: { + return 1; + } + case kSpecialVarFalse: + case kSpecialVarNull: { + return 0; + } + } + break; + } + case VAR_UNKNOWN: { + emsgf(_(e_intern2), "tv_get_number(UNKNOWN)"); + break; + } + } + if (ret_error != NULL) { + *ret_error = true; + } + return (ret_error == NULL ? -1 : 0); +} + +/// Get the line number from VimL object +/// +/// @param[in] tv Object to get value from. Is expected to be a number or +/// a special string like ".", "$", โฆ (works with current buffer +/// only). +/// +/// @return Line number or -1 or 0. +linenr_T tv_get_lnum(const typval_T *const tv) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ + linenr_T lnum = (linenr_T)tv_get_number_chk(tv, NULL); + if (lnum == 0) { // No valid number, try using same function as line() does. + int fnum; + pos_T *const fp = var2fpos(tv, true, &fnum); + if (fp != NULL) { + lnum = fp->lnum; + } + } + return lnum; +} + +/// Get the floating-point value of a VimL object +/// +/// Raises an error if object is not number or floating-point. +/// +/// @param[in] tv Object to get value of. +/// +/// @return Floating-point value of the variable or zero. +float_T tv_get_float(const typval_T *const tv) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ + switch (tv->v_type) { + case VAR_NUMBER: { + return (float_T)(tv->vval.v_number); + } + case VAR_FLOAT: { + return tv->vval.v_float; + } + case VAR_PARTIAL: + case VAR_FUNC: { + emsgf(_("E891: Using a Funcref as a Float")); + break; + } + case VAR_STRING: { + emsgf(_("E892: Using a String as a Float")); + break; + } + case VAR_LIST: { + emsgf(_("E893: Using a List as a Float")); + break; + } + case VAR_DICT: { + emsgf(_("E894: Using a Dictionary as a Float")); + break; + } + case VAR_SPECIAL: { + emsgf(_("E907: Using a special value as a Float")); + break; + } + case VAR_UNKNOWN: { + emsgf(_(e_intern2), "tv_get_float(UNKNOWN)"); + break; + } + } + return 0; +} + +/// Get the string value of a VimL object +/// +/// @param[in] tv Object to get value of. +/// @param buf Buffer used to hold numbers and special variables converted to +/// string. When function encounters one of these stringified value +/// will be written to buf and buf will be returned. +/// +/// Buffer must have NUMBUFLEN size. +/// +/// @return Object value if it is VAR_STRING object, number converted to +/// a string for VAR_NUMBER, v: variable name for VAR_SPECIAL or NULL. +const char *tv_get_string_buf_chk(const typval_T *const tv, char *const buf) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ + switch (tv->v_type) { + case VAR_NUMBER: { + snprintf(buf, NUMBUFLEN, "%" PRIdVARNUMBER, tv->vval.v_number); + return buf; + } + case VAR_STRING: { + if (tv->vval.v_string != NULL) { + return (const char *)tv->vval.v_string; + } + return ""; + } + case VAR_SPECIAL: { + STRCPY(buf, encode_special_var_names[tv->vval.v_special]); + return buf; + } + case VAR_PARTIAL: + case VAR_FUNC: + case VAR_LIST: + case VAR_DICT: + case VAR_FLOAT: + case VAR_UNKNOWN: { + emsgf(_(str_errors[tv->v_type])); + return false; + } + } + return NULL; +} + +/// Get the string value of a VimL object +/// +/// @warning For number and special values it uses a single, static buffer. It +/// may be used only once, next call to get_tv_string may reuse it. Use +/// tv_get_string_buf() if you need to use tv_get_string() output after +/// calling it again. +/// +/// @param[in] tv Object to get value of. +/// +/// @return Object value if it is VAR_STRING object, number converted to +/// a string for VAR_NUMBER, v: variable name for VAR_SPECIAL or NULL. +const char *tv_get_string_chk(const typval_T *const tv) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ + static char mybuf[NUMBUFLEN]; + + return tv_get_string_buf_chk(tv, mybuf); +} + +/// Get the string value of a VimL object +/// +/// @warning For number and special values it uses a single, static buffer. It +/// may be used only once, next call to get_tv_string may reuse it. Use +/// tv_get_string_buf() if you need to use tv_get_string() output after +/// calling it again. +/// +/// @note tv_get_string_chk() and tv_get_string_buf_chk() are similar, but +/// return NULL on error. +/// +/// @param[in] tv Object to get value of. +/// +/// @return Object value if it is VAR_STRING object, number converted to +/// a string for VAR_NUMBER, v: variable name for VAR_SPECIAL or empty +/// string. +const char *tv_get_string(const typval_T *const tv) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET FUNC_ATTR_WARN_UNUSED_RESULT +{ + static char mybuf[NUMBUFLEN]; + return tv_get_string_buf((typval_T *)tv, mybuf); +} + +/// Get the string value of a VimL object +/// +/// @note tv_get_string_chk() and tv_get_string_buf_chk() are similar, but +/// return NULL on error. +/// +/// @param[in] tv Object to get value of. +/// @param buf Buffer used to hold numbers and special variables converted to +/// string. When function encounters one of these stringified value +/// will be written to buf and buf will be returned. +/// +/// Buffer must have NUMBUFLEN size. +/// +/// @return Object value if it is VAR_STRING object, number converted to +/// a string for VAR_NUMBER, v: variable name for VAR_SPECIAL or empty +/// string. +const char *tv_get_string_buf(const typval_T *const tv, char *const buf) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET FUNC_ATTR_WARN_UNUSED_RESULT +{ + const char *const res = (const char *)tv_get_string_buf_chk(tv, buf); + + return res != NULL ? res : ""; +} diff --git a/src/nvim/eval/typval.h b/src/nvim/eval/typval.h new file mode 100644 index 0000000000..c44b85644d --- /dev/null +++ b/src/nvim/eval/typval.h @@ -0,0 +1,448 @@ +#ifndef NVIM_EVAL_TYPVAL_H +#define NVIM_EVAL_TYPVAL_H + +#include <inttypes.h> +#include <stddef.h> +#include <stdint.h> +#include <string.h> +#include <stdbool.h> + +#include "nvim/types.h" +#include "nvim/hashtab.h" +#include "nvim/garray.h" +#include "nvim/mbyte.h" +#include "nvim/func_attr.h" +#include "nvim/lib/queue.h" +#include "nvim/profile.h" // for proftime_T +#include "nvim/pos.h" // for linenr_T +#include "nvim/gettext.h" +#include "nvim/message.h" +#include "nvim/macros.h" + +/// Type used for VimL VAR_NUMBER values +typedef int64_t varnumber_T; +typedef uint64_t uvarnumber_T; + +/// Type used for VimL VAR_FLOAT values +typedef double float_T; + +/// Maximal possible value of varnumber_T variable +#define VARNUMBER_MAX INT64_MAX +#define UVARNUMBER_MAX UINT64_MAX + +/// Mimimal possible value of varnumber_T variable +#define VARNUMBER_MIN INT64_MIN + +/// %d printf format specifier for varnumber_T +#define PRIdVARNUMBER PRId64 + +typedef struct listvar_S list_T; +typedef struct dictvar_S dict_T; +typedef struct partial_S partial_T; + +typedef struct ufunc ufunc_T; + +typedef enum { + kCallbackNone = 0, + kCallbackFuncref, + kCallbackPartial, +} CallbackType; + +typedef struct { + union { + char_u *funcref; + partial_T *partial; + } data; + CallbackType type; +} Callback; +#define CALLBACK_NONE ((Callback){ .type = kCallbackNone }) + +/// Structure holding dictionary watcher +typedef struct dict_watcher { + Callback callback; + char *key_pattern; + size_t key_pattern_len; + QUEUE node; + bool busy; // prevent recursion if the dict is changed in the callback +} DictWatcher; + +/// Special variable values +typedef enum { + kSpecialVarFalse, ///< v:false + kSpecialVarTrue, ///< v:true + kSpecialVarNull, ///< v:null +} SpecialVarValue; + +/// Variable lock status for typval_T.v_lock +typedef enum { + VAR_UNLOCKED = 0, ///< Not locked. + VAR_LOCKED = 1, ///< User lock, can be unlocked. + VAR_FIXED = 2, ///< Locked forever. +} VarLockStatus; + +/// VimL variable types, for use in typval_T.v_type +typedef enum { + VAR_UNKNOWN = 0, ///< Unknown (unspecified) value. + VAR_NUMBER, ///< Number, .v_number is used. + VAR_STRING, ///< String, .v_string is used. + VAR_FUNC, ///< Function reference, .v_string is used as function name. + VAR_LIST, ///< List, .v_list is used. + VAR_DICT, ///< Dictionary, .v_dict is used. + VAR_FLOAT, ///< Floating-point value, .v_float is used. + VAR_SPECIAL, ///< Special value (true, false, null), .v_special + ///< is used. + VAR_PARTIAL, ///< Partial, .v_partial is used. +} VarType; + +/// Structure that holds an internal variable value +typedef struct { + VarType v_type; ///< Variable type. + VarLockStatus v_lock; ///< Variable lock status. + union typval_vval_union { + varnumber_T v_number; ///< Number, for VAR_NUMBER. + SpecialVarValue v_special; ///< Special value, for VAR_SPECIAL. + float_T v_float; ///< Floating-point number, for VAR_FLOAT. + char_u *v_string; ///< String, for VAR_STRING and VAR_FUNC, can be NULL. + list_T *v_list; ///< List for VAR_LIST, can be NULL. + dict_T *v_dict; ///< Dictionary for VAR_DICT, can be NULL. + partial_T *v_partial; ///< Closure: function with args. + } vval; ///< Actual value. +} typval_T; + +/// Values for (struct dictvar_S).dv_scope +typedef enum { + VAR_NO_SCOPE = 0, ///< Not a scope dictionary. + VAR_SCOPE = 1, ///< Scope dictionary which requires prefix (a:, v:, โฆ). + VAR_DEF_SCOPE = 2, ///< Scope dictionary which may be accessed without prefix + ///< (l:, g:). +} ScopeType; + +/// Structure to hold an item of a list +typedef struct listitem_S listitem_T; + +struct listitem_S { + listitem_T *li_next; ///< Next item in list. + listitem_T *li_prev; ///< Previous item in list. + typval_T li_tv; ///< Item value. +}; + +/// Structure used by those that are using an item in a list +typedef struct listwatch_S listwatch_T; + +struct listwatch_S { + listitem_T *lw_item; ///< Item being watched. + listwatch_T *lw_next; ///< Next watcher. +}; + +/// Structure to hold info about a list +struct listvar_S { + listitem_T *lv_first; ///< First item, NULL if none. + listitem_T *lv_last; ///< Last item, NULL if none. + int lv_refcount; ///< Reference count. + int lv_len; ///< Number of items. + listwatch_T *lv_watch; ///< First watcher, NULL if none. + int lv_idx; ///< Index of a cached item, used for optimising repeated l[idx]. + listitem_T *lv_idx_item; ///< When not NULL item at index "lv_idx". + int lv_copyID; ///< ID used by deepcopy(). + list_T *lv_copylist; ///< Copied list used by deepcopy(). + VarLockStatus lv_lock; ///< Zero, VAR_LOCKED, VAR_FIXED. + list_T *lv_used_next; ///< next list in used lists list. + list_T *lv_used_prev; ///< Previous list in used lists list. +}; + +// Static list with 10 items. Use init_static_list() to initialize. +typedef struct { + list_T sl_list; // must be first + listitem_T sl_items[10]; +} staticList10_T; + +// Structure to hold an item of a Dictionary. +// Also used for a variable. +// The key is copied into "di_key" to avoid an extra alloc/free for it. +struct dictitem_S { + typval_T di_tv; ///< type and value of the variable + char_u di_flags; ///< flags (only used for variable) + char_u di_key[1]; ///< key (actually longer!) +}; + +#define TV_DICTITEM_STRUCT(KEY_LEN) \ + struct { \ + typval_T di_tv; /* Structure that holds scope dictionary itself. */ \ + uint8_t di_flags; /* Flags. */ \ + char_u di_key[KEY_LEN]; /* Key value. */ \ + } + +/// Structure to hold a scope dictionary +/// +/// @warning Must be compatible with dictitem_T. +/// +/// For use in find_var_in_ht to pretend that it found dictionary item when it +/// finds scope dictionary. +typedef TV_DICTITEM_STRUCT(1) ScopeDictDictItem; + +/// Structure to hold an item of a Dictionary +/// +/// @warning Must be compatible with ScopeDictDictItem. +/// +/// Also used for a variable. +typedef TV_DICTITEM_STRUCT() dictitem_T; + +/// Flags for dictitem_T.di_flags +typedef enum { + DI_FLAGS_RO = 1, ///< Read-only value + DI_FLAGS_RO_SBX = 2, ///< Value, read-only in the sandbox + DI_FLAGS_FIX = 4, ///< Fixed value: cannot be :unlet or remove()d. + DI_FLAGS_LOCK = 8, ///< Locked value. + DI_FLAGS_ALLOC = 16, ///< Separately allocated. +} DictItemFlags; + +/// Structure representing a Dictionary +struct dictvar_S { + VarLockStatus dv_lock; ///< Whole dictionary lock status. + ScopeType dv_scope; ///< Non-zero (#VAR_SCOPE, #VAR_DEF_SCOPE) if + ///< dictionary represents a scope (i.e. g:, l: โฆ). + int dv_refcount; ///< Reference count. + int dv_copyID; ///< ID used when recursivery traversing a value. + hashtab_T dv_hashtab; ///< Hashtab containing all items. + dict_T *dv_copydict; ///< Copied dict used by deepcopy(). + dict_T *dv_used_next; ///< Next dictionary in used dictionaries list. + dict_T *dv_used_prev; ///< Previous dictionary in used dictionaries list. + QUEUE watchers; ///< Dictionary key watchers set by user code. +}; + +/// Type used for script ID +typedef int scid_T; +/// Format argument for scid_T +#define PRIdSCID "d" + +// Structure to hold info for a function that is currently being executed. +typedef struct funccall_S funccall_T; + +/// Structure to hold info for a user function. +struct ufunc { + int uf_varargs; ///< variable nr of arguments + int uf_flags; + int uf_calls; ///< nr of active calls + bool uf_cleared; ///< func_clear() was already called + 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; ///< reference count, see func_name_refcount() + funccall_T *uf_scoped; ///< l: local variables for closure + char_u uf_name[1]; ///< name of function (actually longer); can + ///< start with <SNR>123_ (<SNR> is K_SPECIAL + ///< KS_EXTRA KE_SNR) +}; + +/// Maximum number of function arguments +#define MAX_FUNC_ARGS 20 + +struct partial_S { + int pt_refcount; ///< Reference count. + char_u *pt_name; ///< Function name; when NULL use pt_func->name. + ufunc_T *pt_func; ///< Function pointer; when NULL lookup function with + ///< pt_name. + bool pt_auto; ///< When true the partial was created by using dict.member + ///< in handle_subscript(). + int pt_argc; ///< Number of arguments. + typval_T *pt_argv; ///< Arguments in allocated array. + dict_T *pt_dict; ///< Dict for "self". +}; + +/// Structure used for explicit stack while garbage collecting hash tables +typedef struct ht_stack_S { + hashtab_T *ht; + struct ht_stack_S *prev; +} ht_stack_T; + +/// Structure used for explicit stack while garbage collecting lists +typedef struct list_stack_S { + list_T *list; + struct list_stack_S *prev; +} list_stack_T; + +// In a hashtab item "hi_key" points to "di_key" in a dictitem. +// This avoids adding a pointer to the hashtab item. + +/// Convert a hashitem pointer to a dictitem pointer +#define TV_DICT_HI2DI(hi) \ + ((dictitem_T *)((hi)->hi_key - offsetof(dictitem_T, di_key))) + +static inline long tv_list_len(const list_T *const l) + REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT; + +/// Get the number of items in a list +/// +/// @param[in] l List to check. +static inline long tv_list_len(const list_T *const l) +{ + if (l == NULL) { + return 0; + } + return l->lv_len; +} + +static inline long tv_dict_len(const dict_T *const d) + REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT; + +/// Get the number of items in a Dictionary +/// +/// @param[in] d Dictionary to check. +static inline long tv_dict_len(const dict_T *const d) +{ + if (d == NULL) { + return 0L; + } + return (long)d->dv_hashtab.ht_used; +} + +static inline bool tv_dict_is_watched(const dict_T *const d) + REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT; + +/// Check if dictionary is watched +/// +/// @param[in] d Dictionary to check. +/// +/// @return true if there is at least one watcher. +static inline bool tv_dict_is_watched(const dict_T *const d) +{ + return d && !QUEUE_EMPTY(&d->watchers); +} + +/// Initialize VimL object +/// +/// Initializes to unlocked VAR_UNKNOWN object. +/// +/// @param[out] tv Object to initialize. +static inline void tv_init(typval_T *const tv) +{ + if (tv != NULL) { + memset(tv, 0, sizeof(*tv)); + } +} + +#define TV_INITIAL_VALUE \ + ((typval_T) { \ + .v_type = VAR_UNKNOWN, \ + .v_lock = VAR_UNLOCKED, \ + }) + +/// Empty string +/// +/// Needed for hack which allows not allocating empty string and still not +/// crashing when freeing it. +extern const char *const tv_empty_string; + +/// Specifies that free_unref_items() function has (not) been entered +extern bool tv_in_free_unref_items; + +/// Iterate over a dictionary +/// +/// @param[in] d Dictionary to iterate over. +/// @param di Name of the variable with current dictitem_T entry. +/// @param code Cycle body. +#define TV_DICT_ITER(d, di, code) \ + HASHTAB_ITER(&(d)->dv_hashtab, di##hi_, { \ + { \ + dictitem_T *const di = TV_DICT_HI2DI(di##hi_); \ + { \ + code \ + } \ + } \ + }) + +static inline bool tv_get_float_chk(const typval_T *const tv, + float_T *const ret_f) + REAL_FATTR_NONNULL_ALL REAL_FATTR_WARN_UNUSED_RESULT; + +// FIXME circular dependency, cannot import message.h. +bool emsgf(const char *const fmt, ...); + +/// Get the float value +/// +/// Raises an error if object is not number or floating-point. +/// +/// @param[in] tv VimL object to get value from. +/// @param[out] ret_f Location where resulting float is stored. +/// +/// @return true in case of success, false if tv is not a number or float. +static inline bool tv_get_float_chk(const typval_T *const tv, + float_T *const ret_f) +{ + if (tv->v_type == VAR_FLOAT) { + *ret_f = tv->vval.v_float; + return true; + } + if (tv->v_type == VAR_NUMBER) { + *ret_f = (float_T)tv->vval.v_number; + return true; + } + emsgf(_("E808: Number or Float required")); + return false; +} + +static inline DictWatcher *tv_dict_watcher_node_data(QUEUE *q) + REAL_FATTR_NONNULL_ALL REAL_FATTR_NONNULL_RET REAL_FATTR_PURE + REAL_FATTR_WARN_UNUSED_RESULT REAL_FATTR_ALWAYS_INLINE; + +/// Compute the `DictWatcher` address from a QUEUE node. +/// +/// This only exists for .asan-blacklist (ASAN doesn't handle QUEUE_DATA pointer +/// arithmetic). +static inline DictWatcher *tv_dict_watcher_node_data(QUEUE *q) +{ + return QUEUE_DATA(q, DictWatcher, node); +} + +static inline bool tv_is_func(const typval_T tv) + FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_CONST; + +/// Check whether given typval_T contains a function +/// +/// That is, whether it contains VAR_FUNC or VAR_PARTIAL. +/// +/// @param[in] tv Typval to check. +/// +/// @return True if it is a function or a partial, false otherwise. +static inline bool tv_is_func(const typval_T tv) +{ + return tv.v_type == VAR_FUNC || tv.v_type == VAR_PARTIAL; +} + +/// Specify that argument needs to be translated +/// +/// Used for size_t length arguments to avoid calling gettext() and strlen() +/// unless needed. +#define TV_TRANSLATE (SIZE_MAX) + +/// Specify that argument is a NUL-terminated C string +/// +/// Used for size_t length arguments to avoid calling strlen() unless needed. +#define TV_CSTRING (SIZE_MAX - 1) + +#ifdef UNIT_TESTING +// Do not use enum constants, see commit message. +EXTERN const size_t kTVCstring INIT(= TV_CSTRING); +EXTERN const size_t kTVTranslate INIT(= TV_TRANSLATE); +#endif + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "eval/typval.h.generated.h" +#endif +#endif // NVIM_EVAL_TYPVAL_H diff --git a/src/nvim/eval/typval_encode.c.h b/src/nvim/eval/typval_encode.c.h index 365eb2dd77..a93ad2dbba 100644 --- a/src/nvim/eval/typval_encode.c.h +++ b/src/nvim/eval/typval_encode.c.h @@ -233,16 +233,12 @@ /// /// This name will only be used by one of the above macros which are defined by /// the caller. Functions defined here do not use first argument directly. -#ifndef NVIM_EVAL_TYPVAL_ENCODE_C_H -#define NVIM_EVAL_TYPVAL_ENCODE_C_H -#undef NVIM_EVAL_TYPVAL_ENCODE_C_H - #include <stddef.h> #include <inttypes.h> #include <assert.h> #include "nvim/lib/kvec.h" -#include "nvim/eval_defs.h" +#include "nvim/eval/typval.h" #include "nvim/eval/encode.h" #include "nvim/func_attr.h" #include "nvim/eval/typval_encode.h" @@ -344,10 +340,11 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE( case VAR_PARTIAL: { partial_T *const pt = tv->vval.v_partial; (void)pt; - TYPVAL_ENCODE_CONV_FUNC_START(tv, (pt == NULL ? NULL : pt->pt_name)); + TYPVAL_ENCODE_CONV_FUNC_START(tv, (pt == NULL ? NULL : partial_name(pt))); _mp_push(*mpstack, ((MPConvStackVal) { .type = kMPConvPartial, .tv = tv, + .saved_copyID = copyID - 1, .data = { .p = { .stage = kMPConvPartialArgs, @@ -362,12 +359,15 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE( TYPVAL_ENCODE_CONV_EMPTY_LIST(tv); break; } + const int saved_copyID = tv->vval.v_list->lv_copyID; _TYPVAL_ENCODE_DO_CHECK_SELF_REFERENCE(tv->vval.v_list, lv_copyID, copyID, kMPConvList); TYPVAL_ENCODE_CONV_LIST_START(tv, tv->vval.v_list->lv_len); + assert(saved_copyID != copyID && saved_copyID != copyID - 1); _mp_push(*mpstack, ((MPConvStackVal) { .type = kMPConvList, .tv = tv, + .saved_copyID = saved_copyID, .data = { .l = { .list = tv->vval.v_list, @@ -402,11 +402,11 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE( const dictitem_T *val_di; if (TYPVAL_ENCODE_ALLOW_SPECIALS && tv->vval.v_dict->dv_hashtab.ht_used == 2 - && (type_di = dict_find((dict_T *)tv->vval.v_dict, - (char_u *)"_TYPE", -1)) != NULL + && (type_di = tv_dict_find((dict_T *)tv->vval.v_dict, + S_LEN("_TYPE"))) != NULL && type_di->di_tv.v_type == VAR_LIST - && (val_di = dict_find((dict_T *)tv->vval.v_dict, - (char_u *)"_VAL", -1)) != NULL) { + && (val_di = tv_dict_find((dict_T *)tv->vval.v_dict, + S_LEN("_VAL"))) != NULL) { size_t i; for (i = 0; i < ARRAY_SIZE(eval_msgpack_type_lists); i++) { if (type_di->di_tv.vval.v_list == eval_msgpack_type_lists[i]) { @@ -485,7 +485,7 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE( } if (is_string) { TYPVAL_ENCODE_CONV_STR_STRING(tv, buf, len); - } else { + } else { // -V523 TYPVAL_ENCODE_CONV_STRING(tv, buf, len); } xfree(buf); @@ -495,14 +495,17 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE( if (val_di->di_tv.v_type != VAR_LIST) { goto _convert_one_value_regular_dict; } + const int saved_copyID = val_di->di_tv.vval.v_list->lv_copyID; _TYPVAL_ENCODE_DO_CHECK_SELF_REFERENCE(val_di->di_tv.vval.v_list, lv_copyID, copyID, kMPConvList); TYPVAL_ENCODE_CONV_LIST_START(tv, val_di->di_tv.vval.v_list->lv_len); + assert(saved_copyID != copyID && saved_copyID != copyID - 1); _mp_push(*mpstack, ((MPConvStackVal) { .tv = tv, .type = kMPConvList, + .saved_copyID = saved_copyID, .data = { .l = { .list = val_di->di_tv.vval.v_list, @@ -528,13 +531,16 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE( goto _convert_one_value_regular_dict; } } + const int saved_copyID = val_di->di_tv.vval.v_list->lv_copyID; _TYPVAL_ENCODE_DO_CHECK_SELF_REFERENCE(val_list, lv_copyID, copyID, kMPConvPairs); TYPVAL_ENCODE_CONV_DICT_START(tv, TYPVAL_ENCODE_NODICT_VAR, val_list->lv_len); + assert(saved_copyID != copyID && saved_copyID != copyID - 1); _mp_push(*mpstack, ((MPConvStackVal) { .tv = tv, .type = kMPConvPairs, + .saved_copyID = saved_copyID, .data = { .l = { .list = val_list, @@ -569,14 +575,17 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE( } break; } -_convert_one_value_regular_dict: +_convert_one_value_regular_dict: {} + const int saved_copyID = tv->vval.v_dict->dv_copyID; _TYPVAL_ENCODE_DO_CHECK_SELF_REFERENCE(tv->vval.v_dict, dv_copyID, copyID, kMPConvDict); TYPVAL_ENCODE_CONV_DICT_START(tv, tv->vval.v_dict, tv->vval.v_dict->dv_hashtab.ht_used); + assert(saved_copyID != copyID && saved_copyID != copyID - 1); _mp_push(*mpstack, ((MPConvStackVal) { .tv = tv, .type = kMPConvDict, + .saved_copyID = saved_copyID, .data = { .d = { .dict = tv->vval.v_dict, @@ -598,7 +607,7 @@ _convert_one_value_regular_dict: typval_encode_stop_converting_one_item: return OK; // Prevent โunused labelโ warnings. - goto typval_encode_stop_converting_one_item; + goto typval_encode_stop_converting_one_item; // -V779 } TYPVAL_ENCODE_SCOPE int _TYPVAL_ENCODE_ENCODE( @@ -638,7 +647,7 @@ typval_encode_stop_converting_one_item: case kMPConvDict: { if (!cur_mpsv->data.d.todo) { (void)_mp_pop(mpstack); - cur_mpsv->data.d.dict->dv_copyID = copyID - 1; + cur_mpsv->data.d.dict->dv_copyID = cur_mpsv->saved_copyID; TYPVAL_ENCODE_CONV_DICT_END(cur_mpsv->tv, *cur_mpsv->data.d.dictp); continue; } else if (cur_mpsv->data.d.todo @@ -649,7 +658,7 @@ typval_encode_stop_converting_one_item: while (HASHITEM_EMPTY(cur_mpsv->data.d.hi)) { cur_mpsv->data.d.hi++; } - dictitem_T *const di = HI2DI(cur_mpsv->data.d.hi); + dictitem_T *const di = TV_DICT_HI2DI(cur_mpsv->data.d.hi); cur_mpsv->data.d.todo--; cur_mpsv->data.d.hi++; TYPVAL_ENCODE_CONV_STR_STRING(NULL, &di->di_key[0], @@ -662,7 +671,7 @@ typval_encode_stop_converting_one_item: case kMPConvList: { if (cur_mpsv->data.l.li == NULL) { (void)_mp_pop(mpstack); - cur_mpsv->data.l.list->lv_copyID = copyID - 1; + cur_mpsv->data.l.list->lv_copyID = cur_mpsv->saved_copyID; TYPVAL_ENCODE_CONV_LIST_END(cur_mpsv->tv); continue; } else if (cur_mpsv->data.l.li != cur_mpsv->data.l.list->lv_first) { @@ -675,7 +684,7 @@ typval_encode_stop_converting_one_item: case kMPConvPairs: { if (cur_mpsv->data.l.li == NULL) { (void)_mp_pop(mpstack); - cur_mpsv->data.l.list->lv_copyID = copyID - 1; + cur_mpsv->data.l.list->lv_copyID = cur_mpsv->saved_copyID; TYPVAL_ENCODE_CONV_DICT_END(cur_mpsv->tv, TYPVAL_ENCODE_NODICT_VAR); continue; } else if (cur_mpsv->data.l.li != cur_mpsv->data.l.list->lv_first) { @@ -711,6 +720,7 @@ typval_encode_stop_converting_one_item: _mp_push(mpstack, ((MPConvStackVal) { .type = kMPConvPartialList, .tv = NULL, + .saved_copyID = copyID - 1, .data = { .a = { .arg = pt->pt_argv, @@ -731,6 +741,7 @@ typval_encode_stop_converting_one_item: TYPVAL_ENCODE_CONV_EMPTY_DICT(NULL, pt->pt_dict); continue; } + const int saved_copyID = dict->dv_copyID; const int te_csr_ret = _TYPVAL_ENCODE_CHECK_SELF_REFERENCE( TYPVAL_ENCODE_FIRST_ARG_NAME, dict, &dict->dv_copyID, &mpstack, copyID, kMPConvDict, @@ -744,9 +755,11 @@ typval_encode_stop_converting_one_item: } TYPVAL_ENCODE_CONV_DICT_START(NULL, pt->pt_dict, dict->dv_hashtab.ht_used); + assert(saved_copyID != copyID && saved_copyID != copyID - 1); _mp_push(mpstack, ((MPConvStackVal) { .type = kMPConvDict, .tv = NULL, + .saved_copyID = saved_copyID, .data = { .d = { .dict = dict, @@ -797,6 +810,5 @@ encode_vim_to__error_ret: _mp_destroy(mpstack); return FAIL; // Prevent โunused labelโ warnings. - goto typval_encode_stop_converting_one_item; + goto typval_encode_stop_converting_one_item; // -V779 } -#endif // NVIM_EVAL_TYPVAL_ENCODE_C_H diff --git a/src/nvim/eval/typval_encode.h b/src/nvim/eval/typval_encode.h index ba325b8f55..3475f6d8b3 100644 --- a/src/nvim/eval/typval_encode.h +++ b/src/nvim/eval/typval_encode.h @@ -11,7 +11,7 @@ #include <assert.h> #include "nvim/lib/kvec.h" -#include "nvim/eval_defs.h" +#include "nvim/eval/typval.h" #include "nvim/func_attr.h" /// Type of the stack entry @@ -34,6 +34,7 @@ typedef enum { typedef struct { MPConvStackValType type; ///< Type of the stack entry. typval_T *tv; ///< Currently converted typval_T. + int saved_copyID; ///< copyID item used to have. union { struct { dict_T *dict; ///< Currently converted dictionary. diff --git a/src/nvim/eval_defs.h b/src/nvim/eval_defs.h deleted file mode 100644 index f478d19ca1..0000000000 --- a/src/nvim/eval_defs.h +++ /dev/null @@ -1,198 +0,0 @@ -#ifndef NVIM_EVAL_DEFS_H -#define NVIM_EVAL_DEFS_H - -#include <limits.h> -#include <stddef.h> - -#include "nvim/hashtab.h" -#include "nvim/lib/queue.h" - -typedef int varnumber_T; -typedef double float_T; - -#define VARNUMBER_MAX INT_MAX -#define VARNUMBER_MIN INT_MIN - -typedef struct listvar_S list_T; -typedef struct dictvar_S dict_T; -typedef struct partial_S partial_T; - -/// Special variable values -typedef enum { - kSpecialVarFalse, ///< v:false - kSpecialVarTrue, ///< v:true - kSpecialVarNull, ///< v:null -} SpecialVarValue; - -/// Variable lock status for typval_T.v_lock -typedef enum { - VAR_UNLOCKED = 0, ///< Not locked. - VAR_LOCKED, ///< User lock, can be unlocked. - VAR_FIXED, ///< Locked forever. -} VarLockStatus; - -/// VimL variable types, for use in typval_T.v_type -typedef enum { - VAR_UNKNOWN = 0, ///< Unknown (unspecified) value. - VAR_NUMBER, ///< Number, .v_number is used. - VAR_STRING, ///< String, .v_string is used. - VAR_FUNC, ///< Function reference, .v_string is used as function name. - VAR_LIST, ///< List, .v_list is used. - VAR_DICT, ///< Dictionary, .v_dict is used. - VAR_FLOAT, ///< Floating-point value, .v_float is used. - VAR_SPECIAL, ///< Special value (true, false, null), .v_special - ///< is used. - VAR_PARTIAL, ///< Partial, .v_partial is used. -} VarType; - -/// Structure that holds an internal variable value -typedef struct { - VarType v_type; ///< Variable type. - VarLockStatus v_lock; ///< Variable lock status. - union { - varnumber_T v_number; ///< Number, for VAR_NUMBER. - SpecialVarValue v_special; ///< Special value, for VAR_SPECIAL. - float_T v_float; ///< Floating-point number, for VAR_FLOAT. - char_u *v_string; ///< String, for VAR_STRING and VAR_FUNC, can be NULL. - list_T *v_list; ///< List for VAR_LIST, can be NULL. - dict_T *v_dict; ///< Dictionary for VAR_DICT, can be NULL. - partial_T *v_partial; ///< Closure: function with args. - } vval; ///< Actual value. -} typval_T; - -/* Values for "dv_scope". */ -#define VAR_SCOPE 1 /* a:, v:, s:, etc. scope dictionaries */ -#define VAR_DEF_SCOPE 2 /* l:, g: scope dictionaries: here funcrefs are not - allowed to mask existing functions */ - -/* - * Structure to hold an item of a list: an internal variable without a name. - */ -typedef struct listitem_S listitem_T; - -struct listitem_S { - listitem_T *li_next; /* next item in list */ - listitem_T *li_prev; /* previous item in list */ - typval_T li_tv; /* type and value of the variable */ -}; - -/* - * Struct used by those that are using an item in a list. - */ -typedef struct listwatch_S listwatch_T; - -struct listwatch_S { - listitem_T *lw_item; /* item being watched */ - listwatch_T *lw_next; /* next watcher */ -}; - -/* - * Structure to hold info about a list. - */ -struct listvar_S { - listitem_T *lv_first; /* first item, NULL if none */ - listitem_T *lv_last; /* last item, NULL if none */ - int lv_refcount; /* reference count */ - int lv_len; /* number of items */ - listwatch_T *lv_watch; /* first watcher, NULL if none */ - int lv_idx; /* cached index of an item */ - listitem_T *lv_idx_item; /* when not NULL item at index "lv_idx" */ - int lv_copyID; /* ID used by deepcopy() */ - list_T *lv_copylist; /* copied list used by deepcopy() */ - char lv_lock; /* zero, VAR_LOCKED, VAR_FIXED */ - list_T *lv_used_next; /* next list in used lists list */ - list_T *lv_used_prev; /* previous list in used lists list */ -}; - -/* - * Structure to hold an item of a Dictionary. - * Also used for a variable. - * The key is copied into "di_key" to avoid an extra alloc/free for it. - */ -struct dictitem_S { - typval_T di_tv; /* type and value of the variable */ - char_u di_flags; /* flags (only used for variable) */ - char_u di_key[1]; /* key (actually longer!) */ -}; - -typedef struct dictitem_S dictitem_T; - -/// A dictitem with a 16 character key (plus NUL) -struct dictitem16_S { - typval_T di_tv; ///< type and value of the variable - char_u di_flags; ///< flags (only used for variable) - char_u di_key[17]; ///< key -}; - -typedef struct dictitem16_S dictitem16_T; - - -#define DI_FLAGS_RO 1 // "di_flags" value: read-only variable -#define DI_FLAGS_RO_SBX 2 // "di_flags" value: read-only in the sandbox -#define DI_FLAGS_FIX 4 // "di_flags" value: fixed: no :unlet or remove() -#define DI_FLAGS_LOCK 8 // "di_flags" value: locked variable -#define DI_FLAGS_ALLOC 16 // "di_flags" value: separately allocated - -/// Structure representing a Dictionary -struct dictvar_S { - VarLockStatus dv_lock; ///< Whole dictionary lock status. - char dv_scope; ///< Non-zero (#VAR_SCOPE, #VAR_DEF_SCOPE) if - ///< dictionary represents a scope (i.e. g:, l: โฆ). - int dv_refcount; ///< Reference count. - int dv_copyID; ///< ID used when recursivery traversing a value. - hashtab_T dv_hashtab; ///< Hashtab containing all items. - dict_T *dv_copydict; ///< Copied dict used by deepcopy(). - dict_T *dv_used_next; ///< Next dictionary in used dictionaries list. - dict_T *dv_used_prev; ///< Previous dictionary in used dictionaries list. - QUEUE watchers; ///< Dictionary key watchers set by user code. -}; - -struct partial_S { - int pt_refcount; ///< Reference count. - char_u *pt_name; ///< Function name. - bool pt_auto; ///< when true the partial was created for using - ///< dict.member in handle_subscript(). - int pt_argc; ///< Number of arguments. - typval_T *pt_argv; ///< Arguments in allocated array. - dict_T *pt_dict; ///< Dict for "self". -}; - -// structure used for explicit stack while garbage collecting hash tables -typedef struct ht_stack_S { - hashtab_T *ht; - struct ht_stack_S *prev; -} ht_stack_T; - -// structure used for explicit stack while garbage collecting lists -typedef struct list_stack_S { - list_T *list; - struct list_stack_S *prev; -} list_stack_T; - -// In a hashtab item "hi_key" points to "di_key" in a dictitem. -// This avoids adding a pointer to the hashtab item. - -/// Convert a dictitem pointer to a hashitem key pointer -#define DI2HIKEY(di) ((di)->di_key) - -/// Convert a hashitem key pointer to a dictitem pointer -#define HIKEY2DI(p) ((dictitem_T *)(p - offsetof(dictitem_T, di_key))) - -/// Convert a hashitem value pointer to a dictitem pointer -#define HIVAL2DI(p) \ - ((dictitem_T *)(((char *)p) - offsetof(dictitem_T, di_tv))) - -/// Convert a hashitem pointer to a dictitem pointer -#define HI2DI(hi) HIKEY2DI((hi)->hi_key) - -/// Type of assert_* check being performed -typedef enum -{ - ASSERT_EQUAL, - ASSERT_NOTEQUAL, - ASSERT_MATCH, - ASSERT_NOTMATCH, - ASSERT_OTHER, -} assert_type_T; - -#endif // NVIM_EVAL_DEFS_H diff --git a/src/nvim/event/defs.h b/src/nvim/event/defs.h index e5335d9f25..cc875d74b9 100644 --- a/src/nvim/event/defs.h +++ b/src/nvim/event/defs.h @@ -8,16 +8,14 @@ typedef void (*argv_callback)(void **argv); typedef struct message { - int priority; argv_callback handler; void *argv[EVENT_HANDLER_MAX_ARGC]; } Event; typedef void(*event_scheduler)(Event event, void *data); -#define VA_EVENT_INIT(event, p, h, a) \ +#define VA_EVENT_INIT(event, h, a) \ do { \ assert(a <= EVENT_HANDLER_MAX_ARGC); \ - (event)->priority = p; \ (event)->handler = h; \ if (a) { \ va_list args; \ @@ -29,11 +27,11 @@ typedef void(*event_scheduler)(Event event, void *data); } \ } while (0) -static inline Event event_create(int priority, argv_callback cb, int argc, ...) +static inline Event event_create(argv_callback cb, int argc, ...) { assert(argc <= EVENT_HANDLER_MAX_ARGC); Event event; - VA_EVENT_INIT(&event, priority, cb, argc); + VA_EVENT_INIT(&event, cb, argc); return event; } diff --git a/src/nvim/event/libuv_process.c b/src/nvim/event/libuv_process.c index a68badcc8f..f6a567a520 100644 --- a/src/nvim/event/libuv_process.c +++ b/src/nvim/event/libuv_process.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #include <assert.h> #include <uv.h> @@ -8,22 +11,31 @@ #include "nvim/event/process.h" #include "nvim/event/libuv_process.h" #include "nvim/log.h" +#include "nvim/macros.h" +#include "nvim/os/os.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "event/libuv_process.c.generated.h" #endif -bool libuv_process_spawn(LibuvProcess *uvproc) +/// @returns zero on success, or negative error code +int libuv_process_spawn(LibuvProcess *uvproc) FUNC_ATTR_NONNULL_ALL { Process *proc = (Process *)uvproc; uvproc->uvopts.file = proc->argv[0]; uvproc->uvopts.args = proc->argv; - uvproc->uvopts.flags = UV_PROCESS_WINDOWS_HIDE - | UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS; + uvproc->uvopts.flags = UV_PROCESS_WINDOWS_HIDE; if (proc->detach) { uvproc->uvopts.flags |= UV_PROCESS_DETACHED; } +#ifdef WIN32 + // libuv collapses the argv to a CommandLineToArgvW()-style string. cmd.exe + // expects a different syntax (must be prepared by the caller before now). + if (os_shell_is_cmdexe(proc->argv[0])) { + uvproc->uvopts.flags |= UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS; + } +#endif uvproc->uvopts.exit_cb = exit_cb; uvproc->uvopts.cwd = proc->cwd; uvproc->uvopts.env = NULL; @@ -36,27 +48,30 @@ bool libuv_process_spawn(LibuvProcess *uvproc) if (proc->in) { uvproc->uvstdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE; - uvproc->uvstdio[0].data.stream = (uv_stream_t *)&proc->in->uv.pipe; + uvproc->uvstdio[0].data.stream = STRUCT_CAST(uv_stream_t, + &proc->in->uv.pipe); } if (proc->out) { uvproc->uvstdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE; - uvproc->uvstdio[1].data.stream = (uv_stream_t *)&proc->out->uv.pipe; + uvproc->uvstdio[1].data.stream = STRUCT_CAST(uv_stream_t, + &proc->out->uv.pipe); } if (proc->err) { uvproc->uvstdio[2].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE; - uvproc->uvstdio[2].data.stream = (uv_stream_t *)&proc->err->uv.pipe; + uvproc->uvstdio[2].data.stream = STRUCT_CAST(uv_stream_t, + &proc->err->uv.pipe); } int status; if ((status = uv_spawn(&proc->loop->uv, &uvproc->uv, &uvproc->uvopts))) { ELOG("uv_spawn failed: %s", uv_strerror(status)); - return false; + return status; } proc->pid = uvproc->uv.pid; - return true; + return status; } void libuv_process_close(LibuvProcess *uvproc) diff --git a/src/nvim/event/libuv_process.h b/src/nvim/event/libuv_process.h index aaaa896e10..1132ce79ca 100644 --- a/src/nvim/event/libuv_process.h +++ b/src/nvim/event/libuv_process.h @@ -14,8 +14,9 @@ typedef struct libuv_process { static inline LibuvProcess libuv_process_init(Loop *loop, void *data) { - LibuvProcess rv; - rv.process = process_init(loop, kProcessTypeUv, data); + LibuvProcess rv = { + .process = process_init(loop, kProcessTypeUv, data) + }; return rv; } diff --git a/src/nvim/event/loop.c b/src/nvim/event/loop.c index 0e1775d01b..25701a1621 100644 --- a/src/nvim/event/loop.c +++ b/src/nvim/event/loop.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #include <stdarg.h> #include <stdint.h> @@ -5,6 +8,7 @@ #include "nvim/event/loop.h" #include "nvim/event/process.h" +#include "nvim/log.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "event/loop.c.generated.h" @@ -41,8 +45,7 @@ void loop_poll_events(Loop *loop, int ms) // we do not block indefinitely for I/O. uv_timer_start(&loop->poll_timer, timer_cb, (uint64_t)ms, (uint64_t)ms); } else if (ms == 0) { - // For ms == 0, we need to do a non-blocking event poll by - // setting the run mode to UV_RUN_NOWAIT. + // For ms == 0, do a non-blocking event poll. mode = UV_RUN_NOWAIT; } @@ -76,20 +79,34 @@ void loop_on_put(MultiQueue *queue, void *data) uv_stop(&loop->uv); } -void loop_close(Loop *loop, bool wait) +/// @returns false if the loop could not be closed gracefully +bool loop_close(Loop *loop, bool wait) { + bool rv = true; uv_mutex_destroy(&loop->mutex); uv_close((uv_handle_t *)&loop->children_watcher, NULL); uv_close((uv_handle_t *)&loop->children_kill_timer, NULL); uv_close((uv_handle_t *)&loop->poll_timer, NULL); uv_close((uv_handle_t *)&loop->async, NULL); - do { + uint64_t start = wait ? os_hrtime() : 0; + while (true) { uv_run(&loop->uv, wait ? UV_RUN_DEFAULT : UV_RUN_NOWAIT); - } while (uv_loop_close(&loop->uv) && wait); + if (!uv_loop_close(&loop->uv) || !wait) { + break; + } + if (os_hrtime() - start >= 2 * 1000000000) { + // Some libuv resource was not correctly deref'd. Log and bail. + rv = false; + ELOG("uv_loop_close() hang?"); + log_uv_handles(&loop->uv); + break; + } + } multiqueue_free(loop->fast_events); multiqueue_free(loop->thread_events); multiqueue_free(loop->events); kl_destroy(WatcherPtr, loop->children); + return rv; } void loop_purge(Loop *loop) diff --git a/src/nvim/event/multiqueue.c b/src/nvim/event/multiqueue.c index 79b4dd9458..ef9f3f1870 100644 --- a/src/nvim/event/multiqueue.c +++ b/src/nvim/event/multiqueue.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + // Multi-level queue for selective async event processing. // Not threadsafe; access must be synchronized externally. // @@ -123,6 +126,7 @@ void multiqueue_free(MultiQueue *this) xfree(this); } +/// Removes the next item and returns its Event. Event multiqueue_get(MultiQueue *this) { return multiqueue_empty(this) ? NILEVENT : multiqueue_remove(this); @@ -141,7 +145,7 @@ void multiqueue_process_events(MultiQueue *this) { assert(this); while (!multiqueue_empty(this)) { - Event event = multiqueue_get(this); + Event event = multiqueue_remove(this); if (event.handler) { event.handler(event.argv); } @@ -175,36 +179,48 @@ size_t multiqueue_size(MultiQueue *this) return this->size; } -static Event multiqueue_remove(MultiQueue *this) +/// Gets an Event from an item. +/// +/// @param remove Remove the node from its queue, and free it. +static Event multiqueueitem_get_event(MultiQueueItem *item, bool remove) { - assert(!multiqueue_empty(this)); - QUEUE *h = QUEUE_HEAD(&this->headtail); - QUEUE_REMOVE(h); - MultiQueueItem *item = multiqueue_node_data(h); - Event rv; - + assert(item != NULL); + Event ev; if (item->link) { - assert(!this->parent); - // remove the next node in the linked queue + // get the next node in the linked queue MultiQueue *linked = item->data.queue; assert(!multiqueue_empty(linked)); MultiQueueItem *child = multiqueue_node_data(QUEUE_HEAD(&linked->headtail)); - QUEUE_REMOVE(&child->node); - rv = child->data.item.event; - xfree(child); + ev = child->data.item.event; + // remove the child node + if (remove) { + QUEUE_REMOVE(&child->node); + xfree(child); + } } else { - if (this->parent) { - // remove the corresponding link node in the parent queue + // remove the corresponding link node in the parent queue + if (remove && item->data.item.parent_item) { QUEUE_REMOVE(&item->data.item.parent_item->node); xfree(item->data.item.parent_item); + item->data.item.parent_item = NULL; } - rv = item->data.item.event; + ev = item->data.item.event; } + return ev; +} +static Event multiqueue_remove(MultiQueue *this) +{ + assert(!multiqueue_empty(this)); + QUEUE *h = QUEUE_HEAD(&this->headtail); + QUEUE_REMOVE(h); + MultiQueueItem *item = multiqueue_node_data(h); + assert(!item->link || !this->parent); // Only a parent queue has link-nodes + Event ev = multiqueueitem_get_event(item, true); this->size--; xfree(item); - return rv; + return ev; } static void multiqueue_push(MultiQueue *this, Event event) @@ -212,6 +228,7 @@ static void multiqueue_push(MultiQueue *this, Event event) MultiQueueItem *item = xmalloc(sizeof(MultiQueueItem)); item->link = false; item->data.item.event = event; + item->data.item.parent_item = NULL; QUEUE_INSERT_TAIL(&this->headtail, &item->node); if (this->parent) { // push link node to the parent queue diff --git a/src/nvim/event/multiqueue.h b/src/nvim/event/multiqueue.h index def6b95a10..a688107665 100644 --- a/src/nvim/event/multiqueue.h +++ b/src/nvim/event/multiqueue.h @@ -10,7 +10,7 @@ typedef struct multiqueue MultiQueue; typedef void (*put_callback)(MultiQueue *multiq, void *data); #define multiqueue_put(q, h, ...) \ - multiqueue_put_event(q, event_create(1, h, __VA_ARGS__)); + multiqueue_put_event(q, event_create(h, __VA_ARGS__)); #ifdef INCLUDE_GENERATED_DECLARATIONS diff --git a/src/nvim/event/process.c b/src/nvim/event/process.c index dc7886469b..8371d3cd48 100644 --- a/src/nvim/event/process.c +++ b/src/nvim/event/process.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #include <assert.h> #include <stdlib.h> @@ -11,15 +14,16 @@ #include "nvim/event/libuv_process.h" #include "nvim/os/pty_process.h" #include "nvim/globals.h" +#include "nvim/macros.h" #include "nvim/log.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "event/process.c.generated.h" #endif -// Time (ns) for a process to exit cleanly before we send TERM/KILL. -#define TERM_TIMEOUT 1000000000 -#define KILL_TIMEOUT (TERM_TIMEOUT * 2) +// Time for a process to exit cleanly before we send KILL. +// For pty processes SIGTERM is sent first (in case SIGHUP was not enough). +#define KILL_TIMEOUT_MS 2000 #define CLOSE_PROC_STREAM(proc, stream) \ do { \ @@ -30,7 +34,8 @@ static bool process_is_tearing_down = false; -bool process_spawn(Process *proc) FUNC_ATTR_NONNULL_ALL +/// @returns zero on success, or negative error code +int process_spawn(Process *proc) FUNC_ATTR_NONNULL_ALL { if (proc->in) { uv_pipe_init(&proc->loop->uv, &proc->in->uv.pipe, 0); @@ -44,19 +49,19 @@ bool process_spawn(Process *proc) FUNC_ATTR_NONNULL_ALL uv_pipe_init(&proc->loop->uv, &proc->err->uv.pipe, 0); } - bool success; + int status; switch (proc->type) { case kProcessTypeUv: - success = libuv_process_spawn((LibuvProcess *)proc); + status = libuv_process_spawn((LibuvProcess *)proc); break; case kProcessTypePty: - success = pty_process_spawn((PtyProcess *)proc); + status = pty_process_spawn((PtyProcess *)proc); break; default: abort(); } - if (!success) { + if (status) { if (proc->in) { uv_close((uv_handle_t *)&proc->in->uv.pipe, NULL); } @@ -74,11 +79,12 @@ bool process_spawn(Process *proc) FUNC_ATTR_NONNULL_ALL } shell_free_argv(proc->argv); proc->status = -1; - return false; + return status; } if (proc->in) { - stream_init(NULL, proc->in, -1, (uv_stream_t *)&proc->in->uv.pipe); + stream_init(NULL, proc->in, -1, + STRUCT_CAST(uv_stream_t, &proc->in->uv.pipe)); proc->in->events = proc->events; proc->in->internal_data = proc; proc->in->internal_close_cb = on_process_stream_close; @@ -86,7 +92,8 @@ bool process_spawn(Process *proc) FUNC_ATTR_NONNULL_ALL } if (proc->out) { - stream_init(NULL, proc->out, -1, (uv_stream_t *)&proc->out->uv.pipe); + stream_init(NULL, proc->out, -1, + STRUCT_CAST(uv_stream_t, &proc->out->uv.pipe)); proc->out->events = proc->events; proc->out->internal_data = proc; proc->out->internal_close_cb = on_process_stream_close; @@ -94,7 +101,8 @@ bool process_spawn(Process *proc) FUNC_ATTR_NONNULL_ALL } if (proc->err) { - stream_init(NULL, proc->err, -1, (uv_stream_t *)&proc->err->uv.pipe); + stream_init(NULL, proc->err, -1, + STRUCT_CAST(uv_stream_t, &proc->err->uv.pipe)); proc->err->events = proc->events; proc->err->internal_data = proc; proc->err->internal_close_cb = on_process_stream_close; @@ -105,7 +113,7 @@ bool process_spawn(Process *proc) FUNC_ATTR_NONNULL_ALL proc->internal_close_cb = decref; proc->refcount++; kl_push(WatcherPtr, proc->loop->children, proc); - return true; + return 0; } void process_teardown(Loop *loop) FUNC_ATTR_NONNULL_ALL @@ -117,8 +125,6 @@ void process_teardown(Loop *loop) FUNC_ATTR_NONNULL_ALL // Close handles to process without killing it. CREATE_EVENT(loop->events, process_close_handles, 1, proc); } else { - uv_kill(proc->pid, SIGTERM); - proc->term_sent = true; process_stop(proc); } } @@ -155,19 +161,16 @@ void process_close_err(Process *proc) FUNC_ATTR_NONNULL_ALL /// Synchronously wait for a process to finish /// -/// @param process The Process instance -/// @param ms Number of milliseconds to wait, 0 for not waiting, -1 for -/// waiting until the process quits. -/// @return returns the status code of the exited process. -1 if the process is -/// still running and the `timeout` has expired. Note that this is -/// indistinguishable from the process returning -1 by itself. Which -/// is possible on some OS. Returns -2 if an user has interruped the -/// wait. +/// @param process Process instance +/// @param ms Time in milliseconds to wait for the process. +/// 0 for no wait. -1 to wait until the process quits. +/// @return Exit code of the process. +/// -1 if the timeout expired while the process is still running. +/// -2 if the user interruped the wait. int process_wait(Process *proc, int ms, MultiQueue *events) FUNC_ATTR_NONNULL_ARG(1) { - // The default status is -1, which represents a timeout - int status = -1; + int status = -1; // default bool interrupted = false; if (!proc->refcount) { status = proc->status; @@ -179,8 +182,8 @@ int process_wait(Process *proc, int ms, MultiQueue *events) events = proc->events; } - // Increase refcount to stop the exit callback from being called(and possibly - // being freed) before we have a chance to get the status. + // Increase refcount to stop the exit callback from being called (and possibly + // freed) before we have a chance to get the status. proc->refcount++; LOOP_PROCESS_EVENTS_UNTIL(proc->loop, events, ms, // Until... @@ -230,9 +233,10 @@ void process_stop(Process *proc) FUNC_ATTR_NONNULL_ALL switch (proc->type) { case kProcessTypeUv: // Close the process's stdin. If the process doesn't close its own - // stdout/stderr, they will be closed when it exits(possibly due to being - // terminated after a timeout) + // stdout/stderr, they will be closed when it exits (voluntarily or not). process_close_in(proc); + ILOG("Sending SIGTERM to pid %d", proc->pid); + uv_kill(proc->pid, SIGTERM); break; case kProcessTypePty: // close all streams for pty processes to send SIGHUP to the process @@ -246,9 +250,10 @@ void process_stop(Process *proc) FUNC_ATTR_NONNULL_ALL Loop *loop = proc->loop; if (!loop->children_stop_requests++) { // When there's at least one stop request pending, start a timer that - // will periodically check if a signal should be send to a to the job - DLOG("Starting job kill timer"); - uv_timer_start(&loop->children_kill_timer, children_kill_cb, 100, 100); + // will periodically check if a signal should be send to the job. + ILOG("Starting job kill timer"); + uv_timer_start(&loop->children_kill_timer, children_kill_cb, + KILL_TIMEOUT_MS, KILL_TIMEOUT_MS); } } @@ -264,15 +269,15 @@ static void children_kill_cb(uv_timer_t *handle) if (!proc->stopped_time) { continue; } - uint64_t elapsed = now - proc->stopped_time; - - if (!proc->term_sent && elapsed >= TERM_TIMEOUT) { - ILOG("Sending SIGTERM to pid %d", proc->pid); - uv_kill(proc->pid, SIGTERM); - proc->term_sent = true; - } else if (elapsed >= KILL_TIMEOUT) { - ILOG("Sending SIGKILL to pid %d", proc->pid); - uv_kill(proc->pid, SIGKILL); + uint64_t elapsed = (now - proc->stopped_time) / 1000000 + 1; + + if (elapsed >= KILL_TIMEOUT_MS) { + int sig = proc->type == kProcessTypePty && elapsed < KILL_TIMEOUT_MS * 2 + ? SIGTERM + : SIGKILL; + ILOG("Sending %s to pid %d", sig == SIGTERM ? "SIGTERM" : "SIGKILL", + proc->pid); + uv_kill(proc->pid, sig); } } } diff --git a/src/nvim/event/process.h b/src/nvim/event/process.h index 5cbf7f9ce7..5c00e8e7ec 100644 --- a/src/nvim/event/process.h +++ b/src/nvim/event/process.h @@ -21,12 +21,12 @@ struct process { int pid, status, refcount; // set to the hrtime of when process_stop was called for the process. uint64_t stopped_time; - char *cwd; + const char *cwd; char **argv; Stream *in, *out, *err; process_exit_cb cb; internal_process_cb internal_exit_cb, internal_close_cb; - bool closed, term_sent, detach; + bool closed, detach; MultiQueue *events; }; @@ -48,7 +48,6 @@ static inline Process process_init(Loop *loop, ProcessType type, void *data) .err = NULL, .cb = NULL, .closed = false, - .term_sent = false, .internal_close_cb = NULL, .internal_exit_cb = NULL, .detach = false diff --git a/src/nvim/event/rstream.c b/src/nvim/event/rstream.c index 92efc9fa2e..2c4db08b30 100644 --- a/src/nvim/event/rstream.c +++ b/src/nvim/event/rstream.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #include <assert.h> #include <stdint.h> #include <stdbool.h> @@ -89,7 +92,10 @@ static void on_rbuffer_nonfull(RBuffer *buf, void *data) static void alloc_cb(uv_handle_t *handle, size_t suggested, uv_buf_t *buf) { Stream *stream = handle->data; - buf->base = rbuffer_write_ptr(stream->buffer, &buf->len); + // `uv_buf_t.len` happens to have different size on Windows. + size_t write_count; + buf->base = rbuffer_write_ptr(stream->buffer, &write_count); + buf->len = write_count; } // Callback invoked by libuv after it copies the data into the buffer provided @@ -112,7 +118,7 @@ static void read_cb(uv_stream_t *uvstream, ssize_t cnt, const uv_buf_t *buf) // to `alloc_cb` will return the same unused pointer(`rbuffer_produced` // won't be called) && cnt != 0) { - DLOG("Closing Stream (%p): %s (%s)", stream, + DLOG("closing Stream: %p: %s (%s)", stream, uv_err_name((int)cnt), os_strerror((int)cnt)); // Read error or EOF, either way stop the stream and invoke the callback // with eof == true @@ -136,7 +142,10 @@ static void fread_idle_cb(uv_idle_t *handle) uv_fs_t req; Stream *stream = handle->data; - stream->uvbuf.base = rbuffer_write_ptr(stream->buffer, &stream->uvbuf.len); + // `uv_buf_t.len` happens to have different size on Windows. + size_t write_count; + stream->uvbuf.base = rbuffer_write_ptr(stream->buffer, &write_count); + stream->uvbuf.len = write_count; // the offset argument to uv_fs_read is int64_t, could someone really try // to read more than 9 quintillion (9e18) bytes? diff --git a/src/nvim/event/signal.c b/src/nvim/event/signal.c index 11ce15a882..fec46da4ff 100644 --- a/src/nvim/event/signal.c +++ b/src/nvim/event/signal.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #include <uv.h> #include "nvim/event/loop.h" diff --git a/src/nvim/event/socket.c b/src/nvim/event/socket.c index 8f9327f3d4..6f45b09fce 100644 --- a/src/nvim/event/socket.c +++ b/src/nvim/event/socket.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #include <assert.h> #include <stdint.h> @@ -12,99 +15,123 @@ #include "nvim/vim.h" #include "nvim/strings.h" #include "nvim/path.h" +#include "nvim/main.h" #include "nvim/memory.h" +#include "nvim/macros.h" +#include "nvim/charset.h" +#include "nvim/log.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "event/socket.c.generated.h" #endif -#define NVIM_DEFAULT_TCP_PORT 7450 - -void socket_watcher_init(Loop *loop, SocketWatcher *watcher, - const char *endpoint, void *data) - FUNC_ATTR_NONNULL_ARG(1) FUNC_ATTR_NONNULL_ARG(2) FUNC_ATTR_NONNULL_ARG(3) +int socket_watcher_init(Loop *loop, SocketWatcher *watcher, + const char *endpoint) + FUNC_ATTR_NONNULL_ALL { - // Trim to `ADDRESS_MAX_SIZE` - if (xstrlcpy(watcher->addr, endpoint, sizeof(watcher->addr)) - >= sizeof(watcher->addr)) { - // TODO(aktau): since this is not what the user wanted, perhaps we - // should return an error here - WLOG("Address was too long, truncated to %s", watcher->addr); - } - - bool tcp = true; - char ip[16], *ip_end = xstrchrnul(watcher->addr, ':'); + xstrlcpy(watcher->addr, endpoint, sizeof(watcher->addr)); + char *addr = watcher->addr; + char *host_end = strrchr(addr, ':'); - // (ip_end - addr) is always > 0, so convert to size_t - size_t addr_len = (size_t)(ip_end - watcher->addr); + if (host_end && addr != host_end) { + // Split user specified address into two strings, addr(hostname) and port. + // The port part in watcher->addr will be updated later. + *host_end = '\0'; + char *port = host_end + 1; + intmax_t iport; - if (addr_len > sizeof(ip) - 1) { - // Maximum length of an IPv4 address buffer is 15 (eg: 255.255.255.255) - addr_len = sizeof(ip) - 1; - } + int ret = getdigits_safe(&(char_u *){ (char_u *)port }, &iport); + if (ret == FAIL || iport < 0 || iport > UINT16_MAX) { + ELOG("Invalid port: %s", port); + return UV_EINVAL; + } - // Extract the address part - xstrlcpy(ip, watcher->addr, addr_len + 1); - int port = NVIM_DEFAULT_TCP_PORT; - - if (*ip_end == ':') { - // Extract the port - long lport = strtol(ip_end + 1, NULL, 10); // NOLINT - if (lport <= 0 || lport > 0xffff) { - // Invalid port, treat as named pipe or unix socket - tcp = false; - } else { - port = (int) lport; + if (*port == NUL) { + // When no port is given, (uv_)getaddrinfo expects NULL otherwise the + // implementation may attempt to lookup the service by name (and fail) + port = NULL; } - } - if (tcp) { - // Try to parse ip address - if (uv_ip4_addr(ip, port, &watcher->uv.tcp.addr)) { - // Invalid address, treat as named pipe or unix socket - tcp = false; + uv_getaddrinfo_t request; + + int retval = uv_getaddrinfo(&loop->uv, &request, NULL, addr, port, + &(struct addrinfo){ + .ai_family = AF_UNSPEC, + .ai_socktype = SOCK_STREAM, + }); + if (retval != 0) { + ELOG("Host lookup failed: %s", endpoint); + return retval; } - } + watcher->uv.tcp.addrinfo = request.addrinfo; - if (tcp) { uv_tcp_init(&loop->uv, &watcher->uv.tcp.handle); - watcher->stream = (uv_stream_t *)&watcher->uv.tcp.handle; + uv_tcp_nodelay(&watcher->uv.tcp.handle, true); + watcher->stream = STRUCT_CAST(uv_stream_t, &watcher->uv.tcp.handle); } else { uv_pipe_init(&loop->uv, &watcher->uv.pipe.handle, 0); - watcher->stream = (uv_stream_t *)&watcher->uv.pipe.handle; + watcher->stream = STRUCT_CAST(uv_stream_t, &watcher->uv.pipe.handle); } watcher->stream->data = watcher; watcher->cb = NULL; watcher->close_cb = NULL; watcher->events = NULL; + watcher->data = NULL; + + return 0; } int socket_watcher_start(SocketWatcher *watcher, int backlog, socket_cb cb) FUNC_ATTR_NONNULL_ALL { watcher->cb = cb; - int result; + int result = UV_EINVAL; if (watcher->stream->type == UV_TCP) { - result = uv_tcp_bind(&watcher->uv.tcp.handle, - (const struct sockaddr *)&watcher->uv.tcp.addr, 0); + struct addrinfo *ai = watcher->uv.tcp.addrinfo; + + for (; ai; ai = ai->ai_next) { + result = uv_tcp_bind(&watcher->uv.tcp.handle, ai->ai_addr, 0); + if (result != 0) { + continue; + } + result = uv_listen(watcher->stream, backlog, connection_cb); + if (result == 0) { + struct sockaddr_storage sas; + + // When the endpoint in socket_watcher_init() didn't specify a port + // number, a free random port number will be assigned. sin_port will + // contain 0 in this case, unless uv_tcp_getsockname() is used first. + uv_tcp_getsockname(&watcher->uv.tcp.handle, (struct sockaddr *)&sas, + &(int){ sizeof(sas) }); + uint16_t port = (uint16_t)( + (sas.ss_family == AF_INET) + ? (STRUCT_CAST(struct sockaddr_in, &sas))->sin_port + : (STRUCT_CAST(struct sockaddr_in6, &sas))->sin6_port); + // v:servername uses the string from watcher->addr + size_t len = strlen(watcher->addr); + snprintf(watcher->addr+len, sizeof(watcher->addr)-len, ":%" PRIu16, + ntohs(port)); + break; + } + } + uv_freeaddrinfo(watcher->uv.tcp.addrinfo); } else { result = uv_pipe_bind(&watcher->uv.pipe.handle, watcher->addr); - } - - if (result == 0) { - result = uv_listen(watcher->stream, backlog, connection_cb); + if (result == 0) { + result = uv_listen(watcher->stream, backlog, connection_cb); + } } assert(result <= 0); // libuv should return negative error code or zero. if (result < 0) { - if (result == -EACCES) { + if (result == UV_EACCES) { // Libuv converts ENOENT to EACCES for Windows compatibility, but if // the parent directory does not exist, ENOENT would be more accurate. *path_tail((char_u *)watcher->addr) = NUL; if (!os_path_exists((char_u *)watcher->addr)) { - result = -ENOENT; + result = UV_ENOENT; } } return result; @@ -119,10 +146,11 @@ int socket_watcher_accept(SocketWatcher *watcher, Stream *stream) uv_stream_t *client; if (watcher->stream->type == UV_TCP) { - client = (uv_stream_t *)&stream->uv.tcp; + client = STRUCT_CAST(uv_stream_t, &stream->uv.tcp); uv_tcp_init(watcher->uv.tcp.handle.loop, (uv_tcp_t *)client); + uv_tcp_nodelay((uv_tcp_t *)client, true); } else { - client = (uv_stream_t *)&stream->uv.pipe; + client = STRUCT_CAST(uv_stream_t, &stream->uv.pipe); uv_pipe_init(watcher->uv.pipe.handle.loop, (uv_pipe_t *)client, 0); } @@ -165,3 +193,77 @@ static void close_cb(uv_handle_t *handle) watcher->close_cb(watcher, watcher->data); } } + +static void connect_cb(uv_connect_t *req, int status) +{ + int *ret_status = req->data; + *ret_status = status; + if (status != 0) { + uv_close((uv_handle_t *)req->handle, NULL); + } +} + +bool socket_connect(Loop *loop, Stream *stream, + bool is_tcp, const char *address, + int timeout, const char **error) +{ + bool success = false; + int status; + uv_connect_t req; + req.data = &status; + uv_stream_t *uv_stream; + + uv_tcp_t *tcp = &stream->uv.tcp; + uv_getaddrinfo_t addr_req; + addr_req.addrinfo = NULL; + const struct addrinfo *addrinfo = NULL; + char *addr = NULL; + if (is_tcp) { + addr = xstrdup(address); + char *host_end = strrchr(addr, ':'); + if (!host_end) { + *error = _("tcp address must be host:port"); + goto cleanup; + } + *host_end = NUL; + + const struct addrinfo hints = { .ai_family = AF_UNSPEC, + .ai_socktype = SOCK_STREAM, + .ai_flags = AI_NUMERICSERV }; + int retval = uv_getaddrinfo(&loop->uv, &addr_req, NULL, + addr, host_end+1, &hints); + if (retval != 0) { + *error = _("failed to lookup host or port"); + goto cleanup; + } + addrinfo = addr_req.addrinfo; + +tcp_retry: + uv_tcp_init(&loop->uv, tcp); + uv_tcp_nodelay(tcp, true); + uv_tcp_connect(&req, tcp, addrinfo->ai_addr, connect_cb); + uv_stream = (uv_stream_t *)tcp; + + } else { + uv_pipe_t *pipe = &stream->uv.pipe; + uv_pipe_init(&loop->uv, pipe, 0); + uv_pipe_connect(&req, pipe, address, connect_cb); + uv_stream = STRUCT_CAST(uv_stream_t, pipe); + } + status = 1; + LOOP_PROCESS_EVENTS_UNTIL(&main_loop, NULL, timeout, status != 1); + if (status == 0) { + stream_init(NULL, stream, -1, uv_stream); + success = true; + } else if (is_tcp && addrinfo->ai_next) { + addrinfo = addrinfo->ai_next; + goto tcp_retry; + } else { + *error = _("connection refused"); + } + +cleanup: + xfree(addr); + uv_freeaddrinfo(addr_req.addrinfo); + return success; +} diff --git a/src/nvim/event/socket.h b/src/nvim/event/socket.h index eb0823c76d..d30ae45502 100644 --- a/src/nvim/event/socket.h +++ b/src/nvim/event/socket.h @@ -20,7 +20,7 @@ struct socket_watcher { union { struct { uv_tcp_t handle; - struct sockaddr_in addr; + struct addrinfo *addrinfo; } tcp; struct { uv_pipe_t handle; diff --git a/src/nvim/event/stream.c b/src/nvim/event/stream.c index 26083c20f4..7c865bfe1e 100644 --- a/src/nvim/event/stream.c +++ b/src/nvim/event/stream.c @@ -1,10 +1,15 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #include <assert.h> #include <stdio.h> #include <stdbool.h> #include <uv.h> +#include "nvim/log.h" #include "nvim/rbuffer.h" +#include "nvim/macros.h" #include "nvim/event/stream.h" #ifdef INCLUDE_GENERATED_DECLARATIONS @@ -23,8 +28,9 @@ int stream_set_blocking(int fd, bool blocking) uv_loop_init(&loop); uv_pipe_init(&loop, &stream, 0); uv_pipe_open(&stream, fd); - int retval = uv_stream_set_blocking((uv_stream_t *)&stream, blocking); - uv_close((uv_handle_t *)&stream, NULL); + int retval = uv_stream_set_blocking(STRUCT_CAST(uv_stream_t, &stream), + blocking); + uv_close(STRUCT_CAST(uv_handle_t, &stream), NULL); uv_run(&loop, UV_RUN_NOWAIT); // not necessary, but couldn't hurt. uv_loop_close(&loop); return retval; @@ -49,7 +55,7 @@ void stream_init(Loop *loop, Stream *stream, int fd, uv_stream_t *uvstream) assert(type == UV_NAMED_PIPE || type == UV_TTY); uv_pipe_init(&loop->uv, &stream->uv.pipe, 0); uv_pipe_open(&stream->uv.pipe, fd); - stream->uvstream = (uv_stream_t *)&stream->uv.pipe; + stream->uvstream = STRUCT_CAST(uv_stream_t, &stream->uv.pipe); } } @@ -76,6 +82,7 @@ void stream_close(Stream *stream, stream_close_cb on_stream_close, void *data) FUNC_ATTR_NONNULL_ARG(1) { assert(!stream->closed); + DLOG("closing Stream: %p", stream); stream->closed = true; stream->close_cb = on_stream_close; stream->close_cb_data = data; diff --git a/src/nvim/event/time.c b/src/nvim/event/time.c index 77260546db..80289c27d1 100644 --- a/src/nvim/event/time.c +++ b/src/nvim/event/time.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #include <stdint.h> #include <uv.h> diff --git a/src/nvim/event/wstream.c b/src/nvim/event/wstream.c index fc7aad8eb9..320006890d 100644 --- a/src/nvim/event/wstream.c +++ b/src/nvim/event/wstream.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #include <assert.h> #include <stdint.h> #include <stdbool.h> @@ -5,6 +8,7 @@ #include <uv.h> +#include "nvim/log.h" #include "nvim/event/loop.h" #include "nvim/event/wstream.h" #include "nvim/vim.h" diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index b1a17e8c44..32dbf4cc69 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + /* * ex_cmds.c: some functions for command line commands */ @@ -315,14 +318,12 @@ static int sort_abort; ///< flag to indicate if sorting has been interrupted /// Struct to store info to be sorted. typedef struct { linenr_T lnum; ///< line number - long start_col_nr; ///< starting column number or number - long end_col_nr; ///< ending column number union { struct { - long start_col_nr; ///< starting column number - long end_col_nr; ///< ending column number + varnumber_T start_col_nr; ///< starting column number + varnumber_T end_col_nr; ///< ending column number } line; - long value; ///< value if sorting by integer + varnumber_T value; ///< value if sorting by integer float_T value_flt; ///< value if sorting by float } st_u; } sorti_T; @@ -357,12 +358,12 @@ static int sort_compare(const void *s1, const void *s2) // We need to copy one line into "sortbuf1", because there is no // guarantee that the first pointer becomes invalid when obtaining the // second one. - STRNCPY(sortbuf1, ml_get(l1.lnum) + l1.st_u.line.start_col_nr, - l1.st_u.line.end_col_nr - l1.st_u.line.start_col_nr + 1); - sortbuf1[l1.st_u.line.end_col_nr - l1.st_u.line.start_col_nr] = 0; - STRNCPY(sortbuf2, ml_get(l2.lnum) + l2.st_u.line.start_col_nr, - l2.st_u.line.end_col_nr - l2.st_u.line.start_col_nr + 1); - sortbuf2[l2.st_u.line.end_col_nr - l2.st_u.line.start_col_nr] = 0; + memcpy(sortbuf1, ml_get(l1.lnum) + l1.st_u.line.start_col_nr, + l1.st_u.line.end_col_nr - l1.st_u.line.start_col_nr + 1); + sortbuf1[l1.st_u.line.end_col_nr - l1.st_u.line.start_col_nr] = NUL; + memcpy(sortbuf2, ml_get(l2.lnum) + l2.st_u.line.start_col_nr, + l2.st_u.line.end_col_nr - l2.st_u.line.start_col_nr + 1); + sortbuf2[l2.st_u.line.end_col_nr - l2.st_u.line.start_col_nr] = NUL; result = sort_ic ? STRICMP(sortbuf1, sortbuf2) : STRCMP(sortbuf1, sortbuf2); @@ -596,9 +597,10 @@ void ex_sort(exarg_T *eap) // Adjust marks for deleted (or added) lines and prepare for displaying. deleted = (long)(count - (lnum - eap->line2)); if (deleted > 0) { - mark_adjust(eap->line2 - deleted, eap->line2, (long)MAXLNUM, -deleted); + mark_adjust(eap->line2 - deleted, eap->line2, (long)MAXLNUM, -deleted, + false); } else if (deleted < 0) { - mark_adjust(eap->line2, MAXLNUM, -deleted, 0L); + mark_adjust(eap->line2, MAXLNUM, -deleted, 0L, false); } changed_lines(eap->line1, 0, eap->line2 + 1, -deleted); @@ -756,14 +758,6 @@ int do_move(linenr_T line1, linenr_T line2, linenr_T dest) linenr_T num_lines; // Num lines moved linenr_T last_line; // Last line in file after adding new text - // Moving lines seems to corrupt the folds, delete folding info now - // and recreate it when finished. Don't do this for manual folding, it - // would delete all folds. - bool isFolded = hasAnyFolding(curwin) && !foldmethodIsManual(curwin); - if (isFolded) { - deleteFoldRecurse(&curwin->w_folds); - } - if (dest >= line1 && dest < line2) { EMSG(_("E134: Move lines into themselves")); return FAIL; @@ -801,21 +795,29 @@ int do_move(linenr_T line1, linenr_T line2, linenr_T dest) * their final destination at the new text position -- webb */ last_line = curbuf->b_ml.ml_line_count; - mark_adjust(line1, line2, last_line - line2, 0L); - changed_lines(last_line - num_lines + 1, 0, last_line + 1, num_lines); + mark_adjust_nofold(line1, line2, last_line - line2, 0L, true); if (dest >= line2) { - mark_adjust(line2 + 1, dest, -num_lines, 0L); + mark_adjust_nofold(line2 + 1, dest, -num_lines, 0L, false); + FOR_ALL_TAB_WINDOWS(tab, win) { + if (win->w_buffer == curbuf) { + foldMoveRange(&win->w_folds, line1, line2, dest); + } + } curbuf->b_op_start.lnum = dest - num_lines + 1; curbuf->b_op_end.lnum = dest; } else { - mark_adjust(dest + 1, line1 - 1, num_lines, 0L); + mark_adjust_nofold(dest + 1, line1 - 1, num_lines, 0L, false); + FOR_ALL_TAB_WINDOWS(tab, win) { + if (win->w_buffer == curbuf) { + foldMoveRange(&win->w_folds, dest + 1, line1 - 1, line2); + } + } curbuf->b_op_start.lnum = dest + 1; curbuf->b_op_end.lnum = dest + num_lines; } curbuf->b_op_start.col = curbuf->b_op_end.col = 0; - mark_adjust(last_line - num_lines + 1, last_line, - -(last_line - dest - extra), 0L); - changed_lines(last_line - num_lines + 1, 0, last_line + 1, -extra); + mark_adjust_nofold(last_line - num_lines + 1, last_line, + -(last_line - dest - extra), 0L, true); /* * Now we delete the original text -- webb @@ -851,11 +853,6 @@ int do_move(linenr_T line1, linenr_T line2, linenr_T dest) changed_lines(dest + 1, 0, line1 + num_lines, 0L); } - // recreate folds - if (isFolded) { - foldUpdateAll(curwin); - } - return OK; } @@ -1013,8 +1010,8 @@ void do_bang(int addr_count, exarg_T *eap, int forceit, int do_in, int do_out) AppendToRedobuffLit(cmd, -1); xfree(cmd); - AppendToRedobuff((char_u *)"\n"); - bangredo = FALSE; + AppendToRedobuff("\n"); + bangredo = false; } /* * Add quotes around the command, for shells that need them. @@ -1131,11 +1128,12 @@ static void do_filter( */ ++no_wait_return; /* don't call wait_return() while busy */ if (itmp != NULL && buf_write(curbuf, itmp, NULL, line1, line2, eap, - FALSE, FALSE, FALSE, TRUE) == FAIL) { - msg_putchar('\n'); /* keep message from buf_write() */ - --no_wait_return; - if (!aborting()) - (void)EMSG2(_(e_notcreate), itmp); /* will call wait_return */ + false, false, false, true) == FAIL) { + msg_putchar('\n'); // Keep message from buf_write(). + no_wait_return--; + if (!aborting()) { + EMSG2(_("E482: Can't create file %s"), itmp); // Will call wait_return. + } goto filterend; } if (curbuf != old_curbuf) @@ -1193,8 +1191,8 @@ static void do_filter( if (do_out) { if (otmp != NULL) { - if (readfile(otmp, NULL, line2, (linenr_T)0, (linenr_T)MAXLNUM, - eap, READ_FILTER) == FAIL) { + if (readfile(otmp, NULL, line2, (linenr_T)0, (linenr_T)MAXLNUM, eap, + READ_FILTER) != OK) { if (!aborting()) { msg_putchar('\n'); EMSG2(_(e_notread), otmp); @@ -1215,15 +1213,14 @@ static void do_filter( if (do_in) { if (cmdmod.keepmarks || vim_strchr(p_cpo, CPO_REMMARK) == NULL) { - if (read_linecount >= linecount) - /* move all marks from old lines to new lines */ - mark_adjust(line1, line2, linecount, 0L); - else { - /* move marks from old lines to new lines, delete marks - * that are in deleted lines */ - mark_adjust(line1, line1 + read_linecount - 1, - linecount, 0L); - mark_adjust(line1 + read_linecount, line2, MAXLNUM, 0L); + if (read_linecount >= linecount) { + // move all marks from old lines to new lines + mark_adjust(line1, line2, linecount, 0L, false); + } else { + // move marks from old lines to new lines, delete marks + // that are in deleted lines + mark_adjust(line1, line1 + read_linecount - 1, linecount, 0L, false); + mark_adjust(line1 + read_linecount, line2, MAXLNUM, 0L, false); } } @@ -1404,36 +1401,34 @@ char_u *make_filter_cmd(char_u *cmd, char_u *itmp, char_u *otmp) : "(%s)"; vim_snprintf(buf, len, fmt, (char *)cmd); } else { - strncpy(buf, (char *) cmd, len); + xstrlcpy(buf, (char *)cmd, len); } if (itmp != NULL) { - strncat(buf, " < ", len); - strncat(buf, (char *) itmp, len); + xstrlcat(buf, " < ", len - 1); + xstrlcat(buf, (const char *)itmp, len - 1); } #else // For shells that don't understand braces around commands, at least allow // the use of commands in a pipe. - strncpy(buf, cmd, len); + xstrlcpy(buf, cmd, len); if (itmp != NULL) { - char_u *p; - // If there is a pipe, we have to put the '<' in front of it. // Don't do this when 'shellquote' is not empty, otherwise the // redirection would be inside the quotes. if (*p_shq == NUL) { - p = strchr(buf, '|'); + char *const p = strchr(buf, '|'); if (p != NULL) { *p = NUL; } } - strncat(buf, " < ", len); - strncat(buf, (char *) itmp, len); + xstrlcat(buf, " < ", len); + xstrlcat(buf, (const char *)itmp, len); if (*p_shq == NUL) { - p = strchr(cmd, '|'); + const char *const p = strchr((const char *)cmd, '|'); if (p != NULL) { - strncat(buf, " ", len); // Insert a space before the '|' for DOS - strncat(buf, p, len); + xstrlcat(buf, " ", len - 1); // Insert a space before the '|' for DOS + xstrlcat(buf, p, len - 1); } } } @@ -1476,12 +1471,12 @@ void append_redir(char *const buf, const size_t buflen, void print_line_no_prefix(linenr_T lnum, int use_number, int list) { - char_u numbuf[30]; + char numbuf[30]; if (curwin->w_p_nu || use_number) { - vim_snprintf((char *)numbuf, sizeof(numbuf), - "%*ld ", number_width(curwin), (long)lnum); - msg_puts_attr(numbuf, hl_attr(HLF_N)); /* Highlight line nrs */ + vim_snprintf(numbuf, sizeof(numbuf), "%*" PRIdLINENR " ", + number_width(curwin), lnum); + msg_puts_attr(numbuf, hl_attr(HLF_N)); // Highlight line nrs. } msg_prt_line(ml_get(lnum), list); } @@ -1493,6 +1488,11 @@ void print_line(linenr_T lnum, int use_number, int list) { int save_silent = silent_mode; + // apply :filter /pat/ + if (message_filtered(ml_get(lnum))) { + return; + } + msg_start(); silent_mode = FALSE; info_message = TRUE; /* use mch_msg(), not mch_errmsg() */ @@ -1906,11 +1906,15 @@ void do_wqall(exarg_T *eap) FALSE) == FAIL) { ++error; } else { - if (buf_write_all(buf, eap->forceit) == FAIL) - ++error; - /* an autocommand may have deleted the buffer */ - if (!buf_valid(buf)) + bufref_T bufref; + set_bufref(&bufref, buf); + if (buf_write_all(buf, eap->forceit) == FAIL) { + error++; + } + // An autocommand may have deleted the buffer. + if (!bufref_valid(&bufref)) { buf = firstbuf; + } } eap->forceit = save_forceit; /* check_overwrite() may set it */ } @@ -2083,7 +2087,8 @@ int do_ecmd( char_u *new_name = NULL; int did_set_swapcommand = FALSE; buf_T *buf; - buf_T *old_curbuf = curbuf; + bufref_T bufref; + bufref_T old_curbuf; char_u *free_fname = NULL; int retval = FAIL; long n; @@ -2100,6 +2105,8 @@ int do_ecmd( if (eap != NULL) command = eap->do_ecmd_cmd; + set_bufref(&old_curbuf, curbuf); + if (fnum != 0) { if (fnum == curbuf->b_fnum) /* file is already being edited */ return OK; /* nothing to do */ @@ -2211,23 +2218,27 @@ int do_ecmd( if (oldwin != NULL) { oldwin = curwin; } - old_curbuf = curbuf; + set_bufref(&old_curbuf, curbuf); } if (buf == NULL) goto theend; - if (buf->b_ml.ml_mfp == NULL) { /* no memfile yet */ - oldbuf = FALSE; - } else { /* existing memfile */ - oldbuf = TRUE; - (void)buf_check_timestamp(buf, FALSE); - /* Check if autocommands made buffer invalid or changed the current - * buffer. */ - if (!buf_valid(buf) - || curbuf != old_curbuf - ) + if (buf->b_ml.ml_mfp == NULL) { + // No memfile yet. + oldbuf = false; + } else { + // Existing memfile. + oldbuf = true; + set_bufref(&bufref, buf); + (void)buf_check_timestamp(buf, false); + // Check if autocommands made buffer invalid or changed the current + // buffer. + if (!bufref_valid(&bufref) || curbuf != old_curbuf.br_buf) { goto theend; - if (aborting()) /* autocmds may abort script processing */ + } + if (aborting()) { + // Autocmds may abort script processing. goto theend; + } } /* May jump to last used line number for a loaded buffer or when asked @@ -2255,12 +2266,14 @@ int do_ecmd( * - If we ended up in the new buffer already, need to skip a few * things, set auto_buf. */ - if (buf->b_fname != NULL) + if (buf->b_fname != NULL) { new_name = vim_strsave(buf->b_fname); - au_new_curbuf = buf; - apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, FALSE, curbuf); - if (!buf_valid(buf)) { /* new buffer has been deleted */ - delbuf_msg(new_name); /* frees new_name */ + } + set_bufref(&au_new_curbuf, buf); + apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, false, curbuf); + if (!bufref_valid(&au_new_curbuf)) { + // New buffer has been deleted. + delbuf_msg(new_name); // Frees new_name. goto theend; } if (aborting()) { /* autocmds may abort script processing */ @@ -2272,29 +2285,34 @@ int do_ecmd( } else { win_T *the_curwin = curwin; - // Set the w_closing flag to avoid that autocommands close the window. + // Set w_closing to avoid that autocommands close the window. + // Set b_locked for the same reason. the_curwin->w_closing = true; - if (curbuf == old_curbuf) { + buf->b_locked++; + + if (curbuf == old_curbuf.br_buf) { buf_copy_options(buf, BCO_ENTER); } // Close the link to the current buffer. This will set - // curwin->w_buffer to NULL. + // oldwin->w_buffer to NULL. u_sync(false); close_buffer(oldwin, curbuf, (flags & ECMD_HIDE) || curbuf->terminal ? 0 : DOBUF_UNLOAD, false); the_curwin->w_closing = false; + buf->b_locked--; // autocmds may abort script processing if (aborting() && curwin->w_buffer != NULL) { xfree(new_name); goto theend; } - /* Be careful again, like above. */ - if (!buf_valid(buf)) { /* new buffer has been deleted */ - delbuf_msg(new_name); /* frees new_name */ + // Be careful again, like above. + if (!bufref_valid(&au_new_curbuf)) { + // New buffer has been deleted. + delbuf_msg(new_name); // Frees new_name. goto theend; } if (buf == curbuf) { // already in new buffer @@ -2327,7 +2345,8 @@ int do_ecmd( } xfree(new_name); - au_new_curbuf = NULL; + au_new_curbuf.br_buf = NULL; + au_new_curbuf.br_buf_free_count = 0; } curwin->w_pcmark.lnum = 1; @@ -2380,10 +2399,12 @@ int do_ecmd( solcol = curwin->w_cursor.col; } buf = curbuf; - if (buf->b_fname != NULL) + if (buf->b_fname != NULL) { new_name = vim_strsave(buf->b_fname); - else + } else { new_name = NULL; + } + set_bufref(&bufref, buf); if (p_ur < 0 || curbuf->b_ml.ml_line_count <= p_ur) { /* Save all the text, so that the reload can be undone. * Sync first so that this is a separate undo-able action. */ @@ -2396,14 +2417,15 @@ int do_ecmd( u_unchanged(curbuf); buf_freeall(curbuf, BFA_KEEP_UNDO); - /* tell readfile() not to clear or reload undo info */ + // Tell readfile() not to clear or reload undo info. readfile_flags = READ_KEEP_UNDO; - } else - buf_freeall(curbuf, 0); /* free all things for buffer */ - /* If autocommands deleted the buffer we were going to re-edit, give - * up and jump to the end. */ - if (!buf_valid(buf)) { - delbuf_msg(new_name); /* frees new_name */ + } else { + buf_freeall(curbuf, 0); // Free all things for buffer. + } + // If autocommands deleted the buffer we were going to re-edit, give + // up and jump to the end. + if (!bufref_valid(&bufref)) { + delbuf_msg(new_name); // Frees new_name. goto theend; } xfree(new_name); @@ -2428,11 +2450,6 @@ int do_ecmd( retval = OK; /* - * Reset cursor position, could be used by autocommands. - */ - check_cursor(); - - /* * Check if we are editing the w_arg_idx file in the argument list. */ check_arg_idx(curwin); @@ -2474,7 +2491,7 @@ int do_ecmd( if (swap_exists_action == SEA_QUIT) retval = FAIL; - handle_swap_exists(old_curbuf); + handle_swap_exists(&old_curbuf); } else { /* Read the modelines, but only to set window-local options. Any * buffer-local options have already been set and may have been @@ -2609,7 +2626,8 @@ static void delbuf_msg(char_u *name) EMSG2(_("E143: Autocommands unexpectedly deleted new buffer %s"), name == NULL ? (char_u *)"" : name); xfree(name); - au_new_curbuf = NULL; + au_new_curbuf.br_buf = NULL; + au_new_curbuf.br_buf_free_count = 0; } static int append_indent = 0; /* autoindent for first line */ @@ -2784,16 +2802,18 @@ void ex_z(exarg_T *eap) int j; linenr_T lnum = eap->line2; - /* Vi compatible: ":z!" uses display height, without a count uses - * 'scroll' */ - if (eap->forceit) + // Vi compatible: ":z!" uses display height, without a count uses + // 'scroll' + if (eap->forceit) { bigness = curwin->w_height; - else if (firstwin == lastwin) + } else if (ONE_WINDOW) { bigness = curwin->w_p_scr * 2; - else + } else { bigness = curwin->w_height - 3; - if (bigness < 1) + } + if (bigness < 1) { bigness = 1; + } x = eap->arg; kind = x; @@ -2862,8 +2882,11 @@ void ex_z(exarg_T *eap) if (end > curbuf->b_ml.ml_line_count) end = curbuf->b_ml.ml_line_count; - if (curs > curbuf->b_ml.ml_line_count) + if (curs > curbuf->b_ml.ml_line_count) { curs = curbuf->b_ml.ml_line_count; + } else if (curs < 1) { + curs = 1; + } for (i = start; i <= end; i++) { if (minus && i == lnum) { @@ -2883,8 +2906,11 @@ void ex_z(exarg_T *eap) } } - curwin->w_cursor.lnum = curs; - ex_no_reprint = TRUE; + if (curwin->w_cursor.lnum != curs) { + curwin->w_cursor.lnum = curs; + curwin->w_cursor.col = 0; + } + ex_no_reprint = true; } /* @@ -2946,7 +2972,7 @@ void sub_set_replacement(SubReplacementString sub) { xfree(old_sub.sub); if (sub.additional_elements != old_sub.additional_elements) { - list_unref(old_sub.additional_elements); + tv_list_unref(old_sub.additional_elements); } old_sub = sub; } @@ -3308,7 +3334,8 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout) // Check for a match on each line. linenr_T line2 = eap->line2; for (linenr_T lnum = eap->line1; - lnum <= line2 && !(got_quit || aborting()); + lnum <= line2 && !(got_quit || aborting()) + && (!preview || matched_lines.size <= (size_t)p_cwh); lnum++) { long nmatch = vim_regexec_multi(®match, curwin, curbuf, lnum, (colnr_T)0, NULL); @@ -3473,6 +3500,10 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout) setmouse(); /* disable mouse in xterm */ curwin->w_cursor.col = regmatch.startpos[0].col; + if (curwin->w_p_crb) { + do_check_cursorbind(); + } + /* When 'cpoptions' contains "u" don't sync undo when * asking for confirmation. */ if (vim_strchr(p_cpo, CPO_UNDO) != NULL) @@ -3565,11 +3596,9 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout) ui_cursor_goto(msg_row, msg_col); RedrawingDisabled = temp; - ++no_mapping; /* don't map this key */ - ++allow_keys; /* allow special keys */ + no_mapping++; // don't map this key typed = plain_vgetc(); - --allow_keys; - --no_mapping; + no_mapping--; /* clear the question */ msg_didout = FALSE; /* don't scroll up */ @@ -3736,7 +3765,7 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout) *p1 = NUL; // truncate up to the CR ml_append(lnum - 1, new_start, (colnr_T)(p1 - new_start + 1), false); - mark_adjust(lnum + 1, (linenr_T)MAXLNUM, 1L, 0L); + mark_adjust(lnum + 1, (linenr_T)MAXLNUM, 1L, 0L, false); if (subflags.do_ask) { appended_lines(lnum - 1, 1L); } else { @@ -3825,7 +3854,7 @@ skip: for (i = 0; i < nmatch_tl; ++i) ml_delete(lnum, (int)FALSE); mark_adjust(lnum, lnum + nmatch_tl - 1, - (long)MAXLNUM, -nmatch_tl); + (long)MAXLNUM, -nmatch_tl, false); if (subflags.do_ask) { deleted_lines(lnum, nmatch_tl); } @@ -4345,19 +4374,22 @@ void ex_help(exarg_T *eap) if (!curwin->w_buffer->b_help || cmdmod.tab != 0 ) { - if (cmdmod.tab != 0) + if (cmdmod.tab != 0) { wp = NULL; - else - for (wp = firstwin; wp != NULL; wp = wp->w_next) - if (wp->w_buffer != NULL && wp->w_buffer->b_help) + } else { + wp = NULL; + FOR_ALL_WINDOWS_IN_TAB(wp2, curtab) { + if (wp2->w_buffer != NULL && wp2->w_buffer->b_help) { + wp = wp2; break; - if (wp != NULL && wp->w_buffer->b_nwindows > 0) + } + } + } + if (wp != NULL && wp->w_buffer->b_nwindows > 0) { win_enter(wp, true); - else { - /* - * There is no help window yet. - * Try to open the file specified by the "helpfile" option. - */ + } else { + // There is no help window yet. + // Try to open the file specified by the "helpfile" option. if ((helpfd = mch_fopen((char *)p_hf, READBIN)) == NULL) { smsg(_("Sorry, help file \"%s\" not found"), p_hf); goto erret; @@ -4751,8 +4783,8 @@ void fix_help_buffer(void) char_u *p; char_u *rt; - /* set filetype to "help". */ - set_option_value((char_u *)"ft", 0L, (char_u *)"help", OPT_LOCAL); + // Set filetype to "help". + set_option_value("ft", 0L, "help", OPT_LOCAL); if (!syntax_present(curwin)) { for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count; ++lnum) { @@ -4814,9 +4846,13 @@ void fix_help_buffer(void) vimconv_T vc; char_u *cp; - /* Find all "doc/ *.txt" files in this directory. */ - add_pathsep((char *)NameBuff); - STRCAT(NameBuff, "doc/*.??[tx]"); + // Find all "doc/ *.txt" files in this directory. + if (!add_pathsep((char *)NameBuff) + || STRLCAT(NameBuff, "doc/*.??[tx]", + sizeof(NameBuff)) >= MAXPATHL) { + EMSG(_(e_fnametoolong)); + continue; + } // Note: We cannot just do `&NameBuff` because it is a statically sized array // so `NameBuff == &NameBuff` according to C semantics. @@ -4847,8 +4883,9 @@ void fix_help_buffer(void) continue; e1 = vim_strrchr(t1, '.'); e2 = vim_strrchr(path_tail(f2), '.'); - if (e1 == NUL || e2 == NUL) + if (e1 == NULL || e2 == NULL) { continue; + } if (fnamecmp(e1, ".txt") != 0 && fnamecmp(e1, fname + 4) != 0) { /* Not .txt and not .abx, remove it. */ @@ -4979,8 +5016,12 @@ static void helptags_one(char_u *dir, char_u *ext, char_u *tagfname, // Find all *.txt files. size_t dirlen = STRLCPY(NameBuff, dir, sizeof(NameBuff)); - STRCAT(NameBuff, "/**/*"); // NOLINT - STRCAT(NameBuff, ext); + if (dirlen >= MAXPATHL + || STRLCAT(NameBuff, "/**/*", sizeof(NameBuff)) >= MAXPATHL // NOLINT + || STRLCAT(NameBuff, ext, sizeof(NameBuff)) >= MAXPATHL) { + EMSG(_(e_fnametoolong)); + return; + } // Note: We cannot just do `&NameBuff` because it is a statically sized array // so `NameBuff == &NameBuff` according to C semantics. @@ -4988,18 +5029,22 @@ static void helptags_one(char_u *dir, char_u *ext, char_u *tagfname, if (gen_expand_wildcards(1, buff_list, &filecount, &files, EW_FILE|EW_SILENT) == FAIL || filecount == 0) { - if (!got_int) - EMSG2("E151: No match: %s", NameBuff); + if (!got_int) { + EMSG2(_("E151: No match: %s"), NameBuff); + } return; } - /* - * Open the tags file for writing. - * Do this before scanning through all the files. - */ - STRLCPY(NameBuff, dir, sizeof(NameBuff)); - add_pathsep((char *)NameBuff); - STRNCAT(NameBuff, tagfname, sizeof(NameBuff) - dirlen - 2); + // + // Open the tags file for writing. + // Do this before scanning through all the files. + // + memcpy(NameBuff, dir, dirlen + 1); + if (!add_pathsep((char *)NameBuff) + || STRLCAT(NameBuff, tagfname, sizeof(NameBuff)) >= MAXPATHL) { + EMSG(_(e_fnametoolong)); + return; + } fd_tags = mch_fopen((char *)NameBuff, "w"); if (fd_tags == NULL) { EMSG2(_("E152: Cannot open %s for writing"), NameBuff); @@ -5063,14 +5108,13 @@ static void helptags_one(char_u *dir, char_u *ext, char_u *tagfname, } p1 = vim_strchr(IObuff, '*'); /* find first '*' */ while (p1 != NULL) { - /* Use vim_strbyte() instead of vim_strchr() so that when - * 'encoding' is dbcs it still works, don't find '*' in the - * second byte. */ - p2 = vim_strbyte(p1 + 1, '*'); /* find second '*' */ - if (p2 != NULL && p2 > p1 + 1) { /* skip "*" and "**" */ - for (s = p1 + 1; s < p2; ++s) - if (*s == ' ' || *s == '\t' || *s == '|') + p2 = (char_u *)strchr((const char *)p1 + 1, '*'); // Find second '*'. + if (p2 != NULL && p2 > p1 + 1) { // Skip "*" and "**". + for (s = p1 + 1; s < p2; s++) { + if (*s == ' ' || *s == '\t' || *s == '|') { break; + } + } /* * Only accept a *tag* when it consists of valid @@ -5173,8 +5217,12 @@ static void do_helptags(char_u *dirname, bool add_help_tags) // Get a list of all files in the help directory and in subdirectories. STRLCPY(NameBuff, dirname, sizeof(NameBuff)); - add_pathsep((char *)NameBuff); - STRCAT(NameBuff, "**"); + if (!add_pathsep((char *)NameBuff) + || STRLCAT(NameBuff, "**", sizeof(NameBuff)) >= MAXPATHL) { + EMSG(_(e_fnametoolong)); + xfree(dirname); + return; + } // Note: We cannot just do `&NameBuff` because it is a statically sized array // so `NameBuff == &NameBuff` according to C semantics. @@ -5182,7 +5230,7 @@ static void do_helptags(char_u *dirname, bool add_help_tags) if (gen_expand_wildcards(1, buff_list, &filecount, &files, EW_FILE|EW_SILENT) == FAIL || filecount == 0) { - EMSG2("E151: No match: %s", NameBuff); + EMSG2(_("E151: No match: %s"), NameBuff); xfree(dirname); return; } @@ -5688,33 +5736,33 @@ void ex_sign(exarg_T *eap) */ static void sign_list_defined(sign_T *sp) { - char_u *p; - smsg("sign %s", sp->sn_name); if (sp->sn_icon != NULL) { - MSG_PUTS(" icon="); + msg_puts(" icon="); msg_outtrans(sp->sn_icon); - MSG_PUTS(_(" (not supported)")); + msg_puts(_(" (not supported)")); } if (sp->sn_text != NULL) { - MSG_PUTS(" text="); + msg_puts(" text="); msg_outtrans(sp->sn_text); } if (sp->sn_line_hl > 0) { - MSG_PUTS(" linehl="); - p = get_highlight_name(NULL, sp->sn_line_hl - 1); - if (p == NULL) - MSG_PUTS("NONE"); - else + msg_puts(" linehl="); + const char *const p = get_highlight_name(NULL, sp->sn_line_hl - 1); + if (p == NULL) { + msg_puts("NONE"); + } else { msg_puts(p); + } } if (sp->sn_text_hl > 0) { - MSG_PUTS(" texthl="); - p = get_highlight_name(NULL, sp->sn_text_hl - 1); - if (p == NULL) - MSG_PUTS("NONE"); - else + msg_puts(" texthl="); + const char *const p = get_highlight_name(NULL, sp->sn_text_hl - 1); + if (p == NULL) { + msg_puts("NONE"); + } else { msg_puts(p); + } } } @@ -5908,9 +5956,8 @@ void set_context_in_sign_cmd(expand_T *xp, char_u *arg) // :sign define {name} {args}... {last}= // | | // last p - if (p == NUL) - { - /* Expand last argument name (before equal sign). */ + if (p == NULL) { + // Expand last argument name (before equal sign). xp->xp_pattern = last; switch (cmd_idx) { @@ -6093,7 +6140,6 @@ void ex_substitute(exarg_T *eap) int save_w_p_cul = curwin->w_p_cul; int save_w_p_cuc = curwin->w_p_cuc; - emsg_off++; // No error messages during command preview. curbuf->b_p_ul = LONG_MAX; // make sure we can undo all changes curwin->w_p_cul = false; // Disable 'cursorline' curwin->w_p_cuc = false; // Disable 'cursorcolumn' @@ -6107,7 +6153,7 @@ void ex_substitute(exarg_T *eap) // restore it so that undotree() is identical before/after the preview. curbuf->b_u_newhead = save_b_u_newhead; curbuf->b_u_time_cur = save_b_u_time_cur; - curbuf->b_changedtick = save_changedtick; + buf_set_changedtick(curbuf, save_changedtick); } if (buf_valid(preview_buf)) { // XXX: Must do this *after* u_undo_and_forget(), why? @@ -6120,6 +6166,105 @@ void ex_substitute(exarg_T *eap) restore_search_patterns(); win_size_restore(&save_view); ga_clear(&save_view); - emsg_off--; unblock_autocmds(); } + +/// Skip over the pattern argument of ":vimgrep /pat/[g][j]". +/// Put the start of the pattern in "*s", unless "s" is NULL. +/// If "flags" is not NULL put the flags in it: VGR_GLOBAL, VGR_NOJUMP. +/// If "s" is not NULL terminate the pattern with a NUL. +/// Return a pointer to the char just past the pattern plus flags. +char_u *skip_vimgrep_pat(char_u *p, char_u **s, int *flags) +{ + int c; + + if (vim_isIDc(*p)) { + // ":vimgrep pattern fname" + if (s != NULL) { + *s = p; + } + p = skiptowhite(p); + if (s != NULL && *p != NUL) { + *p++ = NUL; + } + } else { + // ":vimgrep /pattern/[g][j] fname" + if (s != NULL) { + *s = p + 1; + } + c = *p; + p = skip_regexp(p + 1, c, true, NULL); + if (*p != c) { + return NULL; + } + + // Truncate the pattern. + if (s != NULL) { + *p = NUL; + } + p++; + + // Find the flags + while (*p == 'g' || *p == 'j') { + if (flags != NULL) { + if (*p == 'g') { + *flags |= VGR_GLOBAL; + } else { + *flags |= VGR_NOJUMP; + } + } + p++; + } + } + return p; +} + +/// List v:oldfiles in a nice way. +void ex_oldfiles(exarg_T *eap) +{ + list_T *l = get_vim_var_list(VV_OLDFILES); + listitem_T *li; + long nr = 0; + + if (l == NULL) { + msg((char_u *)_("No old files")); + } else { + msg_start(); + msg_scroll = true; + for (li = l->lv_first; li != NULL && !got_int; li = li->li_next) { + nr++; + const char *fname = tv_get_string(&li->li_tv); + if (!message_filtered((char_u *)fname)) { + msg_outnum(nr); + MSG_PUTS(": "); + msg_outtrans((char_u *)tv_get_string(&li->li_tv)); + msg_clr_eos(); + msg_putchar('\n'); + ui_flush(); // output one line at a time + os_breakcheck(); + } + } + + // Assume "got_int" was set to truncate the listing. + got_int = false; + + // File selection prompt on ":browse oldfiles" + if (cmdmod.browse) { + quit_more = false; + nr = prompt_for_number(false); + msg_starthere(); + if (nr > 0 && nr <= l->lv_len) { + const char *const p = tv_list_find_str(l, nr - 1); + if (p == NULL) { + return; + } + char *const s = (char *)expand_env_save((char_u *)p); + eap->arg = (char_u *)s; + eap->cmdidx = CMD_edit; + cmdmod.browse = false; + do_exedit(eap, NULL); + xfree(s); + } + } + } +} diff --git a/src/nvim/ex_cmds.h b/src/nvim/ex_cmds.h index 243b11255e..b564cde56c 100644 --- a/src/nvim/ex_cmds.h +++ b/src/nvim/ex_cmds.h @@ -4,8 +4,10 @@ #include <stdbool.h> #include "nvim/os/time.h" -#include "nvim/eval_defs.h" #include "nvim/pos.h" +#include "nvim/eval/typval.h" +#include "nvim/buffer_defs.h" +#include "nvim/ex_cmds_defs.h" // flags for do_ecmd() #define ECMD_HIDE 0x01 // don't free the current buffer diff --git a/src/nvim/ex_cmds.lua b/src/nvim/ex_cmds.lua index 88095602ba..5a578cd088 100644 --- a/src/nvim/ex_cmds.lua +++ b/src/nvim/ex_cmds.lua @@ -1,4 +1,4 @@ -bit = require 'bit' +local bit = require 'bit' -- Description of the values below is contained in ex_cmds_defs.h file. local RANGE = 0x001 @@ -34,7 +34,8 @@ local ADDR_ARGUMENTS = 2 local ADDR_LOADED_BUFFERS = 3 local ADDR_BUFFERS = 4 local ADDR_TABS = 5 -local ADDR_QUICKFIX = 6 +local ADDR_TABS_RELATIVE = 6 +local ADDR_QUICKFIX = 7 local ADDR_OTHER = 99 -- The following table is described in ex_cmds_defs.h file. @@ -462,6 +463,12 @@ return { func='ex_checktime', }, { + command='chistory', + flags=bit.bor(TRLBAR), + addr_type=ADDR_LINES, + func='qf_history', + }, + { command='clist', flags=bit.bor(BANG, EXTRA, TRLBAR, CMDWIN), addr_type=ADDR_LINES, @@ -621,13 +628,13 @@ return { command='cscope', flags=bit.bor(EXTRA, NOTRLCOM, XFILE), addr_type=ADDR_LINES, - func='do_cscope', + func='ex_cscope', }, { command='cstag', flags=bit.bor(BANG, TRLBAR, WORD1), addr_type=ADDR_LINES, - func='do_cstag', + func='ex_cstag', }, { command='cunmap', @@ -924,6 +931,12 @@ return { func='ex_filetype', }, { + command='filter', + flags=bit.bor(BANG, NEEDARG, EXTRA, NOTRLCOM), + addr_type=ADDR_LINES, + func='ex_wrongmodifier', + }, + { command='find', flags=bit.bor(RANGE, NOTADR, BANG, FILE1, EDITCMD, ARGOPT, TRLBAR), addr_type=ADDR_LINES, @@ -1063,7 +1076,7 @@ return { }, { command='hide', - flags=bit.bor(BANG, RANGE, NOTADR, COUNT, EXTRA, NOTRLCOM), + flags=bit.bor(BANG, RANGE, NOTADR, COUNT, EXTRA, TRLBAR), addr_type=ADDR_WINDOWS, func='ex_hide', }, @@ -1311,7 +1324,7 @@ return { command='lcscope', flags=bit.bor(EXTRA, NOTRLCOM, XFILE), addr_type=ADDR_LINES, - func='do_cscope', + func='ex_cscope', }, { command='ldo', @@ -1400,6 +1413,12 @@ return { func='ex_helpgrep', }, { + command='lhistory', + flags=bit.bor(TRLBAR), + addr_type=ADDR_LINES, + func='qf_history', + }, + { command='ll', flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR, BANG), addr_type=ADDR_LINES, @@ -1529,19 +1548,19 @@ return { command='lua', flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN), addr_type=ADDR_LINES, - func='ex_script_ni', + func='ex_lua', }, { command='luado', flags=bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN), addr_type=ADDR_LINES, - func='ex_ni', + func='ex_luado', }, { command='luafile', flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN), addr_type=ADDR_LINES, - func='ex_ni', + func='ex_luafile', }, { command='lvimgrep', @@ -2315,7 +2334,7 @@ return { command='scscope', flags=bit.bor(EXTRA, NOTRLCOM), addr_type=ADDR_LINES, - func='do_scscope', + func='ex_scscope', }, { command='set', @@ -2638,12 +2657,12 @@ return { { command='tab', flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM), - addr_type=ADDR_LINES, + addr_type=ADDR_TABS, func='ex_wrongmodifier', }, { command='tabclose', - flags=bit.bor(RANGE, NOTADR, COUNT, BANG, TRLBAR, CMDWIN), + flags=bit.bor(BANG, RANGE, NOTADR, ZEROR, EXTRA, NOSPC, TRLBAR, CMDWIN), addr_type=ADDR_TABS, func='ex_tabclose', }, @@ -2668,7 +2687,7 @@ return { { command='tabfirst', flags=bit.bor(TRLBAR), - addr_type=ADDR_LINES, + addr_type=ADDR_TABS, func='ex_tabnext', }, { @@ -2680,13 +2699,13 @@ return { { command='tablast', flags=bit.bor(TRLBAR), - addr_type=ADDR_LINES, + addr_type=ADDR_TABS, func='ex_tabnext', }, { command='tabnext', - flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR), - addr_type=ADDR_LINES, + flags=bit.bor(RANGE, NOTADR, ZEROR, EXTRA, NOSPC, TRLBAR), + addr_type=ADDR_TABS, func='ex_tabnext', }, { @@ -2697,32 +2716,32 @@ return { }, { command='tabonly', - flags=bit.bor(BANG, RANGE, NOTADR, TRLBAR, CMDWIN), + flags=bit.bor(BANG, RANGE, NOTADR, ZEROR, EXTRA, NOSPC, TRLBAR, CMDWIN), addr_type=ADDR_TABS, func='ex_tabonly', }, { command='tabprevious', - flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR), - addr_type=ADDR_LINES, + flags=bit.bor(RANGE, NOTADR, ZEROR, EXTRA, NOSPC, TRLBAR), + addr_type=ADDR_TABS_RELATIVE, func='ex_tabnext', }, { command='tabNext', - flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR), - addr_type=ADDR_LINES, + flags=bit.bor(RANGE, NOTADR, ZEROR, EXTRA, NOSPC, TRLBAR), + addr_type=ADDR_TABS_RELATIVE, func='ex_tabnext', }, { command='tabrewind', flags=bit.bor(TRLBAR), - addr_type=ADDR_LINES, + addr_type=ADDR_TABS, func='ex_tabnext', }, { command='tabs', flags=bit.bor(TRLBAR, CMDWIN), - addr_type=ADDR_LINES, + addr_type=ADDR_TABS, func='ex_tabs', }, { diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c index 3b92b3734a..371f7b3bce 100644 --- a/src/nvim/ex_cmds2.c +++ b/src/nvim/ex_cmds2.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + /// @file ex_cmds2.c /// /// Some more functions for command line commands @@ -186,7 +189,8 @@ void do_debug(char_u *cmd) } xfree(cmdline); - cmdline = getcmdline_prompt('>', NULL, 0, EXPAND_NOTHING, NULL); + cmdline = (char_u *)getcmdline_prompt('>', NULL, 0, EXPAND_NOTHING, NULL, + CALLBACK_NONE); if (typeahead_saved) { restore_typeahead(&typeaheadbuf); @@ -957,23 +961,21 @@ char_u *get_profile_name(expand_T *xp, int idx) } /// Handle command line completion for :profile command. -void set_context_in_profile_cmd(expand_T *xp, char_u *arg) +void set_context_in_profile_cmd(expand_T *xp, const char *arg) { - char_u *end_subcmd; - // Default: expand subcommands. xp->xp_context = EXPAND_PROFILE; pexpand_what = PEXP_SUBCMD; - xp->xp_pattern = arg; + xp->xp_pattern = (char_u *)arg; - end_subcmd = skiptowhite(arg); + char_u *const end_subcmd = skiptowhite((const char_u *)arg); if (*end_subcmd == NUL) { return; } - if (end_subcmd - arg == 5 && STRNCMP(arg, "start", 5) == 0) { + if ((const char *)end_subcmd - arg == 5 && strncmp(arg, "start", 5) == 0) { xp->xp_context = EXPAND_FILES; - xp->xp_pattern = skipwhite(end_subcmd); + xp->xp_pattern = skipwhite((const char_u *)end_subcmd); return; } @@ -1181,6 +1183,7 @@ bool prof_def_func(void) int autowrite(buf_T *buf, int forceit) { int r; + bufref_T bufref; if (!(p_aw || p_awa) || !p_write // never autowrite a "nofile" or "nowrite" buffer @@ -1188,11 +1191,12 @@ int autowrite(buf_T *buf, int forceit) || (!forceit && buf->b_p_ro) || buf->b_ffname == NULL) { return FAIL; } + set_bufref(&bufref, buf); r = buf_write_all(buf, forceit); // Writing may succeed but the buffer still changed, e.g., when there is a // conversion error. We do want to return FAIL then. - if (buf_valid(buf) && bufIsChanged(buf)) { + if (bufref_valid(&bufref) && bufIsChanged(buf)) { r = FAIL; } return r; @@ -1207,9 +1211,11 @@ void autowrite_all(void) FOR_ALL_BUFFERS(buf) { if (bufIsChanged(buf) && !buf->b_p_ro) { + bufref_T bufref; + set_bufref(&bufref, buf); (void)buf_write_all(buf, false); // an autocommand may have deleted the buffer - if (!buf_valid(buf)) { + if (!bufref_valid(&bufref)) { buf = firstbuf; } } @@ -1221,6 +1227,8 @@ void autowrite_all(void) bool check_changed(buf_T *buf, int flags) { int forceit = (flags & CCGD_FORCEIT); + bufref_T bufref; + set_bufref(&bufref, buf); if (!forceit && bufIsChanged(buf) @@ -1236,12 +1244,12 @@ bool check_changed(buf_T *buf, int flags) } } } - if (!buf_valid(buf)) { + if (!bufref_valid(&bufref)) { // Autocommand deleted buffer, oops! It's not changed now. return false; } dialog_changed(buf, count > 1); - if (!buf_valid(buf)) { + if (!bufref_valid(&bufref)) { // Autocommand deleted buffer, oops! It's not changed now. return false; } @@ -1300,9 +1308,10 @@ void dialog_changed(buf_T *buf, int checkall) // Skip readonly buffers, these need to be confirmed // individually. FOR_ALL_BUFFERS(buf2) { - if (bufIsChanged(buf2) - && (buf2->b_ffname != NULL) - && !buf2->b_p_ro) { + if (bufIsChanged(buf2) && (buf2->b_ffname != NULL) && !buf2->b_p_ro) { + bufref_T bufref; + set_bufref(&bufref, buf2); + if (buf2->b_fname != NULL && check_overwrite(&ea, buf2, buf2->b_fname, buf2->b_ffname, false) == OK) { @@ -1310,7 +1319,7 @@ void dialog_changed(buf_T *buf, int checkall) (void)buf_write_all(buf2, false); } // an autocommand may have deleted the buffer - if (!buf_valid(buf2)) { + if (!bufref_valid(&bufref)) { buf2 = firstbuf; } } @@ -1407,11 +1416,14 @@ bool check_changed_any(bool hidden, bool unload) continue; } if ((!hidden || buf->b_nwindows == 0) && bufIsChanged(buf)) { + bufref_T bufref; + set_bufref(&bufref, buf); + // Try auto-writing the buffer. If this fails but the buffer no // longer exists it's not changed, that's OK. if (check_changed(buf, (p_awa ? CCGD_AW : 0) | CCGD_MULTWIN - | CCGD_ALLBUF) && buf_valid(buf)) { + | CCGD_ALLBUF) && bufref_valid(&bufref)) { break; // didn't save - still changes } } @@ -1447,9 +1459,11 @@ bool check_changed_any(bool hidden, bool unload) if (buf != curbuf) { FOR_ALL_TAB_WINDOWS(tp, wp) { if (wp->w_buffer == buf) { + bufref_T bufref; + set_bufref(&bufref, buf); goto_tabpage_win(tp, wp); // Paranoia: did autocmds wipe out the buffer with changes? - if (!buf_valid(buf)) { + if (!bufref_valid(&bufref)) { goto theend; } goto buf_found; @@ -2061,9 +2075,9 @@ void ex_listdo(exarg_T *eap) // Clear 'shm' to avoid that the file message overwrites // any output from the command. p_shm_save = vim_strsave(p_shm); - set_option_value((char_u *)"shm", 0L, (char_u *)"", 0); + set_option_value("shm", 0L, "", 0); do_argfile(eap, i); - set_option_value((char_u *)"shm", 0L, p_shm_save, 0); + set_option_value("shm", 0L, (char *)p_shm_save, 0); xfree(p_shm_save); } if (curwin->w_arg_idx != i) { @@ -2126,9 +2140,9 @@ void ex_listdo(exarg_T *eap) // Go to the next buffer. Clear 'shm' to avoid that the file // message overwrites any output from the command. p_shm_save = vim_strsave(p_shm); - set_option_value((char_u *)"shm", 0L, (char_u *)"", 0); + set_option_value("shm", 0L, "", 0); goto_buffer(eap, DOBUF_FIRST, FORWARD, next_fnum); - set_option_value((char_u *)"shm", 0L, p_shm_save, 0); + set_option_value("shm", 0L, (char *)p_shm_save, 0); xfree(p_shm_save); // If autocommands took us elsewhere, quit here. @@ -2238,14 +2252,14 @@ void ex_compiler(exarg_T *eap) // plugin will then skip the settings. Afterwards set // "b:current_compiler" and restore "current_compiler". // Explicitly prepend "g:" to make it work in a function. - old_cur_comp = get_var_value((char_u *)"g:current_compiler"); + old_cur_comp = get_var_value("g:current_compiler"); if (old_cur_comp != NULL) { old_cur_comp = vim_strsave(old_cur_comp); } do_cmdline_cmd("command -nargs=* CompilerSet setlocal <args>"); } - do_unlet((char_u *)"g:current_compiler", true); - do_unlet((char_u *)"b:current_compiler", true); + do_unlet(S_LEN("g:current_compiler"), true); + do_unlet(S_LEN("b:current_compiler"), true); snprintf((char *)buf, bufsize, "compiler/%s.vim", eap->arg); if (source_runtime(buf, DIP_ALL) == FAIL) { @@ -2256,7 +2270,7 @@ void ex_compiler(exarg_T *eap) do_cmdline_cmd(":delcommand CompilerSet"); // Set "b:current_compiler" from "current_compiler". - p = get_var_value((char_u *)"g:current_compiler"); + p = get_var_value("g:current_compiler"); if (p != NULL) { set_internal_string_var((char_u *)"b:current_compiler", p); } @@ -2268,7 +2282,7 @@ void ex_compiler(exarg_T *eap) old_cur_comp); xfree(old_cur_comp); } else { - do_unlet((char_u *)"g:current_compiler", true); + do_unlet(S_LEN("g:current_compiler"), true); } } } @@ -2305,16 +2319,6 @@ static void source_callback(char_u *fname, void *cookie) (void)do_source(fname, false, DOSO_NONE); } -/// Source the file "name" from all directories in 'runtimepath'. -/// "name" can contain wildcards. -/// When "flags" has DIP_ALL: source all files, otherwise only the first one. -/// -/// return FAIL when no file could be sourced, OK otherwise. -int source_runtime(char_u *name, int flags) -{ - return do_in_runtimepath(name, flags, source_callback, NULL); -} - /// Find the file "name" in all directories in "path" and invoke /// "callback(fname, cookie)". /// "name" can contain wildcards. @@ -2349,12 +2353,25 @@ int do_in_path(char_u *path, char_u *name, int flags, while (*rtp != NUL && ((flags & DIP_ALL) || !did_one)) { // Copy the path from 'runtimepath' to buf[]. copy_option_part(&rtp, buf, MAXPATHL, ","); + size_t buflen = STRLEN(buf); + + // Skip after or non-after directories. + if (flags & (DIP_NOAFTER | DIP_AFTER)) { + bool is_after = buflen >= 5 + && STRCMP(buf + buflen - 5, "after") == 0; + + if ((is_after && (flags & DIP_NOAFTER)) + || (!is_after && (flags & DIP_AFTER))) { + continue; + } + } + if (name == NULL) { (*callback)(buf, (void *)&cookie); if (!did_one) { did_one = (cookie == NULL); } - } else if (STRLEN(buf) + STRLEN(name) + 2 < MAXPATHL) { + } else if (buflen + STRLEN(name) + 2 < MAXPATHL) { add_pathsep((char *)buf); tail = buf + STRLEN(buf); @@ -2407,21 +2424,21 @@ int do_in_path(char_u *path, char_u *name, int flags, return did_one ? OK : FAIL; } -/// Find "name" in 'runtimepath'. When found, invoke the callback function for +/// Find "name" in "path". When found, invoke the callback function for /// it: callback(fname, "cookie") /// When "flags" has DIP_ALL repeat for all matches, otherwise only the first /// one is used. /// Returns OK when at least one match found, FAIL otherwise. -/// If "name" is NULL calls callback for each entry in runtimepath. Cookie is +/// If "name" is NULL calls callback for each entry in "path". Cookie is /// passed by reference in this case, setting it to NULL indicates that callback /// has done its job. -int do_in_runtimepath(char_u *name, int flags, DoInRuntimepathCB callback, - void *cookie) +int do_in_path_and_pp(char_u *path, char_u *name, int flags, + DoInRuntimepathCB callback, void *cookie) { int done = FAIL; if ((flags & DIP_NORTP) == 0) { - done = do_in_path(p_rtp, name, flags, callback, cookie); + done = do_in_path(path, name, flags, callback, cookie); } if ((done == FAIL || (flags & DIP_ALL)) && (flags & DIP_START)) { @@ -2449,6 +2466,29 @@ int do_in_runtimepath(char_u *name, int flags, DoInRuntimepathCB callback, return done; } +/// Just like do_in_path_and_pp(), using 'runtimepath' for "path". +int do_in_runtimepath(char_u *name, int flags, DoInRuntimepathCB callback, + void *cookie) +{ + return do_in_path_and_pp(p_rtp, name, flags, callback, cookie); +} + +/// Source the file "name" from all directories in 'runtimepath'. +/// "name" can contain wildcards. +/// When "flags" has DIP_ALL: source all files, otherwise only the first one. +/// +/// return FAIL when no file could be sourced, OK otherwise. +int source_runtime(char_u *name, int flags) +{ + return source_in_path(p_rtp, name, flags); +} + +/// Just like source_runtime(), but use "path" instead of 'runtimepath'. +int source_in_path(char_u *path, char_u *name, int flags) +{ + return do_in_path_and_pp(path, name, flags, source_callback, NULL); +} + // Expand wildcards in "pat" and invoke do_source() for each match. static void source_all_matches(char_u *pat) { @@ -2471,16 +2511,17 @@ static int APP_BOTH; static void add_pack_plugin(char_u *fname, void *cookie) { char_u *p4, *p3, *p2, *p1, *p; - char_u *new_rtp; - char_u *ffname = (char_u *)fix_fname((char *)fname); + char_u *buf = NULL; + + char *const ffname = fix_fname((char *)fname); if (ffname == NULL) { return; } - if (cookie != &APP_LOAD && strstr((char *)p_rtp, (char *)ffname) == NULL) { + if (cookie != &APP_LOAD && strstr((char *)p_rtp, ffname) == NULL) { // directory is not yet in 'runtimepath', add it - p4 = p3 = p2 = p1 = get_past_head(ffname); + p4 = p3 = p2 = p1 = get_past_head((char_u *)ffname); for (p = p1; *p; mb_ptr_adv(p)) { if (vim_ispathsep_nocolon(*p)) { p4 = p3; p3 = p2; p2 = p1; p1 = p; @@ -2496,57 +2537,70 @@ static void add_pack_plugin(char_u *fname, void *cookie) *p4 = NUL; // Find "ffname" in "p_rtp", ignoring '/' vs '\' differences - size_t fname_len = STRLEN(ffname); - char_u *insp = p_rtp; - for (;;) { - if (vim_fnamencmp(insp, ffname, fname_len) == 0) { - break; + size_t fname_len = strlen(ffname); + const char *insp = (const char *)p_rtp; + buf = try_malloc(MAXPATHL); + if (buf == NULL) { + goto theend; + } + while (*insp != NUL) { + copy_option_part((char_u **)&insp, buf, MAXPATHL, ","); + add_pathsep((char *)buf); + char *const rtp_ffname = fix_fname((char *)buf); + if (rtp_ffname == NULL) { + goto theend; } - insp = vim_strchr(insp, ','); - if (insp == NULL) { + bool match = path_fnamencmp(rtp_ffname, ffname, fname_len) == 0; + xfree(rtp_ffname); + if (match) { break; } - insp++; } - if (insp == NULL) { + if (*insp == NUL) { // not found, append at the end - insp = p_rtp + STRLEN(p_rtp); + insp = (const char *)p_rtp + STRLEN(p_rtp); } else { // append after the matching directory. - insp += STRLEN(ffname); - while (*insp != NUL && *insp != ',') { - insp++; - } + insp--; } *p4 = c; // check if rtp/pack/name/start/name/after exists - char *afterdir = concat_fnames((char *)ffname, "after", true); + char *afterdir = concat_fnames(ffname, "after", true); size_t afterlen = 0; if (os_isdir((char_u *)afterdir)) { - afterlen = STRLEN(afterdir) + 1; // add one for comma + afterlen = strlen(afterdir) + 1; // add one for comma } - size_t oldlen = STRLEN(p_rtp); - size_t addlen = STRLEN(ffname) + 1; // add one for comma - new_rtp = try_malloc(oldlen + addlen + afterlen + 1); // add one for NUL + const size_t oldlen = STRLEN(p_rtp); + const size_t addlen = strlen(ffname) + 1; // add one for comma + const size_t new_rtp_len = oldlen + addlen + afterlen + 1; + // add one for NUL -------------------------------------^ + char *const new_rtp = try_malloc(new_rtp_len); if (new_rtp == NULL) { goto theend; } - uintptr_t keep = (uintptr_t)(insp - p_rtp); + const size_t keep = (size_t)(insp - (const char *)p_rtp); + size_t new_rtp_fill = 0; memmove(new_rtp, p_rtp, keep); - new_rtp[keep] = ','; - memmove(new_rtp + keep + 1, ffname, addlen); + new_rtp_fill += keep; + new_rtp[new_rtp_fill++] = ','; + memmove(new_rtp + new_rtp_fill, ffname, addlen); + new_rtp_fill += addlen - 1; + assert(new_rtp[new_rtp_fill] == NUL || new_rtp[new_rtp_fill] == ','); if (p_rtp[keep] != NUL) { - memmove(new_rtp + keep + addlen, p_rtp + keep, - oldlen - keep + 1); + memmove(new_rtp + new_rtp_fill, p_rtp + keep, oldlen - keep + 1); + new_rtp_fill += oldlen - keep; } if (afterlen > 0) { - STRCAT(new_rtp, ","); - STRCAT(new_rtp, afterdir); + assert(new_rtp[new_rtp_fill] == NUL); + new_rtp[new_rtp_fill++] = ','; + memmove(new_rtp + new_rtp_fill, afterdir, afterlen - 1); + new_rtp_fill += afterlen - 1; } - set_option_value((char_u *)"rtp", 0L, new_rtp, 0); + new_rtp[new_rtp_fill] = NUL; + set_option_value("rtp", 0L, new_rtp, 0); xfree(new_rtp); xfree(afterdir); } @@ -2555,7 +2609,7 @@ static void add_pack_plugin(char_u *fname, void *cookie) static const char *plugpat = "%s/plugin/**/*.vim"; // NOLINT static const char *ftpat = "%s/ftdetect/*.vim"; // NOLINT - size_t len = STRLEN(ffname) + STRLEN(ftpat); + size_t len = strlen(ffname) + STRLEN(ftpat); char_u *pat = try_malloc(len + 1); if (pat == NULL) { goto theend; @@ -2578,25 +2632,35 @@ static void add_pack_plugin(char_u *fname, void *cookie) } theend: + xfree(buf); xfree(ffname); } -static bool did_source_packages = false; +/// Add all packages in the "start" directory to 'runtimepath'. +void add_pack_start_dirs(void) +{ + do_in_path(p_pp, (char_u *)"pack/*/start/*", DIP_ALL + DIP_DIR, // NOLINT + add_pack_plugin, &APP_ADD_DIR); +} + +/// Load plugins from all packages in the "start" directory. +void load_start_packages(void) +{ + did_source_packages = true; + do_in_path(p_pp, (char_u *)"pack/*/start/*", DIP_ALL + DIP_DIR, // NOLINT + add_pack_plugin, &APP_LOAD); +} // ":packloadall" // Find plugins in the package directories and source them. void ex_packloadall(exarg_T *eap) { - if (!did_source_packages || (eap != NULL && eap->forceit)) { - did_source_packages = true; - + if (!did_source_packages || eap->forceit) { // First do a round to add all directories to 'runtimepath', then load // the plugins. This allows for plugins to use an autoload directory // of another plugin. - do_in_path(p_pp, (char_u *)"pack/*/start/*", DIP_ALL + DIP_DIR, // NOLINT - add_pack_plugin, &APP_ADD_DIR); - do_in_path(p_pp, (char_u *)"pack/*/start/*", DIP_ALL + DIP_DIR, // NOLINT - add_pack_plugin, &APP_LOAD); + add_pack_start_dirs(); + load_start_packages(); } } @@ -2680,14 +2744,7 @@ static FILE *fopen_noinh_readbin(char *filename) return NULL; } -#ifdef HAVE_FD_CLOEXEC - { - int fdflags = fcntl(fd_tmp, F_GETFD); - if (fdflags >= 0 && (fdflags & FD_CLOEXEC) == 0) { - (void)fcntl(fd_tmp, F_SETFD, fdflags | FD_CLOEXEC); - } - } -#endif + (void)os_set_cloexec(fd_tmp); return fdopen(fd_tmp, READBIN); } @@ -3581,18 +3638,11 @@ void ex_language(exarg_T *eap) static char_u **locales = NULL; // Array of all available locales -static bool did_init_locales = false; -/// Lazy initialization of all available locales. -static void init_locales(void) -{ - if (!did_init_locales) { - did_init_locales = true; - locales = find_locales(); - } -} +#ifndef WIN32 +static bool did_init_locales = false; -// Return an array of strings for all available locales + NULL for the +/// Return an array of strings for all available locales + NULL for the /// last element. Return NULL in case of error. static char_u **find_locales(void) { @@ -3624,6 +3674,18 @@ static char_u **find_locales(void) ((char_u **)locales_ga.ga_data)[locales_ga.ga_len] = NULL; return (char_u **)locales_ga.ga_data; } +#endif + +/// Lazy initialization of all available locales. +static void init_locales(void) +{ +#ifndef WIN32 + if (!did_init_locales) { + did_init_locales = true; + locales = find_locales(); + } +#endif +} # if defined(EXITFREE) void free_locales(void) @@ -3676,19 +3738,18 @@ char_u *get_locales(expand_T *xp, int idx) static void script_host_execute(char *name, exarg_T *eap) { - uint8_t *script = script_get(eap, eap->arg); + size_t len; + char *const script = script_get(eap, &len); - if (!eap->skip) { - list_T *args = list_alloc(); + if (script != NULL) { + list_T *const args = tv_list_alloc(); // script - list_append_string(args, script ? script : eap->arg, -1); + tv_list_append_allocated_string(args, script); // current range - list_append_number(args, (int)eap->line1); - list_append_number(args, (int)eap->line2); + tv_list_append_number(args, (int)eap->line1); + tv_list_append_number(args, (int)eap->line2); (void)eval_call_provider(name, "execute", args); } - - xfree(script); } static void script_host_execute_file(char *name, exarg_T *eap) @@ -3696,21 +3757,21 @@ static void script_host_execute_file(char *name, exarg_T *eap) uint8_t buffer[MAXPATHL]; vim_FullName((char *)eap->arg, (char *)buffer, sizeof(buffer), false); - list_T *args = list_alloc(); + list_T *args = tv_list_alloc(); // filename - list_append_string(args, buffer, -1); + tv_list_append_string(args, (const char *)buffer, -1); // current range - list_append_number(args, (int)eap->line1); - list_append_number(args, (int)eap->line2); + tv_list_append_number(args, (int)eap->line1); + tv_list_append_number(args, (int)eap->line2); (void)eval_call_provider(name, "execute_file", args); } static void script_host_do_range(char *name, exarg_T *eap) { - list_T *args = list_alloc(); - list_append_number(args, (int)eap->line1); - list_append_number(args, (int)eap->line2); - list_append_string(args, eap->arg, -1); + list_T *args = tv_list_alloc(); + tv_list_append_number(args, (int)eap->line1); + tv_list_append_number(args, (int)eap->line2); + tv_list_append_string(args, (const char *)eap->arg, -1); (void)eval_call_provider(name, "do_range", args); } diff --git a/src/nvim/ex_cmds_defs.h b/src/nvim/ex_cmds_defs.h index c6389a0c8b..d72b83404e 100644 --- a/src/nvim/ex_cmds_defs.h +++ b/src/nvim/ex_cmds_defs.h @@ -6,6 +6,7 @@ #include "nvim/pos.h" // for linenr_T #include "nvim/normal.h" +#include "nvim/regexp_defs.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "ex_cmds_enum.generated.h" @@ -72,7 +73,8 @@ #define ADDR_LOADED_BUFFERS 3 #define ADDR_BUFFERS 4 #define ADDR_TABS 5 -#define ADDR_QUICKFIX 6 +#define ADDR_TABS_RELATIVE 6 // Tab page that only relative +#define ADDR_QUICKFIX 7 #define ADDR_OTHER 99 typedef struct exarg exarg_T; @@ -162,18 +164,20 @@ struct expand { /// flag. This needs to be saved for recursive commands, put them in a /// structure for easy manipulation. typedef struct { - int split; ///< flags for win_split() - int tab; ///< > 0 when ":tab" was used - bool browse; ///< true to invoke file dialog - bool confirm; ///< true to invoke yes/no dialog - bool hide; ///< true when ":hide" was used - bool keepalt; ///< true when ":keepalt" was used - bool keepjumps; ///< true when ":keepjumps" was used - bool keepmarks; ///< true when ":keepmarks" was used - bool keeppatterns; ///< true when ":keeppatterns" was used - bool lockmarks; ///< true when ":lockmarks" was used - bool noswapfile; ///< true when ":noswapfile" was used - char_u *save_ei; ///< saved value of 'eventignore' + int split; ///< flags for win_split() + int tab; ///< > 0 when ":tab" was used + bool browse; ///< true to invoke file dialog + bool confirm; ///< true to invoke yes/no dialog + bool hide; ///< true when ":hide" was used + bool keepalt; ///< true when ":keepalt" was used + bool keepjumps; ///< true when ":keepjumps" was used + bool keepmarks; ///< true when ":keepmarks" was used + bool keeppatterns; ///< true when ":keeppatterns" was used + bool lockmarks; ///< true when ":lockmarks" was used + bool noswapfile; ///< true when ":noswapfile" was used + char_u *save_ei; ///< saved value of 'eventignore' + regmatch_T filter_regmatch; ///< set by :filter /pat/ + bool filter_force; ///< set for :filter! } cmdmod_T; #endif // NVIM_EX_CMDS_DEFS_H diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index eccece7ac7..d1405978b3 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + /* * ex_docmd.c: functions for executing an Ex command line. */ @@ -50,6 +53,7 @@ #include "nvim/screen.h" #include "nvim/search.h" #include "nvim/spell.h" +#include "nvim/spellfile.h" #include "nvim/strings.h" #include "nvim/syntax.h" #include "nvim/tag.h" @@ -66,6 +70,8 @@ #include "nvim/event/rstream.h" #include "nvim/event/wstream.h" #include "nvim/shada.h" +#include "nvim/lua/executor.h" +#include "nvim/globals.h" static int quitmore = 0; static int ex_pressedreturn = FALSE; @@ -268,7 +274,7 @@ do_exmode ( /* * Execute a simple command line. Used for translated commands like "*". */ -int do_cmdline_cmd(char *cmd) +int do_cmdline_cmd(const char *cmd) { return do_cmdline((char_u *)cmd, NULL, NULL, DOCMD_NOWAIT|DOCMD_KEYTYPED); @@ -334,12 +340,13 @@ int do_cmdline(char_u *cmdline, LineGetter fgetline, msg_list = &private_msg_list; private_msg_list = NULL; - /* It's possible to create an endless loop with ":execute", catch that - * here. The value of 200 allows nested function calls, ":source", etc. */ - if (call_depth == 200) { + // It's possible to create an endless loop with ":execute", catch that + // here. The value of 200 allows nested function calls, ":source", etc. + // Allow 200 or 'maxfuncdepth', whatever is larger. + if (call_depth >= 200 && call_depth >= p_mfd) { EMSG(_("E169: Command too recursive")); - /* When converting to an exception, we do not include the command name - * since this is not an error of the specific command. */ + // When converting to an exception, we do not include the command name + // since this is not an error of the specific command. do_errthrow((struct condstack *)NULL, (char_u *)NULL); msg_list = saved_msg_list; return FAIL; @@ -583,10 +590,10 @@ int do_cmdline(char_u *cmdline, LineGetter fgetline, ++no_wait_return; verbose_enter_scroll(); - smsg(_("line %" PRId64 ": %s"), - (int64_t)sourcing_lnum, cmdline_copy); - if (msg_silent == 0) - msg_puts((char_u *)"\n"); /* don't overwrite this */ + smsg(_("line %" PRIdLINENR ": %s"), sourcing_lnum, cmdline_copy); + if (msg_silent == 0) { + msg_puts("\n"); // don't overwrite this either + } verbose_leave_scroll(); --no_wait_return; @@ -838,8 +845,6 @@ int do_cmdline(char_u *cmdline, LineGetter fgetline, break; case ET_INTERRUPT: break; - default: - p = vim_strsave((char_u *)_(e_internal)); } saved_sourcing_name = sourcing_name; @@ -1244,6 +1249,7 @@ static char_u * do_one_cmd(char_u **cmdlinep, cmdmod_T save_cmdmod; int ni; /* set when Not Implemented */ char_u *cmd; + int address_count = 1; memset(&ea, 0, sizeof(ea)); ea.line1 = 1; @@ -1301,7 +1307,6 @@ static char_u * do_one_cmd(char_u **cmdlinep, /* * 2. Handle command modifiers. */ - p = ea.cmd; p = skip_range(ea.cmd, NULL); switch (*p) { /* When adding an entry, also modify cmd_exists(). */ @@ -1345,6 +1350,31 @@ static char_u * do_one_cmd(char_u **cmdlinep, cmdmod.keepjumps = true; continue; + case 'f': { // only accept ":filter {pat} cmd" + char_u *reg_pat; + + if (!checkforcmd(&p, "filter", 4) || *p == NUL || ends_excmd(*p)) { + break; + } + if (*p == '!') { + cmdmod.filter_force = true; + p = skipwhite(p + 1); + if (*p == NUL || ends_excmd(*p)) { + break; + } + } + p = skip_vimgrep_pat(p, ®_pat, NULL); + if (p == NULL || *p == NUL) { + break; + } + cmdmod.filter_regmatch.regprog = vim_regcomp(reg_pat, RE_MAGIC); + if (cmdmod.filter_regmatch.regprog == NULL) { + break; + } + ea.cmd = p; + continue; + } + /* ":hide" and ":hide | cmd" are not modifiers */ case 'h': if (p != ea.cmd || !checkforcmd(&p, "hide", 3) || *p == NUL || ends_excmd(*p)) @@ -1405,7 +1435,7 @@ static char_u * do_one_cmd(char_u **cmdlinep, continue; case 't': if (checkforcmd(&p, "tab", 3)) { - long tabnr = get_address(&ea, &ea.cmd, ADDR_TABS, ea.skip, false); + long tabnr = get_address(&ea, &ea.cmd, ADDR_TABS, ea.skip, false, 1); if (tabnr == MAXLNUM) { cmdmod.tab = tabpage_index(curtab) + 1; } else { @@ -1447,6 +1477,7 @@ static char_u * do_one_cmd(char_u **cmdlinep, } break; } + char_u *after_modifier = ea.cmd; ea.skip = did_emsg || got_int || did_throw || (cstack->cs_idx >= 0 && !(cstack->cs_flags[cstack-> @@ -1520,8 +1551,7 @@ static char_u * do_one_cmd(char_u **cmdlinep, ea.line2 = curwin->w_cursor.lnum; break; case ADDR_WINDOWS: - lnum = CURRENT_WIN_NR; - ea.line2 = lnum; + ea.line2 = CURRENT_WIN_NR; break; case ADDR_ARGUMENTS: ea.line2 = curwin->w_arg_idx + 1; @@ -1534,8 +1564,10 @@ static char_u * do_one_cmd(char_u **cmdlinep, ea.line2 = curbuf->b_fnum; break; case ADDR_TABS: - lnum = CURRENT_TAB_NR; - ea.line2 = lnum; + ea.line2 = CURRENT_TAB_NR; + break; + case ADDR_TABS_RELATIVE: + ea.line2 = 1; break; case ADDR_QUICKFIX: ea.line2 = qf_get_cur_valid_idx(&ea); @@ -1543,7 +1575,7 @@ static char_u * do_one_cmd(char_u **cmdlinep, } ea.cmd = skipwhite(ea.cmd); lnum = get_address(&ea, &ea.cmd, ea.addr_type, ea.skip, - ea.addr_count == 0); + ea.addr_count == 0, address_count++); if (ea.cmd == NULL) { // error detected goto doend; } @@ -1585,6 +1617,10 @@ static char_u * do_one_cmd(char_u **cmdlinep, goto doend; } break; + case ADDR_TABS_RELATIVE: + errormsg = (char_u *)_(e_invrange); + goto doend; + break; case ADDR_ARGUMENTS: if (ARGCOUNT == 0) { ea.line1 = ea.line2 = 0; @@ -1630,11 +1666,15 @@ static char_u * do_one_cmd(char_u **cmdlinep, ea.addr_count++; if (*ea.cmd == ';') { - if (!ea.skip) + if (!ea.skip) { curwin->w_cursor.lnum = ea.line2; - } else if (*ea.cmd != ',') + // Don't leave the cursor on an illegal line (caused by ';') + check_cursor_lnum(); + } + } else if (*ea.cmd != ',') { break; - ++ea.cmd; + } + ea.cmd++; } /* One address given: set start and end lines */ @@ -1645,9 +1685,6 @@ static char_u * do_one_cmd(char_u **cmdlinep, ea.addr_count = 0; } - /* Don't leave the cursor on an illegal line (caused by ';') */ - check_cursor_lnum(); - /* * 5. Parse the command. */ @@ -1719,16 +1756,18 @@ static char_u * do_one_cmd(char_u **cmdlinep, errormsg = (char_u *)_("E464: Ambiguous use of user-defined command"); goto doend; } - /* Check for wrong commands. */ - if (*p == '!' && ea.cmd[1] == 0151 && ea.cmd[0] == 78) { - errormsg = uc_fun_cmd(); - goto doend; - } + // Check for wrong commands. if (ea.cmdidx == CMD_SIZE) { if (!ea.skip) { STRCPY(IObuff, _("E492: Not an editor command")); if (!(flags & DOCMD_VERBOSE)) { - append_command(*cmdlinep); + // If the modifier was parsed OK the error must be in the following + // command + if (after_modifier != NULL) { + append_command(after_modifier); + } else { + append_command(*cmdlinep); + } } errormsg = IObuff; did_emsg_syntax = TRUE; @@ -1815,9 +1854,9 @@ static char_u * do_one_cmd(char_u **cmdlinep, errormsg = (char_u *)_("E493: Backwards range given"); goto doend; } - if (ask_yesno((char_u *) - _("Backwards range given, OK to swap"), FALSE) != 'y') + if (ask_yesno(_("Backwards range given, OK to swap"), false) != 'y') { goto doend; + } } lnum = ea.line1; ea.line1 = ea.line2; @@ -1971,6 +2010,9 @@ static char_u * do_one_cmd(char_u **cmdlinep, case ADDR_TABS: ea.line2 = LAST_TAB_NR; break; + case ADDR_TABS_RELATIVE: + ea.line2 = 1; + break; case ADDR_ARGUMENTS: if (ARGCOUNT == 0) { ea.line1 = ea.line2 = 0; @@ -2026,11 +2068,11 @@ static char_u * do_one_cmd(char_u **cmdlinep, ea.line1 = ea.line2; ea.line2 += n - 1; ++ea.addr_count; - /* - * Be vi compatible: no error message for out of range. - */ - if (ea.line2 > curbuf->b_ml.ml_line_count) + // Be vi compatible: no error message for out of range. + if (ea.addr_type == ADDR_LINES + && ea.line2 > curbuf->b_ml.ml_line_count) { ea.line2 = curbuf->b_ml.ml_line_count; + } } } @@ -2095,6 +2137,7 @@ static char_u * do_one_cmd(char_u **cmdlinep, case CMD_echomsg: case CMD_echon: case CMD_execute: + case CMD_filter: case CMD_help: case CMD_hide: case CMD_ijump: @@ -2246,6 +2289,10 @@ doend: free_string_option(cmdmod.save_ei); } + if (cmdmod.filter_regmatch.regprog != NULL) { + vim_regfree(cmdmod.filter_regmatch.regprog); + } + cmdmod = save_cmdmod; if (save_msg_silent != -1) { @@ -2531,28 +2578,29 @@ static struct cmdmod { int minlen; int has_count; /* :123verbose :3tab */ } cmdmods[] = { - {"aboveleft", 3, FALSE}, - {"belowright", 3, FALSE}, - {"botright", 2, FALSE}, - {"browse", 3, FALSE}, - {"confirm", 4, FALSE}, - {"hide", 3, FALSE}, - {"keepalt", 5, FALSE}, - {"keepjumps", 5, FALSE}, - {"keepmarks", 3, FALSE}, - {"keeppatterns", 5, FALSE}, - {"leftabove", 5, FALSE}, - {"lockmarks", 3, FALSE}, - {"noautocmd", 3, FALSE}, - {"noswapfile", 3, FALSE}, - {"rightbelow", 6, FALSE}, - {"sandbox", 3, FALSE}, - {"silent", 3, FALSE}, - {"tab", 3, TRUE}, - {"topleft", 2, FALSE}, - {"unsilent", 3, FALSE}, - {"verbose", 4, TRUE}, - {"vertical", 4, FALSE}, + { "aboveleft", 3, false }, + { "belowright", 3, false }, + { "botright", 2, false }, + { "browse", 3, false }, + { "confirm", 4, false }, + { "filter", 4, false }, + { "hide", 3, false }, + { "keepalt", 5, false }, + { "keepjumps", 5, false }, + { "keepmarks", 3, false }, + { "keeppatterns", 5, false }, + { "leftabove", 5, false }, + { "lockmarks", 3, false }, + { "noautocmd", 3, false }, + { "noswapfile", 3, false }, + { "rightbelow", 6, false }, + { "sandbox", 3, false }, + { "silent", 3, false }, + { "tab", 3, true }, + { "topleft", 2, false }, + { "unsilent", 3, false }, + { "verbose", 4, true }, + { "vertical", 4, false }, }; /* @@ -2582,27 +2630,29 @@ int modifier_len(char_u *cmd) * Return 2 if there is an exact match. * Return 3 if there is an ambiguous match. */ -int cmd_exists(char_u *name) +int cmd_exists(const char *const name) { exarg_T ea; - int full = FALSE; - int i; - int j; char_u *p; - /* Check command modifiers. */ - for (i = 0; i < (int)ARRAY_SIZE(cmdmods); ++i) { - for (j = 0; name[j] != NUL; ++j) - if (name[j] != cmdmods[i].name[j]) + // Check command modifiers. + for (int i = 0; i < (int)ARRAY_SIZE(cmdmods); i++) { + int j; + for (j = 0; name[j] != NUL; j++) { + if (name[j] != (char)cmdmods[i].name[j]) { break; - if (name[j] == NUL && j >= cmdmods[i].minlen) + } + } + if (name[j] == NUL && j >= cmdmods[i].minlen) { return cmdmods[i].name[j] == NUL ? 2 : 1; + } } /* Check built-in commands and user defined commands. * For ":2match" and ":3match" we need to skip the number. */ - ea.cmd = (*name == '2' || *name == '3') ? name + 1 : name; + ea.cmd = (char_u *)((*name == '2' || *name == '3') ? name + 1 : name); ea.cmdidx = (cmdidx_T)0; + int full = false; p = find_command(&ea, &full); if (p == NULL) return 3; @@ -2620,32 +2670,27 @@ int cmd_exists(char_u *name) * perfectly compatible with each other, but then the command line syntax * probably won't change that much -- webb. */ -char_u * -set_one_cmd_context ( +const char * set_one_cmd_context( expand_T *xp, - char_u *buff /* buffer for command string */ + const char *buff // buffer for command string ) { - char_u *p; - char_u *cmd, *arg; - int len = 0; + size_t len = 0; exarg_T ea; - int compl = EXPAND_NOTHING; - int delim; - int forceit = FALSE; - int usefilter = FALSE; /* filter instead of file name */ + int context = EXPAND_NOTHING; + int forceit = false; + int usefilter = false; // Filter instead of file name. ExpandInit(xp); - xp->xp_pattern = buff; - xp->xp_context = EXPAND_COMMANDS; /* Default until we get past command */ + xp->xp_pattern = (char_u *)buff; + xp->xp_context = EXPAND_COMMANDS; // Default until we get past command ea.argt = 0; - /* - * 2. skip comment lines and leading space, colons or bars - */ - for (cmd = buff; vim_strchr((char_u *)" \t:|", *cmd) != NULL; cmd++) - ; - xp->xp_pattern = cmd; + // 2. skip comment lines and leading space, colons or bars + const char *cmd; + for (cmd = buff; vim_strchr((const char_u *)" \t:|", *cmd) != NULL; cmd++) { + } + xp->xp_pattern = (char_u *)cmd; if (*cmd == NUL) return NULL; @@ -2657,14 +2702,15 @@ set_one_cmd_context ( /* * 3. parse a range specifier of the form: addr [,addr] [;addr] .. */ - cmd = skip_range(cmd, &xp->xp_context); + cmd = (const char *)skip_range((const char_u *)cmd, &xp->xp_context); /* * 4. parse command */ - xp->xp_pattern = cmd; - if (*cmd == NUL) + xp->xp_pattern = (char_u *)cmd; + if (*cmd == NUL) { return NULL; + } if (*cmd == '"') { xp->xp_context = EXPAND_NOTHING; return NULL; @@ -2680,6 +2726,7 @@ set_one_cmd_context ( * do accept "keepmarks", "keepalt" and "keepjumps". * - the 's' command can be followed directly by 'c', 'g', 'i', 'I' or 'r' */ + const char *p; if (*cmd == 'k' && cmd[1] != 'e') { ea.cmdidx = CMD_k; p = cmd + 1; @@ -2702,20 +2749,21 @@ set_one_cmd_context ( } } // check for non-alpha command - if (p == cmd && vim_strchr((char_u *)"@*!=><&~#", *p) != NULL) { + if (p == cmd && vim_strchr((const char_u *)"@*!=><&~#", *p) != NULL) { p++; } - len = (int)(p - cmd); + len = (size_t)(p - cmd); if (len == 0) { xp->xp_context = EXPAND_UNSUCCESSFUL; return NULL; } for (ea.cmdidx = (cmdidx_T)0; (int)ea.cmdidx < (int)CMD_SIZE; - ea.cmdidx = (cmdidx_T)((int)ea.cmdidx + 1)) - if (STRNCMP(cmdnames[(int)ea.cmdidx].cmd_name, cmd, - (size_t)len) == 0) + ea.cmdidx = (cmdidx_T)((int)ea.cmdidx + 1)) { + if (STRNCMP(cmdnames[(int)ea.cmdidx].cmd_name, cmd, len) == 0) { break; + } + } if (cmd[0] >= 'A' && cmd[0] <= 'Z') { while (ASCII_ISALNUM(*p) || *p == '*') { // Allow * wild card @@ -2732,16 +2780,15 @@ set_one_cmd_context ( return NULL; if (ea.cmdidx == CMD_SIZE) { - if (*cmd == 's' && vim_strchr((char_u *)"cgriI", cmd[1]) != NULL) { + if (*cmd == 's' && vim_strchr((const char_u *)"cgriI", cmd[1]) != NULL) { ea.cmdidx = CMD_substitute; p = cmd + 1; } else if (cmd[0] >= 'A' && cmd[0] <= 'Z') { - ea.cmd = cmd; - p = find_ucmd(&ea, p, NULL, xp, - &compl - ); - if (p == NULL) - ea.cmdidx = CMD_SIZE; /* ambiguous user command */ + ea.cmd = (char_u *)cmd; + p = (const char *)find_ucmd(&ea, (char_u *)p, NULL, xp, &context); + if (p == NULL) { + ea.cmdidx = CMD_SIZE; // Ambiguous user command. + } } } if (ea.cmdidx == CMD_SIZE) { @@ -2764,16 +2811,17 @@ set_one_cmd_context ( ea.argt = cmdnames[(int)ea.cmdidx].cmd_argt; } - arg = skipwhite(p); + const char *arg = (const char *)skipwhite((const char_u *)p); if (ea.cmdidx == CMD_write || ea.cmdidx == CMD_update) { - if (*arg == '>') { /* append */ - if (*++arg == '>') - ++arg; - arg = skipwhite(arg); - } else if (*arg == '!' && ea.cmdidx == CMD_write) { /* :w !filter */ - ++arg; - usefilter = TRUE; + if (*arg == '>') { // Append. + if (*++arg == '>') { + arg++; + } + arg = (const char *)skipwhite((const char_u *)arg); + } else if (*arg == '!' && ea.cmdidx == CMD_write) { // :w !filter + arg++; + usefilter = true; } } @@ -2786,23 +2834,24 @@ set_one_cmd_context ( } if (ea.cmdidx == CMD_lshift || ea.cmdidx == CMD_rshift) { - while (*arg == *cmd) /* allow any number of '>' or '<' */ - ++arg; - arg = skipwhite(arg); + while (*arg == *cmd) { // allow any number of '>' or '<' + arg++; + } + arg = (const char *)skipwhite((const char_u *)arg); } /* Does command allow "+command"? */ if ((ea.argt & EDITCMD) && !usefilter && *arg == '+') { /* Check if we're in the +command */ p = arg + 1; - arg = skip_cmd_arg(arg, FALSE); + arg = (const char *)skip_cmd_arg((char_u *)arg, false); /* Still touching the command after '+'? */ if (*arg == NUL) return p; - /* Skip space(s) after +command to get to the real argument */ - arg = skipwhite(arg); + // Skip space(s) after +command to get to the real argument. + arg = (const char *)skipwhite((const char_u *)arg); } /* @@ -2831,19 +2880,18 @@ set_one_cmd_context ( } // no arguments allowed - if (!(ea.argt & EXTRA) && *arg != NUL - && vim_strchr((char_u *)"|\"", *arg) == NULL) { + if (!(ea.argt & EXTRA) && *arg != NUL && strchr("|\"", *arg) == NULL) { return NULL; } /* Find start of last argument (argument just before cursor): */ p = buff; - xp->xp_pattern = p; - len = (int)STRLEN(buff); + xp->xp_pattern = (char_u *)p; + len = strlen(buff); while (*p && p < buff + len) { if (*p == ' ' || *p == TAB) { - /* argument starts after a space */ - xp->xp_pattern = ++p; + // Argument starts after a space. + xp->xp_pattern = (char_u *)++p; } else { if (*p == '\\' && *(p + 1) != NUL) ++p; /* skip over escaped character */ @@ -2853,25 +2901,26 @@ set_one_cmd_context ( if (ea.argt & XFILE) { int c; - int in_quote = FALSE; - char_u *bow = NULL; /* Beginning of word */ + int in_quote = false; + const char *bow = NULL; // Beginning of word. /* * Allow spaces within back-quotes to count as part of the argument * being expanded. */ - xp->xp_pattern = skipwhite(arg); - p = xp->xp_pattern; + xp->xp_pattern = skipwhite((const char_u *)arg); + p = (const char *)xp->xp_pattern; while (*p != NUL) { - if (has_mbyte) - c = mb_ptr2char(p); - else - c = *p; - if (c == '\\' && p[1] != NUL) - ++p; - else if (c == '`') { + if (has_mbyte) { + c = mb_ptr2char((const char_u *)p); + } else { + c = (uint8_t)(*p); + } + if (c == '\\' && p[1] != NUL) { + p++; + } else if (c == '`') { if (!in_quote) { - xp->xp_pattern = p; + xp->xp_pattern = (char_u *)p; bow = p + 1; } in_quote = !in_quote; @@ -2884,22 +2933,26 @@ set_one_cmd_context ( || ascii_iswhite(c)) { len = 0; /* avoid getting stuck when space is in 'isfname' */ while (*p != NUL) { - if (has_mbyte) - c = mb_ptr2char(p); - else + if (has_mbyte) { + c = mb_ptr2char((const char_u *)p); + } else { c = *p; - if (c == '`' || vim_isfilec_or_wc(c)) + } + if (c == '`' || vim_isfilec_or_wc(c)) { break; - if (has_mbyte) - len = (*mb_ptr2len)(p); - else + } + if (has_mbyte) { + len = (size_t)(*mb_ptr2len)((const char_u *)p); + } else { len = 1; + } mb_ptr_adv(p); } - if (in_quote) + if (in_quote) { bow = p; - else - xp->xp_pattern = p; + } else { + xp->xp_pattern = (char_u *)p; + } p -= len; } mb_ptr_adv(p); @@ -2909,8 +2962,9 @@ set_one_cmd_context ( * If we are still inside the quotes, and we passed a space, just * expand from there. */ - if (bow != NULL && in_quote) - xp->xp_pattern = bow; + if (bow != NULL && in_quote) { + xp->xp_pattern = (char_u *)bow; + } xp->xp_context = EXPAND_FILES; /* For a shell command more chars need to be escaped. */ @@ -2918,33 +2972,36 @@ set_one_cmd_context ( #ifndef BACKSLASH_IN_FILENAME xp->xp_shell = TRUE; #endif - /* When still after the command name expand executables. */ - if (xp->xp_pattern == skipwhite(arg)) + // When still after the command name expand executables. + if (xp->xp_pattern == skipwhite((const char_u *)arg)) { xp->xp_context = EXPAND_SHELLCMD; + } } - /* Check for environment variable */ - if (*xp->xp_pattern == '$' - ) { - for (p = xp->xp_pattern + 1; *p != NUL; ++p) - if (!vim_isIDc(*p)) + // Check for environment variable. + if (*xp->xp_pattern == '$') { + for (p = (const char *)xp->xp_pattern + 1; *p != NUL; p++) { + if (!vim_isIDc((uint8_t)(*p))) { break; + } + } if (*p == NUL) { xp->xp_context = EXPAND_ENV_VARS; - ++xp->xp_pattern; - /* Avoid that the assignment uses EXPAND_FILES again. */ - if (compl != EXPAND_USER_DEFINED && compl != EXPAND_USER_LIST) - compl = EXPAND_ENV_VARS; + xp->xp_pattern++; + // Avoid that the assignment uses EXPAND_FILES again. + if (context != EXPAND_USER_DEFINED && context != EXPAND_USER_LIST) { + context = EXPAND_ENV_VARS; + } } } /* Check for user names */ if (*xp->xp_pattern == '~') { - for (p = xp->xp_pattern + 1; *p != NUL && *p != '/'; ++p) - ; - /* Complete ~user only if it partially matches a user name. - * A full match ~user<Tab> will be replaced by user's home - * directory i.e. something like ~user<Tab> -> /home/user/ */ - if (*p == NUL && p > xp->xp_pattern + 1 + for (p = (const char *)xp->xp_pattern + 1; *p != NUL && *p != '/'; p++) { + } + // Complete ~user only if it partially matches a user name. + // A full match ~user<Tab> will be replaced by user's home + // directory i.e. something like ~user<Tab> -> /home/user/ + if (*p == NUL && p > (const char *)xp->xp_pattern + 1 && match_user(xp->xp_pattern + 1) == 1) { xp->xp_context = EXPAND_USER; ++xp->xp_pattern; @@ -2974,7 +3031,7 @@ set_one_cmd_context ( break; case CMD_help: xp->xp_context = EXPAND_HELP; - xp->xp_pattern = arg; + xp->xp_pattern = (char_u *)arg; break; /* Command modifiers: return the argument. @@ -3013,17 +3070,28 @@ set_one_cmd_context ( case CMD_windo: return arg; + case CMD_filter: + if (*arg != NUL) { + arg = (const char *)skip_vimgrep_pat((char_u *)arg, NULL, NULL); + } + if (arg == NULL || *arg == NUL) { + xp->xp_context = EXPAND_NOTHING; + return NULL; + } + return (const char *)skipwhite((const char_u *)arg); + case CMD_match: if (*arg == NUL || !ends_excmd(*arg)) { /* also complete "None" */ set_context_in_echohl_cmd(xp, arg); - arg = skipwhite(skiptowhite(arg)); + arg = (const char *)skipwhite(skiptowhite((const char_u *)arg)); if (*arg != NUL) { xp->xp_context = EXPAND_NOTHING; - arg = skip_regexp(arg + 1, *arg, p_magic, NULL); + arg = (const char *)skip_regexp((char_u *)arg + 1, (uint8_t)(*arg), + p_magic, NULL); } } - return find_nextcmd(arg); + return (const char *)find_nextcmd((char_u *)arg); /* * All completion for the +cmdline_compl feature goes here. @@ -3032,15 +3100,15 @@ set_one_cmd_context ( case CMD_command: /* Check for attributes */ while (*arg == '-') { - arg++; /* Skip "-" */ - p = skiptowhite(arg); + arg++; // Skip "-". + p = (const char *)skiptowhite((const char_u *)arg); if (*p == NUL) { - /* Cursor is still in the attribute */ - p = vim_strchr(arg, '='); + // Cursor is still in the attribute. + p = strchr(arg, '='); if (p == NULL) { - /* No "=", so complete attribute names */ + // No "=", so complete attribute names. xp->xp_context = EXPAND_USER_CMD_FLAGS; - xp->xp_pattern = arg; + xp->xp_pattern = (char_u *)arg; return NULL; } @@ -3048,73 +3116,81 @@ set_one_cmd_context ( // their arguments as well. if (STRNICMP(arg, "complete", p - arg) == 0) { xp->xp_context = EXPAND_USER_COMPLETE; - xp->xp_pattern = p + 1; + xp->xp_pattern = (char_u *)p + 1; return NULL; } else if (STRNICMP(arg, "nargs", p - arg) == 0) { xp->xp_context = EXPAND_USER_NARGS; - xp->xp_pattern = p + 1; + xp->xp_pattern = (char_u *)p + 1; return NULL; } else if (STRNICMP(arg, "addr", p - arg) == 0) { xp->xp_context = EXPAND_USER_ADDR_TYPE; - xp->xp_pattern = p + 1; + xp->xp_pattern = (char_u *)p + 1; return NULL; } return NULL; } - arg = skipwhite(p); + arg = (const char *)skipwhite((char_u *)p); } - /* After the attributes comes the new command name */ - p = skiptowhite(arg); + // After the attributes comes the new command name. + p = (const char *)skiptowhite((const char_u *)arg); if (*p == NUL) { xp->xp_context = EXPAND_USER_COMMANDS; - xp->xp_pattern = arg; + xp->xp_pattern = (char_u *)arg; break; } - /* And finally comes a normal command */ - return skipwhite(p); + // And finally comes a normal command. + return (const char *)skipwhite((const char_u *)p); case CMD_delcommand: xp->xp_context = EXPAND_USER_COMMANDS; - xp->xp_pattern = arg; + xp->xp_pattern = (char_u *)arg; break; case CMD_global: - case CMD_vglobal: - delim = *arg; /* get the delimiter */ - if (delim) - ++arg; /* skip delimiter if there is one */ + case CMD_vglobal: { + const int delim = (uint8_t)(*arg); // Get the delimiter. + if (delim) { + arg++; // Skip delimiter if there is one. + } - while (arg[0] != NUL && arg[0] != delim) { - if (arg[0] == '\\' && arg[1] != NUL) - ++arg; - ++arg; + while (arg[0] != NUL && (uint8_t)arg[0] != delim) { + if (arg[0] == '\\' && arg[1] != NUL) { + arg++; + } + arg++; } if (arg[0] != NUL) return arg + 1; break; + } case CMD_and: - case CMD_substitute: - delim = *arg; + case CMD_substitute: { + const int delim = (uint8_t)(*arg); if (delim) { - /* skip "from" part */ - ++arg; - arg = skip_regexp(arg, delim, p_magic, NULL); + // Skip "from" part. + arg++; + arg = (const char *)skip_regexp((char_u *)arg, delim, p_magic, NULL); } - /* skip "to" part */ - while (arg[0] != NUL && arg[0] != delim) { - if (arg[0] == '\\' && arg[1] != NUL) - ++arg; - ++arg; + // Skip "to" part. + while (arg[0] != NUL && (uint8_t)arg[0] != delim) { + if (arg[0] == '\\' && arg[1] != NUL) { + arg++; + } + arg++; } - if (arg[0] != NUL) /* skip delimiter */ - ++arg; - while (arg[0] && vim_strchr((char_u *)"|\"#", arg[0]) == NULL) - ++arg; - if (arg[0] != NUL) + if (arg[0] != NUL) { // Skip delimiter. + arg++; + } + while (arg[0] && strchr("|\"#", arg[0]) == NULL) { + arg++; + } + if (arg[0] != NUL) { return arg; + } break; + } case CMD_isearch: case CMD_dsearch: case CMD_ilist: @@ -3124,36 +3200,40 @@ set_one_cmd_context ( case CMD_djump: case CMD_isplit: case CMD_dsplit: - arg = skipwhite(skipdigits(arg)); /* skip count */ - if (*arg == '/') { /* Match regexp, not just whole words */ - for (++arg; *arg && *arg != '/'; arg++) - if (*arg == '\\' && arg[1] != NUL) + // Skip count. + arg = (const char *)skipwhite(skipdigits((const char_u *)arg)); + if (*arg == '/') { // Match regexp, not just whole words. + for (++arg; *arg && *arg != '/'; arg++) { + if (*arg == '\\' && arg[1] != NUL) { arg++; + } + } if (*arg) { - arg = skipwhite(arg + 1); + arg = (const char *)skipwhite((const char_u *)arg + 1); - /* Check for trailing illegal characters */ - if (*arg && vim_strchr((char_u *)"|\"\n", *arg) == NULL) + // Check for trailing illegal characters. + if (*arg && strchr("|\"\n", *arg) == NULL) { xp->xp_context = EXPAND_NOTHING; - else + } else { return arg; + } } } break; case CMD_autocmd: - return set_context_in_autocmd(xp, arg, FALSE); + return (const char *)set_context_in_autocmd(xp, (char_u *)arg, false); case CMD_doautocmd: case CMD_doautoall: - return set_context_in_autocmd(xp, arg, TRUE); + return (const char *)set_context_in_autocmd(xp, (char_u *)arg, true); case CMD_set: - set_context_in_set_cmd(xp, arg, 0); + set_context_in_set_cmd(xp, (char_u *)arg, 0); break; case CMD_setglobal: - set_context_in_set_cmd(xp, arg, OPT_GLOBAL); + set_context_in_set_cmd(xp, (char_u *)arg, OPT_GLOBAL); break; case CMD_setlocal: - set_context_in_set_cmd(xp, arg, OPT_LOCAL); + set_context_in_set_cmd(xp, (char_u *)arg, OPT_LOCAL); break; case CMD_tag: case CMD_stag: @@ -3165,15 +3245,16 @@ set_one_cmd_context ( case CMD_tjump: case CMD_stjump: case CMD_ptjump: - if (*p_wop != NUL) + if (*p_wop != NUL) { xp->xp_context = EXPAND_TAGS_LISTFILES; - else + } else { xp->xp_context = EXPAND_TAGS; - xp->xp_pattern = arg; + } + xp->xp_pattern = (char_u *)arg; break; case CMD_augroup: xp->xp_context = EXPAND_AUGROUP; - xp->xp_pattern = arg; + xp->xp_pattern = (char_u *)arg; break; case CMD_syntax: set_context_in_syntax_cmd(xp, arg); @@ -3190,20 +3271,21 @@ set_one_cmd_context ( case CMD_echoerr: case CMD_call: case CMD_return: - set_context_for_expression(xp, arg, ea.cmdidx); + set_context_for_expression(xp, (char_u *)arg, ea.cmdidx); break; case CMD_unlet: - while ((xp->xp_pattern = vim_strchr(arg, ' ')) != NULL) - arg = xp->xp_pattern + 1; + while ((xp->xp_pattern = (char_u *)strchr(arg, ' ')) != NULL) { + arg = (const char *)xp->xp_pattern + 1; + } xp->xp_context = EXPAND_USER_VARS; - xp->xp_pattern = arg; + xp->xp_pattern = (char_u *)arg; break; case CMD_function: case CMD_delfunction: xp->xp_context = EXPAND_USER_FUNC; - xp->xp_pattern = arg; + xp->xp_pattern = (char_u *)arg; break; case CMD_echohl: @@ -3218,33 +3300,37 @@ set_one_cmd_context ( set_context_in_cscope_cmd(xp, arg, ea.cmdidx); break; case CMD_sign: - set_context_in_sign_cmd(xp, arg); + set_context_in_sign_cmd(xp, (char_u *)arg); break; case CMD_bdelete: case CMD_bwipeout: case CMD_bunload: - while ((xp->xp_pattern = vim_strchr(arg, ' ')) != NULL) - arg = xp->xp_pattern + 1; - /*FALLTHROUGH*/ + while ((xp->xp_pattern = (char_u *)strchr(arg, ' ')) != NULL) { + arg = (const char *)xp->xp_pattern + 1; + } + // FALLTHROUGH case CMD_buffer: case CMD_sbuffer: case CMD_checktime: xp->xp_context = EXPAND_BUFFERS; - xp->xp_pattern = arg; + xp->xp_pattern = (char_u *)arg; break; case CMD_USER: case CMD_USER_BUF: - if (compl != EXPAND_NOTHING) { - /* XFILE: file names are handled above */ + if (context != EXPAND_NOTHING) { + // XFILE: file names are handled above. if (!(ea.argt & XFILE)) { - if (compl == EXPAND_MENUS) - return set_context_in_menu_cmd(xp, cmd, arg, forceit); - if (compl == EXPAND_COMMANDS) + if (context == EXPAND_MENUS) { + return (const char *)set_context_in_menu_cmd(xp, (char_u *)cmd, + (char_u *)arg, forceit); + } else if (context == EXPAND_COMMANDS) { return arg; - if (compl == EXPAND_MAPPINGS) - return set_context_in_map_cmd(xp, (char_u *)"map", - arg, forceit, FALSE, FALSE, CMD_map); - /* Find start of last argument. */ + } else if (context == EXPAND_MAPPINGS) { + return (const char *)set_context_in_map_cmd( + xp, (char_u *)"map", (char_u *)arg, forceit, false, false, + CMD_map); + } + // Find start of last argument. p = arg; while (*p) { if (*p == ' ') @@ -3254,9 +3340,9 @@ set_one_cmd_context ( ++p; /* skip over escaped character */ mb_ptr_adv(p); } - xp->xp_pattern = arg; + xp->xp_pattern = (char_u *)arg; } - xp->xp_context = compl; + xp->xp_context = context; } break; case CMD_map: case CMD_noremap: @@ -3268,8 +3354,8 @@ set_one_cmd_context ( case CMD_lmap: case CMD_lnoremap: case CMD_smap: case CMD_snoremap: case CMD_xmap: case CMD_xnoremap: - return set_context_in_map_cmd(xp, cmd, arg, forceit, - FALSE, FALSE, ea.cmdidx); + return (const char *)set_context_in_map_cmd( + xp, (char_u *)cmd, (char_u *)arg, forceit, false, false, ea.cmdidx); case CMD_unmap: case CMD_nunmap: case CMD_vunmap: @@ -3279,18 +3365,18 @@ set_one_cmd_context ( case CMD_lunmap: case CMD_sunmap: case CMD_xunmap: - return set_context_in_map_cmd(xp, cmd, arg, forceit, - FALSE, TRUE, ea.cmdidx); + return (const char *)set_context_in_map_cmd( + xp, (char_u *)cmd, (char_u *)arg, forceit, false, true, ea.cmdidx); case CMD_abbreviate: case CMD_noreabbrev: case CMD_cabbrev: case CMD_cnoreabbrev: case CMD_iabbrev: case CMD_inoreabbrev: - return set_context_in_map_cmd(xp, cmd, arg, forceit, - TRUE, FALSE, ea.cmdidx); + return (const char *)set_context_in_map_cmd( + xp, (char_u *)cmd, (char_u *)arg, forceit, true, false, ea.cmdidx); case CMD_unabbreviate: case CMD_cunabbrev: case CMD_iunabbrev: - return set_context_in_map_cmd(xp, cmd, arg, forceit, - TRUE, TRUE, ea.cmdidx); + return (const char *)set_context_in_map_cmd( + xp, (char_u *)cmd, (char_u *)arg, forceit, true, true, ea.cmdidx); case CMD_menu: case CMD_noremenu: case CMD_unmenu: case CMD_amenu: case CMD_anoremenu: case CMD_aunmenu: case CMD_nmenu: case CMD_nnoremenu: case CMD_nunmenu: @@ -3300,47 +3386,49 @@ set_one_cmd_context ( case CMD_cmenu: case CMD_cnoremenu: case CMD_cunmenu: case CMD_tmenu: case CMD_tunmenu: case CMD_popup: case CMD_emenu: - return set_context_in_menu_cmd(xp, cmd, arg, forceit); + return (const char *)set_context_in_menu_cmd( + xp, (char_u *)cmd, (char_u *)arg, forceit); case CMD_colorscheme: xp->xp_context = EXPAND_COLORS; - xp->xp_pattern = arg; + xp->xp_pattern = (char_u *)arg; break; case CMD_compiler: xp->xp_context = EXPAND_COMPILER; - xp->xp_pattern = arg; + xp->xp_pattern = (char_u *)arg; break; case CMD_ownsyntax: xp->xp_context = EXPAND_OWNSYNTAX; - xp->xp_pattern = arg; + xp->xp_pattern = (char_u *)arg; break; case CMD_setfiletype: xp->xp_context = EXPAND_FILETYPE; - xp->xp_pattern = arg; + xp->xp_pattern = (char_u *)arg; break; case CMD_packadd: xp->xp_context = EXPAND_PACKADD; - xp->xp_pattern = arg; + xp->xp_pattern = (char_u *)arg; break; #ifdef HAVE_WORKING_LIBINTL case CMD_language: - p = skiptowhite(arg); + p = (const char *)skiptowhite((const char_u *)arg); if (*p == NUL) { xp->xp_context = EXPAND_LANGUAGE; - xp->xp_pattern = arg; + xp->xp_pattern = (char_u *)arg; } else { - if ( STRNCMP(arg, "messages", p - arg) == 0 - || STRNCMP(arg, "ctype", p - arg) == 0 - || STRNCMP(arg, "time", p - arg) == 0) { + if (strncmp(arg, "messages", p - arg) == 0 + || strncmp(arg, "ctype", p - arg) == 0 + || strncmp(arg, "time", p - arg) == 0) { xp->xp_context = EXPAND_LOCALES; - xp->xp_pattern = skipwhite(p); - } else + xp->xp_pattern = skipwhite((const char_u *)p); + } else { xp->xp_context = EXPAND_NOTHING; + } } break; #endif @@ -3349,16 +3437,21 @@ set_one_cmd_context ( break; case CMD_behave: xp->xp_context = EXPAND_BEHAVE; - xp->xp_pattern = arg; + xp->xp_pattern = (char_u *)arg; + break; + + case CMD_messages: + xp->xp_context = EXPAND_MESSAGES; + xp->xp_pattern = (char_u *)arg; break; case CMD_history: xp->xp_context = EXPAND_HISTORY; - xp->xp_pattern = arg; + xp->xp_pattern = (char_u *)arg; break; case CMD_syntime: xp->xp_context = EXPAND_SYNTIME; - xp->xp_pattern = arg; + xp->xp_pattern = (char_u *)arg; break; @@ -3377,10 +3470,9 @@ set_one_cmd_context ( * Also skip white space and ":" characters. * Returns the "cmd" pointer advanced to beyond the range. */ -char_u * -skip_range ( - char_u *cmd, - int *ctx /* pointer to xp_context or NULL */ +char_u *skip_range( + const char_u *cmd, + int *ctx // pointer to xp_context or NULL ) { unsigned delim; @@ -3405,7 +3497,7 @@ skip_range ( while (*cmd == ':') cmd = skipwhite(cmd + 1); - return cmd; + return (char_u *)cmd; } /* @@ -3420,8 +3512,8 @@ static linenr_T get_address(exarg_T *eap, char_u **ptr, int addr_type, // flag: one of ADDR_LINES, ... int skip, // only skip the address, don't use it - int to_other_file // flag: may jump to other file - ) + int to_other_file, // flag: may jump to other file + int address_count) // 1 for first, >1 after comma { int c; int i; @@ -3455,6 +3547,11 @@ static linenr_T get_address(exarg_T *eap, case ADDR_TABS: lnum = CURRENT_TAB_NR; break; + case ADDR_TABS_RELATIVE: + EMSG(_(e_invrange)); + cmd = NULL; + goto error; + break; case ADDR_QUICKFIX: lnum = qf_get_cur_valid_idx(eap); break; @@ -3489,6 +3586,11 @@ static linenr_T get_address(exarg_T *eap, case ADDR_TABS: lnum = LAST_TAB_NR; break; + case ADDR_TABS_RELATIVE: + EMSG(_(e_invrange)); + cmd = NULL; + goto error; + break; case ADDR_QUICKFIX: lnum = qf_get_size(eap); if (lnum == 0) { @@ -3637,6 +3739,9 @@ static linenr_T get_address(exarg_T *eap, case ADDR_TABS: lnum = CURRENT_TAB_NR; break; + case ADDR_TABS_RELATIVE: + lnum = 1; + break; case ADDR_QUICKFIX: lnum = qf_get_cur_valid_idx(eap); break; @@ -3651,13 +3756,27 @@ static linenr_T get_address(exarg_T *eap, n = 1; else n = getdigits(&cmd); - if (addr_type == ADDR_LOADED_BUFFERS || addr_type == ADDR_BUFFERS) + + if (addr_type == ADDR_TABS_RELATIVE) { + EMSG(_(e_invrange)); + cmd = NULL; + goto error; + } else if (addr_type == ADDR_LOADED_BUFFERS || addr_type == ADDR_BUFFERS) { lnum = compute_buffer_local_count( addr_type, lnum, (i == '-') ? -1 * n : n); - else if (i == '-') - lnum -= n; - else - lnum += n; + } else { + // Relative line addressing, need to adjust for folded lines + // now, but only do it after the first address. + if (addr_type == ADDR_LINES && (i == '-' || i == '+') + && address_count >= 2) { + (void)hasFolding(lnum, NULL, &lnum); + } + if (i == '-') { + lnum -= n; + } else { + lnum += n; + } + } } } while (*cmd == '/' || *cmd == '?'); @@ -3694,10 +3813,12 @@ void ex_ni(exarg_T *eap) /// Skips over ":perl <<EOF" constructs. static void ex_script_ni(exarg_T *eap) { - if (!eap->skip) + if (!eap->skip) { ex_ni(eap); - else - xfree(script_get(eap, eap->arg)); + } else { + size_t len; + xfree(script_get(eap, &len)); + } } /* @@ -3764,6 +3885,9 @@ static char_u *invalid_range(exarg_T *eap) return (char_u *)_(e_invrange); } break; + case ADDR_TABS_RELATIVE: + // Do nothing + break; case ADDR_QUICKFIX: assert(eap->line2 >= 0); if (eap->line2 != 1 && (size_t)eap->line2 > qf_get_size(eap)) { @@ -3854,7 +3978,7 @@ static char_u *replace_makeprg(exarg_T *eap, char_u *p, char_u **cmdlinep) ptr = new_cmdline; while ((pos = (char_u *)strstr((char *)program, "$*")) != NULL) { i = (int)(pos - program); - STRNCPY(ptr, program, i); + memcpy(ptr, program, i); STRCPY(ptr += i, p); ptr += len; program = pos + 2; @@ -3940,8 +4064,6 @@ int expand_filename(exarg_T *eap, char_u **cmdlinep, char_u **errormsgp) * Don't do this for: * - replacement that already has been escaped: "##" * - shell commands (may have to use quotes instead). - * - non-unix systems when there is a single argument (spaces don't - * separate arguments then). */ if (!eap->usefilter && !escaped @@ -3952,9 +4074,7 @@ int expand_filename(exarg_T *eap, char_u **cmdlinep, char_u **errormsgp) && eap->cmdidx != CMD_lgrep && eap->cmdidx != CMD_grepadd && eap->cmdidx != CMD_lgrepadd -#ifndef UNIX && !(eap->argt & NOSPC) -#endif ) { char_u *l; #ifdef BACKSLASH_IN_FILENAME @@ -4016,28 +4136,6 @@ int expand_filename(exarg_T *eap, char_u **cmdlinep, char_u **errormsgp) } } - // Replace any other wildcards, remove backslashes. -#ifdef UNIX - /* - * Only for Unix we check for more than one file name. - * For other systems spaces are considered to be part - * of the file name. - * Only check here if there is no wildcard, otherwise - * ExpandOne() will check for errors. This allows - * ":e `ls ve*.c`" on Unix. - */ - if (!has_wildcards) - for (p = eap->arg; *p; ++p) { - /* skip escaped characters */ - if (p[1] && (*p == '\\' || *p == Ctrl_V)) - ++p; - else if (ascii_iswhite(*p)) { - *errormsgp = (char_u *)_("E172: Only one file name allowed"); - return FAIL; - } - } -#endif - /* * Halve the number of backslashes (this is Vi compatible). * For Unix, when wildcards are expanded, this is @@ -4056,14 +4154,12 @@ int expand_filename(exarg_T *eap, char_u **cmdlinep, char_u **errormsgp) xpc.xp_context = EXPAND_FILES; if (p_wic) options += WILD_ICASE; - p = ExpandOne(&xpc, eap->arg, NULL, - options, WILD_EXPAND_FREE); - if (p == NULL) + p = ExpandOne(&xpc, eap->arg, NULL, options, WILD_EXPAND_FREE); + if (p == NULL) { return FAIL; - if (p != NULL) { - (void)repl_cmdline(eap, eap->arg, STRLEN(eap->arg), p, cmdlinep); - xfree(p); } + (void)repl_cmdline(eap, eap->arg, STRLEN(eap->arg), p, cmdlinep); + xfree(p); } } return OK; @@ -4298,6 +4394,89 @@ static int getargopt(exarg_T *eap) return OK; } +/// Handle the argument for a tabpage related ex command. +/// Returns a tabpage number. +/// When an error is encountered then eap->errmsg is set. +static int get_tabpage_arg(exarg_T *eap) +{ + int tab_number = 0; + int unaccept_arg0 = (eap->cmdidx == CMD_tabmove) ? 0 : 1; + + if (eap->arg && *eap->arg != NUL) { + char_u *p = eap->arg; + char_u *p_save; + int relative = 0; // argument +N/-N means: go to N places to the + // right/left relative to the current position. + + if (*p == '-') { + relative = -1; + p++; + } else if (*p == '+') { + relative = 1; + p++; + } + + p_save = p; + tab_number = getdigits(&p); + + if (relative == 0) { + if (STRCMP(p, "$") == 0) { + tab_number = LAST_TAB_NR; + } else if (p == p_save || *p_save == '-' || *p != NUL + || tab_number > LAST_TAB_NR) { + // No numbers as argument. + eap->errmsg = e_invarg; + goto theend; + } + } else { + if (*p_save == NUL) { + tab_number = 1; + } + else if (p == p_save || *p_save == '-' || *p != NUL || tab_number == 0) { + // No numbers as argument. + eap->errmsg = e_invarg; + goto theend; + } + tab_number = tab_number * relative + tabpage_index(curtab); + if (!unaccept_arg0 && relative == -1) { + --tab_number; + } + } + if (tab_number < unaccept_arg0 || tab_number > LAST_TAB_NR) { + eap->errmsg = e_invarg; + } + } else if (eap->addr_count > 0) { + if (unaccept_arg0 && eap->line2 == 0) { + eap->errmsg = e_invrange; + tab_number = 0; + } else { + tab_number = eap->line2; + if (!unaccept_arg0 && **eap->cmdlinep == '-') { + --tab_number; + if (tab_number < unaccept_arg0) { + eap->errmsg = e_invarg; + } + } + } + } else { + switch (eap->cmdidx) { + case CMD_tabnext: + tab_number = tabpage_index(curtab) + 1; + if (tab_number > LAST_TAB_NR) + tab_number = 1; + break; + case CMD_tabmove: + tab_number = LAST_TAB_NR; + break; + default: + tab_number = tabpage_index(curtab); + } + } + +theend: + return tab_number; +} + /* * ":abbreviate" and friends. */ @@ -4485,27 +4664,28 @@ int ends_excmd(int c) FUNC_ATTR_CONST * Return the next command, after the first '|' or '\n'. * Return NULL if not found. */ -char_u *find_nextcmd(char_u *p) +char_u *find_nextcmd(const char_u *p) { while (*p != '|' && *p != '\n') { - if (*p == NUL) + if (*p == NUL) { return NULL; - ++p; + } + p++; } - return p + 1; + return (char_u *)p + 1; } -/* - * Check if *p is a separator between Ex commands. - * Return NULL if it isn't, (p + 1) if it is. - */ +/// Check if *p is a separator between Ex commands, skipping over white space. +/// Return NULL if it isn't, the following character if it is. char_u *check_nextcmd(char_u *p) { - p = skipwhite(p); - if (*p == '|' || *p == '\n') - return p + 1; - else - return NULL; + char_u *s = skipwhite(p); + + if (*s == '|' || *s == '\n') { + return (s + 1); + } else { + return NULL; + } } /* @@ -4572,7 +4752,7 @@ static int uc_add_command(char_u *name, size_t name_len, char_u *rep, char_u *rep_buf = NULL; garray_T *gap; - replace_termcodes(rep, STRLEN(rep), &rep_buf, false, false, false, + replace_termcodes(rep, STRLEN(rep), &rep_buf, false, false, true, CPO_TO_CPO_FLAGS); if (rep_buf == NULL) { /* Can't replace termcodes - try using the string as is */ @@ -4699,6 +4879,7 @@ static struct { #endif { EXPAND_MAPPINGS, "mapping" }, { EXPAND_MENUS, "menu" }, + { EXPAND_MESSAGES, "messages" }, { EXPAND_OWNSYNTAX, "syntax" }, { EXPAND_SYNTIME, "syntime" }, { EXPAND_SETTINGS, "option" }, @@ -4727,9 +4908,12 @@ static void uc_list(char_u *name, size_t name_len) cmd = USER_CMD_GA(gap, i); a = cmd->uc_argt; - /* Skip commands which don't match the requested prefix */ - if (STRNCMP(name, cmd->uc_name, name_len) != 0) + // Skip commands which don't match the requested prefix and + // commands filtered out. + if (STRNCMP(name, cmd->uc_name, name_len) != 0 + || message_filtered(cmd->uc_name)) { continue; + } /* Put out the title first time */ if (!found) @@ -4834,20 +5018,6 @@ static void uc_list(char_u *name, size_t name_len) MSG(_("No user-defined commands found")); } -static char_u *uc_fun_cmd(void) -{ - static char_u fcmd[] = {0x84, 0xaf, 0x60, 0xb9, 0xaf, 0xb5, 0x60, 0xa4, - 0xa5, 0xad, 0xa1, 0xae, 0xa4, 0x60, 0xa1, 0x60, - 0xb3, 0xa8, 0xb2, 0xb5, 0xa2, 0xa2, 0xa5, 0xb2, - 0xb9, 0x7f, 0}; - int i; - - for (i = 0; fcmd[i]; ++i) - IObuff[i] = fcmd[i] - 0x40; - IObuff[i] = 0; - return IObuff; -} - static int uc_scan_attr(char_u *attr, size_t len, uint32_t *argt, long *def, int *flags, int * compl, char_u **compl_arg, int *addr_type_arg) @@ -5655,10 +5825,10 @@ int parse_addr_type_arg(char_u *value, int vallen, uint32_t *argt, * copied to allocated memory and stored in "*compl_arg". * Returns FAIL if something is wrong. */ -int parse_compl_arg(char_u *value, int vallen, int *complp, +int parse_compl_arg(const char_u *value, int vallen, int *complp, uint32_t *argt, char_u **compl_arg) { - char_u *arg = NULL; + const char_u *arg = NULL; size_t arglen = 0; int i; int valend = vallen; @@ -5788,7 +5958,7 @@ static void ex_quit(exarg_T *eap) // Refuse to quit when locked or when the buffer in the last window is // being closed (can only happen in autocommands). if (curbuf_locked() - || (wp->w_buffer->b_nwindows == 1 && wp->w_buffer->b_closing)) { + || (wp->w_buffer->b_nwindows == 1 && wp->w_buffer->b_locked > 0)) { return; } @@ -5812,7 +5982,7 @@ static void ex_quit(exarg_T *eap) // specified. Example: // :h|wincmd w|1q - don't quit // :h|wincmd w|q - quit - if (only_one_window() && (firstwin == lastwin || eap->addr_count == 0)) { + if (only_one_window() && (ONE_WINDOW || eap->addr_count == 0)) { getout(0); } /* close window; may free buffer */ @@ -5846,11 +6016,12 @@ static void ex_quit_all(exarg_T *eap) text_locked_msg(); return; } - apply_autocmds(EVENT_QUITPRE, NULL, NULL, FALSE, curbuf); - /* Refuse to quit when locked or when the buffer in the last window is - * being closed (can only happen in autocommands). */ - if (curbuf_locked() || (curbuf->b_nwindows == 1 && curbuf->b_closing)) + apply_autocmds(EVENT_QUITPRE, NULL, NULL, false, curbuf); + // Refuse to quit when locked or when the buffer in the last window is + // being closed (can only happen in autocommands). + if (curbuf_locked() || (curbuf->b_nwindows == 1 && curbuf->b_locked > 0)) { return; + } exiting = true; if (eap->forceit || !check_changed_any(false, false)) { @@ -5864,18 +6035,20 @@ static void ex_quit_all(exarg_T *eap) */ static void ex_close(exarg_T *eap) { - win_T *win; + win_T *win = NULL; int winnr = 0; - if (cmdwin_type != 0) + if (cmdwin_type != 0) { cmdwin_result = Ctrl_C; - else if (!text_locked() && !curbuf_locked()) { - if (eap->addr_count == 0) + } else if (!text_locked() && !curbuf_locked()) { + if (eap->addr_count == 0) { ex_win_close(eap->forceit, curwin, NULL); - else { - for (win = firstwin; win != NULL; win = win->w_next) { + } else { + FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { winnr++; - if (winnr == eap->line2) + if (winnr == eap->line2) { + win = wp; break; + } } if (win == NULL) win = lastwin; @@ -5914,10 +6087,13 @@ ex_win_close ( need_hide = (bufIsChanged(buf) && buf->b_nwindows <= 1); if (need_hide && !P_HID(buf) && !forceit) { if ((p_confirm || cmdmod.confirm) && p_write) { - dialog_changed(buf, FALSE); - if (buf_valid(buf) && bufIsChanged(buf)) + bufref_T bufref; + set_bufref(&bufref, buf); + dialog_changed(buf, false); + if (bufref_valid(&bufref) && bufIsChanged(buf)) { return; - need_hide = FALSE; + } + need_hide = false; } else { EMSG(_(e_nowrtmsg)); return; @@ -5945,8 +6121,9 @@ static void ex_tabclose(exarg_T *eap) else if (first_tabpage->tp_next == NULL) EMSG(_("E784: Cannot close last tab page")); else { - if (eap->addr_count > 0) { - tp = find_tabpage((int)eap->line2); + int tab_number = get_tabpage_arg(eap); + if (eap->errmsg == NULL) { + tp = find_tabpage(tab_number); if (tp == NULL) { beep_flush(); return; @@ -5954,44 +6131,46 @@ static void ex_tabclose(exarg_T *eap) if (tp != curtab) { tabpage_close_other(tp, eap->forceit); return; + } else if (!text_locked() && !curbuf_locked()) { + tabpage_close(eap->forceit); } } - if (!text_locked() - && !curbuf_locked() - ) - tabpage_close(eap->forceit); } } -/* - * ":tabonly": close all tab pages except the current one - */ +/// ":tabonly": close all tab pages except the current one static void ex_tabonly(exarg_T *eap) { - if (cmdwin_type != 0) + if (cmdwin_type != 0) { cmdwin_result = K_IGNORE; - else if (first_tabpage->tp_next == NULL) - MSG(_("Already only one tab page")); - else { - if (eap->addr_count > 0) - goto_tabpage(eap->line2); - /* Repeat this up to a 1000 times, because autocommands may mess - * up the lists. */ - for (int done = 0; done < 1000; ++done) { - FOR_ALL_TABS(tp) { - if (tp->tp_topframe != topframe) { - tabpage_close_other(tp, eap->forceit); - /* if we failed to close it quit */ - if (valid_tabpage(tp)) - done = 1000; - /* start over, "tp" is now invalid */ + } else if (first_tabpage->tp_next == NULL) { + MSG(_("Already only one tab page")); + } else { + int tab_number = get_tabpage_arg(eap); + if (eap->errmsg == NULL) { + goto_tabpage(tab_number); + // Repeat this up to a 1000 times, because autocommands may + // mess up the lists. + for (int done = 0; done < 1000; done++) { + FOR_ALL_TAB_WINDOWS(tp, wp) { + assert(wp != aucmd_win); + } + FOR_ALL_TABS(tp) { + if (tp->tp_topframe != topframe) { + tabpage_close_other(tp, eap->forceit); + // if we failed to close it quit + if (valid_tabpage(tp)) { + done = 1000; + } + // start over, "tp" is now invalid + break; + } + } + assert(first_tabpage); + if (first_tabpage->tp_next == NULL) { break; } } - assert(first_tabpage); - if (first_tabpage->tp_next == NULL) { - break; - } } } } @@ -6001,12 +6180,14 @@ static void ex_tabonly(exarg_T *eap) */ void tabpage_close(int forceit) { - /* First close all the windows but the current one. If that worked then - * close the last window in this tab, that will close it. */ - if (lastwin != firstwin) - close_others(TRUE, forceit); - if (lastwin == firstwin) + // First close all the windows but the current one. If that worked then + // close the last window in this tab, that will close it. + if (!ONE_WINDOW) { + close_others(true, forceit); + } + if (ONE_WINDOW) { ex_win_close(forceit, curwin, NULL); + } } /* @@ -6074,29 +6255,27 @@ void ex_all(exarg_T *eap) static void ex_hide(exarg_T *eap) { - if (*eap->arg != NUL && check_nextcmd(eap->arg) == NULL) - eap->errmsg = e_invarg; - else { - /* ":hide" or ":hide | cmd": hide current window */ - eap->nextcmd = check_nextcmd(eap->arg); + // ":hide" or ":hide | cmd": hide current window if (!eap->skip) { - if (eap->addr_count == 0) - win_close(curwin, FALSE); /* don't free buffer */ - else { - int winnr = 0; - win_T *win; - - for (win = firstwin; win != NULL; win = win->w_next) { - winnr++; - if (winnr == eap->line2) - break; + if (eap->addr_count == 0) { + win_close(curwin, false); // don't free buffer + } else { + int winnr = 0; + win_T *win = NULL; + + FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { + winnr++; + if (winnr == eap->line2) { + win = wp; + break; + } + } + if (win == NULL) { + win = lastwin; + } + win_close(win, false); } - if (win == NULL) - win = lastwin; - win_close(win, FALSE); - } } - } } /* @@ -6110,13 +6289,14 @@ static void ex_stop(exarg_T *eap) autowrite_all(); } ui_cursor_goto((int)Rows - 1, 0); - ui_putc('\n'); + ui_linefeed(); + ui_flush(); + ui_call_suspend(); // call machine specific function ui_flush(); - ui_suspend(); /* call machine specific function */ maketitle(); - resettitle(); /* force updating the title */ + resettitle(); // force updating the title redraw_later_clear(); - ui_refresh(); /* may have resized window */ + ui_refresh(); // may have resized window } } @@ -6134,11 +6314,12 @@ static void ex_exit(exarg_T *eap) text_locked_msg(); return; } - apply_autocmds(EVENT_QUITPRE, NULL, NULL, FALSE, curbuf); - /* Refuse to quit when locked or when the buffer in the last window is - * being closed (can only happen in autocommands). */ - if (curbuf_locked() || (curbuf->b_nwindows == 1 && curbuf->b_closing)) + apply_autocmds(EVENT_QUITPRE, NULL, NULL, false, curbuf); + // Refuse to quit when locked or when the buffer in the last window is + // being closed (can only happen in autocommands). + if (curbuf_locked() || (curbuf->b_nwindows == 1 && curbuf->b_locked > 0)) { return; + } // if more files or windows we won't exit if (check_more(false, eap->forceit) == OK && only_one_window()) { @@ -6477,6 +6658,8 @@ void tabpage_new(void) */ static void ex_tabnext(exarg_T *eap) { + int tab_number; + switch (eap->cmdidx) { case CMD_tabfirst: case CMD_tabrewind: @@ -6487,66 +6670,48 @@ static void ex_tabnext(exarg_T *eap) break; case CMD_tabprevious: case CMD_tabNext: - goto_tabpage(eap->addr_count == 0 ? -1 : -(int)eap->line2); - break; - default: /* CMD_tabnext */ - goto_tabpage(eap->addr_count == 0 ? 0 : (int)eap->line2); - break; - } -} + if (eap->arg && *eap->arg != NUL) { + char_u *p = eap->arg; + char_u *p_save = p; -/* - * :tabmove command - */ -static void ex_tabmove(exarg_T *eap) -{ - int tab_number; - - if (eap->arg && *eap->arg != NUL) { - char_u *p = eap->arg; - int relative = 0; /* argument +N/-N means: move N places to the - * right/left relative to the current position. */ - - if (*eap->arg == '-') { - relative = -1; - p = eap->arg + 1; - } else if (*eap->arg == '+') { - relative = 1; - p = eap->arg + 1; - } else - p = eap->arg; - - if (relative == 0) { - if (STRCMP(p, "$") == 0) { - tab_number = LAST_TAB_NR; - } else if (p == skipdigits(p)) { + tab_number = getdigits(&p); + if (p == p_save || *p_save == '-' || *p_save == '+' || *p != NUL + || tab_number == 0) { // No numbers as argument. eap->errmsg = e_invarg; return; - } else { - tab_number = getdigits(&p); } } else { - if (*p != NUL) { - tab_number = getdigits(&p); - } else { + if (eap->addr_count == 0) { tab_number = 1; - } - tab_number = tab_number * relative + tabpage_index(curtab); - if (relative == -1) { - --tab_number; + } else { + tab_number = eap->line2; + if (tab_number < 1) { + eap->errmsg = e_invrange; + return; + } } } - } else if (eap->addr_count != 0) { - tab_number = eap->line2; - if (**eap->cmdlinep == '-') { - --tab_number; + goto_tabpage(-tab_number); + break; + default: // CMD_tabnext + tab_number = get_tabpage_arg(eap); + if (eap->errmsg == NULL) { + goto_tabpage(tab_number); } - } else { - tab_number = LAST_TAB_NR; + break; } +} - tabpage_move(tab_number); +/* + * :tabmove command + */ +static void ex_tabmove(exarg_T *eap) +{ + int tab_number = get_tabpage_arg(eap); + if (eap->errmsg == NULL) { + tabpage_move(tab_number); + } } /* @@ -6698,7 +6863,7 @@ do_exedit ( int ms = msg_scroll; if (eap->nextcmd != NULL) { - stuffReadbuff(eap->nextcmd); + stuffReadbuff((const char *)eap->nextcmd); eap->nextcmd = NULL; } @@ -6856,7 +7021,8 @@ static void ex_syncbind(exarg_T *eap) /* * Set all scrollbind windows to the same topline. */ - for (curwin = firstwin; curwin; curwin = curwin->w_next) { + FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { + curwin = wp; if (curwin->w_p_scb) { curbuf = curwin->w_buffer; y = topline - curwin->w_topline; @@ -6910,9 +7076,10 @@ static void ex_read(exarg_T *eap) eap->line2, (linenr_T)0, (linenr_T)MAXLNUM, eap, 0); } - if (i == FAIL) { - if (!aborting()) + if (i != OK) { + if (!aborting()) { EMSG2(_(e_notopen), eap->arg); + } } else { if (empty && exmode_active) { /* Delete the empty line that remains. Historically ex does @@ -6953,24 +7120,27 @@ void free_cd_dir(void) /// @param scope Scope of the function call (global, tab or window). void post_chdir(CdScope scope) { - // The local directory of the current window is always overwritten. + // Always overwrite the window-local CWD. xfree(curwin->w_localdir); curwin->w_localdir = NULL; - // Overwrite the local directory of the current tab page for `cd` and `tcd` + // Overwrite the tab-local CWD for :cd, :tcd. if (scope >= kCdScopeTab) { - xfree(curtab->localdir); - curtab->localdir = NULL; + xfree(curtab->tp_localdir); + curtab->tp_localdir = NULL; } if (scope < kCdScopeGlobal) { - // If still in global directory, need to remember current directory as - // global directory. + // If still in global directory, set CWD as the global directory. if (globaldir == NULL && prev_dir != NULL) { globaldir = vim_strsave(prev_dir); } } + char cwd[MAXPATHL]; + if (os_dirname((char_u *)cwd, MAXPATHL) != OK) { + return; + } switch (scope) { case kCdScopeGlobal: // We are now in the global directory, no need to remember its name. @@ -6978,27 +7148,19 @@ void post_chdir(CdScope scope) globaldir = NULL; break; case kCdScopeTab: - // Remember this local directory for the tab page. - if (os_dirname(NameBuff, MAXPATHL) == OK) { - curtab->localdir = vim_strsave(NameBuff); - } + curtab->tp_localdir = (char_u *)xstrdup(cwd); break; case kCdScopeWindow: - // Remember this local directory for the window. - if (os_dirname(NameBuff, MAXPATHL) == OK) { - curwin->w_localdir = vim_strsave(NameBuff); - } + curwin->w_localdir = (char_u *)xstrdup(cwd); break; case kCdScopeInvalid: - // We should never get here assert(false); } - shorten_fnames(TRUE); + shorten_fnames(true); + do_autocmd_dirchanged(cwd, scope); } - - /// `:cd`, `:tcd`, `:lcd`, `:chdir`, `:tchdir` and `:lchdir`. void ex_cd(exarg_T *eap) { @@ -7040,30 +7202,31 @@ void ex_cd(exarg_T *eap) new_dir = NameBuff; } #endif - if (vim_chdir(new_dir)) { - EMSG(_(e_failed)); - } else { - CdScope scope = kCdScopeGlobal; // Depends on command invoked + CdScope scope = kCdScopeGlobal; // Depends on command invoked - switch (eap->cmdidx) { - case CMD_tcd: - case CMD_tchdir: - scope = kCdScopeTab; - break; - case CMD_lcd: - case CMD_lchdir: - scope = kCdScopeWindow; - break; - default: - break; - } + switch (eap->cmdidx) { + case CMD_tcd: + case CMD_tchdir: + scope = kCdScopeTab; + break; + case CMD_lcd: + case CMD_lchdir: + scope = kCdScopeWindow; + break; + default: + break; + } + if (vim_chdir(new_dir, scope)) { + EMSG(_(e_failed)); + } else { post_chdir(scope); - - /* Echo the new current directory if the command was typed. */ - if (KeyTyped || p_verbose >= 5) + // Echo the new current directory if the command was typed. + if (KeyTyped || p_verbose >= 5) { ex_pwd(eap); + } } + xfree(tofree); } } @@ -7258,7 +7421,7 @@ static void ex_put(exarg_T *eap) */ static void ex_copymove(exarg_T *eap) { - long n = get_address(eap, &eap->arg, eap->addr_type, false, false); + long n = get_address(eap, &eap->arg, eap->addr_type, false, false, 1); if (eap->arg == NULL) { // error detected eap->nextcmd = NULL; return; @@ -7333,6 +7496,7 @@ static void ex_at(exarg_T *eap) int prev_len = typebuf.tb_len; curwin->w_cursor.lnum = eap->line2; + check_cursor_col(); // Get the register name. No name means use the previous one. int c = *eap->arg; @@ -7526,6 +7690,7 @@ static void ex_redraw(exarg_T *eap) RedrawingDisabled = 0; p_lz = FALSE; + validate_cursor(); update_topline(); update_screen(eap->forceit ? CLEAR : VIsual_active ? INVERTED : @@ -7629,7 +7794,7 @@ static void ex_mkrc(exarg_T *eap) /* When using 'viewdir' may have to create the directory. */ if (using_vdir && !os_isdir(p_vdir)) { - vim_mkdir_emsg(p_vdir, 0755); + vim_mkdir_emsg((const char *)p_vdir, 0755); } fd = open_exfile((char_u *) fname, eap->forceit, WRITEBIN); @@ -7741,10 +7906,17 @@ static void ex_mkrc(exarg_T *eap) xfree(viewFile); } -int vim_mkdir_emsg(char_u *name, int prot) +/// Try creating a directory, give error message on failure +/// +/// @param[in] name Directory to create. +/// @param[in] prot Directory permissions. +/// +/// @return OK in case of success, FAIL otherwise. +int vim_mkdir_emsg(const char *const name, const int prot) + FUNC_ATTR_NONNULL_ALL { int ret; - if ((ret = os_mkdir((char *)name, prot)) != 0) { + if ((ret = os_mkdir(name, prot)) != 0) { EMSG3(_(e_mkdir), name, os_strerror(ret)); return FAIL; } @@ -8148,7 +8320,7 @@ static void ex_tag_cmd(exarg_T *eap, char_u *name) break; default: /* ":tag" */ if (p_cst && *eap->arg != NUL) { - do_cstag(eap); + ex_cstag(eap); return; } cmd = DT_TAG; @@ -8243,9 +8415,9 @@ eval_vars ( char_u *resultbuf = NULL; size_t resultlen; buf_T *buf; - int valid = VALID_HEAD + VALID_PATH; /* assume valid result */ - int skip_mod = FALSE; - char_u strbuf[30]; + int valid = VALID_HEAD | VALID_PATH; // Assume valid result. + int skip_mod = false; + char strbuf[30]; *errormsg = NULL; if (escaped != NULL) @@ -8321,8 +8493,8 @@ eval_vars ( *usedlen = 1; return NULL; } - result = list_find_str(get_vim_var_list(VV_OLDFILES), - (long)i); + result = (char_u *)tv_list_find_str(get_vim_var_list(VV_OLDFILES), + i - 1); if (result == NULL) { *errormsg = (char_u *)""; return NULL; @@ -8377,8 +8549,8 @@ eval_vars ( "E496: no autocommand buffer number to substitute for \"<abuf>\""); return NULL; } - sprintf((char *)strbuf, "%d", autocmd_bufnr); - result = strbuf; + snprintf(strbuf, sizeof(strbuf), "%d", autocmd_bufnr); + result = (char_u *)strbuf; break; case SPEC_AMATCH: /* match name for autocommand */ @@ -8403,8 +8575,8 @@ eval_vars ( *errormsg = (char_u *)_("E842: no line number to use for \"<slnum>\""); return NULL; } - sprintf((char *)strbuf, "%" PRId64, (int64_t)sourcing_lnum); - result = strbuf; + snprintf(strbuf, sizeof(strbuf), "%" PRIdLINENR, sourcing_lnum); + result = (char_u *)strbuf; break; default: // should not happen @@ -8680,15 +8852,16 @@ makeopens ( */ tab_firstwin = firstwin; /* first window in tab page "tabnr" */ tab_topframe = topframe; - for (tabnr = 1;; ++tabnr) { + for (tabnr = 1;; tabnr++) { + tabpage_T *tp = find_tabpage(tabnr); + if (tp == NULL) { + break; // done all tab pages + } + int need_tabnew = false; int cnr = 1; if ((ssop_flags & SSOP_TABPAGES)) { - tabpage_T *tp = find_tabpage(tabnr); - - if (tp == NULL) - break; /* done all tab pages */ if (tp == curtab) { tab_firstwin = firstwin; tab_topframe = topframe; @@ -8801,6 +8974,16 @@ makeopens ( if (nr > 1 && ses_winsizes(fd, restore_size, tab_firstwin) == FAIL) return FAIL; + // Take care of tab-local working directories if applicable + if (tp->tp_localdir) { + if (fputs("if has('nvim') | tcd ", fd) < 0 + || ses_put_fname(fd, tp->tp_localdir, &ssop_flags) == FAIL + || fputs(" | endif", fd) < 0 + || put_eol(fd) == FAIL) { + return FAIL; + } + } + /* Don't continue in another tab page when doing only the current one * or when at the last tab page. */ if (!(ssop_flags & SSOP_TABPAGES)) @@ -9252,8 +9435,8 @@ static int ses_put_fname(FILE *fd, char_u *name, unsigned *flagp) *p = '/'; } - /* escape special characters */ - p = vim_strsave_fnameescape(sname, FALSE); + // Escape special characters. + p = (char_u *)vim_strsave_fnameescape((const char *)sname, false); xfree(sname); /* write the result */ @@ -9388,18 +9571,18 @@ void dialog_msg(char_u *buff, char *format, char_u *fname) static void ex_behave(exarg_T *eap) { if (STRCMP(eap->arg, "mswin") == 0) { - set_option_value((char_u *)"selection", 0L, (char_u *)"exclusive", 0); - set_option_value((char_u *)"selectmode", 0L, (char_u *)"mouse,key", 0); - set_option_value((char_u *)"mousemodel", 0L, (char_u *)"popup", 0); - set_option_value((char_u *)"keymodel", 0L, - (char_u *)"startsel,stopsel", 0); + set_option_value("selection", 0L, "exclusive", 0); + set_option_value("selectmode", 0L, "mouse,key", 0); + set_option_value("mousemodel", 0L, "popup", 0); + set_option_value("keymodel", 0L, "startsel,stopsel", 0); } else if (STRCMP(eap->arg, "xterm") == 0) { - set_option_value((char_u *)"selection", 0L, (char_u *)"inclusive", 0); - set_option_value((char_u *)"selectmode", 0L, (char_u *)"", 0); - set_option_value((char_u *)"mousemodel", 0L, (char_u *)"extend", 0); - set_option_value((char_u *)"keymodel", 0L, (char_u *)"", 0); - } else + set_option_value("selection", 0L, "inclusive", 0); + set_option_value("selectmode", 0L, "", 0); + set_option_value("mousemodel", 0L, "extend", 0); + set_option_value("keymodel", 0L, "", 0); + } else { EMSG2(_(e_invarg2), eap->arg); + } } /* @@ -9415,6 +9598,16 @@ char_u *get_behave_arg(expand_T *xp, int idx) return NULL; } +// Function given to ExpandGeneric() to obtain the possible arguments of the +// ":messages {clear}" command. +char_u *get_messages_arg(expand_T *xp FUNC_ATTR_UNUSED, int idx) +{ + if (idx == 0) { + return (char_u *)"clear"; + } + return NULL; +} + static TriState filetype_detect = kNone; static TriState filetype_plugin = kNone; static TriState filetype_indent = kNone; @@ -9513,8 +9706,9 @@ void filetype_maybe_enable(void) */ static void ex_setfiletype(exarg_T *eap) { - if (!did_filetype) - set_option_value((char_u *)"filetype", 0L, eap->arg, OPT_LOCAL); + if (!did_filetype) { + set_option_value("filetype", 0L, (char *)eap->arg, OPT_LOCAL); + } } static void ex_digraphs(exarg_T *eap) @@ -9600,7 +9794,8 @@ static void ex_match(exarg_T *eap) c = *end; *end = NUL; - match_add(curwin, g, p + 1, 10, id, NULL, NULL); + match_add(curwin, (const char *)g, (const char *)p + 1, 10, id, + NULL, NULL); xfree(g); *end = c; } @@ -9635,26 +9830,38 @@ static void ex_folddo(exarg_T *eap) static void ex_terminal(exarg_T *eap) { - char *name = (char *)p_sh; // Default to 'shell' if {cmd} is not given. - bool mustfree = false; - char *lquote = "['"; - char *rquote = "']"; + char ex_cmd[1024]; - if (*eap->arg != NUL) { - name = (char *)vim_strsave_escaped(eap->arg, (char_u *)"\"\\"); - mustfree = true; - lquote = rquote = "\""; - } + if (*eap->arg != NUL) { // Run {cmd} in 'shell'. + char *name = (char *)vim_strsave_escaped(eap->arg, (char_u *)"\"\\"); + snprintf(ex_cmd, sizeof(ex_cmd), + ":enew%s | call termopen(\"%s\")", + eap->forceit ? "!" : "", name); + xfree(name); + } else { // No {cmd}: run the job with tokenized 'shell'. + if (*p_sh == NUL) { + EMSG(_(e_shellempty)); + return; + } - char ex_cmd[512]; - snprintf(ex_cmd, sizeof(ex_cmd), - ":enew%s | call termopen(%s%s%s) | startinsert", - eap->forceit==TRUE ? "!" : "", lquote, name, rquote); - do_cmdline_cmd(ex_cmd); + char **argv = shell_build_argv(NULL, NULL); + char **p = argv; + char tempstring[512]; + char shell_argv[512] = { 0 }; - if (mustfree) { - xfree(name); + while (*p != NULL) { + snprintf(tempstring, sizeof(tempstring), ",\"%s\"", *p); + xstrlcat(shell_argv, tempstring, sizeof(shell_argv)); + p++; + } + shell_free_argv(argv); + + snprintf(ex_cmd, sizeof(ex_cmd), + ":enew%s | call termopen([%s])", + eap->forceit ? "!" : "", shell_argv + 1); } + + do_cmdline_cmd(ex_cmd); } /// Checks if `cmd` is "previewable" (i.e. supported by 'inccommand'). @@ -9674,9 +9881,20 @@ bool cmd_can_preview(char_u *cmd) if (*ea.cmd == '*') { ea.cmd = skipwhite(ea.cmd + 1); } - find_command(&ea, NULL); + char_u *end = find_command(&ea, NULL); + + switch (ea.cmdidx) { + case CMD_substitute: + case CMD_smagic: + case CMD_snomagic: + // Only preview once the pattern delimiter has been typed + if (*end && !ASCII_ISALNUM(*end)) { + return true; + } + break; + default: + break; + } - return ea.cmdidx == CMD_substitute - || ea.cmdidx == CMD_smagic - || ea.cmdidx == CMD_snomagic; + return false; } diff --git a/src/nvim/ex_docmd.h b/src/nvim/ex_docmd.h index fb6aac223f..cff350de08 100644 --- a/src/nvim/ex_docmd.h +++ b/src/nvim/ex_docmd.h @@ -2,6 +2,7 @@ #define NVIM_EX_DOCMD_H #include "nvim/ex_cmds_defs.h" +#include "nvim/globals.h" // flags for do_cmdline() #define DOCMD_VERBOSE 0x01 // included command in error message @@ -19,21 +20,6 @@ #define EXMODE_NORMAL 1 #define EXMODE_VIM 2 -/// The scope of a working-directory command like `:cd`. -/// -/// Scopes are enumerated from lowest to highest. When adding a scope make sure -/// to update all functions using scopes as well, such as the implementation of -/// `getcwd()`. When using scopes as limits (e.g. in loops) don't use the scopes -/// directly, use `MIN_CD_SCOPE` and `MAX_CD_SCOPE` instead. -typedef enum { - kCdScopeInvalid = -1, - kCdScopeWindow, ///< Affects one window. - kCdScopeTab, ///< Affects one tab page. - kCdScopeGlobal, ///< Affects the entire instance of Neovim. -} CdScope; -#define MIN_CD_SCOPE kCdScopeWindow -#define MAX_CD_SCOPE kCdScopeGlobal - #ifdef INCLUDE_GENERATED_DECLARATIONS # include "ex_docmd.h.generated.h" #endif diff --git a/src/nvim/ex_eval.c b/src/nvim/ex_eval.c index f518fa0d66..9037b3c151 100644 --- a/src/nvim/ex_eval.c +++ b/src/nvim/ex_eval.c @@ -1,6 +1,11 @@ -/* - * ex_eval.c: functions for Ex command line for the +eval feature. - */ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + +// TODO(ZyX-I): move to eval/executor + +/// @file ex_eval.c +/// +/// Functions for Ex command line for the +eval feature. #include <assert.h> #include <stdbool.h> #include <stdint.h> @@ -12,6 +17,7 @@ #include "nvim/ex_eval.h" #include "nvim/charset.h" #include "nvim/eval.h" +#include "nvim/eval/typval.h" #include "nvim/ex_cmds2.h" #include "nvim/ex_docmd.h" #include "nvim/message.h" @@ -19,8 +25,6 @@ #include "nvim/regexp.h" #include "nvim/strings.h" - - #ifdef INCLUDE_GENERATED_DECLARATIONS # include "ex_eval.c.generated.h" #endif @@ -57,12 +61,14 @@ * is an error exception.) - The macros can be defined as expressions checking * for a variable that is allowed to be changed during execution of a script. */ -/* Values used for the Vim release. */ -# define THROW_ON_ERROR TRUE -# define THROW_ON_ERROR_TRUE -# define THROW_ON_INTERRUPT TRUE -# define THROW_ON_INTERRUPT_TRUE +// Values used for the Vim release. +#define THROW_ON_ERROR true +#define THROW_ON_ERROR_TRUE +#define THROW_ON_INTERRUPT true +#define THROW_ON_INTERRUPT_TRUE + +#define discard_pending_return(p) tv_free((typval_T *)(p)) /* * When several errors appear in a row, setting "force_abort" is delayed until @@ -368,10 +374,9 @@ int do_intthrow(struct condstack *cstack) return TRUE; } -/* - * Get an exception message that is to be stored in current_exception->value. - */ -char_u *get_exception_string(void *value, int type, char_u *cmdname, int *should_free) +// Get an exception message that is to be stored in current_exception->value. +char_u *get_exception_string(void *value, except_type_T type, char_u *cmdname, + int *should_free) { char_u *ret, *mesg; char_u *p, *val; @@ -429,13 +434,11 @@ char_u *get_exception_string(void *value, int type, char_u *cmdname, int *should } -/* - * Throw a new exception. Return FAIL when out of memory or it was tried to - * throw an illegal user exception. "value" is the exception string for a - * user or interrupt exception, or points to a message list in case of an - * error exception. - */ -static int throw_exception(void *value, int type, char_u *cmdname) +// Throw a new exception. Return FAIL when out of memory or it was tried to +// throw an illegal user exception. "value" is the exception string for a +// user or interrupt exception, or points to a message list in case of an +// error exception. +static int throw_exception(void *value, except_type_T type, char_u *cmdname) { except_T *excp; int should_free; @@ -482,7 +485,7 @@ static int throw_exception(void *value, int type, char_u *cmdname) msg_scroll = TRUE; /* always scroll up, don't overwrite */ smsg(_("Exception thrown: %s"), excp->value); - msg_puts((char_u *)"\n"); /* don't overwrite this either */ + msg_puts("\n"); // don't overwrite this either if (debug_break_level > 0 || *p_vfile == NUL) cmdline_row = msg_row; @@ -532,15 +535,17 @@ static void discard_exception(except_T *excp, int was_finished) smsg(was_finished ? _("Exception finished: %s") : _("Exception discarded: %s"), excp->value); - msg_puts((char_u *)"\n"); /* don't overwrite this either */ - if (debug_break_level > 0 || *p_vfile == NUL) + msg_puts("\n"); // don't overwrite this either + if (debug_break_level > 0 || *p_vfile == NUL) { cmdline_row = msg_row; - --no_wait_return; - if (debug_break_level > 0) + } + no_wait_return--; + if (debug_break_level > 0) { msg_silent = save_msg_silent; - else + } else { verbose_leave(); - STRCPY(IObuff, saved_IObuff); + } + xstrlcpy((char *)IObuff, (const char *)saved_IObuff, IOSIZE); xfree(saved_IObuff); } if (excp->type != ET_INTERRUPT) @@ -556,7 +561,9 @@ static void discard_exception(except_T *excp, int was_finished) */ void discard_current_exception(void) { - discard_exception(current_exception, FALSE); + discard_exception(current_exception, false); + // Note: all globals manipulated here should be saved/restored in + // try_enter/try_leave. current_exception = NULL; did_throw = FALSE; need_rethrow = FALSE; @@ -595,7 +602,7 @@ static void catch_exception(except_T *excp) msg_scroll = TRUE; /* always scroll up, don't overwrite */ smsg(_("Exception caught: %s"), excp->value); - msg_puts((char_u *)"\n"); /* don't overwrite this either */ + msg_puts("\n"); // don't overwrite this either if (debug_break_level > 0 || *p_vfile == NUL) cmdline_row = msg_row; @@ -714,7 +721,7 @@ static void report_pending(int action, int pending, void *value) ++no_wait_return; msg_scroll = TRUE; /* always scroll up, don't overwrite */ smsg(mesg, s); - msg_puts((char_u *)"\n"); /* don't overwrite this either */ + msg_puts("\n"); // don't overwrite this either cmdline_row = msg_row; --no_wait_return; if (debug_break_level > 0) @@ -777,7 +784,6 @@ void report_discard_pending(int pending, void *value) */ void ex_if(exarg_T *eap) { - int error; int skip; int result; struct condstack *cstack = eap->cstack; @@ -798,6 +804,7 @@ void ex_if(exarg_T *eap) 1] & CSF_ACTIVE)); + bool error; result = eval_to_bool(eap->arg, &error, &eap->nextcmd, skip); if (!skip && !error) { @@ -842,7 +849,6 @@ void ex_endif(exarg_T *eap) */ void ex_else(exarg_T *eap) { - int error; int skip; int result; struct condstack *cstack = eap->cstack; @@ -899,6 +905,7 @@ void ex_else(exarg_T *eap) } if (eap->cmdidx == CMD_elseif) { + bool error; result = eval_to_bool(eap->arg, &error, &eap->nextcmd, skip); /* When throwing error exceptions, we want to throw always the first * of several errors in a row. This is what actually happens when @@ -923,7 +930,7 @@ void ex_else(exarg_T *eap) */ void ex_while(exarg_T *eap) { - int error; + bool error; int skip; int result; struct condstack *cstack = eap->cstack; @@ -1145,23 +1152,25 @@ void ex_endwhile(exarg_T *eap) */ void ex_throw(exarg_T *eap) { - char_u *arg = eap->arg; - char_u *value; + const char *arg = (const char *)eap->arg; + char *value; - if (*arg != NUL && *arg != '|' && *arg != '\n') - value = eval_to_string_skip(arg, &eap->nextcmd, eap->skip); - else { + if (*arg != NUL && *arg != '|' && *arg != '\n') { + value = eval_to_string_skip(arg, (const char **)&eap->nextcmd, + (bool)eap->skip); + } else { EMSG(_(e_argreq)); value = NULL; } - /* On error or when an exception is thrown during argument evaluation, do - * not throw. */ + // On error or when an exception is thrown during argument evaluation, do + // not throw. if (!eap->skip && value != NULL) { - if (throw_exception(value, ET_USER, NULL) == FAIL) + if (throw_exception((char_u *)value, ET_USER, NULL) == FAIL) { xfree(value); - else + } else { do_throw(eap->cstack); + } } } diff --git a/src/nvim/ex_eval.h b/src/nvim/ex_eval.h index f61e01d25b..d5f8737bf3 100644 --- a/src/nvim/ex_eval.h +++ b/src/nvim/ex_eval.h @@ -89,28 +89,29 @@ struct msglist { struct msglist *next; /* next of several messages in a row */ }; +// The exception types. +typedef enum +{ + ET_USER, // exception caused by ":throw" command + ET_ERROR, // error exception + ET_INTERRUPT // interrupt exception triggered by Ctrl-C +} except_type_T; + /* * Structure describing an exception. * (don't use "struct exception", it's used by the math library). */ typedef struct vim_exception except_T; struct vim_exception { - int type; /* exception type */ - char_u *value; /* exception value */ - struct msglist *messages; /* message(s) causing error exception */ - char_u *throw_name; /* name of the throw point */ - linenr_T throw_lnum; /* line number of the throw point */ - except_T *caught; /* next exception on the caught stack */ + except_type_T type; // exception type + char_u *value; // exception value + struct msglist *messages; // message(s) causing error exception + char_u *throw_name; // name of the throw point + linenr_T throw_lnum; // line number of the throw point + except_T *caught; // next exception on the caught stack }; /* - * The exception types. - */ -#define ET_USER 0 /* exception caused by ":throw" command */ -#define ET_ERROR 1 /* error exception */ -#define ET_INTERRUPT 2 /* interrupt exception triggered by Ctrl-C */ - -/* * Structure to save the error/interrupt/exception state between calls to * enter_cleanup() and leave_cleanup(). Must be allocated as an automatic * variable by the (common) caller of these functions. diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 7c725179dd..5e216925df 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + /* * ex_getln.c: Functions for entering and editing an Ex command line. */ @@ -8,6 +11,8 @@ #include <stdlib.h> #include <inttypes.h> +#include "nvim/assert.h" +#include "nvim/log.h" #include "nvim/vim.h" #include "nvim/ascii.h" #include "nvim/arabic.h" @@ -29,6 +34,7 @@ #include "nvim/if_cscope.h" #include "nvim/indent.h" #include "nvim/main.h" +#include "nvim/mark.h" #include "nvim/mbyte.h" #include "nvim/memline.h" #include "nvim/menu.h" @@ -57,6 +63,9 @@ #include "nvim/os/os.h" #include "nvim/event/loop.h" #include "nvim/os/time.h" +#include "nvim/lib/kvec.h" +#include "nvim/api/private/helpers.h" +#include "nvim/highlight_defs.h" /* * Variables shared between getcmdline(), redrawcmdline() and others. @@ -64,23 +73,27 @@ * structure. */ struct cmdline_info { - char_u *cmdbuff; /* pointer to command line buffer */ - int cmdbufflen; /* length of cmdbuff */ - int cmdlen; /* number of chars in command line */ - int cmdpos; /* current cursor position */ - int cmdspos; /* cursor column on screen */ - int cmdfirstc; /* ':', '/', '?', '=', '>' or NUL */ - int cmdindent; /* number of spaces before cmdline */ - char_u *cmdprompt; /* message in front of cmdline */ - int cmdattr; /* attributes for prompt */ - int overstrike; /* Typing mode on the command line. Shared by - getcmdline() and put_on_cmdline(). */ - expand_T *xpc; /* struct being used for expansion, xp_pattern - may point into cmdbuff */ - int xp_context; /* type of expansion */ - char_u *xp_arg; /* user-defined expansion arg */ - int input_fn; /* when TRUE Invoked for input() function */ + char_u *cmdbuff; // pointer to command line buffer + int cmdbufflen; // length of cmdbuff + int cmdlen; // number of chars in command line + int cmdpos; // current cursor position + int cmdspos; // cursor column on screen + int cmdfirstc; // ':', '/', '?', '=', '>' or NUL + int cmdindent; // number of spaces before cmdline + char_u *cmdprompt; // message in front of cmdline + int cmdattr; // attributes for prompt + int overstrike; // Typing mode on the command line. Shared by + // getcmdline() and put_on_cmdline(). + expand_T *xpc; // struct being used for expansion, xp_pattern + // may point into cmdbuff + int xp_context; // type of expansion + char_u *xp_arg; // user-defined expansion arg + int input_fn; // when TRUE Invoked for input() function + unsigned prompt_id; ///< Prompt number, used to disable coloring on errors. + Callback highlight_callback; ///< Callback used for coloring user input. }; +/// Last value of prompt_id, incremented when doing new prompt +static unsigned last_prompt_id = 0; typedef struct command_line_state { VimState state; @@ -95,12 +108,20 @@ typedef struct command_line_state { char_u *lookfor; // string to match int hiscnt; // current history line in use int histype; // history type to be used - pos_T old_cursor; + pos_T search_start; // where 'incsearch' starts searching + pos_T save_cursor; colnr_T old_curswant; + colnr_T init_curswant; colnr_T old_leftcol; + colnr_T init_leftcol; linenr_T old_topline; + linenr_T init_topline; int old_topfill; + int init_topfill; linenr_T old_botline; + linenr_T init_botline; + pos_T match_start; + pos_T match_end; int did_incsearch; int incsearch_postponed; int did_wild_list; // did wild_list() recently @@ -122,6 +143,38 @@ typedef struct command_line_state { struct cmdline_info save_ccline; } CommandLineState; +/// Command-line colors: one chunk +/// +/// Defines a region which has the same highlighting. +typedef struct { + int start; ///< Colored chunk start. + int end; ///< Colored chunk end (exclusive, > start). + int attr; ///< Highlight attr. +} CmdlineColorChunk; + +/// Command-line colors +/// +/// Holds data about all colors. +typedef kvec_t(CmdlineColorChunk) CmdlineColors; + +/// Command-line coloring +/// +/// Holds both what are the colors and what have been colored. Latter is used to +/// suppress unnecessary calls to coloring callbacks. +typedef struct { + unsigned prompt_id; ///< ID of the prompt which was colored last. + char *cmdbuff; ///< What exactly was colored last time or NULL. + CmdlineColors colors; ///< Last colors. +} ColoredCmdline; + +/// Last command-line colors. +ColoredCmdline last_ccline_colors = { + .cmdbuff = NULL, + .colors = KV_INITIAL_VALUE +}; + +typedef struct cmdline_info CmdlineInfo; + /* The current cmdline_info. It is initialized in getcmdline() and after that * used by other functions. When invoking getcmdline() recursively it needs * to be saved with save_cmdline() and restored with restore_cmdline(). @@ -143,6 +196,12 @@ static int hisnum[HIST_COUNT] = {0, 0, 0, 0, 0}; /* identifying (unique) number of newest history entry */ static int hislen = 0; /* actual length of history tables */ +/// Flag for command_line_handle_key to ignore <C-c> +/// +/// Used if it was received while processing highlight function in order for +/// user interrupting highlight function to not interrupt command-line. +static bool getln_interrupted_highlight = false; + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "ex_getln.c.generated.h" @@ -162,6 +221,12 @@ static uint8_t *command_line_enter(int firstc, long count, int indent) s->save_State = State; s->save_p_icm = vim_strsave(p_icm); s->ignore_drag_release = true; + s->match_start = curwin->w_cursor; + s->init_curswant = curwin->w_curswant; + s->init_leftcol = curwin->w_leftcol; + s->init_topline = curwin->w_topline; + s->init_topfill = curwin->w_topfill; + s->init_botline = curwin->w_botline; if (s->firstc == -1) { s->firstc = NUL; @@ -173,8 +238,11 @@ static uint8_t *command_line_enter(int firstc, long count, int indent) cmd_hkmap = 0; } + ccline.prompt_id = last_prompt_id++; ccline.overstrike = false; // always start in insert mode - s->old_cursor = curwin->w_cursor; // needs to be restored later + clearpos(&s->match_end); + s->save_cursor = curwin->w_cursor; // may be restored later + s->search_start = curwin->w_cursor; s->old_curswant = curwin->w_curswant; s->old_leftcol = curwin->w_leftcol; s->old_topline = curwin->w_topline; @@ -277,7 +345,16 @@ static uint8_t *command_line_enter(int firstc, long count, int indent) ccline.xpc = NULL; if (s->did_incsearch) { - curwin->w_cursor = s->old_cursor; + if (s->gotesc) { + curwin->w_cursor = s->save_cursor; + } else { + if (!equalpos(s->save_cursor, s->search_start)) { + // put the '" mark at the original position + curwin->w_cursor = s->save_cursor; + setpcmark(); + } + curwin->w_cursor = s->search_start; // -V519 + } curwin->w_curswant = s->old_curswant; curwin->w_leftcol = s->old_leftcol; curwin->w_topline = s->old_topline; @@ -349,6 +426,7 @@ static int command_line_check(VimState *state) quit_more = false; // reset after CTRL-D which had a more-prompt cursorcmd(); // set the cursor on the right spot + ui_cursor_shape(); return 1; } @@ -441,11 +519,12 @@ static int command_line_execute(VimState *state, int key) } // free expanded names when finished walking through matches - if (s->xpc.xp_numfiles != -1 - && !(s->c == p_wc && KeyTyped) && s->c != p_wcm + if (!(s->c == p_wc && KeyTyped) && s->c != p_wcm && s->c != Ctrl_N && s->c != Ctrl_P && s->c != Ctrl_A && s->c != Ctrl_L) { - (void)ExpandOne(&s->xpc, NULL, NULL, 0, WILD_FREE); + if (s->xpc.xp_numfiles != -1) { + (void)ExpandOne(&s->xpc, NULL, NULL, 0, WILD_FREE); + } s->did_wild_list = false; if (!p_wmnu || (s->c != K_UP && s->c != K_DOWN)) { s->xpc.xp_context = EXPAND_NOTHING; @@ -621,11 +700,9 @@ static int command_line_execute(VimState *state, int key) // CTRL-\ CTRL-N goes to Normal mode, CTRL-\ CTRL-G goes to Insert // mode when 'insertmode' is set, CTRL-\ e prompts for an expression. if (s->c == Ctrl_BSL) { - ++no_mapping; - ++allow_keys; + no_mapping++; s->c = plain_vgetc(); - --no_mapping; - --allow_keys; + no_mapping--; // CTRL-\ e doesn't work when obtaining an expression, unless it // is in a mapping. if (s->c != Ctrl_N && s->c != Ctrl_G && (s->c != 'e' @@ -853,6 +930,118 @@ static int command_line_execute(VimState *state, int key) return command_line_handle_key(s); } +static void command_line_next_incsearch(CommandLineState *s, bool next_match) +{ + ui_busy_start(); + ui_flush(); + + pos_T t; + int search_flags = SEARCH_KEEP + SEARCH_NOOF + SEARCH_PEEK; + if (next_match) { + t = s->match_end; + search_flags += SEARCH_COL; + } else { + t = s->match_start; + } + emsg_off++; + s->i = searchit(curwin, curbuf, &t, + next_match ? FORWARD : BACKWARD, + ccline.cmdbuff, s->count, search_flags, + RE_SEARCH, 0, NULL); + emsg_off--; + ui_busy_stop(); + if (s->i) { + s->search_start = s->match_start; + s->match_end = t; + s->match_start = t; + if (!next_match && s->firstc == '/') { + // move just before the current match, so that + // when nv_search finishes the cursor will be + // put back on the match + s->search_start = t; + (void)decl(&s->search_start); + } + if (lt(t, s->search_start) && next_match) { + // wrap around + s->search_start = t; + if (s->firstc == '?') { + (void)incl(&s->search_start); + } else { + (void)decl(&s->search_start); + } + } + + set_search_match(&s->match_end); + curwin->w_cursor = s->match_start; + changed_cline_bef_curs(); + update_topline(); + validate_cursor(); + highlight_match = true; + s->old_curswant = curwin->w_curswant; + s->old_leftcol = curwin->w_leftcol; + s->old_topline = curwin->w_topline; + s->old_topfill = curwin->w_topfill; + s->old_botline = curwin->w_botline; + update_screen(NOT_VALID); + redrawcmdline(); + } else { + vim_beep(BO_ERROR); + } + return; +} + +static void command_line_next_histidx(CommandLineState *s, bool next_match) +{ + s->j = (int)STRLEN(s->lookfor); + for (;; ) { + // one step backwards + if (!next_match) { + if (s->hiscnt == hislen) { + // first time + s->hiscnt = hisidx[s->histype]; + } else if (s->hiscnt == 0 && hisidx[s->histype] != hislen - 1) { + s->hiscnt = hislen - 1; + } else if (s->hiscnt != hisidx[s->histype] + 1) { + s->hiscnt--; + } else { + // at top of list + s->hiscnt = s->i; + break; + } + } else { // one step forwards + // on last entry, clear the line + if (s->hiscnt == hisidx[s->histype]) { + s->hiscnt = hislen; + break; + } + + // not on a history line, nothing to do + if (s->hiscnt == hislen) { + break; + } + + if (s->hiscnt == hislen - 1) { + // wrap around + s->hiscnt = 0; + } else { + s->hiscnt++; + } + } + + if (s->hiscnt < 0 || history[s->histype][s->hiscnt].hisstr == NULL) { + s->hiscnt = s->i; + break; + } + + if ((s->c != K_UP && s->c != K_DOWN) + || s->hiscnt == s->i + || STRNCMP(history[s->histype][s->hiscnt].hisstr, + s->lookfor, (size_t)s->j) == 0) { + break; + } + } +} + static int command_line_handle_key(CommandLineState *s) { // Big switch for a typed command line character. @@ -925,6 +1114,16 @@ static int command_line_handle_key(CommandLineState *s) // Truncate at the end, required for multi-byte chars. ccline.cmdbuff[ccline.cmdlen] = NUL; + if (ccline.cmdlen == 0) { + s->search_start = s->save_cursor; + // save view settings, so that the screen won't be restored at the + // wrong position + s->old_curswant = s->init_curswant; + s->old_leftcol = s->init_leftcol; + s->old_topline = s->init_topline; + s->old_topfill = s->init_topfill; + s->old_botline = s->init_botline; + } redrawcmd(); } else if (ccline.cmdlen == 0 && s->c != Ctrl_W && ccline.cmdprompt == NULL && s->indent == 0) { @@ -943,6 +1142,7 @@ static int command_line_handle_key(CommandLineState *s) } msg_putchar(' '); // delete ':' } + s->search_start = s->save_cursor; redraw_cmdline = true; return 0; // back to cmd mode } @@ -962,7 +1162,7 @@ static int command_line_handle_key(CommandLineState *s) return command_line_not_changed(s); case Ctrl_HAT: - if (map_to_exists_mode((char_u *)"", LANGMAP, false)) { + if (map_to_exists_mode("", LANGMAP, false)) { // ":lmap" mappings exists, toggle use of mappings. State ^= LANGMAP; if (s->b_im_ptr != NULL) { @@ -997,14 +1197,20 @@ static int command_line_handle_key(CommandLineState *s) // Truncate at the end, required for multi-byte chars. ccline.cmdbuff[ccline.cmdlen] = NUL; + if (ccline.cmdlen == 0) { + s->search_start = s->save_cursor; + } redrawcmd(); return command_line_changed(s); case ESC: // get here if p_wc != ESC or when ESC typed twice case Ctrl_C: // In exmode it doesn't make sense to return. Except when - // ":normal" runs out of characters. - if (exmode_active && (ex_normal_busy == 0 || typebuf.tb_len > 0)) { + // ":normal" runs out of characters. Also when highlight callback is active + // <C-c> should interrupt only it. + if ((exmode_active && (ex_normal_busy == 0 || typebuf.tb_len > 0)) + || (getln_interrupted_highlight && s->c == Ctrl_C)) { + getln_interrupted_highlight = false; return command_line_not_changed(s); } @@ -1067,6 +1273,7 @@ static int command_line_handle_key(CommandLineState *s) break; // Use ^D as normal char instead } + wild_menu_showing = WM_LIST; redrawcmd(); return 1; // don't do incremental search now @@ -1226,24 +1433,27 @@ static int command_line_handle_key(CommandLineState *s) case Ctrl_L: if (p_is && !cmd_silent && (s->firstc == '/' || s->firstc == '?')) { // Add a character from under the cursor for 'incsearch' - if (s->did_incsearch && !equalpos(curwin->w_cursor, s->old_cursor)) { - s->c = gchar_cursor(); - // If 'ignorecase' and 'smartcase' are set and the - // command line has no uppercase characters, convert - // the character to lowercase - if (p_ic && p_scs && !pat_has_uppercase(ccline.cmdbuff)) { - s->c = vim_tolower(s->c); - } - - if (s->c != NUL) { - if (s->c == s->firstc - || vim_strchr((char_u *)(p_magic ? "\\^$.*[" : "\\^$"), s->c) - != NULL) { - // put a backslash before special characters - stuffcharReadbuff(s->c); - s->c = '\\'; + if (s->did_incsearch) { + curwin->w_cursor = s->match_end; + if (!equalpos(curwin->w_cursor, s->search_start)) { + s->c = gchar_cursor(); + // If 'ignorecase' and 'smartcase' are set and the + // command line has no uppercase characters, convert + // the character to lowercase + if (p_ic && p_scs + && !pat_has_uppercase(ccline.cmdbuff)) { + s->c = mb_tolower(s->c); + } + if (s->c != NUL) { + if (s->c == s->firstc + || vim_strchr((char_u *)(p_magic ? "\\^$.*[" : "\\^$"), s->c) + != NULL) { + // put a backslash before special characters + stuffcharReadbuff(s->c); + s->c = '\\'; + } + break; } - break; } } return command_line_not_changed(s); @@ -1262,8 +1472,9 @@ static int command_line_handle_key(CommandLineState *s) 0, s->firstc != '@') == FAIL) { break; } - return command_line_changed(s); + return command_line_not_changed(s); } + // fallthrough case K_UP: case K_DOWN: @@ -1286,60 +1497,14 @@ static int command_line_handle_key(CommandLineState *s) s->lookfor[ccline.cmdpos] = NUL; } - s->j = (int)STRLEN(s->lookfor); - for (;; ) { - // one step backwards - if (s->c == K_UP|| s->c == K_S_UP || s->c == Ctrl_P - || s->c == K_PAGEUP || s->c == K_KPAGEUP) { - if (s->hiscnt == hislen) { - // first time - s->hiscnt = hisidx[s->histype]; - } else if (s->hiscnt == 0 && hisidx[s->histype] != hislen - 1) { - s->hiscnt = hislen - 1; - } else if (s->hiscnt != hisidx[s->histype] + 1) { - --s->hiscnt; - } else { - // at top of list - s->hiscnt = s->i; - break; - } - } else { // one step forwards - // on last entry, clear the line - if (s->hiscnt == hisidx[s->histype]) { - s->hiscnt = hislen; - break; - } - - // not on a history line, nothing to do - if (s->hiscnt == hislen) { - break; - } - - if (s->hiscnt == hislen - 1) { - // wrap around - s->hiscnt = 0; - } else { - ++s->hiscnt; - } - } - - if (s->hiscnt < 0 || history[s->histype][s->hiscnt].hisstr == NULL) { - s->hiscnt = s->i; - break; - } - - if ((s->c != K_UP && s->c != K_DOWN) - || s->hiscnt == s->i - || STRNCMP(history[s->histype][s->hiscnt].hisstr, - s->lookfor, (size_t)s->j) == 0) { - break; - } - } + bool next_match = (s->c == K_DOWN || s->c == K_S_DOWN || s->c == Ctrl_N + || s->c == K_PAGEDOWN || s->c == K_KPAGEDOWN); + command_line_next_histidx(s, next_match); if (s->hiscnt != s->i) { // jumped to other entry char_u *p; - int len; + int len = 0; int old_firstc; xfree(ccline.cmdbuff); @@ -1402,6 +1567,17 @@ static int command_line_handle_key(CommandLineState *s) beep_flush(); return command_line_not_changed(s); + case Ctrl_G: // next match + case Ctrl_T: // previous match + if (p_is && !cmd_silent && (s->firstc == '/' || s->firstc == '?')) { + if (char_avail()) { + return 1; + } + command_line_next_incsearch(s, s->c == Ctrl_G); + return command_line_not_changed(s); + } + break; + case Ctrl_V: case Ctrl_Q: s->ignore_drag_release = true; @@ -1516,7 +1692,7 @@ static int command_line_changed(CommandLineState *s) return 1; } s->incsearch_postponed = false; - curwin->w_cursor = s->old_cursor; // start at old position + curwin->w_cursor = s->search_start; // start at old position // If there is no command line, don't do anything if (ccline.cmdlen == 0) { @@ -1561,16 +1737,11 @@ static int command_line_changed(CommandLineState *s) if (s->i != 0) { pos_T save_pos = curwin->w_cursor; - // First move cursor to end of match, then to the start. This - // moves the whole match onto the screen when 'nowrap' is set. - curwin->w_cursor.lnum += search_match_lines; - curwin->w_cursor.col = search_match_endcol; - if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count) { - curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count; - coladvance((colnr_T)MAXCOL); - } + s->match_start = curwin->w_cursor; + set_search_match(&curwin->w_cursor); validate_cursor(); end_pos = curwin->w_cursor; + s->match_end = end_pos; curwin->w_cursor = save_pos; } else { end_pos = curwin->w_cursor; // shutup gcc 4 @@ -1607,10 +1778,12 @@ static int command_line_changed(CommandLineState *s) // - Update the screen while the effects are in place. // - Immediately undo the effects. State |= CMDPREVIEW; + emsg_silent++; // Block error reporting as the command may be incomplete do_cmdline(ccline.cmdbuff, NULL, NULL, DOCMD_KEEPLINE|DOCMD_NOWAIT); + emsg_silent--; // Unblock error reporting // Restore the window "view". - curwin->w_cursor = s->old_cursor; + curwin->w_cursor = s->save_cursor; curwin->w_curswant = s->old_curswant; curwin->w_leftcol = s->old_leftcol; curwin->w_topline = s->old_topline; @@ -1666,41 +1839,50 @@ getcmdline ( return command_line_enter(firstc, count, indent); } -/* - * Get a command line with a prompt. - * This is prepared to be called recursively from getcmdline() (e.g. by - * f_input() when evaluating an expression from CTRL-R =). - * Returns the command line in allocated memory, or NULL. - */ -char_u * -getcmdline_prompt ( - int firstc, - char_u *prompt, /* command line prompt */ - int attr, /* attributes for prompt */ - int xp_context, /* type of expansion */ - char_u *xp_arg /* user-defined expansion argument */ -) +/// Get a command line with a prompt +/// +/// This is prepared to be called recursively from getcmdline() (e.g. by +/// f_input() when evaluating an expression from `<C-r>=`). +/// +/// @param[in] firstc Prompt type: e.g. '@' for input(), '>' for debug. +/// @param[in] prompt Prompt string: what is displayed before the user text. +/// @param[in] attr Prompt highlighting. +/// @param[in] xp_context Type of expansion. +/// @param[in] xp_arg User-defined expansion argument. +/// @param[in] highlight_callback Callback used for highlighting user input. +/// +/// @return [allocated] Command line or NULL. +char *getcmdline_prompt(const char firstc, const char *const prompt, + const int attr, const int xp_context, + const char *const xp_arg, + const Callback highlight_callback) + FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_MALLOC { - char_u *s; - struct cmdline_info save_ccline; - int msg_col_save = msg_col; + const int msg_col_save = msg_col; + struct cmdline_info save_ccline; save_cmdline(&save_ccline); - ccline.cmdprompt = prompt; + + ccline.prompt_id = last_prompt_id++; + ccline.cmdprompt = (char_u *)prompt; ccline.cmdattr = attr; ccline.xp_context = xp_context; - ccline.xp_arg = xp_arg; + ccline.xp_arg = (char_u *)xp_arg; ccline.input_fn = (firstc == '@'); - s = getcmdline(firstc, 1L, 0); + ccline.highlight_callback = highlight_callback; + + char *const ret = (char *)getcmdline(firstc, 1L, 0); + restore_cmdline(&save_ccline); - /* Restore msg_col, the prompt from input() may have changed it. - * But only if called recursively and the commandline is therefore being - * restored to an old one; if not, the input() prompt stays on the screen, - * so we need its modified msg_col left intact. */ - if (ccline.cmdbuff != NULL) + // Restore msg_col, the prompt from input() may have changed it. + // But only if called recursively and the commandline is therefore being + // restored to an old one; if not, the input() prompt stays on the screen, + // so we need its modified msg_col left intact. + if (ccline.cmdbuff != NULL) { msg_col = msg_col_save; + } - return s; + return ret; } /* @@ -1877,7 +2059,7 @@ getexmodeline ( vcol = indent; while (indent >= 8) { ga_append(&line_ga, TAB); - msg_puts((char_u *)" "); + msg_puts(" "); indent -= 8; } while (indent-- > 0) { @@ -1885,8 +2067,7 @@ getexmodeline ( msg_putchar(' '); } } - ++no_mapping; - ++allow_keys; + no_mapping++; /* * Get the line, one character at a time. @@ -2076,8 +2257,7 @@ redraw: } } - --no_mapping; - --allow_keys; + no_mapping--; /* make following messages go to the next line */ msg_didout = FALSE; @@ -2092,6 +2272,18 @@ redraw: return (char_u *)line_ga.ga_data; } +bool cmdline_overstrike(void) +{ + return ccline.overstrike; +} + + +/// Return true if the cursor is at the end of the cmdline. +bool cmdline_at_end(void) +{ + return (ccline.cmdpos >= ccline.cmdlen); +} + /* * Allocate a new command line buffer. * Assigns the new buffer to ccline.cmdbuff and ccline.cmdbufflen. @@ -2151,75 +2343,329 @@ void free_cmdline_buf(void) # endif +enum { MAX_CB_ERRORS = 1 }; + +/// Color command-line +/// +/// Should use built-in command parser or user-specified one. Currently only the +/// latter is supported. +/// +/// @param[in] colored_ccline Command-line to color. +/// @param[out] ret_ccline_colors What should be colored. Also holds a cache: +/// if ->prompt_id and ->cmdbuff values happen +/// to be equal to those from colored_cmdline it +/// will just do nothing, assuming that ->colors +/// already contains needed data. +/// +/// Always colors the whole cmdline. +/// +/// @return true if draw_cmdline may proceed, false if it does not need anything +/// to do. +static bool color_cmdline(const CmdlineInfo *const colored_ccline, + ColoredCmdline *const ret_ccline_colors) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ + bool printed_errmsg = false; +#define PRINT_ERRMSG(...) \ + do { \ + msg_putchar('\n'); \ + msg_printf_attr(hl_attr(HLF_E)|MSG_HIST, __VA_ARGS__); \ + printed_errmsg = true; \ + } while (0) + bool ret = true; + + // Check whether result of the previous call is still valid. + if (ret_ccline_colors->prompt_id == colored_ccline->prompt_id + && ret_ccline_colors->cmdbuff != NULL + && STRCMP(ret_ccline_colors->cmdbuff, colored_ccline->cmdbuff) == 0) { + return ret; + } + + kv_size(ret_ccline_colors->colors) = 0; + + if (colored_ccline->cmdbuff == NULL || *colored_ccline->cmdbuff == NUL) { + // Nothing to do, exiting. + xfree(ret_ccline_colors->cmdbuff); + ret_ccline_colors->cmdbuff = NULL; + return ret; + } + + bool arg_allocated = false; + typval_T arg = { + .v_type = VAR_STRING, + .vval.v_string = colored_ccline->cmdbuff, + }; + typval_T tv = { .v_type = VAR_UNKNOWN }; + + static unsigned prev_prompt_id = UINT_MAX; + static int prev_prompt_errors = 0; + Callback color_cb = { .type = kCallbackNone }; + bool can_free_cb = false; + TryState tstate; + Error err = ERROR_INIT; + const char *err_errmsg = (const char *)e_intern2; + bool dgc_ret = true; + bool tl_ret = true; + + if (colored_ccline->prompt_id != prev_prompt_id) { + prev_prompt_errors = 0; + prev_prompt_id = colored_ccline->prompt_id; + } else if (prev_prompt_errors >= MAX_CB_ERRORS) { + goto color_cmdline_end; + } + if (colored_ccline->highlight_callback.type != kCallbackNone) { + // Currently this should only happen while processing input() prompts. + assert(colored_ccline->input_fn); + color_cb = colored_ccline->highlight_callback; + } else if (colored_ccline->cmdfirstc == ':') { + try_enter(&tstate); + err_errmsg = N_( + "E5408: Unable to get g:Nvim_color_cmdline callback: %s"); + dgc_ret = tv_dict_get_callback(&globvardict, S_LEN("Nvim_color_cmdline"), + &color_cb); + tl_ret = try_leave(&tstate, &err); + can_free_cb = true; + } else if (colored_ccline->cmdfirstc == '=') { + try_enter(&tstate); + err_errmsg = N_( + "E5409: Unable to get g:Nvim_color_expr callback: %s"); + dgc_ret = tv_dict_get_callback(&globvardict, S_LEN("Nvim_color_expr"), + &color_cb); + tl_ret = try_leave(&tstate, &err); + can_free_cb = true; + } + if (!tl_ret || !dgc_ret) { + goto color_cmdline_error; + } + + if (color_cb.type == kCallbackNone) { + goto color_cmdline_end; + } + if (colored_ccline->cmdbuff[colored_ccline->cmdlen] != NUL) { + arg_allocated = true; + arg.vval.v_string = xmemdupz((const char *)colored_ccline->cmdbuff, + (size_t)colored_ccline->cmdlen); + } + // msg_start() called by e.g. :echo may shift command-line to the first column + // even though msg_silent is here. Two ways to workaround this problem without + // altering message.c: use full_screen or save and restore msg_col. + // + // Saving and restoring full_screen does not work well with :redraw!. Saving + // and restoring msg_col is neither ideal, but while with full_screen it + // appears shifted one character to the right and cursor position is no longer + // correct, with msg_col it just misses leading `:`. Since `redraw!` in + // callback lags this is least of the user problems. + // + // Also using try_enter() because error messages may overwrite typed + // command-line which is not expected. + getln_interrupted_highlight = false; + try_enter(&tstate); + err_errmsg = N_("E5407: Callback has thrown an exception: %s"); + const int saved_msg_col = msg_col; + msg_silent++; + const bool cbcall_ret = callback_call(&color_cb, 1, &arg, &tv); + msg_silent--; + msg_col = saved_msg_col; + if (got_int) { + getln_interrupted_highlight = true; + } + if (!try_leave(&tstate, &err) || !cbcall_ret) { + goto color_cmdline_error; + } + if (tv.v_type != VAR_LIST) { + PRINT_ERRMSG(_("E5400: Callback should return list")); + goto color_cmdline_error; + } + if (tv.vval.v_list == NULL) { + goto color_cmdline_end; + } + varnumber_T prev_end = 0; + int i = 0; + for (const listitem_T *li = tv.vval.v_list->lv_first; + li != NULL; li = li->li_next, i++) { + if (li->li_tv.v_type != VAR_LIST) { + PRINT_ERRMSG(_("E5401: List item %i is not a List"), i); + goto color_cmdline_error; + } + const list_T *const l = li->li_tv.vval.v_list; + if (tv_list_len(l) != 3) { + PRINT_ERRMSG(_("E5402: List item %i has incorrect length: %li /= 3"), + i, tv_list_len(l)); + goto color_cmdline_error; + } + bool error = false; + const varnumber_T start = tv_get_number_chk(&l->lv_first->li_tv, &error); + if (error) { + goto color_cmdline_error; + } else if (!(prev_end <= start && start < colored_ccline->cmdlen)) { + PRINT_ERRMSG(_("E5403: Chunk %i start %" PRIdVARNUMBER " not in range " + "[%" PRIdVARNUMBER ", %i)"), + i, start, prev_end, colored_ccline->cmdlen); + goto color_cmdline_error; + } else if (utf8len_tab_zero[(uint8_t)colored_ccline->cmdbuff[start]] == 0) { + PRINT_ERRMSG(_("E5405: Chunk %i start %" PRIdVARNUMBER " splits " + "multibyte character"), i, start); + goto color_cmdline_error; + } + if (start != prev_end) { + kv_push(ret_ccline_colors->colors, ((CmdlineColorChunk) { + .start = prev_end, + .end = start, + .attr = 0, + })); + } + const varnumber_T end = tv_get_number_chk(&l->lv_first->li_next->li_tv, + &error); + if (error) { + goto color_cmdline_error; + } else if (!(start < end && end <= colored_ccline->cmdlen)) { + PRINT_ERRMSG(_("E5404: Chunk %i end %" PRIdVARNUMBER " not in range " + "(%" PRIdVARNUMBER ", %i]"), + i, end, start, colored_ccline->cmdlen); + goto color_cmdline_error; + } else if (end < colored_ccline->cmdlen + && (utf8len_tab_zero[(uint8_t)colored_ccline->cmdbuff[end]] + == 0)) { + PRINT_ERRMSG(_("E5406: Chunk %i end %" PRIdVARNUMBER " splits multibyte " + "character"), i, end); + goto color_cmdline_error; + } + prev_end = end; + const char *const group = tv_get_string_chk(&l->lv_last->li_tv); + if (group == NULL) { + goto color_cmdline_error; + } + const int id = syn_name2id((char_u *)group); + const int attr = (id == 0 ? 0 : syn_id2attr(id)); + kv_push(ret_ccline_colors->colors, ((CmdlineColorChunk) { + .start = start, + .end = end, + .attr = attr, + })); + } + if (prev_end < colored_ccline->cmdlen) { + kv_push(ret_ccline_colors->colors, ((CmdlineColorChunk) { + .start = prev_end, + .end = colored_ccline->cmdlen, + .attr = 0, + })); + } + prev_prompt_errors = 0; +color_cmdline_end: + assert(!ERROR_SET(&err)); + if (can_free_cb) { + callback_free(&color_cb); + } + xfree(ret_ccline_colors->cmdbuff); + // Note: errors โoutputโ is cached just as well as regular results. + ret_ccline_colors->prompt_id = colored_ccline->prompt_id; + if (arg_allocated) { + ret_ccline_colors->cmdbuff = (char *)arg.vval.v_string; + } else { + ret_ccline_colors->cmdbuff = xmemdupz((const char *)colored_ccline->cmdbuff, + (size_t)colored_ccline->cmdlen); + } + tv_clear(&tv); + return ret; +color_cmdline_error: + if (ERROR_SET(&err)) { + PRINT_ERRMSG(_(err_errmsg), err.msg); + api_clear_error(&err); + } + assert(printed_errmsg); + (void)printed_errmsg; + + prev_prompt_errors++; + kv_size(ret_ccline_colors->colors) = 0; + redrawcmdline(); + ret = false; + goto color_cmdline_end; +#undef PRINT_ERRMSG +} + /* * Draw part of the cmdline at the current cursor position. But draw stars * when cmdline_star is TRUE. */ static void draw_cmdline(int start, int len) { - int i; + if (!color_cmdline(&ccline, &last_ccline_colors)) { + return; + } - if (cmdline_star > 0) - for (i = 0; i < len; ++i) { + if (cmdline_star > 0) { + for (int i = 0; i < len; i++) { msg_putchar('*'); - if (has_mbyte) + if (has_mbyte) { i += (*mb_ptr2len)(ccline.cmdbuff + start + i) - 1; + } } - else if (p_arshape && !p_tbidi && enc_utf8 && len > 0) { - static int buflen = 0; - char_u *p; - int j; - int newlen = 0; + } else if (p_arshape && !p_tbidi && enc_utf8 && len > 0) { + bool do_arabicshape = false; int mb_l; - int pc, pc1 = 0; - int prev_c = 0; - int prev_c1 = 0; - int u8c; - int u8cc[MAX_MCO]; - int nc = 0; + for (int i = start; i < start + len; i += mb_l) { + char_u *p = ccline.cmdbuff + i; + int u8cc[MAX_MCO]; + int u8c = utfc_ptr2char_len(p, u8cc, start + len - i); + mb_l = utfc_ptr2len_len(p, start + len - i); + if (arabic_char(u8c)) { + do_arabicshape = true; + break; + } + } + if (!do_arabicshape) { + goto draw_cmdline_no_arabicshape; + } - /* - * Do arabic shaping into a temporary buffer. This is very - * inefficient! - */ + static int buflen = 0; + + // Do arabic shaping into a temporary buffer. This is very + // inefficient! if (len * 2 + 2 > buflen) { - /* Re-allocate the buffer. We keep it around to avoid a lot of - * alloc()/free() calls. */ + // Re-allocate the buffer. We keep it around to avoid a lot of + // alloc()/free() calls. xfree(arshape_buf); buflen = len * 2 + 2; arshape_buf = xmalloc(buflen); } + int newlen = 0; if (utf_iscomposing(utf_ptr2char(ccline.cmdbuff + start))) { - /* Prepend a space to draw the leading composing char on. */ + // Prepend a space to draw the leading composing char on. arshape_buf[0] = ' '; newlen = 1; } - for (j = start; j < start + len; j += mb_l) { - p = ccline.cmdbuff + j; - u8c = utfc_ptr2char_len(p, u8cc, start + len - j); - mb_l = utfc_ptr2len_len(p, start + len - j); + int prev_c = 0; + int prev_c1 = 0; + for (int i = start; i < start + len; i += mb_l) { + char_u *p = ccline.cmdbuff + i; + int u8cc[MAX_MCO]; + int u8c = utfc_ptr2char_len(p, u8cc, start + len - i); + mb_l = utfc_ptr2len_len(p, start + len - i); if (arabic_char(u8c)) { - /* Do Arabic shaping. */ + int pc; + int pc1 = 0; + int nc = 0; + // Do Arabic shaping. if (cmdmsg_rl) { - /* displaying from right to left */ + // Displaying from right to left. pc = prev_c; pc1 = prev_c1; prev_c1 = u8cc[0]; - if (j + mb_l >= start + len) + if (i + mb_l >= start + len) { nc = NUL; - else + } else { nc = utf_ptr2char(p + mb_l); + } } else { - /* displaying from left to right */ - if (j + mb_l >= start + len) + // Displaying from left to right. + if (i + mb_l >= start + len) { pc = NUL; - else { + } else { int pcc[MAX_MCO]; - pc = utfc_ptr2char_len(p + mb_l, pcc, - start + len - j - mb_l); + pc = utfc_ptr2char_len(p + mb_l, pcc, start + len - i - mb_l); pc1 = pcc[0]; } nc = prev_c; @@ -2243,8 +2689,23 @@ static void draw_cmdline(int start, int len) } msg_outtrans_len(arshape_buf, newlen); - } else - msg_outtrans_len(ccline.cmdbuff + start, len); + } else { +draw_cmdline_no_arabicshape: + if (kv_size(last_ccline_colors.colors)) { + for (size_t i = 0; i < kv_size(last_ccline_colors.colors); i++) { + CmdlineColorChunk chunk = kv_A(last_ccline_colors.colors, i); + if (chunk.end <= start) { + continue; + } + const int chunk_start = MAX(chunk.start, start); + msg_outtrans_len_attr(ccline.cmdbuff + chunk_start, + chunk.end - chunk_start, + chunk.attr); + } + } else { + msg_outtrans_len(ccline.cmdbuff + start, len); + } + } } /* @@ -2262,6 +2723,7 @@ void putcmdline(int c, int shift) draw_cmdline(ccline.cmdpos, ccline.cmdlen - ccline.cmdpos); msg_no_more = FALSE; cursorcmd(); + ui_cursor_shape(); } /* @@ -2281,6 +2743,7 @@ void unputcmdline(void) draw_cmdline(ccline.cmdpos, 1); msg_no_more = FALSE; cursorcmd(); + ui_cursor_shape(); } /* @@ -2555,19 +3018,22 @@ void cmdline_paste_str(char_u *s, int literally) else while (*s != NUL) { cv = *s; - if (cv == Ctrl_V && s[1]) - ++s; - if (has_mbyte) - c = mb_cptr2char_adv(&s); - else + if (cv == Ctrl_V && s[1]) { + s++; + } + if (has_mbyte) { + c = mb_cptr2char_adv((const char_u **)&s); + } else { c = *s++; + } if (cv == Ctrl_V || c == ESC || c == Ctrl_C || c == CAR || c == NL || c == Ctrl_L #ifdef UNIX || c == intr_char #endif - || (c == Ctrl_BSL && *s == Ctrl_N)) + || (c == Ctrl_BSL && *s == Ctrl_N)) { stuffcharReadbuff(Ctrl_V); + } stuffcharReadbuff(c); } } @@ -2595,6 +3061,7 @@ void redrawcmdline(void) compute_cmdrow(); redrawcmd(); cursorcmd(); + ui_cursor_shape(); } static void redrawcmdprompt(void) @@ -2606,7 +3073,7 @@ static void redrawcmdprompt(void) if (ccline.cmdfirstc != NUL) msg_putchar(ccline.cmdfirstc); if (ccline.cmdprompt != NULL) { - msg_puts_attr(ccline.cmdprompt, ccline.cmdattr); + msg_puts_attr((const char *)ccline.cmdprompt, ccline.cmdattr); ccline.cmdindent = msg_col + (msg_row - cmdline_row) * Columns; /* do the reverse of set_cmdspos() */ if (ccline.cmdfirstc != NUL) @@ -3016,7 +3483,7 @@ ExpandOne ( || xp->xp_context == EXPAND_FILES || xp->xp_context == EXPAND_SHELLCMD || xp->xp_context == EXPAND_BUFFERS)) { - if (vim_tolower(c0) != vim_tolower(ci)) { + if (mb_tolower(c0) != mb_tolower(ci)) { break; } } else if (c0 != ci) { @@ -3122,9 +3589,10 @@ void ExpandEscape(expand_T *xp, char_u *str, int numfiles, char_u **files, int o #endif } #ifdef BACKSLASH_IN_FILENAME - p = vim_strsave_fnameescape(files[i], FALSE); + p = (char_u *)vim_strsave_fnameescape((const char *)files[i], false); #else - p = vim_strsave_fnameescape(files[i], xp->xp_shell); + p = (char_u *)vim_strsave_fnameescape((const char *)files[i], + xp->xp_shell); #endif xfree(files[i]); files[i] = p; @@ -3154,42 +3622,49 @@ void ExpandEscape(expand_T *xp, char_u *str, int numfiles, char_u **files, int o } } -/* - * Escape special characters in "fname" for when used as a file name argument - * after a Vim command, or, when "shell" is non-zero, a shell command. - * Returns the result in allocated memory. - */ -char_u *vim_strsave_fnameescape(char_u *fname, int shell) FUNC_ATTR_NONNULL_RET +/// Escape special characters in a file name for use as a command argument +/// +/// @param[in] fname File name to escape. +/// @param[in] shell What to escape for: if false, escapes for VimL command, +/// if true then it escapes for a shell command. +/// +/// @return [allocated] escaped file name. +char *vim_strsave_fnameescape(const char *const fname, const bool shell) + FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL { - char_u *p; #ifdef BACKSLASH_IN_FILENAME -#define PATH_ESC_CHARS ((char_u *)" \t\n*?[{`%#'\"|!<") - char_u buf[20]; +#define PATH_ESC_CHARS " \t\n*?[{`%#'\"|!<" + char_u buf[sizeof(PATH_ESC_CHARS)]; int j = 0; - /* Don't escape '[', '{' and '!' if they are in 'isfname'. */ - for (p = PATH_ESC_CHARS; *p != NUL; ++p) - if ((*p != '[' && *p != '{' && *p != '!') || !vim_isfilec(*p)) - buf[j++] = *p; + // Don't escape '[', '{' and '!' if they are in 'isfname'. + for (const char *s = PATH_ESC_CHARS; *s != NUL; s++) { + if ((*s != '[' && *s != '{' && *s != '!') || !vim_isfilec(*s)) { + buf[j++] = *s; + } + } buf[j] = NUL; - p = vim_strsave_escaped(fname, buf); + char *p = (char *)vim_strsave_escaped((const char_u *)fname, + (const char_u *)buf); #else #define PATH_ESC_CHARS ((char_u *)" \t\n*?[{`$\\%#'\"|!<") #define SHELL_ESC_CHARS ((char_u *)" \t\n*?[{`$\\%#'\"|!<>();&") - p = vim_strsave_escaped(fname, shell ? SHELL_ESC_CHARS : PATH_ESC_CHARS); + char *p = (char *)vim_strsave_escaped( + (const char_u *)fname, (shell ? SHELL_ESC_CHARS : PATH_ESC_CHARS)); if (shell && csh_like_shell()) { - /* For csh and similar shells need to put two backslashes before '!'. - * One is taken by Vim, one by the shell. */ - char_u *s = vim_strsave_escaped(p, (char_u *)"!"); + // For csh and similar shells need to put two backslashes before '!'. + // One is taken by Vim, one by the shell. + char *s = (char *)vim_strsave_escaped((const char_u *)p, + (const char_u *)"!"); xfree(p); p = s; } #endif - /* '>' and '+' are special at the start of some commands, e.g. ":edit" and - * ":write". "cd -" has a special meaning. */ + // '>' and '+' are special at the start of some commands, e.g. ":edit" and + // ":write". "cd -" has a special meaning. if (*p == '>' || *p == '+' || (*p == '-' && p[1] == NUL)) { - escape_fname(&p); + escape_fname((char_u **)&p); } return p; @@ -3315,7 +3790,7 @@ static int showmatches(expand_T *xp, int wildmenu) msg_outtrans_attr(files_found[k], hl_attr(HLF_D)); p = files_found[k] + STRLEN(files_found[k]) + 1; msg_advance(maxlen + 1); - msg_puts(p); + msg_puts((const char *)p); msg_advance(maxlen + 3); msg_puts_long_attr(p + 2, hl_attr(HLF_D)); break; @@ -3626,7 +4101,6 @@ set_cmd_context ( ) { int old_char = NUL; - char_u *nextcomm; /* * Avoid a UMR warning from Purify, only save the character if it has been @@ -3635,7 +4109,7 @@ set_cmd_context ( if (col < len) old_char = str[col]; str[col] = NUL; - nextcomm = str; + const char *nextcomm = (const char *)str; if (use_ccline && ccline.cmdfirstc == '=') { // pass CMD_SIZE because there is no real command @@ -3644,9 +4118,11 @@ set_cmd_context ( xp->xp_context = ccline.xp_context; xp->xp_pattern = ccline.cmdbuff; xp->xp_arg = ccline.xp_arg; - } else - while (nextcomm != NULL) + } else { + while (nextcomm != NULL) { nextcomm = set_one_cmd_context(xp, nextcomm); + } + } /* Store the string here so that call_user_expand_func() can get to them * easily. */ @@ -3757,6 +4233,8 @@ static void cleanup_help_tags(int num_file, char_u **file) } } +typedef char_u *(*ExpandFunc)(expand_T *, int); + /* * Do the expansion based on xp->xp_context and "pat". */ @@ -3896,39 +4374,39 @@ ExpandFromContext ( else { static struct expgen { int context; - char_u *((*func)(expand_T *, int)); + ExpandFunc func; int ic; int escaped; - } tab[] = - { - {EXPAND_COMMANDS, get_command_name, FALSE, TRUE}, - {EXPAND_BEHAVE, get_behave_arg, TRUE, TRUE}, - {EXPAND_HISTORY, get_history_arg, TRUE, TRUE}, - {EXPAND_USER_COMMANDS, get_user_commands, FALSE, TRUE}, - {EXPAND_USER_ADDR_TYPE, get_user_cmd_addr_type, FALSE, TRUE}, - {EXPAND_USER_CMD_FLAGS, get_user_cmd_flags, FALSE, TRUE}, - {EXPAND_USER_NARGS, get_user_cmd_nargs, FALSE, TRUE}, - {EXPAND_USER_COMPLETE, get_user_cmd_complete, FALSE, TRUE}, - {EXPAND_USER_VARS, get_user_var_name, FALSE, TRUE}, - {EXPAND_FUNCTIONS, get_function_name, FALSE, TRUE}, - {EXPAND_USER_FUNC, get_user_func_name, FALSE, TRUE}, - {EXPAND_EXPRESSION, get_expr_name, FALSE, TRUE}, - {EXPAND_MENUS, get_menu_name, FALSE, TRUE}, - {EXPAND_MENUNAMES, get_menu_names, FALSE, TRUE}, - {EXPAND_SYNTAX, get_syntax_name, TRUE, TRUE}, - {EXPAND_SYNTIME, get_syntime_arg, TRUE, TRUE}, - {EXPAND_HIGHLIGHT, get_highlight_name, TRUE, TRUE}, - {EXPAND_EVENTS, get_event_name, TRUE, TRUE}, - {EXPAND_AUGROUP, get_augroup_name, TRUE, TRUE}, - {EXPAND_CSCOPE, get_cscope_name, TRUE, TRUE}, - {EXPAND_SIGN, get_sign_name, TRUE, TRUE}, - {EXPAND_PROFILE, get_profile_name, TRUE, TRUE}, + } tab[] = { + { EXPAND_COMMANDS, get_command_name, false, true }, + { EXPAND_BEHAVE, get_behave_arg, true, true }, + { EXPAND_MESSAGES, get_messages_arg, true, true }, + { EXPAND_HISTORY, get_history_arg, true, true }, + { EXPAND_USER_COMMANDS, get_user_commands, false, true }, + { EXPAND_USER_ADDR_TYPE, get_user_cmd_addr_type, false, true }, + { EXPAND_USER_CMD_FLAGS, get_user_cmd_flags, false, true }, + { EXPAND_USER_NARGS, get_user_cmd_nargs, false, true }, + { EXPAND_USER_COMPLETE, get_user_cmd_complete, false, true }, + { EXPAND_USER_VARS, get_user_var_name, false, true }, + { EXPAND_FUNCTIONS, get_function_name, false, true }, + { EXPAND_USER_FUNC, get_user_func_name, false, true }, + { EXPAND_EXPRESSION, get_expr_name, false, true }, + { EXPAND_MENUS, get_menu_name, false, true }, + { EXPAND_MENUNAMES, get_menu_names, false, true }, + { EXPAND_SYNTAX, get_syntax_name, true, true }, + { EXPAND_SYNTIME, get_syntime_arg, true, true }, + { EXPAND_HIGHLIGHT, (ExpandFunc)get_highlight_name, true, true }, + { EXPAND_EVENTS, get_event_name, true, true }, + { EXPAND_AUGROUP, get_augroup_name, true, true }, + { EXPAND_CSCOPE, get_cscope_name, true, true }, + { EXPAND_SIGN, get_sign_name, true, true }, + { EXPAND_PROFILE, get_profile_name, true, true }, #ifdef HAVE_WORKING_LIBINTL - {EXPAND_LANGUAGE, get_lang_arg, TRUE, FALSE}, - {EXPAND_LOCALES, get_locales, TRUE, FALSE}, + { EXPAND_LANGUAGE, get_lang_arg, true, false }, + { EXPAND_LOCALES, get_locales, true, false }, #endif - {EXPAND_ENV_VARS, get_env_name, TRUE, TRUE}, - {EXPAND_USER, get_users, TRUE, FALSE}, + { EXPAND_ENV_VARS, get_env_name, true, true }, + { EXPAND_USER, get_users, true, false }, }; int i; @@ -4040,7 +4518,7 @@ void ExpandGeneric( /// @param flagsarg is a combination of EW_* flags. static void expand_shellcmd(char_u *filepat, int *num_file, char_u ***file, int flagsarg) - FUNC_ATTR_NONNULL_ALL + FUNC_ATTR_NONNULL_ALL { char_u *pat; int i; @@ -4141,10 +4619,8 @@ static void expand_shellcmd(char_u *filepat, int *num_file, char_u ***file, } } -/* - * Call "user_expand_func()" to invoke a user defined VimL function and return - * the result (either a string or a List). - */ +/// Call "user_expand_func()" to invoke a user defined Vim script function and +/// return the result (either a string or a List). static void * call_user_expand_func(user_expand_func_T user_expand_func, expand_T *xp, int *num_file, char_u ***file) { @@ -4198,9 +4674,11 @@ static int ExpandUserDefined(expand_T *xp, regmatch_T *regmatch, int *num_file, char_u keep; garray_T ga; - retstr = call_user_expand_func(call_func_retstr, xp, num_file, file); - if (retstr == NULL) + retstr = call_user_expand_func((user_expand_func_T)call_func_retstr, xp, + num_file, file); + if (retstr == NULL) { return FAIL; + } ga_init(&ga, (int)sizeof(char *), 3); for (s = retstr; *s != NUL; s = e) { @@ -4238,9 +4716,11 @@ static int ExpandUserList(expand_T *xp, int *num_file, char_u ***file) listitem_T *li; garray_T ga; - retlist = call_user_expand_func(call_func_retlist, xp, num_file, file); - if (retlist == NULL) + retlist = call_user_expand_func((user_expand_func_T)call_func_retlist, xp, + num_file, file); + if (retlist == NULL) { return FAIL; + } ga_init(&ga, (int)sizeof(char *), 3); /* Loop over the items in the list. */ @@ -4250,7 +4730,7 @@ static int ExpandUserList(expand_T *xp, int *num_file, char_u ***file) GA_APPEND(char_u *, &ga, vim_strsave(li->li_tv.vval.v_string)); } - list_unref(retlist); + tv_list_unref(retlist); *file = ga.ga_data; *num_file = ga.ga_len; @@ -4546,7 +5026,7 @@ static inline void hist_free_entry(histentry_T *hisptr) FUNC_ATTR_NONNULL_ALL { xfree(hisptr->hisstr); - list_unref(hisptr->additional_elements); + tv_list_unref(hisptr->additional_elements); clear_hist_entry(hisptr); } @@ -4602,7 +5082,7 @@ in_history ( history[type][last_i] = history[type][i]; last_i = i; } - list_unref(list); + tv_list_unref(list); history[type][i].hisnum = ++hisnum[type]; history[type][i].hisstr = str; history[type][i].timestamp = os_time(); @@ -4624,7 +5104,7 @@ in_history ( /// /// @return Any value from HistoryType enum, including HIST_INVALID. May not /// return HIST_DEFAULT unless return_default is true. -HistoryType get_histtype(const char_u *const name, const size_t len, +HistoryType get_histtype(const char *const name, const size_t len, const bool return_default) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT { @@ -4678,8 +5158,8 @@ add_to_history ( * down, only lines that were added. */ if (histype == HIST_SEARCH && in_map) { - if (maptick == last_maptick) { - /* Current line is from the same mapping, remove it */ + if (maptick == last_maptick && hisidx[HIST_SEARCH] >= 0) { + // Current line is from the same mapping, remove it hisptr = &history[HIST_SEARCH][hisidx[HIST_SEARCH]]; hist_free_entry(hisptr); --hisnum[histype]; @@ -4967,7 +5447,7 @@ int get_list_range(char_u **str, int *num1, int *num2) { int len; int first = false; - long num; + varnumber_T num; *str = skipwhite(*str); if (**str == '-' || ascii_isdigit(**str)) { // parse "from" part of range @@ -5017,7 +5497,7 @@ void ex_history(exarg_T *eap) while (ASCII_ISALPHA(*end) || vim_strchr((char_u *)":=@>/?", *end) != NULL) end++; - histype1 = get_histtype(arg, end - arg, false); + histype1 = get_histtype((const char *)arg, end - arg, false); if (histype1 == HIST_INVALID) { if (STRNICMP(arg, "all", end - arg) == 0) { histype1 = 0; @@ -5132,9 +5612,9 @@ int cmd_gchar(int offset) static int ex_window(void) { struct cmdline_info save_ccline; - buf_T *old_curbuf = curbuf; + bufref_T old_curbuf; + bufref_T bufref; win_T *old_curwin = curwin; - buf_T *bp; win_T *wp; int i; linenr_T lnum; @@ -5153,6 +5633,8 @@ static int ex_window(void) return K_IGNORE; } + set_bufref(&old_curbuf, curbuf); + /* Save current window sizes. */ win_size_save(&winsizes); @@ -5172,7 +5654,7 @@ static int ex_window(void) // Create empty command-line buffer. buf_open_scratch(0, "[Command Line]"); // Command-line buffer has bufhidden=wipe, unlike a true "scratch" buffer. - set_option_value((char_u *)"bh", 0L, (char_u *)"wipe", OPT_LOCAL); + set_option_value("bh", 0L, "wipe", OPT_LOCAL); curwin->w_p_rl = cmdmsg_rl; cmdmsg_rl = false; curbuf->b_p_ma = true; @@ -5190,7 +5672,7 @@ static int ex_window(void) add_map((char_u *)"<buffer> <Tab> <C-X><C-V>", INSERT); add_map((char_u *)"<buffer> <Tab> a<C-X><C-V>", NORMAL); } - set_option_value((char_u *)"ft", 0L, (char_u *)"vim", OPT_LOCAL); + set_option_value("ft", 0L, "vim", OPT_LOCAL); } /* Reset 'textwidth' after setting 'filetype' (the Vim filetype plugin @@ -5222,10 +5704,8 @@ static int ex_window(void) invalidate_botline(); redraw_later(SOME_VALID); - /* Save the command line info, can be used recursively. */ - save_ccline = ccline; - ccline.cmdbuff = NULL; - ccline.cmdprompt = NULL; + // Save the command line info, can be used recursively. + save_cmdline(&save_ccline); /* No Ex mode here! */ exmode_active = 0; @@ -5259,15 +5739,15 @@ static int ex_window(void) /* Restore KeyTyped in case it is modified by autocommands */ KeyTyped = save_KeyTyped; - /* Restore the command line info. */ - ccline = save_ccline; + // Restore the command line info. + restore_cmdline(&save_ccline); cmdwin_type = 0; exmode_active = save_exmode; /* Safety check: The old window or buffer was deleted: It's a bug when * this happens! */ - if (!win_valid(old_curwin) || !buf_valid(old_curbuf)) { + if (!win_valid(old_curwin) || !bufref_valid(&old_curbuf)) { cmdwin_result = Ctrl_C; EMSG(_("E199: Active window or buffer deleted")); } else { @@ -5276,18 +5756,18 @@ static int ex_window(void) cmdwin_result = Ctrl_C; /* Set the new command line from the cmdline buffer. */ xfree(ccline.cmdbuff); - if (cmdwin_result == K_XF1 || cmdwin_result == K_XF2) { /* :qa[!] typed */ - char *p = (cmdwin_result == K_XF2) ? "qa" : "qa!"; + if (cmdwin_result == K_XF1 || cmdwin_result == K_XF2) { // :qa[!] typed + const char *p = (cmdwin_result == K_XF2) ? "qa" : "qa!"; if (histtype == HIST_CMD) { - /* Execute the command directly. */ - ccline.cmdbuff = vim_strsave((char_u *)p); + // Execute the command directly. + ccline.cmdbuff = (char_u *)xstrdup(p); cmdwin_result = CAR; } else { - /* First need to cancel what we were doing. */ + // First need to cancel what we were doing. ccline.cmdbuff = NULL; stuffcharReadbuff(':'); - stuffReadbuff((char_u *)p); + stuffReadbuff(p); stuffcharReadbuff(CAR); } } else if (cmdwin_result == K_XF2) { /* :qa typed */ @@ -5318,14 +5798,15 @@ static int ex_window(void) // Avoid command-line window first character being concealed curwin->w_p_cole = 0; wp = curwin; - bp = curbuf; + set_bufref(&bufref, curbuf); win_goto(old_curwin); win_close(wp, TRUE); - /* win_close() may have already wiped the buffer when 'bh' is - * set to 'wipe' */ - if (buf_valid(bp)) - close_buffer(NULL, bp, DOBUF_WIPE, FALSE); + // win_close() may have already wiped the buffer when 'bh' is + // set to 'wipe'. + if (bufref_valid(&bufref)) { + close_buffer(NULL, bufref.br_buf, DOBUF_WIPE, false); + } /* Restore window sizes. */ win_size_restore(&winsizes); @@ -5343,47 +5824,61 @@ static int ex_window(void) return cmdwin_result; } -/* - * Used for commands that either take a simple command string argument, or: - * cmd << endmarker - * {script} - * endmarker - * Returns a pointer to allocated memory with {script} or NULL. - */ -char_u *script_get(exarg_T *eap, char_u *cmd) +/// Get script string +/// +/// Used for commands which accept either `:command script` or +/// +/// :command << endmarker +/// script +/// endmarker +/// +/// @param eap Command being run. +/// @param[out] lenp Location where length of resulting string is saved. Will +/// be set to zero when skipping. +/// +/// @return [allocated] NULL or script. Does not show any error messages. +/// NULL is returned when skipping and on error. +char *script_get(exarg_T *const eap, size_t *const lenp) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_MALLOC { - char_u *theline; - char *end_pattern = NULL; - char dot[] = "."; - garray_T ga; - - if (cmd[0] != '<' || cmd[1] != '<' || eap->getline == NULL) - return NULL; + const char *const cmd = (const char *)eap->arg; - ga_init(&ga, 1, 0x400); + if (cmd[0] != '<' || cmd[1] != '<' || eap->getline == NULL) { + *lenp = STRLEN(eap->arg); + return eap->skip ? NULL : xmemdupz(eap->arg, *lenp); + } - if (cmd[2] != NUL) - end_pattern = (char *)skipwhite(cmd + 2); - else - end_pattern = dot; + garray_T ga = { .ga_data = NULL, .ga_len = 0 }; + if (!eap->skip) { + ga_init(&ga, 1, 0x400); + } - for (;; ) { - theline = eap->getline( + const char *const end_pattern = ( + cmd[2] != NUL + ? (const char *)skipwhite((const char_u *)cmd + 2) + : "."); + for (;;) { + char *const theline = (char *)eap->getline( eap->cstack->cs_looplevel > 0 ? -1 : NUL, eap->cookie, 0); - if (theline == NULL || STRCMP(end_pattern, theline) == 0) { + if (theline == NULL || strcmp(end_pattern, theline) == 0) { xfree(theline); break; } - ga_concat(&ga, theline); - ga_append(&ga, '\n'); + if (!eap->skip) { + ga_concat(&ga, (const char_u *)theline); + ga_append(&ga, '\n'); + } xfree(theline); } - ga_append(&ga, NUL); + *lenp = (size_t)ga.ga_len; // Set length without trailing NUL. + if (!eap->skip) { + ga_append(&ga, NUL); + } - return (char_u *)ga.ga_data; + return (char *)ga.ga_data; } /// Iterate over history items @@ -5469,3 +5964,15 @@ histentry_T *hist_get_array(const uint8_t history_type, int **const new_hisidx, *new_hisnum = &(hisnum[history_type]); return history[history_type]; } + +static void set_search_match(pos_T *t) +{ + // First move cursor to end of match, then to the start. This + // moves the whole match onto the screen when 'nowrap' is set. + t->lnum += search_match_lines; + t->col = search_match_endcol; + if (t->lnum > curbuf->b_ml.ml_line_count) { + t->lnum = curbuf->b_ml.ml_line_count; + coladvance((colnr_T)MAXCOL); + } +} diff --git a/src/nvim/ex_getln.h b/src/nvim/ex_getln.h index 24eebdc303..051564fbe1 100644 --- a/src/nvim/ex_getln.h +++ b/src/nvim/ex_getln.h @@ -1,8 +1,11 @@ #ifndef NVIM_EX_GETLN_H #define NVIM_EX_GETLN_H -#include "nvim/eval_defs.h" +#include "nvim/eval/typval.h" #include "nvim/ex_cmds.h" +#include "nvim/ex_cmds_defs.h" +#include "nvim/os/time.h" +#include "nvim/regexp_defs.h" /* Values for nextwild() and ExpandOne(). See ExpandOne() for meaning. */ #define WILD_FREE 1 diff --git a/src/nvim/farsi.c b/src/nvim/farsi.c index eb22ad1428..1053cb3ac2 100644 --- a/src/nvim/farsi.c +++ b/src/nvim/farsi.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + /// @file farsi.c /// /// Functions for Farsi language @@ -131,7 +134,7 @@ static char_u toF_Xor_X_(int c) /// @param c The character to convert. /// /// @return Character converted to the Farsi capital leter. -char_u toF_TyA(char_u c) +static char_u toF_TyA(char_u c) { char_u tempc; @@ -321,7 +324,7 @@ static void put_curr_and_l_to_X(char_u c) } if ((curwin->w_cursor.col < (colnr_T)STRLEN(get_cursor_line_ptr()))) { - if ((p_ri && curwin->w_cursor.col) || !p_ri) { + if (!p_ri || curwin->w_cursor.col) { if (p_ri) { dec_cursor(); } else { @@ -1557,7 +1560,7 @@ static char_u toF_ending(char_u c) } /// Convert the Farsi 3342 standard into Farsi VIM. -void conv_to_pvim(void) +static void conv_to_pvim(void) { char_u *ptr; int lnum, llen, i; @@ -1588,23 +1591,23 @@ void conv_to_pvim(void) } // Following lines contains Farsi encoded character. - do_cmdline_cmd("%s/\202\231/\232/g"); - do_cmdline_cmd("%s/\201\231/\370\334/g"); + do_cmdline_cmd("%s/\202\231/\232/ge"); + do_cmdline_cmd("%s/\201\231/\370\334/ge"); // Assume the screen has been messed up: clear it and redraw. redraw_later(CLEAR); - MSG_ATTR(farsi_text_1, hl_attr(HLF_S)); + MSG_ATTR((const char *)farsi_text_1, hl_attr(HLF_S)); } /// Convert the Farsi VIM into Farsi 3342 standard. -void conv_to_pstd(void) +static void conv_to_pstd(void) { char_u *ptr; int lnum, llen, i; // Following line contains Farsi encoded character. - do_cmdline_cmd("%s/\232/\202\231/g"); - for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count; ++lnum) { + do_cmdline_cmd("%s/\232/\202\231/ge"); + for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count; lnum++) { ptr = ml_get((linenr_T)lnum); llen = (int)STRLEN(ptr); for (i = 0; i < llen; i++) { @@ -1614,7 +1617,7 @@ void conv_to_pstd(void) // Assume the screen has been messed up: clear it and redraw. redraw_later(CLEAR); - MSG_ATTR(farsi_text_2, hl_attr(HLF_S)); + msg_attr((const char *)farsi_text_2, hl_attr(HLF_S)); } /// left-right swap the characters in buf[len]. @@ -2036,34 +2039,31 @@ bool F_ischar(int c) return c >= TEE_ && c <= YE_; } -void farsi_fkey(cmdarg_T *cap) +void farsi_f8(cmdarg_T *cap FUNC_ATTR_UNUSED) { - int c = cap->cmdchar; - - if (c == K_F8) { - if (p_altkeymap) { - if (curwin->w_farsi & W_R_L) { - p_fkmap = 0; - do_cmdline_cmd("set norl"); - MSG(""); - } else { - p_fkmap = 1; - do_cmdline_cmd("set rl"); - MSG(""); - } - - curwin->w_farsi = curwin->w_farsi ^ W_R_L; + if (p_altkeymap) { + if (curwin->w_farsi & W_R_L) { + p_fkmap = 0; + do_cmdline_cmd("set norl"); + MSG(""); + } else { + p_fkmap = 1; + do_cmdline_cmd("set rl"); + MSG(""); } + + curwin->w_farsi = curwin->w_farsi ^ W_R_L; } +} - if (c == K_F9) { - if (p_altkeymap && curwin->w_p_rl) { - curwin->w_farsi = curwin->w_farsi ^ W_CONV; - if (curwin->w_farsi & W_CONV) { - conv_to_pvim(); - } else { - conv_to_pstd(); - } +void farsi_f9(cmdarg_T *cap FUNC_ATTR_UNUSED) +{ + if (p_altkeymap && curwin->w_p_rl) { + curwin->w_farsi = curwin->w_farsi ^ W_CONV; + if (curwin->w_farsi & W_CONV) { + conv_to_pvim(); + } else { + conv_to_pstd(); } } } diff --git a/src/nvim/file_search.c b/src/nvim/file_search.c index 2ac8e27047..8094a1b266 100644 --- a/src/nvim/file_search.c +++ b/src/nvim/file_search.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + // File searching functions for 'path', 'tags' and 'cdpath' options. // // External visible functions: @@ -48,6 +51,7 @@ #include <limits.h> #include "nvim/vim.h" +#include "nvim/eval.h" #include "nvim/ascii.h" #include "nvim/file_search.h" #include "nvim/charset.h" @@ -192,7 +196,6 @@ typedef struct ff_search_ctx_T { static char_u e_pathtoolong[] = N_("E854: path too long for completion"); - /* * Initialization routine for vim_findfile(). * @@ -322,8 +325,11 @@ vim_findfile_init ( drive[0] = path[0]; drive[1] = ':'; drive[2] = NUL; - if (vim_FullName(drive, ff_expand_buffer, MAXPATHL, TRUE) == FAIL) + if (vim_FullName((const char *)drive, (char *)ff_expand_buffer, MAXPATHL, + true) + == FAIL) { goto error_return; + } path += 2; } else #endif @@ -636,9 +642,8 @@ char_u *vim_findfile(void *search_ctx_arg) if (p_verbose >= 5) { verbose_enter_scroll(); smsg("Already Searched: %s (%s)", - stackp->ffs_fix_path, stackp->ffs_wc_path); - /* don't overwrite this either */ - msg_puts((char_u *)"\n"); + stackp->ffs_fix_path, stackp->ffs_wc_path); + msg_puts("\n"); // don't overwrite this either verbose_leave_scroll(); } #endif @@ -650,8 +655,7 @@ char_u *vim_findfile(void *search_ctx_arg) verbose_enter_scroll(); smsg("Searching: %s (%s)", stackp->ffs_fix_path, stackp->ffs_wc_path); - /* don't overwrite this either */ - msg_puts((char_u *)"\n"); + msg_puts("\n"); // don't overwrite this either verbose_leave_scroll(); } #endif @@ -809,10 +813,8 @@ char_u *vim_findfile(void *search_ctx_arg) ) == FAIL) { if (p_verbose >= 5) { verbose_enter_scroll(); - smsg("Already: %s", - file_path); - /* don't overwrite this either */ - msg_puts((char_u *)"\n"); + smsg("Already: %s", file_path); + msg_puts("\n"); // don't overwrite this either verbose_leave_scroll(); } continue; @@ -837,8 +839,7 @@ char_u *vim_findfile(void *search_ctx_arg) if (p_verbose >= 5) { verbose_enter_scroll(); smsg("HIT: %s", file_path); - /* don't overwrite this either */ - msg_puts((char_u *)"\n"); + msg_puts("\n"); // don't overwrite this either verbose_leave_scroll(); } #endif @@ -999,10 +1000,8 @@ static ff_visited_list_hdr_T *ff_get_visited_list(char_u *filename, ff_visited_l #ifdef FF_VERBOSE if (p_verbose >= 5) { verbose_enter_scroll(); - smsg("ff_get_visited_list: FOUND list for %s", - filename); - /* don't overwrite this either */ - msg_puts((char_u *)"\n"); + smsg("ff_get_visited_list: FOUND list for %s", filename); + msg_puts("\n"); // don't overwrite this either verbose_leave_scroll(); } #endif @@ -1016,8 +1015,7 @@ static ff_visited_list_hdr_T *ff_get_visited_list(char_u *filename, ff_visited_l if (p_verbose >= 5) { verbose_enter_scroll(); smsg("ff_get_visited_list: new list for %s", filename); - /* don't overwrite this either */ - msg_puts((char_u *)"\n"); + msg_puts("\n"); // don't overwrite this either verbose_leave_scroll(); } #endif @@ -1062,7 +1060,7 @@ static bool ff_wc_equal(char_u *s1, char_u *s2) c1 = PTR2CHAR(s1 + i); c2 = PTR2CHAR(s2 + j); - if ((p_fic ? vim_tolower(c1) != vim_tolower(c2) : c1 != c2) + if ((p_fic ? mb_tolower(c1) != mb_tolower(c2) : c1 != c2) && (prev1 != '*' || prev2 != '*')) { return false; } @@ -1370,6 +1368,11 @@ find_file_in_path_option ( char_u *buf = NULL; int rel_to_curdir; + if (rel_fname != NULL && path_with_url((const char *)rel_fname)) { + // Do not attempt to search "relative" to a URL. #6009 + rel_fname = NULL; + } + if (first == TRUE) { /* copy file name into NameBuff, expanding environment variables */ save_char = ptr[len]; @@ -1522,26 +1525,85 @@ theend: return file_name; } +void do_autocmd_dirchanged(char *new_dir, CdScope scope) +{ + static bool recursive = false; + + if (recursive || !has_event(EVENT_DIRCHANGED)) { + // No autocommand was defined or we changed + // the directory from this autocommand. + return; + } + + recursive = true; + + dict_T *dict = get_vim_var_dict(VV_EVENT); + char buf[8]; + + switch (scope) { + case kCdScopeGlobal: + snprintf(buf, sizeof(buf), "global"); + break; + case kCdScopeTab: + snprintf(buf, sizeof(buf), "tab"); + break; + case kCdScopeWindow: + snprintf(buf, sizeof(buf), "window"); + break; + case kCdScopeInvalid: + // Should never happen. + assert(false); + } + + tv_dict_add_str(dict, S_LEN("scope"), buf); + tv_dict_add_str(dict, S_LEN("cwd"), new_dir); + tv_dict_set_keys_readonly(dict); + + apply_autocmds(EVENT_DIRCHANGED, (char_u *)buf, (char_u *)new_dir, false, + NULL); + + tv_dict_clear(dict); + + recursive = false; +} + /// Change to a file's directory. /// Caller must call shorten_fnames()! /// @return OK or FAIL int vim_chdirfile(char_u *fname) { - char_u dir[MAXPATHL]; + char dir[MAXPATHL]; STRLCPY(dir, fname, MAXPATHL); - *path_tail_with_sep(dir) = NUL; - return os_chdir((char *)dir) == 0 ? OK : FAIL; + *path_tail_with_sep((char_u *)dir) = NUL; + + if (os_dirname(NameBuff, sizeof(NameBuff)) != OK) { + NameBuff[0] = NUL; + } + + if (os_chdir(dir) != 0) { + return FAIL; + } + +#ifdef BACKSLASH_IN_FILENAME + slash_adjust(dir); +#endif + if (!strequal(dir, (char *)NameBuff)) { + do_autocmd_dirchanged(dir, kCdScopeWindow); + } + + return OK; } /// Change directory to "new_dir". Search 'cdpath' for relative directory names. -int vim_chdir(char_u *new_dir) +int vim_chdir(char_u *new_dir, CdScope scope) { char_u *dir_name = find_directory_in_path(new_dir, STRLEN(new_dir), FNAME_MESS, curbuf->b_ffname); if (dir_name == NULL) { return -1; } + int r = os_chdir((char *)dir_name); xfree(dir_name); return r; diff --git a/src/nvim/file_search.h b/src/nvim/file_search.h index 833a1a05ff..b128029123 100644 --- a/src/nvim/file_search.h +++ b/src/nvim/file_search.h @@ -1,6 +1,11 @@ #ifndef NVIM_FILE_SEARCH_H #define NVIM_FILE_SEARCH_H +#include <stdlib.h> // for size_t + +#include "nvim/types.h" // for char_u +#include "nvim/globals.h" // for CdScope + /* Flags for find_file_*() functions. */ #define FINDFILE_FILE 0 /* only files */ #define FINDFILE_DIR 1 /* only directories */ diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index 29114201d2..feb16f44d4 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + /* * fileio.c: read from and write to a file */ @@ -200,18 +203,14 @@ void filemess(buf_T *buf, char_u *name, char_u *s, int attr) { int msg_scroll_save; - if (msg_silent != 0) + if (msg_silent != 0) { return; - msg_add_fname(buf, name); /* put file name in IObuff with quotes */ - /* If it's extremely long, truncate it. */ - if (STRLEN(IObuff) > IOSIZE - 80) - IObuff[IOSIZE - 80] = NUL; - STRCAT(IObuff, s); - /* - * For the first message may have to start a new line. - * For further ones overwrite the previous one, reset msg_scroll before - * calling filemess(). - */ + } + add_quoted_fname((char *)IObuff, IOSIZE - 80, buf, (const char *)name); + xstrlcat((char *)IObuff, (const char *)s, IOSIZE); + // For the first message may have to start a new line. + // For further ones overwrite the previous one, reset msg_scroll before + // calling filemess(). msg_scroll_save = msg_scroll; if (shortmess(SHM_OVERALL) && !exiting && p_verbose == 0) msg_scroll = FALSE; @@ -248,8 +247,9 @@ void filemess(buf_T *buf, char_u *name, char_u *s, int attr) * stdin) * READ_DUMMY read into a dummy buffer (to check if file contents changed) * READ_KEEP_UNDO don't clear undo info or read it from a file + * READ_FIFO read from fifo/socket instead of a file * - * return FAIL for failure, OK otherwise + * return FAIL for failure, NOTDONE for directory (failure), or OK */ int readfile ( @@ -258,7 +258,7 @@ readfile ( linenr_T from, linenr_T lines_to_skip, linenr_T lines_to_read, - exarg_T *eap, /* can be NULL! */ + exarg_T *eap, // can be NULL! int flags ) { @@ -268,6 +268,7 @@ readfile ( int filtering = (flags & READ_FILTER); int read_stdin = (flags & READ_STDIN); int read_buffer = (flags & READ_BUFFER); + int read_fifo = (flags & READ_FIFO); int set_options = newfile || read_buffer || (eap != NULL && eap->read_edit); linenr_T read_buf_lnum = 1; /* next line to read from curbuf */ @@ -281,9 +282,9 @@ readfile ( int wasempty; /* buffer was empty before reading */ colnr_T len; long size = 0; - char_u *p; - off_t filesize = 0; - int skip_read = FALSE; + char_u *p = NULL; + off_T filesize = 0; + int skip_read = false; context_sha256_T sha_ctx; int read_undo_file = FALSE; int split = 0; /* number of split lines */ @@ -427,8 +428,8 @@ readfile ( } } - if (!read_buffer && !read_stdin) { - perm = os_getperm(fname); + if (!read_buffer && !read_stdin && !read_fifo) { + perm = os_getperm((const char *)fname); #ifdef UNIX // On Unix it is possible to read a directory, so we have to // check for it before os_open(). @@ -444,13 +445,14 @@ readfile ( // ... or a character special file named /dev/fd/<n> # endif ) { - if (S_ISDIR(perm)) + if (S_ISDIR(perm)) { filemess(curbuf, fname, (char_u *)_("is a directory"), 0); - else + } else { filemess(curbuf, fname, (char_u *)_("is not a file"), 0); + } msg_end(); msg_scroll = msg_save; - return FAIL; + return S_ISDIR(perm) ? NOTDONE : FAIL; } #endif } @@ -468,8 +470,8 @@ readfile ( if (check_readonly && !readonlymode) curbuf->b_p_ro = FALSE; - if (newfile && !read_stdin && !read_buffer) { - /* Remember time of file. */ + if (newfile && !read_stdin && !read_buffer && !read_fifo) { + // Remember time of file. FileInfo file_info; if (os_fileinfo((char *)fname, &file_info)) { buf_store_file_info(curbuf, &file_info); @@ -613,10 +615,12 @@ readfile ( return FAIL; } #ifdef UNIX - /* Set swap file protection bits after creating it. */ + // Set swap file protection bits after creating it. if (swap_mode > 0 && curbuf->b_ml.ml_mfp != NULL - && curbuf->b_ml.ml_mfp->mf_fname != NULL) - (void)os_setperm(curbuf->b_ml.ml_mfp->mf_fname, (long)swap_mode); + && curbuf->b_ml.ml_mfp->mf_fname != NULL) { + (void)os_setperm((const char *)curbuf->b_ml.ml_mfp->mf_fname, + (long)swap_mode); + } #endif } @@ -699,16 +703,9 @@ readfile ( wasempty = (curbuf->b_ml.ml_flags & ML_EMPTY); if (!recoverymode && !filtering && !(flags & READ_DUMMY)) { - /* - * Show the user that we are busy reading the input. Sometimes this - * may take a while. When reading from stdin another program may - * still be running, don't move the cursor to the last line, unless - * always using the GUI. - */ - if (read_stdin) { - mch_msg(_("Nvim: Reading from stdin...\n")); - } else if (!read_buffer) + if (!read_stdin && !read_buffer) { filemess(curbuf, sfname, (char_u *)"", 0); + } } msg_scroll = FALSE; /* overwrite the file message */ @@ -738,43 +735,16 @@ readfile ( fenc = (char_u *)""; /* binary: don't convert */ fenc_alloced = FALSE; } else if (curbuf->b_help) { - char_u firstline[80]; - int fc; - - /* Help files are either utf-8 or latin1. Try utf-8 first, if this - * fails it must be latin1. - * Always do this when 'encoding' is "utf-8". Otherwise only do - * this when needed to avoid [converted] remarks all the time. - * It is needed when the first line contains non-ASCII characters. - * That is only in *.??x files. */ - fenc = (char_u *)"latin1"; - c = enc_utf8; - if (!c && !read_stdin) { - fc = fname[STRLEN(fname) - 1]; - if (TOLOWER_ASC(fc) == 'x') { - /* Read the first line (and a bit more). Immediately rewind to - * the start of the file. If the read() fails "len" is -1. */ - len = read_eintr(fd, firstline, 80); - lseek(fd, (off_t)0L, SEEK_SET); - for (p = firstline; p < firstline + len; ++p) - if (*p >= 0x80) { - c = TRUE; - break; - } - } - } + // Help files are either utf-8 or latin1. Try utf-8 first, if this + // fails it must be latin1. + // It is needed when the first line contains non-ASCII characters. + // That is only in *.??x files. + fenc_next = (char_u *)"latin1"; + fenc = (char_u *)"utf-8"; - if (c) { - fenc_next = fenc; - fenc = (char_u *)"utf-8"; + fenc_alloced = false; - /* When the file is utf-8 but a character doesn't fit in - * 'encoding' don't retry. In help text editing utf-8 bytes - * doesn't make sense. */ - if (!enc_utf8) - keep_dest_enc = TRUE; - } - fenc_alloced = FALSE; + c = 1; } else if (*p_fencs == NUL) { fenc = curbuf->b_p_fenc; /* use format from buffer */ fenc_alloced = FALSE; @@ -809,9 +779,9 @@ retry: if (read_buffer) { read_buf_lnum = 1; read_buf_col = 0; - } else if (read_stdin || lseek(fd, (off_t)0L, SEEK_SET) != 0) { - /* Can't rewind the file, give up. */ - error = TRUE; + } else if (read_stdin || vim_lseek(fd, (off_T)0L, SEEK_SET) != 0) { + // Can't rewind the file, give up. + error = true; goto failed; } /* Delete the previously read lines. */ @@ -927,6 +897,7 @@ retry: * and we can't do it internally or with iconv(). */ if (fio_flags == 0 && !read_stdin && !read_buffer && *p_ccv != NUL + && !read_fifo # ifdef USE_ICONV && iconv_fd == (iconv_t)-1 # endif @@ -967,7 +938,7 @@ retry: /* Set "can_retry" when it's possible to rewind the file and try with * another "fenc" value. It's FALSE when no other "fenc" to try, reading * stdin or fixed at a specific encoding. */ - can_retry = (*fenc != NUL && !read_stdin && !keep_dest_enc); + can_retry = (*fenc != NUL && !read_stdin && !keep_dest_enc && !read_fifo); if (!skip_read) { linerest = 0; @@ -979,6 +950,7 @@ retry: && curbuf->b_ffname != NULL && curbuf->b_p_udf && !filtering + && !read_fifo && !read_stdin && !read_buffer); if (read_undo_file) @@ -1646,19 +1618,16 @@ rewind_retry: if (fileformat == EOL_DOS) { if (ptr[-1] == CAR) { /* remove CR */ ptr[-1] = NUL; - --len; - } - /* - * Reading in Dos format, but no CR-LF found! - * When 'fileformats' includes "unix", delete all - * the lines read so far and start all over again. - * Otherwise give an error message later. - */ - else if (ff_error != EOL_DOS) { - if ( try_unix - && !read_stdin - && (read_buffer - || lseek(fd, (off_t)0L, SEEK_SET) == 0)) { + len--; + } else if (ff_error != EOL_DOS) { + // Reading in Dos format, but no CR-LF found! + // When 'fileformats' includes "unix", delete all + // the lines read so far and start all over again. + // Otherwise give an error message later. + if (try_unix + && !read_stdin + && (read_buffer + || vim_lseek(fd, (off_T)0L, SEEK_SET) == 0)) { fileformat = EOL_UNIX; if (set_options) set_fileformat(EOL_UNIX, OPT_LOCAL); @@ -1741,16 +1710,11 @@ failed: } # endif - if (!read_buffer && !read_stdin) - close(fd); /* errors are ignored */ -#ifdef HAVE_FD_CLOEXEC - else { - int fdflags = fcntl(fd, F_GETFD); - if (fdflags >= 0 && (fdflags & FD_CLOEXEC) == 0) { - (void)fcntl(fd, F_SETFD, fdflags | FD_CLOEXEC); - } + if (!read_buffer && !read_stdin) { + close(fd); // errors are ignored + } else { + (void)os_set_cloexec(fd); } -#endif xfree(buffer); if (read_stdin) { @@ -1809,8 +1773,8 @@ failed: } if (!filtering && !(flags & READ_DUMMY)) { - msg_add_fname(curbuf, sfname); /* fname in IObuff with quotes */ - c = FALSE; + add_quoted_fname((char *)IObuff, IOSIZE, curbuf, (const char *)sfname); + c = false; #ifdef UNIX # ifdef S_ISFIFO @@ -1881,17 +1845,22 @@ failed: xfree(keep_msg); keep_msg = NULL; + p = NULL; msg_scrolled_ign = TRUE; - p = msg_trunc_attr(IObuff, FALSE, 0); + + if (!read_stdin && !read_buffer) { + p = msg_trunc_attr(IObuff, FALSE, 0); + } + if (read_stdin || read_buffer || restart_edit != 0 - || (msg_scrolled != 0 && !need_wait_return)) - /* Need to repeat the message after redrawing when: - * - When reading from stdin (the screen will be cleared next). - * - When restart_edit is set (otherwise there will be a delay - * before redrawing). - * - When the screen was scrolled but there is no wait-return - * prompt. */ + || (msg_scrolled != 0 && !need_wait_return)) { + // Need to repeat the message after redrawing when: + // - When reading from stdin (the screen will be cleared next). + // - When restart_edit is set (otherwise there will be a delay before + // redrawing). + // - When the screen was scrolled but there is no wait-return prompt. set_keep_msg(p, 0); + } msg_scrolled_ign = FALSE; } @@ -1954,7 +1923,7 @@ failed: u_read_undo(NULL, hash, fname); } - if (!read_stdin && !read_buffer) { + if (!read_stdin && !read_fifo && (!read_buffer || sfname != NULL)) { int m = msg_scroll; int n = msg_scrolled; @@ -1972,7 +1941,7 @@ failed: if (filtering) { apply_autocmds_exarg(EVENT_FILTERREADPOST, NULL, sfname, false, curbuf, eap); - } else if (newfile) { + } else if (newfile || (read_buffer && sfname != NULL)) { apply_autocmds_exarg(EVENT_BUFREADPOST, NULL, sfname, false, curbuf, eap); if (!au_did_filetype && *curbuf->b_p_ft != NUL) { @@ -2005,7 +1974,7 @@ failed: /// Do not accept "/dev/fd/[012]", opening these may hang Vim. /// /// @param fname file name to check -static bool is_dev_fd_file(char_u *fname) +bool is_dev_fd_file(char_u *fname) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT { return STRNCMP(fname, "/dev/fd/", 8) == 0 @@ -2262,9 +2231,16 @@ buf_write ( int len; linenr_T lnum; long nchars; - char_u *errmsg = NULL; - int errmsg_allocated = FALSE; - char_u *errnum = NULL; +#define SET_ERRMSG_NUM(num, msg) \ + errnum = num, errmsg = msg, errmsgarg = 0 +#define SET_ERRMSG_ARG(msg, error) \ + errnum = NULL, errmsg = msg, errmsgarg = error +#define SET_ERRMSG(msg) \ + errnum = NULL, errmsg = msg, errmsgarg = 0 + const char *errnum = NULL; + char *errmsg = NULL; + int errmsgarg = 0; + bool errmsg_allocated = false; char_u *buffer; char_u smallbuf[SMBUFSIZE]; char_u *backup_ext; @@ -2286,7 +2262,6 @@ buf_write ( /* writing everything */ int whole = (start == 1 && end == buf->b_ml.ml_line_count); linenr_T old_line_count = buf->b_ml.ml_line_count; - int attr; int fileformat; int write_bin; struct bw_info write_info; /* info for buf_write_bytes() */ @@ -2396,6 +2371,7 @@ buf_write ( int did_cmd = FALSE; int nofile_err = FALSE; int empty_memline = (buf->b_ml.ml_mfp == NULL); + bufref_T bufref; /* * Apply PRE autocommands. @@ -2411,8 +2387,9 @@ buf_write ( if (fname == buf->b_sfname) buf_fname_s = TRUE; - /* set curwin/curbuf to buf and save a few things */ + // Set curwin/curbuf to buf and save a few things. aucmd_prepbuf(&aco, buf); + set_bufref(&bufref, buf); if (append) { if (!(did_cmd = apply_autocmds_exarg(EVENT_FILEAPPENDCMD, @@ -2460,14 +2437,13 @@ buf_write ( /* restore curwin/curbuf and a few other things */ aucmd_restbuf(&aco); - /* - * In three situations we return here and don't write the file: - * 1. the autocommands deleted or unloaded the buffer. - * 2. The autocommands abort script processing. - * 3. If one of the "Cmd" autocommands was executed. - */ - if (!buf_valid(buf)) + // In three situations we return here and don't write the file: + // 1. the autocommands deleted or unloaded the buffer. + // 2. The autocommands abort script processing. + // 3. If one of the "Cmd" autocommands was executed. + if (!bufref_valid(&bufref)) { buf = NULL; + } if (buf == NULL || (buf->b_ml.ml_mfp == NULL && !empty_memline) || did_cmd || nofile_err || aborting() @@ -2580,13 +2556,11 @@ buf_write ( perm = file_info_old.stat.st_mode; if (!S_ISREG(file_info_old.stat.st_mode)) { /* not a file */ if (S_ISDIR(file_info_old.stat.st_mode)) { - errnum = (char_u *)"E502: "; - errmsg = (char_u *)_("is a directory"); + SET_ERRMSG_NUM("E502", _("is a directory")); goto fail; } if (os_nodetype((char *)fname) != NODE_WRITABLE) { - errnum = (char_u *)"E503: "; - errmsg = (char_u *)_("is not a file or writable device"); + SET_ERRMSG_NUM("E503", _("is not a file or writable device")); goto fail; } /* It's a device of some kind (or a fifo) which we can write to @@ -2596,14 +2570,11 @@ buf_write ( perm = -1; } } -#else /* win32 */ - /* - * Check for a writable device name. - */ - c = os_nodetype((char *)fname); +#else // win32 + // Check for a writable device name. + c = fname == NULL ? NODE_OTHER : os_nodetype((char *)fname); if (c == NODE_OTHER) { - errnum = (char_u *)"E503: "; - errmsg = (char_u *)_("is not a file or writable device"); + SET_ERRMSG_NUM("E503", _("is not a file or writable device")); goto fail; } if (c == NODE_WRITABLE) { @@ -2611,20 +2582,18 @@ buf_write ( newfile = TRUE; perm = -1; } else { - perm = os_getperm(fname); - if (perm < 0) - newfile = TRUE; - else if (os_isdir(fname)) { - errnum = (char_u *)"E502: "; - errmsg = (char_u *)_("is a directory"); + perm = os_getperm((const char *)fname); + if (perm < 0) { + newfile = true; + } else if (os_isdir(fname)) { + SET_ERRMSG_NUM("E502", _("is a directory")); goto fail; } if (overwriting) { os_fileinfo((char *)fname, &file_info_old); } - } -#endif /* !UNIX */ +#endif // !UNIX if (!device && !newfile) { /* @@ -2635,11 +2604,9 @@ buf_write ( if (!forceit && file_readonly) { if (vim_strchr(p_cpo, CPO_FWRITE) != NULL) { - errnum = (char_u *)"E504: "; - errmsg = (char_u *)_(err_readonly); + SET_ERRMSG_NUM("E504", _(err_readonly)); } else { - errnum = (char_u *)"E505: "; - errmsg = (char_u *)_("is read-only (add ! to override)"); + SET_ERRMSG_NUM("E505", _("is read-only (add ! to override)")); } goto fail; } @@ -2875,9 +2842,9 @@ buf_write ( xfree(backup); backup = NULL; } else { - /* set file protection same as original file, but - * strip s-bit */ - (void)os_setperm(backup, perm & 0777); + // set file protection same as original file, but + // strip s-bit. + (void)os_setperm((const char *)backup, perm & 0777); #ifdef UNIX /* @@ -2888,7 +2855,8 @@ buf_write ( */ if (file_info_new.stat.st_gid != file_info_old.stat.st_gid && os_fchown(bfd, -1, file_info_old.stat.st_gid) != 0) { - os_setperm(backup, (perm & 0707) | ((perm & 07) << 3)); + os_setperm((const char *)backup, + (perm & 0707) | ((perm & 07) << 3)); } # ifdef HAVE_SELINUX mch_copy_sec(fname, backup); @@ -2906,23 +2874,27 @@ buf_write ( while ((write_info.bw_len = read_eintr(fd, copybuf, BUFSIZE)) > 0) { if (buf_write_bytes(&write_info) == FAIL) { - errmsg = (char_u *)_( - "E506: Can't write to backup file (add ! to override)"); + SET_ERRMSG(_( + "E506: Can't write to backup file (add ! to override)")); break; } os_breakcheck(); if (got_int) { - errmsg = (char_u *)_(e_interr); + SET_ERRMSG(_(e_interr)); break; } } - if (close(bfd) < 0 && errmsg == NULL) - errmsg = (char_u *)_( - "E507: Close error for backup file (add ! to override)"); - if (write_info.bw_len < 0) - errmsg = (char_u *)_( - "E508: Can't read file for backup (add ! to override)"); + int error; + if ((error = os_close(bfd)) != 0 && errmsg == NULL) { + SET_ERRMSG_ARG(_("E507: Close error for backup file " + "(add ! to override): %s"), + error); + } + if (write_info.bw_len < 0) { + SET_ERRMSG(_( + "E508: Can't read file for backup (add ! to override)")); + } #ifdef UNIX set_file_time(backup, file_info_old.stat.st_atim.tv_sec, @@ -2939,18 +2911,19 @@ buf_write ( } } nobackup: - close(fd); /* ignore errors for closing read file */ + os_close(fd); // Ignore errors for closing read file. xfree(copybuf); - if (backup == NULL && errmsg == NULL) - errmsg = (char_u *)_( - "E509: Cannot create backup file (add ! to override)"); - /* ignore errors when forceit is TRUE */ + if (backup == NULL && errmsg == NULL) { + SET_ERRMSG(_( + "E509: Cannot create backup file (add ! to override)")); + } + // Ignore errors when forceit is TRUE. if ((some_error || errmsg != NULL) && !forceit) { retval = FAIL; goto fail; } - errmsg = NULL; + SET_ERRMSG(NULL); } else { char_u *dirp; char_u *p; @@ -2965,8 +2938,7 @@ nobackup: * anyway, thus we need an extra check here. */ if (file_readonly && vim_strchr(p_cpo, CPO_FWRITE) != NULL) { - errnum = (char_u *)"E504: "; - errmsg = (char_u *)_(err_readonly); + SET_ERRMSG_NUM("E504", _(err_readonly)); goto fail; } @@ -3030,7 +3002,7 @@ nobackup: } } if (backup == NULL && !forceit) { - errmsg = (char_u *)_("E510: Can't make backup file (add ! to override)"); + SET_ERRMSG(_("E510: Can't make backup file (add ! to override)")); goto fail; } } @@ -3042,8 +3014,8 @@ nobackup: && file_info_old.stat.st_uid == getuid() && vim_strchr(p_cpo, CPO_FWRITE) == NULL) { perm |= 0200; - (void)os_setperm(fname, perm); - made_writable = TRUE; + (void)os_setperm((const char *)fname, perm); + made_writable = true; } #endif @@ -3071,7 +3043,7 @@ nobackup: && !(exiting && backup != NULL)) { ml_preserve(buf, FALSE); if (got_int) { - errmsg = (char_u *)_(e_interr); + SET_ERRMSG(_(e_interr)); goto restore_backup; } } @@ -3142,8 +3114,8 @@ nobackup: */ if (*p_ccv != NUL) { wfname = vim_tempname(); - if (wfname == NULL) { /* Can't write without a tempfile! */ - errmsg = (char_u *)_("E214: Can't find temp file for writing"); + if (wfname == NULL) { // Can't write without a tempfile! + SET_ERRMSG(_("E214: Can't find temp file for writing")); goto restore_backup; } } @@ -3155,8 +3127,8 @@ nobackup: && wfname == fname ) { if (!forceit) { - errmsg = (char_u *)_( - "E213: Cannot convert (add ! to write without conversion)"); + SET_ERRMSG(_( + "E213: Cannot convert (add ! to write without conversion)")); goto restore_backup; } notconverted = TRUE; @@ -3187,15 +3159,14 @@ nobackup: #ifdef UNIX FileInfo file_info; - /* Don't delete the file when it's a hard or symbolic link. */ - if ((!newfile && os_fileinfo_hardlinks(&file_info) > 1) + // Don't delete the file when it's a hard or symbolic link. + if ((!newfile && os_fileinfo_hardlinks(&file_info_old) > 1) || (os_fileinfo_link((char *)fname, &file_info) && !os_fileinfo_id_equal(&file_info, &file_info_old))) { - errmsg = (char_u *)_("E166: Can't open linked file for writing"); - } else + SET_ERRMSG(_("E166: Can't open linked file for writing")); + } else { #endif - { - errmsg = (char_u *)_("E212: Can't open file for writing"); + SET_ERRMSG_ARG(_("E212: Can't open file for writing: %s"), fd); if (forceit && vim_strchr(p_cpo, CPO_FWRITE) == NULL && perm >= 0) { #ifdef UNIX @@ -3213,7 +3184,9 @@ nobackup: os_remove((char *)wfname); continue; } +#ifdef UNIX } +#endif } restore_backup: @@ -3255,7 +3228,7 @@ restore_backup: xfree(wfname); goto fail; } - errmsg = NULL; + SET_ERRMSG(NULL); write_info.bw_fd = fd; @@ -3375,7 +3348,6 @@ restore_backup: nchars += len; } -#if defined(UNIX) // On many journalling file systems there is a bug that causes both the // original and the backup file to be lost when halting the system right // after writing the file. That's because only the meta-data is @@ -3384,11 +3356,11 @@ restore_backup: // For a device do try the fsync() but don't complain if it does not work // (could be a pipe). // If the 'fsync' option is FALSE, don't fsync(). Useful for laptops. - if (p_fs && os_fsync(fd) != 0 && !device) { - errmsg = (char_u *)_("E667: Fsync failed"); + int error; + if (p_fs && (error = os_fsync(fd)) != 0 && !device) { + SET_ERRMSG_ARG(_("E667: Fsync failed: %s"), error); end = 0; } -#endif #ifdef HAVE_SELINUX /* Probably need to set the security context. */ @@ -3407,8 +3379,9 @@ restore_backup: || file_info.stat.st_uid != file_info_old.stat.st_uid || file_info.stat.st_gid != file_info_old.stat.st_gid) { os_fchown(fd, file_info_old.stat.st_uid, file_info_old.stat.st_gid); - if (perm >= 0) /* set permission again, may have changed */ - (void)os_setperm(wfname, perm); + if (perm >= 0) { // Set permission again, may have changed. + (void)os_setperm((const char *)wfname, perm); + } } buf_set_file_id(buf); } else if (!buf->file_id_valid) { @@ -3417,8 +3390,8 @@ restore_backup: } #endif - if (close(fd) != 0) { - errmsg = (char_u *)_("E512: Close failed"); + if ((error = os_close(fd)) != 0) { + SET_ERRMSG_ARG(_("E512: Close failed: %s"), error); end = 0; } @@ -3426,8 +3399,9 @@ restore_backup: if (made_writable) perm &= ~0200; /* reset 'w' bit for security reasons */ #endif - if (perm >= 0) /* set perm. of new file same as old file */ - (void)os_setperm(wfname, perm); + if (perm >= 0) { // Set perm. of new file same as old file. + (void)os_setperm((const char *)wfname, perm); + } #ifdef HAVE_ACL /* Probably need to set the ACL before changing the user (can't set the * ACL on a file the user doesn't own). */ @@ -3454,21 +3428,24 @@ restore_backup: if (end == 0) { if (errmsg == NULL) { if (write_info.bw_conv_error) { - if (write_info.bw_conv_error_lnum == 0) - errmsg = (char_u *)_( - "E513: write error, conversion failed (make 'fenc' empty to override)"); - else { - errmsg_allocated = TRUE; - errmsg = xmalloc(300); - vim_snprintf((char *)errmsg, 300, - _("E513: write error, conversion failed in line %" PRId64 + if (write_info.bw_conv_error_lnum == 0) { + SET_ERRMSG(_( + "E513: write error, conversion failed " + "(make 'fenc' empty to override)")); + } else { + errmsg_allocated = true; + SET_ERRMSG(xmalloc(300)); + vim_snprintf( + errmsg, 300, + _("E513: write error, conversion failed in line %" PRIdLINENR " (make 'fenc' empty to override)"), - (int64_t)write_info.bw_conv_error_lnum); + write_info.bw_conv_error_lnum); } - } else if (got_int) - errmsg = (char_u *)_(e_interr); - else - errmsg = (char_u *)_("E514: write error (file system full?)"); + } else if (got_int) { + SET_ERRMSG(_(e_interr)); + } else { + SET_ERRMSG(_("E514: write error (file system full?)")); + } } /* @@ -3523,8 +3500,8 @@ restore_backup: fname = sfname; /* use shortname now, for the messages */ #endif if (!filtering) { - msg_add_fname(buf, fname); /* put fname in IObuff with quotes */ - c = FALSE; + add_quoted_fname((char *)IObuff, IOSIZE, buf, (const char *)fname); + c = false; if (write_info.bw_conv_error) { STRCAT(IObuff, _(" CONVERSION ERROR")); c = TRUE; @@ -3633,7 +3610,7 @@ restore_backup: close(empty_fd); } if (org != NULL) { - os_setperm((char_u *)org, os_getperm(fname) & 0777); + os_setperm(org, os_getperm((const char *)fname) & 0777); xfree(org); } } @@ -3673,33 +3650,32 @@ nofail: #endif if (errmsg != NULL) { - int numlen = errnum != NULL ? (int)STRLEN(errnum) : 0; - - attr = hl_attr(HLF_E); /* set highlight for error messages */ - msg_add_fname(buf, + // - 100 to save some space for further error message #ifndef UNIX - sfname + add_quoted_fname((char *)IObuff, IOSIZE - 100, buf, (const char *)sfname); #else - fname + add_quoted_fname((char *)IObuff, IOSIZE - 100, buf, (const char *)fname); #endif - ); /* put file name in IObuff with quotes */ - if (STRLEN(IObuff) + STRLEN(errmsg) + numlen >= IOSIZE) - IObuff[IOSIZE - STRLEN(errmsg) - numlen - 1] = NUL; - /* If the error message has the form "is ...", put the error number in - * front of the file name. */ if (errnum != NULL) { - STRMOVE(IObuff + numlen, IObuff); - memmove(IObuff, errnum, (size_t)numlen); + if (errmsgarg != 0) { + emsgf("%s: %s%s: %s", errnum, IObuff, errmsg, os_strerror(errmsgarg)); + } else { + emsgf("%s: %s%s", errnum, IObuff, errmsg); + } + } else if (errmsgarg != 0) { + emsgf(errmsg, os_strerror(errmsgarg)); + } else { + emsgf(errmsg); } - STRCAT(IObuff, errmsg); - emsg(IObuff); - if (errmsg_allocated) + if (errmsg_allocated) { xfree(errmsg); + } retval = FAIL; if (end == 0) { + const int attr = hl_attr(HLF_E); // Set highlight for error messages. MSG_PUTS_ATTR(_("\nWARNING: Original file may be lost or damaged\n"), - attr | MSG_HIST); + attr | MSG_HIST); MSG_PUTS_ATTR(_( "don't quit the editor until the file is successfully written!"), attr | MSG_HIST); @@ -3759,6 +3735,9 @@ nofail: got_int |= prev_got_int; return retval; +#undef SET_ERRMSG +#undef SET_ERRMSG_ARG +#undef SET_ERRMSG_NUM } /* @@ -3802,16 +3781,25 @@ static int set_rw_fname(char_u *fname, char_u *sfname) return OK; } -/* - * Put file name into IObuff with quotes. - */ -void msg_add_fname(buf_T *buf, char_u *fname) +/// Put file name into the specified buffer with quotes +/// +/// Replaces home directory at the start with `~`. +/// +/// @param[out] ret_buf Buffer to save results to. +/// @param[in] buf_len ret_buf length. +/// @param[in] buf buf_T file name is coming from. +/// @param[in] fname File name to write. +static void add_quoted_fname(char *const ret_buf, const size_t buf_len, + const buf_T *const buf, const char *fname) + FUNC_ATTR_NONNULL_ARG(1) { - if (fname == NULL) - fname = (char_u *)"-stdin-"; - home_replace(buf, fname, IObuff + 1, IOSIZE - 4, TRUE); - IObuff[0] = '"'; - STRCAT(IObuff, "\" "); + if (fname == NULL) { + fname = "-stdin-"; + } + ret_buf[0] = '"'; + home_replace(buf, (const char_u *)fname, (char_u *)ret_buf + 1, + (int)buf_len - 4, true); + xstrlcat(ret_buf, "\" ", buf_len); } /// Append message for text mode to IObuff. @@ -3843,7 +3831,7 @@ static bool msg_add_fileformat(int eol_type) /* * Append line and character count to IObuff. */ -void msg_add_lines(int insert_space, long lnum, off_t nchars) +void msg_add_lines(int insert_space, long lnum, off_T nchars) { char_u *p; @@ -3888,15 +3876,15 @@ static int check_mtime(buf_T *buf, FileInfo *file_info) if (buf->b_mtime_read != 0 && time_differs(file_info->stat.st_mtim.tv_sec, buf->b_mtime_read)) { - msg_scroll = TRUE; /* don't overwrite messages here */ - msg_silent = 0; /* must give this prompt */ - /* don't use emsg() here, don't want to flush the buffers */ - MSG_ATTR(_("WARNING: The file has been changed since reading it!!!"), - hl_attr(HLF_E)); - if (ask_yesno((char_u *)_("Do you really want to write to it"), - TRUE) == 'n') + msg_scroll = true; // Don't overwrite messages here. + msg_silent = 0; // Must give this prompt. + // Don't use emsg() here, don't want to flush the buffers. + msg_attr(_("WARNING: The file has been changed since reading it!!!"), + hl_attr(HLF_E)); + if (ask_yesno(_("Do you really want to write to it"), true) == 'n') { return FAIL; - msg_scroll = FALSE; /* always overwrite the file message now */ + } + msg_scroll = false; // Always overwrite the file message now. } return OK; } @@ -4553,9 +4541,10 @@ int put_time(FILE *fd, time_t time_) /// os_rename() only works if both files are on the same file system, this /// function will (attempts to?) copy the file across if rename fails -- webb -// +/// /// @return -1 for failure, 0 for success -int vim_rename(char_u *from, char_u *to) +int vim_rename(const char_u *from, const char_u *to) + FUNC_ATTR_NONNULL_ALL { int fd_in; int fd_out; @@ -4574,10 +4563,12 @@ int vim_rename(char_u *from, char_u *to) * the file name differs we need to go through a temp file. */ if (fnamecmp(from, to) == 0) { - if (p_fic && STRCMP(path_tail(from), path_tail(to)) != 0) + if (p_fic && (STRCMP(path_tail((char_u *)from), path_tail((char_u *)to)) + != 0)) { use_tmp_file = true; - else + } else { return 0; + } } // Fail if the "from" file doesn't exist. Avoids that "to" is deleted. @@ -4643,9 +4634,9 @@ int vim_rename(char_u *from, char_u *to) /* * Rename() failed, try copying the file. */ - perm = os_getperm(from); + perm = os_getperm((const char *)from); #ifdef HAVE_ACL - /* For systems that support ACL: get the ACL from the original file. */ + // For systems that support ACL: get the ACL from the original file. acl = mch_get_acl(from); #endif fd_in = os_open((char *)from, O_RDONLY, 0); @@ -4667,7 +4658,7 @@ int vim_rename(char_u *from, char_u *to) return -1; } - // Avoid xmalloc() here as vim_rename() is called by buf_write() when neovim + // Avoid xmalloc() here as vim_rename() is called by buf_write() when nvim // is `preserve_exit()`ing. buffer = try_malloc(BUFSIZE); if (buffer == NULL) { @@ -4693,8 +4684,8 @@ int vim_rename(char_u *from, char_u *to) errmsg = _("E210: Error reading \"%s\""); to = from; } -#ifndef UNIX /* for Unix os_open() already set the permission */ - os_setperm(to, perm); +#ifndef UNIX // For Unix os_open() already set the permission. + os_setperm((const char *)to, perm); #endif #ifdef HAVE_ACL mch_set_acl(to, acl); @@ -4726,7 +4717,6 @@ check_timestamps ( int focus /* called for GUI focus event */ ) { - buf_T *buf; int didit = 0; int n; @@ -4745,32 +4735,33 @@ check_timestamps ( if (!stuff_empty() || global_busy || !typebuf_typed() || autocmd_busy || curbuf_lock > 0 || allbuf_lock > 0 - ) - need_check_timestamps = TRUE; /* check later */ - else { - ++no_wait_return; - did_check_timestamps = TRUE; - already_warned = FALSE; - for (buf = firstbuf; buf != NULL; ) { - /* Only check buffers in a window. */ + ) { + need_check_timestamps = true; // check later + } else { + no_wait_return++; + did_check_timestamps = true; + already_warned = false; + FOR_ALL_BUFFERS(buf) { + // Only check buffers in a window. if (buf->b_nwindows > 0) { + bufref_T bufref; + set_bufref(&bufref, buf); n = buf_check_timestamp(buf, focus); - if (didit < n) + if (didit < n) { didit = n; - if (n > 0 && !buf_valid(buf)) { - /* Autocommands have removed the buffer, start at the - * first one again. */ + } + if (n > 0 && !bufref_valid(&bufref)) { + // Autocommands have removed the buffer, start at the first one again. buf = firstbuf; continue; } } - buf = buf->b_next; } --no_wait_return; need_check_timestamps = FALSE; if (need_wait_return && didit == 2) { - /* make sure msg isn't overwritten */ - msg_puts((char_u *)"\n"); + // make sure msg isn't overwritten + msg_puts("\n"); ui_flush(); } } @@ -4829,6 +4820,7 @@ buf_check_timestamp ( buf_T *buf, int focus /* called for GUI focus event */ ) + FUNC_ATTR_NONNULL_ALL { int retval = 0; char_u *path; @@ -4844,6 +4836,9 @@ buf_check_timestamp ( char_u *s; char *reason; + bufref_T bufref; + set_bufref(&bufref, buf); + // If its a terminal, there is no file name, the buffer is not loaded, // 'buftype' is set, we are in the middle of a save or being called // recursively: ignore this buffer. @@ -4913,8 +4908,9 @@ buf_check_timestamp ( allbuf_lock--; busy = false; if (n) { - if (!buf_valid(buf)) + if (!bufref_valid(&bufref)) { EMSG(_("E246: FileChangedShell autocommand deleted buffer")); + } s = get_vim_var_str(VV_FCS_CHOICE); if (STRCMP(s, "reload") == 0 && *reason != 'd') reload = TRUE; @@ -4976,8 +4972,8 @@ buf_check_timestamp ( set_vim_var_string(VV_WARNINGMSG, tbuf, -1); if (can_reload) { if (*mesg2 != NUL) { - strncat(tbuf, "\n", tbuf_len); - strncat(tbuf, mesg2, tbuf_len); + xstrlcat(tbuf, "\n", tbuf_len - 1); + xstrlcat(tbuf, mesg2, tbuf_len - 1); } if (do_dialog(VIM_WARNING, (char_u *) _("Warning"), (char_u *) tbuf, (char_u *) _("&OK\n&Load File"), 1, NULL, true) == 2) { @@ -4985,18 +4981,17 @@ buf_check_timestamp ( } } else if (State > NORMAL_BUSY || (State & CMDLINE) || already_warned) { if (*mesg2 != NUL) { - strncat(tbuf, "; ", tbuf_len); - strncat(tbuf, mesg2, tbuf_len); + xstrlcat(tbuf, "; ", tbuf_len - 1); + xstrlcat(tbuf, mesg2, tbuf_len - 1); } EMSG(tbuf); retval = 2; } else { if (!autocmd_busy) { msg_start(); - msg_puts_attr((char_u *) tbuf, hl_attr(HLF_E) + MSG_HIST); + msg_puts_attr(tbuf, hl_attr(HLF_E) + MSG_HIST); if (*mesg2 != NUL) { - msg_puts_attr((char_u *)mesg2, - hl_attr(HLF_W) + MSG_HIST); + msg_puts_attr(mesg2, hl_attr(HLF_W) + MSG_HIST); } msg_clr_eos(); (void)msg_end(); @@ -5031,11 +5026,11 @@ buf_check_timestamp ( } } - /* Trigger FileChangedShell when the file was changed in any way. */ - if (buf_valid(buf) && retval != 0) - (void)apply_autocmds(EVENT_FILECHANGEDSHELLPOST, - buf->b_fname, buf->b_fname, FALSE, buf); - + // Trigger FileChangedShell when the file was changed in any way. + if (bufref_valid(&bufref) && retval != 0) { + (void)apply_autocmds(EVENT_FILECHANGEDSHELLPOST, buf->b_fname, buf->b_fname, + false, buf); + } return retval; } @@ -5052,6 +5047,7 @@ void buf_reload(buf_T *buf, int orig_mode) linenr_T old_topline; int old_ro = buf->b_p_ro; buf_T *savebuf; + bufref_T bufref; int saved = OK; aco_save_T aco; int flags = READ_NEW; @@ -5087,6 +5083,7 @@ void buf_reload(buf_T *buf, int orig_mode) } else { // Allocate a buffer without putting it in the buffer list. savebuf = buflist_new(NULL, NULL, (linenr_T)1, BLN_DUMMY); + set_bufref(&bufref, savebuf); if (savebuf != NULL && buf == curbuf) { /* Open the memline. */ curbuf = savebuf; @@ -5104,19 +5101,21 @@ void buf_reload(buf_T *buf, int orig_mode) } if (saved == OK) { - curbuf->b_flags |= BF_CHECK_RO; /* check for RO again */ - keep_filetype = TRUE; /* don't detect 'filetype' */ - if (readfile(buf->b_ffname, buf->b_fname, (linenr_T)0, - (linenr_T)0, - (linenr_T)MAXLNUM, &ea, flags) == FAIL) { - if (!aborting()) + curbuf->b_flags |= BF_CHECK_RO; // check for RO again + keep_filetype = true; // don't detect 'filetype' + if (readfile(buf->b_ffname, buf->b_fname, (linenr_T)0, (linenr_T)0, + (linenr_T)MAXLNUM, &ea, flags) != OK) { + if (!aborting()) { EMSG2(_("E321: Could not reload \"%s\""), buf->b_fname); - if (savebuf != NULL && buf_valid(savebuf) && buf == curbuf) { - /* Put the text back from the save buffer. First - * delete any lines that readfile() added. */ - while (!bufempty()) - if (ml_delete(buf->b_ml.ml_line_count, FALSE) == FAIL) + } + if (savebuf != NULL && bufref_valid(&bufref) && buf == curbuf) { + // Put the text back from the save buffer. First + // delete any lines that readfile() added. + while (!bufempty()) { + if (ml_delete(buf->b_ml.ml_line_count, false) == FAIL) { break; + } + } (void)move_lines(savebuf, buf); } } else if (buf == curbuf) { /* "buf" still valid */ @@ -5133,8 +5132,9 @@ void buf_reload(buf_T *buf, int orig_mode) } xfree(ea.cmd); - if (savebuf != NULL && buf_valid(savebuf)) - wipe_buffer(savebuf, FALSE); + if (savebuf != NULL && bufref_valid(&bufref)) { + wipe_buffer(savebuf, false); + } /* Invalidate diff info if necessary. */ diff_invalidate(curbuf); @@ -5197,7 +5197,7 @@ void forward_slash(char_u *fname) { char_u *p; - if (path_with_url(fname)) { + if (path_with_url((const char *)fname)) { return; } for (p = fname; *p != NUL; p++) { @@ -5258,7 +5258,7 @@ static void vim_maketempdir(void) /// Delete "name" and everything in it, recursively. /// @param name The path which should be deleted. /// @return 0 for success, -1 if some file was not deleted. -int delete_recursive(char_u *name) +int delete_recursive(const char *name) { int result = 0; @@ -5272,7 +5272,7 @@ int delete_recursive(char_u *name) EW_DIR | EW_FILE | EW_SILENT | EW_ALLLINKS | EW_DODOT | EW_EMPTYOK) == OK) { for (int i = 0; i < file_count; i++) { - if (delete_recursive(files[i]) != 0) { + if (delete_recursive((const char *)files[i]) != 0) { result = -1; } } @@ -5282,9 +5282,9 @@ int delete_recursive(char_u *name) } xfree(exp); - os_rmdir((char *)name); + os_rmdir(name); } else { - result = os_remove((char *)name) == 0 ? 0 : -1; + result = os_remove(name) == 0 ? 0 : -1; } return result; @@ -5296,7 +5296,7 @@ void vim_deltempdir(void) if (vim_tempdir != NULL) { // remove the trailing path separator path_tail(vim_tempdir)[-1] = NUL; - delete_recursive(vim_tempdir); + delete_recursive((const char *)vim_tempdir); xfree(vim_tempdir); vim_tempdir = NULL; } @@ -5367,11 +5367,9 @@ char_u *vim_tempname(void) static AutoPatCmd *active_apc_list = NULL; /* stack of active autocommands */ -/* - * augroups stores a list of autocmd group names. - */ -static garray_T augroups = {0, 0, sizeof(char_u *), 10, NULL}; -#define AUGROUP_NAME(i) (((char_u **)augroups.ga_data)[i]) +/// List of autocmd group names +static garray_T augroups = { 0, 0, sizeof(char_u *), 10, NULL }; +#define AUGROUP_NAME(i) (((char **)augroups.ga_data)[i]) /* * The ID of the current group. Group 0 is the default one. @@ -5386,6 +5384,18 @@ static event_T last_event; static int last_group; static int autocmd_blocked = 0; /* block all autocmds */ +// use get_deleted_augroup() to get this +static const char *deleted_augroup = NULL; + +static inline const char *get_deleted_augroup(void) + FUNC_ATTR_ALWAYS_INLINE +{ + if (deleted_augroup == NULL) { + deleted_augroup = _("--Deleted--"); + } + return deleted_augroup; +} + /* * Show the autocommands for one AutoPat. */ @@ -5405,11 +5415,12 @@ static void show_autocmd(AutoPat *ap, event_T event) return; if (event != last_event || ap->group != last_group) { if (ap->group != AUGROUP_DEFAULT) { - if (AUGROUP_NAME(ap->group) == NULL) - msg_puts_attr((char_u *)_("--Deleted--"), hl_attr(HLF_E)); - else + if (AUGROUP_NAME(ap->group) == NULL) { + msg_puts_attr(get_deleted_augroup(), hl_attr(HLF_E)); + } else { msg_puts_attr(AUGROUP_NAME(ap->group), hl_attr(HLF_T)); - msg_puts((char_u *)" "); + } + msg_puts(" "); } msg_puts_attr(event_nr2name(event), hl_attr(HLF_T)); last_event = event; @@ -5538,7 +5549,7 @@ void aubuflocal_remove(buf_T *buf) if (p_verbose >= 6) { verbose_enter(); smsg(_("auto-removing autocommand: %s <buffer=%d>"), - event_nr2name(event), buf->b_fnum); + event_nr2name(event), buf->b_fnum); verbose_leave(); } } @@ -5561,9 +5572,10 @@ static int au_new_group(char_u *name) ga_grow(&augroups, 1); } - AUGROUP_NAME(i) = vim_strsave(name); - if (i == augroups.ga_len) - ++augroups.ga_len; + AUGROUP_NAME(i) = xstrdup((char *)name); + if (i == augroups.ga_len) { + augroups.ga_len++; + } } return i; @@ -5574,11 +5586,33 @@ static void au_del_group(char_u *name) int i; i = au_find_group(name); - if (i == AUGROUP_ERROR) /* the group doesn't exist */ + if (i == AUGROUP_ERROR) { // the group doesn't exist EMSG2(_("E367: No such group: \"%s\""), name); - else { + } else if (i == current_augroup) { + EMSG(_("E936: Cannot delete the current group")); + } else { + event_T event; + AutoPat *ap; + int in_use = false; + + for (event = (event_T)0; (int)event < (int)NUM_EVENTS; + event = (event_T)((int)event + 1)) { + for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next) { + if (ap->group == i && ap->pat != NULL) { + give_warning((char_u *) + _("W19: Deleting augroup that is still in use"), true); + in_use = true; + event = NUM_EVENTS; + break; + } + } + } xfree(AUGROUP_NAME(i)); - AUGROUP_NAME(i) = NULL; + if (in_use) { + AUGROUP_NAME(i) = (char *)get_deleted_augroup(); + } else { + AUGROUP_NAME(i) = NULL; + } } } @@ -5590,8 +5624,9 @@ static void au_del_group(char_u *name) static int au_find_group(const char_u *name) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT { - for (int i = 0; i < augroups.ga_len; ++i) { - if (AUGROUP_NAME(i) != NULL && STRCMP(AUGROUP_NAME(i), name) == 0) { + for (int i = 0; i < augroups.ga_len; i++) { + if (AUGROUP_NAME(i) != NULL && AUGROUP_NAME(i) != get_deleted_augroup() + && STRCMP(AUGROUP_NAME(i), name) == 0) { return i; } } @@ -5628,7 +5663,7 @@ void do_augroup(char_u *arg, int del_group) for (int i = 0; i < augroups.ga_len; ++i) { if (AUGROUP_NAME(i) != NULL) { msg_puts(AUGROUP_NAME(i)); - msg_puts((char_u *)" "); + msg_puts(" "); } } msg_clr_eos(); @@ -5640,11 +5675,18 @@ void do_augroup(char_u *arg, int del_group) void free_all_autocmds(void) { for (current_augroup = -1; current_augroup < augroups.ga_len; - ++current_augroup) - do_autocmd((char_u *)"", TRUE); - ga_clear_strings(&augroups); -} + current_augroup++) { + do_autocmd((char_u *)"", true); + } + for (int i = 0; i < augroups.ga_len; i++) { + char *const s = ((char **)(augroups.ga_data))[i]; + if ((const char *)s != get_deleted_augroup()) { + xfree(s); + } + } + ga_clear(&augroups); +} #endif /* @@ -5652,13 +5694,13 @@ void free_all_autocmds(void) * Return NUM_EVENTS if the event name was not found. * Return a pointer to the next event name in "end". */ -static event_T event_name2nr(char_u *start, char_u **end) +static event_T event_name2nr(const char_u *start, char_u **end) { - char_u *p; + const char_u *p; int i; int len; - // the event name ends with end of line, '|', a blank or a comma */ + // the event name ends with end of line, '|', a blank or a comma for (p = start; *p && !ascii_iswhite(*p) && *p != ',' && *p != '|'; p++) { } for (i = 0; event_names[i].name != NULL; i++) { @@ -5667,25 +5709,32 @@ static event_T event_name2nr(char_u *start, char_u **end) break; } } - if (*p == ',') - ++p; - *end = p; - if (event_names[i].name == NULL) + if (*p == ',') { + p++; + } + *end = (char_u *)p; + if (event_names[i].name == NULL) { return NUM_EVENTS; + } return event_names[i].event; } -/* - * Return the name for event "event". - */ -static char_u *event_nr2name(event_T event) +/// Return the name for event +/// +/// @param[in] event Event to return name for. +/// +/// @return Event name, static string. Returns "Unknown" for unknown events. +static const char *event_nr2name(event_T event) + FUNC_ATTR_NONNULL_RET FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_CONST { int i; - for (i = 0; event_names[i].name != NULL; ++i) - if (event_names[i].event == event) - return (char_u *)event_names[i].name; - return (char_u *)"Unknown"; + for (i = 0; event_names[i].name != NULL; i++) { + if (event_names[i].event == event) { + return event_names[i].name; + } + } + return "Unknown"; } /* @@ -6237,6 +6286,7 @@ void ex_doautoall(exarg_T *eap) aco_save_T aco; char_u *arg = eap->arg; int call_do_modelines = check_nomodeline(&arg); + bufref_T bufref; /* * This is a bit tricky: For some commands curwin->w_buffer needs to be @@ -6249,8 +6299,9 @@ void ex_doautoall(exarg_T *eap) if (buf->b_ml.ml_mfp == NULL) { continue; } - /* find a window for this buffer and save some values */ + // Find a window for this buffer and save some values. aucmd_prepbuf(&aco, buf); + set_bufref(&bufref, buf); bool did_aucmd; // execute the autocommands for this buffer @@ -6266,9 +6317,10 @@ void ex_doautoall(exarg_T *eap) /* restore the current window */ aucmd_restbuf(&aco); - /* stop if there is some error or buffer was deleted */ - if (retval == FAIL || !buf_valid(buf)) + // Stop if there is some error or buffer was deleted. + if (retval == FAIL || !bufref_valid(&bufref)) { break; + } } check_cursor(); /* just in case lines got deleted */ @@ -6375,7 +6427,7 @@ aucmd_prepbuf ( } curbuf = buf; aco->new_curwin = curwin; - aco->new_curbuf = curbuf; + set_bufref(&aco->new_curbuf, curbuf); } /// Cleanup after executing autocommands for a (hidden) buffer. @@ -6409,6 +6461,12 @@ win_found: win_remove(curwin, NULL); aucmd_win_used = false; last_status(false); // may need to remove last status line + + if (!valid_tabpage_win(curtab)) { + // no valid window in current tabpage + close_tabpage(curtab); + } + restore_snapshot(SNAP_AUCMD_IDX, false); (void)win_comp_pos(); // recompute window positions unblock_autocmds(); @@ -6438,14 +6496,14 @@ win_found: // Restore the buffer which was previously edited by curwin, if it was // changed, we are still the same window and the buffer is valid. if (curwin == aco->new_curwin - && curbuf != aco->new_curbuf - && buf_valid(aco->new_curbuf) - && aco->new_curbuf->b_ml.ml_mfp != NULL) { + && curbuf != aco->new_curbuf.br_buf + && bufref_valid(&aco->new_curbuf) + && aco->new_curbuf.br_buf->b_ml.ml_mfp != NULL) { if (curwin->w_s == &curbuf->b_s) { - curwin->w_s = &aco->new_curbuf->b_s; + curwin->w_s = &aco->new_curbuf.br_buf->b_s; } curbuf->b_nwindows--; - curbuf = aco->new_curbuf; + curbuf = aco->new_curbuf.br_buf; curwin->w_buffer = curbuf; curbuf->b_nwindows++; } @@ -6715,8 +6773,9 @@ static bool apply_autocmds_group(event_T event, char_u *fname, char_u *fname_io, fname = vim_strsave(fname); /* make a copy, so we can change it */ } else { sfname = vim_strsave(fname); - // don't try expanding the following events + // Don't try expanding the following events. if (event == EVENT_COLORSCHEME + || event == EVENT_DIRCHANGED || event == EVENT_FILETYPE || event == EVENT_FUNCUNDEFINED || event == EVENT_OPTIONSET @@ -6725,10 +6784,11 @@ static bool apply_autocmds_group(event_T event, char_u *fname, char_u *fname_io, || event == EVENT_REMOTEREPLY || event == EVENT_SPELLFILEMISSING || event == EVENT_SYNTAX - || event == EVENT_TABCLOSED) + || event == EVENT_TABCLOSED) { fname = vim_strsave(fname); - else - fname = (char_u *)FullName_save((char *)fname, FALSE); + } else { + fname = (char_u *)FullName_save((char *)fname, false); + } } if (fname == NULL) { /* out of memory */ xfree(sfname); @@ -6810,8 +6870,8 @@ static bool apply_autocmds_group(event_T event, char_u *fname, char_u *fname_io, patcmd.next = active_apc_list; active_apc_list = &patcmd; - /* set v:cmdarg (only when there is a matching pattern) */ - save_cmdbang = get_vim_var_nr(VV_CMDBANG); + // set v:cmdarg (only when there is a matching pattern) + save_cmdbang = (long)get_vim_var_nr(VV_CMDBANG); if (eap != NULL) { save_cmdarg = set_cmdarg(eap, NULL); set_vim_var_nr(VV_CMDBANG, (long)eap->forceit); @@ -6945,7 +7005,6 @@ auto_next_pat ( { AutoPat *ap; AutoCmd *cp; - char_u *name; char *s; xfree(sourcing_name); @@ -6964,11 +7023,13 @@ auto_next_pat ( ? match_file_pat(NULL, &ap->reg_prog, apc->fname, apc->sfname, apc->tail, ap->allow_dirs) : ap->buflocal_nr == apc->arg_bufnr) { - name = event_nr2name(apc->event); + const char *const name = event_nr2name(apc->event); s = _("%s Auto commands for \"%s\""); - sourcing_name = xmalloc(STRLEN(s) + STRLEN(name) + ap->patlen + 1); - sprintf((char *)sourcing_name, s, - (char *)name, (char *)ap->pat); + const size_t sourcing_name_len = (STRLEN(s) + strlen(name) + ap->patlen + + 1); + sourcing_name = xmalloc(sourcing_name_len); + snprintf((char *)sourcing_name, sourcing_name_len, s, name, + (char *)ap->pat); if (p_verbose >= 8) { verbose_enter(); smsg(_("Executing %s"), sourcing_name); @@ -7034,7 +7095,7 @@ char_u *getnextac(int c, void *cookie, int indent) if (p_verbose >= 9) { verbose_enter_scroll(); smsg(_("autocommand %s"), ac->cmd); - msg_puts((char_u *)"\n"); /* don't overwrite this either */ + msg_puts("\n"); // don't overwrite this either verbose_leave_scroll(); } retval = vim_strsave(ac->cmd); @@ -7100,13 +7161,17 @@ bool has_autocmd(event_T event, char_u *sfname, buf_T *buf) */ char_u *get_augroup_name(expand_T *xp, int idx) { - if (idx == augroups.ga_len) /* add "END" add the end */ + if (idx == augroups.ga_len) { // add "END" add the end return (char_u *)"END"; - if (idx >= augroups.ga_len) /* end of list */ + } + if (idx >= augroups.ga_len) { // end of list return NULL; - if (AUGROUP_NAME(idx) == NULL) /* skip deleted entries */ + } + if (AUGROUP_NAME(idx) == NULL || AUGROUP_NAME(idx) == get_deleted_augroup()) { + // skip deleted entries return (char_u *)""; - return AUGROUP_NAME(idx); /* return a name */ + } + return (char_u *)AUGROUP_NAME(idx); } static int include_groups = FALSE; @@ -7163,21 +7228,27 @@ set_context_in_autocmd ( */ char_u *get_event_name(expand_T *xp, int idx) { - if (idx < augroups.ga_len) { /* First list group names, if wanted */ - if (!include_groups || AUGROUP_NAME(idx) == NULL) - return (char_u *)""; /* skip deleted entries */ - return AUGROUP_NAME(idx); /* return a name */ + if (idx < augroups.ga_len) { // First list group names, if wanted + if (!include_groups || AUGROUP_NAME(idx) == NULL + || AUGROUP_NAME(idx) == get_deleted_augroup()) { + return (char_u *)""; // skip deleted entries + } + return (char_u *)AUGROUP_NAME(idx); } return (char_u *)event_names[idx - augroups.ga_len].name; } -/// Return true if autocmd "event" is supported. -bool autocmd_supported(char_u *event) +/// Check whether given autocommand is supported +/// +/// @param[in] event Event to check. +/// +/// @return True if it is, false otherwise. +bool autocmd_supported(const char *const event) + FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT { char_u *p; - - return event_name2nr(event, &p) != NUM_EVENTS; + return event_name2nr((const char_u *)event, &p) != NUM_EVENTS; } /// Return true if an autocommand is defined for a group, event and @@ -7192,26 +7263,24 @@ bool autocmd_supported(char_u *event) /// exists("#Event#pat") /// /// @param arg autocommand string -bool au_exists(const char_u *arg) FUNC_ATTR_WARN_UNUSED_RESULT +bool au_exists(const char *const arg) FUNC_ATTR_WARN_UNUSED_RESULT { - char_u *arg_save; - char_u *pattern = NULL; - char_u *event_name; - char_u *p; event_T event; AutoPat *ap; buf_T *buflocal_buf = NULL; int group; bool retval = false; - /* Make a copy so that we can change the '#' chars to a NUL. */ - arg_save = vim_strsave(arg); - p = vim_strchr(arg_save, '#'); - if (p != NULL) + // Make a copy so that we can change the '#' chars to a NUL. + char *const arg_save = xstrdup(arg); + char *p = strchr(arg_save, '#'); + if (p != NULL) { *p++ = NUL; + } - /* First, look for an autocmd group name */ - group = au_find_group(arg_save); + // First, look for an autocmd group name. + group = au_find_group((char_u *)arg_save); + char *event_name; if (group == AUGROUP_ERROR) { /* Didn't match a group name, assume the first argument is an event. */ group = AUGROUP_ALL; @@ -7223,17 +7292,18 @@ bool au_exists(const char_u *arg) FUNC_ATTR_WARN_UNUSED_RESULT goto theend; } - /* Must be "Group#Event" or "Group#Event#pat". */ + // Must be "Group#Event" or "Group#Event#pat". event_name = p; - p = vim_strchr(event_name, '#'); - if (p != NULL) - *p++ = NUL; /* "Group#Event#pat" */ + p = strchr(event_name, '#'); + if (p != NULL) { + *p++ = NUL; // "Group#Event#pat" + } } - pattern = p; /* "pattern" is NULL when there is no pattern */ + char *pattern = p; // "pattern" is NULL when there is no pattern. - /* find the index (enum) for the event name */ - event = event_name2nr(event_name, &p); + // Find the index (enum) for the event name. + event = event_name2nr((char_u *)event_name, (char_u **)&p); /* return FALSE if the event name is not recognized */ if (event == NUM_EVENTS) @@ -7259,7 +7329,7 @@ bool au_exists(const char_u *arg) FUNC_ATTR_WARN_UNUSED_RESULT && (group == AUGROUP_ALL || ap->group == group) && (pattern == NULL || (buflocal_buf == NULL - ? fnamecmp(ap->pat, pattern) == 0 + ? fnamecmp(ap->pat, (char_u *)pattern) == 0 : ap->buflocal_nr == buflocal_buf->b_fnum))) { retval = true; break; diff --git a/src/nvim/fileio.h b/src/nvim/fileio.h index ceb101167d..8db4b89806 100644 --- a/src/nvim/fileio.h +++ b/src/nvim/fileio.h @@ -4,13 +4,14 @@ #include "nvim/buffer_defs.h" #include "nvim/os/os.h" -/* Values for readfile() flags */ -#define READ_NEW 0x01 /* read a file into a new buffer */ -#define READ_FILTER 0x02 /* read filter output */ -#define READ_STDIN 0x04 /* read from stdin */ -#define READ_BUFFER 0x08 /* read from curbuf (converting stdin) */ -#define READ_DUMMY 0x10 /* reading into a dummy buffer */ -#define READ_KEEP_UNDO 0x20 /* keep undo info*/ +// Values for readfile() flags +#define READ_NEW 0x01 // read a file into a new buffer +#define READ_FILTER 0x02 // read filter output +#define READ_STDIN 0x04 // read from stdin +#define READ_BUFFER 0x08 // read from curbuf (converting stdin) +#define READ_DUMMY 0x10 // reading into a dummy buffer +#define READ_KEEP_UNDO 0x20 // keep undo info +#define READ_FIFO 0x40 // read from fifo or socket #define READ_STRING(x, y) (char_u *)read_string((x), (size_t)(y)) @@ -19,12 +20,12 @@ * not the current buffer. */ typedef struct { - buf_T *save_curbuf; /* saved curbuf */ - int use_aucmd_win; /* using aucmd_win */ - win_T *save_curwin; /* saved curwin */ - win_T *new_curwin; /* new curwin */ - buf_T *new_curbuf; /* new curbuf */ - char_u *globaldir; /* saved value of globaldir */ + buf_T *save_curbuf; ///< saved curbuf + int use_aucmd_win; ///< using aucmd_win + win_T *save_curwin; ///< saved curwin + win_T *new_curwin; ///< new curwin + bufref_T new_curbuf; ///< new curbuf + char_u *globaldir; ///< saved value of globaldir } aco_save_T; #ifdef INCLUDE_GENERATED_DECLARATIONS diff --git a/src/nvim/fold.c b/src/nvim/fold.c index dcd32acfb7..db88791967 100644 --- a/src/nvim/fold.c +++ b/src/nvim/fold.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + // vim: set fdm=marker fdl=1 fdc=3 /* @@ -29,6 +32,7 @@ #include "nvim/strings.h" #include "nvim/syntax.h" #include "nvim/undo.h" +#include "nvim/ops.h" /* local declarations. {{{1 */ /* typedef fold_T {{{2 */ @@ -1438,13 +1442,16 @@ static void foldMarkAdjustRecurse(garray_T *gap, linenr_T line1, linenr_T line2, } else { /* 5. fold is below line1 and contains line2; need to * correct nested folds too */ - foldMarkAdjustRecurse(&fp->fd_nested, line1 - fp->fd_top, - line2 - fp->fd_top, amount, - amount_after + (fp->fd_top - top)); if (amount == MAXLNUM) { + foldMarkAdjustRecurse(&fp->fd_nested, line1 - fp->fd_top, + line2 - fp->fd_top, amount, + amount_after + (fp->fd_top - top)); fp->fd_len -= line2 - fp->fd_top + 1; fp->fd_top = line1; } else { + foldMarkAdjustRecurse(&fp->fd_nested, line1 - fp->fd_top, + line2 - fp->fd_top, amount, + amount_after - amount); fp->fd_len += amount_after - amount; fp->fd_top += amount; } @@ -1590,29 +1597,32 @@ static void foldCreateMarkers(linenr_T start, linenr_T end) /* * Add "marker[markerlen]" in 'commentstring' to line "lnum". */ -static void foldAddMarker(linenr_T lnum, char_u *marker, size_t markerlen) +static void foldAddMarker(linenr_T lnum, const char_u *marker, size_t markerlen) { char_u *cms = curbuf->b_p_cms; char_u *line; char_u *newline; char_u *p = (char_u *)strstr((char *)curbuf->b_p_cms, "%s"); + bool line_is_comment = false; - /* Allocate a new line: old-line + 'cms'-start + marker + 'cms'-end */ + // Allocate a new line: old-line + 'cms'-start + marker + 'cms'-end line = ml_get(lnum); size_t line_len = STRLEN(line); if (u_save(lnum - 1, lnum + 1) == OK) { + // Check if the line ends with an unclosed comment + skip_comment(line, false, false, &line_is_comment); newline = xmalloc(line_len + markerlen + STRLEN(cms) + 1); STRCPY(newline, line); - if (p == NULL) + // Append the marker to the end of the line + if (p == NULL || line_is_comment) { STRLCPY(newline + line_len, marker, markerlen + 1); - else { + } else { STRCPY(newline + line_len, cms); - STRNCPY(newline + line_len + (p - cms), marker, markerlen); + memcpy(newline + line_len + (p - cms), marker, markerlen); STRCPY(newline + line_len + (p - cms) + markerlen, p + 2); } - - ml_replace(lnum, newline, FALSE); + ml_replace(lnum, newline, false); } } @@ -1673,7 +1683,8 @@ static void foldDelMarker(linenr_T lnum, char_u *marker, size_t markerlen) if (u_save(lnum - 1, lnum + 1) == OK) { /* Make new line: text-before-marker + text-after-marker */ newline = xmalloc(STRLEN(line) - len + 1); - STRNCPY(newline, line, p - line); + assert(p >= line); + memcpy(newline, line, (size_t)(p - line)); STRCPY(newline + (p - line), p + len); ml_replace(lnum, newline, FALSE); } @@ -1681,12 +1692,10 @@ static void foldDelMarker(linenr_T lnum, char_u *marker, size_t markerlen) } } -/* get_foldtext() {{{2 */ -/* - * Return the text for a closed fold at line "lnum", with last line "lnume". - * When 'foldtext' isn't set puts the result in "buf[51]". Otherwise the - * result is in allocated memory. - */ +// get_foldtext() {{{2 +/// Return the text for a closed fold at line "lnum", with last line "lnume". +/// When 'foldtext' isn't set puts the result in "buf[FOLD_TEXT_LEN]". +/// Otherwise the result is in allocated memory. char_u *get_foldtext(win_T *wp, linenr_T lnum, linenr_T lnume, foldinfo_T *foldinfo, char_u *buf) FUNC_ATTR_NONNULL_ARG(1) @@ -1773,8 +1782,12 @@ char_u *get_foldtext(win_T *wp, linenr_T lnum, linenr_T lnume, } } if (text == NULL) { - sprintf((char *)buf, _("+--%3ld lines folded "), - (long)(lnume - lnum + 1)); + unsigned long count = (unsigned long)(lnume - lnum + 1); + + vim_snprintf((char *)buf, FOLD_TEXT_LEN, + ngettext("+--%3ld line folded", + "+--%3ld lines folded ", count), + count); text = buf; } return text; @@ -2224,32 +2237,51 @@ static linenr_T foldUpdateIEMSRecurse(garray_T *gap, int level, * before where we started looking, extend it. If it * starts at another line, update nested folds to keep * their position, compensating for the new fd_top. */ - if (fp->fd_top >= startlnum && fp->fd_top != firstlnum) { - if (fp->fd_top > firstlnum) - /* like lines are inserted */ + if (fp->fd_top == firstlnum) { + // We have found a fold beginning exactly where we want one. + } else if (fp->fd_top >= startlnum) { + if (fp->fd_top > firstlnum) { + // We will move the start of this fold up, hence we move all + // nested folds (with relative line numbers) down. foldMarkAdjustRecurse(&fp->fd_nested, - (linenr_T)0, (linenr_T)MAXLNUM, - (long)(fp->fd_top - firstlnum), 0L); - else - /* like lines are deleted */ + (linenr_T)0, (linenr_T)MAXLNUM, + (long)(fp->fd_top - firstlnum), 0L); + } else { + // Will move fold down, move nested folds relatively up. foldMarkAdjustRecurse(&fp->fd_nested, - (linenr_T)0, - (long)(firstlnum - fp->fd_top - 1), - (linenr_T)MAXLNUM, - (long)(fp->fd_top - firstlnum)); + (linenr_T)0, + (long)(firstlnum - fp->fd_top - 1), + (linenr_T)MAXLNUM, + (long)(fp->fd_top - firstlnum)); + } fp->fd_len += fp->fd_top - firstlnum; fp->fd_top = firstlnum; - fold_changed = TRUE; - } else if (flp->start != 0 && lvl == level - && fp->fd_top != firstlnum) { - /* Existing fold that includes startlnum must stop - * if we find the start of a new fold at the same - * level. Split it. Delete contained folds at - * this point to split them too. */ - foldRemove(&fp->fd_nested, flp->lnum - fp->fd_top, - flp->lnum - fp->fd_top); + fold_changed = true; + } else if ((flp->start != 0 && lvl == level) + || (firstlnum != startlnum)) { + // Before there was a fold spanning from above startlnum to below + // firstlnum. This fold is valid above startlnum (because we are + // not updating that range), but there is now a break in it. + // If the break is because we are now forced to start a new fold + // at the level "level" at line fline->lnum, then we need to + // split the fold at fline->lnum. + // If the break is because the range [startlnum, firstlnum) is + // now at a lower indent than "level", we need to split the fold + // in this range. + // Any splits have to be done recursively. + linenr_T breakstart; + linenr_T breakend; + if (firstlnum != startlnum) { + breakstart = startlnum; + breakend = firstlnum; + } else { + breakstart = flp->lnum; + breakend = flp->lnum; + } + foldRemove(&fp->fd_nested, breakstart - fp->fd_top, + breakend - fp->fd_top); i = (int)(fp - (fold_T *)gap->ga_data); - foldSplit(gap, i, flp->lnum, flp->lnum - 1); + foldSplit(gap, i, breakstart, breakend - 1); fp = (fold_T *)gap->ga_data + i + 1; /* If using the "marker" or "syntax" method, we * need to continue until the end of the fold is @@ -2259,6 +2291,16 @@ static linenr_T foldUpdateIEMSRecurse(garray_T *gap, int level, || getlevel == foldlevelSyntax) finish = TRUE; } + if (fp->fd_top == startlnum && concat) { + i = (int)(fp - (fold_T *)gap->ga_data); + if (i != 0) { + fp2 = fp - 1; + if (fp2->fd_top + fp2->fd_len == fp->fd_top) { + foldMerge(fp2, gap, fp); + fp = fp2; + } + } + } break; } if (fp->fd_top >= startlnum) { @@ -2499,6 +2541,8 @@ static void foldSplit(garray_T *gap, int i, linenr_T top, linenr_T bot) fp = (fold_T *)gap->ga_data + i; fp[1].fd_top = bot + 1; + // check for wrap around (MAXLNUM, and 32bit) + assert(fp[1].fd_top > bot); fp[1].fd_len = fp->fd_len - (fp[1].fd_top - fp->fd_top); fp[1].fd_flags = fp->fd_flags; fp[1].fd_small = MAYBE; @@ -2531,10 +2575,10 @@ static void foldSplit(garray_T *gap, int i, linenr_T top, linenr_T bot) * 1 2 3 * 1 2 3 * top 2 3 4 5 - * 2 3 4 5 - * bot 2 3 4 5 - * 3 5 6 - * 3 5 6 + * 2 3 4 5 + * bot 2 3 4 5 + * 3 5 6 + * 3 5 6 * * 1: not changed * 2: truncate to stop above "top" @@ -2547,34 +2591,35 @@ static void foldRemove(garray_T *gap, linenr_T top, linenr_T bot) { fold_T *fp = NULL; - if (bot < top) - return; /* nothing to do */ + if (bot < top) { + return; // nothing to do + } for (;; ) { - /* Find fold that includes top or a following one. */ + // Find fold that includes top or a following one. if (foldFind(gap, top, &fp) && fp->fd_top < top) { - /* 2: or 3: need to delete nested folds */ + // 2: or 3: need to delete nested folds foldRemove(&fp->fd_nested, top - fp->fd_top, bot - fp->fd_top); - if (fp->fd_top + fp->fd_len > bot + 1) { - /* 3: need to split it. */ + if (fp->fd_top + fp->fd_len - 1 > bot) { + // 3: need to split it. foldSplit(gap, (int)(fp - (fold_T *)gap->ga_data), top, bot); } else { - /* 2: truncate fold at "top". */ + // 2: truncate fold at "top". fp->fd_len = top - fp->fd_top; } - fold_changed = TRUE; + fold_changed = true; continue; } if (fp >= (fold_T *)(gap->ga_data) + gap->ga_len || fp->fd_top > bot) { - /* 6: Found a fold below bot, can stop looking. */ + // 6: Found a fold below bot, can stop looking. break; } if (fp->fd_top >= top) { - /* Found an entry below top. */ - fold_changed = TRUE; + // Found an entry below top. + fold_changed = true; if (fp->fd_top + fp->fd_len - 1 > bot) { - /* 5: Make fold that includes bot start below bot. */ + // 5: Make fold that includes bot start below bot. foldMarkAdjustRecurse(&fp->fd_nested, (linenr_T)0, (long)(bot - fp->fd_top), (linenr_T)MAXLNUM, (long)(fp->fd_top - bot - 1)); @@ -2583,11 +2628,162 @@ static void foldRemove(garray_T *gap, linenr_T top, linenr_T bot) break; } - /* 4: Delete completely contained fold. */ - deleteFoldEntry(gap, (int)(fp - (fold_T *)gap->ga_data), TRUE); + // 4: Delete completely contained fold. + deleteFoldEntry(gap, (int)(fp - (fold_T *)gap->ga_data), true); + } + } +} + +// foldMoveRange() {{{2 +static void reverse_fold_order(garray_T *gap, size_t start, size_t end) +{ + for (; start < end; start++, end--) { + fold_T *left = (fold_T *)gap->ga_data + start; + fold_T *right = (fold_T *)gap->ga_data + end; + fold_T tmp = *left; + *left = *right; + *right = tmp; + } +} + +// Move folds within the inclusive range "line1" to "line2" to after "dest" +// require "line1" <= "line2" <= "dest" +// +// There are the following situations for the first fold at or below line1 - 1. +// 1 2 3 4 +// 1 2 3 4 +// line1 2 3 4 +// 2 3 4 5 6 7 +// line2 3 4 5 6 7 +// 3 4 6 7 8 9 +// dest 4 7 8 9 +// 4 7 8 10 +// 4 7 8 10 +// +// In the following descriptions, "moved" means moving in the buffer, *and* in +// the fold array. +// Meanwhile, "shifted" just means moving in the buffer. +// 1. not changed +// 2. truncated above line1 +// 3. length reduced by line2 - line1, folds starting between the end of 3 and +// dest are truncated and shifted up +// 4. internal folds moved (from [line1, line2] to dest) +// 5. moved to dest. +// 6. truncated below line2 and moved. +// 7. length reduced by line2 - dest, folds starting between line2 and dest are +// removed, top is moved down by move_len. +// 8. truncated below dest and shifted up. +// 9. shifted up +// 10. not changed +static void truncate_fold(fold_T *fp, linenr_T end) +{ + // I want to stop *at here*, foldRemove() stops *above* top + end += 1; + foldRemove(&fp->fd_nested, end - fp->fd_top, MAXLNUM); + fp->fd_len = end - fp->fd_top; +} + +#define FOLD_END(fp) ((fp)->fd_top + (fp)->fd_len - 1) +#define VALID_FOLD(fp, gap) ((fp) < ((fold_T *)(gap)->ga_data + (gap)->ga_len)) +#define FOLD_INDEX(fp, gap) ((size_t)(fp - ((fold_T *)(gap)->ga_data))) +void foldMoveRange(garray_T *gap, const linenr_T line1, const linenr_T line2, + const linenr_T dest) +{ + fold_T *fp; + const linenr_T range_len = line2 - line1 + 1; + const linenr_T move_len = dest - line2; + const bool at_start = foldFind(gap, line1 - 1, &fp); + + if (at_start) { + if (FOLD_END(fp) > dest) { + // Case 4 -- don't have to change this fold, but have to move nested + // folds. + foldMoveRange(&fp->fd_nested, line1 - fp->fd_top, line2 - + fp->fd_top, dest - fp->fd_top); + return; + } else if (FOLD_END(fp) > line2) { + // Case 3 -- Remove nested folds between line1 and line2 & reduce the + // length of fold by "range_len". + // Folds after this one must be dealt with. + foldMarkAdjustRecurse(&fp->fd_nested, line1 - fp->fd_top, + line2 - fp->fd_top, MAXLNUM, -range_len); + fp->fd_len -= range_len; + } else { + // Case 2 -- truncate fold *above* line1. + // Folds after this one must be dealt with. + truncate_fold(fp, line1 - 1); + } + // Look at the next fold, and treat that one as if it were the first after + // "line1" (because now it is). + fp = fp + 1; + } + + if (!VALID_FOLD(fp, gap) || fp->fd_top > dest) { + // No folds after "line1" and before "dest" + // Case 10. + return; + } else if (fp->fd_top > line2) { + for (; VALID_FOLD(fp, gap) && FOLD_END(fp) <= dest; fp++) { + // Case 9. (for all case 9's) -- shift up. + fp->fd_top -= range_len; + } + if (VALID_FOLD(fp, gap) && fp->fd_top <= dest) { + // Case 8. -- ensure truncated at dest, shift up + truncate_fold(fp, dest); + fp->fd_top -= range_len; + } + return; + } else if (FOLD_END(fp) > dest) { + // Case 7 -- remove nested folds and shrink + foldMarkAdjustRecurse(&fp->fd_nested, line2 + 1 - fp->fd_top, + dest - fp->fd_top, MAXLNUM, -move_len); + fp->fd_len -= move_len; + fp->fd_top += move_len; + return; + } + + // Case 5 or 6: changes rely on whether there are folds between the end of + // this fold and "dest". + size_t move_start = FOLD_INDEX(fp, gap); + size_t move_end = 0, dest_index = 0; + for (; VALID_FOLD(fp, gap) && fp->fd_top <= dest; fp++) { + if (fp->fd_top <= line2) { + // 5, or 6 + if (FOLD_END(fp) > line2) { + // 6, truncate before moving + truncate_fold(fp, line2); + } + fp->fd_top += move_len; + continue; + } + + // Record index of the first fold after the moved range. + if (move_end == 0) { + move_end = FOLD_INDEX(fp, gap); + } + + if (FOLD_END(fp) > dest) { + truncate_fold(fp, dest); } + + fp->fd_top -= range_len; + } + dest_index = FOLD_INDEX(fp, gap); + + // All folds are now correct, but not necessarily in the correct order. + // We must swap folds in the range [move_end, dest_index) with those in the + // range [move_start, move_end). + if (move_end == 0) { + // There are no folds after those moved, so none were moved out of order. + return; } + reverse_fold_order(gap, move_start, dest_index - 1); + reverse_fold_order(gap, move_start, move_start + dest_index - move_end - 1); + reverse_fold_order(gap, move_start + dest_index - move_end, dest_index - 1); } +#undef FOLD_END +#undef VALID_FOLD +#undef FOLD_INDEX /* foldMerge() {{{2 */ /* @@ -2698,7 +2894,7 @@ static void foldlevelExpr(fline_T *flp) /* KeyTyped may be reset to 0 when calling a function which invokes * do_cmdline(). To make 'foldopen' work correctly restore KeyTyped. */ save_keytyped = KeyTyped; - n = eval_foldexpr(flp->wp->w_p_fde, &c); + n = (int)eval_foldexpr(flp->wp->w_p_fde, &c); KeyTyped = save_keytyped; switch (c) { diff --git a/src/nvim/fold.h b/src/nvim/fold.h index 2ff10c0e91..f35b328fb1 100644 --- a/src/nvim/fold.h +++ b/src/nvim/fold.h @@ -1,7 +1,12 @@ #ifndef NVIM_FOLD_H #define NVIM_FOLD_H +#include <stdio.h> + #include "nvim/pos.h" +#include "nvim/garray.h" +#include "nvim/types.h" +#include "nvim/buffer_defs.h" /* * Info used to pass info about a fold from the fold-detection code to the diff --git a/src/nvim/func_attr.h b/src/nvim/func_attr.h index d98fe5b22b..bd26205d6d 100644 --- a/src/nvim/func_attr.h +++ b/src/nvim/func_attr.h @@ -41,9 +41,7 @@ // $ gcc -E -dM - </dev/null // $ echo | clang -dM -E - -#ifndef NVIM_FUNC_ATTR_H -#define NVIM_FUNC_ATTR_H -#undef NVIM_FUNC_ATTR_H +#include "nvim/macros.h" #ifdef FUNC_ATTR_MALLOC # undef FUNC_ATTR_MALLOC @@ -93,11 +91,18 @@ # undef FUNC_ATTR_NONNULL_RET #endif +#ifdef FUNC_ATTR_NORETURN +# undef FUNC_ATTR_NORETURN +#endif + +#ifdef FUNC_ATTR_NO_SANITIZE_UNDEFINED +# undef FUNC_ATTR_NO_SANITIZE_UNDEFINED +#endif + #ifndef DID_REAL_ATTR # define DID_REAL_ATTR # ifdef __GNUC__ -// place defines for all gnulikes here, for now that's gcc, clang and -// intel. +// For all gnulikes: gcc, clang, intel. // place these after the argument list of the function declaration // (not definition), like so: @@ -111,27 +116,27 @@ # define REAL_FATTR_UNUSED __attribute__((unused)) # define REAL_FATTR_NONNULL_ALL __attribute__((nonnull)) # define REAL_FATTR_NONNULL_ARG(...) __attribute__((nonnull(__VA_ARGS__))) +# define REAL_FATTR_NORETURN __attribute__((noreturn)) + +# if NVIM_HAS_ATTRIBUTE(returns_nonnull) +# define REAL_FATTR_NONNULL_RET __attribute__((returns_nonnull)) +# endif -# ifdef __clang__ -// clang only -# elif defined(__INTEL_COMPILER) -// intel only -# else -# define GCC_VERSION \ - (__GNUC__ * 10000 + \ - __GNUC_MINOR__ * 100 + \ - __GNUC_PATCHLEVEL__) -// gcc only +# if NVIM_HAS_ATTRIBUTE(alloc_size) # define REAL_FATTR_ALLOC_SIZE(x) __attribute__((alloc_size(x))) # define REAL_FATTR_ALLOC_SIZE_PROD(x, y) __attribute__((alloc_size(x, y))) -# if GCC_VERSION >= 40900 -# define REAL_FATTR_NONNULL_RET __attribute__((returns_nonnull)) -# endif +# endif + +# if NVIM_HAS_ATTRIBUTE(no_sanitize_undefined) +# define REAL_FATTR_NO_SANITIZE_UNDEFINED \ + __attribute__((no_sanitize_undefined)) +# elif NVIM_HAS_ATTRIBUTE(no_sanitize) +# define REAL_FATTR_NO_SANITIZE_UNDEFINED \ + __attribute__((no_sanitize("undefined"))) # endif # endif -// define function attributes that haven't been defined for this specific -// compiler. +// Define attributes that are not defined for this compiler. # ifndef REAL_FATTR_MALLOC # define REAL_FATTR_MALLOC @@ -180,12 +185,22 @@ # ifndef REAL_FATTR_NONNULL_RET # define REAL_FATTR_NONNULL_RET # endif + +# ifndef REAL_FATTR_NORETURN +# define REAL_FATTR_NORETURN +# endif + +# ifndef REAL_FATTR_NO_SANITIZE_UNDEFINED +# define REAL_FATTR_NO_SANITIZE_UNDEFINED +# endif #endif #ifdef DEFINE_FUNC_ATTRIBUTES # define FUNC_API_ASYNC # define FUNC_API_NOEXPORT -# define FUNC_API_NOEVAL +# define FUNC_API_REMOTE_ONLY +# define FUNC_API_SINCE(X) +# define FUNC_API_DEPRECATED_SINCE(X) # define FUNC_ATTR_MALLOC REAL_FATTR_MALLOC # define FUNC_ATTR_ALLOC_SIZE(x) REAL_FATTR_ALLOC_SIZE(x) # define FUNC_ATTR_ALLOC_SIZE_PROD(x, y) REAL_FATTR_ALLOC_SIZE_PROD(x, y) @@ -198,6 +213,8 @@ # define FUNC_ATTR_NONNULL_ALL REAL_FATTR_NONNULL_ALL # define FUNC_ATTR_NONNULL_ARG(...) REAL_FATTR_NONNULL_ARG(__VA_ARGS__) # define FUNC_ATTR_NONNULL_RET REAL_FATTR_NONNULL_RET +# define FUNC_ATTR_NORETURN REAL_FATTR_NORETURN +# define FUNC_ATTR_NO_SANITIZE_UNDEFINED REAL_FATTR_NO_SANITIZE_UNDEFINED #elif !defined(DO_NOT_DEFINE_EMPTY_ATTRIBUTES) # define FUNC_ATTR_MALLOC # define FUNC_ATTR_ALLOC_SIZE(x) @@ -211,5 +228,6 @@ # define FUNC_ATTR_NONNULL_ALL # define FUNC_ATTR_NONNULL_ARG(...) # define FUNC_ATTR_NONNULL_RET +# define FUNC_ATTR_NORETURN +# define FUNC_ATTR_NO_SANITIZE_UNDEFINED #endif -#endif // NVIM_FUNC_ATTR_H diff --git a/src/nvim/garray.c b/src/nvim/garray.c index 9ed3b901ef..2d2af54c95 100644 --- a/src/nvim/garray.c +++ b/src/nvim/garray.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + /// @file garray.c /// /// Functions for handling growing arrays. diff --git a/src/nvim/garray.h b/src/nvim/garray.h index 5d7806bbfa..94e1b61671 100644 --- a/src/nvim/garray.h +++ b/src/nvim/garray.h @@ -37,7 +37,7 @@ typedef struct growarray { static inline void *ga_append_via_ptr(garray_T *gap, size_t item_size) { if ((int)item_size != gap->ga_itemsize) { - ELOG("wrong item size in garray(%d), should be %d", item_size); + WLOG("wrong item size (%d), should be %d", item_size, gap->ga_itemsize); } ga_grow(gap, 1); return ((char *)gap->ga_data) + (item_size * (size_t)gap->ga_len++); diff --git a/src/nvim/generators/c_grammar.lua b/src/nvim/generators/c_grammar.lua new file mode 100644 index 0000000000..d3047e1a9c --- /dev/null +++ b/src/nvim/generators/c_grammar.lua @@ -0,0 +1,50 @@ +lpeg = require('lpeg') + +-- lpeg grammar for building api metadata from a set of header files. It +-- ignores comments and preprocessor commands and parses a very small subset +-- of C prototypes with a limited set of types +local P, R, S = lpeg.P, lpeg.R, lpeg.S +local C, Ct, Cc, Cg = lpeg.C, lpeg.Ct, lpeg.Cc, lpeg.Cg + +local any = P(1) -- (consume one character) +local letter = R('az', 'AZ') + S('_$') +local num = R('09') +local alpha = letter + num +local nl = P('\r\n') + P('\n') +local not_nl = any - nl +local ws = S(' \t') + nl +local fill = ws ^ 0 +local c_comment = P('//') * (not_nl ^ 0) +local c_preproc = P('#') * (not_nl ^ 0) +local typed_container = + (P('ArrayOf(') + P('DictionaryOf(')) * ((any - P(')')) ^ 1) * P(')') +local c_id = ( + typed_container + + (letter * (alpha ^ 0)) +) +local c_void = P('void') +local c_param_type = ( + ((P('Error') * fill * P('*') * fill) * Cc('error')) + + (C(c_id) * (ws ^ 1)) + ) +local c_type = (C(c_void) * (ws ^ 1)) + c_param_type +local c_param = Ct(c_param_type * C(c_id)) +local c_param_list = c_param * (fill * (P(',') * fill * c_param) ^ 0) +local c_params = Ct(c_void + c_param_list) +local c_proto = Ct( + Cg(c_type, 'return_type') * Cg(c_id, 'name') * + fill * P('(') * fill * Cg(c_params, 'parameters') * fill * P(')') * + Cg(Cc(false), 'async') * + (fill * Cg((P('FUNC_API_SINCE(') * C(num ^ 1)) * P(')'), 'since') ^ -1) * + (fill * Cg((P('FUNC_API_DEPRECATED_SINCE(') * C(num ^ 1)) * P(')'), + 'deprecated_since') ^ -1) * + (fill * Cg((P('FUNC_API_ASYNC') * Cc(true)), 'async') ^ -1) * + (fill * Cg((P('FUNC_API_NOEXPORT') * Cc(true)), 'noexport') ^ -1) * + (fill * Cg((P('FUNC_API_REMOTE_ONLY') * Cc(true)), 'remote_only') ^ -1) * + (fill * Cg((P('FUNC_API_REMOTE_IMPL') * Cc(true)), 'remote_impl') ^ -1) * + (fill * Cg((P('FUNC_API_BRIDGE_IMPL') * Cc(true)), 'bridge_impl') ^ -1) * + fill * P(';') + ) + +local grammar = Ct((c_proto + c_comment + c_preproc + ws) ^ 1) +return {grammar=grammar, typed_container=typed_container} diff --git a/src/nvim/generators/dump_bin_array.lua b/src/nvim/generators/dump_bin_array.lua new file mode 100644 index 0000000000..bee5aba73f --- /dev/null +++ b/src/nvim/generators/dump_bin_array.lua @@ -0,0 +1,17 @@ +local function dump_bin_array(output, name, data) + output:write([[ + static const uint8_t ]]..name..[[[] = { +]]) + + for i = 1, #data do + output:write(string.byte(data, i)..', ') + if i % 10 == 0 then + output:write('\n ') + end + end + output:write([[ +}; +]]) +end + +return dump_bin_array diff --git a/scripts/gendispatch.lua b/src/nvim/generators/gen_api_dispatch.lua index 397ccc9aaf..b01321e713 100644 --- a/scripts/gendispatch.lua +++ b/src/nvim/generators/gen_api_dispatch.lua @@ -1,69 +1,40 @@ -lpeg = require('lpeg') mpack = require('mpack') --- lpeg grammar for building api metadata from a set of header files. It --- ignores comments and preprocessor commands and parses a very small subset --- of C prototypes with a limited set of types -P, R, S = lpeg.P, lpeg.R, lpeg.S -C, Ct, Cc, Cg = lpeg.C, lpeg.Ct, lpeg.Cc, lpeg.Cg - -any = P(1) -- (consume one character) -letter = R('az', 'AZ') + S('_$') -alpha = letter + R('09') -nl = P('\r\n') + P('\n') -not_nl = any - nl -ws = S(' \t') + nl -fill = ws ^ 0 -c_comment = P('//') * (not_nl ^ 0) -c_preproc = P('#') * (not_nl ^ 0) -typed_container = - (P('ArrayOf(') + P('DictionaryOf(')) * ((any - P(')')) ^ 1) * P(')') -c_id = ( - typed_container + - (letter * (alpha ^ 0)) -) -c_void = P('void') -c_param_type = ( - ((P('Error') * fill * P('*') * fill) * Cc('error')) + - (C(c_id) * (ws ^ 1)) - ) -c_type = (C(c_void) * (ws ^ 1)) + c_param_type -c_param = Ct(c_param_type * C(c_id)) -c_param_list = c_param * (fill * (P(',') * fill * c_param) ^ 0) -c_params = Ct(c_void + c_param_list) -c_proto = Ct( - Cg(c_type, 'return_type') * Cg(c_id, 'name') * - fill * P('(') * fill * Cg(c_params, 'parameters') * fill * P(')') * - Cg(Cc(false), 'async') * - (fill * Cg((P('FUNC_API_ASYNC') * Cc(true)), 'async') ^ -1) * - (fill * Cg((P('FUNC_API_NOEXPORT') * Cc(true)), 'noexport') ^ -1) * - (fill * Cg((P('FUNC_API_NOEVAL') * Cc(true)), 'noeval') ^ -1) * - fill * P(';') - ) -grammar = Ct((c_proto + c_comment + c_preproc + ws) ^ 1) - -- we need at least 4 arguments since the last two are output files -assert(#arg >= 3) +if arg[1] == '--help' then + print('Usage: genmsgpack.lua args') + print('Args: 1: source directory') + print(' 2: dispatch output file (dispatch_wrappers.generated.h)') + print(' 3: functions metadata output file (funcs_metadata.generated.h)') + print(' 4: API metadata output file (api_metadata.mpack)') + print(' 5: lua C bindings output file (msgpack_lua_c_bindings.generated.c)') + print(' rest: C files where API functions are defined') +end +assert(#arg >= 4) functions = {} -local nvimsrcdir = arg[1] -package.path = nvimsrcdir .. '/?.lua;' .. package.path +local nvimdir = arg[1] +package.path = nvimdir .. '/?.lua;' .. package.path -- names of all headers relative to the source root (for inclusion in the -- generated file) headers = {} + -- output h file with generated dispatch functions -dispatch_outputf = arg[#arg-2] +dispatch_outputf = arg[2] -- output h file with packed metadata -funcs_metadata_outputf = arg[#arg-1] +funcs_metadata_outputf = arg[3] -- output metadata mpack file, for use by other build scripts -mpack_outputf = arg[#arg] +mpack_outputf = arg[4] +lua_c_bindings_outputf = arg[5] -- set of function names, used to detect duplicates function_names = {} +c_grammar = require('generators.c_grammar') + -- read each input file, parse and append to the api metadata -for i = 2, #arg - 3 do +for i = 6, #arg do local full_path = arg[i] local parts = {} for part in string.gmatch(full_path, '[^/]+') do @@ -72,7 +43,8 @@ for i = 2, #arg - 3 do headers[#headers + 1] = parts[#parts - 1]..'/'..parts[#parts] local input = io.open(full_path, 'rb') - local tmp = grammar:match(input:read('*all')) + + local tmp = c_grammar.grammar:match(input:read('*all')) for i = 1, #tmp do local fn = tmp[i] if not fn.noexport then @@ -114,9 +86,17 @@ local deprecated_aliases = require("api.dispatch_deprecated") for i,f in ipairs(shallowcopy(functions)) do local ismethod = false if startswith(f.name, "nvim_") then - -- TODO(bfredl) after 0.1.6 allow method definitions - -- to specify the since and deprecated_since field - f.since = 1 + if startswith(f.name, "nvim__") then + f.since = -1 + elseif f.since == nil then + print("Function "..f.name.." lacks since field.\n") + os.exit(1) + end + f.since = tonumber(f.since) + if f.deprecated_since ~= nil then + f.deprecated_since = tonumber(f.deprecated_since) + end + if startswith(f.name, "nvim_buf_") then ismethod = true elseif startswith(f.name, "nvim_win_") then @@ -125,7 +105,7 @@ for i,f in ipairs(shallowcopy(functions)) do ismethod = true end else - f.noeval = true + f.remote_only = true f.since = 0 f.deprecated_since = 1 end @@ -147,7 +127,7 @@ for i,f in ipairs(shallowcopy(functions)) do newf.return_type = "Object" end newf.impl_name = f.name - newf.noeval = true + newf.remote_only = true newf.since = 0 newf.deprecated_since = 1 functions[#functions+1] = newf @@ -159,31 +139,22 @@ exported_attributes = {'name', 'parameters', 'return_type', 'method', 'since', 'deprecated_since'} exported_functions = {} for _,f in ipairs(functions) do - local f_exported = {} - for _,attr in ipairs(exported_attributes) do - f_exported[attr] = f[attr] + if not startswith(f.name, "nvim__") then + local f_exported = {} + for _,attr in ipairs(exported_attributes) do + f_exported[attr] = f[attr] + end + exported_functions[#exported_functions+1] = f_exported end - exported_functions[#exported_functions+1] = f_exported end -funcs_metadata_output = io.open(funcs_metadata_outputf, 'wb') -funcs_metadata_output:write([[ -static const uint8_t funcs_metadata[] = { -]]) - -- serialize the API metadata using msgpack and embed into the resulting -- binary for easy querying by clients -packed_exported_functions = mpack.pack(exported_functions) -for i = 1, #packed_exported_functions do - funcs_metadata_output:write(string.byte(packed_exported_functions, i)..', ') - if i % 10 == 0 then - funcs_metadata_output:write('\n ') - end -end -funcs_metadata_output:write([[ -}; -]]) +funcs_metadata_output = io.open(funcs_metadata_outputf, 'wb') +packed = mpack.pack(exported_functions) +dump_bin_array = require("generators.dump_bin_array") +dump_bin_array(funcs_metadata_output, 'funcs_metadata', packed) funcs_metadata_output:close() -- start building the dispatch wrapper output @@ -191,7 +162,7 @@ output = io.open(dispatch_outputf, 'wb') local function real_type(type) local rv = type - if typed_container:match(rv) then + if c_grammar.typed_container:match(rv) then if rv:match('Array') then rv = 'Array' else @@ -201,6 +172,14 @@ local function real_type(type) return rv end +local function attr_name(rt) + if rt == 'Float' then + return 'floating' + else + return rt:lower() + end +end + -- start the handler functions. Visit each function metadata to build the -- handler function with code generated for validating arguments and calling to -- the real API. @@ -220,8 +199,7 @@ for i = 1, #functions do end output:write('\n') output:write('\n if (args.size != '..#fn.parameters..') {') - output:write('\n snprintf(error->msg, sizeof(error->msg), "Wrong number of arguments: expecting '..#fn.parameters..' but got %zu", args.size);') - output:write('\n error->set = true;') + output:write('\n api_set_error(error, kErrorTypeException, "Wrong number of arguments: expecting '..#fn.parameters..' but got %zu", args.size);') output:write('\n goto cleanup;') output:write('\n }\n') @@ -238,7 +216,7 @@ for i = 1, #functions do output:write('\n '..converted..' = (handle_T)args.items['..(j - 1)..'].data.integer;') else output:write('\n if (args.items['..(j - 1)..'].type == kObjectType'..rt..') {') - output:write('\n '..converted..' = args.items['..(j - 1)..'].data.'..rt:lower()..';') + output:write('\n '..converted..' = args.items['..(j - 1)..'].data.'..attr_name(rt)..';') end if rt:match('^Buffer$') or rt:match('^Window$') or rt:match('^Tabpage$') or rt:match('^Boolean$') then -- accept nonnegative integers for Booleans, Buffers, Windows and Tabpages @@ -246,8 +224,7 @@ for i = 1, #functions do output:write('\n '..converted..' = (handle_T)args.items['..(j - 1)..'].data.integer;') end output:write('\n } else {') - output:write('\n snprintf(error->msg, sizeof(error->msg), "Wrong type for argument '..j..', expecting '..param[1]..'");') - output:write('\n error->set = true;') + output:write('\n api_set_error(error, kErrorTypeException, "Wrong type for argument '..j..', expecting '..param[1]..'");') output:write('\n goto cleanup;') output:write('\n }\n') else @@ -287,7 +264,7 @@ for i = 1, #functions do output:write('error);\n') end -- and check for the error - output:write('\n if (error->set) {') + output:write('\n if (ERROR_SET(error)) {') output:write('\n goto cleanup;') output:write('\n }\n') else @@ -327,3 +304,155 @@ output:close() mpack_output = io.open(mpack_outputf, 'wb') mpack_output:write(mpack.pack(functions)) mpack_output:close() + +local function include_headers(output, headers) + for i = 1, #headers do + if headers[i]:sub(-12) ~= '.generated.h' then + output:write('\n#include "nvim/'..headers[i]..'"') + end + end +end + +local function write_shifted_output(output, str) + str = str:gsub('\n ', '\n') + str = str:gsub('^ ', '') + str = str:gsub(' +$', '') + output:write(str) +end + +-- start building lua output +output = io.open(lua_c_bindings_outputf, 'wb') + +output:write([[ +#include <lua.h> +#include <lualib.h> +#include <lauxlib.h> + +#include "nvim/func_attr.h" +#include "nvim/api/private/defs.h" +#include "nvim/api/private/helpers.h" +#include "nvim/lua/converter.h" +]]) +include_headers(output, headers) +output:write('\n') + +lua_c_functions = {} + +local function process_function(fn) + lua_c_function_name = ('nlua_msgpack_%s'):format(fn.name) + write_shifted_output(output, string.format([[ + + static int %s(lua_State *lstate) + { + Error err = ERROR_INIT; + if (lua_gettop(lstate) != %i) { + api_set_error(&err, kErrorTypeValidation, "Expected %i argument%s"); + goto exit_0; + } + ]], lua_c_function_name, #fn.parameters, #fn.parameters, + (#fn.parameters == 1) and '' or 's')) + lua_c_functions[#lua_c_functions + 1] = { + binding=lua_c_function_name, + api=fn.name + } + local cparams = '' + local free_code = {} + for j = #fn.parameters,1,-1 do + param = fn.parameters[j] + cparam = string.format('arg%u', j) + param_type = real_type(param[1]) + lc_param_type = param_type:lower() + write_shifted_output(output, string.format([[ + const %s %s = nlua_pop_%s(lstate, &err); + + if (ERROR_SET(&err)) { + goto exit_%u; + } + ]], param[1], cparam, param_type, #fn.parameters - j)) + free_code[#free_code + 1] = ('api_free_%s(%s);'):format( + lc_param_type, cparam) + cparams = cparam .. ', ' .. cparams + end + if fn.receives_channel_id then + cparams = 'LUA_INTERNAL_CALL, ' .. cparams + end + if fn.can_fail then + cparams = cparams .. '&err' + else + cparams = cparams:gsub(', $', '') + end + local free_at_exit_code = '' + for i = 1, #free_code do + local rev_i = #free_code - i + 1 + local code = free_code[rev_i] + if i == 1 then + free_at_exit_code = free_at_exit_code .. ('\n %s'):format(code) + else + free_at_exit_code = free_at_exit_code .. ('\n exit_%u:\n %s'):format( + rev_i, code) + end + end + local err_throw_code = [[ + + exit_0: + if (ERROR_SET(&err)) { + luaL_where(lstate, 1); + lua_pushstring(lstate, err.msg); + api_clear_error(&err); + lua_concat(lstate, 2); + return lua_error(lstate); + } + ]] + if fn.return_type ~= 'void' then + if fn.return_type:match('^ArrayOf') then + return_type = 'Array' + else + return_type = fn.return_type + end + write_shifted_output(output, string.format([[ + const %s ret = %s(%s); + nlua_push_%s(lstate, ret); + api_free_%s(ret); + %s + %s + return 1; + ]], fn.return_type, fn.name, cparams, return_type, return_type:lower(), + free_at_exit_code, err_throw_code)) + else + write_shifted_output(output, string.format([[ + %s(%s); + %s + %s + return 0; + ]], fn.name, cparams, free_at_exit_code, err_throw_code)) + end + write_shifted_output(output, [[ + } + ]]) +end + +for _, fn in ipairs(functions) do + if not fn.remote_only or fn.name:sub(1, 4) == '_vim' then + process_function(fn) + end +end + +output:write(string.format([[ +void nlua_add_api_functions(lua_State *lstate) + FUNC_ATTR_NONNULL_ALL +{ + lua_createtable(lstate, 0, %u); +]], #lua_c_functions)) +for _, func in ipairs(lua_c_functions) do + output:write(string.format([[ + + lua_pushcfunction(lstate, &%s); + lua_setfield(lstate, -2, "%s");]], func.binding, func.api)) +end +output:write([[ + + lua_setfield(lstate, -2, "api"); +} +]]) + +output:close() diff --git a/src/nvim/generators/gen_api_ui_events.lua b/src/nvim/generators/gen_api_ui_events.lua new file mode 100644 index 0000000000..d2b90db707 --- /dev/null +++ b/src/nvim/generators/gen_api_ui_events.lua @@ -0,0 +1,166 @@ +mpack = require('mpack') + +local nvimdir = arg[1] +package.path = nvimdir .. '/?.lua;' .. package.path + +assert(#arg == 7) +input = io.open(arg[2], 'rb') +proto_output = io.open(arg[3], 'wb') +call_output = io.open(arg[4], 'wb') +remote_output = io.open(arg[5], 'wb') +bridge_output = io.open(arg[6], 'wb') +metadata_output = io.open(arg[7], 'wb') + +c_grammar = require('generators.c_grammar') +local events = c_grammar.grammar:match(input:read('*all')) + +function write_signature(output, ev, prefix, notype) + output:write('('..prefix) + if prefix == "" and #ev.parameters == 0 then + output:write('void') + end + for j = 1, #ev.parameters do + if j > 1 or prefix ~= '' then + output:write(', ') + end + local param = ev.parameters[j] + if not notype then + output:write(param[1]..' ') + end + output:write(param[2]) + end + output:write(')') +end + +function write_arglist(output, ev, need_copy) + output:write(' Array args = ARRAY_DICT_INIT;\n') + for j = 1, #ev.parameters do + local param = ev.parameters[j] + local kind = string.upper(param[1]) + local do_copy = need_copy and (kind == "ARRAY" or kind == "DICTIONARY" or kind == "STRING") + output:write(' ADD(args, ') + if do_copy then + output:write('copy_object(') + end + output:write(kind..'_OBJ('..param[2]..')') + if do_copy then + output:write(')') + end + output:write(');\n') + end +end + +for i = 1, #events do + ev = events[i] + assert(ev.return_type == 'void') + + if ev.since == nil then + print("Ui event "..ev.name.." lacks since field.\n") + os.exit(1) + end + ev.since = tonumber(ev.since) + + if not ev.remote_only then + proto_output:write(' void (*'..ev.name..')') + write_signature(proto_output, ev, 'UI *ui') + proto_output:write(';\n') + + if not ev.remote_impl then + remote_output:write('static void remote_ui_'..ev.name) + write_signature(remote_output, ev, 'UI *ui') + remote_output:write('\n{\n') + write_arglist(remote_output, ev, true) + remote_output:write(' push_call(ui, "'..ev.name..'", args);\n') + remote_output:write('}\n\n') + end + + if not ev.bridge_impl then + + send, argv, recv, recv_argv, recv_cleanup = '', '', '', '', '' + argc = 1 + for j = 1, #ev.parameters do + local param = ev.parameters[j] + copy = 'copy_'..param[2] + if param[1] == 'String' then + send = send..' String copy_'..param[2]..' = copy_string('..param[2]..');\n' + argv = argv..', '..copy..'.data, INT2PTR('..copy..'.size)' + recv = (recv..' String '..param[2].. + ' = (String){.data = argv['..argc..'],'.. + '.size = (size_t)argv['..(argc+1)..']};\n') + recv_argv = recv_argv..', '..param[2] + recv_cleanup = recv_cleanup..' api_free_string('..param[2]..');\n' + argc = argc+2 + elseif param[1] == 'Array' then + send = send..' Array copy_'..param[2]..' = copy_array('..param[2]..');\n' + argv = argv..', '..copy..'.items, INT2PTR('..copy..'.size)' + recv = (recv..' Array '..param[2].. + ' = (Array){.items = argv['..argc..'],'.. + '.size = (size_t)argv['..(argc+1)..']};\n') + recv_argv = recv_argv..', '..param[2] + recv_cleanup = recv_cleanup..' api_free_array('..param[2]..');\n' + argc = argc+2 + elseif param[1] == 'Integer' or param[1] == 'Boolean' then + argv = argv..', INT2PTR('..param[2]..')' + recv_argv = recv_argv..', PTR2INT(argv['..argc..'])' + argc = argc+1 + else + assert(false) + end + end + bridge_output:write('static void ui_bridge_'..ev.name.. + '_event(void **argv)\n{\n') + bridge_output:write(' UI *ui = UI(argv[0]);\n') + bridge_output:write(recv) + bridge_output:write(' ui->'..ev.name..'(ui'..recv_argv..');\n') + bridge_output:write(recv_cleanup) + bridge_output:write('}\n\n') + + bridge_output:write('static void ui_bridge_'..ev.name) + write_signature(bridge_output, ev, 'UI *ui') + bridge_output:write('\n{\n') + bridge_output:write(send) + bridge_output:write(' UI_BRIDGE_CALL(ui, '..ev.name..', '..argc..', ui'..argv..');\n}\n') + end + end + + call_output:write('void ui_call_'..ev.name) + write_signature(call_output, ev, '') + call_output:write('\n{\n') + if ev.remote_only then + write_arglist(call_output, ev, false) + call_output:write(' UI_LOG('..ev.name..', 0);\n') + call_output:write(' ui_event("'..ev.name..'", args);\n') + else + call_output:write(' UI_CALL') + write_signature(call_output, ev, ev.name, true) + call_output:write(";\n") + end + call_output:write("}\n\n") + +end + +proto_output:close() +call_output:close() +remote_output:close() + +-- don't expose internal attributes like "impl_name" in public metadata +exported_attributes = {'name', 'parameters', + 'since', 'deprecated_since'} +exported_events = {} +for _,ev in ipairs(events) do + local ev_exported = {} + for _,attr in ipairs(exported_attributes) do + ev_exported[attr] = ev[attr] + end + for _,p in ipairs(ev_exported.parameters) do + if p[1] == 'HlAttrs' then + p[1] = 'Dictionary' + end + end + exported_events[#exported_events+1] = ev_exported +end + +packed = mpack.pack(exported_events) +dump_bin_array = require("generators.dump_bin_array") +dump_bin_array(metadata_output, 'ui_events_metadata', packed) +metadata_output:close() diff --git a/src/nvim/generators/gen_char_blob.lua b/src/nvim/generators/gen_char_blob.lua new file mode 100644 index 0000000000..d860375e26 --- /dev/null +++ b/src/nvim/generators/gen_char_blob.lua @@ -0,0 +1,48 @@ +if arg[1] == '--help' then + print('Usage:') + print(' gencharblob.lua source target varname') + print('') + print('Generates C file with big uint8_t blob.') + print('Blob will be stored in a static const array named varname.') + os.exit() +end + +assert(#arg == 3) + +local source_file = arg[1] +local target_file = arg[2] +local varname = arg[3] + +source = io.open(source_file, 'r') +target = io.open(target_file, 'w') + +target:write('#include <stdint.h>\n\n') +target:write(('static const uint8_t %s[] = {\n'):format(varname)) + +num_bytes = 0 +MAX_NUM_BYTES = 15 -- 78 / 5: maximum number of bytes on one line +target:write(' ') + +increase_num_bytes = function() + num_bytes = num_bytes + 1 + if num_bytes == MAX_NUM_BYTES then + num_bytes = 0 + target:write('\n ') + end +end + +for line in source:lines() do + for i = 1,string.len(line) do + byte = string.byte(line, i) + assert(byte ~= 0) + target:write(string.format(' %3u,', byte)) + increase_num_bytes() + end + target:write(string.format(' %3u,', string.byte('\n', 1))) + increase_num_bytes() +end + +target:write(' 0};\n') + +source:close() +target:close() diff --git a/scripts/gendeclarations.lua b/src/nvim/generators/gen_declarations.lua index ff69b18ae4..e999e53e4a 100755 --- a/scripts/gendeclarations.lua +++ b/src/nvim/generators/gen_declarations.lua @@ -69,17 +69,18 @@ local word = branch( right_word ) ) +local inline_comment = concat( + lit('/*'), + any_amount(concat( + neg_look_ahead(lit('*/')), + any_character + )), + lit('*/') +) local spaces = any_amount(branch( s, -- Comments are really handled by preprocessor, so the following is not needed - concat( - lit('/*'), - any_amount(concat( - neg_look_ahead(lit('*/')), - any_character - )), - lit('*/') - ), + inline_comment, concat( lit('//'), any_amount(concat( @@ -110,6 +111,7 @@ local typ = one_or_more(typ_part) local typ_id = two_or_more(typ_part) local arg = typ_id -- argument name is swallowed by typ local pattern = concat( + any_amount(branch(set(' ', '\t'), inline_comment)), typ_id, -- return type with function name spaces, lit('('), @@ -188,24 +190,44 @@ local footer = [[ local non_static = header local static = header -local filepattern = '^#%a* %d+ "[^"]-/?([^"/]+)"' +local filepattern = '^#%a* (%d+) "([^"]-)/?([^"/]+)"' local curfile -init = 0 -curfile = nil -neededfile = fname:match('[^/]+$') +local init = 0 +local curfile = nil +local neededfile = fname:match('[^/]+$') +local declline = 0 +local declendpos = 0 +local curdir = nil +local is_needed_file = false while init ~= nil do - init = text:find('\n', init) + init = text:find('[\n;}]', init) if init == nil then break end + local init_is_nl = text:sub(init, init) == '\n' init = init + 1 - if text:sub(init, init) == '#' then - file = text:match(filepattern, init) + if init_is_nl and is_needed_file then + declline = declline + 1 + end + if init_is_nl and text:sub(init, init) == '#' then + local line, dir, file = text:match(filepattern, init) if file ~= nil then curfile = file + is_needed_file = (curfile == neededfile) + declline = tonumber(line) - 1 + local curdir_start = dir:find('src/nvim/') + if curdir_start ~= nil then + curdir = dir:sub(curdir_start + #('src/nvim/')) + else + curdir = dir + end + else + declline = declline - 1 end - elseif curfile == neededfile then + elseif init < declendpos then + -- Skipping over declaration + elseif is_needed_file then s = init e = pattern:match(text, init) if e ~= nil then @@ -225,13 +247,17 @@ while init ~= nil do declaration = declaration:gsub(' ?(%*+) ?', ' %1') declaration = declaration:gsub(' ?(FUNC_ATTR_)', ' %1') declaration = declaration:gsub(' $', '') - declaration = declaration .. ';\n' - if text:sub(s, s + 5) == 'static' then + declaration = declaration:gsub('^ ', '') + declaration = declaration .. ';' + declaration = declaration .. (' // %s/%s:%u'):format( + curdir, curfile, declline) + declaration = declaration .. '\n' + if declaration:sub(1, 6) == 'static' then static = static .. declaration else non_static = non_static .. declaration end - init = e + declendpos = e end end end diff --git a/scripts/geneval.lua b/src/nvim/generators/gen_eval.lua index b1ba76296c..23435a1d0b 100644 --- a/scripts/geneval.lua +++ b/src/nvim/generators/gen_eval.lua @@ -25,7 +25,7 @@ local gperfpipe = io.open(funcsfname .. '.gperf', 'wb') local funcs = require('eval').funcs local metadata = mpack.unpack(io.open(arg[3], 'rb'):read("*all")) for i,fun in ipairs(metadata) do - if not fun.noeval then + if not fun.remote_only then funcs[fun.name] = { args=#fun.parameters, func='api_wrapper', @@ -41,6 +41,7 @@ funcsdata:close() gperfpipe:write([[ %language=ANSI-C %global-table +%readonly-tables %define initializer-suffix ,0,0,NULL,NULL %define word-array-name functions %define hash-function-name hash_internal_func_gperf diff --git a/scripts/gen_events.lua b/src/nvim/generators/gen_events.lua index 75e0b3da3a..75e0b3da3a 100644 --- a/scripts/gen_events.lua +++ b/src/nvim/generators/gen_events.lua diff --git a/scripts/genex_cmds.lua b/src/nvim/generators/gen_ex_cmds.lua index b1d34fbffd..cb566d46ca 100644 --- a/scripts/genex_cmds.lua +++ b/src/nvim/generators/gen_ex_cmds.lua @@ -66,7 +66,7 @@ for i, cmd in ipairs(defs) do defsfile:write(string.format([[ [%s] = { .cmd_name = (char_u *) "%s", - .cmd_func = &%s, + .cmd_func = (ex_func_T)&%s, .cmd_argt = %uL, .cmd_addr_type = %i }]], enumname, cmd.command, cmd.func, cmd.flags, cmd.addr_type)) diff --git a/scripts/genoptions.lua b/src/nvim/generators/gen_options.lua index 9f7d94969d..ca0134043c 100644 --- a/scripts/genoptions.lua +++ b/src/nvim/generators/gen_options.lua @@ -31,6 +31,7 @@ local type_flags={ local redraw_flags={ statuslines='P_RSTAT', current_window='P_RWIN', + current_window_only='P_RWINONLY', current_buffer='P_RBUF', all_windows='P_RALL', everything='P_RCLR', @@ -117,7 +118,7 @@ local get_value = function(v) end local get_defaults = function(d) - return '{' .. get_value(d.vi) .. ', ' .. get_value(d.vim) .. '}' + return ('{' .. get_value(d.vi) .. ', ' .. get_value(d.vim) .. '}') end local defines = {} diff --git a/scripts/genunicodetables.lua b/src/nvim/generators/gen_unicode_tables.lua index 66430ba26e..66430ba26e 100644 --- a/scripts/genunicodetables.lua +++ b/src/nvim/generators/gen_unicode_tables.lua diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c index fccbd69dbf..a22b716bb6 100644 --- a/src/nvim/getchar.c +++ b/src/nvim/getchar.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + /* * getchar.c * @@ -15,6 +18,7 @@ #include "nvim/vim.h" #include "nvim/ascii.h" #include "nvim/getchar.h" +#include "nvim/buffer_defs.h" #include "nvim/charset.h" #include "nvim/cursor.h" #include "nvim/edit.h" @@ -44,6 +48,7 @@ #include "nvim/event/loop.h" #include "nvim/os/input.h" #include "nvim/os/os.h" +#include "nvim/api/private/handle.h" /* * These buffers are used for storing: @@ -99,11 +104,10 @@ static int block_redo = FALSE; (NORMAL + VISUAL + SELECTMODE + \ OP_PENDING)) ? (c1) : ((c1) ^ 0x80)) -/* - * Each mapping is put in one of the 256 hash lists, to speed up finding it. - */ -static mapblock_T *(maphash[256]); -static int maphash_valid = FALSE; +// Each mapping is put in one of the MAX_MAPHASH hash lists, +// to speed up finding it. +static mapblock_T *(maphash[MAX_MAPHASH]); +static bool maphash_valid = false; /* * List used for abbreviations. @@ -235,19 +239,18 @@ char_u *get_inserted(void) return get_buffcont(&redobuff, FALSE); } -/* - * Add string "s" after the current block of buffer "buf". - * K_SPECIAL and CSI should have been escaped already. - */ -static void -add_buff ( - buffheader_T *buf, - char_u *s, - ssize_t slen // length of "s" or -1 -) +/// Add string after the current block of the given buffer +/// +/// K_SPECIAL and CSI should have been escaped already. +/// +/// @param[out] buf Buffer to add to. +/// @param[in] s String to add. +/// @param[in] slen String length or -1 for NUL-terminated string. +static void add_buff(buffheader_T *const buf, const char *const s, + ptrdiff_t slen) { if (slen < 0) { - slen = (ssize_t)STRLEN(s); + slen = (ptrdiff_t)strlen(s); } if (slen == 0) { // don't add empty strings return; @@ -292,9 +295,8 @@ add_buff ( */ static void add_num_buff(buffheader_T *buf, long n) { - char_u number[32]; - - sprintf((char *)number, "%" PRId64, (int64_t)n); + char number[32]; + snprintf(number, sizeof(number), "%ld", n); add_buff(buf, number, -1L); } @@ -304,27 +306,29 @@ static void add_num_buff(buffheader_T *buf, long n) */ static void add_char_buff(buffheader_T *buf, int c) { - char_u bytes[MB_MAXBYTES + 1]; - int len; - int i; - char_u temp[4]; + uint8_t bytes[MB_MAXBYTES + 1]; - if (IS_SPECIAL(c)) + int len; + if (IS_SPECIAL(c)) { len = 1; - else - len = (*mb_char2bytes)(c, bytes); - for (i = 0; i < len; ++i) { - if (!IS_SPECIAL(c)) + } else { + len = mb_char2bytes(c, bytes); + } + + for (int i = 0; i < len; i++) { + if (!IS_SPECIAL(c)) { c = bytes[i]; + } + char temp[4]; if (IS_SPECIAL(c) || c == K_SPECIAL || c == NUL) { - /* translate special key code into three byte sequence */ - temp[0] = K_SPECIAL; - temp[1] = (char_u)K_SECOND(c); - temp[2] = (char_u)K_THIRD(c); + // Translate special key code into three byte sequence. + temp[0] = (char)K_SPECIAL; + temp[1] = (char)K_SECOND(c); + temp[2] = (char)K_THIRD(c); temp[3] = NUL; } else { - temp[0] = (char_u)c; + temp[0] = (char)c; temp[1] = NUL; } add_buff(buf, temp, -1L); @@ -479,16 +483,14 @@ static int save_level = 0; void saveRedobuff(void) { - char_u *s; - if (save_level++ == 0) { save_redobuff = redobuff; redobuff.bh_first.b_next = NULL; save_old_redobuff = old_redobuff; old_redobuff.bh_first.b_next = NULL; - /* Make a copy, so that ":normal ." in a function works. */ - s = get_buffcont(&save_redobuff, FALSE); + // Make a copy, so that ":normal ." in a function works. + char *const s = (char *)get_buffcont(&save_redobuff, false); if (s != NULL) { add_buff(&redobuff, s, -1L); xfree(s); @@ -514,10 +516,11 @@ void restoreRedobuff(void) * Append "s" to the redo buffer. * K_SPECIAL and CSI should already have been escaped. */ -void AppendToRedobuff(char_u *s) +void AppendToRedobuff(const char *s) { - if (!block_redo) - add_buff(&redobuff, s, -1L); + if (!block_redo) { + add_buff(&redobuff, (const char *)s, -1L); + } } /* @@ -530,44 +533,47 @@ AppendToRedobuffLit ( int len /* length of "str" or -1 for up to the NUL */ ) { - char_u *s = str; - int c; - char_u *start; - - if (block_redo) + if (block_redo) { return; + } + + const char *s = (const char *)str; + while (len < 0 ? *s != NUL : s - (const char *)str < len) { + // Put a string of normal characters in the redo buffer (that's + // faster). + const char *start = s; + while (*s >= ' ' && *s < DEL && (len < 0 || s - (const char *)str < len)) { + s++; + } - while (len < 0 ? *s != NUL : s - str < len) { - /* Put a string of normal characters in the redo buffer (that's - * faster). */ - start = s; - while (*s >= ' ' && *s < DEL && (len < 0 || s - str < len)) - ++s; - - /* Don't put '0' or '^' as last character, just in case a CTRL-D is - * typed next. */ - if (*s == NUL && (s[-1] == '0' || s[-1] == '^')) - --s; - if (s > start) + // Don't put '0' or '^' as last character, just in case a CTRL-D is + // typed next. + if (*s == NUL && (s[-1] == '0' || s[-1] == '^')) { + s--; + } + if (s > start) { add_buff(&redobuff, start, (long)(s - start)); + } - if (*s == NUL || (len >= 0 && s - str >= len)) + if (*s == NUL || (len >= 0 && s - (const char *)str >= len)) { break; + } - /* Handle a special or multibyte character. */ - if (has_mbyte) - /* Handle composing chars separately. */ - c = mb_cptr2char_adv(&s); - else - c = *s++; - if (c < ' ' || c == DEL || (*s == NUL && (c == '0' || c == '^'))) + // Handle a special or multibyte character. + // Composing chars separately are handled separately. + const int c = (has_mbyte + ? mb_cptr2char_adv((const char_u **)&s) + : (uint8_t)(*s++)); + if (c < ' ' || c == DEL || (*s == NUL && (c == '0' || c == '^'))) { add_char_buff(&redobuff, Ctrl_V); + } - /* CTRL-V '0' must be inserted as CTRL-V 048 */ - if (*s == NUL && c == '0') - add_buff(&redobuff, (char_u *)"048", 3L); - else + // CTRL-V '0' must be inserted as CTRL-V 048. + if (*s == NUL && c == '0') { + add_buff(&redobuff, "048", 3L); + } else { add_char_buff(&redobuff, c); + } } } @@ -594,19 +600,19 @@ void AppendNumberToRedobuff(long n) * Append string "s" to the stuff buffer. * CSI and K_SPECIAL must already have been escaped. */ -void stuffReadbuff(char_u *s) +void stuffReadbuff(const char *s) { add_buff(&readbuf1, s, -1L); } /// Append string "s" to the redo stuff buffer. /// @remark CSI and K_SPECIAL must already have been escaped. -void stuffRedoReadbuff(char_u *s) +void stuffRedoReadbuff(const char *s) { add_buff(&readbuf2, s, -1L); } -void stuffReadbuffLen(char_u *s, long len) +void stuffReadbuffLen(const char *s, long len) { add_buff(&readbuf1, s, len); } @@ -616,19 +622,18 @@ void stuffReadbuffLen(char_u *s, long len) * escaping other K_SPECIAL and CSI bytes. * Change CR, LF and ESC into a space. */ -void stuffReadbuffSpec(char_u *s) +void stuffReadbuffSpec(const char *s) { - int c; - while (*s != NUL) { - if (*s == K_SPECIAL && s[1] != NUL && s[2] != NUL) { - /* Insert special key literally. */ - stuffReadbuffLen(s, 3L); + if ((uint8_t)(*s) == K_SPECIAL && s[1] != NUL && s[2] != NUL) { + // Insert special key literally. + stuffReadbuffLen(s, 3); s += 3; } else { - c = mb_ptr2char_adv(&s); - if (c == CAR || c == NL || c == ESC) + int c = mb_ptr2char_adv((const char_u **)&s); + if (c == CAR || c == NL || c == ESC) { c = ' '; + } stuffcharReadbuff(c); } } @@ -747,8 +752,8 @@ int start_redo(long count, int old_redo) /* copy the buffer name, if present */ if (c == '"') { - add_buff(&readbuf2, (char_u *)"\"", 1L); - c = read_redo(FALSE, old_redo); + add_buff(&readbuf2, "\"", 1L); + c = read_redo(false, old_redo); /* if a numbered buffer is used, increment the number */ if (c >= '1' && c < '9') @@ -1091,21 +1096,19 @@ static void gotchars(char_u *chars, size_t len) { char_u *s = chars; int c; - char_u buf[2]; // remember how many chars were last recorded if (Recording) { last_recorded_len += len; } - buf[1] = NUL; while (len--) { // Handle one byte at a time; no translation to be done. c = *s++; updatescript(c); if (Recording) { - buf[0] = (char_u)c; + char buf[2] = { (char)c, NUL }; add_buff(&recordbuff, buf, 1L); } } @@ -1327,8 +1330,9 @@ int using_script(void) void before_blocking(void) { updatescript(0); - if (may_garbage_collect) - garbage_collect(); + if (may_garbage_collect) { + garbage_collect(false); + } } /* @@ -1366,10 +1370,11 @@ int vgetc(void) char_u buf[MB_MAXBYTES + 1]; int i; - /* Do garbage collection when garbagecollect() was called previously and - * we are now at the toplevel. */ - if (may_garbage_collect && want_garbage_collect) - garbage_collect(); + // Do garbage collection when garbagecollect() was called previously and + // we are now at the toplevel. + if (may_garbage_collect && want_garbage_collect) { + garbage_collect(false); + } /* * If a character was put back with vungetc, it was already processed. @@ -1387,27 +1392,20 @@ int vgetc(void) for (;; ) { // this is done twice if there are modifiers bool did_inc = false; if (mod_mask) { // no mapping after modifier has been read - ++no_mapping; - ++allow_keys; + no_mapping++; did_inc = true; // mod_mask may change value } c = vgetorpeek(true); if (did_inc) { - --no_mapping; - --allow_keys; + no_mapping--; } - /* Get two extra bytes for special keys */ - if (c == K_SPECIAL - ) { - int save_allow_keys = allow_keys; - - ++no_mapping; - allow_keys = 0; /* make sure BS is not found */ - c2 = vgetorpeek(TRUE); /* no mapping for these chars */ - c = vgetorpeek(TRUE); - --no_mapping; - allow_keys = save_allow_keys; + // Get two extra bytes for special keys + if (c == K_SPECIAL) { + no_mapping++; + c2 = vgetorpeek(true); // no mapping for these chars + c = vgetorpeek(true); + no_mapping--; if (c2 == KS_MODIFIER) { mod_mask = c; continue; @@ -1485,7 +1483,7 @@ int vgetc(void) buf[i] = CSI; } } - --no_mapping; + no_mapping--; c = (*mb_ptr2char)(buf); } @@ -1568,7 +1566,7 @@ int char_avail(void) no_mapping++; retval = vpeekc(); - --no_mapping; + no_mapping--; return retval != NUL; } @@ -1595,7 +1593,7 @@ vungetc ( /* unget one character (can only be done once!) */ /// This may do a blocking wait if "advance" is TRUE. /// /// if "advance" is TRUE (vgetc()): -/// really get the character. +/// Really get the character. /// KeyTyped is set to TRUE in the case the user typed the key. /// KeyStuffed is TRUE if the character comes from the stuff buffer. /// if "advance" is FALSE (vpeekc()): @@ -1808,7 +1806,7 @@ static int vgetorpeek(int advance) * <M-a> and then changing 'encoding'. Beware * that 0x80 is escaped. */ char_u *p1 = mp->m_keys; - char_u *p2 = mb_unescape(&p1); + char_u *p2 = (char_u *)mb_unescape((const char **)&p1); if (has_mbyte && p2 != NULL && MB_BYTE2LEN(c1) > MB_PTR2LEN(p2)) mlen = 0; @@ -1855,11 +1853,12 @@ static int vgetorpeek(int advance) mp_match = mp; mp_match_len = keylen; } - } else - /* No match; may have to check for - * termcode at next character. */ - if (max_mlen < mlen) - max_mlen = mlen; + } else { + // No match; may have to check for termcode at next character. + if (max_mlen < mlen) { + max_mlen = mlen; + } + } } } @@ -1886,9 +1885,8 @@ static int vgetorpeek(int advance) (size_t)(mlen - typebuf.tb_maplen)); } - del_typebuf(mlen, 0); /* remove the chars */ - set_option_value((char_u *)"paste", - (long)!p_paste, NULL, 0); + del_typebuf(mlen, 0); // Remove the chars. + set_option_value("paste", !p_paste, NULL, 0); if (!(State & INSERT)) { msg_col = 0; msg_row = (int)Rows - 1; @@ -1911,63 +1909,30 @@ static int vgetorpeek(int advance) if ((mp == NULL || max_mlen >= mp_match_len) && keylen != KEYLEN_PART_MAP) { - /* - * When no matching mapping found or found a - * non-matching mapping that matches at least what the - * matching mapping matched: - * Check if we have a terminal code, when: - * mapping is allowed, - * keys have not been mapped, - * and not an ESC sequence, not in insert mode or - * p_ek is on, - * and when not timed out, - */ - if ((no_mapping == 0 || allow_keys != 0) - && (typebuf.tb_maplen == 0 - || (p_remap && typebuf.tb_noremap[ - typebuf.tb_off] == RM_YES)) - && !timedout) { - keylen = 0; - } else - keylen = 0; - if (keylen == 0) { /* no matching terminal code */ - /* When there was a matching mapping and no - * termcode could be replaced after another one, - * use that mapping (loop around). If there was - * no mapping use the character from the - * typeahead buffer right here. */ - if (mp == NULL) { - /* - * get a character: 2. from the typeahead buffer - */ - c = typebuf.tb_buf[typebuf.tb_off] & 255; - if (advance) { /* remove chars from tb_buf */ - cmd_silent = (typebuf.tb_silent > 0); - if (typebuf.tb_maplen > 0) - KeyTyped = FALSE; - else { - KeyTyped = TRUE; - /* write char to script file(s) */ - gotchars(typebuf.tb_buf - + typebuf.tb_off, 1); - } - KeyNoremap = typebuf.tb_noremap[ - typebuf.tb_off]; - del_typebuf(1, 0); + // No matching mapping found or found a non-matching mapping that + // matches at least what the matching mapping matched + keylen = 0; + // If there was no mapping, use the character from the typeahead + // buffer right here. Otherwise, use the mapping (loop around). + if (mp == NULL) { + // get a character: 2. from the typeahead buffer + c = typebuf.tb_buf[typebuf.tb_off] & 255; + if (advance) { // remove chars from tb_buf + cmd_silent = (typebuf.tb_silent > 0); + if (typebuf.tb_maplen > 0) { + KeyTyped = false; + } else { + KeyTyped = true; + // write char to script file(s) + gotchars(typebuf.tb_buf + typebuf.tb_off, 1); } - break; /* got character, break for loop */ + KeyNoremap = typebuf.tb_noremap[typebuf.tb_off]; + del_typebuf(1, 0); } - } - if (keylen > 0) { /* full matching terminal code */ - continue; /* try mapping again */ - } - - /* Partial match: get some more characters. When a - * matching mapping was found use that one. */ - if (mp == NULL || keylen < 0) - keylen = KEYLEN_PART_KEY; - else + break; // got character, break for loop + } else { keylen = mp_match_len; + } } /* complete match */ @@ -2462,7 +2427,7 @@ inchar ( if (typebuf_changed(tb_change_cnt)) return 0; - return fix_input_buffer(buf, len, script_char >= 0); + return fix_input_buffer(buf, len); } /* @@ -2470,12 +2435,7 @@ inchar ( * buf[] must have room to triple the number of bytes! * Returns the new length. */ -int -fix_input_buffer ( - char_u *buf, - int len, - int script /* TRUE when reading from a script */ -) +int fix_input_buffer(char_u *buf, int len) { if (!using_script()) { // Should not escape K_SPECIAL/CSI reading input from the user because vim @@ -2492,12 +2452,10 @@ fix_input_buffer ( // Replace NUL by K_SPECIAL KS_ZERO KE_FILLER // Replace K_SPECIAL by K_SPECIAL KS_SPECIAL KE_FILLER // Replace CSI by K_SPECIAL KS_EXTRA KE_CSI - // Don't replace K_SPECIAL when reading a script file. for (i = len; --i >= 0; ++p) { if (p[0] == NUL || (p[0] == K_SPECIAL - && !script - && (i < 2 || p[1] != KS_EXTRA))) { + && (i < 2 || p[1] != KS_EXTRA))) { memmove(p + 3, p + 1, (size_t)i); p[2] = (char_u)K_THIRD(p[0]); p[1] = (char_u)K_SECOND(p[0]); @@ -2579,7 +2537,6 @@ do_map ( bool unique = false; bool nowait = false; bool silent = false; - bool special = false; bool expr = false; int noremap; char_u *orig_rhs; @@ -2625,12 +2582,9 @@ do_map ( continue; } - /* - * Check for "<special>": accept special keys in <> - */ + // Ignore obsolete "<special>" modifier. if (STRNCMP(keys, "<special>", 9) == 0) { keys = skipwhite(keys + 9); - special = true; continue; } @@ -2699,7 +2653,7 @@ do_map ( // needs to be freed later (*keys_buf and *arg_buf). // replace_termcodes() also removes CTRL-Vs and sometimes backslashes. if (haskey) { - keys = replace_termcodes(keys, STRLEN(keys), &keys_buf, true, true, special, + keys = replace_termcodes(keys, STRLEN(keys), &keys_buf, true, true, true, CPO_TO_CPO_FLAGS); } orig_rhs = rhs; @@ -2707,7 +2661,7 @@ do_map ( if (STRICMP(rhs, "<nop>") == 0) { // "<Nop>" means nothing rhs = (char_u *)""; } else { - rhs = replace_termcodes(rhs, STRLEN(rhs), &arg_buf, false, true, special, + rhs = replace_termcodes(rhs, STRLEN(rhs), &arg_buf, false, true, true, CPO_TO_CPO_FLAGS); } } @@ -3163,11 +3117,11 @@ map_clear_int ( } } -/* - * Return characters to represent the map mode in an allocated string. - * Returns NULL when out of memory. - */ -char_u *map_mode_to_chars(int mode) +/// Return characters to represent the map mode in an allocated string +/// +/// @return [allocated] NUL-terminated string with characters. +char *map_mode_to_chars(int mode) + FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_RET { garray_T mapmode; @@ -3200,7 +3154,7 @@ char_u *map_mode_to_chars(int mode) } ga_append(&mapmode, NUL); - return (char_u *)mapmode.ga_data; + return (char *)mapmode.ga_data; } static void @@ -3209,8 +3163,11 @@ showmap ( int local /* TRUE for buffer-local map */ ) { - int len = 1; - char_u *mapchars; + size_t len = 1; + + if (message_filtered(mp->m_keys) && message_filtered(mp->m_str)) { + return; + } if (msg_didout || msg_silent != 0) { msg_putchar('\n'); @@ -3218,29 +3175,30 @@ showmap ( return; } - mapchars = map_mode_to_chars(mp->m_mode); - if (mapchars != NULL) { + { + char *const mapchars = map_mode_to_chars(mp->m_mode); msg_puts(mapchars); - len = (int)STRLEN(mapchars); + len = strlen(mapchars); xfree(mapchars); } while (++len <= 3) msg_putchar(' '); - /* Display the LHS. Get length of what we write. */ - len = msg_outtrans_special(mp->m_keys, TRUE); + // Display the LHS. Get length of what we write. + len = (size_t)msg_outtrans_special(mp->m_keys, true); do { msg_putchar(' '); /* padd with blanks */ ++len; } while (len < 12); - if (mp->m_noremap == REMAP_NONE) - msg_puts_attr((char_u *)"*", hl_attr(HLF_8)); - else if (mp->m_noremap == REMAP_SCRIPT) - msg_puts_attr((char_u *)"&", hl_attr(HLF_8)); - else + if (mp->m_noremap == REMAP_NONE) { + msg_puts_attr("*", hl_attr(HLF_8)); + } else if (mp->m_noremap == REMAP_SCRIPT) { + msg_puts_attr("&", hl_attr(HLF_8)); + } else { msg_putchar(' '); + } if (local) msg_putchar('@'); @@ -3249,11 +3207,11 @@ showmap ( /* Use FALSE below if we only want things like <Up> to show up as such on * the rhs, and not M-x etc, TRUE gets both -- webb */ - if (*mp->m_str == NUL) - msg_puts_attr((char_u *)"<Nop>", hl_attr(HLF_8)); - else { - /* Remove escaping of CSI, because "m_str" is in a format to be used - * as typeahead. */ + if (*mp->m_str == NUL) { + msg_puts_attr("<Nop>", hl_attr(HLF_8)); + } else { + // Remove escaping of CSI, because "m_str" is in a format to be used + // as typeahead. char_u *s = vim_strsave(mp->m_str); vim_unescape_csi(s); msg_outtrans_special(s, FALSE); @@ -3264,82 +3222,99 @@ showmap ( ui_flush(); /* show one line at a time */ } -/* - * Return TRUE if a map exists that has "str" in the rhs for mode "modechars". - * Recognize termcap codes in "str". - * Also checks mappings local to the current buffer. - */ -int map_to_exists(char_u *str, char_u *modechars, int abbr) +/// Check if a map exists that has given string in the rhs +/// +/// Also checks mappings local to the current buffer. +/// +/// @param[in] str String which mapping must have in the rhs. Termcap codes +/// are recognized in this argument. +/// @param[in] modechars Mode(s) in which mappings are checked. +/// @param[in] abbr true if checking abbreviations in place of mappings. +/// +/// @return true if there is at least one mapping with given parameters. +bool map_to_exists(const char *const str, const char *const modechars, + const bool abbr) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE { int mode = 0; - char_u *rhs; - char_u *buf; int retval; - rhs = replace_termcodes(str, STRLEN(str), &buf, false, true, false, - CPO_TO_CPO_FLAGS); - - if (vim_strchr(modechars, 'n') != NULL) - mode |= NORMAL; - if (vim_strchr(modechars, 'v') != NULL) - mode |= VISUAL + SELECTMODE; - if (vim_strchr(modechars, 'x') != NULL) - mode |= VISUAL; - if (vim_strchr(modechars, 's') != NULL) - mode |= SELECTMODE; - if (vim_strchr(modechars, 'o') != NULL) - mode |= OP_PENDING; - if (vim_strchr(modechars, 'i') != NULL) - mode |= INSERT; - if (vim_strchr(modechars, 'l') != NULL) - mode |= LANGMAP; - if (vim_strchr(modechars, 'c') != NULL) - mode |= CMDLINE; - - retval = map_to_exists_mode(rhs, mode, abbr); + char_u *buf; + char_u *const rhs = replace_termcodes((const char_u *)str, strlen(str), &buf, + false, true, true, + CPO_TO_CPO_FLAGS); + +#define MAPMODE(mode, modechars, chr, modeflags) \ + do { \ + if (strchr(modechars, chr) != NULL) { \ + mode |= modeflags; \ + } \ + } while (0) + MAPMODE(mode, modechars, 'n', NORMAL); + MAPMODE(mode, modechars, 'v', VISUAL|SELECTMODE); + MAPMODE(mode, modechars, 'x', VISUAL); + MAPMODE(mode, modechars, 's', SELECTMODE); + MAPMODE(mode, modechars, 'o', OP_PENDING); + MAPMODE(mode, modechars, 'i', INSERT); + MAPMODE(mode, modechars, 'l', LANGMAP); + MAPMODE(mode, modechars, 'c', CMDLINE); +#undef MAPMODE + + retval = map_to_exists_mode((const char *)rhs, mode, abbr); xfree(buf); return retval; } -/* - * Return TRUE if a map exists that has "str" in the rhs for mode "mode". - * Also checks mappings local to the current buffer. - */ -int map_to_exists_mode(char_u *rhs, int mode, int abbr) +/// Check if a map exists that has given string in the rhs +/// +/// Also checks mappings local to the current buffer. +/// +/// @param[in] rhs String which mapping must have in the rhs. Termcap codes +/// are recognized in this argument. +/// @param[in] mode Mode(s) in which mappings are checked. +/// @param[in] abbr true if checking abbreviations in place of mappings. +/// +/// @return true if there is at least one mapping with given parameters. +int map_to_exists_mode(const char *const rhs, const int mode, const bool abbr) { mapblock_T *mp; int hash; - int expand_buffer = FALSE; + bool expand_buffer = false; validate_maphash(); - /* Do it twice: once for global maps and once for local maps. */ - for (;; ) { - for (hash = 0; hash < 256; ++hash) { + // Do it twice: once for global maps and once for local maps. + for (;;) { + for (hash = 0; hash < 256; hash++) { if (abbr) { - if (hash > 0) /* there is only one abbr list */ + if (hash > 0) { // There is only one abbr list. break; - if (expand_buffer) + } + if (expand_buffer) { mp = curbuf->b_first_abbr; - else + } else { mp = first_abbr; - } else if (expand_buffer) + } + } else if (expand_buffer) { mp = curbuf->b_maphash[hash]; - else + } else { mp = maphash[hash]; + } for (; mp; mp = mp->m_next) { if ((mp->m_mode & mode) - && strstr((char *)mp->m_str, (char *)rhs) != NULL) - return TRUE; + && strstr((char *)mp->m_str, rhs) != NULL) { + return true; + } } } - if (expand_buffer) + if (expand_buffer) { break; - expand_buffer = TRUE; + } + expand_buffer = true; } - return FALSE; + return false; } /* @@ -3618,8 +3593,8 @@ int check_abbr(int c, char_u *ptr, int col, int mincol) char_u *q = mp->m_keys; int match; - if (vim_strbyte(mp->m_keys, K_SPECIAL) != NULL) { - /* might have CSI escaped mp->m_keys */ + if (strchr((const char *)mp->m_keys, K_SPECIAL) != NULL) { + // Might have CSI escaped mp->m_keys. q = vim_strsave(mp->m_keys); vim_unescape_csi(q); qlen = (int)STRLEN(q); @@ -3755,8 +3730,10 @@ eval_map_expr ( */ char_u *vim_strsave_escape_csi(char_u *p) { - /* Need a buffer to hold up to three times as much. */ - char_u *res = xmalloc(STRLEN(p) * 3 + 1); + // Need a buffer to hold up to three times as much. Four in case of an + // illegal utf-8 byte: + // 0xc0 -> 0xc3 - 0x80 -> 0xc3 K_SPECIAL KS_SPECIAL KE_FILLER + char_u *res = xmalloc(STRLEN(p) * 4 + 1); char_u *d = res; for (char_u *s = p; *s != NUL; ) { if (s[0] == K_SPECIAL && s[1] != NUL && s[2] != NUL) { @@ -3765,17 +3742,10 @@ char_u *vim_strsave_escape_csi(char_u *p) *d++ = *s++; *d++ = *s++; } else { - int len = mb_char2len(PTR2CHAR(s)); - int len2 = mb_ptr2len(s); - /* Add character, possibly multi-byte to destination, escaping - * CSI and K_SPECIAL. */ + // Add character, possibly multi-byte to destination, escaping + // CSI and K_SPECIAL. Be careful, it can be an illegal byte! d = add_char2buf(PTR2CHAR(s), d); - while (len < len2) { - /* add following combining char */ - d = add_char2buf(PTR2CHAR(s + len), d); - len += mb_char2len(PTR2CHAR(s + len)); - } - mb_ptr_adv(s); + s += MB_CPTR2LEN(s); } } *d = NUL; @@ -3821,8 +3791,7 @@ makemap ( char *cmd; int abbr; int hash; - int did_cpo = FALSE; - int i; + bool did_cpo = false; validate_maphash(); @@ -3950,13 +3919,15 @@ makemap ( /* When outputting <> form, need to make sure that 'cpo' * is set to the Vim default. */ if (!did_cpo) { - if (*mp->m_str == NUL) /* will use <Nop> */ - did_cpo = TRUE; - else - for (i = 0; i < 2; ++i) - for (p = (i ? mp->m_str : mp->m_keys); *p; ++p) - if (*p == K_SPECIAL || *p == NL) - did_cpo = TRUE; + if (*mp->m_str == NUL) { // Will use <Nop>. + did_cpo = true; + } else { + const char specials[] = { (char)(uint8_t)K_SPECIAL, NL, NUL }; + if (strpbrk((const char *)mp->m_str, specials) != NULL + || strpbrk((const char *)mp->m_keys, specials) != NULL) { + did_cpo = true; + } + } if (did_cpo) { if (fprintf(fd, "let s:cpo_save=&cpo") < 0 || put_eol(fd) < 0 @@ -4024,12 +3995,10 @@ int put_escstr(FILE *fd, char_u *strstart, int what) return OK; } - for (; *str != NUL; ++str) { - char_u *p; - - /* Check for a multi-byte character, which may contain escaped - * K_SPECIAL and CSI bytes */ - p = mb_unescape(&str); + for (; *str != NUL; str++) { + // Check for a multi-byte character, which may contain escaped + // K_SPECIAL and CSI bytes. + const char *p = mb_unescape((const char **)&str); if (p != NULL) { while (*p != NUL) if (fputc(*p++, fd) < 0) @@ -4185,8 +4154,7 @@ void add_map(char_u *map, int mode) } // Translate an internal mapping/abbreviation representation into the -// corresponding external one recognized by :map/:abbrev commands; -// respects the current B/k/< settings of 'cpoption'. +// corresponding external one recognized by :map/:abbrev commands. // // This function is called when expanding mappings/abbreviations on the // command-line, and for building the "Ambiguous mapping..." error message. @@ -4206,7 +4174,6 @@ static char_u * translate_mapping ( ga_init(&ga, 1, 40); bool cpo_bslash = !(cpo_flags&FLAG_CPO_BSLASH); - bool cpo_special = !(cpo_flags&FLAG_CPO_SPECI); for (; *str; ++str) { int c = *str; @@ -4219,7 +4186,7 @@ static char_u * translate_mapping ( } if (c == K_SPECIAL && str[1] != NUL && str[2] != NUL) { - if (expmap && cpo_special) { + if (expmap) { ga_clear(&ga); return NULL; } @@ -4230,8 +4197,8 @@ static char_u * translate_mapping ( } str += 2; } - if (IS_SPECIAL(c) || modifiers) { /* special key */ - if (expmap && cpo_special) { + if (IS_SPECIAL(c) || modifiers) { // special key + if (expmap) { ga_clear(&ga); return NULL; } @@ -4241,7 +4208,7 @@ static char_u * translate_mapping ( } if (c == ' ' || c == '\t' || c == Ctrl_J || c == Ctrl_V - || (c == '<' && !cpo_special) || (c == '\\' && !cpo_bslash)) { + || (c == '\\' && !cpo_bslash)) { ga_append(&ga, cpo_bslash ? Ctrl_V : '\\'); } @@ -4263,3 +4230,17 @@ static bool typebuf_match_len(const uint8_t *str, int *mlen) *mlen = i; return str[i] == NUL; // matched the whole string } + +/// Retrieve the mapblock at the index either globally or for a certain buffer +/// +/// @param index The index in the maphash[] +/// @param buf The buffer to get the maphash from. NULL for global +mapblock_T *get_maphash(int index, buf_T *buf) + FUNC_ATTR_PURE +{ + if (index > MAX_MAPHASH) { + return NULL; + } + + return (buf == NULL) ? maphash[index] : buf->b_maphash[index]; +} diff --git a/src/nvim/getchar.h b/src/nvim/getchar.h index bdf65909b6..e634273e0d 100644 --- a/src/nvim/getchar.h +++ b/src/nvim/getchar.h @@ -1,17 +1,25 @@ #ifndef NVIM_GETCHAR_H #define NVIM_GETCHAR_H -/* Values for "noremap" argument of ins_typebuf(). Also used for - * map->m_noremap and menu->noremap[]. */ -#define REMAP_YES 0 /* allow remapping */ -#define REMAP_NONE -1 /* no remapping */ -#define REMAP_SCRIPT -2 /* remap script-local mappings only */ -#define REMAP_SKIP -3 /* no remapping for first char */ +#include "nvim/types.h" +#include "nvim/buffer_defs.h" +#include "nvim/ex_cmds_defs.h" + +/// Values for "noremap" argument of ins_typebuf(). Also used for +/// map->m_noremap and menu->noremap[]. +/// @addtogroup REMAP_VALUES +/// @{ +#define REMAP_YES 0 ///< allow remapping +#define REMAP_NONE -1 ///< no remapping +#define REMAP_SCRIPT -2 ///< remap script-local mappings only +#define REMAP_SKIP -3 ///< no remapping for first char +/// @} #define KEYLEN_PART_KEY -1 /* keylen value for incomplete key-code */ #define KEYLEN_PART_MAP -2 /* keylen value for incomplete mapping */ #define KEYLEN_REMOVED 9999 /* keylen value for removed sequence */ + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "getchar.h.generated.h" #endif diff --git a/src/nvim/gettext.h b/src/nvim/gettext.h new file mode 100644 index 0000000000..aa0e97233e --- /dev/null +++ b/src/nvim/gettext.h @@ -0,0 +1,21 @@ +#ifndef NVIM_GETTEXT_H +#define NVIM_GETTEXT_H + +#ifdef HAVE_WORKING_LIBINTL +# include <libintl.h> +# define _(x) gettext((char *)(x)) +// XXX do we actually need this? +# ifdef gettext_noop +# define N_(x) gettext_noop(x) +# else +# define N_(x) x +# endif +#else +# define _(x) ((char *)(x)) +# define N_(x) x +# define bindtextdomain(x, y) // empty +# define bind_textdomain_codeset(x, y) // empty +# define textdomain(x) // empty +#endif + +#endif // NVIM_GETTEXT_H diff --git a/src/nvim/globals.h b/src/nvim/globals.h index 463f4fcd8d..2ee72cdb6a 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -12,10 +12,7 @@ #include "nvim/syntax_defs.h" #include "nvim/types.h" #include "nvim/event/loop.h" - -/* - * definition of global variables - */ +#include "nvim/os/os_defs.h" #define IOSIZE (1024+1) // file I/O and sprintf buffer size @@ -25,19 +22,6 @@ # define MSG_BUF_CLEN (MSG_BUF_LEN / 6) // cell length (worst case: utf-8 // takes 6 bytes for one cell) -/* - * Maximum length of a path (for non-unix systems) Make it a bit long, to stay - * on the safe side. But not too long to put on the stack. - * TODO(metrix78): Move this to os_defs.h - */ -#ifndef MAXPATHL -# ifdef MAXPATHLEN -# define MAXPATHL MAXPATHLEN -# else -# define MAXPATHL 256 -# endif -#endif - #ifdef WIN32 # define _PATHSEPSTR "\\" #else @@ -108,14 +92,39 @@ typedef enum { * They may have different values when the screen wasn't (re)allocated yet * after setting Rows or Columns (e.g., when starting up). */ - -#define DFLT_COLS 80 /* default value for 'columns' */ -#define DFLT_ROWS 24 /* default value for 'lines' */ - +#define DFLT_COLS 80 // default value for 'columns' +#define DFLT_ROWS 24 // default value for 'lines' EXTERN long Rows INIT(= DFLT_ROWS); // nr of rows in the screen - EXTERN long Columns INIT(= DFLT_COLS); // nr of columns in the screen +// We use 64-bit file functions here, if available. E.g. ftello() returns +// off_t instead of long, which helps if long is 32 bit and off_t is 64 bit. +// We assume that when fseeko() is available then ftello() is too. +// Note that Windows has different function names. +#if (defined(_MSC_VER) && (_MSC_VER >= 1300)) || defined(__MINGW32__) +typedef __int64 off_T; +# ifdef __MINGW32__ +# define vim_lseek lseek64 +# define vim_fseek fseeko64 +# define vim_ftell ftello64 +# else +# define vim_lseek _lseeki64 +# define vim_fseek _fseeki64 +# define vim_ftell _ftelli64 +# endif +#else +typedef off_t off_T; +# ifdef HAVE_FSEEKO +# define vim_lseek lseek +# define vim_ftell ftello +# define vim_fseek fseeko +# else +# define vim_lseek lseek +# define vim_ftell ftell +# define vim_fseek(a, b, c) fseek(a, (long)b, c) +# endif +#endif + /* * The characters and attributes cached for the screen. */ @@ -398,6 +407,9 @@ EXTERN int garbage_collect_at_exit INIT(= FALSE); /* ID of script being sourced or was sourced to define the current function. */ EXTERN scid_T current_SID INIT(= 0); + +EXTERN bool did_source_packages INIT(= false); + // Scope information for the code that indirectly triggered the current // provider function call EXTERN struct caller_scope { @@ -430,79 +442,6 @@ EXTERN int did_check_timestamps INIT(= FALSE); /* did check timestamps recently */ EXTERN int no_check_timestamps INIT(= 0); /* Don't check timestamps */ -/* - * Values for index in highlight_attr[]. - * When making changes, also update HL_FLAGS below! And update the default - * value of 'highlight' in option.c. - */ -typedef enum { - HLF_8 = 0 /* Meta & special keys listed with ":map", text that is - displayed different from what it is */ - , HLF_EOB // after the last line in the buffer - , HLF_TERM // terminal cursor focused - , HLF_TERMNC // terminal cursor unfocused - , HLF_AT // @ characters at end of screen, characters that - // don't really exist in the text - , HLF_D // directories in CTRL-D listing - , HLF_E // error messages - , HLF_I // incremental search - , HLF_L // last search string - , HLF_M // "--More--" message - , HLF_CM // Mode (e.g., "-- INSERT --") - , HLF_N // line number for ":number" and ":#" commands - , HLF_CLN // current line number - , HLF_R // return to continue message and yes/no questions - , HLF_S // status lines - , HLF_SNC // status lines of not-current windows - , HLF_C // column to separate vertically split windows - , HLF_T // Titles for output from ":set all", ":autocmd" etc. - , HLF_V // Visual mode - , HLF_VNC // Visual mode, autoselecting and not clipboard owner - , HLF_W // warning messages - , HLF_WM // Wildmenu highlight - , HLF_FL // Folded line - , HLF_FC // Fold column - , HLF_ADD // Added diff line - , HLF_CHD // Changed diff line - , HLF_DED // Deleted diff line - , HLF_TXD // Text Changed in diff line - , HLF_CONCEAL // Concealed text - , HLF_SC // Sign column - , HLF_SPB // SpellBad - , HLF_SPC // SpellCap - , HLF_SPR // SpellRare - , HLF_SPL // SpellLocal - , HLF_PNI // popup menu normal item - , HLF_PSI // popup menu selected item - , HLF_PSB // popup menu scrollbar - , HLF_PST // popup menu scrollbar thumb - , HLF_TP // tabpage line - , HLF_TPS // tabpage line selected - , HLF_TPF // tabpage line filler - , HLF_CUC // 'cursurcolumn' - , HLF_CUL // 'cursurline' - , HLF_MC // 'colorcolumn' - , HLF_QFL // selected quickfix line - , HLF_COUNT // MUST be the last one -} hlf_T; - -/* The HL_FLAGS must be in the same order as the HLF_ enums! - * When changing this also adjust the default for 'highlight'. */ -#define HL_FLAGS { '8', '~', 'z', 'Z', '@', 'd', 'e', 'i', 'l', 'm', 'M', 'n', \ - 'N', 'r', 's', 'S', 'c', 't', 'v', 'V', 'w', 'W', 'f', 'F', \ - 'A', 'C', 'D', 'T', '-', '>', 'B', 'P', 'R', 'L', '+', '=', \ - 'x', 'X', '*', '#', '_', '!', '.', 'o', 'q' } - -EXTERN int highlight_attr[HLF_COUNT]; /* Highl. attr for each context. */ -EXTERN int highlight_user[9]; /* User[1-9] attributes */ -EXTERN int highlight_stlnc[9]; /* On top of user */ -EXTERN int cterm_normal_fg_color INIT(= 0); -EXTERN int cterm_normal_fg_bold INIT(= 0); -EXTERN int cterm_normal_bg_color INIT(= 0); -EXTERN RgbValue normal_fg INIT(= -1); -EXTERN RgbValue normal_bg INIT(= -1); -EXTERN RgbValue normal_sp INIT(= -1); - EXTERN int autocmd_busy INIT(= FALSE); /* Is apply_autocmds() busy? */ EXTERN int autocmd_no_enter INIT(= FALSE); /* *Enter autocmds disabled */ EXTERN int autocmd_no_leave INIT(= FALSE); /* *Leave autocmds disabled */ @@ -512,9 +451,9 @@ EXTERN int keep_filetype INIT(= FALSE); /* value for did_filetype when starting to execute autocommands */ -/* When deleting the current buffer, another one must be loaded. If we know - * which one is preferred, au_new_curbuf is set to it */ -EXTERN buf_T *au_new_curbuf INIT(= NULL); +// When deleting the current buffer, another one must be loaded. +// If we know which one is preferred, au_new_curbuf is set to it. +EXTERN bufref_T au_new_curbuf INIT(= { NULL, 0, 0 }); // When deleting a buffer/window and autocmd_busy is TRUE, do not free the // buffer/window. but link it in the list starting with @@ -558,6 +497,7 @@ EXTERN int updating_screen INIT(= FALSE); EXTERN win_T *firstwin; /* first window */ EXTERN win_T *lastwin; /* last window */ EXTERN win_T *prevwin INIT(= NULL); /* previous window */ +# define ONE_WINDOW (firstwin == lastwin) /* * When using this macro "break" only breaks out of the inner loop. Use "goto" * to break out of the tabpage loop. @@ -566,7 +506,7 @@ EXTERN win_T *prevwin INIT(= NULL); /* previous window */ FOR_ALL_TABS(tp) \ FOR_ALL_WINDOWS_IN_TAB(wp, tp) -# define FOR_ALL_WINDOWS(wp) for (wp = firstwin; wp != NULL; wp = wp->w_next) +// -V:FOR_ALL_WINDOWS_IN_TAB:501 # define FOR_ALL_WINDOWS_IN_TAB(wp, tp) \ for (win_T *wp = ((tp) == curtab) \ ? firstwin : (tp)->tp_firstwin; wp != NULL; wp = wp->w_next) @@ -602,7 +542,10 @@ EXTERN buf_T *lastbuf INIT(= NULL); // last buffer EXTERN buf_T *curbuf INIT(= NULL); // currently active buffer // Iterates over all buffers in the buffer list. -# define FOR_ALL_BUFFERS(buf) for (buf_T *buf = firstbuf; buf != NULL; buf = buf->b_next) +#define FOR_ALL_BUFFERS(buf) \ + for (buf_T *buf = firstbuf; buf != NULL; buf = buf->b_next) +#define FOR_ALL_BUFFERS_BACKWARDS(buf) \ + for (buf_T *buf = lastbuf; buf != NULL; buf = buf->b_prev) /* Flag that is set when switching off 'swapfile'. It means that all blocks * are to be loaded into memory. Shouldn't be global... */ @@ -840,13 +783,11 @@ EXTERN int ex_no_reprint INIT(= FALSE); /* no need to print after z or p */ EXTERN int Recording INIT(= FALSE); /* TRUE when recording into a reg. */ EXTERN int Exec_reg INIT(= FALSE); /* TRUE when executing a register */ -EXTERN int no_mapping INIT(= FALSE); /* currently no mapping allowed */ -EXTERN int no_zero_mapping INIT(= 0); /* mapping zero not allowed */ -EXTERN int allow_keys INIT(= FALSE); /* allow key codes when no_mapping - * is set */ -EXTERN int no_u_sync INIT(= 0); /* Don't call u_sync() */ -EXTERN int u_sync_once INIT(= 0); /* Call u_sync() once when evaluating - an expression. */ +EXTERN int no_mapping INIT(= false); // currently no mapping allowed +EXTERN int no_zero_mapping INIT(= 0); // mapping zero not allowed +EXTERN int no_u_sync INIT(= 0); // Don't call u_sync() +EXTERN int u_sync_once INIT(= 0); // Call u_sync() once when evaluating + // an expression. EXTERN bool force_restart_edit INIT(= false); // force restart_edit after // ex_normal returns @@ -886,9 +827,16 @@ EXTERN int swap_exists_action INIT(= SEA_NONE); EXTERN int swap_exists_did_quit INIT(= FALSE); /* Selected "quit" at the dialog. */ -EXTERN char_u IObuff[IOSIZE]; /* sprintf's are done in this buffer */ -EXTERN char_u NameBuff[MAXPATHL]; /* buffer for expanding file names */ -EXTERN char_u msg_buf[MSG_BUF_LEN]; /* small buffer for messages */ +EXTERN char_u IObuff[IOSIZE]; ///< Buffer for sprintf, I/O, etc. +EXTERN char_u NameBuff[MAXPATHL]; ///< Buffer for expanding file names +EXTERN char_u msg_buf[MSG_BUF_LEN]; ///< Small buffer for messages +EXTERN char os_buf[ ///< Buffer for the os/ layer +#if MAXPATHL > IOSIZE +MAXPATHL +#else +IOSIZE +#endif +]; /* When non-zero, postpone redrawing. */ EXTERN int RedrawingDisabled INIT(= 0); @@ -953,7 +901,7 @@ EXTERN int did_cursorhold INIT(= false); // set when CursorHold t'gerd // for CursorMoved event EXTERN pos_T last_cursormoved INIT(= INIT_POS_T(0, 0, 0)); -EXTERN int last_changedtick INIT(= 0); // for TextChanged event +EXTERN varnumber_T last_changedtick INIT(= 0); // for TextChanged event EXTERN buf_T *last_changedtick_buf INIT(= NULL); EXTERN int postponed_split INIT(= 0); /* for CTRL-W CTRL-] command */ @@ -986,8 +934,11 @@ EXTERN char_u langmap_mapchar[256]; /* mapping for language keys */ EXTERN int save_p_ls INIT(= -1); /* Save 'laststatus' setting */ EXTERN int save_p_wmh INIT(= -1); /* Save 'winminheight' setting */ EXTERN int wild_menu_showing INIT(= 0); -# define WM_SHOWN 1 /* wildmenu showing */ -# define WM_SCROLLED 2 /* wildmenu showing with scroll */ +enum { + WM_SHOWN = 1, ///< wildmenu showing + WM_SCROLLED = 2, ///< wildmenu showing with scroll + WM_LIST = 3, ///< cmdline CTRL-D +}; EXTERN char breakat_flags[256]; /* which characters are in 'breakat' */ @@ -1124,7 +1075,7 @@ EXTERN char_u e_isadir2[] INIT(= N_("E17: \"%s\" is a directory")); EXTERN char_u e_invjob[] INIT(= N_("E900: Invalid job id")); EXTERN char_u e_jobtblfull[] INIT(= N_("E901: Job table is full")); EXTERN char_u e_jobspawn[] INIT(= N_( - "E903: Process for command \"%s\" could not be spawned")); + "E903: Process failed to start: %s: \"%s\"")); EXTERN char_u e_jobnotpty[] INIT(= N_("E904: Job is not connected to a pty")); EXTERN char_u e_libcall[] INIT(= N_("E364: Library call failed for \"%s()\"")); EXTERN char_u e_mkdir[] INIT(= N_("E739: Cannot create directory %s: %s")); @@ -1150,7 +1101,6 @@ EXTERN char_u e_noprev[] INIT(= N_("E34: No previous command")); EXTERN char_u e_noprevre[] INIT(= N_("E35: No previous regular expression")); EXTERN char_u e_norange[] INIT(= N_("E481: No range allowed")); EXTERN char_u e_noroom[] INIT(= N_("E36: Not enough room")); -EXTERN char_u e_notcreate[] INIT(= N_("E482: Can't create file %s")); EXTERN char_u e_notmp[] INIT(= N_("E483: Can't get temp file name")); EXTERN char_u e_notopen[] INIT(= N_("E484: Can't open file %s")); EXTERN char_u e_notread[] INIT(= N_("E485: Can't read file %s")); @@ -1172,11 +1122,7 @@ EXTERN char_u e_loclist[] INIT(= N_("E776: No location list")); EXTERN char_u e_re_damg[] INIT(= N_("E43: Damaged match string")); EXTERN char_u e_re_corr[] INIT(= N_("E44: Corrupted regexp program")); EXTERN char_u e_readonly[] INIT(= N_( - "E45: 'readonly' option is set (add ! to override)")); -EXTERN char_u e_readonlyvar[] INIT(= N_( - "E46: Cannot change read-only variable \"%s\"")); -EXTERN char_u e_readonlysbx[] INIT(= N_( - "E794: Cannot set variable in the sandbox: \"%s\"")); + "E45: 'readonly' option is set (add ! to override)")); EXTERN char_u e_readerrf[] INIT(= N_("E47: Error while reading errorfile")); EXTERN char_u e_sandbox[] INIT(= N_("E48: Not allowed in sandbox")); EXTERN char_u e_secure[] INIT(= N_("E523: Not allowed here")); @@ -1192,6 +1138,7 @@ EXTERN char_u e_longname[] INIT(= N_("E75: Name too long")); EXTERN char_u e_toomsbra[] INIT(= N_("E76: Too many [")); EXTERN char_u e_toomany[] INIT(= N_("E77: Too many file names")); EXTERN char_u e_trailing[] INIT(= N_("E488: Trailing characters")); +EXTERN char_u e_trailing2[] INIT(= N_("E488: Trailing characters: %s")); EXTERN char_u e_umark[] INIT(= N_("E78: Unknown mark")); EXTERN char_u e_wildexpand[] INIT(= N_("E79: Cannot expand wildcards")); EXTERN char_u e_winheight[] INIT(= N_( @@ -1215,6 +1162,8 @@ EXTERN char_u e_invalidreg[] INIT(= N_("E850: Invalid register name")); EXTERN char_u e_dirnotf[] INIT(= N_( "E919: Directory not found in '%s': \"%s\"")); EXTERN char_u e_unsupportedoption[] INIT(= N_("E519: Option not supported")); +EXTERN char_u e_fnametoolong[] INIT(= N_("E856: Filename too long")); +EXTERN char_u e_float_as_string[] INIT(= N_("E806: using Float as a String")); EXTERN char top_bot_msg[] INIT(= N_("search hit TOP, continuing at BOTTOM")); @@ -1233,8 +1182,6 @@ EXTERN FILE *time_fd INIT(= NULL); /* where to write startup timing */ EXTERN int ignored; EXTERN char *ignoredp; -EXTERN bool in_free_unref_items INIT(= false); - // If a msgpack-rpc channel should be started over stdin/stdout EXTERN bool embedded_mode INIT(= false); @@ -1249,4 +1196,20 @@ typedef enum { kBroken } WorkingStatus; +/// The scope of a working-directory command like `:cd`. +/// +/// Scopes are enumerated from lowest to highest. When adding a scope make sure +/// to update all functions using scopes as well, such as the implementation of +/// `getcwd()`. When using scopes as limits (e.g. in loops) don't use the scopes +/// directly, use `MIN_CD_SCOPE` and `MAX_CD_SCOPE` instead. +typedef enum { + kCdScopeInvalid = -1, + kCdScopeWindow, ///< Affects one window. + kCdScopeTab, ///< Affects one tab page. + kCdScopeGlobal, ///< Affects the entire Nvim instance. +} CdScope; + +#define MIN_CD_SCOPE kCdScopeWindow +#define MAX_CD_SCOPE kCdScopeGlobal + #endif /* NVIM_GLOBALS_H */ diff --git a/src/nvim/hardcopy.c b/src/nvim/hardcopy.c index cb0415a486..abc4773d84 100644 --- a/src/nvim/hardcopy.c +++ b/src/nvim/hardcopy.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + /* * hardcopy.c: printing to paper */ @@ -369,7 +372,6 @@ static void prt_get_attr(int hl_id, prt_text_attr_T *pattr, int modec) { int colorindex; uint32_t fg_color; - char *color; pattr->bold = (highlight_has_attr(hl_id, HL_BOLD, modec) != NULL); pattr->italic = (highlight_has_attr(hl_id, HL_ITALIC, modec) != NULL); @@ -377,11 +379,12 @@ static void prt_get_attr(int hl_id, prt_text_attr_T *pattr, int modec) pattr->undercurl = (highlight_has_attr(hl_id, HL_UNDERCURL, modec) != NULL); { - color = (char *)highlight_color(hl_id, (char_u *)"fg", modec); - if (color == NULL) + const char *color = highlight_color(hl_id, "fg", modec); + if (color == NULL) { colorindex = 0; - else + } else { colorindex = atoi(color); + } if (colorindex >= 0 && colorindex < t_colors) fg_color = prt_get_term_color(colorindex); @@ -845,12 +848,10 @@ static colnr_T hardcopy_line(prt_settings_T *psettings, int page_line, prt_pos_T * Loop over the columns until the end of the file line or right margin. */ for (col = ppos->column; line[col] != NUL && !need_break; col += outputlen) { - outputlen = 1; - if (has_mbyte && (outputlen = (*mb_ptr2len)(line + col)) < 1) + if ((outputlen = (*mb_ptr2len)(line + col)) < 1) { outputlen = 1; - /* - * syntax highlighting stuff. - */ + } + // syntax highlighting stuff. if (psettings->do_syntax) { id = syn_get_id(curwin, ppos->file_line, col, 1, NULL, FALSE); if (id > 0) @@ -1544,8 +1545,8 @@ static int prt_find_resource(char *name, struct prt_ps_resource_S *resource) /* Look for named resource file in runtimepath */ STRCPY(buffer, "print"); add_pathsep((char *)buffer); - vim_strcat(buffer, (char_u *)name, MAXPATHL); - vim_strcat(buffer, (char_u *)".ps", MAXPATHL); + xstrlcat((char *)buffer, name, MAXPATHL); + xstrlcat((char *)buffer, ".ps", MAXPATHL); resource->filename[0] = NUL; retval = (do_in_runtimepath(buffer, 0, prt_resource_name, resource->filename) && resource->filename[0] != NUL); @@ -2578,13 +2579,12 @@ int mch_print_begin(prt_settings_T *psettings) prt_conv.vc_type = CONV_NONE; if (!(enc_canon_props(p_enc) & enc_canon_props(p_encoding) & ENC_8BIT)) { - /* Set up encoding conversion if required */ - if (FAIL == convert_setup(&prt_conv, p_enc, p_encoding)) { - EMSG2(_("E620: Unable to convert to print encoding \"%s\""), - p_encoding); - return FALSE; + // Set up encoding conversion if required + if (convert_setup(&prt_conv, p_enc, p_encoding) == FAIL) { + emsgf(_("E620: Unable to convert to print encoding \"%s\""), + p_encoding); + return false; } - prt_do_conv = TRUE; } prt_do_conv = prt_conv.vc_type != CONV_NONE; diff --git a/src/nvim/hardcopy.h b/src/nvim/hardcopy.h index 4ead8dd5d4..a70b20e6f5 100644 --- a/src/nvim/hardcopy.h +++ b/src/nvim/hardcopy.h @@ -2,6 +2,10 @@ #define NVIM_HARDCOPY_H #include <stdint.h> +#include <stdlib.h> // for size_t + +#include "nvim/types.h" // for char_u +#include "nvim/ex_cmds_defs.h" // for exarg_T /* * Structure to hold printing color and font attributes. diff --git a/src/nvim/hashtab.c b/src/nvim/hashtab.c index 376f33e23e..3397788b00 100644 --- a/src/nvim/hashtab.c +++ b/src/nvim/hashtab.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + /// @file hashtab.c /// /// Handling of a hashtable with Vim-specific properties. @@ -82,22 +85,43 @@ void hash_clear_all(hashtab_T *ht, unsigned int off) /// used for that key. /// WARNING: Returned pointer becomes invalid as soon as the hash table /// is changed in any way. -hashitem_T* hash_find(hashtab_T *ht, char_u *key) +hashitem_T *hash_find(const hashtab_T *const ht, const char_u *const key) { - return hash_lookup(ht, key, hash_hash(key)); + return hash_lookup(ht, (const char *)key, STRLEN(key), hash_hash(key)); +} + +/// Like hash_find, but key is not NUL-terminated +/// +/// @param[in] ht Hashtab to look in. +/// @param[in] key Key of the looked-for item. Must not be NULL. +/// @param[in] len Key length. +/// +/// @return Pointer to the hash item corresponding to the given key. +/// If not found, then return pointer to the empty item that would be +/// used for that key. +/// +/// @warning Returned pointer becomes invalid as soon as the hash table +/// is changed in any way. +hashitem_T *hash_find_len(const hashtab_T *const ht, const char *const key, + const size_t len) +{ + return hash_lookup(ht, key, len, hash_hash_len(key, len)); } /// Like hash_find(), but caller computes "hash". /// -/// @param key The key of the looked-for item. Must not be NULL. -/// @param hash The precomputed hash for the key. +/// @param[in] key The key of the looked-for item. Must not be NULL. +/// @param[in] key_len Key length. +/// @param[in] hash The precomputed hash for the key. /// /// @return Pointer to the hashitem corresponding to the given key. /// If not found, then return pointer to the empty item that would be /// used for that key. /// WARNING: Returned pointer becomes invalid as soon as the hash table /// is changed in any way. -hashitem_T* hash_lookup(hashtab_T *ht, char_u *key, hash_T hash) +hashitem_T *hash_lookup(const hashtab_T *const ht, + const char *const key, const size_t key_len, + const hash_T hash) { #ifdef HT_DEBUG hash_count_lookup++; @@ -117,7 +141,9 @@ hashitem_T* hash_lookup(hashtab_T *ht, char_u *key, hash_T hash) hashitem_T *freeitem = NULL; if (hi->hi_key == HI_KEY_REMOVED) { freeitem = hi; - } else if ((hi->hi_hash == hash) && (STRCMP(hi->hi_key, key) == 0)) { + } else if ((hi->hi_hash == hash) + && (STRNCMP(hi->hi_key, key, key_len) == 0) + && hi->hi_key[key_len] == NUL) { return hi; } @@ -142,7 +168,8 @@ hashitem_T* hash_lookup(hashtab_T *ht, char_u *key, hash_T hash) if ((hi->hi_hash == hash) && (hi->hi_key != HI_KEY_REMOVED) - && (STRCMP(hi->hi_key, key) == 0)) { + && (STRNCMP(hi->hi_key, key, key_len) == 0) + && hi->hi_key[key_len] == NUL) { return hi; } @@ -179,7 +206,7 @@ void hash_debug_results(void) int hash_add(hashtab_T *ht, char_u *key) { hash_T hash = hash_hash(key); - hashitem_T *hi = hash_lookup(ht, key, hash); + hashitem_T *hi = hash_lookup(ht, (const char *)key, STRLEN(key), hash); if (!HASHITEM_EMPTY(hi)) { EMSG2(_(e_intern2), "hash_add()"); return FAIL; @@ -359,13 +386,16 @@ static void hash_may_resize(hashtab_T *ht, size_t minitems) ht->ht_filled = ht->ht_used; } +#define HASH_CYCLE_BODY(hash, p) \ + hash = hash * 101 + *p++ + /// Get the hash number for a key. /// /// If you think you know a better hash function: Compile with HT_DEBUG set and /// run a script that uses hashtables a lot. Vim will then print statistics /// when exiting. Try that with the current hash algorithm and yours. The /// lower the percentage the better. -hash_T hash_hash(char_u *key) +hash_T hash_hash(const char_u *key) { hash_T hash = *key; @@ -375,14 +405,43 @@ hash_T hash_hash(char_u *key) // A simplistic algorithm that appears to do very well. // Suggested by George Reilly. - char_u *p = key + 1; + const uint8_t *p = key + 1; while (*p != NUL) { - hash = hash * 101 + *p++; + HASH_CYCLE_BODY(hash, p); + } + + return hash; +} + +/// Get the hash number for a key that is not a NUL-terminated string +/// +/// @warning Function does not check whether key contains NUL. But you will not +/// be able to get hash entry in this case. +/// +/// @param[in] key Key. +/// @param[in] len Key length. +/// +/// @return Key hash. +hash_T hash_hash_len(const char *key, const size_t len) + FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT +{ + if (len == 0) { + return 0; + } + + hash_T hash = *(uint8_t *)key; + const uint8_t *end = (uint8_t *)key + len; + + const uint8_t *p = (const uint8_t *)key + 1; + while (p < end) { + HASH_CYCLE_BODY(hash, p); } return hash; } +#undef HASH_CYCLE_BODY + /// Function to get HI_KEY_REMOVED value /// /// Used for testing because luajit ffi does not allow getting addresses of diff --git a/src/nvim/hashtab.h b/src/nvim/hashtab.h index 0da2b13f2e..973b97d476 100644 --- a/src/nvim/hashtab.h +++ b/src/nvim/hashtab.h @@ -70,6 +70,25 @@ typedef struct hashtable_S { hashitem_T ht_smallarray[HT_INIT_SIZE]; /// initial array } hashtab_T; +/// Iterate over a hashtab +/// +/// @param[in] ht Hashtab to iterate over. +/// @param hi Name of the variable with current hashtab entry. +/// @param code Cycle body. +#define HASHTAB_ITER(ht, hi, code) \ + do { \ + hashtab_T *const hi##ht_ = (ht); \ + size_t hi##todo_ = hi##ht_->ht_used; \ + for (hashitem_T *hi = hi##ht_->ht_array; hi##todo_; hi++) { \ + if (!HASHITEM_EMPTY(hi)) { \ + { \ + code \ + } \ + hi##todo_--; \ + } \ + } \ + } while (0) + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "hashtab.h.generated.h" #endif diff --git a/src/nvim/highlight_defs.h b/src/nvim/highlight_defs.h new file mode 100644 index 0000000000..927fc94bbe --- /dev/null +++ b/src/nvim/highlight_defs.h @@ -0,0 +1,126 @@ +#ifndef NVIM_HIGHLIGHT_DEFS_H +#define NVIM_HIGHLIGHT_DEFS_H + +#include <inttypes.h> + +#include "nvim/macros.h" + +typedef int32_t RgbValue; + +/// Values for index in highlight_attr[]. +/// When making changes, also update hlf_names below! +typedef enum { + HLF_8 = 0 // Meta & special keys listed with ":map", text that is + // displayed different from what it is + , HLF_EOB // after the last line in the buffer + , HLF_TERM // terminal cursor focused + , HLF_TERMNC // terminal cursor unfocused + , HLF_AT // @ characters at end of screen, characters that + // don't really exist in the text + , HLF_D // directories in CTRL-D listing + , HLF_E // error messages + , HLF_I // incremental search + , HLF_L // last search string + , HLF_M // "--More--" message + , HLF_CM // Mode (e.g., "-- INSERT --") + , HLF_N // line number for ":number" and ":#" commands + , HLF_CLN // current line number + , HLF_R // return to continue message and yes/no questions + , HLF_S // status lines + , HLF_SNC // status lines of not-current windows + , HLF_C // column to separate vertically split windows + , HLF_T // Titles for output from ":set all", ":autocmd" etc. + , HLF_V // Visual mode + , HLF_VNC // Visual mode, autoselecting and not clipboard owner + , HLF_W // warning messages + , HLF_WM // Wildmenu highlight + , HLF_FL // Folded line + , HLF_FC // Fold column + , HLF_ADD // Added diff line + , HLF_CHD // Changed diff line + , HLF_DED // Deleted diff line + , HLF_TXD // Text Changed in diff line + , HLF_SC // Sign column + , HLF_CONCEAL // Concealed text + , HLF_SPB // SpellBad + , HLF_SPC // SpellCap + , HLF_SPR // SpellRare + , HLF_SPL // SpellLocal + , HLF_PNI // popup menu normal item + , HLF_PSI // popup menu selected item + , HLF_PSB // popup menu scrollbar + , HLF_PST // popup menu scrollbar thumb + , HLF_TP // tabpage line + , HLF_TPS // tabpage line selected + , HLF_TPF // tabpage line filler + , HLF_CUC // 'cursurcolumn' + , HLF_CUL // 'cursurline' + , HLF_MC // 'colorcolumn' + , HLF_QFL // selected quickfix line + , HLF_0 // Whitespace + , HLF_INACTIVE // NormalNC: Normal text in non-current windows + , HLF_COUNT // MUST be the last one +} hlf_T; + +EXTERN const char *hlf_names[] INIT(= { + [HLF_8] = "SpecialKey", + [HLF_EOB] = "EndOfBuffer", + [HLF_TERM] = "TermCursor", + [HLF_TERMNC] = "TermCursorNC", + [HLF_AT] = "NonText", + [HLF_D] = "Directory", + [HLF_E] = "ErrorMsg", + [HLF_I] = "IncSearch", + [HLF_L] = "Search", + [HLF_M] = "MoreMsg", + [HLF_CM] = "ModeMsg", + [HLF_N] = "LineNr", + [HLF_CLN] = "CursorLineNr", + [HLF_R] = "Question", + [HLF_S] = "StatusLine", + [HLF_SNC] = "StatusLineNC", + [HLF_C] = "VertSplit", + [HLF_T] = "Title", + [HLF_V] = "Visual", + [HLF_VNC] = "VisualNC", + [HLF_W] = "WarningMsg", + [HLF_WM] = "WildMenu", + [HLF_FL] = "Folded", + [HLF_FC] = "FoldColumn", + [HLF_ADD] = "DiffAdd", + [HLF_CHD] = "DiffChange", + [HLF_DED] = "DiffDelete", + [HLF_TXD] = "DiffText", + [HLF_SC] = "SignColumn", + [HLF_CONCEAL] = "Conceal", + [HLF_SPB] = "SpellBad", + [HLF_SPC] = "SpellCap", + [HLF_SPR] = "SpellRare", + [HLF_SPL] = "SpellLocal", + [HLF_PNI] = "Pmenu", + [HLF_PSI] = "PmenuSel", + [HLF_PSB] = "PmenuSbar", + [HLF_PST] = "PmenuThumb", + [HLF_TP] = "TabLine", + [HLF_TPS] = "TabLineSel", + [HLF_TPF] = "TabLineFill", + [HLF_CUC] = "CursorColumn", + [HLF_CUL] = "CursorLine", + [HLF_MC] = "ColorColumn", + [HLF_QFL] = "QuickFixLine", + [HLF_0] = "Whitespace", + [HLF_INACTIVE] = "NormalNC" +}); + + +EXTERN int highlight_attr[HLF_COUNT]; // Highl. attr for each context. +EXTERN int highlight_user[9]; // User[1-9] attributes +EXTERN int highlight_stlnc[9]; // On top of user +EXTERN int cterm_normal_fg_color INIT(= 0); +EXTERN int cterm_normal_fg_bold INIT(= 0); +EXTERN int cterm_normal_bg_color INIT(= 0); +EXTERN RgbValue normal_fg INIT(= -1); +EXTERN RgbValue normal_bg INIT(= -1); +EXTERN RgbValue normal_sp INIT(= -1); + +#endif // NVIM_HIGHLIGHT_DEFS_H diff --git a/src/nvim/iconv.h b/src/nvim/iconv.h index bf29b15247..d7234090c4 100644 --- a/src/nvim/iconv.h +++ b/src/nvim/iconv.h @@ -10,9 +10,7 @@ // USE_ICONV, or to put the USE_ICONV definition in config.h.in directly. As // it stands, globals.h needs to be included alongside iconv.h. -#ifdef HAVE_CONFIG_H -# include "auto/config.h" -#endif +#include "auto/config.h" // Use iconv() when it's available, either by linking to the library at // compile time or by loading it at runtime. diff --git a/src/nvim/if_cscope.c b/src/nvim/if_cscope.c index 0b20647771..0f9ecdf2d7 100644 --- a/src/nvim/if_cscope.c +++ b/src/nvim/if_cscope.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + /* * CSCOPE support for Vim added by Andy Kahn <kahn@zk3.dec.com> * Ported to Win32 by Sergey Khorev <sergey.khorev@gmail.com> @@ -140,44 +143,39 @@ char_u *get_cscope_name(expand_T *xp, int idx) /* * Handle command line completion for :cscope command. */ -void set_context_in_cscope_cmd(expand_T *xp, char_u *arg, cmdidx_T cmdidx) +void set_context_in_cscope_cmd(expand_T *xp, const char *arg, cmdidx_T cmdidx) { - char_u *p; - - /* Default: expand subcommands */ + // Default: expand subcommands. xp->xp_context = EXPAND_CSCOPE; - xp->xp_pattern = arg; - expand_what = (cmdidx == CMD_scscope) - ? EXP_SCSCOPE_SUBCMD : EXP_CSCOPE_SUBCMD; + xp->xp_pattern = (char_u *)arg; + expand_what = ((cmdidx == CMD_scscope) + ? EXP_SCSCOPE_SUBCMD : EXP_CSCOPE_SUBCMD); /* (part of) subcommand already typed */ if (*arg != NUL) { - p = skiptowhite(arg); - if (*p != NUL) { /* past first word */ - xp->xp_pattern = skipwhite(p); - if (*skiptowhite(xp->xp_pattern) != NUL) + const char *p = (const char *)skiptowhite((const char_u *)arg); + if (*p != NUL) { // Past first word. + xp->xp_pattern = skipwhite((const char_u *)p); + if (*skiptowhite(xp->xp_pattern) != NUL) { xp->xp_context = EXPAND_NOTHING; - else if (STRNICMP(arg, "add", p - arg) == 0) + } else if (STRNICMP(arg, "add", p - arg) == 0) { xp->xp_context = EXPAND_FILES; - else if (STRNICMP(arg, "kill", p - arg) == 0) + } else if (STRNICMP(arg, "kill", p - arg) == 0) { expand_what = EXP_CSCOPE_KILL; - else if (STRNICMP(arg, "find", p - arg) == 0) + } else if (STRNICMP(arg, "find", p - arg) == 0) { expand_what = EXP_CSCOPE_FIND; - else + } else { xp->xp_context = EXPAND_NOTHING; + } } } } -/* - * PRIVATE: do_cscope_general - * - * Find the command, print help if invalid, and then call the corresponding - * command function. - */ -static void -do_cscope_general ( +/// Find the command, print help if invalid, and then call the corresponding +/// command function. +static void +do_cscope_general( exarg_T *eap, int make_split /* whether to split window */ ) @@ -206,29 +204,20 @@ do_cscope_general ( postponed_split_tab = 0; } -/* - * PUBLIC: do_cscope - */ -void do_cscope(exarg_T *eap) +/// Implementation of ":cscope" and ":lcscope" +void ex_cscope(exarg_T *eap) { do_cscope_general(eap, FALSE); } -/* - * PUBLIC: do_scscope - * - * same as do_cscope, but splits window, too. - */ -void do_scscope(exarg_T *eap) +/// Implementation of ":scscope". Same as ex_cscope(), but splits window, too. +void ex_scscope(exarg_T *eap) { do_cscope_general(eap, TRUE); } -/* - * PUBLIC: do_cstag - * - */ -void do_cstag(exarg_T *eap) +/// Implementation of ":cstag" +void ex_cstag(exarg_T *eap) { int ret = FALSE; @@ -283,18 +272,13 @@ void do_cstag(exarg_T *eap) (void)EMSG(_("E257: cstag: tag not found")); g_do_tagpreview = 0; } - -} /* do_cscope */ +} -/* - * PUBLIC: cs_find - * - * this simulates a vim_fgets(), but for cscope, returns the next line - * from the cscope output. should only be called from find_tags() - * - * returns TRUE if eof, FALSE otherwise - */ +/// This simulates a vim_fgets(), but for cscope, returns the next line +/// from the cscope output. should only be called from find_tags() +/// +/// @return TRUE if eof, FALSE otherwise int cs_fgets(char_u *buf, int size) { char *p; @@ -307,21 +291,13 @@ int cs_fgets(char_u *buf, int size) } /* cs_fgets */ -/* - * PUBLIC: cs_free_tags - * - * called only from do_tag(), when popping the tag stack - */ +/// Called only from do_tag(), when popping the tag stack. void cs_free_tags(void) { cs_manage_matches(NULL, NULL, 0, Free); } -/* - * PUBLIC: cs_print_tags - * - * called from do_tag() - */ +/// Called from do_tag(). void cs_print_tags(void) { cs_manage_matches(NULL, NULL, 0, Print); @@ -402,14 +378,8 @@ int cs_connection(int num, char_u *dbpath, char_u *ppath) * PRIVATE functions ****************************************************************************/ -/* - * PRIVATE: cs_add - * - * add cscope database or a directory name (to look for cscope.out) - * to the cscope connection list - * - * MAXPATHL 256 - */ +/// Add cscope database or a directory name (to look for cscope.out) +/// to the cscope connection list. static int cs_add(exarg_T *eap) { char *fname, *ppath, *flags = NULL; @@ -435,17 +405,13 @@ static void cs_stat_emsg(char *fname) } -/* - * PRIVATE: cs_add_common - * - * the common routine to add a new cscope connection. called by - * cs_add() and cs_reset(). i really don't like to do this, but this - * routine uses a number of goto statements. - */ -static int -cs_add_common ( - char *arg1, /* filename - may contain environment variables */ - char *arg2, /* prepend path - may contain environment variables */ +/// The common routine to add a new cscope connection. Called by +/// cs_add() and cs_reset(). I really don't like to do this, but this +/// routine uses a number of goto statements. +static int +cs_add_common( + char *arg1, // filename - may contain environment variables + char *arg2, // prepend path - may contain environment variables char *flags ) { @@ -559,11 +525,7 @@ static int cs_check_for_tags(void) return p_tags[0] != NUL && curbuf->b_p_tags != NULL; } /* cs_check_for_tags */ -/* - * PRIVATE: cs_cnt_connections - * - * count the number of cscope connections - */ +/// Count the number of cscope connections. static size_t cs_cnt_connections(void) { size_t cnt = 0; @@ -583,11 +545,7 @@ static void cs_reading_emsg( } #define CSREAD_BUFSIZE 2048 -/* - * PRIVATE: cs_cnt_matches - * - * count the number of matches for a given cscope connection. - */ +/// Count the number of matches for a given cscope connection. static int cs_cnt_matches(size_t idx) { char *stok; @@ -637,11 +595,7 @@ static int cs_cnt_matches(size_t idx) } /* cs_cnt_matches */ -/* - * PRIVATE: cs_create_cmd - * - * Creates the actual cscope command query from what the user entered. - */ +/// Creates the actual cscope command query from what the user entered. static char *cs_create_cmd(char *csoption, char *pattern) { char *cmd; @@ -697,12 +651,8 @@ static char *cs_create_cmd(char *csoption, char *pattern) } /* cs_create_cmd */ -/* - * PRIVATE: cs_create_connection - * - * This piece of code was taken/adapted from nvi. do we need to add - * the BSD license notice? - */ +/// This piece of code was taken/adapted from nvi. do we need to add +/// the BSD license notice? static int cs_create_connection(size_t i) { #ifdef UNIX @@ -891,14 +841,10 @@ err_closing: } /* cs_create_connection */ -/* - * PRIVATE: cs_find - * - * query cscope using command line interface. parse the output and use tselect - * to allow choices. like Nvi, creates a pipe to send to/from query/cscope. - * - * returns TRUE if we jump to a tag or abort, FALSE if not. - */ +/// Query cscope using command line interface. Parse the output and use tselect +/// to allow choices. Like Nvi, creates a pipe to send to/from query/cscope. +/// +/// @return TRUE if we jump to a tag or abort, FALSE if not. static int cs_find(exarg_T *eap) { char *opt, *pat; @@ -932,11 +878,7 @@ static int cs_find(exarg_T *eap) } /* cs_find */ -/* - * PRIVATE: cs_find_common - * - * common code for cscope find, shared by cs_find() and do_cstag() - */ +/// Common code for cscope find, shared by cs_find() and ex_cstag(). static int cs_find_common(char *opt, char *pat, int forceit, int verbose, int use_ll, char_u *cmdline) { @@ -994,11 +936,12 @@ static int cs_find_common(char *opt, char *pat, int forceit, int verbose, return FALSE; } - if (*qfpos != '0') { - apply_autocmds(EVENT_QUICKFIXCMDPRE, (char_u *)"cscope", - curbuf->b_fname, TRUE, curbuf); - if (did_throw || force_abort) - return FALSE; + if (*qfpos != '0' + && apply_autocmds(EVENT_QUICKFIXCMDPRE, (char_u *)"cscope", + curbuf->b_fname, true, curbuf)) { + if (aborting()) { + return false; + } } } @@ -1108,11 +1051,7 @@ static int cs_find_common(char *opt, char *pat, int forceit, int verbose, } /* cs_find_common */ -/* - * PRIVATE: cs_help - * - * print help - */ +/// Print help. static int cs_help(exarg_T *eap) { cscmd_T *cmdp = cs_cmds; @@ -1160,11 +1099,7 @@ static void clear_csinfo(size_t i) csinfo[i].to_fp = NULL; } -/* - * PRIVATE: cs_insert_filelist - * - * insert a new cscope database filename into the filelist - */ +/// Insert a new cscope database filename into the filelist. static int cs_insert_filelist(char *fname, char *ppath, char *flags, FileInfo *file_info) { @@ -1224,11 +1159,7 @@ static int cs_insert_filelist(char *fname, char *ppath, char *flags, } /* cs_insert_filelist */ -/* - * PRIVATE: cs_lookup_cmd - * - * find cscope command in command table - */ +/// Find cscope command in command table. static cscmd_T * cs_lookup_cmd(exarg_T *eap) { cscmd_T *cmdp; @@ -1253,11 +1184,7 @@ static cscmd_T * cs_lookup_cmd(exarg_T *eap) } /* cs_lookup_cmd */ -/* - * PRIVATE: cs_kill - * - * nuke em - */ +/// Nuke em. static int cs_kill(exarg_T *eap) { char *stok; @@ -1294,9 +1221,10 @@ static int cs_kill(exarg_T *eap) } } - if (i >= csinfo_size || csinfo[i].fname == NULL) { - if (p_csverbose) + if (!killall && (i >= csinfo_size || csinfo[i].fname == NULL)) { + if (p_csverbose) { (void)EMSG2(_("E261: cscope connection %s not found"), stok); + } return CSCOPE_FAILURE; } else { if (killall) { @@ -1313,11 +1241,7 @@ static int cs_kill(exarg_T *eap) } /* cs_kill */ -/* - * PRIVATE: cs_kill_execute - * - * Actually kills a specific cscope connection. - */ +/// Actually kills a specific cscope connection. static void cs_kill_execute( size_t i, /* cscope table index */ char *cname /* cscope database name */ @@ -1332,26 +1256,22 @@ static void cs_kill_execute( } -/* - * PRIVATE: cs_make_vim_style_matches - * - * convert the cscope output into a ctags style entry (as might be found - * in a ctags tags file). there's one catch though: cscope doesn't tell you - * the type of the tag you are looking for. for example, in Darren Hiebert's - * ctags (the one that comes with vim), #define's use a line number to find the - * tag in a file while function definitions use a regexp search pattern. - * - * i'm going to always use the line number because cscope does something - * quirky (and probably other things i don't know about): - * - * if you have "# define" in your source file, which is - * perfectly legal, cscope thinks you have "#define". this - * will result in a failed regexp search. :( - * - * besides, even if this particular case didn't happen, the search pattern - * would still have to be modified to escape all the special regular expression - * characters to comply with ctags formatting. - */ +/// Convert the cscope output into a ctags style entry (as might be found +/// in a ctags tags file). there's one catch though: cscope doesn't tell you +/// the type of the tag you are looking for. for example, in Darren Hiebert's +/// ctags (the one that comes with vim), #define's use a line number to find the +/// tag in a file while function definitions use a regexp search pattern. +/// +/// I'm going to always use the line number because cscope does something +/// quirky (and probably other things i don't know about): +/// +/// if you have "# define" in your source file, which is +/// perfectly legal, cscope thinks you have "#define". this +/// will result in a failed regexp search. :( +/// +/// Besides, even if this particular case didn't happen, the search pattern +/// would still have to be modified to escape all the special regular expression +/// characters to comply with ctags formatting. static char *cs_make_vim_style_matches(char *fname, char *slno, char *search, char *tagstr) { @@ -1385,24 +1305,20 @@ static char *cs_make_vim_style_matches(char *fname, char *slno, char *search, } /* cs_make_vim_style_matches */ -/* - * PRIVATE: cs_manage_matches - * - * this is kind of hokey, but i don't see an easy way round this.. - * - * Store: keep a ptr to the (malloc'd) memory of matches originally - * generated from cs_find(). the matches are originally lines directly - * from cscope output, but transformed to look like something out of a - * ctags. see cs_make_vim_style_matches for more details. - * - * Get: used only from cs_fgets(), this simulates a vim_fgets() to return - * the next line from the cscope output. it basically keeps track of which - * lines have been "used" and returns the next one. - * - * Free: frees up everything and resets - * - * Print: prints the tags - */ +/// This is kind of hokey, but i don't see an easy way round this. +/// +/// Store: keep a ptr to the (malloc'd) memory of matches originally +/// generated from cs_find(). the matches are originally lines directly +/// from cscope output, but transformed to look like something out of a +/// ctags. see cs_make_vim_style_matches for more details. +/// +/// Get: used only from cs_fgets(), this simulates a vim_fgets() to return +/// the next line from the cscope output. it basically keeps track of which +/// lines have been "used" and returns the next one. +/// +/// Free: frees up everything and resets +/// +/// Print: prints the tags static char *cs_manage_matches(char **matches, char **contexts, size_t totmatches, mcmd_e cmd) { @@ -1457,11 +1373,7 @@ static char *cs_manage_matches(char **matches, char **contexts, } /* cs_manage_matches */ -/* - * PRIVATE: cs_parse_results - * - * parse cscope output - */ +/// Parse cscope output. static char *cs_parse_results(size_t cnumber, char *buf, int bufsize, char **context, char **linenumber, char **search) { @@ -1511,11 +1423,7 @@ static char *cs_parse_results(size_t cnumber, char *buf, int bufsize, return name; } -/* - * PRIVATE: cs_file_results - * - * write cscope find results to file - */ +/// Write cscope find results to file. static void cs_file_results(FILE *f, int *nummatches_a) { char *search, *slno; @@ -1556,13 +1464,9 @@ static void cs_file_results(FILE *f, int *nummatches_a) xfree(buf); } -/* - * PRIVATE: cs_fill_results - * - * get parsed cscope output and calls cs_make_vim_style_matches to convert - * into ctags format - * When there are no matches sets "*matches_p" to NULL. - */ +/// Get parsed cscope output and calls cs_make_vim_style_matches to convert +/// into ctags format. +/// When there are no matches sets "*matches_p" to NULL. static void cs_fill_results(char *tagstr, size_t totmatches, int *nummatches_a, char ***matches_p, char ***cntxts_p, size_t *matched) @@ -1754,11 +1658,7 @@ static void cs_print_tags_priv(char **matches, char **cntxts, xfree(buf); } -/* - * PRIVATE: cs_read_prompt - * - * read a cscope prompt (basically, skip over the ">> ") - */ +/// Read a cscope prompt (basically, skip over the ">> "). static int cs_read_prompt(size_t i) { int ch; @@ -1843,12 +1743,8 @@ static void sig_handler(int s) { #endif -/* - * PRIVATE: cs_release_csp - * - * Does the actual free'ing for the cs ptr with an optional flag of whether - * or not to free the filename. Called by cs_kill and cs_reset. - */ +/// Does the actual free'ing for the cs ptr with an optional flag of whether +/// or not to free the filename. Called by cs_kill and cs_reset. static void cs_release_csp(size_t i, int freefnpp) { // Trying to exit normally (not sure whether it is fit to Unix cscope) @@ -1960,15 +1856,11 @@ static void cs_release_csp(size_t i, int freefnpp) } /* cs_release_csp */ -/* - * PRIVATE: cs_reset - * - * calls cs_kill on all cscope connections then reinits - */ +/// Calls cs_kill on all cscope connections then reinits. static int cs_reset(exarg_T *eap) { char **dblist = NULL, **pplist = NULL, **fllist = NULL; - char buf[20]; /* for snprintf " (#%zu)" */ + char buf[25]; // for snprintf " (#%zu)" if (csinfo_size == 0) return CSCOPE_SUCCESS; @@ -2007,23 +1899,20 @@ static int cs_reset(exarg_T *eap) xfree(pplist); xfree(fllist); - if (p_csverbose) - MSG_ATTR(_("All cscope databases reset"), hl_attr(HLF_R) | MSG_HIST); + if (p_csverbose) { + msg_attr(_("All cscope databases reset"), hl_attr(HLF_R) | MSG_HIST); + } return CSCOPE_SUCCESS; } /* cs_reset */ -/* - * PRIVATE: cs_resolve_file - * - * Construct the full pathname to a file found in the cscope database. - * (Prepends ppath, if there is one and if it's not already prepended, - * otherwise just uses the name found.) - * - * We need to prepend the prefix because on some cscope's (e.g., the one that - * ships with Solaris 2.6), the output never has the prefix prepended. - * Contrast this with my development system (Digital Unix), which does. - */ +/// Construct the full pathname to a file found in the cscope database. +/// (Prepends ppath, if there is one and if it's not already prepended, +/// otherwise just uses the name found.) +/// +/// We need to prepend the prefix because on some cscope's (e.g., the one that +/// ships with Solaris 2.6), the output never has the prefix prepended. +/// Contrast this with my development system (Digital Unix), which does. static char *cs_resolve_file(size_t i, char *name) { char *fullname; @@ -2069,11 +1958,7 @@ static char *cs_resolve_file(size_t i, char *name) } -/* - * PRIVATE: cs_show - * - * show all cscope connections - */ +/// Show all cscope connections. static int cs_show(exarg_T *eap) { if (cs_cnt_connections() == 0) @@ -2101,11 +1986,7 @@ static int cs_show(exarg_T *eap) } /* cs_show */ -/* - * PUBLIC: cs_end - * - * Only called when VIM exits to quit any cscope sessions. - */ +/// Only called when VIM exits to quit any cscope sessions. void cs_end(void) { for (size_t i = 0; i < csinfo_size; i++) diff --git a/src/nvim/if_cscope.h b/src/nvim/if_cscope.h index 351d9caef6..e20462576a 100644 --- a/src/nvim/if_cscope.h +++ b/src/nvim/if_cscope.h @@ -1,6 +1,9 @@ #ifndef NVIM_IF_CSCOPE_H #define NVIM_IF_CSCOPE_H +#include "nvim/types.h" // for char_u and expand_T +#include "nvim/ex_cmds_defs.h" // for exarg_T + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "if_cscope.h.generated.h" #endif diff --git a/src/nvim/if_cscope_defs.h b/src/nvim/if_cscope_defs.h index f9d06eaea3..fa18866840 100644 --- a/src/nvim/if_cscope_defs.h +++ b/src/nvim/if_cscope_defs.h @@ -18,6 +18,7 @@ #include "nvim/os/os_defs.h" #include "nvim/os/fs_defs.h" +#include "nvim/ex_cmds_defs.h" #define CSCOPE_SUCCESS 0 #define CSCOPE_FAILURE -1 diff --git a/src/nvim/indent.c b/src/nvim/indent.c index 7f31bb8c5c..efca739c2d 100644 --- a/src/nvim/indent.c +++ b/src/nvim/indent.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #include <assert.h> #include <inttypes.h> #include <stdbool.h> @@ -7,6 +10,7 @@ #include "nvim/eval.h" #include "nvim/charset.h" #include "nvim/cursor.h" +#include "nvim/mark.h" #include "nvim/memline.h" #include "nvim/memory.h" #include "nvim/misc1.h" @@ -467,7 +471,7 @@ int get_breakindent_win(win_T *wp, char_u *line) { || prev_tick != wp->w_buffer->b_changedtick) { prev_line = line; prev_ts = wp->w_buffer->b_p_ts; - prev_tick = wp->w_buffer->b_changedtick; + prev_tick = (int)wp->w_buffer->b_changedtick; prev_indent = get_indent_str(line, (int)wp->w_buffer->b_p_ts, wp->w_p_list); } @@ -534,7 +538,7 @@ int get_expr_indent(void) sandbox++; } textlock++; - indent = eval_to_number(curbuf->b_p_inde); + indent = (int)eval_to_number(curbuf->b_p_inde); if (use_sandbox) { sandbox--; @@ -598,7 +602,7 @@ int get_lisp_indent(void) paren = *pos; pos = findmatch(NULL, '['); - if ((pos == NULL) || ltp(pos, &paren)) { + if ((pos == NULL) || lt(*pos, paren)) { pos = &paren; } } diff --git a/src/nvim/indent_c.c b/src/nvim/indent_c.c index 6f03cf6037..4a6393ac36 100644 --- a/src/nvim/indent_c.c +++ b/src/nvim/indent_c.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #include <assert.h> #include <inttypes.h> #include <stdint.h> @@ -10,6 +13,7 @@ #include "nvim/edit.h" #include "nvim/indent.h" #include "nvim/indent_c.h" +#include "nvim/mark.h" #include "nvim/memline.h" #include "nvim/memory.h" #include "nvim/option.h" @@ -173,9 +177,8 @@ static char_u *skip_string(char_u *p) char_u *delim = p + 2; char_u *paren = vim_strchr(delim, '('); - if (paren != NULL) - { - long delim_len = paren - delim; + if (paren != NULL) { + const ptrdiff_t delim_len = paren - delim; for (p += 3; *p; ++p) if (p[0] == ')' && STRNCMP(p + 1, delim, delim_len) == 0 @@ -512,34 +515,41 @@ int cin_isscopedecl(char_u *s) /* Maximum number of lines to search back for a "namespace" line. */ #define FIND_NAMESPACE_LIM 20 -/* - * Recognize a "namespace" scope declaration. - */ -static int cin_is_cpp_namespace(char_u *s) +// Recognize a "namespace" scope declaration. +static bool cin_is_cpp_namespace(char_u *s) { - char_u *p; - int has_name = FALSE; + char_u *p; + bool has_name = false; + bool has_name_start = false; s = cin_skipcomment(s); if (STRNCMP(s, "namespace", 9) == 0 && (s[9] == NUL || !vim_iswordc(s[9]))) { p = cin_skipcomment(skipwhite(s + 9)); while (*p != NUL) { if (ascii_iswhite(*p)) { - has_name = TRUE; /* found end of a name */ + has_name = true; // found end of a name p = cin_skipcomment(skipwhite(p)); } else if (*p == '{') { break; } else if (vim_iswordc(*p)) { - if (has_name) - return FALSE; /* word character after skipping past name */ - ++p; + has_name_start = true; + if (has_name) { + return false; // word character after skipping past name + } + p++; + } else if (p[0] == ':' && p[1] == ':' && vim_iswordc(p[2])) { + if (!has_name_start || has_name) { + return false; + } + // C++ 17 nested namespace + p += 3; } else { - return FALSE; + return false; } } - return TRUE; + return true; } - return FALSE; + return false; } /* @@ -819,21 +829,22 @@ cin_isterminated ( return found_start; } -/* - * Recognize the basic picture of a function declaration -- it needs to - * have an open paren somewhere and a close paren at the end of the line and - * no semicolons anywhere. - * When a line ends in a comma we continue looking in the next line. - * "sp" points to a string with the line. When looking at other lines it must - * be restored to the line. When it's NULL fetch lines here. - * "lnum" is where we start looking. - * "min_lnum" is the line before which we will not be looking. - */ +/// Recognizes the basic picture of a function declaration -- it needs to +/// have an open paren somewhere and a close paren at the end of the line and +/// no semicolons anywhere. +/// When a line ends in a comma we continue looking in the next line. +/// +/// @param[in] sp Points to a string with the line. When looking at other +/// lines it must be restored to the line. When it's NULL fetch +/// lines here. +/// @param[in] first_lnum Where to start looking. +/// @param[in] min_lnum The line before which we will not be looking. static int cin_isfuncdecl(char_u **sp, linenr_T first_lnum, linenr_T min_lnum) { char_u *s; linenr_T lnum = first_lnum; - int retval = FALSE; + linenr_T save_lnum = curwin->w_cursor.lnum; + int retval = false; pos_T *trypos; int just_started = TRUE; @@ -842,18 +853,22 @@ static int cin_isfuncdecl(char_u **sp, linenr_T first_lnum, linenr_T min_lnum) else s = *sp; + curwin->w_cursor.lnum = lnum; if (find_last_paren(s, '(', ')') && (trypos = find_match_paren(curbuf->b_ind_maxparen)) != NULL) { lnum = trypos->lnum; - if (lnum < min_lnum) - return FALSE; - + if (lnum < min_lnum) { + curwin->w_cursor.lnum = save_lnum; + return false; + } s = ml_get(lnum); } - /* Ignore line starting with #. */ - if (cin_ispreproc(s)) - return FALSE; + curwin->w_cursor.lnum = save_lnum; + // Ignore line starting with #. + if (cin_ispreproc(s)) { + return false; + } while (*s && *s != '(' && *s != ';' && *s != '\'' && *s != '"') { // ignore comments diff --git a/src/nvim/keymap.c b/src/nvim/keymap.c index 99e94fc60f..3d7ebb6382 100644 --- a/src/nvim/keymap.c +++ b/src/nvim/keymap.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #include <assert.h> #include <inttypes.h> #include <limits.h> @@ -490,17 +493,19 @@ char_u *get_special_key_name(int c, int modifiers) /// @param[out] dst Location where translation result will be kept. Must have /// at least six bytes. /// @param[in] keycode Prefer key code, e.g. K_DEL in place of DEL. +/// @param[in] in_string Inside a double quoted string /// /// @return Number of characters added to dst, zero for no match. unsigned int trans_special(const char_u **srcp, const size_t src_len, - char_u *const dst, const bool keycode) + char_u *const dst, const bool keycode, + const bool in_string) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT { int modifiers = 0; int key; unsigned int dlen = 0; - key = find_special_key(srcp, src_len, &modifiers, keycode, false); + key = find_special_key(srcp, src_len, &modifiers, keycode, false, in_string); if (key == 0) { return 0; } @@ -536,10 +541,12 @@ unsigned int trans_special(const char_u **srcp, const size_t src_len, /// @param[out] modp Location where information about modifiers is saved. /// @param[in] keycode Prefer key code, e.g. K_DEL in place of DEL. /// @param[in] keep_x_key Donโt translate xHome to Home key. +/// @param[in] in_string In string, double quote is escaped /// /// @return Key and modifiers or 0 if there is no match. int find_special_key(const char_u **srcp, const size_t src_len, int *const modp, - const bool keycode, const bool keep_x_key) + const bool keycode, const bool keep_x_key, + const bool in_string) FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL { const char_u *last_dash; @@ -550,7 +557,7 @@ int find_special_key(const char_u **srcp, const size_t src_len, int *const modp, int modifiers; int bit; int key; - unsigned long n; + uvarnumber_T n; int l; if (src_len == 0) { @@ -573,8 +580,14 @@ int find_special_key(const char_u **srcp, const size_t src_len, int *const modp, } else { l = 1; } - if (end - bp > l && bp[l + 1] == '>') { - bp += l; // anything accepted, like <C-?> + // Anything accepted, like <C-?>. + // <C-"> or <M-"> are not special in strings as " is + // the string delimiter. With a backslash it works: <M-\"> + if (end - bp > l && !(in_string && bp[1] == '"') && bp[2] == '>') { + bp += l; + } else if (end - bp > 2 && in_string && bp[1] == '\\' + && bp[2] == '"' && bp[3] == '>') { + bp += 2; } } } @@ -610,18 +623,17 @@ int find_special_key(const char_u **srcp, const size_t src_len, int *const modp, vim_str2nr(last_dash + 6, NULL, NULL, STR2NR_ALL, NULL, &n, 0); key = (int)n; } else { - /* - * Modifier with single letter, or special key name. - */ - if (has_mbyte) { - l = mb_ptr2len(last_dash + 1); - } else { - l = 1; + int off = 1; + + // Modifier with single letter, or special key name. + if (in_string && last_dash[1] == '\\' && last_dash[2] == '"') { + off = 2; } + l = mb_ptr2len(last_dash + 1); if (modifiers != 0 && last_dash[l + 1] == '>') { - key = PTR2CHAR(last_dash + 1); + key = PTR2CHAR(last_dash + off); } else { - key = get_special_key_code(last_dash + 1); + key = get_special_key_code(last_dash + off); if (!keep_x_key) { key = handle_x_keys(key); } @@ -744,9 +756,9 @@ int get_mouse_button(int code, bool *is_click, bool *is_drag) /// Replace any terminal code strings with the equivalent internal /// representation /// -/// This is used for the "from" and "to" part of a mapping, and the "to" part of +/// Used for the "from" and "to" part of a mapping, and the "to" part of /// a menu command. Any strings like "<C-UP>" are also replaced, unless -/// 'cpoptions' contains '<'. K_SPECIAL by itself is replaced by K_SPECIAL +/// `special` is false. K_SPECIAL by itself is replaced by K_SPECIAL /// KS_SPECIAL KE_FILLER. /// /// @param[in] from What characters to replace. @@ -759,7 +771,7 @@ int get_mouse_button(int code, bool *is_click, bool *is_drag) /// When cpo_flags contains #FLAG_CPO_BSLASH, a backslash /// can be used in place of <C-v>. All other <C-v> /// characters are removed. -/// @param[in] special If true, always accept <key> notation. +/// @param[in] special Replace keycodes, e.g. <CR> becomes a "\n" char. /// @param[in] cpo_flags Relevant flags derived from p_cpo, see /// #CPO_TO_CPO_FLAGS. /// @@ -778,11 +790,9 @@ char_u *replace_termcodes(const char_u *from, const size_t from_len, const char_u *src; const char_u *const end = from + from_len - 1; int do_backslash; // backslash is a special character - int do_special; // recognize <> key codes char_u *result; // buffer for resulting string do_backslash = !(cpo_flags&FLAG_CPO_BSLASH); - do_special = !(cpo_flags&FLAG_CPO_SPECI) || special; // Allocate space for the translation. Worst case a single character is // replaced by 6 bytes (shifted special key), plus a NUL at the end. @@ -805,10 +815,9 @@ char_u *replace_termcodes(const char_u *from, const size_t from_len, // Copy each byte from *from to result[dlen] while (src <= end) { - // If 'cpoptions' does not contain '<', check for special key codes, - // like "<C-S-LeftMouse>" - if (do_special && (do_lt || ((end - src) >= 3 - && STRNCMP(src, "<lt>", 4) != 0))) { + // Check for special <> keycodes, like "<C-S-LeftMouse>" + if (special && (do_lt || ((end - src) >= 3 + && STRNCMP(src, "<lt>", 4) != 0))) { // Replace <SID> by K_SNR <script-nr> _. // (room: 5 * 6 = 30 bytes; needed: 3 + <nr> + 1 <= 14) if (end - src >= 4 && STRNICMP(src, "<SID>", 5) == 0) { @@ -826,14 +835,15 @@ char_u *replace_termcodes(const char_u *from, const size_t from_len, } } - slen = trans_special(&src, (size_t) (end - src) + 1, result + dlen, true); + slen = trans_special(&src, (size_t)(end - src) + 1, result + dlen, true, + true); if (slen) { dlen += slen; continue; } } - if (do_special) { + if (special) { char_u *p, *s, len; // Replace <Leader> by the value of "mapleader". @@ -841,10 +851,10 @@ char_u *replace_termcodes(const char_u *from, const size_t from_len, // If "mapleader" or "maplocalleader" isn't set use a backslash. if (end - src >= 7 && STRNICMP(src, "<Leader>", 8) == 0) { len = 8; - p = get_var_value((char_u *)"g:mapleader"); + p = get_var_value("g:mapleader"); } else if (end - src >= 12 && STRNICMP(src, "<LocalLeader>", 13) == 0) { len = 13; - p = get_var_value((char_u *)"g:maplocalleader"); + p = get_var_value("g:maplocalleader"); } else { len = 0; p = NULL; diff --git a/src/nvim/keymap.h b/src/nvim/keymap.h index bb8ba84a6a..b8fed77a90 100644 --- a/src/nvim/keymap.h +++ b/src/nvim/keymap.h @@ -464,13 +464,9 @@ enum key_extra { #define MAX_KEY_CODE_LEN 6 #define FLAG_CPO_BSLASH 0x01 -#define FLAG_CPO_SPECI 0x02 -#define CPO_TO_CPO_FLAGS (((vim_strchr(p_cpo, CPO_BSLASH) == NULL) \ - ? 0 \ - : FLAG_CPO_BSLASH)| \ - (vim_strchr(p_cpo, CPO_SPECI) == NULL \ - ? 0 \ - : FLAG_CPO_SPECI)) +#define CPO_TO_CPO_FLAGS ((vim_strchr(p_cpo, CPO_BSLASH) == NULL) \ + ? 0 \ + : FLAG_CPO_BSLASH) #ifdef INCLUDE_GENERATED_DECLARATIONS # include "keymap.h.generated.h" diff --git a/src/nvim/lib/kbtree.h b/src/nvim/lib/kbtree.h new file mode 100644 index 0000000000..a3943054e6 --- /dev/null +++ b/src/nvim/lib/kbtree.h @@ -0,0 +1,451 @@ +/*- + * Copyright 1997-1999, 2001, John-Mark Gurney. + * 2008-2009, Attractive Chaos <attractor@live.co.uk> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef NVIM_LIB_KBTREE_H +#define NVIM_LIB_KBTREE_H + +#include <stdlib.h> +#include <string.h> +#include <stdint.h> + +#include "nvim/memory.h" + +#define KB_MAX_DEPTH 64 + +#define __KB_KEY(type, x) (x->key) +#define __KB_PTR(btr, x) (x->ptr) + +#define __KB_TREE_T(name,key_t,T) \ + typedef struct kbnode_##name##_s kbnode_##name##_t; \ + struct kbnode_##name##_s { \ + int32_t n; \ + bool is_internal; \ + key_t key[2*T-1]; \ + kbnode_##name##_t *ptr[]; \ + } ; \ + \ + typedef struct { \ + kbnode_##name##_t *root; \ + int n_keys, n_nodes; \ + } kbtree_##name##_t; \ + \ + typedef struct { \ + kbnode_##name##_t *x; \ + int i; \ + } kbpos_##name##_t; \ + typedef struct { \ + kbpos_##name##_t stack[KB_MAX_DEPTH], *p; \ + } kbitr_##name##_t; \ + + +#define __kb_destroy(kbnode_t,b) do { \ + int i; \ + unsigned int max = 8; \ + kbnode_t *x, **top, **stack = 0; \ + if (b->root) { \ + top = stack = (kbnode_t**)xcalloc(max, sizeof(kbnode_t*)); \ + *top++ = (b)->root; \ + while (top != stack) { \ + x = *--top; \ + if (x->is_internal == 0) { xfree(x); continue; } \ + for (i = 0; i <= x->n; ++i) \ + if (__KB_PTR(b, x)[i]) { \ + if (top - stack == (int)max) { \ + max <<= 1; \ + stack = (kbnode_t**)xrealloc(stack, max * sizeof(kbnode_t*)); \ + top = stack + (max>>1); \ + } \ + *top++ = __KB_PTR(b, x)[i]; \ + } \ + xfree(x); \ + } \ + } \ + xfree(stack); \ + } while (0) + +#define __KB_GET_AUX1(name, key_t, kbnode_t, __cmp) \ + static inline int __kb_getp_aux_##name(const kbnode_t * __restrict x, key_t * __restrict k, int *r) \ + { \ + int tr, *rr, begin = 0, end = x->n; \ + if (x->n == 0) return -1; \ + rr = r? r : &tr; \ + while (begin < end) { \ + int mid = (begin + end) >> 1; \ + if (__cmp(__KB_KEY(key_t, x)[mid], *k) < 0) begin = mid + 1; \ + else end = mid; \ + } \ + if (begin == x->n) { *rr = 1; return x->n - 1; } \ + if ((*rr = __cmp(*k, __KB_KEY(key_t, x)[begin])) < 0) --begin; \ + return begin; \ + } + +#define __KB_GET(name, key_t, kbnode_t) \ + static key_t *kb_getp_##name(kbtree_##name##_t *b, key_t * __restrict k) \ + { \ + if (!b->root) { \ + return 0; \ + } \ + int i, r = 0; \ + kbnode_t *x = b->root; \ + while (x) { \ + i = __kb_getp_aux_##name(x, k, &r); \ + if (i >= 0 && r == 0) return &__KB_KEY(key_t, x)[i]; \ + if (x->is_internal == 0) return 0; \ + x = __KB_PTR(b, x)[i + 1]; \ + } \ + return 0; \ + } \ + static inline key_t *kb_get_##name(kbtree_##name##_t *b, key_t k) \ + { \ + return kb_getp_##name(b, &k); \ + } + +#define __KB_INTERVAL(name, key_t, kbnode_t) \ + static inline void kb_intervalp_##name(kbtree_##name##_t *b, key_t * __restrict k, key_t **lower, key_t **upper) \ + { \ + if (!b->root) { \ + return; \ + } \ + int i, r = 0; \ + kbnode_t *x = b->root; \ + *lower = *upper = 0; \ + while (x) { \ + i = __kb_getp_aux_##name(x, k, &r); \ + if (i >= 0 && r == 0) { \ + *lower = *upper = &__KB_KEY(key_t, x)[i]; \ + return; \ + } \ + if (i >= 0) *lower = &__KB_KEY(key_t, x)[i]; \ + if (i < x->n - 1) *upper = &__KB_KEY(key_t, x)[i + 1]; \ + if (x->is_internal == 0) return; \ + x = __KB_PTR(b, x)[i + 1]; \ + } \ + } \ + static inline void kb_interval_##name(kbtree_##name##_t *b, key_t k, key_t **lower, key_t **upper) \ + { \ + kb_intervalp_##name(b, &k, lower, upper); \ + } + +#define __KB_PUT(name, key_t, kbnode_t, __cmp, T, ILEN) \ + /* x must be an internal node */ \ + static inline void __kb_split_##name(kbtree_##name##_t *b, kbnode_t *x, int i, kbnode_t *y) \ + { \ + kbnode_t *z; \ + z = (kbnode_t*)xcalloc(1, y->is_internal? ILEN : sizeof(kbnode_##name##_t)); \ + ++b->n_nodes; \ + z->is_internal = y->is_internal; \ + z->n = T - 1; \ + memcpy(__KB_KEY(key_t, z), &__KB_KEY(key_t, y)[T], sizeof(key_t) * (T - 1)); \ + if (y->is_internal) memcpy(__KB_PTR(b, z), &__KB_PTR(b, y)[T], sizeof(void*) * T); \ + y->n = T - 1; \ + memmove(&__KB_PTR(b, x)[i + 2], &__KB_PTR(b, x)[i + 1], sizeof(void*) * (unsigned int)(x->n - i)); \ + __KB_PTR(b, x)[i + 1] = z; \ + memmove(&__KB_KEY(key_t, x)[i + 1], &__KB_KEY(key_t, x)[i], sizeof(key_t) * (unsigned int)(x->n - i)); \ + __KB_KEY(key_t, x)[i] = __KB_KEY(key_t, y)[T - 1]; \ + ++x->n; \ + } \ + static inline key_t *__kb_putp_aux_##name(kbtree_##name##_t *b, kbnode_t *x, key_t * __restrict k) \ + { \ + int i = x->n - 1; \ + key_t *ret; \ + if (x->is_internal == 0) { \ + i = __kb_getp_aux_##name(x, k, 0); \ + if (i != x->n - 1) \ + memmove(&__KB_KEY(key_t, x)[i + 2], &__KB_KEY(key_t, x)[i + 1], (unsigned int)(x->n - i - 1) * sizeof(key_t)); \ + ret = &__KB_KEY(key_t, x)[i + 1]; \ + *ret = *k; \ + ++x->n; \ + } else { \ + i = __kb_getp_aux_##name(x, k, 0) + 1; \ + if (__KB_PTR(b, x)[i]->n == 2 * T - 1) { \ + __kb_split_##name(b, x, i, __KB_PTR(b, x)[i]); \ + if (__cmp(*k, __KB_KEY(key_t, x)[i]) > 0) ++i; \ + } \ + ret = __kb_putp_aux_##name(b, __KB_PTR(b, x)[i], k); \ + } \ + return ret; \ + } \ + static inline key_t *kb_putp_##name(kbtree_##name##_t *b, key_t * __restrict k) \ + { \ + if (!b->root) { \ + b->root = (kbnode_t*)xcalloc(1, ILEN); \ + ++b->n_nodes; \ + } \ + kbnode_t *r, *s; \ + ++b->n_keys; \ + r = b->root; \ + if (r->n == 2 * T - 1) { \ + ++b->n_nodes; \ + s = (kbnode_t*)xcalloc(1, ILEN); \ + b->root = s; s->is_internal = 1; s->n = 0; \ + __KB_PTR(b, s)[0] = r; \ + __kb_split_##name(b, s, 0, r); \ + r = s; \ + } \ + return __kb_putp_aux_##name(b, r, k); \ + } \ + static inline void kb_put_##name(kbtree_##name##_t *b, key_t k) \ + { \ + kb_putp_##name(b, &k); \ + } + + +#define __KB_DEL(name, key_t, kbnode_t, T) \ + static inline key_t __kb_delp_aux_##name(kbtree_##name##_t *b, kbnode_t *x, key_t * __restrict k, int s) \ + { \ + int yn, zn, i, r = 0; \ + kbnode_t *xp, *y, *z; \ + key_t kp; \ + if (x == 0) return *k; \ + if (s) { /* s can only be 0, 1 or 2 */ \ + r = x->is_internal == 0? 0 : s == 1? 1 : -1; \ + i = s == 1? x->n - 1 : -1; \ + } else i = __kb_getp_aux_##name(x, k, &r); \ + if (x->is_internal == 0) { \ + if (s == 2) ++i; \ + kp = __KB_KEY(key_t, x)[i]; \ + memmove(&__KB_KEY(key_t, x)[i], &__KB_KEY(key_t, x)[i + 1], (unsigned int)(x->n - i - 1) * sizeof(key_t)); \ + --x->n; \ + return kp; \ + } \ + if (r == 0) { \ + if ((yn = __KB_PTR(b, x)[i]->n) >= T) { \ + xp = __KB_PTR(b, x)[i]; \ + kp = __KB_KEY(key_t, x)[i]; \ + __KB_KEY(key_t, x)[i] = __kb_delp_aux_##name(b, xp, 0, 1); \ + return kp; \ + } else if ((zn = __KB_PTR(b, x)[i + 1]->n) >= T) { \ + xp = __KB_PTR(b, x)[i + 1]; \ + kp = __KB_KEY(key_t, x)[i]; \ + __KB_KEY(key_t, x)[i] = __kb_delp_aux_##name(b, xp, 0, 2); \ + return kp; \ + } else if (yn == T - 1 && zn == T - 1) { \ + y = __KB_PTR(b, x)[i]; z = __KB_PTR(b, x)[i + 1]; \ + __KB_KEY(key_t, y)[y->n++] = *k; \ + memmove(&__KB_KEY(key_t, y)[y->n], __KB_KEY(key_t, z), (unsigned int)z->n * sizeof(key_t)); \ + if (y->is_internal) memmove(&__KB_PTR(b, y)[y->n], __KB_PTR(b, z), (unsigned int)(z->n + 1) * sizeof(void*)); \ + y->n += z->n; \ + memmove(&__KB_KEY(key_t, x)[i], &__KB_KEY(key_t, x)[i + 1], (unsigned int)(x->n - i - 1) * sizeof(key_t)); \ + memmove(&__KB_PTR(b, x)[i + 1], &__KB_PTR(b, x)[i + 2], (unsigned int)(x->n - i - 1) * sizeof(void*)); \ + --x->n; \ + xfree(z); \ + return __kb_delp_aux_##name(b, y, k, s); \ + } \ + } \ + ++i; \ + if ((xp = __KB_PTR(b, x)[i])->n == T - 1) { \ + if (i > 0 && (y = __KB_PTR(b, x)[i - 1])->n >= T) { \ + memmove(&__KB_KEY(key_t, xp)[1], __KB_KEY(key_t, xp), (unsigned int)xp->n * sizeof(key_t)); \ + if (xp->is_internal) memmove(&__KB_PTR(b, xp)[1], __KB_PTR(b, xp), (unsigned int)(xp->n + 1) * sizeof(void*)); \ + __KB_KEY(key_t, xp)[0] = __KB_KEY(key_t, x)[i - 1]; \ + __KB_KEY(key_t, x)[i - 1] = __KB_KEY(key_t, y)[y->n - 1]; \ + if (xp->is_internal) __KB_PTR(b, xp)[0] = __KB_PTR(b, y)[y->n]; \ + --y->n; ++xp->n; \ + } else if (i < x->n && (y = __KB_PTR(b, x)[i + 1])->n >= T) { \ + __KB_KEY(key_t, xp)[xp->n++] = __KB_KEY(key_t, x)[i]; \ + __KB_KEY(key_t, x)[i] = __KB_KEY(key_t, y)[0]; \ + if (xp->is_internal) __KB_PTR(b, xp)[xp->n] = __KB_PTR(b, y)[0]; \ + --y->n; \ + memmove(__KB_KEY(key_t, y), &__KB_KEY(key_t, y)[1], (unsigned int)y->n * sizeof(key_t)); \ + if (y->is_internal) memmove(__KB_PTR(b, y), &__KB_PTR(b, y)[1], (unsigned int)(y->n + 1) * sizeof(void*)); \ + } else if (i > 0 && (y = __KB_PTR(b, x)[i - 1])->n == T - 1) { \ + __KB_KEY(key_t, y)[y->n++] = __KB_KEY(key_t, x)[i - 1]; \ + memmove(&__KB_KEY(key_t, y)[y->n], __KB_KEY(key_t, xp), (unsigned int)xp->n * sizeof(key_t)); \ + if (y->is_internal) memmove(&__KB_PTR(b, y)[y->n], __KB_PTR(b, xp), (unsigned int)(xp->n + 1) * sizeof(void*)); \ + y->n += xp->n; \ + memmove(&__KB_KEY(key_t, x)[i - 1], &__KB_KEY(key_t, x)[i], (unsigned int)(x->n - i) * sizeof(key_t)); \ + memmove(&__KB_PTR(b, x)[i], &__KB_PTR(b, x)[i + 1], (unsigned int)(x->n - i) * sizeof(void*)); \ + --x->n; \ + xfree(xp); \ + xp = y; \ + } else if (i < x->n && (y = __KB_PTR(b, x)[i + 1])->n == T - 1) { \ + __KB_KEY(key_t, xp)[xp->n++] = __KB_KEY(key_t, x)[i]; \ + memmove(&__KB_KEY(key_t, xp)[xp->n], __KB_KEY(key_t, y), (unsigned int)y->n * sizeof(key_t)); \ + if (xp->is_internal) memmove(&__KB_PTR(b, xp)[xp->n], __KB_PTR(b, y), (unsigned int)(y->n + 1) * sizeof(void*)); \ + xp->n += y->n; \ + memmove(&__KB_KEY(key_t, x)[i], &__KB_KEY(key_t, x)[i + 1], (unsigned int)(x->n - i - 1) * sizeof(key_t)); \ + memmove(&__KB_PTR(b, x)[i + 1], &__KB_PTR(b, x)[i + 2], (unsigned int)(x->n - i - 1) * sizeof(void*)); \ + --x->n; \ + xfree(y); \ + } \ + } \ + return __kb_delp_aux_##name(b, xp, k, s); \ + } \ + static inline key_t kb_delp_##name(kbtree_##name##_t *b, key_t * __restrict k) \ + { \ + kbnode_t *x; \ + key_t ret; \ + ret = __kb_delp_aux_##name(b, b->root, k, 0); \ + --b->n_keys; \ + if (b->root->n == 0 && b->root->is_internal) { \ + --b->n_nodes; \ + x = b->root; \ + b->root = __KB_PTR(b, x)[0]; \ + xfree(x); \ + } \ + return ret; \ + } \ + static inline key_t kb_del_##name(kbtree_##name##_t *b, key_t k) \ + { \ + return kb_delp_##name(b, &k); \ + } + +#define __KB_ITR(name, key_t, kbnode_t) \ + static inline void kb_itr_first_##name(kbtree_##name##_t *b, kbitr_##name##_t *itr) \ + { \ + itr->p = 0; \ + if (b->n_keys == 0) return; \ + itr->p = itr->stack; \ + itr->p->x = b->root; itr->p->i = 0; \ + while (itr->p->x->is_internal && __KB_PTR(b, itr->p->x)[0] != 0) { \ + kbnode_t *x = itr->p->x; \ + ++itr->p; \ + itr->p->x = __KB_PTR(b, x)[0]; itr->p->i = 0; \ + } \ + } \ + static inline int kb_itr_next_##name(kbtree_##name##_t *b, kbitr_##name##_t *itr) \ + { \ + if (itr->p < itr->stack) return 0; \ + for (;;) { \ + ++itr->p->i; \ + while (itr->p->x && itr->p->i <= itr->p->x->n) { \ + itr->p[1].i = 0; \ + itr->p[1].x = itr->p->x->is_internal? __KB_PTR(b, itr->p->x)[itr->p->i] : 0; \ + ++itr->p; \ + } \ + --itr->p; \ + if (itr->p < itr->stack) return 0; \ + if (itr->p->x && itr->p->i < itr->p->x->n) return 1; \ + } \ + } \ + static inline int kb_itr_prev_##name(kbtree_##name##_t *b, kbitr_##name##_t *itr) \ + { \ + if (itr->p < itr->stack) return 0; \ + for (;;) { \ + while (itr->p->x && itr->p->i >= 0) { \ + itr->p[1].x = itr->p->x->is_internal? __KB_PTR(b, itr->p->x)[itr->p->i] : 0; \ + itr->p[1].i = itr->p[1].x ? itr->p[1].x->n : -1; \ + ++itr->p; \ + } \ + --itr->p; \ + if (itr->p < itr->stack) return 0; \ + --itr->p->i; \ + if (itr->p->x && itr->p->i >= 0) return 1; \ + } \ + } \ + static inline int kb_itr_getp_##name(kbtree_##name##_t *b, key_t * __restrict k, kbitr_##name##_t *itr) \ + { \ + if (b->n_keys == 0) { \ + itr->p = NULL; \ + return 0; \ + } \ + int i, r = 0; \ + itr->p = itr->stack; \ + itr->p->x = b->root; \ + while (itr->p->x) { \ + i = __kb_getp_aux_##name(itr->p->x, k, &r); \ + itr->p->i = i; \ + if (i >= 0 && r == 0) return 1; \ + ++itr->p->i; \ + itr->p[1].x = itr->p->x->is_internal? __KB_PTR(b, itr->p->x)[i + 1] : 0; \ + ++itr->p; \ + } \ + return 0; \ + } \ + static inline int kb_itr_get_##name(kbtree_##name##_t *b, key_t k, kbitr_##name##_t *itr) \ + { \ + return kb_itr_getp_##name(b,&k,itr); \ + } \ + static inline void kb_del_itr_##name(kbtree_##name##_t *b, kbitr_##name##_t *itr) \ + { \ + key_t k = kb_itr_key(itr); \ + kb_delp_##name(b, &k); \ + kb_itr_getp_##name(b, &k, itr); \ + } + +#define KBTREE_INIT(name, key_t, __cmp, T) \ + KBTREE_INIT_IMPL(name, key_t, kbnode_##name##_t, __cmp, T, (sizeof(kbnode_##name##_t)+(2*T)*sizeof(void *))) + +#if (!defined(__clang__) && !defined(__INTEL_COMPILER)) && (__GNUC__ > 4 ) + +// The index trickery shouldn't be UB anymore, +// still it is to much for gcc:s -Werror=array-bounds +# define __KB_PRAGMA_START \ + _Pragma("GCC diagnostic push") \ + _Pragma("GCC diagnostic ignored \"-Warray-bounds\"") + +# define __KB_PRAGMA_END \ + _Pragma("GCC diagnostic pop") \ + +#else + +# define __KB_PRAGMA_START +# define __KB_PRAGMA_END + +#endif + +#define KBTREE_INIT_IMPL(name, key_t, kbnode_t, __cmp, T, ILEN) \ + __KB_PRAGMA_START \ + __KB_TREE_T(name, key_t, T) \ + __KB_GET_AUX1(name, key_t, kbnode_t, __cmp) \ + __KB_GET(name, key_t, kbnode_t) \ + __KB_INTERVAL(name, key_t, kbnode_t) \ + __KB_PUT(name, key_t, kbnode_t, __cmp, T, ILEN) \ + __KB_DEL(name, key_t, kbnode_t, T) \ + __KB_ITR(name, key_t, kbnode_t) \ + __KB_PRAGMA_END + +#define KB_DEFAULT_SIZE 512 + +#define kbtree_t(name) kbtree_##name##_t +#define kbitr_t(name) kbitr_##name##_t +#define kb_init(b) ((b)->n_keys = (b)->n_nodes = 0, (b)->root = 0) +#define kb_destroy(name, b) __kb_destroy(kbnode_##name##_t, b) +#define kb_get(name, b, k) kb_get_##name(b, k) +#define kb_put(name, b, k) kb_put_##name(b, k) +#define kb_del(name, b, k) kb_del_##name(b, k) +#define kb_interval(name, b, k, l, u) kb_interval_##name(b, k, l, u) +#define kb_getp(name, b, k) kb_getp_##name(b, k) +#define kb_putp(name, b, k) kb_putp_##name(b, k) +#define kb_delp(name, b, k) kb_delp_##name(b, k) +#define kb_intervalp(name, b, k, l, u) kb_intervalp_##name(b, k, l, u) + +#define kb_itr_first(name, b, i) kb_itr_first_##name(b, i) +#define kb_itr_get(name, b, k, i) kb_itr_get_##name(b, k, i) +#define kb_itr_getp(name, b, k, i) kb_itr_getp_##name(b, k, i) +#define kb_itr_next(name, b, i) kb_itr_next_##name(b, i) +#define kb_itr_prev(name, b, i) kb_itr_prev_##name(b, i) +#define kb_del_itr(name, b, i) kb_del_itr_##name(b, i) +#define kb_itr_key(itr) __KB_KEY(dummy, (itr)->p->x)[(itr)->p->i] +#define kb_itr_valid(itr) ((itr)->p >= (itr)->stack) + +#define kb_size(b) ((b)->n_keys) + +#define kb_generic_cmp(a, b) (((b) < (a)) - ((a) < (b))) +#define kb_str_cmp(a, b) strcmp(a, b) + +#endif // NVIM_LIB_KBTREE_H diff --git a/src/nvim/log.c b/src/nvim/log.c index bbb4dfb944..436a8a4079 100644 --- a/src/nvim/log.c +++ b/src/nvim/log.c @@ -1,23 +1,23 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #include <assert.h> #include <inttypes.h> #include <stdarg.h> #include <stdbool.h> #include <stdint.h> #include <stdio.h> +#include <uv.h> #include "nvim/log.h" #include "nvim/types.h" #include "nvim/os/os.h" #include "nvim/os/time.h" -/// First location of the log file used by log_path_init() -#define USR_LOG_FILE "$NVIM_LOG_FILE" - -/// Fall back location of the log file used by log_path_init() -#define USR_LOG_FILE_2 "$HOME" _PATHSEPSTR ".nvimlog" +#define LOG_FILE_ENV "NVIM_LOG_FILE" -/// Cached location of the log file set by log_path_init() -static char expanded_log_file_path[MAXPATHL + 1] = { 0 }; +/// Cached location of the expanded log file path decided by log_path_init(). +static char log_file_path[MAXPATHL + 1] = { 0 }; static uv_mutex_t mutex; @@ -25,31 +25,57 @@ static uv_mutex_t mutex; # include "log.c.generated.h" #endif -/// Initialize path to log file +#ifdef HAVE_EXECINFO_BACKTRACE +# include <execinfo.h> +#endif + +static bool log_try_create(char *fname) +{ + if (fname == NULL || fname[0] == '\0') { + return false; + } + FILE *log_file = fopen(fname, "a"); + if (log_file == NULL) { + return false; + } + fclose(log_file); + return true; +} + +/// Initializes path to log file. Sets $NVIM_LOG_FILE if empty. /// -/// Tries to use #USR_LOG_FILE, then falls back #USR_LOG_FILE_2. Path to log +/// Tries $NVIM_LOG_FILE, or falls back to $XDG_DATA_HOME/nvim/log. Path to log /// file is cached, so only the first call has effect, unless first call was not -/// successful. To make initialization not succeed either a bug in expand_env() -/// is needed or both `$NVIM_LOG_FILE` and `$HOME` environment variables -/// undefined. +/// successful. Failed initialization indicates either a bug in expand_env() +/// or both $NVIM_LOG_FILE and $HOME environment variables are undefined. /// /// @return true if path was initialized, false otherwise. static bool log_path_init(void) { - if (expanded_log_file_path[0]) { + if (log_file_path[0]) { return true; } - expand_env((char_u *)USR_LOG_FILE, (char_u *)expanded_log_file_path, - sizeof(expanded_log_file_path) - 1); - // if the log file path expansion failed then fall back to stderr - if (strcmp(USR_LOG_FILE, expanded_log_file_path) == 0) { - memset(expanded_log_file_path, 0, sizeof(expanded_log_file_path)); - expand_env((char_u *)USR_LOG_FILE_2, (char_u *)expanded_log_file_path, - sizeof(expanded_log_file_path) - 1); - if (strcmp(USR_LOG_FILE_2, expanded_log_file_path) == 0) { - memset(expanded_log_file_path, 0, sizeof(expanded_log_file_path)); + size_t size = sizeof(log_file_path); + expand_env((char_u *)"$" LOG_FILE_ENV, (char_u *)log_file_path, + (int)size - 1); + if (strequal("$" LOG_FILE_ENV, log_file_path) + || log_file_path[0] == '\0' + || os_isdir((char_u *)log_file_path) + || !log_try_create(log_file_path)) { + // Invalid $NVIM_LOG_FILE or failed to expand; fall back to default. + char *defaultpath = stdpaths_user_data_subpath("log", 0, true); + size_t len = xstrlcpy(log_file_path, defaultpath, size); + xfree(defaultpath); + // Fall back to .nvimlog + if (len >= size || !log_try_create(log_file_path)) { + len = xstrlcpy(log_file_path, ".nvimlog", size); + } + // Fall back to stderr + if (len >= size || !log_try_create(log_file_path)) { + log_file_path[0] = '\0'; return false; } + os_setenv(LOG_FILE_ENV, log_file_path, true); } return true; } @@ -72,6 +98,10 @@ void log_unlock(void) bool do_log(int log_level, const char *func_name, int line_num, bool eol, const char* fmt, ...) FUNC_ATTR_UNUSED { + if (log_level < MIN_LOG_LEVEL) { + return false; + } + log_lock(); bool ret = false; FILE *log_file = open_log_file(); @@ -94,26 +124,42 @@ end: return ret; } +void log_uv_handles(void *loop) +{ + uv_loop_t *l = loop; + log_lock(); + FILE *log_file = open_log_file(); + + if (log_file == NULL) { + goto end; + } + + uv_print_all_handles(l, log_file); + + if (log_file != stderr && log_file != stdout) { + fclose(log_file); + } +end: + log_unlock(); +} + /// Open the log file for appending. /// -/// @return The FILE* specified by the USR_LOG_FILE path or stderr in case of -/// error +/// @return FILE* decided by log_path_init() or stderr in case of error FILE *open_log_file(void) { static bool opening_log_file = false; - // check if it's a recursive call if (opening_log_file) { do_log_to_file(stderr, ERROR_LOG_LEVEL, __func__, __LINE__, true, - "Trying to LOG() recursively! Please fix it."); + "Cannot LOG() recursively."); return stderr; } - // expand USR_LOG_FILE if needed and open the file FILE *log_file = NULL; opening_log_file = true; if (log_path_init()) { - log_file = fopen(expanded_log_file_path, "a"); + log_file = fopen(log_file_path, "a"); } opening_log_file = false; @@ -121,13 +167,69 @@ FILE *open_log_file(void) return log_file; } + // May happen if: + // - LOG() is called before early_init() + // - Directory does not exist + // - File is not writable do_log_to_file(stderr, ERROR_LOG_LEVEL, __func__, __LINE__, true, - "Couldn't open USR_LOG_FILE, logging to stderr! This may be " - "caused by attempting to LOG() before initialization " - "functions are called (e.g. init_homedir())."); + "Logging to stderr, failed to open $" LOG_FILE_ENV ": %s", + log_file_path); return stderr; } +#ifdef HAVE_EXECINFO_BACKTRACE +void log_callstack_to_file(FILE *log_file, const char *const func_name, + const int line_num) +{ + void *trace[100]; + int trace_size = backtrace(trace, ARRAY_SIZE(trace)); + + char exepath[MAXPATHL] = { 0 }; + size_t exepathlen = MAXPATHL; + if (os_exepath(exepath, &exepathlen) != 0) { + abort(); + } + assert(24 + exepathlen < IOSIZE); // Must fit in `cmdbuf` below. + + char cmdbuf[IOSIZE + (20 * ARRAY_SIZE(trace))]; + snprintf(cmdbuf, sizeof(cmdbuf), "addr2line -e %s -f -p", exepath); + for (int i = 1; i < trace_size; i++) { + char buf[20]; // 64-bit pointer 0xNNNNNNNNNNNNNNNN with leading space. + snprintf(buf, sizeof(buf), " %p", trace[i]); + xstrlcat(cmdbuf, buf, sizeof(cmdbuf)); + } + // Now we have a command string like: + // addr2line -e /path/to/exe -f -p 0x123 0x456 ... + + do_log_to_file(log_file, DEBUG_LOG_LEVEL, func_name, line_num, true, + "trace:"); + FILE *fp = popen(cmdbuf, "r"); + char linebuf[IOSIZE]; + while (fgets(linebuf, sizeof(linebuf) - 1, fp) != NULL) { + fprintf(log_file, " %s", linebuf); + } + pclose(fp); + + if (log_file != stderr && log_file != stdout) { + fclose(log_file); + } +} + +void log_callstack(const char *const func_name, const int line_num) +{ + log_lock(); + FILE *log_file = open_log_file(); + if (log_file == NULL) { + goto end; + } + + log_callstack_to_file(log_file, func_name, line_num); + +end: + log_unlock(); +} +#endif + static bool do_log_to_file(FILE *log_file, int log_level, const char *func_name, int line_num, bool eol, const char* fmt, ...) @@ -148,8 +250,8 @@ static bool v_do_log_to_file(FILE *log_file, int log_level, static const char *log_levels[] = { [DEBUG_LOG_LEVEL] = "DEBUG", [INFO_LOG_LEVEL] = "INFO ", - [WARNING_LOG_LEVEL] = "WARN ", - [ERROR_LOG_LEVEL] = "ERROR" + [WARN_LOG_LEVEL] = "WARN ", + [ERROR_LOG_LEVEL] = "ERROR", }; assert(log_level >= DEBUG_LOG_LEVEL && log_level <= ERROR_LOG_LEVEL); diff --git a/src/nvim/log.h b/src/nvim/log.h index 32b7276f14..d63bcc366c 100644 --- a/src/nvim/log.h +++ b/src/nvim/log.h @@ -6,7 +6,7 @@ #define DEBUG_LOG_LEVEL 0 #define INFO_LOG_LEVEL 1 -#define WARNING_LOG_LEVEL 2 +#define WARN_LOG_LEVEL 2 #define ERROR_LOG_LEVEL 3 #define DLOG(...) @@ -18,55 +18,52 @@ #define ELOG(...) #define ELOGN(...) -// Logging is disabled if NDEBUG or DISABLE_LOG is defined. -#if !defined(DISABLE_LOG) && defined(NDEBUG) -# define DISABLE_LOG -#endif - -// MIN_LOG_LEVEL can be defined during compilation to adjust the desired level -// of logging. INFO_LOG_LEVEL is used by default. #ifndef MIN_LOG_LEVEL # define MIN_LOG_LEVEL INFO_LOG_LEVEL #endif -#ifndef DISABLE_LOG +#define LOG(level, ...) do_log((level), __func__, __LINE__, true, \ + __VA_ARGS__) -# if MIN_LOG_LEVEL <= DEBUG_LOG_LEVEL -# undef DLOG -# undef DLOGN -# define DLOG(...) do_log(DEBUG_LOG_LEVEL, __func__, __LINE__, true, \ - __VA_ARGS__) -# define DLOGN(...) do_log(DEBUG_LOG_LEVEL, __func__, __LINE__, false, \ - __VA_ARGS__) -# endif +#if MIN_LOG_LEVEL <= DEBUG_LOG_LEVEL +# undef DLOG +# undef DLOGN +# define DLOG(...) do_log(DEBUG_LOG_LEVEL, __func__, __LINE__, true, \ + __VA_ARGS__) +# define DLOGN(...) do_log(DEBUG_LOG_LEVEL, __func__, __LINE__, false, \ + __VA_ARGS__) +#endif -# if MIN_LOG_LEVEL <= INFO_LOG_LEVEL -# undef ILOG -# undef ILOGN -# define ILOG(...) do_log(INFO_LOG_LEVEL, __func__, __LINE__, true, \ - __VA_ARGS__) -# define ILOGN(...) do_log(INFO_LOG_LEVEL, __func__, __LINE__, false, \ - __VA_ARGS__) -# endif +#if MIN_LOG_LEVEL <= INFO_LOG_LEVEL +# undef ILOG +# undef ILOGN +# define ILOG(...) do_log(INFO_LOG_LEVEL, __func__, __LINE__, true, \ + __VA_ARGS__) +# define ILOGN(...) do_log(INFO_LOG_LEVEL, __func__, __LINE__, false, \ + __VA_ARGS__) +#endif -# if MIN_LOG_LEVEL <= WARNING_LOG_LEVEL -# undef WLOG -# undef WLOGN -# define WLOG(...) do_log(WARNING_LOG_LEVEL, __func__, __LINE__, true, \ - __VA_ARGS__) -# define WLOGN(...) do_log(WARNING_LOG_LEVEL, __func__, __LINE__, false, \ - __VA_ARGS__) -# endif +#if MIN_LOG_LEVEL <= WARN_LOG_LEVEL +# undef WLOG +# undef WLOGN +# define WLOG(...) do_log(WARN_LOG_LEVEL, __func__, __LINE__, true, \ + __VA_ARGS__) +# define WLOGN(...) do_log(WARN_LOG_LEVEL, __func__, __LINE__, false, \ + __VA_ARGS__) +#endif -# if MIN_LOG_LEVEL <= ERROR_LOG_LEVEL -# undef ELOG -# undef ELOGN -# define ELOG(...) do_log(ERROR_LOG_LEVEL, __func__, __LINE__, true, \ - __VA_ARGS__) -# define ELOGN(...) do_log(ERROR_LOG_LEVEL, __func__, __LINE__, false, \ - __VA_ARGS__) -# endif +#if MIN_LOG_LEVEL <= ERROR_LOG_LEVEL +# undef ELOG +# undef ELOGN +# define ELOG(...) do_log(ERROR_LOG_LEVEL, __func__, __LINE__, true, \ + __VA_ARGS__) +# define ELOGN(...) do_log(ERROR_LOG_LEVEL, __func__, __LINE__, false, \ + __VA_ARGS__) +#endif +#ifdef HAVE_EXECINFO_BACKTRACE +# define LOG_CALLSTACK() log_callstack(__func__, __LINE__) +# define LOG_CALLSTACK_TO_FILE(fp) log_callstack_to_file(fp, __func__, __LINE__) #endif #ifdef INCLUDE_GENERATED_DECLARATIONS diff --git a/src/nvim/lua/converter.c b/src/nvim/lua/converter.c new file mode 100644 index 0000000000..cacba3ce87 --- /dev/null +++ b/src/nvim/lua/converter.c @@ -0,0 +1,1189 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + +#include <lua.h> +#include <lualib.h> +#include <lauxlib.h> +#include <assert.h> +#include <stdint.h> +#include <stdbool.h> + +#include "nvim/api/private/defs.h" +#include "nvim/api/private/helpers.h" +#include "nvim/func_attr.h" +#include "nvim/memory.h" +#include "nvim/assert.h" +// FIXME: vim.h is not actually needed, but otherwise it states MAXPATHL is +// redefined +#include "nvim/vim.h" +#include "nvim/globals.h" +#include "nvim/message.h" +#include "nvim/eval/typval.h" +#include "nvim/ascii.h" +#include "nvim/macros.h" + +#include "nvim/lib/kvec.h" +#include "nvim/eval/decode.h" + +#include "nvim/lua/converter.h" +#include "nvim/lua/executor.h" + +/// Determine, which keys lua table contains +typedef struct { + size_t maxidx; ///< Maximum positive integral value found. + size_t string_keys_num; ///< Number of string keys. + bool has_string_with_nul; ///< True if there is string key with NUL byte. + ObjectType type; ///< If has_type_key is true then attached value. Otherwise + ///< either kObjectTypeNil, kObjectTypeDictionary or + ///< kObjectTypeArray, depending on other properties. + lua_Number val; ///< If has_val_key and val_type == LUA_TNUMBER: value. + bool has_type_key; ///< True if type key is present. +} LuaTableProps; + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "lua/converter.c.generated.h" +#endif + +#define TYPE_IDX_VALUE true +#define VAL_IDX_VALUE false + +#define LUA_PUSH_STATIC_STRING(lstate, s) \ + lua_pushlstring(lstate, s, sizeof(s) - 1) + +static LuaTableProps nlua_traverse_table(lua_State *const lstate) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ + size_t tsize = 0; // Total number of keys. + int val_type = 0; // If has_val_key: lua type of the value. + bool has_val_key = false; // True if val key was found, + // @see nlua_push_val_idx(). + size_t other_keys_num = 0; // Number of keys that are not string, integral + // or type keys. + LuaTableProps ret; + memset(&ret, 0, sizeof(ret)); + if (!lua_checkstack(lstate, lua_gettop(lstate) + 3)) { + emsgf(_("E1502: Lua failed to grow stack to %i"), lua_gettop(lstate) + 2); + ret.type = kObjectTypeNil; + return ret; + } + lua_pushnil(lstate); + while (lua_next(lstate, -2)) { + switch (lua_type(lstate, -2)) { + case LUA_TSTRING: { + size_t len; + const char *s = lua_tolstring(lstate, -2, &len); + if (memchr(s, NUL, len) != NULL) { + ret.has_string_with_nul = true; + } + ret.string_keys_num++; + break; + } + case LUA_TNUMBER: { + const lua_Number n = lua_tonumber(lstate, -2); + if (n > (lua_Number)SIZE_MAX || n <= 0 + || ((lua_Number)((size_t)n)) != n) { + other_keys_num++; + } else { + const size_t idx = (size_t)n; + if (idx > ret.maxidx) { + ret.maxidx = idx; + } + } + break; + } + case LUA_TBOOLEAN: { + const bool b = lua_toboolean(lstate, -2); + if (b == TYPE_IDX_VALUE) { + if (lua_type(lstate, -1) == LUA_TNUMBER) { + lua_Number n = lua_tonumber(lstate, -1); + if (n == (lua_Number)kObjectTypeFloat + || n == (lua_Number)kObjectTypeArray + || n == (lua_Number)kObjectTypeDictionary) { + ret.has_type_key = true; + ret.type = (ObjectType)n; + } else { + other_keys_num++; + } + } else { + other_keys_num++; + } + } else { + has_val_key = true; + val_type = lua_type(lstate, -1); + if (val_type == LUA_TNUMBER) { + ret.val = lua_tonumber(lstate, -1); + } + } + break; + } + default: { + other_keys_num++; + break; + } + } + tsize++; + lua_pop(lstate, 1); + } + if (ret.has_type_key) { + if (ret.type == kObjectTypeFloat + && (!has_val_key || val_type != LUA_TNUMBER)) { + ret.type = kObjectTypeNil; + } else if (ret.type == kObjectTypeArray) { + // Determine what is the last number in a *sequence* of keys. + // This condition makes sure that Neovim will not crash when it gets table + // {[vim.type_idx]=vim.types.array, [SIZE_MAX]=1}: without it maxidx will + // be SIZE_MAX, with this condition it should be zero and [SIZE_MAX] key + // should be ignored. + if (ret.maxidx != 0 + && ret.maxidx != (tsize + - ret.has_type_key + - other_keys_num + - has_val_key + - ret.string_keys_num)) { + for (ret.maxidx = 0;; ret.maxidx++) { + lua_rawgeti(lstate, -1, (int)ret.maxidx + 1); + if (lua_isnil(lstate, -1)) { + lua_pop(lstate, 1); + break; + } + lua_pop(lstate, 1); + } + } + } + } else { + if (tsize == 0 + || (tsize == ret.maxidx + && other_keys_num == 0 + && ret.string_keys_num == 0)) { + ret.type = kObjectTypeArray; + } else if (ret.string_keys_num == tsize) { + ret.type = kObjectTypeDictionary; + } else { + ret.type = kObjectTypeNil; + } + } + return ret; +} + +/// Helper structure for nlua_pop_typval +typedef struct { + typval_T *tv; ///< Location where conversion result is saved. + bool container; ///< True if tv is a container. + bool special; ///< If true then tv is a _VAL part of special dictionary + ///< that represents mapping. + int idx; ///< Container index (used to detect self-referencing structures). +} TVPopStackItem; + +/// Convert lua object to VimL typval_T +/// +/// Should pop exactly one value from lua stack. +/// +/// @param lstate Lua state. +/// @param[out] ret_tv Where to put the result. +/// +/// @return `true` in case of success, `false` in case of failure. Error is +/// reported automatically. +bool nlua_pop_typval(lua_State *lstate, typval_T *ret_tv) +{ + bool ret = true; + const int initial_size = lua_gettop(lstate); + kvec_t(TVPopStackItem) stack = KV_INITIAL_VALUE; + kv_push(stack, ((TVPopStackItem) { ret_tv, false, false, 0 })); + while (ret && kv_size(stack)) { + if (!lua_checkstack(lstate, lua_gettop(lstate) + 3)) { + emsgf(_("E1502: Lua failed to grow stack to %i"), lua_gettop(lstate) + 3); + ret = false; + break; + } + TVPopStackItem cur = kv_pop(stack); + if (cur.container) { + if (cur.special || cur.tv->v_type == VAR_DICT) { + assert(cur.tv->v_type == (cur.special ? VAR_LIST : VAR_DICT)); + bool next_key_found = false; + while (lua_next(lstate, -2)) { + if (lua_type(lstate, -2) == LUA_TSTRING) { + next_key_found = true; + break; + } + lua_pop(lstate, 1); + } + if (next_key_found) { + size_t len; + const char *s = lua_tolstring(lstate, -2, &len); + if (cur.special) { + list_T *const kv_pair = tv_list_alloc(); + tv_list_append_list(cur.tv->vval.v_list, kv_pair); + listitem_T *const key = tv_list_item_alloc(); + key->li_tv = decode_string(s, len, kTrue, false, false); + tv_list_append(kv_pair, key); + if (key->li_tv.v_type == VAR_UNKNOWN) { + ret = false; + tv_list_unref(kv_pair); + continue; + } + listitem_T *const val = tv_list_item_alloc(); + tv_list_append(kv_pair, val); + kv_push(stack, cur); + cur = (TVPopStackItem) { &val->li_tv, false, false, 0 }; + } else { + dictitem_T *const di = tv_dict_item_alloc_len(s, len); + if (tv_dict_add(cur.tv->vval.v_dict, di) == FAIL) { + assert(false); + } + kv_push(stack, cur); + cur = (TVPopStackItem) { &di->di_tv, false, false, 0 }; + } + } else { + lua_pop(lstate, 1); + continue; + } + } else { + assert(cur.tv->v_type == VAR_LIST); + lua_rawgeti(lstate, -1, cur.tv->vval.v_list->lv_len + 1); + if (lua_isnil(lstate, -1)) { + lua_pop(lstate, 2); + continue; + } + listitem_T *const li = tv_list_item_alloc(); + tv_list_append(cur.tv->vval.v_list, li); + kv_push(stack, cur); + cur = (TVPopStackItem) { &li->li_tv, false, false, 0 }; + } + } + assert(!cur.container); + *cur.tv = (typval_T) { + .v_type = VAR_NUMBER, + .v_lock = VAR_UNLOCKED, + .vval = { .v_number = 0 }, + }; + switch (lua_type(lstate, -1)) { + case LUA_TNIL: { + cur.tv->v_type = VAR_SPECIAL; + cur.tv->vval.v_special = kSpecialVarNull; + break; + } + case LUA_TBOOLEAN: { + cur.tv->v_type = VAR_SPECIAL; + cur.tv->vval.v_special = (lua_toboolean(lstate, -1) + ? kSpecialVarTrue + : kSpecialVarFalse); + break; + } + case LUA_TSTRING: { + size_t len; + const char *s = lua_tolstring(lstate, -1, &len); + *cur.tv = decode_string(s, len, kNone, true, false); + if (cur.tv->v_type == VAR_UNKNOWN) { + ret = false; + } + break; + } + case LUA_TNUMBER: { + const lua_Number n = lua_tonumber(lstate, -1); + if (n > (lua_Number)VARNUMBER_MAX || n < (lua_Number)VARNUMBER_MIN + || ((lua_Number)((varnumber_T)n)) != n) { + cur.tv->v_type = VAR_FLOAT; + cur.tv->vval.v_float = (float_T)n; + } else { + cur.tv->v_type = VAR_NUMBER; + cur.tv->vval.v_number = (varnumber_T)n; + } + break; + } + case LUA_TTABLE: { + const LuaTableProps table_props = nlua_traverse_table(lstate); + + for (size_t i = 0; i < kv_size(stack); i++) { + const TVPopStackItem item = kv_A(stack, i); + if (item.container && lua_rawequal(lstate, -1, item.idx)) { + tv_copy(item.tv, cur.tv); + cur.container = false; + goto nlua_pop_typval_table_processing_end; + } + } + + switch (table_props.type) { + case kObjectTypeArray: { + cur.tv->v_type = VAR_LIST; + cur.tv->vval.v_list = tv_list_alloc(); + cur.tv->vval.v_list->lv_refcount++; + if (table_props.maxidx != 0) { + cur.container = true; + cur.idx = lua_gettop(lstate); + kv_push(stack, cur); + } + break; + } + case kObjectTypeDictionary: { + if (table_props.string_keys_num == 0) { + cur.tv->v_type = VAR_DICT; + cur.tv->vval.v_dict = tv_dict_alloc(); + cur.tv->vval.v_dict->dv_refcount++; + } else { + cur.special = table_props.has_string_with_nul; + if (table_props.has_string_with_nul) { + decode_create_map_special_dict(cur.tv); + assert(cur.tv->v_type == VAR_DICT); + dictitem_T *const val_di = tv_dict_find(cur.tv->vval.v_dict, + S_LEN("_VAL")); + assert(val_di != NULL); + cur.tv = &val_di->di_tv; + assert(cur.tv->v_type == VAR_LIST); + } else { + cur.tv->v_type = VAR_DICT; + cur.tv->vval.v_dict = tv_dict_alloc(); + cur.tv->vval.v_dict->dv_refcount++; + } + cur.container = true; + cur.idx = lua_gettop(lstate); + kv_push(stack, cur); + lua_pushnil(lstate); + } + break; + } + case kObjectTypeFloat: { + cur.tv->v_type = VAR_FLOAT; + cur.tv->vval.v_float = (float_T)table_props.val; + break; + } + case kObjectTypeNil: { + EMSG(_("E5100: Cannot convert given lua table: table " + "should either have a sequence of positive integer keys " + "or contain only string keys")); + ret = false; + break; + } + default: { + assert(false); + } + } +nlua_pop_typval_table_processing_end: + break; + } + default: { + EMSG(_("E5101: Cannot convert given lua type")); + ret = false; + break; + } + } + if (!cur.container) { + lua_pop(lstate, 1); + } + } + kv_destroy(stack); + if (!ret) { + tv_clear(ret_tv); + *ret_tv = (typval_T) { + .v_type = VAR_NUMBER, + .v_lock = VAR_UNLOCKED, + .vval = { .v_number = 0 }, + }; + lua_pop(lstate, lua_gettop(lstate) - initial_size + 1); + } + assert(lua_gettop(lstate) == initial_size - 1); + return ret; +} + +#define TYPVAL_ENCODE_ALLOW_SPECIALS true + +#define TYPVAL_ENCODE_CONV_NIL(tv) \ + lua_pushnil(lstate) + +#define TYPVAL_ENCODE_CONV_BOOL(tv, num) \ + lua_pushboolean(lstate, (bool)(num)) + +#define TYPVAL_ENCODE_CONV_NUMBER(tv, num) \ + lua_pushnumber(lstate, (lua_Number)(num)) + +#define TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER TYPVAL_ENCODE_CONV_NUMBER + +#define TYPVAL_ENCODE_CONV_FLOAT(tv, flt) \ + TYPVAL_ENCODE_CONV_NUMBER(tv, flt) + +#define TYPVAL_ENCODE_CONV_STRING(tv, str, len) \ + lua_pushlstring(lstate, (const char *)(str), (len)) + +#define TYPVAL_ENCODE_CONV_STR_STRING TYPVAL_ENCODE_CONV_STRING + +#define TYPVAL_ENCODE_CONV_EXT_STRING(tv, str, len, type) \ + TYPVAL_ENCODE_CONV_NIL() + +#define TYPVAL_ENCODE_CONV_FUNC_START(tv, fun) \ + do { \ + TYPVAL_ENCODE_CONV_NIL(tv); \ + goto typval_encode_stop_converting_one_item; \ + } while (0) + +#define TYPVAL_ENCODE_CONV_FUNC_BEFORE_ARGS(tv, len) +#define TYPVAL_ENCODE_CONV_FUNC_BEFORE_SELF(tv, len) +#define TYPVAL_ENCODE_CONV_FUNC_END(tv) + +#define TYPVAL_ENCODE_CONV_EMPTY_LIST(tv) \ + lua_createtable(lstate, 0, 0) + +#define TYPVAL_ENCODE_CONV_EMPTY_DICT(tv, dict) \ + nlua_create_typed_table(lstate, 0, 0, kObjectTypeDictionary) + +#define TYPVAL_ENCODE_CONV_LIST_START(tv, len) \ + do { \ + if (!lua_checkstack(lstate, lua_gettop(lstate) + 3)) { \ + emsgf(_("E5102: Lua failed to grow stack to %i"), \ + lua_gettop(lstate) + 3); \ + return false; \ + } \ + lua_createtable(lstate, (int)(len), 0); \ + lua_pushnumber(lstate, 1); \ + } while (0) + +#define TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START(tv, mpsv) + +#define TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS(tv) \ + do { \ + lua_Number idx = lua_tonumber(lstate, -2); \ + lua_rawset(lstate, -3); \ + lua_pushnumber(lstate, idx + 1); \ + } while (0) + +#define TYPVAL_ENCODE_CONV_LIST_END(tv) \ + lua_rawset(lstate, -3) + +#define TYPVAL_ENCODE_CONV_DICT_START(tv, dict, len) \ + do { \ + if (!lua_checkstack(lstate, lua_gettop(lstate) + 3)) { \ + emsgf(_("E5102: Lua failed to grow stack to %i"), \ + lua_gettop(lstate) + 3); \ + return false; \ + } \ + lua_createtable(lstate, 0, (int)(len)); \ + } while (0) + +#define TYPVAL_ENCODE_SPECIAL_DICT_KEY_CHECK(label, kv_pair) + +#define TYPVAL_ENCODE_CONV_REAL_DICT_AFTER_START(tv, dict, mpsv) + +#define TYPVAL_ENCODE_CONV_DICT_AFTER_KEY(tv, dict) + +#define TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS(tv, dict) \ + lua_rawset(lstate, -3) + +#define TYPVAL_ENCODE_CONV_DICT_END(tv, dict) \ + TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS(tv, dict) + +#define TYPVAL_ENCODE_CONV_RECURSE(val, conv_type) \ + do { \ + for (size_t backref = kv_size(*mpstack); backref; backref--) { \ + const MPConvStackVal mpval = kv_A(*mpstack, backref - 1); \ + if (mpval.type == conv_type) { \ + if (conv_type == kMPConvDict \ + ? (void *)mpval.data.d.dict == (void *)(val) \ + : (void *)mpval.data.l.list == (void *)(val)) { \ + lua_pushvalue(lstate, \ + -((int)((kv_size(*mpstack) - backref + 1) * 2))); \ + break; \ + } \ + } \ + } \ + } while (0) + +#define TYPVAL_ENCODE_SCOPE static +#define TYPVAL_ENCODE_NAME lua +#define TYPVAL_ENCODE_FIRST_ARG_TYPE lua_State *const +#define TYPVAL_ENCODE_FIRST_ARG_NAME lstate +#include "nvim/eval/typval_encode.c.h" +#undef TYPVAL_ENCODE_SCOPE +#undef TYPVAL_ENCODE_NAME +#undef TYPVAL_ENCODE_FIRST_ARG_TYPE +#undef TYPVAL_ENCODE_FIRST_ARG_NAME + +#undef TYPVAL_ENCODE_CONV_STRING +#undef TYPVAL_ENCODE_CONV_STR_STRING +#undef TYPVAL_ENCODE_CONV_EXT_STRING +#undef TYPVAL_ENCODE_CONV_NUMBER +#undef TYPVAL_ENCODE_CONV_FLOAT +#undef TYPVAL_ENCODE_CONV_FUNC_START +#undef TYPVAL_ENCODE_CONV_FUNC_BEFORE_ARGS +#undef TYPVAL_ENCODE_CONV_FUNC_BEFORE_SELF +#undef TYPVAL_ENCODE_CONV_FUNC_END +#undef TYPVAL_ENCODE_CONV_EMPTY_LIST +#undef TYPVAL_ENCODE_CONV_LIST_START +#undef TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START +#undef TYPVAL_ENCODE_CONV_EMPTY_DICT +#undef TYPVAL_ENCODE_CONV_NIL +#undef TYPVAL_ENCODE_CONV_BOOL +#undef TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER +#undef TYPVAL_ENCODE_CONV_DICT_START +#undef TYPVAL_ENCODE_CONV_REAL_DICT_AFTER_START +#undef TYPVAL_ENCODE_CONV_DICT_END +#undef TYPVAL_ENCODE_CONV_DICT_AFTER_KEY +#undef TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS +#undef TYPVAL_ENCODE_SPECIAL_DICT_KEY_CHECK +#undef TYPVAL_ENCODE_CONV_LIST_END +#undef TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS +#undef TYPVAL_ENCODE_CONV_RECURSE +#undef TYPVAL_ENCODE_ALLOW_SPECIALS + +/// Convert VimL typval_T to lua value +/// +/// Should leave single value in lua stack. May only fail if lua failed to grow +/// stack. +/// +/// @param lstate Lua interpreter state. +/// @param[in] tv typval_T to convert. +/// +/// @return true in case of success, false otherwise. +bool nlua_push_typval(lua_State *lstate, typval_T *const tv) +{ + const int initial_size = lua_gettop(lstate); + if (!lua_checkstack(lstate, initial_size + 2)) { + emsgf(_("E1502: Lua failed to grow stack to %i"), initial_size + 4); + return false; + } + if (encode_vim_to_lua(lstate, tv, "nlua_push_typval argument") == FAIL) { + return false; + } + assert(lua_gettop(lstate) == initial_size + 1); + return true; +} + +/// Push value which is a type index +/// +/// Used for all โtypedโ tables: i.e. for all tables which represent VimL +/// values. +static inline void nlua_push_type_idx(lua_State *lstate) + FUNC_ATTR_NONNULL_ALL +{ + lua_pushboolean(lstate, TYPE_IDX_VALUE); +} + +/// Push value which is a value index +/// +/// Used for tables which represent scalar values, like float value. +static inline void nlua_push_val_idx(lua_State *lstate) + FUNC_ATTR_NONNULL_ALL +{ + lua_pushboolean(lstate, VAL_IDX_VALUE); +} + +/// Push type +/// +/// Type is a value in vim.types table. +/// +/// @param[out] lstate Lua state. +/// @param[in] type Type to push. +static inline void nlua_push_type(lua_State *lstate, ObjectType type) + FUNC_ATTR_NONNULL_ALL +{ + lua_pushnumber(lstate, (lua_Number)type); +} + +/// Create lua table which has an entry that determines its VimL type +/// +/// @param[out] lstate Lua state. +/// @param[in] narr Number of โarrayโ entries to be populated later. +/// @param[in] nrec Number of โdictionaryโ entries to be populated later. +/// @param[in] type Type of the table. +static inline void nlua_create_typed_table(lua_State *lstate, + const size_t narr, + const size_t nrec, + const ObjectType type) + FUNC_ATTR_NONNULL_ALL +{ + lua_createtable(lstate, (int)narr, (int)(1 + nrec)); + nlua_push_type_idx(lstate); + nlua_push_type(lstate, type); + lua_rawset(lstate, -3); +} + + +/// Convert given String to lua string +/// +/// Leaves converted string on top of the stack. +void nlua_push_String(lua_State *lstate, const String s) + FUNC_ATTR_NONNULL_ALL +{ + lua_pushlstring(lstate, s.data, s.size); +} + +/// Convert given Integer to lua number +/// +/// Leaves converted number on top of the stack. +void nlua_push_Integer(lua_State *lstate, const Integer n) + FUNC_ATTR_NONNULL_ALL +{ + lua_pushnumber(lstate, (lua_Number)n); +} + +/// Convert given Float to lua table +/// +/// Leaves converted table on top of the stack. +void nlua_push_Float(lua_State *lstate, const Float f) + FUNC_ATTR_NONNULL_ALL +{ + nlua_create_typed_table(lstate, 0, 1, kObjectTypeFloat); + nlua_push_val_idx(lstate); + lua_pushnumber(lstate, (lua_Number)f); + lua_rawset(lstate, -3); +} + +/// Convert given Float to lua boolean +/// +/// Leaves converted value on top of the stack. +void nlua_push_Boolean(lua_State *lstate, const Boolean b) + FUNC_ATTR_NONNULL_ALL +{ + lua_pushboolean(lstate, b); +} + +/// Convert given Dictionary to lua table +/// +/// Leaves converted table on top of the stack. +void nlua_push_Dictionary(lua_State *lstate, const Dictionary dict) + FUNC_ATTR_NONNULL_ALL +{ + if (dict.size == 0) { + nlua_create_typed_table(lstate, 0, 0, kObjectTypeDictionary); + } else { + lua_createtable(lstate, 0, (int)dict.size); + } + for (size_t i = 0; i < dict.size; i++) { + nlua_push_String(lstate, dict.items[i].key); + nlua_push_Object(lstate, dict.items[i].value); + lua_rawset(lstate, -3); + } +} + +/// Convert given Array to lua table +/// +/// Leaves converted table on top of the stack. +void nlua_push_Array(lua_State *lstate, const Array array) + FUNC_ATTR_NONNULL_ALL +{ + lua_createtable(lstate, (int)array.size, 0); + for (size_t i = 0; i < array.size; i++) { + nlua_push_Object(lstate, array.items[i]); + lua_rawseti(lstate, -2, (int)i + 1); + } +} + +#define GENERATE_INDEX_FUNCTION(type) \ +void nlua_push_##type(lua_State *lstate, const type item) \ + FUNC_ATTR_NONNULL_ALL \ +{ \ + lua_pushnumber(lstate, (lua_Number)(item)); \ +} + +GENERATE_INDEX_FUNCTION(Buffer) +GENERATE_INDEX_FUNCTION(Window) +GENERATE_INDEX_FUNCTION(Tabpage) + +#undef GENERATE_INDEX_FUNCTION + +/// Convert given Object to lua value +/// +/// Leaves converted value on top of the stack. +void nlua_push_Object(lua_State *lstate, const Object obj) + FUNC_ATTR_NONNULL_ALL +{ + switch (obj.type) { + case kObjectTypeNil: { + lua_pushnil(lstate); + break; + } +#define ADD_TYPE(type, data_key) \ + case kObjectType##type: { \ + nlua_push_##type(lstate, obj.data.data_key); \ + break; \ + } + ADD_TYPE(Boolean, boolean) + ADD_TYPE(Integer, integer) + ADD_TYPE(Float, floating) + ADD_TYPE(String, string) + ADD_TYPE(Array, array) + ADD_TYPE(Dictionary, dictionary) +#undef ADD_TYPE +#define ADD_REMOTE_TYPE(type) \ + case kObjectType##type: { \ + nlua_push_##type(lstate, (type)obj.data.integer); \ + break; \ + } + ADD_REMOTE_TYPE(Buffer) + ADD_REMOTE_TYPE(Window) + ADD_REMOTE_TYPE(Tabpage) +#undef ADD_REMOTE_TYPE + } +} + + +/// Convert lua value to string +/// +/// Always pops one value from the stack. +String nlua_pop_String(lua_State *lstate, Error *err) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ + if (lua_type(lstate, -1) != LUA_TSTRING) { + lua_pop(lstate, 1); + api_set_error(err, kErrorTypeValidation, "Expected lua string"); + return (String) { .size = 0, .data = NULL }; + } + String ret; + + ret.data = (char *)lua_tolstring(lstate, -1, &(ret.size)); + assert(ret.data != NULL); + ret.data = xmemdupz(ret.data, ret.size); + lua_pop(lstate, 1); + + return ret; +} + +/// Convert lua value to integer +/// +/// Always pops one value from the stack. +Integer nlua_pop_Integer(lua_State *lstate, Error *err) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ + if (lua_type(lstate, -1) != LUA_TNUMBER) { + lua_pop(lstate, 1); + api_set_error(err, kErrorTypeValidation, "Expected lua number"); + return 0; + } + const lua_Number n = lua_tonumber(lstate, -1); + lua_pop(lstate, 1); + if (n > (lua_Number)API_INTEGER_MAX || n < (lua_Number)API_INTEGER_MIN + || ((lua_Number)((Integer)n)) != n) { + api_set_error(err, kErrorTypeException, "Number is not integral"); + return 0; + } + return (Integer)n; +} + +/// Convert lua value to boolean +/// +/// Always pops one value from the stack. +Boolean nlua_pop_Boolean(lua_State *lstate, Error *err) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ + const Boolean ret = lua_toboolean(lstate, -1); + lua_pop(lstate, 1); + return ret; +} + +/// Check whether typed table on top of the stack has given type +/// +/// @param[in] lstate Lua state. +/// @param[out] err Location where error will be saved. May be NULL. +/// @param[in] type Type to check. +/// +/// @return @see nlua_traverse_table(). +static inline LuaTableProps nlua_check_type(lua_State *const lstate, + Error *const err, + const ObjectType type) + FUNC_ATTR_NONNULL_ARG(1) FUNC_ATTR_WARN_UNUSED_RESULT +{ + if (lua_type(lstate, -1) != LUA_TTABLE) { + if (err) { + api_set_error(err, kErrorTypeValidation, "Expected lua table"); + } + return (LuaTableProps) { .type = kObjectTypeNil }; + } + LuaTableProps table_props = nlua_traverse_table(lstate); + + if (type == kObjectTypeDictionary && table_props.type == kObjectTypeArray + && table_props.maxidx == 0 && !table_props.has_type_key) { + table_props.type = kObjectTypeDictionary; + } + + if (table_props.type != type) { + if (err) { + api_set_error(err, kErrorTypeValidation, "Unexpected type"); + } + } + + return table_props; +} + +/// Convert lua table to float +/// +/// Always pops one value from the stack. +Float nlua_pop_Float(lua_State *lstate, Error *err) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ + if (lua_type(lstate, -1) == LUA_TNUMBER) { + const Float ret = (Float)lua_tonumber(lstate, -1); + lua_pop(lstate, 1); + return ret; + } + + const LuaTableProps table_props = nlua_check_type(lstate, err, + kObjectTypeFloat); + lua_pop(lstate, 1); + if (table_props.type != kObjectTypeFloat) { + return 0; + } else { + return (Float)table_props.val; + } +} + +/// Convert lua table to array without determining whether it is array +/// +/// @param lstate Lua state. +/// @param[in] table_props nlua_traverse_table() output. +/// @param[out] err Location where error will be saved. +static Array nlua_pop_Array_unchecked(lua_State *const lstate, + const LuaTableProps table_props, + Error *const err) +{ + Array ret = { .size = table_props.maxidx, .items = NULL }; + + if (ret.size == 0) { + lua_pop(lstate, 1); + return ret; + } + + ret.items = xcalloc(ret.size, sizeof(*ret.items)); + for (size_t i = 1; i <= ret.size; i++) { + Object val; + + lua_rawgeti(lstate, -1, (int)i); + + val = nlua_pop_Object(lstate, err); + if (ERROR_SET(err)) { + ret.size = i - 1; + lua_pop(lstate, 1); + api_free_array(ret); + return (Array) { .size = 0, .items = NULL }; + } + ret.items[i - 1] = val; + } + lua_pop(lstate, 1); + + return ret; +} + +/// Convert lua table to array +/// +/// Always pops one value from the stack. +Array nlua_pop_Array(lua_State *lstate, Error *err) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ + const LuaTableProps table_props = nlua_check_type(lstate, err, + kObjectTypeArray); + if (table_props.type != kObjectTypeArray) { + return (Array) { .size = 0, .items = NULL }; + } + return nlua_pop_Array_unchecked(lstate, table_props, err); +} + +/// Convert lua table to dictionary +/// +/// Always pops one value from the stack. Does not check whether whether topmost +/// value on the stack is a table. +/// +/// @param lstate Lua interpreter state. +/// @param[in] table_props nlua_traverse_table() output. +/// @param[out] err Location where error will be saved. +static Dictionary nlua_pop_Dictionary_unchecked(lua_State *lstate, + const LuaTableProps table_props, + Error *err) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ + Dictionary ret = { .size = table_props.string_keys_num, .items = NULL }; + + if (ret.size == 0) { + lua_pop(lstate, 1); + return ret; + } + ret.items = xcalloc(ret.size, sizeof(*ret.items)); + + lua_pushnil(lstate); + for (size_t i = 0; lua_next(lstate, -2) && i < ret.size;) { + // stack: dict, key, value + + if (lua_type(lstate, -2) == LUA_TSTRING) { + lua_pushvalue(lstate, -2); + // stack: dict, key, value, key + + ret.items[i].key = nlua_pop_String(lstate, err); + // stack: dict, key, value + + if (!ERROR_SET(err)) { + ret.items[i].value = nlua_pop_Object(lstate, err); + // stack: dict, key + } else { + lua_pop(lstate, 1); + // stack: dict, key + } + + if (ERROR_SET(err)) { + ret.size = i; + api_free_dictionary(ret); + lua_pop(lstate, 2); + // stack: + return (Dictionary) { .size = 0, .items = NULL }; + } + i++; + } else { + lua_pop(lstate, 1); + // stack: dict, key + } + } + lua_pop(lstate, 1); + + return ret; +} + +/// Convert lua table to dictionary +/// +/// Always pops one value from the stack. +Dictionary nlua_pop_Dictionary(lua_State *lstate, Error *err) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ + const LuaTableProps table_props = nlua_check_type(lstate, err, + kObjectTypeDictionary); + if (table_props.type != kObjectTypeDictionary) { + lua_pop(lstate, 1); + return (Dictionary) { .size = 0, .items = NULL }; + } + + return nlua_pop_Dictionary_unchecked(lstate, table_props, err); +} + +/// Helper structure for nlua_pop_Object +typedef struct { + Object *obj; ///< Location where conversion result is saved. + bool container; ///< True if tv is a container. +} ObjPopStackItem; + +/// Convert lua table to object +/// +/// Always pops one value from the stack. +Object nlua_pop_Object(lua_State *const lstate, Error *const err) +{ + Object ret = NIL; + const int initial_size = lua_gettop(lstate); + kvec_t(ObjPopStackItem) stack = KV_INITIAL_VALUE; + kv_push(stack, ((ObjPopStackItem) { &ret, false })); + while (!ERROR_SET(err) && kv_size(stack)) { + if (!lua_checkstack(lstate, lua_gettop(lstate) + 3)) { + api_set_error(err, kErrorTypeException, "Lua failed to grow stack"); + break; + } + ObjPopStackItem cur = kv_pop(stack); + if (cur.container) { + if (cur.obj->type == kObjectTypeDictionary) { + // stack: โฆ, dict, key + if (cur.obj->data.dictionary.size + == cur.obj->data.dictionary.capacity) { + lua_pop(lstate, 2); + continue; + } + bool next_key_found = false; + while (lua_next(lstate, -2)) { + // stack: โฆ, dict, new key, val + if (lua_type(lstate, -2) == LUA_TSTRING) { + next_key_found = true; + break; + } + lua_pop(lstate, 1); + // stack: โฆ, dict, new key + } + if (next_key_found) { + // stack: โฆ, dict, new key, val + size_t len; + const char *s = lua_tolstring(lstate, -2, &len); + const size_t idx = cur.obj->data.dictionary.size++; + cur.obj->data.dictionary.items[idx].key = (String) { + .data = xmemdupz(s, len), + .size = len, + }; + kv_push(stack, cur); + cur = (ObjPopStackItem) { + .obj = &cur.obj->data.dictionary.items[idx].value, + .container = false, + }; + } else { + // stack: โฆ, dict + lua_pop(lstate, 1); + // stack: โฆ + continue; + } + } else { + if (cur.obj->data.array.size == cur.obj->data.array.capacity) { + lua_pop(lstate, 1); + continue; + } + const size_t idx = cur.obj->data.array.size++; + lua_rawgeti(lstate, -1, (int)idx + 1); + if (lua_isnil(lstate, -1)) { + lua_pop(lstate, 2); + continue; + } + kv_push(stack, cur); + cur = (ObjPopStackItem) { + .obj = &cur.obj->data.array.items[idx], + .container = false, + }; + } + } + assert(!cur.container); + *cur.obj = NIL; + switch (lua_type(lstate, -1)) { + case LUA_TNIL: { + break; + } + case LUA_TBOOLEAN: { + *cur.obj = BOOLEAN_OBJ(lua_toboolean(lstate, -1)); + break; + } + case LUA_TSTRING: { + size_t len; + const char *s = lua_tolstring(lstate, -1, &len); + *cur.obj = STRING_OBJ(((String) { + .data = xmemdupz(s, len), + .size = len, + })); + break; + } + case LUA_TNUMBER: { + const lua_Number n = lua_tonumber(lstate, -1); + if (n > (lua_Number)API_INTEGER_MAX || n < (lua_Number)API_INTEGER_MIN + || ((lua_Number)((Integer)n)) != n) { + *cur.obj = FLOAT_OBJ((Float)n); + } else { + *cur.obj = INTEGER_OBJ((Integer)n); + } + break; + } + case LUA_TTABLE: { + const LuaTableProps table_props = nlua_traverse_table(lstate); + + switch (table_props.type) { + case kObjectTypeArray: { + *cur.obj = ARRAY_OBJ(((Array) { + .items = NULL, + .size = 0, + .capacity = 0, + })); + if (table_props.maxidx != 0) { + cur.obj->data.array.items = + xcalloc(table_props.maxidx, + sizeof(cur.obj->data.array.items[0])); + cur.obj->data.array.capacity = table_props.maxidx; + cur.container = true; + kv_push(stack, cur); + } + break; + } + case kObjectTypeDictionary: { + *cur.obj = DICTIONARY_OBJ(((Dictionary) { + .items = NULL, + .size = 0, + .capacity = 0, + })); + if (table_props.string_keys_num != 0) { + cur.obj->data.dictionary.items = + xcalloc(table_props.string_keys_num, + sizeof(cur.obj->data.dictionary.items[0])); + cur.obj->data.dictionary.capacity = table_props.string_keys_num; + cur.container = true; + kv_push(stack, cur); + lua_pushnil(lstate); + } + break; + } + case kObjectTypeFloat: { + *cur.obj = FLOAT_OBJ((Float)table_props.val); + break; + } + case kObjectTypeNil: { + api_set_error(err, kErrorTypeValidation, + "Cannot convert given lua table"); + break; + } + default: { + assert(false); + } + } + break; + } + default: { + api_set_error(err, kErrorTypeValidation, + "Cannot convert given lua type"); + break; + } + } + if (!cur.container) { + lua_pop(lstate, 1); + } + } + kv_destroy(stack); + if (ERROR_SET(err)) { + api_free_object(ret); + ret = NIL; + lua_pop(lstate, lua_gettop(lstate) - initial_size + 1); + } + assert(lua_gettop(lstate) == initial_size - 1); + return ret; +} + +#define GENERATE_INDEX_FUNCTION(type) \ +type nlua_pop_##type(lua_State *lstate, Error *err) \ + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT \ +{ \ + type ret; \ + ret = (type)lua_tonumber(lstate, -1); \ + lua_pop(lstate, 1); \ + return ret; \ +} + +GENERATE_INDEX_FUNCTION(Buffer) +GENERATE_INDEX_FUNCTION(Window) +GENERATE_INDEX_FUNCTION(Tabpage) + +#undef GENERATE_INDEX_FUNCTION + +/// Record some auxilary values in vim module +/// +/// Assumes that module table is on top of the stack. +/// +/// Recorded values: +/// +/// `vim.type_idx`: @see nlua_push_type_idx() +/// `vim.val_idx`: @see nlua_push_val_idx() +/// `vim.types`: table mapping possible values of `vim.type_idx` to string +/// names (i.e. `array`, `float`, `dictionary`) and back. +void nlua_init_types(lua_State *const lstate) +{ + LUA_PUSH_STATIC_STRING(lstate, "type_idx"); + nlua_push_type_idx(lstate); + lua_rawset(lstate, -3); + + LUA_PUSH_STATIC_STRING(lstate, "val_idx"); + nlua_push_val_idx(lstate); + lua_rawset(lstate, -3); + + LUA_PUSH_STATIC_STRING(lstate, "types"); + lua_createtable(lstate, 0, 3); + + LUA_PUSH_STATIC_STRING(lstate, "float"); + lua_pushnumber(lstate, (lua_Number)kObjectTypeFloat); + lua_rawset(lstate, -3); + lua_pushnumber(lstate, (lua_Number)kObjectTypeFloat); + LUA_PUSH_STATIC_STRING(lstate, "float"); + lua_rawset(lstate, -3); + + LUA_PUSH_STATIC_STRING(lstate, "array"); + lua_pushnumber(lstate, (lua_Number)kObjectTypeArray); + lua_rawset(lstate, -3); + lua_pushnumber(lstate, (lua_Number)kObjectTypeArray); + LUA_PUSH_STATIC_STRING(lstate, "array"); + lua_rawset(lstate, -3); + + LUA_PUSH_STATIC_STRING(lstate, "dictionary"); + lua_pushnumber(lstate, (lua_Number)kObjectTypeDictionary); + lua_rawset(lstate, -3); + lua_pushnumber(lstate, (lua_Number)kObjectTypeDictionary); + LUA_PUSH_STATIC_STRING(lstate, "dictionary"); + lua_rawset(lstate, -3); + + lua_rawset(lstate, -3); +} diff --git a/src/nvim/lua/converter.h b/src/nvim/lua/converter.h new file mode 100644 index 0000000000..542c56ea3e --- /dev/null +++ b/src/nvim/lua/converter.h @@ -0,0 +1,15 @@ +#ifndef NVIM_LUA_CONVERTER_H +#define NVIM_LUA_CONVERTER_H + +#include <lua.h> +#include <stdbool.h> +#include <stdint.h> + +#include "nvim/api/private/defs.h" +#include "nvim/func_attr.h" +#include "nvim/eval.h" + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "lua/converter.h.generated.h" +#endif +#endif // NVIM_LUA_CONVERTER_H diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c new file mode 100644 index 0000000000..eb821f7831 --- /dev/null +++ b/src/nvim/lua/executor.c @@ -0,0 +1,662 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + +#include <lua.h> +#include <lualib.h> +#include <lauxlib.h> + +#include "nvim/misc1.h" +#include "nvim/getchar.h" +#include "nvim/garray.h" +#include "nvim/func_attr.h" +#include "nvim/api/private/defs.h" +#include "nvim/api/private/helpers.h" +#include "nvim/api/vim.h" +#include "nvim/vim.h" +#include "nvim/ex_getln.h" +#include "nvim/ex_cmds2.h" +#include "nvim/message.h" +#include "nvim/memline.h" +#include "nvim/buffer_defs.h" +#include "nvim/macros.h" +#include "nvim/screen.h" +#include "nvim/cursor.h" +#include "nvim/undo.h" +#include "nvim/ascii.h" + +#include "nvim/lua/executor.h" +#include "nvim/lua/converter.h" + +typedef struct { + Error err; + String lua_err_str; +} LuaError; + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "lua/vim_module.generated.h" +# include "lua/executor.c.generated.h" +#endif + +/// Name of the run code for use in messages +#define NLUA_EVAL_NAME "<VimL compiled string>" + +/// Call C function which does not expect any arguments +/// +/// @param function Called function +/// @param numret Number of returned arguments +#define NLUA_CALL_C_FUNCTION_0(lstate, function, numret) \ + do { \ + lua_pushcfunction(lstate, &function); \ + lua_call(lstate, 0, numret); \ + } while (0) +/// Call C function which expects one argument +/// +/// @param function Called function +/// @param numret Number of returned arguments +/// @param aโฆ Supplied argument (should be a void* pointer) +#define NLUA_CALL_C_FUNCTION_1(lstate, function, numret, a1) \ + do { \ + lua_pushcfunction(lstate, &function); \ + lua_pushlightuserdata(lstate, a1); \ + lua_call(lstate, 1, numret); \ + } while (0) +/// Call C function which expects two arguments +/// +/// @param function Called function +/// @param numret Number of returned arguments +/// @param aโฆ Supplied argument (should be a void* pointer) +#define NLUA_CALL_C_FUNCTION_2(lstate, function, numret, a1, a2) \ + do { \ + lua_pushcfunction(lstate, &function); \ + lua_pushlightuserdata(lstate, a1); \ + lua_pushlightuserdata(lstate, a2); \ + lua_call(lstate, 2, numret); \ + } while (0) +/// Call C function which expects three arguments +/// +/// @param function Called function +/// @param numret Number of returned arguments +/// @param aโฆ Supplied argument (should be a void* pointer) +#define NLUA_CALL_C_FUNCTION_3(lstate, function, numret, a1, a2, a3) \ + do { \ + lua_pushcfunction(lstate, &function); \ + lua_pushlightuserdata(lstate, a1); \ + lua_pushlightuserdata(lstate, a2); \ + lua_pushlightuserdata(lstate, a3); \ + lua_call(lstate, 3, numret); \ + } while (0) +/// Call C function which expects five arguments +/// +/// @param function Called function +/// @param numret Number of returned arguments +/// @param aโฆ Supplied argument (should be a void* pointer) +#define NLUA_CALL_C_FUNCTION_4(lstate, function, numret, a1, a2, a3, a4) \ + do { \ + lua_pushcfunction(lstate, &function); \ + lua_pushlightuserdata(lstate, a1); \ + lua_pushlightuserdata(lstate, a2); \ + lua_pushlightuserdata(lstate, a3); \ + lua_pushlightuserdata(lstate, a4); \ + lua_call(lstate, 4, numret); \ + } while (0) + +/// Convert lua error into a Vim error message +/// +/// @param lstate Lua interpreter state. +/// @param[in] msg Message base, must contain one `%s`. +static void nlua_error(lua_State *const lstate, const char *const msg) + FUNC_ATTR_NONNULL_ALL +{ + size_t len; + const char *const str = lua_tolstring(lstate, -1, &len); + + emsgf(msg, (int)len, str); + + lua_pop(lstate, 1); +} + +/// Compare two strings, ignoring case +/// +/// Expects two values on the stack: compared strings. Returns one of the +/// following numbers: 0, -1 or 1. +/// +/// Does no error handling: never call it with non-string or with some arguments +/// omitted. +static int nlua_stricmp(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL +{ + const char *s1 = luaL_checklstring(lstate, 1, NULL); + const char *s2 = luaL_checklstring(lstate, 2, NULL); + const int ret = STRICMP(s1, s2); + lua_pop(lstate, 2); + lua_pushnumber(lstate, (lua_Number)((ret > 0) - (ret < 0))); + return 1; +} + +/// Evaluate lua string +/// +/// Expects two values on the stack: string to evaluate, pointer to the +/// location where result is saved. Always returns nothing (from the lua point +/// of view). +static int nlua_exec_lua_string(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL +{ + const String *const str = (const String *)lua_touserdata(lstate, 1); + typval_T *const ret_tv = (typval_T *)lua_touserdata(lstate, 2); + lua_pop(lstate, 2); + + if (luaL_loadbuffer(lstate, str->data, str->size, NLUA_EVAL_NAME)) { + nlua_error(lstate, _("E5104: Error while creating lua chunk: %.*s")); + return 0; + } + if (lua_pcall(lstate, 0, 1, 0)) { + nlua_error(lstate, _("E5105: Error while calling lua chunk: %.*s")); + return 0; + } + if (!nlua_pop_typval(lstate, ret_tv)) { + return 0; + } + return 0; +} + +/// Evaluate lua string for each line in range +/// +/// Expects two values on the stack: string to evaluate and pointer to integer +/// array with line range. Always returns nothing (from the lua point of view). +static int nlua_exec_luado_string(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL +{ + const String *const str = (const String *)lua_touserdata(lstate, 1); + const linenr_T *const range = (const linenr_T *)lua_touserdata(lstate, 2); + lua_pop(lstate, 2); + +#define DOSTART "return function(line, linenr) " +#define DOEND " end" + const size_t lcmd_len = (str->size + + (sizeof(DOSTART) - 1) + + (sizeof(DOEND) - 1)); + char *lcmd; + if (lcmd_len < IOSIZE) { + lcmd = (char *)IObuff; + } else { + lcmd = xmalloc(lcmd_len + 1); + } + memcpy(lcmd, DOSTART, sizeof(DOSTART) - 1); + memcpy(lcmd + sizeof(DOSTART) - 1, str->data, str->size); + memcpy(lcmd + sizeof(DOSTART) - 1 + str->size, DOEND, sizeof(DOEND) - 1); +#undef DOSTART +#undef DOEND + + if (luaL_loadbuffer(lstate, lcmd, lcmd_len, NLUA_EVAL_NAME)) { + nlua_error(lstate, _("E5109: Error while creating lua chunk: %.*s")); + if (lcmd_len >= IOSIZE) { + xfree(lcmd); + } + return 0; + } + if (lcmd_len >= IOSIZE) { + xfree(lcmd); + } + if (lua_pcall(lstate, 0, 1, 0)) { + nlua_error(lstate, _("E5110: Error while creating lua function: %.*s")); + return 0; + } + for (linenr_T l = range[0]; l <= range[1]; l++) { + if (l > curbuf->b_ml.ml_line_count) { + break; + } + lua_pushvalue(lstate, -1); + lua_pushstring(lstate, (const char *)ml_get_buf(curbuf, l, false)); + lua_pushnumber(lstate, (lua_Number)l); + if (lua_pcall(lstate, 2, 1, 0)) { + nlua_error(lstate, _("E5111: Error while calling lua function: %.*s")); + break; + } + if (lua_isstring(lstate, -1)) { + size_t new_line_len; + const char *const new_line = lua_tolstring(lstate, -1, &new_line_len); + char *const new_line_transformed = xmemdupz(new_line, new_line_len); + for (size_t i = 0; i < new_line_len; i++) { + if (new_line_transformed[i] == NUL) { + new_line_transformed[i] = '\n'; + } + } + ml_replace(l, (char_u *)new_line_transformed, false); + changed_bytes(l, 0); + } + lua_pop(lstate, 1); + } + lua_pop(lstate, 1); + check_cursor(); + update_screen(NOT_VALID); + return 0; +} + +/// Evaluate lua file +/// +/// Expects one value on the stack: file to evaluate. Always returns nothing +/// (from the lua point of view). +static int nlua_exec_lua_file(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL +{ + const char *const filename = (const char *)lua_touserdata(lstate, 1); + lua_pop(lstate, 1); + + if (luaL_loadfile(lstate, filename)) { + nlua_error(lstate, _("E5112: Error while creating lua chunk: %.*s")); + return 0; + } + if (lua_pcall(lstate, 0, 0, 0)) { + nlua_error(lstate, _("E5113: Error while calling lua chunk: %.*s")); + return 0; + } + return 0; +} + +/// Initialize lua interpreter state +/// +/// Called by lua interpreter itself to initialize state. +static int nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL +{ + // stricmp + lua_pushcfunction(lstate, &nlua_stricmp); + lua_setglobal(lstate, "stricmp"); + + // print + lua_pushcfunction(lstate, &nlua_print); + lua_setglobal(lstate, "print"); + + // debug.debug + lua_getglobal(lstate, "debug"); + lua_pushcfunction(lstate, &nlua_debug); + lua_setfield(lstate, -2, "debug"); + lua_pop(lstate, 1); + + // vim + if (luaL_dostring(lstate, (char *)&vim_module[0])) { + nlua_error(lstate, _("E5106: Error while creating vim module: %.*s")); + return 1; + } + // vim.api + nlua_add_api_functions(lstate); + // vim.types, vim.type_idx, vim.val_idx + nlua_init_types(lstate); + lua_setglobal(lstate, "vim"); + return 0; +} + +/// Initialize lua interpreter +/// +/// Crashes NeoVim if initialization fails. Should be called once per lua +/// interpreter instance. +/// +/// @return New lua interpreter instance. +static lua_State *nlua_init(void) + FUNC_ATTR_NONNULL_RET FUNC_ATTR_WARN_UNUSED_RESULT +{ + lua_State *lstate = luaL_newstate(); + if (lstate == NULL) { + EMSG(_("E970: Failed to initialize lua interpreter")); + preserve_exit(); + } + luaL_openlibs(lstate); + NLUA_CALL_C_FUNCTION_0(lstate, nlua_state_init, 0); + return lstate; +} + +/// Enter lua interpreter +/// +/// Calls nlua_init() if needed. Is responsible for pre-lua call initalization +/// like updating `package.[c]path` with directories derived from &runtimepath. +/// +/// @return Interprter instance to use. Will either be initialized now or taken +/// from previous initalization. +static lua_State *nlua_enter(void) + FUNC_ATTR_NONNULL_RET FUNC_ATTR_WARN_UNUSED_RESULT +{ + static lua_State *global_lstate = NULL; + if (global_lstate == NULL) { + global_lstate = nlua_init(); + } + lua_State *const lstate = global_lstate; + // Last used p_rtp value. Must not be dereferenced because value pointed to + // may already be freed. Used to check whether &runtimepath option value + // changed. + static const void *last_p_rtp = NULL; + if (last_p_rtp != (const void *)p_rtp) { + // stack: (empty) + lua_getglobal(lstate, "vim"); + // stack: vim + lua_getfield(lstate, -1, "_update_package_paths"); + // stack: vim, vim._update_package_paths + if (lua_pcall(lstate, 0, 0, 0)) { + // stack: vim, error + nlua_error(lstate, _("E5117: Error while updating package paths: %.*s")); + // stack: vim + } + // stack: vim + lua_pop(lstate, 1); + // stack: (empty) + last_p_rtp = (const void *)p_rtp; + } + return lstate; +} + +/// Execute lua string +/// +/// @param[in] str String to execute. +/// @param[out] ret_tv Location where result will be saved. +/// +/// @return Result of the execution. +void executor_exec_lua(const String str, typval_T *const ret_tv) + FUNC_ATTR_NONNULL_ALL +{ + NLUA_CALL_C_FUNCTION_2(nlua_enter(), nlua_exec_lua_string, 0, + (void *)&str, ret_tv); +} + +/// Evaluate lua string +/// +/// Used for luaeval(). Expects three values on the stack: +/// +/// 1. String to evaluate. +/// 2. _A value. +/// 3. Pointer to location where result is saved. +/// +/// @param[in,out] lstate Lua interpreter state. +static int nlua_eval_lua_string(lua_State *const lstate) + FUNC_ATTR_NONNULL_ALL +{ + const String *const str = (const String *)lua_touserdata(lstate, 1); + typval_T *const arg = (typval_T *)lua_touserdata(lstate, 2); + typval_T *const ret_tv = (typval_T *)lua_touserdata(lstate, 3); + lua_pop(lstate, 3); + + garray_T str_ga; + ga_init(&str_ga, 1, 80); +#define EVALHEADER "local _A=select(1,...) return (" + const size_t lcmd_len = sizeof(EVALHEADER) - 1 + str->size + 1; + char *lcmd; + if (lcmd_len < IOSIZE) { + lcmd = (char *)IObuff; + } else { + lcmd = xmalloc(lcmd_len); + } + memcpy(lcmd, EVALHEADER, sizeof(EVALHEADER) - 1); + memcpy(lcmd + sizeof(EVALHEADER) - 1, str->data, str->size); + lcmd[lcmd_len - 1] = ')'; +#undef EVALHEADER + if (luaL_loadbuffer(lstate, lcmd, lcmd_len, NLUA_EVAL_NAME)) { + nlua_error(lstate, + _("E5107: Error while creating lua chunk for luaeval(): %.*s")); + if (lcmd != (char *)IObuff) { + xfree(lcmd); + } + return 0; + } + if (lcmd != (char *)IObuff) { + xfree(lcmd); + } + + if (arg == NULL || arg->v_type == VAR_UNKNOWN) { + lua_pushnil(lstate); + } else { + nlua_push_typval(lstate, arg); + } + if (lua_pcall(lstate, 1, 1, 0)) { + nlua_error(lstate, + _("E5108: Error while calling lua chunk for luaeval(): %.*s")); + return 0; + } + if (!nlua_pop_typval(lstate, ret_tv)) { + return 0; + } + + return 0; +} + +/// Evaluate lua string +/// +/// Expects four values on the stack: string to evaluate, pointer to args array, +/// and locations where result and error are saved, respectively. Always +/// returns nothing (from the lua point of view). +static int nlua_exec_lua_string_api(lua_State *const lstate) + FUNC_ATTR_NONNULL_ALL +{ + const String *str = (const String *)lua_touserdata(lstate, 1); + const Array *args = (const Array *)lua_touserdata(lstate, 2); + Object *retval = (Object *)lua_touserdata(lstate, 3); + Error *err = (Error *)lua_touserdata(lstate, 4); + + lua_pop(lstate, 4); + + if (luaL_loadbuffer(lstate, str->data, str->size, "<nvim>")) { + size_t len; + const char *str = lua_tolstring(lstate, -1, &len); + api_set_error(err, kErrorTypeValidation, + "Error loading lua: %.*s", (int)len, str); + return 0; + } + + for (size_t i = 0; i < args->size; i++) { + nlua_push_Object(lstate, args->items[i]); + } + + if (lua_pcall(lstate, (int)args->size, 1, 0)) { + size_t len; + const char *str = lua_tolstring(lstate, -1, &len); + api_set_error(err, kErrorTypeException, + "Error executing lua: %.*s", (int)len, str); + return 0; + } + + *retval = nlua_pop_Object(lstate, err); + + return 0; +} + +/// Print as a Vim message +/// +/// @param lstate Lua interpreter state. +static int nlua_print(lua_State *const lstate) + FUNC_ATTR_NONNULL_ALL +{ +#define PRINT_ERROR(msg) \ + do { \ + errmsg = msg; \ + errmsg_len = sizeof(msg) - 1; \ + goto nlua_print_error; \ + } while (0) + const int nargs = lua_gettop(lstate); + lua_getglobal(lstate, "tostring"); + const char *errmsg = NULL; + size_t errmsg_len = 0; + garray_T msg_ga; + ga_init(&msg_ga, 1, 80); + int curargidx = 1; + for (; curargidx <= nargs; curargidx++) { + lua_pushvalue(lstate, -1); // tostring + lua_pushvalue(lstate, curargidx); // arg + if (lua_pcall(lstate, 1, 1, 0)) { + errmsg = lua_tolstring(lstate, -1, &errmsg_len); + goto nlua_print_error; + } + size_t len; + const char *const s = lua_tolstring(lstate, -1, &len); + if (s == NULL) { + PRINT_ERROR( + "<Unknown error: lua_tolstring returned NULL for tostring result>"); + } + ga_concat_len(&msg_ga, s, len); + if (curargidx < nargs) { + ga_append(&msg_ga, ' '); + } + lua_pop(lstate, 1); + } +#undef PRINT_ERROR + lua_pop(lstate, nargs + 1); + ga_append(&msg_ga, NUL); + { + const size_t len = (size_t)msg_ga.ga_len - 1; + char *const str = (char *)msg_ga.ga_data; + + for (size_t i = 0; i < len;) { + const size_t start = i; + while (i < len) { + switch (str[i]) { + case NUL: { + str[i] = NL; + i++; + continue; + } + case NL: { + str[i] = NUL; + i++; + break; + } + default: { + i++; + continue; + } + } + break; + } + msg((char_u *)str + start); + } + if (len && str[len - 1] == NUL) { // Last was newline + msg((char_u *)""); + } + } + ga_clear(&msg_ga); + return 0; +nlua_print_error: + emsgf(_("E5114: Error while converting print argument #%i: %.*s"), + curargidx, errmsg_len, errmsg); + ga_clear(&msg_ga); + lua_pop(lstate, lua_gettop(lstate)); + return 0; +} + +/// debug.debug implementation: interaction with user while debugging +/// +/// @param lstate Lua interpreter state. +int nlua_debug(lua_State *lstate) + FUNC_ATTR_NONNULL_ALL +{ + const typval_T input_args[] = { + { + .v_lock = VAR_FIXED, + .v_type = VAR_STRING, + .vval.v_string = (char_u *)"lua_debug> ", + }, + { + .v_type = VAR_UNKNOWN, + }, + }; + for (;;) { + lua_settop(lstate, 0); + typval_T input; + get_user_input(input_args, &input, false); + msg_putchar('\n'); // Avoid outputting on input line. + if (input.v_type != VAR_STRING + || input.vval.v_string == NULL + || *input.vval.v_string == NUL + || STRCMP(input.vval.v_string, "cont") == 0) { + tv_clear(&input); + return 0; + } + if (luaL_loadbuffer(lstate, (const char *)input.vval.v_string, + STRLEN(input.vval.v_string), "=(debug command)")) { + nlua_error(lstate, _("E5115: Error while loading debug string: %.*s")); + } + tv_clear(&input); + if (lua_pcall(lstate, 0, 0, 0)) { + nlua_error(lstate, _("E5116: Error while calling debug string: %.*s")); + } + } + return 0; +} + +/// Evaluate lua string +/// +/// Used for luaeval(). +/// +/// @param[in] str String to execute. +/// @param[in] arg Second argument to `luaeval()`. +/// @param[out] ret_tv Location where result will be saved. +/// +/// @return Result of the execution. +void executor_eval_lua(const String str, typval_T *const arg, + typval_T *const ret_tv) + FUNC_ATTR_NONNULL_ALL +{ + NLUA_CALL_C_FUNCTION_3(nlua_enter(), nlua_eval_lua_string, 0, + (void *)&str, arg, ret_tv); +} + +/// Execute lua string +/// +/// Used for nvim_execute_lua(). +/// +/// @param[in] str String to execute. +/// @param[in] args array of ... args +/// @param[out] err Location where error will be saved. +/// +/// @return Return value of the execution. +Object executor_exec_lua_api(const String str, const Array args, Error *err) +{ + Object retval = NIL; + NLUA_CALL_C_FUNCTION_4(nlua_enter(), nlua_exec_lua_string_api, 0, + (void *)&str, (void *)&args, &retval, err); + return retval; +} + + +/// Run lua string +/// +/// Used for :lua. +/// +/// @param eap VimL command being run. +void ex_lua(exarg_T *const eap) + FUNC_ATTR_NONNULL_ALL +{ + size_t len; + char *const code = script_get(eap, &len); + if (eap->skip) { + xfree(code); + return; + } + typval_T tv = { .v_type = VAR_UNKNOWN }; + executor_exec_lua((String) { .data = code, .size = len }, &tv); + tv_clear(&tv); + xfree(code); +} + +/// Run lua string for each line in range +/// +/// Used for :luado. +/// +/// @param eap VimL command being run. +void ex_luado(exarg_T *const eap) + FUNC_ATTR_NONNULL_ALL +{ + if (u_save(eap->line1 - 1, eap->line2 + 1) == FAIL) { + EMSG(_("cannot save undo information")); + return; + } + const String cmd = { + .size = STRLEN(eap->arg), + .data = (char *)eap->arg, + }; + const linenr_T range[] = { eap->line1, eap->line2 }; + NLUA_CALL_C_FUNCTION_2(nlua_enter(), nlua_exec_luado_string, 0, + (void *)&cmd, (void *)range); +} + +/// Run lua file +/// +/// Used for :luafile. +/// +/// @param eap VimL command being run. +void ex_luafile(exarg_T *const eap) + FUNC_ATTR_NONNULL_ALL +{ + NLUA_CALL_C_FUNCTION_1(nlua_enter(), nlua_exec_lua_file, 0, + (void *)eap->arg); +} diff --git a/src/nvim/lua/executor.h b/src/nvim/lua/executor.h new file mode 100644 index 0000000000..0cbf290f64 --- /dev/null +++ b/src/nvim/lua/executor.h @@ -0,0 +1,25 @@ +#ifndef NVIM_LUA_EXECUTOR_H +#define NVIM_LUA_EXECUTOR_H + +#include <lua.h> + +#include "nvim/api/private/defs.h" +#include "nvim/func_attr.h" +#include "nvim/eval/typval.h" +#include "nvim/ex_cmds_defs.h" + +// Generated by msgpack-gen.lua +void nlua_add_api_functions(lua_State *lstate) REAL_FATTR_NONNULL_ALL; + +#define set_api_error(s, err) \ + do { \ + Error *err_ = (err); \ + err_->type = kErrorTypeException; \ + err_->set = true; \ + memcpy(&err_->msg[0], s, sizeof(s)); \ + } while (0) + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "lua/executor.h.generated.h" +#endif +#endif // NVIM_LUA_EXECUTOR_H diff --git a/src/nvim/lua/vim.lua b/src/nvim/lua/vim.lua new file mode 100644 index 0000000000..c7952520b0 --- /dev/null +++ b/src/nvim/lua/vim.lua @@ -0,0 +1,64 @@ +-- TODO(ZyX-I): Create compatibility layer. +--{{{1 package.path updater function +-- Last inserted paths. Used to clear out items from package.[c]path when they +-- are no longer in &runtimepath. +local last_nvim_paths = {} +local function _update_package_paths() + local cur_nvim_paths = {} + local rtps = vim.api.nvim_list_runtime_paths() + local sep = package.config:sub(1, 1) + for _, key in ipairs({'path', 'cpath'}) do + local orig_str = package[key] .. ';' + local pathtrails_ordered = {} + local orig = {} + -- Note: ignores trailing item without trailing `;`. Not using something + -- simpler in order to preserve empty items (stand for default path). + for s in orig_str:gmatch('[^;]*;') do + s = s:sub(1, -2) -- Strip trailing semicolon + orig[#orig + 1] = s + end + if key == 'path' then + -- /?.lua and /?/init.lua + pathtrails_ordered = {sep .. '?.lua', sep .. '?' .. sep .. 'init.lua'} + else + local pathtrails = {} + for _, s in ipairs(orig) do + -- Find out path patterns. pathtrail should contain something like + -- /?.so, \?.dll. This allows not to bother determining what correct + -- suffixes are. + local pathtrail = s:match('[/\\][^/\\]*%?.*$') + if pathtrail and not pathtrails[pathtrail] then + pathtrails[pathtrail] = true + pathtrails_ordered[#pathtrails_ordered + 1] = pathtrail + end + end + end + local new = {} + for _, rtp in ipairs(rtps) do + if not rtp:match(';') then + for _, pathtrail in pairs(pathtrails_ordered) do + local new_path = rtp .. sep .. 'lua' .. pathtrail + -- Always keep paths from &runtimepath at the start: + -- append them here disregarding orig possibly containing one of them. + new[#new + 1] = new_path + cur_nvim_paths[new_path] = true + end + end + end + for _, orig_path in ipairs(orig) do + -- Handle removing obsolete paths originating from &runtimepath: such + -- paths either belong to cur_nvim_paths and were already added above or + -- to last_nvim_paths and should not be added at all if corresponding + -- entry was removed from &runtimepath list. + if not (cur_nvim_paths[orig_path] or last_nvim_paths[orig_path]) then + new[#new + 1] = orig_path + end + end + package[key] = table.concat(new, ';') + end + last_nvim_paths = cur_nvim_paths +end +--{{{1 Module definition +return { + _update_package_paths = _update_package_paths, +} diff --git a/src/nvim/macros.h b/src/nvim/macros.h index df2b431e92..26d4f74b6a 100644 --- a/src/nvim/macros.h +++ b/src/nvim/macros.h @@ -19,24 +19,14 @@ # define MAX(X, Y) ((X) > (Y) ? (X) : (Y)) #endif -/* - * Position comparisons - */ -# define lt(a, b) (((a).lnum != (b).lnum) \ - ? (a).lnum < (b).lnum \ - : (a).col != (b).col \ - ? (a).col < (b).col \ - : (a).coladd < (b).coladd) -# define ltp(a, b) (((a)->lnum != (b)->lnum) \ - ? (a)->lnum < (b)->lnum \ - : (a)->col != (b)->col \ - ? (a)->col < (b)->col \ - : (a)->coladd < (b)->coladd) -# define equalpos(a, b) (((a).lnum == (b).lnum) && ((a).col == (b).col) && \ - ((a).coladd == (b).coladd)) -# define clearpos(a) {(a)->lnum = 0; (a)->col = 0; (a)->coladd = 0; } - -#define ltoreq(a, b) (lt(a, b) || equalpos(a, b)) +/// String with length +/// +/// For use in functions which accept (char *s, size_t len) pair in arguments. +/// +/// @param[in] s Static string. +/// +/// @return `s, sizeof(s) - 1` +#define S_LEN(s) (s), (sizeof(s) - 1) /* * lineempty() - return TRUE if the line is empty @@ -53,7 +43,7 @@ * toupper() and tolower() that use the current locale. * Careful: Only call TOUPPER_LOC() and TOLOWER_LOC() with a character in the * range 0 - 255. toupper()/tolower() on some systems can't handle others. - * Note: It is often better to use vim_tolower() and vim_toupper(), because many + * Note: It is often better to use mb_tolower() and mb_toupper(), because many * toupper() and tolower() implementations only work for ASCII. */ #define TOUPPER_LOC toupper @@ -85,7 +75,7 @@ do { \ if (*p_langmap \ && (condition) \ - && (!p_lnr || (p_lnr && typebuf_maplen() == 0)) \ + && (p_lrm || KeyTyped) \ && !KeyStuffed \ && (c) >= 0) \ { \ @@ -111,8 +101,10 @@ /* mch_open_rw(): invoke os_open() with third argument for user R/W. */ #if defined(UNIX) /* open in rw------- mode */ # define mch_open_rw(n, f) os_open((n), (f), (mode_t)0600) +#elif defined(WIN32) +# define mch_open_rw(n, f) os_open((n), (f), S_IREAD | S_IWRITE) #else -# define mch_open_rw(n, f) os_open((n), (f), 0) +# define mch_open_rw(n, f) os_open((n), (f), 0) #endif # define REPLACE_NORMAL(s) (((s) & REPLACE_FLAG) && !((s) & VREPLACE_FLAG)) @@ -138,7 +130,7 @@ // Backup multi-byte pointer. Only use with "p" > "s" ! # define mb_ptr_back(s, p) (p -= mb_head_off((char_u *)s, (char_u *)p - 1) + 1) // get length of multi-byte char, not including composing chars -# define mb_cptr2len(p) utf_ptr2len(p) +# define MB_CPTR2LEN(p) utf_ptr2len(p) # define MB_COPY_CHAR(f, t) mb_copy_char((const char_u **)(&f), &t); @@ -161,4 +153,34 @@ #define STR_(x) #x #define STR(x) STR_(x) +#ifndef __has_attribute +# define NVIM_HAS_ATTRIBUTE(x) 0 +#elif defined(__clang__) && __clang__ == 1 \ + && (__clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ <= 5)) +// Starting in Clang 3.6, __has_attribute was fixed to only report true for +// GNU-style attributes. Prior to that, it reported true if _any_ backend +// supported the attribute. +# define NVIM_HAS_ATTRIBUTE(x) 0 +#else +# define NVIM_HAS_ATTRIBUTE __has_attribute +#endif + +#if NVIM_HAS_ATTRIBUTE(fallthrough) +# define FALLTHROUGH __attribute__((fallthrough)) +#else +# define FALLTHROUGH +#endif + +// -V:STRUCT_CAST:641 + +/// Change type of structure pointers: cast `struct a *` to `struct b *` +/// +/// Used to silence PVS errors. +/// +/// @param Type Structure to cast to. +/// @param obj Object to cast. +/// +/// @return ((Type *)obj). +#define STRUCT_CAST(Type, obj) ((Type *)(obj)) + #endif // NVIM_MACROS_H diff --git a/src/nvim/main.c b/src/nvim/main.c index c7a60d07c1..024c56dd05 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -1,9 +1,17 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #define EXTERN #include <assert.h> #include <stdint.h> #include <string.h> #include <stdbool.h> +#ifdef WIN32 +# include <wchar.h> +# include <winnls.h> +#endif + #include <msgpack.h> #include "nvim/ascii.h" @@ -54,6 +62,7 @@ #include "nvim/os/input.h" #include "nvim/os/os.h" #include "nvim/os/time.h" +#include "nvim/os/fileio.h" #include "nvim/event/loop.h" #include "nvim/os/signal.h" #include "nvim/event/process.h" @@ -94,10 +103,8 @@ typedef struct { bool input_isatty; // stdin is a terminal bool output_isatty; // stdout is a terminal bool err_isatty; // stderr is a terminal - bool headless; // Dont try to start an user interface - // or read/write to stdio(unless - // embedding) - int no_swap_file; /* "-n" argument used */ + bool headless; // Do not start the builtin UI. + int no_swap_file; // "-n" argument used int use_debug_break_level; int window_count; /* number of windows to use */ int window_layout; /* 0, WIN_HOR, WIN_VER or WIN_TABS */ @@ -121,7 +128,7 @@ typedef struct { Loop main_loop; -static char *argv0; +static char *argv0 = NULL; // Error messages static const char *err_arg_missing = N_("Argument missing after"); @@ -150,10 +157,11 @@ void event_init(void) terminal_init(); } -void event_teardown(void) +/// @returns false if main_loop could not be closed gracefully +bool event_teardown(void) { if (!main_loop.events) { - return; + return true; } multiqueue_process_events(main_loop.events); @@ -165,7 +173,7 @@ void event_teardown(void) signal_teardown(); terminal_teardown(); - loop_close(&main_loop, true); + return loop_close(&main_loop, true); } /// Performs early initialization. @@ -176,11 +184,9 @@ void early_init(void) log_init(); fs_init(); handle_init(); - eval_init(); // init global variables - - // Init the table of Normal mode commands. - init_normal_cmds(); + init_path(argv0 ? argv0 : "nvim"); + init_normal_cmds(); // Init the table of Normal mode commands. #if defined(HAVE_LOCALE_H) // Setup to use the current locale (for ctype() and many other things). @@ -214,11 +220,23 @@ void early_init(void) #ifdef MAKE_LIB int nvim_main(int argc, char **argv) +#elif defined(WIN32) +int wmain(int argc, wchar_t **argv_w) // multibyte args on Windows. #7060 #else int main(int argc, char **argv) #endif { - argv0 = (char *)path_tail((char_u *)argv[0]); +#if defined(WIN32) && !defined(MAKE_LIB) + char *argv[argc]; + for (int i = 0; i < argc; i++) { + char *buf = NULL; + utf16_to_utf8(argv_w[i], &buf); + assert(buf); + argv[i] = buf; + } +#endif + + argv0 = argv[0]; char_u *fname = NULL; // file name from command line mparm_T params; // various parameters passed between @@ -238,10 +256,6 @@ int main(int argc, char **argv) // Check if we have an interactive window. check_and_set_isatty(¶ms); - // Get the name with which Nvim was invoked, with and without path. - set_vim_var_string(VV_PROGPATH, argv[0], -1); - set_vim_var_string(VV_PROGNAME, (char *) path_tail((char_u *) argv[0]), -1); - event_init(); /* * Process the command line arguments. File names are put in the global @@ -285,7 +299,7 @@ int main(int argc, char **argv) cmdline_row = (int)(Rows - p_ch); msg_row = cmdline_row; screenalloc(false); /* allocate screen buffers */ - set_init_2(); + set_init_2(params.headless); TIME_MSG("inits 2"); msg_scroll = TRUE; @@ -328,6 +342,12 @@ int main(int argc, char **argv) do_cmdline_cmd("augroup END"); #undef PROTO + // Reset 'loadplugins' for "-u NONE" before "--cmd" arguments. + // Allows for setting 'loadplugins' there. + if (params.use_vimrc != NULL && strcmp(params.use_vimrc, "NONE") == 0) { + p_lpl = false; + } + /* Execute --cmd arguments. */ exe_pre_commands(¶ms); @@ -387,9 +407,10 @@ int main(int argc, char **argv) shada_read_everything(NULL, false, true); TIME_MSG("reading ShaDa"); } - /* It's better to make v:oldfiles an empty list than NULL. */ - if (get_vim_var_list(VV_OLDFILES) == NULL) - set_vim_var_list(VV_OLDFILES, list_alloc()); + // It's better to make v:oldfiles an empty list than NULL. + if (get_vim_var_list(VV_OLDFILES) == NULL) { + set_vim_var_list(VV_OLDFILES, tv_list_alloc()); + } /* * "-q errorfile": Load the error file now. @@ -515,6 +536,12 @@ int main(int argc, char **argv) apply_autocmds(EVENT_VIMENTER, NULL, NULL, false, curbuf); TIME_MSG("VimEnter autocommands"); + // Adjust default register name for "unnamed" in 'clipboard'. Can only be + // done after the clipboard is available and all initial commands that may + // modify the 'clipboard' setting have run; i.e. just before entering the + // main loop. + set_reg_var(get_default_register_name()); + /* When a startup script or session file setup for diff'ing and * scrollbind, sync the scrollbind now. */ if (curwin->w_p_diff && curwin->w_p_scb) { @@ -578,9 +605,9 @@ void getout(int exitval) buf_T *buf = wp->w_buffer; if (buf->b_changedtick != -1) { apply_autocmds(EVENT_BUFWINLEAVE, buf->b_fname, - buf->b_fname, FALSE, buf); - buf->b_changedtick = -1; /* note that we did it already */ - /* start all over, autocommands may mess up the lists */ + buf->b_fname, false, buf); + buf_set_changedtick(buf, -1); // note that we did it already + // start all over, autocommands may mess up the lists next_tp = first_tabpage; break; } @@ -590,10 +617,13 @@ void getout(int exitval) /* Trigger BufUnload for buffers that are loaded */ FOR_ALL_BUFFERS(buf) { if (buf->b_ml.ml_mfp != NULL) { - apply_autocmds(EVENT_BUFUNLOAD, buf->b_fname, buf->b_fname, - FALSE, buf); - if (!buf_valid(buf)) /* autocmd may delete the buffer */ + bufref_T bufref; + set_bufref(&bufref, buf); + apply_autocmds(EVENT_BUFUNLOAD, buf->b_fname, buf->b_fname, false, buf); + if (!bufref_valid(&bufref)) { + // Autocmd deleted the buffer. break; + } } } apply_autocmds(EVENT_VIMLEAVEPRE, NULL, NULL, FALSE, curbuf); @@ -623,8 +653,9 @@ void getout(int exitval) iconv_end(); #endif cs_end(); - if (garbage_collect_at_exit) - garbage_collect(); + if (garbage_collect_at_exit) { + garbage_collect(false); + } mch_exit(exitval); } @@ -642,8 +673,9 @@ void getout(int exitval) /// /// @return argument's numeric value otherwise static int get_number_arg(const char *p, int *idx, int def) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT { - if (ascii_isdigit(p[*idx])) { + if (ascii_isdigit(p[*idx])) { // -V522 def = atoi(&(p[*idx])); while (ascii_isdigit(p[*idx])) { *idx = *idx + 1; @@ -750,16 +782,26 @@ static void command_line_scan(mparm_T *parmp) version(); mch_exit(0); } else if (STRICMP(argv[0] + argv_idx, "api-info") == 0) { - msgpack_sbuffer* b = msgpack_sbuffer_new(); - msgpack_packer* p = msgpack_packer_new(b, msgpack_sbuffer_write); - Object md = DICTIONARY_OBJ(api_metadata()); - msgpack_rpc_from_object(md, p); + FileDescriptor fp; + const int fof_ret = file_open_fd(&fp, OS_STDOUT_FILENO, true); + msgpack_packer *p = msgpack_packer_new(&fp, msgpack_file_write); + + if (fof_ret != 0) { + emsgf(_("E5421: Failed to open stdin: %s"), os_strerror(fof_ret)); + } - for (size_t i = 0; i < b->size; i++) { - putchar(b->data[i]); + if (p == NULL) { + emsgf(_(e_outofmem)); } + Object md = DICTIONARY_OBJ(api_metadata()); + msgpack_rpc_from_object(md, p); + msgpack_packer_free(p); + const int ff_ret = file_flush(&fp); + if (ff_ret < 0) { + msgpack_file_write_error(ff_ret); + } mch_exit(0); } else if (STRICMP(argv[0] + argv_idx, "headless") == 0) { parmp->headless = true; @@ -788,17 +830,18 @@ static void command_line_scan(mparm_T *parmp) argv_idx = -1; /* skip to next argument */ break; - case 'A': /* "-A" start in Arabic mode */ - set_option_value((char_u *)"arabic", 1L, NULL, 0); + case 'A': { // "-A" start in Arabic mode. + set_option_value("arabic", 1L, NULL, 0); break; - - case 'b': /* "-b" binary mode */ - /* Needs to be effective before expanding file names, because - * for Win32 this makes us edit a shortcut file itself, - * instead of the file it links to. */ + } + case 'b': { // "-b" binary mode. + // Needs to be effective before expanding file names, because + // for Win32 this makes us edit a shortcut file itself, + // instead of the file it links to. set_options_bin(curbuf->b_p_bin, 1, 0); - curbuf->b_p_bin = 1; /* binary file I/O */ + curbuf->b_p_bin = 1; // Binary file I/O. break; + } case 'e': /* "-e" Ex mode */ exmode_active = EXMODE_NORMAL; @@ -815,24 +858,27 @@ static void command_line_scan(mparm_T *parmp) main_start_gui(); break; - case 'F': /* "-F" start in Farsi mode: rl + fkmap set */ - p_fkmap = TRUE; - set_option_value((char_u *)"rl", 1L, NULL, 0); + case 'F': { // "-F" start in Farsi mode: rl + fkmap set. + p_fkmap = true; + set_option_value("rl", 1L, NULL, 0); break; + } case 'h': /* "-h" give help message */ usage(); mch_exit(0); - case 'H': /* "-H" start in Hebrew mode: rl + hkmap set */ - p_hkmap = TRUE; - set_option_value((char_u *)"rl", 1L, NULL, 0); + case 'H': { // "-H" start in Hebrew mode: rl + hkmap set. + p_hkmap = true; + set_option_value("rl", 1L, NULL, 0); break; + } - case 'l': /* "-l" lisp mode, 'lisp' and 'showmatch' on */ - set_option_value((char_u *)"lisp", 1L, NULL, 0); - p_sm = TRUE; + case 'l': { // "-l" lisp mode, 'lisp' and 'showmatch' on. + set_option_value("lisp", 1L, NULL, 0); + p_sm = true; break; + } case 'M': /* "-M" no changes or writing of files */ reset_modifiable(); @@ -901,10 +947,11 @@ static void command_line_scan(mparm_T *parmp) break; case 's': - if (exmode_active) /* "-s" silent (batch) mode */ - silent_mode = TRUE; - else /* "-s {scriptin}" read from script file */ - want_argument = TRUE; + if (exmode_active) { // "-es" silent (batch) mode + silent_mode = true; + } else { // "-s {scriptin}" read from script file + want_argument = true; + } break; case 't': /* "-t {tag}" or "-t{tag}" jump to tag */ @@ -931,8 +978,7 @@ static void command_line_scan(mparm_T *parmp) /* default is 10: a little bit verbose */ p_verbose = get_number_arg(argv[0], &argv_idx, 10); if (argv[0][argv_idx] != NUL) { - set_option_value((char_u *)"verbosefile", 0L, - (char_u *)argv[0] + argv_idx, 0); + set_option_value("verbosefile", 0L, argv[0] + argv_idx, 0); argv_idx = (int)STRLEN(argv[0]); } break; @@ -941,7 +987,7 @@ static void command_line_scan(mparm_T *parmp) /* "-w {scriptout}" write to script */ if (ascii_isdigit(((char_u *)argv[0])[argv_idx])) { n = get_number_arg(argv[0], &argv_idx, 10); - set_option_value((char_u *)"window", n, NULL, 0); + set_option_value("window", n, NULL, 0); break; } want_argument = TRUE; @@ -1073,7 +1119,7 @@ scripterror: if (ascii_isdigit(*((char_u *)argv[0]))) { argv_idx = 0; n = get_number_arg(argv[0], &argv_idx, 10); - set_option_value((char_u *)"window", n, NULL, 0); + set_option_value("window", n, NULL, 0); argv_idx = -1; break; } @@ -1194,9 +1240,29 @@ static void check_and_set_isatty(mparm_T *paramp) paramp->err_isatty = os_isatty(fileno(stderr)); TIME_MSG("window checked"); } -/* - * Get filename from command line, given that there is one. - */ + +// Sets v:progname and v:progpath. Also modifies $PATH on Windows. +static void init_path(const char *exename) + FUNC_ATTR_NONNULL_ALL +{ + char exepath[MAXPATHL] = { 0 }; + size_t exepathlen = MAXPATHL; + // Make v:progpath absolute. + if (os_exepath(exepath, &exepathlen) != 0) { + // Fall back to argv[0]. Missing procfs? #6734 + path_guess_exepath(exename, exepath, sizeof(exepath)); + } + set_vim_var_string(VV_PROGPATH, exepath, -1); + set_vim_var_string(VV_PROGNAME, (char *)path_tail((char_u *)exename), -1); + +#ifdef WIN32 + // Append the process start directory to $PATH, so that ":!foo" finds tools + // shipped with Windows package. This also mimics SearchPath(). + os_setenv_append_path(exepath); +#endif +} + +/// Get filename from command line, if any. static char_u *get_fname(mparm_T *parmp, char_u *cwd) { #if !defined(UNIX) @@ -1242,11 +1308,33 @@ static void set_window_layout(mparm_T *paramp) static void load_plugins(void) { if (p_lpl) { - source_runtime((char_u *)"plugin/**/*.vim", DIP_ALL); // NOLINT + char_u *rtp_copy = NULL; + + // First add all package directories to 'runtimepath', so that their + // autoload directories can be found. Only if not done already with a + // :packloadall command. + // Make a copy of 'runtimepath', so that source_runtime does not use the + // pack directories. + if (!did_source_packages) { + rtp_copy = vim_strsave(p_rtp); + add_pack_start_dirs(); + } + + source_in_path(rtp_copy == NULL ? p_rtp : rtp_copy, + (char_u *)"plugin/**/*.vim", // NOLINT + DIP_ALL | DIP_NOAFTER); TIME_MSG("loading plugins"); + xfree(rtp_copy); - ex_packloadall(NULL); + // Only source "start" packages if not done already with a :packloadall + // command. + if (!did_source_packages) { + load_start_packages(); + } TIME_MSG("loading packages"); + + source_runtime((char_u *)"plugin/**/*.vim", DIP_ALL | DIP_AFTER); + TIME_MSG("loading after plugins"); } } @@ -1261,8 +1349,8 @@ static void handle_quickfix(mparm_T *paramp) set_string_option_direct((char_u *)"ef", -1, paramp->use_ef, OPT_FREE, SID_CARG); vim_snprintf((char *)IObuff, IOSIZE, "cfile %s", p_ef); - if (qf_init(NULL, p_ef, p_efm, TRUE, IObuff) < 0) { - ui_putc('\n'); + if (qf_init(NULL, p_ef, p_efm, true, IObuff) < 0) { + ui_linefeed(); mch_exit(3); } TIME_MSG("reading errorfile"); @@ -1642,7 +1730,7 @@ static bool do_user_initialization(void) do { const char *dir; size_t dir_len; - iter = vim_colon_env_iter(config_dirs, iter, &dir, &dir_len); + iter = vim_env_iter(':', config_dirs, iter, &dir, &dir_len); if (dir == NULL || dir_len == 0) { break; } @@ -1682,8 +1770,6 @@ static void source_startup_scripts(const mparm_T *const parmp) if (parmp->use_vimrc != NULL) { if (strcmp(parmp->use_vimrc, "NONE") == 0 || strcmp(parmp->use_vimrc, "NORC") == 0) { - if (parmp->use_vimrc[2] == 'N') - p_lpl = false; // don't load plugins either } else { if (do_source((char_u *)parmp->use_vimrc, FALSE, DOSO_NONE) != OK) EMSG2(_("E282: Cannot read from \"%s\""), parmp->use_vimrc); @@ -1775,6 +1861,7 @@ static int process_env(char *env, bool is_viminit) /// os_fileinfo_link() respectively for extra security. static bool file_owned(const char *fname) { + assert(fname != NULL); uid_t uid = getuid(); FileInfo file_info; bool file_owned = os_fileinfo(fname, &file_info) @@ -1793,9 +1880,11 @@ static bool file_owned(const char *fname) /// @param str string to append to the primary error message, or NULL static void mainerr(const char *errstr, const char *str) { + char *prgname = (char *)path_tail((char_u *)argv0); + signal_stop(); // kill us with CTRL-C here, if you like - mch_errmsg(argv0); + mch_errmsg(prgname); mch_errmsg(": "); mch_errmsg(_(errstr)); if (str != NULL) { @@ -1804,7 +1893,7 @@ static void mainerr(const char *errstr, const char *str) mch_errmsg("\""); } mch_errmsg(_("\nMore info with \"")); - mch_errmsg(argv0); + mch_errmsg(prgname); mch_errmsg(" -h\"\n"); mch_exit(1); @@ -1825,54 +1914,47 @@ static void usage(void) signal_stop(); // kill us with CTRL-C here, if you like mch_msg(_("Usage:\n")); - mch_msg(_(" nvim [arguments] [file ...] Edit specified file(s)\n")); - mch_msg(_(" nvim [arguments] - Read text from stdin\n")); - mch_msg(_(" nvim [arguments] -t <tag> Edit file where tag is defined\n")); - mch_msg(_(" nvim [arguments] -q [errorfile] Edit file with first error\n")); - mch_msg(_("\nArguments:\n")); + mch_msg(_(" nvim [options] [file ...] Edit file(s)\n")); + mch_msg(_(" nvim [options] - Read text from stdin\n")); + mch_msg(_(" nvim [options] -t <tag> Edit file where tag is defined\n")); + mch_msg(_(" nvim [options] -q [errorfile] Edit file with first error\n")); + mch_msg(_("\nOptions:\n")); mch_msg(_(" -- Only file names after this\n")); -#if !defined(UNIX) - mch_msg(_(" --literal Don't expand wildcards\n")); -#endif - mch_msg(_(" -e Ex mode\n")); - mch_msg(_(" -E Improved Ex mode\n")); - mch_msg(_(" -s Silent (batch) mode (only for ex mode)\n")); + mch_msg(_(" + Start at end of file\n")); + mch_msg(_(" --cmd <cmd> Execute <cmd> before any config\n")); + mch_msg(_(" +<cmd>, -c <cmd> Execute <cmd> after config and first file\n")); + mch_msg("\n"); + mch_msg(_(" -b Binary mode\n")); mch_msg(_(" -d Diff mode\n")); - mch_msg(_(" -R Read-only mode\n")); - mch_msg(_(" -Z Restricted mode\n")); + mch_msg(_(" -e, -E Ex mode, Improved Ex mode\n")); + mch_msg(_(" -es Silent (batch) mode\n")); + mch_msg(_(" -h, --help Print this help message\n")); + mch_msg(_(" -i <shada> Use this shada file\n")); mch_msg(_(" -m Modifications (writing files) not allowed\n")); mch_msg(_(" -M Modifications in text not allowed\n")); - mch_msg(_(" -b Binary mode\n")); - mch_msg(_(" -l Lisp mode\n")); - mch_msg(_(" -A Arabic mode\n")); - mch_msg(_(" -F Farsi mode\n")); - mch_msg(_(" -H Hebrew mode\n")); - mch_msg(_(" -V[N][file] Be verbose [level N][log messages to file]\n")); - mch_msg(_(" -D Debugging mode\n")); 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 <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")); - mch_msg(_(" -O[N] Like -o but split vertically\n")); - mch_msg(_(" -p[N] Open N tab pages (default: one for each file)\n")); - 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 vimrc\n")); - mch_msg(_(" -c <command> Execute <command> after loading the first file\n")); + mch_msg(_(" -o[N] Open N windows (default: one per file)\n")); + mch_msg(_(" -O[N] Open N vertical windows (default: one per file)\n")); + mch_msg(_(" -p[N] Open N tab pages (default: one per file)\n")); + mch_msg(_(" -r, -L List swap files\n")); + mch_msg(_(" -r <file> Recover edit state for this file\n")); + mch_msg(_(" -R Read-only mode\n")); mch_msg(_(" -S <session> Source <session> after loading the first file\n")); mch_msg(_(" -s <scriptin> Read Normal mode commands from <scriptin>\n")); - mch_msg(_(" -w <scriptout> Append all typed characters to <scriptout>\n")); - mch_msg(_(" -W <scriptout> Write all typed characters to <scriptout>\n")); - mch_msg(_(" --startuptime <file> Write startup timing messages to <file>\n")); - mch_msg(_(" --api-info Dump API metadata serialized to msgpack and exit\n")); + mch_msg(_(" -u <config> Use this config file\n")); + mch_msg(_(" -v, --version Print version information\n")); + mch_msg(_(" -V[N][file] Verbose [level][file]\n")); + mch_msg(_(" -Z Restricted mode\n")); + mch_msg("\n"); + mch_msg(_(" --api-info Write msgpack-encoded API metadata to stdout\n")); mch_msg(_(" --embed Use stdin/stdout as a msgpack-rpc channel\n")); mch_msg(_(" --headless Don't start a user interface\n")); - mch_msg(_(" -v, --version Print version information and exit\n")); - mch_msg(_(" -h, --help Print this help message and exit\n")); +#if !defined(UNIX) + mch_msg(_(" --literal Don't expand wildcards\n")); +#endif + mch_msg(_(" --noplugin Don't load plugins\n")); + mch_msg(_(" --startuptime <file> Write startup timing messages to <file>\n")); + mch_msg(_("\nSee \":help startup-options\" for all options.\n")); } diff --git a/src/nvim/map.c b/src/nvim/map.c index 73af487f90..537b6751e2 100644 --- a/src/nvim/map.c +++ b/src/nvim/map.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #include <stdlib.h> #include <stdbool.h> #include <string.h> @@ -139,7 +142,6 @@ static inline bool String_eq(String a, String b) MAP_IMPL(int, int, DEFAULT_INITIALIZER) -MAP_IMPL(cstr_t, uint64_t, DEFAULT_INITIALIZER) MAP_IMPL(cstr_t, ptr_t, DEFAULT_INITIALIZER) MAP_IMPL(ptr_t, ptr_t, DEFAULT_INITIALIZER) MAP_IMPL(uint64_t, ptr_t, DEFAULT_INITIALIZER) @@ -147,4 +149,3 @@ MAP_IMPL(handle_T, ptr_t, DEFAULT_INITIALIZER) #define MSGPACK_HANDLER_INITIALIZER { .fn = NULL, .async = false } MAP_IMPL(String, MsgpackRpcRequestHandler, MSGPACK_HANDLER_INITIALIZER) #define KVEC_INITIALIZER { .size = 0, .capacity = 0, .items = NULL } -MAP_IMPL(linenr_T, bufhl_vec_T, KVEC_INITIALIZER) diff --git a/src/nvim/map.h b/src/nvim/map.h index ba3e84cb31..047aa163ce 100644 --- a/src/nvim/map.h +++ b/src/nvim/map.h @@ -25,13 +25,11 @@ void map_##T##_##U##_clear(Map(T, U) *map); MAP_DECLS(int, int) -MAP_DECLS(cstr_t, uint64_t) MAP_DECLS(cstr_t, ptr_t) MAP_DECLS(ptr_t, ptr_t) MAP_DECLS(uint64_t, ptr_t) MAP_DECLS(handle_T, ptr_t) MAP_DECLS(String, MsgpackRpcRequestHandler) -MAP_DECLS(linenr_T, bufhl_vec_T) #define map_new(T, U) map_##T##_##U##_new #define map_free(T, U) map_##T##_##U##_free diff --git a/src/nvim/mark.c b/src/nvim/mark.c index bb5b8e8178..7889fabd45 100644 --- a/src/nvim/mark.c +++ b/src/nvim/mark.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + /* * mark.c: functions for setting marks and jumping to them */ @@ -62,7 +65,7 @@ int setmark(int c) /// Free fmark_T item void free_fmark(fmark_T fm) { - dict_unref(fm.additional_data); + tv_dict_unref(fm.additional_data); } /// Free xfmark_T item @@ -130,9 +133,15 @@ int setmark_pos(int c, pos_T *pos, int fnum) return OK; } + buf_T *buf = buflist_findnr(fnum); + // Can't set a mark in a non-existant buffer. + if (buf == NULL) { + return FAIL; + } + if (ASCII_ISLOWER(c)) { i = c - 'a'; - RESET_FMARK(curbuf->b_namedm + i, *pos, curbuf->b_fnum); + RESET_FMARK(buf->b_namedm + i, *pos, fnum); return OK; } if (ASCII_ISUPPER(c) || ascii_isdigit(c)) { @@ -879,7 +888,29 @@ void ex_changes(exarg_T *eap) * Example: Insert two lines below 55: mark_adjust(56, MAXLNUM, 2, 0); * or: mark_adjust(56, 55, MAXLNUM, 2); */ -void mark_adjust(linenr_T line1, linenr_T line2, long amount, long amount_after) +void mark_adjust(linenr_T line1, + linenr_T line2, + long amount, + long amount_after, + bool end_temp) +{ + mark_adjust_internal(line1, line2, amount, amount_after, true, end_temp); +} + +// mark_adjust_nofold() does the same as mark_adjust() but without adjusting +// folds in any way. Folds must be adjusted manually by the caller. +// This is only useful when folds need to be moved in a way different to +// calling foldMarkAdjust() with arguments line1, line2, amount, amount_after, +// for an example of why this may be necessary, see do_move(). +void mark_adjust_nofold(linenr_T line1, linenr_T line2, long amount, + long amount_after, bool end_temp) +{ + mark_adjust_internal(line1, line2, amount, amount_after, false, end_temp); +} + +static void mark_adjust_internal(linenr_T line1, linenr_T line2, + long amount, long amount_after, + bool adjust_folds, bool end_temp) { int i; int fnum = curbuf->b_fnum; @@ -928,7 +959,7 @@ void mark_adjust(linenr_T line1, linenr_T line2, long amount, long amount_after) } sign_mark_adjust(line1, line2, amount, amount_after); - bufhl_mark_adjust(curbuf, line1, line2, amount, amount_after); + bufhl_mark_adjust(curbuf, line1, line2, amount, amount_after, end_temp); } /* previous context mark */ @@ -1005,8 +1036,9 @@ void mark_adjust(linenr_T line1, linenr_T line2, long amount, long amount_after) } } - /* adjust folds */ - foldMarkAdjust(win, line1, line2, amount, amount_after); + if (adjust_folds) { + foldMarkAdjust(win, line1, line2, amount, amount_after); + } } } @@ -1407,3 +1439,26 @@ void free_all_marks(void) memset(&namedfm[0], 0, sizeof(namedfm)); } #endif + +/// Adjust position to point to the first byte of a multi-byte character +/// +/// If it points to a tail byte it is move backwards to the head byte. +/// +/// @param[in] buf Buffer to adjust position in. +/// @param[out] lp Position to adjust. +void mark_mb_adjustpos(buf_T *buf, pos_T *lp) + FUNC_ATTR_NONNULL_ALL +{ + if (lp->col > 0 || lp->coladd > 1) { + const char_u *const p = ml_get_buf(buf, lp->lnum, false); + lp->col -= (*mb_head_off)(p, p + lp->col); + // Reset "coladd" when the cursor would be on the right half of a + // double-wide character. + if (lp->coladd == 1 + && p[lp->col] != TAB + && vim_isprintc((*mb_ptr2char)(p + lp->col)) + && ptr2cells(p + lp->col) > 1) { + lp->coladd = 0; + } + } +} diff --git a/src/nvim/mark.h b/src/nvim/mark.h index aff6e7273a..ed4e47907b 100644 --- a/src/nvim/mark.h +++ b/src/nvim/mark.h @@ -4,10 +4,12 @@ #include "nvim/macros.h" #include "nvim/ascii.h" #include "nvim/buffer_defs.h" +#include "nvim/func_attr.h" #include "nvim/mark_defs.h" #include "nvim/memory.h" #include "nvim/pos.h" #include "nvim/os/time.h" +#include "nvim/ex_cmds_defs.h" // for exarg_T /// Set fmark using given value #define SET_FMARK(fmarkp_, mark_, fnum_) \ @@ -29,7 +31,7 @@ /// Clear given fmark #define CLEAR_FMARK(fmarkp_) \ - RESET_FMARK(fmarkp_, ((pos_T) {0, 0, 0}), 0) + RESET_FMARK(fmarkp_, ((pos_T) { 0, 0, 0 }), 0) /// Set given extended mark (regular mark + file name) #define SET_XFMARK(xfmarkp_, mark_, fnum_, fname_) \ @@ -74,6 +76,46 @@ static inline int mark_local_index(const char name) : -1)))); } +static inline bool lt(pos_T, pos_T) REAL_FATTR_CONST REAL_FATTR_ALWAYS_INLINE; +static inline bool equalpos(pos_T, pos_T) + REAL_FATTR_CONST REAL_FATTR_ALWAYS_INLINE; +static inline bool ltoreq(pos_T, pos_T) + REAL_FATTR_CONST REAL_FATTR_ALWAYS_INLINE; +static inline void clearpos(pos_T *) + REAL_FATTR_ALWAYS_INLINE; + +/// Return true if position a is before (less than) position b. +static inline bool lt(pos_T a, pos_T b) +{ + if (a.lnum != b.lnum) { + return a.lnum < b.lnum; + } else if (a.col != b.col) { + return a.col < b.col; + } else { + return a.coladd < b.coladd; + } +} + +/// Return true if position a and b are equal. +static inline bool equalpos(pos_T a, pos_T b) +{ + return (a.lnum == b.lnum) && (a.col == b.col) && (a.coladd == b.coladd); +} + +/// Return true if position a is less than or equal to b. +static inline bool ltoreq(pos_T a, pos_T b) +{ + return lt(a, b) || equalpos(a, b); +} + +/// Clear the pos_T structure pointed to by a. +static inline void clearpos(pos_T *a) +{ + a->lnum = 0; + a->col = 0; + a->coladd = 0; +} + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "mark.h.generated.h" #endif diff --git a/src/nvim/mark_defs.h b/src/nvim/mark_defs.h index 720b2475ed..2cb489501e 100644 --- a/src/nvim/mark_defs.h +++ b/src/nvim/mark_defs.h @@ -3,7 +3,7 @@ #include "nvim/pos.h" #include "nvim/os/time.h" -#include "nvim/eval_defs.h" +#include "nvim/eval/typval.h" /* * marks: positions in a file diff --git a/src/nvim/mbyte.c b/src/nvim/mbyte.c index ec4969d4f6..b24770a409 100644 --- a/src/nvim/mbyte.c +++ b/src/nvim/mbyte.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + /// mbyte.c: Code specifically for handling multi-byte characters. /// Multibyte extensions partly by Sung-Hoon Baek /// @@ -50,6 +53,7 @@ #include "nvim/strings.h" #include "nvim/os/os.h" #include "nvim/arabic.h" +#include "nvim/mark.h" typedef struct { int rangeStart; @@ -71,7 +75,7 @@ struct interval { /* * Like utf8len_tab above, but using a zero for illegal lead bytes. */ -static uint8_t utf8len_tab_zero[256] = +const uint8_t utf8len_tab_zero[256] = { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, @@ -355,14 +359,13 @@ int bomb_size(void) */ void remove_bom(char_u *s) { - if (enc_utf8) { - char_u *p = s; + char *p = (char *)s; - while ((p = vim_strbyte(p, 0xef)) != NULL) { - if (p[1] == 0xbb && p[2] == 0xbf) - STRMOVE(p, p + 3); - else - ++p; + while ((p = strchr(p, 0xef)) != NULL) { + if ((uint8_t)p[1] == 0xbb && (uint8_t)p[2] == 0xbf) { + STRMOVE(p, p + 3); + } else { + p++; } } } @@ -376,166 +379,21 @@ void remove_bom(char_u *s) */ int mb_get_class(const char_u *p) { - return mb_get_class_buf(p, curbuf); + return mb_get_class_tab(p, curbuf->b_chartab); } -int mb_get_class_buf(const char_u *p, buf_T *buf) +int mb_get_class_tab(const char_u *p, const uint64_t *const chartab) { if (MB_BYTE2LEN(p[0]) == 1) { - if (p[0] == NUL || ascii_iswhite(p[0])) + if (p[0] == NUL || ascii_iswhite(p[0])) { return 0; - if (vim_iswordc_buf(p[0], buf)) + } + if (vim_iswordc_tab(p[0], chartab)) { return 2; + } return 1; } - if (enc_dbcs != 0 && p[0] != NUL && p[1] != NUL) - return dbcs_class(p[0], p[1]); - if (enc_utf8) - return utf_class(utf_ptr2char(p)); - return 0; -} - -/* - * Get class of a double-byte character. This always returns 3 or bigger. - * TODO: Should return 1 for punctuation. - */ -int dbcs_class(unsigned lead, unsigned trail) -{ - switch (enc_dbcs) { - /* please add classify routine for your language in here */ - - case DBCS_JPNU: /* ? */ - case DBCS_JPN: - { - /* JIS code classification */ - unsigned char lb = lead; - unsigned char tb = trail; - - /* convert process code to JIS */ - /* - * XXX: Code page identification can not use with all - * system! So, some other encoding information - * will be needed. - * In japanese: SJIS,EUC,UNICODE,(JIS) - * Note that JIS-code system don't use as - * process code in most system because it uses - * escape sequences(JIS is context depend encoding). - */ - /* assume process code is JAPANESE-EUC */ - lb &= 0x7f; - tb &= 0x7f; - /* exceptions */ - switch (lb << 8 | tb) { - case 0x2121: /* ZENKAKU space */ - return 0; - case 0x2122: /* TOU-TEN (Japanese comma) */ - case 0x2123: /* KU-TEN (Japanese period) */ - case 0x2124: /* ZENKAKU comma */ - case 0x2125: /* ZENKAKU period */ - return 1; - case 0x213c: /* prolongedsound handled as KATAKANA */ - return 13; - } - /* sieved by KU code */ - switch (lb) { - case 0x21: - case 0x22: - /* special symbols */ - return 10; - case 0x23: - /* alpha-numeric */ - return 11; - case 0x24: - /* hiragana */ - return 12; - case 0x25: - /* katakana */ - return 13; - case 0x26: - /* greek */ - return 14; - case 0x27: - /* russian */ - return 15; - case 0x28: - /* lines */ - return 16; - default: - /* kanji */ - return 17; - } - } - - case DBCS_KORU: /* ? */ - case DBCS_KOR: - { - /* KS code classification */ - unsigned char c1 = lead; - unsigned char c2 = trail; - - /* - * 20 : Hangul - * 21 : Hanja - * 22 : Symbols - * 23 : Alpha-numeric/Roman Letter (Full width) - * 24 : Hangul Letter(Alphabet) - * 25 : Roman Numeral/Greek Letter - * 26 : Box Drawings - * 27 : Unit Symbols - * 28 : Circled/Parenthesized Letter - * 29 : Hiragana/Katakana - * 30 : Cyrillic Letter - */ - - if (c1 >= 0xB0 && c1 <= 0xC8) - /* Hangul */ - return 20; - - else if (c1 >= 0xCA && c1 <= 0xFD) - /* Hanja */ - return 21; - else switch (c1) { - case 0xA1: - case 0xA2: - /* Symbols */ - return 22; - case 0xA3: - /* Alpha-numeric */ - return 23; - case 0xA4: - /* Hangul Letter(Alphabet) */ - return 24; - case 0xA5: - /* Roman Numeral/Greek Letter */ - return 25; - case 0xA6: - /* Box Drawings */ - return 26; - case 0xA7: - /* Unit Symbols */ - return 27; - case 0xA8: - case 0xA9: - if (c2 <= 0xAF) - return 25; /* Roman Letter */ - else if (c2 >= 0xF6) - return 22; /* Symbols */ - else - /* Circled/Parenthesized Letter */ - return 28; - case 0xAA: - case 0xAB: - /* Hiragana/Katakana */ - return 29; - case 0xAC: - /* Cyrillic Letter */ - return 30; - } - } - default: - break; - } - return 3; + return utf_class(utf_ptr2char(p)); } /* @@ -728,7 +586,7 @@ int utf_ptr2char(const char_u *p) * If byte sequence is illegal or incomplete, returns -1 and does not advance * "s". */ -static int utf_safe_read_char_adv(char_u **s, size_t *n) +static int utf_safe_read_char_adv(const char_u **s, size_t *n) { int c; @@ -770,7 +628,7 @@ static int utf_safe_read_char_adv(char_u **s, size_t *n) * Get character at **pp and advance *pp to the next character. * Note: composing characters are skipped! */ -int mb_ptr2char_adv(char_u **pp) +int mb_ptr2char_adv(const char_u **const pp) { int c; @@ -783,15 +641,12 @@ int mb_ptr2char_adv(char_u **pp) * Get character at **pp and advance *pp to the next character. * Note: composing characters are returned as separate characters. */ -int mb_cptr2char_adv(char_u **pp) +int mb_cptr2char_adv(const char_u **pp) { int c; c = (*mb_ptr2char)(*pp); - if (enc_utf8) - *pp += utf_ptr2len(*pp); - else - *pp += (*mb_ptr2len)(*pp); + *pp += utf_ptr2len(*pp); return c; } @@ -1077,12 +932,12 @@ int utf_char2len(int c) return 6; } -/* - * Convert Unicode character "c" to UTF-8 string in "buf[]". - * Returns the number of bytes. - * This does not include composing characters. - */ -int utf_char2bytes(int c, char_u *buf) +/// Convert Unicode character to UTF-8 string +/// +/// @param c character to convert to \p buf +/// @param[out] buf UTF-8 string generated from \p c, does not add \0 +/// @return Number of bytes (1-6). Does not include composing characters. +int utf_char2bytes(int c, char_u *const buf) { if (c < 0x80) { /* 7 bits */ buf[0] = c; @@ -1322,11 +1177,14 @@ int utf_fold(int a) return utf_convert(a, foldCase, ARRAY_SIZE(foldCase)); } -/* - * Return the upper-case equivalent of "a", which is a UCS-4 character. Use - * simple case folding. - */ -int utf_toupper(int a) +// Vim's own character class functions. These exist because many library +// islower()/toupper() etc. do not work properly: they crash when used with +// invalid values or can't handle latin1 when the locale is C. +// Speed is most important here. + +/// Return the upper-case equivalent of "a", which is a UCS-4 character. Use +/// simple case folding. +int mb_toupper(int a) { /* If 'casemap' contains "keepascii" use ASCII style toupper(). */ if (a < 128 && (cmp_flags & CMP_KEEPASCII)) @@ -1346,17 +1204,15 @@ int utf_toupper(int a) return utf_convert(a, toUpper, ARRAY_SIZE(toUpper)); } -bool utf_islower(int a) +bool mb_islower(int a) { - /* German sharp s is lower case but has no upper case equivalent. */ - return (utf_toupper(a) != a) || a == 0xdf; + // German sharp s is lower case but has no upper case equivalent. + return (mb_toupper(a) != a) || a == 0xdf; } -/* - * Return the lower-case equivalent of "a", which is a UCS-4 character. Use - * simple case folding. - */ -int utf_tolower(int a) +/// Return the lower-case equivalent of "a", which is a UCS-4 character. Use +/// simple case folding. +int mb_tolower(int a) { /* If 'casemap' contains "keepascii" use ASCII style tolower(). */ if (a < 128 && (cmp_flags & CMP_KEEPASCII)) @@ -1376,12 +1232,13 @@ int utf_tolower(int a) return utf_convert(a, toLower, ARRAY_SIZE(toLower)); } -bool utf_isupper(int a) +bool mb_isupper(int a) { - return utf_tolower(a) != a; + return mb_tolower(a) != a; } -static int utf_strnicmp(char_u *s1, char_u *s2, size_t n1, size_t n2) +static int utf_strnicmp(const char_u *s1, const char_u *s2, size_t n1, + size_t n2) { int c1, c2, cdiff; char_u buffer[6]; @@ -1451,6 +1308,7 @@ static int utf_strnicmp(char_u *s1, char_u *s2, size_t n1, size_t n2) # define CP_UTF8 65001 /* magic number from winnls.h */ #endif +/// Reassigns `strw` to a new, allocated pointer to a UTF16 string. int utf8_to_utf16(const char *str, WCHAR **strw) FUNC_ATTR_NONNULL_ALL { @@ -1484,42 +1342,48 @@ int utf8_to_utf16(const char *str, WCHAR **strw) (WCHAR *)pos, wchar_len); assert(r == wchar_len); + if (r != wchar_len) { + EMSG2("MultiByteToWideChar failed: %d", r); + } *strw = (WCHAR *)pos; return 0; } +/// Reassigns `str` to a new, allocated pointer to a UTF8 string. int utf16_to_utf8(const WCHAR *strw, char **str) FUNC_ATTR_NONNULL_ALL { // Compute the space required to store the string as UTF-8. - ssize_t utf8_len = WideCharToMultiByte(CP_UTF8, - 0, - strw, - -1, - NULL, - 0, - NULL, - NULL); + DWORD utf8_len = WideCharToMultiByte(CP_UTF8, + 0, + strw, + -1, + NULL, + 0, + NULL, + NULL); if (utf8_len == 0) { return GetLastError(); } - ssize_t buf_sz = utf8_len * sizeof(char); - char *buf = xmalloc(buf_sz); - char *pos = buf; + *str = xmallocz(utf8_len); - // Convert string to UTF-8. - int r = WideCharToMultiByte(CP_UTF8, - 0, - strw, - -1, - (LPSTR *)pos, - utf8_len, - NULL, - NULL); - assert(r == utf8_len); - *str = pos; + // Convert to UTF-8. + utf8_len = WideCharToMultiByte(CP_UTF8, + 0, + strw, + -1, + *str, + utf8_len, + NULL, + NULL); + if (utf8_len == 0) { + free(*str); + *str = NULL; + return GetLastError(); + } + (*str)[utf8_len] = '\0'; return 0; } @@ -1534,48 +1398,26 @@ int utf16_to_utf8(const WCHAR *strw, char **str) * Returns zero if s1 and s2 are equal (ignoring case), the difference between * two characters otherwise. */ -int mb_strnicmp(char_u *s1, char_u *s2, size_t nn) -{ - int i, l; - int cdiff; - int n = (int)nn; - - if (enc_utf8) { - return utf_strnicmp(s1, s2, nn, nn); - } else { - for (i = 0; i < n; i += l) { - if (s1[i] == NUL && s2[i] == NUL) /* both strings end */ - return 0; - - l = (*mb_ptr2len)(s1 + i); - if (l <= 1) { - /* Single byte: first check normally, then with ignore case. */ - if (s1[i] != s2[i]) { - cdiff = vim_tolower(s1[i]) - vim_tolower(s2[i]); - if (cdiff != 0) - return cdiff; - } - } else { - /* For non-Unicode multi-byte don't ignore case. */ - if (l > n - i) - l = n - i; - cdiff = STRNCMP(s1 + i, s2 + i, l); - if (cdiff != 0) - return cdiff; - } - } - } - return 0; +int mb_strnicmp(const char_u *s1, const char_u *s2, const size_t nn) +{ + return utf_strnicmp(s1, s2, nn, nn); } -/* We need to call mb_stricmp() even when we aren't dealing with a multi-byte - * encoding because mb_stricmp() takes care of all ascii and non-ascii - * encodings, including characters with umlauts in latin1, etc., while - * STRICMP() only handles the system locale version, which often does not - * handle non-ascii properly. */ -int mb_stricmp(char_u *s1, char_u *s2) +/// Compare strings case-insensitively +/// +/// @note We need to call mb_stricmp() even when we aren't dealing with +/// a multi-byte encoding because mb_stricmp() takes care of all ASCII and +/// non-ascii encodings, including characters with umlauts in latin1, +/// etc., while STRICMP() only handles the system locale version, which +/// often does not handle non-ascii properly. +/// +/// @param[in] s1 First string to compare, not more then #MAXCOL characters. +/// @param[in] s2 Second string to compare, not more then #MAXCOL characters. +/// +/// @return 0 if strings are equal, <0 if s1 < s2, >0 if s1 > s2. +int mb_stricmp(const char *s1, const char *s2) { - return mb_strnicmp(s1, s2, MAXCOL); + return mb_strnicmp((const char_u *)s1, (const char_u *)s2, MAXCOL); } /* @@ -1693,27 +1535,24 @@ int mb_off_next(char_u *base, char_u *p) int i; int j; - if (enc_utf8) { - if (*p < 0x80) /* be quick for ASCII */ - return 0; + if (*p < 0x80) { // be quick for ASCII + return 0; + } - /* Find the next character that isn't 10xx.xxxx */ - for (i = 0; (p[i] & 0xc0) == 0x80; ++i) - ; - if (i > 0) { - /* Check for illegal sequence. */ - for (j = 0; p - j > base; ++j) - if ((p[-j] & 0xc0) != 0x80) - break; - if (utf8len_tab[p[-j]] != i + j) - return 0; + // Find the next character that isn't 10xx.xxxx + for (i = 0; (p[i] & 0xc0) == 0x80; i++) {} + if (i > 0) { + // Check for illegal sequence. + for (j = 0; p - j > base; j++) { + if ((p[-j] & 0xc0) != 0x80) { + break; + } + } + if (utf8len_tab[p[-j]] != i + j) { + return 0; } - return i; } - - /* Only need to check if we're on a trail byte, it doesn't matter if we - * want the offset to the next or current character. */ - return (*mb_head_off)(base, p); + return i; } /* @@ -1756,10 +1595,10 @@ void utf_find_illegal(void) char_u *tofree = NULL; vimconv.vc_type = CONV_NONE; - if (enc_utf8 && (enc_canon_props(curbuf->b_p_fenc) & ENC_8BIT)) { - /* 'encoding' is "utf-8" but we are editing a 8-bit encoded file, - * possibly a utf-8 file with illegal bytes. Setup for conversion - * from utf-8 to 'fileencoding'. */ + if (enc_canon_props(curbuf->b_p_fenc) & ENC_8BIT) { + // 'encoding' is "utf-8" but we are editing a 8-bit encoded file, + // possibly a utf-8 file with illegal bytes. Setup for conversion + // from utf-8 to 'fileencoding'. convert_setup(&vimconv, p_enc, curbuf->b_p_fenc); } @@ -1816,29 +1655,42 @@ theend: */ void mb_adjust_cursor(void) { - mb_adjustpos(curbuf, &curwin->w_cursor); + mark_mb_adjustpos(curbuf, &curwin->w_cursor); } -/* - * Adjust position "*lp" to point to the first byte of a multi-byte character. - * If it points to a tail byte it's moved backwards to the head byte. - */ -void mb_adjustpos(buf_T *buf, pos_T *lp) +/// Checks and adjusts cursor column. Not mode-dependent. +/// @see check_cursor_col_win +/// +/// @param win_ Places cursor on a valid column for this window. +void mb_check_adjust_col(void *win_) { - char_u *p; + win_T *win = (win_T *)win_; + colnr_T oldcol = win->w_cursor.col; + + // Column 0 is always valid. + if (oldcol != 0) { + char_u *p = ml_get_buf(win->w_buffer, win->w_cursor.lnum, false); + colnr_T len = (colnr_T)STRLEN(p); - if (lp->col > 0 - || lp->coladd > 1 - ) { - p = ml_get_buf(buf, lp->lnum, FALSE); - lp->col -= (*mb_head_off)(p, p + lp->col); - /* Reset "coladd" when the cursor would be on the right half of a - * double-wide character. */ - if (lp->coladd == 1 - && p[lp->col] != TAB - && vim_isprintc((*mb_ptr2char)(p + lp->col)) - && ptr2cells(p + lp->col) > 1) - lp->coladd = 0; + // Empty line or invalid column? + if (len == 0 || oldcol < 0) { + win->w_cursor.col = 0; + } else { + // Cursor column too big for line? + if (oldcol > len) { + win->w_cursor.col = len - 1; + } + // Move the cursor to the head byte. + win->w_cursor.col -= (*mb_head_off)(p, p + win->w_cursor.col); + } + + // Reset `coladd` when the cursor would be on the right half of a + // double-wide character. + if (win->w_cursor.coladd == 1 && p[win->w_cursor.col] != TAB + && vim_isprintc((*mb_ptr2char)(p + win->w_cursor.col)) + && ptr2cells(p + win->w_cursor.col) > 1) { + win->w_cursor.coladd = 0; + } } } @@ -1887,52 +1739,55 @@ int mb_charlen_len(char_u *str, int len) return count; } -/* - * Try to un-escape a multi-byte character. - * Used for the "to" and "from" part of a mapping. - * Return the un-escaped string if it is a multi-byte character, and advance - * "pp" to just after the bytes that formed it. - * Return NULL if no multi-byte char was found. - */ -char_u * mb_unescape(char_u **pp) -{ - static char_u buf[6]; - int n; - int m = 0; - char_u *str = *pp; - - /* Must translate K_SPECIAL KS_SPECIAL KE_FILLER to K_SPECIAL and CSI - * KS_EXTRA KE_CSI to CSI. - * Maximum length of a utf-8 character is 4 bytes. */ - for (n = 0; str[n] != NUL && m < 4; ++n) { - if (str[n] == K_SPECIAL - && str[n + 1] == KS_SPECIAL - && str[n + 2] == KE_FILLER) { - buf[m++] = K_SPECIAL; - n += 2; - } else if ((str[n] == K_SPECIAL - ) - && str[n + 1] == KS_EXTRA - && str[n + 2] == (int)KE_CSI) { - buf[m++] = CSI; - n += 2; - } else if (str[n] == K_SPECIAL - ) - break; /* a special key can't be a multibyte char */ - else - buf[m++] = str[n]; - buf[m] = NUL; +/// Try to unescape a multibyte character +/// +/// Used for the rhs and lhs of the mappings. +/// +/// @param[in,out] pp String to unescape. Is advanced to just after the bytes +/// that form a multibyte character. +/// +/// @return Unescaped string if it is a multibyte character, NULL if no +/// multibyte character was found. Returns a static buffer, always one +/// and the same. +const char *mb_unescape(const char **const pp) + FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL +{ + static char buf[6]; + size_t buf_idx = 0; + uint8_t *str = (uint8_t *)(*pp); + + // Must translate K_SPECIAL KS_SPECIAL KE_FILLER to K_SPECIAL and CSI + // KS_EXTRA KE_CSI to CSI. + // Maximum length of a utf-8 character is 4 bytes. + for (size_t str_idx = 0; str[str_idx] != NUL && buf_idx < 4; str_idx++) { + if (str[str_idx] == K_SPECIAL + && str[str_idx + 1] == KS_SPECIAL + && str[str_idx + 2] == KE_FILLER) { + buf[buf_idx++] = (char)K_SPECIAL; + str_idx += 2; + } else if ((str[str_idx] == K_SPECIAL) + && str[str_idx + 1] == KS_EXTRA + && str[str_idx + 2] == KE_CSI) { + buf[buf_idx++] = (char)CSI; + str_idx += 2; + } else if (str[str_idx] == K_SPECIAL) { + break; // A special key can't be a multibyte char. + } else { + buf[buf_idx++] = (char)str[str_idx]; + } + buf[buf_idx] = NUL; - /* Return a multi-byte character if it's found. An illegal sequence - * will result in a 1 here. */ - if ((*mb_ptr2len)(buf) > 1) { - *pp = str + n + 1; + // Return a multi-byte character if it's found. An illegal sequence + // will result in a 1 here. + if (utf_ptr2len((const char_u *)buf) > 1) { + *pp = (const char *)str + str_idx + 1; return buf; } - /* Bail out quickly for ASCII. */ - if (buf[0] < 128) + // Bail out quickly for ASCII. + if ((uint8_t)buf[0] < 128) { break; + } } return NULL; } @@ -2181,8 +2036,8 @@ void * my_iconv_open(char_u *to, char_u *from) * Returns the converted string in allocated memory. NULL for an error. * If resultlenp is not NULL, sets it to the result length in bytes. */ -static char_u * iconv_string(vimconv_T *vcp, char_u *str, size_t slen, - size_t *unconvlenp, size_t *resultlenp) +static char_u *iconv_string(const vimconv_T *const vcp, char_u *str, + size_t slen, size_t *unconvlenp, size_t *resultlenp) { const char *from; size_t fromlen; @@ -2238,13 +2093,7 @@ static char_u * iconv_string(vimconv_T *vcp, char_u *str, size_t slen, *to++ = '?'; if ((*mb_ptr2cells)((char_u *)from) > 1) *to++ = '?'; - if (enc_utf8) - l = utfc_ptr2len_len((const char_u *)from, (int)fromlen); - else { - l = (*mb_ptr2len)((char_u *)from); - if (l > (int)fromlen) - l = (int)fromlen; - } + l = utfc_ptr2len_len((const char_u *)from, (int)fromlen); from += l; fromlen -= l; } else if (ICONV_ERRNO != ICONV_E2BIG) { @@ -2473,7 +2322,7 @@ int convert_setup_ext(vimconv_T *vcp, char_u *from, bool from_unicode_is_utf8, * Illegal chars are often changed to "?", unless vcp->vc_fail is set. * When something goes wrong, NULL is returned and "*lenp" is unchanged. */ -char_u * string_convert(vimconv_T *vcp, char_u *ptr, size_t *lenp) +char_u *string_convert(const vimconv_T *const vcp, char_u *ptr, size_t *lenp) { return string_convert_ext(vcp, ptr, lenp, NULL); } @@ -2483,7 +2332,7 @@ char_u * string_convert(vimconv_T *vcp, char_u *ptr, size_t *lenp) * an incomplete sequence at the end it is not converted and "*unconvlenp" is * set to the number of remaining bytes. */ -char_u * string_convert_ext(vimconv_T *vcp, char_u *ptr, +char_u * string_convert_ext(const vimconv_T *const vcp, char_u *ptr, size_t *lenp, size_t *unconvlenp) { char_u *retval = NULL; diff --git a/src/nvim/mbyte.h b/src/nvim/mbyte.h index 2c92a0fbb2..bf6ccb13a5 100644 --- a/src/nvim/mbyte.h +++ b/src/nvim/mbyte.h @@ -1,7 +1,14 @@ #ifndef NVIM_MBYTE_H #define NVIM_MBYTE_H +#include <stdint.h> #include <stdbool.h> +#include <string.h> + +#include "nvim/iconv.h" +#include "nvim/func_attr.h" +#include "nvim/os/os_defs.h" // For WCHAR, indirect +#include "nvim/types.h" // for char_u /* * Return byte length of character that starts with byte "b". @@ -12,6 +19,9 @@ #define MB_BYTE2LEN(b) utf8len_tab[b] #define MB_BYTE2LEN_CHECK(b) (((b) < 0 || (b) > 255) ? 1 : utf8len_tab[b]) +// max length of an unicode char +#define MB_MAXCHAR 6 + /* properties used in enc_canon_table[] (first three mutually exclusive) */ #define ENC_8BIT 0x01 #define ENC_DBCS 0x02 @@ -40,7 +50,43 @@ #define mb_ptr2char utf_ptr2char #define mb_head_off utf_head_off +/// Flags for vimconv_T +typedef enum { + CONV_NONE = 0, + CONV_TO_UTF8 = 1, + CONV_9_TO_UTF8 = 2, + CONV_TO_LATIN1 = 3, + CONV_TO_LATIN9 = 4, + CONV_ICONV = 5, +} ConvFlags; + +/// Structure used for string conversions +typedef struct { + int vc_type; ///< Zero or more ConvFlags. + int vc_factor; ///< Maximal expansion factor. +# ifdef USE_ICONV + iconv_t vc_fd; ///< Value for CONV_ICONV. +# endif + bool vc_fail; ///< What to do with invalid characters: if true, fail, + ///< otherwise use '?'. +} vimconv_T; + +extern const uint8_t utf8len_tab_zero[256]; + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "mbyte.h.generated.h" #endif + +static inline int mb_strcmp_ic(bool ic, const char *s1, const char *s2) + REAL_FATTR_NONNULL_ALL REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT; + +/// Compare strings +/// +/// @param[in] ic True if case is to be ignored. +/// +/// @return 0 if s1 == s2, <0 if s1 < s2, >0 if s1 > s2. +static inline int mb_strcmp_ic(bool ic, const char *s1, const char *s2) +{ + return (ic ? mb_stricmp(s1, s2) : strcmp(s1, s2)); +} #endif // NVIM_MBYTE_H diff --git a/src/nvim/memfile.c b/src/nvim/memfile.c index 43412e3916..4428dd42aa 100644 --- a/src/nvim/memfile.c +++ b/src/nvim/memfile.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + /// An abstraction to handle blocks of memory which can be stored in a file. /// This is the implementation of a sort of virtual memory. /// @@ -51,6 +54,7 @@ #include "nvim/memory.h" #include "nvim/os_unix.h" #include "nvim/path.h" +#include "nvim/assert.h" #include "nvim/os/os.h" #include "nvim/os/input.h" @@ -105,23 +109,24 @@ memfile_T *mf_open(char_u *fname, int flags) if (mfp->mf_fd >= 0 && os_fileinfo_fd(mfp->mf_fd, &file_info)) { uint64_t blocksize = os_fileinfo_blocksize(&file_info); if (blocksize >= MIN_SWAP_PAGE_SIZE && blocksize <= MAX_SWAP_PAGE_SIZE) { - assert(blocksize <= UINT_MAX); + STATIC_ASSERT(MAX_SWAP_PAGE_SIZE <= UINT_MAX, + "MAX_SWAP_PAGE_SIZE must fit into an unsigned"); mfp->mf_page_size = (unsigned)blocksize; } } - off_t size; + off_T size; // When recovering, the actual block size will be retrieved from block 0 // in ml_recover(). The size used here may be wrong, therefore mf_blocknr_max // must be rounded up. if (mfp->mf_fd < 0 || (flags & (O_TRUNC|O_EXCL)) - || (size = lseek(mfp->mf_fd, (off_t)0L, SEEK_END)) <= 0) { + || (size = vim_lseek(mfp->mf_fd, 0L, SEEK_END)) <= 0) { // no file or empty file mfp->mf_blocknr_max = 0; } else { - assert(sizeof(off_t) <= sizeof(blocknr_T) + assert(sizeof(off_T) <= sizeof(blocknr_T) && mfp->mf_page_size > 0 && mfp->mf_page_size - 1 <= INT64_MAX - size); mfp->mf_blocknr_max = (((blocknr_T)size + mfp->mf_page_size - 1) @@ -684,9 +689,9 @@ static int mf_read(memfile_T *mfp, bhdr_T *hp) return FAIL; unsigned page_size = mfp->mf_page_size; - // TODO(elmart): Check (page_size * hp->bh_bnum) within off_t bounds. - off_t offset = (off_t)(page_size * hp->bh_bnum); - if (lseek(mfp->mf_fd, offset, SEEK_SET) != offset) { + // TODO(elmart): Check (page_size * hp->bh_bnum) within off_T bounds. + off_T offset = (off_T)(page_size * hp->bh_bnum); + if (vim_lseek(mfp->mf_fd, offset, SEEK_SET) != offset) { PERROR(_("E294: Seek error in swap file read")); return FAIL; } @@ -711,7 +716,7 @@ static int mf_read(memfile_T *mfp, bhdr_T *hp) /// - Write error in swap file. static int mf_write(memfile_T *mfp, bhdr_T *hp) { - off_t offset; // offset in the file + off_T offset; // offset in the file blocknr_T nr; // block nr which is being written bhdr_T *hp2; unsigned page_size; // number of bytes in a page @@ -740,9 +745,9 @@ static int mf_write(memfile_T *mfp, bhdr_T *hp) hp2 = hp; } - // TODO(elmart): Check (page_size * nr) within off_t bounds. - offset = (off_t)(page_size * nr); - if (lseek(mfp->mf_fd, offset, SEEK_SET) != offset) { + // TODO(elmart): Check (page_size * nr) within off_T bounds. + offset = (off_T)(page_size * nr); + if (vim_lseek(mfp->mf_fd, offset, SEEK_SET) != offset) { PERROR(_("E296: Seek error in swap file write")); return FAIL; } @@ -890,6 +895,7 @@ static bool mf_do_open(memfile_T *mfp, char_u *fname, int flags) { // fname cannot be NameBuff, because it must have been allocated. mf_set_fnames(mfp, fname); + assert(mfp->mf_fname != NULL); /// Extra security check: When creating a swap file it really shouldn't /// exist yet. If there is a symbolic link, this is most likely an attack. @@ -909,12 +915,7 @@ static bool mf_do_open(memfile_T *mfp, char_u *fname, int flags) return false; } -#ifdef HAVE_FD_CLOEXEC - int fdflags = fcntl(mfp->mf_fd, F_GETFD); - if (fdflags >= 0 && (fdflags & FD_CLOEXEC) == 0) { - (void)fcntl(mfp->mf_fd, F_SETFD, fdflags | FD_CLOEXEC); - } -#endif + (void)os_set_cloexec(mfp->mf_fd); #ifdef HAVE_SELINUX mch_copy_sec(fname, mfp->mf_fname); #endif diff --git a/src/nvim/memfile_defs.h b/src/nvim/memfile_defs.h index cc71e1a7ff..b3c2f3564c 100644 --- a/src/nvim/memfile_defs.h +++ b/src/nvim/memfile_defs.h @@ -3,8 +3,10 @@ #include <stdint.h> #include <stdbool.h> +#include <stdlib.h> #include "nvim/types.h" +#include "nvim/pos.h" /// A block number. /// diff --git a/src/nvim/memline.c b/src/nvim/memline.c index a9a53ebca7..f28a9e60f4 100644 --- a/src/nvim/memline.c +++ b/src/nvim/memline.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + /* for debugging */ /* #define CHECK(c, s) if (c) EMSG(s) */ #define CHECK(c, s) @@ -439,14 +442,7 @@ void ml_setname(buf_T *buf) EMSG(_("E301: Oops, lost the swap file!!!")); return; } -#ifdef HAVE_FD_CLOEXEC - { - int fdflags = fcntl(mfp->mf_fd, F_GETFD); - if (fdflags >= 0 && (fdflags & FD_CLOEXEC) == 0) { - (void)fcntl(mfp->mf_fd, F_SETFD, fdflags | FD_CLOEXEC); - } - } -#endif + (void)os_set_cloexec(mfp->mf_fd); } if (!success) EMSG(_("E302: Could not rename swap file")); @@ -623,7 +619,7 @@ static bool ml_check_b0_strings(ZERO_BL *b0p) return (memchr(b0p->b0_version, NUL, 10) && memchr(b0p->b0_uname, NUL, B0_UNAME_SIZE) && memchr(b0p->b0_hname, NUL, B0_HNAME_SIZE) - && memchr(b0p->b0_fname, NUL, B0_FNAME_SIZE_CRYPT)); + && memchr(b0p->b0_fname, NUL, B0_FNAME_SIZE_CRYPT)); // -V512 } /* @@ -767,7 +763,7 @@ void ml_recover(void) int idx; int top; int txt_start; - off_t size; + off_T size; int called_from_main; int serious_error = TRUE; long mtime; @@ -918,10 +914,11 @@ void ml_recover(void) msg_end(); goto theend; } - if ((size = lseek(mfp->mf_fd, (off_t)0L, SEEK_END)) <= 0) - mfp->mf_blocknr_max = 0; /* no file or empty file */ - else + if ((size = vim_lseek(mfp->mf_fd, (off_T)0L, SEEK_END)) <= 0) { + mfp->mf_blocknr_max = 0; // no file or empty file + } else { mfp->mf_blocknr_max = size / mfp->mf_page_size; + } mfp->mf_infile_count = mfp->mf_blocknr_max; /* need to reallocate the memory used to store the data */ @@ -999,7 +996,7 @@ void ml_recover(void) if (b0_ff != 0) set_fileformat(b0_ff - 1, OPT_LOCAL); if (b0_fenc != NULL) { - set_option_value((char_u *)"fenc", 0L, b0_fenc, OPT_LOCAL); + set_option_value("fenc", 0L, (char *)b0_fenc, OPT_LOCAL); xfree(b0_fenc); } unchanged(curbuf, TRUE); @@ -1063,11 +1060,12 @@ void ml_recover(void) if (!cannot_open) { line_count = pp->pb_pointer[idx].pe_line_count; if (readfile(curbuf->b_ffname, NULL, lnum, - pp->pb_pointer[idx].pe_old_lnum - 1, - line_count, NULL, 0) == FAIL) - cannot_open = TRUE; - else + pp->pb_pointer[idx].pe_old_lnum - 1, line_count, + NULL, 0) != OK) { + cannot_open = true; + } else { lnum += line_count; + } } if (cannot_open) { ++error; @@ -1179,7 +1177,7 @@ void ml_recover(void) * empty. Don't set the modified flag then. */ if (!(curbuf->b_ml.ml_line_count == 2 && *ml_get(1) == NUL)) { changed_int(); - ++curbuf->b_changedtick; + buf_set_changedtick(curbuf, curbuf->b_changedtick + 1); } } else { for (idx = 1; idx <= lnum; ++idx) { @@ -1189,7 +1187,7 @@ void ml_recover(void) xfree(p); if (i != 0) { changed_int(); - ++curbuf->b_changedtick; + buf_set_changedtick(curbuf, curbuf->b_changedtick + 1); break; } } @@ -1409,8 +1407,8 @@ recover_names ( for (int i = 0; i < num_files; ++i) { /* print the swap file name */ msg_outnum((long)++file_count); - MSG_PUTS(". "); - msg_puts(path_tail(files[i])); + msg_puts(". "); + msg_puts((const char *)path_tail(files[i])); msg_putchar('\n'); (void)swapfile_info(files[i]); } @@ -1462,6 +1460,7 @@ static int process_still_running; */ static time_t swapfile_info(char_u *fname) { + assert(fname != NULL); int fd; struct block0 b0; time_t x = (time_t)0; @@ -2317,7 +2316,7 @@ ml_append_int ( * * return FAIL for failure, OK otherwise */ -int ml_replace(linenr_T lnum, char_u *line, int copy) +int ml_replace(linenr_T lnum, char_u *line, bool copy) { if (line == NULL) /* just checking... */ return FAIL; @@ -3137,6 +3136,7 @@ attention_message ( char_u *fname /* swap file name */ ) { + assert(buf->b_fname != NULL); time_t x, sx; char *p; @@ -3368,29 +3368,32 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, } if (swap_exists_action != SEA_NONE && choice == 0) { - char *name; + const char *const sw_msg_1 = _("Swap file \""); + const char *const sw_msg_2 = _("\" already exists!"); const size_t fname_len = strlen(fname); - name = xmalloc(fname_len - + strlen(_("Swap file \"")) - + strlen(_("\" already exists!")) + 5); - STRCPY(name, _("Swap file \"")); - home_replace(NULL, (char_u *) fname, (char_u *)&name[strlen(name)], - fname_len, true); - STRCAT(name, _("\" already exists!")); - choice = do_dialog(VIM_WARNING, - (char_u *)_("VIM - ATTENTION"), - (char_u *)(name == NULL - ? _("Swap file already exists!") - : name), + const size_t sw_msg_1_len = strlen(sw_msg_1); + const size_t sw_msg_2_len = strlen(sw_msg_2); + + const size_t name_len = sw_msg_1_len + fname_len + sw_msg_2_len + 5; + + char *const name = xmalloc(name_len); + memcpy(name, sw_msg_1, sw_msg_1_len + 1); + home_replace(NULL, (char_u *)fname, (char_u *)&name[sw_msg_1_len], + fname_len, true); + xstrlcat(name, sw_msg_2, name_len); + choice = do_dialog(VIM_WARNING, (char_u *)_("VIM - ATTENTION"), + (char_u *)name, # if defined(UNIX) - process_still_running - ? (char_u *)_( - "&Open Read-Only\n&Edit anyway\n&Recover\n&Quit\n&Abort") : + process_still_running + ? (char_u *)_( + "&Open Read-Only\n&Edit anyway\n&Recover" + "\n&Quit\n&Abort") : # endif - (char_u *)_( - "&Open Read-Only\n&Edit anyway\n&Recover\n&Delete it\n&Quit\n&Abort"), - 1, NULL, FALSE); + (char_u *)_( + "&Open Read-Only\n&Edit anyway\n&Recover" + "\n&Delete it\n&Quit\n&Abort"), + 1, NULL, false); # if defined(UNIX) if (process_still_running && choice >= 4) diff --git a/src/nvim/memline.h b/src/nvim/memline.h index f84e86fea0..a239c6a031 100644 --- a/src/nvim/memline.h +++ b/src/nvim/memline.h @@ -2,6 +2,8 @@ #define NVIM_MEMLINE_H #include "nvim/types.h" +#include "nvim/pos.h" // for pos_T, linenr_T, colnr_T +#include "nvim/buffer_defs.h" // for buf_T #ifdef INCLUDE_GENERATED_DECLARATIONS # include "memline.h.generated.h" diff --git a/src/nvim/memory.c b/src/nvim/memory.c index 92ead873ae..328b96fd5c 100644 --- a/src/nvim/memory.c +++ b/src/nvim/memory.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + // Various routines dealing with allocation and deallocation of memory. #include <assert.h> @@ -342,10 +345,6 @@ char *xstpcpy(char *restrict dst, const char *restrict src) /// WARNING: xstpncpy will ALWAYS write maxlen bytes. If src is shorter than /// maxlen, zeroes will be written to the remaining bytes. /// -/// TODO(aktau): I don't see a good reason to have this last behaviour, and -/// it is potentially wasteful. Could we perhaps deviate from the standard -/// and not zero the rest of the buffer? -/// /// @param dst /// @param src /// @param maxlen @@ -364,29 +363,58 @@ char *xstpncpy(char *restrict dst, const char *restrict src, size_t maxlen) } } -/// xstrlcpy - Copy a %NUL terminated string into a sized buffer +/// xstrlcpy - Copy a NUL-terminated string into a sized buffer /// -/// Compatible with *BSD strlcpy: the result is always a valid -/// NUL-terminated string that fits in the buffer (unless, -/// of course, the buffer size is zero). It does not pad -/// out the result like strncpy() does. +/// Compatible with *BSD strlcpy: the result is always a valid NUL-terminated +/// string that fits in the buffer (unless, of course, the buffer size is +/// zero). It does not pad out the result like strncpy() does. /// -/// @param dst Where to copy the string to -/// @param src Where to copy the string from -/// @param size Size of destination buffer -/// @return Length of the source string (i.e.: strlen(src)) -size_t xstrlcpy(char *restrict dst, const char *restrict src, size_t size) +/// @param dst Buffer to store the result +/// @param src String to be copied +/// @param dsize Size of `dst` +/// @return strlen(src). If retval >= dstsize, truncation occurs. +size_t xstrlcpy(char *restrict dst, const char *restrict src, size_t dsize) FUNC_ATTR_NONNULL_ALL { - size_t ret = strlen(src); + size_t slen = strlen(src); - if (size) { - size_t len = (ret >= size) ? size - 1 : ret; + if (dsize) { + size_t len = MIN(slen, dsize - 1); memcpy(dst, src, len); dst[len] = '\0'; } - return ret; + return slen; // Does not include NUL. +} + +/// Appends `src` to string `dst` of size `dsize` (unlike strncat, dsize is the +/// full size of `dst`, not space left). At most dsize-1 characters +/// will be copied. Always NUL terminates. `src` and `dst` may overlap. +/// +/// @see vim_strcat from Vim. +/// @see strlcat from OpenBSD. +/// +/// @param dst Buffer to be appended-to. Must have a NUL byte. +/// @param src String to put at the end of `dst` +/// @param dsize Size of `dst` including NUL byte. Must be greater than 0. +/// @return strlen(src) + strlen(initial dst) +/// If retval >= dsize, truncation occurs. +size_t xstrlcat(char *const dst, const char *const src, const size_t dsize) + FUNC_ATTR_NONNULL_ALL +{ + assert(dsize > 0); + const size_t dlen = strlen(dst); + assert(dlen < dsize); + const size_t slen = strlen(src); + + if (slen > dsize - dlen - 1) { + memmove(dst + dlen, src, dsize - dlen - 1); + dst[dsize - 1] = '\0'; + } else { + memmove(dst + dlen, src, slen + 1); + } + + return slen + dlen; // Does not include NUL. } /// strdup() wrapper @@ -401,6 +429,19 @@ char *xstrdup(const char *str) return xmemdupz(str, strlen(str)); } +/// strdup() wrapper +/// +/// Unlike xstrdup() allocates a new empty string if it receives NULL. +char *xstrdupnul(const char *const str) + FUNC_ATTR_MALLOC FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_RET +{ + if (str == NULL) { + return xmallocz(0); + } else { + return xstrdup(str); + } +} + /// A version of memchr that starts the search at `src + len`. /// /// Based on glibc's memrchr. @@ -446,6 +487,20 @@ void *xmemdup(const void *data, size_t len) return memcpy(xmalloc(len), data, len); } +/// Returns true if strings `a` and `b` are equal. Arguments may be NULL. +bool strequal(const char *a, const char *b) + FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT +{ + return (a == NULL && b == NULL) || (a && b && strcmp(a, b) == 0); +} + +/// Case-insensitive `strequal`. +bool striequal(const char *a, const char *b) + FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT +{ + return (a == NULL && b == NULL) || (a && b && STRICMP(a, b) == 0); +} + /* * Avoid repeating the error message many times (they take 1 second each). * Did_outofmem_msg is reset when a character is read. @@ -530,7 +585,7 @@ void free_all_mem(void) p_ea = false; if (first_tabpage->tp_next != NULL) do_cmdline_cmd("tabonly!"); - if (firstwin != lastwin) + if (!ONE_WINDOW) do_cmdline_cmd("only!"); /* Free all spell info. */ @@ -596,18 +651,6 @@ void free_all_mem(void) /* Destroy all windows. Must come before freeing buffers. */ win_free_all(); - /* Free all buffers. Reset 'autochdir' to avoid accessing things that - * were freed already. */ - p_acd = false; - for (buf = firstbuf; buf != NULL; ) { - nextbuf = buf->b_next; - close_buffer(NULL, buf, DOBUF_WIPE, false); - if (buf_valid(buf)) - buf = nextbuf; /* didn't work, try next one */ - else - buf = firstbuf; - } - free_cmdline_buf(); /* Clear registers. */ @@ -631,6 +674,20 @@ void free_all_mem(void) eval_clear(); + // Free all buffers. Reset 'autochdir' to avoid accessing things that + // were freed already. + // Must be after eval_clear to avoid it trying to access b:changedtick after + // freeing it. + p_acd = false; + for (buf = firstbuf; buf != NULL; ) { + bufref_T bufref; + set_bufref(&bufref, buf); + nextbuf = buf->b_next; + close_buffer(NULL, buf, DOBUF_WIPE, false); + // Didn't work, try next one. + buf = bufref_valid(&bufref) ? nextbuf : firstbuf; + } + /* screenlines (can't display anything now!) */ free_screenlines(); diff --git a/src/nvim/menu.c b/src/nvim/menu.c index 7c0eee64dd..0db250d111 100644 --- a/src/nvim/menu.c +++ b/src/nvim/menu.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + /* * Code for menus. Used for the GUI and 'wildmenu'. * GUI/Motif support by Robert Webb @@ -23,7 +26,7 @@ #include "nvim/state.h" #include "nvim/strings.h" #include "nvim/ui.h" - +#include "nvim/eval/typval.h" #define MENUDEPTH 10 /* maximum depth of menus */ @@ -35,8 +38,8 @@ -/* The character for each menu mode */ -static char_u menu_mode_chars[] = {'n', 'v', 's', 'o', 'i', 'c', 't'}; +/// The character for each menu mode +static char_u menu_mode_chars[] = { 'n', 'v', 's', 'o', 'i', 'c', 't' }; static char_u e_notsubmenu[] = N_( "E327: Part of menu-item path is not sub-menu"); @@ -44,20 +47,16 @@ static char_u e_othermode[] = N_("E328: Menu only exists in another mode"); static char_u e_nomenu[] = N_("E329: No menu \"%s\""); -/* - * Do the :menu command and relatives. - */ -void -ex_menu ( - exarg_T *eap /* Ex command arguments */ -) +/// Do the :menu command and relatives. +/// @param eap Ex command arguments +void +ex_menu(exarg_T *eap) { char_u *menu_path; int modes; - char_u *map_to; + char_u *map_to; // command mapped to the menu entry int noremap; bool silent = false; - bool special = false; int unmenu; char_u *map_buf; char_u *arg; @@ -83,7 +82,7 @@ ex_menu ( continue; } if (STRNCMP(arg, "<special>", 9) == 0) { - special = true; + // Ignore obsolete "<special>" modifier. arg = skipwhite(arg + 9); continue; } @@ -91,7 +90,8 @@ ex_menu ( } - /* Locate an optional "icon=filename" argument. */ + // Locate an optional "icon=filename" argument + // TODO(nvim): Currently this is only parsed. Should expose it to UIs. if (STRNCMP(arg, "icon=", 5) == 0) { arg += 5; while (*arg != NUL && *arg != ' ') { @@ -105,12 +105,12 @@ ex_menu ( } } - /* - * Fill in the priority table. - */ - for (p = arg; *p; ++p) - if (!ascii_isdigit(*p) && *p != '.') + // Fill in the priority table. + for (p = arg; *p; p++) { + if (!ascii_isdigit(*p) && *p != '.') { break; + } + } if (ascii_iswhite(*p)) { for (i = 0; i < MENUDEPTH && !ascii_iswhite(*arg); ++i) { pri_tab[i] = getdigits_long(&arg); @@ -219,13 +219,12 @@ ex_menu ( map_buf = NULL; // Menu tips are plain text. } else { map_to = replace_termcodes(map_to, STRLEN(map_to), &map_buf, false, true, - special, CPO_TO_CPO_FLAGS); + true, CPO_TO_CPO_FLAGS); } menuarg.modes = modes; menuarg.noremap[0] = noremap; menuarg.silent[0] = silent; - add_menu_path(menu_path, &menuarg, pri_tab, map_to - ); + add_menu_path(menu_path, &menuarg, pri_tab, map_to); /* * For the PopUp menu, add a menu for each mode separately. @@ -244,22 +243,24 @@ ex_menu ( xfree(map_buf); } - ui_update_menu(); + ui_call_update_menu(); theend: ; } -/* - * Add the menu with the given name to the menu hierarchy - */ -static int -add_menu_path ( - char_u *menu_path, - vimmenu_T *menuarg, /* passes modes, iconfile, iconidx, - icon_builtin, silent[0], noremap[0] */ - long *pri_tab, - char_u *call_data + +/// Add the menu with the given name to the menu hierarchy +/// +/// @param[out] menuarg menu entry +/// @param[] pri_tab priority table +/// @param[in] call_data Right hand side command +static int +add_menu_path( + const char_u *const menu_path, + vimmenu_T *menuarg, + const long *const pri_tab, + const char_u *const call_data ) { char_u *path_name; @@ -294,8 +295,9 @@ add_menu_path ( if (map_to != NULL) { en_name = name; name = map_to; - } else + } else { en_name = NULL; + } dname = menu_text(name, NULL, NULL); if (*dname == NUL) { /* Only a mnemonic or accelerator is not valid. */ @@ -309,14 +311,15 @@ add_menu_path ( while (menu != NULL) { if (menu_name_equal(name, menu) || menu_name_equal(dname, menu)) { if (*next_name == NUL && menu->children != NULL) { - if (!sys_menu) + if (!sys_menu) { EMSG(_("E330: Menu path must not lead to a sub-menu")); + } goto erret; } - if (*next_name != NUL && menu->children == NULL - ) { - if (!sys_menu) + if (*next_name != NUL && menu->children == NULL) { + if (!sys_menu) { EMSG(_(e_notsubmenu)); + } goto erret; } break; @@ -350,7 +353,7 @@ add_menu_path ( menu->modes = modes; menu->enabled = MENU_ALL_MODES; menu->name = vim_strsave(name); - /* separate mnemonic and accelerator text from actual menu name */ + // separate mnemonic and accelerator text from actual menu name menu->dname = menu_text(name, &menu->mnemonic, &menu->actext); if (en_name != NULL) { menu->en_name = vim_strsave(en_name); @@ -362,9 +365,7 @@ add_menu_path ( menu->priority = pri_tab[pri_idx]; menu->parent = parent; - /* - * Add after menu that has lower priority. - */ + // Add after menu that has lower priority. menu->next = *lower_pri; *lower_pri = menu; @@ -390,8 +391,9 @@ add_menu_path ( name = next_name; xfree(dname); dname = NULL; - if (pri_tab[pri_idx + 1] != -1) - ++pri_idx; + if (pri_tab[pri_idx + 1] != -1) { + pri_idx++; + } } xfree(path_name); @@ -417,8 +419,7 @@ add_menu_path ( // Don't do this for "<Nop>". c = 0; d = 0; - if (amenu && call_data != NULL && *call_data != NUL - ) { + if (amenu && call_data != NULL && *call_data != NUL) { switch (1 << i) { case MENU_VISUAL_MODE: case MENU_SELECT_MODE: @@ -436,9 +437,9 @@ add_menu_path ( if (c != 0) { menu->strings[i] = xmalloc(STRLEN(call_data) + 5 ); menu->strings[i][0] = c; - if (d == 0) + if (d == 0) { STRCPY(menu->strings[i] + 1, call_data); - else { + } else { menu->strings[i][1] = d; STRCPY(menu->strings[i] + 2, call_data); } @@ -450,8 +451,9 @@ add_menu_path ( menu->strings[i][len + 1] = Ctrl_G; menu->strings[i][len + 2] = NUL; } - } else + } else { menu->strings[i] = p; + } menu->noremap[i] = menuarg->noremap[0]; menu->silent[i] = menuarg->silent[0]; } @@ -655,20 +657,107 @@ static void free_menu_string(vimmenu_T *menu, int idx) menu->strings[idx] = NULL; } -/* - * Show the mapping associated with a menu item or hierarchy in a sub-menu. - */ -static int show_menus(char_u *path_name, int modes) +/// Export menus +/// +/// @param[in] menu if null, starts from root_menu +/// @param modes, a choice of \ref MENU_MODES +/// @return a dict with name/commands +/// @see menu_get +static dict_T *menu_get_recursive(const vimmenu_T *menu, int modes) +{ + dict_T *dict; + + if (!menu || (menu->modes & modes) == 0x0) { + return NULL; + } + + dict = tv_dict_alloc(); + tv_dict_add_str(dict, S_LEN("name"), (char *)menu->dname); + tv_dict_add_nr(dict, S_LEN("priority"), (int)menu->priority); + tv_dict_add_nr(dict, S_LEN("hidden"), menu_is_hidden(menu->dname)); + + if (menu->mnemonic) { + char buf[MB_MAXCHAR + 1] = { 0 }; // > max value of utf8_char2bytes + utf_char2bytes(menu->mnemonic, (char_u *)buf); + tv_dict_add_str(dict, S_LEN("shortcut"), buf); + } + + if (menu->modes & MENU_TIP_MODE && menu->strings[MENU_INDEX_TIP]) { + tv_dict_add_str(dict, S_LEN("tooltip"), + (char *)menu->strings[MENU_INDEX_TIP]); + } + + if (!menu->children) { + // leaf menu + dict_T *commands = tv_dict_alloc(); + tv_dict_add_dict(dict, S_LEN("mappings"), commands); + + for (int bit = 0; bit < MENU_MODES; bit++) { + if ((menu->modes & modes & (1 << bit)) != 0) { + dict_T *impl = tv_dict_alloc(); + if (*menu->strings[bit] == NUL) { + tv_dict_add_str(impl, S_LEN("rhs"), (char *)"<Nop>"); + } else { + tv_dict_add_str(impl, S_LEN("rhs"), (char *)menu->strings[bit]); + } + tv_dict_add_nr(impl, S_LEN("silent"), menu->silent[bit]); + tv_dict_add_nr(impl, S_LEN("enabled"), + (menu->enabled & (1 << bit)) ? 1 : 0); + tv_dict_add_nr(impl, S_LEN("noremap"), + (menu->noremap[bit] & REMAP_NONE) ? 1 : 0); + tv_dict_add_nr(impl, S_LEN("sid"), + (menu->noremap[bit] & REMAP_SCRIPT) ? 1 : 0); + tv_dict_add_dict(commands, (char *)&menu_mode_chars[bit], 1, impl); + } + } + } else { + // visit recursively all children + list_T *children_list = tv_list_alloc(); + for (menu = menu->children; menu != NULL; menu = menu->next) { + dict_T *dic = menu_get_recursive(menu, modes); + if (tv_dict_len(dict) > 0) { + tv_list_append_dict(children_list, dic); + } + } + tv_dict_add_list(dict, S_LEN("submenus"), children_list); + } + return dict; +} + + +/// Export menus matching path \p path_name +/// +/// @param path_name +/// @param modes supported modes, see \ref MENU_MODES +/// @param[in,out] list must be allocated +/// @return false if could not find path_name +bool menu_get(char_u *const path_name, int modes, list_T *list) { - char_u *p; - char_u *name; vimmenu_T *menu; - vimmenu_T *parent = NULL; + menu = find_menu(root_menu, path_name, modes); + if (!menu) { + return false; + } + for (; menu != NULL; menu = menu->next) { + dict_T *dict = menu_get_recursive(menu, modes); + if (dict && tv_dict_len(dict) > 0) { + tv_list_append_dict(list, dict); + } + } + return true; +} - menu = root_menu; - name = path_name = vim_strsave(path_name); - /* First, find the (sub)menu with the given name */ +/// Find menu matching required name and modes +/// +/// @param menu top menu to start looking from +/// @param name path towards the menu +/// @return menu if \p name is null, found menu or NULL +vimmenu_T * +find_menu(vimmenu_T *menu, char_u * name, int modes) +{ + char_u *p; + while (*name) { p = menu_name_skip(name); while (menu != NULL) { @@ -676,39 +765,46 @@ static int show_menus(char_u *path_name, int modes) /* Found menu */ if (*p != NUL && menu->children == NULL) { EMSG(_(e_notsubmenu)); - xfree(path_name); - return FAIL; + return NULL; } else if ((menu->modes & modes) == 0x0) { EMSG(_(e_othermode)); - xfree(path_name); - return FAIL; + return NULL; } break; } menu = menu->next; } + if (menu == NULL) { EMSG2(_(e_nomenu), name); - xfree(path_name); - return FAIL; + return NULL; } name = p; - parent = menu; menu = menu->children; } - xfree(path_name); + return menu; +} + +/// Show the mapping associated with a menu item or hierarchy in a sub-menu. +static int show_menus(char_u *const path_name, int modes) +{ + vimmenu_T *menu; + + // First, find the (sub)menu with the given name + menu = find_menu(root_menu, path_name, modes); + if (!menu) { + return FAIL; + } /* Now we have found the matching menu, and we list the mappings */ /* Highlight title */ MSG_PUTS_TITLE(_("\n--- Menus ---")); - show_menus_recursive(parent, modes, 0); + show_menus_recursive(menu->parent, modes, 0); return OK; } -/* - * Recursively show the mappings associated with the menus under the given one - */ +/// Recursively show the mappings associated with the menus under the given one static void show_menus_recursive(vimmenu_T *menu, int modes, int depth) { int i; @@ -755,10 +851,11 @@ static void show_menus_recursive(vimmenu_T *menu, int modes, int depth) else msg_putchar(' '); MSG_PUTS(" "); - if (*menu->strings[bit] == NUL) - msg_puts_attr((char_u *)"<Nop>", hl_attr(HLF_8)); - else - msg_outtrans_special(menu->strings[bit], FALSE); + if (*menu->strings[bit] == NUL) { + msg_puts_attr("<Nop>", hl_attr(HLF_8)); + } else { + msg_outtrans_special(menu->strings[bit], false); + } } } else { if (menu == NULL) { @@ -990,12 +1087,13 @@ char_u *get_menu_names(expand_T *xp, int idx) return str; } -/* - * Skip over this element of the menu path and return the start of the next - * element. Any \ and ^Vs are removed from the current element. - * "name" may be modified. - */ -char_u *menu_name_skip(char_u *name) + +/// Skip over this element of the menu path and return the start of the next +/// element. Any \ and ^Vs are removed from the current element. +/// +/// @param name may be modified. +/// @return start of the next element +char_u *menu_name_skip(char_u *const name) { char_u *p; @@ -1015,16 +1113,16 @@ char_u *menu_name_skip(char_u *name) * Return TRUE when "name" matches with menu "menu". The name is compared in * two ways: raw menu name and menu name without '&'. ignore part after a TAB. */ -static int menu_name_equal(char_u *name, vimmenu_T *menu) +static bool menu_name_equal(const char_u *const name, vimmenu_T *const menu) { if (menu->en_name != NULL && (menu_namecmp(name, menu->en_name) || menu_namecmp(name, menu->en_dname))) - return TRUE; + return true; return menu_namecmp(name, menu->name) || menu_namecmp(name, menu->dname); } -static int menu_namecmp(char_u *name, char_u *mname) +static bool menu_namecmp(const char_u *const name, const char_u *const mname) { int i; @@ -1035,18 +1133,20 @@ static int menu_namecmp(char_u *name, char_u *mname) && (mname[i] == NUL || mname[i] == TAB); } -/* - * Return the modes specified by the given menu command (eg :menu! returns - * MENU_CMDLINE_MODE | MENU_INSERT_MODE). - * If "noremap" is not NULL, then the flag it points to is set according to - * whether the command is a "nore" command. - * If "unmenu" is not NULL, then the flag it points to is set according to - * whether the command is an "unmenu" command. - */ -static int -get_menu_cmd_modes ( - char_u *cmd, - int forceit, /* Was there a "!" after the command? */ + +/// Returns the \ref MENU_MODES specified by menu command `cmd`. +/// (eg :menu! returns MENU_CMDLINE_MODE | MENU_INSERT_MODE) +/// +/// @param[in] cmd string like "nmenu", "vmenu", etc. +/// @param[in] forceit bang (!) was given after the command +/// @param[out] noremap If not NULL, the flag it points to is set according +/// to whether the command is a "nore" command. +/// @param[out] unmenu If not NULL, the flag it points to is set according +/// to whether the command is an "unmenu" command. +int +get_menu_cmd_modes( + const char_u * cmd, + bool forceit, int *noremap, int *unmenu ) @@ -1087,12 +1187,15 @@ get_menu_cmd_modes ( } /* FALLTHROUGH */ default: - --cmd; - if (forceit) /* menu!! */ + cmd--; + if (forceit) { + // menu!! modes = MENU_INSERT_MODE | MENU_CMDLINE_MODE; - else /* menu */ + } else { + // menu modes = MENU_NORMAL_MODE | MENU_VISUAL_MODE | MENU_SELECT_MODE | MENU_OP_PENDING_MODE; + } } if (noremap != NULL) @@ -1198,12 +1301,14 @@ int menu_is_separator(char_u *name) return name[0] == '-' && name[STRLEN(name) - 1] == '-'; } -/* - * Return TRUE if the menu is hidden: Starts with ']' - */ + +/// True if a popup menu or starts with \ref MNU_HIDDEN_CHAR +/// +/// @return true if the menu is hidden static int menu_is_hidden(char_u *name) { - return (name[0] == ']') || (menu_is_popup(name) && name[5] != NUL); + return (name[0] == MNU_HIDDEN_CHAR) + || (menu_is_popup(name) && name[5] != NUL); } /* diff --git a/src/nvim/menu.h b/src/nvim/menu.h index 3266c511b4..5ff979f2bf 100644 --- a/src/nvim/menu.h +++ b/src/nvim/menu.h @@ -1,7 +1,14 @@ #ifndef NVIM_MENU_H #define NVIM_MENU_H -/* Indices into vimmenu_T->strings[] and vimmenu_T->noremap[] for each mode */ +#include <stdbool.h> // for bool + +#include "nvim/types.h" // for char_u and expand_T +#include "nvim/ex_cmds_defs.h" // for exarg_T + +/// Indices into vimmenu_T->strings[] and vimmenu_T->noremap[] for each mode +/// \addtogroup MENU_INDEX +/// @{ #define MENU_INDEX_INVALID -1 #define MENU_INDEX_NORMAL 0 #define MENU_INDEX_VISUAL 1 @@ -11,8 +18,12 @@ #define MENU_INDEX_CMDLINE 5 #define MENU_INDEX_TIP 6 #define MENU_MODES 7 +/// @} +/// note MENU_INDEX_TIP is not a 'real' mode -/* Menu modes */ +/// Menu modes +/// \addtogroup MENU_MODES +/// @{ #define MENU_NORMAL_MODE (1 << MENU_INDEX_NORMAL) #define MENU_VISUAL_MODE (1 << MENU_INDEX_VISUAL) #define MENU_SELECT_MODE (1 << MENU_INDEX_SELECT) @@ -21,31 +32,30 @@ #define MENU_CMDLINE_MODE (1 << MENU_INDEX_CMDLINE) #define MENU_TIP_MODE (1 << MENU_INDEX_TIP) #define MENU_ALL_MODES ((1 << MENU_INDEX_TIP) - 1) -/*note MENU_INDEX_TIP is not a 'real' mode*/ +/// @} -/* Start a menu name with this to not include it on the main menu bar */ +/// Start a menu name with this to not include it on the main menu bar #define MNU_HIDDEN_CHAR ']' typedef struct VimMenu vimmenu_T; struct VimMenu { - int modes; /* Which modes is this menu visible for? */ - int enabled; /* for which modes the menu is enabled */ - char_u *name; /* Name of menu, possibly translated */ - char_u *dname; /* Displayed Name ("name" without '&') */ - char_u *en_name; /* "name" untranslated, NULL when "name" - * was not translated */ - char_u *en_dname; /* "dname" untranslated, NULL when "dname" - * was not translated */ - int mnemonic; /* mnemonic key (after '&') */ - char_u *actext; /* accelerator text (after TAB) */ - long priority; /* Menu order priority */ - char_u *strings[MENU_MODES]; /* Mapped string for each mode */ - int noremap[MENU_MODES]; /* A REMAP_ flag for each mode */ - bool silent[MENU_MODES]; /* A silent flag for each mode */ - vimmenu_T *children; /* Children of sub-menu */ - vimmenu_T *parent; /* Parent of menu */ - vimmenu_T *next; /* Next item in menu */ + int modes; ///< Which modes is this menu visible for + int enabled; ///< for which modes the menu is enabled + char_u *name; ///< Name of menu, possibly translated + char_u *dname; ///< Displayed Name ("name" without '&') + char_u *en_name; ///< "name" untranslated, NULL when + ///< was not translated + char_u *en_dname; ///< NULL when "dname" untranslated + int mnemonic; ///< mnemonic key (after '&') + char_u *actext; ///< accelerator text (after TAB) + long priority; ///< Menu order priority + char_u *strings[MENU_MODES]; ///< Mapped string for each mode + int noremap[MENU_MODES]; ///< A \ref REMAP_VALUES flag for each mode + bool silent[MENU_MODES]; ///< A silent flag for each mode + vimmenu_T *children; ///< Children of sub-menu + vimmenu_T *parent; ///< Parent of menu + vimmenu_T *next; ///< Next item in menu }; diff --git a/src/nvim/message.c b/src/nvim/message.c index 2f8feda6ec..b90c475ede 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + /* * message.c: functions for displaying messages on the command line */ @@ -7,10 +10,10 @@ #include <stdbool.h> #include <stdarg.h> #include <string.h> -#include <math.h> #include "nvim/vim.h" #include "nvim/ascii.h" +#include "nvim/assert.h" #include "nvim/message.h" #include "nvim/charset.h" #include "nvim/eval.h" @@ -28,6 +31,7 @@ #include "nvim/ops.h" #include "nvim/option.h" #include "nvim/normal.h" +#include "nvim/regexp.h" #include "nvim/screen.h" #include "nvim/strings.h" #include "nvim/ui.h" @@ -128,9 +132,9 @@ int verb_msg(char_u *s) return n; } -int msg_attr(char_u *s, int attr) FUNC_ATTR_NONNULL_ARG(1) +int msg_attr(const char *s, const int attr) FUNC_ATTR_NONNULL_ARG(1) { - return msg_attr_keep(s, attr, FALSE); + return msg_attr_keep((char_u *)s, attr, false); } int @@ -145,6 +149,12 @@ msg_attr_keep ( int retval; char_u *buf = NULL; + // Skip messages not match ":filter pattern". + // Don't filter when there is an error. + if (!emsg_on_display && message_filtered(s)) { + return true; + } + if (attr == 0) { set_vim_var_string(VV_STATUSMSG, (char *) s, -1); } @@ -164,8 +174,9 @@ msg_attr_keep ( || (*s != '<' && last_msg_hist != NULL && last_msg_hist->msg != NULL - && STRCMP(s, last_msg_hist->msg))) - add_msg_hist(s, -1, attr); + && STRCMP(s, last_msg_hist->msg))) { + add_msg_hist((const char *)s, -1, attr); + } /* When displaying keep_msg, don't let msg_start() free it, caller must do * that. */ @@ -236,17 +247,19 @@ msg_strtrunc ( * Truncate a string "s" to "buf" with cell width "room". * "s" and "buf" may be equal. */ -void trunc_string(char_u *s, char_u *buf, int room, int buflen) +void trunc_string(char_u *s, char_u *buf, int room_in, int buflen) { - int half; - int len; + size_t room = room_in - 3; // "..." takes 3 chars + size_t half; + size_t len = 0; int e; int i; int n; - room -= 3; + if (room_in < 3) { + room = 0; + } half = room / 2; - len = 0; /* First part: Start of the string. */ for (e = 0; len < half && e < buflen; ++e) { @@ -256,8 +269,9 @@ void trunc_string(char_u *s, char_u *buf, int room, int buflen) return; } n = ptr2cells(s + e); - if (len + n >= half) + if (len + n > half) { break; + } len += n; buf[e] = s[e]; if (has_mbyte) @@ -268,45 +282,46 @@ void trunc_string(char_u *s, char_u *buf, int room, int buflen) } } - /* Last part: End of the string. */ - i = e; - if (enc_dbcs != 0) { - /* For DBCS going backwards in a string is slow, but - * computing the cell width isn't too slow: go forward - * until the rest fits. */ - n = vim_strsize(s + i); - while (len + n > room) { - n -= ptr2cells(s + i); - i += (*mb_ptr2len)(s + i); - } - } else if (enc_utf8) { - /* For UTF-8 we can go backwards easily. */ - half = i = (int)STRLEN(s); - for (;; ) { - do - half = half - (*mb_head_off)(s, s + half - 1) - 1; - while (utf_iscomposing(utf_ptr2char(s + half)) && half > 0); - n = ptr2cells(s + half); - if (len + n > room) - break; - len += n; - i = half; + // Last part: End of the string. + half = i = (int)STRLEN(s); + for (;;) { + do { + half = half - (*mb_head_off)(s, s + half - 1) - 1; + } while (half > 0 && utf_iscomposing(utf_ptr2char(s + half))); + n = ptr2cells(s + half); + if (len + n > room || half == 0) { + break; } - } else { - for (i = (int)STRLEN(s); len + (n = ptr2cells(s + i - 1)) <= room; --i) - len += n; + len += n; + i = half; } - /* Set the middle and copy the last part. */ - if (e + 3 < buflen) { + if (i <= e + 3) { + // text fits without truncating + if (s != buf) { + len = STRLEN(s); + if (len >= (size_t)buflen) { + len = buflen - 1; + } + len = len - e + 1; + if (len < 1) { + buf[e - 1] = NUL; + } else { + memmove(buf + e, s + e, len); + } + } + } else if (e + 3 < buflen) { + // set the middle and copy the last part memmove(buf + e, "...", (size_t)3); - len = (int)STRLEN(s + i) + 1; - if (len >= buflen - e - 3) + len = STRLEN(s + i) + 1; + if (len >= (size_t)buflen - e - 3) { len = buflen - e - 3 - 1; + } memmove(buf + e + 3, s + i, len); buf[e + 3 + len - 1] = NUL; } else { - buf[e - 1] = NUL; /* make sure it is truncated */ + // can't fit in the "...", just truncate it + buf[e - 1] = NUL; } } @@ -332,7 +347,7 @@ int smsg_attr(int attr, char *s, ...) va_start(arglist, s); vim_vsnprintf((char *)IObuff, IOSIZE, s, arglist, NULL); va_end(arglist); - return msg_attr(IObuff, attr); + return msg_attr((const char *)IObuff, attr); } /* @@ -366,42 +381,40 @@ static int other_sourcing_name(void) return FALSE; } -/* - * Get the message about the source, as used for an error message. - * Returns an allocated string with room for one more character. - * Returns NULL when no message is to be given. - */ -static char_u *get_emsg_source(void) +/// Get the message about the source, as used for an error message +/// +/// @return [allocated] String with room for one more character. NULL when no +/// message is to be given. +static char *get_emsg_source(void) + FUNC_ATTR_MALLOC FUNC_ATTR_WARN_UNUSED_RESULT { - char_u *Buf, *p; - if (sourcing_name != NULL && other_sourcing_name()) { - p = (char_u *)_("Error detected while processing %s:"); - Buf = xmalloc(STRLEN(sourcing_name) + STRLEN(p)); - sprintf((char *)Buf, (char *)p, sourcing_name); - return Buf; + const char *const p = _("Error detected while processing %s:"); + const size_t buf_len = STRLEN(sourcing_name) + strlen(p) + 1; + char *const buf = xmalloc(buf_len); + snprintf(buf, buf_len, p, sourcing_name); + return buf; } return NULL; } -/* - * Get the message about the source lnum, as used for an error message. - * Returns an allocated string with room for one more character. - * Returns NULL when no message is to be given. - */ -static char_u *get_emsg_lnum(void) +/// Get the message about the source lnum, as used for an error message. +/// +/// @return [allocated] String with room for one more character. NULL when no +/// message is to be given. +static char *get_emsg_lnum(void) + FUNC_ATTR_MALLOC FUNC_ATTR_WARN_UNUSED_RESULT { - char_u *Buf, *p; - - /* lnum is 0 when executing a command from the command line - * argument, we don't want a line number then */ + // lnum is 0 when executing a command from the command line + // argument, we don't want a line number then if (sourcing_name != NULL && (other_sourcing_name() || sourcing_lnum != last_sourcing_lnum) && sourcing_lnum != 0) { - p = (char_u *)_("line %4ld:"); - Buf = xmalloc(STRLEN(p) + 20); - sprintf((char *)Buf, (char *)p, (long)sourcing_lnum); - return Buf; + const char *const p = _("line %4ld:"); + const size_t buf_len = 20 + strlen(p); + char *const buf = xmalloc(buf_len); + snprintf(buf, buf_len, p, (long)sourcing_lnum); + return buf; } return NULL; } @@ -413,10 +426,8 @@ static char_u *get_emsg_lnum(void) */ void msg_source(int attr) { - char_u *p; - - ++no_wait_return; - p = get_emsg_source(); + no_wait_return++; + char *p = get_emsg_source(); if (p != NULL) { msg_attr(p, attr); xfree(p); @@ -463,10 +474,10 @@ int emsg_not_now(void) * * return TRUE if wait_return not called */ -int emsg(char_u *s) +int emsg(const char_u *s_) { + const char *s = (const char *)s_; int attr; - char_u *p; int ignore = false; int severe; @@ -493,7 +504,7 @@ int emsg(char_u *s) * when the message should be ignored completely (used for the * interrupt message). */ - if (cause_errthrow(s, severe, &ignore) == true) { + if (cause_errthrow((char_u *)s, severe, &ignore) == true) { if (!ignore) { did_emsg = true; } @@ -501,7 +512,7 @@ int emsg(char_u *s) } // set "v:errmsg", also when using ":silent! cmd" - set_vim_var_string(VV_ERRMSG, (char *) s, -1); + set_vim_var_string(VV_ERRMSG, s, -1); /* * When using ":silent! cmd" ignore error messages. @@ -510,19 +521,21 @@ int emsg(char_u *s) if (emsg_silent != 0) { if (!emsg_noredir) { msg_start(); - p = get_emsg_source(); + char *p = get_emsg_source(); if (p != NULL) { - STRCAT(p, "\n"); - redir_write(p, STRLEN(p)); + const size_t p_len = strlen(p); + p[p_len] = '\n'; + redir_write(p, p_len + 1); xfree(p); } p = get_emsg_lnum(); if (p != NULL) { - STRCAT(p, "\n"); - redir_write(p, STRLEN(p)); + const size_t p_len = strlen(p); + p[p_len] = '\n'; + redir_write(p, p_len + 1); xfree(p); } - redir_write(s, STRLEN(s)); + redir_write(s, strlen(s)); } return true; } @@ -557,10 +570,8 @@ int emsg(char_u *s) */ msg_source(attr); - /* - * Display the error message itself. - */ - msg_nowait = FALSE; /* wait for this msg */ + // Display the error message itself. + msg_nowait = false; // Wait for this msg. return msg_attr(s, attr); } @@ -572,16 +583,17 @@ void emsg_invreg(int name) /// Print an error message with unknown number of arguments bool emsgf(const char *const fmt, ...) { + static char errbuf[IOSIZE]; if (emsg_not_now()) { return true; } va_list ap; va_start(ap, fmt); - vim_vsnprintf((char *) IObuff, IOSIZE, fmt, ap, NULL); + vim_vsnprintf(errbuf, sizeof(errbuf), fmt, ap, NULL); va_end(ap); - return emsg(IObuff); + return emsg((const char_u *)errbuf); } static void msg_emsgf_event(void **argv) @@ -599,7 +611,7 @@ void msg_schedule_emsgf(const char *const fmt, ...) va_end(ap); char *s = xstrdup((char *)IObuff); - loop_schedule(&main_loop, event_create(1, msg_emsgf_event, 1, s)); + loop_schedule(&main_loop, event_create(msg_emsgf_event, 1, s)); } /* @@ -612,14 +624,14 @@ char_u *msg_trunc_attr(char_u *s, int force, int attr) { int n; - /* Add message to history before truncating */ - add_msg_hist(s, -1, attr); + // Add message to history before truncating. + add_msg_hist((const char *)s, -1, attr); s = msg_may_trunc(force, s); - msg_hist_off = TRUE; - n = msg_attr(s, attr); - msg_hist_off = FALSE; + msg_hist_off = true; + n = msg_attr((const char *)s, attr); + msg_hist_off = false; if (n) return s; @@ -658,12 +670,8 @@ char_u *msg_may_trunc(int force, char_u *s) return s; } -static void -add_msg_hist ( - char_u *s, - int len, /* -1 for undetermined length */ - int attr -) +/// @param[in] len Length of s or -1. +static void add_msg_hist(const char *s, int len, int attr) { if (msg_hist_off || msg_silent != 0) return; @@ -681,9 +689,10 @@ add_msg_hist ( ++s; --len; } - while (len > 0 && s[len - 1] == '\n') - --len; - p->msg = vim_strnsave(s, len); + while (len > 0 && s[len - 1] == '\n') { + len--; + } + p->msg = (char_u *)xmemdupz(s, (size_t)len); p->next = NULL; p->attr = attr; if (last_msg_hist != NULL) @@ -716,11 +725,11 @@ int delete_first_msg(void) return OK; } -/* - * ":messages" command. - */ -void ex_messages(exarg_T *eap) +/// :messages command implementation +void ex_messages(void *const eap_p) + FUNC_ATTR_NONNULL_ALL { + const exarg_T *const eap = (const exarg_T *)eap_p; struct msg_hist *p; int c = 0; @@ -758,7 +767,7 @@ void ex_messages(exarg_T *eap) // Display what was not skipped. for (; p != NULL && !got_int; p = p->next) { if (p->msg != NULL) { - msg_attr(p->msg, p->attr); + msg_attr((const char *)p->msg, p->attr); } } @@ -849,23 +858,22 @@ void wait_return(int redraw) * CTRL-C, but we need to loop then. */ had_got_int = got_int; - /* Don't do mappings here, we put the character back in the - * typeahead buffer. */ - ++no_mapping; - ++allow_keys; + // Don't do mappings here, we put the character back in the + // typeahead buffer. + no_mapping++; - /* Temporarily disable Recording. If Recording is active, the - * character will be recorded later, since it will be added to the - * typebuf after the loop */ + // Temporarily disable Recording. If Recording is active, the + // character will be recorded later, since it will be added to the + // typebuf after the loop save_Recording = Recording; save_scriptout = scriptout; Recording = FALSE; scriptout = NULL; c = safe_vgetc(); - if (had_got_int && !global_busy) - got_int = FALSE; - --no_mapping; - --allow_keys; + if (had_got_int && !global_busy) { + got_int = false; + } + no_mapping--; Recording = save_Recording; scriptout = save_scriptout; @@ -1042,9 +1050,10 @@ void msg_start(void) msg_didout = FALSE; /* no output on current line yet */ } - /* when redirecting, may need to start a new line. */ - if (!did_return) - redir_write((char_u *)"\n", -1); + // When redirecting, may need to start a new line. + if (!did_return) { + redir_write("\n", 1); + } } /* @@ -1063,24 +1072,24 @@ void msg_putchar(int c) void msg_putchar_attr(int c, int attr) { - char_u buf[MB_MAXBYTES + 1]; + char buf[MB_MAXBYTES + 1]; if (IS_SPECIAL(c)) { - buf[0] = K_SPECIAL; - buf[1] = K_SECOND(c); - buf[2] = K_THIRD(c); + buf[0] = (char)K_SPECIAL; + buf[1] = (char)K_SECOND(c); + buf[2] = (char)K_THIRD(c); buf[3] = NUL; } else { - buf[(*mb_char2bytes)(c, buf)] = NUL; + buf[(*mb_char2bytes)(c, (char_u *)buf)] = NUL; } msg_puts_attr(buf, attr); } void msg_outnum(long n) { - char_u buf[20]; + char buf[20]; - sprintf((char *)buf, "%" PRId64, (int64_t)n); + snprintf(buf, sizeof(buf), "%ld", n); msg_puts(buf); } @@ -1136,16 +1145,16 @@ char_u *msg_outtrans_one(char_u *p, int attr) msg_outtrans_len_attr(p, l, attr); return p + l; } - msg_puts_attr(transchar_byte(*p), attr); + msg_puts_attr((const char *)transchar_byte(*p), attr); return p + 1; } int msg_outtrans_len_attr(char_u *msgstr, int len, int attr) { int retval = 0; - char_u *str = msgstr; - char_u *plain_start = msgstr; - char_u *s; + const char *str = (const char *)msgstr; + const char *plain_start = (const char *)msgstr; + char_u *s; int mb_l; int c; @@ -1155,60 +1164,59 @@ int msg_outtrans_len_attr(char_u *msgstr, int len, int attr) attr &= ~MSG_HIST; } - /* If the string starts with a composing character first draw a space on - * which the composing char can be drawn. */ - if (enc_utf8 && utf_iscomposing(utf_ptr2char(msgstr))) - msg_puts_attr((char_u *)" ", attr); + // If the string starts with a composing character first draw a space on + // which the composing char can be drawn. + if (enc_utf8 && utf_iscomposing(utf_ptr2char(msgstr))) { + msg_puts_attr(" ", attr); + } /* * Go over the string. Special characters are translated and printed. * Normal characters are printed several at a time. */ while (--len >= 0) { - if (enc_utf8) - /* Don't include composing chars after the end. */ - mb_l = utfc_ptr2len_len(str, len + 1); - else if (has_mbyte) - mb_l = (*mb_ptr2len)(str); - else - mb_l = 1; - if (has_mbyte && mb_l > 1) { - c = (*mb_ptr2char)(str); - if (vim_isprintc(c)) - /* printable multi-byte char: count the cells. */ - retval += (*mb_ptr2cells)(str); - else { - /* unprintable multi-byte char: print the printable chars so - * far and the translation of the unprintable char. */ - if (str > plain_start) - msg_puts_attr_len(plain_start, (int)(str - plain_start), - attr); + // Don't include composing chars after the end. + mb_l = utfc_ptr2len_len((char_u *)str, len + 1); + if (mb_l > 1) { + c = (*mb_ptr2char)((char_u *)str); + if (vim_isprintc(c)) { + // Printable multi-byte char: count the cells. + retval += (*mb_ptr2cells)((char_u *)str); + } else { + // Unprintable multi-byte char: print the printable chars so + // far and the translation of the unprintable char. + if (str > plain_start) { + msg_puts_attr_len(plain_start, str - plain_start, attr); + } plain_start = str + mb_l; - msg_puts_attr(transchar(c), attr == 0 ? hl_attr(HLF_8) : attr); + msg_puts_attr((const char *)transchar(c), + (attr == 0 ? hl_attr(HLF_8) : attr)); retval += char2cells(c); } len -= mb_l - 1; str += mb_l; } else { - s = transchar_byte(*str); + s = transchar_byte((uint8_t)(*str)); if (s[1] != NUL) { - /* unprintable char: print the printable chars so far and the - * translation of the unprintable char. */ - if (str > plain_start) - msg_puts_attr_len(plain_start, (int)(str - plain_start), - attr); + // Unprintable char: print the printable chars so far and the + // translation of the unprintable char. + if (str > plain_start) { + msg_puts_attr_len(plain_start, str - plain_start, attr); + } plain_start = str + 1; - msg_puts_attr(s, attr == 0 ? hl_attr(HLF_8) : attr); + msg_puts_attr((const char *)s, attr == 0 ? hl_attr(HLF_8) : attr); retval += (int)STRLEN(s); - } else - ++retval; - ++str; + } else { + retval++; + } + str++; } } - if (str > plain_start) - /* print the printable chars at the end */ - msg_puts_attr_len(plain_start, (int)(str - plain_start), attr); + if (str > plain_start) { + // Print the printable chars at the end. + msg_puts_attr_len(plain_start, str - plain_start, attr); + } return retval; } @@ -1251,130 +1259,147 @@ msg_outtrans_special ( { char_u *str = strstart; int retval = 0; - char_u *string; int attr; - int len; attr = hl_attr(HLF_8); while (*str != NUL) { - /* Leading and trailing spaces need to be displayed in <> form. */ + const char *string; + // Leading and trailing spaces need to be displayed in <> form. if ((str == strstart || str[1] == NUL) && *str == ' ') { - string = (char_u *)"<Space>"; - ++str; - } else - string = str2special(&str, from); - len = vim_strsize(string); - /* Highlight special keys */ - msg_puts_attr(string, len > 1 - && (*mb_ptr2len)(string) <= 1 - ? attr : 0); + string = "<Space>"; + str++; + } else { + string = str2special((const char **)&str, from, false); + } + const int len = vim_strsize((char_u *)string); + // Highlight special keys + msg_puts_attr(string, (len > 1 + && (*mb_ptr2len)((char_u *)string) <= 1 + ? attr : 0)); retval += len; } return retval; } -/* - * Return the lhs or rhs of a mapping, with the key codes turned into printable - * strings, in an allocated string. - */ -char_u * -str2special_save ( - char_u *str, - int is_lhs /* TRUE for lhs, FALSE for rhs */ -) +/// Convert string, replacing key codes with printables +/// +/// Used for lhs or rhs of mappings. +/// +/// @param[in] str String to convert. +/// @param[in] replace_spaces Convert spaces into `<Space>`, normally used fo +/// lhs, but not rhs. +/// @param[in] replace_lt Convert `<` into `<lt>`. +/// +/// @return [allocated] Converted string. +char *str2special_save(const char *const str, const bool replace_spaces, + const bool replace_lt) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_MALLOC + FUNC_ATTR_NONNULL_RET { garray_T ga; - char_u *p = str; - ga_init(&ga, 1, 40); - while (*p != NUL) - ga_concat(&ga, str2special(&p, is_lhs)); + + const char *p = str; + while (*p != NUL) { + ga_concat(&ga, (const char_u *)str2special(&p, replace_spaces, replace_lt)); + } ga_append(&ga, NUL); - return (char_u *)ga.ga_data; + return (char *)ga.ga_data; } -/* - * Return the printable string for the key codes at "*sp". - * Used for translating the lhs or rhs of a mapping to printable chars. - * Advances "sp" to the next code. - */ -char_u * -str2special ( - char_u **sp, - int from /* TRUE for lhs of mapping */ -) -{ - int c; - static char_u buf[7]; - char_u *str = *sp; - int modifiers = 0; - int special = FALSE; - - if (has_mbyte) { - char_u *p; - - /* Try to un-escape a multi-byte character. Return the un-escaped - * string if it is a multi-byte character. */ - p = mb_unescape(sp); - if (p != NULL) - return p; +/// Convert character, replacing key one key code with printable representation +/// +/// @param[in,out] sp String to convert. Is advanced to the next key code. +/// @param[in] replace_spaces Convert spaces into <Space>, normally used for +/// lhs, but not rhs. +/// @param[in] replace_lt Convert `<` into `<lt>`. +/// +/// @return Converted key code, in a static buffer. Buffer is always one and the +/// same, so save converted string somewhere before running str2special +/// for the second time. +const char *str2special(const char **const sp, const bool replace_spaces, + const bool replace_lt) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_RET +{ + static char buf[7]; + + // Try to un-escape a multi-byte character. Return the un-escaped + // string if it is a multi-byte character. + const char *const p = mb_unescape(sp); + if (p != NULL) { + return p; } - c = *str; + const char *str = *sp; + int c = (uint8_t)(*str); + int modifiers = 0; + bool special = false; if (c == K_SPECIAL && str[1] != NUL && str[2] != NUL) { - if (str[1] == KS_MODIFIER) { - modifiers = str[2]; + if ((uint8_t)str[1] == KS_MODIFIER) { + modifiers = (uint8_t)str[2]; str += 3; - c = *str; + c = (uint8_t)(*str); } if (c == K_SPECIAL && str[1] != NUL && str[2] != NUL) { - c = TO_SPECIAL(str[1], str[2]); + c = TO_SPECIAL((uint8_t)str[1], (uint8_t)str[2]); str += 2; - if (c == KS_ZERO) /* display <Nul> as ^@ or <Nul> */ + if (c == KS_ZERO) { // display <Nul> as ^@ or <Nul> c = NUL; + } + } + if (IS_SPECIAL(c) || modifiers) { // Special key. + special = true; } - if (IS_SPECIAL(c) || modifiers) /* special key */ - special = TRUE; } - if (has_mbyte && !IS_SPECIAL(c)) { - int len = (*mb_ptr2len)(str); + if (!IS_SPECIAL(c)) { + const int len = utf_ptr2len((const char_u *)str); - /* For multi-byte characters check for an illegal byte. */ - if (has_mbyte && MB_BYTE2LEN(*str) > len) { - transchar_nonprint(buf, c); + // Check for an illegal byte. + if (MB_BYTE2LEN((uint8_t)(*str)) > len) { + transchar_nonprint((char_u *)buf, c); *sp = str + 1; return buf; } - /* Since 'special' is TRUE the multi-byte character 'c' will be - * processed by get_special_key_name() */ - c = (*mb_ptr2char)(str); + // Since 'special' is TRUE the multi-byte character 'c' will be + // processed by get_special_key_name(). + c = utf_ptr2char((const char_u *)str); *sp = str + len; - } else + } else { *sp = str + 1; + } - /* Make unprintable characters in <> form, also <M-Space> and <Tab>. - * Use <Space> only for lhs of a mapping. */ - if (special || char2cells(c) > 1 || (from && c == ' ')) - return get_special_key_name(c, modifiers); + // Make unprintable characters in <> form, also <M-Space> and <Tab>. + if (special + || char2cells(c) > 1 + || (replace_spaces && c == ' ') + || (replace_lt && c == '<')) { + return (const char *)get_special_key_name(c, modifiers); + } buf[0] = c; buf[1] = NUL; return buf; } -/* - * Translate a key sequence into special key names. - */ -void str2specialbuf(char_u *sp, char_u *buf, int len) +/// Convert string, replacing key codes with printables +/// +/// @param[in] str String to convert. +/// @param[out] buf Buffer to save results to. +/// @param[in] len Buffer length. +void str2specialbuf(const char *sp, char *buf, size_t len) + FUNC_ATTR_NONNULL_ALL { - char_u *s; - - *buf = NUL; while (*sp) { - s = str2special(&sp, FALSE); - if ((int)(STRLEN(s) + STRLEN(buf)) < len) - STRCAT(buf, s); + const char *s = str2special(&sp, false, false); + const size_t s_len = strlen(s); + if (s_len <= len) { + break; + } + memcpy(buf, s, s_len); + buf += s_len; + len -= s_len; } + *buf = NUL; } /* @@ -1391,7 +1416,6 @@ void msg_prt_line(char_u *s, int list) int attr = 0; char_u *trail = NULL; int l; - char_u buf[MB_MAXBYTES + 1]; if (curwin->w_p_list) list = TRUE; @@ -1417,10 +1441,11 @@ void msg_prt_line(char_u *s, int list) c = *p_extra++; } else if (has_mbyte && (l = (*mb_ptr2len)(s)) > 1) { col += (*mb_ptr2cells)(s); + char buf[MB_MAXBYTES + 1]; if (lcs_nbsp != NUL && list && (mb_ptr2char(s) == 160 || mb_ptr2char(s) == 0x202f)) { - mb_char2bytes(lcs_nbsp, buf); - buf[(*mb_ptr2len)(buf)] = NUL; + mb_char2bytes(lcs_nbsp, (char_u *)buf); + buf[(*mb_ptr2len)((char_u *)buf)] = NUL; } else { memmove(buf, s, (size_t)l); buf[l] = NUL; @@ -1517,12 +1542,12 @@ static char_u *screen_puts_mbyte(char_u *s, int l, int attr) * Output a string to the screen at position msg_row, msg_col. * Update msg_row and msg_col for the next message. */ -void msg_puts(char_u *s) +void msg_puts(const char *s) { msg_puts_attr(s, 0); } -void msg_puts_title(char_u *s) +void msg_puts_title(const char *s) { msg_puts_attr(s, hl_attr(HLF_T)); } @@ -1546,7 +1571,7 @@ void msg_puts_long_len_attr(char_u *longstr, int len, int attr) if (len > room && room >= 20) { slen = (room - 3) / 2; msg_outtrans_len_attr(longstr, slen, attr); - msg_puts_attr((char_u *)"...", hl_attr(HLF_8)); + msg_puts_attr("...", hl_attr(HLF_8)); } msg_outtrans_len_attr(longstr + len - slen, slen, attr); } @@ -1554,18 +1579,22 @@ void msg_puts_long_len_attr(char_u *longstr, int len, int attr) /* * Basic function for writing a message with highlight attributes. */ -void msg_puts_attr(char_u *s, int attr) +void msg_puts_attr(const char *const s, const int attr) { msg_puts_attr_len(s, -1, attr); } -/// Like msg_puts_attr(), but with a maximum length "maxlen" (in bytes). -/// When "maxlen" is -1 there is no maximum length. -/// When "maxlen" is >= 0 the message is not put in the history. -static void msg_puts_attr_len(char_u *str, int maxlen, int attr) +/// Write a message with highlight attributes +/// +/// @param[in] str NUL-terminated message string. +/// @param[in] len Length of the string or -1. +/// @param[in] attr Highlight attribute. +void msg_puts_attr_len(const char *const str, const ptrdiff_t len, int attr) + FUNC_ATTR_NONNULL_ALL { + assert(len < 0 || memchr(str, 0, len) == NULL); // If redirection is on, also write to the redirection file. - redir_write(str, maxlen); + redir_write(str, len); // Don't print anything when using ":silent cmd". if (msg_silent != 0) { @@ -1573,8 +1602,8 @@ static void msg_puts_attr_len(char_u *str, int maxlen, int attr) } // if MSG_HIST flag set, add message to history - if ((attr & MSG_HIST) && maxlen < 0) { - add_msg_hist(str, -1, attr); + if (attr & MSG_HIST) { + add_msg_hist(str, (int)len, attr); attr &= ~MSG_HIST; } @@ -1593,24 +1622,46 @@ static void msg_puts_attr_len(char_u *str, int maxlen, int attr) // different, e.g. for Win32 console) or we just don't know where the // cursor is. if (msg_use_printf()) { - msg_puts_printf((char *)str, maxlen); + msg_puts_printf(str, len); } else { - msg_puts_display(str, maxlen, attr, false); + msg_puts_display((const char_u *)str, len, attr, false); } } +/// Print a formatted message +/// +/// Message printed is limited by #IOSIZE. Must not be used from inside +/// msg_puts_attr(). +/// +/// @param[in] attr Highlight attributes. +/// @param[in] fmt Format string. +void msg_printf_attr(const int attr, const char *const fmt, ...) + FUNC_ATTR_NONNULL_ARG(2) +{ + static char msgbuf[IOSIZE]; + + va_list ap; + va_start(ap, fmt); + const size_t len = vim_vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap, NULL); + va_end(ap); + + msg_scroll = true; + msg_puts_attr_len(msgbuf, (ptrdiff_t)len, attr); +} + /* * The display part of msg_puts_attr_len(). * May be called recursively to display scroll-back text. */ -static void msg_puts_display(char_u *str, int maxlen, int attr, int recurse) +static void msg_puts_display(const char_u *str, int maxlen, int attr, + int recurse) { - char_u *s = str; - char_u *t_s = str; /* string from "t_s" to "s" is still todo */ - int t_col = 0; /* screen cells todo, 0 when "t_s" not used */ + const char_u *s = str; + const char_u *t_s = str; // String from "t_s" to "s" is still todo. + int t_col = 0; // Screen cells todo, 0 when "t_s" not used. int l; int cw; - char_u *sb_str = str; + const char_u *sb_str = str; int sb_col = msg_col; int wrap; int did_last_char; @@ -1652,26 +1703,24 @@ static void msg_puts_display(char_u *str, int maxlen, int attr, int recurse) if (msg_col >= Columns) /* can happen after screen resize */ msg_col = Columns - 1; - /* Display char in last column before showing more-prompt. */ - if (*s >= ' ' - && !cmdmsg_rl - ) { - if (has_mbyte) { - if (enc_utf8 && maxlen >= 0) - /* avoid including composing chars after the end */ - l = utfc_ptr2len_len(s, (int)((str + maxlen) - s)); - else - l = (*mb_ptr2len)(s); - s = screen_puts_mbyte(s, l, attr); - } else - msg_screen_putchar(*s++, attr); - did_last_char = TRUE; - } else - did_last_char = FALSE; - - if (p_more) - /* store text for scrolling back */ - store_sb_text(&sb_str, s, attr, &sb_col, TRUE); + // Display char in last column before showing more-prompt. + if (*s >= ' ' && !cmdmsg_rl) { + if (maxlen >= 0) { + // Avoid including composing chars after the end. + l = utfc_ptr2len_len(s, (int)((str + maxlen) - s)); + } else { + l = utfc_ptr2len(s); + } + s = screen_puts_mbyte((char_u *)s, l, attr); + did_last_char = true; + } else { + did_last_char = false; + } + + if (p_more) { + // Store text for scrolling back. + store_sb_text((char_u **)&sb_str, (char_u *)s, attr, &sb_col, true); + } inc_msg_scrolled(); need_wait_return = TRUE; /* may need wait_return in main() */ @@ -1707,13 +1756,15 @@ static void msg_puts_display(char_u *str, int maxlen, int attr, int recurse) && msg_col + t_col >= Columns - 1) ; if (t_col > 0 && (wrap || *s == '\r' || *s == '\b' - || *s == '\t' || *s == BELL)) - /* output any postponed text */ + || *s == '\t' || *s == BELL)) { + // Output any postponed text. t_puts(&t_col, t_s, s, attr); + } - if (wrap && p_more && !recurse) - /* store text for scrolling back */ - store_sb_text(&sb_str, s, attr, &sb_col, TRUE); + if (wrap && p_more && !recurse) { + // Store text for scrolling back. + store_sb_text((char_u **)&sb_str, (char_u *)s, attr, &sb_col, true); + } if (*s == '\n') { /* go to next line */ msg_didout = FALSE; /* remember that line is empty */ @@ -1751,7 +1802,7 @@ static void msg_puts_display(char_u *str, int maxlen, int attr, int recurse) // characters and draw them all at once later. if (cmdmsg_rl || (cw > 1 && msg_col + t_col >= Columns - 1)) { if (l > 1) { - s = screen_puts_mbyte(s, l, attr) - 1; + s = screen_puts_mbyte((char_u *)s, l, attr) - 1; } else { msg_screen_putchar(*s, attr); } @@ -1766,15 +1817,29 @@ static void msg_puts_display(char_u *str, int maxlen, int attr, int recurse) ++s; } - /* output any postponed text */ - if (t_col > 0) + // Output any postponed text. + if (t_col > 0) { t_puts(&t_col, t_s, s, attr); - if (p_more && !recurse) - store_sb_text(&sb_str, s, attr, &sb_col, FALSE); + } + if (p_more && !recurse) { + store_sb_text((char_u **)&sb_str, (char_u *)s, attr, &sb_col, false); + } msg_check(); } +/// Return true when ":filter pattern" was used and "msg" does not match +/// "pattern". +bool message_filtered(char_u *msg) +{ + if (cmdmod.filter_regmatch.regprog == NULL) { + return false; + } + + bool match = vim_regexec(&cmdmod.filter_regmatch, msg, (colnr_T)0); + return cmdmod.filter_force ? match : !match; +} + /* * Scroll the screen up one line for displaying the next message line. */ @@ -1946,11 +2011,11 @@ static msgchunk_T *disp_sb_line(int row, msgchunk_T *smp) /* * Output any postponed text for msg_puts_attr_len(). */ -static void t_puts(int *t_col, char_u *t_s, char_u *s, int attr) +static void t_puts(int *t_col, const char_u *t_s, const char_u *s, int attr) { - /* output postponed text */ - msg_didout = TRUE; /* remember that line is not empty */ - screen_puts_len(t_s, (int)(s - t_s), msg_row, msg_col, attr); + // Output postponed text. + msg_didout = true; // Remember that line is not empty. + screen_puts_len((char_u *)t_s, (int)(s - t_s), msg_row, msg_col, attr); msg_col += *t_col; *t_col = 0; /* If the string starts with a composing character don't increment the @@ -1971,13 +2036,13 @@ int msg_use_printf(void) } /// Print a message when there is no valid screen. -static void msg_puts_printf(char *str, int maxlen) +static void msg_puts_printf(const char *str, const ptrdiff_t maxlen) { - char *s = str; + const char *s = str; char buf[4]; char *p; - while (*s != NUL && (maxlen < 0 || (int)(s - str) < maxlen)) { + while ((maxlen < 0 || s - str < maxlen) && *s != NUL) { if (!(silent_mode && p_verbose == 0)) { // NL --> CR NL translation (for Unix, not for "--version") p = &buf[0]; @@ -2434,24 +2499,15 @@ void msg_check(void) * May write a string to the redirection file. * When "maxlen" is -1 write the whole string, otherwise up to "maxlen" bytes. */ -static void redir_write(char_u *str, int maxlen) +static void redir_write(const char *const str, const ptrdiff_t maxlen) { - char_u *s = str; + const char_u *s = (char_u *)str; static int cur_col = 0; if (maxlen == 0) { return; } - // Append output for execute(). - if (capture_ga) { - size_t len = 0; - while (str[len] && (maxlen < 0 ? 1 : (len < (size_t)maxlen))) { - len++; - } - ga_concat_len(capture_ga, (const char *)str, len); - } - /* Don't do anything for displaying prompts and the like. */ if (redir_off) return; @@ -2464,6 +2520,9 @@ static void redir_write(char_u *str, int maxlen) /* If the string doesn't start with CR or NL, go to msg_col */ if (*s != '\n' && *s != '\r') { while (cur_col < msg_col) { + if (capture_ga) { + ga_concat_len(capture_ga, " ", 1); + } if (redir_reg) { write_reg_contents(redir_reg, (char_u *)" ", 1, true); } else if (redir_vname) { @@ -2478,28 +2537,36 @@ static void redir_write(char_u *str, int maxlen) } } + size_t len = maxlen == -1 ? STRLEN(s) : (size_t)maxlen; + if (capture_ga) { + ga_concat_len(capture_ga, (const char *)str, len); + } if (redir_reg) { - size_t len = maxlen == -1 ? STRLEN(s) : (size_t)maxlen; write_reg_contents(redir_reg, s, len, true); } if (redir_vname) { - var_redir_str(s, maxlen); + var_redir_str((char_u *)s, maxlen); } - /* Write and adjust the current column. */ - while (*s != NUL && (maxlen < 0 || (int)(s - str) < maxlen)) { - if (!redir_reg && !redir_vname) - if (redir_fd != NULL) + // Write and adjust the current column. + while (*s != NUL + && (maxlen < 0 || (int)(s - (const char_u *)str) < maxlen)) { + if (!redir_reg && !redir_vname && !capture_ga) { + if (redir_fd != NULL) { putc(*s, redir_fd); - if (verbose_fd != NULL) + } + } + if (verbose_fd != NULL) { putc(*s, verbose_fd); - if (*s == '\r' || *s == '\n') + } + if (*s == '\r' || *s == '\n') { cur_col = 0; - else if (*s == '\t') + } else if (*s == '\t') { cur_col += (8 - cur_col % 8); - else - ++cur_col; - ++s; + } else { + cur_col++; + } + s++; } if (msg_silent != 0) /* should update msg_col */ @@ -2605,14 +2672,16 @@ void give_warning(char_u *message, bool hl) FUNC_ATTR_NONNULL_ARG(1) set_vim_var_string(VV_WARNINGMSG, (char *) message, -1); xfree(keep_msg); keep_msg = NULL; - if (hl) + if (hl) { keep_msg_attr = hl_attr(HLF_W); - else + } else { keep_msg_attr = 0; - if (msg_attr(message, keep_msg_attr) && msg_scrolled == 0) + } + if (msg_attr((const char *)message, keep_msg_attr) && msg_scrolled == 0) { set_keep_msg(message, keep_msg_attr); - msg_didout = FALSE; /* overwrite this message */ - msg_nowait = TRUE; /* don't wait for this message */ + } + msg_didout = false; // Overwrite this message. + msg_nowait = true; // Don't wait for this message. msg_col = 0; --no_wait_return; @@ -2674,9 +2743,11 @@ do_dialog ( int c; int i; - /* Don't output anything in silent mode ("ex -s") */ - if (silent_mode) - return dfltbutton; /* return default option */ + if (silent_mode // No dialogs in silent mode ("ex -s") + || !ui_active() // Without a UI Nvim waits for input forever. + ) { + return dfltbutton; // return default option + } oldState = State; @@ -2712,8 +2783,8 @@ do_dialog ( break; } - /* Make the character lowercase, as chars in "hotkeys" are. */ - c = vim_tolower(c); + // Make the character lowercase, as chars in "hotkeys" are. + c = mb_tolower(c); retval = 1; for (i = 0; hotkeys[i]; ++i) { if (has_mbyte) { @@ -2759,7 +2830,7 @@ copy_char ( if (has_mbyte) { if (lowercase) { - c = vim_tolower((*mb_ptr2char)(from)); + c = mb_tolower((*mb_ptr2char)(from)); return (*mb_char2bytes)(c, to); } else { len = (*mb_ptr2len)(from); @@ -2948,11 +3019,12 @@ static void copy_hotkeys_and_msg(const char_u *message, char_u *buttons, */ void display_confirm_msg(void) { - /* avoid that 'q' at the more prompt truncates the message here */ - ++confirm_msg_used; - if (confirm_msg != NULL) - msg_puts_attr(confirm_msg, hl_attr(HLF_M)); - --confirm_msg_used; + // Avoid that 'q' at the more prompt truncates the message here. + confirm_msg_used++; + if (confirm_msg != NULL) { + msg_puts_attr((const char *)confirm_msg, hl_attr(HLF_M)); + } + confirm_msg_used--; } int vim_dialog_yesno(int type, char_u *title, char_u *message, int dflt) @@ -2991,802 +3063,3 @@ int vim_dialog_yesnoallcancel(int type, char_u *title, char_u *message, int dflt } return VIM_CANCEL; } - - - -static char *e_printf = N_("E766: Insufficient arguments for printf()"); - -/* - * Get number argument from "idxp" entry in "tvs". First entry is 1. - */ -static long tv_nr(typval_T *tvs, int *idxp) -{ - int idx = *idxp - 1; - long n = 0; - int err = FALSE; - - if (tvs[idx].v_type == VAR_UNKNOWN) - EMSG(_(e_printf)); - else { - ++*idxp; - n = get_tv_number_chk(&tvs[idx], &err); - if (err) - n = 0; - } - return n; -} - -/* - * Get string argument from "idxp" entry in "tvs". First entry is 1. - * Returns NULL for an error. - */ -static char *tv_str(typval_T *tvs, int *idxp) -{ - int idx = *idxp - 1; - char *s = NULL; - - if (tvs[idx].v_type == VAR_UNKNOWN) - EMSG(_(e_printf)); - else { - ++*idxp; - s = (char *)get_tv_string_chk(&tvs[idx]); - } - return s; -} - -/* - * Get float argument from "idxp" entry in "tvs". First entry is 1. - */ -static double tv_float(typval_T *tvs, int *idxp) -{ - int idx = *idxp - 1; - double f = 0; - - if (tvs[idx].v_type == VAR_UNKNOWN) - EMSG(_(e_printf)); - else { - ++*idxp; - if (tvs[idx].v_type == VAR_FLOAT) - f = tvs[idx].vval.v_float; - else if (tvs[idx].v_type == VAR_NUMBER) - f = tvs[idx].vval.v_number; - else - EMSG(_("E807: Expected Float argument for printf()")); - } - return f; -} - -/* - * This code was included to provide a portable vsnprintf() and snprintf(). - * Some systems may provide their own, but we always use this one for - * consistency. - * - * This code is based on snprintf.c - a portable implementation of snprintf - * by Mark Martinec <mark.martinec@ijs.si>, Version 2.2, 2000-10-06. - * Included with permission. It was heavily modified to fit in Vim. - * The original code, including useful comments, can be found here: - * http://www.ijs.si/software/snprintf/ - * - * This snprintf() only supports the following conversion specifiers: - * s, c, b, B, d, u, o, x, X, p (and synonyms: i, D, U, O - see below) - * with flags: '-', '+', ' ', '0' and '#'. - * An asterisk is supported for field width as well as precision. - * - * Limited support for floating point was added: 'f', 'e', 'E', 'g', 'G'. - * - * Length modifiers 'h' (short int) and 'l' (long int) are supported. - * 'll' (long long int) is not supported. - * - * The locale is not used, the string is used as a byte string. This is only - * relevant for double-byte encodings where the second byte may be '%'. - * - * It is permitted for "str_m" to be zero, and it is permitted to specify NULL - * pointer for resulting string argument if "str_m" is zero (as per ISO C99). - * - * The return value is the number of characters which would be generated - * for the given input, excluding the trailing NUL. If this value - * is greater or equal to "str_m", not all characters from the result - * have been stored in str, output bytes beyond the ("str_m"-1) -th character - * are discarded. If "str_m" is greater than zero it is guaranteed - * the resulting string will be NUL-terminated. - */ - -/* - * When va_list is not supported we only define vim_snprintf(). - * - * vim_vsnprintf() can be invoked with either "va_list" or a list of - * "typval_T". When the latter is not used it must be NULL. - */ - -/* Like vim_vsnprintf() but append to the string. */ -int vim_snprintf_add(char *str, size_t str_m, char *fmt, ...) -{ - va_list ap; - int str_l; - size_t len = STRLEN(str); - size_t space; - - if (str_m <= len) - space = 0; - else - space = str_m - len; - va_start(ap, fmt); - str_l = vim_vsnprintf(str + len, space, fmt, ap, NULL); - va_end(ap); - return str_l; -} - -int vim_snprintf(char *str, size_t str_m, const char *fmt, ...) -{ - va_list ap; - int str_l; - - va_start(ap, fmt); - str_l = vim_vsnprintf(str, str_m, fmt, ap, NULL); - va_end(ap); - return str_l; -} - -int vim_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap, - typval_T *tvs) -{ - size_t str_l = 0; - bool str_avail = str_l < str_m; - const char *p = fmt; - int arg_idx = 1; - - if (!p) { - p = ""; - } - while (*p) { - if (*p != '%') { - // copy up to the next '%' or NUL without any changes - size_t n = (size_t)(xstrchrnul(p + 1, '%') - p); - if (str_avail) { - size_t avail = str_m - str_l; - memmove(str + str_l, p, MIN(n, avail)); - str_avail = n < avail; - } - p += n; - assert(n <= SIZE_MAX - str_l); - str_l += n; - } else { - size_t min_field_width = 0, precision = 0; - int zero_padding = 0, precision_specified = 0, justify_left = 0; - int alternate_form = 0, force_sign = 0; - - // if both ' ' and '+' flags appear, ' ' flag should be ignored - int space_for_positive = 1; - - // allowed values: \0, h, l, 2 (for ll), z, L - char length_modifier = '\0'; - - // temporary buffer for simple numeric->string conversion -# define TMP_LEN 350 // 1e308 seems reasonable as the maximum printable - char tmp[TMP_LEN]; - - // string address in case of string argument - const char *str_arg; - - // natural field width of arg without padding and sign - size_t str_arg_l; - - // unsigned char argument value (only defined for c conversion); - // standard explicitly states the char argument for the c - // conversion is unsigned - unsigned char uchar_arg; - - // number of zeros to be inserted for numeric conversions as - // required by the precision or minimal field width - size_t number_of_zeros_to_pad = 0; - - // index into tmp where zero padding is to be inserted - size_t zero_padding_insertion_ind = 0; - - // current conversion specifier character - char fmt_spec = '\0'; - - str_arg = NULL; - p++; // skip '%' - - // parse flags - while (*p == '0' || *p == '-' || *p == '+' || *p == ' ' - || *p == '#' || *p == '\'') { - switch (*p) { - case '0': zero_padding = 1; break; - case '-': justify_left = 1; break; - // if both '0' and '-' flags appear, '0' should be ignored - case '+': force_sign = 1; space_for_positive = 0; break; - case ' ': force_sign = 1; break; - // if both ' ' and '+' flags appear, ' ' should be ignored - case '#': alternate_form = 1; break; - case '\'': break; - } - p++; - } - - // parse field width - if (*p == '*') { - p++; - int j = tvs ? tv_nr(tvs, &arg_idx) : va_arg(ap, int); - if (j >= 0) { - min_field_width = j; - } else { - min_field_width = -j; - justify_left = 1; - } - } else if (ascii_isdigit((int)(*p))) { - // size_t could be wider than unsigned int; make sure we treat - // argument like common implementations do - unsigned int uj = *p++ - '0'; - - while (ascii_isdigit((int)(*p))) { - uj = 10 * uj + (unsigned int)(*p++ - '0'); - } - min_field_width = uj; - } - - // parse precision - if (*p == '.') { - p++; - precision_specified = 1; - if (*p == '*') { - int j = tvs ? tv_nr(tvs, &arg_idx) : va_arg(ap, int); - p++; - if (j >= 0) { - precision = j; - } else { - precision_specified = 0; - precision = 0; - } - } else if (ascii_isdigit((int)(*p))) { - // size_t could be wider than unsigned int; make sure we - // treat argument like common implementations do - unsigned int uj = *p++ - '0'; - - while (ascii_isdigit((int)(*p))) { - uj = 10 * uj + (unsigned int)(*p++ - '0'); - } - precision = uj; - } - } - - // parse 'h', 'l', 'll' and 'z' length modifiers - if (*p == 'h' || *p == 'l' || *p == 'z') { - length_modifier = *p; - p++; - if (length_modifier == 'l' && *p == 'l') { // ll, encoded as 2 - length_modifier = '2'; - p++; - } - } - - fmt_spec = *p; - - // common synonyms - switch (fmt_spec) { - case 'i': fmt_spec = 'd'; break; - case 'D': fmt_spec = 'd'; length_modifier = 'l'; break; - case 'U': fmt_spec = 'u'; length_modifier = 'l'; break; - case 'O': fmt_spec = 'o'; length_modifier = 'l'; break; - case 'F': fmt_spec = 'f'; break; - default: break; - } - - // get parameter value, do initial processing - switch (fmt_spec) { - // '%' and 'c' behave similar to 's' regarding flags and field widths - case '%': case 'c': case 's': case 'S': - str_arg_l = 1; - switch (fmt_spec) { - case '%': - str_arg = p; - break; - - case 'c': { - int j = tvs ? tv_nr(tvs, &arg_idx) : va_arg(ap, int); - // standard demands unsigned char - uchar_arg = (unsigned char)j; - str_arg = (char *)&uchar_arg; - break; - } - - case 's': - case 'S': - str_arg = tvs ? tv_str(tvs, &arg_idx) : va_arg(ap, char *); - if (!str_arg) { - str_arg = "[NULL]"; - str_arg_l = 6; - } else if (!precision_specified) { - // make sure not to address string beyond the specified precision - str_arg_l = strlen(str_arg); - } else if (precision == 0) { - // truncate string if necessary as requested by precision - str_arg_l = 0; - } else { - // memchr on HP does not like n > 2^31 - // TODO(elmart): check if this still holds / is relevant - str_arg_l = (size_t)((char *)xmemscan(str_arg, - NUL, - MIN(precision, 0x7fffffff)) - - str_arg); - } - if (fmt_spec == 'S') { - if (min_field_width != 0) - min_field_width += strlen(str_arg) - - mb_string2cells((char_u *) str_arg); - if (precision) { - char_u *p1 = (char_u *)str_arg; - for (size_t i = 0; i < precision && *p1; i++) { - p1 += mb_ptr2len(p1); - } - str_arg_l = precision = p1 - (char_u *)str_arg; - } - } - break; - - default: - break; - } - break; - - case 'd': - case 'u': - case 'b': case 'B': - case 'o': - case 'x': case 'X': - case 'p': { - // u, b, B, o, x, X and p conversion specifiers imply - // the value is unsigned; d implies a signed value - - // 0 if numeric argument is zero (or if pointer is NULL for 'p'), - // +1 if greater than zero (or non NULL for 'p'), - // -1 if negative (unsigned argument is never negative) - int arg_sign = 0; - - // only defined for length modifier h, or for no length modifiers - int int_arg = 0; - unsigned int uint_arg = 0; - - // only defined for length modifier l - long int long_arg = 0; - unsigned long int ulong_arg = 0; - - // only defined for length modifier ll - long long int long_long_arg = 0; - unsigned long long int ulong_long_arg = 0; - - // only defined for length modifier z - size_t size_t_arg = 0; - - // only defined for p conversion - void *ptr_arg = NULL; - - if (fmt_spec == 'p') { - length_modifier = '\0'; - ptr_arg = tvs ? (void *)tv_str(tvs, &arg_idx) : va_arg(ap, void *); - if (ptr_arg) { - arg_sign = 1; - } - } else if (fmt_spec == 'd') { - // signed - switch (length_modifier) { - case '\0': - case 'h': - // char and short arguments are passed as int - int_arg = tvs ? tv_nr(tvs, &arg_idx) : va_arg(ap, int); - if (int_arg > 0) { - arg_sign = 1; - } else if (int_arg < 0) { - arg_sign = -1; - } - break; - case 'l': - long_arg = tvs ? tv_nr(tvs, &arg_idx) : va_arg(ap, long int); - if (long_arg > 0) { - arg_sign = 1; - } else if (long_arg < 0) { - arg_sign = -1; - } - break; - case '2': - long_long_arg = tvs ? tv_nr(tvs, &arg_idx) - : va_arg(ap, long long int); // NOLINT (runtime/int) - if (long_long_arg > 0) { - arg_sign = 1; - } else if (long_long_arg < 0) { - arg_sign = -1; - } - break; - } - } else { - // unsigned - switch (length_modifier) { - case '\0': - case 'h': - uint_arg = tvs ? (unsigned)tv_nr(tvs, &arg_idx) - : va_arg(ap, unsigned int); - if (uint_arg != 0) { arg_sign = 1; } - break; - case 'l': - ulong_arg = tvs ? (unsigned long)tv_nr(tvs, &arg_idx) - : va_arg(ap, unsigned long int); - if (ulong_arg != 0) { arg_sign = 1; } - break; - case '2': - ulong_long_arg = tvs - ? (unsigned long long)tv_nr(tvs, &arg_idx) // NOLINT (runtime/int) - : va_arg(ap, unsigned long long int); // NOLINT (runtime/int) - if (ulong_long_arg) { arg_sign = 1; } - break; - case 'z': - size_t_arg = tvs ? (size_t)tv_nr(tvs, &arg_idx) - : va_arg(ap, size_t); - if (size_t_arg) { arg_sign = 1; } - break; - } - } - - str_arg = tmp; - str_arg_l = 0; - - // For d, i, u, o, x, and X conversions, if precision is specified, - // '0' flag should be ignored. This is so with Solaris 2.6, Digital UNIX - // 4.0, HPUX 10, Linux, FreeBSD, NetBSD; but not with Perl. - if (precision_specified) { - zero_padding = 0; - } - - if (fmt_spec == 'd') { - if (force_sign && arg_sign >= 0) { - tmp[str_arg_l++] = space_for_positive ? ' ' : '+'; - } - // leave negative numbers for sprintf to handle, to - // avoid handling tricky cases like (short int)-32768 - } else if (alternate_form) { - if (arg_sign != 0 && (fmt_spec == 'x' || fmt_spec == 'X' - || fmt_spec == 'b' || fmt_spec == 'B')) { - tmp[str_arg_l++] = '0'; - tmp[str_arg_l++] = fmt_spec; - } - // alternate form should have no effect for p * conversion, but ... - } - - zero_padding_insertion_ind = str_arg_l; - if (!precision_specified) { - precision = 1; // default precision is 1 - } - if (precision == 0 && arg_sign == 0) { - // when zero value is formatted with an explicit precision 0, - // resulting formatted string is empty (d, i, u, b, B, o, x, X, p) - } else { - char f[5]; - int f_l = 0; - - // construct a simple format string for sprintf - f[f_l++] = '%'; - if (!length_modifier) { - } else if (length_modifier == '2') { - f[f_l++] = 'l'; - f[f_l++] = 'l'; - } else - f[f_l++] = length_modifier; - f[f_l++] = fmt_spec; - f[f_l++] = '\0'; - - if (fmt_spec == 'p') - str_arg_l += sprintf(tmp + str_arg_l, f, ptr_arg); - else if (fmt_spec == 'd') { - // signed - switch (length_modifier) { - case '\0': - case 'h': str_arg_l += sprintf(tmp + str_arg_l, f, int_arg); - break; - case 'l': str_arg_l += sprintf(tmp + str_arg_l, f, long_arg); - break; - case '2': str_arg_l += sprintf(tmp + str_arg_l, f, long_long_arg); - break; - } - } else if (fmt_spec == 'b' || fmt_spec == 'B') { - // binary - size_t bits = 0; - switch (length_modifier) { - case '\0': - case 'h': for (bits = sizeof(unsigned) * 8; bits > 0; bits--) { - if ((uint_arg >> (bits - 1)) & 0x1) { break; } } - - while (bits > 0) { - tmp[str_arg_l++] = - ((uint_arg >> --bits) & 0x1) ? '1' : '0'; } - break; - case 'l': for (bits = sizeof(unsigned long) * 8; bits > 0; bits--) { - if ((ulong_arg >> (bits - 1)) & 0x1) { break; } } - - while (bits > 0) { - tmp[str_arg_l++] = - ((ulong_arg >> --bits) & 0x1) ? '1' : '0'; } - break; - case '2': for (bits = sizeof(unsigned long long) * 8; // NOLINT (runtime/int) - bits > 0; bits--) { - if ((ulong_long_arg >> (bits - 1)) & 0x1) { break; } } - - while (bits > 0) { - tmp[str_arg_l++] = - ((ulong_long_arg >> --bits) & 0x1) ? '1' : '0'; } - break; - case 'z': for (bits = sizeof(size_t) * 8; bits > 0; bits--) { - if ((size_t_arg >> (bits - 1)) & 0x1) { break; } } - - while (bits > 0) { - tmp[str_arg_l++] = - ((size_t_arg >> --bits) & 0x1) ? '1' : '0'; } - break; - } - } else { - // unsigned - switch (length_modifier) { - case '\0': - case 'h': str_arg_l += sprintf(tmp + str_arg_l, f, uint_arg); - break; - case 'l': str_arg_l += sprintf(tmp + str_arg_l, f, ulong_arg); - break; - case '2': str_arg_l += sprintf(tmp + str_arg_l, f, ulong_long_arg); - break; - case 'z': str_arg_l += sprintf(tmp + str_arg_l, f, size_t_arg); - break; - } - } - - // include the optional minus sign and possible "0x" in the region - // before the zero padding insertion point - if (zero_padding_insertion_ind < str_arg_l - && tmp[zero_padding_insertion_ind] == '-') - zero_padding_insertion_ind++; - if (zero_padding_insertion_ind + 1 < str_arg_l - && tmp[zero_padding_insertion_ind] == '0' - && (tmp[zero_padding_insertion_ind + 1] == 'x' - || tmp[zero_padding_insertion_ind + 1] == 'X' - || tmp[zero_padding_insertion_ind + 1] == 'b' - || tmp[zero_padding_insertion_ind + 1] == 'B')) - zero_padding_insertion_ind += 2; - } - - { - size_t num_of_digits = str_arg_l - zero_padding_insertion_ind; - - if (alternate_form && fmt_spec == 'o' - // unless zero is already the first character - && !(zero_padding_insertion_ind < str_arg_l - && tmp[zero_padding_insertion_ind] == '0')) { - // assure leading zero for alternate-form octal numbers - if (!precision_specified - || precision < num_of_digits + 1) { - // precision is increased to force the first character to be zero, - // except if a zero value is formatted with an explicit precision - // of zero - precision = num_of_digits + 1; - } - } - // zero padding to specified precision? - if (num_of_digits < precision) - number_of_zeros_to_pad = precision - num_of_digits; - } - // zero padding to specified minimal field width? - if (!justify_left && zero_padding) { - int n = (int)(min_field_width - (str_arg_l - + number_of_zeros_to_pad)); - if (n > 0) - number_of_zeros_to_pad += n; - } - break; - } - - case 'f': - case 'e': - case 'E': - case 'g': - case 'G': - { - // floating point - char format[40]; - int l; - int remove_trailing_zeroes = false; - - double f = tvs ? tv_float(tvs, &arg_idx) : va_arg(ap, double); - double abs_f = f < 0 ? -f : f; - - if (fmt_spec == 'g' || fmt_spec == 'G') { - // can't use %g directly, cause it prints "1.0" as "1" - if ((abs_f >= 0.001 && abs_f < 10000000.0) || abs_f == 0.0) - fmt_spec = 'f'; - else - fmt_spec = fmt_spec == 'g' ? 'e' : 'E'; - remove_trailing_zeroes = true; - } - - if (fmt_spec == 'f' && abs_f > 1.0e307) { - // avoid a buffer overflow - strcpy(tmp, "inf"); - str_arg_l = 3; - } else { - format[0] = '%'; - l = 1; - if (precision_specified) { - size_t max_prec = TMP_LEN - 10; - - // make sure we don't get more digits than we have room for - if (fmt_spec == 'f' && abs_f > 1.0) - max_prec -= (size_t)log10(abs_f); - if (precision > max_prec) - precision = max_prec; - l += sprintf(format + 1, ".%d", (int)precision); - } - format[l] = fmt_spec; - format[l + 1] = NUL; - str_arg_l = sprintf(tmp, format, f); - - if (remove_trailing_zeroes) { - int i; - char *tp; - - // using %g or %G: remove superfluous zeroes - if (fmt_spec == 'f') - tp = tmp + str_arg_l - 1; - else { - tp = (char *)vim_strchr((char_u *)tmp, - fmt_spec == 'e' ? 'e' : 'E'); - if (tp) { - // remove superfluous '+' and leading zeroes from exponent - if (tp[1] == '+') { - // change "1.0e+07" to "1.0e07" - STRMOVE(tp + 1, tp + 2); - --str_arg_l; - } - i = (tp[1] == '-') ? 2 : 1; - while (tp[i] == '0') { - // change "1.0e07" to "1.0e7" - STRMOVE(tp + i, tp + i + 1); - --str_arg_l; - } - --tp; - } - } - - if (tp != NULL && !precision_specified) - // remove trailing zeroes, but keep the one just after a dot - while (tp > tmp + 2 && *tp == '0' && tp[-1] != '.') { - STRMOVE(tp, tp + 1); - --tp; - --str_arg_l; - } - } else { - // be consistent: some printf("%e") use 1.0e+12 and some 1.0e+012; - // remove one zero in the last case - char *tp = (char *)vim_strchr((char_u *)tmp, - fmt_spec == 'e' ? 'e' : 'E'); - if (tp && (tp[1] == '+' || tp[1] == '-') && tp[2] == '0' - && ascii_isdigit(tp[3]) && ascii_isdigit(tp[4])) { - STRMOVE(tp + 2, tp + 3); - --str_arg_l; - } - } - } - str_arg = tmp; - break; - } - - default: - // unrecognized conversion specifier, keep format string as-is - zero_padding = 0; // turn zero padding off for non-numeric conversion - justify_left = 1; - min_field_width = 0; // reset flags - - // discard the unrecognized conversion, just keep - // the unrecognized conversion character - str_arg = p; - str_arg_l = 0; - if (*p) - str_arg_l++; // include invalid conversion specifier - // unchanged if not at end-of-string - break; - } - - if (*p) - p++; // step over the just processed conversion specifier - - // insert padding to the left as requested by min_field_width; - // this does not include the zero padding in case of numerical conversions - if (!justify_left) { - assert(str_arg_l <= SIZE_MAX - number_of_zeros_to_pad); - if (min_field_width > str_arg_l + number_of_zeros_to_pad) { - // left padding with blank or zero - size_t pn = min_field_width - (str_arg_l + number_of_zeros_to_pad); - if (str_avail) { - size_t avail = str_m - str_l; - memset(str + str_l, zero_padding ? '0' : ' ', MIN(pn, avail)); - str_avail = pn < avail; - } - assert(pn <= SIZE_MAX - str_l); - str_l += pn; - } - } - - // zero padding as requested by the precision or by the minimal - // field width for numeric conversions required? - if (number_of_zeros_to_pad == 0) { - // will not copy first part of numeric right now, - // force it to be copied later in its entirety - zero_padding_insertion_ind = 0; - } else { - // insert first part of numerics (sign or '0x') before zero padding - if (zero_padding_insertion_ind > 0) { - size_t zn = zero_padding_insertion_ind; - if (str_avail) { - size_t avail = str_m - str_l; - memmove(str + str_l, str_arg, MIN(zn, avail)); - str_avail = zn < avail; - } - assert(zn <= SIZE_MAX - str_l); - str_l += zn; - } - - // insert zero padding as requested by precision or min field width - if (number_of_zeros_to_pad > 0) { - size_t zn = number_of_zeros_to_pad; - if (str_avail) { - size_t avail = str_m - str_l; - memset(str + str_l, '0', MIN(zn, avail)); - str_avail = zn < avail; - } - assert(zn <= SIZE_MAX - str_l); - str_l += zn; - } - } - - // insert formatted string - // (or as-is conversion specifier for unknown conversions) - if (str_arg_l > zero_padding_insertion_ind) { - size_t sn = str_arg_l - zero_padding_insertion_ind; - if (str_avail) { - size_t avail = str_m - str_l; - memmove(str + str_l, - str_arg + zero_padding_insertion_ind, - MIN(sn, avail)); - str_avail = sn < avail; - } - assert(sn <= SIZE_MAX - str_l); - str_l += sn; - } - - // insert right padding - if (justify_left) { - assert(str_arg_l <= SIZE_MAX - number_of_zeros_to_pad); - if (min_field_width > str_arg_l + number_of_zeros_to_pad) { - // right blank padding to the field width - size_t pn = min_field_width - (str_arg_l + number_of_zeros_to_pad); - if (str_avail) { - size_t avail = str_m - str_l; - memset(str + str_l, ' ', MIN(pn, avail)); - str_avail = pn < avail; - } - assert(pn <= SIZE_MAX - str_l); - str_l += pn; - } - } - } - } - - if (str_m > 0) { - // make sure the string is nul-terminated even at the expense of - // overwriting the last character (shouldn't happen, but just in case) - str[str_l <= str_m - 1 ? str_l : str_m - 1] = '\0'; - } - - if (tvs && tvs[arg_idx - 1].v_type != VAR_UNKNOWN) - EMSG(_("E767: Too many arguments to printf()")); - - // return the number of characters formatted (excluding trailing nul - // character); that is, the number of characters that would have been - // written to the buffer if it were large enough. - return (int)str_l; -} diff --git a/src/nvim/message.h b/src/nvim/message.h index d3a16fff93..904a9d3ca1 100644 --- a/src/nvim/message.h +++ b/src/nvim/message.h @@ -3,8 +3,9 @@ #include <stdbool.h> #include <stdarg.h> -#include "nvim/eval_defs.h" // for typval_T -#include "nvim/ex_cmds_defs.h" // for exarg_T +#include <stddef.h> + +#include "nvim/types.h" /* * Types of dialogs passed to do_dialog(). @@ -29,7 +30,7 @@ #define MSG(s) msg((char_u *)(s)) /// Show message highlighted according to the attr -#define MSG_ATTR(s, attr) msg_attr((char_u *)(s), (attr)) +#define MSG_ATTR(s, attr) msg_attr((const char *)(s), (attr)) /// Display error message /// @@ -49,13 +50,13 @@ #define EMSGU(s, n) emsgf((const char *) (s), (uint64_t)(n)) /// Display message at the recorded position -#define MSG_PUTS(s) msg_puts((char_u *)(s)) +#define MSG_PUTS(s) msg_puts((const char *)(s)) /// Display message at the recorded position, highlighted -#define MSG_PUTS_ATTR(s, a) msg_puts_attr((char_u *)(s), (a)) +#define MSG_PUTS_ATTR(s, a) msg_puts_attr((const char *)(s), (a)) /// Like #MSG_PUTS, but highlight like title -#define MSG_PUTS_TITLE(s) msg_puts_title((char_u *)(s)) +#define MSG_PUTS_TITLE(s) msg_puts_title((const char *)(s)) /// Like #MSG_PUTS, but if middle part of too long messages it will be replaced #define MSG_PUTS_LONG(s) msg_puts_long_attr((char_u *)(s), 0) diff --git a/src/nvim/misc1.c b/src/nvim/misc1.c index 71aa6e83e5..5270687a4d 100644 --- a/src/nvim/misc1.c +++ b/src/nvim/misc1.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + /* * misc1.c: functions that didn't seem to fit elsewhere */ @@ -51,6 +54,7 @@ #include "nvim/os/input.h" #include "nvim/os/time.h" #include "nvim/event/stream.h" +#include "nvim/buffer.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "misc1.c.generated.h" @@ -747,7 +751,7 @@ open_line ( // Skip mark_adjust when adding a line after the last one, there can't // be marks there. if (curwin->w_cursor.lnum + 1 < curbuf->b_ml.ml_line_count) { - mark_adjust(curwin->w_cursor.lnum + 1, (linenr_T)MAXLNUM, 1L, 0L); + mark_adjust(curwin->w_cursor.lnum + 1, (linenr_T)MAXLNUM, 1L, 0L, false); } did_append = true; } else { @@ -1405,7 +1409,6 @@ void ins_char_bytes(char_u *buf, size_t charlen) coladvance_force(getviscol()); } - int c = buf[0]; size_t col = (size_t)curwin->w_cursor.col; linenr_T lnum = curwin->w_cursor.lnum; char_u *oldp = ml_get(lnum); @@ -1498,10 +1501,7 @@ void ins_char_bytes(char_u *buf, size_t charlen) && msg_silent == 0 && !ins_compl_active() ) { - if (has_mbyte) - showmatch(mb_ptr2char(buf)); - else - showmatch(c); + showmatch(mb_ptr2char(buf)); } if (!p_ri || (State & REPLACE_FLAG)) { @@ -1788,7 +1788,7 @@ void changed(void) } changed_int(); } - ++curbuf->b_changedtick; + buf_set_changedtick(curbuf, curbuf->b_changedtick + 1); } /* @@ -1866,7 +1866,7 @@ void appended_lines_mark(linenr_T lnum, long count) // Skip mark_adjust when adding a line after the last one, there can't // be marks there. if (lnum + count < curbuf->b_ml.ml_line_count) { - mark_adjust(lnum + 1, (linenr_T)MAXLNUM, count, 0L); + mark_adjust(lnum + 1, (linenr_T)MAXLNUM, count, 0L, false); } changed_lines(lnum + 1, 0, lnum + 1, count); } @@ -1888,7 +1888,7 @@ void deleted_lines(linenr_T lnum, long count) */ void deleted_lines_mark(linenr_T lnum, long count) { - mark_adjust(lnum, (linenr_T)(lnum + count - 1), (long)MAXLNUM, -count); + mark_adjust(lnum, (linenr_T)(lnum + count - 1), (long)MAXLNUM, -count, false); changed_lines(lnum, 0, lnum + count, -count); } @@ -2147,7 +2147,7 @@ unchanged ( redraw_tabline = TRUE; need_maketitle = TRUE; /* set window title later */ } - ++buf->b_changedtick; + buf_set_changedtick(buf, buf->b_changedtick + 1); } /* @@ -2203,7 +2203,7 @@ change_warning ( set_vim_var_string(VV_WARNINGMSG, _(w_readonly), -1); msg_clr_eos(); (void)msg_end(); - if (msg_silent == 0 && !silent_mode) { + if (msg_silent == 0 && !silent_mode && ui_active()) { ui_flush(); os_delay(1000L, true); /* give the user time to think about it */ } @@ -2214,44 +2214,47 @@ change_warning ( } } -/* - * Ask for a reply from the user, a 'y' or a 'n'. - * No other characters are accepted, the message is repeated until a valid - * reply is entered or CTRL-C is hit. - * If direct is TRUE, don't use vgetc() but ui_inchar(), don't get characters - * from any buffers but directly from the user. - * - * return the 'y' or 'n' - */ -int ask_yesno(char_u *str, int direct) +/// Ask for a reply from the user, 'y' or 'n' +/// +/// No other characters are accepted, the message is repeated until a valid +/// reply is entered or <C-c> is hit. +/// +/// @param[in] str Prompt: question to ask user. Is always followed by +/// " (y/n)?". +/// @param[in] direct Determines what function to use to get user input. If +/// true then ui_inchar() will be used, otherwise vgetc(). +/// I.e. when direct is true then characters are obtained +/// directly from the user without buffers involved. +/// +/// @return 'y' or 'n'. Last is also what will be returned in case of interrupt. +int ask_yesno(const char *const str, const bool direct) { - int r = ' '; - int save_State = State; + const int save_State = State; - ++no_wait_return; - State = CONFIRM; /* mouse behaves like with :confirm */ - setmouse(); /* disables mouse for xterm */ - ++no_mapping; - ++allow_keys; /* no mapping here, but recognize keys */ + no_wait_return++; + State = CONFIRM; // Mouse behaves like with :confirm. + setmouse(); // Disable mouse in xterm. + no_mapping++; + int r = ' '; while (r != 'y' && r != 'n') { - /* same highlighting as for wait_return */ - smsg_attr(hl_attr(HLF_R), - "%s (y/n)?", str); - if (direct) + // Same highlighting as for wait_return. + smsg_attr(hl_attr(HLF_R), "%s (y/n)?", str); + if (direct) { r = get_keystroke(); - else + } else { r = plain_vgetc(); - if (r == Ctrl_C || r == ESC) + } + if (r == Ctrl_C || r == ESC) { r = 'n'; - msg_putchar(r); /* show what you typed */ + } + msg_putchar(r); // Show what you typed. ui_flush(); } - --no_wait_return; + no_wait_return--; State = save_State; setmouse(); - --no_mapping; - --allow_keys; + no_mapping--; return r; } @@ -2324,8 +2327,8 @@ int get_keystroke(void) * terminal code to complete. */ n = os_inchar(buf + len, maxlen, len == 0 ? -1L : 100L, 0); if (n > 0) { - /* Replace zero and CSI by a special key code. */ - n = fix_input_buffer(buf + len, n, FALSE); + // Replace zero and CSI by a special key code. + n = fix_input_buffer(buf + len, n); len += n; waited = 0; } else if (len > 0) @@ -2401,8 +2404,7 @@ get_number ( if (msg_silent != 0) return 0; - ++no_mapping; - ++allow_keys; /* no mapping here, but recognize keys */ + no_mapping++; for (;; ) { ui_cursor_goto(msg_row, msg_col); c = safe_vgetc(); @@ -2430,8 +2432,7 @@ get_number ( } else if (c == CAR || c == NL || c == Ctrl_C || c == ESC) break; } - --no_mapping; - --allow_keys; + no_mapping--; return n; } @@ -2507,8 +2508,9 @@ void msgmore(long n) vim_snprintf((char *)msg_buf, MSG_BUF_LEN, _("%" PRId64 " fewer lines"), (int64_t)pn); } - if (got_int) - vim_strcat(msg_buf, (char_u *)_(" (Interrupted)"), MSG_BUF_LEN); + if (got_int) { + xstrlcat((char *)msg_buf, _(" (Interrupted)"), MSG_BUF_LEN); + } if (msg(msg_buf)) { set_keep_msg(msg_buf, 0); keep_msg_more = TRUE; @@ -2534,9 +2536,9 @@ void vim_beep(unsigned val) if (emsg_silent == 0) { if (!((bo_flags & val) || (bo_flags & BO_ALL))) { if (p_vb) { - ui_visual_bell(); + ui_call_visual_bell(); } else { - ui_putc(BELL); + ui_call_bell(); } } @@ -2544,7 +2546,7 @@ void vim_beep(unsigned val) * function give the user a hint where the beep comes from. */ if (vim_strchr(p_debug, 'e') != NULL) { msg_source(hl_attr(HLF_W)); - msg_attr((char_u *)_("Beep!"), hl_attr(HLF_W)); + msg_attr(_("Beep!"), hl_attr(HLF_W)); } } } @@ -2679,7 +2681,8 @@ void fast_breakcheck(void) } } -// Call shell. Calls os_call_shell, with 'shellxquote' added. +// os_call_shell wrapper. Handles 'verbose', :profile, and v:shell_error. +// Invalidates cached tags. int call_shell(char_u *cmd, ShellOpts opts, char_u *extra_shell_arg) { int retval; @@ -2687,9 +2690,8 @@ int call_shell(char_u *cmd, ShellOpts opts, char_u *extra_shell_arg) if (p_verbose > 3) { verbose_enter(); - smsg(_("Calling shell to execute: \"%s\""), - cmd == NULL ? p_sh : cmd); - ui_putc('\n'); + smsg(_("Calling shell to execute: \"%s\""), cmd == NULL ? p_sh : cmd); + ui_linefeed(); verbose_leave(); } diff --git a/src/nvim/mouse.c b/src/nvim/mouse.c index 2ebe199f47..d908a022f1 100644 --- a/src/nvim/mouse.c +++ b/src/nvim/mouse.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #include <stdbool.h> #include "nvim/mouse.h" @@ -456,6 +459,7 @@ void setmouse(void) { int checkfor; + ui_cursor_shape(); /* be quick when mouse is off */ if (*p_mouse == NUL) @@ -475,9 +479,9 @@ void setmouse(void) checkfor = MOUSE_NORMAL; /* assume normal mode */ if (mouse_has(checkfor)) { - ui_mouse_on(); + ui_call_mouse_on(); } else { - ui_mouse_off(); + ui_call_mouse_off(); } } diff --git a/src/nvim/move.c b/src/nvim/move.c index bb6c032db1..4d646f5a4b 100644 --- a/src/nvim/move.c +++ b/src/nvim/move.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + /* * move.c: Functions for moving the cursor and scrolling text. * @@ -1760,7 +1763,7 @@ int onepage(int dir, long count) loff.fill = 0; if (dir == FORWARD) { - if (firstwin == lastwin && p_window > 0 && p_window < Rows - 1) { + if (ONE_WINDOW && p_window > 0 && p_window < Rows - 1) { /* Vi compatible scrolling */ if (p_window <= 2) ++curwin->w_topline; @@ -1794,7 +1797,7 @@ int onepage(int dir, long count) max_topfill(); continue; } - if (firstwin == lastwin && p_window > 0 && p_window < Rows - 1) { + if (ONE_WINDOW && p_window > 0 && p_window < Rows - 1) { /* Vi compatible scrolling (sort of) */ if (p_window <= 2) --curwin->w_topline; @@ -1878,8 +1881,10 @@ int onepage(int dir, long count) } foldAdjustCursor(); cursor_correct(); - if (retval == OK) + check_cursor_col(); + if (retval == OK) { beginline(BL_SOL | BL_FIX); + } curwin->w_valid &= ~(VALID_WCOL|VALID_WROW|VALID_VIRTCOL); /* @@ -2137,18 +2142,17 @@ void do_check_cursorbind(void) * loop through the cursorbound windows */ VIsual_select = VIsual_active = 0; - for (curwin = firstwin; curwin; curwin = curwin->w_next) { + FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { + curwin = wp; curbuf = curwin->w_buffer; /* skip original window and windows with 'noscrollbind' */ if (curwin != old_curwin && curwin->w_p_crb) { - if (curwin->w_p_diff) - curwin->w_cursor.lnum - = diff_get_corresponding_line(old_curbuf, - line, - curbuf, - curwin->w_cursor.lnum); - else + if (curwin->w_p_diff) { + curwin->w_cursor.lnum = + diff_get_corresponding_line(old_curbuf, line); + } else { curwin->w_cursor.lnum = line; + } curwin->w_cursor.col = col; curwin->w_cursor.coladd = coladd; curwin->w_curswant = curswant; diff --git a/src/nvim/move.h b/src/nvim/move.h index 3f3bf70929..00fbcc580f 100644 --- a/src/nvim/move.h +++ b/src/nvim/move.h @@ -2,6 +2,8 @@ #define NVIM_MOVE_H #include <stdbool.h> +#include "nvim/buffer_defs.h" +#include "nvim/pos.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "move.h.generated.h" diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c index 98636263b9..02f3854f47 100644 --- a/src/nvim/msgpack_rpc/channel.c +++ b/src/nvim/msgpack_rpc/channel.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #include <stdbool.h> #include <string.h> #include <inttypes.h> @@ -9,6 +12,7 @@ #include "nvim/api/vim.h" #include "nvim/api/ui.h" #include "nvim/msgpack_rpc/channel.h" +#include "nvim/msgpack_rpc/server.h" #include "nvim/event/loop.h" #include "nvim/event/libuv_process.h" #include "nvim/event/rstream.h" @@ -25,7 +29,9 @@ #include "nvim/map.h" #include "nvim/log.h" #include "nvim/misc1.h" +#include "nvim/path.h" #include "nvim/lib/kvec.h" +#include "nvim/os/input.h" #define CHANNEL_BUFFER_SIZE 0xffff @@ -37,7 +43,8 @@ typedef enum { kChannelTypeSocket, kChannelTypeProc, - kChannelTypeStdio + kChannelTypeStdio, + kChannelTypeInternal } ChannelType; typedef struct { @@ -55,7 +62,7 @@ typedef struct { ChannelType type; msgpack_unpacker *unpacker; union { - Stream stream; + Stream stream; // bidirectional (socket) Process *proc; struct { Stream in; @@ -86,6 +93,7 @@ static msgpack_sbuffer out_buffer; /// Initializes the module void channel_init(void) { + ch_before_blocking_events = multiqueue_new_child(main_loop.events); channels = pmap_new(uint64_t)(); event_strings = pmap_new(cstr_t)(); msgpack_sbuffer_init(&out_buffer); @@ -109,18 +117,24 @@ void channel_teardown(void) /// Creates an API channel by starting a process and connecting to its /// stdin/stdout. stderr is handled by the job infrastructure. /// -/// @param argv The argument vector for the process. [consumed] -/// @return The channel id (> 0), on success. -/// 0, on error. -uint64_t channel_from_process(Process *proc, uint64_t id) +/// @param proc process object +/// @param id (optional) channel id +/// @param source description of source function, rplugin name, TCP addr, etc +/// +/// @return Channel id (> 0), on success. 0, on error. +uint64_t channel_from_process(Process *proc, uint64_t id, char *source) { - Channel *channel = register_channel(kChannelTypeProc, id, proc->events); + Channel *channel = register_channel(kChannelTypeProc, id, proc->events, + source); incref(channel); // process channels are only closed by the exit_cb channel->data.proc = proc; wstream_init(proc->in, 0); rstream_init(proc->out, 0); - rstream_start(proc->out, parse_msgpack, channel); + rstream_start(proc->out, receive_msgpack, channel); + + DLOG("ch %" PRIu64 " in-stream=%p out-stream=%p", channel->id, proc->in, + proc->out); return channel->id; } @@ -130,14 +144,48 @@ uint64_t channel_from_process(Process *proc, uint64_t id) /// @param watcher The SocketWatcher ready to accept the connection void channel_from_connection(SocketWatcher *watcher) { - Channel *channel = register_channel(kChannelTypeSocket, 0, NULL); + Channel *channel = register_channel(kChannelTypeSocket, 0, NULL, + watcher->addr); socket_watcher_accept(watcher, &channel->data.stream); incref(channel); // close channel only after the stream is closed channel->data.stream.internal_close_cb = close_cb; channel->data.stream.internal_data = channel; wstream_init(&channel->data.stream, 0); rstream_init(&channel->data.stream, CHANNEL_BUFFER_SIZE); - rstream_start(&channel->data.stream, parse_msgpack, channel); + rstream_start(&channel->data.stream, receive_msgpack, channel); + + DLOG("ch %" PRIu64 " in/out-stream=%p", channel->id, + &channel->data.stream); +} + +/// @param source description of source function, rplugin name, TCP addr, etc +uint64_t channel_connect(bool tcp, const char *address, int timeout, + char *source, const char **error) +{ + if (!tcp) { + char *path = fix_fname(address); + if (server_owns_pipe_address(path)) { + // avoid deadlock + xfree(path); + return channel_create_internal(); + } + xfree(path); + } + + Channel *channel = register_channel(kChannelTypeSocket, 0, NULL, source); + if (!socket_connect(&main_loop, &channel->data.stream, + tcp, address, timeout, error)) { + decref(channel); + return 0; + } + + incref(channel); // close channel only after the stream is closed + channel->data.stream.internal_close_cb = close_cb; + channel->data.stream.internal_data = channel; + wstream_init(&channel->data.stream, 0); + rstream_init(&channel->data.stream, CHANNEL_BUFFER_SIZE); + rstream_start(&channel->data.stream, receive_msgpack, channel); + return channel->id; } /// Sends event/arguments to channel @@ -147,7 +195,7 @@ void channel_from_connection(SocketWatcher *watcher) /// @param name The event name, an arbitrary string /// @param args Array with event arguments /// @return True if the event was sent successfully, false otherwise. -bool channel_send_event(uint64_t id, char *name, Array args) +bool channel_send_event(uint64_t id, const char *name, Array args) { Channel *channel = NULL; @@ -160,7 +208,7 @@ bool channel_send_event(uint64_t id, char *name, Array args) if (channel) { if (channel->pending_requests) { // Pending request, queue the notification for later sending. - String method = cstr_as_string(name); + const String method = cstr_as_string((char *)name); WBuffer *buffer = serialize_request(id, 0, method, args, &out_buffer, 1); kv_push(channel->delayed_notifications, buffer); } else { @@ -182,14 +230,14 @@ bool channel_send_event(uint64_t id, char *name, Array args) /// @param[out] error True if the return value is an error /// @return Whatever the remote method returned Object channel_send_call(uint64_t id, - char *method_name, + const char *method_name, Array args, Error *err) { Channel *channel = NULL; if (!(channel = pmap_get(uint64_t)(channels, id)) || channel->closed) { - api_set_error(err, Exception, _("Invalid channel \"%" PRIu64 "\""), id); + api_set_error(err, kErrorTypeException, "Invalid channel: %" PRIu64, id); api_free_array(args); return NIL; } @@ -209,7 +257,8 @@ Object channel_send_call(uint64_t id, if (frame.errored) { if (frame.result.type == kObjectTypeString) { - api_set_error(err, Exception, "%s", frame.result.data.string.data); + api_set_error(err, kErrorTypeException, "%s", + frame.result.data.string.data); } else if (frame.result.type == kObjectTypeArray) { // Should be an error in the form [type, message] Array array = frame.result.data.array; @@ -217,14 +266,13 @@ Object channel_send_call(uint64_t id, && (array.items[0].data.integer == kErrorTypeException || array.items[0].data.integer == kErrorTypeValidation) && array.items[1].type == kObjectTypeString) { - err->type = (ErrorType) array.items[0].data.integer; - xstrlcpy(err->msg, array.items[1].data.string.data, sizeof(err->msg)); - err->set = true; + api_set_error(err, (ErrorType)array.items[0].data.integer, "%s", + array.items[1].data.string.data); } else { - api_set_error(err, Exception, "%s", "unknown error"); + api_set_error(err, kErrorTypeException, "%s", "unknown error"); } } else { - api_set_error(err, Exception, "%s", "unknown error"); + api_set_error(err, kErrorTypeException, "%s", "unknown error"); } api_free_object(frame.result); @@ -292,17 +340,28 @@ bool channel_close(uint64_t id) return true; } -/// Creates an API channel from stdin/stdout. This is used when embedding -/// Neovim +/// Creates an API channel from stdin/stdout. Used to embed Nvim. void channel_from_stdio(void) { - Channel *channel = register_channel(kChannelTypeStdio, 0, NULL); + Channel *channel = register_channel(kChannelTypeStdio, 0, NULL, NULL); incref(channel); // stdio channels are only closed on exit // read stream rstream_init_fd(&main_loop, &channel->data.std.in, 0, CHANNEL_BUFFER_SIZE); - rstream_start(&channel->data.std.in, parse_msgpack, channel); + rstream_start(&channel->data.std.in, receive_msgpack, channel); // write stream wstream_init_fd(&main_loop, &channel->data.std.out, 1, 0); + + DLOG("ch %" PRIu64 " in-stream=%p out-stream=%p", channel->id, + &channel->data.std.in, &channel->data.std.out); +} + +/// Creates a loopback channel. This is used to avoid deadlock +/// when an instance connects to its own named pipe. +uint64_t channel_create_internal(void) +{ + Channel *channel = register_channel(kChannelTypeInternal, 0, NULL, NULL); + incref(channel); // internal channel lives until process exit + return channel->id; } void channel_process_exit(uint64_t id, int status) @@ -313,28 +372,50 @@ void channel_process_exit(uint64_t id, int status) decref(channel); } -static void parse_msgpack(Stream *stream, RBuffer *rbuf, size_t c, void *data, - bool eof) +// rstream.c:read_event() invokes this as stream->read_cb(). +static void receive_msgpack(Stream *stream, RBuffer *rbuf, size_t c, + void *data, bool eof) { Channel *channel = data; incref(channel); if (eof) { close_channel(channel); - call_set_error(channel, "Channel was closed by the client"); + char buf[256]; + snprintf(buf, sizeof(buf), "ch %" PRIu64 " was closed by the client", + channel->id); + call_set_error(channel, buf, WARN_LOG_LEVEL); + goto end; + } + + if ((chan_wstream(channel) != NULL && chan_wstream(channel)->closed) + || (chan_rstream(channel) != NULL && chan_rstream(channel)->closed)) { + char buf[256]; + snprintf(buf, sizeof(buf), + "ch %" PRIu64 ": stream closed unexpectedly. " + "closing channel", + channel->id); + call_set_error(channel, buf, WARN_LOG_LEVEL); goto end; } size_t count = rbuffer_size(rbuf); - DLOG("Feeding the msgpack parser with %u bytes of data from Stream(%p)", - count, - stream); + DLOG("ch %" PRIu64 ": parsing %u bytes from msgpack Stream: %p", + channel->id, count, stream); // Feed the unpacker with data msgpack_unpacker_reserve_buffer(channel->unpacker, count); rbuffer_read(rbuf, msgpack_unpacker_buffer(channel->unpacker), count); msgpack_unpacker_buffer_consumed(channel->unpacker, count); + parse_msgpack(channel); + +end: + decref(channel); +} + +static void parse_msgpack(Channel *channel) +{ msgpack_unpacked unpacked; msgpack_unpacked_init(&unpacked); msgpack_unpack_return result; @@ -350,17 +431,15 @@ static void parse_msgpack(Stream *stream, RBuffer *rbuf, size_t c, void *data, complete_call(&unpacked.data, channel); } else { char buf[256]; - snprintf(buf, - sizeof(buf), - "Channel %" PRIu64 " returned a response that doesn't have " - "a matching request id. Ensure the client is properly " - "synchronized", + snprintf(buf, sizeof(buf), + "ch %" PRIu64 " returned a response with an unknown request " + "id. Ensure the client is properly synchronized", channel->id); - call_set_error(channel, buf); + call_set_error(channel, buf, ERROR_LOG_LEVEL); } msgpack_unpacked_destroy(&unpacked); // Bail out from this event loop iteration - goto end; + return; } handle_request(channel, &unpacked.data); @@ -378,17 +457,15 @@ static void parse_msgpack(Stream *stream, RBuffer *rbuf, size_t c, void *data, // causes for this error(search for 'goto _failed') // // A not so uncommon cause for this might be deserializing objects with - // a high nesting level: msgpack will break when it's internal parse stack - // size exceeds MSGPACK_EMBED_STACK_SIZE(defined as 32 by default) + // a high nesting level: msgpack will break when its internal parse stack + // size exceeds MSGPACK_EMBED_STACK_SIZE (defined as 32 by default) send_error(channel, 0, "Invalid msgpack payload. " "This error can also happen when deserializing " "an object with high level of nesting"); } - -end: - decref(channel); } + static void handle_request(Channel *channel, msgpack_object *request) FUNC_ATTR_NONNULL_ALL { @@ -396,7 +473,7 @@ static void handle_request(Channel *channel, msgpack_object *request) Error error = ERROR_INIT; msgpack_rpc_validate(&request_id, request, &error); - if (error.set) { + if (ERROR_SET(&error)) { // Validation failed, send response with error if (channel_write(channel, serialize_response(channel->id, @@ -406,13 +483,13 @@ static void handle_request(Channel *channel, msgpack_object *request) &out_buffer))) { char buf[256]; snprintf(buf, sizeof(buf), - "Channel %" PRIu64 " sent an invalid message, closed.", + "ch %" PRIu64 " sent an invalid message, closed.", channel->id); - call_set_error(channel, buf); + call_set_error(channel, buf, ERROR_LOG_LEVEL); } + api_clear_error(&error); return; } - // Retrieve the request handler MsgpackRpcRequestHandler handler; msgpack_object *method = msgpack_rpc_method(request); @@ -431,16 +508,24 @@ static void handle_request(Channel *channel, msgpack_object *request) handler.async = true; } - RequestEvent *event_data = xmalloc(sizeof(RequestEvent)); - event_data->channel = channel; - event_data->handler = handler; - event_data->args = args; - event_data->request_id = request_id; + RequestEvent *evdata = xmalloc(sizeof(RequestEvent)); + evdata->channel = channel; + evdata->handler = handler; + evdata->args = args; + evdata->request_id = request_id; incref(channel); if (handler.async) { - on_request_event((void **)&event_data); + bool is_get_mode = handler.fn == handle_nvim_get_mode; + + if (is_get_mode && !input_blocking()) { + // Defer the event to a special queue used by os/input.c. #6247 + multiqueue_put(ch_before_blocking_events, on_request_event, 1, evdata); + } else { + // Invoke immediately. + on_request_event((void **)&evdata); + } } else { - multiqueue_put(channel->events, on_request_event, 1, event_data); + multiqueue_put(channel->events, on_request_event, 1, evdata); } } @@ -468,11 +553,45 @@ static void on_request_event(void **argv) api_free_array(args); decref(channel); xfree(e); + api_clear_error(&error); } +/// Returns the Stream that a Channel writes to. +static Stream *chan_wstream(Channel *chan) +{ + switch (chan->type) { + case kChannelTypeSocket: + return &chan->data.stream; + case kChannelTypeProc: + return chan->data.proc->in; + case kChannelTypeStdio: + return &chan->data.std.out; + case kChannelTypeInternal: + return NULL; + } + abort(); +} + +/// Returns the Stream that a Channel reads from. +static Stream *chan_rstream(Channel *chan) +{ + switch (chan->type) { + case kChannelTypeSocket: + return &chan->data.stream; + case kChannelTypeProc: + return chan->data.proc->out; + case kChannelTypeStdio: + return &chan->data.std.in; + case kChannelTypeInternal: + return NULL; + } + abort(); +} + + static bool channel_write(Channel *channel, WBuffer *buffer) { - bool success; + bool success = false; if (channel->closed) { wstream_release_wbuffer(buffer); @@ -481,16 +600,15 @@ static bool channel_write(Channel *channel, WBuffer *buffer) switch (channel->type) { case kChannelTypeSocket: - success = wstream_write(&channel->data.stream, buffer); - break; case kChannelTypeProc: - success = wstream_write(channel->data.proc->in, buffer); - break; case kChannelTypeStdio: - success = wstream_write(&channel->data.std.out, buffer); + success = wstream_write(chan_wstream(channel), buffer); + break; + case kChannelTypeInternal: + incref(channel); + CREATE_EVENT(channel->events, internal_read_event, 2, channel, buffer); + success = true; break; - default: - abort(); } if (!success) { @@ -498,32 +616,49 @@ static bool channel_write(Channel *channel, WBuffer *buffer) char buf[256]; snprintf(buf, sizeof(buf), - "Before returning from a RPC call, channel %" PRIu64 " was " - "closed due to a failed write", + "ch %" PRIu64 ": stream write failed. " + "RPC canceled; closing channel", channel->id); - call_set_error(channel, buf); + call_set_error(channel, buf, ERROR_LOG_LEVEL); } return success; } +static void internal_read_event(void **argv) +{ + Channel *channel = argv[0]; + WBuffer *buffer = argv[1]; + + msgpack_unpacker_reserve_buffer(channel->unpacker, buffer->size); + memcpy(msgpack_unpacker_buffer(channel->unpacker), + buffer->data, buffer->size); + msgpack_unpacker_buffer_consumed(channel->unpacker, buffer->size); + + parse_msgpack(channel); + + decref(channel); + wstream_release_wbuffer(buffer); +} + static void send_error(Channel *channel, uint64_t id, char *err) { Error e = ERROR_INIT; - api_set_error(&e, Exception, "%s", err); + api_set_error(&e, kErrorTypeException, "%s", err); channel_write(channel, serialize_response(channel->id, id, &e, NIL, &out_buffer)); + api_clear_error(&e); } static void send_request(Channel *channel, uint64_t id, - char *name, + const char *name, Array args) { - String method = {.size = strlen(name), .data = name}; + const String method = cstr_as_string((char *)name); channel_write(channel, serialize_request(channel->id, id, method, @@ -533,10 +668,10 @@ static void send_request(Channel *channel, } static void send_event(Channel *channel, - char *name, + const char *name, Array args) { - String method = {.size = strlen(name), .data = name}; + const String method = cstr_as_string((char *)name); channel_write(channel, serialize_request(channel->id, 0, method, @@ -545,7 +680,7 @@ static void send_event(Channel *channel, 1)); } -static void broadcast_event(char *name, Array args) +static void broadcast_event(const char *name, Array args) { kvec_t(Channel *) subscribed = KV_INITIAL_VALUE; Channel *channel; @@ -561,7 +696,7 @@ static void broadcast_event(char *name, Array args) goto end; } - String method = {.size = strlen(name), .data = name}; + const String method = cstr_as_string((char *)name); WBuffer *buffer = serialize_request(0, 0, method, @@ -622,8 +757,9 @@ static void close_channel(Channel *channel) stream_close(&channel->data.std.out, NULL, NULL); multiqueue_put(main_loop.fast_events, exit_event, 1, channel); return; - default: - abort(); + case kChannelTypeInternal: + // nothing to free. + break; } decref(channel); @@ -664,9 +800,12 @@ static void close_cb(Stream *stream, void *data) decref(data); } +/// @param source description of source function, rplugin name, TCP addr, etc static Channel *register_channel(ChannelType type, uint64_t id, - MultiQueue *events) + MultiQueue *events, char *source) { + // Jobs and channels share the same id namespace. + assert(id == 0 || !pmap_get(uint64_t)(channels, id)); Channel *rv = xmalloc(sizeof(Channel)); rv->events = events ? events : multiqueue_new_child(main_loop.events); rv->type = type; @@ -680,6 +819,14 @@ static Channel *register_channel(ChannelType type, uint64_t id, kv_init(rv->call_stack); kv_init(rv->delayed_notifications); pmap_put(uint64_t)(channels, rv->id, rv); + + ILOG("new channel %" PRIu64 " (%s): %s", rv->id, + (type == kChannelTypeProc ? "proc" + : (type == kChannelTypeSocket ? "socket" + : (type == kChannelTypeStdio ? "stdio" + : (type == kChannelTypeInternal ? "internal" : "?")))), + (source ? source : "?")); + return rv; } @@ -714,13 +861,14 @@ static void complete_call(msgpack_object *obj, Channel *channel) } } -static void call_set_error(Channel *channel, char *msg) +static void call_set_error(Channel *channel, char *msg, int loglevel) { - ELOG("msgpack-rpc: %s", msg); + LOG(loglevel, "RPC: %s", msg); for (size_t i = 0; i < kv_size(channel->call_stack); i++) { ChannelCallFrame *frame = kv_A(channel->call_stack, i); frame->returned = true; frame->errored = true; + api_free_object(frame->result); frame->result = STRING_OBJ(cstr_to_string(msg)); } @@ -729,7 +877,7 @@ static void call_set_error(Channel *channel, char *msg) static WBuffer *serialize_request(uint64_t channel_id, uint64_t request_id, - String method, + const String method, Array args, msgpack_sbuffer *sbuffer, size_t refcount) @@ -789,10 +937,10 @@ static void decref(Channel *channel) } #if MIN_LOG_LEVEL <= DEBUG_LOG_LEVEL -#define REQ "[request] " -#define RES "[response] " -#define NOT "[notification] " -#define ERR "[error] " +#define REQ "[request] " +#define RES "[response] " +#define NOT "[notify] " +#define ERR "[error] " // Cannot define array with negative offsets, so this one is needed to be added // to MSGPACK_UNPACK_\* values. @@ -810,7 +958,7 @@ static void log_server_msg(uint64_t channel_id, { msgpack_unpacked unpacked; msgpack_unpacked_init(&unpacked); - DLOGN("[msgpack-rpc] nvim -> client(%" PRIu64 ") ", channel_id); + DLOGN("RPC ->ch %" PRIu64 ": ", channel_id); const msgpack_unpack_return result = msgpack_unpack_next(&unpacked, packed->data, packed->size, NULL); switch (result) { @@ -847,7 +995,7 @@ static void log_client_msg(uint64_t channel_id, bool is_request, msgpack_object msg) { - DLOGN("[msgpack-rpc] client(%" PRIu64 ") -> nvim ", channel_id); + DLOGN("RPC <-ch %" PRIu64 ": ", channel_id); log_lock(); FILE *f = open_log_file(); fprintf(f, is_request ? REQ : RES); diff --git a/src/nvim/msgpack_rpc/channel.h b/src/nvim/msgpack_rpc/channel.h index 0d92976d02..f8fe6f129b 100644 --- a/src/nvim/msgpack_rpc/channel.h +++ b/src/nvim/msgpack_rpc/channel.h @@ -11,6 +11,11 @@ #define METHOD_MAXLEN 512 +/// HACK: os/input.c drains this queue immediately before blocking for input. +/// Events on this queue are async-safe, but they need the resolved state +/// of os_inchar(), so they are processed "just-in-time". +MultiQueue *ch_before_blocking_events; + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "msgpack_rpc/channel.h.generated.h" #endif diff --git a/src/nvim/msgpack_rpc/helpers.c b/src/nvim/msgpack_rpc/helpers.c index 5137b375f0..fecae11d45 100644 --- a/src/nvim/msgpack_rpc/helpers.c +++ b/src/nvim/msgpack_rpc/helpers.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #include <stdint.h> #include <stdbool.h> #include <inttypes.h> @@ -21,12 +24,12 @@ static msgpack_zone zone; static msgpack_sbuffer sbuffer; #define HANDLE_TYPE_CONVERSION_IMPL(t, lt) \ - bool msgpack_rpc_to_##lt(const msgpack_object *const obj, \ - Integer *const arg) \ - FUNC_ATTR_NONNULL_ALL \ + static bool msgpack_rpc_to_##lt(const msgpack_object *const obj, \ + Integer *const arg) \ + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT \ { \ if (obj->type != MSGPACK_OBJECT_EXT \ - || obj->via.ext.type != kObjectType##t) { \ + || obj->via.ext.type + EXT_OBJECT_TYPE_SHIFT != kObjectType##t) { \ return false; \ } \ \ @@ -45,13 +48,14 @@ static msgpack_sbuffer sbuffer; return true; \ } \ \ - void msgpack_rpc_from_##lt(Integer o, msgpack_packer *res) \ + static void msgpack_rpc_from_##lt(Integer o, msgpack_packer *res) \ FUNC_ATTR_NONNULL_ARG(2) \ { \ msgpack_packer pac; \ msgpack_packer_init(&pac, &sbuffer, msgpack_sbuffer_write); \ msgpack_pack_int64(&pac, (handle_T)o); \ - msgpack_pack_ext(res, sbuffer.size, kObjectType##t); \ + msgpack_pack_ext(res, sbuffer.size, \ + kObjectType##t - EXT_OBJECT_TYPE_SHIFT); \ msgpack_pack_ext_body(res, sbuffer.data, sbuffer.size); \ msgpack_sbuffer_clear(&sbuffer); \ } @@ -73,7 +77,7 @@ typedef struct { size_t idx; } MPToAPIObjectStackItem; -/// Convert type used by msgpack parser to Neovim own API type +/// Convert type used by msgpack parser to Nvim API type. /// /// @param[in] obj Msgpack value to convert. /// @param[out] arg Location where result of conversion will be saved. @@ -84,7 +88,12 @@ bool msgpack_rpc_to_object(const msgpack_object *const obj, Object *const arg) { bool ret = true; kvec_t(MPToAPIObjectStackItem) stack = KV_INITIAL_VALUE; - kv_push(stack, ((MPToAPIObjectStackItem) { obj, arg, false, 0 })); + kv_push(stack, ((MPToAPIObjectStackItem) { + .mobj = obj, + .aobj = arg, + .container = false, + .idx = 0, + })); while (ret && kv_size(stack)) { MPToAPIObjectStackItem cur = kv_last(stack); if (!cur.container) { @@ -114,10 +123,16 @@ bool msgpack_rpc_to_object(const msgpack_object *const obj, Object *const arg) } break; } - case MSGPACK_OBJECT_FLOAT: { +#ifdef NVIM_MSGPACK_HAS_FLOAT32 + case MSGPACK_OBJECT_FLOAT32: + case MSGPACK_OBJECT_FLOAT64: +#else + case MSGPACK_OBJECT_FLOAT: +#endif + { STATIC_ASSERT(sizeof(Float) == sizeof(cur.mobj->via.f64), "Msgpack floating-point size does not match API integer"); - *cur.aobj = FLOATING_OBJ(cur.mobj->via.f64); + *cur.aobj = FLOAT_OBJ(cur.mobj->via.f64); break; } #define STR_CASE(type, attr, obj, dest, conv) \ @@ -181,7 +196,12 @@ bool msgpack_rpc_to_object(const msgpack_object *const obj, Object *const arg) case MSGPACK_OBJECT_BOOLEAN: case MSGPACK_OBJECT_POSITIVE_INTEGER: case MSGPACK_OBJECT_NEGATIVE_INTEGER: +#ifdef NVIM_MSGPACK_HAS_FLOAT32 + case MSGPACK_OBJECT_FLOAT32: + case MSGPACK_OBJECT_FLOAT64: +#else case MSGPACK_OBJECT_FLOAT: +#endif case MSGPACK_OBJECT_EXT: case MSGPACK_OBJECT_MAP: case MSGPACK_OBJECT_ARRAY: { @@ -211,7 +231,7 @@ bool msgpack_rpc_to_object(const msgpack_object *const obj, Object *const arg) break; } case MSGPACK_OBJECT_EXT: { - switch (cur.mobj->via.ext.type) { + switch ((ObjectType)(cur.mobj->via.ext.type + EXT_OBJECT_TYPE_SHIFT)) { case kObjectTypeBuffer: { cur.aobj->type = kObjectTypeBuffer; ret = msgpack_rpc_to_buffer(cur.mobj, &cur.aobj->data.integer); @@ -227,6 +247,15 @@ bool msgpack_rpc_to_object(const msgpack_object *const obj, Object *const arg) ret = msgpack_rpc_to_tabpage(cur.mobj, &cur.aobj->data.integer); break; } + case kObjectTypeNil: + case kObjectTypeBoolean: + case kObjectTypeInteger: + case kObjectTypeFloat: + case kObjectTypeString: + case kObjectTypeArray: + case kObjectTypeDictionary: { + break; + } } break; } @@ -322,7 +351,7 @@ void msgpack_rpc_from_float(Float result, msgpack_packer *res) msgpack_pack_double(res, result); } -void msgpack_rpc_from_string(String result, msgpack_packer *res) +void msgpack_rpc_from_string(const String result, msgpack_packer *res) FUNC_ATTR_NONNULL_ARG(2) { msgpack_pack_str(res, result.size); @@ -337,7 +366,7 @@ typedef struct { size_t idx; } APIToMPObjectStackItem; -/// Convert type used by Neovim API to msgpack +/// Convert type used by Nvim API to msgpack type. /// /// @param[in] result Object to convert. /// @param[out] res Structure that defines where conversion results are saved. @@ -350,6 +379,9 @@ void msgpack_rpc_from_object(const Object result, msgpack_packer *const res) kv_push(stack, ((APIToMPObjectStackItem) { &result, false, 0 })); while (kv_size(stack)) { APIToMPObjectStackItem cur = kv_last(stack); + STATIC_ASSERT(kObjectTypeWindow == kObjectTypeBuffer + 1 + && kObjectTypeTabpage == kObjectTypeWindow + 1, + "Buffer, window and tabpage enum items are in order"); switch (cur.aobj->type) { case kObjectTypeNil: { msgpack_pack_nil(res); @@ -461,8 +493,7 @@ Object msgpack_rpc_handle_missing_method(uint64_t channel_id, Array args, Error *error) { - snprintf(error->msg, sizeof(error->msg), "Invalid method name"); - error->set = true; + api_set_error(error, kErrorTypeException, "Invalid method name"); return NIL; } @@ -471,14 +502,13 @@ Object msgpack_rpc_handle_invalid_arguments(uint64_t channel_id, Array args, Error *error) { - snprintf(error->msg, sizeof(error->msg), "Invalid method arguments"); - error->set = true; + api_set_error(error, kErrorTypeException, "Invalid method arguments"); return NIL; } /// Serializes a msgpack-rpc request or notification(id == 0) void msgpack_rpc_serialize_request(uint64_t request_id, - String method, + const String method, Array args, msgpack_packer *pac) FUNC_ATTR_NONNULL_ARG(4) @@ -505,7 +535,7 @@ void msgpack_rpc_serialize_response(uint64_t response_id, msgpack_pack_int(pac, 1); msgpack_pack_uint64(pac, response_id); - if (err->set) { + if (ERROR_SET(err)) { // error represented by a [type, message] array msgpack_pack_array(pac, 2); msgpack_rpc_from_integer(err->type, pac); @@ -558,49 +588,49 @@ void msgpack_rpc_validate(uint64_t *response_id, *response_id = NO_RESPONSE; // Validate the basic structure of the msgpack-rpc payload if (req->type != MSGPACK_OBJECT_ARRAY) { - api_set_error(err, Validation, _("Message is not an array")); + api_set_error(err, kErrorTypeValidation, "Message is not an array"); return; } if (req->via.array.size == 0) { - api_set_error(err, Validation, _("Message is empty")); + api_set_error(err, kErrorTypeValidation, "Message is empty"); return; } if (req->via.array.ptr[0].type != MSGPACK_OBJECT_POSITIVE_INTEGER) { - api_set_error(err, Validation, _("Message type must be an integer")); + api_set_error(err, kErrorTypeValidation, "Message type must be an integer"); return; } uint64_t type = req->via.array.ptr[0].via.u64; if (type != kMessageTypeRequest && type != kMessageTypeNotification) { - api_set_error(err, Validation, _("Unknown message type")); + api_set_error(err, kErrorTypeValidation, "Unknown message type"); return; } if ((type == kMessageTypeRequest && req->via.array.size != 4) || (type == kMessageTypeNotification && req->via.array.size != 3)) { - api_set_error(err, Validation, _("Request array size should be 4 (request) " - "or 3 (notification)")); + api_set_error(err, kErrorTypeValidation, + "Request array size must be 4 (request) or 3 (notification)"); return; } if (type == kMessageTypeRequest) { msgpack_object *id_obj = msgpack_rpc_msg_id(req); if (!id_obj) { - api_set_error(err, Validation, _("ID must be a positive integer")); + api_set_error(err, kErrorTypeValidation, "ID must be a positive integer"); return; } *response_id = id_obj->via.u64; } if (!msgpack_rpc_method(req)) { - api_set_error(err, Validation, _("Method must be a string")); + api_set_error(err, kErrorTypeValidation, "Method must be a string"); return; } if (!msgpack_rpc_args(req)) { - api_set_error(err, Validation, _("Parameters must be an array")); + api_set_error(err, kErrorTypeValidation, "Parameters must be an array"); return; } } diff --git a/src/nvim/msgpack_rpc/helpers.h b/src/nvim/msgpack_rpc/helpers.h index 7d9f114140..0e4cd1be6d 100644 --- a/src/nvim/msgpack_rpc/helpers.h +++ b/src/nvim/msgpack_rpc/helpers.h @@ -9,6 +9,13 @@ #include "nvim/event/wstream.h" #include "nvim/api/private/defs.h" +/// Value by which objects represented as EXT type are shifted +/// +/// Subtracted when packing, added when unpacking. Used to allow moving +/// buffer/window/tabpage block inside ObjectType enum. This block yet cannot be +/// split or reordered. +#define EXT_OBJECT_TYPE_SHIFT kObjectTypeBuffer + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "msgpack_rpc/helpers.h.generated.h" #endif diff --git a/src/nvim/msgpack_rpc/server.c b/src/nvim/msgpack_rpc/server.c index d7c2926a0f..1e0cc27886 100644 --- a/src/nvim/msgpack_rpc/server.c +++ b/src/nvim/msgpack_rpc/server.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #include <assert.h> #include <stdlib.h> #include <string.h> @@ -94,39 +97,61 @@ char *server_address_new(void) #endif } -/// Starts listening for API calls on the TCP address or pipe path `endpoint`. +/// Check if this instance owns a pipe address. +/// The argument must already be resolved to an absolute path! +bool server_owns_pipe_address(const char *path) +{ + for (int i = 0; i < watchers.ga_len; i++) { + if (!strcmp(path, ((SocketWatcher **)watchers.ga_data)[i]->addr)) { + return true; + } + } + return false; +} + +/// Starts listening for API calls. +/// /// The socket type is determined by parsing `endpoint`: If it's a valid IPv4 -/// address in 'ip[:port]' format, then it will be TCP socket. The port is -/// optional and if omitted defaults to NVIM_DEFAULT_TCP_PORT. Otherwise it -/// will be a unix socket or named pipe. +/// or IPv6 address in 'ip:[port]' format, then it will be a TCP socket. +/// Otherwise it will be a Unix socket or named pipe (Windows). +/// +/// If no port is given, a random one will be assigned. /// -/// @param endpoint Address of the server. Either a 'ip[:port]' string or an -/// arbitrary identifier (trimmed to 256 bytes) for the unix socket or -/// named pipe. +/// @param endpoint Address of the server. Either a 'ip:[port]' string or an +/// arbitrary identifier (trimmed to 256 bytes) for the Unix +/// socket or named pipe. /// @returns 0 on success, 1 on a regular error, and negative errno -/// on failure to bind or connect. +/// on failure to bind or listen. int server_start(const char *endpoint) { - if (endpoint == NULL) { - ELOG("Attempting to start server on NULL endpoint"); + if (endpoint == NULL || endpoint[0] == '\0') { + WLOG("Empty or NULL endpoint"); return 1; } SocketWatcher *watcher = xmalloc(sizeof(SocketWatcher)); - socket_watcher_init(&main_loop, watcher, endpoint, NULL); + + int result = socket_watcher_init(&main_loop, watcher, endpoint); + if (result < 0) { + xfree(watcher); + return result; + } // Check if a watcher for the endpoint already exists for (int i = 0; i < watchers.ga_len; i++) { if (!strcmp(watcher->addr, ((SocketWatcher **)watchers.ga_data)[i]->addr)) { ELOG("Already listening on %s", watcher->addr); + if (watcher->stream->type == UV_TCP) { + uv_freeaddrinfo(watcher->uv.tcp.addrinfo); + } socket_watcher_close(watcher, free_server); return 1; } } - int result = socket_watcher_start(watcher, MAX_CONNECTIONS, connection_cb); + result = socket_watcher_start(watcher, MAX_CONNECTIONS, connection_cb); if (result < 0) { - ELOG("Failed to start server: %s", uv_strerror(result)); + WLOG("Failed to start server: %s", uv_strerror(result)); socket_watcher_close(watcher, free_server); return result; } diff --git a/src/nvim/msgpack_rpc/server.h b/src/nvim/msgpack_rpc/server.h index f1a6703938..5446e40e0b 100644 --- a/src/nvim/msgpack_rpc/server.h +++ b/src/nvim/msgpack_rpc/server.h @@ -1,6 +1,8 @@ #ifndef NVIM_MSGPACK_RPC_SERVER_H #define NVIM_MSGPACK_RPC_SERVER_H +#include <stdio.h> + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "msgpack_rpc/server.h.generated.h" #endif diff --git a/src/nvim/normal.c b/src/nvim/normal.c index 227bfbe779..f9017164af 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + /* * normal.c: Contains the main routine for processing characters in command * mode. Communicates closely with the code in ops.c to handle @@ -10,6 +13,7 @@ #include <stdbool.h> #include <stdlib.h> +#include "nvim/log.h" #include "nvim/vim.h" #include "nvim/ascii.h" #include "nvim/normal.h" @@ -45,6 +49,7 @@ #include "nvim/screen.h" #include "nvim/search.h" #include "nvim/spell.h" +#include "nvim/spellfile.h" #include "nvim/strings.h" #include "nvim/syntax.h" #include "nvim/tag.h" @@ -152,196 +157,196 @@ static const struct nv_cmd { short cmd_arg; /* value for ca.arg */ } nv_cmds[] = { - {NUL, nv_error, 0, 0}, - {Ctrl_A, nv_addsub, 0, 0}, - {Ctrl_B, nv_page, NV_STS, BACKWARD}, - {Ctrl_C, nv_esc, 0, true}, - {Ctrl_D, nv_halfpage, 0, 0}, - {Ctrl_E, nv_scroll_line, 0, true}, - {Ctrl_F, nv_page, NV_STS, FORWARD}, - {Ctrl_G, nv_ctrlg, 0, 0}, - {Ctrl_H, nv_ctrlh, 0, 0}, - {Ctrl_I, nv_pcmark, 0, 0}, - {NL, nv_down, 0, false}, - {Ctrl_K, nv_error, 0, 0}, - {Ctrl_L, nv_clear, 0, 0}, - {Ctrl_M, nv_down, 0, true}, - {Ctrl_N, nv_down, NV_STS, false}, - {Ctrl_O, nv_ctrlo, 0, 0}, - {Ctrl_P, nv_up, NV_STS, false}, - {Ctrl_Q, nv_visual, 0, false}, - {Ctrl_R, nv_redo, 0, 0}, - {Ctrl_S, nv_ignore, 0, 0}, - {Ctrl_T, nv_tagpop, NV_NCW, 0}, - {Ctrl_U, nv_halfpage, 0, 0}, - {Ctrl_V, nv_visual, 0, false}, - {'V', nv_visual, 0, false}, - {'v', nv_visual, 0, false}, - {Ctrl_W, nv_window, 0, 0}, - {Ctrl_X, nv_addsub, 0, 0}, - {Ctrl_Y, nv_scroll_line, 0, false}, - {Ctrl_Z, nv_suspend, 0, 0}, - {ESC, nv_esc, 0, false}, - {Ctrl_BSL, nv_normal, NV_NCH_ALW, 0}, - {Ctrl_RSB, nv_ident, NV_NCW, 0}, - {Ctrl_HAT, nv_hat, NV_NCW, 0}, - {Ctrl__, nv_error, 0, 0}, - {' ', nv_right, 0, 0}, - {'!', nv_operator, 0, 0}, - {'"', nv_regname, NV_NCH_NOP|NV_KEEPREG, 0}, - {'#', nv_ident, 0, 0}, - {'$', nv_dollar, 0, 0}, - {'%', nv_percent, 0, 0}, - {'&', nv_optrans, 0, 0}, - {'\'', nv_gomark, NV_NCH_ALW, true}, - {'(', nv_brace, 0, BACKWARD}, - {')', nv_brace, 0, FORWARD}, - {'*', nv_ident, 0, 0}, - {'+', nv_down, 0, true}, - {',', nv_csearch, 0, true}, - {'-', nv_up, 0, true}, - {'.', nv_dot, NV_KEEPREG, 0}, - {'/', nv_search, 0, false}, - {'0', nv_beginline, 0, 0}, - {'1', nv_ignore, 0, 0}, - {'2', nv_ignore, 0, 0}, - {'3', nv_ignore, 0, 0}, - {'4', nv_ignore, 0, 0}, - {'5', nv_ignore, 0, 0}, - {'6', nv_ignore, 0, 0}, - {'7', nv_ignore, 0, 0}, - {'8', nv_ignore, 0, 0}, - {'9', nv_ignore, 0, 0}, - {':', nv_colon, 0, 0}, - {';', nv_csearch, 0, false}, - {'<', nv_operator, NV_RL, 0}, - {'=', nv_operator, 0, 0}, - {'>', nv_operator, NV_RL, 0}, - {'?', nv_search, 0, false}, - {'@', nv_at, NV_NCH_NOP, false}, - {'A', nv_edit, 0, 0}, - {'B', nv_bck_word, 0, 1}, - {'C', nv_abbrev, NV_KEEPREG, 0}, - {'D', nv_abbrev, NV_KEEPREG, 0}, - {'E', nv_wordcmd, 0, true}, - {'F', nv_csearch, NV_NCH_ALW|NV_LANG, BACKWARD}, - {'G', nv_goto, 0, true}, - {'H', nv_scroll, 0, 0}, - {'I', nv_edit, 0, 0}, - {'J', nv_join, 0, 0}, - {'K', nv_ident, 0, 0}, - {'L', nv_scroll, 0, 0}, - {'M', nv_scroll, 0, 0}, - {'N', nv_next, 0, SEARCH_REV}, - {'O', nv_open, 0, 0}, - {'P', nv_put, 0, 0}, - {'Q', nv_exmode, NV_NCW, 0}, - {'R', nv_Replace, 0, false}, - {'S', nv_subst, NV_KEEPREG, 0}, - {'T', nv_csearch, NV_NCH_ALW|NV_LANG, BACKWARD}, - {'U', nv_Undo, 0, 0}, - {'W', nv_wordcmd, 0, true}, - {'X', nv_abbrev, NV_KEEPREG, 0}, - {'Y', nv_abbrev, NV_KEEPREG, 0}, - {'Z', nv_Zet, NV_NCH_NOP|NV_NCW, 0}, - {'[', nv_brackets, NV_NCH_ALW, BACKWARD}, - {'\\', nv_error, 0, 0}, - {']', nv_brackets, NV_NCH_ALW, FORWARD}, - {'^', nv_beginline, 0, BL_WHITE | BL_FIX}, - {'_', nv_lineop, 0, 0}, - {'`', nv_gomark, NV_NCH_ALW, false}, - {'a', nv_edit, NV_NCH, 0}, - {'b', nv_bck_word, 0, 0}, - {'c', nv_operator, 0, 0}, - {'d', nv_operator, 0, 0}, - {'e', nv_wordcmd, 0, false}, - {'f', nv_csearch, NV_NCH_ALW|NV_LANG, FORWARD}, - {'g', nv_g_cmd, NV_NCH_ALW, false}, - {'h', nv_left, NV_RL, 0}, - {'i', nv_edit, NV_NCH, 0}, - {'j', nv_down, 0, false}, - {'k', nv_up, 0, false}, - {'l', nv_right, NV_RL, 0}, - {'m', nv_mark, NV_NCH_NOP, 0}, - {'n', nv_next, 0, 0}, - {'o', nv_open, 0, 0}, - {'p', nv_put, 0, 0}, - {'q', nv_record, NV_NCH, 0}, - {'r', nv_replace, NV_NCH_NOP|NV_LANG, 0}, - {'s', nv_subst, NV_KEEPREG, 0}, - {'t', nv_csearch, NV_NCH_ALW|NV_LANG, FORWARD}, - {'u', nv_undo, 0, 0}, - {'w', nv_wordcmd, 0, false}, - {'x', nv_abbrev, NV_KEEPREG, 0}, - {'y', nv_operator, 0, 0}, - {'z', nv_zet, NV_NCH_ALW, 0}, - {'{', nv_findpar, 0, BACKWARD}, - {'|', nv_pipe, 0, 0}, - {'}', nv_findpar, 0, FORWARD}, - {'~', nv_tilde, 0, 0}, - - /* pound sign */ - {POUND, nv_ident, 0, 0}, - {K_MOUSEUP, nv_mousescroll, 0, MSCR_UP}, - {K_MOUSEDOWN, nv_mousescroll, 0, MSCR_DOWN}, - {K_MOUSELEFT, nv_mousescroll, 0, MSCR_LEFT}, - {K_MOUSERIGHT, nv_mousescroll, 0, MSCR_RIGHT}, - {K_LEFTMOUSE, nv_mouse, 0, 0}, - {K_LEFTMOUSE_NM, nv_mouse, 0, 0}, - {K_LEFTDRAG, nv_mouse, 0, 0}, - {K_LEFTRELEASE, nv_mouse, 0, 0}, - {K_LEFTRELEASE_NM, nv_mouse, 0, 0}, - {K_MIDDLEMOUSE, nv_mouse, 0, 0}, - {K_MIDDLEDRAG, nv_mouse, 0, 0}, - {K_MIDDLERELEASE, nv_mouse, 0, 0}, - {K_RIGHTMOUSE, nv_mouse, 0, 0}, - {K_RIGHTDRAG, nv_mouse, 0, 0}, - {K_RIGHTRELEASE, nv_mouse, 0, 0}, - {K_X1MOUSE, nv_mouse, 0, 0}, - {K_X1DRAG, nv_mouse, 0, 0}, - {K_X1RELEASE, nv_mouse, 0, 0}, - {K_X2MOUSE, nv_mouse, 0, 0}, - {K_X2DRAG, nv_mouse, 0, 0}, - {K_X2RELEASE, nv_mouse, 0, 0}, - {K_IGNORE, nv_ignore, NV_KEEPREG, 0}, - {K_NOP, nv_nop, 0, 0}, - {K_INS, nv_edit, 0, 0}, - {K_KINS, nv_edit, 0, 0}, - {K_BS, nv_ctrlh, 0, 0}, - {K_UP, nv_up, NV_SSS|NV_STS, false}, - {K_S_UP, nv_page, NV_SS, BACKWARD}, - {K_DOWN, nv_down, NV_SSS|NV_STS, false}, - {K_S_DOWN, nv_page, NV_SS, FORWARD}, - {K_LEFT, nv_left, NV_SSS|NV_STS|NV_RL, 0}, - {K_S_LEFT, nv_bck_word, NV_SS|NV_RL, 0}, - {K_C_LEFT, nv_bck_word, NV_SSS|NV_RL|NV_STS, 1}, - {K_RIGHT, nv_right, NV_SSS|NV_STS|NV_RL, 0}, - {K_S_RIGHT, nv_wordcmd, NV_SS|NV_RL, false}, - {K_C_RIGHT, nv_wordcmd, NV_SSS|NV_RL|NV_STS, true}, - {K_PAGEUP, nv_page, NV_SSS|NV_STS, BACKWARD}, - {K_KPAGEUP, nv_page, NV_SSS|NV_STS, BACKWARD}, - {K_PAGEDOWN, nv_page, NV_SSS|NV_STS, FORWARD}, - {K_KPAGEDOWN, nv_page, NV_SSS|NV_STS, FORWARD}, - {K_END, nv_end, NV_SSS|NV_STS, false}, - {K_KEND, nv_end, NV_SSS|NV_STS, false}, - {K_S_END, nv_end, NV_SS, false}, - {K_C_END, nv_end, NV_SSS|NV_STS, true}, - {K_HOME, nv_home, NV_SSS|NV_STS, 0}, - {K_KHOME, nv_home, NV_SSS|NV_STS, 0}, - {K_S_HOME, nv_home, NV_SS, 0}, - {K_C_HOME, nv_goto, NV_SSS|NV_STS, false}, - {K_DEL, nv_abbrev, 0, 0}, - {K_KDEL, nv_abbrev, 0, 0}, - {K_UNDO, nv_kundo, 0, 0}, - {K_HELP, nv_help, NV_NCW, 0}, - {K_F1, nv_help, NV_NCW, 0}, - {K_XF1, nv_help, NV_NCW, 0}, - {K_SELECT, nv_select, 0, 0}, - {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}, + { NUL, nv_error, 0, 0 }, + { Ctrl_A, nv_addsub, 0, 0 }, + { Ctrl_B, nv_page, NV_STS, BACKWARD }, + { Ctrl_C, nv_esc, 0, true }, + { Ctrl_D, nv_halfpage, 0, 0 }, + { Ctrl_E, nv_scroll_line, 0, true }, + { Ctrl_F, nv_page, NV_STS, FORWARD }, + { Ctrl_G, nv_ctrlg, 0, 0 }, + { Ctrl_H, nv_ctrlh, 0, 0 }, + { Ctrl_I, nv_pcmark, 0, 0 }, + { NL, nv_down, 0, false }, + { Ctrl_K, nv_error, 0, 0 }, + { Ctrl_L, nv_clear, 0, 0 }, + { Ctrl_M, nv_down, 0, true }, + { Ctrl_N, nv_down, NV_STS, false }, + { Ctrl_O, nv_ctrlo, 0, 0 }, + { Ctrl_P, nv_up, NV_STS, false }, + { Ctrl_Q, nv_visual, 0, false }, + { Ctrl_R, nv_redo, 0, 0 }, + { Ctrl_S, nv_ignore, 0, 0 }, + { Ctrl_T, nv_tagpop, NV_NCW, 0 }, + { Ctrl_U, nv_halfpage, 0, 0 }, + { Ctrl_V, nv_visual, 0, false }, + { 'V', nv_visual, 0, false }, + { 'v', nv_visual, 0, false }, + { Ctrl_W, nv_window, 0, 0 }, + { Ctrl_X, nv_addsub, 0, 0 }, + { Ctrl_Y, nv_scroll_line, 0, false }, + { Ctrl_Z, nv_suspend, 0, 0 }, + { ESC, nv_esc, 0, false }, + { Ctrl_BSL, nv_normal, NV_NCH_ALW, 0 }, + { Ctrl_RSB, nv_ident, NV_NCW, 0 }, + { Ctrl_HAT, nv_hat, NV_NCW, 0 }, + { Ctrl__, nv_error, 0, 0 }, + { ' ', nv_right, 0, 0 }, + { '!', nv_operator, 0, 0 }, + { '"', nv_regname, NV_NCH_NOP|NV_KEEPREG, 0 }, + { '#', nv_ident, 0, 0 }, + { '$', nv_dollar, 0, 0 }, + { '%', nv_percent, 0, 0 }, + { '&', nv_optrans, 0, 0 }, + { '\'', nv_gomark, NV_NCH_ALW, true }, + { '(', nv_brace, 0, BACKWARD }, + { ')', nv_brace, 0, FORWARD }, + { '*', nv_ident, 0, 0 }, + { '+', nv_down, 0, true }, + { ',', nv_csearch, 0, true }, + { '-', nv_up, 0, true }, + { '.', nv_dot, NV_KEEPREG, 0 }, + { '/', nv_search, 0, false }, + { '0', nv_beginline, 0, 0 }, + { '1', nv_ignore, 0, 0 }, + { '2', nv_ignore, 0, 0 }, + { '3', nv_ignore, 0, 0 }, + { '4', nv_ignore, 0, 0 }, + { '5', nv_ignore, 0, 0 }, + { '6', nv_ignore, 0, 0 }, + { '7', nv_ignore, 0, 0 }, + { '8', nv_ignore, 0, 0 }, + { '9', nv_ignore, 0, 0 }, + { ':', nv_colon, 0, 0 }, + { ';', nv_csearch, 0, false }, + { '<', nv_operator, NV_RL, 0 }, + { '=', nv_operator, 0, 0 }, + { '>', nv_operator, NV_RL, 0 }, + { '?', nv_search, 0, false }, + { '@', nv_at, NV_NCH_NOP, false }, + { 'A', nv_edit, 0, 0 }, + { 'B', nv_bck_word, 0, 1 }, + { 'C', nv_abbrev, NV_KEEPREG, 0 }, + { 'D', nv_abbrev, NV_KEEPREG, 0 }, + { 'E', nv_wordcmd, 0, true }, + { 'F', nv_csearch, NV_NCH_ALW|NV_LANG, BACKWARD }, + { 'G', nv_goto, 0, true }, + { 'H', nv_scroll, 0, 0 }, + { 'I', nv_edit, 0, 0 }, + { 'J', nv_join, 0, 0 }, + { 'K', nv_ident, 0, 0 }, + { 'L', nv_scroll, 0, 0 }, + { 'M', nv_scroll, 0, 0 }, + { 'N', nv_next, 0, SEARCH_REV }, + { 'O', nv_open, 0, 0 }, + { 'P', nv_put, 0, 0 }, + { 'Q', nv_exmode, NV_NCW, 0 }, + { 'R', nv_Replace, 0, false }, + { 'S', nv_subst, NV_KEEPREG, 0 }, + { 'T', nv_csearch, NV_NCH_ALW|NV_LANG, BACKWARD }, + { 'U', nv_Undo, 0, 0 }, + { 'W', nv_wordcmd, 0, true }, + { 'X', nv_abbrev, NV_KEEPREG, 0 }, + { 'Y', nv_abbrev, NV_KEEPREG, 0 }, + { 'Z', nv_Zet, NV_NCH_NOP|NV_NCW, 0 }, + { '[', nv_brackets, NV_NCH_ALW, BACKWARD }, + { '\\', nv_error, 0, 0 }, + { ']', nv_brackets, NV_NCH_ALW, FORWARD }, + { '^', nv_beginline, 0, BL_WHITE | BL_FIX }, + { '_', nv_lineop, 0, 0 }, + { '`', nv_gomark, NV_NCH_ALW, false }, + { 'a', nv_edit, NV_NCH, 0 }, + { 'b', nv_bck_word, 0, 0 }, + { 'c', nv_operator, 0, 0 }, + { 'd', nv_operator, 0, 0 }, + { 'e', nv_wordcmd, 0, false }, + { 'f', nv_csearch, NV_NCH_ALW|NV_LANG, FORWARD }, + { 'g', nv_g_cmd, NV_NCH_ALW, false }, + { 'h', nv_left, NV_RL, 0 }, + { 'i', nv_edit, NV_NCH, 0 }, + { 'j', nv_down, 0, false }, + { 'k', nv_up, 0, false }, + { 'l', nv_right, NV_RL, 0 }, + { 'm', nv_mark, NV_NCH_NOP, 0 }, + { 'n', nv_next, 0, 0 }, + { 'o', nv_open, 0, 0 }, + { 'p', nv_put, 0, 0 }, + { 'q', nv_record, NV_NCH, 0 }, + { 'r', nv_replace, NV_NCH_NOP|NV_LANG, 0 }, + { 's', nv_subst, NV_KEEPREG, 0 }, + { 't', nv_csearch, NV_NCH_ALW|NV_LANG, FORWARD }, + { 'u', nv_undo, 0, 0 }, + { 'w', nv_wordcmd, 0, false }, + { 'x', nv_abbrev, NV_KEEPREG, 0 }, + { 'y', nv_operator, 0, 0 }, + { 'z', nv_zet, NV_NCH_ALW, 0 }, + { '{', nv_findpar, 0, BACKWARD }, + { '|', nv_pipe, 0, 0 }, + { '}', nv_findpar, 0, FORWARD }, + { '~', nv_tilde, 0, 0 }, + + // pound sign + { POUND, nv_ident, 0, 0 }, + { K_MOUSEUP, nv_mousescroll, 0, MSCR_UP }, + { K_MOUSEDOWN, nv_mousescroll, 0, MSCR_DOWN }, + { K_MOUSELEFT, nv_mousescroll, 0, MSCR_LEFT }, + { K_MOUSERIGHT, nv_mousescroll, 0, MSCR_RIGHT }, + { K_LEFTMOUSE, nv_mouse, 0, 0 }, + { K_LEFTMOUSE_NM, nv_mouse, 0, 0 }, + { K_LEFTDRAG, nv_mouse, 0, 0 }, + { K_LEFTRELEASE, nv_mouse, 0, 0 }, + { K_LEFTRELEASE_NM, nv_mouse, 0, 0 }, + { K_MIDDLEMOUSE, nv_mouse, 0, 0 }, + { K_MIDDLEDRAG, nv_mouse, 0, 0 }, + { K_MIDDLERELEASE, nv_mouse, 0, 0 }, + { K_RIGHTMOUSE, nv_mouse, 0, 0 }, + { K_RIGHTDRAG, nv_mouse, 0, 0 }, + { K_RIGHTRELEASE, nv_mouse, 0, 0 }, + { K_X1MOUSE, nv_mouse, 0, 0 }, + { K_X1DRAG, nv_mouse, 0, 0 }, + { K_X1RELEASE, nv_mouse, 0, 0 }, + { K_X2MOUSE, nv_mouse, 0, 0 }, + { K_X2DRAG, nv_mouse, 0, 0 }, + { K_X2RELEASE, nv_mouse, 0, 0 }, + { K_IGNORE, nv_ignore, NV_KEEPREG, 0 }, + { K_NOP, nv_nop, 0, 0 }, + { K_INS, nv_edit, 0, 0 }, + { K_KINS, nv_edit, 0, 0 }, + { K_BS, nv_ctrlh, 0, 0 }, + { K_UP, nv_up, NV_SSS|NV_STS, false }, + { K_S_UP, nv_page, NV_SS, BACKWARD }, + { K_DOWN, nv_down, NV_SSS|NV_STS, false }, + { K_S_DOWN, nv_page, NV_SS, FORWARD }, + { K_LEFT, nv_left, NV_SSS|NV_STS|NV_RL, 0 }, + { K_S_LEFT, nv_bck_word, NV_SS|NV_RL, 0 }, + { K_C_LEFT, nv_bck_word, NV_SSS|NV_RL|NV_STS, 1 }, + { K_RIGHT, nv_right, NV_SSS|NV_STS|NV_RL, 0 }, + { K_S_RIGHT, nv_wordcmd, NV_SS|NV_RL, false }, + { K_C_RIGHT, nv_wordcmd, NV_SSS|NV_RL|NV_STS, true }, + { K_PAGEUP, nv_page, NV_SSS|NV_STS, BACKWARD }, + { K_KPAGEUP, nv_page, NV_SSS|NV_STS, BACKWARD }, + { K_PAGEDOWN, nv_page, NV_SSS|NV_STS, FORWARD }, + { K_KPAGEDOWN, nv_page, NV_SSS|NV_STS, FORWARD }, + { K_END, nv_end, NV_SSS|NV_STS, false }, + { K_KEND, nv_end, NV_SSS|NV_STS, false }, + { K_S_END, nv_end, NV_SS, false }, + { K_C_END, nv_end, NV_SSS|NV_STS, true }, + { K_HOME, nv_home, NV_SSS|NV_STS, 0 }, + { K_KHOME, nv_home, NV_SSS|NV_STS, 0 }, + { K_S_HOME, nv_home, NV_SS, 0 }, + { K_C_HOME, nv_goto, NV_SSS|NV_STS, false }, + { K_DEL, nv_abbrev, 0, 0 }, + { K_KDEL, nv_abbrev, 0, 0 }, + { K_UNDO, nv_kundo, 0, 0 }, + { K_HELP, nv_help, NV_NCW, 0 }, + { K_F1, nv_help, NV_NCW, 0 }, + { K_XF1, nv_help, NV_NCW, 0 }, + { K_SELECT, nv_select, 0, 0 }, + { K_F8, farsi_f8, 0, 0 }, + { K_F9, farsi_f9, 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[]. */ @@ -537,7 +542,7 @@ static bool normal_handle_special_visual_command(NormalState *s) return false; } -static bool normal_need_aditional_char(NormalState *s) +static bool normal_need_additional_char(NormalState *s) { int flags = nv_cmds[s->idx].cmd_flags; bool pending_op = s->oa.op_type != OP_NOP; @@ -617,7 +622,7 @@ static void normal_redraw_mode_message(NormalState *s) update_screen(0); // now reset it, otherwise it's put in the history again keep_msg = kmsg; - msg_attr(kmsg, keep_msg_attr); + msg_attr((const char *)kmsg, keep_msg_attr); xfree(kmsg); } setcursor(); @@ -641,8 +646,7 @@ static void normal_get_additional_char(NormalState *s) bool langmap_active = false; // using :lmap mappings int lang; // getting a text character - ++no_mapping; - ++allow_keys; // no mapping for nchar, but allow key codes + no_mapping++; // Don't generate a CursorHold event here, most commands can't handle // it, e.g., nv_replace(), nv_csearch(). did_cursorhold = true; @@ -680,8 +684,7 @@ static void normal_get_additional_char(NormalState *s) } if (lang && curbuf->b_p_iminsert == B_IMODE_LMAP) { // Allow mappings defined with ":lmap". - --no_mapping; - --allow_keys; + no_mapping--; if (repl) { State = LREPLACE; } else { @@ -694,9 +697,7 @@ static void normal_get_additional_char(NormalState *s) if (langmap_active) { // Undo the decrement done above - ++no_mapping; - ++allow_keys; - State = NORMAL_BUSY; + no_mapping++; } State = NORMAL_BUSY; s->need_flushbuf |= add_to_showcmd(*cp); @@ -780,8 +781,7 @@ static void normal_get_additional_char(NormalState *s) } no_mapping++; } - --no_mapping; - --allow_keys; + no_mapping--; } static void normal_invert_horizontal(NormalState *s) @@ -831,8 +831,7 @@ static bool normal_get_command_count(NormalState *s) } if (s->ctrl_w) { - ++no_mapping; - ++allow_keys; // no mapping for nchar, but keys + no_mapping++; } ++no_zero_mapping; // don't map zero here @@ -840,8 +839,7 @@ static bool normal_get_command_count(NormalState *s) LANGMAP_ADJUST(s->c, true); --no_zero_mapping; if (s->ctrl_w) { - --no_mapping; - --allow_keys; + no_mapping--; } s->need_flushbuf |= add_to_showcmd(s->c); } @@ -851,12 +849,10 @@ static bool normal_get_command_count(NormalState *s) s->ctrl_w = true; s->ca.opcount = s->ca.count0; // remember first count s->ca.count0 = 0; - ++no_mapping; - ++allow_keys; // no mapping for nchar, but keys + no_mapping++; s->c = plain_vgetc(); // get next character LANGMAP_ADJUST(s->c, true); - --no_mapping; - --allow_keys; + no_mapping--; s->need_flushbuf |= add_to_showcmd(s->c); return true; } @@ -924,9 +920,7 @@ normal_end: checkpcmark(); // check if we moved since setting pcmark xfree(s->ca.searchbuf); - if (has_mbyte) { - mb_adjust_cursor(); - } + mb_check_adjust_col(curwin); // #6203 if (curwin->w_p_scb && s->toplevel) { validate_cursor(); // may need to update w_leftcol @@ -1090,7 +1084,7 @@ static int normal_execute(VimState *state, int key) } // Get an additional character if we need one. - if (normal_need_aditional_char(s)) { + if (normal_need_additional_char(s)) { normal_get_additional_char(s); } @@ -1130,6 +1124,7 @@ static int normal_execute(VimState *state, int key) start_selection(); unshift_special(&s->ca); s->idx = find_command(s->ca.cmdchar); + assert(s->idx >= 0); } else if ((nv_cmds[s->idx].cmd_flags & NV_SSS) && (mod_mask & MOD_MASK_SHIFT)) { start_selection(); @@ -1163,7 +1158,7 @@ static void normal_check_stuff_buffer(NormalState *s) if (need_start_insertmode && goto_im() && !VIsual_active) { need_start_insertmode = false; - stuffReadbuff((uint8_t *)"i"); // start insert mode next + stuffReadbuff("i"); // start insert mode next // skip the fileinfo message now, because it would be shown // after insert mode finishes! need_fileinfo = false; @@ -1275,7 +1270,7 @@ static void normal_redraw(NormalState *s) // msg_attr_keep() will set keep_msg to NULL, must free the string here. // Don't reset keep_msg, msg_attr_keep() uses it to check for duplicates. char *p = (char *)keep_msg; - msg_attr((uint8_t *)p, keep_msg_attr); + msg_attr(p, keep_msg_attr); xfree(p); } @@ -1457,9 +1452,8 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank) /* Never redo "zf" (define fold). */ if ((vim_strchr(p_cpo, CPO_YANK) != NULL || oap->op_type != OP_YANK) && ((!VIsual_active || oap->motion_force) - /* Also redo Operator-pending Visual mode mappings */ - || (VIsual_active && cap->cmdchar == ':' - && oap->op_type != OP_COLON)) + // Also redo Operator-pending Visual mode mappings. + || (cap->cmdchar == ':' && oap->op_type != OP_COLON)) && cap->cmdchar != 'D' && oap->op_type != OP_FOLD && oap->op_type != OP_FOLDOPEN @@ -1477,8 +1471,9 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank) * If 'cpoptions' does not contain 'r', insert the search * pattern to really repeat the same command. */ - if (vim_strchr(p_cpo, CPO_REDO) == NULL) + if (vim_strchr(p_cpo, CPO_REDO) == NULL) { AppendToRedobuffLit(cap->searchbuf, -1); + } AppendToRedobuff(NL_STR); } else if (cap->cmdchar == ':') { /* do_cmdline() has stored the first typed line in @@ -1517,10 +1512,7 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank) coladvance(curwin->w_curswant); } cap->count0 = redo_VIsual_count; - if (redo_VIsual_count != 0) - cap->count1 = redo_VIsual_count; - else - cap->count1 = 1; + cap->count1 = (cap->count0 == 0 ? 1 : cap->count0); } else if (VIsual_active) { if (!gui_yank) { /* Save the current VIsual area for '< and '> marks, and "gv" */ @@ -1597,6 +1589,8 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank) oap->start = curwin->w_cursor; } + // Just in case lines were deleted that make the position invalid. + check_pos(curwin->w_buffer, &oap->end); oap->line_count = oap->end.lnum - oap->start.lnum + 1; /* Set "virtual_op" before resetting VIsual_active. */ @@ -1862,10 +1856,12 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank) break; case OP_FILTER: - if (vim_strchr(p_cpo, CPO_FILTER) != NULL) - AppendToRedobuff((char_u *)"!\r"); /* use any last used !cmd */ - else - bangredo = true; /* do_bang() will put cmd in redo buffer */ + if (vim_strchr(p_cpo, CPO_FILTER) != NULL) { + AppendToRedobuff("!\r"); // Use any last used !cmd. + } else { + bangredo = true; // do_bang() will put cmd in redo buffer. + } + // fallthrough case OP_INDENT: case OP_COLON: @@ -1900,12 +1896,13 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank) break; case OP_FORMAT: - if (*curbuf->b_p_fex != NUL) - op_formatexpr(oap); /* use expression */ - else if (*p_fp != NUL) - op_colon(oap); /* use external command */ - else - op_format(oap, false); /* use internal function */ + if (*curbuf->b_p_fex != NUL) { + op_formatexpr(oap); // use expression + } else if (*p_fp != NUL || *curbuf->b_p_fp != NUL) { + op_colon(oap); // use external command + } else { + op_format(oap, false); // use internal function + } break; case OP_FORMAT2: @@ -1913,7 +1910,10 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank) break; case OP_FUNCTION: - op_function(oap); /* call 'operatorfunc' */ + // Restore linebreak, so that when the user edits it looks as + // before. + curwin->w_p_lbr = lbr_saved; + op_function(oap); // call 'operatorfunc' break; case OP_INSERT: @@ -2031,40 +2031,44 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank) static void op_colon(oparg_T *oap) { stuffcharReadbuff(':'); - if (oap->is_VIsual) - stuffReadbuff((char_u *)"'<,'>"); - else { - /* - * Make the range look nice, so it can be repeated. - */ - if (oap->start.lnum == curwin->w_cursor.lnum) + if (oap->is_VIsual) { + stuffReadbuff("'<,'>"); + } else { + // Make the range look nice, so it can be repeated. + if (oap->start.lnum == curwin->w_cursor.lnum) { stuffcharReadbuff('.'); - else + } else { stuffnumReadbuff((long)oap->start.lnum); + } if (oap->end.lnum != oap->start.lnum) { stuffcharReadbuff(','); - if (oap->end.lnum == curwin->w_cursor.lnum) + if (oap->end.lnum == curwin->w_cursor.lnum) { stuffcharReadbuff('.'); - else if (oap->end.lnum == curbuf->b_ml.ml_line_count) + } else if (oap->end.lnum == curbuf->b_ml.ml_line_count) { stuffcharReadbuff('$'); - else if (oap->start.lnum == curwin->w_cursor.lnum) { - stuffReadbuff((char_u *)".+"); + } else if (oap->start.lnum == curwin->w_cursor.lnum) { + stuffReadbuff(".+"); stuffnumReadbuff(oap->line_count - 1); - } else + } else { stuffnumReadbuff((long)oap->end.lnum); + } } } - if (oap->op_type != OP_COLON) - stuffReadbuff((char_u *)"!"); + if (oap->op_type != OP_COLON) { + stuffReadbuff("!"); + } if (oap->op_type == OP_INDENT) { - stuffReadbuff(get_equalprg()); - stuffReadbuff((char_u *)"\n"); + stuffReadbuff((const char *)get_equalprg()); + stuffReadbuff("\n"); } else if (oap->op_type == OP_FORMAT) { - if (*p_fp == NUL) - stuffReadbuff((char_u *)"fmt"); - else - stuffReadbuff(p_fp); - stuffReadbuff((char_u *)"\n']"); + if (*curbuf->b_p_fp != NUL) { + stuffReadbuff((const char *)curbuf->b_p_fp); + } else if (*p_fp != NUL) { + stuffReadbuff((const char *)p_fp); + } else { + stuffReadbuff("fmt"); + } + stuffReadbuff("\n']"); } /* @@ -2077,7 +2081,6 @@ static void op_colon(oparg_T *oap) */ static void op_function(oparg_T *oap) { - char_u *(argv[1]); int save_virtual_op = virtual_op; if (*p_opfunc == NUL) @@ -2091,16 +2094,16 @@ static void op_function(oparg_T *oap) decl(&curbuf->b_op_end); } - if (oap->motion_type == kMTBlockWise) { - argv[0] = (char_u *)"block"; - } else if (oap->motion_type == kMTLineWise) { - argv[0] = (char_u *)"line"; - } else { - argv[0] = (char_u *)"char"; - } + const char_u *const argv[1] = { + (const char_u *)(((const char *const[]) { + [kMTBlockWise] = "block", + [kMTLineWise] = "line", + [kMTCharWise] = "char", + })[oap->motion_type]), + }; - /* Reset virtual_op so that 'virtualedit' can be changed in the - * function. */ + // Reset virtual_op so that 'virtualedit' can be changed in the + // function. virtual_op = MAYBE; (void)call_func_retnr(p_opfunc, 1, argv, false); @@ -2307,7 +2310,7 @@ do_mouse ( if (VIsual_active) { if (VIsual_select) { stuffcharReadbuff(Ctrl_G); - stuffReadbuff((char_u *)"\"+p"); + stuffReadbuff("\"+p"); } else { stuffcharReadbuff('y'); stuffcharReadbuff(K_MIDDLEMOUSE); @@ -2334,10 +2337,11 @@ do_mouse ( if (regname == 0 && eval_has_provider("clipboard")) { regname = '*'; } - if ((State & REPLACE_FLAG) && !yank_register_mline(regname)) + if ((State & REPLACE_FLAG) && !yank_register_mline(regname)) { insert_reg(regname, true); - else { - do_put(regname, NULL, BACKWARD, 1L, fixindent | PUT_CURSEND); + } else { + do_put(regname, NULL, BACKWARD, 1L, + (fixindent ? PUT_FIXINDENT : 0) | PUT_CURSEND); /* Repeat it with CTRL-R CTRL-O r or CTRL-R CTRL-P r */ AppendCharToRedobuff(Ctrl_R); @@ -2462,12 +2466,12 @@ do_mouse ( }; typval_T rettv; int doesrange; - (void) call_func((char_u *) tab_page_click_defs[mouse_col].func, - (int) strlen(tab_page_click_defs[mouse_col].func), - &rettv, ARRAY_SIZE(argv), argv, - curwin->w_cursor.lnum, curwin->w_cursor.lnum, - &doesrange, true, NULL, NULL); - clear_tv(&rettv); + (void)call_func((char_u *)tab_page_click_defs[mouse_col].func, + (int)strlen(tab_page_click_defs[mouse_col].func), + &rettv, ARRAY_SIZE(argv), argv, NULL, + curwin->w_cursor.lnum, curwin->w_cursor.lnum, + &doesrange, true, NULL, NULL); + tv_clear(&rettv); break; } } @@ -2689,7 +2693,8 @@ do_mouse ( */ if (restart_edit != 0) where_paste_started = curwin->w_cursor; - do_put(regname, NULL, dir, count, fixindent | PUT_CURSEND); + do_put(regname, NULL, dir, count, + (fixindent ? PUT_FIXINDENT : 0)| PUT_CURSEND); } /* * Ctrl-Mouse click or double click in a quickfix window jumps to the @@ -2698,13 +2703,12 @@ do_mouse ( else if (((mod_mask & MOD_MASK_CTRL) || (mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK) && bt_quickfix(curbuf)) { - if (State & INSERT) - stuffcharReadbuff(Ctrl_O); - if (curwin->w_llist_ref == NULL) /* quickfix window */ - stuffReadbuff((char_u *)":.cc\n"); - else /* location list window */ - stuffReadbuff((char_u *)":.ll\n"); - got_click = false; /* ignore drag&release now */ + if (curwin->w_llist_ref == NULL) { // quickfix window + do_cmdline_cmd(".cc"); + } else { // location list window + do_cmdline_cmd(".ll"); + } + got_click = false; // ignore drag&release now } /* * Ctrl-Mouse click (or double click in a help window) jumps to the tag @@ -3514,7 +3518,8 @@ void check_scrollbind(linenr_T topline_diff, long leftcol_diff) * loop through the scrollbound windows and scroll accordingly */ VIsual_select = VIsual_active = 0; - for (curwin = firstwin; curwin; curwin = curwin->w_next) { + FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { + curwin = wp; curbuf = curwin->w_buffer; /* skip original window and windows with 'noscrollbind' */ if (curwin == old_curwin || !curwin->w_p_scb) { @@ -3653,6 +3658,39 @@ nv_gd ( } } +// Return true if line[offset] is not inside a C-style comment or string, false +// otherwise. +static bool is_ident(char_u *line, int offset) +{ + bool incomment = false; + int instring = 0; + int prev = 0; + + for (int i = 0; i < offset && line[i] != NUL; i++) { + if (instring != 0) { + if (prev != '\\' && line[i] == instring) { + instring = 0; + } + } else if ((line[i] == '"' || line[i] == '\'') && !incomment) { + instring = line[i]; + } else { + if (incomment) { + if (prev == '*' && line[i] == '/') { + incomment = false; + } + } else if (prev == '/' && line[i] == '*') { + incomment = true; + } else if (prev == '/' && line[i] == '/') { + return false; + } + } + + prev = line[i]; + } + + return incomment == false && instring == 0; +} + /* * Search for variable declaration of "ptr[len]". * When "locally" is true in the current function ("gd"), otherwise in the @@ -3679,6 +3717,7 @@ find_decl ( bool retval = true; bool incll; int searchflags = flags_arg; + bool valid; pat = xmalloc(len + 7); @@ -3713,6 +3752,7 @@ find_decl ( /* Search forward for the identifier, ignore comment lines. */ clearpos(&found_pos); for (;; ) { + valid = false; t = searchit(curwin, curbuf, &curwin->w_cursor, FORWARD, pat, 1L, searchflags, RE_LAST, (linenr_T)0, NULL); if (curwin->w_cursor.lnum >= old_pos.lnum) @@ -3743,20 +3783,35 @@ find_decl ( curwin->w_cursor.col = 0; continue; } - if (!locally) /* global search: use first match found */ + valid = is_ident(get_cursor_line_ptr(), curwin->w_cursor.col); + + // If the current position is not a valid identifier and a previous match is + // present, favor that one instead. + if (!valid && found_pos.lnum != 0) { + curwin->w_cursor = found_pos; break; - if (curwin->w_cursor.lnum >= par_pos.lnum) { - /* If we previously found a valid position, use it. */ - if (found_pos.lnum != 0) + } + // global search: use first match found + if (valid && !locally) { + break; + } + if (valid && curwin->w_cursor.lnum >= par_pos.lnum) { + // If we previously found a valid position, use it. + if (found_pos.lnum != 0) { curwin->w_cursor = found_pos; + } break; } - // For finding a local variable and the match is before the "{" search - // to find a later match. For K&R style function declarations this - // skips the function header without types. Remove SEARCH_START from - // flags to avoid getting stuck at one position. - found_pos = curwin->w_cursor; + // For finding a local variable and the match is before the "{" or + // inside a comment, continue searching. For K&R style function + // declarations this skips the function header without types. + if (!valid) { + clearpos(&found_pos); + } else { + found_pos = curwin->w_cursor; + } + // Remove SEARCH_START from flags to avoid getting stuck at one position. searchflags &= ~SEARCH_START; } @@ -4037,12 +4092,10 @@ static void nv_zet(cmdarg_T *cap) return; n = nchar - '0'; for (;; ) { - ++no_mapping; - ++allow_keys; /* no mapping for nchar, but allow key codes */ + no_mapping++; nchar = plain_vgetc(); LANGMAP_ADJUST(nchar, true); - --no_mapping; - --allow_keys; + no_mapping--; (void)add_to_showcmd(nchar); if (nchar == K_DEL || nchar == K_KDEL) n /= 10; @@ -4370,13 +4423,11 @@ dozet: break; - case 'u': /* "zug" and "zuw": undo "zg" and "zw" */ - ++no_mapping; - ++allow_keys; /* no mapping for nchar, but allow key codes */ + case 'u': // "zug" and "zuw": undo "zg" and "zw" + no_mapping++; nchar = plain_vgetc(); LANGMAP_ADJUST(nchar, true); - --no_mapping; - --allow_keys; + no_mapping--; (void)add_to_showcmd(nchar); if (vim_strchr((char_u *)"gGwW", nchar) == NULL) { clearopbeep(cap->oap); @@ -4483,7 +4534,7 @@ static void nv_colon(cmdarg_T *cap) /* translate "count:" into ":.,.+(count - 1)" */ stuffcharReadbuff('.'); if (cap->count0 > 1) { - stuffReadbuff((char_u *)",.+"); + stuffReadbuff(",.+"); stuffnumReadbuff(cap->count0 - 1L); } } @@ -4674,6 +4725,7 @@ static void nv_ident(cmdarg_T *cap) char_u *kp = *curbuf->b_p_kp == NUL ? p_kp : curbuf->b_p_kp; // 'keywordprg' assert(*kp != NUL); // option.c:do_set() should default to ":help" if empty. bool kp_ex = (*kp == ':'); // 'keywordprg' is an ex command + bool kp_help = (STRCMP(kp, ":he") == 0 || STRCMP(kp, ":help") == 0); size_t buf_size = n * 2 + 30 + STRLEN(kp); char *buf = xmalloc(buf_size); buf[0] = NUL; @@ -4696,7 +4748,9 @@ static void nv_ident(cmdarg_T *cap) break; case 'K': - if (kp_ex) { + if (kp_help) { + STRCPY(buf, "he! "); + } else if (kp_ex) { if (cap->count0 != 0) { // Send the count to the ex command. snprintf(buf, buf_size, "%" PRId64, (int64_t)(cap->count0)); } @@ -4758,13 +4812,16 @@ static void nv_ident(cmdarg_T *cap) } } - /* - * Now grab the chars in the identifier - */ - if (cmdchar == 'K' && !kp_ex) { - /* Escape the argument properly for a shell command */ + // Now grab the chars in the identifier + if (cmdchar == 'K' && !kp_help) { ptr = vim_strnsave(ptr, n); - p = vim_strsave_shellescape(ptr, true, true); + if (kp_ex) { + // Escape the argument properly for an Ex command + p = (char_u *)vim_strsave_fnameescape((const char *)ptr, false); + } else { + // Escape the argument properly for a shell command + p = vim_strsave_shellescape(ptr, true, true); + } xfree(ptr); char *newbuf = xrealloc(buf, STRLEN(buf) + STRLEN(p) + 1); buf = newbuf; @@ -5224,6 +5281,7 @@ static void nv_dollar(cmdarg_T *cap) static void nv_search(cmdarg_T *cap) { oparg_T *oap = cap->oap; + pos_T save_cursor = curwin->w_cursor; if (cap->cmdchar == '?' && cap->oap->op_type == OP_ROT13) { /* Translate "g??" to "g?g?" */ @@ -5233,6 +5291,8 @@ static void nv_search(cmdarg_T *cap) return; } + // When using 'incsearch' the cursor may be moved to set a different search + // start position. cap->searchbuf = getcmdline(cap->cmdchar, cap->count1, 0); if (cap->searchbuf == NULL) { @@ -5241,7 +5301,8 @@ static void nv_search(cmdarg_T *cap) } (void)normal_search(cap, cap->cmdchar, cap->searchbuf, - (cap->arg ? 0 : SEARCH_MARK)); + (cap->arg || !equalpos(save_cursor, curwin->w_cursor)) + ? 0 : SEARCH_MARK); } /* @@ -6160,17 +6221,15 @@ static void nv_abbrev(cmdarg_T *cap) */ static void nv_optrans(cmdarg_T *cap) { - static char_u *(ar[8]) = {(char_u *)"dl", (char_u *)"dh", - (char_u *)"d$", (char_u *)"c$", - (char_u *)"cl", (char_u *)"cc", - (char_u *)"yy", (char_u *)":s\r"}; - static char_u *str = (char_u *)"xXDCsSY&"; + static const char *(ar[]) = { "dl", "dh", "d$", "c$", "cl", "cc", "yy", + ":s\r" }; + static const char *str = "xXDCsSY&"; if (!checkclearopq(cap->oap)) { if (cap->count0) { stuffnumReadbuff(cap->count0); } - stuffReadbuff(ar[(int)(vim_strchr(str, cap->cmdchar) - str)]); + stuffReadbuff(ar[strchr(str, (char)cap->cmdchar) - str]); } cap->opcount = 0; } @@ -7196,8 +7255,10 @@ static void nv_wordcmd(cmdarg_T *cap) // Another strangeness: When standing on the end of a word "ce" will // change until the end of the next word, but "cw" will change only one // character! This is done by setting "flag". - cap->oap->inclusive = true; - word_end = true; + if (vim_strchr(p_cpo, CPO_CHANGEW) != NULL) { + cap->oap->inclusive = true; + word_end = true; + } flag = true; } } @@ -7291,11 +7352,11 @@ static bool unadjust_for_sel(void) pp = &curwin->w_cursor; else pp = &VIsual; - if (pp->coladd > 0) - --pp->coladd; - else if (pp->col > 0) { - --pp->col; - mb_adjustpos(curbuf, pp); + if (pp->coladd > 0) { + pp->coladd--; + } else if (pp->col > 0) { + pp->col--; + mark_mb_adjustpos(curbuf, pp); } else if (pp->lnum > 1) { --pp->lnum; pp->col = (colnr_T)STRLEN(ml_get(pp->lnum)); @@ -7421,27 +7482,23 @@ static void nv_esc(cmdarg_T *cap) restart_edit = 'a'; } -/* - * Handle "A", "a", "I", "i" and <Insert> commands. - */ +/// Handle "A", "a", "I", "i" and <Insert> commands. static void nv_edit(cmdarg_T *cap) { - /* <Insert> is equal to "i" */ - if (cap->cmdchar == K_INS || cap->cmdchar == K_KINS) + // <Insert> is equal to "i" + if (cap->cmdchar == K_INS || cap->cmdchar == K_KINS) { cap->cmdchar = 'i'; + } - /* in Visual mode "A" and "I" are an operator */ - if (VIsual_active && (cap->cmdchar == 'A' || cap->cmdchar == 'I')) + // in Visual mode "A" and "I" are an operator + if (VIsual_active && (cap->cmdchar == 'A' || cap->cmdchar == 'I')) { v_visop(cap); - - /* in Visual mode and after an operator "a" and "i" are for text objects */ - else if ((cap->cmdchar == 'a' || cap->cmdchar == 'i') - && (cap->oap->op_type != OP_NOP - || VIsual_active - )) { + // in Visual mode and after an operator "a" and "i" are for text objects + } else if ((cap->cmdchar == 'a' || cap->cmdchar == 'i') + && (cap->oap->op_type != OP_NOP || VIsual_active)) { nv_object(cap); - } else if (!curbuf->b_p_ma && !p_im) { - /* Only give this error when 'insertmode' is off. */ + } else if (!curbuf->b_p_ma && !p_im && !curbuf->terminal) { + // Only give this error when 'insertmode' is off. EMSG(_(e_modifiable)); clearop(cap->oap); } else if (!checkclearopq(cap->oap)) { @@ -7614,11 +7671,13 @@ static void nv_record(cmdarg_T *cap) if (cap->nchar == ':' || cap->nchar == '/' || cap->nchar == '?') { stuffcharReadbuff(cap->nchar); stuffcharReadbuff(K_CMDWIN); - } else - /* (stop) recording into a named register, unless executing a - * register */ - if (!Exec_reg && do_record(cap->nchar) == false) - clearopbeep(cap->oap); + } else { + // (stop) recording into a named register, unless executing a + // register. + if (!Exec_reg && do_record(cap->nchar) == FAIL) { + clearopbeep(cap->oap); + } + } } } @@ -7727,16 +7786,22 @@ static void nv_put(cmdarg_T *cap) savereg = copy_register(regname); } - /* Now delete the selected text. */ - cap->cmdchar = 'd'; - cap->nchar = NUL; - cap->oap->regname = NUL; - nv_operator(cap); - do_pending_operator(cap, 0, false); - empty = (curbuf->b_ml.ml_flags & ML_EMPTY); + // To place the cursor correctly after a blockwise put, and to leave the + // text in the correct position when putting over a selection with + // 'virtualedit' and past the end of the line, we use the 'c' operator in + // do_put(), which requires the visual selection to still be active. + if (!VIsual_active || VIsual_mode == 'V' || regname != '.') { + // Now delete the selected text. + cap->cmdchar = 'd'; + cap->nchar = NUL; + cap->oap->regname = NUL; + nv_operator(cap); + do_pending_operator(cap, 0, false); + empty = (curbuf->b_ml.ml_flags & ML_EMPTY); - /* delete PUT_LINE_BACKWARD; */ - cap->oap->regname = regname; + // delete PUT_LINE_BACKWARD; + cap->oap->regname = regname; + } /* When deleted a linewise Visual area, put the register as * lines to avoid it joined with the next line. When deletion was @@ -7828,7 +7893,7 @@ static void get_op_vcol( // prevent from moving onto a trail byte if (has_mbyte) { - mb_adjustpos(curwin->w_buffer, &oap->end); + mark_mb_adjustpos(curwin->w_buffer, &oap->end); } getvvcol(curwin, &(oap->start), &oap->start_vcol, NULL, &oap->end_vcol); @@ -7893,6 +7958,7 @@ static void nv_event(cmdarg_T *cap) may_garbage_collect = false; multiqueue_process_events(main_loop.events); cap->retval |= CA_COMMAND_BUSY; // don't call edit() now + finish_op = false; } /// Trigger FocusGained event. diff --git a/src/nvim/ops.c b/src/nvim/ops.c index 907353c271..c01840cfd0 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + /* * ops.c: implementation of various operators: op_shift, op_delete, op_tilde, * op_change, op_yank, do_put, do_join @@ -14,8 +17,10 @@ #include "nvim/buffer.h" #include "nvim/charset.h" #include "nvim/cursor.h" +#include "nvim/assert.h" #include "nvim/edit.h" #include "nvim/eval.h" +#include "nvim/eval/typval.h" #include "nvim/ex_cmds.h" #include "nvim/ex_cmds2.h" #include "nvim/ex_getln.h" @@ -41,6 +46,7 @@ #include "nvim/terminal.h" #include "nvim/ui.h" #include "nvim/undo.h" +#include "nvim/macros.h" #include "nvim/window.h" #include "nvim/os/input.h" #include "nvim/os/time.h" @@ -49,12 +55,11 @@ static yankreg_T y_regs[NUM_REGISTERS]; static yankreg_T *y_previous = NULL; /* ptr to last written yankreg */ -static bool clipboard_didwarn_unnamed = false; - // for behavior between start_batch_changes() and end_batch_changes()) -static bool clipboard_delay_update = false; // delay clipboard update static int batch_change_count = 0; // inside a script +static bool clipboard_delay_update = false; // delay clipboard update static bool clipboard_needs_update = false; // clipboard was updated +static bool clipboard_didwarn = false; /* * structure used by block_prep, op_delete and op_yank for blockwise operators @@ -210,8 +215,6 @@ void op_shift(oparg_T *oap, int curs_top, int amount) } changed_lines(oap->start.lnum, 0, oap->end.lnum + 1, 0L); - /* The cursor line is not in a closed fold */ - foldOpenCursor(); if (oap->motion_type == kMTBlockWise) { curwin->w_cursor.lnum = oap->start.lnum; @@ -222,6 +225,9 @@ void op_shift(oparg_T *oap, int curs_top, int amount) } else --curwin->w_cursor.lnum; /* put cursor on last line, for ":>" */ + // The cursor line is not in a closed fold + foldOpenCursor(); + if (oap->line_count > p_report) { if (oap->op_type == OP_RSHIFT) s = (char_u *)">"; @@ -798,7 +804,6 @@ static bool is_append_register(int regname) /// Returns a copy of contents in register `name` /// for use in do_put. Should be freed by caller. yankreg_T *copy_register(int name) - FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_RET { yankreg_T *reg = get_yank_register(name, YREG_PASTE); @@ -887,7 +892,7 @@ static void set_yreg_additional_data(yankreg_T *reg, dict_T *additional_data) if (reg->additional_data == additional_data) { return; } - dict_unref(reg->additional_data); + tv_dict_unref(reg->additional_data); reg->additional_data = additional_data; } @@ -932,13 +937,11 @@ static int stuff_yank(int regname, char_u *p) static int execreg_lastc = NUL; -/* - * execute a yank register: copy it into the stuff buffer - * - * return FAIL for failure, OK otherwise - */ -int -do_execreg ( +/// Execute a yank register: copy it into the stuff buffer +/// +/// Return FAIL for failure, OK otherwise +int +do_execreg( int regname, int colon, /* insert ':' before each line */ int addcr, /* always add '\n' to end of line */ @@ -1105,7 +1108,6 @@ int insert_reg( ) { int retval = OK; - char_u *arg; int allocated; /* @@ -1121,21 +1123,24 @@ int insert_reg( if (regname != NUL && !valid_yank_reg(regname, false)) return FAIL; - if (regname == '.') /* insert last inserted text */ - retval = stuff_inserted(NUL, 1L, TRUE); - else if (get_spec_reg(regname, &arg, &allocated, TRUE)) { - if (arg == NULL) + char_u *arg; + if (regname == '.') { // Insert last inserted text. + retval = stuff_inserted(NUL, 1L, true); + } else if (get_spec_reg(regname, &arg, &allocated, true)) { + if (arg == NULL) { return FAIL; - stuffescaped(arg, literally); - if (allocated) + } + stuffescaped((const char *)arg, literally); + if (allocated) { xfree(arg); - } else { /* name or number register */ + } + } else { // Name or number register. yankreg_T *reg = get_yank_register(regname, YREG_PASTE); if (reg->y_array == NULL) { retval = FAIL; } else { for (size_t i = 0; i < reg->y_size; i++) { - stuffescaped(reg->y_array[i], literally); + stuffescaped((const char *)reg->y_array[i], literally); // Insert a newline between lines and after last line if // y_type is kMTLineWise. if (reg->y_type == kMTLineWise || i < reg->y_size - 1) { @@ -1152,29 +1157,29 @@ int insert_reg( * Stuff a string into the typeahead buffer, such that edit() will insert it * literally ("literally" TRUE) or interpret is as typed characters. */ -static void stuffescaped(char_u *arg, int literally) +static void stuffescaped(const char *arg, int literally) { - int c; - char_u *start; - while (*arg != NUL) { - /* Stuff a sequence of normal ASCII characters, that's fast. Also - * stuff K_SPECIAL to get the effect of a special key when "literally" - * is TRUE. */ - start = arg; - while ((*arg >= ' ' && *arg < DEL) || (*arg == K_SPECIAL && !literally)) - ++arg; - if (arg > start) + // Stuff a sequence of normal ASCII characters, that's fast. Also + // stuff K_SPECIAL to get the effect of a special key when "literally" + // is TRUE. + const char *const start = arg; + while ((*arg >= ' ' && *arg < DEL) || ((uint8_t)(*arg) == K_SPECIAL + && !literally)) { + arg++; + } + if (arg > start) { stuffReadbuffLen(start, (long)(arg - start)); + } /* stuff a single special character */ if (*arg != NUL) { - if (has_mbyte) - c = mb_cptr2char_adv(&arg); - else - c = *arg++; - if (literally && ((c < ' ' && c != TAB) || c == DEL)) + const int c = (has_mbyte + ? mb_cptr2char_adv((const char_u **)&arg) + : (uint8_t)(*arg++)); + if (literally && ((c < ' ' && c != TAB) || c == DEL)) { stuffcharReadbuff(Ctrl_V); + } stuffcharReadbuff(c); } } @@ -1260,7 +1265,7 @@ int get_spec_reg( /// Paste a yank register into the command line. /// Only for non-special registers. -/// Used by CTRL-R command in command-line mode +/// Used by CTRL-R in command-line mode. /// insert_reg() can't be used here, because special characters from the /// register contents will be interpreted as commands. /// @@ -1278,9 +1283,8 @@ bool cmdline_paste_reg(int regname, bool literally, bool remcr) for (size_t i = 0; i < reg->y_size; i++) { cmdline_paste_str(reg->y_array[i], literally); - // Insert ^M between lines and after last line if type is kMTLineWise. - // Don't do this when "remcr" is true. - if ((reg->y_type == kMTLineWise || i < reg->y_size - 1) && !remcr) { + // Insert ^M between lines, unless `remcr` is true. + if (i < reg->y_size - 1 && !remcr) { cmdline_paste_str((char_u *)"\r", literally); } @@ -1403,8 +1407,11 @@ int op_delete(oparg_T *oap) } if (oap->regname == 0) { + if (reg == NULL) { + abort(); + } set_clipboard(0, reg); - yank_do_autocmd(oap, reg); + do_autocmd_textyankpost(oap, reg); } } @@ -1951,16 +1958,18 @@ int swapchar(int op_type, pos_T *pos) if (enc_dbcs != 0 && c >= 0x100) /* No lower/uppercase letter */ return FALSE; nc = c; - if (vim_islower(c)) { - if (op_type == OP_ROT13) + if (mb_islower(c)) { + if (op_type == OP_ROT13) { nc = ROT13(c, 'a'); - else if (op_type != OP_LOWER) - nc = vim_toupper(c); - } else if (vim_isupper(c)) { - if (op_type == OP_ROT13) + } else if (op_type != OP_LOWER) { + nc = mb_toupper(c); + } + } else if (mb_isupper(c)) { + if (op_type == OP_ROT13) { nc = ROT13(c, 'A'); - else if (op_type != OP_UPPER) - nc = vim_tolower(c); + } else if (op_type != OP_UPPER) { + nc = mb_tolower(c); + } } if (nc != c) { if (enc_utf8 && (c >= 0x80 || nc >= 0x80)) { @@ -2315,7 +2324,7 @@ bool op_yank(oparg_T *oap, bool message) yankreg_T *reg = get_yank_register(oap->regname, YREG_YANK); op_yank_reg(oap, message, reg, is_append_register(oap->regname)); set_clipboard(oap->regname, reg); - yank_do_autocmd(oap, reg); + do_autocmd_textyankpost(oap, reg); return true; } @@ -2538,7 +2547,7 @@ static void yank_copy_line(yankreg_T *reg, struct block_def *bd, size_t y_idx) /// /// @param oap Operator arguments. /// @param reg The yank register used. -static void yank_do_autocmd(oparg_T *oap, yankreg_T *reg) +static void do_autocmd_textyankpost(oparg_T *oap, yankreg_T *reg) FUNC_ATTR_NONNULL_ALL { static bool recursive = false; @@ -2555,33 +2564,33 @@ static void yank_do_autocmd(oparg_T *oap, yankreg_T *reg) dict_T *dict = get_vim_var_dict(VV_EVENT); // the yanked text - list_T *list = list_alloc(); + list_T *list = tv_list_alloc(); for (size_t i = 0; i < reg->y_size; i++) { - list_append_string(list, reg->y_array[i], -1); + tv_list_append_string(list, (const char *)reg->y_array[i], -1); } list->lv_lock = VAR_FIXED; - dict_add_list(dict, "regcontents", list); + tv_dict_add_list(dict, S_LEN("regcontents"), list); // the register type char buf[NUMBUFLEN+2]; format_reg_type(reg->y_type, reg->y_width, buf, ARRAY_SIZE(buf)); - dict_add_nr_str(dict, "regtype", 0, (char_u *)buf); + tv_dict_add_str(dict, S_LEN("regtype"), buf); // name of requested register or the empty string for an unnamed operation. buf[0] = (char)oap->regname; buf[1] = NUL; - dict_add_nr_str(dict, "regname", 0, (char_u *)buf); + tv_dict_add_str(dict, S_LEN("regname"), buf); // kind of operation (yank/delete/change) buf[0] = (char)get_op_char(oap->op_type); buf[1] = NUL; - dict_add_nr_str(dict, "operator", 0, (char_u *)buf); + tv_dict_add_str(dict, S_LEN("operator"), buf); - dict_set_keys_readonly(dict); + tv_dict_set_keys_readonly(dict); textlock++; apply_autocmds(EVENT_TEXTYANKPOST, NULL, NULL, false, curbuf); textlock--; - dict_clear(dict); + tv_dict_clear(dict); recursive = false; } @@ -2637,12 +2646,79 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags) * special characters (newlines, etc.). */ if (regname == '.') { - (void)stuff_inserted((dir == FORWARD ? (count == -1 ? 'o' : 'a') : - (count == -1 ? 'O' : 'i')), count, FALSE); - /* Putting the text is done later, so can't really move the cursor to - * the next character. Use "l" to simulate it. */ - if ((flags & PUT_CURSEND) && gchar_cursor() != NUL) - stuffcharReadbuff('l'); + bool non_linewise_vis = (VIsual_active && VIsual_mode != 'V'); + + // PUT_LINE has special handling below which means we use 'i' to start. + char command_start_char = non_linewise_vis ? 'c' : + (flags & PUT_LINE ? 'i' : (dir == FORWARD ? 'a' : 'i')); + + // To avoid 'autoindent' on linewise puts, create a new line with `:put _`. + if (flags & PUT_LINE) { + do_put('_', NULL, dir, 1, PUT_LINE); + } + + // If given a count when putting linewise, we stuff the readbuf with the + // dot register 'count' times split by newlines. + if (flags & PUT_LINE) { + stuffcharReadbuff(command_start_char); + for (; count > 0; count--) { + (void)stuff_inserted(NUL, 1, count != 1); + if (count != 1) { + // To avoid 'autoindent' affecting the text, use Ctrl_U to remove any + // whitespace. Can't just insert Ctrl_U into readbuf1, this would go + // back to the previous line in the case of 'noautoindent' and + // 'backspace' includes "eol". So we insert a dummy space for Ctrl_U + // to consume. + stuffReadbuff("\n "); + stuffcharReadbuff(Ctrl_U); + } + } + } else { + (void)stuff_inserted(command_start_char, count, false); + } + + // Putting the text is done later, so can't move the cursor to the next + // character. Simulate it with motion commands after the insert. + if (flags & PUT_CURSEND) { + if (flags & PUT_LINE) { + stuffReadbuff("j0"); + } else { + // Avoid ringing the bell from attempting to move into the space after + // the current line. We can stuff the readbuffer with "l" if: + // 1) 'virtualedit' is "all" or "onemore" + // 2) We are not at the end of the line + // 3) We are not (one past the end of the line && on the last line) + // This allows a visual put over a selection one past the end of the + // line joining the current line with the one below. + + // curwin->w_cursor.col marks the byte position of the cursor in the + // currunt line. It increases up to a max of + // STRLEN(ml_get(curwin->w_cursor.lnum)). With 'virtualedit' and the + // cursor past the end of the line, curwin->w_cursor.coladd is + // incremented instead of curwin->w_cursor.col. + char_u *cursor_pos = get_cursor_pos_ptr(); + bool one_past_line = (*cursor_pos == NUL); + bool eol = false; + if (!one_past_line) { + eol = (*(cursor_pos + mb_ptr2len(cursor_pos)) == NUL); + } + + bool ve_allows = (ve_flags == VE_ALL || ve_flags == VE_ONEMORE); + bool eof = curbuf->b_ml.ml_line_count == curwin->w_cursor.lnum + && one_past_line; + if (ve_allows || !(eol || eof)) { + stuffcharReadbuff('l'); + } + } + } else if (flags & PUT_LINE) { + stuffReadbuff("g'["); + } + + // So the 'u' command restores cursor position after ".p, save the cursor + // position now (though not saving any text). + if (command_start_char == 'a') { + u_save(curwin->w_cursor.lnum, curwin->w_cursor.lnum + 1); + } return; } @@ -2712,7 +2788,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags) } if (curbuf->terminal) { - for (int i = 0; i < count; i++) { + for (int i = 0; i < count; i++) { // -V756 // feed the lines to the terminal for (size_t j = 0; j < y_size; j++) { if (j) { @@ -2831,14 +2907,12 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags) else getvcol(curwin, &curwin->w_cursor, NULL, NULL, &col); - if (has_mbyte) - /* move to start of next multi-byte character */ - curwin->w_cursor.col += (*mb_ptr2len)(get_cursor_pos_ptr()); - else if (c != TAB || ve_flags != VE_ALL) - ++curwin->w_cursor.col; - ++col; - } else + // move to start of next multi-byte character + curwin->w_cursor.col += (*mb_ptr2len)(get_cursor_pos_ptr()); + col++; + } else { getvcol(curwin, &curwin->w_cursor, &col, NULL, &endcol2); + } col += curwin->w_cursor.coladd; if (ve_flags == VE_ALL @@ -2892,8 +2966,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags) bd.startspaces = incr - bd.endspaces; --bd.textcol; delcount = 1; - if (has_mbyte) - bd.textcol -= (*mb_head_off)(oldp, oldp + bd.textcol); + bd.textcol -= (*mb_head_off)(oldp, oldp + bd.textcol); if (oldp[bd.textcol] != TAB) { /* Only a Tab can be split into spaces. Other * characters will have to be moved to after the @@ -2975,21 +3048,13 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags) // if type is kMTCharWise, FORWARD is the same as BACKWARD on the next // char if (dir == FORWARD && gchar_cursor() != NUL) { - if (has_mbyte) { - int bytelen = (*mb_ptr2len)(get_cursor_pos_ptr()); - - /* put it on the next of the multi-byte character. */ - col += bytelen; - if (yanklen) { - curwin->w_cursor.col += bytelen; - curbuf->b_op_end.col += bytelen; - } - } else { - ++col; - if (yanklen) { - ++curwin->w_cursor.col; - ++curbuf->b_op_end.col; - } + int bytelen = (*mb_ptr2len)(get_cursor_pos_ptr()); + + // put it on the next of the multi-byte character. + col += bytelen; + if (yanklen) { + curwin->w_cursor.col += bytelen; + curbuf->b_op_end.col += bytelen; } } curbuf->b_op_start = curwin->w_cursor; @@ -3027,7 +3092,9 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags) } if (VIsual_active) lnum++; - } while (VIsual_active && lnum <= curbuf->b_visual.vi_end.lnum); + } while (VIsual_active + && (lnum <= curbuf->b_visual.vi_end.lnum + || lnum <= curbuf->b_visual.vi_start.lnum)); if (VIsual_active) { /* reset lnum to the last visual line */ lnum--; @@ -3114,7 +3181,7 @@ error: if (curbuf->b_op_start.lnum + (y_type == kMTCharWise) - 1 + nr_lines < curbuf->b_ml.ml_line_count) { mark_adjust(curbuf->b_op_start.lnum + (y_type == kMTCharWise), - (linenr_T)MAXLNUM, nr_lines, 0L); + (linenr_T)MAXLNUM, nr_lines, 0L, false); } // note changed text for displaying and folding @@ -3264,10 +3331,11 @@ void ex_display(exarg_T *eap) get_clipboard(name, &yb, true); - if (name == vim_tolower(redir_reg) - || (redir_reg == '"' && yb == y_previous)) - continue; /* do not list register being written to, the - * pointer can be freed */ + if (name == mb_tolower(redir_reg) + || (redir_reg == '"' && yb == y_previous)) { + continue; // do not list register being written to, the + // pointer can be freed + } if (yb->y_array != NULL) { msg_putchar('\n'); @@ -3380,43 +3448,47 @@ dis_msg ( os_breakcheck(); } -/* - * If "process" is TRUE and the line begins with a comment leader (possibly - * after some white space), return a pointer to the text after it. Put a boolean - * value indicating whether the line ends with an unclosed comment in - * "is_comment". - * line - line to be processed, - * process - if FALSE, will only check whether the line ends with an unclosed - * comment, - * include_space - whether to also skip space following the comment leader, - * is_comment - will indicate whether the current line ends with an unclosed - * comment. - */ -static char_u *skip_comment(char_u *line, int process, int include_space, int *is_comment) +/// If \p "process" is true and the line begins with a comment leader (possibly +/// after some white space), return a pointer to the text after it. +/// Put a boolean value indicating whether the line ends with an unclosed +/// comment in "is_comment". +/// +/// @param line - line to be processed +/// @param process - if false, will only check whether the line ends +/// with an unclosed comment, +/// @param include_space - whether to skip space following the comment leader +/// @param[out] is_comment - whether the current line ends with an unclosed +/// comment. +char_u *skip_comment( + char_u *line, bool process, bool include_space, bool *is_comment +) { char_u *comment_flags = NULL; int lead_len; int leader_offset = get_last_leader_offset(line, &comment_flags); - *is_comment = FALSE; + *is_comment = false; if (leader_offset != -1) { /* Let's check whether the line ends with an unclosed comment. * If the last comment leader has COM_END in flags, there's no comment. */ while (*comment_flags) { if (*comment_flags == COM_END - || *comment_flags == ':') + || *comment_flags == ':') { break; - ++comment_flags; + } + comment_flags++; + } + if (*comment_flags != COM_END) { + *is_comment = true; } - if (*comment_flags != COM_END) - *is_comment = TRUE; } - if (process == FALSE) + if (process == false) { return line; + } - lead_len = get_leader_len(line, &comment_flags, FALSE, include_space); + lead_len = get_leader_len(line, &comment_flags, false, include_space); if (lead_len == 0) return line; @@ -3438,8 +3510,9 @@ static char_u *skip_comment(char_u *line, int process, int include_space, int *i * starting with a closing part of a three-part comment. That's good, * because we don't want to remove those as this would be annoying. */ - if (*comment_flags == ':' || *comment_flags == NUL) + if (*comment_flags == ':' || *comment_flags == NUL) { line += lead_len; + } return line; } @@ -3473,7 +3546,7 @@ int do_join(size_t count, int *comments = NULL; int remove_comments = (use_formatoptions == TRUE) && has_format_option(FO_REMOVE_COMS); - int prev_was_comment; + bool prev_was_comment; if (save_undo && u_save(curwin->w_cursor.lnum - 1, curwin->w_cursor.lnum + (linenr_T)count) == FAIL) { @@ -3784,6 +3857,7 @@ fex_format ( int use_sandbox = was_set_insecurely((char_u *)"formatexpr", OPT_LOCAL); int r; + char_u *fex; /* * Set v:lnum to the first line number and v:count to the number of lines. @@ -3793,16 +3867,22 @@ fex_format ( set_vim_var_nr(VV_COUNT, (varnumber_T)count); set_vim_var_char(c); - /* - * Evaluate the function. - */ - if (use_sandbox) - ++sandbox; - r = eval_to_number(curbuf->b_p_fex); - if (use_sandbox) - --sandbox; + // Make a copy, the option could be changed while calling it. + fex = vim_strsave(curbuf->b_p_fex); + if (fex == NULL) { + return 0; + } + // Evaluate the function. + if (use_sandbox) { + sandbox++; + } + r = (int)eval_to_number(fex); + if (use_sandbox) { + sandbox--; + } set_vim_var_string(VV_CHAR, NULL, -1); + xfree(fex); return r; } @@ -4359,8 +4439,8 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1) char_u buf2[NUMBUFLEN]; int pre; // 'X' or 'x': hex; '0': octal; 'B' or 'b': bin static bool hexupper = false; // 0xABC - unsigned long n; - unsigned long oldn; + uvarnumber_T n; + uvarnumber_T oldn; char_u *ptr; int c; int todel; @@ -4397,12 +4477,14 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1) if (dobin) { while (col > 0 && ascii_isbdigit(ptr[col])) { col--; + col -= utf_head_off(ptr, ptr + col); } } if (dohex) { while (col > 0 && ascii_isxdigit(ptr[col])) { col--; + col -= utf_head_off(ptr, ptr + col); } } if (dobin @@ -4410,6 +4492,7 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1) && !((col > 0 && (ptr[col] == 'X' || ptr[col] == 'x') && ptr[col - 1] == '0' + && !utf_head_off(ptr, ptr + col - 1) && ascii_isxdigit(ptr[col + 1])))) { // In case of binary/hexadecimal pattern overlap match, rescan @@ -4417,6 +4500,7 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1) while (col > 0 && ascii_isdigit(ptr[col])) { col--; + col -= utf_head_off(ptr, ptr + col); } } @@ -4424,14 +4508,17 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1) && col > 0 && (ptr[col] == 'X' || ptr[col] == 'x') && ptr[col - 1] == '0' + && !utf_head_off(ptr, ptr + col - 1) && ascii_isxdigit(ptr[col + 1])) || (dobin && col > 0 && (ptr[col] == 'B' || ptr[col] == 'b') && ptr[col - 1] == '0' + && !utf_head_off(ptr, ptr + col - 1) && ascii_isbdigit(ptr[col + 1]))) { // Found hexadecimal or binary number, move to its start. col--; + col -= utf_head_off(ptr, ptr + col); } else { // Search forward and then backward to find the start of number. col = pos->col; @@ -4453,15 +4540,18 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1) if (visual) { while (ptr[col] != NUL && length > 0 && !ascii_isdigit(ptr[col]) && !(doalp && ASCII_ISALPHA(ptr[col]))) { - col++; - length--; + int mb_len = MB_PTR2LEN(ptr + col); + + col += mb_len; + length -= mb_len; } if (length == 0) { goto theend; } - if (col > pos->col && ptr[col - 1] == '-') { + if (col > pos->col && ptr[col - 1] == '-' + && !utf_head_off(ptr, ptr + col - 1)) { negative = true; was_positive = false; } @@ -4507,7 +4597,8 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1) endpos = curwin->w_cursor; curwin->w_cursor.col = col; } else { - if (col > 0 && ptr[col - 1] == '-' && !visual) { + if (col > 0 && ptr[col - 1] == '-' + && !utf_head_off(ptr, ptr + col - 1) && !visual) { // negative number col--; negative = true; @@ -4544,20 +4635,20 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1) oldn = n; - n = subtract ? n - (unsigned long) Prenum1 - : n + (unsigned long) Prenum1; + n = subtract ? n - (uvarnumber_T)Prenum1 + : n + (uvarnumber_T)Prenum1; // handle wraparound for decimal numbers if (!pre) { if (subtract) { if (n > oldn) { - n = 1 + (n ^ (unsigned long)-1); + n = 1 + (n ^ (uvarnumber_T)-1); negative ^= true; } } else { // add if (n < oldn) { - n = (n ^ (unsigned long)-1); + n = (n ^ (uvarnumber_T)-1); negative ^= true; } } @@ -4763,8 +4854,8 @@ static void *get_reg_wrap_one_line(char_u *s, int flags) if (!(flags & kGRegList)) { return s; } - list_T *list = list_alloc(); - list_append_string(list, NULL, -1); + list_T *list = tv_list_alloc(); + tv_list_append_string(list, NULL, 0); list->lv_first->li_tv.vval.v_string = s; return list; } @@ -4814,9 +4905,9 @@ void *get_reg_contents(int regname, int flags) return NULL; if (flags & kGRegList) { - list_T *list = list_alloc(); + list_T *list = tv_list_alloc(); for (size_t i = 0; i < reg->y_size; i++) { - list_append_string(list, reg->y_array[i], -1); + tv_list_append_string(list, (const char *)reg->y_array[i], -1); } return list; @@ -4897,7 +4988,7 @@ void write_reg_contents(int name, const char_u *str, ssize_t len, write_reg_contents_ex(name, str, len, must_append, kMTUnknown, 0L); } -void write_reg_contents_lst(int name, char_u **strings, int maxlen, +void write_reg_contents_lst(int name, char_u **strings, bool must_append, MotionType yank_type, colnr_T block_len) { @@ -5147,11 +5238,13 @@ void clear_oparg(oparg_T *oap) * case, eol_size will be added to the character count to account for * the size of the EOL character. */ -static long line_count_info(char_u *line, long *wc, long *cc, long limit, int eol_size) +static varnumber_T line_count_info(char_u *line, varnumber_T *wc, + varnumber_T *cc, varnumber_T limit, + int eol_size) { - long i; - long words = 0; - long chars = 0; + varnumber_T i; + varnumber_T words = 0; + varnumber_T chars = 0; int is_word = 0; for (i = 0; i < limit && line[i] != NUL; ) { @@ -5189,15 +5282,15 @@ void cursor_pos_info(dict_T *dict) char_u buf1[50]; char_u buf2[40]; linenr_T lnum; - long byte_count = 0; - long bom_count = 0; - long byte_count_cursor = 0; - long char_count = 0; - long char_count_cursor = 0; - long word_count = 0; - long word_count_cursor = 0; + varnumber_T byte_count = 0; + varnumber_T bom_count = 0; + varnumber_T byte_count_cursor = 0; + varnumber_T char_count = 0; + varnumber_T char_count_cursor = 0; + varnumber_T word_count = 0; + varnumber_T word_count_cursor = 0; int eol_size; - long last_check = 100000L; + varnumber_T last_check = 100000L; long line_count_selected = 0; pos_T min_pos, max_pos; oparg_T oparg; @@ -5304,15 +5397,16 @@ void cursor_pos_info(dict_T *dict) if (lnum == curwin->w_cursor.lnum) { word_count_cursor += word_count; char_count_cursor += char_count; - byte_count_cursor = byte_count + - line_count_info(ml_get(lnum), - &word_count_cursor, &char_count_cursor, - (long)(curwin->w_cursor.col + 1), eol_size); + byte_count_cursor = byte_count + + line_count_info(ml_get(lnum), &word_count_cursor, + &char_count_cursor, + (varnumber_T)(curwin->w_cursor.col + 1), + eol_size); } } - /* Add to the running totals */ - byte_count += line_count_info(ml_get(lnum), &word_count, - &char_count, (long)MAXCOL, eol_size); + // Add to the running totals + byte_count += line_count_info(ml_get(lnum), &word_count, &char_count, + (varnumber_T)MAXCOL, eol_size); } // Correction for when last line doesn't have an EOL. @@ -5401,17 +5495,19 @@ void cursor_pos_info(dict_T *dict) if (dict != NULL) { // Don't shorten this message, the user asked for it. - dict_add_nr_str(dict, "words", word_count, NULL); - dict_add_nr_str(dict, "chars", char_count, NULL); - dict_add_nr_str(dict, "bytes", byte_count + bom_count, NULL); - - dict_add_nr_str(dict, l_VIsual_active ? "visual_bytes" : "cursor_bytes", - byte_count_cursor, NULL); - dict_add_nr_str(dict, l_VIsual_active ? "visual_chars" : "cursor_chars", - char_count_cursor, NULL); - dict_add_nr_str(dict, l_VIsual_active ? "visual_words" : "cursor_words", - word_count_cursor, NULL); - } + tv_dict_add_nr(dict, S_LEN("words"), (varnumber_T)word_count); + tv_dict_add_nr(dict, S_LEN("chars"), (varnumber_T)char_count); + tv_dict_add_nr(dict, S_LEN("bytes"), (varnumber_T)(byte_count + bom_count)); + + STATIC_ASSERT(sizeof("visual") == sizeof("cursor"), + "key_len argument in tv_dict_add_nr is wrong"); + tv_dict_add_nr(dict, l_VIsual_active ? "visual_bytes" : "cursor_bytes", + sizeof("visual_bytes") - 1, (varnumber_T)byte_count_cursor); + tv_dict_add_nr(dict, l_VIsual_active ? "visual_chars" : "cursor_chars", + sizeof("visual_chars") - 1, (varnumber_T)char_count_cursor); + tv_dict_add_nr(dict, l_VIsual_active ? "visual_words" : "cursor_words", + sizeof("visual_words") - 1, (varnumber_T)word_count_cursor); + } } /// Check if the default register (used in an unnamed paste) should be a @@ -5427,7 +5523,7 @@ int get_default_register_name(void) } /// Determine if register `*name` should be used as a clipboard. -/// In an unnammed operation, `*name` is `NUL` and will be adjusted to `'*'/'+'` if +/// In an unnamed operation, `*name` is `NUL` and will be adjusted to */+ if /// `clipboard=unnamed[plus]` is set. /// /// @param name The name of register, or `NUL` if unnamed. @@ -5438,33 +5534,41 @@ int get_default_register_name(void) /// if the register isn't a clipboard or provider isn't available. static yankreg_T *adjust_clipboard_name(int *name, bool quiet, bool writing) { - if (*name == '*' || *name == '+') { - if(!eval_has_provider("clipboard")) { - if (!quiet) { - EMSG("clipboard: No provider. Try \":CheckHealth\" or " - "\":h clipboard\"."); - } - return NULL; - } - return &y_regs[*name == '*' ? STAR_REGISTER : PLUS_REGISTER]; - } else if ((*name == NUL) && (cb_flags & CB_UNNAMEDMASK)) { - if(!eval_has_provider("clipboard")) { - if (!quiet && !clipboard_didwarn_unnamed) { - msg((char_u *)"clipboard: No provider. Try \":CheckHealth\" or " - "\":h clipboard\"."); - clipboard_didwarn_unnamed = true; - } - return NULL; +#define MSG_NO_CLIP "clipboard: No provider. " \ + "Try \":CheckHealth\" or \":h clipboard\"." + + yankreg_T *target = NULL; + bool explicit_cb_reg = (*name == '*' || *name == '+'); + bool implicit_cb_reg = (*name == NUL) && (cb_flags & CB_UNNAMEDMASK); + if (!explicit_cb_reg && !implicit_cb_reg) { + goto end; + } + + if (!eval_has_provider("clipboard")) { + if (batch_change_count == 1 && !quiet + && (!clipboard_didwarn || (explicit_cb_reg && !redirecting()))) { + clipboard_didwarn = true; + // Do NOT error (emsg()) here--if it interrupts :redir we get into + // a weird state, stuck in "redirect mode". + msg((char_u *)MSG_NO_CLIP); } + // ... else, be silent (don't flood during :while, :redir, etc.). + goto end; + } + + if (explicit_cb_reg) { + target = &y_regs[*name == '*' ? STAR_REGISTER : PLUS_REGISTER]; + goto end; + } else { // unnamed register: "implicit" clipboard if (writing && clipboard_delay_update) { + // For "set" (copy), defer the clipboard call. clipboard_needs_update = true; - return NULL; + goto end; } else if (!writing && clipboard_needs_update) { - // use the internal value - return NULL; + // For "get" (paste), use the internal value. + goto end; } - yankreg_T *target; if (cb_flags & CB_UNNAMEDPLUS) { *name = (cb_flags & CB_UNNAMED && writing) ? '"': '+'; target = &y_regs[PLUS_REGISTER]; @@ -5472,10 +5576,11 @@ static yankreg_T *adjust_clipboard_name(int *name, bool quiet, bool writing) *name = '*'; target = &y_regs[STAR_REGISTER]; } - return target; // unnamed register + goto end; } - // don't do anything for other register names - return NULL; + +end: + return target; } static bool get_clipboard(int name, yankreg_T **target, bool quiet) @@ -5489,9 +5594,9 @@ static bool get_clipboard(int name, yankreg_T **target, bool quiet) } free_register(reg); - list_T *args = list_alloc(); - char_u regname = (char_u)name; - list_append_string(args, ®name, 1); + list_T *const args = tv_list_alloc(); + const char regname = (char)name; + tv_list_append_string(args, ®name, 1); typval_T result = eval_call_provider("clipboard", "get", args); @@ -5503,7 +5608,8 @@ static bool get_clipboard(int name, yankreg_T **target, bool quiet) goto err; } - list_T *res = result.vval.v_list, *lines = NULL; + list_T *res = result.vval.v_list; + list_T *lines = NULL; if (res->lv_len == 2 && res->lv_first->li_tv.v_type == VAR_LIST) { lines = res->lv_first->li_tv.vval.v_list; if (res->lv_last->li_tv.v_type != VAR_STRING) { @@ -5547,7 +5653,7 @@ static bool get_clipboard(int name, yankreg_T **target, bool quiet) if (li->li_tv.v_type != VAR_STRING) { goto err; } - reg->y_array[i++] = (uint8_t *)xstrdup((char *)li->li_tv.vval.v_string); + reg->y_array[i++] = (char_u *)xstrdupnul((char *)li->li_tv.vval.v_string); } if (reg->y_size > 0 && strlen((char*)reg->y_array[reg->y_size-1]) == 0) { @@ -5605,40 +5711,44 @@ static void set_clipboard(int name, yankreg_T *reg) return; } - list_T *lines = list_alloc(); + list_T *lines = tv_list_alloc(); for (size_t i = 0; i < reg->y_size; i++) { - list_append_string(lines, reg->y_array[i], -1); + tv_list_append_string(lines, (const char *)reg->y_array[i], -1); } - list_T *args = list_alloc(); - list_append_list(args, lines); + list_T *args = tv_list_alloc(); + tv_list_append_list(args, lines); - char_u regtype; + char regtype; switch (reg->y_type) { - case kMTLineWise: - regtype = 'V'; - list_append_string(lines, (char_u*)"", 0); - break; - case kMTCharWise: - regtype = 'v'; - break; - case kMTBlockWise: - regtype = 'b'; - list_append_string(lines, (char_u*)"", 0); - break; - case kMTUnknown: - assert(false); - } - list_append_string(args, ®type, 1); - - char_u regname = (char_u)name; - list_append_string(args, ®name, 1); + case kMTLineWise: { + regtype = 'V'; + tv_list_append_string(lines, NULL, 0); + break; + } + case kMTCharWise: { + regtype = 'v'; + break; + } + case kMTBlockWise: { + regtype = 'b'; + tv_list_append_string(lines, NULL, 0); + break; + } + case kMTUnknown: { + assert(false); + } + } + tv_list_append_string(args, ®type, 1); + + const char regname = (char)name; + tv_list_append_string(args, ®name, 1); (void)eval_call_provider("clipboard", "set", args); } -/// Avoid clipboard (slow) during batch operations (i.e., a script). +/// Avoid slow things (clipboard) during batch operations (while/for-loops). void start_batch_changes(void) { if (++batch_change_count > 1) { @@ -5648,7 +5758,7 @@ void start_batch_changes(void) clipboard_needs_update = false; } -/// Update the clipboard after batch changes finished. +/// Counterpart to start_batch_changes(). void end_batch_changes(void) { if (--batch_change_count > 0) { @@ -5657,6 +5767,7 @@ void end_batch_changes(void) } clipboard_delay_update = false; if (clipboard_needs_update) { + // unnamed ("implicit" clipboard) set_clipboard(NUL, y_previous); clipboard_needs_update = false; } @@ -5682,7 +5793,7 @@ static inline bool reg_empty(const yankreg_T *const reg) /// @return Pointer that needs to be passed to next `op_register_iter` call or /// NULL if iteration is over. const void *op_register_iter(const void *const iter, char *const name, - yankreg_T *const reg) + yankreg_T *const reg, bool *is_unnamed) FUNC_ATTR_NONNULL_ARG(2, 3) FUNC_ATTR_WARN_UNUSED_RESULT { *name = NUL; @@ -5698,6 +5809,7 @@ const void *op_register_iter(const void *const iter, char *const name, int iter_off = (int)(iter_reg - &(y_regs[0])); *name = (char)get_register_name(iter_off); *reg = *iter_reg; + *is_unnamed = (iter_reg == y_previous); while (++iter_reg - &(y_regs[0]) < NUM_SAVED_REGISTERS) { if (!reg_empty(iter_reg)) { return (void *) iter_reg; @@ -5722,10 +5834,11 @@ size_t op_register_amount(void) /// Set register to a given value /// /// @param[in] name Register name. -/// @param[in] reg Register value. +/// @param[in] reg Register value. +/// @param[in] is_unnamed Whether to set the unnamed regiseter to reg /// /// @return true on success, false on failure. -bool op_register_set(const char name, const yankreg_T reg) +bool op_register_set(const char name, const yankreg_T reg, bool is_unnamed) { int i = op_reg_index(name); if (i == -1) { @@ -5733,6 +5846,10 @@ bool op_register_set(const char name, const yankreg_T reg) } free_register(&y_regs[i]); y_regs[i] = reg; + + if (is_unnamed) { + y_previous = &y_regs[i]; + } return true; } @@ -5749,3 +5866,20 @@ const yankreg_T *op_register_get(const char name) } return &y_regs[i]; } + +/// Set the previous yank register +/// +/// @param[in] name Register name. +/// +/// @return true on success, false on failure. +bool op_register_set_previous(const char name) + FUNC_ATTR_WARN_UNUSED_RESULT +{ + int i = op_reg_index(name); + if (i == -1) { + return false; + } + + y_previous = &y_regs[i]; + return true; +} diff --git a/src/nvim/ops.h b/src/nvim/ops.h index 44df2e9e0c..a8867e02ea 100644 --- a/src/nvim/ops.h +++ b/src/nvim/ops.h @@ -6,8 +6,10 @@ #include "nvim/macros.h" #include "nvim/ascii.h" #include "nvim/types.h" -#include "nvim/eval_defs.h" +#include "nvim/eval/typval.h" #include "nvim/os/time.h" +#include "nvim/normal.h" // for MotionType and oparg_T +#include "nvim/ex_cmds_defs.h" // for exarg_T typedef int (*Indenter)(void); diff --git a/src/nvim/option.c b/src/nvim/option.c index 52a8b19ca4..8ba10fd38a 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1,24 +1,24 @@ -/* - * Code to handle user-settable options. This is all pretty much table- - * driven. Checklist for adding a new option: - * - Put it in the options array below (copy an existing entry). - * - For a global option: Add a variable for it in option_defs.h. - * - For a buffer or window local option: - * - Add a PV_XX entry to the enum below. - * - Add a variable to the window or buffer struct in buffer_defs.h. - * - For a window option, add some code to copy_winopt(). - * - For a buffer option, add some code to buf_copy_options(). - * - For a buffer string option, add code to check_buf_options(). - * - If it's a numeric option, add any necessary bounds checks to do_set(). - * - If it's a list of flags, add some code in do_set(), search for WW_ALL. - * - When adding an option with expansion (P_EXPAND), but with a different - * default for Vi and Vim (no P_VI_DEF), add some code at VIMEXP. - * - Add documentation! One line in doc/help.txt, full description in - * options.txt, and any other related places. - * - Add an entry in runtime/optwin.vim. - * When making changes: - * - Adjust the help for the option in doc/option.txt. - */ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + +// User-settable options. Checklist for adding a new option: +// - Put it in options.lua +// - For a global option: Add a variable for it in option_defs.h. +// - For a buffer or window local option: +// - Add a BV_XX or WV_XX entry to option_defs.h +// - Add a variable to the window or buffer struct in buffer_defs.h. +// - For a window option, add some code to copy_winopt(). +// - For a window string option, add code to check_winopt() +// and clear_winopt(). If setting the option needs parsing, +// add some code to didset_window_options(). +// - For a buffer option, add some code to buf_copy_options(). +// - For a buffer string option, add code to check_buf_options(). +// - If it's a numeric option, add any necessary bounds checks to do_set(). +// - If it's a list of flags, add some code in do_set(), search for WW_ALL. +// - When adding an option with expansion (P_EXPAND), but with a different +// default for Vi and Vim (no P_VI_DEF), add some code at VIMEXP. +// - Add documentation! doc/options.txt, and any other related places. +// - Add an entry in runtime/optwin.vim. #define IN_OPTION_C #include <assert.h> @@ -31,6 +31,7 @@ #include <limits.h> #include "nvim/vim.h" +#include "nvim/macros.h" #include "nvim/ascii.h" #include "nvim/edit.h" #include "nvim/option.h" @@ -40,6 +41,7 @@ #include "nvim/diff.h" #include "nvim/digraph.h" #include "nvim/eval.h" +#include "nvim/eval/typval.h" #include "nvim/ex_cmds2.h" #include "nvim/ex_docmd.h" #include "nvim/ex_getln.h" @@ -65,6 +67,7 @@ #include "nvim/regexp.h" #include "nvim/screen.h" #include "nvim/spell.h" +#include "nvim/spellfile.h" #include "nvim/strings.h" #include "nvim/syntax.h" #include "nvim/ui.h" @@ -213,12 +216,12 @@ typedef struct vimoption { #define P_VI_DEF 0x400U /* Use Vi default for Vim */ #define P_VIM 0x800U /* Vim option */ -/* when option changed, what to display: */ -#define P_RSTAT 0x1000U /* redraw status lines */ -#define P_RWIN 0x2000U /* redraw current window */ -#define P_RBUF 0x4000U /* redraw current buffer */ -#define P_RALL 0x6000U /* redraw all windows */ -#define P_RCLR 0x7000U /* clear and redraw all */ +// when option changed, what to display: +#define P_RSTAT 0x1000U ///< redraw status lines +#define P_RWIN 0x2000U ///< redraw current window and recompute text +#define P_RBUF 0x4000U ///< redraw current buffer and recompute text +#define P_RALL 0x6000U ///< redraw all windows +#define P_RCLR 0x7000U ///< clear and redraw all #define P_COMMA 0x8000U ///< comma separated list #define P_ONECOMMA 0x18000U ///< P_COMMA and cannot have two consecutive @@ -238,15 +241,18 @@ typedef struct vimoption { ///< when there is a redraw flag #define P_NO_DEF_EXP 0x8000000U ///< Do not expand default value. +#define P_RWINONLY 0x10000000U ///< only redraw current window + #define HIGHLIGHT_INIT \ "8:SpecialKey,~:EndOfBuffer,z:TermCursor,Z:TermCursorNC,@:NonText," \ "d:Directory,e:ErrorMsg,i:IncSearch,l:Search,m:MoreMsg,M:ModeMsg,n:LineNr," \ "N:CursorLineNr,r:Question,s:StatusLine,S:StatusLineNC,c:VertSplit,t:Title," \ - "v:Visual,w:WarningMsg,W:WildMenu,f:Folded,F:FoldColumn," \ + "v:Visual,V:VisualNOS,w:WarningMsg,W:WildMenu,f:Folded,F:FoldColumn," \ "A:DiffAdd,C:DiffChange,D:DiffDelete,T:DiffText,>:SignColumn,-:Conceal," \ "B:SpellBad,P:SpellCap,R:SpellRare,L:SpellLocal,+:Pmenu,=:PmenuSel," \ "x:PmenuSbar,X:PmenuThumb,*:TabLine,#:TabLineSel,_:TabLineFill," \ - "!:CursorColumn,.:CursorLine,o:ColorColumn,q:QuickFixLine" + "!:CursorColumn,.:CursorLine,o:ColorColumn,q:QuickFixLine," \ + "0:Whitespace,I:NormalNC" /* * options[] is initialized here. @@ -335,7 +341,7 @@ static inline size_t compute_double_colon_len(const char *const val, do { size_t dir_len; const char *dir; - iter = vim_colon_env_iter(val, iter, &dir, &dir_len); + iter = vim_env_iter(':', val, iter, &dir, &dir_len); if (dir != NULL && dir_len > 0) { ret += ((dir_len + memcnt(dir, ',', dir_len) + common_suf_len + !after_pathsep(dir, dir + dir_len)) * 2 @@ -379,8 +385,8 @@ static inline char *add_colon_dirs(char *dest, const char *const val, do { size_t dir_len; const char *dir; - iter = (forward ? vim_colon_env_iter : vim_colon_env_iter_rev)( - val, iter, &dir, &dir_len); + iter = (forward ? vim_env_iter : vim_env_iter_rev)(':', val, iter, &dir, + &dir_len); if (dir != NULL && dir_len > 0) { dest = strcpy_comma_escaped(dest, dir, dir_len); if (!after_pathsep(dest - 1, dest)) { @@ -607,7 +613,7 @@ void set_init_1(void) /* * 'maxmemtot' and 'maxmem' may have to be adjusted for available memory */ - opt_idx = findoption((char_u *)"maxmemtot"); + opt_idx = findoption("maxmemtot"); if (opt_idx >= 0) { { /* Use half of amount of memory available to Vim. */ @@ -617,7 +623,7 @@ void set_init_1(void) ? UINTPTR_MAX : (uintptr_t)(available_kib /2); options[opt_idx].def_val[VI_DEFAULT] = (char_u *)n; - opt_idx = findoption((char_u *)"maxmem"); + opt_idx = findoption("maxmem"); if (opt_idx >= 0) { options[opt_idx].def_val[VI_DEFAULT] = (char_u *)n; } @@ -648,7 +654,7 @@ void set_init_1(void) } } buf[j] = NUL; - opt_idx = findoption((char_u *)"cdpath"); + opt_idx = findoption("cdpath"); if (opt_idx >= 0) { options[opt_idx].def_val[VI_DEFAULT] = buf; options[opt_idx].flags |= P_DEF_ALLOCED; @@ -767,8 +773,9 @@ void set_init_1(void) * NOTE: mlterm's author is being asked to 'set' a variable * instead of an environment variable due to inheritance. */ - if (os_env_exists("MLTERM")) - set_option_value((char_u *)"tbidi", 1L, NULL, 0); + if (os_env_exists("MLTERM")) { + set_option_value("tbidi", 1L, NULL, 0); + } didset_options2(); @@ -778,7 +785,7 @@ void set_init_1(void) char_u *p = enc_locale(); if (p == NULL) { // use utf-8 as 'default' if locale encoding can't be detected. - p = vim_strsave((char_u *)"utf-8"); + p = (char_u *)xmemdupz(S_LEN("utf-8")); } fenc_default = p; @@ -885,7 +892,7 @@ set_options_default ( static void set_string_default(const char *name, char *val, bool allocated) FUNC_ATTR_NONNULL_ALL { - int opt_idx = findoption((char_u *)name); + int opt_idx = findoption(name); if (opt_idx >= 0) { if (options[opt_idx].flags & P_DEF_ALLOCED) { xfree(options[opt_idx].def_val[VI_DEFAULT]); @@ -907,9 +914,10 @@ void set_number_default(char *name, long val) { int opt_idx; - opt_idx = findoption((char_u *)name); - if (opt_idx >= 0) + opt_idx = findoption(name); + if (opt_idx >= 0) { options[opt_idx].def_val[VI_DEFAULT] = (char_u *)val; + } } #if defined(EXITFREE) @@ -937,11 +945,8 @@ void free_all_options(void) #endif -/* - * Initialize the options, part two: After getting Rows and Columns and - * setting 'term'. - */ -void set_init_2(void) +/// Initialize the options, part two: After getting Rows and Columns. +void set_init_2(bool headless) { int idx; @@ -950,20 +955,29 @@ void set_init_2(void) * wrong when the window height changes. */ set_number_default("scroll", Rows / 2); - idx = findoption((char_u *)"scroll"); - if (idx >= 0 && !(options[idx].flags & P_WAS_SET)) + idx = findoption("scroll"); + if (idx >= 0 && !(options[idx].flags & P_WAS_SET)) { set_option_default(idx, OPT_LOCAL, p_cp); + } comp_col(); /* * 'window' is only for backwards compatibility with Vi. * Default is Rows - 1. */ - if (!option_was_set((char_u *)"window")) + if (!option_was_set("window")) { p_window = Rows - 1; + } set_number_default("window", Rows - 1); - parse_shape_opt(SHAPE_CURSOR); /* set cursor shapes from 'guicursor' */ - (void)parse_printoptions(); /* parse 'printoptions' default value */ +#if 0 + // This bodges around problems that should be fixed in the TUI layer. + if (!headless && !os_term_is_nice()) { + set_string_option_direct((char_u *)"guicursor", -1, (char_u *)"", + OPT_GLOBAL, SID_NONE); + } +#endif + parse_shape_opt(SHAPE_CURSOR); // set cursor shapes from 'guicursor' + (void)parse_printoptions(); // parse 'printoptions' default value } /* @@ -979,16 +993,18 @@ void set_init_3(void) int idx_sp; int do_sp; - idx_srr = findoption((char_u *)"srr"); - if (idx_srr < 0) - do_srr = FALSE; - else + idx_srr = findoption("srr"); + if (idx_srr < 0) { + do_srr = false; + } else { do_srr = !(options[idx_srr].flags & P_WAS_SET); - idx_sp = findoption((char_u *)"sp"); - if (idx_sp < 0) - do_sp = FALSE; - else + } + idx_sp = findoption("sp"); + if (idx_sp < 0) { + do_sp = false; + } else { do_sp = !(options[idx_sp].flags & P_WAS_SET); + } size_t len = 0; char_u *p = (char_u *)invocation_path_tail(p_sh, &len); @@ -1032,7 +1048,7 @@ void set_init_3(void) } if (bufempty()) { - int idx_ffs = findoption((char_u *)"ffs"); + int idx_ffs = findoption_len(S_LEN("ffs")); // Apply the first entry of 'fileformats' to the initial buffer. if (idx_ffs >= 0 && (options[idx_ffs].flags & P_WAS_SET)) { @@ -1049,16 +1065,20 @@ void set_init_3(void) */ void set_helplang_default(const char *lang) { - int idx; + if (lang == NULL) { + return; + } - if (lang == NULL || STRLEN(lang) < 2) /* safety check */ + const size_t lang_len = strlen(lang); + if (lang_len < 2) { // safety check return; - idx = findoption((char_u *)"hlg"); + } + int idx = findoption("hlg"); if (idx >= 0 && !(options[idx].flags & P_WAS_SET)) { if (options[idx].flags & P_ALLOCED) free_string_option(p_hlg); - p_hlg = (char_u *)xstrdup(lang); - /* zh_CN becomes "cn", zh_TW becomes "tw". */ + p_hlg = (char_u *)xmemdupz(lang, lang_len); + // zh_CN becomes "cn", zh_TW becomes "tw". if (STRNICMP(p_hlg, "zh_", 3) == 0 && STRLEN(p_hlg) >= 5) { p_hlg[0] = (char_u)TOLOWER_ASC(p_hlg[3]); p_hlg[1] = (char_u)TOLOWER_ASC(p_hlg[4]); @@ -1085,12 +1105,12 @@ void set_title_defaults(void) * icon name. Saves a bit of time, because the X11 display server does * not need to be contacted. */ - idx1 = findoption((char_u *)"title"); + idx1 = findoption("title"); if (idx1 >= 0 && !(options[idx1].flags & P_WAS_SET)) { options[idx1].def_val[VI_DEFAULT] = (char_u *)(intptr_t)0; p_title = 0; } - idx1 = findoption((char_u *)"icon"); + idx1 = findoption("icon"); if (idx1 >= 0 && !(options[idx1].flags & P_WAS_SET)) { options[idx1].def_val[VI_DEFAULT] = (char_u *)(intptr_t)0; p_icon = 0; @@ -1127,7 +1147,7 @@ do_set ( int afterchar; /* character just after option name */ int len; int i; - long value; + varnumber_T value; int key; uint32_t flags; /* flags for current option */ char_u *varp = NULL; /* pointer to variable for current option */ @@ -1165,10 +1185,6 @@ do_set ( showoptions(1, opt_flags); did_show = TRUE; } - } else if (STRNCMP(arg, "termcap", - 7) == 0 && !(opt_flags & OPT_MODELINE)) { - did_show = TRUE; - arg += 7; } else { prefix = 1; if (STRNCMP(arg, "no", 2) == 0) { @@ -1196,7 +1212,7 @@ do_set ( goto skip; } if (arg[1] == 't' && arg[2] == '_') { // could be term code - opt_idx = findoption_len(arg + 1, (size_t) (len - 1)); + opt_idx = findoption_len((const char *)arg + 1, (size_t)(len - 1)); } len++; if (opt_idx == -1) { @@ -1212,7 +1228,7 @@ do_set ( len++; } } - opt_idx = findoption_len(arg, (size_t) len); + opt_idx = findoption_len((const char *)arg, (size_t)len); if (opt_idx == -1) { key = find_key_option(arg); } @@ -1394,10 +1410,10 @@ do_set ( value = prefix; } - errmsg = set_bool_option(opt_idx, varp, (int)value, - opt_flags); - } else { /* numeric or string */ - if (vim_strchr((char_u *)"=:&<", nextchar) == NULL + errmsg = (char_u *)set_bool_option(opt_idx, varp, (int)value, + opt_flags); + } else { // Numeric or string. + if (vim_strchr((const char_u *)"=:&<", nextchar) == NULL || prefix != 1) { errmsg = e_invarg; goto skip; @@ -1451,15 +1467,19 @@ do_set ( goto skip; } - if (adding) + if (adding) { value = *(long *)varp + value; - if (prepending) + } + if (prepending) { value = *(long *)varp * value; - if (removing) + } + if (removing) { value = *(long *)varp - value; - errmsg = set_num_option(opt_idx, varp, value, - errbuf, sizeof(errbuf), opt_flags); - } else if (opt_idx >= 0) { /* string */ + } + errmsg = (char_u *)set_num_option(opt_idx, varp, (long)value, + errbuf, sizeof(errbuf), + opt_flags); + } else if (opt_idx >= 0) { // String. char_u *save_arg = NULL; char_u *s = NULL; char_u *oldval = NULL; // previous value if *varp @@ -1493,7 +1513,7 @@ do_set ( new_value_alloced = true; if (newval == NULL) { newval = empty_option; - } else if (!(options[opt_idx].flags | P_NO_DEF_EXP)) { + } else if (!(options[opt_idx].flags & P_NO_DEF_EXP)) { s = option_expand(opt_idx, newval); if (s == NULL) { s = newval; @@ -1931,15 +1951,7 @@ did_set_title ( { if (starting != NO_SCREEN) { maketitle(); - if (icon) { - if (!p_icon) { - ui_set_icon(NULL); - } - } else { - if (!p_title) { - ui_set_title(NULL); - } - } + resettitle(); } } @@ -2111,7 +2123,7 @@ static void didset_options(void) static void didset_options2(void) { // Initialize the highlight_attr[] table. - (void)highlight_changed(); + highlight_changed(); // Parse default for 'clipboard'. (void)opt_strings_flags(p_cb, p_cb_values, &cb_flags, true); @@ -2152,6 +2164,7 @@ void check_buf_options(buf_T *buf) check_string_option(&buf->b_p_inex); check_string_option(&buf->b_p_inde); check_string_option(&buf->b_p_indk); + check_string_option(&buf->b_p_fp); check_string_option(&buf->b_p_fex); check_string_option(&buf->b_p_kp); check_string_option(&buf->b_p_mps); @@ -2223,7 +2236,7 @@ static void check_string_option(char_u **pp) */ int was_set_insecurely(char_u *opt, int opt_flags) { - int idx = findoption(opt); + int idx = findoption((const char *)opt); if (idx >= 0) { uint32_t *flagp = insecure_flag(idx, opt_flags); @@ -2285,9 +2298,9 @@ set_string_option_direct ( int both = (opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0; int idx = opt_idx; - if (idx == -1) { /* use name */ - idx = findoption(name); - if (idx < 0) { /* not found (should not happen) */ + if (idx == -1) { // Use name. + idx = findoption((const char *)name); + if (idx < 0) { // Not found (should not happen). EMSG2(_(e_intern2), "set_string_option_direct()"); EMSG2(_("For option %s"), name); return; @@ -2440,12 +2453,11 @@ did_set_string_option ( if ((secure || sandbox != 0) && (options[opt_idx].flags & P_SECURE)) { errmsg = e_secure; - } - /* Check for a "normal" file name in some options. Disallow a path - * separator (slash and/or backslash), wildcards and characters that are - * often illegal in a file name. */ - else if ((options[opt_idx].flags & P_NFNAME) - && vim_strpbrk(*varp, (char_u *)"/\\*?[|<>") != NULL) { + } else if ((options[opt_idx].flags & P_NFNAME) + && vim_strpbrk(*varp, (char_u *)"/\\*?[|;&<>\r\n") != NULL) { + // Check for a "normal" file name in some options. Disallow a path + // separator (slash and/or backslash), wildcards and characters that are + // often illegal in a file name. errmsg = e_invarg; } /* 'backupcopy' */ @@ -2524,11 +2536,11 @@ did_set_string_option ( if (s[2] == NUL) break; } - } - /* 'highlight' */ - else if (varp == &p_hl) { - if (highlight_changed() == FAIL) - errmsg = e_invarg; /* invalid flags */ + } else if (varp == &p_hl) { + // 'highlight' + if (strcmp((char *)(*varp), HIGHLIGHT_INIT) != 0) { + errmsg = e_unsupportedoption; + } } /* 'nrformats' */ else if (gvarp == &p_nf) { @@ -2567,12 +2579,11 @@ did_set_string_option ( init_highlight(FALSE, FALSE); - if (dark != (*p_bg == 'd') - && get_var_value((char_u *)"g:colors_name") != NULL) { - /* The color scheme must have set 'background' back to another - * value, that's not what we want here. Disable the color - * scheme and set the colors again. */ - do_unlet((char_u *)"g:colors_name", TRUE); + if (dark != (*p_bg == 'd') && get_var_value("g:colors_name") != NULL) { + // The color scheme must have set 'background' back to another + // value, that's not what we want here. Disable the color + // scheme and set the colors again. + do_unlet(S_LEN("g:colors_name"), true); free_string_option(p_bg); p_bg = vim_strsave((char_u *)(dark ? "dark" : "light")); check_string_option(&p_bg); @@ -2626,7 +2637,7 @@ did_set_string_option ( if (varp == &p_enc) { // only encoding=utf-8 allowed if (STRCMP(p_enc, "utf-8") != 0) { - errmsg = e_invarg; + errmsg = e_unsupportedoption; } } } @@ -2768,7 +2779,7 @@ did_set_string_option ( // option. opt_idx = ((options[opt_idx].fullname[0] == 'v') ? (shada_idx == -1 - ? ((shada_idx = findoption((char_u *) "shada"))) + ? ((shada_idx = findoption("shada"))) : shada_idx) : opt_idx); // Update free_oldval now that we have the opt_idx for 'shada', otherwise @@ -2829,9 +2840,10 @@ did_set_string_option ( } } - /* 'guicursor' */ - else if (varp == &p_guicursor) + // 'guicursor' + else if (varp == &p_guicursor) { errmsg = parse_shape_opt(SHAPE_CURSOR); + } else if (varp == &p_popt) errmsg = parse_printoptions(); @@ -3017,7 +3029,7 @@ did_set_string_option ( /* 'pastetoggle': translate key codes like in a mapping */ else if (varp == &p_pt) { if (*p_pt) { - (void)replace_termcodes(p_pt, STRLEN(p_pt), &p, true, true, false, + (void)replace_termcodes(p_pt, STRLEN(p_pt), &p, true, true, true, CPO_TO_CPO_FLAGS); if (p != NULL) { if (new_value_alloced) @@ -3152,6 +3164,10 @@ did_set_string_option ( if (!valid_filetype(*varp)) { errmsg = e_invarg; } + } else if (varp == &curwin->w_p_winhl) { + if (!parse_winhl_opt(curwin)) { + errmsg = e_invarg; + } } else { // Options that are a list of flags. p = NULL; @@ -3189,8 +3205,6 @@ did_set_string_option ( */ if (did_chartab) (void)init_chartab(); - if (varp == &p_hl) - (void)highlight_changed(); } else { /* Remember where the option was set. */ set_option_scriptID_idx(opt_idx, opt_flags, current_SID); @@ -3256,7 +3270,7 @@ did_set_string_option ( if (varp == &p_mouse) { if (*p_mouse == NUL) { - ui_mouse_off(); + ui_call_mouse_off(); } else { setmouse(); // in case 'mouse' changed } @@ -3409,15 +3423,18 @@ static char_u *set_chars_option(char_u **varp) && p[len] == ':' && p[len + 1] != NUL) { s = p + len + 1; - c1 = mb_ptr2char_adv(&s); - if (mb_char2cells(c1) > 1) + c1 = mb_ptr2char_adv((const char_u **)&s); + if (mb_char2cells(c1) > 1) { continue; + } if (tab[i].cp == &lcs_tab2) { - if (*s == NUL) + if (*s == NUL) { continue; - c2 = mb_ptr2char_adv(&s); - if (mb_char2cells(c2) > 1) + } + c2 = mb_ptr2char_adv((const char_u **)&s); + if (mb_char2cells(c2) > 1) { continue; + } } if (*s == ',' || *s == NUL) { if (round) { @@ -3557,6 +3574,47 @@ static char_u *compile_cap_prog(synblock_T *synblock) return NULL; } +/// Handle setting `winhighlight' in window "wp" +static bool parse_winhl_opt(win_T *wp) +{ + int w_hl_id_normal = 0; + int w_hl_ids[HLF_COUNT] = { 0 }; + int hlf; + + const char *p = (const char *)wp->w_p_winhl; + while (*p) { + char *colon = strchr(p, ':'); + if (!colon) { + return false; + } + size_t nlen = (size_t)(colon-p); + char *hi = colon+1; + char *commap = xstrchrnul(hi, ','); + int hl_id = syn_check_group((char_u *)hi, (int)(commap-hi)); + + if (strncmp("Normal", p, nlen) == 0) { + w_hl_id_normal = hl_id; + } else { + for (hlf = 0; hlf < (int)HLF_COUNT; hlf++) { + if (strncmp(hlf_names[hlf], p, nlen) == 0) { + w_hl_ids[hlf] = hl_id; + break; + } + } + if (hlf == HLF_COUNT) { + return false; + } + } + + p = *commap ? commap+1 : ""; + } + + wp->w_hl_id_normal = w_hl_id_normal; + memcpy(wp->w_hl_ids, w_hl_ids, sizeof(w_hl_ids)); + wp->w_hl_needs_update = true; + return true; +} + /* * Set the scriptID for an option, taking care of setting the buffer- or * window-local value. @@ -3578,24 +3636,24 @@ static void set_option_scriptID_idx(int opt_idx, int opt_flags, int id) } } -/* - * Set the value of a boolean option, and take care of side effects. - * Returns NULL for success, or an error message for an error. - */ -static char_u * -set_bool_option ( - int opt_idx, /* index in options[] table */ - char_u *varp, /* pointer to the option variable */ - int value, /* new value */ - int opt_flags /* OPT_LOCAL and/or OPT_GLOBAL */ -) +/// Set the value of a boolean option, taking care of side effects +/// +/// @param[in] opt_idx Option index in options[] table. +/// @param[out] varp Pointer to the option variable. +/// @param[in] value New value. +/// @param[in] opt_flags OPT_LOCAL and/or OPT_GLOBAL. +/// +/// @return NULL on success, error message on error. +static char *set_bool_option(const int opt_idx, char_u *const varp, + const int value, + const int opt_flags) { int old_value = *(int *)varp; /* Disallow changing some options from secure mode */ if ((secure || sandbox != 0) && (options[opt_idx].flags & P_SECURE)) { - return e_secure; + return (char *)e_secure; } *(int *)varp = value; /* set the new value */ @@ -3608,29 +3666,34 @@ set_bool_option ( *(int *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL) = value; // Ensure that options set to p_force_on cannot be disabled. - if ((int *)varp == &p_force_on && p_force_on == FALSE) { - p_force_on = TRUE; - return e_unsupportedoption; - } + if ((int *)varp == &p_force_on && p_force_on == false) { + p_force_on = true; + return (char *)e_unsupportedoption; // Ensure that options set to p_force_off cannot be enabled. - else if ((int *)varp == &p_force_off && p_force_off == TRUE) { - p_force_off = FALSE; - return e_unsupportedoption; - } - /* 'undofile' */ - else if ((int *)varp == &curbuf->b_p_udf || (int *)varp == &p_udf) { - /* Only take action when the option was set. When reset we do not - * delete the undo file, the option may be set again without making - * any changes in between. */ + } else if ((int *)varp == &p_force_off && p_force_off == true) { + p_force_off = false; + return (char *)e_unsupportedoption; + } else if ((int *)varp == &p_lrm) { + // 'langremap' -> !'langnoremap' + p_lnr = !p_lrm; + } else if ((int *)varp == &p_lnr) { + // 'langnoremap' -> !'langremap' + p_lrm = !p_lnr; + // 'undofile' + } else if ((int *)varp == &curbuf->b_p_udf || (int *)varp == &p_udf) { + // Only take action when the option was set. When reset we do not + // delete the undo file, the option may be set again without making + // any changes in between. if (curbuf->b_p_udf || p_udf) { char_u hash[UNDO_HASH_SIZE]; buf_T *save_curbuf = curbuf; - for (curbuf = firstbuf; curbuf != NULL; curbuf = curbuf->b_next) { - /* When 'undofile' is set globally: for every buffer, otherwise - * only for the current buffer: Try to read in the undofile, - * if one exists, the buffer wasn't changed and the buffer was - * loaded */ + FOR_ALL_BUFFERS(bp) { + curbuf = bp; + // When 'undofile' is set globally: for every buffer, otherwise + // only for the current buffer: Try to read in the undofile, + // if one exists, the buffer wasn't changed and the buffer was + // loaded if ((curbuf == save_curbuf || (opt_flags & OPT_GLOBAL) || opt_flags == 0) && !curbufIsChanged() && curbuf->b_ml.ml_mfp != NULL) { @@ -3742,8 +3805,8 @@ set_bool_option ( if (curwin->w_p_pvw) { FOR_ALL_WINDOWS_IN_TAB(win, curtab) { if (win->w_p_pvw && win != curwin) { - curwin->w_p_pvw = FALSE; - return (char_u *)N_("E590: A preview window already exists"); + curwin->w_p_pvw = false; + return N_("E590: A preview window already exists"); } } } @@ -3884,16 +3947,15 @@ set_bool_option ( "W17: Arabic requires UTF-8, do ':set encoding=utf-8'"); msg_source(hl_attr(HLF_W)); - MSG_ATTR(_(w_arabic), hl_attr(HLF_W)); + msg_attr(_(w_arabic), hl_attr(HLF_W)); set_vim_var_string(VV_WARNINGMSG, _(w_arabic), -1); } /* set 'delcombine' */ p_deco = TRUE; - /* Force-set the necessary keymap for arabic */ - set_option_value((char_u *)"keymap", 0L, (char_u *)"arabic", - OPT_LOCAL); + // Force-set the necessary keymap for arabic. + set_option_value("keymap", 0L, "arabic", OPT_LOCAL); p_altkeymap = 0; p_hkmap = 0; p_fkmap = 0; @@ -3959,20 +4021,18 @@ set_bool_option ( return NULL; } -/* - * Set the value of a number option, and take care of side effects. - * Returns NULL for success, or an error message for an error. - */ -static char_u * -set_num_option ( - int opt_idx, /* index in options[] table */ - char_u *varp, /* pointer to the option variable */ - long value, /* new value */ - char_u *errbuf, /* buffer for error messages */ - size_t errbuflen, /* length of "errbuf" */ - int opt_flags /* OPT_LOCAL, OPT_GLOBAL and - OPT_MODELINE */ -) +/// Set the value of a number option, taking care of side effects +/// +/// @param[in] opt_idx Option index in options[] table. +/// @param[out] varp Pointer to the option variable. +/// @param[in] value New value. +/// @param errbuf Buffer for error messages. +/// @param[in] errbuflen Length of `errbuf`. +/// @param[in] opt_flags OPT_LOCAL, OPT_GLOBAL or OPT_MODELINE. +/// +/// @return NULL on success, error message on error. +static char *set_num_option(int opt_idx, char_u *varp, long value, + char_u *errbuf, size_t errbuflen, int opt_flags) { char_u *errmsg = NULL; long old_value = *(long *)varp; @@ -3983,7 +4043,7 @@ set_num_option ( /* Disallow changing some options from secure mode. */ if ((secure || sandbox != 0) && (options[opt_idx].flags & P_SECURE)) { - return e_secure; + return (char *)e_secure; } *pp = value; @@ -4013,7 +4073,7 @@ set_num_option ( } /* Change window height NOW */ - if (lastwin != firstwin) { + if (!ONE_WINDOW) { if (pp == &p_wh && curwin->w_height < p_wh) win_setheight((int)p_wh); if (pp == &p_hh && curbuf->b_help && curwin->w_height < p_hh) @@ -4042,7 +4102,7 @@ set_num_option ( } /* Change window width NOW */ - if (lastwin != firstwin && curwin->w_width < p_wiw) + if (!ONE_WINDOW && curwin->w_width < p_wiw) win_setwidth((int)p_wiw); } /* 'winminwidth' */ @@ -4200,7 +4260,16 @@ set_num_option ( FOR_ALL_TAB_WINDOWS(tp, wp) { check_colorcolumn(wp); } - + } else if (pp == &curbuf->b_p_scbk || pp == &p_scbk) { + // 'scrollback' + if (*pp < -1 || *pp > SB_MAX + || (*pp != -1 && opt_flags == OPT_LOCAL && !curbuf->terminal)) { + errmsg = e_invarg; + *pp = old_value; + } else if (curbuf->terminal) { + // Force the scrollback to take effect. + terminal_resize(curbuf->terminal, UINT16_MAX, UINT16_MAX); + } } /* @@ -4244,8 +4313,9 @@ set_num_option ( cmdline_row = (int)(Rows - p_ch); } } - if (p_window >= Rows || !option_was_set((char_u *)"window")) + if (p_window >= Rows || !option_was_set("window")) { p_window = Rows - 1; + } } if (curbuf->b_p_ts <= 0) { @@ -4320,6 +4390,11 @@ set_num_option ( if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0) *(long *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL) = *pp; + if (pp == &curbuf->b_p_scbk && !curbuf->terminal) { + // Normal buffer: reset local 'scrollback' after updating the global value. + curbuf->b_p_scbk = -1; + } + options[opt_idx].flags |= P_WAS_SET; if (!starting && errmsg == NULL) { @@ -4345,7 +4420,7 @@ set_num_option ( curwin->w_set_curswant = TRUE; check_redraw(options[opt_idx].flags); - return errmsg; + return (char *)errmsg; } /* @@ -4357,17 +4432,24 @@ static void check_redraw(uint32_t flags) bool doclear = (flags & P_RCLR) == P_RCLR; bool all = ((flags & P_RALL) == P_RALL || doclear); - if ((flags & P_RSTAT) || all) /* mark all status lines dirty */ + if ((flags & P_RSTAT) || all) { // mark all status lines dirty status_redraw_all(); + } - if ((flags & P_RBUF) || (flags & P_RWIN) || all) + if ((flags & P_RBUF) || (flags & P_RWIN) || all) { changed_window_setting(); - if (flags & P_RBUF) + } + if (flags & P_RBUF) { redraw_curbuf_later(NOT_VALID); - if (doclear) + } + if (flags & P_RWINONLY) { + redraw_later(NOT_VALID); + } + if (doclear) { redraw_all_later(CLEAR); - else if (all) + } else if (all) { redraw_all_later(NOT_VALID); + } } /// Find index for named option @@ -4376,39 +4458,36 @@ static void check_redraw(uint32_t flags) /// @param[in] len Length of the option. /// /// @return Index of the option or -1 if option was not found. -int findoption_len(const char_u *const arg, const size_t len) +int findoption_len(const char *const arg, const size_t len) { - char *s, *p; + const char *s; + const char *p; static int quick_tab[27] = { 0, 0 }; // quick access table - int is_term_opt; - /* - * For first call: Initialize the quick-access table. - * It contains the index for the first option that starts with a certain - * letter. There are 26 letters, plus the first "t_" option. - */ + // For first call: Initialize the quick-access table. + // It contains the index for the first option that starts with a certain + // letter. There are 26 letters, plus the first "t_" option. if (quick_tab[1] == 0) { p = options[0].fullname; for (short int i = 1; (s = options[i].fullname) != NULL; i++) { if (s[0] != p[0]) { - if (s[0] == 't' && s[1] == '_') + if (s[0] == 't' && s[1] == '_') { quick_tab[26] = i; - else + } else { quick_tab[CharOrdLow(s[0])] = i; + } } p = s; } } - /* - * Check for name starting with an illegal character. - */ + // Check for name starting with an illegal character. if (len == 0 || arg[0] < 'a' || arg[0] > 'z') { return -1; } int opt_idx; - is_term_opt = (len > 2 && arg[0] == 't' && arg[1] == '_'); + const bool is_term_opt = (len > 2 && arg[0] == 't' && arg[1] == '_'); if (is_term_opt) { opt_idx = quick_tab[26]; } else { @@ -4416,7 +4495,7 @@ int findoption_len(const char_u *const arg, const size_t len) } // Match full name for (; (s = options[opt_idx].fullname) != NULL; opt_idx++) { - if (STRNCMP(arg, s, len) == 0 && s[len] == NUL) { + if (strncmp(arg, s, len) == 0 && s[len] == NUL) { break; } } @@ -4425,20 +4504,22 @@ int findoption_len(const char_u *const arg, const size_t len) // Match short name for (; options[opt_idx].fullname != NULL; opt_idx++) { s = options[opt_idx].shortname; - if (s != NULL && STRNCMP(arg, s, len) == 0 && s[len] == NUL) { + if (s != NULL && strncmp(arg, s, len) == 0 && s[len] == NUL) { break; } s = NULL; } } - if (s == NULL) + if (s == NULL) { opt_idx = -1; + } return opt_idx; } -bool is_tty_option(char *name) +bool is_tty_option(const char *name) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT { - return (name[0] == 't' && name[1] == '_') || !strcmp((char *)name, "term"); + return (name[0] == 't' && name[1] == '_') || strcmp(name, "term") == 0; } #define TCO_BUFFER_SIZE 8 @@ -4474,7 +4555,7 @@ bool get_tty_option(char *name, char **value) return false; } -bool set_tty_option(char *name, char *value) +bool set_tty_option(const char *name, const char *value) { if (!strcmp(name, "t_Co")) { int colors = atoi(value); @@ -4485,23 +4566,24 @@ bool set_tty_option(char *name, char *value) if (colors != t_colors) { t_colors = colors; // We now have a different color setup, initialize it again. - init_highlight(TRUE, FALSE); + init_highlight(true, false); } return true; } - return is_tty_option(name) || !strcmp(name, "term") - || !strcmp(name, "ttytype"); + return (is_tty_option(name) || !strcmp(name, "term") + || !strcmp(name, "ttytype")); } -/* - * Find index for option 'arg'. - * Return -1 if not found. - */ -static int findoption(char_u *arg) +/// Find index for an option +/// +/// @param[in] arg Option name. +/// +/// @return Option index or -1 if option was not found. +static int findoption(const char *const arg) { - return findoption_len(arg, STRLEN(arg)); + return findoption_len(arg, strlen(arg)); } /* @@ -4529,9 +4611,10 @@ get_option_value ( int opt_idx; char_u *varp; - opt_idx = findoption(name); - if (opt_idx < 0) /* unknown option */ + opt_idx = findoption((const char *)name); + if (opt_idx < 0) { // Unknown option. return -3; + } varp = get_varp_scope(&(options[opt_idx]), opt_flags); @@ -4554,7 +4637,7 @@ get_option_value ( if ((int *)varp == &curbuf->b_changed) { *numval = curbufIsChanged(); } else { - *numval = *(int *)varp; + *numval = (long) *(int *)varp; // NOLINT(whitespace/cast) } } return 1; @@ -4568,7 +4651,7 @@ get_option_value ( // // Pretends that option is absent if it is not present in the requested scope // (i.e. has no global, window-local or buffer-local value depending on -// opt_type). Uses +// opt_type). // // Returned flags: // 0 hidden or unknown option, also option that does not have requested @@ -4587,14 +4670,13 @@ int get_option_value_strict(char *name, } char_u *varp = NULL; - vimoption_T *p; int rv = 0; - int opt_idx = findoption((uint8_t *)name); + int opt_idx = findoption(name); if (opt_idx < 0) { return 0; } - p = &(options[opt_idx]); + vimoption_T *p = &options[opt_idx]; // Hidden option if (p->var == NULL) { @@ -4610,26 +4692,25 @@ int get_option_value_strict(char *name, } if (p->indir == PV_NONE) { - if (opt_type == SREQ_GLOBAL) + if (opt_type == SREQ_GLOBAL) { rv |= SOPT_GLOBAL; - else - return 0; // Did not request global-only option + } else { + return 0; // Did not request global-only option + } } else { if (p->indir & PV_BOTH) { rv |= SOPT_GLOBAL; - } else if (opt_type == SREQ_GLOBAL) { - return 0; // Requested global option } if (p->indir & PV_WIN) { if (opt_type == SREQ_BUF) { - return 0; // Did not request window-local option + return 0; // Requested buffer-local, not window-local option } else { rv |= SOPT_WIN; } } else if (p->indir & PV_BUF) { if (opt_type == SREQ_WIN) { - return 0; // Did not request buffer-local option + return 0; // Requested window-local, not buffer-local option } else { rv |= SOPT_BUF; } @@ -4641,7 +4722,11 @@ int get_option_value_strict(char *name, } if (opt_type == SREQ_GLOBAL) { - varp = p->var; + if (p->var == VAR_WIN) { + return 0; + } else { + varp = p->var; + } } else { if (opt_type == SREQ_BUF) { // Special case: 'modified' is b_changed, but we also want to @@ -4683,21 +4768,19 @@ int get_option_value_strict(char *name, return rv; } -/* - * Set the value of option "name". - * Use "string" for string options, use "number" for other options. - * - * Returns NULL on success or error message on error. - */ -char_u * -set_option_value ( - char_u *name, - long number, - char_u *string, - int opt_flags /* OPT_LOCAL or 0 (both) */ -) +/// Set the value of an option +/// +/// @param[in] name Option name. +/// @param[in] number New value for the number or boolean option. +/// @param[in] string New value for string option. +/// @param[in] opt_flags Flags: OPT_LOCAL, OPT_GLOBAL, or 0 (both). +/// +/// @return NULL on success, error message on error. +char *set_option_value(const char *const name, const long number, + const char *const string, const int opt_flags) + FUNC_ATTR_NONNULL_ARG(1) { - if (set_tty_option((char *)name, (char *)string)) { + if (set_tty_option(name, string)) { return NULL; } @@ -4705,9 +4788,9 @@ set_option_value ( char_u *varp; opt_idx = findoption(name); - if (opt_idx < 0) + if (opt_idx < 0) { EMSG2(_("E355: Unknown option: %s"), name); - else { + } else { uint32_t flags = options[opt_idx].flags; // Disallow changing some options in the sandbox if (sandbox > 0 && (flags & P_SECURE)) { @@ -4715,11 +4798,11 @@ set_option_value ( return NULL; } if (flags & P_STRING) { - const char *s = (const char *)string; + const char *s = string; if (s == NULL) { s = ""; } - return (char_u *)set_string_option(opt_idx, s, opt_flags); + return set_string_option(opt_idx, s, opt_flags); } else { varp = get_varp_scope(&(options[opt_idx]), opt_flags); if (varp != NULL) { /* hidden option is not changed */ @@ -4738,28 +4821,17 @@ set_option_value ( return NULL; // do nothing as we hit an error } } - if (flags & P_NUM) - return set_num_option(opt_idx, varp, number, - NULL, 0, opt_flags); - else - return set_bool_option(opt_idx, varp, (int)number, - opt_flags); + if (flags & P_NUM) { + return set_num_option(opt_idx, varp, number, NULL, 0, opt_flags); + } else { + return set_bool_option(opt_idx, varp, (int)number, opt_flags); + } } } } return NULL; } -char_u *get_highlight_default(void) -{ - int i; - - i = findoption((char_u *)"hl"); - if (i >= 0) - return options[i].def_val[VI_DEFAULT]; - return (char_u *)NULL; -} - /* * Translate a string like "t_xx", "<t_xx>" or "<S-Tab>" to a key number. */ @@ -4775,7 +4847,7 @@ int find_key_option_len(const char_u *arg, size_t len) } else { arg--; // put arg at the '<' modifiers = 0; - key = find_special_key(&arg, len + 1, &modifiers, true, true); + key = find_special_key(&arg, len + 1, &modifiers, true, true, false); if (modifiers) { // can't handle modifiers here key = 0; } @@ -5101,9 +5173,13 @@ static int put_setstring(FILE *fd, char *cmd, char *name, char_u **valuep, int e * CTRL-V or backslash */ if (valuep == &p_pt) { s = *valuep; - while (*s != NUL) - if (put_escstr(fd, str2special(&s, FALSE), 2) == FAIL) + while (*s != NUL) { + if (put_escstr(fd, (char_u *)str2special((const char **)&s, false, + false), 2) + == FAIL) { return FAIL; + } + } } else if (expand) { buf = xmalloc(MAXPATHL); home_replace(NULL, *valuep, buf, MAXPATHL, FALSE); @@ -5158,7 +5234,7 @@ static int put_setbool(FILE *fd, char *cmd, char *name, int value) void comp_col(void) { - int last_has_status = (p_ls == 2 || (p_ls == 1 && firstwin != lastwin)); + int last_has_status = (p_ls == 2 || (p_ls == 1 && !ONE_WINDOW)); sc_col = 0; ru_col = 0; @@ -5193,7 +5269,7 @@ void unset_global_local_option(char *name, void *from) vimoption_T *p; buf_T *buf = (buf_T *)from; - int opt_idx = findoption((uint8_t *)name); + int opt_idx = findoption(name); if (opt_idx < 0) { EMSG2(_("E355: Unknown option: %s"), name); return; @@ -5238,6 +5314,9 @@ void unset_global_local_option(char *name, void *from) case PV_TSR: clear_string_option(&buf->b_p_tsr); break; + case PV_FP: + clear_string_option(&buf->b_p_fp); + break; case PV_EFM: clear_string_option(&buf->b_p_efm); break; @@ -5271,6 +5350,7 @@ static char_u *get_varp_scope(vimoption_T *p, int opt_flags) } if ((opt_flags & OPT_LOCAL) && ((int)p->indir & PV_BOTH)) { switch ((int)p->indir) { + case PV_FP: return (char_u *)&(curbuf->b_p_fp); case PV_EFM: return (char_u *)&(curbuf->b_p_efm); case PV_GP: return (char_u *)&(curbuf->b_p_gp); case PV_MP: return (char_u *)&(curbuf->b_p_mp); @@ -5329,6 +5409,8 @@ static char_u *get_varp(vimoption_T *p) ? (char_u *)&(curbuf->b_p_dict) : p->var; case PV_TSR: return *curbuf->b_p_tsr != NUL ? (char_u *)&(curbuf->b_p_tsr) : p->var; + case PV_FP: return *curbuf->b_p_fp != NUL + ? (char_u *)&(curbuf->b_p_fp) : p->var; case PV_EFM: return *curbuf->b_p_efm != NUL ? (char_u *)&(curbuf->b_p_efm) : p->var; case PV_GP: return *curbuf->b_p_gp != NUL @@ -5418,6 +5500,7 @@ static char_u *get_varp(vimoption_T *p) case PV_PI: return (char_u *)&(curbuf->b_p_pi); case PV_QE: return (char_u *)&(curbuf->b_p_qe); case PV_RO: return (char_u *)&(curbuf->b_p_ro); + case PV_SCBK: return (char_u *)&(curbuf->b_p_scbk); case PV_SI: return (char_u *)&(curbuf->b_p_si); case PV_STS: return (char_u *)&(curbuf->b_p_sts); case PV_SUA: return (char_u *)&(curbuf->b_p_sua); @@ -5434,6 +5517,7 @@ static char_u *get_varp(vimoption_T *p) case PV_WM: return (char_u *)&(curbuf->b_p_wm); case PV_KMAP: return (char_u *)&(curbuf->b_p_keymap); case PV_SCL: return (char_u *)&(curwin->w_p_scl); + case PV_WINHL: return (char_u *)&(curwin->w_p_winhl); default: EMSG(_("E356: get_varp ERROR")); } /* always return a valid pointer to avoid a crash! */ @@ -5460,7 +5544,6 @@ void win_copy_options(win_T *wp_from, win_T *wp_to) copy_winopt(&wp_from->w_allbuf_opt, &wp_to->w_allbuf_opt); /* Is this right? */ wp_to->w_farsi = wp_from->w_farsi; - briopt_check(wp_to); } /* @@ -5512,6 +5595,7 @@ void copy_winopt(winopt_T *from, winopt_T *to) to->wo_fdt = vim_strsave(from->wo_fdt); to->wo_fmr = vim_strsave(from->wo_fmr); to->wo_scl = vim_strsave(from->wo_scl); + to->wo_winhl = vim_strsave(from->wo_winhl); check_winopt(to); // don't want NULL pointers } @@ -5541,6 +5625,7 @@ static void check_winopt(winopt_T *wop) check_string_option(&wop->wo_cc); check_string_option(&wop->wo_cocu); check_string_option(&wop->wo_briopt); + check_string_option(&wop->wo_winhl); } /* @@ -5560,8 +5645,17 @@ void clear_winopt(winopt_T *wop) clear_string_option(&wop->wo_cc); clear_string_option(&wop->wo_cocu); clear_string_option(&wop->wo_briopt); + clear_string_option(&wop->wo_winhl); } +void didset_window_options(win_T *wp) +{ + check_colorcolumn(wp); + briopt_check(wp); + parse_winhl_opt(wp); +} + + /* * Copy global option values to local options for one buffer. * Used when creating a new buffer and sometimes when entering a buffer. @@ -5579,12 +5673,6 @@ void buf_copy_options(buf_T *buf, int flags) int did_isk = FALSE; /* - * Don't do anything if the buffer is invalid. - */ - if (buf == NULL || !buf_valid(buf)) - return; - - /* * Skip this when the option defaults have not been set yet. Happens when * main() allocates the first buffer. */ @@ -5625,7 +5713,22 @@ void buf_copy_options(buf_T *buf, int flags) free_buf_options(buf, TRUE); buf->b_p_ro = FALSE; /* don't copy readonly */ buf->b_p_fenc = vim_strsave(p_fenc); - buf->b_p_ff = vim_strsave(p_ff); + switch (*p_ffs) { + case 'm': + buf->b_p_ff = vim_strsave((char_u *)FF_MAC); + break; + case 'd': + buf->b_p_ff = vim_strsave((char_u *)FF_DOS); + break; + case 'u': + buf->b_p_ff = vim_strsave((char_u *)FF_UNIX); + break; + default: + buf->b_p_ff = vim_strsave(p_ff); + } + if (buf->b_p_ff != NULL) { + buf->b_start_ffc = *buf->b_p_ff; + } buf->b_p_bh = empty_option; buf->b_p_bt = empty_option; } else @@ -5634,6 +5737,7 @@ void buf_copy_options(buf_T *buf, int flags) buf->b_p_ai = p_ai; buf->b_p_ai_nopaste = p_ai_nopaste; buf->b_p_sw = p_sw; + buf->b_p_scbk = -1; buf->b_p_tw = p_tw; buf->b_p_tw_nopaste = p_tw_nopaste; buf->b_p_tw_nobin = p_tw_nobin; @@ -5681,6 +5785,7 @@ void buf_copy_options(buf_T *buf, int flags) buf->b_s.b_p_spl = vim_strsave(p_spl); buf->b_p_inde = vim_strsave(p_inde); buf->b_p_indk = vim_strsave(p_indk); + buf->b_p_fp = empty_option; buf->b_p_fex = vim_strsave(p_fex); buf->b_p_sua = vim_strsave(p_sua); buf->b_p_keymap = vim_strsave(p_keymap); @@ -5753,11 +5858,12 @@ void reset_modifiable(void) { int opt_idx; - curbuf->b_p_ma = FALSE; - p_ma = FALSE; - opt_idx = findoption((char_u *)"ma"); - if (opt_idx >= 0) - options[opt_idx].def_val[VI_DEFAULT] = FALSE; + curbuf->b_p_ma = false; + p_ma = false; + opt_idx = findoption("ma"); + if (opt_idx >= 0) { + options[opt_idx].def_val[VI_DEFAULT] = false; + } } /* @@ -5855,15 +5961,15 @@ set_context_in_set_cmd ( expand_option_name[2] = p[-2]; expand_option_name[3] = p[-1]; } else { - /* Allow * wildcard */ - while (ASCII_ISALNUM(*p) || *p == '_' || *p == '*') + // Allow * wildcard. + while (ASCII_ISALNUM(*p) || *p == '_' || *p == '*') { p++; - if (*p == NUL) + } + if (*p == NUL) { return; + } nextchar = *p; - *p = NUL; - opt_idx = findoption(arg); - *p = nextchar; + opt_idx = findoption_len((const char *)arg, (size_t)(p - arg)); if (opt_idx == -1 || options[opt_idx].var == NULL) { xp->xp_context = EXPAND_NOTHING; return; @@ -5960,8 +6066,8 @@ int ExpandSettings(expand_T *xp, regmatch_T *regmatch, int *num_file, char_u *** int count = 0; char_u *str; int loop; - static char *(names[]) = {"all", "termcap"}; - int ic = regmatch->rm_ic; /* remember the ignore-case flag */ + static char *(names[]) = { "all" }; + int ic = regmatch->rm_ic; // remember the ignore-case flag /* do this loop twice: * loop == 0: count the number of matching options @@ -6025,7 +6131,7 @@ void ExpandOldSetting(int *num_file, char_u ***file) * For a terminal key code expand_option_idx is < 0. */ if (expand_option_idx < 0) { - expand_option_idx = findoption(expand_option_name); + expand_option_idx = findoption((const char *)expand_option_name); } if (expand_option_idx >= 0) { @@ -6084,15 +6190,16 @@ option_value2string ( } } else { // P_STRING varp = *(char_u **)(varp); - if (varp == NULL) /* just in case */ + if (varp == NULL) { // Just in case. NameBuff[0] = NUL; - else if (opp->flags & P_EXPAND) - home_replace(NULL, varp, NameBuff, MAXPATHL, FALSE); - /* Translate 'pastetoggle' into special key names */ - else if ((char_u **)opp->var == &p_pt) - str2specialbuf(p_pt, NameBuff, MAXPATHL); - else + } else if (opp->flags & P_EXPAND) { + home_replace(NULL, varp, NameBuff, MAXPATHL, false); + // Translate 'pastetoggle' into special key names. + } else if ((char_u **)opp->var == &p_pt) { + str2specialbuf((const char *)p_pt, (char *)NameBuff, MAXPATHL); + } else { STRLCPY(NameBuff, varp, MAXPATHL); + } } } @@ -6425,20 +6532,22 @@ void vimrc_found(char_u *fname, char_u *envname) } } -/* - * Return TRUE when option "name" has been set. - * Only works correctly for global options. - */ -int option_was_set(char_u *name) +/// Check whether global option has been set +/// +/// @param[in] name Option name. +/// +/// @return True if it was set. +static bool option_was_set(const char *name) { int idx; idx = findoption(name); - if (idx < 0) /* unknown option */ - return FALSE; - if (options[idx].flags & P_WAS_SET) - return TRUE; - return FALSE; + if (idx < 0) { // Unknown option. + return false; + } else if (options[idx].flags & P_WAS_SET) { + return true; + } + return false; } /* @@ -6854,8 +6963,8 @@ void set_fileformat(int eol_style, int opt_flags) need_maketitle = true; // Set window title later. } -/// Skip to next part of an option argument: Skip space and comma. -char_u *skip_to_option_part(char_u *p) +/// Skip to next part of an option argument: skip space and comma +char_u *skip_to_option_part(const char_u *p) { if (*p == ',') { p++; @@ -6863,7 +6972,7 @@ char_u *skip_to_option_part(char_u *p) while (*p == ' ') { p++; } - return p; + return (char_u *)p; } /// Isolate one part of a string option separated by `sep_chars`. @@ -6923,10 +7032,11 @@ bool signcolumn_on(win_T *wp) return wp->w_buffer->b_signlist != NULL; } -/// Get window or buffer local options. -dict_T * get_winbuf_options(int bufopt) +/// Get window or buffer local options +dict_T *get_winbuf_options(const int bufopt) + FUNC_ATTR_WARN_UNUSED_RESULT { - dict_T *d = dict_alloc(); + dict_T *const d = tv_dict_alloc(); for (int opt_idx = 0; options[opt_idx].fullname; opt_idx++) { struct vimoption *opt = &options[opt_idx]; @@ -6937,9 +7047,13 @@ dict_T * get_winbuf_options(int bufopt) if (varp != NULL) { if (opt->flags & P_STRING) { - dict_add_nr_str(d, opt->fullname, 0L, *(char_u **)varp); + tv_dict_add_str(d, opt->fullname, strlen(opt->fullname), + *(const char **)varp); + } else if (opt->flags & P_NUM) { + tv_dict_add_nr(d, opt->fullname, strlen(opt->fullname), + *(long *)varp); } else { - dict_add_nr_str(d, opt->fullname, *varp, NULL); + tv_dict_add_nr(d, opt->fullname, strlen(opt->fullname), *(int *)varp); } } } diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h index 32021da922..a2fe90b3c2 100644 --- a/src/nvim/option_defs.h +++ b/src/nvim/option_defs.h @@ -16,9 +16,9 @@ #define SOPT_UNSET 0x40 // Option does not have local value set // Option types for various functions in option.c -#define SREQ_GLOBAL 0 // Request global option -#define SREQ_WIN 1 // Request window-local option -#define SREQ_BUF 2 // Request buffer-local option +#define SREQ_GLOBAL 0 // Request global option value +#define SREQ_WIN 1 // Request window-local option value +#define SREQ_BUF 2 // Request buffer-local option value /* * Default values for 'errorformat'. @@ -81,57 +81,56 @@ #define DFLT_FO_VIM "tcqj" #define FO_ALL "tcroq2vlb1mMBn,awj" /* for do_set() */ -/* characters for the p_cpo option: */ -#define CPO_ALTREAD 'a' /* ":read" sets alternate file name */ -#define CPO_ALTWRITE 'A' /* ":write" sets alternate file name */ -#define CPO_BAR 'b' /* "\|" ends a mapping */ -#define CPO_BSLASH 'B' /* backslash in mapping is not special */ +// characters for the p_cpo option: +#define CPO_ALTREAD 'a' // ":read" sets alternate file name +#define CPO_ALTWRITE 'A' // ":write" sets alternate file name +#define CPO_BAR 'b' // "\|" ends a mapping +#define CPO_BSLASH 'B' // backslash in mapping is not special #define CPO_SEARCH 'c' -#define CPO_CONCAT 'C' /* Don't concatenate sourced lines */ -#define CPO_DOTTAG 'd' /* "./tags" in 'tags' is in current dir */ -#define CPO_DIGRAPH 'D' /* No digraph after "r", "f", etc. */ +#define CPO_CONCAT 'C' // Don't concatenate sourced lines +#define CPO_DOTTAG 'd' // "./tags" in 'tags' is in current dir +#define CPO_DIGRAPH 'D' // No digraph after "r", "f", etc. #define CPO_EXECBUF 'e' -#define CPO_EMPTYREGION 'E' /* operating on empty region is an error */ -#define CPO_FNAMER 'f' /* set file name for ":r file" */ -#define CPO_FNAMEW 'F' /* set file name for ":w file" */ -#define CPO_INTMOD 'i' /* interrupt a read makes buffer modified */ -#define CPO_INDENT 'I' /* remove auto-indent more often */ -#define CPO_ENDOFSENT 'J' /* need two spaces to detect end of sentence */ -#define CPO_KEYCODE 'k' /* don't recognize raw key code in mappings */ -#define CPO_KOFFSET 'K' /* don't wait for key code in mappings */ -#define CPO_LITERAL 'l' /* take char after backslash in [] literal */ -#define CPO_LISTWM 'L' /* 'list' changes wrapmargin */ +#define CPO_EMPTYREGION 'E' // operating on empty region is an error +#define CPO_FNAMER 'f' // set file name for ":r file" +#define CPO_FNAMEW 'F' // set file name for ":w file" +#define CPO_INTMOD 'i' // interrupt a read makes buffer modified +#define CPO_INDENT 'I' // remove auto-indent more often +#define CPO_ENDOFSENT 'J' // need two spaces to detect end of sentence +#define CPO_KOFFSET 'K' // don't wait for key code in mappings +#define CPO_LITERAL 'l' // take char after backslash in [] literal +#define CPO_LISTWM 'L' // 'list' changes wrapmargin #define CPO_SHOWMATCH 'm' -#define CPO_MATCHBSL 'M' /* "%" ignores use of backslashes */ -#define CPO_NUMCOL 'n' /* 'number' column also used for text */ +#define CPO_MATCHBSL 'M' // "%" ignores use of backslashes +#define CPO_NUMCOL 'n' // 'number' column also used for text #define CPO_LINEOFF 'o' -#define CPO_OVERNEW 'O' /* silently overwrite new file */ -#define CPO_LISP 'p' /* 'lisp' indenting */ -#define CPO_FNAMEAPP 'P' /* set file name for ":w >>file" */ -#define CPO_JOINCOL 'q' /* with "3J" use column after first join */ +#define CPO_OVERNEW 'O' // silently overwrite new file +#define CPO_LISP 'p' // 'lisp' indenting +#define CPO_FNAMEAPP 'P' // set file name for ":w >>file" +#define CPO_JOINCOL 'q' // with "3J" use column after first join #define CPO_REDO 'r' -#define CPO_REMMARK 'R' /* remove marks when filtering */ +#define CPO_REMMARK 'R' // remove marks when filtering #define CPO_BUFOPT 's' #define CPO_BUFOPTGLOB 'S' #define CPO_TAGPAT 't' -#define CPO_UNDO 'u' /* "u" undoes itself */ -#define CPO_BACKSPACE 'v' /* "v" keep deleted text */ -#define CPO_FWRITE 'W' /* "w!" doesn't overwrite readonly files */ +#define CPO_UNDO 'u' // "u" undoes itself +#define CPO_BACKSPACE 'v' // "v" keep deleted text +#define CPO_FWRITE 'W' // "w!" doesn't overwrite readonly files #define CPO_ESC 'x' -#define CPO_REPLCNT 'X' /* "R" with a count only deletes chars once */ +#define CPO_REPLCNT 'X' // "R" with a count only deletes chars once #define CPO_YANK 'y' -#define CPO_KEEPRO 'Z' /* don't reset 'readonly' on ":w!" */ +#define CPO_KEEPRO 'Z' // don't reset 'readonly' on ":w!" #define CPO_DOLLAR '$' #define CPO_FILTER '!' #define CPO_MATCH '%' -#define CPO_PLUS '+' /* ":write file" resets 'modified' */ -#define CPO_SPECI '<' /* don't recognize <> in mappings */ -#define CPO_REGAPPEND '>' /* insert NL when appending to a register */ -#define CPO_SCOLON ';' /* using "," and ";" will skip over char if - * cursor would not move */ -/* default values for Vim and Vi */ -#define CPO_VIM "aABceFs" -#define CPO_VI "aAbBcCdDeEfFiIJkKlLmMnoOpPqrRsStuvWxXyZ$!%+<>;" +#define CPO_PLUS '+' // ":write file" resets 'modified' +#define CPO_REGAPPEND '>' // insert NL when appending to a register +#define CPO_SCOLON ';' // using "," and ";" will skip over char if + // cursor would not move +#define CPO_CHANGEW '_' // "cw" special-case +// default values for Vim and Vi +#define CPO_VIM "aABceFs_" +#define CPO_VI "aAbBcCdDeEfFiIJKlLmMnoOpPqrRsStuvWxXyZ$!%+>;_" /* characters for p_ww option: */ #define WW_ALL "bshl<>[],~" @@ -411,7 +410,6 @@ EXTERN char_u *p_efm; // 'errorformat' EXTERN char_u *p_gefm; // 'grepformat' EXTERN char_u *p_gp; // 'grepprg' EXTERN char_u *p_ei; // 'eventignore' -EXTERN int p_ek; // 'esckeys' EXTERN int p_exrc; // 'exrc' EXTERN char_u *p_fencs; // 'fileencodings' EXTERN char_u *p_ffs; // 'fileformats' @@ -476,8 +474,9 @@ EXTERN char_u *p_isp; // 'isprint' EXTERN int p_js; // 'joinspaces' EXTERN char_u *p_kp; // 'keywordprg' EXTERN char_u *p_km; // 'keymodel' -EXTERN char_u *p_langmap; // 'langmap'*/ -EXTERN int p_lnr; // 'langnoremap'*/ +EXTERN char_u *p_langmap; // 'langmap' +EXTERN int p_lnr; // 'langnoremap' +EXTERN int p_lrm; // 'langremap' EXTERN char_u *p_lm; // 'langmenu' EXTERN char_u *p_lispwords; // 'lispwords' EXTERN long p_ls; // 'laststatus' @@ -524,6 +523,7 @@ EXTERN int p_ru; // 'ruler' EXTERN char_u *p_ruf; // 'rulerformat' EXTERN char_u *p_pp; // 'packpath' EXTERN char_u *p_rtp; // 'runtimepath' +EXTERN long p_scbk; // 'scrollback' EXTERN long p_sj; // 'scrolljump' EXTERN long p_so; // 'scrolloff' EXTERN char_u *p_sbo; // 'scrollopt' @@ -602,11 +602,14 @@ EXTERN int p_tbs; ///< 'tagbsearch' EXTERN char_u *p_tc; ///< 'tagcase' EXTERN unsigned tc_flags; ///< flags from 'tagcase' #ifdef IN_OPTION_C -static char *(p_tc_values[]) = { "followic", "ignore", "match", NULL }; +static char *(p_tc_values[]) = + { "followic", "ignore", "match", "followscs", "smart", NULL }; #endif #define TC_FOLLOWIC 0x01 #define TC_IGNORE 0x02 #define TC_MATCH 0x04 +#define TC_FOLLOWSCS 0x08 +#define TC_SMART 0x10 EXTERN long p_tl; ///< 'taglength' EXTERN int p_tr; ///< 'tagrelative' EXTERN char_u *p_tags; ///< 'tags' @@ -710,6 +713,7 @@ enum { , BV_EP , BV_ET , BV_FENC + , BV_FP , BV_BEXPR , BV_FEX , BV_FF @@ -737,6 +741,7 @@ enum { , BV_PI , BV_QE , BV_RO + , BV_SCBK , BV_SI , BV_SMC , BV_SYN @@ -800,10 +805,13 @@ enum { , WV_WFW , WV_WRAP , WV_SCL + , WV_WINHL , WV_COUNT // must be the last one }; /* Value for b_p_ul indicating the global value must be used. */ #define NO_LOCAL_UNDOLEVEL -123456 +#define SB_MAX 100000 // Maximum 'scrollback' value. + #endif // NVIM_OPTION_DEFS_H diff --git a/src/nvim/options.lua b/src/nvim/options.lua index 70d1f73cf4..103227f6b5 100644 --- a/src/nvim/options.lua +++ b/src/nvim/options.lua @@ -17,8 +17,8 @@ -- types: bool, number, string -- lists: (nil), comma, onecomma, flags, flagscomma -- scopes: global, buffer, window --- redraw options: statuslines, current_window, current_buffer, all_windows, --- everything, curswant +-- redraw options: statuslines, current_window, curent_window_only, +-- current_buffer, all_windows, everything, curswant -- default: {vi=โฆ[, vim=โฆ]} -- defaults: {condition=#if condition, if_true=default, if_false=default} -- #if condition: @@ -34,6 +34,11 @@ local macros=function(s) return s end end +local imacros=function(s) + return function() + return '(intptr_t)' .. s + end +end local N_=function(s) return function() return 'N_(' .. cstr(s) .. ')' @@ -190,7 +195,7 @@ return { type='string', list='comma', scope={'global'}, vi_def=true, varname='p_bo', - defaults={if_true={vi=""}} + defaults={if_true={vi="all"}} }, { full_name='binary', abbreviation='bin', @@ -539,7 +544,7 @@ return { full_name='cursorline', abbreviation='cul', type='bool', scope={'window'}, vi_def=true, - redraw={'current_window'}, + redraw={'current_window_only'}, defaults={if_true={vi=false}} }, { @@ -711,13 +716,6 @@ return { defaults={if_true={vi=macros('DFLT_EFM')}} }, { - full_name='esckeys', abbreviation='ek', - type='bool', scope={'global'}, - vim=true, - varname='p_ek', - defaults={if_true={vi=false, vim=true}} - }, - { full_name='eventignore', abbreviation='ei', type='string', list='onecomma', scope={'global'}, deny_duplicates=true, @@ -955,7 +953,7 @@ return { }, { full_name='formatprg', abbreviation='fp', - type='string', scope={'global'}, + type='string', scope={'global', 'buffer'}, secure=true, vi_def=true, expand=true, @@ -1007,7 +1005,7 @@ return { deny_duplicates=true, vi_def=true, varname='p_guicursor', - defaults={if_true={vi="n-v-c:block,o:hor50,i-ci:hor15,r-cr:hor30,sm:block"}} + defaults={if_true={vi="n-v-c-sm:block,i-ci-ve:ver25,r-cr-o:hor20"}} }, { full_name='guifont', abbreviation='gfn', @@ -1033,13 +1031,6 @@ return { enable_if=false, }, { - full_name='guiheadroom', abbreviation='ghr', - type='number', scope={'global'}, - vi_def=true, - enable_if=false, - defaults={if_true={vi=50}} - }, - { full_name='guioptions', abbreviation='go', type='string', list='flags', scope={'global'}, vi_def=true, @@ -1354,6 +1345,12 @@ return { defaults={if_true={vi=false, vim=true}} }, { + full_name='langremap', abbreviation='lrm', + type='bool', scope={'global'}, + varname='p_lrm', + defaults={if_true={vi=true, vim=false}} + }, + { full_name='laststatus', abbreviation='ls', type='number', scope={'global'}, vim=true, @@ -1572,7 +1569,7 @@ return { full_name='mouse', type='string', list='flags', scope={'global'}, varname='p_mouse', - defaults={if_true={vi="", vim="a"}} + defaults={if_true={vi="", vim=""}} }, { full_name='mousefocus', abbreviation='mousef', @@ -1890,7 +1887,7 @@ return { vim=true, redraw={'statuslines'}, varname='p_ru', - defaults={if_true={vi=false}} + defaults={if_true={vi=true}} }, { full_name='rulerformat', abbreviation='ruf', @@ -1920,6 +1917,14 @@ return { defaults={if_true={vi=12}} }, { + full_name='scrollback', abbreviation='scbk', + type='number', scope={'buffer'}, + vi_def=true, + varname='p_scbk', + redraw={'current_buffer'}, + defaults={if_true={vi=1000}} + }, + { full_name='scrollbind', abbreviation='scb', type='bool', scope={'window'}, vi_def=true, @@ -2051,7 +2056,11 @@ return { secure=true, vi_def=true, varname='p_srr', - defaults={if_true={vi=">"}} + defaults={ + condition='WIN32', + if_true={vi=">%s 2>&1"}, + if_false={vi=">"} + } }, { full_name='shellslash', abbreviation='ssl', @@ -2118,11 +2127,7 @@ return { type='bool', scope={'global'}, vim=true, varname='p_sc', - defaults={ - condition='UNIX', - if_true={vi=false, vim=false}, - if_false={vi=false, vim=true}, - } + defaults={if_true={vi=false, vim=true}} }, { full_name='showfulltag', abbreviation='sft', @@ -2508,14 +2513,14 @@ return { vi_def=true, vim=true, varname='p_ttimeout', - defaults={if_true={vi=false}} + defaults={if_true={vi=true}} }, { full_name='ttimeoutlen', abbreviation='ttm', type='number', scope={'global'}, vi_def=true, varname='p_ttm', - defaults={if_true={vi=-1}} + defaults={if_true={vi=50}} }, { full_name='ttyfast', abbreviation='tf', @@ -2648,7 +2653,7 @@ return { type='number', scope={'global'}, vim=true, varname='p_wc', - defaults={if_true={vi=macros('Ctrl_E'), vim=macros('TAB')}} + defaults={if_true={vi=imacros('Ctrl_E'), vim=imacros('TAB')}} }, { full_name='wildcharm', abbreviation='wcm', @@ -2702,6 +2707,14 @@ return { defaults={if_true={vi="menu"}} }, { + full_name='winhighlight', abbreviation='winhl', + type='string', scope={'window'}, + vi_def=true, + alloced=true, + redraw={'current_window'}, + defaults={if_true={vi=""}} + }, + { full_name='window', abbreviation='wi', type='number', scope={'global'}, vi_def=true, diff --git a/src/nvim/os/dl.c b/src/nvim/os/dl.c index fef02cc784..267cf5ae4b 100644 --- a/src/nvim/os/dl.c +++ b/src/nvim/os/dl.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + /// Functions for using external native libraries #include <stdbool.h> diff --git a/src/nvim/os/env.c b/src/nvim/os/env.c index 83a0262545..de0cd10d9c 100644 --- a/src/nvim/os/env.c +++ b/src/nvim/os/env.c @@ -1,14 +1,15 @@ -// env.c -- environment variable access +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com -#include <assert.h> +// Environment inspection +#include <assert.h> #include <uv.h> -// vim.h must be included before charset.h (and possibly others) or things -// blow up #include "nvim/vim.h" #include "nvim/ascii.h" #include "nvim/charset.h" +#include "nvim/fileio.h" #include "nvim/os/os.h" #include "nvim/memory.h" #include "nvim/message.h" @@ -18,6 +19,10 @@ #include "nvim/ex_getln.h" #include "nvim/version.h" +#ifdef WIN32 +#include "nvim/mbyte.h" // for utf8_to_utf16, utf16_to_utf8 +#endif + #ifdef HAVE__NSGETENVIRON #include <crt_externs.h> #endif @@ -45,7 +50,21 @@ bool os_env_exists(const char *name) int os_setenv(const char *name, const char *value, int overwrite) FUNC_ATTR_NONNULL_ALL { -#ifdef HAVE_SETENV +#ifdef WIN32 + size_t envbuflen = strlen(name) + strlen(value) + 2; + char *envbuf = xmalloc(envbuflen); + snprintf(envbuf, envbuflen, "%s=%s", name, value); + + WCHAR *p; + utf8_to_utf16(envbuf, &p); + xfree(envbuf); + if (p == NULL) { + return -1; + } + _wputenv(p); + xfree(p); // Unlike Unix systems, we can free the string for _wputenv(). + return 0; +#elif defined(HAVE_SETENV) return setenv(name, value, overwrite); #elif defined(HAVE_PUTENV_S) if (!overwrite && os_getenv(name) != NULL) { @@ -99,7 +118,6 @@ char *os_getenvname_at_index(size_t index) return name; } - /// Get the process ID of the Neovim process. /// /// @return the process ID. @@ -112,11 +130,11 @@ int64_t os_get_pid(void) #endif } -/// Get the hostname of the machine running Neovim. +/// Gets the hostname of the current machine. /// -/// @param hostname Buffer to store the hostname. -/// @param len Length of `hostname`. -void os_get_hostname(char *hostname, size_t len) +/// @param hostname Buffer to store the hostname. +/// @param size Size of `hostname`. +void os_get_hostname(char *hostname, size_t size) { #ifdef HAVE_SYS_UTSNAME_H struct utsname vutsname; @@ -124,13 +142,29 @@ void os_get_hostname(char *hostname, size_t len) if (uname(&vutsname) < 0) { *hostname = '\0'; } else { - strncpy(hostname, vutsname.nodename, len - 1); - hostname[len - 1] = '\0'; + xstrlcpy(hostname, vutsname.nodename, size); + } +#elif defined(WIN32) + WCHAR host_utf16[MAX_COMPUTERNAME_LENGTH + 1]; + DWORD host_wsize = sizeof(host_utf16) / sizeof(host_utf16[0]); + if (GetComputerNameW(host_utf16, &host_wsize) == 0) { + *hostname = '\0'; + DWORD err = GetLastError(); + EMSG2("GetComputerNameW failed: %d", err); + return; + } + host_utf16[host_wsize] = '\0'; + + char *host_utf8; + int conversion_result = utf16_to_utf8(host_utf16, &host_utf8); + if (conversion_result != 0) { + EMSG2("utf16_to_utf8 failed: %d", conversion_result); + return; } + xstrlcpy(hostname, host_utf8, size); + xfree(host_utf8); #else - // TODO(unknown): Implement this for windows. - // See the implementation used in vim: - // https://code.google.com/p/vim/source/browse/src/os_win32.c?r=6b69d8dde19e32909f4ee3a6337e6a2ecfbb6f72#2899 + EMSG("os_get_hostname failed: missing uname()"); *hostname = '\0'; #endif } @@ -146,11 +180,11 @@ static char_u *homedir = NULL; void init_homedir(void) { - // In case we are called a second time (when 'encoding' changes). + // In case we are called a second time. xfree(homedir); homedir = NULL; - char_u *var = (char_u *)os_getenv("HOME"); + const char *var = os_getenv("HOME"); #ifdef WIN32 // Typically, $HOME is not defined on Windows, unless the user has @@ -164,10 +198,10 @@ void init_homedir(void) homepath = "\\"; } if (homedrive != NULL && strlen(homedrive) + strlen(homepath) < MAXPATHL) { - snprintf((char *)NameBuff, MAXPATHL, "%s%s", homedrive, homepath); - if (NameBuff[0] != NUL) { - var = NameBuff; - vim_setenv("HOME", (char *)NameBuff); + snprintf(os_buf, MAXPATHL, "%s%s", homedrive, homepath); + if (os_buf[0] != NUL) { + var = os_buf; + vim_setenv("HOME", os_buf); } } } @@ -177,17 +211,16 @@ void init_homedir(void) #ifdef UNIX // Change to the directory and get the actual path. This resolves // links. Don't do it when we can't return. - if (os_dirname(NameBuff, MAXPATHL) == OK - && os_chdir((char *)NameBuff) == 0) { - if (!os_chdir((char *)var) && os_dirname(IObuff, IOSIZE) == OK) { - var = IObuff; + if (os_dirname((char_u *)os_buf, MAXPATHL) == OK && os_chdir(os_buf) == 0) { + if (!os_chdir(var) && os_dirname(IObuff, IOSIZE) == OK) { + var = (char *)IObuff; } - if (os_chdir((char *)NameBuff) != 0) { + if (os_chdir(os_buf) != 0) { EMSG(_(e_prev_dir)); } } #endif - homedir = vim_strsave(var); + homedir = vim_strsave((char_u *)var); } } @@ -226,25 +259,24 @@ char_u *expand_env_save_opt(char_u *src, bool one) /// "~/" is also expanded, using $HOME. For Unix "~user/" is expanded. /// Skips over "\ ", "\~" and "\$" (not for Win32 though). /// If anything fails no expansion is done and dst equals src. -/// @param src Input string e.g. "$HOME/vim.hlp" -/// @param dst Where to put the result -/// @param dstlen Maximum length of the result +/// +/// @param src Input string e.g. "$HOME/vim.hlp" +/// @param dst[out] Where to put the result +/// @param dstlen Maximum length of the result void expand_env(char_u *src, char_u *dst, int dstlen) { expand_env_esc(src, dst, dstlen, false, false, NULL); } /// Expand environment variable with path name and escaping. -/// "~/" is also expanded, using $HOME. For Unix "~user/" is expanded. -/// Skips over "\ ", "\~" and "\$" (not for Win32 though). -/// If anything fails no expansion is done and dst equals src. -/// prefix recognize the start of a new name, for '~' expansion. -/// @param srcp Input string e.g. "$HOME/vim.hlp" -/// @param dst Where to put the result -/// @param dstlen Maximum length of the result -/// @param esc Should we escape spaces in expanded variables? -/// @param one Should we expand more than one '~'? -/// @param prefix Common prefix for paths, can be NULL +/// @see expand_env +/// +/// @param srcp Input string e.g. "$HOME/vim.hlp" +/// @param dst[out] Where to put the result +/// @param dstlen Maximum length of the result +/// @param esc Escape spaces in expanded variables +/// @param one `srcp` is a single filename +/// @param prefix Start again after this (can be NULL) void expand_env_esc(char_u *restrict srcp, char_u *restrict dst, int dstlen, @@ -489,10 +521,11 @@ static char *remove_tail(char *path, char *pend, char *dirname) return pend; } -/// Iterate over colon-separated list +/// Iterate over a delimited list. /// /// @note Environment variables must not be modified during iteration. /// +/// @param[in] delim Delimiter character. /// @param[in] val Value of the environment variable to iterate over. /// @param[in] iter Pointer used for iteration. Must be NULL on first /// iteration. @@ -501,18 +534,19 @@ static char *remove_tail(char *path, char *pend, char *dirname) /// @param[out] len Location where current directory length should be saved. /// /// @return Next iter argument value or NULL when iteration should stop. -const void *vim_colon_env_iter(const char *const val, - const void *const iter, - const char **const dir, - size_t *const len) - FUNC_ATTR_NONNULL_ARG(1, 3, 4) FUNC_ATTR_WARN_UNUSED_RESULT +const void *vim_env_iter(const char delim, + const char *const val, + const void *const iter, + const char **const dir, + size_t *const len) + FUNC_ATTR_NONNULL_ARG(2, 4, 5) FUNC_ATTR_WARN_UNUSED_RESULT { const char *varval = (const char *) iter; if (varval == NULL) { varval = val; } *dir = varval; - const char *const dirend = strchr(varval, ':'); + const char *const dirend = strchr(varval, delim); if (dirend == NULL) { *len = strlen(varval); return NULL; @@ -522,10 +556,11 @@ const void *vim_colon_env_iter(const char *const val, } } -/// Iterate over colon-separated list in reverse order +/// Iterate over a delimited list in reverse order. /// /// @note Environment variables must not be modified during iteration. /// +/// @param[in] delim Delimiter character. /// @param[in] val Value of the environment variable to iterate over. /// @param[in] iter Pointer used for iteration. Must be NULL on first /// iteration. @@ -534,18 +569,19 @@ const void *vim_colon_env_iter(const char *const val, /// @param[out] len Location where current directory length should be saved. /// /// @return Next iter argument value or NULL when iteration should stop. -const void *vim_colon_env_iter_rev(const char *const val, - const void *const iter, - const char **const dir, - size_t *const len) - FUNC_ATTR_NONNULL_ARG(1, 3, 4) FUNC_ATTR_WARN_UNUSED_RESULT +const void *vim_env_iter_rev(const char delim, + const char *const val, + const void *const iter, + const char **const dir, + size_t *const len) + FUNC_ATTR_NONNULL_ARG(2, 4, 5) FUNC_ATTR_WARN_UNUSED_RESULT { const char *varend = (const char *) iter; if (varend == NULL) { varend = val + strlen(val) - 1; } - const size_t varlen = (size_t) (varend - val) + 1; - const char *const colon = xmemrchr(val, ':', varlen); + const size_t varlen = (size_t)(varend - val) + 1; + const char *const colon = xmemrchr(val, (uint8_t)delim, varlen); if (colon == NULL) { *len = varlen; *dir = val; @@ -560,10 +596,13 @@ const void *vim_colon_env_iter_rev(const char *const val, /// Vim's version of getenv(). /// Special handling of $HOME, $VIM and $VIMRUNTIME, allowing the user to /// override the vim runtime directory at runtime. Also does ACP to 'enc' -/// conversion for Win32. Results must be freed by the calling function. -/// @param name Name of environment variable to expand +/// conversion for Win32. Result must be freed by the caller. +/// @param name Environment variable to expand char *vim_getenv(const char *name) { + // init_path() should have been called before now. + assert(get_vim_var_str(VV_PROGPATH)[0] != NUL); + const char *kos_env_path = os_getenv(name); if (kos_env_path != NULL) { return xstrdup(kos_env_path); @@ -598,6 +637,24 @@ char *vim_getenv(const char *name) if (p_hf != NULL && vim_strchr(p_hf, '$') == NULL) { vim_path = (char *)p_hf; } + + char exe_name[MAXPATHL]; + // Find runtime path relative to the nvim binary: ../share/nvim/runtime + if (vim_path == NULL) { + xstrlcpy(exe_name, (char *)get_vim_var_str(VV_PROGPATH), + sizeof(exe_name)); + char *path_end = (char *)path_tail_with_sep((char_u *)exe_name); + *path_end = '\0'; // remove the trailing "nvim.exe" + path_end = (char *)path_tail((char_u *)exe_name); + *path_end = '\0'; // remove the trailing "bin/" + if (append_path( + exe_name, + "share" _PATHSEPSTR "nvim" _PATHSEPSTR "runtime" _PATHSEPSTR, + MAXPATHL) == OK) { + vim_path = exe_name; // -V507 + } + } + if (vim_path != NULL) { // remove the file name char *vim_path_end = (char *)path_tail((char_u *)vim_path); @@ -627,6 +684,7 @@ char *vim_getenv(const char *name) vim_path = NULL; } } + assert(vim_path != exe_name); } #ifdef HAVE_PATHDEF @@ -668,7 +726,8 @@ char *vim_getenv(const char *name) /// @param dstlen Maximum length of the result /// @param one If true, only replace one file name, including spaces and commas /// in the file name -void home_replace(buf_T *buf, char_u *src, char_u *dst, int dstlen, bool one) +void home_replace(const buf_T *const buf, const char_u *src, + char_u *dst, size_t dstlen, bool one) { size_t dirlen = 0, envlen = 0; size_t len; @@ -682,7 +741,7 @@ void home_replace(buf_T *buf, char_u *src, char_u *dst, int dstlen, bool one) * If the file is a help file, remove the path completely. */ if (buf != NULL && buf->b_help) { - STRCPY(dst, path_tail(src)); + xstrlcpy((char *)dst, (char *)path_tail(src), dstlen); return; } @@ -774,7 +833,7 @@ char_u * home_replace_save(buf_T *buf, char_u *src) FUNC_ATTR_NONNULL_RET len += STRLEN(src); } char_u *dst = xmalloc(len); - home_replace(buf, src, dst, (int)len, true); + home_replace(buf, src, dst, len, true); return dst; } @@ -812,3 +871,86 @@ char_u *get_env_name(expand_T *xp, int idx) return NULL; } +/// Appends the head of `fname` to $PATH and sets it in the environment. +/// +/// @param fname Full path whose parent directory will be appended to $PATH. +/// +/// @return true if `path` was appended-to +bool os_setenv_append_path(const char *fname) + FUNC_ATTR_NONNULL_ALL +{ +#ifdef WIN32 +// 8191 (plus NUL) is considered the practical maximum. +# define MAX_ENVPATHLEN 8192 +#else +// No prescribed maximum on unix. +# define MAX_ENVPATHLEN INT_MAX +#endif + if (!path_is_absolute_path((char_u *)fname)) { + EMSG2(_(e_intern2), "os_setenv_append_path()"); + return false; + } + const char *tail = (char *)path_tail_with_sep((char_u *)fname); + size_t dirlen = (size_t)(tail - fname); + assert(tail >= fname && dirlen + 1 < sizeof(os_buf)); + xstrlcpy(os_buf, fname, dirlen + 1); + const char *path = os_getenv("PATH"); + const size_t pathlen = path ? strlen(path) : 0; + const size_t newlen = pathlen + dirlen + 2; + if (newlen < MAX_ENVPATHLEN) { + char *temp = xmalloc(newlen); + if (pathlen == 0) { + temp[0] = NUL; + } else { + xstrlcpy(temp, path, newlen); + xstrlcat(temp, ENV_SEPSTR, newlen); + } + xstrlcat(temp, os_buf, newlen); + os_setenv("PATH", temp, 1); + xfree(temp); + return true; + } + return false; +} + +/// Returns true if the terminal can be assumed to silently ignore unknown +/// control codes. +bool os_term_is_nice(void) +{ +#if defined(__APPLE__) || defined(WIN32) + return true; +#else + const char *vte_version = os_getenv("VTE_VERSION"); + if ((vte_version && atoi(vte_version) >= 3900) + || os_getenv("KONSOLE_PROFILE_NAME") + || os_getenv("KONSOLE_DBUS_SESSION")) { + return true; + } + const char *termprg = os_getenv("TERM_PROGRAM"); + if (termprg && striequal(termprg, "iTerm.app")) { + return true; + } + const char *term = os_getenv("TERM"); + if (term && strncmp(term, "rxvt", 4) == 0) { + return true; + } + return false; +#endif +} + +/// Returns true if `sh` looks like it resolves to "cmd.exe". +bool os_shell_is_cmdexe(const char *sh) + FUNC_ATTR_NONNULL_ALL +{ + if (*sh == NUL) { + return false; + } + if (striequal(sh, "$COMSPEC")) { + const char *comspec = os_getenv("COMSPEC"); + return striequal("cmd.exe", (char *)path_tail((char_u *)comspec)); + } + if (striequal(sh, "cmd.exe") || striequal(sh, "cmd")) { + return true; + } + return striequal("cmd.exe", (char *)path_tail((char_u *)sh)); +} diff --git a/src/nvim/os/fileio.c b/src/nvim/os/fileio.c index cf5bfd60ae..5d68473982 100644 --- a/src/nvim/os/fileio.c +++ b/src/nvim/os/fileio.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + /// @file fileio.c /// /// Buffered reading/writing to a file. Unlike fileio.c this is not dealing with @@ -23,6 +26,7 @@ #include "nvim/globals.h" #include "nvim/rbuffer.h" #include "nvim/macros.h" +#include "nvim/message.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "os/fileio.c.generated.h" @@ -45,8 +49,8 @@ int file_open(FileDescriptor *const ret_fp, const char *const fname, FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT { int os_open_flags = 0; - int fd; TriState wr = kNone; + // -V:FLAG:501 #define FLAG(flags, flag, fcntl_flags, wrval, cond) \ do { \ if (flags & flag) { \ @@ -62,19 +66,42 @@ int file_open(FileDescriptor *const ret_fp, const char *const fname, FLAG(flags, kFileCreate, O_CREAT|O_WRONLY, kTrue, !(flags & kFileCreateOnly)); FLAG(flags, kFileTruncate, O_TRUNC|O_WRONLY, kTrue, !(flags & kFileCreateOnly)); + FLAG(flags, kFileAppend, O_APPEND|O_WRONLY, kTrue, + !(flags & kFileCreateOnly)); FLAG(flags, kFileReadOnly, O_RDONLY, kFalse, wr != kTrue); #ifdef O_NOFOLLOW FLAG(flags, kFileNoSymlink, O_NOFOLLOW, kNone, true); #endif #undef FLAG + // wr is used for kFileReadOnly flag, but on + // QB:neovim-qb-slave-ubuntu-12-04-64bit it still errors out with + // `error: variable โwrโ set but not used [-Werror=unused-but-set-variable]` + (void)wr; - fd = os_open(fname, os_open_flags, mode); + const int fd = os_open(fname, os_open_flags, mode); if (fd < 0) { return fd; } + return file_open_fd(ret_fp, fd, (wr == kTrue)); +} - ret_fp->wr = (wr == kTrue); +/// Wrap file descriptor with FileDescriptor structure +/// +/// @warning File descriptor wrapped like this must not be accessed by other +/// means. +/// +/// @param[out] ret_fp Address where information needed for reading from or +/// writing to a file is saved +/// @param[in] fd File descriptor to wrap. +/// @param[in] wr True if fd is opened for writing only, false if it is read +/// only. +/// +/// @return Error code (@see os_strerror()) or 0. Currently always returns 0. +int file_open_fd(FileDescriptor *const ret_fp, const int fd, const bool wr) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ + ret_fp->wr = wr; ret_fp->fd = fd; ret_fp->eof = false; ret_fp->rv = rbuffer_new(kRWBufferSize); @@ -98,7 +125,7 @@ int file_open(FileDescriptor *const ret_fp, const char *const fname, /// @return [allocated] Opened file or NULL in case of error. FileDescriptor *file_open_new(int *const error, const char *const fname, const int flags, const int mode) - FUNC_ATTR_NONNULL_ALL FUNC_ATTR_MALLOC FUNC_ATTR_WARN_UNUSED_RESULT + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT { FileDescriptor *const fp = xmalloc(sizeof(*fp)); if ((*error = file_open(fp, fname, flags, mode)) != 0) { @@ -108,30 +135,54 @@ FileDescriptor *file_open_new(int *const error, const char *const fname, return fp; } +/// Like file_open_fd(), but allocate and return ret_fp +/// +/// @param[out] error Error code, @see os_strerror(). Is set to zero on +/// success. +/// @param[in] fd File descriptor to wrap. +/// @param[in] wr True if fd is opened for writing only, false if it is read +/// only. +/// +/// @return [allocated] Opened file or NULL in case of error. +FileDescriptor *file_open_fd_new(int *const error, const int fd, const bool wr) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_MALLOC FUNC_ATTR_WARN_UNUSED_RESULT +{ + FileDescriptor *const fp = xmalloc(sizeof(*fp)); + if ((*error = file_open_fd(fp, fd, wr)) != 0) { + xfree(fp); + return NULL; + } + return fp; +} + /// Close file and free its buffer /// /// @param[in,out] fp File to close. +/// @param[in] do_fsync If true, use fsync() to write changes to disk. /// /// @return 0 or error code. -int file_close(FileDescriptor *const fp) FUNC_ATTR_NONNULL_ALL +int file_close(FileDescriptor *const fp, const bool do_fsync) + FUNC_ATTR_NONNULL_ALL { - const int error = file_fsync(fp); - const int error2 = os_close(fp->fd); + const int flush_error = (do_fsync ? file_fsync(fp) : file_flush(fp)); + const int close_error = os_close(fp->fd); rbuffer_free(fp->rv); - if (error2 != 0) { - return error2; + if (close_error != 0) { + return close_error; } - return error; + return flush_error; } /// Close and free file obtained using file_open_new() /// /// @param[in,out] fp File to close. +/// @param[in] do_fsync If true, use fsync() to write changes to disk. /// /// @return 0 or error code. -int file_free(FileDescriptor *const fp) FUNC_ATTR_NONNULL_ALL +int file_free(FileDescriptor *const fp, const bool do_fsync) + FUNC_ATTR_NONNULL_ALL { - const int ret = file_close(fp); + const int ret = file_close(fp, do_fsync); xfree(fp); return ret; } @@ -141,19 +192,38 @@ int file_free(FileDescriptor *const fp) FUNC_ATTR_NONNULL_ALL /// @param[in,out] fp File to work with. /// /// @return 0 or error code. -int file_fsync(FileDescriptor *const fp) +int file_flush(FileDescriptor *const fp) FUNC_ATTR_NONNULL_ALL { if (!fp->wr) { return 0; } file_rb_write_full_cb(fp->rv, fp); - if (fp->_error != 0) { - const int error = fp->_error; - fp->_error = 0; - return error; + const int error = fp->_error; + fp->_error = 0; + return error; +} + +/// Flush file modifications to disk and run fsync() +/// +/// @param[in,out] fp File to work with. +/// +/// @return 0 or error code. +int file_fsync(FileDescriptor *const fp) + FUNC_ATTR_NONNULL_ALL +{ + if (!fp->wr) { + return 0; + } + const int flush_error = file_flush(fp); + if (flush_error != 0) { + return flush_error; } - return os_fsync(fp->fd); + const int fsync_error = os_fsync(fp->fd); + if (fsync_error != UV_EINVAL && fsync_error != UV_EROFS) { + return fsync_error; + } + return 0; } /// Buffer used for writing @@ -316,3 +386,32 @@ ptrdiff_t file_skip(FileDescriptor *const fp, const size_t size) return (ptrdiff_t)read_bytes; } + +/// Msgpack callback for writing to a file +/// +/// @param data File to write to. +/// @param[in] buf Data to write. +/// @param[in] len Length of the data to write. +/// +/// @return 0 in case of success, -1 in case of error. +int msgpack_file_write(void *data, const char *buf, size_t len) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ + assert(len < PTRDIFF_MAX); + const ptrdiff_t written_bytes = file_write((FileDescriptor *)data, buf, len); + if (written_bytes < 0) { + return msgpack_file_write_error((int)written_bytes); + } + return 0; +} + +/// Print error which occurs when failing to write msgpack data +/// +/// @param[in] error Error code of the error to print. +/// +/// @return -1 (error return for msgpack_packer callbacks). +int msgpack_file_write_error(const int error) +{ + emsgf(_("E5420: Failed to write to file: %s"), os_strerror(error)); + return -1; +} diff --git a/src/nvim/os/fileio.h b/src/nvim/os/fileio.h index 2cffd5c851..0b55cc695f 100644 --- a/src/nvim/os/fileio.h +++ b/src/nvim/os/fileio.h @@ -30,6 +30,8 @@ typedef enum { kFileTruncate = 32, ///< Truncate the file if it exists. ///< Implies kFileWriteOnly. Cannot be used with ///< kFileCreateOnly. + kFileAppend = 64, ///< Append to the file. Implies kFileWriteOnly. Cannot + ///< be used with kFileCreateOnly. } FileOpenFlags; static inline bool file_eof(const FileDescriptor *const fp) diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c index 3c821936e9..78627f8703 100644 --- a/src/nvim/os/fs.c +++ b/src/nvim/os/fs.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + // fs.c -- filesystem access #include <stdbool.h> #include <stddef.h> @@ -58,9 +61,9 @@ void fs_init(void) } -/// Change to the given directory. +/// Changes the current directory to `path`. /// -/// @return `0` on success, a libuv error code on failure. +/// @return 0 on success, or negative error code. int os_chdir(const char *path) FUNC_ATTR_NONNULL_ALL { @@ -91,11 +94,11 @@ int os_dirname(char_u *buf, size_t len) /// Check if the given path is a directory and not a symlink to a directory. /// @return `true` if `name` is a directory and NOT a symlink to a directory. /// `false` if `name` is not a directory or if an error occurred. -bool os_isrealdir(const char_u *name) +bool os_isrealdir(const char *name) FUNC_ATTR_NONNULL_ALL { uv_fs_t request; - if (uv_fs_lstat(&fs_loop, &request, (char *)name, NULL) != kLibuvSuccess) { + if (uv_fs_lstat(&fs_loop, &request, name, NULL) != kLibuvSuccess) { return false; } if (S_ISLNK(request.statbuf.st_mode)) { @@ -111,7 +114,7 @@ bool os_isrealdir(const char_u *name) bool os_isdir(const char_u *name) FUNC_ATTR_NONNULL_ALL { - int32_t mode = os_getperm(name); + int32_t mode = os_getperm((const char *)name); if (mode < 0) { return false; } @@ -128,6 +131,7 @@ bool os_isdir(const char_u *name) /// NODE_WRITABLE: writable device, socket, fifo, etc. /// NODE_OTHER: non-writable things int os_nodetype(const char *name) + FUNC_ATTR_NONNULL_ALL { #ifdef WIN32 // Edge case from Vim os_win32.c: @@ -168,6 +172,10 @@ int os_nodetype(const char *name) | O_NONBLOCK #endif , 0); + if (fd == -1) { + return NODE_OTHER; // open() failed. + } + switch (uv_guess_handle(fd)) { case UV_TTY: // FILE_TYPE_CHAR nodetype = NODE_WRITABLE; @@ -192,6 +200,20 @@ int os_nodetype(const char *name) return nodetype; } +/// Gets the absolute path of the currently running executable. +/// May fail if procfs is missing. #6734 +/// @see path_exepath +/// +/// @param[out] buffer Full path to the executable. +/// @param[in] size Size of `buffer`. +/// +/// @return 0 on success, or libuv error code. +int os_exepath(char *buffer, size_t *size) + FUNC_ATTR_NONNULL_ALL +{ + return uv_exepath(buffer, size); +} + /// Checks if the given path represents an executable file. /// /// @param[in] name Name of the executable. @@ -207,49 +229,87 @@ int os_nodetype(const char *name) bool os_can_exe(const char_u *name, char_u **abspath, bool use_path) FUNC_ATTR_NONNULL_ARG(1) { - // when use_path is false or if it's an absolute or relative path don't - // need to use $PATH. - if (!use_path || path_is_absolute_path(name) - || (name[0] == '.' - && (name[1] == '/' - || (name[1] == '.' && name[2] == '/')))) { - // There must be a path separator, files in the current directory - // can't be executed - if (gettail_dir(name) != name && is_executable(name)) { + bool no_path = !use_path || path_is_absolute_path(name); +#ifndef WIN32 + // If the filename is "qualified" (relative or absolute) do not check $PATH. + no_path |= (name[0] == '.' + && (name[1] == '/' || (name[1] == '.' && name[2] == '/'))); +#endif + + if (no_path) { +#ifdef WIN32 + const char *pathext = os_getenv("PATHEXT"); + if (!pathext) { + pathext = ".com;.exe;.bat;.cmd"; + } + bool ok = is_executable((char *)name) || is_executable_ext((char *)name, + pathext); +#else + // Must have path separator, cannot execute files in the current directory. + const bool ok = ((const char_u *)gettail_dir((const char *)name) != name + && is_executable((char *)name)); +#endif + if (ok) { if (abspath != NULL) { *abspath = save_absolute_path(name); } - return true; } - return false; } return is_executable_in_path(name, abspath); } -// Return true if "name" is an executable file, false if not or it doesn't -// exist. -static bool is_executable(const char_u *name) +/// Returns true if `name` is an executable file. +static bool is_executable(const char *name) FUNC_ATTR_NONNULL_ALL { - int32_t mode = os_getperm(name); + int32_t mode = os_getperm((const char *)name); if (mode < 0) { return false; } -#if WIN32 +#ifdef WIN32 // Windows does not have exec bit; just check if the file exists and is not // a directory. return (S_ISREG(mode)); #else return (S_ISREG(mode) && (S_IXUSR & mode)); #endif +} + +#ifdef WIN32 +/// Appends file extensions from `pathext` to `name` and returns true if any +/// such combination is executable. +static bool is_executable_ext(char *name, const char *pathext) + FUNC_ATTR_NONNULL_ALL +{ + xstrlcpy(os_buf, name, sizeof(os_buf)); + char *buf_end = xstrchrnul(os_buf, '\0'); + for (const char *ext = pathext; *ext; ext++) { + // Skip the extension if there is no suffix after a '.'. + if (ext[0] == '.' && (ext[1] == '\0' || ext[1] == ENV_SEPCHAR)) { + ext++; + continue; + } + + const char *ext_end = xstrchrnul(ext, ENV_SEPCHAR); + STRLCPY(buf_end, ext, ext_end - ext + 1); + if (is_executable(os_buf)) { + return true; + } + + if (*ext_end != ENV_SEPCHAR) { + break; + } + ext = ext_end; + } return false; } +#endif /// Checks if a file is inside the `$PATH` and is executable. /// @@ -260,89 +320,69 @@ static bool is_executable(const char_u *name) static bool is_executable_in_path(const char_u *name, char_u **abspath) FUNC_ATTR_NONNULL_ARG(1) { - const char *path = os_getenv("PATH"); - if (path == NULL) { + const char *path_env = os_getenv("PATH"); + if (path_env == NULL) { return false; } - size_t buf_len = STRLEN(name) + STRLEN(path) + 2; +#ifdef WIN32 + // Prepend ".;" to $PATH. + size_t pathlen = strlen(path_env); + char *path = memcpy(xmallocz(pathlen + 3), "." ENV_SEPSTR, 2); + memcpy(path + 2, path_env, pathlen); +#else + char *path = xstrdup(path_env); +#endif + + size_t buf_len = STRLEN(name) + strlen(path) + 2; #ifdef WIN32 const char *pathext = os_getenv("PATHEXT"); if (!pathext) { pathext = ".com;.exe;.bat;.cmd"; } - - buf_len += STRLEN(pathext); + buf_len += strlen(pathext); #endif - char_u *buf = xmalloc(buf_len); + char *buf = xmalloc(buf_len); // Walk through all entries in $PATH to check if "name" exists there and // is an executable file. + char *p = path; + bool rv = false; for (;; ) { - const char *e = xstrchrnul(path, ENV_SEPCHAR); - - // Glue together the given directory from $PATH with name and save into - // buf. - STRLCPY(buf, path, e - path + 1); - append_path((char *) buf, (const char *) name, buf_len); - - if (is_executable(buf)) { - // Check if the caller asked for a copy of the path. - if (abspath != NULL) { - *abspath = save_absolute_path(buf); - } + char *e = xstrchrnul(p, ENV_SEPCHAR); - xfree(buf); - - return true; - } + // Combine the $PATH segment with `name`. + STRLCPY(buf, p, e - p + 1); + append_path(buf, (char *)name, buf_len); #ifdef WIN32 - // Try appending file extensions from $PATHEXT to the name. - char *buf_end = xstrchrnul((char *)buf, '\0'); - for (const char *ext = pathext; *ext; ext++) { - // Skip the extension if there is no suffix after a '.'. - if (ext[0] == '.' && (ext[1] == '\0' || ext[1] == ';')) { - *ext++; - - continue; - } - - const char *ext_end = xstrchrnul(ext, ENV_SEPCHAR); - STRLCPY(buf_end, ext, ext_end - ext + 1); - - if (is_executable(buf)) { - // Check if the caller asked for a copy of the path. - if (abspath != NULL) { - *abspath = save_absolute_path(buf); - } - - xfree(buf); - - return true; + bool ok = is_executable(buf) || is_executable_ext(buf, pathext); +#else + bool ok = is_executable(buf); +#endif + if (ok) { + if (abspath != NULL) { // Caller asked for a copy of the path. + *abspath = save_absolute_path((char_u *)buf); } - if (*ext_end != ENV_SEPCHAR) { - break; - } - ext = ext_end; + rv = true; + goto end; } -#endif if (*e != ENV_SEPCHAR) { // End of $PATH without finding any executable called name. - xfree(buf); - return false; + goto end; } - path = e + 1; + p = e + 1; } - // We should never get to this point. - assert(false); - return false; +end: + xfree(buf); + xfree(path); + return rv; } /// Opens or creates a file and returns a non-negative integer representing @@ -362,6 +402,35 @@ int os_open(const char* path, int flags, int mode) return r; } +/// Sets file descriptor `fd` to close-on-exec. +// +// @return -1 if failed to set, 0 otherwise. +int os_set_cloexec(const int fd) +{ +#ifdef HAVE_FD_CLOEXEC + int e; + int fdflags = fcntl(fd, F_GETFD); + if (fdflags < 0) { + e = errno; + ELOG("Failed to get flags on descriptor %d: %s", fd, strerror(e)); + errno = e; + return -1; + } + if ((fdflags & FD_CLOEXEC) == 0 + && fcntl(fd, F_SETFD, fdflags | FD_CLOEXEC) == -1) { + e = errno; + ELOG("Failed to set CLOEXEC on descriptor %d: %s", fd, strerror(e)); + errno = e; + return -1; + } + return 0; +#endif + + // No FD_CLOEXEC flag. On Windows, the file should have been opened with + // O_NOINHERIT anyway. + return -1; +} + /// Close a file /// /// @return 0 or libuv error code on failure. @@ -395,11 +464,11 @@ ptrdiff_t os_read(const int fd, bool *ret_eof, char *const ret_buf, size_t read_bytes = 0; bool did_try_to_free = false; while (read_bytes != size) { + assert(size >= read_bytes); const ptrdiff_t cur_read_bytes = read(fd, ret_buf + read_bytes, size - read_bytes); if (cur_read_bytes > 0) { read_bytes += (size_t)cur_read_bytes; - assert(read_bytes <= size); } if (cur_read_bytes < 0) { const int error = os_translate_sys_error(errno); @@ -498,6 +567,7 @@ ptrdiff_t os_write(const int fd, const char *const buf, const size_t size) } size_t written_bytes = 0; while (written_bytes != size) { + assert(size >= written_bytes); const ptrdiff_t cur_written_bytes = write(fd, buf + written_bytes, size - written_bytes); if (cur_written_bytes > 0) { @@ -535,8 +605,11 @@ int os_fsync(int fd) /// /// @return libuv return code. static int os_stat(const char *name, uv_stat_t *statbuf) - FUNC_ATTR_NONNULL_ALL + FUNC_ATTR_NONNULL_ARG(2) { + if (!name) { + return UV_ENOENT; + } uv_fs_t request; int result = uv_fs_stat(&fs_loop, &request, name, NULL); *statbuf = request.statbuf; @@ -547,11 +620,10 @@ static int os_stat(const char *name, uv_stat_t *statbuf) /// Get the file permissions for a given file. /// /// @return libuv error code on error. -int32_t os_getperm(const char_u *name) - FUNC_ATTR_NONNULL_ALL +int32_t os_getperm(const char *name) { uv_stat_t statbuf; - int stat_result = os_stat((char *)name, &statbuf); + int stat_result = os_stat(name, &statbuf); if (stat_result == kLibuvSuccess) { return (int32_t)statbuf.st_mode; } else { @@ -562,11 +634,11 @@ int32_t os_getperm(const char_u *name) /// Set the permission of a file. /// /// @return `OK` for success, `FAIL` for failure. -int os_setperm(const char_u *name, int perm) +int os_setperm(const char *const name, int perm) FUNC_ATTR_NONNULL_ALL { int r; - RUN_UV_FS_FUNC(r, uv_fs_chmod, (const char *)name, perm, NULL); + RUN_UV_FS_FUNC(r, uv_fs_chmod, name, perm, NULL); return (r == kLibuvSuccess ? OK : FAIL); } @@ -587,7 +659,6 @@ int os_fchown(int fd, uv_uid_t owner, uv_gid_t group) /// /// @return `true` if `path` exists bool os_path_exists(const char_u *path) - FUNC_ATTR_NONNULL_ALL { uv_stat_t statbuf; return os_stat((char *)path, &statbuf) == kLibuvSuccess; @@ -777,7 +848,7 @@ int os_remove(const char *path) /// @param[out] file_info Pointer to a FileInfo to put the information in. /// @return `true` on success, `false` for failure. bool os_fileinfo(const char *path, FileInfo *file_info) - FUNC_ATTR_NONNULL_ALL + FUNC_ATTR_NONNULL_ARG(2) { return os_stat(path, &(file_info->stat)) == kLibuvSuccess; } @@ -788,8 +859,11 @@ bool os_fileinfo(const char *path, FileInfo *file_info) /// @param[out] file_info Pointer to a FileInfo to put the information in. /// @return `true` on success, `false` for failure. bool os_fileinfo_link(const char *path, FileInfo *file_info) - FUNC_ATTR_NONNULL_ALL + FUNC_ATTR_NONNULL_ARG(2) { + if (path == NULL) { + return false; + } uv_fs_t request; int result = uv_fs_lstat(&fs_loop, &request, path, NULL); file_info->stat = request.statbuf; @@ -920,14 +994,13 @@ bool os_fileid_equal_fileinfo(const FileID *file_id, /// When "fname" is the name of a shortcut (*.lnk) resolve the file it points /// to and return that name in allocated memory. /// Otherwise NULL is returned. -char_u * os_resolve_shortcut(char_u *fname) +char *os_resolve_shortcut(const char *fname) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_MALLOC { HRESULT hr; IPersistFile *ppf = NULL; OLECHAR wsz[MAX_PATH]; - char_u *rfname = NULL; - int len; - int conversion_result; + char *rfname = NULL; IShellLinkW *pslw = NULL; WIN32_FIND_DATAW ffdw; @@ -936,7 +1009,7 @@ char_u * os_resolve_shortcut(char_u *fname) if (fname == NULL) { return rfname; } - len = (int)STRLEN(fname); + const size_t len = strlen(fname); if (len <= 4 || STRNICMP(fname + len - 4, ".lnk", 4) != 0) { return rfname; } @@ -948,9 +1021,9 @@ char_u * os_resolve_shortcut(char_u *fname) &IID_IShellLinkW, (void **)&pslw); if (hr == S_OK) { WCHAR *p; - int conversion_result = utf8_to_utf16((char *)fname, &p); + const int conversion_result = utf8_to_utf16(fname, &p); if (conversion_result != 0) { - EMSG2("utf8_to_utf16 failed: %s", uv_strerror(conversion_result)); + EMSG2("utf8_to_utf16 failed: %d", conversion_result); } if (p != NULL) { @@ -978,7 +1051,7 @@ char_u * os_resolve_shortcut(char_u *fname) ZeroMemory(wsz, MAX_PATH * sizeof(WCHAR)); hr = pslw->lpVtbl->GetPath(pslw, wsz, MAX_PATH, &ffdw, 0); if (hr == S_OK && wsz[0] != NUL) { - int conversion_result = utf16_to_utf8(wsz, &rfname); + const int conversion_result = utf16_to_utf8(wsz, &rfname); if (conversion_result != 0) { EMSG2("utf16_to_utf8 failed: %s", uv_strerror(conversion_result)); } @@ -1008,7 +1081,7 @@ shortcut_end: int os_translate_sys_error(int sys_errno) { #ifdef HAVE_UV_TRANSLATE_SYS_ERROR return uv_translate_sys_error(sys_errno); -#elif WIN32 +#elif defined(WIN32) // TODO(equalsraf): libuv does not yet expose uv_translate_sys_error() // in its public API, include a version here until it can be used. // See https://github.com/libuv/libuv/issues/79 diff --git a/src/nvim/os/fs_defs.h b/src/nvim/os/fs_defs.h index 0bd9c37750..2277d926b3 100644 --- a/src/nvim/os/fs_defs.h +++ b/src/nvim/os/fs_defs.h @@ -14,7 +14,7 @@ typedef struct { uint64_t device_id; ///< @private The id of the device containing the file } FileID; -#define FILE_ID_EMPTY (FileID) {.inode = 0, .device_id = 0} +#define FILE_ID_EMPTY (FileID) { .inode = 0, .device_id = 0 } typedef struct { uv_fs_t request; ///< @private The request to uv for the directory. diff --git a/src/nvim/os/input.c b/src/nvim/os/input.c index b60a7eed36..31e06ce404 100644 --- a/src/nvim/os/input.c +++ b/src/nvim/os/input.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #include <assert.h> #include <string.h> #include <stdbool.h> @@ -20,6 +23,7 @@ #include "nvim/main.h" #include "nvim/misc1.h" #include "nvim/state.h" +#include "nvim/msgpack_rpc/channel.h" #define READ_BUFFER_SIZE 0xfff #define INPUT_BUFFER_SIZE (READ_BUFFER_SIZE * 4) @@ -35,6 +39,7 @@ static RBuffer *input_buffer = NULL; static bool input_eof = false; static int global_fd = 0; static int events_enabled = 0; +static bool blocking = false; #ifdef INCLUDE_GENERATED_DECLARATIONS # include "os/input.c.generated.h" @@ -144,9 +149,15 @@ bool os_char_avail(void) // Check for CTRL-C typed by reading all available characters. void os_breakcheck(void) { + int save_us = updating_screen; + // We do not want screen_resize() to redraw here. + updating_screen++; + if (!got_int) { loop_poll_events(&main_loop, 0); } + + updating_screen = save_us; } void input_enable_events(void) @@ -170,12 +181,14 @@ bool os_isatty(int fd) size_t input_enqueue(String keys) { - char *ptr = keys.data, *end = ptr + keys.size; + char *ptr = keys.data; + char *end = ptr + keys.size; while (rbuffer_space(input_buffer) >= 6 && ptr < end) { uint8_t buf[6] = { 0 }; - unsigned int new_size = trans_special((const uint8_t **)&ptr, keys.size, - buf, true); + unsigned int new_size + = trans_special((const uint8_t **)&ptr, (size_t)(end - ptr), buf, true, + true); if (new_size) { new_size = handle_mouse_event(&ptr, buf, new_size); @@ -185,8 +198,7 @@ size_t input_enqueue(String keys) if (*ptr == '<') { char *old_ptr = ptr; - // Invalid or incomplete key sequence, skip until the next '>' or until - // *end + // Invalid or incomplete key sequence, skip until the next '>' or *end. do { ptr++; } while (ptr < end && *ptr != '>'); @@ -317,13 +329,25 @@ static unsigned int handle_mouse_event(char **ptr, uint8_t *buf, return bufsize; } +/// @return true if the main loop is blocked and waiting for input. +bool input_blocking(void) +{ + return blocking; +} + static bool input_poll(int ms) { if (do_profiling == PROF_YES && ms) { prof_inchar_enter(); } + if ((ms == - 1 || ms > 0) && !events_enabled && !input_eof) { + // The pending input provoked a blocking wait. Do special events now. #6247 + blocking = true; + multiqueue_process_events(ch_before_blocking_events); + } LOOP_PROCESS_EVENTS_UNTIL(&main_loop, NULL, ms, input_ready() || input_eof); + blocking = false; if (do_profiling == PROF_YES && ms) { prof_inchar_exit(); diff --git a/src/nvim/os/mem.c b/src/nvim/os/mem.c index 871ece7a0e..eccb3c97e5 100644 --- a/src/nvim/os/mem.c +++ b/src/nvim/os/mem.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + /// Functions for accessing system memory information. #include <uv.h> diff --git a/src/nvim/os/os_defs.h b/src/nvim/os/os_defs.h index 5e164b54a5..923a362b41 100644 --- a/src/nvim/os/os_defs.h +++ b/src/nvim/os/os_defs.h @@ -13,10 +13,17 @@ # include "nvim/os/unix_defs.h" #endif +/// File descriptor number used for standard IO streams +enum { + OS_STDIN_FILENO = STDIN_FILENO, + OS_STDOUT_FILENO = STDOUT_FILENO, + OS_STDERR_FILENO = STDERR_FILENO, +}; + #define BASENAMELEN (NAME_MAX - 5) // Use the system path length if it makes sense. -#if defined(PATH_MAX) && (PATH_MAX > 1000) +#if defined(PATH_MAX) && (PATH_MAX > 1024) # define MAXPATHL PATH_MAX #else # define MAXPATHL 1024 @@ -27,11 +34,11 @@ // Use up to 5 Mbyte for a buffer. #ifndef DFLT_MAXMEM -# define DFLT_MAXMEM (5*1024) +# define DFLT_MAXMEM (5 * 1024) #endif // use up to 10 Mbyte for Vim. #ifndef DFLT_MAXMEMTOT -# define DFLT_MAXMEMTOT (10*1024) +# define DFLT_MAXMEMTOT (10 * 1024) #endif // Note: Some systems need both string.h and strings.h (Savage). However, diff --git a/src/nvim/os/pty_process_unix.c b/src/nvim/os/pty_process_unix.c index b57a69b82b..ee3ab96a83 100644 --- a/src/nvim/os/pty_process_unix.c +++ b/src/nvim/os/pty_process_unix.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + // Some of the code came from pangoterm and libuv #include <stdbool.h> #include <stdlib.h> @@ -9,7 +12,7 @@ #include <sys/ioctl.h> // forkpty is not in POSIX, so headers are platform-specific -#if defined(__FreeBSD__) +#if defined(__FreeBSD__) || defined (__DragonFly__) # include <libutil.h> #elif defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__) # include <util.h> @@ -33,7 +36,8 @@ # include "os/pty_process_unix.c.generated.h" #endif -bool pty_process_spawn(PtyProcess *ptyproc) +/// @returns zero on success, or negative error code +int pty_process_spawn(PtyProcess *ptyproc) FUNC_ATTR_NONNULL_ALL { static struct termios termios; @@ -41,6 +45,7 @@ bool pty_process_spawn(PtyProcess *ptyproc) init_termios(&termios); } + int status = 0; // zero or negative error code (libuv convention) Process *proc = (Process *)ptyproc; assert(!proc->err); uv_signal_start(&proc->loop->children_watcher, chld_handler, SIGCHLD); @@ -50,8 +55,9 @@ bool pty_process_spawn(PtyProcess *ptyproc) int pid = forkpty(&master, NULL, &termios, &ptyproc->winsize); if (pid < 0) { + status = -errno; ELOG("forkpty failed: %s", strerror(errno)); - return false; + return status; } else if (pid == 0) { init_child(ptyproc); abort(); @@ -60,30 +66,41 @@ bool pty_process_spawn(PtyProcess *ptyproc) // make sure the master file descriptor is non blocking int master_status_flags = fcntl(master, F_GETFL); if (master_status_flags == -1) { + status = -errno; ELOG("Failed to get master descriptor status flags: %s", strerror(errno)); goto error; } if (fcntl(master, F_SETFL, master_status_flags | O_NONBLOCK) == -1) { + status = -errno; ELOG("Failed to make master descriptor non-blocking: %s", strerror(errno)); goto error; } - if (proc->in && !set_duplicating_descriptor(master, &proc->in->uv.pipe)) { + // Other jobs and providers should not get a copy of this file descriptor. + if (os_set_cloexec(master) == -1) { + status = -errno; + ELOG("Failed to set CLOEXEC on ptmx file descriptor"); + goto error; + } + + if (proc->in + && (status = set_duplicating_descriptor(master, &proc->in->uv.pipe))) { goto error; } - if (proc->out && !set_duplicating_descriptor(master, &proc->out->uv.pipe)) { + if (proc->out + && (status = set_duplicating_descriptor(master, &proc->out->uv.pipe))) { goto error; } ptyproc->tty_fd = master; proc->pid = pid; - return true; + return 0; error: close(master); kill(pid, SIGKILL); waitpid(pid, NULL, 0); - return false; + return status; } void pty_process_resize(PtyProcess *ptyproc, uint16_t width, uint16_t height) @@ -137,9 +154,10 @@ static void init_child(PtyProcess *ptyproc) FUNC_ATTR_NONNULL_ALL return; } + char *prog = ptyproc->process.argv[0]; setenv("TERM", ptyproc->term_name ? ptyproc->term_name : "ansi", 1); - execvp(ptyproc->process.argv[0], ptyproc->process.argv); - fprintf(stderr, "execvp failed: %s\n", strerror(errno)); + execvp(prog, ptyproc->process.argv); + fprintf(stderr, "execvp failed: %s: %s\n", strerror(errno), prog); } static void init_termios(struct termios *termios) FUNC_ATTR_NONNULL_ALL @@ -197,22 +215,34 @@ static void init_termios(struct termios *termios) FUNC_ATTR_NONNULL_ALL termios->c_cc[VTIME] = 0; } -static bool set_duplicating_descriptor(int fd, uv_pipe_t *pipe) +static int set_duplicating_descriptor(int fd, uv_pipe_t *pipe) FUNC_ATTR_NONNULL_ALL { + int status = 0; // zero or negative error code (libuv convention) int fd_dup = dup(fd); if (fd_dup < 0) { + status = -errno; ELOG("Failed to dup descriptor %d: %s", fd, strerror(errno)); - return false; + return status; } - int uv_result = uv_pipe_open(pipe, fd_dup); - if (uv_result) { + + if (os_set_cloexec(fd_dup) == -1) { + status = -errno; + ELOG("Failed to set CLOEXEC on duplicate fd"); + goto error; + } + + status = uv_pipe_open(pipe, fd_dup); + if (status) { ELOG("Failed to set pipe to descriptor %d: %s", - fd_dup, uv_strerror(uv_result)); - close(fd_dup); - return false; + fd_dup, uv_strerror(status)); + goto error; } - return true; + return status; + +error: + close(fd_dup); + return status; } static void chld_handler(uv_signal_t *handle, int signum) diff --git a/src/nvim/os/pty_process_win.c b/src/nvim/os/pty_process_win.c new file mode 100644 index 0000000000..ef8a699c56 --- /dev/null +++ b/src/nvim/os/pty_process_win.c @@ -0,0 +1,410 @@ +#include <assert.h> +#include <stdbool.h> +#include <stdlib.h> + +#include <winpty_constants.h> + +#include "nvim/os/os.h" +#include "nvim/ascii.h" +#include "nvim/memory.h" +#include "nvim/mbyte.h" // for utf8_to_utf16, utf16_to_utf8 +#include "nvim/os/pty_process_win.h" + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "os/pty_process_win.c.generated.h" +#endif + +static void CALLBACK pty_process_finish1(void *context, BOOLEAN unused) + FUNC_ATTR_NONNULL_ALL +{ + PtyProcess *ptyproc = (PtyProcess *)context; + Process *proc = (Process *)ptyproc; + + uv_timer_init(&proc->loop->uv, &ptyproc->wait_eof_timer); + ptyproc->wait_eof_timer.data = (void *)ptyproc; + uv_timer_start(&ptyproc->wait_eof_timer, wait_eof_timer_cb, 200, 200); +} + +/// @returns zero on success, or negative error code. +int pty_process_spawn(PtyProcess *ptyproc) + FUNC_ATTR_NONNULL_ALL +{ + Process *proc = (Process *)ptyproc; + int status = 0; + winpty_error_ptr_t err = NULL; + winpty_config_t *cfg = NULL; + winpty_spawn_config_t *spawncfg = NULL; + winpty_t *winpty_object = NULL; + char *in_name = NULL; + char *out_name = NULL; + HANDLE process_handle = NULL; + uv_connect_t *in_req = NULL; + uv_connect_t *out_req = NULL; + wchar_t *cmd_line = NULL; + wchar_t *cwd = NULL; + const char *emsg = NULL; + + assert(!proc->err); + + cfg = winpty_config_new(WINPTY_FLAG_ALLOW_CURPROC_DESKTOP_CREATION, &err); + if (cfg == NULL) { + emsg = "Failed, winpty_config_new."; + goto cleanup; + } + + winpty_config_set_initial_size(cfg, ptyproc->width, ptyproc->height); + winpty_object = winpty_open(cfg, &err); + if (winpty_object == NULL) { + emsg = "Failed, winpty_open."; + goto cleanup; + } + + status = utf16_to_utf8(winpty_conin_name(winpty_object), &in_name); + if (status != 0) { + emsg = "Failed to convert in_name from utf16 to utf8."; + goto cleanup; + } + + status = utf16_to_utf8(winpty_conout_name(winpty_object), &out_name); + if (status != 0) { + emsg = "Failed to convert out_name from utf16 to utf8."; + goto cleanup; + } + + if (proc->in != NULL) { + in_req = xmalloc(sizeof(uv_connect_t)); + uv_pipe_connect( + in_req, + &proc->in->uv.pipe, + in_name, + pty_process_connect_cb); + } + + if (proc->out != NULL) { + out_req = xmalloc(sizeof(uv_connect_t)); + uv_pipe_connect( + out_req, + &proc->out->uv.pipe, + out_name, + pty_process_connect_cb); + } + + if (proc->cwd != NULL) { + status = utf8_to_utf16(proc->cwd, &cwd); + if (status != 0) { + emsg = "Failed to convert pwd form utf8 to utf16."; + goto cleanup; + } + } + + status = build_cmd_line(proc->argv, &cmd_line, + os_shell_is_cmdexe(proc->argv[0])); + if (status != 0) { + emsg = "Failed to convert cmd line form utf8 to utf16."; + goto cleanup; + } + + spawncfg = winpty_spawn_config_new( + WINPTY_SPAWN_FLAG_AUTO_SHUTDOWN, + NULL, // Optional application name + cmd_line, + cwd, + NULL, // Optional environment variables + &err); + if (spawncfg == NULL) { + emsg = "Failed winpty_spawn_config_new."; + goto cleanup; + } + + DWORD win_err = 0; + if (!winpty_spawn(winpty_object, + spawncfg, + &process_handle, + NULL, // Optional thread handle + &win_err, + &err)) { + if (win_err) { + status = (int)win_err; + emsg = "Failed spawn process."; + } else { + emsg = "Failed winpty_spawn."; + } + goto cleanup; + } + proc->pid = GetProcessId(process_handle); + + if (!RegisterWaitForSingleObject( + &ptyproc->finish_wait, + process_handle, + pty_process_finish1, + ptyproc, + INFINITE, + WT_EXECUTEDEFAULT | WT_EXECUTEONLYONCE)) { + abort(); + } + + // Wait until pty_process_connect_cb is called. + while ((in_req != NULL && in_req->handle != NULL) + || (out_req != NULL && out_req->handle != NULL)) { + uv_run(&proc->loop->uv, UV_RUN_ONCE); + } + + ptyproc->winpty_object = winpty_object; + ptyproc->process_handle = process_handle; + winpty_object = NULL; + process_handle = NULL; + +cleanup: + if (status) { + // In the case of an error of MultiByteToWideChar or CreateProcessW. + ELOG("%s error code: %d", emsg, status); + status = os_translate_sys_error(status); + } else if (err != NULL) { + status = (int)winpty_error_code(err); + ELOG("%s error code: %d", emsg, status); + status = translate_winpty_error(status); + } + winpty_error_free(err); + winpty_config_free(cfg); + winpty_spawn_config_free(spawncfg); + winpty_free(winpty_object); + xfree(in_name); + xfree(out_name); + if (process_handle != NULL) { + CloseHandle(process_handle); + } + xfree(in_req); + xfree(out_req); + xfree(cmd_line); + xfree(cwd); + return status; +} + +void pty_process_resize(PtyProcess *ptyproc, uint16_t width, + uint16_t height) + FUNC_ATTR_NONNULL_ALL +{ + if (ptyproc->winpty_object != NULL) { + winpty_set_size(ptyproc->winpty_object, width, height, NULL); + } +} + +void pty_process_close(PtyProcess *ptyproc) + FUNC_ATTR_NONNULL_ALL +{ + Process *proc = (Process *)ptyproc; + + pty_process_close_master(ptyproc); + + if (proc->internal_close_cb) { + proc->internal_close_cb(proc); + } +} + +void pty_process_close_master(PtyProcess *ptyproc) + FUNC_ATTR_NONNULL_ALL +{ + if (ptyproc->winpty_object != NULL) { + winpty_free(ptyproc->winpty_object); + ptyproc->winpty_object = NULL; + } +} + +void pty_process_teardown(Loop *loop) + FUNC_ATTR_NONNULL_ALL +{ +} + +static void pty_process_connect_cb(uv_connect_t *req, int status) + FUNC_ATTR_NONNULL_ALL +{ + assert(status == 0); + req->handle = NULL; +} + +static void wait_eof_timer_cb(uv_timer_t *wait_eof_timer) + FUNC_ATTR_NONNULL_ALL +{ + PtyProcess *ptyproc = wait_eof_timer->data; + Process *proc = (Process *)ptyproc; + + if (!proc->out || !uv_is_readable(proc->out->uvstream)) { + uv_timer_stop(&ptyproc->wait_eof_timer); + pty_process_finish2(ptyproc); + } +} + +static void pty_process_finish2(PtyProcess *ptyproc) + FUNC_ATTR_NONNULL_ALL +{ + Process *proc = (Process *)ptyproc; + + UnregisterWaitEx(ptyproc->finish_wait, NULL); + uv_close((uv_handle_t *)&ptyproc->wait_eof_timer, NULL); + + DWORD exit_code = 0; + GetExitCodeProcess(ptyproc->process_handle, &exit_code); + proc->status = (int)exit_code; + + CloseHandle(ptyproc->process_handle); + ptyproc->process_handle = NULL; + + proc->internal_exit_cb(proc); +} + +/// Build the command line to pass to CreateProcessW. +/// +/// @param[in] argv Array with string arguments. +/// @param[out] cmd_line Location where saved builded cmd line. +/// +/// @returns zero on success, or error code of MultiByteToWideChar function. +/// +static int build_cmd_line(char **argv, wchar_t **cmd_line, bool is_cmdexe) + FUNC_ATTR_NONNULL_ALL +{ + size_t utf8_cmd_line_len = 0; + size_t argc = 0; + QUEUE args_q; + + QUEUE_INIT(&args_q); + while (*argv) { + size_t buf_len = is_cmdexe ? (strlen(*argv) + 1) : (strlen(*argv) * 2 + 3); + ArgNode *arg_node = xmalloc(sizeof(*arg_node)); + arg_node->arg = xmalloc(buf_len); + if (is_cmdexe) { + xstrlcpy(arg_node->arg, *argv, buf_len); + } else { + quote_cmd_arg(arg_node->arg, buf_len, *argv); + } + utf8_cmd_line_len += strlen(arg_node->arg); + QUEUE_INIT(&arg_node->node); + QUEUE_INSERT_TAIL(&args_q, &arg_node->node); + argc++; + argv++; + } + + utf8_cmd_line_len += argc; + char *utf8_cmd_line = xmalloc(utf8_cmd_line_len); + *utf8_cmd_line = NUL; + while (1) { + QUEUE *head = QUEUE_HEAD(&args_q); + QUEUE_REMOVE(head); + ArgNode *arg_node = QUEUE_DATA(head, ArgNode, node); + xstrlcat(utf8_cmd_line, arg_node->arg, utf8_cmd_line_len); + xfree(arg_node->arg); + xfree(arg_node); + if (QUEUE_EMPTY(&args_q)) { + break; + } else { + xstrlcat(utf8_cmd_line, " ", utf8_cmd_line_len); + } + } + + int result = utf8_to_utf16(utf8_cmd_line, cmd_line); + xfree(utf8_cmd_line); + return result; +} + +/// Emulate quote_cmd_arg of libuv and quotes command line argument. +/// Most of the code came from libuv. +/// +/// @param[out] dest Location where saved quotes argument. +/// @param dest_remaining Destination buffer size. +/// @param[in] src Pointer to argument. +/// +static void quote_cmd_arg(char *dest, size_t dest_remaining, const char *src) + FUNC_ATTR_NONNULL_ALL +{ + size_t src_len = strlen(src); + bool quote_hit = true; + char *start = dest; + + if (src_len == 0) { + // Need double quotation for empty argument. + snprintf(dest, dest_remaining, "\"\""); + return; + } + + if (NULL == strpbrk(src, " \t\"")) { + // No quotation needed. + xstrlcpy(dest, src, dest_remaining); + return; + } + + if (NULL == strpbrk(src, "\"\\")) { + // No embedded double quotes or backlashes, so I can just wrap quote marks. + // around the whole thing. + snprintf(dest, dest_remaining, "\"%s\"", src); + return; + } + + // Expected input/output: + // input : hello"world + // output: "hello\"world" + // input : hello""world + // output: "hello\"\"world" + // input : hello\world + // output: hello\world + // input : hello\\world + // output: hello\\world + // input : hello\"world + // output: "hello\\\"world" + // input : hello\\"world + // output: "hello\\\\\"world" + // input : hello world\ + // output: "hello world\\" + + assert(dest_remaining--); + *(dest++) = NUL; + assert(dest_remaining--); + *(dest++) = '"'; + for (size_t i = src_len; i > 0; i--) { + assert(dest_remaining--); + *(dest++) = src[i - 1]; + if (quote_hit && src[i - 1] == '\\') { + assert(dest_remaining--); + *(dest++) = '\\'; + } else if (src[i - 1] == '"') { + quote_hit = true; + assert(dest_remaining--); + *(dest++) = '\\'; + } else { + quote_hit = false; + } + } + assert(dest_remaining); + *dest = '"'; + + while (start < dest) { + char tmp = *start; + *start = *dest; + *dest = tmp; + start++; + dest--; + } +} + +/// Translate winpty error code to libuv error. +/// +/// @param[in] winpty_errno Winpty error code returned by winpty_error_code +/// function. +/// +/// @returns Error code of libuv error. +int translate_winpty_error(int winpty_errno) +{ + if (winpty_errno <= 0) { + return winpty_errno; // If < 0 then it's already a libuv error. + } + + switch (winpty_errno) { + case WINPTY_ERROR_OUT_OF_MEMORY: return UV_ENOMEM; + case WINPTY_ERROR_SPAWN_CREATE_PROCESS_FAILED: return UV_EAI_FAIL; + case WINPTY_ERROR_LOST_CONNECTION: return UV_ENOTCONN; + case WINPTY_ERROR_AGENT_EXE_MISSING: return UV_ENOENT; + case WINPTY_ERROR_UNSPECIFIED: return UV_UNKNOWN; + case WINPTY_ERROR_AGENT_DIED: return UV_ESRCH; + case WINPTY_ERROR_AGENT_TIMEOUT: return UV_ETIMEDOUT; + case WINPTY_ERROR_AGENT_CREATION_FAILED: return UV_EAI_FAIL; + default: return UV_UNKNOWN; + } +} diff --git a/src/nvim/os/pty_process_win.h b/src/nvim/os/pty_process_win.h index 20cc589925..1a4019e654 100644 --- a/src/nvim/os/pty_process_win.h +++ b/src/nvim/os/pty_process_win.h @@ -1,19 +1,27 @@ #ifndef NVIM_OS_PTY_PROCESS_WIN_H #define NVIM_OS_PTY_PROCESS_WIN_H -#include "nvim/event/libuv_process.h" +#include <uv.h> +#include <winpty.h> + +#include "nvim/event/process.h" +#include "nvim/lib/queue.h" typedef struct pty_process { Process process; char *term_name; uint16_t width, height; + winpty_t *winpty_object; + HANDLE finish_wait; + HANDLE process_handle; + uv_timer_t wait_eof_timer; } PtyProcess; -#define pty_process_spawn(job) libuv_process_spawn((LibuvProcess *)job) -#define pty_process_close(job) libuv_process_close((LibuvProcess *)job) -#define pty_process_close_master(job) libuv_process_close((LibuvProcess *)job) -#define pty_process_resize(job, width, height) -#define pty_process_teardown(loop) +// Structure used by build_cmd_line() +typedef struct arg_node { + char *arg; // pointer to argument. + QUEUE node; // QUEUE structure. +} ArgNode; static inline PtyProcess pty_process_init(Loop *loop, void *data) { @@ -22,7 +30,14 @@ static inline PtyProcess pty_process_init(Loop *loop, void *data) rv.term_name = NULL; rv.width = 80; rv.height = 24; + rv.winpty_object = NULL; + rv.finish_wait = NULL; + rv.process_handle = NULL; return rv; } +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "os/pty_process_win.h.generated.h" +#endif + #endif // NVIM_OS_PTY_PROCESS_WIN_H diff --git a/src/nvim/os/shell.c b/src/nvim/os/shell.c index 9514936ad0..32e9a70e57 100644 --- a/src/nvim/os/shell.c +++ b/src/nvim/os/shell.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #include <string.h> #include <assert.h> #include <stdbool.h> @@ -39,14 +42,15 @@ typedef struct { #endif /// Builds the argument vector for running the user-configured 'shell' (p_sh) -/// with an optional command prefixed by 'shellcmdflag' (p_shcf). +/// with an optional command prefixed by 'shellcmdflag' (p_shcf). E.g.: +/// +/// ["shell", "-extra_args", "-shellcmdflag", "command with spaces"] /// /// @param cmd Command string, or NULL to run an interactive shell. /// @param extra_args Extra arguments to the shell, or NULL. -/// @return A newly allocated argument vector. It must be freed with -/// `shell_free_argv` when no longer needed. +/// @return Newly allocated argument vector. Must be freed with shell_free_argv. char **shell_build_argv(const char *cmd, const char *extra_args) - FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC + FUNC_ATTR_NONNULL_RET { size_t argc = tokenize(p_sh, NULL) + (cmd ? tokenize(p_shcf, NULL) : 0); char **rv = xmalloc((argc + 4) * sizeof(*rv)); @@ -123,15 +127,9 @@ int os_call_shell(char_u *cmd, ShellOpts opts, char_u *extra_args) } size_t nread; - - int status = do_os_system(shell_build_argv((char *)cmd, (char *)extra_args), - input.data, - input.len, - output_ptr, - &nread, - emsg_silent, - forward_output); - + int exitcode = do_os_system(shell_build_argv((char *)cmd, (char *)extra_args), + input.data, input.len, output_ptr, &nread, + emsg_silent, forward_output); xfree(input.data); if (output) { @@ -139,16 +137,16 @@ int os_call_shell(char_u *cmd, ShellOpts opts, char_u *extra_args) xfree(output); } - if (!emsg_silent && status != 0 && !(opts & kShellOptSilent)) { + if (!emsg_silent && exitcode != 0 && !(opts & kShellOptSilent)) { MSG_PUTS(_("\nshell returned ")); - msg_outnum(status); + msg_outnum(exitcode); msg_putchar('\n'); } State = current_state; signal_accept_deadly(); - return status; + return exitcode; } /// os_system - synchronously execute a command in the shell @@ -157,7 +155,7 @@ int os_call_shell(char_u *cmd, ShellOpts opts, char_u *extra_args) /// char *output = NULL; /// size_t nread = 0; /// char *argv[] = {"ls", "-la", NULL}; -/// int status = os_sytem(argv, NULL, 0, &output, &nread); +/// int exitcode = os_sytem(argv, NULL, 0, &output, &nread); /// /// @param argv The commandline arguments to be passed to the shell. `argv` /// will be consumed. @@ -218,11 +216,14 @@ static int do_os_system(char **argv, proc->in = input != NULL ? &in : NULL; proc->out = &out; proc->err = &err; - if (!process_spawn(proc)) { + int status = process_spawn(proc); + if (status) { loop_poll_events(&main_loop, 0); - // Failed, probably due to 'sh' not being executable + // Failed, probably 'shell' is not executable. if (!silent) { - MSG_PUTS(_("\nCannot execute ")); + MSG_PUTS(_("\nshell failed to start: ")); + msg_outtrans((char_u *)os_strerror(status)); + MSG_PUTS(": "); msg_outtrans((char_u *)prog); msg_putchar('\n'); } @@ -262,7 +263,7 @@ static int do_os_system(char **argv, // busy state. ui_busy_start(); ui_flush(); - int status = process_wait(proc, -1, NULL); + int exitcode = process_wait(proc, -1, NULL); if (!got_int && out_data_decide_throttle(0)) { // Last chunk of output was skipped; display it now. out_data_ring(NULL, SIZE_MAX); @@ -289,7 +290,7 @@ static int do_os_system(char **argv, assert(multiqueue_empty(events)); multiqueue_free(events); - return status; + return exitcode; } /// - ensures at least `desired` bytes in buffer @@ -321,7 +322,7 @@ static void system_data_cb(Stream *stream, RBuffer *buf, size_t count, /// Tracks output received for the current executing shell command, and displays /// a pulsing "..." when output should be skipped. Tracking depends on the /// synchronous/blocking nature of ":!". -// +/// /// Purpose: /// 1. CTRL-C is more responsive. #1234 #5396 /// 2. Improves performance of :! (UI, esp. TUI, is the bottleneck). @@ -446,7 +447,7 @@ static void out_data_append_to_screen(char *output, size_t remaining, size_t off = 0; int last_row = (int)Rows - 1; - while (off < remaining) { + while (output != NULL && off < remaining) { // Found end of line? if (output[off] == NL) { // Can we start a new line or do we need to continue the last one? @@ -463,15 +464,16 @@ static void out_data_append_to_screen(char *output, size_t remaining, continue; } - // Translate NUL to SOH - if (output[off] == NUL) { - output[off] = 1; + // TODO(bfredl): using msg_puts would be better until + // terminal emulation is implemented. + if (output[off] < 0x20) { + output[off] = ' '; } off++; } - if (remaining) { + if (output != NULL && remaining) { if (last_col == 0) { screen_del_lines(0, 0, 1, (int)Rows, NULL); } @@ -683,7 +685,7 @@ static void shell_write_cb(Stream *stream, void *data, int status) uv_err_name(status)); } if (stream->closed) { // Process may have exited before this write. - ELOG("stream was already closed"); + WLOG("stream was already closed"); return; } stream_close(stream, NULL, NULL); diff --git a/src/nvim/os/shell.h b/src/nvim/os/shell.h index 58960db157..48503f2601 100644 --- a/src/nvim/os/shell.h +++ b/src/nvim/os/shell.h @@ -1,6 +1,8 @@ #ifndef NVIM_OS_SHELL_H #define NVIM_OS_SHELL_H +#include <stdio.h> + #include "nvim/types.h" // Flags for os_call_shell() second argument diff --git a/src/nvim/os/signal.c b/src/nvim/os/signal.c index 1ac6d3f5e1..fd6d3b32e4 100644 --- a/src/nvim/os/signal.c +++ b/src/nvim/os/signal.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #include <assert.h> #include <stdbool.h> diff --git a/src/nvim/os/stdpaths.c b/src/nvim/os/stdpaths.c index afb9bdec31..a41fb7c621 100644 --- a/src/nvim/os/stdpaths.c +++ b/src/nvim/os/stdpaths.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #include <stdbool.h> #include "nvim/os/stdpaths_defs.h" diff --git a/src/nvim/os/time.c b/src/nvim/os/time.c index 8ce2ecf4f4..c471352c02 100644 --- a/src/nvim/os/time.c +++ b/src/nvim/os/time.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #include <assert.h> #include <stdint.h> #include <stdbool.h> diff --git a/src/nvim/os/unix_defs.h b/src/nvim/os/unix_defs.h index 690a39c3cd..5c9daca476 100644 --- a/src/nvim/os/unix_defs.h +++ b/src/nvim/os/unix_defs.h @@ -8,7 +8,7 @@ // POSIX.1-2008 says that NAME_MAX should be in here #include <limits.h> -#define TEMP_DIR_NAMES {"$TMPDIR", "/tmp", ".", "~"} +#define TEMP_DIR_NAMES { "$TMPDIR", "/tmp", ".", "~" } #define TEMP_FILE_PATH_MAXLEN 256 #define HAVE_ACL (HAVE_POSIX_ACL || HAVE_SOLARIS_ACL) @@ -16,7 +16,8 @@ // Special wildcards that need to be handled by the shell. #define SPECIAL_WILDCHAR "`'{" -// Separator character for environment variables. +// Character that separates entries in $PATH. #define ENV_SEPCHAR ':' +#define ENV_SEPSTR ":" #endif // NVIM_OS_UNIX_DEFS_H diff --git a/src/nvim/os/users.c b/src/nvim/os/users.c index 1c94ef0067..82bb918f70 100644 --- a/src/nvim/os/users.c +++ b/src/nvim/os/users.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + // users.c -- operating system user information #include <uv.h> diff --git a/src/nvim/os/win_defs.h b/src/nvim/os/win_defs.h index 6a29f86e79..8fd2e51f8b 100644 --- a/src/nvim/os/win_defs.h +++ b/src/nvim/os/win_defs.h @@ -1,6 +1,10 @@ #ifndef NVIM_OS_WIN_DEFS_H #define NVIM_OS_WIN_DEFS_H +#ifndef WIN32 +# error Header must be included only when compiling for Windows. +#endif + // winsock2.h must be first to avoid incompatibilities // with winsock.h (included by windows.h) #include <winsock2.h> @@ -15,18 +19,24 @@ #define NAME_MAX _MAX_PATH -#define TEMP_DIR_NAMES {"$TMP", "$TEMP", "$USERPROFILE", ""} +#define TEMP_DIR_NAMES { "$TMPDIR", "$TMP", "$TEMP", "$USERPROFILE", "" } #define TEMP_FILE_PATH_MAXLEN _MAX_PATH #define FNAME_ILLEGAL "\"*?><|" -// Separator character for environment variables. +// Character that separates entries in $PATH. #define ENV_SEPCHAR ';' +#define ENV_SEPSTR ";" #define USE_CRNL -// We have our own RGB macro in macros.h. -#undef RGB +// Windows defines a RGB macro that produces 0x00bbggrr color values for use +// with GDI. Our macro is different, and we don't use GDI. +#if defined(RGB) +# undef RGB + // Duplicated from macros.h to avoid include-order sensitivity. +# define RGB(r, g, b) ((r << 16) | (g << 8) | b) +#endif #ifdef _MSC_VER # ifndef inline @@ -86,4 +96,14 @@ typedef SSIZE_T ssize_t; # define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) #endif +#ifndef STDIN_FILENO +# define STDIN_FILENO 0 +#endif +#ifndef STDOUT_FILENO +# define STDOUT_FILENO 1 +#endif +#ifndef STDERR_FILENO +# define STDERR_FILENO 2 +#endif + #endif // NVIM_OS_WIN_DEFS_H diff --git a/src/nvim/os_unix.c b/src/nvim/os_unix.c index 08294fa6a0..692bcc97f4 100644 --- a/src/nvim/os_unix.c +++ b/src/nvim/os_unix.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + /* * os_unix.c -- code for all flavors of Unix (BSD, SYSV, SVR4, POSIX, ...) * @@ -62,9 +65,7 @@ static int selinux_enabled = -1; #if defined(HAVE_SELINUX) -/* - * Copy security info from "from_file" to "to_file". - */ +// Copy security info from "from_file" to "to_file". void mch_copy_sec(char_u *from_file, char_u *to_file) { if (from_file == NULL) @@ -78,11 +79,12 @@ void mch_copy_sec(char_u *from_file, char_u *to_file) security_context_t to_context = NULL; if (getfilecon((char *)from_file, &from_context) < 0) { - /* If the filesystem doesn't support extended attributes, - the original had no special security context and the - target cannot have one either. */ - if (errno == EOPNOTSUPP) + // If the filesystem doesn't support extended attributes, + // the original had no special security context and the + // target cannot have one either. + if (errno == EOPNOTSUPP) { return; + } MSG_PUTS(_("\nCould not get security context for ")); msg_outtrans(from_file); @@ -107,22 +109,18 @@ void mch_copy_sec(char_u *from_file, char_u *to_file) freecon(from_context); } } -#endif /* HAVE_SELINUX */ +#endif // HAVE_SELINUX -/* - * Return a pointer to the ACL of file "fname" in allocated memory. - * Return NULL if the ACL is not available for whatever reason. - */ -vim_acl_T mch_get_acl(char_u *fname) +// Return a pointer to the ACL of file "fname" in allocated memory. +// Return NULL if the ACL is not available for whatever reason. +vim_acl_T mch_get_acl(const char_u *fname) { vim_acl_T ret = NULL; return ret; } -/* - * Set the ACL of file "fname" to "acl" (unless it's NULL). - */ -void mch_set_acl(char_u *fname, vim_acl_T aclent) +// Set the ACL of file "fname" to "acl" (unless it's NULL). +void mch_set_acl(const char_u *fname, vim_acl_T aclent) { if (aclent == NULL) return; @@ -135,15 +133,17 @@ void mch_free_acl(vim_acl_T aclent) } #endif -void mch_exit(int r) +void mch_exit(int r) FUNC_ATTR_NORETURN { exiting = true; ui_builtin_stop(); ui_flush(); - ml_close_all(true); /* remove all memfiles */ + ml_close_all(true); // remove all memfiles - event_teardown(); + if (!event_teardown() && r == 0) { + r = 1; // Exit with error if main_loop did not teardown gracefully. + } stream_set_blocking(input_global_fd(), true); // normalize stream (#2598) #ifdef EXITFREE @@ -175,7 +175,7 @@ void mch_exit(int r) /// @returns OK for success or FAIL for error. int mch_expand_wildcards(int num_pat, char_u **pat, int *num_file, char_u ***file, int flags) FUNC_ATTR_NONNULL_ARG(3) - FUNC_ATTR_NONNULL_ARG(4) + FUNC_ATTR_NONNULL_ARG(4) { int i; size_t len; @@ -198,17 +198,22 @@ int mch_expand_wildcards(int num_pat, char_u **pat, int *num_file, int check_spaces; static bool did_find_nul = false; bool ampersent = false; - /* vimglob() function to define for Posix shell */ + // vimglob() function to define for Posix shell static char *sh_vimglob_func = "vimglob() { while [ $# -ge 1 ]; do echo \"$1\"; shift; done }; vimglob >"; - *num_file = 0; /* default: no files found */ + bool is_fish_shell = +#if defined(UNIX) + STRNCMP(invocation_path_tail(p_sh, NULL), "fish", 4) == 0; +#else + false; +#endif + + *num_file = 0; // default: no files found *file = NULL; - /* - * If there are no wildcards, just copy the names to allocated memory. - * Saves a lot of time, because we don't have to start a new shell. - */ + // If there are no wildcards, just copy the names to allocated memory. + // Saves a lot of time, because we don't have to start a new shell. if (!have_wildcard(num_pat, pat)) { save_patterns(num_pat, pat, num_file, file); return OK; @@ -219,87 +224,99 @@ int mch_expand_wildcards(int num_pat, char_u **pat, int *num_file, return FAIL; } - /* - * Don't allow the use of backticks in secure and restricted mode. - */ - if (secure || restricted) - for (i = 0; i < num_pat; ++i) + // Don't allow the use of backticks in secure and restricted mode. + if (secure || restricted) { + for (i = 0; i < num_pat; i++) { if (vim_strchr(pat[i], '`') != NULL - && (check_restricted() || check_secure())) + && (check_restricted() || check_secure())) { return FAIL; + } + } + } - /* - * get a name for the temp file - */ + // get a name for the temp file if ((tempname = vim_tempname()) == NULL) { EMSG(_(e_notmp)); return FAIL; } - /* - * Let the shell expand the patterns and write the result into the temp - * file. - * STYLE_BT: NL separated - * If expanding `cmd` execute it directly. - * STYLE_GLOB: NUL separated - * If we use *csh, "glob" will work better than "echo". - * STYLE_PRINT: NL or NUL separated - * If we use *zsh, "print -N" will work better than "glob". - * STYLE_VIMGLOB: NL separated - * If we use *sh*, we define "vimglob()". - * STYLE_ECHO: space separated. - * A shell we don't know, stay safe and use "echo". - */ + // Let the shell expand the patterns and write the result into the temp + // file. + // STYLE_BT: NL separated + // If expanding `cmd` execute it directly. + // STYLE_GLOB: NUL separated + // If we use *csh, "glob" will work better than "echo". + // STYLE_PRINT: NL or NUL separated + // If we use *zsh, "print -N" will work better than "glob". + // STYLE_VIMGLOB: NL separated + // If we use *sh*, we define "vimglob()". + // STYLE_ECHO: space separated. + // A shell we don't know, stay safe and use "echo". if (num_pat == 1 && *pat[0] == '`' && (len = STRLEN(pat[0])) > 2 - && *(pat[0] + len - 1) == '`') + && *(pat[0] + len - 1) == '`') { shell_style = STYLE_BT; - else if ((len = STRLEN(p_sh)) >= 3) { - if (STRCMP(p_sh + len - 3, "csh") == 0) + } else if ((len = STRLEN(p_sh)) >= 3) { + if (STRCMP(p_sh + len - 3, "csh") == 0) { shell_style = STYLE_GLOB; - else if (STRCMP(p_sh + len - 3, "zsh") == 0) + } else if (STRCMP(p_sh + len - 3, "zsh") == 0) { shell_style = STYLE_PRINT; + } } if (shell_style == STYLE_ECHO && strstr((char *)path_tail(p_sh), "sh") != NULL) shell_style = STYLE_VIMGLOB; - /* Compute the length of the command. We need 2 extra bytes: for the - * optional '&' and for the NUL. - * Worst case: "unset nonomatch; print -N >" plus two is 29 */ + // Compute the length of the command. We need 2 extra bytes: for the + // optional '&' and for the NUL. + // Worst case: "unset nonomatch; print -N >" plus two is 29 len = STRLEN(tempname) + 29; if (shell_style == STYLE_VIMGLOB) len += STRLEN(sh_vimglob_func); - for (i = 0; i < num_pat; ++i) { - /* Count the length of the patterns in the same way as they are put in - * "command" below. */ - ++len; /* add space */ - for (j = 0; pat[i][j] != NUL; ++j) { - if (vim_strchr(SHELL_SPECIAL, pat[i][j]) != NULL) - ++len; /* may add a backslash */ - ++len; + for (i = 0; i < num_pat; i++) { + // Count the length of the patterns in the same way as they are put in + // "command" below. + len++; // add space + for (j = 0; pat[i][j] != NUL; j++) { + if (vim_strchr(SHELL_SPECIAL, pat[i][j]) != NULL) { + len++; // may add a backslash + } + len++; } } + + if (is_fish_shell) { + len += sizeof("egin;"" end") - 1; + } + command = xmalloc(len); - /* - * Build the shell command: - * - Set $nonomatch depending on EW_NOTFOUND (hopefully the shell - * recognizes this). - * - Add the shell command to print the expanded names. - * - Add the temp file name. - * - Add the file name patterns. - */ + // Build the shell command: + // - Set $nonomatch depending on EW_NOTFOUND (hopefully the shell + // recognizes this). + // - Add the shell command to print the expanded names. + // - Add the temp file name. + // - Add the file name patterns. if (shell_style == STYLE_BT) { - /* change `command; command& ` to (command; command ) */ - STRCPY(command, "("); - STRCAT(command, pat[0] + 1); /* exclude first backtick */ + // change `command; command& ` to (command; command ) + if (is_fish_shell) { + STRCPY(command, "begin; "); + } else { + STRCPY(command, "("); + } + STRCAT(command, pat[0] + 1); // exclude first backtick p = command + STRLEN(command) - 1; - *p-- = ')'; /* remove last backtick */ - while (p > command && ascii_iswhite(*p)) - --p; - if (*p == '&') { /* remove trailing '&' */ + if (is_fish_shell) { + *p-- = ';'; + STRCAT(command, " end"); + } else { + *p-- = ')'; // remove last backtick + } + while (p > command && ascii_iswhite(*p)) { + p--; + } + if (*p == '&') { // remove trailing '&' ampersent = true; *p = ' '; } @@ -321,113 +338,109 @@ int mch_expand_wildcards(int num_pat, char_u **pat, int *num_file, STRCAT(command, tempname); - if (shell_style != STYLE_BT) - for (i = 0; i < num_pat; ++i) { - /* Put a backslash before special - * characters, except inside ``. */ + if (shell_style != STYLE_BT) { + for (i = 0; i < num_pat; i++) { + // Put a backslash before special + // characters, except inside ``. bool intick = false; p = command + STRLEN(command); *p++ = ' '; - for (j = 0; pat[i][j] != NUL; ++j) { - if (pat[i][j] == '`') + for (j = 0; pat[i][j] != NUL; j++) { + if (pat[i][j] == '`') { intick = !intick; - else if (pat[i][j] == '\\' && pat[i][j + 1] != NUL) { - /* Remove a backslash, take char literally. But keep - * backslash inside backticks, before a special character - * and before a backtick. */ + } else if (pat[i][j] == '\\' && pat[i][j + 1] != NUL) { + // Remove a backslash, take char literally. But keep + // backslash inside backticks, before a special character + // and before a backtick. if (intick || vim_strchr(SHELL_SPECIAL, pat[i][j + 1]) != NULL - || pat[i][j + 1] == '`') + || pat[i][j + 1] == '`') { *p++ = '\\'; - ++j; + } + j++; } else if (!intick - && ((flags & EW_KEEPDOLLAR) == 0 || pat[i][j] != '$') - && vim_strchr(SHELL_SPECIAL, pat[i][j]) != NULL) - /* Put a backslash before a special character, but not - * when inside ``. And not for $var when EW_KEEPDOLLAR is - * set. */ + && ((flags & EW_KEEPDOLLAR) == 0 || pat[i][j] != '$') + && vim_strchr(SHELL_SPECIAL, pat[i][j]) != NULL) { + // Put a backslash before a special character, but not + // when inside ``. And not for $var when EW_KEEPDOLLAR is + // set. *p++ = '\\'; + } - /* Copy one character. */ + // Copy one character. *p++ = pat[i][j]; } *p = NUL; } + } if (flags & EW_SILENT) { shellopts |= kShellOptHideMess; } - if (ampersent) - STRCAT(command, "&"); /* put the '&' after the redirection */ - - /* - * Using zsh -G: If a pattern has no matches, it is just deleted from - * the argument list, otherwise zsh gives an error message and doesn't - * expand any other pattern. - */ - if (shell_style == STYLE_PRINT) - extra_shell_arg = (char_u *)"-G"; /* Use zsh NULL_GLOB option */ - - /* - * If we use -f then shell variables set in .cshrc won't get expanded. - * vi can do it, so we will too, but it is only necessary if there is a "$" - * in one of the patterns, otherwise we can still use the fast option. - */ - else if (shell_style == STYLE_GLOB && !have_dollars(num_pat, pat)) - extra_shell_arg = (char_u *)"-f"; /* Use csh fast option */ - - /* - * execute the shell command - */ + if (ampersent) { + STRCAT(command, "&"); // put the '&' after the redirection + } + + // Using zsh -G: If a pattern has no matches, it is just deleted from + // the argument list, otherwise zsh gives an error message and doesn't + // expand any other pattern. + if (shell_style == STYLE_PRINT) { + extra_shell_arg = (char_u *)"-G"; // Use zsh NULL_GLOB option + + // If we use -f then shell variables set in .cshrc won't get expanded. + // vi can do it, so we will too, but it is only necessary if there is a "$" + // in one of the patterns, otherwise we can still use the fast option. + } else if (shell_style == STYLE_GLOB && !have_dollars(num_pat, pat)) { + extra_shell_arg = (char_u *)"-f"; // Use csh fast option + } + + // execute the shell command i = call_shell( command, shellopts, extra_shell_arg ); - /* When running in the background, give it some time to create the temp - * file, but don't wait for it to finish. */ - if (ampersent) + // When running in the background, give it some time to create the temp + // file, but don't wait for it to finish. + if (ampersent) { os_delay(10L, true); + } xfree(command); - if (i) { /* os_call_shell() failed */ + if (i) { // os_call_shell() failed os_remove((char *)tempname); xfree(tempname); - /* - * With interactive completion, the error message is not printed. - */ - if (!(flags & EW_SILENT)) - { - redraw_later_clear(); /* probably messed up screen */ - msg_putchar('\n'); /* clear bottom line quickly */ + // With interactive completion, the error message is not printed. + if (!(flags & EW_SILENT)) { + redraw_later_clear(); // probably messed up screen + msg_putchar('\n'); // clear bottom line quickly #if SIZEOF_LONG > SIZEOF_INT assert(Rows <= (long)INT_MAX + 1); #endif - cmdline_row = (int)(Rows - 1); /* continue on last line */ + cmdline_row = (int)(Rows - 1); // continue on last line MSG(_(e_wildexpand)); - msg_start(); /* don't overwrite this message */ + msg_start(); // don't overwrite this message } - /* If a `cmd` expansion failed, don't list `cmd` as a match, even when - * EW_NOTFOUND is given */ - if (shell_style == STYLE_BT) + // If a `cmd` expansion failed, don't list `cmd` as a match, even when + // EW_NOTFOUND is given + if (shell_style == STYLE_BT) { return FAIL; + } goto notfound; } - /* - * read the names from the file into memory - */ + // read the names from the file into memory fd = fopen((char *)tempname, READBIN); if (fd == NULL) { - /* Something went wrong, perhaps a file name with a special char. */ + // Something went wrong, perhaps a file name with a special char. if (!(flags & EW_SILENT)) { MSG(_(e_wildexpand)); - msg_start(); /* don't overwrite this message */ + msg_start(); // don't overwrite this message } xfree(tempname); goto notfound; @@ -438,7 +451,7 @@ int mch_expand_wildcards(int num_pat, char_u **pat, int *num_file, fclose(fd); return FAIL; } - long long templen = ftell(fd); /* get size of temp file */ + int64_t templen = ftell(fd); // get size of temp file if (templen < 0) { xfree(tempname); fclose(fd); @@ -456,7 +469,7 @@ int mch_expand_wildcards(int num_pat, char_u **pat, int *num_file, fclose(fd); os_remove((char *)tempname); if (readlen != len) { - /* unexpected read error */ + // unexpected read error EMSG2(_(e_notread), tempname); xfree(tempname); xfree(buffer); @@ -464,41 +477,40 @@ int mch_expand_wildcards(int num_pat, char_u **pat, int *num_file, } xfree(tempname); - /* file names are separated with Space */ + // file names are separated with Space if (shell_style == STYLE_ECHO) { - buffer[len] = '\n'; /* make sure the buffer ends in NL */ + buffer[len] = '\n'; // make sure the buffer ends in NL p = buffer; - for (i = 0; *p != '\n'; ++i) { /* count number of entries */ - while (*p != ' ' && *p != '\n') - ++p; - p = skipwhite(p); /* skip to next entry */ + for (i = 0; *p != '\n'; i++) { // count number of entries + while (*p != ' ' && *p != '\n') { + p++; + } + p = skipwhite(p); // skip to next entry } - } - /* file names are separated with NL */ - else if (shell_style == STYLE_BT || shell_style == STYLE_VIMGLOB) { - buffer[len] = NUL; /* make sure the buffer ends in NUL */ + // file names are separated with NL + } else if (shell_style == STYLE_BT || shell_style == STYLE_VIMGLOB) { + buffer[len] = NUL; // make sure the buffer ends in NUL p = buffer; - for (i = 0; *p != NUL; ++i) { /* count number of entries */ - while (*p != '\n' && *p != NUL) - ++p; - if (*p != NUL) - ++p; - p = skipwhite(p); /* skip leading white space */ + for (i = 0; *p != NUL; i++) { // count number of entries + while (*p != '\n' && *p != NUL) { + p++; + } + if (*p != NUL) { + p++; + } + p = skipwhite(p); // skip leading white space } - } - /* file names are separated with NUL */ - else { - /* - * Some versions of zsh use spaces instead of NULs to separate - * results. Only do this when there is no NUL before the end of the - * buffer, otherwise we would never be able to use file names with - * embedded spaces when zsh does use NULs. - * When we found a NUL once, we know zsh is OK, set did_find_nul and - * don't check for spaces again. - */ + // file names are separated with NUL + } else { + // Some versions of zsh use spaces instead of NULs to separate + // results. Only do this when there is no NUL before the end of the + // buffer, otherwise we would never be able to use file names with + // embedded spaces when zsh does use NULs. + // When we found a NUL once, we know zsh is OK, set did_find_nul and + // don't check for spaces again. check_spaces = false; if (shell_style == STYLE_PRINT && !did_find_nul) { - /* If there is a NUL, set did_find_nul, else set check_spaces */ + // If there is a NUL, set did_find_nul, else set check_spaces buffer[len] = NUL; if (len && (int)STRLEN(buffer) < (int)len) did_find_nul = true; @@ -506,72 +518,69 @@ int mch_expand_wildcards(int num_pat, char_u **pat, int *num_file, check_spaces = true; } - /* - * Make sure the buffer ends with a NUL. For STYLE_PRINT there - * already is one, for STYLE_GLOB it needs to be added. - */ - if (len && buffer[len - 1] == NUL) - --len; - else + // Make sure the buffer ends with a NUL. For STYLE_PRINT there + // already is one, for STYLE_GLOB it needs to be added. + if (len && buffer[len - 1] == NUL) { + len--; + } else { buffer[len] = NUL; + } i = 0; - for (p = buffer; p < buffer + len; ++p) - if (*p == NUL || (*p == ' ' && check_spaces)) { /* count entry */ - ++i; + for (p = buffer; p < buffer + len; p++) { + if (*p == NUL || (*p == ' ' && check_spaces)) { // count entry + i++; *p = NUL; } - if (len) - ++i; /* count last entry */ + } + if (len) { + i++; // count last entry + } } assert(buffer[len] == NUL || buffer[len] == '\n'); if (i == 0) { - /* - * Can happen when using /bin/sh and typing ":e $NO_SUCH_VAR^I". - * /bin/sh will happily expand it to nothing rather than returning an - * error; and hey, it's good to check anyway -- webb. - */ + // Can happen when using /bin/sh and typing ":e $NO_SUCH_VAR^I". + // /bin/sh will happily expand it to nothing rather than returning an + // error; and hey, it's good to check anyway -- webb. xfree(buffer); goto notfound; } *num_file = i; *file = xmalloc(sizeof(char_u *) * (size_t)i); - /* - * Isolate the individual file names. - */ + // Isolate the individual file names. p = buffer; for (i = 0; i < *num_file; ++i) { (*file)[i] = p; - /* Space or NL separates */ + // Space or NL separates if (shell_style == STYLE_ECHO || shell_style == STYLE_BT || shell_style == STYLE_VIMGLOB) { while (!(shell_style == STYLE_ECHO && *p == ' ') - && *p != '\n' && *p != NUL) - ++p; - if (p == buffer + len) /* last entry */ + && *p != '\n' && *p != NUL) { + p++; + } + if (p == buffer + len) { // last entry *p = NUL; - else { + } else { *p++ = NUL; - p = skipwhite(p); /* skip to next entry */ + p = skipwhite(p); // skip to next entry } - } else { /* NUL separates */ - while (*p && p < buffer + len) /* skip entry */ - ++p; - ++p; /* skip NUL */ + } else { // NUL separates + while (*p && p < buffer + len) { // skip entry + p++; + } + p++; // skip NUL } } - /* - * Move the file names to allocated memory. - */ + // Move the file names to allocated memory. for (j = 0, i = 0; i < *num_file; i++) { // Require the files to exist. Helps when using /bin/sh if (!(flags & EW_NOTFOUND) && !os_path_exists((*file)[i])) { continue; } - /* check if this entry should be included */ + // check if this entry should be included dir = (os_isdir((*file)[i])); if ((dir && !(flags & EW_DIR)) || (!dir && !(flags & EW_FILE))) continue; @@ -584,14 +593,15 @@ int mch_expand_wildcards(int num_pat, char_u **pat, int *num_file, p = xmalloc(STRLEN((*file)[i]) + 1 + dir); STRCPY(p, (*file)[i]); - if (dir) - add_pathsep((char *)p); /* add '/' to a directory name */ + if (dir) { + add_pathsep((char *)p); // add '/' to a directory name + } (*file)[j++] = p; } xfree(buffer); *num_file = j; - if (*num_file == 0) { /* rejected all entries */ + if (*num_file == 0) { // rejected all entries xfree(*file); *file = NULL; goto notfound; @@ -619,8 +629,8 @@ static void save_patterns(int num_pat, char_u **pat, int *num_file, for (i = 0; i < num_pat; i++) { s = vim_strsave(pat[i]); - /* Be compatible with expand_filename(): halve the number of - * backslashes. */ + // Be compatible with expand_filename(): halve the number of + // backslashes. backslash_halve(s); (*file)[i] = s; } diff --git a/src/nvim/path.c b/src/nvim/path.c index 3d1def8dd4..f2339c8046 100644 --- a/src/nvim/path.c +++ b/src/nvim/path.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #include <assert.h> #include <inttypes.h> #include <stdbool.h> @@ -84,15 +87,15 @@ FileComparison path_full_compare(char_u *s1, char_u *s2, int checkname) /// /// @return pointer just past the last path separator (empty string, if fname /// ends in a slash), or empty string if fname is NULL. -char_u *path_tail(char_u *fname) +char_u *path_tail(const char_u *fname) FUNC_ATTR_NONNULL_RET { if (fname == NULL) { return (char_u *)""; } - char_u *tail = get_past_head(fname); - char_u *p = tail; + const char_u *tail = get_past_head(fname); + const char_u *p = tail; // Find last part of path. while (*p != NUL) { if (vim_ispathsep_nocolon(*p)) { @@ -100,7 +103,7 @@ char_u *path_tail(char_u *fname) } mb_ptr_adv(p); } - return tail; + return (char_u *)tail; } /// Get pointer to tail of "fname", including path separators. @@ -159,7 +162,7 @@ const char_u *invocation_path_tail(const char_u *invocation, size_t *len) /// @param fname A file path. (Must be != NULL.) /// @return Pointer to first found path separator + 1. /// An empty string, if `fname` doesn't contain a path separator, -char_u *path_next_component(char_u *fname) +const char *path_next_component(const char *fname) { assert(fname != NULL); while (*fname != NUL && !vim_ispathsep(*fname)) { @@ -174,9 +177,9 @@ char_u *path_next_component(char_u *fname) /// Get a pointer to one character past the head of a path name. /// Unix: after "/"; Win: after "c:\" /// If there is no head, path is returned. -char_u *get_past_head(char_u *path) +char_u *get_past_head(const char_u *path) { - char_u *retval = path; + const char_u *retval = path; #ifdef WIN32 // May skip "c:" @@ -189,7 +192,7 @@ char_u *get_past_head(char_u *path) ++retval; } - return retval; + return (char_u *)retval; } /* @@ -282,48 +285,63 @@ bool dir_of_file_exists(char_u *fname) return retval; } -/* - * Versions of fnamecmp() and fnamencmp() that handle '/' and '\' equally - * and deal with 'fileignorecase'. - */ -int vim_fnamecmp(char_u *x, char_u *y) +/// Compare two file names +/// +/// Handles '/' and '\\' correctly and deals with &fileignorecase option. +/// +/// @param[in] fname1 First file name. +/// @param[in] fname2 Second file name. +/// +/// @return 0 if they are equal, non-zero otherwise. +int path_fnamecmp(const char *fname1, const char *fname2) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT { #ifdef BACKSLASH_IN_FILENAME - return vim_fnamencmp(x, y, MAXPATHL); + const size_t len1 = strlen(fname1); + const size_t len2 = strlen(fname2); + return path_fnamencmp(fname1, fname2, MAX(len1, len2)); #else - if (p_fic) - return mb_stricmp(x, y); - return STRCMP(x, y); + return mb_strcmp_ic((bool)p_fic, fname1, fname2); #endif } -int vim_fnamencmp(char_u *x, char_u *y, size_t len) +/// Compare two file names +/// +/// Handles '/' and '\\' correctly and deals with &fileignorecase option. +/// +/// @param[in] fname1 First file name. +/// @param[in] fname2 Second file name. +/// @param[in] len Compare at most len bytes. +/// +/// @return 0 if they are equal, non-zero otherwise. +int path_fnamencmp(const char *const fname1, const char *const fname2, + size_t len) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT { #ifdef BACKSLASH_IN_FILENAME - char_u *px = x; - char_u *py = y; - int cx = NUL; - int cy = NUL; + int c1 = NUL; + int c2 = NUL; + const char *p1 = fname1; + const char *p2 = fname2; while (len > 0) { - cx = PTR2CHAR(px); - cy = PTR2CHAR(py); - if (cx == NUL || cy == NUL - || ((p_fic ? vim_tolower(cx) != vim_tolower(cy) : cx != cy) - && !(cx == '/' && cy == '\\') - && !(cx == '\\' && cy == '/'))) + c1 = PTR2CHAR((const char_u *)p1); + c2 = PTR2CHAR((const char_u *)p2); + if ((c1 == NUL || c2 == NUL + || (!((c1 == '/' || c1 == '\\') && (c2 == '\\' || c2 == '/')))) + && (p_fic ? (c1 != c2 && CH_FOLD(c1) != CH_FOLD(c2)) : c1 != c2)) { break; - len -= MB_PTR2LEN(px); - px += MB_PTR2LEN(px); - py += MB_PTR2LEN(py); + } + len -= MB_PTR2LEN((const char_u *)p1); + p1 += MB_PTR2LEN((const char_u *)p1); + p2 += MB_PTR2LEN((const char_u *)p2); } - if (len == 0) - return 0; - return cx - cy; + return c1 - c2; #else - if (p_fic) - return mb_strnicmp(x, y, len); - return STRNCMP(x, y, len); + if (p_fic) { + return mb_strnicmp((const char_u *)fname1, (const char_u *)fname2, len); + } + return strncmp(fname1, fname2, len); #endif } @@ -391,15 +409,22 @@ char *concat_fnames_realloc(char *fname1, const char *fname2, bool sep) fname2, len2, sep); } -/* - * Add a path separator to a file name, unless it already ends in a path - * separator. - */ -void add_pathsep(char *p) +/// Adds a path separator to a filename, unless it already ends in one. +/// +/// @return `true` if the path separator was added or already existed. +/// `false` if the filename is too long. +bool add_pathsep(char *p) FUNC_ATTR_NONNULL_ALL { - if (*p != NUL && !after_pathsep(p, p + strlen(p))) - strcat(p, PATHSEPSTR); + const size_t len = strlen(p); + if (*p != NUL && !after_pathsep(p, p + len)) { + const size_t pathsep_len = sizeof(PATHSEPSTR); + if (len > MAXPATHL - pathsep_len) { + return false; + } + memcpy(p + len, PATHSEPSTR, pathsep_len); + } + return true; } /// Get an allocated copy of the full path to a file. @@ -409,8 +434,8 @@ void add_pathsep(char *p) /// /// @return [allocated] Copy of absolute path to `fname` or NULL when /// `fname` is NULL. -char *FullName_save(char *fname, bool force) - FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC +char *FullName_save(const char *fname, bool force) + FUNC_ATTR_MALLOC { if (fname == NULL) { return NULL; @@ -428,7 +453,7 @@ char *FullName_save(char *fname, bool force) /// @param name An absolute or relative path. /// @return The absolute path of `name`. char_u *save_absolute_path(const char_u *name) - FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_RET FUNC_ATTR_NONNULL_ALL + FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL { if (!path_is_absolute_path(name)) { return (char_u *)FullName_save((char *)name, true); @@ -579,7 +604,7 @@ static size_t do_path_expand(garray_T *gap, const char_u *path, } if (has_mbyte) { len = (size_t)(*mb_ptr2len)(path_end); - STRNCPY(p, path_end, len); + memcpy(p, path_end, len); p += len; path_end += len; } else @@ -797,7 +822,7 @@ static void expand_path_option(char_u *curdir, garray_T *gap) } STRMOVE(buf + len + 1, buf); STRCPY(buf, curdir); - buf[len] = PATHSEP; + buf[len] = (char_u)PATHSEP; simplify_filename(buf); } @@ -884,9 +909,9 @@ static void uniquefy_paths(garray_T *gap, char_u *pattern) in_curdir = xcalloc((size_t)gap->ga_len, sizeof(char_u *)); for (int i = 0; i < gap->ga_len && !got_int; i++) { - char_u *path = fnames[i]; + char_u *path = fnames[i]; int is_in_curdir; - char_u *dir_end = gettail_dir(path); + char_u *dir_end = (char_u *)gettail_dir((const char *)path); char_u *pathsep_p; char_u *path_cutoff; @@ -988,20 +1013,22 @@ static void uniquefy_paths(garray_T *gap, char_u *pattern) ga_remove_duplicate_strings(gap); } -/* - * Return the end of the directory name, on the first path - * separator: - * "/path/file", "/path/dir/", "/path//dir", "/file" - * ^ ^ ^ ^ - */ -char_u *gettail_dir(const char_u *fname) +/// Find end of the directory name +/// +/// @param[in] fname File name to process. +/// +/// @return end of the directory name, on the first path separator: +/// +/// "/path/file", "/path/dir/", "/path//dir", "/file" +/// ^ ^ ^ ^ +const char *gettail_dir(const char *const fname) + FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL { - const char_u *dir_end = fname; - const char_u *next_dir_end = fname; + const char *dir_end = fname; + const char *next_dir_end = fname; bool look_for_sep = true; - const char_u *p; - for (p = fname; *p != NUL; ) { + for (const char *p = fname; *p != NUL; ) { if (vim_ispathsep(*p)) { if (look_for_sep) { next_dir_end = p; @@ -1014,7 +1041,7 @@ char_u *gettail_dir(const char_u *fname) } mb_ptr_adv(p); } - return (char_u *)dir_end; + return dir_end; } @@ -1220,7 +1247,7 @@ int gen_expand_wildcards(int num_pat, char_u **pat, int *num_file, * "vim c:/" work. */ if (flags & EW_NOTFOUND) { addfile(&ga, t, flags | EW_DIR | EW_FILE); - } else if (os_path_exists(t)) { + } else { addfile(&ga, t, flags); } xfree(t); @@ -1309,12 +1336,12 @@ static int expand_backtick( /// When the path looks like a URL leave it unmodified. void slash_adjust(char_u *p) { - if (path_with_url(p)) { + if (path_with_url((const char *)p)) { return; } while (*p) { - if (*p == psepcN) { - *p = psepc; + if (*p == (char_u)psepcN) { + *p = (char_u)psepc; } mb_ptr_adv(p); } @@ -1533,8 +1560,8 @@ void simplify_filename(char_u *filename) p = tail; /* skip to char after ".." or "../" */ } } else { - ++components; /* simple path component */ - p = path_next_component(p); + components++; // Simple path component. + p = (char_u *)path_next_component((const char *)p); } } while (*p != NUL); } @@ -1688,7 +1715,7 @@ int vim_FullName(const char *fname, char *buf, size_t len, bool force) /// /// @param fname is the filename to expand /// @return [allocated] Full path (NULL for failure). -char *fix_fname(char *fname) +char *fix_fname(const char *fname) { #ifdef UNIX return FullName_save(fname, true); @@ -1829,7 +1856,7 @@ int pathcmp(const char *p, const char *q, int maxlen) break; } - if ((p_fic ? vim_toupper(c1) != vim_toupper(c2) : c1 != c2) + if ((p_fic ? mb_toupper(c1) != mb_toupper(c2) : c1 != c2) #ifdef BACKSLASH_IN_FILENAME /* consider '/' and '\\' to be equal */ && !((c1 == '/' && c2 == '\\') @@ -1840,8 +1867,8 @@ int pathcmp(const char *p, const char *q, int maxlen) return -1; if (vim_ispathsep(c2)) return 1; - return p_fic ? vim_toupper(c1) - vim_toupper(c2) - : c1 - c2; /* no match */ + return p_fic ? mb_toupper(c1) - mb_toupper(c2) + : c1 - c2; // no match } i += MB_PTR2LEN((char_u *)p + i); @@ -2124,17 +2151,12 @@ int append_path(char *path, const char *to_append, size_t max_len) size_t current_length = strlen(path); size_t to_append_length = strlen(to_append); - // Do not append empty strings. - if (to_append_length == 0) { + // Do not append empty string or a dot. + if (to_append_length == 0 || strcmp(to_append, ".") == 0) { return OK; } - // Do not append a dot. - if (STRCMP(to_append, ".") == 0) { - return OK; - } - - // Glue both paths with a slash. + // Combine the path segments, separated by a slash. if (current_length > 0 && !vim_ispathsep_nocolon(path[current_length-1])) { current_length += 1; // Count the trailing slash. @@ -2143,7 +2165,7 @@ int append_path(char *path, const char *to_append, size_t max_len) return FAIL; } - STRCAT(path, PATHSEPSTR); + xstrlcat(path, PATHSEPSTR, max_len); } // +1 for the NUL at the end. @@ -2151,7 +2173,7 @@ int append_path(char *path, const char *to_append, size_t max_len) return FAIL; } - STRCAT(path, to_append); + xstrlcat(path, to_append, max_len); return OK; } @@ -2181,7 +2203,8 @@ static int path_get_absolute_path(const char_u *fname, char_u *buf, relative_directory[0] = '/'; relative_directory[1] = NUL; } else { - STRNCPY(relative_directory, fname, p-fname); + assert(p >= fname); + memcpy(relative_directory, fname, (size_t)(p - fname)); relative_directory[p-fname] = NUL; } end_of_path = (char *) (p + 1); @@ -2214,3 +2237,50 @@ int path_is_absolute_path(const char_u *fname) return *fname == '/' || *fname == '~'; #endif } + +/// Builds a full path from an invocation name `argv0`, based on heuristics. +/// +/// @param[in] argv0 Name by which Nvim was invoked. +/// @param[out] buf Guessed full path to `argv0`. +/// @param[in] bufsize Size of `buf`. +/// +/// @see os_exepath +void path_guess_exepath(const char *argv0, char *buf, size_t bufsize) + FUNC_ATTR_NONNULL_ALL +{ + char *path = getenv("PATH"); + + if (path == NULL || path_is_absolute_path((char_u *)argv0)) { + xstrlcpy(buf, argv0, bufsize); + } else if (argv0[0] == '.' || strchr(argv0, PATHSEP)) { + // Relative to CWD. + if (os_dirname((char_u *)buf, MAXPATHL) != OK) { + buf[0] = NUL; + } + xstrlcat(buf, PATHSEPSTR, bufsize); + xstrlcat(buf, argv0, bufsize); + } else { + // Search $PATH for plausible location. + const void *iter = NULL; + do { + const char *dir; + size_t dir_len; + iter = vim_env_iter(ENV_SEPCHAR, path, iter, &dir, &dir_len); + if (dir == NULL || dir_len == 0) { + break; + } + if (dir_len + 1 > sizeof(NameBuff)) { + continue; + } + xstrlcpy((char *)NameBuff, dir, dir_len + 1); + xstrlcat((char *)NameBuff, PATHSEPSTR, sizeof(NameBuff)); + xstrlcat((char *)NameBuff, argv0, sizeof(NameBuff)); + if (os_can_exe(NameBuff, NULL, false)) { + xstrlcpy(buf, (char *)NameBuff, bufsize); + return; + } + } while (iter != NULL); + // Not found in $PATH, fall back to argv0. + xstrlcpy(buf, argv0, bufsize); + } +} diff --git a/src/nvim/po/CMakeLists.txt b/src/nvim/po/CMakeLists.txt index d2b62f89a0..121f22129a 100644 --- a/src/nvim/po/CMakeLists.txt +++ b/src/nvim/po/CMakeLists.txt @@ -32,10 +32,10 @@ if(HAVE_WORKING_LIBINTL AND GETTEXT_FOUND AND XGETTEXT_PRG AND ICONV_PRG) zh_CN.UTF-8 zh_TW.UTF-8) - set(NEOVIM_RELATIVE_SOURCES) - foreach(SRC ${NEOVIM_SOURCES} ${NEOVIM_HEADERS}) + set(NVIM_RELATIVE_SOURCES) + foreach(SRC ${NVIM_SOURCES} ${NVIM_HEADERS}) file(RELATIVE_PATH RELATIVE_SRC ${CMAKE_CURRENT_SOURCE_DIR} ${SRC}) - list(APPEND NEOVIM_RELATIVE_SOURCES ${RELATIVE_SRC}) + list(APPEND NVIM_RELATIVE_SOURCES ${RELATIVE_SRC}) endforeach() set(NVIM_POT ${CMAKE_CURRENT_BINARY_DIR}/nvim.pot) @@ -46,9 +46,9 @@ if(HAVE_WORKING_LIBINTL AND GETTEXT_FOUND AND XGETTEXT_PRG AND ICONV_PRG) -DXGETTEXT_PRG=${XGETTEXT_PRG} -DPOT_FILE=${NVIM_POT} -DSEARCH_DIR=${CMAKE_CURRENT_SOURCE_DIR} - "\"-DSOURCES=${NEOVIM_RELATIVE_SOURCES}\"" + "\"-DSOURCES=${NVIM_RELATIVE_SOURCES}\"" -P ${PROJECT_SOURCE_DIR}/cmake/RunXgettext.cmake - DEPENDS ${NEOVIM_SOURCES}) + DEPENDS ${NVIM_SOURCES}) add_custom_target(potfile DEPENDS ${NVIM_POT}) diff --git a/src/nvim/po/check.vim b/src/nvim/po/check.vim index 1622741da6..b323174550 100644 --- a/src/nvim/po/check.vim +++ b/src/nvim/po/check.vim @@ -33,36 +33,66 @@ func! GetMline() return substitute(idline, '[^%]*\(%[-+ #''.0-9*]*l\=[dsuxXpoc%]\)\=', '\1', 'g') endfunc -" This only works when 'wrapscan' is set. +" This only works when 'wrapscan' is not set. let s:save_wrapscan = &wrapscan -set wrapscan +set nowrapscan " Start at the first "msgid" line. 1 -/^msgid -let startline = line('.') +/^msgid\> + +" When an error is detected this is set to the line number. +" Note: this is used in the Makefile. let error = 0 while 1 if getline(line('.') - 1) !~ "no-c-format" - let fromline = GetMline() + " go over the "msgid" and "msgid_plural" lines + let prevfromline = 'foobar' + while 1 + let fromline = GetMline() + if prevfromline != 'foobar' && prevfromline != fromline + echomsg 'Mismatching % in line ' . (line('.') - 1) + echomsg 'msgid: ' . prevfromline + echomsg 'msgid ' . fromline + if error == 0 + let error = line('.') + endif + endif + if getline('.') !~ 'msgid_plural' + break + endif + let prevfromline = fromline + endwhile + if getline('.') !~ '^msgstr' - echo 'Missing "msgstr" in line ' . line('.') - let error = 1 - endif - let toline = GetMline() - if fromline != toline - echo 'Mismatching % in line ' . (line('.') - 1) - echo 'msgid: ' . fromline - echo 'msgstr: ' . toline - let error = 1 + echomsg 'Missing "msgstr" in line ' . line('.') + if error == 0 + let error = line('.') + endif endif + + " check all the 'msgstr' lines + while getline('.') =~ '^msgstr' + let toline = GetMline() + if fromline != toline + echomsg 'Mismatching % in line ' . (line('.') - 1) + echomsg 'msgid: ' . fromline + echomsg 'msgstr: ' . toline + if error == 0 + let error = line('.') + endif + endif + if line('.') == line('$') + break + endif + endwhile endif - " Find next msgid. - " Wrap around at the end of the file, quit when back at the first one. - /^msgid - if line('.') == startline + " Find next msgid. Quit when there is no more. + let lnum = line('.') + silent! /^msgid\> + if line('.') == lnum break endif endwhile @@ -77,12 +107,16 @@ endwhile " 1 if search('msgid "\("\n"\)\?\([EW][0-9]\+:\).*\nmsgstr "\("\n"\)\?[^"]\@=\2\@!') > 0 - echo 'Mismatching error/warning code in line ' . line('.') - let error = 1 + echomsg 'Mismatching error/warning code in line ' . line('.') + if error == 0 + let error = line('.') + endif endif if error == 0 - echo "OK" + echomsg "OK" +else + exe error endif redir END diff --git a/src/nvim/po/eo.po b/src/nvim/po/eo.po index d0a47d6e9b..3fb300c63f 100644 --- a/src/nvim/po/eo.po +++ b/src/nvim/po/eo.po @@ -5,7 +5,7 @@ # # UNUA TRADUKISTO Dominique PELLE <dominique.pelle ฤe gmail.com> # PROVLEGANTO(J) Felipe CASTRO <fefcas ฤe gmail.com> -# Antono MECHELYNCK <antoine.mechelynck ฤe skynet.be> +# Antono MECHELYNCK <antoine.mechelynck ฤe gmail.com> # Yves NEVELSTEEN # # Uzitaj vortaroj kaj fakvortaroj: @@ -23,8 +23,8 @@ msgid "" msgstr "" "Project-Id-Version: Vim(Esperanto)\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2016-03-29 23:03+0200\n" -"PO-Revision-Date: 2016-03-29 23:05+0200\n" +"POT-Creation-Date: 2017-01-16 00:30+0100\n" +"PO-Revision-Date: 2017-01-16 01:14+0100\n" "Last-Translator: Dominique PELLร <dominique.pelle@gmail.com>\n" "Language-Team: \n" "Language: eo\n" @@ -32,203 +32,169 @@ msgstr "" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -#: ../api/private/helpers.c:201 -#, fuzzy -msgid "Unable to get option value" -msgstr "fiaskis akiri valoron de opcio" +msgid "E831: bf_key_init() called with empty password" +msgstr "E831: bf_key_init() alvokita kun malplena pasvorto" -#: ../api/private/helpers.c:204 -#, fuzzy -msgid "internal error: unknown option type" -msgstr "interna eraro: neniu vim-a listero" +msgid "E820: sizeof(uint32_t) != 4" +msgstr "E820: sizeof(uint32_t) != 4" + +msgid "E817: Blowfish big/little endian use wrong" +msgstr "E817: Misuzo de pezkomenca/pezfina en blowfish" + +msgid "E818: sha256 test failed" +msgstr "E818: Testo de sha256 malsukcesis" + +msgid "E819: Blowfish test failed" +msgstr "E819: Testo de blowfish malsukcesis" -#: ../buffer.c:92 msgid "[Location List]" msgstr "[Listo de lokoj]" # DP: ฤu vere indas traduki Quickfix? -#: ../buffer.c:93 msgid "[Quickfix List]" msgstr "[Listo de rapidriparoj]" -#: ../buffer.c:94 msgid "E855: Autocommands caused command to abort" msgstr "E855: Aลญtokomandoj haltigis komandon" -#: ../buffer.c:135 msgid "E82: Cannot allocate any buffer, exiting..." msgstr "E82: Ne eblas disponigi iun ajn bufron, nun eliras..." -#: ../buffer.c:138 msgid "E83: Cannot allocate buffer, using other one..." msgstr "E83: Ne eblas disponigi bufron, nun uzas alian..." -#: ../buffer.c:763 +msgid "E931: Buffer cannot be registered" +msgstr "E931: Bufro ne povas esti registrita" + +msgid "E937: Attempt to delete a buffer that is in use" +msgstr "E937: Provo de forviลo de bufro, kiu estas uzanta" + msgid "E515: No buffers were unloaded" msgstr "E515: Neniu bufro estis malลargita" -#: ../buffer.c:765 msgid "E516: No buffers were deleted" msgstr "E516: Neniu bufro estis forviลita" -#: ../buffer.c:767 msgid "E517: No buffers were wiped out" msgstr "E517: Neniu bufro estis detruita" -#: ../buffer.c:772 msgid "1 buffer unloaded" msgstr "1 bufro malลargita" -#: ../buffer.c:774 #, c-format msgid "%d buffers unloaded" msgstr "%d bufroj malลargitaj" -#: ../buffer.c:777 msgid "1 buffer deleted" msgstr "1 bufro forviลita" -#: ../buffer.c:779 #, c-format msgid "%d buffers deleted" msgstr "%d bufroj forviลitaj" -#: ../buffer.c:782 msgid "1 buffer wiped out" msgstr "1 bufro detruita" -#: ../buffer.c:784 #, c-format msgid "%d buffers wiped out" msgstr "%d bufroj detruitaj" -#: ../buffer.c:806 msgid "E90: Cannot unload last buffer" msgstr "E90: Ne eblas malลargi la lastan bufron" -#: ../buffer.c:874 msgid "E84: No modified buffer found" msgstr "E84: Neniu modifita bufro trovita" #. back where we started, didn't find anything. -#: ../buffer.c:903 msgid "E85: There is no listed buffer" msgstr "E85: Estas neniu listigita bufro" -#: ../buffer.c:915 msgid "E87: Cannot go beyond last buffer" msgstr "E87: Ne eblas iri preter la lastan bufron" -#: ../buffer.c:917 msgid "E88: Cannot go before first buffer" msgstr "E88: Ne eblas iri antaลญ la unuan bufron" -#: ../buffer.c:945 #, c-format -msgid "" -"E89: No write since last change for buffer %<PRId64> (add ! to override)" +msgid "E89: No write since last change for buffer %ld (add ! to override)" msgstr "" -"E89: Neniu skribo de post la lasta ลanฤo de la bufro %<PRId64> (aldonu ! por " +"E89: Neniu skribo de post la lasta ลanฤo de la bufro %ld (aldonu ! por " "transpasi)" -#. wrap around (may cause duplicates) -#: ../buffer.c:1423 msgid "W14: Warning: List of file names overflow" msgstr "W14: Averto: Listo de dosiernomoj troas" -#: ../buffer.c:1555 ../quickfix.c:3361 #, c-format -msgid "E92: Buffer %<PRId64> not found" -msgstr "E92: Bufro %<PRId64> ne trovita" +msgid "E92: Buffer %ld not found" +msgstr "E92: Bufro %ld ne trovita" -#: ../buffer.c:1798 #, c-format msgid "E93: More than one match for %s" msgstr "E93: Pli ol unu kongruo kun %s" -#: ../buffer.c:1800 #, c-format msgid "E94: No matching buffer for %s" msgstr "E94: Neniu bufro kongruas kun %s" -#: ../buffer.c:2161 #, c-format -msgid "line %<PRId64>" -msgstr "linio %<PRId64>" +msgid "line %ld" +msgstr "linio %ld" -#: ../buffer.c:2233 msgid "E95: Buffer with this name already exists" msgstr "E95: Bufro kun tiu nomo jam ekzistas" -#: ../buffer.c:2498 msgid " [Modified]" msgstr "[Modifita]" -#: ../buffer.c:2501 msgid "[Not edited]" msgstr "[Ne redaktita]" -#: ../buffer.c:2504 msgid "[New file]" msgstr "[Nova dosiero]" -#: ../buffer.c:2505 msgid "[Read errors]" msgstr "[Eraroj de legado]" -#: ../buffer.c:2506 ../buffer.c:3217 ../fileio.c:1807 ../screen.c:4895 msgid "[RO]" msgstr "[Nurlegebla]" -#: ../buffer.c:2507 ../fileio.c:1807 msgid "[readonly]" msgstr "[nurlegebla]" -#: ../buffer.c:2524 #, c-format msgid "1 line --%d%%--" msgstr "1 linio --%d%%--" -#: ../buffer.c:2526 #, c-format -msgid "%<PRId64> lines --%d%%--" -msgstr "%<PRId64> linioj --%d%%--" +msgid "%ld lines --%d%%--" +msgstr "%ld linioj --%d%%--" -#: ../buffer.c:2530 #, c-format -msgid "line %<PRId64> of %<PRId64> --%d%%-- col " -msgstr "linio %<PRId64> de %<PRId64> --%d%%-- kol " +msgid "line %ld of %ld --%d%%-- col " +msgstr "linio %ld de %ld --%d%%-- kol " -#: ../buffer.c:2632 ../buffer.c:4292 ../memline.c:1554 msgid "[No Name]" msgstr "[Neniu nomo]" #. must be a help buffer -#: ../buffer.c:2667 msgid "help" msgstr "helpo" -#: ../buffer.c:3225 ../screen.c:4883 msgid "[Help]" msgstr "[Helpo]" -#: ../buffer.c:3254 ../screen.c:4887 msgid "[Preview]" msgstr "[Antaลญvido]" -#: ../buffer.c:3528 msgid "All" msgstr "ฤio" -#: ../buffer.c:3528 msgid "Bot" msgstr "Subo" -#: ../buffer.c:3531 msgid "Top" msgstr "Supro" -#: ../buffer.c:4244 msgid "" "\n" "# Buffer list:\n" @@ -236,12 +202,10 @@ msgstr "" "\n" "# Listo de bufroj:\n" -#: ../buffer.c:4289 msgid "[Scratch]" msgstr "[Malneto]" # DP: Vidu ":help sign-support" por klarigo pri "Sign" -#: ../buffer.c:4529 msgid "" "\n" "--- Signs ---" @@ -249,200 +213,235 @@ msgstr "" "\n" "--- Emfazaj simbolaฤตoj ---" -#: ../buffer.c:4538 #, c-format msgid "Signs for %s:" msgstr "Emfazaj simbolaฤตoj de %s:" -#: ../buffer.c:4543 #, c-format -msgid " line=%<PRId64> id=%d name=%s" -msgstr " linio=%<PRId64> id=%d nomo=%s" +msgid " line=%ld id=%d name=%s" +msgstr " linio=%ld id=%d nomo=%s" -#: ../cursor_shape.c:68 -msgid "E545: Missing colon" -msgstr "E545: Mankas dupunkto" +msgid "E902: Cannot connect to port" +msgstr "E902: Ne eblas konekti al pordo" -#: ../cursor_shape.c:70 ../cursor_shape.c:94 -msgid "E546: Illegal mode" -msgstr "E546: Reฤimo nepermesata" +msgid "E901: gethostbyname() in channel_open()" +msgstr "E901: gethostbyname() en channel_open()" -#: ../cursor_shape.c:134 -msgid "E548: digit expected" -msgstr "E548: cifero atendata" +msgid "E898: socket() in channel_open()" +msgstr "E898: gethostbyname() en channel_open()" -#: ../cursor_shape.c:138 -msgid "E549: Illegal percentage" -msgstr "E549: Nevalida procento" +msgid "E903: received command with non-string argument" +msgstr "E903: ricevis komandon kun argumento, kiu ne estas ฤeno" + +msgid "E904: last argument for expr/call must be a number" +msgstr "E904: lasta argumento de \"expr/call\" devas esti nombro" + +msgid "E904: third argument for call must be a list" +msgstr "E904: tria argumento de \"call\" devas esti listo" + +#, c-format +msgid "E905: received unknown command: %s" +msgstr "E905: nekonata komando ricevita: %s" + +#, c-format +msgid "E630: %s(): write while not connected" +msgstr "E630: %s(): konservo dum nekonektita" + +#, c-format +msgid "E631: %s(): write failed" +msgstr "E631: %s(): Konservo malsukcesis" + +#, c-format +msgid "E917: Cannot use a callback with %s()" +msgstr "E917: Ne eblas uzi reagfunkcion kun %s()" + +msgid "E912: cannot use ch_evalexpr()/ch_sendexpr() with a raw or nl channel" +msgstr "E912: ne eblas uzi ch_evalexpr()/ch_sendexpr() kun kruda aลญ nl kanalo" + +msgid "E906: not an open channel" +msgstr "E906: ne estas malfermita kanalo" + +msgid "E920: _io file requires _name to be set" +msgstr "E920: dosiero _io bezonas _name" + +msgid "E915: in_io buffer requires in_buf or in_name to be set" +msgstr "E915: bufro in_io bezonas in_buf aลญ in_name" + +#, c-format +msgid "E918: buffer must be loaded: %s" +msgstr "E918: bufro devas esti ลargita: %s" + +msgid "E821: File is encrypted with unknown method" +msgstr "E821: Dosiero estas ฤifrita per nekonata metodo" + +msgid "Warning: Using a weak encryption method; see :help 'cm'" +msgstr "Averto: uzo de malfortika ฤifrada metodo; vidu :help 'cm'" + +msgid "Enter encryption key: " +msgstr "Tajpu la ลlosilon de ฤifrado: " + +msgid "Enter same key again: " +msgstr "Tajpu la ลlosilon denove: " + +msgid "Keys don't match!" +msgstr "ลlosiloj ne kongruas!" + +msgid "[crypted]" +msgstr "[ฤifrita]" + +#, c-format +msgid "E720: Missing colon in Dictionary: %s" +msgstr "E720: Mankas dupunkto en la vortaro: %s" + +#, c-format +msgid "E721: Duplicate key in Dictionary: \"%s\"" +msgstr "E721: Ripetita ลlosilo en la vortaro: \"%s\"" + +#, c-format +msgid "E722: Missing comma in Dictionary: %s" +msgstr "E722: Mankas komo en la vortaro: %s" + +#, c-format +msgid "E723: Missing end of Dictionary '}': %s" +msgstr "E723: Mankas fino de vortaro '}': %s" + +msgid "extend() argument" +msgstr "argumento de extend()" -#: ../diff.c:146 #, c-format -msgid "E96: Can not diff more than %<PRId64> buffers" -msgstr "E96: Ne eblas dosierdiferenci pli ol %<PRId64> bufrojn" +msgid "E737: Key already exists: %s" +msgstr "E737: ลlosilo jam ekzistas: %s" + +#, c-format +msgid "E96: Cannot diff more than %ld buffers" +msgstr "E96: Ne eblas dosierdiferenci pli ol %ld bufrojn" -#: ../diff.c:753 msgid "E810: Cannot read or write temp files" msgstr "E810: Ne eblas legi aลญ skribi provizorajn dosierojn" -#: ../diff.c:755 msgid "E97: Cannot create diffs" msgstr "E97: Ne eblas krei dosierdiferencojn" -#: ../diff.c:966 +msgid "Patch file" +msgstr "Flika dosiero" + msgid "E816: Cannot read patch output" msgstr "E816: Ne eblas legi eliron de flikilo \"patch\"" -#: ../diff.c:1220 msgid "E98: Cannot read diff output" msgstr "E98: Ne eblas legi eliron de dosierdiferencilo \"diff\"" -#: ../diff.c:2081 msgid "E99: Current buffer is not in diff mode" msgstr "E99: Aktuala bufro ne estas en dosierdiferenca reฤimo" -#: ../diff.c:2100 msgid "E793: No other buffer in diff mode is modifiable" msgstr "E793: Neniu alia bufro en dosierdiferenca reฤimo estas modifebla" -#: ../diff.c:2102 msgid "E100: No other buffer in diff mode" msgstr "E100: Neniu alia bufro en dosierdiferenca reฤimo" -#: ../diff.c:2112 msgid "E101: More than two buffers in diff mode, don't know which one to use" msgstr "E101: Pli ol du bufroj en dosierdiferenca reฤimo, ne scias kiun uzi" -#: ../diff.c:2141 #, c-format msgid "E102: Can't find buffer \"%s\"" msgstr "E102: Ne eblas trovi bufron \"%s\"" -#: ../diff.c:2152 #, c-format msgid "E103: Buffer \"%s\" is not in diff mode" msgstr "E103: Bufro \"%s\" ne estas en dosierdiferenca reฤimo" -#: ../diff.c:2193 msgid "E787: Buffer changed unexpectedly" msgstr "E787: Bufro ลanฤiฤis neatendite" -#: ../digraph.c:1598 msgid "E104: Escape not allowed in digraph" msgstr "E104: Eskapsigno nepermesebla en duliteraฤตo" -#: ../digraph.c:1760 msgid "E544: Keymap file not found" msgstr "E544: Dosiero de klavmapo ne troveblas" -#: ../digraph.c:1785 msgid "E105: Using :loadkeymap not in a sourced file" msgstr "E105: Uzo de \":loadkeymap\" nur eblas en vim-skripto" -#: ../digraph.c:1821 msgid "E791: Empty keymap entry" msgstr "E791: Malplena rikordo en klavmapo" -#: ../edit.c:82 msgid " Keyword completion (^N^P)" msgstr " Kompletigo de ลlosilvorto (^N^P)" #. ctrl_x_mode == 0, ^P/^N compl. -#: ../edit.c:83 msgid " ^X mode (^]^D^E^F^I^K^L^N^O^Ps^U^V^Y)" msgstr " Reฤimo ^X (^]^D^E^F^I^K^L^N^O^Ps^U^V^Y)" -#: ../edit.c:85 msgid " Whole line completion (^L^N^P)" msgstr " Kompletigo de tuta linio (^L^N^P)" -#: ../edit.c:86 msgid " File name completion (^F^N^P)" msgstr " Kompletigo de dosiernomo (^F^N^P)" -#: ../edit.c:87 msgid " Tag completion (^]^N^P)" msgstr " Kompletigo de etikedo (^]^N^P)" -#: ../edit.c:88 msgid " Path pattern completion (^N^P)" msgstr " Kompletigo de ลablona dosierindiko (^N^P)" -#: ../edit.c:89 msgid " Definition completion (^D^N^P)" msgstr " Kompletigo de difino (^D^N^P)" -#: ../edit.c:91 msgid " Dictionary completion (^K^N^P)" msgstr " Kompletigo de vortaro (^K^N^P)" -#: ../edit.c:92 msgid " Thesaurus completion (^T^N^P)" msgstr " Kompletigo de tezaลญro (^T^N^P)" -#: ../edit.c:93 msgid " Command-line completion (^V^N^P)" msgstr " Kompletigo de komanda linio (^V^N^P)" -#: ../edit.c:94 msgid " User defined completion (^U^N^P)" msgstr " Kompletigo difinita de uzanto (^U^N^P)" # DP: ฤu eblas trovi pli bonan tradukon? -#: ../edit.c:95 msgid " Omni completion (^O^N^P)" msgstr " Kompletigo Omni (^O^N^P)" -#: ../edit.c:96 msgid " Spelling suggestion (s^N^P)" msgstr " Sugesto de literumo (s^N^P)" -#: ../edit.c:97 msgid " Keyword Local completion (^N^P)" msgstr " Kompletigo loka de ลlosilvorto (^N/^P)" -#: ../edit.c:100 msgid "Hit end of paragraph" msgstr "Atingis finon de alineo" -#: ../edit.c:101 msgid "E839: Completion function changed window" msgstr "E839: Kompletiga funkcio ลanฤis la fenestron" -#: ../edit.c:102 msgid "E840: Completion function deleted text" msgstr "E840: Kompletiga funkcio forviลis tekston" -#: ../edit.c:1847 msgid "'dictionary' option is empty" msgstr "La opcio 'dictionary' estas malplena" -#: ../edit.c:1848 msgid "'thesaurus' option is empty" msgstr "La opcio 'thesaurus' estas malplena" -#: ../edit.c:2655 #, c-format msgid "Scanning dictionary: %s" msgstr "Analizas vortaron: %s" -#: ../edit.c:3079 msgid " (insert) Scroll (^E/^Y)" msgstr " (enmeto) Rulumo (^E/^Y)" -#: ../edit.c:3081 msgid " (replace) Scroll (^E/^Y)" msgstr " (anstataลญigo) Rulumo (^E/^Y)" -#: ../edit.c:3587 #, c-format msgid "Scanning: %s" msgstr "Analizas: %s" -#: ../edit.c:3614 msgid "Scanning tags." msgstr "Analizas etikedojn." -#: ../edit.c:4519 msgid " Adding" msgstr " Aldonanta" @@ -450,429 +449,159 @@ msgstr " Aldonanta" #. * be called before line = ml_get(), or when this address is no #. * longer needed. -- Acevedo. #. -#: ../edit.c:4562 msgid "-- Searching..." msgstr "-- Serฤanta..." -#: ../edit.c:4618 msgid "Back at original" msgstr "Reveninta al originalo" -#: ../edit.c:4621 msgid "Word from other line" msgstr "Vorto el alia linio" -#: ../edit.c:4624 msgid "The only match" msgstr "La sola kongruo" -#: ../edit.c:4680 #, c-format msgid "match %d of %d" msgstr "kongruo %d de %d" -#: ../edit.c:4684 #, c-format msgid "match %d" msgstr "kongruo %d" -#: ../eval.c:137 +#. maximum nesting of lists and dicts msgid "E18: Unexpected characters in :let" msgstr "E18: Neatenditaj signoj en \":let\"" -#: ../eval.c:138 -#, c-format -msgid "E684: list index out of range: %<PRId64>" -msgstr "E684: indekso de listo ekster limoj: %<PRId64>" - -#: ../eval.c:139 #, c-format msgid "E121: Undefined variable: %s" msgstr "E121: Nedifinita variablo: %s" -#: ../eval.c:140 msgid "E111: Missing ']'" msgstr "E111: Mankas ']'" -#: ../eval.c:141 -#, c-format -msgid "E686: Argument of %s must be a List" -msgstr "E686: Argumento de %s devas esti Listo" - -#: ../eval.c:143 -#, c-format -msgid "E712: Argument of %s must be a List or Dictionary" -msgstr "E712: Argumento de %s devas esti Listo aลญ Vortaro" - -#: ../eval.c:145 -msgid "E714: List required" -msgstr "E714: Listo bezonata" - -#: ../eval.c:146 -msgid "E715: Dictionary required" -msgstr "E715: Vortaro bezonata" - -#: ../eval.c:147 -#, c-format -msgid "E118: Too many arguments for function: %s" -msgstr "E118: Tro da argumentoj por funkcio: %s" - -#: ../eval.c:148 -#, c-format -msgid "E716: Key not present in Dictionary: %s" -msgstr "E716: ลlosilo malekzistas en Vortaro: %s" - -#: ../eval.c:150 -#, c-format -msgid "E122: Function %s already exists, add ! to replace it" -msgstr "E122: La funkcio %s jam ekzistas (aldonu ! por anstataลญigi ฤin)" - -#: ../eval.c:151 -msgid "E717: Dictionary entry already exists" -msgstr "E717: Rikordo de vortaro jam ekzistas" - -#: ../eval.c:152 -msgid "E718: Funcref required" -msgstr "E718: Funcref bezonata" - -#: ../eval.c:153 msgid "E719: Cannot use [:] with a Dictionary" msgstr "E719: Uzo de [:] ne eblas kun Vortaro" -#: ../eval.c:154 #, c-format msgid "E734: Wrong variable type for %s=" msgstr "E734: Nevalida datumtipo de variablo de %s=" -#: ../eval.c:155 -#, c-format -msgid "E130: Unknown function: %s" -msgstr "E130: Nekonata funkcio: %s" - -#: ../eval.c:156 #, c-format msgid "E461: Illegal variable name: %s" msgstr "E461: Nevalida nomo de variablo: %s" -#: ../eval.c:157 msgid "E806: using Float as a String" msgstr "E806: uzo de Glitpunktnombro kiel ฤeno" -#: ../eval.c:1830 msgid "E687: Less targets than List items" msgstr "E687: Malpli da celoj ol Listeroj" -#: ../eval.c:1834 msgid "E688: More targets than List items" msgstr "E688: Pli da celoj ol Listeroj" -#: ../eval.c:1906 msgid "Double ; in list of variables" msgstr "Duobla ; en listo de variabloj" -#: ../eval.c:2078 #, c-format msgid "E738: Can't list variables for %s" msgstr "E738: Ne eblas listigi variablojn de %s" -#: ../eval.c:2391 msgid "E689: Can only index a List or Dictionary" msgstr "E689: Nur eblas indeksi Liston aลญ Vortaron" -#: ../eval.c:2396 msgid "E708: [:] must come last" msgstr "E708: [:] devas esti laste" -#: ../eval.c:2439 msgid "E709: [:] requires a List value" msgstr "E709: [:] bezonas listan valoron" -#: ../eval.c:2674 msgid "E710: List value has more items than target" msgstr "E710: Lista valoro havas pli da eroj ol la celo" -#: ../eval.c:2678 msgid "E711: List value has not enough items" msgstr "E711: Lista valoro ne havas sufiฤe da eroj" -#: ../eval.c:2867 msgid "E690: Missing \"in\" after :for" msgstr "E690: \"in\" mankas post \":for\"" -#: ../eval.c:3063 -#, c-format -msgid "E107: Missing parentheses: %s" -msgstr "E107: Mankas krampoj: %s" - -#: ../eval.c:3263 #, c-format msgid "E108: No such variable: \"%s\"" msgstr "E108: Ne estas tia variablo: \"%s\"" -#: ../eval.c:3333 msgid "E743: variable nested too deep for (un)lock" msgstr "E743: variablo ingita tro profunde por malลlosi" -#: ../eval.c:3630 msgid "E109: Missing ':' after '?'" msgstr "E109: Mankas ':' post '?'" -#: ../eval.c:3893 msgid "E691: Can only compare List with List" msgstr "E691: Eblas nur kompari Liston kun Listo" -#: ../eval.c:3895 -msgid "E692: Invalid operation for Lists" +msgid "E692: Invalid operation for List" msgstr "E692: Nevalida operacio de Listoj" -#: ../eval.c:3915 msgid "E735: Can only compare Dictionary with Dictionary" msgstr "E735: Eblas nur kompari Vortaron kun Vortaro" -#: ../eval.c:3917 msgid "E736: Invalid operation for Dictionary" msgstr "E736: Nevalida operacio de Vortaro" -#: ../eval.c:3932 -msgid "E693: Can only compare Funcref with Funcref" -msgstr "E693: Eblas nur kompari Funcref kun Funcref" - -#: ../eval.c:3934 msgid "E694: Invalid operation for Funcrefs" msgstr "E694: Nevalida operacio de Funcref-oj" -#: ../eval.c:4277 msgid "E804: Cannot use '%' with Float" msgstr "E804: Ne eblas uzi '%' kun Glitpunktnombro" -#: ../eval.c:4478 msgid "E110: Missing ')'" msgstr "E110: Mankas ')'" -#: ../eval.c:4609 msgid "E695: Cannot index a Funcref" msgstr "E695: Ne eblas indeksi Funcref" msgid "E909: Cannot index a special variable" msgstr "E909: Ne eblas indeksi specialan variablon" -#: ../eval.c:4839 #, c-format msgid "E112: Option name missing: %s" msgstr "E112: Mankas nomo de opcio: %s" -#: ../eval.c:4855 #, c-format msgid "E113: Unknown option: %s" msgstr "E113: Nekonata opcio: %s" -#: ../eval.c:4904 #, c-format msgid "E114: Missing quote: %s" msgstr "E114: Mankas citilo: %s" -#: ../eval.c:5020 #, c-format msgid "E115: Missing quote: %s" msgstr "E115: Mankas citilo: %s" -#: ../eval.c:5084 -#, c-format -msgid "E696: Missing comma in List: %s" -msgstr "E696: Mankas komo en Listo: %s" - -#: ../eval.c:5091 -#, c-format -msgid "E697: Missing end of List ']': %s" -msgstr "E697: Mankas fino de Listo ']': %s" - -#: ../eval.c:5750 msgid "Not enough memory to set references, garbage collection aborted!" msgstr "Ne sufiฤa memoro por valorigi referencojn, senrubigado ฤesigita!" -#: ../eval.c:6475 -#, c-format -msgid "E720: Missing colon in Dictionary: %s" -msgstr "E720: Mankas dupunkto en la vortaro: %s" - -#: ../eval.c:6499 -#, c-format -msgid "E721: Duplicate key in Dictionary: \"%s\"" -msgstr "E721: Ripetita ลlosilo en la vortaro: \"%s\"" - -#: ../eval.c:6517 -#, c-format -msgid "E722: Missing comma in Dictionary: %s" -msgstr "E722: Mankas komo en la vortaro: %s" - -#: ../eval.c:6524 -#, c-format -msgid "E723: Missing end of Dictionary '}': %s" -msgstr "E723: Mankas fino de vortaro '}': %s" - -#: ../eval.c:6555 msgid "E724: variable nested too deep for displaying" msgstr "E724: variablo ingita tro profunde por vidigi" -#: ../eval.c:7188 -#, c-format -msgid "E740: Too many arguments for function %s" -msgstr "E740: Tro da argumentoj por funkcio: %s" - -#: ../eval.c:7190 -#, c-format -msgid "E116: Invalid arguments for function %s" -msgstr "E116: Nevalidaj argumentoj por funkcio: %s" - -#: ../eval.c:7377 -#, c-format -msgid "E117: Unknown function: %s" -msgstr "E117: Nekonata funkcio: %s" - -#: ../eval.c:7383 -#, c-format -msgid "E119: Not enough arguments for function: %s" -msgstr "E119: Ne sufiฤe da argumentoj por funkcio: %s" - -#: ../eval.c:7387 -#, c-format -msgid "E120: Using <SID> not in a script context: %s" -msgstr "E120: <SID> estas uzata ekster kunteksto de skripto: %s" - -#: ../eval.c:7391 -#, c-format -msgid "E725: Calling dict function without Dictionary: %s" -msgstr "E725: Alvoko de funkcio dict sen Vortaro: %s" - -#: ../eval.c:7453 -msgid "E808: Number or Float required" -msgstr "E808: Nombro aลญ Glitpunktnombro bezonata" - -#: ../eval.c:7503 -msgid "add() argument" -msgstr "argumento de add()" - -#: ../eval.c:7907 -msgid "E699: Too many arguments" -msgstr "E699: Tro da argumentoj" - -#: ../eval.c:8073 -msgid "E785: complete() can only be used in Insert mode" -msgstr "E785: complete() uzeblas nur en Enmeta reฤimo" - -#: ../eval.c:8156 -msgid "&Ok" -msgstr "&Bone" - -#: ../eval.c:8676 -#, c-format -msgid "E737: Key already exists: %s" -msgstr "E737: ลlosilo jam ekzistas: %s" - -#: ../eval.c:8692 -msgid "extend() argument" -msgstr "argumento de extend()" - -#: ../eval.c:8915 -msgid "map() argument" -msgstr "argumento de map()" - -#: ../eval.c:8916 -msgid "filter() argument" -msgstr "argumento de filter()" - -#: ../eval.c:9229 -#, c-format -msgid "+-%s%3ld lines: " -msgstr "+-%s%3ld linioj: " - -#: ../eval.c:9291 -#, c-format -msgid "E700: Unknown function: %s" -msgstr "E700: Nekonata funkcio: %s" - -#: ../eval.c:10729 -msgid "called inputrestore() more often than inputsave()" -msgstr "alvokis inputrestore() pli ofte ol inputsave()" - -#: ../eval.c:10771 -msgid "insert() argument" -msgstr "argumento de insert()" - -#: ../eval.c:10841 -msgid "E786: Range not allowed" -msgstr "E786: Amplekso nepermesebla" - -#: ../eval.c:11140 -msgid "E701: Invalid type for len()" -msgstr "E701: Nevalida datumtipo de len()" - -#: ../eval.c:11980 -msgid "E726: Stride is zero" -msgstr "E726: Paลo estas nul" - -#: ../eval.c:11982 -msgid "E727: Start past end" -msgstr "E727: Komenco preter fino" - -#: ../eval.c:12024 ../eval.c:15297 -msgid "<empty>" -msgstr "<malplena>" - -#: ../eval.c:12282 -msgid "remove() argument" -msgstr "argumento de remove()" - -#: ../eval.c:12466 -msgid "E655: Too many symbolic links (cycle?)" -msgstr "E655: Tro da simbolaj ligiloj (ฤu estas ciklo?)" - -#: ../eval.c:12593 -msgid "reverse() argument" -msgstr "argumento de reverse()" - -#: ../eval.c:13721 -msgid "sort() argument" -msgstr "argumento de sort()" - -#: ../eval.c:13721 -#, fuzzy -msgid "uniq() argument" -msgstr "argumento de add()" - -#: ../eval.c:13776 -msgid "E702: Sort compare function failed" -msgstr "E702: Ordiga funkcio fiaskis" - -#: ../eval.c:13806 -#, fuzzy -msgid "E882: Uniq compare function failed" -msgstr "E702: Ordiga funkcio fiaskis" - -#: ../eval.c:14085 -msgid "(Invalid)" -msgstr "(Nevalida)" - -#: ../eval.c:14590 -msgid "E677: Error writing temp file" -msgstr "E677: Eraro dum skribo de provizora dosiero" - -#: ../eval.c:16159 msgid "E805: Using a Float as a Number" msgstr "E805: Uzo de Glitpunktnombro kiel Nombro" -#: ../eval.c:16162 msgid "E703: Using a Funcref as a Number" msgstr "E703: Uzo de Funcref kiel Nombro" -#: ../eval.c:16170 msgid "E745: Using a List as a Number" msgstr "E745: Uzo de Listo kiel Nombro" -#: ../eval.c:16173 msgid "E728: Using a Dictionary as a Number" msgstr "E728: Uzo de Vortaro kiel Nombro" +msgid "E910: Using a Job as a Number" +msgstr "E910: Uzo de Tasko kiel Nombro" + +msgid "E913: Using a Channel as a Number" +msgstr "E913: Uzo de Kanalo kiel Nombro" + msgid "E891: Using a Funcref as a Float" msgstr "E891: Uzo de Funcref kiel Glitpunktnombro" @@ -885,268 +614,280 @@ msgstr "E893: Uzo de Listo kiel Glitpunktnombro" msgid "E894: Using a Dictionary as a Float" msgstr "E894: Uzo de Vortaro kiel Glitpunktnombro" -#: ../eval.c:16259 +msgid "E907: Using a special value as a Float" +msgstr "E907: Uzo de speciala valoro kiel Glitpunktnombro" + +msgid "E911: Using a Job as a Float" +msgstr "E911: Uzo de Tasko kiel Glitpunktnombro" + +msgid "E914: Using a Channel as a Float" +msgstr "E914: Uzo de Kanalo kiel Glitpunktnombro" + msgid "E729: using Funcref as a String" msgstr "E729: uzo de Funcref kiel ฤeno" -#: ../eval.c:16262 msgid "E730: using List as a String" msgstr "E730: uzo de Listo kiel ฤeno" -#: ../eval.c:16265 msgid "E731: using Dictionary as a String" msgstr "E731: uzo de Vortaro kiel ฤeno" msgid "E908: using an invalid value as a String" msgstr "E908: uzo de nevalida valoro kiel ฤeno" -#: ../eval.c:16619 -#, c-format -msgid "E706: Variable type mismatch for: %s" -msgstr "E706: Nekongrua datumtipo de variablo: %s" - -#: ../eval.c:16705 #, c-format msgid "E795: Cannot delete variable %s" msgstr "E795: Ne eblas forviลi variablon %s" -#: ../eval.c:16724 #, c-format msgid "E704: Funcref variable name must start with a capital: %s" msgstr "E704: Nomo de variablo Funcref devas finiฤi per majusklo: %s" -#: ../eval.c:16732 #, c-format msgid "E705: Variable name conflicts with existing function: %s" msgstr "E705: Nomo de variablo konfliktas kun ekzistanta funkcio: %s" -#: ../eval.c:16763 #, c-format msgid "E741: Value is locked: %s" msgstr "E741: Valoro estas ลlosita: %s" -#: ../eval.c:16764 ../eval.c:16769 ../message.c:1839 msgid "Unknown" msgstr "Nekonata" -#: ../eval.c:16768 #, c-format msgid "E742: Cannot change value of %s" msgstr "E742: Ne eblas ลanฤi valoron de %s" -#: ../eval.c:16838 msgid "E698: variable nested too deep for making a copy" msgstr "E698: variablo ingita tro profunde por fari kopion" -#: ../eval.c:17249 -#, c-format -msgid "E123: Undefined function: %s" -msgstr "E123: Nedifinita funkcio: %s" +msgid "" +"\n" +"# global variables:\n" +msgstr "" +"\n" +"# mallokaj variabloj:\n" -#: ../eval.c:17260 -#, c-format -msgid "E124: Missing '(': %s" -msgstr "E124: Mankas '(': %s" +msgid "" +"\n" +"\tLast set from " +msgstr "" +"\n" +"\tLaste ลaltita de " -#: ../eval.c:17293 -msgid "E862: Cannot use g: here" -msgstr "E862: Ne eblas uzi g: ฤi tie" +msgid "map() argument" +msgstr "argumento de map()" -#: ../eval.c:17312 -#, c-format -msgid "E125: Illegal argument: %s" -msgstr "E125: Nevalida argumento: %s" +msgid "filter() argument" +msgstr "argumento de filter()" -#: ../eval.c:17323 #, c-format -msgid "E853: Duplicate argument name: %s" -msgstr "E853: Ripetita nomo de argumento: %s" +msgid "E686: Argument of %s must be a List" +msgstr "E686: Argumento de %s devas esti Listo" -#: ../eval.c:17416 -msgid "E126: Missing :endfunction" -msgstr "E126: Mankas \":endfunction\"" +msgid "E928: String required" +msgstr "E928: ฤeno bezonata" -#: ../eval.c:17537 -#, c-format -msgid "E707: Function name conflicts with variable: %s" -msgstr "E707: Nomo de funkcio konfliktas kun variablo: %s" +msgid "E808: Number or Float required" +msgstr "E808: Nombro aลญ Glitpunktnombro bezonata" + +msgid "add() argument" +msgstr "argumento de add()" + +msgid "E785: complete() can only be used in Insert mode" +msgstr "E785: complete() uzeblas nur en Enmeta reฤimo" + +#. +#. * Yes this is ugly, I don't particularly like it either. But doing it +#. * this way has the compelling advantage that translations need not to +#. * be touched at all. See below what 'ok' and 'ync' are used for. +#. +msgid "&Ok" +msgstr "&Bone" -#: ../eval.c:17549 #, c-format -msgid "E127: Cannot redefine function %s: It is in use" -msgstr "E127: Ne eblas redifini funkcion %s: Estas nuntempe uzata" +msgid "+-%s%3ld line: " +msgid_plural "+-%s%3ld lines: " +msgstr[0] "+-%s%3ld linio: " +msgstr[1] "+-%s%3ld linioj: " -#: ../eval.c:17604 #, c-format -msgid "E746: Function name does not match script file name: %s" -msgstr "E746: Nomo de funkcio ne kongruas kun dosiernomo de skripto: %s" +msgid "E700: Unknown function: %s" +msgstr "E700: Nekonata funkcio: %s" -#: ../eval.c:17716 -msgid "E129: Function name required" -msgstr "E129: Nomo de funkcio bezonata" +msgid "E922: expected a dict" +msgstr "E922: vortaro atendita" -#: ../eval.c:17824 -#, fuzzy, c-format -msgid "E128: Function name must start with a capital or \"s:\": %s" -msgstr "E128: Nomo de funkcio devas eki per majusklo aลญ enhavi dupunkton: %s" +msgid "E923: Second argument of function() must be a list or a dict" +msgstr "E923: Dua argumento de function() devas esti listo aลญ Vortaro" -#: ../eval.c:17833 -#, fuzzy, c-format -msgid "E884: Function name cannot contain a colon: %s" -msgstr "E128: Nomo de funkcio devas eki per majusklo aลญ enhavi dupunkton: %s" +msgid "" +"&OK\n" +"&Cancel" +msgstr "" +"&Bone\n" +"&Rezigni" -#: ../eval.c:18336 -#, c-format -msgid "E131: Cannot delete function %s: It is in use" -msgstr "E131: Ne eblas forviลi funkcion %s: Estas nuntempe uzata" +msgid "called inputrestore() more often than inputsave()" +msgstr "alvokis inputrestore() pli ofte ol inputsave()" -#: ../eval.c:18441 -msgid "E132: Function call depth is higher than 'maxfuncdepth'" -msgstr "E132: Profundo de funkcia alvoko superas 'maxfuncdepth'" +msgid "insert() argument" +msgstr "argumento de insert()" -#: ../eval.c:18568 -#, c-format -msgid "calling %s" -msgstr "alvokas %s" +msgid "E786: Range not allowed" +msgstr "E786: Amplekso nepermesebla" -#: ../eval.c:18651 -#, c-format -msgid "%s aborted" -msgstr "%s ฤesigita" +msgid "E916: not a valid job" +msgstr "E916: nevalida tasko" + +msgid "E701: Invalid type for len()" +msgstr "E701: Nevalida datumtipo de len()" -#: ../eval.c:18653 #, c-format -msgid "%s returning #%<PRId64>" -msgstr "%s liveras #%<PRId64>" +msgid "E798: ID is reserved for \":match\": %ld" +msgstr "E798: ID estas rezervita por \":match\": %ld" + +msgid "E726: Stride is zero" +msgstr "E726: Paลo estas nul" + +msgid "E727: Start past end" +msgstr "E727: Komenco preter fino" + +msgid "<empty>" +msgstr "<malplena>" + +msgid "E240: No connection to Vim server" +msgstr "E240: Neniu konekto al Vim-servilo" -#: ../eval.c:18670 #, c-format -msgid "%s returning %s" -msgstr "%s liveras %s" +msgid "E241: Unable to send to %s" +msgstr "E241: Ne eblas sendi al %s" + +msgid "E277: Unable to read a server reply" +msgstr "E277: Ne eblas legi respondon de servilo" + +msgid "remove() argument" +msgstr "argumento de remove()" + +msgid "E655: Too many symbolic links (cycle?)" +msgstr "E655: Tro da simbolaj ligiloj (ฤu estas ciklo?)" + +msgid "reverse() argument" +msgstr "argumento de reverse()" + +msgid "E258: Unable to send to client" +msgstr "E258: Ne eblas sendi al kliento" -#: ../eval.c:18691 ../ex_cmds2.c:2695 #, c-format -msgid "continuing in %s" -msgstr "daลญrigas en %s" +msgid "E927: Invalid action: '%s'" +msgstr "E927: Nevalida ago: '%s'" -#: ../eval.c:18795 -msgid "E133: :return not inside a function" -msgstr "E133: \":return\" ekster funkcio" +msgid "sort() argument" +msgstr "argumento de sort()" -#: ../eval.c:19159 -msgid "" -"\n" -"# global variables:\n" -msgstr "" -"\n" -"# mallokaj variabloj:\n" +msgid "uniq() argument" +msgstr "argumento de uniq()" -#: ../eval.c:19254 -msgid "" -"\n" -"\tLast set from " -msgstr "" -"\n" -"\tLaste ลaltita de " +msgid "E702: Sort compare function failed" +msgstr "E702: Ordiga funkcio malsukcesis" -#: ../eval.c:19272 -msgid "No old files" -msgstr "Neniu malnova dosiero" +msgid "E882: Uniq compare function failed" +msgstr "E882: kompara funkcio de uniq() malsukcesis" + +msgid "(Invalid)" +msgstr "(Nevalida)" + +#, c-format +msgid "E935: invalid submatch number: %d" +msgstr "E935: nevalida indekso de \"submatch\": %d" + +msgid "E677: Error writing temp file" +msgstr "E677: Eraro dum skribo de provizora dosiero" + +msgid "E921: Invalid callback argument" +msgstr "E921: Nevalida argumento de reagfunctio" -#: ../ex_cmds.c:122 #, c-format msgid "<%s>%s%s %d, Hex %02x, Octal %03o" msgstr "<%s>%s%s %d, Deksesuma %02x, Okuma %03o" -#: ../ex_cmds.c:145 #, c-format msgid "> %d, Hex %04x, Octal %o" msgstr "> %d, Deksesuma %04x, Okuma %o" -#: ../ex_cmds.c:146 #, c-format msgid "> %d, Hex %08x, Octal %o" msgstr "> %d, Deksesuma %08x, Okuma %o" -#: ../ex_cmds.c:684 msgid "E134: Move lines into themselves" msgstr "E134: Movas liniojn en ilin mem" -#: ../ex_cmds.c:747 msgid "1 line moved" msgstr "1 linio movita" -#: ../ex_cmds.c:749 #, c-format -msgid "%<PRId64> lines moved" -msgstr "%<PRId64> linioj movitaj" +msgid "%ld lines moved" +msgstr "%ld linioj movitaj" -#: ../ex_cmds.c:1175 #, c-format -msgid "%<PRId64> lines filtered" -msgstr "%<PRId64> linioj filtritaj" +msgid "%ld lines filtered" +msgstr "%ld linioj filtritaj" -#: ../ex_cmds.c:1194 msgid "E135: *Filter* Autocommands must not change current buffer" msgstr "E135: *Filtraj* Aลญtokomandoj ne rajtas ลanฤi aktualan bufron" -#: ../ex_cmds.c:1244 msgid "[No write since last change]\n" msgstr "[Neniu skribo de post lasta ลanฤo]\n" -#: ../ex_cmds.c:1424 #, c-format msgid "%sviminfo: %s in line: " msgstr "%sviminfo: %s en linio: " -#: ../ex_cmds.c:1431 msgid "E136: viminfo: Too many errors, skipping rest of file" msgstr "E136: viminfo: Tro da eraroj, nun ignoras la reston de la dosiero" -#: ../ex_cmds.c:1458 #, c-format msgid "Reading viminfo file \"%s\"%s%s%s" msgstr "Legado de dosiero viminfo \"%s\"%s%s%s" -#: ../ex_cmds.c:1460 msgid " info" msgstr " informo" -#: ../ex_cmds.c:1461 msgid " marks" msgstr " markoj" -#: ../ex_cmds.c:1462 msgid " oldfiles" msgstr " malnovaj dosieroj" -#: ../ex_cmds.c:1463 msgid " FAILED" -msgstr " FIASKIS" +msgstr " MALSUKCESIS" #. avoid a wait_return for this message, it's annoying -#: ../ex_cmds.c:1541 #, c-format msgid "E137: Viminfo file is not writable: %s" msgstr "E137: Dosiero viminfo ne skribeblas: %s" -#: ../ex_cmds.c:1626 +#, c-format +msgid "E929: Too many viminfo temp files, like %s!" +msgstr "E929: Tro da provizoraj dosieroj viminfo, kiel %s!" + #, c-format msgid "E138: Can't write viminfo file %s!" msgstr "E138: Ne eblas skribi dosieron viminfo %s!" -#: ../ex_cmds.c:1635 #, c-format msgid "Writing viminfo file \"%s\"" msgstr "Skribas dosieron viminfo \"%s\"" +#, c-format +msgid "E886: Can't rename viminfo file to %s!" +msgstr "E886: Ne eblas renomi dosieron viminfo al %s!" + #. Write the info: -#: ../ex_cmds.c:1720 #, c-format msgid "# This viminfo file was generated by Vim %s.\n" msgstr "# Tiu dosiero viminfo estis kreita de Vim %s.\n" -#: ../ex_cmds.c:1722 msgid "" "# You may edit it if you're careful!\n" "\n" @@ -1154,47 +895,47 @@ msgstr "" "# Vi povas redakti ฤin se vi estas singarda.\n" "\n" -#: ../ex_cmds.c:1723 msgid "# Value of 'encoding' when this file was written\n" msgstr "# Valoro de 'encoding' kiam tiu dosiero estis kreita\n" -#: ../ex_cmds.c:1800 msgid "Illegal starting char" msgstr "Nevalida eka signo" -#: ../ex_cmds.c:2162 +msgid "" +"\n" +"# Bar lines, copied verbatim:\n" +msgstr "" +"\n" +"# Linioj komencantaj per |, kopiitaj sen ลanฤo:\n" + +msgid "Save As" +msgstr "Konservi kiel" + msgid "Write partial file?" msgstr "ฤu skribi partan dosieron?" -#: ../ex_cmds.c:2166 msgid "E140: Use ! to write partial buffer" msgstr "E140: Uzu ! por skribi partan bufron" -#: ../ex_cmds.c:2281 #, c-format msgid "Overwrite existing file \"%s\"?" msgstr "ฤu anstataลญigi ekzistantan dosieron \"%s\"?" -#: ../ex_cmds.c:2317 #, c-format msgid "Swap file \"%s\" exists, overwrite anyway?" msgstr "Permutodosiero .swp \"%s\" ekzistas, ฤu tamen anstataลญigi ฤin?" -#: ../ex_cmds.c:2326 #, c-format msgid "E768: Swap file exists: %s (:silent! overrides)" msgstr "E768: Permutodosiero .swp ekzistas: %s (:silent! por transpasi)" -#: ../ex_cmds.c:2381 #, c-format -msgid "E141: No file name for buffer %<PRId64>" -msgstr "E141: Neniu dosiernomo de bufro %<PRId64>" +msgid "E141: No file name for buffer %ld" +msgstr "E141: Neniu dosiernomo de bufro %ld" -#: ../ex_cmds.c:2412 msgid "E142: File not written: Writing is disabled by 'write' option" msgstr "E142: Dosiero ne skribita: Skribo malลaltita per la opcio 'write'" -#: ../ex_cmds.c:2434 #, c-format msgid "" "'readonly' option is set for \"%s\".\n" @@ -1203,7 +944,6 @@ msgstr "" "La opcio 'readonly' estas ลaltita por \"%s\".\n" "ฤu vi tamen volas skribi?" -#: ../ex_cmds.c:2439 #, c-format msgid "" "File permissions of \"%s\" are read-only.\n" @@ -1214,84 +954,69 @@ msgstr "" "Bonลance ฤi eble skribeblus.\n" "ฤu vi volas provi?" -#: ../ex_cmds.c:2451 #, c-format msgid "E505: \"%s\" is read-only (add ! to override)" msgstr "E505: \"%s\" estas nurlegebla (aldonu ! por transpasi)" -#: ../ex_cmds.c:3120 +msgid "Edit File" +msgstr "Redakti dosieron" + #, c-format msgid "E143: Autocommands unexpectedly deleted new buffer %s" msgstr "E143: Aลญtokomandoj neatendite forviลis novan bufron %s" -#: ../ex_cmds.c:3313 msgid "E144: non-numeric argument to :z" msgstr "E144: nenumera argumento de :z" -#: ../ex_cmds.c:3404 msgid "E145: Shell commands not allowed in rvim" msgstr "E145: ลelkomandoj nepermeseblaj en rvim" -#: ../ex_cmds.c:3498 msgid "E146: Regular expressions can't be delimited by letters" msgstr "E146: Ne eblas limigi regulesprimon per literoj" -#: ../ex_cmds.c:3964 #, c-format msgid "replace with %s (y/n/a/q/l/^E/^Y)?" msgstr "ฤu anstataลญigi per %s (y/n/a/q/l/^E/^Y)?" -#: ../ex_cmds.c:4379 msgid "(Interrupted) " msgstr "(Interrompita) " -#: ../ex_cmds.c:4384 msgid "1 match" msgstr "1 kongruo" -#: ../ex_cmds.c:4384 msgid "1 substitution" msgstr "1 anstataลญigo" -#: ../ex_cmds.c:4387 #, c-format -msgid "%<PRId64> matches" -msgstr "%<PRId64> kongruoj" +msgid "%ld matches" +msgstr "%ld kongruoj" -#: ../ex_cmds.c:4388 #, c-format -msgid "%<PRId64> substitutions" -msgstr "%<PRId64> anstataลญigoj" +msgid "%ld substitutions" +msgstr "%ld anstataลญigoj" -#: ../ex_cmds.c:4392 msgid " on 1 line" msgstr " en 1 linio" -#: ../ex_cmds.c:4395 #, c-format -msgid " on %<PRId64> lines" -msgstr " en %<PRId64> linioj" +msgid " on %ld lines" +msgstr " en %ld linioj" -#: ../ex_cmds.c:4438 msgid "E147: Cannot do :global recursive" msgstr "E147: Ne eblas fari \":global\" rekursie" # DP: global estas por ":global" do mi ne tradukis ฤin -#: ../ex_cmds.c:4467 msgid "E148: Regular expression missing from global" msgstr "E148: Regulesprimo mankas el global" -#: ../ex_cmds.c:4508 #, c-format msgid "Pattern found in every line: %s" msgstr "ลablono trovita en ฤiuj linioj: %s" -#: ../ex_cmds.c:4510 #, c-format msgid "Pattern not found: %s" msgstr "ลablono ne trovita: %s" -#: ../ex_cmds.c:4587 msgid "" "\n" "# Last Substitute String:\n" @@ -1302,104 +1027,100 @@ msgstr "" "$" # This message should *so* be E42! -#: ../ex_cmds.c:4679 msgid "E478: Don't panic!" msgstr "E478: Ne paniku!" -#: ../ex_cmds.c:4717 #, c-format msgid "E661: Sorry, no '%s' help for %s" msgstr "E661: Bedaลญrinde estas neniu helpo '%s' por %s" -#: ../ex_cmds.c:4719 #, c-format msgid "E149: Sorry, no help for %s" msgstr "E149: Bedaลญrinde estas neniu helpo por %s" -#: ../ex_cmds.c:4751 #, c-format msgid "Sorry, help file \"%s\" not found" msgstr "Bedaลญrinde, la helpdosiero \"%s\" ne troveblas" -#: ../ex_cmds.c:5323 #, c-format -msgid "E150: Not a directory: %s" -msgstr "E150: Ne estas dosierujo: %s" +msgid "E151: No match: %s" +msgstr "E151: Neniu kongruo: %s" -#: ../ex_cmds.c:5446 #, c-format msgid "E152: Cannot open %s for writing" msgstr "E152: Ne eblas malfermi %s en skribreฤimo" -#: ../ex_cmds.c:5471 #, c-format msgid "E153: Unable to open %s for reading" msgstr "E153: Ne eblas malfermi %s en legreฤimo" -#: ../ex_cmds.c:5500 #, c-format msgid "E670: Mix of help file encodings within a language: %s" msgstr "E670: Miksaฤตo de kodoprezento de helpa dosiero en lingvo: %s" -#: ../ex_cmds.c:5565 #, c-format msgid "E154: Duplicate tag \"%s\" in file %s/%s" msgstr "E154: Ripetita etikedo \"%s\" en dosiero %s/%s" #, c-format +msgid "E150: Not a directory: %s" +msgstr "E150: Ne estas dosierujo: %s" + +#, c-format msgid "E160: Unknown sign command: %s" msgstr "E160: Nekonata simbola komando: %s" -#: ../ex_cmds.c:5704 msgid "E156: Missing sign name" msgstr "E156: Mankas nomo de simbolo" -#: ../ex_cmds.c:5746 msgid "E612: Too many signs defined" msgstr "E612: Tro da simboloj estas difinitaj" -#: ../ex_cmds.c:5813 #, c-format msgid "E239: Invalid sign text: %s" msgstr "E239: Nevalida teksto de simbolo: %s" -#: ../ex_cmds.c:5844 ../ex_cmds.c:6035 #, c-format msgid "E155: Unknown sign: %s" msgstr "E155: Nekonata simbolo: %s" -#: ../ex_cmds.c:5877 msgid "E159: Missing sign number" msgstr "E159: Mankas numero de simbolo" -#: ../ex_cmds.c:5971 #, c-format msgid "E158: Invalid buffer name: %s" msgstr "E158: Nevalida nomo de bufro: %s" -#: ../ex_cmds.c:6008 +msgid "E934: Cannot jump to a buffer that does not have a name" +msgstr "E934: Ne eblas salti al sennoma bufro" + +#, c-format +msgid "E157: Invalid sign ID: %ld" +msgstr "E157: Nevalida identigilo de simbolo: %ld" + #, c-format -msgid "E157: Invalid sign ID: %<PRId64>" -msgstr "E157: Nevalida identigilo de simbolo: %<PRId64>" +msgid "E885: Not possible to change sign %s" +msgstr "E885: Ne eblas ลanฤi simbolon %s" + +msgid " (NOT FOUND)" +msgstr " (NETROVITA)" -#: ../ex_cmds.c:6066 msgid " (not supported)" msgstr " (nesubtenata)" -#: ../ex_cmds.c:6169 msgid "[Deleted]" msgstr "[Forviลita]" -#: ../ex_cmds2.c:139 +msgid "No old files" +msgstr "Neniu malnova dosiero" + msgid "Entering Debug mode. Type \"cont\" to continue." msgstr "Eniras sencimigan reฤimon. Tajpu \"cont\" por daลญrigi." -#: ../ex_cmds2.c:143 ../ex_docmd.c:759 #, c-format -msgid "line %<PRId64>: %s" -msgstr "linio %<PRId64>: %s" +msgid "line %ld: %s" +msgstr "linio %ld: %s" -#: ../ex_cmds2.c:145 #, c-format msgid "cmd: %s" msgstr "kmd: %s" @@ -1411,231 +1132,183 @@ msgstr "kadro estas nul" msgid "frame at highest level: %d" msgstr "kadro je la plej alta nivelo: %d" -#: ../ex_cmds2.c:322 #, c-format -msgid "Breakpoint in \"%s%s\" line %<PRId64>" -msgstr "Kontrolpunkto en \"%s%s\" linio %<PRId64>" +msgid "Breakpoint in \"%s%s\" line %ld" +msgstr "Kontrolpunkto en \"%s%s\" linio %ld" -#: ../ex_cmds2.c:581 #, c-format msgid "E161: Breakpoint not found: %s" msgstr "E161: Kontrolpunkto ne trovita: %s" -#: ../ex_cmds2.c:611 msgid "No breakpoints defined" msgstr "Neniu kontrolpunkto estas difinita" -#: ../ex_cmds2.c:617 #, c-format -msgid "%3d %s %s line %<PRId64>" -msgstr "%3d %s %s linio %<PRId64>" +msgid "%3d %s %s line %ld" +msgstr "%3d %s %s linio %ld" -#: ../ex_cmds2.c:942 msgid "E750: First use \":profile start {fname}\"" msgstr "E750: Uzu unue \":profile start {dosiernomo}\"" -#: ../ex_cmds2.c:1269 #, c-format msgid "Save changes to \"%s\"?" msgstr "ฤu konservi ลanฤojn al \"%s\"?" -#: ../ex_cmds2.c:1271 ../ex_docmd.c:8851 msgid "Untitled" msgstr "Sen titolo" -#: ../ex_cmds2.c:1421 #, c-format msgid "E162: No write since last change for buffer \"%s\"" msgstr "E162: Neniu skribo de post la lasta ลanฤo por bufro \"%s\"" -#: ../ex_cmds2.c:1480 msgid "Warning: Entered other buffer unexpectedly (check autocommands)" msgstr "Averto: Eniris neatendite alian bufron (kontrolu aลญtokomandojn)" -#: ../ex_cmds2.c:1826 msgid "E163: There is only one file to edit" msgstr "E163: Estas nur unu redaktenda dosiero" -#: ../ex_cmds2.c:1828 msgid "E164: Cannot go before first file" msgstr "E164: Ne eblas iri antaลญ ol la unuan dosieron" -#: ../ex_cmds2.c:1830 msgid "E165: Cannot go beyond last file" msgstr "E165: Ne eblas iri preter la lastan dosieron" -#: ../ex_cmds2.c:2175 #, c-format msgid "E666: compiler not supported: %s" msgstr "E666: kompililo nesubtenata: %s" -#: ../ex_cmds2.c:2257 #, c-format msgid "Searching for \"%s\" in \"%s\"" msgstr "Serฤado de \"%s\" en \"%s\"" -#: ../ex_cmds2.c:2284 #, c-format msgid "Searching for \"%s\"" msgstr "Serฤado de \"%s\"" -#: ../ex_cmds2.c:2307 #, c-format msgid "not found in '%s': \"%s\"" msgstr "ne trovita en '%s: \"%s\"" -#: ../ex_cmds2.c:2472 +msgid "Source Vim script" +msgstr "Ruli Vim-skripton" + #, c-format msgid "Cannot source a directory: \"%s\"" msgstr "Ne eblas ruli dosierujon: \"%s\"" -#: ../ex_cmds2.c:2518 #, c-format msgid "could not source \"%s\"" msgstr "ne eblis ruli \"%s\"" -#: ../ex_cmds2.c:2520 #, c-format -msgid "line %<PRId64>: could not source \"%s\"" -msgstr "linio %<PRId64>: ne eblis ruli \"%s\"" +msgid "line %ld: could not source \"%s\"" +msgstr "linio %ld: ne eblis ruli \"%s\"" -#: ../ex_cmds2.c:2535 #, c-format msgid "sourcing \"%s\"" msgstr "rulas \"%s\"" -#: ../ex_cmds2.c:2537 #, c-format -msgid "line %<PRId64>: sourcing \"%s\"" -msgstr "linio %<PRId64>: rulas \"%s\"" +msgid "line %ld: sourcing \"%s\"" +msgstr "linio %ld: rulas \"%s\"" -#: ../ex_cmds2.c:2693 #, c-format msgid "finished sourcing %s" msgstr "finis ruli %s" -#: ../ex_cmds2.c:2765 +#, c-format +msgid "continuing in %s" +msgstr "daลญrigas en %s" + msgid "modeline" msgstr "reฤimlinio" -#: ../ex_cmds2.c:2767 msgid "--cmd argument" msgstr "--cmd argumento" -#: ../ex_cmds2.c:2769 msgid "-c argument" msgstr "-c argumento" -#: ../ex_cmds2.c:2771 msgid "environment variable" msgstr "medivariablo" -#: ../ex_cmds2.c:2773 msgid "error handler" msgstr "erartraktilo" -#: ../ex_cmds2.c:3020 msgid "W15: Warning: Wrong line separator, ^M may be missing" msgstr "W15: Averto: Neฤusta disigilo de linio, ^M eble mankas" -#: ../ex_cmds2.c:3139 msgid "E167: :scriptencoding used outside of a sourced file" msgstr "E167: \":scriptencoding\" uzita ekster rulita dosiero" -#: ../ex_cmds2.c:3166 msgid "E168: :finish used outside of a sourced file" msgstr "E168: \":finish\" uzita ekster rulita dosiero" -#: ../ex_cmds2.c:3389 #, c-format msgid "Current %slanguage: \"%s\"" msgstr "Aktuala %slingvo: \"%s\"" -#: ../ex_cmds2.c:3404 #, c-format msgid "E197: Cannot set language to \"%s\"" msgstr "E197: Ne eblas ลanฤi la lingvon al \"%s\"" -#. don't redisplay the window -#. don't wait for return -#: ../ex_docmd.c:387 msgid "Entering Ex mode. Type \"visual\" to go to Normal mode." msgstr "Eniras reฤimon Ex. Tajpu \"visual\" por iri al reฤimo Normala." -#: ../ex_docmd.c:428 msgid "E501: At end-of-file" msgstr "E501: ฤe fino-de-dosiero" -#: ../ex_docmd.c:513 msgid "E169: Command too recursive" msgstr "E169: Komando tro rekursia" -#: ../ex_docmd.c:1006 #, c-format msgid "E605: Exception not caught: %s" msgstr "E605: Escepto nekaptita: %s" -#: ../ex_docmd.c:1085 msgid "End of sourced file" msgstr "Fino de rulita dosiero" -#: ../ex_docmd.c:1086 msgid "End of function" msgstr "Fino de funkcio" -#: ../ex_docmd.c:1628 msgid "E464: Ambiguous use of user-defined command" msgstr "E464: Ambigua uzo de komando difinita de uzanto" -#: ../ex_docmd.c:1638 msgid "E492: Not an editor command" msgstr "E492: Ne estas redaktila komando" -#: ../ex_docmd.c:1729 msgid "E493: Backwards range given" msgstr "E493: Inversa amplekso donita" -#: ../ex_docmd.c:1733 msgid "Backwards range given, OK to swap" msgstr "Inversa amplekso donita, permuteblas" -#. append -#. typed wrong -#: ../ex_docmd.c:1787 msgid "E494: Use w or w>>" msgstr "E494: Uzu w aลญ w>>" -#: ../ex_docmd.c:3454 -msgid "E319: The command is not available in this version" +msgid "E319: Sorry, the command is not available in this version" msgstr "E319: Bedaลญrinde, tiu komando ne haveblas en tiu versio" -#: ../ex_docmd.c:3752 msgid "E172: Only one file name allowed" msgstr "E172: Nur unu dosiernomo permesebla" -#: ../ex_docmd.c:4238 msgid "1 more file to edit. Quit anyway?" msgstr "1 plia redaktenda dosiero. ฤu tamen eliri?" -#: ../ex_docmd.c:4242 #, c-format msgid "%d more files to edit. Quit anyway?" msgstr "%d pliaj redaktendaj dosieroj. ฤu tamen eliri?" -#: ../ex_docmd.c:4248 msgid "E173: 1 more file to edit" msgstr "E173: 1 plia redaktenda dosiero" -#: ../ex_docmd.c:4250 #, c-format -msgid "E173: %<PRId64> more files to edit" -msgstr "E173: %<PRId64> pliaj redaktendaj dosieroj" +msgid "E173: %ld more files to edit" +msgstr "E173: %ld pliaj redaktendaj dosieroj" -#: ../ex_docmd.c:4320 msgid "E174: Command already exists: add ! to replace it" msgstr "E174: La komando jam ekzistas: aldonu ! por anstataลญigi ฤin" -#: ../ex_docmd.c:4432 msgid "" "\n" " Name Args Address Complete Definition" @@ -1643,352 +1316,308 @@ msgstr "" "\n" " Nomo Argumentoj Adreso Kompleto Difino" -#: ../ex_docmd.c:4516 msgid "No user-defined commands found" msgstr "Neniu komando difinita de uzanto trovita" -#: ../ex_docmd.c:4538 msgid "E175: No attribute specified" msgstr "E175: Neniu atributo specifita" -#: ../ex_docmd.c:4583 msgid "E176: Invalid number of arguments" msgstr "E176: Nevalida nombro de argumentoj" -#: ../ex_docmd.c:4594 msgid "E177: Count cannot be specified twice" msgstr "E177: Kvantoro ne povas aperi dufoje" -#: ../ex_docmd.c:4603 msgid "E178: Invalid default value for count" msgstr "E178: Nevalida defaลญlta valoro de kvantoro" -#: ../ex_docmd.c:4625 msgid "E179: argument required for -complete" msgstr "E179: argumento bezonata por -complete" -#: ../ex_docmd.c:4933 msgid "E179: argument required for -addr" msgstr "E179: argumento bezonata por -addr" -#: ../ex_docmd.c:4635 #, c-format msgid "E181: Invalid attribute: %s" msgstr "E181: Nevalida atributo: %s" -#: ../ex_docmd.c:4678 msgid "E182: Invalid command name" msgstr "E182: Nevalida komanda nomo" -#: ../ex_docmd.c:4691 msgid "E183: User defined commands must start with an uppercase letter" msgstr "E183: Komandoj difinataj de uzanto devas eki per majusklo" -#: ../ex_docmd.c:4696 msgid "E841: Reserved name, cannot be used for user defined command" msgstr "E841: Rezervita nomo, neuzebla por komando difinita de uzanto" -#: ../ex_docmd.c:4751 #, c-format msgid "E184: No such user-defined command: %s" msgstr "E184: Neniu komando-difinita-de-uzanto kiel: %s" -#: ../ex_docmd.c:5516 #, c-format msgid "E180: Invalid address type value: %s" msgstr "E180: Nevalida valoro de tipo de adreso: %s" -#: ../ex_docmd.c:5219 #, c-format msgid "E180: Invalid complete value: %s" msgstr "E180: Nevalida valoro de kompletigo: %s" -#: ../ex_docmd.c:5225 msgid "E468: Completion argument only allowed for custom completion" msgstr "" "E468: Argumento de kompletigo nur permesebla por kompletigo difinita de " "uzanto" -#: ../ex_docmd.c:5231 msgid "E467: Custom completion requires a function argument" msgstr "E467: Uzula kompletigo bezonas funkcian argumenton" -#: ../ex_docmd.c:5257 +msgid "unknown" +msgstr "nekonata" + #, c-format msgid "E185: Cannot find color scheme '%s'" msgstr "E185: Ne eblas trovi agordaron de koloroj '%s'" -#: ../ex_docmd.c:5263 msgid "Greetings, Vim user!" msgstr "Bonvenon, uzanto de Vim!" -#: ../ex_docmd.c:5431 msgid "E784: Cannot close last tab page" msgstr "E784: Ne eblas fermi lastan langeton" -#: ../ex_docmd.c:5462 msgid "Already only one tab page" msgstr "Jam nur unu langeto" -#: ../ex_docmd.c:6004 +msgid "Edit File in new window" +msgstr "Redakti Dosieron en nova fenestro" + #, c-format msgid "Tab page %d" msgstr "Langeto %d" -#: ../ex_docmd.c:6295 msgid "No swap file" msgstr "Neniu permutodosiero .swp" -#: ../ex_docmd.c:6478 +msgid "Append File" +msgstr "Postaldoni dosieron" + msgid "E747: Cannot change directory, buffer is modified (add ! to override)" msgstr "" "E747: Ne eblas ลanฤi dosierujon, bufro estas ลanฤita (aldonu ! por transpasi)" -#: ../ex_docmd.c:6485 msgid "E186: No previous directory" msgstr "E186: Neniu antaลญa dosierujo" -#: ../ex_docmd.c:6530 msgid "E187: Unknown" msgstr "E187: Nekonata" -#: ../ex_docmd.c:6610 msgid "E465: :winsize requires two number arguments" msgstr "E465: \":winsize\" bezonas du numerajn argumentojn" -#: ../ex_docmd.c:6655 +#, c-format +msgid "Window position: X %d, Y %d" +msgstr "Pozicio de fenestro: X %d, Y %d" + msgid "E188: Obtaining window position not implemented for this platform" msgstr "" "E188: Akiro de pozicio de fenestro ne estas realigita por tiu platformo" -#: ../ex_docmd.c:6662 msgid "E466: :winpos requires two number arguments" msgstr "E466: \":winpos\" bezonas du numerajn argumentojn" -#: ../ex_docmd.c:7241 +msgid "E930: Cannot use :redir inside execute()" +msgstr "E930: Ne eblas uzi :redir en execute()" + +msgid "Save Redirection" +msgstr "Konservi alidirekton" + +# DP: mi ne certas pri superflugo +msgid "Save View" +msgstr "Konservi superflugon" + +msgid "Save Session" +msgstr "Konservi seancon" + +msgid "Save Setup" +msgstr "Konservi agordaron" + #, c-format msgid "E739: Cannot create directory: %s" msgstr "E739: Ne eblas krei dosierujon %s" -#: ../ex_docmd.c:7268 #, c-format msgid "E189: \"%s\" exists (add ! to override)" msgstr "E189: \"%s\" ekzistas (aldonu ! por transpasi)" -#: ../ex_docmd.c:7273 #, c-format msgid "E190: Cannot open \"%s\" for writing" msgstr "E190: Ne eblas malfermi \"%s\" por skribi" #. set mark -#: ../ex_docmd.c:7294 msgid "E191: Argument must be a letter or forward/backward quote" msgstr "E191: Argumento devas esti litero, citilo aลญ retrocitilo" -#: ../ex_docmd.c:7333 msgid "E192: Recursive use of :normal too deep" msgstr "E192: Tro profunda rekursia alvoko de \":normal\"" -#: ../ex_docmd.c:7807 +msgid "E809: #< is not available without the +eval feature" +msgstr "E809: #< ne haveblas sen la eblo +eval" + msgid "E194: No alternate file name to substitute for '#'" msgstr "E194: Neniu alterna dosiernomo por anstataลญigi al '#'" -#: ../ex_docmd.c:7841 msgid "E495: no autocommand file name to substitute for \"<afile>\"" msgstr "E495: neniu dosiernomo de aลญtokomando por anstataลญigi al \"<afile>\"" -#: ../ex_docmd.c:7850 msgid "E496: no autocommand buffer number to substitute for \"<abuf>\"" msgstr "" "E496: neniu numero de bufro de aลญtokomando por anstataลญigi al \"<abuf>\"" # DP: ฤu match estas verbo aลญ nomo en la angla version? # AM: ฤi tie, nomo, ลajnas al mi -#: ../ex_docmd.c:7861 msgid "E497: no autocommand match name to substitute for \"<amatch>\"" msgstr "" "E497: neniu nomo de kongruo de aลญtokomando por anstataลญigi al \"<amatch>\"" -#: ../ex_docmd.c:7870 msgid "E498: no :source file name to substitute for \"<sfile>\"" msgstr "E498: neniu dosiernomo \":source\" por anstataลญigi al \"<sfile>\"" -#: ../ex_docmd.c:7876 msgid "E842: no line number to use for \"<slnum>\"" msgstr "E842: neniu uzebla numero de linio por \"<slnum>\"" -#: ../ex_docmd.c:7903 -#, fuzzy, c-format +#, no-c-format msgid "E499: Empty file name for '%' or '#', only works with \":p:h\"" msgstr "E499: Malplena dosiernomo por '%' aลญ '#', nur funkcias kun \":p:h\"" -#: ../ex_docmd.c:7905 msgid "E500: Evaluates to an empty string" msgstr "E500: Liveras malplenan ฤenon" -#: ../ex_docmd.c:8838 msgid "E195: Cannot open viminfo file for reading" msgstr "E195: Ne eblas malfermi dosieron viminfo en lega reฤimo" -#: ../ex_eval.c:464 +msgid "E196: No digraphs in this version" +msgstr "E196: Neniu duliteraฤตo en tiu versio" + msgid "E608: Cannot :throw exceptions with 'Vim' prefix" msgstr "E608: Ne eblas lanฤi (:throw) escepton kun prefikso 'Vim'" #. always scroll up, don't overwrite -#: ../ex_eval.c:496 #, c-format msgid "Exception thrown: %s" msgstr "Escepto lanฤita: %s" -#: ../ex_eval.c:545 #, c-format msgid "Exception finished: %s" msgstr "Escepto finiฤis: %s" -#: ../ex_eval.c:546 #, c-format msgid "Exception discarded: %s" msgstr "Escepto ne konservita: %s" -#: ../ex_eval.c:588 ../ex_eval.c:634 #, c-format -msgid "%s, line %<PRId64>" -msgstr "%s, linio %<PRId64>" +msgid "%s, line %ld" +msgstr "%s, linio %ld" #. always scroll up, don't overwrite -#: ../ex_eval.c:608 #, c-format msgid "Exception caught: %s" msgstr "Kaptis escepton: %s" -#: ../ex_eval.c:676 #, c-format msgid "%s made pending" msgstr "%s iฤis atendanta(j)" -#: ../ex_eval.c:679 #, c-format msgid "%s resumed" msgstr "%s daลญrigita(j)" -#: ../ex_eval.c:683 #, c-format msgid "%s discarded" msgstr "%s ne konservita(j)" -#: ../ex_eval.c:708 msgid "Exception" msgstr "Escepto" -#: ../ex_eval.c:713 msgid "Error and interrupt" msgstr "Eraro kaj interrompo" -#: ../ex_eval.c:715 msgid "Error" msgstr "Eraro" #. if (pending & CSTP_INTERRUPT) -#: ../ex_eval.c:717 msgid "Interrupt" msgstr "Interrompo" -#: ../ex_eval.c:795 msgid "E579: :if nesting too deep" msgstr "E579: \":if\" tro profunde ingita" -#: ../ex_eval.c:830 msgid "E580: :endif without :if" msgstr "E580: \":endif\" sen \":if\"" -#: ../ex_eval.c:873 msgid "E581: :else without :if" msgstr "E581: \":else\" sen \":if\"" -#: ../ex_eval.c:876 msgid "E582: :elseif without :if" msgstr "E582: \":elseif\" sen \":if\"" -#: ../ex_eval.c:880 msgid "E583: multiple :else" msgstr "E583: pluraj \":else\"" -#: ../ex_eval.c:883 msgid "E584: :elseif after :else" msgstr "E584: \":elseif\" post \":else\"" -#: ../ex_eval.c:941 msgid "E585: :while/:for nesting too deep" msgstr "E585: \":while/:for\" ingita tro profunde" -#: ../ex_eval.c:1028 msgid "E586: :continue without :while or :for" msgstr "E586: \":continue\" sen \":while\" aลญ \":for\"" -#: ../ex_eval.c:1061 msgid "E587: :break without :while or :for" msgstr "E587: \":break\" sen \":while\" aลญ \":for\"" -#: ../ex_eval.c:1102 msgid "E732: Using :endfor with :while" msgstr "E732: Uzo de \":endfor\" kun \":while\"" -#: ../ex_eval.c:1104 msgid "E733: Using :endwhile with :for" msgstr "E733: Uzo de \":endwhile\" kun \":for\"" -#: ../ex_eval.c:1247 msgid "E601: :try nesting too deep" msgstr "E601: \":try\" ingita tro profunde" -#: ../ex_eval.c:1317 msgid "E603: :catch without :try" msgstr "E603: \":catch\" sen \":try\"" #. Give up for a ":catch" after ":finally" and ignore it. #. * Just parse. -#: ../ex_eval.c:1332 msgid "E604: :catch after :finally" msgstr "E604: \":catch\" post \":finally\"" -#: ../ex_eval.c:1451 msgid "E606: :finally without :try" msgstr "E606: \":finally\" sen \":try\"" #. Give up for a multiple ":finally" and ignore it. -#: ../ex_eval.c:1467 msgid "E607: multiple :finally" msgstr "E607: pluraj \":finally\"" -#: ../ex_eval.c:1571 msgid "E602: :endtry without :try" msgstr "E602: \":endtry\" sen \":try\"" -#: ../ex_eval.c:2026 msgid "E193: :endfunction not inside a function" msgstr "E193: \":endfunction\" ekster funkcio" -#: ../ex_getln.c:1643 msgid "E788: Not allowed to edit another buffer now" msgstr "E788: Ne eblas redakti alian bufron nun" -#: ../ex_getln.c:1656 msgid "E811: Not allowed to change buffer information now" msgstr "E811: Ne eblas ลanฤi informon de bufro nun" -#: ../ex_getln.c:3178 msgid "tagname" msgstr "nomo de etikedo" -#: ../ex_getln.c:3181 msgid " kind file\n" msgstr " tipo de dosiero\n" -#: ../ex_getln.c:4799 msgid "'history' option is zero" msgstr "opcio 'history' estas nul" -#: ../ex_getln.c:5046 #, c-format msgid "" "\n" @@ -1997,303 +1626,224 @@ msgstr "" "\n" "# Historio %s (de plej nova al plej malnova):\n" -#: ../ex_getln.c:5047 msgid "Command Line" msgstr "Komanda linio" -#: ../ex_getln.c:5048 msgid "Search String" msgstr "Serฤa ฤeno" -#: ../ex_getln.c:5049 msgid "Expression" msgstr "Esprimo" -#: ../ex_getln.c:5050 msgid "Input Line" msgstr "Eniga linio" -#: ../ex_getln.c:5117 +msgid "Debug Line" +msgstr "Sencimiga linio" + msgid "E198: cmd_pchar beyond the command length" msgstr "E198: cmd_pchar preter la longo de komando" -#: ../ex_getln.c:5279 msgid "E199: Active window or buffer deleted" msgstr "E199: Aktiva fenestro aลญ bufro forviลita" -#: ../file_search.c:203 -msgid "E854: path too long for completion" -msgstr "E854: tro longa vojo por kompletigo" - -#: ../file_search.c:446 -#, c-format -msgid "" -"E343: Invalid path: '**[number]' must be at the end of the path or be " -"followed by '%s'." -msgstr "" -"E343: Nevalida vojo: '**[nombro]' devas esti ฤe la fino de la vojo aลญ " -"sekvita de '%s'." - -#: ../file_search.c:1505 -#, c-format -msgid "E344: Can't find directory \"%s\" in cdpath" -msgstr "E344: Ne eblas trovi dosierujon \"%s\" en cdpath" - -#: ../file_search.c:1508 -#, c-format -msgid "E345: Can't find file \"%s\" in path" -msgstr "E345: Ne eblas trovi dosieron \"%s\" en serฤvojo" - -#: ../file_search.c:1512 -#, c-format -msgid "E346: No more directory \"%s\" found in cdpath" -msgstr "E346: Ne plu trovis dosierujon \"%s\" en cdpath" - -#: ../file_search.c:1515 -#, c-format -msgid "E347: No more file \"%s\" found in path" -msgstr "E347: Ne plu trovis dosieron \"%s\" en serฤvojo" - -#: ../fileio.c:137 msgid "E812: Autocommands changed buffer or buffer name" msgstr "E812: Aลญtokomandoj ลanฤis bufron aลญ nomon de bufro" -#: ../fileio.c:368 msgid "Illegal file name" msgstr "Nevalida dosiernomo" -#: ../fileio.c:395 ../fileio.c:476 ../fileio.c:2543 ../fileio.c:2578 msgid "is a directory" msgstr "estas dosierujo" -#: ../fileio.c:397 msgid "is not a file" msgstr "ne estas dosiero" -#: ../fileio.c:508 ../fileio.c:3522 +msgid "is a device (disabled with 'opendevice' option)" +msgstr "estas aparatdosiero (malลaltita per la opcio 'opendevice')" + msgid "[New File]" msgstr "[Nova dosiero]" -#: ../fileio.c:511 msgid "[New DIRECTORY]" msgstr "[Nova DOSIERUJO]" -#: ../fileio.c:529 ../fileio.c:532 msgid "[File too big]" msgstr "[Dosiero tro granda]" -#: ../fileio.c:534 msgid "[Permission Denied]" msgstr "[Permeso rifuzita]" -#: ../fileio.c:653 msgid "E200: *ReadPre autocommands made the file unreadable" msgstr "E200: La aลญtokomandoj *ReadPre igis la dosieron nelegebla" -#: ../fileio.c:655 msgid "E201: *ReadPre autocommands must not change current buffer" msgstr "E201: La aลญtokomandoj *ReadPre ne rajtas ลanฤi la aktualan bufron" -#: ../fileio.c:672 -msgid "Nvim: Reading from stdin...\n" +msgid "Vim: Reading from stdin...\n" msgstr "Vim: Legado el stdin...\n" +msgid "Reading from stdin..." +msgstr "Legado el stdin..." + #. Re-opening the original file failed! -#: ../fileio.c:909 msgid "E202: Conversion made file unreadable!" msgstr "E202: Konverto igis la dosieron nelegebla!" -#. fifo or socket -#: ../fileio.c:1782 msgid "[fifo/socket]" msgstr "[rektvica memoro/kontaktoskatolo]" -#. fifo -#: ../fileio.c:1788 msgid "[fifo]" msgstr "[rektvica memoro]" -#. or socket -#: ../fileio.c:1794 msgid "[socket]" msgstr "[kontaktoskatolo]" -#. or character special -#: ../fileio.c:1801 msgid "[character special]" msgstr "[speciala signo]" -#: ../fileio.c:1815 msgid "[CR missing]" msgstr "[CR mankas]" -#: ../fileio.c:1819 msgid "[long lines split]" msgstr "[divido de longaj linioj]" -#: ../fileio.c:1823 ../fileio.c:3512 msgid "[NOT converted]" msgstr "[NE konvertita]" -#: ../fileio.c:1826 ../fileio.c:3515 msgid "[converted]" msgstr "[konvertita]" -#: ../fileio.c:1831 #, c-format -msgid "[CONVERSION ERROR in line %<PRId64>]" -msgstr "[ERARO DE KONVERTO en linio %<PRId64>]" +msgid "[CONVERSION ERROR in line %ld]" +msgstr "[ERARO DE KONVERTO en linio %ld]" -#: ../fileio.c:1835 #, c-format -msgid "[ILLEGAL BYTE in line %<PRId64>]" -msgstr "[NEVALIDA BAJTO en linio %<PRId64>]" +msgid "[ILLEGAL BYTE in line %ld]" +msgstr "[NEVALIDA BAJTO en linio %ld]" -#: ../fileio.c:1838 msgid "[READ ERRORS]" msgstr "[ERAROJ DE LEGADO]" -#: ../fileio.c:2104 msgid "Can't find temp file for conversion" msgstr "Ne eblas trovi provizoran dosieron por konverti" -#: ../fileio.c:2110 msgid "Conversion with 'charconvert' failed" -msgstr "Konverto kun 'charconvert' fiaskis" +msgstr "Konverto kun 'charconvert' malsukcesis" -#: ../fileio.c:2113 msgid "can't read output of 'charconvert'" msgstr "ne eblas legi la eligon de 'charconvert'" -#: ../fileio.c:2437 msgid "E676: No matching autocommands for acwrite buffer" msgstr "E676: Neniu kongrua aลญtokomando por la bufro acwrite" -#: ../fileio.c:2466 msgid "E203: Autocommands deleted or unloaded buffer to be written" msgstr "E203: Aลญtokomandoj forviลis aลญ malลargis la skribendan bufron" -#: ../fileio.c:2486 msgid "E204: Autocommand changed number of lines in unexpected way" msgstr "E204: Aลญtokomando ลanฤis la nombron de linioj neatendite" -#: ../fileio.c:2548 ../fileio.c:2565 +msgid "NetBeans disallows writes of unmodified buffers" +msgstr "NetBeans malpermesas skribojn de neลanฤitaj bufroj" + +msgid "Partial writes disallowed for NetBeans buffers" +msgstr "Partaj skriboj malpermesitaj ฤe bufroj NetBeans" + msgid "is not a file or writable device" msgstr "ne estas dosiero aลญ skribebla aparatdosiero" -#: ../fileio.c:2601 +msgid "writing to device disabled with 'opendevice' option" +msgstr "skribo al aparatdosiero malลaltita per la opcio 'opendevice'" + msgid "is read-only (add ! to override)" msgstr "estas nurlegebla (aldonu ! por transpasi)" -#: ../fileio.c:2886 msgid "E506: Can't write to backup file (add ! to override)" msgstr "E506: Ne eblas skribi restaลญrkopion (aldonu ! por transpasi)" -#: ../fileio.c:2898 msgid "E507: Close error for backup file (add ! to override)" msgstr "E507: Eraro dum fermo de restaลญrkopio (aldonu ! transpasi)" -#: ../fileio.c:2901 msgid "E508: Can't read file for backup (add ! to override)" msgstr "E508: Ne eblas legi restaลญrkopion (aldonu ! por transpasi)" -#: ../fileio.c:2923 msgid "E509: Cannot create backup file (add ! to override)" msgstr "E509: Ne eblas krei restaลญrkopion (aldonu ! por transpasi)" -#: ../fileio.c:3008 msgid "E510: Can't make backup file (add ! to override)" msgstr "E510: Ne eblas krei restaลญrkopion (aldonu ! por transpasi)" -#. Can't write without a tempfile! -#: ../fileio.c:3121 +msgid "E460: The resource fork would be lost (add ! to override)" +msgstr "E460: La rimeda forko estus perdita (aldonu ! por transpasi)" + msgid "E214: Can't find temp file for writing" msgstr "E214: Ne eblas trovi provizoran dosieron por skribi" -#: ../fileio.c:3134 msgid "E213: Cannot convert (add ! to write without conversion)" msgstr "E213: Ne eblas konverti (aldonu ! por skribi sen konverto)" -#: ../fileio.c:3169 msgid "E166: Can't open linked file for writing" msgstr "E166: Ne eblas malfermi ligitan dosieron por skribi" -#: ../fileio.c:3173 msgid "E212: Can't open file for writing" msgstr "E212: Ne eblas malfermi la dosieron por skribi" # AM: fsync: ne traduku (nomo de C-komando) -#: ../fileio.c:3363 msgid "E667: Fsync failed" -msgstr "E667: Fsync fiaskis" +msgstr "E667: Fsync malsukcesis" -#: ../fileio.c:3398 msgid "E512: Close failed" -msgstr "E512: Fermo fiaskis" +msgstr "E512: Fermo malsukcesis" -#: ../fileio.c:3436 msgid "E513: write error, conversion failed (make 'fenc' empty to override)" -msgstr "E513: skriberaro, konverto fiaskis (igu 'fenc' malplena por transpasi)" +msgstr "" +"E513: skriberaro, konverto malsukcesis (igu 'fenc' malplena por transpasi)" -#: ../fileio.c:3441 #, c-format msgid "" -"E513: write error, conversion failed in line %<PRId64> (make 'fenc' empty to " +"E513: write error, conversion failed in line %ld (make 'fenc' empty to " "override)" msgstr "" -"E513: skriberaro, konverto fiaskis en linio %<PRId64> (igu 'fenc' malplena " +"E513: skriberaro, konverto malsukcesis en linio %ld (igu 'fenc' malplena " "por transpasi)" -#: ../fileio.c:3448 msgid "E514: write error (file system full?)" msgstr "E514: skriberaro (ฤu plena dosiersistemo?)" -#: ../fileio.c:3506 msgid " CONVERSION ERROR" msgstr " ERARO DE KONVERTO" -#: ../fileio.c:3509 #, c-format -msgid " in line %<PRId64>;" -msgstr " en linio %<PRId64>;" +msgid " in line %ld;" +msgstr " en linio %ld;" -#: ../fileio.c:3519 msgid "[Device]" msgstr "[Aparatdosiero]" -#: ../fileio.c:3522 msgid "[New]" msgstr "[Nova]" -#: ../fileio.c:3535 msgid " [a]" msgstr " [a]" -#: ../fileio.c:3535 msgid " appended" msgstr " postaldonita(j)" -#: ../fileio.c:3537 msgid " [w]" msgstr " [s]" -#: ../fileio.c:3537 msgid " written" msgstr " skribita(j)" -#: ../fileio.c:3579 msgid "E205: Patchmode: can't save original file" msgstr "E205: Patchmode: ne eblas konservi originalan dosieron" -#: ../fileio.c:3602 msgid "E206: patchmode: can't touch empty original file" msgstr "E206: patchmode: ne eblas tuลi malplenan originalan dosieron" -#: ../fileio.c:3616 msgid "E207: Can't delete backup file" msgstr "E207: Ne eblas forviลi restaลญrkopion" -#: ../fileio.c:3672 msgid "" "\n" "WARNING: Original file may be lost or damaged\n" @@ -2301,96 +1851,75 @@ msgstr "" "\n" "AVERTO: Originala dosiero estas eble perdita aลญ difekta\n" -#: ../fileio.c:3675 msgid "don't quit the editor until the file is successfully written!" msgstr "ne eliru el la redaktilo ฤis kiam la dosiero estas sukcese konservita!" -#: ../fileio.c:3795 msgid "[dos]" msgstr "[dos]" -#: ../fileio.c:3795 msgid "[dos format]" msgstr "[formato dos]" -#: ../fileio.c:3801 msgid "[mac]" msgstr "[mac]" -#: ../fileio.c:3801 msgid "[mac format]" msgstr "[formato mac]" -#: ../fileio.c:3807 msgid "[unix]" msgstr "[unikso]" -#: ../fileio.c:3807 msgid "[unix format]" msgstr "[formato unikso]" -#: ../fileio.c:3831 msgid "1 line, " msgstr "1 linio, " -#: ../fileio.c:3833 #, c-format -msgid "%<PRId64> lines, " -msgstr "%<PRId64> linioj, " +msgid "%ld lines, " +msgstr "%ld linioj, " -#: ../fileio.c:3836 msgid "1 character" msgstr "1 signo" -#: ../fileio.c:3838 #, c-format -msgid "%<PRId64> characters" -msgstr "%<PRId64> signoj" +msgid "%lld characters" +msgstr "%lld signoj" -#: ../fileio.c:3849 msgid "[noeol]" msgstr "[sen EOL]" -#: ../fileio.c:3849 msgid "[Incomplete last line]" msgstr "[Nekompleta lasta linio]" #. don't overwrite messages here #. must give this prompt #. don't use emsg() here, don't want to flush the buffers -#: ../fileio.c:3865 msgid "WARNING: The file has been changed since reading it!!!" msgstr "AVERTO: La dosiero estas ลanฤita de post kiam ฤi estis legita!!!" -#: ../fileio.c:3867 msgid "Do you really want to write to it" msgstr "ฤu vi vere volas skribi al ฤi" -#: ../fileio.c:4648 #, c-format msgid "E208: Error writing to \"%s\"" msgstr "E208: Eraro dum skribo de \"%s\"" -#: ../fileio.c:4655 #, c-format msgid "E209: Error closing \"%s\"" msgstr "E209: Eraro dum fermo de \"%s\"" -#: ../fileio.c:4657 #, c-format msgid "E210: Error reading \"%s\"" msgstr "E210: Eraro dum lego de \"%s\"" -#: ../fileio.c:4883 msgid "E246: FileChangedShell autocommand deleted buffer" msgstr "E246: Aลญtokomando FileChangedShell forviลis bufron" -#: ../fileio.c:4894 #, c-format msgid "E211: File \"%s\" no longer available" msgstr "E211: Dosiero \"%s\" ne plu haveblas" -#: ../fileio.c:4906 #, c-format msgid "" "W12: Warning: File \"%s\" has changed and the buffer was changed in Vim as " @@ -2398,38 +1927,30 @@ msgid "" msgstr "" "W12: Averto: Dosiero \"%s\" ลanฤiฤis kaj la bufro estis ลanฤita ankaลญ en Vim" -#: ../fileio.c:4907 msgid "See \":help W12\" for more info." msgstr "Vidu \":help W12\" por pliaj informoj." -#: ../fileio.c:4910 #, c-format msgid "W11: Warning: File \"%s\" has changed since editing started" msgstr "W11: Averto: La dosiero \"%s\" ลanฤiฤis ekde redakti ฤin" -#: ../fileio.c:4911 msgid "See \":help W11\" for more info." msgstr "Vidu \":help W11\" por pliaj informoj." -#: ../fileio.c:4914 #, c-format msgid "W16: Warning: Mode of file \"%s\" has changed since editing started" msgstr "W16: Averto: Permeso de dosiero \"%s\" ลanฤiฤis ekde redakti ฤin" -#: ../fileio.c:4915 msgid "See \":help W16\" for more info." msgstr "Vidu \":help W16\" por pliaj informoj." -#: ../fileio.c:4927 #, c-format msgid "W13: Warning: File \"%s\" has been created after editing started" msgstr "W13: Averto: Dosiero \"%s\" kreiฤis post la komenco de redaktado" -#: ../fileio.c:4947 msgid "Warning" msgstr "Averto" -#: ../fileio.c:4948 msgid "" "&OK\n" "&Load File" @@ -2437,48 +1958,45 @@ msgstr "" "&Bone\n" "ล&argi Dosieron" -#: ../fileio.c:5065 #, c-format msgid "E462: Could not prepare for reloading \"%s\"" msgstr "E462: Ne eblis prepari por reลargi \"%s\"" -#: ../fileio.c:5078 #, c-format msgid "E321: Could not reload \"%s\"" msgstr "E321: Ne eblis reลargi \"%s\"" -#: ../fileio.c:5601 msgid "--Deleted--" msgstr "--Forviลita--" -#: ../fileio.c:5732 #, c-format msgid "auto-removing autocommand: %s <buffer=%d>" msgstr "aลญto-forviลas aลญtokomandon: %s <bufro=%d>" #. the group doesn't exist -#: ../fileio.c:5772 #, c-format msgid "E367: No such group: \"%s\"" msgstr "E367: Ne ekzistas tia grupo: \"%s\"" -#: ../fileio.c:5897 +msgid "E936: Cannot delete the current group" +msgstr "E936: Ne eblas forviลi la aktualan grupon" + +msgid "W19: Deleting augroup that is still in use" +msgstr "W19: Forviลo de augroup kiu estas ankoraลญ uzata" + #, c-format msgid "E215: Illegal character after *: %s" msgstr "E215: Nevalida signo post *: %s" -#: ../fileio.c:5905 #, c-format msgid "E216: No such event: %s" msgstr "E216: Ne estas tia evento: %s" -#: ../fileio.c:5907 #, c-format msgid "E216: No such group or event: %s" msgstr "E216: Ne ekzistas tia grupo aลญ evento: %s" #. Highlight title -#: ../fileio.c:6090 msgid "" "\n" "--- Auto-Commands ---" @@ -2486,767 +2004,561 @@ msgstr "" "\n" "--- Aลญto-Komandoj ---" -#: ../fileio.c:6293 #, c-format msgid "E680: <buffer=%d>: invalid buffer number " msgstr "E680: <bufro=%d>: nevalida numero de bufro " -#: ../fileio.c:6370 msgid "E217: Can't execute autocommands for ALL events" msgstr "E217: Ne eblas plenumi aลญtokomandojn por ฤIUJ eventoj" -#: ../fileio.c:6393 msgid "No matching autocommands" msgstr "Neniu kongrua aลญtokomando" -#: ../fileio.c:6831 msgid "E218: autocommand nesting too deep" msgstr "E218: aลญtokomando tro ingita" -#: ../fileio.c:7143 #, c-format msgid "%s Auto commands for \"%s\"" msgstr "%s Aลญtokomandoj por \"%s\"" -#: ../fileio.c:7149 #, c-format msgid "Executing %s" msgstr "Plenumado de %s" -#: ../fileio.c:7211 #, c-format msgid "autocommand %s" msgstr "aลญtokomando %s" -#: ../fileio.c:7795 msgid "E219: Missing {." msgstr "E219: Mankas {." -#: ../fileio.c:7797 msgid "E220: Missing }." msgstr "E220: Mankas }." -#: ../fold.c:93 msgid "E490: No fold found" msgstr "E490: Neniu faldo trovita" -#: ../fold.c:544 msgid "E350: Cannot create fold with current 'foldmethod'" msgstr "E350: Ne eblas krei faldon per la aktuala 'foldmethod'" -#: ../fold.c:546 msgid "E351: Cannot delete fold with current 'foldmethod'" msgstr "E351: Ne eblas forviลi faldon per la aktuala 'foldmethod'" -#: ../fold.c:1784 #, c-format -msgid "+--%3ld lines folded " -msgstr "+--%3ld linioj falditaj " +msgid "+--%3ld line folded " +msgid_plural "+--%3ld lines folded " +msgstr[0] "+--%3ld linio faldita " +msgstr[1] "+--%3ld linioj falditaj " -#. buffer has already been read -#: ../getchar.c:273 msgid "E222: Add to read buffer" msgstr "E222: Aldoni al lega bufro" -#: ../getchar.c:2040 msgid "E223: recursive mapping" msgstr "E223: rekursia mapo" -#: ../getchar.c:2849 #, c-format msgid "E224: global abbreviation already exists for %s" msgstr "E224: malloka mallongigo jam ekzistas por %s" -#: ../getchar.c:2852 #, c-format msgid "E225: global mapping already exists for %s" msgstr "E225: malloka mapo jam ekzistas por %s" -#: ../getchar.c:2952 #, c-format msgid "E226: abbreviation already exists for %s" msgstr "E226: mallongigo jam ekzistas por %s" -#: ../getchar.c:2955 #, c-format msgid "E227: mapping already exists for %s" msgstr "E227: mapo jam ekzistas por %s" -#: ../getchar.c:3008 msgid "No abbreviation found" msgstr "Neniu mallongigo trovita" -#: ../getchar.c:3010 msgid "No mapping found" msgstr "Neniu mapo trovita" -#: ../getchar.c:3974 msgid "E228: makemap: Illegal mode" msgstr "E228: makemap: Nevalida reฤimo" -#. key value of 'cedit' option -#. type of cmdline window or 0 -#. result of cmdline window or 0 -#: ../globals.h:924 -msgid "--No lines in buffer--" -msgstr "--Neniu linio en bufro--" - -#. -#. * The error messages that can be shared are included here. -#. * Excluded are errors that are only used once and debugging messages. -#. -#: ../globals.h:996 -msgid "E470: Command aborted" -msgstr "E470: komando ฤesigita" +msgid "E851: Failed to create a new process for the GUI" +msgstr "E851: Malsukcesis krei novan procezon por la grafika interfaco" -#: ../globals.h:997 -msgid "E471: Argument required" -msgstr "E471: Argumento bezonata" +msgid "E852: The child process failed to start the GUI" +msgstr "E852: La ida procezo malsukcesis startigi la grafikan interfacon" -#: ../globals.h:998 -msgid "E10: \\ should be followed by /, ? or &" -msgstr "E10: \\ devus esti sekvita de /, ? aลญ &" +msgid "E229: Cannot start the GUI" +msgstr "E229: Ne eblas lanฤi la grafikan interfacon" -#: ../globals.h:1000 -msgid "E11: Invalid in command-line window; <CR> executes, CTRL-C quits" -msgstr "" -"E11: Nevalida en fenestro de komanda linio; <CR> plenumas, CTRL-C eliras" +#, c-format +msgid "E230: Cannot read from \"%s\"" +msgstr "E230: Ne eblas legi el \"%s\"" -#: ../globals.h:1002 -msgid "E12: Command not allowed from exrc/vimrc in current dir or tag search" +msgid "E665: Cannot start GUI, no valid font found" msgstr "" -"E12: Nepermesebla komando el exrc/vimrc en aktuala dosierujo aลญ etikeda serฤo" +"E665: Ne eblas startigi grafikan interfacon, neniu valida tiparo trovita" -#: ../globals.h:1003 -msgid "E171: Missing :endif" -msgstr "E171: Mankas \":endif\"" +msgid "E231: 'guifontwide' invalid" +msgstr "E231: 'guifontwide' nevalida" -#: ../globals.h:1004 -msgid "E600: Missing :endtry" -msgstr "E600: Mankas \":endtry\"" +msgid "E599: Value of 'imactivatekey' is invalid" +msgstr "E599: Valoro de 'imactivatekey' estas nevalida" -#: ../globals.h:1005 -msgid "E170: Missing :endwhile" -msgstr "E170: Mankas \":endwhile\"" +#, c-format +msgid "E254: Cannot allocate color %s" +msgstr "E254: Ne eblas disponigi koloron %s" -#: ../globals.h:1006 -msgid "E170: Missing :endfor" -msgstr "E170: Mankas \":endfor\"" +msgid "No match at cursor, finding next" +msgstr "Neniu kongruo ฤe kursorpozicio, trovas sekvan" -#: ../globals.h:1007 -msgid "E588: :endwhile without :while" -msgstr "E588: \":endwhile\" sen \":while\"" +msgid "<cannot open> " +msgstr "<ne eblas malfermi> " -#: ../globals.h:1008 -msgid "E588: :endfor without :for" -msgstr "E588: \":endfor\" sen \":for\"" +#, c-format +msgid "E616: vim_SelFile: can't get font %s" +msgstr "E616: vim_SelFile: ne eblas akiri tiparon %s" -#: ../globals.h:1009 -msgid "E13: File exists (add ! to override)" -msgstr "E13: Dosiero ekzistas (aldonu ! por transpasi)" +msgid "E614: vim_SelFile: can't return to current directory" +msgstr "E614: vim_SelFile: ne eblas reveni al la aktuala dosierujo" -#: ../globals.h:1010 -msgid "E472: Command failed" -msgstr "E472: La komando fiaskis" +msgid "Pathname:" +msgstr "Serฤvojo:" -#: ../globals.h:1011 -msgid "E473: Internal error" -msgstr "E473: Interna eraro" +msgid "E615: vim_SelFile: can't get current directory" +msgstr "E615: vim_SelFile: ne eblas akiri aktualan dosierujon" -#: ../globals.h:1012 -msgid "Interrupted" -msgstr "Interrompita" +msgid "OK" +msgstr "Bone" -#: ../globals.h:1013 -msgid "E14: Invalid address" -msgstr "E14: Nevalida adreso" +msgid "Cancel" +msgstr "Rezigni" -#: ../globals.h:1014 -msgid "E474: Invalid argument" -msgstr "E474: Nevalida argumento" +msgid "Scrollbar Widget: Could not get geometry of thumb pixmap." +msgstr "" +"Fenestraฤตo de rulumskalo: Ne eblis akiri geometrion de reduktita rastrumbildo" -#: ../globals.h:1015 -#, c-format -msgid "E475: Invalid argument: %s" -msgstr "E475: Nevalida argumento: %s" +msgid "Vim dialog" +msgstr "Vim dialogo" -#: ../globals.h:1016 -#, c-format -msgid "E15: Invalid expression: %s" -msgstr "E15: Nevalida esprimo: %s" +msgid "E232: Cannot create BalloonEval with both message and callback" +msgstr "E232: Ne eblas krei BalloonEval kun ambaลญ mesaฤo kaj reagfunkcio" -#: ../globals.h:1017 -msgid "E16: Invalid range" -msgstr "E16: Nevalida amplekso" +msgid "_Cancel" +msgstr "_Rezigni" -#: ../globals.h:1018 -msgid "E476: Invalid command" -msgstr "E476: Nevalida komando" +msgid "_Save" +msgstr "_Konservi" -#: ../globals.h:1019 -#, c-format -msgid "E17: \"%s\" is a directory" -msgstr "E17: \"%s\" estas dosierujo" +msgid "_Open" +msgstr "_Malfermi" -#: ../globals.h:1020 -#, fuzzy -msgid "E900: Invalid job id" -msgstr "E49: Nevalida grando de rulumo" +msgid "_OK" +msgstr "_Bone" -#: ../globals.h:1021 -msgid "E901: Job table is full" +msgid "" +"&Yes\n" +"&No\n" +"&Cancel" msgstr "" +"&Jes\n" +"&Ne\n" +"&Rezigni" -#: ../globals.h:1024 -#, c-format -msgid "E364: Library call failed for \"%s()\"" -msgstr "E364: Alvoko al biblioteko fiaskis por \"%s()\"" +msgid "Yes" +msgstr "Jes" -#: ../globals.h:1026 -msgid "E19: Mark has invalid line number" -msgstr "E19: Marko havas nevalidan numeron de linio" +msgid "No" +msgstr "Ne" -#: ../globals.h:1027 -msgid "E20: Mark not set" -msgstr "E20: Marko ne estas agordita" +# todo '_' is for hotkey, i guess? +msgid "Input _Methods" +msgstr "Enigaj _metodoj" -#: ../globals.h:1029 -msgid "E21: Cannot make changes, 'modifiable' is off" -msgstr "E21: Ne eblas fari ลanฤojn, 'modifiable' estas malลaltita" +msgid "VIM - Search and Replace..." +msgstr "VIM - Serฤi kaj anstataลญigi..." -#: ../globals.h:1030 -msgid "E22: Scripts nested too deep" -msgstr "E22: Tro profunde ingitaj skriptoj" +msgid "VIM - Search..." +msgstr "VIM- Serฤi..." -#: ../globals.h:1031 -msgid "E23: No alternate file" -msgstr "E23: Neniu alterna dosiero" +msgid "Find what:" +msgstr "Serฤi kion:" -#: ../globals.h:1032 -msgid "E24: No such abbreviation" -msgstr "E24: Ne estas tia mallongigo" +msgid "Replace with:" +msgstr "Anstataลญigi per:" -#: ../globals.h:1033 -msgid "E477: No ! allowed" -msgstr "E477: Neniu ! permesebla" +#. whole word only button +msgid "Match whole word only" +msgstr "Kongrui kun nur plena vorto" -#: ../globals.h:1035 -msgid "E25: Nvim does not have a built-in GUI" -msgstr "E25: Grafika interfaco ne uzeblas: Malลaltita dum kompilado" +#. match case button +msgid "Match case" +msgstr "Uskleca kongruo" -#: ../globals.h:1036 -#, c-format -msgid "E28: No such highlight group name: %s" -msgstr "E28: Neniu grupo de emfazo kiel: %s" +msgid "Direction" +msgstr "Direkto" -#: ../globals.h:1037 -msgid "E29: No inserted text yet" -msgstr "E29: Ankoraลญ neniu enmetita teksto" +#. 'Up' and 'Down' buttons +msgid "Up" +msgstr "Supren" -#: ../globals.h:1038 -msgid "E30: No previous command line" -msgstr "E30: Neniu antaลญa komanda linio" +msgid "Down" +msgstr "Suben" -#: ../globals.h:1039 -msgid "E31: No such mapping" -msgstr "E31: Neniu tiel mapo" +msgid "Find Next" +msgstr "Trovi sekvantan" -#: ../globals.h:1040 -msgid "E479: No match" -msgstr "E479: Neniu kongruo" +msgid "Replace" +msgstr "Anstataลญigi" -#: ../globals.h:1041 -#, c-format -msgid "E480: No match: %s" -msgstr "E480: Neniu kongruo: %s" +msgid "Replace All" +msgstr "Anstataลญigi ฤiujn" -#: ../globals.h:1042 -msgid "E32: No file name" -msgstr "E32: Neniu dosiernomo" +msgid "_Close" +msgstr "_Fermi" -#: ../globals.h:1044 -msgid "E33: No previous substitute regular expression" -msgstr "E33: Neniu antaลญa regulesprimo de anstataลญigo" +msgid "Vim: Received \"die\" request from session manager\n" +msgstr "Vim: Ricevis peton \"die\" (morti) el la seanca administrilo\n" -#: ../globals.h:1045 -msgid "E34: No previous command" -msgstr "E34: Neniu antaลญa komando" +msgid "Close tab" +msgstr "Fermi langeton" -#: ../globals.h:1046 -msgid "E35: No previous regular expression" -msgstr "E35: Neniu antaลญa regulesprimo" +msgid "New tab" +msgstr "Nova langeto" -#: ../globals.h:1047 -msgid "E481: No range allowed" -msgstr "E481: Amplekso nepermesebla" +msgid "Open Tab..." +msgstr "Malfermi langeton..." -#: ../globals.h:1048 -msgid "E36: Not enough room" -msgstr "E36: Ne sufiฤe da spaco" +msgid "Vim: Main window unexpectedly destroyed\n" +msgstr "Vim: ฤefa fenestro neatendite detruiฤis\n" -#: ../globals.h:1049 -#, c-format -msgid "E482: Can't create file %s" -msgstr "E482: Ne eblas krei dosieron %s" +msgid "&Filter" +msgstr "&Filtri" -#: ../globals.h:1050 -msgid "E483: Can't get temp file name" -msgstr "E483: Ne eblas akiri provizoran dosiernomon" +msgid "&Cancel" +msgstr "&Rezigni" -#: ../globals.h:1051 -#, c-format -msgid "E484: Can't open file %s" -msgstr "E484: Ne eblas malfermi dosieron %s" +msgid "Directories" +msgstr "Dosierujoj" -#: ../globals.h:1052 -#, c-format -msgid "E485: Can't read file %s" -msgstr "E485: Ne eblas legi dosieron %s" +msgid "Filter" +msgstr "Filtri" -#: ../globals.h:1054 -msgid "E37: No write since last change (add ! to override)" -msgstr "E37: Neniu skribo de post lasta ลanฤo (aldonu ! por transpasi)" +msgid "&Help" +msgstr "&Helpo" -#: ../globals.h:1055 -#, fuzzy -msgid "E37: No write since last change" -msgstr "[Neniu skribo de post lasta ลanฤo]\n" +msgid "Files" +msgstr "Dosieroj" -#: ../globals.h:1056 -msgid "E38: Null argument" -msgstr "E38: Nula argumento" +msgid "&OK" +msgstr "&Bone" -#: ../globals.h:1057 -msgid "E39: Number expected" -msgstr "E39: Nombro atendita" +msgid "Selection" +msgstr "Apartigo" -#: ../globals.h:1058 -#, c-format -msgid "E40: Can't open errorfile %s" -msgstr "E40: Ne eblas malfermi eraran dosieron %s" +msgid "Find &Next" +msgstr "Trovi &Sekvanta" -#: ../globals.h:1059 -msgid "E41: Out of memory!" -msgstr "E41: Ne plu restas memoro!" +msgid "&Replace" +msgstr "&Anstataลญigi" -#: ../globals.h:1060 -msgid "Pattern not found" -msgstr "ลablono ne trovita" +msgid "Replace &All" +msgstr "Anstataลญigi ฤi&on" -#: ../globals.h:1061 -#, c-format -msgid "E486: Pattern not found: %s" -msgstr "E486: ลablono ne trovita: %s" - -#: ../globals.h:1062 -msgid "E487: Argument must be positive" -msgstr "E487: La argumento devas esti pozitiva" +msgid "&Undo" +msgstr "&Malfari" -#: ../globals.h:1064 -msgid "E459: Cannot go back to previous directory" -msgstr "E459: Ne eblas reiri al antaลญa dosierujo" - -#: ../globals.h:1066 -msgid "E42: No Errors" -msgstr "E42: Neniu eraro" +msgid "Open tab..." +msgstr "Malfermi langeton..." -#: ../globals.h:1067 -msgid "E776: No location list" -msgstr "E776: Neniu listo de loko" +msgid "Find string (use '\\\\' to find a '\\')" +msgstr "Trovi ฤenon (uzu '\\\\' por trovi '\\')" -#: ../globals.h:1068 -msgid "E43: Damaged match string" -msgstr "E43: Difekta kongruenda ฤeno" +msgid "Find & Replace (use '\\\\' to find a '\\')" +msgstr "Trovi kaj anstataลญigi (uzu '\\\\' por trovi '\\')" -#: ../globals.h:1069 -msgid "E44: Corrupted regexp program" -msgstr "E44: Difekta programo de regulesprimo" +#. We fake this: Use a filter that doesn't select anything and a default +#. * file name that won't be used. +msgid "Not Used" +msgstr "Ne uzata" -#: ../globals.h:1071 -msgid "E45: 'readonly' option is set (add ! to override)" -msgstr "E45: La opcio 'readonly' estas ลaltita '(aldonu ! por transpasi)" +msgid "Directory\t*.nothing\n" +msgstr "Dosierujo\t*.nenio\n" -#: ../globals.h:1073 #, c-format -msgid "E46: Cannot change read-only variable \"%s\"" -msgstr "E46: Ne eblas ลanฤi nurlegeblan variablon \"%s\"" +msgid "E671: Cannot find window title \"%s\"" +msgstr "E671: Ne eblas trovi titolon de fenestro \"%s\"" -#: ../globals.h:1075 #, c-format -msgid "E794: Cannot set variable in the sandbox: \"%s\"" -msgstr "E794: Ne eblas agordi variablon en la sabloludejo: \"%s\"" +msgid "E243: Argument not supported: \"-%s\"; Use the OLE version." +msgstr "E243: Ne subtenata argumento: \"-%s\"; Uzu la version OLE." -msgid "E713: Cannot use empty key for Dictionary" -msgstr "E713: Ne eblas uzi malplenan ลlosilon de Vortaro" - -#: ../globals.h:1076 -msgid "E47: Error while reading errorfile" -msgstr "E47: Eraro dum legado de erardosiero" - -#: ../globals.h:1078 -msgid "E48: Not allowed in sandbox" -msgstr "E48: Nepermesebla en sabloludejo" - -#: ../globals.h:1080 -msgid "E523: Not allowed here" -msgstr "E523: Nepermesebla tie" +msgid "E672: Unable to open window inside MDI application" +msgstr "E672: Ne eblas malfermi fenestron interne de aplikaฤตo MDI" -#: ../globals.h:1082 -msgid "E359: Screen mode setting not supported" -msgstr "E359: Reฤimo de ekrano ne subtenata" - -#: ../globals.h:1083 -msgid "E49: Invalid scroll size" -msgstr "E49: Nevalida grando de rulumo" - -#: ../globals.h:1084 -msgid "E91: 'shell' option is empty" -msgstr "E91: La opcio 'shell' estas malplena" - -#: ../globals.h:1085 -msgid "E255: Couldn't read in sign data!" -msgstr "E255: Ne eblis legi datumojn de simboloj!" - -#: ../globals.h:1086 -msgid "E72: Close error on swap file" -msgstr "E72: Eraro dum malfermo de permutodosiero .swp" - -#: ../globals.h:1087 -msgid "E73: tag stack empty" -msgstr "E73: malplena stako de etikedo" - -#: ../globals.h:1088 -msgid "E74: Command too complex" -msgstr "E74: Komando tro kompleksa" - -#: ../globals.h:1089 -msgid "E75: Name too long" -msgstr "E75: Nomo tro longa" +msgid "Vim E458: Cannot allocate colormap entry, some colors may be incorrect" +msgstr "" +"Vim E458: Ne eblas disponigi rikordon de kolormapo, iuj koloroj estas eble " +"neฤustaj" -#: ../globals.h:1090 -msgid "E76: Too many [" -msgstr "E76: Tro da [" +#, c-format +msgid "E250: Fonts for the following charsets are missing in fontset %s:" +msgstr "E250: Tiparoj de tiuj signaroj mankas en aro de tiparo %s:" -#: ../globals.h:1091 -msgid "E77: Too many file names" -msgstr "E77: Tro da dosiernomoj" +#, c-format +msgid "E252: Fontset name: %s" +msgstr "E252: Nomo de tiparo: %s" -#: ../globals.h:1092 -msgid "E488: Trailing characters" -msgstr "E488: Vostaj signoj" +#, c-format +msgid "Font '%s' is not fixed-width" +msgstr "Tiparo '%s' ne estas egallarฤa" -#: ../globals.h:1093 -msgid "E78: Unknown mark" -msgstr "E78: Nekonata marko" +#, c-format +msgid "E253: Fontset name: %s" +msgstr "E253: Nomo de tiparo: %s" -#: ../globals.h:1094 -msgid "E79: Cannot expand wildcards" -msgstr "E79: Ne eblas malvolvi ฤตokerojn" +#, c-format +msgid "Font0: %s" +msgstr "Font0: %s" -#: ../globals.h:1096 -msgid "E591: 'winheight' cannot be smaller than 'winminheight'" -msgstr "E591: 'winheight' ne rajtas esti malpli ol 'winminheight'" +#, c-format +msgid "Font1: %s" +msgstr "Font1: %s" -#: ../globals.h:1098 -msgid "E592: 'winwidth' cannot be smaller than 'winminwidth'" -msgstr "E592: 'winwidth' ne rajtas esti malpli ol 'winminwidth'" +#, c-format +msgid "Font%ld width is not twice that of font0" +msgstr "Font%ld ne estas duoble pli larฤa ol font0" -#: ../globals.h:1099 -msgid "E80: Error while writing" -msgstr "E80: Eraro dum skribado" +#, c-format +msgid "Font0 width: %ld" +msgstr "Larฤo de font0: %ld" -#: ../globals.h:1100 -msgid "Zero count" -msgstr "Nul kvantoro" +#, c-format +msgid "Font1 width: %ld" +msgstr "Larฤo de Font1: %ld" -#: ../globals.h:1101 -msgid "E81: Using <SID> not in a script context" -msgstr "E81: Uzo de <SID> ekster kunteksto de skripto" +msgid "Invalid font specification" +msgstr "Nevalida tiparo specifita" -#: ../globals.h:1102 -#, c-format -msgid "E685: Internal error: %s" -msgstr "E685: Interna eraro: %s" +msgid "&Dismiss" +msgstr "&Forlasi" -#: ../globals.h:1104 -msgid "E363: pattern uses more memory than 'maxmempattern'" -msgstr "E363: ลablono uzas pli da memoro ol 'maxmempattern'" +msgid "no specific match" +msgstr "Neniu specifa kongruo" -#: ../globals.h:1105 -msgid "E749: empty buffer" -msgstr "E749: malplena bufro" +msgid "Vim - Font Selector" +msgstr "Vim - Elektilo de tiparo" -#: ../globals.h:1226 -#, c-format -msgid "E86: Buffer %<PRId64> does not exist" -msgstr "E86: La bufro %<PRId64> ne ekzistas" +msgid "Name:" +msgstr "Nomo:" -#: ../globals.h:1108 -msgid "E682: Invalid search pattern or delimiter" -msgstr "E682: Nevalida serฤa ลablono aลญ disigilo" +#. create toggle button +msgid "Show size in Points" +msgstr "Montri grandon en punktoj" -#: ../globals.h:1109 -msgid "E139: File is loaded in another buffer" -msgstr "E139: Dosiero estas ลargita en alia bufro" +msgid "Encoding:" +msgstr "Kodoprezento:" -#: ../globals.h:1110 -#, c-format -msgid "E764: Option '%s' is not set" -msgstr "E764: La opcio '%s' ne estas ลaltita" +msgid "Font:" +msgstr "Tiparo:" -#: ../globals.h:1111 -msgid "E850: Invalid register name" -msgstr "E850: Nevalida nomo de reฤistro" +msgid "Style:" +msgstr "Stilo:" -#: ../globals.h:1114 -msgid "search hit TOP, continuing at BOTTOM" -msgstr "serฤo atingis SUPRON, daลญrigonte al SUBO" +msgid "Size:" +msgstr "Grando:" -#: ../globals.h:1115 -msgid "search hit BOTTOM, continuing at TOP" -msgstr "serฤo atingis SUBON, daลญrigonte al SUPRO" +msgid "E256: Hangul automata ERROR" +msgstr "E256: ERARO en aลญtomato de korea alfabeto" -#: ../hardcopy.c:240 msgid "E550: Missing colon" msgstr "E550: Mankas dupunkto" -#: ../hardcopy.c:252 msgid "E551: Illegal component" msgstr "E551: Nevalida komponento" -#: ../hardcopy.c:259 msgid "E552: digit expected" msgstr "E552: cifero atendita" -#: ../hardcopy.c:473 #, c-format msgid "Page %d" msgstr "Paฤo %d" -#: ../hardcopy.c:597 msgid "No text to be printed" msgstr "Neniu presenda teksto" -#: ../hardcopy.c:668 #, c-format msgid "Printing page %d (%d%%)" msgstr "Presas paฤon %d (%d%%)" -#: ../hardcopy.c:680 #, c-format msgid " Copy %d of %d" msgstr " Kopio %d de %d" -#: ../hardcopy.c:733 #, c-format msgid "Printed: %s" msgstr "Presis: %s" -#: ../hardcopy.c:740 msgid "Printing aborted" msgstr "Presado ฤesigita" -#: ../hardcopy.c:1365 msgid "E455: Error writing to PostScript output file" msgstr "E455: Eraro dum skribo de PostSkripta eliga dosiero" -#: ../hardcopy.c:1747 #, c-format msgid "E624: Can't open file \"%s\"" msgstr "E624: Ne eblas malfermi dosieron \"%s\"" -#: ../hardcopy.c:1756 ../hardcopy.c:2470 #, c-format msgid "E457: Can't read PostScript resource file \"%s\"" msgstr "E457: Ne eblas legi dosieron de PostSkripta rimedo \"%s\"" -#: ../hardcopy.c:1772 #, c-format msgid "E618: file \"%s\" is not a PostScript resource file" msgstr "E618: \"%s\" ne estas dosiero de PostSkripta rimedo" -#: ../hardcopy.c:1788 ../hardcopy.c:1805 ../hardcopy.c:1844 #, c-format msgid "E619: file \"%s\" is not a supported PostScript resource file" msgstr "E619: \"%s\" ne estas subtenata dosiero de PostSkripta rimedo" -#: ../hardcopy.c:1856 #, c-format msgid "E621: \"%s\" resource file has wrong version" msgstr "E621: \"%s\" dosiero de rimedo havas neฤustan version" -#: ../hardcopy.c:2225 msgid "E673: Incompatible multi-byte encoding and character set." msgstr "E673: Nekongrua plurbajta kodoprezento kaj signaro." -#: ../hardcopy.c:2238 msgid "E674: printmbcharset cannot be empty with multi-byte encoding." msgstr "" "E674: printmbcharset ne rajtas esti malplena kun plurbajta kodoprezento." -#: ../hardcopy.c:2254 msgid "E675: No default font specified for multi-byte printing." msgstr "E675: Neniu defaลญlta tiparo specifita por plurbajta presado." -#: ../hardcopy.c:2426 msgid "E324: Can't open PostScript output file" msgstr "E324: Ne eblas malfermi eligan PostSkriptan dosieron" -#: ../hardcopy.c:2458 #, c-format msgid "E456: Can't open file \"%s\"" msgstr "E456: Ne eblas malfermi dosieron \"%s\"" -#: ../hardcopy.c:2583 msgid "E456: Can't find PostScript resource file \"prolog.ps\"" msgstr "E456: Dosiero de PostSkripta rimedo \"prolog.ps\" ne troveblas" -#: ../hardcopy.c:2593 msgid "E456: Can't find PostScript resource file \"cidfont.ps\"" msgstr "E456: Dosiero de PostSkripta rimedo \"cidfont.ps\" ne troveblas" -#: ../hardcopy.c:2622 ../hardcopy.c:2639 ../hardcopy.c:2665 #, c-format msgid "E456: Can't find PostScript resource file \"%s.ps\"" msgstr "E456: Dosiero de PostSkripta rimedo \"%s.ps\" ne troveblas" -#: ../hardcopy.c:2654 #, c-format msgid "E620: Unable to convert to print encoding \"%s\"" msgstr "E620: Ne eblas konverti al la presa kodoprezento \"%s\"" -#: ../hardcopy.c:2877 msgid "Sending to printer..." msgstr "Sendas al presilo..." -#: ../hardcopy.c:2881 msgid "E365: Failed to print PostScript file" -msgstr "E365: Presado de PostSkripta dosiero fiaskis" +msgstr "E365: Presado de PostSkripta dosiero malsukcesis" -#: ../hardcopy.c:2883 msgid "Print job sent." msgstr "Laboro de presado sendita." -#: ../if_cscope.c:85 msgid "Add a new database" msgstr "Aldoni novan datumbazon" -#: ../if_cscope.c:87 msgid "Query for a pattern" msgstr "Serฤi ลablonon" -#: ../if_cscope.c:89 msgid "Show this message" msgstr "Montri tiun mesaฤon" -#: ../if_cscope.c:91 msgid "Kill a connection" msgstr "ฤesigi konekton" -#: ../if_cscope.c:93 msgid "Reinit all connections" msgstr "Repravalorizi ฤiujn konektojn" -#: ../if_cscope.c:95 msgid "Show connections" msgstr "Montri konektojn" -#: ../if_cscope.c:101 #, c-format msgid "E560: Usage: cs[cope] %s" msgstr "E560: Uzo: cs[cope] %s" -#: ../if_cscope.c:225 msgid "This cscope command does not support splitting the window.\n" msgstr "Tiu ฤi komando de cscope ne subtenas dividon de fenestro.\n" -#: ../if_cscope.c:266 msgid "E562: Usage: cstag <ident>" msgstr "E562: Uzo: cstag <ident>" -#: ../if_cscope.c:313 msgid "E257: cstag: tag not found" msgstr "E257: cstag: etikedo netrovita" -#: ../if_cscope.c:461 #, c-format msgid "E563: stat(%s) error: %d" msgstr "E563: Eraro de stat(%s): %d" -#: ../if_cscope.c:551 +msgid "E563: stat error" +msgstr "E563: Eraro de stat" + #, c-format msgid "E564: %s is not a directory or a valid cscope database" msgstr "E564: %s ne estas dosierujo aลญ valida datumbazo de cscope" -#: ../if_cscope.c:566 #, c-format msgid "Added cscope database %s" msgstr "Aldonis datumbazon de cscope %s" -#: ../if_cscope.c:616 #, c-format -msgid "E262: error reading cscope connection %<PRId64>" -msgstr "E262: eraro dum legado de konekto de cscope %<PRId64>" +msgid "E262: error reading cscope connection %ld" +msgstr "E262: eraro dum legado de konekto de cscope %ld" -#: ../if_cscope.c:711 msgid "E561: unknown cscope search type" msgstr "E561: nekonata tipo de serฤo de cscope" -#: ../if_cscope.c:752 ../if_cscope.c:789 msgid "E566: Could not create cscope pipes" msgstr "E566: Ne eblis krei duktojn de cscope" -#: ../if_cscope.c:767 msgid "E622: Could not fork for cscope" msgstr "E622: Ne eblis forki cscope" -#: ../if_cscope.c:849 -#, fuzzy msgid "cs_create_connection setpgid failed" -msgstr "plenumo de cs_create_connection fiaskis" +msgstr "plenumo de cs_create_connection-setgpid malsukcesis" -#: ../if_cscope.c:853 ../if_cscope.c:889 msgid "cs_create_connection exec failed" -msgstr "plenumo de cs_create_connection fiaskis" +msgstr "plenumo de cs_create_connection malsukcesis" -#: ../if_cscope.c:863 ../if_cscope.c:902 msgid "cs_create_connection: fdopen for to_fp failed" -msgstr "cs_create_connection: fdopen de to_fp fiaskis" +msgstr "cs_create_connection: fdopen de to_fp malsukcesis" -#: ../if_cscope.c:865 ../if_cscope.c:906 msgid "cs_create_connection: fdopen for fr_fp failed" -msgstr "cs_create_connection: fdopen de fr_fp fiaskis" +msgstr "cs_create_connection: fdopen de fr_fp malsukcesis" -#: ../if_cscope.c:890 msgid "E623: Could not spawn cscope process" msgstr "E623: Ne eblis naskigi procezon cscope" -#: ../if_cscope.c:932 msgid "E567: no cscope connections" msgstr "E567: neniu konekto al cscope" -#: ../if_cscope.c:1009 #, c-format msgid "E469: invalid cscopequickfix flag %c for %c" msgstr "E469: nevalida flago cscopequickfix %c de %c" -#: ../if_cscope.c:1058 #, c-format msgid "E259: no matches found for cscope query %s of %s" msgstr "E259: neniu kongruo trovita por serฤo per cscope %s de %s" -#: ../if_cscope.c:1142 msgid "cscope commands:\n" msgstr "komandoj de cscope:\n" -#: ../if_cscope.c:1150 #, c-format msgid "%-5s: %s%*s (Usage: %s)" msgstr "%-5s: %s%*s (Uzo: %s)" -#: ../if_cscope.c:1155 msgid "" "\n" +" a: Find assignments to this symbol\n" " c: Find functions calling this function\n" " d: Find functions called by this function\n" " e: Find this egrep pattern\n" @@ -3257,6 +2569,7 @@ msgid "" " t: Find this text string\n" msgstr "" "\n" +" a: Trovi valirizojn al tiu simbolo\n" " c: Trovi funkciojn, kiuj alvokas tiun funkcion\n" " d: Trovi funkciojn alvokataj de tiu funkcio\n" " e: Trovi tiun egrep-ลablonon\n" @@ -3266,31 +2579,32 @@ msgstr "" " s: Trovi tiun C-simbolon\n" " t: Trovi tiun ฤenon\n" -#: ../if_cscope.c:1226 +#, c-format +msgid "E625: cannot open cscope database: %s" +msgstr "E625: ne eblas malfermi datumbazon de cscope: %s" + +msgid "E626: cannot get cscope database information" +msgstr "E626: ne eblas akiri informojn pri la datumbazo de cscope" + msgid "E568: duplicate cscope database not added" msgstr "E568: ripetita datumbazo de cscope ne aldonita" -#: ../if_cscope.c:1335 #, c-format msgid "E261: cscope connection %s not found" msgstr "E261: konekto cscope %s netrovita" -#: ../if_cscope.c:1364 #, c-format msgid "cscope connection %s closed" msgstr "konekto cscope %s fermita" #. should not reach here -#: ../if_cscope.c:1486 msgid "E570: fatal error in cs_manage_matches" msgstr "E570: neriparebla eraro en cs_manage_matches" -#: ../if_cscope.c:1693 #, c-format msgid "Cscope tag: %s" msgstr "Etikedo de cscope: %s" -#: ../if_cscope.c:1711 msgid "" "\n" " # line" @@ -3298,87 +2612,306 @@ msgstr "" "\n" " nro linio" -#: ../if_cscope.c:1713 msgid "filename / context / line\n" msgstr "dosiernomo / kunteksto / linio\n" -#: ../if_cscope.c:1809 #, c-format msgid "E609: Cscope error: %s" msgstr "E609: Eraro de cscope: %s" -#: ../if_cscope.c:2053 msgid "All cscope databases reset" msgstr "Reลargo de ฤiuj datumbazoj de cscope" -#: ../if_cscope.c:2123 msgid "no cscope connections\n" msgstr "neniu konekto de cscope\n" -#: ../if_cscope.c:2126 msgid " # pid database name prepend path\n" msgstr " # pid nomo de datumbazo prefiksa vojo\n" -#: ../main.c:144 +msgid "Lua library cannot be loaded." +msgstr "La biblioteko Lua no ลargeblis." + +msgid "cannot save undo information" +msgstr "ne eblas konservi informojn de malfaro" + +msgid "" +"E815: Sorry, this command is disabled, the MzScheme libraries could not be " +"loaded." +msgstr "" +"E815: Bedaลญrinde, tiu komando estas malลaltita, ne eblis ลargi la " +"bibliotekojn." + +msgid "" +"E895: Sorry, this command is disabled, the MzScheme's racket/base module " +"could not be loaded." +msgstr "" +"E895: Bedaลญrinde, tiu komando estas malลaltita, ne eblis ลargi la modulon de " +"MzScheme racket/base." + +msgid "invalid expression" +msgstr "nevalida esprimo" + +msgid "expressions disabled at compile time" +msgstr "esprimoj malลaltitaj dum kompilado" + +msgid "hidden option" +msgstr "kaลita opcio" + +msgid "unknown option" +msgstr "nekonata opcio" + +msgid "window index is out of range" +msgstr "indekso de fenestro estas ekster limoj" + +msgid "couldn't open buffer" +msgstr "ne eblis malfermi bufron" + +msgid "cannot delete line" +msgstr "ne eblas forviลi linion" + +msgid "cannot replace line" +msgstr "ne eblas anstataลญigi linion" + +msgid "cannot insert line" +msgstr "ne eblas enmeti linion" + +msgid "string cannot contain newlines" +msgstr "ฤeno ne rajtas enhavi liniavancojn" + +msgid "error converting Scheme values to Vim" +msgstr "eraro dum konverto de Scheme-valoro al Vim" + +msgid "Vim error: ~a" +msgstr "Eraro de Vim: ~a" + +msgid "Vim error" +msgstr "Eraro de Vim" + +msgid "buffer is invalid" +msgstr "bufro estas nevalida" + +msgid "window is invalid" +msgstr "fenestro estas nevalida" + +msgid "linenr out of range" +msgstr "numero de linio ekster limoj" + +msgid "not allowed in the Vim sandbox" +msgstr "nepermesebla en sabloludejo de Vim" + +msgid "E836: This Vim cannot execute :python after using :py3" +msgstr "E836: Vim ne povas plenumi :python post uzo de :py3" + +msgid "" +"E263: Sorry, this command is disabled, the Python library could not be " +"loaded." +msgstr "" +"E263: Bedaลญrinde tiu komando estas malลaltita: la biblioteko de Pitono ne " +"ลargeblis." + +msgid "" +"E887: Sorry, this command is disabled, the Python's site module could not be " +"loaded." +msgstr "" +"E887` Bedaลญrinde tiu komando estas malลaltita: la biblioteko de Pitono ne " +"ลargeblis." + +msgid "E659: Cannot invoke Python recursively" +msgstr "E659: Ne eblas alvoki Pitonon rekursie" + +msgid "E837: This Vim cannot execute :py3 after using :python" +msgstr "E837: Vim ne povas plenumi :py3 post uzo de :python" + +msgid "E265: $_ must be an instance of String" +msgstr "E265: $_ devas esti apero de ฤeno" + +msgid "" +"E266: Sorry, this command is disabled, the Ruby library could not be loaded." +msgstr "" +"E266: Bedaลญrinde tiu komando estas malลaltita, la biblioteko Ruby ne " +"ลargeblis." + +msgid "E267: unexpected return" +msgstr "E267: \"return\" neatendita" + +msgid "E268: unexpected next" +msgstr "E268: \"next\" neatendita" + +msgid "E269: unexpected break" +msgstr "E269: \"break\" neatendita" + +msgid "E270: unexpected redo" +msgstr "E270: \"redo\" neatendita" + +msgid "E271: retry outside of rescue clause" +msgstr "E271: \"retry\" ekster klaลญzo \"rescue\"" + +msgid "E272: unhandled exception" +msgstr "E272: netraktita escepto" + +#, c-format +msgid "E273: unknown longjmp status %d" +msgstr "E273: nekonata stato de longjmp: %d" + +msgid "invalid buffer number" +msgstr "nevalida numero de bufro" + +msgid "not implemented yet" +msgstr "ankoraลญ ne realigita" + +#. ??? +msgid "cannot set line(s)" +msgstr "ne eblas meti la linio(j)n" + +msgid "invalid mark name" +msgstr "nevalida nomo de marko" + +msgid "mark not set" +msgstr "marko ne estas metita" + +#, c-format +msgid "row %d column %d" +msgstr "linio %d kolumno %d" + +msgid "cannot insert/append line" +msgstr "ne eblas enmeti/postaldoni linion" + +msgid "line number out of range" +msgstr "numero de linio ekster limoj" + +msgid "unknown flag: " +msgstr "nekonata flago: " + +# DP: ฤu traduki vimOption +msgid "unknown vimOption" +msgstr "nekonata vimOption" + +msgid "keyboard interrupt" +msgstr "klavara interrompo" + +msgid "vim error" +msgstr "eraro de Vim" + +msgid "cannot create buffer/window command: object is being deleted" +msgstr "ne eblas krei komandon de bufro/fenestro: objekto estas forviลiฤanta" + +msgid "" +"cannot register callback command: buffer/window is already being deleted" +msgstr "" +"ne eblas registri postalvokan komandon: bufro/fenestro estas jam forviลiฤanta" + +#. This should never happen. Famous last word? +msgid "" +"E280: TCL FATAL ERROR: reflist corrupt!? Please report this to vim-dev@vim." +"org" +msgstr "" +"E280: NERIPAREBLA TCL-ERARO: reflist difekta!? Bv. retpoลti al vim-dev@vim." +"org" + +msgid "cannot register callback command: buffer/window reference not found" +msgstr "" +"ne eblas registri postalvokan komandon: referenco de bufro/fenestro ne " +"troveblas" + +msgid "" +"E571: Sorry, this command is disabled: the Tcl library could not be loaded." +msgstr "" +"E571: Bedaลญrinde tiu komando estas malลaltita: la biblioteko Tcl ne " +"ลargeblis." + +#, c-format +msgid "E572: exit code %d" +msgstr "E572: elira kodo %d" + +msgid "cannot get line" +msgstr "ne eblas akiri linion" + +msgid "Unable to register a command server name" +msgstr "Ne eblas registri nomon de komanda servilo" + +msgid "E248: Failed to send command to the destination program" +msgstr "E248: Sendo de komando al cela programo malsukcesis" + +#, c-format +msgid "E573: Invalid server id used: %s" +msgstr "E573: Nevalida identigilo de servilo uzita: %s" + +msgid "E251: VIM instance registry property is badly formed. Deleted!" +msgstr "" +"E251: Ecoj de registro de apero de VIM estas nevalide formata. Forviลita!" + +#, c-format +msgid "E938: Duplicate key in JSON: \"%s\"" +msgstr "E938: Ripetita ลlosilo en JSON: \"%s\"" + +#, c-format +msgid "E696: Missing comma in List: %s" +msgstr "E696: Mankas komo en Listo: %s" + +#, c-format +msgid "E697: Missing end of List ']': %s" +msgstr "E697: Mankas fino de Listo ']': %s" + msgid "Unknown option argument" msgstr "Nekonata argumento de opcio" -#: ../main.c:146 msgid "Too many edit arguments" msgstr "Tro da argumentoj de redakto" -#: ../main.c:148 msgid "Argument missing after" msgstr "Argumento mankas post" -#: ../main.c:150 msgid "Garbage after option argument" msgstr "Forฤตetindaฤตo post argumento de opcio" -#: ../main.c:152 msgid "Too many \"+command\", \"-c command\" or \"--cmd command\" arguments" msgstr "Tro da argumentoj \"+komando\", \"-c komando\" aลญ \"--cmd komando\"" -#: ../main.c:154 msgid "Invalid argument for" msgstr "Nevalida argumento por" -#: ../main.c:294 #, c-format msgid "%d files to edit\n" msgstr "%d redaktendaj dosieroj\n" -#: ../main.c:1342 +msgid "netbeans is not supported with this GUI\n" +msgstr "netbeans ne estas subtenata kun tiu grafika interfaco\n" + +msgid "'-nb' cannot be used: not enabled at compile time\n" +msgstr "'-nb' ne uzeblas: malลaltita dum kompilado\n" + +msgid "This Vim was not compiled with the diff feature." +msgstr "Tiu Vim ne estis kompilita kun la kompara eblo." + msgid "Attempt to open script file again: \"" msgstr "Provas malfermi skriptan dosieron denove: \"" -#: ../main.c:1350 msgid "Cannot open for reading: \"" msgstr "Ne eblas malfermi en lega reฤimo: \"" -#: ../main.c:1393 msgid "Cannot open for script output: \"" msgstr "Ne eblas malfermi por eligo de skripto: \"" -#: ../main.c:1622 +msgid "Vim: Error: Failure to start gvim from NetBeans\n" +msgstr "Vim: Eraro: malsukcesis lanฤi gvim el NetBeans\n" + +msgid "Vim: Error: This version of Vim does not run in a Cygwin terminal\n" +msgstr "Vim: Eraro: Tiu versio de Vim ne ruliฤas en terminalo Cygwin\n" + msgid "Vim: Warning: Output is not to a terminal\n" msgstr "Vim: Averto: Eligo ne estas al terminalo\n" -#: ../main.c:1624 msgid "Vim: Warning: Input is not from a terminal\n" msgstr "Vim: Averto: Enigo ne estas el terminalo\n" #. just in case.. -#: ../main.c:1891 msgid "pre-vimrc command line" msgstr "komanda linio pre-vimrc" -#: ../main.c:1964 #, c-format msgid "E282: Cannot read from \"%s\"" msgstr "E282: Ne eblas legi el \"%s\"" -#: ../main.c:2149 msgid "" "\n" "More info with: \"vim -h\"\n" @@ -3387,23 +2920,18 @@ msgstr "" "Pliaj informoj per: \"vim -h\"\n" # DP: tajpu "vim --help" por testi tiujn mesaฤojn -#: ../main.c:2178 msgid "[file ..] edit specified file(s)" msgstr "[dosiero...] redakti specifita(j)n dosiero(j)n" -#: ../main.c:2179 msgid "- read text from stdin" msgstr "- legi tekston el stdin" -#: ../main.c:2180 msgid "-t tag edit file where tag is defined" msgstr "-t etikedo redakti dosieron kie etikedo estas difinata" -#: ../main.c:2181 msgid "-q [errorfile] edit file with first error" msgstr "-q [erardosiero] redakti dosieron kun unua eraro" -#: ../main.c:2187 msgid "" "\n" "\n" @@ -3413,11 +2941,9 @@ msgstr "" "\n" " uzo:" -#: ../main.c:2189 msgid " vim [arguments] " msgstr " vim [argumentoj] " -#: ../main.c:2193 msgid "" "\n" " or:" @@ -3425,7 +2951,13 @@ msgstr "" "\n" " aลญ:" -#: ../main.c:2196 +msgid "" +"\n" +"Where case is ignored prepend / to make flag upper case" +msgstr "" +"\n" +"Kie uskleco estas ignorita antaลญaldonu / por igi flagon majuskla" + msgid "" "\n" "\n" @@ -3435,197 +2967,336 @@ msgstr "" "\n" "Argumentoj:\n" -#: ../main.c:2197 msgid "--\t\t\tOnly file names after this" msgstr "--\t\t\tNur dosiernomoj post tio" -#: ../main.c:2199 msgid "--literal\t\tDon't expand wildcards" msgstr "--literal\t\tNe malvolvi ฤตokerojn" -#: ../main.c:2201 +msgid "-register\t\tRegister this gvim for OLE" +msgstr "-register\t\tRegistri tiun gvim al OLE" + +msgid "-unregister\t\tUnregister gvim for OLE" +msgstr "-unregister\t\tMalregistri gvim de OLE" + +msgid "-g\t\t\tRun using GUI (like \"gvim\")" +msgstr "-g\t\t\tRuli per grafika interfaco (kiel \"gvim\")" + +msgid "-f or --nofork\tForeground: Don't fork when starting GUI" +msgstr "-f aลญ --nofork\tMalfono: ne forki kiam lanฤas grafikan interfacon" + msgid "-v\t\t\tVi mode (like \"vi\")" msgstr "-v\t\t\tReฤimo Vi (kiel \"vi\")" -#: ../main.c:2202 msgid "-e\t\t\tEx mode (like \"ex\")" msgstr "-e\t\t\tReฤimo Ex (kiel \"ex\")" -#: ../main.c:2203 msgid "-E\t\t\tImproved Ex mode" msgstr "-E\t\t\tPlibonigita Ex-reฤimo" -#: ../main.c:2204 msgid "-s\t\t\tSilent (batch) mode (only for \"ex\")" msgstr "-s\t\t\tSilenta (stapla) reฤimo (nur por \"ex\")" -#: ../main.c:2205 msgid "-d\t\t\tDiff mode (like \"vimdiff\")" msgstr "-d\t\t\tKompara reฤimo (kiel \"vimdiff\")" -#: ../main.c:2206 msgid "-y\t\t\tEasy mode (like \"evim\", modeless)" msgstr "-y\t\t\tFacila reฤimo (kiel \"evim\", senreฤima)" -#: ../main.c:2207 msgid "-R\t\t\tReadonly mode (like \"view\")" msgstr "-R\t\t\tNurlegebla reฤimo (kiel \"view\")" -#: ../main.c:2208 msgid "-Z\t\t\tRestricted mode (like \"rvim\")" msgstr "-Z\t\t\tLimigita reฤimo (kiel \"rvim\")" -#: ../main.c:2209 msgid "-m\t\t\tModifications (writing files) not allowed" msgstr "-m\t\t\tลanฤoj (skribo al dosieroj) nepermeseblaj" -#: ../main.c:2210 msgid "-M\t\t\tModifications in text not allowed" msgstr "-M\t\t\tลanฤoj al teksto nepermeseblaj" -#: ../main.c:2211 msgid "-b\t\t\tBinary mode" msgstr "-b\t\t\tDuuma reฤimo" -#: ../main.c:2212 msgid "-l\t\t\tLisp mode" msgstr "-l\t\t\tReฤimo Lisp" -#: ../main.c:2213 msgid "-C\t\t\tCompatible with Vi: 'compatible'" msgstr "-C\t\t\tKongrua kun Vi: 'compatible'" -#: ../main.c:2214 msgid "-N\t\t\tNot fully Vi compatible: 'nocompatible'" msgstr "-N\t\t\tNe tute kongrua kun Vi: 'nocompatible'" -#: ../main.c:2215 msgid "-V[N][fname]\t\tBe verbose [level N] [log messages to fname]" msgstr "" "-V[N][dosiernomo]\tEsti babilema [nivelo N] [konservi mesaฤojn al dosiernomo]" -#: ../main.c:2216 msgid "-D\t\t\tDebugging mode" msgstr "-D\t\t\tSencimiga reฤimo" -#: ../main.c:2217 msgid "-n\t\t\tNo swap file, use memory only" msgstr "-n\t\t\tNeniu permutodosiero .swp, uzas nur memoron" -#: ../main.c:2218 msgid "-r\t\t\tList swap files and exit" msgstr "-r\t\t\tListigi permutodosierojn .swp kaj eliri" -#: ../main.c:2219 msgid "-r (with file name)\tRecover crashed session" msgstr "-r (kun dosiernomo)\tRestaลญri kolapsintan seancon" -#: ../main.c:2220 msgid "-L\t\t\tSame as -r" msgstr "-L\t\t\tKiel -r" -#: ../main.c:2221 +msgid "-f\t\t\tDon't use newcli to open window" +msgstr "-f\t\t\tNe uzi newcli por malfermi fenestrojn" + +msgid "-dev <device>\t\tUse <device> for I/O" +msgstr "-dev <aparatdosiero>\t\tUzi <aparatdosiero>-n por eneligo" + msgid "-A\t\t\tstart in Arabic mode" msgstr "-A\t\t\tKomenci en araba reฤimo" -#: ../main.c:2222 msgid "-H\t\t\tStart in Hebrew mode" msgstr "-H\t\t\tKomenci en hebrea reฤimo" -#: ../main.c:2223 msgid "-F\t\t\tStart in Farsi mode" msgstr "-F\t\t\tKomenci en persa reฤimo" -#: ../main.c:2224 msgid "-T <terminal>\tSet terminal type to <terminal>" msgstr "-T <terminalo>\tAgordi terminalon al <terminalo>" -#: ../main.c:2225 +msgid "--not-a-term\t\tSkip warning for input/output not being a terminal" +msgstr "" +"--not-a-term\t\tPreterpasi averton por enigo/eligo, kiu ne estas terminalo" + +msgid "--ttyfail\t\tExit if input or output is not a terminal" +msgstr "" +"--ttyfail\t\tEliri se le eniro aลญ eliro ne estas terminalo" + msgid "-u <vimrc>\t\tUse <vimrc> instead of any .vimrc" msgstr "-u <vimrc>\t\tUzi <vimrc> anstataลญ iun ajn .vimrc" -#: ../main.c:2226 +msgid "-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc" +msgstr "-U <gvimrc>\t\tUzi <gvimrc> anstataลญ iun ajn .gvimrc" + msgid "--noplugin\t\tDon't load plugin scripts" msgstr "--noplugin\t\tNe ลargi kromaฤตajn skriptojn" -#: ../main.c:2227 msgid "-p[N]\t\tOpen N tab pages (default: one for each file)" msgstr "-p[N]\t\tMalfermi N langetojn (defaลญlto: po unu por ฤiu dosiero)" -#: ../main.c:2228 msgid "-o[N]\t\tOpen N windows (default: one for each file)" msgstr "-o[N]\t\tMalfermi N fenestrojn (defaลญlto: po unu por ฤiu dosiero)" -#: ../main.c:2229 msgid "-O[N]\t\tLike -o but split vertically" msgstr "-O[N]\t\tKiel -o sed dividi vertikale" -#: ../main.c:2230 msgid "+\t\t\tStart at end of file" msgstr "+\t\t\tKomenci ฤe la fino de la dosiero" -#: ../main.c:2231 msgid "+<lnum>\t\tStart at line <lnum>" msgstr "+<numL>\t\tKomenci ฤe linio <numL>" -#: ../main.c:2232 msgid "--cmd <command>\tExecute <command> before loading any vimrc file" msgstr "" "--cmd <komando>\tPlenumi <komando>-n antaลญ ol ลargi iun ajn dosieron vimrc" -#: ../main.c:2233 msgid "-c <command>\t\tExecute <command> after loading the first file" msgstr "-c <komando>\t\tPlenumi <komando>-n post kiam la unua dosiero ลargiฤis" -#: ../main.c:2235 msgid "-S <session>\t\tSource file <session> after loading the first file" msgstr "" "-S <seanco>\t\tRuli dosieron <seanco>-n post kiam la unua dosiero ลargiฤis" -#: ../main.c:2236 msgid "-s <scriptin>\tRead Normal mode commands from file <scriptin>" msgstr "-s <skripto>\t\tLegi komandojn en Normala reฤimo el dosiero <skripto>" -#: ../main.c:2237 msgid "-w <scriptout>\tAppend all typed commands to file <scriptout>" msgstr "" "-w <eligaskripto>\tPostaldoni ฤiujn tajpitajn komandojn al dosiero " "<eligaskripto>" -#: ../main.c:2238 msgid "-W <scriptout>\tWrite all typed commands to file <scriptout>" msgstr "" "-W <eligaskripto>\tSkribi ฤiujn tajpitajn komandojn al dosiero <eligaskripto>" -#: ../main.c:2240 +msgid "-x\t\t\tEdit encrypted files" +msgstr "-x\t\t\tRedakti ฤifradan dosieron" + +msgid "-display <display>\tConnect vim to this particular X-server" +msgstr "-display <ekrano>\tKonekti Vim al tiu X-servilo" + +msgid "-X\t\t\tDo not connect to X server" +msgstr "-X\t\t\tNe konekti al X-servilo" + +msgid "--remote <files>\tEdit <files> in a Vim server if possible" +msgstr "--remote <dosieroj>\tRedakti <dosieroj>-n en Vim-servilo se eblas" + +msgid "--remote-silent <files> Same, don't complain if there is no server" +msgstr "--remote-silent <dosieroj> Same, sed ne plendi se ne estas servilo" + +msgid "" +"--remote-wait <files> As --remote but wait for files to have been edited" +msgstr "" +"--remote-wait <dosieroj> Kiel --remote sed atendi ฤis dosieroj estas " +"redaktitaj" + +msgid "" +"--remote-wait-silent <files> Same, don't complain if there is no server" +msgstr "" +"--remote-wait-silent <dosieroj> Same, sed ne plendi se ne estas servilo" + +msgid "" +"--remote-tab[-wait][-silent] <files> As --remote but use tab page per file" +msgstr "" +"--remote-tab[-wait][-silent] <dosieroj> Kiel --remote sed uzi langeton por " +"ฤiu dosiero" + +msgid "--remote-send <keys>\tSend <keys> to a Vim server and exit" +msgstr "--remote-send <klavoj> Sendi <klavoj>-n al Vim-servilo kaj eliri" + +msgid "--remote-expr <expr>\tEvaluate <expr> in a Vim server and print result" +msgstr "--remote-expr <espr>\tKomputi <espr> en Vim-servilo kaj afiลi rezulton" + +msgid "--serverlist\t\tList available Vim server names and exit" +msgstr "--serverlist\t\tListigi haveblajn nomojn de Vim-serviloj kaj eliri" + +msgid "--servername <name>\tSend to/become the Vim server <name>" +msgstr "--servername <nomo>\tSendu al/iฤi la Vim-servilo <nomo>" + msgid "--startuptime <file>\tWrite startup timing messages to <file>" msgstr "" "--startuptime <dosiero> Skribi mesaฤojn de komenca tempomezurado al " "<dosiero>" -#: ../main.c:2242 msgid "-i <viminfo>\t\tUse <viminfo> instead of .viminfo" msgstr "-i <viminfo>\t\tUzi <viminfo> anstataลญ .viminfo" -#: ../main.c:2243 msgid "-h or --help\tPrint Help (this message) and exit" msgstr "-h aลญ --help\tAfiลi Helpon (tiun mesaฤon) kaj eliri" -#: ../main.c:2244 msgid "--version\t\tPrint version information and exit" msgstr "--version\t\tAfiลi informon de versio kaj eliri" -#: ../mark.c:676 +msgid "" +"\n" +"Arguments recognised by gvim (Motif version):\n" +msgstr "" +"\n" +"Argumentoj agnoskitaj de gvim (versio Motif):\n" + +msgid "" +"\n" +"Arguments recognised by gvim (neXtaw version):\n" +msgstr "" +"\n" +"Argumentoj agnoskitaj de gvim (versio neXtaw):\n" + +msgid "" +"\n" +"Arguments recognised by gvim (Athena version):\n" +msgstr "" +"\n" +"Argumentoj agnoskitaj de gvim (versio Athena):\n" + +msgid "-display <display>\tRun vim on <display>" +msgstr "-display <ekrano>\tLanฤi vim sur <ekrano>" + +msgid "-iconic\t\tStart vim iconified" +msgstr "-iconic\t\tLanฤi vim piktograme" + +msgid "-background <color>\tUse <color> for the background (also: -bg)" +msgstr "-background <koloro>\tUzi <koloro>-n por la fona koloro (ankaลญ: -bg)" + +msgid "-foreground <color>\tUse <color> for normal text (also: -fg)" +msgstr "" +"-foreground <koloro>\tUzi <koloro>-n por la malfona koloro (ankaลญ: -fg)" + +msgid "-font <font>\t\tUse <font> for normal text (also: -fn)" +msgstr "-font <tiparo>\tUzi <tiparo>-n por normala teksto (ankaลญ: -fn)" + +msgid "-boldfont <font>\tUse <font> for bold text" +msgstr "-boldfont <tiparo>\tUzi <tiparo>-n por grasa teksto" + +msgid "-italicfont <font>\tUse <font> for italic text" +msgstr "-italicfont <tiparo>\tUzi <tiparo>-n por kursiva teksto" + +msgid "-geometry <geom>\tUse <geom> for initial geometry (also: -geom)" +msgstr "-geometry <geom>\tUzi <geom> kiel komenca geometrio (ankaลญ: -geom)" + +msgid "-borderwidth <width>\tUse a border width of <width> (also: -bw)" +msgstr "-borderwidth <larฤo>\tUzi <larฤo>-n kiel larฤo de bordero (ankaลญ: -bw)" + +msgid "-scrollbarwidth <width> Use a scrollbar width of <width> (also: -sw)" +msgstr "" +"-scrollbarwidth <larฤo> Uzi <larฤo>-n kiel larฤo de rulumskalo (ankaลญ: -sw)" + +msgid "-menuheight <height>\tUse a menu bar height of <height> (also: -mh)" +msgstr "" +"-menuheight <alto>\tUzi <alto>-n kiel alto de menuzona alto (ankaลญ: -mh)" + +msgid "-reverse\t\tUse reverse video (also: -rv)" +msgstr "-reverse\t\tUzi inversan videon (ankaลญ: -rv)" + +msgid "+reverse\t\tDon't use reverse video (also: +rv)" +msgstr "+reverse\t\tNe uzi inversan videon (ankaลญ: +rv)" + +msgid "-xrm <resource>\tSet the specified resource" +msgstr "-xrm <rimedo>\tAgordi la specifitan <rimedo>-n" + +msgid "" +"\n" +"Arguments recognised by gvim (GTK+ version):\n" +msgstr "" +"\n" +"Argumentoj agnoskitaj de gvim (versio GTK+):\n" + +msgid "-display <display>\tRun vim on <display> (also: --display)" +msgstr "-display <ekrano>\tLanฤi Vim sur tiu <ekrano> (ankaลญ: --display)" + +msgid "--role <role>\tSet a unique role to identify the main window" +msgstr "--role <rolo>\tDoni unikan rolon por identigi la ฤefan fenestron" + +msgid "--socketid <xid>\tOpen Vim inside another GTK widget" +msgstr "--socketid <xid>\tMalfermi Vim en alia GTK fenestraฤตo" + +msgid "--echo-wid\t\tMake gvim echo the Window ID on stdout" +msgstr "--echo-wid\t\tIgas gvim afiลi la identigilon de vindozo sur stdout" + +msgid "-P <parent title>\tOpen Vim inside parent application" +msgstr "-P <gepatra titolo>\tMalfermi Vim en gepatra aplikaฤตo" + +msgid "--windowid <HWND>\tOpen Vim inside another win32 widget" +msgstr "--windowid <HWND>\tMalfermi Vim en alia win32 fenestraฤตo" + +msgid "No display" +msgstr "Neniu ekrano" + +#. Failed to send, abort. +msgid ": Send failed.\n" +msgstr ": Sendo malsukcesis.\n" + +#. Let vim start normally. +msgid ": Send failed. Trying to execute locally\n" +msgstr ": Sendo malsukcesis. Provo de loka plenumo\n" + +#, c-format +msgid "%d of %d edited" +msgstr "%d de %d redaktita(j)" + +msgid "No display: Send expression failed.\n" +msgstr "Neniu ekrano: Sendado de esprimo malsukcesis.\n" + +msgid ": Send expression failed.\n" +msgstr ": Sendado de esprimo malsukcesis.\n" + msgid "No marks set" msgstr "Neniu marko" -#: ../mark.c:678 #, c-format msgid "E283: No marks matching \"%s\"" msgstr "E283: Neniu marko kongruas kun \"%s\"" #. Highlight title -#: ../mark.c:687 msgid "" "\n" "mark line col file/text" @@ -3634,7 +3305,6 @@ msgstr "" "mark linio kol dosiero/teksto" #. Highlight title -#: ../mark.c:789 msgid "" "\n" " jump line col file/text" @@ -3643,7 +3313,6 @@ msgstr "" " salt linio kol dosiero/teksto" #. Highlight title -#: ../mark.c:831 msgid "" "\n" "change line col text" @@ -3651,7 +3320,6 @@ msgstr "" "\n" "ลanฤo linio kol teksto" -#: ../mark.c:1238 msgid "" "\n" "# File marks:\n" @@ -3660,7 +3328,6 @@ msgstr "" "# Markoj de dosiero:\n" #. Write the jumplist with -' -#: ../mark.c:1271 msgid "" "\n" "# Jumplist (newest first):\n" @@ -3668,7 +3335,6 @@ msgstr "" "\n" "# Saltlisto (plej novaj unue):\n" -#: ../mark.c:1352 msgid "" "\n" "# History of marks within files (newest to oldest):\n" @@ -3676,85 +3342,90 @@ msgstr "" "\n" "# Historio de markoj en dosieroj (de plej nova al plej malnova):\n" -#: ../mark.c:1431 msgid "Missing '>'" msgstr "Mankas '>'" -#: ../memfile.c:426 +msgid "E543: Not a valid codepage" +msgstr "E543: Nevalida kodpaฤo" + +msgid "E284: Cannot set IC values" +msgstr "E284: Ne eblas agordi valorojn de IC" + +msgid "E285: Failed to create input context" +msgstr "E285: Kreado de eniga kunteksto malsukcesis" + +msgid "E286: Failed to open input method" +msgstr "E286: Malfermo de eniga metodo malsukcesis" + +msgid "E287: Warning: Could not set destroy callback to IM" +msgstr "E287: Averto: Ne eblis agordi detruan reagfunkcion al IM" + +msgid "E288: input method doesn't support any style" +msgstr "E288: eniga metodo subtenas neniun stilon" + +# DP: mi ne scias, kio estas "preedit" +msgid "E289: input method doesn't support my preedit type" +msgstr "E289: eniga metodo ne subtenas mian antaลญredaktan tipon" + msgid "E293: block was not locked" msgstr "E293: bloko ne estis ลlosita" -#: ../memfile.c:799 msgid "E294: Seek error in swap file read" msgstr "E294: Eraro de enpoziciigo dum lego de permutodosiero .swp" -#: ../memfile.c:803 msgid "E295: Read error in swap file" msgstr "E295: Eraro de lego en permutodosiero .swp" -#: ../memfile.c:849 msgid "E296: Seek error in swap file write" msgstr "E296: Eraro de enpoziciigo dum skribo de permutodosiero .swp" -#: ../memfile.c:865 msgid "E297: Write error in swap file" msgstr "E297: Skriberaro en permutodosiero .swp" -#: ../memfile.c:1036 msgid "E300: Swap file already exists (symlink attack?)" msgstr "E300: Permutodosiero .swp jam ekzistas (ฤu atako per simbola ligilo?)" -#: ../memline.c:318 msgid "E298: Didn't get block nr 0?" msgstr "E298: ฤu ne akiris blokon n-ro 0?" -#: ../memline.c:361 msgid "E298: Didn't get block nr 1?" msgstr "E298: ฤu ne akiris blokon n-ro 1?" -#: ../memline.c:377 msgid "E298: Didn't get block nr 2?" msgstr "E298: ฤu ne akiris blokon n-ro 2?" +msgid "E843: Error while updating swap file crypt" +msgstr "E843: Eraro dum ฤisdatigo de ฤifrada permutodosiero .swp" + #. could not (re)open the swap file, what can we do???? -#: ../memline.c:465 msgid "E301: Oops, lost the swap file!!!" msgstr "E301: Ve, perdis la permutodosieron .swp!!!" -#: ../memline.c:477 msgid "E302: Could not rename swap file" msgstr "E302: Ne eblis renomi la permutodosieron .swp" -#: ../memline.c:554 #, c-format msgid "E303: Unable to open swap file for \"%s\", recovery impossible" msgstr "" "E303: Ne eblas malfermi permutodosieron .swp de \"%s\", restaลญro neeblas" -#: ../memline.c:666 msgid "E304: ml_upd_block0(): Didn't get block 0??" msgstr "E304: ml_upd_block0(): Ne akiris blokon 0??" -#. no swap files found -#: ../memline.c:830 #, c-format msgid "E305: No swap file found for %s" msgstr "E305: Neniu permutodosiero .swp trovita por %s" -#: ../memline.c:839 msgid "Enter number of swap file to use (0 to quit): " msgstr "Entajpu la uzendan numeron de permutodosiero .swp (0 por eliri): " -#: ../memline.c:879 #, c-format msgid "E306: Cannot open %s" msgstr "E306: Ne eblas malfermi %s" -#: ../memline.c:897 msgid "Unable to read block 0 from " msgstr "Ne eblas legi blokon 0 de " -#: ../memline.c:900 msgid "" "\n" "Maybe no changes were made or Vim did not update the swap file." @@ -3762,28 +3433,22 @@ msgstr "" "\n" "Eble neniu ลanฤo estis farita aลญ Vim ne ฤisdatigis la permutodosieron .swp." -#: ../memline.c:909 msgid " cannot be used with this version of Vim.\n" msgstr " ne uzeblas per tiu versio de vim.\n" -#: ../memline.c:911 msgid "Use Vim version 3.0.\n" msgstr "Uzu version 3.0 de Vim\n" -#: ../memline.c:916 #, c-format msgid "E307: %s does not look like a Vim swap file" msgstr "E307: %s ne aspektas kiel permutodosiero .swp de Vim" -#: ../memline.c:922 msgid " cannot be used on this computer.\n" msgstr " ne uzeblas per tiu komputilo.\n" -#: ../memline.c:924 msgid "The file was created on " msgstr "La dosiero estas kreita je " -#: ../memline.c:928 msgid "" ",\n" "or the file has been damaged." @@ -3791,85 +3456,104 @@ msgstr "" ",\n" "aลญ la dosiero estas difekta." -#: ../memline.c:945 +#, c-format +msgid "" +"E833: %s is encrypted and this version of Vim does not support encryption" +msgstr "E833: %s estas ฤifrata kaj tiu versio de Vim ne subtenas ฤifradon" + msgid " has been damaged (page size is smaller than minimum value).\n" msgstr " difektiฤis (paฤa grando pli malgranda ol minimuma valoro).\n" -#: ../memline.c:974 #, c-format msgid "Using swap file \"%s\"" msgstr "Uzado de permutodosiero .swp \"%s\"" -#: ../memline.c:980 #, c-format msgid "Original file \"%s\"" msgstr "Originala dosiero \"%s\"" -#: ../memline.c:995 msgid "E308: Warning: Original file may have been changed" msgstr "E308: Averto: Originala dosiero eble ลanฤiฤis" -#: ../memline.c:1061 +#, c-format +msgid "Swap file is encrypted: \"%s\"" +msgstr "Perumutodosiero .swp estas ฤifrata: \"%s\"" + +msgid "" +"\n" +"If you entered a new crypt key but did not write the text file," +msgstr "" +"\n" +"Se vi tajpis novan ลlosilon de ฤifrado sed ne skribis la tekstan dosieron," + +msgid "" +"\n" +"enter the new crypt key." +msgstr "" +"\n" +"tajpu la novan ลlosilon de ฤifrado." + +msgid "" +"\n" +"If you wrote the text file after changing the crypt key press enter" +msgstr "" +"\n" +"Se vi skribis la tekstan dosieron post ลanฤo de la ลlosilo de ฤifrado, premu " +"enenklavon" + +msgid "" +"\n" +"to use the same key for text file and swap file" +msgstr "" +"\n" +"por uzi la saman ลlosilon por la teksta dosiero kaj permuto dosiero .swp" + #, c-format msgid "E309: Unable to read block 1 from %s" msgstr "E309: Ne eblas legi blokon 1 de %s" -#: ../memline.c:1065 msgid "???MANY LINES MISSING" msgstr "???MULTAJ LINIOJ MANKAS" -#: ../memline.c:1076 msgid "???LINE COUNT WRONG" msgstr "???NOMBRO DE LINIOJ NE ฤUSTAS" -#: ../memline.c:1082 msgid "???EMPTY BLOCK" msgstr "???MALPLENA BLOKO" -#: ../memline.c:1103 msgid "???LINES MISSING" msgstr "???LINIOJ MANKANTAJ" -#: ../memline.c:1128 #, c-format msgid "E310: Block 1 ID wrong (%s not a .swp file?)" msgstr "" "E310: Nevalida identigilo de bloko 1 (ฤu %s ne estas permutodosiero .swp?)" -#: ../memline.c:1133 msgid "???BLOCK MISSING" msgstr "???MANKAS BLOKO" -#: ../memline.c:1147 msgid "??? from here until ???END lines may be messed up" msgstr "??? ekde tie ฤis ???FINO linioj estas eble difektaj" -#: ../memline.c:1164 msgid "??? from here until ???END lines may have been inserted/deleted" msgstr "??? ekde tie ฤis ???FINO linioj estas eble enmetitaj/forviลitaj" -#: ../memline.c:1181 msgid "???END" msgstr "???FINO" -#: ../memline.c:1238 msgid "E311: Recovery Interrupted" msgstr "E311: Restaลญro interrompita" -#: ../memline.c:1243 msgid "" "E312: Errors detected while recovering; look for lines starting with ???" msgstr "E312: Eraroj dum restaลญro; rigardu liniojn komencantajn per ???" -#: ../memline.c:1245 msgid "See \":help E312\" for more information." msgstr "Vidu \":help E312\" por pliaj informoj." -#: ../memline.c:1249 msgid "Recovery completed. You should check if everything is OK." msgstr "Restaลญro finiฤis. Indus kontroli ฤu ฤio estas en ordo." -#: ../memline.c:1251 msgid "" "\n" "(You might want to write out this file under another name\n" @@ -3877,16 +3561,13 @@ msgstr "" "\n" "(Indas konservi tiun dosieron per alia nomo\n" -#: ../memline.c:1252 msgid "and run diff with the original file to check for changes)" msgstr "kaj lanฤi diff kun la originala dosiero por kontroli la ลanฤojn)" -#: ../memline.c:1254 msgid "Recovery completed. Buffer contents equals file contents." msgstr "" "Restaลญro finiฤis. La enhavo de la bufro samas kun la enhavo de la dosiero." -#: ../memline.c:1255 msgid "" "\n" "You may want to delete the .swp file now.\n" @@ -3896,52 +3577,44 @@ msgstr "" "La dosiero .swp nun forviลindas.\n" "\n" +msgid "Using crypt key from swap file for the text file.\n" +msgstr "" +"Uzas ลlosilon de ฤifrado el permuto dosiero .swp por la teksta dosiero.\n" + #. use msg() to start the scrolling properly -#: ../memline.c:1327 msgid "Swap files found:" msgstr "Permutodosiero .swp trovita:" -#: ../memline.c:1446 msgid " In current directory:\n" msgstr " En la aktuala dosierujo:\n" -#: ../memline.c:1448 msgid " Using specified name:\n" msgstr " Uzado de specifita nomo:\n" -#: ../memline.c:1450 msgid " In directory " msgstr " En dosierujo " -#: ../memline.c:1465 msgid " -- none --\n" msgstr " -- nenio --\n" -#: ../memline.c:1527 msgid " owned by: " msgstr " posedata de: " -#: ../memline.c:1529 msgid " dated: " msgstr " dato: " -#: ../memline.c:1532 ../memline.c:3231 msgid " dated: " msgstr " dato: " -#: ../memline.c:1548 msgid " [from Vim version 3.0]" msgstr " [de Vim versio 3.0]" -#: ../memline.c:1550 msgid " [does not look like a Vim swap file]" msgstr " [ne aspektas kiel permutodosiero .swp de Vim]" -#: ../memline.c:1552 msgid " file name: " msgstr " dosiernomo: " -#: ../memline.c:1558 msgid "" "\n" " modified: " @@ -3949,15 +3622,12 @@ msgstr "" "\n" " modifita: " -#: ../memline.c:1559 msgid "YES" msgstr "JES" -#: ../memline.c:1559 msgid "no" msgstr "ne" -#: ../memline.c:1562 msgid "" "\n" " user name: " @@ -3965,11 +3635,9 @@ msgstr "" "\n" " uzantonomo: " -#: ../memline.c:1568 msgid " host name: " msgstr " komputila nomo: " -#: ../memline.c:1570 msgid "" "\n" " host name: " @@ -3977,7 +3645,6 @@ msgstr "" "\n" " komputila nomo: " -#: ../memline.c:1575 msgid "" "\n" " process ID: " @@ -3985,11 +3652,16 @@ msgstr "" "\n" " proceza ID: " -#: ../memline.c:1579 msgid " (still running)" msgstr " (ankoraลญ ruliฤas)" -#: ../memline.c:1586 +msgid "" +"\n" +" [not usable with this version of Vim]" +msgstr "" +"\n" +" [ne uzebla per tiu versio de Vim]" + msgid "" "\n" " [not usable on this computer]" @@ -3997,97 +3669,75 @@ msgstr "" "\n" " [neuzebla per tiu komputilo]" -#: ../memline.c:1590 msgid " [cannot be read]" msgstr " [nelegebla]" -#: ../memline.c:1593 msgid " [cannot be opened]" msgstr " [nemalfermebla]" -#: ../memline.c:1698 msgid "E313: Cannot preserve, there is no swap file" msgstr "E313: Ne eblas konservi, ne estas permutodosiero .swp" -#: ../memline.c:1747 msgid "File preserved" msgstr "Dosiero konservita" -#: ../memline.c:1749 msgid "E314: Preserve failed" -msgstr "E314: Konservo fiaskis" +msgstr "E314: Konservo malsukcesis" -#: ../memline.c:1819 #, c-format -msgid "E315: ml_get: invalid lnum: %<PRId64>" -msgstr "E315: ml_get: nevalida lnum: %<PRId64>" +msgid "E315: ml_get: invalid lnum: %ld" +msgstr "E315: ml_get: nevalida lnum: %ld" -#: ../memline.c:1851 #, c-format -msgid "E316: ml_get: cannot find line %<PRId64>" -msgstr "E316: ml_get: ne eblas trovi linion %<PRId64>" +msgid "E316: ml_get: cannot find line %ld" +msgstr "E316: ml_get: ne eblas trovi linion %ld" -#: ../memline.c:2236 msgid "E317: pointer block id wrong 3" msgstr "E317: nevalida referenco de bloko id 3" -#: ../memline.c:2311 msgid "stack_idx should be 0" msgstr "stack_idx devus esti 0" -#: ../memline.c:2369 msgid "E318: Updated too many blocks?" msgstr "E318: ฤu ฤisdatigis tro da blokoj?" -#: ../memline.c:2511 msgid "E317: pointer block id wrong 4" msgstr "E317: nevalida referenco de bloko id 4" -#: ../memline.c:2536 msgid "deleted block 1?" msgstr "ฤu forviลita bloko 1?" -#: ../memline.c:2707 #, c-format -msgid "E320: Cannot find line %<PRId64>" -msgstr "E320: Ne eblas trovi linion %<PRId64>" +msgid "E320: Cannot find line %ld" +msgstr "E320: Ne eblas trovi linion %ld" -#: ../memline.c:2916 msgid "E317: pointer block id wrong" msgstr "E317: nevalida referenco de bloko id" -#: ../memline.c:2930 msgid "pe_line_count is zero" msgstr "pe_line_count estas nul" -#: ../memline.c:2955 #, c-format -msgid "E322: line number out of range: %<PRId64> past the end" -msgstr "E322: numero de linio ekster limoj: %<PRId64> preter la fino" +msgid "E322: line number out of range: %ld past the end" +msgstr "E322: numero de linio ekster limoj: %ld preter la fino" -#: ../memline.c:2959 #, c-format -msgid "E323: line count wrong in block %<PRId64>" -msgstr "E323: nevalida nombro de linioj en bloko %<PRId64>" +msgid "E323: line count wrong in block %ld" +msgstr "E323: nevalida nombro de linioj en bloko %ld" -#: ../memline.c:2999 msgid "Stack size increases" msgstr "Stako pligrandiฤas" -#: ../memline.c:3038 msgid "E317: pointer block id wrong 2" msgstr "E317: nevalida referenco de bloko id 2" -#: ../memline.c:3070 #, c-format msgid "E773: Symlink loop for \"%s\"" msgstr "E773: Buklo de simbolaj ligiloj por \"%s\"" -#: ../memline.c:3221 msgid "E325: ATTENTION" msgstr "E325: ATENTO" -#: ../memline.c:3222 msgid "" "\n" "Found a swap file by the name \"" @@ -4095,15 +3745,14 @@ msgstr "" "\n" "Trovis permutodosieron .swp kun la nomo \"" -#: ../memline.c:3226 msgid "While opening file \"" msgstr "Dum malfermo de dosiero \"" -#: ../memline.c:3239 msgid " NEWER than swap file!\n" msgstr " PLI NOVA ol permutodosiero .swp!\n" -#: ../memline.c:3244 +#. Some of these messages are long to allow translation to +#. * other languages. msgid "" "\n" "(1) Another program may be editing the same file. If this is the case,\n" @@ -4115,19 +3764,12 @@ msgstr "" " por ne havi du malsamajn aperojn de la sama dosiero, kiam vi faros\n" " ลanฤojn. Eliru aลญ daลญrigu singarde.\n" -#: ../memline.c:3245 -msgid " Quit, or continue with caution.\n" -msgstr " Eliru, aลญ daลญrigu singarde.\n" - -#: ../memline.c:3246 msgid "(2) An edit session for this file crashed.\n" msgstr "(2) Redakta seanco de tiu dosiero kolapsis.\n" -#: ../memline.c:3247 msgid " If this is the case, use \":recover\" or \"vim -r " msgstr " Se veras, uzu \":recover\" aลญ \"vim -r " -#: ../memline.c:3249 msgid "" "\"\n" " to recover the changes (see \":help recovery\").\n" @@ -4135,11 +3777,9 @@ msgstr "" "\"\n" " por restaลญri la ลanฤojn (vidu \":help recovery\").\n" -#: ../memline.c:3250 msgid " If you did this already, delete the swap file \"" msgstr " Se vi jam faris ฤin, forviลu la permutodosieron .swp \"" -#: ../memline.c:3252 msgid "" "\"\n" " to avoid this message.\n" @@ -4147,25 +3787,20 @@ msgstr "" "\"\n" " por eviti tiun mesaฤon.\n" -#: ../memline.c:3450 ../memline.c:3452 msgid "Swap file \"" msgstr "Permutodosiero .swp \"" -#: ../memline.c:3451 ../memline.c:3455 msgid "\" already exists!" msgstr "\" jam ekzistas!" -#: ../memline.c:3457 msgid "VIM - ATTENTION" msgstr "VIM - ATENTO" -#: ../memline.c:3459 msgid "Swap file already exists!" msgstr "Permutodosiero .swp jam ekzistas!" # AM: ฤu Vim konvertos la unuliterajn respondojn de la uzulo? # DP: jes, la '&' respondoj bone funkcias (mi kontrolis) -#: ../memline.c:3464 msgid "" "&Open Read-Only\n" "&Edit anyway\n" @@ -4179,7 +3814,6 @@ msgstr "" "&Eliri\n" "ฤe&sigi" -#: ../memline.c:3467 msgid "" "&Open Read-Only\n" "&Edit anyway\n" @@ -4195,56 +3829,34 @@ msgstr "" "&Eliri\n" "ฤe&sigi" -#. -#. * Change the ".swp" extension to find another file that can be used. -#. * First decrement the last char: ".swo", ".swn", etc. -#. * If that still isn't enough decrement the last but one char: ".svz" -#. * Can happen when editing many "No Name" buffers. -#. -#. ".s?a" -#. ".saa": tried enough, give up -#: ../memline.c:3528 msgid "E326: Too many swap files found" msgstr "E326: Tro da dosieroj trovitaj" -#: ../memory.c:227 -#, c-format -msgid "E342: Out of memory! (allocating %<PRIu64> bytes)" -msgstr "E342: Ne plu restas memoro! (disponigo de %<PRIu64> bajtoj)" - -#: ../menu.c:62 msgid "E327: Part of menu-item path is not sub-menu" msgstr "E327: Parto de vojo de menuero ne estas sub-menuo" -#: ../menu.c:63 msgid "E328: Menu only exists in another mode" msgstr "E328: Menuo nur ekzistas en alia reฤimo" -#: ../menu.c:64 #, c-format msgid "E329: No menu \"%s\"" msgstr "E329: Neniu menuo \"%s\"" #. Only a mnemonic or accelerator is not valid. -#: ../menu.c:329 msgid "E792: Empty menu name" msgstr "E792: Malplena nomo de menuo" -#: ../menu.c:340 msgid "E330: Menu path must not lead to a sub-menu" msgstr "E330: Vojo de menuo ne rajtas konduki al sub-menuo" -#: ../menu.c:365 msgid "E331: Must not add menu items directly to menu bar" msgstr "E331: Aldono de menueroj direkte al menuzono estas malpermesita" -#: ../menu.c:370 msgid "E332: Separator cannot be part of a menu path" msgstr "E332: Disigilo ne rajtas esti ero de vojo de menuo" #. Now we have found the matching menu, and we list the mappings #. Highlight title -#: ../menu.c:762 msgid "" "\n" "--- Menus ---" @@ -4252,69 +3864,60 @@ msgstr "" "\n" "--- Menuoj ---" -#: ../menu.c:1313 +msgid "Tear off this menu" +msgstr "Disigi tiun menuon" + msgid "E333: Menu path must lead to a menu item" msgstr "E333: Vojo de menuo devas konduki al menuero" -#: ../menu.c:1330 #, c-format msgid "E334: Menu not found: %s" msgstr "E334: Menuo netrovita: %s" -#: ../menu.c:1396 #, c-format msgid "E335: Menu not defined for %s mode" msgstr "E335: Menuo ne estas difinita por reฤimo %s" -#: ../menu.c:1426 msgid "E336: Menu path must lead to a sub-menu" msgstr "E336: Vojo de menuo devas konduki al sub-menuo" -#: ../menu.c:1447 msgid "E337: Menu not found - check menu names" msgstr "E337: Menuo ne trovita - kontrolu nomojn de menuoj" -#: ../message.c:423 #, c-format msgid "Error detected while processing %s:" msgstr "Eraro okazis dum traktado de %s:" -#: ../message.c:445 #, c-format msgid "line %4ld:" msgstr "linio %4ld:" -#: ../message.c:617 #, c-format msgid "E354: Invalid register name: '%s'" msgstr "E354: Nevalida nomo de reฤistro: '%s'" -#: ../message.c:986 +msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>" +msgstr "Flegado de mesaฤoj: Dominique PELLร <dominique.pelle@gmail.com>" + msgid "Interrupt: " msgstr "Interrompo: " -#: ../message.c:988 msgid "Press ENTER or type command to continue" msgstr "Premu ENEN-KLAVON aลญ tajpu komandon por daลญrigi" -#: ../message.c:1843 #, c-format -msgid "%s line %<PRId64>" -msgstr "%s linio %<PRId64>" +msgid "%s line %ld" +msgstr "%s linio %ld" -#: ../message.c:2392 msgid "-- More --" msgstr "-- Pli --" -#: ../message.c:2398 msgid " SPACE/d/j: screen/page/line down, b/u/k: up, q: quit " msgstr " SPACETO/d/j: ekrano/paฤo/sub linio, b/u/k: supre, q: eliri " -#: ../message.c:3021 ../message.c:3031 msgid "Question" msgstr "Demando" -#: ../message.c:3023 msgid "" "&Yes\n" "&No" @@ -4322,19 +3925,8 @@ msgstr "" "&Jes\n" "&Ne" -#: ../message.c:3033 -msgid "" -"&Yes\n" -"&No\n" -"&Cancel" -msgstr "" -"&Jes\n" -"&Ne\n" -"&Rezigni" - # AM: ฤu Vim konvertos unuliterajn respondojn? # DP: jes, '&' bone funkcias (mi kontrolis) -#: ../message.c:3045 msgid "" "&Yes\n" "&No\n" @@ -4348,175 +3940,249 @@ msgstr "" "&Forlasi ฤion\n" "&Rezigni" -#: ../message.c:3058 +msgid "Select Directory dialog" +msgstr "Dialogujo de dosiera elekto" + +msgid "Save File dialog" +msgstr "Dialogujo de dosiera konservo" + +msgid "Open File dialog" +msgstr "Dialogujo de dosiera malfermo" + +#. TODO: non-GUI file selector here +msgid "E338: Sorry, no file browser in console mode" +msgstr "E338: Bedaลญrinde ne estas dosierfoliumilo en konzola reฤimo" + msgid "E766: Insufficient arguments for printf()" msgstr "E766: Ne sufiฤaj argumentoj por printf()" -#: ../message.c:3119 msgid "E807: Expected Float argument for printf()" -msgstr "E807: Atendis Glitpunktnombron kiel argumento de printf()" +msgstr "E807: Atendis Glitpunktnombron kiel argumenton de printf()" -#: ../message.c:3873 msgid "E767: Too many arguments to printf()" msgstr "E767: Tro da argumentoj al printf()" -#: ../misc1.c:2256 msgid "W10: Warning: Changing a readonly file" msgstr "W10: Averto: ลanฤo de nurlegebla dosiero" -#: ../misc1.c:2537 msgid "Type number and <Enter> or click with mouse (empty cancels): " msgstr "" "Tajpu nombron kaj <Enenklavon> aลญ alklaku per la muso (malpleno rezignas): " -#: ../misc1.c:2539 msgid "Type number and <Enter> (empty cancels): " msgstr "Tajpu nombron kaj <Enenklavon> (malpleno rezignas): " -#: ../misc1.c:2585 msgid "1 more line" msgstr "1 plia linio" -#: ../misc1.c:2588 msgid "1 line less" msgstr "1 malplia linio" -#: ../misc1.c:2593 #, c-format -msgid "%<PRId64> more lines" -msgstr "%<PRId64> pliaj linioj" +msgid "%ld more lines" +msgstr "%ld pliaj linioj" -#: ../misc1.c:2596 #, c-format -msgid "%<PRId64> fewer lines" -msgstr "%<PRId64> malpliaj linioj" +msgid "%ld fewer lines" +msgstr "%ld malpliaj linioj" -#: ../misc1.c:2599 msgid " (Interrupted)" msgstr " (Interrompita)" -#: ../misc1.c:2635 msgid "Beep!" msgstr "Bip!" -#: ../misc2.c:738 +msgid "ERROR: " +msgstr "ERARO: " + +#, c-format +msgid "" +"\n" +"[bytes] total alloc-freed %lu-%lu, in use %lu, peak use %lu\n" +msgstr "" +"\n" +"[bajtoj] totalaj disponigitaj/maldisponigitaj %lu-%lu, nun uzataj %lu, " +"kulmina uzo %lu\n" + +#, c-format +msgid "" +"[calls] total re/malloc()'s %lu, total free()'s %lu\n" +"\n" +msgstr "" +"[alvokoj] totalaj re/malloc() %lu, totalaj free() %lu\n" +"\n" + +msgid "E340: Line is becoming too long" +msgstr "E340: Linio iฤas tro longa" + +#, c-format +msgid "E341: Internal error: lalloc(%ld, )" +msgstr "E341: Interna eraro: lalloc(%ld, )" + +#, c-format +msgid "E342: Out of memory! (allocating %lu bytes)" +msgstr "E342: Ne plu restas memoro! (disponigo de %lu bajtoj)" + #, c-format msgid "Calling shell to execute: \"%s\"" msgstr "Alvokas ลelon por plenumi: \"%s\"" -#: ../normal.c:183 +msgid "E545: Missing colon" +msgstr "E545: Mankas dupunkto" + +msgid "E546: Illegal mode" +msgstr "E546: Reฤimo nepermesata" + +msgid "E547: Illegal mouseshape" +msgstr "E547: Nevalida formo de muskursoro" + +msgid "E548: digit expected" +msgstr "E548: cifero atendata" + +msgid "E549: Illegal percentage" +msgstr "E549: Nevalida procento" + +msgid "E854: path too long for completion" +msgstr "E854: tro longa vojo por kompletigo" + +#, c-format +msgid "" +"E343: Invalid path: '**[number]' must be at the end of the path or be " +"followed by '%s'." +msgstr "" +"E343: Nevalida vojo: '**[nombro]' devas esti ฤe la fino de la vojo aลญ " +"sekvita de '%s'." + +#, c-format +msgid "E344: Can't find directory \"%s\" in cdpath" +msgstr "E344: Ne eblas trovi dosierujon \"%s\" en cdpath" + +#, c-format +msgid "E345: Can't find file \"%s\" in path" +msgstr "E345: Ne eblas trovi dosieron \"%s\" en serฤvojo" + +#, c-format +msgid "E346: No more directory \"%s\" found in cdpath" +msgstr "E346: Ne plu trovis dosierujon \"%s\" en cdpath" + +#, c-format +msgid "E347: No more file \"%s\" found in path" +msgstr "E347: Ne plu trovis dosieron \"%s\" en serฤvojo" + +#, c-format +msgid "E668: Wrong access mode for NetBeans connection info file: \"%s\"" +msgstr "" +"E668: Nevalida permeso de dosiero de informo de konekto NetBeans: \"%s\"" + +#, c-format +msgid "E658: NetBeans connection lost for buffer %ld" +msgstr "E658: Konekto de NetBeans perdita por bufro %ld" + +msgid "E838: netbeans is not supported with this GUI" +msgstr "E838: netbeans ne estas subtenata kun tiu grafika interfaco" + +msgid "E511: netbeans already connected" +msgstr "E511: nebeans jam konektata" + +#, c-format +msgid "E505: %s is read-only (add ! to override)" +msgstr "E505: %s estas nurlegebla (aldonu ! por transpasi)" + msgid "E349: No identifier under cursor" msgstr "E349: Neniu identigilo sub la kursoro" -#: ../normal.c:1866 msgid "E774: 'operatorfunc' is empty" msgstr "E774: 'operatorfunc' estas malplena" -#: ../normal.c:2637 +# DP: ฤu Eval devas esti tradukita? +msgid "E775: Eval feature not available" +msgstr "E775: Eval eblo ne disponeblas" + msgid "Warning: terminal cannot highlight" msgstr "Averto: terminalo ne povas emfazi" -#: ../normal.c:2807 msgid "E348: No string under cursor" msgstr "E348: Neniu ฤeno sub la kursoro" -#: ../normal.c:3937 msgid "E352: Cannot erase folds with current 'foldmethod'" msgstr "E352: Ne eblas forviลi faldon per aktuala 'foldmethod'" -#: ../normal.c:5897 msgid "E664: changelist is empty" msgstr "E664: Listo de ลanฤoj estas malplena" -#: ../normal.c:5899 msgid "E662: At start of changelist" msgstr "E662: ฤe komenco de ลanฤlisto" -#: ../normal.c:5901 msgid "E663: At end of changelist" msgstr "E663: ฤe fino de ลanฤlisto" -#: ../normal.c:7053 -msgid "Type :quit<Enter> to exit Nvim" +msgid "Type :quit<Enter> to exit Vim" msgstr "Tajpu \":quit<Enenklavo>\" por eliri el Vim" -#: ../ops.c:248 #, c-format msgid "1 line %sed 1 time" msgstr "1 linio %sita 1 foje" -#: ../ops.c:250 #, c-format msgid "1 line %sed %d times" msgstr "1 linio %sita %d foje" -#: ../ops.c:253 #, c-format -msgid "%<PRId64> lines %sed 1 time" -msgstr "%<PRId64> linio %sita 1 foje" +msgid "%ld lines %sed 1 time" +msgstr "%ld linio %sita 1 foje" -#: ../ops.c:256 #, c-format -msgid "%<PRId64> lines %sed %d times" -msgstr "%<PRId64> linioj %sitaj %d foje" +msgid "%ld lines %sed %d times" +msgstr "%ld linioj %sitaj %d foje" -#: ../ops.c:592 #, c-format -msgid "%<PRId64> lines to indent... " -msgstr "%<PRId64> krommarฤenendaj linioj... " +msgid "%ld lines to indent... " +msgstr "%ld krommarฤenendaj linioj... " -#: ../ops.c:634 msgid "1 line indented " msgstr "1 linio krommarฤenita " -#: ../ops.c:636 #, c-format -msgid "%<PRId64> lines indented " -msgstr "%<PRId64> linioj krommarฤenitaj " +msgid "%ld lines indented " +msgstr "%ld linioj krommarฤenitaj " -#: ../ops.c:938 msgid "E748: No previously used register" msgstr "E748: Neniu reฤistro antaลญe uzata" #. must display the prompt -#: ../ops.c:1433 msgid "cannot yank; delete anyway" -msgstr "ne eblas kopii; forviลi tamene" +msgstr "ne eblas kopii; tamen forviลi" -#: ../ops.c:1929 msgid "1 line changed" msgstr "1 linio ลanฤita" -#: ../ops.c:1931 #, c-format -msgid "%<PRId64> lines changed" -msgstr "%<PRId64> linioj ลanฤitaj" +msgid "%ld lines changed" +msgstr "%ld linioj ลanฤitaj" + +#, c-format +msgid "freeing %ld lines" +msgstr "malokupas %ld liniojn" -#: ../ops.c:2521 msgid "block of 1 line yanked" msgstr "bloko de 1 linio kopiita" -#: ../ops.c:2523 msgid "1 line yanked" msgstr "1 linio kopiita" -#: ../ops.c:2525 #, c-format -msgid "block of %<PRId64> lines yanked" -msgstr "bloko de %<PRId64> linioj kopiita" +msgid "block of %ld lines yanked" +msgstr "bloko de %ld linioj kopiita" -#: ../ops.c:2528 #, c-format -msgid "%<PRId64> lines yanked" -msgstr "%<PRId64> linioj kopiitaj" +msgid "%ld lines yanked" +msgstr "%ld linioj kopiitaj" -#: ../ops.c:2710 #, c-format msgid "E353: Nothing in register %s" msgstr "E353: Nenio en reฤistro %s" #. Highlight title -#: ../ops.c:3185 msgid "" "\n" "--- Registers ---" @@ -4524,11 +4190,9 @@ msgstr "" "\n" "--- Reฤistroj ---" -#: ../ops.c:4455 msgid "Illegal register name" msgstr "Nevalida nomo de reฤistro" -#: ../ops.c:4533 msgid "" "\n" "# Registers:\n" @@ -4536,186 +4200,173 @@ msgstr "" "\n" "# Reฤistroj:\n" -#: ../ops.c:4575 #, c-format msgid "E574: Unknown register type %d" msgstr "E574: Nekonata tipo de reฤistro %d" -#: ../ops.c:5089 +msgid "" +"E883: search pattern and expression register may not contain two or more " +"lines" +msgstr "" +"E883: serฤa ลablono kaj esprima reฤistro ne povas enhavi du aลญ pliajn liniojn" + #, c-format -msgid "%<PRId64> Cols; " -msgstr "%<PRId64> Kolumnoj; " +msgid "%ld Cols; " +msgstr "%ld Kolumnoj; " -#: ../ops.c:5097 #, c-format -msgid "" -"Selected %s%<PRId64> of %<PRId64> Lines; %<PRId64> of %<PRId64> Words; " -"%<PRId64> of %<PRId64> Bytes" +msgid "Selected %s%ld of %ld Lines; %lld of %lld Words; %lld of %lld Bytes" msgstr "" -"Apartigis %s%<PRId64> de %<PRId64> Linioj; %<PRId64> de %<PRId64> Vortoj; " -"%<PRId64> de %<PRId64> Bajtoj" +"Apartigis %s%ld de %ld Linioj; %lld de %lld Vortoj; %lld de %lld Bajtoj" -#: ../ops.c:5105 #, c-format msgid "" -"Selected %s%<PRId64> of %<PRId64> Lines; %<PRId64> of %<PRId64> Words; " -"%<PRId64> of %<PRId64> Chars; %<PRId64> of %<PRId64> Bytes" +"Selected %s%ld of %ld Lines; %lld of %lld Words; %lld of %lld Chars; %lld of " +"%lld Bytes" msgstr "" -"Apartigis %s%<PRId64> de %<PRId64> Linioj; %<PRId64> de %<PRId64> Vortoj; " -"%<PRId64> de %<PRId64> Signoj; %<PRId64> de %<PRId64> Bajtoj" +"Apartigis %s%ld de %ld Linioj; %lld de %lld Vortoj; %lld de %lld Signoj; " +"%lld de %lld Bajtoj" -#: ../ops.c:5123 #, c-format -msgid "" -"Col %s of %s; Line %<PRId64> of %<PRId64>; Word %<PRId64> of %<PRId64>; Byte " -"%<PRId64> of %<PRId64>" -msgstr "" -"Kol %s de %s; Linio %<PRId64> de %<PRId64>; Vorto %<PRId64> de %<PRId64>; " -"Bajto %<PRId64> de %<PRId64>" +msgid "Col %s of %s; Line %ld of %ld; Word %lld of %lld; Byte %lld of %lld" +msgstr "Kol %s de %s; Linio %ld de %ld; Vorto %lld de %lld; Bajto %lld de %lld" -#: ../ops.c:5133 #, c-format msgid "" -"Col %s of %s; Line %<PRId64> of %<PRId64>; Word %<PRId64> of %<PRId64>; Char " -"%<PRId64> of %<PRId64>; Byte %<PRId64> of %<PRId64>" +"Col %s of %s; Line %ld of %ld; Word %lld of %lld; Char %lld of %lld; Byte " +"%lld of %lld" msgstr "" -"Kol %s de %s; Linio %<PRId64> de %<PRId64>; Vorto %<PRId64> de %<PRId64>; " -"Signo %<PRId64> de %<PRId64>; Bajto %<PRId64> de %<PRId64>" +"Kol %s de %s; Linio %ld de %ld; Vorto %lld de %lld; Signo %lld de %lld; " +"Bajto %lld de %lld" -#: ../ops.c:5146 #, c-format -msgid "(+%<PRId64> for BOM)" -msgstr "(+%<PRId64> por BOM)" +msgid "(+%ld for BOM)" +msgstr "(+%ld por BOM)" -#: ../option.c:1238 msgid "%<%f%h%m%=Page %N" msgstr "%<%f%h%m%=Folio %N" -#: ../option.c:1574 msgid "Thanks for flying Vim" msgstr "Dankon pro flugi per Vim" -#. found a mismatch: skip -#: ../option.c:2698 msgid "E518: Unknown option" msgstr "E518: Nekonata opcio" -#: ../option.c:2709 msgid "E519: Option not supported" msgstr "E519: Opcio ne subtenata" -#: ../option.c:2740 msgid "E520: Not allowed in a modeline" msgstr "E520: Nepermesebla en reฤimlinio" -#: ../option.c:2815 msgid "E846: Key code not set" msgstr "E846: Klavkodo ne agordita" -#: ../option.c:2924 msgid "E521: Number required after =" msgstr "E521: Nombro bezonata post =" -#: ../option.c:3226 ../option.c:3864 msgid "E522: Not found in termcap" msgstr "E522: Netrovita en termcap" -#: ../option.c:3335 #, c-format msgid "E539: Illegal character <%s>" msgstr "E539: Nevalida signo <%s>" -#: ../option.c:2253 #, c-format msgid "For option %s" msgstr "Por opcio %s" -#: ../option.c:3862 msgid "E529: Cannot set 'term' to empty string" msgstr "E529: Ne eblas agordi 'term' al malplena ฤeno" -#: ../option.c:3885 +msgid "E530: Cannot change term in GUI" +msgstr "E530: term ne ลanฤeblas en grafika interfaco" + +msgid "E531: Use \":gui\" to start the GUI" +msgstr "E531: Uzu \":gui\" por lanฤi la grafikan interfacon" + msgid "E589: 'backupext' and 'patchmode' are equal" msgstr "E589: 'backupext' kaj 'patchmode' estas egalaj" -#: ../option.c:3964 msgid "E834: Conflicts with value of 'listchars'" msgstr "E834: Konfliktoj kun la valoro de 'listchars'" -#: ../option.c:3966 msgid "E835: Conflicts with value of 'fillchars'" msgstr "E835: Konfliktoj kun la valoro de 'fillchars'" -#: ../option.c:4163 +msgid "E617: Cannot be changed in the GTK+ 2 GUI" +msgstr "E617: Ne ลanฤeblas en la grafika interfaco GTK+ 2" + msgid "E524: Missing colon" msgstr "E524: Mankas dupunkto" -#: ../option.c:4165 msgid "E525: Zero length string" msgstr "E525: ฤeno de nula longo" -#: ../option.c:4220 #, c-format msgid "E526: Missing number after <%s>" msgstr "E526: Mankas nombro post <%s>" -#: ../option.c:4232 msgid "E527: Missing comma" msgstr "E527: Mankas komo" -#: ../option.c:4239 msgid "E528: Must specify a ' value" msgstr "E528: Devas specifi ' valoron" -#: ../option.c:4271 msgid "E595: contains unprintable or wide character" msgstr "E595: enhavas nepreseblan aลญ plurฤellarฤan signon" -#: ../option.c:4469 +msgid "E596: Invalid font(s)" +msgstr "E596: Nevalida(j) tiparo(j)" + +msgid "E597: can't select fontset" +msgstr "E597: ne eblas elekti tiparon" + +msgid "E598: Invalid fontset" +msgstr "E598: Nevalida tiparo" + +msgid "E533: can't select wide font" +msgstr "E533: ne eblas elekti larฤan tiparon" + +msgid "E534: Invalid wide font" +msgstr "E534: Nevalida larฤa tiparo" + #, c-format msgid "E535: Illegal character after <%c>" msgstr "E535: Nevalida signo post <%c>" -#: ../option.c:4534 msgid "E536: comma required" msgstr "E536: komo bezonata" -#: ../option.c:4543 #, c-format msgid "E537: 'commentstring' must be empty or contain %s" msgstr "E537: 'commentstring' devas esti malplena aลญ enhavi %s" -#: ../option.c:4928 +msgid "E538: No mouse support" +msgstr "E538: Neniu muso subtenata" + msgid "E540: Unclosed expression sequence" msgstr "E540: '}' mankas" -#: ../option.c:4932 msgid "E541: too many items" msgstr "E541: tro da elementoj" -#: ../option.c:4934 msgid "E542: unbalanced groups" -msgstr "E542: misekvilibritaj grupoj" +msgstr "E542: misekvilibraj grupoj" -#: ../option.c:5148 msgid "E590: A preview window already exists" msgstr "E590: Antaลญvida fenestro jam ekzistas" -#: ../option.c:5311 msgid "W17: Arabic requires UTF-8, do ':set encoding=utf-8'" msgstr "W17: La araba bezonas UTF-8, tajpu \":set encoding=utf-8\"" -#: ../option.c:5623 #, c-format msgid "E593: Need at least %d lines" msgstr "E593: Bezonas almenaลญ %d liniojn" -#: ../option.c:5631 #, c-format msgid "E594: Need at least %d columns" msgstr "E594: Bezonas almenaลญ %d kolumnojn" -#: ../option.c:6011 #, c-format msgid "E355: Unknown option: %s" msgstr "E355: Nekonata opcio: %s" @@ -4723,12 +4374,10 @@ msgstr "E355: Nekonata opcio: %s" #. There's another character after zeros or the string #. * is empty. In both cases, we are trying to set a #. * num option using a string. -#: ../option.c:6037 #, c-format msgid "E521: Number required: &%s = '%s'" msgstr "E521: Nombro bezonata: &%s = '%s'" -#: ../option.c:6149 msgid "" "\n" "--- Terminal codes ---" @@ -4736,7 +4385,6 @@ msgstr "" "\n" "--- Kodoj de terminalo ---" -#: ../option.c:6151 msgid "" "\n" "--- Global option values ---" @@ -4744,7 +4392,6 @@ msgstr "" "\n" "--- Mallokaj opcioj ---" -#: ../option.c:6153 msgid "" "\n" "--- Local option values ---" @@ -4752,7 +4399,6 @@ msgstr "" "\n" "--- Valoroj de lokaj opcioj ---" -#: ../option.c:6155 msgid "" "\n" "--- Options ---" @@ -4760,37 +4406,116 @@ msgstr "" "\n" "--- Opcioj ---" -#: ../option.c:6816 msgid "E356: get_varp ERROR" msgstr "E356: ERARO get_varp" -#: ../option.c:7696 #, c-format msgid "E357: 'langmap': Matching character missing for %s" msgstr "E357: 'langmap': Kongrua signo mankas por %s" -#: ../option.c:7715 #, c-format msgid "E358: 'langmap': Extra characters after semicolon: %s" msgstr "E358: 'langmap': Ekstraj signoj post punktokomo: %s" -#: ../os/shell.c:194 -msgid "" -"\n" -"Cannot execute shell " -msgstr "" -"\n" -"Ne eblas plenumi ลelon " +msgid "cannot open " +msgstr "ne eblas malfermi " + +msgid "VIM: Can't open window!\n" +msgstr "VIM: Ne eblas malfermi fenestron!\n" + +msgid "Need Amigados version 2.04 or later\n" +msgstr "Bezonas version 2.04 de Amigados aลญ pli novan\n" + +#, c-format +msgid "Need %s version %ld\n" +msgstr "Bezonas %s-on versio %ld\n" + +msgid "Cannot open NIL:\n" +msgstr "Ne eblas malfermi NIL:\n" + +msgid "Cannot create " +msgstr "Ne eblas krei " + +#, c-format +msgid "Vim exiting with %d\n" +msgstr "Vim eliras kun %d\n" + +msgid "cannot change console mode ?!\n" +msgstr "ne eblas ลanฤi reฤimon de konzolo?!\n" + +msgid "mch_get_shellsize: not a console??\n" +msgstr "mch_get_shellsize: ne estas konzolo??\n" + +#. if Vim opened a window: Executing a shell may cause crashes +msgid "E360: Cannot execute shell with -f option" +msgstr "E360: Ne eblas plenumi ลelon kun opcio -f" + +msgid "Cannot execute " +msgstr "Ne eblas plenumi " + +msgid "shell " +msgstr "ลelo " + +msgid " returned\n" +msgstr " liveris\n" + +msgid "ANCHOR_BUF_SIZE too small." +msgstr "ANCHOR_BUF_SIZE tro malgranda." + +msgid "I/O ERROR" +msgstr "ERARO DE ENIGO/ELIGO" + +msgid "Message" +msgstr "Mesaฤo" + +msgid "E237: Printer selection failed" +msgstr "E237: Elekto de presilo malsukcesis" + +#, c-format +msgid "to %s on %s" +msgstr "al %s de %s" + +#, c-format +msgid "E613: Unknown printer font: %s" +msgstr "E613: Nekonata tiparo de presilo: %s" + +#, c-format +msgid "E238: Print error: %s" +msgstr "E238: Eraro de presado: %s" + +#, c-format +msgid "Printing '%s'" +msgstr "Presas '%s'" + +#, c-format +msgid "E244: Illegal charset name \"%s\" in font name \"%s\"" +msgstr "E244: Nevalida nomo de signaro \"%s\" en nomo de tiparo \"%s\"" + +#, c-format +msgid "E244: Illegal quality name \"%s\" in font name \"%s\"" +msgstr "E244: Nevalida nomo de kvalito \"%s\" en nomo de tiparo \"%s\"" + +#, c-format +msgid "E245: Illegal char '%c' in font name \"%s\"" +msgstr "E245: Nevalida signo '%c' en nomo de tiparo \"%s\"" + +#, c-format +msgid "Opening the X display took %ld msec" +msgstr "Malfermo de vidigo X daลญris %ld msek" -#: ../os/shell.c:439 msgid "" "\n" -"shell returned " +"Vim: Got X error\n" msgstr "" "\n" -"ลelo liveris " +"Vim: Alvenis X eraro\n" + +msgid "Testing the X display failed" +msgstr "Testo de la vidigo X malsukcesis" + +msgid "Opening the X display timed out" +msgstr "Tempolimo okazis dum malfermo de vidigo X" -#: ../os_unix.c:465 ../os_unix.c:471 msgid "" "\n" "Could not get security context for " @@ -4798,7 +4523,6 @@ msgstr "" "\n" "Ne povis akiri kuntekston de sekureco por " -#: ../os_unix.c:479 msgid "" "\n" "Could not set security context for " @@ -4815,219 +4539,293 @@ msgid "Could not get security context %s for %s. Removing it!" msgstr "" "Ne povis akiri kuntekston de sekureco %s por %s. Gi nun estas forigata!" -#: ../os_unix.c:1558 ../os_unix.c:1647 +msgid "" +"\n" +"Cannot execute shell sh\n" +msgstr "" +"\n" +"Ne eblas plenumi ลelon sh\n" + +msgid "" +"\n" +"shell returned " +msgstr "" +"\n" +"ลelo liveris " + +msgid "" +"\n" +"Cannot create pipes\n" +msgstr "" +"\n" +"Ne eblas krei duktojn\n" + +msgid "" +"\n" +"Cannot fork\n" +msgstr "" +"\n" +"Ne eblas forki\n" + +msgid "" +"\n" +"Cannot execute shell " +msgstr "" +"\n" +"Ne eblas plenumi ลelon " + +msgid "" +"\n" +"Command terminated\n" +msgstr "" +"\n" +"Komando terminigita\n" + +msgid "XSMP lost ICE connection" +msgstr "XSMP perdis la konekton ICE" + #, c-format msgid "dlerror = \"%s\"" msgstr "dlerror = \"%s\"" -#: ../path.c:1449 +msgid "Opening the X display failed" +msgstr "Malfermo de vidigo X malsukcesis" + +msgid "XSMP handling save-yourself request" +msgstr "XSMP: traktado de peto konservi-mem" + +msgid "XSMP opening connection" +msgstr "XSMP: malfermo de konekto" + +msgid "XSMP ICE connection watch failed" +msgstr "XSMP: kontrolo de konekto ICE malsukcesis" + #, c-format -msgid "E447: Can't find file \"%s\" in path" -msgstr "E447: Ne eblas trovi dosieron \"%s\" en serฤvojo" +msgid "XSMP SmcOpenConnection failed: %s" +msgstr "XSMP: SmcOpenConnection malsukcesis: %s" + +msgid "At line" +msgstr "ฤe linio" + +msgid "Could not load vim32.dll!" +msgstr "Ne eblis ลargi vim32.dll!" + +msgid "VIM Error" +msgstr "Eraro de VIM" + +msgid "Could not fix up function pointers to the DLL!" +msgstr "Ne eblis ripari referencojn de funkcioj al la DLL!" + +# DP: la eventoj estas tiuj, kiuj estas en la sekvantaj ฤenoj +#, c-format +msgid "Vim: Caught %s event\n" +msgstr "Vim: Kaptis eventon %s\n" + +msgid "close" +msgstr "fermo" + +msgid "logoff" +msgstr "elsaluto" + +msgid "shutdown" +msgstr "sistemfermo" + +msgid "E371: Command not found" +msgstr "E371: Netrovebla komando" + +msgid "" +"VIMRUN.EXE not found in your $PATH.\n" +"External commands will not pause after completion.\n" +"See :help win32-vimrun for more information." +msgstr "" +"VIMRUN.EXE ne troveblas en via $PATH.\n" +"Eksteraj komandoj ne paลญzos post kompletigo.\n" +"Vidu :help win32-vimrun por pliaj informoj." + +msgid "Vim Warning" +msgstr "Averto de Vim" + +#, c-format +msgid "shell returned %d" +msgstr "la ลelo liveris %d" -#: ../quickfix.c:359 #, c-format msgid "E372: Too many %%%c in format string" msgstr "E372: Tro da %%%c en formata ฤeno" -#: ../quickfix.c:371 #, c-format msgid "E373: Unexpected %%%c in format string" msgstr "E373: Neatendita %%%c en formata ฤeno" -#: ../quickfix.c:420 msgid "E374: Missing ] in format string" msgstr "E374: Mankas ] en formata ฤeno" -#: ../quickfix.c:431 #, c-format msgid "E375: Unsupported %%%c in format string" msgstr "E375: Nesubtenata %%%c en formata ฤeno" -#: ../quickfix.c:448 #, c-format msgid "E376: Invalid %%%c in format string prefix" msgstr "E376: Nevalida %%%c en prefikso de formata ฤeno" -#: ../quickfix.c:454 #, c-format msgid "E377: Invalid %%%c in format string" msgstr "E377: Nevalida %%%c en formata ฤeno" #. nothing found -#: ../quickfix.c:477 msgid "E378: 'errorformat' contains no pattern" msgstr "E378: 'errorformat' enhavas neniun ลablonon" -#: ../quickfix.c:695 msgid "E379: Missing or empty directory name" msgstr "E379: Nomo de dosierujo mankas aลญ estas malplena" -#: ../quickfix.c:1305 msgid "E553: No more items" msgstr "E553: Ne plu estas eroj" -#: ../quickfix.c:1674 +msgid "E924: Current window was closed" +msgstr "E924: Aktuala vindozo fermiฤis" + +msgid "E925: Current quickfix was changed" +msgstr "E925: Aktuala rapidriparo ลanฤiฤis" + +msgid "E926: Current location list was changed" +msgstr "E926: Aktuala listo de lokoj ลanฤiฤis" + #, c-format msgid "(%d of %d)%s%s: " msgstr "(%d de %d)%s%s: " -#: ../quickfix.c:1676 msgid " (line deleted)" msgstr " (forviลita linio)" -#: ../quickfix.c:1863 +#, c-format +msgid "%serror list %d of %d; %d errors " +msgstr "%slisto de eraroj %d de %d; %d eraroj" + msgid "E380: At bottom of quickfix stack" msgstr "E380: ฤe la subo de stako de rapidriparo" -#: ../quickfix.c:1869 msgid "E381: At top of quickfix stack" msgstr "E381: ฤe la supro de stako de rapidriparo" -#: ../quickfix.c:1880 -#, c-format -msgid "error list %d of %d; %d errors" -msgstr "listo de eraroj %d de %d; %d eraroj" +msgid "No entries" +msgstr "Neniu ano" -#: ../quickfix.c:2427 msgid "E382: Cannot write, 'buftype' option is set" msgstr "E382: Ne eblas skribi, opcio 'buftype' estas ลaltita" -#: ../quickfix.c:2812 +msgid "Error file" +msgstr "Erara Dosiero" + msgid "E683: File name missing or invalid pattern" msgstr "E683: Dosiernomo mankas aลญ nevalida ลablono" -#: ../quickfix.c:2911 #, c-format msgid "Cannot open file \"%s\"" msgstr "Ne eblas malfermi dosieron \"%s\"" -#: ../quickfix.c:3429 msgid "E681: Buffer is not loaded" msgstr "E681: Bufro ne estas ลargita" -#: ../quickfix.c:3487 msgid "E777: String or List expected" msgstr "E777: ฤeno aลญ Listo atendita" -#: ../regexp.c:359 #, c-format msgid "E369: invalid item in %s%%[]" msgstr "E369: nevalida ano en %s%%[]" -#: ../regexp.c:374 #, c-format msgid "E769: Missing ] after %s[" msgstr "E769: Mankas ] post %s[" -#: ../regexp.c:375 #, c-format msgid "E53: Unmatched %s%%(" msgstr "E53: Neekvilibra %s%%(" -#: ../regexp.c:376 #, c-format msgid "E54: Unmatched %s(" msgstr "E54: Neekvilibra %s(" -#: ../regexp.c:377 #, c-format msgid "E55: Unmatched %s)" msgstr "E55: Neekvilibra %s" -#: ../regexp.c:378 msgid "E66: \\z( not allowed here" -msgstr "E66: \\z( estas permesebla tie" +msgstr "E66: \\z( estas nepermesebla tie" # DP: vidu http://www.thefreedictionary.com/et+al. -#: ../regexp.c:379 msgid "E67: \\z1 et al. not allowed here" msgstr "E67: \\z1 kaj aliaj estas nepermeseblaj tie" -#: ../regexp.c:380 #, c-format msgid "E69: Missing ] after %s%%[" msgstr "E69: Mankas ] post %s%%[" -#: ../regexp.c:381 #, c-format msgid "E70: Empty %s%%[]" msgstr "E70: Malplena %s%%[]" -#: ../regexp.c:1209 ../regexp.c:1224 msgid "E339: Pattern too long" msgstr "E339: ลablono tro longa" -#: ../regexp.c:1371 msgid "E50: Too many \\z(" msgstr "E50: Tro da \\z(" -#: ../regexp.c:1378 #, c-format msgid "E51: Too many %s(" msgstr "E51: Tro da %s(" -#: ../regexp.c:1427 msgid "E52: Unmatched \\z(" msgstr "E52: Neekvilibra \\z(" -#: ../regexp.c:1637 #, c-format msgid "E59: invalid character after %s@" msgstr "E59: nevalida signo post %s@" -#: ../regexp.c:1672 #, c-format msgid "E60: Too many complex %s{...}s" msgstr "E60: Tro da kompleksaj %s{...}-oj" -#: ../regexp.c:1687 #, c-format msgid "E61: Nested %s*" msgstr "E61: Ingita %s*" -#: ../regexp.c:1690 #, c-format msgid "E62: Nested %s%c" msgstr "E62: Ingita %s%c" -#: ../regexp.c:1800 msgid "E63: invalid use of \\_" msgstr "E63: nevalida uzo de \\_" -#: ../regexp.c:1850 #, c-format msgid "E64: %s%c follows nothing" msgstr "E64: %s%c sekvas nenion" -#: ../regexp.c:1902 msgid "E65: Illegal back reference" msgstr "E65: Nevalida retro-referenco" -#: ../regexp.c:1943 msgid "E68: Invalid character after \\z" msgstr "E68: Nevalida signo post \\z" -#: ../regexp.c:2049 ../regexp_nfa.c:1296 #, c-format msgid "E678: Invalid character after %s%%[dxouU]" msgstr "E678: Nevalida signo post %s%%[dxouU]" -#: ../regexp.c:2107 #, c-format msgid "E71: Invalid character after %s%%" msgstr "E71: Nevalida signo post %s%%" -#: ../regexp.c:3017 #, c-format msgid "E554: Syntax error in %s{...}" msgstr "E554: Sintaksa eraro en %s{...}" -#: ../regexp.c:3805 msgid "External submatches:\n" msgstr "Eksteraj subkongruoj:\n" -#: ../regexp.c:7022 +#, c-format +msgid "E888: (NFA regexp) cannot repeat %s" +msgstr "E888: (NFA-regulesprimo) ne eblas ripeti %s" + msgid "" "E864: \\%#= can only be followed by 0, 1, or 2. The automatic engine will be " "used " @@ -5035,65 +4833,58 @@ msgstr "" "E864: \\%#= povas nur esti sekvita de 0, 1, aลญ 2. La aลญtomata motoro de " "regulesprimo estos uzata " -#: ../regexp_nfa.c:239 +msgid "Switching to backtracking RE engine for pattern: " +msgstr "ลangota al malavanca motoro de regulesprimo por ลablono: " + msgid "E865: (NFA) Regexp end encountered prematurely" msgstr "E865: (NFA) Trovis finon de regulesprimo tro frue" -#: ../regexp_nfa.c:240 #, c-format msgid "E866: (NFA regexp) Misplaced %c" msgstr "E866: (NFA-regulesprimo) Mispoziciigita %c" -#: ../regexp_nfa.c:242 -#, fuzzy, c-format -msgid "E877: (NFA regexp) Invalid character class: %<PRId64>" -msgstr "E877: (NFA-regulesprimo) Nevalida klaso de signo " +#, c-format +msgid "E877: (NFA regexp) Invalid character class: %ld" +msgstr "E877: (NFA-regulesprimo) Nevalida klaso de signo: %ld" -#: ../regexp_nfa.c:1261 #, c-format msgid "E867: (NFA) Unknown operator '\\z%c'" msgstr "E867: (NFA) Nekonata operatoro '\\z%c'" -#: ../regexp_nfa.c:1387 -#, fuzzy, c-format +#, c-format msgid "E867: (NFA) Unknown operator '\\%%%c'" -msgstr "E867: (NFA) Nekonata operatoro '\\z%c'" +msgstr "E867: (NFA) Nekonata operatoro '\\%%%c'" + +#. should never happen +msgid "E868: Error building NFA with equivalence class!" +msgstr "E868: Eraro dum prekomputado de NFA kun ekvivalentoklaso!" -#: ../regexp_nfa.c:1802 #, c-format msgid "E869: (NFA) Unknown operator '\\@%c'" msgstr "E869: (NFA) Nekonata operatoro '\\@%c'" -#: ../regexp_nfa.c:1831 msgid "E870: (NFA regexp) Error reading repetition limits" msgstr "E870: (NFS-regulesprimo) Eraro dum legado de limoj de ripeto" #. Can't have a multi follow a multi. -#: ../regexp_nfa.c:1895 msgid "E871: (NFA regexp) Can't have a multi follow a multi !" msgstr "" "E871: (NFA-regulesprimo) Ne povas havi mult-selekton tuj post alia mult-" "selekto!" #. Too many `(' -#: ../regexp_nfa.c:2037 msgid "E872: (NFA regexp) Too many '('" msgstr "E872: (NFA-regulesprimo) tro da '('" -#: ../regexp_nfa.c:2042 -#, fuzzy msgid "E879: (NFA regexp) Too many \\z(" -msgstr "E872: (NFA-regulesprimo) tro da '('" +msgstr "E879: (NFA-regulesprimo) tro da \\z(" -#: ../regexp_nfa.c:2066 msgid "E873: (NFA regexp) proper termination error" msgstr "E873: (NFA-regulesprimo) propra end-eraro" -#: ../regexp_nfa.c:2599 msgid "E874: (NFA) Could not pop the stack !" msgstr "E874: (NFA) Ne povis elpreni de la staplo!" -#: ../regexp_nfa.c:3298 msgid "" "E875: (NFA regexp) (While converting from postfix to NFA), too many states " "left on stack" @@ -5101,177 +4892,136 @@ msgstr "" "E875: (NFA-regulesprimo) (dum konverto de postmeto al NFA), restas tro da " "statoj en la staplo" -#: ../regexp_nfa.c:3302 msgid "E876: (NFA regexp) Not enough space to store the whole NFA " msgstr "E876: (NFA-regulesprimo) ne sufiฤa spaco por enmomorigi la tutan NFA " -#: ../regexp_nfa.c:4571 ../regexp_nfa.c:4869 +msgid "E878: (NFA) Could not allocate memory for branch traversal!" +msgstr "E878: (NFA) Ne povis asigni memoron por traigi branฤojn!" + msgid "" "Could not open temporary log file for writing, displaying on stderr ... " msgstr "" "Ne povis malfermi provizoran protokolan dosieron por skribi, nun montras sur " "stderr ..." -#: ../regexp_nfa.c:4840 #, c-format msgid "(NFA) COULD NOT OPEN %s !" msgstr "(NFA) NE POVIS MALFERMI %s!" -#: ../regexp_nfa.c:6049 msgid "Could not open temporary log file for writing " msgstr "Ne povis malfermi la provizoran protokolan dosieron por skribi " -#: ../screen.c:7435 msgid " VREPLACE" msgstr " V-ANSTATAลฌIGO" -#: ../screen.c:7437 msgid " REPLACE" msgstr " ANSTATAลฌIGO" -#: ../screen.c:7440 msgid " REVERSE" msgstr " INVERSI" -#: ../screen.c:7441 msgid " INSERT" msgstr " ENMETO" -#: ../screen.c:7443 msgid " (insert)" msgstr " (enmeto)" -#: ../screen.c:7445 msgid " (replace)" msgstr " (anstataลญigo)" -#: ../screen.c:7447 msgid " (vreplace)" msgstr " (v-anstataลญigo)" -#: ../screen.c:7449 msgid " Hebrew" msgstr " hebrea" -#: ../screen.c:7454 msgid " Arabic" msgstr " araba" -#: ../screen.c:7456 -msgid " (lang)" -msgstr " (lingvo)" - -#: ../screen.c:7459 msgid " (paste)" msgstr " (algluo)" -#: ../screen.c:7469 msgid " VISUAL" msgstr " VIDUMA" -#: ../screen.c:7470 msgid " VISUAL LINE" msgstr " VIDUMA LINIO" -#: ../screen.c:7471 msgid " VISUAL BLOCK" msgstr " VIDUMA BLOKO" -#: ../screen.c:7472 msgid " SELECT" msgstr " APARTIGO" -#: ../screen.c:7473 msgid " SELECT LINE" msgstr " APARTIGITA LINIO" -#: ../screen.c:7474 msgid " SELECT BLOCK" msgstr " APARTIGITA BLOKO" -#: ../screen.c:7486 ../screen.c:7541 msgid "recording" msgstr "registrado" -#: ../search.c:487 #, c-format msgid "E383: Invalid search string: %s" msgstr "E383: Nevalida serฤenda ฤeno: %s" -#: ../search.c:832 #, c-format msgid "E384: search hit TOP without match for: %s" msgstr "E384: serฤo atingis SUPRON sen trovi: %s" -#: ../search.c:835 #, c-format msgid "E385: search hit BOTTOM without match for: %s" msgstr "E385: serฤo atingis SUBON sen trovi: %s" -#: ../search.c:1200 msgid "E386: Expected '?' or '/' after ';'" msgstr "E386: Atendis '?' aลญ '/' post ';'" -#: ../search.c:4085 msgid " (includes previously listed match)" msgstr " (enhavas antaลญe listigitajn kongruojn)" #. cursor at status line -#: ../search.c:4104 msgid "--- Included files " msgstr "--- Inkluzivitaj dosieroj " -#: ../search.c:4106 msgid "not found " msgstr "netrovitaj " -#: ../search.c:4107 msgid "in path ---\n" msgstr "en serฤvojo ---\n" -#: ../search.c:4168 msgid " (Already listed)" msgstr " (Jam listigita)" -#: ../search.c:4170 msgid " NOT FOUND" msgstr " NETROVITA" -#: ../search.c:4211 #, c-format msgid "Scanning included file: %s" msgstr "Skanado de inkluzivitaj dosieroj: %s" -#: ../search.c:4216 #, c-format msgid "Searching included file %s" msgstr "Serฤado de inkluzivitaj dosieroj %s" -#: ../search.c:4405 msgid "E387: Match is on current line" msgstr "E387: Kongruo estas ฤe aktuala linio" -#: ../search.c:4517 msgid "All included files were found" msgstr "ฤiuj inkluzivitaj dosieroj estis trovitaj" -#: ../search.c:4519 msgid "No included files" msgstr "Neniu inkluzivita dosiero" -#: ../search.c:4527 msgid "E388: Couldn't find definition" msgstr "E388: Ne eblis trovi difinon" -#: ../search.c:4529 msgid "E389: Couldn't find pattern" msgstr "E389: Ne eblis trovi ลablonon" -#: ../search.c:4668 msgid "Substitute " msgstr "Anstataลญigi " -#: ../search.c:4681 #, c-format msgid "" "\n" @@ -5282,97 +5032,128 @@ msgstr "" "# Lasta serฤa ลablono %s:\n" "~" -#: ../spell.c:951 -msgid "E759: Format error in spell file" -msgstr "E759: Eraro de formato en literuma dosiero" +msgid "E756: Spell checking is not enabled" +msgstr "E756: Literumilo ne estas ลaltita" + +#, c-format +msgid "Warning: Cannot find word list \"%s_%s.spl\" or \"%s_ascii.spl\"" +msgstr "Averto: Ne eblas trovi vortliston \"%s_%s.spl\" aลญ \"%s_ascii.spl\"" + +#, c-format +msgid "Warning: Cannot find word list \"%s.%s.spl\" or \"%s.ascii.spl\"" +msgstr "Averto: Ne eblas trovi vortliston \"%s.%s.spl\" aลญ \"%s.ascii.spl\"" + +msgid "E797: SpellFileMissing autocommand deleted buffer" +msgstr "E797: Aลญtokomando SpellFileMissing forviลis bufron" + +#, c-format +msgid "Warning: region %s not supported" +msgstr "Averto: regiono %s ne subtenata" + +msgid "Sorry, no suggestions" +msgstr "Bedaลญrinde ne estas sugestoj" + +#, c-format +msgid "Sorry, only %ld suggestions" +msgstr "Bedaลญrinde estas nur %ld sugestoj" + +#. for when 'cmdheight' > 1 +#. avoid more prompt +#, c-format +msgid "Change \"%.*s\" to:" +msgstr "Anstataลญigi \"%.*s\" per:" + +#, c-format +msgid " < \"%.*s\"" +msgstr " < \"%.*s\"" + +msgid "E752: No previous spell replacement" +msgstr "E752: Neniu antaลญa literuma anstataลญigo" + +#, c-format +msgid "E753: Not found: %s" +msgstr "E753: Netrovita: %s" -#: ../spell.c:952 msgid "E758: Truncated spell file" msgstr "E758: Trunkita literuma dosiero" -#: ../spell.c:953 #, c-format msgid "Trailing text in %s line %d: %s" msgstr "Vosta teksto en %s linio %d: %s" -#: ../spell.c:954 #, c-format msgid "Affix name too long in %s line %d: %s" msgstr "Nomo de afikso tro longa en %s linio %d: %s" -#: ../spell.c:955 msgid "E761: Format error in affix file FOL, LOW or UPP" msgstr "E761: Eraro de formato en afiksa dosiero FOL, LOW aลญ UPP" -#: ../spell.c:957 msgid "E762: Character in FOL, LOW or UPP is out of range" msgstr "E762: Signo en FOL, LOW aลญ UPP estas ekster limoj" -#: ../spell.c:958 msgid "Compressing word tree..." msgstr "Densigas arbon de vortoj..." -#: ../spell.c:1951 -msgid "E756: Spell checking is not enabled" -msgstr "E756: Literumilo ne estas ลaltita" - -#: ../spell.c:2249 -#, c-format -msgid "Warning: Cannot find word list \"%s.%s.spl\" or \"%s.ascii.spl\"" -msgstr "Averto: Ne eblas trovi vortliston \"%s.%s.spl\" aลญ \"%s.ascii.spl\"" - -#: ../spell.c:2473 #, c-format msgid "Reading spell file \"%s\"" msgstr "Legado de literuma dosiero \"%s\"" -#: ../spell.c:2496 msgid "E757: This does not look like a spell file" msgstr "E757: Tio ne ลajnas esti literuma dosiero" -#: ../spell.c:2501 msgid "E771: Old spell file, needs to be updated" msgstr "E771: Malnova literuma dosiero, ฤisdatigo bezonata" -#: ../spell.c:2504 msgid "E772: Spell file is for newer version of Vim" msgstr "E772: Literuma dosiero estas por pli nova versio de Vim" -#: ../spell.c:2602 msgid "E770: Unsupported section in spell file" msgstr "E770: Nesubtenata sekcio en literuma dosiero" -#: ../spell.c:3762 #, c-format -msgid "Warning: region %s not supported" -msgstr "Averto: regiono %s ne subtenata" +msgid "E778: This does not look like a .sug file: %s" +msgstr "E778: Tio ne ลajnas esti dosiero .sug: %s" + +#, c-format +msgid "E779: Old .sug file, needs to be updated: %s" +msgstr "E779: Malnova dosiero .sug, bezonas ฤisdatigon: %s" + +#, c-format +msgid "E780: .sug file is for newer version of Vim: %s" +msgstr "E780: Dosiero .sug estas por pli nova versio de Vim: %s" + +#, c-format +msgid "E781: .sug file doesn't match .spl file: %s" +msgstr "E781: Dosiero .sug ne kongruas kun dosiero .spl: %s" + +#, c-format +msgid "E782: error while reading .sug file: %s" +msgstr "E782: eraro dum legado de dosiero .sug: %s" -#: ../spell.c:4550 #, c-format msgid "Reading affix file %s ..." msgstr "Legado de afiksa dosiero %s ..." -#: ../spell.c:4589 ../spell.c:5635 ../spell.c:6140 #, c-format msgid "Conversion failure for word in %s line %d: %s" msgstr "Malsukceso dum konverto de vorto en %s linio %d: %s" -#: ../spell.c:4630 ../spell.c:6170 #, c-format msgid "Conversion in %s not supported: from %s to %s" msgstr "Konverto en %s nesubtenata: de %s al %s" -#: ../spell.c:4642 +#, c-format +msgid "Conversion in %s not supported" +msgstr "Konverto en %s nesubtenata" + #, c-format msgid "Invalid value for FLAG in %s line %d: %s" msgstr "Nevalida valoro de FLAG en %s linio %d: %s" -#: ../spell.c:4655 #, c-format msgid "FLAG after using flags in %s line %d: %s" msgstr "FLAG post flagoj en %s linio %d: %s" -#: ../spell.c:4723 #, c-format msgid "" "Defining COMPOUNDFORBIDFLAG after PFX item may give wrong results in %s line " @@ -5381,7 +5162,6 @@ msgstr "" "Difino de COMPOUNDFORBIDFLAG post ano PFX povas doni neฤustajn rezultojn en " "%s linio %d" -#: ../spell.c:4731 #, c-format msgid "" "Defining COMPOUNDPERMITFLAG after PFX item may give wrong results in %s line " @@ -5390,42 +5170,34 @@ msgstr "" "Difino de COMPOUNDPERMITFLAG post ano PFX povas doni neฤustajn rezultojn en " "%s linio %d" -#: ../spell.c:4747 #, c-format msgid "Wrong COMPOUNDRULES value in %s line %d: %s" msgstr "Nevalida valoro de COMPOUNDRULES en %s linio %d: %s" -#: ../spell.c:4771 #, c-format msgid "Wrong COMPOUNDWORDMAX value in %s line %d: %s" msgstr "Nevalida valoro de COMPOUNDWORDMAX en %s linio %d: %s" -#: ../spell.c:4777 #, c-format msgid "Wrong COMPOUNDMIN value in %s line %d: %s" msgstr "Nevalida valoro de COMPOUNDMIN en %s linio %d: %s" -#: ../spell.c:4783 #, c-format msgid "Wrong COMPOUNDSYLMAX value in %s line %d: %s" msgstr "Nevalida valoro de COMPOUNDSYLMAX en %s linio %d: %s" -#: ../spell.c:4795 #, c-format msgid "Wrong CHECKCOMPOUNDPATTERN value in %s line %d: %s" msgstr "Nevalida valoro de CHECKCOMPOUNDPATTERN en %s linio %d: %s" -#: ../spell.c:4847 #, c-format msgid "Different combining flag in continued affix block in %s line %d: %s" msgstr "Malsama flago de kombino en daลญra bloko de afikso en %s linio %d: %s" -#: ../spell.c:4850 #, c-format msgid "Duplicate affix in %s line %d: %s" msgstr "Ripetita afikso en %s linio %d: %s" -#: ../spell.c:4871 #, c-format msgid "" "Affix also used for BAD/RARE/KEEPCASE/NEEDAFFIX/NEEDCOMPOUND/NOSUGGEST in %s " @@ -5434,308 +5206,206 @@ msgstr "" "Afikso ankaลญ uzata por BAD/RARE/KEEPCASE/NEEDAFFIX/NEEDCOMPOUND/NOSUGGEST en " "%s linio %d: %s" -#: ../spell.c:4893 #, c-format msgid "Expected Y or N in %s line %d: %s" msgstr "Y aลญ N atendita en %s linio %d: %s" -#: ../spell.c:4968 #, c-format msgid "Broken condition in %s line %d: %s" msgstr "Nevalida kondiฤo en %s linio %d: %s" -#: ../spell.c:5091 #, c-format msgid "Expected REP(SAL) count in %s line %d" msgstr "Neatendita nombro REP(SAL) en %s linio %d" -#: ../spell.c:5120 #, c-format msgid "Expected MAP count in %s line %d" msgstr "Neatendita nombro de MAPen %s linio %d" -#: ../spell.c:5132 #, c-format msgid "Duplicate character in MAP in %s line %d" msgstr "Ripetita signo en MAP en %s linio %d" -#: ../spell.c:5176 #, c-format msgid "Unrecognized or duplicate item in %s line %d: %s" msgstr "Neagnoskita aลญ ripetita ano en %s linio %d: %s" -#: ../spell.c:5197 #, c-format msgid "Missing FOL/LOW/UPP line in %s" msgstr "Mankas linio FOL/LOW/UPP en %s" -#: ../spell.c:5220 msgid "COMPOUNDSYLMAX used without SYLLABLE" msgstr "COMPOUNDSYLMAX uzita sen SYLLABLE" -#: ../spell.c:5236 msgid "Too many postponed prefixes" msgstr "Tro da prokrastitaj prefiksoj" -#: ../spell.c:5238 msgid "Too many compound flags" msgstr "Tro da kunmetitaj flagoj" -#: ../spell.c:5240 msgid "Too many postponed prefixes and/or compound flags" msgstr "Tro da prokrastitaj prefiksoj kaj/aลญ kunmetitaj flagoj" -#: ../spell.c:5250 #, c-format msgid "Missing SOFO%s line in %s" msgstr "Mankas SOFO%s-aj linioj en %s" -#: ../spell.c:5253 #, c-format msgid "Both SAL and SOFO lines in %s" msgstr "Ambaลญ SAL kaj SOFO linioj en %s" -#: ../spell.c:5331 #, c-format msgid "Flag is not a number in %s line %d: %s" msgstr "Flago ne estas nombro en %s linio %d: %s" -#: ../spell.c:5334 #, c-format msgid "Illegal flag in %s line %d: %s" msgstr "Nevalida flago en %s linio %d: %s" -#: ../spell.c:5493 ../spell.c:5501 #, c-format msgid "%s value differs from what is used in another .aff file" msgstr "Valoro de %s malsamas ol tiu en alia dosiero .aff" -#: ../spell.c:5602 #, c-format msgid "Reading dictionary file %s ..." msgstr "Legado de vortardosiero %s ..." -#: ../spell.c:5611 #, c-format msgid "E760: No word count in %s" msgstr "E760: Ne estas nombro de vortoj en %s" -#: ../spell.c:5669 #, c-format msgid "line %6d, word %6d - %s" msgstr "linio %6d, vorto %6d - %s" -#: ../spell.c:5691 #, c-format msgid "Duplicate word in %s line %d: %s" msgstr "Ripetita vorto en %s linio %d: %s" -#: ../spell.c:5694 #, c-format msgid "First duplicate word in %s line %d: %s" msgstr "Unua ripetita vorto en %s linio %d: %s" -#: ../spell.c:5746 #, c-format msgid "%d duplicate word(s) in %s" msgstr "%d ripetita(j) vorto(j) en %s" -#: ../spell.c:5748 #, c-format msgid "Ignored %d word(s) with non-ASCII characters in %s" msgstr "%d ignorita(j) vorto(j) kun neaskiaj signoj en %s" -#: ../spell.c:6115 #, c-format msgid "Reading word file %s ..." msgstr "Legado de dosiero de vortoj %s ..." -#: ../spell.c:6155 #, c-format msgid "Duplicate /encoding= line ignored in %s line %d: %s" msgstr "Ripetita linio /encoding= ignorita en %s linio %d: %s" -#: ../spell.c:6159 #, c-format msgid "/encoding= line after word ignored in %s line %d: %s" msgstr "Linio /encoding= post vorto ignorita en %s linio %d: %s" -#: ../spell.c:6180 #, c-format msgid "Duplicate /regions= line ignored in %s line %d: %s" msgstr "Ripetita linio /regions= ignorita en %s linio %d: %s" -#: ../spell.c:6185 #, c-format msgid "Too many regions in %s line %d: %s" msgstr "Tro da regionoj en %s linio %d: %s" -#: ../spell.c:6198 #, c-format msgid "/ line ignored in %s line %d: %s" msgstr "Linio / ignorita en %s linio %d: %s" -#: ../spell.c:6224 #, c-format msgid "Invalid region nr in %s line %d: %s" msgstr "Nevalida regiono nr en %s linio %d: %s" -#: ../spell.c:6230 #, c-format msgid "Unrecognized flags in %s line %d: %s" msgstr "Nekonata flago en %s linio %d: %s" -#: ../spell.c:6257 #, c-format msgid "Ignored %d words with non-ASCII characters" msgstr "Ignoris %d vorto(j)n kun neaskiaj signoj" -#: ../spell.c:6656 +msgid "E845: Insufficient memory, word list will be incomplete" +msgstr "E845: Ne sufiฤe da memoro, vortlisto estos nekompleta." + #, c-format msgid "Compressed %d of %d nodes; %d (%d%%) remaining" msgstr "Densigis %d de %d nodoj; %d (%d%%) restantaj" -#: ../spell.c:7340 msgid "Reading back spell file..." msgstr "Relegas la dosieron de literumo..." -#. Go through the trie of good words, soundfold each word and add it to -#. the soundfold trie. -#: ../spell.c:7357 +#. +#. * Go through the trie of good words, soundfold each word and add it to +#. * the soundfold trie. +#. msgid "Performing soundfolding..." msgstr "Fonetika analizado..." -#: ../spell.c:7368 #, c-format -msgid "Number of words after soundfolding: %<PRId64>" -msgstr "Nombro de vortoj post fonetika analizado: %<PRId64>" +msgid "Number of words after soundfolding: %ld" +msgstr "Nombro de vortoj post fonetika analizado: %ld" -#: ../spell.c:7476 #, c-format msgid "Total number of words: %d" msgstr "Totala nombro de vortoj: %d" -#: ../spell.c:7655 #, c-format msgid "Writing suggestion file %s ..." msgstr "Skribado de dosiero de sugesto %s ..." -#: ../spell.c:7707 ../spell.c:7927 #, c-format msgid "Estimated runtime memory use: %d bytes" msgstr "Evaluo de memoro uzata: %d bajtoj" -#: ../spell.c:7820 msgid "E751: Output file name must not have region name" msgstr "E751: Nomo de eliga dosiero ne devas havi nomon de regiono" -#: ../spell.c:7822 msgid "E754: Only up to 8 regions supported" msgstr "E754: Nur 8 regionoj subtenataj" -#: ../spell.c:7846 #, c-format msgid "E755: Invalid region in %s" msgstr "E755: Nevalida regiono en %s" -#: ../spell.c:7907 msgid "Warning: both compounding and NOBREAK specified" msgstr "Averto: ambaลญ NOBREAK kaj NOBREAK specifitaj" -#: ../spell.c:7920 #, c-format msgid "Writing spell file %s ..." msgstr "Skribado de literuma dosiero %s ..." -#: ../spell.c:7925 msgid "Done!" msgstr "Farita!" -#: ../spell.c:8034 #, c-format -msgid "E765: 'spellfile' does not have %<PRId64> entries" -msgstr "E765: 'spellfile' ne havas %<PRId64> rikordojn" +msgid "E765: 'spellfile' does not have %ld entries" +msgstr "E765: 'spellfile' ne havas %ld rikordojn" -#: ../spell.c:8074 -#, fuzzy, c-format +#, c-format msgid "Word '%.*s' removed from %s" -msgstr "Vorto fortirita el %s" +msgstr "Vorto '%.*s' fortirita el %s" -#: ../spell.c:8117 -#, fuzzy, c-format +#, c-format msgid "Word '%.*s' added to %s" -msgstr "Vorto aldonita al %s" +msgstr "Vorto '%.*s' aldonita al %s" -#: ../spell.c:8381 msgid "E763: Word characters differ between spell files" msgstr "E763: Signoj de vorto malsamas tra literumaj dosieroj" -#: ../spell.c:8684 -msgid "Sorry, no suggestions" -msgstr "Bedaลญrinde ne estas sugestoj" - -#: ../spell.c:8687 -#, c-format -msgid "Sorry, only %<PRId64> suggestions" -msgstr "Bedaลญrinde estas nur %<PRId64> sugestoj" - -#. for when 'cmdheight' > 1 -#. avoid more prompt -#: ../spell.c:8704 -#, c-format -msgid "Change \"%.*s\" to:" -msgstr "Anstataลญigi \"%.*s\" per:" - -#: ../spell.c:8737 -#, c-format -msgid " < \"%.*s\"" -msgstr " < \"%.*s\"" - -#: ../spell.c:8882 -msgid "E752: No previous spell replacement" -msgstr "E752: Neniu antaลญa literuma anstataลญigo" - -#: ../spell.c:8925 -#, c-format -msgid "E753: Not found: %s" -msgstr "E753: Netrovita: %s" - -#: ../spell.c:9276 -#, c-format -msgid "E778: This does not look like a .sug file: %s" -msgstr "E778: Tio ne ลajnas esti dosiero .sug: %s" - -#: ../spell.c:9282 -#, c-format -msgid "E779: Old .sug file, needs to be updated: %s" -msgstr "E779: Malnova dosiero .sug, bezonas ฤisdatigon: %s" - -#: ../spell.c:9286 -#, c-format -msgid "E780: .sug file is for newer version of Vim: %s" -msgstr "E780: Dosiero .sug estas por pli nova versio de Vim: %s" - -#: ../spell.c:9295 -#, c-format -msgid "E781: .sug file doesn't match .spl file: %s" -msgstr "E781: Dosiero .sug ne kongruas kun dosiero .spl: %s" - -#: ../spell.c:9305 -#, c-format -msgid "E782: error while reading .sug file: %s" -msgstr "E782: eraro dum legado de dosiero .sug: %s" - #. This should have been checked when generating the .spl -#. file. -#: ../spell.c:11575 +#. * file. msgid "E783: duplicate char in MAP entry" msgstr "E783: ripetita signo en rikordo MAP" -#: ../syntax.c:266 msgid "No Syntax items defined for this buffer" msgstr "Neniu sintaksa elemento difinita por tiu bufro" -#: ../syntax.c:3083 ../syntax.c:3104 ../syntax.c:3127 #, c-format msgid "E390: Illegal argument: %s" msgstr "E390: Nevalida argumento: %s" @@ -5743,28 +5413,22 @@ msgstr "E390: Nevalida argumento: %s" msgid "syntax iskeyword " msgstr "sintakso iskeyword " -#: ../syntax.c:3299 #, c-format msgid "E391: No such syntax cluster: %s" msgstr "E391: Nenia sintaksa fasko: %s" -#: ../syntax.c:3433 msgid "syncing on C-style comments" msgstr "sinkronigo per C-stilaj komentoj" -#: ../syntax.c:3439 msgid "no syncing" msgstr "neniu sinkronigo" -#: ../syntax.c:3441 msgid "syncing starts " msgstr "sinkronigo ekas " -#: ../syntax.c:3443 ../syntax.c:3506 msgid " lines before top line" msgstr " linioj antaลญ supra linio" -#: ../syntax.c:3448 msgid "" "\n" "--- Syntax sync items ---" @@ -5772,7 +5436,6 @@ msgstr "" "\n" "--- Eroj de sintaksa sinkronigo ---" -#: ../syntax.c:3452 msgid "" "\n" "syncing on items" @@ -5780,7 +5443,6 @@ msgstr "" "\n" "sinkronigo per eroj" -#: ../syntax.c:3457 msgid "" "\n" "--- Syntax items ---" @@ -5788,53 +5450,41 @@ msgstr "" "\n" "--- Sintakseroj ---" -#: ../syntax.c:3475 #, c-format msgid "E392: No such syntax cluster: %s" msgstr "E392: Nenia sintaksa fasko: %s" -#: ../syntax.c:3497 msgid "minimal " msgstr "minimuma " -#: ../syntax.c:3503 msgid "maximal " msgstr "maksimuma " -#: ../syntax.c:3513 msgid "; match " msgstr "; kongruo " -#: ../syntax.c:3515 msgid " line breaks" msgstr " liniavancoj" -#: ../syntax.c:4076 msgid "E395: contains argument not accepted here" msgstr "E395: La argumento \"contains\" ne akcepteblas tie" -#: ../syntax.c:4096 msgid "E844: invalid cchar value" msgstr "E844: nevalida valoro de cchar" -#: ../syntax.c:4107 msgid "E393: group[t]here not accepted here" msgstr "E393: La argumento \"group[t]here\" ne akcepteblas tie" -#: ../syntax.c:4126 #, c-format msgid "E394: Didn't find region item for %s" msgstr "E394: Ne trovis regionan elementon por %s" -#: ../syntax.c:4188 msgid "E397: Filename required" msgstr "E397: Dosiernomo bezonata" -#: ../syntax.c:4221 msgid "E847: Too many syntax includes" msgstr "E847: Tro da sintaksaj inkluzivoj" -#: ../syntax.c:4303 #, c-format msgid "E789: Missing ']': %s" msgstr "E789: Mankas ']': %s" @@ -5843,221 +5493,174 @@ msgstr "E789: Mankas ']': %s" msgid "E890: trailing char after ']': %s]%s" msgstr "E890: vosta signo post ']': %s]%s" -#: ../syntax.c:4531 #, c-format msgid "E398: Missing '=': %s" msgstr "E398: Mankas '=': %s" -#: ../syntax.c:4666 #, c-format msgid "E399: Not enough arguments: syntax region %s" msgstr "E399: Ne sufiฤaj argumentoj: sintaksa regiono %s" -#: ../syntax.c:4870 msgid "E848: Too many syntax clusters" msgstr "E848: Tro da sintaksaj grupoj" -#: ../syntax.c:4954 msgid "E400: No cluster specified" msgstr "E400: Neniu fasko specifita" -#. end delimiter not found -#: ../syntax.c:4986 #, c-format msgid "E401: Pattern delimiter not found: %s" msgstr "E401: Disigilo de ลablono netrovita: %s" -#: ../syntax.c:5049 #, c-format msgid "E402: Garbage after pattern: %s" msgstr "E402: Forฤตetindaฤตo post ลablono: %s" -#: ../syntax.c:5120 msgid "E403: syntax sync: line continuations pattern specified twice" msgstr "E403: sintaksa sinkronigo: ลablono de linia daลญrigo specifita dufoje" -#: ../syntax.c:5169 #, c-format msgid "E404: Illegal arguments: %s" msgstr "E404: Nevalidaj argumentoj: %s" -#: ../syntax.c:5217 #, c-format msgid "E405: Missing equal sign: %s" msgstr "E405: Mankas egalsigno: %s" -#: ../syntax.c:5222 #, c-format msgid "E406: Empty argument: %s" msgstr "E406: Malplena argumento: %s" -#: ../syntax.c:5240 #, c-format msgid "E407: %s not allowed here" msgstr "E407: %s ne estas permesebla tie" -#: ../syntax.c:5246 #, c-format msgid "E408: %s must be first in contains list" msgstr "E408: %s devas esti la unua ano de la listo \"contains\"" -#: ../syntax.c:5304 #, c-format msgid "E409: Unknown group name: %s" msgstr "E409: Nekonata nomo de grupo: %s" -#: ../syntax.c:5512 #, c-format msgid "E410: Invalid :syntax subcommand: %s" msgstr "E410: Nevalida \":syntax\" subkomando: %s" -#: ../syntax.c:5854 msgid "" " TOTAL COUNT MATCH SLOWEST AVERAGE NAME PATTERN" msgstr "" +" TOTALO NOMBRO KONGRUO PLEJ MALRAPID MEZA NOMO ลABLONO" -#: ../syntax.c:6146 msgid "E679: recursive loop loading syncolor.vim" msgstr "E679: rekursia buklo dum ลargo de syncolor.vim" -#: ../syntax.c:6256 #, c-format msgid "E411: highlight group not found: %s" msgstr "E411: emfaza grupo netrovita: %s" -#: ../syntax.c:6278 #, c-format msgid "E412: Not enough arguments: \":highlight link %s\"" msgstr "E412: Ne sufiฤaj argumentoj: \":highlight link %s\"" -#: ../syntax.c:6284 #, c-format msgid "E413: Too many arguments: \":highlight link %s\"" -msgstr "E413: Tro argumentoj: \":highlight link %s\"" +msgstr "E413: Tro da argumentoj: \":highlight link %s\"" -#: ../syntax.c:6302 msgid "E414: group has settings, highlight link ignored" msgstr "E414: grupo havas agordojn, ligilo de emfazo ignorita" -#: ../syntax.c:6367 #, c-format msgid "E415: unexpected equal sign: %s" msgstr "E415: neatendita egalsigno: %s" -#: ../syntax.c:6395 #, c-format msgid "E416: missing equal sign: %s" msgstr "E416: mankas egalsigno: %s" -#: ../syntax.c:6418 #, c-format msgid "E417: missing argument: %s" msgstr "E417: mankas argumento: %s" -#: ../syntax.c:6446 #, c-format msgid "E418: Illegal value: %s" msgstr "E418: Nevalida valoro: %s" -#: ../syntax.c:6496 msgid "E419: FG color unknown" msgstr "E419: Nekonata malfona koloro" -#: ../syntax.c:6504 msgid "E420: BG color unknown" msgstr "E420: Nekonata fona koloro" -#: ../syntax.c:6564 #, c-format msgid "E421: Color name or number not recognized: %s" msgstr "E421: Kolora nomo aลญ nombro nerekonita: %s" -#: ../syntax.c:6714 #, c-format msgid "E422: terminal code too long: %s" msgstr "E422: kodo de terminalo estas tro longa: %s" -#: ../syntax.c:6753 #, c-format msgid "E423: Illegal argument: %s" msgstr "E423: Nevalida argumento: %s" -#: ../syntax.c:6925 msgid "E424: Too many different highlighting attributes in use" msgstr "E424: Tro da malsamaj atributoj de emfazo uzataj" -#: ../syntax.c:7427 msgid "E669: Unprintable character in group name" msgstr "E669: Nepresebla signo en nomo de grupo" -#: ../syntax.c:7434 msgid "W18: Invalid character in group name" msgstr "W18: Nevalida signo en nomo de grupo" -#: ../syntax.c:7448 msgid "E849: Too many highlight and syntax groups" msgstr "E849: Tro da emfazaj kaj sintaksaj grupoj" -#: ../tag.c:104 msgid "E555: at bottom of tag stack" msgstr "E555: ฤe subo de stako de etikedoj" -#: ../tag.c:105 msgid "E556: at top of tag stack" msgstr "E556: ฤe supro de stako de etikedoj" -#: ../tag.c:380 msgid "E425: Cannot go before first matching tag" msgstr "E425: Ne eblas iri antaลญ la unuan kongruan etikedon" -#: ../tag.c:504 #, c-format msgid "E426: tag not found: %s" msgstr "E426: etikedo netrovita: %s" # DP: "pri" estas "priority" -#: ../tag.c:528 msgid " # pri kind tag" msgstr "nro pri tipo etikedo" -#: ../tag.c:531 msgid "file\n" msgstr "dosiero\n" -#: ../tag.c:829 msgid "E427: There is only one matching tag" msgstr "E427: Estas nur unu kongrua etikedo" -#: ../tag.c:831 msgid "E428: Cannot go beyond last matching tag" msgstr "E428: Ne eblas iri preter lastan kongruan etikedon" -#: ../tag.c:850 #, c-format msgid "File \"%s\" does not exist" msgstr "La dosiero \"%s\" ne ekzistas" #. Give an indication of the number of matching tags -#: ../tag.c:859 #, c-format msgid "tag %d of %d%s" msgstr "etikedo %d de %d%s" -#: ../tag.c:862 msgid " or more" msgstr " aลญ pli" -#: ../tag.c:864 msgid " Using tag with different case!" msgstr " Uzo de etikedo kun malsama uskleco!" -#: ../tag.c:909 #, c-format msgid "E429: File \"%s\" does not exist" msgstr "E429: Dosiero \"%s\" ne ekzistas" #. Highlight title -#: ../tag.c:960 msgid "" "\n" " # TO tag FROM line in file/text" @@ -6065,79 +5668,66 @@ msgstr "" "\n" "nro AL etikedo DE linio en dosiero/teksto" -#: ../tag.c:1303 #, c-format msgid "Searching tags file %s" msgstr "Serฤado de dosiero de etikedoj %s" -#: ../tag.c:1545 +#, c-format +msgid "E430: Tag file path truncated for %s\n" +msgstr "E430: Vojo de etikeda dosiero trunkita por %s\n" + msgid "Ignoring long line in tags file" msgstr "Ignoro de longa linio en etikeda dosiero" -#: ../tag.c:1915 #, c-format msgid "E431: Format error in tags file \"%s\"" msgstr "E431: Eraro de formato en etikeda dosiero \"%s\"" -#: ../tag.c:1917 #, c-format -msgid "Before byte %<PRId64>" -msgstr "Antaลญ bajto %<PRId64>" +msgid "Before byte %ld" +msgstr "Antaลญ bajto %ld" -#: ../tag.c:1929 #, c-format msgid "E432: Tags file not sorted: %s" msgstr "E432: Etikeda dosiero ne estas ordigita: %s" #. never opened any tags file -#: ../tag.c:1960 msgid "E433: No tags file" msgstr "E433: Neniu etikeda dosiero" -#: ../tag.c:2536 msgid "E434: Can't find tag pattern" msgstr "E434: Ne eblas trovi ลablonon de etikedo" -#: ../tag.c:2544 msgid "E435: Couldn't find tag, just guessing!" msgstr "E435: Ne eblis trovi etikedon, nur divenas!" -#: ../tag.c:2797 #, c-format msgid "Duplicate field name: %s" msgstr "Ripetita kamponomo: %s" -#: ../term.c:1442 msgid "' not known. Available builtin terminals are:" msgstr "' nekonata. Haveblaj terminaloj estas:" -#: ../term.c:1463 msgid "defaulting to '" msgstr "defaลญlto al '" -#: ../term.c:1731 msgid "E557: Cannot open termcap file" msgstr "E557: Ne eblas malfermi la dosieron termcap" -#: ../term.c:1735 msgid "E558: Terminal entry not found in terminfo" msgstr "E558: Ne trovis rikordon de terminalo terminfo" -#: ../term.c:1737 msgid "E559: Terminal entry not found in termcap" msgstr "E559: Ne trovis rikordon de terminalo en termcap" -#: ../term.c:1878 #, c-format msgid "E436: No \"%s\" entry in termcap" msgstr "E436: Neniu rikordo \"%s\" en termcap" -#: ../term.c:2249 msgid "E437: terminal capability \"cm\" required" msgstr "E437: kapablo de terminalo \"cm\" bezonata" #. Highlight title -#: ../term.c:4376 msgid "" "\n" "--- Terminal keys ---" @@ -6145,169 +5735,339 @@ msgstr "" "\n" "--- Klavoj de terminalo ---" -#: ../ui.c:481 +msgid "Cannot open $VIMRUNTIME/rgb.txt" +msgstr "Ne povas malfermi $VIMRUNTIME/rgb.txt" + +msgid "new shell started\n" +msgstr "nova ลelo lanฤita\n" + msgid "Vim: Error reading input, exiting...\n" msgstr "Vim: Eraro dum legado de eniro, elironta...\n" +msgid "Used CUT_BUFFER0 instead of empty selection" +msgstr "Uzis CUT_BUFFER0 anstataลญ malplenan apartigon" + #. This happens when the FileChangedRO autocommand changes the #. * file in a way it becomes shorter. -#: ../undo.c:379 -#, fuzzy msgid "E881: Line count changed unexpectedly" -msgstr "E834: Nombro de linioj ลanฤiฤis neatendite" +msgstr "E881: Nombro de linioj ลanฤiฤis neatendite" + +#. must display the prompt +msgid "No undo possible; continue anyway" +msgstr "Malfaro neebla; tamen daลญrigi" -#: ../undo.c:627 #, c-format msgid "E828: Cannot open undo file for writing: %s" msgstr "E828: Ne eblas malfermi la malfaran dosieron por skribi: %s" -#: ../undo.c:717 #, c-format msgid "E825: Corrupted undo file (%s): %s" msgstr "E825: Difektita malfara dosiero (%s): %s" -#: ../undo.c:1039 msgid "Cannot write undo file in any directory in 'undodir'" msgstr "Ne eblis skribi malfaran dosieron en iu dosiero ajn de 'undodir'" -#: ../undo.c:1074 #, c-format msgid "Will not overwrite with undo file, cannot read: %s" msgstr "Ne superskribos malfaran dosieron, ne eblis legi: %s" -#: ../undo.c:1092 #, c-format msgid "Will not overwrite, this is not an undo file: %s" msgstr "Ne superskribos, tio ne estas malfara dosiero: %s" -#: ../undo.c:1108 msgid "Skipping undo file write, nothing to undo" msgstr "Preterpasas skribon de malfara dosiero, nenio por malfari" -#: ../undo.c:1121 #, c-format msgid "Writing undo file: %s" msgstr "Skribas malfaran dosieron: %s" -#: ../undo.c:1213 #, c-format msgid "E829: write error in undo file: %s" msgstr "E829: Skriberaro en malfara dosiero: %s" -#: ../undo.c:1280 #, c-format msgid "Not reading undo file, owner differs: %s" msgstr "Ne legas malfaran dosieron, posedanto malsamas: %s" -#: ../undo.c:1292 #, c-format msgid "Reading undo file: %s" msgstr "Legado de malfara dosiero: %s" -#: ../undo.c:1299 #, c-format msgid "E822: Cannot open undo file for reading: %s" msgstr "E822: Ne eblas malfermi malfaran dosieron por legi: %s" -#: ../undo.c:1308 #, c-format msgid "E823: Not an undo file: %s" msgstr "E823: Ne estas malfara dosiero: %s" -#: ../undo.c:1313 +#, c-format +msgid "E832: Non-encrypted file has encrypted undo file: %s" +msgstr "E832: Ne ฤifrata dosiero havas ฤifratan malfaran dosieron: %s" + +#, c-format +msgid "E826: Undo file decryption failed: %s" +msgstr "E826: Malฤifrado de malfara dosiero malsukcesis: %s" + +#, c-format +msgid "E827: Undo file is encrypted: %s" +msgstr "E827: Malfara dosiero estas ฤifrata: %s" + #, c-format msgid "E824: Incompatible undo file: %s" msgstr "E824: Malkongrua malfara dosiero: %s" -#: ../undo.c:1328 msgid "File contents changed, cannot use undo info" msgstr "Enhavo de dosiero ลanฤiฤis, ne eblas uzi malfarajn informojn" -#: ../undo.c:1497 #, c-format msgid "Finished reading undo file %s" msgstr "Finis legi malfaran dosieron %s" -#: ../undo.c:1586 ../undo.c:1812 msgid "Already at oldest change" msgstr "Jam al la plej malnova ลanฤo" -#: ../undo.c:1597 ../undo.c:1814 msgid "Already at newest change" msgstr "Jam al la plej nova ลanฤo" -#: ../undo.c:1806 #, c-format -msgid "E830: Undo number %<PRId64> not found" -msgstr "E830: Malfara numero %<PRId64> netrovita" +msgid "E830: Undo number %ld not found" +msgstr "E830: Malfara numero %ld netrovita" -#: ../undo.c:1979 msgid "E438: u_undo: line numbers wrong" msgstr "E438: u_undo: nevalidaj numeroj de linioj" -#: ../undo.c:2183 msgid "more line" msgstr "plia linio" -#: ../undo.c:2185 msgid "more lines" msgstr "pliaj linioj" -#: ../undo.c:2187 msgid "line less" msgstr "malpli linio" -#: ../undo.c:2189 msgid "fewer lines" msgstr "malpli linioj" -#: ../undo.c:2193 msgid "change" msgstr "ลanฤo" -#: ../undo.c:2195 msgid "changes" msgstr "ลanฤoj" -#: ../undo.c:2225 #, c-format -msgid "%<PRId64> %s; %s #%<PRId64> %s" -msgstr "%<PRId64> %s; %s #%<PRId64> %s" +msgid "%ld %s; %s #%ld %s" +msgstr "%ld %s; %s #%ld %s" -#: ../undo.c:2228 msgid "before" msgstr "antaลญ" -#: ../undo.c:2228 msgid "after" msgstr "post" -#: ../undo.c:2325 msgid "Nothing to undo" msgstr "Nenio por malfari" -#: ../undo.c:2330 msgid "number changes when saved" msgstr "numero ลanฤoj tempo konservita" -#: ../undo.c:2360 #, c-format -msgid "%<PRId64> seconds ago" -msgstr "antaลญ %<PRId64> sekundoj" +msgid "%ld seconds ago" +msgstr "antaลญ %ld sekundoj" -#: ../undo.c:2372 msgid "E790: undojoin is not allowed after undo" msgstr "E790: undojoin estas nepermesebla post malfaro" -#: ../undo.c:2466 msgid "E439: undo list corrupt" msgstr "E439: listo de malfaro estas difekta" -#: ../undo.c:2495 msgid "E440: undo line missing" msgstr "E440: linio de malfaro mankas" -#: ../version.c:600 +#, c-format +msgid "E122: Function %s already exists, add ! to replace it" +msgstr "E122: La funkcio %s jam ekzistas (aldonu ! por anstataลญigi ฤin)" + +msgid "E717: Dictionary entry already exists" +msgstr "E717: Rikordo de vortaro jam ekzistas" + +msgid "E718: Funcref required" +msgstr "E718: Funcref bezonata" + +#, c-format +msgid "E130: Unknown function: %s" +msgstr "E130: Nekonata funkcio: %s" + +#, c-format +msgid "E125: Illegal argument: %s" +msgstr "E125: Nevalida argumento: %s" + +#, c-format +msgid "E853: Duplicate argument name: %s" +msgstr "E853: Ripetita nomo de argumento: %s" + +#, c-format +msgid "E740: Too many arguments for function %s" +msgstr "E740: Tro da argumentoj por funkcio: %s" + +#, c-format +msgid "E116: Invalid arguments for function %s" +msgstr "E116: Nevalidaj argumentoj por funkcio: %s" + +msgid "E132: Function call depth is higher than 'maxfuncdepth'" +msgstr "E132: Profundo de funkcia alvoko superas 'maxfuncdepth'" + +#, c-format +msgid "calling %s" +msgstr "alvokas %s" + +#, c-format +msgid "%s aborted" +msgstr "%s ฤesigita" + +#, c-format +msgid "%s returning #%ld" +msgstr "%s liveras #%ld" + +#, c-format +msgid "%s returning %s" +msgstr "%s liveras %s" + +msgid "E699: Too many arguments" +msgstr "E699: Tro da argumentoj" + +#, c-format +msgid "E117: Unknown function: %s" +msgstr "E117: Nekonata funkcio: %s" + +#, c-format +msgid "E933: Function was deleted: %s" +msgstr "E933: funkcio estis forviลita: %s" + +#, c-format +msgid "E119: Not enough arguments for function: %s" +msgstr "E119: Ne sufiฤe da argumentoj por funkcio: %s" + +#, c-format +msgid "E120: Using <SID> not in a script context: %s" +msgstr "E120: <SID> estas uzata ekster kunteksto de skripto: %s" + +#, c-format +msgid "E725: Calling dict function without Dictionary: %s" +msgstr "E725: Alvoko de funkcio dict sen Vortaro: %s" + +msgid "E129: Function name required" +msgstr "E129: Nomo de funkcio bezonata" + +#, c-format +msgid "E128: Function name must start with a capital or \"s:\": %s" +msgstr "E128: Nomo de funkcio devas eki per majusklo aลญ per \"s:\": %s" + +#, c-format +msgid "E884: Function name cannot contain a colon: %s" +msgstr "E884: Nomo de funkcio ne povas enhavi dupunkton: %s" + +#, c-format +msgid "E123: Undefined function: %s" +msgstr "E123: Nedifinita funkcio: %s" + +#, c-format +msgid "E124: Missing '(': %s" +msgstr "E124: Mankas '(': %s" + +msgid "E862: Cannot use g: here" +msgstr "E862: Ne eblas uzi g: ฤi tie" + +#, c-format +msgid "E932: Closure function should not be at top level: %s" +msgstr "E932: Fermo-funkcio devus esti je la plej alta nivelo: %s" + +msgid "E126: Missing :endfunction" +msgstr "E126: Mankas \":endfunction\"" + +#, c-format +msgid "E707: Function name conflicts with variable: %s" +msgstr "E707: Nomo de funkcio konfliktas kun variablo: %s" + +#, c-format +msgid "E127: Cannot redefine function %s: It is in use" +msgstr "E127: Ne eblas redifini funkcion %s: Estas nuntempe uzata" + +#, c-format +msgid "E746: Function name does not match script file name: %s" +msgstr "E746: Nomo de funkcio ne kongruas kun dosiernomo de skripto: %s" + +#, c-format +msgid "E131: Cannot delete function %s: It is in use" +msgstr "E131: Ne eblas forviลi funkcion %s: Estas nuntempe uzata" + +msgid "E133: :return not inside a function" +msgstr "E133: \":return\" ekster funkcio" + +#, c-format +msgid "E107: Missing parentheses: %s" +msgstr "E107: Mankas krampoj: %s" + +msgid "" +"\n" +"MS-Windows 64-bit GUI version" +msgstr "" +"\n" +"Grafika versio MS-Vindozo 64-bitoj" + +msgid "" +"\n" +"MS-Windows 32-bit GUI version" +msgstr "" +"\n" +"Grafika versio MS-Vindozo 32-bitoj" + +msgid " with OLE support" +msgstr " kun subteno de OLE" + +msgid "" +"\n" +"MS-Windows 64-bit console version" +msgstr "" +"\n" +"Versio konzola MS-Vindozo 64-bitoj" + +msgid "" +"\n" +"MS-Windows 32-bit console version" +msgstr "" +"\n" +"Versio konzola MS-Vindozo 32-bitoj" + +msgid "" +"\n" +"MacOS X (unix) version" +msgstr "" +"\n" +"Versio Mak OS X (unikso)" + +msgid "" +"\n" +"MacOS X version" +msgstr "" +"\n" +"Versio Mak OS X" + +msgid "" +"\n" +"MacOS version" +msgstr "" +"\n" +"Versio Mak OS" + +msgid "" +"\n" +"OpenVMS version" +msgstr "" +"\n" +"Versio OpenVMS" + msgid "" "\n" "Included patches: " @@ -6315,7 +6075,6 @@ msgstr "" "\n" "Flikaฤตoj inkluzivitaj: " -#: ../version.c:627 msgid "" "\n" "Extra patches: " @@ -6323,11 +6082,9 @@ msgstr "" "\n" "Ekstraj flikaฤตoj: " -#: ../version.c:639 ../version.c:864 msgid "Modified by " msgstr "Modifita de " -#: ../version.c:646 msgid "" "\n" "Compiled " @@ -6335,11 +6092,9 @@ msgstr "" "\n" "Kompilita " -#: ../version.c:649 msgid "by " msgstr "de " -#: ../version.c:660 msgid "" "\n" "Huge version " @@ -6347,1903 +6102,936 @@ msgstr "" "\n" "Grandega versio " -#: ../version.c:661 +msgid "" +"\n" +"Big version " +msgstr "" +"\n" +"Granda versio " + +msgid "" +"\n" +"Normal version " +msgstr "" +"\n" +"Normala versio " + +msgid "" +"\n" +"Small version " +msgstr "" +"\n" +"Malgranda versio " + +msgid "" +"\n" +"Tiny version " +msgstr "" +"\n" +"Malgrandega versio " + msgid "without GUI." msgstr "sen grafika interfaco." -#: ../version.c:662 +msgid "with GTK3 GUI." +msgstr "kun grafika interfaco GTK3." + +msgid "with GTK2-GNOME GUI." +msgstr "kun grafika interfaco GTK2-GNOME." + +msgid "with GTK2 GUI." +msgstr "kun grafika interfaco GTK2." + +msgid "with X11-Motif GUI." +msgstr "kun grafika interfaco X11-Motif." + +msgid "with X11-neXtaw GUI." +msgstr "kun grafika interfaco X11-neXtaw." + +msgid "with X11-Athena GUI." +msgstr "kun grafika interfaco X11-Athena." + +msgid "with Photon GUI." +msgstr "kun grafika interfaco Photon." + +msgid "with GUI." +msgstr "sen grafika interfaco." + +msgid "with Carbon GUI." +msgstr "kun grafika interfaco Carbon." + +msgid "with Cocoa GUI." +msgstr "kun grafika interfaco Cocoa." + +msgid "with (classic) GUI." +msgstr "kun (klasika) grafika interfaco." + msgid " Features included (+) or not (-):\n" msgstr " Ebloj inkluzivitaj (+) aลญ ne (-):\n" -#: ../version.c:667 msgid " system vimrc file: \"" msgstr " sistema dosiero vimrc: \"" -#: ../version.c:672 msgid " user vimrc file: \"" msgstr " dosiero vimrc de uzanto: \"" -#: ../version.c:677 msgid " 2nd user vimrc file: \"" msgstr " 2-a dosiero vimrc de uzanto: \"" -#: ../version.c:682 msgid " 3rd user vimrc file: \"" msgstr " 3-a dosiero vimrc de uzanto: \"" -#: ../version.c:687 msgid " user exrc file: \"" msgstr " dosiero exrc de uzanto: \"" -#: ../version.c:692 msgid " 2nd user exrc file: \"" msgstr " 2-a dosiero exrc de uzanto: \"" -#: ../version.c:699 +msgid " system gvimrc file: \"" +msgstr " sistema dosiero gvimrc: \"" + +msgid " user gvimrc file: \"" +msgstr " dosiero gvimrc de uzanto: \"" + +msgid "2nd user gvimrc file: \"" +msgstr " 2-a dosiero gvimrc de uzanto: \"" + +msgid "3rd user gvimrc file: \"" +msgstr " 3-a dosiero gvimrc de uzanto: \"" + +msgid " defaults file: \"" +msgstr " dosiero de defaลญltoj: \"" + +msgid " system menu file: \"" +msgstr " dosiero de sistema menuo: \"" + msgid " fall-back for $VIM: \"" msgstr " defaลญlto de $VIM: \"" -#: ../version.c:705 msgid " f-b for $VIMRUNTIME: \"" msgstr " defaลญlto de VIMRUNTIME: \"" -#: ../version.c:709 msgid "Compilation: " msgstr "Kompilado: " -#: ../version.c:712 +msgid "Compiler: " +msgstr "Kompililo: " + msgid "Linking: " msgstr "Ligado: " -#: ../version.c:717 msgid " DEBUG BUILD" msgstr " SENCIMIGA MUNTO" -#: ../version.c:767 msgid "VIM - Vi IMproved" msgstr "VIM - Vi plibonigita" -#: ../version.c:769 msgid "version " msgstr "versio " # DP: vidu http://www.thefreedictionary.com/et+al. -#: ../version.c:770 msgid "by Bram Moolenaar et al." msgstr "de Bram Moolenaar kaj aliuloj" -#: ../version.c:774 msgid "Vim is open source and freely distributable" msgstr "Vim estas libera programo kaj disdoneblas libere" -#: ../version.c:776 msgid "Help poor children in Uganda!" msgstr "Helpu malriฤajn infanojn en Ugando!" # DP: atentu al la spacetoj: ฤiuj ฤenoj devas havi la saman longon -#: ../version.c:777 msgid "type :help iccf<Enter> for information " msgstr "tajpu :help iccf<Enenklavo> por pliaj informoj " # DP: atentu al la spacetoj: ฤiuj ฤenoj devas havi la saman longon -#: ../version.c:779 msgid "type :q<Enter> to exit " msgstr "tajpu :q<Enenklavo> por eliri " # DP: atentu al la spacetoj: ฤiuj ฤenoj devas havi la saman longon -#: ../version.c:780 msgid "type :help<Enter> or <F1> for on-line help" msgstr "tajpu :help<Enenklavo> aลญ <F1> por aliri la helpon " # DP: atentu al la spacetoj: ฤiuj ฤenoj devas havi la saman longon -#: ../version.c:781 -msgid "type :help version7<Enter> for version info" -msgstr "tajpu :help version7<Enenklavo> por informo de versio" +msgid "type :help version8<Enter> for version info" +msgstr "tajpu :help version8<Enenklavo> por informo de versio" -#: ../version.c:784 msgid "Running in Vi compatible mode" msgstr "Ruliฤas en reฤimo kongrua kun Vi" # DP: atentu al la spacetoj: ฤiuj ฤenoj devas havi la saman longon -#: ../version.c:785 msgid "type :set nocp<Enter> for Vim defaults" msgstr "tajpu :set nocp<Enenklavo> por Vim defaลญltoj " # DP: atentu al la spacetoj: ฤiuj ฤenoj devas havi la saman longon -#: ../version.c:786 msgid "type :help cp-default<Enter> for info on this" msgstr "tajpu :help cp-default<Enenklavo> por pliaj informoj " -#: ../version.c:827 +# DP: atentu al la spacetoj: ฤiuj ฤenoj devas havi la saman longon +msgid "menu Help->Orphans for information " +msgstr "menuo Help->Orfinoj por pliaj informoj " + +msgid "Running modeless, typed text is inserted" +msgstr "Ruliฤas senreฤime, tajpita teksto estas enmetita" + +# DP: atentu al la spacetoj: ฤiuj ฤenoj devas havi la saman longon +msgid "menu Edit->Global Settings->Toggle Insert Mode " +msgstr "menuo Redakti->Mallokaj Agordoj->Baskuligi Enmetan Reฤimon" + +# DP: atentu al la spacetoj: ฤiuj ฤenoj devas havi la saman longon +msgid " for two modes " +msgstr " por du reฤimoj " + +# DP: tiu ฤeno pli longas (mi ne volas igi ฤiujn aliajn ฤenojn +# pli longajn) +msgid "menu Edit->Global Settings->Toggle Vi Compatible" +msgstr "menuo Redakti->Mallokaj Agordoj->Baskuligi Reฤimon Kongruan kun Vi" + +# DP: atentu al la spacetoj: ฤiuj ฤenoj devas havi la saman longon +msgid " for Vim defaults " +msgstr " por defaลญltoj de Vim " + msgid "Sponsor Vim development!" msgstr "Subtenu la programadon de Vim!" -#: ../version.c:828 msgid "Become a registered Vim user!" msgstr "Iฤu registrita uzanto de Vim!" # DP: atentu al la spacetoj: ฤiuj ฤenoj devas havi la saman longon -#: ../version.c:831 msgid "type :help sponsor<Enter> for information " msgstr "tajpu :help sponsor<Enenklavo> por pliaj informoj " # DP: atentu al la spacetoj: ฤiuj ฤenoj devas havi la saman longon -#: ../version.c:832 msgid "type :help register<Enter> for information " msgstr "tajpu :help register<Enenklavo> por pliaj informoj " # DP: atentu al la spacetoj: ฤiuj ฤenoj devas havi la saman longon -#: ../version.c:834 msgid "menu Help->Sponsor/Register for information " msgstr "menuo Helpo->Subteni/Registri por pliaj informoj " -#: ../window.c:119 msgid "Already only one window" msgstr "Jam nur unu fenestro" -#: ../window.c:224 msgid "E441: There is no preview window" msgstr "E441: Ne estas antaลญvida fenestro" -#: ../window.c:559 msgid "E442: Can't split topleft and botright at the same time" msgstr "E442: Ne eblas dividi supralivan kaj subdekstran samtempe" -#: ../window.c:1228 msgid "E443: Cannot rotate when another window is split" msgstr "E443: Ne eblas rotacii kiam alia fenestro estas dividita" -#: ../window.c:1803 msgid "E444: Cannot close last window" msgstr "E444: Ne eblas fermi la lastan fenestron" -#: ../window.c:1810 msgid "E813: Cannot close autocmd window" msgstr "E813: Ne eblas fermi la fenestron de aลญtokomandoj" -#: ../window.c:1814 msgid "E814: Cannot close window, only autocmd window would remain" msgstr "E814: Ne eblas fermi fenestron, nur la fenestro de aลญtokomandoj restus" -#: ../window.c:2717 msgid "E445: Other window contains changes" msgstr "E445: La alia fenestro enhavas ลanฤojn" -#: ../window.c:4805 msgid "E446: No file name under cursor" msgstr "E446: Neniu dosiernomo sub la kursoro" -#~ msgid "E831: bf_key_init() called with empty password" -#~ msgstr "E831: bf_key_init() alvokita kun malplena pasvorto" - -#~ msgid "E820: sizeof(uint32_t) != 4" -#~ msgstr "E820: sizeof(uint32_t) != 4" - -#~ msgid "E817: Blowfish big/little endian use wrong" -#~ msgstr "E817: Misuzo de pezkomenca/pezfina en blowfish" - -#~ msgid "E818: sha256 test failed" -#~ msgstr "E818: Testo de sha256 fiaskis" - -#~ msgid "E819: Blowfish test failed" -#~ msgstr "E819: Testo de blowfish fiaskis" - -#~ msgid "Patch file" -#~ msgstr "Flika dosiero" - -#~ msgid "" -#~ "&OK\n" -#~ "&Cancel" -#~ msgstr "" -#~ "&Bone\n" -#~ "&Rezigni" - -#~ msgid "E240: No connection to Vim server" -#~ msgstr "E240: Neniu konekto al Vim-servilo" - -#~ msgid "E241: Unable to send to %s" -#~ msgstr "E241: Ne eblas sendi al %s" - -#~ msgid "E277: Unable to read a server reply" -#~ msgstr "E277: Ne eblas legi respondon de servilo" - -#~ msgid "E258: Unable to send to client" -#~ msgstr "E258: Ne eblas sendi al kliento" - -#~ msgid "Save As" -#~ msgstr "Konservi kiel" - -#~ msgid "Edit File" -#~ msgstr "Redakti dosieron" - -#~ msgid " (NOT FOUND)" -#~ msgstr " (NETROVITA)" - -#~ msgid "Source Vim script" -#~ msgstr "Ruli Vim-skripton" - -#~ msgid "unknown" -#~ msgstr "nekonata" - -#~ msgid "Edit File in new window" -#~ msgstr "Redakti Dosieron en nova fenestro" - -#~ msgid "Append File" -#~ msgstr "Postaldoni dosieron" - -#~ msgid "Window position: X %d, Y %d" -#~ msgstr "Pozicio de fenestro: X %d, Y %d" - -#~ msgid "Save Redirection" -#~ msgstr "Konservi alidirekton" - -# DP: mi ne certas pri superflugo -#~ msgid "Save View" -#~ msgstr "Konservi superflugon" - -#~ msgid "Save Session" -#~ msgstr "Konservi seancon" - -#~ msgid "Save Setup" -#~ msgstr "Konservi agordaron" - -#~ msgid "E809: #< is not available without the +eval feature" -#~ msgstr "E809: #< ne haveblas sen la eblo +eval" - -#~ msgid "E196: No digraphs in this version" -#~ msgstr "E196: Neniu duliteraฤตo en tiu versio" - -#~ msgid "is a device (disabled with 'opendevice' option)" -#~ msgstr "estas aparatdosiero (malลaltita per la opcio 'opendevice')" - -#~ msgid "Reading from stdin..." -#~ msgstr "Legado el stdin..." - -#~ msgid "[crypted]" -#~ msgstr "[ฤifrita]" - -#~ msgid "E821: File is encrypted with unknown method" -#~ msgstr "E821: Dosiero estas ฤifrata per nekonata metodo" - -#~ msgid "Warning: Using a weak encryption method; see :help 'cm'" -#~ msgstr "Averto: uzo de malfortika ฤifrada metodo; vidu :help 'cm'" - -#~ msgid "NetBeans disallows writes of unmodified buffers" -#~ msgstr "NetBeans malpermesas skribojn de neลanฤitaj bufroj" - -#~ msgid "Partial writes disallowed for NetBeans buffers" -#~ msgstr "Partaj skriboj malpermesitaj ฤe bufroj NetBeans" - -#~ msgid "writing to device disabled with 'opendevice' option" -#~ msgstr "skribo al aparatdosiero malลaltita per la opcio 'opendevice'" - -#~ msgid "E460: The resource fork would be lost (add ! to override)" -#~ msgstr "E460: La rimeda forko estus perdita (aldonu ! por transpasi)" - -#~ msgid "E851: Failed to create a new process for the GUI" -#~ msgstr "E851: Ne sukcesis krei novan procezon por la grafika interfaco" - -#~ msgid "E852: The child process failed to start the GUI" -#~ msgstr "E852: La ida procezo ne sukcesis startigi la grafikan interfacon" - -#~ msgid "E229: Cannot start the GUI" -#~ msgstr "E229: Ne eblas lanฤi la grafikan interfacon" - -#~ msgid "E230: Cannot read from \"%s\"" -#~ msgstr "E230: Ne eblas legi el \"%s\"" - -#~ msgid "E665: Cannot start GUI, no valid font found" -#~ msgstr "" -#~ "E665: Ne eblas startigi grafikan interfacon, neniu valida tiparo trovita" - -#~ msgid "E231: 'guifontwide' invalid" -#~ msgstr "E231: 'guifontwide' nevalida" - -#~ msgid "E599: Value of 'imactivatekey' is invalid" -#~ msgstr "E599: Valoro de 'imactivatekey' estas nevalida" - -#~ msgid "E254: Cannot allocate color %s" -#~ msgstr "E254: Ne eblas disponigi koloron %s" - -#~ msgid "No match at cursor, finding next" -#~ msgstr "Neniu kongruo ฤe kursorpozicio, trovas sekvan" - -#~ msgid "<cannot open> " -#~ msgstr "<ne eblas malfermi> " - -#~ msgid "E616: vim_SelFile: can't get font %s" -#~ msgstr "E616: vim_SelFile: ne eblas akiri tiparon %s" - -#~ msgid "E614: vim_SelFile: can't return to current directory" -#~ msgstr "E614: vim_SelFile: ne eblas reveni al la aktuala dosierujo" - -#~ msgid "Pathname:" -#~ msgstr "Serฤvojo:" - -#~ msgid "E615: vim_SelFile: can't get current directory" -#~ msgstr "E615: vim_SelFile: ne eblas akiri aktualan dosierujon" - -#~ msgid "OK" -#~ msgstr "Bone" - -#~ msgid "Cancel" -#~ msgstr "Rezigni" - -#~ msgid "Scrollbar Widget: Could not get geometry of thumb pixmap." -#~ msgstr "" -#~ "Fenestraฤตo de rulumskalo: Ne eblis akiri geometrion de reduktita " -#~ "rastrumbildo" - -#~ msgid "Vim dialog" -#~ msgstr "Vim dialogo" - -#~ msgid "E232: Cannot create BalloonEval with both message and callback" -#~ msgstr "E232: Ne eblas krei BalloonEval kun ambaลญ mesaฤo kaj reagfunkcio" - -msgid "Yes" -msgstr "Jes" - -msgid "No" -msgstr "Ne" - -# todo '_' is for hotkey, i guess? -#~ msgid "Input _Methods" -#~ msgstr "Enigaj _metodoj" - -#~ msgid "VIM - Search and Replace..." -#~ msgstr "VIM - Serฤi kaj anstataลญigi..." - -#~ msgid "VIM - Search..." -#~ msgstr "VIM- Serฤi..." - -#~ msgid "Find what:" -#~ msgstr "Serฤi kion:" - -#~ msgid "Replace with:" -#~ msgstr "Anstataลญigi per:" - -#~ msgid "Match whole word only" -#~ msgstr "Kongrui kun nur plena vorto" - -#~ msgid "Match case" -#~ msgstr "Uskleca kongruo" - -#~ msgid "Direction" -#~ msgstr "Direkto" - -#~ msgid "Up" -#~ msgstr "Supren" - -#~ msgid "Down" -#~ msgstr "Suben" - -#~ msgid "Find Next" -#~ msgstr "Trovi sekvantan" - -#~ msgid "Replace" -#~ msgstr "Anstataลญigi" - -#~ msgid "Replace All" -#~ msgstr "Anstataลญigi ฤiujn" - -#~ msgid "Vim: Received \"die\" request from session manager\n" -#~ msgstr "Vim: Ricevis peton \"die\" (morti) el la seanca administrilo\n" - -#~ msgid "Close tab" -#~ msgstr "Fermi langeton" - -#~ msgid "New tab" -#~ msgstr "Nova langeto" - -#~ msgid "Open Tab..." -#~ msgstr "Malfermi langeton..." - -#~ msgid "Vim: Main window unexpectedly destroyed\n" -#~ msgstr "Vim: ฤefa fenestro neatendite detruiฤis\n" - -#~ msgid "&Filter" -#~ msgstr "&Filtri" - -#~ msgid "&Cancel" -#~ msgstr "&Rezigni" - -#~ msgid "Directories" -#~ msgstr "Dosierujoj" - -#~ msgid "Filter" -#~ msgstr "Filtri" - -#~ msgid "&Help" -#~ msgstr "&Helpo" - -#~ msgid "Files" -#~ msgstr "Dosieroj" - -#~ msgid "&OK" -#~ msgstr "&Bone" - -#~ msgid "Selection" -#~ msgstr "Apartigo" - -#~ msgid "Find &Next" -#~ msgstr "Trovi &Sekvanta" - -#~ msgid "&Replace" -#~ msgstr "&Anstataลญigi" - -#~ msgid "Replace &All" -#~ msgstr "Anstataลญigi ฤi&on" - -#~ msgid "&Undo" -#~ msgstr "&Malfari" - -#~ msgid "E671: Cannot find window title \"%s\"" -#~ msgstr "E671: Ne eblas trovi titolon de fenestro \"%s\"" - -#~ msgid "E243: Argument not supported: \"-%s\"; Use the OLE version." -#~ msgstr "E243: Ne subtenata argumento: \"-%s\"; Uzu la version OLE." - -#~ msgid "E672: Unable to open window inside MDI application" -#~ msgstr "E672: Ne eblas malfermi fenestron interne de aplikaฤตo MDI" - -#~ msgid "Open tab..." -#~ msgstr "Malfermi langeton..." - -#~ msgid "Find string (use '\\\\' to find a '\\')" -#~ msgstr "Trovi ฤenon (uzu '\\\\' por trovi '\\')" - -#~ msgid "Find & Replace (use '\\\\' to find a '\\')" -#~ msgstr "Trovi kaj anstataลญigi (uzu '\\\\' por trovi '\\')" - -#~ msgid "Not Used" -#~ msgstr "Ne uzata" - -#~ msgid "Directory\t*.nothing\n" -#~ msgstr "Dosierujo\t*.nenio\n" - -#~ msgid "" -#~ "Vim E458: Cannot allocate colormap entry, some colors may be incorrect" -#~ msgstr "" -#~ "Vim E458: Ne eblas disponigi rikordon de kolormapo, iuj koloroj estas " -#~ "eble neฤustaj" - -#~ msgid "E250: Fonts for the following charsets are missing in fontset %s:" -#~ msgstr "E250: Tiparoj de tiuj signaroj mankas en aro de tiparo %s:" - -#~ msgid "E252: Fontset name: %s" -#~ msgstr "E252: Nomo de tiparo: %s" - -#~ msgid "Font '%s' is not fixed-width" -#~ msgstr "Tiparo '%s' ne estas egallarฤa" - -#~ msgid "E253: Fontset name: %s\n" -#~ msgstr "E253: Nomo de tiparo: %s\n" - -#~ msgid "Font0: %s\n" -#~ msgstr "Font0: %s\n" - -#~ msgid "Font1: %s\n" -#~ msgstr "Font1: %s\n" - -#~ msgid "Font%<PRId64> width is not twice that of font0\n" -#~ msgstr "Font%<PRId64> ne estas duoble pli larฤa ol font0\n" - -#~ msgid "Font0 width: %<PRId64>\n" -#~ msgstr "Larฤo de font0: %<PRId64>\n" - -#~ msgid "" -#~ "Font1 width: %<PRId64>\n" -#~ "\n" -#~ msgstr "" -#~ "Larฤo de Font1: %<PRId64>\n" -#~ "\n" - -#~ msgid "Invalid font specification" -#~ msgstr "Nevalida tiparo specifita" - -#~ msgid "&Dismiss" -#~ msgstr "&Forlasi" - -#~ msgid "no specific match" -#~ msgstr "Neniu specifa kongruo" - -#~ msgid "Vim - Font Selector" -#~ msgstr "Vim - Elektilo de tiparo" - -#~ msgid "Name:" -#~ msgstr "Nomo:" - -#~ msgid "Show size in Points" -#~ msgstr "Montri grandon en punktoj" - -#~ msgid "Encoding:" -#~ msgstr "Kodoprezento:" - -#~ msgid "Font:" -#~ msgstr "Tiparo:" - -#~ msgid "Style:" -#~ msgstr "Stilo:" - -#~ msgid "Size:" -#~ msgstr "Grando:" - -#~ msgid "E256: Hangul automata ERROR" -#~ msgstr "E256: ERARO en aลญtomato de korea alfabeto" - -#~ msgid "E563: stat error" -#~ msgstr "E563: Eraro de stat" - -#~ msgid "E625: cannot open cscope database: %s" -#~ msgstr "E625: ne eblas malfermi datumbazon de cscope: %s" - -#~ msgid "E626: cannot get cscope database information" -#~ msgstr "E626: ne eblas akiri informojn pri la datumbazo de cscope" - -#~ msgid "Lua library cannot be loaded." -#~ msgstr "La biblioteko Lua no ลargeblis." - -#~ msgid "cannot save undo information" -#~ msgstr "ne eblas konservi informojn de malfaro" - -#~ msgid "" -#~ "E815: Sorry, this command is disabled, the MzScheme libraries could not " -#~ "be loaded." -#~ msgstr "" -#~ "E815: Bedaลญrinde, tiu komando estas malลaltita, ne eblis ลargi la " -#~ "bibliotekojn." - -#~ msgid "invalid expression" -#~ msgstr "nevalida esprimo" - -#~ msgid "expressions disabled at compile time" -#~ msgstr "esprimoj malลaltitaj dum kompilado" - -#~ msgid "hidden option" -#~ msgstr "kaลita opcio" - -#~ msgid "unknown option" -#~ msgstr "nekonata opcio" - -#~ msgid "window index is out of range" -#~ msgstr "indekso de fenestro estas ekster limoj" - -#~ msgid "couldn't open buffer" -#~ msgstr "ne eblis malfermi bufron" - -#~ msgid "cannot delete line" -#~ msgstr "ne eblas forviลi linion" - -#~ msgid "cannot replace line" -#~ msgstr "ne eblas anstataลญigi linion" - -#~ msgid "cannot insert line" -#~ msgstr "ne eblas enmeti linion" - -#~ msgid "string cannot contain newlines" -#~ msgstr "ฤeno ne rajtas enhavi liniavancojn" - -#~ msgid "error converting Scheme values to Vim" -#~ msgstr "eraro dum konverto de Scheme-valoro al Vim" - -#~ msgid "Vim error: ~a" -#~ msgstr "Eraro de Vim: ~a" - -#~ msgid "Vim error" -#~ msgstr "Eraro de Vim" - -#~ msgid "buffer is invalid" -#~ msgstr "bufro estas nevalida" - -#~ msgid "window is invalid" -#~ msgstr "fenestro estas nevalida" - -#~ msgid "linenr out of range" -#~ msgstr "numero de linio ekster limoj" - -#~ msgid "not allowed in the Vim sandbox" -#~ msgstr "nepermesebla en sabloludejo de Vim" - -#~ msgid "E836: This Vim cannot execute :python after using :py3" -#~ msgstr "E836: Vim ne povas plenumi :python post uzo de :py3" - -#~ msgid "only string keys are allowed" -#~ msgstr "nur ฤenaj ลlosiloj estas permeseblaj" - -#~ msgid "" -#~ "E263: Sorry, this command is disabled, the Python library could not be " -#~ "loaded." -#~ msgstr "" -#~ "E263: Bedaลญrinde tiu komando estas malลaltita: la biblioteko de Pitono ne " -#~ "ลargeblis." - -#~ msgid "E659: Cannot invoke Python recursively" -#~ msgstr "E659: Ne eblas alvoki Pitonon rekursie" - -#~ msgid "E837: This Vim cannot execute :py3 after using :python" -#~ msgstr "E837: Vim ne povas plenumi :py3 post uzo de :python" - -#~ msgid "index must be int or slice" -#~ msgstr "indekso devas esti 'int' aลญ 'slice'" - -#~ msgid "E265: $_ must be an instance of String" -#~ msgstr "E265: $_ devas esti apero de ฤeno" - -#~ msgid "" -#~ "E266: Sorry, this command is disabled, the Ruby library could not be " -#~ "loaded." -#~ msgstr "" -#~ "E266: Bedaลญrinde tiu komando estas malลaltita, la biblioteko Ruby ne " -#~ "ลargeblis." - -#~ msgid "E267: unexpected return" -#~ msgstr "E267: \"return\" neatendita" - -#~ msgid "E268: unexpected next" -#~ msgstr "E268: \"next\" neatendita" - -#~ msgid "E269: unexpected break" -#~ msgstr "E269: \"break\" neatendita" - -#~ msgid "E270: unexpected redo" -#~ msgstr "E270: \"redo\" neatendita" - -#~ msgid "E271: retry outside of rescue clause" -#~ msgstr "E271: \"retry\" ekster klaลญzo \"rescue\"" - -#~ msgid "E272: unhandled exception" -#~ msgstr "E272: netraktita escepto" - -#~ msgid "E273: unknown longjmp status %d" -#~ msgstr "E273: nekonata stato de longjmp: %d" - -#~ msgid "Toggle implementation/definition" -#~ msgstr "Baskuligi realigon/difinon" - -#~ msgid "Show base class of" -#~ msgstr "Vidigi bazan klason de" - -#~ msgid "Show overridden member function" -#~ msgstr "Montri anajn homonimigajn funkciojn" - -#~ msgid "Retrieve from file" -#~ msgstr "Rekuperi el dosiero" - -#~ msgid "Retrieve from project" -#~ msgstr "Rekuperi el projekto" - -#~ msgid "Retrieve from all projects" -#~ msgstr "Rekuperi de ฤiuj projektoj" - -#~ msgid "Retrieve" -#~ msgstr "Rekuperi" - -#~ msgid "Show source of" -#~ msgstr "Vidigi fonton de" - -#~ msgid "Find symbol" -#~ msgstr "Trovi simbolon" - -#~ msgid "Browse class" -#~ msgstr "Foliumi klasojn" - -#~ msgid "Show class in hierarchy" -#~ msgstr "Montri klason en hierarkio" - -#~ msgid "Show class in restricted hierarchy" -#~ msgstr "Montri klason en hierarkio restriktita" - -# todo -#~ msgid "Xref refers to" -#~ msgstr "Xref ligas al" - -#~ msgid "Xref referred by" -#~ msgstr "Xref ligiฤas de" - -#~ msgid "Xref has a" -#~ msgstr "Xref havas" - -#~ msgid "Xref used by" -#~ msgstr "Xref uzita de" - -# DP: mi ne certas pri kio temas -#~ msgid "Show docu of" -#~ msgstr "Vidigi dokumentaron de" - -#~ msgid "Generate docu for" -#~ msgstr "Krei dokumentaron de" - -#~ msgid "" -#~ "Cannot connect to SNiFF+. Check environment (sniffemacs must be found in " -#~ "$PATH).\n" -#~ msgstr "" -#~ "Konekto al SNiFF+ neeblas. Kontrolu medion (sniffemacs trovendas en " -#~ "$PATH).\n" - -#~ msgid "E274: Sniff: Error during read. Disconnected" -#~ msgstr "E274: Sniff: Eraro dum lego. Malkonektita" - -# DP: Tiuj 3 mesaฤoj estas kune -#~ msgid "SNiFF+ is currently " -#~ msgstr "SNiFF+ estas aktuale " - -#~ msgid "not " -#~ msgstr "ne " - -#~ msgid "connected" -#~ msgstr "konektita" - -#~ msgid "E275: Unknown SNiFF+ request: %s" -#~ msgstr "E275: Nekonata peto de SNiFF+: %s" - -#~ msgid "E276: Error connecting to SNiFF+" -#~ msgstr "E276: Eraro dum konekto al SNiFF+" - -#~ msgid "E278: SNiFF+ not connected" -#~ msgstr "E278: SNiFF+ ne estas konektita" - -#~ msgid "E279: Not a SNiFF+ buffer" -#~ msgstr "E279: Ne estas bufro SNiFF+" - -#~ msgid "Sniff: Error during write. Disconnected" -#~ msgstr "Sniff: Eraro dum skribo. Malkonektita" - -#~ msgid "invalid buffer number" -#~ msgstr "nevalida numero de bufro" - -#~ msgid "not implemented yet" -#~ msgstr "ankoraลญ ne realigita" - -#~ msgid "cannot set line(s)" -#~ msgstr "ne eblas meti la linio(j)n" - -#~ msgid "invalid mark name" -#~ msgstr "nevalida nomo de marko" - -#~ msgid "mark not set" -#~ msgstr "marko ne estas metita" - -#~ msgid "row %d column %d" -#~ msgstr "linio %d kolumno %d" - -#~ msgid "cannot insert/append line" -#~ msgstr "ne eblas enmeti/postaldoni linion" - -#~ msgid "line number out of range" -#~ msgstr "numero de linio ekster limoj" - -#~ msgid "unknown flag: " -#~ msgstr "nekonata flago: " - -# DP: ฤu traduki vimOption -#~ msgid "unknown vimOption" -#~ msgstr "nekonata vimOption" - -#~ msgid "keyboard interrupt" -#~ msgstr "klavara interrompo" - -#~ msgid "vim error" -#~ msgstr "eraro de Vim" - -#~ msgid "cannot create buffer/window command: object is being deleted" -#~ msgstr "" -#~ "ne eblas krei komandon de bufro/fenestro: objekto estas forviลiฤanta" - -#~ msgid "" -#~ "cannot register callback command: buffer/window is already being deleted" -#~ msgstr "" -#~ "ne eblas registri postalvokan komandon: bufro/fenestro estas jam " -#~ "forviลiฤanta" - -#~ msgid "" -#~ "E280: TCL FATAL ERROR: reflist corrupt!? Please report this to vim-" -#~ "dev@vim.org" -#~ msgstr "" -#~ "E280: NERIPAREBLA TCL-ERARO: reflist difekta!? Bv. retpoลti al vim-" -#~ "dev@vim.org" - -#~ msgid "cannot register callback command: buffer/window reference not found" -#~ msgstr "" -#~ "ne eblas registri postalvokan komandon: referenco de bufro/fenestro ne " -#~ "troveblas" - -#~ msgid "" -#~ "E571: Sorry, this command is disabled: the Tcl library could not be " -#~ "loaded." -#~ msgstr "" -#~ "E571: Bedaลญrinde tiu komando estas malลaltita: la biblioteko Tcl ne " -#~ "ลargeblis." - -#~ msgid "E572: exit code %d" -#~ msgstr "E572: elira kodo %d" - -#~ msgid "cannot get line" -#~ msgstr "ne eblas akiri linion" - -#~ msgid "Unable to register a command server name" -#~ msgstr "Ne eblas registri nomon de komanda servilo" - -#~ msgid "E248: Failed to send command to the destination program" -#~ msgstr "E248: Sendo de komando al cela programo fiaskis" - -#~ msgid "E573: Invalid server id used: %s" -#~ msgstr "E573: Nevalida identigilo de servilo uzita: %s" - -#~ msgid "E251: VIM instance registry property is badly formed. Deleted!" -#~ msgstr "" -#~ "E251: Ecoj de registro de apero de VIM estas nevalide formata. Forviลita!" - -#~ msgid "netbeans is not supported with this GUI\n" -#~ msgstr "netbeans ne estas subtenata kun tiu grafika interfaco\n" - -#~ msgid "This Vim was not compiled with the diff feature." -#~ msgstr "Tiu Vim ne estis kompilita kun la kompara eblo." - -#~ msgid "'-nb' cannot be used: not enabled at compile time\n" -#~ msgstr "'-nb' ne uzeblas: malลaltita dum kompilado\n" - -#~ msgid "Vim: Error: Failure to start gvim from NetBeans\n" -#~ msgstr "Vim: Eraro: Fiaskis lanฤi gvim el NetBeans\n" - -#~ msgid "" -#~ "\n" -#~ "Where case is ignored prepend / to make flag upper case" -#~ msgstr "" -#~ "\n" -#~ "Kie uskleco estas ignorita antaลญaldonu / por igi flagon majuskla" - -#~ msgid "-register\t\tRegister this gvim for OLE" -#~ msgstr "-register\t\tRegistri tiun gvim al OLE" - -#~ msgid "-unregister\t\tUnregister gvim for OLE" -#~ msgstr "-unregister\t\tMalregistri gvim de OLE" - -#~ msgid "-g\t\t\tRun using GUI (like \"gvim\")" -#~ msgstr "-g\t\t\tRuli per grafika interfaco (kiel \"gvim\")" - -#~ msgid "-f or --nofork\tForeground: Don't fork when starting GUI" -#~ msgstr "-f aลญ --nofork\tMalfono: ne forki kiam lanฤas grafikan interfacon" - -#~ msgid "-f\t\t\tDon't use newcli to open window" -#~ msgstr "-f\t\t\tNe uzi newcli por malfermi fenestrojn" - -#~ msgid "-dev <device>\t\tUse <device> for I/O" -#~ msgstr "-dev <aparatdosiero>\t\tUzi <aparatdosiero>-n por eneligo" - -#~ msgid "-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc" -#~ msgstr "-U <gvimrc>\t\tUzi <gvimrc> anstataลญ iun ajn .gvimrc" - -#~ msgid "-x\t\t\tEdit encrypted files" -#~ msgstr "-x\t\t\tRedakti ฤifradan dosieron" - -#~ msgid "-display <display>\tConnect vim to this particular X-server" -#~ msgstr "-display <ekrano>\tKonekti Vim al tiu X-servilo" - -#~ msgid "-X\t\t\tDo not connect to X server" -#~ msgstr "-X\t\t\tNe konekti al X-servilo" - -#~ msgid "--remote <files>\tEdit <files> in a Vim server if possible" -#~ msgstr "--remote <dosieroj>\tRedakti <dosieroj>-n en Vim-servilo se eblas" - -#~ msgid "--remote-silent <files> Same, don't complain if there is no server" -#~ msgstr "--remote-silent <dosieroj> Same, sed ne plendi se ne estas servilo" - -#~ msgid "" -#~ "--remote-wait <files> As --remote but wait for files to have been edited" -#~ msgstr "" -#~ "--remote-wait <dosieroj> Kiel --remote sed atendi ฤis dosieroj estas " -#~ "redaktitaj" - -#~ msgid "" -#~ "--remote-wait-silent <files> Same, don't complain if there is no server" -#~ msgstr "" -#~ "--remote-wait-silent <dosieroj> Same, sed ne plendi se ne estas servilo" - -#~ msgid "" -#~ "--remote-tab[-wait][-silent] <files> As --remote but use tab page per " -#~ "file" -#~ msgstr "" -#~ "--remote-tab[-wait][-silent] <dosieroj> Kiel --remote sed uzi langeton " -#~ "por ฤiu dosiero" - -#~ msgid "--remote-send <keys>\tSend <keys> to a Vim server and exit" -#~ msgstr "--remote-send <klavoj> Sendi <klavoj>-n al Vim-servilo kaj eliri" - -#~ msgid "" -#~ "--remote-expr <expr>\tEvaluate <expr> in a Vim server and print result" -#~ msgstr "" -#~ "--remote-expr <espr>\tKomputi <espr> en Vim-servilo kaj afiลi rezulton" - -#~ msgid "--serverlist\t\tList available Vim server names and exit" -#~ msgstr "--serverlist\t\tListigi haveblajn nomojn de Vim-serviloj kaj eliri" - -#~ msgid "--servername <name>\tSend to/become the Vim server <name>" -#~ msgstr "--servername <nomo>\tSendu al/iฤi la Vim-servilo <nomo>" - -#~ msgid "" -#~ "\n" -#~ "Arguments recognised by gvim (Motif version):\n" -#~ msgstr "" -#~ "\n" -#~ "Argumentoj agnoskitaj de gvim (versio Motif):\n" - -#~ msgid "" -#~ "\n" -#~ "Arguments recognised by gvim (neXtaw version):\n" -#~ msgstr "" -#~ "\n" -#~ "Argumentoj agnoskitaj de gvim (versio neXtaw):\n" - -#~ msgid "" -#~ "\n" -#~ "Arguments recognised by gvim (Athena version):\n" -#~ msgstr "" -#~ "\n" -#~ "Argumentoj agnoskitaj de gvim (versio Athena):\n" - -#~ msgid "-display <display>\tRun vim on <display>" -#~ msgstr "-display <ekrano>\tLanฤi vim sur <ekrano>" - -#~ msgid "-iconic\t\tStart vim iconified" -#~ msgstr "-iconic\t\tLanฤi vim piktograme" - -#~ msgid "-background <color>\tUse <color> for the background (also: -bg)" -#~ msgstr "" -#~ "-background <koloro>\tUzi <koloro>-n por la fona koloro (ankaลญ: -bg)" - -#~ msgid "-foreground <color>\tUse <color> for normal text (also: -fg)" -#~ msgstr "" -#~ "-foreground <koloro>\tUzi <koloro>-n por la malfona koloro (ankaลญ: -fg)" - -#~ msgid "-font <font>\t\tUse <font> for normal text (also: -fn)" -#~ msgstr "-font <tiparo>\tUzi <tiparo>-n por normala teksto (ankaลญ: -fn)" - -#~ msgid "-boldfont <font>\tUse <font> for bold text" -#~ msgstr "-boldfont <tiparo>\tUzi <tiparo>-n por grasa teksto" - -#~ msgid "-italicfont <font>\tUse <font> for italic text" -#~ msgstr "-italicfont <tiparo>\tUzi <tiparo>-n por kursiva teksto" - -#~ msgid "-geometry <geom>\tUse <geom> for initial geometry (also: -geom)" -#~ msgstr "-geometry <geom>\tUzi <geom> kiel komenca geometrio (ankaลญ: -geom)" - -#~ msgid "-borderwidth <width>\tUse a border width of <width> (also: -bw)" -#~ msgstr "" -#~ "-borderwidth <larฤo>\tUzi <larฤo>-n kiel larฤo de bordero (ankaลญ: -bw)" - -#~ msgid "" -#~ "-scrollbarwidth <width> Use a scrollbar width of <width> (also: -sw)" -#~ msgstr "" -#~ "-scrollbarwidth <larฤo> Uzi <larฤo>-n kiel larฤo de rulumskalo (ankaลญ: -" -#~ "sw)" - -#~ msgid "-menuheight <height>\tUse a menu bar height of <height> (also: -mh)" -#~ msgstr "" -#~ "-menuheight <alto>\tUzi <alto>-n kiel alto de menuzona alto (ankaลญ: -mh)" - -#~ msgid "-reverse\t\tUse reverse video (also: -rv)" -#~ msgstr "-reverse\t\tUzi inversan videon (ankaลญ: -rv)" - -#~ msgid "+reverse\t\tDon't use reverse video (also: +rv)" -#~ msgstr "+reverse\t\tNe uzi inversan videon (ankaลญ: +rv)" +#, c-format +msgid "E447: Can't find file \"%s\" in path" +msgstr "E447: Ne eblas trovi dosieron \"%s\" en serฤvojo" -#~ msgid "-xrm <resource>\tSet the specified resource" -#~ msgstr "-xrm <rimedo>\tAgordi la specifitan <rimedo>-n" +#, c-format +msgid "E799: Invalid ID: %ld (must be greater than or equal to 1)" +msgstr "E799: Nevalida ID: %ld (devas esti egala aลญ pli granda ol 1)" -#~ msgid "" -#~ "\n" -#~ "Arguments recognised by gvim (GTK+ version):\n" -#~ msgstr "" -#~ "\n" -#~ "Argumentoj agnoskitaj de gvim (versio GTK+):\n" +#, c-format +msgid "E801: ID already taken: %ld" +msgstr "E801: ID jam uzata: %ld" -#~ msgid "-display <display>\tRun vim on <display> (also: --display)" -#~ msgstr "-display <ekrano>\tLanฤi Vim sur tiu <ekrano> (ankaลญ: --display)" +msgid "List or number required" +msgstr "Listo aลญ nombro bezonata" -#~ msgid "--role <role>\tSet a unique role to identify the main window" -#~ msgstr "--role <rolo>\tDoni unikan rolon por identigi la ฤefan fenestron" +#, c-format +msgid "E802: Invalid ID: %ld (must be greater than or equal to 1)" +msgstr "E802: Nevalida ID: %ld (devas esti egala aลญ pli granda ol 1)" -#~ msgid "--socketid <xid>\tOpen Vim inside another GTK widget" -#~ msgstr "--socketid <xid>\tMalfermi Vim en alia GTK fenestraฤตo" +#, c-format +msgid "E803: ID not found: %ld" +msgstr "E803: ID netrovita: %ld" -#~ msgid "--echo-wid\t\tMake gvim echo the Window ID on stdout" -#~ msgstr "--echo-wid\t\tIgas gvim afiลi la identigilon de vindozo sur stdout" +#, c-format +msgid "E370: Could not load library %s" +msgstr "E370: Ne eblis ลargi bibliotekon %s" -#~ msgid "-P <parent title>\tOpen Vim inside parent application" -#~ msgstr "-P <gepatra titolo>\tMalfermi Vim en gepatra aplikaฤตo" +msgid "Sorry, this command is disabled: the Perl library could not be loaded." +msgstr "" +"Bedaลญrinde tiu komando estas malลaltita: la biblioteko de Perl ne ลargeblis." -#~ msgid "--windowid <HWND>\tOpen Vim inside another win32 widget" -#~ msgstr "--windowid <HWND>\tMalfermi Vim en alia win32 fenestraฤตo" +msgid "E299: Perl evaluation forbidden in sandbox without the Safe module" +msgstr "" +"E299: Plenumo de Perl esprimoj malpermesata en sabloludejo sen la modulo Safe" -#~ msgid "No display" -#~ msgstr "Neniu ekrano" +msgid "Edit with &multiple Vims" +msgstr "Redakti per &pluraj Vim-oj" -#~ msgid ": Send failed.\n" -#~ msgstr ": Sendo fiaskis.\n" +msgid "Edit with single &Vim" +msgstr "Redakti per unuopa &Vim" -#~ msgid ": Send failed. Trying to execute locally\n" -#~ msgstr ": Sendo fiaskis. Provo de loka plenumo\n" +msgid "Diff with Vim" +msgstr "Kompari per Vim" -#~ msgid "%d of %d edited" -#~ msgstr "%d de %d redaktita(j)" +msgid "Edit with &Vim" +msgstr "Redakti per &Vim" -#~ msgid "No display: Send expression failed.\n" -#~ msgstr "Neniu ekrano: Sendado de esprimo fiaskis.\n" +#. Now concatenate +msgid "Edit with existing Vim - " +msgstr "Redakti per ekzistanta Vim - " -#~ msgid ": Send expression failed.\n" -#~ msgstr ": Sendado de esprimo fiaskis.\n" +msgid "Edits the selected file(s) with Vim" +msgstr "Redakti la apartigita(j)n dosiero(j)n per Vim" -#~ msgid "E543: Not a valid codepage" -#~ msgstr "E543: Nevalida kodpaฤo" +msgid "Error creating process: Check if gvim is in your path!" +msgstr "Eraro dum kreo de procezo: Kontrolu ฤu gvim estas en via serฤvojo!" -#~ msgid "E284: Cannot set IC values" -#~ msgstr "E284: Ne eblas agordi valorojn de IC" +msgid "gvimext.dll error" +msgstr "Eraro de gvimext.dll" -#~ msgid "E285: Failed to create input context" -#~ msgstr "E285: Ne eblis krei enigan kuntekston" +msgid "Path length too long!" +msgstr "Serฤvojo estas tro longa!" -#~ msgid "E286: Failed to open input method" -#~ msgstr "E286: Ne eblis malfermi enigan metodon" +msgid "--No lines in buffer--" +msgstr "--Neniu linio en bufro--" -#~ msgid "E287: Warning: Could not set destroy callback to IM" -#~ msgstr "E287: Averto: Ne eblis agordi detruan reagfunkcion al IM" +#. +#. * The error messages that can be shared are included here. +#. * Excluded are errors that are only used once and debugging messages. +#. +msgid "E470: Command aborted" +msgstr "E470: komando ฤesigita" -#~ msgid "E288: input method doesn't support any style" -#~ msgstr "E288: eniga metodo subtenas neniun stilon" +msgid "E471: Argument required" +msgstr "E471: Argumento bezonata" -# DP: mi ne scias, kio estas "preedit" -#~ msgid "E289: input method doesn't support my preedit type" -#~ msgstr "E289: eniga metodo ne subtenas mian antaลญredaktan tipon" - -#~ msgid "E843: Error while updating swap file crypt" -#~ msgstr "E843: Eraro dum ฤisdatigo de ฤifrada permutodosiero .swp" - -#~ msgid "" -#~ "E833: %s is encrypted and this version of Vim does not support encryption" -#~ msgstr "E833: %s estas ฤifrata kaj tiu versio de Vim ne subtenas ฤifradon" - -#~ msgid "Swap file is encrypted: \"%s\"" -#~ msgstr "Perumutodosiero .swp estas ฤifrata: \"%s\"" - -#~ msgid "" -#~ "\n" -#~ "If you entered a new crypt key but did not write the text file," -#~ msgstr "" -#~ "\n" -#~ "Se vi tajpis novan ลlosilon de ฤifrado sed ne skribis la tekstan dosieron," - -#~ msgid "" -#~ "\n" -#~ "enter the new crypt key." -#~ msgstr "" -#~ "\n" -#~ "tajpu la novan ลlosilon de ฤifrado." +msgid "E10: \\ should be followed by /, ? or &" +msgstr "E10: \\ devus esti sekvita de /, ? aลญ &" -#~ msgid "" -#~ "\n" -#~ "If you wrote the text file after changing the crypt key press enter" -#~ msgstr "" -#~ "\n" -#~ "Se vi skribis la tekstan dosieron post ลanฤo de la ลlosilo de ฤifrado, " -#~ "premu enenklavon" +msgid "E11: Invalid in command-line window; <CR> executes, CTRL-C quits" +msgstr "" +"E11: Nevalida en fenestro de komanda linio; <CR> plenumas, CTRL-C eliras" -#~ msgid "" -#~ "\n" -#~ "to use the same key for text file and swap file" -#~ msgstr "" -#~ "\n" -#~ "por uzi la saman ลlosilon por la teksta dosiero kaj permuto dosiero .swp" +msgid "E12: Command not allowed from exrc/vimrc in current dir or tag search" +msgstr "" +"E12: Nepermesebla komando el exrc/vimrc en aktuala dosierujo aลญ etikeda serฤo" -#~ msgid "Using crypt key from swap file for the text file.\n" -#~ msgstr "" -#~ "Uzas ลlosilon de ฤifrado el permuto dosiero .swp por la teksta dosiero.\n" +msgid "E171: Missing :endif" +msgstr "E171: Mankas \":endif\"" -#~ msgid "" -#~ "\n" -#~ " [not usable with this version of Vim]" -#~ msgstr "" -#~ "\n" -#~ " [ne uzebla per tiu versio de Vim]" +msgid "E600: Missing :endtry" +msgstr "E600: Mankas \":endtry\"" -#~ msgid "Tear off this menu" -#~ msgstr "Disigi tiun menuon" +msgid "E170: Missing :endwhile" +msgstr "E170: Mankas \":endwhile\"" -#~ msgid "Select Directory dialog" -#~ msgstr "Dialogujo de dosiera elekto" +msgid "E170: Missing :endfor" +msgstr "E170: Mankas \":endfor\"" -#~ msgid "Save File dialog" -#~ msgstr "Dialogujo de dosiera konservo" +msgid "E588: :endwhile without :while" +msgstr "E588: \":endwhile\" sen \":while\"" -#~ msgid "Open File dialog" -#~ msgstr "Dialogujo de dosiera malfermo" +msgid "E588: :endfor without :for" +msgstr "E588: \":endfor\" sen \":for\"" -#~ msgid "E338: Sorry, no file browser in console mode" -#~ msgstr "E338: Bedaลญrinde ne estas dosierfoliumilo en konzola reฤimo" +msgid "E13: File exists (add ! to override)" +msgstr "E13: Dosiero ekzistas (aldonu ! por transpasi)" -#~ msgid "Vim: preserving files...\n" -#~ msgstr "Vim: konservo de dosieroj...\n" +msgid "E472: Command failed" +msgstr "E472: La komando malsukcesis" -#~ msgid "Vim: Finished.\n" -#~ msgstr "Vim: Finita.\n" +#, c-format +msgid "E234: Unknown fontset: %s" +msgstr "E234: Nekonata familio de tiparo: %s" -#~ msgid "ERROR: " -#~ msgstr "ERARO: " +#, c-format +msgid "E235: Unknown font: %s" +msgstr "E235: Nekonata tiparo: %s" -#~ msgid "" -#~ "\n" -#~ "[bytes] total alloc-freed %<PRIu64>-%<PRIu64>, in use %<PRIu64>, peak use " -#~ "%<PRIu64>\n" -#~ msgstr "" -#~ "\n" -#~ "[bajtoj] totalaj disponigitaj/maldisponigitaj %<PRIu64>-%<PRIu64>, nun " -#~ "uzataj %<PRIu64>, kulmina uzo %<PRIu64>\n" +#, c-format +msgid "E236: Font \"%s\" is not fixed-width" +msgstr "E236: La tiparo \"%s\" ne estas egallarฤa" -#~ msgid "" -#~ "[calls] total re/malloc()'s %<PRIu64>, total free()'s %<PRIu64>\n" -#~ "\n" -#~ msgstr "" -#~ "[alvokoj] totalaj re/malloc() %<PRIu64>, totalaj free() %<PRIu64>\n" -#~ "\n" +msgid "E473: Internal error" +msgstr "E473: Interna eraro" -#~ msgid "E340: Line is becoming too long" -#~ msgstr "E340: Linio iฤas tro longa" +#, c-format +msgid "E685: Internal error: %s" +msgstr "E685: Interna eraro: %s" -#~ msgid "E341: Internal error: lalloc(%<PRId64>, )" -#~ msgstr "E341: Interna eraro: lalloc(%<PRId64>, )" +msgid "Interrupted" +msgstr "Interrompita" -#~ msgid "E547: Illegal mouseshape" -#~ msgstr "E547: Nevalida formo de muskursoro" +msgid "E14: Invalid address" +msgstr "E14: Nevalida adreso" -#~ msgid "Enter encryption key: " -#~ msgstr "Tajpu la ลlosilon de ฤifrado: " +msgid "E474: Invalid argument" +msgstr "E474: Nevalida argumento" -#~ msgid "Enter same key again: " -#~ msgstr "Tajpu la ลlosilon denove: " +#, c-format +msgid "E475: Invalid argument: %s" +msgstr "E475: Nevalida argumento: %s" -#~ msgid "Keys don't match!" -#~ msgstr "ลlosiloj ne kongruas!" +#, c-format +msgid "E15: Invalid expression: %s" +msgstr "E15: Nevalida esprimo: %s" -#~ msgid "Cannot connect to Netbeans #2" -#~ msgstr "Ne eblas konekti al Netbeans n-ro 2" +msgid "E16: Invalid range" +msgstr "E16: Nevalida amplekso" -#~ msgid "Cannot connect to Netbeans" -#~ msgstr "Ne eblas konekti al Netbeans" +msgid "E476: Invalid command" +msgstr "E476: Nevalida komando" -#~ msgid "E668: Wrong access mode for NetBeans connection info file: \"%s\"" -#~ msgstr "" -#~ "E668: Nevalida permeso de dosiero de informo de konekto NetBeans: \"%s\"" +#, c-format +msgid "E17: \"%s\" is a directory" +msgstr "E17: \"%s\" estas dosierujo" -#~ msgid "read from Netbeans socket" -#~ msgstr "lego el kontaktoskatolo de Netbeans" +#, c-format +msgid "E364: Library call failed for \"%s()\"" +msgstr "E364: Alvoko al biblioteko malsukcesis por \"%s()\"" -#~ msgid "E658: NetBeans connection lost for buffer %<PRId64>" -#~ msgstr "E658: Konekto de NetBeans perdita por bufro %<PRId64>" +#, c-format +msgid "E448: Could not load library function %s" +msgstr "E448: Ne eblis ลargi bibliotekan funkcion %s" -#~ msgid "E838: netbeans is not supported with this GUI" -#~ msgstr "E838: netbeans ne estas subtenata kun tiu grafika interfaco" +msgid "E19: Mark has invalid line number" +msgstr "E19: Marko havas nevalidan numeron de linio" -#~ msgid "E511: netbeans already connected" -#~ msgstr "E511: nebeans jam konektata" +msgid "E20: Mark not set" +msgstr "E20: Marko ne estas agordita" -#~ msgid "E505: %s is read-only (add ! to override)" -#~ msgstr "E505: %s estas nurlegebla (aldonu ! por transpasi)" +msgid "E21: Cannot make changes, 'modifiable' is off" +msgstr "E21: Ne eblas fari ลanฤojn, 'modifiable' estas malลaltita" -# DP: ฤu Eval devas esti tradukita? -#~ msgid "E775: Eval feature not available" -#~ msgstr "E775: Eval eblo ne disponeblas" +msgid "E22: Scripts nested too deep" +msgstr "E22: Tro profunde ingitaj skriptoj" -#~ msgid "freeing %<PRId64> lines" -#~ msgstr "malokupas %<PRId64> liniojn" +msgid "E23: No alternate file" +msgstr "E23: Neniu alterna dosiero" -#~ msgid "E530: Cannot change term in GUI" -#~ msgstr "E530: term ne ลanฤeblas en grafika interfaco" +msgid "E24: No such abbreviation" +msgstr "E24: Ne estas tia mallongigo" -#~ msgid "E531: Use \":gui\" to start the GUI" -#~ msgstr "E531: Uzu \":gui\" por lanฤi la grafikan interfacon" +msgid "E477: No ! allowed" +msgstr "E477: Neniu ! permesebla" -#~ msgid "E617: Cannot be changed in the GTK+ 2 GUI" -#~ msgstr "E617: Ne ลanฤeblas en la grafika interfaco GTK+ 2" +msgid "E25: GUI cannot be used: Not enabled at compile time" +msgstr "E25: Grafika interfaco ne uzeblas: Malลaltita dum kompilado" -#~ msgid "E596: Invalid font(s)" -#~ msgstr "E596: Nevalida(j) tiparo(j)" +msgid "E26: Hebrew cannot be used: Not enabled at compile time\n" +msgstr "E26: La hebrea ne uzeblas: Malลaltita dum kompilado\n" -#~ msgid "E597: can't select fontset" -#~ msgstr "E597: ne eblas elekti tiparon" +msgid "E27: Farsi cannot be used: Not enabled at compile time\n" +msgstr "E27: La persa ne uzeblas: Malลaltita dum kompilado\n" -#~ msgid "E598: Invalid fontset" -#~ msgstr "E598: Nevalida tiparo" +msgid "E800: Arabic cannot be used: Not enabled at compile time\n" +msgstr "E800: La araba ne uzeblas: Malลaltita dum kompilado\n" -#~ msgid "E533: can't select wide font" -#~ msgstr "E533: ne eblas elekti larฤan tiparon" +#, c-format +msgid "E28: No such highlight group name: %s" +msgstr "E28: Neniu grupo de emfazo kiel: %s" -#~ msgid "E534: Invalid wide font" -#~ msgstr "E534: Nevalida larฤa tiparo" +msgid "E29: No inserted text yet" +msgstr "E29: Ankoraลญ neniu enmetita teksto" -#~ msgid "E538: No mouse support" -#~ msgstr "E538: Neniu muso subtenata" +msgid "E30: No previous command line" +msgstr "E30: Neniu antaลญa komanda linio" -#~ msgid "cannot open " -#~ msgstr "ne eblas malfermi " +msgid "E31: No such mapping" +msgstr "E31: Neniu tiel mapo" -#~ msgid "VIM: Can't open window!\n" -#~ msgstr "VIM: Ne eblas malfermi fenestron!\n" +msgid "E479: No match" +msgstr "E479: Neniu kongruo" -#~ msgid "Need Amigados version 2.04 or later\n" -#~ msgstr "Bezonas version 2.04 de Amigados aลญ pli novan\n" +#, c-format +msgid "E480: No match: %s" +msgstr "E480: Neniu kongruo: %s" -#~ msgid "Need %s version %<PRId64>\n" -#~ msgstr "Bezonas %s-on versio %<PRId64>\n" +msgid "E32: No file name" +msgstr "E32: Neniu dosiernomo" -#~ msgid "Cannot open NIL:\n" -#~ msgstr "Ne eblas malfermi NIL:\n" +msgid "E33: No previous substitute regular expression" +msgstr "E33: Neniu antaลญa regulesprimo de anstataลญigo" -#~ msgid "Cannot create " -#~ msgstr "Ne eblas krei " +msgid "E34: No previous command" +msgstr "E34: Neniu antaลญa komando" -#~ msgid "Vim exiting with %d\n" -#~ msgstr "Vim eliras kun %d\n" +msgid "E35: No previous regular expression" +msgstr "E35: Neniu antaลญa regulesprimo" -#~ msgid "cannot change console mode ?!\n" -#~ msgstr "ne eblas ลanฤi reฤimon de konzolo?!\n" +msgid "E481: No range allowed" +msgstr "E481: Amplekso nepermesebla" -#~ msgid "mch_get_shellsize: not a console??\n" -#~ msgstr "mch_get_shellsize: ne estas konzolo??\n" +msgid "E36: Not enough room" +msgstr "E36: Ne sufiฤe da spaco" -#~ msgid "E360: Cannot execute shell with -f option" -#~ msgstr "E360: Ne eblas plenumi ลelon kun opcio -f" +#, c-format +msgid "E247: no registered server named \"%s\"" +msgstr "E247: neniu registrita servilo nomita \"%s\"" -#~ msgid "Cannot execute " -#~ msgstr "Ne eblas plenumi " +#, c-format +msgid "E482: Can't create file %s" +msgstr "E482: Ne eblas krei dosieron %s" -#~ msgid "shell " -#~ msgstr "ลelo " +msgid "E483: Can't get temp file name" +msgstr "E483: Ne eblas akiri provizoran dosiernomon" -#~ msgid " returned\n" -#~ msgstr " liveris\n" +#, c-format +msgid "E484: Can't open file %s" +msgstr "E484: Ne eblas malfermi dosieron %s" -#~ msgid "ANCHOR_BUF_SIZE too small." -#~ msgstr "ANCHOR_BUF_SIZE tro malgranda." +#, c-format +msgid "E485: Can't read file %s" +msgstr "E485: Ne eblas legi dosieron %s" -#~ msgid "I/O ERROR" -#~ msgstr "ERARO DE ENIGO/ELIGO" +msgid "E37: No write since last change (add ! to override)" +msgstr "E37: Neniu skribo de post lasta ลanฤo (aldonu ! por transpasi)" -#~ msgid "Message" -#~ msgstr "Mesaฤo" +msgid "E37: No write since last change" +msgstr "E37: Neniu skribo de post lasta ลanฤo" -#~ msgid "'columns' is not 80, cannot execute external commands" -#~ msgstr "'columns' ne estas 80, ne eblas plenumi eksternajn komandojn" +msgid "E38: Null argument" +msgstr "E38: Nula argumento" -#~ msgid "E237: Printer selection failed" -#~ msgstr "E237: Elekto de presilo fiaskis" +msgid "E39: Number expected" +msgstr "E39: Nombro atendita" -#~ msgid "to %s on %s" -#~ msgstr "al %s de %s" +#, c-format +msgid "E40: Can't open errorfile %s" +msgstr "E40: Ne eblas malfermi eraran dosieron %s" -#~ msgid "E613: Unknown printer font: %s" -#~ msgstr "E613: Nekonata tiparo de presilo: %s" +msgid "E233: cannot open display" +msgstr "E233: ne eblas malfermi vidigon" -#~ msgid "E238: Print error: %s" -#~ msgstr "E238: Eraro de presado: %s" +msgid "E41: Out of memory!" +msgstr "E41: Ne plu restas memoro!" -#~ msgid "Printing '%s'" -#~ msgstr "Presas '%s'" +msgid "Pattern not found" +msgstr "ลablono ne trovita" -#~ msgid "E244: Illegal charset name \"%s\" in font name \"%s\"" -#~ msgstr "E244: Nevalida nomo de signaro \"%s\" en nomo de tiparo \"%s\"" +#, c-format +msgid "E486: Pattern not found: %s" +msgstr "E486: ลablono ne trovita: %s" -#~ msgid "E245: Illegal char '%c' in font name \"%s\"" -#~ msgstr "E245: Nevalida signo '%c' en nomo de tiparo \"%s\"" +msgid "E487: Argument must be positive" +msgstr "E487: La argumento devas esti pozitiva" -#~ msgid "Vim: Double signal, exiting\n" -#~ msgstr "Vim: Duobla signalo, eliranta\n" +msgid "E459: Cannot go back to previous directory" +msgstr "E459: Ne eblas reiri al antaลญa dosierujo" -#~ msgid "Vim: Caught deadly signal %s\n" -#~ msgstr "Vim: Kaptis mortigantan signalon %s\n" +msgid "E42: No Errors" +msgstr "E42: Neniu eraro" -#~ msgid "Vim: Caught deadly signal\n" -#~ msgstr "Vim: Kaptis mortigantan signalon\n" +msgid "E776: No location list" +msgstr "E776: Neniu listo de lokoj" -#~ msgid "Opening the X display took %<PRId64> msec" -#~ msgstr "Malfermo de vidigo X daลญris %<PRId64> msek" +msgid "E43: Damaged match string" +msgstr "E43: Difekta kongruenda ฤeno" -#~ msgid "" -#~ "\n" -#~ "Vim: Got X error\n" -#~ msgstr "" -#~ "\n" -#~ "Vim: Alvenis X eraro\n" +msgid "E44: Corrupted regexp program" +msgstr "E44: Difekta programo de regulesprimo" -#~ msgid "Testing the X display failed" -#~ msgstr "Testo de la vidigo X fiaskis" +msgid "E45: 'readonly' option is set (add ! to override)" +msgstr "E45: La opcio 'readonly' estas ลaltita '(aldonu ! por transpasi)" -#~ msgid "Opening the X display timed out" -#~ msgstr "Tempolimo okazis dum malfermo de vidigo X" +#, c-format +msgid "E46: Cannot change read-only variable \"%s\"" +msgstr "E46: Ne eblas ลanฤi nurlegeblan variablon \"%s\"" -#~ msgid "" -#~ "\n" -#~ "Cannot execute shell sh\n" -#~ msgstr "" -#~ "\n" -#~ "Ne eblas plenumi ลelon sh\n" +#, c-format +msgid "E794: Cannot set variable in the sandbox: \"%s\"" +msgstr "E794: Ne eblas agordi variablon en la sabloludejo: \"%s\"" -#~ msgid "" -#~ "\n" -#~ "Cannot create pipes\n" -#~ msgstr "" -#~ "\n" -#~ "Ne eblas krei duktojn\n" +msgid "E713: Cannot use empty key for Dictionary" +msgstr "E713: Ne eblas uzi malplenan ลlosilon de Vortaro" -#~ msgid "" -#~ "\n" -#~ "Cannot fork\n" -#~ msgstr "" -#~ "\n" -#~ "Ne eblas forki\n" +msgid "E715: Dictionary required" +msgstr "E715: Vortaro bezonata" -#~ msgid "" -#~ "\n" -#~ "Command terminated\n" -#~ msgstr "" -#~ "\n" -#~ "Komando terminigita\n" +#, c-format +msgid "E684: list index out of range: %ld" +msgstr "E684: indekso de listo ekster limoj: %ld" -#~ msgid "XSMP lost ICE connection" -#~ msgstr "XSMP perdis la konekton ICE" +#, c-format +msgid "E118: Too many arguments for function: %s" +msgstr "E118: Tro da argumentoj por funkcio: %s" -#~ msgid "Opening the X display failed" -#~ msgstr "Malfermo de vidigo X fiaskis" +#, c-format +msgid "E716: Key not present in Dictionary: %s" +msgstr "E716: ลlosilo malekzistas en Vortaro: %s" -#~ msgid "XSMP handling save-yourself request" -#~ msgstr "XSMP: traktado de peto konservi-mem" +msgid "E714: List required" +msgstr "E714: Listo bezonata" -#~ msgid "XSMP opening connection" -#~ msgstr "XSMP: malfermo de konekto" +#, c-format +msgid "E712: Argument of %s must be a List or Dictionary" +msgstr "E712: Argumento de %s devas esti Listo aลญ Vortaro" -#~ msgid "XSMP ICE connection watch failed" -#~ msgstr "XSMP: kontrolo de konekto ICE fiaskis" +msgid "E47: Error while reading errorfile" +msgstr "E47: Eraro dum legado de erardosiero" -#~ msgid "XSMP SmcOpenConnection failed: %s" -#~ msgstr "XSMP: SmcOpenConnection fiaskis: %s" +msgid "E48: Not allowed in sandbox" +msgstr "E48: Nepermesebla en sabloludejo" -#~ msgid "At line" -#~ msgstr "ฤe linio" +msgid "E523: Not allowed here" +msgstr "E523: Nepermesebla tie" -#~ msgid "Could not load vim32.dll!" -#~ msgstr "Ne eblis ลargi vim32.dll!" +msgid "E359: Screen mode setting not supported" +msgstr "E359: Reฤimo de ekrano ne subtenata" -#~ msgid "VIM Error" -#~ msgstr "Eraro de VIM" +msgid "E49: Invalid scroll size" +msgstr "E49: Nevalida grando de rulumo" -#~ msgid "Could not fix up function pointers to the DLL!" -#~ msgstr "Ne eblis ripari referencojn de funkcioj al la DLL!" +msgid "E91: 'shell' option is empty" +msgstr "E91: La opcio 'shell' estas malplena" -#~ msgid "shell returned %d" -#~ msgstr "la ลelo liveris %d" +msgid "E255: Couldn't read in sign data!" +msgstr "E255: Ne eblis legi datumojn de simboloj!" -# DP: la eventoj estas tiuj, kiuj estas en la sekvantaj ฤenoj -#~ msgid "Vim: Caught %s event\n" -#~ msgstr "Vim: Kaptis eventon %s\n" +msgid "E72: Close error on swap file" +msgstr "E72: Eraro dum malfermo de permutodosiero .swp" -#~ msgid "close" -#~ msgstr "fermo" +msgid "E73: tag stack empty" +msgstr "E73: malplena stako de etikedo" -#~ msgid "logoff" -#~ msgstr "elsaluto" +msgid "E74: Command too complex" +msgstr "E74: Komando tro kompleksa" -#~ msgid "shutdown" -#~ msgstr "sistemfermo" +msgid "E75: Name too long" +msgstr "E75: Nomo tro longa" -#~ msgid "E371: Command not found" -#~ msgstr "E371: Netrovebla komando" +msgid "E76: Too many [" +msgstr "E76: Tro da [" -#~ msgid "" -#~ "VIMRUN.EXE not found in your $PATH.\n" -#~ "External commands will not pause after completion.\n" -#~ "See :help win32-vimrun for more information." -#~ msgstr "" -#~ "VIMRUN.EXE ne troveblas en via $PATH.\n" -#~ "Eksteraj komandoj ne paลญzos post kompletigo.\n" -#~ "Vidu :help win32-vimrun por pliaj informoj." - -#~ msgid "Vim Warning" -#~ msgstr "Averto de Vim" - -#~ msgid "Error file" -#~ msgstr "Erara Dosiero" - -#~ msgid "E868: Error building NFA with equivalence class!" -#~ msgstr "E868: Eraro dum prekomputado de NFA kun ekvivalentoklaso!" - -#~ msgid "E999: (NFA regexp internal error) Should not process NOT node !" -#~ msgstr "" -#~ "E999: (interna eraro de NFA-regulesprimo) Ne devus procezi nodon 'NOT'!" - -#~ msgid "E878: (NFA) Could not allocate memory for branch traversal!" -#~ msgstr "E878: (NFA) Ne povis asigni memoron por traigi branฤojn!" - -#~ msgid "Warning: Cannot find word list \"%s_%s.spl\" or \"%s_ascii.spl\"" -#~ msgstr "Averto: Ne eblas trovi vortliston \"%s_%s.spl\" aลญ \"%s_ascii.spl\"" - -#~ msgid "Conversion in %s not supported" -#~ msgstr "Konverto en %s nesubtenata" - -#~ msgid "E845: Insufficient memory, word list will be incomplete" -#~ msgstr "E845: Ne sufiฤe da memoro, vortlisto estos nekompleta." - -#~ msgid "E430: Tag file path truncated for %s\n" -#~ msgstr "E430: Vojo de etikeda dosiero trunkita por %s\n" - -#~ msgid "new shell started\n" -#~ msgstr "nova ลelo lanฤita\n" - -#~ msgid "Used CUT_BUFFER0 instead of empty selection" -#~ msgstr "Uzis CUT_BUFFER0 anstataลญ malplenan apartigon" - -#~ msgid "No undo possible; continue anyway" -#~ msgstr "Malfaro neebla; daลญrigi tamene" - -#~ msgid "E832: Non-encrypted file has encrypted undo file: %s" -#~ msgstr "E832: Ne ฤifrata dosiero havas ฤifratan malfaran dosieron: %s" - -#~ msgid "E826: Undo file decryption failed: %s" -#~ msgstr "E826: Malฤifrado de malfara dosiero fiaskis: %s" - -#~ msgid "E827: Undo file is encrypted: %s" -#~ msgstr "E827: Malfara dosiero estas ฤifrata: %s" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 16/32-bit GUI version" -#~ msgstr "" -#~ "\n" -#~ "Grafika versio MS-Vindozo 16/32-bitoj" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 64-bit GUI version" -#~ msgstr "" -#~ "\n" -#~ "Grafika versio MS-Vindozo 64-bitoj" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 32-bit GUI version" -#~ msgstr "" -#~ "\n" -#~ "Grafika versio MS-Vindozo 32-bitoj" - -#~ msgid " in Win32s mode" -#~ msgstr " en reฤimo Win32s" - -#~ msgid " with OLE support" -#~ msgstr " kun subteno de OLE" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 64-bit console version" -#~ msgstr "" -#~ "\n" -#~ "Versio konzola MS-Vindozo 64-bitoj" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 32-bit console version" -#~ msgstr "" -#~ "\n" -#~ "Versio konzola MS-Vindozo 32-bitoj" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 16-bit version" -#~ msgstr "" -#~ "\n" -#~ "Versio MS-Vindozo 16-bitoj" - -#~ msgid "" -#~ "\n" -#~ "32-bit MS-DOS version" -#~ msgstr "" -#~ "\n" -#~ "Versio MS-DOS 32-bitoj" - -#~ msgid "" -#~ "\n" -#~ "16-bit MS-DOS version" -#~ msgstr "" -#~ "\n" -#~ "Versio MS-DOS 16-bitoj" - -#~ msgid "" -#~ "\n" -#~ "MacOS X (unix) version" -#~ msgstr "" -#~ "\n" -#~ "Versio Mak OS X (unikso)" - -#~ msgid "" -#~ "\n" -#~ "MacOS X version" -#~ msgstr "" -#~ "\n" -#~ "Versio Mak OS X" - -#~ msgid "" -#~ "\n" -#~ "MacOS version" -#~ msgstr "" -#~ "\n" -#~ "Versio Mak OS" - -#~ msgid "" -#~ "\n" -#~ "OpenVMS version" -#~ msgstr "" -#~ "\n" -#~ "Versio OpenVMS" - -#~ msgid "" -#~ "\n" -#~ "Big version " -#~ msgstr "" -#~ "\n" -#~ "Granda versio " - -#~ msgid "" -#~ "\n" -#~ "Normal version " -#~ msgstr "" -#~ "\n" -#~ "Normala versio " - -#~ msgid "" -#~ "\n" -#~ "Small version " -#~ msgstr "" -#~ "\n" -#~ "Malgranda versio " - -#~ msgid "" -#~ "\n" -#~ "Tiny version " -#~ msgstr "" -#~ "\n" -#~ "Malgrandega versio " - -#~ msgid "with GTK2-GNOME GUI." -#~ msgstr "kun grafika interfaco GTK2-GNOME." - -#~ msgid "with GTK2 GUI." -#~ msgstr "kun grafika interfaco GTK2." - -#~ msgid "with X11-Motif GUI." -#~ msgstr "kun grafika interfaco X11-Motif." - -#~ msgid "with X11-neXtaw GUI." -#~ msgstr "kun grafika interfaco X11-neXtaw." - -#~ msgid "with X11-Athena GUI." -#~ msgstr "kun grafika interfaco X11-Athena." - -#~ msgid "with Photon GUI." -#~ msgstr "kun grafika interfaco Photon." - -#~ msgid "with GUI." -#~ msgstr "sen grafika interfaco." - -#~ msgid "with Carbon GUI." -#~ msgstr "kun grafika interfaco Carbon." - -#~ msgid "with Cocoa GUI." -#~ msgstr "kun grafika interfaco Cocoa." - -#~ msgid "with (classic) GUI." -#~ msgstr "kun (klasika) grafika interfaco." - -#~ msgid " system gvimrc file: \"" -#~ msgstr " sistema dosiero gvimrc: \"" - -#~ msgid " user gvimrc file: \"" -#~ msgstr " dosiero gvimrc de uzanto: \"" - -#~ msgid "2nd user gvimrc file: \"" -#~ msgstr " 2-a dosiero gvimrc de uzanto: \"" - -#~ msgid "3rd user gvimrc file: \"" -#~ msgstr " 3-a dosiero gvimrc de uzanto: \"" - -#~ msgid " system menu file: \"" -#~ msgstr " dosiero de sistema menuo: \"" - -#~ msgid "Compiler: " -#~ msgstr "Kompililo: " +msgid "E77: Too many file names" +msgstr "E77: Tro da dosiernomoj" -# DP: atentu al la spacetoj: ฤiuj ฤenoj devas havi la saman longon -#~ msgid "menu Help->Orphans for information " -#~ msgstr "menuo Help->Orfinoj por pliaj informoj " +msgid "E488: Trailing characters" +msgstr "E488: Vostaj signoj" -#~ msgid "Running modeless, typed text is inserted" -#~ msgstr "Ruliฤas senreฤime, tajpita teksto estas enmetita" +msgid "E78: Unknown mark" +msgstr "E78: Nekonata marko" -# DP: atentu al la spacetoj: ฤiuj ฤenoj devas havi la saman longon -#~ msgid "menu Edit->Global Settings->Toggle Insert Mode " -#~ msgstr "menuo Redakti->Mallokaj Agordoj->Baskuligi Enmetan Reฤimon" +msgid "E79: Cannot expand wildcards" +msgstr "E79: Ne eblas malvolvi ฤตokerojn" -# DP: atentu al la spacetoj: ฤiuj ฤenoj devas havi la saman longon -#~ msgid " for two modes " -#~ msgstr " por du reฤimoj " +msgid "E591: 'winheight' cannot be smaller than 'winminheight'" +msgstr "E591: 'winheight' ne rajtas esti malpli ol 'winminheight'" -# DP: tiu ฤeno pli longas (mi ne volas igi ฤiujn aliajn ฤenojn -# pli longajn) -#~ msgid "menu Edit->Global Settings->Toggle Vi Compatible" -#~ msgstr "menuo Redakti->Mallokaj Agordoj->Baskuligi Reฤimon Kongruan kun Vi" +msgid "E592: 'winwidth' cannot be smaller than 'winminwidth'" +msgstr "E592: 'winwidth' ne rajtas esti malpli ol 'winminwidth'" -# DP: atentu al la spacetoj: ฤiuj ฤenoj devas havi la saman longon -#~ msgid " for Vim defaults " -#~ msgstr " por defaลญltoj de Vim " +msgid "E80: Error while writing" +msgstr "E80: Eraro dum skribado" -#~ msgid "WARNING: Windows 95/98/ME detected" -#~ msgstr "AVERTO: Trovis Vindozon 95/98/ME" +msgid "Zero count" +msgstr "Nul kvantoro" -# DP: atentu al la spacetoj: ฤiuj ฤenoj devas havi la saman longon -#~ msgid "type :help windows95<Enter> for info on this" -#~ msgstr "tajpu :help windows95<Enenklavo> por pliaj informoj " +msgid "E81: Using <SID> not in a script context" +msgstr "E81: Uzo de <SID> ekster kunteksto de skripto" -#~ msgid "E370: Could not load library %s" -#~ msgstr "E370: Ne eblis ลargi bibliotekon %s" +msgid "E449: Invalid expression received" +msgstr "E449: Nevalida esprimo ricevita" -#~ msgid "" -#~ "Sorry, this command is disabled: the Perl library could not be loaded." -#~ msgstr "" -#~ "Bedaลญrinde tiu komando estas malลaltita: la biblioteko de Perl ne " -#~ "ลargeblis." +msgid "E463: Region is guarded, cannot modify" +msgstr "E463: Regiono estas gardita, ne eblas ลanฤi" -#~ msgid "E299: Perl evaluation forbidden in sandbox without the Safe module" -#~ msgstr "" -#~ "E299: Plenumo de Perl esprimoj malpermesata en sabloludejo sen la modulo " -#~ "Safe" +msgid "E744: NetBeans does not allow changes in read-only files" +msgstr "E744: NetBeans ne permesas ลanฤojn en nurlegeblaj dosieroj" -#~ msgid "Edit with &multiple Vims" -#~ msgstr "Redakti per &pluraj Vim-oj" +msgid "E363: pattern uses more memory than 'maxmempattern'" +msgstr "E363: ลablono uzas pli da memoro ol 'maxmempattern'" -#~ msgid "Edit with single &Vim" -#~ msgstr "Redakti per unuopa &Vim" +msgid "E749: empty buffer" +msgstr "E749: malplena bufro" -#~ msgid "Diff with Vim" -#~ msgstr "Kompari per Vim" +#, c-format +msgid "E86: Buffer %ld does not exist" +msgstr "E86: La bufro %ld ne ekzistas" -#~ msgid "Edit with &Vim" -#~ msgstr "Redakti per &Vim" +msgid "E682: Invalid search pattern or delimiter" +msgstr "E682: Nevalida serฤa ลablono aลญ disigilo" -#~ msgid "Edit with existing Vim - " -#~ msgstr "Redakti per ekzistanta Vim - " +msgid "E139: File is loaded in another buffer" +msgstr "E139: Dosiero estas ลargita en alia bufro" -#~ msgid "Edits the selected file(s) with Vim" -#~ msgstr "Redakti la apartigita(j)n dosiero(j)n per Vim" +#, c-format +msgid "E764: Option '%s' is not set" +msgstr "E764: La opcio '%s' ne estas ลaltita" -#~ msgid "Error creating process: Check if gvim is in your path!" -#~ msgstr "Eraro dum kreo de procezo: Kontrolu ฤu gvim estas en via serฤvojo!" +msgid "E850: Invalid register name" +msgstr "E850: Nevalida nomo de reฤistro" -#~ msgid "gvimext.dll error" -#~ msgstr "Eraro de gvimext.dll" +#, c-format +msgid "E919: Directory not found in '%s': \"%s\"" +msgstr "E919: Dosierujo ne trovita en '%s': \"%s\"" -#~ msgid "Path length too long!" -#~ msgstr "Serฤvojo estas tro longa!" +msgid "search hit TOP, continuing at BOTTOM" +msgstr "serฤo atingis SUPRON, daลญrigonte al SUBO" -#~ msgid "E234: Unknown fontset: %s" -#~ msgstr "E234: Nekonata familio de tiparo: %s" +msgid "search hit BOTTOM, continuing at TOP" +msgstr "serฤo atingis SUBON, daลญrigonte al SUPRO" -#~ msgid "E235: Unknown font: %s" -#~ msgstr "E235: Nekonata tiparo: %s" +#, c-format +msgid "Need encryption key for \"%s\"" +msgstr "ลlosilo de ฤifrado bezonata por \"%s\"" -#~ msgid "E236: Font \"%s\" is not fixed-width" -#~ msgstr "E236: La tiparo \"%s\" ne estas egallarฤa" +msgid "empty keys are not allowed" +msgstr "malplenaj ลlosiloj nepermeseblaj" -#~ msgid "E448: Could not load library function %s" -#~ msgstr "E448: Ne eblis ลargi bibliotekan funkcion %s" +msgid "dictionary is locked" +msgstr "vortaro estas ลlosita" -#~ msgid "E26: Hebrew cannot be used: Not enabled at compile time\n" -#~ msgstr "E26: La hebrea ne uzeblas: Malลaltita dum kompilado\n" +msgid "list is locked" +msgstr "listo estas ลlosita" -#~ msgid "E27: Farsi cannot be used: Not enabled at compile time\n" -#~ msgstr "E27: La persa ne uzeblas: Malลaltita dum kompilado\n" +#, c-format +msgid "failed to add key '%s' to dictionary" +msgstr "aldono de ลlosilo '%s' al vortaro malsukcesis" -#~ msgid "E800: Arabic cannot be used: Not enabled at compile time\n" -#~ msgstr "E800: La araba ne uzeblas: Malลaltita dum kompilado\n" +#, c-format +msgid "index must be int or slice, not %s" +msgstr "indekso devas esti 'int' aลญ 'slice', ne %s" -#~ msgid "E247: no registered server named \"%s\"" -#~ msgstr "E247: neniu registrita servilo nomita \"%s\"" +#, c-format +msgid "expected str() or unicode() instance, but got %s" +msgstr "atendis aperon de str() aลญ unicode(), sed ricevis %s" -#~ msgid "E233: cannot open display" -#~ msgstr "E233: ne eblas malfermi vidigon" +#, c-format +msgid "expected bytes() or str() instance, but got %s" +msgstr "atendis aperon de bytes() aลญ str(), sed ricevis %s" -#~ msgid "E449: Invalid expression received" -#~ msgstr "E449: Nevalida esprimo ricevita" +#, c-format +msgid "" +"expected int(), long() or something supporting coercing to long(), but got %s" +msgstr "atendis int(), long() aลญ ion konverteblan al long(), sed ricevis %s" -#~ msgid "E463: Region is guarded, cannot modify" -#~ msgstr "E463: Regiono estas gardita, ne eblas ลanฤi" +#, c-format +msgid "expected int() or something supporting coercing to int(), but got %s" +msgstr "atendis int() aลญ ion konverteblan al int(), sed ricevis %s" -#~ msgid "E744: NetBeans does not allow changes in read-only files" -#~ msgstr "E744: NetBeans ne permesas ลanฤojn en nurlegeblaj dosieroj" +msgid "value is too large to fit into C int type" +msgstr "valoro estas tro grada por C-tipo 'int'" -#~ msgid "Need encryption key for \"%s\"" -#~ msgstr "ลlosilo de ฤifrado bezonata por \"%s\"" +msgid "value is too small to fit into C int type" +msgstr "valoro estas tro malgranda por C-tipo 'int'" -#~ msgid "can't delete OutputObject attributes" -#~ msgstr "ne eblas forviลi atributojn de OutputObject" +msgid "number must be greater than zero" +msgstr "nombro devas esti pli granda ol nul" -#~ msgid "softspace must be an integer" -#~ msgstr "malmolspaceto (softspace) devas esti entjero" +msgid "number must be greater or equal to zero" +msgstr "nombro devas esti egala aลญ pli granda ol nul" -#~ msgid "invalid attribute" -#~ msgstr "nevalida atributo" +msgid "can't delete OutputObject attributes" +msgstr "ne eblas forviลi atributojn de OutputObject" -#~ msgid "writelines() requires list of strings" -#~ msgstr "writelines() bezonas liston de ฤenoj" +#, c-format +msgid "invalid attribute: %s" +msgstr "nevalida atributo: %s" -#~ msgid "E264: Python: Error initialising I/O objects" -#~ msgstr "E264: Pitono: Eraro de pravalorizo de eneligaj objektoj" +msgid "E264: Python: Error initialising I/O objects" +msgstr "E264: Pitono: Eraro de pravalorizo de eneligaj objektoj" -#~ msgid "empty keys are not allowed" -#~ msgstr "malplenaj ลlosiloj nepermeseblaj" +msgid "failed to change directory" +msgstr "malsukcesis ลanฤi dosierujon" -#~ msgid "Cannot delete DictionaryObject attributes" -#~ msgstr "ne eblas forviลi atributojn de DictionaryObject" +#, c-format +msgid "expected 3-tuple as imp.find_module() result, but got %s" +msgstr "atendis 3-opon kiel rezulto de imp.find_module(), sed ricevis %s" -#~ msgid "Cannot modify fixed dictionary" -#~ msgstr "Ne eblas ลanฤi fiksan vortaron" +#, c-format +msgid "expected 3-tuple as imp.find_module() result, but got tuple of size %d" +msgstr "atendis 3-opon kiel rezulto de imp.find_module(), sed ricevis %d-opon" -#~ msgid "Cannot set this attribute" -#~ msgstr "Ne eblas agordi tiun atributon" +msgid "internal error: imp.find_module returned tuple with NULL" +msgstr "interna eraro: imp.find_module liveris opon kun NULL" -#~ msgid "dict is locked" -#~ msgstr "vortaro estas ลlosita" +msgid "cannot delete vim.Dictionary attributes" +msgstr "ne eblas forviลi atributojn de 'vim.Dictionary'" -#~ msgid "failed to add key to dictionary" -#~ msgstr "aldono de ลlosilo al vortaro fiaskis" +msgid "cannot modify fixed dictionary" +msgstr "ne eblas ลanฤi fiksan vortaron" -#~ msgid "list index out of range" -#~ msgstr "indekso de listo ekster limoj" +#, c-format +msgid "cannot set attribute %s" +msgstr "ne eblas agordi atributon %s" -#~ msgid "internal error: failed to get vim list item" -#~ msgstr "interna eraro: obteno de vim-a listero fiaskis" +msgid "hashtab changed during iteration" +msgstr "hakettabelo ลanฤiฤis dum iteracio" -#~ msgid "list is locked" -#~ msgstr "listo estas ลlosita" +#, c-format +msgid "expected sequence element of size 2, but got sequence of size %d" +msgstr "atendis 2-longan sekvencon, sed ricevis %d-longan sekvencon" -#~ msgid "Failed to add item to list" -#~ msgstr "Aldono de listero fiaskis" +msgid "list constructor does not accept keyword arguments" +msgstr "konstruilo de listo ne akceptas ลlosilvortajn argumentojn" -#~ msgid "can only assign lists to slice" -#~ msgstr "nur eblas pravalorizi listojn al segmento" +msgid "list index out of range" +msgstr "indekso de listo ekster limoj" -#~ msgid "internal error: failed to add item to list" -#~ msgstr "interna eraro: aldono de listero fiaskis" +#. No more suitable format specifications in python-2.3 +#, c-format +msgid "internal error: failed to get vim list item %d" +msgstr "interna eraro: obteno de vim-a listero %d malsukcesis" -#~ msgid "can only concatenate with lists" -#~ msgstr "eblas nur kunmeti kun listoj" +msgid "slice step cannot be zero" +msgstr "paลo de sekco ne povas esti nul" -#~ msgid "cannot delete vim.dictionary attributes" -#~ msgstr "ne eblas forviลi atributojn de 'vim.dictionary'" +#, c-format +msgid "attempt to assign sequence of size greater than %d to extended slice" +msgstr "provis valorizi sekvencon kun pli ol %d eroj en etendita sekco" -#~ msgid "cannot modify fixed list" -#~ msgstr "ne eblas ลanฤi fiksan liston" +#, c-format +msgid "internal error: no vim list item %d" +msgstr "interna eraro: neniu vim-a listero %d" -#~ msgid "cannot set this attribute" -#~ msgstr "ne eblas agordi tiun atributon" +msgid "internal error: not enough list items" +msgstr "interna eraro: ne sufiฤaj listeroj" -#~ msgid "'self' argument must be a dictionary" -#~ msgstr "argumento 'self' devas esti vortaro" +msgid "internal error: failed to add item to list" +msgstr "interna eraro: aldono de listero malsukcesis" -#~ msgid "failed to run function" -#~ msgstr "fiaskis ruli funkcion" +#, c-format +msgid "attempt to assign sequence of size %d to extended slice of size %d" +msgstr "provis valorizi sekvencon kun %d eroj al etendita sekco kun %d eroj" -#~ msgid "unable to unset global option" -#~ msgstr "ne povis malลalti mallokan opcion" +msgid "failed to add item to list" +msgstr "aldono de listero malsukcesis" -#~ msgid "unable to unset option without global value" -#~ msgstr "ne povis malลalti opcion sen malloka valoro" +msgid "cannot delete vim.List attributes" +msgstr "ne eblas forviลi atributojn de 'vim.List'" -#~ msgid "object must be integer" -#~ msgstr "objekto devas esti entjero." +msgid "cannot modify fixed list" +msgstr "ne eblas ลanฤi fiksan liston" -#~ msgid "object must be string" -#~ msgstr "objekto devas esti ฤeno" +#, c-format +msgid "unnamed function %s does not exist" +msgstr "sennoma funkcio %s ne ekzistas" -#~ msgid "attempt to refer to deleted tab page" -#~ msgstr "provo de referenco al forviลita langeto" +#, c-format +msgid "function %s does not exist" +msgstr "funkcio %s ne ekzistas" -#~ msgid "<tabpage object (deleted) at %p>" -#~ msgstr "<langeta objekto (forviลita) ฤe %p>" +#, c-format +msgid "failed to run function %s" +msgstr "malsukcesis ruli funkcion %s" -#~ msgid "<tabpage object (unknown) at %p>" -#~ msgstr "<langeta objekto (nekonata) ฤe %p>" +msgid "unable to get option value" +msgstr "malsukcesis akiri valoron de opcio" -#~ msgid "<tabpage %d>" -#~ msgstr "<langeto %d>" +msgid "internal error: unknown option type" +msgstr "interna eraro: nekonata tipo de opcio" -#~ msgid "no such tab page" -#~ msgstr "ne estas tia langeto" +msgid "problem while switching windows" +msgstr "problemo dum salto al vindozoj" -#~ msgid "attempt to refer to deleted window" -#~ msgstr "provo de referenco al forviลita fenestro" +#, c-format +msgid "unable to unset global option %s" +msgstr "ne povis malลalti mallokan opcion %s" -#~ msgid "readonly attribute" -#~ msgstr "nurlegebla atributo" +#, c-format +msgid "unable to unset option %s which does not have global value" +msgstr "ne povis malลalti opcion %s, kiu ne havas mallokan valoron" -#~ msgid "cursor position outside buffer" -#~ msgstr "kursoro poziciita ekster bufro" +msgid "attempt to refer to deleted tab page" +msgstr "provo de referenco al forviลita langeto" -#~ msgid "<window object (deleted) at %p>" -#~ msgstr "<fenestra objekto (forviลita) ฤe %p>" +msgid "no such tab page" +msgstr "ne estas tia langeto" -#~ msgid "<window object (unknown) at %p>" -#~ msgstr "<objekta fenestro (nekonata) ฤe %p>" +msgid "attempt to refer to deleted window" +msgstr "provo de referenco al forviลita fenestro" -#~ msgid "<window %d>" -#~ msgstr "<fenestro %d>" +msgid "readonly attribute: buffer" +msgstr "nurlegebla atributo: buffer" -#~ msgid "no such window" -#~ msgstr "ne estas tia fenestro" +msgid "cursor position outside buffer" +msgstr "kursoro poziciita ekster bufro" -#~ msgid "attempt to refer to deleted buffer" -#~ msgstr "provo de referenco al forviลita bufro" +msgid "no such window" +msgstr "ne estas tia fenestro" -#~ msgid "<buffer object (deleted) at %p>" -#~ msgstr "<bufra objekto (forviลita) ฤe %p>" +msgid "attempt to refer to deleted buffer" +msgstr "provo de referenco al forviลita bufro" -#~ msgid "key must be integer" -#~ msgstr "ลlosilo devas esti entjero." +msgid "failed to rename buffer" +msgstr "malsukcesis renomi bufron" -#~ msgid "expected vim.buffer object" -#~ msgstr "atendis objekton vim.buffer" +msgid "mark name must be a single character" +msgstr "nomo de marko devas esti unuopa signo" -#~ msgid "failed to switch to given buffer" -#~ msgstr "ne povis salti al la specifita bufro" +#, c-format +msgid "expected vim.Buffer object, but got %s" +msgstr "atendis objekton vim.Buffer, sed ricevis %s" -#~ msgid "expected vim.window object" -#~ msgstr "atendis objekton vim.window" +#, c-format +msgid "failed to switch to buffer %d" +msgstr "salto al la bufro %d malsukcesis" -#~ msgid "failed to find window in the current tab page" -#~ msgstr "ne povis trovi vindozon en la nuna langeto" +#, c-format +msgid "expected vim.Window object, but got %s" +msgstr "atendis objekton vim.window, sed ricevis %s" -#~ msgid "did not switch to the specified window" -#~ msgstr "ne saltis al la specifita vindozo" +msgid "failed to find window in the current tab page" +msgstr "malsukcesis trovi vindozon en la nuna langeto" -#~ msgid "expected vim.tabpage object" -#~ msgstr "atendis objekton vim.tabpage" +msgid "did not switch to the specified window" +msgstr "ne saltis al la specifita vindozo" -#~ msgid "did not switch to the specified tab page" -#~ msgstr "ne saltis al la specifita langeto" +#, c-format +msgid "expected vim.TabPage object, but got %s" +msgstr "atendis objekton vim.TabPage, sed ricevis %s" -#~ msgid "failed to run the code" -#~ msgstr "fiaskis ruli la kodon" +msgid "did not switch to the specified tab page" +msgstr "ne saltis al la specifita langeto" -#~ msgid "E858: Eval did not return a valid python object" -#~ msgstr "E858: Eval ne revenis kun valida python-objekto" +msgid "failed to run the code" +msgstr "malsukcesis ruli la kodon" -#~ msgid "E859: Failed to convert returned python object to vim value" -#~ msgstr "E859: Konverto de revena python-objekto al vim-valoro fiaskis" +msgid "E858: Eval did not return a valid python object" +msgstr "E858: Eval ne revenis kun valida python-objekto" -#~ msgid "unable to convert to vim structure" -#~ msgstr "ne povis konverti al vim-strukturo" +msgid "E859: Failed to convert returned python object to vim value" +msgstr "E859: Konverto de revena python-objekto al vim-valoro malsukcesis" -#~ msgid "NULL reference passed" -#~ msgstr "NULL-referenco argumento" +#, c-format +msgid "unable to convert %s to vim dictionary" +msgstr "ne povis konverti %s al vim-vortaro" -#~ msgid "internal error: invalid value type" -#~ msgstr "interna eraro: nevalida tipo de valoro" +#, c-format +msgid "unable to convert %s to vim list" +msgstr "ne povis konverti %s al vim-listo" -#~ msgid "E863: return value must be an instance of str" -#~ msgstr "E863: elira valoro devas esti apero de str" +#, c-format +msgid "unable to convert %s to vim structure" +msgstr "ne povis konverti %s al vim-strukturo" -#~ msgid "E860: Eval did not return a valid python 3 object" -#~ msgstr "E860: Eval ne revenis kun valida python3-objekto" +msgid "internal error: NULL reference passed" +msgstr "interna eraro: NULL-referenco argumento" -#~ msgid "E861: Failed to convert returned python 3 object to vim value" -#~ msgstr "E861: Konverto de revena python3-objekto al vim-valoro fiaskis" +msgid "internal error: invalid value type" +msgstr "interna eraro: nevalida tipo de valoro" -#~ msgid "Only boolean objects are allowed" -#~ msgstr "Nur buleaj objektoj estas permeseblaj" +msgid "" +"Failed to set path hook: sys.path_hooks is not a list\n" +"You should now do the following:\n" +"- append vim.path_hook to sys.path_hooks\n" +"- append vim.VIM_SPECIAL_PATH to sys.path\n" +msgstr "" +"Valorizo de sys.path_hooks malsukcesis: sys.path_hooks ne estas listo\n" +"Vi nun devas fari tion:\n" +"- postaldoni vim.path_hook al sys.path_hooks\n" +"- postaldoni vim.VIM_SPECIAL_PATH al sys.path\n" -#~ msgid "no such key in dictionary" -#~ msgstr "tiu ลlosilo ne ekzistas en vortaro" +msgid "" +"Failed to set path: sys.path is not a list\n" +"You should now append vim.VIM_SPECIAL_PATH to sys.path" +msgstr "" +"Agordo de serฤvojo malsukcesis: sys.path ne estas listo\n" +"Vi nun devas aldoni vim.VIM_SPECIAL_PATH al sys.path" diff --git a/src/nvim/po/fi.po b/src/nvim/po/fi.po index d30faeb554..3551c07ff2 100644 --- a/src/nvim/po/fi.po +++ b/src/nvim/po/fi.po @@ -1,247 +1,419 @@ # Finnish translation for Vim. # Copyright (C) 2003-2006 Free Software Foundation, Inc. -# 2007-2010, Flammie Pirinen <flammie@iki.fi> +# 2007-2016, Flammie Pirinen <flammie@iki.fi> # -# Vimin kไyttไjไt on n๖rttejไ. Sanasto on jargonia :-p -# -# Lไhinnไ latin-1:tไ, sillไ vim pitไไ portata ilmeisen obskuureille -# alustoille. My๖s: pluralit puuttuu, ohjelman kไytt๖liittymไn fontti -# tasavไlinen, tila rajattu, jne. jne., luovia ratkaisuja edessไ. +# Jargonia ei ole yritetty suotta kotoperรคistรครค missรค teknisempi lainasanasto +# tulee paremmin kyseeseen. # # Sanastosta: -# Fold on sellainen moderneissa ohjelmointi-IDE:issไ oleva toiminto, jolla -# lohko koodia esim. funktio piilotetaan nไkymไstไ: suom. taitos alkup. +# * Fold on sellainen moderneissa ohjelmointi-IDE:issรค oleva toiminto, jolla +# lohko koodia esim. funktio piilotetaan nรคkymรคstรค: suom. taitos alkup. # analogian mukaan -# source v. lataa tiedoston, kuten bash-komento source (tai .) +# * source, v. lataa tiedoston, kuten bash-komento source (tai .) +# * dictionary (dict) on vaihtelevasti sanakirja tai tietorakenne # msgid "" msgstr "" "Project-Id-Version: Vim 7\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-05-26 14:21+0200\n" -"PO-Revision-Date: 2010-08-09 02:35+0300\n" -"Last-Translator: Flammie Pirinen <flammie@iki.fi>\n" +"POT-Creation-Date: 2017-04-19 16:46+0200\n" +"PO-Revision-Date: 2016-08-29 11:27+0200\n" +"Last-Translator: Flammie A Pirinen <flammie@iki.fi>\n" "Language-Team: Finnish <laatu@lokalisointi.org>\n" "Language: fi\n" "MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=ISO-8859-1\n" +"Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: ../api/private/helpers.c:201 #, fuzzy -msgid "Unable to get option value" -msgstr "Roskaa argumentin perไssไ" +#~ msgid "Index out of bounds" +#~ msgstr "ei lรถytynyt " -#: ../api/private/helpers.c:204 -msgid "internal error: unknown option type" -msgstr "" +#, fuzzy +#~ msgid "Line index is too high" +#~ msgstr "ikkunan indeksi alueen ulkopuolella" + +#~ msgid "Argument \"start\" is higher than \"end\"" +#~ msgstr "" + +#~ msgid "All items in the replacement array must be strings" +#~ msgstr "" + +msgid "string cannot contain newlines" +msgstr "merkkijono ei saa sisรคltรครค rivinvaihtoja" + +#, fuzzy +#~ msgid "Failed to save undo information" +#~ msgstr "ei voitu tallentaa kumoustietoja" + +#, fuzzy +#~ msgid "Failed to delete line" +#~ msgstr "ei voitu poistaa riviรค" + +#~ msgid "Index value is too high" +#~ msgstr "" + +#, fuzzy +#~ msgid "Failed to replace line" +#~ msgstr "ei voitu korvata riviรค" + +#, fuzzy +#~ msgid "Failed to insert line" +#~ msgstr "ei voitu lisรคtรค riviรค" + +#, fuzzy +#~ msgid "Failed to rename buffer" +#~ msgstr "ei voity uudelleennimetรค puskuria" + +#, fuzzy +#~ msgid "Mark name must be a single character" +#~ msgstr "merkin nimen pitรครค olla yksi merkki" + +#, fuzzy +#~ msgid "Invalid mark name" +#~ msgstr "virheellinen merkin nimi" + +#, fuzzy +#~ msgid "Line number outside range" +#~ msgstr "rivinumero arvoalueen ulkopuolella" + +#, fuzzy +#~ msgid "Column value outside range" +#~ msgstr "rivinumero arvoalueen ulkopuolella" + +#, fuzzy +#~ msgid "Keyboard interrupt" +#~ msgstr "nรคppรคimistรถkeskeytys" + +#, fuzzy +#~ msgid "Key not found" +#~ msgstr "ei lรถytynyt " + +#, fuzzy +#~ msgid "Dictionary is locked" +#~ msgstr "dictionary on lukittu" + +#, fuzzy +#~ msgid "Empty variable names aren't allowed" +#~ msgstr "tyhjiรค avaimia ei voi kรคyttรครค" + +#, fuzzy +#~ msgid "Key length is too high" +#~ msgstr "Liian pitkรค polku" + +#, c-format +#~ msgid "Key is read-only: %s" +#~ msgstr "" + +#, c-format +#~ msgid "Key is fixed: %s" +#~ msgstr "" + +#, fuzzy, c-format +#~ msgid "Key is locked: %s" +#~ msgstr "E741: Arvo on lukittu: %s" + +#. Doesn't exist, fail +#, fuzzy, c-format +#~ msgid "Key does not exist: %s" +#~ msgstr "Tiedostoa %s ei ole" + +#, fuzzy +#~ msgid "Empty option name" +#~ msgstr "E792: tyhjรค valikkonimi" + +#, fuzzy, c-format +#~ msgid "Invalid option name \"%s\"" +#~ msgstr "E755: Virheellinen alue kohteelle %s" + +#, fuzzy, c-format +#~ msgid "Unable to get value for option \"%s\"" +#~ msgstr "ei voi tyhjentรครค yleistรค asetusta %s" + +#, fuzzy, c-format +#~ msgid "Unknown type for option \"%s\"" +#~ msgstr "E113: Tuntematon asetus: %s" + +#, fuzzy, c-format +#~ msgid "Unable to unset option \"%s\"" +#~ msgstr "ei voi tyhjentรครค yleistรค asetusta %s" + +#, fuzzy, c-format +#~ msgid "Cannot unset option \"%s\" because it doesn't have a global value" +#~ msgstr "ei voi tyhjentรครค asetusta %s jolla ei ole yleistรค arvoa" + +#, c-format +#~ msgid "Option \"%s\" requires a boolean value" +#~ msgstr "" + +#, fuzzy, c-format +#~ msgid "Option \"%s\" requires an integer value" +#~ msgstr "E709: [:] toimii vain listalla" + +#, c-format +#~ msgid "Value for option \"%s\" is outside range" +#~ msgstr "" + +#, fuzzy, c-format +#~ msgid "Option \"%s\" requires a string value" +#~ msgstr "E709: [:] toimii vain listalla" + +#, fuzzy +#~ msgid "Invalid buffer id" +#~ msgstr "virheellinen puskurinumero" + +#, fuzzy +#~ msgid "Invalid window id" +#~ msgstr "E534: Viallinen leveรค fontti" + +#, fuzzy +#~ msgid "Invalid tabpage id" +#~ msgstr "Vรครคrรค argumentti valitsimelle" + +#~ msgid "Integer value outside range" +#~ msgstr "" + +#, fuzzy +#~ msgid "Empty dictionary keys aren't allowed" +#~ msgstr "tyhjiรค avaimia ei voi kรคyttรครค" + +#, fuzzy +#~ msgid "Problem while switching windows" +#~ msgstr "virhe ikkunaa vaihtaessa" + +#, fuzzy +#~ msgid "UI already attached for channel" +#~ msgstr "Vanhimmassa muutoksessa" + +#~ msgid "Expected width > 0 and height > 0" +#~ msgstr "" + +#~ msgid "UI is not attached for channel" +#~ msgstr "" + +#~ msgid "rgb must be a Boolean" +#~ msgstr "" + +#~ msgid "popupmenu_external must be a Boolean" +#~ msgstr "" + +#, fuzzy +#~ msgid "No such ui option" +#~ msgstr "E24: Lyhennettรค ei ole" + +#~ msgid "Function called with too many arguments." +#~ msgstr "" + +#~ msgid "Error calling function." +#~ msgstr "" + +#, fuzzy +#~ msgid "String length is too high" +#~ msgstr "Liian pitkรค polku" + +#~ msgid "Directory string is too long" +#~ msgstr "" + +#, fuzzy +#~ msgid "Failed to change directory" +#~ msgstr "hakemistoa ei voitu muuttaa" + +#, fuzzy, c-format +#~ msgid "Failed to switch to buffer %d" +#~ msgstr "ei voitu vaihtaa puskuriin %d" + +#, fuzzy, c-format +#~ msgid "Failed to switch to window %d" +#~ msgstr "ei voitu vaihtaa puskuriin %d" + +#, fuzzy, c-format +#~ msgid "Failed to switch to tabpage %d" +#~ msgstr "ei voitu vaihtaa puskuriin %d" + +#~ msgid "All items in calls array must be arrays" +#~ msgstr "" + +#~ msgid "All items in calls array must be arrays of size 2" +#~ msgstr "" + +#~ msgid "name must be String" +#~ msgstr "" + +#~ msgid "args must be Array" +#~ msgstr "" + +# datarakenteita +#, fuzzy +#~ msgid "Argument \"pos\" must be a [row, col] array" +#~ msgstr "E712: Argumentin %s pitรครค olla lista tai sanakirja" + +#, fuzzy +#~ msgid "Cursor position outside buffer" +#~ msgstr "kursorin sijainti puskurin ulkopuolella" + +#~ msgid "Height value outside range" +#~ msgstr "" + +#~ msgid "Width value outside range" +#~ msgstr "" -#: ../buffer.c:92 msgid "[Location List]" msgstr "[Sijaintiluettelo]" -#: ../buffer.c:93 msgid "[Quickfix List]" msgstr "[Pikakorjausluettelo]" -#: ../buffer.c:94 -#, fuzzy msgid "E855: Autocommands caused command to abort" -msgstr "E812: Autocommands muutti puskurin tai sen nimen" +msgstr "E855: Autocommands lopetti komennon" -#: ../buffer.c:135 msgid "E82: Cannot allocate any buffer, exiting..." -msgstr "E82: Mitไไn puskuria ei voitu varata, lopetetaan..." +msgstr "E82: Mitรครคn puskuria ei voitu varata, lopetetaan..." -#: ../buffer.c:138 msgid "E83: Cannot allocate buffer, using other one..." -msgstr "E83: Puskuria ei voitu varata, kไytetไไn toista..." +msgstr "E83: Puskuria ei voitu varata, kรคytetรครคn toista..." + +#, fuzzy +#~ msgid "E937: Attempt to delete a buffer that is in use" +#~ msgstr "E934: Ei voida hypรคtรค puskuriin jolla ei ole nimeรค" -#: ../buffer.c:763 msgid "E515: No buffers were unloaded" msgstr "E515: Puskureita ei vapautettu" -#: ../buffer.c:765 msgid "E516: No buffers were deleted" msgstr "E516: Puskureita ei poistettu" -#: ../buffer.c:767 msgid "E517: No buffers were wiped out" msgstr "E517: Puskureita ei pyyhitty" -#: ../buffer.c:772 msgid "1 buffer unloaded" msgstr "1 puskuri vapautettiin" -#: ../buffer.c:774 #, c-format msgid "%d buffers unloaded" msgstr "%d puskuria vapautettiin" -#: ../buffer.c:777 msgid "1 buffer deleted" msgstr "1 puskuri poistettu" -#: ../buffer.c:779 #, c-format msgid "%d buffers deleted" msgstr "%d puskuria poistettu" -#: ../buffer.c:782 msgid "1 buffer wiped out" msgstr "1 puskuri pyyhitty" -#: ../buffer.c:784 #, c-format msgid "%d buffers wiped out" msgstr "%d puskuria pyyhitty" -#: ../buffer.c:806 msgid "E90: Cannot unload last buffer" -msgstr "E90: Ei voi vapauttaa viimeistไ puskuria" +msgstr "E90: Ei voi vapauttaa viimeistรค puskuria" -#: ../buffer.c:874 msgid "E84: No modified buffer found" msgstr "E84: Ei muokattuja puskureita" #. back where we started, didn't find anything. -#: ../buffer.c:903 msgid "E85: There is no listed buffer" msgstr "E85: Luetteloitua puskuria ei ole" -#: ../buffer.c:913 -#, c-format -msgid "E86: Buffer %<PRId64> does not exist" -msgstr "E86: Puskuria %<PRId64> ei ole" - -#: ../buffer.c:915 msgid "E87: Cannot go beyond last buffer" -msgstr "E87: Viimeisen puskurin ohi ei voi edetไ" +msgstr "E87: Viimeisen puskurin ohi ei voi edetรค" -#: ../buffer.c:917 msgid "E88: Cannot go before first buffer" -msgstr "E88: Ensimmไisen puskurin ohi ei voi edetไ" +msgstr "E88: Ensimmรคisen puskurin ohi ei voi edetรค" -#: ../buffer.c:945 -#, c-format +#, fuzzy, c-format +#~ msgid "E89: %s will be killed(add ! to override)" +#~ msgstr "E189: %s on jo olemassa (lisรครค komentoon ! ohittaaksesi)" + +#, fuzzy, c-format msgid "" "E89: No write since last change for buffer %<PRId64> (add ! to override)" msgstr "" -"E89: Puskurin %<PRId64> muutoksia ei ole tallennettu (lisไไ komentoon ! " +"E89: Puskurin %ld muutoksia ei ole tallennettu (lisรครค komentoon ! " "ohittaaksesi)" #. wrap around (may cause duplicates) -#: ../buffer.c:1423 msgid "W14: Warning: List of file names overflow" msgstr "W14: Varoitus: Tiedostonimiluettelon ylivuoto" -#: ../buffer.c:1555 ../quickfix.c:3361 -#, c-format -msgid "E92: Buffer %<PRId64> not found" -msgstr "E92: Puskuria %<PRId64> ei l๖ydy" +#, fuzzy, c-format +#~ msgid "E92: Buffer %<PRId64> not found" +#~ msgstr "E92: Puskuria %ld ei lรถydy" -#: ../buffer.c:1798 #, c-format msgid "E93: More than one match for %s" -msgstr "E93: %s tไsmไไ useampaan kuin yhteen puskuriin" +msgstr "E93: %s tรคsmรครค useampaan kuin yhteen puskuriin" -#: ../buffer.c:1800 #, c-format msgid "E94: No matching buffer for %s" -msgstr "E94: %s ei tไsmไไ yhteenkไไn puskuriin" +msgstr "E94: %s ei tรคsmรครค yhteenkรครคn puskuriin" -#: ../buffer.c:2161 -#, c-format -msgid "line %<PRId64>" -msgstr "rivi %<PRId64>" +#, fuzzy, c-format +#~ msgid "line %<PRId64>" +#~ msgstr "rivi %ld" -#: ../buffer.c:2233 msgid "E95: Buffer with this name already exists" msgstr "E95: Samanniminen puskuri on jo olemassa" -#: ../buffer.c:2498 msgid " [Modified]" msgstr " [Muokattu]" -#: ../buffer.c:2501 msgid "[Not edited]" msgstr "[Muokkaamaton]" -#: ../buffer.c:2504 msgid "[New file]" msgstr "[Uusi tiedosto]" -#: ../buffer.c:2505 msgid "[Read errors]" -msgstr "[Lukuvirheitไ]" +msgstr "[Lukuvirheitรค]" -#: ../buffer.c:2506 ../buffer.c:3217 ../fileio.c:1807 ../screen.c:4895 msgid "[RO]" msgstr "[Luku]" -#: ../buffer.c:2507 ../fileio.c:1807 msgid "[readonly]" msgstr "[kirjoitussuojattu]" -#: ../buffer.c:2524 #, c-format msgid "1 line --%d%%--" msgstr "1 rivi --%d %%--" -#: ../buffer.c:2526 -#, c-format -msgid "%<PRId64> lines --%d%%--" -msgstr "%<PRId64> riviไ --%d %%--" +#, fuzzy, c-format +#~ msgid "%<PRId64> lines --%d%%--" +#~ msgstr "%ld riviรค --%d %%--" -#: ../buffer.c:2530 -#, c-format -msgid "line %<PRId64> of %<PRId64> --%d%%-- col " -msgstr "rivi %<PRId64>/%<PRId64> --%d %%-- sarake " +#, fuzzy, c-format +#~ msgid "line %<PRId64> of %<PRId64> --%d%%-- col " +#~ msgstr "rivi %ld/%ld --%d %%-- sarake " -#: ../buffer.c:2632 ../buffer.c:4292 ../memline.c:1554 msgid "[No Name]" -msgstr "[Nimet๖n]" +msgstr "[Nimetรถn]" #. must be a help buffer -#: ../buffer.c:2667 msgid "help" msgstr "ohje" -#: ../buffer.c:3225 ../screen.c:4883 msgid "[Help]" msgstr "[Ohje]" -#: ../buffer.c:3254 ../screen.c:4887 msgid "[Preview]" msgstr "[Esikatselu]" # sijainti tiedostossa -indikaattoreja: -# 4 merkkiไ sais riittไไ -#: ../buffer.c:3528 +# 4 merkkiรค sais riittรครค msgid "All" msgstr "Kaik" -#: ../buffer.c:3528 msgid "Bot" msgstr "Loppu" -#: ../buffer.c:3531 msgid "Top" msgstr "Alku" -#: ../buffer.c:4244 -msgid "" -"\n" -"# Buffer list:\n" -msgstr "" -"\n" -"# Puskuriluettelo:\n" - -#: ../buffer.c:4289 msgid "[Scratch]" msgstr "[Raapust]" -#: ../buffer.c:4529 msgid "" "\n" "--- Signs ---" @@ -249,795 +421,669 @@ msgstr "" "\n" "--- Merkit ---" -#: ../buffer.c:4538 #, c-format msgid "Signs for %s:" msgstr "Merkit kohteelle %s:" -#: ../buffer.c:4543 -#, c-format -msgid " line=%<PRId64> id=%d name=%s" -msgstr " rivi=%<PRId64> id=%d nimi=%s" +#, fuzzy, c-format +#~ msgid " line=%<PRId64> id=%d name=%s" +#~ msgstr " rivi=%ld id=%d nimi=%s" -#: ../cursor_shape.c:68 msgid "E545: Missing colon" msgstr "E545: Kaksoispiste puuttuu" -#: ../cursor_shape.c:70 ../cursor_shape.c:94 msgid "E546: Illegal mode" msgstr "E546: Virheellinen tila" -#: ../cursor_shape.c:134 msgid "E548: digit expected" -msgstr "E548: pitไไ olla numero" +msgstr "E548: pitรครค olla numero" -#: ../cursor_shape.c:138 msgid "E549: Illegal percentage" msgstr "E549: Virheellinen prosenttiluku" -#: ../diff.c:146 -#, c-format -msgid "E96: Can not diff more than %<PRId64> buffers" -msgstr "E96: Ei voi diffata enempไไ kuin %<PRId64> puskuria" +#, fuzzy, c-format +#~ msgid "E96: Cannot diff more than %<PRId64> buffers" +#~ msgstr "E96: Ei voi diffata enempรครค kuin %ld puskuria" -#: ../diff.c:753 msgid "E810: Cannot read or write temp files" -msgstr "E810: Ei voi lukea tai kirjoittaa vไliaikaistiedostoja" +msgstr "E810: Ei voi lukea tai kirjoittaa vรคliaikaistiedostoja" -#: ../diff.c:755 msgid "E97: Cannot create diffs" -msgstr "E97: Ei voi luoda diffejไ" +msgstr "E97: Ei voi luoda diffejรค" -#: ../diff.c:966 msgid "E816: Cannot read patch output" msgstr "E816: Ei voi lukea patchin tulostetta" -#: ../diff.c:1220 msgid "E98: Cannot read diff output" msgstr "E98: Ei voi lukea diffin tulostetta" -#: ../diff.c:2081 msgid "E99: Current buffer is not in diff mode" -msgstr "E99: Tไmไ puskuri ei ole diff-tilassa" +msgstr "E99: Tรคmรค puskuri ei ole diff-tilassa" -#: ../diff.c:2100 msgid "E793: No other buffer in diff mode is modifiable" -msgstr "E793: Yksikไไn muu diff-tilan puskurit ei ole muokattavissa" +msgstr "E793: Yksikรครคn muu diff-tilan puskurit ei ole muokattavissa" -#: ../diff.c:2102 msgid "E100: No other buffer in diff mode" -msgstr "E100: Yksikไไn muu puskuri ei ole diff-tilassa" +msgstr "E100: Yksikรครคn muu puskuri ei ole diff-tilassa" -#: ../diff.c:2112 msgid "E101: More than two buffers in diff mode, don't know which one to use" -msgstr "E101: Monta puskuria on diff-tilassa, kไytettไvไn valinta ei onnistu" +msgstr "E101: Monta puskuria on diff-tilassa, kรคytettรคvรคn valinta ei onnistu" -#: ../diff.c:2141 #, c-format msgid "E102: Can't find buffer \"%s\"" -msgstr "E102: Puskuria %s ei l๖ydy" +msgstr "E102: Puskuria %s ei lรถydy" -#: ../diff.c:2152 #, c-format msgid "E103: Buffer \"%s\" is not in diff mode" msgstr "E103: Puskuri %s ei ole diff-tilassa" -#: ../diff.c:2193 msgid "E787: Buffer changed unexpectedly" msgstr "E787: Puskuri vaihtui odottamatta" -#: ../digraph.c:1598 msgid "E104: Escape not allowed in digraph" -msgstr "E104: Escapea ei voi kไyttไไ digraafissa" +msgstr "E104: Escapea ei voi kรคyttรครค digraafissa" -#: ../digraph.c:1760 msgid "E544: Keymap file not found" -msgstr "E544: Nไppไinkarttaa ei l๖ydy" +msgstr "E544: Nรคppรคinkarttaa ei lรถydy" -#: ../digraph.c:1785 msgid "E105: Using :loadkeymap not in a sourced file" -msgstr "E105: Kไytetไไn :loadkeymapia ladatun tiedoston ulkopuolella" +msgstr "E105: Kรคytetรครคn :loadkeymapia ladatun tiedoston ulkopuolella" -#: ../digraph.c:1821 msgid "E791: Empty keymap entry" -msgstr "E791: Tyhjไ keymap-kenttไ" +msgstr "E791: Tyhjรค keymap-kenttรค" -#: ../edit.c:82 msgid " Keyword completion (^N^P)" -msgstr " Avainsanatไydennys (^N^P)" +msgstr " Avainsanatรคydennys (^N^P)" #. ctrl_x_mode == 0, ^P/^N compl. -#: ../edit.c:83 msgid " ^X mode (^]^D^E^F^I^K^L^N^O^Ps^U^V^Y)" msgstr " ^X-tila (^]^D^E^F^I^K^L^N^O^Ps^U^V^Y)" -#: ../edit.c:85 msgid " Whole line completion (^L^N^P)" -msgstr " Tไysrivitไydennys (^L^N^P)" +msgstr " Tรคysrivitรคydennys (^L^N^P)" -#: ../edit.c:86 msgid " File name completion (^F^N^P)" -msgstr " Tiedostonimitไydennys (^F^N^P)" +msgstr " Tiedostonimitรคydennys (^F^N^P)" -#: ../edit.c:87 msgid " Tag completion (^]^N^P)" -msgstr " Tไgitไydennys (^]^N^P)" +msgstr " Tรคgitรคydennys (^]^N^P)" -#: ../edit.c:88 msgid " Path pattern completion (^N^P)" -msgstr " Polkukuviotไydennys (^N^P)" +msgstr " Polkukuviotรคydennys (^N^P)" -#: ../edit.c:89 msgid " Definition completion (^D^N^P)" -msgstr " Mไไritelmไtไydennys (^D^N^P)" +msgstr " Mรครคritelmรคtรคydennys (^D^N^P)" -#: ../edit.c:91 msgid " Dictionary completion (^K^N^P)" -msgstr " Sanakirjatไydennys (^K^N^P)" +msgstr " Sanakirjatรคydennys (^K^N^P)" -#: ../edit.c:92 msgid " Thesaurus completion (^T^N^P)" -msgstr " Thesaurus-tไydennys (^T^N^P)" +msgstr " Thesaurus-tรคydennys (^T^N^P)" -#: ../edit.c:93 msgid " Command-line completion (^V^N^P)" -msgstr " Komentorivitไydennys (^V^N^P)" +msgstr " Komentorivitรคydennys (^V^N^P)" -#: ../edit.c:94 msgid " User defined completion (^U^N^P)" -msgstr " Kไyttไjไn mไไrittelemไ tไydennys (^U^N^P)" +msgstr " Kรคyttรคjรคn mรครคrittelemรค tรคydennys (^U^N^P)" -#: ../edit.c:95 msgid " Omni completion (^O^N^P)" -msgstr " Omnitไydennys (^O^N^P)" +msgstr " Omnitรคydennys (^O^N^P)" -#: ../edit.c:96 msgid " Spelling suggestion (s^N^P)" msgstr " Oikaisulukuehdotus (s^N^P)" -#: ../edit.c:97 msgid " Keyword Local completion (^N^P)" -msgstr " Avainsanan paikallinen tไydennys (^N^P)" +msgstr " Avainsanan paikallinen tรคydennys (^N^P)" -#: ../edit.c:100 msgid "Hit end of paragraph" msgstr "Kappaleen loppu tuli vastaan" -#: ../edit.c:101 -#, fuzzy msgid "E839: Completion function changed window" -msgstr "E813: Ei voi sulkea autocmd-ikkunaa" +msgstr "E839: Tรคydennys vaihtoi ikkunaa" -#: ../edit.c:102 msgid "E840: Completion function deleted text" -msgstr "" +msgstr "E840: Tรคydennys poisti tekstiรค" -#: ../edit.c:1847 msgid "'dictionary' option is empty" -msgstr "dictionary-asetus on tyhjไ" +msgstr "dictionary-asetus on tyhjรค" -#: ../edit.c:1848 msgid "'thesaurus' option is empty" -msgstr "thesaurus-asetus on tyhjไ" +msgstr "thesaurus-asetus on tyhjรค" -#: ../edit.c:2655 #, c-format msgid "Scanning dictionary: %s" msgstr "Luetaan sanakirjaa: %s" -#: ../edit.c:3079 msgid " (insert) Scroll (^E/^Y)" -msgstr " (sy๖tt๖) Vieritys (^E/^Y)" +msgstr " (syรถttรถ) Vieritys (^E/^Y)" -#: ../edit.c:3081 msgid " (replace) Scroll (^E/^Y)" msgstr " (korvaus) Vieritys (^E/^Y)" -#: ../edit.c:3587 #, c-format msgid "Scanning: %s" msgstr "Luetaan: %s" -#: ../edit.c:3614 msgid "Scanning tags." -msgstr "Luetaan tไgejไ." +msgstr "Luetaan tรคgejรค." -#: ../edit.c:4519 msgid " Adding" -msgstr " Lisไtไไn" +msgstr " Lisรคtรครคn" #. showmode might reset the internal line pointers, so it must #. * be called before line = ml_get(), or when this address is no #. * longer needed. -- Acevedo. #. -#: ../edit.c:4562 msgid "-- Searching..." msgstr "-- Haetaan..." -#: ../edit.c:4618 msgid "Back at original" -msgstr "Takaisin lไht๖pisteessไ" +msgstr "Takaisin lรคhtรถpisteessรค" -#: ../edit.c:4621 msgid "Word from other line" -msgstr "Sana toisella rivillไ" +msgstr "Sana toisella rivillรค" -#: ../edit.c:4624 msgid "The only match" -msgstr "Ainoa tไsmไys" +msgstr "Ainoa tรคsmรคys" -#: ../edit.c:4680 #, c-format msgid "match %d of %d" -msgstr "tไsmไys %d/%d" +msgstr "tรคsmรคys %d/%d" -#: ../edit.c:4684 #, c-format msgid "match %d" -msgstr "tไsmไys %d" +msgstr "tรคsmรคys %d" -#: ../eval.c:137 msgid "E18: Unexpected characters in :let" -msgstr "E18: Odottamattomia merkkejไ komennossa :let" - -#: ../eval.c:138 -#, c-format -msgid "E684: list index out of range: %<PRId64>" -msgstr "E684: Indeksi %<PRId64> luettelon rajojen ulkopuolella" +msgstr "E18: Odottamattomia merkkejรค komennossa :let" -#: ../eval.c:139 -#, c-format -msgid "E121: Undefined variable: %s" -msgstr "E121: Mไไrittelemไt๖n muuttuja: %s" - -#: ../eval.c:140 msgid "E111: Missing ']'" msgstr "E111: ] puuttuu" -#: ../eval.c:141 #, c-format msgid "E686: Argument of %s must be a List" -msgstr "E686: Argumentin %s pitไไ olla lista" +msgstr "E686: Argumentin %s pitรครค olla lista" # datarakenteita -#: ../eval.c:143 #, c-format msgid "E712: Argument of %s must be a List or Dictionary" -msgstr "E712: Argumentin %s pitไไ olla lista tai sanakirja" - -#: ../eval.c:144 -msgid "E713: Cannot use empty key for Dictionary" -msgstr "E713: Sanakirjassa ei voi olla tyhjiไ avaimia" +msgstr "E712: Argumentin %s pitรครค olla lista tai sanakirja" -#: ../eval.c:145 msgid "E714: List required" msgstr "E714: Lista tarvitaan" -#: ../eval.c:146 msgid "E715: Dictionary required" msgstr "E715: Sanakirja tarvitaan" -#: ../eval.c:147 +msgid "E928: String required" +msgstr "E928: Merkkijono puuttuu" + #, c-format msgid "E118: Too many arguments for function: %s" msgstr "E118: Liikaa argumentteja funktiolle: %s" -#: ../eval.c:148 #, c-format msgid "E716: Key not present in Dictionary: %s" msgstr "E716: Avainta %s ei ole sanakirjassa" -#: ../eval.c:150 #, c-format msgid "E122: Function %s already exists, add ! to replace it" -msgstr "E122: Funktio %s on jo olemassa, lisไไ ! korvataksesi" +msgstr "E122: Funktio %s on jo olemassa, lisรครค ! korvataksesi" -#: ../eval.c:151 msgid "E717: Dictionary entry already exists" msgstr "E717: Sanakirja-alkio on jo olemassa" -#: ../eval.c:152 msgid "E718: Funcref required" msgstr "E718: Funcref tarvitaan" -#: ../eval.c:153 msgid "E719: Cannot use [:] with a Dictionary" -msgstr "E719: Sanakirjassa ei voi kไyttไไ merkintไไ [:]" +msgstr "E719: Sanakirjassa ei voi kรคyttรครค merkintรครค [:]" -#: ../eval.c:154 -#, c-format -msgid "E734: Wrong variable type for %s=" -msgstr "E734: Vไไrไ muuttujatyyppi muuttujalle %s=" - -#: ../eval.c:155 #, c-format msgid "E130: Unknown function: %s" msgstr "E130: Tuntematon funktio: %s" -#: ../eval.c:156 #, c-format msgid "E461: Illegal variable name: %s" msgstr "E461: Virheellinen muuttujanimi: %s" -#: ../eval.c:157 -msgid "E806: using Float as a String" -msgstr "E806: Float ei kไy merkkijonosta" +#, fuzzy, c-format +#~ msgid "E46: Cannot change read-only variable \"%.*s\"" +#~ msgstr "E46: Kirjoitussuojattua muuttujaa %s ei voi muuttaa" + +#. TODO(ZyX-I): move to eval/executor +#, c-format +msgid "E734: Wrong variable type for %s=" +msgstr "E734: Vรครคrรค muuttujatyyppi muuttujalle %s=" -#: ../eval.c:1830 msgid "E687: Less targets than List items" -msgstr "E687: Kohteita on vไhemmไn kuin listan alkioita" +msgstr "E687: Kohteita on vรคhemmรคn kuin listan alkioita" -#: ../eval.c:1834 msgid "E688: More targets than List items" -msgstr "E688: Kohteita on enemmไn kuin listan alkioita" +msgstr "E688: Kohteita on enemmรคn kuin listan alkioita" -#: ../eval.c:1906 msgid "Double ; in list of variables" -msgstr "Kaksi ;:ttไ listan muuttujissa" +msgstr "Kaksi ;:ttรค listan muuttujissa" -#: ../eval.c:2078 #, c-format msgid "E738: Can't list variables for %s" msgstr "E738: Kohteen %s muuttujia ei voi listata" -#: ../eval.c:2391 +#, fuzzy, c-format +#~ msgid "E121: Undefined variable: %.*s" +#~ msgstr "E121: Mรครคrittelemรคtรถn muuttuja: %s" + msgid "E689: Can only index a List or Dictionary" -msgstr "E689: Vain listalla ja sanakirjalla voi olla indeksejไ" +msgstr "E689: Vain listalla ja sanakirjalla voi olla indeksejรค" -#: ../eval.c:2396 msgid "E708: [:] must come last" -msgstr "E708: [:]:n pitไไ olla viimeisenไ" +msgstr "E708: [:]:n pitรครค olla viimeisenรค" + +#, fuzzy +#~ msgid "E713: Cannot use empty key after ." +#~ msgstr "E713: Sanakirjassa ei voi olla tyhjiรค avaimia" -#: ../eval.c:2439 msgid "E709: [:] requires a List value" msgstr "E709: [:] toimii vain listalla" -#: ../eval.c:2674 msgid "E710: List value has more items than target" -msgstr "E710: Listalla on enemmไn alkioita kuin kohteella" +msgstr "E710: Listalla on enemmรคn alkioita kuin kohteella" -#: ../eval.c:2678 msgid "E711: List value has not enough items" msgstr "E711: Listalla ei ole tarpeeksi alkioita" -#: ../eval.c:2867 msgid "E690: Missing \"in\" after :for" msgstr "E690: :for-kommenolta puuttuu in" -#: ../eval.c:3063 #, c-format msgid "E107: Missing parentheses: %s" msgstr "E107: Sulkeita puuttuu: %s" -#: ../eval.c:3263 #, c-format msgid "E108: No such variable: \"%s\"" msgstr "E108: Muuttujaa %s ei ole" -#: ../eval.c:3333 -msgid "E743: variable nested too deep for (un)lock" -msgstr "E743: muuttujassa liian monta tasoa lukituksen kไsittelyyn" +#. For historical reasons this error is not given for Lists and +#. Dictionaries. E.g. b: dictionary may be locked/unlocked. +#, fuzzy, c-format +#~ msgid "E940: Cannot lock or unlock variable %s" +#~ msgstr "E46: Kirjoitussuojattua muuttujaa %s ei voi muuttaa" -#: ../eval.c:3630 msgid "E109: Missing ':' after '?'" -msgstr "E109: ?:n jไlkeen puuttuu :" +msgstr "E109: ?:n jรคlkeen puuttuu :" -#: ../eval.c:3893 msgid "E691: Can only compare List with List" msgstr "E691: Listaa voi verrata vain listaan" -#: ../eval.c:3895 -msgid "E692: Invalid operation for Lists" +msgid "E692: Invalid operation for List" msgstr "E692: Virheellinen toiminto listalle" -#: ../eval.c:3915 msgid "E735: Can only compare Dictionary with Dictionary" msgstr "E735: Sanakirjaa voi verrata vain sanakirjaan" -#: ../eval.c:3917 msgid "E736: Invalid operation for Dictionary" msgstr "E736: Virheellinen toiminto sanakirjalle" -#: ../eval.c:3932 -msgid "E693: Can only compare Funcref with Funcref" -msgstr "E693: Funcrefiไ voi verrata vain funcrefiin" - -#: ../eval.c:3934 msgid "E694: Invalid operation for Funcrefs" msgstr "E694: Virheellinen toiminto funcrefille" -#: ../eval.c:4277 msgid "E804: Cannot use '%' with Float" -msgstr "E804: Ei voi kไyttไไ '%':a Floatin kanssa" +msgstr "E804: Ei voi kรคyttรครค '%':a Floatin kanssa" -#: ../eval.c:4478 msgid "E110: Missing ')'" msgstr "E110: ) puuttuu" -#: ../eval.c:4609 msgid "E695: Cannot index a Funcref" -msgstr "E695: Funcrefiไ ei voi indeksoida" +msgstr "E695: Funcrefiรค ei voi indeksoida" + +msgid "E909: Cannot index a special variable" +msgstr "E909: erikoismuuttujaa ei voi indeksoida" -#: ../eval.c:4839 #, c-format msgid "E112: Option name missing: %s" msgstr "E112: Asetuksen nimi puuttuu: %s" -#: ../eval.c:4855 #, c-format msgid "E113: Unknown option: %s" msgstr "E113: Tuntematon asetus: %s" -#: ../eval.c:4904 #, c-format msgid "E114: Missing quote: %s" msgstr "E114: Puuttuva lainausmerkki: %s" -#: ../eval.c:5020 #, c-format msgid "E115: Missing quote: %s" msgstr "E115: Puuttuva lainausmerkki: %s" -#: ../eval.c:5084 #, c-format msgid "E696: Missing comma in List: %s" msgstr "E696: Listasta puuttuu pilkku: %s" -#: ../eval.c:5091 #, c-format msgid "E697: Missing end of List ']': %s" msgstr "E697: Listan lopusta puuttuu ]: %s" -#: ../eval.c:6475 +msgid "Not enough memory to set references, garbage collection aborted!" +msgstr "" +"Ei tarpeeksi muistia viitteiden asettamista varten, roskiekeruu peruttiin." + #, c-format msgid "E720: Missing colon in Dictionary: %s" msgstr "E720: Sanakirjasta puuttuu kaksoispiste: %s" -#: ../eval.c:6499 #, c-format msgid "E721: Duplicate key in Dictionary: \"%s\"" msgstr "E721: Kaksi samaa avainta sanakirjassa: %s" -#: ../eval.c:6517 #, c-format msgid "E722: Missing comma in Dictionary: %s" msgstr "E722: Sanakirjasta puuttuu pilkku: %s" -#: ../eval.c:6524 #, c-format msgid "E723: Missing end of Dictionary '}': %s" msgstr "E723: Sanakirjan lopusta puuttuu }: %s" -#: ../eval.c:6555 -msgid "E724: variable nested too deep for displaying" -msgstr "E724: muuttuja on upotettu liian syvไlle nไytettไvไksi" +#, c-format +msgid "E125: Illegal argument: %s" +msgstr "E125: Virheellinen argumentti: %s" + +#, c-format +msgid "E853: Duplicate argument name: %s" +msgstr "E853: Kaksoiskappale argumentin nimestรค: %s" -#: ../eval.c:7188 #, c-format msgid "E740: Too many arguments for function %s" msgstr "E740: Liikaa argumentteja funktiolle %s" -#: ../eval.c:7190 #, c-format msgid "E116: Invalid arguments for function %s" -msgstr "E116: Vไไriไ argumentteja funktiolle %s" +msgstr "E116: Vรครคriรค argumentteja funktiolle %s" -#: ../eval.c:7377 #, c-format msgid "E117: Unknown function: %s" msgstr "E117: Tuntematon funktio: %s" -#: ../eval.c:7383 +#, c-format +msgid "E933: Function was deleted: %s" +msgstr "E933: Funktion nimi poistettu: %s" + #, c-format msgid "E119: Not enough arguments for function: %s" msgstr "E119: Liikaa argumentteja funktiolle %s" -#: ../eval.c:7387 #, c-format msgid "E120: Using <SID> not in a script context: %s" msgstr "E120: <SID> skriptin ulkopuolella: %s" -#: ../eval.c:7391 #, c-format msgid "E725: Calling dict function without Dictionary: %s" msgstr "E725: dict-funktio ilman sanakirjaa: %s" -#: ../eval.c:7453 -msgid "E808: Number or Float required" -msgstr "E808: Number tai Float vaaditaan" +#, fuzzy, c-format +#~ msgid "Error converting the call result: %s" +#~ msgstr "virhe Schemestรค Vimiin konversiossa" -#: ../eval.c:7503 -#, fuzzy msgid "add() argument" -msgstr "-c-argumentti" +msgstr "add()-argumentti" -#: ../eval.c:7907 msgid "E699: Too many arguments" msgstr "E699: Liikaa argumentteja" -#: ../eval.c:8073 msgid "E785: complete() can only be used in Insert mode" -msgstr "E785: complete() toimii vain sy๖tt๖tilassa" +msgstr "E785: complete() toimii vain syรถttรถtilassa" -#: ../eval.c:8156 msgid "&Ok" msgstr "&Ok" -#: ../eval.c:8676 -#, c-format -msgid "E737: Key already exists: %s" -msgstr "E737: Avain on jo olemassa: %s" - -#: ../eval.c:8692 #, fuzzy +#~ msgid "dictwatcheradd() argument" +#~ msgstr "add()-argumentti" + msgid "extend() argument" -msgstr "--cmd-argumentti" +msgstr "extend()-argumentti" -#: ../eval.c:8915 -#, fuzzy msgid "map() argument" -msgstr "-c-argumentti" +msgstr "map()-argumentti" -#: ../eval.c:8916 -#, fuzzy msgid "filter() argument" -msgstr "-c-argumentti" +msgstr "filter()-argumentti" -#: ../eval.c:9229 -#, c-format -msgid "+-%s%3ld lines: " -msgstr "+-%s%3ld riviไ: " +#, fuzzy, c-format +#~ msgid "+-%s%3ld lines: " +#~ msgstr "+-%s%3ld rivi: " -#: ../eval.c:9291 #, c-format msgid "E700: Unknown function: %s" msgstr "E700: Tuntematon funktio: %s" -#: ../eval.c:10729 +msgid "E922: expected a dict" +msgstr "E922: odotettiin dictiรค" + +# datarakenteita +msgid "E923: Second argument of function() must be a list or a dict" +msgstr "E923: toisen function()-argumentin pitรครค olla lista tai sanakirja" + +#, fuzzy +#~ msgid "E5000: Cannot find tab number." +#~ msgstr "E695: Funcrefiรค ei voi indeksoida" + +#~ msgid "E5001: Higher scope cannot be -1 if lower scope is >= 0." +#~ msgstr "" + +#, fuzzy +#~ msgid "E5002: Cannot find window number." +#~ msgstr "E671: Ikkunan otsikkoa ei lรถydy %s" + msgid "called inputrestore() more often than inputsave()" msgstr "inputrestore() suoritettu useammin kuin inputsave()" -#: ../eval.c:10771 -#, fuzzy msgid "insert() argument" -msgstr "-c-argumentti" +msgstr "insert()-argumentti" -#: ../eval.c:10841 msgid "E786: Range not allowed" -msgstr "E786: Aluetta ei voi kไyttไไ" +msgstr "E786: Aluetta ei voi kรคyttรครค" + +#~ msgid "Invalid stream on rpc job, use jobclose(id, 'rpc')" +#~ msgstr "" + +#~ msgid "Invalid job stream: Not an rpc job" +#~ msgstr "" + +#, c-format +#~ msgid "Invalid job stream \"%s\"" +#~ msgstr "" + +#~ msgid "Can't send data to the job: stdin is closed" +#~ msgstr "" + +#~ msgid "Can't send raw data to rpc channel" +#~ msgstr "" + +#, fuzzy +#~ msgid "E474: Failed to convert list to string" +#~ msgstr "ei voitu konvertoida tyypistรค %s vim-listaksi" + +#, fuzzy, c-format +#~ msgid "E474: Failed to parse %.*s" +#~ msgstr "E241: Kohteeseen %s lรคhettรคminen ei onnistunut" -#: ../eval.c:11140 msgid "E701: Invalid type for len()" msgstr "E701: Virheellinen tyyppi funktiolle len()" -#: ../eval.c:11980 +#, fuzzy, c-format +#~ msgid "msgpackdump() argument, index %i" +#~ msgstr "map()-argumentti" + +#, fuzzy +#~ msgid "E5070: Character number must not be less than zero" +#~ msgstr "luvun on oltava nollaa suurempi" + +#, fuzzy, c-format +#~ msgid "E5071: Character number must not be greater than INT_MAX (%i)" +#~ msgstr "luvun on oltava nollaa suurempi" + msgid "E726: Stride is zero" msgstr "E726: Stride on nolla" -#: ../eval.c:11982 msgid "E727: Start past end" -msgstr "E727: Alku on lopun jไlkeen" +msgstr "E727: Alku on lopun jรคlkeen" -#: ../eval.c:12024 ../eval.c:15297 msgid "<empty>" -msgstr "<tyhjไ>" +msgstr "<tyhjรค>" -#: ../eval.c:12282 -#, fuzzy msgid "remove() argument" -msgstr "--cmd-argumentti" +msgstr "remove()-argumentti" -#: ../eval.c:12466 msgid "E655: Too many symbolic links (cycle?)" -msgstr "E655: Liikaa symbolisia linkkejไ (mahdollinen sykli)" +msgstr "E655: Liikaa symbolisia linkkejรค (mahdollinen sykli)" -#: ../eval.c:12593 -#, fuzzy msgid "reverse() argument" -msgstr "-c-argumentti" +msgstr "reverse()-argumentti" + +#, c-format +msgid "E927: Invalid action: '%s'" +msgstr "E927: Viallinen toiminto: %s" -#: ../eval.c:13721 -#, fuzzy msgid "sort() argument" -msgstr "-c-argumentti" +msgstr "sort()-argumentti" -#: ../eval.c:13721 -#, fuzzy msgid "uniq() argument" -msgstr "-c-argumentti" +msgstr "uniq()-argumentti" -#: ../eval.c:13776 msgid "E702: Sort compare function failed" msgstr "E702: Lajittelun vertausfunktio ei onnistunut" -#: ../eval.c:13806 -#, fuzzy msgid "E882: Uniq compare function failed" -msgstr "E702: Lajittelun vertausfunktio ei onnistunut" +msgstr "E882: Uniqin vertausfunktio ei onnistunut" -#: ../eval.c:14085 msgid "(Invalid)" msgstr "(Virheellinen)" -#: ../eval.c:14590 -msgid "E677: Error writing temp file" -msgstr "E677: Vไliaikaistiedostoon kirjoittaminen ei onnistunut" +#, c-format +msgid "E935: invalid submatch number: %d" +msgstr "E935: Virheellinen alitรคsmรคyksen numero: %d" -#: ../eval.c:16159 -msgid "E805: Using a Float as a Number" -msgstr "E805: Float ei kไy Numberista" +#~ msgid "Can only call this function in an unmodified buffer" +#~ msgstr "" -#: ../eval.c:16162 -msgid "E703: Using a Funcref as a Number" -msgstr "E703: Funcref ei kไy Numberista" +msgid "E921: Invalid callback argument" +msgstr "E921: Virheellinen callback-argumentti" -#: ../eval.c:16170 -msgid "E745: Using a List as a Number" -msgstr "E745: Lista ei kไy Numberista" +#, fuzzy, c-format +#~ msgid "E80: Error while writing: %s" +#~ msgstr "E80: Kirjoitusvirhe" -#: ../eval.c:16173 -msgid "E728: Using a Dictionary as a Number" -msgstr "E728: Sanakirja ei kไy Numberista" +#. Using %s, p and not %c, *p to preserve multibyte characters +#, fuzzy, c-format +#~ msgid "E5060: Unknown flag: %s" +#~ msgstr "E235: Tuntematon fontti: %s" -#: ../eval.c:16259 -msgid "E729: using Funcref as a String" -msgstr "E729: Funcref ei kไy merkkijonosta" +#, fuzzy +#~ msgid "E482: Can't open file with an empty name" +#~ msgstr "E212: Tiedoston avaus kirjoittamista varten ei onnistu" -#: ../eval.c:16262 -msgid "E730: using List as a String" -msgstr "E730: Lista ei kไy merkkijonosta" +#, fuzzy, c-format +#~ msgid "E482: Can't open file %s for writing: %s" +#~ msgstr "E212: Tiedoston avaus kirjoittamista varten ei onnistu" -#: ../eval.c:16265 -msgid "E731: using Dictionary as a String" -msgstr "E731: Sanakirja ei kไy merkkijonosta" +#, fuzzy, c-format +#~ msgid "E80: Error when closing file %s: %s" +#~ msgstr "E209: Virhe suljettaessa tiedostoa %s" -#: ../eval.c:16619 -#, c-format -msgid "E706: Variable type mismatch for: %s" -msgstr "E706: Muuttujatyyppi ei tไsmไไ: %s" +#, fuzzy, c-format +#~ msgid "E794: Cannot set variable in the sandbox: \"%.*s\"" +#~ msgstr "E794: Muuttujaa ei voi asettaa hiekkalaatikossa: %s" -#: ../eval.c:16705 -#, c-format -msgid "E795: Cannot delete variable %s" -msgstr "E795: Muuttujaa %s ei voi poistaa" +#, fuzzy, c-format +#~ msgid "E795: Cannot delete variable %.*s" +#~ msgstr "E795: Muuttujaa %s ei voi poistaa" -#: ../eval.c:16724 #, c-format msgid "E704: Funcref variable name must start with a capital: %s" -msgstr "E704: Funcrefin muuttujanimen pitไไ alkaa suuraakkosella: %s" +msgstr "E704: Funcrefin muuttujanimen pitรครค alkaa suuraakkosella: %s" -#: ../eval.c:16732 #, c-format msgid "E705: Variable name conflicts with existing function: %s" msgstr "E705: Muuttujanimi on sama kuin olemassaolevan funktion: %s" -#: ../eval.c:16763 -#, c-format -msgid "E741: Value is locked: %s" -msgstr "E741: Arvo on lukittu: %s" - -#: ../eval.c:16764 ../eval.c:16769 ../message.c:1839 -msgid "Unknown" -msgstr "Tuntematon" - -#: ../eval.c:16768 -#, c-format -msgid "E742: Cannot change value of %s" -msgstr "E742: Ei voi muuttaa muuttujan %s arvoa" - -#: ../eval.c:16838 msgid "E698: variable nested too deep for making a copy" -msgstr "E698: muuttuja on upotettu liian syvไlle kopioitavaksi" +msgstr "E698: muuttuja on upotettu liian syvรคlle kopioitavaksi" -#: ../eval.c:17249 #, c-format msgid "E123: Undefined function: %s" msgstr "E123: Tuntematon funktio: %s" -#: ../eval.c:17260 #, c-format msgid "E124: Missing '(': %s" msgstr "E124: ( puuttuu: %s" -#: ../eval.c:17293 -#, fuzzy msgid "E862: Cannot use g: here" -msgstr "E284: Ei voi asettaa IC-arvoja" +msgstr "E862: g: ei toimi tรครคllรค" -#: ../eval.c:17312 -#, c-format -msgid "E125: Illegal argument: %s" -msgstr "E125: Virheellinen argumentti: %s" - -#: ../eval.c:17323 #, fuzzy, c-format -msgid "E853: Duplicate argument name: %s" -msgstr "Kaksoiskappale kentไn nimestไ: %s" +#~ msgid "E932: Closure function should not be at top level: %s" +#~ msgstr "E932 Sulkeumafunktio ei voi olla uloimmalla tasolla: %s" -#: ../eval.c:17416 msgid "E126: Missing :endfunction" msgstr "E126: :endfunction puuttuu" -#: ../eval.c:17537 #, c-format msgid "E707: Function name conflicts with variable: %s" msgstr "E707: Funktion nimi on ristiriidassa muuttujan kanssa: %s" -#: ../eval.c:17549 #, c-format msgid "E127: Cannot redefine function %s: It is in use" -msgstr "E127: Funktiota %s ei voi mไไritellไ uudestaan, koska se on kไyt๖ssไ" +msgstr "E127: Funktiota %s ei voi mรครคritellรค uudestaan, koska se on kรคytรถssรค" -#: ../eval.c:17604 #, c-format msgid "E746: Function name does not match script file name: %s" msgstr "E746: Funktion nimi ei ole sama kuin skriptin tiedostonnimi: %s" -#: ../eval.c:17716 msgid "E129: Function name required" msgstr "E129: Funktion nimi puuttuu" -#: ../eval.c:17824 -#, fuzzy, c-format +#, c-format msgid "E128: Function name must start with a capital or \"s:\": %s" -msgstr "" -"E128: Funktion nimen pitไไ alkaa suuraakkosella tai sisไltไไ kaksoispisteen: " -"%s" +msgstr "E128: Funktion nimen pitรครค alkaa suuraakkosella tai merkeillรค โs:โ: %s" -#: ../eval.c:17833 -#, fuzzy, c-format +#, c-format msgid "E884: Function name cannot contain a colon: %s" -msgstr "" -"E128: Funktion nimen pitไไ alkaa suuraakkosella tai sisไltไไ kaksoispisteen: " -"%s" +msgstr "E884: Funktion nimessรค ei saa olla kaksoispistettรค: %s" -#: ../eval.c:18336 #, c-format msgid "E131: Cannot delete function %s: It is in use" msgstr "E131: Funktiota %s ei voi poistaa" -#: ../eval.c:18441 +#, fuzzy, c-format +#~ msgid "Cannot delete function %s: It is being used internally" +#~ msgstr "E131: Funktiota %s ei voi poistaa" + msgid "E132: Function call depth is higher than 'maxfuncdepth'" -msgstr "E132: Funktiokutsujen syvyys on enemmไn kuin maxfuncdepth" +msgstr "E132: Funktiokutsujen syvyys on enemmรคn kuin maxfuncdepth" -#: ../eval.c:18568 #, c-format msgid "calling %s" msgstr "kutsutaan funktiota %s" -#: ../eval.c:18651 #, c-format msgid "%s aborted" msgstr "%s keskeytettiin" -#: ../eval.c:18653 -#, c-format -msgid "%s returning #%<PRId64>" -msgstr "%s palaa kohdassa #%<PRId64>" +#, fuzzy, c-format +#~ msgid "%s returning #%<PRId64>" +#~ msgstr "%s palaa kohdassa #%ld" -#: ../eval.c:18670 #, c-format msgid "%s returning %s" msgstr "%s palaa kohdassa %s" -#: ../eval.c:18691 ../ex_cmds2.c:2695 #, c-format msgid "continuing in %s" msgstr "jatkaa kohdassa %s" -#: ../eval.c:18795 msgid "E133: :return not inside a function" -msgstr "E133: :return ei ole funktion sisไllไ" +msgstr "E133: :return ei ole funktion sisรคllรค" -#: ../eval.c:19159 -msgid "" -"\n" -"# global variables:\n" -msgstr "" -"\n" -"# globaalit muuttujat:\n" - -#: ../eval.c:19254 msgid "" "\n" "\tLast set from " @@ -1045,154 +1091,396 @@ msgstr "" "\n" "\tViimeksi asetettu kohteesta " -#: ../eval.c:19272 msgid "No old files" msgstr "Ei vanhoja tiedostoja" -# puhutaan merkin ulkoasusta snprintf(..., c, c, c, c) -#: ../ex_cmds.c:122 #, c-format -msgid "<%s>%s%s %d, Hex %02x, Octal %03o" -msgstr "<%s>%s%s %d, heksana %02x, oktaalina %03o" +#~ msgid "E474: Expected comma before list item: %s" +#~ msgstr "" -#: ../ex_cmds.c:145 #, c-format -msgid "> %d, Hex %04x, Octal %o" -msgstr "> %d, heksana %04x, oktaalina %o" +#~ msgid "E474: Expected colon before dictionary value: %s" +#~ msgstr "" + +#, fuzzy, c-format +#~ msgid "E474: Expected string key: %s" +#~ msgstr "E415: odotuksenvastainen =-merkki: %s" + +#, fuzzy, c-format +#~ msgid "E474: Expected comma before dictionary key: %s" +#~ msgstr "E722: Sanakirjasta puuttuu pilkku: %s" + +#, fuzzy, c-format +#~ msgid "E474: Unfinished escape sequence: %.*s" +#~ msgstr "E540: Sulkematon lausekesarja" -#: ../ex_cmds.c:146 #, c-format -msgid "> %d, Hex %08x, Octal %o" -msgstr "> %d, hekdana %08x, oktaalina %o" +#~ msgid "E474: Unfinished unicode escape sequence: %.*s" +#~ msgstr "" -#: ../ex_cmds.c:684 -msgid "E134: Move lines into themselves" -msgstr "E134: Rivien siirto itsejensไ pไไlle" +#, c-format +#~ msgid "E474: Expected four hex digits after \\u: %.*s" +#~ msgstr "" -#: ../ex_cmds.c:747 -msgid "1 line moved" -msgstr "1 rivi siirretty" +#, fuzzy, c-format +#~ msgid "E474: Unknown escape sequence: %.*s" +#~ msgstr "E409: Tuntematon ryhmรคn nimi: %s" -#: ../ex_cmds.c:749 #, c-format -msgid "%<PRId64> lines moved" -msgstr "%<PRId64> riviไ siirretty" +#~ msgid "E474: ASCII control characters cannot be present inside string: %.*s" +#~ msgstr "" -#: ../ex_cmds.c:1175 #, c-format -msgid "%<PRId64> lines filtered" -msgstr "%<PRId64> riviไ suodatettu" +#~ msgid "E474: Only UTF-8 strings allowed: %.*s" +#~ msgstr "" -#: ../ex_cmds.c:1194 -msgid "E135: *Filter* Autocommands must not change current buffer" -msgstr "E135: *Filter*-autocommand ei voi vaihtaa puskuria" +#, c-format +#~ msgid "" +#~ "E474: Only UTF-8 code points up to U+10FFFF are allowed to appear unescaped: " +#~ "%.*s" +#~ msgstr "" -#: ../ex_cmds.c:1244 -msgid "[No write since last change]\n" -msgstr "[Viimeisintไ muutosta ei ole kirjoitettu]\n" +#, fuzzy, c-format +#~ msgid "E474: Expected string end: %.*s" +#~ msgstr "E415: odotuksenvastainen =-merkki: %s" + +#, fuzzy, c-format +#~ msgid "E474: Leading zeroes are not allowed: %.*s" +#~ msgstr "E786: Aluetta ei voi kรคyttรครค" + +#, fuzzy, c-format +#~ msgid "E474: Missing number after minus sign: %.*s" +#~ msgstr "E526: Lukuarvo puuttuu merkkijonon <%s> jรคlkeen" + +#, fuzzy, c-format +#~ msgid "E474: Missing number after decimal dot: %.*s" +#~ msgstr "E526: Lukuarvo puuttuu merkkijonon <%s> jรคlkeen" + +#, fuzzy, c-format +#~ msgid "E474: Missing exponent: %.*s" +#~ msgstr "E114: Puuttuva lainausmerkki: %s" -#: ../ex_cmds.c:1424 #, c-format -msgid "%sviminfo: %s in line: " -msgstr "%sviminfo: %s rivillไ: " +#~ msgid "" +#~ "E685: internal error: while converting number \"%.*s\" to float string2float " +#~ "consumed %zu bytes in place of %zu" +#~ msgstr "" -#: ../ex_cmds.c:1431 -msgid "E136: viminfo: Too many errors, skipping rest of file" -msgstr "E136: viminfo: liikaa virheitไ, ohitetaan lopputiedosto" +#, c-format +#~ msgid "" +#~ "E685: internal error: while converting number \"%.*s\" to integer vim_str2nr " +#~ "consumed %i bytes in place of %zu" +#~ msgstr "" + +#~ msgid "E474: Attempt to decode a blank string" +#~ msgstr "" -#: ../ex_cmds.c:1458 #, c-format -msgid "Reading viminfo file \"%s\"%s%s%s" -msgstr "Luetaan viminfo-tiedostoa \"%s\"%s%s%s" +#~ msgid "E474: No container to close: %.*s" +#~ msgstr "" -#: ../ex_cmds.c:1460 -msgid " info" -msgstr " info" +#, c-format +#~ msgid "E474: Closing list with curly bracket: %.*s" +#~ msgstr "" -#: ../ex_cmds.c:1461 -msgid " marks" -msgstr " merkit" +#, fuzzy, c-format +#~ msgid "E474: Closing dictionary with square bracket: %.*s" +#~ msgstr "E725: dict-funktio ilman sanakirjaa: %s" -#: ../ex_cmds.c:1462 -msgid " oldfiles" -msgstr " vanhaatiedostoa" +#, fuzzy, c-format +#~ msgid "E474: Trailing comma: %.*s" +#~ msgstr "E488: Ylimรครคrรคisiรค merkkejรค perรคssรค" -#: ../ex_cmds.c:1463 -msgid " FAILED" -msgstr " EPฤONNISTUI" +#, c-format +#~ msgid "E474: Expected value after colon: %.*s" +#~ msgstr "" + +#, fuzzy, c-format +#~ msgid "E474: Expected value: %.*s" +#~ msgstr "E415: odotuksenvastainen =-merkki: %s" -#. avoid a wait_return for this message, it's annoying -#: ../ex_cmds.c:1541 #, c-format -msgid "E137: Viminfo file is not writable: %s" -msgstr "E137: Viminfo-tiedostoon ei voitu kirjoittaa: %s" +#~ msgid "E474: Comma not inside container: %.*s" +#~ msgstr "" + +#, fuzzy, c-format +#~ msgid "E474: Duplicate comma: %.*s" +#~ msgstr "E721: Kaksi samaa avainta sanakirjassa: %s" + +#, fuzzy, c-format +#~ msgid "E474: Comma after colon: %.*s" +#~ msgstr "E254: Vรคriรค %s ei voi mรครคritellรค" + +#, fuzzy, c-format +#~ msgid "E474: Using comma in place of colon: %.*s" +#~ msgstr "E722: Sanakirjasta puuttuu pilkku: %s" -#: ../ex_cmds.c:1626 #, c-format -msgid "E138: Can't write viminfo file %s!" -msgstr "E138: Viminfo-tiedoston kirjoittaminen ei onnistu %s" +#~ msgid "E474: Leading comma: %.*s" +#~ msgstr "" -#: ../ex_cmds.c:1635 #, c-format -msgid "Writing viminfo file \"%s\"" -msgstr "Kirjoitetaan viminfo-tiedostoa %s" +#~ msgid "E474: Colon not inside container: %.*s" +#~ msgstr "" + +#, fuzzy, c-format +#~ msgid "E474: Using colon not in dictionary: %.*s" +#~ msgstr "E720: Sanakirjasta puuttuu kaksoispiste: %s" + +#, fuzzy, c-format +#~ msgid "E474: Unexpected colon: %.*s" +#~ msgstr "E415: odotuksenvastainen =-merkki: %s" -#. Write the info: -#: ../ex_cmds.c:1720 #, c-format -msgid "# This viminfo file was generated by Vim %s.\n" -msgstr "# Vimin %s generoima viminfo-tiedosto.\n" +#~ msgid "E474: Colon after comma: %.*s" +#~ msgstr "" -#: ../ex_cmds.c:1722 -msgid "" -"# You may edit it if you're careful!\n" -"\n" -msgstr "" -"# Muokkaa varovasti!\n" -"\n" +#, fuzzy, c-format +#~ msgid "E474: Duplicate colon: %.*s" +#~ msgstr "E721: Kaksi samaa avainta sanakirjassa: %s" + +#, fuzzy, c-format +#~ msgid "E474: Expected null: %.*s" +#~ msgstr "E415: odotuksenvastainen =-merkki: %s" + +#, fuzzy, c-format +#~ msgid "E474: Expected true: %.*s" +#~ msgstr "E270: odotuksenvastainen redo" + +#, fuzzy, c-format +#~ msgid "E474: Expected false: %.*s" +#~ msgstr "E415: odotuksenvastainen =-merkki: %s" -#: ../ex_cmds.c:1723 -msgid "# Value of 'encoding' when this file was written\n" -msgstr "# encoding-muuttujan arvo tiedostoa kirjoitettaessa\n" +#, fuzzy, c-format +#~ msgid "E474: Unidentified byte: %.*s" +#~ msgstr "E121: Mรครคrittelemรคtรถn muuttuja: %s" -#: ../ex_cmds.c:1800 -msgid "Illegal starting char" -msgstr "Virheellinen aloitusmerkki" +#, fuzzy, c-format +#~ msgid "E474: Trailing characters: %.*s" +#~ msgstr "E488: Ylimรครคrรคisiรค merkkejรค perรคssรค" + +#, fuzzy, c-format +#~ msgid "E474: Unexpected end of input: %.*s" +#~ msgstr "E415: odotuksenvastainen =-merkki: %s" + +#, c-format +#~ msgid "key %s" +#~ msgstr "" + +#, c-format +#~ msgid "key %s at index %i from special map" +#~ msgstr "" + +#, c-format +#~ msgid "index %i" +#~ msgstr "" + +#~ msgid "partial" +#~ msgstr "" + +#, fuzzy, c-format +#~ msgid "argument %i" +#~ msgstr "-c-argumentti" + +#, fuzzy +#~ msgid "partial self dictionary" +#~ msgstr "ei voida muuttaa kiinnitettyรค sanakirjaa" + +#~ msgid "itself" +#~ msgstr "" + +#. Only give this message once for a recursive call to avoid +#. flooding the user with errors. +#~ msgid "E724: unable to correctly dump variable with self-referencing container" +#~ msgstr "" + +#~ msgid "E474: Unable to represent NaN value in JSON" +#~ msgstr "" + +#~ msgid "E474: Unable to represent infinity in JSON" +#~ msgstr "" + +#, c-format +#~ msgid "" +#~ "E474: String \"%.*s\" contains byte that does not start any UTF-8 character" +#~ msgstr "" + +#, c-format +#~ msgid "" +#~ "E474: UTF-8 string contains code point which belongs to a surrogate pair: " +#~ "%.*s" +#~ msgstr "" + +#, fuzzy +#~ msgid "E474: Unable to convert EXT string to JSON" +#~ msgstr "E620: Tulostuskoodaukseen %s muunto ei onnistu" + +#, c-format +#~ msgid "E474: Error while dumping %s, %s: attempt to dump function reference" +#~ msgstr "" + +#, fuzzy +#~ msgid "E474: Invalid key in special dictionary" +#~ msgstr "E736: Virheellinen toiminto sanakirjalle" + +#, c-format +#~ msgid "E5004: Error while dumping %s, %s: attempt to dump function reference" +#~ msgstr "" + +#, c-format +#~ msgid "E5005: Unable to dump %s: container references itself in %s" +#~ msgstr "" + +#, fuzzy, c-format +#~ msgid "E684: list index out of range: %<PRId64>" +#~ msgstr "E684: Indeksi %ld luettelon rajojen ulkopuolella" + +#~ msgid "E6000: Argument is not a function or function name" +#~ msgstr "" + +#, c-format +msgid "E737: Key already exists: %s" +msgstr "E737: Avain on jo olemassa: %s" + +#, fuzzy +#~ msgid "tv_clear() argument" +#~ msgstr "filter()-argumentti" + +msgid "E743: variable nested too deep for (un)lock" +msgstr "E743: muuttujassa liian monta tasoa lukituksen kรคsittelyyn" + +#, fuzzy, c-format +#~ msgid "E741: Value is locked: %.*s" +#~ msgstr "E741: Arvo on lukittu: %s" + +#, fuzzy, c-format +#~ msgid "E742: Cannot change value of %.*s" +#~ msgstr "E742: Ei voi muuttaa muuttujan %s arvoa" + +msgid "Unknown" +msgstr "Tuntematon" + +#, fuzzy +#~ msgid "E805: Expected a Number or a String, Float found" +#~ msgstr "E807: Odotettiin Float-argumenttia printf():lle" + +#~ msgid "E703: Expected a Number or a String, Funcref found" +#~ msgstr "" + +#, fuzzy +#~ msgid "E745: Expected a Number or a String, List found" +#~ msgstr "E807: Odotettiin Float-argumenttia printf():lle" + +#~ msgid "E728: Expected a Number or a String, Dictionary found" +#~ msgstr "" + +#, fuzzy +#~ msgid "E5300: Expected a Number or a String" +#~ msgstr "E807: Odotettiin Float-argumenttia printf():lle" + +msgid "E745: Using a List as a Number" +msgstr "E745: Lista ei kรคy Numberista" + +msgid "E728: Using a Dictionary as a Number" +msgstr "E728: Sanakirja ei kรคy Numberista" + +msgid "E805: Using a Float as a Number" +msgstr "E805: Float ei kรคy Numberista" + +#, fuzzy +#~ msgid "E685: using an invalid value as a Number" +#~ msgstr "E908: huono arvo merkkijonolle" + +msgid "E730: using List as a String" +msgstr "E730: Lista ei kรคy merkkijonosta" + +msgid "E731: using Dictionary as a String" +msgstr "E731: Sanakirja ei kรคy merkkijonosta" + +msgid "E908: using an invalid value as a String" +msgstr "E908: huono arvo merkkijonolle" + +msgid "E891: Using a Funcref as a Float" +msgstr "E891: Funcref ei kรคy Floatista" + +msgid "E892: Using a String as a Float" +msgstr "E892: String ei kรคy Floatista" + +msgid "E893: Using a List as a Float" +msgstr "E893: Lista ei kรคy Floatista" + +msgid "E894: Using a Dictionary as a Float" +msgstr "E894: Sanakirja ei kรคy Floatista" + +msgid "E907: Using a special value as a Float" +msgstr "E907: Kรคytettiin erikoisarvoa Floattina" + +msgid "E808: Number or Float required" +msgstr "E808: Number tai Float vaaditaan" + +# puhutaan merkin ulkoasusta snprintf(..., c, c, c, c) +#, c-format +msgid "<%s>%s%s %d, Hex %02x, Octal %03o" +msgstr "<%s>%s%s %d, heksana %02x, oktaalina %03o" + +#, c-format +msgid "> %d, Hex %04x, Octal %o" +msgstr "> %d, heksana %04x, oktaalina %o" + +#, c-format +msgid "> %d, Hex %08x, Octal %o" +msgstr "> %d, hekdana %08x, oktaalina %o" + +msgid "E134: Move lines into themselves" +msgstr "E134: Rivien siirto itsejensรค pรครคlle" + +msgid "1 line moved" +msgstr "1 rivi siirretty" + +#, fuzzy, c-format +#~ msgid "%<PRId64> lines moved" +#~ msgstr "%ld riviรค siirretty" + +#, c-format +msgid "E482: Can't create file %s" +msgstr "E482: Tiedostoa %s ei voi luoda" + +#, fuzzy, c-format +#~ msgid "%<PRId64> lines filtered" +#~ msgstr "%ld riviรค suodatettu" + +msgid "E135: *Filter* Autocommands must not change current buffer" +msgstr "E135: *Filter*-autocommand ei voi vaihtaa puskuria" + +msgid "[No write since last change]\n" +msgstr "[Viimeisintรค muutosta ei ole kirjoitettu]\n" -#: ../ex_cmds.c:2162 msgid "Write partial file?" msgstr "Kirjoita osittainen tiedosto" -#: ../ex_cmds.c:2166 msgid "E140: Use ! to write partial buffer" -msgstr "E140: Kไytไ !-komentoa osittaisen puskurin kirjoittamiseen" +msgstr "E140: Kรคytรค !-komentoa osittaisen puskurin kirjoittamiseen" -#: ../ex_cmds.c:2281 #, c-format msgid "Overwrite existing file \"%s\"?" msgstr "Ylikirjoitetaanko olemassaoleva tiedosto %s?" -#: ../ex_cmds.c:2317 #, c-format msgid "Swap file \"%s\" exists, overwrite anyway?" msgstr "Swap-tiedosto %s on olemassa, ylikirjoitetaanko?" -#: ../ex_cmds.c:2326 #, c-format msgid "E768: Swap file exists: %s (:silent! overrides)" msgstr "E768: Swap-tiedosto on jo olemassa: %s (komento :silent! ohittaa)" -#: ../ex_cmds.c:2381 -#, c-format -msgid "E141: No file name for buffer %<PRId64>" -msgstr "E141: Ei tiedostonimeไ puskurille %<PRId64>" +#, fuzzy, c-format +#~ msgid "E141: No file name for buffer %<PRId64>" +#~ msgstr "E141: Ei tiedostonimeรค puskurille %ld" -#: ../ex_cmds.c:2412 msgid "E142: File not written: Writing is disabled by 'write' option" msgstr "" -"E142: Tiedostoa ei kirjoitettu; write-asetus poistaa kirjoituksen kไyt๖stไ" +"E142: Tiedostoa ei kirjoitettu; write-asetus poistaa kirjoituksen kรคytรถstรค" -#: ../ex_cmds.c:2434 #, c-format msgid "" "'readonly' option is set for \"%s\".\n" @@ -1201,7 +1489,6 @@ msgstr "" "readonly asetettu tiedostolle \"%s\".\n" "Kirjoitetaanko?" -#: ../ex_cmds.c:2439 #, c-format msgid "" "File permissions of \"%s\" are read-only.\n" @@ -1210,799 +1497,599 @@ msgid "" msgstr "" "Tiedosto %s on kirjoitussuojattu.\n" "Siihen saattaa voida silti kirjoittaa.\n" -"Yritetไไnk๖?" +"Yritetรครคnkรถ?" -#: ../ex_cmds.c:2451 #, c-format msgid "E505: \"%s\" is read-only (add ! to override)" -msgstr "E505: %s on kirjoitussuojattu (lisไไ komentoon ! ohittaaksesi)" +msgstr "E505: %s on kirjoitussuojattu (lisรครค komentoon ! ohittaaksesi)" -#: ../ex_cmds.c:3120 #, c-format msgid "E143: Autocommands unexpectedly deleted new buffer %s" msgstr "E143: Autocommand poisti uuden puskurin odotuksen vastaisesti %s" -#: ../ex_cmds.c:3313 msgid "E144: non-numeric argument to :z" msgstr "E144: :z:n argumentti ei ole numero" -#: ../ex_cmds.c:3404 -msgid "E145: Shell commands not allowed in rvim" -msgstr "E145: Kuoren komennot eivไt toimi rvimissไ" +#, fuzzy +#~ msgid "E145: Shell commands not allowed in restricted mode" +#~ msgstr "E145: Kuoren komennot eivรคt toimi rvimissรค" -#: ../ex_cmds.c:3498 msgid "E146: Regular expressions can't be delimited by letters" -msgstr "E146: Sไไnn๖llistไ ilmausta ei voi rajata kirjaimilla" +msgstr "E146: Sรครคnnรถllistรค ilmausta ei voi rajata kirjaimilla" -#: ../ex_cmds.c:3964 #, c-format msgid "replace with %s (y/n/a/q/l/^E/^Y)?" msgstr "korvaa kohteella %s (y/n/a/q/l/^E/^Y)?" -#: ../ex_cmds.c:4379 msgid "(Interrupted) " msgstr "(Keskeytetty)" -#: ../ex_cmds.c:4384 msgid "1 match" -msgstr "1 tไsmไys" +msgstr "1 tรคsmรคys" -#: ../ex_cmds.c:4384 msgid "1 substitution" msgstr "1 korvaus" -#: ../ex_cmds.c:4387 -#, c-format -msgid "%<PRId64> matches" -msgstr "%<PRId64> tไsmไystไ" +#, fuzzy, c-format +#~ msgid "%<PRId64> matches" +#~ msgstr "%ld tรคsmรคystรค" -#: ../ex_cmds.c:4388 -#, c-format -msgid "%<PRId64> substitutions" -msgstr "%<PRId64> korvausta" +#, fuzzy, c-format +#~ msgid "%<PRId64> substitutions" +#~ msgstr "%ld korvausta" -#: ../ex_cmds.c:4392 msgid " on 1 line" -msgstr " 1 rivillไ" +msgstr " 1 rivillรค" -#: ../ex_cmds.c:4395 -#, c-format -msgid " on %<PRId64> lines" -msgstr " %<PRId64> rivillไ" +#, fuzzy, c-format +#~ msgid " on %<PRId64> lines" +#~ msgstr " %ld rivillรค" -#: ../ex_cmds.c:4438 msgid "E147: Cannot do :global recursive" msgstr "E147: :globalia ei voi suorittaa rekursiivisesti" -#: ../ex_cmds.c:4467 msgid "E148: Regular expression missing from global" -msgstr "E148: Sไไnn๖llinen ilmaus puuttuu globaalista" +msgstr "E148: Sรครคnnรถllinen ilmaus puuttuu globaalista" -#: ../ex_cmds.c:4508 #, c-format msgid "Pattern found in every line: %s" -msgstr "Kuvio l๖ytyi joka riviltไ: %s" +msgstr "Kuvio lรถytyi joka riviltรค: %s" -#: ../ex_cmds.c:4510 -#, fuzzy, c-format +#, c-format msgid "Pattern not found: %s" -msgstr "Kuviota ei l๖ydy" - -#: ../ex_cmds.c:4587 -msgid "" -"\n" -"# Last Substitute String:\n" -"$" -msgstr "" -"\n" -"# Viimeisin korvausmerkkijono:\n" -"$" +msgstr "Kuviota ei lรถydy: %s" -#: ../ex_cmds.c:4679 msgid "E478: Don't panic!" -msgstr "E478: ฤlไ panikoi." +msgstr "E478: รlรค panikoi." -#: ../ex_cmds.c:4717 #, c-format msgid "E661: Sorry, no '%s' help for %s" -msgstr "E661: Sori, ei l๖ydy %s-ohjetta kohteelle %s" +msgstr "E661: ei lรถydy %s-ohjetta kohteelle %s" -#: ../ex_cmds.c:4719 #, c-format msgid "E149: Sorry, no help for %s" -msgstr "E149: Sori, ei l๖ydy ohjetta kohteelle %s" +msgstr "E149: ei lรถydy ohjetta kohteelle %s" -#: ../ex_cmds.c:4751 #, c-format msgid "Sorry, help file \"%s\" not found" -msgstr "Sori, ohjetiedostoa %s ei l๖ydy" +msgstr "ohjetiedostoa %s ei lรถydy" -#: ../ex_cmds.c:5323 -#, c-format -msgid "E150: Not a directory: %s" -msgstr "E150: Ei ole hakemisto: %s" - -#: ../ex_cmds.c:5446 #, c-format msgid "E152: Cannot open %s for writing" msgstr "E152: Ei voi avata tiedostoa %s kirjoittamista varten" -#: ../ex_cmds.c:5471 #, c-format msgid "E153: Unable to open %s for reading" msgstr "E153: Ei voi avata tiedostoa %s lukemista varten" -#: ../ex_cmds.c:5500 #, c-format msgid "E670: Mix of help file encodings within a language: %s" -msgstr "E670: Monia ohjetiedostokoodauksia kielessไ: %s" +msgstr "E670: Monia ohjetiedostokoodauksia kielessรค: %s" -#: ../ex_cmds.c:5565 #, c-format msgid "E154: Duplicate tag \"%s\" in file %s/%s" -msgstr "E154: Kaksoiskappale tไgistไ %s tiedostossa %s/%s" +msgstr "E154: Kaksoiskappale tรคgistรค %s tiedostossa %s/%s" + +#, c-format +msgid "E150: Not a directory: %s" +msgstr "E150: Ei ole hakemisto: %s" -#: ../ex_cmds.c:5687 #, c-format msgid "E160: Unknown sign command: %s" msgstr "E160: Tuntematon merkkikomento: %s" -#: ../ex_cmds.c:5704 msgid "E156: Missing sign name" msgstr "E156: Merkki puuttuu" -#: ../ex_cmds.c:5746 msgid "E612: Too many signs defined" -msgstr "E612: Liikaa merkkejไ mไไritelty" +msgstr "E612: Liikaa merkkejรค mรครคritelty" -#: ../ex_cmds.c:5813 #, c-format msgid "E239: Invalid sign text: %s" msgstr "E239: Virheellinen merkkiteksti: %s" -#: ../ex_cmds.c:5844 ../ex_cmds.c:6035 #, c-format msgid "E155: Unknown sign: %s" msgstr "E155: Tuntematon merkki: %s" -#: ../ex_cmds.c:5877 msgid "E159: Missing sign number" msgstr "E159: Merkin numero puuttuu" -#: ../ex_cmds.c:5971 #, c-format msgid "E158: Invalid buffer name: %s" msgstr "E158: Virheellinen puskurin nimi: %s" -#: ../ex_cmds.c:6008 +msgid "E934: Cannot jump to a buffer that does not have a name" +msgstr "E934: Ei voida hypรคtรค puskuriin jolla ei ole nimeรค" + +#, fuzzy, c-format +#~ msgid "E157: Invalid sign ID: %<PRId64>" +#~ msgstr "E157: Virheellinen merkin tunnus: %ld" + #, c-format -msgid "E157: Invalid sign ID: %<PRId64>" -msgstr "E157: Virheellinen merkin tunnus: %<PRId64>" +msgid "E885: Not possible to change sign %s" +msgstr "E885: Ei voida muuttaa merkkiรค %s" -#: ../ex_cmds.c:6066 msgid " (not supported)" msgstr " (ei tuettu)" -#: ../ex_cmds.c:6169 msgid "[Deleted]" msgstr "[Poistettu]" -#: ../ex_cmds2.c:139 msgid "Entering Debug mode. Type \"cont\" to continue." -msgstr "Siirrytไไn vianetsintไtilaan, kirjoita cont jatkaaksesi." +msgstr "Siirrytรครคn vianetsintรคtilaan, kirjoita cont jatkaaksesi." -#: ../ex_cmds2.c:143 ../ex_docmd.c:759 -#, c-format -msgid "line %<PRId64>: %s" -msgstr "rivi %<PRId64>: %s" +#, fuzzy, c-format +#~ msgid "line %<PRId64>: %s" +#~ msgstr "rivi %ld: %s" -#: ../ex_cmds2.c:145 #, c-format msgid "cmd: %s" msgstr "kmnt: %s" -#: ../ex_cmds2.c:322 +msgid "frame is zero" +msgstr "kehys on nolla" + #, c-format -msgid "Breakpoint in \"%s%s\" line %<PRId64>" -msgstr "Katkaisukohta %s%s rivillไ %<PRId64>" +msgid "frame at highest level: %d" +msgstr "kehys ylimmรคllรค tasolla: %d" + +#, fuzzy, c-format +#~ msgid "Breakpoint in \"%s%s\" line %<PRId64>" +#~ msgstr "Katkaisukohta %s%s rivillรค %ld" -#: ../ex_cmds2.c:581 #, c-format msgid "E161: Breakpoint not found: %s" msgstr "E161: Katkaisukohta puuttuu: %s" -#: ../ex_cmds2.c:611 msgid "No breakpoints defined" msgstr "Ei katkaisukohtia" -#: ../ex_cmds2.c:617 -#, c-format -msgid "%3d %s %s line %<PRId64>" -msgstr "%3d %s %s rivi %<PRId64>" +#, fuzzy, c-format +#~ msgid "%3d %s %s line %<PRId64>" +#~ msgstr "%3d %s %s rivi %ld" -#: ../ex_cmds2.c:942 msgid "E750: First use \":profile start {fname}\"" -msgstr "E750: Aloita kไskyllไ :profile start {fname}" +msgstr "E750: Aloita kรคskyllรค :profile start {fname}" -#: ../ex_cmds2.c:1269 #, c-format msgid "Save changes to \"%s\"?" msgstr "Tallennetaanko muutokset tiedostoon %s?" -#: ../ex_cmds2.c:1271 ../ex_docmd.c:8851 msgid "Untitled" -msgstr "Nimet๖n" +msgstr "Nimetรถn" -#: ../ex_cmds2.c:1421 #, c-format msgid "E162: No write since last change for buffer \"%s\"" -msgstr "E162: Muutoksia ei ole kirjoitettu puskurin %s viime muutoksen jไlkeen" +msgstr "E162: Muutoksia ei ole kirjoitettu puskurin %s viime muutoksen jรคlkeen" -#: ../ex_cmds2.c:1480 msgid "Warning: Entered other buffer unexpectedly (check autocommands)" msgstr "Varoitus: Puskuri vaihtui odottamatta (tarkista autocommands)" -#: ../ex_cmds2.c:1826 msgid "E163: There is only one file to edit" msgstr "E163: Vain yksi tiedosto muokattavana" -#: ../ex_cmds2.c:1828 msgid "E164: Cannot go before first file" -msgstr "E164: Ensimmไisen tiedoston ohi ei voi mennไ" +msgstr "E164: Ensimmรคisen tiedoston ohi ei voi mennรค" -#: ../ex_cmds2.c:1830 msgid "E165: Cannot go beyond last file" -msgstr "E165: Viimeisen tiedoston ohi ei voi mennไ" +msgstr "E165: Viimeisen tiedoston ohi ei voi mennรค" -#: ../ex_cmds2.c:2175 #, c-format msgid "E666: compiler not supported: %s" -msgstr "E666: kไไntไjไไ ei tueta: %s" +msgstr "E666: kรครคntรคjรครค ei tueta: %s" -#: ../ex_cmds2.c:2257 #, c-format msgid "Searching for \"%s\" in \"%s\"" -msgstr "Etsitไไn ilmausta %s kohteesta %s" +msgstr "Etsitรครคn ilmausta %s kohteesta %s" -#: ../ex_cmds2.c:2284 #, c-format msgid "Searching for \"%s\"" -msgstr "Etsitไไn ilmausta %s" +msgstr "Etsitรครคn ilmausta %s" -#: ../ex_cmds2.c:2307 #, c-format -msgid "not found in 'runtimepath': \"%s\"" -msgstr "ei l๖ydy runtimepathista: %s" +msgid "not found in '%s': \"%s\"" +msgstr "'%s' ei lรถydy kohteesta: %s" -#: ../ex_cmds2.c:2472 #, c-format msgid "Cannot source a directory: \"%s\"" msgstr "Hakemistoa ei voi ladata: %s" -#: ../ex_cmds2.c:2518 #, c-format msgid "could not source \"%s\"" msgstr "ei voitu ladata %s" -#: ../ex_cmds2.c:2520 -#, c-format -msgid "line %<PRId64>: could not source \"%s\"" -msgstr "rivi %<PRId64>: ei voitu ladata %s" +#, fuzzy, c-format +#~ msgid "line %<PRId64>: could not source \"%s\"" +#~ msgstr "rivi %ld: ei voitu ladata %s" -#: ../ex_cmds2.c:2535 #, c-format msgid "sourcing \"%s\"" msgstr "ladataan %s" -#: ../ex_cmds2.c:2537 -#, c-format -msgid "line %<PRId64>: sourcing \"%s\"" -msgstr "rivi %<PRId64>: ladataan %s" +#, fuzzy, c-format +#~ msgid "line %<PRId64>: sourcing \"%s\"" +#~ msgstr "rivi %ld: ladataan %s" -#: ../ex_cmds2.c:2693 #, c-format msgid "finished sourcing %s" msgstr "ladattu %s" -#: ../ex_cmds2.c:2765 msgid "modeline" msgstr "mode-rivi" -#: ../ex_cmds2.c:2767 msgid "--cmd argument" msgstr "--cmd-argumentti" -#: ../ex_cmds2.c:2769 msgid "-c argument" msgstr "-c-argumentti" -#: ../ex_cmds2.c:2771 msgid "environment variable" -msgstr "ympไrist๖muuttuja" +msgstr "ympรคristรถmuuttuja" -#: ../ex_cmds2.c:2773 msgid "error handler" -msgstr "virhekไsittelin" +msgstr "virhekรคsittelin" -#: ../ex_cmds2.c:3020 msgid "W15: Warning: Wrong line separator, ^M may be missing" -msgstr "W15: Varoitus: Vไไrไ rivierotin, ^M saattaa puuttua" +msgstr "W15: Varoitus: Vรครคrรค rivierotin, ^M saattaa puuttua" -#: ../ex_cmds2.c:3139 msgid "E167: :scriptencoding used outside of a sourced file" msgstr "E167: :scriptencoding ladatun tiedoston ulkopuolella" -#: ../ex_cmds2.c:3166 msgid "E168: :finish used outside of a sourced file" msgstr "E168: :finish ladatun tiedoston ulkopuolella" -#: ../ex_cmds2.c:3389 #, c-format msgid "Current %slanguage: \"%s\"" -msgstr "Kไyt๖ssไ oleva %skieli: %s" +msgstr "Kรคytรถssรค oleva %skieli: %s" -#: ../ex_cmds2.c:3404 #, c-format msgid "E197: Cannot set language to \"%s\"" -msgstr "E197: Kieleksi ei voitu asettaa kieltไ %s" +msgstr "E197: Kieleksi ei voitu asettaa kieltรค %s" #. don't redisplay the window #. don't wait for return -#: ../ex_docmd.c:387 msgid "Entering Ex mode. Type \"visual\" to go to Normal mode." -msgstr "Siirrytไไn Ex-tilaan, kirjoita visual palataksesi normaaliin tilaan." +msgstr "Siirrytรครคn Ex-tilaan, kirjoita visual palataksesi normaaliin tilaan." -#: ../ex_docmd.c:428 msgid "E501: At end-of-file" msgstr "E501: Tiedoston lopussa" -#: ../ex_docmd.c:513 msgid "E169: Command too recursive" msgstr "E169: Liian rekursiivinen komento" -#: ../ex_docmd.c:1006 +#, fuzzy +#~ msgid "line %" +#~ msgstr "rivi %ld" + #, c-format msgid "E605: Exception not caught: %s" msgstr "E605: Kiinniottamaton poikkeus: %s" -#: ../ex_docmd.c:1085 msgid "End of sourced file" msgstr "Ladatun tiedoston loppu" -#: ../ex_docmd.c:1086 msgid "End of function" msgstr "Funktion loppu" -#: ../ex_docmd.c:1628 msgid "E464: Ambiguous use of user-defined command" -msgstr "E464: Kไyttไjไn mไไrittelemไn komennon monimerkityksinen kไytt๖" +msgstr "E464: Kรคyttรคjรคn mรครคrittelemรคn komennon monimerkityksinen kรคyttรถ" -#: ../ex_docmd.c:1638 msgid "E492: Not an editor command" msgstr "E492: Ei ole editorikomento" -#: ../ex_docmd.c:1729 msgid "E493: Backwards range given" msgstr "E493: Takaperoinen arvoalue annettu" -#: ../ex_docmd.c:1733 msgid "Backwards range given, OK to swap" -msgstr "Takaperoinen arvoalue annettu, OK kไไntไไ" +msgstr "Takaperoinen arvoalue annettu, OK kรครคntรครค" #. append #. typed wrong -#: ../ex_docmd.c:1787 msgid "E494: Use w or w>>" -msgstr "E494: Kไytไ w:tไ tai w>>:aa" - -#: ../ex_docmd.c:3454 -msgid "E319: The command is not available in this version" -msgstr "E319: Komento ei ole kไytettไvissไ tไssไ versiossa" +msgstr "E494: Kรคytรค w:tรค tai w>>:aa" -#: ../ex_docmd.c:3752 -msgid "E172: Only one file name allowed" -msgstr "E172: Vain yksi tiedostonimi sallitaan" +#, fuzzy +#~ msgid "E319: The command is not available in this version" +#~ msgstr "E319: Komento ei ole kรคytettรคvissรค tรคssรค versiossa" -#: ../ex_docmd.c:4238 msgid "1 more file to edit. Quit anyway?" -msgstr "vielไ 1 tiedosto muokattavana, lopetaanko silti?" +msgstr "vielรค 1 tiedosto muokattavana, lopetaanko silti?" -#: ../ex_docmd.c:4242 #, c-format msgid "%d more files to edit. Quit anyway?" -msgstr "vielไ %d tiedostoa muokattavana, lopetetaanko silti?" +msgstr "vielรค %d tiedostoa muokattavana, lopetetaanko silti?" -#: ../ex_docmd.c:4248 msgid "E173: 1 more file to edit" -msgstr "E173: vielไ 1 tiedosto muokattavana" +msgstr "E173: vielรค 1 tiedosto muokattavana" -#: ../ex_docmd.c:4250 -#, c-format -msgid "E173: %<PRId64> more files to edit" -msgstr "E173: vielไ %<PRId64> tiedostoa muokattavana" +#, fuzzy, c-format +#~ msgid "E173: %<PRId64> more files to edit" +#~ msgstr "E173: vielรค %ld tiedostoa muokattavana" -#: ../ex_docmd.c:4320 msgid "E174: Command already exists: add ! to replace it" -msgstr "E174: Komento on jo olemassa, kไytไ !:ไ korvataksesi" +msgstr "E174: Komento on jo olemassa, kรคytรค !:รค korvataksesi" -#: ../ex_docmd.c:4432 msgid "" "\n" -" Name Args Range Complete Definition" +" Name Args Address Complete Definition" msgstr "" "\n" -" Nimi Arg Arvot Valmis Mไไritelmไ" +" Nimi Argumentit Osoite Valmis Mรครคritelmรค" -#: ../ex_docmd.c:4516 msgid "No user-defined commands found" -msgstr "Ei kไyttไjไn mไไrittelemiไ komentoja" +msgstr "Ei kรคyttรคjรคn mรครคrittelemiรค komentoja" -#: ../ex_docmd.c:4538 msgid "E175: No attribute specified" -msgstr "E175: Ei attribuutteja mไไriteltynไ" +msgstr "E175: Ei attribuutteja mรครคriteltynรค" -#: ../ex_docmd.c:4583 msgid "E176: Invalid number of arguments" -msgstr "E176: Vไไrไ mไไrไ attribuutteja" +msgstr "E176: Vรครคrรค mรครคrรค attribuutteja" -#: ../ex_docmd.c:4594 msgid "E177: Count cannot be specified twice" -msgstr "E177: Lukumไไrไไ ei voi mไไritellไ kahdesti" +msgstr "E177: Lukumรครคrรครค ei voi mรครคritellรค kahdesti" -#: ../ex_docmd.c:4603 msgid "E178: Invalid default value for count" -msgstr "E178: Lukumไไrไn oletusarvo on vไไrไ" +msgstr "E178: Lukumรครคrรคn oletusarvo on vรครคrรค" -#: ../ex_docmd.c:4625 msgid "E179: argument required for -complete" msgstr "E179: -complete vaatii argumentin" -#: ../ex_docmd.c:4635 +msgid "E179: argument required for -addr" +msgstr "E179: -addr vaatii argumentin" + #, c-format msgid "E181: Invalid attribute: %s" msgstr "E181: Virheellinen attribuutti: %s" -#: ../ex_docmd.c:4678 msgid "E182: Invalid command name" msgstr "E182: Virheellinen komennon nimi" -#: ../ex_docmd.c:4691 msgid "E183: User defined commands must start with an uppercase letter" -msgstr "E183: Kไyttไjไn mไไrittelemไn komennon pitไไ alkaa suuraakkosella" +msgstr "E183: Kรคyttรคjรคn mรครคrittelemรคn komennon pitรครค alkaa suuraakkosella" -#: ../ex_docmd.c:4696 -#, fuzzy msgid "E841: Reserved name, cannot be used for user defined command" -msgstr "E464: Kไyttไjไn mไไrittelemไn komennon monimerkityksinen kไytt๖" +msgstr "E841: Varattua nimeรค ei voi kรคyttรครค kรคyttรคjรคn mรครคrittelemรคnรค komentona" -#: ../ex_docmd.c:4751 #, c-format msgid "E184: No such user-defined command: %s" -msgstr "E184: Kไyttไjไn komentoa ei ole olemassa: %s" +msgstr "E184: Kรคyttรคjรคn komentoa ei ole olemassa: %s" + +#, c-format +msgid "E180: Invalid address type value: %s" +msgstr "E180: Virheellinen osoitetyyppiarvo: %s" -#: ../ex_docmd.c:5219 #, c-format msgid "E180: Invalid complete value: %s" -msgstr "E180: Virheellinen tไydennysarvo: %s" +msgstr "E180: Virheellinen tรคydennysarvo: %s" -#: ../ex_docmd.c:5225 msgid "E468: Completion argument only allowed for custom completion" -msgstr "E468: Tไydennysargumentti sopii vain itse mไไriteltyyn tไydennykseen" +msgstr "E468: Tรคydennysargumentti sopii vain itse mรครคriteltyyn tรคydennykseen" -#: ../ex_docmd.c:5231 msgid "E467: Custom completion requires a function argument" -msgstr "E467: Itse mไไritelty tไydennys vaatii funktioargumentin" +msgstr "E467: Itse mรครคritelty tรคydennys vaatii funktioargumentin" -#: ../ex_docmd.c:5257 -#, fuzzy, c-format +#, c-format msgid "E185: Cannot find color scheme '%s'" -msgstr "E185: Vไriteemaa %s ei l๖ydy" +msgstr "E185: Vรคriteemaa %s ei lรถydy" -#: ../ex_docmd.c:5263 msgid "Greetings, Vim user!" -msgstr "Tervehdys, Vimin kไyttไjไ." +msgstr "Tervehdys, Vimin kรคyttรคjรค." -#: ../ex_docmd.c:5431 msgid "E784: Cannot close last tab page" -msgstr "E784: Viimeistไ vไlilehteไ ei voi sulkea" +msgstr "E784: Viimeistรค vรคlilehteรค ei voi sulkea" -#: ../ex_docmd.c:5462 msgid "Already only one tab page" -msgstr "Vain yksi vไlilehti jไljellไ enไไ" +msgstr "Vain yksi vรคlilehti jรคljellรค enรครค" -#: ../ex_docmd.c:6004 #, c-format msgid "Tab page %d" msgstr "Tabisivu %d" -#: ../ex_docmd.c:6295 msgid "No swap file" msgstr "Ei swap-tiedostoa" -#: ../ex_docmd.c:6478 -msgid "E747: Cannot change directory, buffer is modified (add ! to override)" -msgstr "" -"E747: Hakemistoa ei voida muuttaa, puskuria on muokattu (lisไไ komentoon ! " -"ohittaaksesi" - -#: ../ex_docmd.c:6485 msgid "E186: No previous directory" -msgstr "E186: Ei edellistไ hakemistoa" +msgstr "E186: Ei edellistรค hakemistoa" -#: ../ex_docmd.c:6530 msgid "E187: Unknown" msgstr "E187: Tuntematon" -#: ../ex_docmd.c:6610 msgid "E465: :winsize requires two number arguments" msgstr "E465: :winsize vaatii kaksi numeroargumenttia" -#: ../ex_docmd.c:6655 -msgid "E188: Obtaining window position not implemented for this platform" -msgstr "E188: Ikkunan sijainnin selvitys ei toimi tไllไ alustalla" - -#: ../ex_docmd.c:6662 -msgid "E466: :winpos requires two number arguments" -msgstr "E466: :winpos vaatii kaksi lukuargumenttia" - -#: ../ex_docmd.c:7241 -#, c-format -msgid "E739: Cannot create directory: %s" -msgstr "E739: hakemistoa ei voi luoda: %s" - -#: ../ex_docmd.c:7268 #, c-format msgid "E189: \"%s\" exists (add ! to override)" -msgstr "E189: %s on jo olemassa (lisไไ komentoon ! ohittaaksesi)" +msgstr "E189: %s on jo olemassa (lisรครค komentoon ! ohittaaksesi)" -#: ../ex_docmd.c:7273 #, c-format msgid "E190: Cannot open \"%s\" for writing" msgstr "E190: Tiedostoa %s ei voitu avata kirjoittamista varten" #. set mark -#: ../ex_docmd.c:7294 msgid "E191: Argument must be a letter or forward/backward quote" -msgstr "E191: Argumentin eteen- tai taaksepไin lainaukseen pitไไ olla kirjain" +msgstr "E191: Argumentin eteen- tai taaksepรคin lainaukseen pitรครค olla kirjain" -#: ../ex_docmd.c:7333 msgid "E192: Recursive use of :normal too deep" -msgstr "E192: :normalin liian syvไ rekursio" +msgstr "E192: :normalin liian syvรค rekursio" -#: ../ex_docmd.c:7807 msgid "E194: No alternate file name to substitute for '#'" -msgstr "E194: Ei vaihtoehtoista tiedostonimeไ #:lle" +msgstr "E194: Ei vaihtoehtoista tiedostonimeรค #:lle" -#: ../ex_docmd.c:7841 msgid "E495: no autocommand file name to substitute for \"<afile>\"" msgstr "E495: ei autocommand-tiedostoa kohteelle <afile>" -#: ../ex_docmd.c:7850 msgid "E496: no autocommand buffer number to substitute for \"<abuf>\"" msgstr "E496: ei autocommand-puskurinumeroa kohteelle <abuf>" -#: ../ex_docmd.c:7861 msgid "E497: no autocommand match name to substitute for \"<amatch>\"" -msgstr "E497: ei autocommand-tไsmไysnimeไ kohteella <amatch>" +msgstr "E497: ei autocommand-tรคsmรคysnimeรค kohteella <amatch>" -#: ../ex_docmd.c:7870 msgid "E498: no :source file name to substitute for \"<sfile>\"" -msgstr "E498: ei :source-tiedostonimeไ kohteelle <sfile>" +msgstr "E498: ei :source-tiedostonimeรค kohteelle <sfile>" -#: ../ex_docmd.c:7876 -#, fuzzy msgid "E842: no line number to use for \"<slnum>\"" -msgstr "E498: ei :source-tiedostonimeไ kohteelle <sfile>" +msgstr "E842: ei rivinumeroa kohteelle <slnum>" -#: ../ex_docmd.c:7903 #, fuzzy, c-format -msgid "E499: Empty file name for '%' or '#', only works with \":p:h\"" -msgstr "E499: Tyhjไ tiedostonimi kohteissa % tai # toimii vain :p:h" +#~ msgid "E499: Empty file name for '%' or '#', only works with \":p:h\"" +#~ msgstr "E499: Tyhjรค tiedostonimi kohteissa % tai # toimii vain :p:h" -#: ../ex_docmd.c:7905 msgid "E500: Evaluates to an empty string" -msgstr "E500: Loppuarvo on tyhjไ merkkijono" - -#: ../ex_docmd.c:8838 -msgid "E195: Cannot open viminfo file for reading" -msgstr "E195: Viminfoa ei voi avata lukemista varten" +msgstr "E500: Loppuarvo on tyhjรค merkkijono" -#: ../ex_eval.c:464 msgid "E608: Cannot :throw exceptions with 'Vim' prefix" -msgstr "E608: Vim-alkuisia poikkeuksia ei voi heittไไ :throw-komennolla" +msgstr "E608: Vim-alkuisia poikkeuksia ei voi heittรครค :throw-komennolla" #. always scroll up, don't overwrite -#: ../ex_eval.c:496 #, c-format msgid "Exception thrown: %s" msgstr "Poikkeus heitetty: %s" -#: ../ex_eval.c:545 +#. always scroll up, don't overwrite #, c-format msgid "Exception finished: %s" msgstr "Poikkeus lopeteltu: %s" -#: ../ex_eval.c:546 #, c-format msgid "Exception discarded: %s" msgstr "Poikkeus poistettu: %s" -#: ../ex_eval.c:588 ../ex_eval.c:634 -#, c-format -msgid "%s, line %<PRId64>" -msgstr "%s, rivi %<PRId64>" +#, fuzzy, c-format +#~ msgid "%s, line %<PRId64>" +#~ msgstr "%s, rivi %ld" #. always scroll up, don't overwrite -#: ../ex_eval.c:608 #, c-format msgid "Exception caught: %s" msgstr "Poikkeus otettu kiinni: %s" -#: ../ex_eval.c:676 #, c-format msgid "%s made pending" msgstr "%s odotutettu" -#: ../ex_eval.c:679 #, c-format msgid "%s resumed" msgstr "%s palautettu" -#: ../ex_eval.c:683 #, c-format msgid "%s discarded" msgstr "%s poistettu" -#: ../ex_eval.c:708 msgid "Exception" msgstr "Poikkeus" -#: ../ex_eval.c:713 msgid "Error and interrupt" msgstr "Virhe ja keskeytys" -#: ../ex_eval.c:715 msgid "Error" msgstr "Virhe" #. if (pending & CSTP_INTERRUPT) -#: ../ex_eval.c:717 msgid "Interrupt" msgstr "Keskeytys" -#: ../ex_eval.c:795 msgid "E579: :if nesting too deep" msgstr "E579: liian monta kerrosta :if-komennossa" -#: ../ex_eval.c:830 msgid "E580: :endif without :if" msgstr "E580: :endif ilman komentoa :if" -#: ../ex_eval.c:873 msgid "E581: :else without :if" msgstr "E581: :else ilman komentoa :if" -#: ../ex_eval.c:876 msgid "E582: :elseif without :if" msgstr "E582: :elseif ilman komentoa :if" -#: ../ex_eval.c:880 msgid "E583: multiple :else" msgstr "E583: :else monta kertaa" -#: ../ex_eval.c:883 msgid "E584: :elseif after :else" -msgstr "E584: :elseif komennon :else jไlkeen" +msgstr "E584: :elseif komennon :else jรคlkeen" -#: ../ex_eval.c:941 msgid "E585: :while/:for nesting too deep" msgstr "E585: liian monta tasoa :while- tai :for-komennoissa" -#: ../ex_eval.c:1028 msgid "E586: :continue without :while or :for" msgstr "E586: :continue ilman komentoa :while tai :for" -#: ../ex_eval.c:1061 msgid "E587: :break without :while or :for" msgstr "E587: :break ilman komentoa :while tai :for" -#: ../ex_eval.c:1102 msgid "E732: Using :endfor with :while" msgstr "E732: :endfor ilman komentoa :while" -#: ../ex_eval.c:1104 msgid "E733: Using :endwhile with :for" msgstr "E733: :endwhile ilman komentoa :for" -#: ../ex_eval.c:1247 msgid "E601: :try nesting too deep" msgstr "E601: liian monta tasoa :try-komennossa" -#: ../ex_eval.c:1317 msgid "E603: :catch without :try" msgstr "E603: :catch ilman komentoa :try" #. Give up for a ":catch" after ":finally" and ignore it. #. * Just parse. -#: ../ex_eval.c:1332 msgid "E604: :catch after :finally" msgstr "E604: :catch ilman komentoa :finally" -#: ../ex_eval.c:1451 msgid "E606: :finally without :try" msgstr "E606: :finally ilman komentoa :try" #. Give up for a multiple ":finally" and ignore it. -#: ../ex_eval.c:1467 msgid "E607: multiple :finally" msgstr "E607: :finally monta kertaa" -#: ../ex_eval.c:1571 msgid "E602: :endtry without :try" msgstr "E602: :endtry ilman komentoa :try" -#: ../ex_eval.c:2026 msgid "E193: :endfunction not inside a function" msgstr "E193: :endfunction funktion ulkopuolella" -#: ../ex_getln.c:1643 msgid "E788: Not allowed to edit another buffer now" msgstr "E788: Puskuria ei voi muokata nyt" -#: ../ex_getln.c:1656 msgid "E811: Not allowed to change buffer information now" msgstr "E811: Puskuria ei voi vaihtaa nyt" -#: ../ex_getln.c:3178 msgid "tagname" -msgstr "tไginimi" +msgstr "tรคginimi" -#: ../ex_getln.c:3181 msgid " kind file\n" msgstr " -tiedostotyyppi\n" -#: ../ex_getln.c:4799 msgid "'history' option is zero" msgstr "history-asetus on nolla" -#: ../ex_getln.c:5046 -#, c-format -msgid "" -"\n" -"# %s History (newest to oldest):\n" -msgstr "" -"\n" -"# %s Historia (uusimmasta alkaen):\n" - -#: ../ex_getln.c:5047 -msgid "Command Line" -msgstr "Komentorivi" - -#: ../ex_getln.c:5048 -msgid "Search String" -msgstr "Hakujono" - -#: ../ex_getln.c:5049 -msgid "Expression" -msgstr "Ilmaus" - -#: ../ex_getln.c:5050 -msgid "Input Line" -msgstr "Sy๖terivi" - -#: ../ex_getln.c:5117 msgid "E198: cmd_pchar beyond the command length" msgstr "E198: cmd_pchar komennon pituuden ulkopuolella" -#: ../ex_getln.c:5279 msgid "E199: Active window or buffer deleted" msgstr "E199: Aktiivinen ikkuna tai puskuri poistettu" -#: ../file_search.c:203 msgid "E854: path too long for completion" -msgstr "" +msgstr "E854: polku on liian pitkรค tรคydennykseen" -#: ../file_search.c:446 #, c-format msgid "" "E343: Invalid path: '**[number]' must be at the end of the path or be " @@ -2011,376 +2098,296 @@ msgstr "" "E343: Virheellinen polku: '**[numero]' kuuluu polun loppuun tai ennen kohtaa " "%s." -#: ../file_search.c:1505 #, c-format msgid "E344: Can't find directory \"%s\" in cdpath" -msgstr "E344: Hakemistoa %s ei l๖ydy cdpathista" +msgstr "E344: Hakemistoa %s ei lรถydy cdpathista" -#: ../file_search.c:1508 #, c-format msgid "E345: Can't find file \"%s\" in path" -msgstr "E345: Tiedostoa %s ei l๖ydy polulta" +msgstr "E345: Tiedostoa %s ei lรถydy polulta" -#: ../file_search.c:1512 #, c-format msgid "E346: No more directory \"%s\" found in cdpath" -msgstr "E346: Hakemisto %s ei ole enไไ cdpathissa" +msgstr "E346: Hakemisto %s ei ole enรครค cdpathissa" -#: ../file_search.c:1515 #, c-format msgid "E347: No more file \"%s\" found in path" -msgstr "E347: Tiedosto %s ei ole enไไ polulla" +msgstr "E347: Tiedosto %s ei ole enรครค polulla" -#: ../fileio.c:137 msgid "E812: Autocommands changed buffer or buffer name" msgstr "E812: Autocommands muutti puskurin tai sen nimen" -#: ../fileio.c:368 msgid "Illegal file name" msgstr "Virheellinen tiedostonimi" -#: ../fileio.c:395 ../fileio.c:476 ../fileio.c:2543 ../fileio.c:2578 msgid "is a directory" msgstr "on hakemisto" -#: ../fileio.c:397 msgid "is not a file" msgstr "ei ole tiedosto" -#: ../fileio.c:508 ../fileio.c:3522 msgid "[New File]" msgstr "[Uusi tiedosto]" -#: ../fileio.c:511 msgid "[New DIRECTORY]" msgstr "[uusi HAKEMISTO]" -#: ../fileio.c:529 ../fileio.c:532 +#. libuv only returns -errno in Unix and in Windows open() does not +#. set EOVERFLOW msgid "[File too big]" msgstr "[Liian iso tiedosto]" -#: ../fileio.c:534 msgid "[Permission Denied]" msgstr "[Lupa kielletty]" -#: ../fileio.c:653 msgid "E200: *ReadPre autocommands made the file unreadable" msgstr "" -"E200: *ReadPre-autocommand-komennot tekivไt tiedostosta lukukelvottoman" +"E200: *ReadPre-autocommand-komennot tekivรคt tiedostosta lukukelvottoman" -#: ../fileio.c:655 msgid "E201: *ReadPre autocommands must not change current buffer" -msgstr "E201: *ReadPre-autocommand-komennot eivไt saa muuttaa puskuria" - -#: ../fileio.c:672 -msgid "Nvim: Reading from stdin...\n" -msgstr "Vim: Luetaan vakiosy๖tteestไ...\n" +msgstr "E201: *ReadPre-autocommand-komennot eivรคt saa muuttaa puskuria" #. Re-opening the original file failed! -#: ../fileio.c:909 msgid "E202: Conversion made file unreadable!" msgstr "E202: Muunnos teki tiedostosta lukukelvottoman." #. fifo or socket -#: ../fileio.c:1782 msgid "[fifo/socket]" msgstr "[fifo t. soketti]" #. fifo -#: ../fileio.c:1788 msgid "[fifo]" msgstr "[fifo]" #. or socket -#: ../fileio.c:1794 msgid "[socket]" msgstr "[soketti]" #. or character special -#: ../fileio.c:1801 msgid "[character special]" msgstr "[merkki erikoinen]" -# Carriage Return elikkไ rivinvaihtomerkin erไs muoto/osa (vrt. LF) -#: ../fileio.c:1815 +# Carriage Return elikkรค rivinvaihtomerkin erรคs muoto/osa (vrt. LF) msgid "[CR missing]" msgstr "[CR puuttuu]" -#: ../fileio.c:1819 msgid "[long lines split]" -msgstr "[pitkไt rivit hajotettu]" +msgstr "[pitkรคt rivit hajotettu]" -#: ../fileio.c:1823 ../fileio.c:3512 msgid "[NOT converted]" msgstr "[EI muunnettu]" -#: ../fileio.c:1826 ../fileio.c:3515 msgid "[converted]" msgstr "[muunnettu]" -#: ../fileio.c:1831 -#, c-format -msgid "[CONVERSION ERROR in line %<PRId64>]" -msgstr "[MUUNNOSVIRHE rivillไ %<PRId64>]" +#, fuzzy, c-format +#~ msgid "[CONVERSION ERROR in line %<PRId64>]" +#~ msgstr "[MUUNNOSVIRHE rivillรค %ld]" -#: ../fileio.c:1835 -#, c-format -msgid "[ILLEGAL BYTE in line %<PRId64>]" -msgstr "[VIRHEELLINEN OKTETTI rivillไ %<PRId64>]" +#, fuzzy, c-format +#~ msgid "[ILLEGAL BYTE in line %<PRId64>]" +#~ msgstr "[VIRHEELLINEN OKTETTI rivillรค %ld]" -#: ../fileio.c:1838 msgid "[READ ERRORS]" -msgstr "[LUKUVIRHEITฤ]" +msgstr "[LUKUVIRHEITร]" -#: ../fileio.c:2104 msgid "Can't find temp file for conversion" -msgstr "Ei voi l๖ytไไ vไliaikaistiedstoa muuntamiseksi" +msgstr "Ei voi lรถytรครค vรคliaikaistiedstoa muuntamiseksi" -#: ../fileio.c:2110 msgid "Conversion with 'charconvert' failed" -msgstr "Muunnos charconvert epไonnistui" +msgstr "Muunnos charconvert epรคonnistui" -#: ../fileio.c:2113 msgid "can't read output of 'charconvert'" msgstr "charconvertin tulostetta ei voida lukea" -#: ../fileio.c:2437 msgid "E676: No matching autocommands for acwrite buffer" msgstr "E676: Ei autocommand-komentoa acwrite-puskurille" -#: ../fileio.c:2466 msgid "E203: Autocommands deleted or unloaded buffer to be written" msgstr "" "E203: Autocommand-komennot poistivat tai vapauttivat puskurin, johon piti " "kirjoittaa" -#: ../fileio.c:2486 msgid "E204: Autocommand changed number of lines in unexpected way" -msgstr "E204: Autocommand-komento muutti rivien mไไrไ odottamatta" +msgstr "E204: Autocommand-komento muutti rivien mรครคrรค odottamatta" -#: ../fileio.c:2548 ../fileio.c:2565 msgid "is not a file or writable device" msgstr "ei ole tiedosto tai kirjoitettava laite" -#: ../fileio.c:2601 msgid "is read-only (add ! to override)" -msgstr "on kirjoitussuojattu (lisไไ komentoon ! ohittaaksesi)" +msgstr "on kirjoitussuojattu (lisรครค komentoon ! ohittaaksesi)" -#: ../fileio.c:2886 msgid "E506: Can't write to backup file (add ! to override)" msgstr "" -"E506: Ei voi kirjoittaa varmuuskopiotiedostoon (lisไไ komentoon ! " +"E506: Ei voi kirjoittaa varmuuskopiotiedostoon (lisรครค komentoon ! " "ohittaaksesi)" -#: ../fileio.c:2898 -msgid "E507: Close error for backup file (add ! to override)" -msgstr "" -"E507: Varmuuskopiotiedoston sulkeminen ei onnistu (lisไไ komentoon ! " -"ohittaaksesi)" +#, fuzzy, c-format +#~ msgid "E507: Close error for backup file (add ! to override): %s" +#~ msgstr "" +#~ "E507: Varmuuskopiotiedoston sulkeminen ei onnistu (lisรครค komentoon ! " +#~ "ohittaaksesi)" -#: ../fileio.c:2901 msgid "E508: Can't read file for backup (add ! to override)" msgstr "" -"E508: Varmuuskopiotiedostoa ei voi lukea (lisไไ komentoon ! ohittaaksesi)" +"E508: Varmuuskopiotiedostoa ei voi lukea (lisรครค komentoon ! ohittaaksesi)" -#: ../fileio.c:2923 msgid "E509: Cannot create backup file (add ! to override)" msgstr "" -"E509: Ei voi luoda varmuuskopiotiedostoa (lisไไ komentoon ! ohittaaksesi)" +"E509: Ei voi luoda varmuuskopiotiedostoa (lisรครค komentoon ! ohittaaksesi)" -#: ../fileio.c:3008 msgid "E510: Can't make backup file (add ! to override)" msgstr "" -"E510: Ei voi tehdไ varmuuskopiotiedostoa (lisไไ komentoon ! ohittaaksesi)" +"E510: Ei voi tehdรค varmuuskopiotiedostoa (lisรครค komentoon ! ohittaaksesi)" #. Can't write without a tempfile! -#: ../fileio.c:3121 msgid "E214: Can't find temp file for writing" -msgstr "E214: Ei voi l๖ytไไ vไliaikaistiedostoa kirjoitettavaksi" +msgstr "E214: Ei voi lรถytรครค vรคliaikaistiedostoa kirjoitettavaksi" -#: ../fileio.c:3134 msgid "E213: Cannot convert (add ! to write without conversion)" msgstr "" -"E213: Muunnos ei onnistu (lisไไ komentoon ! kirjoittaaksesi muuntamatta)" +"E213: Muunnos ei onnistu (lisรครค komentoon ! kirjoittaaksesi muuntamatta)" -#: ../fileio.c:3169 msgid "E166: Can't open linked file for writing" msgstr "E166: Linkitetyn tiedoston avaus kirjoittamista varten ei onnistu" -#: ../fileio.c:3173 -msgid "E212: Can't open file for writing" -msgstr "E212: Tiedoston avaus kirjoittamista varten ei onnistu" +#, fuzzy, c-format +#~ msgid "E212: Can't open file for writing: %s" +#~ msgstr "E212: Tiedoston avaus kirjoittamista varten ei onnistu" -#: ../fileio.c:3363 -msgid "E667: Fsync failed" -msgstr "E667: Fsync ei onnistunut" +#, fuzzy, c-format +#~ msgid "E667: Fsync failed: %s" +#~ msgstr "E667: Fsync ei onnistunut" -#: ../fileio.c:3398 -msgid "E512: Close failed" -msgstr "E512: Sulkeminen ei onnistunut" +#, fuzzy, c-format +#~ msgid "E512: Close failed: %s" +#~ msgstr "E512: Sulkeminen ei onnistunut" -#: ../fileio.c:3436 msgid "E513: write error, conversion failed (make 'fenc' empty to override)" -msgstr "E513: kirjoitusvirhe, muunnos epไonnistui (tyhjไไ fenc ohittaaksesi)" +msgstr "E513: kirjoitusvirhe, muunnos epรคonnistui (tyhjรครค fenc ohittaaksesi)" -#: ../fileio.c:3441 -#, c-format -msgid "" -"E513: write error, conversion failed in line %<PRId64> (make 'fenc' empty to " -"override)" -msgstr "" -"E513: kirjoitusvirhe, muunnos epไonnistui rivillไ %<PRId64>(tyhjไไ fenc " -"ohittaaksesi)" +#, fuzzy +#~ msgid "E513: write error, conversion failed in line %" +#~ msgstr "" +#~ "E513: kirjoitusvirhe, muunnos epรคonnistui rivillรค %ld(tyhjรครค fenc " +#~ "ohittaaksesi)" -#: ../fileio.c:3448 msgid "E514: write error (file system full?)" -msgstr "E514: kirjoitusvirhe (tiedostojไrjestelmไ tไysi)" +msgstr "E514: kirjoitusvirhe (tiedostojรคrjestelmรค tรคysi)" -#: ../fileio.c:3506 msgid " CONVERSION ERROR" msgstr " MUUNNOSVIRHE" -#: ../fileio.c:3509 -#, c-format -msgid " in line %<PRId64>;" -msgstr " rivillไ %<PRId64>" +#, fuzzy, c-format +#~ msgid " in line %<PRId64>;" +#~ msgstr " rivillรค %ld" -#: ../fileio.c:3519 msgid "[Device]" msgstr "[Laite]" -#: ../fileio.c:3522 msgid "[New]" msgstr "[Uusi]" -#: ../fileio.c:3535 msgid " [a]" msgstr " [a]" -#: ../fileio.c:3535 msgid " appended" -msgstr " lisไtty" +msgstr " lisรคtty" -#: ../fileio.c:3537 msgid " [w]" msgstr " [w]" -#: ../fileio.c:3537 msgid " written" msgstr " kirjoitettu" -#: ../fileio.c:3579 msgid "E205: Patchmode: can't save original file" -msgstr "E205: Patch-tilassa ei voi tallentaa alkuperไistiedostoa" +msgstr "E205: Patch-tilassa ei voi tallentaa alkuperรคistiedostoa" -#: ../fileio.c:3602 msgid "E206: patchmode: can't touch empty original file" -msgstr "E206: patch-tilassa ei voi muuttaa tyhjไไ alkuperไistiedostoa" +msgstr "E206: patch-tilassa ei voi muuttaa tyhjรครค alkuperรคistiedostoa" -#: ../fileio.c:3616 msgid "E207: Can't delete backup file" msgstr "E207: Ei voi poistaa varmuuskopiota" -#: ../fileio.c:3672 +#. Set highlight for error messages. msgid "" "\n" "WARNING: Original file may be lost or damaged\n" msgstr "" "\n" -"VAROITUS: Alkuperไistiedosto voi hไvitไ tai vahingoittua\n" +"VAROITUS: Alkuperรคistiedosto voi hรคvitรค tai vahingoittua\n" -#: ../fileio.c:3675 msgid "don't quit the editor until the file is successfully written!" -msgstr "ไlไ lopeta editoria kesken tallentamisen." +msgstr "รคlรค lopeta editoria kesken tallentamisen." -#: ../fileio.c:3795 -msgid "[dos]" -msgstr "[dos]" - -#: ../fileio.c:3795 msgid "[dos format]" msgstr "[dos-muoto]" -#: ../fileio.c:3801 -msgid "[mac]" -msgstr "[mac]" +msgid "[dos]" +msgstr "[dos]" -#: ../fileio.c:3801 msgid "[mac format]" msgstr "[mac-muoto]" -#: ../fileio.c:3807 -msgid "[unix]" -msgstr "[unix]" +msgid "[mac]" +msgstr "[mac]" -#: ../fileio.c:3807 msgid "[unix format]" msgstr "[unix-muoto]" -#: ../fileio.c:3831 +msgid "[unix]" +msgstr "[unix]" + msgid "1 line, " msgstr "1 rivi, " -#: ../fileio.c:3833 -#, c-format -msgid "%<PRId64> lines, " -msgstr "%<PRId64> riviไ, " +#, fuzzy, c-format +#~ msgid "%<PRId64> lines, " +#~ msgstr "%ld riviรค, " -#: ../fileio.c:3836 msgid "1 character" msgstr "1 merkki" -#: ../fileio.c:3838 -#, c-format -msgid "%<PRId64> characters" -msgstr "%<PRId64> merkkiไ" +#, fuzzy, c-format +#~ msgid "%<PRId64> characters" +#~ msgstr "%lld merkkiรค" + +msgid "[Incomplete last line]" +msgstr "[Vajaa viimeinen rivi]" # ei rivinvaihtoja -#: ../fileio.c:3849 msgid "[noeol]" msgstr "[eiriviv.]" -#: ../fileio.c:3849 -msgid "[Incomplete last line]" -msgstr "[Vajaa viimeinen rivi]" - -# Jos aukiolevaa tiedostoa s๖rkkii toisella ohjelmalla -#. don't overwrite messages here -#. must give this prompt -#. don't use emsg() here, don't want to flush the buffers -#: ../fileio.c:3865 +# Jos aukiolevaa tiedostoa sรถrkkii toisella ohjelmalla +#. Don't overwrite messages here. +#. Must give this prompt. +#. Don't use emsg() here, don't want to flush the buffers. msgid "WARNING: The file has been changed since reading it!!!" -msgstr "VAROITUS: tiedosto on muuttunut viime lukukerran jไlkeen!" +msgstr "VAROITUS: tiedosto on muuttunut viime lukukerran jรคlkeen!" -#: ../fileio.c:3867 msgid "Do you really want to write to it" msgstr "Kirjoitetaanko" -#: ../fileio.c:4648 #, c-format msgid "E208: Error writing to \"%s\"" msgstr "E208: Virhe kirjoitettaessa tiedostoon %s" -#: ../fileio.c:4655 #, c-format msgid "E209: Error closing \"%s\"" msgstr "E209: Virhe suljettaessa tiedostoa %s" -#: ../fileio.c:4657 #, c-format msgid "E210: Error reading \"%s\"" msgstr "E210: Virhe luettaessa tiedostoa %s" -#: ../fileio.c:4883 msgid "E246: FileChangedShell autocommand deleted buffer" msgstr "E246: FileChangedShell-autocommand poisti puskurin" -#: ../fileio.c:4894 #, c-format msgid "E211: File \"%s\" no longer available" -msgstr "E211: Tiedostoa %s ei ole enไไ" +msgstr "E211: Tiedostoa %s ei ole enรครค" -#: ../fileio.c:4906 #, c-format msgid "" "W12: Warning: File \"%s\" has changed and the buffer was changed in Vim as " @@ -2389,41 +2396,33 @@ msgstr "" "W12: Varoitus: Tiedostoa %s on muutettu ja Vimin puskurissa on muutoksia " "tiedostoon" -#: ../fileio.c:4907 msgid "See \":help W12\" for more info." -msgstr ":help W12 kertoo lisไtietoja." +msgstr ":help W12 kertoo lisรคtietoja." -#: ../fileio.c:4910 #, c-format msgid "W11: Warning: File \"%s\" has changed since editing started" -msgstr "W11: Varoitus: Tiedostoa %s on muutettu muokkauksen aloituksen jไlkeen" +msgstr "W11: Varoitus: Tiedostoa %s on muutettu muokkauksen aloituksen jรคlkeen" -#: ../fileio.c:4911 msgid "See \":help W11\" for more info." -msgstr ":help W11 kertoo lisไtietoja." +msgstr ":help W11 kertoo lisรคtietoja." -#: ../fileio.c:4914 #, c-format msgid "W16: Warning: Mode of file \"%s\" has changed since editing started" msgstr "" "W16: Varoitus: Tiedoston %s oikeuksia on muutettu muokkauksen aloituksen " -"jไlkeen" +"jรคlkeen" -#: ../fileio.c:4915 msgid "See \":help W16\" for more info." -msgstr ":help W16 kertoo lisไtietoja." +msgstr ":help W16 kertoo lisรคtietoja." -#: ../fileio.c:4927 #, c-format msgid "W13: Warning: File \"%s\" has been created after editing started" -msgstr "W13: Varoitus: Tiedosto %s on luotu muokkauksen aloituksen jไlkeen" +msgstr "W13: Varoitus: Tiedosto %s on luotu muokkauksen aloituksen jรคlkeen" -#: ../fileio.c:4947 msgid "Warning" msgstr "Varoitus" -# yllไ olevien varoitusten ratkaisut -#: ../fileio.c:4948 +# yllรค olevien varoitusten ratkaisut msgid "" "&OK\n" "&Load File" @@ -2431,48 +2430,46 @@ msgstr "" "&OK\n" "&Avaa tiedosto uudelleen" -#: ../fileio.c:5065 #, c-format msgid "E462: Could not prepare for reloading \"%s\"" msgstr "E462: Ei voitu valmistella uudelleen avausta %s" -#: ../fileio.c:5078 #, c-format msgid "E321: Could not reload \"%s\"" msgstr "E321: Ei voitu uudelleenavata %s" -#: ../fileio.c:5601 msgid "--Deleted--" msgstr "--Poistettu--" -#: ../fileio.c:5732 #, c-format msgid "auto-removing autocommand: %s <buffer=%d>" msgstr "poistetaan autocommand automaattisesti: %s <puskuri=%d>" #. the group doesn't exist -#: ../fileio.c:5772 #, c-format msgid "E367: No such group: \"%s\"" -msgstr "E367: Ryhmไไ ei ole: %s" +msgstr "E367: Ryhmรครค ei ole: %s" + +#, fuzzy +#~ msgid "E936: Cannot delete the current group" +#~ msgstr "E351: Taitosta ei voi poistaa tรคllรค foldmethodilla" + +msgid "W19: Deleting augroup that is still in use" +msgstr "W19: kรคytรถssรค oleva augroup poistetaan" -#: ../fileio.c:5897 #, c-format msgid "E215: Illegal character after *: %s" -msgstr "E215: Virheellinen merkki *:n jไlkeen: %s" +msgstr "E215: Virheellinen merkki *:n jรคlkeen: %s" -#: ../fileio.c:5905 #, c-format msgid "E216: No such event: %s" -msgstr "E216: Eventtiไ ei ole: %s" +msgstr "E216: Eventtiรค ei ole: %s" -#: ../fileio.c:5907 #, c-format msgid "E216: No such group or event: %s" -msgstr "E216: Ryhmไไ tai eventtiไ ei ole: %s" +msgstr "E216: Ryhmรครค tai eventtiรค ei ole: %s" #. Highlight title -#: ../fileio.c:6090 msgid "" "\n" "--- Auto-Commands ---" @@ -2480,762 +2477,611 @@ msgstr "" "\n" "--- Autocommandit ---" -#: ../fileio.c:6293 #, c-format msgid "E680: <buffer=%d>: invalid buffer number " msgstr "E680: <puskuri=%d>: virheellinen puskurinumero" -#: ../fileio.c:6370 msgid "E217: Can't execute autocommands for ALL events" msgstr "E217: Ei voi suorittaa autocommandsia kaikille eventeille" -#: ../fileio.c:6393 msgid "No matching autocommands" -msgstr "Ei tไsmไไviไ autocommandsia" +msgstr "Ei tรคsmรครคviรค autocommandsia" -#: ../fileio.c:6831 msgid "E218: autocommand nesting too deep" msgstr "E218: liian monta tasoa autocommandissa" -#: ../fileio.c:7143 #, c-format msgid "%s Auto commands for \"%s\"" msgstr "%s Autocommands kohteelle %s" -#: ../fileio.c:7149 #, c-format msgid "Executing %s" msgstr "Suoritetaan %s" -#: ../fileio.c:7211 #, c-format msgid "autocommand %s" msgstr "autocommand %s" -#: ../fileio.c:7795 msgid "E219: Missing {." msgstr "E219: { puuttuu." -#: ../fileio.c:7797 msgid "E220: Missing }." msgstr "E220: } puuttuu." -#: ../fold.c:93 msgid "E490: No fold found" msgstr "E490: taitos puuttuu" -#: ../fold.c:544 msgid "E350: Cannot create fold with current 'foldmethod'" -msgstr "E350: Taitoksia ei voi tehdไ tไllไ foldmethodilla" +msgstr "E350: Taitoksia ei voi tehdรค tรคllรค foldmethodilla" -#: ../fold.c:546 msgid "E351: Cannot delete fold with current 'foldmethod'" -msgstr "E351: Taitosta ei voi poistaa tไllไ foldmethodilla" +msgstr "E351: Taitosta ei voi poistaa tรคllรค foldmethodilla" -#: ../fold.c:1784 -#, c-format -msgid "+--%3ld lines folded " -msgstr "+--%3ld riviไ taitettu pois " +#, fuzzy, c-format +#~ msgid "+--%3ld lines folded " +#~ msgstr "+--%3ld rivi taitettu pois " #. buffer has already been read -#: ../getchar.c:273 msgid "E222: Add to read buffer" -msgstr "E222: Lisไไ lukupuskuriin" +msgstr "E222: Lisรครค lukupuskuriin" -#: ../getchar.c:2040 msgid "E223: recursive mapping" msgstr "E223: rekursiivinen kuvaus" -#: ../getchar.c:2849 #, c-format msgid "E224: global abbreviation already exists for %s" -msgstr "E224: globaali lyhenne merkinnไlle %s on jo olemassa" +msgstr "E224: globaali lyhenne merkinnรคlle %s on jo olemassa" -#: ../getchar.c:2852 #, c-format msgid "E225: global mapping already exists for %s" -msgstr "E225: globaali kuvaus merkinnไlle %s on jo olemassa" +msgstr "E225: globaali kuvaus merkinnรคlle %s on jo olemassa" -#: ../getchar.c:2952 #, c-format msgid "E226: abbreviation already exists for %s" msgstr "E226: lyhenne on jo olemassa %s" -#: ../getchar.c:2955 #, c-format msgid "E227: mapping already exists for %s" msgstr "E227: kuvaus on jo olemassa %s" -#: ../getchar.c:3008 msgid "No abbreviation found" -msgstr "Lyhennettไ ei l๖ydy" +msgstr "Lyhennettรค ei lรถydy" -#: ../getchar.c:3010 msgid "No mapping found" -msgstr "Kuvausta ei l๖ydy" +msgstr "Kuvausta ei lรถydy" -#: ../getchar.c:3974 msgid "E228: makemap: Illegal mode" msgstr "E228: makemap: Virheellinen tila" #. key value of 'cedit' option #. type of cmdline window or 0 #. result of cmdline window or 0 -#: ../globals.h:924 msgid "--No lines in buffer--" -msgstr "--Ei rivejไ puskurissa--" +msgstr "--Ei rivejรค puskurissa--" #. #. * The error messages that can be shared are included here. #. * Excluded are errors that are only used once and debugging messages. #. -#: ../globals.h:996 msgid "E470: Command aborted" msgstr "E470: Komento peruttu" -#: ../globals.h:997 +#, fuzzy +#~ msgid "E905: Cannot set this option after startup" +#~ msgstr "E529: Termiรค ei voi asettaa tyhjรคksi merkkijonoksi" + +#, fuzzy +#~ msgid "E903: Could not spawn API job" +#~ msgstr "E623: Cscope-prosessin luonti epรคonnistui" + msgid "E471: Argument required" msgstr "E471: Argumentti puuttuu" -#: ../globals.h:998 msgid "E10: \\ should be followed by /, ? or &" -msgstr "E10: \\:n jไlkeen pitไไ tulla /, ? tai &" +msgstr "E10: \\:n jรคlkeen pitรครค tulla /, ? tai &" -#: ../globals.h:1000 msgid "E11: Invalid in command-line window; <CR> executes, CTRL-C quits" msgstr "E11: Virheellinen komentorivi-ikkuna, <CR> suorittaa, Ctrl C lopettaa" -#: ../globals.h:1002 msgid "E12: Command not allowed from exrc/vimrc in current dir or tag search" msgstr "" -"E12: Komentoa ei tueta exrc:ssไ tai vimrc:ssไ tไssไ hakemistossa tai " -"tไgihaussa" +"E12: Komentoa ei tueta exrc:ssรค tai vimrc:ssรค tรคssรค hakemistossa tai " +"tรคgihaussa" -#: ../globals.h:1003 msgid "E171: Missing :endif" msgstr "E171: :endif puuttuu" -#: ../globals.h:1004 msgid "E600: Missing :endtry" msgstr "E600: :endtry puuttuu" -#: ../globals.h:1005 msgid "E170: Missing :endwhile" msgstr "E170: :endwhile puuttuu" -#: ../globals.h:1006 msgid "E170: Missing :endfor" msgstr "E170: :endfor puuttuu" -#: ../globals.h:1007 msgid "E588: :endwhile without :while" msgstr "E588: :endwhile ilman komentoa :while" -#: ../globals.h:1008 msgid "E588: :endfor without :for" msgstr "E588: :endfor ilman komentoa :for" -#: ../globals.h:1009 msgid "E13: File exists (add ! to override)" -msgstr "E13: Tiedosto on jo olemassa (lisไไ ! ohittaaksesi)" +msgstr "E13: Tiedosto on jo olemassa (lisรครค ! ohittaaksesi)" -#: ../globals.h:1010 msgid "E472: Command failed" -msgstr "E472: Komento epไonnistui" +msgstr "E472: Komento epรคonnistui" -#: ../globals.h:1011 msgid "E473: Internal error" -msgstr "E473: Sisไinen virhe" +msgstr "E473: Sisรคinen virhe" -#: ../globals.h:1012 msgid "Interrupted" msgstr "Keskeytetty" -#: ../globals.h:1013 msgid "E14: Invalid address" msgstr "E14: Virheellinen osoite" -#: ../globals.h:1014 msgid "E474: Invalid argument" msgstr "E474: Virheellinen argumentti" -#: ../globals.h:1015 #, c-format msgid "E475: Invalid argument: %s" msgstr "E475: Virheellinen argumentti: %s" -#: ../globals.h:1016 #, c-format msgid "E15: Invalid expression: %s" msgstr "E15: Virheellinen ilmaus: %s" -#: ../globals.h:1017 msgid "E16: Invalid range" msgstr "E16: Virheellinen arvoalue" -#: ../globals.h:1018 msgid "E476: Invalid command" msgstr "E476: Virheellinen komento" -#: ../globals.h:1019 #, c-format msgid "E17: \"%s\" is a directory" msgstr "E17: %s on hakemisto" -#: ../globals.h:1020 #, fuzzy -msgid "E900: Invalid job id" -msgstr "E49: Virheellinen vierityskoko" +#~ msgid "E900: Invalid job id" +#~ msgstr "E916: ei ole job" -#: ../globals.h:1021 -msgid "E901: Job table is full" -msgstr "" +#~ msgid "E901: Job table is full" +#~ msgstr "" + +#, fuzzy, c-format +#~ msgid "E903: Process failed to start: %s: \"%s\"" +#~ msgstr "E852: Lapsiprosesi ei voinut kรคynnistรครค kรคyttรถliittymรครค" + +#, fuzzy +#~ msgid "E904: Job is not connected to a pty" +#~ msgstr "E902: Ei voi yhdistรครค porttiin" -#: ../globals.h:1024 #, c-format msgid "E364: Library call failed for \"%s()\"" -msgstr "E364: Kirjastukutsu %s() epไonnistui" +msgstr "E364: Kirjastukutsu %s() epรคonnistui" + +#, fuzzy, c-format +#~ msgid "E739: Cannot create directory %s: %s" +#~ msgstr "E739: hakemistoa ei voi luoda: %s" -#: ../globals.h:1026 msgid "E19: Mark has invalid line number" -msgstr "E19: Merkillไ on virheellinen rivinumero" +msgstr "E19: Merkillรค on virheellinen rivinumero" -#: ../globals.h:1027 msgid "E20: Mark not set" -msgstr "E20: Merkkiไ ei asetettu" +msgstr "E20: Merkkiรค ei asetettu" -#: ../globals.h:1029 msgid "E21: Cannot make changes, 'modifiable' is off" -msgstr "E21: Ei voi tehdไ muutoksia, modifiable on pois pไไltไ" +msgstr "E21: Ei voi tehdรค muutoksia, modifiable on pois pรครคltรค" -#: ../globals.h:1030 msgid "E22: Scripts nested too deep" -msgstr "E22: Liian monta tasoa skripteissไ" +msgstr "E22: Liian monta tasoa skripteissรค" -#: ../globals.h:1031 msgid "E23: No alternate file" msgstr "E23: Eo vaihtoehtoista tiedostoa" -#: ../globals.h:1032 msgid "E24: No such abbreviation" -msgstr "E24: Lyhennettไ ei ole" +msgstr "E24: Lyhennettรค ei ole" -#: ../globals.h:1033 msgid "E477: No ! allowed" msgstr "E477: ! ei sallittu" -#: ../globals.h:1035 -msgid "E25: Nvim does not have a built-in GUI" -msgstr "E25: GUIta ei voi kไyttไไ, koska sitไ ei kไไnnetty mukaan" +#~ msgid "E25: Nvim does not have a built-in GUI" +#~ msgstr "" -#: ../globals.h:1036 #, c-format msgid "E28: No such highlight group name: %s" -msgstr "E28: Korostusryhmไไ ei ole nimellไ: %s" +msgstr "E28: Korostusryhmรครค ei ole nimellรค: %s" -#: ../globals.h:1037 msgid "E29: No inserted text yet" -msgstr "E29: Tekstiไ ei ole sy๖tetty vielไ" +msgstr "E29: Tekstiรค ei ole syรถtetty vielรค" -#: ../globals.h:1038 msgid "E30: No previous command line" -msgstr "E30: Ei edellistไ komentoriviไ" +msgstr "E30: Ei edellistรค komentoriviรค" -#: ../globals.h:1039 msgid "E31: No such mapping" msgstr "E31: Kuvausta ei ole" -#: ../globals.h:1040 msgid "E479: No match" -msgstr "E479: Ei tไsmไไ" +msgstr "E479: Ei tรคsmรครค" -#: ../globals.h:1041 #, c-format msgid "E480: No match: %s" -msgstr "E480: Ei tsไmไไ: %s" +msgstr "E480: Ei tsรคmรครค: %s" -#: ../globals.h:1042 msgid "E32: No file name" -msgstr "E32: Ei tiedostonimeไ" +msgstr "E32: Ei tiedostonimeรค" -#: ../globals.h:1044 msgid "E33: No previous substitute regular expression" -msgstr "E33: Ei edellistไ korvausta sไไnn๖lliselle ilmaukselle" +msgstr "E33: Ei edellistรค korvausta sรครคnnรถlliselle ilmaukselle" -#: ../globals.h:1045 msgid "E34: No previous command" -msgstr "E34: Ei edellistไ komentoa" +msgstr "E34: Ei edellistรค komentoa" -#: ../globals.h:1046 msgid "E35: No previous regular expression" -msgstr "E35: Ei edellistไ sไไnn๖llistไ ilmausta" +msgstr "E35: Ei edellistรค sรครคnnรถllistรค ilmausta" -#: ../globals.h:1047 msgid "E481: No range allowed" msgstr "E481: Arvoalue ei sallittu" -#: ../globals.h:1048 msgid "E36: Not enough room" -msgstr "E36: Tila ei riitไ" +msgstr "E36: Tila ei riitรค" -#: ../globals.h:1049 -#, c-format -msgid "E482: Can't create file %s" -msgstr "E482: Tiedostoa %s ei voi luoda" - -#: ../globals.h:1050 msgid "E483: Can't get temp file name" -msgstr "E483: vไliaikaistiedoston nimeไ ei saada selville" +msgstr "E483: vรคliaikaistiedoston nimeรค ei saada selville" -#: ../globals.h:1051 #, c-format msgid "E484: Can't open file %s" msgstr "E484: Ei voi avata tiedostoa %s" -#: ../globals.h:1052 #, c-format msgid "E485: Can't read file %s" msgstr "E485: Ei voi lukea tiedostoa %s" -#: ../globals.h:1054 msgid "E37: No write since last change (add ! to override)" msgstr "" -"E37: Viimeisen muutoksen jไlkeen ei ole kirjoitettu (lisไไ ! ohittaaksesi)" +"E37: Viimeisen muutoksen jรคlkeen ei ole kirjoitettu (lisรครค ! ohittaaksesi)" -#: ../globals.h:1055 -#, fuzzy msgid "E37: No write since last change" -msgstr "[Viimeisintไ muutosta ei ole kirjoitettu]\n" +msgstr "E37: Viimeisimmรคn muutoksen jรคlkeen ei ole kirjoitettu mitรครคn" -#: ../globals.h:1056 msgid "E38: Null argument" msgstr "E38: Null-argumentti" -#: ../globals.h:1057 msgid "E39: Number expected" -msgstr "E39: Pitไไ olla numero" +msgstr "E39: Pitรครค olla numero" -#: ../globals.h:1058 #, c-format msgid "E40: Can't open errorfile %s" msgstr "E40: virhetiedostoa %s ei voi avata" -#: ../globals.h:1059 msgid "E41: Out of memory!" msgstr "E41: Muisti loppui" -#: ../globals.h:1060 msgid "Pattern not found" -msgstr "Kuviota ei l๖ydy" +msgstr "Kuviota ei lรถydy" -#: ../globals.h:1061 #, c-format msgid "E486: Pattern not found: %s" -msgstr "E486: Kuviota ei l๖ydy: %s" +msgstr "E486: Kuviota ei lรถydy: %s" -#: ../globals.h:1062 msgid "E487: Argument must be positive" -msgstr "E487: Argumentin pitไไ olla positiivinen" +msgstr "E487: Argumentin pitรครค olla positiivinen" -#: ../globals.h:1064 msgid "E459: Cannot go back to previous directory" -msgstr "E459: Ei voi siirtyไ edelliseen hakemistoon" +msgstr "E459: Ei voi siirtyรค edelliseen hakemistoon" # ;-) -#: ../globals.h:1066 msgid "E42: No Errors" -msgstr "E42: Ei virheitไ" +msgstr "E42: Ei virheitรค" -#: ../globals.h:1067 msgid "E776: No location list" msgstr "E776: Ei sijaintilistaa" -#: ../globals.h:1068 msgid "E43: Damaged match string" -msgstr "E43: Viallinen tไsmไysmerkkijono" +msgstr "E43: Viallinen tรคsmรคysmerkkijono" -#: ../globals.h:1069 msgid "E44: Corrupted regexp program" msgstr "E44: Viallinen regexp-ohjelma" -#: ../globals.h:1071 msgid "E45: 'readonly' option is set (add ! to override)" -msgstr "E45: readonly asetettu (lisไไ ! ohittaaksesi)" - -#: ../globals.h:1073 -#, c-format -msgid "E46: Cannot change read-only variable \"%s\"" -msgstr "E46: Kirjoitussuojattua muuttujaa %s ei voi muuttaa" - -#: ../globals.h:1075 -#, c-format -msgid "E794: Cannot set variable in the sandbox: \"%s\"" -msgstr "E794: Muuttujaa ei voi asettaa hiekkalaatikossa: %s" +msgstr "E45: readonly asetettu (lisรครค ! ohittaaksesi)" -#: ../globals.h:1076 msgid "E47: Error while reading errorfile" msgstr "E47: Virhe virhetiedostoa luettaessa" -#: ../globals.h:1078 msgid "E48: Not allowed in sandbox" msgstr "E48: Ei sallittu hiekkalaatikossa" -#: ../globals.h:1080 msgid "E523: Not allowed here" -msgstr "E523: Ei sallittu tไไllไ" +msgstr "E523: Ei sallittu tรครคllรค" -#: ../globals.h:1082 msgid "E359: Screen mode setting not supported" -msgstr "E359: Nไytt๖tila-asetus ei tuettu" +msgstr "E359: Nรคyttรถtila-asetus ei tuettu" -#: ../globals.h:1083 msgid "E49: Invalid scroll size" msgstr "E49: Virheellinen vierityskoko" -#: ../globals.h:1084 msgid "E91: 'shell' option is empty" -msgstr "E91: shell-asetus on tyhjไ" +msgstr "E91: shell-asetus on tyhjรค" -#: ../globals.h:1085 msgid "E255: Couldn't read in sign data!" msgstr "E255: Merkkidatan luku ei onnistu" -#: ../globals.h:1086 msgid "E72: Close error on swap file" msgstr "E72: Swap-tiedoston sulkemisvirhe" -#: ../globals.h:1087 msgid "E73: tag stack empty" -msgstr "E73: tไgipino tyhjไ" +msgstr "E73: tรคgipino tyhjรค" -#: ../globals.h:1088 msgid "E74: Command too complex" msgstr "E74: Liian monimutkainen komento" -#: ../globals.h:1089 msgid "E75: Name too long" -msgstr "E75: Liian pitkไ nimi" +msgstr "E75: Liian pitkรค nimi" -#: ../globals.h:1090 msgid "E76: Too many [" msgstr "E76: Liian monta [:a" -#: ../globals.h:1091 msgid "E77: Too many file names" -msgstr "E77: Liikaa tiedostonimiไ" +msgstr "E77: Liikaa tiedostonimiรค" -#: ../globals.h:1092 msgid "E488: Trailing characters" -msgstr "E488: Ylimไไrไisiไ merkkejไ perไssไ" +msgstr "E488: Ylimรครคrรคisiรค merkkejรค perรคssรค" -#: ../globals.h:1093 msgid "E78: Unknown mark" msgstr "E78: Tuntematon merkki" -#: ../globals.h:1094 msgid "E79: Cannot expand wildcards" msgstr "E79: Jokerimerkkien avaus ei onnistu" -#: ../globals.h:1096 msgid "E591: 'winheight' cannot be smaller than 'winminheight'" msgstr "E591: winheight ei voi olla pienempi kuin winminheight" -#: ../globals.h:1098 msgid "E592: 'winwidth' cannot be smaller than 'winminwidth'" msgstr "E592: winwidth ei voi olla pienempi kuin winminwidth" -#: ../globals.h:1099 msgid "E80: Error while writing" msgstr "E80: Kirjoitusvirhe" -#: ../globals.h:1100 msgid "Zero count" msgstr "Nollalaskuri" -#: ../globals.h:1101 msgid "E81: Using <SID> not in a script context" msgstr "E81: <SID> skriptin ulkopuolella" -#: ../globals.h:1102 #, c-format msgid "E685: Internal error: %s" -msgstr "E685: Sisไinen virhe: %s" +msgstr "E685: Sisรคinen virhe: %s" -#: ../globals.h:1104 msgid "E363: pattern uses more memory than 'maxmempattern'" -msgstr "E363: kuvio kไyttไไ enemmไn muistia kuin maxmempattern on" +msgstr "E363: kuvio kรคyttรครค enemmรคn muistia kuin maxmempattern on" -#: ../globals.h:1105 msgid "E749: empty buffer" -msgstr "E749: tyhjไ puskuri" +msgstr "E749: tyhjรค puskuri" + +#, fuzzy, c-format +#~ msgid "E86: Buffer %<PRId64> does not exist" +#~ msgstr "E86: Puskuria %ld ei ole" -#: ../globals.h:1108 msgid "E682: Invalid search pattern or delimiter" msgstr "E682: Virheellinen hakulauseke tai erotin" -#: ../globals.h:1109 msgid "E139: File is loaded in another buffer" msgstr "E139: Tiedosto on ladattu toiseen puskuriin" -#: ../globals.h:1110 #, c-format msgid "E764: Option '%s' is not set" msgstr "E764: Asetus %s on asettamatta" -#: ../globals.h:1111 -#, fuzzy msgid "E850: Invalid register name" -msgstr "E354: Virheellinen rekisterin nimi: %s" +msgstr "E850: Virheellinen rekisterin nimi" + +#, c-format +msgid "E919: Directory not found in '%s': \"%s\"" +msgstr "E919: Hakemisto puuttuu kohteesta %s: %s" + +msgid "E519: Option not supported" +msgstr "E519: Asetusta ei tueta" + +#, fuzzy +#~ msgid "E856: Filename too long" +#~ msgstr "E75: Liian pitkรค nimi" + +msgid "E806: using Float as a String" +msgstr "E806: Float ei kรคy merkkijonosta" -#: ../globals.h:1114 msgid "search hit TOP, continuing at BOTTOM" -msgstr "haku pไไsi ALKUUN, jatketaan LOPUSTA" +msgstr "haku pรครคsi ALKUUN, jatketaan LOPUSTA" -#: ../globals.h:1115 msgid "search hit BOTTOM, continuing at TOP" -msgstr "haku pไไsi LOPPUUN, jatketaan ALUSTA" +msgstr "haku pรครคsi LOPPUUN, jatketaan ALUSTA" -#: ../hardcopy.c:240 msgid "E550: Missing colon" msgstr "E550: kaksoispiste puuttuu" -#: ../hardcopy.c:252 msgid "E551: Illegal component" msgstr "E551: Virheellinen komponentti" -#: ../hardcopy.c:259 msgid "E552: digit expected" -msgstr "E552: pitไisi olla numero" +msgstr "E552: pitรคisi olla numero" -#: ../hardcopy.c:473 #, c-format msgid "Page %d" msgstr "Sivu %d" -#: ../hardcopy.c:597 msgid "No text to be printed" -msgstr "Ei tekstiไ tulostettavaksi" +msgstr "Ei tekstiรค tulostettavaksi" -#: ../hardcopy.c:668 -#, c-format -msgid "Printing page %d (%d%%)" -msgstr "Tulostetaan sivua %d (%d %%)" +#, fuzzy, c-format +#~ msgid "Printing page %d (%zu%%)" +#~ msgstr "Tulostetaan sivua %d (%d %%)" -#: ../hardcopy.c:680 #, c-format msgid " Copy %d of %d" msgstr " Kopio %d/%d" -#: ../hardcopy.c:733 #, c-format msgid "Printed: %s" msgstr "Tulostettu: %s" -#: ../hardcopy.c:740 msgid "Printing aborted" msgstr "Tulostus peruttu" -#: ../hardcopy.c:1365 msgid "E455: Error writing to PostScript output file" -msgstr "E455: Virhe kirjoitettaessa PostScriptiไ tiedostoon" +msgstr "E455: Virhe kirjoitettaessa PostScriptiรค tiedostoon" -#: ../hardcopy.c:1747 #, c-format msgid "E624: Can't open file \"%s\"" msgstr "E624: Ei voi avata tiedostoa %s" -#: ../hardcopy.c:1756 ../hardcopy.c:2470 #, c-format msgid "E457: Can't read PostScript resource file \"%s\"" msgstr "E457: Ei voi lukea PostScript-resurssitiedostoa %s" -#: ../hardcopy.c:1772 #, c-format msgid "E618: file \"%s\" is not a PostScript resource file" msgstr "E618: tiedosto %s ei ole PostScript-resurssitiedosto" -#: ../hardcopy.c:1788 ../hardcopy.c:1805 ../hardcopy.c:1844 #, c-format msgid "E619: file \"%s\" is not a supported PostScript resource file" msgstr "E619: tiedosto %s ei ole tuettu PostScript-resurssitiedosto" -#: ../hardcopy.c:1856 #, c-format msgid "E621: \"%s\" resource file has wrong version" -msgstr "E621: resurssitiedoston %s versio on vไไrไ" +msgstr "E621: resurssitiedoston %s versio on vรครคrรค" -#: ../hardcopy.c:2225 msgid "E673: Incompatible multi-byte encoding and character set." -msgstr "E673: Tukematon monitvauinen merkist๖koodaus ja merkist๖." +msgstr "E673: Tukematon monitvauinen merkistรถkoodaus ja merkistรถ." -#: ../hardcopy.c:2238 msgid "E674: printmbcharset cannot be empty with multi-byte encoding." -msgstr "E674: printmbcharset ei voi olla tyhjไ monitavuiselle koodaukselle." +msgstr "E674: printmbcharset ei voi olla tyhjรค monitavuiselle koodaukselle." -#: ../hardcopy.c:2254 msgid "E675: No default font specified for multi-byte printing." msgstr "E675: Ei oletusfonttia monitavuiseen tulostukseen" -#: ../hardcopy.c:2426 msgid "E324: Can't open PostScript output file" msgstr "E324: PostScript-tulostetiedoston avaus ei onnistu" -#: ../hardcopy.c:2458 #, c-format msgid "E456: Can't open file \"%s\"" msgstr "E456: Tiedoston %s avaus ei onnistu" -#: ../hardcopy.c:2583 msgid "E456: Can't find PostScript resource file \"prolog.ps\"" -msgstr "E456: PostScript-resurssitiedostoa prolog.ps ei l๖ydy" +msgstr "E456: PostScript-resurssitiedostoa prolog.ps ei lรถydy" -#: ../hardcopy.c:2593 msgid "E456: Can't find PostScript resource file \"cidfont.ps\"" -msgstr "E456: PostScript-resurssitiedostoa cidfont.ps ei l๖ydy" +msgstr "E456: PostScript-resurssitiedostoa cidfont.ps ei lรถydy" -#: ../hardcopy.c:2622 ../hardcopy.c:2639 ../hardcopy.c:2665 #, c-format msgid "E456: Can't find PostScript resource file \"%s.ps\"" -msgstr "E456: Postscript-resurssitiedosta %s.ps ei l๖ydy" +msgstr "E456: Postscript-resurssitiedosta %s.ps ei lรถydy" -#: ../hardcopy.c:2654 #, c-format msgid "E620: Unable to convert to print encoding \"%s\"" msgstr "E620: Tulostuskoodaukseen %s muunto ei onnistu" -#: ../hardcopy.c:2877 msgid "Sending to printer..." -msgstr "Lไhetetไไn tulostimelle..." +msgstr "Lรคhetetรครคn tulostimelle..." -#: ../hardcopy.c:2881 msgid "E365: Failed to print PostScript file" -msgstr "E365: PostScript-tiedoston tulostus epไonnistui" +msgstr "E365: PostScript-tiedoston tulostus epรคonnistui" -#: ../hardcopy.c:2883 msgid "Print job sent." -msgstr "Tulostusty๖ lไhetetty." +msgstr "Tulostustyรถ lรคhetetty." -#: ../if_cscope.c:85 msgid "Add a new database" -msgstr "Lisไไ uusi tietokanta" +msgstr "Lisรครค uusi tietokanta" -#: ../if_cscope.c:87 msgid "Query for a pattern" msgstr "Hae kuviota" -#: ../if_cscope.c:89 msgid "Show this message" -msgstr "Nไytไ tไmไ viesti" +msgstr "Nรคytรค tรคmรค viesti" -#: ../if_cscope.c:91 msgid "Kill a connection" msgstr "Tapa yhteys" -#: ../if_cscope.c:93 msgid "Reinit all connections" msgstr "Alusta uudelleen yhteydet" -#: ../if_cscope.c:95 msgid "Show connections" -msgstr "Nไytไ yhteydet" +msgstr "Nรคytรค yhteydet" -#: ../if_cscope.c:101 #, c-format msgid "E560: Usage: cs[cope] %s" -msgstr "E560: Kไytt๖: cs[cope] %s" +msgstr "E560: Kรคyttรถ: cs[cope] %s" -#: ../if_cscope.c:225 msgid "This cscope command does not support splitting the window.\n" -msgstr "Tไmไ cscope-komento ei tue ikkunan jakamista.\n" +msgstr "Tรคmรค cscope-komento ei tue ikkunan jakamista.\n" -#: ../if_cscope.c:266 msgid "E562: Usage: cstag <ident>" -msgstr "E562: Kไytt๖: cstag <ident>" +msgstr "E562: Kรคyttรถ: cstag <ident>" -#: ../if_cscope.c:313 msgid "E257: cstag: tag not found" -msgstr "E257: cstag: tไgia ei l๖ydy" +msgstr "E257: cstag: tรคgia ei lรถydy" -#: ../if_cscope.c:461 #, c-format msgid "E563: stat(%s) error: %d" msgstr "E563: stat(%s)-virhe: %d" -#: ../if_cscope.c:551 #, c-format msgid "E564: %s is not a directory or a valid cscope database" -msgstr "E564: %s ei ole hakemisto eikไ cscope-tietokanta" +msgstr "E564: %s ei ole hakemisto eikรค cscope-tietokanta" -#: ../if_cscope.c:566 #, c-format msgid "Added cscope database %s" -msgstr "Lisไtty cscope-tietokanta %s" +msgstr "Lisรคtty cscope-tietokanta %s" -#: ../if_cscope.c:616 -#, c-format -msgid "E262: error reading cscope connection %<PRId64>" -msgstr "E262: Virhe luettaessa cscope-yhteyttไ %<PRId64>" +#, fuzzy, c-format +#~ msgid "E262: error reading cscope connection %<PRIu64>" +#~ msgstr "E262: Virhe luettaessa cscope-yhteyttรค %ld" -#: ../if_cscope.c:711 msgid "E561: unknown cscope search type" msgstr "E561: tuntematon cscope-hakutyyppi" -#: ../if_cscope.c:752 ../if_cscope.c:789 msgid "E566: Could not create cscope pipes" msgstr "E566: Ei voitu luoda cscope-putkia" -#: ../if_cscope.c:767 msgid "E622: Could not fork for cscope" msgstr "E622: Ei voitu haarauttaa cscopea" -#: ../if_cscope.c:849 -#, fuzzy msgid "cs_create_connection setpgid failed" -msgstr "cs_create_connection epไonnistui" +msgstr "cs_create_connection setpgid epรคonnistui" -#: ../if_cscope.c:853 ../if_cscope.c:889 msgid "cs_create_connection exec failed" -msgstr "cs_create_connection epไonnistui" +msgstr "cs_create_connection epรคonnistui" -#: ../if_cscope.c:863 ../if_cscope.c:902 msgid "cs_create_connection: fdopen for to_fp failed" -msgstr "cs_create_connection: fdopen to_fp epไonnistui" +msgstr "cs_create_connection: fdopen to_fp epรคonnistui" -#: ../if_cscope.c:865 ../if_cscope.c:906 msgid "cs_create_connection: fdopen for fr_fp failed" -msgstr "cs_create_connection: fdopen fr_fp epไonnistui" +msgstr "cs_create_connection: fdopen fr_fp epรคonnistui" -#: ../if_cscope.c:890 msgid "E623: Could not spawn cscope process" -msgstr "E623: Cscope-prosessin luonti epไonnistui" +msgstr "E623: Cscope-prosessin luonti epรคonnistui" -#: ../if_cscope.c:932 msgid "E567: no cscope connections" -msgstr "E567: ei cscope-yhteyksiไ" +msgstr "E567: ei cscope-yhteyksiรค" -#: ../if_cscope.c:1009 #, c-format msgid "E469: invalid cscopequickfix flag %c for %c" msgstr "E469: virheellinen cscopequickfix-asetus %c kohteelle %c" -#: ../if_cscope.c:1058 #, c-format msgid "E259: no matches found for cscope query %s of %s" -msgstr "E259: ei tไsmไyksiไ cscope-hakuun %s/%s" +msgstr "E259: ei tรคsmรคyksiรค cscope-hakuun %s/%s" -#: ../if_cscope.c:1142 msgid "cscope commands:\n" msgstr "cscope-komennot:\n" -#: ../if_cscope.c:1150 #, c-format msgid "%-5s: %s%*s (Usage: %s)" -msgstr "%-5s: %s%*s (Kไytt๖: %s)" +msgstr "%-5s: %s%*s (Kรคyttรถ: %s)" -#: ../if_cscope.c:1155 -#, fuzzy msgid "" "\n" +" a: Find assignments to this symbol\n" " c: Find functions calling this function\n" " d: Find functions called by this function\n" " e: Find this egrep pattern\n" @@ -3246,40 +3092,36 @@ msgid "" " t: Find this text string\n" msgstr "" "\n" -" c: Etsi tไtไ funktiota kutsuvat funktiot\n" -" d: Etsi tไmไn funktion kutsumat funktiot\n" -" e: Etsi tไmไ egrep-lauseke\n" -" f: Find tไmไ tiedosto\n" -" g: Etsi tไmไ mไไritys\n" -" i: Etsi tiedostoja jotka #inkluudaavat tไmไn\n" -" s: Etsi tไmไ C-symboli\n" +" a: Etsi sijotukset tรคhรคn symboliin\n" +" c: Etsi tรคtรค funktiota kutsuvat funktiot\n" +" d: Etsi tรคmรคn funktion kutsumat funktiot\n" +" e: Etsi tรคmรค egrep-lauseke\n" +" f: Etsi tรคmรค tiedosto\n" +" g: Etsi tรคmรค mรครคritys\n" +" i: Etsi tiedostoja jotka #inkluudaavat tรคmรคn\n" +" s: Etsi tรคmรค C-symboli\n" " t: Etsi sijoitukset muuttujaan \n" -#: ../if_cscope.c:1226 msgid "E568: duplicate cscope database not added" -msgstr "E568: kaksoiskappaletta cscope-tietokannasta ei lisไtty" +msgstr "E568: kaksoiskappaletta cscope-tietokannasta ei lisรคtty" -#: ../if_cscope.c:1335 #, c-format msgid "E261: cscope connection %s not found" msgstr "E261: cscope-yhteys %s puuttuu" -#: ../if_cscope.c:1364 #, c-format msgid "cscope connection %s closed" msgstr "cscope-yhteys %s on katkaistu" #. should not reach here -#: ../if_cscope.c:1486 msgid "E570: fatal error in cs_manage_matches" msgstr "E570: kriittinen virhe cs_manage_matches-funktiossa" -#: ../if_cscope.c:1693 #, c-format msgid "Cscope tag: %s" -msgstr "Cscope-tไgi: %s" +msgstr "Cscope-tรคgi: %s" -#: ../if_cscope.c:1711 +#. Column headers for match number, line number and filename. msgid "" "\n" " # line" @@ -3287,326 +3129,272 @@ msgstr "" "\n" " # rivi" -#: ../if_cscope.c:1713 msgid "filename / context / line\n" msgstr "tiedosto / konteksti / rivi\n" -#: ../if_cscope.c:1809 #, c-format msgid "E609: Cscope error: %s" msgstr "E609: Cscope-virhe: %s" -#: ../if_cscope.c:2053 msgid "All cscope databases reset" msgstr "Kaikki cscope-tietokannat nollattu" -#: ../if_cscope.c:2123 msgid "no cscope connections\n" -msgstr "ei cscope-yhteyksiไ\n" +msgstr "ei cscope-yhteyksiรค\n" -#: ../if_cscope.c:2126 msgid " # pid database name prepend path\n" -msgstr " # pid tietokanta lisไyspolku\n" +msgstr " # pid tietokanta lisรคyspolku\n" + +#. Error messages +msgid "Argument missing after" +msgstr "Argumentti puuttuu kohdasta" + +msgid "Garbage after option argument" +msgstr "Roskaa argumentin perรคssรค" -#: ../main.c:144 msgid "Unknown option argument" msgstr "Tuntematon asetusargumentti" -#: ../main.c:146 msgid "Too many edit arguments" msgstr "Liikaa muokkausargumentteja" -#: ../main.c:148 -msgid "Argument missing after" -msgstr "Argumentti puuttuu kohdasta" - -#: ../main.c:150 -msgid "Garbage after option argument" -msgstr "Roskaa argumentin perไssไ" - -#: ../main.c:152 msgid "Too many \"+command\", \"-c command\" or \"--cmd command\" arguments" msgstr "Liikaa +komentoja, -c-komentoja tai --cmd-komentoja" -#: ../main.c:154 -msgid "Invalid argument for" -msgstr "Vไไrไ argumentti valitsimelle" - -#: ../main.c:294 -#, c-format -msgid "%d files to edit\n" -msgstr "%d tiedostoa muokattavana\n" - -#: ../main.c:1342 msgid "Attempt to open script file again: \"" msgstr "Yritettiin avata skriptitiedostoa uudestaan:" -#: ../main.c:1350 msgid "Cannot open for reading: \"" msgstr "Ei voi avata luettavaksi: " -#: ../main.c:1393 msgid "Cannot open for script output: \"" msgstr "Ei voi avata skriptin tulostetta varten: " -#: ../main.c:1622 msgid "Vim: Warning: Output is not to a terminal\n" msgstr "Vim: Varoitus: Tuloste ei mene terminaalille\n" -#: ../main.c:1624 msgid "Vim: Warning: Input is not from a terminal\n" -msgstr "Vim: Varoitus: Sy๖te ei tule terminaalilta\n" +msgstr "Vim: Varoitus: Syรถte ei tule terminaalilta\n" #. just in case.. -#: ../main.c:1891 msgid "pre-vimrc command line" msgstr "esi-vimrc-komentorivi" -#: ../main.c:1964 #, c-format msgid "E282: Cannot read from \"%s\"" msgstr "E282: Ei voida lukea kohteesta %s" -#: ../main.c:2149 +#, fuzzy msgid "" "\n" -"More info with: \"vim -h\"\n" +"More info with \"" msgstr "" "\n" -"Lisไtietoja: \"vim -h\"\n" - -#: ../main.c:2178 -msgid "[file ..] edit specified file(s)" -msgstr "[tiedosto ..] muokkaa tiedostoja" - -#: ../main.c:2179 -msgid "- read text from stdin" -msgstr "- lue vakiosy๖tteestไ" +"Lisรคtietoja: \"vim -h\"\n" -#: ../main.c:2180 -msgid "-t tag edit file where tag is defined" -msgstr "-t tไgi muokkaa tiedostoa tไgistไ" +#. kill us with CTRL-C here, if you like +#, fuzzy +#~ msgid "Usage:\n" +#~ msgstr "" +#~ "\n" +#~ "\n" +#~ "kรคyttรถ:" -#: ../main.c:2181 -msgid "-q [errorfile] edit file with first error" -msgstr "-q [virhetiedosto] muokkaa tiedostoa ensimmไisestไ virheestไ" +#, fuzzy +#~ msgid " nvim [arguments] [file ...] Edit specified file(s)\n" +#~ msgstr "[tiedosto ..] muokkaa tiedostoja" -#: ../main.c:2187 -msgid "" -"\n" -"\n" -"usage:" -msgstr "" -"\n" -"\n" -"kไytt๖:" +#, fuzzy +#~ msgid " nvim [arguments] - Read text from stdin\n" +#~ msgstr "- lue vakiosyรถtteestรค" -#: ../main.c:2189 -msgid " vim [arguments] " -msgstr " vim [argumentit] " +#, fuzzy +#~ msgid " nvim [arguments] -t <tag> Edit file where tag is defined\n" +#~ msgstr "-t tรคgi muokkaa tiedostoa tรคgistรค" -#: ../main.c:2193 -msgid "" -"\n" -" or:" -msgstr "" -"\n" -" tai:" +#, fuzzy +#~ msgid " nvim [arguments] -q [errorfile] Edit file with first error\n" +#~ msgstr "-q [virhetiedosto] muokkaa tiedostoa ensimmรคisestรค virheestรค" -#: ../main.c:2196 +#, fuzzy msgid "" "\n" -"\n" "Arguments:\n" msgstr "" "\n" "\n" "Argumentit:\n" -#: ../main.c:2197 -msgid "--\t\t\tOnly file names after this" -msgstr "--\t\t\tvain tiedostonimiไ tไmไn jไlkeen" - -#: ../main.c:2199 -msgid "--literal\t\tDon't expand wildcards" -msgstr "--literal\t\tฤlไ kไsittele jokerimerkkejไ " - -#: ../main.c:2201 -msgid "-v\t\t\tVi mode (like \"vi\")" -msgstr "-v\t\t\tVi-tila (kuten villไ)" +#, fuzzy +#~ msgid " -- Only file names after this\n" +#~ msgstr "--\t\t\tvain tiedostonimiรค tรคmรคn jรคlkeen" -#: ../main.c:2202 -msgid "-e\t\t\tEx mode (like \"ex\")" -msgstr "-e\t\t\tEx-tila (kute exillไ)" +#, fuzzy +#~ msgid " --literal Don't expand wildcards\n" +#~ msgstr "--literal\t\tรlรค kรคsittele jokerimerkkejรค " -#: ../main.c:2203 -msgid "-E\t\t\tImproved Ex mode" -msgstr "" +#, fuzzy +#~ msgid " -e Ex mode\n" +#~ msgstr " kahta tilaa varten " -#: ../main.c:2204 -msgid "-s\t\t\tSilent (batch) mode (only for \"ex\")" -msgstr "-s\t\t\tHiljainen (erไajo)tila (vain exillไ)" +#, fuzzy +#~ msgid " -E Improved Ex mode\n" +#~ msgstr " kahta tilaa varten " -#: ../main.c:2205 -msgid "-d\t\t\tDiff mode (like \"vimdiff\")" -msgstr "-d\t\t\tDiff-tila (kuten vimdiffillไ)" +#, fuzzy +#~ msgid " -s Silent (batch) mode (only for ex mode)\n" +#~ msgstr "-s\t\t\tHiljainen (erรคajo)tila (vain exillรค)" -#: ../main.c:2206 -msgid "-y\t\t\tEasy mode (like \"evim\", modeless)" -msgstr "-y\t\t\tHelppokไytt๖tila (kuten evimissไ, ilman tiloja)" +#, fuzzy +#~ msgid " -d Diff mode\n" +#~ msgstr " kahta tilaa varten " -#: ../main.c:2207 -msgid "-R\t\t\tReadonly mode (like \"view\")" -msgstr "-R\t\t\tKirjoitussuojattu tila (kuten view'lla)" +#, fuzzy +#~ msgid " -R Read-only mode\n" +#~ msgstr " kahta tilaa varten " -#: ../main.c:2208 -msgid "-Z\t\t\tRestricted mode (like \"rvim\")" -msgstr "-Z\t\t\tRajoitettu tila (kuten rvimillไ)" +#, fuzzy +#~ msgid " -Z Restricted mode\n" +#~ msgstr " kahta tilaa varten " -#: ../main.c:2209 -msgid "-m\t\t\tModifications (writing files) not allowed" -msgstr "-m\t\t\tMuokkaukset (kirjoittaminen tiedostoon) pois kไyt๖stไ" +#, fuzzy +#~ msgid " -m Modifications (writing files) not allowed\n" +#~ msgstr "-m\t\t\tMuokkaukset (kirjoittaminen tiedostoon) pois kรคytรถstรค" -#: ../main.c:2210 -msgid "-M\t\t\tModifications in text not allowed" -msgstr "-M\t\t\tTekstin muokkaus pois kไyt๖stไ" +#, fuzzy +#~ msgid " -M Modifications in text not allowed\n" +#~ msgstr "-M\t\t\tTekstin muokkaus pois kรคytรถstรค" -#: ../main.c:2211 -msgid "-b\t\t\tBinary mode" -msgstr "-b\t\t\tBinไไritila" +#, fuzzy +#~ msgid " -b Binary mode\n" +#~ msgstr " kahta tilaa varten " -#: ../main.c:2212 -msgid "-l\t\t\tLisp mode" -msgstr "-l\t\t\tLisp-tila" +#, fuzzy +#~ msgid " -l Lisp mode\n" +#~ msgstr " kahta tilaa varten " -#: ../main.c:2213 -msgid "-C\t\t\tCompatible with Vi: 'compatible'" -msgstr "-C\t\t\tVi-yhteensopivuustila: compatible" +#, fuzzy +#~ msgid " -A Arabic mode\n" +#~ msgstr " kahta tilaa varten " -#: ../main.c:2214 -msgid "-N\t\t\tNot fully Vi compatible: 'nocompatible'" -msgstr "-N\t\t\tEi Vi-yhteensopivuutta: nocompatible" +#, fuzzy +#~ msgid " -F Farsi mode\n" +#~ msgstr " kahta tilaa varten " -#: ../main.c:2215 -msgid "-V[N][fname]\t\tBe verbose [level N] [log messages to fname]" -msgstr "" -"-V[N][tnimi]\t\tMonisanainen tuloste [Taso N] [kirjoita tuloste tnimeen] " +#, fuzzy +#~ msgid " -H Hebrew mode\n" +#~ msgstr " kahta tilaa varten " -#: ../main.c:2216 -msgid "-D\t\t\tDebugging mode" -msgstr "-D\t\t\tVianetsintไtila" +#, fuzzy +#~ msgid " -V[N][file] Be verbose [level N][log messages to file]\n" +#~ msgstr "" +#~ "-V[N][tnimi]\t\tMonisanainen tuloste [Taso N] [kirjoita tuloste tnimeen] " -#: ../main.c:2217 -msgid "-n\t\t\tNo swap file, use memory only" -msgstr "-n\t\t\tEi swap-tiedostoja, kไytไ muistia" +#, fuzzy +#~ msgid " -D Debugging mode\n" +#~ msgstr " kahta tilaa varten " -#: ../main.c:2218 -msgid "-r\t\t\tList swap files and exit" -msgstr "-r\t\t\tLuetteloi swap-tiedostot ja poistu" +#, fuzzy +#~ msgid " -n No swap file, use memory only\n" +#~ msgstr "-n\t\t\tEi swap-tiedostoja, kรคytรค muistia" -#: ../main.c:2219 -msgid "-r (with file name)\tRecover crashed session" -msgstr "-r (tiedostonimi)\tPalauta kaatunut sessio" +#, fuzzy +#~ msgid " -r, -L List swap files and exit\n" +#~ msgstr "-r\t\t\tLuetteloi swap-tiedostot ja poistu" -#: ../main.c:2220 -msgid "-L\t\t\tSame as -r" -msgstr "-L\t\t\tkuten -r" +#, fuzzy +#~ msgid " -r <file> Recover crashed session\n" +#~ msgstr "-r (tiedostonimi)\tPalauta kaatunut sessio" -#: ../main.c:2221 -msgid "-A\t\t\tstart in Arabic mode" -msgstr "-A\t\t\tkไynnistไ arabia-tilassa" +#, fuzzy +#~ msgid " -u <vimrc> Use <vimrc> instead of the default\n" +#~ msgstr "-u <vimrc>\t\tKรคytรค <vimrc>-tiedostoa .vimrc:iden sijasta" -#: ../main.c:2222 -msgid "-H\t\t\tStart in Hebrew mode" -msgstr "-H\t\t\tkไynnistไ heprea-tilassa" +#~ msgid " -i <shada> Use <shada> instead of the default\n" +#~ msgstr "" -#: ../main.c:2223 -msgid "-F\t\t\tStart in Farsi mode" -msgstr "-F\t\t\tkไynnistไ farsi-tilassa" +#, fuzzy +#~ msgid " --noplugin Don't load plugin scripts\n" +#~ msgstr "--noplugin\t\tรlรค lataa liitรคnnรคisiรค" -#: ../main.c:2224 -msgid "-T <terminal>\tSet terminal type to <terminal>" -msgstr "-T <terminaali>\tAseta terminaalin tyypiksi <terminaali>" +#, fuzzy +#~ msgid " -o[N] Open N windows (default: one for each file)\n" +#~ msgstr "-o[N]\t\tAvaa N ikkunaa (oletus: yksi per tiedosto)" -#: ../main.c:2225 -msgid "-u <vimrc>\t\tUse <vimrc> instead of any .vimrc" -msgstr "-u <vimrc>\t\tKไytไ <vimrc>-tiedostoa .vimrc:iden sijasta" +#, fuzzy +#~ msgid " -O[N] Like -o but split vertically\n" +#~ msgstr "-O[N]\t\tKuten -o, mutta jaa pystysuunnassa" -#: ../main.c:2226 -msgid "--noplugin\t\tDon't load plugin scripts" -msgstr "--noplugin\t\tฤlไ lataa liitไnnไisiไ" +#, fuzzy +#~ msgid " -p[N] Open N tab pages (default: one for each file)\n" +#~ msgstr "-p[N]\t\tAvaa N vรคlilehteรค (oletus: yksi per tiedosto)" -#: ../main.c:2227 -msgid "-p[N]\t\tOpen N tab pages (default: one for each file)" -msgstr "-p[N]\t\tAvaa N vไlilehteไ (oletus: yksi per tiedosto)" +#, fuzzy +#~ msgid " + Start at end of file\n" +#~ msgstr " kahta tilaa varten " -#: ../main.c:2228 -msgid "-o[N]\t\tOpen N windows (default: one for each file)" -msgstr "-o[N]\t\tAvaa N ikkunaa (oletus: yksi per tiedosto)" +#, fuzzy +#~ msgid " +<linenum> Start at line <linenum>\n" +#~ msgstr "+<rivi>\t\t\tAloita riviltรค <rivi>" -#: ../main.c:2229 -msgid "-O[N]\t\tLike -o but split vertically" -msgstr "-O[N]\t\tKuten -o, mutta jaa pystysuunnassa" +#~ msgid " +/<pattern> Start at first occurrence of <pattern>\n" +#~ msgstr "" -#: ../main.c:2230 -msgid "+\t\t\tStart at end of file" -msgstr "+\t\t\tAloita tiedoston lopusta" +#, fuzzy +#~ msgid " --cmd <command> Execute <command> before loading any vimrc\n" +#~ msgstr "--cmd <komento>\tSuorita <komento> ennen vimrc:iden latausta" -#: ../main.c:2231 -msgid "+<lnum>\t\tStart at line <lnum>" -msgstr "+<rivi>\t\t\tAloita riviltไ <rivi>" +#, fuzzy +msgid "" +" -c <command> Execute <command> after loading the first file\n" +msgstr "-c <komento>\t\tSuorita <komento> ensimmรคisen tiedoston latauduttua" -#: ../main.c:2232 -msgid "--cmd <command>\tExecute <command> before loading any vimrc file" -msgstr "--cmd <komento>\tSuorita <komento> ennen vimrc:iden latausta" +#, fuzzy +#~ msgid " -S <session> Source <session> after loading the first file\n" +#~ msgstr "-S <sessio>\t\tLataa <sessio> ensimmรคisen tiedoston latauduttua" -#: ../main.c:2233 -msgid "-c <command>\t\tExecute <command> after loading the first file" -msgstr "-c <komento>\t\tSuorita <komento> ensimmไisen tiedoston latauduttua" +#, fuzzy +#~ msgid " -s <scriptin> Read Normal mode commands from <scriptin>\n" +#~ msgstr "-s <skripti>\tLue normaalitilan komentoja <skripti>-tiedostosta" -#: ../main.c:2235 -msgid "-S <session>\t\tSource file <session> after loading the first file" -msgstr "-S <sessio>\t\tLataa <sessio> ensimmไisen tiedoston latauduttua" +#, fuzzy +#~ msgid " -w <scriptout> Append all typed characters to <scriptout>\n" +#~ msgstr "-w <skripti>\tLisรครค kirjoitetut komennot <skripti>-tiedostoon" -#: ../main.c:2236 -msgid "-s <scriptin>\tRead Normal mode commands from file <scriptin>" -msgstr "-s <skripti>\tLue normaalitilan komentoja <skripti>-tiedostosta" +#, fuzzy +#~ msgid " -W <scriptout> Write all typed characters to <scriptout>\n" +#~ msgstr "-W <skripti>\tKirjoita komennot <skripti>-tiedostoon" -#: ../main.c:2237 -msgid "-w <scriptout>\tAppend all typed commands to file <scriptout>" -msgstr "-w <skripti>\tLisไไ kirjoitetut komennot <skripti>-tiedostoon" +#, fuzzy +#~ msgid " --startuptime <file> Write startup timing messages to <file>\n" +#~ msgstr "--startuptime <file>\tKirjoita kรคynnistysaikaviestit tiedostoon <file>" -#: ../main.c:2238 -msgid "-W <scriptout>\tWrite all typed commands to file <scriptout>" -msgstr "-W <skripti>\tKirjoita komennot <skripti>-tiedostoon" +#~ msgid "" +#~ " --api-info Dump API metadata serialized to msgpack and exit\n" +#~ msgstr "" -#: ../main.c:2240 -msgid "--startuptime <file>\tWrite startup timing messages to <file>" -msgstr "--startuptime <file>\tKirjoita kไynnistysaikaviestit tiedostoon <file>" +#~ msgid " --embed Use stdin/stdout as a msgpack-rpc channel\n" +#~ msgstr "" -#: ../main.c:2242 -msgid "-i <viminfo>\t\tUse <viminfo> instead of .viminfo" -msgstr "-i <viminfo>\t\tKไytไ <viminfo>-tiedostoa .viminfon sijaan" +#~ msgid " --headless Don't start a user interface\n" +#~ msgstr "" -#: ../main.c:2243 -msgid "-h or --help\tPrint Help (this message) and exit" -msgstr "-h tai --help\tTulosta ohje (tไmไ viesti) ja lopeta" +#, fuzzy +#~ msgid " -v, --version Print version information and exit\n" +#~ msgstr "--version\t\t\tTulosta versiotiedot ja lopeta" -#: ../main.c:2244 -msgid "--version\t\tPrint version information and exit" -msgstr "--version\t\t\tTulosta versiotiedot ja lopeta" +#, fuzzy +#~ msgid " -h, --help Print this help message and exit\n" +#~ msgstr "-h tai --help\tTulosta ohje (tรคmรค viesti) ja lopeta" -#: ../mark.c:676 msgid "No marks set" -msgstr "Ei asetettuja merkkejไ" +msgstr "Ei asetettuja merkkejรค" -#: ../mark.c:678 #, c-format msgid "E283: No marks matching \"%s\"" -msgstr "E283: Mikไไn merkki ei tไsmไไ ilmaukseen \"%s\"" +msgstr "E283: Mikรครคn merkki ei tรคsmรครค ilmaukseen \"%s\"" #. Highlight title -#: ../mark.c:687 msgid "" "\n" "mark line col file/text" @@ -3615,7 +3403,6 @@ msgstr "" "merkki rivi sarake tiedosto/teksti" #. Highlight title -#: ../mark.c:789 msgid "" "\n" " jump line col file/text" @@ -3624,7 +3411,6 @@ msgstr "" "hyppy rivi sarake tiedosto/teksti" #. Highlight title -#: ../mark.c:831 msgid "" "\n" "change line col text" @@ -3632,138 +3418,85 @@ msgstr "" "\n" "muutos rivi sarake teksti" -#: ../mark.c:1238 -msgid "" -"\n" -"# File marks:\n" -msgstr "" -"\n" -"# Tiedoston merkit:\n" - -#. Write the jumplist with -' -#: ../mark.c:1271 -msgid "" -"\n" -"# Jumplist (newest first):\n" -msgstr "" -"\n" -"# Hyppylista (uusin ensiksi):\n" - -#: ../mark.c:1352 -msgid "" -"\n" -"# History of marks within files (newest to oldest):\n" -msgstr "" -"\n" -"# Tiedostojen merkkien historia (uusimmasta vanhimpaan):\n" - -#: ../mark.c:1431 -msgid "Missing '>'" -msgstr "> puuttuu" - -#: ../memfile.c:426 msgid "E293: block was not locked" msgstr "E293: lohkoa ei ole lukittu" -#: ../memfile.c:799 msgid "E294: Seek error in swap file read" msgstr "E294: Hakuvirhe swap-tiedostoa luettaessa" -#: ../memfile.c:803 msgid "E295: Read error in swap file" msgstr "E295: Lukuvirhe swap-tiedostossa" -#: ../memfile.c:849 msgid "E296: Seek error in swap file write" msgstr "E296: Hakuvirhe swap-tiedostoa kirjoitettaessa" -#: ../memfile.c:865 msgid "E297: Write error in swap file" msgstr "E297: Kirjoitusvirhe swap-tiedostossa" -#: ../memfile.c:1036 msgid "E300: Swap file already exists (symlink attack?)" -msgstr "E300: Swaptiedosto on jo olemassa (symlink-hy๖kkไys?)" +msgstr "E300: Swaptiedosto on jo olemassa (symlink-hyรถkkรคys?)" -#: ../memline.c:318 msgid "E298: Didn't get block nr 0?" msgstr "E298: Lohko 0:aa ei saatu?" -#: ../memline.c:361 msgid "E298: Didn't get block nr 1?" -msgstr "E298: Lohko 1:tไ ei saatu?" +msgstr "E298: Lohko 1:tรค ei saatu?" -#: ../memline.c:377 msgid "E298: Didn't get block nr 2?" msgstr "E298: Lohko 2:ta ei saatu?" #. could not (re)open the swap file, what can we do???? -#: ../memline.c:465 msgid "E301: Oops, lost the swap file!!!" -msgstr "E301: Hups, swap-tiedosto hไvisi!" +msgstr "E301: Hups, swap-tiedosto hรคvisi!" -#: ../memline.c:477 msgid "E302: Could not rename swap file" msgstr "E302: Swap-tiedoston uudellennimeys ei onnistu" -#: ../memline.c:554 #, c-format msgid "E303: Unable to open swap file for \"%s\", recovery impossible" msgstr "E303: Swap-tiedostoa %s ei voi avata, palautus ei onnistu" -#: ../memline.c:666 msgid "E304: ml_upd_block0(): Didn't get block 0??" msgstr "E304: ml_upd_block0(): Lohko 0:aa ei saatu?" #. no swap files found -#: ../memline.c:830 #, c-format msgid "E305: No swap file found for %s" msgstr "E305: Ei swap-tiedostoa tiedostolle %s" -#: ../memline.c:839 msgid "Enter number of swap file to use (0 to quit): " msgstr "Anna swap-tiedoston numero tai 0 lopettaaksesi: " -#: ../memline.c:879 #, c-format msgid "E306: Cannot open %s" msgstr "E306: Ei voi avata tiedostoa %s" -#: ../memline.c:897 msgid "Unable to read block 0 from " msgstr "Ei voi lukea lohkoa 0 kohteesta " -#: ../memline.c:900 msgid "" "\n" "Maybe no changes were made or Vim did not update the swap file." msgstr "" "\n" -"Muutoksia ei tehty, tai Vim ei pไivittไnyt swap-tiedostoa." +"Muutoksia ei tehty, tai Vim ei pรคivittรคnyt swap-tiedostoa." -#: ../memline.c:909 msgid " cannot be used with this version of Vim.\n" -msgstr " ei toimi tไmไn version Vimin kanssa.\n" +msgstr " ei toimi tรคmรคn version Vimin kanssa.\n" -#: ../memline.c:911 msgid "Use Vim version 3.0.\n" -msgstr "Kไytไ Vimin versiota 3.0\n" +msgstr "Kรคytรค Vimin versiota 3.0\n" -#: ../memline.c:916 #, c-format msgid "E307: %s does not look like a Vim swap file" msgstr "E307: %s ei ole Vimin swap-tiedosto" -#: ../memline.c:922 msgid " cannot be used on this computer.\n" -msgstr " ei toimi tไllไ koneella.\n" +msgstr " ei toimi tรคllรค koneella.\n" -#: ../memline.c:924 msgid "The file was created on " msgstr "Tiedosto luotiin " -#: ../memline.c:928 msgid "" ",\n" "or the file has been damaged." @@ -3771,100 +3504,78 @@ msgstr "" ",\n" "tai tiedosto on vahingoittunut." -#: ../memline.c:945 msgid " has been damaged (page size is smaller than minimum value).\n" -msgstr " on vioittunut (sivun koko on vไhimmไisarvoa pienempi).\n" +msgstr " on vioittunut (sivun koko on vรคhimmรคisarvoa pienempi).\n" -#: ../memline.c:974 #, c-format msgid "Using swap file \"%s\"" -msgstr "Kไytetไไn swap-tiedostoa %s" +msgstr "Kรคytetรครคn swap-tiedostoa %s" -#: ../memline.c:980 #, c-format msgid "Original file \"%s\"" -msgstr "Alkuperไinen tiedosto %s" +msgstr "Alkuperรคinen tiedosto %s" -#: ../memline.c:995 msgid "E308: Warning: Original file may have been changed" -msgstr "E308: Varoitus: Alkuperไistไ tiedostoa saattaa olla muutettu" +msgstr "E308: Varoitus: Alkuperรคistรค tiedostoa saattaa olla muutettu" -#: ../memline.c:1061 #, c-format msgid "E309: Unable to read block 1 from %s" msgstr "E309: Ei voitu lukea lohkoa 1 tiedostosta %s" -#: ../memline.c:1065 msgid "???MANY LINES MISSING" -msgstr "???PALJON RIVEJฤ PUUTTUU" +msgstr "???PALJON RIVEJร PUUTTUU" -#: ../memline.c:1076 msgid "???LINE COUNT WRONG" -msgstr "???RIVIMฤฤRฤ PIELESSฤ" +msgstr "???RIVIMรรRร PIELESSร" -#: ../memline.c:1082 msgid "???EMPTY BLOCK" -msgstr "???TYHJฤ LOHKO" +msgstr "???TYHJร LOHKO" -#: ../memline.c:1103 msgid "???LINES MISSING" -msgstr "???RIVEJฤ PUUTTUU" +msgstr "???RIVEJร PUUTTUU" -#: ../memline.c:1128 #, c-format msgid "E310: Block 1 ID wrong (%s not a .swp file?)" -msgstr "E310: Lohon 1 tunniste vไไrไ (%s ei ole .swp-tiedosto?)" +msgstr "E310: Lohon 1 tunniste vรครคrรค (%s ei ole .swp-tiedosto?)" -#: ../memline.c:1133 msgid "???BLOCK MISSING" msgstr "???LOHKO PUUTTUU" -#: ../memline.c:1147 msgid "??? from here until ???END lines may be messed up" -msgstr "??? tไstไ kohtaan ???LOPPU rivejไ sekaisin" +msgstr "??? tรคstรค kohtaan ???LOPPU rivejรค sekaisin" -#: ../memline.c:1164 msgid "??? from here until ???END lines may have been inserted/deleted" -msgstr "??? tไstไ kohtaan ???LOPPU rivejไ saattaa olla lisไtty tai poistettu" +msgstr "??? tรคstรค kohtaan ???LOPPU rivejรค saattaa olla lisรคtty tai poistettu" -#: ../memline.c:1181 msgid "???END" msgstr "???LOPPU" -#: ../memline.c:1238 msgid "E311: Recovery Interrupted" msgstr "E311: Palautus keskeytetty" -#: ../memline.c:1243 msgid "" "E312: Errors detected while recovering; look for lines starting with ???" -msgstr "E312: Palautuksessa oli virheitไ, etsi rivejไ, jotka alkavat ???" +msgstr "E312: Palautuksessa oli virheitรค, etsi rivejรค, jotka alkavat ???" -#: ../memline.c:1245 msgid "See \":help E312\" for more information." -msgstr ":help E312 kertoo lisไtietoja" +msgstr ":help E312 kertoo lisรคtietoja" -#: ../memline.c:1249 msgid "Recovery completed. You should check if everything is OK." -msgstr "Palautus onnistui. Tarkista, ettไ kaikki on kunnossa." +msgstr "Palautus onnistui. Tarkista, ettรค kaikki on kunnossa." -#: ../memline.c:1251 msgid "" "\n" "(You might want to write out this file under another name\n" msgstr "" "\n" -"(Saattaa kannattaa kirjoittaa tไmไ tiedosto toisella nimellไ\n" +"(Saattaa kannattaa kirjoittaa tรคmรค tiedosto toisella nimellรค\n" -#: ../memline.c:1252 msgid "and run diff with the original file to check for changes)" -msgstr "ja katso diffillไ muutokset alkuperไiseen tiedostoon)" +msgstr "ja katso diffillรค muutokset alkuperรคiseen tiedostoon)" -#: ../memline.c:1254 msgid "Recovery completed. Buffer contents equals file contents." -msgstr "Palautus onnistui. Puskurin ja tiedoston sisไll๖t tไsmไไvไt." +msgstr "Palautus onnistui. Puskurin ja tiedoston sisรคllรถt tรคsmรครคvรคt." -#: ../memline.c:1255 msgid "" "\n" "You may want to delete the .swp file now.\n" @@ -3875,51 +3586,42 @@ msgstr "" "\n" #. use msg() to start the scrolling properly -#: ../memline.c:1327 msgid "Swap files found:" -msgstr "Swap-tiedostoja l๖ytyi:" +msgstr "Swap-tiedostoja lรถytyi:" -#: ../memline.c:1446 msgid " In current directory:\n" -msgstr " Tไssไ hakemistossa:\n" +msgstr " Tรคssรค hakemistossa:\n" -#: ../memline.c:1448 msgid " Using specified name:\n" -msgstr " Mไไritellyllไ nimellไ:\n" +msgstr " Mรครคritellyllรค nimellรค:\n" -#: ../memline.c:1450 msgid " In directory " msgstr " Hakemistossa " -#: ../memline.c:1465 msgid " -- none --\n" -msgstr " -- ei mitไไn --\n" +msgstr " -- ei mitรครคn --\n" -#: ../memline.c:1527 msgid " owned by: " msgstr " omistaja: " -#: ../memline.c:1529 msgid " dated: " msgstr " ajalta: " -#: ../memline.c:1532 ../memline.c:3231 msgid " dated: " msgstr " ajalta:" -#: ../memline.c:1548 msgid " [from Vim version 3.0]" msgstr " [Vimin 3.0-versiosta]" -#: ../memline.c:1550 msgid " [does not look like a Vim swap file]" -msgstr " [ei nไytไ Vimin swap-tiedostolta]" +msgstr " [ei nรคytรค Vimin swap-tiedostolta]" + +#~ msgid " [garbled strings (not nul terminated)]" +#~ msgstr "" -#: ../memline.c:1552 msgid " file name: " msgstr " tiedostonimi: " -#: ../memline.c:1558 msgid "" "\n" " modified: " @@ -3927,27 +3629,22 @@ msgstr "" "\n" " muokattu: " -#: ../memline.c:1559 msgid "YES" -msgstr "KYLLฤ" +msgstr "KYLLร" -#: ../memline.c:1559 msgid "no" msgstr "ei" -#: ../memline.c:1562 msgid "" "\n" " user name: " msgstr "" "\n" -" kไyttไjไnimi: " +" kรคyttรคjรคnimi: " -#: ../memline.c:1568 msgid " host name: " msgstr " laitenimi: " -#: ../memline.c:1570 msgid "" "\n" " host name: " @@ -3955,7 +3652,6 @@ msgstr "" "\n" " laitenimi: " -#: ../memline.c:1575 msgid "" "\n" " process ID: " @@ -3963,190 +3659,143 @@ msgstr "" "\n" " prosessin tunniste: " -#: ../memline.c:1579 msgid " (still running)" -msgstr " (kไynnissไ)" +msgstr " (kรคynnissรค)" -#: ../memline.c:1586 msgid "" "\n" " [not usable on this computer]" msgstr "" "\n" -" [ei toimi tไllไ koneella]" +" [ei toimi tรคllรค koneella]" -#: ../memline.c:1590 msgid " [cannot be read]" msgstr " [ei voi lukea]" -#: ../memline.c:1593 msgid " [cannot be opened]" msgstr " [ei voi avata]" -#: ../memline.c:1698 msgid "E313: Cannot preserve, there is no swap file" -msgstr "E313: Ei voi sไilyttไไ, swap-tiedostoa ei ole" +msgstr "E313: Ei voi sรคilyttรครค, swap-tiedostoa ei ole" -#: ../memline.c:1747 msgid "File preserved" -msgstr "Tiedosto sไilytetty" +msgstr "Tiedosto sรคilytetty" -#: ../memline.c:1749 msgid "E314: Preserve failed" -msgstr "E314: Sไilyttไminen epไonnistui" +msgstr "E314: Sรคilyttรคminen epรคonnistui" -#: ../memline.c:1819 -#, c-format -msgid "E315: ml_get: invalid lnum: %<PRId64>" -msgstr "E315: ml_get: virheellinen lnum: %<PRId64>" +#, fuzzy, c-format +#~ msgid "E315: ml_get: invalid lnum: %<PRId64>" +#~ msgstr "E315: ml_get: virheellinen lnum: %ld" -#: ../memline.c:1851 -#, c-format -msgid "E316: ml_get: cannot find line %<PRId64>" -msgstr "E316: ml_get: riviไ %<PRId64> ei l๖ydy" +#, fuzzy, c-format +#~ msgid "E316: ml_get: cannot find line %<PRId64>" +#~ msgstr "E316: ml_get: riviรค %ld ei lรถydy" -#: ../memline.c:2236 msgid "E317: pointer block id wrong 3" -msgstr "E317: osoitinlohkon tunnus vไไrไ 3" +msgstr "E317: osoitinlohkon tunnus vรครคrรค 3" -#: ../memline.c:2311 msgid "stack_idx should be 0" -msgstr "stack_idx pitไไ olla 0" +msgstr "stack_idx pitรครค olla 0" -#: ../memline.c:2369 msgid "E318: Updated too many blocks?" -msgstr "E318: Pไivitetty liikaa lohkoja" +msgstr "E318: Pรคivitetty liikaa lohkoja" -#: ../memline.c:2511 msgid "E317: pointer block id wrong 4" -msgstr "E317: osoitinlohkon tunnus vไไrไ 4" +msgstr "E317: osoitinlohkon tunnus vรครคrรค 4" -#: ../memline.c:2536 msgid "deleted block 1?" msgstr "poistettu lohko 1?" -#: ../memline.c:2707 -#, c-format -msgid "E320: Cannot find line %<PRId64>" -msgstr "E320: Riviไ %<PRId64> ei l๖ydy" +#, fuzzy, c-format +#~ msgid "E320: Cannot find line %<PRId64>" +#~ msgstr "E320: Riviรค %ld ei lรถydy" -#: ../memline.c:2916 msgid "E317: pointer block id wrong" -msgstr "E317: osoitinlohkon tunnus vไไrไ" +msgstr "E317: osoitinlohkon tunnus vรครคrรค" -#: ../memline.c:2930 msgid "pe_line_count is zero" msgstr "pe_line_count on nolla" -#: ../memline.c:2955 -#, c-format -msgid "E322: line number out of range: %<PRId64> past the end" -msgstr "E322: rivinumero arvoalueen ulkopuoleta: %<PRId64> on loppua suurempi" +#, fuzzy, c-format +#~ msgid "E322: line number out of range: %<PRId64> past the end" +#~ msgstr "E322: rivinumero arvoalueen ulkopuoleta: %ld on loppua suurempi" -#: ../memline.c:2959 -#, c-format -msgid "E323: line count wrong in block %<PRId64>" -msgstr "E323: rivimไไrไ vไไrin lohkossa %<PRId64>" +#, fuzzy, c-format +#~ msgid "E323: line count wrong in block %<PRId64>" +#~ msgstr "E323: rivimรครคrรค vรครคrin lohkossa %ld" -#: ../memline.c:2999 msgid "Stack size increases" msgstr "Pinon koko kasvaa" -#: ../memline.c:3038 msgid "E317: pointer block id wrong 2" -msgstr "E317: osoitinlohon tunnus vไไrไ 2" +msgstr "E317: osoitinlohon tunnus vรครคrรค 2" -#: ../memline.c:3070 #, c-format msgid "E773: Symlink loop for \"%s\"" msgstr "E773: Symlinkkisilmukka kohteelle %s" -#: ../memline.c:3221 msgid "E325: ATTENTION" msgstr "E325: HUOMAA" -#: ../memline.c:3222 msgid "" "\n" "Found a swap file by the name \"" msgstr "" "\n" -"Swap-tiedosto l๖ytyi: \"" +"Swap-tiedosto lรถytyi: \"" -#: ../memline.c:3226 msgid "While opening file \"" msgstr "Avattaessa tiedostoa " -#: ../memline.c:3239 msgid " NEWER than swap file!\n" msgstr " joka on UUDEMPI kuin swap-tiedosto!\n" -#: ../memline.c:3244 -#, fuzzy +#. Some of these messages are long to allow translation to +#. * other languages. msgid "" "\n" "(1) Another program may be editing the same file. If this is the case,\n" " be careful not to end up with two different instances of the same\n" -" file when making changes." +" file when making changes. Quit, or continue with caution.\n" msgstr "" "\n" -"(1) Toinen ohjelma saattaa kไyttไไ samaa tiedostoa.\n" -" Jos nไin on, varo, ettet muokkaa saman tiedoston\n" -" kahta instanssia yhtไ aikaa.\n" - -#: ../memline.c:3245 -#, fuzzy -msgid " Quit, or continue with caution.\n" -msgstr " Lopeta, tai jatka.\n" +"(1) Toinen ohjelma saattaa kรคyttรครค samaa tiedostoa.\n" +" Jos nรคin on, varo, ettet muokkaa saman tiedoston\n" +" kahta instanssia yhtรค aikaa. Lopeta tai jatka varoen.\n" -#: ../memline.c:3246 -#, fuzzy msgid "(2) An edit session for this file crashed.\n" -msgstr "" -"\n" -"(2) Ohjelma on kaatunut muokatessa tiedostoa.\n" +msgstr "(2) Tiedostonmuokkausistunto on kaatunut.\n" -#: ../memline.c:3247 msgid " If this is the case, use \":recover\" or \"vim -r " -msgstr " Jos nไin on, kไytไ komentoa :recover tai vim -r " +msgstr " Jos nรคin on, kรคytรค komentoa :recover tai vim -r " -#: ../memline.c:3249 msgid "" "\"\n" " to recover the changes (see \":help recovery\").\n" msgstr "" "\"\n" -" palauttaaksesi muutokset (lisไtietoja: \":help recovery\").\n" +" palauttaaksesi muutokset (lisรคtietoja: \":help recovery\").\n" -#: ../memline.c:3250 msgid " If you did this already, delete the swap file \"" -msgstr " Jos teit jo nไin, poista swap-tiedosto " +msgstr " Jos teit jo nรคin, poista swap-tiedosto " -#: ../memline.c:3252 msgid "" "\"\n" " to avoid this message.\n" msgstr "" "\"\n" -" vไlttไไksesi tไmไn viestin.\n" +" vรคlttรครคksesi tรคmรคn viestin.\n" -#: ../memline.c:3450 ../memline.c:3452 msgid "Swap file \"" msgstr "Swap-tiedosto " -#: ../memline.c:3451 ../memline.c:3455 msgid "\" already exists!" msgstr " on jo olemassa" -#: ../memline.c:3457 msgid "VIM - ATTENTION" msgstr "VIM - HUOMAUTUS" -#: ../memline.c:3459 -msgid "Swap file already exists!" -msgstr "Swap-tiedosto on jo olemassa" - -#: ../memline.c:3464 msgid "" "&Open Read-Only\n" "&Edit anyway\n" @@ -4160,7 +3809,6 @@ msgstr "" "&Lopeta\n" "P&eru" -#: ../memline.c:3467 msgid "" "&Open Read-Only\n" "&Edit anyway\n" @@ -4184,48 +3832,48 @@ msgstr "" #. #. ".s?a" #. ".saa": tried enough, give up -#: ../memline.c:3528 msgid "E326: Too many swap files found" msgstr "E326: Liian monta swap-tiedostoa" -#: ../memory.c:227 -#, c-format -msgid "E342: Out of memory! (allocating %<PRIu64> bytes)" -msgstr "E342: Muisti loppui! (varattaessa %<PRIu64> tavua)" +#, fuzzy, c-format +msgid "" +"E303: Unable to create directory \"%s\" for swap file, recovery impossible: " +"%s" +msgstr "E303: Swap-tiedostoa %s ei voi avata, palautus ei onnistu" + +#, fuzzy +#~ msgid "Vim: Data too large to fit into virtual memory space\n" +#~ msgstr "arvo on liian suuri mahtumaan C:n int-tyyppiin" + +#, fuzzy, c-format +#~ msgid "E342: Out of memory! (allocating %<PRIu64> bytes)" +#~ msgstr "E342: Muisti loppui! (varattaessa %lu tavua)" -#: ../menu.c:62 msgid "E327: Part of menu-item path is not sub-menu" msgstr "E327: Valikkokohtapolun osa ei ole alivalikko" -#: ../menu.c:63 msgid "E328: Menu only exists in another mode" msgstr "E328: Valikko on olemassa vain toisessa tilassa" -#: ../menu.c:64 #, c-format msgid "E329: No menu \"%s\"" msgstr "E329: Ei valikkoa %s" #. Only a mnemonic or accelerator is not valid. -#: ../menu.c:329 msgid "E792: Empty menu name" -msgstr "E792: tyhjไ valikkonimi" +msgstr "E792: tyhjรค valikkonimi" -#: ../menu.c:340 msgid "E330: Menu path must not lead to a sub-menu" msgstr "E330: Valikkopolku ei saa johtaa alivalikkoon" -#: ../menu.c:365 msgid "E331: Must not add menu items directly to menu bar" -msgstr "E331: Valikkokohtia ei saa lisไtไ suoraan valikkopalkkiin" +msgstr "E331: Valikkokohtia ei saa lisรคtรค suoraan valikkopalkkiin" -#: ../menu.c:370 msgid "E332: Separator cannot be part of a menu path" msgstr "E332: Erotin ei voi olla valikkopolun osa" #. Now we have found the matching menu, and we list the mappings #. Highlight title -#: ../menu.c:762 msgid "" "\n" "--- Menus ---" @@ -4233,87 +3881,64 @@ msgstr "" "\n" "--- Valikot ---" -#: ../menu.c:1313 msgid "E333: Menu path must lead to a menu item" msgstr "E333: Valikkopolun on johdettava valikkokohtaan" -#: ../menu.c:1330 #, c-format msgid "E334: Menu not found: %s" -msgstr "E334: Valikkoa ei l๖ydy: %s" +msgstr "E334: Valikkoa ei lรถydy: %s" -#: ../menu.c:1396 #, c-format msgid "E335: Menu not defined for %s mode" -msgstr "E335: Valikkoa ei ole mไไritelty %s-tilassa" - -#: ../menu.c:1426 -msgid "E336: Menu path must lead to a sub-menu" -msgstr "E336: Valikkopolun pitไไ johtaa alivalikkoon" +msgstr "E335: Valikkoa ei ole mรครคritelty %s-tilassa" -#: ../menu.c:1447 -msgid "E337: Menu not found - check menu names" -msgstr "E337: Valikkoa ei l๖ytynyt - tarkista valikkojen nimet" - -#: ../message.c:423 #, c-format msgid "Error detected while processing %s:" msgstr "Virhe suoritettaessa komentoja %s:" -#: ../message.c:445 #, c-format msgid "line %4ld:" msgstr "rivi %4ld:" -#: ../message.c:617 #, c-format msgid "E354: Invalid register name: '%s'" msgstr "E354: Virheellinen rekisterin nimi: %s" -#: ../message.c:986 msgid "Interrupt: " msgstr "Keskeytys: " -#: ../message.c:988 msgid "Press ENTER or type command to continue" -msgstr "Paina enteriไ tai kirjoita komento aloittaaksesi " +msgstr "Paina enteriรค tai kirjoita komento aloittaaksesi " -#: ../message.c:1843 -#, c-format -msgid "%s line %<PRId64>" -msgstr "%s rivi %<PRId64>" +#, fuzzy, c-format +#~ msgid "%s line %<PRId64>" +#~ msgstr "%s rivi %ld" -#: ../message.c:2392 msgid "-- More --" -msgstr "-- Lisไไ --" +msgstr "-- Lisรครค --" -#: ../message.c:2398 msgid " SPACE/d/j: screen/page/line down, b/u/k: up, q: quit " -msgstr " SPACE/d/j: ruutu/sivu/rivi alas, b/u/k: yl๖s, q: lopeta " +msgstr " SPACE/d/j: ruutu/sivu/rivi alas, b/u/k: ylรถs, q: lopeta " -#: ../message.c:3021 ../message.c:3031 msgid "Question" msgstr "Kysymys" -#: ../message.c:3023 msgid "" "&Yes\n" "&No" msgstr "" -"&Kyllไ\n" +"&Kyllรค\n" "&Ei" -#: ../message.c:3033 msgid "" "&Yes\n" "&No\n" "&Cancel" msgstr "" -"&Kyllไ\n" +"&Kyllรค\n" "&Ei\n" "&Peru" -#: ../message.c:3045 msgid "" "&Yes\n" "&No\n" @@ -4321,180 +3946,165 @@ msgid "" "&Discard All\n" "&Cancel" msgstr "" -"&Kyllไ\n" +"&Kyllรค\n" "&Ei\n" "&Tallenna kaikki\n" "T&uhoa kaikki\n" "&Peru" -#: ../message.c:3058 -msgid "E766: Insufficient arguments for printf()" -msgstr "E766: printf():lle ei annettu tarpeeksi argumentteja" - -#: ../message.c:3119 -msgid "E807: Expected Float argument for printf()" -msgstr "E807: Odotettiin Float-argumenttia printf():lle" - -#: ../message.c:3873 -msgid "E767: Too many arguments to printf()" -msgstr "E767: printf():lle annettiin liikaa argumentteja" - -#: ../misc1.c:2256 msgid "W10: Warning: Changing a readonly file" msgstr "W10: Varoitus: Muutetaan kirjoitussuojattua tiedostoa" -#: ../misc1.c:2537 msgid "Type number and <Enter> or click with mouse (empty cancels): " -msgstr "Kirjoita numero ja <Enter> tai valitse hiirellไ (tyhjไ peruu): " +msgstr "Kirjoita numero ja <Enter> tai valitse hiirellรค (tyhjรค peruu): " -#: ../misc1.c:2539 msgid "Type number and <Enter> (empty cancels): " -msgstr "Valitse numero ja <Enter> (tyhjไ peruu): " +msgstr "Valitse numero ja <Enter> (tyhjรค peruu): " -#: ../misc1.c:2585 msgid "1 more line" -msgstr "1 rivi lisไไ" +msgstr "1 rivi lisรครค" -#: ../misc1.c:2588 msgid "1 line less" -msgstr "1 rivi vไhemmไn" +msgstr "1 rivi vรคhemmรคn" -#: ../misc1.c:2593 -#, c-format -msgid "%<PRId64> more lines" -msgstr "%<PRId64> riviไ lisไไ" +#, fuzzy, c-format +#~ msgid "%<PRId64> more lines" +#~ msgstr "%ld riviรค lisรครค" -#: ../misc1.c:2596 -#, c-format -msgid "%<PRId64> fewer lines" -msgstr "%<PRId64> riviไ vไhemmไn" +#, fuzzy, c-format +#~ msgid "%<PRId64> fewer lines" +#~ msgstr "%ld riviรค vรคhemmรคn" -#: ../misc1.c:2599 msgid " (Interrupted)" msgstr " (Keskeytetty)" -#: ../misc1.c:2635 msgid "Beep!" msgstr "Piip!" -#: ../misc2.c:738 #, c-format msgid "Calling shell to execute: \"%s\"" msgstr "Kutsutaan kuorta suorittamaan: %s" -#: ../normal.c:183 +#, c-format +#~ msgid "Invalid channel: %<PRIu64>" +#~ msgstr "" + +#~ msgid "Message is not an array" +#~ msgstr "" + +#, fuzzy +#~ msgid "Message is empty" +#~ msgstr "Viesti" + +#~ msgid "Message type must be an integer" +#~ msgstr "" + +#, fuzzy +#~ msgid "Unknown message type" +#~ msgstr "E574: Tuntematon rekisterityyppi %d" + +#~ msgid "Request array size must be 4 (request) or 3 (notification)" +#~ msgstr "" + +#~ msgid "ID must be a positive integer" +#~ msgstr "" + +#~ msgid "Method must be a string" +#~ msgstr "" + +#, fuzzy +#~ msgid "Parameters must be an array" +#~ msgstr "merkin nimen pitรครค olla yksi merkki" + +#. +#. * nv_*(): functions called to handle Normal and Visual mode commands. +#. * n_*(): functions called to handle Normal mode commands. +#. * v_*(): functions called to handle Visual mode commands. +#. msgid "E349: No identifier under cursor" msgstr "E349: Ei tunnistetta osoittimen alla" -#: ../normal.c:1866 msgid "E774: 'operatorfunc' is empty" -msgstr "E774: operatorfunc on tyhjไ" +msgstr "E774: operatorfunc on tyhjรค" -#: ../normal.c:2637 msgid "Warning: terminal cannot highlight" msgstr "Varoitus: terminaalista puuttuu korostus" -#: ../normal.c:2807 msgid "E348: No string under cursor" msgstr "E348: Ei merkkijonoa kursorin alla" -#: ../normal.c:3937 msgid "E352: Cannot erase folds with current 'foldmethod'" -msgstr "E352: taitoksia ei voi poistaa tไllไ foldmethodilla" +msgstr "E352: taitoksia ei voi poistaa tรคllรค foldmethodilla" -#: ../normal.c:5897 msgid "E664: changelist is empty" -msgstr "E664: muutoslista on tyhjไ" +msgstr "E664: muutoslista on tyhjรค" -#: ../normal.c:5899 msgid "E662: At start of changelist" msgstr "E662: Muutoslistan alussa" -#: ../normal.c:5901 msgid "E663: At end of changelist" msgstr "E663: Muutoslistan lopussa" -#: ../normal.c:7053 -msgid "Type :quit<Enter> to exit Nvim" -msgstr "Komento :quit<Enter> lopettaa Vimin" +#, fuzzy +#~ msgid "Type :quit<Enter> to exit Nvim" +#~ msgstr "Komento :quit<Enter> lopettaa Vimin" -#: ../ops.c:248 #, c-format msgid "1 line %sed 1 time" -msgstr "1 riviไ %s kerran" +msgstr "1 riviรค %s kerran" -#: ../ops.c:250 #, c-format msgid "1 line %sed %d times" -msgstr "1 riviไ %s %d kertaa" +msgstr "1 riviรค %s %d kertaa" -#: ../ops.c:253 -#, c-format -msgid "%<PRId64> lines %sed 1 time" -msgstr "%<PRId64> riviไ %s kerran" +#, fuzzy, c-format +#~ msgid "%<PRId64> lines %sed 1 time" +#~ msgstr "%ld riviรค %s kerran" -#: ../ops.c:256 -#, c-format -msgid "%<PRId64> lines %sed %d times" -msgstr "%<PRId64> riviไ %s %d kertaa" +#, fuzzy, c-format +#~ msgid "%<PRId64> lines %sed %d times" +#~ msgstr "%ld riviรค %s %d kertaa" -#: ../ops.c:592 -#, c-format -msgid "%<PRId64> lines to indent... " -msgstr "%<PRId64> riviไ sisennettไvไnไ..." +#, fuzzy, c-format +#~ msgid "%<PRId64> lines to indent... " +#~ msgstr "%ld riviรค sisennettรคvรคnรค..." -#: ../ops.c:634 msgid "1 line indented " msgstr "1 rivi sisennetty " -#: ../ops.c:636 -#, c-format -msgid "%<PRId64> lines indented " -msgstr "%<PRId64> riviไ sisennetty " +#, fuzzy, c-format +#~ msgid "%<PRId64> lines indented " +#~ msgstr "%ld riviรค sisennetty " -#: ../ops.c:938 msgid "E748: No previously used register" -msgstr "E748: Ei aiemmin kไytettyjไ rekisterejไ" +msgstr "E748: Ei aiemmin kรคytettyjรค rekisterejรค" -#. must display the prompt -#: ../ops.c:1433 -msgid "cannot yank; delete anyway" -msgstr "Ei voi kopioida; poista joka tapauksessa" - -#: ../ops.c:1929 msgid "1 line changed" msgstr "1 rivi muuttui" -#: ../ops.c:1931 -#, c-format -msgid "%<PRId64> lines changed" -msgstr "%<PRId64> riviไ muuttui" +#, fuzzy, c-format +#~ msgid "%<PRId64> lines changed" +#~ msgstr "%ld riviรค muuttui" -#: ../ops.c:2521 msgid "block of 1 line yanked" msgstr "1 rivin lohko kopioitu" -#: ../ops.c:2523 msgid "1 line yanked" msgstr "1 rivi kopioitu" -#: ../ops.c:2525 -#, c-format -msgid "block of %<PRId64> lines yanked" -msgstr "lohko %<PRId64> riviltไ kopioitu" +#, fuzzy, c-format +#~ msgid "block of %<PRId64> lines yanked" +#~ msgstr "lohko %ld riviltรค kopioitu" -#: ../ops.c:2528 -#, c-format -msgid "%<PRId64> lines yanked" -msgstr "%<PRId64> riviไ kopioitu" +#, fuzzy, c-format +#~ msgid "%<PRId64> lines yanked" +#~ msgstr "%ld riviรค kopioitu" -#: ../ops.c:2710 #, c-format msgid "E353: Nothing in register %s" -msgstr "E353: Rekisterissไ %s ei ole mitไไn" +msgstr "E353: Rekisterissรค %s ei ole mitรครคn" #. Highlight title -#: ../ops.c:3185 msgid "" "\n" "--- Registers ---" @@ -4502,207 +4112,142 @@ msgstr "" "\n" "--- Rekisterit ---" -#: ../ops.c:4455 -msgid "Illegal register name" -msgstr "Virheellinen rekisterin nimi" - -#: ../ops.c:4533 msgid "" -"\n" -"# Registers:\n" +"E883: search pattern and expression register may not contain two or more " +"lines" msgstr "" -"\n" -"# Rekisterit:\n" +"E883: hakulauseke- ja -ilmausrekisteri ei voi sisรคltรครค kahta tai useampaa " +"riviรค" -#: ../ops.c:4575 -#, c-format -msgid "E574: Unknown register type %d" -msgstr "E574: Tuntematon rekisterityyppi %d" - -#: ../ops.c:5089 -#, c-format -msgid "%<PRId64> Cols; " -msgstr "%<PRId64> saraketta, " +#, fuzzy, c-format +#~ msgid "%<PRId64> Cols; " +#~ msgstr "%ld saraketta, " -#: ../ops.c:5097 -#, c-format +#, fuzzy, c-format msgid "" "Selected %s%<PRId64> of %<PRId64> Lines; %<PRId64> of %<PRId64> Words; " "%<PRId64> of %<PRId64> Bytes" -msgstr "" -"Valittu %s%<PRId64>/%<PRId64> riviไ, %<PRId64>/%<PRId64> sanaa, %<PRId64>/" -"%<PRId64> tavua" +msgstr "Valittu %s%ld/%ld riviรค, %lld/%lld sanaa, %lld/%lld tavua" -#: ../ops.c:5105 -#, c-format +#, fuzzy, c-format msgid "" "Selected %s%<PRId64> of %<PRId64> Lines; %<PRId64> of %<PRId64> Words; " "%<PRId64> of %<PRId64> Chars; %<PRId64> of %<PRId64> Bytes" msgstr "" -"Valittu %s%<PRId64>/%<PRId64> riviไ, %<PRId64>/%<PRId64> sanaa, %<PRId64>/" -"%<PRId64> merkkiไ, %<PRId64>/%<PRId64> tavua" +"Valittu %s%ld/%ld riviรค, %lld/%lld sanaa, %lld/%lld merkkiรค, %lld/%lld tavua" -#: ../ops.c:5123 -#, c-format +#, fuzzy, c-format msgid "" "Col %s of %s; Line %<PRId64> of %<PRId64>; Word %<PRId64> of %<PRId64>; Byte " "%<PRId64> of %<PRId64>" -msgstr "" -"Sarake %s/%s, Rivi %<PRId64>/%<PRId64>, sana %<PRId64>/%<PRId64>, tavu " -"%<PRId64>/%<PRId64>" +msgstr "Sarake %s/%s, Rivi %ld/%ld, sana %lld/%lld, tavu %lld/%lld" -#: ../ops.c:5133 -#, c-format +#, fuzzy, c-format msgid "" "Col %s of %s; Line %<PRId64> of %<PRId64>; Word %<PRId64> of %<PRId64>; Char " "%<PRId64> of %<PRId64>; Byte %<PRId64> of %<PRId64>" msgstr "" -"Sarake %s/%s, rivi %<PRId64>/%<PRId64>, sana %<PRId64>/%<PRId64>, merkki " -"%<PRId64>/%<PRId64>, tavu %<PRId64>/%<PRId64>" +"Sarake %s/%s, rivi %ld/%ld, sana %lld/%lld, merkki %lld/%lld, tavu %lld/%lld" # Unicode Byte Order Mark -#: ../ops.c:5146 -#, c-format -msgid "(+%<PRId64> for BOM)" -msgstr "(+%<PRId64> BOMista)" - -#: ../option.c:1238 -msgid "%<%f%h%m%=Page %N" -msgstr "%<%f%h%m%=Sivu %N" - -#: ../option.c:1574 -msgid "Thanks for flying Vim" -msgstr "Kiitos ettไ ajoit Vimiไ" +#, fuzzy, c-format +#~ msgid "(+%<PRId64> for BOM)" +#~ msgstr "(+%ld BOMista)" #. found a mismatch: skip -#: ../option.c:2698 msgid "E518: Unknown option" msgstr "E518: Tuntematon asetus" -#: ../option.c:2709 -msgid "E519: Option not supported" -msgstr "E519: Asetusta ei tueta" - -#: ../option.c:2740 msgid "E520: Not allowed in a modeline" -msgstr "E520: Ei sallitu modeline-rivillไ" +msgstr "E520: Ei sallitu modeline-rivillรค" -#: ../option.c:2815 msgid "E846: Key code not set" -msgstr "" +msgstr "E846: Avainkoodi puuttuu" -#: ../option.c:2924 msgid "E521: Number required after =" -msgstr "E521: =:n jไlkeen tarvitaan luku" - -#: ../option.c:3226 ../option.c:3864 -msgid "E522: Not found in termcap" -msgstr "E522: Puuttuu termcapista" +msgstr "E521: =:n jรคlkeen tarvitaan luku" -#: ../option.c:3335 #, c-format msgid "E539: Illegal character <%s>" msgstr "E539: Virheellinen merkki <%s>" -#: ../option.c:3862 -msgid "E529: Cannot set 'term' to empty string" -msgstr "E529: Termiไ ei voi asettaa tyhjไksi merkkijonoksi" +#, c-format +msgid "For option %s" +msgstr "Asetukselle %s" -#: ../option.c:3885 msgid "E589: 'backupext' and 'patchmode' are equal" msgstr "E589: backupext ja patchmod ovat samat" -#: ../option.c:3964 msgid "E834: Conflicts with value of 'listchars'" msgstr "E834: listcharsin arvoissa on ristiriitoja" -#: ../option.c:3966 msgid "E835: Conflicts with value of 'fillchars'" msgstr "E835: fillcharsin arvossa on ristiriitoja" -#: ../option.c:4163 msgid "E524: Missing colon" msgstr "E524: Kaksoispiste puuttuu" -#: ../option.c:4165 msgid "E525: Zero length string" msgstr "E525: Nollan pituinen merkkijono" -#: ../option.c:4220 #, c-format msgid "E526: Missing number after <%s>" -msgstr "E526: Lukuarvo puuttuu merkkijonon <%s> jไlkeen" +msgstr "E526: Lukuarvo puuttuu merkkijonon <%s> jรคlkeen" -#: ../option.c:4232 msgid "E527: Missing comma" msgstr "E527: Pilkku puuttuu" -#: ../option.c:4239 msgid "E528: Must specify a ' value" -msgstr "E528: '-arvo pitไไ antaa" +msgstr "E528: '-arvo pitรครค antaa" -#: ../option.c:4271 msgid "E595: contains unprintable or wide character" -msgstr "E595: Sisไltไไ tulostumattomia tai leveitไ merkkejไ" +msgstr "E595: Sisรคltรครค tulostumattomia tai leveitรค merkkejรค" -#: ../option.c:4469 #, c-format msgid "E535: Illegal character after <%c>" -msgstr "E535: Virheellinen merkki merkin <%c> jไlkeen" +msgstr "E535: Virheellinen merkki merkin <%c> jรคlkeen" -#: ../option.c:4534 msgid "E536: comma required" msgstr "E536: pilkku puuttuu" -#: ../option.c:4543 #, c-format msgid "E537: 'commentstring' must be empty or contain %s" -msgstr "E537: commentstringin pitไไ olla tyhjไ tai sisไltไไ %s" +msgstr "E537: commentstringin pitรครค olla tyhjรค tai sisรคltรครค %s" -#: ../option.c:4928 msgid "E540: Unclosed expression sequence" msgstr "E540: Sulkematon lausekesarja" -#: ../option.c:4932 msgid "E541: too many items" msgstr "E541: liikaa kohteita" -#: ../option.c:4934 msgid "E542: unbalanced groups" -msgstr "E542: epไtasapainoisia ryhmiไ" +msgstr "E542: epรคtasapainoisia ryhmiรค" -#: ../option.c:5148 msgid "E590: A preview window already exists" msgstr "E590: Esikatseluikkuna on jo olemassa" -#: ../option.c:5311 msgid "W17: Arabic requires UTF-8, do ':set encoding=utf-8'" -msgstr "W17: Arabialle pitไไ olla UTF-8:aa, aseta :set encoding=utf-8" +msgstr "W17: Arabialle pitรครค olla UTF-8:aa, aseta :set encoding=utf-8" -#: ../option.c:5623 #, c-format msgid "E593: Need at least %d lines" -msgstr "E593: Tarvitaan ainakin %d riviไ" +msgstr "E593: Tarvitaan ainakin %d riviรค" -#: ../option.c:5631 #, c-format msgid "E594: Need at least %d columns" msgstr "E594: Tarvitaan ainakin %d saraketta" -#: ../option.c:6011 #, c-format msgid "E355: Unknown option: %s" msgstr "E355: Tuntematon asetus: %s" #. There's another character after zeros or the string -#. * is empty. In both cases, we are trying to set a -#. * num option using a string. -#: ../option.c:6037 +#. is empty. In both cases, we are trying to set a +#. num option using a string. #, c-format msgid "E521: Number required: &%s = '%s'" msgstr "E521: tarvitaan luku: &%s = '%s'" -#: ../option.c:6149 msgid "" "\n" "--- Terminal codes ---" @@ -4710,7 +4255,6 @@ msgstr "" "\n" "--- Terminaalikoodit ---" -#: ../option.c:6151 msgid "" "\n" "--- Global option values ---" @@ -4718,7 +4262,6 @@ msgstr "" "\n" "--- Globaalit asetukset ---" -#: ../option.c:6153 msgid "" "\n" "--- Local option values ---" @@ -4726,7 +4269,6 @@ msgstr "" "\n" "--- Paikalliset asetukset ---" -#: ../option.c:6155 msgid "" "\n" "--- Options ---" @@ -4734,29 +4276,24 @@ msgstr "" "\n" "--- Asetukset ---" -#: ../option.c:6816 msgid "E356: get_varp ERROR" msgstr "E356: get_varp-virhe" -#: ../option.c:7696 #, c-format msgid "E357: 'langmap': Matching character missing for %s" -msgstr "E357: langmap: Merkkiin %s tไsmไไvไ merkki puuttuu" +msgstr "E357: langmap: Merkkiin %s tรคsmรครคvรค merkki puuttuu" -#: ../option.c:7715 #, c-format msgid "E358: 'langmap': Extra characters after semicolon: %s" -msgstr "E358: langmap: ylimไไrไisiไ merkkejไ puolipisteen jไlkeen: %s" +msgstr "E358: langmap: ylimรครคrรคisiรค merkkejรค puolipisteen jรคlkeen: %s" -#: ../os/shell.c:194 -msgid "" -"\n" -"Cannot execute shell " -msgstr "" -"\n" -"Kuoren suoritus ei onnistu " +#, c-format +msgid "dlerror = \"%s\"" +msgstr "dlerror = %s" + +msgid "Vim: Error reading input, exiting...\n" +msgstr "Vim: Virhe luettaessa syรถtettรค, poistutaan...\n" -#: ../os/shell.c:439 msgid "" "\n" "shell returned " @@ -4764,8 +4301,18 @@ msgstr "" "\n" "kuoren palautusarvo " -# mikไ security context? -#: ../os_unix.c:465 ../os_unix.c:471 +#~ msgid "" +#~ "\n" +#~ "shell failed to start: " +#~ msgstr "" + +#. Can happen if system() tries to send input to a shell command that was +#. backgrounded (:call system("cat - &", "foo")). #3529 #5241 +#, fuzzy, c-format +#~ msgid "E5677: Error writing input to shell-command: %s" +#~ msgstr "E677: Vรคliaikaistiedostoon kirjoittaminen ei onnistunut" + +# mikรค security context? msgid "" "\n" "Could not get security context for " @@ -4773,7 +4320,6 @@ msgstr "" "\n" "Ei saatu turvallisuuskontekstia kohteelle " -#: ../os_unix.c:479 msgid "" "\n" "Could not set security context for " @@ -4781,947 +4327,897 @@ msgstr "" "\n" "Ei voitu asettaa turvallisuuskontekstia kohteelle " -#: ../os_unix.c:1558 ../os_unix.c:1647 -#, c-format -msgid "dlerror = \"%s\"" -msgstr "dlerror = %s" - -#: ../path.c:1449 #, c-format msgid "E447: Can't find file \"%s\" in path" -msgstr "E447: Tiedosto %s ei l๖ydy polulta" +msgstr "E447: Tiedosto %s ei lรถydy polulta" -#: ../quickfix.c:359 #, c-format msgid "E372: Too many %%%c in format string" msgstr "E372: Liikaa %%%c-juttuja muotoilumerkkijonossa" -#: ../quickfix.c:371 #, c-format msgid "E373: Unexpected %%%c in format string" msgstr "E373: Odottamaton %%%c muotoilumerkkijonossa" -#: ../quickfix.c:420 msgid "E374: Missing ] in format string" msgstr "E374: ] puuttuu muotoilemerkkijonosta" -#: ../quickfix.c:431 #, c-format msgid "E375: Unsupported %%%c in format string" msgstr "E375: Tukematon %%%c muotoilumerkkijonossa" -#: ../quickfix.c:448 #, c-format msgid "E376: Invalid %%%c in format string prefix" msgstr "E376: Virheellinen %%%c muotoilumerkkijonon alussa" -#: ../quickfix.c:454 #, c-format msgid "E377: Invalid %%%c in format string" msgstr "E377: Virheellinen %%%c muotoilumerkkijonossa" #. nothing found -#: ../quickfix.c:477 msgid "E378: 'errorformat' contains no pattern" msgstr "E378: errorformatissa ei ole kuvioita" -#: ../quickfix.c:695 msgid "E379: Missing or empty directory name" -msgstr "E379: Puuttuva tai tyhjไ hakemiston nimi" +msgstr "E379: Puuttuva tai tyhjรค hakemiston nimi" -#: ../quickfix.c:1305 msgid "E553: No more items" -msgstr "E553: Ei enไไ kohteita" +msgstr "E553: Ei enรครค kohteita" + +msgid "E924: Current window was closed" +msgstr "E924: Nykyinen ikkuna on suljettu" + +msgid "E925: Current quickfix was changed" +msgstr "E925: Nykyinen quickfix on muuttunut" + +msgid "E926: Current location list was changed" +msgstr "E926: Nykyinen sijaintiluettelo on muuttunut" -#: ../quickfix.c:1674 #, c-format msgid "(%d of %d)%s%s: " msgstr "(%d/%d)%s%s: " -#: ../quickfix.c:1676 msgid " (line deleted)" msgstr " (rivi poistettu)" -#: ../quickfix.c:1863 +#, c-format +msgid "%serror list %d of %d; %d errors " +msgstr "%svirhelista %d/%d, %d virhettรค" + msgid "E380: At bottom of quickfix stack" msgstr "E380: quickfix-pinon pohjalla" -#: ../quickfix.c:1869 msgid "E381: At top of quickfix stack" msgstr "E381: quickfix-pinon huipulla" -#: ../quickfix.c:1880 -#, c-format -msgid "error list %d of %d; %d errors" -msgstr "virhelista %d/%d, %d virhettไ" +msgid "No entries" +msgstr "Ei kenttiรค" -#: ../quickfix.c:2427 msgid "E382: Cannot write, 'buftype' option is set" msgstr "E382: Ei voi kirjoittaa, buftype asetettu" -#: ../quickfix.c:2812 msgid "E683: File name missing or invalid pattern" msgstr "E683: Tiedostonimi puuttuu tai kuvio on viallinen" -#: ../quickfix.c:2911 #, c-format msgid "Cannot open file \"%s\"" msgstr "Tiedostoa %s ei voi avata" -#: ../quickfix.c:3429 msgid "E681: Buffer is not loaded" msgstr "E681: Puskuria ei ole ladattu" -#: ../quickfix.c:3487 msgid "E777: String or List expected" -msgstr "E777: Pitไไ olla merkkijono tai lista" +msgstr "E777: Pitรครค olla merkkijono tai lista" -#: ../regexp.c:359 #, c-format msgid "E369: invalid item in %s%%[]" msgstr "E369: virheellinen olio kohdassa %s%%[]" -#: ../regexp.c:374 #, c-format msgid "E769: Missing ] after %s[" -msgstr "E769: ] puuttuu merkinnไn %s[ jไljestไ" +msgstr "E769: ] puuttuu merkinnรคn %s[ jรคljestรค" -#: ../regexp.c:375 #, c-format msgid "E53: Unmatched %s%%(" msgstr "E53: Pariton %s%%(" -#: ../regexp.c:376 #, c-format msgid "E54: Unmatched %s(" msgstr "E54: Pariton %s(" -#: ../regexp.c:377 #, c-format msgid "E55: Unmatched %s)" msgstr "E55: Pariton %s)" -#: ../regexp.c:378 msgid "E66: \\z( not allowed here" -msgstr "E66: \\z( ei ole sallittu tไssไ" +msgstr "E66: \\z( ei ole sallittu tรคssรค" -#: ../regexp.c:379 msgid "E67: \\z1 et al. not allowed here" -msgstr "E67: \\z1 jne. ei ole sallittu tไssไ" +msgstr "E67: \\z1 jne. ei ole sallittu tรคssรค" -#: ../regexp.c:380 #, c-format msgid "E69: Missing ] after %s%%[" -msgstr "E69: ] puuttuu merkinnไn %s%%[ jไljestไ" +msgstr "E69: ] puuttuu merkinnรคn %s%%[ jรคljestรค" -#: ../regexp.c:381 #, c-format msgid "E70: Empty %s%%[]" -msgstr "E70: Tyhjไ %s%%[]" +msgstr "E70: Tyhjรค %s%%[]" -#: ../regexp.c:1209 ../regexp.c:1224 msgid "E339: Pattern too long" -msgstr "E339: Liian pitkไ kuvio" +msgstr "E339: Liian pitkรค kuvio" -#: ../regexp.c:1371 msgid "E50: Too many \\z(" -msgstr "E50: Liikaa merkkejไ \\z(" +msgstr "E50: Liikaa merkkejรค \\z(" -#: ../regexp.c:1378 #, c-format msgid "E51: Too many %s(" -msgstr "E51: Liikaa merkkejไ %s(" +msgstr "E51: Liikaa merkkejรค %s(" -#: ../regexp.c:1427 msgid "E52: Unmatched \\z(" msgstr "E52: Pariton \\z(" -#: ../regexp.c:1637 #, c-format msgid "E59: invalid character after %s@" -msgstr "E59: virheellinen merkki kohdan %s@ jไlkeen" +msgstr "E59: virheellinen merkki kohdan %s@ jรคlkeen" -#: ../regexp.c:1672 #, c-format msgid "E60: Too many complex %s{...}s" msgstr "E60: Liikaa monimutkaisia ilmauksia %s{...}s" -#: ../regexp.c:1687 #, c-format msgid "E61: Nested %s*" -msgstr "E61: Sisไkkไistetty %s*" +msgstr "E61: Sisรคkkรคistetty %s*" -#: ../regexp.c:1690 #, c-format msgid "E62: Nested %s%c" -msgstr "E62: Sisไkkไistetty %s%c" +msgstr "E62: Sisรคkkรคistetty %s%c" -#: ../regexp.c:1800 msgid "E63: invalid use of \\_" -msgstr "E63: vไไrinkไytetty \\_" +msgstr "E63: vรครคrinkรคytetty \\_" -#: ../regexp.c:1850 #, c-format msgid "E64: %s%c follows nothing" -msgstr "E64: %s%c jไlkeen ei minkไไn" +msgstr "E64: %s%c jรคlkeen ei minkรครคn" -#: ../regexp.c:1902 msgid "E65: Illegal back reference" -msgstr "E65: Virheellinen tไsmไysviittaus" +msgstr "E65: Virheellinen tรคsmรคysviittaus" -#: ../regexp.c:1943 msgid "E68: Invalid character after \\z" -msgstr "E68: Virheellinen merkki ilmauksen \\z jไlkeen" +msgstr "E68: Virheellinen merkki ilmauksen \\z jรคlkeen" -#: ../regexp.c:2049 ../regexp_nfa.c:1296 #, c-format msgid "E678: Invalid character after %s%%[dxouU]" -msgstr "E678: Virheellinen merkki merkinnไn %s%%[dxouU] jไljessไ" +msgstr "E678: Virheellinen merkki merkinnรคn %s%%[dxouU] jรคljessรค" -#: ../regexp.c:2107 #, c-format msgid "E71: Invalid character after %s%%" -msgstr "E71: Virheellinen merkki merkinnไn %s%% jไljessไ" +msgstr "E71: Virheellinen merkki merkinnรคn %s%% jรคljessรค" + +#, c-format +msgid "E888: (NFA regexp) cannot repeat %s" +msgstr "E888: (NFA-sรครคnn. ilmaus) ei voi toistaa kohdetta %s" -#: ../regexp.c:3017 #, c-format msgid "E554: Syntax error in %s{...}" msgstr "E554: Syntaksivirhe ilmauksessa %s{...}" -#: ../regexp.c:3805 msgid "External submatches:\n" -msgstr "Ulkoisia alitไsmไyksiไ:\n" +msgstr "Ulkoisia alitรคsmรคyksiรค:\n" -#: ../regexp.c:7022 msgid "" "E864: \\%#= can only be followed by 0, 1, or 2. The automatic engine will be " "used " msgstr "" +"E864: \\%#=-merkkien perรครคn voi tulla vain 0, 1 tai 2. Kรคytetรครคn " +"automaattista engineรค " -#: ../regexp_nfa.c:239 -msgid "E865: (NFA) Regexp end encountered prematurely" -msgstr "" - -#: ../regexp_nfa.c:240 -#, c-format -msgid "E866: (NFA regexp) Misplaced %c" -msgstr "" - -#: ../regexp_nfa.c:242 -#, c-format -msgid "E877: (NFA regexp) Invalid character class: %<PRId64>" -msgstr "" - -#: ../regexp_nfa.c:1261 -#, c-format -msgid "E867: (NFA) Unknown operator '\\z%c'" -msgstr "" - -#: ../regexp_nfa.c:1387 -#, c-format -msgid "E867: (NFA) Unknown operator '\\%%%c'" -msgstr "" - -#: ../regexp_nfa.c:1802 -#, c-format -msgid "E869: (NFA) Unknown operator '\\@%c'" -msgstr "" - -#: ../regexp_nfa.c:1831 -msgid "E870: (NFA regexp) Error reading repetition limits" -msgstr "" - -#. Can't have a multi follow a multi. -#: ../regexp_nfa.c:1895 -msgid "E871: (NFA regexp) Can't have a multi follow a multi !" -msgstr "" - -#. Too many `(' -#: ../regexp_nfa.c:2037 -msgid "E872: (NFA regexp) Too many '('" -msgstr "" - -#: ../regexp_nfa.c:2042 -#, fuzzy -msgid "E879: (NFA regexp) Too many \\z(" -msgstr "E50: Liikaa merkkejไ \\z(" - -#: ../regexp_nfa.c:2066 -msgid "E873: (NFA regexp) proper termination error" -msgstr "" - -#: ../regexp_nfa.c:2599 -msgid "E874: (NFA) Could not pop the stack !" -msgstr "" - -#: ../regexp_nfa.c:3298 -msgid "" -"E875: (NFA regexp) (While converting from postfix to NFA), too many states " -"left on stack" -msgstr "" - -#: ../regexp_nfa.c:3302 -msgid "E876: (NFA regexp) Not enough space to store the whole NFA " -msgstr "" - -#: ../regexp_nfa.c:4571 ../regexp_nfa.c:4869 -msgid "" -"Could not open temporary log file for writing, displaying on stderr ... " -msgstr "" +msgid "Switching to backtracking RE engine for pattern: " +msgstr "Vaihdetaan kรคyttรคmรครคn backtrackkaavaa RE-engineรค ilmaukselle: " -#: ../regexp_nfa.c:4840 -#, c-format -msgid "(NFA) COULD NOT OPEN %s !" -msgstr "" - -#: ../regexp_nfa.c:6049 -#, fuzzy -msgid "Could not open temporary log file for writing " -msgstr "E828: Kumoustiedoston avaus kirjoittamista varten ei onnistu: %s" +#~ msgid " TERMINAL" +#~ msgstr "" # tiloja -#: ../screen.c:7435 msgid " VREPLACE" msgstr " VKORVAUS" -#: ../screen.c:7437 msgid " REPLACE" msgstr " KORVAUS" -#: ../screen.c:7440 msgid " REVERSE" -msgstr " KฤฤNTEIS" +msgstr " KรรNTEIS" -#: ../screen.c:7441 msgid " INSERT" -msgstr " SYึTTึ" +msgstr " SYรTTร" -#: ../screen.c:7443 msgid " (insert)" -msgstr " (sy๖tt๖)" +msgstr " (syรถttรถ)" -#: ../screen.c:7445 msgid " (replace)" msgstr " (korvaus)" -#: ../screen.c:7447 msgid " (vreplace)" msgstr " (vkorvaus)" -#: ../screen.c:7449 msgid " Hebrew" msgstr " Heprea" -#: ../screen.c:7454 msgid " Arabic" msgstr " Arabia" -#: ../screen.c:7456 -msgid " (lang)" -msgstr " (kieli)" - -#: ../screen.c:7459 msgid " (paste)" msgstr " (liitos)" -#: ../screen.c:7469 msgid " VISUAL" msgstr " VALINTA" -#: ../screen.c:7470 msgid " VISUAL LINE" msgstr " VALINTARIVI" -#: ../screen.c:7471 msgid " VISUAL BLOCK" msgstr " VALINTALOHKO" -#: ../screen.c:7472 msgid " SELECT" msgstr " WALINTA" -#: ../screen.c:7473 msgid " SELECT LINE" msgstr " WALINTARIVI" -#: ../screen.c:7474 msgid " SELECT BLOCK" msgstr " WALINTALOHKO" -#: ../screen.c:7486 ../screen.c:7541 msgid "recording" msgstr "tallennetaan" -#: ../search.c:487 #, c-format msgid "E383: Invalid search string: %s" msgstr "E383: Viallinen hakujono: %s" -#: ../search.c:832 #, c-format msgid "E384: search hit TOP without match for: %s" -msgstr "E384: Haku pไไsi alkuun l๖ytไmไttไ jonoa: %s" +msgstr "E384: Haku pรครคsi alkuun lรถytรคmรคttรค jonoa: %s" -#: ../search.c:835 #, c-format msgid "E385: search hit BOTTOM without match for: %s" -msgstr "E385: Haku pไไsi loppuun l๖ytไmไttไ jonoa: %s" +msgstr "E385: Haku pรครคsi loppuun lรถytรคmรคttรค jonoa: %s" -#: ../search.c:1200 msgid "E386: Expected '?' or '/' after ';'" -msgstr "E386: ;:n jไlkeen pitไไ olla ? tai /" +msgstr "E386: ;:n jรคlkeen pitรครค olla ? tai /" -#: ../search.c:4085 msgid " (includes previously listed match)" -msgstr " (sisไltไไ viimeksi luetellun tไsmไyksen)" +msgstr " (sisรคltรครค viimeksi luetellun tรคsmรคyksen)" #. cursor at status line -#: ../search.c:4104 msgid "--- Included files " -msgstr "--- Sisไllytetyt tiedostot " +msgstr "--- Sisรคllytetyt tiedostot " -#: ../search.c:4106 msgid "not found " -msgstr "ei l๖ytynyt " +msgstr "ei lรถytynyt " -#: ../search.c:4107 msgid "in path ---\n" msgstr "polusta ---\n" -#: ../search.c:4168 msgid " (Already listed)" msgstr " (Jo lueteltu)" -#: ../search.c:4170 msgid " NOT FOUND" -msgstr " EI LึYTYNYT" +msgstr " EI LรYTYNYT" -#: ../search.c:4211 #, c-format msgid "Scanning included file: %s" -msgstr "Haku sisไlsi tiedoston: %s" +msgstr "Haku sisรคlsi tiedoston: %s" -#: ../search.c:4216 #, c-format msgid "Searching included file %s" -msgstr "Haku sisไlsi tiedoston %s" +msgstr "Haku sisรคlsi tiedoston %s" -#: ../search.c:4405 msgid "E387: Match is on current line" -msgstr "E387: Tไsmไys tไllไ rivillไ" +msgstr "E387: Tรคsmรคys tรคllรค rivillรค" -#: ../search.c:4517 msgid "All included files were found" -msgstr "Kaikki sisไllytetyt rivit l๖ytyivไt" +msgstr "Kaikki sisรคllytetyt rivit lรถytyivรคt" -#: ../search.c:4519 msgid "No included files" -msgstr "Ei sisไllytettyjไ tiedostoja" +msgstr "Ei sisรคllytettyjรค tiedostoja" -#: ../search.c:4527 msgid "E388: Couldn't find definition" -msgstr "E388: Mไไritelmไ ei l๖ydy" +msgstr "E388: Mรครคritelmรค ei lรถydy" -#: ../search.c:4529 msgid "E389: Couldn't find pattern" -msgstr "E389: kuvio ei l๖ydy" +msgstr "E389: kuvio ei lรถydy" + +#~ msgid "too few bytes read" +#~ msgstr "" -#: ../search.c:4668 -msgid "Substitute " -msgstr "Korvaa " +#, fuzzy, c-format +#~ msgid "System error while skipping in ShaDa file: %s" +#~ msgstr "E782: virhe luettaessa .sug-tiedostoa: %s" -#: ../search.c:4681 #, c-format -msgid "" -"\n" -"# Last %sSearch Pattern:\n" -"~" -msgstr "" -"\n" -"# Edellinen %sHakulauseke:\n" -"~" +#~ msgid "" +#~ "Error while reading ShaDa file: last entry specified that it occupies " +#~ "%<PRIu64> bytes, but file ended earlier" +#~ msgstr "" + +#, fuzzy, c-format +#~ msgid "System error while closing ShaDa file: %s" +#~ msgstr "E782: virhe luettaessa .sug-tiedostoa: %s" + +#, fuzzy, c-format +#~ msgid "System error while writing ShaDa file: %s" +#~ msgstr "E782: virhe luettaessa .sug-tiedostoa: %s" + +#, fuzzy, c-format +#~ msgid "Reading ShaDa file \"%s\"%s%s%s" +#~ msgstr "Luetaan viminfo-tiedostoa \"%s\"%s%s%s" + +msgid " info" +msgstr " info" + +msgid " marks" +msgstr " merkit" + +msgid " oldfiles" +msgstr " vanhaatiedostoa" + +msgid " FAILED" +msgstr " EPรONNISTUI" + +#, c-format +#~ msgid "System error while opening ShaDa file %s for reading: %s" +#~ msgstr "" + +#~ msgid "additional elements of ShaDa " +#~ msgstr "" + +#~ msgid "additional data of ShaDa " +#~ msgstr "" + +#, fuzzy, c-format +#~ msgid "Failed to write variable %s" +#~ msgstr "ei voitu vaihtaa puskuriin %d" + +#, c-format +#~ msgid "" +#~ "Failed to parse ShaDa file due to a msgpack parser error at position " +#~ "%<PRIu64>" +#~ msgstr "" + +#, c-format +#~ msgid "" +#~ "Failed to parse ShaDa file: incomplete msgpack string at position %<PRIu64>" +#~ msgstr "" + +#, c-format +#~ msgid "" +#~ "Failed to parse ShaDa file: extra bytes in msgpack string at position " +#~ "%<PRIu64>" +#~ msgstr "" + +#, c-format +#~ msgid "" +#~ "System error while opening ShaDa file %s for reading to merge before writing " +#~ "it: %s" +#~ msgstr "" + +#. Tried names from .tmp.a to .tmp.z, all failed. Something must be +#. wrong then. +#, c-format +#~ msgid "E138: All %s.tmp.X files exist, cannot write ShaDa file!" +#~ msgstr "" + +#, fuzzy, c-format +#~ msgid "System error while opening temporary ShaDa file %s for writing: %s" +#~ msgstr "Vรคliaikaislokitiedoston avaus kirjoittamista varten ei onnistu" + +#, c-format +#~ msgid "Failed to create directory %s for writing ShaDa file: %s" +#~ msgstr "" + +#, c-format +#~ msgid "System error while opening ShaDa file %s for writing: %s" +#~ msgstr "" + +#, fuzzy, c-format +#~ msgid "Writing ShaDa file \"%s\"" +#~ msgstr "Kirjoitetaan viminfo-tiedostoa %s" + +#, fuzzy, c-format +#~ msgid "Failed setting uid and gid for file %s: %s" +#~ msgstr "Ladattu kumoustiedoto %s" + +#, fuzzy, c-format +#~ msgid "E137: ShaDa file is not writable: %s" +#~ msgstr "E137: Viminfo-tiedostoon ei voitu kirjoittaa: %s" + +#, fuzzy, c-format +#~ msgid "Can't rename ShaDa file from %s to %s!" +#~ msgstr "E886: Viminfo-tiedostoa ei voit uudelleennimetรค nimelle %s" + +#, fuzzy, c-format +#~ msgid "Did not rename %s because %s does not looks like a ShaDa file" +#~ msgstr " [ei nรคytรค Vimin swap-tiedostolta]" + +#, c-format +#~ msgid "Did not rename %s to %s because there were errors during writing it" +#~ msgstr "" + +#, c-format +#~ msgid "Do not forget to remove %s or rename it manually to %s." +#~ msgstr "" + +#, fuzzy, c-format +#~ msgid "System error while reading ShaDa file: %s" +#~ msgstr "E782: virhe luettaessa .sug-tiedostoa: %s" + +#, fuzzy, c-format +#~ msgid "System error while reading integer from ShaDa file: %s" +#~ msgstr "E782: virhe luettaessa .sug-tiedostoa: %s" + +#, c-format +#~ msgid "" +#~ "Error while reading ShaDa file: expected positive integer at position " +#~ "%<PRIu64>, but got nothing" +#~ msgstr "" -#: ../spell.c:951 -msgid "E759: Format error in spell file" -msgstr "E759: Muotoiluvirhe oikolukutiedostossa" +#, c-format +#~ msgid "" +#~ "Error while reading ShaDa file: expected positive integer at position " +#~ "%<PRIu64>" +#~ msgstr "" + +#. kSDItemUnknown cannot possibly pass that far because it is -1 and that +#. will fail in msgpack_read_uint64. But kSDItemMissing may and it will +#. otherwise be skipped because (1 << 0) will never appear in flags. +#, c-format +#~ msgid "" +#~ "Error while reading ShaDa file: there is an item at position %<PRIu64> that " +#~ "must not be there: Missing items are for internal uses only" +#~ msgstr "" + +#, c-format +#~ msgid "" +#~ "Error while reading ShaDa file: buffer list at position %<PRIu64> contains " +#~ "entry that is not a dictionary" +#~ msgstr "" + +#, c-format +#~ msgid "" +#~ "Error while reading ShaDa file: buffer list at position %<PRIu64> contains " +#~ "entry with invalid line number" +#~ msgstr "" + +#, c-format +#~ msgid "" +#~ "Error while reading ShaDa file: buffer list at position %<PRIu64> contains " +#~ "entry with invalid column number" +#~ msgstr "" + +#, c-format +#~ msgid "" +#~ "Error while reading ShaDa file: buffer list at position %<PRIu64> contains " +#~ "entry that does not have a file name" +#~ msgstr "" + +#. values for ts_isdiff +#. no different byte (yet) +#. different byte found +#. inserting character +#. values for ts_flags +#. already checked that prefix is OK +#. tried split at this point +#. did a delete, "ts_delidx" has index +#. special values ts_prefixdepth +#. not using prefixes +#. walking through the prefix tree +#. highest value that's not special +#. mode values for find_word +#. find word case-folded +#. find keep-case word +#. find word after prefix +#. find case-folded compound word +#. find keep-case compound word +#, fuzzy +#~ msgid "E759: Format error in spell file" +#~ msgstr "E297: Kirjoitusvirhe swap-tiedostossa" + +msgid "E756: Spell checking is not enabled" +msgstr "E756: Oikaisuluku ei ole pรครคllรค" + +#, c-format +msgid "Warning: Cannot find word list \"%s.%s.spl\" or \"%s.ascii.spl\"" +msgstr "Varoitus: Ei lรถydetty sanalistaa %s.%s.spl tai %s.ascii.spl" + +#. This is probably an error. Give a warning and +#. accept the words anyway. +#, c-format +msgid "Warning: region %s not supported" +msgstr "Varoitus: osaa %s ei tueta" + +msgid "Sorry, no suggestions" +msgstr "ei ehdotuksia" + +#, fuzzy, c-format +#~ msgid "Sorry, only %<PRId64> suggestions" +#~ msgstr "vain %ld ehdotusta" + +#. for when 'cmdheight' > 1 +#. avoid more prompt +#, c-format +msgid "Change \"%.*s\" to:" +msgstr "Muuta %.*s:" + +#, c-format +msgid " < \"%.*s\"" +msgstr " < %.*s" + +msgid "E752: No previous spell replacement" +msgstr "E752: Ei edellistรค oikaisulukukorjausta" + +#, c-format +msgid "E753: Not found: %s" +msgstr "E753: Ei lรถytynyt: %s" -#: ../spell.c:952 msgid "E758: Truncated spell file" msgstr "E758: Oikolukutiedosto katkaistu" -#: ../spell.c:953 #, c-format msgid "Trailing text in %s line %d: %s" -msgstr "Tekstiไ rivin perไssไ tiedostossa %s rivillไ %d: %s" +msgstr "Tekstiรค rivin perรคssรค tiedostossa %s rivillรค %d: %s" -#: ../spell.c:954 #, c-format msgid "Affix name too long in %s line %d: %s" -msgstr "Affiksin nimi on liian pitkไ tiedostossa %s rivillไ %d: %s" +msgstr "Affiksin nimi on liian pitkรค tiedostossa %s rivillรค %d: %s" -#: ../spell.c:955 msgid "E761: Format error in affix file FOL, LOW or UPP" msgstr "E761: Affiksitiedoston FOL-, LOW- tai UPP-muotovirhe " -#: ../spell.c:957 msgid "E762: Character in FOL, LOW or UPP is out of range" -msgstr "E762: Merkki FOL:ssไ, LOW:ssไ tai UPP:ssไ ei kuulu arvoalueeseen" +msgstr "E762: Merkki FOL:ssรค, LOW:ssรค tai UPP:ssรค ei kuulu arvoalueeseen" -#: ../spell.c:958 msgid "Compressing word tree..." -msgstr "Tiivistetไไn sanapuuta..." - -#: ../spell.c:1951 -msgid "E756: Spell checking is not enabled" -msgstr "E756: Oikaisuluku ei ole pไไllไ" - -#: ../spell.c:2249 -#, c-format -msgid "Warning: Cannot find word list \"%s.%s.spl\" or \"%s.ascii.spl\"" -msgstr "Varoitus: Ei l๖ydetty sanalistaa %s.%s.spl tai %s.ascii.spl" +msgstr "Tiivistetรครคn sanapuuta..." -#: ../spell.c:2473 #, c-format msgid "Reading spell file \"%s\"" msgstr "Luetaan oikaisulukutiedosta %s" -#: ../spell.c:2496 msgid "E757: This does not look like a spell file" msgstr "E757: Ei vaikuta oikaisulukutiedostolta" -#: ../spell.c:2501 +#, fuzzy, c-format +#~ msgid "E5042: Failed to read spell file %s: %s" +#~ msgstr "E482: Tiedostoa %s ei voi luoda" + msgid "E771: Old spell file, needs to be updated" -msgstr "E771: Vanha oikaisulukutiedosto vaatii pไivittไmistไ" +msgstr "E771: Vanha oikaisulukutiedosto vaatii pรคivittรคmistรค" -#: ../spell.c:2504 msgid "E772: Spell file is for newer version of Vim" msgstr "E772: Oikaisulukutiedosto on uudemmalle Vimille" -#: ../spell.c:2602 msgid "E770: Unsupported section in spell file" msgstr "E770: Tukematon osio oikaisulukutiedostossa" -#: ../spell.c:3762 #, c-format -msgid "Warning: region %s not supported" -msgstr "Varoitus: osaa %s ei tueta" +msgid "E778: This does not look like a .sug file: %s" +msgstr "E778: Ei vaikuta .sug-tiedostolta: %s" + +#, c-format +msgid "E779: Old .sug file, needs to be updated: %s" +msgstr "E779: Vanha .sug-tiedosto pitรครค pรคivittรครค: %s" + +#, c-format +msgid "E780: .sug file is for newer version of Vim: %s" +msgstr "E780: .sug-tiedosto on uudemmalle Vimille: %s" + +#, c-format +msgid "E781: .sug file doesn't match .spl file: %s" +msgstr "E781: .sug-tiedosto ei tรคsmรครค .spl-tiedostoon: %s" + +#, c-format +msgid "E782: error while reading .sug file: %s" +msgstr "E782: virhe luettaessa .sug-tiedostoa: %s" -#: ../spell.c:4550 #, c-format msgid "Reading affix file %s ..." msgstr "Luetaan affiksitiedostoa %s..." -#: ../spell.c:4589 ../spell.c:5635 ../spell.c:6140 #, c-format msgid "Conversion failure for word in %s line %d: %s" -msgstr "Muunnosvirhe sanalle %s rivillไ %d: %s" +msgstr "Muunnosvirhe sanalle %s rivillรค %d: %s" -#: ../spell.c:4630 ../spell.c:6170 #, c-format msgid "Conversion in %s not supported: from %s to %s" msgstr "Muunnosta kohteessa %s ei tueta: kohteesta %s kohteeseen %s" -#: ../spell.c:4642 #, c-format msgid "Invalid value for FLAG in %s line %d: %s" -msgstr "Tuntematon FLAG kohteessa %s rivillไ %d: %s" +msgstr "Tuntematon FLAG kohteessa %s rivillรค %d: %s" -#: ../spell.c:4655 #, c-format msgid "FLAG after using flags in %s line %d: %s" -msgstr "FLAG kohteessa %s lippujen jไlkeen rivillไ %d: %s" +msgstr "FLAG kohteessa %s lippujen jรคlkeen rivillรค %d: %s" -#: ../spell.c:4723 #, c-format msgid "" "Defining COMPOUNDFORBIDFLAG after PFX item may give wrong results in %s line " "%d" msgstr "" -"COMPOUNDFORBIDFLAG PFX:n jไlkeen voi antaa vไไriไ tuloksia kohteessa %s " -"rivillไ %d" +"COMPOUNDFORBIDFLAG PFX:n jรคlkeen voi antaa vรครคriรค tuloksia kohteessa %s " +"rivillรค %d" -#: ../spell.c:4731 #, c-format msgid "" "Defining COMPOUNDPERMITFLAG after PFX item may give wrong results in %s line " "%d" msgstr "" -"COMPOUNDPERMITFLAG PFX:n jไlkeen voi antaa vไไriไ tuloksia kohteessa %s " -"rivillไ %d" +"COMPOUNDPERMITFLAG PFX:n jรคlkeen voi antaa vรครคriรค tuloksia kohteessa %s " +"rivillรค %d" -#: ../spell.c:4747 #, c-format msgid "Wrong COMPOUNDRULES value in %s line %d: %s" -msgstr "Vไไrไ COMPOUNDRULES-arvo kohteessa %s rivillไ %d: %s" +msgstr "Vรครคrรค COMPOUNDRULES-arvo kohteessa %s rivillรค %d: %s" -#: ../spell.c:4771 #, c-format msgid "Wrong COMPOUNDWORDMAX value in %s line %d: %s" -msgstr "Vไไrไ COMPOUNDWORDMAX-arvo kohteessa %s rivillไ %d: %s" +msgstr "Vรครคrรค COMPOUNDWORDMAX-arvo kohteessa %s rivillรค %d: %s" -#: ../spell.c:4777 #, c-format msgid "Wrong COMPOUNDMIN value in %s line %d: %s" -msgstr "Vไไrไ COMPOUNDMIN-arvo kohteessa %s rivillไ %d: %s" +msgstr "Vรครคrรค COMPOUNDMIN-arvo kohteessa %s rivillรค %d: %s" -#: ../spell.c:4783 #, c-format msgid "Wrong COMPOUNDSYLMAX value in %s line %d: %s" -msgstr "Vไไrไ COMPOUNDSYLMAX-arvo kohteessa %s rivillไ %d: %s" +msgstr "Vรครคrรค COMPOUNDSYLMAX-arvo kohteessa %s rivillรค %d: %s" -#: ../spell.c:4795 #, c-format msgid "Wrong CHECKCOMPOUNDPATTERN value in %s line %d: %s" -msgstr "Vไไrไ CHECKCOMPOUNDPATTERN-arvo kohteessa %s rivillไ %d: %s" +msgstr "Vรครคrรค CHECKCOMPOUNDPATTERN-arvo kohteessa %s rivillรค %d: %s" -#: ../spell.c:4847 #, c-format msgid "Different combining flag in continued affix block in %s line %d: %s" msgstr "" -"Eri yhdistelmไlippu jatketussa affiksilohkossa kohteessa %s rivillไ %d: %s" +"Eri yhdistelmรคlippu jatketussa affiksilohkossa kohteessa %s rivillรค %d: %s" -#: ../spell.c:4850 #, c-format msgid "Duplicate affix in %s line %d: %s" -msgstr "Kaksoiskappale affiksista kohteessa %s rivillไ %d: %s" +msgstr "Kaksoiskappale affiksista kohteessa %s rivillรค %d: %s" -#: ../spell.c:4871 -#, c-format +#, fuzzy, c-format msgid "" -"Affix also used for BAD/RARE/KEEPCASE/NEEDAFFIX/NEEDCOMPOUND/NOSUGGEST in %s " +"Affix also used for BAD/RARE/KEEPCASE/NEEDAFFIX/NEEDCOMPOUND/NOSUGGESTin %s " "line %d: %s" msgstr "" -"Affiksia kไytetty my๖s BAD-, RARE-, KEEPCASE-, NEEDAFFIX-, NEEDCOMPOUND- tai " -"NOSUGGEST-arvossa kohteessa %s rivillไ %d: %s" +"Affiksia kรคytetty myรถs BAD-, RARE-, KEEPCASE-, NEEDAFFIX-, NEEDCOMPOUND- tai " +"NOSUGGEST-arvossa kohteessa %s rivillรค %d: %s" -#: ../spell.c:4893 #, c-format msgid "Expected Y or N in %s line %d: %s" -msgstr "Odotettiin Y:tไ tai N:ไไ kohteessa %s rivillไ %d: %s" +msgstr "Odotettiin Y:tรค tai N:รครค kohteessa %s rivillรค %d: %s" -#: ../spell.c:4968 #, c-format msgid "Broken condition in %s line %d: %s" -msgstr "Viallinen ehto kohteessa %s rivillไ %d: %s" +msgstr "Viallinen ehto kohteessa %s rivillรค %d: %s" -#: ../spell.c:5091 #, c-format msgid "Expected REP(SAL) count in %s line %d" -msgstr "Odotettiin REP(SAL)-arvoa kohteessa %s rivillไ %d" +msgstr "Odotettiin REP(SAL)-arvoa kohteessa %s rivillรค %d" -#: ../spell.c:5120 #, c-format msgid "Expected MAP count in %s line %d" -msgstr "Odotettiin MAP-arvoa kohteessa %s rivillไ %d" +msgstr "Odotettiin MAP-arvoa kohteessa %s rivillรค %d" -#: ../spell.c:5132 #, c-format msgid "Duplicate character in MAP in %s line %d" -msgstr "Kaksoiskappale merkistไ MAP:ssไ kohteessa %s rivillไ %d" +msgstr "Kaksoiskappale merkistรค MAP:ssรค kohteessa %s rivillรค %d" -#: ../spell.c:5176 #, c-format msgid "Unrecognized or duplicate item in %s line %d: %s" -msgstr "Tunnistamaton tai kaksoiskappale arvosta kohteessa %s rivillไ %d: %s" +msgstr "Tunnistamaton tai kaksoiskappale arvosta kohteessa %s rivillรค %d: %s" -#: ../spell.c:5197 #, c-format msgid "Missing FOL/LOW/UPP line in %s" msgstr "Puuttuva FOL, LOW tai UPP rivi kohteessa %s" -#: ../spell.c:5220 msgid "COMPOUNDSYLMAX used without SYLLABLE" msgstr "COMPOUNDSYLMAX ilman SYLLABLEa" -#: ../spell.c:5236 msgid "Too many postponed prefixes" -msgstr "Liikaa jไlkikไteistettyjไ prefiksejไ" +msgstr "Liikaa jรคlkikรคteistettyjรค prefiksejรค" -#: ../spell.c:5238 msgid "Too many compound flags" msgstr "Liikaa yhdyssanalippuja" -#: ../spell.c:5240 msgid "Too many postponed prefixes and/or compound flags" -msgstr "Liikaa jไlkikไteistettyjไ prefiksejไ tai yhdyssanalippuja" +msgstr "Liikaa jรคlkikรคteistettyjรค prefiksejรค tai yhdyssanalippuja" -#: ../spell.c:5250 #, c-format msgid "Missing SOFO%s line in %s" msgstr "Puuttuva SOFO%s-rivi kohteessa %s" -#: ../spell.c:5253 #, c-format msgid "Both SAL and SOFO lines in %s" msgstr "SAL- ja SOFO-rivit kohteessa %s" -#: ../spell.c:5331 #, c-format msgid "Flag is not a number in %s line %d: %s" -msgstr "Lippu ei ole lukuarvo kohteessa %s rivillไ %d: %s" +msgstr "Lippu ei ole lukuarvo kohteessa %s rivillรค %d: %s" -#: ../spell.c:5334 #, c-format msgid "Illegal flag in %s line %d: %s" -msgstr "Tuntematon lippu kohteessa %s rivillไ %d: %s" +msgstr "Tuntematon lippu kohteessa %s rivillรค %d: %s" -#: ../spell.c:5493 ../spell.c:5501 #, c-format msgid "%s value differs from what is used in another .aff file" msgstr "%s-arvo eroaa toisessa .aff-tiedostossa olevasta" -#: ../spell.c:5602 #, c-format msgid "Reading dictionary file %s ..." msgstr "Luetaan sanakirjatiedostoa %s" -#: ../spell.c:5611 #, c-format msgid "E760: No word count in %s" msgstr "E760: Ei sanalaskuria kohteessa %s" -#: ../spell.c:5669 #, c-format msgid "line %6d, word %6d - %s" msgstr "rivi %6d, sana %6d - %s" -#: ../spell.c:5691 #, c-format msgid "Duplicate word in %s line %d: %s" -msgstr "Toistettu sana kohteessa %s rivillไ %d: %s" +msgstr "Toistettu sana kohteessa %s rivillรค %d: %s" -#: ../spell.c:5694 #, c-format msgid "First duplicate word in %s line %d: %s" -msgstr "Ensimmไinen kappale kohteessa %s rivillไ %d: %s" +msgstr "Ensimmรคinen kappale kohteessa %s rivillรค %d: %s" -#: ../spell.c:5746 #, c-format msgid "%d duplicate word(s) in %s" msgstr "toistettuja sanoja %d kohteessa %s" -#: ../spell.c:5748 #, c-format msgid "Ignored %d word(s) with non-ASCII characters in %s" msgstr "Ei-ASCII-merkkien takia ohitettuja sanoja %d kohteessa %s" -#: ../spell.c:6115 #, c-format msgid "Reading word file %s ..." msgstr "Luetaan sanatiedostoa %s..." -#: ../spell.c:6155 #, c-format msgid "Duplicate /encoding= line ignored in %s line %d: %s" -msgstr "Toistettu /encoding= ohitettu kohteessa %s rivillไ %d: %s" +msgstr "Toistettu /encoding= ohitettu kohteessa %s rivillรค %d: %s" -#: ../spell.c:6159 #, c-format msgid "/encoding= line after word ignored in %s line %d: %s" -msgstr "/encoding= sanojen jไlkeen ohitettu kohteessa %s rivillไ %d: %s" +msgstr "/encoding= sanojen jรคlkeen ohitettu kohteessa %s rivillรค %d: %s" -#: ../spell.c:6180 #, c-format msgid "Duplicate /regions= line ignored in %s line %d: %s" -msgstr "Toistettu /regions= ohitettu kohteessa %s rivillไ %d: %s" +msgstr "Toistettu /regions= ohitettu kohteessa %s rivillรค %d: %s" -#: ../spell.c:6185 #, c-format msgid "Too many regions in %s line %d: %s" -msgstr "Liikaa regionseja kohteessa %s rivillไ %d: %s" +msgstr "Liikaa regionseja kohteessa %s rivillรค %d: %s" -#: ../spell.c:6198 #, c-format msgid "/ line ignored in %s line %d: %s" -msgstr "/ ohitettu kohteessa %s rivillไ %d: %s" +msgstr "/ ohitettu kohteessa %s rivillรค %d: %s" -#: ../spell.c:6224 #, c-format msgid "Invalid region nr in %s line %d: %s" -msgstr "Virheellinen region-luku kohteessa %s rivillไ %d: %s" +msgstr "Virheellinen region-luku kohteessa %s rivillรค %d: %s" -#: ../spell.c:6230 #, c-format msgid "Unrecognized flags in %s line %d: %s" -msgstr "Tunnistamaton lippu kohteessa %s rivillไ %d: %s" +msgstr "Tunnistamaton lippu kohteessa %s rivillรค %d: %s" -#: ../spell.c:6257 #, c-format msgid "Ignored %d words with non-ASCII characters" msgstr "Ei-ASCIIn takia ohitettuja sanoja %d" -#: ../spell.c:6656 #, c-format msgid "Compressed %d of %d nodes; %d (%d%%) remaining" -msgstr "Tiivistetty %d/%d noodia. %d (%d %%) jไljellไ" +msgstr "Tiivistetty %d/%d noodia. %d (%d %%) jรคljellรค" -#: ../spell.c:7340 msgid "Reading back spell file..." msgstr "Luetaan taas oikaisulukutiedostoa..." #. Go through the trie of good words, soundfold each word and add it to #. the soundfold trie. -#: ../spell.c:7357 msgid "Performing soundfolding..." -msgstr "ฤไntไmyksen mukaan yhdistellไไn..." +msgstr "รรคntรคmyksen mukaan yhdistellรครคn..." -#: ../spell.c:7368 -#, c-format -msgid "Number of words after soundfolding: %<PRId64>" -msgstr "Sanoja ไไntไmysyhdistelyn jไlkeen: %<PRId64>" +#, fuzzy, c-format +#~ msgid "Number of words after soundfolding: %<PRId64>" +#~ msgstr "Sanoja รครคntรคmysyhdistelyn jรคlkeen: %ld" -#: ../spell.c:7476 #, c-format msgid "Total number of words: %d" -msgstr "Sanoja yhteensไ: %d" +msgstr "Sanoja yhteensรค: %d" -#: ../spell.c:7655 #, c-format msgid "Writing suggestion file %s ..." msgstr "Kirjoitetaan ehdotustiedostoa %s..." -#: ../spell.c:7707 ../spell.c:7927 #, c-format msgid "Estimated runtime memory use: %d bytes" -msgstr "Arvioitu kไytt๖muisti: %d tavua" +msgstr "Arvioitu kรคyttรถmuisti: %d tavua" -#: ../spell.c:7820 msgid "E751: Output file name must not have region name" -msgstr "E751: Tulostetiedostonimessไ ei saa olla alueen nimeไ" +msgstr "E751: Tulostetiedostonimessรค ei saa olla alueen nimeรค" -#: ../spell.c:7822 msgid "E754: Only up to 8 regions supported" -msgstr "E754: Enintไไn 8 aluetta tuetaan" +msgstr "E754: Enintรครคn 8 aluetta tuetaan" -#: ../spell.c:7846 #, c-format msgid "E755: Invalid region in %s" msgstr "E755: Virheellinen alue kohteelle %s" -#: ../spell.c:7907 msgid "Warning: both compounding and NOBREAK specified" -msgstr "Varoitus: sekไ yhdyssanamuodostus ettไ NOBREAK kไyt๖ssไ" +msgstr "Varoitus: sekรค yhdyssanamuodostus ettรค NOBREAK kรคytรถssรค" -#: ../spell.c:7920 #, c-format msgid "Writing spell file %s ..." msgstr "Kirjoitetaan oikaisulukutiedostoa %s..." -#: ../spell.c:7925 msgid "Done!" msgstr "Valmista." -#: ../spell.c:8034 -#, c-format -msgid "E765: 'spellfile' does not have %<PRId64> entries" -msgstr "E765: spellfile ei sisไllไ %<PRId64> kohtaa" - -#: ../spell.c:8074 #, fuzzy, c-format -msgid "Word '%.*s' removed from %s" -msgstr "Sana poistettu kohteesta %s" +#~ msgid "E765: 'spellfile' does not have %<PRId64> entries" +#~ msgstr "E765: spellfile ei sisรคllรค %ld kohtaa" -#: ../spell.c:8117 -#, fuzzy, c-format -msgid "Word '%.*s' added to %s" -msgstr "Sana lisไtty kohteeseen %s" - -#: ../spell.c:8381 -msgid "E763: Word characters differ between spell files" -msgstr "E763: Sanan merkit muuttuvat oikaisulukutiedostojen vไlillไ" - -#: ../spell.c:8684 -msgid "Sorry, no suggestions" -msgstr "Sori, ei ehdotuksia" - -#: ../spell.c:8687 -#, c-format -msgid "Sorry, only %<PRId64> suggestions" -msgstr "Sori, vain %<PRId64> ehdotusta" - -#. for when 'cmdheight' > 1 -#. avoid more prompt -#: ../spell.c:8704 -#, c-format -msgid "Change \"%.*s\" to:" -msgstr "Muuta %.*s:" - -#: ../spell.c:8737 -#, c-format -msgid " < \"%.*s\"" -msgstr " < %.*s" - -#: ../spell.c:8882 -msgid "E752: No previous spell replacement" -msgstr "E752: Ei edellistไ oikaisulukukorjausta" - -#: ../spell.c:8925 -#, c-format -msgid "E753: Not found: %s" -msgstr "E753: Ei l๖ytynyt: %s" - -#: ../spell.c:9276 -#, c-format -msgid "E778: This does not look like a .sug file: %s" -msgstr "E778: Ei vaikuta .sug-tiedostolta: %s" - -#: ../spell.c:9282 -#, c-format -msgid "E779: Old .sug file, needs to be updated: %s" -msgstr "E779: Vanha .sug-tiedosto pitไไ pไivittไไ: %s" - -#: ../spell.c:9286 #, c-format -msgid "E780: .sug file is for newer version of Vim: %s" -msgstr "E780: .sug-tiedosto on uudemmalle Vimille: %s" +msgid "Word '%.*s' removed from %s" +msgstr "Sana %.*s poistettu kohteesta %s" -#: ../spell.c:9295 #, c-format -msgid "E781: .sug file doesn't match .spl file: %s" -msgstr "E781: .sug-tiedosto ei tไsmไไ .spl-tiedostoon: %s" +msgid "Word '%.*s' added to %s" +msgstr "Sana %.*s lisรคtty kohteeseen %s" -#: ../spell.c:9305 -#, c-format -msgid "E782: error while reading .sug file: %s" -msgstr "E782: virhe luettaessa .sug-tiedostoa: %s" +msgid "E763: Word characters differ between spell files" +msgstr "E763: Sanan merkit muuttuvat oikaisulukutiedostojen vรคlillรค" #. This should have been checked when generating the .spl #. file. -#: ../spell.c:11575 msgid "E783: duplicate char in MAP entry" -msgstr "E783: kaksoiskappale merkistไ MAP-kohdassa" +msgstr "E783: kaksoiskappale merkistรค MAP-kohdassa" + +msgid "E766: Insufficient arguments for printf()" +msgstr "E766: printf():lle ei annettu tarpeeksi argumentteja" + +msgid "E807: Expected Float argument for printf()" +msgstr "E807: Odotettiin Float-argumenttia printf():lle" + +msgid "E767: Too many arguments to printf()" +msgstr "E767: printf():lle annettiin liikaa argumentteja" -#: ../syntax.c:266 msgid "No Syntax items defined for this buffer" -msgstr "Ei syntaksikohteita tไlle puskurille" +msgstr "Ei syntaksikohteita tรคlle puskurille" -#: ../syntax.c:3083 ../syntax.c:3104 ../syntax.c:3127 #, c-format msgid "E390: Illegal argument: %s" msgstr "E390: Virheellinen argumentti: %s" -#: ../syntax.c:3299 +msgid "syntax iskeyword " +msgstr "syntax iskeyword " + #, c-format msgid "E391: No such syntax cluster: %s" msgstr "E391: Syntaksiklusteri puuttuu: %s" -#: ../syntax.c:3433 msgid "syncing on C-style comments" msgstr "synkkaa C-tyylin kommentteihin" -#: ../syntax.c:3439 msgid "no syncing" msgstr "ei synkkausta" -#: ../syntax.c:3441 msgid "syncing starts " msgstr "synkkaus aloitettu " -#: ../syntax.c:3443 ../syntax.c:3506 msgid " lines before top line" -msgstr " riviไ ennen alkua" +msgstr " riviรค ennen alkua" -#: ../syntax.c:3448 msgid "" "\n" "--- Syntax sync items ---" @@ -5729,7 +5225,6 @@ msgstr "" "\n" "--- Syntax sync -kohteet ---" -#: ../syntax.c:3452 msgid "" "\n" "syncing on items" @@ -5737,7 +5232,6 @@ msgstr "" "\n" "synkataan kohteisiin" -#: ../syntax.c:3457 msgid "" "\n" "--- Syntax items ---" @@ -5745,2314 +5239,2499 @@ msgstr "" "\n" "--- Syntax-kohteet ---" -#: ../syntax.c:3475 #, c-format msgid "E392: No such syntax cluster: %s" msgstr "E392: syntaksiklusteria ei ole: %s" -#: ../syntax.c:3497 msgid "minimal " -msgstr "vไhintไไn " +msgstr "vรคhintรครคn " -#: ../syntax.c:3503 msgid "maximal " -msgstr "enitntไไn " +msgstr "enitntรครคn " -#: ../syntax.c:3513 msgid "; match " -msgstr "; tไsmไไ " +msgstr "; tรคsmรครค " -#: ../syntax.c:3515 msgid " line breaks" msgstr " rivinvaihdot" -#: ../syntax.c:4076 msgid "E395: contains argument not accepted here" -msgstr "E395: contains ei sovi tไhไn" +msgstr "E395: contains ei sovi tรคhรคn" -#: ../syntax.c:4096 -#, fuzzy msgid "E844: invalid cchar value" -msgstr "E474: Virheellinen argumentti" +msgstr "E844: Virheellinen cchar-arvo" -#: ../syntax.c:4107 msgid "E393: group[t]here not accepted here" -msgstr "E393: group[t]here ei sovi tไhไn" +msgstr "E393: group[t]here ei sovi tรคhรคn" -#: ../syntax.c:4126 #, c-format msgid "E394: Didn't find region item for %s" -msgstr "E394: Aluetta nimelle %s ei l๖ydy" +msgstr "E394: Aluetta nimelle %s ei lรถydy" -#: ../syntax.c:4188 msgid "E397: Filename required" msgstr "E397: Tiedostonimi puuttuu" -#: ../syntax.c:4221 -#, fuzzy msgid "E847: Too many syntax includes" -msgstr "E77: Liikaa tiedostonimiไ" +msgstr "E847: Liikaa syntax includeja" -#: ../syntax.c:4303 #, c-format msgid "E789: Missing ']': %s" msgstr "E789: ] puuttuu: %s" -#: ../syntax.c:4531 +#, c-format +msgid "E890: trailing char after ']': %s]%s" +msgstr "E890: Ylimรครคrรคisiรค merkkejรค merkin ] perรคssรค: %s]%s" + #, c-format msgid "E398: Missing '=': %s" msgstr "E398: = puuttuu: %s" -#: ../syntax.c:4666 #, c-format msgid "E399: Not enough arguments: syntax region %s" msgstr "E399: Argumentteja puuttuu: syntaksialue %s" -#: ../syntax.c:4870 -#, fuzzy msgid "E848: Too many syntax clusters" -msgstr "E391: Syntaksiklusteri puuttuu: %s" +msgstr "E848: Liikaa syntaksiklustereita" -#: ../syntax.c:4954 msgid "E400: No cluster specified" -msgstr "E400: klusteri mไไrittelemไttไ" +msgstr "E400: klusteri mรครคrittelemรคttรค" #. end delimiter not found -#: ../syntax.c:4986 #, c-format msgid "E401: Pattern delimiter not found: %s" msgstr "E401: Kuvoin erotin puuttuu: %s" -#: ../syntax.c:5049 #, c-format msgid "E402: Garbage after pattern: %s" -msgstr "E402: Roskia kuvion jไljessไ: %s" +msgstr "E402: Roskia kuvion jรคljessรค: %s" -#: ../syntax.c:5120 msgid "E403: syntax sync: line continuations pattern specified twice" -msgstr "E403: syntax sync: rivinjatkamiskuvio mไไritelty kahdesti" +msgstr "E403: syntax sync: rivinjatkamiskuvio mรครคritelty kahdesti" -#: ../syntax.c:5169 #, c-format msgid "E404: Illegal arguments: %s" msgstr "E404: Virheelliset argumentit: %s" -#: ../syntax.c:5217 #, c-format msgid "E405: Missing equal sign: %s" msgstr "E405: = puuttuu: %s" -#: ../syntax.c:5222 #, c-format msgid "E406: Empty argument: %s" -msgstr "E406: Tyhjไ argumentti: %s" +msgstr "E406: Tyhjรค argumentti: %s" -#: ../syntax.c:5240 #, c-format msgid "E407: %s not allowed here" -msgstr "E407: %s ei sovi tไhไn" +msgstr "E407: %s ei sovi tรคhรคn" -#: ../syntax.c:5246 #, c-format msgid "E408: %s must be first in contains list" msgstr "E408: %s kuuluu contains-listan alkuun" -#: ../syntax.c:5304 #, c-format msgid "E409: Unknown group name: %s" -msgstr "E409: Tuntematon ryhmไn nimi: %s" +msgstr "E409: Tuntematon ryhmรคn nimi: %s" -#: ../syntax.c:5512 #, c-format msgid "E410: Invalid :syntax subcommand: %s" msgstr "E410: Virheelluinen :syntax-osakomento: %s" -#: ../syntax.c:5854 msgid "" " TOTAL COUNT MATCH SLOWEST AVERAGE NAME PATTERN" msgstr "" +" KAIKKI MรรRร TรSMรYS HITAIN KEKSIARVO NIMI ILMAUS" -#: ../syntax.c:6146 msgid "E679: recursive loop loading syncolor.vim" -msgstr "E679: rekursiivinen silmukka syncolor.vimissไ" +msgstr "E679: rekursiivinen silmukka syncolor.vimissรค" -#: ../syntax.c:6256 #, c-format msgid "E411: highlight group not found: %s" -msgstr "E411: korostusryhmไไ ei l๖ytynyt: %s" +msgstr "E411: korostusryhmรครค ei lรถytynyt: %s" -#: ../syntax.c:6278 #, c-format msgid "E412: Not enough arguments: \":highlight link %s\"" msgstr "E412: Argumentteja puuttuu: :highlight link %s" -#: ../syntax.c:6284 #, c-format msgid "E413: Too many arguments: \":highlight link %s\"" msgstr "E413: Liikaa argumentteja: :highlight link %s" -#: ../syntax.c:6302 msgid "E414: group has settings, highlight link ignored" -msgstr "E414: ryhmไllไ on asetuksia, highlight link -komento ohitetaan" +msgstr "E414: ryhmรคllรค on asetuksia, highlight link -komento ohitetaan" -#: ../syntax.c:6367 #, c-format msgid "E415: unexpected equal sign: %s" msgstr "E415: odotuksenvastainen =-merkki: %s" -#: ../syntax.c:6395 #, c-format msgid "E416: missing equal sign: %s" msgstr "E416: puuttuva =-merkki: %s" -#: ../syntax.c:6418 #, c-format msgid "E417: missing argument: %s" msgstr "E417: puuttuva argumentti: %s" -#: ../syntax.c:6446 #, c-format msgid "E418: Illegal value: %s" msgstr "E418: Viallinen arvo: %s" -#: ../syntax.c:6496 msgid "E419: FG color unknown" -msgstr "E419: edustavไri tuntematon" +msgstr "E419: edustavรคri tuntematon" -#: ../syntax.c:6504 msgid "E420: BG color unknown" -msgstr "E420: taustavไri tuntematon" +msgstr "E420: taustavรคri tuntematon" -#: ../syntax.c:6564 #, c-format msgid "E421: Color name or number not recognized: %s" -msgstr "E421: Vไrin nimi tai numero tuntematon: %s" - -#: ../syntax.c:6714 -#, c-format -msgid "E422: terminal code too long: %s" -msgstr "E422: terminaalikoodi liian pitkไ: %s" +msgstr "E421: Vรคrin nimi tai numero tuntematon: %s" -#: ../syntax.c:6753 #, c-format msgid "E423: Illegal argument: %s" msgstr "E423: Virheellinen argumentti: %s" -#: ../syntax.c:6925 msgid "E424: Too many different highlighting attributes in use" msgstr "E424: Liikaa eri korostusattribuutteja" -#: ../syntax.c:7427 msgid "E669: Unprintable character in group name" -msgstr "E669: Tulostuskelvoton merkki ryhmไn nimessไ" +msgstr "E669: Tulostuskelvoton merkki ryhmรคn nimessรค" -#: ../syntax.c:7434 msgid "W18: Invalid character in group name" -msgstr "W18: Virheellinen merkki ryhmไn nimessไ" +msgstr "W18: Virheellinen merkki ryhmรคn nimessรค" -#: ../syntax.c:7448 msgid "E849: Too many highlight and syntax groups" -msgstr "" +msgstr "E849: Liikaa korostuksia ja syntaksiryhmiรค" -#: ../tag.c:104 msgid "E555: at bottom of tag stack" -msgstr "E555: tไgipinon pohja" +msgstr "E555: tรคgipinon pohja" -#: ../tag.c:105 msgid "E556: at top of tag stack" -msgstr "E556: tไgipinon huippu" +msgstr "E556: tรคgipinon huippu" -#: ../tag.c:380 msgid "E425: Cannot go before first matching tag" -msgstr "E425: Ei voida mennไ ensimmไistไ tไsmไไvไไ tไgiไ alummaksi" +msgstr "E425: Ei voida mennรค ensimmรคistรค tรคsmรครคvรครค tรคgiรค alummaksi" -#: ../tag.c:504 #, c-format msgid "E426: tag not found: %s" -msgstr "E426: tไgi puuttuu: %s" +msgstr "E426: tรคgi puuttuu: %s" -#: ../tag.c:528 msgid " # pri kind tag" -msgstr " # arvo tyyppi tไgi" +msgstr " # arvo tyyppi tรคgi" -#: ../tag.c:531 msgid "file\n" msgstr "tiedosto\n" -#: ../tag.c:829 msgid "E427: There is only one matching tag" -msgstr "E427: Vain yksi tไgi tไsmไไ" +msgstr "E427: Vain yksi tรคgi tรคsmรครค" -#: ../tag.c:831 msgid "E428: Cannot go beyond last matching tag" -msgstr "E428: Ei voida edetไ viimeisen tไsmไไvไn tไgin ohi" +msgstr "E428: Ei voida edetรค viimeisen tรคsmรครคvรคn tรคgin ohi" -#: ../tag.c:850 #, c-format msgid "File \"%s\" does not exist" msgstr "Tiedostoa %s ei ole" #. Give an indication of the number of matching tags -#: ../tag.c:859 #, c-format msgid "tag %d of %d%s" -msgstr "tไgi %d/%d%s" +msgstr "tรคgi %d/%d%s" -#: ../tag.c:862 msgid " or more" msgstr " tai useammasta" -#: ../tag.c:864 msgid " Using tag with different case!" -msgstr " Tไgissไ eri kirjaintaso" +msgstr " Tรคgissรค eri kirjaintaso" -#: ../tag.c:909 #, c-format msgid "E429: File \"%s\" does not exist" msgstr "E429: Tiedostoa %s ei ole" #. Highlight title -#: ../tag.c:960 msgid "" "\n" " # TO tag FROM line in file/text" msgstr "" "\n" -" # TILL tagg FRลN LINJE i fil/text" +" # TILL tagg FRร
N LINJE i fil/text" -#: ../tag.c:1303 #, c-format msgid "Searching tags file %s" -msgstr "Etsitไไn tไgitiedostoa %s" +msgstr "Etsitรครคn tรคgitiedostoa %s" -#: ../tag.c:1545 msgid "Ignoring long line in tags file" -msgstr "Ohitetaan pitkไ rivi tไgitiedostossa" +msgstr "Ohitetaan pitkรค rivi tรคgitiedostossa" -#: ../tag.c:1915 #, c-format msgid "E431: Format error in tags file \"%s\"" -msgstr "E431: Muotovirh tไgitiedostossa %s" +msgstr "E431: Muotovirh tรคgitiedostossa %s" -#: ../tag.c:1917 -#, c-format -msgid "Before byte %<PRId64>" -msgstr "Ennen tavua %<PRId64>" +#, fuzzy, c-format +#~ msgid "Before byte %<PRId64>" +#~ msgstr "Ennen tavua %ld" -#: ../tag.c:1929 #, c-format msgid "E432: Tags file not sorted: %s" -msgstr "E432: Tไgitiedosto ei ole jไrjestetty: %s" +msgstr "E432: Tรคgitiedosto ei ole jรคrjestetty: %s" #. never opened any tags file -#: ../tag.c:1960 msgid "E433: No tags file" -msgstr "E433: Ei tไgitiedostoja" +msgstr "E433: Ei tรคgitiedostoja" -#: ../tag.c:2536 msgid "E434: Can't find tag pattern" -msgstr "E434: Tไgikuviota ei l๖ydy" +msgstr "E434: Tรคgikuviota ei lรถydy" -#: ../tag.c:2544 msgid "E435: Couldn't find tag, just guessing!" -msgstr "E435: Tไgiไ ei l๖ydy, arvataan." +msgstr "E435: Tรคgiรค ei lรถydy, arvataan." -#: ../tag.c:2797 #, c-format msgid "Duplicate field name: %s" -msgstr "Kaksoiskappale kentไn nimestไ: %s" - -#: ../term.c:1442 -msgid "' not known. Available builtin terminals are:" -msgstr " ei tunnettu. Tuetut terminaalit:" - -#: ../term.c:1463 -msgid "defaulting to '" -msgstr "oletusarvona " - -#: ../term.c:1731 -msgid "E557: Cannot open termcap file" -msgstr "E557: Ei voi avata termcap-tiedostoa" - -#: ../term.c:1735 -msgid "E558: Terminal entry not found in terminfo" -msgstr "E558: Terminaalia ei l๖ytynyt terminfosta" - -#: ../term.c:1737 -msgid "E559: Terminal entry not found in termcap" -msgstr "E559: Terminaalia ei l๖ytynyt termcapista" - -#: ../term.c:1878 -#, c-format -msgid "E436: No \"%s\" entry in termcap" -msgstr "E436: %s ei l๖ytynyt termcapista" - -#: ../term.c:2249 -msgid "E437: terminal capability \"cm\" required" -msgstr "E437: terminaalilla pitไไ olla cm kyvyissไไn" - -#. Highlight title -#: ../term.c:4376 -msgid "" -"\n" -"--- Terminal keys ---" -msgstr "" -"\n" -"--- Terminaalinไppไimet ---" - -#: ../ui.c:481 -msgid "Vim: Error reading input, exiting...\n" -msgstr "Vim: Virhe luettaessa sy๖tettไ, poistutaan...\n" +msgstr "Kaksoiskappale kentรคn nimestรค: %s" #. This happens when the FileChangedRO autocommand changes the #. * file in a way it becomes shorter. -#: ../undo.c:379 -#, fuzzy msgid "E881: Line count changed unexpectedly" -msgstr "E834: Rivimไไrไ vaihtui odottamatta" +msgstr "E881: Rivimรครคrรค vaihtui odottamatta" -#: ../undo.c:627 #, c-format msgid "E828: Cannot open undo file for writing: %s" msgstr "E828: Kumoustiedoston avaus kirjoittamista varten ei onnistu: %s" -#: ../undo.c:717 +#, fuzzy, c-format +#~ msgid "E5003: Unable to create directory \"%s\" for undo file: %s" +#~ msgstr "E346: Hakemisto %s ei ole enรครค cdpathissa" + #, c-format msgid "E825: Corrupted undo file (%s): %s" msgstr "E825: Pilaanntunut kumoustiedosto (%s): %s" -#: ../undo.c:1039 msgid "Cannot write undo file in any directory in 'undodir'" -msgstr "Ei voitu lukea kumoustiedostoa mistไไn undodir-muuttujan hakemistosta" +msgstr "Ei voitu lukea kumoustiedostoa mistรครคn undodir-muuttujan hakemistosta" -#: ../undo.c:1074 #, c-format msgid "Will not overwrite with undo file, cannot read: %s" msgstr "Ei ylikirjoitetat kumoustiedostolla, koska ei voida lukea: %s" -#: ../undo.c:1092 #, c-format msgid "Will not overwrite, this is not an undo file: %s" -msgstr "Ei ylikirjoiteta, koska tไmไ ei ole kumoustiedosto: %s" +msgstr "Ei ylikirjoiteta, koska tรคmรค ei ole kumoustiedosto: %s" -#: ../undo.c:1108 msgid "Skipping undo file write, nothing to undo" msgstr "Ohitetaan kumoustiedoston kirjoitus, koska ei ole peruutettavia" -#: ../undo.c:1121 #, c-format msgid "Writing undo file: %s" msgstr "Kirjoitetaan kumoustiedostoa: %s" -#: ../undo.c:1213 #, c-format msgid "E829: write error in undo file: %s" msgstr "E829: Kirjoitusvirhe kumoustiedostossa: %s" -#: ../undo.c:1280 #, c-format msgid "Not reading undo file, owner differs: %s" msgstr "Ei lueta kumoustiedosto jonka omistaja on eri: %s" -#: ../undo.c:1292 #, c-format msgid "Reading undo file: %s" msgstr "Luetaan kumoustiedostoa: %s" -#: ../undo.c:1299 #, c-format msgid "E822: Cannot open undo file for reading: %s" msgstr "E822: Kumoustiedostoa ei voi avata lukemista varten: %s" -#: ../undo.c:1308 #, c-format msgid "E823: Not an undo file: %s" msgstr "E823: Ei ole kumoustiedosto: %s" -#: ../undo.c:1313 #, c-format msgid "E824: Incompatible undo file: %s" -msgstr "E824: Epไyhteensopiva kumoustiedosto: %s" +msgstr "E824: Epรคyhteensopiva kumoustiedosto: %s" -#: ../undo.c:1328 msgid "File contents changed, cannot use undo info" msgstr "" -"Tiedoston sisไlt๖ on muuttunut, joen kumoustiedot ovat kไytt๖kelvottomia" +"Tiedoston sisรคltรถ on muuttunut, joen kumoustiedot ovat kรคyttรถkelvottomia" -#: ../undo.c:1497 #, c-format msgid "Finished reading undo file %s" msgstr "Ladattu kumoustiedoto %s" -#: ../undo.c:1586 ../undo.c:1812 msgid "Already at oldest change" msgstr "Vanhimmassa muutoksessa" -#: ../undo.c:1597 ../undo.c:1814 msgid "Already at newest change" msgstr "Nuorimmassa muutoksessa" -#: ../undo.c:1806 -#, c-format -msgid "E830: Undo number %<PRId64> not found" -msgstr "E830: Kumouslukua %<PRId64> ei l๖ydy" +#, fuzzy, c-format +#~ msgid "E830: Undo number %<PRId64> not found" +#~ msgstr "E830: Kumouslukua %ld ei lรถydy" -#: ../undo.c:1979 msgid "E438: u_undo: line numbers wrong" -msgstr "E438: u_undo: vไไrไt rivinumerot" +msgstr "E438: u_undo: vรครคrรคt rivinumerot" -#: ../undo.c:2183 msgid "more line" -msgstr "rivi lisไไ" +msgstr "rivi lisรครค" -#: ../undo.c:2185 msgid "more lines" -msgstr "riviไ lisไไ" +msgstr "riviรค lisรครค" -#: ../undo.c:2187 msgid "line less" -msgstr "rivi vไhemmไn" +msgstr "rivi vรคhemmรคn" -#: ../undo.c:2189 msgid "fewer lines" -msgstr "riviไ vไhemmไn" +msgstr "riviรค vรคhemmรคn" -#: ../undo.c:2193 msgid "change" msgstr "muutos" -#: ../undo.c:2195 msgid "changes" msgstr "muutosta" -# eka %s ylไpuolelta, toka %s alapuolelta, kolmas %s aika -#: ../undo.c:2225 -#, c-format -msgid "%<PRId64> %s; %s #%<PRId64> %s" -msgstr "%<PRId64> %s, %s #%<PRId64> %s" +# eka %s ylรคpuolelta, toka %s alapuolelta, kolmas %s aika +#, fuzzy, c-format +#~ msgid "%<PRId64> %s; %s #%<PRId64> %s" +#~ msgstr "%ld %s, %s #%ld %s" + +msgid "after" +msgstr "jรคlkeen muutoksen" -#: ../undo.c:2228 msgid "before" msgstr "ennen muutosta" -#: ../undo.c:2228 -msgid "after" -msgstr "jไlkeen muutoksen" - -#: ../undo.c:2325 msgid "Nothing to undo" msgstr "Ei kumottavaa" -#: ../undo.c:2330 -#, fuzzy msgid "number changes when saved" -msgstr "muutoksia aika tallennettu" +msgstr "numero muutoksia aika tallennettu" -#: ../undo.c:2360 -#, c-format -msgid "%<PRId64> seconds ago" -msgstr "%<PRId64> sekuntia sitten" +#, fuzzy, c-format +#~ msgid "%<PRId64> seconds ago" +#~ msgstr "%ld sekuntia sitten" -#: ../undo.c:2372 msgid "E790: undojoin is not allowed after undo" -msgstr "E790: undojoin ei toimi undon jไlkeen" +msgstr "E790: undojoin ei toimi undon jรคlkeen" -#: ../undo.c:2466 msgid "E439: undo list corrupt" msgstr "E439: kumouslista rikki" -#: ../undo.c:2495 msgid "E440: undo line missing" msgstr "E440: kumousrivi puuttuu" -#: ../version.c:600 -msgid "" -"\n" -"Included patches: " -msgstr "" -"\n" -"Pไtsit: " - -#: ../version.c:627 msgid "" "\n" "Extra patches: " msgstr "" "\n" -"Muita pไtsejไ: " - -#: ../version.c:639 ../version.c:864 -msgid "Modified by " -msgstr "Muokannut " +"Muita pรคtsejรค: " -#: ../version.c:646 msgid "" "\n" "Compiled " msgstr "" "\n" -"Kไไntไnyt " +"Kรครคntรคnyt " -#: ../version.c:649 msgid "by " msgstr ": " -#: ../version.c:660 +#, fuzzy msgid "" "\n" -"Huge version " -msgstr "" "\n" -"Huge-versio " - -#: ../version.c:661 -msgid "without GUI." -msgstr "ilman GUIta." - -#: ../version.c:662 -msgid " Features included (+) or not (-):\n" +"Optional features included (+) or not (-): " msgstr " Ominaisuudet mukana (+) ja poissa (-):\n" -#: ../version.c:667 msgid " system vimrc file: \"" -msgstr " jไrjestelmไn vimrc: \"" - -#: ../version.c:672 -msgid " user vimrc file: \"" -msgstr " kไyttไjไn vimrc: \"" - -#: ../version.c:677 -msgid " 2nd user vimrc file: \"" -msgstr " 2. kไyttไjไn vimrc: \"" +msgstr " jรคrjestelmรคn vimrc: \"" -#: ../version.c:682 -msgid " 3rd user vimrc file: \"" -msgstr " 3. kไyttไjไn vimrc: \"" - -#: ../version.c:687 -msgid " user exrc file: \"" -msgstr " kไyttไjไn exrc: \"" - -#: ../version.c:692 -msgid " 2nd user exrc file: \"" -msgstr " 2. kไyttไjไn exrc: \"" - -#: ../version.c:699 msgid " fall-back for $VIM: \"" msgstr " $VIMin fallback: \"" -#: ../version.c:705 msgid " f-b for $VIMRUNTIME: \"" msgstr " $VIMRUNTIMEn f-b: \"" -#: ../version.c:709 -msgid "Compilation: " -msgstr "Kไไnn๖s: " - -#: ../version.c:712 -msgid "Linking: " -msgstr "Linkitys: " - -#: ../version.c:717 -msgid " DEBUG BUILD" -msgstr " DEBUG-versio" - -#: ../version.c:767 -msgid "VIM - Vi IMproved" -msgstr "VIM - Vi IMproved" - -#: ../version.c:769 -msgid "version " -msgstr "versio " - -#: ../version.c:770 msgid "by Bram Moolenaar et al." -msgstr "tekijไt Bram Moolenaar et al." +msgstr "tekijรคt Bram Moolenaar et al." -#: ../version.c:774 -msgid "Vim is open source and freely distributable" -msgstr "Vim on avointa lไhdekoodia ja vapaasti jaossa" +#, fuzzy +#~ msgid "Nvim is open source and freely distributable" +#~ msgstr "Vim on avointa lรคhdekoodia ja vapaasti jaossa" -#: ../version.c:776 -msgid "Help poor children in Uganda!" -msgstr "Auta Ugandan k๖yhiไ lapsia" +#~ msgid "https://neovim.io/community" +#~ msgstr "" -#: ../version.c:777 -msgid "type :help iccf<Enter> for information " -msgstr "kirjoita :help iccf<Enter> lisไtietoa varten " +#, fuzzy +#~ msgid "type :help nvim<Enter> if you are new! " +#~ msgstr "kirjoita :help iccf<Enter> lisรคtietoa varten " + +#, fuzzy +#~ msgid "type :CheckHealth<Enter> to optimize Nvim" +#~ msgstr "kirjoita :help iccf<Enter> lisรคtietoa varten " -#: ../version.c:779 msgid "type :q<Enter> to exit " msgstr "kirjoita :q<Enter> lopettaaksesi " -#: ../version.c:780 -msgid "type :help<Enter> or <F1> for on-line help" -msgstr "kirjoita :help<Enter> tai <F1> ohjetta varten " - -#: ../version.c:781 -msgid "type :help version7<Enter> for version info" -msgstr "kirjoita :help version7<Enter> versiotietoja varten " - -#: ../version.c:784 -msgid "Running in Vi compatible mode" -msgstr "Suoritetaan Vi-yhteensopivuustilaa" +#, fuzzy +#~ msgid "type :help<Enter> for help " +#~ msgstr "kirjoita :q<Enter> lopettaaksesi " -#: ../version.c:785 -msgid "type :set nocp<Enter> for Vim defaults" -msgstr "kirjoita :set nocp<Enter> Vimin oletuksiin " +msgid "Help poor children in Uganda!" +msgstr "Auta Ugandan kรถyhiรค lapsia" -#: ../version.c:786 -msgid "type :help cp-default<Enter> for info on this" -msgstr "kirjoita :help cp-default<Enter> ohjetta oletuksista varten" +msgid "type :help iccf<Enter> for information " +msgstr "kirjoita :help iccf<Enter> lisรคtietoa varten " -#: ../version.c:827 msgid "Sponsor Vim development!" -msgstr "Tue Vimin kehitystไ" +msgstr "Tue Vimin kehitystรค" -#: ../version.c:828 msgid "Become a registered Vim user!" -msgstr "Rekister๖idy Vim-kไyttไjไksi." +msgstr "Rekisterรถidy Vim-kรคyttรคjรคksi." -#: ../version.c:831 msgid "type :help sponsor<Enter> for information " -msgstr "kirjoita :help sponsor<Enter> lisไtietoja varten" +msgstr "kirjoita :help sponsor<Enter> lisรคtietoja varten" -#: ../version.c:832 msgid "type :help register<Enter> for information " -msgstr "kirjoita :help register<Enter> lisไtietoja varten" +msgstr "kirjoita :help register<Enter> lisรคtietoja varten" -#: ../version.c:834 msgid "menu Help->Sponsor/Register for information " -msgstr "valikko Ohje->Sponsoroi/Rekister๖i lisไtietoja varten" +msgstr "valikko Ohje->Sponsoroi/Rekisterรถi lisรคtietoja varten" -#: ../window.c:119 msgid "Already only one window" -msgstr "Enไไ yksi ikkuna jไljellไ" +msgstr "Enรครค yksi ikkuna jรคljellรค" -#: ../window.c:224 msgid "E441: There is no preview window" msgstr "E441: Ei esikatseluikkunaa" -#: ../window.c:559 msgid "E442: Can't split topleft and botright at the same time" -msgstr "E442: Ei voi jakaa vasenta ylไnurkkaa ja oikeaa alanurkkaa yhtไaikaa" +msgstr "E442: Ei voi jakaa vasenta ylรคnurkkaa ja oikeaa alanurkkaa yhtรคaikaa" -#: ../window.c:1228 msgid "E443: Cannot rotate when another window is split" -msgstr "E443: Ei voi kiertไไ kun toinen ikkuna on jaettu" +msgstr "E443: Ei voi kiertรครค kun toinen ikkuna on jaettu" -#: ../window.c:1803 msgid "E444: Cannot close last window" -msgstr "E444: Ei voi sulkea viimeistไ ikkunaa" +msgstr "E444: Ei voi sulkea viimeistรค ikkunaa" -#: ../window.c:1810 msgid "E813: Cannot close autocmd window" msgstr "E813: Ei voi sulkea autocmd-ikkunaa" -#: ../window.c:1814 msgid "E814: Cannot close window, only autocmd window would remain" -msgstr "E814: Ei voi sulkea viimeistไ ikkunaa, joka ei ole autocmd-ikkuna" +msgstr "E814: Ei voi sulkea viimeistรค ikkunaa, joka ei ole autocmd-ikkuna" -#: ../window.c:2717 msgid "E445: Other window contains changes" -msgstr "E445: Toinen ikkuna sisไltไไ muutoksia" +msgstr "E445: Toinen ikkuna sisรคltรครค muutoksia" -#: ../window.c:4805 msgid "E446: No file name under cursor" -msgstr "E446: Ei tiedostonimeไ kursorin alla" +msgstr "E446: Ei tiedostonimeรค kursorin alla" -#~ msgid "E831: bf_key_init() called with empty password" -#~ msgstr "E831: bf_key_init() tyhjไllไ salasanalla" +msgid "List or number required" +msgstr "Lista tai luku tarvitaan" -#~ msgid "E820: sizeof(uint32_t) != 4" -#~ msgstr "E820: sizeof(uint32_t) != 4" +#~ msgid "" +#~ "Failed to set path: sys.path is not a list\n" +#~ "You should now append vim.VIM_SPECIAL_PATH to sys.path" +#~ msgstr "" +#~ "Ei onnistuttu asettaman polkua: sys.path ei ole list\n" +#~ "Lisรครค vim.VIM_SPECIAL_PATH muuttujaan sys.path" -#~ msgid "E817: Blowfish big/little endian use wrong" -#~ msgstr "E817: Blowfishin tavujไrjestys vไไrไ" +#~ msgid "" +#~ "Failed to set path hook: sys.path_hooks is not a list\n" +#~ "You should now do the following:\n" +#~ "- append vim.path_hook to sys.path_hooks\n" +#~ "- append vim.VIM_SPECIAL_PATH to sys.path\n" +#~ msgstr "" +#~ "Ei voitu asettaa polkukoukkua: sys.path_hooks ei ole lista\n" +#~ "Koeta seuraavaa:\n" +#~ "- lisรครค vim.path_hook muuttujaan sys.path_hooks\n" +#~ "- lisรครค vim.VIM_SPECIAL_PATH muuttujaan sys.path\n" -#~ msgid "E818: sha256 test failed" -#~ msgstr "E818: sha256-testi epไonnistui failed" +#~ msgid "internal error: invalid value type" +#~ msgstr "sisรคinen virhe: huono arvotyyppi" -#~ msgid "E819: Blowfish test failed" -#~ msgstr "E819: Blowfish-testi epไonnistui" +#~ msgid "internal error: NULL reference passed" +#~ msgstr "sisรคinen virhe: NULL-viite annettu" -#~ msgid "Patch file" -#~ msgstr "Patch-tiedosto" +#~ msgid "unable to convert %s to vim structure" +#~ msgstr "ei voi konvertoida oliota %s vim-tietorakenteeksi" -#~ msgid "" -#~ "&OK\n" -#~ "&Cancel" -#~ msgstr "" -#~ "&OK\n" -#~ "&Peru" +#~ msgid "unable to convert %s to vim dictionary" +#~ msgstr "ei voitu konvertoida oliota %s vim-sanakirjaksi" -#~ msgid "E240: No connection to Vim server" -#~ msgstr "E240: Ei yhteyttไ vim-palvelimeen" +#~ msgid "E859: Failed to convert returned python object to vim value" +#~ msgstr "E859: Ei voitu konvertoida python-oliota vim-arvoksi" -#~ msgid "E241: Unable to send to %s" -#~ msgstr "E241: Kohteeseen %s lไhettไminen ei onnistunut" +#~ msgid "E858: Eval did not return a valid python object" +#~ msgstr "E858: Eval ei palauttanut python-oliota" -#~ msgid "E277: Unable to read a server reply" -#~ msgstr "E277: Palvelimen vastauksen lukeminen ei onnistunut" +#~ msgid "failed to run the code" +#~ msgstr "ei voitu suorittaa koodia" -#~ msgid "E258: Unable to send to client" -#~ msgstr "E258: Asiakkaalle lไhetys ei onnistunut" +#~ msgid "did not switch to the specified tab page" +#~ msgstr "ei voitu vaihtaa annetulle vรคlilehtisivulle" -#~ msgid "Save As" -#~ msgstr "Tallenna nimellไ" +#~ msgid "expected vim.TabPage object, but got %s" +#~ msgstr "odotettiin vim.TabPage-oliota, saatiin %s" -#~ msgid "Source Vim script" -#~ msgstr "Lataa vim-skripti" +#~ msgid "did not switch to the specified window" +#~ msgstr "ei vaihdettu annettuun ikkunaan" -#~ msgid "Edit File" -#~ msgstr "Muokkaa tiedostoa" +#~ msgid "failed to find window in the current tab page" +#~ msgstr "ei voitu lรถytรครค ikkunaa nykyiselle vรคlilehtisivulle" -#~ msgid " (NOT FOUND)" -#~ msgstr " (EI LึYTYNYT)" +#~ msgid "expected vim.Window object, but got %s" +#~ msgstr "odotettiin vim.Window-oliota, saatiin %s" -#~ msgid "unknown" -#~ msgstr "tuntematon" +#~ msgid "expected vim.Buffer object, but got %s" +#~ msgstr "odotettiin vim.Buffer-oliota, ei %s" -#~ msgid "Edit File in new window" -#~ msgstr "Muokkaa uudessa ikkunassa" +#~ msgid "attempt to refer to deleted buffer" +#~ msgstr "yritettiin viitata poistettuun puskuriin" -#~ msgid "Append File" -#~ msgstr "Lisไไ tiedostoon" +#~ msgid "no such window" +#~ msgstr "ikkunaa ei ole" -#~ msgid "Window position: X %d, Y %d" -#~ msgstr "Ikkunan sijainti: X %d, Y %d" +#~ msgid "readonly attribute: buffer" +#~ msgstr "kirjoitussuojausattribuutti: puskuri" -#~ msgid "Save Redirection" -#~ msgstr "Tallenna uudelleenosoitus" +#~ msgid "attempt to refer to deleted window" +#~ msgstr "yritettiin viitata poistettuun ikkunaan" -#~ msgid "Save View" -#~ msgstr "Tallenna nไkymไ" +#~ msgid "no such tab page" +#~ msgstr "vรคlilehteรค ei ole" -#~ msgid "Save Session" -#~ msgstr "Tallenna sessio" +#~ msgid "attempt to refer to deleted tab page" +#~ msgstr "yritettiin viitata poistettuun vรคlilehteen" -#~ msgid "Save Setup" -#~ msgstr "Tallenna asetukset" +#~ msgid "internal error: unknown option type" +#~ msgstr "sisรคinen virhe: tuntematon asetustyyppi" -#~ msgid "E809: #< is not available without the +eval feature" -#~ msgstr "E809: #< ei ole kไyt๖ssไ jollei +eval ole pไไllไ" +#~ msgid "unable to get option value" +#~ msgstr "ei voitu hakea asetuksen arvoa" -#~ msgid "E196: No digraphs in this version" -#~ msgstr "E196: Digraafeja ei ole tไssไ versiossa" +#~ msgid "failed to run function %s" +#~ msgstr "ei voitu suorittaa funktiota %s" -#~ msgid "is a device (disabled with 'opendevice' option)" -#~ msgstr "on laite (ei kไyt๖ssไ opendevice-asetuksen takia)" +#~ msgid "function %s does not exist" +#~ msgstr "funktiota %s ei ole" -#~ msgid "Reading from stdin..." -#~ msgstr "Luetaan vakiosy๖tteestไ" +#~ msgid "unnamed function %s does not exist" +#~ msgstr "nimetรถntรค funktiota %s ei ole" -#~ msgid "[crypted]" -#~ msgstr "[salattu]" +#~ msgid "cannot modify fixed list" +#~ msgstr "ei voida muokata kiinitettyรค listaa" -#~ msgid "E821: File is encrypted with unknown method" -#~ msgstr "E821: Tiedoston salaus on tuntematon" +#~ msgid "cannot delete vim.List attributes" +#~ msgstr "ei voi poistaa vim.List-attribuutteja" -#~ msgid "NetBeans disallows writes of unmodified buffers" -#~ msgstr "NetBeans ei salli kirjoittaa muokkaamattomiin puskureihin" +#~ msgid "failed to add item to list" +#~ msgstr "ei voitu lisรคtรค kohtaa listaan" -#~ msgid "Partial writes disallowed for NetBeans buffers" -#~ msgstr "Osittaiset kirjoitukset kielletty NetBeans-puskureissa" +#~ msgid "attempt to assign sequence of size %d to extended slice of size %d" +#~ msgstr "" +#~ "yritettiin asettaa sekvenssiรค jonka koko on %d sliceen jonka koko on %d" -#~ msgid "writing to device disabled with 'opendevice' option" -#~ msgstr "laitteeseen kirjoittaminen pois kไyt๖stไ opendevice-asetuksella" +#~ msgid "internal error: failed to add item to list" +#~ msgstr "sisรคinen virhe: ei voitu lisรคtรค kohtaa listaan" -# tietไไkseni resurssiforkki on applen tiedostojไrjestelmไn tunnistejuttujuttu -#~ msgid "E460: The resource fork would be lost (add ! to override)" -#~ msgstr "E460: resurssiosa hไviไisi (lisไไ komentoon ! ohittaaksesi)" +#~ msgid "internal error: not enough list items" +#~ msgstr "sisรคinen virhe: ei tarpeeksi listan kohtia" -#~ msgid "<cannot open> " -#~ msgstr "<ei voi avata> " - -#~ msgid "E616: vim_SelFile: can't get font %s" -#~ msgstr "E616: vim_SelFile: ei saada fonttia %s" +#~ msgid "internal error: no vim list item %d" +#~ msgstr "sisรคinen virhe: ei vim-listan indeksiรค %d" -#~ msgid "E614: vim_SelFile: can't return to current directory" -#~ msgstr "E614: vim_SelFile: nykyiseen hakemistoon ei voi palata" +#~ msgid "attempt to assign sequence of size greater than %d to extended slice" +#~ msgstr "" +#~ "yritettiin sijoittaa sekvenssiรค jonka koko on enemmรคn kuin %d sliceen" -#~ msgid "Pathname:" -#~ msgstr "Polku:" +#~ msgid "slice step cannot be zero" +#~ msgstr "slicen askel ei voi olla nolla" -#~ msgid "E615: vim_SelFile: can't get current directory" -#~ msgstr "E615: vim_SelFile: nykyistไ hakemistoa ei saada selville" +#~ msgid "internal error: failed to get vim list item %d" +#~ msgstr "sisรคinen virhe: ei pystytty hakea vimin listan indeksiรค %d" -#~ msgid "OK" -#~ msgstr "OK" +#~ msgid "list index out of range" +#~ msgstr "listaindeksi arvoalueen ulkopuolelta" -#~ msgid "Cancel" -#~ msgstr "Peru" +#~ msgid "list constructor does not accept keyword arguments" +#~ msgstr "listakonstruktori ei tue avainsanaparametrejรค" -#~ msgid "Vim dialog" -#~ msgstr "Vim-ikkuna" +#~ msgid "expected sequence element of size 2, but got sequence of size %d" +#~ msgstr "sekvenssin elementin koon pitรคisi olla 2, ei %d" -#~ msgid "Scrollbar Widget: Could not get geometry of thumb pixmap." -#~ msgstr "Vierityspalkki: Pixmapin geometria ei selviไ" +#~ msgid "hashtab changed during iteration" +#~ msgstr "hashtab muuttui kesken iteraation" -#~ msgid "E232: Cannot create BalloonEval with both message and callback" -#~ msgstr "E232: Ei voi luoda BalloonEvalia viestille ja callbackille" +#~ msgid "cannot set attribute %s" +#~ msgstr "ei voi asettaa attribuuttia %s" -#~ msgid "E229: Cannot start the GUI" -#~ msgstr "E229: GUIn kไynnistys ei onnistu" +#~ msgid "cannot delete vim.Dictionary attributes" +#~ msgstr "ei voi poistaa vim.Dictionary-attribuutteja" -#~ msgid "E230: Cannot read from \"%s\"" -#~ msgstr "E230: Ei voi lukea kohteesta %s" +#~ msgid "internal error: imp.find_module returned tuple with NULL" +#~ msgstr "" +#~ "sisรคinen virhe: imp.find_module palautti tuplen joka sisรคltรครค nullin" -#~ msgid "E665: Cannot start GUI, no valid font found" -#~ msgstr "E665: Ei voi avata GUIta, sopivaa fonttia ei l๖ydy" +#~ msgid "" +#~ "expected 3-tuple as imp.find_module() result, but got tuple of size %d" +#~ msgstr "" +#~ "odotettiin 3-tuple tuloksnea imp.find_module()-kutsulle, mutta tuplen " +#~ "koko onkin %d" -#~ msgid "E231: 'guifontwide' invalid" -#~ msgstr "E231: guifontwide virheellinen" +#~ msgid "expected 3-tuple as imp.find_module() result, but got %s" +#~ msgstr "odotettiin 3-tuplea tuloksena imp.find_module()-kutsulle, ei %s" -#~ msgid "E599: Value of 'imactivatekey' is invalid" -#~ msgstr "E599: imactivatekeyn arvo on virheellinen" +#~ msgid "E264: Python: Error initialising I/O objects" +#~ msgstr "E264: Python: Virhe IO-olioiden alustuksessa" -#~ msgid "E254: Cannot allocate color %s" -#~ msgstr "E254: Vไriไ %s ei voi mไไritellไ" +#~ msgid "invalid attribute: %s" +#~ msgstr "virheellinen attribuutti: %s" -#~ msgid "No match at cursor, finding next" -#~ msgstr "Ei tไsmไystไ kursorin alla, etsitไไn seuraava" +#~ msgid "can't delete OutputObject attributes" +#~ msgstr "ei voi poistaa OutputObject-attribuutteja" -#~ msgid "Input _Methods" -#~ msgstr "Sy๖te_menetelmไt" +#~ msgid "number must be greater or equal to zero" +#~ msgstr "luvun on oltava yhtรค suuri tai suurempi kuin nolla" -#~ msgid "VIM - Search and Replace..." -#~ msgstr "VIM - Etsi ja korvaa..." +#~ msgid "value is too small to fit into C int type" +#~ msgstr "arvo on liian pieni mahtumaan C:n int-tyyppiin" -#~ msgid "VIM - Search..." -#~ msgstr "VIM - Etsi..." +#~ msgid "expected int() or something supporting coercing to int(), but got %s" +#~ msgstr "" +#~ "odotettiin tyyppiรค int() tai jotain joka muuntuu tyyppiin int(), ei %s" -#~ msgid "Find what:" -#~ msgstr "Etsi:" +#~ msgid "" +#~ "expected int(), long() or something supporting coercing to long(), but " +#~ "got %s" +#~ msgstr "" +#~ "odotettiin instanssia tyypeistรค int(), long() tai mitรค tahansa joka " +#~ "muuntuisi tyyppiin long(), ei %s" -#~ msgid "Replace with:" -#~ msgstr "Korvaa:" +#~ msgid "expected bytes() or str() instance, but got %s" +#~ msgstr "odotettiin instanssia tyypeistรค bytes() tai str(), ei %s" -#~ msgid "Match whole word only" -#~ msgstr "Korvaa kokonaisia sanoja" +#~ msgid "expected str() or unicode() instance, but got %s" +#~ msgstr "odottettiin insanssia tyypeistรค str() tai unicode(), ei %s" -#~ msgid "Match case" -#~ msgstr "Kirjaintaso" +#~ msgid "index must be int or slice, not %s" +#~ msgstr "indeksin pitรครค olla int tai slice, ei %s" -#~ msgid "Direction" -#~ msgstr "Suunta" +#~ msgid "failed to add key '%s' to dictionary" +#~ msgstr "avaimen %s lisรครคminen sanakirjaan ei onnistu" -#~ msgid "Up" -#~ msgstr "Yl๖s" +#~ msgid "list is locked" +#~ msgstr "luettelo on lukittu" -#~ msgid "Down" -#~ msgstr "Alas" +#~ msgid "Need encryption key for \"%s\"" +#~ msgstr "Tarvitaan salausavain kohteelle %s " -#~ msgid "Find Next" -#~ msgstr "Etsi seuraava" +#~ msgid "E744: NetBeans does not allow changes in read-only files" +#~ msgstr "E744: NetBeans ei tue muutoksia kirjoitussuojattuihin tiedostoihin" -#~ msgid "Replace" -#~ msgstr "Korvaa" +#~ msgid "E463: Region is guarded, cannot modify" +#~ msgstr "E463: Alue on suojattu, muuttaminen ei onnistu" -#~ msgid "Replace All" -#~ msgstr "Korvaa kaikki" +#~ msgid "E449: Invalid expression received" +#~ msgstr "E449: Virheellinen ilmaus saatu" -#~ msgid "Vim: Received \"die\" request from session manager\n" -#~ msgstr "Vim: sessiomanageri lไhetti die-pyynn๖n\n" +#~ msgid "E233: cannot open display" +#~ msgstr "E233: nรคyttรถรค ei voi avata" -#~ msgid "Close" -#~ msgstr "Sulje" +#~ msgid "E247: no registered server named \"%s\"" +#~ msgstr "E247: palvelinta %s ei ole rekisterรถitynรค" -#~ msgid "New tab" -#~ msgstr "Uusi vไlilehti" +#~ msgid "E800: Arabic cannot be used: Not enabled at compile time\n" +#~ msgstr "E800: Arabiaa ei voi kรคyttรครค, koska sitรค ei kรครคnnetty mukaan\n" -#~ msgid "Open Tab..." -#~ msgstr "Avaa vไlilehti..." +#~ msgid "E27: Farsi cannot be used: Not enabled at compile time\n" +#~ msgstr "E27: Farsia ei voi kรคyttรครค, koska sitรค ei kรครคnnetty mukaan\n" -#~ msgid "Vim: Main window unexpectedly destroyed\n" -#~ msgstr "Vim: Pไไikkuna tuhoutui odottamatta\n" +#~ msgid "E26: Hebrew cannot be used: Not enabled at compile time\n" +#~ msgstr "E26: Hepreaa ei voi kรคyttรครค, koska sitรค ei kรครคnnetty mukaan\n" -#~ msgid "&Filter" -#~ msgstr "&Suodata" +#~ msgid "E25: GUI cannot be used: Not enabled at compile time" +#~ msgstr "E25: GUIta ei voi kรคyttรครค, koska sitรค ei kรครคnnetty mukaan" -#~ msgid "&Cancel" -#~ msgstr "&Peru" +#~ msgid "E448: Could not load library function %s" +#~ msgstr "E448: Ei voitu ladta kirjastofunktiota %s" -#~ msgid "Directories" -#~ msgstr "Hakemistot" +#~ msgid "E236: Font \"%s\" is not fixed-width" +#~ msgstr "E236: Fontti %s ei ole tasavรคlinen" -#~ msgid "Filter" -#~ msgstr "Suodatus" +#~ msgid "E234: Unknown fontset: %s" +#~ msgstr "E234: Tuntematon fontset: %s" -#~ msgid "&Help" -#~ msgstr "O&hje" +#~ msgid "gvimext.dll error" +#~ msgstr "gvimext.dll-virhe" -#~ msgid "Files" -#~ msgstr "Tiedostot" +#~ msgid "Error creating process: Check if gvim is in your path!" +#~ msgstr "Virhe prosessin kรคynnistรคmisessรค, varmista ettรค gvim on polulla" -#~ msgid "&OK" -#~ msgstr "&Ok" +#~ msgid "Edits the selected file(s) with Vim" +#~ msgstr "Muokkaa valittuja tiedostoja Vimillรค" -#~ msgid "Selection" -#~ msgstr "Valinta" +#~ msgid "Edit with existing Vim - " +#~ msgstr "Muokkaa olemassaolevalla Vimillรค - " -#~ msgid "Find &Next" -#~ msgstr "Hae &seuraava" +#~ msgid "Edit with &Vim" +#~ msgstr "Muokkaa &Vimillรค" -#~ msgid "&Replace" -#~ msgstr "Ko&rvaa" +#~ msgid "Diff with Vim" +#~ msgstr "Diffi Vimillรค" -#~ msgid "Replace &All" -#~ msgstr "Korvaa k&aikki" +#~ msgid "Edit with single &Vim" +#~ msgstr "Muokkaa yhdellรค &Vimillรค" -#~ msgid "&Undo" -#~ msgstr "&Kumoa" +#~ msgid "Edit with &multiple Vims" +#~ msgstr "&Muokkaa usealla Vimillรค" -#~ msgid "E671: Cannot find window title \"%s\"" -#~ msgstr "E671: Ikkunan otsikkoa ei l๖ydy %s" +#~ msgid "E299: Perl evaluation forbidden in sandbox without the Safe module" +#~ msgstr "E299: Perl-suoritus kielletty hiekkalaatikossa ilman Safe-moduulia" -# OLE on object linking and embedding pๅ windowska -#~ msgid "E243: Argument not supported: \"-%s\"; Use the OLE version." -#~ msgstr "E243: Argumenttia ei tueta: -%s, kไytไ OLE-versiota" +#~ msgid "" +#~ "Sorry, this command is disabled: the Perl library could not be loaded." +#~ msgstr "komento ei toimi, Perl kirjastoa ei voinut ladata." -# MDI eli windowsin moni-ikkunasovellus -#~ msgid "E672: Unable to open window inside MDI application" -#~ msgstr "E672: Ikkunaa ei voitu avata MDI-sovellukseen" +#~ msgid "E370: Could not load library %s" +#~ msgstr "E370: Kirjaston %s lataaminen ei onnistu" -#~ msgid "Close tab" -#~ msgstr "Sulje vไlilehti" +#~ msgid "type :help windows95<Enter> for info on this" +#~ msgstr "kirjoita :help windows95<Enter> lisรคtietoja varten" -#~ msgid "Open tab..." -#~ msgstr "Avaa vไlilehti..." +#~ msgid "WARNING: Windows 95/98/ME detected" +#~ msgstr "VAROITUS: Window 95/98/ME havaittu" -#~ msgid "Find string (use '\\\\' to find a '\\')" -#~ msgstr "Etsi merkkijonoa (\\\\:llไ l๖ytไไ \\:t)" +#~ msgid " for Vim defaults " +#~ msgstr " Vim-oletuksia varten" -#~ msgid "Find & Replace (use '\\\\' to find a '\\')" -#~ msgstr "Etsi ja korvaa (\\\\:llไ l๖ytไไ \\:t)" +#~ msgid "menu Edit->Global Settings->Toggle Vi Compatible" +#~ msgstr "valikko Muokkaa->Yleiset asetukset->Vaihda Vi-yhteensopivuutta" -#~ msgid "Not Used" -#~ msgstr "Ei kไyt๖ssไ" +#~ msgid "menu Edit->Global Settings->Toggle Insert Mode " +#~ msgstr "valikko Muokkaa->Yleiset asetukset->Vaihda syรถtetilaa" -#~ msgid "Directory\t*.nothing\n" -#~ msgstr "Hakemisto\t*.nothing\n" +#~ msgid "Running modeless, typed text is inserted" +#~ msgstr "Suoritetaan tilattomana, kirjoitettu teksti syรถtetรครคn" -#~ msgid "" -#~ "Vim E458: Cannot allocate colormap entry, some colors may be incorrect" -#~ msgstr "" -#~ "Vim E458: Ei voi varata vไrikartan alkiota, vไrit voivat mennไ vไไrin" +#~ msgid "menu Help->Orphans for information " +#~ msgstr "valikko Ohje->Orvot lisรคtietoja varten " -#~ msgid "E250: Fonts for the following charsets are missing in fontset %s:" -#~ msgstr "E250: Seuraavien merkist๖joukkojen fontit puuttuvat fontsetistไ %s:" +#~ msgid "type :help cp-default<Enter> for info on this" +#~ msgstr "kirjoita :help cp-default<Enter> ohjetta oletuksista varten" -#~ msgid "E252: Fontset name: %s" -#~ msgstr "E252: Fontsetin nimi: %s" +#~ msgid "type :set nocp<Enter> for Vim defaults" +#~ msgstr "kirjoita :set nocp<Enter> Vimin oletuksiin " -#~ msgid "Font '%s' is not fixed-width" -#~ msgstr "Fontti %s ei ole tasavไlinen" +#~ msgid "Running in Vi compatible mode" +#~ msgstr "Suoritetaan Vi-yhteensopivuustilaa" -#~ msgid "E253: Fontset name: %s\n" -#~ msgstr "E253: Fontsetin nimi: %s\n" +#~ msgid "type :help version8<Enter> for version info" +#~ msgstr "kirjoita :help version8<Enter> versiotietoja varten " -#~ msgid "Font0: %s\n" -#~ msgstr "Fontti0: %s\n" +#~ msgid "type :help<Enter> or <F1> for on-line help" +#~ msgstr "kirjoita :help<Enter> tai <F1> ohjetta varten " -#~ msgid "Font1: %s\n" -#~ msgstr "Fontti1: %s\n" +#~ msgid "version " +#~ msgstr "versio " -#~ msgid "Font%<PRId64> width is not twice that of font0\n" -#~ msgstr "Fontti%<PRId64>:n leveys ei ole kaksi kertaa fontti0:n\n" +#~ msgid "VIM - Vi IMproved" +#~ msgstr "VIM - Vi IMproved" -#~ msgid "Font0 width: %<PRId64>\n" -#~ msgstr "Fontti0:n leveys: %<PRId64>\n" +#~ msgid " DEBUG BUILD" +#~ msgstr " DEBUG-versio" -#~ msgid "" -#~ "Font1 width: %<PRId64>\n" -#~ "\n" -#~ msgstr "" -#~ "Fontti1:n leveys: %<PRId64>\n" -#~ "\n" +#~ msgid "Linking: " +#~ msgstr "Linkitys: " -#~ msgid "Invalid font specification" -#~ msgstr "Virheellinen fonttimไไritys" +#~ msgid "Compiler: " +#~ msgstr "Kรครคnnin: " -#~ msgid "&Dismiss" -#~ msgstr "&Ohita" +#~ msgid "Compilation: " +#~ msgstr "Kรครคnnรถs: " -#~ msgid "no specific match" -#~ msgstr "ei tarkkaa tไsmไystไ" +#~ msgid " system menu file: \"" +#~ msgstr " jรคrjestelmรคvalikko: \"" -#~ msgid "Vim - Font Selector" -#~ msgstr "Vim - fonttivalitsin" +#~ msgid " defaults file: \"" +#~ msgstr " defaults-tiedosto: \"" -#~ msgid "Name:" -#~ msgstr "Nimi:" +#~ msgid "3rd user gvimrc file: \"" +#~ msgstr "3. kรคyttรคjรคn gvimrc: \"" -#~ msgid "Show size in Points" -#~ msgstr "Nไytไ koko pisteinไ" +#~ msgid "2nd user gvimrc file: \"" +#~ msgstr "2. kรคyttรคjรคn gvimrc: \"" -#~ msgid "Encoding:" -#~ msgstr "Koodaus:" +#~ msgid " user gvimrc file: \"" +#~ msgstr " kรคyttรคjรคn gvimrc: \"" -#~ msgid "Font:" -#~ msgstr "Fontti:" +#~ msgid " system gvimrc file: \"" +#~ msgstr " jรคrjestelmรคn gvimrc: \"" -#~ msgid "Style:" -#~ msgstr "Tyyli:" +#~ msgid " 2nd user exrc file: \"" +#~ msgstr " 2. kรคyttรคjรคn exrc: \"" -#~ msgid "Size:" -#~ msgstr "Koko:" +#~ msgid " user exrc file: \"" +#~ msgstr " kรคyttรคjรคn exrc: \"" -#~ msgid "E256: Hangul automata ERROR" -#~ msgstr "E256: Hangu-automaattivirhe" +#~ msgid " 3rd user vimrc file: \"" +#~ msgstr " 3. kรคyttรคjรคn vimrc: \"" -#~ msgid "E563: stat error" -#~ msgstr "E563: stat-virhe" +#~ msgid " 2nd user vimrc file: \"" +#~ msgstr " 2. kรคyttรคjรคn vimrc: \"" -#~ msgid "E625: cannot open cscope database: %s" -#~ msgstr "E625: ei voi avata cscope-tietokantaa: %s" +#~ msgid " user vimrc file: \"" +#~ msgstr " kรคyttรคjรคn vimrc: \"" -#~ msgid "E626: cannot get cscope database information" -#~ msgstr "E626: ei voi hakea cscope-tietokannan tietoja" +#~ msgid "with (classic) GUI." +#~ msgstr "perinteisellรค GUIlla." -#~ msgid "Lua library cannot be loaded." -#~ msgstr "Luan kirjastoa ei voitu ladata." +#~ msgid "with Cocoa GUI." +#~ msgstr "Cocoa-GUIlla." -#~ msgid "cannot save undo information" -#~ msgstr "ei voitu tallentaa kumoustietoja" +#~ msgid "with Carbon GUI." +#~ msgstr "Carbon-GUIlla." -#~ msgid "" -#~ "E815: Sorry, this command is disabled, the MzScheme libraries could not " -#~ "be loaded." -#~ msgstr "E815: Sori, komento ei toimi, MzScheme-kirjastoa ei voitu ladata." +#~ msgid "with GUI." +#~ msgstr "GUIlla." -#~ msgid "invalid expression" -#~ msgstr "virheellinen ilmaus" +#~ msgid "with Photon GUI." +#~ msgstr "Photon-GUIlla." -#~ msgid "expressions disabled at compile time" -#~ msgstr "ilmaukset poistettu kไyt๖stไ kไไnn๖saikana" +#~ msgid "with X11-Athena GUI." +#~ msgstr "X11-Athena-GUIlla." -#~ msgid "hidden option" -#~ msgstr "piilotettu asetus" +#~ msgid "with X11-neXtaw GUI." +#~ msgstr "X11-neXtaw-GUIlla." -#~ msgid "unknown option" -#~ msgstr "tuntematon asetus" +#~ msgid "with X11-Motif GUI." +#~ msgstr "X11-Motif-GUIlla." -#~ msgid "window index is out of range" -#~ msgstr "ikkunan indeksi alueen ulkopuolella" +#~ msgid "with GTK2 GUI." +#~ msgstr "GTK2-GUIlla." -#~ msgid "couldn't open buffer" -#~ msgstr "ei voitu avata puskuria" +#~ msgid "with GTK2-GNOME GUI." +#~ msgstr "GTK2-Gnome-GUIlla." -#~ msgid "cannot delete line" -#~ msgstr "ei voitu poistaa riviไ" +#~ msgid "with GTK3 GUI." +#~ msgstr "GTK3-GUIlla." -#~ msgid "cannot replace line" -#~ msgstr "ei voitu korvata riviไ" +#~ msgid "without GUI." +#~ msgstr "ilman GUIta." -#~ msgid "cannot insert line" -#~ msgstr "ei voitu lisไtไ riviไ" +#~ msgid "" +#~ "\n" +#~ "Tiny version " +#~ msgstr "" +#~ "\n" +#~ "Tiny-versio " -#~ msgid "string cannot contain newlines" -#~ msgstr "merkkijono ei saa sisไltไไ rivinvaihtoja" +#~ msgid "" +#~ "\n" +#~ "Small version " +#~ msgstr "" +#~ "\n" +#~ "Small-versio " -#~ msgid "Vim error: ~a" -#~ msgstr "Vim-virhe: ~a" +#~ msgid "" +#~ "\n" +#~ "Normal version " +#~ msgstr "" +#~ "\n" +#~ "Normal-versio " -#~ msgid "Vim error" -#~ msgstr "Vim-virhe" +#~ msgid "" +#~ "\n" +#~ "Big version " +#~ msgstr "" +#~ "\n" +#~ "Big-version " -#~ msgid "buffer is invalid" -#~ msgstr "puskuri on virheellinen" +#~ msgid "" +#~ "\n" +#~ "Huge version " +#~ msgstr "" +#~ "\n" +#~ "Huge-versio " -#~ msgid "window is invalid" -#~ msgstr "ikkuna on virheellinen" +#~ msgid "Modified by " +#~ msgstr "Muokannut " -#~ msgid "linenr out of range" -#~ msgstr "rivinumero arvoalueen ulkopuolelta" +#~ msgid "" +#~ "\n" +#~ "Included patches: " +#~ msgstr "" +#~ "\n" +#~ "Pรคtsit: " -#~ msgid "not allowed in the Vim sandbox" -#~ msgstr "ei sallittu Vimin hiekkalaatikossa" +#~ msgid "" +#~ "\n" +#~ "OpenVMS version" +#~ msgstr "" +#~ "\n" +#~ "OpenVMS-version" -#~ msgid "E836: This Vim cannot execute :python after using :py3" +#~ msgid "" +#~ "\n" +#~ "MacOS version" #~ msgstr "" -#~ "E836: Python: Ei voi kไyttไไ komentoja :py ja :py3 samassa istunnossa" +#~ "\n" +#~ "MacOS-version" -#~ msgid "E837: This Vim cannot execute :py3 after using :python" +#~ msgid "" +#~ "\n" +#~ "MacOS X version" #~ msgstr "" -#~ "E837: Python: Ei voi kไyttไไ komentoja :py ja :py3 samassa istunnossa" +#~ "\n" +#~ "MacOS X-version" #~ msgid "" -#~ "E263: Sorry, this command is disabled, the Python library could not be " -#~ "loaded." +#~ "\n" +#~ "MacOS X (unix) version" #~ msgstr "" -#~ "E263: Sori, komento ei toimi, Python-kirjaston lataaminen ei onnistunut." +#~ "\n" +#~ "MacOS X-version (unix)" -#~ msgid "can't delete OutputObject attributes" -#~ msgstr "ei voi poistaa OutputObject-attribuutteja" +#~ msgid "" +#~ "\n" +#~ "MS-Windows 32-bit console version" +#~ msgstr "" +#~ "\n" +#~ "MS-Windows 32-bittinen konsoliversio" -#~ msgid "softspace must be an integer" -#~ msgstr "softspacen pitไไ olla kokonaisluku" +#~ msgid "" +#~ "\n" +#~ "MS-Windows 64-bit console version" +#~ msgstr "" +#~ "\n" +#~ "MS-Windows 32-bittinen konsoliversio" -#~ msgid "invalid attribute" -#~ msgstr "virheellinen attribuutti" +#~ msgid " with OLE support" +#~ msgstr " OLE-tuella" -#~ msgid "<buffer object (deleted) at %p>" -#~ msgstr "<puskuriolio (poistettu) kohdassa %p>" +#~ msgid " in Win32s mode" +#~ msgstr " Win32s-tilassa" -#~ msgid "E659: Cannot invoke Python recursively" -#~ msgstr "E659: Pythonia ei voi kutsua rekursiivisesti" +#~ msgid "" +#~ "\n" +#~ "MS-Windows 32-bit GUI version" +#~ msgstr "" +#~ "\n" +#~ "MS-Windows 32-bittinen GUI-version" -#~ msgid "E265: $_ must be an instance of String" -#~ msgstr "E265: muuttujan $_ pitไไ olla Stringin instanssi" +#~ msgid "" +#~ "\n" +#~ "MS-Windows 64-bit GUI version" +#~ msgstr "" +#~ "\n" +#~ "MS-Windows 64-bittinen GUI-versio" #~ msgid "" -#~ "E266: Sorry, this command is disabled, the Ruby library could not be " -#~ "loaded." -#~ msgstr "E266: Sori, komento ei toimi, Ruby-kirjastoa ei voitu ladata." +#~ "\n" +#~ "MS-Windows 16/32-bit GUI version" +#~ msgstr "" +#~ "\n" +#~ "MS-Windows 16- t. 32-bittinen GUI-versio" -#~ msgid "E267: unexpected return" -#~ msgstr "E267: odotuksenvastainen return" +#~ msgid "E827: Undo file is encrypted: %s" +#~ msgstr "E827: Kumoustiedosto on salattu: %s" -#~ msgid "E268: unexpected next" -#~ msgstr "E268: Odotuksenvastainen next" +#~ msgid "E826: Undo file decryption failed: %s" +#~ msgstr "E826: Kumoustiedoston purku epรคonnistui: %s" -#~ msgid "E269: unexpected break" -#~ msgstr "E269: Odotuksenvastainen break" +#~ msgid "E832: Non-encrypted file has encrypted undo file: %s" +#~ msgstr "E832: Salaamattomalla tiedostolla on salattu kumoustiedosto: %s" -#~ msgid "E270: unexpected redo" -#~ msgstr "E270: odotuksenvastainen redo" +#~ msgid "No undo possible; continue anyway" +#~ msgstr "Ei voi kumota, jatketaan silti" -#~ msgid "E271: retry outside of rescue clause" -#~ msgstr "E271: retry rescuen ulkopuolella" +#~ msgid "Used CUT_BUFFER0 instead of empty selection" +#~ msgstr "Kรคytettiin CUT_BUFFER0:aa tyhjรคn valinnan sijaan" -#~ msgid "E272: unhandled exception" -#~ msgstr "E272: kไsittelemไt๖n poikkeus" +#~ msgid "new shell started\n" +#~ msgstr "uusi kuori avattu\n" -#~ msgid "E273: unknown longjmp status %d" -#~ msgstr "E273: tuntematon longjmp-tila %d" +#~ msgid "Cannot open $VIMRUNTIME/rgb.txt" +#~ msgstr "Ei voida avata tiedostoa $VIMRUNTIME/rgb.txt" -#~ msgid "Toggle implementation/definition" -#~ msgstr "Vaihda toteutuksen ja mไไritelmไn vไlillไ" +#~ msgid "" +#~ "\n" +#~ "--- Terminal keys ---" +#~ msgstr "" +#~ "\n" +#~ "--- Terminaalinรคppรคimet ---" -#~ msgid "Show base class of" -#~ msgstr "Nไytไ kantaluokka kohteelle" +#~ msgid "E437: terminal capability \"cm\" required" +#~ msgstr "E437: terminaalilla pitรครค olla cm kyvyissรครคn" -#~ msgid "Show overridden member function" -#~ msgstr "Nไytไ korvattu jไsenfunktio" +#~ msgid "E436: No \"%s\" entry in termcap" +#~ msgstr "E436: %s ei lรถytynyt termcapista" -#~ msgid "Retrieve from file" -#~ msgstr "Jไljitไ tiedostosta" +#~ msgid "E559: Terminal entry not found in termcap" +#~ msgstr "E559: Terminaalia ei lรถytynyt termcapista" -#~ msgid "Retrieve from project" -#~ msgstr "Jไljitไ projektista" +#~ msgid "E558: Terminal entry not found in terminfo" +#~ msgstr "E558: Terminaalia ei lรถytynyt terminfosta" -#~ msgid "Retrieve from all projects" -#~ msgstr "Jไljitไ kaikista projekteista" +#~ msgid "E557: Cannot open termcap file" +#~ msgstr "E557: Ei voi avata termcap-tiedostoa" -#~ msgid "Retrieve" -#~ msgstr "Jไljitไ" +#~ msgid "defaulting to '" +#~ msgstr "oletusarvona " -#~ msgid "Show source of" -#~ msgstr "Nไytไ lไhdekoodi kohteelle" +#~ msgid "' not known. Available builtin terminals are:" +#~ msgstr " ei tunnettu. Tuetut terminaalit:" -#~ msgid "Find symbol" -#~ msgstr "Etsi symboli" +#~ msgid "E430: Tag file path truncated for %s\n" +#~ msgstr "E430: Tรคgitiedoston polku katkaistu kohdassa %s\n" -#~ msgid "Browse class" -#~ msgstr "Selaa luokkaa" +#~ msgid "E422: terminal code too long: %s" +#~ msgstr "E422: terminaalikoodi liian pitkรค: %s" -#~ msgid "Show class in hierarchy" -#~ msgstr "Nไytไ luokka hierarkiassa" +#~ msgid "E845: Insufficient memory, word list will be incomplete" +#~ msgstr "E845: Muisti ei riitรค, sanalista jรครค keskenerรคiseksi" + +#~ msgid "Conversion in %s not supported" +#~ msgstr "Muutosta kohteessa %s ei tueta" -#~ msgid "Show class in restricted hierarchy" -#~ msgstr "Nไytไ luokka rajoitetussa hierarkiassa" +#~ msgid "Warning: Cannot find word list \"%s_%s.spl\" or \"%s_ascii.spl\"" +#~ msgstr "Varoitus: Ei lรถydetty sanalistaa %s_%s.spl tai %s_ascii.spl" -#~ msgid "Xref refers to" -#~ msgstr "Xref viittaa kohteeseen" +#~ msgid "" +#~ "\n" +#~ "# Last %sSearch Pattern:\n" +#~ "~" +#~ msgstr "" +#~ "\n" +#~ "# Edellinen %sHakulauseke:\n" +#~ "~" -#~ msgid "Xref referred by" -#~ msgstr "Xref viitattu kohteesta" +#~ msgid "Substitute " +#~ msgstr "Korvaa " -#~ msgid "Xref has a" -#~ msgstr "Xref sisไltไไ kohteen" +#~ msgid "(NFA) COULD NOT OPEN %s !" +#~ msgstr "(NFA) EI VOI AVATA KOHDETTA %s" -#~ msgid "Xref used by" -#~ msgstr "Xrefiไ kไyttไไ" +#~ msgid "" +#~ "Could not open temporary log file for writing, displaying on stderr ... " +#~ msgstr "" +#~ "Ei voitu avata vรคliaikaislokitiedosta kirjoittamista varten, joten " +#~ "virheet nรคytetรครคn vakiovirhevirrassa. " -#~ msgid "Show docu of" -#~ msgstr "Nไytไ dokumentti kohteelle" +#~ msgid "E878: (NFA) Could not allocate memory for branch traversal!" +#~ msgstr "E878: (NFA) Ei voitu allokoida muistia polkujen lรคpikรคyntiin" -#~ msgid "Generate docu for" -#~ msgstr "Luo dokumentti kohteelle" +#~ msgid "E876: (NFA regexp) Not enough space to store the whole NFA " +#~ msgstr "E876: (NFA regexp) Tila ei riitรค NFA:n tallentamiseen" #~ msgid "" -#~ "Cannot connect to SNiFF+. Check environment (sniffemacs must be found in " -#~ "$PATH).\n" +#~ "E875: (NFA regexp) (While converting from postfix to NFA), too many " +#~ "states left on stack" #~ msgstr "" -#~ "Ei voida yhdistไไ SNiFF+:aan. Tarkista ympไrist๖muuttujat (sniffemacsin " -#~ "l๖ytyไ polkumuuttujasta $PATH).\n" +#~ "E875: (NFA regexp) (Muunnettaessa postfixistรค NFA:ksi), liikaa tiloja " +#~ "jรคljellรค pinossa" -#~ msgid "E274: Sniff: Error during read. Disconnected" -#~ msgstr "E274: Sniff: Virhe luettaessa, yhteys katkaistu" +#~ msgid "E874: (NFA) Could not pop the stack !" +#~ msgstr "E874: (NFA) Ei voida poistaa pinosta" -#~ msgid "SNiFF+ is currently " -#~ msgstr "SNiFF+ " +#~ msgid "E873: (NFA regexp) proper termination error" +#~ msgstr "E873: (NFA regexp) oikea lopetusvirhe" -#~ msgid "not " -#~ msgstr "ei ole " +#~ msgid "E879: (NFA regexp) Too many \\z(" +#~ msgstr "E879: (NFA regexp) Liikaa merkkejรค \\z(" -#~ msgid "connected" -#~ msgstr "yhdistetty" +#~ msgid "E872: (NFA regexp) Too many '('" +#~ msgstr "E872: (NFA regexp) Liian monta suljetta '('" -#~ msgid "E275: Unknown SNiFF+ request: %s" -#~ msgstr "E275: Tuntematon SNiFF+-pyynt๖: %s" +#~ msgid "E871: (NFA regexp) Can't have a multi follow a multi !" +#~ msgstr "E871: (NFA regexp) Multi ei voi seurata multia" -#~ msgid "E276: Error connecting to SNiFF+" -#~ msgstr "E276: Virhe yhdistettไessไ SNiFF+:aan" +#~ msgid "E870: (NFA regexp) Error reading repetition limits" +#~ msgstr "E870: (NFA regexp) Virhe luettaessa toiston mรครคriรค" -#~ msgid "E278: SNiFF+ not connected" -#~ msgstr "E278: SNiFF+ ei ole yhdistetty" +#~ msgid "E869: (NFA) Unknown operator '\\@%c'" +#~ msgstr "E869: (NFA) Tuntematon operaattori '\\@%c'" -#~ msgid "E279: Not a SNiFF+ buffer" -#~ msgstr "E279: Ei ole SNiFF+-puskuri" +#~ msgid "E868: Error building NFA with equivalence class!" +#~ msgstr "E868: Virhe NFA:n ekvivalenssiluokkia tekemisessรค" -#~ msgid "Sniff: Error during write. Disconnected" -#~ msgstr "Sniff: Virhe kirjoituksessa, yhteys katkaistu" +#~ msgid "E867: (NFA) Unknown operator '\\%%%c'" +#~ msgstr "E867: (NFA) Tuntematon operaattori '\\%%%c'" -#~ msgid "invalid buffer number" -#~ msgstr "virheellinen puskurinumero" +#~ msgid "E867: (NFA) Unknown operator '\\z%c'" +#~ msgstr "E867: (NFA) Tuntematon operaattori '\\z%c'" -#~ msgid "not implemented yet" -#~ msgstr "ei toteutettu" +#~ msgid "E877: (NFA regexp) Invalid character class: %ld" +#~ msgstr "E877: (NFA regexp) Virheellinen merkkiluokka: %ld" -#~ msgid "cannot set line(s)" -#~ msgstr "ei voi asettaa rivejไ" +#~ msgid "E866: (NFA regexp) Misplaced %c" +#~ msgstr "E866: (NFA-regexp) %c vรครคrรคssรค paikassa" -#~ msgid "invalid mark name" -#~ msgstr "virheellinen merkin nimi" +#~ msgid "E865: (NFA) Regexp end encountered prematurely" +#~ msgstr "E865: (NFA) Sรครคnnรถllisen ilmauksen ennenaikainen loppu" -#~ msgid "mark not set" -#~ msgstr "merkko ei ole asetettu" +#~ msgid "Error file" +#~ msgstr "Virhetiedosto" -#~ msgid "row %d column %d" -#~ msgstr "rivi %d sarake %d" +#~ msgid "shell returned %d" +#~ msgstr "kuori palautti arvon %d" -#~ msgid "cannot insert/append line" -#~ msgstr "rivin lisไys ei onnistu" +#~ msgid "Vim Warning" +#~ msgstr "Vim-varoitus" -#~ msgid "line number out of range" -#~ msgstr "rivinumero arvoalueen ulkopuolella" +#~ msgid "" +#~ "VIMRUN.EXE not found in your $PATH.\n" +#~ "External commands will not pause after completion.\n" +#~ "See :help win32-vimrun for more information." +#~ msgstr "" +#~ "VIMRUN.EXEรค ei lรถydy muuttujasta $PATH.\n" +#~ "Ulkoiset komennot eivรคt pysรคhdy suorituksen lopussa.\n" +#~ "Lisรคtietoja komennolla :help win32-vimrun" -#~ msgid "unknown flag: " -#~ msgstr "tuntematon asetus: " +#~ msgid "E371: Command not found" +#~ msgstr "E371: Komentoa ei lรถydy" -#~ msgid "unknown vimOption" -#~ msgstr "tuntematon vimOption" +#~ msgid "shutdown" +#~ msgstr "sammutus" -#~ msgid "keyboard interrupt" -#~ msgstr "nไppไimist๖keskeytys" +#~ msgid "logoff" +#~ msgstr "uloskirjautuminen" -#~ msgid "vim error" -#~ msgstr "vim-virhe" +#~ msgid "close" +#~ msgstr "sulkeminen" -#~ msgid "cannot create buffer/window command: object is being deleted" -#~ msgstr "ei voi luoda puskuri- tai ikkunakomentoa, olio on poistumassa" +#~ msgid "Vim: Caught %s event\n" +#~ msgstr "Vim: Napattiin %s\n" + +#~ msgid "Could not fix up function pointers to the DLL!" +#~ msgstr "Ei voitu korjata funktio-osoittimia DLL:ssรค" + +#~ msgid "VIM Error" +#~ msgstr "VIM-virhe" + +#~ msgid "Could not load vim32.dll!" +#~ msgstr "Vim32.dll:รครค ei voitu ladata" + +#~ msgid "At line" +#~ msgstr "Rivillรค" + +#~ msgid "XSMP SmcOpenConnection failed: %s" +#~ msgstr "XSMP SmcOpenConnection epรคonnistui: %s" + +#~ msgid "XSMP ICE connection watch failed" +#~ msgstr "XSMP:n ICE-yhteyden tarkkailu epรคonnistui" + +#~ msgid "XSMP opening connection" +#~ msgstr "XSMP avaa yhteyttรค" + +#~ msgid "XSMP handling save-yourself request" +#~ msgstr "XSMP kรคsittelee save-yourself-pyyntรถรค" + +#~ msgid "Opening the X display failed" +#~ msgstr "X-nรคytรถn avaus epรคonnistui" + +#~ msgid "XSMP lost ICE connection" +#~ msgstr "XSMP kadotti ICE-yhteyden" #~ msgid "" -#~ "cannot register callback command: buffer/window is already being deleted" -#~ msgstr "callbackia ei voi rekister๖idไ: puskuri tai ikkuna on poistettu" +#~ "\n" +#~ "Command terminated\n" +#~ msgstr "" +#~ "\n" +#~ "Komento loppui\n" #~ msgid "" -#~ "E280: TCL FATAL ERROR: reflist corrupt!? Please report this to vim-" -#~ "dev@vim.org" +#~ "\n" +#~ "Cannot execute shell " #~ msgstr "" -#~ "E280: kriittinen TCL-virhe: reflist hajalla? Ilmoita asiasta " -#~ "postituslistalle vim-dev@vim.org" +#~ "\n" +#~ "Kuoren suoritus ei onnistu " -#~ msgid "cannot register callback command: buffer/window reference not found" +#~ msgid "" +#~ "\n" +#~ "Cannot fork\n" #~ msgstr "" -#~ "callbackia ei voi rekister๖idไ: puskurin tai ikkunan viitettไ ei l๖ydy" +#~ "\n" +#~ "Ei voi haarauttaa\n" #~ msgid "" -#~ "E571: Sorry, this command is disabled: the Tcl library could not be " -#~ "loaded." -#~ msgstr "E571: Sori, komento ei toimi, Tcl-kirjastoa ei voitu ladata." +#~ "\n" +#~ "Cannot create pipes\n" +#~ msgstr "" +#~ "\n" +#~ "Putkia ei voi tehdรค\n" #~ msgid "" -#~ "E281: TCL ERROR: exit code is not int!? Please report this to vim-dev@vim." -#~ "org" +#~ "\n" +#~ "Cannot execute shell sh\n" #~ msgstr "" -#~ "E281: TCL-virhe: lopetuskoodi ei ole kokonaisluku? Ilmoita asiasta " -#~ "postituslistalle vim-dev@vim.org" +#~ "\n" +#~ "Kuoren sh suoritus ei onnistu\n" -#~ msgid "E572: exit code %d" -#~ msgstr "E572: palautusarvo %d" +# mikรค security context? +#~ msgid "Could not get security context %s for %s. Removing it!" +#~ msgstr "Ei saatu turvallisuuskontekstia %s kohteelle %s ja se poistetaan" -#~ msgid "cannot get line" -#~ msgstr "ei voida hakea riviไ" +#~ msgid "Could not set security context %s for %s" +#~ msgstr "Ei voitu asettaa turvallisuuskontekstia %s kohteelle %s" -#~ msgid "Unable to register a command server name" -#~ msgstr "Komentopalvelimen nimen rekister๖inti ei onnistu" +#~ msgid "Opening the X display timed out" +#~ msgstr "X-nรคytรถn avaus aikakatkaistiin" -#~ msgid "E248: Failed to send command to the destination program" -#~ msgstr "E248: Komennon lไhetys kohdeohjelmalle ei onnistu" +#~ msgid "Testing the X display failed" +#~ msgstr "X-nรคytรถn testaus epรคonnistui" -#~ msgid "E573: Invalid server id used: %s" -#~ msgstr "E573: Virheellinen palvelimen tunniste: %s" +#~ msgid "" +#~ "\n" +#~ "Vim: Got X error\n" +#~ msgstr "" +#~ "\n" +#~ "Vim: X-virhe\n" -#~ msgid "E251: VIM instance registry property is badly formed. Deleted!" -#~ msgstr "E251: VIMin instanssin rekisteriarvo on virheellinen, poistettiin." +#~ msgid "Opening the X display took %ld msec" +#~ msgstr "X-nรคytรถn avaus vei %ld millisekuntia" -#~ msgid "netbeans is not supported with this GUI\n" -#~ msgstr "netbeans ei toimi tไssไ kไytt๖liittymไssไ\n" +#~ msgid "E245: Illegal char '%c' in font name \"%s\"" +#~ msgstr "E245: Virheellinen merkki %c fontin nimessรค %s" -#~ msgid "This Vim was not compiled with the diff feature." -#~ msgstr "Tไhไn Vimiin ei ole kไไnnetty diff-toimintoja mukaan." +#~ msgid "E244: Illegal quality name \"%s\" in font name \"%s\"" +#~ msgstr "E244: Virheellinen laatunimi %s fontin nimessรค %s" -#~ msgid "'-nb' cannot be used: not enabled at compile time\n" -#~ msgstr "-nb:tไ ei voi kไyttไไ, koska sitไ ei kไไnnetty mukaan\n" +#~ msgid "E244: Illegal charset name \"%s\" in font name \"%s\"" +#~ msgstr "E244: Virheellinen merkistรถn nimi %s fontin nimessรค %s" -#~ msgid "Vim: Error: Failure to start gvim from NetBeans\n" -#~ msgstr "Vim: Virhe: Gvimin kไynnistys NetBeansistไ ei onnistu\n" +#~ msgid "Printing '%s'" +#~ msgstr "Tulostetaan %s" + +#~ msgid "E238: Print error: %s" +#~ msgstr "E238: Tulostinvirhe: %s" + +#~ msgid "E613: Unknown printer font: %s" +#~ msgstr "E613: Tuntematon tulostimen fontti: %s" + +#~ msgid "to %s on %s" +#~ msgstr "tulostimelle %s kohteessa %s" + +#~ msgid "E237: Printer selection failed" +#~ msgstr "E237: Tulostimen valinta epรคonnistui" + +#~ msgid "'columns' is not 80, cannot execute external commands" +#~ msgstr "columns ei ole 80, ei voi suorittaa ulkoista komentoa" + +#~ msgid "I/O ERROR" +#~ msgstr "IO-virhe" + +#~ msgid "ANCHOR_BUF_SIZE too small." +#~ msgstr "ANCHOR_BUF_SIZE liian pieni." + +#~ msgid " returned\n" +#~ msgstr " palautti\n" + +#~ msgid "shell " +#~ msgstr "kuori " + +#~ msgid "Cannot execute " +#~ msgstr "Ei voi suorittaa " + +#~ msgid "E360: Cannot execute shell with -f option" +#~ msgstr "E360: Kuorta ei voi avata asetuksella -f" + +#~ msgid "mch_get_shellsize: not a console??\n" +#~ msgstr "mch_get_shellsize: ei ole konsoli?\n" + +#~ msgid "cannot change console mode ?!\n" +#~ msgstr "ei voi vaihtaa konsolitilaa?\n" + +#~ msgid "Vim exiting with %d\n" +#~ msgstr "Vim sulkeutuu koodilla %d\n" + +#~ msgid "Cannot create " +#~ msgstr "Ei voi luoda " + +#~ msgid "Cannot open NIL:\n" +#~ msgstr "Ei voi avata NILiรค:\n" + +#~ msgid "Need %s version %ld\n" +#~ msgstr "Tarvitaan %s versio %ld\n" + +#~ msgid "Need Amigados version 2.04 or later\n" +#~ msgstr "Amigados 2.04 tai uudempi tarvitaan\n" + +#~ msgid "VIM: Can't open window!\n" +#~ msgstr "VIM: Ei voi avata ikkunaa\n" + +#~ msgid "cannot open " +#~ msgstr "ei voi avata " + +#~ msgid "E538: No mouse support" +#~ msgstr "E538: Hiirtรค ei tueta" + +#~ msgid "E533: can't select wide font" +#~ msgstr "E533: Leveรคn fontin valinta ei onnistu" + +#~ msgid "E598: Invalid fontset" +#~ msgstr "E598: Viallinen fontset" + +#~ msgid "E597: can't select fontset" +#~ msgstr "E597: Fontsetin valinta ei onnistu" + +#~ msgid "E596: Invalid font(s)" +#~ msgstr "E596: Viallisia fontteja" + +#~ msgid "E617: Cannot be changed in the GTK+ 2 GUI" +#~ msgstr "E617: Ei voi muuttaa GTK+2-GUIssa" + +#~ msgid "E531: Use \":gui\" to start the GUI" +#~ msgstr "E531: Kรคytรค komentoa :gui GUIn kรคynnistรคmiseen" + +#~ msgid "E530: Cannot change term in GUI" +#~ msgstr "E530: Ei voi vaihtaa termiรค GUIssa" + +#~ msgid "E522: Not found in termcap" +#~ msgstr "E522: Puuttuu termcapista" + +#~ msgid "Thanks for flying Vim" +#~ msgstr "Kiitos ettรค ajoit Vimiรค" + +#~ msgid "%<%f%h%m%=Page %N" +#~ msgstr "%<%f%h%m%=Sivu %N" #~ msgid "" #~ "\n" -#~ "Where case is ignored prepend / to make flag upper case" +#~ "# Registers:\n" #~ msgstr "" #~ "\n" -#~ "Jos aakkoslaji on ohitettu, lisไไ alkuun / tehdไksesi asetuksesta " -#~ "suuraakkosia" +#~ "# Rekisterit:\n" -#~ msgid "-register\t\tRegister this gvim for OLE" -#~ msgstr "-register\t\trekister๖i gvim OLEa varten" +#~ msgid "Illegal register name" +#~ msgstr "Virheellinen rekisterin nimi" -#~ msgid "-unregister\t\tUnregister gvim for OLE" -#~ msgstr "-unregister\t\tPoista gvim OLE-rekisteristไ" +#~ msgid "freeing %ld lines" +#~ msgstr "vapautetaan %ld riviรค" -#~ msgid "-g\t\t\tRun using GUI (like \"gvim\")" -#~ msgstr "-g\t\t\tAvaa GUI (kuten gvimillไ)" +#~ msgid "cannot yank; delete anyway" +#~ msgstr "Ei voi kopioida; poista joka tapauksessa" -#~ msgid "-f or --nofork\tForeground: Don't fork when starting GUI" -#~ msgstr "-f tai --nofork\tEdustalle: ฤlไ haarauta GUIn kไynnistyksessไ" +#~ msgid "E775: Eval feature not available" +#~ msgstr "E775: Eval ei ole kรคytettรคvissรค" -#~ msgid "-f\t\t\tDon't use newcli to open window" -#~ msgstr "-f\t\t\tฤlไ kไytไ newcli:tไ ikkunan avaamiseen" +#~ msgid "E505: %s is read-only (add ! to override)" +#~ msgstr "E505: %s on kirjoitussuojattu (lisรครค komentoon ! ohittaaksesi)" -#~ msgid "-dev <device>\t\tUse <device> for I/O" -#~ msgstr "-dev <laite>\t\tKไytไ <laitetta> IO:hon" +#~ msgid "E511: netbeans already connected" +#~ msgstr "E511: netbeans on yhdistetty jo" -#~ msgid "-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc" -#~ msgstr "-U <gvimrc>\t\tKไytไ <gvimrc>-tiedostoa .gvimrc:iden sijasta" +#~ msgid "E838: netbeans is not supported with this GUI" +#~ msgstr "E838: netbeans ei toimi tรคssรค kรคyttรถliittymรคssรค" -#~ msgid "-x\t\t\tEdit encrypted files" -#~ msgstr "-x\t\t\tMuokkaa salattua tiedostoa" +#~ msgid "E658: NetBeans connection lost for buffer %ld" +#~ msgstr "E658: NetBeans-yhteys katkesi puskurille %ld" -#~ msgid "-display <display>\tConnect vim to this particular X-server" -#~ msgstr "-display <nไytt๖>\tYhdistไ vim tiettyyn X-palvelimeen" +#~ msgid "E668: Wrong access mode for NetBeans connection info file: \"%s\"" +#~ msgstr "E668: Vรครคrรค avaustila NetBeans-yhteyden infotiedostolle: %s" -#~ msgid "-X\t\t\tDo not connect to X server" -#~ msgstr "-X\t\t\tฤlไ yhdistไ X-palvelimeen" +#~ msgid "E547: Illegal mouseshape" +#~ msgstr "E547: Virheellinen hiiren muoto" -#~ msgid "--remote <files>\tEdit <files> in a Vim server if possible" -#~ msgstr "" -#~ "--remote <tiedostoja>\tMuokkaa <tiedostoja> Vim-palvelimessa, jos " -#~ "mahdollista" +#~ msgid "E341: Internal error: lalloc(%ld, )" +#~ msgstr "E341: Sisรคinen virhe: lalloc(%ld, )" -#~ msgid "--remote-silent <files> Same, don't complain if there is no server" -#~ msgstr "" -#~ "--remote-silent <tiedostoja>\tSama, mutta ไlไ ilmoita puuttuvasta " -#~ "palvelimesta" +#~ msgid "E340: Line is becoming too long" +#~ msgstr "E340: Rivistรค tulee liian pitkรค" #~ msgid "" -#~ "--remote-wait <files> As --remote but wait for files to have been edited" +#~ "[calls] total re/malloc()'s %lu, total free()'s %lu\n" +#~ "\n" #~ msgstr "" -#~ "--remote-wait <tiedostoja> kuten --remote, mutta odota tiedostojen " -#~ "muokkaamista" +#~ "[kutsut] yht. re/malloc() %lu, yht. free() %lu\n" +#~ "\n" #~ msgid "" -#~ "--remote-wait-silent <files> Same, don't complain if there is no server" +#~ "\n" +#~ "[bytes] total alloc-freed %lu-%lu, in use %lu, peak use %lu\n" #~ msgstr "" -#~ "--remote-wait-silent <tiedostoja> sama, mutta ไlไ ilmoita puuttuvasta " -#~ "palvelimesta" +#~ "\n" +#~ "[tavua] yht. alloc-free %lu-%lu, kรคytรถssรค %lu, kรคyttรถhuippu %lu\n" -#~ msgid "" -#~ "--remote-tab[-wait][-silent] <files> As --remote but use tab page per " -#~ "file" -#~ msgstr "" -#~ "--remote-tab[-wait][-silent] <tiedostoja> kuten --remote, mutta avaa " -#~ "vไlilehti joka tiedostolle" +#~ msgid "ERROR: " +#~ msgstr "VIRHE: " -#~ msgid "--remote-send <keys>\tSend <keys> to a Vim server and exit" -#~ msgstr "" -#~ "--remote-send <nไppไimiไ>\tLไhetไ <nไppไimiไ> painalluksina Vimille ja " -#~ "lopeta" +#~ msgid "E338: Sorry, no file browser in console mode" +#~ msgstr "E338: tiedostonselain puuttuu konsolitilasta" -#~ msgid "" -#~ "--remote-expr <expr>\tEvaluate <expr> in a Vim server and print result" -#~ msgstr "" -#~ "--remote-expr <ilmaus>\tKไsittele <ilmaus> Vim-palvelimella ja tulosta " -#~ "tulos" +#~ msgid "Open File dialog" +#~ msgstr "Avausikkuna" -#~ msgid "--serverlist\t\tList available Vim server names and exit" -#~ msgstr "--serverlist\t\tLuettele Vim-palvelinten nimet ja lopeta" +#~ msgid "Save File dialog" +#~ msgstr "Tallennusikkuna" -#~ msgid "--servername <name>\tSend to/become the Vim server <name>" -#~ msgstr "--servername <nimi>\tLไhetไ Vim-palvelimelle <nimi> tai luo se" +#~ msgid "Select Directory dialog" +#~ msgstr "Hakemiston valintaikkuna" + +#~ msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>" +#~ msgstr "Kรครคnnรถksen yllรคpitรคjรค: Flammie Pirinen <flammie@iki.fi>" + +#~ msgid "E337: Menu not found - check menu names" +#~ msgstr "E337: Valikkoa ei lรถytynyt - tarkista valikkojen nimet" + +#~ msgid "E336: Menu path must lead to a sub-menu" +#~ msgstr "E336: Valikkopolun pitรครค johtaa alivalikkoon" + +#~ msgid "Tear off this menu" +#~ msgstr "Repรคise valikko irti" + +#~ msgid "Swap file already exists!" +#~ msgstr "Swap-tiedosto on jo olemassa" #~ msgid "" #~ "\n" -#~ "Arguments recognised by gvim (Motif version):\n" +#~ " [not usable with this version of Vim]" #~ msgstr "" #~ "\n" -#~ "Gvimin (Motif-version) tuntemat argumentit:\n" +#~ " [ei toimi tรคmรคn Vim-version kanssa]" + +#~ msgid "Using crypt key from swap file for the text file.\n" +#~ msgstr "Kรคytetรครคn swรคpin salausavainta tekstitiedostolle\n" #~ msgid "" #~ "\n" -#~ "Arguments recognised by gvim (neXtaw version):\n" +#~ "to use the same key for text file and swap file" #~ msgstr "" #~ "\n" -#~ "Gvimin (neXtaw-version) tuntemat argumentit:\n" +#~ "kรคyttรครคksesi samaa avainta teksti- ja swรคppitiedostoille" #~ msgid "" #~ "\n" -#~ "Arguments recognised by gvim (Athena version):\n" +#~ "If you wrote the text file after changing the crypt key press enter" #~ msgstr "" #~ "\n" -#~ "Gvimin (Athena-version) tuntemat argumentit:\n" +#~ "Jos kirjoitit tekstitiedoston salausavaimen vaihdon jรคlkeen paina enteriรค" -#~ msgid "-display <display>\tRun vim on <display>" -#~ msgstr "-display <nไytt๖>\tSuorita vim <nไyt๖ssไ>" +#~ msgid "" +#~ "\n" +#~ "enter the new crypt key." +#~ msgstr "" +#~ "\n" +#~ "anna uusi salausavain." -#~ msgid "-iconic\t\tStart vim iconified" -#~ msgstr "-iconic\t\tKไynnistไ pienennettynไ" +#~ msgid "" +#~ "\n" +#~ "If you entered a new crypt key but did not write the text file," +#~ msgstr "" +#~ "\n" +#~ "Jos kรคytit uutta salausavainta muttet kirjoittanut tekstitiedostoa," -#~ msgid "-background <color>\tUse <color> for the background (also: -bg)" -#~ msgstr "-background <vไri>\tKไytไ <vไriไ> taustavไrinไ (my๖s: -bg)" +#~ msgid "Swap file is encrypted: \"%s\"" +#~ msgstr "Swap-tiedosto on salattu: %s" -#~ msgid "-foreground <color>\tUse <color> for normal text (also: -fg)" -#~ msgstr "-foreground <vไri>\tKไytไ <vไriไ> tekstin vไrinไ (my๖s: -fg)" +#~ msgid "" +#~ "E833: %s is encrypted and this version of Vim does not support encryption" +#~ msgstr "E833: %s on salattu eikรค tรคmรค Vim tue salausta" -#~ msgid "-font <font>\t\tUse <font> for normal text (also: -fn)" -#~ msgstr "-font <fontti>\t\tKไytไ <fonttia> tekstissไ (my๖s: -fn)" +#~ msgid "E843: Error while updating swap file crypt" +#~ msgstr "E843: Virhe pรคivitettรคessรค swapin kryptausta" -#~ msgid "-boldfont <font>\tUse <font> for bold text" -#~ msgstr "-boldfont <fontti>\tKไytไ <fonttia> lihavoidussa tekstissไ" +#~ msgid "E289: input method doesn't support my preedit type" +#~ msgstr "E289: syรถtemetodi ei tue tรคtรค preedit-tyyppiรค" -#~ msgid "-italicfont <font>\tUse <font> for italic text" -#~ msgstr "-italicfont <fontti>\tKไytไ <fonttia> kursivoidussa tekstissไ" +#~ msgid "E288: input method doesn't support any style" +#~ msgstr "E288: syรถtemetodi ei tue tyylejรค" -#~ msgid "-geometry <geom>\tUse <geom> for initial geometry (also: -geom)" +#~ msgid "E287: Warning: Could not set destroy callback to IM" #~ msgstr "" -#~ "-geometry <geom>\tKไytไ mittoja <geom> ikkunan asetteluun (my๖s: -geom)" +#~ "E287: Varoitus: Ei voitu asettaa destroy-kutsua syรถtemetodipalvelimelle" -#~ msgid "-borderwidth <width>\tUse a border width of <width> (also: -bw)" -#~ msgstr "-borderwidt <leveys>\tKไytไ <leveyttไ> reunuksissa (my๖s: -bw) " - -#~ msgid "" -#~ "-scrollbarwidth <width> Use a scrollbar width of <width> (also: -sw)" -#~ msgstr "" -#~ "-scrollbarwidth <leveys> Kไytไ <leveyttไ> vierityspalkissa (my๖s: -sw)" +#~ msgid "E286: Failed to open input method" +#~ msgstr "E286: Syรถtemetodin avaus ei onnistu" -#~ msgid "-menuheight <height>\tUse a menu bar height of <height> (also: -mh)" -#~ msgstr "-menuheight <korkeus>\tKไytไ <korkeutta> valikossa (my๖s: -mh)" +#~ msgid "E285: Failed to create input context" +#~ msgstr "E285: Syรถtekontekstin luonti ei onnistu" -#~ msgid "-reverse\t\tUse reverse video (also: -rv)" -#~ msgstr "-reverse\t\tKไytไ kไไnteisvไrejไ (my๖s: -rv) " +#~ msgid "E284: Cannot set IC values" +#~ msgstr "E284: Ei voi asettaa IC-arvoja" -#~ msgid "+reverse\t\tDon't use reverse video (also: +rv)" -#~ msgstr "+reverse\t\tฤlไ kไytไ kไไnteisvไrejไ (my๖s: +rv)" +#~ msgid "E543: Not a valid codepage" +#~ msgstr "E543: Koodisivu ei ole kรคypรค" -#~ msgid "-xrm <resource>\tSet the specified resource" -#~ msgstr "-xrm <resurssi>\tAseta resurssi" +#~ msgid "Missing '>'" +#~ msgstr "> puuttuu" #~ msgid "" #~ "\n" -#~ "Arguments recognised by gvim (RISC OS version):\n" +#~ "# History of marks within files (newest to oldest):\n" #~ msgstr "" #~ "\n" -#~ "Gvimin (RISC OS -version) tuntemat argumentit:\n" - -#~ msgid "--columns <number>\tInitial width of window in columns" -#~ msgstr "--columns <luku>\tIkkunan alkuleveys sarakkeina" +#~ "# Tiedostojen merkkien historia (uusimmasta vanhimpaan):\n" -#~ msgid "--rows <number>\tInitial height of window in rows" -#~ msgstr "--rows <luku>\tIkkunan alkukorkeus riveinไ" +#~ msgid "" +#~ "\n" +#~ "# Jumplist (newest first):\n" +#~ msgstr "" +#~ "\n" +#~ "# Hyppylista (uusin ensiksi):\n" #~ msgid "" #~ "\n" -#~ "Arguments recognised by gvim (GTK+ version):\n" +#~ "# File marks:\n" #~ msgstr "" #~ "\n" -#~ "Gvimin (GTK+-version) tuntemat argumentit:\n" +#~ "# Tiedoston merkit:\n" -#~ msgid "-display <display>\tRun vim on <display> (also: --display)" -#~ msgstr "-display <nไytt๖>\tSuorita vim nไyt๖llไ <nไytt๖> (my๖s: --display)" +#~ msgid ": Send expression failed.\n" +#~ msgstr ": Ilmauksen lรคhetys epรคonnistui.\n" -# X-ikkunointijไrjestelmไssไ saman sovelluksen saman luokan ikkunat -# tunnistetaan rooliresursseista -#~ msgid "--role <role>\tSet a unique role to identify the main window" -#~ msgstr "" -#~ "--role <rooli>\tAseta pไไikkunalle ainutlaatuinen rooli tunnisteeksi" +#~ msgid "No display: Send expression failed.\n" +#~ msgstr "Ei nรคyttรถรค: Ilmauksen lรคhetys epรคonnistui.\n" -#~ msgid "--socketid <xid>\tOpen Vim inside another GTK widget" -#~ msgstr "--socketid <xid>\tAvaa Vim annettuun GTK-olioon " +#~ msgid "%d of %d edited" +#~ msgstr "%d/%d muokattu" -#~ msgid "-P <parent title>\tOpen Vim inside parent application" -#~ msgstr "-P <otsikko>\tAvaa Vim isไntไohjelman sisไไn" +#~ msgid ": Send failed. Trying to execute locally\n" +#~ msgstr ": Lรคhetys epรคonnistui. Yritetรครคn suorittaa paikallisena\n" + +#~ msgid ": Send failed.\n" +#~ msgstr ": Lรคhetys epรคonnistui.\n" + +#~ msgid "No display" +#~ msgstr "Ei nรคyttรถรค" #~ msgid "--windowid <HWND>\tOpen Vim inside another win32 widget" #~ msgstr "--windowid <HWND>\tAvaa Vim annettuun win32-olioon " -#~ msgid "No display" -#~ msgstr "Ei nไytt๖ไ" +#~ msgid "-P <parent title>\tOpen Vim inside parent application" +#~ msgstr "-P <otsikko>\tAvaa Vim isรคntรคohjelman sisรครคn" -#~ msgid ": Send failed.\n" -#~ msgstr ": Lไhetys epไonnistui.\n" +#~ msgid "--echo-wid\t\tMake gvim echo the Window ID on stdout" +#~ msgstr "--echo-wid\t\tTulosta gvimin Window ID vakiotulosteeseen" -#~ msgid ": Send failed. Trying to execute locally\n" -#~ msgstr ": Lไhetys epไonnistui. Yritetไไn suorittaa paikallisena\n" +#~ msgid "--socketid <xid>\tOpen Vim inside another GTK widget" +#~ msgstr "--socketid <xid>\tAvaa Vim annettuun GTK-olioon " -#~ msgid "%d of %d edited" -#~ msgstr "%d/%d muokattu" +# X-ikkunointijรคrjestelmรคssรค saman sovelluksen saman luokan ikkunat +# tunnistetaan rooliresursseista +#~ msgid "--role <role>\tSet a unique role to identify the main window" +#~ msgstr "" +#~ "--role <rooli>\tAseta pรครคikkunalle ainutlaatuinen rooli tunnisteeksi" -#~ msgid "No display: Send expression failed.\n" -#~ msgstr "Ei nไytt๖ไ: Ilmauksen lไhetys epไonnistui.\n" +#~ msgid "-display <display>\tRun vim on <display> (also: --display)" +#~ msgstr "-display <nรคyttรถ>\tSuorita vim nรคytรถllรค <nรคyttรถ> (myรถs: --display)" -#~ msgid ": Send expression failed.\n" -#~ msgstr ": Ilmauksen lไhetys epไonnistui.\n" +#~ msgid "" +#~ "\n" +#~ "Arguments recognised by gvim (GTK+ version):\n" +#~ msgstr "" +#~ "\n" +#~ "Gvimin (GTK+-version) tuntemat argumentit:\n" -#~ msgid "E543: Not a valid codepage" -#~ msgstr "E543: Koodisivu ei ole kไypไ" +#~ msgid "-xrm <resource>\tSet the specified resource" +#~ msgstr "-xrm <resurssi>\tAseta resurssi" -#~ msgid "E285: Failed to create input context" -#~ msgstr "E285: Sy๖tekontekstin luonti ei onnistu" +#~ msgid "+reverse\t\tDon't use reverse video (also: +rv)" +#~ msgstr "+reverse\t\tรlรค kรคytรค kรครคnteisvรคrejรค (myรถs: +rv)" -#~ msgid "E286: Failed to open input method" -#~ msgstr "E286: Sy๖temetodin avaus ei onnistu" +#~ msgid "-reverse\t\tUse reverse video (also: -rv)" +#~ msgstr "-reverse\t\tKรคytรค kรครคnteisvรคrejรค (myรถs: -rv) " -#~ msgid "E287: Warning: Could not set destroy callback to IM" +#~ msgid "-menuheight <height>\tUse a menu bar height of <height> (also: -mh)" +#~ msgstr "-menuheight <korkeus>\tKรคytรค <korkeutta> valikossa (myรถs: -mh)" + +#~ msgid "" +#~ "-scrollbarwidth <width> Use a scrollbar width of <width> (also: -sw)" #~ msgstr "" -#~ "E287: Varoitus: Ei voitu asettaa destroy-kutsua sy๖temetodipalvelimelle" +#~ "-scrollbarwidth <leveys> Kรคytรค <leveyttรค> vierityspalkissa (myรถs: -sw)" -#~ msgid "E288: input method doesn't support any style" -#~ msgstr "E288: sy๖temetodi ei tue tyylejไ" +#~ msgid "-borderwidth <width>\tUse a border width of <width> (also: -bw)" +#~ msgstr "-borderwidt <leveys>\tKรคytรค <leveyttรค> reunuksissa (myรถs: -bw) " -#~ msgid "E289: input method doesn't support my preedit type" -#~ msgstr "E289: sy๖temetodi ei tue tไtไ preedit-tyyppiไ" +#~ msgid "-geometry <geom>\tUse <geom> for initial geometry (also: -geom)" +#~ msgstr "" +#~ "-geometry <geom>\tKรคytรค mittoja <geom> ikkunan asetteluun (myรถs: -geom)" -#~ msgid "" -#~ "E833: %s is encrypted and this version of Vim does not support encryption" -#~ msgstr "E833: %s on salattu eikไ tไmไ Vim tue salausta" +#~ msgid "-italicfont <font>\tUse <font> for italic text" +#~ msgstr "-italicfont <fontti>\tKรคytรค <fonttia> kursivoidussa tekstissรค" -#~ msgid "Swap file is encrypted: \"%s\"" -#~ msgstr "Swap-tiedosto on salattu: %s" +#~ msgid "-boldfont <font>\tUse <font> for bold text" +#~ msgstr "-boldfont <fontti>\tKรคytรค <fonttia> lihavoidussa tekstissรค" + +#~ msgid "-font <font>\t\tUse <font> for normal text (also: -fn)" +#~ msgstr "-font <fontti>\t\tKรคytรค <fonttia> tekstissรค (myรถs: -fn)" + +#~ msgid "-foreground <color>\tUse <color> for normal text (also: -fg)" +#~ msgstr "-foreground <vรคri>\tKรคytรค <vรคriรค> tekstin vรคrinรค (myรถs: -fg)" + +#~ msgid "-background <color>\tUse <color> for the background (also: -bg)" +#~ msgstr "-background <vรคri>\tKรคytรค <vรคriรค> taustavรคrinรค (myรถs: -bg)" + +#~ msgid "-iconic\t\tStart vim iconified" +#~ msgstr "-iconic\t\tKรคynnistรค pienennettynรค" + +#~ msgid "-display <display>\tRun vim on <display>" +#~ msgstr "-display <nรคyttรถ>\tSuorita vim <nรคytรถssรค>" #~ msgid "" #~ "\n" -#~ "If you entered a new crypt key but did not write the text file," +#~ "Arguments recognised by gvim (Athena version):\n" #~ msgstr "" #~ "\n" -#~ "Jos kไytit uutta salausavainta muttet kirjoittanut tekstitiedostoa," +#~ "Gvimin (Athena-version) tuntemat argumentit:\n" #~ msgid "" #~ "\n" -#~ "enter the new crypt key." +#~ "Arguments recognised by gvim (neXtaw version):\n" #~ msgstr "" #~ "\n" -#~ "anna uusi salausavain." +#~ "Gvimin (neXtaw-version) tuntemat argumentit:\n" #~ msgid "" #~ "\n" -#~ "If you wrote the text file after changing the crypt key press enter" +#~ "Arguments recognised by gvim (Motif version):\n" #~ msgstr "" #~ "\n" -#~ "Jos kirjoitit tekstitiedoston salausavaimen vaihdon jไlkeen paina enteriไ" +#~ "Gvimin (Motif-version) tuntemat argumentit:\n" + +#~ msgid "-i <viminfo>\t\tUse <viminfo> instead of .viminfo" +#~ msgstr "-i <viminfo>\t\tKรคytรค <viminfo>-tiedostoa .viminfon sijaan" + +#~ msgid "--servername <name>\tSend to/become the Vim server <name>" +#~ msgstr "--servername <nimi>\tLรคhetรค Vim-palvelimelle <nimi> tai luo se" + +#~ msgid "--serverlist\t\tList available Vim server names and exit" +#~ msgstr "--serverlist\t\tLuettele Vim-palvelinten nimet ja lopeta" #~ msgid "" -#~ "\n" -#~ "to use the same key for text file and swap file" +#~ "--remote-expr <expr>\tEvaluate <expr> in a Vim server and print result" #~ msgstr "" -#~ "\n" -#~ "kไyttไไksesi samaa avainta teksti- ja swไppitiedostoille" +#~ "--remote-expr <ilmaus>\tKรคsittele <ilmaus> Vim-palvelimella ja tulosta " +#~ "tulos" -#~ msgid "Using crypt key from swap file for the text file.\n" -#~ msgstr "Kไytetไไn swไpin salausavainta tekstitiedostolle\n" +#~ msgid "--remote-send <keys>\tSend <keys> to a Vim server and exit" +#~ msgstr "" +#~ "--remote-send <nรคppรคimiรค>\tLรคhetรค <nรคppรคimiรค> painalluksina Vimille ja " +#~ "lopeta" #~ msgid "" -#~ "\n" -#~ " [not usable with this version of Vim]" +#~ "--remote-tab[-wait][-silent] <files> As --remote but use tab page per " +#~ "file" #~ msgstr "" -#~ "\n" -#~ " [ei toimi tไmไn Vim-version kanssa]" +#~ "--remote-tab[-wait][-silent] <tiedostoja> kuten --remote, mutta avaa " +#~ "vรคlilehti joka tiedostolle" -#~ msgid "Tear off this menu" -#~ msgstr "Repไise valikko irti" +#~ msgid "" +#~ "--remote-wait-silent <files> Same, don't complain if there is no server" +#~ msgstr "" +#~ "--remote-wait-silent <tiedostoja> sama, mutta รคlรค ilmoita puuttuvasta " +#~ "palvelimesta" -#~ msgid "Select Directory dialog" -#~ msgstr "Hakemiston valintaikkuna" +#~ msgid "" +#~ "--remote-wait <files> As --remote but wait for files to have been edited" +#~ msgstr "" +#~ "--remote-wait <tiedostoja> kuten --remote, mutta odota tiedostojen " +#~ "muokkaamista" -#~ msgid "Save File dialog" -#~ msgstr "Tallennusikkuna" +#~ msgid "--remote-silent <files> Same, don't complain if there is no server" +#~ msgstr "" +#~ "--remote-silent <tiedostoja>\tSama, mutta รคlรค ilmoita puuttuvasta " +#~ "palvelimesta" -#~ msgid "Open File dialog" -#~ msgstr "Avausikkuna" +#~ msgid "--remote <files>\tEdit <files> in a Vim server if possible" +#~ msgstr "" +#~ "--remote <tiedostoja>\tMuokkaa <tiedostoja> Vim-palvelimessa, jos " +#~ "mahdollista" -#~ msgid "E338: Sorry, no file browser in console mode" -#~ msgstr "E338: Sori, tiedostonselain puuttuu konsolitilasta" +#~ msgid "-X\t\t\tDo not connect to X server" +#~ msgstr "-X\t\t\tรlรค yhdistรค X-palvelimeen" -#~ msgid "Vim: preserving files...\n" -#~ msgstr "Vim: sไไstetไไn tiedostoja...\n" +#~ msgid "-display <display>\tConnect vim to this particular X-server" +#~ msgstr "-display <nรคyttรถ>\tYhdistรค vim tiettyyn X-palvelimeen" -#~ msgid "Vim: Finished.\n" -#~ msgstr "Vim: Valmis.\n" +#~ msgid "-x\t\t\tEdit encrypted files" +#~ msgstr "-x\t\t\tMuokkaa salattua tiedostoa" -#~ msgid "ERROR: " -#~ msgstr "VIRHE: " +#~ msgid "+\t\t\tStart at end of file" +#~ msgstr "+\t\t\tAloita tiedoston lopusta" -#~ msgid "" -#~ "\n" -#~ "[bytes] total alloc-freed %<PRIu64>-%<PRIu64>, in use %<PRIu64>, peak use " -#~ "%<PRIu64>\n" -#~ msgstr "" -#~ "\n" -#~ "[tavua] yht. alloc-free %<PRIu64>-%<PRIu64>, kไyt๖ssไ %<PRIu64>, " -#~ "kไytt๖huippu %<PRIu64>\n" +#~ msgid "-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc" +#~ msgstr "-U <gvimrc>\t\tKรคytรค <gvimrc>-tiedostoa .gvimrc:iden sijasta" -#~ msgid "" -#~ "[calls] total re/malloc()'s %<PRIu64>, total free()'s %<PRIu64>\n" -#~ "\n" -#~ msgstr "" -#~ "[kutsut] yht. re/malloc() %<PRIu64>, yht. free() %<PRIu64>\n" -#~ "\n" +#~ msgid "--not-a-term\t\tSkip warning for input/output not being a terminal" +#~ msgstr "--not-a-term\t\tOhita varoitus siitรค ettรค i/o ei ole terminaali" -#~ msgid "E340: Line is becoming too long" -#~ msgstr "E340: Rivistไ tulee liian pitkไ" +#~ msgid "-T <terminal>\tSet terminal type to <terminal>" +#~ msgstr "-T <terminaali>\tAseta terminaalin tyypiksi <terminaali>" -#~ msgid "E341: Internal error: lalloc(%<PRId64>, )" -#~ msgstr "E341: Sisไinen virhe: lalloc(%<PRId64>, )" +#~ msgid "-F\t\t\tStart in Farsi mode" +#~ msgstr "-F\t\t\tkรคynnistรค farsi-tilassa" -#~ msgid "E547: Illegal mouseshape" -#~ msgstr "E547: Virheellinen hiiren muoto" +#~ msgid "-H\t\t\tStart in Hebrew mode" +#~ msgstr "-H\t\t\tkรคynnistรค heprea-tilassa" -#~ msgid "Enter encryption key: " -#~ msgstr "Anna salausavain: " +#~ msgid "-A\t\t\tstart in Arabic mode" +#~ msgstr "-A\t\t\tkรคynnistรค arabia-tilassa" -#~ msgid "Enter same key again: " -#~ msgstr "Anna sama avain uudestaan: " +#~ msgid "-dev <device>\t\tUse <device> for I/O" +#~ msgstr "-dev <laite>\t\tKรคytรค <laitetta> IO:hon" -#~ msgid "Keys don't match!" -#~ msgstr "Avaimet eivไt tไsmไไ!" +#~ msgid "-f\t\t\tDon't use newcli to open window" +#~ msgstr "-f\t\t\tรlรค kรคytรค newcli:tรค ikkunan avaamiseen" -#~ msgid "Cannot connect to Netbeans #2" -#~ msgstr "Ei voi yhdistไไ Netbeans #2:een" +#~ msgid "-L\t\t\tSame as -r" +#~ msgstr "-L\t\t\tkuten -r" -#~ msgid "Cannot connect to Netbeans" -#~ msgstr "Ei voi yhdistไไ Netbeansiin" +#~ msgid "-D\t\t\tDebugging mode" +#~ msgstr "-D\t\t\tVianetsintรคtila" -#~ msgid "E668: Wrong access mode for NetBeans connection info file: \"%s\"" -#~ msgstr "E668: Vไไrไ avaustila NetBeans-yhteyden infotiedostolle: %s" +#~ msgid "-N\t\t\tNot fully Vi compatible: 'nocompatible'" +#~ msgstr "-N\t\t\tEi Vi-yhteensopivuutta: nocompatible" -#~ msgid "read from Netbeans socket" -#~ msgstr "luettu Netbeans-soketista" +#~ msgid "-C\t\t\tCompatible with Vi: 'compatible'" +#~ msgstr "-C\t\t\tVi-yhteensopivuustila: compatible" -#~ msgid "E658: NetBeans connection lost for buffer %<PRId64>" -#~ msgstr "E658: NetBeans-yhteys katkesi puskurille %<PRId64>" +#~ msgid "-l\t\t\tLisp mode" +#~ msgstr "-l\t\t\tLisp-tila" -#~ msgid "E511: netbeans already connected" -#~ msgstr "E511: netbeans on yhdistetty jo" +#~ msgid "-b\t\t\tBinary mode" +#~ msgstr "-b\t\t\tBinรครคritila" -#~ msgid "E505: " -#~ msgstr "E505: " +#~ msgid "-Z\t\t\tRestricted mode (like \"rvim\")" +#~ msgstr "-Z\t\t\tRajoitettu tila (kuten rvimillรค)" -#~ msgid "E775: Eval feature not available" -#~ msgstr "E775: Eval ei ole kไytettไvissไ" +#~ msgid "-R\t\t\tReadonly mode (like \"view\")" +#~ msgstr "-R\t\t\tKirjoitussuojattu tila (kuten view'lla)" -#~ msgid "freeing %<PRId64> lines" -#~ msgstr "vapautetaan %<PRId64> riviไ" +#~ msgid "-y\t\t\tEasy mode (like \"evim\", modeless)" +#~ msgstr "-y\t\t\tHelppokรคyttรถtila (kuten evimissรค, ilman tiloja)" -#~ msgid "E530: Cannot change term in GUI" -#~ msgstr "E530: Ei voi vaihtaa termiไ GUIssa" +#~ msgid "-d\t\t\tDiff mode (like \"vimdiff\")" +#~ msgstr "-d\t\t\tDiff-tila (kuten vimdiffillรค)" -#~ msgid "E531: Use \":gui\" to start the GUI" -#~ msgstr "E531: Kไytไ komentoa :gui GUIn kไynnistไmiseen" +#~ msgid "-E\t\t\tImproved Ex mode" +#~ msgstr "-E\t\t\tParanneltu Ex-tila" -#~ msgid "E617: Cannot be changed in the GTK+ 2 GUI" -#~ msgstr "E617: Ei voi muuttaa GTK+2-GUIssa" +#~ msgid "-e\t\t\tEx mode (like \"ex\")" +#~ msgstr "-e\t\t\tEx-tila (kute exillรค)" -#~ msgid "E596: Invalid font(s)" -#~ msgstr "E596: Viallisia fontteja" +#~ msgid "-v\t\t\tVi mode (like \"vi\")" +#~ msgstr "-v\t\t\tVi-tila (kuten villรค)" -#~ msgid "E597: can't select fontset" -#~ msgstr "E597: Fontsetin valinta ei onnistu" +#~ msgid "-f or --nofork\tForeground: Don't fork when starting GUI" +#~ msgstr "-f tai --nofork\tEdustalle: รlรค haarauta GUIn kรคynnistyksessรค" -#~ msgid "E598: Invalid fontset" -#~ msgstr "E598: Viallinen fontset" +#~ msgid "-g\t\t\tRun using GUI (like \"gvim\")" +#~ msgstr "-g\t\t\tAvaa GUI (kuten gvimillรค)" -#~ msgid "E533: can't select wide font" -#~ msgstr "E533: Leveไn fontin valinta ei onnistu" +#~ msgid "-unregister\t\tUnregister gvim for OLE" +#~ msgstr "-unregister\t\tPoista gvim OLE-rekisteristรค" -#~ msgid "E534: Invalid wide font" -#~ msgstr "E534: Viallinen leveไ fontti" +#~ msgid "-register\t\tRegister this gvim for OLE" +#~ msgstr "-register\t\trekisterรถi gvim OLEa varten" -#~ msgid "E538: No mouse support" -#~ msgstr "E538: Hiirtไ ei tueta" +#~ msgid "" +#~ "\n" +#~ "Where case is ignored prepend / to make flag upper case" +#~ msgstr "" +#~ "\n" +#~ "Jos aakkoslaji on ohitettu, lisรครค alkuun / tehdรคksesi asetuksesta " +#~ "suuraakkosia" -#~ msgid "cannot open " -#~ msgstr "ei voi avata " +#~ msgid "" +#~ "\n" +#~ " or:" +#~ msgstr "" +#~ "\n" +#~ " tai:" -#~ msgid "VIM: Can't open window!\n" -#~ msgstr "VIM: Ei voi avata ikkunaa\n" +#~ msgid " vim [arguments] " +#~ msgstr " vim [argumentit] " -#~ msgid "Need Amigados version 2.04 or later\n" -#~ msgstr "Amigados 2.04 tai uudempi tarvitaan\n" +#~ msgid "Vim: Error: This version of Vim does not run in a Cygwin terminal\n" +#~ msgstr "Vim: Virhe: Tรคmรค versio Vimistรค ei toimi Cygwinin terminaalissa\n" -#~ msgid "Need %s version %<PRId64>\n" -#~ msgstr "Tarvitaan %s versio %<PRId64>\n" +#~ msgid "Vim: Error: Failure to start gvim from NetBeans\n" +#~ msgstr "Vim: Virhe: Gvimin kรคynnistys NetBeansistรค ei onnistu\n" -#~ msgid "Cannot open NIL:\n" -#~ msgstr "Ei voi avata NILiไ:\n" +#~ msgid "This Vim was not compiled with the diff feature." +#~ msgstr "Tรคhรคn Vimiin ei ole kรครคnnetty diff-toimintoja mukaan." -#~ msgid "Cannot create " -#~ msgstr "Ei voi luoda " +#~ msgid "'-nb' cannot be used: not enabled at compile time\n" +#~ msgstr "-nb:tรค ei voi kรคyttรครค, koska sitรค ei kรครคnnetty mukaan\n" -#~ msgid "Vim exiting with %d\n" -#~ msgstr "Vim sulkeutuu koodilla %d\n" +#~ msgid "netbeans is not supported with this GUI\n" +#~ msgstr "netbeans ei toimi tรคssรค kรคyttรถliittymรคssรค\n" -#~ msgid "cannot change console mode ?!\n" -#~ msgstr "ei voi vaihtaa konsolitilaa?\n" +#~ msgid "%d files to edit\n" +#~ msgstr "%d tiedostoa muokattavana\n" -#~ msgid "mch_get_shellsize: not a console??\n" -#~ msgstr "mch_get_shellsize: ei ole konsoli?\n" +#~ msgid "E251: VIM instance registry property is badly formed. Deleted!" +#~ msgstr "E251: VIMin instanssin rekisteriarvo on virheellinen, poistettiin." -#~ msgid "E360: Cannot execute shell with -f option" -#~ msgstr "E360: Kuorta ei voi avata asetuksella -f" +#~ msgid "E573: Invalid server id used: %s" +#~ msgstr "E573: Virheellinen palvelimen tunniste: %s" -#~ msgid "Cannot execute " -#~ msgstr "Ei voi suorittaa " +#~ msgid "E248: Failed to send command to the destination program" +#~ msgstr "E248: Komennon lรคhetys kohdeohjelmalle ei onnistu" -#~ msgid "shell " -#~ msgstr "kuori " +#~ msgid "Unable to register a command server name" +#~ msgstr "Komentopalvelimen nimen rekisterรถinti ei onnistu" -#~ msgid " returned\n" -#~ msgstr " palautti\n" +#~ msgid "cannot get line" +#~ msgstr "ei voida hakea riviรค" -#~ msgid "ANCHOR_BUF_SIZE too small." -#~ msgstr "ANCHOR_BUF_SIZE liian pieni." +#~ msgid "E572: exit code %d" +#~ msgstr "E572: palautusarvo %d" -#~ msgid "I/O ERROR" -#~ msgstr "IO-virhe" +#~ msgid "" +#~ "E571: Sorry, this command is disabled: the Tcl library could not be " +#~ "loaded." +#~ msgstr "E571: komento ei toimi, Tcl-kirjastoa ei voitu ladata." -#~ msgid "Message" -#~ msgstr "Viesti" +#~ msgid "cannot register callback command: buffer/window reference not found" +#~ msgstr "" +#~ "callbackia ei voi rekisterรถidรค: puskurin tai ikkunan viitettรค ei lรถydy" -#~ msgid "'columns' is not 80, cannot execute external commands" -#~ msgstr "columns ei ole 80, ei voi suorittaa ulkoista komentoa" +#~ msgid "" +#~ "E280: TCL FATAL ERROR: reflist corrupt!? Please report this to vim-" +#~ "dev@vim.org" +#~ msgstr "" +#~ "E280: kriittinen TCL-virhe: reflist hajalla? Ilmoita asiasta " +#~ "postituslistalle vim-dev@vim.org" -#~ msgid "E237: Printer selection failed" -#~ msgstr "E237: Tulostimen valinta epไonnistui" +#~ msgid "" +#~ "cannot register callback command: buffer/window is already being deleted" +#~ msgstr "callbackia ei voi rekisterรถidรค: puskuri tai ikkuna on poistettu" -#~ msgid "to %s on %s" -#~ msgstr "tulostimelle %s kohteessa %s" +#~ msgid "cannot create buffer/window command: object is being deleted" +#~ msgstr "ei voi luoda puskuri- tai ikkunakomentoa, olio on poistumassa" -#~ msgid "E613: Unknown printer font: %s" -#~ msgstr "E613: Tuntematon tulostimen fontti: %s" +#~ msgid "vim error" +#~ msgstr "vim-virhe" -#~ msgid "E238: Print error: %s" -#~ msgstr "E238: Tulostinvirhe: %s" +#~ msgid "unknown vimOption" +#~ msgstr "tuntematon vimOption" -#~ msgid "Printing '%s'" -#~ msgstr "Tulostetaan %s" +#~ msgid "unknown flag: " +#~ msgstr "tuntematon asetus: " -#~ msgid "E244: Illegal charset name \"%s\" in font name \"%s\"" -#~ msgstr "E244: Virheellinen merkist๖n nimi %s fontin nimessไ %s" +#~ msgid "cannot insert/append line" +#~ msgstr "rivin lisรคys ei onnistu" -#~ msgid "E245: Illegal char '%c' in font name \"%s\"" -#~ msgstr "E245: Virheellinen merkki %c fontin nimessไ %s" +#~ msgid "row %d column %d" +#~ msgstr "rivi %d sarake %d" + +#~ msgid "mark not set" +#~ msgstr "merkko ei ole asetettu" + +#~ msgid "cannot set line(s)" +#~ msgstr "ei voi asettaa rivejรค" -#~ msgid "Vim: Double signal, exiting\n" -#~ msgstr "Vim: Kaksoissignaali, lopetetaan\n" +#~ msgid "not implemented yet" +#~ msgstr "ei toteutettu" -#~ msgid "Vim: Caught deadly signal %s\n" -#~ msgstr "Vim: Tappava signaali %s\n" +#~ msgid "E273: unknown longjmp status %d" +#~ msgstr "E273: tuntematon longjmp-tila %d" -#~ msgid "Vim: Caught deadly signal\n" -#~ msgstr "Vim: Tappava signaali\n" +#~ msgid "E272: unhandled exception" +#~ msgstr "E272: kรคsittelemรคtรถn poikkeus" -#~ msgid "Opening the X display took %<PRId64> msec" -#~ msgstr "X-nไyt๖n avaus vei %<PRId64> millisekuntia" +#~ msgid "E271: retry outside of rescue clause" +#~ msgstr "E271: retry rescuen ulkopuolella" -#~ msgid "" -#~ "\n" -#~ "Vim: Got X error\n" -#~ msgstr "" -#~ "\n" -#~ "Vim: X-virhe\n" +#~ msgid "E269: unexpected break" +#~ msgstr "E269: Odotuksenvastainen break" -#~ msgid "Testing the X display failed" -#~ msgstr "X-nไyt๖n testaus epไonnistui" +#~ msgid "E268: unexpected next" +#~ msgstr "E268: Odotuksenvastainen next" -#~ msgid "Opening the X display timed out" -#~ msgstr "X-nไyt๖n avaus aikakatkaistiin" +#~ msgid "E267: unexpected return" +#~ msgstr "E267: odotuksenvastainen return" #~ msgid "" -#~ "\n" -#~ "Cannot execute shell sh\n" +#~ "E266: Sorry, this command is disabled, the Ruby library could not be " +#~ "loaded." +#~ msgstr "E266: komento ei toimi, Ruby-kirjastoa ei voitu ladata." + +#~ msgid "E265: $_ must be an instance of String" +#~ msgstr "E265: muuttujan $_ pitรครค olla Stringin instanssi" + +#~ msgid "E837: This Vim cannot execute :py3 after using :python" #~ msgstr "" -#~ "\n" -#~ "Kuoren sh suoritus ei onnistu\n" +#~ "E837: Python: Ei voi kรคyttรครค komentoja :py ja :py3 samassa istunnossa" + +#~ msgid "E659: Cannot invoke Python recursively" +#~ msgstr "E659: Pythonia ei voi kutsua rekursiivisesti" #~ msgid "" -#~ "\n" -#~ "Cannot create pipes\n" +#~ "E887: Sorry, this command is disabled, the Python's site module could not " +#~ "be loaded." #~ msgstr "" -#~ "\n" -#~ "Putkia ei voi tehdไ\n" +#~ "E887: Komento ei toimi, Pythonin site-moduulien lataaminen ei onnistunut." #~ msgid "" -#~ "\n" -#~ "Cannot fork\n" +#~ "E263: Sorry, this command is disabled, the Python library could not be " +#~ "loaded." +#~ msgstr "E263: komento ei toimi, Python-kirjaston lataaminen ei onnistunut." + +#~ msgid "E836: This Vim cannot execute :python after using :py3" #~ msgstr "" -#~ "\n" -#~ "Ei voi haarauttaa\n" +#~ "E836: Python: Ei voi kรคyttรครค komentoja :py ja :py3 samassa istunnossa" + +#~ msgid "not allowed in the Vim sandbox" +#~ msgstr "ei sallittu Vimin hiekkalaatikossa" + +#~ msgid "linenr out of range" +#~ msgstr "rivinumero arvoalueen ulkopuolelta" + +#~ msgid "window is invalid" +#~ msgstr "ikkuna on virheellinen" + +#~ msgid "buffer is invalid" +#~ msgstr "puskuri on virheellinen" + +#~ msgid "Vim error" +#~ msgstr "Vim-virhe" + +#~ msgid "Vim error: ~a" +#~ msgstr "Vim-virhe: ~a" + +#~ msgid "couldn't open buffer" +#~ msgstr "ei voitu avata puskuria" + +#~ msgid "unknown option" +#~ msgstr "tuntematon asetus" + +#~ msgid "hidden option" +#~ msgstr "piilotettu asetus" + +#~ msgid "expressions disabled at compile time" +#~ msgstr "ilmaukset poistettu kรคytรถstรค kรครคnnรถsaikana" + +#~ msgid "invalid expression" +#~ msgstr "virheellinen ilmaus" #~ msgid "" -#~ "\n" -#~ "Command terminated\n" +#~ "E895: Sorry, this command is disabled, the MzScheme's racket/base module " +#~ "could not be loaded." #~ msgstr "" -#~ "\n" -#~ "Komento loppui\n" +#~ "E895: Komento ei toimi, MzScheme-moduulia racket/base ei voitu ladata." -#~ msgid "XSMP lost ICE connection" -#~ msgstr "XSMP kadotti ICE-yhteyden" +#~ msgid "" +#~ "E815: Sorry, this command is disabled, the MzScheme libraries could not " +#~ "be loaded." +#~ msgstr "E815: komento ei toimi, MzScheme-kirjastoa ei voitu ladata." -#~ msgid "Opening the X display failed" -#~ msgstr "X-nไyt๖n avaus epไonnistui" +#~ msgid "Lua library cannot be loaded." +#~ msgstr "Luan kirjastoa ei voitu ladata." -#~ msgid "XSMP handling save-yourself request" -#~ msgstr "XSMP kไsittelee save-yourself-pyynt๖ไ" +#~ msgid "E626: cannot get cscope database information" +#~ msgstr "E626: ei voi hakea cscope-tietokannan tietoja" -#~ msgid "XSMP opening connection" -#~ msgstr "XSMP avaa yhteyttไ" +#~ msgid "E625: cannot open cscope database: %s" +#~ msgstr "E625: ei voi avata cscope-tietokantaa: %s" -#~ msgid "XSMP ICE connection watch failed" -#~ msgstr "XSMP:n ICE-yhteyden tarkkailu epไonnistui" +#~ msgid "E563: stat error" +#~ msgstr "E563: stat-virhe" -#~ msgid "XSMP SmcOpenConnection failed: %s" -#~ msgstr "XSMP SmcOpenConnection epไonnistui: %s" +#~ msgid "E256: Hangul automata ERROR" +#~ msgstr "E256: Hangu-automaattivirhe" -#~ msgid "At line" -#~ msgstr "Rivillไ" +#~ msgid "Size:" +#~ msgstr "Koko:" -#~ msgid "Could not load vim32.dll!" -#~ msgstr "Vim32.dll:ไไ ei voitu ladata" +#~ msgid "Style:" +#~ msgstr "Tyyli:" -#~ msgid "VIM Error" -#~ msgstr "VIM-virhe" +#~ msgid "Font:" +#~ msgstr "Fontti:" -#~ msgid "Could not fix up function pointers to the DLL!" -#~ msgstr "Ei voitu korjata funktio-osoittimia DLL:ssไ" +#~ msgid "Encoding:" +#~ msgstr "Koodaus:" -#~ msgid "shell returned %d" -#~ msgstr "kuori palautti arvon %d" +#~ msgid "Show size in Points" +#~ msgstr "Nรคytรค koko pisteinรค" -#~ msgid "Vim: Caught %s event\n" -#~ msgstr "Vim: Napattiin %s\n" +#~ msgid "Name:" +#~ msgstr "Nimi:" -#~ msgid "close" -#~ msgstr "sulkeminen" +#~ msgid "Vim - Font Selector" +#~ msgstr "Vim - fonttivalitsin" -#~ msgid "logoff" -#~ msgstr "uloskirjautuminen" +#~ msgid "no specific match" +#~ msgstr "ei tarkkaa tรคsmรคystรค" -#~ msgid "shutdown" -#~ msgstr "sammutus" +#~ msgid "&Dismiss" +#~ msgstr "&Ohita" -#~ msgid "E371: Command not found" -#~ msgstr "E371: Komentoa ei l๖ydy" +#~ msgid "Invalid font specification" +#~ msgstr "Virheellinen fonttimรครคritys" + +#~ msgid "Font1 width: %ld" +#~ msgstr "Fontti1:n leveys: %ld" + +#~ msgid "Font0 width: %ld" +#~ msgstr "Fontti0:n leveys: %ld" + +#~ msgid "Font%ld width is not twice that of font0" +#~ msgstr "Fontti%ld:n leveys ei ole kaksi kertaa fontti0:n" + +#~ msgid "Font1: %s" +#~ msgstr "Fontti1: %s" + +#~ msgid "Font0: %s" +#~ msgstr "Fontti0: %s" + +#~ msgid "E253: Fontset name: %s" +#~ msgstr "E253: Fontsetin nimi: %s" + +#~ msgid "Font '%s' is not fixed-width" +#~ msgstr "Fontti %s ei ole tasavรคlinen" + +#~ msgid "E252: Fontset name: %s" +#~ msgstr "E252: Fontsetin nimi: %s" + +#~ msgid "E250: Fonts for the following charsets are missing in fontset %s:" +#~ msgstr "E250: Seuraavien merkistรถjoukkojen fontit puuttuvat fontsetistรค %s:" #~ msgid "" -#~ "VIMRUN.EXE not found in your $PATH.\n" -#~ "External commands will not pause after completion.\n" -#~ "See :help win32-vimrun for more information." +#~ "Vim E458: Cannot allocate colormap entry, some colors may be incorrect" #~ msgstr "" -#~ "VIMRUN.EXEไ ei l๖ydy muuttujasta $PATH.\n" -#~ "Ulkoiset komennot eivไt pysไhdy suorituksen lopussa.\n" -#~ "Lisไtietoja komennolla :help win32-vimrun" +#~ "Vim E458: Ei voi varata vรคrikartan alkiota, vรคrit voivat mennรค vรครคrin" -#~ msgid "Vim Warning" -#~ msgstr "Vim-varoitus" +# MDI eli windowsin moni-ikkunasovellus +#~ msgid "E672: Unable to open window inside MDI application" +#~ msgstr "E672: Ikkunaa ei voitu avata MDI-sovellukseen" -#~ msgid "Error file" -#~ msgstr "Virhetiedosto" +# OLE on object linking and embedding pรฅ windowska +#~ msgid "E243: Argument not supported: \"-%s\"; Use the OLE version." +#~ msgstr "E243: Argumenttia ei tueta: -%s, kรคytรค OLE-versiota" -#~ msgid "Conversion in %s not supported" -#~ msgstr "Muutosta kohteessa %s ei tueta" +#~ msgid "Directory\t*.nothing\n" +#~ msgstr "Hakemisto\t*.nothing\n" -#~ msgid "E430: Tag file path truncated for %s\n" -#~ msgstr "E430: Tไgitiedoston polku katkaistu kohdassa %s\n" +#~ msgid "Not Used" +#~ msgstr "Ei kรคytรถssรค" -#~ msgid "new shell started\n" -#~ msgstr "uusi kuori avattu\n" +#~ msgid "Find & Replace (use '\\\\' to find a '\\')" +#~ msgstr "Etsi ja korvaa (\\\\:llรค lรถytรครค \\:t)" -#~ msgid "Used CUT_BUFFER0 instead of empty selection" -#~ msgstr "Kไytettiin CUT_BUFFER0:aa tyhjไn valinnan sijaan" +#~ msgid "Find string (use '\\\\' to find a '\\')" +#~ msgstr "Etsi merkkijonoa (\\\\:llรค lรถytรครค \\:t)" -#~ msgid "No undo possible; continue anyway" -#~ msgstr "Ei voi kumota, jatketaan silti" +#~ msgid "Open tab..." +#~ msgstr "Avaa vรคlilehti..." -#~ msgid "E832: Non-encrypted file has encrypted undo file: %s" -#~ msgstr "E832: Salaamattomalla tiedostolla on salattu kumoustiedosto: %s" +#~ msgid "&Undo" +#~ msgstr "&Kumoa" -#~ msgid "E826: Undo file decryption failed: %s" -#~ msgstr "E826: Kumoustiedoston purku epไonnistui: %s" +#~ msgid "Replace &All" +#~ msgstr "Korvaa k&aikki" -#~ msgid "E827: Undo file is encrypted: %s" -#~ msgstr "E827: Kumoustiedosto on salattu: %s" +#~ msgid "&Replace" +#~ msgstr "Ko&rvaa" -#~ msgid "" -#~ "\n" -#~ "MS-Windows 16/32-bit GUI version" -#~ msgstr "" -#~ "\n" -#~ "MS-Windows 16- t. 32-bittinen GUI-versio" +#~ msgid "Find &Next" +#~ msgstr "Hae &seuraava" -#~ msgid "" -#~ "\n" -#~ "MS-Windows 64-bit GUI version" -#~ msgstr "" -#~ "\n" -#~ "MS-Windows 64-bittinen GUI-versio" +#~ msgid "Selection" +#~ msgstr "Valinta" -#~ msgid "" -#~ "\n" -#~ "MS-Windows 32-bit GUI version" -#~ msgstr "" -#~ "\n" -#~ "MS-Windows 32-bittinen GUI-version" +#~ msgid "&OK" +#~ msgstr "&Ok" -#~ msgid " in Win32s mode" -#~ msgstr " Win32s-tilassa" +#~ msgid "Files" +#~ msgstr "Tiedostot" -#~ msgid " with OLE support" -#~ msgstr " OLE-tuella" +#~ msgid "&Help" +#~ msgstr "O&hje" -#~ msgid "" -#~ "\n" -#~ "MS-Windows 64-bit console version" -#~ msgstr "" -#~ "\n" -#~ "MS-Windows 32-bittinen konsoliversio" +#~ msgid "Filter" +#~ msgstr "Suodatus" -#~ msgid "" -#~ "\n" -#~ "MS-Windows 32-bit console version" -#~ msgstr "" -#~ "\n" -#~ "MS-Windows 32-bittinen konsoliversio" +#~ msgid "Directories" +#~ msgstr "Hakemistot" -#~ msgid "" -#~ "\n" -#~ "MS-Windows 16-bit version" -#~ msgstr "" -#~ "\n" -#~ "MS-Windows 16-bittinen versio" +#~ msgid "&Cancel" +#~ msgstr "&Peru" -#~ msgid "" -#~ "\n" -#~ "32-bit MS-DOS version" -#~ msgstr "" -#~ "\n" -#~ "32-bittinen MS-DOS-versio" +#~ msgid "&Filter" +#~ msgstr "&Suodata" -#~ msgid "" -#~ "\n" -#~ "16-bit MS-DOS version" -#~ msgstr "" -#~ "\n" -#~ "16-bittinen MS-DOS-versio" +#~ msgid "Vim: Main window unexpectedly destroyed\n" +#~ msgstr "Vim: Pรครคikkuna tuhoutui odottamatta\n" -#~ msgid "" -#~ "\n" -#~ "MacOS X (unix) version" -#~ msgstr "" -#~ "\n" -#~ "MacOS X-version (unix)" +#~ msgid "Open Tab..." +#~ msgstr "Avaa vรคlilehti..." -#~ msgid "" -#~ "\n" -#~ "MacOS X version" -#~ msgstr "" -#~ "\n" -#~ "MacOS X-version" +#~ msgid "New tab" +#~ msgstr "Uusi vรคlilehti" -#~ msgid "" -#~ "\n" -#~ "MacOS version" -#~ msgstr "" -#~ "\n" -#~ "MacOS-version" +#~ msgid "Close tab" +#~ msgstr "Sulje vรคlilehti" -#~ msgid "" -#~ "\n" -#~ "RISC OS version" -#~ msgstr "" -#~ "\n" -#~ "RISC OS-version" +#~ msgid "Vim: Received \"die\" request from session manager\n" +#~ msgstr "Vim: sessiomanageri lรคhetti die-pyynnรถn\n" -#~ msgid "" -#~ "\n" -#~ "OpenVMS version" -#~ msgstr "" -#~ "\n" -#~ "OpenVMS-version" +#~ msgid "_Close" +#~ msgstr "_Sulje" -#~ msgid "" -#~ "\n" -#~ "Big version " -#~ msgstr "" -#~ "\n" -#~ "Big-version " +#~ msgid "Replace All" +#~ msgstr "Korvaa kaikki" -#~ msgid "" -#~ "\n" -#~ "Normal version " -#~ msgstr "" -#~ "\n" -#~ "Normal-versio " +#~ msgid "Replace" +#~ msgstr "Korvaa" -#~ msgid "" -#~ "\n" -#~ "Small version " -#~ msgstr "" -#~ "\n" -#~ "Small-versio " +#~ msgid "Find Next" +#~ msgstr "Etsi seuraava" -#~ msgid "" -#~ "\n" -#~ "Tiny version " -#~ msgstr "" -#~ "\n" -#~ "Tiny-versio " +#~ msgid "Down" +#~ msgstr "Alas" -#~ msgid "with GTK2-GNOME GUI." -#~ msgstr "GTK2-Gnome-GUIlla." +#~ msgid "Up" +#~ msgstr "Ylรถs" -#~ msgid "with GTK2 GUI." -#~ msgstr "GTK2-GUIlla." +#~ msgid "Direction" +#~ msgstr "Suunta" -#~ msgid "with X11-Motif GUI." -#~ msgstr "X11-Motif-GUIlla." +#~ msgid "Match case" +#~ msgstr "Kirjaintaso" -#~ msgid "with X11-neXtaw GUI." -#~ msgstr "X11-neXtaw-GUIlla." +#~ msgid "Match whole word only" +#~ msgstr "Korvaa kokonaisia sanoja" -#~ msgid "with X11-Athena GUI." -#~ msgstr "X11-Athena-GUIlla." +#~ msgid "Replace with:" +#~ msgstr "Korvaa:" -#~ msgid "with Photon GUI." -#~ msgstr "Photon-GUIlla." +#~ msgid "Find what:" +#~ msgstr "Etsi:" -#~ msgid "with GUI." -#~ msgstr "GUIlla." +#~ msgid "VIM - Search..." +#~ msgstr "VIM - Etsi..." -#~ msgid "with Carbon GUI." -#~ msgstr "Carbon-GUIlla." +#~ msgid "VIM - Search and Replace..." +#~ msgstr "VIM - Etsi ja korvaa..." -#~ msgid "with Cocoa GUI." -#~ msgstr "Cocoa-GUIlla." +#~ msgid "Input _Methods" +#~ msgstr "Syรถte_menetelmรคt" -#~ msgid "with (classic) GUI." -#~ msgstr "perinteisellไ GUIlla." +#~ msgid "No" +#~ msgstr "Ei" -#~ msgid " system gvimrc file: \"" -#~ msgstr " jไrjestelmไn gvimrc: \"" +#~ msgid "Yes" +#~ msgstr "Kyllรค" -#~ msgid " user gvimrc file: \"" -#~ msgstr " kไyttไjไn gvimrc: \"" +#~ msgid "_OK" +#~ msgstr "_OK" -#~ msgid "2nd user gvimrc file: \"" -#~ msgstr "2. kไyttไjไn gvimrc: \"" +#~ msgid "_Open" +#~ msgstr "_Avaa" -#~ msgid "3rd user gvimrc file: \"" -#~ msgstr "3. kไyttไjไn gvimrc: \"" +#~ msgid "_Save" +#~ msgstr "_Tallenna" -#~ msgid " system menu file: \"" -#~ msgstr " jไrjestelmไvalikko: \"" +#~ msgid "_Cancel" +#~ msgstr "_Peru" -#~ msgid "Compiler: " -#~ msgstr "Kไไnnin: " +#~ msgid "E232: Cannot create BalloonEval with both message and callback" +#~ msgstr "E232: Ei voi luoda BalloonEvalia viestille ja callbackille" -#~ msgid "menu Help->Orphans for information " -#~ msgstr "valikko Ohje->Orvot lisไtietoja varten " +#~ msgid "Vim dialog" +#~ msgstr "Vim-ikkuna" -#~ msgid "Running modeless, typed text is inserted" -#~ msgstr "Suoritetaan tilattomana, kirjoitettu teksti sy๖tetไไn" +#~ msgid "Scrollbar Widget: Could not get geometry of thumb pixmap." +#~ msgstr "Vierityspalkki: Pixmapin geometria ei selviรค" -#~ msgid "menu Edit->Global Settings->Toggle Insert Mode " -#~ msgstr "valikko Muokkaa->Yleiset asetukset->Vaihda sy๖tetilaa" +#~ msgid "Cancel" +#~ msgstr "Peru" -#~ msgid " for two modes " -#~ msgstr " kahta tilaa varten " +#~ msgid "OK" +#~ msgstr "OK" -#~ msgid "menu Edit->Global Settings->Toggle Vi Compatible" -#~ msgstr "valikko Muokkaa->Yleiset asetukset->Vaihda Vi-yhteensopivuutta" +#~ msgid "E615: vim_SelFile: can't get current directory" +#~ msgstr "E615: vim_SelFile: nykyistรค hakemistoa ei saada selville" -#~ msgid " for Vim defaults " -#~ msgstr " Vim-oletuksia varten" +#~ msgid "Pathname:" +#~ msgstr "Polku:" -#~ msgid "WARNING: Windows 95/98/ME detected" -#~ msgstr "VAROITUS: Window 95/98/ME havaittu" +#~ msgid "E614: vim_SelFile: can't return to current directory" +#~ msgstr "E614: vim_SelFile: nykyiseen hakemistoon ei voi palata" -#~ msgid "type :help windows95<Enter> for info on this" -#~ msgstr "kirjoita :help windows95<Enter> lisไtietoja varten" +#~ msgid "E616: vim_SelFile: can't get font %s" +#~ msgstr "E616: vim_SelFile: ei saada fonttia %s" -#~ msgid "E370: Could not load library %s" -#~ msgstr "E370: Kirjaston %s lataaminen ei onnistu" +#~ msgid "<cannot open> " +#~ msgstr "<ei voi avata> " + +#~ msgid "No match at cursor, finding next" +#~ msgstr "Ei tรคsmรคystรค kursorin alla, etsitรครคn seuraava" + +#~ msgid "E599: Value of 'imactivatekey' is invalid" +#~ msgstr "E599: imactivatekeyn arvo on virheellinen" + +#~ msgid "E231: 'guifontwide' invalid" +#~ msgstr "E231: guifontwide virheellinen" + +#~ msgid "E665: Cannot start GUI, no valid font found" +#~ msgstr "E665: Ei voi avata GUIta, sopivaa fonttia ei lรถydy" + +#~ msgid "E230: Cannot read from \"%s\"" +#~ msgstr "E230: Ei voi lukea kohteesta %s" + +#~ msgid "E229: Cannot start the GUI" +#~ msgstr "E229: GUIn kรคynnistys ei onnistu" + +#~ msgid "E851: Failed to create a new process for the GUI" +#~ msgstr "E851: Ei voitu luoda uutta prosessia kรคyttรถliittymรคlle" + +# tietรครคkseni resurssiforkki on applen tiedostojรคrjestelmรคn tunnistejuttujuttu +#~ msgid "E460: The resource fork would be lost (add ! to override)" +#~ msgstr "E460: resurssiosa hรคviรคisi (lisรครค komentoon ! ohittaaksesi)" + +#~ msgid "writing to device disabled with 'opendevice' option" +#~ msgstr "laitteeseen kirjoittaminen pois kรคytรถstรค opendevice-asetuksella" + +#~ msgid "Partial writes disallowed for NetBeans buffers" +#~ msgstr "Osittaiset kirjoitukset kielletty NetBeans-puskureissa" + +#~ msgid "NetBeans disallows writes of unmodified buffers" +#~ msgstr "NetBeans ei salli kirjoittaa muokkaamattomiin puskureihin" + +#~ msgid "Reading from stdin..." +#~ msgstr "Luetaan vakiosyรถtteestรค" + +#~ msgid "Vim: Reading from stdin...\n" +#~ msgstr "Vim: Luetaan vakiosyรถtteestรค...\n" + +#~ msgid "is a device (disabled with 'opendevice' option)" +#~ msgstr "on laite (ei kรคytรถssรค opendevice-asetuksen takia)" + +#~ msgid "Debug Line" +#~ msgstr "Vianetsintรคrivi" + +#~ msgid "Input Line" +#~ msgstr "Syรถterivi" + +#~ msgid "Expression" +#~ msgstr "Ilmaus" + +#~ msgid "Search String" +#~ msgstr "Hakujono" + +#~ msgid "Command Line" +#~ msgstr "Komentorivi" #~ msgid "" -#~ "Sorry, this command is disabled: the Perl library could not be loaded." -#~ msgstr "Sori, komento ei toimi, Perl kirjastoa ei voinut ladata." +#~ "\n" +#~ "# %s History (newest to oldest):\n" +#~ msgstr "" +#~ "\n" +#~ "# %s Historia (uusimmasta alkaen):\n" -#~ msgid "E299: Perl evaluation forbidden in sandbox without the Safe module" -#~ msgstr "E299: Perl-suoritus kielletty hiekkalaatikossa ilman Safe-moduulia" +#~ msgid "E196: No digraphs in this version" +#~ msgstr "E196: Digraafeja ei ole tรคssรค versiossa" -#~ msgid "Edit with &multiple Vims" -#~ msgstr "&Muokkaa usealla Vimillไ" +#~ msgid "E195: Cannot open viminfo file for reading" +#~ msgstr "E195: Viminfoa ei voi avata lukemista varten" -#~ msgid "Edit with single &Vim" -#~ msgstr "Muokkaa yhdellไ &Vimillไ" +#~ msgid "E809: #< is not available without the +eval feature" +#~ msgstr "E809: #< ei ole kรคytรถssรค jollei +eval ole pรครคllรค" -#~ msgid "Diff with Vim" -#~ msgstr "Diffi Vimillไ" +#~ msgid "Save Setup" +#~ msgstr "Tallenna asetukset" -#~ msgid "Edit with &Vim" -#~ msgstr "Muokkaa &Vimillไ" +#~ msgid "Save Session" +#~ msgstr "Tallenna sessio" -#~ msgid "Edit with existing Vim - " -#~ msgstr "Muokkaa olemassaolevalla Vimillไ - " +#~ msgid "Save View" +#~ msgstr "Tallenna nรคkymรค" -#~ msgid "Edits the selected file(s) with Vim" -#~ msgstr "Muokkaa valittuja tiedostoja Vimillไ" +#~ msgid "Save Redirection" +#~ msgstr "Tallenna uudelleenosoitus" -#~ msgid "Error creating process: Check if gvim is in your path!" -#~ msgstr "Virhe prosessin kไynnistไmisessไ, varmista ettไ gvim on polulla" +#~ msgid "E930: Cannot use :redir inside execute()" +#~ msgstr "E930: Komentoa :redir ei voi kรคyttรครค funktion execute() sisรคllรค" -#~ msgid "gvimext.dll error" -#~ msgstr "gvimext.dll-virhe" +#~ msgid "E466: :winpos requires two number arguments" +#~ msgstr "E466: :winpos vaatii kaksi lukuargumenttia" -#~ msgid "Path length too long!" -#~ msgstr "Liian pitkไ polku" +#~ msgid "E188: Obtaining window position not implemented for this platform" +#~ msgstr "E188: Ikkunan sijainnin selvitys ei toimi tรคllรค alustalla" -#~ msgid "E234: Unknown fontset: %s" -#~ msgstr "E234: Tuntematon fontset: %s" +#~ msgid "Window position: X %d, Y %d" +#~ msgstr "Ikkunan sijainti: X %d, Y %d" -#~ msgid "E235: Unknown font: %s" -#~ msgstr "E235: Tuntematon fontti: %s" +#~ msgid "" +#~ "E747: Cannot change directory, buffer is modified (add ! to override)" +#~ msgstr "" +#~ "E747: Hakemistoa ei voida muuttaa, puskuria on muokattu (lisรครค " +#~ "komentoon ! ohittaaksesi" -#~ msgid "E236: Font \"%s\" is not fixed-width" -#~ msgstr "E236: Fontti %s ei ole tasavไlinen" +#~ msgid "Append File" +#~ msgstr "Lisรครค tiedostoon" -#~ msgid "E448: Could not load library function %s" -#~ msgstr "E448: Ei voitu ladta kirjastofunktiota %s" +#~ msgid "Edit File in new window" +#~ msgstr "Muokkaa uudessa ikkunassa" -#~ msgid "E26: Hebrew cannot be used: Not enabled at compile time\n" -#~ msgstr "E26: Hepreaa ei voi kไyttไไ, koska sitไ ei kไไnnetty mukaan\n" +#~ msgid "unknown" +#~ msgstr "tuntematon" -#~ msgid "E27: Farsi cannot be used: Not enabled at compile time\n" -#~ msgstr "E27: Farsia ei voi kไyttไไ, koska sitไ ei kไไnnetty mukaan\n" +#~ msgid "E172: Only one file name allowed" +#~ msgstr "E172: Vain yksi tiedostonimi sallitaan" -#~ msgid "E800: Arabic cannot be used: Not enabled at compile time\n" -#~ msgstr "E800: Arabiaa ei voi kไyttไไ, koska sitไ ei kไไnnetty mukaan\n" +#~ msgid "Source Vim script" +#~ msgstr "Lataa vim-skripti" -#~ msgid "E247: no registered server named \"%s\"" -#~ msgstr "E247: palvelinta %s ei ole rekister๖itynไ" +#~ msgid " (NOT FOUND)" +#~ msgstr " (EI LรYTYNYT)" -#~ msgid "E233: cannot open display" -#~ msgstr "E233: nไytt๖ไ ei voi avata" +#~ msgid "" +#~ "\n" +#~ "# Last Substitute String:\n" +#~ "$" +#~ msgstr "" +#~ "\n" +#~ "# Viimeisin korvausmerkkijono:\n" +#~ "$" -#~ msgid "E449: Invalid expression received" -#~ msgstr "E449: Virheellinen ilmaus saatu" +#~ msgid "Edit File" +#~ msgstr "Muokkaa tiedostoa" -#~ msgid "E463: Region is guarded, cannot modify" -#~ msgstr "E463: Alue on suojattu, muuttaminen ei onnistu" +#~ msgid "Save As" +#~ msgstr "Tallenna nimellรค" -#~ msgid "E744: NetBeans does not allow changes in read-only files" -#~ msgstr "E744: NetBeans ei tue muutoksia kirjoitussuojattuihin tiedostoihin" +#~ msgid "" +#~ "\n" +#~ "# Bar lines, copied verbatim:\n" +#~ msgstr "" +#~ "\n" +#~ "# Bar-rivit, kopiotu sellaisenaan:\n" -#~ msgid "Need encryption key for \"%s\"" -#~ msgstr "Tarvitaan salausavain kohteelle %s " +#~ msgid "Illegal starting char" +#~ msgstr "Virheellinen aloitusmerkki" -#~ msgid "writelines() requires list of strings" -#~ msgstr "writelines()-komennolle pitไไ antaa merkkijonolista" +#~ msgid "# Value of 'encoding' when this file was written\n" +#~ msgstr "# encoding-muuttujan arvo tiedostoa kirjoitettaessa\n" -#~ msgid "E264: Python: Error initialising I/O objects" -#~ msgstr "E264: Python: Virhe IO-olioiden alustuksessa" +#~ msgid "" +#~ "# You may edit it if you're careful!\n" +#~ "\n" +#~ msgstr "" +#~ "# Muokkaa varovasti!\n" +#~ "\n" -#~ msgid "no such buffer" -#~ msgstr "puskuria ei ole" +#~ msgid "# This viminfo file was generated by Vim %s.\n" +#~ msgstr "# Vimin %s generoima viminfo-tiedosto.\n" -#~ msgid "attempt to refer to deleted window" -#~ msgstr "yritettiin viitata poistettuun ikkunaan" +#~ msgid "E138: Can't write viminfo file %s!" +#~ msgstr "E138: Viminfo-tiedoston kirjoittaminen ei onnistu %s" -#~ msgid "readonly attribute" -#~ msgstr "kirjoitussuojattu attribuutti" +#~ msgid "E929: Too many viminfo temp files, like %s!" +#~ msgstr "E929: liikaa viminfo-vรคliaikaistiedostoja, kuten %s." -#~ msgid "cursor position outside buffer" -#~ msgstr "kursorin sijainti puskurin ulkopuolella" +#~ msgid "E136: viminfo: Too many errors, skipping rest of file" +#~ msgstr "E136: viminfo: liikaa virheitรค, ohitetaan lopputiedosto" -#~ msgid "<window object (deleted) at %p>" -#~ msgstr "<ikkunaolio (poistettu) kohdassa %p>" +#~ msgid "%sviminfo: %s in line: " +#~ msgstr "%sviminfo: %s rivillรค: " -#~ msgid "<window object (unknown) at %p>" -#~ msgstr "<ikkunaolio (tuntematon) kohdassa %p>" +#~ msgid "E258: Unable to send to client" +#~ msgstr "E258: Asiakkaalle lรคhetys ei onnistunut" -#~ msgid "<window %d>" -#~ msgstr "<ikkuna %d>" +#~ msgid "E277: Unable to read a server reply" +#~ msgstr "E277: Palvelimen vastauksen lukeminen ei onnistunut" -#~ msgid "no such window" -#~ msgstr "ikkunaa ei ole" +#~ msgid "E240: No connection to Vim server" +#~ msgstr "E240: Ei yhteyttรค vim-palvelimeen" -#~ msgid "attempt to refer to deleted buffer" -#~ msgstr "yritettiin viitata poistettuun puskuriin" +#~ msgid "" +#~ "&OK\n" +#~ "&Cancel" +#~ msgstr "" +#~ "&OK\n" +#~ "&Peru" + +#~ msgid "" +#~ "\n" +#~ "# global variables:\n" +#~ msgstr "" +#~ "\n" +#~ "# globaalit muuttujat:\n" + +#~ msgid "E729: using Funcref as a String" +#~ msgstr "E729: Funcref ei kรคy merkkijonosta" + +#~ msgid "E914: Using a Channel as a Float" +#~ msgstr "E914: Kรคytettiin Channelia Floattina" + +#~ msgid "E911: Using a Job as a Float" +#~ msgstr "E911: Job ei kรคy Floatista" + +#~ msgid "E913: Using a Channel as a Number" +#~ msgstr "E913: Channel ei kรคy Numberista" + +#~ msgid "E910: Using a Job as a Number" +#~ msgstr "E910: Job ei kรคy Numberista" + +#~ msgid "E703: Using a Funcref as a Number" +#~ msgstr "E703: Funcref ei kรคy Numberista" + +#~ msgid "E724: variable nested too deep for displaying" +#~ msgstr "E724: muuttuja on upotettu liian syvรคlle nรคytettรคvรคksi" + +#~ msgid "Patch file" +#~ msgstr "Patch-tiedosto" + +#~ msgid "[crypted]" +#~ msgstr "[salattu]" + +#~ msgid "Keys don't match!" +#~ msgstr "Avaimet eivรคt tรคsmรครค!" -# New Line eli uusi rivinvaihtomerkki (ei CR, LF tai CR LF) -#~ msgid "[NL found]" -#~ msgstr "[NL puuttuu]" +#~ msgid "Enter same key again: " +#~ msgstr "Anna sama avain uudestaan: " -#~ msgid "Vim dialog..." -#~ msgstr "Vim-ikkuna..." +#~ msgid "Enter encryption key: " +#~ msgstr "Anna salausavain: " -#~ msgid "Font Selection" -#~ msgstr "Fontin valinta" +#~ msgid "Warning: Using a weak encryption method; see :help 'cm'" +#~ msgstr "Varoitus: Kรคytetรครคn heikkoa salausmenetelmรครค, ks. :help 'cm'" -#~ msgid "E569: maximum number of cscope connections reached" -#~ msgstr "E569: enimmไismไไrไ cscope-yhteyksiไ otettu" +#~ msgid "E821: File is encrypted with unknown method" +#~ msgstr "E821: Tiedoston salaus on tuntematon" + +#~ msgid "E918: buffer must be loaded: %s" +#~ msgstr "E918: puskuria ei voi ladata: %s" + +#~ msgid "E915: in_io buffer requires in_buf or in_name to be set" +#~ msgstr "E915: in_io-puskurilla pitรครค olla in_buf tai in_name asetettu" -#~ msgid "-name <name>\t\tUse resource as if vim was <name>" -#~ msgstr "-name <nimi>\t\tKไytไ resurssia vim <nimenไ>" +#~ msgid "E920: _io file requires _name to be set" +#~ msgstr "E920: _io-tiedostolla pitรครค olla _name asetettu" -#~ msgid "\t\t\t (Unimplemented)\n" -#~ msgstr "\t\t\t (toteuttamatta)\n" +#~ msgid "E906: not an open channel" +#~ msgstr "E906: ei ole avoin kanava" + +#~ msgid "" +#~ "E912: cannot use ch_evalexpr()/ch_sendexpr() with a raw or nl channel" +#~ msgstr "" +#~ "E912: ei voida kรคyttรครค funktioita ch_evalexpr(), ch_sendexpr() raa'an tai " +#~ "nl-kanavan kanssa" -#~ msgid "E290: over-the-spot style requires fontset" -#~ msgstr "E290: over-the-spot-tyylissไ pitไไ olla fontset" +#~ msgid "E917: Cannot use a callback with %s()" +#~ msgstr "E917: Ei voitu kรคyttรครค callbackia %s()" -#~ msgid "E291: Your GTK+ is older than 1.2.3. Status area disabled" -#~ msgstr "E291: GTK+-versio vanhempi kuin 1.2.3: Tila-alue poistettu kไyt๖stไ" +#~ msgid "" +#~ "\n" +#~ "# Buffer list:\n" +#~ msgstr "" +#~ "\n" +#~ "# Puskuriluettelo:\n" -#~ msgid "E292: Input Method Server is not running" -#~ msgstr "E292: Sy๖temetodipalvelin ei ole kไynnissไ" +#~ msgid "E931: Buffer cannot be registered" +#~ msgstr "E931: Puskuria ei voi rekisterรถidรค" -#~ msgid "E396: containedin argument not accepted here" -#~ msgstr "E396: containedin ei sovi tไhไn" +#~ msgid "E819: Blowfish test failed" +#~ msgstr "E819: Blowfish-testi epรคonnistui" -#~ msgid "with GTK-GNOME GUI." -#~ msgstr "GTK-Gnome-GUIlla." +#~ msgid "E818: sha256 test failed" +#~ msgstr "E818: sha256-testi epรคonnistui failed" -#~ msgid "with GTK GUI." -#~ msgstr "GTK-GUIlla." +#~ msgid "E817: Blowfish big/little endian use wrong" +#~ msgstr "E817: Blowfishin tavujรคrjestys vรครคrรค" -#~ msgid "-V[N]\t\tVerbose level" -#~ msgstr "-V[N]\t\tMonisanaisuustaso" +#~ msgid "E820: sizeof(uint32_t) != 4" +#~ msgstr "E820: sizeof(uint32_t) != 4" -#~ msgid "...(truncated)" -#~ msgstr "...(katkaistu)" +#~ msgid "E831: bf_key_init() called with empty password" +#~ msgstr "E831: bf_key_init() tyhjรคllรค salasanalla" diff --git a/src/nvim/po/fr.po b/src/nvim/po/fr.po index bf0610de02..c0df5f2170 100644 --- a/src/nvim/po/fr.po +++ b/src/nvim/po/fr.po @@ -1,3 +1,4 @@ + # French Translation for Vim # # Do ":help uganda" in Vim to read copying and usage conditions. @@ -6,7 +7,7 @@ # FIRST AUTHOR DindinX <David.Odin@bigfoot.com> 2000. # SECOND AUTHOR Adrien Beau <version.francaise@free.fr> 2002, 2003. # THIRD AUTHOR David Blanchet <david.blanchet@free.fr> 2006, 2008. -# FOURTH AUTHOR Dominique Pell้ <dominique.pelle@gmail.com> 2008, 2015. +# FOURTH AUTHOR Dominique Pell้ <dominique.pelle@gmail.com> 2008, 2017. # # Latest translation available at: # http://dominique.pelle.free.fr/vim-fr.php @@ -15,8 +16,8 @@ msgid "" msgstr "" "Project-Id-Version: Vim(Fran็ais)\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-07-30 17:54+0200\n" -"PO-Revision-Date: 2015-07-30 18:00+0200\n" +"POT-Creation-Date: 2017-01-16 00:30+0100\n" +"PO-Revision-Date: 2017-01-16 00:51+0100\n" "Last-Translator: Dominique Pell้ <dominique.pelle@gmail.com>\n" "Language-Team: \n" "Language: fr\n" @@ -24,201 +25,172 @@ msgstr "" "Content-Type: text/plain; charset=ISO_8859-15\n" "Content-Transfer-Encoding: 8bit\n" -#: ../api/private/helpers.c:201 -#, fuzzy -msgid "Unable to get option value" -msgstr "impossible d'obtenir la valeur d'une option" +msgid "E831: bf_key_init() called with empty password" +msgstr "E831: bf_key_init() appel้e avec un mot de passe vide" -#: ../api/private/helpers.c:204 -#, fuzzy -msgid "internal error: unknown option type" -msgstr "erreur interne : pas d'้l้ment de liste vim" +msgid "E820: sizeof(uint32_t) != 4" +msgstr "E820: sizeof(uint32_t) != 4" + +msgid "E817: Blowfish big/little endian use wrong" +msgstr "E817: petit/gros boutisme incorrect dans blowfish" + +msgid "E818: sha256 test failed" +msgstr "E818: le test de sha256 a ้chou้" + +msgid "E819: Blowfish test failed" +msgstr "E819: le test de blowfish a ้chou้" # DB - TODO : Trouver une traduction valable et attest้e pour "location". -#: ../buffer.c:92 msgid "[Location List]" msgstr "[Liste des emplacements]" -#: ../buffer.c:93 msgid "[Quickfix List]" msgstr "[Liste Quickfix]" -#: ../buffer.c:94 msgid "E855: Autocommands caused command to abort" msgstr "E855: Des autocommandes ont caus้ la terminaison de la commande" # AB - Il faut respecter l'esprit plus que la lettre. -#: ../buffer.c:135 msgid "E82: Cannot allocate any buffer, exiting..." msgstr "E82: Aucun tampon ne peut ๊tre allou้, Vim doit s'arr๊ter" # AB - La situation est probablement plus grave que la version anglaise ne le # laisse entendre (voir l'aide en ligne). La version fran็aise est plus # explicite. -#: ../buffer.c:138 msgid "E83: Cannot allocate buffer, using other one..." msgstr "" "E83: L'allocation du tampon a ้chou้ : arr๊tez Vim, lib้rez de la m้moire" -#: ../buffer.c:763 +msgid "E931: Buffer cannot be registered" +msgstr "E931: Le tampon ne peut pas ๊tre enregistr้" + +msgid "E937: Attempt to delete a buffer that is in use" +msgstr "E937: Tentative de suppression d'un tampon en cours d'utilisation" + msgid "E515: No buffers were unloaded" msgstr "E515: Aucun tampon n'a ้t้ d้charg้" -#: ../buffer.c:765 msgid "E516: No buffers were deleted" msgstr "E516: Aucun tampon n'a ้t้ effac้" -#: ../buffer.c:767 msgid "E517: No buffers were wiped out" msgstr "E517: Aucun tampon n'a ้t้ d้truit" -#: ../buffer.c:772 msgid "1 buffer unloaded" msgstr "1 tampon a ้t้ d้charg้" -#: ../buffer.c:774 #, c-format msgid "%d buffers unloaded" msgstr "%d tampons ont ้t้ d้charg้s" -#: ../buffer.c:777 msgid "1 buffer deleted" msgstr "1 tampon a ้t้ effac้" -#: ../buffer.c:779 #, c-format msgid "%d buffers deleted" msgstr "%d tampons ont ้t้ effac้s" -#: ../buffer.c:782 msgid "1 buffer wiped out" msgstr "1 tampon a ้t้ d้truit" -#: ../buffer.c:784 #, c-format msgid "%d buffers wiped out" msgstr "%d tampons ont ้t้ d้truits" -#: ../buffer.c:806 msgid "E90: Cannot unload last buffer" msgstr "E90: Impossible de d้charger le dernier tampon" # AB - La version fran็aise est meilleure que la version anglaise. -#: ../buffer.c:874 msgid "E84: No modified buffer found" msgstr "E84: Aucun tampon n'est modifi้" #. back where we started, didn't find anything. -#: ../buffer.c:903 msgid "E85: There is no listed buffer" msgstr "E85: Aucun tampon n'est list้" # AB - Je ne suis pas s๛r que l'on puisse obtenir ce message. -#: ../buffer.c:915 msgid "E87: Cannot go beyond last buffer" msgstr "E87: Impossible d'aller apr่s le dernier tampon" # AB - Je ne suis pas s๛r que l'on puisse obtenir ce message. -#: ../buffer.c:917 msgid "E88: Cannot go before first buffer" msgstr "E88: Impossible d'aller avant le premier tampon" -#: ../buffer.c:945 #, c-format -msgid "" -"E89: No write since last change for buffer %<PRId64> (add ! to override)" +msgid "E89: No write since last change for buffer %ld (add ! to override)" msgstr "" -"E89: Le tampon %<PRId64> n'a pas ้t้ enregistr้ (ajoutez ! pour passer outre)" +"E89: Le tampon %ld n'a pas ้t้ enregistr้ (ajoutez ! pour passer outre)" -#. wrap around (may cause duplicates) -#: ../buffer.c:1423 msgid "W14: Warning: List of file names overflow" msgstr "W14: Alerte : La liste des noms de fichier d้borde" # AB - Vu le code source, la version fran็aise est meilleure que la # version anglaise. Ce message est similaire au message E86. -#: ../buffer.c:1555 ../quickfix.c:3361 #, c-format -msgid "E92: Buffer %<PRId64> not found" -msgstr "E92: Le tampon %<PRId64> n'existe pas" +msgid "E92: Buffer %ld not found" +msgstr "E92: Le tampon %ld n'existe pas" # AB - Il faut respecter l'esprit plus que la lettre. -#: ../buffer.c:1798 #, c-format msgid "E93: More than one match for %s" msgstr "E93: Plusieurs tampons correspondent เ %s" -#: ../buffer.c:1800 #, c-format msgid "E94: No matching buffer for %s" msgstr "E94: Aucun tampon ne correspond เ %s" -#: ../buffer.c:2161 #, c-format -msgid "line %<PRId64>" -msgstr "ligne %<PRId64>" +msgid "line %ld" +msgstr "ligne %ld" -#: ../buffer.c:2233 msgid "E95: Buffer with this name already exists" msgstr "E95: Un tampon porte d้jเ ce nom" -#: ../buffer.c:2498 msgid " [Modified]" msgstr "[Modifi้]" # AB - "[In้dit้]" est plus correct, mais sonne faux. -#: ../buffer.c:2501 msgid "[Not edited]" msgstr "[Non ้dit้]" -#: ../buffer.c:2504 msgid "[New file]" msgstr "[Nouveau fichier]" -#: ../buffer.c:2505 msgid "[Read errors]" msgstr "[Erreurs de lecture]" -#: ../buffer.c:2506 ../buffer.c:3217 ../fileio.c:1807 ../screen.c:4895 msgid "[RO]" msgstr "[RO]" # AB - La version courte, "[RO]", devrait-elle ๊tre traduite par "[LS]" ? # Il faudrait faire un sondage aupr่s des utilisateurs francophones. -#: ../buffer.c:2507 ../fileio.c:1807 msgid "[readonly]" msgstr "[lecture-seule]" -#: ../buffer.c:2524 #, c-format msgid "1 line --%d%%--" msgstr "1 ligne --%d%%--" -#: ../buffer.c:2526 #, c-format -msgid "%<PRId64> lines --%d%%--" -msgstr "%<PRId64> lignes --%d%%--" +msgid "%ld lines --%d%%--" +msgstr "%ld lignes --%d%%--" # AB - Faut-il remplacer "sur" par "de" ? # DB - Mon avis : oui. -#: ../buffer.c:2530 #, c-format -msgid "line %<PRId64> of %<PRId64> --%d%%-- col " -msgstr "ligne %<PRId64> sur %<PRId64> --%d%%-- col " +msgid "line %ld of %ld --%d%%-- col " +msgstr "ligne %ld sur %ld --%d%%-- col " # DB - Je trouvais [Aucun fichier] (VO : [No file]) plus naturel # lors du lancement de Vim en mode graphique (ce message # appara๎t notamment dans le titre de la fen๊tre). -#: ../buffer.c:2632 ../buffer.c:4292 ../memline.c:1554 msgid "[No Name]" msgstr "[Aucun nom]" #. must be a help buffer -#: ../buffer.c:2667 msgid "help" msgstr "aide" -#: ../buffer.c:3225 ../screen.c:4883 msgid "[Help]" msgstr "[Aide]" @@ -226,24 +198,19 @@ msgstr "[Aide]" # traduction litt้rale et br่ve, mais qui risque fort d'๊tre mal comprise. # J'ai finalement choisi d'utiliser une abr้viation, mais cela ne me # satisfait pas. -#: ../buffer.c:3254 ../screen.c:4887 msgid "[Preview]" msgstr "[Pr้visu]" -#: ../buffer.c:3528 msgid "All" msgstr "Tout" -#: ../buffer.c:3528 msgid "Bot" msgstr "Bas" # AB - Attention, on passe de trois เ quatre lettres. -#: ../buffer.c:3531 msgid "Top" msgstr "Haut" -#: ../buffer.c:4244 msgid "" "\n" "# Buffer list:\n" @@ -251,11 +218,9 @@ msgstr "" "\n" "# Liste des tampons :\n" -#: ../buffer.c:4289 msgid "[Scratch]" msgstr "[Brouillon]" -#: ../buffer.c:4529 msgid "" "\n" "--- Signs ---" @@ -263,175 +228,220 @@ msgstr "" "\n" "--- Symboles ---" -#: ../buffer.c:4538 #, c-format msgid "Signs for %s:" msgstr "Symboles dans %s :" -#: ../buffer.c:4543 #, c-format -msgid " line=%<PRId64> id=%d name=%s" -msgstr " ligne=%<PRId64> id=%d nom=%s" +msgid " line=%ld id=%d name=%s" +msgstr " ligne=%ld id=%d nom=%s" -#: ../cursor_shape.c:68 -msgid "E545: Missing colon" -msgstr "E545: ':' manquant" +msgid "E902: Cannot connect to port" +msgstr "E902: Impossible de se connecter au port" -#: ../cursor_shape.c:70 ../cursor_shape.c:94 -msgid "E546: Illegal mode" -msgstr "E546: Mode non autoris้" +msgid "E901: gethostbyname() in channel_open()" +msgstr "E901: gethostbyname() dans channel_open()" -#: ../cursor_shape.c:134 -msgid "E548: digit expected" -msgstr "E548: chiffre attendu" +msgid "E898: socket() in channel_open()" +msgstr "E898: socket() dans channel_open()" -#: ../cursor_shape.c:138 -msgid "E549: Illegal percentage" -msgstr "E549: Pourcentage non autoris้" +msgid "E903: received command with non-string argument" +msgstr "E903: commande re็ue avec un argument qui n'est pas une cha๎ne" + +msgid "E904: last argument for expr/call must be a number" +msgstr "E904: le dernier argument de expr/call doit ๊tre un nombre" + +msgid "E904: third argument for call must be a list" +msgstr "E904: le troisi่me argument de \"call\" doit ๊tre une liste" + +#, c-format +msgid "E905: received unknown command: %s" +msgstr "E905: commande inconnue re็ue : %s" + +#, c-format +msgid "E630: %s(): write while not connected" +msgstr "E630: %s() : ้criture sans ๊tre connect้" + +#, c-format +msgid "E631: %s(): write failed" +msgstr "E631: %s() : erreur d'้criture" + +#, c-format +msgid "E917: Cannot use a callback with %s()" +msgstr "E917: Impossible d'utiliser un callback avec %s()" + +msgid "E912: cannot use ch_evalexpr()/ch_sendexpr() with a raw or nl channel" +msgstr "" +"E912: Impossible d'utiliser ch_evalexpr()/ch_sendexpr() avec un canal brut " +"ou nl" + +msgid "E906: not an open channel" +msgstr "E906: pas un canal ouvert" + +msgid "E920: _io file requires _name to be set" +msgstr "E920: fichier _io n้cessite _name" + +msgid "E915: in_io buffer requires in_buf or in_name to be set" +msgstr "E915: tampon in_io n้cessite in_buf ou in_name " + +#, c-format +msgid "E918: buffer must be loaded: %s" +msgstr "E918: le tampon doit ๊tre charg้ : %s" + +msgid "E821: File is encrypted with unknown method" +msgstr "E821: Le fichier est chiffr้ avec une m้thode inconnue" + +msgid "Warning: Using a weak encryption method; see :help 'cm'" +msgstr "" +"Alerte : utilisation d'une m้thode de chiffrage faible ; consultez :help 'cm'" + +msgid "Enter encryption key: " +msgstr "Tapez la cl้ de chiffrement : " + +msgid "Enter same key again: " +msgstr "Tapez la cl้ เ nouveau : " + +msgid "Keys don't match!" +msgstr "Les cl้s ne correspondent pas !" + +msgid "[crypted]" +msgstr "[chiffr้]" -# AB - Je n'ai pas trouv้ de traduction satisfaisante au verbe "diff". Comme -# Vim fait en pratique appel au programme "diff" pour evaluer les -# diff้rences entre fichiers, "to diff" a ้t้ traduit par "utiliser diff" -# et d'autres expressions appropri้es. -#: ../diff.c:146 #, c-format -msgid "E96: Can not diff more than %<PRId64> buffers" -msgstr "E96: Impossible d'utiliser diff sur plus de %<PRId64> tampons" +msgid "E720: Missing colon in Dictionary: %s" +msgstr "E720: Il manque ':' dans le Dictionnaire %s" + +#, c-format +msgid "E721: Duplicate key in Dictionary: \"%s\"" +msgstr "E721: Cl้ dupliqu้e dans le Dictionnaire : %s" + +#, c-format +msgid "E722: Missing comma in Dictionary: %s" +msgstr "E722: Il manque une virgule dans le Dictionnaire : %s" + +#, c-format +msgid "E723: Missing end of Dictionary '}': %s" +msgstr "E723: Il manque '}' เ la fin du Dictionnaire : %s" + +msgid "extend() argument" +msgstr "argument de extend()" + +#, c-format +msgid "E737: Key already exists: %s" +msgstr "E737: La cl้ existe d้jเ : %s" + +#, c-format +msgid "E96: Cannot diff more than %ld buffers" +msgstr "E96: Impossible d'utiliser diff sur plus de %ld tampons" -#: ../diff.c:753 msgid "E810: Cannot read or write temp files" msgstr "E810: Impossible de lire ou ้crire des fichiers temporaires" # AB - La version fran็aise est meilleure que la version anglaise. -#: ../diff.c:755 msgid "E97: Cannot create diffs" msgstr "E97: diff ne fonctionne pas" -#: ../diff.c:966 +msgid "Patch file" +msgstr "Fichier rustine" + msgid "E816: Cannot read patch output" msgstr "E816: Le fichier interm้diaire produit par patch n'a pu ๊tre lu" -#: ../diff.c:1220 msgid "E98: Cannot read diff output" msgstr "E98: Le fichier interm้diaire produit par diff n'a pu ๊tre lu" -#: ../diff.c:2081 msgid "E99: Current buffer is not in diff mode" msgstr "E99: Le tampon courant n'est pas en mode diff" -#: ../diff.c:2100 msgid "E793: No other buffer in diff mode is modifiable" msgstr "E793: Aucun autre tampon en mode diff n'est modifiable" -#: ../diff.c:2102 msgid "E100: No other buffer in diff mode" msgstr "E100: Aucun autre tampon n'est en mode diff" # AB - La version fran็aise est meilleure que la version anglaise, mais elle # peut ๊tre am้lior้e. -#: ../diff.c:2112 msgid "E101: More than two buffers in diff mode, don't know which one to use" msgstr "E101: Plus de deux tampons sont en mode diff, soyez plus pr้cis" -#: ../diff.c:2141 #, c-format msgid "E102: Can't find buffer \"%s\"" msgstr "E102: Le tampon %s est introuvable" -#: ../diff.c:2152 #, c-format msgid "E103: Buffer \"%s\" is not in diff mode" msgstr "E103: Le tampon %s n'est pas en mode diff" -#: ../diff.c:2193 msgid "E787: Buffer changed unexpectedly" msgstr "E787: Le tampon a ้t้ modifi้ inopin้ment" # AB - Je cherche une traduction plus concise pour "escape". -#: ../digraph.c:1598 msgid "E104: Escape not allowed in digraph" msgstr "E104: Un digraphe ne peut contenir le caract่re d'้chappement" # AB - La version fran็aise est trop verbeuse. -#: ../digraph.c:1760 msgid "E544: Keymap file not found" msgstr "E544: Le fichier descripteur de clavier est introuvable" # AB - La version fran็aise est meilleure que la version anglaise. -#: ../digraph.c:1785 msgid "E105: Using :loadkeymap not in a sourced file" msgstr "E105: :loadkeymap ne peut ๊tre utilis้ que dans un script Vim" -#: ../digraph.c:1821 msgid "E791: Empty keymap entry" msgstr "E791: Entr้e du descripteur de clavier (keymap) vide" # AB - Remplacer "compl้tion" par "compl่tement" ? Voir l'้thymologie # d'"accr้tion". -#: ../edit.c:82 msgid " Keyword completion (^N^P)" msgstr " Compl่tement de mot-cl้ (^N^P)" # DB - todo : Faut-il une majuscule เ "mode" ? #. ctrl_x_mode == 0, ^P/^N compl. -#: ../edit.c:83 msgid " ^X mode (^]^D^E^F^I^K^L^N^O^Ps^U^V^Y)" msgstr " mode ^X (^]^D^E^F^I^K^L^N^O^Ps^U^V^Y)" -#: ../edit.c:85 msgid " Whole line completion (^L^N^P)" msgstr " Compl่tement de ligne enti่re (^L^N^P)" -#: ../edit.c:86 msgid " File name completion (^F^N^P)" msgstr " Compl่tement de nom de fichier (^F^N^P)" -#: ../edit.c:87 msgid " Tag completion (^]^N^P)" msgstr " Compl่tement de marqueur (^]^N^P)" # AB - J'ai d๛ avoir une bonne raison de faire une version fran็aise aussi # diff้rente de la version anglaise. Il me faut la retrouver. # DB - TODO -#: ../edit.c:88 msgid " Path pattern completion (^N^P)" msgstr " Compl่tement global de mot-cl้ (^N^P)" -#: ../edit.c:89 msgid " Definition completion (^D^N^P)" msgstr " Compl่tement de d้finition (^D^N^P)" # AB - Trouver une meilleure formulation que "selon le". # DB : proposition : "avec" -#: ../edit.c:91 msgid " Dictionary completion (^K^N^P)" msgstr " Compl่tement avec le dictionnaire (^K^N^P)" # AB - Trouver une meilleure formulation que "selon le". -#: ../edit.c:92 msgid " Thesaurus completion (^T^N^P)" msgstr " Compl่tement avec le th้saurus (^T^N^P)" # AB - La version fran็aise est meilleure que la version anglaise. # DB : Suggestion. -#: ../edit.c:93 msgid " Command-line completion (^V^N^P)" msgstr " Compl่tement de ligne de commande (^V^N^P)" -#: ../edit.c:94 msgid " User defined completion (^U^N^P)" msgstr " Compl่tement d้fini par l'utilisateur (^U^N^P)" # DB : On doit pouvoir trouver nettement mieux que ็a. -#: ../edit.c:95 msgid " Omni completion (^O^N^P)" msgstr " Compl่tement selon le type de fichier (Omni) (^O^N^P)" -#: ../edit.c:96 msgid " Spelling suggestion (s^N^P)" msgstr " Suggestion d'orthographe (s^N^P)" -#: ../edit.c:97 msgid " Keyword Local completion (^N^P)" msgstr " Compl่tement local de mot-cl้ (^N/^P)" @@ -439,45 +449,35 @@ msgstr " Compl่tement local de mot-cl้ (^N/^P)" # Il faut ้viter de le faire trop long. Je pense que la version fran็aise # est suffisamment compr้hensible dans le contexte dans lequel elle est # affich้e. -#: ../edit.c:100 msgid "Hit end of paragraph" msgstr "Fin du paragraphe" -#: ../edit.c:101 msgid "E839: Completion function changed window" msgstr "E839: La fonction de compl่tement a chang้ la fen๊tre" -#: ../edit.c:102 msgid "E840: Completion function deleted text" msgstr "E840: La fonction de compl่tement a effac้ du texte" -#: ../edit.c:1847 msgid "'dictionary' option is empty" msgstr "L'option 'dictionary' est vide" -#: ../edit.c:1848 msgid "'thesaurus' option is empty" msgstr "L'option 'thesaurus' est vide" -#: ../edit.c:2655 #, c-format msgid "Scanning dictionary: %s" msgstr "Examen du dictionnaire : %s" -#: ../edit.c:3079 msgid " (insert) Scroll (^E/^Y)" msgstr " (insertion) D้filement (^E/^Y)" -#: ../edit.c:3081 msgid " (replace) Scroll (^E/^Y)" msgstr " (remplacement) D้filement (^E/^Y)" -#: ../edit.c:3587 #, c-format msgid "Scanning: %s" msgstr "Examen : %s" -#: ../edit.c:3614 msgid "Scanning tags." msgstr "Examen des marqueurs." @@ -485,7 +485,6 @@ msgstr "Examen des marqueurs." # op้ration de compl้tion est r้p้t้e (typiquement avec CTRL-X CTRL-N). # Que ce soit en anglais ou en fran็ais, il y a un probl่me de majuscules. # Bien qu'insatisfaisante, cette traduction semble optimale. -#: ../edit.c:4519 msgid " Adding" msgstr " Ajout" @@ -493,236 +492,138 @@ msgstr " Ajout" #. * be called before line = ml_get(), or when this address is no #. * longer needed. -- Acevedo. #. -#: ../edit.c:4562 msgid "-- Searching..." msgstr "-- Recherche en cours..." # AB - Ce texte s'ajoute เ la fin d'un des messages de compl้tion ci-dessus. # AB - Faut-il utiliser "origine" ou "originel" au lieu d'"original" ? # DB : Suggestion. -#: ../edit.c:4618 msgid "Back at original" msgstr "Retour au point de d้part" # AB - Ce texte s'ajoute เ la fin d'un des messages de compl้tion ci-dessus. -#: ../edit.c:4621 msgid "Word from other line" msgstr "Mot d'une autre ligne" # AB - Ce texte s'ajoute เ la fin d'un des messages de compl้tion ci-dessus. -#: ../edit.c:4624 msgid "The only match" msgstr "La seule correspondance" # AB - Ce texte s'ajoute เ la fin d'un des messages de compl้tion ci-dessus. # AB - Faut-il remplacer "sur" par "de" ? # DB : Pour moi, non. -#: ../edit.c:4680 #, c-format msgid "match %d of %d" msgstr "Correspondance %d sur %d" # AB - Ce texte s'ajoute เ la fin d'un des messages de compl้tion ci-dessus. # DB - todo : la VO n'a pas de majuscule. -#: ../edit.c:4684 #, c-format msgid "match %d" msgstr "Correspondance %d" -#: ../eval.c:137 +#. maximum nesting of lists and dicts msgid "E18: Unexpected characters in :let" msgstr "E18: Caract่res inattendus avant '='" -#: ../eval.c:138 -#, c-format -msgid "E684: list index out of range: %<PRId64>" -msgstr "E684: index de Liste hors limites : %<PRId64> au-delเ de la fin" - -#: ../eval.c:139 #, c-format msgid "E121: Undefined variable: %s" msgstr "E121: Variable non d้finie : %s" -#: ../eval.c:140 msgid "E111: Missing ']'" msgstr "E111: ']' manquant" -#: ../eval.c:141 -#, c-format -msgid "E686: Argument of %s must be a List" -msgstr "E686: L'argument de %s doit ๊tre une Liste" - -#: ../eval.c:143 -#, c-format -msgid "E712: Argument of %s must be a List or Dictionary" -msgstr "E712: L'argument de %s doit ๊tre une Liste ou un Dictionnaire" - -#: ../eval.c:144 -msgid "E713: Cannot use empty key for Dictionary" -msgstr "E713: Impossible d'utiliser une cl้ vide dans un Dictionnaire" - -#: ../eval.c:145 -msgid "E714: List required" -msgstr "E714: Liste requise" - -#: ../eval.c:146 -msgid "E715: Dictionary required" -msgstr "E715: Dictionnaire requis" - -# DB : Suggestion -#: ../eval.c:147 -#, c-format -msgid "E118: Too many arguments for function: %s" -msgstr "E118: La fonction %s a re็u trop d'arguments" - -#: ../eval.c:148 -#, c-format -msgid "E716: Key not present in Dictionary: %s" -msgstr "E716: La cl้ %s n'existe pas dans le Dictionnaire" - -#: ../eval.c:150 -#, c-format -msgid "E122: Function %s already exists, add ! to replace it" -msgstr "E122: La fonction %s existe d้jเ (ajoutez ! pour la remplacer)" - -#: ../eval.c:151 -msgid "E717: Dictionary entry already exists" -msgstr "E717: Une entr้e du Dictionnaire porte d้jเ ce nom" - -#: ../eval.c:152 -msgid "E718: Funcref required" -msgstr "E718: R้f้rence de fonction (Funcref) requise" - -#: ../eval.c:153 msgid "E719: Cannot use [:] with a Dictionary" msgstr "E719: Utilisation de [:] impossible avec un Dictionnaire" -#: ../eval.c:154 #, c-format msgid "E734: Wrong variable type for %s=" msgstr "E734: Type de variable erron้ avec %s=" -#: ../eval.c:155 -#, c-format -msgid "E130: Unknown function: %s" -msgstr "E130: Fonction inconnue : %s" - -#: ../eval.c:156 #, c-format msgid "E461: Illegal variable name: %s" msgstr "E461: Nom de variable invalide : %s" -#: ../eval.c:157 msgid "E806: using Float as a String" msgstr "E806: Utilisation d'un Flottant comme une Cha๎ne" # DB - todo : trouver mieux que "destinations". -#: ../eval.c:1830 msgid "E687: Less targets than List items" msgstr "E687: Moins de destinations que d'้l้ments dans la Liste" # DB - todo : trouver mieux que "destinations". -#: ../eval.c:1834 msgid "E688: More targets than List items" msgstr "E688: Plus de destinations que d'้l้ments dans la Liste" -#: ../eval.c:1906 msgid "Double ; in list of variables" msgstr "Double ; dans une liste de variables" -#: ../eval.c:2078 #, c-format msgid "E738: Can't list variables for %s" msgstr "E738: Impossible de lister les variables de %s" -#: ../eval.c:2391 msgid "E689: Can only index a List or Dictionary" msgstr "E689: Seul une Liste ou un Dictionnaire peut ๊tre index้" -#: ../eval.c:2396 msgid "E708: [:] must come last" msgstr "E708: [:] ne peut ๊tre sp้cifi้ qu'en dernier" -#: ../eval.c:2439 msgid "E709: [:] requires a List value" -msgstr "E709: [:] n?cessite une Liste" +msgstr "E709: [:] n้cessite une Liste" -#: ../eval.c:2674 msgid "E710: List value has more items than target" msgstr "E710: La Liste a plus d'้l้ments que la destination" -#: ../eval.c:2678 msgid "E711: List value has not enough items" msgstr "E711: La Liste n'a pas assez d'้l้ments" -#: ../eval.c:2867 msgid "E690: Missing \"in\" after :for" msgstr "E690: \"in\" manquant apr่s :for" -#: ../eval.c:3063 -#, c-format -msgid "E107: Missing parentheses: %s" -msgstr "E107: Parenth่ses manquantes : %s" - -#: ../eval.c:3263 #, c-format msgid "E108: No such variable: \"%s\"" msgstr "E108: Variable inexistante : %s" -#: ../eval.c:3333 msgid "E743: variable nested too deep for (un)lock" msgstr "E743: variable trop imbriqu้e pour la (d้)verrouiller" # AB - Je suis partag้ entre la concision d'une traduction assez litt้rale et # la lourdeur d'une traduction plus correcte. -#: ../eval.c:3630 msgid "E109: Missing ':' after '?'" msgstr "E109: Il manque ':' apr่s '?'" -#: ../eval.c:3893 msgid "E691: Can only compare List with List" msgstr "E691: Une Liste ne peut ๊tre compar้e qu'avec une Liste" -#: ../eval.c:3895 -msgid "E692: Invalid operation for Lists" -msgstr "E692: Op้ration invalide avec les Listes" +msgid "E692: Invalid operation for List" +msgstr "E692: Op้ration invalide avec les Liste" -#: ../eval.c:3915 msgid "E735: Can only compare Dictionary with Dictionary" msgstr "E735: Un Dictionnaire ne peut ๊tre compar้ qu'avec un Dictionnaire" -#: ../eval.c:3917 msgid "E736: Invalid operation for Dictionary" msgstr "E736: Op้ration invalide avec les Dictionnaires" -# DB - todo : Traduction valable (et courte) pour Funcref ? -#: ../eval.c:3932 -msgid "E693: Can only compare Funcref with Funcref" -msgstr "E693: Une Funcref ne peut ๊tre compar้e qu'เ une Funcref" - -#: ../eval.c:3934 msgid "E694: Invalid operation for Funcrefs" msgstr "E694: Op้ration invalide avec les Funcrefs" -#: ../eval.c:4277 msgid "E804: Cannot use '%' with Float" msgstr "E804: Impossible d'utiliser '%' avec un Flottant" -#: ../eval.c:4478 msgid "E110: Missing ')'" msgstr "E110: ')' manquant" -#: ../eval.c:4609 msgid "E695: Cannot index a Funcref" msgstr "E695: Impossible d'indexer une Funcref" +msgid "E909: Cannot index a special variable" +msgstr "E909: Impossible d'indexer une variable sp้ciale" + # AB - La version fran็aise est meilleure que la version anglaise. -#: ../eval.c:4839 #, c-format msgid "E112: Option name missing: %s" msgstr "E112: Il manque un nom d'option apr่s %s" -#: ../eval.c:4855 #, c-format msgid "E113: Unknown option: %s" msgstr "E113: Option inconnue : %s" @@ -730,464 +631,307 @@ msgstr "E113: Option inconnue : %s" # AB - La version fran็aise est meilleure que la version anglaise, qui est # erron้e, d'ailleurs : il s'agit d'une "double quote" et non d'une # "quote". -#: ../eval.c:4904 #, c-format msgid "E114: Missing quote: %s" msgstr "E114: Il manque \" เ la fin de %s" # AB - La version fran็aise est meilleure que la version anglaise. -#: ../eval.c:5020 #, c-format msgid "E115: Missing quote: %s" msgstr "E115: Il manque ' เ la fin de %s" -#: ../eval.c:5084 -#, c-format -msgid "E696: Missing comma in List: %s" -msgstr "E696: Il manque une virgule dans la Liste %s" - -#: ../eval.c:5091 -#, c-format -msgid "E697: Missing end of List ']': %s" -msgstr "E697: Il manque ']' เ la fin de la Liste %s" - -#: ../eval.c:5750 msgid "Not enough memory to set references, garbage collection aborted!" msgstr "" "Pas assez de m้moire pour les r้f้rences, arr๊t du ramassage de mi่tes !" -#: ../eval.c:6475 -#, c-format -msgid "E720: Missing colon in Dictionary: %s" -msgstr "E720: Il manque ':' dans le Dictionnaire %s" +msgid "E724: variable nested too deep for displaying" +msgstr "E724: variable trop imbriqu้e pour ๊tre affich้e" -#: ../eval.c:6499 -#, c-format -msgid "E721: Duplicate key in Dictionary: \"%s\"" -msgstr "E721: Cl้ \"%s\" dupliqu้e dans le Dictionnaire" +msgid "E805: Using a Float as a Number" +msgstr "E805: Utilisation d'un Flottant comme un Nombre" -#: ../eval.c:6517 -#, c-format -msgid "E722: Missing comma in Dictionary: %s" -msgstr "E722: Il manque une virgule dans le Dictionnaire %s" +msgid "E703: Using a Funcref as a Number" +msgstr "E703: Utilisation d'une Funcref comme un Nombre" -#: ../eval.c:6524 -#, c-format -msgid "E723: Missing end of Dictionary '}': %s" -msgstr "E723: Il manque '}' เ la fin du Dictionnaire %s" +msgid "E745: Using a List as a Number" +msgstr "E745: Utilisation d'une Liste comme un Nombre" -#: ../eval.c:6555 -msgid "E724: variable nested too deep for displaying" -msgstr "E724: variable trop imbriqu้e pour ๊tre affich้e" +msgid "E728: Using a Dictionary as a Number" +msgstr "E728: Utilisation d'un Dictionnaire comme un Nombre" + +msgid "E910: Using a Job as a Number" +msgstr "E910: Utilisation d'une Tโche comme un Nombre" + +msgid "E913: Using a Channel as a Number" +msgstr "E913: Utilisation d'un Canal comme un Nombre" + +msgid "E891: Using a Funcref as a Float" +msgstr "E891: Utilisation d'une Funcref comme un Flottant" + +msgid "E892: Using a String as a Float" +msgstr "E892: Utilisation d'une Cha๎ne comme un Flottant" + +msgid "E893: Using a List as a Float" +msgstr "E893: Utilisation d'une Liste comme un Flottant" + +msgid "E894: Using a Dictionary as a Float" +msgstr "E894: Utilisation d'un Dictionnaire comme un Flottant" + +msgid "E907: Using a special value as a Float" +msgstr "E907: Utilisation d'une valeur sp้ciale comme un Flottant" + +msgid "E911: Using a Job as a Float" +msgstr "E911: Utilisation d'une Tโche comme un Flottant" + +msgid "E914: Using a Channel as a Float" +msgstr "E914: Utilisation d'un Canal comme un Flottant" + +msgid "E729: using Funcref as a String" +msgstr "E729: Utilisation d'une Funcref comme une Cha๎ne" + +msgid "E730: using List as a String" +msgstr "E730: Utilisation d'une Liste comme une Cha๎ne" + +msgid "E731: using Dictionary as a String" +msgstr "E731: Utilisation d'un Dictionnaire comme une Cha๎ne" + +msgid "E908: using an invalid value as a String" +msgstr "E908: Utilisation d'une valeur invalide comme une Cha๎ne" -#: ../eval.c:7188 #, c-format -msgid "E740: Too many arguments for function %s" -msgstr "E740: Trop d'arguments pour la fonction %s" +msgid "E795: Cannot delete variable %s" +msgstr "E795: Impossible de supprimer la variable %s" -#: ../eval.c:7190 #, c-format -msgid "E116: Invalid arguments for function %s" -msgstr "E116: Arguments invalides pour la fonction %s" +msgid "E704: Funcref variable name must start with a capital: %s" +msgstr "E704: Le nom d'une Funcref doit commencer par une majuscule : %s" -#: ../eval.c:7377 #, c-format -msgid "E117: Unknown function: %s" -msgstr "E117: Fonction inconnue : %s" +msgid "E705: Variable name conflicts with existing function: %s" +msgstr "E705: Le nom d'une variable entre en conflit avec la fonction %s" -#: ../eval.c:7383 #, c-format -msgid "E119: Not enough arguments for function: %s" -msgstr "E119: La fonction %s n'a pas re็u assez d'arguments" +msgid "E741: Value is locked: %s" +msgstr "E741: La valeur de %s est verrouill้e" + +msgid "Unknown" +msgstr "Inconnu" -#: ../eval.c:7387 #, c-format -msgid "E120: Using <SID> not in a script context: %s" -msgstr "E120: <SID> utilis้ en dehors d'un script : %s" +msgid "E742: Cannot change value of %s" +msgstr "E742: Impossible de modifier la valeur de %s" + +msgid "E698: variable nested too deep for making a copy" +msgstr "E698: variable trop imbriqu้e pour en faire une copie" + +# AB - La version fran็aise est capitalis้e pour ๊tre en accord avec les autres +# commentaires enregistr้s dans le fichier viminfo. +msgid "" +"\n" +"# global variables:\n" +msgstr "" +"\n" +"# Variables globales:\n" + +# DB - Plus pr้cis ("la derni่re fois") ? +msgid "" +"\n" +"\tLast set from " +msgstr "" +"\n" +"\tModifi้ la derni่re fois dans " + +msgid "map() argument" +msgstr "argument de map()" + +msgid "filter() argument" +msgstr "argument de filter()" -#: ../eval.c:7391 #, c-format -msgid "E725: Calling dict function without Dictionary: %s" -msgstr "E725: Appel d'une fonction ซ dict ป sans Dictionnaire : %s" +msgid "E686: Argument of %s must be a List" +msgstr "E686: L'argument de %s doit ๊tre une Liste" + +msgid "E928: String required" +msgstr "E928: Cha๎ne requis" -#: ../eval.c:7453 msgid "E808: Number or Float required" msgstr "E808: Nombre ou Flottant requis" -#: ../eval.c:7503 msgid "add() argument" msgstr "argument de add()" -#: ../eval.c:7907 -msgid "E699: Too many arguments" -msgstr "E699: Trop d'arguments" - -#: ../eval.c:8073 msgid "E785: complete() can only be used in Insert mode" msgstr "E785: complete() n'est utilisable que dans le mode Insertion" # AB - Texte par d้faut du bouton de la bo๎te de dialogue affich้e par la # fonction confirm(). -#: ../eval.c:8156 +#. +#. * Yes this is ugly, I don't particularly like it either. But doing it +#. * this way has the compelling advantage that translations need not to +#. * be touched at all. See below what 'ok' and 'ync' are used for. +#. msgid "&Ok" msgstr "&Ok" -#: ../eval.c:8692 -msgid "extend() argument" -msgstr "argument de extend()" - -#: ../eval.c:9345 -#, c-format -msgid "E737: Key already exists: %s" -msgstr "E737: un mappage existe d้jเ pour %s" - -#: ../eval.c:8915 -msgid "map() argument" -msgstr "argument de map()" - -#: ../eval.c:8916 -msgid "filter() argument" -msgstr "argument de filter()" - -#: ../eval.c:9229 #, c-format -msgid "+-%s%3ld lines: " -msgstr "+-%s%3ld lignes : " +msgid "+-%s%3ld line: " +msgid_plural "+-%s%3ld lines: " +msgstr[0] "+-%s%3ld ligne : " +msgstr[1] "+-%s%3ld lignes : " -#: ../eval.c:9291 #, c-format msgid "E700: Unknown function: %s" msgstr "E700: Fonction inconnue : %s" +msgid "E922: expected a dict" +msgstr "E922: dictionnaire attendu" + +msgid "E923: Second argument of function() must be a list or a dict" +msgstr "" +"E923: Le second argument de function() doit ๊tre une liste ou un dictionnaire" + +# AB - Textes des boutons de la bo๎te de dialogue affich้e par inputdialog(). +msgid "" +"&OK\n" +"&Cancel" +msgstr "" +"&Ok\n" +"&Annuler" + # AB - La version fran็aise est meilleure que la version anglaise. -#: ../eval.c:10729 msgid "called inputrestore() more often than inputsave()" msgstr "inputrestore() a ้t้ appel้ plus de fois qu'inputsave()" -#: ../eval.c:10771 msgid "insert() argument" msgstr "argument de insert()" -#: ../eval.c:10841 msgid "E786: Range not allowed" msgstr "E786: Les plages ne sont pas autoris้es" -#: ../eval.c:11140 +msgid "E916: not a valid job" +msgstr "E916: tโche invalide" + msgid "E701: Invalid type for len()" msgstr "E701: Type invalide avec len()" -#: ../eval.c:11980 +#, c-format +msgid "E798: ID is reserved for \":match\": %ld" +msgstr "E798: ID est r้serv้ pour \":match\": %ld" + msgid "E726: Stride is zero" msgstr "E726: Le pas est nul" -#: ../eval.c:11982 msgid "E727: Start past end" msgstr "E727: D้but au-delเ de la fin" -#: ../eval.c:12024 ../eval.c:15297 msgid "<empty>" msgstr "<vide>" -#: ../eval.c:12282 +# AB - ภ mon avis, la version anglaise est erron้e. +# DB : V้rifier +msgid "E240: No connection to Vim server" +msgstr "E240: Pas de connexion au serveur X" + +# AB - La version fran็aise est meilleure que la version anglaise. +#, c-format +msgid "E241: Unable to send to %s" +msgstr "E241: L'envoi au serveur %s a ้chou้" + +msgid "E277: Unable to read a server reply" +msgstr "E277: Impossible de lire la r้ponse du serveur" + msgid "remove() argument" msgstr "argument de remove()" -#: ../eval.c:12466 msgid "E655: Too many symbolic links (cycle?)" msgstr "E655: Trop de liens symboliques (cycle ?)" -#: ../eval.c:12593 msgid "reverse() argument" msgstr "argument de reverse()" -#: ../eval.c:13721 +# AB - La version fran็aise est meilleure que la version anglaise. +msgid "E258: Unable to send to client" +msgstr "E258: La r้ponse n'a pas pu ๊tre envoy้e au client" + +#, c-format +msgid "E927: Invalid action: '%s'" +msgstr "E927: Action invalide : ซ %s ป" + msgid "sort() argument" msgstr "argument de sort()" -#: ../eval.c:13721 -#, fuzzy msgid "uniq() argument" -msgstr "argument de add()" +msgstr "argument de uniq()" -#: ../eval.c:13776 msgid "E702: Sort compare function failed" msgstr "E702: La fonction de comparaison de sort() a ้chou้" -#: ../eval.c:13806 -#, fuzzy msgid "E882: Uniq compare function failed" -msgstr "E702: La fonction de comparaison de sort() a ้chou้" +msgstr "E882: La fonction de comparaison de uniq() a ้chou้" -#: ../eval.c:14085 msgid "(Invalid)" msgstr "(Invalide)" -#: ../eval.c:14590 -msgid "E677: Error writing temp file" -msgstr "E677: Erreur lors de l'้criture du fichier temporaire" - -#: ../eval.c:16159 -msgid "E805: Using a Float as a Number" -msgstr "E805: Utilisation d'un Flottant comme un Nombre" - -#: ../eval.c:16162 -msgid "E703: Using a Funcref as a Number" -msgstr "E703: Utilisation d'une Funcref comme un Nombre" - -#: ../eval.c:16170 -msgid "E745: Using a List as a Number" -msgstr "E745: Utilisation d'une Liste comme un Nombre" - -#: ../eval.c:16173 -msgid "E728: Using a Dictionary as a Number" -msgstr "E728: Utilisation d'un Dictionnaire comme un Nombre" - -#: ../eval.c:16259 -msgid "E729: using Funcref as a String" -msgstr "E729: Utilisation d'une Funcref comme une Cha๎ne" - -#: ../eval.c:16262 -msgid "E730: using List as a String" -msgstr "E730: Utilisation d'une Liste comme une Cha๎ne" - -#: ../eval.c:16265 -msgid "E731: using Dictionary as a String" -msgstr "E731: Utilisation d'un Dictionnaire comme une Cha๎ne" - -# DB : On doit pouvoir trouver nettement mieux que ็a. -#: ../eval.c:16619 -#, c-format -msgid "E706: Variable type mismatch for: %s" -msgstr "E706: Type de variable incoh้rent pour %s" - -#: ../eval.c:16705 -#, c-format -msgid "E795: Cannot delete variable %s" -msgstr "E795: Impossible de supprimer la variable %s" - -#: ../eval.c:16724 -#, c-format -msgid "E704: Funcref variable name must start with a capital: %s" -msgstr "E704: Le nom d'une Funcref doit commencer par une majuscule : %s" - -#: ../eval.c:16732 -#, c-format -msgid "E705: Variable name conflicts with existing function: %s" -msgstr "E705: Le nom d'une variable entre en conflit avec la fonction %s" - -#: ../eval.c:16763 -#, c-format -msgid "E741: Value is locked: %s" -msgstr "E741: La valeur de %s est verrouill้e" - -#: ../eval.c:16764 ../eval.c:16769 ../message.c:1839 -msgid "Unknown" -msgstr "Inconnu" - -#: ../eval.c:16768 -#, c-format -msgid "E742: Cannot change value of %s" -msgstr "E742: Impossible de modifier la valeur de %s" - -#: ../eval.c:16838 -msgid "E698: variable nested too deep for making a copy" -msgstr "E698: variable trop imbriqu้e pour en faire une copie" - -#: ../eval.c:17249 -#, c-format -msgid "E123: Undefined function: %s" -msgstr "E123: Fonction non d้finie : %s" - -# AB - La version fran็aise est plus consistante que la version anglaise. -# AB - Je suis partag้ entre la concision d'une traduction assez litt้rale et -# la lourdeur d'une traduction plus correcte. -#: ../eval.c:17260 -#, c-format -msgid "E124: Missing '(': %s" -msgstr "E124: Il manque '(' apr่s %s" - -#: ../eval.c:17293 -msgid "E862: Cannot use g: here" -msgstr "E862: Impossible d'utiliser g: ici" - -#: ../eval.c:17312 -#, c-format -msgid "E125: Illegal argument: %s" -msgstr "E125: Argument invalide : %s" - -#: ../eval.c:17323 -#, c-format -msgid "E853: Duplicate argument name: %s" -msgstr "E853: Nom d'argument dupliqu้ : %s" - -#: ../eval.c:17416 -msgid "E126: Missing :endfunction" -msgstr "E126: Il manque :endfunction" - -#: ../eval.c:17537 -#, c-format -msgid "E707: Function name conflicts with variable: %s" -msgstr "E707: Le nom de fonction entre en conflit avec la variable : %s" - -#: ../eval.c:17549 -#, c-format -msgid "E127: Cannot redefine function %s: It is in use" -msgstr "E127: Impossible de red้finir fonction %s : d้jเ utilis้e" - -# DB - Le contenu du "c-format" est le nom de la fonction. -#: ../eval.c:17604 -#, c-format -msgid "E746: Function name does not match script file name: %s" -msgstr "E746: Le nom de la fonction %s ne correspond pas le nom du script" - -#: ../eval.c:17716 -msgid "E129: Function name required" -msgstr "E129: Nom de fonction requis" - -#: ../eval.c:17824 -#, fuzzy, c-format -msgid "E128: Function name must start with a capital or \"s:\": %s" -msgstr "E128: La fonction %s ne commence pas par une majuscule ou contient ':'" - -#: ../eval.c:17833 -#, fuzzy, c-format -msgid "E884: Function name cannot contain a colon: %s" -msgstr "E128: La fonction %s ne commence pas par une majuscule ou contient ':'" - -# AB - Il est difficile de cr้er une version fran็aise qui fasse moins de 80 -# caract่res de long, nom de la fonction compris : "It is in use" est une -# expression tr่s dense. Traductions possibles : "elle est utilis้e", -# "elle s'ex้cute" ou "elle est occup้e". -#: ../eval.c:18336 -#, c-format -msgid "E131: Cannot delete function %s: It is in use" -msgstr "E131: Impossible d'effacer %s : cette fonction est utilis้e" - -# AB - V้rifier dans la litt้rature technique s'il n'existe pas une meilleure -# traduction pour "function call depth". -#: ../eval.c:18441 -msgid "E132: Function call depth is higher than 'maxfuncdepth'" -msgstr "" -"E132: La profondeur d'appel de fonction est sup้rieure เ 'maxfuncdepth'" - -# AB - Ce texte fait partie d'un message de d้bogage. -#: ../eval.c:18568 #, c-format -msgid "calling %s" -msgstr "appel de %s" +msgid "E935: invalid submatch number: %d" +msgstr "E935: num้ro de submatch invalide : %d" -# AB - V้rifier. -#: ../eval.c:18651 -#, c-format -msgid "%s aborted" -msgstr "%s annul้e" - -# AB - Ce texte fait partie d'un message de d้bogage. -#: ../eval.c:18653 -#, c-format -msgid "%s returning #%<PRId64>" -msgstr "%s a retourn้ #%<PRId64>" - -# AB - Ce texte fait partie d'un message de d้bogage. -#: ../eval.c:18670 -#, c-format -msgid "%s returning %s" -msgstr "%s a retourn้ \"%s\"" - -# AB - Ce texte fait partie d'un message de d้bogage. -#: ../eval.c:18691 ../ex_cmds2.c:2695 -#, c-format -msgid "continuing in %s" -msgstr "de retour dans %s" - -#: ../eval.c:18795 -msgid "E133: :return not inside a function" -msgstr "E133: :return en dehors d'une fonction" - -# AB - La version fran็aise est capitalis้e pour ๊tre en accord avec les autres -# commentaires enregistr้s dans le fichier viminfo. -#: ../eval.c:19159 -msgid "" -"\n" -"# global variables:\n" -msgstr "" -"\n" -"# Variables globales:\n" - -# DB - Plus pr้cis ("la derni่re fois") ? -#: ../eval.c:19254 -msgid "" -"\n" -"\tLast set from " -msgstr "" -"\n" -"\tModifi้ la derni่re fois dans " +msgid "E677: Error writing temp file" +msgstr "E677: Erreur lors de l'้criture du fichier temporaire" -#: ../eval.c:19272 -msgid "No old files" -msgstr "Aucun vieux fichier" +msgid "E921: Invalid callback argument" +msgstr "E921: Argument de callback invalide" -#: ../ex_cmds.c:122 #, c-format msgid "<%s>%s%s %d, Hex %02x, Octal %03o" msgstr "<%s>%s%s %d, Hexa %02x, Octal %03o" -#: ../ex_cmds.c:145 #, c-format msgid "> %d, Hex %04x, Octal %o" msgstr "> %d, Hexa %04x, Octal %o" -#: ../ex_cmds.c:146 #, c-format msgid "> %d, Hex %08x, Octal %o" msgstr "> %d, Hexa %08x, Octal %o" # AB - La version anglaise est tr่s mauvaise, ce qui m'oblige a inventer une # version fran็aise. -#: ../ex_cmds.c:684 msgid "E134: Move lines into themselves" msgstr "E134: La destination est dans la plage d'origine" -#: ../ex_cmds.c:747 msgid "1 line moved" msgstr "1 ligne d้plac้e" -#: ../ex_cmds.c:749 #, c-format -msgid "%<PRId64> lines moved" -msgstr "%<PRId64> lignes d้plac้es" +msgid "%ld lines moved" +msgstr "%ld lignes d้plac้es" -#: ../ex_cmds.c:1175 #, c-format -msgid "%<PRId64> lines filtered" -msgstr "%<PRId64> lignes filtr้es" +msgid "%ld lines filtered" +msgstr "%ld lignes filtr้es" # AB - J'ai volontairement omis l'ast้risque initiale car je pense que le # motif "Filter*" d้crit plus clairement les quatre autocommandes li้es # au filtrage (FilterReadPre, FilterReadPost, FilterWritePre et # FilterWritePost) que "*Filter*" que l'on confond avec une tentative de # mise en valeur. -#: ../ex_cmds.c:1194 msgid "E135: *Filter* Autocommands must not change current buffer" msgstr "" "E135: Les autocommandes Filter* ne doivent pas changer le tampon courant" # AB - Il faut respecter l'esprit plus que la lettre. Dans le cas pr้sent, # nettement plus. -#: ../ex_cmds.c:1244 msgid "[No write since last change]\n" msgstr "[Attention : tout n'est pas enregistr้]\n" # AB - Le num้ro et le message d'erreur (%s ci-dessous) et le "num้ro" de ligne # sont des cha๎nes de caract่res dont le contenu est เ la discr้tion de # l'appelant de la fonction viminfo_error(). -#: ../ex_cmds.c:1424 #, c-format msgid "%sviminfo: %s in line: " msgstr "%sviminfo : %s เ la ligne " # AB - La version fran็aise est meilleure que la version anglaise. -#: ../ex_cmds.c:1431 msgid "E136: viminfo: Too many errors, skipping rest of file" msgstr "" "E136: Il y a trop d'erreurs ; interruption de la lecture du fichier viminfo" @@ -1195,30 +939,25 @@ msgstr "" # AB - Ce texte fait partie d'un message de d้bogage. # DB - ... dont les valeurs possibles sont les messages # qui suivent. -#: ../ex_cmds.c:1458 #, c-format msgid "Reading viminfo file \"%s\"%s%s%s" msgstr "Lecture du fichier viminfo \"%s\"%s%s%s" # AB - Ce texte fait partie d'un message de d้bogage. # DB - Voir ci-dessus. -#: ../ex_cmds.c:1460 msgid " info" msgstr " info" # AB - Ce texte fait partie d'un message de d้bogage. # DB - Voir ci-dessus. -#: ../ex_cmds.c:1461 msgid " marks" msgstr " marques" -#: ../ex_cmds.c:1462 msgid " oldfiles" msgstr " vieux fichiers" # AB - Ce texte fait partie d'un message de d้bogage. # DB - Voir ci-dessus. -#: ../ex_cmds.c:1463 msgid " FAILED" msgstr " ษCHEC" @@ -1227,33 +966,36 @@ msgstr " ษCHEC" # AB - Le mot "viminfo" a ้t้ retir้ pour que le message ne d้passe pas 80 # caract่res dans le cas courant o๙ %s = /home/12345678/.viminfo #. avoid a wait_return for this message, it's annoying -#: ../ex_cmds.c:1541 #, c-format msgid "E137: Viminfo file is not writable: %s" msgstr "E137: L'้criture dans le fichier %s est interdite" +#, c-format +msgid "E929: Too many viminfo temp files, like %s!" +msgstr "E929: Trop de fichiers temporaires viminfo, comme %s!" + # AB - Le point d'exclamation est superflu. # AB - Le mot "viminfo" a ้t้ retir้ pour que le message ne d้passe pas 80 # caract่res dans le cas courant o๙ %s = /home/12345678/.viminfo -#: ../ex_cmds.c:1626 #, c-format msgid "E138: Can't write viminfo file %s!" msgstr "E138: Impossible d'้crire le fichier %s" # AB - Ce texte est un message de d้bogage. -#: ../ex_cmds.c:1635 #, c-format msgid "Writing viminfo file \"%s\"" msgstr "ษcriture du fichier viminfo \"%s\"" +#, c-format +msgid "E886: Can't rename viminfo file to %s!" +msgstr "E886: Impossible de renommer viminfo en %s" + #. Write the info: -#: ../ex_cmds.c:1720 #, c-format msgid "# This viminfo file was generated by Vim %s.\n" msgstr "# Ce fichier viminfo a ้t้ g้n้r้ par Vim %s.\n" # AB - Les deux versions, bien que diff้rentes, se valent. -#: ../ex_cmds.c:1722 msgid "" "# You may edit it if you're careful!\n" "\n" @@ -1261,58 +1003,61 @@ msgstr "" "# Vous pouvez l'้diter, mais soyez prudent.\n" "\n" -#: ../ex_cmds.c:1723 msgid "# Value of 'encoding' when this file was written\n" msgstr "# 'encoding' dans lequel ce fichier a ้t้ ้crit\n" # AB - Ce texte est pass้ en argument เ la fonction viminfo_error(). # AB - "ill้gal" est un terme trop fort เ mon go๛t. -#: ../ex_cmds.c:1800 msgid "Illegal starting char" msgstr "Caract่re initial non valide" +msgid "" +"\n" +"# Bar lines, copied verbatim:\n" +msgstr "" +"\n" +"# Lignes commen็ant par |, copi้es litt้ralement :\n" + +# AB - Ceci est un titre de bo๎te de dialogue. V้rifier que la version +# fran็aise est correcte pour les trois r้f้rences ; j'ai un doute quant +# เ la troisi่me. +msgid "Save As" +msgstr "Enregistrer sous - Vim" + # AB - Ceci est un contenu de bo๎te de dialogue (้ventuellement en mode texte). # AB - La version fran็aise est meilleure que la version anglaise. -#: ../ex_cmds.c:2162 msgid "Write partial file?" msgstr "Perdre une partie du fichier ?" # AB - La version fran็aise est nettement meilleure que la version anglaise. -#: ../ex_cmds.c:2166 msgid "E140: Use ! to write partial buffer" msgstr "" "E140: Une partie du fichier serait perdue (ajoutez ! pour passer outre)" -#: ../ex_cmds.c:2281 #, c-format msgid "Overwrite existing file \"%s\"?" msgstr "ษcraser le fichier %s existant ?" -#: ../ex_cmds.c:2317 #, c-format msgid "Swap file \"%s\" exists, overwrite anyway?" msgstr "Le fichier d'้change \"%s\" existe d้jเ, l'้craser ?" # DB - Un peu long เ mon avis. -#: ../ex_cmds.c:2326 #, c-format msgid "E768: Swap file exists: %s (:silent! overrides)" msgstr "E768: Le fichier d'้change %s existe d้jเ (:silent! pour passer outre)" -#: ../ex_cmds.c:2381 #, c-format -msgid "E141: No file name for buffer %<PRId64>" -msgstr "E141: Pas de nom de fichier pour le tampon %<PRId64>" +msgid "E141: No file name for buffer %ld" +msgstr "E141: Pas de nom de fichier pour le tampon %ld" # AB - Il faut respecter l'esprit plus que la lettre. -#: ../ex_cmds.c:2412 msgid "E142: File not written: Writing is disabled by 'write' option" msgstr "" "E142: L'option 'nowrite' est activ้e et emp๊che toute ้criture du fichier" # AB - Ceci est un contenu de bo๎te de dialogue (้ventuellement en mode texte). # AB - "activ้e pour" n'est pas une formulation tr่s heureuse. -#: ../ex_cmds.c:2434 #, c-format msgid "" "'readonly' option is set for \"%s\".\n" @@ -1321,7 +1066,6 @@ msgstr "" "L'option 'readonly' est activ้e pour \"%s\".\n" "Voulez-vous tout de m๊me enregistrer ?" -#: ../ex_cmds.c:2439 #, c-format msgid "" "File permissions of \"%s\" are read-only.\n" @@ -1332,94 +1076,81 @@ msgstr "" "Il peut ๊tre possible de l'้crire tout de m๊me.\n" "Tenter ?" -#: ../ex_cmds.c:2451 #, c-format msgid "E505: \"%s\" is read-only (add ! to override)" msgstr "E505: \"%s\" est en lecture seule (ajoutez ! pour passer outre)" +# AB - Ceci est un titre de bo๎te de dialogue. +msgid "Edit File" +msgstr "Ouvrir un fichier - Vim" + # AB - Il faut respecter l'esprit plus que la lettre. # AB - J'h้site เ ajouter "เ sa cr้ation" apr่s le nom du tampon. Ce message # devrait n'๊tre affich้ qu'apr่s une tentative d'ouverture de fichier, # la version actuelle devrait donc suffire. # DB - Suggestion : "nouveau tampon" ? -#: ../ex_cmds.c:3120 #, c-format msgid "E143: Autocommands unexpectedly deleted new buffer %s" msgstr "E143: Une autocommande a effac้ le nouveau tampon %s" -#: ../ex_cmds.c:3313 msgid "E144: non-numeric argument to :z" msgstr "E144: L'argument de :z n'est pas num้rique" # AB - La version fran็aise fera peut-๊tre mieux passer l'am่re pilule. # La consultation de l'aide donnera l'explication compl่te เ ceux qui # ne comprendraient pas เ quoi ce message est d๛. -#: ../ex_cmds.c:3404 msgid "E145: Shell commands not allowed in rvim" msgstr "E145: Les commandes externes sont indisponibles dans rvim" -#: ../ex_cmds.c:3498 msgid "E146: Regular expressions can't be delimited by letters" msgstr "" "E146: Les expressions r้guli่res ne peuvent pas ๊tre d้limit้es par des " "lettres" -#: ../ex_cmds.c:3964 #, c-format msgid "replace with %s (y/n/a/q/l/^E/^Y)?" msgstr "remplacer par %s (y/n/a/q/l/^E/^Y)?" -#: ../ex_cmds.c:4379 msgid "(Interrupted) " msgstr "(Interrompu) " -#: ../ex_cmds.c:4384 msgid "1 match" msgstr "1 correspondance" -#: ../ex_cmds.c:4384 msgid "1 substitution" msgstr "1 substitution" -#: ../ex_cmds.c:4387 #, c-format -msgid "%<PRId64> matches" -msgstr "%<PRId64> correspondances" +msgid "%ld matches" +msgstr "%ld correspondances" -#: ../ex_cmds.c:4388 #, c-format -msgid "%<PRId64> substitutions" -msgstr "%<PRId64> substitutions" +msgid "%ld substitutions" +msgstr "%ld substitutions" -#: ../ex_cmds.c:4392 msgid " on 1 line" msgstr " sur 1 ligne" -#: ../ex_cmds.c:4395 #, c-format -msgid " on %<PRId64> lines" -msgstr " sur %<PRId64> lignes" +msgid " on %ld lines" +msgstr " sur %ld lignes" # AB - Il faut respecter l'esprit plus que la lettre. # AB - Ce message devrait contenir une r้f้rence เ :vglobal. -#: ../ex_cmds.c:4438 msgid "E147: Cannot do :global recursive" msgstr "E147: :global ne peut pas ex้cuter :global" # AB - Ce message devrait contenir une r้f้rence เ :vglobal. -#: ../ex_cmds.c:4467 msgid "E148: Regular expression missing from global" msgstr "E148: :global doit ๊tre suivi par une expression r้guli่re" # AB - Ce message est utilis้ lorsque :vglobal ne trouve rien. Lorsque :global # ne trouve rien, c'est "Pattern not found: %s" / "Motif introuvable: %s" # qui est utilis้. -#: ../ex_cmds.c:4508 #, c-format msgid "Pattern found in every line: %s" msgstr "Motif trouv้ dans toutes les lignes : %s" -#: ../ex_cmds.c:4510 #, c-format msgid "Pattern not found: %s" msgstr "Motif introuvable: %s" @@ -1430,7 +1161,6 @@ msgstr "Motif introuvable: %s" # เ internationalisation. J'attends que les deux autres messages soient # traduisibles pour traduire celui-ci. # DB - TODO : Qu'en est-il เ pr้sent ? -#: ../ex_cmds.c:4587 msgid "" "\n" "# Last Substitute String:\n" @@ -1441,43 +1171,33 @@ msgstr "" "$" # This message should *so* be E42! -#: ../ex_cmds.c:4679 msgid "E478: Don't panic!" msgstr "E478: Pas de panique !" -#: ../ex_cmds.c:4717 #, c-format msgid "E661: Sorry, no '%s' help for %s" msgstr "E661: D้sol้, aucune aide en langue '%s' pour %s" -#: ../ex_cmds.c:4719 #, c-format msgid "E149: Sorry, no help for %s" msgstr "E149: D้sol้, aucune aide pour %s" -#: ../ex_cmds.c:4751 #, c-format msgid "Sorry, help file \"%s\" not found" msgstr "D้sol้, le fichier d'aide \"%s\" est introuvable" -#: ../ex_cmds.c:5323 #, c-format -msgid "E150: Not a directory: %s" -msgstr "E150: %s n'est pas un r้pertoire" +msgid "E151: No match: %s" +msgstr "E151: Aucune correspondance : %s" -# AB - La version anglaise est plus pr้cise, mais trop technique. -#: ../ex_cmds.c:5446 #, c-format msgid "E152: Cannot open %s for writing" -msgstr "E152: Impossible d'้crire %s" +msgstr "E152: Impossible d'ouvrir %s en ้criture" -# AB - La version anglaise est plus pr้cise, mais trop technique. -#: ../ex_cmds.c:5471 #, c-format msgid "E153: Unable to open %s for reading" -msgstr "E153: Impossible de lire %s" +msgstr "E153: Impossible d'ouvrir %s en lecture" -#: ../ex_cmds.c:5500 #, c-format msgid "E670: Mix of help file encodings within a language: %s" msgstr "E670: Encodages diff้rents dans les fichiers d'aide en langue %s" @@ -1487,315 +1207,279 @@ msgstr "E670: Encodages diff้rents dans les fichiers d'aide en langue %s" # traduction de 40 caract่res ou moins. Ce qui est loin d'๊tre le cas # pr้sent. # DB - Suggestion. -#: ../ex_cmds.c:5565 #, c-format msgid "E154: Duplicate tag \"%s\" in file %s/%s" msgstr "E154: Marqueur \"%s\" dupliqu้ dans le fichier %s/%s" +#, c-format +msgid "E150: Not a directory: %s" +msgstr "E150: %s n'est pas un r้pertoire" + # AB - Il faut respecter l'esprit plus que la lettre. -#: ../ex_cmds.c:5687 #, c-format msgid "E160: Unknown sign command: %s" msgstr "E160: Commande inconnue : :sign %s" # AB - La version fran็aise est meilleure que la version anglaise. -#: ../ex_cmds.c:5704 msgid "E156: Missing sign name" msgstr "E156: Il manque le nom du symbole" -#: ../ex_cmds.c:5746 msgid "E612: Too many signs defined" msgstr "E612: Trop de symboles sont d้finis" # AB - Cette traduction ne me satisfait pas. # DB - Suggestion. -#: ../ex_cmds.c:5813 #, c-format msgid "E239: Invalid sign text: %s" msgstr "E239: Le texte du symbole est invalide : %s" -#: ../ex_cmds.c:5844 ../ex_cmds.c:6035 #, c-format msgid "E155: Unknown sign: %s" msgstr "E155: Symbole inconnu : %s" # AB - La version fran็aise est meilleure que la version anglaise. -#: ../ex_cmds.c:5877 msgid "E159: Missing sign number" msgstr "E159: Il manque l'ID du symbole" # AB - Vu le code source, la version fran็aise est meilleure que la # version anglaise. Ce message est similaire au message E102. -#: ../ex_cmds.c:5971 #, c-format msgid "E158: Invalid buffer name: %s" msgstr "E158: Le tampon %s est introuvable" +msgid "E934: Cannot jump to a buffer that does not have a name" +msgstr "E934: Impossible de sauter เ un tampon sans nom" + # AB - Vu le code source, la version fran็aise est meilleure que la # version anglaise. -#: ../ex_cmds.c:6008 #, c-format -msgid "E157: Invalid sign ID: %<PRId64>" -msgstr "E157: Le symbole %<PRId64> est introuvable" +msgid "E157: Invalid sign ID: %ld" +msgstr "E157: Le symbole %ld est introuvable" + +#, c-format +msgid "E885: Not possible to change sign %s" +msgstr "E885: Impossible de changer le symbole %s" + +msgid " (NOT FOUND)" +msgstr " (INTROUVABLE)" -#: ../ex_cmds.c:6066 msgid " (not supported)" msgstr " (non support้)" -#: ../ex_cmds.c:6169 msgid "[Deleted]" msgstr "[Effac้]" +msgid "No old files" +msgstr "Aucun vieux fichier" + # AB - La version fran็aise de la premi่re phrase ne me satisfait pas. # DB - Suggestion. -#: ../ex_cmds2.c:139 msgid "Entering Debug mode. Type \"cont\" to continue." msgstr "Mode d้bogage activ้. Tapez \"cont\" pour continuer." -#: ../ex_cmds2.c:143 ../ex_docmd.c:759 #, c-format -msgid "line %<PRId64>: %s" -msgstr "ligne %<PRId64> : %s" +msgid "line %ld: %s" +msgstr "ligne %ld : %s" -#: ../ex_cmds2.c:145 #, c-format msgid "cmd: %s" msgstr "cmde : %s" -#: ../ex_cmds2.c:322 +msgid "frame is zero" +msgstr "le cadre de pile est z้ro" + +#, c-format +msgid "frame at highest level: %d" +msgstr "cadre de pile au niveau le plus haut : %d" + #, c-format -msgid "Breakpoint in \"%s%s\" line %<PRId64>" -msgstr "Point d'arr๊t dans %s%s ligne %<PRId64>" +msgid "Breakpoint in \"%s%s\" line %ld" +msgstr "Point d'arr๊t dans %s%s ligne %ld" -#: ../ex_cmds2.c:581 #, c-format msgid "E161: Breakpoint not found: %s" msgstr "E161: Le point d'arr๊t %s est introuvable" -#: ../ex_cmds2.c:611 msgid "No breakpoints defined" msgstr "Aucun point d'arr๊t n'est d้fini" # AB - Le deuxi่me %s est remplac้ par "func" ou "file" sans que l'on puisse # traduire ces mots. -#: ../ex_cmds2.c:617 #, c-format -msgid "%3d %s %s line %<PRId64>" -msgstr "%3d %s %s ligne %<PRId64>" +msgid "%3d %s %s line %ld" +msgstr "%3d %s %s ligne %ld" -#: ../ex_cmds2.c:942 msgid "E750: First use \":profile start {fname}\"" msgstr "E750: Utilisez d'abord \":profile start {nomfichier}\"" # AB - "changes to" est redondant et a ้t้ omis de la version fran็aise. -#: ../ex_cmds2.c:1269 #, c-format msgid "Save changes to \"%s\"?" msgstr "Enregistrer \"%s\" ?" # AB - Si les parenth่ses posent probl่me, il faudra remettre les guillemets # ci-dessus. -#: ../ex_cmds2.c:1271 ../ex_docmd.c:8851 msgid "Untitled" msgstr "(sans titre)" # AB - Il faut respecter l'esprit plus que la lettre. # AB - Ce message est similaire au message E89. -#: ../ex_cmds2.c:1421 #, c-format msgid "E162: No write since last change for buffer \"%s\"" msgstr "E162: Le tampon %s n'a pas ้t้ enregistr้" -#: ../ex_cmds2.c:1480 msgid "Warning: Entered other buffer unexpectedly (check autocommands)" -msgstr "Alerte : Entr้e inattendue dans un autre tampon (v้rifier autocmdes)" +msgstr "" +"Alerte : Entr้e inattendue dans un autre tampon (v้rifier autocommandes)" -#: ../ex_cmds2.c:1826 msgid "E163: There is only one file to edit" msgstr "E163: Il n'y a qu'un seul fichier เ ้diter" -#: ../ex_cmds2.c:1828 msgid "E164: Cannot go before first file" msgstr "E164: Impossible d'aller avant le premier fichier" -#: ../ex_cmds2.c:1830 msgid "E165: Cannot go beyond last file" msgstr "E165: Impossible d'aller au-delเ du dernier fichier" -#: ../ex_cmds2.c:2175 #, c-format msgid "E666: compiler not supported: %s" msgstr "E666: Compilateur %s non support้" -#: ../ex_cmds2.c:2257 #, c-format msgid "Searching for \"%s\" in \"%s\"" msgstr "Recherche de \"%s\" dans \"%s\"" -#: ../ex_cmds2.c:2284 #, c-format msgid "Searching for \"%s\"" msgstr "Recherche de \"%s\"" -#: ../ex_cmds2.c:2307 #, c-format msgid "not found in '%s': \"%s\"" msgstr "introuvable dans '%s' : \"%s\"" -#: ../ex_cmds2.c:2472 +msgid "Source Vim script" +msgstr "Sourcer un script - Vim" + #, c-format msgid "Cannot source a directory: \"%s\"" msgstr "Impossible de sourcer un r้pertoire : \"%s\"" -#: ../ex_cmds2.c:2518 #, c-format msgid "could not source \"%s\"" msgstr "impossible de sourcer \"%s\"" -#: ../ex_cmds2.c:2520 #, c-format -msgid "line %<PRId64>: could not source \"%s\"" -msgstr "ligne %<PRId64> : impossible de sourcer \"%s\"" +msgid "line %ld: could not source \"%s\"" +msgstr "ligne %ld : impossible de sourcer \"%s\"" -#: ../ex_cmds2.c:2535 #, c-format msgid "sourcing \"%s\"" msgstr "sourcement \"%s\"" -#: ../ex_cmds2.c:2537 #, c-format -msgid "line %<PRId64>: sourcing \"%s\"" -msgstr "ligne %<PRId64> : sourcement de \"%s\"" +msgid "line %ld: sourcing \"%s\"" +msgstr "ligne %ld : sourcement de \"%s\"" -#: ../ex_cmds2.c:2693 #, c-format msgid "finished sourcing %s" msgstr "fin du sourcement de %s" -#: ../ex_cmds2.c:2765 +# AB - Ce texte fait partie d'un message de d้bogage. +#, c-format +msgid "continuing in %s" +msgstr "de retour dans %s" + msgid "modeline" msgstr "ligne de mode" -#: ../ex_cmds2.c:2767 msgid "--cmd argument" msgstr "argument --cmd" -#: ../ex_cmds2.c:2769 msgid "-c argument" msgstr "argument -c" -#: ../ex_cmds2.c:2771 msgid "environment variable" msgstr "variable d'environnement" -#: ../ex_cmds2.c:2773 msgid "error handler" msgstr "gestionnaire d'erreur" -#: ../ex_cmds2.c:3020 msgid "W15: Warning: Wrong line separator, ^M may be missing" msgstr "W15: Alerte : S้parateur de ligne erron้, ^M possiblement manquant" -#: ../ex_cmds2.c:3139 msgid "E167: :scriptencoding used outside of a sourced file" msgstr "E167: :scriptencoding utilis้ en dehors d'un fichier sourc้" -#: ../ex_cmds2.c:3166 msgid "E168: :finish used outside of a sourced file" msgstr "E168: :finish utilis้ en dehors d'un fichier sourc้" # DB - Le premier %s est, au choix : "time ", "ctype " ou "messages ", # sans qu'il soit possible de les traduire. -#: ../ex_cmds2.c:3389 #, c-format msgid "Current %slanguage: \"%s\"" msgstr "Langue courante pour %s : \"%s\"" -#: ../ex_cmds2.c:3404 #, c-format msgid "E197: Cannot set language to \"%s\"" msgstr "E197: Impossible de choisir la langue \"%s\"" -#. don't redisplay the window -#. don't wait for return -#: ../ex_docmd.c:387 msgid "Entering Ex mode. Type \"visual\" to go to Normal mode." msgstr "Mode Ex activ้. Tapez \"visual\" pour passer en mode Normal." -#: ../ex_docmd.c:428 msgid "E501: At end-of-file" msgstr "E501: ภ la fin du fichier" -#: ../ex_docmd.c:513 msgid "E169: Command too recursive" msgstr "E169: Commande trop r้cursive" -#: ../ex_docmd.c:1006 #, c-format msgid "E605: Exception not caught: %s" msgstr "E605: Exception non intercept้e : %s" -#: ../ex_docmd.c:1085 msgid "End of sourced file" msgstr "Fin du fichier sourc้" -#: ../ex_docmd.c:1086 msgid "End of function" msgstr "Fin de la fonction" -#: ../ex_docmd.c:1628 msgid "E464: Ambiguous use of user-defined command" msgstr "E464: Utilisation ambigu๋ d'une commande d้finie par l'utilisateur" -#: ../ex_docmd.c:1638 msgid "E492: Not an editor command" msgstr "E492: Commande inconnue" -#: ../ex_docmd.c:1729 msgid "E493: Backwards range given" msgstr "E493: La plage sp้cifi้e est invers้e" -#: ../ex_docmd.c:1733 msgid "Backwards range given, OK to swap" msgstr "La plage sp้cifi้e est invers้e, OK pour l'inverser" -#. append -#. typed wrong -#: ../ex_docmd.c:1787 msgid "E494: Use w or w>>" msgstr "E494: Utilisez w ou w>>" -#: ../ex_docmd.c:3454 -msgid "E319: The command is not available in this version" +msgid "E319: Sorry, the command is not available in this version" msgstr "E319: D้sol้, cette commande n'est pas disponible dans cette version" -#: ../ex_docmd.c:3752 msgid "E172: Only one file name allowed" msgstr "E172: Un seul nom de fichier autoris้" -#: ../ex_docmd.c:4238 msgid "1 more file to edit. Quit anyway?" msgstr "Encore 1 fichier เ ้diter. Quitter tout de m๊me ?" -#: ../ex_docmd.c:4242 #, c-format msgid "%d more files to edit. Quit anyway?" msgstr "Encore %d fichiers เ ้diter. Quitter tout de m๊me ?" -#: ../ex_docmd.c:4248 msgid "E173: 1 more file to edit" msgstr "E173: encore 1 fichier เ ้diter" -#: ../ex_docmd.c:4250 #, c-format -msgid "E173: %<PRId64> more files to edit" -msgstr "E173: encore %<PRId64> fichiers เ ้diter" +msgid "E173: %ld more files to edit" +msgstr "E173: encore %ld fichiers เ ้diter" -#: ../ex_docmd.c:4320 msgid "E174: Command already exists: add ! to replace it" msgstr "E174: La commande existe d้jเ : ajoutez ! pour la red้finir" -#: ../ex_docmd.c:4432 msgid "" "\n" " Name Args Address Complete Definition" @@ -1803,356 +1487,311 @@ msgstr "" "\n" " Nom Args Adresse Complet. D้finition" -#: ../ex_docmd.c:4516 msgid "No user-defined commands found" msgstr "Aucune commande d้finie par l'utilisateur trouv้e" -#: ../ex_docmd.c:4538 msgid "E175: No attribute specified" msgstr "E175: Pas d'attribut sp้cifi้" -#: ../ex_docmd.c:4583 msgid "E176: Invalid number of arguments" msgstr "E176: Nombre d'arguments invalide" -#: ../ex_docmd.c:4594 msgid "E177: Count cannot be specified twice" msgstr "E177: Le quantificateur ne peut ๊tre sp้cifi้ deux fois" -#: ../ex_docmd.c:4603 msgid "E178: Invalid default value for count" msgstr "E178: La valeur par d้faut du quantificateur est invalide" -#: ../ex_docmd.c:4625 msgid "E179: argument required for -complete" msgstr "E179: argument requis avec -complete" -#: ../ex_docmd.c:4933 msgid "E179: argument required for -addr" msgstr "E179: argument requis avec -addr" -#: ../ex_docmd.c:4635 #, c-format msgid "E181: Invalid attribute: %s" msgstr "E181: Attribut invalide : %s" -#: ../ex_docmd.c:4678 msgid "E182: Invalid command name" msgstr "E182: Nom de commande invalide" -#: ../ex_docmd.c:4691 msgid "E183: User defined commands must start with an uppercase letter" msgstr "E183: Les commandes utilisateur doivent commencer par une majuscule" -#: ../ex_docmd.c:4696 msgid "E841: Reserved name, cannot be used for user defined command" msgstr "" "E841: Nom r้serv้, ne peux pas ๊tre utilis้ pour une commande utilisateur" -#: ../ex_docmd.c:4751 #, c-format msgid "E184: No such user-defined command: %s" msgstr "E184: Aucune commande %s d้finie par l'utilisateur" -#: ../ex_docmd.c:5516 #, c-format msgid "E180: Invalid address type value: %s" msgstr "E180: Valeur de type d'adresse invalide : %s" -#: ../ex_docmd.c:5219 #, c-format msgid "E180: Invalid complete value: %s" msgstr "E180: Valeur invalide pour \"-complete=\" : %s" -#: ../ex_docmd.c:5225 msgid "E468: Completion argument only allowed for custom completion" msgstr "E468: Seul le compl่tement personnalis้ accepte un argument" -#: ../ex_docmd.c:5231 msgid "E467: Custom completion requires a function argument" -msgstr "E467: Le compl่tement personnalis้ requiert une fonction en argument" +msgstr "E467: Le compl่tement personnalis้ n้cessite une fonction en argument" + +msgid "unknown" +msgstr "inconnu" -#: ../ex_docmd.c:5257 #, c-format msgid "E185: Cannot find color scheme '%s'" msgstr "E185: Impossible de trouver le jeu de couleurs '%s'" -#: ../ex_docmd.c:5263 msgid "Greetings, Vim user!" msgstr "Bienvenue, utilisateur de Vim !" -#: ../ex_docmd.c:5431 msgid "E784: Cannot close last tab page" msgstr "E784: Impossible de fermer le dernier onglet" -#: ../ex_docmd.c:5462 msgid "Already only one tab page" msgstr "Il ne reste d้jเ plus qu'un seul onglet" -#: ../ex_docmd.c:6004 +msgid "Edit File in new window" +msgstr "Ouvrir un fichier dans une nouvelle fen๊tre - Vim" + #, c-format msgid "Tab page %d" msgstr "Onglet %d" -#: ../ex_docmd.c:6295 msgid "No swap file" msgstr "Pas de fichier d'้change" -#: ../ex_docmd.c:6478 +msgid "Append File" +msgstr "Ajouter fichier" + msgid "E747: Cannot change directory, buffer is modified (add ! to override)" msgstr "" "E747: Tampon modifi้ : impossible de changer de r้pertoire (ajoutez ! pour " "passer outre)" -#: ../ex_docmd.c:6485 msgid "E186: No previous directory" msgstr "E186: Pas de r้pertoire pr้c้dent" -#: ../ex_docmd.c:6530 msgid "E187: Unknown" msgstr "E187: Inconnu" -#: ../ex_docmd.c:6610 msgid "E465: :winsize requires two number arguments" -msgstr "E465: :winsize requiert deux arguments num้riques" +msgstr "E465: :winsize n้cessite deux arguments num้riques" + +#, c-format +msgid "Window position: X %d, Y %d" +msgstr "Position de la fen๊tre : X %d, Y %d" # DB : Suggestion, sans doute perfectible. -#: ../ex_docmd.c:6655 msgid "E188: Obtaining window position not implemented for this platform" msgstr "" "E188: R้cup้rer la position de la fen๊tre non impl้ment้ dans cette version" -#: ../ex_docmd.c:6662 msgid "E466: :winpos requires two number arguments" -msgstr "E466: :winpos requiert deux arguments num้riques" +msgstr "E466: :winpos n้cessite deux arguments num้riques" + +msgid "E930: Cannot use :redir inside execute()" +msgstr "E930: Impossible d'utiliser :redir dans execute()" + +msgid "Save Redirection" +msgstr "Enregistrer la redirection" + +msgid "Save View" +msgstr "Enregistrer la vue - Vim" + +msgid "Save Session" +msgstr "Enregistrer la session - Vim" + +msgid "Save Setup" +msgstr "Enregistrer les r้glages - Vim" -#: ../ex_docmd.c:7241 #, c-format msgid "E739: Cannot create directory: %s" msgstr "E739: Impossible de cr้er le r้pertoire \"%s\"" -#: ../ex_docmd.c:7268 #, c-format msgid "E189: \"%s\" exists (add ! to override)" msgstr "E189: \"%s\" existe (ajoutez ! pour passer outre)" -#: ../ex_docmd.c:7273 #, c-format msgid "E190: Cannot open \"%s\" for writing" msgstr "E190: Impossible d'ouvrir \"%s\" pour y ้crire" #. set mark -#: ../ex_docmd.c:7294 msgid "E191: Argument must be a letter or forward/backward quote" msgstr "E191: L'argument doit ๊tre une lettre ou une (contre-)apostrophe" -#: ../ex_docmd.c:7333 msgid "E192: Recursive use of :normal too deep" msgstr "E192: Appel r้cursif de :normal trop important" -#: ../ex_docmd.c:7807 +msgid "E809: #< is not available without the +eval feature" +msgstr "E809: #< n'est pas disponible sans la fonctionnalit้ +eval" + msgid "E194: No alternate file name to substitute for '#'" msgstr "E194: Aucun nom de fichier alternatif เ substituer เ '#'" -#: ../ex_docmd.c:7841 msgid "E495: no autocommand file name to substitute for \"<afile>\"" msgstr "E495: Aucun nom de ficher d'autocommande เ substituer เ \"<afile>\"" -#: ../ex_docmd.c:7850 msgid "E496: no autocommand buffer number to substitute for \"<abuf>\"" msgstr "E496: Aucun num้ro de tampon d'autocommande เ substituer เ \"<abuf>\"" -#: ../ex_docmd.c:7861 msgid "E497: no autocommand match name to substitute for \"<amatch>\"" msgstr "E497: Aucune correspondance d'autocommande เ substituer เ \"<amatch>\"" -#: ../ex_docmd.c:7870 msgid "E498: no :source file name to substitute for \"<sfile>\"" msgstr "E498: Aucun nom de fichier :source เ substituer เ \"<sfile>\"" -#: ../ex_docmd.c:7876 msgid "E842: no line number to use for \"<slnum>\"" msgstr "E842: aucun num้ro de ligne เ utiliser pour \"<slnum>\"" -#: ../ex_docmd.c:7903 -#, c-format +#, no-c-format msgid "E499: Empty file name for '%' or '#', only works with \":p:h\"" msgstr "E499: Nom de fichier vide pour '%' ou '#', ne marche qu'avec \":p:h\"" -#: ../ex_docmd.c:7905 msgid "E500: Evaluates to an empty string" msgstr "E500: ษvalu้ en une cha๎ne vide" -#: ../ex_docmd.c:8838 msgid "E195: Cannot open viminfo file for reading" msgstr "E195: Impossible d'ouvrir le viminfo en lecture" -#: ../ex_eval.c:464 +msgid "E196: No digraphs in this version" +msgstr "E196: Pas de digraphes dans cette version" + msgid "E608: Cannot :throw exceptions with 'Vim' prefix" msgstr "E608: Impossible d'้mettre des exceptions avec 'Vim' comme pr้fixe" #. always scroll up, don't overwrite -#: ../ex_eval.c:496 #, c-format msgid "Exception thrown: %s" msgstr "Exception ้mise : %s" -#: ../ex_eval.c:545 #, c-format msgid "Exception finished: %s" msgstr "Exception termin้e : %s" -#: ../ex_eval.c:546 #, c-format msgid "Exception discarded: %s" msgstr "Exception ้limin้e : %s" -#: ../ex_eval.c:588 ../ex_eval.c:634 #, c-format -msgid "%s, line %<PRId64>" -msgstr "%s, ligne %<PRId64>" +msgid "%s, line %ld" +msgstr "%s, ligne %ld" #. always scroll up, don't overwrite -#: ../ex_eval.c:608 #, c-format msgid "Exception caught: %s" msgstr "Exception intercept้e : %s" # DB - Le c-format est f้minin, singulier ou pluriel (cf. 3 messages plus bas). -#: ../ex_eval.c:676 #, c-format msgid "%s made pending" msgstr "%s mise(s) en attente" -#: ../ex_eval.c:679 #, c-format msgid "%s resumed" msgstr "%s r้-้mise(s)" -#: ../ex_eval.c:683 #, c-format msgid "%s discarded" msgstr "%s ้limin้e(s)" -#: ../ex_eval.c:708 msgid "Exception" msgstr "Exception" -#: ../ex_eval.c:713 msgid "Error and interrupt" msgstr "Erreur et interruption" -#: ../ex_eval.c:715 msgid "Error" msgstr "Erreur" #. if (pending & CSTP_INTERRUPT) -#: ../ex_eval.c:717 msgid "Interrupt" msgstr "Interruption" -#: ../ex_eval.c:795 msgid "E579: :if nesting too deep" msgstr "E579: Imbrication de :if trop importante" -#: ../ex_eval.c:830 msgid "E580: :endif without :if" msgstr "E580: :endif sans :if" -#: ../ex_eval.c:873 msgid "E581: :else without :if" msgstr "E581: :else sans :if" -#: ../ex_eval.c:876 msgid "E582: :elseif without :if" msgstr "E582: :elseif sans :if" -#: ../ex_eval.c:880 msgid "E583: multiple :else" msgstr "E583: Il ne peut y avoir qu'un seul :else" -#: ../ex_eval.c:883 msgid "E584: :elseif after :else" msgstr "E584: :elseif apr่s :else" -#: ../ex_eval.c:941 msgid "E585: :while/:for nesting too deep" msgstr "E585: Imbrication de :while ou :for trop importante" -#: ../ex_eval.c:1028 msgid "E586: :continue without :while or :for" msgstr "E586: :continue sans :while ou :for" -#: ../ex_eval.c:1061 msgid "E587: :break without :while or :for" msgstr "E587: :break sans :while ou :for" -#: ../ex_eval.c:1102 msgid "E732: Using :endfor with :while" msgstr "E732: Utilisation de :endfor avec :while" -#: ../ex_eval.c:1104 msgid "E733: Using :endwhile with :for" msgstr "E733: Utilisation de :endwhile avec :for" -#: ../ex_eval.c:1247 msgid "E601: :try nesting too deep" msgstr "E601: Imbrication de :try trop importante" -#: ../ex_eval.c:1317 msgid "E603: :catch without :try" msgstr "E603: :catch sans :try" #. Give up for a ":catch" after ":finally" and ignore it. #. * Just parse. -#: ../ex_eval.c:1332 msgid "E604: :catch after :finally" msgstr "E604: :catch apr่s :finally" -#: ../ex_eval.c:1451 msgid "E606: :finally without :try" msgstr "E606: :finally sans :try" #. Give up for a multiple ":finally" and ignore it. -#: ../ex_eval.c:1467 msgid "E607: multiple :finally" msgstr "E607: Il ne peut y avoir qu'un seul :finally" -#: ../ex_eval.c:1571 msgid "E602: :endtry without :try" msgstr "E602: :endtry sans :try" -#: ../ex_eval.c:2026 msgid "E193: :endfunction not inside a function" msgstr "E193: :endfunction en dehors d'une fonction" -#: ../ex_getln.c:1643 msgid "E788: Not allowed to edit another buffer now" msgstr "E788: L'้dition d'un autre tampon n'est plus permise" -#: ../ex_getln.c:1656 msgid "E811: Not allowed to change buffer information now" msgstr "" "E811: Changement des informations du tampon n'est pas permise maintenant" # DB - TODO : Pas compris le message ni comment le d้clencher malgr้ une visite # dans le code. -#: ../ex_getln.c:3178 msgid "tagname" msgstr "nom du marqueur" # DB - TODO : Idem pr้c้dent. -#: ../ex_getln.c:3181 msgid " kind file\n" msgstr " type de fichier\n" -#: ../ex_getln.c:4799 msgid "'history' option is zero" msgstr "l'option 'history' vaut z้ro" # DB - Messages et les suivants : fichier .viminfo. # Pas de majuscule n้cessaire pour les messages d'apr่s. -#: ../ex_getln.c:5046 #, c-format msgid "" "\n" @@ -2161,311 +1800,232 @@ msgstr "" "\n" "# Historique %s (chronologie d้croissante) :\n" -#: ../ex_getln.c:5047 msgid "Command Line" msgstr "ligne de commande" -#: ../ex_getln.c:5048 msgid "Search String" msgstr "cha๎ne de recherche" -#: ../ex_getln.c:5049 msgid "Expression" msgstr "expression" -#: ../ex_getln.c:5050 msgid "Input Line" msgstr "ligne de saisie" -#: ../ex_getln.c:5117 +msgid "Debug Line" +msgstr "Ligne de d้bogage" + msgid "E198: cmd_pchar beyond the command length" msgstr "E198: cmd_pchar au-delเ de la longueur de la commande" -#: ../ex_getln.c:5279 msgid "E199: Active window or buffer deleted" msgstr "E199: Fen๊tre ou tampon actif effac้" -#: ../file_search.c:203 -msgid "E854: path too long for completion" -msgstr "E854: chemin trop long pour compl่tement" - -#: ../file_search.c:446 -#, c-format -msgid "" -"E343: Invalid path: '**[number]' must be at the end of the path or be " -"followed by '%s'." -msgstr "" -"E343: Chemin invalide : '**[nombre]' doit ๊tre เ la fin du chemin ou ๊tre " -"suivi de '%s'." - -#: ../file_search.c:1505 -#, c-format -msgid "E344: Can't find directory \"%s\" in cdpath" -msgstr "E344: R้pertoire \"%s\" introuvable dans 'cdpath'" - -#: ../file_search.c:1508 -#, c-format -msgid "E345: Can't find file \"%s\" in path" -msgstr "E345: Fichier \"%s\" introuvable dans 'path'" - -#: ../file_search.c:1512 -#, c-format -msgid "E346: No more directory \"%s\" found in cdpath" -msgstr "E346: Plus de r้pertoire \"%s\" dans 'cdpath'" - -#: ../file_search.c:1515 -#, c-format -msgid "E347: No more file \"%s\" found in path" -msgstr "E347: Plus de fichier \"%s\" dans 'path'" - -#: ../fileio.c:137 msgid "E812: Autocommands changed buffer or buffer name" msgstr "E812: Des autocommandes ont chang้ le tampon ou le nom du tampon" -#: ../fileio.c:368 msgid "Illegal file name" msgstr "Nom de fichier invalide" -#: ../fileio.c:395 ../fileio.c:476 ../fileio.c:2543 ../fileio.c:2578 msgid "is a directory" msgstr "est un r้pertoire" -#: ../fileio.c:397 msgid "is not a file" msgstr "n'est pas un fichier" -#: ../fileio.c:508 ../fileio.c:3522 +msgid "is a device (disabled with 'opendevice' option)" +msgstr "est un p้riph้rique (d้sactiv้ par l'option 'opendevice')" + msgid "[New File]" msgstr "[Nouveau fichier]" -#: ../fileio.c:511 msgid "[New DIRECTORY]" msgstr "[Nouveau RษPERTOIRE]" -#: ../fileio.c:529 ../fileio.c:532 msgid "[File too big]" msgstr "[Fichier trop volumineux]" -#: ../fileio.c:534 msgid "[Permission Denied]" msgstr "[Permission refus้e]" -#: ../fileio.c:653 msgid "E200: *ReadPre autocommands made the file unreadable" msgstr "E200: Les autocommandes *ReadPre ont rendu le fichier illisible" -#: ../fileio.c:655 msgid "E201: *ReadPre autocommands must not change current buffer" msgstr "" "E201: Autocommandes *ReadPre ne doivent pas modifier le contenu du tampon " "courant" -#: ../fileio.c:672 -msgid "Nvim: Reading from stdin...\n" +msgid "Vim: Reading from stdin...\n" msgstr "Vim : Lecture de stdin...\n" +msgid "Reading from stdin..." +msgstr "Lecture de stdin..." + #. Re-opening the original file failed! -#: ../fileio.c:909 msgid "E202: Conversion made file unreadable!" msgstr "E202: La conversion a rendu le fichier illisible !" -#. fifo or socket -#: ../fileio.c:1782 msgid "[fifo/socket]" msgstr "[fifo/socket]" -#. fifo -#: ../fileio.c:1788 msgid "[fifo]" msgstr "[fifo]" -#. or socket -#: ../fileio.c:1794 msgid "[socket]" msgstr "[socket]" -#. or character special -#: ../fileio.c:1801 msgid "[character special]" msgstr "[caract่re sp้cial]" -#: ../fileio.c:1815 msgid "[CR missing]" msgstr "[CR manquant]" -#: ../fileio.c:1819 msgid "[long lines split]" msgstr "[lignes longues coup้es]" -#: ../fileio.c:1823 ../fileio.c:3512 msgid "[NOT converted]" msgstr "[NON converti]" -#: ../fileio.c:1826 ../fileio.c:3515 msgid "[converted]" msgstr "[converti]" -#: ../fileio.c:1831 #, c-format -msgid "[CONVERSION ERROR in line %<PRId64>]" -msgstr "[ERREUR DE CONVERSION เ la ligne %<PRId64>]" +msgid "[CONVERSION ERROR in line %ld]" +msgstr "[ERREUR DE CONVERSION เ la ligne %ld]" -#: ../fileio.c:1835 #, c-format -msgid "[ILLEGAL BYTE in line %<PRId64>]" -msgstr "[OCTET INVALIDE เ la ligne %<PRId64>]" +msgid "[ILLEGAL BYTE in line %ld]" +msgstr "[OCTET INVALIDE เ la ligne %ld]" -#: ../fileio.c:1838 msgid "[READ ERRORS]" msgstr "[ERREURS DE LECTURE]" -#: ../fileio.c:2104 msgid "Can't find temp file for conversion" msgstr "Impossible de g้n้rer un fichier temporaire pour la conversion" -#: ../fileio.c:2110 msgid "Conversion with 'charconvert' failed" msgstr "La conversion avec 'charconvert' a ้chou้" # DB : Pas de majuscule ? -#: ../fileio.c:2113 msgid "can't read output of 'charconvert'" msgstr "Impossible de lire la sortie de 'charconvert'" -#: ../fileio.c:2437 msgid "E676: No matching autocommands for acwrite buffer" msgstr "E676: Pas d'autocommande correspondante pour le tampon acwrite" -#: ../fileio.c:2466 msgid "E203: Autocommands deleted or unloaded buffer to be written" msgstr "E203: Des autocommandes ont effac้ ou d้charg้ le tampon เ ้crire" -#: ../fileio.c:2486 msgid "E204: Autocommand changed number of lines in unexpected way" msgstr "" "E204: L'autocommande a modifi้ le nombre de lignes de mani่re inattendue" -#: ../fileio.c:2548 ../fileio.c:2565 +msgid "NetBeans disallows writes of unmodified buffers" +msgstr "NetBeans interdit l'้criture des tampons non modifi้s" + +msgid "Partial writes disallowed for NetBeans buffers" +msgstr "Netbeans interdit l'้criture partielle de ses tampons" + msgid "is not a file or writable device" msgstr "n'est pas un fichier ou un p้riph้rique inscriptible" -#: ../fileio.c:2601 +msgid "writing to device disabled with 'opendevice' option" +msgstr "้criture vers un p้riph้rique d้sactiv้ par l'option 'opendevice'" + msgid "is read-only (add ! to override)" msgstr "est en lecture seule (ajoutez ! pour passer outre)" -#: ../fileio.c:2886 msgid "E506: Can't write to backup file (add ! to override)" msgstr "E506: Impossible d'้crire la copie de secours (! pour passer outre)" -#: ../fileio.c:2898 msgid "E507: Close error for backup file (add ! to override)" msgstr "E507: Erreur de fermeture de la copie de secours (! pour passer outre)" -#: ../fileio.c:2901 msgid "E508: Can't read file for backup (add ! to override)" msgstr "" "E508: Impossible de lire le fichier pour la copie de secours (ajoutez ! pour " "passer outre)" -#: ../fileio.c:2923 msgid "E509: Cannot create backup file (add ! to override)" msgstr "" "E509: Impossible de cr้er la copie de secours (ajoutez ! pour passer outre)" -#: ../fileio.c:3008 msgid "E510: Can't make backup file (add ! to override)" msgstr "" "E510: Impossible de g้n้rer la copie de secours (ajoutez ! pour passer outre)" -#. Can't write without a tempfile! -#: ../fileio.c:3121 +msgid "E460: The resource fork would be lost (add ! to override)" +msgstr "" +"E460: Les ressources partag้es seraient perdues (ajoutez ! pour passer outre)" + msgid "E214: Can't find temp file for writing" msgstr "E214: Impossible de g้n้rer un fichier temporaire pour y ้crire" -#: ../fileio.c:3134 msgid "E213: Cannot convert (add ! to write without conversion)" msgstr "E213: Impossible de convertir (ajoutez ! pour ้crire sans convertir)" -#: ../fileio.c:3169 msgid "E166: Can't open linked file for writing" msgstr "E166: Impossible d'ouvrir le lien pour y ้crire" -#: ../fileio.c:3173 msgid "E212: Can't open file for writing" msgstr "E212: Impossible d'ouvrir le fichier pour y ้crire" -#: ../fileio.c:3363 msgid "E667: Fsync failed" msgstr "E667: Fsynch a ้chou้" -#: ../fileio.c:3398 msgid "E512: Close failed" msgstr "E512: Erreur de fermeture de fichier" -#: ../fileio.c:3436 msgid "E513: write error, conversion failed (make 'fenc' empty to override)" msgstr "" "E513: Erreur d'้criture, ้chec de conversion (videz 'fenc' pour passer outre)" -#: ../fileio.c:3441 #, c-format msgid "" -"E513: write error, conversion failed in line %<PRId64> (make 'fenc' empty to " +"E513: write error, conversion failed in line %ld (make 'fenc' empty to " "override)" msgstr "" -"E513: Erreur d'้criture, ้chec de conversion เ la ligne %<PRId64> (videz " -"'fenc' pour passer outre)" +"E513: Erreur d'้criture, ้chec de conversion เ la ligne %ld (videz 'fenc' " +"pour passer outre)" -#: ../fileio.c:3448 msgid "E514: write error (file system full?)" msgstr "E514: erreur d'้criture (syst่me de fichiers plein ?)" -#: ../fileio.c:3506 msgid " CONVERSION ERROR" msgstr " ERREUR DE CONVERSION" -#: ../fileio.c:3509 #, c-format -msgid " in line %<PRId64>;" -msgstr " เ la ligne %<PRId64>" +msgid " in line %ld;" +msgstr " เ la ligne %ld" -#: ../fileio.c:3519 msgid "[Device]" msgstr "[P้riph.]" -#: ../fileio.c:3522 msgid "[New]" msgstr "[Nouveau]" -#: ../fileio.c:3535 msgid " [a]" msgstr " [a]" -#: ../fileio.c:3535 msgid " appended" msgstr " ajout้(s)" -#: ../fileio.c:3537 msgid " [w]" msgstr " [e]" -#: ../fileio.c:3537 msgid " written" msgstr " ้crit(s)" -#: ../fileio.c:3579 msgid "E205: Patchmode: can't save original file" msgstr "E205: Patchmode : impossible d'enregistrer le fichier original" -#: ../fileio.c:3602 msgid "E206: patchmode: can't touch empty original file" msgstr "E206: patchmode : impossible de cr้er le fichier original vide" -#: ../fileio.c:3616 msgid "E207: Can't delete backup file" msgstr "E207: Impossible d'effacer la copie de secours" -#: ../fileio.c:3672 msgid "" "\n" "WARNING: Original file may be lost or damaged\n" @@ -2474,99 +2034,78 @@ msgstr "" "ALERTE: Le fichier original est peut-๊tre perdu ou endommag้\n" # DB - todo : un peu long... -#: ../fileio.c:3675 msgid "don't quit the editor until the file is successfully written!" msgstr "" "ne quittez pas l'้diteur tant que le fichier n'est pas correctement " "enregistr้ !" -#: ../fileio.c:3795 msgid "[dos]" msgstr "[dos]" -#: ../fileio.c:3795 msgid "[dos format]" msgstr "[format dos]" -#: ../fileio.c:3801 msgid "[mac]" msgstr "[mac]" -#: ../fileio.c:3801 msgid "[mac format]" msgstr "[format mac]" -#: ../fileio.c:3807 msgid "[unix]" msgstr "[unix]" -#: ../fileio.c:3807 msgid "[unix format]" msgstr "[format unix]" -#: ../fileio.c:3831 msgid "1 line, " msgstr "1 ligne, " -#: ../fileio.c:3833 #, c-format -msgid "%<PRId64> lines, " -msgstr "%<PRId64> lignes, " +msgid "%ld lines, " +msgstr "%ld lignes, " -#: ../fileio.c:3836 msgid "1 character" msgstr "1 caract่re" -#: ../fileio.c:3838 #, c-format -msgid "%<PRId64> characters" -msgstr "%<PRId64> caract่res" +msgid "%lld characters" +msgstr "%lld caract่res" -#: ../fileio.c:3849 msgid "[noeol]" msgstr "[noeol]" -#: ../fileio.c:3849 msgid "[Incomplete last line]" msgstr "[Derni่re ligne incompl่te]" #. don't overwrite messages here #. must give this prompt #. don't use emsg() here, don't want to flush the buffers -#: ../fileio.c:3865 msgid "WARNING: The file has been changed since reading it!!!" msgstr "ALERTE : Le fichier a ้t้ modifi้ depuis que Vim l'a lu !" -#: ../fileio.c:3867 msgid "Do you really want to write to it" msgstr "Voulez-vous vraiment ้crire dedans" -#: ../fileio.c:4648 #, c-format msgid "E208: Error writing to \"%s\"" msgstr "E208: Erreur lors de l'้criture dans \"%s\"" -#: ../fileio.c:4655 #, c-format msgid "E209: Error closing \"%s\"" msgstr "E209: Erreur lors de la fermeture de \"%s\"" -#: ../fileio.c:4657 #, c-format msgid "E210: Error reading \"%s\"" msgstr "E210: Erreur lors de la lecture de \"%s\"" -#: ../fileio.c:4883 msgid "E246: FileChangedShell autocommand deleted buffer" msgstr "E246: L'autocommande FileChangedShell a effac้ le tampon" -#: ../fileio.c:4894 #, c-format msgid "E211: File \"%s\" no longer available" msgstr "E211: Le fichier \"%s\" n'est plus disponible" # DB - todo : Suggestion. Bof bof, เ am้liorer. -#: ../fileio.c:4906 #, c-format msgid "" "W12: Warning: File \"%s\" has changed and the buffer was changed in Vim as " @@ -2574,40 +2113,32 @@ msgid "" msgstr "" "W12: Alerte : Le fichier \"%s\" a ้t้ modifi้, ainsi que le tampon dans Vim" -#: ../fileio.c:4907 msgid "See \":help W12\" for more info." msgstr "Consultez \":help W12\" pour plus d'information." -#: ../fileio.c:4910 #, c-format msgid "W11: Warning: File \"%s\" has changed since editing started" msgstr "W11: Alerte : Le fichier \"%s\" a chang้ depuis le d้but de l'้dition" -#: ../fileio.c:4911 msgid "See \":help W11\" for more info." msgstr "Consultez \":help W11\" pour plus d'information." -#: ../fileio.c:4914 #, c-format msgid "W16: Warning: Mode of file \"%s\" has changed since editing started" msgstr "" "W16: Alerte : Les permissions de \"%s\" ont chang้ depuis le d้but de " "l'้dition" -#: ../fileio.c:4915 msgid "See \":help W16\" for more info." msgstr "Consultez \":help W16\" pour plus d'information." -#: ../fileio.c:4927 #, c-format msgid "W13: Warning: File \"%s\" has been created after editing started" msgstr "W13: Alerte : Le fichier \"%s\" a ้t้ cr้้ apr่s le d้but de l'้dition" -#: ../fileio.c:4947 msgid "Warning" msgstr "Alerte" -#: ../fileio.c:4948 msgid "" "&OK\n" "&Load File" @@ -2615,48 +2146,45 @@ msgstr "" "&Ok\n" "&Charger le fichier" -#: ../fileio.c:5065 #, c-format msgid "E462: Could not prepare for reloading \"%s\"" msgstr "E462: Impossible de pr้parer le rechargement de \"%s\"" -#: ../fileio.c:5078 #, c-format msgid "E321: Could not reload \"%s\"" msgstr "E321: Impossible de recharger \"%s\"" -#: ../fileio.c:5601 msgid "--Deleted--" msgstr "--Effac้--" -#: ../fileio.c:5732 #, c-format msgid "auto-removing autocommand: %s <buffer=%d>" msgstr "Autocommandes marqu้es pour auto-suppression : %s <tampon=%d>" #. the group doesn't exist -#: ../fileio.c:5772 #, c-format msgid "E367: No such group: \"%s\"" msgstr "E367: Aucun groupe \"%s\"" -#: ../fileio.c:5897 +msgid "E936: Cannot delete the current group" +msgstr "E936: Impossible de supprimer le groupe courant" + +msgid "W19: Deleting augroup that is still in use" +msgstr "W19: Effacement d'augroup toujours en usage" + #, c-format msgid "E215: Illegal character after *: %s" msgstr "E215: Caract่re non valide apr่s * : %s" -#: ../fileio.c:5905 #, c-format msgid "E216: No such event: %s" msgstr "E216: Aucun ้v้nement %s" -#: ../fileio.c:5907 #, c-format msgid "E216: No such group or event: %s" msgstr "E216: Aucun ้v้nement ou groupe %s" #. Highlight title -#: ../fileio.c:6090 msgid "" "\n" "--- Auto-Commands ---" @@ -2664,776 +2192,580 @@ msgstr "" "\n" "--- Auto-commandes ---" -#: ../fileio.c:6293 #, c-format msgid "E680: <buffer=%d>: invalid buffer number " msgstr "E680: <buffer=%d> : num้ro de tampon invalide" -#: ../fileio.c:6370 msgid "E217: Can't execute autocommands for ALL events" msgstr "" "E217: Impossible d'ex้cuter les autocommandes pour TOUS les ้v้nements (ALL)" -#: ../fileio.c:6393 msgid "No matching autocommands" msgstr "Aucune autocommande correspondante" -#: ../fileio.c:6831 msgid "E218: autocommand nesting too deep" msgstr "E218: autocommandes trop imbriqu้es" -#: ../fileio.c:7143 #, c-format msgid "%s Auto commands for \"%s\"" msgstr "Autocommandes %s pour \"%s\"" -#: ../fileio.c:7149 #, c-format msgid "Executing %s" msgstr "Ex้cution de %s" -#: ../fileio.c:7211 #, c-format msgid "autocommand %s" msgstr "autocommande %s" -#: ../fileio.c:7795 msgid "E219: Missing {." msgstr "E219: { manquant." -#: ../fileio.c:7797 msgid "E220: Missing }." msgstr "E220: } manquant." -#: ../fold.c:93 msgid "E490: No fold found" msgstr "E490: Aucun repli trouv้" -#: ../fold.c:544 msgid "E350: Cannot create fold with current 'foldmethod'" msgstr "E350: Impossible de cr้er un repli avec la 'foldmethod'e actuelle" -#: ../fold.c:546 msgid "E351: Cannot delete fold with current 'foldmethod'" msgstr "E351: Impossible de supprimer un repli avec la 'foldmethod'e actuelle" -#: ../fold.c:1784 #, c-format -msgid "+--%3ld lines folded " -msgstr "+--%3ld lignes repli้es " +msgid "+--%3ld line folded " +msgid_plural "+--%3ld lines folded " +msgstr[0] "+--%3ld ligne repli้e " +msgstr[1] "+--%3ld lignes repli้es " -#. buffer has already been read -#: ../getchar.c:273 msgid "E222: Add to read buffer" msgstr "E222: Ajout au tampon de lecture" -#: ../getchar.c:2040 msgid "E223: recursive mapping" msgstr "E223: mappage r้cursif" -#: ../getchar.c:2849 #, c-format msgid "E224: global abbreviation already exists for %s" msgstr "E224: une abr้viation globale existe d้jเ pour %s" -#: ../getchar.c:2852 #, c-format msgid "E225: global mapping already exists for %s" msgstr "E225: un mappage global existe d้jเ pour %s" -#: ../getchar.c:2952 #, c-format msgid "E226: abbreviation already exists for %s" msgstr "E226: une abr้viation existe d้jเ pour %s" -#: ../getchar.c:2955 #, c-format msgid "E227: mapping already exists for %s" msgstr "E227: un mappage existe d้jเ pour %s" -#: ../getchar.c:3008 msgid "No abbreviation found" msgstr "Aucune abr้viation trouv้e" -#: ../getchar.c:3010 msgid "No mapping found" msgstr "Aucun mappage trouv้" -#: ../getchar.c:3974 msgid "E228: makemap: Illegal mode" msgstr "E228: makemap : mode invalide" -# msgstr "--Pas de lignes dans le tampon--" -# DB - todo : ou encore : msgstr "--Aucune ligne dans le tampon--" -#. key value of 'cedit' option -#. type of cmdline window or 0 -#. result of cmdline window or 0 -#: ../globals.h:924 -msgid "--No lines in buffer--" -msgstr "--Le tampon est vide--" - -#. -#. * The error messages that can be shared are included here. -#. * Excluded are errors that are only used once and debugging messages. -#. -#: ../globals.h:996 -msgid "E470: Command aborted" -msgstr "E470: Commande annul้e" - -#: ../globals.h:997 -msgid "E471: Argument required" -msgstr "E471: Argument requis" - -#: ../globals.h:998 -msgid "E10: \\ should be followed by /, ? or &" -msgstr "E10: \\ devrait ๊tre suivi de /, ? ou &" - -#: ../globals.h:1000 -msgid "E11: Invalid in command-line window; <CR> executes, CTRL-C quits" +msgid "E851: Failed to create a new process for the GUI" msgstr "" -"E11: Invalide dans la fen๊tre ligne-de-commande ; <CR> ex้cute, CTRL-C quitte" +"E851: ษchec lors de la cr้ation d'un nouveau processus pour l'interface " +"graphique" -#: ../globals.h:1002 -msgid "E12: Command not allowed from exrc/vimrc in current dir or tag search" +msgid "E852: The child process failed to start the GUI" msgstr "" -"E12: commande non autoris้e depuis un exrc/vimrc dans r้pertoire courant ou " -"une recherche de marqueur" - -#: ../globals.h:1003 -msgid "E171: Missing :endif" -msgstr "E171: :endif manquant" +"E852: Le processus fils n'a pas r้ussi เ d้marrer l'interface graphique" -#: ../globals.h:1004 -msgid "E600: Missing :endtry" -msgstr "E600: :endtry manquant" +msgid "E229: Cannot start the GUI" +msgstr "E229: Impossible de d้marrer l'interface graphique" -#: ../globals.h:1005 -msgid "E170: Missing :endwhile" -msgstr "E170: :endwhile manquant" - -#: ../globals.h:1006 -msgid "E170: Missing :endfor" -msgstr "E170: :endfor manquant" - -#: ../globals.h:1007 -msgid "E588: :endwhile without :while" -msgstr "E588: :endwhile sans :while" - -#: ../globals.h:1008 -msgid "E588: :endfor without :for" -msgstr "E588: :endfor sans :for" - -#: ../globals.h:1009 -msgid "E13: File exists (add ! to override)" -msgstr "E13: Le fichier existe d้jเ (ajoutez ! pour passer outre)" - -#: ../globals.h:1010 -msgid "E472: Command failed" -msgstr "E472: La commande a ้chou้" - -#: ../globals.h:1011 -msgid "E473: Internal error" -msgstr "E473: Erreur interne" - -#: ../globals.h:1012 -msgid "Interrupted" -msgstr "Interrompu" +#, c-format +msgid "E230: Cannot read from \"%s\"" +msgstr "E230: Impossible de lire \"%s\"" -#: ../globals.h:1013 -msgid "E14: Invalid address" -msgstr "E14: Adresse invalide" +msgid "E665: Cannot start GUI, no valid font found" +msgstr "" +"E665: Impossible de d้marrer l'IHM graphique, aucune police valide trouv้e" -#: ../globals.h:1014 -msgid "E474: Invalid argument" -msgstr "E474: Argument invalide" +msgid "E231: 'guifontwide' invalid" +msgstr "E231: 'guifontwide' est invalide" -#: ../globals.h:1015 -#, c-format -msgid "E475: Invalid argument: %s" -msgstr "E475: Argument invalide : %s" +msgid "E599: Value of 'imactivatekey' is invalid" +msgstr "E599: Valeur de 'imactivatekey' invalide" -#: ../globals.h:1016 #, c-format -msgid "E15: Invalid expression: %s" -msgstr "E15: Expression invalide : %s" +msgid "E254: Cannot allocate color %s" +msgstr "E254: Impossible d'allouer la couleur %s" -#: ../globals.h:1017 -msgid "E16: Invalid range" -msgstr "E16: Plage invalide" +msgid "No match at cursor, finding next" +msgstr "Aucune correspondance sous le curseur, recherche de la suivante" -#: ../globals.h:1018 -msgid "E476: Invalid command" -msgstr "E476: Commande invalide" +msgid "<cannot open> " +msgstr "<impossible d'ouvrir> " -#: ../globals.h:1019 #, c-format -msgid "E17: \"%s\" is a directory" -msgstr "E17: \"%s\" est un r้pertoire" +msgid "E616: vim_SelFile: can't get font %s" +msgstr "E616: vim_SelFile : impossible d'obtenir la police %s" -#: ../globals.h:1020 -#, fuzzy -msgid "E900: Invalid job id" -msgstr "E49: Valeur de d้filement invalide" +msgid "E614: vim_SelFile: can't return to current directory" +msgstr "E614: vim_SelFile : impossible de revenir dans le r้pertoire courant" -#: ../globals.h:1021 -msgid "E901: Job table is full" -msgstr "" +msgid "Pathname:" +msgstr "Chemin :" -#: ../globals.h:1024 -#, c-format -msgid "E364: Library call failed for \"%s()\"" -msgstr "E364: L'appel เ la biblioth่que a ้chou้ pour \"%s()\"" +msgid "E615: vim_SelFile: can't get current directory" +msgstr "E615: vim_SelFile : impossible d'obtenir le r้pertoire courant" -#: ../globals.h:1026 -msgid "E19: Mark has invalid line number" -msgstr "E19: La marque a un num้ro de ligne invalide" +msgid "OK" +msgstr "Ok" -#: ../globals.h:1027 -msgid "E20: Mark not set" -msgstr "E20: Marque non positionn้e" +msgid "Cancel" +msgstr "Annuler" -#: ../globals.h:1029 -msgid "E21: Cannot make changes, 'modifiable' is off" -msgstr "E21: Impossible de modifier, 'modifiable' est d้sactiv้" +msgid "Scrollbar Widget: Could not get geometry of thumb pixmap." +msgstr "Widget scrollbar : Impossible d'obtenir la g้om้trie du pixmap 'thumb'" -#: ../globals.h:1030 -msgid "E22: Scripts nested too deep" -msgstr "E22: Trop de r้cursion dans les scripts" +msgid "Vim dialog" +msgstr "Vim" -#: ../globals.h:1031 -msgid "E23: No alternate file" -msgstr "E23: Pas de fichier alternatif" +msgid "E232: Cannot create BalloonEval with both message and callback" +msgstr "E232: Impossible de cr้er un BalloonEval avec message ET callback" -#: ../globals.h:1032 -msgid "E24: No such abbreviation" -msgstr "E24: Cette abr้viation n'existe pas" +msgid "_Cancel" +msgstr "_Annuler" -#: ../globals.h:1033 -msgid "E477: No ! allowed" -msgstr "E477: Le ! n'est pas autoris้" +msgid "_Save" +msgstr "_Enregistrer" -#: ../globals.h:1035 -msgid "E25: Nvim does not have a built-in GUI" -msgstr "E25: L'interface graphique n'a pas ้t้ compil้e dans cette version" +msgid "_Open" +msgstr "_Ouvrir" -#: ../globals.h:1036 -#, c-format -msgid "E28: No such highlight group name: %s" -msgstr "E28: Aucun nom de groupe de surbrillance %s" +msgid "_OK" +msgstr "_Ok" -#: ../globals.h:1037 -msgid "E29: No inserted text yet" -msgstr "E29: Pas encore de texte ins้r้" +msgid "" +"&Yes\n" +"&No\n" +"&Cancel" +msgstr "" +"&Oui\n" +"&Non\n" +"&Annuler" -#: ../globals.h:1038 -msgid "E30: No previous command line" -msgstr "E30: Aucune ligne de commande pr้c้dente" +msgid "Yes" +msgstr "Oui" -#: ../globals.h:1039 -msgid "E31: No such mapping" -msgstr "E31: Mappage inexistant" +msgid "No" +msgstr "Non" -#: ../globals.h:1040 -msgid "E479: No match" -msgstr "E479: Aucune correspondance" +# todo '_' is for hotkey, i guess? +msgid "Input _Methods" +msgstr "_M้thodes de saisie" -#: ../globals.h:1041 -#, c-format -msgid "E480: No match: %s" -msgstr "E480: Aucune correspondance : %s" +msgid "VIM - Search and Replace..." +msgstr "Remplacer - Vim" -#: ../globals.h:1042 -msgid "E32: No file name" -msgstr "E32: Aucun nom de fichier" +msgid "VIM - Search..." +msgstr "Rechercher - Vim" -#: ../globals.h:1044 -msgid "E33: No previous substitute regular expression" -msgstr "E33: Aucune expression r้guli่re de substitution pr้c้dente" +msgid "Find what:" +msgstr "Rechercher :" -#: ../globals.h:1045 -msgid "E34: No previous command" -msgstr "E34: Aucune commande pr้c้dente" +msgid "Replace with:" +msgstr "Remplacer par :" -#: ../globals.h:1046 -msgid "E35: No previous regular expression" -msgstr "E35: Aucune expression r้guli่re pr้c้dente" +#. whole word only button +msgid "Match whole word only" +msgstr "Mots entiers seulement" -#: ../globals.h:1047 -msgid "E481: No range allowed" -msgstr "E481: Les plages ne sont pas autoris้es" +#. match case button +msgid "Match case" +msgstr "Respecter la casse" -#: ../globals.h:1048 -msgid "E36: Not enough room" -msgstr "E36: Pas assez de place" +msgid "Direction" +msgstr "Direction" -#: ../globals.h:1049 -#, c-format -msgid "E482: Can't create file %s" -msgstr "E482: Impossible de cr้er le fichier %s" +#. 'Up' and 'Down' buttons +msgid "Up" +msgstr "Haut" -#: ../globals.h:1050 -msgid "E483: Can't get temp file name" -msgstr "E483: Impossible d'obtenir un nom de fichier temporaire" +msgid "Down" +msgstr "Bas" -#: ../globals.h:1051 -#, c-format -msgid "E484: Can't open file %s" -msgstr "E484: Impossible d'ouvrir le fichier \"%s\"" +msgid "Find Next" +msgstr "Suivant" -#: ../globals.h:1052 -#, c-format -msgid "E485: Can't read file %s" -msgstr "E485: Impossible de lire le fichier %s" +msgid "Replace" +msgstr "Remplacer" -#: ../globals.h:1054 -msgid "E37: No write since last change (add ! to override)" -msgstr "E37: Modifications non enregistr้es (ajoutez ! pour passer outre)" +msgid "Replace All" +msgstr "Remplacer tout" -# AB - Il faut respecter l'esprit plus que la lettre. Dans le cas pr้sent, -# nettement plus. -#: ../globals.h:1055 -#, fuzzy -msgid "E37: No write since last change" -msgstr "[Attention : tout n'est pas enregistr้]\n" +msgid "_Close" +msgstr "_Fermer" -#: ../globals.h:1056 -msgid "E38: Null argument" -msgstr "E38: Argument null" +msgid "Vim: Received \"die\" request from session manager\n" +msgstr "Vim : Une requ๊te \"die\" a ้t้ re็ue par le gestionnaire de session\n" -#: ../globals.h:1057 -msgid "E39: Number expected" -msgstr "E39: Nombre attendu" +msgid "Close tab" +msgstr "Fermer l'onglet" -#: ../globals.h:1058 -#, c-format -msgid "E40: Can't open errorfile %s" -msgstr "E40: Impossible d'ouvrir le fichier d'erreurs %s" +msgid "New tab" +msgstr "Nouvel onglet" -#: ../globals.h:1059 -msgid "E41: Out of memory!" -msgstr "E41: M้moire ้puis้e" +# DB - todo : un peu long. Cet entr้e de menu permet d'ouvrir un fichier +# dans un nouvel onglet via le s้lecteur de fichiers graphique. +msgid "Open Tab..." +msgstr "Ouvrir dans un onglet..." -#: ../globals.h:1060 -msgid "Pattern not found" -msgstr "Motif introuvable" +msgid "Vim: Main window unexpectedly destroyed\n" +msgstr "Vim : Fen๊tre principale d้truite inopin้ment\n" -#: ../globals.h:1061 -#, c-format -msgid "E486: Pattern not found: %s" -msgstr "E486: Motif introuvable : %s" +msgid "&Filter" +msgstr "&Filtrer" -#: ../globals.h:1062 -msgid "E487: Argument must be positive" -msgstr "E487: L'argument doit ๊tre positif" +msgid "&Cancel" +msgstr "&Annuler" -#: ../globals.h:1064 -msgid "E459: Cannot go back to previous directory" -msgstr "E459: Impossible de retourner au r้pertoire pr้c้dent" +msgid "Directories" +msgstr "R้pertoires" -#: ../globals.h:1066 -msgid "E42: No Errors" -msgstr "E42: Aucune erreur" +msgid "Filter" +msgstr "Filtre" -# DB - TODO : trouver une traduction valable et attest้e pour "location". -#: ../globals.h:1067 -msgid "E776: No location list" -msgstr "E776: Aucune liste d'emplacements" +msgid "&Help" +msgstr "&Aide" -#: ../globals.h:1068 -msgid "E43: Damaged match string" -msgstr "E43: La cha๎ne de recherche est endommag้e" +msgid "Files" +msgstr "Fichiers" -#: ../globals.h:1069 -msgid "E44: Corrupted regexp program" -msgstr "E44: L'automate de regexp est corrompu" +msgid "&OK" +msgstr "&Ok" -#: ../globals.h:1071 -msgid "E45: 'readonly' option is set (add ! to override)" -msgstr "E45: L'option 'readonly' est activ้e (ajoutez ! pour passer outre)" +msgid "Selection" +msgstr "S้lection" -#: ../globals.h:1073 -#, c-format -msgid "E46: Cannot change read-only variable \"%s\"" -msgstr "E46: La variable \"%s\" est en lecture seule" +msgid "Find &Next" +msgstr "Suiva&nt" -#: ../globals.h:1075 -#, c-format -msgid "E794: Cannot set variable in the sandbox: \"%s\"" -msgstr "" -"E794: Impossible de modifier une variable depuis le bac เ sable : \"%s\"" +msgid "&Replace" +msgstr "&Remplacer" -#: ../globals.h:1076 -msgid "E47: Error while reading errorfile" -msgstr "E47: Erreur lors de la lecture du fichier d'erreurs" +msgid "Replace &All" +msgstr "Rempl&acer tout" -#: ../globals.h:1078 -msgid "E48: Not allowed in sandbox" -msgstr "E48: Op้ration interdite dans le bac เ sable" +msgid "&Undo" +msgstr "Ann&uler" -#: ../globals.h:1080 -msgid "E523: Not allowed here" -msgstr "E523: Interdit เ cet endroit" +msgid "Open tab..." +msgstr "Ouvrir dans un onglet..." -#: ../globals.h:1082 -msgid "E359: Screen mode setting not supported" -msgstr "E359: Choix du mode d'้cran non support้" +msgid "Find string (use '\\\\' to find a '\\')" +msgstr "Chercher une cha๎ne (utilisez '\\\\' pour chercher un '\\')" -#: ../globals.h:1083 -msgid "E49: Invalid scroll size" -msgstr "E49: Valeur de d้filement invalide" +msgid "Find & Replace (use '\\\\' to find a '\\')" +msgstr "Chercher et remplacer (utilisez '\\\\' pour trouver un '\\')" -#: ../globals.h:1084 -msgid "E91: 'shell' option is empty" -msgstr "E91: L'option 'shell' est vide" +# DB - Traduction non indispensable puisque le code indique qu'il s'agit d'un +# param้trage bidon afin de s้lectionner un r้pertoire plut๔t qu'un +# fichier. +#. We fake this: Use a filter that doesn't select anything and a default +#. * file name that won't be used. +msgid "Not Used" +msgstr "Non utilis้" -#: ../globals.h:1085 -msgid "E255: Couldn't read in sign data!" -msgstr "E255: Impossible de lire les donn้es du symbole !" +# DB - Traduction non indispensable puisque le code indique qu'il s'agit d'un +# param้trage bidon afin de s้lectionner un r้pertoire plut๔t qu'un +# fichier. +msgid "Directory\t*.nothing\n" +msgstr "R้pertoire\t*.rien\n" -#: ../globals.h:1086 -msgid "E72: Close error on swap file" -msgstr "E72: Erreur lors de la fermeture du fichier d'้change" +#, c-format +msgid "E671: Cannot find window title \"%s\"" +msgstr "E671: Titre de fen๊tre \"%s\" introuvable" -#: ../globals.h:1087 -msgid "E73: tag stack empty" -msgstr "E73: La pile des marqueurs est vide" +#, c-format +msgid "E243: Argument not supported: \"-%s\"; Use the OLE version." +msgstr "E243: Argument non support้ : \"-%s\" ; Utilisez la version OLE." -#: ../globals.h:1088 -msgid "E74: Command too complex" -msgstr "E74: Commande trop complexe" +msgid "E672: Unable to open window inside MDI application" +msgstr "E672: Impossible d'ouvrir une fen๊tre dans une application MDI" -#: ../globals.h:1089 -msgid "E75: Name too long" -msgstr "E75: Nom trop long" +# DB - todo : perfectible. +msgid "Vim E458: Cannot allocate colormap entry, some colors may be incorrect" +msgstr "" +"Vim E458: Erreur d'allocation de couleurs, couleurs possiblement incorrectes" -#: ../globals.h:1090 -msgid "E76: Too many [" -msgstr "E76: Trop de [" +# DB - todo : La VF est-elle compr้hensible ? +#, c-format +msgid "E250: Fonts for the following charsets are missing in fontset %s:" +msgstr "" +"E250: Des polices manquent dans %s pour les jeux de caract่res suivants :" -#: ../globals.h:1091 -msgid "E77: Too many file names" -msgstr "E77: Trop de noms de fichiers" +#, c-format +msgid "E252: Fontset name: %s" +msgstr "E252: Nom du jeu de polices : %s" -#: ../globals.h:1092 -msgid "E488: Trailing characters" -msgstr "E488: Caract่res surnum้raires" +#, c-format +msgid "Font '%s' is not fixed-width" +msgstr "La police '%s' n'a pas une largeur fixe" -#: ../globals.h:1093 -msgid "E78: Unknown mark" -msgstr "E78: Marque inconnue" +#, c-format +msgid "E253: Fontset name: %s" +msgstr "E253: Nom du jeu de polices : %s" -#: ../globals.h:1094 -msgid "E79: Cannot expand wildcards" -msgstr "E79: Impossible de d้velopper les m้tacaract่res" +#, c-format +msgid "Font0: %s" +msgstr "Font0: %s" -#: ../globals.h:1096 -msgid "E591: 'winheight' cannot be smaller than 'winminheight'" -msgstr "E591: 'winheight' ne peut pas ๊tre plus petit que 'winminheight'" +#, c-format +msgid "Font1: %s" +msgstr "Font1: %s" -#: ../globals.h:1098 -msgid "E592: 'winwidth' cannot be smaller than 'winminwidth'" -msgstr "E592: 'winwidth' ne peut pas ๊tre plus petit que 'winminwidth'" +#, c-format +msgid "Font%ld width is not twice that of font0" +msgstr "La largeur de Font%ld n'est pas le double de celle de Font0" -#: ../globals.h:1099 -msgid "E80: Error while writing" -msgstr "E80: Erreur lors de l'้criture" +#, c-format +msgid "Font0 width: %ld" +msgstr "Largeur de Font0 : %ld" -#: ../globals.h:1100 -msgid "Zero count" -msgstr "Le quantificateur est nul" +#, c-format +msgid "Font1 width: %ld" +msgstr "Largeur de Font1 : %ld" -#: ../globals.h:1101 -msgid "E81: Using <SID> not in a script context" -msgstr "E81: <SID> utilis้ en dehors d'un script" +# DB - todo : Pas certain de mon coup, ici... +msgid "Invalid font specification" +msgstr "La sp้cification de la police est invalide" -#: ../globals.h:1102 -#, c-format -msgid "E685: Internal error: %s" -msgstr "E685: Erreur interne : %s" +msgid "&Dismiss" +msgstr "Aban&donner" -#: ../globals.h:1104 -msgid "E363: pattern uses more memory than 'maxmempattern'" -msgstr "E363: le motif utilise plus de m้moire que 'maxmempattern'" +# DB - todo : Pas certain de mon coup, ici... +msgid "no specific match" +msgstr "aucune correspondance particuli่re" -#: ../globals.h:1105 -msgid "E749: empty buffer" -msgstr "E749: tampon vide" +msgid "Vim - Font Selector" +msgstr "Choisir une police - Vim" -#: ../buffer.c:1587 -#, c-format -msgid "E86: Buffer %<PRId64> does not exist" -msgstr "E86: Le tampon %<PRId64> n'existe pas" +msgid "Name:" +msgstr "Nom :" -#: ../globals.h:1108 -msgid "E682: Invalid search pattern or delimiter" -msgstr "E682: D้limiteur ou motif de recherche invalide" +#. create toggle button +msgid "Show size in Points" +msgstr "Afficher la taille en Points" -#: ../globals.h:1109 -msgid "E139: File is loaded in another buffer" -msgstr "E139: Le fichier est charg้ dans un autre tampon" +msgid "Encoding:" +msgstr "Encodage :" -#: ../globals.h:1110 -#, c-format -msgid "E764: Option '%s' is not set" -msgstr "E764: L'option '%s' n'est pas activ้e" +msgid "Font:" +msgstr "Police :" -#: ../globals.h:1111 -msgid "E850: Invalid register name" -msgstr "E850: Nom de registre invalide" +msgid "Style:" +msgstr "Style :" -#: ../globals.h:1114 -msgid "search hit TOP, continuing at BOTTOM" -msgstr "La recherche a atteint le HAUT, et continue en BAS" +msgid "Size:" +msgstr "Taille :" -#: ../globals.h:1115 -msgid "search hit BOTTOM, continuing at TOP" -msgstr "La recherche a atteint le BAS, et continue en HAUT" +msgid "E256: Hangul automata ERROR" +msgstr "E256: ERREUR dans l'automate Hangul" -#: ../hardcopy.c:240 msgid "E550: Missing colon" msgstr "E550: ':' manquant" # DB - Il s'agit ici d'un probl่me lors du parsing d'une option dont le contenu # est une liste d'้l้ments s้par้s par des virgules. -#: ../hardcopy.c:252 msgid "E551: Illegal component" msgstr "E551: ้l้ment invalide" -#: ../hardcopy.c:259 msgid "E552: digit expected" msgstr "E552: chiffre attendu" -#: ../hardcopy.c:473 #, c-format msgid "Page %d" msgstr "Page %d" -#: ../hardcopy.c:597 msgid "No text to be printed" msgstr "Aucun texte เ imprimer" -#: ../hardcopy.c:668 #, c-format msgid "Printing page %d (%d%%)" msgstr "Impression de la page %d (%d%%)" -#: ../hardcopy.c:680 #, c-format msgid " Copy %d of %d" msgstr " Copie %d sur %d" -#: ../hardcopy.c:733 #, c-format msgid "Printed: %s" msgstr "Imprim้ : %s" -#: ../hardcopy.c:740 msgid "Printing aborted" msgstr "Impression interrompue" -#: ../hardcopy.c:1365 msgid "E455: Error writing to PostScript output file" msgstr "E455: Erreur lors de l'้criture du fichier PostScript" -#: ../hardcopy.c:1747 #, c-format msgid "E624: Can't open file \"%s\"" msgstr "E624: Impossible d'ouvrir le fichier \"%s\"" -#: ../hardcopy.c:1756 ../hardcopy.c:2470 #, c-format msgid "E457: Can't read PostScript resource file \"%s\"" msgstr "E457: Impossible de lire le fichier de ressource PostScript \"%s\"" -#: ../hardcopy.c:1772 #, c-format msgid "E618: file \"%s\" is not a PostScript resource file" msgstr "E618: \"%s\" n'est pas un fichier de ressource PostScript" -#: ../hardcopy.c:1788 ../hardcopy.c:1805 ../hardcopy.c:1844 #, c-format msgid "E619: file \"%s\" is not a supported PostScript resource file" msgstr "E619: \"%s\" n'est pas un fichier de ressource PostScript support้" -#: ../hardcopy.c:1856 #, c-format msgid "E621: \"%s\" resource file has wrong version" msgstr "E621: La version du fichier de ressource \"%s\" est erron้e" -#: ../hardcopy.c:2225 msgid "E673: Incompatible multi-byte encoding and character set." msgstr "E673: Jeu de caract่res et encodage multi-octets incompatibles" -#: ../hardcopy.c:2238 msgid "E674: printmbcharset cannot be empty with multi-byte encoding." msgstr "" "E674: 'printmbcharset' ne peut pas ๊tre vide avec un encodage multi-octets" -#: ../hardcopy.c:2254 msgid "E675: No default font specified for multi-byte printing." msgstr "E675: Aucune police par d้faut pour l'impression multi-octets" -#: ../hardcopy.c:2426 msgid "E324: Can't open PostScript output file" msgstr "E324: Impossible d'ouvrir le fichier PostScript de sortie" -#: ../hardcopy.c:2458 #, c-format msgid "E456: Can't open file \"%s\"" msgstr "E456: Impossible d'ouvrir le fichier \"%s\"" -#: ../hardcopy.c:2583 msgid "E456: Can't find PostScript resource file \"prolog.ps\"" msgstr "E456: Le fichier de ressource PostScript \"prolog.ps\" est introuvable" -#: ../hardcopy.c:2593 msgid "E456: Can't find PostScript resource file \"cidfont.ps\"" msgstr "" "E456: Le fichier de ressource PostScript \"cidfont.ps\" est introuvable" -#: ../hardcopy.c:2622 ../hardcopy.c:2639 ../hardcopy.c:2665 #, c-format msgid "E456: Can't find PostScript resource file \"%s.ps\"" msgstr "E456: Le fichier de ressource PostScript \"%s.ps\" est introuvable" -#: ../hardcopy.c:2654 #, c-format msgid "E620: Unable to convert to print encoding \"%s\"" msgstr "E620: La conversion pour imprimer dans l'encodage \"%s\" a ้chou้" -#: ../hardcopy.c:2877 msgid "Sending to printer..." msgstr "Envoi เ l'imprimante..." -#: ../hardcopy.c:2881 msgid "E365: Failed to print PostScript file" msgstr "E365: L'impression du fichier PostScript a ้chou้" -#: ../hardcopy.c:2883 msgid "Print job sent." msgstr "Tโche d'impression envoy้e." -#: ../if_cscope.c:85 msgid "Add a new database" msgstr "Ajouter une base de donn้es" -#: ../if_cscope.c:87 msgid "Query for a pattern" msgstr "Rechercher un motif" -#: ../if_cscope.c:89 msgid "Show this message" msgstr "Afficher ce message" -#: ../if_cscope.c:91 msgid "Kill a connection" msgstr "Fermer une connexion" -#: ../if_cscope.c:93 msgid "Reinit all connections" msgstr "R้initialiser toutes les connexions" -#: ../if_cscope.c:95 msgid "Show connections" msgstr "Afficher les connexions" -#: ../if_cscope.c:101 #, c-format msgid "E560: Usage: cs[cope] %s" msgstr "E560: Utilisation : cs[cope] %s" -#: ../if_cscope.c:225 msgid "This cscope command does not support splitting the window.\n" msgstr "Cette commande cscope ne supporte pas le partage de la fen๊tre.\n" -#: ../if_cscope.c:266 msgid "E562: Usage: cstag <ident>" msgstr "E562: Utilisation : cstag <ident>" -#: ../if_cscope.c:313 msgid "E257: cstag: tag not found" msgstr "E257: cstag : marqueur introuvable" -#: ../if_cscope.c:461 #, c-format msgid "E563: stat(%s) error: %d" msgstr "E563: Erreur stat(%s) : %d" -#: ../if_cscope.c:551 +msgid "E563: stat error" +msgstr "E563: Erreur stat" + #, c-format msgid "E564: %s is not a directory or a valid cscope database" msgstr "E564: %s n'est pas un r้pertoire ou une base de donn้es cscope valide" -#: ../if_cscope.c:566 #, c-format msgid "Added cscope database %s" msgstr "Base de donn้es cscope %s ajout้e" -#: ../if_cscope.c:616 #, c-format -msgid "E262: error reading cscope connection %<PRId64>" -msgstr "E262: erreur lors de la lecture de la connexion cscope %<PRId64>" +msgid "E262: error reading cscope connection %ld" +msgstr "E262: erreur lors de la lecture de la connexion cscope %ld" -#: ../if_cscope.c:711 msgid "E561: unknown cscope search type" msgstr "E561: type de recherche cscope inconnu" -#: ../if_cscope.c:752 ../if_cscope.c:789 msgid "E566: Could not create cscope pipes" msgstr "E566: Impossible de cr้er les tuyaux (pipes) cscope" -#: ../if_cscope.c:767 msgid "E622: Could not fork for cscope" msgstr "E622: Impossible de forker pour cscope" -#: ../if_cscope.c:849 -#, fuzzy msgid "cs_create_connection setpgid failed" -msgstr "exec de cs_create_connection a ้chou้" +msgstr "cs_create_connection setpgid a ้chou้" -#: ../if_cscope.c:853 ../if_cscope.c:889 msgid "cs_create_connection exec failed" msgstr "exec de cs_create_connection a ้chou้" -#: ../if_cscope.c:863 ../if_cscope.c:902 msgid "cs_create_connection: fdopen for to_fp failed" msgstr "cs_create_connection : fdopen pour to_fp a ้chou้" -#: ../if_cscope.c:865 ../if_cscope.c:906 msgid "cs_create_connection: fdopen for fr_fp failed" msgstr "cs_create_connection : fdopen pour fr_fp a ้chou้" -#: ../if_cscope.c:890 msgid "E623: Could not spawn cscope process" msgstr "E623: Impossible d'engendrer le processus cscope" -#: ../if_cscope.c:932 msgid "E567: no cscope connections" msgstr "E567: Aucune connexion cscope" -#: ../if_cscope.c:1009 #, c-format msgid "E469: invalid cscopequickfix flag %c for %c" msgstr "E469: Drapeau cscopequickfix %c invalide pour %c" # DB - todo -#: ../if_cscope.c:1058 #, c-format msgid "E259: no matches found for cscope query %s of %s" msgstr "E259: aucune correspondance trouv้e pour la requ๊te cscope %s de %s" -#: ../if_cscope.c:1142 msgid "cscope commands:\n" msgstr "commandes cscope :\n" -#: ../if_cscope.c:1150 #, c-format msgid "%-5s: %s%*s (Usage: %s)" msgstr "%-5s: %s%*s (Utilisation : %s)" -#: ../if_cscope.c:1155 msgid "" "\n" +" a: Find assignments to this symbol\n" " c: Find functions calling this function\n" " d: Find functions called by this function\n" " e: Find this egrep pattern\n" @@ -3444,6 +2776,7 @@ msgid "" " t: Find this text string\n" msgstr "" "\n" +" a: Trouver les affectations เ ce symbole\n" " c: Trouver les fonctions appelant cette fonction\n" " d: Trouver les fonctions appel้es par cette fonction\n" " e: Trouver ce motif egrep\n" @@ -3453,31 +2786,33 @@ msgstr "" " s: Trouver ce symbole C\n" " t: Trouver cette cha๎ne\n" -#: ../if_cscope.c:1226 +#, c-format +msgid "E625: cannot open cscope database: %s" +msgstr "E625: impossible d'ouvrir la base de donn้es cscope %s" + +msgid "E626: cannot get cscope database information" +msgstr "" +"E626: impossible d'obtenir des informations sur la base de donn้es cscope" + msgid "E568: duplicate cscope database not added" msgstr "E568: base de donn้es cscope redondante non ajout้e" -#: ../if_cscope.c:1335 #, c-format msgid "E261: cscope connection %s not found" msgstr "E261: Connexion cscope %s introuvable" -#: ../if_cscope.c:1364 #, c-format msgid "cscope connection %s closed" msgstr "connexion cscope %s ferm้e" #. should not reach here -#: ../if_cscope.c:1486 msgid "E570: fatal error in cs_manage_matches" msgstr "E570: erreur fatale dans cs_manage_matches" -#: ../if_cscope.c:1693 #, c-format msgid "Cscope tag: %s" msgstr "Marqueur cscope : %s" -#: ../if_cscope.c:1711 msgid "" "\n" " # line" @@ -3486,87 +2821,307 @@ msgstr "" " # ligne" # DB - todo : Faut-il respecter l'alignement ici ? -#: ../if_cscope.c:1713 msgid "filename / context / line\n" msgstr "nom / contexte/ ligne\n" -#: ../if_cscope.c:1809 #, c-format msgid "E609: Cscope error: %s" msgstr "E609: Erreur cscope : %s" -#: ../if_cscope.c:2053 msgid "All cscope databases reset" msgstr "Toutes les bases de donn้es cscope ont ้t้ r้initialis้es" -#: ../if_cscope.c:2123 msgid "no cscope connections\n" msgstr "aucune connexion cscope\n" -#: ../if_cscope.c:2126 msgid " # pid database name prepend path\n" msgstr " # pid nom de la base de donn้es chemin\n" -#: ../main.c:144 +msgid "Lua library cannot be loaded." +msgstr "La biblioth่que Lua n'a pas pu ๊tre charg้e." + +msgid "cannot save undo information" +msgstr "impossible d'enregistrer les informations d'annulation" + +msgid "" +"E815: Sorry, this command is disabled, the MzScheme libraries could not be " +"loaded." +msgstr "" +"E815: D้sol้, cette commande est d้sactiv้e : les biblioth่ques MzScheme " +"n'ont pas pu ๊tre charg้es." + +msgid "" +"E895: Sorry, this command is disabled, the MzScheme's racket/base module " +"could not be loaded." +msgstr "" +"E895: D้sol้, cette commande est d้sactiv้e : le module MzScheme racket/base " +"ne peut pas ๊tre charg้." + +msgid "invalid expression" +msgstr "expression invalide" + +msgid "expressions disabled at compile time" +msgstr "expressions d้sactiv้es lors de la compilation" + +msgid "hidden option" +msgstr "option cach้e" + +msgid "unknown option" +msgstr "option inconnue" + +msgid "window index is out of range" +msgstr "num้ro de fen๊tre hors limites" + +msgid "couldn't open buffer" +msgstr "impossible d'ouvrir le tampon" + +msgid "cannot delete line" +msgstr "impossible d'effacer la ligne" + +msgid "cannot replace line" +msgstr "impossible de remplacer la ligne" + +msgid "cannot insert line" +msgstr "impossible d'ins้rer la ligne" + +msgid "string cannot contain newlines" +msgstr "une cha๎ne ne peut pas contenir de saut-de-ligne" + +msgid "error converting Scheme values to Vim" +msgstr "erreur lors de la conversion d'une valeur de Scheme เ Vim" + +msgid "Vim error: ~a" +msgstr "Erreur Vim : ~a" + +msgid "Vim error" +msgstr "Erreur Vim" + +msgid "buffer is invalid" +msgstr "tampon invalide" + +msgid "window is invalid" +msgstr "fen๊tre invalide" + +msgid "linenr out of range" +msgstr "num้ro de ligne hors limites" + +msgid "not allowed in the Vim sandbox" +msgstr "non autoris้ dans le bac เ sable" + +msgid "E836: This Vim cannot execute :python after using :py3" +msgstr "E836: Vim ne peut pas ex้cuter :python apr่s avoir utilis้ :py3" + +msgid "" +"E263: Sorry, this command is disabled, the Python library could not be " +"loaded." +msgstr "" +"E263: D้sol้, commande d้sactiv้e : la biblioth่que Python n'a pas pu ๊tre " +"charg้e." + +msgid "" +"E887: Sorry, this command is disabled, the Python's site module could not be " +"loaded." +msgstr "" +"E887: D้sol้, commande d้sactiv้e : la biblioth่que Python n'a pas pu ๊tre " +"charg้e." + +msgid "E659: Cannot invoke Python recursively" +msgstr "E659: Impossible d'invoquer Python r้cursivement" + +msgid "E837: This Vim cannot execute :py3 after using :python" +msgstr "E837: Vim ne peut pas ex้cuter :py3 apr่s avoir utilis้ :python" + +msgid "E265: $_ must be an instance of String" +msgstr "E265: $_ doit ๊tre une instance de cha๎ne (String)" + +msgid "" +"E266: Sorry, this command is disabled, the Ruby library could not be loaded." +msgstr "" +"E266: D้sol้, commande d้sactiv้e : la biblioth่que Ruby n'a pas pu ๊tre " +"charg้e." + +msgid "E267: unexpected return" +msgstr "E267: ซ return ป inattendu" + +msgid "E268: unexpected next" +msgstr "E268: ซ next ป inattendu" + +msgid "E269: unexpected break" +msgstr "E269: ซ break ป inattendu" + +msgid "E270: unexpected redo" +msgstr "E270: ซ redo ป inattendu" + +msgid "E271: retry outside of rescue clause" +msgstr "E271: ซ retry ป hors d'une clause ซ rescue ป" + +msgid "E272: unhandled exception" +msgstr "E272: Exception non prise en charge" + +# DB - todo +#, c-format +msgid "E273: unknown longjmp status %d" +msgstr "E273: contexte de longjmp inconnu : %d" + +msgid "invalid buffer number" +msgstr "num้ro de tampon invalide" + +msgid "not implemented yet" +msgstr "pas encore impl้ment้" + +# DB - TODO : le contexte est celui d'une annulation. +#. ??? +msgid "cannot set line(s)" +msgstr "Impossible de remettre la/les ligne(s)" + +msgid "invalid mark name" +msgstr "nom de marque invalide" + +msgid "mark not set" +msgstr "marque non positionn้e" + +#, c-format +msgid "row %d column %d" +msgstr "ligne %d colonne %d" + +msgid "cannot insert/append line" +msgstr "Impossible d'ins้rer/ajouter de lignes" + +msgid "line number out of range" +msgstr "num้ro de ligne hors limites" + +msgid "unknown flag: " +msgstr "drapeau inconnu : " + +msgid "unknown vimOption" +msgstr "vimOption inconnue" + +msgid "keyboard interrupt" +msgstr "interruption clavier" + +msgid "vim error" +msgstr "erreur Vim" + +msgid "cannot create buffer/window command: object is being deleted" +msgstr "" +"Impossible de cr้er commande de tampon/fen๊tre : objet en cours d'effacement" + +msgid "" +"cannot register callback command: buffer/window is already being deleted" +msgstr "" +"Impossible d'inscrire la commande de rappel : tampon/fen๊tre en effacement" + +#. This should never happen. Famous last word? +msgid "" +"E280: TCL FATAL ERROR: reflist corrupt!? Please report this to vim-dev@vim." +"org" +msgstr "" +"E280: ERREUR FATALE TCL: reflist corrompue ?! Contactez vim-dev@vim.org, SVP." + +msgid "cannot register callback command: buffer/window reference not found" +msgstr "" +"Impossible d'inscrire la commande de rappel : r้f. tampon/fen๊tre introuvable" + +msgid "" +"E571: Sorry, this command is disabled: the Tcl library could not be loaded." +msgstr "" +"E571: D้sol้, commande d้sactiv้e: la biblioth่que Tcl n'a pas pu ๊tre " +"charg้e." + +#, c-format +msgid "E572: exit code %d" +msgstr "E572: code de sortie %d" + +msgid "cannot get line" +msgstr "Impossible d'obtenir la ligne" + +msgid "Unable to register a command server name" +msgstr "Impossible d'inscrire un nom de serveur de commande" + +msgid "E248: Failed to send command to the destination program" +msgstr "E248: ษchec de l'envoi de la commande au programme cible" + +#, c-format +msgid "E573: Invalid server id used: %s" +msgstr "E573: Id utilis้ pour le serveur invalide : %s" + +msgid "E251: VIM instance registry property is badly formed. Deleted!" +msgstr "E251: Entr้e registre de l'instance de Vim mal format้e. Suppression !" + +#, c-format +msgid "E938: Duplicate key in JSON: \"%s\"" +msgstr "E938: Cl้ dupliqu้e dans le document JSON : \"%s\"" + +#, c-format +msgid "E696: Missing comma in List: %s" +msgstr "E696: Il manque une virgule dans la Liste %s" + +#, c-format +msgid "E697: Missing end of List ']': %s" +msgstr "E697: Il manque ']' เ la fin de la Liste %s" + msgid "Unknown option argument" msgstr "Option inconnue" -#: ../main.c:146 msgid "Too many edit arguments" msgstr "Trop d'arguments d'้dition" -#: ../main.c:148 msgid "Argument missing after" msgstr "Argument manquant apr่s" -#: ../main.c:150 msgid "Garbage after option argument" msgstr "arguments en trop apr่s l'option" -#: ../main.c:152 msgid "Too many \"+command\", \"-c command\" or \"--cmd command\" arguments" msgstr "Trop d'arguments \"+command\", \"-c command\" ou \"--cmd command\"" -#: ../main.c:154 msgid "Invalid argument for" msgstr "Argument invalide pour" -#: ../main.c:294 #, c-format msgid "%d files to edit\n" msgstr "%d fichiers เ ้diter\n" -#: ../main.c:1342 +msgid "netbeans is not supported with this GUI\n" +msgstr "netbeans n'est pas support้ avec cette interface graphique\n" + +msgid "'-nb' cannot be used: not enabled at compile time\n" +msgstr "'-nb' ne peut pas ๊tre utilis้ : d้sactiv้ เ la compilation\n" + +msgid "This Vim was not compiled with the diff feature." +msgstr "Ce Vim n'a pas ้t้ compil้ avec la fonctionnalit้ diff" + msgid "Attempt to open script file again: \"" msgstr "Nouvelle tentative pour ouvrir le script : \"" -#: ../main.c:1350 msgid "Cannot open for reading: \"" msgstr "Impossible d'ouvrir en lecture : \"" -#: ../main.c:1393 msgid "Cannot open for script output: \"" msgstr "Impossible d'ouvrir pour la sortie script : \"" -#: ../main.c:1622 +msgid "Vim: Error: Failure to start gvim from NetBeans\n" +msgstr "Vim : Erreur : Impossible de d้marrer gvim depuis NetBeans\n" + +msgid "Vim: Error: This version of Vim does not run in a Cygwin terminal\n" +msgstr "" +"Vim : Erreur : Cette version de Vim ne fonctionne pas dans un terminal " +"Cygwin\n" + msgid "Vim: Warning: Output is not to a terminal\n" msgstr "Vim : Alerte : La sortie ne s'effectue pas sur un terminal\n" -#: ../main.c:1624 msgid "Vim: Warning: Input is not from a terminal\n" msgstr "Vim : Alerte : L'entr้e ne se fait pas sur un terminal\n" #. just in case.. -#: ../main.c:1891 msgid "pre-vimrc command line" msgstr "ligne de commande pre-vimrc" -#: ../main.c:1964 #, c-format msgid "E282: Cannot read from \"%s\"" msgstr "E282: Impossible de lire \"%s\"" -#: ../main.c:2149 msgid "" "\n" "More info with: \"vim -h\"\n" @@ -3574,23 +3129,18 @@ msgstr "" "\n" "Plus d'info avec : \"vim -h\"\n" -#: ../main.c:2178 msgid "[file ..] edit specified file(s)" msgstr "[fichier ...] ouvrir le ou les fichiers sp้cifi้s" -#: ../main.c:2179 msgid "- read text from stdin" msgstr "- lire le texte เ partir de stdin" -#: ../main.c:2180 msgid "-t tag edit file where tag is defined" msgstr "-t marqueur ouvrir le fichier qui contient le marqueur" -#: ../main.c:2181 msgid "-q [errorfile] edit file with first error" msgstr "-q [fichErr] ouvrir เ l'endroit de la premi่re erreur" -#: ../main.c:2187 msgid "" "\n" "\n" @@ -3600,11 +3150,9 @@ msgstr "" "\n" "utilisation :" -#: ../main.c:2189 msgid " vim [arguments] " msgstr " vim [args] " -#: ../main.c:2193 msgid "" "\n" " or:" @@ -3612,7 +3160,15 @@ msgstr "" "\n" " ou :" -#: ../main.c:2196 +# DB - todo (VMS uniquement). +msgid "" +"\n" +"Where case is ignored prepend / to make flag upper case" +msgstr "" +"\n" +"pour lesquels la casse est indiff้rente (/ pour que le drapeau soit " +"majuscule)" + msgid "" "\n" "\n" @@ -3622,192 +3178,338 @@ msgstr "" "\n" "Arguments :\n" -#: ../main.c:2197 msgid "--\t\t\tOnly file names after this" msgstr "--\t\tSeuls des noms de fichier sont sp้cifi้s apr่s ceci" -#: ../main.c:2199 msgid "--literal\t\tDon't expand wildcards" msgstr "--literal\tNe pas d้velopper les m้tacaract่res" -#: ../main.c:2201 +msgid "-register\t\tRegister this gvim for OLE" +msgstr "-register\tInscrire ce gvim pour OLE" + +msgid "-unregister\t\tUnregister gvim for OLE" +msgstr "-unregister\tD้sinscrire gvim de OLE" + +msgid "-g\t\t\tRun using GUI (like \"gvim\")" +msgstr "-g\t\tLancer l'interface graphique (comme \"gvim\")" + +msgid "-f or --nofork\tForeground: Don't fork when starting GUI" +msgstr "" +"-f, --nofork\tPremier-plan : ne pas d้tacher l'interface graphique du " +"terminal" + msgid "-v\t\t\tVi mode (like \"vi\")" msgstr "-v\t\tMode Vi (comme \"vi\")" -#: ../main.c:2202 msgid "-e\t\t\tEx mode (like \"ex\")" msgstr "-e\t\tMode Ex (comme \"ex\")" -#: ../main.c:2203 msgid "-E\t\t\tImproved Ex mode" msgstr "-E\t\t\tMode Ex am้lior้" -#: ../main.c:2204 msgid "-s\t\t\tSilent (batch) mode (only for \"ex\")" msgstr "-s\t\tMode silencieux (batch) (seulement pour \"ex\")" -#: ../main.c:2205 msgid "-d\t\t\tDiff mode (like \"vimdiff\")" msgstr "-d\t\tMode diff (comme \"vimdiff\")" -#: ../main.c:2206 msgid "-y\t\t\tEasy mode (like \"evim\", modeless)" msgstr "-y\t\tMode facile (comme \"evim\", vim sans modes)" -#: ../main.c:2207 msgid "-R\t\t\tReadonly mode (like \"view\")" msgstr "-R\t\tMode lecture seule (comme \"view\")" -#: ../main.c:2208 msgid "-Z\t\t\tRestricted mode (like \"rvim\")" msgstr "-Z\t\tMode restreint (comme \"rvim\")" -#: ../main.c:2209 msgid "-m\t\t\tModifications (writing files) not allowed" msgstr "-m\t\tInterdire l'enregistrement des fichiers" -#: ../main.c:2210 msgid "-M\t\t\tModifications in text not allowed" msgstr "-M\t\tInterdire toute modification de texte" -#: ../main.c:2211 msgid "-b\t\t\tBinary mode" msgstr "-b\t\tMode binaire" -#: ../main.c:2212 msgid "-l\t\t\tLisp mode" msgstr "-l\t\tMode lisp" -#: ../main.c:2213 msgid "-C\t\t\tCompatible with Vi: 'compatible'" msgstr "-C\t\tCompatible avec Vi : 'compatible'" -#: ../main.c:2214 msgid "-N\t\t\tNot fully Vi compatible: 'nocompatible'" msgstr "-N\t\tPas totalement compatible avec Vi : 'nocompatible'" -#: ../main.c:2215 msgid "-V[N][fname]\t\tBe verbose [level N] [log messages to fname]" msgstr "-V[N][<fichier>]\tMode verbeux [niveau N] [dans <fichier>]" -#: ../main.c:2216 msgid "-D\t\t\tDebugging mode" msgstr "-D\t\tMode d้bogage" -#: ../main.c:2217 msgid "-n\t\t\tNo swap file, use memory only" msgstr "-n\t\tNe pas utiliser de fichier d'้change, seulement la m้moire" -#: ../main.c:2218 msgid "-r\t\t\tList swap files and exit" msgstr "-r\t\tLister les fichiers d'้change et quitter" -#: ../main.c:2219 msgid "-r (with file name)\tRecover crashed session" msgstr "-r <fichier>\tR้cup้rer une session plant้e" -#: ../main.c:2220 msgid "-L\t\t\tSame as -r" msgstr "-L\t\tComme -r" -#: ../main.c:2221 +msgid "-f\t\t\tDon't use newcli to open window" +msgstr "-f\t\tNe pas utiliser newcli pour l'ouverture des fen๊tres" + +msgid "-dev <device>\t\tUse <device> for I/O" +msgstr "-dev <p้riph>\tUtiliser <p้riph้rique> pour les E/S" + msgid "-A\t\t\tstart in Arabic mode" msgstr "-A\t\tD้marrer en mode arabe" -#: ../main.c:2222 msgid "-H\t\t\tStart in Hebrew mode" msgstr "-H\t\tD้marrer en mode h้breu" -#: ../main.c:2223 msgid "-F\t\t\tStart in Farsi mode" msgstr "-F\t\tD้marrer en mode farsi" -#: ../main.c:2224 msgid "-T <terminal>\tSet terminal type to <terminal>" msgstr "-T <term>\tR้gler le type du terminal sur <terminal>" -#: ../main.c:2225 +msgid "--not-a-term\t\tSkip warning for input/output not being a terminal" +msgstr "" +"--no-a-term\t\tAucun avertissement si l'entr้e/sortie n'est pas un terminal" + +msgid "--ttyfail\t\tExit if input or output is not a terminal" +msgstr "" +"--ttyfail\t\tQuitte si l'entr้e ou la sortie ne sont pas un terminal" + msgid "-u <vimrc>\t\tUse <vimrc> instead of any .vimrc" msgstr "-u <vimrc>\tUtiliser <vimrc> au lieu du vimrc habituel" -#: ../main.c:2226 +msgid "-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc" +msgstr "-U <gvimrc>\tUtiliser <gvimrc> au lieu du gvimrc habituel" + msgid "--noplugin\t\tDon't load plugin scripts" msgstr "--noplugin\tNe charger aucun greffon" -#: ../main.c:2227 msgid "-p[N]\t\tOpen N tab pages (default: one for each file)" msgstr "-p[N]\tOuvrir N onglets (d้faut : un pour chaque fichier)" -#: ../main.c:2228 msgid "-o[N]\t\tOpen N windows (default: one for each file)" msgstr "-o[N]\tOuvrir N fen๊tres (d้faut : une pour chaque fichier)" -#: ../main.c:2229 msgid "-O[N]\t\tLike -o but split vertically" msgstr "-O[N]\tComme -o, mais partager verticalement" -#: ../main.c:2230 msgid "+\t\t\tStart at end of file" msgstr "+\t\tOuvrir เ la fin du fichier" -#: ../main.c:2231 msgid "+<lnum>\t\tStart at line <lnum>" msgstr "+<numL>\tOuvrir le fichier เ la ligne <numL>" -#: ../main.c:2232 msgid "--cmd <command>\tExecute <command> before loading any vimrc file" msgstr "--cmd <cmde>\tEx้cuter <commande> avant de charger les fichiers vimrc" -#: ../main.c:2233 msgid "-c <command>\t\tExecute <command> after loading the first file" msgstr "-c <cmde>\tEx้cuter <commande> une fois le 1er fichier charg้" -#: ../main.c:2235 msgid "-S <session>\t\tSource file <session> after loading the first file" msgstr "" "-S <session>\tSourcer le fichier <session> une fois le 1er fichier charg้" -#: ../main.c:2236 msgid "-s <scriptin>\tRead Normal mode commands from file <scriptin>" msgstr "-s <src>\tLire les commandes du mode Normal เ partir du fichier <src>" -#: ../main.c:2237 msgid "-w <scriptout>\tAppend all typed commands to file <scriptout>" msgstr "-w <dest>\tAjouter toutes les commandes tap้es dans le fichier <dest>" -#: ../main.c:2238 msgid "-W <scriptout>\tWrite all typed commands to file <scriptout>" msgstr "-W <dest>\tษcrire toutes les commandes tap้es dans le fichier <dest>" -#: ../main.c:2240 +msgid "-x\t\t\tEdit encrypted files" +msgstr "-x\t\t\tษditer des fichiers chiffr้s" + +msgid "-display <display>\tConnect vim to this particular X-server" +msgstr "-display <display>\tConnecter Vim au serveur X sp้cifi้" + +msgid "-X\t\t\tDo not connect to X server" +msgstr "-X\t\t\tNe pas se connecter เ un serveur X" + +msgid "--remote <files>\tEdit <files> in a Vim server if possible" +msgstr "--remote <fich>\tษditer les <fichiers> dans un serveur Vim si possible" + +msgid "--remote-silent <files> Same, don't complain if there is no server" +msgstr "" +"--remote-silent ...\tPareil, mais pas d'erreur s'il n'y a aucun serveur" + +msgid "" +"--remote-wait <files> As --remote but wait for files to have been edited" +msgstr "" +"--remote-wait <fich>\tComme --remote mais ne quitter qu'เ la fin de l'้dition" + +msgid "" +"--remote-wait-silent <files> Same, don't complain if there is no server" +msgstr "" +"--remote-wait-silent\tPareil, mais pas d'erreur s'il n'y a aucun serveur" + +msgid "" +"--remote-tab[-wait][-silent] <files> As --remote but use tab page per file" +msgstr "" +"--remote-tab[-wait][-silent] <fich>\tComme --remote mais ouvrir un onglet " +"pour chaque fichier" + +msgid "--remote-send <keys>\tSend <keys> to a Vim server and exit" +msgstr "--remote-send <tche>\tEnvoyer <touches> เ un serveur Vim puis quitter" + +msgid "--remote-expr <expr>\tEvaluate <expr> in a Vim server and print result" +msgstr "" +"--remote-expr <expr>\tษvaluer <expr> dans un serveur Vim, afficher le " +"r้sultat" + +msgid "--serverlist\t\tList available Vim server names and exit" +msgstr "" +"--serverlist\t\tLister les noms des serveurs Vim disponibles et quitter" + +msgid "--servername <name>\tSend to/become the Vim server <name>" +msgstr "--servername <nom>\tEnvoyer au/devenir le serveur Vim nomm้ <nom>" + msgid "--startuptime <file>\tWrite startup timing messages to <file>" msgstr "" "--startuptime <fich>\tษcrire les messages d'horodatage au d้marrage dans " "<fich>" -#: ../main.c:2242 msgid "-i <viminfo>\t\tUse <viminfo> instead of .viminfo" msgstr "-i <viminfo>\t\tUtiliser <viminfo> au lieu du viminfo habituel" -#: ../main.c:2243 msgid "-h or --help\tPrint Help (this message) and exit" msgstr "-h ou --help\t\tAfficher l'aide (ce message) puis quitter" -#: ../main.c:2244 msgid "--version\t\tPrint version information and exit" msgstr "--version\t\tAfficher les informations de version et quitter" -#: ../mark.c:676 +msgid "" +"\n" +"Arguments recognised by gvim (Motif version):\n" +msgstr "" +"\n" +"Arguments reconnus par gvim (version Motif) :\n" + +msgid "" +"\n" +"Arguments recognised by gvim (neXtaw version):\n" +msgstr "" +"\n" +"Arguments reconnus par gvim (version neXtaw) :\n" + +msgid "" +"\n" +"Arguments recognised by gvim (Athena version):\n" +msgstr "" +"\n" +"Arguments reconnus par gvim (version Athena) :\n" + +msgid "-display <display>\tRun vim on <display>" +msgstr "-display <้cran>\tLancer Vim sur ce <display>" + +msgid "-iconic\t\tStart vim iconified" +msgstr "-iconic\t\tIconifier Vim au d้marrage" + +msgid "-background <color>\tUse <color> for the background (also: -bg)" +msgstr "" +"-background <coul>\tUtiliser <couleur> pour l'arri่re-plan\t (abrv : -bg)" + +msgid "-foreground <color>\tUse <color> for normal text (also: -fg)" +msgstr "" +"-foreground <coul>\tUtiliser <couleur> pour le texte normal\t (abrv : -fg)" + +msgid "-font <font>\t\tUse <font> for normal text (also: -fn)" +msgstr "-font <fonte>\tUtiliser <fonte> pour le texte normal\t (abrv : -fn)" + +msgid "-boldfont <font>\tUse <font> for bold text" +msgstr "-boldfont <fonte>\tUtiliser <fonte> pour le texte gras" + +msgid "-italicfont <font>\tUse <font> for italic text" +msgstr "-italicfont <fonte>\tUtiliser <fonte> pour le texte italique" + +msgid "-geometry <geom>\tUse <geom> for initial geometry (also: -geom)" +msgstr "-geometry <g้om>\tUtiliser cette <g้om้trie> initiale\t (abrv : -geom)" + +msgid "-borderwidth <width>\tUse a border width of <width> (also: -bw)" +msgstr "" +"-borderwidth <้pais>\tUtiliser cette <้paisseur> de bordure\t (abrv : -bw)" + +msgid "-scrollbarwidth <width> Use a scrollbar width of <width> (also: -sw)" +msgstr "" +"-scrollbarwidth <lg>\tUtiliser cette <largeur> de barre de d้fil. (abrv: -sw)" + +msgid "-menuheight <height>\tUse a menu bar height of <height> (also: -mh)" +msgstr "-menuheight <haut>\tUtiliser cette <hauteur> de menu\t (abrv : -mh)" + +msgid "-reverse\t\tUse reverse video (also: -rv)" +msgstr "-reverse\t\tUtiliser la vid้o inverse\t\t (abrv : -rv)" + +msgid "+reverse\t\tDon't use reverse video (also: +rv)" +msgstr "+reverse\t\tNe pas utiliser de vid้o inverse\t (abrv : +rv)" + +msgid "-xrm <resource>\tSet the specified resource" +msgstr "-xrm <ressource>\tConfigurer la <ressource> sp้cifi้e" + +msgid "" +"\n" +"Arguments recognised by gvim (GTK+ version):\n" +msgstr "" +"\n" +"Arguments reconnus par gvim (version GTK+) :\n" + +msgid "-display <display>\tRun vim on <display> (also: --display)" +msgstr "" +"-display <display>\tLancer Vim sur ce <display>\t(้galement : --display)" + +msgid "--role <role>\tSet a unique role to identify the main window" +msgstr "--role <r๔le>\tDonner un r๔le pour identifier la fen๊tre principale" + +msgid "--socketid <xid>\tOpen Vim inside another GTK widget" +msgstr "--socketid <xid>\tOuvrir Vim dans un autre widget GTK" + +msgid "--echo-wid\t\tMake gvim echo the Window ID on stdout" +msgstr "--echo-wid\t\tGvim affiche l'ID de la fen๊tre sur stdout" + +msgid "-P <parent title>\tOpen Vim inside parent application" +msgstr "-P <titre parent>\tOuvrir Vim dans une application parente" + +msgid "--windowid <HWND>\tOpen Vim inside another win32 widget" +msgstr "--windowid <HWND>\tOuvrir Vim dans un autre widget win32" + +msgid "No display" +msgstr "Aucun display" + +#. Failed to send, abort. +msgid ": Send failed.\n" +msgstr " : L'envoi a ้chou้.\n" + +#. Let vim start normally. +msgid ": Send failed. Trying to execute locally\n" +msgstr " : L'envoi a ้chou้. Tentative d'ex้cution locale\n" + +#, c-format +msgid "%d of %d edited" +msgstr "%d ้dit้s sur %d" + +msgid "No display: Send expression failed.\n" +msgstr "Aucun display : L'envoi de l'expression a ้chou้.\n" + +msgid ": Send expression failed.\n" +msgstr " : L'envoi de l'expression a ้chou้.\n" + msgid "No marks set" msgstr "Aucune marque positionn้e" -#: ../mark.c:678 #, c-format msgid "E283: No marks matching \"%s\"" msgstr "E283: Aucune marque ne correspond เ \"%s\"" #. Highlight title -#: ../mark.c:687 msgid "" "\n" "mark line col file/text" @@ -3816,7 +3518,6 @@ msgstr "" "marq ligne col fichier/texte" #. Highlight title -#: ../mark.c:789 msgid "" "\n" " jump line col file/text" @@ -3825,7 +3526,6 @@ msgstr "" " saut ligne col fichier/texte" #. Highlight title -#: ../mark.c:831 msgid "" "\n" "change line col text" @@ -3833,7 +3533,6 @@ msgstr "" "\n" "modif ligne col fichier/texte" -#: ../mark.c:1238 msgid "" "\n" "# File marks:\n" @@ -3842,7 +3541,6 @@ msgstr "" "# Marques dans le fichier :\n" #. Write the jumplist with -' -#: ../mark.c:1271 msgid "" "\n" "# Jumplist (newest first):\n" @@ -3850,7 +3548,6 @@ msgstr "" "\n" "# Liste de sauts (le plus r้cent en premier) :\n" -#: ../mark.c:1352 msgid "" "\n" "# History of marks within files (newest to oldest):\n" @@ -3858,84 +3555,91 @@ msgstr "" "\n" "# Historique des marques dans les fichiers (les plus r้centes en premier) :\n" -#: ../mark.c:1431 msgid "Missing '>'" msgstr "'>' manquant" -#: ../memfile.c:426 +msgid "E543: Not a valid codepage" +msgstr "E543: Page de codes non valide" + +msgid "E284: Cannot set IC values" +msgstr "E284: Impossible de r้gler les valeurs IC" + +msgid "E285: Failed to create input context" +msgstr "E285: ษchec de la cr้ation du contexte de saisie" + +msgid "E286: Failed to open input method" +msgstr "E286: ษchec de l'ouverture de la m้thode de saisie" + +msgid "E287: Warning: Could not set destroy callback to IM" +msgstr "" +"E287: Alerte : Impossible d'inscrire le callback de destruction dans la MS" + +msgid "E288: input method doesn't support any style" +msgstr "E288: la m้thode de saisie ne supporte aucun style" + +msgid "E289: input method doesn't support my preedit type" +msgstr "" +"E289: le type de pr้้dition de Vim n'est pas support้ par la m้thode de " +"saisie" + msgid "E293: block was not locked" msgstr "E293: le bloc n'้tait pas verrouill้" -#: ../memfile.c:799 msgid "E294: Seek error in swap file read" msgstr "E294: Erreur de positionnement lors de la lecture du fichier d'้change" -#: ../memfile.c:803 msgid "E295: Read error in swap file" msgstr "E295: Erreur de lecture dans le fichier d'้change" -#: ../memfile.c:849 msgid "E296: Seek error in swap file write" msgstr "E296: Erreur de positionnement lors de l'้criture du fichier d'้change" -#: ../memfile.c:865 msgid "E297: Write error in swap file" msgstr "E297: Erreur d'้criture dans le fichier d'้change" -#: ../memfile.c:1036 msgid "E300: Swap file already exists (symlink attack?)" msgstr "E300: Le fichier d'้change existe d้jเ (attaque par symlink ?)" -#: ../memline.c:318 msgid "E298: Didn't get block nr 0?" msgstr "E298: Bloc nฐ0 non r้cup้r้ ?" -#: ../memline.c:361 msgid "E298: Didn't get block nr 1?" msgstr "E298: Bloc nฐ1 non r้cup้r้ ?" -#: ../memline.c:377 msgid "E298: Didn't get block nr 2?" msgstr "E298: Bloc nฐ2 non r้cup้r้ ?" +msgid "E843: Error while updating swap file crypt" +msgstr "E843: Erreur lors de la mise เ jour du fichier d'้change crypt้" + #. could not (re)open the swap file, what can we do???? -#: ../memline.c:465 msgid "E301: Oops, lost the swap file!!!" msgstr "E301: Oups, le fichier d'้change a disparu !" -#: ../memline.c:477 msgid "E302: Could not rename swap file" msgstr "E302: Impossible de renommer le fichier d'้change" -#: ../memline.c:554 #, c-format msgid "E303: Unable to open swap file for \"%s\", recovery impossible" msgstr "E303: Impossible d'ouvrir fichier .swp pour \"%s\", r้cup. impossible" -#: ../memline.c:666 msgid "E304: ml_upd_block0(): Didn't get block 0??" msgstr "E304: ml_upd_block0() : bloc 0 non r้cup้r้ ?!" -#. no swap files found -#: ../memline.c:830 #, c-format msgid "E305: No swap file found for %s" msgstr "E305: Aucun fichier d'้change trouv้ pour %s" -#: ../memline.c:839 msgid "Enter number of swap file to use (0 to quit): " msgstr "Entrez le num้ro du fichier d'้change เ utiliser (0 pour quitter) : " -#: ../memline.c:879 #, c-format msgid "E306: Cannot open %s" msgstr "E306: Impossible d'ouvrir %s" -#: ../memline.c:897 msgid "Unable to read block 0 from " msgstr "Impossible de lire le bloc 0 de " -#: ../memline.c:900 msgid "" "\n" "Maybe no changes were made or Vim did not update the swap file." @@ -3944,28 +3648,22 @@ msgstr "" "Il est possible qu'aucune modification n'a ้t้ faite ou que Vim n'a pas mis " "เ jour le fichier d'้change." -#: ../memline.c:909 msgid " cannot be used with this version of Vim.\n" msgstr " ne peut pas ๊tre utilis้ avec cette version de Vim.\n" -#: ../memline.c:911 msgid "Use Vim version 3.0.\n" msgstr "Utilisez Vim version 3.0.\n" -#: ../memline.c:916 #, c-format msgid "E307: %s does not look like a Vim swap file" msgstr "E307: %s ne semble pas ๊tre un fichier d'้change de Vim" -#: ../memline.c:922 msgid " cannot be used on this computer.\n" msgstr " ne peut pas ๊tre utilis้ sur cet ordinateur.\n" -#: ../memline.c:924 msgid "The file was created on " msgstr "Le fichier a ้t้ cr้้ le " -#: ../memline.c:928 msgid "" ",\n" "or the file has been damaged." @@ -3973,86 +3671,107 @@ msgstr "" ",\n" "ou le fichier a ้t้ endommag้." -#: ../memline.c:945 +#, c-format +msgid "" +"E833: %s is encrypted and this version of Vim does not support encryption" +msgstr "" +"E833: %s est chiffr้ et cette version de Vim ne supporte pas le chiffrement" + msgid " has been damaged (page size is smaller than minimum value).\n" msgstr " a ้t้ endommag้ (taille de page inf้rieure เ la valeur minimale).\n" -#: ../memline.c:974 #, c-format msgid "Using swap file \"%s\"" msgstr "Utilisation du fichier d'้change \"%s\"" -#: ../memline.c:980 #, c-format msgid "Original file \"%s\"" msgstr "Fichier original \"%s\"" -#: ../memline.c:995 msgid "E308: Warning: Original file may have been changed" msgstr "E308: Alerte : Le fichier original a pu ๊tre modifi้" -#: ../memline.c:1061 +#, c-format +msgid "Swap file is encrypted: \"%s\"" +msgstr "Fichier d'้change chiffr้ : \"%s\"" + +msgid "" +"\n" +"If you entered a new crypt key but did not write the text file," +msgstr "" +"\n" +"Si vous avez tap้ une nouvelle cl้ de chiffrement mais n'avez pas enregistr้ " +"le fichier texte," + +msgid "" +"\n" +"enter the new crypt key." +msgstr "" +"\n" +"tapez la nouvelle cl้ de chiffrement." + +msgid "" +"\n" +"If you wrote the text file after changing the crypt key press enter" +msgstr "" +"\n" +"Si vous avez ้crit le fichier texte apr่s avoir chang้ la cl้ de " +"chiffrement, appuyez sur entr้e" + +msgid "" +"\n" +"to use the same key for text file and swap file" +msgstr "" +"\n" +"afin d'utiliser la m๊me cl้ pour le fichier texte et le fichier d'้change" + #, c-format msgid "E309: Unable to read block 1 from %s" msgstr "E309: Impossible de lire le bloc 1 de %s" -#: ../memline.c:1065 msgid "???MANY LINES MISSING" msgstr "???DE NOMBREUSES LIGNES MANQUENT" -#: ../memline.c:1076 msgid "???LINE COUNT WRONG" msgstr "???NOMBRE DE LIGNES ERRONษ" -#: ../memline.c:1082 msgid "???EMPTY BLOCK" msgstr "???BLOC VIDE" -#: ../memline.c:1103 msgid "???LINES MISSING" msgstr "???LIGNES MANQUANTES" -#: ../memline.c:1128 #, c-format msgid "E310: Block 1 ID wrong (%s not a .swp file?)" msgstr "E310: ID du bloc 1 erron้ (%s n'est pas un fichier d'้change ?)" -#: ../memline.c:1133 msgid "???BLOCK MISSING" msgstr "???BLOC MANQUANT" -#: ../memline.c:1147 msgid "??? from here until ???END lines may be messed up" msgstr "??? d'ici jusqu'เ ???FIN des lignes peuvent ๊tre corrompues" -#: ../memline.c:1164 msgid "??? from here until ???END lines may have been inserted/deleted" msgstr "??? d'ici jusqu'เ ???FIN des lignes ont pu ๊tre ins้r้es/effac้es" -#: ../memline.c:1181 msgid "???END" msgstr "???FIN" -#: ../memline.c:1238 msgid "E311: Recovery Interrupted" msgstr "E311: R้cup้ration interrompue" -#: ../memline.c:1243 msgid "" "E312: Errors detected while recovering; look for lines starting with ???" msgstr "" "E312: Erreurs lors de la r้cup้ration ; examinez les lignes commen็ant " "par ???" -#: ../memline.c:1245 msgid "See \":help E312\" for more information." msgstr "Consultez \":help E312\" pour plus d'information." -#: ../memline.c:1249 msgid "Recovery completed. You should check if everything is OK." msgstr "R้cup้ration achev้e. V้rifiez que tout est correct." -#: ../memline.c:1251 msgid "" "\n" "(You might want to write out this file under another name\n" @@ -4060,17 +3779,14 @@ msgstr "" "\n" "(Vous voudrez peut-๊tre enregistrer ce fichier sous un autre nom\n" -#: ../memline.c:1252 msgid "and run diff with the original file to check for changes)" msgstr "et lancer diff avec le fichier original pour rep้rer les changements)" -#: ../memline.c:1254 msgid "Recovery completed. Buffer contents equals file contents." msgstr "" "R้cup้ration achev้e. Le contenu du tampon est identique au contenu du " "fichier." -#: ../memline.c:1255 msgid "" "\n" "You may want to delete the .swp file now.\n" @@ -4080,52 +3796,45 @@ msgstr "" "Il est conseill้ d'effacer maintenant le fichier .swp.\n" "\n" +msgid "Using crypt key from swap file for the text file.\n" +msgstr "" +"Utilisation de la cl้ de chiffrement du fichier d'้change pour le fichier " +"texte.\n" + #. use msg() to start the scrolling properly -#: ../memline.c:1327 msgid "Swap files found:" msgstr "Fichiers d'้change trouv้s :" -#: ../memline.c:1446 msgid " In current directory:\n" msgstr " Dans le r้pertoire courant :\n" -#: ../memline.c:1448 msgid " Using specified name:\n" msgstr "Utilisant le nom indiqu้ :\n" -#: ../memline.c:1450 msgid " In directory " msgstr " Dans le r้pertoire " -#: ../memline.c:1465 msgid " -- none --\n" msgstr " -- aucun --\n" -#: ../memline.c:1527 msgid " owned by: " msgstr " propri้t้ de : " -#: ../memline.c:1529 msgid " dated: " msgstr " dat้ : " -#: ../memline.c:1532 ../memline.c:3231 msgid " dated: " msgstr " dat้ : " -#: ../memline.c:1548 msgid " [from Vim version 3.0]" msgstr " [de Vim version 3.0]" -#: ../memline.c:1550 msgid " [does not look like a Vim swap file]" msgstr " [ne semble pas ๊tre un fichier d'้change Vim]" -#: ../memline.c:1552 msgid " file name: " msgstr " nom de fichier : " -#: ../memline.c:1558 msgid "" "\n" " modified: " @@ -4133,15 +3842,12 @@ msgstr "" "\n" " modifi้ : " -#: ../memline.c:1559 msgid "YES" msgstr "OUI" -#: ../memline.c:1559 msgid "no" msgstr "non" -#: ../memline.c:1562 msgid "" "\n" " user name: " @@ -4149,11 +3855,9 @@ msgstr "" "\n" " nom d'utilisateur : " -#: ../memline.c:1568 msgid " host name: " msgstr " nom d'h๔te : " -#: ../memline.c:1570 msgid "" "\n" " host name: " @@ -4161,7 +3865,6 @@ msgstr "" "\n" " nom d'h๔te : " -#: ../memline.c:1575 msgid "" "\n" " process ID: " @@ -4169,11 +3872,16 @@ msgstr "" "\n" " processus nฐ : " -#: ../memline.c:1579 msgid " (still running)" msgstr " (en cours d'ex้cution)" -#: ../memline.c:1586 +msgid "" +"\n" +" [not usable with this version of Vim]" +msgstr "" +"\n" +" [inutilisable avec cette version de Vim]" + msgid "" "\n" " [not usable on this computer]" @@ -4181,97 +3889,75 @@ msgstr "" "\n" " [inutilisable sur cet ordinateur]" -#: ../memline.c:1590 msgid " [cannot be read]" msgstr " [ne peut ๊tre lu]" -#: ../memline.c:1593 msgid " [cannot be opened]" msgstr " [ne peut ๊tre ouvert]" -#: ../memline.c:1698 msgid "E313: Cannot preserve, there is no swap file" msgstr "E313: Pr้servation impossible, il n'y a pas de fichier d'้change" -#: ../memline.c:1747 msgid "File preserved" msgstr "Fichier pr้serv้" -#: ../memline.c:1749 msgid "E314: Preserve failed" msgstr "E314: ษchec de la pr้servation" -#: ../memline.c:1819 #, c-format -msgid "E315: ml_get: invalid lnum: %<PRId64>" -msgstr "E315: ml_get : num้ro de ligne invalide : %<PRId64>" +msgid "E315: ml_get: invalid lnum: %ld" +msgstr "E315: ml_get : num้ro de ligne invalide : %ld" -#: ../memline.c:1851 #, c-format -msgid "E316: ml_get: cannot find line %<PRId64>" -msgstr "E316: ml_get : ligne %<PRId64> introuvable" +msgid "E316: ml_get: cannot find line %ld" +msgstr "E316: ml_get : ligne %ld introuvable" -#: ../memline.c:2236 msgid "E317: pointer block id wrong 3" msgstr "E317: mauvais id de pointeur de bloc 3" -#: ../memline.c:2311 msgid "stack_idx should be 0" msgstr "stack_idx devrait ๊tre 0" -#: ../memline.c:2369 msgid "E318: Updated too many blocks?" msgstr "E318: Trop de blocs mis เ jour ?" -#: ../memline.c:2511 msgid "E317: pointer block id wrong 4" msgstr "E317: mauvais id de pointeur de bloc 4" -#: ../memline.c:2536 msgid "deleted block 1?" msgstr "bloc 1 effac้ ?" -#: ../memline.c:2707 #, c-format -msgid "E320: Cannot find line %<PRId64>" -msgstr "E320: Ligne %<PRId64> introuvable" +msgid "E320: Cannot find line %ld" +msgstr "E320: Ligne %ld introuvable" -#: ../memline.c:2916 msgid "E317: pointer block id wrong" msgstr "E317: mauvais id de pointeur de bloc" -#: ../memline.c:2930 msgid "pe_line_count is zero" msgstr "pe_line_count vaut z้ro" -#: ../memline.c:2955 #, c-format -msgid "E322: line number out of range: %<PRId64> past the end" -msgstr "E322: num้ro de ligne hors limites : %<PRId64> au-delเ de la fin" +msgid "E322: line number out of range: %ld past the end" +msgstr "E322: num้ro de ligne hors limites : %ld au-delเ de la fin" -#: ../memline.c:2959 #, c-format -msgid "E323: line count wrong in block %<PRId64>" -msgstr "E323: nombre de lignes erron้ dans le bloc %<PRId64>" +msgid "E323: line count wrong in block %ld" +msgstr "E323: nombre de lignes erron้ dans le bloc %ld" -#: ../memline.c:2999 msgid "Stack size increases" msgstr "La taille de la pile s'accro๎t" -#: ../memline.c:3038 msgid "E317: pointer block id wrong 2" msgstr "E317: mauvais id de pointeur de block 2" -#: ../memline.c:3070 #, c-format msgid "E773: Symlink loop for \"%s\"" msgstr "E773: cycle de liens symboliques avec \"%s\"" -#: ../memline.c:3221 msgid "E325: ATTENTION" msgstr "E325: ATTENTION" -#: ../memline.c:3222 msgid "" "\n" "Found a swap file by the name \"" @@ -4279,39 +3965,32 @@ msgstr "" "\n" "Trouv้ un fichier d'้change nomm้ \"" -#: ../memline.c:3226 msgid "While opening file \"" msgstr "Lors de l'ouverture du fichier \"" -#: ../memline.c:3239 msgid " NEWER than swap file!\n" msgstr " PLUS RษCENT que le fichier d'้change !\n" -#: ../memline.c:3244 +#. Some of these messages are long to allow translation to +#. * other languages. msgid "" "\n" "(1) Another program may be editing the same file. If this is the case,\n" " be careful not to end up with two different instances of the same\n" -" file when making changes." +" file when making changes. Quit, or continue with caution.\n" msgstr "" "\n" "(1) Un autre programme est peut-๊tre en train d'้diter ce fichier.\n" " Si c'est le cas, faites attention เ ne pas vous retrouver avec\n" -" deux versions diff้rentes du m๊me fichier en faisant des modifications." - -#: ../memline.c:3245 -msgid " Quit, or continue with caution.\n" -msgstr " Quittez, ou continuez prudemment.\n" +" deux versions diff้rentes du m๊me fichier en faisant des modifications.\n" +" Quitter ou continuer avec attention.\n" -#: ../memline.c:3246 msgid "(2) An edit session for this file crashed.\n" msgstr "(2) Une session d'้dition de ce fichier a plant้.\n" -#: ../memline.c:3247 msgid " If this is the case, use \":recover\" or \"vim -r " msgstr " Si c'est le cas, utilisez \":recover\" ou \"vim -r " -#: ../memline.c:3249 msgid "" "\"\n" " to recover the changes (see \":help recovery\").\n" @@ -4319,11 +3998,9 @@ msgstr "" "\"\n" " pour r้cup้rer le fichier (consultez \":help recovery\").\n" -#: ../memline.c:3250 msgid " If you did this already, delete the swap file \"" msgstr " Si vous l'avez d้jเ fait, effacez le fichier d'้change \"" -#: ../memline.c:3252 msgid "" "\"\n" " to avoid this message.\n" @@ -4331,23 +4008,18 @@ msgstr "" "\"\n" " pour ้viter ce message.\n" -#: ../memline.c:3450 ../memline.c:3452 msgid "Swap file \"" msgstr "Le fichier d'้change \"" -#: ../memline.c:3451 ../memline.c:3455 msgid "\" already exists!" msgstr "\" existe d้jเ !" -#: ../memline.c:3457 msgid "VIM - ATTENTION" msgstr "VIM - ATTENTION" -#: ../memline.c:3459 msgid "Swap file already exists!" msgstr "Un fichier d'้change existe d้jเ !" -#: ../memline.c:3464 msgid "" "&Open Read-Only\n" "&Edit anyway\n" @@ -4361,7 +4033,6 @@ msgstr "" "&Quitter\n" "&Abandonner" -#: ../memline.c:3467 msgid "" "&Open Read-Only\n" "&Edit anyway\n" @@ -4377,58 +4048,36 @@ msgstr "" "&Quitter\n" "&Abandonner" -#. -#. * Change the ".swp" extension to find another file that can be used. -#. * First decrement the last char: ".swo", ".swn", etc. -#. * If that still isn't enough decrement the last but one char: ".svz" -#. * Can happen when editing many "No Name" buffers. -#. -#. ".s?a" -#. ".saa": tried enough, give up -#: ../memline.c:3528 msgid "E326: Too many swap files found" msgstr "E326: Trop de fichiers d'้change trouv้s" -#: ../memory.c:227 -#, c-format -msgid "E342: Out of memory! (allocating %<PRIu64> bytes)" -msgstr "E342: M้moire ้puis้e ! (allocation de %<PRIu64> octets)" - -#: ../menu.c:62 msgid "E327: Part of menu-item path is not sub-menu" msgstr "E327: Une partie du chemin de l'้l้ment de menu n'est pas un sous-menu" # DB - todo : J'h้site avec # msgstr "E328: Le menu n'existe pas dans ce mode" -#: ../menu.c:63 msgid "E328: Menu only exists in another mode" msgstr "E328: Le menu n'existe que dans un autre mode" -#: ../menu.c:64 #, c-format msgid "E329: No menu \"%s\"" msgstr "E329: Aucun menu \"%s\"" #. Only a mnemonic or accelerator is not valid. -#: ../menu.c:329 msgid "E792: Empty menu name" msgstr "E792: Nom de menu vide" -#: ../menu.c:340 msgid "E330: Menu path must not lead to a sub-menu" msgstr "E330: Le chemin de menu ne doit pas conduire เ un sous-menu" -#: ../menu.c:365 msgid "E331: Must not add menu items directly to menu bar" msgstr "E331: Ajout d'้l้ments de menu directement dans barre de menu interdit" -#: ../menu.c:370 msgid "E332: Separator cannot be part of a menu path" msgstr "E332: Un s้parateur ne peut faire partie d'un chemin de menu" #. Now we have found the matching menu, and we list the mappings #. Highlight title -#: ../menu.c:762 msgid "" "\n" "--- Menus ---" @@ -4436,71 +4085,62 @@ msgstr "" "\n" "--- Menus ---" -#: ../menu.c:1313 +msgid "Tear off this menu" +msgstr "D้tacher ce menu" + msgid "E333: Menu path must lead to a menu item" msgstr "E333: Le chemin du menu doit conduire เ un ้l้ment de menu" -#: ../menu.c:1330 #, c-format msgid "E334: Menu not found: %s" msgstr "E334: Menu introuvable : %s" -#: ../menu.c:1396 #, c-format msgid "E335: Menu not defined for %s mode" msgstr "E335: Le menu n'est pas d้fini pour le mode %s" -#: ../menu.c:1426 msgid "E336: Menu path must lead to a sub-menu" msgstr "E336: Le chemin du menu doit conduire เ un sous-menu" -#: ../menu.c:1447 msgid "E337: Menu not found - check menu names" msgstr "E337: Menu introuvable - v้rifiez les noms des menus" -#: ../message.c:423 #, c-format msgid "Error detected while processing %s:" msgstr "Erreur d้tect้e en traitant %s :" -#: ../message.c:445 #, c-format msgid "line %4ld:" msgstr "ligne %4ld :" -#: ../message.c:617 #, c-format msgid "E354: Invalid register name: '%s'" msgstr "E354: Nom de registre invalide : '%s'" # DB - todo : mettre เ jour ? -#: ../message.c:986 +msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>" +msgstr "Maintenance des messages : Dominique Pell้ <dominique.pelle@gmail.com>" + msgid "Interrupt: " msgstr "Interruption : " -#: ../message.c:988 msgid "Press ENTER or type command to continue" msgstr "Appuyez sur ENTRษE ou tapez une commande pour continuer" -#: ../message.c:1843 #, c-format -msgid "%s line %<PRId64>" -msgstr "%s, ligne %<PRId64>" +msgid "%s line %ld" +msgstr "%s, ligne %ld" -#: ../message.c:2392 msgid "-- More --" msgstr "-- Plus --" -#: ../message.c:2398 msgid " SPACE/d/j: screen/page/line down, b/u/k: up, q: quit " msgstr "" "ESPACE/d/j : ้cran/page/ligne vers le bas, b/u/k : vers le haut, q : quitter" -#: ../message.c:3021 ../message.c:3031 msgid "Question" msgstr "Question" -#: ../message.c:3023 msgid "" "&Yes\n" "&No" @@ -4508,17 +4148,6 @@ msgstr "" "&Oui\n" "&Non" -#: ../message.c:3033 -msgid "" -"&Yes\n" -"&No\n" -"&Cancel" -msgstr "" -"&Oui\n" -"&Non\n" -"&Annuler" - -#: ../message.c:3045 msgid "" "&Yes\n" "&No\n" @@ -4532,176 +4161,251 @@ msgstr "" "Tout aban&donner\n" "&Annuler" -#: ../message.c:3058 +# DB : Les trois messages qui suivent sont des titres de bo๎tes +# de dialogue par d้faut. +msgid "Select Directory dialog" +msgstr "S้lecteur de r้pertoire" + +msgid "Save File dialog" +msgstr "Enregistrer un fichier" + +msgid "Open File dialog" +msgstr "Ouvrir un fichier" + +#. TODO: non-GUI file selector here +msgid "E338: Sorry, no file browser in console mode" +msgstr "E338: D้sol้, pas de s้lecteur de fichiers en mode console" + msgid "E766: Insufficient arguments for printf()" msgstr "E766: Pas assez d'arguments pour printf()" -#: ../message.c:3119 msgid "E807: Expected Float argument for printf()" msgstr "E807: printf() attend un argument de type Flottant" -#: ../message.c:3873 msgid "E767: Too many arguments to printf()" msgstr "E767: Trop d'arguments pour printf()" -#: ../misc1.c:2256 msgid "W10: Warning: Changing a readonly file" msgstr "W10: Alerte : Modification d'un fichier en lecture seule" -#: ../misc1.c:2537 msgid "Type number and <Enter> or click with mouse (empty cancels): " msgstr "Tapez un nombre et <Entr้e> ou cliquez avec la souris (rien annule) :" -#: ../misc1.c:2539 msgid "Type number and <Enter> (empty cancels): " msgstr "Tapez un nombre et <Entr้e> (rien annule) :" -#: ../misc1.c:2585 msgid "1 more line" msgstr "1 ligne en plus" -#: ../misc1.c:2588 msgid "1 line less" msgstr "1 ligne en moins" -#: ../misc1.c:2593 #, c-format -msgid "%<PRId64> more lines" -msgstr "%<PRId64> lignes en plus" +msgid "%ld more lines" +msgstr "%ld lignes en plus" -#: ../misc1.c:2596 #, c-format -msgid "%<PRId64> fewer lines" -msgstr "%<PRId64> lignes en moins" +msgid "%ld fewer lines" +msgstr "%ld lignes en moins" -#: ../misc1.c:2599 msgid " (Interrupted)" msgstr " (Interrompu)" -#: ../misc1.c:2635 msgid "Beep!" msgstr "Bip !" -#: ../misc2.c:738 +msgid "ERROR: " +msgstr "ERREUR : " + +#, c-format +msgid "" +"\n" +"[bytes] total alloc-freed %lu-%lu, in use %lu, peak use %lu\n" +msgstr "" +"\n" +"[octets] total allou้-lib้r้ %lu-%lu, utilis้ %lu, pic %lu\n" + +#, c-format +msgid "" +"[calls] total re/malloc()'s %lu, total free()'s %lu\n" +"\n" +msgstr "" +"[appels] total re/malloc() %lu, total free() %lu\n" +"\n" + +msgid "E340: Line is becoming too long" +msgstr "E340: La ligne devient trop longue" + +#, c-format +msgid "E341: Internal error: lalloc(%ld, )" +msgstr "E341: Erreur interne : lalloc(%ld, )" + +#, c-format +msgid "E342: Out of memory! (allocating %lu bytes)" +msgstr "E342: M้moire ้puis้e ! (allocation de %lu octets)" + #, c-format msgid "Calling shell to execute: \"%s\"" msgstr "Appel du shell pour ex้cuter : \"%s\"" -#: ../normal.c:183 +msgid "E545: Missing colon" +msgstr "E545: ':' manquant" + +msgid "E546: Illegal mode" +msgstr "E546: Mode non autoris้" + +msgid "E547: Illegal mouseshape" +msgstr "E547: Forme de curseur invalide" + +msgid "E548: digit expected" +msgstr "E548: chiffre attendu" + +msgid "E549: Illegal percentage" +msgstr "E549: Pourcentage non autoris้" + +msgid "E854: path too long for completion" +msgstr "E854: chemin trop long pour compl่tement" + +#, c-format +msgid "" +"E343: Invalid path: '**[number]' must be at the end of the path or be " +"followed by '%s'." +msgstr "" +"E343: Chemin invalide : '**[nombre]' doit ๊tre เ la fin du chemin ou ๊tre " +"suivi de '%s'." + +#, c-format +msgid "E344: Can't find directory \"%s\" in cdpath" +msgstr "E344: R้pertoire \"%s\" introuvable dans 'cdpath'" + +#, c-format +msgid "E345: Can't find file \"%s\" in path" +msgstr "E345: Fichier \"%s\" introuvable dans 'path'" + +#, c-format +msgid "E346: No more directory \"%s\" found in cdpath" +msgstr "E346: Plus de r้pertoire \"%s\" dans 'cdpath'" + +#, c-format +msgid "E347: No more file \"%s\" found in path" +msgstr "E347: Plus de fichier \"%s\" dans 'path'" + +#, c-format +msgid "E668: Wrong access mode for NetBeans connection info file: \"%s\"" +msgstr "" +"E668: Mode d'acc่s incorrect au fichier d'infos de connexion NetBeans : \"%s" +"\"" + +#, c-format +msgid "E658: NetBeans connection lost for buffer %ld" +msgstr "E658: Connexion NetBeans perdue pour le tampon %ld" + +msgid "E838: netbeans is not supported with this GUI" +msgstr "E838: netbeans n'est pas support้ avec cette interface graphique" + +msgid "E511: netbeans already connected" +msgstr "E511: netbeans d้jเ connect้" + +#, c-format +msgid "E505: %s is read-only (add ! to override)" +msgstr "E505: %s est en lecture seule (ajoutez ! pour passer outre)" + msgid "E349: No identifier under cursor" msgstr "E349: Aucun identifiant sous le curseur" -#: ../normal.c:1866 msgid "E774: 'operatorfunc' is empty" msgstr "E774: 'operatorfunc' est vide" +msgid "E775: Eval feature not available" +msgstr "E775: La fonctionnalit้ d'้valuation n'est pas disponible" + # DB : Il est ici question du mode Visuel. -#: ../normal.c:2637 msgid "Warning: terminal cannot highlight" msgstr "Alerte : le terminal ne peut pas surligner" -#: ../normal.c:2807 msgid "E348: No string under cursor" msgstr "E348: Aucune cha๎ne sous le curseur" -#: ../normal.c:3937 msgid "E352: Cannot erase folds with current 'foldmethod'" msgstr "E352: Impossible d'effacer des replis avec la 'foldmethod'e actuelle" -#: ../normal.c:5897 msgid "E664: changelist is empty" msgstr "E664: La liste des modifications (changelist) est vide" -#: ../normal.c:5899 msgid "E662: At start of changelist" msgstr "E662: Au d้but de la liste des modifications" -#: ../normal.c:5901 msgid "E663: At end of changelist" msgstr "E663: ภ la fin de la liste des modifications" -#: ../normal.c:7053 -msgid "Type :quit<Enter> to exit Nvim" +msgid "Type :quit<Enter> to exit Vim" msgstr "tapez :q<Entr้e> pour quitter Vim" -#: ../ops.c:248 #, c-format msgid "1 line %sed 1 time" msgstr "1 ligne %s้e 1 fois" -#: ../ops.c:250 #, c-format msgid "1 line %sed %d times" msgstr "1 ligne %s้e %d fois" -#: ../ops.c:253 #, c-format -msgid "%<PRId64> lines %sed 1 time" -msgstr "%<PRId64> lignes %s้es 1 fois" +msgid "%ld lines %sed 1 time" +msgstr "%ld lignes %s้es 1 fois" -#: ../ops.c:256 #, c-format -msgid "%<PRId64> lines %sed %d times" -msgstr "%<PRId64> lignes %s้es %d fois" +msgid "%ld lines %sed %d times" +msgstr "%ld lignes %s้es %d fois" -#: ../ops.c:592 #, c-format -msgid "%<PRId64> lines to indent... " -msgstr "%<PRId64> lignes เ indenter... " +msgid "%ld lines to indent... " +msgstr "%ld lignes เ indenter... " -#: ../ops.c:634 msgid "1 line indented " msgstr "1 ligne indent้e " -#: ../ops.c:636 #, c-format -msgid "%<PRId64> lines indented " -msgstr "%<PRId64> lignes indent้es " +msgid "%ld lines indented " +msgstr "%ld lignes indent้es " -#: ../ops.c:938 msgid "E748: No previously used register" msgstr "E748: Aucun registre n'a ้t้ pr้c้demment utilis้" # DB - Question O/N. #. must display the prompt -#: ../ops.c:1433 msgid "cannot yank; delete anyway" msgstr "impossible de r้aliser une copie ; effacer tout de m๊me" -#: ../ops.c:1929 msgid "1 line changed" msgstr "1 ligne modifi้e" -#: ../ops.c:1931 #, c-format -msgid "%<PRId64> lines changed" -msgstr "%<PRId64> lignes modifi้es" +msgid "%ld lines changed" +msgstr "%ld lignes modifi้es" + +#, c-format +msgid "freeing %ld lines" +msgstr "lib้ration de %ld lignes" -#: ../ops.c:2521 msgid "block of 1 line yanked" msgstr "bloc de 1 ligne copi้" -#: ../ops.c:2523 msgid "1 line yanked" msgstr "1 ligne copi้e" -#: ../ops.c:2525 #, c-format -msgid "block of %<PRId64> lines yanked" -msgstr "bloc de %<PRId64> lignes copi้" +msgid "block of %ld lines yanked" +msgstr "bloc de %ld lignes copi้" -#: ../ops.c:2528 #, c-format -msgid "%<PRId64> lines yanked" -msgstr "%<PRId64> lignes copi้es" +msgid "%ld lines yanked" +msgstr "%ld lignes copi้es" -#: ../ops.c:2710 #, c-format msgid "E353: Nothing in register %s" msgstr "E353: Le registre %s est vide" #. Highlight title -#: ../ops.c:3185 msgid "" "\n" "--- Registers ---" @@ -4709,11 +4413,9 @@ msgstr "" "\n" "--- Registres ---" -#: ../ops.c:4455 msgid "Illegal register name" msgstr "Nom de registre invalide" -#: ../ops.c:4533 msgid "" "\n" "# Registers:\n" @@ -4721,189 +4423,179 @@ msgstr "" "\n" "# Registres :\n" -#: ../ops.c:4575 #, c-format msgid "E574: Unknown register type %d" msgstr "E574: Type de registre %d inconnu" -#: ../ops.c:5089 +msgid "" +"E883: search pattern and expression register may not contain two or more " +"lines" +msgstr "" +"E883: le motif de recherche et le registre d'expression ne peuvent pas " +"contenir deux lignes ou plus" + #, c-format -msgid "%<PRId64> Cols; " -msgstr "%<PRId64> Colonnes ; " +msgid "%ld Cols; " +msgstr "%ld Colonnes ; " -#: ../ops.c:5097 #, c-format -msgid "" -"Selected %s%<PRId64> of %<PRId64> Lines; %<PRId64> of %<PRId64> Words; " -"%<PRId64> of %<PRId64> Bytes" +msgid "Selected %s%ld of %ld Lines; %lld of %lld Words; %lld of %lld Bytes" msgstr "" -"%s%<PRId64> sur %<PRId64> Lignes ; %<PRId64> sur %<PRId64> Mots ; %<PRId64> " -"sur %<PRId64> Octets s้lectionn้s" +"%s%ld sur %ld Lignes ; %lld sur %lld Mots ; %lld sur %lld Octets s้lectionn้s" -#: ../ops.c:5105 #, c-format msgid "" -"Selected %s%<PRId64> of %<PRId64> Lines; %<PRId64> of %<PRId64> Words; " -"%<PRId64> of %<PRId64> Chars; %<PRId64> of %<PRId64> Bytes" +"Selected %s%ld of %ld Lines; %lld of %lld Words; %lld of %lld Chars; %lld of " +"%lld Bytes" msgstr "" -"%s%<PRId64> sur %<PRId64> Lignes ; %<PRId64> sur %<PRId64> Mots ; %<PRId64> " -"sur %<PRId64> Caract่res ; %<PRId64> sur %<PRId64> octets s้lectionn้s" +"%s%ld sur %ld Lignes ; %lld sur %lld Mots ; %lld sur %lld Caract่res ; %lld " +"sur %lld octets s้lectionn้s" -#: ../ops.c:5123 #, c-format -msgid "" -"Col %s of %s; Line %<PRId64> of %<PRId64>; Word %<PRId64> of %<PRId64>; Byte " -"%<PRId64> of %<PRId64>" +msgid "Col %s of %s; Line %ld of %ld; Word %lld of %lld; Byte %lld of %lld" msgstr "" -"Colonne %s sur %s ; Ligne %<PRId64> sur %<PRId64> ; Mot %<PRId64> sur " -"%<PRId64> ; Octet %<PRId64> sur %<PRId64>" +"Colonne %s sur %s ; Ligne %ld sur %ld ; Mot %lld sur %lld ; Octet %lld sur " +"%lld" -#: ../ops.c:5133 #, c-format msgid "" -"Col %s of %s; Line %<PRId64> of %<PRId64>; Word %<PRId64> of %<PRId64>; Char " -"%<PRId64> of %<PRId64>; Byte %<PRId64> of %<PRId64>" +"Col %s of %s; Line %ld of %ld; Word %lld of %lld; Char %lld of %lld; Byte " +"%lld of %lld" msgstr "" -"Colonne %s sur %s ; Ligne %<PRId64> sur %<PRId64> ; Mot %<PRId64> sur " -"%<PRId64> ; Caract่re %<PRId64> sur %<PRId64> ; Octet %<PRId64> sur %<PRId64>" +"Colonne %s sur %s ; Ligne %ld sur %ld ; Mot %lld sur %lld ; Caract่re %lld " +"sur %lld ; Octet %lld sur %lld" -#: ../ops.c:5146 #, c-format -msgid "(+%<PRId64> for BOM)" -msgstr "(+%<PRId64> pour le BOM)" +msgid "(+%ld for BOM)" +msgstr "(+%ld pour le BOM)" -#: ../option.c:1238 msgid "%<%f%h%m%=Page %N" msgstr "%<%f%h%m%=Page %N" -#: ../option.c:1574 msgid "Thanks for flying Vim" msgstr "Merci d'avoir choisi Vim" -#. found a mismatch: skip -#: ../option.c:2698 msgid "E518: Unknown option" msgstr "E518: Option inconnue" -#: ../option.c:2709 msgid "E519: Option not supported" msgstr "E519: Option non support้e" -#: ../option.c:2740 msgid "E520: Not allowed in a modeline" msgstr "E520: Non autoris้ dans une ligne de mode" -#: ../option.c:2815 msgid "E846: Key code not set" msgstr "E846: Le code de touche n'est pas configur้" -#: ../option.c:2924 msgid "E521: Number required after =" msgstr "E521: Nombre requis apr่s =" -#: ../option.c:3226 ../option.c:3864 msgid "E522: Not found in termcap" msgstr "E522: Introuvable dans termcap" -#: ../option.c:3335 #, c-format msgid "E539: Illegal character <%s>" msgstr "E539: Caract่re <%s> invalide" -#: ../option.c:2253 #, c-format msgid "For option %s" msgstr "Pour l'option %s" -#: ../option.c:3862 msgid "E529: Cannot set 'term' to empty string" msgstr "E529: 'term' ne doit pas ๊tre une cha๎ne vide" -#: ../option.c:3885 +msgid "E530: Cannot change term in GUI" +msgstr "E530: Impossible de modifier term dans l'interface graphique" + +msgid "E531: Use \":gui\" to start the GUI" +msgstr "E531: Utilisez \":gui\" pour d้marrer l'interface graphique" + msgid "E589: 'backupext' and 'patchmode' are equal" msgstr "E589: 'backupext' et 'patchmode' sont ้gaux" -#: ../option.c:3964 msgid "E834: Conflicts with value of 'listchars'" msgstr "E834: Conflits avec la valeur de 'listchars'" -#: ../option.c:3966 msgid "E835: Conflicts with value of 'fillchars'" msgstr "E835: Conflits avec la valeur de 'fillchars'" -#: ../option.c:4163 +msgid "E617: Cannot be changed in the GTK+ 2 GUI" +msgstr "E617: Non modifiable dans l'interface graphique GTK+ 2" + msgid "E524: Missing colon" msgstr "E524: ':' manquant" -#: ../option.c:4165 msgid "E525: Zero length string" msgstr "E525: Cha๎ne de longueur nulle" -#: ../option.c:4220 #, c-format msgid "E526: Missing number after <%s>" msgstr "E526: Nombre manquant apr่s <%s>" -#: ../option.c:4232 msgid "E527: Missing comma" msgstr "E527: Virgule manquante" -#: ../option.c:4239 msgid "E528: Must specify a ' value" msgstr "E528: Une valeur ' doit ๊tre sp้cifi้e" -#: ../option.c:4271 msgid "E595: contains unprintable or wide character" msgstr "E595: contient des caract่res เ largeur double non-imprimables" -#: ../option.c:4469 +msgid "E596: Invalid font(s)" +msgstr "E596: Police(s) invalide(s)" + +msgid "E597: can't select fontset" +msgstr "E597: Impossible de s้lectionner un jeu de polices" + +msgid "E598: Invalid fontset" +msgstr "E598: Jeu de polices invalide" + +msgid "E533: can't select wide font" +msgstr "E533: Impossible de s้lectionner une police เ largeur double" + +msgid "E534: Invalid wide font" +msgstr "E534: Police เ largeur double invalide" + #, c-format msgid "E535: Illegal character after <%c>" msgstr "E535: Caract่re invalide apr่s <%c>" -#: ../option.c:4534 msgid "E536: comma required" msgstr "E536: virgule requise" -#: ../option.c:4543 #, c-format msgid "E537: 'commentstring' must be empty or contain %s" msgstr "E537: 'commentstring' doit ๊tre vide ou contenir %s" +msgid "E538: No mouse support" +msgstr "E538: La souris n'est pas support้e" + # DB - Le code est sans ambigu๏t้ sur le caract่re manquant. # ภ d้faut d'une traduction valable, au moins comprend-on # ce qui se passe. -#: ../option.c:4928 msgid "E540: Unclosed expression sequence" msgstr "E540: '}' manquant" -#: ../option.c:4932 msgid "E541: too many items" msgstr "E541: trop d'้l้ments" -#: ../option.c:4934 msgid "E542: unbalanced groups" msgstr "E542: parenth่ses non ้quilibr้es" -#: ../option.c:5148 msgid "E590: A preview window already exists" msgstr "E590: Il existe d้jเ une fen๊tre de pr้visualisation" -#: ../option.c:5311 msgid "W17: Arabic requires UTF-8, do ':set encoding=utf-8'" -msgstr "W17: L'arabe requiert l'UTF-8, tapez ':set encoding=utf-8'" +msgstr "W17: L'arabe n้cessite l'UTF-8, tapez ':set encoding=utf-8'" -#: ../option.c:5623 #, c-format msgid "E593: Need at least %d lines" msgstr "E593: Au moins %d lignes sont n้cessaires" -#: ../option.c:5631 #, c-format msgid "E594: Need at least %d columns" msgstr "E594: Au moins %d colonnes sont n้cessaires" -#: ../option.c:6011 #, c-format msgid "E355: Unknown option: %s" msgstr "E355: Option inconnue : %s" @@ -4911,12 +4603,10 @@ msgstr "E355: Option inconnue : %s" #. There's another character after zeros or the string #. * is empty. In both cases, we are trying to set a #. * num option using a string. -#: ../option.c:6037 #, c-format msgid "E521: Number required: &%s = '%s'" msgstr "E521: Nombre requis : &%s = '%s'" -#: ../option.c:6149 msgid "" "\n" "--- Terminal codes ---" @@ -4924,7 +4614,6 @@ msgstr "" "\n" "--- Codes de terminal ---" -#: ../option.c:6151 msgid "" "\n" "--- Global option values ---" @@ -4932,7 +4621,6 @@ msgstr "" "\n" "--- Valeur des options globales ---" -#: ../option.c:6153 msgid "" "\n" "--- Local option values ---" @@ -4940,7 +4628,6 @@ msgstr "" "\n" "--- Valeur des options locales ---" -#: ../option.c:6155 msgid "" "\n" "--- Options ---" @@ -4948,29 +4635,147 @@ msgstr "" "\n" "--- Options ---" -#: ../option.c:6816 msgid "E356: get_varp ERROR" msgstr "E356: ERREUR get_varp" -#: ../option.c:7696 #, c-format msgid "E357: 'langmap': Matching character missing for %s" msgstr "E357: 'langmap' : Aucun caract่re correspondant pour %s" -#: ../option.c:7715 #, c-format msgid "E358: 'langmap': Extra characters after semicolon: %s" msgstr "E358: 'langmap' : Caract่res surnum้raires apr่s point-virgule : %s" -#: ../os/shell.c:194 +msgid "cannot open " +msgstr "impossible d'ouvrir " + +msgid "VIM: Can't open window!\n" +msgstr "VIM : Impossible d'ouvrir la fen๊tre !\n" + +msgid "Need Amigados version 2.04 or later\n" +msgstr "Amigados version 2.04 ou ult้rieure est n้cessaire\n" + +#, c-format +msgid "Need %s version %ld\n" +msgstr "%s version %ld est n้cessaire\n" + +msgid "Cannot open NIL:\n" +msgstr "Impossible d'ouvrir NIL :\n" + +msgid "Cannot create " +msgstr "Impossible de cr้er " + +#, c-format +msgid "Vim exiting with %d\n" +msgstr "Vim quitte avec %d\n" + +msgid "cannot change console mode ?!\n" +msgstr "Impossible de modifier le mode de la console ?!\n" + +msgid "mch_get_shellsize: not a console??\n" +msgstr "mch_get_shellsize : pas une console ?!\n" + +#. if Vim opened a window: Executing a shell may cause crashes +msgid "E360: Cannot execute shell with -f option" +msgstr "E360: Impossible d'ex้cuter un shell avec l'option -f" + +msgid "Cannot execute " +msgstr "Impossible d'ex้cuter " + +msgid "shell " +msgstr "le shell " + +msgid " returned\n" +msgstr " a ้t้ retourn้\n" + +msgid "ANCHOR_BUF_SIZE too small." +msgstr "ANCHOR_BUF_SIZE trop petit." + +msgid "I/O ERROR" +msgstr "ERREUR d'E/S" + +msgid "Message" +msgstr "Message" + +msgid "E237: Printer selection failed" +msgstr "E237: La s้lection de l'imprimante a ้chou้" + +# DB - Contenu des c-formats : Imprimante puis Port. +#, c-format +msgid "to %s on %s" +msgstr "vers %s sur %s" + +#, c-format +msgid "E613: Unknown printer font: %s" +msgstr "E613: Police d'imprimante inconnue : %s" + +#, c-format +msgid "E238: Print error: %s" +msgstr "E238: Erreur d'impression : %s" + +#, c-format +msgid "Printing '%s'" +msgstr "Impression de '%s'" + +#, c-format +msgid "E244: Illegal charset name \"%s\" in font name \"%s\"" +msgstr "E244: Jeu de caract่res \"%s\" invalide dans le nom de fonte \"%s\"" + +#, c-format +msgid "E244: Illegal quality name \"%s\" in font name \"%s\"" +msgstr "E244: Nom de qualit้ \"%s\" invalide dans le nom de fonte \"%s\"" + +#, c-format +msgid "E245: Illegal char '%c' in font name \"%s\"" +msgstr "E245: Caract่re '%c' invalide dans le nom de fonte \"%s\"" + +#, c-format +msgid "Opening the X display took %ld msec" +msgstr "L'ouverture du display X a pris %ld ms" + msgid "" "\n" -"Cannot execute shell " +"Vim: Got X error\n" msgstr "" "\n" -"Impossible d'ex้cuter le shell " +"Vim : R้ception d'une erreur X\n" + +msgid "Testing the X display failed" +msgstr "Le test du display X a ้chou้" + +msgid "Opening the X display timed out" +msgstr "L'ouverture du display X a d้pass้ le d้lai d'attente" + +msgid "" +"\n" +"Could not get security context for " +msgstr "" +"\n" +"Impossible d'obtenir le contexte de s้curit้ pour " + +msgid "" +"\n" +"Could not set security context for " +msgstr "" +"\n" +"Impossible de modifier le contexte de s้curit้ pour " + +#, c-format +msgid "Could not set security context %s for %s" +msgstr "Impossible d'initialiser le contexte de s้curit้ %s pour %s" + +#, c-format +msgid "Could not get security context %s for %s. Removing it!" +msgstr "" +"Impossible d'obtenir le contexte de s้curit้ %s pour %s. Il sera supprim้ !" + +msgid "" +"\n" +"Cannot execute shell sh\n" +msgstr "" +"\n" +"Impossible d'ex้cuter le shell sh\n" -#: ../os/shell.c:439 msgid "" "\n" "shell returned " @@ -4978,234 +4783,278 @@ msgstr "" "\n" "le shell a retourn้ " -#: ../os_unix.c:465 ../os_unix.c:471 msgid "" "\n" -"Could not get security context for " +"Cannot create pipes\n" msgstr "" "\n" -"Impossible d'obtenir le contexte de s้curit้ pour " +"Impossible de cr้er des tuyaux (pipes)\n" -#: ../os_unix.c:479 msgid "" "\n" -"Could not set security context for " +"Cannot fork\n" msgstr "" "\n" -"Impossible de modifier le contexte de s้curit้ pour " +"Impossible de forker\n" + +msgid "" +"\n" +"Cannot execute shell " +msgstr "" +"\n" +"Impossible d'ex้cuter le shell " + +msgid "" +"\n" +"Command terminated\n" +msgstr "" +"\n" +"Commande interrompue\n" + +msgid "XSMP lost ICE connection" +msgstr "XSMP a perdu la connexion ICE" -#: ../os_unix.c:1558 ../os_unix.c:1647 #, c-format msgid "dlerror = \"%s\"" msgstr "dlerror = \"%s\"" -#: ../path.c:1449 +msgid "Opening the X display failed" +msgstr "L'ouverture du display X a ้chou้" + +msgid "XSMP handling save-yourself request" +msgstr "XSMP : prise en charge d'une requ๊te save-yourself" + +msgid "XSMP opening connection" +msgstr "XSMP : ouverture de la connexion" + +msgid "XSMP ICE connection watch failed" +msgstr "XSMP : ้chec de la surveillance de connexion ICE" + #, c-format -msgid "E447: Can't find file \"%s\" in path" -msgstr "E447: Le fichier \"%s\" est introuvable dans 'path'" +msgid "XSMP SmcOpenConnection failed: %s" +msgstr "XSMP : SmcOpenConnection a ้chou้ : %s" + +msgid "At line" +msgstr "ภ la ligne" + +msgid "Could not load vim32.dll!" +msgstr "Impossible de charger vim32.dll !" + +msgid "VIM Error" +msgstr "Erreur VIM" + +msgid "Could not fix up function pointers to the DLL!" +msgstr "Impossible d'initialiser les pointeurs de fonction vers la DLL !" + +# DB - Les ้v้nements en question sont ceux des messages qui suivent. +#, c-format +msgid "Vim: Caught %s event\n" +msgstr "Vim : ษv้nement %s intercept้\n" + +msgid "close" +msgstr "de fermeture" + +msgid "logoff" +msgstr "de d้connexion" + +msgid "shutdown" +msgstr "d'arr๊t" + +msgid "E371: Command not found" +msgstr "E371: Commande introuvable" + +msgid "" +"VIMRUN.EXE not found in your $PATH.\n" +"External commands will not pause after completion.\n" +"See :help win32-vimrun for more information." +msgstr "" +"VIMRUN.EXE est introuvable votre $PATH.\n" +"Les commandes externes ne feront pas de pause une fois termin้es.\n" +"Consultez :help win32-vimrun pour plus d'informations." + +msgid "Vim Warning" +msgstr "Alerte Vim" + +#, c-format +msgid "shell returned %d" +msgstr "le shell a retourn้ %d" -#: ../quickfix.c:359 #, c-format msgid "E372: Too many %%%c in format string" msgstr "E372: Trop de %%%c dans la cha๎ne de format" -#: ../quickfix.c:371 #, c-format msgid "E373: Unexpected %%%c in format string" msgstr "E373: %%%c inattendu dans la cha๎ne de format" -#: ../quickfix.c:420 msgid "E374: Missing ] in format string" msgstr "E374: ] manquant dans la cha๎ne de format" -#: ../quickfix.c:431 #, c-format msgid "E375: Unsupported %%%c in format string" msgstr "E375: %%%c non support้ dans la cha๎ne de format" -#: ../quickfix.c:448 #, c-format msgid "E376: Invalid %%%c in format string prefix" msgstr "E376: %%%c invalide dans le pr้fixe de la cha๎ne de format" -#: ../quickfix.c:454 #, c-format msgid "E377: Invalid %%%c in format string" msgstr "E377: %%%c invalide dans la cha๎ne de format" #. nothing found -#: ../quickfix.c:477 msgid "E378: 'errorformat' contains no pattern" msgstr "E378: 'errorformat' ne contient aucun motif" -#: ../quickfix.c:695 msgid "E379: Missing or empty directory name" msgstr "E379: Nom de r้pertoire vide ou absent" -#: ../quickfix.c:1305 msgid "E553: No more items" msgstr "E553: Plus d'้l้ments" -#: ../quickfix.c:1674 +msgid "E924: Current window was closed" +msgstr "E924: La fen๊tre courante doit ๊tre ferm้e" + +msgid "E925: Current quickfix was changed" +msgstr "E925: Le quickfix courant a chang้" + +msgid "E926: Current location list was changed" +msgstr "E926: La liste d'emplacements courante a chang้" + #, c-format msgid "(%d of %d)%s%s: " msgstr "(%d sur %d)%s%s : " -#: ../quickfix.c:1676 msgid " (line deleted)" msgstr " (ligne effac้e)" -#: ../quickfix.c:1863 +#, c-format +msgid "%serror list %d of %d; %d errors " +msgstr "%sliste d'erreurs %d sur %d ; %d erreurs" + msgid "E380: At bottom of quickfix stack" msgstr "E380: En bas de la pile quickfix" -#: ../quickfix.c:1869 msgid "E381: At top of quickfix stack" msgstr "E381: Au sommet de la pile quickfix" -#: ../quickfix.c:1880 -#, c-format -msgid "error list %d of %d; %d errors" -msgstr "liste d'erreurs %d sur %d ; %d erreurs" +msgid "No entries" +msgstr "Aucune entr้e" -#: ../quickfix.c:2427 msgid "E382: Cannot write, 'buftype' option is set" msgstr "E382: ษcriture impossible, l'option 'buftype' est activ้e" -#: ../quickfix.c:2812 +msgid "Error file" +msgstr "Fichier d'erreurs" + msgid "E683: File name missing or invalid pattern" msgstr "E683: Nom de fichier manquant ou motif invalide" -#: ../quickfix.c:2911 #, c-format msgid "Cannot open file \"%s\"" msgstr "Impossible d'ouvrir le fichier \"%s\"" -#: ../quickfix.c:3429 msgid "E681: Buffer is not loaded" msgstr "E681: le tampon n'est pas charg้" -#: ../quickfix.c:3487 msgid "E777: String or List expected" msgstr "E777: Cha๎ne ou Liste attendue" -#: ../regexp.c:359 #, c-format msgid "E369: invalid item in %s%%[]" msgstr "E369: ้l้ment invalide dans %s%%[]" -#: ../regexp.c:374 #, c-format msgid "E769: Missing ] after %s[" msgstr "E769: ']' manquant apr่s %s[" -#: ../regexp.c:375 #, c-format msgid "E53: Unmatched %s%%(" msgstr "E53: Pas de correspondance pour %s%%(" -#: ../regexp.c:376 #, c-format msgid "E54: Unmatched %s(" msgstr "E54: %s( ouvrante non ferm้e" -#: ../regexp.c:377 #, c-format msgid "E55: Unmatched %s)" msgstr "E55: %s) fermante non ouverte" -#: ../regexp.c:378 msgid "E66: \\z( not allowed here" msgstr "E66: \\z( n'est pas autoris้ ici" -#: ../regexp.c:379 msgid "E67: \\z1 et al. not allowed here" msgstr "E67: \\z1 et co. ne sont pas autoris้s ici" -#: ../regexp.c:380 #, c-format msgid "E69: Missing ] after %s%%[" msgstr "E69: ']' manquant apr่s %s%%[" -#: ../regexp.c:381 #, c-format msgid "E70: Empty %s%%[]" msgstr "E70: %s%%[] vide" -#: ../regexp.c:1209 ../regexp.c:1224 msgid "E339: Pattern too long" msgstr "E339: Motif trop long" -#: ../regexp.c:1371 msgid "E50: Too many \\z(" msgstr "E50: Trop de \\z(" -#: ../regexp.c:1378 #, c-format msgid "E51: Too many %s(" msgstr "E51: Trop de %s(" -#: ../regexp.c:1427 msgid "E52: Unmatched \\z(" msgstr "E52: Pas de correspondance pour \\z(" -#: ../regexp.c:1637 #, c-format msgid "E59: invalid character after %s@" msgstr "E59: caract่re invalide apr่s %s@" -#: ../regexp.c:1672 #, c-format msgid "E60: Too many complex %s{...}s" msgstr "E60: Trop de %s{...}s complexes" -#: ../regexp.c:1687 #, c-format msgid "E61: Nested %s*" msgstr "E61: %s* imbriqu้s" -#: ../regexp.c:1690 #, c-format msgid "E62: Nested %s%c" msgstr "E62: %s%c imbriqu้s" -#: ../regexp.c:1800 msgid "E63: invalid use of \\_" msgstr "E63: utilisation invalide de \\_" -#: ../regexp.c:1850 #, c-format msgid "E64: %s%c follows nothing" msgstr "E64: %s%c ne suit aucun atome" -#: ../regexp.c:1902 msgid "E65: Illegal back reference" msgstr "E65: post-r้f้rence invalide" -#: ../regexp.c:1943 msgid "E68: Invalid character after \\z" msgstr "E68: Caract่re invalide apr่s \\z" -#: ../regexp.c:2049 ../regexp_nfa.c:1296 #, c-format msgid "E678: Invalid character after %s%%[dxouU]" msgstr "E678: Caract่re invalide apr่s %s%%[dxouU]" -#: ../regexp.c:2107 #, c-format msgid "E71: Invalid character after %s%%" msgstr "E71: Caract่re invalide apr่s %s%%" -#: ../regexp.c:3017 #, c-format msgid "E554: Syntax error in %s{...}" msgstr "E554: Erreur de syntaxe dans %s{...}" -#: ../regexp.c:3805 msgid "External submatches:\n" msgstr "Sous-correspondances externes :\n" -#: ../regexp.c:7022 +#, c-format +msgid "E888: (NFA regexp) cannot repeat %s" +msgstr "E888: (regexp NFA) %s ne peut pas ๊tre r้p้t้" + msgid "" "E864: \\%#= can only be followed by 0, 1, or 2. The automatic engine will be " "used " @@ -5213,63 +5062,56 @@ msgstr "" "E864: \\%#= peut ๊tre suivi uniquement de 0, 1 ou 2. Le moteur automatique " "sera utilis้ " -#: ../regexp_nfa.c:239 +msgid "Switching to backtracking RE engine for pattern: " +msgstr "Moteur RE avec backtracking utilis้ pour le motif : " + msgid "E865: (NFA) Regexp end encountered prematurely" msgstr "E865: (NFA) Fin de regexp rencontr้e pr้matur้ment" -#: ../regexp_nfa.c:240 #, c-format msgid "E866: (NFA regexp) Misplaced %c" msgstr "E866: (regexp NFA) %c au mauvais endroit" -#: ../regexp_nfa.c:242 -#, fuzzy, c-format -msgid "E877: (NFA regexp) Invalid character class: %<PRId64>" -msgstr "E877: (regexp NFA) Classe de caract่re invalide " +#, c-format +msgid "E877: (NFA regexp) Invalid character class: %ld" +msgstr "E877: (regexp NFA) Classe de caract่re invalide : %ld" -#: ../regexp_nfa.c:1261 #, c-format msgid "E867: (NFA) Unknown operator '\\z%c'" msgstr "E867: (NFA) Op้rateur inconnu '\\z%c'" -#: ../regexp_nfa.c:1387 -#, fuzzy, c-format +#, c-format msgid "E867: (NFA) Unknown operator '\\%%%c'" -msgstr "E867: (NFA) Op้rateur inconnu '\\z%c'" +msgstr "E867: (NFA) Op้rateur inconnu '\\%%%c'" + +#. should never happen +msgid "E868: Error building NFA with equivalence class!" +msgstr "E868: Erreur lors de la construction du NFA avec classe d'้quivalence" -#: ../regexp_nfa.c:1802 #, c-format msgid "E869: (NFA) Unknown operator '\\@%c'" msgstr "E869: (NFA) Op้rateur inconnu '\\@%c'" -#: ../regexp_nfa.c:1831 msgid "E870: (NFA regexp) Error reading repetition limits" msgstr "E870: (regexp NFA) Erreur เ la lecture des limites de r้p้tition" #. Can't have a multi follow a multi. -#: ../regexp_nfa.c:1895 msgid "E871: (NFA regexp) Can't have a multi follow a multi !" msgstr "E871: (regexp NFA) Un multi ne peut pas suivre un multi !" #. Too many `(' -#: ../regexp_nfa.c:2037 msgid "E872: (NFA regexp) Too many '('" msgstr "E872: (regexp NFA) Trop de '('" -#: ../regexp_nfa.c:2042 -#, fuzzy msgid "E879: (NFA regexp) Too many \\z(" -msgstr "E872: (regexp NFA) Trop de '('" +msgstr "E879: (regexp NFA) Trop de \\z(" -#: ../regexp_nfa.c:2066 msgid "E873: (NFA regexp) proper termination error" msgstr "E873: (NFA regexp) erreur de terminaison" -#: ../regexp_nfa.c:2599 msgid "E874: (NFA) Could not pop the stack !" msgstr "E874: (NFA) Impossible de d้piler !" -#: ../regexp_nfa.c:3298 msgid "" "E875: (NFA regexp) (While converting from postfix to NFA), too many states " "left on stack" @@ -5277,178 +5119,138 @@ msgstr "" "E875: (regexp NFA) (lors de la conversion de postfix เ NFA), il reste trop " "d'้tats sur la pile" -#: ../regexp_nfa.c:3302 msgid "E876: (NFA regexp) Not enough space to store the whole NFA " msgstr "E876: (regexp NFA) Pas assez de m้moire pour stocker le NFA" -#: ../regexp_nfa.c:4571 ../regexp_nfa.c:4869 +msgid "E878: (NFA) Could not allocate memory for branch traversal!" +msgstr "" +"E878: (NFA) Impossible d'allouer la m้moire pour parcourir les branches !" + msgid "" "Could not open temporary log file for writing, displaying on stderr ... " msgstr "" "Impossible d'ouvrir le fichier de log temporaire en ้criture, affichage sur " "stderr ... " -#: ../regexp_nfa.c:4840 #, c-format msgid "(NFA) COULD NOT OPEN %s !" msgstr "(NFA) IMPOSSIBLE D'OUVRIR %s !" -#: ../regexp_nfa.c:6049 msgid "Could not open temporary log file for writing " msgstr "Impossible d'ouvrir le fichier de log en ้criture" -#: ../screen.c:7435 msgid " VREPLACE" msgstr " VREMPLACEMENT" -#: ../screen.c:7437 msgid " REPLACE" msgstr " REMPLACEMENT" # DB - todo -#: ../screen.c:7440 msgid " REVERSE" msgstr " REVERSE" -#: ../screen.c:7441 msgid " INSERT" msgstr " INSERTION" -#: ../screen.c:7443 msgid " (insert)" msgstr " (insertion)" -#: ../screen.c:7445 msgid " (replace)" msgstr " (remplacement)" -#: ../screen.c:7447 msgid " (vreplace)" msgstr " (vremplacement)" -#: ../screen.c:7449 msgid " Hebrew" msgstr " h้breu" -#: ../screen.c:7454 msgid " Arabic" msgstr " arabe" -#: ../screen.c:7456 -msgid " (lang)" -msgstr " (langue)" - -#: ../screen.c:7459 msgid " (paste)" msgstr " (collage)" -#: ../screen.c:7469 msgid " VISUAL" msgstr " VISUEL" -#: ../screen.c:7470 msgid " VISUAL LINE" msgstr " VISUEL LIGNE" -#: ../screen.c:7471 msgid " VISUAL BLOCK" msgstr " VISUEL BLOC" -#: ../screen.c:7472 msgid " SELECT" msgstr " SษLECTION" -#: ../screen.c:7473 msgid " SELECT LINE" msgstr " SษLECTION LIGNE" -#: ../screen.c:7474 msgid " SELECT BLOCK" msgstr " SษLECTION BLOC" -#: ../screen.c:7486 ../screen.c:7541 msgid "recording" msgstr "Enregistrement" -#: ../search.c:487 #, c-format msgid "E383: Invalid search string: %s" msgstr "E383: Cha๎ne de recherche invalide : %s" -#: ../search.c:832 #, c-format msgid "E384: search hit TOP without match for: %s" msgstr "E384: la recherche a atteint le HAUT sans trouver : %s" -#: ../search.c:835 #, c-format msgid "E385: search hit BOTTOM without match for: %s" msgstr "E385: la recherche a atteint le BAS sans trouver : %s" -#: ../search.c:1200 msgid "E386: Expected '?' or '/' after ';'" msgstr "E386: '?' ou '/' attendu apr่s ';'" -#: ../search.c:4085 msgid " (includes previously listed match)" msgstr " (inclut des correspondances list้es pr้c้demment)" #. cursor at status line -#: ../search.c:4104 msgid "--- Included files " msgstr "--- Fichiers inclus " -#: ../search.c:4106 msgid "not found " msgstr "introuvables " -#: ../search.c:4107 msgid "in path ---\n" msgstr "dans le chemin ---\n" -#: ../search.c:4168 msgid " (Already listed)" msgstr " (D้jเ list้)" -#: ../search.c:4170 msgid " NOT FOUND" msgstr " INTROUVABLE" -#: ../search.c:4211 #, c-format msgid "Scanning included file: %s" msgstr "Examen des fichiers inclus : %s" -#: ../search.c:4216 #, c-format msgid "Searching included file %s" msgstr "Recherche du fichier inclus %s" -#: ../search.c:4405 msgid "E387: Match is on current line" msgstr "E387: La correspondance est sur la ligne courante" -#: ../search.c:4517 msgid "All included files were found" msgstr "Tous les fichiers inclus ont ้t้ trouv้s" -#: ../search.c:4519 msgid "No included files" msgstr "Aucun fichier inclus" -#: ../search.c:4527 msgid "E388: Couldn't find definition" msgstr "E388: Impossible de trouver la d้finition" -#: ../search.c:4529 msgid "E389: Couldn't find pattern" msgstr "E389: Impossible de trouver le motif" -#: ../search.c:4668 msgid "Substitute " msgstr "Substitue " -#: ../search.c:4681 #, c-format msgid "" "\n" @@ -5459,97 +5261,129 @@ msgstr "" "# Dernier motif de recherche %s :\n" "~" -#: ../spell.c:951 -msgid "E759: Format error in spell file" -msgstr "E759: Erreur de format du fichier orthographique" +msgid "E756: Spell checking is not enabled" +msgstr "E756: La v้rification orthographique n'est pas activ้e" + +#, c-format +msgid "Warning: Cannot find word list \"%s_%s.spl\" or \"%s_ascii.spl\"" +msgstr "Alerte : Liste de mots \"%s_%s.spl\" ou \"%s_ascii.spl\" introuvable" + +#, c-format +msgid "Warning: Cannot find word list \"%s.%s.spl\" or \"%s.ascii.spl\"" +msgstr "Alerte : Liste de mots \"%s.%s.spl\" ou \"%s.ascii.spl\" introuvable" + +msgid "E797: SpellFileMissing autocommand deleted buffer" +msgstr "E797: L'autocommande SpellFileMissing a effac้ le tampon" + +#, c-format +msgid "Warning: region %s not supported" +msgstr "Alerte : r้gion %s non support้e" + +msgid "Sorry, no suggestions" +msgstr "D้sol้, aucune suggestion" + +#, c-format +msgid "Sorry, only %ld suggestions" +msgstr "D้sol้, seulement %ld suggestions" + +#. for when 'cmdheight' > 1 +#. avoid more prompt +#, c-format +msgid "Change \"%.*s\" to:" +msgstr "Remplacer \"%.*s\" par :" + +# DB - todo : l'int้r๊t de traduire ce message m'้chappe. +#, c-format +msgid " < \"%.*s\"" +msgstr " < \"%.*s\"" + +msgid "E752: No previous spell replacement" +msgstr "E752: Pas de suggestion orthographique pr้c้dente" + +#, c-format +msgid "E753: Not found: %s" +msgstr "E753: Introuvable : %s" -#: ../spell.c:952 msgid "E758: Truncated spell file" msgstr "E758: Fichier orthographique tronqu้" -#: ../spell.c:953 #, c-format msgid "Trailing text in %s line %d: %s" msgstr "Texte en trop dans %s ligne %d : %s" -#: ../spell.c:954 #, c-format msgid "Affix name too long in %s line %d: %s" msgstr "Nom d'affixe trop long dans %s ligne %d : %s" -#: ../spell.c:955 msgid "E761: Format error in affix file FOL, LOW or UPP" msgstr "E761: Erreur de format dans le fichier d'affixe FOL, LOW et UPP" -#: ../spell.c:957 msgid "E762: Character in FOL, LOW or UPP is out of range" msgstr "E762: Un caract่re dans FOL, LOW ou UPP est hors-limites" -#: ../spell.c:958 msgid "Compressing word tree..." msgstr "Compression de l'arbre des mots" -#: ../spell.c:1951 -msgid "E756: Spell checking is not enabled" -msgstr "E756: La v้rification orthographique n'est pas activ้e" - -#: ../spell.c:2249 -#, c-format -msgid "Warning: Cannot find word list \"%s.%s.spl\" or \"%s.ascii.spl\"" -msgstr "Alerte : Liste de mots \"%s.%s.spl\" ou \"%s.ascii.spl\" introuvable" - -#: ../spell.c:2473 #, c-format msgid "Reading spell file \"%s\"" msgstr "Lecture du fichier orthographique \"%s\"" -#: ../spell.c:2496 msgid "E757: This does not look like a spell file" msgstr "E757: Le fichier ne ressemble pas เ un fichier orthographique" -#: ../spell.c:2501 msgid "E771: Old spell file, needs to be updated" msgstr "E771: Fichier orthographique obsol่te, sa mise เ jour est n้cessaire" -#: ../spell.c:2504 msgid "E772: Spell file is for newer version of Vim" msgstr "E772: Le fichier est pr้vu pour une version de Vim plus r้cente" -#: ../spell.c:2602 msgid "E770: Unsupported section in spell file" msgstr "E770: Section non support้e dans le fichier orthographique" -#: ../spell.c:3762 #, c-format -msgid "Warning: region %s not supported" -msgstr "Alerte : r้gion %s non support้e" +msgid "E778: This does not look like a .sug file: %s" +msgstr "E778: %s ne semble pas ๊tre un fichier .sug" + +#, c-format +msgid "E779: Old .sug file, needs to be updated: %s" +msgstr "E779: Fichier de suggestions obsol่te, mise เ jour n้cessaire : %s" + +#, c-format +msgid "E780: .sug file is for newer version of Vim: %s" +msgstr "E780: Fichier .sug pr้vu pour une version de Vim plus r้cente : %s" + +#, c-format +msgid "E781: .sug file doesn't match .spl file: %s" +msgstr "E781: Le fichier .sug ne correspond pas au fichier .spl : %s" + +#, c-format +msgid "E782: error while reading .sug file: %s" +msgstr "E782: Erreur lors de la lecture de fichier de suggestions : %s" -#: ../spell.c:4550 #, c-format msgid "Reading affix file %s ..." msgstr "Lecture du fichier d'affixes %s..." -#: ../spell.c:4589 ../spell.c:5635 ../spell.c:6140 #, c-format msgid "Conversion failure for word in %s line %d: %s" msgstr "ษchec de conversion du mot dans %s ligne %d : %s" -#: ../spell.c:4630 ../spell.c:6170 #, c-format msgid "Conversion in %s not supported: from %s to %s" msgstr "La conversion dans %s non support้e : de %s vers %s" -#: ../spell.c:4642 +#, c-format +msgid "Conversion in %s not supported" +msgstr "La conversion dans %s non support้e" + #, c-format msgid "Invalid value for FLAG in %s line %d: %s" msgstr "Valeur de FLAG invalide dans %s ligne %d : %s" -#: ../spell.c:4655 #, c-format msgid "FLAG after using flags in %s line %d: %s" msgstr "FLAG trouv้ apr่s des drapeaux dans %s ligne %d : %s" -#: ../spell.c:4723 #, c-format msgid "" "Defining COMPOUNDFORBIDFLAG after PFX item may give wrong results in %s line " @@ -5558,7 +5392,6 @@ msgstr "" "D้finir COMPOUNDFORBIDFLAG apr่s des PFX peut donner des r้sultats erron้s " "dans %s ligne %d" -#: ../spell.c:4731 #, c-format msgid "" "Defining COMPOUNDPERMITFLAG after PFX item may give wrong results in %s line " @@ -5567,45 +5400,37 @@ msgstr "" "D้finir COMPOUNDPERMITFLAG apr่s des PFX peut donner des r้sultats erron้s " "dans %s ligne %d" -#: ../spell.c:4747 #, c-format msgid "Wrong COMPOUNDRULES value in %s line %d: %s" msgstr "Valeur de COMPOUNDRULES erron้e dans %s ligne %d : %s" -#: ../spell.c:4771 #, c-format msgid "Wrong COMPOUNDWORDMAX value in %s line %d: %s" msgstr "Valeur de COMPOUNDWORDMAX erron้e dans %s ligne %d : %s" -#: ../spell.c:4777 #, c-format msgid "Wrong COMPOUNDMIN value in %s line %d: %s" msgstr "Valeur de COMPOUNDMIN erron้e dans %s ligne %d : %s" -#: ../spell.c:4783 #, c-format msgid "Wrong COMPOUNDSYLMAX value in %s line %d: %s" msgstr "Valeur de COMPOUNDSYLMAX erron้e dans %s ligne %d : %s" -#: ../spell.c:4795 #, c-format msgid "Wrong CHECKCOMPOUNDPATTERN value in %s line %d: %s" msgstr "Valeur de CHECKCOMPOUNDPATTERN erron้e dans %s ligne %d : %s" # DB - TODO -#: ../spell.c:4847 #, c-format msgid "Different combining flag in continued affix block in %s line %d: %s" msgstr "" "Drapeaux de composition diff้rents dans un bloc d'affixes continu dans %s " "ligne %d : %s" -#: ../spell.c:4850 #, c-format msgid "Duplicate affix in %s line %d: %s" msgstr "Affixe dupliqu้ dans %s ligne %d : %s" -#: ../spell.c:4871 #, c-format msgid "" "Affix also used for BAD/RARE/KEEPCASE/NEEDAFFIX/NEEDCOMPOUND/NOSUGGEST in %s " @@ -5614,339 +5439,233 @@ msgstr "" "Affixe aussi utilis้e pour BAD/RARE/KEEPCASE/NEEDAFFIX/NEEDCOMPOUND/" "NOSUGGEST dans %s ligne %d : %s" -#: ../spell.c:4893 #, c-format msgid "Expected Y or N in %s line %d: %s" msgstr "Y ou N attendu dans %s ligne %d : %s" # DB - todo (regexp impossible เ compiler...) -#: ../spell.c:4968 #, c-format msgid "Broken condition in %s line %d: %s" msgstr "Condition non valide dans %s ligne %d : %s" -#: ../spell.c:5091 #, c-format msgid "Expected REP(SAL) count in %s line %d" msgstr "Nombre de REP(SAL) attendu dans %s ligne %d" -#: ../spell.c:5120 #, c-format msgid "Expected MAP count in %s line %d" msgstr "Nombre de MAP attendu dans %s ligne %d" -#: ../spell.c:5132 #, c-format msgid "Duplicate character in MAP in %s line %d" msgstr "Caract่re dupliqu้ dans MAP dans %s ligne %d" -#: ../spell.c:5176 #, c-format msgid "Unrecognized or duplicate item in %s line %d: %s" msgstr "ษl้ment non reconnu ou dupliqu้ dans %s ligne %d : %s" -#: ../spell.c:5197 #, c-format msgid "Missing FOL/LOW/UPP line in %s" msgstr "Ligne FOL/LOW/UPP manquante dans %s" -#: ../spell.c:5220 msgid "COMPOUNDSYLMAX used without SYLLABLE" msgstr "Utilisation de COMPOUNDSYLMAX sans SYLLABLE" -#: ../spell.c:5236 msgid "Too many postponed prefixes" msgstr "Trop de pr้fixes report้s (PFXPOSTPONE)" -#: ../spell.c:5238 msgid "Too many compound flags" msgstr "Trop de drapeaux de composition" -#: ../spell.c:5240 msgid "Too many postponed prefixes and/or compound flags" msgstr "Trop de pr้fixes report้s et/ou de drapeaux de composition" -#: ../spell.c:5250 #, c-format msgid "Missing SOFO%s line in %s" msgstr "Ligne SOFO%s manquante dans %s" -#: ../spell.c:5253 #, c-format msgid "Both SAL and SOFO lines in %s" msgstr "Lignes SAL et lignes SOFO pr้sentes dans %s" -#: ../spell.c:5331 #, c-format msgid "Flag is not a number in %s line %d: %s" msgstr "Le drapeau n'est pas un nombre dans %s ligne %d : %s" -#: ../spell.c:5334 #, c-format msgid "Illegal flag in %s line %d: %s" msgstr "Drapeau non autoris้ dans %s ligne %d : %s" -#: ../spell.c:5493 ../spell.c:5501 #, c-format msgid "%s value differs from what is used in another .aff file" msgstr "La valeur de %s est diff้rente de celle d'un autre fichier .aff" -#: ../spell.c:5602 #, c-format msgid "Reading dictionary file %s ..." msgstr "Lecture du fichier orthographique %s..." -#: ../spell.c:5611 #, c-format msgid "E760: No word count in %s" msgstr "E760: Nombre de mots non indiqu้ dans %s" -#: ../spell.c:5669 #, c-format msgid "line %6d, word %6d - %s" msgstr "ligne %6d, mot %6d - %s" -#: ../spell.c:5691 #, c-format msgid "Duplicate word in %s line %d: %s" msgstr "Mot dupliqu้ dans %s ligne %d : %s" -#: ../spell.c:5694 #, c-format msgid "First duplicate word in %s line %d: %s" msgstr "Premier mot dupliqu้ dans %s ligne %d : %s" -#: ../spell.c:5746 #, c-format msgid "%d duplicate word(s) in %s" msgstr "%d mot(s) dupliqu้(s) dans %s" -#: ../spell.c:5748 #, c-format msgid "Ignored %d word(s) with non-ASCII characters in %s" msgstr "%d mot(s) ignor้(s) avec des caract่res non-ASCII dans %s" -#: ../spell.c:6115 #, c-format msgid "Reading word file %s ..." msgstr "Lecture de la liste de mots %s..." -#: ../spell.c:6155 #, c-format msgid "Duplicate /encoding= line ignored in %s line %d: %s" msgstr "Ligne /encoding= en double ignor้e dans %s ligne %d : %s" -#: ../spell.c:6159 #, c-format msgid "/encoding= line after word ignored in %s line %d: %s" msgstr "Ligne /encoding= apr่s des mots ignor้e dans %s ligne %d : %s" -#: ../spell.c:6180 #, c-format msgid "Duplicate /regions= line ignored in %s line %d: %s" msgstr "Ligne /regions= en double ignor้e dans %s ligne %d : %s" -#: ../spell.c:6185 #, c-format msgid "Too many regions in %s line %d: %s" msgstr "Trop de r้gions dans %s ligne %d : %s" -#: ../spell.c:6198 #, c-format msgid "/ line ignored in %s line %d: %s" msgstr "Ligne / ignor้e dans %s ligne %d : %s" -#: ../spell.c:6224 #, c-format msgid "Invalid region nr in %s line %d: %s" msgstr "Num้ro de r้gion invalide dans %s ligne %d : %s" -#: ../spell.c:6230 #, c-format msgid "Unrecognized flags in %s line %d: %s" msgstr "Drapeaux non reconnus dans %s ligne %d : %s" -#: ../spell.c:6257 #, c-format msgid "Ignored %d words with non-ASCII characters" msgstr "%d mot(s) ignor้(s) avec des caract่res non-ASCII" -#: ../spell.c:6656 +msgid "E845: Insufficient memory, word list will be incomplete" +msgstr "E845: m้moire insuffisante, liste de mots peut-๊tre incompl่te" + #, c-format msgid "Compressed %d of %d nodes; %d (%d%%) remaining" msgstr "%d noeuds compress้s sur %d ; %d (%d%%) restants " -#: ../spell.c:7340 msgid "Reading back spell file..." msgstr "Relecture du fichier orthographique" -#. Go through the trie of good words, soundfold each word and add it to -#. the soundfold trie. -#: ../spell.c:7357 +#. +#. * Go through the trie of good words, soundfold each word and add it to +#. * the soundfold trie. +#. msgid "Performing soundfolding..." msgstr "Analyse phon้tique en cours..." -#: ../spell.c:7368 #, c-format -msgid "Number of words after soundfolding: %<PRId64>" -msgstr "Nombre de mots apr่s l'analyse phon้tique : %<PRId64>" +msgid "Number of words after soundfolding: %ld" +msgstr "Nombre de mots apr่s l'analyse phon้tique : %ld" -#: ../spell.c:7476 #, c-format msgid "Total number of words: %d" msgstr "Nombre total de mots : %d" -#: ../spell.c:7655 #, c-format msgid "Writing suggestion file %s ..." msgstr "ษcriture du fichier de suggestions %s..." -#: ../spell.c:7707 ../spell.c:7927 #, c-format msgid "Estimated runtime memory use: %d bytes" msgstr "Estimation de m้moire consomm้e : %d octets" -#: ../spell.c:7820 msgid "E751: Output file name must not have region name" msgstr "E751: Le nom du fichier ne doit pas contenir de nom de r้gion" -#: ../spell.c:7822 msgid "E754: Only up to 8 regions supported" msgstr "E754: 8 r้gions au maximum sont support้es" -#: ../spell.c:7846 #, c-format msgid "E755: Invalid region in %s" msgstr "E755: R้gion invalide dans %s" -#: ../spell.c:7907 msgid "Warning: both compounding and NOBREAK specified" msgstr "Alerte : la composition et NOBREAK sont tous les deux sp้cifi้s" -#: ../spell.c:7920 #, c-format msgid "Writing spell file %s ..." msgstr "ษcriture du fichier orthographique %s..." -#: ../spell.c:7925 msgid "Done!" msgstr "Termin้ !" # DB - todo : perfectible. -#: ../spell.c:8034 #, c-format -msgid "E765: 'spellfile' does not have %<PRId64> entries" -msgstr "E765: 'spellfile' n'a pas %<PRId64> entr้es" +msgid "E765: 'spellfile' does not have %ld entries" +msgstr "E765: 'spellfile' n'a pas %ld entr้es" -#: ../spell.c:8074 -#, fuzzy, c-format +#, c-format msgid "Word '%.*s' removed from %s" -msgstr "Mot retir้ de %s" +msgstr "Mot '%.*s' retir้ de %s" -#: ../spell.c:8117 -#, fuzzy, c-format +#, c-format msgid "Word '%.*s' added to %s" -msgstr "Mot ajout้ dans %s" +msgstr "Mot '%.*s' ajout้ dans %s" -#: ../spell.c:8381 msgid "E763: Word characters differ between spell files" msgstr "" "E763: Les caract่res de mots diff่rent entre les fichiers orthographiques" -#: ../spell.c:8684 -msgid "Sorry, no suggestions" -msgstr "D้sol้, aucune suggestion" - -#: ../spell.c:8687 -#, c-format -msgid "Sorry, only %<PRId64> suggestions" -msgstr "D้sol้, seulement %<PRId64> suggestions" - -#. for when 'cmdheight' > 1 -#. avoid more prompt -#: ../spell.c:8704 -#, c-format -msgid "Change \"%.*s\" to:" -msgstr "Remplacer \"%.*s\" par :" - -# DB - todo : l'int้r๊t de traduire ce message m'้chappe. -#: ../spell.c:8737 -#, c-format -msgid " < \"%.*s\"" -msgstr " < \"%.*s\"" - -#: ../spell.c:8882 -msgid "E752: No previous spell replacement" -msgstr "E752: Pas de suggestion orthographique pr้c้dente" - -#: ../spell.c:8925 -#, c-format -msgid "E753: Not found: %s" -msgstr "E753: Introuvable : %s" - -#: ../spell.c:9276 -#, c-format -msgid "E778: This does not look like a .sug file: %s" -msgstr "E778: %s ne semble pas ๊tre un fichier .sug" - -#: ../spell.c:9282 -#, c-format -msgid "E779: Old .sug file, needs to be updated: %s" -msgstr "E779: Fichier de suggestions obsol่te, mise เ jour n้cessaire : %s" - -#: ../spell.c:9286 -#, c-format -msgid "E780: .sug file is for newer version of Vim: %s" -msgstr "E780: Fichier .sug pr้vu pour une version de Vim plus r้cente : %s" - -#: ../spell.c:9295 -#, c-format -msgid "E781: .sug file doesn't match .spl file: %s" -msgstr "E781: Le fichier .sug ne correspond pas au fichier .spl : %s" - -#: ../spell.c:9305 -#, c-format -msgid "E782: error while reading .sug file: %s" -msgstr "E782: Erreur lors de la lecture de fichier de suggestions : %s" - #. This should have been checked when generating the .spl -#. file. -#: ../spell.c:11575 +#. * file. msgid "E783: duplicate char in MAP entry" -msgstr "E783: caract่res dupliqu้ dans l'entr้e MAP" +msgstr "E783: caract่re dupliqu้ dans l'entr้e MAP" -#: ../syntax.c:266 msgid "No Syntax items defined for this buffer" msgstr "Aucun ้l้ment de syntaxe d้fini pour ce tampon" -#: ../syntax.c:3083 ../syntax.c:3104 ../syntax.c:3127 #, c-format msgid "E390: Illegal argument: %s" msgstr "E390: Argument invalide : %s" -#: ../syntax.c:3299 +msgid "syntax iskeyword " +msgstr "syntaxe iskeyword " + #, c-format msgid "E391: No such syntax cluster: %s" msgstr "E391: Aucune grappe de syntaxe %s" -#: ../syntax.c:3433 msgid "syncing on C-style comments" msgstr "synchronisation sur les commentaires de type C" -#: ../syntax.c:3439 msgid "no syncing" msgstr "Aucune synchronisation" # DB - Les deux messages qui suivent vont ensemble. -#: ../syntax.c:3441 msgid "syncing starts " msgstr "La synchronisation d้bute " -#: ../syntax.c:3443 ../syntax.c:3506 msgid " lines before top line" msgstr " lignes avant la ligne du haut" -#: ../syntax.c:3448 msgid "" "\n" "--- Syntax sync items ---" @@ -5954,7 +5673,6 @@ msgstr "" "\n" "--- ษl้ments de synchronisation syntaxique ---" -#: ../syntax.c:3452 msgid "" "\n" "syncing on items" @@ -5962,7 +5680,6 @@ msgstr "" "\n" "synchronisation sur ้l้ments" -#: ../syntax.c:3457 msgid "" "\n" "--- Syntax items ---" @@ -5970,275 +5687,220 @@ msgstr "" "\n" "--- ษl้ments de syntaxe ---" -#: ../syntax.c:3475 #, c-format msgid "E392: No such syntax cluster: %s" msgstr "E392: Aucune grappe de syntaxe %s" -#: ../syntax.c:3497 msgid "minimal " msgstr "minimum " -#: ../syntax.c:3503 msgid "maximal " msgstr "maximum " # DB - todo -#: ../syntax.c:3513 msgid "; match " msgstr "; correspond avec " # DB - todo -#: ../syntax.c:3515 msgid " line breaks" msgstr " coupures de ligne" -#: ../syntax.c:4076 msgid "E395: contains argument not accepted here" msgstr "E395: L'argument ซ contains ป n'est pas accept้ ici" -#: ../syntax.c:4096 msgid "E844: invalid cchar value" msgstr "E844: valeur de cchar invalide" -#: ../syntax.c:4107 msgid "E393: group[t]here not accepted here" msgstr "E393: L'argument ซ group[t]here ป n'est pas accept้ ici" -#: ../syntax.c:4126 #, c-format msgid "E394: Didn't find region item for %s" msgstr "E394: Aucun ้l้ment de type r้gion trouv้ pour %s" -#: ../syntax.c:4188 msgid "E397: Filename required" msgstr "E397: Nom de fichier requis" -#: ../syntax.c:4221 msgid "E847: Too many syntax includes" msgstr "E847: Trop d'inclusions de syntaxe" -#: ../syntax.c:4303 #, c-format msgid "E789: Missing ']': %s" msgstr "E789: ']' manquant : %s" -#: ../syntax.c:4531 +#, c-format +msgid "E890: trailing char after ']': %s]%s" +msgstr "E890: Caract่re surnum้raire apr่s ']': %s]%s" + #, c-format msgid "E398: Missing '=': %s" msgstr "E398: '=' manquant : %s" -#: ../syntax.c:4666 #, c-format msgid "E399: Not enough arguments: syntax region %s" msgstr "E399: Pas assez d'arguments : syntax region %s" -#: ../syntax.c:4870 msgid "E848: Too many syntax clusters" msgstr "E848: Trop de grappes de syntaxe" -#: ../syntax.c:4954 msgid "E400: No cluster specified" msgstr "E400: Aucune grappe sp้cifi้e" -#. end delimiter not found -#: ../syntax.c:4986 #, c-format msgid "E401: Pattern delimiter not found: %s" msgstr "E401: D้limiteur de motif introuvable : %s" -#: ../syntax.c:5049 #, c-format msgid "E402: Garbage after pattern: %s" msgstr "E402: caract่res en trop apr่s le motif : %s" -#: ../syntax.c:5120 msgid "E403: syntax sync: line continuations pattern specified twice" msgstr "" "E403: synchro syntax : motif de continuation de ligne pr้sent deux fois" -#: ../syntax.c:5169 #, c-format msgid "E404: Illegal arguments: %s" msgstr "E404: Arguments invalides : %s" -#: ../syntax.c:5217 #, c-format msgid "E405: Missing equal sign: %s" msgstr "E405: '=' manquant : %s" -#: ../syntax.c:5222 #, c-format msgid "E406: Empty argument: %s" msgstr "E406: Argument vide : %s" -#: ../syntax.c:5240 #, c-format msgid "E407: %s not allowed here" msgstr "E407: %s n'est pas autoris้ ici" -#: ../syntax.c:5246 #, c-format msgid "E408: %s must be first in contains list" msgstr "E408: %s doit ๊tre le premier ้l้ment d'une liste ซ contains ป" -#: ../syntax.c:5304 #, c-format msgid "E409: Unknown group name: %s" msgstr "E409: Nom de groupe inconnu : %s" -#: ../syntax.c:5512 #, c-format msgid "E410: Invalid :syntax subcommand: %s" msgstr "E410: Sous-commande de :syntax invalide : %s" -#: ../syntax.c:5854 msgid "" " TOTAL COUNT MATCH SLOWEST AVERAGE NAME PATTERN" msgstr "" +" TOTAL NOMBRE MATCH PLUS LENT MOYEN NOM MOTIF" -#: ../syntax.c:6146 msgid "E679: recursive loop loading syncolor.vim" msgstr "E679: boucle r้cursive lors du chargement de syncolor.vim" -#: ../syntax.c:6256 #, c-format msgid "E411: highlight group not found: %s" msgstr "E411: groupe de surbrillance introuvable : %s" -#: ../syntax.c:6278 #, c-format msgid "E412: Not enough arguments: \":highlight link %s\"" msgstr "E412: Trop peu d'arguments : \":highlight link %s\"" -#: ../syntax.c:6284 #, c-format msgid "E413: Too many arguments: \":highlight link %s\"" msgstr "E413: Trop d'arguments : \":highlight link %s\"" -#: ../syntax.c:6302 msgid "E414: group has settings, highlight link ignored" msgstr "E414: le groupe a d้jเ des attributs, lien de surbrillance ignor้" -#: ../syntax.c:6367 #, c-format msgid "E415: unexpected equal sign: %s" msgstr "E415: signe ้gal inattendu : %s" -#: ../syntax.c:6395 #, c-format msgid "E416: missing equal sign: %s" msgstr "E416: '=' manquant : %s" -#: ../syntax.c:6418 #, c-format msgid "E417: missing argument: %s" msgstr "E417: argument manquant : %s" -#: ../syntax.c:6446 #, c-format msgid "E418: Illegal value: %s" msgstr "E418: Valeur invalide : %s" -#: ../syntax.c:6496 msgid "E419: FG color unknown" msgstr "E419: Couleur de premier plan inconnue" -#: ../syntax.c:6504 msgid "E420: BG color unknown" msgstr "E420: Couleur d'arri่re-plan inconnue" -#: ../syntax.c:6564 #, c-format msgid "E421: Color name or number not recognized: %s" msgstr "E421: Nom ou num้ro de couleur non reconnu : %s" -#: ../syntax.c:6714 #, c-format msgid "E422: terminal code too long: %s" msgstr "E422: le code de terminal est trop long : %s" -#: ../syntax.c:6753 #, c-format msgid "E423: Illegal argument: %s" msgstr "E423: Argument invalide : %s" -#: ../syntax.c:6925 msgid "E424: Too many different highlighting attributes in use" msgstr "" "E424: Trop d'attributs de surbrillance diff้rents en cours d'utilisation" -#: ../syntax.c:7427 msgid "E669: Unprintable character in group name" msgstr "E669: Caract่re non-imprimable dans un nom de groupe" -#: ../syntax.c:7434 msgid "W18: Invalid character in group name" msgstr "W18: Caract่re invalide dans un nom de groupe" -#: ../syntax.c:7448 msgid "E849: Too many highlight and syntax groups" msgstr "E849: Trop de groupes de surbrillance et de syntaxe" -#: ../tag.c:104 msgid "E555: at bottom of tag stack" msgstr "E555: En bas de la pile de marqueurs" -#: ../tag.c:105 msgid "E556: at top of tag stack" msgstr "E556: Au sommet de la pile de marqueurs" -#: ../tag.c:380 msgid "E425: Cannot go before first matching tag" msgstr "E425: Impossible d'aller avant le premier marqueur correspondant" -#: ../tag.c:504 #, c-format msgid "E426: tag not found: %s" msgstr "E426: Marqueur introuvable : %s" -#: ../tag.c:528 msgid " # pri kind tag" msgstr " # pri type marqueur" -#: ../tag.c:531 msgid "file\n" msgstr "fichier\n" -#: ../tag.c:829 msgid "E427: There is only one matching tag" msgstr "E427: Il n'y a qu'un marqueur correspondant" -#: ../tag.c:831 msgid "E428: Cannot go beyond last matching tag" msgstr "E428: Impossible d'aller au-delเ du dernier marqueur correspondant" -#: ../tag.c:850 #, c-format msgid "File \"%s\" does not exist" msgstr "Le fichier \"%s\" n'existe pas" #. Give an indication of the number of matching tags -#: ../tag.c:859 #, c-format msgid "tag %d of %d%s" msgstr "marqueur %d sur %d%s" -#: ../tag.c:862 msgid " or more" msgstr " ou plus" -#: ../tag.c:864 msgid " Using tag with different case!" msgstr " Utilisation d'un marqueur avec une casse diff้rente !" -#: ../tag.c:909 #, c-format msgid "E429: File \"%s\" does not exist" msgstr "E429: Le fichier \"%s\" n'existe pas" #. Highlight title -#: ../tag.c:960 msgid "" "\n" " # TO tag FROM line in file/text" @@ -6246,80 +5908,67 @@ msgstr "" "\n" " # VERS marqueur DE ligne dans le fichier/texte" -#: ../tag.c:1303 #, c-format msgid "Searching tags file %s" msgstr "Examen du fichier de marqueurs %s" -#: ../tag.c:1545 +#, c-format +msgid "E430: Tag file path truncated for %s\n" +msgstr "E430: Chemin de fichiers de marqueurs tronqu้ pour %s\n" + msgid "Ignoring long line in tags file" msgstr "Ignore longue ligne dans le fichier de marqueurs" -#: ../tag.c:1915 #, c-format msgid "E431: Format error in tags file \"%s\"" msgstr "E431: Erreur de format dans le fichier de marqueurs \"%s\"" -#: ../tag.c:1917 #, c-format -msgid "Before byte %<PRId64>" -msgstr "Avant l'octet %<PRId64>" +msgid "Before byte %ld" +msgstr "Avant l'octet %ld" -#: ../tag.c:1929 #, c-format msgid "E432: Tags file not sorted: %s" msgstr "E432: Le fichier de marqueurs %s n'est pas ordonn้" #. never opened any tags file -#: ../tag.c:1960 msgid "E433: No tags file" msgstr "E433: Aucun fichier de marqueurs" -#: ../tag.c:2536 msgid "E434: Can't find tag pattern" msgstr "E434: Le motif de marqueur est introuvable" -#: ../tag.c:2544 msgid "E435: Couldn't find tag, just guessing!" msgstr "E435: Marqueur introuvable, tentative pour deviner !" -#: ../tag.c:2797 #, c-format msgid "Duplicate field name: %s" msgstr "Nom de champ dupliqu้ : %s" -#: ../term.c:1442 msgid "' not known. Available builtin terminals are:" msgstr "' inconnu. Les terminaux int้gr้s sont :" -#: ../term.c:1463 msgid "defaulting to '" msgstr "utilisation par d้faut de '" -#: ../term.c:1731 msgid "E557: Cannot open termcap file" msgstr "E557: Impossible d'ouvrir le fichier termcap" -#: ../term.c:1735 msgid "E558: Terminal entry not found in terminfo" msgstr "E558: La description du terminal est introuvable dans terminfo" -#: ../term.c:1737 msgid "E559: Terminal entry not found in termcap" msgstr "E559: La description du terminal est introuvable dans termcap" -#: ../term.c:1878 #, c-format msgid "E436: No \"%s\" entry in termcap" msgstr "E436: Aucune entr้e \"%s\" dans termcap" # DB - todo : Comment am้liorer ? -#: ../term.c:2249 msgid "E437: terminal capability \"cm\" required" msgstr "E437: capacit้ de terminal \"cm\" requise" #. Highlight title -#: ../term.c:4376 msgid "" "\n" "--- Terminal keys ---" @@ -6327,174 +5976,365 @@ msgstr "" "\n" "--- Touches du terminal ---" -#: ../ui.c:481 +msgid "Cannot open $VIMRUNTIME/rgb.txt" +msgstr "Impossible d'ouvrir $VIMRUNTIME/rgb.txt" + +msgid "new shell started\n" +msgstr "nouveau shell d้marr้\n" + msgid "Vim: Error reading input, exiting...\n" msgstr "Vim : Erreur lors de la lecture de l'entr้e, sortie...\n" +# DB - Message de d้bogage. +msgid "Used CUT_BUFFER0 instead of empty selection" +msgstr "CUT_BUFFER0 utilis้ plut๔t qu'une s้lection vide" + #. This happens when the FileChangedRO autocommand changes the #. * file in a way it becomes shorter. -#: ../undo.c:379 -#, fuzzy msgid "E881: Line count changed unexpectedly" -msgstr "E834: Le nombre de lignes a ้t้ chang้ inopin้ment" +msgstr "E881: Le nombre de lignes a ้t้ chang้ inopin้ment" + +# DB - Question O/N. +#. must display the prompt +msgid "No undo possible; continue anyway" +msgstr "Annulation impossible ; continuer" -#: ../undo.c:627 #, c-format msgid "E828: Cannot open undo file for writing: %s" msgstr "E828: Impossible d'ouvrir le fichier d'annulations en ้criture : %s" -#: ../undo.c:717 #, c-format msgid "E825: Corrupted undo file (%s): %s" msgstr "E825: Fichier d'annulations corrompu (%s) : %s" -#: ../undo.c:1039 msgid "Cannot write undo file in any directory in 'undodir'" msgstr "" "Impossible d'้crire le fichier d'annulations dans n'importe quel r้pertoire " "de 'undodir'" -#: ../undo.c:1074 #, c-format msgid "Will not overwrite with undo file, cannot read: %s" msgstr "Le fichier d'annulations ne sera pas ้cras้, impossible de lire : %s" -#: ../undo.c:1092 #, c-format msgid "Will not overwrite, this is not an undo file: %s" msgstr "Fichier ne sera pas ้cras้, ce n'est pas un fichier d'annulations : %s" -#: ../undo.c:1108 msgid "Skipping undo file write, nothing to undo" msgstr "Le fichier d'annulations n'est pas ้crit, rien เ annuler" -#: ../undo.c:1121 #, c-format msgid "Writing undo file: %s" msgstr "ษcriture du fichier d'annulations : %s" -#: ../undo.c:1213 #, c-format msgid "E829: write error in undo file: %s" msgstr "E829: Erreur d'้criture dans le fichier d'annulations : %s" -#: ../undo.c:1280 #, c-format msgid "Not reading undo file, owner differs: %s" msgstr "Le fichier d'annulations n'est pas lu, propri้taire diff้rent : %s" -#: ../undo.c:1292 #, c-format msgid "Reading undo file: %s" msgstr "Lecture du fichier d'annulations : %s..." -#: ../undo.c:1299 #, c-format msgid "E822: Cannot open undo file for reading: %s" msgstr "E822: Impossible d'ouvrir le fichier d'annulations en lecture : %s" -#: ../undo.c:1308 #, c-format msgid "E823: Not an undo file: %s" msgstr "E823: Ce n'est pas un fichier d'annulations : %s" -#: ../undo.c:1313 +#, c-format +msgid "E832: Non-encrypted file has encrypted undo file: %s" +msgstr "E832: Fichier non-chiffr้ a un fichier d'annulations chiffr้ : %s" + +#, c-format +msgid "E826: Undo file decryption failed: %s" +msgstr "E826: D้chiffrage du fichier d'annulation a ้chou้ : %s" + +#, c-format +msgid "E827: Undo file is encrypted: %s" +msgstr "E827: Le fichier d'annulations est chiffr้ : %s" + #, c-format msgid "E824: Incompatible undo file: %s" msgstr "E824: Fichier d'annulations incompatible : %s" -#: ../undo.c:1328 msgid "File contents changed, cannot use undo info" msgstr "" "Le contenu du fichier a chang้, impossible d'utiliser les informations " "d'annulation" -#: ../undo.c:1497 #, c-format msgid "Finished reading undo file %s" msgstr "Fin de lecture du fichier d'annulations %s" -#: ../undo.c:1586 ../undo.c:1812 msgid "Already at oldest change" msgstr "D้jเ เ la modification la plus ancienne" -#: ../undo.c:1597 ../undo.c:1814 msgid "Already at newest change" msgstr "D้jเ เ la modification la plus r้cente" -#: ../undo.c:1806 #, c-format -msgid "E830: Undo number %<PRId64> not found" -msgstr "E830: Annulation nฐ %<PRId64> introuvable" +msgid "E830: Undo number %ld not found" +msgstr "E830: Annulation nฐ %ld introuvable" -#: ../undo.c:1979 msgid "E438: u_undo: line numbers wrong" msgstr "E438: u_undo : num้ros de ligne erron้s" -#: ../undo.c:2183 msgid "more line" msgstr "ligne en plus" -#: ../undo.c:2185 msgid "more lines" msgstr "lignes en plus" -#: ../undo.c:2187 msgid "line less" msgstr "ligne en moins" -#: ../undo.c:2189 msgid "fewer lines" msgstr "lignes en moins" -#: ../undo.c:2193 msgid "change" msgstr "modification" -#: ../undo.c:2195 msgid "changes" msgstr "modifications" -#: ../undo.c:2225 #, c-format -msgid "%<PRId64> %s; %s #%<PRId64> %s" -msgstr "%<PRId64> %s ; %s #%<PRId64> ; %s" +msgid "%ld %s; %s #%ld %s" +msgstr "%ld %s ; %s #%ld ; %s" -#: ../undo.c:2228 msgid "before" msgstr "avant" -#: ../undo.c:2228 msgid "after" msgstr "apr่s" -#: ../undo.c:2325 msgid "Nothing to undo" msgstr "Rien เ annuler" # DB - Les deux premi่res colonnes sont align้es เ droite. -#: ../undo.c:2330 msgid "number changes when saved" msgstr "num้ro modif. instant enregistr้" -#: ../undo.c:2360 #, c-format -msgid "%<PRId64> seconds ago" -msgstr "il y a %<PRId64> secondes" +msgid "%ld seconds ago" +msgstr "il y a %ld secondes" -#: ../undo.c:2372 msgid "E790: undojoin is not allowed after undo" msgstr "E790: undojoin n'est pas autoris้ apr่s une annulation" -#: ../undo.c:2466 msgid "E439: undo list corrupt" msgstr "E439: la liste d'annulation est corrompue" -#: ../undo.c:2495 msgid "E440: undo line missing" msgstr "E440: ligne d'annulation manquante" -#: ../version.c:600 +#, c-format +msgid "E122: Function %s already exists, add ! to replace it" +msgstr "E122: La fonction %s existe d้jเ (ajoutez ! pour la remplacer)" + +msgid "E717: Dictionary entry already exists" +msgstr "E717: Une entr้e du Dictionnaire porte d้jเ ce nom" + +msgid "E718: Funcref required" +msgstr "E718: R้f้rence de fonction (Funcref) requise" + +#, c-format +msgid "E130: Unknown function: %s" +msgstr "E130: Fonction inconnue : %s" + +#, c-format +msgid "E125: Illegal argument: %s" +msgstr "E125: Argument invalide : %s" + +#, c-format +msgid "E853: Duplicate argument name: %s" +msgstr "E853: Nom d'argument dupliqu้ : %s" + +#, c-format +msgid "E740: Too many arguments for function %s" +msgstr "E740: Trop d'arguments pour la fonction %s" + +#, c-format +msgid "E116: Invalid arguments for function %s" +msgstr "E116: Arguments invalides pour la fonction %s" + +# AB - V้rifier dans la litt้rature technique s'il n'existe pas une meilleure +# traduction pour "function call depth". +msgid "E132: Function call depth is higher than 'maxfuncdepth'" +msgstr "" +"E132: La profondeur d'appel de fonction est sup้rieure เ 'maxfuncdepth'" + +# AB - Ce texte fait partie d'un message de d้bogage. +#, c-format +msgid "calling %s" +msgstr "appel de %s" + +# AB - V้rifier. +#, c-format +msgid "%s aborted" +msgstr "%s annul้e" + +# AB - Ce texte fait partie d'un message de d้bogage. +#, c-format +msgid "%s returning #%ld" +msgstr "%s a retourn้ #%ld" + +# AB - Ce texte fait partie d'un message de d้bogage. +#, c-format +msgid "%s returning %s" +msgstr "%s a retourn้ \"%s\"" + +msgid "E699: Too many arguments" +msgstr "E699: Trop d'arguments" + +#, c-format +msgid "E117: Unknown function: %s" +msgstr "E117: Fonction inconnue : %s" + +#, c-format +msgid "E933: Function was deleted: %s" +msgstr "E933: La fonction a ้t้ effac้e: %s" + +#, c-format +msgid "E119: Not enough arguments for function: %s" +msgstr "E119: La fonction %s n'a pas re็u assez d'arguments" + +#, c-format +msgid "E120: Using <SID> not in a script context: %s" +msgstr "E120: <SID> utilis้ en dehors d'un script : %s" + +#, c-format +msgid "E725: Calling dict function without Dictionary: %s" +msgstr "E725: Appel d'une fonction ซ dict ป sans Dictionnaire : %s" + +msgid "E129: Function name required" +msgstr "E129: Nom de fonction requis" + +#, c-format +msgid "E128: Function name must start with a capital or \"s:\": %s" +msgstr "" +"E128: Le nom de la fonction doit commencer par une majuscule ou \"s:\": %s" + +#, c-format +msgid "E884: Function name cannot contain a colon: %s" +msgstr "" +"E884: Le nom de la fonction ne peut pas contenir le caract่re deux-points : " +"%s" + +#, c-format +msgid "E123: Undefined function: %s" +msgstr "E123: Fonction non d้finie : %s" + +# AB - La version fran็aise est plus consistante que la version anglaise. +# AB - Je suis partag้ entre la concision d'une traduction assez litt้rale et +# la lourdeur d'une traduction plus correcte. +#, c-format +msgid "E124: Missing '(': %s" +msgstr "E124: Il manque '(' apr่s %s" + +msgid "E862: Cannot use g: here" +msgstr "E862: Impossible d'utiliser g: ici" + +#, c-format +msgid "E932: Closure function should not be at top level: %s" +msgstr "" +"E932: une fonction fermeture ne devrait pas ๊tre au niveau principal : %s" + +msgid "E126: Missing :endfunction" +msgstr "E126: Il manque :endfunction" + +#, c-format +msgid "E707: Function name conflicts with variable: %s" +msgstr "E707: Le nom de fonction entre en conflit avec la variable : %s" + +#, c-format +msgid "E127: Cannot redefine function %s: It is in use" +msgstr "E127: Impossible de red้finir fonction %s : d้jเ utilis้e" + +# DB - Le contenu du "c-format" est le nom de la fonction. +#, c-format +msgid "E746: Function name does not match script file name: %s" +msgstr "E746: Le nom de la fonction %s ne correspond pas le nom du script" + +# AB - Il est difficile de cr้er une version fran็aise qui fasse moins de 80 +# caract่res de long, nom de la fonction compris : "It is in use" est une +# expression tr่s dense. Traductions possibles : "elle est utilis้e", +# "elle s'ex้cute" ou "elle est occup้e". +#, c-format +msgid "E131: Cannot delete function %s: It is in use" +msgstr "E131: Impossible d'effacer %s : cette fonction est utilis้e" + +msgid "E133: :return not inside a function" +msgstr "E133: :return en dehors d'une fonction" + +#, c-format +msgid "E107: Missing parentheses: %s" +msgstr "E107: Parenth่ses manquantes : %s" + +msgid "" +"\n" +"MS-Windows 64-bit GUI version" +msgstr "" +"\n" +"Version graphique MS-Windows 64 bits" + +msgid "" +"\n" +"MS-Windows 32-bit GUI version" +msgstr "" +"\n" +"Version graphique MS-Windows 32 bits" + +msgid " with OLE support" +msgstr " supportant l'OLE" + +msgid "" +"\n" +"MS-Windows 64-bit console version" +msgstr "" +"\n" +"Version console MS-Windows 64 bits" + +msgid "" +"\n" +"MS-Windows 32-bit console version" +msgstr "" +"\n" +"Version console MS-Windows 32 bits" + +msgid "" +"\n" +"MacOS X (unix) version" +msgstr "" +"\n" +"Version MaxOS X (unix)" + +msgid "" +"\n" +"MacOS X version" +msgstr "" +"\n" +"Version MacOS X" + +msgid "" +"\n" +"MacOS version" +msgstr "" +"\n" +"Version MacOS" + +msgid "" +"\n" +"OpenVMS version" +msgstr "" +"\n" +"Version OpenVMS" + msgid "" "\n" "Included patches: " @@ -6502,7 +6342,6 @@ msgstr "" "\n" "Rustines incluses : " -#: ../version.c:627 msgid "" "\n" "Extra patches: " @@ -6510,11 +6349,9 @@ msgstr "" "\n" "Rustines extra : " -#: ../version.c:639 ../version.c:864 msgid "Modified by " msgstr "Modifi้ par " -#: ../version.c:646 msgid "" "\n" "Compiled " @@ -6522,11 +6359,9 @@ msgstr "" "\n" "Compil้ " -#: ../version.c:649 msgid "by " msgstr "par " -#: ../version.c:660 msgid "" "\n" "Huge version " @@ -6534,1872 +6369,949 @@ msgstr "" "\n" "ษnorme version " -#: ../version.c:661 +msgid "" +"\n" +"Big version " +msgstr "" +"\n" +"Grosse version " + +msgid "" +"\n" +"Normal version " +msgstr "" +"\n" +"Version normale " + +msgid "" +"\n" +"Small version " +msgstr "" +"\n" +"Petite version " + +msgid "" +"\n" +"Tiny version " +msgstr "" +"\n" +"Version minuscule " + msgid "without GUI." msgstr "sans interface graphique." -#: ../version.c:662 +msgid "with GTK3 GUI." +msgstr "avec interface graphique GTK3." + +msgid "with GTK2-GNOME GUI." +msgstr "avec interface graphique GTK2-GNOME." + +msgid "with GTK2 GUI." +msgstr "avec interface graphique GTK2." + +msgid "with X11-Motif GUI." +msgstr "avec interface graphique X11-Motif." + +msgid "with X11-neXtaw GUI." +msgstr "avec interface graphique X11-neXtaw." + +msgid "with X11-Athena GUI." +msgstr "avec interface graphique X11-Athena." + +msgid "with Photon GUI." +msgstr "avec interface graphique Photon." + +msgid "with GUI." +msgstr "avec une interface graphique." + +msgid "with Carbon GUI." +msgstr "avec interface graphique Carbon." + +msgid "with Cocoa GUI." +msgstr "avec interface graphique Cocoa." + +msgid "with (classic) GUI." +msgstr "avec interface graphique (classic)." + msgid " Features included (+) or not (-):\n" msgstr " Fonctionnalit้s incluses (+) ou non (-) :\n" -#: ../version.c:667 msgid " system vimrc file: \"" msgstr " fichier vimrc syst่me : \"" -#: ../version.c:672 msgid " user vimrc file: \"" msgstr " fichier vimrc utilisateur : \"" -#: ../version.c:677 msgid " 2nd user vimrc file: \"" msgstr " 2me fichier vimrc utilisateur : \"" -#: ../version.c:682 msgid " 3rd user vimrc file: \"" msgstr " 3me fichier vimrc utilisateur : \"" -#: ../version.c:687 msgid " user exrc file: \"" msgstr " fichier exrc utilisateur : \"" -#: ../version.c:692 msgid " 2nd user exrc file: \"" msgstr " 2me fichier exrc utilisateur : \"" -#: ../version.c:699 +msgid " system gvimrc file: \"" +msgstr " fichier gvimrc syst่me : \"" + +msgid " user gvimrc file: \"" +msgstr " fichier gvimrc utilisateur : \"" + +msgid "2nd user gvimrc file: \"" +msgstr "2me fichier gvimrc utilisateur : \"" + +msgid "3rd user gvimrc file: \"" +msgstr "3me fichier gvimrc utilisateur : \"" + +msgid " defaults file: \"" +msgstr " fichier de valeurs par d้faut : \"" + +msgid " system menu file: \"" +msgstr " fichier menu syst่me : \"" + msgid " fall-back for $VIM: \"" msgstr " $VIM par d้faut : \"" -#: ../version.c:705 msgid " f-b for $VIMRUNTIME: \"" msgstr " $VIMRUNTIME par d้faut : \"" -#: ../version.c:709 msgid "Compilation: " msgstr "Compilation : " -#: ../version.c:712 +msgid "Compiler: " +msgstr "Compilateur : " + msgid "Linking: " msgstr "ษdition de liens : " -#: ../version.c:717 msgid " DEBUG BUILD" msgstr " VERSION DE DษBOGAGE" -#: ../version.c:767 msgid "VIM - Vi IMproved" msgstr "VIM - Vi Am้lior้" -#: ../version.c:769 msgid "version " msgstr "version " -#: ../version.c:770 msgid "by Bram Moolenaar et al." msgstr "par Bram Moolenaar et al." -#: ../version.c:774 msgid "Vim is open source and freely distributable" msgstr "Vim est un logiciel libre" -#: ../version.c:776 msgid "Help poor children in Uganda!" msgstr "Aidez les enfants pauvres d'Ouganda !" -#: ../version.c:777 msgid "type :help iccf<Enter> for information " msgstr "tapez :help iccf<Entr้e> pour plus d'informations " -#: ../version.c:779 msgid "type :q<Enter> to exit " msgstr "tapez :q<Entr้e> pour sortir du programme " -#: ../version.c:780 msgid "type :help<Enter> or <F1> for on-line help" msgstr "tapez :help<Entr้e> ou <F1> pour acc้der เ l'aide en ligne " -#: ../version.c:781 -msgid "type :help version7<Enter> for version info" -msgstr "tapez :help version7<Entr้e> pour lire les notes de mise เ jour" +msgid "type :help version8<Enter> for version info" +msgstr "tapez :help version8<Entr้e> pour lire les notes de mise เ jour" # DB - Pour les trois messages qui suivent : # :set cp # :intro -#: ../version.c:784 msgid "Running in Vi compatible mode" msgstr "Compatibilit้ avec Vi activ้e" -#: ../version.c:785 msgid "type :set nocp<Enter> for Vim defaults" msgstr "tapez :set nocp<Entr้e> pour la d้sactiver" -#: ../version.c:786 msgid "type :help cp-default<Enter> for info on this" msgstr "tapez :help cp-default<Entr้e> pour plus d'info" -#: ../version.c:827 +msgid "menu Help->Orphans for information " +msgstr "menu Aide->Orphelins pour plus d'info" + +msgid "Running modeless, typed text is inserted" +msgstr "Les modes sont d้sactiv้s, le texte saisi est ins้r้" + +msgid "menu Edit->Global Settings->Toggle Insert Mode " +msgstr "menu ษdition->R้glages Globaux->Insertion Permanente" + +# DB - todo +msgid " for two modes " +msgstr " pour les modes " + +# DB - todo +msgid "menu Edit->Global Settings->Toggle Vi Compatible" +msgstr "menu ษdition->R้glages Globaux->Compatibilit้ Vi" + +# DB - todo +msgid " for Vim defaults " +msgstr " pour d้f. de Vim " + msgid "Sponsor Vim development!" msgstr "Sponsorisez le d้veloppement de Vim !" -#: ../version.c:828 msgid "Become a registered Vim user!" msgstr "Devenez un utilisateur de Vim enregistr้ !" -#: ../version.c:831 msgid "type :help sponsor<Enter> for information " msgstr "tapez :help sponsor<Entr้e> pour plus d'informations " -#: ../version.c:832 msgid "type :help register<Enter> for information " msgstr "tapez :help register<Entr้e> pour plus d'informations " -#: ../version.c:834 msgid "menu Help->Sponsor/Register for information " msgstr "menu Aide->Sponsor/Enregistrement pour plus d'info" -#: ../window.c:119 msgid "Already only one window" msgstr "Il n'y a d้jเ plus qu'une fen๊tre" -#: ../window.c:224 msgid "E441: There is no preview window" msgstr "E441: Il n'y a pas de fen๊tre de pr้visualisation" -#: ../window.c:559 msgid "E442: Can't split topleft and botright at the same time" msgstr "E442: Impossible de partager topleft et botright en m๊me temps" -#: ../window.c:1228 msgid "E443: Cannot rotate when another window is split" msgstr "E443: Rotation impossible quand une autre fen๊tre est partag้e" -#: ../window.c:1803 msgid "E444: Cannot close last window" msgstr "E444: Impossible de fermer la derni่re fen๊tre" -#: ../window.c:1810 msgid "E813: Cannot close autocmd window" msgstr "E813: Impossible de fermer la fen๊tre des autocommandes" -#: ../window.c:1814 msgid "E814: Cannot close window, only autocmd window would remain" msgstr "" "E814: Impossible de fermer la fen๊tre, seule la fen๊tre des autocommandes " "resterait" -#: ../window.c:2717 msgid "E445: Other window contains changes" msgstr "E445: Les modifications de l'autre fen๊tre n'ont pas ้t้ enregistr้es" -#: ../window.c:4805 msgid "E446: No file name under cursor" msgstr "E446: Aucun nom de fichier sous le curseur" -#~ msgid "E831: bf_key_init() called with empty password" -#~ msgstr "E831: bf_key_init() appel้e avec un mot de passe vide" - -#~ msgid "E820: sizeof(uint32_t) != 4" -#~ msgstr "E820: sizeof(uint32_t) != 4" - -#~ msgid "E817: Blowfish big/little endian use wrong" -#~ msgstr "E817: petit/gros boutisme incorrect dans blowfish" - -#~ msgid "E818: sha256 test failed" -#~ msgstr "E818: le test de sha256 a ้chou้" - -#~ msgid "E819: Blowfish test failed" -#~ msgstr "E819: le test de blowfish a ้chou้" - -#~ msgid "Patch file" -#~ msgstr "Fichier rustine" - -# AB - Textes des boutons de la bo๎te de dialogue affich้e par inputdialog(). -#~ msgid "" -#~ "&OK\n" -#~ "&Cancel" -#~ msgstr "" -#~ "&Ok\n" -#~ "&Annuler" - -# AB - ภ mon avis, la version anglaise est erron้e. -# DB : V้rifier -#~ msgid "E240: No connection to Vim server" -#~ msgstr "E240: Pas de connexion au serveur X" - -# AB - La version fran็aise est meilleure que la version anglaise. -#~ msgid "E241: Unable to send to %s" -#~ msgstr "E241: L'envoi au serveur %s เ ้chou้" - -#~ msgid "E277: Unable to read a server reply" -#~ msgstr "E277: Impossible de lire la r้ponse du serveur" - -# AB - La version fran็aise est meilleure que la version anglaise. -#~ msgid "E258: Unable to send to client" -#~ msgstr "E258: La r้ponse n'a pas pu ๊tre envoy้e au client" - -# AB - Ceci est un titre de bo๎te de dialogue. V้rifier que la version -# fran็aise est correcte pour les trois r้f้rences ; j'ai un doute quant -# เ la troisi่me. -#~ msgid "Save As" -#~ msgstr "Enregistrer sous - Vim" - -# AB - Ceci est un titre de bo๎te de dialogue. -#~ msgid "Edit File" -#~ msgstr "Ouvrir un fichier - Vim" - -#~ msgid " (NOT FOUND)" -#~ msgstr " (INTROUVABLE)" - -#~ msgid "Source Vim script" -#~ msgstr "Sourcer un script - Vim" - -#~ msgid "unknown" -#~ msgstr "inconnu" - -#~ msgid "Edit File in new window" -#~ msgstr "Ouvrir un fichier dans une nouvelle fen๊tre - Vim" - -#~ msgid "Append File" -#~ msgstr "Ajouter fichier" - -#~ msgid "Window position: X %d, Y %d" -#~ msgstr "Position de la fen๊tre : X %d, Y %d" - -#~ msgid "Save Redirection" -#~ msgstr "Enregistrer la redirection" - -#~ msgid "Save View" -#~ msgstr "Enregistrer la vue - Vim" - -#~ msgid "Save Session" -#~ msgstr "Enregistrer la session - Vim" - -#~ msgid "Save Setup" -#~ msgstr "Enregistrer les r้glages - Vim" - -#~ msgid "E809: #< is not available without the +eval feature" -#~ msgstr "E809: #< n'est pas disponible sans la fonctionnalit้ +eval" - -#~ msgid "E196: No digraphs in this version" -#~ msgstr "E196: Pas de digraphes dans cette version" - -#~ msgid "is a device (disabled with 'opendevice' option)" -#~ msgstr "est un p้riph้rique (d้sactiv้ par l'option 'opendevice')" - -#~ msgid "Reading from stdin..." -#~ msgstr "Lecture de stdin..." - -#~ msgid "[crypted]" -#~ msgstr "[chiffr้]" - -#~ msgid "E821: File is encrypted with unknown method" -#~ msgstr "E821: Le fichier est chiffr้ avec une m้thode inconnue" - -#~ msgid "NetBeans disallows writes of unmodified buffers" -#~ msgstr "NetBeans interdit l'้criture des tampons non modifi้s" - -#~ msgid "Partial writes disallowed for NetBeans buffers" -#~ msgstr "Netbeans interdit l'้criture partielle de ses tampons" - -#~ msgid "writing to device disabled with 'opendevice' option" -#~ msgstr "้criture vers un p้riph้rique d้sactiv้ par l'option 'opendevice'" - -#~ msgid "E460: The resource fork would be lost (add ! to override)" -#~ msgstr "" -#~ "E460: Les ressources partag้es seraient perdues (ajoutez ! pour passer " -#~ "outre)" - -#~ msgid "E851: Failed to create a new process for the GUI" -#~ msgstr "" -#~ "E851: ษchec lors de la cr้ation d'un nouveau processus pour l'interface " -#~ "graphique" - -#~ msgid "E852: The child process failed to start the GUI" -#~ msgstr "" -#~ "E852: Le processus fils n'a pas r้ussi เ d้marrer l'interface graphique" - -#~ msgid "E229: Cannot start the GUI" -#~ msgstr "E229: Impossible de d้marrer l'interface graphique" - -#~ msgid "E230: Cannot read from \"%s\"" -#~ msgstr "E230: Impossible de lire \"%s\"" - -#~ msgid "E665: Cannot start GUI, no valid font found" -#~ msgstr "" -#~ "E665: Impossible de d้marrer l'IHM graphique, aucune police valide trouv้e" - -#~ msgid "E231: 'guifontwide' invalid" -#~ msgstr "E231: 'guifontwide' est invalide" - -#~ msgid "E599: Value of 'imactivatekey' is invalid" -#~ msgstr "E599: Valeur de 'imactivatekey' invalide" - -#~ msgid "E254: Cannot allocate color %s" -#~ msgstr "E254: Impossible d'allouer la couleur %s" - -#~ msgid "No match at cursor, finding next" -#~ msgstr "Aucune correspondance sous le curseur, recherche de la suivante" - -#~ msgid "<cannot open> " -#~ msgstr "<impossible d'ouvrir> " - -#~ msgid "E616: vim_SelFile: can't get font %s" -#~ msgstr "E616: vim_SelFile : impossible d'obtenir la police %s" - -#~ msgid "E614: vim_SelFile: can't return to current directory" -#~ msgstr "" -#~ "E614: vim_SelFile : impossible de revenir dans le r้pertoire courant" - -#~ msgid "Pathname:" -#~ msgstr "Chemin :" - -#~ msgid "E615: vim_SelFile: can't get current directory" -#~ msgstr "E615: vim_SelFile : impossible d'obtenir le r้pertoire courant" - -#~ msgid "OK" -#~ msgstr "Ok" - -#~ msgid "Cancel" -#~ msgstr "Annuler" - -#~ msgid "Scrollbar Widget: Could not get geometry of thumb pixmap." -#~ msgstr "" -#~ "Widget scrollbar : Impossible d'obtenir la g้om้trie du pixmap 'thumb'" - -#~ msgid "Vim dialog" -#~ msgstr "Vim" - -#~ msgid "E232: Cannot create BalloonEval with both message and callback" -#~ msgstr "E232: Impossible de cr้er un BalloonEval avec message ET callback" - -msgid "Yes" -msgstr "Oui" - -msgid "No" -msgstr "Non" - -# todo '_' is for hotkey, i guess? -#~ msgid "Input _Methods" -#~ msgstr "_M้thodes de saisie" - -#~ msgid "VIM - Search and Replace..." -#~ msgstr "Remplacer - Vim" - -#~ msgid "VIM - Search..." -#~ msgstr "Rechercher - Vim" - -#~ msgid "Find what:" -#~ msgstr "Rechercher :" - -#~ msgid "Replace with:" -#~ msgstr "Remplacer par :" - -#~ msgid "Match whole word only" -#~ msgstr "Mots entiers seulement" - -#~ msgid "Match case" -#~ msgstr "Respecter la casse" - -#~ msgid "Direction" -#~ msgstr "Direction" - -#~ msgid "Up" -#~ msgstr "Haut" - -#~ msgid "Down" -#~ msgstr "Bas" - -#~ msgid "Find Next" -#~ msgstr "Suivant" - -#~ msgid "Replace" -#~ msgstr "Remplacer" - -#~ msgid "Replace All" -#~ msgstr "Remplacer tout" - -#~ msgid "Vim: Received \"die\" request from session manager\n" -#~ msgstr "" -#~ "Vim : Une requ๊te \"die\" a ้t้ re็ue par le gestionnaire de session\n" - -#~ msgid "Close tab" -#~ msgstr "Fermer l'onglet" - -#~ msgid "New tab" -#~ msgstr "Nouvel onglet" - -# DB - todo : un peu long. Cet entr้e de menu permet d'ouvrir un fichier -# dans un nouvel onglet via le s้lecteur de fichiers graphique. -#~ msgid "Open Tab..." -#~ msgstr "Ouvrir dans un onglet..." - -#~ msgid "Vim: Main window unexpectedly destroyed\n" -#~ msgstr "Vim : Fen๊tre principale d้truite inopin้ment\n" - -#~ msgid "&Filter" -#~ msgstr "&Filtrer" - -#~ msgid "&Cancel" -#~ msgstr "&Annuler" - -#~ msgid "Directories" -#~ msgstr "R้pertoires" - -#~ msgid "Filter" -#~ msgstr "Filtre" - -#~ msgid "&Help" -#~ msgstr "&Aide" - -#~ msgid "Files" -#~ msgstr "Fichiers" - -#~ msgid "&OK" -#~ msgstr "&Ok" - -#~ msgid "Selection" -#~ msgstr "S้lection" - -#~ msgid "Find &Next" -#~ msgstr "Suiva&nt" - -#~ msgid "&Replace" -#~ msgstr "&Remplacer" - -#~ msgid "Replace &All" -#~ msgstr "Rempl&acer tout" - -#~ msgid "&Undo" -#~ msgstr "Ann&uler" - -#~ msgid "E671: Cannot find window title \"%s\"" -#~ msgstr "E671: Titre de fen๊tre \"%s\" introuvable" - -#~ msgid "E243: Argument not supported: \"-%s\"; Use the OLE version." -#~ msgstr "E243: Argument non support้ : \"-%s\" ; Utilisez la version OLE." - -#~ msgid "E672: Unable to open window inside MDI application" -#~ msgstr "E672: Impossible d'ouvrir une fen๊tre dans une application MDI" - -#~ msgid "Open tab..." -#~ msgstr "Ouvrir dans un onglet..." - -#~ msgid "Find string (use '\\\\' to find a '\\')" -#~ msgstr "Chercher une cha๎ne (utilisez '\\\\' pour chercher un '\\')" - -#~ msgid "Find & Replace (use '\\\\' to find a '\\')" -#~ msgstr "Chercher et remplacer (utilisez '\\\\' pour trouver un '\\')" - -# DB - Traduction non indispensable puisque le code indique qu'il s'agit d'un -# param้trage bidon afin de s้lectionner un r้pertoire plut๔t qu'un -# fichier. -#~ msgid "Not Used" -#~ msgstr "Non utilis้" - -# DB - Traduction non indispensable puisque le code indique qu'il s'agit d'un -# param้trage bidon afin de s้lectionner un r้pertoire plut๔t qu'un -# fichier. -#~ msgid "Directory\t*.nothing\n" -#~ msgstr "R้pertoire\t*.rien\n" - -# DB - todo : perfectible. -#~ msgid "" -#~ "Vim E458: Cannot allocate colormap entry, some colors may be incorrect" -#~ msgstr "" -#~ "Vim E458: Erreur d'allocation de couleurs, couleurs possiblement " -#~ "incorrectes" - -# DB - todo : La VF est-elle compr้hensible ? -#~ msgid "E250: Fonts for the following charsets are missing in fontset %s:" -#~ msgstr "" -#~ "E250: Des polices manquent dans %s pour les jeux de caract่res suivants :" - -#~ msgid "E252: Fontset name: %s" -#~ msgstr "E252: Nom du jeu de polices : %s" - -#~ msgid "Font '%s' is not fixed-width" -#~ msgstr "La police '%s' n'a pas une largeur fixe" - -#~ msgid "E253: Fontset name: %s\n" -#~ msgstr "E253: Nom du jeu de polices : %s\n" - -#~ msgid "Font0: %s\n" -#~ msgstr "Font0: %s\n" - -#~ msgid "Font1: %s\n" -#~ msgstr "Font1: %s\n" - -#~ msgid "Font%<PRId64> width is not twice that of font0\n" -#~ msgstr "La largeur de Font%<PRId64> n'est pas le double de celle de Font0\n" - -#~ msgid "Font0 width: %<PRId64>\n" -#~ msgstr "Largeur de Font0 : %<PRId64>\n" - -#~ msgid "" -#~ "Font1 width: %<PRId64>\n" -#~ "\n" -#~ msgstr "" -#~ "Largeur de Font1 : %<PRId64>\n" -#~ "\n" - -# DB - todo : Pas certain de mon coup, ici... -#~ msgid "Invalid font specification" -#~ msgstr "La sp้cification de la police est invalide" - -#~ msgid "&Dismiss" -#~ msgstr "Aban&donner" - -# DB - todo : Pas certain de mon coup, ici... -#~ msgid "no specific match" -#~ msgstr "aucune correspondance particuli่re" - -#~ msgid "Vim - Font Selector" -#~ msgstr "Choisir une police - Vim" - -#~ msgid "Name:" -#~ msgstr "Nom :" - -#~ msgid "Show size in Points" -#~ msgstr "Afficher la taille en Points" - -#~ msgid "Encoding:" -#~ msgstr "Encodage :" - -#~ msgid "Font:" -#~ msgstr "Police :" - -#~ msgid "Style:" -#~ msgstr "Style :" - -#~ msgid "Size:" -#~ msgstr "Taille :" - -#~ msgid "E256: Hangul automata ERROR" -#~ msgstr "E256: ERREUR dans l'automate Hangul" - -#~ msgid "E563: stat error" -#~ msgstr "E563: Erreur stat" - -#~ msgid "E625: cannot open cscope database: %s" -#~ msgstr "E625: impossible d'ouvrir la base de donn้es cscope %s" - -#~ msgid "E626: cannot get cscope database information" -#~ msgstr "" -#~ "E626: impossible d'obtenir des informations sur la base de donn้es cscope" - -#~ msgid "Lua library cannot be loaded." -#~ msgstr "La biblioth่que Lua n'a pas pu ๊tre charg้e." - -#~ msgid "cannot save undo information" -#~ msgstr "impossible d'enregistrer les informations d'annulation" - -#~ msgid "" -#~ "E815: Sorry, this command is disabled, the MzScheme libraries could not " -#~ "be loaded." -#~ msgstr "" -#~ "E815: D้sol้, cette commande est d้sactiv้e : les biblioth่ques MzScheme " -#~ "n'ont pas pu ๊tre charg้es." - -#~ msgid "invalid expression" -#~ msgstr "expression invalide" - -#~ msgid "expressions disabled at compile time" -#~ msgstr "expressions d้sactiv้e lors de la compilation" - -#~ msgid "hidden option" -#~ msgstr "option cach้e" - -#~ msgid "unknown option" -#~ msgstr "option inconnue" - -#~ msgid "window index is out of range" -#~ msgstr "num้ro de fen๊tre hors limites" - -#~ msgid "couldn't open buffer" -#~ msgstr "impossible d'ouvrir le tampon" - -#~ msgid "cannot delete line" -#~ msgstr "impossible d'effacer la ligne" - -#~ msgid "cannot replace line" -#~ msgstr "impossible de remplacer la ligne" - -#~ msgid "cannot insert line" -#~ msgstr "impossible d'ins้rer la ligne" - -#~ msgid "string cannot contain newlines" -#~ msgstr "une cha๎ne ne peut pas contenir de saut-de-ligne" - -#~ msgid "error converting Scheme values to Vim" -#~ msgstr "erreur lors de la conversion d'une valeur de Scheme เ Vim" - -#~ msgid "Vim error: ~a" -#~ msgstr "Erreur Vim : ~a" - -#~ msgid "Vim error" -#~ msgstr "Erreur Vim" - -#~ msgid "buffer is invalid" -#~ msgstr "tampon invalide" - -#~ msgid "window is invalid" -#~ msgstr "fen๊tre invalide" - -#~ msgid "linenr out of range" -#~ msgstr "num้ro de ligne hors limites" - -#~ msgid "not allowed in the Vim sandbox" -#~ msgstr "non autoris้ dans le bac เ sable" - -#~ msgid "E836: This Vim cannot execute :python after using :py3" -#~ msgstr "E836: Vim ne peut pas ex้cuter :python apr่s avoir utilis้ :py3" - -#~ msgid "" -#~ "E263: Sorry, this command is disabled, the Python library could not be " -#~ "loaded." -#~ msgstr "" -#~ "E263: D้sol้, commande d้sactiv้e : la biblioth่que Python n'a pas pu " -#~ "๊tre charg้e." - -#~ msgid "E659: Cannot invoke Python recursively" -#~ msgstr "E659: Impossible d'invoquer Python r้cursivement" - -#~ msgid "E837: This Vim cannot execute :py3 after using :python" -#~ msgstr "E837: Vim ne peut pas ex้cuter :py3 apr่s avoir utilis้ :python" - -#~ msgid "index must be int or slice" -#~ msgstr "index doit ๊tre int ou slice" - -#~ msgid "E265: $_ must be an instance of String" -#~ msgstr "E265: $_ doit ๊tre une instance de cha๎ne (String)" - -#~ msgid "" -#~ "E266: Sorry, this command is disabled, the Ruby library could not be " -#~ "loaded." -#~ msgstr "" -#~ "E266: D้sol้, commande d้sactiv้e : la biblioth่que Ruby n'a pas pu ๊tre " -#~ "charg้e." - -#~ msgid "E267: unexpected return" -#~ msgstr "E267: ซ return ป inattendu" - -#~ msgid "E268: unexpected next" -#~ msgstr "E268: ซ next ป inattendu" - -#~ msgid "E269: unexpected break" -#~ msgstr "E269: ซ break ป inattendu" - -#~ msgid "E270: unexpected redo" -#~ msgstr "E270: ซ redo ป inattendu" - -#~ msgid "E271: retry outside of rescue clause" -#~ msgstr "E271: ซ retry ป hors d'une clause ซ rescue ป" - -#~ msgid "E272: unhandled exception" -#~ msgstr "E272: Exception non prise en charge" - -# DB - todo -#~ msgid "E273: unknown longjmp status %d" -#~ msgstr "E273: contexte de longjmp inconnu : %d" - -#~ msgid "Toggle implementation/definition" -#~ msgstr "Basculer impl้mentation/d้finition" - -#~ msgid "Show base class of" -#~ msgstr "Montrer la classe de base de" - -#~ msgid "Show overridden member function" -#~ msgstr "Montrer les fonctions membres surcharg้es" - -#~ msgid "Retrieve from file" -#~ msgstr "R้cup้rer du fichier" - -#~ msgid "Retrieve from project" -#~ msgstr "R้cup้rer du projet" - -#~ msgid "Retrieve from all projects" -#~ msgstr "R้cup้rer de tous les projets" - -#~ msgid "Retrieve" -#~ msgstr "R้cup้rer" - -#~ msgid "Show source of" -#~ msgstr "Montrer source de" - -#~ msgid "Find symbol" -#~ msgstr "Trouver symbole" - -#~ msgid "Browse class" -#~ msgstr "Parcourir classe" - -#~ msgid "Show class in hierarchy" -#~ msgstr "Montrer classe dans hi้rarchie" - -#~ msgid "Show class in restricted hierarchy" -#~ msgstr "Montrer classe dans hi้rarchie restreinte" - -# todo -#~ msgid "Xref refers to" -#~ msgstr "Xref r้f้rence" - -#~ msgid "Xref referred by" -#~ msgstr "Xref est r้f้renc้ par" - -#~ msgid "Xref has a" -#~ msgstr "Xref a un(e)" - -#~ msgid "Xref used by" -#~ msgstr "Xref utilis้e par" - -#~ msgid "Show docu of" -#~ msgstr "Montrer doc de" - -#~ msgid "Generate docu for" -#~ msgstr "G้n้rer la doc de" - -#~ msgid "" -#~ "Cannot connect to SNiFF+. Check environment (sniffemacs must be found in " -#~ "$PATH).\n" -#~ msgstr "" -#~ "Connexion เ SNiFF+ impossible. V้rifiez l'environnement (sniffemacs doit " -#~ "๊tre dans le $PATH).\n" - -#~ msgid "E274: Sniff: Error during read. Disconnected" -#~ msgstr "E274: Sniff : Erreur de lecture. D้connexion" - -# DB - Les trois messages suivants vont ensembles. -#~ msgid "SNiFF+ is currently " -#~ msgstr "SNiFF+ est actuellement " - -#~ msgid "not " -#~ msgstr "d้" - -#~ msgid "connected" -#~ msgstr "connect้" - -#~ msgid "E275: Unknown SNiFF+ request: %s" -#~ msgstr "E275: Requ๊te SNiFF+ inconnue : %s" - -#~ msgid "E276: Error connecting to SNiFF+" -#~ msgstr "E276: Erreur lors de la connexion เ SNiFF+" - -#~ msgid "E278: SNiFF+ not connected" -#~ msgstr "E278: SNiFF+ n'est pas connect้" - -#~ msgid "E279: Not a SNiFF+ buffer" -#~ msgstr "E279: Ce tampon n'est pas un tampon SNiFF+" - -#~ msgid "Sniff: Error during write. Disconnected" -#~ msgstr "Sniff : Erreur lors d'une ้criture. D้connexion" - -#~ msgid "invalid buffer number" -#~ msgstr "num้ro de tampon invalide" - -#~ msgid "not implemented yet" -#~ msgstr "pas encore impl้ment้" - -# DB - TODO : le contexte est celui d'une annulation. -#~ msgid "cannot set line(s)" -#~ msgstr "Impossible de remettre la/les ligne(s)" - -#~ msgid "invalid mark name" -#~ msgstr "nom de marque invalide" - -#~ msgid "mark not set" -#~ msgstr "marque non positionn้e" - -#~ msgid "row %d column %d" -#~ msgstr "ligne %d colonne %d" - -#~ msgid "cannot insert/append line" -#~ msgstr "Impossible d'ins้rer/ajouter de lignes" - -#~ msgid "line number out of range" -#~ msgstr "num้ro de ligne hors limites" - -#~ msgid "unknown flag: " -#~ msgstr "drapeau inconnu : " - -#~ msgid "unknown vimOption" -#~ msgstr "vimOption inconnue" +#, c-format +msgid "E447: Can't find file \"%s\" in path" +msgstr "E447: Le fichier \"%s\" est introuvable dans 'path'" -#~ msgid "keyboard interrupt" -#~ msgstr "interruption clavier" +#, c-format +msgid "E799: Invalid ID: %ld (must be greater than or equal to 1)" +msgstr "E799: ID invalide : %ld (doit ๊tre plus grand ou ้gal เ 1)" -#~ msgid "vim error" -#~ msgstr "erreur Vim" +#, c-format +msgid "E801: ID already taken: %ld" +msgstr "E801: ID d้jเ pris: %ld" -#~ msgid "cannot create buffer/window command: object is being deleted" -#~ msgstr "" -#~ "Impossible de cr้er commande de tampon/fen๊tre : objet en cours " -#~ "d'effacement" +msgid "List or number required" +msgstr "Liste ou nombre requis" -#~ msgid "" -#~ "cannot register callback command: buffer/window is already being deleted" -#~ msgstr "" -#~ "Impossible d'inscrire la commande de rappel : tampon/fen๊tre en effacement" +#, c-format +msgid "E802: Invalid ID: %ld (must be greater than or equal to 1)" +msgstr "E802: ID invalide : %ld (doit ๊tre plus grand ou ้gal เ 1)" -#~ msgid "" -#~ "E280: TCL FATAL ERROR: reflist corrupt!? Please report this to vim-" -#~ "dev@vim.org" -#~ msgstr "" -#~ "E280: ERREUR FATALE TCL: reflist corrompue ?! Contactez vim-dev@vim.org, " -#~ "SVP." +#, c-format +msgid "E803: ID not found: %ld" +msgstr "E803: ID introuvable : %ld" -#~ msgid "cannot register callback command: buffer/window reference not found" -#~ msgstr "" -#~ "Impossible d'inscrire la commande de rappel : r้f. tampon/fen๊tre " -#~ "introuvable" +#, c-format +msgid "E370: Could not load library %s" +msgstr "E370: Impossible de charger la biblioth่que %s" -#~ msgid "" -#~ "E571: Sorry, this command is disabled: the Tcl library could not be " -#~ "loaded." -#~ msgstr "" -#~ "E571: D้sol้, commande d้sactiv้e: la biblioth่que Tcl n'a pas pu ๊tre " -#~ "charg้e." +msgid "Sorry, this command is disabled: the Perl library could not be loaded." +msgstr "" +"D้sol้, commande d้sactiv้e : la biblioth่que Perl n'a pas pu ๊tre charg้e." -#~ msgid "E572: exit code %d" -#~ msgstr "E572: code de sortie %d" +msgid "E299: Perl evaluation forbidden in sandbox without the Safe module" +msgstr "E299: ษvaluation Perl interdite dans bac เ sable sans le module Safe" -#~ msgid "cannot get line" -#~ msgstr "Impossible d'obtenir la ligne" +msgid "Edit with &multiple Vims" +msgstr "ษditer dans &plusieurs Vims" -#~ msgid "Unable to register a command server name" -#~ msgstr "Impossible d'inscrire un nom de serveur de commande" +msgid "Edit with single &Vim" +msgstr "ษditer dans un seul &Vim" -#~ msgid "E248: Failed to send command to the destination program" -#~ msgstr "E248: ษchec de l'envoi de la commande au programme cible" +msgid "Diff with Vim" +msgstr "&Comparer avec Vim" -#~ msgid "E573: Invalid server id used: %s" -#~ msgstr "E573: Id utilis้ pour le serveur invalide : %s" +msgid "Edit with &Vim" +msgstr "ษditer dans &Vim" -#~ msgid "E251: VIM instance registry property is badly formed. Deleted!" -#~ msgstr "" -#~ "E251: Entr้e registre de l'instance de Vim mal format้e. Suppression !" +#. Now concatenate +msgid "Edit with existing Vim - " +msgstr "ษditer dans le Vim existant - " -#~ msgid "netbeans is not supported with this GUI\n" -#~ msgstr "netbeans n'est pas support้ avec cette interface graphique\n" +msgid "Edits the selected file(s) with Vim" +msgstr "ษdites le(s) fichier(s) s้lectionn้(s) avec Vim" -#~ msgid "This Vim was not compiled with the diff feature." -#~ msgstr "Ce Vim n'a pas ้t้ compil้ avec la fonctionnalit้ diff" +# DB - MessageBox win32, la longueur n'est pas un probl่me ! +msgid "Error creating process: Check if gvim is in your path!" +msgstr "" +"Erreur de cr้ation du processus : v้rifiez que gvim est bien dans votre " +"chemin !" -#~ msgid "'-nb' cannot be used: not enabled at compile time\n" -#~ msgstr "'-nb' ne peut pas ๊tre utilis้ : d้sactiv้ เ la compilation\n" +msgid "gvimext.dll error" +msgstr "Erreur de gvimext.dll" -#~ msgid "Vim: Error: Failure to start gvim from NetBeans\n" -#~ msgstr "Vim : Erreur : Impossible de d้marrer gvim depuis NetBeans\n" +msgid "Path length too long!" +msgstr "Le chemin est trop long !" -# DB - todo (VMS uniquement). -#~ msgid "" -#~ "\n" -#~ "Where case is ignored prepend / to make flag upper case" -#~ msgstr "" -#~ "\n" -#~ "pour lesquels la casse est indiff้rente (/ pour que le drapeau soit " -#~ "majuscule)" - -#~ msgid "-register\t\tRegister this gvim for OLE" -#~ msgstr "-register\tInscrire ce gvim pour OLE" - -#~ msgid "-unregister\t\tUnregister gvim for OLE" -#~ msgstr "-unregister\tD้sinscrire gvim de OLE" - -#~ msgid "-g\t\t\tRun using GUI (like \"gvim\")" -#~ msgstr "-g\t\tLancer l'interface graphique (comme \"gvim\")" - -#~ msgid "-f or --nofork\tForeground: Don't fork when starting GUI" -#~ msgstr "" -#~ "-f, --nofork\tPremier-plan : ne pas d้tacher l'interface graphique du " -#~ "terminal" - -#~ msgid "-f\t\t\tDon't use newcli to open window" -#~ msgstr "-f\t\tNe pas utiliser newcli pour l'ouverture des fen๊tres" - -#~ msgid "-dev <device>\t\tUse <device> for I/O" -#~ msgstr "-dev <p้riph>\tUtiliser <p้riph้rique> pour les E/S" - -#~ msgid "-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc" -#~ msgstr "-U <gvimrc>\tUtiliser <gvimrc> au lieu du gvimrc habituel" - -#~ msgid "-x\t\t\tEdit encrypted files" -#~ msgstr "-x\t\t\tษditer des fichiers chiffr้s" - -#~ msgid "-display <display>\tConnect vim to this particular X-server" -#~ msgstr "-display <display>\tConnecter Vim au serveur X sp้cifi้" - -#~ msgid "-X\t\t\tDo not connect to X server" -#~ msgstr "-X\t\t\tNe pas se connecter เ un serveur X" - -#~ msgid "--remote <files>\tEdit <files> in a Vim server if possible" -#~ msgstr "" -#~ "--remote <fich>\tษditer les <fichiers> dans un serveur Vim si possible" - -#~ msgid "--remote-silent <files> Same, don't complain if there is no server" -#~ msgstr "" -#~ "--remote-silent ...\tPareil, mais pas d'erreur s'il n'y a aucun serveur" - -#~ msgid "" -#~ "--remote-wait <files> As --remote but wait for files to have been edited" -#~ msgstr "" -#~ "--remote-wait <fich>\tComme --remote mais ne quitter qu'เ la fin de " -#~ "l'้dition" - -#~ msgid "" -#~ "--remote-wait-silent <files> Same, don't complain if there is no server" -#~ msgstr "" -#~ "--remote-wait-silent\tPareil, mais pas d'erreur s'il n'y a aucun serveur" - -#~ msgid "" -#~ "--remote-tab[-wait][-silent] <files> As --remote but use tab page per " -#~ "file" -#~ msgstr "" -#~ "--remote-tab[-wait][-silent] <fich>\tComme --remote mais ouvrir un onglet " -#~ "pour chaque fichier" - -#~ msgid "--remote-send <keys>\tSend <keys> to a Vim server and exit" -#~ msgstr "" -#~ "--remote-send <tche>\tEnvoyer <touches> เ un serveur Vim puis quitter" - -#~ msgid "" -#~ "--remote-expr <expr>\tEvaluate <expr> in a Vim server and print result" -#~ msgstr "" -#~ "--remote-expr <expr>\tษvaluer <expr> dans un serveur Vim, afficher le " -#~ "r้sultat" - -#~ msgid "--serverlist\t\tList available Vim server names and exit" -#~ msgstr "" -#~ "--serverlist\t\tLister les noms des serveurs Vim disponibles et quitter" - -#~ msgid "--servername <name>\tSend to/become the Vim server <name>" -#~ msgstr "--servername <nom>\tEnvoyer au/devenir le serveur Vim nomm้ <nom>" - -#~ msgid "" -#~ "\n" -#~ "Arguments recognised by gvim (Motif version):\n" -#~ msgstr "" -#~ "\n" -#~ "Arguments reconnus par gvim (version Motif) :\n" - -#~ msgid "" -#~ "\n" -#~ "Arguments recognised by gvim (neXtaw version):\n" -#~ msgstr "" -#~ "\n" -#~ "Arguments reconnus par gvim (version neXtaw) :\n" - -#~ msgid "" -#~ "\n" -#~ "Arguments recognised by gvim (Athena version):\n" -#~ msgstr "" -#~ "\n" -#~ "Arguments reconnus par gvim (version Athena) :\n" +# msgstr "--Pas de lignes dans le tampon--" +# DB - todo : ou encore : msgstr "--Aucune ligne dans le tampon--" +msgid "--No lines in buffer--" +msgstr "--Le tampon est vide--" -#~ msgid "-display <display>\tRun vim on <display>" -#~ msgstr "-display <้cran>\tLancer Vim sur ce <display>" +#. +#. * The error messages that can be shared are included here. +#. * Excluded are errors that are only used once and debugging messages. +#. +msgid "E470: Command aborted" +msgstr "E470: Commande annul้e" -#~ msgid "-iconic\t\tStart vim iconified" -#~ msgstr "-iconic\t\tIconifier Vim au d้marrage" +msgid "E471: Argument required" +msgstr "E471: Argument requis" -#~ msgid "-background <color>\tUse <color> for the background (also: -bg)" -#~ msgstr "" -#~ "-background <coul>\tUtiliser <couleur> pour l'arri่re-plan\t (abrv : -" -#~ "bg)" +msgid "E10: \\ should be followed by /, ? or &" +msgstr "E10: \\ devrait ๊tre suivi de /, ? ou &" -#~ msgid "-foreground <color>\tUse <color> for normal text (also: -fg)" -#~ msgstr "" -#~ "-foreground <coul>\tUtiliser <couleur> pour le texte normal\t (abrv : -" -#~ "fg)" +msgid "E11: Invalid in command-line window; <CR> executes, CTRL-C quits" +msgstr "" +"E11: Invalide dans la fen๊tre ligne-de-commande ; <CR> ex้cute, CTRL-C quitte" -#~ msgid "-font <font>\t\tUse <font> for normal text (also: -fn)" -#~ msgstr "" -#~ "-font <fonte>\tUtiliser <fonte> pour le texte normal\t (abrv : -fn)" +msgid "E12: Command not allowed from exrc/vimrc in current dir or tag search" +msgstr "" +"E12: commande non autoris้e depuis un exrc/vimrc dans r้pertoire courant ou " +"une recherche de marqueur" -#~ msgid "-boldfont <font>\tUse <font> for bold text" -#~ msgstr "-boldfont <fonte>\tUtiliser <fonte> pour le texte gras" +msgid "E171: Missing :endif" +msgstr "E171: :endif manquant" -#~ msgid "-italicfont <font>\tUse <font> for italic text" -#~ msgstr "-italicfont <fonte>\tUtiliser <fonte> pour le texte italique" +msgid "E600: Missing :endtry" +msgstr "E600: :endtry manquant" -#~ msgid "-geometry <geom>\tUse <geom> for initial geometry (also: -geom)" -#~ msgstr "" -#~ "-geometry <g้om>\tUtiliser cette <g้om้trie> initiale\t (abrv : -geom)" +msgid "E170: Missing :endwhile" +msgstr "E170: :endwhile manquant" -#~ msgid "-borderwidth <width>\tUse a border width of <width> (also: -bw)" -#~ msgstr "" -#~ "-borderwidth <้pais>\tUtiliser cette <้paisseur> de bordure\t (abrv : -" -#~ "bw)" +msgid "E170: Missing :endfor" +msgstr "E170: :endfor manquant" -#~ msgid "" -#~ "-scrollbarwidth <width> Use a scrollbar width of <width> (also: -sw)" -#~ msgstr "" -#~ "-scrollbarwidth <lg>\tUtiliser cette <largeur> de barre de d้fil. (abrv: -" -#~ "sw)" - -#~ msgid "-menuheight <height>\tUse a menu bar height of <height> (also: -mh)" -#~ msgstr "" -#~ "-menuheight <haut>\tUtiliser cette <hauteur> de menu\t (abrv : -mh)" - -#~ msgid "-reverse\t\tUse reverse video (also: -rv)" -#~ msgstr "-reverse\t\tUtiliser la vid้o inverse\t\t (abrv : -rv)" - -#~ msgid "+reverse\t\tDon't use reverse video (also: +rv)" -#~ msgstr "+reverse\t\tNe pas utiliser de vid้o inverse\t (abrv : +rv)" - -#~ msgid "-xrm <resource>\tSet the specified resource" -#~ msgstr "-xrm <ressource>\tConfigurer la <ressource> sp้cifi้e" - -#~ msgid "" -#~ "\n" -#~ "Arguments recognised by gvim (GTK+ version):\n" -#~ msgstr "" -#~ "\n" -#~ "Arguments reconnus par gvim (version GTK+) :\n" - -#~ msgid "-display <display>\tRun vim on <display> (also: --display)" -#~ msgstr "" -#~ "-display <display>\tLancer Vim sur ce <display>\t(้galement : --display)" - -#~ msgid "--role <role>\tSet a unique role to identify the main window" -#~ msgstr "--role <r๔le>\tDonner un r๔le pour identifier la fen๊tre principale" - -#~ msgid "--socketid <xid>\tOpen Vim inside another GTK widget" -#~ msgstr "--socketid <xid>\tOuvrir Vim dans un autre widget GTK" - -#~ msgid "--echo-wid\t\tMake gvim echo the Window ID on stdout" -#~ msgstr "--echo-wid\t\tGvim affiche l'ID de la fen๊tre sur stdout" - -#~ msgid "-P <parent title>\tOpen Vim inside parent application" -#~ msgstr "-P <titre parent>\tOuvrir Vim dans une application parente" - -#~ msgid "--windowid <HWND>\tOpen Vim inside another win32 widget" -#~ msgstr "--windowid <HWND>\tOuvrir Vim dans un autre widget win32" - -#~ msgid "No display" -#~ msgstr "Aucun display" - -#~ msgid ": Send failed.\n" -#~ msgstr " : L'envoi a ้chou้.\n" - -#~ msgid ": Send failed. Trying to execute locally\n" -#~ msgstr " : L'envoi a ้chou้. Tentative d'ex้cution locale\n" - -#~ msgid "%d of %d edited" -#~ msgstr "%d ้dit้s sur %d" - -#~ msgid "No display: Send expression failed.\n" -#~ msgstr "Aucun display : L'envoi de l'expression a ้chou้.\n" - -#~ msgid ": Send expression failed.\n" -#~ msgstr " : L'envoi de l'expression a ้chou้.\n" +msgid "E588: :endwhile without :while" +msgstr "E588: :endwhile sans :while" -#~ msgid "E543: Not a valid codepage" -#~ msgstr "E543: Page de codes non valide" +msgid "E588: :endfor without :for" +msgstr "E588: :endfor sans :for" -#~ msgid "E284: Cannot set IC values" -#~ msgstr "E284: Impossible de r้gler les valeurs IC" - -#~ msgid "E285: Failed to create input context" -#~ msgstr "E285: ษchec de la cr้ation du contexte de saisie" - -#~ msgid "E286: Failed to open input method" -#~ msgstr "E286: ษchec de l'ouverture de la m้thode de saisie" +msgid "E13: File exists (add ! to override)" +msgstr "E13: Le fichier existe d้jเ (ajoutez ! pour passer outre)" -#~ msgid "E287: Warning: Could not set destroy callback to IM" -#~ msgstr "" -#~ "E287: Alerte : Impossible d'inscrire la callback de destruction dans la MS" +msgid "E472: Command failed" +msgstr "E472: La commande a ้chou้" -#~ msgid "E288: input method doesn't support any style" -#~ msgstr "E288: la m้thode de saisie ne supporte aucun style" +#, c-format +msgid "E234: Unknown fontset: %s" +msgstr "E234: Jeu de police inconnu : %s" -#~ msgid "E289: input method doesn't support my preedit type" -#~ msgstr "" -#~ "E289: le type de pr้้dition de Vim n'est pas support้ par la m้thode de " -#~ "saisie" +#, c-format +msgid "E235: Unknown font: %s" +msgstr "E235: Police inconnue : %s" -#~ msgid "E843: Error while updating swap file crypt" -#~ msgstr "E843: Erreur lors de la mise เ jour du fichier d'้change crypt้" +#, c-format +msgid "E236: Font \"%s\" is not fixed-width" +msgstr "E236: La police \"%s\" n'a pas une chasse (largeur) fixe" -#~ msgid "" -#~ "E833: %s is encrypted and this version of Vim does not support encryption" -#~ msgstr "" -#~ "E833: %s est chiffr้ et cette version de Vim ne supporte pas le " -#~ "chiffrement" - -#~ msgid "Swap file is encrypted: \"%s\"" -#~ msgstr "Fichier d'้change chiffr้ : \"%s\"" +msgid "E473: Internal error" +msgstr "E473: Erreur interne" -#~ msgid "" -#~ "\n" -#~ "If you entered a new crypt key but did not write the text file," -#~ msgstr "" -#~ "\n" -#~ "Si vous avez tap้ une nouvelle cl้ de chiffrement mais n'avez pas " -#~ "enregistr้ le fichier texte," +#, c-format +msgid "E685: Internal error: %s" +msgstr "E685: Erreur interne : %s" -#~ msgid "" -#~ "\n" -#~ "enter the new crypt key." -#~ msgstr "" -#~ "\n" -#~ "tapez la nouvelle cl้ de chiffrement." +msgid "Interrupted" +msgstr "Interrompu" -#~ msgid "" -#~ "\n" -#~ "If you wrote the text file after changing the crypt key press enter" -#~ msgstr "" -#~ "\n" -#~ "Si vous avez ้crit le fichier texte apr่s avoir chang้ la cl้ de " -#~ "chiffrement, appuyez sur entr้e" +msgid "E14: Invalid address" +msgstr "E14: Adresse invalide" -#~ msgid "" -#~ "\n" -#~ "to use the same key for text file and swap file" -#~ msgstr "" -#~ "\n" -#~ "afin d'utiliser la m๊me cl้ pour le fichier texte et le fichier d'้change" +msgid "E474: Invalid argument" +msgstr "E474: Argument invalide" -#~ msgid "Using crypt key from swap file for the text file.\n" -#~ msgstr "" -#~ "Utilisation de la cl้ de chiffrement du fichier d'้change pour le fichier " -#~ "texte.\n" +#, c-format +msgid "E475: Invalid argument: %s" +msgstr "E475: Argument invalide : %s" -#~ msgid "" -#~ "\n" -#~ " [not usable with this version of Vim]" -#~ msgstr "" -#~ "\n" -#~ " [inutilisable avec cette version de Vim]" - -#~ msgid "Tear off this menu" -#~ msgstr "D้tacher ce menu" +#, c-format +msgid "E15: Invalid expression: %s" +msgstr "E15: Expression invalide : %s" -# DB : Les trois messages qui suivent sont des titres de bo๎tes -# de dialogue par d้faut. -#~ msgid "Select Directory dialog" -#~ msgstr "S้lecteur de r้pertoire" +msgid "E16: Invalid range" +msgstr "E16: Plage invalide" -#~ msgid "Save File dialog" -#~ msgstr "Enregistrer un fichier" +msgid "E476: Invalid command" +msgstr "E476: Commande invalide" -#~ msgid "Open File dialog" -#~ msgstr "Ouvrir un fichier" +#, c-format +msgid "E17: \"%s\" is a directory" +msgstr "E17: \"%s\" est un r้pertoire" -#~ msgid "E338: Sorry, no file browser in console mode" -#~ msgstr "E338: D้sol้, pas de s้lecteur de fichiers en mode console" +#, c-format +msgid "E364: Library call failed for \"%s()\"" +msgstr "E364: L'appel เ la biblioth่que a ้chou้ pour \"%s()\"" -#~ msgid "ERROR: " -#~ msgstr "ERREUR : " +#, c-format +msgid "E448: Could not load library function %s" +msgstr "E448: Impossible de charger la fonction %s de la biblioth่que" -#~ msgid "" -#~ "\n" -#~ "[bytes] total alloc-freed %<PRIu64>-%<PRIu64>, in use %<PRIu64>, peak use " -#~ "%<PRIu64>\n" -#~ msgstr "" -#~ "\n" -#~ "[octets] total allou้-lib้r้ %<PRIu64>-%<PRIu64>, utilis้ %<PRIu64>, pic " -#~ "%<PRIu64>\n" +msgid "E19: Mark has invalid line number" +msgstr "E19: La marque a un num้ro de ligne invalide" -#~ msgid "" -#~ "[calls] total re/malloc()'s %<PRIu64>, total free()'s %<PRIu64>\n" -#~ "\n" -#~ msgstr "" -#~ "[appels] total re/malloc() %<PRIu64>, total free() %<PRIu64>\n" -#~ "\n" +msgid "E20: Mark not set" +msgstr "E20: Marque non positionn้e" -#~ msgid "E340: Line is becoming too long" -#~ msgstr "E340: La ligne devient trop longue" +msgid "E21: Cannot make changes, 'modifiable' is off" +msgstr "E21: Impossible de modifier, 'modifiable' est d้sactiv้" -#~ msgid "E341: Internal error: lalloc(%<PRId64>, )" -#~ msgstr "E341: Erreur interne : lalloc(%<PRId64>, )" +msgid "E22: Scripts nested too deep" +msgstr "E22: Trop de r้cursion dans les scripts" -#~ msgid "E547: Illegal mouseshape" -#~ msgstr "E547: Forme de curseur invalide" +msgid "E23: No alternate file" +msgstr "E23: Pas de fichier alternatif" -#~ msgid "Warning: Using a weak encryption method; see :help 'cm'" -#~ msgstr "" -#~ "Alerte : utilisation d'une m้thode de chiffrage faible ; consultez :help 'cm'" +msgid "E24: No such abbreviation" +msgstr "E24: Cette abr้viation n'existe pas" -#~ msgid "Enter encryption key: " -#~ msgstr "Tapez la cl้ de chiffrement : " +msgid "E477: No ! allowed" +msgstr "E477: Le ! n'est pas autoris้" -#~ msgid "Enter same key again: " -#~ msgstr "Tapez la cl้ เ nouveau : " +msgid "E25: GUI cannot be used: Not enabled at compile time" +msgstr "E25: L'interface graphique n'a pas ้t้ compil้e dans cette version" -#~ msgid "Keys don't match!" -#~ msgstr "Les cl้s ne correspondent pas !" +msgid "E26: Hebrew cannot be used: Not enabled at compile time\n" +msgstr "E26: Le support de l'h้breu n'a pas ้t้ compil้ dans cette version\n" -#~ msgid "Cannot connect to Netbeans #2" -#~ msgstr "Impossible de se connecter เ Netbeans nฐ2" +msgid "E27: Farsi cannot be used: Not enabled at compile time\n" +msgstr "E27: Le support du farsi n'a pas ้t้ compil้ dans cette version\n" -#~ msgid "Cannot connect to Netbeans" -#~ msgstr "Impossible de se connecter เ Netbeans" +msgid "E800: Arabic cannot be used: Not enabled at compile time\n" +msgstr "E800: Le support de l'arabe n'a pas ้t้ compil้ dans cette version\n" -#~ msgid "E668: Wrong access mode for NetBeans connection info file: \"%s\"" -#~ msgstr "" -#~ "E668: Mode d'acc่s incorrect au fichier d'infos de connexion NetBeans : " -#~ "\"%s\"" +#, c-format +msgid "E28: No such highlight group name: %s" +msgstr "E28: Aucun nom de groupe de surbrillance %s" -# DB : message d'un appel เ perror(). -#~ msgid "read from Netbeans socket" -#~ msgstr "read sur la socket Netbeans" +msgid "E29: No inserted text yet" +msgstr "E29: Pas encore de texte ins้r้" -#~ msgid "E658: NetBeans connection lost for buffer %<PRId64>" -#~ msgstr "E658: Connexion NetBeans perdue pour le tampon %<PRId64>" +msgid "E30: No previous command line" +msgstr "E30: Aucune ligne de commande pr้c้dente" -#~ msgid "E838: netbeans is not supported with this GUI" -#~ msgstr "E838: netbeans n'est pas support้ avec cette interface graphique" +msgid "E31: No such mapping" +msgstr "E31: Mappage inexistant" -#~ msgid "E511: netbeans already connected" -#~ msgstr "E511: netbeans d้jเ connect้" +msgid "E479: No match" +msgstr "E479: Aucune correspondance" -#~ msgid "E505: %s is read-only (add ! to override)" -#~ msgstr "E505: %s est en lecture seule (ajoutez ! pour passer outre)" +#, c-format +msgid "E480: No match: %s" +msgstr "E480: Aucune correspondance : %s" -#~ msgid "E775: Eval feature not available" -#~ msgstr "E775: La fonctionnalit้ d'้valuation n'est pas disponible" +msgid "E32: No file name" +msgstr "E32: Aucun nom de fichier" -#~ msgid "freeing %<PRId64> lines" -#~ msgstr "lib้ration de %<PRId64> lignes" +msgid "E33: No previous substitute regular expression" +msgstr "E33: Aucune expression r้guli่re de substitution pr้c้dente" -#~ msgid "E530: Cannot change term in GUI" -#~ msgstr "E530: Impossible de modifier term dans l'interface graphique" +msgid "E34: No previous command" +msgstr "E34: Aucune commande pr้c้dente" -#~ msgid "E531: Use \":gui\" to start the GUI" -#~ msgstr "E531: Utilisez \":gui\" pour d้marrer l'interface graphique" +msgid "E35: No previous regular expression" +msgstr "E35: Aucune expression r้guli่re pr้c้dente" -#~ msgid "E617: Cannot be changed in the GTK+ 2 GUI" -#~ msgstr "E617: Non modifiable dans l'interface graphique GTK+ 2" +msgid "E481: No range allowed" +msgstr "E481: Les plages ne sont pas autoris้es" -#~ msgid "E596: Invalid font(s)" -#~ msgstr "E596: Police(s) invalide(s)" +msgid "E36: Not enough room" +msgstr "E36: Pas assez de place" -#~ msgid "E597: can't select fontset" -#~ msgstr "E597: Impossible de s้lectionner un jeu de polices" +#, c-format +msgid "E247: no registered server named \"%s\"" +msgstr "E247: aucun serveur nomm้ \"%s\" n'est enregistr้" -#~ msgid "E598: Invalid fontset" -#~ msgstr "E598: Jeu de polices invalide" +#, c-format +msgid "E482: Can't create file %s" +msgstr "E482: Impossible de cr้er le fichier %s" -#~ msgid "E533: can't select wide font" -#~ msgstr "E533: Impossible de s้lectionner une police เ largeur double" +msgid "E483: Can't get temp file name" +msgstr "E483: Impossible d'obtenir un nom de fichier temporaire" -#~ msgid "E534: Invalid wide font" -#~ msgstr "E534: Police เ largeur double invalide" +#, c-format +msgid "E484: Can't open file %s" +msgstr "E484: Impossible d'ouvrir le fichier \"%s\"" -#~ msgid "E538: No mouse support" -#~ msgstr "E538: La souris n'est pas support้e" +#, c-format +msgid "E485: Can't read file %s" +msgstr "E485: Impossible de lire le fichier %s" -#~ msgid "cannot open " -#~ msgstr "impossible d'ouvrir " +msgid "E37: No write since last change (add ! to override)" +msgstr "E37: Modifications non enregistr้es (ajoutez ! pour passer outre)" -#~ msgid "VIM: Can't open window!\n" -#~ msgstr "VIM : Impossible d'ouvrir la fen๊tre !\n" +msgid "E37: No write since last change" +msgstr "E37: Modifications non enregistr้es" -#~ msgid "Need Amigados version 2.04 or later\n" -#~ msgstr "Amigados version 2.04 ou ult้rieure est n้cessaire\n" +msgid "E38: Null argument" +msgstr "E38: Argument null" -#~ msgid "Need %s version %<PRId64>\n" -#~ msgstr "%s version %<PRId64> est n้cessaire\n" +msgid "E39: Number expected" +msgstr "E39: Nombre attendu" -#~ msgid "Cannot open NIL:\n" -#~ msgstr "Impossible d'ouvrir NIL :\n" +#, c-format +msgid "E40: Can't open errorfile %s" +msgstr "E40: Impossible d'ouvrir le fichier d'erreurs %s" -#~ msgid "Cannot create " -#~ msgstr "Impossible de cr้er " +msgid "E233: cannot open display" +msgstr "E233: ouverture du display impossible" -#~ msgid "Vim exiting with %d\n" -#~ msgstr "Vim quitte avec %d\n" +msgid "E41: Out of memory!" +msgstr "E41: M้moire ้puis้e" -#~ msgid "cannot change console mode ?!\n" -#~ msgstr "Impossible de modifier le mode de la console ?!\n" +msgid "Pattern not found" +msgstr "Motif introuvable" -#~ msgid "mch_get_shellsize: not a console??\n" -#~ msgstr "mch_get_shellsize : pas une console ?!\n" +#, c-format +msgid "E486: Pattern not found: %s" +msgstr "E486: Motif introuvable : %s" -#~ msgid "E360: Cannot execute shell with -f option" -#~ msgstr "E360: Impossible d'ex้cuter un shell avec l'option -f" +msgid "E487: Argument must be positive" +msgstr "E487: L'argument doit ๊tre positif" -#~ msgid "Cannot execute " -#~ msgstr "Impossible d'ex้cuter " +msgid "E459: Cannot go back to previous directory" +msgstr "E459: Impossible de retourner au r้pertoire pr้c้dent" -#~ msgid "shell " -#~ msgstr "le shell " +msgid "E42: No Errors" +msgstr "E42: Aucune erreur" -#~ msgid " returned\n" -#~ msgstr " a ้t้ retourn้\n" +# DB - TODO : trouver une traduction valable et attest้e pour "location". +msgid "E776: No location list" +msgstr "E776: Aucune liste d'emplacements" -#~ msgid "ANCHOR_BUF_SIZE too small." -#~ msgstr "ANCHOR_BUF_SIZE trop petit." +msgid "E43: Damaged match string" +msgstr "E43: La cha๎ne de recherche est endommag้e" -#~ msgid "I/O ERROR" -#~ msgstr "ERREUR d'E/S" +msgid "E44: Corrupted regexp program" +msgstr "E44: L'automate de regexp est corrompu" -#~ msgid "Message" -#~ msgstr "Message" +msgid "E45: 'readonly' option is set (add ! to override)" +msgstr "E45: L'option 'readonly' est activ้e (ajoutez ! pour passer outre)" -#~ msgid "'columns' is not 80, cannot execute external commands" -#~ msgstr "" -#~ "'columns' ne vaut pas 80, impossible d'ex้cuter des commandes externes" +#, c-format +msgid "E46: Cannot change read-only variable \"%s\"" +msgstr "E46: La variable \"%s\" est en lecture seule" -#~ msgid "E237: Printer selection failed" -#~ msgstr "E237: La s้lection de l'imprimante a ้chou้" +#, c-format +msgid "E794: Cannot set variable in the sandbox: \"%s\"" +msgstr "" +"E794: Impossible de modifier une variable depuis le bac เ sable : \"%s\"" -# DB - Contenu des c-formats : Imprimante puis Port. -#~ msgid "to %s on %s" -#~ msgstr "vers %s sur %s" +msgid "E713: Cannot use empty key for Dictionary" +msgstr "E713: Impossible d'utiliser une cl้ vide dans un Dictionnaire" -#~ msgid "E613: Unknown printer font: %s" -#~ msgstr "E613: Police d'imprimante inconnue : %s" +msgid "E715: Dictionary required" +msgstr "E715: Dictionnaire requis" -#~ msgid "E238: Print error: %s" -#~ msgstr "E238: Erreur d'impression : %s" +#, c-format +msgid "E684: list index out of range: %ld" +msgstr "E684: index de Liste hors limites : %ld au-delเ de la fin" -#~ msgid "Printing '%s'" -#~ msgstr "Impression de '%s'" +# DB : Suggestion +#, c-format +msgid "E118: Too many arguments for function: %s" +msgstr "E118: La fonction %s a re็u trop d'arguments" -#~ msgid "E244: Illegal charset name \"%s\" in font name \"%s\"" -#~ msgstr "E244: Jeu de caract่res \"%s\" invalide dans le nom de fonte \"%s\"" +#, c-format +msgid "E716: Key not present in Dictionary: %s" +msgstr "E716: La cl้ %s n'existe pas dans le Dictionnaire" -#~ msgid "E245: Illegal char '%c' in font name \"%s\"" -#~ msgstr "E245: Caract่re '%c' invalide dans le nom de fonte \"%s\"" +msgid "E714: List required" +msgstr "E714: Liste requise" -#~ msgid "Opening the X display took %<PRId64> msec" -#~ msgstr "L'ouverture du display X a pris %<PRId64> ms" +#, c-format +msgid "E712: Argument of %s must be a List or Dictionary" +msgstr "E712: L'argument de %s doit ๊tre une Liste ou un Dictionnaire" -#~ msgid "" -#~ "\n" -#~ "Vim: Got X error\n" -#~ msgstr "" -#~ "\n" -#~ "Vim : R้ception d'une erreur X\n" +msgid "E47: Error while reading errorfile" +msgstr "E47: Erreur lors de la lecture du fichier d'erreurs" -#~ msgid "Testing the X display failed" -#~ msgstr "Le test du display X a ้chou้" +msgid "E48: Not allowed in sandbox" +msgstr "E48: Op้ration interdite dans le bac เ sable" -#~ msgid "Opening the X display timed out" -#~ msgstr "L'ouverture du display X a d้pass้ le d้lai d'attente" +msgid "E523: Not allowed here" +msgstr "E523: Interdit เ cet endroit" -#~ msgid "" -#~ "\n" -#~ "Cannot execute shell sh\n" -#~ msgstr "" -#~ "\n" -#~ "Impossible d'ex้cuter le shell sh\n" +msgid "E359: Screen mode setting not supported" +msgstr "E359: Choix du mode d'้cran non support้" -#~ msgid "" -#~ "\n" -#~ "Cannot create pipes\n" -#~ msgstr "" -#~ "\n" -#~ "Impossible de cr้er des tuyaux (pipes)\n" +msgid "E49: Invalid scroll size" +msgstr "E49: Valeur de d้filement invalide" -#~ msgid "" -#~ "\n" -#~ "Cannot fork\n" -#~ msgstr "" -#~ "\n" -#~ "Impossible de forker\n" +msgid "E91: 'shell' option is empty" +msgstr "E91: L'option 'shell' est vide" -#~ msgid "" -#~ "\n" -#~ "Command terminated\n" -#~ msgstr "" -#~ "\n" -#~ "Commande interrompue\n" +msgid "E255: Couldn't read in sign data!" +msgstr "E255: Impossible de lire les donn้es du symbole !" -#~ msgid "XSMP lost ICE connection" -#~ msgstr "XSMP a perdu la connexion ICE" +msgid "E72: Close error on swap file" +msgstr "E72: Erreur lors de la fermeture du fichier d'้change" -#~ msgid "Opening the X display failed" -#~ msgstr "L'ouverture du display X a ้chou้" +msgid "E73: tag stack empty" +msgstr "E73: La pile des marqueurs est vide" -#~ msgid "XSMP handling save-yourself request" -#~ msgstr "XSMP : prise en charge d'une requ๊te save-yourself" +msgid "E74: Command too complex" +msgstr "E74: Commande trop complexe" -#~ msgid "XSMP opening connection" -#~ msgstr "XSMP : ouverture de la connexion" +msgid "E75: Name too long" +msgstr "E75: Nom trop long" -#~ msgid "XSMP ICE connection watch failed" -#~ msgstr "XSMP : ้chec de la surveillance de connexion ICE" +msgid "E76: Too many [" +msgstr "E76: Trop de [" -#~ msgid "XSMP SmcOpenConnection failed: %s" -#~ msgstr "XSMP : SmcOpenConnection a ้chou้ : %s" +msgid "E77: Too many file names" +msgstr "E77: Trop de noms de fichiers" -#~ msgid "At line" -#~ msgstr "ภ la ligne" +msgid "E488: Trailing characters" +msgstr "E488: Caract่res surnum้raires" -#~ msgid "Could not load vim32.dll!" -#~ msgstr "Impossible de charger vim32.dll !" +msgid "E78: Unknown mark" +msgstr "E78: Marque inconnue" -#~ msgid "VIM Error" -#~ msgstr "Erreur VIM" +msgid "E79: Cannot expand wildcards" +msgstr "E79: Impossible de d้velopper les m้tacaract่res" -#~ msgid "Could not fix up function pointers to the DLL!" -#~ msgstr "Impossible d'initialiser les pointeurs de fonction vers la DLL !" +msgid "E591: 'winheight' cannot be smaller than 'winminheight'" +msgstr "E591: 'winheight' ne peut pas ๊tre plus petit que 'winminheight'" -#~ msgid "shell returned %d" -#~ msgstr "le shell a retourn้ %d" +msgid "E592: 'winwidth' cannot be smaller than 'winminwidth'" +msgstr "E592: 'winwidth' ne peut pas ๊tre plus petit que 'winminwidth'" -# DB - Les ้v้nements en question sont ceux des messages qui suivent. -#~ msgid "Vim: Caught %s event\n" -#~ msgstr "Vim : ษv้nement %s intercept้\n" +msgid "E80: Error while writing" +msgstr "E80: Erreur lors de l'้criture" -#~ msgid "close" -#~ msgstr "de fermeture" +msgid "Zero count" +msgstr "Le quantificateur est nul" -#~ msgid "logoff" -#~ msgstr "de d้connexion" +msgid "E81: Using <SID> not in a script context" +msgstr "E81: <SID> utilis้ en dehors d'un script" -#~ msgid "shutdown" -#~ msgstr "d'arr๊t" +msgid "E449: Invalid expression received" +msgstr "E449: Expression invalide re็ue" -#~ msgid "E371: Command not found" -#~ msgstr "E371: Commande introuvable" +msgid "E463: Region is guarded, cannot modify" +msgstr "E463: Cette zone est verrouill้e et ne peut pas ๊tre modifi้e" -#~ msgid "" -#~ "VIMRUN.EXE not found in your $PATH.\n" -#~ "External commands will not pause after completion.\n" -#~ "See :help win32-vimrun for more information." -#~ msgstr "" -#~ "VIMRUN.EXE est introuvable votre $PATH.\n" -#~ "Les commandes externes ne feront pas de pause une fois termin้es.\n" -#~ "Consultez :help win32-vimrun pour plus d'informations." +msgid "E744: NetBeans does not allow changes in read-only files" +msgstr "" +"E744: NetBeans n'autorise pas la modification des fichiers en lecture seule" -#~ msgid "Vim Warning" -#~ msgstr "Alerte Vim" +msgid "E363: pattern uses more memory than 'maxmempattern'" +msgstr "E363: le motif utilise plus de m้moire que 'maxmempattern'" -#~ msgid "Error file" -#~ msgstr "Fichier d'erreurs" +msgid "E749: empty buffer" +msgstr "E749: tampon vide" -#~ msgid "E868: Error building NFA with equivalence class!" -#~ msgstr "" -#~ "E868: Erreur lors de la construction du NFA avec classe d'้quivalence" +#, c-format +msgid "E86: Buffer %ld does not exist" +msgstr "E86: Le tampon %ld n'existe pas" -#~ msgid "E878: (NFA) Could not allocate memory for branch traversal!" -#~ msgstr "" -#~ "E878: (NFA) Impossible d'allouer la m้moire pour parcourir les branches!" +msgid "E682: Invalid search pattern or delimiter" +msgstr "E682: D้limiteur ou motif de recherche invalide" -#~ msgid "Warning: Cannot find word list \"%s_%s.spl\" or \"%s_ascii.spl\"" -#~ msgstr "" -#~ "Alerte : Liste de mots \"%s_%s.spl\" ou \"%s_ascii.spl\" introuvable" +msgid "E139: File is loaded in another buffer" +msgstr "E139: Le fichier est charg้ dans un autre tampon" -#~ msgid "Conversion in %s not supported" -#~ msgstr "La conversion dans %s non support้e" +#, c-format +msgid "E764: Option '%s' is not set" +msgstr "E764: L'option '%s' n'est pas activ้e" -#~ msgid "E845: Insufficient memory, word list will be incomplete" -#~ msgstr "E845: m้moire insuffisante, liste de mots peut-๊tre incompl่te" +msgid "E850: Invalid register name" +msgstr "E850: Nom de registre invalide" -#~ msgid "E430: Tag file path truncated for %s\n" -#~ msgstr "E430: Chemin de fichiers de marqueurs tronqu้ pour %s\n" +#, c-format +msgid "E919: Directory not found in '%s': \"%s\"" +msgstr "E919: R้pertoire introuvable dans '%s' : \"%s\"" -#~ msgid "new shell started\n" -#~ msgstr "nouveau shell d้marr้\n" +msgid "search hit TOP, continuing at BOTTOM" +msgstr "La recherche a atteint le HAUT, et continue en BAS" -# DB - Message de d้bogage. -#~ msgid "Used CUT_BUFFER0 instead of empty selection" -#~ msgstr "CUT_BUFFER0 utilis้ plut๔t qu'une s้lection vide" +msgid "search hit BOTTOM, continuing at TOP" +msgstr "La recherche a atteint le BAS, et continue en HAUT" -# DB - Question O/N. -#~ msgid "No undo possible; continue anyway" -#~ msgstr "Annulation impossible ; continuer" - -#~ msgid "E832: Non-encrypted file has encrypted undo file: %s" -#~ msgstr "E832: Fichier non-chiffr้ a un fichier d'annulations chiffr้ : %s" - -#~ msgid "E826: Undo file decryption failed: %s" -#~ msgstr "E826: D้chiffrage du fichier d'annulation a ้chou้ : %s" - -#~ msgid "E827: Undo file is encrypted: %s" -#~ msgstr "E827: Le fichier d'annulations est chiffr้ : %s" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 16/32-bit GUI version" -#~ msgstr "" -#~ "\n" -#~ "Version graphique MS-Windows 16/32 bits" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 64-bit GUI version" -#~ msgstr "" -#~ "\n" -#~ "Version graphique MS-Windows 64 bits" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 32-bit GUI version" -#~ msgstr "" -#~ "\n" -#~ "Version graphique MS-Windows 32 bits" - -#~ msgid " in Win32s mode" -#~ msgstr " lanc้e en mode Win32s" - -#~ msgid " with OLE support" -#~ msgstr " supportant l'OLE" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 64-bit console version" -#~ msgstr "" -#~ "\n" -#~ "Version console MS-Windows 64 bits" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 32-bit console version" -#~ msgstr "" -#~ "\n" -#~ "Version console MS-Windows 32 bits" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 16-bit version" -#~ msgstr "" -#~ "\n" -#~ "Version MS-Windows 16 bits" - -#~ msgid "" -#~ "\n" -#~ "32-bit MS-DOS version" -#~ msgstr "" -#~ "\n" -#~ "Version MS-DOS 32 bits" - -#~ msgid "" -#~ "\n" -#~ "16-bit MS-DOS version" -#~ msgstr "" -#~ "\n" -#~ "Version MS-DOS 16 bits" - -#~ msgid "" -#~ "\n" -#~ "MacOS X (unix) version" -#~ msgstr "" -#~ "\n" -#~ "Version MaxOS X (unix)" - -#~ msgid "" -#~ "\n" -#~ "MacOS X version" -#~ msgstr "" -#~ "\n" -#~ "Version MacOS X" - -#~ msgid "" -#~ "\n" -#~ "MacOS version" -#~ msgstr "" -#~ "\n" -#~ "Version MacOS" - -#~ msgid "" -#~ "\n" -#~ "OpenVMS version" -#~ msgstr "" -#~ "\n" -#~ "Version OpenVMS" - -#~ msgid "" -#~ "\n" -#~ "Big version " -#~ msgstr "" -#~ "\n" -#~ "Grosse version " - -#~ msgid "" -#~ "\n" -#~ "Normal version " -#~ msgstr "" -#~ "\n" -#~ "Version normale " - -#~ msgid "" -#~ "\n" -#~ "Small version " -#~ msgstr "" -#~ "\n" -#~ "Petite version " - -#~ msgid "" -#~ "\n" -#~ "Tiny version " -#~ msgstr "" -#~ "\n" -#~ "Version minuscule " - -#~ msgid "with GTK2-GNOME GUI." -#~ msgstr "avec interface graphique GTK2-GNOME." - -#~ msgid "with GTK2 GUI." -#~ msgstr "avec interface graphique GTK2." - -#~ msgid "with X11-Motif GUI." -#~ msgstr "avec interface graphique X11-Motif." - -#~ msgid "with X11-neXtaw GUI." -#~ msgstr "avec interface graphique X11-neXtaw." - -#~ msgid "with X11-Athena GUI." -#~ msgstr "avec interface graphique X11-Athena." - -#~ msgid "with Photon GUI." -#~ msgstr "avec interface graphique Photon." - -#~ msgid "with GUI." -#~ msgstr "avec une interface graphique." - -#~ msgid "with Carbon GUI." -#~ msgstr "avec interface graphique Carbon." - -#~ msgid "with Cocoa GUI." -#~ msgstr "avec interface graphique Cocoa." - -#~ msgid "with (classic) GUI." -#~ msgstr "avec interface graphique (classic)." - -#~ msgid " system gvimrc file: \"" -#~ msgstr " fichier gvimrc syst่me : \"" - -#~ msgid " user gvimrc file: \"" -#~ msgstr " fichier gvimrc utilisateur : \"" - -#~ msgid "2nd user gvimrc file: \"" -#~ msgstr "2me fichier gvimrc utilisateur : \"" - -#~ msgid "3rd user gvimrc file: \"" -#~ msgstr "3me fichier gvimrc utilisateur : \"" - -#~ msgid " system menu file: \"" -#~ msgstr " fichier menu syst่me : \"" - -#~ msgid "Compiler: " -#~ msgstr "Compilateur : " +#, c-format +msgid "Need encryption key for \"%s\"" +msgstr "Besoin de la cl้ de chiffrement pour \"%s\"" -#~ msgid "menu Help->Orphans for information " -#~ msgstr "menu Aide->Orphelins pour plus d'info" +msgid "empty keys are not allowed" +msgstr "les cl้s vides ne sont pas autoris้es" -#~ msgid "Running modeless, typed text is inserted" -#~ msgstr "Les modes sont d้sactiv้s, le texte saisi est ins้r้" +msgid "dictionary is locked" +msgstr "dictionnaire est verrouill้" -#~ msgid "menu Edit->Global Settings->Toggle Insert Mode " -#~ msgstr "menu ษdition->R้glages Globaux->Insertion Permanente" +msgid "list is locked" +msgstr "liste verrouill้e" -# DB - todo -#~ msgid " for two modes " -#~ msgstr " pour les modes " +#, c-format +msgid "failed to add key '%s' to dictionary" +msgstr "l'ajout de cl้ '%s' au dictionnaire a ้chou้" -# DB - todo -#~ msgid "menu Edit->Global Settings->Toggle Vi Compatible" -#~ msgstr "menu ษdition->R้glages Globaux->Compatibilit้ Vi" +#, c-format +msgid "index must be int or slice, not %s" +msgstr "index doit ๊tre int ou slice, et non %s" -# DB - todo -#~ msgid " for Vim defaults " -#~ msgstr " pour d้f. de Vim " +#, c-format +msgid "expected str() or unicode() instance, but got %s" +msgstr "attendu instance de str() ou unicode(), mais re็u %s" -#~ msgid "WARNING: Windows 95/98/ME detected" -#~ msgstr "ALERTE: Windows 95/98/ME d้tect้" +#, c-format +msgid "expected bytes() or str() instance, but got %s" +msgstr "attendu instance de bytes() ou str(), mais re็u %s" -#~ msgid "type :help windows95<Enter> for info on this" -#~ msgstr "tapez :help windows95<Entr้e> pour plus d'information" +#, c-format +msgid "" +"expected int(), long() or something supporting coercing to long(), but got %s" +msgstr "" +"attendu int(), long() ou quelque chose qui peut ๊tre transform้ en long(), " +"mais re็u %s" -#~ msgid "E370: Could not load library %s" -#~ msgstr "E370: Impossible de charger la biblioth่que %s" +#, c-format +msgid "expected int() or something supporting coercing to int(), but got %s" +msgstr "" +"attendu int() ou quelque chose qui peut ๊tre transform้ en int(), mais re็u " +"%s" -#~ msgid "" -#~ "Sorry, this command is disabled: the Perl library could not be loaded." -#~ msgstr "" -#~ "D้sol้, commande d้sactiv้e : la biblioth่que Perl n'a pas pu ๊tre " -#~ "charg้e." +msgid "value is too large to fit into C int type" +msgstr "valeur trop grande pour ๊tre stock้e dans le type C int" -#~ msgid "E299: Perl evaluation forbidden in sandbox without the Safe module" -#~ msgstr "" -#~ "E299: ษvaluation Perl interdite dans bac เ sable sans le module Safe" +msgid "value is too small to fit into C int type" +msgstr "valeur trop petite pour ๊tre stock้e dans le type C int" -#~ msgid "Edit with &multiple Vims" -#~ msgstr "ษditer dans &plusieurs Vims" +msgid "number must be greater than zero" +msgstr "le nombre doit ๊tre plus grand que z้ro" -#~ msgid "Edit with single &Vim" -#~ msgstr "ษditer dans un seul &Vim" +msgid "number must be greater or equal to zero" +msgstr "le nombre doit ๊tre plus grand ou ้gal เ z้ro" -#~ msgid "Diff with Vim" -#~ msgstr "&Comparer avec Vim" +msgid "can't delete OutputObject attributes" +msgstr "impossible d'effacer les attributs d'OutputObject" -#~ msgid "Edit with &Vim" -#~ msgstr "ษditer dans &Vim" +#, c-format +msgid "invalid attribute: %s" +msgstr "attribut invalide : %s" -#~ msgid "Edit with existing Vim - " -#~ msgstr "ษditer dans le Vim existant - " +msgid "E264: Python: Error initialising I/O objects" +msgstr "E264: Python : Erreur d'initialisation des objets d'E/S" -#~ msgid "Edits the selected file(s) with Vim" -#~ msgstr "ษdites le(s) fichier(s) s้lectionn้(s) avec Vim" +msgid "failed to change directory" +msgstr "changement de r้pertoire a ้chou้" -# DB - MessageBox win32, la longueur n'est pas un probl่me ! -#~ msgid "Error creating process: Check if gvim is in your path!" -#~ msgstr "" -#~ "Erreur de cr้ation du processus : v้rifiez que gvim est bien dans votre " -#~ "chemin !" +#, c-format +msgid "expected 3-tuple as imp.find_module() result, but got %s" +msgstr "attendu un 3-tuple comme r้sultat de imp.find_module(), mais re็u %s" -#~ msgid "gvimext.dll error" -#~ msgstr "Erreur de gvimext.dll" +#, c-format +msgid "expected 3-tuple as imp.find_module() result, but got tuple of size %d" +msgstr "" +"attendu un 3-tuple comme r้sultat de imp.find_module(), mais re็u un tuple " +"de taille %d" -#~ msgid "Path length too long!" -#~ msgstr "Le chemin est trop long !" +msgid "internal error: imp.find_module returned tuple with NULL" +msgstr "erreur interne : imp.find_module a retourn้ un tuple contenant NULL" -#~ msgid "E234: Unknown fontset: %s" -#~ msgstr "E234: Jeu de police inconnu : %s" +msgid "cannot delete vim.Dictionary attributes" +msgstr "impossible d'effacer les attributs de vim.Dictionary" -#~ msgid "E235: Unknown font: %s" -#~ msgstr "E235: Police inconnue : %s" +msgid "cannot modify fixed dictionary" +msgstr "impossible de modifier un dictionnaire fixe" -#~ msgid "E236: Font \"%s\" is not fixed-width" -#~ msgstr "E236: La police \"%s\" n'a pas une chasse (largeur) fixe" +#, c-format +msgid "cannot set attribute %s" +msgstr "impossible d'initialiser l'attribut %s" -#~ msgid "E448: Could not load library function %s" -#~ msgstr "E448: Impossible de charger la fonction %s de la biblioth่que" +msgid "hashtab changed during iteration" +msgstr "la table de hachage a ้t้ chang้e pendant une it้ration" -#~ msgid "E26: Hebrew cannot be used: Not enabled at compile time\n" -#~ msgstr "" -#~ "E26: Le support de l'h้breu n'a pas ้t้ compil้ dans cette version\n" +#, c-format +msgid "expected sequence element of size 2, but got sequence of size %d" +msgstr "" +"attendu une s้quence d'้l้ments de taille 2, mais re็u une s้quence de " +"taille %d" -#~ msgid "E27: Farsi cannot be used: Not enabled at compile time\n" -#~ msgstr "E27: Le support du farsi n'a pas ้t้ compil้ dans cette version\n" +msgid "list constructor does not accept keyword arguments" +msgstr "le constructeur de liste n'accepte pas les arguments nomm้s" -#~ msgid "E800: Arabic cannot be used: Not enabled at compile time\n" -#~ msgstr "" -#~ "E800: Le support de l'arabe n'a pas ้t้ compil้ dans cette version\n" +msgid "list index out of range" +msgstr "index de liste hors limites" -#~ msgid "E247: no registered server named \"%s\"" -#~ msgstr "E247: aucun serveur nomm้ \"%s\" n'est enregistr้" +#. No more suitable format specifications in python-2.3 +#, c-format +msgid "internal error: failed to get vim list item %d" +msgstr "erreur interne : acc่s เ un ้l้ment %d de liste a ้chou้" -#~ msgid "E233: cannot open display" -#~ msgstr "E233: ouverture du display impossible" +msgid "slice step cannot be zero" +msgstr "le pas du d้coupage en tranche ne peut pas ๊tre z้ro" -#~ msgid "E449: Invalid expression received" -#~ msgstr "E449: Expression invalide re็ue" +#, c-format +msgid "attempt to assign sequence of size greater than %d to extended slice" +msgstr "" +"tentative d'assigner une s้quence de taille plus grande que %d เ un " +"d้coupage en tranche ้tendu " -#~ msgid "E463: Region is guarded, cannot modify" -#~ msgstr "E463: Cette zone est verrouill้e et ne peut pas ๊tre modifi้e" +#, c-format +msgid "internal error: no vim list item %d" +msgstr "erreur interne : pas d'้l้ment %d de liste vim" -#~ msgid "E744: NetBeans does not allow changes in read-only files" -#~ msgstr "" -#~ "E744: NetBeans n'autorise pas la modification des fichiers en lecture " -#~ "seule" +msgid "internal error: not enough list items" +msgstr "erreur interne : pas assez d'้l้ments de liste" -#~ msgid "Need encryption key for \"%s\"" -#~ msgstr "Besoin de la cl้ de chiffrement pour \"%s\"" +msgid "internal error: failed to add item to list" +msgstr "erreur interne : ajout d'้l้ment เ la liste a ้chou้" -#~ msgid "can't delete OutputObject attributes" -#~ msgstr "impossible d'effacer les attributs d'OutputObject" +#, c-format +msgid "attempt to assign sequence of size %d to extended slice of size %d" +msgstr "" +"tentative d'assigner une s้quence de taille %d เ un d้coupage en tranche " +"้tendu de taille %d" -#~ msgid "invalid attribute" -#~ msgstr "attribut invalide" +msgid "failed to add item to list" +msgstr "ajout เ la liste a ้chou้" -#~ msgid "E264: Python: Error initialising I/O objects" -#~ msgstr "E264: Python : Erreur d'initialisation des objets d'E/S" +msgid "cannot delete vim.List attributes" +msgstr "impossible d'effacer les attributs de vim.List" -#~ msgid "empty keys are not allowed" -#~ msgstr "les cl้s vides ne sont pas autoris้es" +msgid "cannot modify fixed list" +msgstr "impossible de modifier une liste fixe" -#~ msgid "Cannot modify fixed dictionary" -#~ msgstr "Impossible de modifier un dictionnaire fixe" +#, c-format +msgid "unnamed function %s does not exist" +msgstr "la fonction sans nom %s n'existe pas" -#~ msgid "dict is locked" -#~ msgstr "dictionnaire est verrouill้" +#, c-format +msgid "function %s does not exist" +msgstr "la fonction %s n'existe pas" -#~ msgid "failed to add key to dictionary" -#~ msgstr "l'ajout de cl้ au dictionnaire a ้chou้" +#, c-format +msgid "failed to run function %s" +msgstr "ex้cution de la fonction %s a ้chou้" -#~ msgid "list index out of range" -#~ msgstr "index de liste hors limites" +msgid "unable to get option value" +msgstr "impossible d'obtenir la valeur d'une option" -#~ msgid "internal error: failed to get vim list item" -#~ msgstr "erreur interne : acc่s เ un ้l้ment de liste a ้chou้" +msgid "internal error: unknown option type" +msgstr "erreur interne : type d'option inconnu" -#~ msgid "list is locked" -#~ msgstr "liste verrouill้e" +msgid "problem while switching windows" +msgstr "probl่me lors du changement de fen๊tres" -#~ msgid "Failed to add item to list" -#~ msgstr "Ajout เ la liste a ้chou้" +#, c-format +msgid "unable to unset global option %s" +msgstr "impossible de d้sactiver une option globale %s" -#~ msgid "internal error: failed to add item to list" -#~ msgstr "erreur interne : ajout d'้l้ment เ la liste a ้chou้" +#, c-format +msgid "unable to unset option %s which does not have global value" +msgstr "impossible de d้sactiver l'option %s qui n'a pas de valeur globale" -#~ msgid "cannot delete vim.dictionary attributes" -#~ msgstr "impossible d'effacer les attributs de vim.dictionary" +msgid "attempt to refer to deleted tab page" +msgstr "tentative de r้f้rencer un onglet effac้" -#~ msgid "cannot modify fixed list" -#~ msgstr "impossible de modifier une liste fixe" +msgid "no such tab page" +msgstr "cet onglet n'existe pas" -#~ msgid "cannot set this attribute" -#~ msgstr "impossible d'initialiser cet attribut" +msgid "attempt to refer to deleted window" +msgstr "tentative de r้f้rencer une fen๊tre effac้e" -#~ msgid "failed to run function" -#~ msgstr "ex้cution de la fonction a ้chou้" +msgid "readonly attribute: buffer" +msgstr "attribut en lecture seule : tampon" -#~ msgid "unable to unset global option" -#~ msgstr "impossible de d้sactiver une option globale" +msgid "cursor position outside buffer" +msgstr "curseur positionn้ en dehors du tampon" -#~ msgid "unable to unset option without global value" -#~ msgstr "impossible de d้sactiver une option sans une valeur globale" +msgid "no such window" +msgstr "Cette fen๊tre n'existe pas" -#~ msgid "attempt to refer to deleted tab page" -#~ msgstr "tentative de r้f้rencer un onglet effac้" +msgid "attempt to refer to deleted buffer" +msgstr "tentative de r้f้rencer un tampon effac้" -#~ msgid "no such tab page" -#~ msgstr "cet onglet n'existe pas" +msgid "failed to rename buffer" +msgstr "impossible de renommer le tampon" -#~ msgid "attempt to refer to deleted window" -#~ msgstr "tentative de r้f้rencer une fen๊tre effac้e" +msgid "mark name must be a single character" +msgstr "le nom de marque doit ๊tre un seul caract่re" -#~ msgid "readonly attribute" -#~ msgstr "attribut en lecture seule" +#, c-format +msgid "expected vim.Buffer object, but got %s" +msgstr "attendu un objet vim.Buffer, mais re็u %s" -#~ msgid "cursor position outside buffer" -#~ msgstr "curseur positionn้ en dehors du tampon" +#, c-format +msgid "failed to switch to buffer %d" +msgstr "impossible de se d้placer au tampon %d" -#~ msgid "no such window" -#~ msgstr "Cette fen๊tre n'existe pas" +#, c-format +msgid "expected vim.Window object, but got %s" +msgstr "attendu un objet vim.Window, mais re็u %s" -#~ msgid "attempt to refer to deleted buffer" -#~ msgstr "tentative de r้f้rencer un tampon effac้" +msgid "failed to find window in the current tab page" +msgstr "impossible de trouver une fen๊tre dans l'onglet courant" -#~ msgid "expected vim.buffer object" -#~ msgstr "objet vim.buffer attendu" +msgid "did not switch to the specified window" +msgstr "ne s'est pas d้plac้ เ la fen๊tre sp้cifi้e" -#~ msgid "failed to switch to given buffer" -#~ msgstr "impossible de se d้placer au tampon donn้" +#, c-format +msgid "expected vim.TabPage object, but got %s" +msgstr "attendu un objet vim.TabPage, mais re็u %s" -#~ msgid "expected vim.window object" -#~ msgstr "objet vim.window attendu" +msgid "did not switch to the specified tab page" +msgstr "impossible de se d้placer เ l'onglet sp้cifi้" -#~ msgid "failed to find window in the current tab page" -#~ msgstr "impossible de trouver une fen๊tre dans l'onglet courant" +msgid "failed to run the code" +msgstr "ex้cution du code a ้chou้" -#~ msgid "did not switch to the specified window" -#~ msgstr "ne s'est pas d้plac้ เ la fen๊tre sp้cifi้e" +msgid "E858: Eval did not return a valid python object" +msgstr "E858: Eval n'a pas retourn้ un objet python valide" -#~ msgid "expected vim.tabpage object" -#~ msgstr "objet vim.tabpage attendu" +msgid "E859: Failed to convert returned python object to vim value" +msgstr "E859: Conversion d'objet python เ une valeur de vim a ้chou้" -#~ msgid "did not switch to the specified tab page" -#~ msgstr "impossible de se d้placer เ l'onglet sp้cifi้" +#, c-format +msgid "unable to convert %s to vim dictionary" +msgstr "impossible de convertir %s เ un dictionnaire vim" -#~ msgid "failed to run the code" -#~ msgstr "ex้cution du code a ้chou้" +#, c-format +msgid "unable to convert %s to vim list" +msgstr "impossible de convertir %s เ une liste de vim" -#~ msgid "E858: Eval did not return a valid python object" -#~ msgstr "E858: Eval n'a pas retourn้ un objet python valide" +#, c-format +msgid "unable to convert %s to vim structure" +msgstr "impossible de convertir %s เ une structure de vim" -#~ msgid "E859: Failed to convert returned python object to vim value" -#~ msgstr "E859: Conversion d'objet python เ une valeur de vim a ้chou้" +msgid "internal error: NULL reference passed" +msgstr "erreur interne : r้f้rence NULL pass้e" -#~ msgid "unable to convert to vim structure" -#~ msgstr "conversion เ une structure vim impossible" +msgid "internal error: invalid value type" +msgstr "erreur interne : type de valeur invalide" -#~ msgid "NULL reference passed" -#~ msgstr "r้f้rence NULL pass้e" +msgid "" +"Failed to set path hook: sys.path_hooks is not a list\n" +"You should now do the following:\n" +"- append vim.path_hook to sys.path_hooks\n" +"- append vim.VIM_SPECIAL_PATH to sys.path\n" +msgstr "" +"Impossible d'initialiser sys.path_hook qui n'est pas un liste\n" +"Vous devez maintenant :\n" +"- ajouter vim.path_hook เ sys.path_hooks\n" +"- ajouter vim.VIM_SPECIAL_PATH เ sys.path\n" -#~ msgid "internal error: invalid value type" -#~ msgstr "erreur interne : type de valeur invalide" +msgid "" +"Failed to set path: sys.path is not a list\n" +"You should now append vim.VIM_SPECIAL_PATH to sys.path" +msgstr "" +"Impossible d'initialiser le chemin : sys.math n'est pas une liste\n" +"Vous devez maintenant ajouter vim.VIM_SPECIAL_PATH เ sys.path" diff --git a/src/nvim/po/ga.po b/src/nvim/po/ga.po index 761539039d..abb3565077 100644 --- a/src/nvim/po/ga.po +++ b/src/nvim/po/ga.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: vim 7.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-05-26 14:21+0200\n" +"POT-Creation-Date: 2016-10-25 09:31-0500\n" "PO-Revision-Date: 2010-04-14 10:01-0500\n" "Last-Translator: Kevin Patrick Scannell <kscanne@gmail.com>\n" "Language-Team: Irish <gaeilge-gnulinux@lists.sourceforge.net>\n" @@ -14,208 +14,171 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=ISO-8859-1\n" "Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=5; plural=n==1 ? 0 : n==2 ? 1 : (n>2 && n<7) ? 2 :" +"(n>6 && n<11) ? 3 : 4;\n" -#: ../api/private/helpers.c:201 -#, fuzzy -msgid "Unable to get option value" -msgstr "Dramhaํl i ndiaidh arg๓inte rogha" +msgid "E831: bf_key_init() called with empty password" +msgstr "E831: cuireadh glaoch ar bf_key_init() le focal faire folamh" -#: ../api/private/helpers.c:204 -msgid "internal error: unknown option type" -msgstr "" +msgid "E820: sizeof(uint32_t) != 4" +msgstr "E820: sizeof(uint32_t) != 4" + +msgid "E817: Blowfish big/little endian use wrong" +msgstr "E817: ฺsแid mhํcheart Blowfish m๓rcheannach/caolcheannach" + +msgid "E818: sha256 test failed" +msgstr "E818: Theip ar thแstแil sha256" + +msgid "E819: Blowfish test failed" +msgstr "E819: Theip ar thแstแil Blowfish" -#: ../buffer.c:92 msgid "[Location List]" msgstr "[Liosta Suํomh]" -#: ../buffer.c:93 msgid "[Quickfix List]" -msgstr "[Liosta Ceart๚chแn Tapa]" +msgstr "[Liosta Mearcheart๚chแn]" -#: ../buffer.c:94 -#, fuzzy msgid "E855: Autocommands caused command to abort" -msgstr "E812: Bhํ maolแn n๓ ainm maolแin athraithe ag orduithe uathoibrํocha" +msgstr "E855: Tobscoireadh an t-ord๚ mar gheall ar uathorduithe" -#: ../buffer.c:135 msgid "E82: Cannot allocate any buffer, exiting..." msgstr "E82: Nํ f้idir maolแn a dhแileadh, ag scor..." -#: ../buffer.c:138 msgid "E83: Cannot allocate buffer, using other one..." msgstr "E83: Nํ f้idir maolแn a dhแileadh, ag ๚sแid cinn eile..." -#: ../buffer.c:763 +msgid "E931: Buffer cannot be registered" +msgstr "E931: Nํ f้idir an maolแn a chlแr๚" + +msgid "E937: Attempt to delete a buffer that is in use" +msgstr "E937: Iarracht ar mhaolแn in ๚sแid a scriosadh" + msgid "E515: No buffers were unloaded" msgstr "E515: Nํ raibh aon mhaolแn dํluchtaithe" -#: ../buffer.c:765 msgid "E516: No buffers were deleted" msgstr "E516: Nํ raibh aon mhaolแn scriosta" -#: ../buffer.c:767 msgid "E517: No buffers were wiped out" msgstr "E517: Nํ raibh aon mhaolแn bแnaithe" -#: ../buffer.c:772 msgid "1 buffer unloaded" msgstr "Bhํ maolแn amhแin dํluchtaithe" -#: ../buffer.c:774 #, c-format msgid "%d buffers unloaded" msgstr "%d maolแn folmhaithe" -#: ../buffer.c:777 msgid "1 buffer deleted" msgstr "Bhํ maolแn amhแin scriosta" -#: ../buffer.c:779 #, c-format msgid "%d buffers deleted" msgstr "%d maolแn scriosta" -#: ../buffer.c:782 msgid "1 buffer wiped out" msgstr "Bhํ maolแn amhแin bแnaithe" -#: ../buffer.c:784 #, c-format msgid "%d buffers wiped out" msgstr "%d maolแn bแnaithe" -#: ../buffer.c:806 msgid "E90: Cannot unload last buffer" msgstr "E90: Nํ f้idir an maolแn deireanach a dhํlucht๚" -#: ../buffer.c:874 msgid "E84: No modified buffer found" msgstr "E84: Nํor aimsํodh maolแn mionathraithe" #. back where we started, didn't find anything. -#: ../buffer.c:903 msgid "E85: There is no listed buffer" msgstr "E85: Nํl aon mhaolแn liostaithe ann" -#: ../buffer.c:913 -#, c-format -msgid "E86: Buffer %<PRId64> does not exist" -msgstr "E86: Nํl a leith้id de mhaolแn %<PRId64>" - -#: ../buffer.c:915 msgid "E87: Cannot go beyond last buffer" msgstr "E87: Nํ f้idir a dhul thar an maolแn deireanach" -#: ../buffer.c:917 msgid "E88: Cannot go before first buffer" msgstr "E88: Nํ f้idir a dhul roimh an ch้ad mhaolแn" -#: ../buffer.c:945 #, c-format -msgid "" -"E89: No write since last change for buffer %<PRId64> (add ! to override)" +msgid "E89: No write since last change for buffer %ld (add ! to override)" msgstr "" -"E89: Athraํodh maolแn %<PRId64> ach nach bhfuil s้ sแbhแilte ๓ shin (cuir ! " -"leis an ord๚ chun sแr๚)" +"E89: Athraํodh maolแn %ld ach nach bhfuil s้ sแbhแilte ๓ shin (cuir ! leis " +"an ord๚ chun sแr๚)" -#. wrap around (may cause duplicates) -#: ../buffer.c:1423 msgid "W14: Warning: List of file names overflow" msgstr "W14: Rabhadh: Liosta ainmneacha comhaid thar maoil" -#: ../buffer.c:1555 ../quickfix.c:3361 #, c-format -msgid "E92: Buffer %<PRId64> not found" -msgstr "E92: Maolแn %<PRId64> gan aimsi๚" +msgid "E92: Buffer %ld not found" +msgstr "E92: Maolแn %ld gan aimsi๚" -#: ../buffer.c:1798 #, c-format msgid "E93: More than one match for %s" msgstr "E93: Nํos m๓ nแ teaghrแn amhแin comhoiri๚naithe le %s" -#: ../buffer.c:1800 #, c-format msgid "E94: No matching buffer for %s" msgstr "E94: Nํl aon mhaolแn comhoiri๚naithe le %s" -#: ../buffer.c:2161 #, c-format -msgid "line %<PRId64>" -msgstr "lํne %<PRId64>:" +msgid "line %ld" +msgstr "lํne %ld:" -#: ../buffer.c:2233 msgid "E95: Buffer with this name already exists" msgstr "E95: Tแ maolแn ann leis an ainm seo cheana" -#: ../buffer.c:2498 msgid " [Modified]" msgstr " [Mionathraithe]" -#: ../buffer.c:2501 msgid "[Not edited]" msgstr "[Gan eagr๚]" -#: ../buffer.c:2504 msgid "[New file]" msgstr "[Comhad nua]" -#: ../buffer.c:2505 msgid "[Read errors]" msgstr "[Earrแidํ l้imh]" -#: ../buffer.c:2506 ../buffer.c:3217 ../fileio.c:1807 ../screen.c:4895 msgid "[RO]" msgstr "[L-A]" -#: ../buffer.c:2507 ../fileio.c:1807 msgid "[readonly]" msgstr "[inl้ite amhแin]" -#: ../buffer.c:2524 #, c-format msgid "1 line --%d%%--" msgstr "1 lํne --%d%%--" -#: ../buffer.c:2526 #, c-format -msgid "%<PRId64> lines --%d%%--" -msgstr "%<PRId64> lํne --%d%%--" +msgid "%ld lines --%d%%--" +msgstr "%ld lํne --%d%%--" -#: ../buffer.c:2530 #, c-format -msgid "line %<PRId64> of %<PRId64> --%d%%-- col " -msgstr "lํne %<PRId64> de %<PRId64> --%d%%-- col " +msgid "line %ld of %ld --%d%%-- col " +msgstr "lํne %ld de %ld --%d%%-- col " -#: ../buffer.c:2632 ../buffer.c:4292 ../memline.c:1554 msgid "[No Name]" msgstr "[Gan Ainm]" #. must be a help buffer -#: ../buffer.c:2667 msgid "help" msgstr "cabhair" -#: ../buffer.c:3225 ../screen.c:4883 msgid "[Help]" msgstr "[Cabhair]" -#: ../buffer.c:3254 ../screen.c:4887 msgid "[Preview]" msgstr "[R้amhamharc]" -#: ../buffer.c:3528 msgid "All" msgstr "Uile" -#: ../buffer.c:3528 msgid "Bot" msgstr "Bun" -#: ../buffer.c:3531 msgid "Top" msgstr "Barr" -#: ../buffer.c:4244 msgid "" "\n" "# Buffer list:\n" @@ -223,11 +186,9 @@ msgstr "" "\n" "# Liosta maolแin:\n" -#: ../buffer.c:4289 msgid "[Scratch]" msgstr "[Sealadach]" -#: ../buffer.c:4529 msgid "" "\n" "--- Signs ---" @@ -235,202 +196,236 @@ msgstr "" "\n" "--- Comharthaํ ---" -#: ../buffer.c:4538 #, c-format msgid "Signs for %s:" msgstr "Comharthaํ do %s:" -#: ../buffer.c:4543 #, c-format -msgid " line=%<PRId64> id=%d name=%s" -msgstr " lํne=%<PRId64> id=%d ainm=%s" +msgid " line=%ld id=%d name=%s" +msgstr " lํne=%ld id=%d ainm=%s" -#: ../cursor_shape.c:68 -msgid "E545: Missing colon" -msgstr "E545: Idirstad ar iarraidh" +msgid "E902: Cannot connect to port" +msgstr "E902: Nํ f้idir ceangal leis an bport" -#: ../cursor_shape.c:70 ../cursor_shape.c:94 -msgid "E546: Illegal mode" -msgstr "E546: M๓d neamhcheadaithe" +msgid "E901: gethostbyname() in channel_open()" +msgstr "E901: gethostbyname() in channel_open()" -#: ../cursor_shape.c:134 -msgid "E548: digit expected" -msgstr "E548: ag s๚il le digit" +msgid "E898: socket() in channel_open()" +msgstr "E898: socket() in channel_open()" -#: ../cursor_shape.c:138 -msgid "E549: Illegal percentage" -msgstr "E549: C้atadแn neamhcheadaithe" +msgid "E903: received command with non-string argument" +msgstr "E903: fuarthas ord๚ le harg๓int nach bhfuil ina theaghrแn" + +msgid "E904: last argument for expr/call must be a number" +msgstr "E904: nํ m๓r don arg๓int dheireanach ar expr/call a bheith ina huimhir" + +msgid "E904: third argument for call must be a list" +msgstr "E904: Caithfidh an trํ๚ arg๓int a bheith ina liosta" + +#, c-format +msgid "E905: received unknown command: %s" +msgstr "E905: fuarthas ord๚ anaithnid: %s" + +#, c-format +msgid "E630: %s(): write while not connected" +msgstr "E630: %s(): scrํobh gan ceangal a bheith ann" + +#, c-format +msgid "E631: %s(): write failed" +msgstr "E631: %s(): theip ar scrํobh" + +#, c-format +msgid "E917: Cannot use a callback with %s()" +msgstr "E917: Nํ f้idir aisghlaoch a ๚sแid le %s()" + +msgid "E912: cannot use ch_evalexpr()/ch_sendexpr() with a raw or nl channel" +msgstr "E912: nํ f้idir ch_evalexpr()/ch_sendexpr() a ๚sแid le cain้al raw n๓ nl" + +msgid "E906: not an open channel" +msgstr "E906: nํ cain้al oscailte ้" + +msgid "E920: _io file requires _name to be set" +msgstr "E920: caithfear _name a shocr๚ chun comhad _io a ๚sแid" + +msgid "E915: in_io buffer requires in_buf or in_name to be set" +msgstr "E915: caithfear in_buf n๓ in_name a shocr๚ chun maolแn in_io a ๚sแid" + +#, c-format +msgid "E918: buffer must be loaded: %s" +msgstr "E918: nํ m๓r an maolแn a lucht๚: %s" + +msgid "E821: File is encrypted with unknown method" +msgstr "E821: Comhad criptithe le modh anaithnid" + +msgid "Warning: Using a weak encryption method; see :help 'cm'" +msgstr "Rabhadh: Cripti๚chแn lag; f้ach :help 'cm'" + +msgid "Enter encryption key: " +msgstr "Iontrแil eochair chripti๚chแin: " + +msgid "Enter same key again: " +msgstr "Iontrแil an eochair arํs: " + +msgid "Keys don't match!" +msgstr "Nํl na heochracha comhoiri๚nach le ch้ile!" + +msgid "[crypted]" +msgstr "[criptithe]" -#: ../diff.c:146 #, c-format -msgid "E96: Can not diff more than %<PRId64> buffers" -msgstr "E96: Nํ f้idir diff a dh้anamh ar nํos m๓ nแ %<PRId64> maolแn" +msgid "E720: Missing colon in Dictionary: %s" +msgstr "E720: Idirstad ar iarraidh i bhFocl๓ir: %s" + +#, c-format +msgid "E721: Duplicate key in Dictionary: \"%s\"" +msgstr "E721: Eochair dh๚blach i bhFocl๓ir: \"%s\"" + +#, c-format +msgid "E722: Missing comma in Dictionary: %s" +msgstr "E722: Cam๓g ar iarraidh i bhFocl๓ir: %s" + +#, c-format +msgid "E723: Missing end of Dictionary '}': %s" +msgstr "E723: '}' ar iarraidh ag deireadh focl๓ra: %s" + +msgid "extend() argument" +msgstr "arg๓int extend()" + +#, c-format +msgid "E737: Key already exists: %s" +msgstr "E737: Tแ eochair ann cheana: %s" + +#, c-format +msgid "E96: Cannot diff more than %ld buffers" +msgstr "E96: Nํ f้idir diff a dh้anamh ar nํos m๓ nแ %ld maolแn" -#: ../diff.c:753 msgid "E810: Cannot read or write temp files" msgstr "E810: Nํ f้idir comhaid shealadacha a l้amh n๓ a scrํobh" -#: ../diff.c:755 msgid "E97: Cannot create diffs" msgstr "E97: Nํ f้idir diffeanna a chruth๚" -#: ../diff.c:966 +msgid "Patch file" +msgstr "Comhad paiste" + msgid "E816: Cannot read patch output" msgstr "E816: Nํ f้idir aschur ๓ 'patch' a l้amh" -#: ../diff.c:1220 msgid "E98: Cannot read diff output" msgstr "E98: Nํ f้idir aschur ๓ 'diff' a l้amh" -#: ../diff.c:2081 msgid "E99: Current buffer is not in diff mode" msgstr "E99: Nํl an maolแn reatha sa mh๓d diff" -#: ../diff.c:2100 msgid "E793: No other buffer in diff mode is modifiable" msgstr "E793: Nํ f้idir aon mhaolแn eile a athr๚ sa mh๓d diff" -#: ../diff.c:2102 msgid "E100: No other buffer in diff mode" msgstr "E100: Nํl aon mhaolแn eile sa mh๓d diff" -#: ../diff.c:2112 msgid "E101: More than two buffers in diff mode, don't know which one to use" msgstr "" "E101: Tแ nํos m๓ nแ dhแ mhaolแn sa mh๓d diff, nํl fhios agam c้ acu ba ch๓ir " "a ๚sแid" -#: ../diff.c:2141 #, c-format msgid "E102: Can't find buffer \"%s\"" msgstr "E102: Tแ maolแn \"%s\" gan aimsi๚" -#: ../diff.c:2152 #, c-format msgid "E103: Buffer \"%s\" is not in diff mode" msgstr "E103: Nํl maolแn \"%s\" i m๓d diff" -#: ../diff.c:2193 msgid "E787: Buffer changed unexpectedly" msgstr "E787: Athraํodh an maolแn gan choinne" -#: ../digraph.c:1598 msgid "E104: Escape not allowed in digraph" msgstr "E104: Nํ cheadaํtear carachtair ้al๚chแin i nd้ghraf" -#: ../digraph.c:1760 msgid "E544: Keymap file not found" msgstr "E544: Comhad eochairmhapแla gan aimsi๚" -#: ../digraph.c:1785 msgid "E105: Using :loadkeymap not in a sourced file" msgstr "E105: Ag ๚sแid :loadkeymap ach nํ comhad foinsithe ้ seo" -#: ../digraph.c:1821 msgid "E791: Empty keymap entry" msgstr "E791: Iontrแil fholamh eochairmhapแla" -#: ../edit.c:82 msgid " Keyword completion (^N^P)" msgstr " Comhlแn๚ lorgfhocal (^N^P)" #. ctrl_x_mode == 0, ^P/^N compl. -#: ../edit.c:83 msgid " ^X mode (^]^D^E^F^I^K^L^N^O^Ps^U^V^Y)" msgstr " m๓d ^X (^]^D^E^F^I^K^L^N^O^Ps^U^V^Y)" -#: ../edit.c:85 msgid " Whole line completion (^L^N^P)" msgstr " Comhlแn๚ Lํnte Ina Iomlแn (^L^N^P)" -#: ../edit.c:86 msgid " File name completion (^F^N^P)" msgstr " Comhlแn๚ de na hainmneacha comhaid (^F^N^P)" -#: ../edit.c:87 msgid " Tag completion (^]^N^P)" msgstr " Comhlแn๚ clibeanna (^]/^N/^P)" -#: ../edit.c:88 msgid " Path pattern completion (^N^P)" msgstr " Comhlแn๚ Conaire (^N^P)" -#: ../edit.c:89 msgid " Definition completion (^D^N^P)" msgstr " Comhlแn๚ de na sainmhํnithe (^D^N^P)" -#: ../edit.c:91 msgid " Dictionary completion (^K^N^P)" msgstr " Comhlแn๚ focl๓ra (^K^N^P)" -#: ../edit.c:92 msgid " Thesaurus completion (^T^N^P)" msgstr " Comhlแn๚ teasแrais (^T^N^P)" -#: ../edit.c:93 msgid " Command-line completion (^V^N^P)" msgstr " Comhlแn๚ den lํne ordaithe (^V^N^P)" -#: ../edit.c:94 msgid " User defined completion (^U^N^P)" msgstr " Comhlแn๚ saincheaptha (^U^N^P)" -#: ../edit.c:95 msgid " Omni completion (^O^N^P)" msgstr " Comhlแn๚ Omni (^O^N^P)" -#: ../edit.c:96 msgid " Spelling suggestion (s^N^P)" msgstr " Moladh litrithe (s^N^P)" -#: ../edit.c:97 msgid " Keyword Local completion (^N^P)" msgstr " Comhlแn๚ logแnta lorgfhocal (^N^P)" -#: ../edit.c:100 msgid "Hit end of paragraph" msgstr "Sroicheadh crํoch an pharagraif" -#: ../edit.c:101 -#, fuzzy msgid "E839: Completion function changed window" -msgstr "E813: Nํ f้idir fuinneog autocmd a dh๚nadh" +msgstr "E839: D'athraigh an fheidhm chomhlแnaithe an fhuinneog" -#: ../edit.c:102 msgid "E840: Completion function deleted text" -msgstr "" +msgstr "E840: Scrios an fheidhm chomhlแnaithe roinnt t้acs" -#: ../edit.c:1847 msgid "'dictionary' option is empty" msgstr "tแ an rogha 'dictionary' folamh" -#: ../edit.c:1848 msgid "'thesaurus' option is empty" msgstr "tแ an rogha 'thesaurus' folamh" -#: ../edit.c:2655 #, c-format msgid "Scanning dictionary: %s" msgstr "Focl๓ir แ scanadh: %s" -#: ../edit.c:3079 msgid " (insert) Scroll (^E/^Y)" msgstr " (ionsแigh) Scrollaigh (^E/^Y)" -#: ../edit.c:3081 msgid " (replace) Scroll (^E/^Y)" msgstr " (ionadaigh) Scrollaigh (^E/^Y)" -#: ../edit.c:3587 #, c-format msgid "Scanning: %s" msgstr "%s แ scanadh" -#: ../edit.c:3614 msgid "Scanning tags." msgstr "Clibeanna แ scanadh." -#: ../edit.c:4519 msgid " Adding" msgstr " M้ad๚" @@ -438,702 +433,451 @@ msgstr " M้ad๚" #. * be called before line = ml_get(), or when this address is no #. * longer needed. -- Acevedo. #. -#: ../edit.c:4562 msgid "-- Searching..." msgstr "-- Ag Cuardach..." -#: ../edit.c:4618 msgid "Back at original" msgstr "Ar ais ag an mbunแit" -#: ../edit.c:4621 msgid "Word from other line" msgstr "Focal as lํne eile" -#: ../edit.c:4624 msgid "The only match" msgstr "An t-aon teaghrแn amhแin comhoiri๚naithe" -#: ../edit.c:4680 #, c-format msgid "match %d of %d" msgstr "comhoiri๚n๚ %d as %d" -#: ../edit.c:4684 #, c-format msgid "match %d" msgstr "comhoiri๚n๚ %d" -#: ../eval.c:137 +#. maximum nesting of lists and dicts msgid "E18: Unexpected characters in :let" msgstr "E18: Carachtair gan choinne i :let" -#: ../eval.c:138 -#, c-format -msgid "E684: list index out of range: %<PRId64>" -msgstr "E684: inn้acs liosta as raon: %<PRId64>" - -#: ../eval.c:139 #, c-format msgid "E121: Undefined variable: %s" msgstr "E121: Athr๓g gan sainmhํni๚: %s" -#: ../eval.c:140 msgid "E111: Missing ']'" msgstr "E111: `]' ar iarraidh" -#: ../eval.c:141 -#, c-format -msgid "E686: Argument of %s must be a List" -msgstr "E686: Caithfidh arg๓int de %s a bheith ina Liosta" - -#: ../eval.c:143 -#, c-format -msgid "E712: Argument of %s must be a List or Dictionary" -msgstr "E712: Caithfidh arg๓int de %s a bheith ina Liosta n๓ Focl๓ir" - -#: ../eval.c:144 -msgid "E713: Cannot use empty key for Dictionary" -msgstr "E713: Nํ f้idir eochair fholamh a ๚sแid le Focl๓ir" - -#: ../eval.c:145 -msgid "E714: List required" -msgstr "E714: Tแ gแ le liosta" - -#: ../eval.c:146 -msgid "E715: Dictionary required" -msgstr "E715: Tแ gแ le focl๓ir" - -#: ../eval.c:147 -#, c-format -msgid "E118: Too many arguments for function: %s" -msgstr "E118: An iomarca arg๓intํ d'fheidhm: %s" - -#: ../eval.c:148 -#, c-format -msgid "E716: Key not present in Dictionary: %s" -msgstr "E716: Nํl an eochair seo san Fhocl๓ir: %s" - -#: ../eval.c:150 -#, c-format -msgid "E122: Function %s already exists, add ! to replace it" -msgstr "E122: Tแ feidhm %s ann cheana, cuir ! leis an ord๚ chun ้ a asแiti๚" - -#: ../eval.c:151 -msgid "E717: Dictionary entry already exists" -msgstr "E717: Tแ an iontrแil focl๓ra seo ann cheana" - -#: ../eval.c:152 -msgid "E718: Funcref required" -msgstr "E718: Tแ gแ le Funcref" - -#: ../eval.c:153 msgid "E719: Cannot use [:] with a Dictionary" msgstr "E719: Nํ f้idir [:] a ๚sแid le focl๓ir" -#: ../eval.c:154 #, c-format msgid "E734: Wrong variable type for %s=" msgstr "E734: Cineแl mํcheart athr๓ige le haghaidh %s=" -#: ../eval.c:155 -#, c-format -msgid "E130: Unknown function: %s" -msgstr "E130: Feidhm anaithnid: %s" - -#: ../eval.c:156 #, c-format msgid "E461: Illegal variable name: %s" msgstr "E461: Ainm athr๓ige neamhcheadaithe: %s" -#: ../eval.c:157 msgid "E806: using Float as a String" msgstr "E806: Snแmhphointe แ ๚sแid mar Theaghrแn" -#: ../eval.c:1830 msgid "E687: Less targets than List items" msgstr "E687: Nํos l๚ spriocanna nแ mํreanna Liosta" -#: ../eval.c:1834 msgid "E688: More targets than List items" msgstr "E688: Nํos m๓ spriocanna nแ mํreanna Liosta" -#: ../eval.c:1906 msgid "Double ; in list of variables" msgstr "; d๚blach i liosta na n-athr๓g" -#: ../eval.c:2078 #, c-format msgid "E738: Can't list variables for %s" msgstr "E738: Nํ f้idir athr๓ga do %s a thaispeแint" -#: ../eval.c:2391 msgid "E689: Can only index a List or Dictionary" msgstr "E689: Is f้idir Liosta n๓ Focl๓ir amhแin a inn้acs๚" -#: ../eval.c:2396 msgid "E708: [:] must come last" msgstr "E708: caithfidh [:] a bheith ar deireadh" -#: ../eval.c:2439 msgid "E709: [:] requires a List value" msgstr "E709: nํ folแir Liosta a thabhairt le [:]" -#: ../eval.c:2674 msgid "E710: List value has more items than target" msgstr "E710: Tแ nํos m๓ mํreanna ag an Liosta nแ an sprioc" -#: ../eval.c:2678 msgid "E711: List value has not enough items" msgstr "E711: Nํl go leor mํreanna ag an Liosta" -#: ../eval.c:2867 msgid "E690: Missing \"in\" after :for" msgstr "E690: \"in\" ar iarraidh i ndiaidh :for" -#: ../eval.c:3063 -#, c-format -msgid "E107: Missing parentheses: %s" -msgstr "E107: L๚ibํnํ ar iarraidh: %s" - -#: ../eval.c:3263 #, c-format msgid "E108: No such variable: \"%s\"" msgstr "E108: Nํl a leith้id d'athr๓g: \"%s\"" -#: ../eval.c:3333 msgid "E743: variable nested too deep for (un)lock" msgstr "E743: athr๓g neadaithe r๓dhomhain chun ํ a (dํ)ghlasแil" -#: ../eval.c:3630 msgid "E109: Missing ':' after '?'" msgstr "E109: ':' ar iarraidh i ndiaidh '?'" -#: ../eval.c:3893 msgid "E691: Can only compare List with List" msgstr "E691: Is f้idir Liosta a chur i gcomparแid le Liosta eile amhแin" -#: ../eval.c:3895 -msgid "E692: Invalid operation for Lists" +msgid "E692: Invalid operation for List" msgstr "E692: Oibrํocht neamhbhailํ ar Liostaํ" -#: ../eval.c:3915 msgid "E735: Can only compare Dictionary with Dictionary" msgstr "E735: Is f้idir Focl๓ir a chur i gcomparแid le Focl๓ir eile amhแin" -#: ../eval.c:3917 msgid "E736: Invalid operation for Dictionary" msgstr "E736: Oibrํocht neamhbhailํ ar Fhocl๓ir" -#: ../eval.c:3932 -msgid "E693: Can only compare Funcref with Funcref" -msgstr "E693: Is f้idir Funcref a chur i gcomparแid le Funcref eile amhแin" - -#: ../eval.c:3934 msgid "E694: Invalid operation for Funcrefs" msgstr "E694: Oibrํocht neamhbhailํ ar Funcref" -#: ../eval.c:4277 msgid "E804: Cannot use '%' with Float" msgstr "E804: Nํ f้idir '%' a ๚sแid le Snแmhphointe" -#: ../eval.c:4478 msgid "E110: Missing ')'" msgstr "E110: ')' ar iarraidh" -#: ../eval.c:4609 msgid "E695: Cannot index a Funcref" msgstr "E695: Nํ f้idir Funcref a inn้acs๚" -#: ../eval.c:4839 +msgid "E909: Cannot index a special variable" +msgstr "E909: Nํ f้idir athr๓g speisialta a inn้acs๚" + #, c-format msgid "E112: Option name missing: %s" msgstr "E112: Ainm rogha ar iarraidh: %s" -#: ../eval.c:4855 #, c-format msgid "E113: Unknown option: %s" msgstr "E113: Rogha anaithnid: %s" -#: ../eval.c:4904 #, c-format msgid "E114: Missing quote: %s" msgstr "E114: Comhartha athfhriotail ar iarraidh: %s" -#: ../eval.c:5020 #, c-format msgid "E115: Missing quote: %s" msgstr "E115: Comhartha athfhriotail ar iarraidh: %s" -#: ../eval.c:5084 -#, c-format -msgid "E696: Missing comma in List: %s" -msgstr "E696: Cam๓g ar iarraidh i Liosta: %s" - -#: ../eval.c:5091 -#, c-format -msgid "E697: Missing end of List ']': %s" -msgstr "E697: ']' ar iarraidh ag deireadh liosta: %s" - -#: ../eval.c:6475 -#, c-format -msgid "E720: Missing colon in Dictionary: %s" -msgstr "E720: Idirstad ar iarraidh i bhFocl๓ir: %s" - -#: ../eval.c:6499 -#, c-format -msgid "E721: Duplicate key in Dictionary: \"%s\"" -msgstr "E721: Eochair dh๚blach i bhFocl๓ir: \"%s\"" - -#: ../eval.c:6517 -#, c-format -msgid "E722: Missing comma in Dictionary: %s" -msgstr "E722: Cam๓g ar iarraidh i bhFocl๓ir: %s" - -#: ../eval.c:6524 -#, c-format -msgid "E723: Missing end of Dictionary '}': %s" -msgstr "E723: '}' ar iarraidh ag deireadh focl๓ra: %s" +msgid "Not enough memory to set references, garbage collection aborted!" +msgstr "" +"Nํl go leor cuimhne ann le tagairtํ a shocr๚; baili๚ dramhaํola แ thobscor!" -#: ../eval.c:6555 msgid "E724: variable nested too deep for displaying" msgstr "E724: athr๓g neadaithe r๓dhomhain chun ํ a thaispeแint" -#: ../eval.c:7188 -#, c-format -msgid "E740: Too many arguments for function %s" -msgstr "E740: An iomarca arg๓intํ d'fheidhm %s" - -#: ../eval.c:7190 -#, c-format -msgid "E116: Invalid arguments for function %s" -msgstr "E116: Arg๓intํ neamhbhailํ d'fheidhm %s" - -#: ../eval.c:7377 -#, c-format -msgid "E117: Unknown function: %s" -msgstr "E117: Feidhm anaithnid: %s" - -#: ../eval.c:7383 -#, c-format -msgid "E119: Not enough arguments for function: %s" -msgstr "E119: Nํl go leor feidhmeanna d'fheidhm: %s" - -#: ../eval.c:7387 -#, c-format -msgid "E120: Using <SID> not in a script context: %s" -msgstr "E120: <SID> แ ๚sแid ach gan a bheith i gcomhth้acs scripte: %s" - -#: ../eval.c:7391 -#, c-format -msgid "E725: Calling dict function without Dictionary: %s" -msgstr "E725: Feidhm 'dict' แ ghlao gan Focl๓ir: %s" - -#: ../eval.c:7453 -msgid "E808: Number or Float required" -msgstr "E808: Uimhir n๓ Snแmhphointe de dhํth" - -#: ../eval.c:7503 -#, fuzzy -msgid "add() argument" -msgstr "arg๓int -c" - -#: ../eval.c:7907 -msgid "E699: Too many arguments" -msgstr "E699: An iomarca arg๓intํ" - -#: ../eval.c:8073 -msgid "E785: complete() can only be used in Insert mode" -msgstr "E785: is f้idir complete() a ๚sแid sa mh๓d Ionsแite amhแin" - -#: ../eval.c:8156 -msgid "&Ok" -msgstr "&Ok" - -#: ../eval.c:8676 -#, c-format -msgid "E737: Key already exists: %s" -msgstr "E737: Tแ eochair ann cheana: %s" - -#: ../eval.c:8692 -#, fuzzy -msgid "extend() argument" -msgstr "arg๓int --cmd" - -#: ../eval.c:8915 -#, fuzzy -msgid "map() argument" -msgstr "arg๓int -c" - -#: ../eval.c:8916 -#, fuzzy -msgid "filter() argument" -msgstr "arg๓int -c" - -#: ../eval.c:9229 -#, c-format -msgid "+-%s%3ld lines: " -msgstr "+-%s%3ld lํne: " - -#: ../eval.c:9291 -#, c-format -msgid "E700: Unknown function: %s" -msgstr "E700: Feidhm anaithnid: %s" - -#: ../eval.c:10729 -msgid "called inputrestore() more often than inputsave()" -msgstr "Glaodh inputrestore() nํos minice nแ inputsave()" - -#: ../eval.c:10771 -#, fuzzy -msgid "insert() argument" -msgstr "arg๓int -c" - -#: ../eval.c:10841 -msgid "E786: Range not allowed" -msgstr "E786: Nํ cheadaํtear an raon" - -#: ../eval.c:11140 -msgid "E701: Invalid type for len()" -msgstr "E701: Cineแl neamhbhailํ le haghaidh len()" - -#: ../eval.c:11980 -msgid "E726: Stride is zero" -msgstr "E726: Is nialas ํ an ch้im" - -#: ../eval.c:11982 -msgid "E727: Start past end" -msgstr "E727: Tosach thar dheireadh" - -#: ../eval.c:12024 ../eval.c:15297 -msgid "<empty>" -msgstr "<folamh>" - -#: ../eval.c:12282 -#, fuzzy -msgid "remove() argument" -msgstr "arg๓int --cmd" +msgid "E805: Using a Float as a Number" +msgstr "E805: Snแmhphointe แ ๚sแid mar Uimhir" -#: ../eval.c:12466 -msgid "E655: Too many symbolic links (cycle?)" -msgstr "E655: An iomarca naisc shiombalacha (ciogal?)" +msgid "E703: Using a Funcref as a Number" +msgstr "E703: Funcref แ ๚sแid mar Uimhir" -#: ../eval.c:12593 -#, fuzzy -msgid "reverse() argument" -msgstr "arg๓int -c" +msgid "E745: Using a List as a Number" +msgstr "E745: Liosta แ ๚sแid mar Uimhir" -#: ../eval.c:13721 -#, fuzzy -msgid "sort() argument" -msgstr "arg๓int -c" +msgid "E728: Using a Dictionary as a Number" +msgstr "E728: Focl๓ir แ ๚sแid mar Uimhir" -#: ../eval.c:13721 -#, fuzzy -msgid "uniq() argument" -msgstr "arg๓int -c" +msgid "E910: Using a Job as a Number" +msgstr "E910: Jab แ ๚sแid mar Uimhir" -#: ../eval.c:13776 -msgid "E702: Sort compare function failed" -msgstr "E702: Theip ar fheidhm chomparแide le linn s๓rtแla" +msgid "E913: Using a Channel as a Number" +msgstr "E913: Cain้al แ ๚sแid mar Uimhir" -#: ../eval.c:13806 -#, fuzzy -msgid "E882: Uniq compare function failed" -msgstr "E702: Theip ar fheidhm chomparแide le linn s๓rtแla" +msgid "E891: Using a Funcref as a Float" +msgstr "E891: Funcref แ ๚sแid mar Shnแmhphointe" -#: ../eval.c:14085 -msgid "(Invalid)" -msgstr "(Neamhbhailํ)" +msgid "E892: Using a String as a Float" +msgstr "E892: Teaghrแn แ ๚sแid mar Shnแmhphointe" -#: ../eval.c:14590 -msgid "E677: Error writing temp file" -msgstr "E677: Earrแid agus comhad sealadach แ scrํobh" +msgid "E893: Using a List as a Float" +msgstr "E893: Liosta แ ๚sแid mar Shnแmhphointe" -#: ../eval.c:16159 -msgid "E805: Using a Float as a Number" -msgstr "E805: Snแmhphointe แ ๚sแid mar Uimhir" +msgid "E894: Using a Dictionary as a Float" +msgstr "E894: Focl๓ir แ ๚sแid mar Shnแmhphointe" -#: ../eval.c:16162 -msgid "E703: Using a Funcref as a Number" -msgstr "E703: Funcref แ ๚sแid mar Uimhir" +msgid "E907: Using a special value as a Float" +msgstr "E907: Luach speisialta แ ๚sแid mar Shnแmhphointe" -#: ../eval.c:16170 -msgid "E745: Using a List as a Number" -msgstr "E745: Liosta แ ๚sแid mar Uimhir" +msgid "E911: Using a Job as a Float" +msgstr "E911: Jab แ ๚sแid mar Shnแmhphointe" -#: ../eval.c:16173 -msgid "E728: Using a Dictionary as a Number" -msgstr "E728: Focl๓ir แ ๚sแid mar Uimhir" +msgid "E914: Using a Channel as a Float" +msgstr "E914: Cain้al แ ๚sแid mar Shnแmhphointe" -#: ../eval.c:16259 msgid "E729: using Funcref as a String" msgstr "E729: Funcref แ ๚sแid mar Theaghrแn" -#: ../eval.c:16262 msgid "E730: using List as a String" msgstr "E730: Liosta แ ๚sแid mar Theaghrแn" -#: ../eval.c:16265 msgid "E731: using Dictionary as a String" msgstr "E731: Focl๓ir แ ๚sแid mar Theaghrแn" -#: ../eval.c:16619 -#, c-format -msgid "E706: Variable type mismatch for: %s" -msgstr "E706: Mํmheaitseแil idir cineแlacha athr๓ige: %s" +msgid "E908: using an invalid value as a String" +msgstr "E908: luach neamhbhailํ แ ๚sแid mar Theaghrแn" -#: ../eval.c:16705 #, c-format msgid "E795: Cannot delete variable %s" msgstr "E795: Nํ f้idir athr๓g %s a scriosadh" -#: ../eval.c:16724 #, c-format msgid "E704: Funcref variable name must start with a capital: %s" msgstr "E704: Caithfidh ceannlitir a bheith ar dt๚s ainm Funcref: %s" -#: ../eval.c:16732 #, c-format msgid "E705: Variable name conflicts with existing function: %s" msgstr "E705: Tagann ainm athr๓ige salach ar fheidhm atแ ann cheana: %s" -#: ../eval.c:16763 #, c-format msgid "E741: Value is locked: %s" msgstr "E741: Tแ an luach faoi ghlas: %s" -#: ../eval.c:16764 ../eval.c:16769 ../message.c:1839 msgid "Unknown" msgstr "Anaithnid" -#: ../eval.c:16768 #, c-format msgid "E742: Cannot change value of %s" msgstr "E742: Nํ f้idir an luach de %s a athr๚" -#: ../eval.c:16838 msgid "E698: variable nested too deep for making a copy" msgstr "E698: athr๓g neadaithe r๓dhomhain chun ํ a ch๓ipeแil" -#: ../eval.c:17249 -#, c-format -msgid "E123: Undefined function: %s" -msgstr "E123: Feidhm gan sainmhํni๚: %s" +msgid "" +"\n" +"# global variables:\n" +msgstr "" +"\n" +"# athr๓ga comhchoiteanna:\n" -#: ../eval.c:17260 -#, c-format -msgid "E124: Missing '(': %s" -msgstr "E124: '(' ar iarraidh: %s" +msgid "" +"\n" +"\tLast set from " +msgstr "" +"\n" +"\tSocraithe is d้anaํ ๓ " -#: ../eval.c:17293 -#, fuzzy -msgid "E862: Cannot use g: here" -msgstr "E284: Nํ f้idir luachanna IC a shocr๚" +msgid "map() argument" +msgstr "arg๓int map()" + +msgid "filter() argument" +msgstr "arg๓int filter()" -#: ../eval.c:17312 #, c-format -msgid "E125: Illegal argument: %s" -msgstr "E125: Arg๓int neamhcheadaithe: %s" +msgid "E686: Argument of %s must be a List" +msgstr "E686: Caithfidh arg๓int de %s a bheith ina Liosta" -#: ../eval.c:17323 -#, fuzzy, c-format -msgid "E853: Duplicate argument name: %s" -msgstr "E125: Arg๓int neamhcheadaithe: %s" +msgid "E928: String required" +msgstr "E928: Teaghrแn de dhํth" -#: ../eval.c:17416 -msgid "E126: Missing :endfunction" -msgstr "E126: :endfunction ar iarraidh" +msgid "E808: Number or Float required" +msgstr "E808: Uimhir n๓ Snแmhphointe de dhํth" -#: ../eval.c:17537 -#, c-format -msgid "E707: Function name conflicts with variable: %s" -msgstr "E707: Tagann ainm na feidhme salach ar athr๓g: %s" +msgid "add() argument" +msgstr "arg๓int add()" + +msgid "E785: complete() can only be used in Insert mode" +msgstr "E785: is f้idir complete() a ๚sแid sa mh๓d Ionsแite amhแin" + +#. +#. * Yes this is ugly, I don't particularly like it either. But doing it +#. * this way has the compelling advantage that translations need not to +#. * be touched at all. See below what 'ok' and 'ync' are used for. +#. +msgid "&Ok" +msgstr "&Ok" -#: ../eval.c:17549 #, c-format -msgid "E127: Cannot redefine function %s: It is in use" -msgstr "" -"E127: Nํ f้idir sainmhํni๚ nua a dh้anamh ar fheidhm %s: In ๚sแid cheana" +msgid "+-%s%3ld line: " +msgid_plural "+-%s%3ld lines: " +msgstr[0] "+-%s%3ld lํne: " +msgstr[1] "+-%s%3ld lํne: " +msgstr[2] "+-%s%3ld lํne: " +msgstr[3] "+-%s%3ld lํne: " +msgstr[4] "+-%s%3ld lํne: " -#: ../eval.c:17604 #, c-format -msgid "E746: Function name does not match script file name: %s" -msgstr "" -"E746: Nํl ainm na feidhme comhoiri๚nach le hainm comhaid na scripte: %s" +msgid "E700: Unknown function: %s" +msgstr "E700: Feidhm anaithnid: %s" -#: ../eval.c:17716 -msgid "E129: Function name required" -msgstr "E129: Tแ gแ le hainm feidhme" +msgid "E922: expected a dict" +msgstr "E922: bhํothas ag s๚il le focl๓ir" -#: ../eval.c:17824 -#, fuzzy, c-format -msgid "E128: Function name must start with a capital or \"s:\": %s" -msgstr "" -"E128: Caithfidh ceannlitir a bheith ar dt๚s ainm feidhme, n๓ idirstad a " -"bheith ann: %s" +msgid "E923: Second argument of function() must be a list or a dict" +msgstr "E923: Caithfidh an dara harg๓int de function() a bheith ina liosta n๓ ina focl๓ir" -#: ../eval.c:17833 -#, fuzzy, c-format -msgid "E884: Function name cannot contain a colon: %s" +msgid "" +"&OK\n" +"&Cancel" msgstr "" -"E128: Caithfidh ceannlitir a bheith ar dt๚s ainm feidhme, n๓ idirstad a " -"bheith ann: %s" +"&OK\n" +"&Cealaigh" -#: ../eval.c:18336 -#, c-format -msgid "E131: Cannot delete function %s: It is in use" -msgstr "E131: Nํ f้idir feidhm %s a scriosadh: Tแ s้ in ๚sแid faoi lแthair" +msgid "called inputrestore() more often than inputsave()" +msgstr "Glaodh inputrestore() nํos minice nแ inputsave()" -#: ../eval.c:18441 -msgid "E132: Function call depth is higher than 'maxfuncdepth'" -msgstr "E132: Doimhneacht na nglaonna nํos m๓ nแ 'maxfuncdepth'" +msgid "insert() argument" +msgstr "arg๓int insert()" -#: ../eval.c:18568 -#, c-format -msgid "calling %s" -msgstr "%s แ glao" +msgid "E786: Range not allowed" +msgstr "E786: Nํ cheadaํtear an raon" -#: ../eval.c:18651 -#, c-format -msgid "%s aborted" -msgstr "%s tobscortha" +msgid "E916: not a valid job" +msgstr "E916: nํ jab bailํ ้" + +msgid "E701: Invalid type for len()" +msgstr "E701: Cineแl neamhbhailํ le haghaidh len()" -#: ../eval.c:18653 #, c-format -msgid "%s returning #%<PRId64>" -msgstr "%s ag aisfhilleadh #%<PRId64>" +msgid "E798: ID is reserved for \":match\": %ld" +msgstr "E798: Aitheantas in แirithe do \":match\": %ld" + +msgid "E726: Stride is zero" +msgstr "E726: Is nialas ํ an ch้im" + +msgid "E727: Start past end" +msgstr "E727: Tosach thar dheireadh" + +msgid "<empty>" +msgstr "<folamh>" + +msgid "E240: No connection to Vim server" +msgstr "E240: Nํl aon nasc le freastalaํ Vim" -#: ../eval.c:18670 #, c-format -msgid "%s returning %s" -msgstr "%s ag aisfhilleadh %s" +msgid "E241: Unable to send to %s" +msgstr "E241: Nํ f้idir aon rud a sheoladh chuig %s" + +msgid "E277: Unable to read a server reply" +msgstr "E277: Nํ f้idir freagra ๓n fhreastalaํ a l้amh" + +msgid "remove() argument" +msgstr "arg๓int remove()" + +msgid "E655: Too many symbolic links (cycle?)" +msgstr "E655: An iomarca naisc shiombalacha (ciogal?)" + +msgid "reverse() argument" +msgstr "arg๓int reverse()" + +msgid "E258: Unable to send to client" +msgstr "E258: Nํ f้idir aon rud a sheoladh chuig an chliant" -#: ../eval.c:18691 ../ex_cmds2.c:2695 #, c-format -msgid "continuing in %s" -msgstr "ag lean๚int i %s" +msgid "E927: Invalid action: '%s'" +msgstr "E927: Gnํomh neamhbhailํ: '%s'" -#: ../eval.c:18795 -msgid "E133: :return not inside a function" -msgstr "E133: Caithfidh :return a bheith isteach i bhfeidhm" +msgid "sort() argument" +msgstr "arg๓int sort()" -#: ../eval.c:19159 -msgid "" -"\n" -"# global variables:\n" -msgstr "" -"\n" -"# athr๓ga comhchoiteanna:\n" +msgid "uniq() argument" +msgstr "arg๓int uniq()" -#: ../eval.c:19254 -msgid "" -"\n" -"\tLast set from " -msgstr "" -"\n" -"\tSocraithe is d้anaํ ๓ " +msgid "E702: Sort compare function failed" +msgstr "E702: Theip ar fheidhm chomparแide le linn s๓rtแla" -#: ../eval.c:19272 -msgid "No old files" -msgstr "Gan seanchomhaid" +msgid "E882: Uniq compare function failed" +msgstr "E882: Theip ar fheidhm chomparแide Uniq" + +msgid "(Invalid)" +msgstr "(Neamhbhailํ)" + +#, c-format +msgid "E935: invalid submatch number: %d" +msgstr "E935: uimhir fho-mheaitseแla neamhbhailํ: %d" + +msgid "E677: Error writing temp file" +msgstr "E677: Earrแid agus comhad sealadach แ scrํobh" + +msgid "E921: Invalid callback argument" +msgstr "E921: Arg๓int neamhbhailํ ar aisghlaoch" -#: ../ex_cmds.c:122 #, c-format msgid "<%s>%s%s %d, Hex %02x, Octal %03o" msgstr "<%s>%s%s %d, Heics %02x, Ocht %03o" -#: ../ex_cmds.c:145 #, c-format msgid "> %d, Hex %04x, Octal %o" msgstr "> %d, Heics %04x, Ocht %o" -#: ../ex_cmds.c:146 #, c-format msgid "> %d, Hex %08x, Octal %o" msgstr "> %d, Heics %08x, Ocht %o" -#: ../ex_cmds.c:684 msgid "E134: Move lines into themselves" msgstr "E134: Bog lํnte isteach iontu f้in" -#: ../ex_cmds.c:747 msgid "1 line moved" msgstr "Bogadh lํne amhแin" -#: ../ex_cmds.c:749 #, c-format -msgid "%<PRId64> lines moved" -msgstr "Bogadh %<PRId64> lํne" +msgid "%ld lines moved" +msgstr "Bogadh %ld lํne" -#: ../ex_cmds.c:1175 #, c-format -msgid "%<PRId64> lines filtered" -msgstr "Scagadh %<PRId64> lํne" +msgid "%ld lines filtered" +msgstr "Scagadh %ld lํne" -#: ../ex_cmds.c:1194 msgid "E135: *Filter* Autocommands must not change current buffer" msgstr "" "E135: Nํ cheadaํtear d'uathorduithe *scagaire* an maolแn reatha a athr๚" -#: ../ex_cmds.c:1244 msgid "[No write since last change]\n" msgstr "[Athraithe agus nach sแbhแilte ๓ shin]\n" -#: ../ex_cmds.c:1424 #, c-format msgid "%sviminfo: %s in line: " msgstr "%sviminfo: %s i lํne: " -#: ../ex_cmds.c:1431 msgid "E136: viminfo: Too many errors, skipping rest of file" msgstr "" "E136: viminfo: An iomarca earrแidํ, ag scipeแil an chuid eile den chomhad" -#: ../ex_cmds.c:1458 #, c-format msgid "Reading viminfo file \"%s\"%s%s%s" msgstr "Comhad viminfo \"%s\"%s%s%s แ l้amh" -#: ../ex_cmds.c:1460 msgid " info" msgstr " eolas" -#: ../ex_cmds.c:1461 msgid " marks" msgstr " marcanna" -#: ../ex_cmds.c:1462 msgid " oldfiles" msgstr " seanchomhad" -#: ../ex_cmds.c:1463 msgid " FAILED" msgstr " TEIPTHE" #. avoid a wait_return for this message, it's annoying -#: ../ex_cmds.c:1541 #, c-format msgid "E137: Viminfo file is not writable: %s" msgstr "E137: Nํl an comhad Viminfo inscrํofa: %s" -#: ../ex_cmds.c:1626 +#, c-format +msgid "E929: Too many viminfo temp files, like %s!" +msgstr "E929: An iomarca comhad sealadach viminfo, mar shampla %s!" + #, c-format msgid "E138: Can't write viminfo file %s!" msgstr "E138: Nํ f้idir comhad viminfo %s a scrํobh!" -#: ../ex_cmds.c:1635 #, c-format msgid "Writing viminfo file \"%s\"" msgstr "Comhad viminfo \"%s\" แ scrํobh" +#, c-format +msgid "E886: Can't rename viminfo file to %s!" +msgstr "E886: Nํ f้idir ainm %s a chur ar an gcomhad viminfo!" + #. Write the info: -#: ../ex_cmds.c:1720 #, c-format msgid "# This viminfo file was generated by Vim %s.\n" msgstr "# Chruthaigh Vim an comhad viminfo seo %s.\n" -#: ../ex_cmds.c:1722 msgid "" "# You may edit it if you're careful!\n" "\n" @@ -1141,47 +885,47 @@ msgstr "" "# Is f้idir leat an comhad seo a chur in eagar ach bํ c๚ramach!\n" "\n" -#: ../ex_cmds.c:1723 msgid "# Value of 'encoding' when this file was written\n" msgstr "# Luach 'encoding' agus an comhad seo แ scrํobh\n" -#: ../ex_cmds.c:1800 msgid "Illegal starting char" msgstr "Carachtar neamhcheadaithe tosaigh" -#: ../ex_cmds.c:2162 +msgid "" +"\n" +"# Bar lines, copied verbatim:\n" +msgstr "" +"\n" +"# Barralํnte, c๓ipeแilte focal ar fhocal:\n" + +msgid "Save As" +msgstr "Sแbhแil Mar" + msgid "Write partial file?" msgstr "Scrํobh comhad neamhiomlแn?" -#: ../ex_cmds.c:2166 msgid "E140: Use ! to write partial buffer" msgstr "E140: Bain ๚sแid as ! chun maolแn neamhiomlแn a scrํobh" -#: ../ex_cmds.c:2281 #, c-format msgid "Overwrite existing file \"%s\"?" msgstr "Forscrํobh comhad \"%s\" atแ ann cheana?" -#: ../ex_cmds.c:2317 #, c-format msgid "Swap file \"%s\" exists, overwrite anyway?" msgstr "Tแ comhad babhtแla \"%s\" ann cheana; forscrํobh mar sin f้in?" -#: ../ex_cmds.c:2326 #, c-format msgid "E768: Swap file exists: %s (:silent! overrides)" msgstr "E768: Tแ comhad babhtแla ann cheana: %s (๚sแid :silent! chun sแr๚)" -#: ../ex_cmds.c:2381 #, c-format -msgid "E141: No file name for buffer %<PRId64>" -msgstr "E141: Nํl aon ainm ar mhaolแn %<PRId64>" +msgid "E141: No file name for buffer %ld" +msgstr "E141: Nํl aon ainm ar mhaolแn %ld" -#: ../ex_cmds.c:2412 msgid "E142: File not written: Writing is disabled by 'write' option" msgstr "E142: Nํor scrํobhadh an comhad: dํchumasaithe leis an rogha 'write'" -#: ../ex_cmds.c:2434 #, c-format msgid "" "'readonly' option is set for \"%s\".\n" @@ -1190,7 +934,6 @@ msgstr "" "tแ an rogha 'readonly' socraithe do \"%s\".\n" "Ar mhaith leat ้ a scrํobh mar sin f้in?" -#: ../ex_cmds.c:2439 #, c-format msgid "" "File permissions of \"%s\" are read-only.\n" @@ -1201,85 +944,70 @@ msgstr "" "Seans gurbh fh้idir scrํobh ann mar sin f้in.\n" "An bhfuil fonn ort triail a bhaint as?" -#: ../ex_cmds.c:2451 #, c-format msgid "E505: \"%s\" is read-only (add ! to override)" msgstr "E505: is inl้ite amhแin ้ \"%s\" (cuir ! leis an ord๚ chun sแr๚)" -#: ../ex_cmds.c:3120 +msgid "Edit File" +msgstr "Cuir Comhad in Eagar" + #, c-format msgid "E143: Autocommands unexpectedly deleted new buffer %s" msgstr "E143: Scrios na huathorduithe maolแn nua %s go tobann" -#: ../ex_cmds.c:3313 msgid "E144: non-numeric argument to :z" msgstr "E144: arg๓int neamhuimhri๚il chun :z" -#: ../ex_cmds.c:3404 msgid "E145: Shell commands not allowed in rvim" msgstr "E145: Nํ cheadaํtear orduithe blaoisce i rvim" -#: ../ex_cmds.c:3498 msgid "E146: Regular expressions can't be delimited by letters" msgstr "" "E146: Nํ cheadaํtear litreacha mar theormharc๓irํ ar shloinn ionadaํochta" -#: ../ex_cmds.c:3964 #, c-format msgid "replace with %s (y/n/a/q/l/^E/^Y)?" msgstr "cuir %s ina ionad (y/n/a/q/l/^E/^Y)?" -#: ../ex_cmds.c:4379 msgid "(Interrupted) " msgstr "(Idirbhriste) " -#: ../ex_cmds.c:4384 msgid "1 match" msgstr "1 rud comhoiri๚nach" -#: ../ex_cmds.c:4384 msgid "1 substitution" msgstr "1 ionadaํocht" -#: ../ex_cmds.c:4387 #, c-format -msgid "%<PRId64> matches" -msgstr "%<PRId64> rud comhoiri๚nach" +msgid "%ld matches" +msgstr "%ld rud comhoiri๚nach" -#: ../ex_cmds.c:4388 #, c-format -msgid "%<PRId64> substitutions" -msgstr "%<PRId64> ionadaํocht" +msgid "%ld substitutions" +msgstr "%ld ionadaํocht" -#: ../ex_cmds.c:4392 msgid " on 1 line" msgstr " ar lํne amhแin" -#: ../ex_cmds.c:4395 #, c-format -msgid " on %<PRId64> lines" -msgstr " ar %<PRId64> lํne" +msgid " on %ld lines" +msgstr " ar %ld lํne" -#: ../ex_cmds.c:4438 msgid "E147: Cannot do :global recursive" msgstr "E147: Nํ cheadaํtear :global go hathch๚rsach" # should have ":" -#: ../ex_cmds.c:4467 msgid "E148: Regular expression missing from global" msgstr "E148: Slonn ionadaํochta ar iarraidh ๓ :global" -#: ../ex_cmds.c:4508 #, c-format msgid "Pattern found in every line: %s" msgstr "Aimsํodh an patr๚n i ngach lํne: %s" -#: ../ex_cmds.c:4510 -#, fuzzy, c-format +#, c-format msgid "Pattern not found: %s" -msgstr "Patr๚n gan aimsi๚" +msgstr "Patr๚n gan aimsi๚: %s" -#: ../ex_cmds.c:4587 msgid "" "\n" "# Last Substitute String:\n" @@ -1289,682 +1017,599 @@ msgstr "" "# Teaghrแn Ionadach Is D้anaํ:\n" "$" -#: ../ex_cmds.c:4679 msgid "E478: Don't panic!" msgstr "E478: Nแ t้igh i scaoll!" -#: ../ex_cmds.c:4717 #, c-format msgid "E661: Sorry, no '%s' help for %s" msgstr "E661: Tแ br๓n orm, nํ aon chabhair '%s' do %s" -#: ../ex_cmds.c:4719 #, c-format msgid "E149: Sorry, no help for %s" msgstr "E149: Tแ br๓n orm, nํl aon chabhair do %s" -#: ../ex_cmds.c:4751 #, c-format msgid "Sorry, help file \"%s\" not found" msgstr "Tแ br๓n orm, comhad cabhrach \"%s\" gan aimsi๚" -#: ../ex_cmds.c:5323 #, c-format -msgid "E150: Not a directory: %s" -msgstr "E150: Nํ comhadlann ้: %s" +msgid "E151: No match: %s" +msgstr "E151: Gan meaitseแil: %s" -#: ../ex_cmds.c:5446 #, c-format msgid "E152: Cannot open %s for writing" msgstr "E152: Nํ f้idir %s a oscailt chun scrํobh ann" -#: ../ex_cmds.c:5471 #, c-format msgid "E153: Unable to open %s for reading" msgstr "E153: Nํ f้idir %s a oscailt chun ้ a l้amh" -#: ../ex_cmds.c:5500 #, c-format msgid "E670: Mix of help file encodings within a language: %s" msgstr "E670: Ionch๓duithe ้ags๚la do chomhaid chabhracha i dteanga aonair: %s" -#: ../ex_cmds.c:5565 #, c-format msgid "E154: Duplicate tag \"%s\" in file %s/%s" msgstr "E154: Clib dh๚blach \"%s\" i gcomhad %s/%s" -#: ../ex_cmds.c:5687 +#, c-format +msgid "E150: Not a directory: %s" +msgstr "E150: Nํ comhadlann ้: %s" + #, c-format msgid "E160: Unknown sign command: %s" msgstr "E160: Ord๚ anaithnid comhartha: %s" -#: ../ex_cmds.c:5704 msgid "E156: Missing sign name" msgstr "E156: Ainm comhartha ar iarraidh" -#: ../ex_cmds.c:5746 msgid "E612: Too many signs defined" msgstr "E612: An iomarca comharthaํ sainmhํnithe" -#: ../ex_cmds.c:5813 #, c-format msgid "E239: Invalid sign text: %s" msgstr "E239: T้acs neamhbhailํ comhartha: %s" -#: ../ex_cmds.c:5844 ../ex_cmds.c:6035 #, c-format msgid "E155: Unknown sign: %s" msgstr "E155: Comhartha anaithnid: %s" -#: ../ex_cmds.c:5877 msgid "E159: Missing sign number" msgstr "E159: Uimhir chomhartha ar iarraidh" -#: ../ex_cmds.c:5971 #, c-format msgid "E158: Invalid buffer name: %s" msgstr "E158: Ainm maolแin neamhbhailํ: %s" -#: ../ex_cmds.c:6008 +msgid "E934: Cannot jump to a buffer that does not have a name" +msgstr "E934: Nํ f้idir l้im go maolแn gan ainm" + #, c-format -msgid "E157: Invalid sign ID: %<PRId64>" -msgstr "E157: ID neamhbhailํ comhartha: %<PRId64>" +msgid "E157: Invalid sign ID: %ld" +msgstr "E157: ID neamhbhailํ comhartha: %ld" + +#, c-format +msgid "E885: Not possible to change sign %s" +msgstr "E885: Nํ f้idir an comhartha a athr๚: %s" + +msgid " (NOT FOUND)" +msgstr " (AR IARRAIDH)" -#: ../ex_cmds.c:6066 msgid " (not supported)" msgstr " (nํl an rogha seo ar fแil)" -#: ../ex_cmds.c:6169 msgid "[Deleted]" msgstr "[Scriosta]" -#: ../ex_cmds2.c:139 +msgid "No old files" +msgstr "Gan seanchomhaid" + msgid "Entering Debug mode. Type \"cont\" to continue." msgstr "M๓d dํfhabhtaithe แ thos๚. Cl๓scrํobh \"cont\" chun lean๚int." -#: ../ex_cmds2.c:143 ../ex_docmd.c:759 #, c-format -msgid "line %<PRId64>: %s" -msgstr "lํne %<PRId64>: %s" +msgid "line %ld: %s" +msgstr "lํne %ld: %s" -#: ../ex_cmds2.c:145 #, c-format msgid "cmd: %s" msgstr "ord๚: %s" -#: ../ex_cmds2.c:322 +msgid "frame is zero" +msgstr "is nialas ้ an frแma" + #, c-format -msgid "Breakpoint in \"%s%s\" line %<PRId64>" -msgstr "Brisphointe i \"%s%s\" lํne %<PRId64>" +msgid "frame at highest level: %d" +msgstr "frแma ag an leibh้al is airde: %d" + +#, c-format +msgid "Breakpoint in \"%s%s\" line %ld" +msgstr "Brisphointe i \"%s%s\" lํne %ld" -#: ../ex_cmds2.c:581 #, c-format msgid "E161: Breakpoint not found: %s" msgstr "E161: Brisphointe gan aimsi๚: %s" -#: ../ex_cmds2.c:611 msgid "No breakpoints defined" msgstr "Nํl aon bhrisphointe socraithe" -#: ../ex_cmds2.c:617 #, c-format -msgid "%3d %s %s line %<PRId64>" -msgstr "%3d %s %s lํne %<PRId64>" +msgid "%3d %s %s line %ld" +msgstr "%3d %s %s lํne %ld" -#: ../ex_cmds2.c:942 msgid "E750: First use \":profile start {fname}\"" msgstr "E750: ฺsแid \":profile start {ainm}\" ar dt๚s" -#: ../ex_cmds2.c:1269 #, c-format msgid "Save changes to \"%s\"?" msgstr "Sแbhแil athruithe ar \"%s\"?" -#: ../ex_cmds2.c:1271 ../ex_docmd.c:8851 msgid "Untitled" msgstr "Gan Teideal" -#: ../ex_cmds2.c:1421 #, c-format msgid "E162: No write since last change for buffer \"%s\"" msgstr "E162: Athraํodh maolแn \"%s\" ach nach bhfuil s้ sแbhแilte ๓ shin" -#: ../ex_cmds2.c:1480 msgid "Warning: Entered other buffer unexpectedly (check autocommands)" msgstr "Rabhadh: Chuathas i maolแn eile go tobann (seiceแil na huathorduithe)" -#: ../ex_cmds2.c:1826 msgid "E163: There is only one file to edit" msgstr "E163: Nํl ach aon chomhad amhแin le cur in eagar" -#: ../ex_cmds2.c:1828 msgid "E164: Cannot go before first file" msgstr "E164: Nํ f้idir a dhul roimh an ch้ad chomhad" -#: ../ex_cmds2.c:1830 msgid "E165: Cannot go beyond last file" msgstr "E165: Nํ f้idir a dhul thar an gcomhad deireanach" -#: ../ex_cmds2.c:2175 #, c-format msgid "E666: compiler not supported: %s" msgstr "E666: nํ ghlactar leis an tiomsaitheoir: %s" -#: ../ex_cmds2.c:2257 #, c-format msgid "Searching for \"%s\" in \"%s\"" msgstr "Ag d้anamh cuardach ar \"%s\" i \"%s\"" -#: ../ex_cmds2.c:2284 #, c-format msgid "Searching for \"%s\"" msgstr "Ag d้anamh cuardach ar \"%s\"" -#: ../ex_cmds2.c:2307 #, c-format -msgid "not found in 'runtimepath': \"%s\"" -msgstr "gan aimsi๚ i 'runtimepath': \"%s\"" +msgid "not found in '%s': \"%s\"" +msgstr "gan aimsi๚ in '%s': \"%s\"" + +msgid "Source Vim script" +msgstr "Foinsigh script Vim" -#: ../ex_cmds2.c:2472 #, c-format msgid "Cannot source a directory: \"%s\"" msgstr "Nํ f้idir comhadlann a l้amh: \"%s\"" -#: ../ex_cmds2.c:2518 #, c-format msgid "could not source \"%s\"" msgstr "nํorbh fh้idir \"%s\" a l้amh" -#: ../ex_cmds2.c:2520 #, c-format -msgid "line %<PRId64>: could not source \"%s\"" -msgstr "lํne %<PRId64>: nํorbh fh้idir \"%s\" a fhoinsi๚" +msgid "line %ld: could not source \"%s\"" +msgstr "lํne %ld: nํorbh fh้idir \"%s\" a fhoinsi๚" -#: ../ex_cmds2.c:2535 #, c-format msgid "sourcing \"%s\"" msgstr "\"%s\" แ fhoinsi๚" -#: ../ex_cmds2.c:2537 #, c-format -msgid "line %<PRId64>: sourcing \"%s\"" -msgstr "lํne %<PRId64>: \"%s\" แ fhoinsi๚" +msgid "line %ld: sourcing \"%s\"" +msgstr "lํne %ld: \"%s\" แ fhoinsi๚" -#: ../ex_cmds2.c:2693 #, c-format msgid "finished sourcing %s" msgstr "deireadh ag foinsi๚ %s" -#: ../ex_cmds2.c:2765 +#, c-format +msgid "continuing in %s" +msgstr "ag lean๚int i %s" + msgid "modeline" msgstr "m๓dlํne" -#: ../ex_cmds2.c:2767 msgid "--cmd argument" msgstr "arg๓int --cmd" -#: ../ex_cmds2.c:2769 msgid "-c argument" msgstr "arg๓int -c" -#: ../ex_cmds2.c:2771 msgid "environment variable" msgstr "athr๓g thimpeallachta" -#: ../ex_cmds2.c:2773 msgid "error handler" msgstr "lแimhseแlaํ earrแidํ" -#: ../ex_cmds2.c:3020 msgid "W15: Warning: Wrong line separator, ^M may be missing" msgstr "" "W15: Rabhadh: Deighilteoir lํnte mํcheart, is f้idir go bhfuil ^M ar iarraidh" -#: ../ex_cmds2.c:3139 msgid "E167: :scriptencoding used outside of a sourced file" msgstr "E167: nํ ๚sแidtear :scriptencoding ach i gcomhad foinsithe" -#: ../ex_cmds2.c:3166 msgid "E168: :finish used outside of a sourced file" msgstr "E168: nํ ๚sแidtear :finish ach i gcomhaid foinsithe" -#: ../ex_cmds2.c:3389 #, c-format msgid "Current %slanguage: \"%s\"" msgstr "%sTeanga faoi lแthair: \"%s\"" -#: ../ex_cmds2.c:3404 #, c-format msgid "E197: Cannot set language to \"%s\"" msgstr "E197: Nํ f้idir an teanga a shocr๚ mar \"%s\"" -#. don't redisplay the window -#. don't wait for return -#: ../ex_docmd.c:387 msgid "Entering Ex mode. Type \"visual\" to go to Normal mode." msgstr "M๓d Ex แ thos๚. Cl๓scrํobh \"visual\" le haghaidh an ghnแthmh๓d." # in FARF -KPS -#: ../ex_docmd.c:428 msgid "E501: At end-of-file" msgstr "E501: Ag an chomhadchrํoch" -#: ../ex_docmd.c:513 msgid "E169: Command too recursive" msgstr "E169: Ord๚ r๓-athch๚rsach" -#: ../ex_docmd.c:1006 #, c-format msgid "E605: Exception not caught: %s" msgstr "E605: Eisceacht gan lแimhseแil: %s" -#: ../ex_docmd.c:1085 msgid "End of sourced file" msgstr "Crํoch chomhaid foinsithe" -#: ../ex_docmd.c:1086 msgid "End of function" msgstr "Crํoch fheidhme" -#: ../ex_docmd.c:1628 msgid "E464: Ambiguous use of user-defined command" msgstr "E464: ฺsแid athbhrํoch d'ord๚ saincheaptha" -#: ../ex_docmd.c:1638 msgid "E492: Not an editor command" msgstr "E492: Nํl ina ord๚ eagarth๓ra" -#: ../ex_docmd.c:1729 msgid "E493: Backwards range given" msgstr "E493: Raon droim ar ais" -#: ../ex_docmd.c:1733 msgid "Backwards range given, OK to swap" msgstr "Raon droim ar ais, babhtแil" -#. append -#. typed wrong -#: ../ex_docmd.c:1787 msgid "E494: Use w or w>>" msgstr "E494: Bain ๚sแid as w n๓ w>>" -#: ../ex_docmd.c:3454 -msgid "E319: The command is not available in this version" +msgid "E319: Sorry, the command is not available in this version" msgstr "E319: Tแ br๓n orm, nํl an t-ord๚ ar fแil sa leagan seo" -#: ../ex_docmd.c:3752 msgid "E172: Only one file name allowed" msgstr "E172: Nํ cheadaํtear ach aon ainm comhaid amhแin" -#: ../ex_docmd.c:4238 msgid "1 more file to edit. Quit anyway?" msgstr "1 comhad le cur in eagar f๓s. Scoir mar sin f้in?" -#: ../ex_docmd.c:4242 #, c-format msgid "%d more files to edit. Quit anyway?" msgstr "%d comhad le cur in eagar f๓s. Scoir mar sin f้in?" -#: ../ex_docmd.c:4248 msgid "E173: 1 more file to edit" msgstr "E173: 1 chomhad le heagr๚ f๓s" -#: ../ex_docmd.c:4250 #, c-format -msgid "E173: %<PRId64> more files to edit" -msgstr "E173: %<PRId64> comhad le cur in eagar" +msgid "E173: %ld more files to edit" +msgstr "E173: %ld comhad le cur in eagar" -#: ../ex_docmd.c:4320 msgid "E174: Command already exists: add ! to replace it" msgstr "E174: Tแ an t-ord๚ ann cheana: cuir ! leis chun sแr๚" -#: ../ex_docmd.c:4432 msgid "" "\n" -" Name Args Range Complete Definition" +" Name Args Address Complete Definition" msgstr "" "\n" -" Ainm Arg Raon Iomlแn Sainmhํni๚" +" Ainm Arg Seoladh Iomlแn Sainmhํni๚" -#: ../ex_docmd.c:4516 msgid "No user-defined commands found" msgstr "Nํl aon ord๚ aimsithe atแ sainithe ag an ๚sแideoir" -#: ../ex_docmd.c:4538 msgid "E175: No attribute specified" msgstr "E175: Nํl aon aitreab๚id sainithe" -#: ../ex_docmd.c:4583 msgid "E176: Invalid number of arguments" msgstr "E176: Tแ lํon na n-arg๓intํ mํcheart" -#: ../ex_docmd.c:4594 msgid "E177: Count cannot be specified twice" msgstr "E177: Nํ cheadaํtear an t-แireamh a bheith tugtha faoi dh๓" -#: ../ex_docmd.c:4603 msgid "E178: Invalid default value for count" msgstr "E178: Luach r้amhshocraithe neamhbhailํ ar แireamh" -#: ../ex_docmd.c:4625 msgid "E179: argument required for -complete" msgstr "E179: tแ gแ le harg๓int i ndiaidh -complete" -#: ../ex_docmd.c:4635 +msgid "E179: argument required for -addr" +msgstr "E179: tแ gแ le harg๓int i ndiaidh -addr" + #, c-format msgid "E181: Invalid attribute: %s" msgstr "E181: Aitreab๚id neamhbhailํ: %s" -#: ../ex_docmd.c:4678 msgid "E182: Invalid command name" msgstr "E182: Ainm neamhbhailํ ordaithe" -#: ../ex_docmd.c:4691 msgid "E183: User defined commands must start with an uppercase letter" msgstr "" "E183: Caithfidh ceannlitir a bheith ar dt๚s orduithe atแ sainithe ag an " "๚sแideoir" -#: ../ex_docmd.c:4696 -#, fuzzy msgid "E841: Reserved name, cannot be used for user defined command" -msgstr "E464: ฺsแid athbhrํoch d'ord๚ saincheaptha" +msgstr "" +"E841: Ainm in แirithe, nํ f้idir ้ a chur ar ord๚ sainithe ag an ๚sแideoir" -#: ../ex_docmd.c:4751 #, c-format msgid "E184: No such user-defined command: %s" msgstr "E184: Nํl a leith้id d'ord๚ saincheaptha: %s" -#: ../ex_docmd.c:5219 +#, c-format +msgid "E180: Invalid address type value: %s" +msgstr "E180: Cineแl neamhbhailํ seolta: %s" + #, c-format msgid "E180: Invalid complete value: %s" msgstr "E180: Luach iomlแn neamhbhailํ: %s" -#: ../ex_docmd.c:5225 msgid "E468: Completion argument only allowed for custom completion" msgstr "" "E468: Nํ cheadaํtear arg๓int chomhlแnaithe ach le comhlแn๚ saincheaptha" -#: ../ex_docmd.c:5231 msgid "E467: Custom completion requires a function argument" msgstr "E467: Tแ gแ le harg๓int fheidhme le comhlแn๚ saincheaptha" -#: ../ex_docmd.c:5257 -#, fuzzy, c-format +msgid "unknown" +msgstr "anaithnid" + +#, c-format msgid "E185: Cannot find color scheme '%s'" -msgstr "E185: Sc้im dathanna %s gan aimsi๚" +msgstr "E185: Sc้im dathanna '%s' gan aimsi๚" -#: ../ex_docmd.c:5263 msgid "Greetings, Vim user!" msgstr "Dia duit, a ๚sแideoir Vim!" -#: ../ex_docmd.c:5431 msgid "E784: Cannot close last tab page" -msgstr "E784: Nํ f้idir an leathanach cluaisํn deiridh a dh๚nadh" +msgstr "E784: Nํ f้idir an leathanach cluaisํnํ deiridh a dh๚nadh" -#: ../ex_docmd.c:5462 msgid "Already only one tab page" -msgstr "Nํl ach leathanach cluaisํn amhแin cheana f้in" +msgstr "Nํl ach leathanach cluaisํnํ amhแin cheana f้in" + +msgid "Edit File in new window" +msgstr "Cuir comhad in eagar i bhfuinneog nua" -#: ../ex_docmd.c:6004 #, c-format msgid "Tab page %d" msgstr "Leathanach cluaisํn %d" -#: ../ex_docmd.c:6295 msgid "No swap file" msgstr "Nํl aon chomhad babhtแla ann" -#: ../ex_docmd.c:6478 +msgid "Append File" +msgstr "Cuir Comhad i nDeireadh" + msgid "E747: Cannot change directory, buffer is modified (add ! to override)" msgstr "" "E747: Nํ f้idir an chomhadlann a athr๚, mionathraํodh an maolแn (cuir ! leis " "an ord๚ chun sแr๚)" -#: ../ex_docmd.c:6485 msgid "E186: No previous directory" msgstr "E186: Nํl aon chomhadlann roimhe seo" -#: ../ex_docmd.c:6530 msgid "E187: Unknown" msgstr "E187: Anaithnid" -#: ../ex_docmd.c:6610 msgid "E465: :winsize requires two number arguments" msgstr "E465: nํ folแir dhแ arg๓int uimhri๚la le :winsize" -#: ../ex_docmd.c:6655 +#, c-format +msgid "Window position: X %d, Y %d" +msgstr "Ionad na fuinneoige: X %d, Y %d" + msgid "E188: Obtaining window position not implemented for this platform" msgstr "E188: Nํ f้idir ionad na fuinneoige a fhแil amach ar an ch๓ras seo" -#: ../ex_docmd.c:6662 msgid "E466: :winpos requires two number arguments" msgstr "E466: nํ folแir dhแ arg๓int uimhri๚la le :winpos" -#: ../ex_docmd.c:7241 +msgid "E930: Cannot use :redir inside execute()" +msgstr "E930: Nํ f้idir :redir a ๚sแid laistigh de execute()" + +msgid "Save Redirection" +msgstr "Sแbhแil Atreor๚" + +msgid "Save View" +msgstr "Sแbhแil an tAmharc" + +msgid "Save Session" +msgstr "Sแbhแil an Seisi๚n" + +msgid "Save Setup" +msgstr "Sแbhแil an Socr๚" + #, c-format msgid "E739: Cannot create directory: %s" msgstr "E739: Nํ f้idir comhadlann a chruth๚: %s" -#: ../ex_docmd.c:7268 #, c-format msgid "E189: \"%s\" exists (add ! to override)" msgstr "E189: Tแ \"%s\" ann cheana (cuir ! leis an ord๚ chun sแr๚)" -#: ../ex_docmd.c:7273 #, c-format msgid "E190: Cannot open \"%s\" for writing" msgstr "E190: Nํ f้idir \"%s\" a oscailt chun l้amh" #. set mark -#: ../ex_docmd.c:7294 msgid "E191: Argument must be a letter or forward/backward quote" msgstr "E191: Caithfidh an arg๓int a bheith litir n๓ comhartha athfhriotal" -#: ../ex_docmd.c:7333 msgid "E192: Recursive use of :normal too deep" msgstr "E192: athch๚rsแil :normal r๓dhomhain" -#: ../ex_docmd.c:7807 +msgid "E809: #< is not available without the +eval feature" +msgstr "E809: nํl #< ar fแil gan ghn้ +eval" + msgid "E194: No alternate file name to substitute for '#'" msgstr "E194: Nํl aon ainm comhaid a chur in ionad '#'" -#: ../ex_docmd.c:7841 msgid "E495: no autocommand file name to substitute for \"<afile>\"" msgstr "E495: nํl aon ainm comhaid uathordaithe le cur in ionad \"<afile>\"" -#: ../ex_docmd.c:7850 msgid "E496: no autocommand buffer number to substitute for \"<abuf>\"" msgstr "E496: nํl aon uimhir mhaolแn uathordaithe le cur in ionad \"<abuf>\"" -#: ../ex_docmd.c:7861 msgid "E497: no autocommand match name to substitute for \"<amatch>\"" msgstr "" "E497: nํl aon ainm meaitseแla uathordaithe le cur in ionad \"<amatch>\"" -#: ../ex_docmd.c:7870 msgid "E498: no :source file name to substitute for \"<sfile>\"" msgstr "E498: nํl aon ainm comhaid :source le cur in ionad \"<sfile>\"" -#: ../ex_docmd.c:7876 -#, fuzzy msgid "E842: no line number to use for \"<slnum>\"" -msgstr "E498: nํl aon ainm comhaid :source le cur in ionad \"<sfile>\"" +msgstr "E842: nํl aon lํne-uimhir ar fแil le haghaidh \"<slnum>\"" -#: ../ex_docmd.c:7903 -#, fuzzy, c-format +#, no-c-format msgid "E499: Empty file name for '%' or '#', only works with \":p:h\"" msgstr "" "E499: Ainm comhaid folamh le haghaidh '%' n๓ '#', oibreoidh s้ le \":p:h\" " "amhแin" -#: ../ex_docmd.c:7905 msgid "E500: Evaluates to an empty string" msgstr "E500: Luachแiltear ้ seo mar theaghrแn folamh" -#: ../ex_docmd.c:8838 msgid "E195: Cannot open viminfo file for reading" msgstr "E195: Nํ f้idir an comhad viminfo a oscailt chun l้amh" -#: ../ex_eval.c:464 +msgid "E196: No digraphs in this version" +msgstr "E196: Nํ cheadaํtear d้ghraif sa leagan seo" + msgid "E608: Cannot :throw exceptions with 'Vim' prefix" msgstr "E608: Nํ f้idir eisceachtaํ a :throw le r้imํr 'Vim'" #. always scroll up, don't overwrite -#: ../ex_eval.c:496 #, c-format msgid "Exception thrown: %s" msgstr "Gineadh eisceacht: %s" -#: ../ex_eval.c:545 #, c-format msgid "Exception finished: %s" msgstr "Eisceacht curtha i gcrํch: %s" -#: ../ex_eval.c:546 #, c-format msgid "Exception discarded: %s" msgstr "Eisceacht curtha i leataobh: %s" -#: ../ex_eval.c:588 ../ex_eval.c:634 #, c-format -msgid "%s, line %<PRId64>" -msgstr "%s, lํne %<PRId64>" +msgid "%s, line %ld" +msgstr "%s, lํne %ld" #. always scroll up, don't overwrite -#: ../ex_eval.c:608 #, c-format msgid "Exception caught: %s" msgstr "Lแimhseแladh eisceacht: %s" -#: ../ex_eval.c:676 #, c-format msgid "%s made pending" msgstr "%s ar feitheamh anois" -#: ../ex_eval.c:679 #, c-format msgid "%s resumed" msgstr "atosaํodh %s" -#: ../ex_eval.c:683 #, c-format msgid "%s discarded" msgstr "%s curtha i leataobh" -#: ../ex_eval.c:708 msgid "Exception" msgstr "Eisceacht" -#: ../ex_eval.c:713 msgid "Error and interrupt" msgstr "Earrแid agus idirbhriseadh" -#: ../ex_eval.c:715 msgid "Error" msgstr "Earrแid" #. if (pending & CSTP_INTERRUPT) -#: ../ex_eval.c:717 msgid "Interrupt" msgstr "Idirbhriseadh" -#: ../ex_eval.c:795 msgid "E579: :if nesting too deep" msgstr "E579: :if neadaithe r๓dhomhain" -#: ../ex_eval.c:830 msgid "E580: :endif without :if" msgstr "E580: :endif gan :if" -#: ../ex_eval.c:873 msgid "E581: :else without :if" msgstr "E581: :else gan :if" -#: ../ex_eval.c:876 msgid "E582: :elseif without :if" msgstr "E582: :elseif gan :if" -#: ../ex_eval.c:880 msgid "E583: multiple :else" msgstr "E583: :else iomad๚la" -#: ../ex_eval.c:883 msgid "E584: :elseif after :else" msgstr "E584: :elseif i ndiaidh :else" -#: ../ex_eval.c:941 msgid "E585: :while/:for nesting too deep" msgstr "E585: :while/:for neadaithe r๓dhomhain" -#: ../ex_eval.c:1028 msgid "E586: :continue without :while or :for" msgstr "E586: :continue gan :while nแ :for" -#: ../ex_eval.c:1061 msgid "E587: :break without :while or :for" msgstr "E587: :break gan :while nแ :for" -#: ../ex_eval.c:1102 msgid "E732: Using :endfor with :while" msgstr "E732: :endfor แ ๚sแid le :while" -#: ../ex_eval.c:1104 msgid "E733: Using :endwhile with :for" msgstr "E733: :endwhile แ ๚sแid le :for" -#: ../ex_eval.c:1247 msgid "E601: :try nesting too deep" msgstr "E601: :try neadaithe r๓dhomhain" -#: ../ex_eval.c:1317 msgid "E603: :catch without :try" msgstr "E603: :catch gan :try" #. Give up for a ":catch" after ":finally" and ignore it. #. * Just parse. -#: ../ex_eval.c:1332 msgid "E604: :catch after :finally" msgstr "E604: :catch i ndiaidh :finally" -#: ../ex_eval.c:1451 msgid "E606: :finally without :try" msgstr "E606: :finally gan :try" #. Give up for a multiple ":finally" and ignore it. -#: ../ex_eval.c:1467 msgid "E607: multiple :finally" msgstr "E607: :finally iomad๚la" -#: ../ex_eval.c:1571 msgid "E602: :endtry without :try" msgstr "E602: :endtry gan :try" -#: ../ex_eval.c:2026 msgid "E193: :endfunction not inside a function" msgstr "E193: Caithfidh :endfunction a bheith isteach i bhfeidhm" -#: ../ex_getln.c:1643 msgid "E788: Not allowed to edit another buffer now" msgstr "E788: Nํl cead agat maolแn eile a chur in eagar anois" -#: ../ex_getln.c:1656 msgid "E811: Not allowed to change buffer information now" msgstr "E811: Nํl cead agat faisn้is an mhaolแin a athr๚ anois" -#: ../ex_getln.c:3178 msgid "tagname" msgstr "clibainm" -#: ../ex_getln.c:3181 msgid " kind file\n" msgstr " cineแl comhaid\n" -#: ../ex_getln.c:4799 msgid "'history' option is zero" msgstr "tแ an rogha 'history' nialas" -#: ../ex_getln.c:5046 #, c-format msgid "" "\n" @@ -1975,310 +1620,230 @@ msgstr "" # this gets plugged into the %s in the previous string, # hence the colon -#: ../ex_getln.c:5047 msgid "Command Line" msgstr "Lํne na nOrduithe:" -#: ../ex_getln.c:5048 msgid "Search String" msgstr "Teaghrแn Cuardaigh" -#: ../ex_getln.c:5049 msgid "Expression" msgstr "Sloinn:" -#: ../ex_getln.c:5050 msgid "Input Line" msgstr "Lํne an Ionchuir:" -#: ../ex_getln.c:5117 +msgid "Debug Line" +msgstr "Lํne Dhํfhabhtaithe" + msgid "E198: cmd_pchar beyond the command length" msgstr "E198: cmd_pchar os cionn fad an ordaithe" -#: ../ex_getln.c:5279 msgid "E199: Active window or buffer deleted" msgstr "E199: Scriosadh an fhuinneog reatha n๓ an maolแn reatha" -#: ../file_search.c:203 -msgid "E854: path too long for completion" -msgstr "" - -#: ../file_search.c:446 -#, c-format -msgid "" -"E343: Invalid path: '**[number]' must be at the end of the path or be " -"followed by '%s'." -msgstr "" -"E343: Conair neamhbhailํ: nํ m๓r '**[uimhir]' a bheith ag deireadh na " -"conaire, n๓ le '%s' ina dhiaidh." - -#: ../file_search.c:1505 -#, c-format -msgid "E344: Can't find directory \"%s\" in cdpath" -msgstr "E344: Nํ f้idir comhadlann \"%s\" a aimsi๚ sa cdpath" - -#: ../file_search.c:1508 -#, c-format -msgid "E345: Can't find file \"%s\" in path" -msgstr "E345: Nํ f้idir comhad \"%s\" a aimsi๚ sa chonair" - -#: ../file_search.c:1512 -#, c-format -msgid "E346: No more directory \"%s\" found in cdpath" -msgstr "E346: Nํl comhadlann \"%s\" sa cdpath a thuilleadh" - -#: ../file_search.c:1515 -#, c-format -msgid "E347: No more file \"%s\" found in path" -msgstr "E347: Nํl comhad \"%s\" sa chonair a thuilleadh" - -#: ../fileio.c:137 msgid "E812: Autocommands changed buffer or buffer name" msgstr "E812: Bhํ maolแn n๓ ainm maolแin athraithe ag orduithe uathoibrํocha" -#: ../fileio.c:368 msgid "Illegal file name" msgstr "Ainm comhaid neamhcheadaithe" -#: ../fileio.c:395 ../fileio.c:476 ../fileio.c:2543 ../fileio.c:2578 msgid "is a directory" msgstr "is comhadlann ้" -#: ../fileio.c:397 msgid "is not a file" msgstr "nํ comhad ้" -#: ../fileio.c:508 ../fileio.c:3522 +msgid "is a device (disabled with 'opendevice' option)" +msgstr "is gl้as ้ seo (dํchumasaithe le rogha 'opendevice')" + msgid "[New File]" msgstr "[Comhad Nua]" -#: ../fileio.c:511 msgid "[New DIRECTORY]" msgstr "[COMHADLANN nua]" -#: ../fileio.c:529 ../fileio.c:532 msgid "[File too big]" msgstr "[Comhad r๓mh๓r]" -#: ../fileio.c:534 msgid "[Permission Denied]" msgstr "[Cead Di๚ltaithe]" -#: ../fileio.c:653 msgid "E200: *ReadPre autocommands made the file unreadable" msgstr "E200: Rinne uathorduithe *ReadPre praiseach as an chomhad" -#: ../fileio.c:655 msgid "E201: *ReadPre autocommands must not change current buffer" msgstr "E201: Nํ cheadaํtear d'uathorduithe *ReadPre an maolแn reatha a athr๚" -#: ../fileio.c:672 -msgid "Nvim: Reading from stdin...\n" +msgid "Vim: Reading from stdin...\n" msgstr "Vim: Ag l้amh ๓n ionchur caighdeแnach...\n" +msgid "Reading from stdin..." +msgstr "Ag l้amh ๓n ionchur caighdeแnach..." + #. Re-opening the original file failed! -#: ../fileio.c:909 msgid "E202: Conversion made file unreadable!" msgstr "E202: Comhad dol้ite i ndiaidh an tiontaithe!" -#. fifo or socket -#: ../fileio.c:1782 msgid "[fifo/socket]" msgstr "[fifo/soic้ad]" # `TITA' ?! -KPS -#. fifo -#: ../fileio.c:1788 msgid "[fifo]" msgstr "[fifo]" -#. or socket -#: ../fileio.c:1794 msgid "[socket]" msgstr "[soic้ad]" -#. or character special -#: ../fileio.c:1801 msgid "[character special]" msgstr "[comhad speisialta den chineแl carachtar]" -#: ../fileio.c:1815 msgid "[CR missing]" msgstr "[CR ar iarraidh]" -#: ../fileio.c:1819 msgid "[long lines split]" msgstr "[lํnte fada deighilte]" -#: ../fileio.c:1823 ../fileio.c:3512 msgid "[NOT converted]" msgstr "[Nอ tiontaithe]" -#: ../fileio.c:1826 ../fileio.c:3515 msgid "[converted]" msgstr "[tiontaithe]" -#: ../fileio.c:1831 #, c-format -msgid "[CONVERSION ERROR in line %<PRId64>]" -msgstr "[EARRมID TIONTAITHE i lํne %<PRId64>]" +msgid "[CONVERSION ERROR in line %ld]" +msgstr "[EARRมID TIONTAITHE i lํne %ld]" -#: ../fileio.c:1835 #, c-format -msgid "[ILLEGAL BYTE in line %<PRId64>]" -msgstr "[BEART NEAMHCHEADAITHE i lํne %<PRId64>]" +msgid "[ILLEGAL BYTE in line %ld]" +msgstr "[BEART NEAMHCHEADAITHE i lํne %ld]" -#: ../fileio.c:1838 msgid "[READ ERRORS]" msgstr "[EARRมIDอ LษIMH]" -#: ../fileio.c:2104 msgid "Can't find temp file for conversion" msgstr "Nํ f้idir comhad sealadach a aimsi๚ le haghaidh tiontaithe" -#: ../fileio.c:2110 msgid "Conversion with 'charconvert' failed" msgstr "Theip ar thiont๚ le 'charconvert'" -#: ../fileio.c:2113 msgid "can't read output of 'charconvert'" msgstr "nํ f้idir an t-aschur ๓ 'charconvert' a l้amh" -#: ../fileio.c:2437 msgid "E676: No matching autocommands for acwrite buffer" msgstr "E676: Nํl aon uathord๚ comhoiri๚naithe le haghaidh maolแin acwrite" -#: ../fileio.c:2466 msgid "E203: Autocommands deleted or unloaded buffer to be written" msgstr "E203: Scrios n๓ dhํluchtaigh uathorduithe an maolแn le scrํobh" -#: ../fileio.c:2486 msgid "E204: Autocommand changed number of lines in unexpected way" msgstr "E204: D'athraigh uathord๚ lํon na lํnte gan choinne" -#: ../fileio.c:2548 ../fileio.c:2565 +msgid "NetBeans disallows writes of unmodified buffers" +msgstr "Nํ cheadaํonn NetBeans maolแin gan athr๚ a bheith scrํofa" + +msgid "Partial writes disallowed for NetBeans buffers" +msgstr "Nํ cheadaํtear maolแin NetBeans a bheith scrํofa go neamhiomlแn" + msgid "is not a file or writable device" msgstr "nํ comhad nแ gl้as inscrํofa แ" -#: ../fileio.c:2601 +msgid "writing to device disabled with 'opendevice' option" +msgstr "dํchumasaํodh scrํobh chuig gl้as le rogha 'opendevice'" + msgid "is read-only (add ! to override)" msgstr "is inl้ite amhแin ้ (cuir ! leis an ord๚ chun sแr๚)" -#: ../fileio.c:2886 msgid "E506: Can't write to backup file (add ! to override)" msgstr "" "E506: Nํ f้idir scrํobh a dh้anamh sa chomhad c๚ltaca (๚sแid ! chun sแr๚)" -#: ../fileio.c:2898 msgid "E507: Close error for backup file (add ! to override)" msgstr "" "E507: Earrแid agus comhad c๚ltaca แ dh๚nadh (cuir ! leis an ord๚ chun sแr๚)" -#: ../fileio.c:2901 msgid "E508: Can't read file for backup (add ! to override)" msgstr "" "E508: Nํ f้idir an comhad c๚ltaca a l้amh (cuir ! leis an ord๚ chun sแr๚)" -#: ../fileio.c:2923 msgid "E509: Cannot create backup file (add ! to override)" msgstr "" "E509: Nํ f้idir comhad c๚ltaca a chruth๚ (cuir ! leis an ord๚ chun sแr๚)" -#: ../fileio.c:3008 msgid "E510: Can't make backup file (add ! to override)" msgstr "" "E510: Nํ f้idir comhad c๚ltaca a chruth๚ (cuir ! leis an ord๚ chun sแr๚)" -#. Can't write without a tempfile! -#: ../fileio.c:3121 +msgid "E460: The resource fork would be lost (add ! to override)" +msgstr "E460: Chaillfํ an forc acmhainne (cuir ! leis an ord๚ chun sแr๚)" + msgid "E214: Can't find temp file for writing" msgstr "E214: Nํ f้idir comhad sealadach a aimsi๚ chun scrํobh ann" -#: ../fileio.c:3134 msgid "E213: Cannot convert (add ! to write without conversion)" msgstr "E213: Nํ f้idir tiont๚ (cuir ! leis an ord๚ chun scrํobh gan tiont๚)" -#: ../fileio.c:3169 msgid "E166: Can't open linked file for writing" msgstr "E166: Nํ f้idir comhad nasctha a oscailt chun scrํobh ann" -#: ../fileio.c:3173 msgid "E212: Can't open file for writing" msgstr "E212: Nํ f้idir comhad a oscailt chun scrํobh ann" -#: ../fileio.c:3363 msgid "E667: Fsync failed" msgstr "E667: Theip ar fsync" -#: ../fileio.c:3398 msgid "E512: Close failed" msgstr "E512: Theip ar d๚nadh" -#: ../fileio.c:3436 msgid "E513: write error, conversion failed (make 'fenc' empty to override)" msgstr "" "E513: earrแid le linn scrํobh, theip ar thiont๚ (๚sแid 'fenc' folamh chun " "sแr๚)" -#: ../fileio.c:3441 #, c-format msgid "" -"E513: write error, conversion failed in line %<PRId64> (make 'fenc' empty to " +"E513: write error, conversion failed in line %ld (make 'fenc' empty to " "override)" msgstr "" -"E513: earrแid le linn scrํofa, theip ar thiont๚ ar lํne %<PRId64> (๚sแid " -"'fenc' folamh le sแr๚)" +"E513: earrแid le linn scrํofa, theip ar thiont๚ ar lํne %ld (๚sแid 'fenc' " +"folamh le sแr๚)" -#: ../fileio.c:3448 msgid "E514: write error (file system full?)" msgstr "E514: earrแid le linn scrํofa (an bhfuil an c๓ras comhaid lแn?)" -#: ../fileio.c:3506 msgid " CONVERSION ERROR" msgstr " EARRมID TIONTAITHE" -#: ../fileio.c:3509 #, c-format -msgid " in line %<PRId64>;" -msgstr " ar lํne %<PRId64>;" +msgid " in line %ld;" +msgstr " ar lํne %ld;" -#: ../fileio.c:3519 msgid "[Device]" msgstr "[Gl้as]" -#: ../fileio.c:3522 msgid "[New]" msgstr "[Nua]" -#: ../fileio.c:3535 msgid " [a]" msgstr " [a]" -#: ../fileio.c:3535 msgid " appended" msgstr " iarcheangailte" -#: ../fileio.c:3537 msgid " [w]" msgstr " [w]" -#: ../fileio.c:3537 msgid " written" msgstr " scrํofa" -#: ../fileio.c:3579 msgid "E205: Patchmode: can't save original file" msgstr "E205: Patchmode: nํ f้idir an comhad bun๚sach a shแbhแil" -#: ../fileio.c:3602 msgid "E206: patchmode: can't touch empty original file" msgstr "E206: patchmode: nํ f้idir an comhad bun๚sach folamh a theagmhแil" -#: ../fileio.c:3616 msgid "E207: Can't delete backup file" msgstr "E207: Nํ f้idir an comhad c๚ltaca a scriosadh" -#: ../fileio.c:3672 msgid "" "\n" "WARNING: Original file may be lost or damaged\n" @@ -2286,96 +1851,75 @@ msgstr "" "\n" "RABHADH: Is f้idir gur caillte n๓ loite an comhad bun๚sach\n" -#: ../fileio.c:3675 msgid "don't quit the editor until the file is successfully written!" msgstr "nแ scoir go dtํ go scrํobhfaํ an comhad!" -#: ../fileio.c:3795 msgid "[dos]" msgstr "[dos]" -#: ../fileio.c:3795 msgid "[dos format]" msgstr "[formแid dos]" -#: ../fileio.c:3801 msgid "[mac]" msgstr "[mac]" -#: ../fileio.c:3801 msgid "[mac format]" msgstr "[formแid mac]" -#: ../fileio.c:3807 msgid "[unix]" msgstr "[unix]" -#: ../fileio.c:3807 msgid "[unix format]" msgstr "[formแid unix]" -#: ../fileio.c:3831 msgid "1 line, " msgstr "1 lํne, " -#: ../fileio.c:3833 #, c-format -msgid "%<PRId64> lines, " -msgstr "%<PRId64> lํne, " +msgid "%ld lines, " +msgstr "%ld lํne, " -#: ../fileio.c:3836 msgid "1 character" msgstr "1 carachtar" -#: ../fileio.c:3838 #, c-format -msgid "%<PRId64> characters" -msgstr "%<PRId64> carachtar" +msgid "%lld characters" +msgstr "%lld carachtar" -#: ../fileio.c:3849 msgid "[noeol]" msgstr "[ganEOL]" -#: ../fileio.c:3849 msgid "[Incomplete last line]" msgstr "[Is neamhiomlแn an lํne dheireanach]" #. don't overwrite messages here #. must give this prompt #. don't use emsg() here, don't want to flush the buffers -#: ../fileio.c:3865 msgid "WARNING: The file has been changed since reading it!!!" msgstr "RABHADH: Athraํodh an comhad ๓ l้adh ้!!!" -#: ../fileio.c:3867 msgid "Do you really want to write to it" msgstr "An bhfuil t๚ cinnte gur mhaith leat ้ a scrํobh" -#: ../fileio.c:4648 #, c-format msgid "E208: Error writing to \"%s\"" msgstr "E208: Earrแid agus \"%s\" แ scrํobh" -#: ../fileio.c:4655 #, c-format msgid "E209: Error closing \"%s\"" msgstr "E209: Earrแid agus \"%s\" แ dh๚nadh" -#: ../fileio.c:4657 #, c-format msgid "E210: Error reading \"%s\"" msgstr "E210: Earrแid agus \"%s\" แ l้amh" -#: ../fileio.c:4883 msgid "E246: FileChangedShell autocommand deleted buffer" msgstr "E246: Scrios uathord๚ FileChangedShell an maolแn" -#: ../fileio.c:4894 #, c-format msgid "E211: File \"%s\" no longer available" msgstr "E211: Nํl comhad \"%s\" ar fแil feasta" -#: ../fileio.c:4906 #, c-format msgid "" "W12: Warning: File \"%s\" has changed and the buffer was changed in Vim as " @@ -2383,39 +1927,31 @@ msgid "" msgstr "" "W12: Rabhadh: Athraํodh comhad \"%s\" agus athraํodh an maolแn i Vim fosta" -#: ../fileio.c:4907 msgid "See \":help W12\" for more info." msgstr "Bain triail as \":help W12\" chun tuilleadh eolais a fhแil." -#: ../fileio.c:4910 #, c-format msgid "W11: Warning: File \"%s\" has changed since editing started" msgstr "W11: Rabhadh: Athraํodh comhad \"%s\" ๓ tosaํodh ้ a chur in eagar" -#: ../fileio.c:4911 msgid "See \":help W11\" for more info." msgstr "Bain triail as \":help W11\" chun tuilleadh eolais a fhแil." -#: ../fileio.c:4914 #, c-format msgid "W16: Warning: Mode of file \"%s\" has changed since editing started" msgstr "" "W16: Rabhadh: Athraํodh m๓d an chomhaid \"%s\" ๓ tosaํodh ้ a chur in eagar" -#: ../fileio.c:4915 msgid "See \":help W16\" for more info." msgstr "Bain triail as \":help W16\" chun tuilleadh eolais a fhแil." -#: ../fileio.c:4927 #, c-format msgid "W13: Warning: File \"%s\" has been created after editing started" msgstr "W13: Rabhadh: Cruthaํodh comhad \"%s\" ๓ tosaํodh ้ a chur in eagar" -#: ../fileio.c:4947 msgid "Warning" msgstr "Rabhadh" -#: ../fileio.c:4948 msgid "" "&OK\n" "&Load File" @@ -2423,48 +1959,45 @@ msgstr "" "&OK\n" "&Luchtaigh Comhad" -#: ../fileio.c:5065 #, c-format msgid "E462: Could not prepare for reloading \"%s\"" msgstr "E462: Nํ f้idir \"%s\" a ullmh๚ le haghaidh athluchtaithe" -#: ../fileio.c:5078 #, c-format msgid "E321: Could not reload \"%s\"" msgstr "E321: Nํ f้idir \"%s\" a athlucht๚" -#: ../fileio.c:5601 msgid "--Deleted--" msgstr "--Scriosta--" -#: ../fileio.c:5732 #, c-format msgid "auto-removing autocommand: %s <buffer=%d>" msgstr "uathord๚ แ bhaint go huathoibrํoch: %s <maolแn=%d>" #. the group doesn't exist -#: ../fileio.c:5772 #, c-format msgid "E367: No such group: \"%s\"" msgstr "E367: Nํl a leith้id de ghr๚pa: \"%s\"" -#: ../fileio.c:5897 +msgid "E936: Cannot delete the current group" +msgstr "E936: Nํ f้idir an gr๚pa reatha a scriosadh" + +msgid "W19: Deleting augroup that is still in use" +msgstr "W19: Iarracht ar augroup atแ f๓s in ๚sแid a scriosadh" + #, c-format msgid "E215: Illegal character after *: %s" msgstr "E215: Carachtar neamhcheadaithe i ndiaidh *: %s" -#: ../fileio.c:5905 #, c-format msgid "E216: No such event: %s" msgstr "E216: Nํl a leith้id de theagmhas: %s" -#: ../fileio.c:5907 #, c-format msgid "E216: No such group or event: %s" msgstr "E216: Nํl a leith้id de ghr๚pa n๓ theagmhas: %s" #. Highlight title -#: ../fileio.c:6090 msgid "" "\n" "--- Auto-Commands ---" @@ -2472,765 +2005,567 @@ msgstr "" "\n" "--- Uathorduithe ---" -#: ../fileio.c:6293 #, c-format msgid "E680: <buffer=%d>: invalid buffer number " msgstr "E680: <maolแn=%d>: uimhir neamhbhailํ mhaolแin " -#: ../fileio.c:6370 msgid "E217: Can't execute autocommands for ALL events" msgstr "E217: Nํ f้idir uathorduithe a rith i gcomhair teagmhas UILE" -#: ../fileio.c:6393 msgid "No matching autocommands" msgstr "Nํl aon uathord๚ comhoiri๚naithe" -#: ../fileio.c:6831 msgid "E218: autocommand nesting too deep" msgstr "E218: uathord๚ neadaithe r๓dhomhain" -#: ../fileio.c:7143 #, c-format msgid "%s Auto commands for \"%s\"" msgstr "%s Uathorduithe do \"%s\"" -#: ../fileio.c:7149 #, c-format msgid "Executing %s" msgstr "%s แ rith" -#: ../fileio.c:7211 #, c-format msgid "autocommand %s" msgstr "uathord๚ %s" -#: ../fileio.c:7795 msgid "E219: Missing {." msgstr "E219: { ar iarraidh." -#: ../fileio.c:7797 msgid "E220: Missing }." msgstr "E220: } ar iarraidh." -#: ../fold.c:93 msgid "E490: No fold found" msgstr "E490: Nํor aimsํodh aon fhilleadh" -#: ../fold.c:544 msgid "E350: Cannot create fold with current 'foldmethod'" msgstr "E350: Nํ f้idir filleadh a chruth๚ leis an 'foldmethod' reatha" -#: ../fold.c:546 msgid "E351: Cannot delete fold with current 'foldmethod'" msgstr "E351: Nํ f้idir filleadh a scriosadh leis an 'foldmethod' reatha" -#: ../fold.c:1784 #, c-format -msgid "+--%3ld lines folded " -msgstr "+--%3ld lํne fillte " +msgid "+--%3ld line folded " +msgid_plural "+--%3ld lines folded " +msgstr[0] "+--%3ld lํne fillte " +msgstr[1] "+--%3ld lํne fillte " +msgstr[2] "+--%3ld lํne fillte " +msgstr[3] "+--%3ld lํne fillte " +msgstr[4] "+--%3ld lํne fillte " -#. buffer has already been read -#: ../getchar.c:273 msgid "E222: Add to read buffer" msgstr "E222: Cuir leis an maolแn l้ite" -#: ../getchar.c:2040 msgid "E223: recursive mapping" msgstr "E223: mapแil athch๚rsach" -#: ../getchar.c:2849 #, c-format msgid "E224: global abbreviation already exists for %s" msgstr "E224: tแ giorr๚chแn comhchoiteann ann cheana le haghaidh %s" -#: ../getchar.c:2852 #, c-format msgid "E225: global mapping already exists for %s" msgstr "E225: tแ mapแil chomhchoiteann ann cheana le haghaidh %s" -#: ../getchar.c:2952 #, c-format msgid "E226: abbreviation already exists for %s" msgstr "E226: tแ giorr๚chแn ann cheana le haghaidh %s" -#: ../getchar.c:2955 #, c-format msgid "E227: mapping already exists for %s" msgstr "E227: tแ mapแil ann cheana le haghaidh %s" -#: ../getchar.c:3008 msgid "No abbreviation found" msgstr "Nํor aimsํodh aon ghiorr๚chแn" -#: ../getchar.c:3010 msgid "No mapping found" msgstr "Nํor aimsํodh aon mhapแil" -#: ../getchar.c:3974 msgid "E228: makemap: Illegal mode" msgstr "E228: makemap: M๓d neamhcheadaithe" -#. key value of 'cedit' option -#. type of cmdline window or 0 -#. result of cmdline window or 0 -#: ../globals.h:924 -msgid "--No lines in buffer--" -msgstr "--Tแ an maolแn folamh--" - -#. -#. * The error messages that can be shared are included here. -#. * Excluded are errors that are only used once and debugging messages. -#. -#: ../globals.h:996 -msgid "E470: Command aborted" -msgstr "E470: Ord๚ tobscortha" +msgid "E851: Failed to create a new process for the GUI" +msgstr "E851: Nํorbh fh้idir pr๓iseas nua a chruth๚ don GUI" -#: ../globals.h:997 -msgid "E471: Argument required" -msgstr "E471: Tแ gแ le harg๓int" +msgid "E852: The child process failed to start the GUI" +msgstr "E852: Theip ar an macphr๓iseas an GUI a thos๚" -#: ../globals.h:998 -msgid "E10: \\ should be followed by /, ? or &" -msgstr "E10: Ba ch๓ir /, ? n๓ & a chur i ndiaidh \\" +msgid "E229: Cannot start the GUI" +msgstr "E229: Nํ f้idir an GUI a chur ag obair" -#: ../globals.h:1000 -msgid "E11: Invalid in command-line window; <CR> executes, CTRL-C quits" -msgstr "" -"E11: Neamhbhailํ i bhfuinneog lํne na n-orduithe; <CR>=rith, CTRL-C=scoir" +#, c-format +msgid "E230: Cannot read from \"%s\"" +msgstr "E230: Nํ f้idir l้amh ๓ \"%s\"" -#: ../globals.h:1002 -msgid "E12: Command not allowed from exrc/vimrc in current dir or tag search" +msgid "E665: Cannot start GUI, no valid font found" msgstr "" -"E12: Nํ cheadaํtear ord๚ ๓ exrc/vimrc sa chomhadlann reatha nแ ๓ chuardach " -"clibe" +"E665: Nํ f้idir an GUI a chur ag obair, nํl aon chl๓fhoireann bhailํ ann" -#: ../globals.h:1003 -msgid "E171: Missing :endif" -msgstr "E171: :endif ar iarraidh" +msgid "E231: 'guifontwide' invalid" +msgstr "E231: 'guifontwide' neamhbhailํ" -#: ../globals.h:1004 -msgid "E600: Missing :endtry" -msgstr "E600: :endtry ar iarraidh" - -#: ../globals.h:1005 -msgid "E170: Missing :endwhile" -msgstr "E170: :endwhile ar iarraidh" - -#: ../globals.h:1006 -msgid "E170: Missing :endfor" -msgstr "E170: :endfor ar iarraidh" - -#: ../globals.h:1007 -msgid "E588: :endwhile without :while" -msgstr "E588: :endwhile gan :while" - -#: ../globals.h:1008 -msgid "E588: :endfor without :for" -msgstr "E588: :endfor gan :for" +msgid "E599: Value of 'imactivatekey' is invalid" +msgstr "E599: Luach neamhbhailํ ar 'imactivatekey'" -#: ../globals.h:1009 -msgid "E13: File exists (add ! to override)" -msgstr "E13: Tแ comhad ann cheana (cuir ! leis an ord๚ chun forscrํobh)" - -#: ../globals.h:1010 -msgid "E472: Command failed" -msgstr "E472: Theip ar ord๚" - -#: ../globals.h:1011 -msgid "E473: Internal error" -msgstr "E473: Earrแid inmheแnach" +#, c-format +msgid "E254: Cannot allocate color %s" +msgstr "E254: Nํ f้idir dath %s a dhแileadh" -#: ../globals.h:1012 -msgid "Interrupted" -msgstr "Idirbhriste" +msgid "No match at cursor, finding next" +msgstr "Nํl a leith้id ag an ch๚rs๓ir, ag cuardach ar an ch้ad cheann eile" -#: ../globals.h:1013 -msgid "E14: Invalid address" -msgstr "E14: Drochsheoladh" +msgid "<cannot open> " +msgstr "<nํ f้idir a oscailt> " -#: ../globals.h:1014 -msgid "E474: Invalid argument" -msgstr "E474: Arg๓int neamhbhailํ" - -#: ../globals.h:1015 #, c-format -msgid "E475: Invalid argument: %s" -msgstr "E475: Arg๓int neamhbhailํ: %s" +msgid "E616: vim_SelFile: can't get font %s" +msgstr "E616: vim_SelFile: nํl aon fhแil ar an chl๓fhoireann %s" -#: ../globals.h:1016 -#, c-format -msgid "E15: Invalid expression: %s" -msgstr "E15: Slonn neamhbhailํ: %s" +msgid "E614: vim_SelFile: can't return to current directory" +msgstr "E614: vim_SelFile: nํ f้idir dul ar ais go dtํ an chomhadlann reatha" -#: ../globals.h:1017 -msgid "E16: Invalid range" -msgstr "E16: Raon neamhbhailํ" +msgid "Pathname:" +msgstr "Conair:" -#: ../globals.h:1018 -msgid "E476: Invalid command" -msgstr "E476: Ord๚ neamhbhailํ" +msgid "E615: vim_SelFile: can't get current directory" +msgstr "E615: vim_SelFile: nํl an chomhadlann reatha ar fแil" -#: ../globals.h:1019 -#, c-format -msgid "E17: \"%s\" is a directory" -msgstr "E17: is comhadlann \"%s\"" +msgid "OK" +msgstr "OK" -#: ../globals.h:1020 -#, fuzzy -msgid "E900: Invalid job id" -msgstr "E49: M้id neamhbhailํ scrollaithe" +msgid "Cancel" +msgstr "Cealaigh" -#: ../globals.h:1021 -msgid "E901: Job table is full" +msgid "Scrollbar Widget: Could not get geometry of thumb pixmap." msgstr "" +"Giuirl้id Scrollbharra: Nํ f้idir c้imseata an mhapa picteilํnํ a fhแil." -#: ../globals.h:1024 -#, c-format -msgid "E364: Library call failed for \"%s()\"" -msgstr "E364: Theip ar ghlao leabharlainne \"%s()\"" - -#: ../globals.h:1026 -msgid "E19: Mark has invalid line number" -msgstr "E19: Tแ lํne-uimhir neamhbhailํ ag an mharc" +msgid "Vim dialog" +msgstr "Dial๓g Vim" -#: ../globals.h:1027 -msgid "E20: Mark not set" -msgstr "E20: Marc gan socr๚" - -#: ../globals.h:1029 -msgid "E21: Cannot make changes, 'modifiable' is off" +msgid "E232: Cannot create BalloonEval with both message and callback" msgstr "" -"E21: Nํ f้idir athruithe a chur i bhfeidhm, nํl an bhratach 'modifiable' " -"socraithe" +"E232: Nํ f้idir BalloonEval a chruth๚ le teachtaireacht agus aisghlaoch araon" -#: ../globals.h:1030 -msgid "E22: Scripts nested too deep" -msgstr "E22: scripteanna neadaithe r๓dhomhain" +msgid "_Cancel" +msgstr "_Cealaigh" -#: ../globals.h:1031 -msgid "E23: No alternate file" -msgstr "E23: Nํl aon chomhad malartach" +msgid "_Save" +msgstr "_Sแbhแil" -#: ../globals.h:1032 -msgid "E24: No such abbreviation" -msgstr "E24: Nํl a leith้id de ghiorr๚chแn ann" +msgid "_Open" +msgstr "_Oscail" -#: ../globals.h:1033 -msgid "E477: No ! allowed" -msgstr "E477: Nํ cheadaํtear !" +msgid "_OK" +msgstr "_OK" -#: ../globals.h:1035 -msgid "E25: Nvim does not have a built-in GUI" -msgstr "E25: Nํ f้idir an GUI a ๚sแid: Nํor cumasaํodh ้ ag am tiomsaithe" +msgid "" +"&Yes\n" +"&No\n" +"&Cancel" +msgstr "" +"&Tแ\n" +"&Nํl\n" +"&Cealaigh" -#: ../globals.h:1036 -#, c-format -msgid "E28: No such highlight group name: %s" -msgstr "E28: Nํl a leith้id d'ainm gr๚pa aibhsithe: %s" +msgid "Yes" +msgstr "Tแ" -#: ../globals.h:1037 -msgid "E29: No inserted text yet" -msgstr "E29: Nํl aon t้acs ionsแite go dtํ seo" +msgid "No" +msgstr "Nํl" -#: ../globals.h:1038 -msgid "E30: No previous command line" -msgstr "E30: Nํl aon lํne na n-orduithe roimhe seo" +msgid "Input _Methods" +msgstr "_Modhanna ionchuir" -#: ../globals.h:1039 -msgid "E31: No such mapping" -msgstr "E31: Nํl a leith้id de mhapแil" +# in OLT --KPS +msgid "VIM - Search and Replace..." +msgstr "VIM - Cuardaigh agus Athchuir..." -#: ../globals.h:1040 -msgid "E479: No match" -msgstr "E479: Nํl aon rud comhoiri๚nach ann" +msgid "VIM - Search..." +msgstr "VIM - Cuardaigh..." -#: ../globals.h:1041 -#, c-format -msgid "E480: No match: %s" -msgstr "E480: Nํl aon rud comhoiri๚nach ann: %s" +msgid "Find what:" +msgstr "Aimsigh:" -#: ../globals.h:1042 -msgid "E32: No file name" -msgstr "E32: Nํl aon ainm comhaid" +msgid "Replace with:" +msgstr "Le cur in ionad:" -#: ../globals.h:1044 -msgid "E33: No previous substitute regular expression" -msgstr "E33: Nํl aon slonn ionadaํochta roimhe seo" +#. whole word only button +msgid "Match whole word only" +msgstr "Focal iomlแn amhแin" -#: ../globals.h:1045 -msgid "E34: No previous command" -msgstr "E34: Nํl aon ord๚ roimhe seo" +#. match case button +msgid "Match case" +msgstr "Meaitseแil an cแs" -#: ../globals.h:1046 -msgid "E35: No previous regular expression" -msgstr "E35: Nํl aon slonn ionadaํochta roimhe seo" +msgid "Direction" +msgstr "Treo" -#: ../globals.h:1047 -msgid "E481: No range allowed" -msgstr "E481: Nํ cheadaํtear raon" +#. 'Up' and 'Down' buttons +msgid "Up" +msgstr "Suas" -#: ../globals.h:1048 -msgid "E36: Not enough room" -msgstr "E36: Nํl slํ a dh๓thain ann" +msgid "Down" +msgstr "Sํos" -#: ../globals.h:1049 -#, c-format -msgid "E482: Can't create file %s" -msgstr "E482: Nํ f้idir comhad %s a chruth๚" +msgid "Find Next" +msgstr "An Ch้ad Cheann Eile" -#: ../globals.h:1050 -msgid "E483: Can't get temp file name" -msgstr "E483: Nํl aon fhแil ar ainm comhaid sealadach" +msgid "Replace" +msgstr "Ionadaigh" -#: ../globals.h:1051 -#, c-format -msgid "E484: Can't open file %s" -msgstr "E484: Nํ f้idir comhad %s a oscailt" +msgid "Replace All" +msgstr "Ionadaigh Uile" -#: ../globals.h:1052 -#, c-format -msgid "E485: Can't read file %s" -msgstr "E485: Nํ f้idir comhad %s a l้amh" +msgid "_Close" +msgstr "_D๚n" -#: ../globals.h:1054 -msgid "E37: No write since last change (add ! to override)" -msgstr "E37: Tแ athruithe ann gan sแbhแil (cuir ! leis an ord๚ chun sแr๚)" +msgid "Vim: Received \"die\" request from session manager\n" +msgstr "Vim: Fuarthas iarratas \"die\" ๓ bhainisteoir an tseisi๚in\n" -#: ../globals.h:1055 -#, fuzzy -msgid "E37: No write since last change" -msgstr "[Athraithe agus nach sแbhแilte ๓ shin]\n" +msgid "Close tab" +msgstr "D๚n cluaisํn" -#: ../globals.h:1056 -msgid "E38: Null argument" -msgstr "E38: Arg๓int nialasach" - -#: ../globals.h:1057 -msgid "E39: Number expected" -msgstr "E39: Ag s๚il le huimhir" +msgid "New tab" +msgstr "Cluaisํn nua" -#: ../globals.h:1058 -#, c-format -msgid "E40: Can't open errorfile %s" -msgstr "E40: Nํ f้idir an comhad earrแide %s a oscailt" +msgid "Open Tab..." +msgstr "Oscail Cluaisํn..." -#: ../globals.h:1059 -msgid "E41: Out of memory!" -msgstr "E41: Cuimhne ํdithe!" +msgid "Vim: Main window unexpectedly destroyed\n" +msgstr "Vim: Milleadh an prํomhfhuinneog gan choinne\n" -#: ../globals.h:1060 -msgid "Pattern not found" -msgstr "Patr๚n gan aimsi๚" +msgid "&Filter" +msgstr "&Scagaire" -#: ../globals.h:1061 -#, c-format -msgid "E486: Pattern not found: %s" -msgstr "E486: Patr๚n gan aimsi๚: %s" +msgid "&Cancel" +msgstr "&Cealaigh" -#: ../globals.h:1062 -msgid "E487: Argument must be positive" -msgstr "E487: Nํ folแir arg๓int dheimhneach" +msgid "Directories" +msgstr "Comhadlanna" -#: ../globals.h:1064 -msgid "E459: Cannot go back to previous directory" -msgstr "E459: Nํ f้idir a fhilleadh ar an chomhadlann roimhe seo" +msgid "Filter" +msgstr "Scagaire" -#: ../globals.h:1066 -msgid "E42: No Errors" -msgstr "E42: Nํl Aon Earrแid Ann" +msgid "&Help" +msgstr "&Cabhair" -#: ../globals.h:1067 -msgid "E776: No location list" -msgstr "E776: Gan liosta suํomh" +msgid "Files" +msgstr "Comhaid" -#: ../globals.h:1068 -msgid "E43: Damaged match string" -msgstr "E43: Teaghrแn cuardaigh loite" +msgid "&OK" +msgstr "&OK" -#: ../globals.h:1069 -msgid "E44: Corrupted regexp program" -msgstr "E44: Clแr na sloinn ionadaํochta truaillithe" +msgid "Selection" +msgstr "Roghn๚" -#: ../globals.h:1071 -msgid "E45: 'readonly' option is set (add ! to override)" -msgstr "E45: tแ an rogha 'readonly' socraithe (cuir ! leis an ord๚ chun sแr๚)" +msgid "Find &Next" +msgstr "An Ch้ad Chea&nn Eile" -#: ../globals.h:1073 -#, c-format -msgid "E46: Cannot change read-only variable \"%s\"" -msgstr "E46: Nํ f้idir athr๓g inl้ite amhแin \"%s\" a athr๚" +msgid "&Replace" +msgstr "&Ionadaigh" -#: ../globals.h:1075 -#, c-format -msgid "E794: Cannot set variable in the sandbox: \"%s\"" -msgstr "E794: Nํ f้idir athr๓g a shocr๚ sa bhosca gainimh: \"%s\"" +msgid "Replace &All" +msgstr "Ionadaigh &Uile" -#: ../globals.h:1076 -msgid "E47: Error while reading errorfile" -msgstr "E47: Earrแid agus comhad earrแide แ l้amh" +msgid "&Undo" +msgstr "&Cealaigh" -#: ../globals.h:1078 -msgid "E48: Not allowed in sandbox" -msgstr "E48: Nํ cheadaํtear ้ seo i mbosca gainimh" +msgid "Open tab..." +msgstr "Oscail cluaisํn..." -#: ../globals.h:1080 -msgid "E523: Not allowed here" -msgstr "E523: Nํ cheadaํtear ้ anseo" +msgid "Find string (use '\\\\' to find a '\\')" +msgstr "Aimsigh teaghrแn (bain ๚sแid as '\\\\' chun '\\' a aimsi๚)" -#: ../globals.h:1082 -msgid "E359: Screen mode setting not supported" -msgstr "E359: Nํ f้idir an m๓d scแileแin a shocr๚" +msgid "Find & Replace (use '\\\\' to find a '\\')" +msgstr "Aimsigh & Athchuir (๚sแid '\\\\' chun '\\' a aimsi๚)" -#: ../globals.h:1083 -msgid "E49: Invalid scroll size" -msgstr "E49: M้id neamhbhailํ scrollaithe" +#. We fake this: Use a filter that doesn't select anything and a default +#. * file name that won't be used. +msgid "Not Used" +msgstr "Gan ฺsแid" -#: ../globals.h:1084 -msgid "E91: 'shell' option is empty" -msgstr "E91: rogha 'shell' folamh" +msgid "Directory\t*.nothing\n" +msgstr "Comhadlann\t*.neamhnํ\n" -#: ../globals.h:1085 -msgid "E255: Couldn't read in sign data!" -msgstr "E255: Nํorbh fh้idir na sonraํ comhartha a l้amh!" +#, c-format +msgid "E671: Cannot find window title \"%s\"" +msgstr "E671: Nํ f้idir teideal na fuinneoige \"%s\" a aimsi๚" -#: ../globals.h:1086 -msgid "E72: Close error on swap file" -msgstr "E72: Earrแid agus comhad babhtแla แ dh๚nadh" +#, c-format +msgid "E243: Argument not supported: \"-%s\"; Use the OLE version." +msgstr "E243: Arg๓int gan tacaํocht: \"-%s\"; Bain ๚sแid as an leagan OLE." -#: ../globals.h:1087 -msgid "E73: tag stack empty" -msgstr "E73: tแ cruach na gclibeanna folamh" +msgid "E672: Unable to open window inside MDI application" +msgstr "E672: Nํ f้idir fuinneog a oscailt isteach i bhfeidhmchlแr MDI" -#: ../globals.h:1088 -msgid "E74: Command too complex" -msgstr "E74: Ord๚ r๓chasta" +msgid "Vim E458: Cannot allocate colormap entry, some colors may be incorrect" +msgstr "" +"Vim E458: Nํ f้idir iontrแil dathmhapแla a dhแileadh, is f้idir go mbeidh " +"dathanna mํchearta ann" -#: ../globals.h:1089 -msgid "E75: Name too long" -msgstr "E75: Ainm r๓fhada" +#, c-format +msgid "E250: Fonts for the following charsets are missing in fontset %s:" +msgstr "" +"E250: Cl๓nna ar iarraidh le haghaidh na dtacar carachtar i dtacar cl๓ %s:" -#: ../globals.h:1090 -msgid "E76: Too many [" -msgstr "E76: an iomarca [" +#, c-format +msgid "E252: Fontset name: %s" +msgstr "E252: Ainm an tacar cl๓: %s" -#: ../globals.h:1091 -msgid "E77: Too many file names" -msgstr "E77: An iomarca ainmneacha comhaid" +#, c-format +msgid "Font '%s' is not fixed-width" +msgstr "Nํ cl๓ aonleithid ้ '%s'" -#: ../globals.h:1092 -msgid "E488: Trailing characters" -msgstr "E488: Carachtair chun deiridh" +#, c-format +msgid "E253: Fontset name: %s" +msgstr "E253: Ainm an tacar cl๓: %s" -#: ../globals.h:1093 -msgid "E78: Unknown mark" -msgstr "E78: Marc anaithnid" +#, c-format +msgid "Font0: %s" +msgstr "Cl๓0: %s" -#: ../globals.h:1094 -msgid "E79: Cannot expand wildcards" -msgstr "E79: Nํ f้idir saor๓ga a leathn๚" +#, c-format +msgid "Font1: %s" +msgstr "Cl๓1: %s" -#: ../globals.h:1096 -msgid "E591: 'winheight' cannot be smaller than 'winminheight'" -msgstr "E591: nํ cheadaํtear 'winheight' a bheith nํos l๚ nแ 'winminheight'" +#, c-format +msgid "Font%ld width is not twice that of font0" +msgstr "Nํl Cl๓%ld nํos leithne faoi dh๓ nแ cl๓0" -#: ../globals.h:1098 -msgid "E592: 'winwidth' cannot be smaller than 'winminwidth'" -msgstr "E592: nํ cheadaํtear 'winwidth' a bheith nํos l๚ nแ 'winminwidth'" +#, c-format +msgid "Font0 width: %ld" +msgstr "Leithead Cl๓0: %ld" -#: ../globals.h:1099 -msgid "E80: Error while writing" -msgstr "E80: Earrแid agus แ scrํobh" +#, c-format +msgid "Font1 width: %ld" +msgstr "Leithead cl๓1: %ld" -#: ../globals.h:1100 -msgid "Zero count" -msgstr "Nialas" +msgid "Invalid font specification" +msgstr "Sonr๚ neamhbhailํ cl๓" -#: ../globals.h:1101 -msgid "E81: Using <SID> not in a script context" -msgstr "E81: <SID> แ ๚sแid nach i gcomhth้acs scripte" +msgid "&Dismiss" +msgstr "&Ruaig" -#: ../globals.h:1102 -#, c-format -msgid "E685: Internal error: %s" -msgstr "E685: Earrแid inmheแnach: %s" +msgid "no specific match" +msgstr "nํl a leith้id ann" -#: ../globals.h:1104 -msgid "E363: pattern uses more memory than 'maxmempattern'" -msgstr "E363: ๚sแideann an patr๚n nํos m๓ cuimhne nแ 'maxmempattern'" +msgid "Vim - Font Selector" +msgstr "Vim - Roghn๚ Cl๓" -#: ../globals.h:1105 -msgid "E749: empty buffer" -msgstr "E749: maolแn folamh" +msgid "Name:" +msgstr "Ainm:" -#: ../globals.h:1108 -msgid "E682: Invalid search pattern or delimiter" -msgstr "E682: Patr๚n n๓ teormharc๓ir neamhbhailํ cuardaigh" +#. create toggle button +msgid "Show size in Points" +msgstr "Taispeแin m้id (Pointํ)" -#: ../globals.h:1109 -msgid "E139: File is loaded in another buffer" -msgstr "E139: Tแ an comhad luchtaithe i maolแn eile" +msgid "Encoding:" +msgstr "Ionch๓d๚:" -#: ../globals.h:1110 -#, c-format -msgid "E764: Option '%s' is not set" -msgstr "E764: Rogha '%s' gan socr๚" +msgid "Font:" +msgstr "Cl๓:" -#: ../globals.h:1111 -#, fuzzy -msgid "E850: Invalid register name" -msgstr "E354: Ainm neamhbhailํ tabhaill: '%s'" +msgid "Style:" +msgstr "Stํl:" -#: ../globals.h:1114 -msgid "search hit TOP, continuing at BOTTOM" -msgstr "Buaileadh an BARR le linn an chuardaigh, ag lean๚int ag an CHRอOCH" +msgid "Size:" +msgstr "M้id:" -#: ../globals.h:1115 -msgid "search hit BOTTOM, continuing at TOP" -msgstr "Buaileadh an BUN le linn an chuardaigh, ag lean๚int ag an BHARR" +msgid "E256: Hangul automata ERROR" +msgstr "E256: EARRมID leis na huathoibreแin Hangul" -#: ../hardcopy.c:240 msgid "E550: Missing colon" msgstr "E550: Idirstad ar iarraidh" -#: ../hardcopy.c:252 msgid "E551: Illegal component" msgstr "E551: Comhphแirt neamhcheadaithe" -#: ../hardcopy.c:259 msgid "E552: digit expected" msgstr "E552: ag s๚il le digit" -#: ../hardcopy.c:473 #, c-format msgid "Page %d" msgstr "Leathanach %d" -#: ../hardcopy.c:597 msgid "No text to be printed" msgstr "Nํl aon t้acs le priontแil" -#: ../hardcopy.c:668 #, c-format msgid "Printing page %d (%d%%)" msgstr "Leathanach %d (%d%%) แ phriontแil" -#: ../hardcopy.c:680 #, c-format msgid " Copy %d of %d" msgstr " C๓ip %d de %d" -#: ../hardcopy.c:733 #, c-format msgid "Printed: %s" msgstr "Priontแilte: %s" -#: ../hardcopy.c:740 msgid "Printing aborted" msgstr "Priontแil tobscortha" -#: ../hardcopy.c:1365 msgid "E455: Error writing to PostScript output file" msgstr "E455: Earrแid le linn scrํobh chuig aschomhad PostScript" -#: ../hardcopy.c:1747 #, c-format msgid "E624: Can't open file \"%s\"" msgstr "E624: Nํ f้idir an comhad \"%s\" a oscailt" -#: ../hardcopy.c:1756 ../hardcopy.c:2470 #, c-format msgid "E457: Can't read PostScript resource file \"%s\"" msgstr "E457: Nํ f้idir comhad acmhainne PostScript \"%s\" a l้amh" -#: ../hardcopy.c:1772 #, c-format msgid "E618: file \"%s\" is not a PostScript resource file" msgstr "E618: Nํl comhad \"%s\" ina chomhad acmhainne PostScript" -#: ../hardcopy.c:1788 ../hardcopy.c:1805 ../hardcopy.c:1844 #, c-format msgid "E619: file \"%s\" is not a supported PostScript resource file" msgstr "E619: Tแ \"%s\" ina chomhad acmhainne PostScript gan tac๚" -#: ../hardcopy.c:1856 #, c-format msgid "E621: \"%s\" resource file has wrong version" msgstr "E621: Tแ an leagan mํcheart ar an gcomhad acmhainne \"%s\"" -#: ../hardcopy.c:2225 msgid "E673: Incompatible multi-byte encoding and character set." msgstr "E673: Ionch๓d๚ agus tacar carachtar ilbhirt neamh-chomhoiri๚nach." -#: ../hardcopy.c:2238 msgid "E674: printmbcharset cannot be empty with multi-byte encoding." msgstr "" "E674: nํ cheadaํtear printmbcharset a bheith folamh le hionch๓d๚ ilbhirt." -#: ../hardcopy.c:2254 msgid "E675: No default font specified for multi-byte printing." msgstr "E675: Nํor r้amhshocraํodh cl๓ le haghaidh priontแla ilbhirt." -#: ../hardcopy.c:2426 msgid "E324: Can't open PostScript output file" msgstr "E324: Nํ f้idir aschomhad PostScript a oscailt" -#: ../hardcopy.c:2458 #, c-format msgid "E456: Can't open file \"%s\"" msgstr "E456: Nํ f้idir an comhad \"%s\" a oscailt" -#: ../hardcopy.c:2583 msgid "E456: Can't find PostScript resource file \"prolog.ps\"" msgstr "E456: Comhad acmhainne PostScript \"prolog.ps\" gan aimsi๚" -#: ../hardcopy.c:2593 msgid "E456: Can't find PostScript resource file \"cidfont.ps\"" msgstr "E456: Comhad acmhainne PostScript \"cidfont.ps\" gan aimsi๚" -#: ../hardcopy.c:2622 ../hardcopy.c:2639 ../hardcopy.c:2665 #, c-format msgid "E456: Can't find PostScript resource file \"%s.ps\"" msgstr "E456: Comhad acmhainne PostScript \"%s.ps\" gan aimsi๚" -#: ../hardcopy.c:2654 #, c-format msgid "E620: Unable to convert to print encoding \"%s\"" msgstr "E620: Nํ f้idir an t-ionch๓d๚ priontแla \"%s\" a thiont๚" -#: ../hardcopy.c:2877 msgid "Sending to printer..." msgstr "ม sheoladh chuig an phrint้ir..." -#: ../hardcopy.c:2881 msgid "E365: Failed to print PostScript file" msgstr "E365: Theip ar phriontแil comhaid PostScript" -#: ../hardcopy.c:2883 msgid "Print job sent." msgstr "Seoladh jab priontแla." -#: ../if_cscope.c:85 msgid "Add a new database" msgstr "Bunachar sonraํ nua" -#: ../if_cscope.c:87 msgid "Query for a pattern" msgstr "Iarratas ar phatr๚n" -#: ../if_cscope.c:89 msgid "Show this message" msgstr "Taispeแin an teachtaireacht seo" -#: ../if_cscope.c:91 msgid "Kill a connection" msgstr "Maraigh nasc" -#: ../if_cscope.c:93 msgid "Reinit all connections" msgstr "At๚saigh gach nasc" -#: ../if_cscope.c:95 msgid "Show connections" msgstr "Taispeแin naisc" -#: ../if_cscope.c:101 #, c-format msgid "E560: Usage: cs[cope] %s" msgstr "E560: ฺsแid: cs[cope] %s" -#: ../if_cscope.c:225 msgid "This cscope command does not support splitting the window.\n" msgstr "Nํ f้idir fuinneoga a scoilteadh leis an ord๚ seo `cscope'.\n" -#: ../if_cscope.c:266 msgid "E562: Usage: cstag <ident>" msgstr "E562: ฺsแid: cstag <ident>" -#: ../if_cscope.c:313 msgid "E257: cstag: tag not found" msgstr "E257: cstag: clib gan aimsi๚" -#: ../if_cscope.c:461 #, c-format msgid "E563: stat(%s) error: %d" msgstr "E563: earrแid stat(%s): %d" -#: ../if_cscope.c:551 +msgid "E563: stat error" +msgstr "E563: earrแid stat" + #, c-format msgid "E564: %s is not a directory or a valid cscope database" msgstr "E564: Nํl %s ina comhadlann n๓ bunachar sonraํ cscope bailํ" -#: ../if_cscope.c:566 #, c-format msgid "Added cscope database %s" msgstr "Bunachar sonraํ nua cscope: %s" -#: ../if_cscope.c:616 #, c-format -msgid "E262: error reading cscope connection %<PRId64>" -msgstr "E262: earrแid agus an nasc cscope %<PRId64> แ l้amh" +msgid "E262: error reading cscope connection %ld" +msgstr "E262: earrแid agus an nasc cscope %ld แ l้amh" -#: ../if_cscope.c:711 msgid "E561: unknown cscope search type" msgstr "E561: cineแl anaithnid cuardaigh cscope" -#: ../if_cscope.c:752 ../if_cscope.c:789 msgid "E566: Could not create cscope pipes" msgstr "E566: Nํorbh fh้idir pํopaํ cscope a chruth๚" -#: ../if_cscope.c:767 msgid "E622: Could not fork for cscope" msgstr "E622: Nํorbh fh้idir forc a dh้anamh le haghaidh cscope" -#: ../if_cscope.c:849 -#, fuzzy msgid "cs_create_connection setpgid failed" -msgstr "theip ar rith cs_create_connection" +msgstr "theip ar setpgid do cs_create_connection" -#: ../if_cscope.c:853 ../if_cscope.c:889 msgid "cs_create_connection exec failed" msgstr "theip ar rith cs_create_connection" -#: ../if_cscope.c:863 ../if_cscope.c:902 msgid "cs_create_connection: fdopen for to_fp failed" msgstr "cs_create_connection: theip ar fdopen le haghaidh to_fp" -#: ../if_cscope.c:865 ../if_cscope.c:906 msgid "cs_create_connection: fdopen for fr_fp failed" msgstr "cs_create_connection: theip ar fdopen le haghaidh fr_fp" -#: ../if_cscope.c:890 msgid "E623: Could not spawn cscope process" msgstr "E623: Nํorbh fh้idir pr๓iseas cscope a sceitheadh" -#: ../if_cscope.c:932 msgid "E567: no cscope connections" msgstr "E567: nํl aon nasc cscope ann" -#: ../if_cscope.c:1009 #, c-format msgid "E469: invalid cscopequickfix flag %c for %c" msgstr "E469: bratach neamhbhailํ cscopequickfix %c le haghaidh %c" -#: ../if_cscope.c:1058 #, c-format msgid "E259: no matches found for cscope query %s of %s" msgstr "" "E259: nํor aimsํodh aon rud comhoiri๚nach leis an iarratas cscope %s de %s" -#: ../if_cscope.c:1142 msgid "cscope commands:\n" msgstr "Orduithe cscope:\n" -#: ../if_cscope.c:1150 #, c-format msgid "%-5s: %s%*s (Usage: %s)" msgstr "%-5s: %s%*s (ฺsแid: %s)" -#: ../if_cscope.c:1155 -#, fuzzy msgid "" "\n" +" a: Find assignments to this symbol\n" " c: Find functions calling this function\n" " d: Find functions called by this function\n" " e: Find this egrep pattern\n" @@ -3241,6 +2576,7 @@ msgid "" " t: Find this text string\n" msgstr "" "\n" +" a: Aimsigh rแitis sannachแin leis an tsiombail seo\n" " c: Aimsigh feidhmeanna a chuireann glaoch ar an bhfeidhm seo\n" " d: Aimsigh feidhmeanna a gcuireann an fheidhm seo glaoch orthu\n" " e: Aimsigh an patr๚n egrep seo\n" @@ -3248,33 +2584,34 @@ msgstr "" " g: Aimsigh an sainmhํni๚ seo\n" " i: Aimsigh comhaid a #include-แil an comhad seo\n" " s: Aimsigh an tsiombail C seo\n" -" t: Aimsigh sanntaํ do\n" +" t: Aimsigh an teaghrแn t้acs seo\n" + +#, c-format +msgid "E625: cannot open cscope database: %s" +msgstr "E625: nํ f้idir bunachar sonraํ cscope a oscailt: %s" + +msgid "E626: cannot get cscope database information" +msgstr "E626: nํ f้idir eolas a fhแil faoin bhunachar sonraํ cscope" -#: ../if_cscope.c:1226 msgid "E568: duplicate cscope database not added" msgstr "E568: nํor cuireadh bunachar sonraํ d๚blach cscope leis" -#: ../if_cscope.c:1335 #, c-format msgid "E261: cscope connection %s not found" msgstr "E261: nasc cscope %s gan aimsi๚" -#: ../if_cscope.c:1364 #, c-format msgid "cscope connection %s closed" msgstr "D๚nadh nasc cscope %s" #. should not reach here -#: ../if_cscope.c:1486 msgid "E570: fatal error in cs_manage_matches" msgstr "E570: earrแid mharfach i cs_manage_matches" -#: ../if_cscope.c:1693 #, c-format msgid "Cscope tag: %s" msgstr "Clib cscope: %s" -#: ../if_cscope.c:1711 msgid "" "\n" " # line" @@ -3282,88 +2619,301 @@ msgstr "" "\n" " # lํne" -#: ../if_cscope.c:1713 msgid "filename / context / line\n" msgstr "ainm comhaid / comhth้acs / lํne\n" -#: ../if_cscope.c:1809 #, c-format msgid "E609: Cscope error: %s" msgstr "E609: Earrแid cscope: %s" -#: ../if_cscope.c:2053 msgid "All cscope databases reset" msgstr "Athshocraํodh gach bunachar sonraํ cscope" -#: ../if_cscope.c:2123 msgid "no cscope connections\n" msgstr "nํl aon nasc cscope\n" -#: ../if_cscope.c:2126 msgid " # pid database name prepend path\n" msgstr " # pid ainm bunachair conair thosaigh\n" -#: ../main.c:144 +msgid "Lua library cannot be loaded." +msgstr "Nํ f้idir an leabharlann Lua a lucht๚." + +msgid "cannot save undo information" +msgstr "nํ f้idir eolas cealaithe a shแbhแil" + +msgid "" +"E815: Sorry, this command is disabled, the MzScheme libraries could not be " +"loaded." +msgstr "" +"E815: Tแ br๓n orm, bhํ an t-ord๚ seo dํchumasaithe, nํorbh fh้idir " +"leabharlanna MzScheme a lucht๚." + +msgid "" +"E895: Sorry, this command is disabled, the MzScheme's racket/base module " +"could not be loaded." +msgstr "" +"E895: มr leithsc้al, tแ an t-ord๚ seo dํchumasaithe; nํorbh fh้idir " +"mod๚l racket/base MzScheme a lucht๚." + +msgid "invalid expression" +msgstr "slonn neamhbhailํ" + +msgid "expressions disabled at compile time" +msgstr "dํchumasaํodh sloinn ag am an tiomsaithe" + +msgid "hidden option" +msgstr "rogha fholaithe" + +msgid "unknown option" +msgstr "rogha anaithnid" + +msgid "window index is out of range" +msgstr "inn้acs fuinneoige as raon" + +msgid "couldn't open buffer" +msgstr "nํ f้idir maolแn a oscailt" + +msgid "cannot delete line" +msgstr "nํ f้idir an lํne a scriosadh" + +msgid "cannot replace line" +msgstr "nํ f้idir an lํne a athchur" + +msgid "cannot insert line" +msgstr "nํ f้idir lํne a ionsแ" + +msgid "string cannot contain newlines" +msgstr "nํ cheadaํtear carachtair lํne nua sa teaghrแn" + +msgid "error converting Scheme values to Vim" +msgstr "earrแid agus luach Scheme แ thiont๚ go Vim" + +msgid "Vim error: ~a" +msgstr "earrแid Vim: ~a" + +msgid "Vim error" +msgstr "earrแid Vim" + +msgid "buffer is invalid" +msgstr "maolแn neamhbhailํ" + +msgid "window is invalid" +msgstr "fuinneog neamhbhailํ" + +msgid "linenr out of range" +msgstr "lํne-uimhir as raon" + +msgid "not allowed in the Vim sandbox" +msgstr "nํ cheadaํtear ้ seo i mbosca gainimh Vim" + +msgid "E836: This Vim cannot execute :python after using :py3" +msgstr "" +"E836: Nํ f้idir leis an leagan seo de Vim :python a rith tar ้is :py3 a ๚sแid" + +msgid "" +"E263: Sorry, this command is disabled, the Python library could not be " +"loaded." +msgstr "" +"E263: Tแ br๓n orm, nํl an t-ord๚ seo le fแil, nํorbh fh้idir an leabharlann " +"Python a lucht๚." + +msgid "" +"E887: Sorry, this command is disabled, the Python's site module could not be " +"loaded." +msgstr "" +"E887: มr leithsc้al, nํl an t-ord๚ seo le fแil, nํorbh fh้idir an mod๚l " +"Python a lucht๚." + +msgid "E659: Cannot invoke Python recursively" +msgstr "E659: Nํ f้idir Python a rith go hathch๚rsach" + +msgid "E837: This Vim cannot execute :py3 after using :python" +msgstr "" +"E837: Nํ f้idir leis an leagan seo de Vim :py3 a rith tar ้is :python a ๚sแid" + +msgid "E265: $_ must be an instance of String" +msgstr "E265: caithfidh $_ a bheith cineแl Teaghrแin" + +msgid "" +"E266: Sorry, this command is disabled, the Ruby library could not be loaded." +msgstr "" +"E266: Tแ br๓n orm, nํl an t-ord๚ seo le fแil, nํorbh fh้idir an leabharlann " +"Ruby a lucht๚." + +msgid "E267: unexpected return" +msgstr "E267: \"return\" gan choinne" + +msgid "E268: unexpected next" +msgstr "E268: \"next\" gan choinne" + +msgid "E269: unexpected break" +msgstr "E269: \"break\" gan choinne" + +msgid "E270: unexpected redo" +msgstr "E270: \"redo\" gan choinne" + +msgid "E271: retry outside of rescue clause" +msgstr "E271: \"retry\" taobh amuigh de chlแsal tarrthแla" + +msgid "E272: unhandled exception" +msgstr "E272: eisceacht gan lแimhseแil" + +#, c-format +msgid "E273: unknown longjmp status %d" +msgstr "E273: stแdas anaithnid longjmp %d" + +msgid "invalid buffer number" +msgstr "uimhir neamhbhailํ mhaolแin" + +msgid "not implemented yet" +msgstr "nํl ar fแil" + +#. ??? +msgid "cannot set line(s)" +msgstr "nํ f้idir lํn(t)e a shocr๚" + +msgid "invalid mark name" +msgstr "ainm neamhbhailํ mairc" + +msgid "mark not set" +msgstr "marc gan socr๚" + +#, c-format +msgid "row %d column %d" +msgstr "lํne %d col๚n %d" + +msgid "cannot insert/append line" +msgstr "nํ f้idir lํne a ionsแ/iarcheangal" + +msgid "line number out of range" +msgstr "lํne-uimhir as raon" + +msgid "unknown flag: " +msgstr "bratach anaithnid: " + +msgid "unknown vimOption" +msgstr "vimOption anaithnid" + +msgid "keyboard interrupt" +msgstr "idirbhriseadh m้archlแir" + +msgid "vim error" +msgstr "earrแid vim" + +msgid "cannot create buffer/window command: object is being deleted" +msgstr "nํ f้idir ord๚ maolแin/fuinneoige a chruth๚: r้ad แ scriosadh" + +msgid "" +"cannot register callback command: buffer/window is already being deleted" +msgstr "nํ f้idir ord๚ aisghlaoch a chlแr๚: maolแn/fuinneog แ scriosadh cheana" + +#. This should never happen. Famous last word? +msgid "" +"E280: TCL FATAL ERROR: reflist corrupt!? Please report this to vim-dev@vim." +"org" +msgstr "" +"E280: EARRมID MHARFACH TCL: liosta truaillithe tagartha!? Seol tuairisc " +"fhabht chuig <vim-dev@vim.org> le do thoil" + +msgid "cannot register callback command: buffer/window reference not found" +msgstr "" +"nํ f้idir ord๚ aisghlaoch a chlแr๚: tagairt mhaolแn/fhuinneoige gan aimsi๚" + +msgid "" +"E571: Sorry, this command is disabled: the Tcl library could not be loaded." +msgstr "" +"E571: Tแ br๓n orm, nํl an t-ord๚ seo le fแil: nํorbh fh้idir an leabharlann " +"Tcl a lucht๚." + +#, c-format +msgid "E572: exit code %d" +msgstr "E572: c๓d scortha %d" + +msgid "cannot get line" +msgstr "nํ f้idir an lํne a fhแil" + +msgid "Unable to register a command server name" +msgstr "Nํ f้idir ainm fhreastalaํ ordaithe a chlแr๚" + +msgid "E248: Failed to send command to the destination program" +msgstr "E248: Theip ar sheoladh ord๚ chuig an sprioc-chlแr" + +#, c-format +msgid "E573: Invalid server id used: %s" +msgstr "E573: Aitheantas neamhbhailํ freastalaํ in ๚sแid: %s" + +msgid "E251: VIM instance registry property is badly formed. Deleted!" +msgstr "E251: Airํ mํchumtha sa chlแrlann แisc VIM. Scriosta!" + +#, c-format +msgid "E696: Missing comma in List: %s" +msgstr "E696: Cam๓g ar iarraidh i Liosta: %s" + +#, c-format +msgid "E697: Missing end of List ']': %s" +msgstr "E697: ']' ar iarraidh ag deireadh liosta: %s" + msgid "Unknown option argument" msgstr "Arg๓int anaithnid rogha" -#: ../main.c:146 msgid "Too many edit arguments" msgstr "An iomarca arg๓intํ eagarth๓ireachta" -#: ../main.c:148 msgid "Argument missing after" msgstr "Arg๓int ar iarraidh i ndiaidh" -#: ../main.c:150 msgid "Garbage after option argument" msgstr "Dramhaํl i ndiaidh arg๓inte rogha" -#: ../main.c:152 msgid "Too many \"+command\", \"-c command\" or \"--cmd command\" arguments" msgstr "" "An iomarca arg๓intํ den chineแl \"+ord๚\", \"-c ord๚\" n๓ \"--cmd ord๚\"" -#: ../main.c:154 msgid "Invalid argument for" msgstr "Arg๓int neamhbhailํ do" -#: ../main.c:294 #, c-format msgid "%d files to edit\n" msgstr "%d comhad le heagr๚\n" -#: ../main.c:1342 +msgid "netbeans is not supported with this GUI\n" +msgstr "Nํ thacaํtear le netbeans sa GUI seo\n" + +msgid "'-nb' cannot be used: not enabled at compile time\n" +msgstr "Nํ f้idir '-nb' a ๚sแid: nํor cumasaํodh ้ ag am tiomsaithe\n" + +msgid "This Vim was not compiled with the diff feature." +msgstr "Nํor tiomsaํodh an leagan Vim seo le `diff' ar fแil." + msgid "Attempt to open script file again: \"" msgstr "D้an iarracht ar oscailt na scripte arํs: \"" -#: ../main.c:1350 msgid "Cannot open for reading: \"" msgstr "Nํ f้idir ้ a oscailt chun l้amh: \"" -#: ../main.c:1393 msgid "Cannot open for script output: \"" msgstr "Nํ f้idir a oscailt le haghaidh an aschuir scripte: \"" -#: ../main.c:1622 +msgid "Vim: Error: Failure to start gvim from NetBeans\n" +msgstr "Vim: Earrแid: Theip ar thos๚ gvim ๓ NetBeans\n" + +msgid "Vim: Error: This version of Vim does not run in a Cygwin terminal\n" +msgstr "Vim: Earrแid: Nํ f้idir an leagan seo de Vim a rith i dteirmin้al Cygwin\n" + msgid "Vim: Warning: Output is not to a terminal\n" msgstr "Vim: Rabhadh: Nํl an t-aschur ag dul chuig teirmin้al\n" -#: ../main.c:1624 msgid "Vim: Warning: Input is not from a terminal\n" msgstr "Vim: Rabhadh: Nํl an t-ionchur ag teacht ๓ theirmin้al\n" #. just in case.. -#: ../main.c:1891 msgid "pre-vimrc command line" msgstr "lํne na n-orduithe pre-vimrc" -#: ../main.c:1964 #, c-format msgid "E282: Cannot read from \"%s\"" msgstr "E282: Nํ f้idir l้amh ๓ \"%s\"" -#: ../main.c:2149 msgid "" "\n" "More info with: \"vim -h\"\n" @@ -3371,23 +2921,18 @@ msgstr "" "\n" "Tuilleadh eolais: \"vim -h\"\n" -#: ../main.c:2178 msgid "[file ..] edit specified file(s)" msgstr "[comhad ..] cuir na comhaid ceaptha in eagar" -#: ../main.c:2179 msgid "- read text from stdin" msgstr "- scrํobh t้acs ๓ stdin" -#: ../main.c:2180 msgid "-t tag edit file where tag is defined" msgstr "-t tag cuir an comhad ina bhfuil an chlib in eagar" -#: ../main.c:2181 msgid "-q [errorfile] edit file with first error" msgstr "-q [comhadearr] cuir comhad leis an ch้ad earrแid in eagar" -#: ../main.c:2187 msgid "" "\n" "\n" @@ -3397,11 +2942,9 @@ msgstr "" "\n" "๚sแid:" -#: ../main.c:2189 msgid " vim [arguments] " msgstr " vim [arg๓intํ] " -#: ../main.c:2193 msgid "" "\n" " or:" @@ -3409,7 +2952,14 @@ msgstr "" "\n" " n๓:" -#: ../main.c:2196 +msgid "" +"\n" +"Where case is ignored prepend / to make flag upper case" +msgstr "" +"\n" +"Nuair nach cแsํogair ้, cuir '/' ag tosach na brataํ chun ํ a chur sa chแs " +"uachtair" + msgid "" "\n" "\n" @@ -3419,194 +2969,338 @@ msgstr "" "\n" "Arg๓intํ:\n" -#: ../main.c:2197 msgid "--\t\t\tOnly file names after this" msgstr "--\t\t\tNํ cheadaํtear ach ainmneacha comhaid i ndiaidh ้ seo" -#: ../main.c:2199 msgid "--literal\t\tDon't expand wildcards" msgstr "--literal\t\tNแ leathnaigh saor๓ga" -#: ../main.c:2201 +msgid "-register\t\tRegister this gvim for OLE" +msgstr "-register\t\tClแraigh an gvim seo le haghaidh OLE" + +msgid "-unregister\t\tUnregister gvim for OLE" +msgstr "-unregister\t\tDํchlแraigh an gvim seo le haghaidh OLE" + +msgid "-g\t\t\tRun using GUI (like \"gvim\")" +msgstr "-g\t\t\tRith agus ๚sแid an GUI (mar \"gvim\")" + +msgid "-f or --nofork\tForeground: Don't fork when starting GUI" +msgstr "-f n๓ --nofork\tTulra: Nแ d้an forc agus an GUI แ thos๚" + msgid "-v\t\t\tVi mode (like \"vi\")" msgstr "-v\t\t\tM๓d Vi (mar \"vi\")" -#: ../main.c:2202 msgid "-e\t\t\tEx mode (like \"ex\")" msgstr "-e\t\t\tM๓d Ex (mar \"ex\")" -#: ../main.c:2203 msgid "-E\t\t\tImproved Ex mode" -msgstr "" +msgstr "-E\t\t\tM๓d Ex feabhsaithe" -#: ../main.c:2204 msgid "-s\t\t\tSilent (batch) mode (only for \"ex\")" msgstr "-s\t\t\tM๓d ci๚in (baiscphr๓iseแla) (do \"ex\" amhแin)" -#: ../main.c:2205 msgid "-d\t\t\tDiff mode (like \"vimdiff\")" msgstr "-d\t\t\tM๓d diff (mar \"vimdiff\")" -#: ../main.c:2206 msgid "-y\t\t\tEasy mode (like \"evim\", modeless)" msgstr "-y\t\t\tM๓d ้asca (mar \"evim\", gan mh๓id)" -#: ../main.c:2207 msgid "-R\t\t\tReadonly mode (like \"view\")" msgstr "-R\t\t\tM๓d inl้ite amhแin (mar \"view\")" -#: ../main.c:2208 msgid "-Z\t\t\tRestricted mode (like \"rvim\")" msgstr "-Z\t\t\tM๓d srianta (mar \"rvim\")" -#: ../main.c:2209 msgid "-m\t\t\tModifications (writing files) not allowed" msgstr "-m\t\t\tNํ cheadaํtear athruithe (.i. scrํobh na gcomhad)" -#: ../main.c:2210 msgid "-M\t\t\tModifications in text not allowed" msgstr "-M\t\t\tNํ cheadaํtear athruithe sa t้acs" -#: ../main.c:2211 msgid "-b\t\t\tBinary mode" msgstr "-b\t\t\tM๓d d้nแrtha" -#: ../main.c:2212 msgid "-l\t\t\tLisp mode" msgstr "-l\t\t\tM๓d Lisp" -#: ../main.c:2213 msgid "-C\t\t\tCompatible with Vi: 'compatible'" msgstr "-C\t\t\tComhoiri๚nach le Vi: 'compatible'" -#: ../main.c:2214 msgid "-N\t\t\tNot fully Vi compatible: 'nocompatible'" msgstr "-N\t\t\tNํ comhoiri๚naithe le Vi go hiomlแn: 'nocompatible'" -#: ../main.c:2215 msgid "-V[N][fname]\t\tBe verbose [level N] [log messages to fname]" msgstr "" "-V[N][fname]\t\tBํ foclach [leibh้al N] [logแil teachtaireachtaํ i fname]" -#: ../main.c:2216 msgid "-D\t\t\tDebugging mode" msgstr "-D\t\t\tM๓d dํfhabhtaithe" -#: ../main.c:2217 msgid "-n\t\t\tNo swap file, use memory only" msgstr "-n\t\t\tNแ h๚sแid comhad babhtแla .i. nแ h๚sแid ach an chuimhne" -#: ../main.c:2218 msgid "-r\t\t\tList swap files and exit" msgstr "-r\t\t\tTaispeแin comhaid bhabhtแla agus scoir" -#: ../main.c:2219 msgid "-r (with file name)\tRecover crashed session" msgstr "-r (le hainm comhaid)\tAthshlแnaigh ๓ chliseadh" -#: ../main.c:2220 msgid "-L\t\t\tSame as -r" msgstr "-L\t\t\tAr comhbhrํ le -r" -#: ../main.c:2221 +msgid "-f\t\t\tDon't use newcli to open window" +msgstr "-f\t\t\tNแ h๚sแid newcli chun fuinneog a oscailt" + +msgid "-dev <device>\t\tUse <device> for I/O" +msgstr "-dev <gl้as>\t\tBain ๚sแid as <gl้as> do I/A" + msgid "-A\t\t\tstart in Arabic mode" msgstr "-A\t\t\ttosaigh sa mh๓d Araibise" -#: ../main.c:2222 msgid "-H\t\t\tStart in Hebrew mode" msgstr "-H\t\t\tTosaigh sa mh๓d Eabhraise" -#: ../main.c:2223 msgid "-F\t\t\tStart in Farsi mode" msgstr "-F\t\t\tTosaigh sa mh๓d Pheirsise" -#: ../main.c:2224 msgid "-T <terminal>\tSet terminal type to <terminal>" msgstr "-T <teirmin้al>\tSocraigh cineแl teirmin้al" -#: ../main.c:2225 +msgid "--not-a-term\t\tSkip warning for input/output not being a terminal" +msgstr "--not-a-term\t\tNแ bac le rabhadh faoi ionchur/aschur gan a bheith ๓n teirmin้al" + msgid "-u <vimrc>\t\tUse <vimrc> instead of any .vimrc" msgstr "-u <vimrc>\t\tฺsแid <vimrc> in ionad aon .vimrc" -#: ../main.c:2226 +msgid "-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc" +msgstr "-U <gvimrc>\t\tBain ๚sแid as <gvimrc> in ionad aon .gvimrc" + msgid "--noplugin\t\tDon't load plugin scripts" msgstr "--noplugin\t\tNแ luchtaigh breiseแin" -#: ../main.c:2227 msgid "-p[N]\t\tOpen N tab pages (default: one for each file)" -msgstr "-p[N]\t\tOscail N leathanach cluaisํn (default: ceann do gach comhad)" +msgstr "-p[N]\t\tOscail N leathanach cluaisํnํ (default: ceann do gach comhad)" -#: ../main.c:2228 msgid "-o[N]\t\tOpen N windows (default: one for each file)" msgstr "-o[N]\t\tOscail N fuinneog (r้amhshocr๚: ceann do gach comhad)" -#: ../main.c:2229 msgid "-O[N]\t\tLike -o but split vertically" msgstr "-O[N]\t\tMar -o, ach roinn go hingearach" -#: ../main.c:2230 msgid "+\t\t\tStart at end of file" msgstr "+\t\t\tTosaigh ag an chomhadchrํoch" -#: ../main.c:2231 msgid "+<lnum>\t\tStart at line <lnum>" msgstr "+<lnum>\t\tTosaigh ar lํne <lnum>" -#: ../main.c:2232 msgid "--cmd <command>\tExecute <command> before loading any vimrc file" msgstr "--cmd <ord๚>\tRith <ord๚> roimh aon chomhad vimrc a lucht๚" -#: ../main.c:2233 msgid "-c <command>\t\tExecute <command> after loading the first file" msgstr "-c <ord๚>\t\tRith <ord๚> i ndiaidh lucht๚ an ch้ad chomhad" -#: ../main.c:2235 msgid "-S <session>\t\tSource file <session> after loading the first file" msgstr "" "-S <seisi๚n>\t\tL้igh comhad <seisi๚n> i ndiaidh an ch้ad chomhad แ l้amh" -#: ../main.c:2236 msgid "-s <scriptin>\tRead Normal mode commands from file <scriptin>" msgstr "-s <script>\tL้igh orduithe gnแthmh๓id ๓n chomhad <script>" -#: ../main.c:2237 msgid "-w <scriptout>\tAppend all typed commands to file <scriptout>" msgstr "" "-w <script>\tIarcheangail gach ord๚ iontrแilte leis an gcomhad <script>" -#: ../main.c:2238 msgid "-W <scriptout>\tWrite all typed commands to file <scriptout>" msgstr "-W <aschur>\tScrํobh gach ord๚ cl๓scrํofa sa chomhad <aschur>" -#: ../main.c:2240 +msgid "-x\t\t\tEdit encrypted files" +msgstr "-x\t\t\tCuir comhaid chriptithe in eagar" + +msgid "-display <display>\tConnect vim to this particular X-server" +msgstr "-display <freastalaํ>\tNasc vim leis an bhfreastalaํ-X seo" + +msgid "-X\t\t\tDo not connect to X server" +msgstr "-X\t\t\tNแ naisc leis an bhfreastalaํ X" + +msgid "--remote <files>\tEdit <files> in a Vim server if possible" +msgstr "" +"--remote <comhaid>\tCuir <comhaid> in eagar le freastalaํ Vim mแs f้idir" + +msgid "--remote-silent <files> Same, don't complain if there is no server" +msgstr "" +"--remote-silent <comhaid> Mar an gc้anna, nแ d้an gearแn mura bhfuil " +"freastalaํ ann" + +msgid "" +"--remote-wait <files> As --remote but wait for files to have been edited" +msgstr "" +"--remote-wait <comhaid> Mar --remote ach fan leis na comhaid a bheith " +"curtha in eagar" + +msgid "" +"--remote-wait-silent <files> Same, don't complain if there is no server" +msgstr "" +"--remote-wait-silent <comhaid> Mar an gc้anna, nแ d้an gearแn mura bhfuil " +"freastalaํ ann" + +msgid "" +"--remote-tab[-wait][-silent] <files> As --remote but use tab page per file" +msgstr "" +"--remote-tab[-wait][-silent] <comhaid> Cos๚il le --remote ach oscail " +"cluaisํn do gach comhad" + +msgid "--remote-send <keys>\tSend <keys> to a Vim server and exit" +msgstr "" +"--remote-send <eochracha>\tSeol <eochracha> chuig freastalaํ Vim agus scoir" + +msgid "--remote-expr <expr>\tEvaluate <expr> in a Vim server and print result" +msgstr "" +"--remote-expr <slonn>\tLuachแil <slonn> le freastalaํ Vim agus taispeแin an " +"toradh" + +msgid "--serverlist\t\tList available Vim server names and exit" +msgstr "--serverlist\t\tTaispeแin freastalaithe Vim atแ ar fแil agus scoir" + +msgid "--servername <name>\tSend to/become the Vim server <name>" +msgstr "--servername <ainm>\tSeol chuig/T้igh i do fhreastalaํ Vim <ainm>" + msgid "--startuptime <file>\tWrite startup timing messages to <file>" msgstr "" "--startuptime <comhad>\tScrํobh faisn้is maidir le tr้imhse tosaithe i " "<comhad>" -#: ../main.c:2242 msgid "-i <viminfo>\t\tUse <viminfo> instead of .viminfo" msgstr "-i <viminfo>\t\tฺsแid <viminfo> in ionad .viminfo" -#: ../main.c:2243 msgid "-h or --help\tPrint Help (this message) and exit" msgstr "-h n๓ --help\tTaispeแin an chabhair seo agus scoir" -#: ../main.c:2244 msgid "--version\t\tPrint version information and exit" msgstr "--version\t\tTaispeแin eolas faoin leagan agus scoir" -#: ../mark.c:676 +msgid "" +"\n" +"Arguments recognised by gvim (Motif version):\n" +msgstr "" +"\n" +"Arg๓intํ ar eolas do gvim (leagan Motif):\n" + +msgid "" +"\n" +"Arguments recognised by gvim (neXtaw version):\n" +msgstr "" +"\n" +"Arg๓intํ ar eolas do gvim (leagan neXtaw):\n" + +msgid "" +"\n" +"Arguments recognised by gvim (Athena version):\n" +msgstr "" +"\n" +"Arg๓intํ ar eolas do gvim (leagan Athena):\n" + +msgid "-display <display>\tRun vim on <display>" +msgstr "-display <scแileแn>\tRith vim ar <scแileแn>" + +msgid "-iconic\t\tStart vim iconified" +msgstr "-iconic\t\tTosaigh vim sa mh๓d ํoslaghdaithe" + +msgid "-background <color>\tUse <color> for the background (also: -bg)" +msgstr "-background <dath>\tBain ๚sแid as <dath> don ch๚lra (-bg fosta)" + +msgid "-foreground <color>\tUse <color> for normal text (also: -fg)" +msgstr "-foreground <dath>\tฺsแid <dath> le haghaidh gnแth-th้acs (fosta: -fg)" + +msgid "-font <font>\t\tUse <font> for normal text (also: -fn)" +msgstr "-font <cl๓>\t\tฺsแid <cl๓> le haghaidh gnแth-th้acs (fosta: -fn)" + +msgid "-boldfont <font>\tUse <font> for bold text" +msgstr "-boldfont <cl๓>\tBain ๚sแid as <cl๓> do chl๓ trom" + +msgid "-italicfont <font>\tUse <font> for italic text" +msgstr "-italicfont <cl๓>\tฺsแid <cl๓> le haghaidh t้acs iodแlach" + +msgid "-geometry <geom>\tUse <geom> for initial geometry (also: -geom)" +msgstr "" +"-geometry <geoim>\tฺsแid <geoim> le haghaidh na c้imseatan tosaigh (fosta: -" +"geom)" + +msgid "-borderwidth <width>\tUse a border width of <width> (also: -bw)" +msgstr "-borderwidth <leithead>\tSocraigh <leithead> na himlํne (-bw fosta)" + +msgid "-scrollbarwidth <width> Use a scrollbar width of <width> (also: -sw)" +msgstr "" +"-scrollbarwidth <leithead> Socraigh leithead na scrollbharraํ a bheith " +"<leithead> (fosta: -sw)" + +msgid "-menuheight <height>\tUse a menu bar height of <height> (also: -mh)" +msgstr "" +"-menuheight <airde>\tSocraigh airde an bharra roghchlแir a bheith <airde> " +"(fosta: -mh)" + +msgid "-reverse\t\tUse reverse video (also: -rv)" +msgstr "-reverse\t\tฺsแid fํs aisiompaithe (fosta: -rv)" + +msgid "+reverse\t\tDon't use reverse video (also: +rv)" +msgstr "+reverse\t\tNแ h๚sแid fํs aisiompaithe (fosta: +rv)" + +msgid "-xrm <resource>\tSet the specified resource" +msgstr "-xrm <acmhainn>\tSocraigh an acmhainn sainithe" + +msgid "" +"\n" +"Arguments recognised by gvim (GTK+ version):\n" +msgstr "" +"\n" +"Arg๓intํ ar eolas do gvim (leagan GTK+):\n" + +msgid "-display <display>\tRun vim on <display> (also: --display)" +msgstr "-display <scแileแn>\tRith vim ar <scแileแn> (fosta: --display)" + +msgid "--role <role>\tSet a unique role to identify the main window" +msgstr "--role <r๓l>\tSocraigh r๓l saini๚il chun an phrํomhfhuinneog a aithint" + +msgid "--socketid <xid>\tOpen Vim inside another GTK widget" +msgstr "--socketid <xid>\tOscail Vim isteach i ngiuirl้id GTK eile" + +msgid "--echo-wid\t\tMake gvim echo the Window ID on stdout" +msgstr "--echo-wid\t\tTaispeแnann gvim aitheantas na fuinneoige ar stdout" + +msgid "-P <parent title>\tOpen Vim inside parent application" +msgstr "-P <mแthairchlแr>\tOscail Vim isteach sa mhแthairchlแr" + +msgid "--windowid <HWND>\tOpen Vim inside another win32 widget" +msgstr "--windowid <HWND>\tOscail Vim isteach i ngiuirl้id win32 eile" + +msgid "No display" +msgstr "Gan taispeแint" + +#. Failed to send, abort. +msgid ": Send failed.\n" +msgstr ": Theip ar seoladh.\n" + +#. Let vim start normally. +msgid ": Send failed. Trying to execute locally\n" +msgstr ": Theip ar seoladh. Ag baint triail as go logแnta\n" + +#, c-format +msgid "%d of %d edited" +msgstr "%d as %d d้anta" + +msgid "No display: Send expression failed.\n" +msgstr "Gan taispeแint: Theip ar sheoladh sloinn.\n" + +msgid ": Send expression failed.\n" +msgstr ": Theip ar sheoladh sloinn.\n" + msgid "No marks set" msgstr "Nํl aon mharc socraithe" -#: ../mark.c:678 #, c-format msgid "E283: No marks matching \"%s\"" msgstr "E283: Nํl aon mharc comhoiri๚naithe le \"%s\"" #. Highlight title -#: ../mark.c:687 msgid "" "\n" "mark line col file/text" @@ -3615,7 +3309,6 @@ msgstr "" "marc lํne col comhad/t้acs" #. Highlight title -#: ../mark.c:789 msgid "" "\n" " jump line col file/text" @@ -3624,7 +3317,6 @@ msgstr "" " l้im lํne col comhad/t้acs" #. Highlight title -#: ../mark.c:831 msgid "" "\n" "change line col text" @@ -3632,7 +3324,6 @@ msgstr "" "\n" "athr๚ lํne col t้acs" -#: ../mark.c:1238 msgid "" "\n" "# File marks:\n" @@ -3641,7 +3332,6 @@ msgstr "" "# Marcanna comhaid:\n" #. Write the jumplist with -' -#: ../mark.c:1271 msgid "" "\n" "# Jumplist (newest first):\n" @@ -3649,7 +3339,6 @@ msgstr "" "\n" "# Liosta l้imeanna (is nuaํ i dtosach):\n" -#: ../mark.c:1352 msgid "" "\n" "# History of marks within files (newest to oldest):\n" @@ -3657,86 +3346,90 @@ msgstr "" "\n" "# Stair na marcanna i gcomhaid (is nuaํ ar dt๚s):\n" -#: ../mark.c:1431 msgid "Missing '>'" msgstr "`>' ar iarraidh" -#: ../memfile.c:426 +msgid "E543: Not a valid codepage" +msgstr "E543: Nํ c๓dleathanach bailํ ้" + +msgid "E284: Cannot set IC values" +msgstr "E284: Nํ f้idir luachanna IC a shocr๚" + +msgid "E285: Failed to create input context" +msgstr "E285: Theip ar chruth๚ comhth้acs ionchuir" + +msgid "E286: Failed to open input method" +msgstr "E286: Theip ar oscailt mhodh ionchuir" + +msgid "E287: Warning: Could not set destroy callback to IM" +msgstr "E287: Rabhadh: Nํorbh fh้idir aisghlaoch l้irscriosta a shocr๚ le IM" + +msgid "E288: input method doesn't support any style" +msgstr "E288: Nํ thacaํonn an modh ionchuir aon stํl" + +msgid "E289: input method doesn't support my preedit type" +msgstr "E289: nํ thacaํonn an modh ionchuir mo chineแl r้amheagair" + msgid "E293: block was not locked" msgstr "E293: nํ raibh an bloc faoi ghlas" -#: ../memfile.c:799 msgid "E294: Seek error in swap file read" msgstr "E294: Earrแid chuardaigh agus comhad babhtแla แ l้amh" -#: ../memfile.c:803 msgid "E295: Read error in swap file" msgstr "E295: Earrแid sa l้amh i gcomhad babhtแla" -#: ../memfile.c:849 msgid "E296: Seek error in swap file write" msgstr "E296: Earrแid chuardaigh agus comhad babhtแla แ scrํobh" -#: ../memfile.c:865 msgid "E297: Write error in swap file" msgstr "E297: Earrแid sa scrํobh i gcomhad babhtแla" -#: ../memfile.c:1036 msgid "E300: Swap file already exists (symlink attack?)" msgstr "E300: Tแ comhad babhtแla ann cheana (ionsaํ le naisc shiombalacha?)" -#: ../memline.c:318 msgid "E298: Didn't get block nr 0?" msgstr "E298: Nํ bhfuarthas bloc 0?" -#: ../memline.c:361 msgid "E298: Didn't get block nr 1?" msgstr "E298: Nํ bhfuarthas bloc a haon?" -#: ../memline.c:377 msgid "E298: Didn't get block nr 2?" msgstr "E298: Nํ bhfuarthas bloc a d๓?" +msgid "E843: Error while updating swap file crypt" +msgstr "E843: Earrแid agus cripti๚ an chomhaid bhabhtแla แ nuashonr๚" + #. could not (re)open the swap file, what can we do???? -#: ../memline.c:465 msgid "E301: Oops, lost the swap file!!!" msgstr "E301: ฺps, cailleadh an comhad babhtแla!!!" -#: ../memline.c:477 msgid "E302: Could not rename swap file" msgstr "E302: Nํorbh fh้idir an comhad babhtแla a athainmni๚" -#: ../memline.c:554 #, c-format msgid "E303: Unable to open swap file for \"%s\", recovery impossible" msgstr "" "E303: Nํ f้idir comhad babhtแla le haghaidh \"%s\" a oscailt, nํ f้idir " "athshlแn๚" -#: ../memline.c:666 msgid "E304: ml_upd_block0(): Didn't get block 0??" msgstr "E304: ml_upd_block0(): Nํ bhfuarthas bloc 0??" -#. no swap files found -#: ../memline.c:830 #, c-format msgid "E305: No swap file found for %s" msgstr "E305: Nํor aimsํodh comhad babhtแla le haghaidh %s" -#: ../memline.c:839 msgid "Enter number of swap file to use (0 to quit): " msgstr "Iontrแil uimhir an chomhaid babhtแla le h๚sแid (0 = scoir): " -#: ../memline.c:879 #, c-format msgid "E306: Cannot open %s" msgstr "E306: Nํ f้idir %s a oscailt" -#: ../memline.c:897 msgid "Unable to read block 0 from " msgstr "Nํ f้idir bloc 0 a l้amh ๓ " -#: ../memline.c:900 msgid "" "\n" "Maybe no changes were made or Vim did not update the swap file." @@ -3745,28 +3438,22 @@ msgstr "" "B'fh้idir nach raibh aon athr๚ แ dh้anamh, n๓ tแ an comhad\n" "babhtแla as dแta." -#: ../memline.c:909 msgid " cannot be used with this version of Vim.\n" msgstr " nํl ar fแil leis an leagan seo de Vim.\n" -#: ../memline.c:911 msgid "Use Vim version 3.0.\n" msgstr "Bain ๚sแid as Vim, leagan 3.0.\n" -#: ../memline.c:916 #, c-format msgid "E307: %s does not look like a Vim swap file" msgstr "E307: Nํl %s cos๚il le comhad babhtแla Vim" -#: ../memline.c:922 msgid " cannot be used on this computer.\n" msgstr " nํl ar fแil ar an rํomhaire seo.\n" -#: ../memline.c:924 msgid "The file was created on " msgstr "Cruthaํodh an comhad seo ar " -#: ../memline.c:928 msgid "" ",\n" "or the file has been damaged." @@ -3774,86 +3461,107 @@ msgstr "" ",\n" "is ้ sin n๓ rinneadh dochar don chomhad." -#: ../memline.c:945 +#, c-format +msgid "" +"E833: %s is encrypted and this version of Vim does not support encryption" +msgstr "" +"E833: tแ %s criptithe agus nํ thacaํonn an leagan seo de Vim le cripti๚" + msgid " has been damaged (page size is smaller than minimum value).\n" msgstr " rinneadh dochar d๓ (m้id an leathanaigh nํos l๚ nแ an ํosmh้id).\n" -#: ../memline.c:974 #, c-format msgid "Using swap file \"%s\"" msgstr "Comhad babhtแla \"%s\" แ ๚sแid" -#: ../memline.c:980 #, c-format msgid "Original file \"%s\"" msgstr "Comhad bun๚sach \"%s\"" -#: ../memline.c:995 msgid "E308: Warning: Original file may have been changed" msgstr "E308: Rabhadh: Is f้idir gur athraํodh an comhad bun๚sach" -#: ../memline.c:1061 +#, c-format +msgid "Swap file is encrypted: \"%s\"" +msgstr "Tแ an comhad babhtแla criptithe: \"%s\"" + +msgid "" +"\n" +"If you entered a new crypt key but did not write the text file," +msgstr "" +"\n" +"Mแ chuir t๚ eochair nua chripti๚chแin isteach, ach mura scrํobh t๚ an " +"t้acschomhad," + +msgid "" +"\n" +"enter the new crypt key." +msgstr "" +"\n" +"cuir isteach an eochair nua chripti๚chแin." + +msgid "" +"\n" +"If you wrote the text file after changing the crypt key press enter" +msgstr "" +"\n" +"Mแ scrํobh t๚ an t้acschomhad tar ้is duit an eochair chripti๚chแํn a athr๚, " +"br๚igh Enter" + +msgid "" +"\n" +"to use the same key for text file and swap file" +msgstr "" +"\n" +"chun an eochair ch้anna a ๚sแid don t้acschomhad agus an comhad babhtแla" + #, c-format msgid "E309: Unable to read block 1 from %s" msgstr "E309: Nํ f้idir bloc a haon a l้amh ๓ %s" -#: ../memline.c:1065 msgid "???MANY LINES MISSING" msgstr "???GO LEOR LอNTE AR IARRAIDH" -#: ../memline.c:1076 msgid "???LINE COUNT WRONG" msgstr "???LอON MอCHEART NA LอNTE" -#: ../memline.c:1082 msgid "???EMPTY BLOCK" msgstr "???BLOC FOLAMH" -#: ../memline.c:1103 msgid "???LINES MISSING" msgstr "???LอNTE AR IARRAIDH" -#: ../memline.c:1128 #, c-format msgid "E310: Block 1 ID wrong (%s not a .swp file?)" msgstr "E310: Aitheantas mํcheart ar bhloc a haon (nํl %s ina chomhad .swp?)" -#: ../memline.c:1133 msgid "???BLOCK MISSING" msgstr "???BLOC AR IARRAIDH" -#: ../memline.c:1147 msgid "??? from here until ???END lines may be messed up" msgstr "??? is f้idir go ndearnadh praiseach de lํnte ๓ anseo go ???END" -#: ../memline.c:1164 msgid "??? from here until ???END lines may have been inserted/deleted" msgstr "??? is f้idir go bhfuil lํnte ionsแite/scriosta ๓ anseo go ???END" -#: ../memline.c:1181 msgid "???END" msgstr "???DEIREADH" -#: ../memline.c:1238 msgid "E311: Recovery Interrupted" msgstr "E311: Idirbhriseadh an t-athshlแn๚" -#: ../memline.c:1243 msgid "" "E312: Errors detected while recovering; look for lines starting with ???" msgstr "" "E312: Braitheadh earrแidํ le linn athshlแnaithe; f้ach ar na lํnte le ??? ar " "tosach" -#: ../memline.c:1245 msgid "See \":help E312\" for more information." msgstr "Bain triail as \":help E312\" chun tuilleadh eolais a fhแil." -#: ../memline.c:1249 msgid "Recovery completed. You should check if everything is OK." msgstr "Athshlแnaํodh. Ba ch๓ir duit gach rud a sheiceแil uair amhแin eile." -#: ../memline.c:1251 msgid "" "\n" "(You might want to write out this file under another name\n" @@ -3861,73 +3569,61 @@ msgstr "" "\n" "(B'fh้idir gur mian leat an comhad seo a shแbhแil de r้ir ainm eile\n" -#: ../memline.c:1252 -#, fuzzy msgid "and run diff with the original file to check for changes)" -msgstr "" -"agus d้an comparแid leis an chomhad bhun๚sach (m.sh. le `diff') chun " -"athruithe a scr๚d๚)\n" +msgstr "agus d้an comparแid leis an mbunchomhad chun athruithe a lorg)" -#: ../memline.c:1254 msgid "Recovery completed. Buffer contents equals file contents." msgstr "" +"Athshlแn๚ crํochnaithe. Is ionann an t-แbhar sa mhaolแn agus an t-แbhar sa " +"chomhad." -#: ../memline.c:1255 -#, fuzzy msgid "" "\n" "You may want to delete the .swp file now.\n" "\n" msgstr "" -"Scrios an comhad .swp tar ้is sin.\n" "\n" +"B'fh้idir gur mhaith leat an comhad .swp a scriosadh anois.\n" +"\n" + +msgid "Using crypt key from swap file for the text file.\n" +msgstr "" +"Eochair chripti๚chแin ๓n gcomhad babhtแla แ h๚sแid ar an t้acschomhad.\n" #. use msg() to start the scrolling properly -#: ../memline.c:1327 msgid "Swap files found:" msgstr "Comhaid bhabhtแla aimsithe:" -#: ../memline.c:1446 msgid " In current directory:\n" msgstr " Sa chomhadlann reatha:\n" -#: ../memline.c:1448 msgid " Using specified name:\n" msgstr " Ag baint ๚sแid as ainm socraithe:\n" -#: ../memline.c:1450 msgid " In directory " msgstr " Sa chomhadlann " -#: ../memline.c:1465 msgid " -- none --\n" msgstr " -- neamhnํ --\n" -#: ../memline.c:1527 msgid " owned by: " msgstr " ๚in้ir: " -#: ../memline.c:1529 msgid " dated: " msgstr " dแtaithe: " -#: ../memline.c:1532 ../memline.c:3231 msgid " dated: " msgstr " dแtaithe: " -#: ../memline.c:1548 msgid " [from Vim version 3.0]" msgstr " [๓ leagan 3.0 Vim]" -#: ../memline.c:1550 msgid " [does not look like a Vim swap file]" msgstr " [nํ cos๚il le comhad babhtแla Vim]" -#: ../memline.c:1552 msgid " file name: " msgstr " ainm comhaid: " -#: ../memline.c:1558 msgid "" "\n" " modified: " @@ -3935,15 +3631,12 @@ msgstr "" "\n" " mionathraithe: " -#: ../memline.c:1559 msgid "YES" msgstr "IS SEA" -#: ../memline.c:1559 msgid "no" msgstr "nํ hea" -#: ../memline.c:1562 msgid "" "\n" " user name: " @@ -3951,11 +3644,9 @@ msgstr "" "\n" " ๚sแideoir: " -#: ../memline.c:1568 msgid " host name: " msgstr " ainm an ๓strํomhaire: " -#: ../memline.c:1570 msgid "" "\n" " host name: " @@ -3963,7 +3654,6 @@ msgstr "" "\n" " ๓stainm: " -#: ../memline.c:1575 msgid "" "\n" " process ID: " @@ -3971,11 +3661,16 @@ msgstr "" "\n" " PID: " -#: ../memline.c:1579 msgid " (still running)" msgstr " (ag rith f๓s)" -#: ../memline.c:1586 +msgid "" +"\n" +" [not usable with this version of Vim]" +msgstr "" +"\n" +" [nํ in๚sแidte leis an leagan seo Vim]" + msgid "" "\n" " [not usable on this computer]" @@ -3983,97 +3678,75 @@ msgstr "" "\n" " [nํ in๚sแidte ar an rํomhaire seo]" -#: ../memline.c:1590 msgid " [cannot be read]" msgstr " [nํ f้idir a l้amh]" -#: ../memline.c:1593 msgid " [cannot be opened]" msgstr " [nํ f้idir oscailt]" -#: ../memline.c:1698 msgid "E313: Cannot preserve, there is no swap file" msgstr "E313: Nํ f้idir ้ a chaomhn๚, nํl aon chomhad babhtแla ann" -#: ../memline.c:1747 msgid "File preserved" msgstr "Caomhnaํodh an comhad" -#: ../memline.c:1749 msgid "E314: Preserve failed" msgstr "E314: Theip ar chaomhn๚" -#: ../memline.c:1819 #, c-format -msgid "E315: ml_get: invalid lnum: %<PRId64>" -msgstr "E315: ml_get: lnum neamhbhailํ: %<PRId64>" +msgid "E315: ml_get: invalid lnum: %ld" +msgstr "E315: ml_get: lnum neamhbhailํ: %ld" -#: ../memline.c:1851 #, c-format -msgid "E316: ml_get: cannot find line %<PRId64>" -msgstr "E316: ml_get: lํne %<PRId64> gan aimsi๚" +msgid "E316: ml_get: cannot find line %ld" +msgstr "E316: ml_get: lํne %ld gan aimsi๚" -#: ../memline.c:2236 msgid "E317: pointer block id wrong 3" msgstr "E317: aitheantas mํcheart ar an mbloc pointeora 3" -#: ../memline.c:2311 msgid "stack_idx should be 0" msgstr "ba ch๓ir do stack_idx a bheith 0" -#: ../memline.c:2369 msgid "E318: Updated too many blocks?" msgstr "E318: An iomarca bloic nuashonraithe?" -#: ../memline.c:2511 msgid "E317: pointer block id wrong 4" msgstr "E317: aitheantas mํcheart ar an mbloc pointeora 4" -#: ../memline.c:2536 msgid "deleted block 1?" msgstr "bloc a haon scriosta?" -#: ../memline.c:2707 #, c-format -msgid "E320: Cannot find line %<PRId64>" -msgstr "E320: Lํne %<PRId64> gan aimsi๚" +msgid "E320: Cannot find line %ld" +msgstr "E320: Lํne %ld gan aimsi๚" -#: ../memline.c:2916 msgid "E317: pointer block id wrong" msgstr "E317: aitheantas mํcheart ar an mbloc pointeora" -#: ../memline.c:2930 msgid "pe_line_count is zero" msgstr "is 0 pe_line_count\"" -#: ../memline.c:2955 #, c-format -msgid "E322: line number out of range: %<PRId64> past the end" -msgstr "E322: lํne-uimhir as raon: %<PRId64> thar dheireadh" +msgid "E322: line number out of range: %ld past the end" +msgstr "E322: lํne-uimhir as raon: %ld thar dheireadh" -#: ../memline.c:2959 #, c-format -msgid "E323: line count wrong in block %<PRId64>" -msgstr "E323: lํon mํcheart na lํnte i mbloc %<PRId64>" +msgid "E323: line count wrong in block %ld" +msgstr "E323: lํon mํcheart na lํnte i mbloc %ld" -#: ../memline.c:2999 msgid "Stack size increases" msgstr "M้adaํonn an chruach" -#: ../memline.c:3038 msgid "E317: pointer block id wrong 2" msgstr "E317: aitheantas mํcheart ar an mbloc pointeora 2" -#: ../memline.c:3070 #, c-format msgid "E773: Symlink loop for \"%s\"" msgstr "E773: Ciogal i naisc shiombalacha le haghaidh \"%s\"" -#: ../memline.c:3221 msgid "E325: ATTENTION" msgstr "E325: AIRE" -#: ../memline.c:3222 msgid "" "\n" "Found a swap file by the name \"" @@ -4081,45 +3754,31 @@ msgstr "" "\n" "Fuarthas comhad babhtแla darbh ainm \"" -#: ../memline.c:3226 msgid "While opening file \"" msgstr "Agus an comhad seo แ oscailt: \"" -#: ../memline.c:3239 msgid " NEWER than swap file!\n" msgstr " NอOS NUAอ nแ comhad babhtแla!\n" -#: ../memline.c:3244 -#, fuzzy +#. Some of these messages are long to allow translation to +#. * other languages. msgid "" "\n" "(1) Another program may be editing the same file. If this is the case,\n" " be careful not to end up with two different instances of the same\n" -" file when making changes." +" file when making changes. Quit, or continue with caution.\n" msgstr "" "\n" -"(1) Is f้idir go bhfuil clแr eile ag rochtain an comhad seo.\n" -" Mแs ea, bํ c๚ramach nach bhfuil dhแ leagan den chomhad\n" -" c้anna.\n" - -#: ../memline.c:3245 -#, fuzzy -msgid " Quit, or continue with caution.\n" -msgstr " Scoir, n๓ lean ar aghaidh go hairdeallach.\n" +"(1) Seans go bhfuil an comhad seo แ chur in eagar ag clแr eile. Mแ tแ,\n" +" bํ c๚ramach nach bhfuil dhแ leagan den chomhad c้anna agat nuair\n" +" a athraํonn t๚ ้. Scoir anois, n๓ lean ort go faichilleach.\n" -#: ../memline.c:3246 -#, fuzzy msgid "(2) An edit session for this file crashed.\n" -msgstr "" -"\n" -"(2) Rinne Vim thobscor agus an comhad seo\n" -" idir lแmha agat.\n" +msgstr "(2) Thuairteแil seisi๚n eagarth๓ireachta.\n" -#: ../memline.c:3247 msgid " If this is the case, use \":recover\" or \"vim -r " msgstr " Mแs amhlaidh, bain ๚sแid as \":recover\" n๓ \"vim -r " -#: ../memline.c:3249 msgid "" "\"\n" " to recover the changes (see \":help recovery\").\n" @@ -4127,11 +3786,9 @@ msgstr "" "\"\n" " chun na hathruithe a fhแil ar ais (f้ach \":help recovery\").\n" -#: ../memline.c:3250 msgid " If you did this already, delete the swap file \"" msgstr " Mแ tแ s้ seo d้anta cheana agat, scrios an comhad babhtแla \"" -#: ../memline.c:3252 msgid "" "\"\n" " to avoid this message.\n" @@ -4139,23 +3796,18 @@ msgstr "" "\"\n" " chun an teachtaireacht seo a sheachaint.\n" -#: ../memline.c:3450 ../memline.c:3452 msgid "Swap file \"" msgstr "Comhad babhtแla \"" -#: ../memline.c:3451 ../memline.c:3455 msgid "\" already exists!" msgstr "\" tแ s้ ann cheana!" -#: ../memline.c:3457 msgid "VIM - ATTENTION" msgstr "VIM - AIRE" -#: ../memline.c:3459 msgid "Swap file already exists!" msgstr "Tแ comhad babhtแla ann cheana!" -#: ../memline.c:3464 msgid "" "&Open Read-Only\n" "&Edit anyway\n" @@ -4169,7 +3821,6 @@ msgstr "" "&Scoir\n" "&Tobscoir" -#: ../memline.c:3467 msgid "" "&Open Read-Only\n" "&Edit anyway\n" @@ -4185,58 +3836,36 @@ msgstr "" "&Scoir\n" "&Tobscoir" -#. -#. * Change the ".swp" extension to find another file that can be used. -#. * First decrement the last char: ".swo", ".swn", etc. -#. * If that still isn't enough decrement the last but one char: ".svz" -#. * Can happen when editing many "No Name" buffers. -#. -#. ".s?a" -#. ".saa": tried enough, give up -#: ../memline.c:3528 msgid "E326: Too many swap files found" msgstr "E326: Aimsํodh an iomarca comhaid bhabhtแla" -#: ../memory.c:227 -#, c-format -msgid "E342: Out of memory! (allocating %<PRIu64> bytes)" -msgstr "E342: Cuimhne ํdithe! (%<PRIu64> beart แ ndแileadh)" - -#: ../menu.c:62 msgid "E327: Part of menu-item path is not sub-menu" msgstr "E327: Nํ fo-roghchlแr ํ pแirt de chonair roghchlแir" -#: ../menu.c:63 msgid "E328: Menu only exists in another mode" msgstr "E328: Nํl an roghchlแr ar fแil sa mh๓d seo" -#: ../menu.c:64 #, c-format msgid "E329: No menu \"%s\"" msgstr "E329: Nํl aon roghchlแr darbh ainm \"%s\"" #. Only a mnemonic or accelerator is not valid. -#: ../menu.c:329 msgid "E792: Empty menu name" msgstr "E792: Ainm folamh ar an roghchlแr" -#: ../menu.c:340 msgid "E330: Menu path must not lead to a sub-menu" msgstr "E330: Nํ cheadaํtear conair roghchlแir a threoraํonn go fo-roghchlแr" -#: ../menu.c:365 msgid "E331: Must not add menu items directly to menu bar" msgstr "" "E331: Nํ cheadaํtear mํreanna roghchlแir a chur le barra roghchlแir go " "dํreach" -#: ../menu.c:370 msgid "E332: Separator cannot be part of a menu path" msgstr "E332: Nํ cheadaํtear deighilteoir mar phแirt de chonair roghchlแir" #. Now we have found the matching menu, and we list the mappings #. Highlight title -#: ../menu.c:762 msgid "" "\n" "--- Menus ---" @@ -4244,69 +3873,61 @@ msgstr "" "\n" "--- Roghchlแir ---" -#: ../menu.c:1313 +msgid "Tear off this menu" +msgstr "Bain an roghchlแr seo" + msgid "E333: Menu path must lead to a menu item" msgstr "E333: Nํ m๓r conair roghchlแir a threor๚ chun mํr roghchlแir" -#: ../menu.c:1330 #, c-format msgid "E334: Menu not found: %s" msgstr "E334: Roghchlแr gan aimsi๚: %s" -#: ../menu.c:1396 #, c-format msgid "E335: Menu not defined for %s mode" msgstr "E335: Nํl an roghchlแr ar fแil sa mh๓d %s" -#: ../menu.c:1426 msgid "E336: Menu path must lead to a sub-menu" msgstr "E336: Nํ m๓r conair roghchlแir a threor๚ chun fo-roghchlแr" -#: ../menu.c:1447 msgid "E337: Menu not found - check menu names" msgstr "E337: Roghchlแr gan aimsi๚ - deimhnigh ainmneacha na roghchlแr" -#: ../message.c:423 #, c-format msgid "Error detected while processing %s:" msgstr "Earrแid agus %s แ phr๓iseแil:" -#: ../message.c:445 #, c-format msgid "line %4ld:" msgstr "lํne %4ld:" -#: ../message.c:617 #, c-format msgid "E354: Invalid register name: '%s'" msgstr "E354: Ainm neamhbhailํ tabhaill: '%s'" -#: ../message.c:986 +msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>" +msgstr "" +"Cothaitheoir na dteachtaireachtaํ: Kevin P. Scannell <scannell@slu.edu>" + msgid "Interrupt: " msgstr "Idirbhriseadh: " -#: ../message.c:988 msgid "Press ENTER or type command to continue" msgstr "Br๚igh ENTER n๓ iontrแil ord๚ le lean๚int" -#: ../message.c:1843 #, c-format -msgid "%s line %<PRId64>" -msgstr "%s lํne %<PRId64>" +msgid "%s line %ld" +msgstr "%s lํne %ld" -#: ../message.c:2392 msgid "-- More --" msgstr "-- Tuilleadh --" -#: ../message.c:2398 msgid " SPACE/d/j: screen/page/line down, b/u/k: up, q: quit " msgstr " SPมS/d/j: scแileแn/leathanach/lํne sํos, b/u/k: suas, q: scoir " -#: ../message.c:3021 ../message.c:3031 msgid "Question" msgstr "Ceist" -#: ../message.c:3023 msgid "" "&Yes\n" "&No" @@ -4314,17 +3935,6 @@ msgstr "" "&Tแ\n" "&Nํl" -#: ../message.c:3033 -msgid "" -"&Yes\n" -"&No\n" -"&Cancel" -msgstr "" -"&Tแ\n" -"&Nํl\n" -"&Cealaigh" - -#: ../message.c:3045 msgid "" "&Yes\n" "&No\n" @@ -4338,180 +3948,251 @@ msgstr "" "&Dealaigh Uile\n" "&Cealaigh" -#: ../message.c:3058 +msgid "Select Directory dialog" +msgstr "Dial๓g `Roghnaigh Comhadlann'" + +msgid "Save File dialog" +msgstr "Dial๓g `Sแbhแil Comhad'" + +msgid "Open File dialog" +msgstr "Dial๓g `Oscail Comhad'" + +#. TODO: non-GUI file selector here +msgid "E338: Sorry, no file browser in console mode" +msgstr "E338: Nํl brabhsแlaํ comhaid ar fแil sa mh๓d cons๓il" + msgid "E766: Insufficient arguments for printf()" msgstr "E766: Easpa arg๓intํ d'fheidhm printf()" -#: ../message.c:3119 msgid "E807: Expected Float argument for printf()" msgstr "E807: Bhํothas ag s๚il le harg๓int Snแmhphointe d'fheidhm printf()" -#: ../message.c:3873 msgid "E767: Too many arguments to printf()" msgstr "E767: An iomarca arg๓intํ d'fheidhm printf()" -#: ../misc1.c:2256 msgid "W10: Warning: Changing a readonly file" msgstr "W10: Rabhadh: Comhad inl้ite amhแin แ athr๚" -#: ../misc1.c:2537 msgid "Type number and <Enter> or click with mouse (empty cancels): " msgstr "" "Cl๓scrํobh uimhir agus <Enter> n๓ cliceแil leis an luch (fแg folamh le " "ceal๚): " -#: ../misc1.c:2539 msgid "Type number and <Enter> (empty cancels): " msgstr "Cl๓scrํobh uimhir agus <Enter> (fแg folamh le ceal๚): " -#: ../misc1.c:2585 msgid "1 more line" msgstr "1 lํne eile" -#: ../misc1.c:2588 msgid "1 line less" msgstr "1 lํne nํos l๚" -#: ../misc1.c:2593 #, c-format -msgid "%<PRId64> more lines" -msgstr "%<PRId64> lํne eile" +msgid "%ld more lines" +msgstr "%ld lํne eile" -#: ../misc1.c:2596 #, c-format -msgid "%<PRId64> fewer lines" -msgstr "%<PRId64> lํne nํos l๚" +msgid "%ld fewer lines" +msgstr "%ld lํne nํos l๚" -#: ../misc1.c:2599 msgid " (Interrupted)" msgstr " (Idirbhriste)" -#: ../misc1.c:2635 msgid "Beep!" msgstr "Bํp!" -#: ../misc2.c:738 +msgid "ERROR: " +msgstr "EARRมID: " + +#, c-format +msgid "" +"\n" +"[bytes] total alloc-freed %lu-%lu, in use %lu, peak use %lu\n" +msgstr "" +"\n" +"[beart] iomlแn dแilte-saor %lu-%lu, in ๚sแid %lu, buaic %lu\n" + +#, c-format +msgid "" +"[calls] total re/malloc()'s %lu, total free()'s %lu\n" +"\n" +msgstr "" +"[glaonna] re/malloc(): %lu, free(): %lu\n" +"\n" + +msgid "E340: Line is becoming too long" +msgstr "E340: Tแ an lํne ag ้irํ r๓fhada" + +#, c-format +msgid "E341: Internal error: lalloc(%ld, )" +msgstr "E341: Earrแid inmheแnach: lalloc(%ld, )" + +#, c-format +msgid "E342: Out of memory! (allocating %lu bytes)" +msgstr "E342: Cuimhne ํdithe! (%lu beart แ ndแileadh)" + #, c-format msgid "Calling shell to execute: \"%s\"" msgstr "An t-ord๚ seo แ rith leis an bhlaosc: \"%s\"" -#: ../normal.c:183 +msgid "E545: Missing colon" +msgstr "E545: Idirstad ar iarraidh" + +msgid "E546: Illegal mode" +msgstr "E546: M๓d neamhcheadaithe" + +msgid "E547: Illegal mouseshape" +msgstr "E547: Cruth neamhcheadaithe luiche" + +msgid "E548: digit expected" +msgstr "E548: ag s๚il le digit" + +msgid "E549: Illegal percentage" +msgstr "E549: C้atadแn neamhcheadaithe" + +msgid "E854: path too long for completion" +msgstr "E854: conair r๓fhada le comhlแn๚" + +#, c-format +msgid "" +"E343: Invalid path: '**[number]' must be at the end of the path or be " +"followed by '%s'." +msgstr "" +"E343: Conair neamhbhailํ: nํ m๓r '**[uimhir]' a bheith ag deireadh na " +"conaire, n๓ le '%s' ina dhiaidh." + +#, c-format +msgid "E344: Can't find directory \"%s\" in cdpath" +msgstr "E344: Nํ f้idir comhadlann \"%s\" a aimsi๚ sa cdpath" + +#, c-format +msgid "E345: Can't find file \"%s\" in path" +msgstr "E345: Nํ f้idir comhad \"%s\" a aimsi๚ sa chonair" + +#, c-format +msgid "E346: No more directory \"%s\" found in cdpath" +msgstr "E346: Nํl comhadlann \"%s\" sa cdpath a thuilleadh" + +#, c-format +msgid "E347: No more file \"%s\" found in path" +msgstr "E347: Nํl comhad \"%s\" sa chonair a thuilleadh" + +#, c-format +msgid "E668: Wrong access mode for NetBeans connection info file: \"%s\"" +msgstr "E668: M๓d mํcheart rochtana ar an chomhad eolas naisc NetBeans: \"%s\"" + +#, c-format +msgid "E658: NetBeans connection lost for buffer %ld" +msgstr "E658: Cailleadh nasc NetBeans le haghaidh maolแin %ld" + +msgid "E838: netbeans is not supported with this GUI" +msgstr "E838: Nํ thacaํtear le netbeans sa GUI seo" + +msgid "E511: netbeans already connected" +msgstr "E511: Tแ netbeans ceangailte cheana" + +#, c-format +msgid "E505: %s is read-only (add ! to override)" +msgstr "E505: Tแ %s inl้ite amhแin (cuir ! leis chun sแr๚)" + msgid "E349: No identifier under cursor" msgstr "E349: Nํl aitheant๓ir faoin ch๚rs๓ir" -#: ../normal.c:1866 msgid "E774: 'operatorfunc' is empty" msgstr "E774: 'operatorfunc' folamh" -#: ../normal.c:2637 +msgid "E775: Eval feature not available" +msgstr "E775: Nํl an ghn้ Eval le fแil" + msgid "Warning: terminal cannot highlight" msgstr "Rabhadh: nํ f้idir leis an teirmin้al aibhsi๚" -#: ../normal.c:2807 msgid "E348: No string under cursor" msgstr "E348: Nํl teaghrแn faoin ch๚rs๓ir" -#: ../normal.c:3937 msgid "E352: Cannot erase folds with current 'foldmethod'" msgstr "E352: Nํ f้idir fillteacha a l้irscriosadh leis an 'foldmethod' reatha" -#: ../normal.c:5897 msgid "E664: changelist is empty" msgstr "E664: tแ liosta na n-athruithe folamh" -#: ../normal.c:5899 msgid "E662: At start of changelist" msgstr "E662: Ag tosach liosta na n-athruithe" -#: ../normal.c:5901 msgid "E663: At end of changelist" msgstr "E663: Ag deireadh liosta na n-athruithe" -#: ../normal.c:7053 -msgid "Type :quit<Enter> to exit Nvim" +msgid "Type :quit<Enter> to exit Vim" msgstr "Cl๓scrํobh :quit<Enter> chun Vim a scor" # ouch - English -ed ? -#: ../ops.c:248 #, c-format msgid "1 line %sed 1 time" msgstr "1 lํne %s uair amhแin" # ouch - English -ed ? -#: ../ops.c:250 #, c-format msgid "1 line %sed %d times" msgstr "1 lํne %s %d uair" # ouch - English -ed ? -#: ../ops.c:253 #, c-format -msgid "%<PRId64> lines %sed 1 time" -msgstr "%<PRId64> lํne %sed uair amhแin" +msgid "%ld lines %sed 1 time" +msgstr "%ld lํne %sed uair amhแin" # ouch - English -ed ? -#: ../ops.c:256 #, c-format -msgid "%<PRId64> lines %sed %d times" -msgstr "%<PRId64> lํne %sed %d uair" +msgid "%ld lines %sed %d times" +msgstr "%ld lํne %sed %d uair" -#: ../ops.c:592 #, c-format -msgid "%<PRId64> lines to indent... " -msgstr "%<PRId64> lํne le heang๚... " +msgid "%ld lines to indent... " +msgstr "%ld lํne le heang๚... " -#: ../ops.c:634 msgid "1 line indented " msgstr "eangaํodh lํne amhแin " -#: ../ops.c:636 #, c-format -msgid "%<PRId64> lines indented " -msgstr "%<PRId64> lํne eangaithe " +msgid "%ld lines indented " +msgstr "%ld lํne eangaithe " -#: ../ops.c:938 msgid "E748: No previously used register" msgstr "E748: Nํl aon tabhall ๚sแidte roimhe seo" #. must display the prompt -#: ../ops.c:1433 msgid "cannot yank; delete anyway" msgstr "nํ f้idir a sracadh; scrios mar sin f้in" -#: ../ops.c:1929 msgid "1 line changed" msgstr "athraํodh lํne amhแin" -#: ../ops.c:1931 #, c-format -msgid "%<PRId64> lines changed" -msgstr "athraํodh %<PRId64> lํne" +msgid "%ld lines changed" +msgstr "athraํodh %ld lํne" + +#, c-format +msgid "freeing %ld lines" +msgstr "%ld lํne แ saoradh" -#: ../ops.c:2521 msgid "block of 1 line yanked" msgstr "sracadh bloc de lํne amhแin" -#: ../ops.c:2523 msgid "1 line yanked" msgstr "sracadh lํne amhแin" -#: ../ops.c:2525 #, c-format -msgid "block of %<PRId64> lines yanked" -msgstr "sracadh bloc de %<PRId64> lํne" +msgid "block of %ld lines yanked" +msgstr "sracadh bloc de %ld lํne" -#: ../ops.c:2528 #, c-format -msgid "%<PRId64> lines yanked" -msgstr "%<PRId64> lํne sractha" +msgid "%ld lines yanked" +msgstr "%ld lํne sractha" -#: ../ops.c:2710 #, c-format msgid "E353: Nothing in register %s" msgstr "E353: Tabhall folamh %s" #. Highlight title -#: ../ops.c:3185 msgid "" "\n" "--- Registers ---" @@ -4519,11 +4200,9 @@ msgstr "" "\n" "--- Tabhaill ---" -#: ../ops.c:4455 msgid "Illegal register name" msgstr "Ainm neamhcheadaithe tabhaill" -#: ../ops.c:4533 msgid "" "\n" "# Registers:\n" @@ -4531,185 +4210,175 @@ msgstr "" "\n" "# Tabhaill:\n" -#: ../ops.c:4575 #, c-format msgid "E574: Unknown register type %d" msgstr "E574: Cineแl anaithnid tabhaill %d" -#: ../ops.c:5089 +msgid "" +"E883: search pattern and expression register may not contain two or more " +"lines" +msgstr "" +"E883: nํ cheadaํtear nํos m๓ nแ lํne amhแin i bpatr๚n cuardaigh nแ sa " +"slonntabhall" + #, c-format -msgid "%<PRId64> Cols; " -msgstr "%<PRId64> Col๚n; " +msgid "%ld Cols; " +msgstr "%ld Col๚n; " -#: ../ops.c:5097 #, c-format -msgid "" -"Selected %s%<PRId64> of %<PRId64> Lines; %<PRId64> of %<PRId64> Words; " -"%<PRId64> of %<PRId64> Bytes" -msgstr "" -"Roghnaํodh %s%<PRId64> as %<PRId64> Lํne; %<PRId64> as %<PRId64> Focal; " -"%<PRId64> as %<PRId64> Beart" +msgid "Selected %s%ld of %ld Lines; %lld of %lld Words; %lld of %lld Bytes" +msgstr "Roghnaํodh %s%ld as %ld Lํne; %lld as %lld Focal; %lld as %lld Beart" -#: ../ops.c:5105 #, c-format msgid "" -"Selected %s%<PRId64> of %<PRId64> Lines; %<PRId64> of %<PRId64> Words; " -"%<PRId64> of %<PRId64> Chars; %<PRId64> of %<PRId64> Bytes" +"Selected %s%ld of %ld Lines; %lld of %lld Words; %lld of %lld Chars; %lld of " +"%lld Bytes" msgstr "" -"Roghnaํodh %s%<PRId64> as %<PRId64> Lํne; %<PRId64> as %<PRId64> Focal; " -"%<PRId64> as %<PRId64> Carachtar; %<PRId64> as %<PRId64> Beart" +"Roghnaํodh %s%ld as %ld Lํne; %lld as %lld Focal; %lld as %lld Carachtar; %lld as %lld Beart" -#: ../ops.c:5123 #, c-format -msgid "" -"Col %s of %s; Line %<PRId64> of %<PRId64>; Word %<PRId64> of %<PRId64>; Byte " -"%<PRId64> of %<PRId64>" -msgstr "" -"Col %s as %s; Lํne %<PRId64> as %<PRId64>; Focal %<PRId64> as %<PRId64>; " -"Beart %<PRId64> as %<PRId64>" +msgid "Col %s of %s; Line %ld of %ld; Word %lld of %lld; Byte %lld of %lld" +msgstr "Col %s as %s; Lํne %ld as %ld; Focal %lld as %lld; Beart %lld as %lld" -#: ../ops.c:5133 #, c-format msgid "" -"Col %s of %s; Line %<PRId64> of %<PRId64>; Word %<PRId64> of %<PRId64>; Char " -"%<PRId64> of %<PRId64>; Byte %<PRId64> of %<PRId64>" +"Col %s of %s; Line %ld of %ld; Word %lld of %lld; Char %lld of %lld; Byte " +"%lld of %lld" msgstr "" -"Col %s as %s; Lํne %<PRId64> as %<PRId64>; Focal %<PRId64> as %<PRId64>; " -"Carachtar %<PRId64> as %<PRId64>; Beart %<PRId64> as %<PRId64>" +"Col %s as %s; Lํne %ld as %ld; Focal %lld as %lld; Carachtar %lld as %lld; Beart %lld as %lld" -#: ../ops.c:5146 #, c-format -msgid "(+%<PRId64> for BOM)" -msgstr "(+%<PRId64> do BOM)" +msgid "(+%ld for BOM)" +msgstr "(+%ld do BOM)" -#: ../option.c:1238 msgid "%<%f%h%m%=Page %N" msgstr "%<%f%h%m%=Leathanach %N" -#: ../option.c:1574 msgid "Thanks for flying Vim" msgstr "Go raibh mํle maith agat as Vim a ๚sแid" -#. found a mismatch: skip -#: ../option.c:2698 msgid "E518: Unknown option" msgstr "E518: Rogha anaithnid" -#: ../option.c:2709 msgid "E519: Option not supported" msgstr "E519: Nํl an rogha seo ar fแil" -#: ../option.c:2740 msgid "E520: Not allowed in a modeline" msgstr "E520: Nํ cheadaithe i m๓dlํne" -#: ../option.c:2815 msgid "E846: Key code not set" -msgstr "" +msgstr "E846: C๓d eochrach gan socr๚" -#: ../option.c:2924 msgid "E521: Number required after =" msgstr "E521: Tแ gแ le huimhir i ndiaidh =" -#: ../option.c:3226 ../option.c:3864 msgid "E522: Not found in termcap" msgstr "E522: Gan aimsi๚ sa termcap" -#: ../option.c:3335 #, c-format msgid "E539: Illegal character <%s>" msgstr "E539: Carachtar neamhcheadaithe <%s>" -#: ../option.c:3862 +#, c-format +msgid "For option %s" +msgstr "Le haghaidh rogha %s" + msgid "E529: Cannot set 'term' to empty string" msgstr "E529: Nํ f้idir 'term' a shocr๚ mar theaghrแn folamh" -#: ../option.c:3885 +msgid "E530: Cannot change term in GUI" +msgstr "E530: Nํ f้idir 'term' a athr๚ sa GUI" + +msgid "E531: Use \":gui\" to start the GUI" +msgstr "E531: ฺsแid \":gui\" chun an GUI a chur ag obair" + msgid "E589: 'backupext' and 'patchmode' are equal" msgstr "E589: is ionann iad 'backupext' agus 'patchmode'" -#: ../option.c:3964 msgid "E834: Conflicts with value of 'listchars'" -msgstr "" +msgstr "E834: Tagann s้ salach ar luach de 'listchars'" -#: ../option.c:3966 msgid "E835: Conflicts with value of 'fillchars'" -msgstr "" +msgstr "E835: Tagann s้ salach ar luach de 'fillchars'" + +msgid "E617: Cannot be changed in the GTK+ 2 GUI" +msgstr "E617: Nํ f้idir ้ a athr๚ sa GUI GTK+ 2" -#: ../option.c:4163 msgid "E524: Missing colon" msgstr "E524: Idirstad ar iarraidh" -#: ../option.c:4165 msgid "E525: Zero length string" msgstr "E525: Teaghrแn folamh" -#: ../option.c:4220 #, c-format msgid "E526: Missing number after <%s>" msgstr "E526: Uimhir ar iarraidh i ndiaidh <%s>" -#: ../option.c:4232 msgid "E527: Missing comma" msgstr "E527: Cam๓g ar iarraidh" -#: ../option.c:4239 msgid "E528: Must specify a ' value" msgstr "E528: Caithfidh luach ' a shonr๚" -#: ../option.c:4271 msgid "E595: contains unprintable or wide character" msgstr "E595: tแ carachtar neamhghrafach n๓ leathan ann" -#: ../option.c:4469 +msgid "E596: Invalid font(s)" +msgstr "E596: Cl๓(nna) neamhbhailํ" + +msgid "E597: can't select fontset" +msgstr "E597: nํ f้idir tacar cl๓ a roghn๚" + +msgid "E598: Invalid fontset" +msgstr "E598: Tacar cl๓ neamhbhailํ" + +msgid "E533: can't select wide font" +msgstr "E533: nํ f้idir cl๓ leathan a roghn๚" + +msgid "E534: Invalid wide font" +msgstr "E534: Cl๓ leathan neamhbhailํ" + #, c-format msgid "E535: Illegal character after <%c>" msgstr "E535: Carachtar neamhbhailํ i ndiaidh <%c>" -#: ../option.c:4534 msgid "E536: comma required" msgstr "E536: tแ gแ le cam๓g" -#: ../option.c:4543 #, c-format msgid "E537: 'commentstring' must be empty or contain %s" msgstr "" "E537: nํ m๓r %s a bheith i 'commentstring', is ้ sin n๓ nํ m๓r d๓ a bheith " "folamh" -#: ../option.c:4928 +msgid "E538: No mouse support" +msgstr "E538: Gan tacaํocht luiche" + msgid "E540: Unclosed expression sequence" msgstr "E540: Seicheamh gan d๚nadh" -#: ../option.c:4932 msgid "E541: too many items" msgstr "E541: an iomarca mํreanna" -#: ../option.c:4934 msgid "E542: unbalanced groups" msgstr "E542: gr๚paํ neamhchothromaithe" -#: ../option.c:5148 msgid "E590: A preview window already exists" msgstr "E590: Tแ fuinneog r้amhamhairc ann cheana" -#: ../option.c:5311 msgid "W17: Arabic requires UTF-8, do ':set encoding=utf-8'" msgstr "" "W17: Tแ UTF-8 ag teastแil le haghaidh Araibise, socraigh ้ le ':set " "encoding=utf-8'" -#: ../option.c:5623 #, c-format msgid "E593: Need at least %d lines" msgstr "E593: Tแ gแ le %d lํne ar a laghad" -#: ../option.c:5631 #, c-format msgid "E594: Need at least %d columns" msgstr "E594: Tแ gแ le %d col๚n ar a laghad" -#: ../option.c:6011 #, c-format msgid "E355: Unknown option: %s" msgstr "E355: Rogha anaithnid: %s" @@ -4717,12 +4386,10 @@ msgstr "E355: Rogha anaithnid: %s" #. There's another character after zeros or the string #. * is empty. In both cases, we are trying to set a #. * num option using a string. -#: ../option.c:6037 #, c-format msgid "E521: Number required: &%s = '%s'" msgstr "E521: Uimhir de dhํth: &%s = '%s'" -#: ../option.c:6149 msgid "" "\n" "--- Terminal codes ---" @@ -4730,7 +4397,6 @@ msgstr "" "\n" "--- C๓id teirmin้il ---" -#: ../option.c:6151 msgid "" "\n" "--- Global option values ---" @@ -4738,7 +4404,6 @@ msgstr "" "\n" "--- Luachanna na roghanna comhchoiteann ---" -#: ../option.c:6153 msgid "" "\n" "--- Local option values ---" @@ -4746,7 +4411,6 @@ msgstr "" "\n" "--- Luachanna na roghanna logแnta ---" -#: ../option.c:6155 msgid "" "\n" "--- Options ---" @@ -4754,29 +4418,148 @@ msgstr "" "\n" "--- Roghanna ---" -#: ../option.c:6816 msgid "E356: get_varp ERROR" msgstr "E356: EARRมID get_varp" -#: ../option.c:7696 #, c-format msgid "E357: 'langmap': Matching character missing for %s" msgstr "E357: 'langmap': Carachtar comhoiri๚nach ar iarraidh le haghaidh %s" -#: ../option.c:7715 #, c-format msgid "E358: 'langmap': Extra characters after semicolon: %s" msgstr "E358: 'langmap': Carachtair breise i ndiaidh an idirstad: %s" -#: ../os/shell.c:194 +msgid "cannot open " +msgstr "nํ f้idir a oscailt: " + +msgid "VIM: Can't open window!\n" +msgstr "VIM: Nํ f้idir fuinneog a oscailt!\n" + +msgid "Need Amigados version 2.04 or later\n" +msgstr "Tแ gแ le Amigados leagan 2.04 n๓ nํos d้anaํ\n" + +#, c-format +msgid "Need %s version %ld\n" +msgstr "Tแ gแ le %s, leagan %ld\n" + +msgid "Cannot open NIL:\n" +msgstr "Nํ f้idir NIL a oscailt:\n" + +msgid "Cannot create " +msgstr "Nํ f้idir a chruth๚: " + +#, c-format +msgid "Vim exiting with %d\n" +msgstr "Vim แ scor le stแdas %d\n" + +msgid "cannot change console mode ?!\n" +msgstr "nํ f้idir m๓d cons๓il a athr๚ ?!\n" + +msgid "mch_get_shellsize: not a console??\n" +msgstr "mch_get_shellsize: nํ cons๓l ้ seo??\n" + +#. if Vim opened a window: Executing a shell may cause crashes +msgid "E360: Cannot execute shell with -f option" +msgstr "E360: Nํ f้idir blaosc a rith le rogha -f" + +msgid "Cannot execute " +msgstr "Nํ f้idir blaosc a rith: " + +msgid "shell " +msgstr "blaosc " + +msgid " returned\n" +msgstr " aisfhilleadh\n" + +msgid "ANCHOR_BUF_SIZE too small." +msgstr "ANCHOR_BUF_SIZE r๓bheag." + +msgid "I/O ERROR" +msgstr "EARRมID I/A" + +msgid "Message" +msgstr "Teachtaireacht" + +msgid "E237: Printer selection failed" +msgstr "E237: Theip ar roghn๚ print้ara" + +#, c-format +msgid "to %s on %s" +msgstr "go %s ar %s" + +#, c-format +msgid "E613: Unknown printer font: %s" +msgstr "E613: Cl๓fhoireann anaithnid print้ara: %s" + +#, c-format +msgid "E238: Print error: %s" +msgstr "E238: Earrแid phriontแla: %s" + +#, c-format +msgid "Printing '%s'" +msgstr "'%s' แ phriontแil" + +#, c-format +msgid "E244: Illegal charset name \"%s\" in font name \"%s\"" +msgstr "" +"E244: Ainm neamhcheadaithe ar thacar carachtar \"%s\" mar phแirt d'ainm cl๓ " +"\"%s\"" + +#, c-format +msgid "E244: Illegal quality name \"%s\" in font name \"%s\"" +msgstr "" +"E244: Ainm neamhcheadaithe ar chแilํocht \"%s\" in ainm cl๓ \"%s\"" + +#, c-format +msgid "E245: Illegal char '%c' in font name \"%s\"" +msgstr "E245: Carachtar neamhcheadaithe '%c' mar phแirt d'ainm cl๓ \"%s\"" + +#, c-format +msgid "Opening the X display took %ld msec" +msgstr "Th๓g %ld ms chun an scแileแn X a oscailt" + msgid "" "\n" -"Cannot execute shell " +"Vim: Got X error\n" msgstr "" "\n" -"Nํ f้idir blaosc a rith " +"Vim: Fuarthas earrแid ๓ X\n" + +msgid "Testing the X display failed" +msgstr "Theip ar thแstแil an scแileแin X" + +msgid "Opening the X display timed out" +msgstr "Oscailt an scแileแin X thar am" + +msgid "" +"\n" +"Could not get security context for " +msgstr "" +"\n" +"Nํorbh fh้idir comhth้acs slแndแla a fhแil le haghaidh " + +msgid "" +"\n" +"Could not set security context for " +msgstr "" +"\n" +"Nํorbh fh้idir comhth้acs slแndแla a shocr๚ le haghaidh " + +#, c-format +msgid "Could not set security context %s for %s" +msgstr "Nํorbh fh้idir comhth้acs slแndแla %s a shocr๚ le haghaidh %s" + +#, c-format +msgid "Could not get security context %s for %s. Removing it!" +msgstr "Nํorbh fh้idir comhth้acs slแndแla %s a fhแil le haghaidh %s. ม bhaint!" + +msgid "" +"\n" +"Cannot execute shell sh\n" +msgstr "" +"\n" +"Nํ f้idir an bhlaosc sh a rith\n" -#: ../os/shell.c:439 msgid "" "\n" "shell returned " @@ -4784,472 +4567,476 @@ msgstr "" "\n" "d'aisfhill an bhlaosc " -#: ../os_unix.c:465 ../os_unix.c:471 msgid "" "\n" -"Could not get security context for " +"Cannot create pipes\n" msgstr "" "\n" -"Nํorbh fh้idir comhth้acs slแndแla a fhแil le haghaidh " +"Nํ f้idir pํopaํ a chruth๚\n" -#: ../os_unix.c:479 +# "fork" not in standard refs/corpus. Maybe want a "gabhl*" word instead? -KPS msgid "" "\n" -"Could not set security context for " +"Cannot fork\n" msgstr "" "\n" -"Nํorbh fh้idir comhth้acs slแndแla a shocr๚ le haghaidh " +"Nํ f้idir forc a dh้anamh\n" + +msgid "" +"\n" +"Cannot execute shell " +msgstr "" +"\n" +"Nํ f้idir blaosc a rith " + +msgid "" +"\n" +"Command terminated\n" +msgstr "" +"\n" +"Ord๚ crํochnaithe\n" + +msgid "XSMP lost ICE connection" +msgstr "Chaill XSMP an nasc ICE" -#: ../os_unix.c:1558 ../os_unix.c:1647 #, c-format msgid "dlerror = \"%s\"" msgstr "dlerror = \"%s\"" -#: ../path.c:1449 +msgid "Opening the X display failed" +msgstr "Theip ar oscailt an scแileแin X" + +msgid "XSMP handling save-yourself request" +msgstr "Iarratas sแbhแil-do-f้in แ lแimhseแil ag XSMP" + +msgid "XSMP opening connection" +msgstr "Nasc แ oscailt ag XSMP" + +msgid "XSMP ICE connection watch failed" +msgstr "Theip ar fhaire nasc ICE XSMP" + #, c-format -msgid "E447: Can't find file \"%s\" in path" -msgstr "E447: Nํl aon fhแil ar chomhad \"%s\" sa chonair" +msgid "XSMP SmcOpenConnection failed: %s" +msgstr "Theip ar XSMP SmcOpenConnection: %s" + +msgid "At line" +msgstr "Ag lํne" + +msgid "Could not load vim32.dll!" +msgstr "Nํorbh fh้idir vim32.dll a lucht๚!" + +msgid "VIM Error" +msgstr "Earrแid VIM" + +msgid "Could not fix up function pointers to the DLL!" +msgstr "Nํorbh fh้idir pointeoirํ feidhme a ch๓iri๚ i gcomhair an DLL!" + +#, c-format +msgid "Vim: Caught %s event\n" +msgstr "Vim: Fuarthas teagmhas %s\n" + +msgid "close" +msgstr "d๚n" + +msgid "logoff" +msgstr "logแil amach" + +msgid "shutdown" +msgstr "m๚chadh" + +msgid "E371: Command not found" +msgstr "E371: Nํ bhfuarthas an t-ord๚" + +msgid "" +"VIMRUN.EXE not found in your $PATH.\n" +"External commands will not pause after completion.\n" +"See :help win32-vimrun for more information." +msgstr "" +"Nํor aimsํodh VIMRUN.EXE i do $PATH.\n" +"Nํ mhoilleoidh orduithe seachtracha agus iad curtha i gcrํch.\n" +"F้ach ar :help win32-vimrun chun nํos m๓ eolas a fhแil." + +msgid "Vim Warning" +msgstr "Rabhadh Vim" + +#, c-format +msgid "shell returned %d" +msgstr "d'aisfhill an bhlaosc %d" -#: ../quickfix.c:359 #, c-format msgid "E372: Too many %%%c in format string" msgstr "E372: An iomarca %%%c i dteaghrแn formแide" -#: ../quickfix.c:371 #, c-format msgid "E373: Unexpected %%%c in format string" msgstr "E373: %%%c gan choinne i dteaghrแn formแide" -#: ../quickfix.c:420 msgid "E374: Missing ] in format string" msgstr "E374: ] ar iarraidh i dteaghrแn formแide" -#: ../quickfix.c:431 #, c-format msgid "E375: Unsupported %%%c in format string" msgstr "E375: %%%c gan tacaํocht i dteaghrแn formแide" -#: ../quickfix.c:448 #, c-format msgid "E376: Invalid %%%c in format string prefix" msgstr "E376: %%%c neamhbhailํ i r้imํr an teaghrแin formแide" -#: ../quickfix.c:454 #, c-format msgid "E377: Invalid %%%c in format string" msgstr "E377: %%%c neamhbhailํ i dteaghrแn formแide" #. nothing found -#: ../quickfix.c:477 msgid "E378: 'errorformat' contains no pattern" msgstr "E378: Nํl aon phatr๚n i 'errorformat'" -#: ../quickfix.c:695 msgid "E379: Missing or empty directory name" msgstr "E379: Ainm comhadlainne ar iarraidh, n๓ folamh" -#: ../quickfix.c:1305 msgid "E553: No more items" msgstr "E553: Nํl aon mhํr eile" -#: ../quickfix.c:1674 +msgid "E924: Current window was closed" +msgstr "E924: D๚nadh an fhuinneog reatha" + +msgid "E925: Current quickfix was changed" +msgstr "E925: Athraํodh an mearcheart๚chแn reatha" + +msgid "E926: Current location list was changed" +msgstr "E926: Athraํodh an liosta suํomh reatha" + #, c-format msgid "(%d of %d)%s%s: " msgstr "(%d as %d)%s%s: " -#: ../quickfix.c:1676 msgid " (line deleted)" msgstr " (lํne scriosta)" -#: ../quickfix.c:1863 +#, c-format +msgid "%serror list %d of %d; %d errors " +msgstr "%sliosta earrแidํ %d as %d; %d earrแid " + msgid "E380: At bottom of quickfix stack" -msgstr "E380: In ํochtar na cruaiche quickfix" +msgstr "E380: In ํochtar chruach na mearcheart๚chแn" -#: ../quickfix.c:1869 msgid "E381: At top of quickfix stack" -msgstr "E381: In uachtar na cruaiche quickfix" +msgstr "E381: In uachtar chruach na mearcheart๚chแn" -#: ../quickfix.c:1880 -#, c-format -msgid "error list %d of %d; %d errors" -msgstr "liosta earrแidํ %d as %d; %d earrแid" +msgid "No entries" +msgstr "Gan iontrแil" -#: ../quickfix.c:2427 msgid "E382: Cannot write, 'buftype' option is set" msgstr "E382: Nํ f้idir scrํobh, rogha 'buftype' socraithe" -#: ../quickfix.c:2812 +msgid "Error file" +msgstr "Comhad earrแide" + msgid "E683: File name missing or invalid pattern" msgstr "E683: Ainm comhaid ar iarraidh, n๓ patr๚n neamhbhailํ" -#: ../quickfix.c:2911 #, c-format msgid "Cannot open file \"%s\"" msgstr "Nํ f้idir comhad \"%s\" a oscailt" -#: ../quickfix.c:3429 msgid "E681: Buffer is not loaded" msgstr "E681: Nํl an maolแn luchtaithe" -#: ../quickfix.c:3487 msgid "E777: String or List expected" msgstr "E777: Bhํothas ag s๚il le Teaghrแn n๓ Liosta" -#: ../regexp.c:359 #, c-format msgid "E369: invalid item in %s%%[]" msgstr "E369: mํr neamhbhailํ i %s%%[]" -#: ../regexp.c:374 #, c-format msgid "E769: Missing ] after %s[" msgstr "E769: ] ar iarraidh i ndiaidh %s[" -#: ../regexp.c:375 #, c-format msgid "E53: Unmatched %s%%(" msgstr "E53: %s%%( corr" -#: ../regexp.c:376 #, c-format msgid "E54: Unmatched %s(" msgstr "E54: %s( corr" -#: ../regexp.c:377 #, c-format msgid "E55: Unmatched %s)" msgstr "E55: %s) corr" -#: ../regexp.c:378 msgid "E66: \\z( not allowed here" msgstr "E66: nํ cheadaํtear \\z( anseo" -#: ../regexp.c:379 msgid "E67: \\z1 et al. not allowed here" msgstr "E67: nํ cheadaํtear \\z1 et al. anseo" -#: ../regexp.c:380 #, c-format msgid "E69: Missing ] after %s%%[" msgstr "E69: ] ar iarraidh i ndiaidh %s%%[" -#: ../regexp.c:381 #, c-format msgid "E70: Empty %s%%[]" msgstr "E70: %s%%[] folamh" -#: ../regexp.c:1209 ../regexp.c:1224 msgid "E339: Pattern too long" msgstr "E339: Slonn r๓fhada" -#: ../regexp.c:1371 msgid "E50: Too many \\z(" msgstr "E50: an iomarca \\z(" -#: ../regexp.c:1378 #, c-format msgid "E51: Too many %s(" msgstr "E51: an iomarca %s(" -#: ../regexp.c:1427 msgid "E52: Unmatched \\z(" msgstr "E52: \\z( corr" -#: ../regexp.c:1637 #, c-format msgid "E59: invalid character after %s@" msgstr "E59: carachtar neamhbhailํ i ndiaidh %s@" -#: ../regexp.c:1672 #, c-format msgid "E60: Too many complex %s{...}s" msgstr "E60: An iomarca %s{...} coimpl้ascach" -#: ../regexp.c:1687 #, c-format msgid "E61: Nested %s*" msgstr "E61: %s* neadaithe" -#: ../regexp.c:1690 #, c-format msgid "E62: Nested %s%c" msgstr "E62: %s%c neadaithe" -#: ../regexp.c:1800 msgid "E63: invalid use of \\_" msgstr "E63: ๚sแid neamhbhailํ de \\_" -#: ../regexp.c:1850 #, c-format msgid "E64: %s%c follows nothing" msgstr "E64: nํl aon rud roimh %s%c" -#: ../regexp.c:1902 msgid "E65: Illegal back reference" msgstr "E65: C๚ltagairt neamhbhailํ" -#: ../regexp.c:1943 msgid "E68: Invalid character after \\z" msgstr "E68: Carachtar neamhbhailํ i ndiaidh \\z" -#: ../regexp.c:2049 ../regexp_nfa.c:1296 #, c-format msgid "E678: Invalid character after %s%%[dxouU]" msgstr "E678: Carachtar neamhbhailํ i ndiaidh %s%%[dxouU]" -#: ../regexp.c:2107 #, c-format msgid "E71: Invalid character after %s%%" msgstr "E71: Carachtar neamhbhailํ i ndiaidh %s%%" -#: ../regexp.c:3017 #, c-format msgid "E554: Syntax error in %s{...}" msgstr "E554: Earrแid chomhr้ire i %s{...}" -#: ../regexp.c:3805 msgid "External submatches:\n" msgstr "Fo-mheaitseแil sheachtrach:\n" -#: ../regexp.c:7022 +#, c-format +msgid "E888: (NFA regexp) cannot repeat %s" +msgstr "E888: (slonn NFA) nํ f้idir %s a athdh้anamh" + msgid "" "E864: \\%#= can only be followed by 0, 1, or 2. The automatic engine will be " "used " msgstr "" +"E864: Nํ cheadaํtear ach 0, 1, n๓ 2 tar ้is \\%#=. ฺsแidfear an t-inneall " +"uathoibrํoch " -#: ../regexp_nfa.c:239 -msgid "E865: (NFA) Regexp end encountered prematurely" +msgid "Switching to backtracking RE engine for pattern: " msgstr "" +"Ag athr๚ go dtํ an t-inneall rianaithe siar le haghaidh an phatr๚in seo: " + +msgid "E865: (NFA) Regexp end encountered prematurely" +msgstr "E865: (NFA) Thแngthas ar dheireadh an tsloinn gan s๚il leis" -#: ../regexp_nfa.c:240 #, c-format msgid "E866: (NFA regexp) Misplaced %c" -msgstr "" +msgstr "E866: (slonn NFA) %c as แit" -#: ../regexp_nfa.c:242 #, c-format -msgid "E877: (NFA regexp) Invalid character class: %<PRId64>" -msgstr "" +msgid "E877: (NFA regexp) Invalid character class: %ld" +msgstr "E877: (slonn NFA) Aicme carachtar neamhbhailํ: %ld" -#: ../regexp_nfa.c:1261 #, c-format msgid "E867: (NFA) Unknown operator '\\z%c'" -msgstr "" +msgstr "E867: (NFA) Oibreoir anaithnid '\\z%c'" -#: ../regexp_nfa.c:1387 #, c-format msgid "E867: (NFA) Unknown operator '\\%%%c'" -msgstr "" +msgstr "E867: (NFA) Oibreoir anaithnid '\\%%%c'" + +#. should never happen +msgid "E868: Error building NFA with equivalence class!" +msgstr "E868: Earrแid agus NFA แ th๓gแil le haicme coibh้ise!" -#: ../regexp_nfa.c:1802 #, c-format msgid "E869: (NFA) Unknown operator '\\@%c'" -msgstr "" +msgstr "E869: (NFA) Oibreoir anaithnid '\\@%c'" -#: ../regexp_nfa.c:1831 msgid "E870: (NFA regexp) Error reading repetition limits" -msgstr "" +msgstr "E870: (slonn NFA) Earrแid agus teorainneacha athdh้anta แ l้amh" #. Can't have a multi follow a multi. -#: ../regexp_nfa.c:1895 msgid "E871: (NFA regexp) Can't have a multi follow a multi !" -msgstr "" +msgstr "E871: (slonn NFA) Nํ cheadaํtear ilchodach tar ้is ilchodach!" #. Too many `(' -#: ../regexp_nfa.c:2037 msgid "E872: (NFA regexp) Too many '('" -msgstr "" +msgstr "E872: (slonn NFA) An iomarca '('" -#: ../regexp_nfa.c:2042 -#, fuzzy msgid "E879: (NFA regexp) Too many \\z(" -msgstr "E50: an iomarca \\z(" +msgstr "E879: (slonn NFA) An iomarca \\z(" -#: ../regexp_nfa.c:2066 msgid "E873: (NFA regexp) proper termination error" -msgstr "" +msgstr "E873: (slonn NFA) crํochn๚ neamhoiri๚nach" -#: ../regexp_nfa.c:2599 msgid "E874: (NFA) Could not pop the stack !" -msgstr "" +msgstr "E874: (NFA) Nํorbh fh้idir an chruach a phlobadh!" -#: ../regexp_nfa.c:3298 msgid "" "E875: (NFA regexp) (While converting from postfix to NFA), too many states " "left on stack" msgstr "" +"E875: (slonn NFA) (Le linn tiontaithe ๓ postfix go NFA), an iomarca " +"staideanna fแgtha ar an gcruach" -#: ../regexp_nfa.c:3302 msgid "E876: (NFA regexp) Not enough space to store the whole NFA " +msgstr "E876: (slonn NFA) Nํl go leor spแis ann don NFA iomlแn " + +msgid "E878: (NFA) Could not allocate memory for branch traversal!" msgstr "" +"E878: (NFA) Nํorbh fh้idir cuimhne a leithdhแileadh leis an gcraobh a " +"thrasnaํl!" -#: ../regexp_nfa.c:4571 ../regexp_nfa.c:4869 msgid "" "Could not open temporary log file for writing, displaying on stderr ... " msgstr "" +"Nํorbh fh้idir logchomhad sealadach a oscailt le scrํobh ann, แ thaispeแint " +"ar stderr..." -#: ../regexp_nfa.c:4840 #, c-format msgid "(NFA) COULD NOT OPEN %s !" -msgstr "" +msgstr "(NFA) NอORBH FHษIDIR %s A OSCAILT!" -#: ../regexp_nfa.c:6049 -#, fuzzy msgid "Could not open temporary log file for writing " -msgstr "E214: Nํ f้idir comhad sealadach a aimsi๚ chun scrํobh ann" +msgstr "Nํorbh fh้idir logchomhad sealadach a oscailt le scrํobh ann " -#: ../screen.c:7435 msgid " VREPLACE" msgstr " V-IONADAIGH" -#: ../screen.c:7437 msgid " REPLACE" msgstr " ATHCHUR" -#: ../screen.c:7440 msgid " REVERSE" msgstr " TIONTฺ" -#: ../screen.c:7441 msgid " INSERT" msgstr " IONSม" -#: ../screen.c:7443 msgid " (insert)" msgstr " (ionsแigh)" -#: ../screen.c:7445 msgid " (replace)" msgstr " (ionadaigh)" -#: ../screen.c:7447 msgid " (vreplace)" msgstr " (v-ionadaigh)" -#: ../screen.c:7449 msgid " Hebrew" msgstr " Eabhrais" -#: ../screen.c:7454 msgid " Arabic" msgstr " Araibis" -#: ../screen.c:7456 -msgid " (lang)" -msgstr " (teanga)" - -#: ../screen.c:7459 msgid " (paste)" msgstr " (greamaigh)" -#: ../screen.c:7469 msgid " VISUAL" msgstr " RADHARCACH" -#: ../screen.c:7470 msgid " VISUAL LINE" msgstr " LอNE RADHARCACH" -#: ../screen.c:7471 msgid " VISUAL BLOCK" msgstr " BLOC RADHARCACH" -#: ../screen.c:7472 msgid " SELECT" msgstr " ROGHNฺ" -#: ../screen.c:7473 msgid " SELECT LINE" msgstr " SELECT LINE" -#: ../screen.c:7474 msgid " SELECT BLOCK" msgstr " SELECT BLOCK" -#: ../screen.c:7486 ../screen.c:7541 msgid "recording" msgstr "แ thaifeadadh" -#: ../search.c:487 #, c-format msgid "E383: Invalid search string: %s" msgstr "E383: Teaghrแn cuardaigh neamhbhailํ: %s" -#: ../search.c:832 #, c-format msgid "E384: search hit TOP without match for: %s" msgstr "E384: bhuail an cuardach an BARR gan teaghrแn comhoiri๚nach le %s" -#: ../search.c:835 #, c-format msgid "E385: search hit BOTTOM without match for: %s" msgstr "E385: bhuail an cuardach an BUN gan teaghrแn comhoiri๚nach le %s" -#: ../search.c:1200 msgid "E386: Expected '?' or '/' after ';'" msgstr "E386: Ag s๚il le '?' n๓ '/' i ndiaidh ';'" -#: ../search.c:4085 msgid " (includes previously listed match)" msgstr " (tแ an teaghrแn comhoiri๚naithe roimhe seo san แireamh)" #. cursor at status line -#: ../search.c:4104 msgid "--- Included files " msgstr "--- Comhaid cheanntแisc " -#: ../search.c:4106 msgid "not found " msgstr "gan aimsi๚" -#: ../search.c:4107 msgid "in path ---\n" msgstr "i gconair ---\n" -#: ../search.c:4168 msgid " (Already listed)" msgstr " (Liostaithe cheana f้in)" -#: ../search.c:4170 msgid " NOT FOUND" msgstr " AR IARRAIDH" -#: ../search.c:4211 #, c-format msgid "Scanning included file: %s" msgstr "Comhad ceanntแisc แ scanadh: %s" -#: ../search.c:4216 #, c-format msgid "Searching included file %s" msgstr "Comhad ceanntแisc %s แ chuardach" -#: ../search.c:4405 msgid "E387: Match is on current line" msgstr "E387: Tแ an teaghrแn comhoiri๚naithe ar an lํne reatha" -#: ../search.c:4517 msgid "All included files were found" msgstr "Aimsํodh gach comhad ceanntแisc" -#: ../search.c:4519 msgid "No included files" msgstr "Gan comhaid cheanntแisc" -#: ../search.c:4527 msgid "E388: Couldn't find definition" msgstr "E388: Sainmhํni๚ gan aimsi๚" -#: ../search.c:4529 msgid "E389: Couldn't find pattern" msgstr "E389: Patr๚n gan aimsi๚" -#: ../search.c:4668 msgid "Substitute " msgstr "Ionad๚ " # in .viminfo -#: ../search.c:4681 #, c-format msgid "" "\n" @@ -5260,98 +5047,130 @@ msgstr "" "# %sPatr๚n Cuardaigh Is D้anaํ:\n" "~" -#: ../spell.c:951 -msgid "E759: Format error in spell file" -msgstr "E759: Earrแid fhormแide i gcomhad litrithe" +msgid "E756: Spell checking is not enabled" +msgstr "E756: Nํl seiceแil litrithe cumasaithe" + +#, c-format +msgid "Warning: Cannot find word list \"%s_%s.spl\" or \"%s_ascii.spl\"" +msgstr "" +"Rabhadh: Nํ f้idir liosta focal \"%s_%s.spl\" n๓ \"%s_ascii.spl\" a aimsi๚" + +#, c-format +msgid "Warning: Cannot find word list \"%s.%s.spl\" or \"%s.ascii.spl\"" +msgstr "" +"Rabhadh: Nํ f้idir liosta focal \"%s.%s.spl\" n๓ \"%s.ascii.spl\" a aimsi๚" + +msgid "E797: SpellFileMissing autocommand deleted buffer" +msgstr "E797: Scrios uathord๚ SpellFileMissing an maolแn" + +#, c-format +msgid "Warning: region %s not supported" +msgstr "Rabhadh: r้igi๚n %s gan tacaํocht" + +msgid "Sorry, no suggestions" +msgstr "Tแ br๓n orm, nํl aon mholadh ann" + +#, c-format +msgid "Sorry, only %ld suggestions" +msgstr "Tแ br๓n orm, nํl ach %ld moladh ann" + +#. for when 'cmdheight' > 1 +#. avoid more prompt +#, c-format +msgid "Change \"%.*s\" to:" +msgstr "Athraigh \"%.*s\" go:" + +#, c-format +msgid " < \"%.*s\"" +msgstr " < \"%.*s\"" + +msgid "E752: No previous spell replacement" +msgstr "E752: Nํl aon ionadaํ litrithe roimhe seo" + +#, c-format +msgid "E753: Not found: %s" +msgstr "E753: Gan aimsi๚: %s" -#: ../spell.c:952 msgid "E758: Truncated spell file" msgstr "E758: Comhad teasctha litrithe" -#: ../spell.c:953 #, c-format msgid "Trailing text in %s line %d: %s" msgstr "T้acs chun deiridh i %s lํne %d: %s" -#: ../spell.c:954 #, c-format msgid "Affix name too long in %s line %d: %s" msgstr "Ainm foircinn r๓fhada i %s lํne %d: %s" -#: ../spell.c:955 msgid "E761: Format error in affix file FOL, LOW or UPP" msgstr "E761: Earrแid fhormแide i gcomhad foircinn FOL, LOW, n๓ UPP" -#: ../spell.c:957 msgid "E762: Character in FOL, LOW or UPP is out of range" msgstr "E762: Carachtar i FOL, LOW n๓ UPP as raon" -#: ../spell.c:958 msgid "Compressing word tree..." msgstr "Crann focal แ chomhbhr๚..." -#: ../spell.c:1951 -msgid "E756: Spell checking is not enabled" -msgstr "E756: Nํl seiceแil litrithe cumasaithe" - -#: ../spell.c:2249 -#, c-format -msgid "Warning: Cannot find word list \"%s.%s.spl\" or \"%s.ascii.spl\"" -msgstr "" -"Rabhadh: Nํ f้idir liosta focal \"%s.%s.spl\" n๓ \"%s.ascii.spl\" a aimsi๚" - -#: ../spell.c:2473 #, c-format msgid "Reading spell file \"%s\"" msgstr "Comhad litrithe \"%s\" แ l้amh" -#: ../spell.c:2496 msgid "E757: This does not look like a spell file" msgstr "E757: Nํl s้ cos๚il le comhad litrithe" -#: ../spell.c:2501 msgid "E771: Old spell file, needs to be updated" msgstr "E771: Seanchomhad litrithe, tแ gแ lena nuashonr๚" -#: ../spell.c:2504 msgid "E772: Spell file is for newer version of Vim" msgstr "E772: Oibrํonn an comhad litrithe le leagan nํos nuaํ de Vim" -#: ../spell.c:2602 msgid "E770: Unsupported section in spell file" msgstr "E770: Rannแn gan tacaํocht i gcomhad litrithe" -#: ../spell.c:3762 #, c-format -msgid "Warning: region %s not supported" -msgstr "Rabhadh: r้igi๚n %s gan tacaํocht" +msgid "E778: This does not look like a .sug file: %s" +msgstr "E778: Nํl s้ cos๚il le comhad .sug: %s" + +#, c-format +msgid "E779: Old .sug file, needs to be updated: %s" +msgstr "E779: Seanchomhad .sug, tแ gแ lena nuashonr๚: %s" + +#, c-format +msgid "E780: .sug file is for newer version of Vim: %s" +msgstr "E780: Oibrํonn an comhad .sug le leagan nํos nuaํ de Vim: %s" + +#, c-format +msgid "E781: .sug file doesn't match .spl file: %s" +msgstr "E781: Nํl an comhad .sug comhoiri๚nach leis an gcomhad .spl: %s" + +#, c-format +msgid "E782: error while reading .sug file: %s" +msgstr "E782: earrแid agus comhad .sug แ l้amh: %s" -#: ../spell.c:4550 #, c-format msgid "Reading affix file %s ..." msgstr "Comhad foircinn %s แ l้amh..." -#: ../spell.c:4589 ../spell.c:5635 ../spell.c:6140 #, c-format msgid "Conversion failure for word in %s line %d: %s" msgstr "Theip ar thiont๚ focail i %s lํne %d: %s" -#: ../spell.c:4630 ../spell.c:6170 #, c-format msgid "Conversion in %s not supported: from %s to %s" msgstr "Tiont๚ i %s gan tacaํocht: ๓ %s go %s" -#: ../spell.c:4642 +#, c-format +msgid "Conversion in %s not supported" +msgstr "Tiont๚ i %s gan tacaํocht" + #, c-format msgid "Invalid value for FLAG in %s line %d: %s" msgstr "Luach neamhbhailํ ar FLAG i %s lํne %d: %s" -#: ../spell.c:4655 #, c-format msgid "FLAG after using flags in %s line %d: %s" msgstr "FLAG i ndiaidh bratacha in ๚sแid i %s lํne %d: %s" -#: ../spell.c:4723 #, c-format msgid "" "Defining COMPOUNDFORBIDFLAG after PFX item may give wrong results in %s line " @@ -5360,7 +5179,6 @@ msgstr "" "Seans go bhfaighfidh t๚ torthaํ mํchearta mแ chuireann t๚ COMPOUNDFORBIDFLAG " "tar ้is mํre PFX i %s lํne %d" -#: ../spell.c:4731 #, c-format msgid "" "Defining COMPOUNDPERMITFLAG after PFX item may give wrong results in %s line " @@ -5369,42 +5187,34 @@ msgstr "" "Seans go bhfaighfidh t๚ torthaํ mํchearta mแ chuireann t๚ COMPOUNDPERMITFLAG " "tar ้is mํre PFX i %s lํne %d" -#: ../spell.c:4747 #, c-format msgid "Wrong COMPOUNDRULES value in %s line %d: %s" msgstr "Luach mํcheart ar COMPOUNDRULES i %s lํne %d: %s" -#: ../spell.c:4771 #, c-format msgid "Wrong COMPOUNDWORDMAX value in %s line %d: %s" msgstr "Luach mํcheart ar COMPOUNDWORDMAX i %s lํne %d: %s" -#: ../spell.c:4777 #, c-format msgid "Wrong COMPOUNDMIN value in %s line %d: %s" msgstr "Luach mํcheart ar COMPOUNDMIN i %s lํne %d: %s" -#: ../spell.c:4783 #, c-format msgid "Wrong COMPOUNDSYLMAX value in %s line %d: %s" msgstr "Luach mํcheart ar COMPOUNDSYLMAX i %s lํne %d: %s" -#: ../spell.c:4795 #, c-format msgid "Wrong CHECKCOMPOUNDPATTERN value in %s line %d: %s" msgstr "Luach mํcheart ar CHECKCOMPOUNDPATTERN i %s lํne %d: %s" -#: ../spell.c:4847 #, c-format msgid "Different combining flag in continued affix block in %s line %d: %s" msgstr "Bratach dhifri๚il cheangail i mbloc leanta foircinn i %s lํne %d: %s" -#: ../spell.c:4850 #, c-format msgid "Duplicate affix in %s line %d: %s" msgstr "Clib dh๚blach i %s lํne %d: %s" -#: ../spell.c:4871 #, c-format msgid "" "Affix also used for BAD/RARE/KEEPCASE/NEEDAFFIX/NEEDCOMPOUND/NOSUGGEST in %s " @@ -5413,335 +5223,230 @@ msgstr "" "Foirceann in ๚sแid le haghaidh BAD/RARE/KEEPCASE/NEEDAFFIX/NEEDCOMPOUND/" "NOSUGGEST freisin i %s lํne %d: %s" -#: ../spell.c:4893 #, c-format msgid "Expected Y or N in %s line %d: %s" msgstr "Bhํothas ag s๚il le `Y' n๓ `N' i %s lํne %d: %s" -#: ../spell.c:4968 #, c-format msgid "Broken condition in %s line %d: %s" msgstr "Coinnํoll briste i %s lํne %d: %s" -#: ../spell.c:5091 #, c-format msgid "Expected REP(SAL) count in %s line %d" msgstr "Bhํothas ag s๚il le lํon na REP(SAL) i %s lํne %d" -#: ../spell.c:5120 #, c-format msgid "Expected MAP count in %s line %d" msgstr "Bhํothas ag s๚il le lํon na MAP i %s lํne %d" -#: ../spell.c:5132 #, c-format msgid "Duplicate character in MAP in %s line %d" msgstr "Carachtar d๚blach i MAP i %s lํne %d" -#: ../spell.c:5176 #, c-format msgid "Unrecognized or duplicate item in %s line %d: %s" msgstr "Mํr anaithnid n๓ dh๚blach i %s lํne %d: %s" -#: ../spell.c:5197 #, c-format msgid "Missing FOL/LOW/UPP line in %s" msgstr "Lํne FOL/LOW/UPP ar iarraidh i %s" -#: ../spell.c:5220 msgid "COMPOUNDSYLMAX used without SYLLABLE" msgstr "COMPOUNDSYLMAX in ๚sแid gan SYLLABLE" -#: ../spell.c:5236 msgid "Too many postponed prefixes" msgstr "An iomarca r้imํreanna curtha siar" -#: ../spell.c:5238 msgid "Too many compound flags" msgstr "An iomarca bratach comhfhocail" -#: ../spell.c:5240 msgid "Too many postponed prefixes and/or compound flags" msgstr "An iomarca r้imํreanna curtha siar agus/n๓ bratacha comhfhocal" -#: ../spell.c:5250 #, c-format msgid "Missing SOFO%s line in %s" msgstr "Lํne SOFO%s ar iarraidh i %s" -#: ../spell.c:5253 #, c-format msgid "Both SAL and SOFO lines in %s" msgstr "Lํnte SAL agus SOFO araon i %s" -#: ../spell.c:5331 #, c-format msgid "Flag is not a number in %s line %d: %s" msgstr "Nํ uimhir ํ an bhratach i %s lํne %d: %s" -#: ../spell.c:5334 #, c-format msgid "Illegal flag in %s line %d: %s" msgstr "Bratach neamhcheadaithe i %s lํne %d: %s" -#: ../spell.c:5493 ../spell.c:5501 #, c-format msgid "%s value differs from what is used in another .aff file" msgstr "Tแ difear idir luach %s agus an luach i gcomhad .aff eile" -#: ../spell.c:5602 #, c-format msgid "Reading dictionary file %s ..." msgstr "Focl๓ir %s แ l้amh ..." -#: ../spell.c:5611 #, c-format msgid "E760: No word count in %s" msgstr "E760: Lํon na bhfocal ar iarraidh i %s" -#: ../spell.c:5669 #, c-format msgid "line %6d, word %6d - %s" msgstr "lํne %6d, focal %6d - %s" -#: ../spell.c:5691 #, c-format msgid "Duplicate word in %s line %d: %s" msgstr "Focal d๚blach i %s lํne %d: %s" -#: ../spell.c:5694 #, c-format msgid "First duplicate word in %s line %d: %s" msgstr "An ch้ad fhocal d๚blach i %s lํne %d: %s" -#: ../spell.c:5746 #, c-format msgid "%d duplicate word(s) in %s" msgstr "%d focal d๚blach i %s" -#: ../spell.c:5748 #, c-format msgid "Ignored %d word(s) with non-ASCII characters in %s" msgstr "Rinneadh neamhshuim ar %d focal le carachtair neamh-ASCII i %s" -#: ../spell.c:6115 #, c-format msgid "Reading word file %s ..." msgstr "Comhad focail %s แ l้amh ..." -#: ../spell.c:6155 #, c-format msgid "Duplicate /encoding= line ignored in %s line %d: %s" msgstr "Rinneadh neamhshuim ar lํne dh๚blach `/encoding=' i %s lํne %d: %s" -#: ../spell.c:6159 #, c-format msgid "/encoding= line after word ignored in %s line %d: %s" msgstr "" "Rinneadh neamhshuim ar lํne `/encoding=' i ndiaidh focail i %s lํne %d: %s" -#: ../spell.c:6180 #, c-format msgid "Duplicate /regions= line ignored in %s line %d: %s" msgstr "Rinneadh neamhshuim ar lํne `/regions=' i %s lํne %d: %s" -#: ../spell.c:6185 #, c-format msgid "Too many regions in %s line %d: %s" msgstr "An iomarca r้igi๚n i %s lํne %d: %s" -#: ../spell.c:6198 #, c-format msgid "/ line ignored in %s line %d: %s" msgstr "Rinneadh neamhshuim ar lํne `/' i %s lํne %d: %s" -#: ../spell.c:6224 #, c-format msgid "Invalid region nr in %s line %d: %s" msgstr "Uimhir neamhbhailํ r้igi๚in i %s lํne %d: %s" -#: ../spell.c:6230 #, c-format msgid "Unrecognized flags in %s line %d: %s" msgstr "Bratacha anaithnide i %s lํne %d: %s" -#: ../spell.c:6257 #, c-format msgid "Ignored %d words with non-ASCII characters" msgstr "Rinneadh neamhshuim ar %d focal le carachtair neamh-ASCII" -#: ../spell.c:6656 +msgid "E845: Insufficient memory, word list will be incomplete" +msgstr "E845: Easpa cuimhne, beidh an liosta focal neamhiomlแn" + #, c-format msgid "Compressed %d of %d nodes; %d (%d%%) remaining" msgstr "Comhbhr๚dh %d as %d n๓d; %d (%d%%) fแgtha" -#: ../spell.c:7340 msgid "Reading back spell file..." msgstr "Comhad litrithe แ l้amh arํs..." -#. Go through the trie of good words, soundfold each word and add it to -#. the soundfold trie. -#: ../spell.c:7357 +#. +#. * Go through the trie of good words, soundfold each word and add it to +#. * the soundfold trie. +#. msgid "Performing soundfolding..." msgstr "Fuaimfhilleadh..." -#: ../spell.c:7368 #, c-format -msgid "Number of words after soundfolding: %<PRId64>" -msgstr "Lํon na bhfocal tar ้is fuaimfhillte: %<PRId64>" +msgid "Number of words after soundfolding: %ld" +msgstr "Lํon na bhfocal tar ้is fuaimfhillte: %ld" -#: ../spell.c:7476 #, c-format msgid "Total number of words: %d" msgstr "Lํon iomlแn na bhfocal: %d" -#: ../spell.c:7655 #, c-format msgid "Writing suggestion file %s ..." msgstr "Comhad moltaํ %s แ scrํobh ..." -#: ../spell.c:7707 ../spell.c:7927 #, c-format msgid "Estimated runtime memory use: %d bytes" msgstr "Cuimhne measta a bheith in ๚sแid le linn rite: %d beart" -#: ../spell.c:7820 msgid "E751: Output file name must not have region name" msgstr "E751: Nํ cheadaํtear ainm r้igi๚in in ainm an aschomhaid" -#: ../spell.c:7822 msgid "E754: Only up to 8 regions supported" msgstr "E754: Nํ thacaํtear le nํos m๓ nแ 8 r้igi๚n" -#: ../spell.c:7846 #, c-format msgid "E755: Invalid region in %s" msgstr "E755: R้igi๚n neamhbhailํ i %s" -#: ../spell.c:7907 msgid "Warning: both compounding and NOBREAK specified" msgstr "Rabhadh: sonraํodh comhfhocail agus NOBREAK araon" -#: ../spell.c:7920 #, c-format msgid "Writing spell file %s ..." msgstr "Comhad litrithe %s แ scrํobh ..." -#: ../spell.c:7925 msgid "Done!" msgstr "Crํochnaithe!" -#: ../spell.c:8034 #, c-format -msgid "E765: 'spellfile' does not have %<PRId64> entries" -msgstr "E765: nํl %<PRId64> iontrแil i 'spellfile'" +msgid "E765: 'spellfile' does not have %ld entries" +msgstr "E765: nํl %ld iontrแil i 'spellfile'" -#: ../spell.c:8074 -#, fuzzy, c-format +#, c-format msgid "Word '%.*s' removed from %s" -msgstr "Baineadh focal ๓ %s" +msgstr "Baineadh focal '%.*s' ๓ %s" -#: ../spell.c:8117 -#, fuzzy, c-format +#, c-format msgid "Word '%.*s' added to %s" -msgstr "Cuireadh focal le %s" +msgstr "Cuireadh focal '%.*s' le %s" -#: ../spell.c:8381 msgid "E763: Word characters differ between spell files" msgstr "E763: Tแ carachtair dhifri๚la fhocail sna comhaid litrithe" -#: ../spell.c:8684 -msgid "Sorry, no suggestions" -msgstr "Tแ br๓n orm, nํl aon mholadh ann" - -#: ../spell.c:8687 -#, c-format -msgid "Sorry, only %<PRId64> suggestions" -msgstr "Tแ br๓n orm, nํl ach %<PRId64> moladh ann" - -#. for when 'cmdheight' > 1 -#. avoid more prompt -#: ../spell.c:8704 -#, c-format -msgid "Change \"%.*s\" to:" -msgstr "Athraigh \"%.*s\" go:" - -#: ../spell.c:8737 -#, c-format -msgid " < \"%.*s\"" -msgstr " < \"%.*s\"" - -#: ../spell.c:8882 -msgid "E752: No previous spell replacement" -msgstr "E752: Nํl aon ionadaํ litrithe roimhe seo" - -#: ../spell.c:8925 -#, c-format -msgid "E753: Not found: %s" -msgstr "E753: Gan aimsi๚: %s" - -#: ../spell.c:9276 -#, c-format -msgid "E778: This does not look like a .sug file: %s" -msgstr "E778: Nํl s้ cos๚il le comhad .sug: %s" - -#: ../spell.c:9282 -#, c-format -msgid "E779: Old .sug file, needs to be updated: %s" -msgstr "E779: Seanchomhad .sug, tแ gแ lena nuashonr๚: %s" - -#: ../spell.c:9286 -#, c-format -msgid "E780: .sug file is for newer version of Vim: %s" -msgstr "E780: Oibrํonn an comhad .sug le leagan nํos nuaํ de Vim: %s" - -#: ../spell.c:9295 -#, c-format -msgid "E781: .sug file doesn't match .spl file: %s" -msgstr "E781: Nํl an comhad .sug comhoiri๚nach leis an gcomhad .spl: %s" - -#: ../spell.c:9305 -#, c-format -msgid "E782: error while reading .sug file: %s" -msgstr "E782: earrแid agus comhad .sug แ l้amh: %s" - #. This should have been checked when generating the .spl -#. file. -#: ../spell.c:11575 +#. * file. msgid "E783: duplicate char in MAP entry" msgstr "E783: carachtar d๚blach in iontrแil MAP" -#: ../syntax.c:266 msgid "No Syntax items defined for this buffer" msgstr "Nํl aon mhํr chomhr้ire sainmhํnithe le haghaidh an mhaolแin seo" -#: ../syntax.c:3083 ../syntax.c:3104 ../syntax.c:3127 #, c-format msgid "E390: Illegal argument: %s" msgstr "E390: Arg๓int neamhcheadaithe: %s" -#: ../syntax.c:3299 +msgid "syntax iskeyword " +msgstr "comhr้ir iskeyword " + #, c-format msgid "E391: No such syntax cluster: %s" msgstr "E391: Nํl a leith้id de mhogall comhr้ire: %s" -#: ../syntax.c:3433 msgid "syncing on C-style comments" msgstr "ag sioncr๓n๚ ar n๓ta den n๓s C" -#: ../syntax.c:3439 msgid "no syncing" msgstr "gan sioncr๓n๚" -#: ../syntax.c:3441 msgid "syncing starts " msgstr "tosaํonn an sioncr๓n๚ " -#: ../syntax.c:3443 ../syntax.c:3506 msgid " lines before top line" msgstr " lํnte roimh an bharr" -#: ../syntax.c:3448 msgid "" "\n" "--- Syntax sync items ---" @@ -5749,7 +5454,6 @@ msgstr "" "\n" "--- Mํreanna Comhr้ire Sionc ---" -#: ../syntax.c:3452 msgid "" "\n" "syncing on items" @@ -5757,7 +5461,6 @@ msgstr "" "\n" "ag sioncr๓n๚ ar mhํreanna" -#: ../syntax.c:3457 msgid "" "\n" "--- Syntax items ---" @@ -5765,275 +5468,217 @@ msgstr "" "\n" "--- Mํreanna comhr้ire ---" -#: ../syntax.c:3475 #, c-format msgid "E392: No such syntax cluster: %s" msgstr "E392: Nํl a leith้id de mhogall comhr้ire: %s" -#: ../syntax.c:3497 msgid "minimal " msgstr "ํosta " -#: ../syntax.c:3503 msgid "maximal " msgstr "uasta " -#: ../syntax.c:3513 msgid "; match " msgstr "; meaitseแil " -#: ../syntax.c:3515 msgid " line breaks" msgstr " bristeacha lํne" -#: ../syntax.c:4076 msgid "E395: contains argument not accepted here" msgstr "E395: tแ arg๓int ann nach nglactar leis anseo" -#: ../syntax.c:4096 -#, fuzzy msgid "E844: invalid cchar value" -msgstr "E474: Arg๓int neamhbhailํ" +msgstr "E844: luach neamhbhailํ cchar" -#: ../syntax.c:4107 msgid "E393: group[t]here not accepted here" msgstr "E393: nํ ghlactar le group[t]here anseo" -#: ../syntax.c:4126 #, c-format msgid "E394: Didn't find region item for %s" msgstr "E394: Nํor aimsํodh mํr r้igi๚in le haghaidh %s" -#: ../syntax.c:4188 msgid "E397: Filename required" msgstr "E397: Tแ gแ le hainm comhaid" -#: ../syntax.c:4221 -#, fuzzy msgid "E847: Too many syntax includes" -msgstr "E77: An iomarca ainmneacha comhaid" +msgstr "E847: An iomarca comhad comhr้ire in ๚sแid" -#: ../syntax.c:4303 #, c-format msgid "E789: Missing ']': %s" msgstr "E789: ']' ar iarraidh: %s" -#: ../syntax.c:4531 +#, c-format +msgid "E890: trailing char after ']': %s]%s" +msgstr "E890: carachtar tar ้is ']': %s]%s" + #, c-format msgid "E398: Missing '=': %s" msgstr "E398: '=' ar iarraidh: %s" -#: ../syntax.c:4666 #, c-format msgid "E399: Not enough arguments: syntax region %s" msgstr "E399: Nํl go leor arg๓intํ ann: r้igi๚n comhr้ire %s" -#: ../syntax.c:4870 -#, fuzzy msgid "E848: Too many syntax clusters" -msgstr "E391: Nํl a leith้id de mhogall comhr้ire: %s" +msgstr "E848: An iomarca mogall comhr้ire" -#: ../syntax.c:4954 msgid "E400: No cluster specified" msgstr "E400: Nํor sonraํodh mogall" -#. end delimiter not found -#: ../syntax.c:4986 #, c-format msgid "E401: Pattern delimiter not found: %s" msgstr "E401: Teormharc๓ir patr๚in gan aimsi๚: %s" -#: ../syntax.c:5049 #, c-format msgid "E402: Garbage after pattern: %s" msgstr "E402: Dramhaํl i ndiaidh patr๚in: %s" -#: ../syntax.c:5120 msgid "E403: syntax sync: line continuations pattern specified twice" msgstr "E403: comhr้ir sionc: tugadh patr๚n lean๚int lํne faoi dh๓" -#: ../syntax.c:5169 #, c-format msgid "E404: Illegal arguments: %s" msgstr "E404: Arg๓intํ neamhcheadaithe: %s" -#: ../syntax.c:5217 #, c-format msgid "E405: Missing equal sign: %s" msgstr "E405: Sํn chothroime ar iarraidh: %s" -#: ../syntax.c:5222 #, c-format msgid "E406: Empty argument: %s" msgstr "E406: Arg๓int fholamh: %s" -#: ../syntax.c:5240 #, c-format msgid "E407: %s not allowed here" msgstr "E407: nํ cheadaํtear %s anseo" -#: ../syntax.c:5246 #, c-format msgid "E408: %s must be first in contains list" msgstr "E408: nํ folแir %s a thabhairt ar dt๚s sa liosta `contains'" -#: ../syntax.c:5304 #, c-format msgid "E409: Unknown group name: %s" msgstr "E409: Ainm anaithnid gr๚pa: %s" -#: ../syntax.c:5512 #, c-format msgid "E410: Invalid :syntax subcommand: %s" msgstr "E410: Fo-ord๚ neamhbhailํ :syntax: %s" -#: ../syntax.c:5854 msgid "" " TOTAL COUNT MATCH SLOWEST AVERAGE NAME PATTERN" msgstr "" +" IOMLมN LอON MEAITS IS MOILLE MEมN AINM PATRฺN" -#: ../syntax.c:6146 msgid "E679: recursive loop loading syncolor.vim" msgstr "E679: l๚b athch๚rsach agus syncolor.vim แ lucht๚" -#: ../syntax.c:6256 #, c-format msgid "E411: highlight group not found: %s" msgstr "E411: Gr๚pa aibhsithe gan aimsi๚: %s" -#: ../syntax.c:6278 #, c-format msgid "E412: Not enough arguments: \":highlight link %s\"" msgstr "E412: Easpa arg๓intํ: \":highlight link %s\"" -#: ../syntax.c:6284 #, c-format msgid "E413: Too many arguments: \":highlight link %s\"" msgstr "E413: An iomarca arg๓intํ: \":highlight link %s\"" -#: ../syntax.c:6302 msgid "E414: group has settings, highlight link ignored" msgstr "" "E414: tแ socruithe ag an ghr๚pa, ag d้anamh neamhshuim ar nasc aibhsithe" -#: ../syntax.c:6367 #, c-format msgid "E415: unexpected equal sign: %s" msgstr "E415: sํn chothroime gan choinne: %s" -#: ../syntax.c:6395 #, c-format msgid "E416: missing equal sign: %s" msgstr "E416: sํn chothroime ar iarraidh: %s" -#: ../syntax.c:6418 #, c-format msgid "E417: missing argument: %s" msgstr "E417: arg๓int ar iarraidh: %s" -#: ../syntax.c:6446 #, c-format msgid "E418: Illegal value: %s" msgstr "E418: Luach neamhcheadaithe: %s" -#: ../syntax.c:6496 msgid "E419: FG color unknown" msgstr "E419: Dath anaithnid an ch๚lra" -#: ../syntax.c:6504 msgid "E420: BG color unknown" msgstr "E420: Dath anaithnid an tulra" -#: ../syntax.c:6564 #, c-format msgid "E421: Color name or number not recognized: %s" msgstr "E421: Nํor aithnํodh ainm/uimhir an datha: %s" -#: ../syntax.c:6714 #, c-format msgid "E422: terminal code too long: %s" msgstr "E422: c๓d teirmin้il r๓fhada: %s" -#: ../syntax.c:6753 #, c-format msgid "E423: Illegal argument: %s" msgstr "E423: Arg๓int neamhcheadaithe: %s" -#: ../syntax.c:6925 msgid "E424: Too many different highlighting attributes in use" msgstr "E424: An iomarca tr้ithe aibhsithe in ๚sแid" -#: ../syntax.c:7427 msgid "E669: Unprintable character in group name" msgstr "E669: Carachtar neamhghrafach in ainm gr๚pa" -#: ../syntax.c:7434 msgid "W18: Invalid character in group name" msgstr "W18: Carachtar neamhbhailํ in ainm gr๚pa" -#: ../syntax.c:7448 msgid "E849: Too many highlight and syntax groups" -msgstr "" +msgstr "E849: An iomarca gr๚paํ aibhsithe agus comhr้ire" -#: ../tag.c:104 msgid "E555: at bottom of tag stack" msgstr "E555: in ํochtar na cruaiche clibeanna" -#: ../tag.c:105 msgid "E556: at top of tag stack" msgstr "E556: in uachtar na cruaiche clibeanna" -#: ../tag.c:380 msgid "E425: Cannot go before first matching tag" msgstr "E425: Nํ f้idir a dhul roimh an ch้ad chlib chomhoiri๚nach" -#: ../tag.c:504 #, c-format msgid "E426: tag not found: %s" msgstr "E426: clib gan aimsi๚: %s" -#: ../tag.c:528 msgid " # pri kind tag" msgstr " # tos cin clib" -#: ../tag.c:531 msgid "file\n" msgstr "comhad\n" -#: ../tag.c:829 msgid "E427: There is only one matching tag" msgstr "E427: Tแ aon chlib chomhoiri๚nach amhแin" -#: ../tag.c:831 msgid "E428: Cannot go beyond last matching tag" msgstr "E428: Nํ f้idir a dhul thar an chlib chomhoiri๚nach deireanach" -#: ../tag.c:850 #, c-format msgid "File \"%s\" does not exist" msgstr "Nํl a leith้id de chomhad \"%s\" ann" #. Give an indication of the number of matching tags -#: ../tag.c:859 #, c-format msgid "tag %d of %d%s" msgstr "clib %d as %d%s" -#: ../tag.c:862 msgid " or more" msgstr " n๓ os a chionn" -#: ../tag.c:864 msgid " Using tag with different case!" msgstr " Ag ๚sแid clib le cแs eile!" -#: ../tag.c:909 #, c-format msgid "E429: File \"%s\" does not exist" msgstr "E429: Nํl a leith้id de chomhad \"%s\"" #. Highlight title -#: ../tag.c:960 msgid "" "\n" " # TO tag FROM line in file/text" @@ -6041,79 +5686,66 @@ msgstr "" "\n" " # Go clib ำ lํne i gcomhad/t้acs" -#: ../tag.c:1303 #, c-format msgid "Searching tags file %s" msgstr "Comhad clibeanna %s แ chuardach" -#: ../tag.c:1545 +#, c-format +msgid "E430: Tag file path truncated for %s\n" +msgstr "E430: Teascadh conair an chomhaid clibeanna le haghaidh %s\n" + msgid "Ignoring long line in tags file" msgstr "Ag d้anamh neamhaird de lํne fhada sa chomhad clibeanna" -#: ../tag.c:1915 #, c-format msgid "E431: Format error in tags file \"%s\"" msgstr "E431: Earrแid fhormแide i gcomhad clibeanna \"%s\"" -#: ../tag.c:1917 #, c-format -msgid "Before byte %<PRId64>" -msgstr "Roimh bheart %<PRId64>" +msgid "Before byte %ld" +msgstr "Roimh bheart %ld" -#: ../tag.c:1929 #, c-format msgid "E432: Tags file not sorted: %s" msgstr "E432: Comhad clibeanna gan s๓rtแil: %s" #. never opened any tags file -#: ../tag.c:1960 msgid "E433: No tags file" msgstr "E433: Nํl aon chomhad clibeanna" -#: ../tag.c:2536 msgid "E434: Can't find tag pattern" msgstr "E434: Patr๚n clibe gan aimsi๚" -#: ../tag.c:2544 msgid "E435: Couldn't find tag, just guessing!" msgstr "E435: Clib gan aimsi๚, ag tabhairt buille faoi thuairim!" -#: ../tag.c:2797 -#, fuzzy, c-format +#, c-format msgid "Duplicate field name: %s" -msgstr "Clib dh๚blach i %s lํne %d: %s" +msgstr "Ainm r้imse d๚bailte: %s" -#: ../term.c:1442 msgid "' not known. Available builtin terminals are:" msgstr "' anaithnid. Is iad seo na teirmin้il insuite:" -#: ../term.c:1463 msgid "defaulting to '" msgstr "r้amhshocr๚ = '" -#: ../term.c:1731 msgid "E557: Cannot open termcap file" msgstr "E557: Nํ f้idir an comhad termcap a oscailt" -#: ../term.c:1735 msgid "E558: Terminal entry not found in terminfo" msgstr "E558: Iontrแil teirmin้il gan aimsi๚ sa terminfo" -#: ../term.c:1737 msgid "E559: Terminal entry not found in termcap" msgstr "E559: Iontrแil teirmin้il gan aimsi๚ sa termcap" -#: ../term.c:1878 #, c-format msgid "E436: No \"%s\" entry in termcap" msgstr "E436: Nํl aon iontrแil \"%s\" sa termcap" -#: ../term.c:2249 msgid "E437: terminal capability \"cm\" required" msgstr "E437: tแ gแ leis an chumas teirmin้il \"cm\"" #. Highlight title -#: ../term.c:4376 msgid "" "\n" "--- Terminal keys ---" @@ -6121,169 +5753,342 @@ msgstr "" "\n" "--- Eochracha teirmin้il ---" -#: ../ui.c:481 +msgid "Cannot open $VIMRUNTIME/rgb.txt" +msgstr "Nํ f้idir $VIMRUNTIME/rgb.txt a oscailt" + +msgid "new shell started\n" +msgstr "tosaํodh blaosc nua\n" + msgid "Vim: Error reading input, exiting...\n" msgstr "Vim: Earrแid agus an t-inchomhad แ l้amh; ag scor...\n" +msgid "Used CUT_BUFFER0 instead of empty selection" +msgstr "ฺsแideadh CUT_BUFFER0 in ionad roghn๚chแin folaimh" + #. This happens when the FileChangedRO autocommand changes the #. * file in a way it becomes shorter. -#: ../undo.c:379 -#, fuzzy msgid "E881: Line count changed unexpectedly" -msgstr "E787: Athraํodh an maolแn gan choinne" +msgstr "E881: Athraํodh lํon na lํnte gan s๚il leis" + +#. must display the prompt +msgid "No undo possible; continue anyway" +msgstr "Nํ f้idir a cheal๚; lean ar aghaidh mar sin f้in" -#: ../undo.c:627 -#, fuzzy, c-format +#, c-format msgid "E828: Cannot open undo file for writing: %s" -msgstr "E212: Nํ f้idir comhad a oscailt chun scrํobh ann" +msgstr "E828: Nํ f้idir comhad staire a oscailt le scrํobh ann: %s" -#: ../undo.c:717 #, c-format msgid "E825: Corrupted undo file (%s): %s" -msgstr "" +msgstr "E825: Comhad staire truaillithe (%s): %s" -#: ../undo.c:1039 msgid "Cannot write undo file in any directory in 'undodir'" -msgstr "" +msgstr "Nํ f้idir comhad staire a shแbhแil in aon chomhadlann in 'undodir'" -#: ../undo.c:1074 #, c-format msgid "Will not overwrite with undo file, cannot read: %s" -msgstr "" +msgstr "Nํ forscrํobhfar le comhad staire, nํ f้idir ้ a l้amh: %s" -#: ../undo.c:1092 #, c-format msgid "Will not overwrite, this is not an undo file: %s" -msgstr "" +msgstr "Nํ forscrํobhfar ้, nํ comhad staire ้ seo: %s" -#: ../undo.c:1108 msgid "Skipping undo file write, nothing to undo" -msgstr "" +msgstr "Nํ scrํobhfar an comhad staire, nํl aon stair ann" -#: ../undo.c:1121 -#, fuzzy, c-format +#, c-format msgid "Writing undo file: %s" -msgstr "Comhad viminfo \"%s\" แ scrํobh" +msgstr "Comhad staire แ scrํobh: %s" -#: ../undo.c:1213 -#, fuzzy, c-format +#, c-format msgid "E829: write error in undo file: %s" -msgstr "E297: Earrแid sa scrํobh i gcomhad babhtแla" +msgstr "E829: earrแid le linn scrํofa i gcomhad staire: %s" -#: ../undo.c:1280 #, c-format msgid "Not reading undo file, owner differs: %s" -msgstr "" +msgstr "Nํor l้adh an comhad staire; ๚in้ir difri๚il: %s" -#: ../undo.c:1292 -#, fuzzy, c-format +#, c-format msgid "Reading undo file: %s" -msgstr "Comhad focail %s แ l้amh ..." +msgstr "Comhad staire แ l้amh: %s" -#: ../undo.c:1299 -#, fuzzy, c-format +#, c-format msgid "E822: Cannot open undo file for reading: %s" -msgstr "E195: Nํ f้idir an comhad viminfo a oscailt chun l้amh" +msgstr "E822: Nํ f้idir an comhad staire a oscailt lena l้amh: %s" -#: ../undo.c:1308 -#, fuzzy, c-format +#, c-format msgid "E823: Not an undo file: %s" -msgstr "E753: Gan aimsi๚: %s" +msgstr "E823: Nํ comhad staire ้: %s" + +#, c-format +msgid "E832: Non-encrypted file has encrypted undo file: %s" +msgstr "E832: Comhad neamhchriptithe le comhad staire criptithe: %s" -#: ../undo.c:1313 -#, fuzzy, c-format +#, c-format +msgid "E826: Undo file decryption failed: %s" +msgstr "E826: Nํorbh fh้idir an comhad staire a dhํchripti๚: %s" + +#, c-format +msgid "E827: Undo file is encrypted: %s" +msgstr "E827: Tแ an comhad staire criptithe: %s" + +#, c-format msgid "E824: Incompatible undo file: %s" -msgstr "E484: Nํ f้idir comhad %s a oscailt" +msgstr "E824: Comhad staire neamh-chomhoiri๚nach: %s" -#: ../undo.c:1328 msgid "File contents changed, cannot use undo info" -msgstr "" +msgstr "Athraํodh แbhar an chomhaid, nํ f้idir comhad staire a ๚sแid" -#: ../undo.c:1497 -#, fuzzy, c-format +#, c-format msgid "Finished reading undo file %s" -msgstr "deireadh ag foinsi๚ %s" +msgstr "Comhad staire %s l้ite" -#: ../undo.c:1586 ../undo.c:1812 msgid "Already at oldest change" msgstr "Ag an athr๚ is sine cheana" -#: ../undo.c:1597 ../undo.c:1814 msgid "Already at newest change" msgstr "Ag an athr๚ is nuaํ cheana" -#: ../undo.c:1806 -#, fuzzy, c-format -msgid "E830: Undo number %<PRId64> not found" -msgstr "Nํor aimsํodh ceal๚ uimhir a %<PRId64>" +#, c-format +msgid "E830: Undo number %ld not found" +msgstr "E830: Mํr staire %ld gan aimsi๚" -#: ../undo.c:1979 msgid "E438: u_undo: line numbers wrong" msgstr "E438: u_undo: lํne-uimhreacha mํchearta" -#: ../undo.c:2183 msgid "more line" msgstr "lํne eile" -#: ../undo.c:2185 msgid "more lines" msgstr "lํne eile" -#: ../undo.c:2187 msgid "line less" msgstr "lํne nํos l๚" -#: ../undo.c:2189 msgid "fewer lines" msgstr "lํne nํos l๚" -#: ../undo.c:2193 msgid "change" msgstr "athr๚" -#: ../undo.c:2195 msgid "changes" msgstr "athr๚" -#: ../undo.c:2225 #, c-format -msgid "%<PRId64> %s; %s #%<PRId64> %s" -msgstr "%<PRId64> %s; %s #%<PRId64> %s" +msgid "%ld %s; %s #%ld %s" +msgstr "%ld %s; %s #%ld %s" -#: ../undo.c:2228 msgid "before" msgstr "roimh" -#: ../undo.c:2228 msgid "after" msgstr "tar ้is" -#: ../undo.c:2325 msgid "Nothing to undo" msgstr "Nํl faic le ceal๚" -#: ../undo.c:2330 msgid "number changes when saved" -msgstr "" +msgstr "athraํonn an uimhir ag am sแbhแla" -#: ../undo.c:2360 #, c-format -msgid "%<PRId64> seconds ago" -msgstr "%<PRId64> soicind ๓ shin" +msgid "%ld seconds ago" +msgstr "%ld soicind ๓ shin" -#: ../undo.c:2372 msgid "E790: undojoin is not allowed after undo" msgstr "E790: nํ cheadaํtear \"undojoin\" tar ้is \"undo\"" -#: ../undo.c:2466 msgid "E439: undo list corrupt" msgstr "E439: tแ an liosta cealaithe truaillithe" -#: ../undo.c:2495 msgid "E440: undo line missing" msgstr "E440: lํne chealaithe ar iarraidh" -#: ../version.c:600 +#, c-format +msgid "E122: Function %s already exists, add ! to replace it" +msgstr "E122: Tแ feidhm %s ann cheana, cuir ! leis an ord๚ chun ้ a asแiti๚" + +msgid "E717: Dictionary entry already exists" +msgstr "E717: Tแ an iontrแil focl๓ra seo ann cheana" + +msgid "E718: Funcref required" +msgstr "E718: Tแ gแ le Funcref" + +#, c-format +msgid "E130: Unknown function: %s" +msgstr "E130: Feidhm anaithnid: %s" + +#, c-format +msgid "E125: Illegal argument: %s" +msgstr "E125: Arg๓int neamhcheadaithe: %s" + +#, c-format +msgid "E853: Duplicate argument name: %s" +msgstr "E853: Arg๓int dh๚bailte: %s" + +#, c-format +msgid "E740: Too many arguments for function %s" +msgstr "E740: An iomarca arg๓intํ d'fheidhm %s" + +#, c-format +msgid "E116: Invalid arguments for function %s" +msgstr "E116: Arg๓intํ neamhbhailํ d'fheidhm %s" + +msgid "E132: Function call depth is higher than 'maxfuncdepth'" +msgstr "E132: Doimhneacht na nglaonna nํos m๓ nแ 'maxfuncdepth'" + +#, c-format +msgid "calling %s" +msgstr "%s แ glao" + +#, c-format +msgid "%s aborted" +msgstr "%s tobscortha" + +#, c-format +msgid "%s returning #%ld" +msgstr "%s ag aisfhilleadh #%ld" + +#, c-format +msgid "%s returning %s" +msgstr "%s ag aisfhilleadh %s" + +msgid "E699: Too many arguments" +msgstr "E699: An iomarca arg๓intํ" + +#, c-format +msgid "E117: Unknown function: %s" +msgstr "E117: Feidhm anaithnid: %s" + +#, c-format +msgid "E933: Function was deleted: %s" +msgstr "E933: Scriosadh an fheidhm: %s" + +#, c-format +msgid "E119: Not enough arguments for function: %s" +msgstr "E119: Nํl go leor feidhmeanna d'fheidhm: %s" + +#, c-format +msgid "E120: Using <SID> not in a script context: %s" +msgstr "E120: <SID> แ ๚sแid ach gan a bheith i gcomhth้acs scripte: %s" + +#, c-format +msgid "E725: Calling dict function without Dictionary: %s" +msgstr "E725: Feidhm 'dict' แ ghlao gan Focl๓ir: %s" + +msgid "E129: Function name required" +msgstr "E129: Tแ gแ le hainm feidhme" + +#, c-format +msgid "E128: Function name must start with a capital or \"s:\": %s" +msgstr "" +"E128: Caithfidh ceannlitir a bheith ar dt๚s ainm feidhme, n๓ \"s:\": %s" + +#, c-format +msgid "E884: Function name cannot contain a colon: %s" +msgstr "E884: Nํ cheadaํtear idirstad in ainm feidhme: %s" + +#, c-format +msgid "E123: Undefined function: %s" +msgstr "E123: Feidhm gan sainmhํni๚: %s" + +#, c-format +msgid "E124: Missing '(': %s" +msgstr "E124: '(' ar iarraidh: %s" + +msgid "E862: Cannot use g: here" +msgstr "E862: Nํ f้idir g: a ๚sแid anseo" + +#, c-format +msgid "E932: Closure function should not be at top level: %s" +msgstr "E932: Nํ m๓r don chlabhs๚r a bheith ag an mbarrleibh้al: %s" + +msgid "E126: Missing :endfunction" +msgstr "E126: :endfunction ar iarraidh" + +#, c-format +msgid "E707: Function name conflicts with variable: %s" +msgstr "E707: Tagann ainm na feidhme salach ar athr๓g: %s" + +#, c-format +msgid "E127: Cannot redefine function %s: It is in use" +msgstr "" +"E127: Nํ f้idir sainmhํni๚ nua a dh้anamh ar fheidhm %s: In ๚sแid cheana" + +#, c-format +msgid "E746: Function name does not match script file name: %s" +msgstr "" +"E746: Nํl ainm na feidhme comhoiri๚nach le hainm comhaid na scripte: %s" + +#, c-format +msgid "E131: Cannot delete function %s: It is in use" +msgstr "E131: Nํ f้idir feidhm %s a scriosadh: Tแ s้ in ๚sแid faoi lแthair" + +msgid "E133: :return not inside a function" +msgstr "E133: Caithfidh :return a bheith isteach i bhfeidhm" + +#, c-format +msgid "E107: Missing parentheses: %s" +msgstr "E107: L๚ibํnํ ar iarraidh: %s" + +msgid "" +"\n" +"MS-Windows 64-bit GUI version" +msgstr "" +"\n" +"Leagan GUI 64 giotแn MS-Windows" + +msgid "" +"\n" +"MS-Windows 32-bit GUI version" +msgstr "" +"\n" +"Leagan GUI 32 giotแn MS-Windows" + +msgid " with OLE support" +msgstr " le tacaํocht OLE" + +msgid "" +"\n" +"MS-Windows 64-bit console version" +msgstr "" +"\n" +"Leagan cons๓il 64 giotแn MS-Windows" + +msgid "" +"\n" +"MS-Windows 32-bit console version" +msgstr "" +"\n" +"Leagan cons๓il 32 giotแn MS-Windows" + +msgid "" +"\n" +"MacOS X (unix) version" +msgstr "" +"\n" +"Leagan MacOS X (unix)" + +msgid "" +"\n" +"MacOS X version" +msgstr "" +"\n" +"Leagan MacOS X" + +msgid "" +"\n" +"MacOS version" +msgstr "" +"\n" +"Leagan MacOS" + +msgid "" +"\n" +"OpenVMS version" +msgstr "" +"\n" +"Leagan OpenVMS" + msgid "" "\n" "Included patches: " @@ -6291,7 +6096,6 @@ msgstr "" "\n" "Paistํ san แireamh: " -#: ../version.c:627 msgid "" "\n" "Extra patches: " @@ -6299,11 +6103,9 @@ msgstr "" "\n" "Paistํ sa bhreis: " -#: ../version.c:639 ../version.c:864 msgid "Modified by " msgstr "Mionathraithe ag " -#: ../version.c:646 msgid "" "\n" "Compiled " @@ -6312,11 +6114,9 @@ msgstr "" "Tiomsaithe " # with "Tiomsaithe" -#: ../version.c:649 msgid "by " msgstr "ag " -#: ../version.c:660 msgid "" "\n" "Huge version " @@ -6324,656 +6124,952 @@ msgstr "" "\n" "Leagan ollmh๓r " -#: ../version.c:661 +msgid "" +"\n" +"Big version " +msgstr "" +"\n" +"Leagan m๓r " + +msgid "" +"\n" +"Normal version " +msgstr "" +"\n" +"Leagan coitianta " + +msgid "" +"\n" +"Small version " +msgstr "" +"\n" +"Leagan beag " + +msgid "" +"\n" +"Tiny version " +msgstr "" +"\n" +"Leagan beag bํdeach " + msgid "without GUI." msgstr "gan GUI." -#: ../version.c:662 +msgid "with GTK3 GUI." +msgstr "le GUI GTK3." + +msgid "with GTK2-GNOME GUI." +msgstr "le GUI GTK2-GNOME." + +msgid "with GTK2 GUI." +msgstr "le GUI GTK2." + +msgid "with X11-Motif GUI." +msgstr "le GUI X11-Motif." + +msgid "with X11-neXtaw GUI." +msgstr "le GUI X11-neXtaw." + +msgid "with X11-Athena GUI." +msgstr "le GUI X11-Athena." + +msgid "with Photon GUI." +msgstr "le GUI Photon." + +msgid "with GUI." +msgstr "le GUI." + +msgid "with Carbon GUI." +msgstr "le GUI Carbon." + +msgid "with Cocoa GUI." +msgstr "le GUI Cocoa." + +msgid "with (classic) GUI." +msgstr "le GUI (clasaiceach)." + msgid " Features included (+) or not (-):\n" msgstr " Gn้ithe san แireamh (+) n๓ nach bhfuil (-):\n" -#: ../version.c:667 msgid " system vimrc file: \"" msgstr " comhad vimrc an ch๓rais: \"" -#: ../version.c:672 msgid " user vimrc file: \"" msgstr " comhad vimrc ๚sแideora: \"" -#: ../version.c:677 msgid " 2nd user vimrc file: \"" msgstr " dara comhad vimrc ๚sแideora: \"" -#: ../version.c:682 msgid " 3rd user vimrc file: \"" msgstr " trํ๚ comhad vimrc ๚sแideora: \"" -#: ../version.c:687 msgid " user exrc file: \"" msgstr " comhad exrc ๚sแideora: \"" -#: ../version.c:692 msgid " 2nd user exrc file: \"" msgstr " dara comhad ๚sแideora exrc: \"" -#: ../version.c:699 +msgid " system gvimrc file: \"" +msgstr " comhad gvimrc c๓rais: \"" + +msgid " user gvimrc file: \"" +msgstr " comhad gvimrc ๚sแideora: \"" + +msgid "2nd user gvimrc file: \"" +msgstr "dara comhad gvimrc ๚sแideora: \"" + +msgid "3rd user gvimrc file: \"" +msgstr "trํ๚ comhad gvimrc ๚sแideora: \"" + +msgid " defaults file: \"" +msgstr " comhad na r้amhshocruithe: \"" + +msgid " system menu file: \"" +msgstr " comhad roghchlแir an ch๓rais: \"" + msgid " fall-back for $VIM: \"" msgstr " rogha thแnaisteach do $VIM: \"" -#: ../version.c:705 msgid " f-b for $VIMRUNTIME: \"" msgstr " f-b do $VIMRUNTIME: \"" -#: ../version.c:709 msgid "Compilation: " msgstr "Tioms๚: " -#: ../version.c:712 +msgid "Compiler: " +msgstr "Tiomsaitheoir: " + msgid "Linking: " msgstr "Nascแil: " -#: ../version.c:717 msgid " DEBUG BUILD" msgstr " LEAGAN DอFHABHTAITHE" -#: ../version.c:767 msgid "VIM - Vi IMproved" msgstr "VIM - Vi IMproved" -#: ../version.c:769 msgid "version " msgstr "leagan " -#: ../version.c:770 msgid "by Bram Moolenaar et al." msgstr "le Bram Moolenaar et al." -#: ../version.c:774 msgid "Vim is open source and freely distributable" msgstr "Is saorbhogearra ้ Vim" -#: ../version.c:776 msgid "Help poor children in Uganda!" msgstr "Tabhair cabhair do phแistํ bochta in Uganda!" -#: ../version.c:777 msgid "type :help iccf<Enter> for information " msgstr "cl๓scrํobh :help iccf<Enter> chun eolas a fhแil " -#: ../version.c:779 msgid "type :q<Enter> to exit " msgstr "cl๓scrํobh :q<Enter> chun scoir " -#: ../version.c:780 msgid "type :help<Enter> or <F1> for on-line help" msgstr "cl๓scrํobh :help<Enter> n๓ <F1> le haghaidh cabhrach ar lํne" -#: ../version.c:781 -msgid "type :help version7<Enter> for version info" -msgstr "cl๓scrํobh :help version7<Enter> le haghaidh eolais faoin leagan" +msgid "type :help version8<Enter> for version info" +msgstr "cl๓scrํobh :help version8<Enter> le haghaidh eolais faoin leagan" -#: ../version.c:784 msgid "Running in Vi compatible mode" msgstr "Sa mh๓d comhoiri๚nachta Vi" -#: ../version.c:785 msgid "type :set nocp<Enter> for Vim defaults" msgstr "" "cl๓scrํobh :set nocp<Enter> chun na r้amhshocruithe Vim a thaispeแint" -#: ../version.c:786 msgid "type :help cp-default<Enter> for info on this" msgstr "" "cl๓scrํobh :help cp-default<Enter> chun nํos m๓ eolas faoi seo a fhแil" -#: ../version.c:827 +# don't see where to localize "Help->Orphans"? --kps +msgid "menu Help->Orphans for information " +msgstr "roghchlแr Help->Orphans chun eolas a fhแil " + +msgid "Running modeless, typed text is inserted" +msgstr "ม rith gan mh๓id, ag ionsแ an t้acs atแ iontrแilte" + +# same problem --kps +msgid "menu Edit->Global Settings->Toggle Insert Mode " +msgstr "roghchlแr Edit->Global Settings->Toggle Insert Mode " + +msgid " for two modes " +msgstr " do dhแ mh๓d " + +# same problem --kps +msgid "menu Edit->Global Settings->Toggle Vi Compatible" +msgstr "roghchlแr Edit->Global Settings->Toggle Vi Compatible" + +msgid " for Vim defaults " +msgstr " le haghaidh r้amhshocruithe Vim " + msgid "Sponsor Vim development!" msgstr "Bํ i d'urraitheoir Vim!" -#: ../version.c:828 msgid "Become a registered Vim user!" msgstr "Bํ i d'๚sแideoir clแraithe Vim!" -#: ../version.c:831 msgid "type :help sponsor<Enter> for information " msgstr "cl๓scrํobh :help sponsor<Enter> chun eolas a fhแil " -#: ../version.c:832 msgid "type :help register<Enter> for information " msgstr "cl๓scrํobh :help register<Enter> chun eolas a fhแil " -#: ../version.c:834 msgid "menu Help->Sponsor/Register for information " msgstr "roghchlแr Help->Sponsor/Register chun eolas a fhแil " -#: ../window.c:119 msgid "Already only one window" msgstr "Nํl ach aon fhuinneog amhแin ann cheana" -#: ../window.c:224 msgid "E441: There is no preview window" msgstr "E441: Nํl aon fhuinneog r้amhamhairc ann" -#: ../window.c:559 msgid "E442: Can't split topleft and botright at the same time" msgstr "E442: Nํ f้idir a scoilteadh topleft agus botright san am c้anna" -#: ../window.c:1228 msgid "E443: Cannot rotate when another window is split" msgstr "E443: Nํ f้idir rothl๚ nuair atแ fuinneog eile scoilte" -#: ../window.c:1803 msgid "E444: Cannot close last window" msgstr "E444: Nํ f้idir an fhuinneog dheiridh a dh๚nadh" -#: ../window.c:1810 msgid "E813: Cannot close autocmd window" msgstr "E813: Nํ f้idir fuinneog autocmd a dh๚nadh" -#: ../window.c:1814 msgid "E814: Cannot close window, only autocmd window would remain" msgstr "" "E814: Nํ f้idir an fhuinneog a dh๚nadh, nํ bheadh ach fuinneog autocmd fแgtha" -#: ../window.c:2717 msgid "E445: Other window contains changes" msgstr "E445: Tแ athruithe ann san fhuinneog eile" -#: ../window.c:4805 msgid "E446: No file name under cursor" msgstr "E446: Nํl ainm comhaid faoin ch๚rs๓ir" -#~ msgid "Patch file" -#~ msgstr "Comhad paiste" +#, c-format +msgid "E447: Can't find file \"%s\" in path" +msgstr "E447: Nํl aon fhแil ar chomhad \"%s\" sa chonair" -#~ msgid "" -#~ "&OK\n" -#~ "&Cancel" -#~ msgstr "" -#~ "&OK\n" -#~ "&Cealaigh" +#, c-format +msgid "E799: Invalid ID: %ld (must be greater than or equal to 1)" +msgstr "E799: Aitheantas neamhbhailํ: %ld (nํ m๓r d๓ a bheith >= 1)" -#~ msgid "E240: No connection to Vim server" -#~ msgstr "E240: Nํl aon nasc le freastalaํ Vim" +#, c-format +msgid "E801: ID already taken: %ld" +msgstr "E801: Aitheantas in ๚sแid cheana: %ld" -#~ msgid "E241: Unable to send to %s" -#~ msgstr "E241: Nํ f้idir aon rud a sheoladh chuig %s" +msgid "List or number required" +msgstr "Tแ gแ le liosta n๓ uimhir" -#~ msgid "E277: Unable to read a server reply" -#~ msgstr "E277: Nํ f้idir freagra ๓n fhreastalaํ a l้amh" +#, c-format +msgid "E802: Invalid ID: %ld (must be greater than or equal to 1)" +msgstr "E802: Aitheantas neamhbhailํ: %ld (nํ m๓r d๓ a bheith >= 1)" -#~ msgid "E258: Unable to send to client" -#~ msgstr "E258: Nํ f้idir aon rud a sheoladh chuig an chliant" +#, c-format +msgid "E803: ID not found: %ld" +msgstr "E803: Aitheantas gan aimsi๚: %ld" -#~ msgid "Save As" -#~ msgstr "Sแbhแil Mar" +#, c-format +msgid "E370: Could not load library %s" +msgstr "E370: Nํorbh fh้idir an leabharlann %s a oscailt" -#~ msgid "Edit File" -#~ msgstr "Cuir Comhad in Eagar" +msgid "Sorry, this command is disabled: the Perl library could not be loaded." +msgstr "" +"Tแ br๓n orm, nํl an t-ord๚ seo le fแil: nํorbh fh้idir an leabharlann Perl a " +"lucht๚." -#~ msgid " (NOT FOUND)" -#~ msgstr " (AR IARRAIDH)" +msgid "E299: Perl evaluation forbidden in sandbox without the Safe module" +msgstr "E299: Nํ cheadaํtear luachแil Perl i mbosca gainimh gan an mod๚l Safe" -#~ msgid "Source Vim script" -#~ msgstr "Foinsigh script Vim" +msgid "Edit with &multiple Vims" +msgstr "Cuir in eagar le Vimeanna io&mad๚la" -#~ msgid "Edit File in new window" -#~ msgstr "Cuir comhad in eagar i bhfuinneog nua" +msgid "Edit with single &Vim" +msgstr "Cuir in eagar le &Vim aonair" -#~ msgid "Append File" -#~ msgstr "Cuir Comhad i nDeireadh" +msgid "Diff with Vim" +msgstr "Diff le Vim" -#~ msgid "Window position: X %d, Y %d" -#~ msgstr "Ionad na fuinneoige: X %d, Y %d" +msgid "Edit with &Vim" +msgstr "Cuir in Eagar le &Vim" -#~ msgid "Save Redirection" -#~ msgstr "Sแbhแil Atreor๚" +#. Now concatenate +msgid "Edit with existing Vim - " +msgstr "Cuir in Eagar le Vim beo - " -#~ msgid "Save View" -#~ msgstr "Sแbhแil an tAmharc" +msgid "Edits the selected file(s) with Vim" +msgstr "Cuir an comhad roghnaithe in eagar le Vim" -#~ msgid "Save Session" -#~ msgstr "Sแbhแil an Seisi๚n" +msgid "Error creating process: Check if gvim is in your path!" +msgstr "" +"Earrแid agus pr๓iseas แ chruth๚: Deimhnigh go bhfuil gvim i do chonair!" -#~ msgid "Save Setup" -#~ msgstr "Sแbhแil an Socr๚" +msgid "gvimext.dll error" +msgstr "earrแid gvimext.dll" -#~ msgid "E809: #< is not available without the +eval feature" -#~ msgstr "E809: nํl #< ar fแil gan ghn้ +eval" +msgid "Path length too long!" +msgstr "Conair r๓fhada!" -#~ msgid "E196: No digraphs in this version" -#~ msgstr "E196: Nํ cheadaํtear d้ghraif sa leagan seo" +msgid "--No lines in buffer--" +msgstr "--Tแ an maolแn folamh--" -#~ msgid "is a device (disabled with 'opendevice' option)" -#~ msgstr "is gl้as ้ seo (dํchumasaithe le rogha 'opendevice')" +#. +#. * The error messages that can be shared are included here. +#. * Excluded are errors that are only used once and debugging messages. +#. +msgid "E470: Command aborted" +msgstr "E470: Ord๚ tobscortha" -#~ msgid "Reading from stdin..." -#~ msgstr "Ag l้amh ๓n ionchur caighdeแnach..." +msgid "E471: Argument required" +msgstr "E471: Tแ gแ le harg๓int" -#~ msgid "[crypted]" -#~ msgstr "[criptithe]" +msgid "E10: \\ should be followed by /, ? or &" +msgstr "E10: Ba ch๓ir /, ? n๓ & a chur i ndiaidh \\" -#~ msgid "NetBeans disallows writes of unmodified buffers" -#~ msgstr "Nํ cheadaํonn NetBeans maolแin gan athr๚ a bheith scrํofa" +msgid "E11: Invalid in command-line window; <CR> executes, CTRL-C quits" +msgstr "" +"E11: Neamhbhailํ i bhfuinneog lํne na n-orduithe; <CR>=rith, CTRL-C=scoir" -#~ msgid "Partial writes disallowed for NetBeans buffers" -#~ msgstr "Nํ cheadaํtear maolแin NetBeans a bheith scrํofa go neamhiomlแn" +msgid "E12: Command not allowed from exrc/vimrc in current dir or tag search" +msgstr "" +"E12: Nํ cheadaํtear ord๚ ๓ exrc/vimrc sa chomhadlann reatha nแ ๓ chuardach " +"clibe" -#~ msgid "writing to device disabled with 'opendevice' option" -#~ msgstr "dํchumasaํodh scrํobh chuig gl้as le rogha 'opendevice'" +msgid "E171: Missing :endif" +msgstr "E171: :endif ar iarraidh" -#~ msgid "E460: The resource fork would be lost (add ! to override)" -#~ msgstr "E460: Chaillfํ an forc acmhainne (cuir ! leis an ord๚ chun sแr๚)" +msgid "E600: Missing :endtry" +msgstr "E600: :endtry ar iarraidh" -#~ msgid "E229: Cannot start the GUI" -#~ msgstr "E229: Nํ f้idir an GUI a chur ag obair" +msgid "E170: Missing :endwhile" +msgstr "E170: :endwhile ar iarraidh" -#~ msgid "E230: Cannot read from \"%s\"" -#~ msgstr "E230: Nํ f้idir l้amh ๓ \"%s\"" +msgid "E170: Missing :endfor" +msgstr "E170: :endfor ar iarraidh" -#~ msgid "E665: Cannot start GUI, no valid font found" -#~ msgstr "" -#~ "E665: Nํ f้idir an GUI a chur ag obair, nํl aon chl๓fhoireann bhailํ ann" +msgid "E588: :endwhile without :while" +msgstr "E588: :endwhile gan :while" -#~ msgid "E231: 'guifontwide' invalid" -#~ msgstr "E231: 'guifontwide' neamhbhailํ" +msgid "E588: :endfor without :for" +msgstr "E588: :endfor gan :for" + +msgid "E13: File exists (add ! to override)" +msgstr "E13: Tแ comhad ann cheana (cuir ! leis an ord๚ chun forscrํobh)" + +msgid "E472: Command failed" +msgstr "E472: Theip ar ord๚" -#~ msgid "E599: Value of 'imactivatekey' is invalid" -#~ msgstr "E599: Luach neamhbhailํ ar 'imactivatekey'" +#, c-format +msgid "E234: Unknown fontset: %s" +msgstr "E234: Tacar cl๓ anaithnid: %s" -#~ msgid "E254: Cannot allocate color %s" -#~ msgstr "E254: Nํ f้idir dath %s a dhแileadh" +#, c-format +msgid "E235: Unknown font: %s" +msgstr "E235: Cl๓fhoireann anaithnid: %s" -#~ msgid "No match at cursor, finding next" -#~ msgstr "Nํl a leith้id ag an ch๚rs๓ir, ag cuardach ar an ch้ad cheann eile" +#, c-format +msgid "E236: Font \"%s\" is not fixed-width" +msgstr "E236: Nํ cl๓ aonleithid ้ \"%s\"" -#~ msgid "<cannot open> " -#~ msgstr "<nํ f้idir a oscailt> " +msgid "E473: Internal error" +msgstr "E473: Earrแid inmheแnach" -#~ msgid "E616: vim_SelFile: can't get font %s" -#~ msgstr "E616: vim_SelFile: nํl aon fhแil ar an chl๓fhoireann %s" +msgid "Interrupted" +msgstr "Idirbhriste" -#~ msgid "E614: vim_SelFile: can't return to current directory" -#~ msgstr "" -#~ "E614: vim_SelFile: nํ f้idir dul ar ais go dtํ an chomhadlann reatha" +msgid "E14: Invalid address" +msgstr "E14: Drochsheoladh" -#~ msgid "Pathname:" -#~ msgstr "Conair:" +msgid "E474: Invalid argument" +msgstr "E474: Arg๓int neamhbhailํ" -#~ msgid "E615: vim_SelFile: can't get current directory" -#~ msgstr "E615: vim_SelFile: nํl an chomhadlann reatha ar fแil" +#, c-format +msgid "E475: Invalid argument: %s" +msgstr "E475: Arg๓int neamhbhailํ: %s" -#~ msgid "OK" -#~ msgstr "OK" +#, c-format +msgid "E15: Invalid expression: %s" +msgstr "E15: Slonn neamhbhailํ: %s" -#~ msgid "Cancel" -#~ msgstr "Cealaigh" +msgid "E16: Invalid range" +msgstr "E16: Raon neamhbhailํ" -#~ msgid "Scrollbar Widget: Could not get geometry of thumb pixmap." -#~ msgstr "" -#~ "Giuirl้id Scrollbharra: Nํ f้idir c้imseata an mhapa picteilํnํ a fhแil." +msgid "E476: Invalid command" +msgstr "E476: Ord๚ neamhbhailํ" -#~ msgid "Vim dialog" -#~ msgstr "Dial๓g Vim" +#, c-format +msgid "E17: \"%s\" is a directory" +msgstr "E17: is comhadlann \"%s\"" -#~ msgid "E232: Cannot create BalloonEval with both message and callback" -#~ msgstr "" -#~ "E232: Nํ f้idir BalloonEval a chruth๚ le teachtaireacht agus aisghlaoch " -#~ "araon" +#, c-format +msgid "E364: Library call failed for \"%s()\"" +msgstr "E364: Theip ar ghlao leabharlainne \"%s()\"" -#~ msgid "Vim dialog..." -#~ msgstr "Dial๓g Vim..." +#, c-format +msgid "E448: Could not load library function %s" +msgstr "E448: Nํ f้idir feidhm %s leabharlainne a lucht๚" -#~ msgid "Input _Methods" -#~ msgstr "_Modhanna ionchuir" +msgid "E19: Mark has invalid line number" +msgstr "E19: Tแ lํne-uimhir neamhbhailํ ag an mharc" -# in OLT --KPS -#~ msgid "VIM - Search and Replace..." -#~ msgstr "VIM - Cuardaigh agus Athchuir..." +msgid "E20: Mark not set" +msgstr "E20: Marc gan socr๚" -#~ msgid "VIM - Search..." -#~ msgstr "VIM - Cuardaigh..." +msgid "E21: Cannot make changes, 'modifiable' is off" +msgstr "" +"E21: Nํ f้idir athruithe a chur i bhfeidhm, nํl an bhratach 'modifiable' " +"socraithe" -#~ msgid "Find what:" -#~ msgstr "Aimsigh:" +msgid "E22: Scripts nested too deep" +msgstr "E22: scripteanna neadaithe r๓dhomhain" -#~ msgid "Replace with:" -#~ msgstr "Le cur in ionad:" +msgid "E23: No alternate file" +msgstr "E23: Nํl aon chomhad malartach" -#~ msgid "Match whole word only" -#~ msgstr "Focal iomlแn amhแin" +msgid "E24: No such abbreviation" +msgstr "E24: Nํl a leith้id de ghiorr๚chแn ann" -#~ msgid "Match case" -#~ msgstr "Meaitseแil an cแs" +msgid "E477: No ! allowed" +msgstr "E477: Nํ cheadaํtear !" -#~ msgid "Direction" -#~ msgstr "Treo" +msgid "E25: GUI cannot be used: Not enabled at compile time" +msgstr "E25: Nํ f้idir an GUI a ๚sแid: Nํor cumasaํodh ้ ag am tiomsaithe" -#~ msgid "Up" -#~ msgstr "Suas" +msgid "E26: Hebrew cannot be used: Not enabled at compile time\n" +msgstr "" +"E26: Nํl tacaํocht Eabhraise ar fแil: Nํor cumasaํodh ้ ag am tiomsaithe\n" -#~ msgid "Down" -#~ msgstr "Sํos" +msgid "E27: Farsi cannot be used: Not enabled at compile time\n" +msgstr "" +"E27: Nํl tacaํocht Pheirsise ar fแil: Nํor cumasaํodh ้ ag am tiomsaithe\n" -#~ msgid "Find Next" -#~ msgstr "An Ch้ad Cheann Eile" +msgid "E800: Arabic cannot be used: Not enabled at compile time\n" +msgstr "" +"E800: Nํl tacaํocht Araibise ar fแil: Nํor cumasaํodh ้ ag am tiomsaithe\n" -#~ msgid "Replace" -#~ msgstr "Ionadaigh" +#, c-format +msgid "E28: No such highlight group name: %s" +msgstr "E28: Nํl a leith้id d'ainm gr๚pa aibhsithe: %s" -#~ msgid "Replace All" -#~ msgstr "Ionadaigh Uile" +msgid "E29: No inserted text yet" +msgstr "E29: Nํl aon t้acs ionsแite go dtํ seo" -#~ msgid "Vim: Received \"die\" request from session manager\n" -#~ msgstr "Vim: Fuarthas iarratas \"die\" ๓ bhainisteoir an tseisi๚in\n" +msgid "E30: No previous command line" +msgstr "E30: Nํl aon lํne na n-orduithe roimhe seo" -#~ msgid "Close" -#~ msgstr "D๚n" +msgid "E31: No such mapping" +msgstr "E31: Nํl a leith้id de mhapแil" -#~ msgid "New tab" -#~ msgstr "Cluaisํn nua" +msgid "E479: No match" +msgstr "E479: Nํl aon rud comhoiri๚nach ann" -#~ msgid "Open Tab..." -#~ msgstr "Oscail Cluaisํn..." +#, c-format +msgid "E480: No match: %s" +msgstr "E480: Nํl aon rud comhoiri๚nach ann: %s" -#~ msgid "Vim: Main window unexpectedly destroyed\n" -#~ msgstr "Vim: Milleadh an prํomhfhuinneog gan choinne\n" +msgid "E32: No file name" +msgstr "E32: Nํl aon ainm comhaid" -#~ msgid "Font Selection" -#~ msgstr "Roghn๚ Cl๓" +msgid "E33: No previous substitute regular expression" +msgstr "E33: Nํl aon slonn ionadaํochta roimhe seo" -#~ msgid "&Filter" -#~ msgstr "&Scagaire" +msgid "E34: No previous command" +msgstr "E34: Nํl aon ord๚ roimhe seo" -#~ msgid "&Cancel" -#~ msgstr "&Cealaigh" +msgid "E35: No previous regular expression" +msgstr "E35: Nํl aon slonn ionadaํochta roimhe seo" -#~ msgid "Directories" -#~ msgstr "Comhadlanna" +msgid "E481: No range allowed" +msgstr "E481: Nํ cheadaํtear raon" -#~ msgid "Filter" -#~ msgstr "Scagaire" +msgid "E36: Not enough room" +msgstr "E36: Nํl slํ a dh๓thain ann" -#~ msgid "&Help" -#~ msgstr "&Cabhair" +#, c-format +msgid "E247: no registered server named \"%s\"" +msgstr "E247: nํl aon fhreastalaํ clแraithe leis an ainm \"%s\"" -#~ msgid "Files" -#~ msgstr "Comhaid" +#, c-format +msgid "E482: Can't create file %s" +msgstr "E482: Nํ f้idir comhad %s a chruth๚" -#~ msgid "&OK" -#~ msgstr "&OK" +msgid "E483: Can't get temp file name" +msgstr "E483: Nํl aon fhแil ar ainm comhaid sealadach" -#~ msgid "Selection" -#~ msgstr "Roghn๚" +#, c-format +msgid "E484: Can't open file %s" +msgstr "E484: Nํ f้idir comhad %s a oscailt" -#~ msgid "Find &Next" -#~ msgstr "An Ch้ad Chea&nn Eile" +#, c-format +msgid "E485: Can't read file %s" +msgstr "E485: Nํ f้idir comhad %s a l้amh" -#~ msgid "&Replace" -#~ msgstr "&Ionadaigh" +msgid "E37: No write since last change (add ! to override)" +msgstr "E37: Tแ athruithe ann gan sแbhแil (cuir ! leis an ord๚ chun sแr๚)" -#~ msgid "Replace &All" -#~ msgstr "Ionadaigh &Uile" +msgid "E37: No write since last change" +msgstr "E37: Gan scrํobh ๓n athr๚ is d้anaํ" -#~ msgid "&Undo" -#~ msgstr "&Cealaigh" +msgid "E38: Null argument" +msgstr "E38: Arg๓int nialasach" -#~ msgid "E671: Cannot find window title \"%s\"" -#~ msgstr "E671: Nํ f้idir teideal na fuinneoige \"%s\" a aimsi๚" +msgid "E39: Number expected" +msgstr "E39: Ag s๚il le huimhir" -#~ msgid "E243: Argument not supported: \"-%s\"; Use the OLE version." -#~ msgstr "E243: Arg๓int gan tacaํocht: \"-%s\"; Bain ๚sแid as an leagan OLE." +#, c-format +msgid "E40: Can't open errorfile %s" +msgstr "E40: Nํ f้idir an comhad earrแide %s a oscailt" -#~ msgid "E672: Unable to open window inside MDI application" -#~ msgstr "E672: Nํ f้idir fuinneog a oscailt isteach i bhfeidhmchlแr MDI" +msgid "E233: cannot open display" +msgstr "E233: nํ f้idir an scแileแn a oscailt" -#~ msgid "Close tab" -#~ msgstr "D๚n cluaisํn" +msgid "E41: Out of memory!" +msgstr "E41: Cuimhne ํdithe!" -#~ msgid "Open tab..." -#~ msgstr "Oscail cluaisํn..." +msgid "Pattern not found" +msgstr "Patr๚n gan aimsi๚" -#~ msgid "Find string (use '\\\\' to find a '\\')" -#~ msgstr "Aimsigh teaghrแn (bain ๚sแid as '\\\\' chun '\\' a aimsi๚)" +#, c-format +msgid "E486: Pattern not found: %s" +msgstr "E486: Patr๚n gan aimsi๚: %s" -#~ msgid "Find & Replace (use '\\\\' to find a '\\')" -#~ msgstr "Aimsigh & Athchuir (๚sแid '\\\\' chun '\\' a aimsi๚)" +msgid "E487: Argument must be positive" +msgstr "E487: Nํ folแir arg๓int dheimhneach" -#~ msgid "Not Used" -#~ msgstr "Gan ฺsแid" +msgid "E459: Cannot go back to previous directory" +msgstr "E459: Nํ f้idir a fhilleadh ar an chomhadlann roimhe seo" -#~ msgid "Directory\t*.nothing\n" -#~ msgstr "Comhadlann\t*.neamhnํ\n" +msgid "E42: No Errors" +msgstr "E42: Nํl Aon Earrแid Ann" -#~ msgid "" -#~ "Vim E458: Cannot allocate colormap entry, some colors may be incorrect" -#~ msgstr "" -#~ "Vim E458: Nํ f้idir iontrแil dathmhapแla a dhแileadh, is f้idir go mbeidh " -#~ "dathanna mํchearta ann" +msgid "E776: No location list" +msgstr "E776: Gan liosta suํomh" -#~ msgid "E250: Fonts for the following charsets are missing in fontset %s:" -#~ msgstr "" -#~ "E250: Cl๓nna ar iarraidh le haghaidh na dtacar carachtar i dtacar cl๓ %s:" +msgid "E43: Damaged match string" +msgstr "E43: Teaghrแn cuardaigh loite" + +msgid "E44: Corrupted regexp program" +msgstr "E44: Clแr na sloinn ionadaํochta truaillithe" + +msgid "E45: 'readonly' option is set (add ! to override)" +msgstr "E45: tแ an rogha 'readonly' socraithe (cuir ! leis an ord๚ chun sแr๚)" -#~ msgid "E252: Fontset name: %s" -#~ msgstr "E252: Ainm an tacar cl๓: %s" +#, c-format +msgid "E46: Cannot change read-only variable \"%s\"" +msgstr "E46: Nํ f้idir athr๓g inl้ite amhแin \"%s\" a athr๚" -#~ msgid "Font '%s' is not fixed-width" -#~ msgstr "Nํ cl๓ aonleithid ้ '%s'" +#, c-format +msgid "E794: Cannot set variable in the sandbox: \"%s\"" +msgstr "E794: Nํ f้idir athr๓g a shocr๚ sa bhosca gainimh: \"%s\"" + +msgid "E713: Cannot use empty key for Dictionary" +msgstr "E713: Nํ f้idir eochair fholamh a ๚sแid le Focl๓ir" -#~ msgid "E253: Fontset name: %s\n" -#~ msgstr "E253: Ainm an tacar cl๓: %s\n" +msgid "E715: Dictionary required" +msgstr "E715: Tแ gแ le focl๓ir" -#~ msgid "Font0: %s\n" -#~ msgstr "Cl๓0: %s\n" +#, c-format +msgid "E684: list index out of range: %ld" +msgstr "E684: inn้acs liosta as raon: %ld" -#~ msgid "Font1: %s\n" -#~ msgstr "Cl๓1: %s\n" +#, c-format +msgid "E118: Too many arguments for function: %s" +msgstr "E118: An iomarca arg๓intํ d'fheidhm: %s" -#~ msgid "Font%<PRId64> width is not twice that of font0\n" -#~ msgstr "Nํl Cl๓%<PRId64> nํos leithne faoi dh๓ nแ cl๓0\n" +#, c-format +msgid "E716: Key not present in Dictionary: %s" +msgstr "E716: Nํl an eochair seo san Fhocl๓ir: %s" -#~ msgid "Font0 width: %<PRId64>\n" -#~ msgstr "Leithead Cl๓0: %<PRId64>\n" +msgid "E714: List required" +msgstr "E714: Tแ gแ le liosta" -#~ msgid "" -#~ "Font1 width: %<PRId64>\n" -#~ "\n" -#~ msgstr "" -#~ "Leithead Cl๓1: %<PRId64>\n" -#~ "\n" +#, c-format +msgid "E712: Argument of %s must be a List or Dictionary" +msgstr "E712: Caithfidh arg๓int de %s a bheith ina Liosta n๓ Focl๓ir" -#~ msgid "Invalid font specification" -#~ msgstr "Sonr๚ neamhbhailํ cl๓" +msgid "E47: Error while reading errorfile" +msgstr "E47: Earrแid agus comhad earrแide แ l้amh" -#~ msgid "&Dismiss" -#~ msgstr "&Ruaig" +msgid "E48: Not allowed in sandbox" +msgstr "E48: Nํ cheadaํtear ้ seo i mbosca gainimh" -#~ msgid "no specific match" -#~ msgstr "nํl a leith้id ann" +msgid "E523: Not allowed here" +msgstr "E523: Nํ cheadaํtear ้ anseo" -#~ msgid "Vim - Font Selector" -#~ msgstr "Vim - Roghn๚ Cl๓" +msgid "E359: Screen mode setting not supported" +msgstr "E359: Nํ f้idir an m๓d scแileแin a shocr๚" -#~ msgid "Name:" -#~ msgstr "Ainm:" +msgid "E49: Invalid scroll size" +msgstr "E49: M้id neamhbhailํ scrollaithe" -#~ msgid "Show size in Points" -#~ msgstr "Taispeแin m้id (Pointํ)" +msgid "E91: 'shell' option is empty" +msgstr "E91: rogha 'shell' folamh" -#~ msgid "Encoding:" -#~ msgstr "Ionch๓d๚:" +msgid "E255: Couldn't read in sign data!" +msgstr "E255: Nํorbh fh้idir na sonraํ comhartha a l้amh!" -#~ msgid "Font:" -#~ msgstr "Cl๓:" +msgid "E72: Close error on swap file" +msgstr "E72: Earrแid agus comhad babhtแla แ dh๚nadh" -#~ msgid "Style:" -#~ msgstr "Stํl:" +msgid "E73: tag stack empty" +msgstr "E73: tแ cruach na gclibeanna folamh" -#~ msgid "Size:" -#~ msgstr "M้id:" +msgid "E74: Command too complex" +msgstr "E74: Ord๚ r๓chasta" -#~ msgid "E256: Hangul automata ERROR" -#~ msgstr "E256: EARRมID leis na huathoibreแin Hangul" +msgid "E75: Name too long" +msgstr "E75: Ainm r๓fhada" -#~ msgid "E563: stat error" -#~ msgstr "E563: earrแid stat" +msgid "E76: Too many [" +msgstr "E76: an iomarca [" + +msgid "E77: Too many file names" +msgstr "E77: An iomarca ainmneacha comhaid" -#~ msgid "E625: cannot open cscope database: %s" -#~ msgstr "E625: nํ f้idir bunachar sonraํ cscope a oscailt: %s" +msgid "E488: Trailing characters" +msgstr "E488: Carachtair chun deiridh" -#~ msgid "E626: cannot get cscope database information" -#~ msgstr "E626: nํ f้idir eolas a fhแil faoin bhunachar sonraํ cscope" +msgid "E78: Unknown mark" +msgstr "E78: Marc anaithnid" -#~ msgid "" -#~ "E815: Sorry, this command is disabled, the MzScheme libraries could not " -#~ "be loaded." -#~ msgstr "" -#~ "E815: Tแ br๓n orm, bhํ an t-ord๚ seo dํchumasaithe, nํorbh fh้idir " -#~ "leabharlanna MzScheme a lucht๚." +msgid "E79: Cannot expand wildcards" +msgstr "E79: Nํ f้idir saor๓ga a leathn๚" -#~ msgid "invalid expression" -#~ msgstr "slonn neamhbhailํ" +msgid "E591: 'winheight' cannot be smaller than 'winminheight'" +msgstr "E591: nํ cheadaํtear 'winheight' a bheith nํos l๚ nแ 'winminheight'" -#~ msgid "expressions disabled at compile time" -#~ msgstr "dํchumasaํodh sloinn ag am an tiomsaithe" +msgid "E592: 'winwidth' cannot be smaller than 'winminwidth'" +msgstr "E592: nํ cheadaํtear 'winwidth' a bheith nํos l๚ nแ 'winminwidth'" -#~ msgid "hidden option" -#~ msgstr "rogha fholaithe" +msgid "E80: Error while writing" +msgstr "E80: Earrแid agus แ scrํobh" -#~ msgid "unknown option" -#~ msgstr "rogha anaithnid" +msgid "Zero count" +msgstr "Nialas" -#~ msgid "window index is out of range" -#~ msgstr "inn้acs fuinneoige as raon" +msgid "E81: Using <SID> not in a script context" +msgstr "E81: <SID> แ ๚sแid nach i gcomhth้acs scripte" -#~ msgid "couldn't open buffer" -#~ msgstr "nํ f้idir maolแn a oscailt" +msgid "E449: Invalid expression received" +msgstr "E449: Fuarthas slonn neamhbhailํ" -#~ msgid "cannot save undo information" -#~ msgstr "nํ f้idir eolas cealaithe a shแbhแil" +msgid "E463: Region is guarded, cannot modify" +msgstr "E463: R้igi๚n cosanta, nํ f้idir ้ a athr๚" -#~ msgid "cannot delete line" -#~ msgstr "nํ f้idir an lํne a scriosadh" +msgid "E744: NetBeans does not allow changes in read-only files" +msgstr "E744: Nํ cheadaํonn NetBeans aon athr๚ i gcomhaid inl้ite amhแin" -#~ msgid "cannot replace line" -#~ msgstr "nํ f้idir an lํne a athchur" +#, c-format +msgid "E685: Internal error: %s" +msgstr "E685: Earrแid inmheแnach: %s" -#~ msgid "cannot insert line" -#~ msgstr "nํ f้idir lํne a ionsแ" +msgid "E363: pattern uses more memory than 'maxmempattern'" +msgstr "E363: ๚sแideann an patr๚n nํos m๓ cuimhne nแ 'maxmempattern'" -#~ msgid "string cannot contain newlines" -#~ msgstr "nํ cheadaํtear carachtair lํne nua sa teaghrแn" +msgid "E749: empty buffer" +msgstr "E749: maolแn folamh" -#~ msgid "Vim error: ~a" -#~ msgstr "earrแid Vim: ~a" +#, c-format +msgid "E86: Buffer %ld does not exist" +msgstr "E86: Nํl a leith้id de mhaolแn %ld" -#~ msgid "Vim error" -#~ msgstr "earrแid Vim" +msgid "E682: Invalid search pattern or delimiter" +msgstr "E682: Patr๚n n๓ teormharc๓ir neamhbhailํ cuardaigh" -#~ msgid "buffer is invalid" -#~ msgstr "maolแn neamhbhailํ" +msgid "E139: File is loaded in another buffer" +msgstr "E139: Tแ an comhad luchtaithe i maolแn eile" -#~ msgid "window is invalid" -#~ msgstr "fuinneog neamhbhailํ" +#, c-format +msgid "E764: Option '%s' is not set" +msgstr "E764: Rogha '%s' gan socr๚" -#~ msgid "linenr out of range" -#~ msgstr "lํne-uimhir as raon" +msgid "E850: Invalid register name" +msgstr "E850: Ainm neamhbhailํ tabhaill" -#~ msgid "not allowed in the Vim sandbox" -#~ msgstr "nํ cheadaํtear ้ seo i mbosca gainimh Vim" +#, c-format +msgid "E919: Directory not found in '%s': \"%s\"" +msgstr "E919: Comhadlann gan aimsi๚ in '%s': \"%s\"" -#~ msgid "" -#~ "E263: Sorry, this command is disabled, the Python library could not be " -#~ "loaded." -#~ msgstr "" -#~ "E263: Tแ br๓n orm, nํl an t-ord๚ seo le fแil, nํorbh fh้idir an " -#~ "leabharlann Python a lucht๚." +msgid "search hit TOP, continuing at BOTTOM" +msgstr "Buaileadh an BARR le linn an chuardaigh, ag lean๚int ag an CHRอOCH" -#~ msgid "E659: Cannot invoke Python recursively" -#~ msgstr "E659: Nํ f้idir Python a rith go hathch๚rsach" +msgid "search hit BOTTOM, continuing at TOP" +msgstr "Buaileadh an BUN le linn an chuardaigh, ag lean๚int ag an BHARR" -#~ msgid "can't delete OutputObject attributes" -#~ msgstr "nํ f้idir tr้ithe OutputObject a scriosadh" +#, c-format +msgid "Need encryption key for \"%s\"" +msgstr "Eochair chripti๚chแin le haghaidh \"%s\" de dhํth" -#~ msgid "softspace must be an integer" -#~ msgstr "caithfidh softspace a bheith ina shlแnuimhir" +msgid "empty keys are not allowed" +msgstr "nํ cheadaํtear eochracha folmha" -#~ msgid "invalid attribute" -#~ msgstr "aitreab๚id neamhbhailํ" +msgid "dictionary is locked" +msgstr "tแ an focl๓ir faoi ghlas" -#~ msgid "writelines() requires list of strings" -#~ msgstr "liosta teaghrแn ag teastแil ๓ writelines()" +msgid "list is locked" +msgstr "tแ an liosta faoi ghlas" -#~ msgid "E264: Python: Error initialising I/O objects" -#~ msgstr "E264: Python: Earrแid agus r้ada I/A แ dt๚s๚" +#, c-format +msgid "failed to add key '%s' to dictionary" +msgstr "nํorbh fh้idir eochair '%s' a chur leis an bhfocl๓ir" -#~ msgid "attempt to refer to deleted buffer" -#~ msgstr "rinneadh iarracht ar mhaolแn scriosta a rochtain" +#, c-format +msgid "index must be int or slice, not %s" +msgstr "nํ m๓r don inn้acs a bheith ina shlแnuimhir n๓ ina shlisne, seachas %s" -#~ msgid "line number out of range" -#~ msgstr "lํne-uimhir as raon" +#, c-format +msgid "expected str() or unicode() instance, but got %s" +msgstr "bhํothas ag s๚il le str() n๓ unicode(), ach fuarthas %s" -#~ msgid "<buffer object (deleted) at %p>" -#~ msgstr "<r้ad maolแin (scriosta) ag %p>" +#, c-format +msgid "expected bytes() or str() instance, but got %s" +msgstr "bhํothas ag s๚il le bytes() n๓ str(), ach fuarthas %s" -#~ msgid "invalid mark name" -#~ msgstr "ainm neamhbhailํ mairc" +#, c-format +msgid "" +"expected int(), long() or something supporting coercing to long(), but got %s" +msgstr "" +"bhํothas ag s๚il le int(), long(), n๓ rud ้igin inathraithe ina long(), ach " +"fuarthas %s" -#~ msgid "no such buffer" -#~ msgstr "nํl a leith้id de mhaolแn ann" +#, c-format +msgid "expected int() or something supporting coercing to int(), but got %s" +msgstr "" +"bhํothas ag s๚il le int() n๓ rud ้igin inathraithe ina int(), ach fuarthas %s" -#~ msgid "attempt to refer to deleted window" -#~ msgstr "rinneadh iarracht ar fhuinneog scriosta a rochtain" +msgid "value is too large to fit into C int type" +msgstr "tแ an luach nํos m๓ nแ athr๓g int sa teanga C" -#~ msgid "readonly attribute" -#~ msgstr "tr้ith inl้ite amhแin" +msgid "value is too small to fit into C int type" +msgstr "tแ an luach nํos l๚ nแ athr๓g int sa teanga C" -#~ msgid "cursor position outside buffer" -#~ msgstr "c๚rs๓ir taobh amuigh den mhaolแn" +msgid "number must be greater than zero" +msgstr "nํ m๓r don uimhir a bheith deimhneach" -#~ msgid "<window object (deleted) at %p>" -#~ msgstr "<r้ad fuinneoige (scriosta) ag %p>" +msgid "number must be greater or equal to zero" +msgstr "nํ m๓r don uimhir a bheith >= 0" -#~ msgid "<window object (unknown) at %p>" -#~ msgstr "<r้ad fuinneoige (anaithnid) ag %p>" +msgid "can't delete OutputObject attributes" +msgstr "nํ f้idir tr้ithe OutputObject a scriosadh" -#~ msgid "<window %d>" -#~ msgstr "<fuinneog %d>" +#, c-format +msgid "invalid attribute: %s" +msgstr "aitreab๚id neamhbhailํ: %s" -#~ msgid "no such window" -#~ msgstr "nํl a leith้id d'fhuinneog ann" +msgid "E264: Python: Error initialising I/O objects" +msgstr "E264: Python: Earrแid agus r้ada I/A แ dt๚s๚" -#~ msgid "E265: $_ must be an instance of String" -#~ msgstr "E265: caithfidh $_ a bheith cineแl Teaghrแin" +msgid "failed to change directory" +msgstr "nํorbh fh้idir an chomhadlann a athr๚" -#~ msgid "" -#~ "E266: Sorry, this command is disabled, the Ruby library could not be " -#~ "loaded." -#~ msgstr "" -#~ "E266: Tแ br๓n orm, nํl an t-ord๚ seo le fแil, nํorbh fh้idir an " -#~ "leabharlann Ruby a lucht๚." +#, c-format +msgid "expected 3-tuple as imp.find_module() result, but got %s" +msgstr "" +"bhํothas ag s๚il le 3-chodach mar thoradh ar imp.find_module(), ach fuarthas " +"%s" + +#, c-format +msgid "expected 3-tuple as imp.find_module() result, but got tuple of size %d" +msgstr "" +"bhํothas ag s๚il le 3-chodach mar thoradh ar imp.find_module(), ach fuarthas " +"%d-chodach" + +msgid "internal error: imp.find_module returned tuple with NULL" +msgstr "earrแid inmheแnach: fuarthas codach NULL ar ais ๓ imp.find_module" + +msgid "cannot delete vim.Dictionary attributes" +msgstr "nํ f้idir tr้ithe vim.Dictionary a scriosadh" + +msgid "cannot modify fixed dictionary" +msgstr "nํ f้idir focl๓ir socraithe a athr๚" + +#, c-format +msgid "cannot set attribute %s" +msgstr "nํ f้idir tr้ith %s a shocr๚" + +msgid "hashtab changed during iteration" +msgstr "athraํodh an haistแb le linn atriallta" + +#, c-format +msgid "expected sequence element of size 2, but got sequence of size %d" +msgstr "bhํothas ag s๚il le heilimint de mh้id 2, ach fuarthas m้id %d" + +msgid "list constructor does not accept keyword arguments" +msgstr "nํ ghlacann cruthaitheoir an liosta le harg๓intํ eochairfhocail" + +msgid "list index out of range" +msgstr "inn้acs liosta as raon" + +#. No more suitable format specifications in python-2.3 +#, c-format +msgid "internal error: failed to get vim list item %d" +msgstr "earrแid inmheแnach: nํl aon fhแil ar mhํr %d sa liosta vim" -#~ msgid "E267: unexpected return" -#~ msgstr "E267: \"return\" gan choinne" +msgid "slice step cannot be zero" +msgstr "nํ cheadaํtear slisne le c้im 0" -#~ msgid "E268: unexpected next" -#~ msgstr "E268: \"next\" gan choinne" +#, c-format +msgid "attempt to assign sequence of size greater than %d to extended slice" +msgstr "iarracht ar sheicheamh nํos m๓ nแ %d a shannadh do shlisne fadaithe" + +#, c-format +msgid "internal error: no vim list item %d" +msgstr "earrแid inmheแnach: nํl aon mhํr %d sa liosta vim" + +msgid "internal error: not enough list items" +msgstr "earrแid inmheแnach: nํl go leor mํreanna liosta ann" + +msgid "internal error: failed to add item to list" +msgstr "earrแid inmheแnach: nํorbh fh้idir mํr a chur leis an liosta" -#~ msgid "E269: unexpected break" -#~ msgstr "E269: \"break\" gan choinne" +#, c-format +msgid "attempt to assign sequence of size %d to extended slice of size %d" +msgstr "iarracht ar sheicheamh de mh้id %d a shannadh do shlisne de mh้id %d" + +msgid "failed to add item to list" +msgstr "nํorbh fh้idir mํr a chur leis an liosta" -#~ msgid "E270: unexpected redo" -#~ msgstr "E270: \"redo\" gan choinne" +msgid "cannot delete vim.List attributes" +msgstr "nํ f้idir tr้ithe vim.List a scriosadh" -#~ msgid "E271: retry outside of rescue clause" -#~ msgstr "E271: \"retry\" taobh amuigh de chlแsal tarrthแla" +msgid "cannot modify fixed list" +msgstr "nํ f้idir liosta socraithe a athr๚" -#~ msgid "E272: unhandled exception" -#~ msgstr "E272: eisceacht gan lแimhseแil" +#, c-format +msgid "unnamed function %s does not exist" +msgstr "nํl feidhm %s gan ainm ann" + +#, c-format +msgid "function %s does not exist" +msgstr "nํl feidhm %s ann" -#~ msgid "E273: unknown longjmp status %d" -#~ msgstr "E273: stแdas anaithnid longjmp %d" +#, c-format +msgid "failed to run function %s" +msgstr "nํorbh fh้idir feidhm %s a rith" + +msgid "unable to get option value" +msgstr "nํ f้idir luach na rogha a fhแil" + +msgid "internal error: unknown option type" +msgstr "earrแid inmheแnach: cineแl rogha anaithnid" + +msgid "problem while switching windows" +msgstr "tharla earrแid agus an fhuinneog แ hathr๚" + +#, c-format +msgid "unable to unset global option %s" +msgstr "nํ f้idir rogha chomhchoiteann %s a dhํshocr๚" + +#, c-format +msgid "unable to unset option %s which does not have global value" +msgstr "nํ f้idir rogha %s gan luach comhchoiteann a dhํshocr๚" + +msgid "attempt to refer to deleted tab page" +msgstr "tagairt d้anta do leathanach cluaisํnํ scriosta" + +msgid "no such tab page" +msgstr "nํl a leith้id de leathanach cluaisํnํ ann" + +msgid "attempt to refer to deleted window" +msgstr "rinneadh iarracht ar fhuinneog scriosta a rochtain" + +msgid "readonly attribute: buffer" +msgstr "tr้ith inl้ite amhแin: maolแn" + +msgid "cursor position outside buffer" +msgstr "c๚rs๓ir taobh amuigh den mhaolแn" + +msgid "no such window" +msgstr "nํl a leith้id d'fhuinneog ann" + +msgid "attempt to refer to deleted buffer" +msgstr "rinneadh iarracht ar mhaolแn scriosta a rochtain" + +msgid "failed to rename buffer" +msgstr "nํorbh fh้idir ainm nua a chur ar an maolแn" + +msgid "mark name must be a single character" +msgstr "nํ cheadaํtear ach carachtar amhแin in ainm an mhairc" + +#, c-format +msgid "expected vim.Buffer object, but got %s" +msgstr "bhํothas ag s๚il le r้ad vim.Buffer, ach fuarthas %s" + +#, c-format +msgid "failed to switch to buffer %d" +msgstr "nํorbh fh้idir athr๚ go dtํ maolแn a %d" + +#, c-format +msgid "expected vim.Window object, but got %s" +msgstr "bhํothas ag s๚il le r้ad vim.Window, ach fuarthas %s" + +msgid "failed to find window in the current tab page" +msgstr "nํor aimsํodh fuinneog sa leathanach cluaisํnํ reatha" + +msgid "did not switch to the specified window" +msgstr "nํor athraํodh go dtํ an fhuinneog roghnaithe" + +#, c-format +msgid "expected vim.TabPage object, but got %s" +msgstr "bhํothas ag s๚il le r้ad vim.TabPage, ach fuarthas %s" + +msgid "did not switch to the specified tab page" +msgstr "nํor athraํodh go dtํ an leathanach cluaisํnํ roghnaithe" + +msgid "failed to run the code" +msgstr "nํorbh fh้idir an c๓d a chur ar si๚l" + +msgid "E858: Eval did not return a valid python object" +msgstr "E858: Nํ bhfuarthas r้ad bailํ python ar ais ๓ Eval" + +msgid "E859: Failed to convert returned python object to vim value" +msgstr "E859: Nํorbh fh้idir luach vim a dh้anamh as an r้ad python" + +#, c-format +msgid "unable to convert %s to vim dictionary" +msgstr "nํ f้idir focl๓ir vim a dh้anamh as %s" + +#, c-format +msgid "unable to convert %s to vim list" +msgstr "nํ f้idir liosta vim a dh้anamh as %s" + +#, c-format +msgid "unable to convert %s to vim structure" +msgstr "nํ f้idir strucht๚r vim a dh้anamh as %s" + +msgid "internal error: NULL reference passed" +msgstr "earrแid inmheแnach: tagairt NULL seolta" + +msgid "internal error: invalid value type" +msgstr "earrแid inmheแnach: cineแl neamhbhailํ" + +msgid "" +"Failed to set path hook: sys.path_hooks is not a list\n" +"You should now do the following:\n" +"- append vim.path_hook to sys.path_hooks\n" +"- append vim.VIM_SPECIAL_PATH to sys.path\n" +msgstr "" +"Nํorbh fh้idir path_hook a shocr๚: nํ liosta ้ sys.path_hooks\n" +"Ba ch๓ir duit na rudaํ seo a leanas a dh้anamh:\n" +"- cuir vim.path_hook le deireadh sys.path_hooks\n" +"- cuir vim.VIM_SPECIAL_PATH le deireadh sys.path\n" + +msgid "" +"Failed to set path: sys.path is not a list\n" +"You should now append vim.VIM_SPECIAL_PATH to sys.path" +msgstr "" +"Nํorbh fh้idir an chonair a shocr๚: nํ liosta ้ sys.path\n" +"Ba ch๓ir duit vim.VIM_SPECIAL_PATH a cheangal le deireadh sys.path" + +#~ msgid "E693: Can only compare Funcref with Funcref" +#~ msgstr "E693: Is f้idir Funcref a chur i gcomparแid le Funcref eile amhแin" + +#~ msgid "E706: Variable type mismatch for: %s" +#~ msgstr "E706: Mํmheaitseแil idir cineแlacha athr๓ige: %s" + +#~ msgid "%ld characters" +#~ msgstr "%ld carachtar" #~ msgid "Toggle implementation/definition" #~ msgstr "Scorแnaigh feidhmi๚/sainmhํni๚" @@ -7063,255 +7159,112 @@ msgstr "E446: Nํl ainm comhaid faoin ch๚rs๓ir" #~ msgid "Sniff: Error during write. Disconnected" #~ msgstr "Sniff: Earrแid sa scrํobh. Dํnasctha" -#~ msgid "invalid buffer number" -#~ msgstr "uimhir neamhbhailํ mhaolแin" - -#~ msgid "not implemented yet" -#~ msgstr "nํl ar fแil" - -#~ msgid "cannot set line(s)" -#~ msgstr "nํ f้idir lํn(t)e a shocr๚" - -#~ msgid "mark not set" -#~ msgstr "marc gan socr๚" - -#~ msgid "row %d column %d" -#~ msgstr "lํne %d col๚n %d" - -#~ msgid "cannot insert/append line" -#~ msgstr "nํ f้idir lํne a ionsแ/iarcheangal" - -#~ msgid "unknown flag: " -#~ msgstr "bratach anaithnid: " - -#~ msgid "unknown vimOption" -#~ msgstr "vimOption anaithnid" - -#~ msgid "keyboard interrupt" -#~ msgstr "idirbhriseadh m้archlแir" - -#~ msgid "vim error" -#~ msgstr "earrแid vim" - -#~ msgid "cannot create buffer/window command: object is being deleted" -#~ msgstr "nํ f้idir ord๚ maolแin/fuinneoige a chruth๚: r้ad แ scriosadh" - -#~ msgid "" -#~ "cannot register callback command: buffer/window is already being deleted" -#~ msgstr "" -#~ "nํ f้idir ord๚ aisghlaoch a chlแr๚: maolแn/fuinneog แ scriosadh cheana" - -#~ msgid "" -#~ "E280: TCL FATAL ERROR: reflist corrupt!? Please report this to vim-" -#~ "dev@vim.org" -#~ msgstr "" -#~ "E280: EARRมID MHARFACH TCL: liosta truaillithe tagartha!? Seol tuairisc " -#~ "fhabht chuig <vim-dev@vim.org> le do thoil" - -#~ msgid "cannot register callback command: buffer/window reference not found" -#~ msgstr "" -#~ "nํ f้idir ord๚ aisghlaoch a chlแr๚: tagairt mhaolแn/fhuinneoige gan aimsi๚" - -#~ msgid "" -#~ "E571: Sorry, this command is disabled: the Tcl library could not be " -#~ "loaded." -#~ msgstr "" -#~ "E571: Tแ br๓n orm, nํl an t-ord๚ seo le fแil: nํorbh fh้idir an " -#~ "leabharlann Tcl a lucht๚." +#~ msgid " Quit, or continue with caution.\n" +#~ msgstr " Scoir, n๓ lean ar aghaidh go hairdeallach.\n" -#~ msgid "" -#~ "E281: TCL ERROR: exit code is not int!? Please report this to vim-dev@vim." -#~ "org" -#~ msgstr "" -#~ "E281: EARRมID TCL: nํl an c๓d scortha ina shlแnuimhir!? Seol tuairisc " -#~ "fhabht chuig <vim-dev@vim.org> le do thoil" - -#~ msgid "E572: exit code %d" -#~ msgstr "E572: c๓d scortha %d" +#~ msgid "Cannot connect to Netbeans #2" +#~ msgstr "Nํ f้idir nascadh le Netbeans #2" -#~ msgid "cannot get line" -#~ msgstr "nํ f้idir an lํne a fhแil" +#~ msgid "read from Netbeans socket" +#~ msgstr "l้adh ๓ shoic้ad Netbeans" -#~ msgid "Unable to register a command server name" -#~ msgstr "Nํ f้idir ainm fhreastalaํ ordaithe a chlแr๚" +#~ msgid "'columns' is not 80, cannot execute external commands" +#~ msgstr "nํ 80 ้ 'columns', nํ f้idir orduithe seachtracha a rith" -#~ msgid "E248: Failed to send command to the destination program" -#~ msgstr "E248: Theip ar sheoladh ord๚ chuig an sprioc-chlแr" +#~ msgid "Could not set security context " +#~ msgstr "Nํorbh fh้idir comhth้acs slแndแla a shocr๚ " -#~ msgid "E573: Invalid server id used: %s" -#~ msgstr "E573: Aitheantas neamhbhailํ freastalaํ in ๚sแid: %s" +#~ msgid " for " +#~ msgstr " le haghaidh " -#~ msgid "E251: VIM instance registry property is badly formed. Deleted!" -#~ msgstr "E251: Airํ mํchumtha sa chlแrlann แisc VIM. Scriosta!" +#~ msgid "Could not get security context " +#~ msgstr "Nํorbh fh้idir comhth้acs slแndแla a fhแil " -#~ msgid "This Vim was not compiled with the diff feature." -#~ msgstr "Nํor tiomsaํodh an leagan Vim seo le `diff' ar fแil." +#~ msgid ". Removing it!\n" +#~ msgstr ". ม scriosadh!\n" -#~ msgid "'-nb' cannot be used: not enabled at compile time\n" -#~ msgstr "Nํ f้idir '-nb' a ๚sแid: nํor cumasaํodh ้ ag am tiomsaithe\n" +#~ msgid " (lang)" +#~ msgstr " (teanga)" -#~ msgid "Vim: Error: Failure to start gvim from NetBeans\n" -#~ msgstr "Vim: Earrแid: Theip ar thos๚ gvim ๓ NetBeans\n" +#~ msgid "E759: Format error in spell file" +#~ msgstr "E759: Earrแid fhormแide i gcomhad litrithe" #~ msgid "" #~ "\n" -#~ "Where case is ignored prepend / to make flag upper case" +#~ "MS-Windows 16/32-bit GUI version" #~ msgstr "" #~ "\n" -#~ "Nuair nach cแsํogair ้, cuir '/' ag tosach na brataํ chun ํ a chur sa " -#~ "chแs uachtair" - -#~ msgid "-register\t\tRegister this gvim for OLE" -#~ msgstr "-register\t\tClแraigh an gvim seo le haghaidh OLE" - -#~ msgid "-unregister\t\tUnregister gvim for OLE" -#~ msgstr "-unregister\t\tDํchlแraigh an gvim seo le haghaidh OLE" - -#~ msgid "-g\t\t\tRun using GUI (like \"gvim\")" -#~ msgstr "-g\t\t\tRith agus ๚sแid an GUI (mar \"gvim\")" - -#~ msgid "-f or --nofork\tForeground: Don't fork when starting GUI" -#~ msgstr "-f n๓ --nofork\tTulra: Nแ d้an forc agus an GUI แ thos๚" - -#~ msgid "-f\t\t\tDon't use newcli to open window" -#~ msgstr "-f\t\t\tNแ h๚sแid newcli chun fuinneog a oscailt" - -#~ msgid "-dev <device>\t\tUse <device> for I/O" -#~ msgstr "-dev <gl้as>\t\tBain ๚sแid as <gl้as> do I/A" - -#~ msgid "-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc" -#~ msgstr "-U <gvimrc>\t\tBain ๚sแid as <gvimrc> in ionad aon .gvimrc" - -#~ msgid "-x\t\t\tEdit encrypted files" -#~ msgstr "-x\t\t\tCuir comhaid chriptithe in eagar" - -#~ msgid "-display <display>\tConnect vim to this particular X-server" -#~ msgstr "-display <freastalaํ>\tNasc vim leis an bhfreastalaํ-X seo" - -#~ msgid "-X\t\t\tDo not connect to X server" -#~ msgstr "-X\t\t\tNแ naisc leis an bhfreastalaํ X" - -#~ msgid "--remote <files>\tEdit <files> in a Vim server if possible" -#~ msgstr "" -#~ "--remote <comhaid>\tCuir <comhaid> in eagar le freastalaํ Vim mแs f้idir" - -#~ msgid "--remote-silent <files> Same, don't complain if there is no server" -#~ msgstr "" -#~ "--remote-silent <comhaid> Mar an gc้anna, nแ d้an gearแn mura bhfuil " -#~ "freastalaํ ann" - -#~ msgid "" -#~ "--remote-wait <files> As --remote but wait for files to have been edited" -#~ msgstr "" -#~ "--remote-wait <comhaid> Mar --remote ach fan leis na comhaid a bheith " -#~ "curtha in eagar" - -#~ msgid "" -#~ "--remote-wait-silent <files> Same, don't complain if there is no server" -#~ msgstr "" -#~ "--remote-wait-silent <comhaid> Mar an gc้anna, nแ d้an gearแn mura " -#~ "bhfuil freastalaํ ann" - -#~ msgid "" -#~ "--remote-tab[-wait][-silent] <files> As --remote but use tab page per " -#~ "file" -#~ msgstr "" -#~ "--remote-tab[-wait][-silent] <comhaid> Cos๚il le --remote ach oscail " -#~ "cluaisํn do gach comhad" - -#~ msgid "--remote-send <keys>\tSend <keys> to a Vim server and exit" -#~ msgstr "" -#~ "--remote-send <eochracha>\tSeol <eochracha> chuig freastalaํ Vim agus " -#~ "scoir" - -#~ msgid "" -#~ "--remote-expr <expr>\tEvaluate <expr> in a Vim server and print result" -#~ msgstr "" -#~ "--remote-expr <slonn>\tLuachแil <slonn> le freastalaํ Vim agus taispeแin " -#~ "an toradh" - -#~ msgid "--serverlist\t\tList available Vim server names and exit" -#~ msgstr "--serverlist\t\tTaispeแin freastalaithe Vim atแ ar fแil agus scoir" +#~ "Leagan GUI 16/32 giotแn MS-Windows" -#~ msgid "--servername <name>\tSend to/become the Vim server <name>" -#~ msgstr "--servername <ainm>\tSeol chuig/T้igh i do fhreastalaํ Vim <ainm>" +#~ msgid " in Win32s mode" +#~ msgstr " i m๓d Win32s" #~ msgid "" #~ "\n" -#~ "Arguments recognised by gvim (Motif version):\n" +#~ "MS-Windows 16-bit version" #~ msgstr "" #~ "\n" -#~ "Arg๓intํ ar eolas do gvim (leagan Motif):\n" +#~ "Leagan 16 giotแn MS-Windows" #~ msgid "" #~ "\n" -#~ "Arguments recognised by gvim (neXtaw version):\n" +#~ "32-bit MS-DOS version" #~ msgstr "" #~ "\n" -#~ "Arg๓intํ ar eolas do gvim (leagan neXtaw):\n" +#~ "Leagan 32 giotแn MS-DOS" #~ msgid "" #~ "\n" -#~ "Arguments recognised by gvim (Athena version):\n" +#~ "16-bit MS-DOS version" #~ msgstr "" #~ "\n" -#~ "Arg๓intํ ar eolas do gvim (leagan Athena):\n" +#~ "Leagan 16 giotแn MS-DOS" -#~ msgid "-display <display>\tRun vim on <display>" -#~ msgstr "-display <scแileแn>\tRith vim ar <scแileแn>" +#~ msgid "WARNING: Windows 95/98/ME detected" +#~ msgstr "RABHADH: Braitheadh Windows 95/98/ME" -#~ msgid "-iconic\t\tStart vim iconified" -#~ msgstr "-iconic\t\tTosaigh vim sa mh๓d ํoslaghdaithe" +#~ msgid "type :help windows95<Enter> for info on this" +#~ msgstr "cl๓scrํobh :help windows95<Enter> chun eolas a fhแil " -#~ msgid "-name <name>\t\tUse resource as if vim was <name>" -#~ msgstr "-name <ainm>\t\tฺsแid acmhainn mar a bheadh vim <ainm>" +#~ msgid "function constructor does not accept keyword arguments" +#~ msgstr "nํ ghlacann cruthaitheoir na feidhme le harg๓intํ eochairfhocail" -#~ msgid "\t\t\t (Unimplemented)\n" -#~ msgstr "\t\t\t (Nํl ar fแil)\n" +#~ msgid "Vim dialog..." +#~ msgstr "Dial๓g Vim..." -#~ msgid "-background <color>\tUse <color> for the background (also: -bg)" -#~ msgstr "-background <dath>\tBain ๚sแid as <dath> don ch๚lra (-bg fosta)" +#~ msgid "Font Selection" +#~ msgstr "Roghn๚ Cl๓" -#~ msgid "-foreground <color>\tUse <color> for normal text (also: -fg)" -#~ msgstr "" -#~ "-foreground <dath>\tฺsแid <dath> le haghaidh gnแth-th้acs (fosta: -fg)" +#~ msgid "softspace must be an integer" +#~ msgstr "caithfidh softspace a bheith ina shlแnuimhir" -#~ msgid "-font <font>\t\tUse <font> for normal text (also: -fn)" -#~ msgstr "-font <cl๓>\t\tฺsแid <cl๓> le haghaidh gnแth-th้acs (fosta: -fn)" +#~ msgid "writelines() requires list of strings" +#~ msgstr "liosta teaghrแn ag teastแil ๓ writelines()" -#~ msgid "-boldfont <font>\tUse <font> for bold text" -#~ msgstr "-boldfont <cl๓>\tBain ๚sแid as <cl๓> do chl๓ trom" +#~ msgid "<buffer object (deleted) at %p>" +#~ msgstr "<r้ad maolแin (scriosta) ag %p>" -#~ msgid "-italicfont <font>\tUse <font> for italic text" -#~ msgstr "-italicfont <cl๓>\tฺsแid <cl๓> le haghaidh t้acs iodแlach" +#~ msgid "<window object (deleted) at %p>" +#~ msgstr "<r้ad fuinneoige (scriosta) ag %p>" -#~ msgid "-geometry <geom>\tUse <geom> for initial geometry (also: -geom)" -#~ msgstr "" -#~ "-geometry <geoim>\tฺsแid <geoim> le haghaidh na c้imseatan tosaigh " -#~ "(fosta: -geom)" +#~ msgid "<window object (unknown) at %p>" +#~ msgstr "<r้ad fuinneoige (anaithnid) ag %p>" -#~ msgid "-borderwidth <width>\tUse a border width of <width> (also: -bw)" -#~ msgstr "-borderwidth <leithead>\tSocraigh <leithead> na himlํne (-bw fosta)" +#~ msgid "<window %d>" +#~ msgstr "<fuinneog %d>" #~ msgid "" -#~ "-scrollbarwidth <width> Use a scrollbar width of <width> (also: -sw)" -#~ msgstr "" -#~ "-scrollbarwidth <leithead> Socraigh leithead na scrollbharraํ a bheith " -#~ "<leithead> (fosta: -sw)" - -#~ msgid "-menuheight <height>\tUse a menu bar height of <height> (also: -mh)" +#~ "E281: TCL ERROR: exit code is not int!? Please report this to vim-dev@vim." +#~ "org" #~ msgstr "" -#~ "-menuheight <airde>\tSocraigh airde an bharra roghchlแir a bheith <airde> " -#~ "(fosta: -mh)" - -#~ msgid "-reverse\t\tUse reverse video (also: -rv)" -#~ msgstr "-reverse\t\tฺsแid fํs aisiompaithe (fosta: -rv)" +#~ "E281: EARRมID TCL: nํl an c๓d scortha ina shlแnuimhir!? Seol tuairisc " +#~ "fhabht chuig <vim-dev@vim.org> le do thoil" -#~ msgid "+reverse\t\tDon't use reverse video (also: +rv)" -#~ msgstr "+reverse\t\tNแ h๚sแid fํs aisiompaithe (fosta: +rv)" +#~ msgid "-name <name>\t\tUse resource as if vim was <name>" +#~ msgstr "-name <ainm>\t\tฺsแid acmhainn mar a bheadh vim <ainm>" -#~ msgid "-xrm <resource>\tSet the specified resource" -#~ msgstr "-xrm <acmhainn>\tSocraigh an acmhainn sainithe" +#~ msgid "\t\t\t (Unimplemented)\n" +#~ msgstr "\t\t\t (Nํl ar fแil)\n" #~ msgid "" #~ "\n" @@ -7326,66 +7279,6 @@ msgstr "E446: Nํl ainm comhaid faoin ch๚rs๓ir" #~ msgid "--rows <number>\tInitial height of window in rows" #~ msgstr "--rows <uimhir>\tAirde fhuinneoige i dtosach (r๓nna)" -#~ msgid "" -#~ "\n" -#~ "Arguments recognised by gvim (GTK+ version):\n" -#~ msgstr "" -#~ "\n" -#~ "Arg๓intํ ar eolas do gvim (leagan GTK+):\n" - -#~ msgid "-display <display>\tRun vim on <display> (also: --display)" -#~ msgstr "-display <scแileแn>\tRith vim ar <scแileแn> (fosta: --display)" - -#~ msgid "--role <role>\tSet a unique role to identify the main window" -#~ msgstr "" -#~ "--role <r๓l>\tSocraigh r๓l saini๚il chun an phrํomhfhuinneog a aithint" - -#~ msgid "--socketid <xid>\tOpen Vim inside another GTK widget" -#~ msgstr "--socketid <xid>\tOscail Vim isteach i ngiuirl้id GTK eile" - -#~ msgid "-P <parent title>\tOpen Vim inside parent application" -#~ msgstr "-P <mแthairchlแr>\tOscail Vim isteach sa mhแthairchlแr" - -#~ msgid "--windowid <HWND>\tOpen Vim inside another win32 widget" -#~ msgstr "--windowid <HWND>\tOscail Vim isteach i ngiuirl้id win32 eile" - -#~ msgid "No display" -#~ msgstr "Gan taispeแint" - -#~ msgid ": Send failed.\n" -#~ msgstr ": Theip ar seoladh.\n" - -#~ msgid ": Send failed. Trying to execute locally\n" -#~ msgstr ": Theip ar seoladh. Ag baint triail as go logแnta\n" - -#~ msgid "%d of %d edited" -#~ msgstr "%d as %d d้anta" - -#~ msgid "No display: Send expression failed.\n" -#~ msgstr "Gan taispeแint: Theip ar sheoladh sloinn.\n" - -#~ msgid ": Send expression failed.\n" -#~ msgstr ": Theip ar sheoladh sloinn.\n" - -#~ msgid "E543: Not a valid codepage" -#~ msgstr "E543: Nํ c๓dleathanach bailํ ้" - -#~ msgid "E285: Failed to create input context" -#~ msgstr "E285: Theip ar chruth๚ comhth้acs ionchuir" - -#~ msgid "E286: Failed to open input method" -#~ msgstr "E286: Theip ar oscailt mhodh ionchuir" - -#~ msgid "E287: Warning: Could not set destroy callback to IM" -#~ msgstr "" -#~ "E287: Rabhadh: Nํorbh fh้idir aisghlaoch l้irscriosta a shocr๚ le IM" - -#~ msgid "E288: input method doesn't support any style" -#~ msgstr "E288: Nํ thacaํonn an modh ionchuir aon stํl" - -#~ msgid "E289: input method doesn't support my preedit type" -#~ msgstr "E289: nํ thacaํonn an modh ionchuir mo chineแl r้amheagair" - #~ msgid "E290: over-the-spot style requires fontset" #~ msgstr "E290: tacar cl๓ ag teastแil ๓ stํl thar-an-spota" @@ -7397,197 +7290,15 @@ msgstr "E446: Nํl ainm comhaid faoin ch๚rs๓ir" #~ msgid "E292: Input Method Server is not running" #~ msgstr "E292: Nํl an Freastalaํ Mhodh Ionchuir ag rith" -#~ msgid "" -#~ "\n" -#~ " [not usable with this version of Vim]" -#~ msgstr "" -#~ "\n" -#~ " [nํ in๚sแidte leis an leagan seo Vim]" - -#~ msgid "Tear off this menu" -#~ msgstr "Bain an roghchlแr seo" - -#~ msgid "Select Directory dialog" -#~ msgstr "Dial๓g `Roghnaigh Comhadlann'" - -#~ msgid "Save File dialog" -#~ msgstr "Dial๓g `Sแbhแil Comhad'" - -#~ msgid "Open File dialog" -#~ msgstr "Dial๓g `Oscail Comhad'" - -#~ msgid "E338: Sorry, no file browser in console mode" -#~ msgstr "E338: Nํl brabhsแlaํ comhaid ar fแil sa mh๓d cons๓il" - #~ msgid "Vim: preserving files...\n" #~ msgstr "Vim: comhaid แ gcaomhn๚...\n" #~ msgid "Vim: Finished.\n" #~ msgstr "Vim: Crํochnaithe.\n" -#~ msgid "ERROR: " -#~ msgstr "EARRมID: " - -#~ msgid "" -#~ "\n" -#~ "[bytes] total alloc-freed %<PRIu64>-%<PRIu64>, in use %<PRIu64>, peak use " -#~ "%<PRIu64>\n" -#~ msgstr "" -#~ "\n" -#~ "[beart] iomlแn dแilte-saor %<PRIu64>-%<PRIu64>, in ๚sแid %<PRIu64>, buaic " -#~ "%<PRIu64>\n" - -#~ msgid "" -#~ "[calls] total re/malloc()'s %<PRIu64>, total free()'s %<PRIu64>\n" -#~ "\n" -#~ msgstr "" -#~ "[glaonna] re/malloc(): %<PRIu64>, free(): %<PRIu64>\n" -#~ "\n" - -#~ msgid "E340: Line is becoming too long" -#~ msgstr "E340: Tแ an lํne ag ้irํ r๓fhada" - -#~ msgid "E341: Internal error: lalloc(%<PRId64>, )" -#~ msgstr "E341: Earrแid inmheแnach: lalloc(%<PRId64>, )" - -#~ msgid "E547: Illegal mouseshape" -#~ msgstr "E547: Cruth neamhcheadaithe luiche" - -#~ msgid "Enter encryption key: " -#~ msgstr "Iontrแil eochair chripti๚chแin: " - -#~ msgid "Enter same key again: " -#~ msgstr "Iontrแil an eochair arํs: " - -#~ msgid "Keys don't match!" -#~ msgstr "Nํl na heochracha comhoiri๚nach le ch้ile!" - -#~ msgid "Cannot connect to Netbeans #2" -#~ msgstr "Nํ f้idir nascadh le Netbeans #2" - -#~ msgid "Cannot connect to Netbeans" -#~ msgstr "Nํ f้idir nascadh le Netbeans" - -#~ msgid "E668: Wrong access mode for NetBeans connection info file: \"%s\"" -#~ msgstr "" -#~ "E668: M๓d mํcheart rochtana ar an chomhad eolas naisc NetBeans: \"%s\"" - -#~ msgid "read from Netbeans socket" -#~ msgstr "l้adh ๓ shoic้ad Netbeans" - -#~ msgid "E658: NetBeans connection lost for buffer %<PRId64>" -#~ msgstr "E658: Cailleadh nasc NetBeans le haghaidh maolแin %<PRId64>" - #~ msgid "E505: " #~ msgstr "E505: " -#~ msgid "E775: Eval feature not available" -#~ msgstr "E775: Nํl an ghn้ Eval le fแil" - -#~ msgid "freeing %<PRId64> lines" -#~ msgstr "%<PRId64> lํne แ saoradh" - -#~ msgid "E530: Cannot change term in GUI" -#~ msgstr "E530: Nํ f้idir 'term' a athr๚ sa GUI" - -#~ msgid "E531: Use \":gui\" to start the GUI" -#~ msgstr "E531: ฺsแid \":gui\" chun an GUI a chur ag obair" - -#~ msgid "E617: Cannot be changed in the GTK+ 2 GUI" -#~ msgstr "E617: Nํ f้idir ้ a athr๚ sa GUI GTK+ 2" - -#~ msgid "E596: Invalid font(s)" -#~ msgstr "E596: Cl๓(nna) neamhbhailํ" - -#~ msgid "E597: can't select fontset" -#~ msgstr "E597: nํ f้idir tacar cl๓ a roghn๚" - -#~ msgid "E598: Invalid fontset" -#~ msgstr "E598: Tacar cl๓ neamhbhailํ" - -#~ msgid "E533: can't select wide font" -#~ msgstr "E533: nํ f้idir cl๓ leathan a roghn๚" - -#~ msgid "E534: Invalid wide font" -#~ msgstr "E534: Cl๓ leathan neamhbhailํ" - -#~ msgid "E538: No mouse support" -#~ msgstr "E538: Gan tacaํocht luiche" - -#~ msgid "cannot open " -#~ msgstr "nํ f้idir a oscailt: " - -#~ msgid "VIM: Can't open window!\n" -#~ msgstr "VIM: Nํ f้idir fuinneog a oscailt!\n" - -#~ msgid "Need Amigados version 2.04 or later\n" -#~ msgstr "Tแ gแ le Amigados leagan 2.04 n๓ nํos d้anaํ\n" - -#~ msgid "Need %s version %<PRId64>\n" -#~ msgstr "Tแ gแ le %s, leagan %<PRId64>\n" - -#~ msgid "Cannot open NIL:\n" -#~ msgstr "Nํ f้idir NIL a oscailt:\n" - -#~ msgid "Cannot create " -#~ msgstr "Nํ f้idir a chruth๚: " - -#~ msgid "Vim exiting with %d\n" -#~ msgstr "Vim แ scor le stแdas %d\n" - -#~ msgid "cannot change console mode ?!\n" -#~ msgstr "nํ f้idir m๓d cons๓il a athr๚ ?!\n" - -#~ msgid "mch_get_shellsize: not a console??\n" -#~ msgstr "mch_get_shellsize: nํ cons๓l ้ seo??\n" - -#~ msgid "E360: Cannot execute shell with -f option" -#~ msgstr "E360: Nํ f้idir blaosc a rith le rogha -f" - -#~ msgid "Cannot execute " -#~ msgstr "Nํ f้idir blaosc a rith: " - -#~ msgid "shell " -#~ msgstr "blaosc " - -#~ msgid " returned\n" -#~ msgstr " aisfhilleadh\n" - -#~ msgid "ANCHOR_BUF_SIZE too small." -#~ msgstr "ANCHOR_BUF_SIZE r๓bheag." - -#~ msgid "I/O ERROR" -#~ msgstr "EARRมID I/A" - -#~ msgid "Message" -#~ msgstr "Teachtaireacht" - -#~ msgid "'columns' is not 80, cannot execute external commands" -#~ msgstr "nํ 80 ้ 'columns', nํ f้idir orduithe seachtracha a rith" - -#~ msgid "E237: Printer selection failed" -#~ msgstr "E237: Theip ar roghn๚ print้ara" - -#~ msgid "to %s on %s" -#~ msgstr "go %s ar %s" - -#~ msgid "E613: Unknown printer font: %s" -#~ msgstr "E613: Cl๓fhoireann anaithnid print้ara: %s" - -#~ msgid "E238: Print error: %s" -#~ msgstr "E238: Earrแid phriontแla: %s" - -#~ msgid "Printing '%s'" -#~ msgstr "'%s' แ phriontแil" - -#~ msgid "E244: Illegal charset name \"%s\" in font name \"%s\"" -#~ msgstr "" -#~ "E244: Ainm neamhcheadaithe ar thacar carachtar \"%s\" mar phแirt d'ainm " -#~ "cl๓ \"%s\"" - -#~ msgid "E245: Illegal char '%c' in font name \"%s\"" -#~ msgstr "E245: Carachtar neamhcheadaithe '%c' mar phแirt d'ainm cl๓ \"%s\"" - #~ msgid "Vim: Double signal, exiting\n" #~ msgstr "Vim: Comhartha d๚bailte, ag scor\n" @@ -7597,419 +7308,23 @@ msgstr "E446: Nํl ainm comhaid faoin ch๚rs๓ir" #~ msgid "Vim: Caught deadly signal\n" #~ msgstr "Vim: Fuarthas comhartha marfach\n" -#~ msgid "Opening the X display took %<PRId64> msec" -#~ msgstr "Th๓g %<PRId64> ms chun an scแileแn X a oscailt" - -#~ msgid "" -#~ "\n" -#~ "Vim: Got X error\n" -#~ msgstr "" -#~ "\n" -#~ "Vim: Fuarthas earrแid ๓ X\n" - -#~ msgid "Testing the X display failed" -#~ msgstr "Theip ar thแstแil an scแileแin X" - -#~ msgid "Opening the X display timed out" -#~ msgstr "Oscailt an scแileแin X thar am" - -#~ msgid "" -#~ "\n" -#~ "Cannot execute shell sh\n" -#~ msgstr "" -#~ "\n" -#~ "Nํ f้idir an bhlaosc sh a rith\n" - -#~ msgid "" -#~ "\n" -#~ "Cannot create pipes\n" -#~ msgstr "" -#~ "\n" -#~ "Nํ f้idir pํopaํ a chruth๚\n" - -# "fork" not in standard refs/corpus. Maybe want a "gabhl*" word instead? -KPS -#~ msgid "" -#~ "\n" -#~ "Cannot fork\n" -#~ msgstr "" -#~ "\n" -#~ "Nํ f้idir forc a dh้anamh\n" - -#~ msgid "" -#~ "\n" -#~ "Command terminated\n" -#~ msgstr "" -#~ "\n" -#~ "Ord๚ crํochnaithe\n" - -#~ msgid "XSMP lost ICE connection" -#~ msgstr "Chaill XSMP an nasc ICE" - -#~ msgid "Opening the X display failed" -#~ msgstr "Theip ar oscailt an scแileแin X" - -#~ msgid "XSMP handling save-yourself request" -#~ msgstr "Iarratas sแbhแil-do-f้in แ lแimhseแil ag XSMP" - -#~ msgid "XSMP opening connection" -#~ msgstr "Nasc แ oscailt ag XSMP" - -#~ msgid "XSMP ICE connection watch failed" -#~ msgstr "Theip ar fhaire nasc ICE XSMP" - -#~ msgid "XSMP SmcOpenConnection failed: %s" -#~ msgstr "Theip ar XSMP SmcOpenConnection: %s" - -#~ msgid "At line" -#~ msgstr "Ag lํne" - -#~ msgid "Could not load vim32.dll!" -#~ msgstr "Nํorbh fh้idir vim32.dll a lucht๚!" - -#~ msgid "VIM Error" -#~ msgstr "Earrแid VIM" - -#~ msgid "Could not fix up function pointers to the DLL!" -#~ msgstr "Nํorbh fh้idir pointeoirํ feidhme a ch๓iri๚ i gcomhair an DLL!" - -#~ msgid "shell returned %d" -#~ msgstr "d'aisfhill an bhlaosc %d" - -#~ msgid "Vim: Caught %s event\n" -#~ msgstr "Vim: Fuarthas teagmhas %s\n" - -#~ msgid "close" -#~ msgstr "d๚n" - -#~ msgid "logoff" -#~ msgstr "logแil amach" - -#~ msgid "shutdown" -#~ msgstr "m๚chadh" - -#~ msgid "E371: Command not found" -#~ msgstr "E371: Nํ bhfuarthas an t-ord๚" - -#~ msgid "" -#~ "VIMRUN.EXE not found in your $PATH.\n" -#~ "External commands will not pause after completion.\n" -#~ "See :help win32-vimrun for more information." -#~ msgstr "" -#~ "Nํor aimsํodh VIMRUN.EXE i do $PATH.\n" -#~ "Nํ mhoilleoidh orduithe seachtracha agus iad curtha i gcrํch.\n" -#~ "F้ach ar :help win32-vimrun chun nํos m๓ eolas a fhแil." - -#~ msgid "Vim Warning" -#~ msgstr "Rabhadh Vim" - -#~ msgid "Conversion in %s not supported" -#~ msgstr "Tiont๚ i %s gan tacaํocht" - #~ msgid "E396: containedin argument not accepted here" #~ msgstr "E396: nํ ghlactar leis an arg๓int containedin anseo" -#~ msgid "E430: Tag file path truncated for %s\n" -#~ msgstr "E430: Teascadh conair an chomhaid clibeanna le haghaidh %s\n" - -#~ msgid "new shell started\n" -#~ msgstr "tosaํodh blaosc nua\n" - -#~ msgid "Used CUT_BUFFER0 instead of empty selection" -#~ msgstr "ฺsแideadh CUT_BUFFER0 in ionad roghn๚chแin folaimh" - -#~ msgid "No undo possible; continue anyway" -#~ msgstr "Nํ f้idir a cheal๚; lean ar aghaidh mar sin f้in" - # columns? #~ msgid "number changes time" #~ msgstr "uimhir athruithe am" #~ msgid "" #~ "\n" -#~ "MS-Windows 16/32-bit GUI version" -#~ msgstr "" -#~ "\n" -#~ "Leagan GUI 16/32 giotแn MS-Windows" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 64-bit GUI version" -#~ msgstr "" -#~ "\n" -#~ "Leagan GUI 64 giotแn MS-Windows" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 32-bit GUI version" -#~ msgstr "" -#~ "\n" -#~ "Leagan GUI 32 giotแn MS-Windows" - -#~ msgid " in Win32s mode" -#~ msgstr " i m๓d Win32s" - -#~ msgid " with OLE support" -#~ msgstr " le tacaํocht OLE" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 64-bit console version" -#~ msgstr "" -#~ "\n" -#~ "Leagan cons๓il 64 giotแn MS-Windows" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 32-bit console version" -#~ msgstr "" -#~ "\n" -#~ "Leagan cons๓il 32 giotแn MS-Windows" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 16-bit version" -#~ msgstr "" -#~ "\n" -#~ "Leagan 16 giotแn MS-Windows" - -#~ msgid "" -#~ "\n" -#~ "32-bit MS-DOS version" -#~ msgstr "" -#~ "\n" -#~ "Leagan 32 giotแn MS-DOS" - -#~ msgid "" -#~ "\n" -#~ "16-bit MS-DOS version" -#~ msgstr "" -#~ "\n" -#~ "Leagan 16 giotแn MS-DOS" - -#~ msgid "" -#~ "\n" -#~ "MacOS X (unix) version" -#~ msgstr "" -#~ "\n" -#~ "Leagan MacOS X (unix)" - -#~ msgid "" -#~ "\n" -#~ "MacOS X version" -#~ msgstr "" -#~ "\n" -#~ "Leagan MacOS X" - -#~ msgid "" -#~ "\n" -#~ "MacOS version" -#~ msgstr "" -#~ "\n" -#~ "Leagan MacOS" - -#~ msgid "" -#~ "\n" #~ "RISC OS version" #~ msgstr "" #~ "\n" #~ "Leagan RISC OS" -#~ msgid "" -#~ "\n" -#~ "OpenVMS version" -#~ msgstr "" -#~ "\n" -#~ "Leagan OpenVMS" - -#~ msgid "" -#~ "\n" -#~ "Big version " -#~ msgstr "" -#~ "\n" -#~ "Leagan m๓r " - -#~ msgid "" -#~ "\n" -#~ "Normal version " -#~ msgstr "" -#~ "\n" -#~ "Leagan coitianta " - -#~ msgid "" -#~ "\n" -#~ "Small version " -#~ msgstr "" -#~ "\n" -#~ "Leagan beag " - -#~ msgid "" -#~ "\n" -#~ "Tiny version " -#~ msgstr "" -#~ "\n" -#~ "Leagan beag bํdeach " - -#~ msgid "with GTK2-GNOME GUI." -#~ msgstr "le GUI GTK2-GNOME." - #~ msgid "with GTK-GNOME GUI." #~ msgstr "le GUI GTK-GNOME." -#~ msgid "with GTK2 GUI." -#~ msgstr "le GUI GTK2." - -#~ msgid "with GTK GUI." -#~ msgstr "le GUI GTK." - -#~ msgid "with X11-Motif GUI." -#~ msgstr "le GUI X11-Motif." - -#~ msgid "with X11-neXtaw GUI." -#~ msgstr "le GUI X11-neXtaw." - -#~ msgid "with X11-Athena GUI." -#~ msgstr "le GUI X11-Athena." - -#~ msgid "with Photon GUI." -#~ msgstr "le GUI Photon." - -#~ msgid "with GUI." -#~ msgstr "le GUI." - -#~ msgid "with Carbon GUI." -#~ msgstr "le GUI Carbon." - -#~ msgid "with Cocoa GUI." -#~ msgstr "le GUI Cocoa." - -#~ msgid "with (classic) GUI." -#~ msgstr "le GUI (clasaiceach)." - -#~ msgid " system gvimrc file: \"" -#~ msgstr " comhad gvimrc c๓rais: \"" - -#~ msgid " user gvimrc file: \"" -#~ msgstr " comhad gvimrc ๚sแideora: \"" - -#~ msgid "2nd user gvimrc file: \"" -#~ msgstr "dara comhad gvimrc ๚sแideora: \"" - -#~ msgid "3rd user gvimrc file: \"" -#~ msgstr "trํ๚ comhad gvimrc ๚sแideora: \"" - -#~ msgid " system menu file: \"" -#~ msgstr " comhad roghchlแir an ch๓rais: \"" - -#~ msgid "Compiler: " -#~ msgstr "Tiomsaitheoir: " - -# don't see where to localize "Help->Orphans"? --kps -#~ msgid "menu Help->Orphans for information " -#~ msgstr "roghchlแr Help->Orphans chun eolas a fhแil " - -#~ msgid "Running modeless, typed text is inserted" -#~ msgstr "ม rith gan mh๓id, ag ionsแ an t้acs atแ iontrแilte" - -# same problem --kps -#~ msgid "menu Edit->Global Settings->Toggle Insert Mode " -#~ msgstr "roghchlแr Edit->Global Settings->Toggle Insert Mode " - -#~ msgid " for two modes " -#~ msgstr " do dhแ mh๓d " - -# same problem --kps -#~ msgid "menu Edit->Global Settings->Toggle Vi Compatible" -#~ msgstr "roghchlแr Edit->Global Settings->Toggle Vi Compatible" - -#~ msgid " for Vim defaults " -#~ msgstr " le haghaidh r้amhshocruithe Vim " - -#~ msgid "WARNING: Windows 95/98/ME detected" -#~ msgstr "RABHADH: Braitheadh Windows 95/98/ME" - -#~ msgid "type :help windows95<Enter> for info on this" -#~ msgstr "cl๓scrํobh :help windows95<Enter> chun eolas a fhแil " - -#~ msgid "E370: Could not load library %s" -#~ msgstr "E370: Nํorbh fh้idir an leabharlann %s a oscailt" - -#~ msgid "" -#~ "Sorry, this command is disabled: the Perl library could not be loaded." -#~ msgstr "" -#~ "Tแ br๓n orm, nํl an t-ord๚ seo le fแil: nํorbh fh้idir an leabharlann " -#~ "Perl a lucht๚." - -#~ msgid "E299: Perl evaluation forbidden in sandbox without the Safe module" -#~ msgstr "" -#~ "E299: Nํ cheadaํtear luachแil Perl i mbosca gainimh gan an mod๚l Safe" - -#~ msgid "Edit with &multiple Vims" -#~ msgstr "Cuir in eagar le Vimeanna io&mad๚la" - -#~ msgid "Edit with single &Vim" -#~ msgstr "Cuir in eagar le &Vim aonair" - -#~ msgid "Diff with Vim" -#~ msgstr "Diff le Vim" - -#~ msgid "Edit with &Vim" -#~ msgstr "Cuir in Eagar le &Vim" - -#~ msgid "Edit with existing Vim - " -#~ msgstr "Cuir in Eagar le Vim beo - " - -#~ msgid "Edits the selected file(s) with Vim" -#~ msgstr "Cuir an comhad roghnaithe in eagar le Vim" - -#~ msgid "Error creating process: Check if gvim is in your path!" -#~ msgstr "" -#~ "Earrแid agus pr๓iseas แ chruth๚: Deimhnigh go bhfuil gvim i do chonair!" - -#~ msgid "gvimext.dll error" -#~ msgstr "earrแid gvimext.dll" - -#~ msgid "Path length too long!" -#~ msgstr "Conair r๓fhada!" - -#~ msgid "E234: Unknown fontset: %s" -#~ msgstr "E234: Tacar cl๓ anaithnid: %s" - -#~ msgid "E235: Unknown font: %s" -#~ msgstr "E235: Cl๓fhoireann anaithnid: %s" - -#~ msgid "E236: Font \"%s\" is not fixed-width" -#~ msgstr "E236: Nํ cl๓ aonleithid ้ \"%s\"" - -#~ msgid "E448: Could not load library function %s" -#~ msgstr "E448: Nํ f้idir feidhm %s leabharlainne a lucht๚" - -#~ msgid "E26: Hebrew cannot be used: Not enabled at compile time\n" -#~ msgstr "" -#~ "E26: Nํl tacaํocht Eabhraise ar fแil: Nํor cumasaํodh ้ ag am tiomsaithe\n" - -#~ msgid "E27: Farsi cannot be used: Not enabled at compile time\n" -#~ msgstr "" -#~ "E27: Nํl tacaํocht Pheirsise ar fแil: Nํor cumasaํodh ้ ag am tiomsaithe\n" - -#~ msgid "E800: Arabic cannot be used: Not enabled at compile time\n" -#~ msgstr "" -#~ "E800: Nํl tacaํocht Araibise ar fแil: Nํor cumasaํodh ้ ag am tiomsaithe\n" - -#~ msgid "E247: no registered server named \"%s\"" -#~ msgstr "E247: nํl aon fhreastalaํ clแraithe leis an ainm \"%s\"" - -#~ msgid "E233: cannot open display" -#~ msgstr "E233: nํ f้idir an scแileแn a oscailt" - -#~ msgid "E449: Invalid expression received" -#~ msgstr "E449: Fuarthas slonn neamhbhailํ" - -#~ msgid "E463: Region is guarded, cannot modify" -#~ msgstr "E463: R้igi๚n cosanta, nํ f้idir ้ a athr๚" - -#~ msgid "E744: NetBeans does not allow changes in read-only files" -#~ msgstr "E744: Nํ cheadaํonn NetBeans aon athr๚ i gcomhaid inl้ite amhแin" - #~ msgid "E569: maximum number of cscope connections reached" #~ msgstr "E569: nํ cheadaํtear nํos m๓ nแ an lํon uasta nasc cscope" @@ -8070,8 +7385,8 @@ msgstr "E446: Nํl ainm comhaid faoin ch๚rs๓ir" #~ msgstr "" #~ "Nํ m๓r do charachtar a ๚sแidtear ar SLASH a bheith ASCII; i %s lํne %d: %s" -#~ msgid "%<PRId64> changes" -#~ msgstr "%<PRId64> athr๚" +#~ msgid "%ld changes" +#~ msgstr "%ld athr๚" #~ msgid "with KDE GUI." #~ msgstr "le GUI KDE." diff --git a/src/nvim/po/it.po b/src/nvim/po/it.po index 6c62262675..b8b119ade6 100644 --- a/src/nvim/po/it.po +++ b/src/nvim/po/it.po @@ -2541,7 +2541,7 @@ msgstr "E490: Non trovo alcuna piegatura" #: ../fold.c:544 msgid "E350: Cannot create fold with current 'foldmethod'" -msgstr "E350: Non posso create piegatura con il 'foldmethod' in uso" +msgstr "E350: Non posso creare piegatura con il 'foldmethod' in uso" #: ../fold.c:546 msgid "E351: Cannot delete fold with current 'foldmethod'" diff --git a/src/nvim/po/ja.euc-jp.po b/src/nvim/po/ja.euc-jp.po index c6425324b1..4b32096f1a 100644 --- a/src/nvim/po/ja.euc-jp.po +++ b/src/nvim/po/ja.euc-jp.po @@ -1,3 +1,4 @@ + # Japanese translation for Vim # # Do ":help uganda" in Vim to read copying and usage conditions. @@ -14,213 +15,176 @@ msgid "" msgstr "" "Project-Id-Version: Vim 7.4\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2016-02-01 09:02+0900\n" -"PO-Revision-Date: 2016-02-01 09:08+0900\n" +"POT-Creation-Date: 2016-09-10 21:10+0900\n" +"PO-Revision-Date: 2016-09-10 21:20+0900\n" "Last-Translator: MURAOKA Taro <koron.kaoriya@gmail.com>\n" "Language-Team: vim-jp (https://github.com/vim-jp/lang-ja)\n" "Language: Japanese\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=euc-jp\n" "Content-Transfer-Encoding: 8-bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" -#: ../api/private/helpers.c:201 -#, fuzzy -msgid "Unable to get option value" -msgstr "ฅชฅืฅทฅ็ฅ๓คฮรอคฯผ่ฦภควคญคคปค๓" +msgid "E831: bf_key_init() called with empty password" +msgstr "E831: bf_key_init() คฌถ๕ฅัฅนฅ๏กผฅษควธฦคำฝะคตค์คคทคฟ" -#: ../api/private/helpers.c:204 -msgid "internal error: unknown option type" -msgstr "ฦโษ๔ฅจฅ้กผ: ฬครฮคฮฅชฅืฅทฅ็ฅ๓ทฟควคน" +msgid "E820: sizeof(uint32_t) != 4" +msgstr "E820: sizeof(uint32_t) != 4" + +msgid "E817: Blowfish big/little endian use wrong" +msgstr "E817: Blowfishฐลนๆคฮฅำฅรฅฐ/ฅ๊ฅศฅ๋ฅจฅ๓ฅวฅฃฅขฅ๓คฌดึฐใครคฦคคคคน" + +msgid "E818: sha256 test failed" +msgstr "E818: sha256คฮฅฦฅนฅศคหผบวิคทคคทคฟ" + +msgid "E819: Blowfish test failed" +msgstr "E819: Blowfishฐลนๆคฮฅฦฅนฅศคหผบวิคทคคทคฟ" -#: ../buffer.c:92 msgid "[Location List]" msgstr "[ฅํฅฑกผฅทฅ็ฅ๓ฅ๊ฅนฅศ]" -#: ../buffer.c:93 msgid "[Quickfix List]" msgstr "[Quickfixฅ๊ฅนฅศ]" -#: ../buffer.c:94 msgid "E855: Autocommands caused command to abort" msgstr "E855: autocommandคฌฅณฅฅ๓ฅษคฮฤไป฿ค๒ฐ๚คญตฏคณคทคคทคฟ" -#: ../buffer.c:135 msgid "E82: Cannot allocate any buffer, exiting..." msgstr "E82: ฅะฅรฅีฅกค๒1คฤคโบ๎ภฎควคญคสคคคฮคว, ฝชฮปคทคคน..." -#: ../buffer.c:138 msgid "E83: Cannot allocate buffer, using other one..." msgstr "E83: ฅะฅรฅีฅกค๒บ๎ภฎควคญคสคคคฮคว, ยพคฮค๒ปศอัคทคคน..." -#: ../buffer.c:763 +msgid "E931: Buffer cannot be registered" +msgstr "E931: ฅะฅรฅีฅกค๒ละฯฟควคญคคปค๓" + +msgid "E937: Attempt to delete a buffer that is in use" +msgstr "E937: ปศอัรๆคฮฅะฅรฅีฅกค๒บ๏ฝคทค่คฆคศป๎ค฿คคทคฟ" + msgid "E515: No buffers were unloaded" msgstr "E515: ฒ๒สคตค์คฟฅะฅรฅีฅกคฯคขค๊คคปค๓" -#: ../buffer.c:765 msgid "E516: No buffers were deleted" msgstr "E516: บ๏ฝคตค์คฟฅะฅรฅีฅกคฯคขค๊คคปค๓" -#: ../buffer.c:767 msgid "E517: No buffers were wiped out" msgstr "E517: วหดคตค์คฟฅะฅรฅีฅกคฯคขค๊คคปค๓" -#: ../buffer.c:772 msgid "1 buffer unloaded" msgstr "1 ธฤคฮฅะฅรฅีฅกคฌฒ๒สคตค์คคทคฟ" -#: ../buffer.c:774 #, c-format msgid "%d buffers unloaded" msgstr "%d ธฤคฮฅะฅรฅีฅกคฌฒ๒สคตค์คคทคฟ" -#: ../buffer.c:777 msgid "1 buffer deleted" msgstr "1 ธฤคฮฅะฅรฅีฅกคฌบ๏ฝคตค์คคทคฟ" -#: ../buffer.c:779 #, c-format msgid "%d buffers deleted" msgstr "%d ธฤคฮฅะฅรฅีฅกคฌบ๏ฝคตค์คคทคฟ" -#: ../buffer.c:782 msgid "1 buffer wiped out" msgstr "1 ธฤคฮฅะฅรฅีฅกคฌวหดคตค์คคทคฟ" -#: ../buffer.c:784 #, c-format msgid "%d buffers wiped out" msgstr "%d ธฤคฮฅะฅรฅีฅกคฌวหดคตค์คคทคฟ" -#: ../buffer.c:806 msgid "E90: Cannot unload last buffer" msgstr "E90: บวธๅคฮฅะฅรฅีฅกคฯฒ๒สควคญคคปค๓" -#: ../buffer.c:874 msgid "E84: No modified buffer found" msgstr "E84: สันนคตค์คฟฅะฅรฅีฅกคฯคขค๊คคปค๓" #. back where we started, didn't find anything. -#: ../buffer.c:903 msgid "E85: There is no listed buffer" msgstr "E85: ฅ๊ฅนฅศษฝผจคตค์ค๋ฅะฅรฅีฅกคฯคขค๊คคปค๓" -#: ../buffer.c:913 -#, c-format -msgid "E86: Buffer %<PRId64> does not exist" -msgstr "E86: ฅะฅรฅีฅก %<PRId64> คฯคขค๊คคปค๓" - -#: ../buffer.c:915 msgid "E87: Cannot go beyond last buffer" msgstr "E87: บวธๅคฮฅะฅรฅีฅกค๒ฑคจคฦฐฦฐคฯควคญคคปค๓" -#: ../buffer.c:917 msgid "E88: Cannot go before first buffer" msgstr "E88: บวฝ้คฮฅะฅรฅีฅกค่ค๊มฐคุคฯฐฦฐควคญคคปค๓" -#: ../buffer.c:945 #, c-format -msgid "" -"E89: No write since last change for buffer %<PRId64> (add ! to override)" -msgstr "E89: ฅะฅรฅีฅก %<PRId64> คฮสันนคฯสยธคตค์คฦคคคคปค๓ (! ควสันนค๒วหด)" +msgid "E89: No write since last change for buffer %ld (add ! to override)" +msgstr "E89: ฅะฅรฅีฅก %ld คฮสันนคฯสยธคตค์คฦคคคคปค๓ (! ควสันนค๒วหด)" -#. wrap around (may cause duplicates) -#: ../buffer.c:1423 msgid "W14: Warning: List of file names overflow" msgstr "W14: ทูน๐: ฅีฅกฅคฅ๋ฬพคฮฅ๊ฅนฅศคฌฤนฒแคฎคคน" -#: ../buffer.c:1555 ../quickfix.c:3361 #, c-format -msgid "E92: Buffer %<PRId64> not found" -msgstr "E92: ฅะฅรฅีฅก %<PRId64> คฌธซคฤคซค๊คคปค๓" +msgid "E92: Buffer %ld not found" +msgstr "E92: ฅะฅรฅีฅก %ld คฌธซคฤคซค๊คคปค๓" -#: ../buffer.c:1798 #, c-format msgid "E93: More than one match for %s" msgstr "E93: %s คหสฃฟ๔คฮณบล๖คฌคขค๊คคทคฟ" -#: ../buffer.c:1800 #, c-format msgid "E94: No matching buffer for %s" msgstr "E94: %s คหณบล๖คนค๋ฅะฅรฅีฅกคฯคขค๊คคปค๓ควคทคฟ" -#: ../buffer.c:2161 #, c-format -msgid "line %<PRId64>" -msgstr "นิ %<PRId64>" +msgid "line %ld" +msgstr "นิ %ld" -#: ../buffer.c:2233 msgid "E95: Buffer with this name already exists" msgstr "E95: คณคฮฬพมฐคฮฅะฅรฅีฅกคฯด๛คหคขค๊คคน" -#: ../buffer.c:2498 msgid " [Modified]" msgstr " [สันนคขค๊]" -#: ../buffer.c:2501 msgid "[Not edited]" msgstr "[ฬคสิฝธ]" -#: ../buffer.c:2504 msgid "[New file]" msgstr "[ฟทฅีฅกฅคฅ๋]" -#: ../buffer.c:2505 msgid "[Read errors]" msgstr "[ฦษนฅจฅ้กผ]" -#: ../buffer.c:2506 ../buffer.c:3217 ../fileio.c:1807 ../screen.c:4895 msgid "[RO]" msgstr "[ฦษภ์]" -#: ../buffer.c:2507 ../fileio.c:1807 msgid "[readonly]" msgstr "[ฦษนภ์อั]" -#: ../buffer.c:2524 #, c-format msgid "1 line --%d%%--" msgstr "1 นิ --%d%%--" -#: ../buffer.c:2526 #, c-format -msgid "%<PRId64> lines --%d%%--" -msgstr "%<PRId64> นิ --%d%%--" +msgid "%ld lines --%d%%--" +msgstr "%ld นิ --%d%%--" -#: ../buffer.c:2530 #, c-format -msgid "line %<PRId64> of %<PRId64> --%d%%-- col " -msgstr "นิ %<PRId64> (มดยฮ %<PRId64>) --%d%%-- col " +msgid "line %ld of %ld --%d%%-- col " +msgstr "นิ %ld (มดยฮ %ld) --%d%%-- col " -#: ../buffer.c:2632 ../buffer.c:4292 ../memline.c:1554 msgid "[No Name]" msgstr "[ฬตฬพ]" #. must be a help buffer -#: ../buffer.c:2667 msgid "help" msgstr "ฅุฅ๋ฅื" -#: ../buffer.c:3225 ../screen.c:4883 msgid "[Help]" msgstr "[ฅุฅ๋ฅื]" -#: ../buffer.c:3254 ../screen.c:4887 msgid "[Preview]" msgstr "[ฅืฅ์ฅำฅๅกผ]" -#: ../buffer.c:3528 msgid "All" msgstr "มดคฦ" -#: ../buffer.c:3528 msgid "Bot" msgstr "ห๖ศ๘" -#: ../buffer.c:3531 msgid "Top" msgstr "ภ่ฦฌ" -#: ../buffer.c:4244 msgid "" "\n" "# Buffer list:\n" @@ -228,11 +192,9 @@ msgstr "" "\n" "# ฅะฅรฅีฅกฅ๊ฅนฅศ:\n" -#: ../buffer.c:4289 msgid "[Scratch]" msgstr "[ฒผฝ๑คญ]" -#: ../buffer.c:4529 msgid "" "\n" "--- Signs ---" @@ -240,200 +202,235 @@ msgstr "" "\n" "--- ฅตฅคฅ๓ ---" -#: ../buffer.c:4538 #, c-format msgid "Signs for %s:" msgstr "%s คฮฅตฅคฅ๓:" -#: ../buffer.c:4543 #, c-format -msgid " line=%<PRId64> id=%d name=%s" -msgstr " นิ=%<PRId64> ผฑสฬปา=%d ฬพมฐ=%s" +msgid " line=%ld id=%d name=%s" +msgstr " นิ=%ld ผฑสฬปา=%d ฬพมฐ=%s" -#: ../cursor_shape.c:68 -msgid "E545: Missing colon" -msgstr "E545: ฅณฅํฅ๓คฌคขค๊คคปค๓" +msgid "E902: Cannot connect to port" +msgstr "E902: ฅกผฅศคหภยณควคญคคปค๓" -#: ../cursor_shape.c:70 ../cursor_shape.c:94 -msgid "E546: Illegal mode" -msgstr "E546: ษิภตคสฅโกผฅษควคน" +msgid "E901: gethostbyname() in channel_open()" +msgstr "E901: channel_open() ฦโคฮ gethostbyname() คฌผบวิคทคคทคฟ" -#: ../cursor_shape.c:134 -msgid "E548: digit expected" -msgstr "E548: ฟ๔รอคฌษฌอืควคน" +msgid "E898: socket() in channel_open()" +msgstr "E898: channel_open() ฦโคฮ socket() คฌผบวิคทคคทคฟ" -#: ../cursor_shape.c:138 -msgid "E549: Illegal percentage" -msgstr "E549: ษิภตคสฅักผฅปฅ๓ฅฦกผฅธควคน" +msgid "E903: received command with non-string argument" +msgstr "E903: ศ๓สธป๚ฮ๓คฮฐ๚ฟ๔คฮฅณฅฅ๓ฅษค๒ผ๕ฟฎคทคคทคฟ" + +msgid "E904: last argument for expr/call must be a number" +msgstr "E904: expr/call คฮบวธๅคฮฐ๚ฟ๔คฯฟ๔ป๚ควคสคฑค์คะคสค๊คคปค๓" + +msgid "E904: third argument for call must be a list" +msgstr "E904: call คฮ3ศึฬคฮฐ๚ฟ๔คฯฅ๊ฅนฅศทฟควคสคฑค์คะคสค๊คคปค๓" + +#, c-format +msgid "E905: received unknown command: %s" +msgstr "E905: ฬครฮคฮฅณฅฅ๓ฅษค๒ผ๕ฟฎคทคคทคฟ: %s" + +#, c-format +msgid "E630: %s(): write while not connected" +msgstr "E630: %s(): ศ๓ภยณพ๕ยึควฝ๑คญนค฿คคทคฟ" + +#, c-format +msgid "E631: %s(): write failed" +msgstr "E631: %s(): ฝ๑คญนค฿คหผบวิคทคคทคฟ" + +#, c-format +msgid "E917: Cannot use a callback with %s()" +msgstr "E917: %s() คหฅณกผฅ๋ฅะฅรฅฏคฯปศคจคคปค๓" + +msgid "E912: cannot use ch_evalexpr()/ch_sendexpr() with a raw or nl channel" +msgstr "E912: ภธคไ nl ฅมฅใฅ๓ฅอฅ๋คห ch_evalexpr()/ch_sendexpr คฯปศคจคคปค๓" + +msgid "E906: not an open channel" +msgstr "E906: ณซคคคฦคคคสคคฅมฅใฅ๓ฅอฅ๋ควคน" + +msgid "E920: _io file requires _name to be set" +msgstr "E920: _io ฅีฅกฅคฅ๋คฯ _name คฮภ฿ฤ๊คฌษฌอืควคน" + +msgid "E915: in_io buffer requires in_buf or in_name to be set" +msgstr "E915: in_io ฅะฅรฅีฅกคฯ in_buf คซ in_name คฮภ฿ฤ๊คฌษฌอืควคน" + +#, c-format +msgid "E918: buffer must be loaded: %s" +msgstr "E918: ฅะฅรฅีฅกคฌฅํกผฅษคตค์คฦคสคฑค์คะคสค๊คคปค๓: %s" + +msgid "E821: File is encrypted with unknown method" +msgstr "E821: ฅีฅกฅคฅ๋คฌฬครฮคฮสหกควฐลนๆฒฝคตค์คฦคคคคน" + +msgid "Warning: Using a weak encryption method; see :help 'cm'" +msgstr "ทูน๐: ผๅคคฐลนๆสหกค๒ปศครคฦคคคคน; :help 'cm' ค๒ปฒพศคทคฦคฏคภคตคค" + +msgid "Enter encryption key: " +msgstr "ฐลนๆฒฝอัคฮฅญกผค๒ฦฮฯคทคฦคฏคภคตคค: " + +msgid "Enter same key again: " +msgstr "คโคฆฐ์ลูฦฑคธฅญกผค๒ฦฮฯคทคฦคฏคภคตคค: " + +msgid "Keys don't match!" +msgstr "ฅญกผคฌฐ์รืคทคคปค๓" + +msgid "[crypted]" +msgstr "[ฐลนๆฒฝ]" + +#, c-format +msgid "E720: Missing colon in Dictionary: %s" +msgstr "E720: ผญฝ๑ทฟคหฅณฅํฅ๓คฌคขค๊คคปค๓: %s" + +#, c-format +msgid "E721: Duplicate key in Dictionary: \"%s\"" +msgstr "E721: ผญฝ๑ทฟคหฝลสฃฅญกผคฌคขค๊คคน: \"%s\"" + +#, c-format +msgid "E722: Missing comma in Dictionary: %s" +msgstr "E722: ผญฝ๑ทฟคหฅซฅ๓ฅคฌคขค๊คคปค๓: %s" + +#, c-format +msgid "E723: Missing end of Dictionary '}': %s" +msgstr "E723: ผญฝ๑ทฟคฮบวธๅคห '}' คฌคขค๊คคปค๓: %s" + +msgid "extend() argument" +msgstr "extend() คฮฐ๚ฟ๔" -#: ../diff.c:146 #, c-format -msgid "E96: Can not diff more than %<PRId64> buffers" -msgstr "E96: %<PRId64> ฐสพๅคฮฅะฅรฅีฅกคฯdiffควคญคคปค๓" +msgid "E737: Key already exists: %s" +msgstr "E737: ฅญกผคฯด๛คหยธบ฿คทคคน: %s" + +#, c-format +msgid "E96: Cannot diff more than %ld buffers" +msgstr "E96: %ld ฐสพๅคฮฅะฅรฅีฅกคฯdiffควคญคคปค๓" -#: ../diff.c:753 msgid "E810: Cannot read or write temp files" msgstr "E810: ฐ์ปฅีฅกฅคฅ๋คฮฦษนคโคทคฏคฯฝ๑นคฌควคญคคปค๓" -#: ../diff.c:755 msgid "E97: Cannot create diffs" msgstr "E97: บนสฌค๒บ๎ภฎควคญคคปค๓" -#: ../diff.c:966 +msgid "Patch file" +msgstr "ฅัฅรฅมฅีฅกฅคฅ๋" + msgid "E816: Cannot read patch output" msgstr "E816: patchคฮฝะฮฯค๒ฦษนคแคคปค๓" -#: ../diff.c:1220 msgid "E98: Cannot read diff output" msgstr "E98: diffคฮฝะฮฯค๒ฦษนคแคคปค๓" -#: ../diff.c:2081 msgid "E99: Current buffer is not in diff mode" msgstr "E99: ธฝบ฿คฮฅะฅรฅีฅกคฯบนสฌฅโกผฅษควคฯคขค๊คคปค๓" -#: ../diff.c:2100 msgid "E793: No other buffer in diff mode is modifiable" msgstr "E793: บนสฌฅโกผฅษควคขค๋ยพคฮฅะฅรฅีฅกคฯสันนควคญคคปค๓" -#: ../diff.c:2102 msgid "E100: No other buffer in diff mode" msgstr "E100: บนสฌฅโกผฅษควคขค๋ยพคฮฅะฅรฅีฅกคฯคขค๊คคปค๓" -#: ../diff.c:2112 msgid "E101: More than two buffers in diff mode, don't know which one to use" msgstr "" "E101: บนสฌฅโกผฅษคฮฅะฅรฅีฅกคฌ2ธฤฐสพๅคขค๋คฮควกขคษค์ค๒ปศคฆคซฦรฤ๊ควคญคคปค๓" -#: ../diff.c:2141 #, c-format msgid "E102: Can't find buffer \"%s\"" msgstr "E102: ฅะฅรฅีฅก \"%s\" คฌธซคฤคซค๊คคปค๓" -#: ../diff.c:2152 #, c-format msgid "E103: Buffer \"%s\" is not in diff mode" msgstr "E103: ฅะฅรฅีฅก \"%s\" คฯบนสฌฅโกผฅษควคฯคขค๊คคปค๓" -#: ../diff.c:2193 msgid "E787: Buffer changed unexpectedly" msgstr "E787: อฝดคปคบฅะฅรฅีฅกคฌสันนสันนคตค์คคทคฟ" -#: ../digraph.c:1598 msgid "E104: Escape not allowed in digraph" msgstr "E104: น็ป๚คหEscapeคฯปศอัควคญคคปค๓" -#: ../digraph.c:1760 msgid "E544: Keymap file not found" msgstr "E544: ฅญกผฅฅรฅืฅีฅกฅคฅ๋คฌธซคฤคซค๊คคปค๓" -#: ../digraph.c:1785 msgid "E105: Using :loadkeymap not in a sourced file" msgstr "E105: :source ควผ่นคเฅีฅกฅคฅ๋ฐสณฐควคฯ :loadkeymap ค๒ปศคจคคปค๓" -#: ../digraph.c:1821 msgid "E791: Empty keymap entry" msgstr "E791: ถ๕คฮฅญกผฅฅรฅืฅจฅ๓ฅศฅ๊" -#: ../edit.c:82 msgid " Keyword completion (^N^P)" msgstr " ฅญกผฅ๏กผฅษสไดฐ (^N^P)" #. ctrl_x_mode == 0, ^P/^N compl. -#: ../edit.c:83 msgid " ^X mode (^]^D^E^F^I^K^L^N^O^Ps^U^V^Y)" msgstr " ^X ฅโกผฅษ (^]^D^E^F^I^K^L^N^O^Ps^U^V^Y)" -#: ../edit.c:85 msgid " Whole line completion (^L^N^P)" msgstr " นิ(มดยฮ)สไดฐ (^L^N^P)" -#: ../edit.c:86 msgid " File name completion (^F^N^P)" msgstr " ฅีฅกฅคฅ๋ฬพสไดฐ (^F^N^P)" -#: ../edit.c:87 msgid " Tag completion (^]^N^P)" msgstr " ฅฟฅฐสไดฐ (^]^N^P)" -#: ../edit.c:88 msgid " Path pattern completion (^N^P)" msgstr " ฅัฅนฅัฅฟกผฅ๓สไดฐ (^N^P)" -#: ../edit.c:89 msgid " Definition completion (^D^N^P)" msgstr " ฤ๊ตมสไดฐ (^D^N^P)" -#: ../edit.c:91 msgid " Dictionary completion (^K^N^P)" msgstr " ผญฝ๑สไดฐ (^K^N^P)" -#: ../edit.c:92 msgid " Thesaurus completion (^T^N^P)" msgstr " ฅทฅฝกผฅ้ฅนสไดฐ (^T^N^P)" -#: ../edit.c:93 msgid " Command-line completion (^V^N^P)" msgstr " ฅณฅฅ๓ฅษฅ้ฅคฅ๓สไดฐ (^V^N^P)" -#: ../edit.c:94 msgid " User defined completion (^U^N^P)" msgstr " ฅๆกผฅถกผฤ๊ตมสไดฐ (^U^N^P)" -#: ../edit.c:95 msgid " Omni completion (^O^N^P)" msgstr " ฅชฅเฅหสไดฐ (^O^N^P)" -#: ../edit.c:96 msgid " Spelling suggestion (s^N^P)" msgstr " ฤึค๊ฝคภตธ๕สไ (s^N^P)" -#: ../edit.c:97 msgid " Keyword Local completion (^N^P)" msgstr " ถษฝ๊ฅญกผฅ๏กผฅษสไดฐ (^N^P)" -#: ../edit.c:100 msgid "Hit end of paragraph" msgstr "รสอ๎คฮบวธๅคหฅาฅรฅศ" -#: ../edit.c:101 msgid "E839: Completion function changed window" msgstr "E839: สไดึดุฟ๔คฌฅฆฅฃฅ๓ฅษฅฆค๒สันนคทคคทคฟ" -#: ../edit.c:102 msgid "E840: Completion function deleted text" msgstr "E840: สไดฐดุฟ๔คฌฅฦฅญฅนฅศค๒บ๏ฝคทคคทคฟ" -#: ../edit.c:1847 msgid "'dictionary' option is empty" msgstr "'dictionary' ฅชฅืฅทฅ็ฅ๓คฌถ๕ควคน" -#: ../edit.c:1848 msgid "'thesaurus' option is empty" msgstr "'thesaurus' ฅชฅืฅทฅ็ฅ๓คฌถ๕ควคน" -#: ../edit.c:2655 #, c-format msgid "Scanning dictionary: %s" msgstr "ผญฝ๑ค๒ฅนฅญฅใฅ๓รๆ: %s" -#: ../edit.c:3079 msgid " (insert) Scroll (^E/^Y)" msgstr " (มฦ) ฅนฅฏฅํกผฅ๋(^E/^Y)" -#: ../edit.c:3081 msgid " (replace) Scroll (^E/^Y)" msgstr " (รึดน) ฅนฅฏฅํกผฅ๋ (^E/^Y)" -#: ../edit.c:3587 #, c-format msgid "Scanning: %s" msgstr "ฅนฅญฅใฅ๓รๆ: %s" -#: ../edit.c:3614 msgid "Scanning tags." msgstr "ฅฟฅฐค๒ฅนฅญฅใฅ๓รๆ." -#: ../edit.c:4519 msgid " Adding" msgstr " ฤษฒรรๆ" @@ -441,431 +438,161 @@ msgstr " ฤษฒรรๆ" #. * be called before line = ml_get(), or when this address is no #. * longer needed. -- Acevedo. #. -#: ../edit.c:4562 msgid "-- Searching..." msgstr "-- ธกบ๗รๆ..." -#: ../edit.c:4618 msgid "Back at original" msgstr "ปฯคแคหฬแค๋" -#: ../edit.c:4621 msgid "Word from other line" msgstr "ยพคฮนิคฮรฑธ์" -#: ../edit.c:4624 msgid "The only match" msgstr "อฃฐ์คฮณบล๖" -#: ../edit.c:4680 #, c-format msgid "match %d of %d" msgstr "%d ศึฬคฮณบล๖ (มดณบล๖ %d ธฤรๆ)" -#: ../edit.c:4684 #, c-format msgid "match %d" msgstr "%d ศึฬคฮณบล๖" -#: ../eval.c:137 +#. maximum nesting of lists and dicts msgid "E18: Unexpected characters in :let" msgstr "E18: อฝดคปคฬสธป๚คฌ :let คหคขค๊คคทคฟ" -#: ../eval.c:138 -#, c-format -msgid "E684: list index out of range: %<PRId64>" -msgstr "E684: ฅ๊ฅนฅศคฮฅคฅ๓ฅวฅรฅฏฅนคฌศฯฐฯณฐควคน: %<PRId64>" - -#: ../eval.c:139 #, c-format msgid "E121: Undefined variable: %s" msgstr "E121: ฬคฤ๊ตมคฮสัฟ๔ควคน: %s" -#: ../eval.c:140 msgid "E111: Missing ']'" msgstr "E111: ']' คฌธซคฤคซค๊คคปค๓" -#: ../eval.c:141 -#, c-format -msgid "E686: Argument of %s must be a List" -msgstr "E686: %s คฮฐ๚ฟ๔คฯฅ๊ฅนฅศทฟควคสคฑค์คะคสค๊คคปค๓" - -#: ../eval.c:143 -#, c-format -msgid "E712: Argument of %s must be a List or Dictionary" -msgstr "E712: %s คฮฐ๚ฟ๔คฯฅ๊ฅนฅศทฟคคฟคฯผญฝ๑ทฟควคสคฑค์คะคสค๊คคปค๓" - -#: ../eval.c:144 -msgid "E713: Cannot use empty key for Dictionary" -msgstr "E713: ผญฝ๑ทฟคหถ๕คฮฅญกผค๒ปศคฆคณคศคฯควคญคคปค๓" - -#: ../eval.c:145 -msgid "E714: List required" -msgstr "E714: ฅ๊ฅนฅศทฟคฌษฌอืควคน" - -#: ../eval.c:146 -msgid "E715: Dictionary required" -msgstr "E715: ผญฝ๑ทฟคฌษฌอืควคน" - -#: ../eval.c:147 -#, c-format -msgid "E118: Too many arguments for function: %s" -msgstr "E118: ดุฟ๔คฮฐ๚ฟ๔คฌยฟฒแคฎคคน: %s" - -#: ../eval.c:148 -#, c-format -msgid "E716: Key not present in Dictionary: %s" -msgstr "E716: ผญฝ๑ทฟคหฅญกผคฌยธบ฿คทคคปค๓: %s" - -#: ../eval.c:150 -#, c-format -msgid "E122: Function %s already exists, add ! to replace it" -msgstr "E122: ดุฟ๔ %s คฯฤ๊ตมบัควคน, บฦฤ๊ตมคนค๋คหคฯ ! ค๒ฤษฒรคทคฦคฏคภคตคค" - -#: ../eval.c:151 -msgid "E717: Dictionary entry already exists" -msgstr "E717: ผญฝ๑ทฟฦโคหฅจฅ๓ฅศฅ๊คฌด๛คหยธบ฿คทคคน" - -#: ../eval.c:152 -msgid "E718: Funcref required" -msgstr "E718: ดุฟ๔ปฒพศทฟคฌอืตแคตค์คคน" - -#: ../eval.c:153 msgid "E719: Cannot use [:] with a Dictionary" msgstr "E719: [:] ค๒ผญฝ๑ทฟคศมศค฿น็ค๏คปคฦคฯปศคจคคปค๓" -#: ../eval.c:154 #, c-format msgid "E734: Wrong variable type for %s=" msgstr "E734: ฐคสครคฟทฟคฮสัฟ๔ควคน %s=" -#: ../eval.c:155 -#, c-format -msgid "E130: Unknown function: %s" -msgstr "E130: ฬครฮคฮดุฟ๔ควคน: %s" - -#: ../eval.c:156 #, c-format msgid "E461: Illegal variable name: %s" msgstr "E461: ษิภตคสสัฟ๔ฬพควคน: %s" -#: ../eval.c:157 msgid "E806: using Float as a String" msgstr "E806: ษโฦฐพฎฟ๔ลภฟ๔ค๒สธป๚ฮ๓คศคทคฦฐทครคฦคคคคน" -#: ../eval.c:1830 msgid "E687: Less targets than List items" msgstr "E687: ฅฟกผฅฒฅรฅศคฌฅ๊ฅนฅศทฟฦโคฮอืมวค่ค๊คโพฏคสคคควคน" -#: ../eval.c:1834 msgid "E688: More targets than List items" msgstr "E688: ฅฟกผฅฒฅรฅศคฌฅ๊ฅนฅศทฟฦโคฮอืมวค่ค๊คโยฟคคควคน" -#: ../eval.c:1906 msgid "Double ; in list of variables" msgstr "ฅ๊ฅนฅศทฟคฮรอคห2คฤฐสพๅคฮ ; คฌธกฝะคตค์คคทคฟ" -#: ../eval.c:2078 #, c-format msgid "E738: Can't list variables for %s" msgstr "E738: %s คฮรอค๒ฐ์อ๗ษฝผจควคญคคปค๓" -#: ../eval.c:2391 msgid "E689: Can only index a List or Dictionary" msgstr "E689: ฅ๊ฅนฅศทฟคศผญฝ๑ทฟฐสณฐคฯฅคฅ๓ฅวฅรฅฏฅนปุฤ๊ควคญคคปค๓" -#: ../eval.c:2396 msgid "E708: [:] must come last" msgstr "E708: [:] คฯบวธๅควคสคฑค์คะคคคฑคคปค๓" -#: ../eval.c:2439 msgid "E709: [:] requires a List value" msgstr "E709: [:] คหคฯฅ๊ฅนฅศทฟคฮรอคฌษฌอืควคน" -#: ../eval.c:2674 msgid "E710: List value has more items than target" msgstr "E710: ฅ๊ฅนฅศทฟสัฟ๔คหฅฟกผฅฒฅรฅศค่ค๊คโยฟคคอืมวคฌคขค๊คคน" -#: ../eval.c:2678 msgid "E711: List value has not enough items" msgstr "E711: ฅ๊ฅนฅศทฟสัฟ๔คหฝฝสฌคสฟ๔คฮอืมวคฌคขค๊คคปค๓" # -#: ../eval.c:2867 msgid "E690: Missing \"in\" after :for" msgstr "E690: :for คฮธๅคห \"in\" คฌคขค๊คคปค๓" -#: ../eval.c:3063 -#, c-format -msgid "E107: Missing parentheses: %s" -msgstr "E107: ฅซฅรฅณ '(' คฌคขค๊คคปค๓: %s" - -#: ../eval.c:3263 #, c-format msgid "E108: No such variable: \"%s\"" msgstr "E108: คฝคฮสัฟ๔คฯคขค๊คคปค๓: \"%s\"" -#: ../eval.c:3333 msgid "E743: variable nested too deep for (un)lock" msgstr "E743: (ฅขฅ๓)ฅํฅรฅฏคนค๋คหคฯสัฟ๔คฮฦค์ปาคฌฟผฒแคฎคคน" -#: ../eval.c:3630 msgid "E109: Missing ':' after '?'" msgstr "E109: '?' คฮธๅคห ':' คฌคขค๊คคปค๓" -#: ../eval.c:3893 msgid "E691: Can only compare List with List" msgstr "E691: ฅ๊ฅนฅศทฟคฯฅ๊ฅนฅศทฟคศคทคซศๆณำควคญคคปค๓" -#: ../eval.c:3895 -msgid "E692: Invalid operation for Lists" +msgid "E692: Invalid operation for List" msgstr "E692: ฅ๊ฅนฅศทฟคหคฯฬตธ๚คสมเบ๎ควคน" -#: ../eval.c:3915 msgid "E735: Can only compare Dictionary with Dictionary" msgstr "E735: ผญฝ๑ทฟคฯผญฝ๑ทฟคศคทคซศๆณำควคญคคปค๓" -#: ../eval.c:3917 msgid "E736: Invalid operation for Dictionary" msgstr "E736: ผญฝ๑ทฟคหคฯฬตธ๚คสมเบ๎ควคน" -#: ../eval.c:3932 -msgid "E693: Can only compare Funcref with Funcref" -msgstr "E693: ดุฟ๔ปฒพศทฟคฯดุฟ๔ปฒพศทฟคศคทคซศๆณำควคญคคปค๓" - -#: ../eval.c:3934 msgid "E694: Invalid operation for Funcrefs" msgstr "E694: ดุฟ๔ปฒพศทฟคหคฯฬตธ๚คสมเบ๎ควคน" -#: ../eval.c:4277 msgid "E804: Cannot use '%' with Float" msgstr "E804: '%' ค๒ษโฦฐพฎฟ๔ลภฟ๔คศมศค฿น็ค๏คปคฦคฯปศคจคคปค๓" -#: ../eval.c:4478 msgid "E110: Missing ')'" msgstr "E110: ')' คฌธซคฤคซค๊คคปค๓" -#: ../eval.c:4609 msgid "E695: Cannot index a Funcref" msgstr "E695: ดุฟ๔ปฒพศทฟคฯฅคฅ๓ฅวฅรฅฏฅนควคญคคปค๓" -#: ../eval.c:4839 +msgid "E909: Cannot index a special variable" +msgstr "E909: ฦรผ์สัฟ๔คฯฅคฅ๓ฅวฅรฅฏฅนควคญคคปค๓" + #, c-format msgid "E112: Option name missing: %s" msgstr "E112: ฅชฅืฅทฅ็ฅ๓ฬพคฌคขค๊คคปค๓: %s" -#: ../eval.c:4855 #, c-format msgid "E113: Unknown option: %s" msgstr "E113: ฬครฮคฮฅชฅืฅทฅ็ฅ๓ควคน: %s" -#: ../eval.c:4904 #, c-format msgid "E114: Missing quote: %s" msgstr "E114: ฐ๚อัษไ (\") คฌคขค๊คคปค๓: %s" -#: ../eval.c:5020 #, c-format msgid "E115: Missing quote: %s" msgstr "E115: ฐ๚อัษไ (') คฌคขค๊คคปค๓: %s" -#: ../eval.c:5084 -#, c-format -msgid "E696: Missing comma in List: %s" -msgstr "E696: ฅ๊ฅนฅศทฟคหฅซฅ๓ฅคฌคขค๊คคปค๓: %s" - -#: ../eval.c:5091 -#, c-format -msgid "E697: Missing end of List ']': %s" -msgstr "E697: ฅ๊ฅนฅศทฟคฮบวธๅคห ']' คฌคขค๊คคปค๓: %s" - -#: ../eval.c:5807 msgid "Not enough memory to set references, garbage collection aborted!" msgstr "" "ฅฌกผฅูฅรฅธฅณฅ์ฅฏฅทฅ็ฅ๓ค๒รๆป฿คทคคทคฟ! ปฒพศค๒บ๎ภฎคนค๋คฮคหฅแฅโฅ๊คฌษิยญคทคคทคฟ" -#: ../eval.c:6475 -#, c-format -msgid "E720: Missing colon in Dictionary: %s" -msgstr "E720: ผญฝ๑ทฟคหฅณฅํฅ๓คฌคขค๊คคปค๓: %s" - -#: ../eval.c:6499 -#, c-format -msgid "E721: Duplicate key in Dictionary: \"%s\"" -msgstr "E721: ผญฝ๑ทฟคหฝลสฃฅญกผคฌคขค๊คคน: \"%s\"" - -#: ../eval.c:6517 -#, c-format -msgid "E722: Missing comma in Dictionary: %s" -msgstr "E722: ผญฝ๑ทฟคหฅซฅ๓ฅคฌคขค๊คคปค๓: %s" - -#: ../eval.c:6524 -#, c-format -msgid "E723: Missing end of Dictionary '}': %s" -msgstr "E723: ผญฝ๑ทฟคฮบวธๅคห '}' คฌคขค๊คคปค๓: %s" - -#: ../eval.c:6555 msgid "E724: variable nested too deep for displaying" msgstr "E724: ษฝผจคนค๋คหคฯสัฟ๔คฮฦค์ปาคฌฟผฒแคฎคคน" -#: ../eval.c:7188 -#, c-format -msgid "E740: Too many arguments for function %s" -msgstr "E740: ดุฟ๔คฮฐ๚ฟ๔คฌยฟฒแคฎคคน: %s" - -#: ../eval.c:7190 -#, c-format -msgid "E116: Invalid arguments for function %s" -msgstr "E116: ดุฟ๔คฮฬตธ๚คสฐ๚ฟ๔ควคน: %s" - -#: ../eval.c:7377 -#, c-format -msgid "E117: Unknown function: %s" -msgstr "E117: ฬครฮคฮดุฟ๔ควคน: %s" - -#: ../eval.c:7383 -#, c-format -msgid "E119: Not enough arguments for function: %s" -msgstr "E119: ดุฟ๔คฮฐ๚ฟ๔คฌยญค๊คคปค๓: %s" - -#: ../eval.c:7387 -#, c-format -msgid "E120: Using <SID> not in a script context: %s" -msgstr "E120: ฅนฅฏฅ๊ฅืฅศฐสณฐคว<SID>คฌปศค๏ค์คคทคฟ: %s" - -#: ../eval.c:7391 -#, c-format -msgid "E725: Calling dict function without Dictionary: %s" -msgstr "E725: ผญฝ๑อัดุฟ๔คฌธฦคะค์คคทคฟคฌผญฝ๑คฌคขค๊คคปค๓: %s" - -#: ../eval.c:7453 -msgid "E808: Number or Float required" -msgstr "E808: ฟ๔รอคซษโฦฐพฎฟ๔ลภฟ๔คฌษฌอืควคน" - -#: ../eval.c:7503 -msgid "add() argument" -msgstr "add() คฮฐ๚ฟ๔" - -#: ../eval.c:7907 -msgid "E699: Too many arguments" -msgstr "E699: ฐ๚ฟ๔คฌยฟฒแคฎคคน" - -#: ../eval.c:8073 -msgid "E785: complete() can only be used in Insert mode" -msgstr "E785: complete() คฯมฦฅโกผฅษควคทคซอ๘อัควคญคคปค๓" - -#: ../eval.c:8156 -msgid "&Ok" -msgstr "&Ok" - -#: ../eval.c:8676 -#, c-format -msgid "E737: Key already exists: %s" -msgstr "E737: ฅญกผคฯด๛คหยธบ฿คทคคน: %s" - -#: ../eval.c:8692 -msgid "extend() argument" -msgstr "extend() คฮฐ๚ฟ๔" - -#: ../eval.c:8915 -msgid "map() argument" -msgstr "map() คฮฐ๚ฟ๔" - -#: ../eval.c:8916 -msgid "filter() argument" -msgstr "filter() คฮฐ๚ฟ๔" - -#: ../eval.c:9229 -#, c-format -msgid "+-%s%3ld lines: " -msgstr "+-%s%3ld นิ: " - -#: ../eval.c:9291 -#, c-format -msgid "E700: Unknown function: %s" -msgstr "E700: ฬครฮคฮดุฟ๔ควคน: %s" - -#: ../eval.c:10729 -msgid "called inputrestore() more often than inputsave()" -msgstr "inputrestore() คฌ inputsave() ค่ค๊คโยฟคฏธฦคะค์คคทคฟ" - -#: ../eval.c:10771 -msgid "insert() argument" -msgstr "insert() คฮฐ๚ฟ๔" - -#: ../eval.c:10841 -msgid "E786: Range not allowed" -msgstr "E786: ศฯฐฯปุฤ๊คฯต๖ฒฤคตค์คฦคคคคปค๓" - -#: ../eval.c:11140 -msgid "E701: Invalid type for len()" -msgstr "E701: len() คหคฯฬตธ๚คสทฟควคน" - -#: ../eval.c:11980 -msgid "E726: Stride is zero" -msgstr "E726: ฅนฅศฅ้ฅคฅษ(มฐฟสฮฬ)คฌ 0 ควคน" - -#: ../eval.c:11982 -msgid "E727: Start past end" -msgstr "E727: ณซปฯฐฬรึคฌฝชฮปฐฬรึค๒ฑคจคคทคฟ" - -#: ../eval.c:12024 ../eval.c:15297 -msgid "<empty>" -msgstr "<ถ๕>" - -#: ../eval.c:12282 -msgid "remove() argument" -msgstr "remove() คฮฐ๚ฟ๔" - -# Added at 10-Mar-2004. -#: ../eval.c:12466 -msgid "E655: Too many symbolic links (cycle?)" -msgstr "E655: ฅทฅ๓ฅฅ๊ฅรฅฏฅ๊ฅ๓ฅฏคฌยฟฒแคฎคคน (ฝดฤคทคฦคคค๋ฒฤวฝภญคฌคขค๊คคน)" - -#: ../eval.c:12593 -msgid "reverse() argument" -msgstr "reverse() คฮฐ๚ฟ๔" - -#: ../eval.c:13721 -msgid "sort() argument" -msgstr "sort() คฮฐ๚ฟ๔" - -#: ../eval.c:13721 -msgid "uniq() argument" -msgstr "uniq() คฮฐ๚ฟ๔" - -#: ../eval.c:13776 -msgid "E702: Sort compare function failed" -msgstr "E702: ฅฝกผฅศคฮศๆณำดุฟ๔คฌผบวิคทคคทคฟ" - -#: ../eval.c:13806 -msgid "E882: Uniq compare function failed" -msgstr "E882: Uniq คฮศๆณำดุฟ๔คฌผบวิคทคคทคฟ" - -#: ../eval.c:14085 -msgid "(Invalid)" -msgstr "(ฬตธ๚)" - -#: ../eval.c:14590 -msgid "E677: Error writing temp file" -msgstr "E677: ฐ์ปฅีฅกฅคฅ๋ฝ๑นรๆคหฅจฅ้กผคฌศฏภธคทคคทคฟ" - -#: ../eval.c:16159 msgid "E805: Using a Float as a Number" msgstr "E805: ษโฦฐพฎฟ๔ลภฟ๔ค๒ฟ๔รอคศคทคฦฐทครคฦคคคคน" -#: ../eval.c:16162 msgid "E703: Using a Funcref as a Number" msgstr "E703: ดุฟ๔ปฒพศทฟค๒ฟ๔รอคศคทคฦฐทครคฦคคคคนกฃ" -#: ../eval.c:16170 msgid "E745: Using a List as a Number" msgstr "E745: ฅ๊ฅนฅศทฟค๒ฟ๔รอคศคทคฦฐทครคฦคคคคน" -#: ../eval.c:16173 msgid "E728: Using a Dictionary as a Number" msgstr "E728: ผญฝ๑ทฟค๒ฟ๔รอคศคทคฦฐทครคฦคคคคน" +msgid "E910: Using a Job as a Number" +msgstr "E910: ฅธฅ็ฅึค๒ฟ๔รอคศคทคฦฐทครคฦคคคคน" + +msgid "E913: Using a Channel as a Number" +msgstr "E913: ฅมฅใฅ๓ฅอฅ๋ค๒ฟ๔รอคศคทคฦฐทครคฦคคคคนกฃ" + msgid "E891: Using a Funcref as a Float" msgstr "E891: ดุฟ๔ปฒพศทฟค๒ษโฦฐพฎฟ๔ลภฟ๔คศคทคฦฐทครคฦคคคคนกฃ" @@ -878,265 +605,280 @@ msgstr "E893: ฅ๊ฅนฅศทฟค๒ษโฦฐพฎฟ๔ลภฟ๔คศคทคฦฐทครคฦคคคคน" msgid "E894: Using a Dictionary as a Float" msgstr "E894: ผญฝ๑ทฟค๒ษโฦฐพฎฟ๔ลภฟ๔คศคทคฦฐทครคฦคคคคน" -#: ../eval.c:16259 +msgid "E907: Using a special value as a Float" +msgstr "E907: ฦรผ์รอค๒ษโฦฐพฎฟ๔ลภฟ๔คศคทคฦฐทครคฦคคคคน" + +msgid "E911: Using a Job as a Float" +msgstr "E911: ฅธฅ็ฅึค๒ษโฦฐพฎฟ๔ลภฟ๔คศคทคฦฐทครคฦคคคคน" + +msgid "E914: Using a Channel as a Float" +msgstr "E914: ฅมฅใฅ๓ฅอฅ๋ค๒ษโฦฐพฎฟ๔ลภฟ๔คศคทคฦฐทครคฦคคคคนกฃ" + msgid "E729: using Funcref as a String" msgstr "E729: ดุฟ๔ปฒพศทฟค๒สธป๚ฮ๓คศคทคฦฐทครคฦคคคคน" -#: ../eval.c:16262 msgid "E730: using List as a String" msgstr "E730: ฅ๊ฅนฅศทฟค๒สธป๚ฮ๓คศคทคฦฐทครคฦคคคคน" -#: ../eval.c:16265 msgid "E731: using Dictionary as a String" msgstr "E731: ผญฝ๑ทฟค๒สธป๚ฮ๓คศคทคฦฐทครคฦคคคคน" -#: ../eval.c:16619 -#, c-format -msgid "E706: Variable type mismatch for: %s" -msgstr "E706: สัฟ๔คฮทฟคฌฐ์รืคทคคปค๓: %s" +msgid "E908: using an invalid value as a String" +msgstr "E908: ฬตธ๚คสรอค๒สธป๚ฮ๓คศคทคฦฐทครคฦคคคคน" -#: ../eval.c:16705 #, c-format msgid "E795: Cannot delete variable %s" msgstr "E795: สัฟ๔ %s ค๒บ๏ฝควคญคคปค๓" -#: ../eval.c:16724 #, c-format msgid "E704: Funcref variable name must start with a capital: %s" msgstr "E704: ดุฟ๔ปฒพศทฟสัฟ๔ฬพคฯย็สธป๚ควปฯคค้คสคฑค์คะคสค๊คคปค๓: %s" -#: ../eval.c:16732 #, c-format msgid "E705: Variable name conflicts with existing function: %s" msgstr "E705: สัฟ๔ฬพคฌด๛ยธคฮดุฟ๔ฬพคศพืฦอคทคคน: %s" -#: ../eval.c:16763 #, c-format msgid "E741: Value is locked: %s" msgstr "E741: รอคฌฅํฅรฅฏคตค์คฦคคคคน: %s" -#: ../eval.c:16764 ../eval.c:16769 ../message.c:1839 msgid "Unknown" msgstr "ษิฬภ" -#: ../eval.c:16768 #, c-format msgid "E742: Cannot change value of %s" msgstr "E742: %s คฮรอค๒สันนควคญคคปค๓" -#: ../eval.c:16838 msgid "E698: variable nested too deep for making a copy" msgstr "E698: ฅณฅิกผค๒ผ่ค๋คหคฯสัฟ๔คฮฦค์ปาคฌฟผฒแคฎคคน" -#: ../eval.c:17249 -#, c-format -msgid "E123: Undefined function: %s" -msgstr "E123: ฬคฤ๊ตมคฮดุฟ๔ควคน: %s" +msgid "" +"\n" +"# global variables:\n" +msgstr "" +"\n" +"# ฅฐฅํกผฅะฅ๋สัฟ๔:\n" -#: ../eval.c:17260 -#, c-format -msgid "E124: Missing '(': %s" -msgstr "E124: '(' คฌคขค๊คคปค๓: %s" +msgid "" +"\n" +"\tLast set from " +msgstr "" +"\n" +"\tบวธๅคหฅปฅรฅศคทคฟฅนฅฏฅ๊ฅืฅศ: " -#: ../eval.c:17293 -msgid "E862: Cannot use g: here" -msgstr "E862: คณคณควคฯ g: คฯปศคจคคปค๓" +msgid "map() argument" +msgstr "map() คฮฐ๚ฟ๔" -#: ../eval.c:17312 -#, c-format -msgid "E125: Illegal argument: %s" -msgstr "E125: ษิภตคสฐ๚ฟ๔ควคน: %s" +msgid "filter() argument" +msgstr "filter() คฮฐ๚ฟ๔" -#: ../eval.c:17323 #, c-format -msgid "E853: Duplicate argument name: %s" -msgstr "E853: ฐ๚ฟ๔ฬพคฌฝลสฃคทคฦคคคคน: %s" +msgid "E686: Argument of %s must be a List" +msgstr "E686: %s คฮฐ๚ฟ๔คฯฅ๊ฅนฅศทฟควคสคฑค์คะคสค๊คคปค๓" -#: ../eval.c:17416 -msgid "E126: Missing :endfunction" -msgstr "E126: :endfunction คฌคขค๊คคปค๓" +msgid "E928: String required" +msgstr "E928: สธป๚ฮ๓คฌษฌอืควคน" -#: ../eval.c:17537 -#, c-format -msgid "E707: Function name conflicts with variable: %s" -msgstr "E707: ดุฟ๔ฬพคฌสัฟ๔ฬพคศพืฦอคทคคน: %s" +msgid "E808: Number or Float required" +msgstr "E808: ฟ๔รอคซษโฦฐพฎฟ๔ลภฟ๔คฌษฌอืควคน" -#: ../eval.c:17549 -#, c-format -msgid "E127: Cannot redefine function %s: It is in use" -msgstr "E127: ดุฟ๔ %s ค๒บฦฤ๊ตมควคญคคปค๓: ปศอัรๆควคน" +msgid "add() argument" +msgstr "add() คฮฐ๚ฟ๔" -#: ../eval.c:17604 -#, c-format -msgid "E746: Function name does not match script file name: %s" -msgstr "E746: ดุฟ๔ฬพคฌฅนฅฏฅ๊ฅืฅศคฮฅีฅกฅคฅ๋ฬพคศฐ์รืคทคคปค๓: %s" +msgid "E785: complete() can only be used in Insert mode" +msgstr "E785: complete() คฯมฦฅโกผฅษควคทคซอ๘อัควคญคคปค๓" -#: ../eval.c:17716 -msgid "E129: Function name required" -msgstr "E129: ดุฟ๔ฬพคฌอืตแคตค์คคน" +#. +#. * Yes this is ugly, I don't particularly like it either. But doing it +#. * this way has the compelling advantage that translations need not to +#. * be touched at all. See below what 'ok' and 'ync' are used for. +#. +msgid "&Ok" +msgstr "&Ok" -#: ../eval.c:17824 #, c-format -msgid "E128: Function name must start with a capital or \"s:\": %s" -msgstr "E128: ดุฟ๔ฬพคฯย็สธป๚คซ \"s:\" ควปฯคค้คสคฑค์คะคสค๊คคปค๓: %s" +msgid "+-%s%3ld line: " +msgid_plural "+-%s%3ld lines: " +msgstr[0] "+-%s%3ld นิ: " -#: ../eval.c:17833 #, c-format -msgid "E884: Function name cannot contain a colon: %s" -msgstr "E884: ดุฟ๔ฬพคหคฯฅณฅํฅ๓คฯดคแค้ค์คคปค๓: %s" +msgid "E700: Unknown function: %s" +msgstr "E700: ฬครฮคฮดุฟ๔ควคน: %s" -#: ../eval.c:18336 -#, c-format -msgid "E131: Cannot delete function %s: It is in use" -msgstr "E131: ดุฟ๔ %s ค๒บ๏ฝควคญคคปค๓: ปศอัรๆควคน" +msgid "E922: expected a dict" +msgstr "E922: ผญฝ๑คฌดยิคตค์คฦคคคคน" -#: ../eval.c:18441 -msgid "E132: Function call depth is higher than 'maxfuncdepth'" -msgstr "E132: ดุฟ๔ธฦฝะคฮฦค์ปาฟ๔คฌ 'maxfuncdepth' ค๒ฤถคจคคทคฟ" +msgid "E923: Second argument of function() must be a list or a dict" +msgstr "E923: function() คฮย่ 2 ฐ๚ฟ๔คฯฅ๊ฅนฅศทฟคคฟคฯผญฝ๑ทฟควคสคฑค์คะคสค๊คคปค๓" -#: ../eval.c:18568 -#, c-format -msgid "calling %s" -msgstr "%s ค๒ผยนิรๆควคน" +msgid "" +"&OK\n" +"&Cancel" +msgstr "" +"ท่ฤ๊(&O)\n" +"ฅญฅใฅ๓ฅปฅ๋(&C)" -#: ../eval.c:18651 -#, c-format -msgid "%s aborted" -msgstr "%s คฌรๆรวคตค์คคทคฟ" +msgid "called inputrestore() more often than inputsave()" +msgstr "inputrestore() คฌ inputsave() ค่ค๊คโยฟคฏธฦคะค์คคทคฟ" + +msgid "insert() argument" +msgstr "insert() คฮฐ๚ฟ๔" + +msgid "E786: Range not allowed" +msgstr "E786: ศฯฐฯปุฤ๊คฯต๖ฒฤคตค์คฦคคคคปค๓" + +msgid "E916: not a valid job" +msgstr "E916: อญธ๚คสฅธฅ็ฅึควคฯคขค๊คคปค๓" + +msgid "E701: Invalid type for len()" +msgstr "E701: len() คหคฯฬตธ๚คสทฟควคน" -#: ../eval.c:18653 #, c-format -msgid "%s returning #%<PRId64>" -msgstr "%s คฌ #%<PRId64> ค๒สึคทคคทคฟ" +msgid "E798: ID is reserved for \":match\": %ld" +msgstr "E798: ID คฯ \":match\" คฮคฟคแคหอฝฬ๓คตค์คฦคคคคน: %ld" + +msgid "E726: Stride is zero" +msgstr "E726: ฅนฅศฅ้ฅคฅษ(มฐฟสฮฬ)คฌ 0 ควคน" + +msgid "E727: Start past end" +msgstr "E727: ณซปฯฐฬรึคฌฝชฮปฐฬรึค๒ฑคจคคทคฟ" + +msgid "<empty>" +msgstr "<ถ๕>" + +msgid "E240: No connection to Vim server" +msgstr "E240: Vim ฅตกผฅะกผคุคฮภยณคฌคขค๊คคปค๓" -#: ../eval.c:18670 #, c-format -msgid "%s returning %s" -msgstr "%s คฌ %s ค๒สึคทคคทคฟ" +msgid "E241: Unable to send to %s" +msgstr "E241: %s คุม๗ค๋คณคศคฌควคญคคปค๓" + +msgid "E277: Unable to read a server reply" +msgstr "E277: ฅตกผฅะกผคฮฑล๚คฌคขค๊คคปค๓" + +msgid "remove() argument" +msgstr "remove() คฮฐ๚ฟ๔" + +# Added at 10-Mar-2004. +msgid "E655: Too many symbolic links (cycle?)" +msgstr "E655: ฅทฅ๓ฅฅ๊ฅรฅฏฅ๊ฅ๓ฅฏคฌยฟฒแคฎคคน (ฝดฤคทคฦคคค๋ฒฤวฝภญคฌคขค๊คคน)" + +msgid "reverse() argument" +msgstr "reverse() คฮฐ๚ฟ๔" + +msgid "E258: Unable to send to client" +msgstr "E258: ฅฏฅ้ฅคฅขฅ๓ฅศคุม๗ค๋คณคศคฌควคญคคปค๓" -#: ../eval.c:18691 ../ex_cmds2.c:2695 #, c-format -msgid "continuing in %s" -msgstr "%s คฮผยนิค๒ทัยณรๆควคน" +msgid "E927: Invalid action: '%s'" +msgstr "E927: ฬตธ๚คสมเบ๎ควคน: %s" -#: ../eval.c:18795 -msgid "E133: :return not inside a function" -msgstr "E133: ดุฟ๔ณฐคห :return คฌคขค๊คคทคฟ" +msgid "sort() argument" +msgstr "sort() คฮฐ๚ฟ๔" -#: ../eval.c:19159 -msgid "" -"\n" -"# global variables:\n" -msgstr "" -"\n" -"# ฅฐฅํกผฅะฅ๋สัฟ๔:\n" +msgid "uniq() argument" +msgstr "uniq() คฮฐ๚ฟ๔" -#: ../eval.c:19254 -msgid "" -"\n" -"\tLast set from " -msgstr "" -"\n" -"\tLast set from " +msgid "E702: Sort compare function failed" +msgstr "E702: ฅฝกผฅศคฮศๆณำดุฟ๔คฌผบวิคทคคทคฟ" -#: ../eval.c:19272 -msgid "No old files" -msgstr "ธลคคฅีฅกฅคฅ๋คฯคขค๊คคปค๓" +msgid "E882: Uniq compare function failed" +msgstr "E882: Uniq คฮศๆณำดุฟ๔คฌผบวิคทคคทคฟ" + +msgid "(Invalid)" +msgstr "(ฬตธ๚)" + +#, c-format +msgid "E935: invalid submatch number: %d" +msgstr "E935: ฬตธ๚คสฅตฅึฅฅรฅมศึนๆ: %d" + +msgid "E677: Error writing temp file" +msgstr "E677: ฐ์ปฅีฅกฅคฅ๋ฝ๑นรๆคหฅจฅ้กผคฌศฏภธคทคคทคฟ" + +msgid "E921: Invalid callback argument" +msgstr "E921: ฬตธ๚คสฅณกผฅ๋ฅะฅรฅฏฐ๚ฟ๔ควคน" -#: ../ex_cmds.c:122 #, c-format msgid "<%s>%s%s %d, Hex %02x, Octal %03o" msgstr "<%s>%s%s %d, 16ฟสฟ๔ %02x, 8ฟสฟ๔ %03o" -#: ../ex_cmds.c:145 #, c-format msgid "> %d, Hex %04x, Octal %o" msgstr "> %d, 16ฟสฟ๔ %04x, 8ฟสฟ๔ %o" -#: ../ex_cmds.c:146 #, c-format msgid "> %d, Hex %08x, Octal %o" msgstr "> %d, 16ฟสฟ๔ %08x, 8ฟสฟ๔ %o" -#: ../ex_cmds.c:684 msgid "E134: Move lines into themselves" msgstr "E134: นิค๒คฝค์ผซฟศคหคฯฐฦฐควคญคคปค๓" -#: ../ex_cmds.c:747 msgid "1 line moved" msgstr "1 นิคฌฐฦฐคตค์คคทคฟ" -#: ../ex_cmds.c:749 #, c-format -msgid "%<PRId64> lines moved" -msgstr "%<PRId64> นิคฌฐฦฐคตค์คคทคฟ" +msgid "%ld lines moved" +msgstr "%ld นิคฌฐฦฐคตค์คคทคฟ" -#: ../ex_cmds.c:1175 #, c-format -msgid "%<PRId64> lines filtered" -msgstr "%<PRId64> นิคฌฅีฅฃฅ๋ฅฟฝ่อคตค์คคทคฟ" +msgid "%ld lines filtered" +msgstr "%ld นิคฌฅีฅฃฅ๋ฅฟฝ่อคตค์คคทคฟ" -#: ../ex_cmds.c:1194 msgid "E135: *Filter* Autocommands must not change current buffer" msgstr "E135: *ฅีฅฃฅ๋ฅฟ* autocommandคฯธฝบ฿คฮฅะฅรฅีฅกค๒สันนคทคฦคฯคคคฑคคปค๓" -#: ../ex_cmds.c:1244 msgid "[No write since last change]\n" msgstr "[บวธๅคฮสันนคฌสยธคตค์คฦคคคคปค๓]\n" -#: ../ex_cmds.c:1424 #, c-format msgid "%sviminfo: %s in line: " msgstr "%sviminfo: %s นิฬ: " -#: ../ex_cmds.c:1431 msgid "E136: viminfo: Too many errors, skipping rest of file" msgstr "E136: viminfo: ฅจฅ้กผคฌยฟฒแคฎค๋คฮคว, ฐสน฿คฯฅนฅญฅรฅืคทคคน" -#: ../ex_cmds.c:1458 #, c-format msgid "Reading viminfo file \"%s\"%s%s%s" msgstr "viminfoฅีฅกฅคฅ๋ \"%s\"%s%s%s ค๒ฦษนค฿รๆ" -#: ../ex_cmds.c:1460 msgid " info" msgstr " พ๐ส๓" -#: ../ex_cmds.c:1461 msgid " marks" msgstr " ฅกผฅฏ" -#: ../ex_cmds.c:1462 msgid " oldfiles" msgstr " ต์ฅีฅกฅคฅ๋ทฒ" -#: ../ex_cmds.c:1463 msgid " FAILED" msgstr " ผบวิ" #. avoid a wait_return for this message, it's annoying -#: ../ex_cmds.c:1541 #, c-format msgid "E137: Viminfo file is not writable: %s" msgstr "E137: viminfoฅีฅกฅคฅ๋คฌฝ๑นค฿ควคญคคปค๓: %s" -#: ../ex_cmds.c:1626 +#, c-format +msgid "E929: Too many viminfo temp files, like %s!" +msgstr "E929: ฐ์ปviminfoฅีฅกฅคฅ๋คฌยฟฒแคฎคคน! ฮใ: %s" + #, c-format msgid "E138: Can't write viminfo file %s!" msgstr "E138: viminfoฅีฅกฅคฅ๋ %s ค๒สยธควคญคคปค๓!" -#: ../ex_cmds.c:1635 #, c-format msgid "Writing viminfo file \"%s\"" msgstr "viminfoฅีฅกฅคฅ๋ \"%s\" ค๒ฝ๑นค฿รๆ" +#, c-format +msgid "E886: Can't rename viminfo file to %s!" +msgstr "E886: viminfoฅีฅกฅคฅ๋ค๒ %s คุฬพมฐสันนควคญคคปค๓!" + #. Write the info: -#: ../ex_cmds.c:1720 #, c-format msgid "# This viminfo file was generated by Vim %s.\n" msgstr "# คณคฮ viminfo ฅีฅกฅคฅ๋คฯ Vim %s คหค่ครคฦภธภฎคตค์คคทคฟ.\n" -#: ../ex_cmds.c:1722 msgid "" "# You may edit it if you're careful!\n" "\n" @@ -1144,47 +886,47 @@ msgstr "" "# สันนคนค๋บคหคฯฝฝสฌรํฐีคทคฦคฏคภคตคค!\n" "\n" -#: ../ex_cmds.c:1723 msgid "# Value of 'encoding' when this file was written\n" msgstr "# คณคฮฅีฅกฅคฅ๋คฌฝ๑คซค์คฟปคฮ 'encoding' คฮรอ\n" -#: ../ex_cmds.c:1800 msgid "Illegal starting char" msgstr "ษิภตคสภ่ฦฌสธป๚ควคน" -#: ../ex_cmds.c:2162 +msgid "" +"\n" +"# Bar lines, copied verbatim:\n" +msgstr "" +"\n" +"# '|' ควปฯคค๋นิคฮกขสธป๚ฤฬค๊คฮฅณฅิกผ:\n" + +msgid "Save As" +msgstr "สฬฬพควสยธ" + msgid "Write partial file?" msgstr "ฅีฅกฅคฅ๋ค๒ษ๔สฌลชคหสยธคทคคนคซ?" -#: ../ex_cmds.c:2166 msgid "E140: Use ! to write partial buffer" msgstr "E140: ฅะฅรฅีฅกค๒ษ๔สฌลชคหสยธคนค๋คหคฯ ! ค๒ปศครคฦคฏคภคตคค" -#: ../ex_cmds.c:2281 #, c-format msgid "Overwrite existing file \"%s\"?" msgstr "ด๛ยธคฮฅีฅกฅคฅ๋ \"%s\" ค๒พๅฝ๑คญคทคคนคซ?" -#: ../ex_cmds.c:2317 #, c-format msgid "Swap file \"%s\" exists, overwrite anyway?" msgstr "ฅนฅ๏ฅรฅืฅีฅกฅคฅ๋ \"%s\" คฌยธบ฿คทคคน. พๅฝ๑คญค๒ถฏภฉคทคคนคซ?" -#: ../ex_cmds.c:2326 #, c-format msgid "E768: Swap file exists: %s (:silent! overrides)" msgstr "E768: ฅนฅ๏ฅรฅืฅีฅกฅคฅ๋คฌยธบ฿คทคคน: %s (:silent! ค๒ฤษฒรควพๅฝ๑)" -#: ../ex_cmds.c:2381 #, c-format -msgid "E141: No file name for buffer %<PRId64>" -msgstr "E141: ฅะฅรฅีฅก %<PRId64> คหคฯฬพมฐคฌคขค๊คคปค๓" +msgid "E141: No file name for buffer %ld" +msgstr "E141: ฅะฅรฅีฅก %ld คหคฯฬพมฐคฌคขค๊คคปค๓" -#: ../ex_cmds.c:2412 msgid "E142: File not written: Writing is disabled by 'write' option" msgstr "E142: ฅีฅกฅคฅ๋คฯสยธคตค์คคปค๓ควคทคฟ: 'write' ฅชฅืฅทฅ็ฅ๓คหค่ค๊ฬตธ๚ควคน" -#: ../ex_cmds.c:2434 #, c-format msgid "" "'readonly' option is set for \"%s\".\n" @@ -1193,7 +935,6 @@ msgstr "" "\"%s\" คหคฯ 'readonly' ฅชฅืฅทฅ็ฅ๓คฌภ฿ฤ๊คตค์คฦคคคคน.\n" "พๅฝ๑คญถฏภฉค๒คทคคนคซ?" -#: ../ex_cmds.c:2439 #, c-format msgid "" "File permissions of \"%s\" are read-only.\n" @@ -1204,83 +945,68 @@ msgstr "" "คฝค์ควคโถฒค้คฏฝ๑คญนคเคณคศคฯฒฤวฝควคน.\n" "ทัยณคทคคนคซ?" -#: ../ex_cmds.c:2451 #, c-format msgid "E505: \"%s\" is read-only (add ! to override)" msgstr "E505: \"%s\" คฯฦษนภ์อัควคน (ถฏภฉฝ๑นคหคฯ ! ค๒ฤษฒร)" -#: ../ex_cmds.c:3120 +msgid "Edit File" +msgstr "ฅีฅกฅคฅ๋ค๒สิฝธ" + #, c-format msgid "E143: Autocommands unexpectedly deleted new buffer %s" msgstr "E143: autocommandคฌอฝดคปคบฟทคทคคฅะฅรฅีฅก %s ค๒บ๏ฝคทคคทคฟ" -#: ../ex_cmds.c:3313 msgid "E144: non-numeric argument to :z" msgstr "E144: ฟ๔ควคฯคสคคฐ๚ฟ๔คฌ :z คหลฯคตค์คคทคฟ" -#: ../ex_cmds.c:3404 msgid "E145: Shell commands not allowed in rvim" msgstr "E145: rvimควคฯฅทฅงฅ๋ฅณฅฅ๓ฅษค๒ปศคจคคปค๓" -#: ../ex_cmds.c:3498 msgid "E146: Regular expressions can't be delimited by letters" msgstr "E146: ภตตฌษฝธฝคฯสธป๚ควถ่ภฺค๋คณคศคฌควคญคคปค๓" -#: ../ex_cmds.c:3964 #, c-format msgid "replace with %s (y/n/a/q/l/^E/^Y)?" msgstr "%s คหรึดนคทคคนคซ? (y/n/a/q/l/^E/^Y)" -#: ../ex_cmds.c:4379 msgid "(Interrupted) " msgstr "(ณไนคค์คคทคฟ) " -#: ../ex_cmds.c:4384 msgid "1 match" msgstr "1 ฒีฝ๊ณบล๖คทคคทคฟ" -#: ../ex_cmds.c:4384 msgid "1 substitution" msgstr "1 ฒีฝ๊รึดนคทคคทคฟ" -#: ../ex_cmds.c:4387 #, c-format -msgid "%<PRId64> matches" -msgstr "%<PRId64> ฒีฝ๊ณบล๖คทคคทคฟ" +msgid "%ld matches" +msgstr "%ld ฒีฝ๊ณบล๖คทคคทคฟ" -#: ../ex_cmds.c:4388 #, c-format -msgid "%<PRId64> substitutions" -msgstr "%<PRId64> ฒีฝ๊รึดนคทคคทคฟ" +msgid "%ld substitutions" +msgstr "%ld ฒีฝ๊รึดนคทคคทคฟ" -#: ../ex_cmds.c:4392 msgid " on 1 line" msgstr " (ทื 1 นิฦโ)" -#: ../ex_cmds.c:4395 #, c-format -msgid " on %<PRId64> lines" -msgstr " (ทื %<PRId64> นิฦโ)" +msgid " on %ld lines" +msgstr " (ทื %ld นิฦโ)" -#: ../ex_cmds.c:4438 msgid "E147: Cannot do :global recursive" msgstr "E147: :global ค๒บฦตขลชคหคฯปศคจคคปค๓" -#: ../ex_cmds.c:4467 msgid "E148: Regular expression missing from global" msgstr "E148: globalฅณฅฅ๓ฅษคหภตตฌษฝธฝคฌปุฤ๊คตค์คฦคคคคปค๓" -#: ../ex_cmds.c:4508 #, c-format msgid "Pattern found in every line: %s" msgstr "ฅัฅฟกผฅ๓คฌมดคฦคฮนิควธซคฤคซค๊คคทคฟ: %s" -#: ../ex_cmds.c:4510 #, c-format msgid "Pattern not found: %s" msgstr "ฅัฅฟกผฅ๓คฯธซคฤคซค๊คคปค๓ควคทคฟ: %s" -#: ../ex_cmds.c:4587 msgid "" "\n" "# Last Substitute String:\n" @@ -1290,110 +1016,102 @@ msgstr "" "# บวธๅคหรึดนคตค์คฟสธป๚ฮ๓:\n" "$" -#: ../ex_cmds.c:4679 msgid "E478: Don't panic!" msgstr "E478: นฒคฦคสคคควคฏคภคตคค" -#: ../ex_cmds.c:4717 #, c-format msgid "E661: Sorry, no '%s' help for %s" msgstr "E661: ปฤวฐควคนคฌ '%s' คฮฅุฅ๋ฅืคฌ %s คหคฯคขค๊คคปค๓" -#: ../ex_cmds.c:4719 #, c-format msgid "E149: Sorry, no help for %s" msgstr "E149: ปฤวฐควคนคฌ %s คหคฯฅุฅ๋ฅืคฌคขค๊คคปค๓" -#: ../ex_cmds.c:4751 #, c-format msgid "Sorry, help file \"%s\" not found" msgstr "ปฤวฐควคนคฌฅุฅ๋ฅืฅีฅกฅคฅ๋ \"%s\" คฌธซคฤคซค๊คคปค๓" -#: ../ex_cmds.c:5323 #, c-format -msgid "E150: Not a directory: %s" -msgstr "E150: ฅวฅฃฅ์ฅฏฅศฅ๊ควคฯคขค๊คคปค๓: %s" +msgid "E151: No match: %s" +msgstr "E151: ฅฅรฅมคฯคขค๊คคปค๓: %s" -#: ../ex_cmds.c:5446 #, c-format msgid "E152: Cannot open %s for writing" msgstr "E152: ฝ๑นค฿อัคห %s ค๒ณซคฑคคปค๓" -#: ../ex_cmds.c:5471 #, c-format msgid "E153: Unable to open %s for reading" msgstr "E153: ฦษนอัคห %s ค๒ณซคฑคคปค๓" # Added at 29-Apr-2004. -#: ../ex_cmds.c:5500 #, c-format msgid "E670: Mix of help file encodings within a language: %s" msgstr "E670: 1คฤคฮธภธ์คฮฅุฅ๋ฅืฅีฅกฅคฅ๋คหสฃฟ๔คฮฅจฅ๓ฅณกผฅษคฌบฎบ฿คทคฦคคคคน: %s" -#: ../ex_cmds.c:5565 #, c-format msgid "E154: Duplicate tag \"%s\" in file %s/%s" msgstr "E154: ฅฟฅฐ \"%s\" คฌฅีฅกฅคฅ๋ %s/%s คหฝลสฃคทคฦคคคคน" -#: ../ex_cmds.c:5687 +#, c-format +msgid "E150: Not a directory: %s" +msgstr "E150: ฅวฅฃฅ์ฅฏฅศฅ๊ควคฯคขค๊คคปค๓: %s" + #, c-format msgid "E160: Unknown sign command: %s" msgstr "E160: ฬครฮคฮsignฅณฅฅ๓ฅษควคน: %s" -#: ../ex_cmds.c:5704 msgid "E156: Missing sign name" msgstr "E156: signฬพคฌคขค๊คคปค๓" -#: ../ex_cmds.c:5746 msgid "E612: Too many signs defined" msgstr "E612: signคฮฤ๊ตมคฌยฟฟ๔ธซคฤคซค๊คคทคฟ" -#: ../ex_cmds.c:5813 #, c-format msgid "E239: Invalid sign text: %s" msgstr "E239: ฬตธ๚คสsignคฮฅฦฅญฅนฅศควคน: %s" -#: ../ex_cmds.c:5844 ../ex_cmds.c:6035 #, c-format msgid "E155: Unknown sign: %s" msgstr "E155: ฬครฮคฮsignควคน: %s" -#: ../ex_cmds.c:5877 msgid "E159: Missing sign number" msgstr "E159: signคฮศึนๆคฌคขค๊คคปค๓" -#: ../ex_cmds.c:5971 #, c-format msgid "E158: Invalid buffer name: %s" msgstr "E158: ฬตธ๚คสฅะฅรฅีฅกฬพควคน: %s" -#: ../ex_cmds.c:6008 +msgid "E934: Cannot jump to a buffer that does not have a name" +msgstr "E934: ฬพมฐคฮฬตคคฅะฅรฅีฅกคุคฯฅธฅใฅ๓ฅืควคญคคปค๓" + #, c-format -msgid "E157: Invalid sign ID: %<PRId64>" -msgstr "E157: ฬตธ๚คสsignผฑสฬปาควคน: %<PRId64>" +msgid "E157: Invalid sign ID: %ld" +msgstr "E157: ฬตธ๚คสsignผฑสฬปาควคน: %ld" #, c-format msgid "E885: Not possible to change sign %s" msgstr "E885: สันนควคญคสคค sign ควคน: %s" -#: ../ex_cmds.c:6066 +# Added at 27-Jan-2004. +msgid " (NOT FOUND)" +msgstr " (ธซคฤคซค๊คคปค๓)" + msgid " (not supported)" msgstr " (ศ๓ฅตฅกผฅศ)" -#: ../ex_cmds.c:6169 msgid "[Deleted]" msgstr "[บ๏ฝบั]" -#: ../ex_cmds2.c:139 +msgid "No old files" +msgstr "ธลคคฅีฅกฅคฅ๋คฯคขค๊คคปค๓" + msgid "Entering Debug mode. Type \"cont\" to continue." msgstr "ฅวฅะฅรฅฐฅโกผฅษคหฦค๊คคน. ยณคฑค๋คหคฯ \"cont\" คศฦฮฯคทคฦคฏคภคตคค." -#: ../ex_cmds2.c:143 ../ex_docmd.c:759 #, c-format -msgid "line %<PRId64>: %s" -msgstr "นิ %<PRId64>: %s" +msgid "line %ld: %s" +msgstr "นิ %ld: %s" -#: ../ex_cmds2.c:145 #, c-format msgid "cmd: %s" msgstr "ฅณฅฅ๓ฅษ: %s" @@ -1405,232 +1123,184 @@ msgstr "ฅีฅ์กผฅเคฌ 0 ควคน" msgid "frame at highest level: %d" msgstr "บวนโฅ์ฅูฅ๋คฮฅีฅ์กผฅเ: %d" -#: ../ex_cmds2.c:322 #, c-format -msgid "Breakpoint in \"%s%s\" line %<PRId64>" -msgstr "ฅึฅ์กผฅฏฅฅคฅ๓ฅศ \"%s%s\" นิ %<PRId64>" +msgid "Breakpoint in \"%s%s\" line %ld" +msgstr "ฅึฅ์กผฅฏฅฅคฅ๓ฅศ \"%s%s\" นิ %ld" -#: ../ex_cmds2.c:581 #, c-format msgid "E161: Breakpoint not found: %s" msgstr "E161: ฅึฅ์กผฅฏฅฅคฅ๓ฅศคฌธซคฤคซค๊คคปค๓: %s" -#: ../ex_cmds2.c:611 msgid "No breakpoints defined" msgstr "ฅึฅ์กผฅฏฅฅคฅ๓ฅศคฌฤ๊ตมคตค์คฦคคคคปค๓" -#: ../ex_cmds2.c:617 #, c-format -msgid "%3d %s %s line %<PRId64>" -msgstr "%3d %s %s นิ %<PRId64>" +msgid "%3d %s %s line %ld" +msgstr "%3d %s %s นิ %ld" -#: ../ex_cmds2.c:942 msgid "E750: First use \":profile start {fname}\"" msgstr "E750: ฝ้คแคห \":profile start {fname}\" ค๒ผยนิคทคฦคฏคภคตคค" -#: ../ex_cmds2.c:1269 #, c-format msgid "Save changes to \"%s\"?" msgstr "สันนค๒ \"%s\" คหสยธคทคคนคซ?" -#: ../ex_cmds2.c:1271 ../ex_docmd.c:8851 msgid "Untitled" msgstr "ฬตย๊" -#: ../ex_cmds2.c:1421 #, c-format msgid "E162: No write since last change for buffer \"%s\"" msgstr "E162: ฅะฅรฅีฅก \"%s\" คฮสันนคฯสยธคตค์คฦคคคคปค๓" -#: ../ex_cmds2.c:1480 msgid "Warning: Entered other buffer unexpectedly (check autocommands)" msgstr "ทูน๐: อฝดคปคบยพฅะฅรฅีฅกคุฐฦฐคทคคทคฟ (autocommands ค๒ฤดคูคฦคฏคภคตคค)" -#: ../ex_cmds2.c:1826 msgid "E163: There is only one file to edit" msgstr "E163: สิฝธคนค๋ฅีฅกฅคฅ๋คฯ1คฤคทคซคขค๊คคปค๓" -#: ../ex_cmds2.c:1828 msgid "E164: Cannot go before first file" msgstr "E164: บวฝ้คฮฅีฅกฅคฅ๋ค่ค๊มฐคหคฯนิคฑคคปค๓" -#: ../ex_cmds2.c:1830 msgid "E165: Cannot go beyond last file" msgstr "E165: บวธๅคฮฅีฅกฅคฅ๋ค๒ฑคจคฦธๅคหคฯนิคฑคคปค๓" -#: ../ex_cmds2.c:2175 #, c-format msgid "E666: compiler not supported: %s" msgstr "E666: คฝคฮฅณฅ๓ฅัฅคฅ้คหคฯยะฑคทคฦคคคคปค๓: %s" -#: ../ex_cmds2.c:2257 #, c-format msgid "Searching for \"%s\" in \"%s\"" msgstr "\"%s\" ค๒ \"%s\" คซค้ธกบ๗รๆ" -#: ../ex_cmds2.c:2284 #, c-format msgid "Searching for \"%s\"" msgstr "\"%s\" ค๒ธกบ๗รๆ" -#: ../ex_cmds2.c:2307 #, c-format -msgid "not found in 'runtimepath': \"%s\"" -msgstr "'runtimepath' คฮรๆคหคฯธซคฤคซค๊คคปค๓: \"%s\"" +msgid "not found in '%s': \"%s\"" +msgstr "'%s' คฮรๆคหคฯคขค๊คคปค๓: \"%s\"" + +msgid "Source Vim script" +msgstr "Vimฅนฅฏฅ๊ฅืฅศคฮผ่นค฿" -#: ../ex_cmds2.c:2472 #, c-format msgid "Cannot source a directory: \"%s\"" msgstr "ฅวฅฃฅ์ฅฏฅศฅ๊คฯผ่นคแคคปค๓: \"%s\"" -#: ../ex_cmds2.c:2518 #, c-format msgid "could not source \"%s\"" msgstr "\"%s\" ค๒ผ่นคแคคปค๓" -#: ../ex_cmds2.c:2520 #, c-format -msgid "line %<PRId64>: could not source \"%s\"" -msgstr "นิ %<PRId64>: \"%s\" ค๒ผ่นคแคคปค๓" +msgid "line %ld: could not source \"%s\"" +msgstr "นิ %ld: \"%s\" ค๒ผ่นคแคคปค๓" -#: ../ex_cmds2.c:2535 #, c-format msgid "sourcing \"%s\"" msgstr "\"%s\" ค๒ผ่นรๆ" -#: ../ex_cmds2.c:2537 #, c-format -msgid "line %<PRId64>: sourcing \"%s\"" -msgstr "นิ %<PRId64>: %s ค๒ผ่นรๆ" +msgid "line %ld: sourcing \"%s\"" +msgstr "นิ %ld: %s ค๒ผ่นรๆ" -#: ../ex_cmds2.c:2693 #, c-format msgid "finished sourcing %s" msgstr "%s คฮผ่นค๒ดฐฮป" -#: ../ex_cmds2.c:2765 +#, c-format +msgid "continuing in %s" +msgstr "%s คฮผยนิค๒ทัยณรๆควคน" + msgid "modeline" msgstr "ฅโกผฅษนิ" -#: ../ex_cmds2.c:2767 msgid "--cmd argument" msgstr "--cmd ฐ๚ฟ๔" -#: ../ex_cmds2.c:2769 msgid "-c argument" msgstr "-c ฐ๚ฟ๔" -#: ../ex_cmds2.c:2771 msgid "environment variable" msgstr "ดฤถญสัฟ๔" -#: ../ex_cmds2.c:2773 msgid "error handler" msgstr "ฅจฅ้กผฅฯฅ๓ฅษฅ้" -#: ../ex_cmds2.c:3020 msgid "W15: Warning: Wrong line separator, ^M may be missing" msgstr "W15: ทูน๐: นิถ่ภฺคฌษิภตควคน. ^M คฌคสคคคฮควคทค็คฆ" -#: ../ex_cmds2.c:3139 msgid "E167: :scriptencoding used outside of a sourced file" msgstr "E167: :scriptencoding คฌผ่นฅนฅฏฅ๊ฅืฅศฐสณฐควปศอัคตค์คคทคฟ" -#: ../ex_cmds2.c:3166 msgid "E168: :finish used outside of a sourced file" msgstr "E168: :finish คฌผ่นฅนฅฏฅ๊ฅืฅศฐสณฐควปศอัคตค์คคทคฟ" -#: ../ex_cmds2.c:3389 #, c-format msgid "Current %slanguage: \"%s\"" msgstr "ธฝบ฿คฮ %sธภธ์: \"%s\"" -#: ../ex_cmds2.c:3404 #, c-format msgid "E197: Cannot set language to \"%s\"" msgstr "E197: ธภธ์ค๒ \"%s\" คหภ฿ฤ๊ควคญคคปค๓" -#. don't redisplay the window -#. don't wait for return -#: ../ex_docmd.c:387 msgid "Entering Ex mode. Type \"visual\" to go to Normal mode." msgstr "" "Exฅโกผฅษคหฦค๊คคน. ฅฮกผฅฅ๋ฅโกผฅษคหฬแค๋คหคฯ\"visual\"คศฦฮฯคทคฦคฏคภคตคค." -#: ../ex_docmd.c:428 msgid "E501: At end-of-file" msgstr "E501: ฅีฅกฅคฅ๋คฮฝชฮปฐฬรึ" -#: ../ex_docmd.c:513 msgid "E169: Command too recursive" msgstr "E169: ฅณฅฅ๓ฅษคฌบฦตขลชฒแคฎคคน" -#: ../ex_docmd.c:1006 #, c-format msgid "E605: Exception not caught: %s" msgstr "E605: ฮใณฐคฌสแยชคตค์คคปค๓ควคทคฟ: %s" -#: ../ex_docmd.c:1085 msgid "End of sourced file" msgstr "ผ่นฅีฅกฅคฅ๋คฮบวธๅควคน" -#: ../ex_docmd.c:1086 msgid "End of function" msgstr "ดุฟ๔คฮบวธๅควคน" -#: ../ex_docmd.c:1628 msgid "E464: Ambiguous use of user-defined command" msgstr "E464: ฅๆกผฅถกผฤ๊ตมฅณฅฅ๓ฅษคฮคขคคคคคคสปศอัควคน" -#: ../ex_docmd.c:1638 msgid "E492: Not an editor command" msgstr "E492: ฅจฅวฅฃฅฟคฮฅณฅฅ๓ฅษควคฯคขค๊คคปค๓" -#: ../ex_docmd.c:1729 msgid "E493: Backwards range given" msgstr "E493: ตีคตคคฮศฯฐฯคฌปุฤ๊คตค์คคทคฟ" -#: ../ex_docmd.c:1733 msgid "Backwards range given, OK to swap" msgstr "ตีคตคคฮศฯฐฯคฌปุฤ๊คตค์คคทคฟ, ฦยุคจคคนคซ?" -#. append -#. typed wrong -#: ../ex_docmd.c:1787 msgid "E494: Use w or w>>" msgstr "E494: w คโคทคฏคฯ w>> ค๒ปศอัคทคฦคฏคภคตคค" -#: ../ex_docmd.c:3454 -msgid "E319: The command is not available in this version" +msgid "E319: Sorry, the command is not available in this version" msgstr "E319: คณคฮฅะกผฅธฅ็ฅ๓ควคฯคณคฮฅณฅฅ๓ฅษคฯอ๘อัควคญคคปค๓, คดคแค๓คสคตคค" -#: ../ex_docmd.c:3752 msgid "E172: Only one file name allowed" msgstr "E172: ฅีฅกฅคฅ๋ฬพคฯ 1 คฤคหคทคฦคฏคภคตคค" -#: ../ex_docmd.c:4238 msgid "1 more file to edit. Quit anyway?" msgstr "สิฝธคนคูคญฅีฅกฅคฅ๋คฌ 1 ธฤคขค๊คคนคฌ, ฝชฮปคทคคนคซ?" -#: ../ex_docmd.c:4242 #, c-format msgid "%d more files to edit. Quit anyway?" msgstr "สิฝธคนคูคญฅีฅกฅคฅ๋คฌคขคศ %d ธฤคขค๊คคนคฌ, ฝชฮปคทคคนคซ?" -#: ../ex_docmd.c:4248 msgid "E173: 1 more file to edit" msgstr "E173: สิฝธคนคูคญฅีฅกฅคฅ๋คฌ 1 ธฤคขค๊คคน" -#: ../ex_docmd.c:4250 #, c-format -msgid "E173: %<PRId64> more files to edit" -msgstr "E173: สิฝธคนคูคญฅีฅกฅคฅ๋คฌคขคศ %<PRId64> ธฤคขค๊คคน" +msgid "E173: %ld more files to edit" +msgstr "E173: สิฝธคนคูคญฅีฅกฅคฅ๋คฌคขคศ %ld ธฤคขค๊คคน" -#: ../ex_docmd.c:4320 msgid "E174: Command already exists: add ! to replace it" msgstr "E174: ฅณฅฅ๓ฅษคฌด๛คหคขค๊คคน: บฦฤ๊ตมคนค๋คหคฯ ! ค๒ฤษฒรคทคฦคฏคภคตคค" -#: ../ex_docmd.c:4432 msgid "" "\n" " Name Args Address Complete Definition" @@ -1638,51 +1308,40 @@ msgstr "" "\n" " ฬพมฐ ฐ๚ฟ๔ ฅขฅษฅ์ฅน สไดฐ ฤ๊ตม" -#: ../ex_docmd.c:4516 msgid "No user-defined commands found" msgstr "ฅๆกผฅถกผฤ๊ตมฅณฅฅ๓ฅษคฌธซคฤคซค๊คคปค๓ควคทคฟ" -#: ../ex_docmd.c:4538 msgid "E175: No attribute specified" msgstr "E175: ยฐภญคฯฤ๊ตมคตค์คฦคคคคปค๓" -#: ../ex_docmd.c:4583 msgid "E176: Invalid number of arguments" msgstr "E176: ฐ๚ฟ๔คฮฟ๔คฌฬตธ๚ควคน" -#: ../ex_docmd.c:4594 msgid "E177: Count cannot be specified twice" msgstr "E177: ฅซฅฆฅ๓ฅศค๒2ฝลปุฤ๊คนค๋คณคศคฯควคญคคปค๓" -#: ../ex_docmd.c:4603 msgid "E178: Invalid default value for count" msgstr "E178: ฅซฅฆฅ๓ฅศคฮพสฮฌรอคฌฬตธ๚ควคน" -#: ../ex_docmd.c:4625 msgid "E179: argument required for -complete" msgstr "E179: -complete คหคฯฐ๚ฟ๔คฌษฌอืควคน" msgid "E179: argument required for -addr" msgstr "E179: -addr คหคฯฐ๚ฟ๔คฌษฌอืควคน" -#: ../ex_docmd.c:4635 #, c-format msgid "E181: Invalid attribute: %s" msgstr "E181: ฬตธ๚คสยฐภญควคน: %s" -#: ../ex_docmd.c:4678 msgid "E182: Invalid command name" msgstr "E182: ฬตธ๚คสฅณฅฅ๓ฅษฬพควคน" -#: ../ex_docmd.c:4691 msgid "E183: User defined commands must start with an uppercase letter" -msgstr "E183: ฅๆกผฅถฤ๊ตมฅณฅฅ๓ฅษคฯฑัย็สธป๚ควปฯคค้คสคฑค์คะคสค๊คคปค๓" +msgstr "E183: ฅๆกผฅถกผฤ๊ตมฅณฅฅ๓ฅษคฯฑัย็สธป๚ควปฯคค้คสคฑค์คะคสค๊คคปค๓" -#: ../ex_docmd.c:4696 msgid "E841: Reserved name, cannot be used for user defined command" msgstr "E841: อฝฬ๓ฬพคสคฮคว, ฅๆกผฅถกผฤ๊ตมฅณฅฅ๓ฅษคหอ๘อัควคญคคปค๓" -#: ../ex_docmd.c:4751 #, c-format msgid "E184: No such user-defined command: %s" msgstr "E184: คฝคฮฅๆกผฅถกผฤ๊ตมฅณฅฅ๓ฅษคฯคขค๊คคปค๓: %s" @@ -1691,293 +1350,261 @@ msgstr "E184: คฝคฮฅๆกผฅถกผฤ๊ตมฅณฅฅ๓ฅษคฯคขค๊คคปค๓: %s" msgid "E180: Invalid address type value: %s" msgstr "E180: ฬตธ๚คสฅขฅษฅ์ฅนฅฟฅคฅืรอควคน: %s" -#: ../ex_docmd.c:5219 #, c-format msgid "E180: Invalid complete value: %s" msgstr "E180: ฬตธ๚คสสไดฐปุฤ๊ควคน: %s" -#: ../ex_docmd.c:5225 msgid "E468: Completion argument only allowed for custom completion" msgstr "E468: สไดฐฐ๚ฟ๔คฯฅซฅนฅฟฅเสไดฐควคทคซปศอัควคญคคปค๓" -#: ../ex_docmd.c:5231 msgid "E467: Custom completion requires a function argument" msgstr "E467: ฅซฅนฅฟฅเสไดฐคหคฯฐ๚ฟ๔คศคทคฦดุฟ๔คฌษฌอืควคน" -#: ../ex_docmd.c:5257 +msgid "unknown" +msgstr "ษิฬภ" + #, c-format msgid "E185: Cannot find color scheme '%s'" msgstr "E185: ฅซฅ้กผฅนฅญกผฅเ '%s' คฌธซคฤคซค๊คคปค๓" -#: ../ex_docmd.c:5263 msgid "Greetings, Vim user!" msgstr "Vim ปศคคคตค๓กขคไคข!" -#: ../ex_docmd.c:5431 msgid "E784: Cannot close last tab page" msgstr "E784: บวธๅคฮฅฟฅึฅฺกผฅธค๒สฤคธค๋คณคศคฯควคญคคปค๓" -#: ../ex_docmd.c:5462 msgid "Already only one tab page" msgstr "ด๛คหฅฟฅึฅฺกผฅธคฯ1คฤคทคซคขค๊คคปค๓" -#: ../ex_docmd.c:6004 +msgid "Edit File in new window" +msgstr "ฟทคทคคฅฆฅฃฅ๓ฅษฅฆควฅีฅกฅคฅ๋ค๒สิฝธคทคคน" + #, c-format msgid "Tab page %d" msgstr "ฅฟฅึฅฺกผฅธ %d" -#: ../ex_docmd.c:6295 msgid "No swap file" msgstr "ฅนฅ๏ฅรฅืฅีฅกฅคฅ๋คฌคขค๊คคปค๓" -#: ../ex_docmd.c:6478 +msgid "Append File" +msgstr "ฤษฒรฅีฅกฅคฅ๋" + msgid "E747: Cannot change directory, buffer is modified (add ! to override)" msgstr "" "E747: ฅะฅรฅีฅกคฌฝคภตคตค์คฦคคค๋คฮคว, ฅวฅฃฅ์ฅฏฅศฅ๊ค๒สันนควคญคคปค๓ (! ค๒ฤษฒรคว" "พๅฝ๑)" -#: ../ex_docmd.c:6485 msgid "E186: No previous directory" msgstr "E186: มฐคฮฅวฅฃฅ์ฅฏฅศฅ๊คฯคขค๊คคปค๓" -#: ../ex_docmd.c:6530 msgid "E187: Unknown" msgstr "E187: ฬครฮ" -#: ../ex_docmd.c:6610 msgid "E465: :winsize requires two number arguments" msgstr "E465: :winsize คหคฯ2คฤคฮฟ๔รอคฮฐ๚ฟ๔คฌษฌอืควคน" -#: ../ex_docmd.c:6655 +#, c-format +msgid "Window position: X %d, Y %d" +msgstr "ฅฆฅฃฅ๓ฅษฅฆฐฬรึ: X %d, Y %d" + msgid "E188: Obtaining window position not implemented for this platform" msgstr "" "E188: คณคฮฅืฅ้ฅรฅศฅกผฅเคหคฯฅฆฅฃฅ๓ฅษฅฆฐฬรึคฮผ่ฦภตกวฝคฯผยม๕คตค์คฦคคคคปค๓" -#: ../ex_docmd.c:6662 msgid "E466: :winpos requires two number arguments" msgstr "E466: :winpos คหคฯ2คฤคฮฟ๔รอคฮฐ๚ฟ๔คฌษฌอืควคน" -#: ../ex_docmd.c:7241 +msgid "E930: Cannot use :redir inside execute()" +msgstr "E930: execute() คฮรๆควคฯ :redir คฯปศคจคคปค๓" + +msgid "Save Redirection" +msgstr "ฅ๊ฅภฅคฅ์ฅฏฅศค๒สยธคทคคน" + +msgid "Save View" +msgstr "ฅำฅๅกผค๒สยธคทคคน" + +msgid "Save Session" +msgstr "ฅปฅรฅทฅ็ฅ๓พ๐ส๓ค๒สยธคทคคน" + +msgid "Save Setup" +msgstr "ภ฿ฤ๊ค๒สยธคทคคน" + #, c-format msgid "E739: Cannot create directory: %s" msgstr "E739: ฅวฅฃฅ์ฅฏฅศฅ๊ค๒บ๎ภฎควคญคคปค๓: %s" -#: ../ex_docmd.c:7268 #, c-format msgid "E189: \"%s\" exists (add ! to override)" msgstr "E189: \"%s\" คฌยธบ฿คทคคน (พๅฝ๑คนค๋คหคฯ ! ค๒ฤษฒรคทคฦคฏคภคตคค)" -#: ../ex_docmd.c:7273 #, c-format msgid "E190: Cannot open \"%s\" for writing" msgstr "E190: \"%s\" ค๒ฝ๑นค฿อัคศคทคฦณซคฑคคปค๓" #. set mark -#: ../ex_docmd.c:7294 msgid "E191: Argument must be a letter or forward/backward quote" msgstr "E191: ฐ๚ฟ๔คฯ1สธป๚คฮฑัป๚คซฐ๚อัษไ (' คซ `) ควคสคฑค์คะคคคฑคคปค๓" -#: ../ex_docmd.c:7333 msgid "E192: Recursive use of :normal too deep" msgstr "E192: :normal คฮบฦตขอ๘อัคฌฟผคฏคสค๊ฒแคฎคคทคฟ" -#: ../ex_docmd.c:7807 +msgid "E809: #< is not available without the +eval feature" +msgstr "E809: #< คฯ +eval ตกวฝคฌฬตคคคศอ๘อัควคญคคปค๓" + msgid "E194: No alternate file name to substitute for '#'" msgstr "E194: '#'ค๒รึคญดนคจค๋ษ๛ฅีฅกฅคฅ๋คฮฬพมฐคฌคขค๊คคปค๓" -#: ../ex_docmd.c:7841 msgid "E495: no autocommand file name to substitute for \"<afile>\"" msgstr "E495: \"<afile>\"ค๒รึคญดนคจค๋autocommandคฮฅีฅกฅคฅ๋ฬพคฌคขค๊คคปค๓" -#: ../ex_docmd.c:7850 msgid "E496: no autocommand buffer number to substitute for \"<abuf>\"" msgstr "E496: \"<abuf>\"ค๒รึคญดนคจค๋autocommandฅะฅรฅีฅกศึนๆคฌคขค๊คคปค๓" -#: ../ex_docmd.c:7861 msgid "E497: no autocommand match name to substitute for \"<amatch>\"" msgstr "E497: \"<amatch>\"ค๒รึคญดนคจค๋autocommandคฮณบล๖ฬพคฌคขค๊คคปค๓" -#: ../ex_docmd.c:7870 msgid "E498: no :source file name to substitute for \"<sfile>\"" msgstr "E498: \"<sfile>\"ค๒รึคญดนคจค๋ :source ยะพฅีฅกฅคฅ๋ฬพคฌคขค๊คคปค๓" -#: ../ex_docmd.c:7876 msgid "E842: no line number to use for \"<slnum>\"" msgstr "E842: \"<slnum>\"ค๒รึคญดนคจค๋นิศึนๆคฌคขค๊คคปค๓" -#: ../ex_docmd.c:7903 -#, fuzzy, c-format +#, no-c-format msgid "E499: Empty file name for '%' or '#', only works with \":p:h\"" msgstr "" "E499: '%' คไ '#' คฌฬตฬพฅีฅกฅคฅ๋คสคฮคว \":p:h\" ค๒ศผค๏คสคคปศคคสคฯควคญคคปค๓" -#: ../ex_docmd.c:7905 msgid "E500: Evaluates to an empty string" msgstr "E500: ถ๕สธป๚ฮ๓คศคทคฦษพฒมคตค์คคทคฟ" -#: ../ex_docmd.c:8838 msgid "E195: Cannot open viminfo file for reading" msgstr "E195: viminfoฅีฅกฅคฅ๋ค๒ฦษนอัคศคทคฦณซคฑคคปค๓" -#: ../ex_eval.c:464 +msgid "E196: No digraphs in this version" +msgstr "E196: คณคฮฅะกผฅธฅ็ฅ๓คหน็ป๚คฯคขค๊คคปค๓" + msgid "E608: Cannot :throw exceptions with 'Vim' prefix" msgstr "E608: 'Vim' ควปฯคค๋ฮใณฐคฯ :throw ควคญคคปค๓" #. always scroll up, don't overwrite -#: ../ex_eval.c:496 #, c-format msgid "Exception thrown: %s" msgstr "ฮใณฐคฌศฏภธคทคคทคฟ: %s" -#: ../ex_eval.c:545 #, c-format msgid "Exception finished: %s" msgstr "ฮใณฐคฌผยซคทคคทคฟ: %s" -#: ../ex_eval.c:546 #, c-format msgid "Exception discarded: %s" msgstr "ฮใณฐคฌวหดคตค์คคทคฟ: %s" -#: ../ex_eval.c:588 ../ex_eval.c:634 #, c-format -msgid "%s, line %<PRId64>" -msgstr "%s, นิ %<PRId64>" +msgid "%s, line %ld" +msgstr "%s, นิ %ld" #. always scroll up, don't overwrite -#: ../ex_eval.c:608 #, c-format msgid "Exception caught: %s" msgstr "ฮใณฐคฌสแยชคตค์คคทคฟ: %s" -#: ../ex_eval.c:676 #, c-format msgid "%s made pending" msgstr "%s คหค่ค๊ฬคท่ฤ๊พ๕ยึคฌภธคธคคทคฟ" -#: ../ex_eval.c:679 #, c-format msgid "%s resumed" msgstr "%s คฌบฦณซคทคคทคฟ" -#: ../ex_eval.c:683 #, c-format msgid "%s discarded" msgstr "%s คฌวหดคตค์คคทคฟ" -#: ../ex_eval.c:708 msgid "Exception" msgstr "ฮใณฐ" -#: ../ex_eval.c:713 msgid "Error and interrupt" msgstr "ฅจฅ้กผคศณไนค฿" -#: ../ex_eval.c:715 msgid "Error" msgstr "ฅจฅ้กผ" #. if (pending & CSTP_INTERRUPT) -#: ../ex_eval.c:717 msgid "Interrupt" msgstr "ณไนค฿" -#: ../ex_eval.c:795 msgid "E579: :if nesting too deep" msgstr "E579: :if คฮฦค์ปาคฌฟผฒแคฎคคน" -#: ../ex_eval.c:830 msgid "E580: :endif without :if" msgstr "E580: :if คฮคสคค :endif คฌคขค๊คคน" -#: ../ex_eval.c:873 msgid "E581: :else without :if" msgstr "E581: :if คฮคสคค :else คฌคขค๊คคน" -#: ../ex_eval.c:876 msgid "E582: :elseif without :if" msgstr "E582: :if คฮคสคค :elseif คฌคขค๊คคน" -#: ../ex_eval.c:880 msgid "E583: multiple :else" msgstr "E583: สฃฟ๔คฮ :else คฌคขค๊คคน" -#: ../ex_eval.c:883 msgid "E584: :elseif after :else" msgstr "E584: :else คฮธๅคห :elseif คฌคขค๊คคน" -#: ../ex_eval.c:941 msgid "E585: :while/:for nesting too deep" msgstr "E585: :while คไ :for คฮฦค์ปาคฌฟผฒแคฎคคน" -#: ../ex_eval.c:1028 msgid "E586: :continue without :while or :for" msgstr "E586: :while คไ :for คฮคสคค :continue คฌคขค๊คคน" -#: ../ex_eval.c:1061 msgid "E587: :break without :while or :for" msgstr "E587: :while คไ :for คฮคสคค :break คฌคขค๊คคน" -#: ../ex_eval.c:1102 msgid "E732: Using :endfor with :while" msgstr "E732: :endfor ค๒ :while คศมศค฿น็ค๏คปคฦคคคคน" -#: ../ex_eval.c:1104 msgid "E733: Using :endwhile with :for" msgstr "E733: :endwhile ค๒ :for คศมศค฿น็ค๏คปคฦคคคคน" -#: ../ex_eval.c:1247 msgid "E601: :try nesting too deep" msgstr "E601: :try คฮฦค์ปาคฌฟผฒแคฎคคน" -#: ../ex_eval.c:1317 msgid "E603: :catch without :try" msgstr "E603: :try คฮคสคค :catch คฌคขค๊คคน" #. Give up for a ":catch" after ":finally" and ignore it. #. * Just parse. -#: ../ex_eval.c:1332 msgid "E604: :catch after :finally" msgstr "E604: :finally คฮธๅคห :catch คฌคขค๊คคน" -#: ../ex_eval.c:1451 msgid "E606: :finally without :try" msgstr "E606: :try คฮคสคค :finally คฌคขค๊คคน" #. Give up for a multiple ":finally" and ignore it. -#: ../ex_eval.c:1467 msgid "E607: multiple :finally" msgstr "E607: สฃฟ๔คฮ :finally คฌคขค๊คคน" -#: ../ex_eval.c:1571 msgid "E602: :endtry without :try" msgstr "E602: :try คฮคสคค :endtry ควคน" -#: ../ex_eval.c:2026 msgid "E193: :endfunction not inside a function" msgstr "E193: ดุฟ๔คฮณฐคห :endfunction คฌคขค๊คคทคฟ" -#: ../ex_getln.c:1643 msgid "E788: Not allowed to edit another buffer now" msgstr "E788: ธฝบ฿คฯยพคฮฅะฅรฅีฅกค๒สิฝธคนค๋คณคศคฯต๖คตค์คคปค๓" -#: ../ex_getln.c:1656 msgid "E811: Not allowed to change buffer information now" msgstr "E811: ธฝบ฿คฯฅะฅรฅีฅกพ๐ส๓ค๒สันนคนค๋คณคศคฯต๖คตค์คคปค๓" -#: ../ex_getln.c:3178 msgid "tagname" msgstr "ฅฟฅฐฬพ" -#: ../ex_getln.c:3181 msgid " kind file\n" msgstr " ฅีฅกฅคฅ๋ผ๏ฮเ\n" -#: ../ex_getln.c:4799 msgid "'history' option is zero" msgstr "ฅชฅืฅทฅ็ฅ๓ 'history' คฌฅผฅํควคน" -#: ../ex_getln.c:5046 #, c-format msgid "" "\n" @@ -1986,303 +1613,224 @@ msgstr "" "\n" "# %s นเฬคฮอ๚ฮ๒ (ฟทคทคคคโคฮคซค้ธลคคคโคฮคุ):\n" -#: ../ex_getln.c:5047 msgid "Command Line" msgstr "ฅณฅฅ๓ฅษฅ้ฅคฅ๓" -#: ../ex_getln.c:5048 msgid "Search String" msgstr "ธกบ๗สธป๚ฮ๓" -#: ../ex_getln.c:5049 msgid "Expression" msgstr "ผฐ" -#: ../ex_getln.c:5050 msgid "Input Line" msgstr "ฦฮฯนิ" -#: ../ex_getln.c:5117 +msgid "Debug Line" +msgstr "ฅวฅะฅรฅฐนิ" + msgid "E198: cmd_pchar beyond the command length" msgstr "E198: cmd_pchar คฌฅณฅฅ๓ฅษฤนค๒ฤถคจคคทคฟ" -#: ../ex_getln.c:5279 msgid "E199: Active window or buffer deleted" msgstr "E199: ฅขฅฏฅฦฅฃฅึคสฅฆฅฃฅ๓ฅษฅฆคซฅะฅรฅีฅกคฌบ๏ฝคตค์คคทคฟ" -#: ../file_search.c:203 -msgid "E854: path too long for completion" -msgstr "E854: ฅัฅนคฌฤนฒแคฎคฦสไดฐควคญคคปค๓" - -#: ../file_search.c:446 -#, c-format -msgid "" -"E343: Invalid path: '**[number]' must be at the end of the path or be " -"followed by '%s'." -msgstr "" -"E343: ฬตธ๚คสฅัฅนควคน: '**[ฟ๔รอ]' คฯpathคฮบวธๅคซ '%s' คฌยณคคคฦคสคคคศคคคฑคคป" -"ค๓." - -#: ../file_search.c:1505 -#, c-format -msgid "E344: Can't find directory \"%s\" in cdpath" -msgstr "E344: cdpathคหคฯ \"%s\" คศคคคฆฅีฅกฅคฅ๋คฌคขค๊คคปค๓" - -#: ../file_search.c:1508 -#, c-format -msgid "E345: Can't find file \"%s\" in path" -msgstr "E345: pathคหคฯ \"%s\" คศคคคฆฅีฅกฅคฅ๋คฌคขค๊คคปค๓" - -#: ../file_search.c:1512 -#, c-format -msgid "E346: No more directory \"%s\" found in cdpath" -msgstr "E346: cdpathคหคฯคณค์ฐสพๅ \"%s\" คศคคคฆฅีฅกฅคฅ๋คฌคขค๊คคปค๓" - -#: ../file_search.c:1515 -#, c-format -msgid "E347: No more file \"%s\" found in path" -msgstr "E347: ฅัฅนคหคฯคณค์ฐสพๅ \"%s\" คศคคคฆฅีฅกฅคฅ๋คฌคขค๊คคปค๓" - -#: ../fileio.c:137 msgid "E812: Autocommands changed buffer or buffer name" msgstr "E812: autocommandคฌฅะฅรฅีฅกคซฅะฅรฅีฅกฬพค๒สันนคทคคทคฟ" -#: ../fileio.c:368 msgid "Illegal file name" msgstr "ษิภตคสฅีฅกฅคฅ๋ฬพ" -#: ../fileio.c:395 ../fileio.c:476 ../fileio.c:2543 ../fileio.c:2578 msgid "is a directory" msgstr "คฯฅวฅฃฅ์ฅฏฅศฅ๊ควคน" -#: ../fileio.c:397 msgid "is not a file" msgstr "คฯฅีฅกฅคฅ๋ควคฯคขค๊คคปค๓" -#: ../fileio.c:508 ../fileio.c:3522 +msgid "is a device (disabled with 'opendevice' option)" +msgstr "คฯฅวฅะฅคฅนควคน ('opendevice' ฅชฅืฅทฅ็ฅ๓ควฒ๓ศ๒ควคญคคน)" + msgid "[New File]" msgstr "[ฟทฅีฅกฅคฅ๋]" -#: ../fileio.c:511 msgid "[New DIRECTORY]" msgstr "[ฟทตฌฅวฅฃฅ์ฅฏฅศฅ๊]" -#: ../fileio.c:529 ../fileio.c:532 msgid "[File too big]" msgstr "[ฅีฅกฅคฅ๋ฒแย็]" -#: ../fileio.c:534 msgid "[Permission Denied]" msgstr "[ธขธยคฌคขค๊คคปค๓]" -#: ../fileio.c:653 msgid "E200: *ReadPre autocommands made the file unreadable" msgstr "E200: *ReadPre autocommand คฌฅีฅกฅคฅ๋ค๒ฦษนษิฒฤคหคทคคทคฟ" -#: ../fileio.c:655 msgid "E201: *ReadPre autocommands must not change current buffer" msgstr "E201: *ReadPre autocommand คฯธฝบ฿คฮฅะฅรฅีฅกค๒สัคจค้ค์คคปค๓" -#: ../fileio.c:672 -msgid "Nvim: Reading from stdin...\n" +msgid "Vim: Reading from stdin...\n" msgstr "Vim: ษธฝเฦฮฯคซค้ฦษนรๆ...\n" +msgid "Reading from stdin..." +msgstr "ษธฝเฦฮฯคซค้ฦษนค฿รๆ..." + #. Re-opening the original file failed! -#: ../fileio.c:909 msgid "E202: Conversion made file unreadable!" msgstr "E202: สัดนคฌฅีฅกฅคฅ๋ค๒ฦษนษิฒฤคหคทคคทคฟ" -#. fifo or socket -#: ../fileio.c:1782 msgid "[fifo/socket]" msgstr "[FIFO/ฅฝฅฑฅรฅศ]" -#. fifo -#: ../fileio.c:1788 msgid "[fifo]" msgstr "[FIFO]" -#. or socket -#: ../fileio.c:1794 msgid "[socket]" msgstr "[ฅฝฅฑฅรฅศ]" -#. or character special -#: ../fileio.c:1801 msgid "[character special]" msgstr "[ฅญฅใฅ้ฅฏฅฟกฆฅวฅะฅคฅน]" -#: ../fileio.c:1815 msgid "[CR missing]" msgstr "[CRฬต]" -#: ../fileio.c:1819 msgid "[long lines split]" msgstr "[ฤนนิสฌณไ]" -#: ../fileio.c:1823 ../fileio.c:3512 msgid "[NOT converted]" msgstr "[ฬคสัดน]" -#: ../fileio.c:1826 ../fileio.c:3515 msgid "[converted]" msgstr "[สัดนบั]" -#: ../fileio.c:1831 #, c-format -msgid "[CONVERSION ERROR in line %<PRId64>]" -msgstr "[%<PRId64> นิฬควสัดนฅจฅ้กผ]" +msgid "[CONVERSION ERROR in line %ld]" +msgstr "[%ld นิฬควสัดนฅจฅ้กผ]" -#: ../fileio.c:1835 #, c-format -msgid "[ILLEGAL BYTE in line %<PRId64>]" -msgstr "[%<PRId64> นิฬคฮษิภตคสฅะฅคฅศ]" +msgid "[ILLEGAL BYTE in line %ld]" +msgstr "[%ld นิฬคฮษิภตคสฅะฅคฅศ]" -#: ../fileio.c:1838 msgid "[READ ERRORS]" msgstr "[ฦษนฅจฅ้กผ]" -#: ../fileio.c:2104 msgid "Can't find temp file for conversion" msgstr "สัดนคหษฌอืคสฐ์ปฅีฅกฅคฅ๋คฌธซคฤคซค๊คคปค๓" -#: ../fileio.c:2110 msgid "Conversion with 'charconvert' failed" msgstr "'charconvert' คหค่ค๋สัดนคฌผบวิคทคคทคฟ" -#: ../fileio.c:2113 msgid "can't read output of 'charconvert'" msgstr "'charconvert' คฮฝะฮฯค๒ฦษนคแคคปค๓ควคทคฟ" -#: ../fileio.c:2437 msgid "E676: No matching autocommands for acwrite buffer" msgstr "E676: acwriteฅะฅรฅีฅกคฮณบล๖คนค๋autocommandคฯยธบ฿คทคคปค๓" -#: ../fileio.c:2466 msgid "E203: Autocommands deleted or unloaded buffer to be written" msgstr "E203: สยธคนค๋ฅะฅรฅีฅกค๒autocommandคฌบ๏ฝคซฒ๒สคทคคทคฟ" -#: ../fileio.c:2486 msgid "E204: Autocommand changed number of lines in unexpected way" msgstr "E204: autocommandคฌอฝดคปคฬสหกควนิฟ๔ค๒สันนคทคคทคฟ" -#: ../fileio.c:2548 ../fileio.c:2565 +# Added at 19-Jan-2004. +msgid "NetBeans disallows writes of unmodified buffers" +msgstr "NetBeansคฯฬคสันนคฮฅะฅรฅีฅกค๒พๅฝ๑คนค๋คณคศคฯต๖ฒฤคทคฦคคคคปค๓" + +msgid "Partial writes disallowed for NetBeans buffers" +msgstr "NetBeansฅะฅรฅีฅกคฮฐ์ษ๔ค๒ฝ๑คญฝะคนคณคศคฯควคญคคปค๓" + msgid "is not a file or writable device" msgstr "คฯฅีฅกฅคฅ๋ควคโฝ๑นค฿ฒฤวฝฅวฅะฅคฅนควคโคขค๊คคปค๓" -#: ../fileio.c:2601 +msgid "writing to device disabled with 'opendevice' option" +msgstr "'opendevice' ฅชฅืฅทฅ็ฅ๓คหค่ค๊ฅวฅะฅคฅนคุคฮฝ๑คญนค฿คฯควคญคคปค๓" + msgid "is read-only (add ! to override)" msgstr "คฯฦษนภ์อัควคน (ถฏภฉฝ๑นคหคฯ ! ค๒ฤษฒร)" -#: ../fileio.c:2886 msgid "E506: Can't write to backup file (add ! to override)" msgstr "E506: ฅะฅรฅฏฅขฅรฅืฅีฅกฅคฅ๋ค๒สยธควคญคคปค๓ (! ค๒ฤษฒรควถฏภฉสยธ)" -#: ../fileio.c:2898 msgid "E507: Close error for backup file (add ! to override)" msgstr "" "E507: ฅะฅรฅฏฅขฅรฅืฅีฅกฅคฅ๋ค๒สฤคธค๋บคหฅจฅ้กผคฌศฏภธคทคคทคฟ (! ค๒ฤษฒรควถฏภฉ)" -#: ../fileio.c:2901 msgid "E508: Can't read file for backup (add ! to override)" msgstr "E508: ฅะฅรฅฏฅขฅรฅือัฅีฅกฅคฅ๋ค๒ฦษนคแคคปค๓ (! ค๒ฤษฒรควถฏภฉฦษน)" -#: ../fileio.c:2923 msgid "E509: Cannot create backup file (add ! to override)" msgstr "E509: ฅะฅรฅฏฅขฅรฅืฅีฅกฅคฅ๋ค๒บ๎ค์คคปค๓ (! ค๒ฤษฒรควถฏภฉบ๎ภฎ)" -#: ../fileio.c:3008 msgid "E510: Can't make backup file (add ! to override)" msgstr "E510: ฅะฅรฅฏฅขฅรฅืฅีฅกฅคฅ๋ค๒บ๎ค์คคปค๓ (! ค๒ฤษฒรควถฏภฉบ๎ภฎ)" -#. Can't write without a tempfile! -#: ../fileio.c:3121 +msgid "E460: The resource fork would be lost (add ! to override)" +msgstr "E460: ฅ๊ฅฝกผฅนฅีฅฉกผฅฏคฌผบค๏ค์ค๋คซคโคทค์คคปค๓ (! ค๒ฤษฒรควถฏภฉ)" + msgid "E214: Can't find temp file for writing" msgstr "E214: สยธอัฐ์ปฅีฅกฅคฅ๋คฌธซคฤคซค๊คคปค๓" -#: ../fileio.c:3134 msgid "E213: Cannot convert (add ! to write without conversion)" msgstr "E213: สัดนควคญคคปค๓ (! ค๒ฤษฒรควสัดนคปคบคหสยธ)" -#: ../fileio.c:3169 msgid "E166: Can't open linked file for writing" msgstr "E166: ฅ๊ฅ๓ฅฏคตค์คฟฅีฅกฅคฅ๋คหฝ๑นคแคคปค๓" -#: ../fileio.c:3173 msgid "E212: Can't open file for writing" msgstr "E212: ฝ๑นค฿อัคหฅีฅกฅคฅ๋ค๒ณซคฑคคปค๓" -#: ../fileio.c:3363 msgid "E667: Fsync failed" msgstr "E667: fsync คหผบวิคทคคทคฟ" -#: ../fileio.c:3398 msgid "E512: Close failed" msgstr "E512: สฤคธค๋คณคศคหผบวิ" -#: ../fileio.c:3436 msgid "E513: write error, conversion failed (make 'fenc' empty to override)" msgstr "E513: ฝ๑นค฿ฅจฅ้กผ, สัดนผบวิ (พๅฝ๑คนค๋คหคฯ 'fenc' ค๒ถ๕คหคทคฦคฏคภคตคค)" -#: ../fileio.c:3441 #, c-format msgid "" -"E513: write error, conversion failed in line %<PRId64> (make 'fenc' empty to " +"E513: write error, conversion failed in line %ld (make 'fenc' empty to " "override)" msgstr "" -"E513: ฝ๑นค฿ฅจฅ้กผ, สัดนผบวิ, นิฟ๔ %<PRId64> (พๅฝ๑คนค๋คหคฯ 'fenc' ค๒ถ๕คหคทคฦ" -"คฏคภคตคค)" +"E513: ฝ๑นค฿ฅจฅ้กผ, สัดนผบวิ, นิฟ๔ %ld (พๅฝ๑คนค๋คหคฯ 'fenc' ค๒ถ๕คหคทคฦคฏคภคต" +"คค)" -#: ../fileio.c:3448 msgid "E514: write error (file system full?)" msgstr "E514: ฝ๑นค฿ฅจฅ้กผ, (ฅีฅกฅคฅ๋ฅทฅนฅฦฅเคฌหวี?)" -#: ../fileio.c:3506 msgid " CONVERSION ERROR" msgstr " สัดนฅจฅ้กผ" -#: ../fileio.c:3509 #, c-format -msgid " in line %<PRId64>;" -msgstr " นิ %<PRId64>;" +msgid " in line %ld;" +msgstr " นิ %ld;" -#: ../fileio.c:3519 msgid "[Device]" msgstr "[ฅวฅะฅคฅน]" -#: ../fileio.c:3522 msgid "[New]" msgstr "[ฟท]" -#: ../fileio.c:3535 msgid " [a]" msgstr " [a]" -#: ../fileio.c:3535 msgid " appended" msgstr " ฤษฒร" -#: ../fileio.c:3537 msgid " [w]" msgstr " [w]" -#: ../fileio.c:3537 msgid " written" msgstr " ฝ๑นค฿" -#: ../fileio.c:3579 msgid "E205: Patchmode: can't save original file" msgstr "E205: patchmode: ธถหฅีฅกฅคฅ๋ค๒สยธควคญคคปค๓" -#: ../fileio.c:3602 msgid "E206: patchmode: can't touch empty original file" msgstr "E206: patchmode: ถ๕คฮธถหฅีฅกฅคฅ๋ค๒touchควคญคคปค๓" -#: ../fileio.c:3616 msgid "E207: Can't delete backup file" msgstr "E207: ฅะฅรฅฏฅขฅรฅืฅีฅกฅคฅ๋ค๒พรคปคคปค๓" -#: ../fileio.c:3672 msgid "" "\n" "WARNING: Original file may be lost or damaged\n" @@ -2290,134 +1838,105 @@ msgstr "" "\n" "ทูน๐: ธถหฅีฅกฅคฅ๋คฌผบค๏ค์คฟคซสันนคตค์คคทคฟ\n" -#: ../fileio.c:3675 msgid "don't quit the editor until the file is successfully written!" msgstr "ฅีฅกฅคฅ๋คฮสยธคหภฎธ๙คนค๋คควฅจฅวฅฃฅฟค๒ฝชฮปคทคสคคควคฏคภคตคค!" -#: ../fileio.c:3795 msgid "[dos]" msgstr "[dos]" -#: ../fileio.c:3795 msgid "[dos format]" msgstr "[dosฅีฅฉกผฅฅรฅศ]" -#: ../fileio.c:3801 msgid "[mac]" msgstr "[mac]" -#: ../fileio.c:3801 msgid "[mac format]" msgstr "[macฅีฅฉกผฅฅรฅศ]" -#: ../fileio.c:3807 msgid "[unix]" msgstr "[unix]" -#: ../fileio.c:3807 msgid "[unix format]" msgstr "[unixฅีฅฉกผฅฅรฅศ]" -#: ../fileio.c:3831 msgid "1 line, " msgstr "1 นิ, " -#: ../fileio.c:3833 #, c-format -msgid "%<PRId64> lines, " -msgstr "%<PRId64> นิ, " +msgid "%ld lines, " +msgstr "%ld นิ, " -#: ../fileio.c:3836 msgid "1 character" msgstr "1 สธป๚" -#: ../fileio.c:3838 #, c-format -msgid "%<PRId64> characters" -msgstr "%<PRId64> สธป๚" +msgid "%lld characters" +msgstr "%lld สธป๚" -#: ../fileio.c:3849 msgid "[noeol]" msgstr "[noeol]" -#: ../fileio.c:3849 msgid "[Incomplete last line]" msgstr "[บวฝชนิคฌษิดฐมด]" #. don't overwrite messages here #. must give this prompt #. don't use emsg() here, don't want to flush the buffers -#: ../fileio.c:3865 msgid "WARNING: The file has been changed since reading it!!!" msgstr "ทูน๐: ฦษนค๓คภธๅคหฅีฅกฅคฅ๋คหสันนคฌคขค๊คคทคฟ!!!" -#: ../fileio.c:3867 msgid "Do you really want to write to it" msgstr "หล๖คหพๅฝ๑คญคทคคนคซ" -#: ../fileio.c:4648 #, c-format msgid "E208: Error writing to \"%s\"" msgstr "E208: \"%s\" ค๒ฝ๑นค฿รๆคฮฅจฅ้กผควคน" -#: ../fileio.c:4655 #, c-format msgid "E209: Error closing \"%s\"" msgstr "E209: \"%s\" ค๒สฤคธค๋ปคหฅจฅ้กผควคน" -#: ../fileio.c:4657 #, c-format msgid "E210: Error reading \"%s\"" msgstr "E210: \"%s\" ค๒ฦษนรๆคฮฅจฅ้กผควคน" -#: ../fileio.c:4883 msgid "E246: FileChangedShell autocommand deleted buffer" msgstr "E246: autocommand คฮ FileChangedShell คฌฅะฅรฅีฅกค๒บ๏ฝคทคคทคฟ" -#: ../fileio.c:4894 #, c-format msgid "E211: File \"%s\" no longer available" msgstr "E211: ฅีฅกฅคฅ๋ \"%s\" คฯด๛คหยธบ฿คทคคปค๓" -#: ../fileio.c:4906 #, c-format msgid "" "W12: Warning: File \"%s\" has changed and the buffer was changed in Vim as " "well" msgstr "W12: ทูน๐: ฅีฅกฅคฅ๋ \"%s\" คฌสันนคตค์Vimคฮฅะฅรฅีฅกคโสันนคตค์คคทคฟ" -#: ../fileio.c:4907 msgid "See \":help W12\" for more info." msgstr "พบูคฯ \":help W12\" ค๒ปฒพศคทคฦคฏคภคตคค" -#: ../fileio.c:4910 #, c-format msgid "W11: Warning: File \"%s\" has changed since editing started" msgstr "W11: ทูน๐: ฅีฅกฅคฅ๋ \"%s\" คฯสิฝธณซปฯธๅคหสันนคตค์คคทคฟ" -#: ../fileio.c:4911 msgid "See \":help W11\" for more info." msgstr "พบูคฯ \":help W11\" ค๒ปฒพศคทคฦคฏคภคตคค" -#: ../fileio.c:4914 #, c-format msgid "W16: Warning: Mode of file \"%s\" has changed since editing started" msgstr "W16: ทูน๐: ฅีฅกฅคฅ๋ \"%s\" คฮฅโกผฅษคฌสิฝธณซปฯธๅคหสันนคตค์คคทคฟ" -#: ../fileio.c:4915 msgid "See \":help W16\" for more info." msgstr "พบูคฯ \":help W16\" ค๒ปฒพศคทคฦคฏคภคตคค" -#: ../fileio.c:4927 #, c-format msgid "W13: Warning: File \"%s\" has been created after editing started" msgstr "W13: ทูน๐: ฅีฅกฅคฅ๋ \"%s\" คฯสิฝธณซปฯธๅคหบ๎ภฎคตค์คคทคฟ" -#: ../fileio.c:4947 msgid "Warning" msgstr "ทูน๐" -#: ../fileio.c:4948 msgid "" "&OK\n" "&Load File" @@ -2425,48 +1944,45 @@ msgstr "" "&OK\n" "ฅีฅกฅคฅ๋ฦษน(&L)" -#: ../fileio.c:5065 #, c-format msgid "E462: Could not prepare for reloading \"%s\"" msgstr "E462: \"%s\" ค๒ฅ๊ฅํกผฅษคนค๋ฝเศ๗คฌควคญคคปค๓ควคทคฟ" -#: ../fileio.c:5078 #, c-format msgid "E321: Could not reload \"%s\"" msgstr "E321: \"%s\" คฯฅ๊ฅํกผฅษควคญคคปค๓ควคทคฟ" -#: ../fileio.c:5601 msgid "--Deleted--" msgstr "--บ๏ฝบั--" -#: ../fileio.c:5732 #, c-format msgid "auto-removing autocommand: %s <buffer=%d>" msgstr "autocommand: %s <ฅะฅรฅีฅก=%d> คฌผซฦฐลชคหบ๏ฝคตค์คคน" #. the group doesn't exist -#: ../fileio.c:5772 #, c-format msgid "E367: No such group: \"%s\"" msgstr "E367: คฝคฮฅฐฅ๋กผฅืคฯคขค๊คคปค๓: \"%s\"" -#: ../fileio.c:5897 +msgid "E936: Cannot delete the current group" +msgstr "E936: ธฝบ฿คฮฅฐฅ๋กผฅืคฯบ๏ฝควคญคคปค๓" + +msgid "W19: Deleting augroup that is still in use" +msgstr "W19: ปศอัรๆคฮ augroup ค๒พรคฝคฆคศคทคฦคคคคน" + #, c-format msgid "E215: Illegal character after *: %s" msgstr "E215: * คฮธๅคหษิภตคสสธป๚คฌคขค๊คคทคฟ: %s" -#: ../fileio.c:5905 #, c-format msgid "E216: No such event: %s" msgstr "E216: คฝคฮค่คฆคสฅคฅูฅ๓ฅศคฯคขค๊คคปค๓: %s" -#: ../fileio.c:5907 #, c-format msgid "E216: No such group or event: %s" msgstr "E216: คฝคฮค่คฆคสฅฐฅ๋กผฅืคโคทคฏคฯฅคฅูฅ๓ฅศคฯคขค๊คคปค๓: %s" #. Highlight title -#: ../fileio.c:6090 msgid "" "\n" "--- Auto-Commands ---" @@ -2474,756 +1990,555 @@ msgstr "" "\n" "--- Auto-Commands ---" -#: ../fileio.c:6293 #, c-format msgid "E680: <buffer=%d>: invalid buffer number " msgstr "E680: <ฅะฅรฅีฅก=%d>: ฬตธ๚คสฅะฅรฅีฅกศึนๆควคน " -#: ../fileio.c:6370 msgid "E217: Can't execute autocommands for ALL events" msgstr "E217: มดคฦคฮฅคฅูฅ๓ฅศคหยะคทคฦคฮautocommandคฯผยนิควคญคคปค๓" -#: ../fileio.c:6393 msgid "No matching autocommands" msgstr "ณบล๖คนค๋autocommandคฯยธบ฿คทคคปค๓" -#: ../fileio.c:6831 msgid "E218: autocommand nesting too deep" msgstr "E218: autocommandคฮฦค์ปาคฌฟผฒแคฎคคน" -#: ../fileio.c:7143 #, c-format msgid "%s Auto commands for \"%s\"" msgstr "%s Auto commands for \"%s\"" -#: ../fileio.c:7149 #, c-format msgid "Executing %s" msgstr "%s ค๒ผยนิคทคฦคคคคน" -#: ../fileio.c:7211 #, c-format msgid "autocommand %s" msgstr "autocommand %s" -#: ../fileio.c:7795 msgid "E219: Missing {." msgstr "E219: { คฌคขค๊คคปค๓." -#: ../fileio.c:7797 msgid "E220: Missing }." msgstr "E220: } คฌคขค๊คคปค๓." -#: ../fold.c:93 msgid "E490: No fold found" msgstr "E490: ภพ๖ค฿คฌคขค๊คคปค๓" -#: ../fold.c:544 msgid "E350: Cannot create fold with current 'foldmethod'" msgstr "E350: ธฝบ฿คฮ 'foldmethod' ควคฯภพ๖ค฿ค๒บ๎ภฎควคญคคปค๓" -#: ../fold.c:546 msgid "E351: Cannot delete fold with current 'foldmethod'" msgstr "E351: ธฝบ฿คฮ 'foldmethod' ควคฯภพ๖ค฿ค๒บ๏ฝควคญคคปค๓" -#: ../fold.c:1784 #, c-format -msgid "+--%3ld lines folded " -msgstr "+--%3ld นิคฌภพ๖คค์คคทคฟ " +msgid "+--%3ld line folded " +msgid_plural "+--%3ld lines folded " +msgstr[0] "+--%3ld นิคฌภพ๖คค์คคทคฟ " -#. buffer has already been read -#: ../getchar.c:273 msgid "E222: Add to read buffer" msgstr "E222: ฦษนฅะฅรฅีฅกคุฤษฒร" -#: ../getchar.c:2040 msgid "E223: recursive mapping" msgstr "E223: บฦตขลชฅฅรฅิฅ๓ฅฐ" -#: ../getchar.c:2849 #, c-format msgid "E224: global abbreviation already exists for %s" msgstr "E224: %s คศคคคฆฅฐฅํกผฅะฅ๋รปฝฬฦฮฯคฯด๛คหยธบ฿คทคคน" -#: ../getchar.c:2852 #, c-format msgid "E225: global mapping already exists for %s" msgstr "E225: %s คศคคคฆฅฐฅํกผฅะฅ๋ฅฅรฅิฅ๓ฅฐคฯด๛คหยธบ฿คทคคน" -#: ../getchar.c:2952 #, c-format msgid "E226: abbreviation already exists for %s" msgstr "E226: %s คศคคคฆรปฝฬฦฮฯคฯด๛คหยธบ฿คทคคน" -#: ../getchar.c:2955 #, c-format msgid "E227: mapping already exists for %s" msgstr "E227: %s คศคคคฆฅฅรฅิฅ๓ฅฐคฯด๛คหยธบ฿คทคคน" -#: ../getchar.c:3008 msgid "No abbreviation found" msgstr "รปฝฬฦฮฯคฯธซคฤคซค๊คคปค๓ควคทคฟ" -#: ../getchar.c:3010 msgid "No mapping found" msgstr "ฅฅรฅิฅ๓ฅฐคฯธซคฤคซค๊คคปค๓ควคทคฟ" -#: ../getchar.c:3974 msgid "E228: makemap: Illegal mode" msgstr "E228: makemap: ษิภตคสฅโกผฅษ" -#. key value of 'cedit' option -#. type of cmdline window or 0 -#. result of cmdline window or 0 -#: ../globals.h:924 -msgid "--No lines in buffer--" -msgstr "--ฅะฅรฅีฅกคหนิคฌคขค๊คคปค๓--" +msgid "E851: Failed to create a new process for the GUI" +msgstr "E851: GUIอัคฮฅืฅํฅปฅนคฮตฏฦฐคหผบวิคทคคทคฟ" -#. -#. * The error messages that can be shared are included here. -#. * Excluded are errors that are only used once and debugging messages. -#. -#: ../globals.h:996 -msgid "E470: Command aborted" -msgstr "E470: ฅณฅฅ๓ฅษคฌรๆรวคตค์คคทคฟ" +msgid "E852: The child process failed to start the GUI" +msgstr "E852: ปาฅืฅํฅปฅนคฌGUIคฮตฏฦฐคหผบวิคทคคทคฟ" -#: ../globals.h:997 -msgid "E471: Argument required" -msgstr "E471: ฐ๚ฟ๔คฌษฌอืควคน" +msgid "E229: Cannot start the GUI" +msgstr "E229: GUIค๒ณซปฯควคญคคปค๓" -#: ../globals.h:998 -msgid "E10: \\ should be followed by /, ? or &" -msgstr "E10: \\ คฮธๅคฯ / คซ ? คซ & ควคสคฑค์คะคสค๊คคปค๓" +#, c-format +msgid "E230: Cannot read from \"%s\"" +msgstr "E230: \"%s\"คซค้ฦษนคเคณคศคฌควคญคคปค๓" -#: ../globals.h:1000 -msgid "E11: Invalid in command-line window; <CR> executes, CTRL-C quits" -msgstr "E11: ฅณฅฅ๓ฅษฅ้ฅคฅ๓ควคฯฬตธ๚ควคน; <CR>ควผยนิ, CTRL-Cควคไคแค๋" +msgid "E665: Cannot start GUI, no valid font found" +msgstr "E665: อญธ๚คสฅีฅฉฅ๓ฅศคฌธซคฤคซค้คสคคคฮคว, GUIค๒ณซปฯควคญคคปค๓" -#: ../globals.h:1002 -msgid "E12: Command not allowed from exrc/vimrc in current dir or tag search" -msgstr "" -"E12: ธฝบ฿คฮฅวฅฃฅ์ฅฏฅศฅ๊คไฅฟฅฐธกบ๗ควคฯexrc/vimrcคฮฅณฅฅ๓ฅษคฯต๖ฒฤคตค์คคปค๓" +msgid "E231: 'guifontwide' invalid" +msgstr "E231: 'guifontwide' คฌฬตธ๚ควคน" -#: ../globals.h:1003 -msgid "E171: Missing :endif" -msgstr "E171: :endif คฌคขค๊คคปค๓" +msgid "E599: Value of 'imactivatekey' is invalid" +msgstr "E599: 'imactivatekey' คหภ฿ฤ๊คตค์คฟรอคฌฬตธ๚ควคน" -#: ../globals.h:1004 -msgid "E600: Missing :endtry" -msgstr "E600: :endtry คฌคขค๊คคปค๓" +#, c-format +msgid "E254: Cannot allocate color %s" +msgstr "E254: %s คฮฟงค๒ณไค๊ล๖คฦค้ค์คคปค๓" -#: ../globals.h:1005 -msgid "E170: Missing :endwhile" -msgstr "E170: :endwhile คฌคขค๊คคปค๓" +msgid "No match at cursor, finding next" +msgstr "ฅซกผฅฝฅ๋คฮฐฬรึคหฅฅรฅมคฯคขค๊คคปค๓, ผกค๒ธกบ๗คทคฦคคคคน" -#: ../globals.h:1006 -msgid "E170: Missing :endfor" -msgstr "E170: :endfor คฌคขค๊คคปค๓" - -#: ../globals.h:1007 -msgid "E588: :endwhile without :while" -msgstr "E588: :while คฮคสคค :endwhile คฌคขค๊คคน" +msgid "<cannot open> " +msgstr "<ณซคฑคคปค๓> " -#: ../globals.h:1008 -msgid "E588: :endfor without :for" -msgstr "E588: :endfor คฮคสคค :for คฌคขค๊คคน" +#, c-format +msgid "E616: vim_SelFile: can't get font %s" +msgstr "E616: vim_SelFile: ฅีฅฉฅ๓ฅศ %s ค๒ผ่ฦภควคญคคปค๓" -#: ../globals.h:1009 -msgid "E13: File exists (add ! to override)" -msgstr "E13: ฅีฅกฅคฅ๋คฌยธบ฿คทคคน (! ค๒ฤษฒรควพๅฝ๑)" +msgid "E614: vim_SelFile: can't return to current directory" +msgstr "E614: vim_SelFile: ธฝบ฿คฮฅวฅฃฅ์ฅฏฅศฅ๊คหฬแค์คคปค๓" -#: ../globals.h:1010 -msgid "E472: Command failed" -msgstr "E472: ฅณฅฅ๓ฅษคฌผบวิคทคคทคฟ" +msgid "Pathname:" +msgstr "ฅัฅนฬพ:" -#: ../globals.h:1011 -msgid "E473: Internal error" -msgstr "E473: ฦโษ๔ฅจฅ้กผควคน" +msgid "E615: vim_SelFile: can't get current directory" +msgstr "E615: vim_SelFile: ธฝบ฿คฮฅวฅฃฅ์ฅฏฅศฅ๊ค๒ผ่ฦภควคญคคปค๓" -#: ../globals.h:1012 -msgid "Interrupted" -msgstr "ณไนคค์คคทคฟ" +msgid "OK" +msgstr "OK" -#: ../globals.h:1013 -msgid "E14: Invalid address" -msgstr "E14: ฬตธ๚คสฅขฅษฅ์ฅนควคน" +msgid "Cancel" +msgstr "ฅญฅใฅ๓ฅปฅ๋" -#: ../globals.h:1014 -msgid "E474: Invalid argument" -msgstr "E474: ฬตธ๚คสฐ๚ฟ๔ควคน" +msgid "Scrollbar Widget: Could not get geometry of thumb pixmap." +msgstr "ฅนฅฏฅํกผฅ๋ฅะกผ: ฒ่มค๒ผ่ฦภควคญคคปค๓ควคทคฟ." -#: ../globals.h:1015 -#, c-format -msgid "E475: Invalid argument: %s" -msgstr "E475: ฬตธ๚คสฐ๚ฟ๔ควคน: %s" +msgid "Vim dialog" +msgstr "Vim ฅภฅคฅขฅํฅฐ" -#: ../globals.h:1016 -#, c-format -msgid "E15: Invalid expression: %s" -msgstr "E15: ฬตธ๚คสผฐควคน: %s" +msgid "E232: Cannot create BalloonEval with both message and callback" +msgstr "E232: ฅแฅรฅปกผฅธคศฅณกผฅ๋ฅะฅรฅฏคฮคขค๋ BalloonEval ค๒บ๎ภฎควคญคคปค๓" -#: ../globals.h:1017 -msgid "E16: Invalid range" -msgstr "E16: ฬตธ๚คสศฯฐฯควคน" +msgid "_Cancel" +msgstr "ฅญฅใฅ๓ฅปฅ๋(_C)" -#: ../globals.h:1018 -msgid "E476: Invalid command" -msgstr "E476: ฬตธ๚คสฅณฅฅ๓ฅษควคน" +msgid "_Save" +msgstr "สยธ(_S)" -#: ../globals.h:1019 -#, c-format -msgid "E17: \"%s\" is a directory" -msgstr "E17: \"%s\" คฯฅวฅฃฅ์ฅฏฅศฅ๊ควคน" +msgid "_Open" +msgstr "ณซคฏ(_O)" -#: ../globals.h:1020 -#, fuzzy -msgid "E900: Invalid job id" -msgstr "E49: ฬตธ๚คสฅนฅฏฅํกผฅ๋ฮฬควคน" +msgid "_OK" +msgstr "_OK" -#: ../globals.h:1021 -msgid "E901: Job table is full" +msgid "" +"&Yes\n" +"&No\n" +"&Cancel" msgstr "" +"คฯคค(&Y)\n" +"คคคคคจ(&N)\n" +"ฅญฅใฅ๓ฅปฅ๋(&C)" -#: ../globals.h:1024 -#, c-format -msgid "E364: Library call failed for \"%s()\"" -msgstr "E364: \"%s\"() คฮฅ้ฅคฅึฅ้ฅ๊ธฦฝะคหผบวิคทคคทคฟ" +msgid "Yes" +msgstr "คฯคค" -#: ../globals.h:1026 -msgid "E19: Mark has invalid line number" -msgstr "E19: ฅกผฅฏคหฬตธ๚คสนิศึนๆคฌปุฤ๊คตค์คฦคคคคทคฟ" +msgid "No" +msgstr "คคคคคจ" -#: ../globals.h:1027 -msgid "E20: Mark not set" -msgstr "E20: ฅกผฅฏคฯภ฿ฤ๊คตค์คฦคคคคปค๓" +msgid "Input _Methods" +msgstr "ฅคฅ๓ฅืฅรฅศฅแฅฝฅรฅษ" -#: ../globals.h:1029 -msgid "E21: Cannot make changes, 'modifiable' is off" -msgstr "E21: 'modifiable' คฌฅชฅีคสคฮคว, สันนควคญคคปค๓" +msgid "VIM - Search and Replace..." +msgstr "VIM - ธกบ๗คศรึดน..." -#: ../globals.h:1030 -msgid "E22: Scripts nested too deep" -msgstr "E22: ฅนฅฏฅ๊ฅืฅศคฮฦค์ปาคฌฟผฒแคฎคคน" +msgid "VIM - Search..." +msgstr "VIM - ธกบ๗..." -#: ../globals.h:1031 -msgid "E23: No alternate file" -msgstr "E23: ษ๛ฅีฅกฅคฅ๋คฯคขค๊คคปค๓" +msgid "Find what:" +msgstr "ธกบ๗สธป๚ฮ๓:" -#: ../globals.h:1032 -msgid "E24: No such abbreviation" -msgstr "E24: คฝคฮค่คฆคสรปฝฬฦฮฯคฯคขค๊คคปค๓" +msgid "Replace with:" +msgstr "รึดนสธป๚ฮ๓:" -#: ../globals.h:1033 -msgid "E477: No ! allowed" -msgstr "E477: ! คฯต๖ฒฤคตค์คฦคคคคปค๓" +#. whole word only button +msgid "Match whole word only" +msgstr "ภตณฮคหณบล๖คนค๋คโคฮคภคฑ" -#: ../globals.h:1035 -msgid "E25: Nvim does not have a built-in GUI" -msgstr "E25: GUIคฯปศอัษิฒฤวฝควคน: ฅณฅ๓ฅัฅคฅ๋ปคหฬตธ๚คหคตค์คฦคคคคน" +#. match case button +msgid "Match case" +msgstr "ย็สธป๚/พฎสธป๚ค๒ถ่สฬคนค๋" -#: ../globals.h:1036 -#, c-format -msgid "E28: No such highlight group name: %s" -msgstr "E28: คฝคฮค่คฆคสฬพคฮฅฯฅคฅ้ฅคฅศฅฐฅ๋กผฅืคฯคขค๊คคปค๓: %s" +msgid "Direction" +msgstr "สธ" -#: ../globals.h:1037 -msgid "E29: No inserted text yet" -msgstr "E29: คคภฅฦฅญฅนฅศคฌมฦคตค์คฦคคคคปค๓" +#. 'Up' and 'Down' buttons +msgid "Up" +msgstr "พๅ" -#: ../globals.h:1038 -msgid "E30: No previous command line" -msgstr "E30: ฐสมฐคหฅณฅฅ๓ฅษนิคฌคขค๊คคปค๓" +msgid "Down" +msgstr "ฒผ" -#: ../globals.h:1039 -msgid "E31: No such mapping" -msgstr "E31: คฝคฮค่คฆคสฅฅรฅิฅ๓ฅฐคฯคขค๊คคปค๓" +msgid "Find Next" +msgstr "ผกค๒ธกบ๗" -#: ../globals.h:1040 -msgid "E479: No match" -msgstr "E479: ณบล๖คฯคขค๊คคปค๓" +msgid "Replace" +msgstr "รึดน" -#: ../globals.h:1041 -#, c-format -msgid "E480: No match: %s" -msgstr "E480: ณบล๖คฯคขค๊คคปค๓: %s" +msgid "Replace All" +msgstr "มดคฦรึดน" -#: ../globals.h:1042 -msgid "E32: No file name" -msgstr "E32: ฅีฅกฅคฅ๋ฬพคฌคขค๊คคปค๓" +msgid "_Close" +msgstr "สฤคธค๋(_C)" -#: ../globals.h:1044 -msgid "E33: No previous substitute regular expression" -msgstr "E33: ภตตฌษฝธฝรึดนคฌคคภผยนิคตค์คฦคคคคปค๓" +msgid "Vim: Received \"die\" request from session manager\n" +msgstr "Vim: ฅปฅรฅทฅ็ฅ๓ฅฅอกผฅธฅใคซค้ \"die\" อืตแค๒ผ๕คฑผ่ค๊คคทคฟ\n" -#: ../globals.h:1045 -msgid "E34: No previous command" -msgstr "E34: ฅณฅฅ๓ฅษคฌคคภผยนิคตค์คฦคคคคปค๓" +msgid "Close tab" +msgstr "ฅฟฅึฅฺกผฅธค๒สฤคธค๋" -#: ../globals.h:1046 -msgid "E35: No previous regular expression" -msgstr "E35: ภตตฌษฝธฝคฌคคภผยนิคตค์คฦคคคคปค๓" +msgid "New tab" +msgstr "ฟทตฌฅฟฅึฅฺกผฅธ" -#: ../globals.h:1047 -msgid "E481: No range allowed" -msgstr "E481: ศฯฐฯปุฤ๊คฯต๖ฒฤคตค์คฦคคคคปค๓" +msgid "Open Tab..." +msgstr "ฅฟฅึฅฺกผฅธค๒ณซคฏ..." -#: ../globals.h:1048 -msgid "E36: Not enough room" -msgstr "E36: ฅฆฅฃฅ๓ฅษฅฆคหฝฝสฌคสนโคตคโคทคฏคฯษคฌคขค๊คคปค๓" +msgid "Vim: Main window unexpectedly destroyed\n" +msgstr "Vim: ฅแฅคฅ๓ฅฆฅฃฅ๓ฅษฅฆคฌษิฐีคหวหฒ๕คตค์คคทคฟ\n" -#: ../globals.h:1049 -#, c-format -msgid "E482: Can't create file %s" -msgstr "E482: ฅีฅกฅคฅ๋ %s ค๒บ๎ภฎควคญคคปค๓" +msgid "&Filter" +msgstr "ฅีฅฃฅ๋ฅฟ(&F)" -#: ../globals.h:1050 -msgid "E483: Can't get temp file name" -msgstr "E483: ฐ์ปฅีฅกฅคฅ๋คฮฬพมฐค๒ผ่ฦภควคญคคปค๓" +msgid "&Cancel" +msgstr "ฅญฅใฅ๓ฅปฅ๋(&C)" -#: ../globals.h:1051 -#, c-format -msgid "E484: Can't open file %s" -msgstr "E484: ฅีฅกฅคฅ๋ \"%s\" ค๒ณซคฑคคปค๓" +msgid "Directories" +msgstr "ฅวฅฃฅ์ฅฏฅศฅ๊" -#: ../globals.h:1052 -#, c-format -msgid "E485: Can't read file %s" -msgstr "E485: ฅีฅกฅคฅ๋ %s ค๒ฦษนคแคคปค๓" +msgid "Filter" +msgstr "ฅีฅฃฅ๋ฅฟ" -#: ../globals.h:1054 -msgid "E37: No write since last change (add ! to override)" -msgstr "E37: บวธๅคฮสันนคฌสยธคตค์คฦคคคคปค๓ (! ค๒ฤษฒรควสันนค๒วหด)" +msgid "&Help" +msgstr "ฅุฅ๋ฅื(&H)" -#: ../globals.h:1055 -msgid "E37: No write since last change" -msgstr "E37: บวธๅคฮสันนคฌสยธคตค์คฦคคคคปค๓" +msgid "Files" +msgstr "ฅีฅกฅคฅ๋" -#: ../globals.h:1056 -msgid "E38: Null argument" -msgstr "E38: ฐ๚ฟ๔คฌถ๕ควคน" +msgid "&OK" +msgstr "&OK" -#: ../globals.h:1057 -msgid "E39: Number expected" -msgstr "E39: ฟ๔รอคฌอืตแคตค์คฦคคคคน" +msgid "Selection" +msgstr "มชย๒" -#: ../globals.h:1058 -#, c-format -msgid "E40: Can't open errorfile %s" -msgstr "E40: ฅจฅ้กผฅีฅกฅคฅ๋ %s ค๒ณซคฑคคปค๓" +msgid "Find &Next" +msgstr "ผกค๒ธกบ๗(&N)" -#: ../globals.h:1059 -msgid "E41: Out of memory!" -msgstr "E41: ฅแฅโฅ๊คฌฟิคญฒฬคฦคคทคฟ!" +msgid "&Replace" +msgstr "รึดน(&R)" -#: ../globals.h:1060 -msgid "Pattern not found" -msgstr "ฅัฅฟกผฅ๓คฯธซคฤคซค๊คคปค๓ควคทคฟ" +msgid "Replace &All" +msgstr "มดคฦรึดน(&A)" -#: ../globals.h:1061 -#, c-format -msgid "E486: Pattern not found: %s" -msgstr "E486: ฅัฅฟกผฅ๓คฯธซคฤคซค๊คคปค๓ควคทคฟ: %s" +msgid "&Undo" +msgstr "ฅขฅ๓ฅษฅฅ(&U)" -#: ../globals.h:1062 -msgid "E487: Argument must be positive" -msgstr "E487: ฐ๚ฟ๔คฯภตคฮรอควคสคฑค์คะคสค๊คคปค๓" +msgid "Open tab..." +msgstr "ฅฟฅึฅฺกผฅธค๒ณซคฏ" -#: ../globals.h:1064 -msgid "E459: Cannot go back to previous directory" -msgstr "E459: มฐคฮฅวฅฃฅ์ฅฏฅศฅ๊คหฬแค์คคปค๓" +msgid "Find string (use '\\\\' to find a '\\')" +msgstr "ธกบ๗สธป๚ฮ๓ ('\\' ค๒ธกบ๗คนค๋คหคฯ '\\\\')" -#: ../globals.h:1066 -msgid "E42: No Errors" -msgstr "E42: ฅจฅ้กผคฯคขค๊คคปค๓" +msgid "Find & Replace (use '\\\\' to find a '\\')" +msgstr "ธกบ๗กฆรึดน ('\\' ค๒ธกบ๗คนค๋คหคฯ '\\\\')" -#: ../globals.h:1067 -msgid "E776: No location list" -msgstr "E776: ฅํฅฑกผฅทฅ็ฅ๓ฅ๊ฅนฅศคฯคขค๊คคปค๓" - -#: ../globals.h:1068 -msgid "E43: Damaged match string" -msgstr "E43: ณบล๖สธป๚ฮ๓คฌวหยปคทคฦคคคคน" +#. We fake this: Use a filter that doesn't select anything and a default +#. * file name that won't be used. +msgid "Not Used" +msgstr "ปศค๏ค์คคปค๓" -#: ../globals.h:1069 -msgid "E44: Corrupted regexp program" -msgstr "E44: ษิภตคสภตตฌษฝธฝฅืฅํฅฐฅ้ฅเควคน" +msgid "Directory\t*.nothing\n" +msgstr "ฅวฅฃฅ์ฅฏฅศฅ๊\t*.nothing\n" -#: ../globals.h:1071 -msgid "E45: 'readonly' option is set (add ! to override)" -msgstr "E45: 'readonly' ฅชฅืฅทฅ็ฅ๓คฌภ฿ฤ๊คตค์คฦคคคคน (! ค๒ฤษฒรควพๅฝ๑คญ)" - -#: ../globals.h:1073 #, c-format -msgid "E46: Cannot change read-only variable \"%s\"" -msgstr "E46: ฦษผ่ภ์อัสัฟ๔ \"%s\" คหคฯรอค๒ภ฿ฤ๊ควคญคคปค๓" +msgid "E671: Cannot find window title \"%s\"" +msgstr "E671: ฅฟฅคฅศฅ๋คฌ \"%s\" คฮฅฆฅฃฅ๓ฅษฅฆคฯธซคฤคซค๊คคปค๓" -#: ../globals.h:1075 #, c-format -msgid "E794: Cannot set variable in the sandbox: \"%s\"" -msgstr "E794: ฅตฅ๓ฅษฅฅรฅฏฅนควคฯสัฟ๔ \"%s\" คหรอค๒ภ฿ฤ๊ควคญคคปค๓" - -#: ../globals.h:1076 -msgid "E47: Error while reading errorfile" -msgstr "E47: ฅจฅ้กผฅีฅกฅคฅ๋คฮฦษนรๆคหฅจฅ้กผคฌศฏภธคทคคทคฟ" - -#: ../globals.h:1078 -msgid "E48: Not allowed in sandbox" -msgstr "E48: ฅตฅ๓ฅษฅฅรฅฏฅนควคฯต๖คตค์คคปค๓" - -#: ../globals.h:1080 -msgid "E523: Not allowed here" -msgstr "E523: คณคณควคฯต๖ฒฤคตค์คคปค๓" +msgid "E243: Argument not supported: \"-%s\"; Use the OLE version." +msgstr "E243: ฐ๚ฟ๔คฯฅตฅกผฅศคตค์คคปค๓: \"-%s\"; OLEศวค๒ปศอัคทคฦคฏคภคตคค." -#: ../globals.h:1082 -msgid "E359: Screen mode setting not supported" -msgstr "E359: ฅนฅฏฅ๊กผฅ๓ฅโกผฅษคฮภ฿ฤ๊คหคฯยะฑคทคฦคคคคปค๓" +msgid "E672: Unable to open window inside MDI application" +msgstr "E672: MDIฅขฅืฅ๊คฮรๆควคฯฅฆฅฃฅ๓ฅษฅฆค๒ณซคฑคคปค๓" -#: ../globals.h:1083 -msgid "E49: Invalid scroll size" -msgstr "E49: ฬตธ๚คสฅนฅฏฅํกผฅ๋ฮฬควคน" +msgid "Vim E458: Cannot allocate colormap entry, some colors may be incorrect" +msgstr "Vim E458: ฟงปุฤ๊คฌภตคทคฏคสคคคฮควฅจฅ๓ฅศฅ๊ค๒ณไค๊ล๖คฦค้ค์คคปค๓" -#: ../globals.h:1084 -msgid "E91: 'shell' option is empty" -msgstr "E91: 'shell' ฅชฅืฅทฅ็ฅ๓คฌถ๕ควคน" +#, c-format +msgid "E250: Fonts for the following charsets are missing in fontset %s:" +msgstr "E250: ฐสฒผคฮสธป๚ฅปฅรฅศคฮฅีฅฉฅ๓ฅศคฌคขค๊คคปค๓ %s:" -#: ../globals.h:1085 -msgid "E255: Couldn't read in sign data!" -msgstr "E255: sign คฮฅวกผฅฟค๒ฦษนคแคคปค๓ควคทคฟ" +#, c-format +msgid "E252: Fontset name: %s" +msgstr "E252: ฅีฅฉฅ๓ฅศฅปฅรฅศฬพ: %s" -#: ../globals.h:1086 -msgid "E72: Close error on swap file" -msgstr "E72: ฅนฅ๏ฅรฅืฅีฅกฅคฅ๋คฮฅฏฅํกผฅบปฅจฅ้กผควคน" +#, c-format +msgid "Font '%s' is not fixed-width" +msgstr "ฅีฅฉฅ๓ฅศ '%s' คฯธวฤ๊ษควคฯคขค๊คคปค๓" -#: ../globals.h:1087 -msgid "E73: tag stack empty" -msgstr "E73: ฅฟฅฐฅนฅฟฅรฅฏคฌถ๕ควคน" +#, c-format +msgid "E253: Fontset name: %s" +msgstr "E253: ฅีฅฉฅ๓ฅศฅปฅรฅศฬพ: %s" -#: ../globals.h:1088 -msgid "E74: Command too complex" -msgstr "E74: ฅณฅฅ๓ฅษคฌสฃปจฒแคฎคคน" +#, c-format +msgid "Font0: %s" +msgstr "ฅีฅฉฅ๓ฅศ0: %s" -#: ../globals.h:1089 -msgid "E75: Name too long" -msgstr "E75: ฬพมฐคฌฤนฒแคฎคคน" +#, c-format +msgid "Font1: %s" +msgstr "ฅีฅฉฅ๓ฅศ1: %s" -#: ../globals.h:1090 -msgid "E76: Too many [" -msgstr "E76: [ คฌยฟฒแคฎคคน" +#, c-format +msgid "Font%ld width is not twice that of font0" +msgstr "ฅีฅฉฅ๓ฅศ%ld คฮษคฌฅีฅฉฅ๓ฅศ0คฮ2วควคฯคขค๊คคปค๓" -#: ../globals.h:1091 -msgid "E77: Too many file names" -msgstr "E77: ฅีฅกฅคฅ๋ฬพคฌยฟฒแคฎคคน" +#, c-format +msgid "Font0 width: %ld" +msgstr "ฅีฅฉฅ๓ฅศ0คฮษ: %ld" -#: ../globals.h:1092 -msgid "E488: Trailing characters" -msgstr "E488: อพสฌคสสธป๚คฌธๅคํคหคขค๊คคน" +#, c-format +msgid "Font1 width: %ld" +msgstr "ฅีฅฉฅ๓ฅศ1คฮษ: %ld" -#: ../globals.h:1093 -msgid "E78: Unknown mark" -msgstr "E78: ฬครฮคฮฅกผฅฏ" +msgid "Invalid font specification" +msgstr "ฬตธ๚คสฅีฅฉฅ๓ฅศปุฤ๊ควคน" -#: ../globals.h:1094 -msgid "E79: Cannot expand wildcards" -msgstr "E79: ฅ๏ฅคฅ๋ฅษฅซกผฅษค๒ลธณซควคญคคปค๓" +msgid "&Dismiss" +msgstr "ตัฒผคนค๋(&D)" -#: ../globals.h:1096 -msgid "E591: 'winheight' cannot be smaller than 'winminheight'" -msgstr "E591: 'winheight' คฯ 'winminheight' ค่ค๊พฎคตคฏควคญคคปค๓" +msgid "no specific match" +msgstr "ฅฅรฅมคนค๋คโคฮคฌคขค๊คคปค๓" -#: ../globals.h:1098 -msgid "E592: 'winwidth' cannot be smaller than 'winminwidth'" -msgstr "E592: 'winwidth' คฯ 'winminwidth' ค่ค๊พฎคตคฏควคญคคปค๓" +msgid "Vim - Font Selector" +msgstr "Vim - ฅีฅฉฅ๓ฅศมชย๒" -#: ../globals.h:1099 -msgid "E80: Error while writing" -msgstr "E80: ฝ๑นค฿รๆคฮฅจฅ้กผ" +msgid "Name:" +msgstr "ฬพมฐ:" -#: ../globals.h:1100 -msgid "Zero count" -msgstr "ฅผฅํฅซฅฆฅ๓ฅศ" +#. create toggle button +msgid "Show size in Points" +msgstr "ฅตฅคฅบค๒ฅฅคฅ๓ฅศควษฝผจคนค๋" -#: ../globals.h:1101 -msgid "E81: Using <SID> not in a script context" -msgstr "E81: ฅนฅฏฅ๊ฅืฅศฐสณฐคว<SID>คฌปศค๏ค์คคทคฟ" +msgid "Encoding:" +msgstr "ฅจฅ๓ฅณกผฅษ:" -#: ../globals.h:1102 -#, c-format -msgid "E685: Internal error: %s" -msgstr "E685: ฦโษ๔ฅจฅ้กผควคน: %s" +msgid "Font:" +msgstr "ฅีฅฉฅ๓ฅศ:" -#: ../globals.h:1104 -msgid "E363: pattern uses more memory than 'maxmempattern'" -msgstr "E363: ฅัฅฟกผฅ๓คฌ 'maxmempattern' ฐสพๅคฮฅแฅโฅ๊ค๒ปศอัคทคคน" +msgid "Style:" +msgstr "ฅนฅฟฅคฅ๋:" -#: ../globals.h:1105 -msgid "E749: empty buffer" -msgstr "E749: ฅะฅรฅีฅกคฌถ๕ควคน" +msgid "Size:" +msgstr "ฅตฅคฅบ:" -#: ../globals.h:1108 -msgid "E682: Invalid search pattern or delimiter" -msgstr "E682: ธกบ๗ฅัฅฟกผฅ๓คซถ่ภฺค๊ตญนๆคฌษิภตควคน" +msgid "E256: Hangul automata ERROR" +msgstr "E256: ฅฯฅ๓ฅฐฅ๋ฅชกผฅศฅฅศฅ๓ฅจฅ้กผ" -#: ../globals.h:1109 -msgid "E139: File is loaded in another buffer" -msgstr "E139: ฦฑคธฬพมฐคฮฅีฅกฅคฅ๋คฌยพคฮฅะฅรฅีฅกควฦษนคค์คฦคคคคน" - -#: ../globals.h:1110 -#, c-format -msgid "E764: Option '%s' is not set" -msgstr "E764: ฅชฅืฅทฅ็ฅ๓ '%s' คฯภ฿ฤ๊คตค์คฦคคคคปค๓" - -#: ../globals.h:1111 -msgid "E850: Invalid register name" -msgstr "E850: ฬตธ๚คสฅ์ฅธฅนฅฟฬพควคน" - -#: ../globals.h:1114 -msgid "search hit TOP, continuing at BOTTOM" -msgstr "พๅคควธกบ๗คทคฟคฮควฒผคหฬแค๊คคน" - -#: ../globals.h:1115 -msgid "search hit BOTTOM, continuing at TOP" -msgstr "ฒผคควธกบ๗คทคฟคฮควพๅคหฬแค๊คคน" - -#: ../hardcopy.c:240 msgid "E550: Missing colon" msgstr "E550: ฅณฅํฅ๓คฌคขค๊คคปค๓" -#: ../hardcopy.c:252 msgid "E551: Illegal component" msgstr "E551: ษิภตคสนฝสธอืมวควคน" -#: ../hardcopy.c:259 msgid "E552: digit expected" msgstr "E552: ฟ๔รอคฌษฌอืควคน" -#: ../hardcopy.c:473 #, c-format msgid "Page %d" msgstr "%d ฅฺกผฅธ" -#: ../hardcopy.c:597 msgid "No text to be printed" msgstr "ฐ๕บคนค๋ฅฦฅญฅนฅศคฌคขค๊คคปค๓" -#: ../hardcopy.c:668 #, c-format msgid "Printing page %d (%d%%)" msgstr "ฐ๕บรๆ: ฅฺกผฅธ %d (%d%%)" -#: ../hardcopy.c:680 #, c-format msgid " Copy %d of %d" msgstr " ฅณฅิกผ %d (มด %d รๆ)" -#: ../hardcopy.c:733 #, c-format msgid "Printed: %s" msgstr "ฐ๕บคทคคทคฟ: %s" -#: ../hardcopy.c:740 msgid "Printing aborted" msgstr "ฐ๕บคฌรๆป฿คตค์คคทคฟ" -#: ../hardcopy.c:1365 msgid "E455: Error writing to PostScript output file" msgstr "E455: PostScriptฝะฮฯฅีฅกฅคฅ๋คฮฝ๑นค฿ฅจฅ้กผควคน" -#: ../hardcopy.c:1747 #, c-format msgid "E624: Can't open file \"%s\"" msgstr "E624: ฅีฅกฅคฅ๋ \"%s\" ค๒ณซคฑคคปค๓" -#: ../hardcopy.c:1756 ../hardcopy.c:2470 #, c-format msgid "E457: Can't read PostScript resource file \"%s\"" msgstr "E457: PostScriptคฮฅ๊ฅฝกผฅนฅีฅกฅคฅ๋ \"%s\" ค๒ฦษนคแคคปค๓" -#: ../hardcopy.c:1772 #, c-format msgid "E618: file \"%s\" is not a PostScript resource file" msgstr "E618: ฅีฅกฅคฅ๋ \"%s\" คฯ PostScript ฅ๊ฅฝกผฅนฅีฅกฅคฅ๋ควคฯคขค๊คคปค๓" -#: ../hardcopy.c:1788 ../hardcopy.c:1805 ../hardcopy.c:1844 #, c-format msgid "E619: file \"%s\" is not a supported PostScript resource file" msgstr "E619: ฅีฅกฅคฅ๋ \"%s\" คฯยะฑคทคฦคคคสคค PostScript ฅ๊ฅฝกผฅนฅีฅกฅคฅ๋ควคน" -#: ../hardcopy.c:1856 #, c-format msgid "E621: \"%s\" resource file has wrong version" msgstr "E621: ฅ๊ฅฝกผฅนฅีฅกฅคฅ๋ \"%s\" คฯฅะกผฅธฅ็ฅ๓คฌฐคสค๊คคน" -#: ../hardcopy.c:2225 msgid "E673: Incompatible multi-byte encoding and character set." msgstr "E673: ธ฿ดนภญคฮฬตคคฅฅ๋ฅมฅะฅคฅศฅจฅ๓ฅณกผฅวฅฃฅ๓ฅฐคศสธป๚ฅปฅรฅศควคน" -#: ../hardcopy.c:2238 msgid "E674: printmbcharset cannot be empty with multi-byte encoding." msgstr "E674: ฅฅ๋ฅมฅะฅคฅศฅจฅ๓ฅณกผฅวฅฃฅ๓ฅฐควคฯ printmbcharset ค๒ถ๕คหควคญคคปค๓" -#: ../hardcopy.c:2254 msgid "E675: No default font specified for multi-byte printing." msgstr "" "E675: ฅฅ๋ฅมฅะฅคฅศสธป๚ค๒ฐ๕บคนค๋คฟคแคฮฅวฅีฅฉฅ๋ฅศฅีฅฉฅ๓ฅศคฌปุฤ๊คตค์คฦคคคคปค๓" -#: ../hardcopy.c:2426 msgid "E324: Can't open PostScript output file" msgstr "E324: PostScriptฝะฮฯอัคฮฅีฅกฅคฅ๋ค๒ณซคฑคคปค๓" -#: ../hardcopy.c:2458 #, c-format msgid "E456: Can't open file \"%s\"" msgstr "E456: ฅีฅกฅคฅ๋ \"%s\" ค๒ณซคฑคคปค๓" -#: ../hardcopy.c:2583 msgid "E456: Can't find PostScript resource file \"prolog.ps\"" msgstr "E456: PostScriptคฮฅ๊ฅฝกผฅนฅีฅกฅคฅ๋ \"prolog.ps\" คฌธซคฤคซค๊คคปค๓" -#: ../hardcopy.c:2593 msgid "E456: Can't find PostScript resource file \"cidfont.ps\"" msgstr "E456: PostScriptคฮฅ๊ฅฝกผฅนฅีฅกฅคฅ๋ \"cidfont.ps\" คฌธซคฤคซค๊คคปค๓" -#: ../hardcopy.c:2622 ../hardcopy.c:2639 ../hardcopy.c:2665 #, c-format msgid "E456: Can't find PostScript resource file \"%s.ps\"" msgstr "E456: PostScriptคฮฅ๊ฅฝกผฅนฅีฅกฅคฅ๋ \"%s.ps\" คฌธซคฤคซค๊คคปค๓" -#: ../hardcopy.c:2654 #, c-format msgid "E620: Unable to convert to print encoding \"%s\"" msgstr "E620: ฐ๕บฅจฅ๓ฅณกผฅษ \"%s\" คุสัดนควคญคคปค๓" -#: ../hardcopy.c:2877 msgid "Sending to printer..." msgstr "ฅืฅ๊ฅ๓ฅฟคหม๗ฟฎรๆ..." -#: ../hardcopy.c:2881 msgid "E365: Failed to print PostScript file" msgstr "E365: PostScriptฅีฅกฅคฅ๋คฮฐ๕บคหผบวิคทคคทคฟ" -#: ../hardcopy.c:2883 msgid "Print job sent." msgstr "ฐ๕บฅธฅ็ฅึค๒ม๗ฟฎคทคคทคฟ." -#: ../if_cscope.c:85 msgid "Add a new database" msgstr "ฟทฅวกผฅฟฅูกผฅนค๒ฤษฒร" -#: ../if_cscope.c:87 msgid "Query for a pattern" msgstr "ฅัฅฟกผฅ๓คฮฅฏฅจฅ๊กผค๒ฤษฒร" -#: ../if_cscope.c:89 msgid "Show this message" msgstr "คณคฮฅแฅรฅปกผฅธค๒ษฝผจคนค๋" -#: ../if_cscope.c:91 msgid "Kill a connection" msgstr "ภยณค๒ฝชฮปคนค๋" -#: ../if_cscope.c:93 msgid "Reinit all connections" msgstr "มดคฦคฮภยณค๒บฦฝ้ดฒฝคนค๋" -#: ../if_cscope.c:95 msgid "Show connections" msgstr "ภยณค๒ษฝผจคนค๋" -#: ../if_cscope.c:101 #, c-format msgid "E560: Usage: cs[cope] %s" msgstr "E560: ปศอัสหก: cs[cope] %s" -#: ../if_cscope.c:225 msgid "This cscope command does not support splitting the window.\n" msgstr "คณคฮcscopeฅณฅฅ๓ฅษคฯสฌณไฅฆฅฃฅ๓ฅษฅฆควคฯฅตฅกผฅศคตค์คคปค๓.\n" -#: ../if_cscope.c:266 msgid "E562: Usage: cstag <ident>" msgstr "E562: ปศอัหก: cstag <ident>" -#: ../if_cscope.c:313 msgid "E257: cstag: tag not found" msgstr "E257: cstag: ฅฟฅฐคฌธซคฤคซค๊คคปค๓" -#: ../if_cscope.c:461 #, c-format msgid "E563: stat(%s) error: %d" msgstr "E563: stat(%s) ฅจฅ้กผ: %d" -#: ../if_cscope.c:551 +msgid "E563: stat error" +msgstr "E563: stat ฅจฅ้กผ" + #, c-format msgid "E564: %s is not a directory or a valid cscope database" msgstr "E564: %s คฯฅวฅฃฅ์ฅฏฅศฅ๊ตฺคำอญธ๚คสcscopeคฮฅวกผฅฟฅูกผฅนควคฯคขค๊คคปค๓" -#: ../if_cscope.c:566 #, c-format msgid "Added cscope database %s" msgstr "cscopeฅวกผฅฟฅูกผฅน %s ค๒ฤษฒร" -#: ../if_cscope.c:616 #, c-format -msgid "E262: error reading cscope connection %<PRId64>" -msgstr "E262: cscopeคฮภยณ %<PRId64> ค๒ฦษนค฿รๆคฮฅจฅ้กผควคน" +msgid "E262: error reading cscope connection %ld" +msgstr "E262: cscopeคฮภยณ %ld ค๒ฦษนค฿รๆคฮฅจฅ้กผควคน" -#: ../if_cscope.c:711 msgid "E561: unknown cscope search type" msgstr "E561: ฬครฮคฮcscopeธกบ๗ทฟควคน" -#: ../if_cscope.c:752 ../if_cscope.c:789 msgid "E566: Could not create cscope pipes" msgstr "E566: cscopeฅัฅคฅืค๒บ๎ภฎควคญคคปค๓ควคทคฟ" -#: ../if_cscope.c:767 msgid "E622: Could not fork for cscope" msgstr "E622: cscopeคฮตฏฦฐฝเศ๗(fork)คหผบวิคทคคทคฟ" -#: ../if_cscope.c:849 msgid "cs_create_connection setpgid failed" msgstr "cs_create_connection คุคฮ setpgid คหผบวิคทคคทคฟ" -#: ../if_cscope.c:853 ../if_cscope.c:889 msgid "cs_create_connection exec failed" msgstr "cs_create_connection คฮผยนิคหผบวิคทคคทคฟ" -#: ../if_cscope.c:863 ../if_cscope.c:902 msgid "cs_create_connection: fdopen for to_fp failed" msgstr "cs_create_connection: to_fp คฮ fdopen คหผบวิคทคคทคฟ" -#: ../if_cscope.c:865 ../if_cscope.c:906 msgid "cs_create_connection: fdopen for fr_fp failed" msgstr "cs_create_connection: fr_fp คฮ fdopen คหผบวิคทคคทคฟ" -#: ../if_cscope.c:890 msgid "E623: Could not spawn cscope process" msgstr "E623: cscopeฅืฅํฅปฅนค๒ตฏฦฐควคญคคปค๓ควคทคฟ" -#: ../if_cscope.c:932 msgid "E567: no cscope connections" msgstr "E567: cscopeภยณคหผบวิคทคคทคฟ" -#: ../if_cscope.c:1009 #, c-format msgid "E469: invalid cscopequickfix flag %c for %c" msgstr "E469: ฬตธ๚คส cscopequickfix ฅีฅ้ฅฐ %c คฮ %c ควคน" -#: ../if_cscope.c:1058 #, c-format msgid "E259: no matches found for cscope query %s of %s" msgstr "E259: cscopeฅฏฅจฅ๊กผ %s of %s คหณบล๖คฌคขค๊คคปค๓ควคทคฟ" -#: ../if_cscope.c:1142 msgid "cscope commands:\n" msgstr "cscopeฅณฅฅ๓ฅษ:\n" -#: ../if_cscope.c:1150 #, c-format msgid "%-5s: %s%*s (Usage: %s)" msgstr "%-5s: %s%*s (ปศอัหก: %s)" -#: ../if_cscope.c:1155 msgid "" "\n" +" a: Find assignments to this symbol\n" " c: Find functions calling this function\n" " d: Find functions called by this function\n" " e: Find this egrep pattern\n" @@ -3234,6 +2549,7 @@ msgid "" " t: Find this text string\n" msgstr "" "\n" +" a: คณคฮฅทฅ๓ฅฅ๋คหยะคนค๋ยๅฦค๒รตคน\n" " c: คณคฮดุฟ๔ค๒ธฦค๓ควคคค๋ดุฟ๔ค๒รตคน\n" " d: คณคฮดุฟ๔คซค้ธฦค๓ควคคค๋ดุฟ๔ค๒รตคน\n" " e: คณคฮegrepฅัฅฟกผฅ๓ค๒รตคน\n" @@ -3243,31 +2559,32 @@ msgstr "" " s: คณคฮCฅทฅ๓ฅฅ๋ค๒รตคน\n" " t: คณคฮฅฦฅญฅนฅศสธป๚ฮ๓ค๒รตคน\n" -#: ../if_cscope.c:1226 +#, c-format +msgid "E625: cannot open cscope database: %s" +msgstr "E625: cscopeฅวกผฅฟฅูกผฅน: %s ค๒ณซคฏคณคศคฌควคญคคปค๓" + +msgid "E626: cannot get cscope database information" +msgstr "E626: cscopeฅวกผฅฟฅูกผฅนคฮพ๐ส๓ค๒ผ่ฦภควคญคคปค๓" + msgid "E568: duplicate cscope database not added" msgstr "E568: ฝลสฃคนค๋cscopeฅวกผฅฟฅูกผฅนคฯฤษฒรคตค์คคปค๓ควคทคฟ" -#: ../if_cscope.c:1335 #, c-format msgid "E261: cscope connection %s not found" msgstr "E261: cscopeภยณ %s คฌธซคฤคซค๊คคปค๓ควคทคฟ" -#: ../if_cscope.c:1364 #, c-format msgid "cscope connection %s closed" msgstr "cscopeภยณ %s คฌสฤคธค้ค์คคทคฟ" #. should not reach here -#: ../if_cscope.c:1486 msgid "E570: fatal error in cs_manage_matches" msgstr "E570: cs_manage_matches ควรืฬฟลชคสฅจฅ้กผควคน" -#: ../if_cscope.c:1693 #, c-format msgid "Cscope tag: %s" msgstr "Cscope ฅฟฅฐ: %s" -#: ../if_cscope.c:1711 msgid "" "\n" " # line" @@ -3275,87 +2592,300 @@ msgstr "" "\n" " # นิศึนๆ" -#: ../if_cscope.c:1713 msgid "filename / context / line\n" msgstr "ฅีฅกฅคฅ๋ฬพ / สธฬฎ / นิ\n" -#: ../if_cscope.c:1809 #, c-format msgid "E609: Cscope error: %s" msgstr "E609: cscopeฅจฅ้กผ: %s" -#: ../if_cscope.c:2053 msgid "All cscope databases reset" msgstr "มดคฦคฮcscopeฅวกผฅฟฅูกผฅนค๒ฅ๊ฅปฅรฅศคทคคน" -#: ../if_cscope.c:2123 msgid "no cscope connections\n" msgstr "cscopeภยณคฌคขค๊คคปค๓\n" -#: ../if_cscope.c:2126 msgid " # pid database name prepend path\n" msgstr " # pid ฅวกผฅฟฅูกผฅนฬพ prepend ฅัฅน\n" -#: ../main.c:144 +msgid "Lua library cannot be loaded." +msgstr "Luaฅ้ฅคฅึฅ้ฅ๊ค๒ฅํกผฅษควคญคคปค๓." + +msgid "cannot save undo information" +msgstr "ฅขฅ๓ฅษฅฅพ๐ส๓คฌสยธควคญคคปค๓" + +msgid "" +"E815: Sorry, this command is disabled, the MzScheme libraries could not be " +"loaded." +msgstr "E815: คณคฮฅณฅฅ๓ฅษคฯฬตธ๚ควคน. MzScheme ฅ้ฅคฅึฅ้ฅ๊ค๒ฅํกผฅษควคญคคปค๓." + +msgid "" +"E895: Sorry, this command is disabled, the MzScheme's racket/base module " +"could not be loaded." +msgstr "" +"E895: คณคฮฅณฅฅ๓ฅษคฯฬตธ๚ควคน,คดคแค๓คสคตคค. MzScheme คฮ racket/base ฅโฅธฅๅกผฅ๋" +"คฌฅํกผฅษควคญคคปค๓ควคทคฟ." + +msgid "invalid expression" +msgstr "ฬตธ๚คสผฐควคน" + +msgid "expressions disabled at compile time" +msgstr "ผฐคฯฅณฅ๓ฅัฅคฅ๋ปคหฬตธ๚คหคตค์คฦคคคคน" + +msgid "hidden option" +msgstr "ฑฃคทฅชฅืฅทฅ็ฅ๓" + +msgid "unknown option" +msgstr "ฬครฮคฮฅชฅืฅทฅ็ฅ๓ควคน" + +msgid "window index is out of range" +msgstr "ศฯฐฯณฐคฮฅฆฅฃฅ๓ฅษฅฆศึนๆควคน" + +msgid "couldn't open buffer" +msgstr "ฅะฅรฅีฅกค๒ณซคฑคคปค๓" + +msgid "cannot delete line" +msgstr "นิค๒พรคปคคปค๓" + +msgid "cannot replace line" +msgstr "นิค๒รึดนควคญคคปค๓" + +msgid "cannot insert line" +msgstr "นิค๒มฦควคญคคปค๓" + +msgid "string cannot contain newlines" +msgstr "สธป๚ฮ๓คหคฯฒนิสธป๚ค๒ดคแค้ค์คคปค๓" + +msgid "error converting Scheme values to Vim" +msgstr "SchemeรอคฮVimคุคฮสัดนฅจฅ้กผ" + +msgid "Vim error: ~a" +msgstr "Vim ฅจฅ้กผ: ~a" + +msgid "Vim error" +msgstr "Vim ฅจฅ้กผ" + +msgid "buffer is invalid" +msgstr "ฅะฅรฅีฅกคฯฬตธ๚ควคน" + +msgid "window is invalid" +msgstr "ฅฆฅฃฅ๓ฅษฅฆคฯฬตธ๚ควคน" + +msgid "linenr out of range" +msgstr "ศฯฐฯณฐคฮนิศึนๆควคน" + +msgid "not allowed in the Vim sandbox" +msgstr "ฅตฅ๓ฅษฅฅรฅฏฅนควคฯต๖คตค์คคปค๓" + +msgid "E836: This Vim cannot execute :python after using :py3" +msgstr "E836: คณคฮVimควคฯ :py3 ค๒ปศครคฟธๅคห :python ค๒ปศคจคคปค๓" + +msgid "" +"E263: Sorry, this command is disabled, the Python library could not be " +"loaded." +msgstr "" +"E263: คณคฮฅณฅฅ๓ฅษคฯฬตธ๚ควคน,คดคแค๓คสคตคค: Pythonฅ้ฅคฅึฅ้ฅ๊ค๒ฅํกผฅษควคญคคปค๓" +"ควคทคฟ." + +msgid "" +"E887: Sorry, this command is disabled, the Python's site module could not be " +"loaded." +msgstr "" +"E887: คณคฮฅณฅฅ๓ฅษคฯฬตธ๚ควคน,คดคแค๓คสคตคค. Python คฮ site ฅโฅธฅๅกผฅ๋ค๒ฅํกผฅษ" +"ควคญคคปค๓ควคทคฟ." + +# Added at 07-Feb-2004. +msgid "E659: Cannot invoke Python recursively" +msgstr "E659: Python ค๒บฦตขลชคหผยนิคนค๋คณคศคฯควคญคคปค๓" + +msgid "E837: This Vim cannot execute :py3 after using :python" +msgstr "E837: คณคฮVimควคฯ :python ค๒ปศครคฟธๅคห :py3 ค๒ปศคจคคปค๓" + +msgid "E265: $_ must be an instance of String" +msgstr "E265: $_ คฯสธป๚ฮ๓คฮฅคฅ๓ฅนฅฟฅ๓ฅนควคสคฑค์คะคสค๊คคปค๓" + +msgid "" +"E266: Sorry, this command is disabled, the Ruby library could not be loaded." +msgstr "" +"E266: คณคฮฅณฅฅ๓ฅษคฯฬตธ๚ควคน,คดคแค๓คสคตคค: Rubyฅ้ฅคฅึฅ้ฅ๊ค๒ฅํกผฅษควคญคคปค๓คว" +"คทคฟ." + +msgid "E267: unexpected return" +msgstr "E267: อฝดคปคฬ return ควคน" + +msgid "E268: unexpected next" +msgstr "E268: อฝดคปคฬ next ควคน" + +msgid "E269: unexpected break" +msgstr "E269: อฝดคปคฬ break ควคน" + +msgid "E270: unexpected redo" +msgstr "E270: อฝดคปคฬ redo ควคน" + +msgid "E271: retry outside of rescue clause" +msgstr "E271: rescue คฮณฐคฮ retry ควคน" + +msgid "E272: unhandled exception" +msgstr "E272: ผ่ค๊ฐทค๏ค์คสคซครคฟฮใณฐคฌคขค๊คคน" + +#, c-format +msgid "E273: unknown longjmp status %d" +msgstr "E273: ฬครฮคฮlongjmpพ๕ยึ: %d" + +msgid "invalid buffer number" +msgstr "ฬตธ๚คสฅะฅรฅีฅกศึนๆควคน" + +msgid "not implemented yet" +msgstr "คคภผยม๕คตค์คฦคคคคปค๓" + +#. ??? +msgid "cannot set line(s)" +msgstr "นิค๒ภ฿ฤ๊ควคญคคปค๓" + +msgid "invalid mark name" +msgstr "ฬตธ๚คสฅกผฅฏฬพควคน" + +msgid "mark not set" +msgstr "ฅกผฅฏคฯภ฿ฤ๊คตค์คฦคคคคปค๓" + +#, c-format +msgid "row %d column %d" +msgstr "นิ %d ฮ๓ %d" + +msgid "cannot insert/append line" +msgstr "นิคฮมฦ/ฤษฒรค๒ควคญคคปค๓" + +msgid "line number out of range" +msgstr "ศฯฐฯณฐคฮนิศึนๆควคน" + +msgid "unknown flag: " +msgstr "ฬครฮคฮฅีฅ้ฅฐ: " + +msgid "unknown vimOption" +msgstr "ฬครฮคฮ vimOption ควคน" + +msgid "keyboard interrupt" +msgstr "ฅญกผฅกผฅษณไนค฿" + +msgid "vim error" +msgstr "vim ฅจฅ้กผ" + +msgid "cannot create buffer/window command: object is being deleted" +msgstr "" +"ฅะฅรฅีฅก/ฅฆฅฃฅ๓ฅษฅฆบ๎ภฎฅณฅฅ๓ฅษค๒บ๎ภฎควคญคคปค๓: ฅชฅึฅธฅงฅฏฅศคฌพรต๎คตค์คฦคคค" +"คทคฟ" + +msgid "" +"cannot register callback command: buffer/window is already being deleted" +msgstr "" +"ฅณกผฅ๋ฅะฅรฅฏฅณฅฅ๓ฅษค๒ละฯฟควคญคคปค๓: ฅะฅรฅีฅก/ฅฆฅฃฅ๓ฅษฅฆคฌด๛คหพรต๎คตค์คคทคฟ" + +#. This should never happen. Famous last word? +msgid "" +"E280: TCL FATAL ERROR: reflist corrupt!? Please report this to vim-dev@vim." +"org" +msgstr "" +"E280: TCL รืฬฟลชฅจฅ้กผ: reflist ฑ๘ภ๗!? vim-dev@vim.org คหส๓น๐คทคฦคฏคภคตคค" + +msgid "cannot register callback command: buffer/window reference not found" +msgstr "" +"ฅณกผฅ๋ฅะฅรฅฏฅณฅฅ๓ฅษค๒ละฯฟควคญคคปค๓: ฅะฅรฅีฅก/ฅฆฅฃฅ๓ฅษฅฆคฮปฒพศคฌธซคฤคซค๊คคป" +"ค๓" + +msgid "" +"E571: Sorry, this command is disabled: the Tcl library could not be loaded." +msgstr "" +"E571: คณคฮฅณฅฅ๓ฅษคฯฬตธ๚ควคน,คดคแค๓คสคตคค: Tclฅ้ฅคฅึฅ้ฅ๊ค๒ฅํกผฅษควคญคคปค๓คว" +"คทคฟ." + +#, c-format +msgid "E572: exit code %d" +msgstr "E572: ฝชฮปฅณกผฅษ %d" + +msgid "cannot get line" +msgstr "นิค๒ผ่ฦภควคญคคปค๓" + +msgid "Unable to register a command server name" +msgstr "ฬฟฮแฅตกผฅะกผคฮฬพมฐค๒ละฯฟควคญคคปค๓" + +msgid "E248: Failed to send command to the destination program" +msgstr "E248: ฬลชคฮฅืฅํฅฐฅ้ฅเคุคฮฅณฅฅ๓ฅษม๗ฟฎคหผบวิคทคคทคฟ" + +#, c-format +msgid "E573: Invalid server id used: %s" +msgstr "E573: ฬตธ๚คสฅตกผฅะกผIDคฌปศค๏ค์คคทคฟ: %s" + +msgid "E251: VIM instance registry property is badly formed. Deleted!" +msgstr "E251: VIM ผยยฮคฮละฯฟฅืฅํฅัฅฦฅฃคฌษิภตควคน. พรต๎คทคคทคฟ!" + +#, c-format +msgid "E696: Missing comma in List: %s" +msgstr "E696: ฅ๊ฅนฅศทฟคหฅซฅ๓ฅคฌคขค๊คคปค๓: %s" + +#, c-format +msgid "E697: Missing end of List ']': %s" +msgstr "E697: ฅ๊ฅนฅศทฟคฮบวธๅคห ']' คฌคขค๊คคปค๓: %s" + msgid "Unknown option argument" msgstr "ฬครฮคฮฅชฅืฅทฅ็ฅ๓ฐ๚ฟ๔ควคน" -#: ../main.c:146 msgid "Too many edit arguments" msgstr "สิฝธฐ๚ฟ๔คฌยฟฒแคฎคคน" -#: ../main.c:148 msgid "Argument missing after" msgstr "ฐ๚ฟ๔คฌคขค๊คคปค๓" -#: ../main.c:150 msgid "Garbage after option argument" msgstr "ฅชฅืฅทฅ็ฅ๓ฐ๚ฟ๔คฮธๅคหฅดฅ฿คฌคขค๊คคน" -#: ../main.c:152 msgid "Too many \"+command\", \"-c command\" or \"--cmd command\" arguments" msgstr "\"+command\", \"-c command\", \"--cmd command\" คฮฐ๚ฟ๔คฌยฟฒแคฎคคน" -#: ../main.c:154 msgid "Invalid argument for" msgstr "ฬตธ๚คสฐ๚ฟ๔ควคน: " -#: ../main.c:294 #, c-format msgid "%d files to edit\n" msgstr "%d ธฤคฮฅีฅกฅคฅ๋คฌสิฝธค๒นตคจคฦคคคคน\n" -#: ../main.c:1342 +msgid "netbeans is not supported with this GUI\n" +msgstr "netbeans คฯคณคฮGUIควคฯอ๘อัควคญคคปค๓\n" + +msgid "'-nb' cannot be used: not enabled at compile time\n" +msgstr "'-nb' ปศอัษิฒฤวฝควคน: ฅณฅ๓ฅัฅคฅ๋ปคหฬตธ๚คหคตค์คฦคคคคน\n" + +msgid "This Vim was not compiled with the diff feature." +msgstr "คณคฮVimคหคฯdiffตกวฝคฌคขค๊คคปค๓(ฅณฅ๓ฅัฅคฅ๋ปภ฿ฤ๊)." + msgid "Attempt to open script file again: \"" msgstr "ฅนฅฏฅ๊ฅืฅศฅีฅกฅคฅ๋ค๒บฦคำณซคคคฦค฿คคน: \"" -#: ../main.c:1350 msgid "Cannot open for reading: \"" msgstr "ฦษนอัคศคทคฦณซคฑคคปค๓" -#: ../main.c:1393 msgid "Cannot open for script output: \"" msgstr "ฅนฅฏฅ๊ฅืฅศฝะฮฯอัค๒ณซคฑคคปค๓" -#: ../main.c:1622 +msgid "Vim: Error: Failure to start gvim from NetBeans\n" +msgstr "Vim: ฅจฅ้กผ: NetBeansคซค้gvimค๒ฅนฅฟกผฅศควคญคคปค๓\n" + +msgid "Vim: Error: This version of Vim does not run in a Cygwin terminal\n" +msgstr "Vim: ฅจฅ้กผ: คณคฮฅะกผฅธฅ็ฅ๓คฮVimคฯCygwinรผห๖ควคฯฦฐบ๎คทคคปค๓\n" + msgid "Vim: Warning: Output is not to a terminal\n" msgstr "Vim: ทูน๐: รผห๖คุคฮฝะฮฯควคฯคขค๊คคปค๓\n" -#: ../main.c:1624 msgid "Vim: Warning: Input is not from a terminal\n" msgstr "Vim: ทูน๐: รผห๖คซค้คฮฦฮฯควคฯคขค๊คคปค๓\n" #. just in case.. -#: ../main.c:1891 msgid "pre-vimrc command line" msgstr "vimrcมฐคฮฅณฅฅ๓ฅษฅ้ฅคฅ๓" -#: ../main.c:1964 #, c-format msgid "E282: Cannot read from \"%s\"" msgstr "E282: \"%s\"คซค้ฦษนคเคณคศคฌควคญคคปค๓" -#: ../main.c:2149 msgid "" "\n" "More info with: \"vim -h\"\n" @@ -3363,23 +2893,18 @@ msgstr "" "\n" "ค่ค๊พบูคสพ๐ส๓คฯ: \"vim -h\"\n" -#: ../main.c:2178 msgid "[file ..] edit specified file(s)" msgstr "[ฅีฅกฅคฅ๋..] คขค๋ฅีฅกฅคฅ๋ค๒สิฝธคนค๋" -#: ../main.c:2179 msgid "- read text from stdin" msgstr "- ษธฝเฦฮฯคซค้ฅฦฅญฅนฅศค๒ฦษนคเ" -#: ../main.c:2180 msgid "-t tag edit file where tag is defined" msgstr "-t ฅฟฅฐ ฅฟฅฐคฌฤ๊ตมคตค์คฟคศคณคํคซค้สิฝธคนค๋" -#: ../main.c:2181 msgid "-q [errorfile] edit file with first error" msgstr "-q [errorfile] บวฝ้คฮฅจฅ้กผควสิฝธคนค๋" -#: ../main.c:2187 msgid "" "\n" "\n" @@ -3389,11 +2914,9 @@ msgstr "" "\n" "ปศอัหก:" -#: ../main.c:2189 msgid " vim [arguments] " msgstr " vim [ฐ๚ฟ๔] " -#: ../main.c:2193 msgid "" "\n" " or:" @@ -3401,7 +2924,13 @@ msgstr "" "\n" " คโคทคฏคฯ:" -#: ../main.c:2196 +msgid "" +"\n" +"Where case is ignored prepend / to make flag upper case" +msgstr "" +"\n" +"ย็พฎสธป๚คฌฬตป๋คตค์ค๋พ์น็คฯย็สธป๚คหคนค๋คฟคแคห / ค๒มฐรึคทคฦคฏคภคตคค" + msgid "" "\n" "\n" @@ -3411,189 +2940,319 @@ msgstr "" "\n" "ฐ๚ฟ๔:\n" -#: ../main.c:2197 msgid "--\t\t\tOnly file names after this" msgstr "--\t\t\tคณคฮคขคศคหคฯฅีฅกฅคฅ๋ฬพคภคฑ" -#: ../main.c:2199 msgid "--literal\t\tDon't expand wildcards" msgstr "--literal\t\tฅ๏ฅคฅ๋ฅษฅซกผฅษค๒ลธณซคทคสคค" -#: ../main.c:2201 +msgid "-register\t\tRegister this gvim for OLE" +msgstr "-register\t\tคณคฮgvimค๒OLEคศคทคฦละฯฟคนค๋" + +msgid "-unregister\t\tUnregister gvim for OLE" +msgstr "-unregister\t\tgvimคฮOLEละฯฟค๒ฒ๒ฝคนค๋" + +msgid "-g\t\t\tRun using GUI (like \"gvim\")" +msgstr "-g\t\t\tGUIควตฏฦฐคนค๋ (\"gvim\" คศฦฑคธ)" + +msgid "-f or --nofork\tForeground: Don't fork when starting GUI" +msgstr "-f or --nofork\tฅีฅฉฅขฅฐฅ้ฅฆฅ๓ฅษ: GUIค๒ปฯคแค๋คศคญคหforkคทคสคค" + msgid "-v\t\t\tVi mode (like \"vi\")" msgstr "-v\t\t\tViฅโกผฅษ (\"vi\" คศฦฑคธ)" -#: ../main.c:2202 msgid "-e\t\t\tEx mode (like \"ex\")" msgstr "-e\t\t\tExฅโกผฅษ (\"ex\" คศฦฑคธ)" -#: ../main.c:2203 msgid "-E\t\t\tImproved Ex mode" msgstr "-E\t\t\tฒฮษExฅโกผฅษ" -#: ../main.c:2204 msgid "-s\t\t\tSilent (batch) mode (only for \"ex\")" msgstr "-s\t\t\tฅตฅคฅ์ฅ๓ฅศ(ฅะฅรฅม)ฅโกผฅษ (\"ex\" ภ์อั)" -#: ../main.c:2205 msgid "-d\t\t\tDiff mode (like \"vimdiff\")" msgstr "-d\t\t\tบนสฌฅโกผฅษ (\"vidiff\" คศฦฑคธ)" -#: ../main.c:2206 msgid "-y\t\t\tEasy mode (like \"evim\", modeless)" msgstr "-y\t\t\tฅคกผฅธกผฅโกผฅษ (\"evim\" คศฦฑคธ, ฅโกผฅษฬต)" -#: ../main.c:2207 msgid "-R\t\t\tReadonly mode (like \"view\")" msgstr "-R\t\t\tฦษนภ์อัฅโกผฅษ (\"view\" คศฦฑคธ)" -#: ../main.c:2208 msgid "-Z\t\t\tRestricted mode (like \"rvim\")" msgstr "-Z\t\t\tภฉธยฅโกผฅษ (\"rvim\" คศฦฑคธ)" -#: ../main.c:2209 msgid "-m\t\t\tModifications (writing files) not allowed" msgstr "-m\t\t\tสันน (ฅีฅกฅคฅ๋สยธป) ค๒ควคญคสคคค่คฆคหคนค๋" -#: ../main.c:2210 msgid "-M\t\t\tModifications in text not allowed" msgstr "-M\t\t\tฅฦฅญฅนฅศคฮสิฝธค๒นิคสคจคสคคค่คฆคหคนค๋" -#: ../main.c:2211 msgid "-b\t\t\tBinary mode" msgstr "-b\t\t\tฅะฅคฅสฅ๊ฅโกผฅษ" -#: ../main.c:2212 msgid "-l\t\t\tLisp mode" msgstr "-l\t\t\tLispฅโกผฅษ" -#: ../main.c:2213 msgid "-C\t\t\tCompatible with Vi: 'compatible'" msgstr "-C\t\t\tViธ฿ดนฅโกผฅษ: 'compatible'" -#: ../main.c:2214 msgid "-N\t\t\tNot fully Vi compatible: 'nocompatible'" msgstr "-N\t\t\tViศ๓ธ฿ดนฅโกผฅษ: 'nocompatible" -#: ../main.c:2215 msgid "-V[N][fname]\t\tBe verbose [level N] [log messages to fname]" msgstr "-V[N][fname]\t\tฅํฅฐฝะฮฯภ฿ฤ๊ [ฅ์ฅูฅ๋ N] [ฅํฅฐฅีฅกฅคฅ๋ฬพ fname]" -#: ../main.c:2216 msgid "-D\t\t\tDebugging mode" msgstr "-D\t\t\tฅวฅะฅรฅฐฅโกผฅษ" -#: ../main.c:2217 msgid "-n\t\t\tNo swap file, use memory only" msgstr "-n\t\t\tฅนฅ๏ฅรฅืฅีฅกฅคฅ๋ค๒ปศอัคปคบฅแฅโฅ๊คภคฑ" -#: ../main.c:2218 msgid "-r\t\t\tList swap files and exit" msgstr "-r\t\t\tฅนฅ๏ฅรฅืฅีฅกฅคฅ๋ค๒ฮ๓ต๓คทฝชฮป" -#: ../main.c:2219 msgid "-r (with file name)\tRecover crashed session" msgstr "-r (ฅีฅกฅคฅ๋ฬพ)\tฅฏฅ้ฅรฅทฅๅคทคฟฅปฅรฅทฅ็ฅ๓ค๒ษตข" -#: ../main.c:2220 msgid "-L\t\t\tSame as -r" msgstr "-L\t\t\t-rคศฦฑคธ" -#: ../main.c:2221 +msgid "-f\t\t\tDon't use newcli to open window" +msgstr "-f\t\t\tฅฆฅฃฅ๓ฅษฅฆค๒ณซคฏคฮคห newcli ค๒ปศอัคทคสคค" + +msgid "-dev <device>\t\tUse <device> for I/O" +msgstr "-dev <device>\t\tI/Oคห <device> ค๒ปศอัคนค๋" + msgid "-A\t\t\tstart in Arabic mode" msgstr "-A\t\t\tฅขฅ้ฅำฅขธ์ฅโกผฅษควตฏฦฐคนค๋" -#: ../main.c:2222 msgid "-H\t\t\tStart in Hebrew mode" msgstr "-H\t\t\tฅุฅึฅ้ฅคธ์ฅโกผฅษควตฏฦฐคนค๋" -#: ../main.c:2223 msgid "-F\t\t\tStart in Farsi mode" msgstr "-F\t\t\tฅฺฅ๋ฅทฅขธ์ฅโกผฅษควตฏฦฐคนค๋" -#: ../main.c:2224 msgid "-T <terminal>\tSet terminal type to <terminal>" msgstr "-T <terminal>\tรผห๖ค๒ <terminal> คหภ฿ฤ๊คนค๋" -#: ../main.c:2225 +msgid "--not-a-term\t\tSkip warning for input/output not being a terminal" +msgstr "--not-a-term\t\tฦฝะฮฯคฌรผห๖ควคสคคคศคฮทูน๐ค๒ฅนฅญฅรฅืคนค๋" + msgid "-u <vimrc>\t\tUse <vimrc> instead of any .vimrc" msgstr "-u <vimrc>\t\t.vimrcคฮยๅค๏ค๊คห <vimrc> ค๒ปศคฆ" -#: ../main.c:2226 +msgid "-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc" +msgstr "-U <gvimrc>\t\t.gvimrcคฮยๅค๏ค๊คห <gvimrc> ค๒ปศคฆ" + msgid "--noplugin\t\tDon't load plugin scripts" msgstr "--noplugin\t\tฅืฅ้ฅฐฅคฅ๓ฅนฅฏฅ๊ฅืฅศค๒ฅํกผฅษคทคสคค" -#: ../main.c:2227 msgid "-p[N]\t\tOpen N tab pages (default: one for each file)" msgstr "-p[N]\t\tN ธฤฅฟฅึฅฺกผฅธค๒ณซคฏ(พสฮฌรอ: ฅีฅกฅคฅ๋คหคฤคญ1ธฤ)" -#: ../main.c:2228 msgid "-o[N]\t\tOpen N windows (default: one for each file)" msgstr "-o[N]\t\tN ธฤฅฆฅฃฅ๓ฅษฅฆค๒ณซคฏ(พสฮฌรอ: ฅีฅกฅคฅ๋คหคฤคญ1ธฤ)" -#: ../main.c:2229 msgid "-O[N]\t\tLike -o but split vertically" msgstr "-O[N]\t\t-oคศฦฑคธคภคฌฟโฤพสฌณไ" -#: ../main.c:2230 msgid "+\t\t\tStart at end of file" msgstr "+\t\t\tฅีฅกฅคฅ๋คฮบวธๅคซค้คฯคธคแค๋" -#: ../main.c:2231 msgid "+<lnum>\t\tStart at line <lnum>" msgstr "+<lnum>\t\t<lnum> นิคซค้คฯคธคแค๋" -#: ../main.c:2232 msgid "--cmd <command>\tExecute <command> before loading any vimrc file" msgstr "--cmd <command>\tvimrcค๒ฅํกผฅษคนค๋มฐคห <command> ค๒ผยนิคนค๋" -#: ../main.c:2233 msgid "-c <command>\t\tExecute <command> after loading the first file" msgstr "-c <command>\t\tบวฝ้คฮฅีฅกฅคฅ๋ค๒ฅํกผฅษธๅ <command> ค๒ผยนิคนค๋" -#: ../main.c:2235 msgid "-S <session>\t\tSource file <session> after loading the first file" msgstr "-S <session>\t\tบวฝ้คฮฅีฅกฅคฅ๋ค๒ฅํกผฅษธๅฅีฅกฅคฅ๋ <session> ค๒ผ่นคเ" -#: ../main.c:2236 msgid "-s <scriptin>\tRead Normal mode commands from file <scriptin>" msgstr "-s <scriptin>\tฅีฅกฅคฅ๋ <scriptin> คซค้ฅฮกผฅฅ๋ฅณฅฅ๓ฅษค๒ฦษนคเ" -#: ../main.c:2237 msgid "-w <scriptout>\tAppend all typed commands to file <scriptout>" msgstr "-w <scriptout>\tฦฮฯคทคฟมดฅณฅฅ๓ฅษค๒ฅีฅกฅคฅ๋ <scriptout> คหฤษฒรคนค๋" -#: ../main.c:2238 msgid "-W <scriptout>\tWrite all typed commands to file <scriptout>" msgstr "-W <scriptout>\tฦฮฯคทคฟมดฅณฅฅ๓ฅษค๒ฅีฅกฅคฅ๋ <scriptout> คหสยธคนค๋" -#: ../main.c:2240 +msgid "-x\t\t\tEdit encrypted files" +msgstr "-x\t\t\tฐลนๆฒฝคตค์คฟฅีฅกฅคฅ๋ค๒สิฝธคนค๋" + +msgid "-display <display>\tConnect vim to this particular X-server" +msgstr "-display <display>\tvimค๒ปุฤ๊คทคฟ X ฅตกผฅะกผคหภยณคนค๋" + +msgid "-X\t\t\tDo not connect to X server" +msgstr "-X\t\t\tXฅตกผฅะกผคหภยณคทคสคค" + +msgid "--remote <files>\tEdit <files> in a Vim server if possible" +msgstr "--remote <files>\tฒฤวฝคสค้คะVimฅตกผฅะกผคว <files> ค๒สิฝธคนค๋" + +msgid "--remote-silent <files> Same, don't complain if there is no server" +msgstr "--remote-silent <files> ฦฑพๅ, ฅตกผฅะกผคฌฬตคฏคฦคโทูน๐สธค๒ฝะฮฯคทคสคค" + +msgid "" +"--remote-wait <files> As --remote but wait for files to have been edited" +msgstr "--remote-wait <files>\t--remoteธๅ ฅีฅกฅคฅ๋คฮสิฝธคฌฝชค๏ค๋คฮค๒ยิคฤ" + +msgid "" +"--remote-wait-silent <files> Same, don't complain if there is no server" +msgstr "" +"--remote-wait-silent <files> ฦฑพๅ, ฅตกผฅะกผคฌฬตคฏคฦคโทูน๐สธค๒ฝะฮฯคทคสคค" + +msgid "" +"--remote-tab[-wait][-silent] <files> As --remote but use tab page per file" +msgstr "" +"--remote-tab[-wait][-silent] <files> --remoteควฅีฅกฅคฅ๋1คฤคหคฤคญ1คฤคฮฅฟฅึ" +"ฅฺกผฅธค๒ณซคฏ" + +msgid "--remote-send <keys>\tSend <keys> to a Vim server and exit" +msgstr "--remote-send <keys>\tVimฅตกผฅะกผคห <keys> ค๒ม๗ฟฎคทคฦฝชฮปคนค๋" + +msgid "--remote-expr <expr>\tEvaluate <expr> in a Vim server and print result" +msgstr "--remote-expr <expr>\tฅตกผฅะกผคว <expr> ค๒ผยนิคทคฦท๋ฒฬค๒ษฝผจคนค๋" + +msgid "--serverlist\t\tList available Vim server names and exit" +msgstr "--serverlist\t\tVimฅตกผฅะกผฬพคฮฐ์อ๗ค๒ษฝผจคทคฦฝชฮปคนค๋" + +msgid "--servername <name>\tSend to/become the Vim server <name>" +msgstr "--servername <name>\tVimฅตกผฅะกผ <name> คหม๗ฟฎ/ฬพมฐภ฿ฤ๊คนค๋" + msgid "--startuptime <file>\tWrite startup timing messages to <file>" msgstr "--startuptime <file>\tตฏฦฐคหคซคซครคฟปดึคฮพบูค๒ <file> คุฝะฮฯคนค๋" -#: ../main.c:2242 msgid "-i <viminfo>\t\tUse <viminfo> instead of .viminfo" msgstr "-i <viminfo>\t\t.viminfoคฮยๅค๏ค๊คห <viminfo> ค๒ปศคฆ" -#: ../main.c:2243 msgid "-h or --help\tPrint Help (this message) and exit" msgstr "-h or --help\tฅุฅ๋ฅื(คณคฮฅแฅรฅปกผฅธ)ค๒ษฝผจคทฝชฮปคนค๋" -#: ../main.c:2244 msgid "--version\t\tPrint version information and exit" msgstr "--version\t\tฅะกผฅธฅ็ฅ๓พ๐ส๓ค๒ษฝผจคทฝชฮปคนค๋" -#: ../mark.c:676 +msgid "" +"\n" +"Arguments recognised by gvim (Motif version):\n" +msgstr "" +"\n" +"gvimคหค่ครคฦฒ๒ผแคตค์ค๋ฐ๚ฟ๔(Motifฅะกผฅธฅ็ฅ๓):\n" + +msgid "" +"\n" +"Arguments recognised by gvim (neXtaw version):\n" +msgstr "" +"\n" +"gvimคหค่ครคฦฒ๒ผแคตค์ค๋ฐ๚ฟ๔(neXtawฅะกผฅธฅ็ฅ๓):\n" + +msgid "" +"\n" +"Arguments recognised by gvim (Athena version):\n" +msgstr "" +"\n" +"gvimคหค่ครคฦฒ๒ผแคตค์ค๋ฐ๚ฟ๔(Athenaฅะกผฅธฅ็ฅ๓):\n" + +msgid "-display <display>\tRun vim on <display>" +msgstr "-display <display>\t<display> ควvimค๒ผยนิคนค๋" + +msgid "-iconic\t\tStart vim iconified" +msgstr "-iconic\t\tบวพฎฒฝคทคฟพ๕ยึควvimค๒ตฏฦฐคนค๋" + +msgid "-background <color>\tUse <color> for the background (also: -bg)" +msgstr "-background <color>\tวุทสฟงคห <color> ค๒ปศคฆ(ฦฑตม: -bg)" + +msgid "-foreground <color>\tUse <color> for normal text (also: -fg)" +msgstr "-foreground <color>\tมฐทสฟงคห <color> ค๒ปศคฆ(ฦฑตม: -fg)" + +msgid "-font <font>\t\tUse <font> for normal text (also: -fn)" +msgstr "-font <font>\t\tฅฦฅญฅนฅศษฝผจคห <font> ค๒ปศคฆ(ฦฑตม: -fn)" + +msgid "-boldfont <font>\tUse <font> for bold text" +msgstr "-boldfont <font>\tยภป๚คห <font> ค๒ปศคฆ" + +msgid "-italicfont <font>\tUse <font> for italic text" +msgstr "-italicfont <for>\tผะยฮป๚คห <font> ค๒ปศคฆ" + +msgid "-geometry <geom>\tUse <geom> for initial geometry (also: -geom)" +msgstr "-geometry <geom>\tฝ้ดวรึคห <geom> ค๒ปศคฆ(ฦฑตม: -geom)" + +msgid "-borderwidth <width>\tUse a border width of <width> (also: -bw)" +msgstr "-borderwidth <width>\tถญณฆคฮษค๒ <width> คหคนค๋(ฦฑตม: -bw)" + +msgid "-scrollbarwidth <width> Use a scrollbar width of <width> (also: -sw)" +msgstr "" +"-scrollbarwidth <width> ฅนฅฏฅํกผฅ๋ฅะกผคฮษค๒ <width> คหคนค๋(ฦฑตม: -sw)" + +msgid "-menuheight <height>\tUse a menu bar height of <height> (also: -mh)" +msgstr "-menuheight <height>\tฅแฅหฅๅกผฅะกผคฮนโคตค๒ <height> คหคนค๋(ฦฑตม: -mh)" + +msgid "-reverse\t\tUse reverse video (also: -rv)" +msgstr "-reverse\t\tศฟลพฑวมค๒ปศอัคนค๋(ฦฑตม: -rv)" + +msgid "+reverse\t\tDon't use reverse video (also: +rv)" +msgstr "+reverse\t\tศฟลพฑวมค๒ปศอัคทคสคค(ฦฑตม: +rv)" + +msgid "-xrm <resource>\tSet the specified resource" +msgstr "-xrm <resource>\tฦรฤ๊คฮฅ๊ฅฝกผฅนค๒ปศอัคนค๋" + +msgid "" +"\n" +"Arguments recognised by gvim (GTK+ version):\n" +msgstr "" +"\n" +"gvimคหค่ครคฦฒ๒ผแคตค์ค๋ฐ๚ฟ๔(GTK+ฅะกผฅธฅ็ฅ๓):\n" + +msgid "-display <display>\tRun vim on <display> (also: --display)" +msgstr "-display <display>\t<display> ควvimค๒ผยนิคนค๋(ฦฑตม: --display)" + +msgid "--role <role>\tSet a unique role to identify the main window" +msgstr "--role <role>\tฅแฅคฅ๓ฅฆฅฃฅ๓ฅษฅฆค๒ผฑสฬคนค๋ฐ์ฐีคสฬ๒ณไ(role)ค๒ภ฿ฤ๊คนค๋" + +msgid "--socketid <xid>\tOpen Vim inside another GTK widget" +msgstr "--socketid <xid>\tฐคสค๋GTK widgetควVimค๒ณซคฏ" + +msgid "--echo-wid\t\tMake gvim echo the Window ID on stdout" +msgstr "--echo-wid\t\tฅฆฅฃฅ๓ฅษฅฆIDค๒ษธฝเฝะฮฯคหฝะฮฯคนค๋" + +msgid "-P <parent title>\tOpen Vim inside parent application" +msgstr "-P <ฟฦคฮฅฟฅคฅศฅ๋>\tVimค๒ฟฦฅขฅืฅ๊ฅฑกผฅทฅ็ฅ๓คฮรๆควตฏฦฐคนค๋" + +msgid "--windowid <HWND>\tOpen Vim inside another win32 widget" +msgstr "--windowid <HWND>\tฐคสค๋Win32 widgetคฮฦโษ๔คหVimค๒ณซคฏ" + +msgid "No display" +msgstr "ฅวฅฃฅนฅืฅ์ฅคคฌธซคฤคซค๊คคปค๓" + +#. Failed to send, abort. +msgid ": Send failed.\n" +msgstr ": ม๗ฟฎคหผบวิคทคคทคฟ.\n" + +#. Let vim start normally. +msgid ": Send failed. Trying to execute locally\n" +msgstr ": ม๗ฟฎคหผบวิคทคคทคฟ. ฅํกผฅซฅ๋ควคฮผยนิค๒ป๎ค฿คฦคคคคน\n" + +#, c-format +msgid "%d of %d edited" +msgstr "%d ธฤ (%d ธฤรๆ) คฮฅีฅกฅคฅ๋ค๒สิฝธคทคคทคฟ" + +msgid "No display: Send expression failed.\n" +msgstr "ฅวฅฃฅนฅืฅ์ฅคคฌคขค๊คคปค๓: ผฐคฮม๗ฟฎคหผบวิคทคคทคฟ.\n" + +msgid ": Send expression failed.\n" +msgstr ": ผฐคฮม๗ฟฎคหผบวิคทคคทคฟ.\n" + msgid "No marks set" msgstr "ฅกผฅฏคฌภ฿ฤ๊คตค์คฦคคคคปค๓" -#: ../mark.c:678 #, c-format msgid "E283: No marks matching \"%s\"" msgstr "E283: \"%s\" คหณบล๖คนค๋ฅกผฅฏคฌคขค๊คคปค๓" #. Highlight title -#: ../mark.c:687 msgid "" "\n" "mark line col file/text" @@ -3602,7 +3261,6 @@ msgstr "" "mark นิ ฮ๓ ฅีฅกฅคฅ๋/ฅฦฅญฅนฅศ" #. Highlight title -#: ../mark.c:789 msgid "" "\n" " jump line col file/text" @@ -3611,7 +3269,6 @@ msgstr "" " jump นิ ฮ๓ ฅีฅกฅคฅ๋/ฅฦฅญฅนฅศ" #. Highlight title -#: ../mark.c:831 msgid "" "\n" "change line col text" @@ -3619,7 +3276,6 @@ msgstr "" "\n" "สันน นิ ฮ๓ ฅฦฅญฅนฅศ" -#: ../mark.c:1238 msgid "" "\n" "# File marks:\n" @@ -3628,7 +3284,6 @@ msgstr "" "# ฅีฅกฅคฅ๋ฅกผฅฏ:\n" #. Write the jumplist with -' -#: ../mark.c:1271 msgid "" "\n" "# Jumplist (newest first):\n" @@ -3636,7 +3291,6 @@ msgstr "" "\n" "# ฅธฅใฅ๓ฅืฅ๊ฅนฅศ (ฟทคทคคคโคฮคฌภ่):\n" -#: ../mark.c:1352 msgid "" "\n" "# History of marks within files (newest to oldest):\n" @@ -3644,84 +3298,88 @@ msgstr "" "\n" "# ฅีฅกฅคฅ๋ฦโฅกผฅฏคฮอ๚ฮ๒ (ฟทคทคคคโคฮคซค้ธลคคคโคฮ):\n" -#: ../mark.c:1431 msgid "Missing '>'" msgstr "'>' คฌธซคฤคซค๊คคปค๓" -#: ../memfile.c:426 +msgid "E543: Not a valid codepage" +msgstr "E543: ฬตธ๚คสฅณกผฅษฅฺกผฅธควคน" + +msgid "E284: Cannot set IC values" +msgstr "E284: ICคฮรอค๒ภ฿ฤ๊ควคญคคปค๓" + +msgid "E285: Failed to create input context" +msgstr "E285: ฅคฅ๓ฅืฅรฅศฅณฅ๓ฅฦฅญฅนฅศคฮบ๎ภฎคหผบวิคทคคทคฟ" + +msgid "E286: Failed to open input method" +msgstr "E286: ฅคฅ๓ฅืฅรฅศฅแฅฝฅรฅษคฮฅชกผฅืฅ๓คหผบวิคทคคทคฟ" + +msgid "E287: Warning: Could not set destroy callback to IM" +msgstr "E287: ทูน๐: IMคฮวหฒ๕ฅณกผฅ๋ฅะฅรฅฏค๒ภ฿ฤ๊ควคญคคปค๓ควคทคฟ" + +msgid "E288: input method doesn't support any style" +msgstr "E288: ฅคฅ๓ฅืฅรฅศฅแฅฝฅรฅษคฯคษค๓คสฅนฅฟฅคฅ๋คโฅตฅกผฅศคทคคปค๓" + +msgid "E289: input method doesn't support my preedit type" +msgstr "E289: ฅคฅ๓ฅืฅรฅศฅแฅฝฅรฅษคฯ my preedit type ค๒ฅตฅกผฅศคทคคปค๓" + msgid "E293: block was not locked" msgstr "E293: ฅึฅํฅรฅฏคฌฅํฅรฅฏคตค์คฦคคคคปค๓" -#: ../memfile.c:799 msgid "E294: Seek error in swap file read" msgstr "E294: ฅนฅ๏ฅรฅืฅีฅกฅคฅ๋ฦษนปคหฅทกผฅฏฅจฅ้กผควคน" -#: ../memfile.c:803 msgid "E295: Read error in swap file" msgstr "E295: ฅนฅ๏ฅรฅืฅีฅกฅคฅ๋คฮฦษนค฿ฅจฅ้กผควคน" -#: ../memfile.c:849 msgid "E296: Seek error in swap file write" msgstr "E296: ฅนฅ๏ฅรฅืฅีฅกฅคฅ๋ฝ๑นค฿ปคหฅทกผฅฏฅจฅ้กผควคน" -#: ../memfile.c:865 msgid "E297: Write error in swap file" msgstr "E297: ฅนฅ๏ฅรฅืฅีฅกฅคฅ๋คฮฝ๑นค฿ฅจฅ้กผควคน" -#: ../memfile.c:1036 msgid "E300: Swap file already exists (symlink attack?)" msgstr "E300: ฅนฅ๏ฅรฅืฅีฅกฅคฅ๋คฌด๛คหยธบ฿คทคคน (symlinkคหค่ค๋นถทโ?)" -#: ../memline.c:318 msgid "E298: Didn't get block nr 0?" msgstr "E298: ฅึฅํฅรฅฏ 0 ค๒ผ่ฦภควคญคคปค๓?" -#: ../memline.c:361 msgid "E298: Didn't get block nr 1?" msgstr "E298: ฅึฅํฅรฅฏ 1 ค๒ผ่ฦภควคญคคปค๓?" -#: ../memline.c:377 msgid "E298: Didn't get block nr 2?" msgstr "E298: ฅึฅํฅรฅฏ 2 ค๒ผ่ฦภควคญคคปค๓?" +msgid "E843: Error while updating swap file crypt" +msgstr "E843: ฅนฅ๏ฅรฅืฅีฅกฅคฅ๋คฮฐลนๆค๒นนฟทรๆคหฅจฅ้กผคฌศฏภธคทคคทคฟ" + #. could not (re)open the swap file, what can we do???? -#: ../memline.c:465 msgid "E301: Oops, lost the swap file!!!" msgstr "E301: คชครคศ, ฅนฅ๏ฅรฅืฅีฅกฅคฅ๋คฌผบค๏ค์คคทคฟ!!!" -#: ../memline.c:477 msgid "E302: Could not rename swap file" msgstr "E302: ฅนฅ๏ฅรฅืฅีฅกฅคฅ๋คฮฬพมฐค๒สัคจค้ค์คคปค๓" -#: ../memline.c:554 #, c-format msgid "E303: Unable to open swap file for \"%s\", recovery impossible" msgstr "E303: \"%s\" คฮฅนฅ๏ฅรฅืฅีฅกฅคฅ๋ค๒ณซคฑคสคคคฮควฅ๊ฅซฅะฅ๊คฯษิฒฤวฝควคน" -#: ../memline.c:666 msgid "E304: ml_upd_block0(): Didn't get block 0??" msgstr "E304: ml_upd_block0(): ฅึฅํฅรฅฏ 0 ค๒ผ่ฦภควคญคคปค๓ควคทคฟ??" -#. no swap files found -#: ../memline.c:830 #, c-format msgid "E305: No swap file found for %s" msgstr "E305: %s คหคฯฅนฅ๏ฅรฅืฅีฅกฅคฅ๋คฌธซคฤคซค๊คคปค๓" -#: ../memline.c:839 msgid "Enter number of swap file to use (0 to quit): " msgstr "ปศอัคนค๋ฅนฅ๏ฅรฅืฅีฅกฅคฅ๋คฮศึนๆค๒ฦฮฯคทคฦคฏคภคตคค(0 ควฝชฮป): " -#: ../memline.c:879 #, c-format msgid "E306: Cannot open %s" msgstr "E306: %s ค๒ณซคฑคคปค๓" -#: ../memline.c:897 msgid "Unable to read block 0 from " msgstr "ฅึฅํฅรฅฏ 0 ค๒ฦษนคแคคปค๓ " -#: ../memline.c:900 msgid "" "\n" "Maybe no changes were made or Vim did not update the swap file." @@ -3729,28 +3387,22 @@ msgstr "" "\n" "ถฒค้คฏสันนคฌคตค์คฦคคคสคคคซVimคฌฅนฅ๏ฅรฅืฅีฅกฅคฅ๋ค๒นนฟทคทคฦคคคคปค๓." -#: ../memline.c:909 msgid " cannot be used with this version of Vim.\n" msgstr " Vimคฮคณคฮฅะกผฅธฅ็ฅ๓ควคฯปศอัควคญคคปค๓.\n" -#: ../memline.c:911 msgid "Use Vim version 3.0.\n" msgstr "Vimคฮฅะกผฅธฅ็ฅ๓3.0ค๒ปศอัคทคฦคฏคภคตคค.\n" -#: ../memline.c:916 #, c-format msgid "E307: %s does not look like a Vim swap file" msgstr "E307: %s คฯVimคฮฅนฅ๏ฅรฅืฅีฅกฅคฅ๋ควคฯคสคคค่คฆควคน" -#: ../memline.c:922 msgid " cannot be used on this computer.\n" msgstr " คณคฮฅณฅ๓ฅิฅๅกผฅฟควคฯปศอัควคญคคปค๓.\n" -#: ../memline.c:924 msgid "The file was created on " msgstr "คณคฮฅีฅกฅคฅ๋คฯผกคฮพ์ฝ๊ควบ๎ค้ค์คคทคฟ " -#: ../memline.c:928 msgid "" ",\n" "or the file has been damaged." @@ -3758,85 +3410,104 @@ msgstr "" ",\n" "คโคทคฏคฯฅีฅกฅคฅ๋คฌยปฝคทคฦคคคคน." -#: ../memline.c:945 +#, c-format +msgid "" +"E833: %s is encrypted and this version of Vim does not support encryption" +msgstr "" +"E833: %s คฯคณคฮฅะกผฅธฅ็ฅ๓คฮVimควฅตฅกผฅศคทคฦคคคสคคทมผฐควฐลนๆฒฝคตค์คฦคคคคน" + msgid " has been damaged (page size is smaller than minimum value).\n" msgstr " คฯยปฝคทคฦคคคคน (ฅฺกผฅธฅตฅคฅบคฌบวพฎรอค๒ฒผฒ๓ครคฦคคคคน).\n" -#: ../memline.c:974 #, c-format msgid "Using swap file \"%s\"" msgstr "ฅนฅ๏ฅรฅืฅีฅกฅคฅ๋ \"%s\" ค๒ปศอัรๆ" -#: ../memline.c:980 #, c-format msgid "Original file \"%s\"" msgstr "ธถหฅีฅกฅคฅ๋ \"%s\"" -#: ../memline.c:995 msgid "E308: Warning: Original file may have been changed" msgstr "E308: ทูน๐: ธถหฅีฅกฅคฅ๋คฌสันนคตค์คฦคคคคน" -#: ../memline.c:1061 +#, c-format +msgid "Swap file is encrypted: \"%s\"" +msgstr "ฅนฅ๏ฅรฅืฅีฅกฅคฅ๋คฯฐลนๆฒฝคตค์คฦคคคคน: \"%s\"" + +msgid "" +"\n" +"If you entered a new crypt key but did not write the text file," +msgstr "" +"\n" +"ฟทคทคคฐลนๆฅญกผค๒ฦฮฯคทคฟคขคศคหฅฦฅญฅนฅศฅีฅกฅคฅ๋ค๒สยธคทคฦคคคสคคพ์น็คฯ," + +msgid "" +"\n" +"enter the new crypt key." +msgstr "" +"\n" +"ฟทคทคคฐลนๆฅญกผค๒ฦฮฯคทคฦคฏคภคตคค." + +msgid "" +"\n" +"If you wrote the text file after changing the crypt key press enter" +msgstr "" +"\n" +"ฐลนๆฅญกผค๒สัคจคฟคขคศคหฅฦฅญฅนฅศฅีฅกฅคฅ๋ค๒สยธคทคฟพ์น็คฯ, ฅฦฅญฅนฅศฅีฅกฅคฅ๋คศ" + +msgid "" +"\n" +"to use the same key for text file and swap file" +msgstr "" +"\n" +"ฅนฅ๏ฅรฅืฅีฅกฅคฅ๋คหฦฑคธฐลนๆฅญกผค๒ปศคฆคฟคแคหenterคภคฑค๒ฒกคทคฦคฏคภคตคค." + #, c-format msgid "E309: Unable to read block 1 from %s" msgstr "E309: %s คซค้ฅึฅํฅรฅฏ 1 ค๒ฦษนคแคคปค๓" -#: ../memline.c:1065 msgid "???MANY LINES MISSING" msgstr "???ยฟคฏคฮนิคฌผบค๏ค์คฦคคคคน" -#: ../memline.c:1076 msgid "???LINE COUNT WRONG" msgstr "???นิฟ๔คฌดึฐใครคฦคคคคน" -#: ../memline.c:1082 msgid "???EMPTY BLOCK" msgstr "???ฅึฅํฅรฅฏคฌถ๕ควคน" -#: ../memline.c:1103 msgid "???LINES MISSING" msgstr "???นิคฌผบค๏ค์คฦคคคคน" -#: ../memline.c:1128 #, c-format msgid "E310: Block 1 ID wrong (%s not a .swp file?)" msgstr "E310: ฅึฅํฅรฅฏ 1 คฮIDคฌดึฐใครคฦคคคคน(%s คฌ.swpฅีฅกฅคฅ๋ควคสคค?)" -#: ../memline.c:1133 msgid "???BLOCK MISSING" msgstr "???ฅึฅํฅรฅฏคฌคขค๊คคปค๓" -#: ../memline.c:1147 msgid "??? from here until ???END lines may be messed up" msgstr "??? คณคณคซค้ ???END คควคฮนิคฌวหฒ๕คตค์คฦคคค๋ค่คฆควคน" -#: ../memline.c:1164 msgid "??? from here until ???END lines may have been inserted/deleted" msgstr "??? คณคณคซค้ ???END คควคฮนิคฌมฦคซบ๏ฝคตค์คฟค่คฆควคน" -#: ../memline.c:1181 msgid "???END" msgstr "???END" -#: ../memline.c:1238 msgid "E311: Recovery Interrupted" msgstr "E311: ฅ๊ฅซฅะฅ๊คฌณไนคค์คคทคฟ" -#: ../memline.c:1243 msgid "" "E312: Errors detected while recovering; look for lines starting with ???" msgstr "" "E312: ฅ๊ฅซฅะฅ๊คฮบวรๆคหฅจฅ้กผคฌธกฝะคตค์คคทคฟ; ???ควปฯคค๋นิค๒ปฒพศคทคฦคฏคภคตคค" -#: ../memline.c:1245 msgid "See \":help E312\" for more information." msgstr "พบูคฯ \":help E312\" ค๒ปฒพศคทคฦคฏคภคตคค" -#: ../memline.c:1249 msgid "Recovery completed. You should check if everything is OK." msgstr "ฅ๊ฅซฅะฅ๊คฌฝชฮปคทคคทคฟ. มดคฦคฌภตคทคคคซฅมฅงฅรฅฏคทคฦคฏคภคตคค." -#: ../memline.c:1251 msgid "" "\n" "(You might want to write out this file under another name\n" @@ -3844,15 +3515,12 @@ msgstr "" "\n" "(สันนค๒ฅมฅงฅรฅฏคนค๋คฟคแคห, คณคฮฅีฅกฅคฅ๋ค๒สฬคฮฬพมฐควสยธคทคฟพๅคว\n" -#: ../memline.c:1252 msgid "and run diff with the original file to check for changes)" msgstr "ธถหฅีฅกฅคฅ๋คศคฮ diff ค๒ผยนิคนค๋คศฮษคคควคทค็คฆ)" -#: ../memline.c:1254 msgid "Recovery completed. Buffer contents equals file contents." msgstr "ษธตดฐฮป. ฅะฅรฅีฅกคฮฦโอฦคฯฅีฅกฅคฅ๋คศฦฑคธคหคสค๊คคทคฟ." -#: ../memline.c:1255 msgid "" "\n" "You may want to delete the .swp file now.\n" @@ -3862,52 +3530,43 @@ msgstr "" "ธตคฮ.swpฅีฅกฅคฅ๋คฯบ๏ฝคทคฦคโนฝคคคคปค๓\n" "\n" +msgid "Using crypt key from swap file for the text file.\n" +msgstr "ฅนฅ๏ฅรฅืฅีฅกฅคฅ๋คซค้ผ่ฦภคทคฟฐลนๆฅญกผค๒ฅฦฅญฅนฅศฅีฅกฅคฅ๋คหปศคคคคน.\n" + #. use msg() to start the scrolling properly -#: ../memline.c:1327 msgid "Swap files found:" msgstr "ฅนฅ๏ฅรฅืฅีฅกฅคฅ๋คฌสฃฟ๔ธซคฤคซค๊คคทคฟ:" -#: ../memline.c:1446 msgid " In current directory:\n" msgstr " ธฝบ฿คฮฅวฅฃฅ์ฅฏฅศฅ๊:\n" -#: ../memline.c:1448 msgid " Using specified name:\n" msgstr " ฐสฒผคฮฬพมฐค๒ปศอัรๆ:\n" -#: ../memline.c:1450 msgid " In directory " msgstr " ฅวฅฃฅ์ฅฏฅศฅ๊ " -#: ../memline.c:1465 msgid " -- none --\n" msgstr " -- คสคท --\n" -#: ../memline.c:1527 msgid " owned by: " msgstr " ฝ๊อญผิ: " -#: ../memline.c:1529 msgid " dated: " msgstr " ฦษี: " -#: ../memline.c:1532 ../memline.c:3231 msgid " dated: " msgstr " ฦษี: " -#: ../memline.c:1548 msgid " [from Vim version 3.0]" msgstr " [from Vim version 3.0]" -#: ../memline.c:1550 msgid " [does not look like a Vim swap file]" msgstr " [Vimคฮฅนฅ๏ฅรฅืฅีฅกฅคฅ๋ควคฯคสคคค่คฆควคน]" -#: ../memline.c:1552 msgid " file name: " msgstr " ฅีฅกฅคฅ๋ฬพ: " -#: ../memline.c:1558 msgid "" "\n" " modified: " @@ -3915,15 +3574,12 @@ msgstr "" "\n" " สันนพ๕ยึ: " -#: ../memline.c:1559 msgid "YES" msgstr "คขค๊" -#: ../memline.c:1559 msgid "no" msgstr "คสคท" -#: ../memline.c:1562 msgid "" "\n" " user name: " @@ -3931,11 +3587,9 @@ msgstr "" "\n" " ฅๆกผฅถกผฬพ: " -#: ../memline.c:1568 msgid " host name: " msgstr " ฅฅนฅศฬพ: " -#: ../memline.c:1570 msgid "" "\n" " host name: " @@ -3943,7 +3597,6 @@ msgstr "" "\n" " ฅฅนฅศฬพ: " -#: ../memline.c:1575 msgid "" "\n" " process ID: " @@ -3951,11 +3604,16 @@ msgstr "" "\n" " ฅืฅํฅปฅนID: " -#: ../memline.c:1579 msgid " (still running)" msgstr " (คคภผยนิรๆ)" -#: ../memline.c:1586 +msgid "" +"\n" +" [not usable with this version of Vim]" +msgstr "" +"\n" +" [คณคฮVimฅะกผฅธฅ็ฅ๓ควคฯปศอัควคญคคปค๓]" + msgid "" "\n" " [not usable on this computer]" @@ -3963,97 +3621,75 @@ msgstr "" "\n" " [คณคฮฅณฅ๓ฅิฅๅกผฅฟควคฯปศอัควคญคคปค๓]" -#: ../memline.c:1590 msgid " [cannot be read]" msgstr " [ฦษนคแคคปค๓]" -#: ../memline.c:1593 msgid " [cannot be opened]" msgstr " [ณซคฑคคปค๓]" -#: ../memline.c:1698 msgid "E313: Cannot preserve, there is no swap file" msgstr "E313: ฅนฅ๏ฅรฅืฅีฅกฅคฅ๋คฌฬตคคคฮควฐปควคญคคปค๓" -#: ../memline.c:1747 msgid "File preserved" msgstr "ฅีฅกฅคฅ๋คฌฐปคตค์คคน" -#: ../memline.c:1749 msgid "E314: Preserve failed" msgstr "E314: ฐปคหผบวิคทคคทคฟ" -#: ../memline.c:1819 #, c-format -msgid "E315: ml_get: invalid lnum: %<PRId64>" -msgstr "E315: ml_get: ฬตธ๚คสlnumควคน: %<PRId64>" +msgid "E315: ml_get: invalid lnum: %ld" +msgstr "E315: ml_get: ฬตธ๚คสlnumควคน: %ld" -#: ../memline.c:1851 #, c-format -msgid "E316: ml_get: cannot find line %<PRId64>" -msgstr "E316: ml_get: นิ %<PRId64> ค๒ธซคฤคฑค้ค์คคปค๓" +msgid "E316: ml_get: cannot find line %ld" +msgstr "E316: ml_get: นิ %ld ค๒ธซคฤคฑค้ค์คคปค๓" -#: ../memline.c:2236 msgid "E317: pointer block id wrong 3" msgstr "E317: ฅฅคฅ๓ฅฟฅึฅํฅรฅฏคฮIDคฌดึฐใครคฦคคคคน 3" -#: ../memline.c:2311 msgid "stack_idx should be 0" msgstr "stack_idx คฯ 0 ควคขค๋คูคญควคน" -#: ../memline.c:2369 msgid "E318: Updated too many blocks?" msgstr "E318: นนฟทคตค์คฟฅึฅํฅรฅฏคฌยฟฒแคฎค๋คซคโ?" -#: ../memline.c:2511 msgid "E317: pointer block id wrong 4" msgstr "E317: ฅฅคฅ๓ฅฟฅึฅํฅรฅฏคฮIDคฌดึฐใครคฦคคคคน 4" -#: ../memline.c:2536 msgid "deleted block 1?" msgstr "ฅึฅํฅรฅฏ 1 คฯพรคตค์คฟ?" -#: ../memline.c:2707 #, c-format -msgid "E320: Cannot find line %<PRId64>" -msgstr "E320: นิ %<PRId64> คฌธซคฤคซค๊คคปค๓" +msgid "E320: Cannot find line %ld" +msgstr "E320: นิ %ld คฌธซคฤคซค๊คคปค๓" -#: ../memline.c:2916 msgid "E317: pointer block id wrong" msgstr "E317: ฅฅคฅ๓ฅฟฅึฅํฅรฅฏคฮIDคฌดึฐใครคฦคคคคน" -#: ../memline.c:2930 msgid "pe_line_count is zero" msgstr "pe_line_count คฌฅผฅํควคน" -#: ../memline.c:2955 #, c-format -msgid "E322: line number out of range: %<PRId64> past the end" -msgstr "E322: นิศึนๆคฌศฯฐฯณฐควคน: %<PRId64> ฤถคจคฦคคคคน" +msgid "E322: line number out of range: %ld past the end" +msgstr "E322: นิศึนๆคฌศฯฐฯณฐควคน: %ld ฤถคจคฦคคคคน" -#: ../memline.c:2959 #, c-format -msgid "E323: line count wrong in block %<PRId64>" -msgstr "E323: ฅึฅํฅรฅฏ %<PRId64> คฮนิฅซฅฆฅ๓ฅศคฌดึฐใครคฦคคคคน" +msgid "E323: line count wrong in block %ld" +msgstr "E323: ฅึฅํฅรฅฏ %ld คฮนิฅซฅฆฅ๓ฅศคฌดึฐใครคฦคคคคน" -#: ../memline.c:2999 msgid "Stack size increases" msgstr "ฅนฅฟฅรฅฏฅตฅคฅบคฌมคจคคน" -#: ../memline.c:3038 msgid "E317: pointer block id wrong 2" msgstr "E317: ฅฅคฅ๓ฅฟฅึฅํฅรฅฏคฮIDคฌดึฐใครคฦคคคคน 2" -#: ../memline.c:3070 #, c-format msgid "E773: Symlink loop for \"%s\"" msgstr "E773: \"%s\" คฮฅทฅ๓ฅฅ๊ฅรฅฏฅ๊ฅ๓ฅฏคฌฅ๋กผฅืคหคสครคฦคคคคน" -#: ../memline.c:3221 msgid "E325: ATTENTION" msgstr "E325: รํฐี" -#: ../memline.c:3222 msgid "" "\n" "Found a swap file by the name \"" @@ -4061,39 +3697,32 @@ msgstr "" "\n" "ผกคฮฬพมฐควฅนฅ๏ฅรฅืฅีฅกฅคฅ๋ค๒ธซคฤคฑคคทคฟ \"" -#: ../memline.c:3226 msgid "While opening file \"" msgstr "ผกคฮฅีฅกฅคฅ๋ค๒ณซคคคฦคคค๋บวรๆ \"" -#: ../memline.c:3239 msgid " NEWER than swap file!\n" msgstr " ฅนฅ๏ฅรฅืฅีฅกฅคฅ๋ค่ค๊คโฟทคทคคควคน!\n" -#: ../memline.c:3244 +#. Some of these messages are long to allow translation to +#. * other languages. msgid "" "\n" "(1) Another program may be editing the same file. If this is the case,\n" " be careful not to end up with two different instances of the same\n" -" file when making changes." +" file when making changes. Quit, or continue with caution.\n" msgstr "" "\n" "(1) สฬคฮฅืฅํฅฐฅ้ฅเคฌฦฑคธฅีฅกฅคฅ๋ค๒สิฝธคทคฦคคค๋คซคโคทค์คคปค๓.\n" " คณคฮพ์น็คหคฯ, สันนค๒คทคฦคทคคฆคศ1คฤคฮฅีฅกฅคฅ๋คหยะคทคฦฐคสค๋2คฤคฮ\n" -" ฅคฅ๓ฅนฅฟฅ๓ฅนคฌควคญคฦคทคคฆคฮคว, คฝคฆคทคสคคค่คฆคหตคค๒คฤคฑคฦคฏคภคตคค." - -#: ../memline.c:3245 -msgid " Quit, or continue with caution.\n" -msgstr " ฝชฮปคนค๋คซ, รํฐีคทคสคฌค้ยณคฑคฦคฏคภคตคค.\n" +" ฅคฅ๓ฅนฅฟฅ๓ฅนคฌควคญคฦคทคคฆคฮคว, คฝคฆคทคสคคค่คฆคหตคค๒คฤคฑคฦคฏคภคตคค.\n" +" ฝชฮปคนค๋คซ, รํฐีคทคสคฌค้ยณคฑคฦคฏคภคตคค.\n" -#: ../memline.c:3246 msgid "(2) An edit session for this file crashed.\n" msgstr "(2) คณคฮฅีฅกฅคฅ๋คฮสิฝธฅปฅรฅทฅ็ฅ๓คฌฅฏฅ้ฅรฅทฅๅคทคฟ.\n" -#: ../memline.c:3247 msgid " If this is the case, use \":recover\" or \"vim -r " msgstr " คณคฮพ์น็คหคฯ \":recover\" คซ \"vim -r " -#: ../memline.c:3249 msgid "" "\"\n" " to recover the changes (see \":help recovery\").\n" @@ -4101,11 +3730,9 @@ msgstr "" "\"\n" " ค๒ปศอัคทคฦสันนค๒ฅ๊ฅซฅะกผคทคคน(\":help recovery\" ค๒ปฒพศ).\n" -#: ../memline.c:3250 msgid " If you did this already, delete the swap file \"" msgstr " ด๛คหคณค์ค๒นิคสครคฟคฮคสค้คะ, ฅนฅ๏ฅรฅืฅีฅกฅคฅ๋ \"" -#: ../memline.c:3252 msgid "" "\"\n" " to avoid this message.\n" @@ -4113,23 +3740,18 @@ msgstr "" "\"\n" " ค๒พรคปคะคณคฮฅแฅรฅปกผฅธค๒ฒ๓ศ๒ควคญคคน.\n" -#: ../memline.c:3450 ../memline.c:3452 msgid "Swap file \"" msgstr "ฅนฅ๏ฅรฅืฅีฅกฅคฅ๋ \"" -#: ../memline.c:3451 ../memline.c:3455 msgid "\" already exists!" msgstr "\" คฌด๛คหคขค๊คคน!" -#: ../memline.c:3457 msgid "VIM - ATTENTION" msgstr "VIM - รํฐี" -#: ../memline.c:3459 msgid "Swap file already exists!" msgstr "ฅนฅ๏ฅรฅืฅีฅกฅคฅ๋คฌด๛คหยธบ฿คทคคน!" -#: ../memline.c:3464 msgid "" "&Open Read-Only\n" "&Edit anyway\n" @@ -4143,7 +3765,6 @@ msgstr "" "ฝชฮปคนค๋(&Q)\n" "รๆป฿คนค๋(&A)" -#: ../memline.c:3467 msgid "" "&Open Read-Only\n" "&Edit anyway\n" @@ -4159,56 +3780,34 @@ msgstr "" "ฝชฮปคนค๋(&Q)\n" "รๆป฿คนค๋(&A)" -#. -#. * Change the ".swp" extension to find another file that can be used. -#. * First decrement the last char: ".swo", ".swn", etc. -#. * If that still isn't enough decrement the last but one char: ".svz" -#. * Can happen when editing many "No Name" buffers. -#. -#. ".s?a" -#. ".saa": tried enough, give up -#: ../memline.c:3528 msgid "E326: Too many swap files found" msgstr "E326: ฅนฅ๏ฅรฅืฅีฅกฅคฅ๋คฌยฟฟ๔ธซคฤคซค๊คคทคฟ" -#: ../memory.c:227 -#, c-format -msgid "E342: Out of memory! (allocating %<PRIu64> bytes)" -msgstr "E342: ฅแฅโฅ๊คฌยญค๊คคปค๓! (%<PRIu64> ฅะฅคฅศค๒ณไล๖อืตแ)" - -#: ../menu.c:62 msgid "E327: Part of menu-item path is not sub-menu" msgstr "E327: ฅแฅหฅๅกผฅขฅคฅฦฅเคฮฅัฅนคฮษ๔สฌคฌฅตฅึฅแฅหฅๅกผควคฯคขค๊คคปค๓" -#: ../menu.c:63 msgid "E328: Menu only exists in another mode" msgstr "E328: ฅแฅหฅๅกผคฯยพคฮฅโกผฅษคหคภคฑคขค๊คคน" -#: ../menu.c:64 #, c-format msgid "E329: No menu \"%s\"" msgstr "E329: \"%s\" คศคคคฆฅแฅหฅๅกผคฯคขค๊คคปค๓" #. Only a mnemonic or accelerator is not valid. -#: ../menu.c:329 msgid "E792: Empty menu name" msgstr "E792: ฅแฅหฅๅกผฬพคฌถ๕ควคน" -#: ../menu.c:340 msgid "E330: Menu path must not lead to a sub-menu" msgstr "E330: ฅแฅหฅๅกผฅัฅนคฯฅตฅึฅแฅหฅๅกผค๒ภธคธค๋คูคญควคฯคขค๊คคปค๓" -#: ../menu.c:365 msgid "E331: Must not add menu items directly to menu bar" msgstr "E331: ฅแฅหฅๅกผฅะกผคหคฯฤพภฅแฅหฅๅกผฅขฅคฅฦฅเค๒ฤษฒรควคญคคปค๓" -#: ../menu.c:370 msgid "E332: Separator cannot be part of a menu path" msgstr "E332: ถ่ภฺค๊คฯฅแฅหฅๅกผฅัฅนคฮฐ์ษ๔ควคฯคขค๊คคปค๓" #. Now we have found the matching menu, and we list the mappings #. Highlight title -#: ../menu.c:762 msgid "" "\n" "--- Menus ---" @@ -4216,69 +3815,60 @@ msgstr "" "\n" "--- ฅแฅหฅๅกผ ---" -#: ../menu.c:1313 +msgid "Tear off this menu" +msgstr "คณคฮฅแฅหฅๅกผค๒ภฺค๊ผ่ค๋" + msgid "E333: Menu path must lead to a menu item" msgstr "E333: ฅแฅหฅๅกผฅัฅนคฯฅแฅหฅๅกผฅขฅคฅฦฅเค๒ภธคธคสคฑค์คะคคคฑคคปค๓" -#: ../menu.c:1330 #, c-format msgid "E334: Menu not found: %s" msgstr "E334: ฅแฅหฅๅกผคฌธซคฤคซค๊คคปค๓: %s" -#: ../menu.c:1396 #, c-format msgid "E335: Menu not defined for %s mode" msgstr "E335: %s คหคฯฅแฅหฅๅกผคฌฤ๊ตมคตค์คฦคคคคปค๓" -#: ../menu.c:1426 msgid "E336: Menu path must lead to a sub-menu" msgstr "E336: ฅแฅหฅๅกผฅัฅนคฯฅตฅึฅแฅหฅๅกผค๒ภธคธคสคฑค์คะคคคฑคคปค๓" -#: ../menu.c:1447 msgid "E337: Menu not found - check menu names" msgstr "E337: ฅแฅหฅๅกผคฌธซคฤคซค๊คคปค๓ - ฅแฅหฅๅกผฬพค๒ณฮวงคทคฦคฏคภคตคค" -#: ../message.c:423 #, c-format msgid "Error detected while processing %s:" msgstr "%s คฮฝ่อรๆคหฅจฅ้กผคฌธกฝะคตค์คคทคฟ:" -#: ../message.c:445 #, c-format msgid "line %4ld:" msgstr "นิ %4ld:" -#: ../message.c:617 #, c-format msgid "E354: Invalid register name: '%s'" msgstr "E354: ฬตธ๚คสฅ์ฅธฅนฅฟฬพ: '%s'" -#: ../message.c:986 +msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>" +msgstr "ฦหธ์ฅแฅรฅปกผฅธหฬ๕/ดฦฝค: ยผฒฌ ยภฯบ <koron.kaoriya@gmail.com>" + msgid "Interrupt: " msgstr "ณไนค฿: " -#: ../message.c:988 msgid "Press ENTER or type command to continue" msgstr "ยณคฑค๋คหคฯENTERค๒ฒกคนคซฅณฅฅ๓ฅษค๒ฦฮฯคทคฦคฏคภคตคค" -#: ../message.c:1843 #, c-format -msgid "%s line %<PRId64>" -msgstr "%s นิ %<PRId64>" +msgid "%s line %ld" +msgstr "%s นิ %ld" -#: ../message.c:2392 msgid "-- More --" msgstr "-- ทัยณ --" -#: ../message.c:2398 msgid " SPACE/d/j: screen/page/line down, b/u/k: up, q: quit " msgstr " SPACE/d/j: ฒ่ฬฬ/ฅฺกผฅธ/นิ ฒผ, b/u/k: พๅ, q: ฝชฮป " -#: ../message.c:3021 ../message.c:3031 msgid "Question" msgstr "ผมฬไ" -#: ../message.c:3023 msgid "" "&Yes\n" "&No" @@ -4286,17 +3876,6 @@ msgstr "" "คฯคค(&Y)\n" "คคคคคจ(&N)" -#: ../message.c:3033 -msgid "" -"&Yes\n" -"&No\n" -"&Cancel" -msgstr "" -"คฯคค(&Y)\n" -"คคคคคจ(&N)\n" -"ฅญฅใฅ๓ฅปฅ๋(&C)" - -#: ../message.c:3045 msgid "" "&Yes\n" "&No\n" @@ -4310,175 +3889,247 @@ msgstr "" "มดคฦสด(&D)\n" "ฅญฅใฅ๓ฅปฅ๋(&C)" -#: ../message.c:3058 +msgid "Select Directory dialog" +msgstr "ฅวฅฃฅ์ฅฏฅศฅ๊มชย๒ฅภฅคฅขฅํฅฐ" + +msgid "Save File dialog" +msgstr "ฅีฅกฅคฅ๋สยธฅภฅคฅขฅํฅฐ" + +msgid "Open File dialog" +msgstr "ฅีฅกฅคฅ๋ฦษนฅภฅคฅขฅํฅฐ" + +#. TODO: non-GUI file selector here +msgid "E338: Sorry, no file browser in console mode" +msgstr "E338: ฅณฅ๓ฅฝกผฅ๋ฅโกผฅษควคฯฅีฅกฅคฅ๋ฅึฅ้ฅฆฅถค๒ปศคจคคปค๓, คดคแค๓คสคตคค" + msgid "E766: Insufficient arguments for printf()" msgstr "E766: printf() คฮฐ๚ฟ๔คฌษิฝฝสฌควคน" -#: ../message.c:3119 msgid "E807: Expected Float argument for printf()" msgstr "E807: printf() คฮฐ๚ฟ๔คหคฯษโฦฐพฏฟ๔ลภฟ๔คฌดยิคตค์คฦคคคคน" -#: ../message.c:3873 msgid "E767: Too many arguments to printf()" msgstr "E767: printf() คฮฐ๚ฟ๔คฌยฟฒแคฎคคน" -#: ../misc1.c:2256 msgid "W10: Warning: Changing a readonly file" msgstr "W10: ทูน๐: ฦษนภ์อัฅีฅกฅคฅ๋ค๒สันนคทคคน" -#: ../misc1.c:2537 msgid "Type number and <Enter> or click with mouse (empty cancels): " msgstr "" "ศึนๆคศ<Enter>ค๒ฦฮฯคนค๋คซฅฅฆฅนควฅฏฅ๊ฅรฅฏคทคฦคฏคภคตคค (ถ๕ควฅญฅใฅ๓ฅปฅ๋): " -#: ../misc1.c:2539 msgid "Type number and <Enter> (empty cancels): " msgstr "ศึนๆคศ<Enter>ค๒ฦฮฯคทคฦคฏคภคตคค (ถ๕ควฅญฅใฅ๓ฅปฅ๋): " -#: ../misc1.c:2585 msgid "1 more line" msgstr "1 นิ ฤษฒรคทคคทคฟ" -#: ../misc1.c:2588 msgid "1 line less" msgstr "1 นิ บ๏ฝคทคคทคฟ" -#: ../misc1.c:2593 #, c-format -msgid "%<PRId64> more lines" -msgstr "%<PRId64> นิ ฤษฒรคทคคทคฟ" +msgid "%ld more lines" +msgstr "%ld นิ ฤษฒรคทคคทคฟ" -#: ../misc1.c:2596 #, c-format -msgid "%<PRId64> fewer lines" -msgstr "%<PRId64> นิ บ๏ฝคทคคทคฟ" +msgid "%ld fewer lines" +msgstr "%ld นิ บ๏ฝคทคคทคฟ" -#: ../misc1.c:2599 msgid " (Interrupted)" msgstr " (ณไนคค์คคทคฟ)" -#: ../misc1.c:2635 msgid "Beep!" msgstr "ฅำกผฅร!" -#: ../misc2.c:738 +msgid "ERROR: " +msgstr "ฅจฅ้กผ: " + +#, c-format +msgid "" +"\n" +"[bytes] total alloc-freed %lu-%lu, in use %lu, peak use %lu\n" +msgstr "" +"\n" +"[ฅแฅโฅ๊(ฅะฅคฅศ)] มํณไล๖-ฒ๒สฮฬ %lu-%lu, ปศอัฮฬ %lu, ฅิกผฅฏป %lu\n" + +#, c-format +msgid "" +"[calls] total re/malloc()'s %lu, total free()'s %lu\n" +"\n" +msgstr "" +"[ธฦฝะ] มํ re/malloc() ฒ๓ฟ๔ %lu, มํ free() ฒ๓ฟ๔ %lu\n" +"\n" + +msgid "E340: Line is becoming too long" +msgstr "E340: นิคฌฤนคฏคสค๊ฒแคฎคคทคฟ" + +#, c-format +msgid "E341: Internal error: lalloc(%ld, )" +msgstr "E341: ฦโษ๔ฅจฅ้กผ: lalloc(%ld,)" + +#, c-format +msgid "E342: Out of memory! (allocating %lu bytes)" +msgstr "E342: ฅแฅโฅ๊คฌยญค๊คคปค๓! (%lu ฅะฅคฅศค๒ณไล๖อืตแ)" + #, c-format msgid "Calling shell to execute: \"%s\"" msgstr "ผยนิคฮคฟคแคหฅทฅงฅ๋ค๒ธฦฝะคทรๆ: \"%s\"" -#: ../normal.c:183 +msgid "E545: Missing colon" +msgstr "E545: ฅณฅํฅ๓คฌคขค๊คคปค๓" + +msgid "E546: Illegal mode" +msgstr "E546: ษิภตคสฅโกผฅษควคน" + +msgid "E547: Illegal mouseshape" +msgstr "E547: ษิภตคส 'mouseshape' ควคน" + +msgid "E548: digit expected" +msgstr "E548: ฟ๔รอคฌษฌอืควคน" + +msgid "E549: Illegal percentage" +msgstr "E549: ษิภตคสฅักผฅปฅ๓ฅฦกผฅธควคน" + +msgid "E854: path too long for completion" +msgstr "E854: ฅัฅนคฌฤนฒแคฎคฦสไดฐควคญคคปค๓" + +#, c-format +msgid "" +"E343: Invalid path: '**[number]' must be at the end of the path or be " +"followed by '%s'." +msgstr "" +"E343: ฬตธ๚คสฅัฅนควคน: '**[ฟ๔รอ]' คฯpathคฮบวธๅคซ '%s' คฌยณคคคฦคสคคคศคคคฑคคป" +"ค๓." + +#, c-format +msgid "E344: Can't find directory \"%s\" in cdpath" +msgstr "E344: cdpathคหคฯ \"%s\" คศคคคฆฅีฅกฅคฅ๋คฌคขค๊คคปค๓" + +#, c-format +msgid "E345: Can't find file \"%s\" in path" +msgstr "E345: pathคหคฯ \"%s\" คศคคคฆฅีฅกฅคฅ๋คฌคขค๊คคปค๓" + +#, c-format +msgid "E346: No more directory \"%s\" found in cdpath" +msgstr "E346: cdpathคหคฯคณค์ฐสพๅ \"%s\" คศคคคฆฅีฅกฅคฅ๋คฌคขค๊คคปค๓" + +#, c-format +msgid "E347: No more file \"%s\" found in path" +msgstr "E347: ฅัฅนคหคฯคณค์ฐสพๅ \"%s\" คศคคคฆฅีฅกฅคฅ๋คฌคขค๊คคปค๓" + +#, c-format +msgid "E668: Wrong access mode for NetBeans connection info file: \"%s\"" +msgstr "" +"E668: NetBeansคฮภยณพ๐ส๓ฅีฅกฅคฅ๋คฮฅขฅฏฅปฅนฅโกผฅษคหฬไย๊คฌคขค๊คคน: \"%s\"" + +#, c-format +msgid "E658: NetBeans connection lost for buffer %ld" +msgstr "E658: ฅะฅรฅีฅก %ld คฮ NetBeans ภยณคฌผบค๏ค์คคทคฟ" + +msgid "E838: netbeans is not supported with this GUI" +msgstr "E838: NetBeansคฯคณคฮGUIคหคฯยะฑคทคฦคคคคปค๓" + +msgid "E511: netbeans already connected" +msgstr "E511: NetBeansคฯด๛คหภยณคทคฦคคคคน" + +#, c-format +msgid "E505: %s is read-only (add ! to override)" +msgstr "E505: %s คฯฦษนภ์อัควคน (ถฏภฉฝ๑นคหคฯ ! ค๒ฤษฒร)" + msgid "E349: No identifier under cursor" msgstr "E349: ฅซกผฅฝฅ๋คฮฐฬรึคหคฯผฑสฬปาคฌคขค๊คคปค๓" -#: ../normal.c:1866 msgid "E774: 'operatorfunc' is empty" msgstr "E774: 'operatorfunc' ฅชฅืฅทฅ็ฅ๓คฌถ๕ควคน" -#: ../normal.c:2637 +msgid "E775: Eval feature not available" +msgstr "E775: ผฐษพฒมตกวฝคฌฬตธ๚คหคสครคฦคคคคน" + msgid "Warning: terminal cannot highlight" msgstr "ทูน๐: ปศอัคทคฦคคค๋รผห๖คฯฅฯฅคฅ้ฅคฅศควคญคคปค๓" -#: ../normal.c:2807 msgid "E348: No string under cursor" msgstr "E348: ฅซกผฅฝฅ๋คฮฐฬรึคหคฯสธป๚ฮ๓คฌคขค๊คคปค๓" -#: ../normal.c:3937 msgid "E352: Cannot erase folds with current 'foldmethod'" msgstr "E352: ธฝบ฿คฮ 'foldmethod' ควคฯภพ๖ค฿ค๒พรต๎ควคญคคปค๓" -#: ../normal.c:5897 msgid "E664: changelist is empty" msgstr "E664: สันนฅ๊ฅนฅศคฌถ๕ควคน" -#: ../normal.c:5899 msgid "E662: At start of changelist" msgstr "E662: สันนฅ๊ฅนฅศคฮภ่ฦฌ" -#: ../normal.c:5901 msgid "E663: At end of changelist" msgstr "E663: สันนฅ๊ฅนฅศคฮห๖ศ๘" -#: ../normal.c:7053 -msgid "Type :quit<Enter> to exit Nvim" +msgid "Type :quit<Enter> to exit Vim" msgstr "Vimค๒ฝชฮปคนค๋คหคฯ :quit<Enter> คศฦฮฯคทคฦคฏคภคตคค" -#: ../ops.c:248 #, c-format msgid "1 line %sed 1 time" msgstr "1 นิคฌ %s คว 1 ฒ๓ฝ่อคตค์คคทคฟ" -#: ../ops.c:250 #, c-format msgid "1 line %sed %d times" msgstr "1 นิคฌ %s คว %d ฒ๓ฝ่อคตค์คคทคฟ" -#: ../ops.c:253 #, c-format -msgid "%<PRId64> lines %sed 1 time" -msgstr "%<PRId64> นิคฌ %s คว 1 ฒ๓ฝ่อคตค์คคทคฟ" +msgid "%ld lines %sed 1 time" +msgstr "%ld นิคฌ %s คว 1 ฒ๓ฝ่อคตค์คคทคฟ" -#: ../ops.c:256 #, c-format -msgid "%<PRId64> lines %sed %d times" -msgstr "%<PRId64> นิคฌ %s คว %d ฒ๓ฝ่อคตค์คคทคฟ" +msgid "%ld lines %sed %d times" +msgstr "%ld นิคฌ %s คว %d ฒ๓ฝ่อคตค์คคทคฟ" -#: ../ops.c:592 #, c-format -msgid "%<PRId64> lines to indent... " -msgstr "%<PRId64> นิคฌฅคฅ๓ฅวฅ๓ฅศคตค์คคน... " +msgid "%ld lines to indent... " +msgstr "%ld นิคฌฅคฅ๓ฅวฅ๓ฅศคตค์คคน... " -#: ../ops.c:634 msgid "1 line indented " msgstr "1 นิค๒ฅคฅ๓ฅวฅ๓ฅศคทคคทคฟ " -#: ../ops.c:636 #, c-format -msgid "%<PRId64> lines indented " -msgstr "%<PRId64> นิค๒ฅคฅ๓ฅวฅ๓ฅศคทคคทคฟ " +msgid "%ld lines indented " +msgstr "%ld นิค๒ฅคฅ๓ฅวฅ๓ฅศคทคคทคฟ " -#: ../ops.c:938 msgid "E748: No previously used register" msgstr "E748: คคภฅ์ฅธฅนฅฟค๒ปศอัคทคฦคคคคปค๓" #. must display the prompt -#: ../ops.c:1433 msgid "cannot yank; delete anyway" msgstr "ฅไฅ๓ฅฏควคญคคปค๓; คศคหคซคฏพรต๎" -#: ../ops.c:1929 msgid "1 line changed" msgstr "1 นิคฌสันนคตค์คคทคฟ" -#: ../ops.c:1931 #, c-format -msgid "%<PRId64> lines changed" -msgstr "%<PRId64> นิคฌสันนคตค์คคทคฟ" +msgid "%ld lines changed" +msgstr "%ld นิคฌสันนคตค์คคทคฟ" + +#, c-format +msgid "freeing %ld lines" +msgstr "%ld นิค๒ฒ๒สรๆ" -#: ../ops.c:2521 msgid "block of 1 line yanked" msgstr "1 นิคฮฅึฅํฅรฅฏคฌฅไฅ๓ฅฏคตค์คคทคฟ" -#: ../ops.c:2523 msgid "1 line yanked" msgstr "1 นิคฌฅไฅ๓ฅฏคตค์คคทคฟ" -#: ../ops.c:2525 #, c-format -msgid "block of %<PRId64> lines yanked" -msgstr "%<PRId64> นิคฮฅึฅํฅรฅฏคฌฅไฅ๓ฅฏคตค์คคทคฟ" +msgid "block of %ld lines yanked" +msgstr "%ld นิคฮฅึฅํฅรฅฏคฌฅไฅ๓ฅฏคตค์คคทคฟ" -#: ../ops.c:2528 #, c-format -msgid "%<PRId64> lines yanked" -msgstr "%<PRId64> นิคฌฅไฅ๓ฅฏคตค์คคทคฟ" +msgid "%ld lines yanked" +msgstr "%ld นิคฌฅไฅ๓ฅฏคตค์คคทคฟ" -#: ../ops.c:2710 #, c-format msgid "E353: Nothing in register %s" msgstr "E353: ฅ์ฅธฅนฅฟ %s คหคฯฒฟคโคขค๊คคปค๓" #. Highlight title -#: ../ops.c:3185 msgid "" "\n" "--- Registers ---" @@ -4486,11 +4137,9 @@ msgstr "" "\n" "--- ฅ์ฅธฅนฅฟ ---" -#: ../ops.c:4455 msgid "Illegal register name" msgstr "ษิภตคสฅ์ฅธฅนฅฟฬพ" -#: ../ops.c:4533 msgid "" "\n" "# Registers:\n" @@ -4498,7 +4147,6 @@ msgstr "" "\n" "# ฅ์ฅธฅนฅฟ:\n" -#: ../ops.c:4575 #, c-format msgid "E574: Unknown register type %d" msgstr "E574: ฬครฮคฮฅ์ฅธฅนฅฟทฟ %d ควคน" @@ -4508,86 +4156,61 @@ msgid "" "lines" msgstr "E883: ธกบ๗ฅัฅฟกผฅ๓คศผฐฅ์ฅธฅนฅฟคหคฯ2นิฐสพๅค๒ดคแค้ค์คคปค๓" -#: ../ops.c:5089 #, c-format -msgid "%<PRId64> Cols; " -msgstr "%<PRId64> ฮ๓; " +msgid "%ld Cols; " +msgstr "%ld ฮ๓; " -#: ../ops.c:5097 #, c-format -msgid "" -"Selected %s%<PRId64> of %<PRId64> Lines; %<PRId64> of %<PRId64> Words; " -"%<PRId64> of %<PRId64> Bytes" -msgstr "" -"มชย๒ %s%<PRId64> / %<PRId64> นิ; %<PRId64> / %<PRId64> รฑธ์; %<PRId64> / " -"%<PRId64> ฅะฅคฅศ" +msgid "Selected %s%ld of %ld Lines; %lld of %lld Words; %lld of %lld Bytes" +msgstr "มชย๒ %s%ld / %ld นิ; %lld / %lld รฑธ์; %lld / %lld ฅะฅคฅศ" -#: ../ops.c:5105 #, c-format msgid "" -"Selected %s%<PRId64> of %<PRId64> Lines; %<PRId64> of %<PRId64> Words; " -"%<PRId64> of %<PRId64> Chars; %<PRId64> of %<PRId64> Bytes" +"Selected %s%ld of %ld Lines; %lld of %lld Words; %lld of %lld Chars; %lld of " +"%lld Bytes" msgstr "" -"มชย๒ %s%<PRId64> / %<PRId64> นิ; %<PRId64> / %<PRId64> รฑธ์; %<PRId64> / " -"%<PRId64> สธป๚; %<PRId64> / %<PRId64> ฅะฅคฅศ" +"มชย๒ %s%ld / %ld นิ; %lld / %lld รฑธ์; %lld / %lld สธป๚; %lld / %lld ฅะฅคฅศ" -#: ../ops.c:5123 #, c-format -msgid "" -"Col %s of %s; Line %<PRId64> of %<PRId64>; Word %<PRId64> of %<PRId64>; Byte " -"%<PRId64> of %<PRId64>" -msgstr "" -"ฮ๓ %s / %s; นิ %<PRId64> of %<PRId64>; รฑธ์ %<PRId64> / %<PRId64>; ฅะฅคฅศ " -"%<PRId64> / %<PRId64>" +msgid "Col %s of %s; Line %ld of %ld; Word %lld of %lld; Byte %lld of %lld" +msgstr "ฮ๓ %s / %s; นิ %ld of %ld; รฑธ์ %lld / %lld; ฅะฅคฅศ %lld / %lld" -#: ../ops.c:5133 #, c-format msgid "" -"Col %s of %s; Line %<PRId64> of %<PRId64>; Word %<PRId64> of %<PRId64>; Char " -"%<PRId64> of %<PRId64>; Byte %<PRId64> of %<PRId64>" +"Col %s of %s; Line %ld of %ld; Word %lld of %lld; Char %lld of %lld; Byte " +"%lld of %lld" msgstr "" -"ฮ๓ %s / %s; นิ %<PRId64> / %<PRId64>; รฑธ์ %<PRId64> / %<PRId64>; สธป๚ " -"%<PRId64> / %<PRId64>; ฅะฅคฅศ %<PRId64> of %<PRId64>" +"ฮ๓ %s / %s; นิ %ld / %ld; รฑธ์ %lld / %lld; สธป๚ %lld / %lld; ฅะฅคฅศ %lld of " +"%lld" -#: ../ops.c:5146 #, c-format -msgid "(+%<PRId64> for BOM)" -msgstr "(+%<PRId64> for BOM)" +msgid "(+%ld for BOM)" +msgstr "(+%ld for BOM)" -#: ../option.c:1238 msgid "%<%f%h%m%=Page %N" msgstr "%<%f%h%m%=%N ฅฺกผฅธ" -#: ../option.c:1574 msgid "Thanks for flying Vim" msgstr "Vim ค๒ปศครคฦคฏค์คฦคขค๊คฌคศคฆ" -#. found a mismatch: skip -#: ../option.c:2698 msgid "E518: Unknown option" msgstr "E518: ฬครฮคฮฅชฅืฅทฅ็ฅ๓ควคน" -#: ../option.c:2709 msgid "E519: Option not supported" msgstr "E519: ฅชฅืฅทฅ็ฅ๓คฯฅตฅกผฅศคตค์คฦคคคคปค๓" -#: ../option.c:2740 msgid "E520: Not allowed in a modeline" msgstr "E520: modeline ควคฯต๖ฒฤคตค์คคปค๓" -#: ../option.c:2815 msgid "E846: Key code not set" msgstr "E846: ฅญกผฅณกผฅษคฌภ฿ฤ๊คตค์คฦคคคคปค๓" -#: ../option.c:2924 msgid "E521: Number required after =" msgstr "E521: = คฮธๅคหคฯฟ๔ป๚คฌษฌอืควคน" -#: ../option.c:3226 ../option.c:3864 msgid "E522: Not found in termcap" msgstr "E522: termcap ฦโคหธซคฤคซค๊คคปค๓" -#: ../option.c:3335 #, c-format msgid "E539: Illegal character <%s>" msgstr "E539: ษิภตคสสธป๚ควคน <%s>" @@ -4596,93 +4219,99 @@ msgstr "E539: ษิภตคสสธป๚ควคน <%s>" msgid "For option %s" msgstr "ฅชฅืฅทฅ็ฅ๓: %s" -#: ../option.c:3862 msgid "E529: Cannot set 'term' to empty string" msgstr "E529: 'term' คหคฯถ๕สธป๚ฮ๓ค๒ภ฿ฤ๊ควคญคคปค๓" -#: ../option.c:3885 +msgid "E530: Cannot change term in GUI" +msgstr "E530: GUIควคฯ 'term' ค๒สันนควคญคคปค๓" + +msgid "E531: Use \":gui\" to start the GUI" +msgstr "E531: GUIค๒ฅนฅฟกผฅศคนค๋คหคฯ \":gui\" ค๒ปศอัคทคฦคฏคภคตคค" + msgid "E589: 'backupext' and 'patchmode' are equal" msgstr "E589: 'backupext' คศ 'patchmode' คฌฦฑคธควคน" -#: ../option.c:3964 msgid "E834: Conflicts with value of 'listchars'" msgstr "E834: 'listchars'คฮรอคหฬทฝโคฌคขค๊คคน" -#: ../option.c:3966 msgid "E835: Conflicts with value of 'fillchars'" msgstr "E835: 'fillchars'คฮรอคหฬทฝโคฌคขค๊คคน" -#: ../option.c:4163 +msgid "E617: Cannot be changed in the GTK+ 2 GUI" +msgstr "E617: GTK+2 GUIควคฯสันนควคญคคปค๓" + msgid "E524: Missing colon" msgstr "E524: ฅณฅํฅ๓คฌคขค๊คคปค๓" -#: ../option.c:4165 msgid "E525: Zero length string" msgstr "E525: สธป๚ฮ๓คฮฤนคตคฌฅผฅํควคน" -#: ../option.c:4220 #, c-format msgid "E526: Missing number after <%s>" msgstr "E526: <%s> คฮธๅคหฟ๔ป๚คฌคขค๊คคปค๓" -#: ../option.c:4232 msgid "E527: Missing comma" msgstr "E527: ฅซฅ๓ฅคฌคขค๊คคปค๓" -#: ../option.c:4239 msgid "E528: Must specify a ' value" msgstr "E528: ' คฮรอค๒ปุฤ๊คทคสคฑค์คะคสค๊คคปค๓" -#: ../option.c:4271 msgid "E595: contains unprintable or wide character" msgstr "E595: ษฝผจควคญคสคคสธป๚คซฅ๏ฅคฅษสธป๚ค๒ดค๓ควคคคคน" -#: ../option.c:4469 +msgid "E596: Invalid font(s)" +msgstr "E596: ฬตธ๚คสฅีฅฉฅ๓ฅศควคน" + +msgid "E597: can't select fontset" +msgstr "E597: ฅีฅฉฅ๓ฅศฅปฅรฅศค๒มชย๒ควคญคคปค๓" + +msgid "E598: Invalid fontset" +msgstr "E598: ฬตธ๚คสฅีฅฉฅ๓ฅศฅปฅรฅศควคน" + +msgid "E533: can't select wide font" +msgstr "E533: ฅ๏ฅคฅษฅีฅฉฅ๓ฅศค๒มชย๒ควคญคคปค๓" + +msgid "E534: Invalid wide font" +msgstr "E534: ฬตธ๚คสฅ๏ฅคฅษฅีฅฉฅ๓ฅศควคน" + #, c-format msgid "E535: Illegal character after <%c>" msgstr "E535: <%c> คฮธๅคหษิภตคสสธป๚คฌคขค๊คคน" -#: ../option.c:4534 msgid "E536: comma required" msgstr "E536: ฅซฅ๓ฅคฌษฌอืควคน" -#: ../option.c:4543 #, c-format msgid "E537: 'commentstring' must be empty or contain %s" msgstr "E537: 'commentstring' คฯถ๕ควคขค๋คซ %s ค๒ดคเษฌอืคฌคขค๊คคน" -#: ../option.c:4928 +msgid "E538: No mouse support" +msgstr "E538: ฅฅฆฅนคฯฅตฅกผฅศคตค์คคปค๓" + msgid "E540: Unclosed expression sequence" msgstr "E540: ผฐคฌฝชฮปคทคฦคคคคปค๓" -#: ../option.c:4932 msgid "E541: too many items" msgstr "E541: อืมวคฌยฟฒแคฎคคน" -#: ../option.c:4934 msgid "E542: unbalanced groups" msgstr "E542: ฅฐฅ๋กผฅืคฌฤเน็คคคคปค๓" -#: ../option.c:5148 msgid "E590: A preview window already exists" msgstr "E590: ฅืฅ์ฅำฅๅกผฅฆฅฃฅ๓ฅษฅฆคฌด๛คหยธบ฿คทคคน" -#: ../option.c:5311 msgid "W17: Arabic requires UTF-8, do ':set encoding=utf-8'" msgstr "" "W17: ฅขฅ้ฅำฅขสธป๚คหคฯUTF-8คฌษฌอืคสคฮคว, ':set encoding=utf-8' คทคฦคฏคภคตคค" -#: ../option.c:5623 #, c-format msgid "E593: Need at least %d lines" msgstr "E593: บวฤใ %d คฮนิฟ๔คฌษฌอืควคน" -#: ../option.c:5631 #, c-format msgid "E594: Need at least %d columns" msgstr "E594: บวฤใ %d คฮฅซฅ้ฅเษคฌษฌอืควคน" -#: ../option.c:6011 #, c-format msgid "E355: Unknown option: %s" msgstr "E355: ฬครฮคฮฅชฅืฅทฅ็ฅ๓ควคน: %s" @@ -4690,12 +4319,10 @@ msgstr "E355: ฬครฮคฮฅชฅืฅทฅ็ฅ๓ควคน: %s" #. There's another character after zeros or the string #. * is empty. In both cases, we are trying to set a #. * num option using a string. -#: ../option.c:6037 #, c-format msgid "E521: Number required: &%s = '%s'" msgstr "E521: ฟ๔ป๚คฌษฌอืควคน: &%s = '%s'" -#: ../option.c:6149 msgid "" "\n" "--- Terminal codes ---" @@ -4703,7 +4330,6 @@ msgstr "" "\n" "--- รผห๖ฅณกผฅษ ---" -#: ../option.c:6151 msgid "" "\n" "--- Global option values ---" @@ -4711,7 +4337,6 @@ msgstr "" "\n" "--- ฅฐฅํกผฅะฅ๋ฅชฅืฅทฅ็ฅ๓รอ ---" -#: ../option.c:6153 msgid "" "\n" "--- Local option values ---" @@ -4719,7 +4344,6 @@ msgstr "" "\n" "--- ฅํกผฅซฅ๋ฅชฅืฅทฅ็ฅ๓รอ ---" -#: ../option.c:6155 msgid "" "\n" "--- Options ---" @@ -4727,37 +4351,119 @@ msgstr "" "\n" "--- ฅชฅืฅทฅ็ฅ๓ ---" -#: ../option.c:6816 msgid "E356: get_varp ERROR" msgstr "E356: get_varp ฅจฅ้กผ" -#: ../option.c:7696 #, c-format msgid "E357: 'langmap': Matching character missing for %s" msgstr "E357: 'langmap': %s คหยะฑคนค๋สธป๚คฌคขค๊คคปค๓" -#: ../option.c:7715 #, c-format msgid "E358: 'langmap': Extra characters after semicolon: %s" msgstr "E358: 'langmap': ฅปฅ฿ฅณฅํฅ๓คฮธๅคหอพสฌคสสธป๚คฌคขค๊คคน: %s" -#: ../os/shell.c:194 -msgid "" -"\n" -"Cannot execute shell " -msgstr "" -"\n" -"ฅทฅงฅ๋ค๒ผยนิควคญคคปค๓ " +msgid "cannot open " +msgstr "ณซคฑคคปค๓ " + +msgid "VIM: Can't open window!\n" +msgstr "VIM: ฅฆฅฃฅ๓ฅษฅฆค๒ณซคฑคคปค๓!\n" + +msgid "Need Amigados version 2.04 or later\n" +msgstr "Amigadosคฮฅะกผฅธฅ็ฅ๓ 2.04คซคฝค์ฐสน฿คฌษฌอืควคน\n" + +#, c-format +msgid "Need %s version %ld\n" +msgstr "%s คฮฅะกผฅธฅ็ฅ๓ %ld คฌษฌอืควคน\n" + +msgid "Cannot open NIL:\n" +msgstr "NILค๒ณซคฑคคปค๓:\n" + +msgid "Cannot create " +msgstr "บ๎ภฎควคญคคปค๓ " + +#, c-format +msgid "Vim exiting with %d\n" +msgstr "Vimคฯ %d ควฝชฮปคทคคน\n" + +msgid "cannot change console mode ?!\n" +msgstr "ฅณฅ๓ฅฝกผฅ๋ฅโกผฅษค๒สันนควคญคคปค๓?!\n" + +msgid "mch_get_shellsize: not a console??\n" +msgstr "mch_get_shellsize: ฅณฅ๓ฅฝกผฅ๋ควคฯคสคค??\n" + +#. if Vim opened a window: Executing a shell may cause crashes +msgid "E360: Cannot execute shell with -f option" +msgstr "E360: -f ฅชฅืฅทฅ็ฅ๓ควฅทฅงฅ๋ค๒ผยนิควคญคคปค๓" + +msgid "Cannot execute " +msgstr "ผยนิควคญคคปค๓ " + +msgid "shell " +msgstr "ฅทฅงฅ๋ " + +msgid " returned\n" +msgstr " ฬแค๊คคทคฟ\n" + +msgid "ANCHOR_BUF_SIZE too small." +msgstr "ANCHOR_BUF_SIZE คฌพฎคตฒแคฎคคน." + +msgid "I/O ERROR" +msgstr "ฦฝะฮฯฅจฅ้กผ" + +msgid "Message" +msgstr "ฅแฅรฅปกผฅธ" + +msgid "'columns' is not 80, cannot execute external commands" +msgstr "'columns' คฌ 80 ควคฯคสคคคฟคแกขณฐษ๔ฅณฅฅ๓ฅษค๒ผยนิควคญคคปค๓" + +msgid "E237: Printer selection failed" +msgstr "E237: ฅืฅ๊ฅ๓ฅฟคฮมชย๒คหผบวิคทคคทคฟ" + +#, c-format +msgid "to %s on %s" +msgstr "%s คุ (%s พๅคฮ)" + +#, c-format +msgid "E613: Unknown printer font: %s" +msgstr "E613: ฬครฮคฮฅืฅ๊ฅ๓ฅฟฅชฅืฅทฅ็ฅ๓ควคน: %s" + +#, c-format +msgid "E238: Print error: %s" +msgstr "E238: ฐ๕บฅจฅ้กผ: %s" + +#, c-format +msgid "Printing '%s'" +msgstr "ฐ๕บคทคฦคคคคน: '%s'" + +#, c-format +msgid "E244: Illegal charset name \"%s\" in font name \"%s\"" +msgstr "E244: สธป๚ฅปฅรฅศฬพ \"%s\" คฯษิภตควคน (ฅีฅฉฅ๓ฅศฬพ \"%s\")" + +#, c-format +msgid "E244: Illegal quality name \"%s\" in font name \"%s\"" +msgstr "E244: ษสผมฬพ \"%s\" คฯษิภตควคน (ฅีฅฉฅ๓ฅศฬพ \"%s\")" + +#, c-format +msgid "E245: Illegal char '%c' in font name \"%s\"" +msgstr "E245: '%c' คฯษิภตคสสธป๚ควคน (ฅีฅฉฅ๓ฅศฬพ \"%s\")" + +#, c-format +msgid "Opening the X display took %ld msec" +msgstr "Xฅตกผฅะกผคุคฮภยณคห %ld ฅ฿ฅ๊ษรคซคซค๊คคทคฟ" -#: ../os/shell.c:439 msgid "" "\n" -"shell returned " +"Vim: Got X error\n" msgstr "" "\n" -"ฅทฅงฅ๋คฌรอค๒สึคทคคทคฟ " +"Vim: X คฮฅจฅ้กผค๒ธกฝะคทคคทคฟr\n" + +msgid "Testing the X display failed" +msgstr "X display คฮฅมฅงฅรฅฏคหผบวิคทคคทคฟ" + +msgid "Opening the X display timed out" +msgstr "X display คฮ open คฌฅฟฅคฅเฅขฅฆฅศคทคคทคฟ" -#: ../os_unix.c:465 ../os_unix.c:471 msgid "" "\n" "Could not get security context for " @@ -4765,7 +4471,6 @@ msgstr "" "\n" "ฅปฅญฅๅฅ๊ฅฦฅฃฅณฅ๓ฅฦฅญฅนฅศค๒ผ่ฦภควคญคคปค๓ " -#: ../os_unix.c:479 msgid "" "\n" "Could not set security context for " @@ -4781,223 +4486,293 @@ msgstr "ฅปฅญฅๅฅ๊ฅฦฅฃฅณฅ๓ฅฦฅญฅนฅศ %s ค๒ %s คหภ฿ฤ๊ควคญคคปค๓" msgid "Could not get security context %s for %s. Removing it!" msgstr "ฅปฅญฅๅฅ๊ฅฦฅฃฅณฅ๓ฅฦฅญฅนฅศ %s ค๒ %s คซค้ผ่ฦภควคญคคปค๓. บ๏ฝคทคคน!" -#: ../os_unix.c:1558 ../os_unix.c:1647 +msgid "" +"\n" +"Cannot execute shell sh\n" +msgstr "" +"\n" +"sh ฅทฅงฅ๋ค๒ผยนิควคญคคปค๓\n" + +msgid "" +"\n" +"shell returned " +msgstr "" +"\n" +"ฅทฅงฅ๋คฌรอค๒สึคทคคทคฟ " + +msgid "" +"\n" +"Cannot create pipes\n" +msgstr "" +"\n" +"ฅัฅคฅืค๒บ๎ภฎควคญคคปค๓\n" + +msgid "" +"\n" +"Cannot fork\n" +msgstr "" +"\n" +"fork ควคญคคปค๓\n" + +msgid "" +"\n" +"Cannot execute shell " +msgstr "" +"\n" +"ฅทฅงฅ๋ค๒ผยนิควคญคคปค๓ " + +msgid "" +"\n" +"Command terminated\n" +msgstr "" +"\n" +"ฅณฅฅ๓ฅษค๒รๆรวคทคคทคฟ\n" + +msgid "XSMP lost ICE connection" +msgstr "XSMP คฌICEภยณค๒ผบคคคคทคฟ" + #, c-format msgid "dlerror = \"%s\"" msgstr "dlerror = \"%s\"" -#: ../path.c:1449 +msgid "Opening the X display failed" +msgstr "X display คฮ open คหผบวิคทคคทคฟ" + +msgid "XSMP handling save-yourself request" +msgstr "XSMP คฌsave-yourselfอืตแค๒ฝ่อคทคฦคคคคน" + +msgid "XSMP opening connection" +msgstr "XSMP คฌภยณค๒ณซปฯคทคฦคคคคน" + +msgid "XSMP ICE connection watch failed" +msgstr "XSMP ICEภยณคฌผบวิคทคฟค่คฆควคน" + #, c-format -msgid "E447: Can't find file \"%s\" in path" -msgstr "E447: pathคหคฯ \"%s\" คศคคคฆฅีฅกฅคฅ๋คฌคขค๊คคปค๓" +msgid "XSMP SmcOpenConnection failed: %s" +msgstr "XSMP SmcOpenConnectionคฌผบวิคทคคทคฟ: %s" + +msgid "At line" +msgstr "นิ" + +msgid "Could not load vim32.dll!" +msgstr "vim32.dll ค๒ฅํกผฅษควคญคคปค๓ควคทคฟ" + +msgid "VIM Error" +msgstr "VIMฅจฅ้กผ" + +msgid "Could not fix up function pointers to the DLL!" +msgstr "DLLคซค้ดุฟ๔ฅฅคฅ๓ฅฟค๒ผ่ฦภควคญคคปค๓ควคทคฟ" + +#, c-format +msgid "Vim: Caught %s event\n" +msgstr "Vim: ฅคฅูฅ๓ฅศ %s ค๒ธกรฮ\n" + +msgid "close" +msgstr "สฤคธค๋" + +msgid "logoff" +msgstr "ฅํฅฐฅชฅี" + +msgid "shutdown" +msgstr "ฅทฅใฅรฅศฅภฅฆฅ๓" + +msgid "E371: Command not found" +msgstr "E371: ฅณฅฅ๓ฅษคฌคขค๊คคปค๓" + +msgid "" +"VIMRUN.EXE not found in your $PATH.\n" +"External commands will not pause after completion.\n" +"See :help win32-vimrun for more information." +msgstr "" +"VIMRUN.EXEคฌ $PATH คฮรๆคหธซคฤคซค๊คคปค๓.\n" +"ณฐษ๔ฅณฅฅ๓ฅษคฮฝชฮปธๅคหฐ์ปฤไป฿ค๒คทคคปค๓.\n" +"พบูคฯ :help win32-vimrun ค๒ปฒพศคทคฦคฏคภคตคค." + +msgid "Vim Warning" +msgstr "Vimคฮทูน๐" + +#, c-format +msgid "shell returned %d" +msgstr "ฅทฅงฅ๋คฌฅณกผฅษ %d ควฝชฮปคทคคทคฟ" -#: ../quickfix.c:359 #, c-format msgid "E372: Too many %%%c in format string" msgstr "E372: ฅีฅฉกผฅฅรฅศสธป๚ฮ๓คห %%%c คฌยฟฒแคฎคคน" -#: ../quickfix.c:371 #, c-format msgid "E373: Unexpected %%%c in format string" msgstr "E373: ฅีฅฉกผฅฅรฅศสธป๚ฮ๓คหอฝดคปคฬ %%%c คฌคขค๊คคทคฟ" -#: ../quickfix.c:420 msgid "E374: Missing ] in format string" msgstr "E374: ฅีฅฉกผฅฅรฅศสธป๚ฮ๓คห ] คฌคขค๊คคปค๓" -#: ../quickfix.c:431 #, c-format msgid "E375: Unsupported %%%c in format string" msgstr "E375: ฅีฅฉกผฅฅรฅศสธป๚ฮ๓ควคฯ %%%c คฯฅตฅกผฅศคตค์คคปค๓" -#: ../quickfix.c:448 #, c-format msgid "E376: Invalid %%%c in format string prefix" msgstr "E376: ฅีฅฉกผฅฅรฅศสธป๚ฮ๓คฮมฐรึคหฬตธ๚คส %%%c คฌคขค๊คคน" -#: ../quickfix.c:454 #, c-format msgid "E377: Invalid %%%c in format string" msgstr "E377: ฅีฅฉกผฅฅรฅศสธป๚ฮ๓คหฬตธ๚คส %%%c คฌคขค๊คคน" #. nothing found -#: ../quickfix.c:477 msgid "E378: 'errorformat' contains no pattern" msgstr "E378: 'errorformat' คหฅัฅฟกผฅ๓คฌปุฤ๊คตค์คฦคคคคปค๓" -#: ../quickfix.c:695 msgid "E379: Missing or empty directory name" msgstr "E379: ฅวฅฃฅ์ฅฏฅศฅ๊ฬพคฌฬตคคคซถ๕ควคน" -#: ../quickfix.c:1305 msgid "E553: No more items" msgstr "E553: อืมวคฌคโคฆคขค๊คคปค๓" -#: ../quickfix.c:1674 +msgid "E924: Current window was closed" +msgstr "E924: ธฝบ฿คฮฅฆฅฃฅ๓ฅษฅฆคฌสฤคธค้ค์คคทคฟ" + +msgid "E925: Current quickfix was changed" +msgstr "E925: ธฝบ฿คฮ quickfix คฌสันนคตค์คคทคฟ" + +msgid "E926: Current location list was changed" +msgstr "E926: ธฝบ฿คฮฅํฅฑกผฅทฅ็ฅ๓ฅ๊ฅนฅศคฌสันนคตค์คคทคฟ" + #, c-format msgid "(%d of %d)%s%s: " msgstr "(%d of %d)%s%s: " -#: ../quickfix.c:1676 msgid " (line deleted)" msgstr " (นิคฌบ๏ฝคตค์คคทคฟ)" -#: ../quickfix.c:1863 +#, c-format +msgid "%serror list %d of %d; %d errors " +msgstr "%s ฅจฅ้กผฐ์อ๗ %d of %d; %d ธฤฅจฅ้กผ" + msgid "E380: At bottom of quickfix stack" msgstr "E380: quickfix ฅนฅฟฅรฅฏคฮห๖ศ๘ควคน" -#: ../quickfix.c:1869 msgid "E381: At top of quickfix stack" msgstr "E381: quickfix ฅนฅฟฅรฅฏคฮภ่ฦฌควคน" -#: ../quickfix.c:1880 -#, c-format -msgid "error list %d of %d; %d errors" -msgstr "ฅจฅ้กผฐ์อ๗ %d of %d; %d ธฤฅจฅ้กผ" +msgid "No entries" +msgstr "ฅจฅ๓ฅศฅ๊คฌคขค๊คคปค๓" -#: ../quickfix.c:2427 msgid "E382: Cannot write, 'buftype' option is set" msgstr "E382: 'buftype' ฅชฅืฅทฅ็ฅ๓คฌภ฿ฤ๊คตค์คฦคคค๋คฮควฝ๑นค฿คคปค๓" -#: ../quickfix.c:2812 +msgid "Error file" +msgstr "ฅจฅ้กผฅีฅกฅคฅ๋" + msgid "E683: File name missing or invalid pattern" msgstr "E683: ฅีฅกฅคฅ๋ฬพคฌฬตคคคซฬตธ๚คสฅัฅฟกผฅ๓ควคน" -#: ../quickfix.c:2911 #, c-format msgid "Cannot open file \"%s\"" msgstr "ฅีฅกฅคฅ๋ \"%s\" ค๒ณซคฑคคปค๓" -#: ../quickfix.c:3429 msgid "E681: Buffer is not loaded" msgstr "E681: ฅะฅรฅีฅกคฯฦษค฿นคค์คคปค๓ควคทคฟ" -#: ../quickfix.c:3487 msgid "E777: String or List expected" msgstr "E777: สธป๚ฮ๓คซฅ๊ฅนฅศคฌษฌอืควคน" -#: ../regexp.c:359 #, c-format msgid "E369: invalid item in %s%%[]" msgstr "E369: ฬตธ๚คสนเฬควคน: %s%%[]" # -#: ../regexp.c:374 #, c-format msgid "E769: Missing ] after %s[" msgstr "E769: %s[ คฮธๅคห ] คฌคขค๊คคปค๓" -#: ../regexp.c:375 #, c-format msgid "E53: Unmatched %s%%(" msgstr "E53: %s%%( คฌฤเค๊น็ครคฦคคคคปค๓" -#: ../regexp.c:376 #, c-format msgid "E54: Unmatched %s(" msgstr "E54: %s( คฌฤเค๊น็ครคฦคคคคปค๓" -#: ../regexp.c:377 #, c-format msgid "E55: Unmatched %s)" msgstr "E55: %s) คฌฤเค๊น็ครคฦคคคคปค๓" # -#: ../regexp.c:378 msgid "E66: \\z( not allowed here" msgstr "E66: \\z( คฯฅณฅณควคฯต๖ฒฤคตค์คฦคคคคปค๓" # -#: ../regexp.c:379 msgid "E67: \\z1 et al. not allowed here" msgstr "E67: \\z1 คฝคฮยพคฯฅณฅณควคฯต๖ฒฤคตค์คฦคคคคปค๓" # -#: ../regexp.c:380 #, c-format msgid "E69: Missing ] after %s%%[" msgstr "E69: %s%%[ คฮธๅคห ] คฌคขค๊คคปค๓" -#: ../regexp.c:381 #, c-format msgid "E70: Empty %s%%[]" msgstr "E70: %s%%[] คฌถ๕ควคน" -#: ../regexp.c:1209 ../regexp.c:1224 msgid "E339: Pattern too long" msgstr "E339: ฅัฅฟกผฅ๓คฌฤนฒแคฎคคน" -#: ../regexp.c:1371 msgid "E50: Too many \\z(" msgstr "E50: \\z( คฌยฟฒแคฎคคน" -#: ../regexp.c:1378 #, c-format msgid "E51: Too many %s(" msgstr "E51: %s( คฌยฟฒแคฎคคน" -#: ../regexp.c:1427 msgid "E52: Unmatched \\z(" msgstr "E52: \\z( คฌฤเค๊น็ครคฦคคคคปค๓" -#: ../regexp.c:1637 #, c-format msgid "E59: invalid character after %s@" msgstr "E59: %s@ คฮธๅคหษิภตคสสธป๚คฌคขค๊คคทคฟ" -#: ../regexp.c:1672 #, c-format msgid "E60: Too many complex %s{...}s" msgstr "E60: สฃปจคส %s{...} คฌยฟฒแคฎคคน" -#: ../regexp.c:1687 #, c-format msgid "E61: Nested %s*" msgstr "E61:%s* คฌฦค์ปาคหคสครคฦคคคคน" -#: ../regexp.c:1690 #, c-format msgid "E62: Nested %s%c" msgstr "E62:%s%c คฌฦค์ปาคหคสครคฦคคคคน" # -#: ../regexp.c:1800 msgid "E63: invalid use of \\_" msgstr "E63: \\_ คฮฬตธ๚คสปศอัสหกควคน" -#: ../regexp.c:1850 #, c-format msgid "E64: %s%c follows nothing" msgstr "E64:%s%c คฮธๅคหคสคหคโคขค๊คคปค๓" # -#: ../regexp.c:1902 msgid "E65: Illegal back reference" msgstr "E65: ษิภตคสธๅสปฒพศควคน" # -#: ../regexp.c:1943 msgid "E68: Invalid character after \\z" msgstr "E68: \\z คฮธๅคหษิภตคสสธป๚คฌคขค๊คคทคฟ" # -#: ../regexp.c:2049 ../regexp_nfa.c:1296 #, c-format msgid "E678: Invalid character after %s%%[dxouU]" msgstr "E678: %s%%[dxouU] คฮธๅคหษิภตคสสธป๚คฌคขค๊คคทคฟ" # -#: ../regexp.c:2107 #, c-format msgid "E71: Invalid character after %s%%" msgstr "E71: %s%% คฮธๅคหษิภตคสสธป๚คฌคขค๊คคทคฟ" -#: ../regexp.c:3017 #, c-format msgid "E554: Syntax error in %s{...}" msgstr "E554: %s{...} ฦโคหสธหกฅจฅ้กผคฌคขค๊คคน" -#: ../regexp.c:3805 msgid "External submatches:\n" msgstr "ณฐษ๔คฮษ๔สฌณบล๖:\n" @@ -5005,7 +4780,6 @@ msgstr "ณฐษ๔คฮษ๔สฌณบล๖:\n" msgid "E888: (NFA regexp) cannot repeat %s" msgstr "E888: (NFA ภตตฌษฝธฝ) ทซค๊สึคปคคปค๓ %s" -#: ../regexp.c:7022 msgid "" "E864: \\%#= can only be followed by 0, 1, or 2. The automatic engine will be " "used " @@ -5016,62 +4790,54 @@ msgstr "" msgid "Switching to backtracking RE engine for pattern: " msgstr "ผกคฮฅัฅฟกผฅ๓คหฅะฅรฅฏฅศฅ้ฅรฅญฅ๓ฅฐ RE ฅจฅ๓ฅธฅ๓ค๒ลฌอัคทคคน: " -#: ../regexp_nfa.c:239 msgid "E865: (NFA) Regexp end encountered prematurely" msgstr "E865: (NFA) ดยิค่ค๊มแคฏภตตฌษฝธฝคฮฝชรผคหลรฃคทคคทคฟ" -#: ../regexp_nfa.c:240 #, c-format msgid "E866: (NFA regexp) Misplaced %c" msgstr "E866: (NFA ภตตฌษฝธฝ) ฐฬรึคฌธํครคฦคคคคน: %c" -#: ../regexp_nfa.c:242 +# #, c-format -msgid "E877: (NFA regexp) Invalid character class: %<PRId64>" -msgstr "E877: (NFA ภตตฌษฝธฝ) ฬตธ๚คสสธป๚ฅฏฅ้ฅน: %<PRId64>" +msgid "E877: (NFA regexp) Invalid character class: %ld" +msgstr "E877: (NFA ภตตฌษฝธฝ) ฬตธ๚คสสธป๚ฅฏฅ้ฅน: %ld" -#: ../regexp_nfa.c:1261 #, c-format msgid "E867: (NFA) Unknown operator '\\z%c'" msgstr "E867: (NFA) ฬครฮคฮฅชฅฺฅ์กผฅฟควคน: '\\z%c'" -#: ../regexp_nfa.c:1387 #, c-format msgid "E867: (NFA) Unknown operator '\\%%%c'" msgstr "E867: (NFA) ฬครฮคฮฅชฅฺฅ์กผฅฟควคน: '\\%%%c'" -#: ../regexp_nfa.c:1802 +#. should never happen +msgid "E868: Error building NFA with equivalence class!" +msgstr "E868: ล๙ฒมฅฏฅ้ฅนค๒ดคเNFAนฝรคหผบวิคทคคทคฟ!" + #, c-format msgid "E869: (NFA) Unknown operator '\\@%c'" msgstr "E869: (NFA) ฬครฮคฮฅชฅฺฅ์กผฅฟควคน: '\\@%c'" -#: ../regexp_nfa.c:1831 msgid "E870: (NFA regexp) Error reading repetition limits" msgstr "E870: (NFA ภตตฌษฝธฝ) ทซค๊สึคทคฮภฉธยฒ๓ฟ๔ค๒ฦษนรๆคหฅจฅ้กผ" #. Can't have a multi follow a multi. -#: ../regexp_nfa.c:1895 msgid "E871: (NFA regexp) Can't have a multi follow a multi !" msgstr "E871: (NFA ภตตฌษฝธฝ) ทซค๊สึคท คฮธๅคห ทซค๊สึคท คฯควคญคคปค๓!" #. Too many `(' -#: ../regexp_nfa.c:2037 msgid "E872: (NFA regexp) Too many '('" msgstr "E872: (NFA ภตตฌษฝธฝ) '(' คฌยฟฒแคฎคคน" -#: ../regexp_nfa.c:2042 msgid "E879: (NFA regexp) Too many \\z(" msgstr "E879: (NFA ภตตฌษฝธฝ) \\z( คฌยฟฒแคฎคคน" -#: ../regexp_nfa.c:2066 msgid "E873: (NFA regexp) proper termination error" msgstr "E873: (NFA ภตตฌษฝธฝ) ฝชรผตญนๆคฌคขค๊คคปค๓" -#: ../regexp_nfa.c:2599 msgid "E874: (NFA) Could not pop the stack !" msgstr "E874: (NFA) ฅนฅฟฅรฅฏค๒ฅฅรฅืควคญคคปค๓!" -#: ../regexp_nfa.c:3298 msgid "" "E875: (NFA regexp) (While converting from postfix to NFA), too many states " "left on stack" @@ -5079,177 +4845,136 @@ msgstr "" "E875: (NFA ภตตฌษฝธฝ) (ธๅรึสธป๚ฮ๓ค๒NFAคหสัดนรๆคห) ฅนฅฟฅรฅฏคหปฤคตค์คฟฅนฅฦกผฅศคฌ" "ยฟฒแคฎคคน" -#: ../regexp_nfa.c:3302 msgid "E876: (NFA regexp) Not enough space to store the whole NFA " msgstr "E876: (NFA ภตตฌษฝธฝ) NFAมดยฮค๒สยธคนค๋คหคฯถ๕คญฅนฅฺกผฅนคฌยญค๊คคปค๓" -#: ../regexp_nfa.c:4571 ../regexp_nfa.c:4869 +msgid "E878: (NFA) Could not allocate memory for branch traversal!" +msgstr "E878: (NFA) ธฝบ฿ฒฃรวรๆคฮฅึฅ้ฅ๓ฅมคหฝฝสฌคสฅแฅโฅ๊ค๒ณไค๊ล๖คฦค้ค์คคปค๓!" + msgid "" "Could not open temporary log file for writing, displaying on stderr ... " msgstr "" "NFAภตตฌษฝธฝฅจฅ๓ฅธฅ๓อัคฮฅํฅฐฅีฅกฅคฅ๋ค๒ฝ๑นอัคศคทคฦณซคฑคคปค๓กฃฅํฅฐคฯษธฝเฝะฮฯคห" "ฝะฮฯคทคคนกฃ" -#: ../regexp_nfa.c:4840 #, c-format msgid "(NFA) COULD NOT OPEN %s !" msgstr "(NFA) ฅํฅฐฅีฅกฅคฅ๋ %s ค๒ณซคฑคคปค๓!" -#: ../regexp_nfa.c:6049 msgid "Could not open temporary log file for writing " msgstr "NFAภตตฌษฝธฝฅจฅ๓ฅธฅ๓อัคฮฅํฅฐฅีฅกฅคฅ๋ค๒ฝ๑นอัคศคทคฦณซคฑคคปค๓กฃ" -#: ../screen.c:7435 msgid " VREPLACE" msgstr " ฒพมรึดน" -#: ../screen.c:7437 msgid " REPLACE" msgstr " รึดน" -#: ../screen.c:7440 msgid " REVERSE" msgstr " ศฟลพ" -#: ../screen.c:7441 msgid " INSERT" msgstr " มฦ" -#: ../screen.c:7443 msgid " (insert)" msgstr " (มฦ)" -#: ../screen.c:7445 msgid " (replace)" msgstr " (รึดน)" -#: ../screen.c:7447 msgid " (vreplace)" msgstr " (ฒพมรึดน)" -#: ../screen.c:7449 msgid " Hebrew" msgstr " ฅุฅึฅ้ฅค" -#: ../screen.c:7454 msgid " Arabic" msgstr " ฅขฅ้ฅำฅข" -#: ../screen.c:7456 -msgid " (lang)" -msgstr " (ธภธ์)" - -#: ../screen.c:7459 msgid " (paste)" msgstr " (ลฝค๊ษีคฑ)" -#: ../screen.c:7469 msgid " VISUAL" msgstr " ฅำฅธฅๅฅขฅ๋" -#: ../screen.c:7470 msgid " VISUAL LINE" msgstr " ฅำฅธฅๅฅขฅ๋ นิ" -#: ../screen.c:7471 msgid " VISUAL BLOCK" msgstr " ฅำฅธฅๅฅขฅ๋ ถ๋ทม" -#: ../screen.c:7472 msgid " SELECT" msgstr " ฅปฅ์ฅฏฅศ" -#: ../screen.c:7473 msgid " SELECT LINE" msgstr " นิปุธมชย๒" -#: ../screen.c:7474 msgid " SELECT BLOCK" msgstr " ถ๋ทมมชย๒" -#: ../screen.c:7486 ../screen.c:7541 msgid "recording" msgstr "ตญฯฟรๆ" -#: ../search.c:487 #, c-format msgid "E383: Invalid search string: %s" msgstr "E383: ฬตธ๚คสธกบ๗สธป๚ฮ๓ควคน: %s" -#: ../search.c:832 #, c-format msgid "E384: search hit TOP without match for: %s" msgstr "E384: พๅคควธกบ๗คทคคทคฟคฌณบล๖ฒีฝ๊คฯคขค๊คคปค๓: %s" -#: ../search.c:835 #, c-format msgid "E385: search hit BOTTOM without match for: %s" msgstr "E385: ฒผคควธกบ๗คทคคทคฟคฌณบล๖ฒีฝ๊คฯคขค๊คคปค๓: %s" -#: ../search.c:1200 msgid "E386: Expected '?' or '/' after ';'" msgstr "E386: ';' คฮคขคศคหคฯ '?' คซ '/' คฌดยิคตค์คฦคคค๋" -#: ../search.c:4085 msgid " (includes previously listed match)" msgstr " (มฐคหฮ๓ต๓คทคฟณบล๖ฒีฝ๊ค๒ดคเ)" #. cursor at status line -#: ../search.c:4104 msgid "--- Included files " msgstr "--- ฅคฅ๓ฅฏฅ๋กผฅษคตค์คฟฅีฅกฅคฅ๋ " -#: ../search.c:4106 msgid "not found " msgstr "ธซคฤคซค๊คคปค๓ " -#: ../search.c:4107 msgid "in path ---\n" msgstr "ฅัฅนคห ----\n" -#: ../search.c:4168 msgid " (Already listed)" msgstr " (ด๛คหฮ๓ต๓)" -#: ../search.c:4170 msgid " NOT FOUND" msgstr " ธซคฤคซค๊คคปค๓" -#: ../search.c:4211 #, c-format msgid "Scanning included file: %s" msgstr "ฅคฅ๓ฅฏฅ๋กผฅษคตค์คฟฅีฅกฅคฅ๋ค๒ฅนฅญฅใฅ๓รๆ: %s" -#: ../search.c:4216 #, c-format msgid "Searching included file %s" msgstr "ฅคฅ๓ฅฏฅ๋กผฅษคตค์คฟฅีฅกฅคฅ๋ค๒ฅนฅญฅใฅ๓รๆ %s" -#: ../search.c:4405 msgid "E387: Match is on current line" msgstr "E387: ธฝบ฿นิคหณบล๖คฌคขค๊คคน" -#: ../search.c:4517 msgid "All included files were found" msgstr "มดคฦคฮฅคฅ๓ฅฏฅ๋กผฅษคตค์คฟฅีฅกฅคฅ๋คฌธซคฤคซค๊คคทคฟ" -#: ../search.c:4519 msgid "No included files" msgstr "ฅคฅ๓ฅฏฅ๋กผฅษฅีฅกฅคฅ๋คฯคขค๊คคปค๓" -#: ../search.c:4527 msgid "E388: Couldn't find definition" msgstr "E388: ฤ๊ตมค๒ธซคฤคฑค้ค์คคปค๓" -#: ../search.c:4529 msgid "E389: Couldn't find pattern" msgstr "E389: ฅัฅฟกผฅ๓ค๒ธซคฤคฑค้ค์คคปค๓" -#: ../search.c:4668 msgid "Substitute " msgstr "Substitute " -#: ../search.c:4681 #, c-format msgid "" "\n" @@ -5260,99 +4985,131 @@ msgstr "" "# บวธๅคฮ %sธกบ๗ฅัฅฟกผฅ๓:\n" "~" -#: ../spell.c:951 -msgid "E759: Format error in spell file" -msgstr "E759: ฅนฅฺฅ๋ฅีฅกฅคฅ๋คฮฝ๑ผฐฅจฅ้กผควคน" +msgid "E756: Spell checking is not enabled" +msgstr "E756: ฅนฅฺฅ๋ฅมฅงฅรฅฏคฯฬตธ๚ฒฝคตค์คฦคคคคน" + +#, c-format +msgid "Warning: Cannot find word list \"%s_%s.spl\" or \"%s_ascii.spl\"" +msgstr "" +"ทูน๐: รฑธ์ฅ๊ฅนฅศ \"%s_%s.spl\" คชค่คำ \"%s_ascii.spl\" คฯธซคฤคซค๊คคปค๓" + +#, c-format +msgid "Warning: Cannot find word list \"%s.%s.spl\" or \"%s.ascii.spl\"" +msgstr "" +"ทูน๐: รฑธ์ฅ๊ฅนฅศ \"%s.%s.spl\" คชค่คำ \"%s.ascii.spl\" คฯธซคฤคซค๊คคปค๓" + +msgid "E797: SpellFileMissing autocommand deleted buffer" +msgstr "E797: autocommand คฮ SpellFileMissing คฌฅะฅรฅีฅกค๒บ๏ฝคทคคทคฟ" + +#, c-format +msgid "Warning: region %s not supported" +msgstr "ทูน๐9: %s คศคคคฆศฯฐฯคฯฅตฅกผฅศคตค์คฦคคคคปค๓" + +msgid "Sorry, no suggestions" +msgstr "ปฤวฐควคนคฌ, ฝคภตธ๕สไคฯคขค๊คคปค๓" + +#, c-format +msgid "Sorry, only %ld suggestions" +msgstr "ปฤวฐควคนคฌ, ฝคภตธ๕สไคฯ %ld ธฤคทคซคขค๊คคปค๓" + +#. for when 'cmdheight' > 1 +#. avoid more prompt +#, c-format +msgid "Change \"%.*s\" to:" +msgstr "\"%.*s\" ค๒ผกคุสัดน:" + +#, c-format +msgid " < \"%.*s\"" +msgstr " < \"%.*s\"" + +msgid "E752: No previous spell replacement" +msgstr "E752: ฅนฅฺฅ๋รึดนคฌคคภผยนิคตค์คฦคคคคปค๓" + +#, c-format +msgid "E753: Not found: %s" +msgstr "E753: ธซคฤคซค๊คคปค๓: %s" -#: ../spell.c:952 msgid "E758: Truncated spell file" msgstr "E758: ฅนฅฺฅ๋ฅีฅกฅคฅ๋คฌภฺผ่ค้ค์คฦคคค๋ค่คฆควคน" -#: ../spell.c:953 #, c-format msgid "Trailing text in %s line %d: %s" msgstr "%s (%d นิฬ) คหยณคฏฅฦฅญฅนฅศ: %s" -#: ../spell.c:954 #, c-format msgid "Affix name too long in %s line %d: %s" msgstr "%s (%d นิฬ) คฮ affix ฬพคฌฤนฒแคฎคคน: %s" -#: ../spell.c:955 msgid "E761: Format error in affix file FOL, LOW or UPP" msgstr "" "E761: affixฅีฅกฅคฅ๋คฮ FOL, LOW คโคทคฏคฯ UPP คฮฅีฅฉกผฅฅรฅศคหฅจฅ้กผคฌคขค๊คคน" -#: ../spell.c:957 msgid "E762: Character in FOL, LOW or UPP is out of range" msgstr "E762: FOL, LOW คโคทคฏคฯ UPP คฮสธป๚คฌศฯฐฯณฐควคน" -#: ../spell.c:958 msgid "Compressing word tree..." msgstr "รฑธ์ฅฤฅ๊กผค๒ฐตฝฬคทคฦคคคคน..." -#: ../spell.c:1951 -msgid "E756: Spell checking is not enabled" -msgstr "E756: ฅนฅฺฅ๋ฅมฅงฅรฅฏคฯฬตธ๚ฒฝคตค์คฦคคคคน" - -#: ../spell.c:2249 -#, c-format -msgid "Warning: Cannot find word list \"%s.%s.spl\" or \"%s.ascii.spl\"" -msgstr "" -"ทูน๐: รฑธ์ฅ๊ฅนฅศ \"%s.%s.spl\" คชค่คำ \"%s.ascii.spl\" คฯธซคฤคซค๊คคปค๓" - -#: ../spell.c:2473 #, c-format msgid "Reading spell file \"%s\"" msgstr "ฅนฅฺฅ๋ฅีฅกฅคฅ๋ \"%s\" ค๒ฦษนรๆ" -#: ../spell.c:2496 msgid "E757: This does not look like a spell file" msgstr "E757: ฅนฅฺฅ๋ฅีฅกฅคฅ๋ควคฯคสคคค่คฆควคน" -#: ../spell.c:2501 msgid "E771: Old spell file, needs to be updated" msgstr "E771: ธลคคฅนฅฺฅ๋ฅีฅกฅคฅ๋คสคฮคว, ฅขฅรฅืฅวกผฅศคทคฦคฏคภคตคค" -#: ../spell.c:2504 msgid "E772: Spell file is for newer version of Vim" msgstr "E772: ค่ค๊ฟทคทคคฅะกผฅธฅ็ฅ๓คฮ Vim อัคฮฅนฅฺฅ๋ฅีฅกฅคฅ๋ควคน" -#: ../spell.c:2602 msgid "E770: Unsupported section in spell file" msgstr "E770: ฅนฅฺฅ๋ฅีฅกฅคฅ๋คหฅตฅกผฅศคทคฦคคคสคคฅปฅฏฅทฅ็ฅ๓คฌคขค๊คคน" -#: ../spell.c:3762 #, c-format -msgid "Warning: region %s not supported" -msgstr "ทูน๐9: %s คศคคคฆศฯฐฯคฯฅตฅกผฅศคตค์คฦคคคคปค๓" +msgid "E778: This does not look like a .sug file: %s" +msgstr "E778: .sug ฅีฅกฅคฅ๋ควคฯคสคคค่คฆควคน: %s" + +#, c-format +msgid "E779: Old .sug file, needs to be updated: %s" +msgstr "E779: ธลคค .sug ฅีฅกฅคฅ๋คสคฮคว, ฅขฅรฅืฅวกผฅศคทคฦคฏคภคตคค: %s" + +#, c-format +msgid "E780: .sug file is for newer version of Vim: %s" +msgstr "E780: ค่ค๊ฟทคทคคฅะกผฅธฅ็ฅ๓คฮ Vim อัคฮ .sug ฅีฅกฅคฅ๋ควคน: %s" + +#, c-format +msgid "E781: .sug file doesn't match .spl file: %s" +msgstr "E781: .sug ฅีฅกฅคฅ๋คฌ .spl ฅีฅกฅคฅ๋คศฐ์รืคทคคปค๓: %s" + +#, c-format +msgid "E782: error while reading .sug file: %s" +msgstr "E782: .sug ฅีฅกฅคฅ๋คฮฦษนรๆคหฅจฅ้กผคฌศฏภธคทคคทคฟ: %s" -#: ../spell.c:4550 #, c-format msgid "Reading affix file %s ..." msgstr "affix ฅีฅกฅคฅ๋ %s ค๒ฦษนรๆ..." -#: ../spell.c:4589 ../spell.c:5635 ../spell.c:6140 #, c-format msgid "Conversion failure for word in %s line %d: %s" msgstr "%s (%d นิฬ) คฮรฑธ์ค๒สัดนควคญคคปค๓ควคทคฟ: %s" -#: ../spell.c:4630 ../spell.c:6170 #, c-format msgid "Conversion in %s not supported: from %s to %s" msgstr "%s ฦโคฮผกคฮสัดนคฯฅตฅกผฅศคตค์คฦคคคคปค๓: %s คซค้ %s คุ" -#: ../spell.c:4642 +#, c-format +msgid "Conversion in %s not supported" +msgstr "%s ฦโคฮสัดนคฯฅตฅกผฅศคตค์คฦคคคคปค๓" + #, c-format msgid "Invalid value for FLAG in %s line %d: %s" msgstr "%s ฦโคฮ %d นิฬคฮ FLAG คหฬตธ๚คสรอคฌคขค๊คคน: %s" -#: ../spell.c:4655 #, c-format msgid "FLAG after using flags in %s line %d: %s" msgstr "%s ฦโคฮ %d นิฬคหฅีฅ้ฅฐคฮฦ๓ฝลปศอัคฌคขค๊คคน: %s" -#: ../spell.c:4723 #, c-format msgid "" "Defining COMPOUNDFORBIDFLAG after PFX item may give wrong results in %s line " @@ -5361,7 +5118,6 @@ msgstr "" "%s คฮ %d นิฬคฮ PFX นเฬคฮธๅคฮ COMPOUNDFORBIDFLAG คฮฤ๊ตมคฯธํครคฟท๋ฒฬค๒ภธคธค๋" "คณคศคฌคขค๊คคน" -#: ../spell.c:4731 #, c-format msgid "" "Defining COMPOUNDPERMITFLAG after PFX item may give wrong results in %s line " @@ -5370,43 +5126,35 @@ msgstr "" "%s คฮ %d นิฬคฮ PFX นเฬคฮธๅคฮ COMPOUNDPERMITFLAG คฮฤ๊ตมคฯธํครคฟท๋ฒฬค๒ภธคธค๋" "คณคศคฌคขค๊คคน" -#: ../spell.c:4747 #, c-format msgid "Wrong COMPOUNDRULES value in %s line %d: %s" msgstr "COMPOUNDRULES คฮรอคหธํค๊คฌคขค๊คคน. ฅีฅกฅคฅ๋ %s คฮ %d นิฬ: %s" -#: ../spell.c:4771 #, c-format msgid "Wrong COMPOUNDWORDMAX value in %s line %d: %s" msgstr "%s คฮ %d นิฬคฮ COMPOUNDWORDMAX คฮรอคหธํค๊คฌคขค๊คคน: %s" -#: ../spell.c:4777 #, c-format msgid "Wrong COMPOUNDMIN value in %s line %d: %s" msgstr "%s คฮ %d นิฬคฮ COMPOUNDMIN คฮรอคหธํค๊คฌคขค๊คคน: %s" -#: ../spell.c:4783 #, c-format msgid "Wrong COMPOUNDSYLMAX value in %s line %d: %s" msgstr "%s คฮ %d นิฬคฮ COMPOUNDSYLMAX คฮรอคหธํค๊คฌคขค๊คคน: %s" -#: ../spell.c:4795 #, c-format msgid "Wrong CHECKCOMPOUNDPATTERN value in %s line %d: %s" msgstr "%s คฮ %d นิฬคฮ CHECKCOMPOUNDPATTERN คฮรอคหธํค๊คฌคขค๊คคน: %s" -#: ../spell.c:4847 #, c-format msgid "Different combining flag in continued affix block in %s line %d: %s" msgstr "" "%s คฮ %d นิฬคฮ ฯขยณ affix ฅึฅํฅรฅฏคฮฅีฅ้ฅฐคฮมศน็คปคหฐใคคคฌคขค๊คคน: %s" -#: ../spell.c:4850 #, c-format msgid "Duplicate affix in %s line %d: %s" msgstr "%s คฮ %d นิฬคห ฝลสฃคทคฟ affix ค๒ธกฝะคทคคทคฟ: %s" -#: ../spell.c:4871 #, c-format msgid "" "Affix also used for BAD/RARE/KEEPCASE/NEEDAFFIX/NEEDCOMPOUND/NOSUGGEST in %s " @@ -5415,308 +5163,206 @@ msgstr "" "%s คฮ %d นิฬคฮ affix คฯ BAD/RARE/KEEPCASE/NEEDAFFIX/NEEDCOMPOUND/NOSUGGEST " "คหปศอัคทคฦคฏคภคตคค: %s" -#: ../spell.c:4893 #, c-format msgid "Expected Y or N in %s line %d: %s" msgstr "%s คฮ %d นิฬควคฯ Y คซ N คฌษฌอืควคน: %s" -#: ../spell.c:4968 #, c-format msgid "Broken condition in %s line %d: %s" msgstr "%s คฮ %d นิฬคฮ พ๒ท๏คฯฒ๕ค์คฦคคคคน: %s" -#: ../spell.c:5091 #, c-format msgid "Expected REP(SAL) count in %s line %d" msgstr "%s คฮ %d นิฬคหคฯ REP(SAL) คฮฒ๓ฟ๔คฌษฌอืควคน" -#: ../spell.c:5120 #, c-format msgid "Expected MAP count in %s line %d" msgstr "%s คฮ %d นิฬคหคฯ MAP คฮฒ๓ฟ๔คฌษฌอืควคน" -#: ../spell.c:5132 #, c-format msgid "Duplicate character in MAP in %s line %d" msgstr "%s คฮ %d นิฬคฮ MAP คหฝลสฃคทคฟสธป๚คฌคขค๊คคน" -#: ../spell.c:5176 #, c-format msgid "Unrecognized or duplicate item in %s line %d: %s" msgstr "%s คฮ %d นิฬคห วงผฑควคญคสคคคซฝลสฃคทคฟนเฬคฌคขค๊คคน: %s" -#: ../spell.c:5197 #, c-format msgid "Missing FOL/LOW/UPP line in %s" msgstr "%s นิฬคห FOL/LOW/UPP คฌคขค๊คคปค๓" -#: ../spell.c:5220 msgid "COMPOUNDSYLMAX used without SYLLABLE" msgstr "SYLLABLE คฌปุฤ๊คตค์คสคค COMPOUNDSYLMAX" -#: ../spell.c:5236 msgid "Too many postponed prefixes" msgstr "รูฑไธๅรึปาคฌยฟฒแคฎคคน" -#: ../spell.c:5238 msgid "Too many compound flags" msgstr "สฃน็ฅีฅ้ฅฐคฌยฟฒแคฎคคน" -#: ../spell.c:5240 msgid "Too many postponed prefixes and/or compound flags" msgstr "รูฑไธๅรึปา คศ/คโคทคฏคฯ สฃน็ฅีฅ้ฅฐคฌยฟฒแคฎคคน" -#: ../spell.c:5250 #, c-format msgid "Missing SOFO%s line in %s" msgstr "SOFO%s นิคฌ %s คหคขค๊คคปค๓" -#: ../spell.c:5253 #, c-format msgid "Both SAL and SOFO lines in %s" msgstr "SALนิ คศ SOFOนิ คฌ %s ควฮพสปุฤ๊คตค์คฦคคคคน" -#: ../spell.c:5331 #, c-format msgid "Flag is not a number in %s line %d: %s" msgstr "%s คฮ %d นิคฮ ฅีฅ้ฅฐคฌฟ๔รอควคฯคขค๊คคปค๓: %s" -#: ../spell.c:5334 #, c-format msgid "Illegal flag in %s line %d: %s" msgstr "%s คฮ %d นิฬคฮ ฅีฅ้ฅฐคฌษิภตควคน: %s" -#: ../spell.c:5493 ../spell.c:5501 #, c-format msgid "%s value differs from what is used in another .aff file" msgstr "รอ %s คฯยพคฮ .aff ฅีฅกฅคฅ๋ควปศอัคตค์คฟคฮคศฐคสค๊คคน" -#: ../spell.c:5602 #, c-format msgid "Reading dictionary file %s ..." msgstr "ผญฝ๑ฅีฅกฅคฅ๋ %s ค๒ฅนฅญฅใฅ๓รๆ..." -#: ../spell.c:5611 #, c-format msgid "E760: No word count in %s" msgstr "E760: %s คหคฯรฑธ์ฟ๔คฌคขค๊คคปค๓" -#: ../spell.c:5669 #, c-format msgid "line %6d, word %6d - %s" msgstr "นิ %6d, รฑธ์ %6d - %s" -#: ../spell.c:5691 #, c-format msgid "Duplicate word in %s line %d: %s" msgstr "%s คฮ %d นิฬคว ฝลสฃรฑธ์คฌธซคฤคซค๊คคทคฟ: %s" -#: ../spell.c:5694 #, c-format msgid "First duplicate word in %s line %d: %s" msgstr "ฝลสฃคฮคฆคมบวฝ้คฮรฑธ์คฯ %s คฮ %d นิฬควคน: %s" -#: ../spell.c:5746 #, c-format msgid "%d duplicate word(s) in %s" msgstr "%d ธฤคฮรฑธ์คฌธซคฤคซค๊คคทคฟ (%s ฦโ)" -#: ../spell.c:5748 #, c-format msgid "Ignored %d word(s) with non-ASCII characters in %s" msgstr "ศ๓ASCIIสธป๚ค๒ดคเ %d ธฤคฮรฑธ์ค๒ฬตป๋คทคคทคฟ (%s ฦโ)" -#: ../spell.c:6115 #, c-format msgid "Reading word file %s ..." msgstr "ษธฝเฦฮฯคซค้ฦษนค฿รๆ %s ..." -#: ../spell.c:6155 #, c-format msgid "Duplicate /encoding= line ignored in %s line %d: %s" msgstr "%s คฮ %d นิฬคฮ ฝลสฃคทคฟ /encoding= นิค๒ฬตป๋คทคคทคฟ: %s" -#: ../spell.c:6159 #, c-format msgid "/encoding= line after word ignored in %s line %d: %s" msgstr "%s คฮ %d นิฬคฮ รฑธ์คฮธๅคฮ /encoding= นิค๒ฬตป๋คทคคทคฟ: %s" -#: ../spell.c:6180 #, c-format msgid "Duplicate /regions= line ignored in %s line %d: %s" msgstr "%s คฮ %d นิฬคฮ ฝลสฃคทคฟ /regions= นิค๒ฬตป๋คทคคทคฟ: %s" -#: ../spell.c:6185 #, c-format msgid "Too many regions in %s line %d: %s" msgstr "%s คฮ %d นิฬ, ศฯฐฯปุฤ๊คฌยฟฒแคฎคคน: %s" -#: ../spell.c:6198 #, c-format msgid "/ line ignored in %s line %d: %s" msgstr "%s คฮ %d นิฬคฮ ฝลสฃคทคฟ / นิค๒ฬตป๋คทคคทคฟ: %s" -#: ../spell.c:6224 #, c-format msgid "Invalid region nr in %s line %d: %s" msgstr "%s คฮ %d นิฬ ฬตธ๚คส nr ฮฮฐ่ควคน: %s" -#: ../spell.c:6230 #, c-format msgid "Unrecognized flags in %s line %d: %s" msgstr "%s คฮ %d นิฬ วงผฑษิวฝคสฅีฅ้ฅฐควคน: %s" -#: ../spell.c:6257 #, c-format msgid "Ignored %d words with non-ASCII characters" msgstr "ศ๓ASCIIสธป๚ค๒ดคเ %d ธฤคฮรฑธ์ค๒ฬตป๋คทคคทคฟ" -#: ../spell.c:6656 +msgid "E845: Insufficient memory, word list will be incomplete" +msgstr "E845: ฅแฅโฅ๊คฌยญค๊คสคคคฮควกขรฑธ์ฅ๊ฅนฅศคฯษิดฐมดควคน" + #, c-format msgid "Compressed %d of %d nodes; %d (%d%%) remaining" msgstr "ฅฮกผฅษ %d ธฤ(มด %d ธฤรๆ) ค๒ฐตฝฬคทคคทคฟ; ปฤค๊ %d (%d%%)" -#: ../spell.c:7340 msgid "Reading back spell file..." msgstr "ฅนฅฺฅ๋ฅีฅกฅคฅ๋ค๒ตีฦษนรๆ" -#. Go through the trie of good words, soundfold each word and add it to -#. the soundfold trie. -#: ../spell.c:7357 +#. +#. * Go through the trie of good words, soundfold each word and add it to +#. * the soundfold trie. +#. msgid "Performing soundfolding..." msgstr "ฒปภผพ๖นค฿ค๒ผยนิรๆ..." -#: ../spell.c:7368 #, c-format -msgid "Number of words after soundfolding: %<PRId64>" -msgstr "ฒปภผพ๖นค฿ธๅคฮมํรฑธ์ฟ๔: %<PRId64>" +msgid "Number of words after soundfolding: %ld" +msgstr "ฒปภผพ๖นค฿ธๅคฮมํรฑธ์ฟ๔: %ld" -#: ../spell.c:7476 #, c-format msgid "Total number of words: %d" msgstr "มํรฑธ์ฟ๔: %d" -#: ../spell.c:7655 #, c-format msgid "Writing suggestion file %s ..." msgstr "ฝคภตธ๕สไฅีฅกฅคฅ๋ \"%s\" ค๒ฝ๑นค฿รๆ..." -#: ../spell.c:7707 ../spell.c:7927 #, c-format msgid "Estimated runtime memory use: %d bytes" msgstr "ฟไฤ๊ฅแฅโฅ๊ปศอัฮฬ: %d ฅะฅคฅศ" -#: ../spell.c:7820 msgid "E751: Output file name must not have region name" msgstr "E751: ฝะฮฯฅีฅกฅคฅ๋ฬพคหคฯศฯฐฯฬพค๒ดคแค้ค์คคปค๓" -#: ../spell.c:7822 msgid "E754: Only up to 8 regions supported" msgstr "E754: ศฯฐฯคฯ 8 ธฤคควคทคซฅตฅกผฅศคตค์คฦคคคคปค๓" -#: ../spell.c:7846 #, c-format msgid "E755: Invalid region in %s" msgstr "E755: ฬตธ๚คสศฯฐฯควคน: %s" -#: ../spell.c:7907 msgid "Warning: both compounding and NOBREAK specified" msgstr "ทูน๐: สฃน็ฅีฅ้ฅฐคศ NOBREAK คฌฮพสคศคโปุฤ๊คตค์คคทคฟ" -#: ../spell.c:7920 #, c-format msgid "Writing spell file %s ..." msgstr "ฅนฅฺฅ๋ฅีฅกฅคฅ๋ %s ค๒ฝ๑นค฿รๆ..." -#: ../spell.c:7925 msgid "Done!" msgstr "ผยนิคทคคทคฟ!" -#: ../spell.c:8034 #, c-format -msgid "E765: 'spellfile' does not have %<PRId64> entries" -msgstr "E765: 'spellfile' คหคฯ %<PRId64> ธฤคฮฅจฅ๓ฅศฅ๊คฯคขค๊คคปค๓" +msgid "E765: 'spellfile' does not have %ld entries" +msgstr "E765: 'spellfile' คหคฯ %ld ธฤคฮฅจฅ๓ฅศฅ๊คฯคขค๊คคปค๓" -#: ../spell.c:8074 #, c-format msgid "Word '%.*s' removed from %s" msgstr "รฑธ์ '%.*s' คฌ %s คซค้บ๏ฝคตค์คคทคฟ" -#: ../spell.c:8117 #, c-format msgid "Word '%.*s' added to %s" msgstr "รฑธ์ '%.*s' คฌ %s คุฤษฒรคตค์คคทคฟ" -#: ../spell.c:8381 msgid "E763: Word characters differ between spell files" msgstr "E763: รฑธ์คฮสธป๚คฌฅนฅฺฅ๋ฅีฅกฅคฅ๋คศฐคสค๊คคน" -#: ../spell.c:8684 -msgid "Sorry, no suggestions" -msgstr "ปฤวฐควคนคฌ, ฝคภตธ๕สไคฯคขค๊คคปค๓" - -#: ../spell.c:8687 -#, c-format -msgid "Sorry, only %<PRId64> suggestions" -msgstr "ปฤวฐควคนคฌ, ฝคภตธ๕สไคฯ %<PRId64> ธฤคทคซคขค๊คคปค๓" - -#. for when 'cmdheight' > 1 -#. avoid more prompt -#: ../spell.c:8704 -#, c-format -msgid "Change \"%.*s\" to:" -msgstr "\"%.*s\" ค๒ผกคุสัดน:" - -#: ../spell.c:8737 -#, c-format -msgid " < \"%.*s\"" -msgstr " < \"%.*s\"" - -#: ../spell.c:8882 -msgid "E752: No previous spell replacement" -msgstr "E752: ฅนฅฺฅ๋รึดนคฌคคภผยนิคตค์คฦคคคคปค๓" - -#: ../spell.c:8925 -#, c-format -msgid "E753: Not found: %s" -msgstr "E753: ธซคฤคซค๊คคปค๓: %s" - -#: ../spell.c:9276 -#, c-format -msgid "E778: This does not look like a .sug file: %s" -msgstr "E778: .sug ฅีฅกฅคฅ๋ควคฯคสคคค่คฆควคน: %s" - -#: ../spell.c:9282 -#, c-format -msgid "E779: Old .sug file, needs to be updated: %s" -msgstr "E779: ธลคค .sug ฅีฅกฅคฅ๋คสคฮคว, ฅขฅรฅืฅวกผฅศคทคฦคฏคภคตคค: %s" - -#: ../spell.c:9286 -#, c-format -msgid "E780: .sug file is for newer version of Vim: %s" -msgstr "E780: ค่ค๊ฟทคทคคฅะกผฅธฅ็ฅ๓คฮ Vim อัคฮ .sug ฅีฅกฅคฅ๋ควคน: %s" - -#: ../spell.c:9295 -#, c-format -msgid "E781: .sug file doesn't match .spl file: %s" -msgstr "E781: .sug ฅีฅกฅคฅ๋คฌ .spl ฅีฅกฅคฅ๋คศฐ์รืคทคคปค๓: %s" - -#: ../spell.c:9305 -#, c-format -msgid "E782: error while reading .sug file: %s" -msgstr "E782: .sug ฅีฅกฅคฅ๋คฮฦษนรๆคหฅจฅ้กผคฌศฏภธคทคคทคฟ: %s" - #. This should have been checked when generating the .spl -#. file. -#: ../spell.c:11575 +#. * file. msgid "E783: duplicate char in MAP entry" msgstr "E783: MAP ฅจฅ๓ฅศฅ๊คหฝลสฃสธป๚คฌยธบ฿คทคคน" -#: ../syntax.c:266 msgid "No Syntax items defined for this buffer" msgstr "คณคฮฅะฅรฅีฅกคหฤ๊ตมคตค์คฟนฝสธอืมวคฯคขค๊คคปค๓" -#: ../syntax.c:3083 ../syntax.c:3104 ../syntax.c:3127 #, c-format msgid "E390: Illegal argument: %s" msgstr "E390: ษิภตคสฐ๚ฟ๔ควคน: %s" @@ -5724,28 +5370,22 @@ msgstr "E390: ษิภตคสฐ๚ฟ๔ควคน: %s" msgid "syntax iskeyword " msgstr "ฅทฅ๓ฅฟฅรฅฏฅนอั iskeyword " -#: ../syntax.c:3299 #, c-format msgid "E391: No such syntax cluster: %s" msgstr "E391: คฝคฮค่คฆคสนฝสธฅฏฅ้ฅนฅฟคฯคขค๊คคปค๓: %s" -#: ../syntax.c:3433 msgid "syncing on C-style comments" msgstr "Cธภธ์ษ๗ฅณฅแฅ๓ฅศคซค้ฦฑดรๆ" -#: ../syntax.c:3439 msgid "no syncing" msgstr "ศ๓ฦฑด" -#: ../syntax.c:3441 msgid "syncing starts " msgstr "ฦฑดณซปฯ " -#: ../syntax.c:3443 ../syntax.c:3506 msgid " lines before top line" msgstr " นิมฐ(ฅศฅรฅืนิค่ค๊คโ)" -#: ../syntax.c:3448 msgid "" "\n" "--- Syntax sync items ---" @@ -5753,7 +5393,6 @@ msgstr "" "\n" "--- นฝสธฦฑดอืมว ---" -#: ../syntax.c:3452 msgid "" "\n" "syncing on items" @@ -5761,7 +5400,6 @@ msgstr "" "\n" "อืมวพๅควฦฑดรๆ" -#: ../syntax.c:3457 msgid "" "\n" "--- Syntax items ---" @@ -5769,53 +5407,41 @@ msgstr "" "\n" "--- นฝสธอืมว ---" -#: ../syntax.c:3475 #, c-format msgid "E392: No such syntax cluster: %s" msgstr "E392: คฝคฮค่คฆคสนฝสธฅฏฅ้ฅนฅฟคฯคขค๊คคปค๓: %s" -#: ../syntax.c:3497 msgid "minimal " msgstr "minimal " -#: ../syntax.c:3503 msgid "maximal " msgstr "maximal " -#: ../syntax.c:3513 msgid "; match " msgstr "; ณบล๖ " -#: ../syntax.c:3515 msgid " line breaks" msgstr " ธฤคฮฒนิ" -#: ../syntax.c:4076 msgid "E395: contains argument not accepted here" msgstr "E395: คณคฮพ์ฝ๊ควคฯฐ๚ฟ๔containsคฯต๖ฒฤคตค์คฦคคคคปค๓" -#: ../syntax.c:4096 msgid "E844: invalid cchar value" msgstr "E844: ฬตธ๚คสccharคฮรอควคน" -#: ../syntax.c:4107 msgid "E393: group[t]here not accepted here" msgstr "E393: คณคณควคฯฅฐฅ๋กผฅืคฯต๖ฒฤคตค์คคปค๓" -#: ../syntax.c:4126 #, c-format msgid "E394: Didn't find region item for %s" msgstr "E394: %s คฮศฯฐฯอืมวคฌธซคฤคซค๊คคปค๓" -#: ../syntax.c:4188 msgid "E397: Filename required" msgstr "E397: ฅีฅกฅคฅ๋ฬพคฌษฌอืควคน" -#: ../syntax.c:4221 msgid "E847: Too many syntax includes" msgstr "E847: นฝสธคฮผ่ค๊นค฿(include)คฌยฟฒแคฎคคน" -#: ../syntax.c:4303 #, c-format msgid "E789: Missing ']': %s" msgstr "E789: ']' คฌคขค๊คคปค๓: %s" @@ -5824,221 +5450,173 @@ msgstr "E789: ']' คฌคขค๊คคปค๓: %s" msgid "E890: trailing char after ']': %s]%s" msgstr "E890: ']' คฮธๅคํคหอพสฌคสสธป๚คฌคขค๊คคน: %s]%s" -#: ../syntax.c:4531 #, c-format msgid "E398: Missing '=': %s" msgstr "E398: '=' คฌคขค๊คคปค๓: %s" -#: ../syntax.c:4666 #, c-format msgid "E399: Not enough arguments: syntax region %s" msgstr "E399: ฐ๚ฟ๔คฌยญค๊คคปค๓: นฝสธศฯฐฯ %s" -#: ../syntax.c:4870 msgid "E848: Too many syntax clusters" msgstr "E848: นฝสธฅฏฅ้ฅนฅฟคฌยฟฒแคฎคคน" -#: ../syntax.c:4954 msgid "E400: No cluster specified" msgstr "E400: ฅฏฅ้ฅนฅฟคฌปุฤ๊คตค์คฦคคคคปค๓" -#. end delimiter not found -#: ../syntax.c:4986 #, c-format msgid "E401: Pattern delimiter not found: %s" msgstr "E401: ฅัฅฟกผฅ๓ถ่ภฺค๊คฌธซคฤคซค๊คคปค๓: %s" -#: ../syntax.c:5049 #, c-format msgid "E402: Garbage after pattern: %s" msgstr "E402: ฅัฅฟกผฅ๓คฮคขคศคหฅดฅ฿คฌคขค๊คคน: %s" -#: ../syntax.c:5120 msgid "E403: syntax sync: line continuations pattern specified twice" msgstr "E403: นฝสธฦฑด: ฯขยณนิฅัฅฟกผฅ๓คฌ2ลูปุฤ๊คตค์คคทคฟ" -#: ../syntax.c:5169 #, c-format msgid "E404: Illegal arguments: %s" msgstr "E404: ษิภตคสฐ๚ฟ๔ควคน: %s" -#: ../syntax.c:5217 #, c-format msgid "E405: Missing equal sign: %s" msgstr "E405: ล๙นๆคฌคขค๊คคปค๓: %s" -#: ../syntax.c:5222 #, c-format msgid "E406: Empty argument: %s" msgstr "E406: ถ๕คฮฐ๚ฟ๔: %s" -#: ../syntax.c:5240 #, c-format msgid "E407: %s not allowed here" msgstr "E407: %s คฯฅณฅณควคฯต๖ฒฤคตค์คฦคคคคปค๓" -#: ../syntax.c:5246 #, c-format msgid "E408: %s must be first in contains list" msgstr "E408: %s คฯฦโอฦฅ๊ฅนฅศคฮภ่ฦฌควคสคฑค์คะคสค้คสคค" -#: ../syntax.c:5304 #, c-format msgid "E409: Unknown group name: %s" msgstr "E409: ฬครฮคฮฅฐฅ๋กผฅืฬพ: %s" -#: ../syntax.c:5512 #, c-format msgid "E410: Invalid :syntax subcommand: %s" msgstr "E410: ฬตธ๚คส :syntax คฮฅตฅึฅณฅฅ๓ฅษ: %s" -#: ../syntax.c:5854 msgid "" " TOTAL COUNT MATCH SLOWEST AVERAGE NAME PATTERN" msgstr "" " TOTAL COUNT MATCH SLOWEST AVERAGE NAME PATTERN" -#: ../syntax.c:6146 msgid "E679: recursive loop loading syncolor.vim" msgstr "E679: syncolor.vim คฮบฦตขธฦคำฝะคทค๒ธกฝะคทคคทคฟ" -#: ../syntax.c:6256 #, c-format msgid "E411: highlight group not found: %s" msgstr "E411: ฅฯฅคฅ้ฅคฅศฅฐฅ๋กผฅืคฌธซคฤคซค๊คคปค๓: %s" -#: ../syntax.c:6278 #, c-format msgid "E412: Not enough arguments: \":highlight link %s\"" msgstr "E412: ฐ๚ฟ๔คฌฝผสฌควคฯคสคค: \":highlight link %s\"" -#: ../syntax.c:6284 #, c-format msgid "E413: Too many arguments: \":highlight link %s\"" msgstr "E413: ฐ๚ฟ๔คฌยฟฒแคฎคคน: \":highlight link %s\"" -#: ../syntax.c:6302 msgid "E414: group has settings, highlight link ignored" msgstr "E414: ฅฐฅ๋กผฅืคฌภ฿ฤ๊คตค์คฦคคค๋คฮควฅฯฅคฅ้ฅคฅศฅ๊ฅ๓ฅฏคฯฬตป๋คตค์คคน" -#: ../syntax.c:6367 #, c-format msgid "E415: unexpected equal sign: %s" msgstr "E415: อฝดคปคฬล๙นๆควคน: %s" -#: ../syntax.c:6395 #, c-format msgid "E416: missing equal sign: %s" msgstr "E416: ล๙นๆคฌคขค๊คคปค๓: %s" -#: ../syntax.c:6418 #, c-format msgid "E417: missing argument: %s" msgstr "E417: ฐ๚ฟ๔คฌคขค๊คคปค๓: %s" -#: ../syntax.c:6446 #, c-format msgid "E418: Illegal value: %s" msgstr "E418: ษิภตคสรอควคน: %s" -#: ../syntax.c:6496 msgid "E419: FG color unknown" msgstr "E419: ฬครฮคฮมฐทสฟงควคน" -#: ../syntax.c:6504 msgid "E420: BG color unknown" msgstr "E420: ฬครฮคฮวุทสฟงควคน" -#: ../syntax.c:6564 #, c-format msgid "E421: Color name or number not recognized: %s" msgstr "E421: ฅซฅ้กผฬพคไศึนๆค๒วงผฑควคญคคปค๓: %s" -#: ../syntax.c:6714 #, c-format msgid "E422: terminal code too long: %s" msgstr "E422: ฝชรผฅณกผฅษคฌฤนฒแคฎคคน: %s" -#: ../syntax.c:6753 #, c-format msgid "E423: Illegal argument: %s" msgstr "E423: ษิภตคสฐ๚ฟ๔ควคน: %s" -#: ../syntax.c:6925 msgid "E424: Too many different highlighting attributes in use" msgstr "E424: ยฟคฏคฮฐคสค๋ฅฯฅคฅ้ฅคฅศยฐภญคฌปศค๏ค์ฒแคฎคฦคคคคน" -#: ../syntax.c:7427 msgid "E669: Unprintable character in group name" msgstr "E669: ฅฐฅ๋กผฅืฬพคหฐ๕บษิฒฤวฝคสสธป๚คฌคขค๊คคน" -#: ../syntax.c:7434 msgid "W18: Invalid character in group name" msgstr "W18: ฅฐฅ๋กผฅืฬพคหษิภตคสสธป๚คฌคขค๊คคน" -#: ../syntax.c:7448 msgid "E849: Too many highlight and syntax groups" msgstr "E849: ฅฯฅคฅ้ฅคฅศคศนฝสธฅฐฅ๋กผฅืคฌยฟฒแคฎคคน" -#: ../tag.c:104 msgid "E555: at bottom of tag stack" msgstr "E555: ฅฟฅฐฅนฅฟฅรฅฏคฮห๖ศ๘ควคน" -#: ../tag.c:105 msgid "E556: at top of tag stack" msgstr "E556: ฅฟฅฐฅนฅฟฅรฅฏคฮภ่ฦฌควคน" -#: ../tag.c:380 msgid "E425: Cannot go before first matching tag" msgstr "E425: บวฝ้คฮณบล๖ฅฟฅฐค๒ฤถคจคฦฬแค๋คณคศคฯควคญคคปค๓" -#: ../tag.c:504 #, c-format msgid "E426: tag not found: %s" msgstr "E426: ฅฟฅฐคฌธซคฤคซค๊คคปค๓: %s" -#: ../tag.c:528 msgid " # pri kind tag" msgstr " # pri kind tag" -#: ../tag.c:531 msgid "file\n" msgstr "ฅีฅกฅคฅ๋\n" -#: ../tag.c:829 msgid "E427: There is only one matching tag" msgstr "E427: ณบล๖ฅฟฅฐคฌ1คฤคภคฑคทคซคขค๊คคปค๓" -#: ../tag.c:831 msgid "E428: Cannot go beyond last matching tag" msgstr "E428: บวธๅคหณบล๖คนค๋ฅฟฅฐค๒ฤถคจคฦฟสคเคณคศคฯควคญคคปค๓" -#: ../tag.c:850 #, c-format msgid "File \"%s\" does not exist" msgstr "ฅีฅกฅคฅ๋ \"%s\" คฌคขค๊คคปค๓" #. Give an indication of the number of matching tags -#: ../tag.c:859 #, c-format msgid "tag %d of %d%s" msgstr "ฅฟฅฐ %d (มด%d%s)" -#: ../tag.c:862 msgid " or more" msgstr " คซคฝค์ฐสพๅ" -#: ../tag.c:864 msgid " Using tag with different case!" msgstr " ฅฟฅฐค๒ฐคสค๋caseควปศอัคทคคน!" -#: ../tag.c:909 #, c-format msgid "E429: File \"%s\" does not exist" msgstr "E429: ฅีฅกฅคฅ๋ \"%s\" คฌคขค๊คคปค๓" #. Highlight title -#: ../tag.c:960 msgid "" "\n" " # TO tag FROM line in file/text" @@ -6046,79 +5624,66 @@ msgstr "" "\n" " # TO ฅฟฅฐ FROM นิ in file/text" -#: ../tag.c:1303 #, c-format msgid "Searching tags file %s" msgstr "ฅฟฅฐฅีฅกฅคฅ๋ %s ค๒ธกบ๗รๆ" -#: ../tag.c:1545 +#, c-format +msgid "E430: Tag file path truncated for %s\n" +msgstr "E430: ฅฟฅฐฅีฅกฅคฅ๋คฮฅัฅนคฌ %s คหภฺค๊ผฮคฦค้ค์คคทคฟ\n" + msgid "Ignoring long line in tags file" msgstr "ฅฟฅฐฅีฅกฅคฅ๋ฦโคฮฤนคคนิค๒ฬตป๋คทคคน" -#: ../tag.c:1915 #, c-format msgid "E431: Format error in tags file \"%s\"" msgstr "E431: ฅฟฅฐฅีฅกฅคฅ๋ \"%s\" คฮฅีฅฉกผฅฅรฅศคหฅจฅ้กผคฌคขค๊คคน" -#: ../tag.c:1917 #, c-format -msgid "Before byte %<PRId64>" -msgstr "ฤพมฐคฮ %<PRId64> ฅะฅคฅศ" +msgid "Before byte %ld" +msgstr "ฤพมฐคฮ %ld ฅะฅคฅศ" -#: ../tag.c:1929 #, c-format msgid "E432: Tags file not sorted: %s" msgstr "E432: ฅฟฅฐฅีฅกฅคฅ๋คฌฅฝกผฅศคตค์คฦคคคคปค๓: %s" #. never opened any tags file -#: ../tag.c:1960 msgid "E433: No tags file" msgstr "E433: ฅฟฅฐฅีฅกฅคฅ๋คฌคขค๊คคปค๓" -#: ../tag.c:2536 msgid "E434: Can't find tag pattern" msgstr "E434: ฅฟฅฐฅัฅฟกผฅ๓ค๒ธซคฤคฑค้ค์คคปค๓" -#: ../tag.c:2544 msgid "E435: Couldn't find tag, just guessing!" msgstr "E435: ฅฟฅฐค๒ธซคฤคฑค้ค์คสคคคฮควรฑคหฟไยฌคทคคน!" -#: ../tag.c:2797 #, c-format msgid "Duplicate field name: %s" msgstr "ฝลสฃคทคฟฅีฅฃกผฅ๋ฅษฬพ: %s" -#: ../term.c:1442 msgid "' not known. Available builtin terminals are:" msgstr "' คฯฬครฮควคน. ธฝนิคฮมศค฿นค฿รผห๖คฯผกคฮคศคชค๊ควคน:" -#: ../term.c:1463 msgid "defaulting to '" msgstr "พสฮฌรอค๒ผกคฮค่คฆคหภ฿ฤ๊คทคคน '" -#: ../term.c:1731 msgid "E557: Cannot open termcap file" msgstr "E557: termcapฅีฅกฅคฅ๋ค๒ณซคฑคคปค๓" -#: ../term.c:1735 msgid "E558: Terminal entry not found in terminfo" msgstr "E558: terminfoคหรผห๖ฅจฅ๓ฅศฅ๊ค๒ธซคฤคฑค้ค์คคปค๓" -#: ../term.c:1737 msgid "E559: Terminal entry not found in termcap" msgstr "E559: termcapคหรผห๖ฅจฅ๓ฅศฅ๊ค๒ธซคฤคฑค้ค์คคปค๓" -#: ../term.c:1878 #, c-format msgid "E436: No \"%s\" entry in termcap" msgstr "E436: termcapคห \"%s\" คฮฅจฅ๓ฅศฅ๊คฌคขค๊คคปค๓" -#: ../term.c:2249 msgid "E437: terminal capability \"cm\" required" msgstr "E437: รผห๖คห \"cm\" ตกวฝคฌษฌอืควคน" #. Highlight title -#: ../term.c:4376 msgid "" "\n" "--- Terminal keys ---" @@ -6126,168 +5691,347 @@ msgstr "" "\n" "--- รผห๖ฅญกผ ---" -#: ../ui.c:481 +msgid "Cannot open $VIMRUNTIME/rgb.txt" +msgstr "$VIMRUNTIME/rgb.txtค๒ณซคฑคคปค๓" + +msgid "new shell started\n" +msgstr "ฟทคทคคฅทฅงฅ๋ค๒ตฏฦฐคทคคน\n" + msgid "Vim: Error reading input, exiting...\n" msgstr "Vim: ฦฮฯค๒ฦษนค฿รๆคฮฅจฅ้กผคหค่ค๊ฝชฮปคทคคน...\n" +msgid "Used CUT_BUFFER0 instead of empty selection" +msgstr "ถ๕คฮมชย๒ฮฮฐ่คฮคซค๏ค๊คหCUT_BUFFER0คฌปศอัคตค์คคทคฟ" + #. This happens when the FileChangedRO autocommand changes the #. * file in a way it becomes shorter. -#: ../undo.c:379 msgid "E881: Line count changed unexpectedly" msgstr "E881: อฝดคปคบนิฅซฅฆฅ๓ฅศคฌสัค๏ค๊คคทคฟ" -#: ../undo.c:627 +#. must display the prompt +msgid "No undo possible; continue anyway" +msgstr "ฒฤวฝคสฅขฅ๓ฅษฅฅคฯคขค๊คคปค๓: คศค๊คขคจคบยณคฑคคน" + #, c-format msgid "E828: Cannot open undo file for writing: %s" msgstr "E828: ฝ๑นค฿อัคหฅขฅ๓ฅษฅฅฅีฅกฅคฅ๋ค๒ณซคฑคคปค๓: %s" -#: ../undo.c:717 #, c-format msgid "E825: Corrupted undo file (%s): %s" msgstr "E825: ฅขฅ๓ฅษฅฅฅีฅกฅคฅ๋คฌฒ๕ค์คฦคคคคน (%s): %s" -#: ../undo.c:1039 msgid "Cannot write undo file in any directory in 'undodir'" msgstr "'undodir'คฮฅวฅฃฅ์ฅฏฅศฅ๊คหฅขฅ๓ฅษฅฅฅีฅกฅคฅ๋ค๒ฝ๑คญนคแคคปค๓" -#: ../undo.c:1074 #, c-format msgid "Will not overwrite with undo file, cannot read: %s" msgstr "ฅขฅ๓ฅษฅฅฅีฅกฅคฅ๋คศคทคฦฦษค฿นคแคสคคคฮควพๅฝ๑คญคทคคปค๓: %s" -#: ../undo.c:1092 #, c-format msgid "Will not overwrite, this is not an undo file: %s" msgstr "ฅขฅ๓ฅษฅฅฅีฅกฅคฅ๋ควคฯคสคคคฮควพๅฝ๑คญคทคคปค๓: %s" -#: ../undo.c:1108 msgid "Skipping undo file write, nothing to undo" msgstr "ยะพคฌคสคคคฮควฅขฅ๓ฅษฅฅฅีฅกฅคฅ๋คฮฝ๑คญนค฿ค๒ฅนฅญฅรฅืคทคคน" -#: ../undo.c:1121 #, c-format msgid "Writing undo file: %s" msgstr "ฅขฅ๓ฅษฅฅฅีฅกฅคฅ๋ฝ๑คญนค฿รๆ: %s" -#: ../undo.c:1213 #, c-format msgid "E829: write error in undo file: %s" msgstr "E829: ฅขฅ๓ฅษฅฅฅีฅกฅคฅ๋คฮฝ๑คญนค฿ฅจฅ้กผควคน: %s" -#: ../undo.c:1280 #, c-format msgid "Not reading undo file, owner differs: %s" msgstr "ฅชกผฅสกผคฌฐคสค๋คฮควฅขฅ๓ฅษฅฅฅีฅกฅคฅ๋ค๒ฦษค฿นค฿คคปค๓: %s" -#: ../undo.c:1292 #, c-format msgid "Reading undo file: %s" msgstr "ฅขฅ๓ฅษฅฅฅีฅกฅคฅ๋ฦษนรๆ: %s" -#: ../undo.c:1299 #, c-format msgid "E822: Cannot open undo file for reading: %s" msgstr "E822: ฅขฅ๓ฅษฅฅฅีฅกฅคฅ๋ค๒ฦษนอัคศคทคฦณซคฑคคปค๓: %s" -#: ../undo.c:1308 #, c-format msgid "E823: Not an undo file: %s" msgstr "E823: ฅขฅ๓ฅษฅฅฅีฅกฅคฅ๋ควคฯคขค๊คคปค๓: %s" -#: ../undo.c:1313 +#, c-format +msgid "E832: Non-encrypted file has encrypted undo file: %s" +msgstr "E832: ศ๓ฐลนๆฒฝฅีฅกฅคฅ๋คฌฐลนๆฒฝคตค์คฟฅขฅ๓ฅษฅฅฅีฅกฅคฅ๋ค๒ปศครคฦคคน: %s" + +#, c-format +msgid "E826: Undo file decryption failed: %s" +msgstr "E826: ฐลนๆฒฝคตค์คฟฅขฅ๓ฅษฅฅฅีฅกฅคฅ๋คฮฒ๒ฦษคหผบวิคทคคทคฟ: %s" + +#, c-format +msgid "E827: Undo file is encrypted: %s" +msgstr "E827: ฅขฅ๓ฅษฅฅฅีฅกฅคฅ๋คฌฐลนๆฒฝคตค์คฦคคคคน: %s" + #, c-format msgid "E824: Incompatible undo file: %s" msgstr "E824: ธ฿ดนภญคฮฬตคคฅขฅ๓ฅษฅฅฅีฅกฅคฅ๋ควคน: %s" -#: ../undo.c:1328 msgid "File contents changed, cannot use undo info" msgstr "ฅีฅกฅคฅ๋คฮฦโอฦคฌสัค๏ครคฦคคค๋คฟคแกขฅขฅ๓ฅษฅฅพ๐ส๓ค๒อ๘อัควคญคคปค๓" -#: ../undo.c:1497 #, c-format msgid "Finished reading undo file %s" msgstr "ฅขฅ๓ฅษฅฅฅีฅกฅคฅ๋ %s คฮผ่นค๒ดฐฮป" -#: ../undo.c:1586 ../undo.c:1812 msgid "Already at oldest change" msgstr "ด๛คหฐ์ศึธลคคสันนควคน" -#: ../undo.c:1597 ../undo.c:1814 msgid "Already at newest change" msgstr "ด๛คหฐ์ศึฟทคทคคสันนควคน" -#: ../undo.c:1806 #, c-format -msgid "E830: Undo number %<PRId64> not found" -msgstr "E830: ฅขฅ๓ฅษฅฅศึนๆ %<PRId64> คฯธซคฤคซค๊คคปค๓" +msgid "E830: Undo number %ld not found" +msgstr "E830: ฅขฅ๓ฅษฅฅศึนๆ %ld คฯธซคฤคซค๊คคปค๓" -#: ../undo.c:1979 msgid "E438: u_undo: line numbers wrong" msgstr "E438: u_undo: นิศึนๆคฌดึฐใครคฦคคคคน" -#: ../undo.c:2183 msgid "more line" msgstr "นิ ฤษฒรคทคคทคฟ" -#: ../undo.c:2185 msgid "more lines" msgstr "นิ ฤษฒรคทคคทคฟ" -#: ../undo.c:2187 msgid "line less" msgstr "นิ บ๏ฝคทคคทคฟ" -#: ../undo.c:2189 msgid "fewer lines" msgstr "นิ บ๏ฝคทคคทคฟ" -#: ../undo.c:2193 msgid "change" msgstr "ฒีฝ๊สันนคทคคทคฟ" -#: ../undo.c:2195 msgid "changes" msgstr "ฒีฝ๊สันนคทคคทคฟ" -#: ../undo.c:2225 #, c-format -msgid "%<PRId64> %s; %s #%<PRId64> %s" -msgstr "%<PRId64> %s; %s #%<PRId64> %s" +msgid "%ld %s; %s #%ld %s" +msgstr "%ld %s; %s #%ld %s" -#: ../undo.c:2228 msgid "before" msgstr "มฐส" -#: ../undo.c:2228 msgid "after" msgstr "ธๅส" -#: ../undo.c:2325 msgid "Nothing to undo" msgstr "ฅขฅ๓ฅษฅฅยะพคฌคขค๊คคปค๓" -#: ../undo.c:2330 msgid "number changes when saved" msgstr "ฤฬศึ สันนฟ๔ สันนปด สยธบั" -#: ../undo.c:2360 #, c-format -msgid "%<PRId64> seconds ago" -msgstr "%<PRId64> ษรทะฒแคทคฦคคคคน" +msgid "%ld seconds ago" +msgstr "%ld ษรทะฒแคทคฦคคคคน" -#: ../undo.c:2372 msgid "E790: undojoin is not allowed after undo" msgstr "E790: undo คฮฤพธๅคห undojoin คฯควคญคคปค๓" -#: ../undo.c:2466 msgid "E439: undo list corrupt" msgstr "E439: ฅขฅ๓ฅษฅฅฅ๊ฅนฅศคฌฒ๕ค์คฦคคคคน" -#: ../undo.c:2495 msgid "E440: undo line missing" msgstr "E440: ฅขฅ๓ฅษฅฅนิคฌคขค๊คคปค๓" -#: ../version.c:600 +#, c-format +msgid "E122: Function %s already exists, add ! to replace it" +msgstr "E122: ดุฟ๔ %s คฯฤ๊ตมบัควคน, บฦฤ๊ตมคนค๋คหคฯ ! ค๒ฤษฒรคทคฦคฏคภคตคค" + +msgid "E717: Dictionary entry already exists" +msgstr "E717: ผญฝ๑ทฟฦโคหฅจฅ๓ฅศฅ๊คฌด๛คหยธบ฿คทคคน" + +msgid "E718: Funcref required" +msgstr "E718: ดุฟ๔ปฒพศทฟคฌอืตแคตค์คคน" + +#, c-format +msgid "E130: Unknown function: %s" +msgstr "E130: ฬครฮคฮดุฟ๔ควคน: %s" + +#, c-format +msgid "E125: Illegal argument: %s" +msgstr "E125: ษิภตคสฐ๚ฟ๔ควคน: %s" + +#, c-format +msgid "E853: Duplicate argument name: %s" +msgstr "E853: ฐ๚ฟ๔ฬพคฌฝลสฃคทคฦคคคคน: %s" + +#, c-format +msgid "E740: Too many arguments for function %s" +msgstr "E740: ดุฟ๔คฮฐ๚ฟ๔คฌยฟฒแคฎคคน: %s" + +#, c-format +msgid "E116: Invalid arguments for function %s" +msgstr "E116: ดุฟ๔คฮฬตธ๚คสฐ๚ฟ๔ควคน: %s" + +msgid "E132: Function call depth is higher than 'maxfuncdepth'" +msgstr "E132: ดุฟ๔ธฦฝะคฮฦค์ปาฟ๔คฌ 'maxfuncdepth' ค๒ฤถคจคคทคฟ" + +#, c-format +msgid "calling %s" +msgstr "%s ค๒ผยนิรๆควคน" + +#, c-format +msgid "%s aborted" +msgstr "%s คฌรๆรวคตค์คคทคฟ" + +#, c-format +msgid "%s returning #%ld" +msgstr "%s คฌ #%ld ค๒สึคทคคทคฟ" + +#, c-format +msgid "%s returning %s" +msgstr "%s คฌ %s ค๒สึคทคคทคฟ" + +msgid "E699: Too many arguments" +msgstr "E699: ฐ๚ฟ๔คฌยฟฒแคฎคคน" + +#, c-format +msgid "E117: Unknown function: %s" +msgstr "E117: ฬครฮคฮดุฟ๔ควคน: %s" + +#, c-format +msgid "E933: Function was deleted: %s" +msgstr "E933: ดุฟ๔คฯบ๏ฝคตค์คคทคฟ: %s" + +#, c-format +msgid "E119: Not enough arguments for function: %s" +msgstr "E119: ดุฟ๔คฮฐ๚ฟ๔คฌยญค๊คคปค๓: %s" + +#, c-format +msgid "E120: Using <SID> not in a script context: %s" +msgstr "E120: ฅนฅฏฅ๊ฅืฅศฐสณฐคว<SID>คฌปศค๏ค์คคทคฟ: %s" + +#, c-format +msgid "E725: Calling dict function without Dictionary: %s" +msgstr "E725: ผญฝ๑อัดุฟ๔คฌธฦคะค์คคทคฟคฌผญฝ๑คฌคขค๊คคปค๓: %s" + +msgid "E129: Function name required" +msgstr "E129: ดุฟ๔ฬพคฌอืตแคตค์คคน" + +#, c-format +msgid "E128: Function name must start with a capital or \"s:\": %s" +msgstr "E128: ดุฟ๔ฬพคฯย็สธป๚คซ \"s:\" ควปฯคค้คสคฑค์คะคสค๊คคปค๓: %s" + +#, c-format +msgid "E884: Function name cannot contain a colon: %s" +msgstr "E884: ดุฟ๔ฬพคหคฯฅณฅํฅ๓คฯดคแค้ค์คคปค๓: %s" + +#, c-format +msgid "E123: Undefined function: %s" +msgstr "E123: ฬคฤ๊ตมคฮดุฟ๔ควคน: %s" + +#, c-format +msgid "E124: Missing '(': %s" +msgstr "E124: '(' คฌคขค๊คคปค๓: %s" + +msgid "E862: Cannot use g: here" +msgstr "E862: คณคณควคฯ g: คฯปศคจคคปค๓" + +#, c-format +msgid "E932: Closure function should not be at top level: %s" +msgstr "E932: ฅฏฅํกผฅธฅใกผดุฟ๔คฯฅศฅรฅืฅ์ฅูฅ๋คหตญฝาควคญคคปค๓: %s" + +msgid "E126: Missing :endfunction" +msgstr "E126: :endfunction คฌคขค๊คคปค๓" + +#, c-format +msgid "E707: Function name conflicts with variable: %s" +msgstr "E707: ดุฟ๔ฬพคฌสัฟ๔ฬพคศพืฦอคทคคน: %s" + +#, c-format +msgid "E127: Cannot redefine function %s: It is in use" +msgstr "E127: ดุฟ๔ %s ค๒บฦฤ๊ตมควคญคคปค๓: ปศอัรๆควคน" + +#, c-format +msgid "E746: Function name does not match script file name: %s" +msgstr "E746: ดุฟ๔ฬพคฌฅนฅฏฅ๊ฅืฅศคฮฅีฅกฅคฅ๋ฬพคศฐ์รืคทคคปค๓: %s" + +#, c-format +msgid "E131: Cannot delete function %s: It is in use" +msgstr "E131: ดุฟ๔ %s ค๒บ๏ฝควคญคคปค๓: ปศอัรๆควคน" + +msgid "E133: :return not inside a function" +msgstr "E133: ดุฟ๔ณฐคห :return คฌคขค๊คคทคฟ" + +#, c-format +msgid "E107: Missing parentheses: %s" +msgstr "E107: ฅซฅรฅณ '(' คฌคขค๊คคปค๓: %s" + +#. Only MS VC 4.1 and earlier can do Win32s +msgid "" +"\n" +"MS-Windows 16/32-bit GUI version" +msgstr "" +"\n" +"MS-Windows 16/32 ฅำฅรฅศ GUI ศว" + +msgid "" +"\n" +"MS-Windows 64-bit GUI version" +msgstr "" +"\n" +"MS-Windows 64 ฅำฅรฅศ GUI ศว" + +msgid "" +"\n" +"MS-Windows 32-bit GUI version" +msgstr "" +"\n" +"MS-Windows 32 ฅำฅรฅศ GUI ศว" + +msgid " with OLE support" +msgstr " with OLE ฅตฅกผฅศ" + +msgid "" +"\n" +"MS-Windows 64-bit console version" +msgstr "" +"\n" +"MS-Windows 64 ฅำฅรฅศ ฅณฅ๓ฅฝกผฅ๋ ศว" + +msgid "" +"\n" +"MS-Windows 32-bit console version" +msgstr "" +"\n" +"MS-Windows 32 ฅำฅรฅศ ฅณฅ๓ฅฝกผฅ๋ ศว" + +msgid "" +"\n" +"MacOS X (unix) version" +msgstr "" +"\n" +"MacOS X (unix) ศว" + +msgid "" +"\n" +"MacOS X version" +msgstr "" +"\n" +"MacOS X ศว" + +msgid "" +"\n" +"MacOS version" +msgstr "" +"\n" +"MacOS ศว" + +msgid "" +"\n" +"OpenVMS version" +msgstr "" +"\n" +"OpenVMS ศว" + msgid "" "\n" "Included patches: " @@ -6295,7 +6039,6 @@ msgstr "" "\n" "ลฌอับัฅัฅรฅม: " -#: ../version.c:627 msgid "" "\n" "Extra patches: " @@ -6303,11 +6046,9 @@ msgstr "" "\n" "ฤษฒรณศฤฅฅัฅรฅม: " -#: ../version.c:639 ../version.c:864 msgid "Modified by " msgstr "Modified by " -#: ../version.c:646 msgid "" "\n" "Compiled " @@ -6315,11 +6056,9 @@ msgstr "" "\n" "Compiled " -#: ../version.c:649 msgid "by " msgstr "by " -#: ../version.c:660 msgid "" "\n" "Huge version " @@ -6327,1886 +6066,926 @@ msgstr "" "\n" "Huge ศว " -#: ../version.c:661 +msgid "" +"\n" +"Big version " +msgstr "" +"\n" +"Big ศว " + +msgid "" +"\n" +"Normal version " +msgstr "" +"\n" +"ฤฬพ๏ ศว " + +msgid "" +"\n" +"Small version " +msgstr "" +"\n" +"Small ศว " + +msgid "" +"\n" +"Tiny version " +msgstr "" +"\n" +"Tiny ศว " + msgid "without GUI." msgstr "without GUI." -#: ../version.c:662 +msgid "with GTK3 GUI." +msgstr "with GTK3 GUI." + +msgid "with GTK2-GNOME GUI." +msgstr "with GTK2-GNOME GUI." + +msgid "with GTK2 GUI." +msgstr "with GTK2 GUI." + +msgid "with X11-Motif GUI." +msgstr "with X11-Motif GUI." + +msgid "with X11-neXtaw GUI." +msgstr "with X11-neXtaw GUI." + +msgid "with X11-Athena GUI." +msgstr "with X11-Athena GUI." + +msgid "with Photon GUI." +msgstr "with Photon GUI." + +msgid "with GUI." +msgstr "with GUI." + +msgid "with Carbon GUI." +msgstr "with Carbon GUI." + +msgid "with Cocoa GUI." +msgstr "with Cocoa GUI." + +msgid "with (classic) GUI." +msgstr "with (ฅฏฅ้ฅทฅรฅฏ) GUI." + msgid " Features included (+) or not (-):\n" msgstr " ตกวฝคฮฐ์อ๗ อญธ๚(+)/ฬตธ๚(-)\n" -#: ../version.c:667 msgid " system vimrc file: \"" msgstr " ฅทฅนฅฦฅเ vimrc: \"" -#: ../version.c:672 msgid " user vimrc file: \"" msgstr " ฅๆกผฅถกผ vimrc: \"" -#: ../version.c:677 msgid " 2nd user vimrc file: \"" msgstr " ย่2ฅๆกผฅถกผ vimrc: \"" -#: ../version.c:682 msgid " 3rd user vimrc file: \"" msgstr " ย่3ฅๆกผฅถกผ vimrc: \"" -#: ../version.c:687 msgid " user exrc file: \"" msgstr " ฅๆกผฅถกผ exrc: \"" -#: ../version.c:692 msgid " 2nd user exrc file: \"" msgstr " ย่2ฅๆกผฅถกผ exrc: \"" -#: ../version.c:699 +msgid " system gvimrc file: \"" +msgstr " ฅทฅนฅฦฅเ gvimrc: \"" + +msgid " user gvimrc file: \"" +msgstr " ฅๆกผฅถกผ gvimrc: \"" + +msgid "2nd user gvimrc file: \"" +msgstr " ย่2ฅๆกผฅถกผ gvimrc: \"" + +msgid "3rd user gvimrc file: \"" +msgstr " ย่3ฅๆกผฅถกผ gvimrc: \"" + +msgid " defaults file: \"" +msgstr " ฅวฅีฅฉฅ๋ฅศฅีฅกฅคฅ๋: \"" + +msgid " system menu file: \"" +msgstr " ฅทฅนฅฦฅเฅแฅหฅๅกผ: \"" + msgid " fall-back for $VIM: \"" msgstr " พสฮฌปคฮ $VIM: \"" -#: ../version.c:705 msgid " f-b for $VIMRUNTIME: \"" msgstr "พสฮฌปคฮ $VIMRUNTIME: \"" -#: ../version.c:709 msgid "Compilation: " msgstr "ฅณฅ๓ฅัฅคฅ๋: " -#: ../version.c:712 +msgid "Compiler: " +msgstr "ฅณฅ๓ฅัฅคฅ้: " + msgid "Linking: " msgstr "ฅ๊ฅ๓ฅฏ: " -#: ../version.c:717 msgid " DEBUG BUILD" msgstr "ฅวฅะฅรฅฐฅำฅ๋ฅษ" -#: ../version.c:767 msgid "VIM - Vi IMproved" msgstr "VIM - Vi IMproved" -#: ../version.c:769 msgid "version " msgstr "version " -#: ../version.c:770 msgid "by Bram Moolenaar et al." msgstr "by Bram Moolenaar ยพ." -#: ../version.c:774 msgid "Vim is open source and freely distributable" msgstr "Vim คฯฅชกผฅืฅ๓ฅฝกผฅนควคขค๊ผซอณคหวษฒฤวฝควคน" -#: ../version.c:776 msgid "Help poor children in Uganda!" msgstr "ฅฆฅฌฅ๓ฅภคฮทรคค์คสคคปาถกคฟคมคหฑ็ฝ๕ค๒!" -#: ../version.c:777 msgid "type :help iccf<Enter> for information " msgstr "พบูคสพ๐ส๓คฯ :help iccf<Enter> " -#: ../version.c:779 msgid "type :q<Enter> to exit " msgstr "ฝชฮปคนค๋คหคฯ :q<Enter> " -#: ../version.c:780 msgid "type :help<Enter> or <F1> for on-line help" msgstr "ฅชฅ๓ฅ้ฅคฅ๓ฅุฅ๋ฅืคฯ :help<Enter> คซ <F1> " -#: ../version.c:781 -msgid "type :help version7<Enter> for version info" -msgstr "ฅะกผฅธฅ็ฅ๓พ๐ส๓คฯ :help version7<Enter> " +msgid "type :help version8<Enter> for version info" +msgstr "ฅะกผฅธฅ็ฅ๓พ๐ส๓คฯ :help version8<Enter> " -#: ../version.c:784 msgid "Running in Vi compatible mode" msgstr "Viธ฿ดนฅโกผฅษควฦฐบ๎รๆ" -#: ../version.c:785 msgid "type :set nocp<Enter> for Vim defaults" msgstr "Vimฟไพฉรอคหคนค๋คหคฯ :set nocp<Enter> " -#: ../version.c:786 msgid "type :help cp-default<Enter> for info on this" msgstr "พบูคสพ๐ส๓คฯ :help cp-default<Enter>" -#: ../version.c:827 +msgid "menu Help->Orphans for information " +msgstr "พบูคฯฅแฅหฅๅกผคฮ ฅุฅ๋ฅื->ธษป๙ ค๒ปฒพศคทคฦฒผคตคค " + +msgid "Running modeless, typed text is inserted" +msgstr "ฅโกผฅษฬตควผยนิรๆ, ฅฟฅคฅืคทคฟสธป๚คฌมฦคตค์คคน" + +msgid "menu Edit->Global Settings->Toggle Insert Mode " +msgstr "ฅแฅหฅๅกผคฮ สิฝธ->มดยฮภ฿ฤ๊->มฦ(ฝ้ฟดผิ)ฅโกผฅษภฺยุ " + +msgid " for two modes " +msgstr " ควฅโกผฅษอญคห " + +msgid "menu Edit->Global Settings->Toggle Vi Compatible" +msgstr "ฅแฅหฅๅกผคฮ สิฝธ->มดยฮภ฿ฤ๊->Viธ฿ดนฅโกผฅษภฺยุ " + +msgid " for Vim defaults " +msgstr " ควVimคศคทคฦฦฐบ๎ " + msgid "Sponsor Vim development!" msgstr "Vimคฮณซศฏค๒ฑฑ็คทคฦคฏคภคตคค!" -#: ../version.c:828 msgid "Become a registered Vim user!" msgstr "Vimคฮละฯฟฅๆกผฅถกผคหคสครคฦคฏคภคตคค!" -#: ../version.c:831 msgid "type :help sponsor<Enter> for information " msgstr "พบูคสพ๐ส๓คฯ :help sponsor<Enter> " -#: ../version.c:832 msgid "type :help register<Enter> for information " msgstr "พบูคสพ๐ส๓คฯ :help register<Enter> " -#: ../version.c:834 msgid "menu Help->Sponsor/Register for information " msgstr "พบูคฯฅแฅหฅๅกผคฮ ฅุฅ๋ฅื->ฅนฅฅ๓ฅตกผ/ละฯฟ ค๒ปฒพศคทคฦฒผคตคค" -#: ../window.c:119 +msgid "WARNING: Windows 95/98/ME detected" +msgstr "ทูน๐: Windows 95/98/ME ค๒ธกฝะคทคคทคฟ" + +msgid "type :help windows95<Enter> for info on this" +msgstr "พบูคสพ๐ส๓คฯ :help windows95<Enter>" + msgid "Already only one window" msgstr "ด๛คหฅฆฅฃฅ๓ฅษฅฆคฯ1คฤคทคซคขค๊คคปค๓" -#: ../window.c:224 msgid "E441: There is no preview window" msgstr "E441: ฅืฅ์ฅำฅๅกผฅฆฅฃฅ๓ฅษฅฆคฌคขค๊คคปค๓" -#: ../window.c:559 msgid "E442: Can't split topleft and botright at the same time" msgstr "E442: บธพๅคศฑฆฒผค๒ฦฑปคหสฌณไคนค๋คณคศคฯควคญคคปค๓" -#: ../window.c:1228 msgid "E443: Cannot rotate when another window is split" msgstr "E443: ยพคฮฅฆฅฃฅ๓ฅษฅฆคฌสฌณไคตค์คฦคคค๋ปคหคฯฝ็ฒ๓ควคญคคปค๓" -#: ../window.c:1803 msgid "E444: Cannot close last window" msgstr "E444: บวธๅคฮฅฆฅฃฅ๓ฅษฅฆค๒สฤคธค๋คณคศคฯควคญคคปค๓" -#: ../window.c:1810 msgid "E813: Cannot close autocmd window" msgstr "E813: autocmdฅฆฅฃฅ๓ฅษฅฆคฯสฤคธค้ค์คคปค๓" -#: ../window.c:1814 msgid "E814: Cannot close window, only autocmd window would remain" msgstr "E814: autocmdฅฆฅฃฅ๓ฅษฅฆคทคซปฤค้คสคคคฟคแกขฅฆฅฃฅ๓ฅษฅฆคฯสฤคธค้ค์คคปค๓" -#: ../window.c:2717 msgid "E445: Other window contains changes" msgstr "E445: ยพคฮฅฆฅฃฅ๓ฅษฅฆคหคฯสันนคฌคขค๊คคน" -#: ../window.c:4805 msgid "E446: No file name under cursor" msgstr "E446: ฅซกผฅฝฅ๋คฮฒผคหฅีฅกฅคฅ๋ฬพคฌคขค๊คคปค๓" -msgid "List or number required" -msgstr "ฅ๊ฅนฅศคซฟ๔รอคฌษฌอืควคน" - -#~ msgid "E831: bf_key_init() called with empty password" -#~ msgstr "E831: bf_key_init() คฌถ๕ฅัฅนฅ๏กผฅษควธฦคำฝะคตค์คคทคฟ" - -#~ msgid "E820: sizeof(uint32_t) != 4" -#~ msgstr "E820: sizeof(uint32_t) != 4" - -#~ msgid "E817: Blowfish big/little endian use wrong" -#~ msgstr "E817: Blowfishฐลนๆคฮฅำฅรฅฐ/ฅ๊ฅศฅ๋ฅจฅ๓ฅวฅฃฅขฅ๓คฌดึฐใครคฦคคคคน" - -#~ msgid "E818: sha256 test failed" -#~ msgstr "E818: sha256คฮฅฦฅนฅศคหผบวิคทคคทคฟ" - -#~ msgid "E819: Blowfish test failed" -#~ msgstr "E819: Blowfishฐลนๆคฮฅฦฅนฅศคหผบวิคทคคทคฟ" - -#~ msgid "Patch file" -#~ msgstr "ฅัฅรฅมฅีฅกฅคฅ๋" - -#~ msgid "" -#~ "&OK\n" -#~ "&Cancel" -#~ msgstr "" -#~ "ท่ฤ๊(&O)\n" -#~ "ฅญฅใฅ๓ฅปฅ๋(&C)" - -#~ msgid "E240: No connection to Vim server" -#~ msgstr "E240: Vim ฅตกผฅะคุคฮภยณคฌคขค๊คคปค๓" - -#~ msgid "E241: Unable to send to %s" -#~ msgstr "E241: %s คุม๗ค๋คณคศคฌควคญคคปค๓" - -#~ msgid "E277: Unable to read a server reply" -#~ msgstr "E277: ฅตกผฅะคฮฑล๚คฌคขค๊คคปค๓" - -#~ msgid "E258: Unable to send to client" -#~ msgstr "E258: ฅฏฅ้ฅคฅขฅ๓ฅศคุม๗ค๋คณคศคฌควคญคคปค๓" - -#~ msgid "Save As" -#~ msgstr "สฬฬพควสยธ" - -#~ msgid "Edit File" -#~ msgstr "ฅีฅกฅคฅ๋ค๒สิฝธ" - -# Added at 27-Jan-2004. -#~ msgid " (NOT FOUND)" -#~ msgstr " (ธซคฤคซค๊คคปค๓)" - -#~ msgid "Source Vim script" -#~ msgstr "Vimฅนฅฏฅ๊ฅืฅศคฮผ่นค฿" - -#~ msgid "unknown" -#~ msgstr "ษิฬภ" - -#~ msgid "Edit File in new window" -#~ msgstr "ฟทคทคคฅฆฅฃฅ๓ฅษฅฆควฅีฅกฅคฅ๋ค๒สิฝธคทคคน" - -#~ msgid "Append File" -#~ msgstr "ฤษฒรฅีฅกฅคฅ๋" - -#~ msgid "Window position: X %d, Y %d" -#~ msgstr "ฅฆฅฃฅ๓ฅษฅฆฐฬรึ: X %d, Y %d" - -#~ msgid "Save Redirection" -#~ msgstr "ฅ๊ฅภฅคฅ์ฅฏฅศค๒สยธคทคคน" - -#~ msgid "Save View" -#~ msgstr "ฅำฅๅกผค๒สยธคทคคน" - -#~ msgid "Save Session" -#~ msgstr "ฅปฅรฅทฅ็ฅ๓พ๐ส๓ค๒สยธคทคคน" - -#~ msgid "Save Setup" -#~ msgstr "ภ฿ฤ๊ค๒สยธคทคคน" - -#~ msgid "E809: #< is not available without the +eval feature" -#~ msgstr "E809: #< คฯ +eval ตกวฝคฌฬตคคคศอ๘อัควคญคคปค๓" - -#~ msgid "E196: No digraphs in this version" -#~ msgstr "E196: คณคฮฅะกผฅธฅ็ฅ๓คหน็ป๚คฯคขค๊คคปค๓" - -#~ msgid "is a device (disabled with 'opendevice' option)" -#~ msgstr " คฯฅวฅะฅคฅนควคน ('opendevice' ฅชฅืฅทฅ็ฅ๓ควฒ๓ศ๒ควคญคคน)" - -#~ msgid "Reading from stdin..." -#~ msgstr "ษธฝเฦฮฯคซค้ฦษนค฿รๆ..." - -#~ msgid "[blowfish]" -#~ msgstr "[blowfishฐลนๆฒฝ]" - -#~ msgid "[crypted]" -#~ msgstr "[ฐลนๆฒฝ]" - -#~ msgid "E821: File is encrypted with unknown method" -#~ msgstr "E821: ฅีฅกฅคฅ๋คฌฬครฮคฮสหกควฐลนๆฒฝคตค์คฦคคคคน" - -# Added at 19-Jan-2004. -#~ msgid "NetBeans disallows writes of unmodified buffers" -#~ msgstr "NetBeansคฯฬคสันนคฮฅะฅรฅีฅกค๒พๅฝ๑คนค๋คณคศคฯต๖ฒฤคทคฦคคคคปค๓" - -#~ msgid "Partial writes disallowed for NetBeans buffers" -#~ msgstr "NetBeansฅะฅรฅีฅกคฮฐ์ษ๔ค๒ฝ๑คญฝะคนคณคศคฯควคญคคปค๓" - -#~ msgid "writing to device disabled with 'opendevice' option" -#~ msgstr "'opendevice' ฅชฅืฅทฅ็ฅ๓คหค่ค๊ฅวฅะฅคฅนคุคฮฝ๑คญนค฿คฯควคญคคปค๓" - -#~ msgid "E460: The resource fork would be lost (add ! to override)" -#~ msgstr "E460: ฅ๊ฅฝกผฅนฅีฅฉกผฅฏคฌผบค๏ค์ค๋คซคโคทค์คคปค๓ (! ค๒ฤษฒรควถฏภฉ)" - -#~ msgid "E851: Failed to create a new process for the GUI" -#~ msgstr "E851: GUIอัคฮฅืฅํฅปฅนคฮตฏฦฐคหผบวิคทคคทคฟ" - -#~ msgid "E852: The child process failed to start the GUI" -#~ msgstr "E852: ปาฅืฅํฅปฅนคฌGUIคฮตฏฦฐคหผบวิคทคคทคฟ" - -#~ msgid "E229: Cannot start the GUI" -#~ msgstr "E229: GUIค๒ณซปฯควคญคคปค๓" - -#~ msgid "E230: Cannot read from \"%s\"" -#~ msgstr "E230: \"%s\"คซค้ฦษนคเคณคศคฌควคญคคปค๓" - -#~ msgid "E665: Cannot start GUI, no valid font found" -#~ msgstr "E665: อญธ๚คสฅีฅฉฅ๓ฅศคฌธซคฤคซค้คสคคคฮคว, GUIค๒ณซปฯควคญคคปค๓" - -#~ msgid "E231: 'guifontwide' invalid" -#~ msgstr "E231: 'guifontwide' คฌฬตธ๚ควคน" - -#~ msgid "E599: Value of 'imactivatekey' is invalid" -#~ msgstr "E599: 'imactivatekey' คหภ฿ฤ๊คตค์คฟรอคฌฬตธ๚ควคน" - -#~ msgid "E254: Cannot allocate color %s" -#~ msgstr "E254: %s คฮฟงค๒ณไค๊ล๖คฦค้ค์คคปค๓" - -#~ msgid "No match at cursor, finding next" -#~ msgstr "ฅซกผฅฝฅ๋คฮฐฬรึคหฅฅรฅมคฯคขค๊คคปค๓, ผกค๒ธกบ๗คทคฦคคคคน" - -#~ msgid "<cannot open> " -#~ msgstr "<ณซคฑคคปค๓> " - -#~ msgid "E616: vim_SelFile: can't get font %s" -#~ msgstr "E616: vim_SelFile: ฅีฅฉฅ๓ฅศ %s ค๒ผ่ฦภควคญคคปค๓" - -#~ msgid "E614: vim_SelFile: can't return to current directory" -#~ msgstr "E614: vim_SelFile: ธฝบ฿คฮฅวฅฃฅ์ฅฏฅศฅ๊คหฬแค์คคปค๓" - -#~ msgid "Pathname:" -#~ msgstr "ฅัฅนฬพ:" - -#~ msgid "E615: vim_SelFile: can't get current directory" -#~ msgstr "E615: vim_SelFile: ธฝบ฿คฮฅวฅฃฅ์ฅฏฅศฅ๊ค๒ผ่ฦภควคญคคปค๓" - -#~ msgid "OK" -#~ msgstr "OK" - -#~ msgid "Cancel" -#~ msgstr "ฅญฅใฅ๓ฅปฅ๋" - -#~ msgid "Scrollbar Widget: Could not get geometry of thumb pixmap." -#~ msgstr "ฅนฅฏฅํกผฅ๋ฅะกผ: ฒ่มค๒ผ่ฦภควคญคคปค๓ควคทคฟ." - -#~ msgid "Vim dialog" -#~ msgstr "Vim ฅภฅคฅขฅํฅฐ" - -#~ msgid "E232: Cannot create BalloonEval with both message and callback" -#~ msgstr "E232: ฅแฅรฅปกผฅธคศฅณกผฅ๋ฅะฅรฅฏคฮคขค๋ BalloonEval ค๒บ๎ภฎควคญคคปค๓" - -#~ msgid "Input _Methods" -#~ msgstr "ฅคฅ๓ฅืฅรฅศฅแฅฝฅรฅษ" - -#~ msgid "VIM - Search and Replace..." -#~ msgstr "VIM - ธกบ๗คศรึดน..." - -#~ msgid "VIM - Search..." -#~ msgstr "VIM - ธกบ๗..." - -#~ msgid "Find what:" -#~ msgstr "ธกบ๗สธป๚ฮ๓:" - -#~ msgid "Replace with:" -#~ msgstr "รึดนสธป๚ฮ๓:" - -#~ msgid "Match whole word only" -#~ msgstr "ภตณฮคหณบล๖คนค๋คโคฮคภคฑ" - -#~ msgid "Match case" -#~ msgstr "ย็สธป๚/พฎสธป๚ค๒ถ่สฬคนค๋" - -#~ msgid "Direction" -#~ msgstr "สธ" - -#~ msgid "Up" -#~ msgstr "พๅ" - -#~ msgid "Down" -#~ msgstr "ฒผ" - -#~ msgid "Find Next" -#~ msgstr "ผกค๒ธกบ๗" - -#~ msgid "Replace" -#~ msgstr "รึดน" - -#~ msgid "Replace All" -#~ msgstr "มดคฦรึดน" - -#~ msgid "Vim: Received \"die\" request from session manager\n" -#~ msgstr "Vim: ฅปฅรฅทฅ็ฅ๓ฅฅอกผฅธฅใคซค้ \"die\" อืตแค๒ผ๕คฑผ่ค๊คคทคฟ\n" - -#~ msgid "Close" -#~ msgstr "สฤคธค๋" - -#~ msgid "New tab" -#~ msgstr "ฟทตฌฅฟฅึฅฺกผฅธ" - -#~ msgid "Open Tab..." -#~ msgstr "ฅฟฅึฅฺกผฅธค๒ณซคฏ..." - -#~ msgid "Vim: Main window unexpectedly destroyed\n" -#~ msgstr "Vim: ฅแฅคฅ๓ฅฆฅฃฅ๓ฅษฅฆคฌษิฐีคหวหฒ๕คตค์คคทคฟ\n" - -#~ msgid "&Filter" -#~ msgstr "ฅีฅฃฅ๋ฅฟ(&F)" - -#~ msgid "&Cancel" -#~ msgstr "ฅญฅใฅ๓ฅปฅ๋(&C)" - -#~ msgid "Directories" -#~ msgstr "ฅวฅฃฅ์ฅฏฅศฅ๊" - -#~ msgid "Filter" -#~ msgstr "ฅีฅฃฅ๋ฅฟ" - -#~ msgid "&Help" -#~ msgstr "ฅุฅ๋ฅื(&H)" - -#~ msgid "Files" -#~ msgstr "ฅีฅกฅคฅ๋" - -#~ msgid "&OK" -#~ msgstr "&OK" - -#~ msgid "Selection" -#~ msgstr "มชย๒" - -#~ msgid "Find &Next" -#~ msgstr "ผกค๒ธกบ๗(&N)" - -#~ msgid "&Replace" -#~ msgstr "รึดน(&R)" - -#~ msgid "Replace &All" -#~ msgstr "มดคฦรึดน(&A)" - -#~ msgid "&Undo" -#~ msgstr "ฅขฅ๓ฅษฅฅ(&U)" - -#~ msgid "E671: Cannot find window title \"%s\"" -#~ msgstr "E671: ฅฟฅคฅศฅ๋คฌ \"%s\" คฮฅฆฅฃฅ๓ฅษฅฆคฯธซคฤคซค๊คคปค๓" - -#~ msgid "E243: Argument not supported: \"-%s\"; Use the OLE version." -#~ msgstr "E243: ฐ๚ฟ๔คฯฅตฅกผฅศคตค์คคปค๓: \"-%s\"; OLEศวค๒ปศอัคทคฦคฏคภคตคค." - -#~ msgid "E672: Unable to open window inside MDI application" -#~ msgstr "E672: MDIฅขฅืฅ๊คฮรๆควคฯฅฆฅฃฅ๓ฅษฅฆค๒ณซคฑคคปค๓" - -#~ msgid "Close tab" -#~ msgstr "ฅฟฅึฅฺกผฅธค๒สฤคธค๋" - -#~ msgid "Open tab..." -#~ msgstr "ฅฟฅึฅฺกผฅธค๒ณซคฏ" - -#~ msgid "Find string (use '\\\\' to find a '\\')" -#~ msgstr "ธกบ๗สธป๚ฮ๓ ('\\' ค๒ธกบ๗คนค๋คหคฯ '\\\\')" - -#~ msgid "Find & Replace (use '\\\\' to find a '\\')" -#~ msgstr "ธกบ๗กฆรึดน ('\\' ค๒ธกบ๗คนค๋คหคฯ '\\\\')" - -#~ msgid "Not Used" -#~ msgstr "ปศค๏ค์คคปค๓" - -#~ msgid "Directory\t*.nothing\n" -#~ msgstr "ฅวฅฃฅ์ฅฏฅศฅ๊\t*.nothing\n" - -#~ msgid "" -#~ "Vim E458: Cannot allocate colormap entry, some colors may be incorrect" -#~ msgstr "Vim E458: ฟงปุฤ๊คฌภตคทคฏคสคคคฮควฅจฅ๓ฅศฅ๊ค๒ณไค๊ล๖คฦค้ค์คคปค๓" - -#~ msgid "E250: Fonts for the following charsets are missing in fontset %s:" -#~ msgstr "E250: ฐสฒผคฮสธป๚ฅปฅรฅศคฮฅีฅฉฅ๓ฅศคฌคขค๊คคปค๓ %s:" - -#~ msgid "E252: Fontset name: %s" -#~ msgstr "E252: ฅีฅฉฅ๓ฅศฅปฅรฅศฬพ: %s" - -#~ msgid "Font '%s' is not fixed-width" -#~ msgstr "ฅีฅฉฅ๓ฅศ '%s' คฯธวฤ๊ษควคฯคขค๊คคปค๓" - -#~ msgid "E253: Fontset name: %s" -#~ msgstr "E253: ฅีฅฉฅ๓ฅศฅปฅรฅศฬพ: %s" - -#~ msgid "Font0: %s" -#~ msgstr "ฅีฅฉฅ๓ฅศ0: %s" - -#~ msgid "Font1: %s" -#~ msgstr "ฅีฅฉฅ๓ฅศ1: %s" - -#~ msgid "Font%<PRId64> width is not twice that of font0" -#~ msgstr "ฅีฅฉฅ๓ฅศ%<PRId64> คฮษคฌฅีฅฉฅ๓ฅศ0คฮ2วควคฯคขค๊คคปค๓" - -#~ msgid "Font0 width: %<PRId64>" -#~ msgstr "ฅีฅฉฅ๓ฅศ0คฮษ: %<PRId64>" - -#~ msgid "Font1 width: %<PRId64>" -#~ msgstr "ฅีฅฉฅ๓ฅศ1คฮษ: %<PRId64>" - -#~ msgid "Invalid font specification" -#~ msgstr "ฬตธ๚คสฅีฅฉฅ๓ฅศปุฤ๊ควคน" - -#~ msgid "&Dismiss" -#~ msgstr "ตัฒผคนค๋(&D)" - -#~ msgid "no specific match" -#~ msgstr "ฅฅรฅมคนค๋คโคฮคฌคขค๊คคปค๓" - -#~ msgid "Vim - Font Selector" -#~ msgstr "Vim - ฅีฅฉฅ๓ฅศมชย๒" - -#~ msgid "Name:" -#~ msgstr "ฬพมฐ:" - -#~ msgid "Show size in Points" -#~ msgstr "ฅตฅคฅบค๒ฅฅคฅ๓ฅศควษฝผจคนค๋" - -#~ msgid "Encoding:" -#~ msgstr "ฅจฅ๓ฅณกผฅษ:" - -#~ msgid "Font:" -#~ msgstr "ฅีฅฉฅ๓ฅศ:" - -#~ msgid "Style:" -#~ msgstr "ฅนฅฟฅคฅ๋:" - -#~ msgid "Size:" -#~ msgstr "ฅตฅคฅบ:" - -#~ msgid "E256: Hangul automata ERROR" -#~ msgstr "E256: ฅฯฅ๓ฅฐฅ๋ฅชกผฅศฅฅศฅ๓ฅจฅ้กผ" - -#~ msgid "E563: stat error" -#~ msgstr "E563: stat ฅจฅ้กผ" - -#~ msgid "E625: cannot open cscope database: %s" -#~ msgstr "E625: cscopeฅวกผฅฟฅูกผฅน: %s ค๒ณซคฏคณคศคฌควคญคคปค๓" - -#~ msgid "E626: cannot get cscope database information" -#~ msgstr "E626: cscopeฅวกผฅฟฅูกผฅนคฮพ๐ส๓ค๒ผ่ฦภควคญคคปค๓" - -#~ msgid "Lua library cannot be loaded." -#~ msgstr "Luaฅ้ฅคฅึฅ้ฅ๊ค๒ฅํกผฅษควคญคคปค๓." - -#~ msgid "cannot save undo information" -#~ msgstr "ฅขฅ๓ฅษฅฅพ๐ส๓คฌสยธควคญคคปค๓" - -#~ msgid "" -#~ "E815: Sorry, this command is disabled, the MzScheme libraries could not " -#~ "be loaded." -#~ msgstr "" -#~ "E815: คณคฮฅณฅฅ๓ฅษคฯฬตธ๚ควคน. MzScheme ฅ้ฅคฅึฅ้ฅ๊ค๒ฅํกผฅษควคญคคปค๓." - -#~ msgid "invalid expression" -#~ msgstr "ฬตธ๚คสผฐควคน" - -#~ msgid "expressions disabled at compile time" -#~ msgstr "ผฐคฯฅณฅ๓ฅัฅคฅ๋ปคหฬตธ๚คหคตค์คฦคคคคน" - -#~ msgid "hidden option" -#~ msgstr "ฑฃคทฅชฅืฅทฅ็ฅ๓" - -#~ msgid "unknown option" -#~ msgstr "ฬครฮคฮฅชฅืฅทฅ็ฅ๓ควคน" - -#~ msgid "window index is out of range" -#~ msgstr "ศฯฐฯณฐคฮฅฆฅฃฅ๓ฅษฅฆศึนๆควคน" - -#~ msgid "couldn't open buffer" -#~ msgstr "ฅะฅรฅีฅกค๒ณซคฑคคปค๓" - -#~ msgid "cannot delete line" -#~ msgstr "นิค๒พรคปคคปค๓" - -#~ msgid "cannot replace line" -#~ msgstr "นิค๒รึดนควคญคคปค๓" - -#~ msgid "cannot insert line" -#~ msgstr "นิค๒มฦควคญคคปค๓" - -#~ msgid "string cannot contain newlines" -#~ msgstr "สธป๚ฮ๓คหคฯฒนิสธป๚ค๒ดคแค้ค์คคปค๓" - -#~ msgid "error converting Scheme values to Vim" -#~ msgstr "SchemeรอคฮVimคุคฮสัดนฅจฅ้กผ" - -#~ msgid "Vim error: ~a" -#~ msgstr "Vim ฅจฅ้กผ: ~a" - -#~ msgid "Vim error" -#~ msgstr "Vim ฅจฅ้กผ" - -#~ msgid "buffer is invalid" -#~ msgstr "ฅะฅรฅีฅกคฯฬตธ๚ควคน" - -#~ msgid "window is invalid" -#~ msgstr "ฅฆฅฃฅ๓ฅษฅฆคฯฬตธ๚ควคน" - -#~ msgid "linenr out of range" -#~ msgstr "ศฯฐฯณฐคฮนิศึนๆควคน" - -#~ msgid "not allowed in the Vim sandbox" -#~ msgstr "ฅตฅ๓ฅษฅฅรฅฏฅนควคฯต๖คตค์คคปค๓" - -#~ msgid "E370: Could not load library %s" -#~ msgstr "E370: ฅ้ฅคฅึฅ้ฅ๊ %s ค๒ฅํกผฅษควคญคคปค๓ควคทคฟ" - -#~ msgid "" -#~ "Sorry, this command is disabled: the Perl library could not be loaded." -#~ msgstr "" -#~ "คณคฮฅณฅฅ๓ฅษคฯฬตธ๚ควคน, คดคแค๓คสคตคค: Perlฅ้ฅคฅึฅ้ฅ๊ค๒ฅํกผฅษควคญคคปค๓ควคท" -#~ "คฟ." - -#~ msgid "E299: Perl evaluation forbidden in sandbox without the Safe module" -#~ msgstr "" -#~ "E299: ฅตฅ๓ฅษฅฅรฅฏฅนควคฯ Safe ฅโฅธฅๅกผฅ๋ค๒ปศอัคทคสคคPerlฅนฅฏฅ๊ฅืฅศคฯถุคธค้" -#~ "ค์คฦคคคคน" - -#~ msgid "E836: This Vim cannot execute :python after using :py3" -#~ msgstr "E836: คณคฮVimควคฯ :py3 ค๒ปศครคฟธๅคห :python ค๒ปศคจคคปค๓" - -#~ msgid "" -#~ "E263: Sorry, this command is disabled, the Python library could not be " -#~ "loaded." -#~ msgstr "" -#~ "E263: คณคฮฅณฅฅ๓ฅษคฯฬตธ๚ควคน,คดคแค๓คสคตคค: Pythonฅ้ฅคฅึฅ้ฅ๊ค๒ฅํกผฅษควคญค" -#~ "คปค๓ควคทคฟ." - -# Added at 07-Feb-2004. -#~ msgid "E659: Cannot invoke Python recursively" -#~ msgstr "E659: Python ค๒บฦตขลชคหผยนิคนค๋คณคศคฯควคญคคปค๓" - -#~ msgid "E837: This Vim cannot execute :py3 after using :python" -#~ msgstr "E837: คณคฮVimควคฯ :python ค๒ปศครคฟธๅคห :py3 ค๒ปศคจคคปค๓" - -#~ msgid "E265: $_ must be an instance of String" -#~ msgstr "E265: $_ คฯสธป๚ฮ๓คฮฅคฅ๓ฅนฅฟฅ๓ฅนควคสคฑค์คะคสค๊คคปค๓" - -#~ msgid "" -#~ "E266: Sorry, this command is disabled, the Ruby library could not be " -#~ "loaded." -#~ msgstr "" -#~ "E266: คณคฮฅณฅฅ๓ฅษคฯฬตธ๚ควคน,คดคแค๓คสคตคค: Rubyฅ้ฅคฅึฅ้ฅ๊ค๒ฅํกผฅษควคญคคป" -#~ "ค๓ควคทคฟ." - -#~ msgid "E267: unexpected return" -#~ msgstr "E267: อฝดคปคฬ return ควคน" - -#~ msgid "E268: unexpected next" -#~ msgstr "E268: อฝดคปคฬ next ควคน" - -#~ msgid "E269: unexpected break" -#~ msgstr "E269: อฝดคปคฬ break ควคน" - -#~ msgid "E270: unexpected redo" -#~ msgstr "E270: อฝดคปคฬ redo ควคน" - -#~ msgid "E271: retry outside of rescue clause" -#~ msgstr "E271: rescue คฮณฐคฮ retry ควคน" - -#~ msgid "E272: unhandled exception" -#~ msgstr "E272: ผ่ค๊ฐทค๏ค์คสคซครคฟฮใณฐคฌคขค๊คคน" - -#~ msgid "E273: unknown longjmp status %d" -#~ msgstr "E273: ฬครฮคฮlongjmpพ๕ยึ: %d" - -#~ msgid "Toggle implementation/definition" -#~ msgstr "ผยม๕คศฤ๊ตมค๒ภฺค๊ยุคจค๋" - -#~ msgid "Show base class of" -#~ msgstr "ผกคฮฅฏฅ้ฅนคฮด๐ฤ์ค๒ษฝผจ" - -#~ msgid "Show overridden member function" -#~ msgstr "ฅชกผฅะกผฅ้ฅคฅษคตค์คฟฅแฅ๓ฅะดุฟ๔ค๒ษฝผจ" - -#~ msgid "Retrieve from file" -#~ msgstr "ฅีฅกฅคฅ๋คซค้ฒ๓ษคนค๋" - -#~ msgid "Retrieve from project" -#~ msgstr "ฅืฅํฅธฅงฅฏฅศคซค้ฒ๓ษคนค๋" - -#~ msgid "Retrieve from all projects" -#~ msgstr "มดคฦคฮฅืฅํฅธฅงฅฏฅศคซค้ฒ๓ษคนค๋" - -#~ msgid "Retrieve" -#~ msgstr "ฒ๓ษ" - -#~ msgid "Show source of" -#~ msgstr "ผกคฮฅฝกผฅนค๒ษฝผจคนค๋" - -#~ msgid "Find symbol" -#~ msgstr "ธซคฤคฑคฟฅทฅ๓ฅฅ๋" - -#~ msgid "Browse class" -#~ msgstr "ฅฏฅ้ฅนค๒ปฒพศ" - -#~ msgid "Show class in hierarchy" -#~ msgstr "ณฌมุควฅฏฅ้ฅนค๒ษฝผจ" - -#~ msgid "Show class in restricted hierarchy" -#~ msgstr "ธยฤ๊คตค์คฟณฌมุควฅฏฅ้ฅนค๒ษฝผจ" - -#~ msgid "Xref refers to" -#~ msgstr "Xref คฮปฒพศภ่" - -#~ msgid "Xref referred by" -#~ msgstr "Xref คฌปฒพศคตค์ค๋" - -#~ msgid "Xref has a" -#~ msgstr "Xref คฌผกคฮคโคฮค๒คโครคฦคคคคน" - -#~ msgid "Xref used by" -#~ msgstr "Xref คฌปศอัคตค์ค๋" - -#~ msgid "Show docu of" -#~ msgstr "ผกคฮสธพฯค๒ษฝผจ" - -#~ msgid "Generate docu for" -#~ msgstr "ผกคฮสธพฯค๒ภธภฎ" - -#~ msgid "" -#~ "Cannot connect to SNiFF+. Check environment (sniffemacs must be found in " -#~ "$PATH).\n" -#~ msgstr "" -#~ "SNiFF+คหภยณควคญคคปค๓. ดฤถญค๒ฅมฅงฅรฅฏคทคฦคฏคภคตคค(sniffemacs คฌ $PATH คห" -#~ "คสคฑค์คะคสค๊คคปค๓).\n" - -#~ msgid "E274: Sniff: Error during read. Disconnected" -#~ msgstr "E274: Sniff: ฦษนรๆคหฅจฅ้กผคฌศฏภธคทคคทคฟ. ภฺรวคทคคทคฟ" - -#~ msgid "SNiFF+ is currently " -#~ msgstr "ธฝบ฿SNiFF+ คฮพ๕ยึคฯกึ" - -#~ msgid "not " -#~ msgstr "ฬค" - -#~ msgid "connected" -#~ msgstr "ภยณกืควคน" - -#~ msgid "E275: Unknown SNiFF+ request: %s" -#~ msgstr "E275: ฬครฮคฮ SNiFF+ ฅ๊ฅฏฅจฅนฅศควคน: %s" - -#~ msgid "E276: Error connecting to SNiFF+" -#~ msgstr "E276: SNiFF+ คุคฮภยณรๆคฮฅจฅ้กผควคน" - -#~ msgid "E278: SNiFF+ not connected" -#~ msgstr "E278: SNiFF+ คหภยณคตค์คฦคคคคปค๓" - -#~ msgid "E279: Not a SNiFF+ buffer" -#~ msgstr "E279: SNiFF+ ฅะฅรฅีฅกคฌคขค๊คคปค๓" - -#~ msgid "Sniff: Error during write. Disconnected" -#~ msgstr "Sniff: ฝ๑นค฿รๆคหฅจฅ้กผคฌศฏภธคทคฟคฮควภฺรวคทคคทคฟ" - -#~ msgid "invalid buffer number" -#~ msgstr "ฬตธ๚คสฅะฅรฅีฅกศึนๆควคน" - -#~ msgid "not implemented yet" -#~ msgstr "คคภผยม๕คตค์คฦคคคคปค๓" - -#~ msgid "cannot set line(s)" -#~ msgstr "นิค๒ภ฿ฤ๊ควคญคคปค๓" - -#~ msgid "invalid mark name" -#~ msgstr "ฬตธ๚คสฅกผฅฏฬพควคน" - -#~ msgid "mark not set" -#~ msgstr "ฅกผฅฏคฯภ฿ฤ๊คตค์คฦคคคคปค๓" - -#~ msgid "row %d column %d" -#~ msgstr "นิ %d ฮ๓ %d" - -#~ msgid "cannot insert/append line" -#~ msgstr "นิคฮมฦ/ฤษฒรค๒ควคญคคปค๓" - -#~ msgid "line number out of range" -#~ msgstr "ศฯฐฯณฐคฮนิศึนๆควคน" - -#~ msgid "unknown flag: " -#~ msgstr "ฬครฮคฮฅีฅ้ฅฐ: " - -#~ msgid "unknown vimOption" -#~ msgstr "ฬครฮคฮ vimOption ควคน" - -#~ msgid "keyboard interrupt" -#~ msgstr "ฅญกผฅกผฅษณไนค฿" - -#~ msgid "vim error" -#~ msgstr "vim ฅจฅ้กผ" - -#~ msgid "cannot create buffer/window command: object is being deleted" -#~ msgstr "" -#~ "ฅะฅรฅีฅก/ฅฆฅฃฅ๓ฅษฅฆบ๎ภฎฅณฅฅ๓ฅษค๒บ๎ภฎควคญคคปค๓: ฅชฅึฅธฅงฅฏฅศคฌพรต๎คตค์คฦ" -#~ "คคคคทคฟ" - -#~ msgid "" -#~ "cannot register callback command: buffer/window is already being deleted" -#~ msgstr "" -#~ "ฅณกผฅ๋ฅะฅรฅฏฅณฅฅ๓ฅษค๒ละฯฟควคญคคปค๓: ฅะฅรฅีฅก/ฅฆฅฃฅ๓ฅษฅฆคฌด๛คหพรต๎คตค์ค" -#~ "คทคฟ" - -#~ msgid "" -#~ "E280: TCL FATAL ERROR: reflist corrupt!? Please report this to vim-" -#~ "dev@vim.org" -#~ msgstr "" -#~ "E280: TCL รืฬฟลชฅจฅ้กผ: reflist ฑ๘ภ๗!? vim-dev@vim.org คหส๓น๐คทคฦคฏคภคตคค" - -#~ msgid "cannot register callback command: buffer/window reference not found" -#~ msgstr "" -#~ "ฅณกผฅ๋ฅะฅรฅฏฅณฅฅ๓ฅษค๒ละฯฟควคญคคปค๓: ฅะฅรฅีฅก/ฅฆฅฃฅ๓ฅษฅฆคฮปฒพศคฌธซคฤคซค๊" -#~ "คคปค๓" - -#~ msgid "" -#~ "E571: Sorry, this command is disabled: the Tcl library could not be " -#~ "loaded." -#~ msgstr "" -#~ "E571: คณคฮฅณฅฅ๓ฅษคฯฬตธ๚ควคน,คดคแค๓คสคตคค: Tclฅ้ฅคฅึฅ้ฅ๊ค๒ฅํกผฅษควคญคคปค๓" -#~ "ควคทคฟ." - -#~ msgid "E572: exit code %d" -#~ msgstr "E572: ฝชฮปฅณกผฅษ %d" - -#~ msgid "cannot get line" -#~ msgstr "นิค๒ผ่ฦภควคญคคปค๓" - -#~ msgid "Unable to register a command server name" -#~ msgstr "ฬฟฮแฅตกผฅะคฮฬพมฐค๒ละฯฟควคญคคปค๓" - -#~ msgid "E248: Failed to send command to the destination program" -#~ msgstr "E248: ฬลชคฮฅืฅํฅฐฅ้ฅเคุคฮฅณฅฅ๓ฅษม๗ฟฎคหผบวิคทคคทคฟ" - -#~ msgid "E573: Invalid server id used: %s" -#~ msgstr "E573: ฬตธ๚คสฅตกผฅะIDคฌปศค๏ค์คคทคฟ: %s" - -#~ msgid "E251: VIM instance registry property is badly formed. Deleted!" -#~ msgstr "E251: VIM ผยยฮคฮละฯฟฅืฅํฅัฅฦฅฃคฌษิภตควคน. พรต๎คทคคทคฟ!" - -#~ msgid "netbeans is not supported with this GUI\n" -#~ msgstr "netbeans คฯคณคฮGUIควคฯอ๘อัควคญคคปค๓\n" - -#~ msgid "This Vim was not compiled with the diff feature." -#~ msgstr "คณคฮVimคหคฯdiffตกวฝคฌคขค๊คคปค๓(ฅณฅ๓ฅัฅคฅ๋ปภ฿ฤ๊)." - -#~ msgid "'-nb' cannot be used: not enabled at compile time\n" -#~ msgstr "'-nb' ปศอัษิฒฤวฝควคน: ฅณฅ๓ฅัฅคฅ๋ปคหฬตธ๚คหคตค์คฦคคคคน\n" - -#~ msgid "Vim: Error: Failure to start gvim from NetBeans\n" -#~ msgstr "Vim: ฅจฅ้กผ: NetBeansคซค้gvimค๒ฅนฅฟกผฅศควคญคคปค๓\n" - -#~ msgid "" -#~ "\n" -#~ "Where case is ignored prepend / to make flag upper case" -#~ msgstr "" -#~ "\n" -#~ "ย็พฎสธป๚คฌฬตป๋คตค์ค๋พ์น็คฯย็สธป๚คหคนค๋คฟคแคห / ค๒มฐรึคทคฦคฏคภคตคค" - -#~ msgid "-register\t\tRegister this gvim for OLE" -#~ msgstr "-register\t\tคณคฮgvimค๒OLEคศคทคฦละฯฟคนค๋" - -#~ msgid "-unregister\t\tUnregister gvim for OLE" -#~ msgstr "-unregister\t\tgvimคฮOLEละฯฟค๒ฒ๒ฝคนค๋" - -#~ msgid "-g\t\t\tRun using GUI (like \"gvim\")" -#~ msgstr "-g\t\t\tGUIควตฏฦฐคนค๋ (\"gvim\" คศฦฑคธ)" - -#~ msgid "-f or --nofork\tForeground: Don't fork when starting GUI" -#~ msgstr "-f or --nofork\tฅีฅฉฅขฅฐฅ้ฅฆฅ๓ฅษ: GUIค๒ปฯคแค๋คศคญคหforkคทคสคค" - -#~ msgid "-f\t\t\tDon't use newcli to open window" -#~ msgstr "-f\t\t\tฅฆฅฃฅ๓ฅษฅฆค๒ณซคฏคฮคห newcli ค๒ปศอัคทคสคค" - -#~ msgid "-dev <device>\t\tUse <device> for I/O" -#~ msgstr "-dev <device>\t\tI/Oคห <device> ค๒ปศอัคนค๋" - -#~ msgid "-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc" -#~ msgstr "-U <gvimrc>\t\t.gvimrcคฮยๅค๏ค๊คห <gvimrc> ค๒ปศคฆ" - -#~ msgid "-x\t\t\tEdit encrypted files" -#~ msgstr "-x\t\t\tฐลนๆฒฝคตค์คฟฅีฅกฅคฅ๋ค๒สิฝธคนค๋" - -#~ msgid "-display <display>\tConnect vim to this particular X-server" -#~ msgstr "-display <display>\tvimค๒ปุฤ๊คทคฟ X ฅตกผฅะคหภยณคนค๋" - -#~ msgid "-X\t\t\tDo not connect to X server" -#~ msgstr "-X\t\t\tXฅตกผฅะคหภยณคทคสคค" - -#~ msgid "--remote <files>\tEdit <files> in a Vim server if possible" -#~ msgstr "--remote <files>\tฒฤวฝคสค้คะVimฅตกผฅะคว <files> ค๒สิฝธคนค๋" - -#~ msgid "--remote-silent <files> Same, don't complain if there is no server" -#~ msgstr "--remote-silent <files> ฦฑพๅ, ฅตกผฅะคฌฬตคฏคฦคโทูน๐สธค๒ฝะฮฯคทคสคค" - -#~ msgid "" -#~ "--remote-wait <files> As --remote but wait for files to have been edited" -#~ msgstr "--remote-wait <files>\t--remoteธๅ ฅีฅกฅคฅ๋คฮสิฝธคฌฝชค๏ค๋คฮค๒ยิคฤ" - -#~ msgid "" -#~ "--remote-wait-silent <files> Same, don't complain if there is no server" -#~ msgstr "" -#~ "--remote-wait-silent <files> ฦฑพๅ, ฅตกผฅะคฌฬตคฏคฦคโทูน๐สธค๒ฝะฮฯคทคสคค" - -#~ msgid "" -#~ "--remote-tab[-wait][-silent] <files> As --remote but use tab page per " -#~ "file" -#~ msgstr "" -#~ "--remote-tab[-wait][-silent] <files> --remoteควฅีฅกฅคฅ๋1คฤคหคฤคญ1คฤคฮฅฟฅึ" -#~ "ฅฺกผฅธค๒ณซคฏ" - -#~ msgid "--remote-send <keys>\tSend <keys> to a Vim server and exit" -#~ msgstr "--remote-send <keys>\tVimฅตกผฅะคห <keys> ค๒ม๗ฟฎคทคฦฝชฮปคนค๋" - -#~ msgid "" -#~ "--remote-expr <expr>\tEvaluate <expr> in a Vim server and print result" -#~ msgstr "--remote-expr <expr>\tฅตกผฅะคว <expr> ค๒ผยนิคทคฦท๋ฒฬค๒ษฝผจคนค๋" - -#~ msgid "--serverlist\t\tList available Vim server names and exit" -#~ msgstr "--serverlist\t\tVimฅตกผฅะฬพคฮฐ์อ๗ค๒ษฝผจคทคฦฝชฮปคนค๋" - -#~ msgid "--servername <name>\tSend to/become the Vim server <name>" -#~ msgstr "--servername <name>\tVimฅตกผฅะ <name> คหม๗ฟฎ/ฬพมฐภ฿ฤ๊คนค๋" - -#~ msgid "" -#~ "\n" -#~ "Arguments recognised by gvim (Motif version):\n" -#~ msgstr "" -#~ "\n" -#~ "gvimคหค่ครคฦฒ๒ผแคตค์ค๋ฐ๚ฟ๔(Motifฅะกผฅธฅ็ฅ๓):\n" - -#~ msgid "" -#~ "\n" -#~ "Arguments recognised by gvim (neXtaw version):\n" -#~ msgstr "" -#~ "\n" -#~ "gvimคหค่ครคฦฒ๒ผแคตค์ค๋ฐ๚ฟ๔(neXtawฅะกผฅธฅ็ฅ๓):\n" - -#~ msgid "" -#~ "\n" -#~ "Arguments recognised by gvim (Athena version):\n" -#~ msgstr "" -#~ "\n" -#~ "gvimคหค่ครคฦฒ๒ผแคตค์ค๋ฐ๚ฟ๔(Athenaฅะกผฅธฅ็ฅ๓):\n" - -#~ msgid "-display <display>\tRun vim on <display>" -#~ msgstr "-display <display>\t<display> ควvimค๒ผยนิคนค๋" - -#~ msgid "-iconic\t\tStart vim iconified" -#~ msgstr "-iconic\t\tบวพฎฒฝคทคฟพ๕ยึควvimค๒ตฏฦฐคนค๋" - -#~ msgid "-background <color>\tUse <color> for the background (also: -bg)" -#~ msgstr "-background <color>\tวุทสฟงคห <color> ค๒ปศคฆ(ฦฑตม: -bg)" - -#~ msgid "-foreground <color>\tUse <color> for normal text (also: -fg)" -#~ msgstr "-foreground <color>\tมฐทสฟงคห <color> ค๒ปศคฆ(ฦฑตม: -fg)" - -#~ msgid "-font <font>\t\tUse <font> for normal text (also: -fn)" -#~ msgstr "-font <font>\t\tฅฦฅญฅนฅศษฝผจคห <font> ค๒ปศคฆ(ฦฑตม: -fn)" - -#~ msgid "-boldfont <font>\tUse <font> for bold text" -#~ msgstr "-boldfont <font>\tยภป๚คห <font> ค๒ปศคฆ" - -#~ msgid "-italicfont <font>\tUse <font> for italic text" -#~ msgstr "-italicfont <for>\tผะยฮป๚คห <font> ค๒ปศคฆ" - -#~ msgid "-geometry <geom>\tUse <geom> for initial geometry (also: -geom)" -#~ msgstr "-geometry <geom>\tฝ้ดวรึคห <geom> ค๒ปศคฆ(ฦฑตม: -geom)" - -#~ msgid "-borderwidth <width>\tUse a border width of <width> (also: -bw)" -#~ msgstr "-borderwidth <width>\tถญณฆคฮษค๒ <width> คหคนค๋(ฦฑตม: -bw)" - -#~ msgid "" -#~ "-scrollbarwidth <width> Use a scrollbar width of <width> (also: -sw)" -#~ msgstr "" -#~ "-scrollbarwidth <width> ฅนฅฏฅํกผฅ๋ฅะกผคฮษค๒ <width> คหคนค๋(ฦฑตม: -sw)" - -#~ msgid "-menuheight <height>\tUse a menu bar height of <height> (also: -mh)" -#~ msgstr "" -#~ "-menuheight <height>\tฅแฅหฅๅกผฅะกผคฮนโคตค๒ <height> คหคนค๋(ฦฑตม: -mh)" - -#~ msgid "-reverse\t\tUse reverse video (also: -rv)" -#~ msgstr "-reverse\t\tศฟลพฑวมค๒ปศอัคนค๋(ฦฑตม: -rv)" - -#~ msgid "+reverse\t\tDon't use reverse video (also: +rv)" -#~ msgstr "+reverse\t\tศฟลพฑวมค๒ปศอัคทคสคค(ฦฑตม: +rv)" - -#~ msgid "-xrm <resource>\tSet the specified resource" -#~ msgstr "-xrm <resource>\tฦรฤ๊คฮฅ๊ฅฝกผฅนค๒ปศอัคนค๋" - -#~ msgid "" -#~ "\n" -#~ "Arguments recognised by gvim (GTK+ version):\n" -#~ msgstr "" -#~ "\n" -#~ "gvimคหค่ครคฦฒ๒ผแคตค์ค๋ฐ๚ฟ๔(GTK+ฅะกผฅธฅ็ฅ๓):\n" - -#~ msgid "-display <display>\tRun vim on <display> (also: --display)" -#~ msgstr "-display <display>\t<display> ควvimค๒ผยนิคนค๋(ฦฑตม: --display)" - -#~ msgid "--role <role>\tSet a unique role to identify the main window" -#~ msgstr "--role <role>\tฅแฅคฅ๓ฅฆฅฃฅ๓ฅษฅฆค๒ผฑสฬคนค๋ฐ์ฐีคสฬ๒ณไ(role)ค๒ภ฿ฤ๊คนค๋" - -#~ msgid "--socketid <xid>\tOpen Vim inside another GTK widget" -#~ msgstr "--socketid <xid>\tฐคสค๋GTK widgetควVimค๒ณซคฏ" - -#~ msgid "--echo-wid\t\tMake gvim echo the Window ID on stdout" -#~ msgstr "--echo-wid\t\tฅฆฅฃฅ๓ฅษฅฆIDค๒ษธฝเฝะฮฯคหฝะฮฯคนค๋" - -#~ msgid "-P <parent title>\tOpen Vim inside parent application" -#~ msgstr "-P <ฟฦคฮฅฟฅคฅศฅ๋>\tVimค๒ฟฦฅขฅืฅ๊ฅฑกผฅทฅ็ฅ๓คฮรๆควตฏฦฐคนค๋" - -#~ msgid "--windowid <HWND>\tOpen Vim inside another win32 widget" -#~ msgstr "--windowid <HWND>\tฐคสค๋Win32 widgetคฮฦโษ๔คหVimค๒ณซคฏ" - -#~ msgid "No display" -#~ msgstr "ฅวฅฃฅนฅืฅ์ฅคคฌธซคฤคซค๊คคปค๓" - -#~ msgid ": Send failed.\n" -#~ msgstr ": ม๗ฟฎคหผบวิคทคคทคฟ.\n" - -#~ msgid ": Send failed. Trying to execute locally\n" -#~ msgstr ": ม๗ฟฎคหผบวิคทคคทคฟ. ฅํกผฅซฅ๋ควคฮผยนิค๒ป๎ค฿คฦคคคคน\n" - -#~ msgid "%d of %d edited" -#~ msgstr "%d ธฤ (%d ธฤรๆ) คฮฅีฅกฅคฅ๋ค๒สิฝธคทคคทคฟ" - -#~ msgid "No display: Send expression failed.\n" -#~ msgstr "ฅวฅฃฅนฅืฅ์ฅคคฌคขค๊คคปค๓: ผฐคฮม๗ฟฎคหผบวิคทคคทคฟ.\n" - -#~ msgid ": Send expression failed.\n" -#~ msgstr ": ผฐคฮม๗ฟฎคหผบวิคทคคทคฟ.\n" - -#~ msgid "E543: Not a valid codepage" -#~ msgstr "E543: ฬตธ๚คสฅณกผฅษฅฺกผฅธควคน" - -#~ msgid "E284: Cannot set IC values" -#~ msgstr "E284: ICคฮรอค๒ภ฿ฤ๊ควคญคคปค๓" - -#~ msgid "E285: Failed to create input context" -#~ msgstr "E285: ฅคฅ๓ฅืฅรฅศฅณฅ๓ฅฦฅญฅนฅศคฮบ๎ภฎคหผบวิคทคคทคฟ" - -#~ msgid "E286: Failed to open input method" -#~ msgstr "E286: ฅคฅ๓ฅืฅรฅศฅแฅฝฅรฅษคฮฅชกผฅืฅ๓คหผบวิคทคคทคฟ" - -#~ msgid "E287: Warning: Could not set destroy callback to IM" -#~ msgstr "E287: ทูน๐: IMคฮวหฒ๕ฅณกผฅ๋ฅะฅรฅฏค๒ภ฿ฤ๊ควคญคคปค๓ควคทคฟ" - -#~ msgid "E288: input method doesn't support any style" -#~ msgstr "E288: ฅคฅ๓ฅืฅรฅศฅแฅฝฅรฅษคฯคษค๓คสฅนฅฟฅคฅ๋คโฅตฅกผฅศคทคคปค๓" - -#~ msgid "E289: input method doesn't support my preedit type" -#~ msgstr "E289: ฅคฅ๓ฅืฅรฅศฅแฅฝฅรฅษคฯ my preedit type ค๒ฅตฅกผฅศคทคคปค๓" +#, c-format +msgid "E447: Can't find file \"%s\" in path" +msgstr "E447: pathคหคฯ \"%s\" คศคคคฆฅีฅกฅคฅ๋คฌคขค๊คคปค๓" -#~ msgid "E843: Error while updating swap file crypt" -#~ msgstr "E843: ฅนฅ๏ฅรฅืฅีฅกฅคฅ๋คฮฐลนๆค๒นนฟทรๆคหฅจฅ้กผคฌศฏภธคทคคทคฟ" +#, c-format +msgid "E799: Invalid ID: %ld (must be greater than or equal to 1)" +msgstr "E799: ฬตธ๚คส ID: %ld (1 ฐสพๅควคสคฑค์คะคสค๊คคปค๓)" -#~ msgid "" -#~ "E833: %s is encrypted and this version of Vim does not support encryption" -#~ msgstr "" -#~ "E833: %s คฯคณคฮฅะกผฅธฅ็ฅ๓คฮVimควฅตฅกผฅศคทคฦคคคสคคทมผฐควฐลนๆฒฝคตค์คฦคคคคน" +#, c-format +msgid "E801: ID already taken: %ld" +msgstr "E801: ID คฯคนควคหอ๘อัรๆควคน: %ld" -#~ msgid "Swap file is encrypted: \"%s\"" -#~ msgstr "ฅนฅ๏ฅรฅืฅีฅกฅคฅ๋คฯฐลนๆฒฝคตค์คฦคคคคน: \"%s\"" +msgid "List or number required" +msgstr "ฅ๊ฅนฅศคซฟ๔รอคฌษฌอืควคน" -#~ msgid "" -#~ "\n" -#~ "If you entered a new crypt key but did not write the text file," -#~ msgstr "" -#~ "\n" -#~ "ฟทคทคคฐลนๆฅญกผค๒ฦฮฯคทคฟคขคศคหฅฦฅญฅนฅศฅีฅกฅคฅ๋ค๒สยธคทคฦคคคสคคพ์น็คฯ," +#, c-format +msgid "E802: Invalid ID: %ld (must be greater than or equal to 1)" +msgstr "E802: ฬตธ๚คส ID: %ld (1 ฐสพๅควคสคฑค์คะคสค๊คคปค๓)" -#~ msgid "" -#~ "\n" -#~ "enter the new crypt key." -#~ msgstr "" -#~ "\n" -#~ "ฟทคทคคฐลนๆฅญกผค๒ฦฮฯคทคฦคฏคภคตคค." +#, c-format +msgid "E803: ID not found: %ld" +msgstr "E803: ID คฯคขค๊คคปค๓: %ld" -#~ msgid "" -#~ "\n" -#~ "If you wrote the text file after changing the crypt key press enter" -#~ msgstr "" -#~ "\n" -#~ "ฐลนๆฅญกผค๒สัคจคฟคขคศคหฅฦฅญฅนฅศฅีฅกฅคฅ๋ค๒สยธคทคฟพ์น็คฯ, ฅฦฅญฅนฅศฅีฅกฅคฅ๋คศ" +#, c-format +msgid "E370: Could not load library %s" +msgstr "E370: ฅ้ฅคฅึฅ้ฅ๊ %s ค๒ฅํกผฅษควคญคคปค๓ควคทคฟ" -#~ msgid "" -#~ "\n" -#~ "to use the same key for text file and swap file" -#~ msgstr "" -#~ "\n" -#~ "ฅนฅ๏ฅรฅืฅีฅกฅคฅ๋คหฦฑคธฐลนๆฅญกผค๒ปศคฆคฟคแคหenterคภคฑค๒ฒกคทคฦคฏคภคตคค." +msgid "Sorry, this command is disabled: the Perl library could not be loaded." +msgstr "" +"คณคฮฅณฅฅ๓ฅษคฯฬตธ๚ควคน, คดคแค๓คสคตคค: Perlฅ้ฅคฅึฅ้ฅ๊ค๒ฅํกผฅษควคญคคปค๓ควคทคฟ." -#~ msgid "Using crypt key from swap file for the text file.\n" -#~ msgstr "ฅนฅ๏ฅรฅืฅีฅกฅคฅ๋คซค้ผ่ฦภคทคฟฐลนๆฅญกผค๒ฅฦฅญฅนฅศฅีฅกฅคฅ๋คหปศคคคคน.\n" +msgid "E299: Perl evaluation forbidden in sandbox without the Safe module" +msgstr "" +"E299: ฅตฅ๓ฅษฅฅรฅฏฅนควคฯ Safe ฅโฅธฅๅกผฅ๋ค๒ปศอัคทคสคคPerlฅนฅฏฅ๊ฅืฅศคฯถุคธค้ค์" +"คฦคคคคน" -#~ msgid "" -#~ "\n" -#~ " [not usable with this version of Vim]" -#~ msgstr "" -#~ "\n" -#~ " [คณคฮVimฅะกผฅธฅ็ฅ๓ควคฯปศอัควคญคคปค๓]" +msgid "Edit with &multiple Vims" +msgstr "สฃฟ๔คฮVimควสิฝธคนค๋ (&M)" -#~ msgid "Tear off this menu" -#~ msgstr "คณคฮฅแฅหฅๅกผค๒ภฺค๊ผ่ค๋" +msgid "Edit with single &Vim" +msgstr "1คฤคฮVimควสิฝธคนค๋ (&V)" -#~ msgid "Select Directory dialog" -#~ msgstr "ฅวฅฃฅ์ฅฏฅศฅ๊มชย๒ฅภฅคฅขฅํฅฐ" +msgid "Diff with Vim" +msgstr "Vimควบนสฌค๒ษฝผจคนค๋" -#~ msgid "Save File dialog" -#~ msgstr "ฅีฅกฅคฅ๋สยธฅภฅคฅขฅํฅฐ" +msgid "Edit with &Vim" +msgstr "Vimควสิฝธคนค๋ (&V)" -#~ msgid "Open File dialog" -#~ msgstr "ฅีฅกฅคฅ๋ฦษนฅภฅคฅขฅํฅฐ" +#. Now concatenate +msgid "Edit with existing Vim - " +msgstr "ตฏฦฐบัคฮVimควสิฝธคนค๋ - " -#~ msgid "E338: Sorry, no file browser in console mode" -#~ msgstr "" -#~ "E338: ฅณฅ๓ฅฝกผฅ๋ฅโกผฅษควคฯฅีฅกฅคฅ๋ฅึฅ้ฅฆฅถค๒ปศคจคคปค๓, คดคแค๓คสคตคค" +msgid "Edits the selected file(s) with Vim" +msgstr "มชย๒คทคฟฅีฅกฅคฅ๋ค๒Vimควสิฝธคนค๋" -#~ msgid "Vim: preserving files...\n" -#~ msgstr "Vim: ฅีฅกฅคฅ๋ค๒สยธรๆ...\n" +msgid "Error creating process: Check if gvim is in your path!" +msgstr "ฅืฅํฅปฅนคฮบ๎ภฎคหผบวิ: gvimคฌดฤถญสัฟ๔PATHพๅคหคขค๋คซณฮวงคทคฦคฏคภคตคค!" -#~ msgid "Vim: Finished.\n" -#~ msgstr "Vim: ฝชฮปคทคคทคฟ.\n" +msgid "gvimext.dll error" +msgstr "gvimext.dll ฅจฅ้กผ" -#~ msgid "ERROR: " -#~ msgstr "ฅจฅ้กผ: " +msgid "Path length too long!" +msgstr "ฅัฅนคฌฤนฒแคฎคคน!" -#~ msgid "" -#~ "\n" -#~ "[bytes] total alloc-freed %<PRIu64>-%<PRIu64>, in use %<PRIu64>, peak use " -#~ "%<PRIu64>\n" -#~ msgstr "" -#~ "\n" -#~ "[ฅแฅโฅ๊(ฅะฅคฅศ)] มํณไล๖-ฒ๒สฮฬ %<PRIu64>-%<PRIu64>, ปศอัฮฬ %<PRIu64>, ฅิกผ" -#~ "ฅฏป %<PRIu64>\n" +msgid "--No lines in buffer--" +msgstr "--ฅะฅรฅีฅกคหนิคฌคขค๊คคปค๓--" -#~ msgid "" -#~ "[calls] total re/malloc()'s %<PRIu64>, total free()'s %<PRIu64>\n" -#~ "\n" -#~ msgstr "" -#~ "[ธฦฝะ] มํ re/malloc() ฒ๓ฟ๔ %<PRIu64>, มํ free() ฒ๓ฟ๔ %<PRIu64>\n" -#~ "\n" +#. +#. * The error messages that can be shared are included here. +#. * Excluded are errors that are only used once and debugging messages. +#. +msgid "E470: Command aborted" +msgstr "E470: ฅณฅฅ๓ฅษคฌรๆรวคตค์คคทคฟ" -#~ msgid "E340: Line is becoming too long" -#~ msgstr "E340: นิคฌฤนคฏคสค๊ฒแคฎคคทคฟ" +msgid "E471: Argument required" +msgstr "E471: ฐ๚ฟ๔คฌษฌอืควคน" -#~ msgid "E341: Internal error: lalloc(%<PRId64>, )" -#~ msgstr "E341: ฦโษ๔ฅจฅ้กผ: lalloc(%<PRId64>,)" +msgid "E10: \\ should be followed by /, ? or &" +msgstr "E10: \\ คฮธๅคฯ / คซ ? คซ & ควคสคฑค์คะคสค๊คคปค๓" -#~ msgid "E547: Illegal mouseshape" -#~ msgstr "E547: ษิภตคส 'mouseshape' ควคน" +msgid "E11: Invalid in command-line window; <CR> executes, CTRL-C quits" +msgstr "E11: ฅณฅฅ๓ฅษฅ้ฅคฅ๓ควคฯฬตธ๚ควคน; <CR>ควผยนิ, CTRL-Cควคไคแค๋" -#~ msgid "Enter encryption key: " -#~ msgstr "ฐลนๆฒฝอัคฮฅญกผค๒ฦฮฯคทคฦคฏคภคตคค: " +msgid "E12: Command not allowed from exrc/vimrc in current dir or tag search" +msgstr "" +"E12: ธฝบ฿คฮฅวฅฃฅ์ฅฏฅศฅ๊คไฅฟฅฐธกบ๗ควคฯexrc/vimrcคฮฅณฅฅ๓ฅษคฯต๖ฒฤคตค์คคปค๓" -#~ msgid "Enter same key again: " -#~ msgstr "คโคฆฐ์ลูฦฑคธฅญกผค๒ฦฮฯคทคฦคฏคภคตคค: " +msgid "E171: Missing :endif" +msgstr "E171: :endif คฌคขค๊คคปค๓" -#~ msgid "Keys don't match!" -#~ msgstr "ฅญกผคฌฐ์รืคทคคปค๓" +msgid "E600: Missing :endtry" +msgstr "E600: :endtry คฌคขค๊คคปค๓" -#~ msgid "Cannot connect to Netbeans #2" -#~ msgstr "Netbeans #2 คหภยณควคญคคปค๓" +msgid "E170: Missing :endwhile" +msgstr "E170: :endwhile คฌคขค๊คคปค๓" -#~ msgid "Cannot connect to Netbeans" -#~ msgstr "Netbeans คหภยณควคญคคปค๓" +msgid "E170: Missing :endfor" +msgstr "E170: :endfor คฌคขค๊คคปค๓" -#~ msgid "E668: Wrong access mode for NetBeans connection info file: \"%s\"" -#~ msgstr "" -#~ "E668: NetBeansคฮภยณพ๐ส๓ฅีฅกฅคฅ๋คฮฅขฅฏฅปฅนฅโกผฅษคหฬไย๊คฌคขค๊คคน: \"%s\"" +msgid "E588: :endwhile without :while" +msgstr "E588: :while คฮคสคค :endwhile คฌคขค๊คคน" -#~ msgid "read from Netbeans socket" -#~ msgstr "Netbeans คฮฅฝฅฑฅรฅศค๒ฦษนค฿" +msgid "E588: :endfor without :for" +msgstr "E588: :endfor คฮคสคค :for คฌคขค๊คคน" -#~ msgid "E658: NetBeans connection lost for buffer %<PRId64>" -#~ msgstr "E658: ฅะฅรฅีฅก %<PRId64> คฮ NetBeans ภยณคฌผบค๏ค์คคทคฟ" +msgid "E13: File exists (add ! to override)" +msgstr "E13: ฅีฅกฅคฅ๋คฌยธบ฿คทคคน (! ค๒ฤษฒรควพๅฝ๑)" -#~ msgid "E838: netbeans is not supported with this GUI" -#~ msgstr "E838: NetBeansคฯคณคฮGUIคหคฯยะฑคทคฦคคคคปค๓" +msgid "E472: Command failed" +msgstr "E472: ฅณฅฅ๓ฅษคฌผบวิคทคคทคฟ" -#~ msgid "E511: netbeans already connected" -#~ msgstr "E511: NetBeansคฯด๛คหภยณคทคฦคคคคน" +#, c-format +msgid "E234: Unknown fontset: %s" +msgstr "E234: ฬครฮคฮฅีฅฉฅ๓ฅศฅปฅรฅศ: %s" -#~ msgid "E505: %s is read-only (add ! to override)" -#~ msgstr "E505: %s คฯฦษนภ์อัควคน (ถฏภฉฝ๑นคหคฯ ! ค๒ฤษฒร)" +#, c-format +msgid "E235: Unknown font: %s" +msgstr "E235: ฬครฮคฮฅีฅฉฅ๓ฅศ: %s" -#~ msgid "E775: Eval feature not available" -#~ msgstr "E775: ผฐษพฒมตกวฝคฌฬตธ๚คหคสครคฦคคคคน" +#, c-format +msgid "E236: Font \"%s\" is not fixed-width" +msgstr "E236: ฅีฅฉฅ๓ฅศ \"%s\" คฯธวฤ๊ษควคฯคขค๊คคปค๓" -#~ msgid "freeing %<PRId64> lines" -#~ msgstr "%<PRId64> นิค๒ฒ๒สรๆ" +msgid "E473: Internal error" +msgstr "E473: ฦโษ๔ฅจฅ้กผควคน" -#~ msgid "E530: Cannot change term in GUI" -#~ msgstr "E530: GUIควคฯ 'term' ค๒สันนควคญคคปค๓" +msgid "Interrupted" +msgstr "ณไนคค์คคทคฟ" -#~ msgid "E531: Use \":gui\" to start the GUI" -#~ msgstr "E531: GUIค๒ฅนฅฟกผฅศคนค๋คหคฯ \":gui\" ค๒ปศอัคทคฦคฏคภคตคค" +msgid "E14: Invalid address" +msgstr "E14: ฬตธ๚คสฅขฅษฅ์ฅนควคน" -#~ msgid "E617: Cannot be changed in the GTK+ 2 GUI" -#~ msgstr "E617: GTK+2 GUIควคฯสันนควคญคคปค๓" +msgid "E474: Invalid argument" +msgstr "E474: ฬตธ๚คสฐ๚ฟ๔ควคน" -#~ msgid "E596: Invalid font(s)" -#~ msgstr "E596: ฬตธ๚คสฅีฅฉฅ๓ฅศควคน" +#, c-format +msgid "E475: Invalid argument: %s" +msgstr "E475: ฬตธ๚คสฐ๚ฟ๔ควคน: %s" -#~ msgid "E597: can't select fontset" -#~ msgstr "E597: ฅีฅฉฅ๓ฅศฅปฅรฅศค๒มชย๒ควคญคคปค๓" +#, c-format +msgid "E15: Invalid expression: %s" +msgstr "E15: ฬตธ๚คสผฐควคน: %s" -#~ msgid "E598: Invalid fontset" -#~ msgstr "E598: ฬตธ๚คสฅีฅฉฅ๓ฅศฅปฅรฅศควคน" +msgid "E16: Invalid range" +msgstr "E16: ฬตธ๚คสศฯฐฯควคน" -#~ msgid "E533: can't select wide font" -#~ msgstr "E533: ฅ๏ฅคฅษฅีฅฉฅ๓ฅศค๒มชย๒ควคญคคปค๓" +msgid "E476: Invalid command" +msgstr "E476: ฬตธ๚คสฅณฅฅ๓ฅษควคน" -#~ msgid "E534: Invalid wide font" -#~ msgstr "E534: ฬตธ๚คสฅ๏ฅคฅษฅีฅฉฅ๓ฅศควคน" +#, c-format +msgid "E17: \"%s\" is a directory" +msgstr "E17: \"%s\" คฯฅวฅฃฅ์ฅฏฅศฅ๊ควคน" -#~ msgid "E538: No mouse support" -#~ msgstr "E538: ฅฅฆฅนคฯฅตฅกผฅศคตค์คคปค๓" +#, c-format +msgid "E364: Library call failed for \"%s()\"" +msgstr "E364: \"%s\"() คฮฅ้ฅคฅึฅ้ฅ๊ธฦฝะคหผบวิคทคคทคฟ" -#~ msgid "cannot open " -#~ msgstr "ณซคฑคคปค๓ " +#, c-format +msgid "E448: Could not load library function %s" +msgstr "E448: ฅ้ฅคฅึฅ้ฅ๊คฮดุฟ๔ %s ค๒ฅํกผฅษควคญคคปค๓ควคทคฟ" -#~ msgid "VIM: Can't open window!\n" -#~ msgstr "VIM: ฅฆฅฃฅ๓ฅษฅฆค๒ณซคฑคคปค๓!\n" +msgid "E19: Mark has invalid line number" +msgstr "E19: ฅกผฅฏคหฬตธ๚คสนิศึนๆคฌปุฤ๊คตค์คฦคคคคทคฟ" -#~ msgid "Need Amigados version 2.04 or later\n" -#~ msgstr "Amigadosคฮฅะกผฅธฅ็ฅ๓ 2.04คซคฝค์ฐสน฿คฌษฌอืควคน\n" +msgid "E20: Mark not set" +msgstr "E20: ฅกผฅฏคฯภ฿ฤ๊คตค์คฦคคคคปค๓" -#~ msgid "Need %s version %<PRId64>\n" -#~ msgstr "%s คฮฅะกผฅธฅ็ฅ๓ %<PRId64> คฌษฌอืควคน\n" +msgid "E21: Cannot make changes, 'modifiable' is off" +msgstr "E21: 'modifiable' คฌฅชฅีคสคฮคว, สันนควคญคคปค๓" -#~ msgid "Cannot open NIL:\n" -#~ msgstr "NILค๒ณซคฑคคปค๓:\n" +msgid "E22: Scripts nested too deep" +msgstr "E22: ฅนฅฏฅ๊ฅืฅศคฮฦค์ปาคฌฟผฒแคฎคคน" -#~ msgid "Cannot create " -#~ msgstr "บ๎ภฎควคญคคปค๓ " +msgid "E23: No alternate file" +msgstr "E23: ษ๛ฅีฅกฅคฅ๋คฯคขค๊คคปค๓" -#~ msgid "Vim exiting with %d\n" -#~ msgstr "Vimคฯ %d ควฝชฮปคทคคน\n" +msgid "E24: No such abbreviation" +msgstr "E24: คฝคฮค่คฆคสรปฝฬฦฮฯคฯคขค๊คคปค๓" -#~ msgid "cannot change console mode ?!\n" -#~ msgstr "ฅณฅ๓ฅฝกผฅ๋ฅโกผฅษค๒สันนควคญคคปค๓?!\n" +msgid "E477: No ! allowed" +msgstr "E477: ! คฯต๖ฒฤคตค์คฦคคคคปค๓" -#~ msgid "mch_get_shellsize: not a console??\n" -#~ msgstr "mch_get_shellsize: ฅณฅ๓ฅฝกผฅ๋ควคฯคสคค??\n" +msgid "E25: GUI cannot be used: Not enabled at compile time" +msgstr "E25: GUIคฯปศอัษิฒฤวฝควคน: ฅณฅ๓ฅัฅคฅ๋ปคหฬตธ๚คหคตค์คฦคคคคน" -#~ msgid "E360: Cannot execute shell with -f option" -#~ msgstr "E360: -f ฅชฅืฅทฅ็ฅ๓ควฅทฅงฅ๋ค๒ผยนิควคญคคปค๓" +msgid "E26: Hebrew cannot be used: Not enabled at compile time\n" +msgstr "E26: ฅุฅึฅ้ฅคธ์คฯปศอัษิฒฤวฝควคน: ฅณฅ๓ฅัฅคฅ๋ปคหฬตธ๚คหคตค์คฦคคคคน\n" -#~ msgid "Cannot execute " -#~ msgstr "ผยนิควคญคคปค๓ " +msgid "E27: Farsi cannot be used: Not enabled at compile time\n" +msgstr "E27: ฅฺฅ๋ฅทฅขธ์คฯปศอัษิฒฤวฝควคน: ฅณฅ๓ฅัฅคฅ๋ปคหฬตธ๚คหคตค์คฦคคคคน\n" -#~ msgid "shell " -#~ msgstr "ฅทฅงฅ๋ " +msgid "E800: Arabic cannot be used: Not enabled at compile time\n" +msgstr "E800: ฅขฅ้ฅำฅขธ์คฯปศอัษิฒฤวฝควคน: ฅณฅ๓ฅัฅคฅ๋ปคหฬตธ๚คหคตค์คฦคคคคน\n" -#~ msgid " returned\n" -#~ msgstr " ฬแค๊คคทคฟ\n" +#, c-format +msgid "E28: No such highlight group name: %s" +msgstr "E28: คฝคฮค่คฆคสฬพคฮฅฯฅคฅ้ฅคฅศฅฐฅ๋กผฅืคฯคขค๊คคปค๓: %s" -#~ msgid "ANCHOR_BUF_SIZE too small." -#~ msgstr "ANCHOR_BUF_SIZE คฌพฎคตฒแคฎคคน." +msgid "E29: No inserted text yet" +msgstr "E29: คคภฅฦฅญฅนฅศคฌมฦคตค์คฦคคคคปค๓" -#~ msgid "I/O ERROR" -#~ msgstr "ฦฝะฮฯฅจฅ้กผ" +msgid "E30: No previous command line" +msgstr "E30: ฐสมฐคหฅณฅฅ๓ฅษนิคฌคขค๊คคปค๓" -#~ msgid "Message" -#~ msgstr "ฅแฅรฅปกผฅธ" +msgid "E31: No such mapping" +msgstr "E31: คฝคฮค่คฆคสฅฅรฅิฅ๓ฅฐคฯคขค๊คคปค๓" -#~ msgid "'columns' is not 80, cannot execute external commands" -#~ msgstr "'columns' คฌ80ควคฯคสคคคฟคแ, ณฐษ๔ฅณฅฅ๓ฅษค๒ผยนิควคญคคปค๓" +msgid "E479: No match" +msgstr "E479: ณบล๖คฯคขค๊คคปค๓" -#~ msgid "E237: Printer selection failed" -#~ msgstr "E237: ฅืฅ๊ฅ๓ฅฟคฮมชย๒คหผบวิคทคคทคฟ" +#, c-format +msgid "E480: No match: %s" +msgstr "E480: ณบล๖คฯคขค๊คคปค๓: %s" -#~ msgid "to %s on %s" -#~ msgstr "%s คุ (%s พๅคฮ)" +msgid "E32: No file name" +msgstr "E32: ฅีฅกฅคฅ๋ฬพคฌคขค๊คคปค๓" -#~ msgid "E613: Unknown printer font: %s" -#~ msgstr "E613: ฬครฮคฮฅืฅ๊ฅ๓ฅฟฅชฅืฅทฅ็ฅ๓ควคน: %s" +msgid "E33: No previous substitute regular expression" +msgstr "E33: ภตตฌษฝธฝรึดนคฌคคภผยนิคตค์คฦคคคคปค๓" -#~ msgid "E238: Print error: %s" -#~ msgstr "E238: ฐ๕บฅจฅ้กผ: %s" +msgid "E34: No previous command" +msgstr "E34: ฅณฅฅ๓ฅษคฌคคภผยนิคตค์คฦคคคคปค๓" -#~ msgid "Printing '%s'" -#~ msgstr "ฐ๕บคทคฦคคคคน: '%s'" +msgid "E35: No previous regular expression" +msgstr "E35: ภตตฌษฝธฝคฌคคภผยนิคตค์คฦคคคคปค๓" -#~ msgid "E244: Illegal charset name \"%s\" in font name \"%s\"" -#~ msgstr "E244: สธป๚ฅปฅรฅศฬพ \"%s\" คฯษิภตควคน (ฅีฅฉฅ๓ฅศฬพ \"%s\")" +msgid "E481: No range allowed" +msgstr "E481: ศฯฐฯปุฤ๊คฯต๖ฒฤคตค์คฦคคคคปค๓" -#~ msgid "E245: Illegal char '%c' in font name \"%s\"" -#~ msgstr "E245: '%c' คฯษิภตคสสธป๚ควคน (ฅีฅฉฅ๓ฅศฬพ \"%s\")" +msgid "E36: Not enough room" +msgstr "E36: ฅฆฅฃฅ๓ฅษฅฆคหฝฝสฌคสนโคตคโคทคฏคฯษคฌคขค๊คคปค๓" -#~ msgid "Vim: Double signal, exiting\n" -#~ msgstr "Vim: 2ฝลคฮฅทฅฐฅสฅ๋คฮคฟคแ, ฝชฮปคทคคน\n" +#, c-format +msgid "E247: no registered server named \"%s\"" +msgstr "E247: %s คศคคคฆฬพมฐคฮละฯฟคตค์คฟฅตกผฅะกผคฯคขค๊คคปค๓" -#~ msgid "Vim: Caught deadly signal %s\n" -#~ msgstr "Vim: รืฬฟลชฅทฅฐฅสฅ๋ %s ค๒ธกรฮคทคคทคฟ\n" +#, c-format +msgid "E482: Can't create file %s" +msgstr "E482: ฅีฅกฅคฅ๋ %s ค๒บ๎ภฎควคญคคปค๓" -#~ msgid "Vim: Caught deadly signal\n" -#~ msgstr "Vim: รืฬฟลชฅทฅฐฅสฅ๋ค๒ธกรฮคทคคทคฟ\n" +msgid "E483: Can't get temp file name" +msgstr "E483: ฐ์ปฅีฅกฅคฅ๋คฮฬพมฐค๒ผ่ฦภควคญคคปค๓" -#~ msgid "Opening the X display took %<PRId64> msec" -#~ msgstr "Xฅตกผฅะคุคฮภยณคห %<PRId64> ฅ฿ฅ๊ษรคซคซค๊คคทคฟ" +#, c-format +msgid "E484: Can't open file %s" +msgstr "E484: ฅีฅกฅคฅ๋ \"%s\" ค๒ณซคฑคคปค๓" -#~ msgid "" -#~ "\n" -#~ "Vim: Got X error\n" -#~ msgstr "" -#~ "\n" -#~ "Vim: X คฮฅจฅ้กผค๒ธกฝะคทคคทคฟr\n" +#, c-format +msgid "E485: Can't read file %s" +msgstr "E485: ฅีฅกฅคฅ๋ %s ค๒ฦษนคแคคปค๓" -#~ msgid "Testing the X display failed" -#~ msgstr "X display คฮฅมฅงฅรฅฏคหผบวิคทคคทคฟ" +msgid "E37: No write since last change (add ! to override)" +msgstr "E37: บวธๅคฮสันนคฌสยธคตค์คฦคคคคปค๓ (! ค๒ฤษฒรควสันนค๒วหด)" -#~ msgid "Opening the X display timed out" -#~ msgstr "X display คฮ open คฌฅฟฅคฅเฅขฅฆฅศคทคคทคฟ" +msgid "E37: No write since last change" +msgstr "E37: บวธๅคฮสันนคฌสยธคตค์คฦคคคคปค๓" -#~ msgid "" -#~ "\n" -#~ "Cannot execute shell sh\n" -#~ msgstr "" -#~ "\n" -#~ "sh ฅทฅงฅ๋ค๒ผยนิควคญคคปค๓\n" +msgid "E38: Null argument" +msgstr "E38: ฐ๚ฟ๔คฌถ๕ควคน" -#~ msgid "" -#~ "\n" -#~ "Cannot create pipes\n" -#~ msgstr "" -#~ "\n" -#~ "ฅัฅคฅืค๒บ๎ภฎควคญคคปค๓\n" +msgid "E39: Number expected" +msgstr "E39: ฟ๔รอคฌอืตแคตค์คฦคคคคน" -#~ msgid "" -#~ "\n" -#~ "Cannot fork\n" -#~ msgstr "" -#~ "\n" -#~ "fork ควคญคคปค๓\n" +#, c-format +msgid "E40: Can't open errorfile %s" +msgstr "E40: ฅจฅ้กผฅีฅกฅคฅ๋ %s ค๒ณซคฑคคปค๓" -#~ msgid "" -#~ "\n" -#~ "Command terminated\n" -#~ msgstr "" -#~ "\n" -#~ "ฅณฅฅ๓ฅษค๒รๆรวคทคคทคฟ\n" +msgid "E233: cannot open display" +msgstr "E233: ฅวฅฃฅนฅืฅ์ฅคค๒ณซคฑคคปค๓" -#~ msgid "XSMP lost ICE connection" -#~ msgstr "XSMP คฌICEภยณค๒ผบคคคคทคฟ" +msgid "E41: Out of memory!" +msgstr "E41: ฅแฅโฅ๊คฌฟิคญฒฬคฦคคทคฟ!" -#~ msgid "Opening the X display failed" -#~ msgstr "X display คฮ open คหผบวิคทคคทคฟ" +msgid "Pattern not found" +msgstr "ฅัฅฟกผฅ๓คฯธซคฤคซค๊คคปค๓ควคทคฟ" -#~ msgid "XSMP handling save-yourself request" -#~ msgstr "XSMP คฌsave-yourselfอืตแค๒ฝ่อคทคฦคคคคน" +#, c-format +msgid "E486: Pattern not found: %s" +msgstr "E486: ฅัฅฟกผฅ๓คฯธซคฤคซค๊คคปค๓ควคทคฟ: %s" -#~ msgid "XSMP opening connection" -#~ msgstr "XSMP คฌภยณค๒ณซปฯคทคฦคคคคน" +msgid "E487: Argument must be positive" +msgstr "E487: ฐ๚ฟ๔คฯภตคฮรอควคสคฑค์คะคสค๊คคปค๓" -#~ msgid "XSMP ICE connection watch failed" -#~ msgstr "XSMP ICEภยณคฌผบวิคทคฟค่คฆควคน" +msgid "E459: Cannot go back to previous directory" +msgstr "E459: มฐคฮฅวฅฃฅ์ฅฏฅศฅ๊คหฬแค์คคปค๓" -#~ msgid "XSMP SmcOpenConnection failed: %s" -#~ msgstr "XSMP SmcOpenConnectionคฌผบวิคทคคทคฟ: %s" +msgid "E42: No Errors" +msgstr "E42: ฅจฅ้กผคฯคขค๊คคปค๓" -#~ msgid "At line" -#~ msgstr "นิ" +msgid "E776: No location list" +msgstr "E776: ฅํฅฑกผฅทฅ็ฅ๓ฅ๊ฅนฅศคฯคขค๊คคปค๓" -#~ msgid "Could not load vim32.dll!" -#~ msgstr "vim32.dll ค๒ฅํกผฅษควคญคคปค๓ควคทคฟ" +msgid "E43: Damaged match string" +msgstr "E43: ณบล๖สธป๚ฮ๓คฌวหยปคทคฦคคคคน" -#~ msgid "VIM Error" -#~ msgstr "VIMฅจฅ้กผ" +msgid "E44: Corrupted regexp program" +msgstr "E44: ษิภตคสภตตฌษฝธฝฅืฅํฅฐฅ้ฅเควคน" -#~ msgid "Could not fix up function pointers to the DLL!" -#~ msgstr "DLLคซค้ดุฟ๔ฅฅคฅ๓ฅฟค๒ผ่ฦภควคญคคปค๓ควคทคฟ" +msgid "E45: 'readonly' option is set (add ! to override)" +msgstr "E45: 'readonly' ฅชฅืฅทฅ็ฅ๓คฌภ฿ฤ๊คตค์คฦคคคคน (! ค๒ฤษฒรควพๅฝ๑คญ)" -#~ msgid "shell returned %d" -#~ msgstr "ฅทฅงฅ๋คฌฅณกผฅษ %d ควฝชฮปคทคคทคฟ" +#, c-format +msgid "E46: Cannot change read-only variable \"%s\"" +msgstr "E46: ฦษผ่ภ์อัสัฟ๔ \"%s\" คหคฯรอค๒ภ฿ฤ๊ควคญคคปค๓" -#~ msgid "Vim: Caught %s event\n" -#~ msgstr "Vim: ฅคฅูฅ๓ฅศ %s ค๒ธกรฮ\n" +#, c-format +msgid "E794: Cannot set variable in the sandbox: \"%s\"" +msgstr "E794: ฅตฅ๓ฅษฅฅรฅฏฅนควคฯสัฟ๔ \"%s\" คหรอค๒ภ฿ฤ๊ควคญคคปค๓" -#~ msgid "close" -#~ msgstr "สฤคธค๋" +msgid "E713: Cannot use empty key for Dictionary" +msgstr "E713: ผญฝ๑ทฟคหถ๕คฮฅญกผค๒ปศคฆคณคศคฯควคญคคปค๓" -#~ msgid "logoff" -#~ msgstr "ฅํฅฐฅชฅี" +msgid "E715: Dictionary required" +msgstr "E715: ผญฝ๑ทฟคฌษฌอืควคน" -#~ msgid "shutdown" -#~ msgstr "ฅทฅใฅรฅศฅภฅฆฅ๓" +#, c-format +msgid "E684: list index out of range: %ld" +msgstr "E684: ฅ๊ฅนฅศคฮฅคฅ๓ฅวฅรฅฏฅนคฌศฯฐฯณฐควคน: %ld" -#~ msgid "E371: Command not found" -#~ msgstr "E371: ฅณฅฅ๓ฅษคฌคขค๊คคปค๓" - -#~ msgid "" -#~ "VIMRUN.EXE not found in your $PATH.\n" -#~ "External commands will not pause after completion.\n" -#~ "See :help win32-vimrun for more information." -#~ msgstr "" -#~ "VIMRUN.EXEคฌ $PATH คฮรๆคหธซคฤคซค๊คคปค๓.\n" -#~ "ณฐษ๔ฅณฅฅ๓ฅษคฮฝชฮปธๅคหฐ์ปฤไป฿ค๒คทคคปค๓.\n" -#~ "พบูคฯ :help win32-vimrun ค๒ปฒพศคทคฦคฏคภคตคค." - -#~ msgid "Vim Warning" -#~ msgstr "Vimคฮทูน๐" - -#~ msgid "Error file" -#~ msgstr "ฅจฅ้กผฅีฅกฅคฅ๋" - -#~ msgid "E868: Error building NFA with equivalence class!" -#~ msgstr "E868: ล๙ฒมฅฏฅ้ฅนค๒ดคเNFAนฝรคหผบวิคทคคทคฟ!" - -#~ msgid "E878: (NFA) Could not allocate memory for branch traversal!" -#~ msgstr "E878: (NFA) ธฝบ฿ฒฃรวรๆคฮฅึฅ้ฅ๓ฅมคหฝฝสฌคสฅแฅโฅ๊ค๒ณไค๊ล๖คฦค้ค์คคปค๓!" - -#~ msgid "Warning: Cannot find word list \"%s_%s.spl\" or \"%s_ascii.spl\"" -#~ msgstr "" -#~ "ทูน๐: รฑธ์ฅ๊ฅนฅศ \"%s_%s.spl\" คชค่คำ \"%s_ascii.spl\" คฯธซคฤคซค๊คคปค๓" - -#~ msgid "Conversion in %s not supported" -#~ msgstr "%s ฦโคฮสัดนคฯฅตฅกผฅศคตค์คฦคคคคปค๓" - -#~ msgid "E845: Insufficient memory, word list will be incomplete" -#~ msgstr "E845: ฅแฅโฅ๊คฌยญค๊คสคคคฮควกขรฑธ์ฅ๊ฅนฅศคฯษิดฐมดควคน" - -#~ msgid "E430: Tag file path truncated for %s\n" -#~ msgstr "E430: ฅฟฅฐฅีฅกฅคฅ๋คฮฅัฅนคฌ %s คหภฺค๊ผฮคฦค้ค์คคทคฟ\n" - -#~ msgid "new shell started\n" -#~ msgstr "ฟทคทคคฅทฅงฅ๋ค๒ตฏฦฐคทคคน\n" - -#~ msgid "Used CUT_BUFFER0 instead of empty selection" -#~ msgstr "ถ๕คฮมชย๒ฮฮฐ่คฮคซค๏ค๊คหCUT_BUFFER0คฌปศอัคตค์คคทคฟ" - -#~ msgid "No undo possible; continue anyway" -#~ msgstr "ฒฤวฝคสฅขฅ๓ฅษฅฅคฯคขค๊คคปค๓: คศค๊คขคจคบยณคฑคคน" - -#~ msgid "E832: Non-encrypted file has encrypted undo file: %s" -#~ msgstr "" -#~ "E832: ศ๓ฐลนๆฒฝฅีฅกฅคฅ๋คฌฐลนๆฒฝคตค์คฟฅขฅ๓ฅษฅฅฅีฅกฅคฅ๋ค๒ปศครคฦคคน: %s" - -#~ msgid "E826: Undo file decryption failed: %s" -#~ msgstr "E826: ฐลนๆฒฝคตค์คฟฅขฅ๓ฅษฅฅฅีฅกฅคฅ๋คฮฒ๒ฦษคหผบวิคทคคทคฟ: %s" - -#~ msgid "E827: Undo file is encrypted: %s" -#~ msgstr "E827: ฅขฅ๓ฅษฅฅฅีฅกฅคฅ๋คฌฐลนๆฒฝคตค์คฦคคคคน: %s" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 16/32-bit GUI version" -#~ msgstr "" -#~ "\n" -#~ "MS-Windows 16/32 ฅำฅรฅศ GUI ศว" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 64-bit GUI version" -#~ msgstr "" -#~ "\n" -#~ "MS-Windows 64 ฅำฅรฅศ GUI ศว" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 32-bit GUI version" -#~ msgstr "" -#~ "\n" -#~ "MS-Windows 32 ฅำฅรฅศ GUI ศว" - -#~ msgid " in Win32s mode" -#~ msgstr " in Win32s ฅโกผฅษ" - -#~ msgid " with OLE support" -#~ msgstr " with OLE ฅตฅกผฅศ" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 64-bit console version" -#~ msgstr "" -#~ "\n" -#~ "MS-Windows 64 ฅำฅรฅศ ฅณฅ๓ฅฝกผฅ๋ ศว" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 32-bit console version" -#~ msgstr "" -#~ "\n" -#~ "MS-Windows 32 ฅำฅรฅศ ฅณฅ๓ฅฝกผฅ๋ ศว" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 16-bit version" -#~ msgstr "" -#~ "\n" -#~ "MS-Windows 16 ฅำฅรฅศ ศว" - -#~ msgid "" -#~ "\n" -#~ "32-bit MS-DOS version" -#~ msgstr "" -#~ "\n" -#~ "32 ฅำฅรฅศ MS-DOS ศว" - -#~ msgid "" -#~ "\n" -#~ "16-bit MS-DOS version" -#~ msgstr "" -#~ "\n" -#~ "16 ฅำฅรฅศ MS-DOS ศว" - -#~ msgid "" -#~ "\n" -#~ "MacOS X (unix) version" -#~ msgstr "" -#~ "\n" -#~ "MacOS X (unix) ศว" - -#~ msgid "" -#~ "\n" -#~ "MacOS X version" -#~ msgstr "" -#~ "\n" -#~ "MacOS X ศว" - -#~ msgid "" -#~ "\n" -#~ "MacOS version" -#~ msgstr "" -#~ "\n" -#~ "MacOS ศว" - -#~ msgid "" -#~ "\n" -#~ "OpenVMS version" -#~ msgstr "" -#~ "\n" -#~ "OpenVMS ศว" - -#~ msgid "" -#~ "\n" -#~ "Big version " -#~ msgstr "" -#~ "\n" -#~ "Big ศว " - -#~ msgid "" -#~ "\n" -#~ "Normal version " -#~ msgstr "" -#~ "\n" -#~ "ฤฬพ๏ ศว " - -#~ msgid "" -#~ "\n" -#~ "Small version " -#~ msgstr "" -#~ "\n" -#~ "Small ศว " - -#~ msgid "" -#~ "\n" -#~ "Tiny version " -#~ msgstr "" -#~ "\n" -#~ "Tiny ศว " - -#~ msgid "with GTK2-GNOME GUI." -#~ msgstr "with GTK2-GNOME GUI." +#, c-format +msgid "E118: Too many arguments for function: %s" +msgstr "E118: ดุฟ๔คฮฐ๚ฟ๔คฌยฟฒแคฎคคน: %s" -#~ msgid "with GTK2 GUI." -#~ msgstr "with GTK2 GUI." +#, c-format +msgid "E716: Key not present in Dictionary: %s" +msgstr "E716: ผญฝ๑ทฟคหฅญกผคฌยธบ฿คทคคปค๓: %s" -#~ msgid "with X11-Motif GUI." -#~ msgstr "with X11-Motif GUI." +msgid "E714: List required" +msgstr "E714: ฅ๊ฅนฅศทฟคฌษฌอืควคน" -#~ msgid "with X11-neXtaw GUI." -#~ msgstr "with X11-neXtaw GUI." +#, c-format +msgid "E712: Argument of %s must be a List or Dictionary" +msgstr "E712: %s คฮฐ๚ฟ๔คฯฅ๊ฅนฅศทฟคคฟคฯผญฝ๑ทฟควคสคฑค์คะคสค๊คคปค๓" -#~ msgid "with X11-Athena GUI." -#~ msgstr "with X11-Athena GUI." +msgid "E47: Error while reading errorfile" +msgstr "E47: ฅจฅ้กผฅีฅกฅคฅ๋คฮฦษนรๆคหฅจฅ้กผคฌศฏภธคทคคทคฟ" -#~ msgid "with Photon GUI." -#~ msgstr "with Photon GUI." +msgid "E48: Not allowed in sandbox" +msgstr "E48: ฅตฅ๓ฅษฅฅรฅฏฅนควคฯต๖คตค์คคปค๓" -#~ msgid "with GUI." -#~ msgstr "with GUI." +msgid "E523: Not allowed here" +msgstr "E523: คณคณควคฯต๖ฒฤคตค์คคปค๓" -#~ msgid "with Carbon GUI." -#~ msgstr "with Carbon GUI." +msgid "E359: Screen mode setting not supported" +msgstr "E359: ฅนฅฏฅ๊กผฅ๓ฅโกผฅษคฮภ฿ฤ๊คหคฯยะฑคทคฦคคคคปค๓" -#~ msgid "with Cocoa GUI." -#~ msgstr "with Cocoa GUI." +msgid "E49: Invalid scroll size" +msgstr "E49: ฬตธ๚คสฅนฅฏฅํกผฅ๋ฮฬควคน" -#~ msgid "with (classic) GUI." -#~ msgstr "with (ฅฏฅ้ฅทฅรฅฏ) GUI." +msgid "E91: 'shell' option is empty" +msgstr "E91: 'shell' ฅชฅืฅทฅ็ฅ๓คฌถ๕ควคน" -#~ msgid " system gvimrc file: \"" -#~ msgstr " ฅทฅนฅฦฅเ gvimrc: \"" +msgid "E255: Couldn't read in sign data!" +msgstr "E255: sign คฮฅวกผฅฟค๒ฦษนคแคคปค๓ควคทคฟ" -#~ msgid " user gvimrc file: \"" -#~ msgstr " ฅๆกผฅถ gvimrc: \"" +msgid "E72: Close error on swap file" +msgstr "E72: ฅนฅ๏ฅรฅืฅีฅกฅคฅ๋คฮฅฏฅํกผฅบปฅจฅ้กผควคน" -#~ msgid "2nd user gvimrc file: \"" -#~ msgstr " ย่2ฅๆกผฅถ gvimrc: \"" +msgid "E73: tag stack empty" +msgstr "E73: ฅฟฅฐฅนฅฟฅรฅฏคฌถ๕ควคน" -#~ msgid "3rd user gvimrc file: \"" -#~ msgstr " ย่3ฅๆกผฅถ gvimrc: \"" +msgid "E74: Command too complex" +msgstr "E74: ฅณฅฅ๓ฅษคฌสฃปจฒแคฎคคน" -#~ msgid " system menu file: \"" -#~ msgstr " ฅทฅนฅฦฅเฅแฅหฅๅกผ: \"" +msgid "E75: Name too long" +msgstr "E75: ฬพมฐคฌฤนฒแคฎคคน" -#~ msgid "Compiler: " -#~ msgstr "ฅณฅ๓ฅัฅคฅ้: " +msgid "E76: Too many [" +msgstr "E76: [ คฌยฟฒแคฎคคน" -#~ msgid "menu Help->Orphans for information " -#~ msgstr "พบูคฯฅแฅหฅๅกผคฮ ฅุฅ๋ฅืขชธษป๙ ค๒ปฒพศคทคฦฒผคตคค " +msgid "E77: Too many file names" +msgstr "E77: ฅีฅกฅคฅ๋ฬพคฌยฟฒแคฎคคน" -#~ msgid "Running modeless, typed text is inserted" -#~ msgstr "ฅโกผฅษฬตควผยนิรๆ, ฅฟฅคฅืคทคฟสธป๚คฌมฦคตค์คคน" +msgid "E488: Trailing characters" +msgstr "E488: อพสฌคสสธป๚คฌธๅคํคหคขค๊คคน" -#~ msgid "menu Edit->Global Settings->Toggle Insert Mode " -#~ msgstr "ฅแฅหฅๅกผคฮ สิฝธขชมดยฮภ฿ฤ๊ขชมฦ(ฝ้ฟดผิ)ฅโกผฅษภฺยุ " +msgid "E78: Unknown mark" +msgstr "E78: ฬครฮคฮฅกผฅฏ" -#~ msgid " for two modes " -#~ msgstr " ควฅโกผฅษอญคห " +msgid "E79: Cannot expand wildcards" +msgstr "E79: ฅ๏ฅคฅ๋ฅษฅซกผฅษค๒ลธณซควคญคคปค๓" -#~ msgid "menu Edit->Global Settings->Toggle Vi Compatible" -#~ msgstr "ฅแฅหฅๅกผคฮ สิฝธขชมดยฮภ฿ฤ๊ขชViธ฿ดนฅโกผฅษภฺยุ " +msgid "E591: 'winheight' cannot be smaller than 'winminheight'" +msgstr "E591: 'winheight' คฯ 'winminheight' ค่ค๊พฎคตคฏควคญคคปค๓" -#~ msgid " for Vim defaults " -#~ msgstr " ควVimคศคทคฦฦฐบ๎ " +msgid "E592: 'winwidth' cannot be smaller than 'winminwidth'" +msgstr "E592: 'winwidth' คฯ 'winminwidth' ค่ค๊พฎคตคฏควคญคคปค๓" -#~ msgid "WARNING: Windows 95/98/ME detected" -#~ msgstr " ทูน๐: Windows 95/98/Me ค๒ธกฝะ " +msgid "E80: Error while writing" +msgstr "E80: ฝ๑นค฿รๆคฮฅจฅ้กผ" -#~ msgid "type :help windows95<Enter> for info on this" -#~ msgstr " พบูคสพ๐ส๓คฯ :help windows95<Enter> " +msgid "Zero count" +msgstr "ฅผฅํฅซฅฆฅ๓ฅศ" -#~ msgid "Edit with &multiple Vims" -#~ msgstr "สฃฟ๔คฮVimควสิฝธคนค๋ (&M)" +msgid "E81: Using <SID> not in a script context" +msgstr "E81: ฅนฅฏฅ๊ฅืฅศฐสณฐคว<SID>คฌปศค๏ค์คคทคฟ" -#~ msgid "Edit with single &Vim" -#~ msgstr "1คฤคฮVimควสิฝธคนค๋ (&V)" +msgid "E449: Invalid expression received" +msgstr "E449: ฬตธ๚คสผฐค๒ผ๕คฑผ่ค๊คคทคฟ" -#~ msgid "Diff with Vim" -#~ msgstr "Vimควบนสฌค๒ษฝผจคนค๋" +msgid "E463: Region is guarded, cannot modify" +msgstr "E463: ฮฮฐ่คฌสธ๎คตค์คฦคคค๋คฮคว, สันนควคญคคปค๓" -#~ msgid "Edit with &Vim" -#~ msgstr "Vimควสิฝธคนค๋ (&V)" +msgid "E744: NetBeans does not allow changes in read-only files" +msgstr "E744: NetBeans คฯฦษนภ์อัฅีฅกฅคฅ๋ค๒สันนคนค๋คณคศค๒ต๖คทคคปค๓" -#~ msgid "Edit with existing Vim - " -#~ msgstr "ตฏฦฐบัคฮVimควสิฝธคนค๋ - " +#, c-format +msgid "E685: Internal error: %s" +msgstr "E685: ฦโษ๔ฅจฅ้กผควคน: %s" -#~ msgid "Edits the selected file(s) with Vim" -#~ msgstr "มชย๒คทคฟฅีฅกฅคฅ๋ค๒Vimควสิฝธคนค๋" +msgid "E363: pattern uses more memory than 'maxmempattern'" +msgstr "E363: ฅัฅฟกผฅ๓คฌ 'maxmempattern' ฐสพๅคฮฅแฅโฅ๊ค๒ปศอัคทคคน" -#~ msgid "Error creating process: Check if gvim is in your path!" -#~ msgstr "ฅืฅํฅปฅนคฮบ๎ภฎคหผบวิ: gvimคฌดฤถญสัฟ๔PATHพๅคหคขค๋คซณฮวงคทคฦคฏคภคตคค!" +msgid "E749: empty buffer" +msgstr "E749: ฅะฅรฅีฅกคฌถ๕ควคน" -#~ msgid "gvimext.dll error" -#~ msgstr "gvimext.dll ฅจฅ้กผ" +#, c-format +msgid "E86: Buffer %ld does not exist" +msgstr "E86: ฅะฅรฅีฅก %ld คฯคขค๊คคปค๓" -#~ msgid "Path length too long!" -#~ msgstr "ฅัฅนคฌฤนคนคฎคคน!" +msgid "E682: Invalid search pattern or delimiter" +msgstr "E682: ธกบ๗ฅัฅฟกผฅ๓คซถ่ภฺค๊ตญนๆคฌษิภตควคน" -#~ msgid "E234: Unknown fontset: %s" -#~ msgstr "E234: ฬครฮคฮฅีฅฉฅ๓ฅศฅปฅรฅศ: %s" +msgid "E139: File is loaded in another buffer" +msgstr "E139: ฦฑคธฬพมฐคฮฅีฅกฅคฅ๋คฌยพคฮฅะฅรฅีฅกควฦษนคค์คฦคคคคน" -#~ msgid "E235: Unknown font: %s" -#~ msgstr "E235: ฬครฮคฮฅีฅฉฅ๓ฅศ: %s" +#, c-format +msgid "E764: Option '%s' is not set" +msgstr "E764: ฅชฅืฅทฅ็ฅ๓ '%s' คฯภ฿ฤ๊คตค์คฦคคคคปค๓" -#~ msgid "E236: Font \"%s\" is not fixed-width" -#~ msgstr "E236: ฅีฅฉฅ๓ฅศ \"%s\" คฯธวฤ๊ษควคฯคขค๊คคปค๓" +msgid "E850: Invalid register name" +msgstr "E850: ฬตธ๚คสฅ์ฅธฅนฅฟฬพควคน" -#~ msgid "E448: Could not load library function %s" -#~ msgstr "E448: ฅ้ฅคฅึฅ้ฅ๊คฮดุฟ๔ %s ค๒ฅํกผฅษควคญคคปค๓ควคทคฟ" +#, c-format +msgid "E919: Directory not found in '%s': \"%s\"" +msgstr "E919: ฅวฅฃฅ์ฅฏฅศฅ๊คฌ '%s' คฮรๆคหคขค๊คคปค๓: \"%s\"" -#~ msgid "E26: Hebrew cannot be used: Not enabled at compile time\n" -#~ msgstr "E26: ฅุฅึฅ้ฅคธ์คฯปศอัษิฒฤวฝควคน: ฅณฅ๓ฅัฅคฅ๋ปคหฬตธ๚คหคตค์คฦคคคคน\n" +msgid "search hit TOP, continuing at BOTTOM" +msgstr "พๅคควธกบ๗คทคฟคฮควฒผคหฬแค๊คคน" -#~ msgid "E27: Farsi cannot be used: Not enabled at compile time\n" -#~ msgstr "E27: ฅฺฅ๋ฅทฅขธ์คฯปศอัษิฒฤวฝควคน: ฅณฅ๓ฅัฅคฅ๋ปคหฬตธ๚คหคตค์คฦคคคคน\n" +msgid "search hit BOTTOM, continuing at TOP" +msgstr "ฒผคควธกบ๗คทคฟคฮควพๅคหฬแค๊คคน" -#~ msgid "E800: Arabic cannot be used: Not enabled at compile time\n" -#~ msgstr "" -#~ "E800: ฅขฅ้ฅำฅขธ์คฯปศอัษิฒฤวฝควคน: ฅณฅ๓ฅัฅคฅ๋ปคหฬตธ๚คหคตค์คฦคคคคน\n" +#, c-format +msgid "Need encryption key for \"%s\"" +msgstr "ฐลนๆฅญกผคฌษฌอืควคน: \"%s\"" -#~ msgid "E247: no registered server named \"%s\"" -#~ msgstr "E247: %s คศคคคฆฬพมฐคฮละฯฟคตค์คฟฅตกผฅะคฯคขค๊คคปค๓" +msgid "empty keys are not allowed" +msgstr "ถ๕คฮฅญกผคฯต๖ฒฤคตค์คฦคคคคปค๓" -#~ msgid "E233: cannot open display" -#~ msgstr "E233: ฅวฅฃฅนฅืฅ์ฅคค๒ณซคฑคคปค๓" +msgid "dictionary is locked" +msgstr "ผญฝ๑คฯฅํฅรฅฏคตค์คฦคคคคน" -#~ msgid "E449: Invalid expression received" -#~ msgstr "E449: ฬตธ๚คสผฐค๒ผ๕คฑผ่ค๊คคทคฟ" +msgid "list is locked" +msgstr "ฅ๊ฅนฅศคฯฅํฅรฅฏคตค์คฦคคคคน" -#~ msgid "E463: Region is guarded, cannot modify" -#~ msgstr "E463: ฮฮฐ่คฌสธ๎คตค์คฦคคค๋คฮคว, สันนควคญคคปค๓" +#, c-format +msgid "failed to add key '%s' to dictionary" +msgstr "ผญฝ๑คหฅญกผ '%s' ค๒ฤษฒรคนค๋คฮคหผบวิคทคคทคฟ" -#~ msgid "E744: NetBeans does not allow changes in read-only files" -#~ msgstr "E744: NetBeans คฯฦษนภ์อัฅีฅกฅคฅ๋ค๒สันนคนค๋คณคศค๒ต๖คทคคปค๓" +#, c-format +msgid "index must be int or slice, not %s" +msgstr "ฅคฅ๓ฅวฅรฅฏฅนคฯ %s ควคฯคสคฏภฐฟ๔คซฅนฅ้ฅคฅนคหคทคฦคฏคภคตคค" -#~ msgid "Need encryption key for \"%s\"" -#~ msgstr "ฐลนๆฅญกผคฌษฌอืควคน: \"%s\"" +#, c-format +msgid "expected str() or unicode() instance, but got %s" +msgstr "str() คโคทคฏคฯ unicode() คฮฅคฅ๓ฅนฅฟฅ๓ฅนคฌดยิคตค์คฦคคค๋คฮคห %s ควคทคฟ" -#~ msgid "empty keys are not allowed" -#~ msgstr "ถ๕คฮฅญกผคฯต๖ฒฤคตค์คฦคคคคปค๓" +#, c-format +msgid "expected bytes() or str() instance, but got %s" +msgstr "bytes() คโคทคฏคฯ str() คฮฅคฅ๓ฅนฅฟฅ๓ฅนคฌดยิคตค์คฦคคค๋คฮคห %s ควคทคฟ" -#~ msgid "dictionary is locked" -#~ msgstr "ผญฝ๑คฯฅํฅรฅฏคตค์คฦคคคคน" +#, c-format +msgid "" +"expected int(), long() or something supporting coercing to long(), but got %s" +msgstr "long() คซคฝค์คุสัดนฒฤวฝคสคโคฮคฌดยิคตค์คฦคคค๋คฮคห %s ควคทคฟ" -#~ msgid "list is locked" -#~ msgstr "ฅ๊ฅนฅศคฯฅํฅรฅฏคตค์คฦคคคคน" +#, c-format +msgid "expected int() or something supporting coercing to int(), but got %s" +msgstr "int() คซคฝค์คุสัดนฒฤวฝคสคโคฮคฌดยิคตค์คฦคคค๋คฮคห %s ควคทคฟ" -#~ msgid "failed to add key '%s' to dictionary" -#~ msgstr "ผญฝ๑คหฅญกผ '%s' ค๒ฤษฒรคนค๋คฮคหผบวิคทคคทคฟ" +msgid "value is too large to fit into C int type" +msgstr "Cธภธ์คฮ int ทฟคศคทคฦคฯรอคฌย็คญฒแคฎคคน" -#~ msgid "index must be int or slice, not %s" -#~ msgstr "ฅคฅ๓ฅวฅรฅฏฅนคฯ %s ควคฯคสคฏภฐฟ๔คซฅนฅ้ฅคฅนคหคทคฦคฏคภคตคค" +msgid "value is too small to fit into C int type" +msgstr "Cธภธ์คฮ int ทฟคศคทคฦคฯรอคฌพฎคตฒแคฎคคน" -#~ msgid "expected str() or unicode() instance, but got %s" -#~ msgstr "" -#~ "str() คโคทคฏคฯ unicode() คฮฅคฅ๓ฅนฅฟฅ๓ฅนคฌดยิคตค์คฦคคค๋คฮคห %s ควคทคฟ" +msgid "number must be greater than zero" +msgstr "ฟ๔รอคฯ 0 ค่ค๊ย็คญคฏคสคฑค์คะคสค๊คคปค๓" -#~ msgid "expected bytes() or str() instance, but got %s" -#~ msgstr "bytes() คโคทคฏคฯ str() คฮฅคฅ๓ฅนฅฟฅ๓ฅนคฌดยิคตค์คฦคคค๋คฮคห %s ควคทคฟ" +msgid "number must be greater or equal to zero" +msgstr "ฟ๔รอคฯ 0 คซคฝค์ฐสพๅควคสคฑค์คะคสค๊คคปค๓" -#~ msgid "" -#~ "expected int(), long() or something supporting coercing to long(), but " -#~ "got %s" -#~ msgstr "long() คซคฝค์คุสัดนฒฤวฝคสคโคฮคฌดยิคตค์คฦคคค๋คฮคห %s ควคทคฟ" +msgid "can't delete OutputObject attributes" +msgstr "OutputObjectยฐภญค๒พรคปคคปค๓" -#~ msgid "expected int() or something supporting coercing to int(), but got %s" -#~ msgstr "int() คซคฝค์คุสัดนฒฤวฝคสคโคฮคฌดยิคตค์คฦคคค๋คฮคห %s ควคทคฟ" +#, c-format +msgid "invalid attribute: %s" +msgstr "ฬตธ๚คสยฐภญควคน: %s" -#~ msgid "value is too large to fit into C int type" -#~ msgstr "Cธภธ์คฮ int ทฟคศคทคฦคฯรอคฌย็คญฒแคฎคคน" +msgid "E264: Python: Error initialising I/O objects" +msgstr "E264: Python: I/Oฅชฅึฅธฅงฅฏฅศคฮฝ้ดฒฝฅจฅ้กผ" -#~ msgid "value is too small to fit into C int type" -#~ msgstr "Cธภธ์คฮ int ทฟคศคทคฦคฯรอคฌพฎคตฒแคฎคคน" +msgid "failed to change directory" +msgstr "ผญฝ๑คฮสันนคหผบวิคทคคทคฟ" -#~ msgid "number must be greater then zero" -#~ msgstr "ฟ๔รอคฯ 0 ค่ค๊ย็คญคฏคสคฑค์คะคสค๊คคปค๓" +#, c-format +msgid "expected 3-tuple as imp.find_module() result, but got %s" +msgstr "imp.find_module() คฌ %s ค๒สึคทคคทคฟ (ดยิรอ: 3 อืมวคฮฅฟฅืฅ๋)" -#~ msgid "number must be greater or equal to zero" -#~ msgstr "ฟ๔รอคฯ 0 คซคฝค์ฐสพๅควคสคฑค์คะคสค๊คคปค๓" +#, c-format +msgid "expected 3-tuple as imp.find_module() result, but got tuple of size %d" +msgstr "imp.find_module() คฌ %d อืมวคฮฅฟฅืฅ๋ค๒สึคทคคทคฟ (ดยิรอ: 3)" -#~ msgid "can't delete OutputObject attributes" -#~ msgstr "OutputObjectยฐภญค๒พรคปคคปค๓" +msgid "internal error: imp.find_module returned tuple with NULL" +msgstr "ฦโษ๔ฅจฅ้กผ: imp.find_module คฌ NULL ค๒ดคเฅฟฅืฅ๋ค๒สึคทคคทคฟ" -#~ msgid "invalid attribute: %s" -#~ msgstr "ฬตธ๚คสยฐภญควคน: %s" +msgid "cannot delete vim.Dictionary attributes" +msgstr "vim.Dictionaryยฐภญคฯพรคปคคปค๓" -#~ msgid "E264: Python: Error initialising I/O objects" -#~ msgstr "E264: Python: I/Oฅชฅึฅธฅงฅฏฅศคฮฝ้ดฒฝฅจฅ้กผ" +msgid "cannot modify fixed dictionary" +msgstr "ธวฤ๊คตค์คฟผญฝ๑คฯสันนควคญคคปค๓" -#~ msgid "failed to change directory" -#~ msgstr "ผญฝ๑คฮสันนคหผบวิคทคคทคฟ" +#, c-format +msgid "cannot set attribute %s" +msgstr "ยฐภญ %s คฯภ฿ฤ๊ควคญคคปค๓" -#~ msgid "expected 3-tuple as imp.find_module() result, but got %s" -#~ msgstr "imp.find_module() คฌ %s ค๒สึคทคคทคฟ (ดยิรอ: 2 อืมวคฮฅฟฅืฅ๋)" +msgid "hashtab changed during iteration" +msgstr "ฅคฅฦฅ์กผฅทฅ็ฅ๓รๆคห hashtab คฌสันนคตค์คคทคฟ" -#~ msgid "" -#~ "expected 3-tuple as imp.find_module() result, but got tuple of size %d" -#~ msgstr "impl.find_module() คฌ %d อืมวคฮฅฟฅืฅ๋ค๒สึคทคคทคฟ (ดยิรอ: 2)" +#, c-format +msgid "expected sequence element of size 2, but got sequence of size %d" +msgstr "ฅทกผฅฑฅ๓ฅนคฮอืมวฟ๔คหคฯ 2 คฌดยิคตค์คฦคคคคทคฟคฌ %d ควคทคฟ" -#~ msgid "internal error: imp.find_module returned tuple with NULL" -#~ msgstr "ฦโษ๔ฅจฅ้กผ: imp.find_module คฌ NULL ค๒ดคเฅฟฅืฅ๋ค๒สึคทคคทคฟ" +msgid "list constructor does not accept keyword arguments" +msgstr "ฅ๊ฅนฅศคฮฅณฅ๓ฅนฅศฅ้ฅฏฅฟคฯฅญกผฅ๏กผฅษฐ๚ฟ๔ค๒ผ๕คฑษีคฑคคปค๓" -#~ msgid "cannot delete vim.Dictionary attributes" -#~ msgstr "vim.Dictionaryยฐภญคฯพรคปคคปค๓" +msgid "list index out of range" +msgstr "ฅ๊ฅนฅศศฯฐฯณฐคฮฅคฅ๓ฅวฅรฅฏฅนควคน" -#~ msgid "cannot modify fixed dictionary" -#~ msgstr "ธวฤ๊คตค์คฟผญฝ๑คฯสันนควคญคคปค๓" +#. No more suitable format specifications in python-2.3 +#, c-format +msgid "internal error: failed to get vim list item %d" +msgstr "ฦโษ๔ฅจฅ้กผ: vimคฮฅ๊ฅนฅศอืมว %d คฮผ่ฦภคหผบวิคทคคทคฟ" -#~ msgid "cannot set attribute %s" -#~ msgstr "ยฐภญ %s คฯภ฿ฤ๊ควคญคคปค๓" +msgid "slice step cannot be zero" +msgstr "ฅนฅ้ฅคฅนคฮฅนฅฦฅรฅืคห 0 คฯปุฤ๊ควคญคคปค๓" -#~ msgid "hashtab changed during iteration" -#~ msgstr "ฅคฅฦฅ์กผฅทฅ็ฅ๓รๆคห hashtab คฌสันนคตค์คคทคฟ" +#, c-format +msgid "attempt to assign sequence of size greater than %d to extended slice" +msgstr "ฤนคต %d คฮณศฤฅฅนฅ้ฅคฅนคหกขค่ค๊ฤนคคฅนฅ้ฅคฅนค๒ณไค๊ล๖คฦค่คฆคศคทคคทคฟ" -#~ msgid "expected sequence element of size 2, but got sequence of size %d" -#~ msgstr "ฅทกผฅฑฅ๓ฅนคฮอืมวฟ๔คหคฯ 2 คฌดยิคตค์คฦคคคคทคฟคฌ %d ควคทคฟ" +#, c-format +msgid "internal error: no vim list item %d" +msgstr "ฦโษ๔ฅจฅ้กผ: vimคฮฅ๊ฅนฅศอืมว %d คฯคขค๊คคปค๓" -#~ msgid "list constructor does not accept keyword arguments" -#~ msgstr "ฅ๊ฅนฅศคฮฅณฅ๓ฅนฅศฅ้ฅฏฅฟคฯฅญกผฅ๏กผฅษฐ๚ฟ๔ค๒ผ๕คฑษีคฑคคปค๓" +msgid "internal error: not enough list items" +msgstr "ฦโษ๔ฅจฅ้กผ: ฅ๊ฅนฅศคหฝฝสฌคสอืมวคฌคขค๊คคปค๓" -#~ msgid "list index out of range" -#~ msgstr "ฅ๊ฅนฅศศฯฐฯณฐคฮฅคฅ๓ฅวฅรฅฏฅนควคน" +msgid "internal error: failed to add item to list" +msgstr "ฦโษ๔ฅจฅ้กผ: ฅ๊ฅนฅศคุคฮอืมวฤษฒรคหผบวิคทคคทคฟ" -#~ msgid "internal error: failed to get vim list item %d" -#~ msgstr "ฦโษ๔ฅจฅ้กผ: vimคฮฅ๊ฅนฅศอืมว %d คฮผ่ฦภคหผบวิคทคคทคฟ" +#, c-format +msgid "attempt to assign sequence of size %d to extended slice of size %d" +msgstr "ฤนคต %d คฮฅนฅ้ฅคฅนค๒ %d คฮณศฤฅฅนฅ้ฅคฅนคหณไค๊ล๖คฦค่คฆคศคทคคทคฟ" -#~ msgid "failed to add item to list" -#~ msgstr "ฅ๊ฅนฅศคุคฮอืมวฤษฒรคหผบวิคทคคทคฟ" +msgid "failed to add item to list" +msgstr "ฅ๊ฅนฅศคุคฮอืมวฤษฒรคหผบวิคทคคทคฟ" -#~ msgid "internal error: no vim list item %d" -#~ msgstr "ฦโษ๔ฅจฅ้กผ: vimคฮฅ๊ฅนฅศอืมว %d คฯคขค๊คคปค๓" +msgid "cannot delete vim.List attributes" +msgstr "vim.List ยฐภญคฯพรคปคคปค๓" -#~ msgid "internal error: failed to add item to list" -#~ msgstr "ฦโษ๔ฅจฅ้กผ: ฅ๊ฅนฅศคุคฮอืมวฤษฒรคหผบวิคทคคทคฟ" +msgid "cannot modify fixed list" +msgstr "ธวฤ๊คตค์คฟฅ๊ฅนฅศคฯสันนควคญคคปค๓" -#~ msgid "cannot delete vim.List attributes" -#~ msgstr "vim.List ยฐภญคฯพรคปคคปค๓" +#, c-format +msgid "unnamed function %s does not exist" +msgstr "ฬตฬพดุฟ๔ %s คฯยธบ฿คทคคปค๓" -#~ msgid "cannot modify fixed list" -#~ msgstr "ธวฤ๊คตค์คฟฅ๊ฅนฅศคฯสันนควคญคคปค๓" +#, c-format +msgid "function %s does not exist" +msgstr "ดุฟ๔ %s คฌคขค๊คคปค๓" -#~ msgid "unnamed function %s does not exist" -#~ msgstr "ฬตฬพดุฟ๔ %s คฯยธบ฿คทคคปค๓" +#, c-format +msgid "failed to run function %s" +msgstr "ดุฟ๔ %s คฮผยนิคหผบวิคทคคทคฟ" -#~ msgid "function %s does not exist" -#~ msgstr "ดุฟ๔ %s คฌคขค๊คคปค๓" +msgid "unable to get option value" +msgstr "ฅชฅืฅทฅ็ฅ๓คฮรอคฯผ่ฦภควคญคคปค๓" -#~ msgid "function constructor does not accept keyword arguments" -#~ msgstr "ดุฟ๔คฮฅณฅ๓ฅนฅศฅ้ฅฏฅฟคฯฅญกผฅ๏กผฅษฐ๚ฟ๔ค๒ผ๕คฑษีคฑคคปค๓" +msgid "internal error: unknown option type" +msgstr "ฦโษ๔ฅจฅ้กผ: ฬครฮคฮฅชฅืฅทฅ็ฅ๓ทฟควคน" -#~ msgid "failed to run function %s" -#~ msgstr "ดุฟ๔ %s คฮผยนิคหผบวิคทคคทคฟ" +msgid "problem while switching windows" +msgstr "ฅฆฅฃฅ๓ฅษฅฆค๒ภฺดนรๆคหฬไย๊คฌศฏภธคทคคทคฟ" -#~ msgid "problem while switching windows" -#~ msgstr "ฅฆฅฃฅ๓ฅษฅฆค๒ภฺดนรๆคหฬไย๊คฌศฏภธคทคคทคฟ" +#, c-format +msgid "unable to unset global option %s" +msgstr "ฅฐฅํกผฅะฅ๋ฅชฅืฅทฅ็ฅ๓ %s คฮภ฿ฤ๊ฒ๒ฝคฯควคญคคปค๓" -#~ msgid "unable to unset global option %s" -#~ msgstr "ฅฐฅํกผฅะฅ๋ฅชฅืฅทฅ็ฅ๓ %s คฮภ฿ฤ๊ฒ๒ฝคฯควคญคคปค๓" +#, c-format +msgid "unable to unset option %s which does not have global value" +msgstr "ฅฐฅํกผฅะฅ๋คสรอคฮฬตคคฅชฅืฅทฅ็ฅ๓ %s คฮภ฿ฤ๊ฒ๒ฝคฯควคญคคปค๓" -#~ msgid "unable to unset option %s which does not have global value" -#~ msgstr "ฅฐฅํกผฅะฅ๋คสรอคฮฬตคคฅชฅืฅทฅ็ฅ๓ %s คฮภ฿ฤ๊ฒ๒ฝคฯควคญคคปค๓" +msgid "attempt to refer to deleted tab page" +msgstr "บ๏ฝคตค์คฟฅฟฅึค๒ปฒพศคทค่คฆคศคทคคทคฟ" -#~ msgid "attempt to refer to deleted tab page" -#~ msgstr "บ๏ฝคตค์คฟฅฟฅึค๒ปฒพศคทค่คฆคศคทคคทคฟ" +msgid "no such tab page" +msgstr "คฝคฮค่คฆคสฅฟฅึฅฺกผฅธคฯคขค๊คคปค๓" -#~ msgid "no such tab page" -#~ msgstr "คฝคฮค่คฆคสฅฟฅึฅฺกผฅธคฯคขค๊คคปค๓" +msgid "attempt to refer to deleted window" +msgstr "บ๏ฝคตค์คฟฅฆฅฃฅ๓ฅษฅฆค๒ปฒพศคทค่คฆคศคทคคทคฟ" -#~ msgid "attempt to refer to deleted window" -#~ msgstr "บ๏ฝคตค์คฟฅฆฅฃฅ๓ฅษฅฆค๒ปฒพศคทค่คฆคศคทคคทคฟ" +msgid "readonly attribute: buffer" +msgstr "ฦษนภ์อัยฐภญ: ฅะฅรฅีฅกกผ" -#~ msgid "readonly attribute: buffer" -#~ msgstr "ฦษนภ์อัยฐภญ: ฅะฅรฅีฅกกผ" +msgid "cursor position outside buffer" +msgstr "ฅซกผฅฝฅ๋ฐฬรึคฌฅะฅรฅีฅกคฮณฐยฆควคน" -#~ msgid "cursor position outside buffer" -#~ msgstr "ฅซกผฅฝฅ๋ฐฬรึคฌฅะฅรฅีฅกคฮณฐยฆควคน" +msgid "no such window" +msgstr "คฝคฮค่คฆคสฅฆฅฃฅ๓ฅษฅฆคฯคขค๊คคปค๓" -#~ msgid "no such window" -#~ msgstr "คฝคฮค่คฆคสฅฆฅฃฅ๓ฅษฅฆคฯคขค๊คคปค๓" +msgid "attempt to refer to deleted buffer" +msgstr "บ๏ฝคตค์คฟฅะฅรฅีฅกค๒ปฒพศคทค่คฆคศคทคคทคฟ" -#~ msgid "attempt to refer to deleted buffer" -#~ msgstr "บ๏ฝคตค์คฟฅะฅรฅีฅกค๒ปฒพศคทค่คฆคศคทคคทคฟ" +msgid "failed to rename buffer" +msgstr "ฅะฅรฅีฅกฬพคฮสันนคหผบวิคทคคทคฟ" -#~ msgid "failed to rename buffer" -#~ msgstr "ฅะฅรฅีฅกฬพคฮสันนคหผบวิคทคคทคฟ" +msgid "mark name must be a single character" +msgstr "ฅกผฅฏฬพคฯ1สธป๚คฮฅขฅ๋ฅีฅกฅูฅรฅศควคสคฑค์คะคสค๊คคปค๓" -#~ msgid "mark name must be a single character" -#~ msgstr "ฅกผฅฏฬพคฯ1สธป๚คฮฅขฅ๋ฅีฅกฅูฅรฅศควคสคฑค์คะคสค๊คคปค๓" +#, c-format +msgid "expected vim.Buffer object, but got %s" +msgstr "vim.Bufferฅชฅึฅธฅงฅฏฅศคฌดยิคตค์คฦคคค๋คฮคห %s ควคทคฟ" -#~ msgid "expected vim.Buffer object, but got %s" -#~ msgstr "vim.Bufferฅชฅึฅธฅงฅฏฅศคฌดยิคตค์คฦคคค๋คฮคห %s ควคทคฟ" +#, c-format +msgid "failed to switch to buffer %d" +msgstr "ปุฤ๊คตค์คฟฅะฅรฅีฅก %d คุคฮภฺค๊ยุคจคหผบวิคทคคทคฟ" -#~ msgid "failed to switch to buffer %d" -#~ msgstr "ปุฤ๊คตค์คฟฅะฅรฅีฅก %d คุคฮภฺค๊ยุคจคหผบวิคทคคทคฟ" +#, c-format +msgid "expected vim.Window object, but got %s" +msgstr "vim.Windowฅชฅึฅธฅงฅฏฅศคฌดยิคตค์คฦคคค๋คฮคห %s ควคทคฟ" -#~ msgid "expected vim.Window object, but got %s" -#~ msgstr "vim.Windowฅชฅึฅธฅงฅฏฅศคฌดยิคตค์คฦคคค๋คฮคห %s ควคทคฟ" +msgid "failed to find window in the current tab page" +msgstr "ธฝบ฿คฮฅฟฅึคหคฯปุฤ๊คตค์คฟฅฆฅฃฅ๓ฅษฅฆคฌคขค๊คคปค๓ควคทคฟ" -#~ msgid "failed to find window in the current tab page" -#~ msgstr "ธฝบ฿คฮฅฟฅึคหคฯปุฤ๊คตค์คฟฅฆฅฃฅ๓ฅษฅฆคฌคขค๊คคปค๓ควคทคฟ" +msgid "did not switch to the specified window" +msgstr "ปุฤ๊คตค์คฟฅฆฅฃฅ๓ฅษฅฆคหภฺค๊ยุคจคคปค๓ควคทคฟ" -#~ msgid "did not switch to the specified window" -#~ msgstr "ปุฤ๊คตค์คฟฅฆฅฃฅ๓ฅษฅฆคหภฺค๊ยุคจคคปค๓ควคทคฟ" +#, c-format +msgid "expected vim.TabPage object, but got %s" +msgstr "vim.TabPageฅชฅึฅธฅงฅฏฅศคฌดยิคตค์คฦคคค๋คฮคห %s ควคทคฟ" -#~ msgid "expected vim.TabPage object, but got %s" -#~ msgstr "vim.TabPageฅชฅึฅธฅงฅฏฅศคฌดยิคตค์คฦคคค๋คฮคห %s ควคทคฟ" +msgid "did not switch to the specified tab page" +msgstr "ปุฤ๊คตค์คฟฅฟฅึฅฺกผฅธคหภฺค๊ยุคจคคปค๓ควคทคฟ" -#~ msgid "did not switch to the specified tab page" -#~ msgstr "ปุฤ๊คตค์คฟฅฟฅึฅฺกผฅธคหภฺค๊ยุคจคคปค๓ควคทคฟ" +msgid "failed to run the code" +msgstr "ฅณกผฅษคฮผยนิคหผบวิคทคคทคฟ" -#~ msgid "failed to run the code" -#~ msgstr "ฅณกผฅษคฮผยนิคหผบวิคทคคทคฟ" +msgid "E858: Eval did not return a valid python object" +msgstr "E858: ผฐษพฒมคฯอญธ๚คสpythonฅชฅึฅธฅงฅฏฅศค๒สึคทคคปค๓ควคทคฟ" -#~ msgid "E858: Eval did not return a valid python object" -#~ msgstr "E858: ผฐษพฒมคฯอญธ๚คสpythonฅชฅึฅธฅงฅฏฅศค๒สึคทคคปค๓ควคทคฟ" +msgid "E859: Failed to convert returned python object to vim value" +msgstr "E859: สึคตค์คฟpythonฅชฅึฅธฅงฅฏฅศค๒vimคฮรอคหสัดนควคญคคปค๓ควคทคฟ" -#~ msgid "E859: Failed to convert returned python object to vim value" -#~ msgstr "E859: สึคตค์คฟpythonฅชฅึฅธฅงฅฏฅศค๒vimคฮรอคหสัดนควคญคคปค๓ควคทคฟ" +#, c-format +msgid "unable to convert %s to vim dictionary" +msgstr "%s vimคฮผญฝ๑ทฟคหสัดนควคญคคปค๓" -#~ msgid "unable to convert %s to vim dictionary" -#~ msgstr "%s vimคฮผญฝ๑ทฟคหสัดนควคญคคปค๓" +#, c-format +msgid "unable to convert %s to vim list" +msgstr "%s ค๒vimคฮฅ๊ฅนฅศคหสัดนควคญคคปค๓" -#~ msgid "unable to convert %s to vim structure" -#~ msgstr "%s ค๒vimคฮนฝยคยฮคหสัดนควคญคคปค๓" +#, c-format +msgid "unable to convert %s to vim structure" +msgstr "%s ค๒vimคฮนฝยคยฮคหสัดนควคญคคปค๓" -#~ msgid "internal error: NULL reference passed" -#~ msgstr "ฦโษ๔ฅจฅ้กผ: NULLปฒพศคฌลฯคตค์คคทคฟ" +msgid "internal error: NULL reference passed" +msgstr "ฦโษ๔ฅจฅ้กผ: NULLปฒพศคฌลฯคตค์คคทคฟ" -#~ msgid "internal error: invalid value type" -#~ msgstr "ฦโษ๔ฅจฅ้กผ: ฬตธ๚คสรอทฟควคน" +msgid "internal error: invalid value type" +msgstr "ฦโษ๔ฅจฅ้กผ: ฬตธ๚คสรอทฟควคน" -#~ msgid "" -#~ "Failed to set path hook: sys.path_hooks is not a list\n" -#~ "You should now do the following:\n" -#~ "- append vim.path_hook to sys.path_hooks\n" -#~ "- append vim.VIM_SPECIAL_PATH to sys.path\n" -#~ msgstr "" -#~ "ฅัฅนฅีฅรฅฏคฮภ฿ฤ๊คหผบวิคทคคทคฟ: sys.path_hooks คฌฅ๊ฅนฅศควคฯคขค๊คคปค๓\n" -#~ "คนคฐคหฒผตญค๒ผยปคทคฦคฏคภคตคค:\n" -#~ "- vim.path_hooks ค๒ sys.path_hooks คุฤษฒร\n" -#~ "- vim.VIM_SPECIAL_PATH ค๒ sys.path คุฤษฒร\n" +msgid "" +"Failed to set path hook: sys.path_hooks is not a list\n" +"You should now do the following:\n" +"- append vim.path_hook to sys.path_hooks\n" +"- append vim.VIM_SPECIAL_PATH to sys.path\n" +msgstr "" +"ฅัฅนฅีฅรฅฏคฮภ฿ฤ๊คหผบวิคทคคทคฟ: sys.path_hooks คฌฅ๊ฅนฅศควคฯคขค๊คคปค๓\n" +"คนคฐคหฒผตญค๒ผยปคทคฦคฏคภคตคค:\n" +"- vim.path_hooks ค๒ sys.path_hooks คุฤษฒร\n" +"- vim.VIM_SPECIAL_PATH ค๒ sys.path คุฤษฒร\n" -#~ msgid "" -#~ "Failed to set path: sys.path is not a list\n" -#~ "You should now append vim.VIM_SPECIAL_PATH to sys.path" -#~ msgstr "" -#~ "ฅัฅนคฮภ฿ฤ๊คหผบวิคทคคทคฟ: sys.path คฌฅ๊ฅนฅศควคฯคขค๊คคปค๓\n" -#~ "คนคฐคห vim.VIM_SPECIAL_PATH ค๒ sys.path คหฤษฒรคทคฦคฏคภคตคค" +msgid "" +"Failed to set path: sys.path is not a list\n" +"You should now append vim.VIM_SPECIAL_PATH to sys.path" +msgstr "" +"ฅัฅนคฮภ฿ฤ๊คหผบวิคทคคทคฟ: sys.path คฌฅ๊ฅนฅศควคฯคขค๊คคปค๓\n" +"คนคฐคห vim.VIM_SPECIAL_PATH ค๒ sys.path คหฤษฒรคทคฦคฏคภคตคค" diff --git a/src/nvim/po/ja.po b/src/nvim/po/ja.po index e12cfb7e70..5cb789c93e 100644 --- a/src/nvim/po/ja.po +++ b/src/nvim/po/ja.po @@ -1,3 +1,4 @@ + # Japanese translation for Vim # # Do ":help uganda" in Vim to read copying and usage conditions. @@ -14,213 +15,176 @@ msgid "" msgstr "" "Project-Id-Version: Vim 7.4\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2016-02-01 09:02+0900\n" -"PO-Revision-Date: 2013-06-02-01 09:08+09n" +"POT-Creation-Date: 2016-09-10 21:10+0900\n" +"PO-Revision-Date: 2016-09-10 21:20+0900\n" "Last-Translator: MURAOKA Taro <koron.kaoriya@gmail.com>\n" "Language-Team: vim-jp (https://github.com/vim-jp/lang-ja)\n" "Language: Japanese\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8-bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" -#: ../api/private/helpers.c:201 -#, fuzzy -msgid "Unable to get option value" -msgstr "ใชใใทใงใณใฎๅคใฏๅๅพใงใใพใใ" +msgid "E831: bf_key_init() called with empty password" +msgstr "E831: bf_key_init() ใ็ฉบใในใฏใผใใงๅผใณๅบใใใพใใ" -#: ../api/private/helpers.c:204 -msgid "internal error: unknown option type" -msgstr "ๅ
้จใจใฉใผ: ๆช็ฅใฎใชใใทใงใณๅใงใ" +msgid "E820: sizeof(uint32_t) != 4" +msgstr "E820: sizeof(uint32_t) != 4" + +msgid "E817: Blowfish big/little endian use wrong" +msgstr "E817: Blowfishๆๅทใฎใใใฐ/ใชใใซใจใณใใฃใขใณใ้้ใฃใฆใใพใ" + +msgid "E818: sha256 test failed" +msgstr "E818: sha256ใฎใในใใซๅคฑๆใใพใใ" + +msgid "E819: Blowfish test failed" +msgstr "E819: Blowfishๆๅทใฎใในใใซๅคฑๆใใพใใ" -#: ../buffer.c:92 msgid "[Location List]" msgstr "[ใญใฑใผใทใงใณใชในใ]" -#: ../buffer.c:93 msgid "[Quickfix List]" msgstr "[Quickfixใชในใ]" -#: ../buffer.c:94 msgid "E855: Autocommands caused command to abort" msgstr "E855: autocommandใใณใใณใใฎๅๆญขใๅผใ่ตทใใใพใใ" -#: ../buffer.c:135 msgid "E82: Cannot allocate any buffer, exiting..." msgstr "E82: ใใใใกใ1ใคใไฝๆใงใใชใใฎใง, ็ตไบใใพใ..." -#: ../buffer.c:138 msgid "E83: Cannot allocate buffer, using other one..." msgstr "E83: ใใใใกใไฝๆใงใใชใใฎใง, ไปใฎใไฝฟ็จใใพใ..." -#: ../buffer.c:763 +msgid "E931: Buffer cannot be registered" +msgstr "E931: ใใใใกใ็ป้ฒใงใใพใใ" + +msgid "E937: Attempt to delete a buffer that is in use" +msgstr "E937: ไฝฟ็จไธญใฎใใใใกใๅ้คใใใใจ่ฉฆใฟใพใใ" + msgid "E515: No buffers were unloaded" msgstr "E515: ่งฃๆพใใใใใใใกใฏใใใพใใ" -#: ../buffer.c:765 msgid "E516: No buffers were deleted" msgstr "E516: ๅ้คใใใใใใใกใฏใใใพใใ" -#: ../buffer.c:767 msgid "E517: No buffers were wiped out" msgstr "E517: ็ ดๆฃใใใใใใใกใฏใใใพใใ" -#: ../buffer.c:772 msgid "1 buffer unloaded" msgstr "1 ๅใฎใใใใกใ่งฃๆพใใใพใใ" -#: ../buffer.c:774 #, c-format msgid "%d buffers unloaded" msgstr "%d ๅใฎใใใใกใ่งฃๆพใใใพใใ" -#: ../buffer.c:777 msgid "1 buffer deleted" msgstr "1 ๅใฎใใใใกใๅ้คใใใพใใ" -#: ../buffer.c:779 #, c-format msgid "%d buffers deleted" msgstr "%d ๅใฎใใใใกใๅ้คใใใพใใ" -#: ../buffer.c:782 msgid "1 buffer wiped out" msgstr "1 ๅใฎใใใใกใ็ ดๆฃใใใพใใ" -#: ../buffer.c:784 #, c-format msgid "%d buffers wiped out" msgstr "%d ๅใฎใใใใกใ็ ดๆฃใใใพใใ" -#: ../buffer.c:806 msgid "E90: Cannot unload last buffer" msgstr "E90: ๆๅพใฎใใใใกใฏ่งฃๆพใงใใพใใ" -#: ../buffer.c:874 msgid "E84: No modified buffer found" msgstr "E84: ๅคๆดใใใใใใใกใฏใใใพใใ" #. back where we started, didn't find anything. -#: ../buffer.c:903 msgid "E85: There is no listed buffer" msgstr "E85: ใชในใ่กจ็คบใใใใใใใกใฏใใใพใใ" -#: ../buffer.c:913 -#, c-format -msgid "E86: Buffer %<PRId64> does not exist" -msgstr "E86: ใใใใก %<PRId64> ใฏใใใพใใ" - -#: ../buffer.c:915 msgid "E87: Cannot go beyond last buffer" msgstr "E87: ๆๅพใฎใใใใกใ่ถใใฆ็งปๅใฏใงใใพใใ" -#: ../buffer.c:917 msgid "E88: Cannot go before first buffer" msgstr "E88: ๆๅใฎใใใใกใใๅใธใฏ็งปๅใงใใพใใ" -#: ../buffer.c:945 #, c-format -msgid "" -"E89: No write since last change for buffer %<PRId64> (add ! to override)" -msgstr "E89: ใใใใก %<PRId64> ใฎๅคๆดใฏไฟๅญใใใฆใใพใใ (! ใงๅคๆดใ็ ดๆฃ)" +msgid "E89: No write since last change for buffer %ld (add ! to override)" +msgstr "E89: ใใใใก %ld ใฎๅคๆดใฏไฟๅญใใใฆใใพใใ (! ใงๅคๆดใ็ ดๆฃ)" -#. wrap around (may cause duplicates) -#: ../buffer.c:1423 msgid "W14: Warning: List of file names overflow" msgstr "W14: ่ญฆๅ: ใใกใคใซๅใฎใชในใใ้ท้ใใพใ" -#: ../buffer.c:1555 ../quickfix.c:3361 #, c-format -msgid "E92: Buffer %<PRId64> not found" -msgstr "E92: ใใใใก %<PRId64> ใ่ฆใคใใใพใใ" +msgid "E92: Buffer %ld not found" +msgstr "E92: ใใใใก %ld ใ่ฆใคใใใพใใ" -#: ../buffer.c:1798 #, c-format msgid "E93: More than one match for %s" msgstr "E93: %s ใซ่คๆฐใฎ่ฉฒๅฝใใใใพใใ" -#: ../buffer.c:1800 #, c-format msgid "E94: No matching buffer for %s" msgstr "E94: %s ใซ่ฉฒๅฝใใใใใใกใฏใใใพใใใงใใ" -#: ../buffer.c:2161 #, c-format -msgid "line %<PRId64>" -msgstr "่ก %<PRId64>" +msgid "line %ld" +msgstr "่ก %ld" -#: ../buffer.c:2233 msgid "E95: Buffer with this name already exists" msgstr "E95: ใใฎๅๅใฎใใใใกใฏๆขใซใใใพใ" -#: ../buffer.c:2498 msgid " [Modified]" msgstr " [ๅคๆดใใ]" -#: ../buffer.c:2501 msgid "[Not edited]" msgstr "[ๆช็ทจ้]" -#: ../buffer.c:2504 msgid "[New file]" msgstr "[ๆฐใใกใคใซ]" -#: ../buffer.c:2505 msgid "[Read errors]" msgstr "[่ชญ่พผใจใฉใผ]" -#: ../buffer.c:2506 ../buffer.c:3217 ../fileio.c:1807 ../screen.c:4895 msgid "[RO]" msgstr "[่ชญๅฐ]" -#: ../buffer.c:2507 ../fileio.c:1807 msgid "[readonly]" msgstr "[่ชญ่พผๅฐ็จ]" -#: ../buffer.c:2524 #, c-format msgid "1 line --%d%%--" msgstr "1 ่ก --%d%%--" -#: ../buffer.c:2526 #, c-format -msgid "%<PRId64> lines --%d%%--" -msgstr "%<PRId64> ่ก --%d%%--" +msgid "%ld lines --%d%%--" +msgstr "%ld ่ก --%d%%--" -#: ../buffer.c:2530 #, c-format -msgid "line %<PRId64> of %<PRId64> --%d%%-- col " -msgstr "่ก %<PRId64> (ๅ
จไฝ %<PRId64>) --%d%%-- col " +msgid "line %ld of %ld --%d%%-- col " +msgstr "่ก %ld (ๅ
จไฝ %ld) --%d%%-- col " -#: ../buffer.c:2632 ../buffer.c:4292 ../memline.c:1554 msgid "[No Name]" msgstr "[็กๅ]" #. must be a help buffer -#: ../buffer.c:2667 msgid "help" msgstr "ใใซใ" -#: ../buffer.c:3225 ../screen.c:4883 msgid "[Help]" msgstr "[ใใซใ]" -#: ../buffer.c:3254 ../screen.c:4887 msgid "[Preview]" msgstr "[ใใฌใใฅใผ]" -#: ../buffer.c:3528 msgid "All" msgstr "ๅ
จใฆ" -#: ../buffer.c:3528 msgid "Bot" msgstr "ๆซๅฐพ" -#: ../buffer.c:3531 msgid "Top" msgstr "ๅ
้ ญ" -#: ../buffer.c:4244 msgid "" "\n" "# Buffer list:\n" @@ -228,11 +192,9 @@ msgstr "" "\n" "# ใใใใกใชในใ:\n" -#: ../buffer.c:4289 msgid "[Scratch]" msgstr "[ไธๆธใ]" -#: ../buffer.c:4529 msgid "" "\n" "--- Signs ---" @@ -240,200 +202,235 @@ msgstr "" "\n" "--- ใตใคใณ ---" -#: ../buffer.c:4538 #, c-format msgid "Signs for %s:" msgstr "%s ใฎใตใคใณ:" -#: ../buffer.c:4543 #, c-format -msgid " line=%<PRId64> id=%d name=%s" -msgstr " ่ก=%<PRId64> ่ญๅฅๅญ=%d ๅๅ=%s" +msgid " line=%ld id=%d name=%s" +msgstr " ่ก=%ld ่ญๅฅๅญ=%d ๅๅ=%s" -#: ../cursor_shape.c:68 -msgid "E545: Missing colon" -msgstr "E545: ใณใญใณใใใใพใใ" +msgid "E902: Cannot connect to port" +msgstr "E902: ใใผใใซๆฅ็ถใงใใพใใ" -#: ../cursor_shape.c:70 ../cursor_shape.c:94 -msgid "E546: Illegal mode" -msgstr "E546: ไธๆญฃใชใขใผใใงใ" +msgid "E901: gethostbyname() in channel_open()" +msgstr "E901: channel_open() ๅ
ใฎ gethostbyname() ใๅคฑๆใใพใใ" -#: ../cursor_shape.c:134 -msgid "E548: digit expected" -msgstr "E548: ๆฐๅคใๅฟ
่ฆใงใ" +msgid "E898: socket() in channel_open()" +msgstr "E898: channel_open() ๅ
ใฎ socket() ใๅคฑๆใใพใใ" -#: ../cursor_shape.c:138 -msgid "E549: Illegal percentage" -msgstr "E549: ไธๆญฃใชใใผใปใณใใผใธใงใ" +msgid "E903: received command with non-string argument" +msgstr "E903: ้ๆๅญๅใฎๅผๆฐใฎใณใใณใใๅไฟกใใพใใ" + +msgid "E904: last argument for expr/call must be a number" +msgstr "E904: expr/call ใฎๆๅพใฎๅผๆฐใฏๆฐๅญใงใชใใใฐใชใใพใใ" + +msgid "E904: third argument for call must be a list" +msgstr "E904: call ใฎ3็ช็ฎใฎๅผๆฐใฏใชในใๅใงใชใใใฐใชใใพใใ" + +#, c-format +msgid "E905: received unknown command: %s" +msgstr "E905: ๆช็ฅใฎใณใใณใใๅไฟกใใพใใ: %s" + +#, c-format +msgid "E630: %s(): write while not connected" +msgstr "E630: %s(): ้ๆฅ็ถ็ถๆ
ใงๆธใ่พผใฟใพใใ" + +#, c-format +msgid "E631: %s(): write failed" +msgstr "E631: %s(): ๆธใ่พผใฟใซๅคฑๆใใพใใ" + +#, c-format +msgid "E917: Cannot use a callback with %s()" +msgstr "E917: %s() ใซใณใผใซใใใฏใฏไฝฟใใพใใ" + +msgid "E912: cannot use ch_evalexpr()/ch_sendexpr() with a raw or nl channel" +msgstr "E912: ็ใ nl ใใฃใณใใซใซ ch_evalexpr()/ch_sendexpr ใฏไฝฟใใพใใ" + +msgid "E906: not an open channel" +msgstr "E906: ้ใใฆใใชใใใฃใณใใซใงใ" + +msgid "E920: _io file requires _name to be set" +msgstr "E920: _io ใใกใคใซใฏ _name ใฎ่จญๅฎใๅฟ
่ฆใงใ" + +msgid "E915: in_io buffer requires in_buf or in_name to be set" +msgstr "E915: in_io ใใใใกใฏ in_buf ใ in_name ใฎ่จญๅฎใๅฟ
่ฆใงใ" + +#, c-format +msgid "E918: buffer must be loaded: %s" +msgstr "E918: ใใใใกใใญใผใใใใฆใชใใใฐใชใใพใใ: %s" + +msgid "E821: File is encrypted with unknown method" +msgstr "E821: ใใกใคใซใๆช็ฅใฎๆนๆณใงๆๅทๅใใใฆใใพใ" + +msgid "Warning: Using a weak encryption method; see :help 'cm'" +msgstr "่ญฆๅ: ๅผฑใๆๅทๆนๆณใไฝฟใฃใฆใใพใ; :help 'cm' ใๅ็
งใใฆใใ ใใ" + +msgid "Enter encryption key: " +msgstr "ๆๅทๅ็จใฎใญใผใๅ
ฅๅใใฆใใ ใใ: " + +msgid "Enter same key again: " +msgstr "ใใไธๅบฆๅใใญใผใๅ
ฅๅใใฆใใ ใใ: " + +msgid "Keys don't match!" +msgstr "ใญใผใไธ่ดใใพใใ" + +msgid "[crypted]" +msgstr "[ๆๅทๅ]" + +#, c-format +msgid "E720: Missing colon in Dictionary: %s" +msgstr "E720: ่พๆธๅใซใณใญใณใใใใพใใ: %s" + +#, c-format +msgid "E721: Duplicate key in Dictionary: \"%s\"" +msgstr "E721: ่พๆธๅใซ้่คใญใผใใใใพใ: \"%s\"" + +#, c-format +msgid "E722: Missing comma in Dictionary: %s" +msgstr "E722: ่พๆธๅใซใซใณใใใใใพใใ: %s" + +#, c-format +msgid "E723: Missing end of Dictionary '}': %s" +msgstr "E723: ่พๆธๅใฎๆๅพใซ '}' ใใใใพใใ: %s" + +msgid "extend() argument" +msgstr "extend() ใฎๅผๆฐ" -#: ../diff.c:146 #, c-format -msgid "E96: Can not diff more than %<PRId64> buffers" -msgstr "E96: %<PRId64> ไปฅไธใฎใใใใกใฏdiffใงใใพใใ" +msgid "E737: Key already exists: %s" +msgstr "E737: ใญใผใฏๆขใซๅญๅจใใพใ: %s" + +#, c-format +msgid "E96: Cannot diff more than %ld buffers" +msgstr "E96: %ld ไปฅไธใฎใใใใกใฏdiffใงใใพใใ" -#: ../diff.c:753 msgid "E810: Cannot read or write temp files" msgstr "E810: ไธๆใใกใคใซใฎ่ชญ่พผใใใใฏๆธ่พผใใงใใพใใ" -#: ../diff.c:755 msgid "E97: Cannot create diffs" msgstr "E97: ๅทฎๅใไฝๆใงใใพใใ" -#: ../diff.c:966 +msgid "Patch file" +msgstr "ใใใใใกใคใซ" + msgid "E816: Cannot read patch output" msgstr "E816: patchใฎๅบๅใ่ชญ่พผใใพใใ" -#: ../diff.c:1220 msgid "E98: Cannot read diff output" msgstr "E98: diffใฎๅบๅใ่ชญ่พผใใพใใ" -#: ../diff.c:2081 msgid "E99: Current buffer is not in diff mode" msgstr "E99: ็พๅจใฎใใใใกใฏๅทฎๅใขใผใใงใฏใใใพใใ" -#: ../diff.c:2100 msgid "E793: No other buffer in diff mode is modifiable" msgstr "E793: ๅทฎๅใขใผใใงใใไปใฎใใใใกใฏๅคๆดใงใใพใใ" -#: ../diff.c:2102 msgid "E100: No other buffer in diff mode" msgstr "E100: ๅทฎๅใขใผใใงใใไปใฎใใใใกใฏใใใพใใ" -#: ../diff.c:2112 msgid "E101: More than two buffers in diff mode, don't know which one to use" msgstr "" "E101: ๅทฎๅใขใผใใฎใใใใกใ2ๅไปฅไธใใใฎใงใใฉใใไฝฟใใ็นๅฎใงใใพใใ" -#: ../diff.c:2141 #, c-format msgid "E102: Can't find buffer \"%s\"" msgstr "E102: ใใใใก \"%s\" ใ่ฆใคใใใพใใ" -#: ../diff.c:2152 #, c-format msgid "E103: Buffer \"%s\" is not in diff mode" msgstr "E103: ใใใใก \"%s\" ใฏๅทฎๅใขใผใใงใฏใใใพใใ" -#: ../diff.c:2193 msgid "E787: Buffer changed unexpectedly" msgstr "E787: ไบๆใใใใใใกใๅคๆดๅคๆดใใใพใใ" -#: ../digraph.c:1598 msgid "E104: Escape not allowed in digraph" msgstr "E104: ๅๅญใซEscapeใฏไฝฟ็จใงใใพใใ" -#: ../digraph.c:1760 msgid "E544: Keymap file not found" msgstr "E544: ใญใผใใใใใกใคใซใ่ฆใคใใใพใใ" -#: ../digraph.c:1785 msgid "E105: Using :loadkeymap not in a sourced file" msgstr "E105: :source ใงๅ่พผใใใกใคใซไปฅๅคใงใฏ :loadkeymap ใไฝฟใใพใใ" -#: ../digraph.c:1821 msgid "E791: Empty keymap entry" msgstr "E791: ็ฉบใฎใญใผใใใใจใณใใช" -#: ../edit.c:82 msgid " Keyword completion (^N^P)" msgstr " ใญใผใฏใผใ่ฃๅฎ (^N^P)" #. ctrl_x_mode == 0, ^P/^N compl. -#: ../edit.c:83 msgid " ^X mode (^]^D^E^F^I^K^L^N^O^Ps^U^V^Y)" msgstr " ^X ใขใผใ (^]^D^E^F^I^K^L^N^O^Ps^U^V^Y)" -#: ../edit.c:85 msgid " Whole line completion (^L^N^P)" msgstr " ่ก(ๅ
จไฝ)่ฃๅฎ (^L^N^P)" -#: ../edit.c:86 msgid " File name completion (^F^N^P)" msgstr " ใใกใคใซๅ่ฃๅฎ (^F^N^P)" -#: ../edit.c:87 msgid " Tag completion (^]^N^P)" msgstr " ใฟใฐ่ฃๅฎ (^]^N^P)" -#: ../edit.c:88 msgid " Path pattern completion (^N^P)" msgstr " ใในใใฟใผใณ่ฃๅฎ (^N^P)" -#: ../edit.c:89 msgid " Definition completion (^D^N^P)" msgstr " ๅฎ็พฉ่ฃๅฎ (^D^N^P)" -#: ../edit.c:91 msgid " Dictionary completion (^K^N^P)" msgstr " ่พๆธ่ฃๅฎ (^K^N^P)" -#: ../edit.c:92 msgid " Thesaurus completion (^T^N^P)" msgstr " ใทใฝใผใฉใน่ฃๅฎ (^T^N^P)" -#: ../edit.c:93 msgid " Command-line completion (^V^N^P)" msgstr " ใณใใณใใฉใคใณ่ฃๅฎ (^V^N^P)" -#: ../edit.c:94 msgid " User defined completion (^U^N^P)" msgstr " ใฆใผใถใผๅฎ็พฉ่ฃๅฎ (^U^N^P)" -#: ../edit.c:95 msgid " Omni completion (^O^N^P)" msgstr " ใชใ ใ่ฃๅฎ (^O^N^P)" -#: ../edit.c:96 msgid " Spelling suggestion (s^N^P)" msgstr " ็ถดใไฟฎๆญฃๅ่ฃ (s^N^P)" -#: ../edit.c:97 msgid " Keyword Local completion (^N^P)" msgstr " ๅฑๆใญใผใฏใผใ่ฃๅฎ (^N^P)" -#: ../edit.c:100 msgid "Hit end of paragraph" msgstr "ๆฎต่ฝใฎๆๅพใซใใใ" -#: ../edit.c:101 msgid "E839: Completion function changed window" msgstr "E839: ่ฃ้้ขๆฐใใฆใฃใณใใฆใๅคๆดใใพใใ" -#: ../edit.c:102 msgid "E840: Completion function deleted text" msgstr "E840: ่ฃๅฎ้ขๆฐใใใญในใใๅ้คใใพใใ" -#: ../edit.c:1847 msgid "'dictionary' option is empty" msgstr "'dictionary' ใชใใทใงใณใ็ฉบใงใ" -#: ../edit.c:1848 msgid "'thesaurus' option is empty" msgstr "'thesaurus' ใชใใทใงใณใ็ฉบใงใ" -#: ../edit.c:2655 #, c-format msgid "Scanning dictionary: %s" msgstr "่พๆธใในใญใฃใณไธญ: %s" -#: ../edit.c:3079 msgid " (insert) Scroll (^E/^Y)" msgstr " (ๆฟๅ
ฅ) ในใฏใญใผใซ(^E/^Y)" -#: ../edit.c:3081 msgid " (replace) Scroll (^E/^Y)" msgstr " (็ฝฎๆ) ในใฏใญใผใซ (^E/^Y)" -#: ../edit.c:3587 #, c-format msgid "Scanning: %s" msgstr "ในใญใฃใณไธญ: %s" -#: ../edit.c:3614 msgid "Scanning tags." msgstr "ใฟใฐใในใญใฃใณไธญ." -#: ../edit.c:4519 msgid " Adding" msgstr " ่ฟฝๅ ไธญ" @@ -441,430 +438,161 @@ msgstr " ่ฟฝๅ ไธญ" #. * be called before line = ml_get(), or when this address is no #. * longer needed. -- Acevedo. #. -#: ../edit.c:4562 msgid "-- Searching..." msgstr "-- ๆค็ดขไธญ..." -#: ../edit.c:4618 msgid "Back at original" msgstr "ๅงใใซๆปใ" -#: ../edit.c:4621 msgid "Word from other line" msgstr "ไปใฎ่กใฎๅ่ช" -#: ../edit.c:4624 msgid "The only match" msgstr "ๅฏไธใฎ่ฉฒๅฝ" -#: ../edit.c:4680 #, c-format msgid "match %d of %d" msgstr "%d ็ช็ฎใฎ่ฉฒๅฝ (ๅ
จ่ฉฒๅฝ %d ๅไธญ)" -#: ../edit.c:4684 #, c-format msgid "match %d" msgstr "%d ็ช็ฎใฎ่ฉฒๅฝ" -#: ../eval.c:137 +#. maximum nesting of lists and dicts msgid "E18: Unexpected characters in :let" msgstr "E18: ไบๆใใฌๆๅญใ :let ใซใใใพใใ" -#: ../eval.c:138 -#, c-format -msgid "E684: list index out of range: %<PRId64>" -msgstr "E684: ใชในใใฎใคใณใใใฏในใ็ฏๅฒๅคใงใ: %<PRId64>" - -#: ../eval.c:139 #, c-format msgid "E121: Undefined variable: %s" msgstr "E121: ๆชๅฎ็พฉใฎๅคๆฐใงใ: %s" -#: ../eval.c:140 msgid "E111: Missing ']'" msgstr "E111: ']' ใ่ฆใคใใใพใใ" -#: ../eval.c:141 -#, c-format -msgid "E686: Argument of %s must be a List" -msgstr "E686: %s ใฎๅผๆฐใฏใชในใๅใงใชใใใฐใชใใพใใ" - -#: ../eval.c:143 -#, c-format -msgid "E712: Argument of %s must be a List or Dictionary" -msgstr "E712: %s ใฎๅผๆฐใฏใชในใๅใพใใฏ่พๆธๅใงใชใใใฐใชใใพใใ" - -#: ../eval.c:144 -msgid "E713: Cannot use empty key for Dictionary" -msgstr "E713: ่พๆธๅใซ็ฉบใฎใญใผใไฝฟใใใจใฏใงใใพใใ" - -#: ../eval.c:145 -msgid "E714: List required" -msgstr "E714: ใชในใๅใๅฟ
่ฆใงใ" - -#: ../eval.c:146 -msgid "E715: Dictionary required" -msgstr "E715: ่พๆธๅใๅฟ
่ฆใงใ" - -#: ../eval.c:147 -#, c-format -msgid "E118: Too many arguments for function: %s" -msgstr "E118: ้ขๆฐใฎๅผๆฐใๅค้ใใพใ: %s" - -#: ../eval.c:148 -#, c-format -msgid "E716: Key not present in Dictionary: %s" -msgstr "E716: ่พๆธๅใซใญใผใๅญๅจใใพใใ: %s" - -#: ../eval.c:150 -#, c-format -msgid "E122: Function %s already exists, add ! to replace it" -msgstr "E122: ้ขๆฐ %s ใฏๅฎ็พฉๆธใงใ, ๅๅฎ็พฉใใใซใฏ ! ใ่ฟฝๅ ใใฆใใ ใใ" - -#: ../eval.c:151 -msgid "E717: Dictionary entry already exists" -msgstr "E717: ่พๆธๅๅ
ใซใจใณใใชใๆขใซๅญๅจใใพใ" - -#: ../eval.c:152 -msgid "E718: Funcref required" -msgstr "E718: ้ขๆฐๅ็
งๅใ่ฆๆฑใใใพใ" - -#: ../eval.c:153 msgid "E719: Cannot use [:] with a Dictionary" msgstr "E719: [:] ใ่พๆธๅใจ็ตใฟๅใใใฆใฏไฝฟใใพใใ" -#: ../eval.c:154 #, c-format msgid "E734: Wrong variable type for %s=" msgstr "E734: ็ฐใชใฃใๅใฎๅคๆฐใงใ %s=" -#: ../eval.c:155 -#, c-format -msgid "E130: Unknown function: %s" -msgstr "E130: ๆช็ฅใฎ้ขๆฐใงใ: %s" - -#: ../eval.c:156 #, c-format msgid "E461: Illegal variable name: %s" msgstr "E461: ไธๆญฃใชๅคๆฐๅใงใ: %s" -#: ../eval.c:157 msgid "E806: using Float as a String" msgstr "E806: ๆตฎๅๅฐๆฐ็นๆฐใๆๅญๅใจใใฆๆฑใฃใฆใใพใ" -#: ../eval.c:1830 msgid "E687: Less targets than List items" msgstr "E687: ใฟใผใฒใใใใชในใๅๅ
ใฎ่ฆ็ด ใใใๅฐใชใใงใ" -#: ../eval.c:1834 msgid "E688: More targets than List items" msgstr "E688: ใฟใผใฒใใใใชในใๅๅ
ใฎ่ฆ็ด ใใใๅคใใงใ" -#: ../eval.c:1906 msgid "Double ; in list of variables" msgstr "ใชในใๅใฎๅคใซ2ใคไปฅไธใฎ ; ใๆคๅบใใใพใใ" -#: ../eval.c:2078 #, c-format msgid "E738: Can't list variables for %s" msgstr "E738: %s ใฎๅคใไธ่ฆง่กจ็คบใงใใพใใ" -#: ../eval.c:2391 msgid "E689: Can only index a List or Dictionary" msgstr "E689: ใชในใๅใจ่พๆธๅไปฅๅคใฏใคใณใใใฏในๆๅฎใงใใพใใ" -#: ../eval.c:2396 msgid "E708: [:] must come last" msgstr "E708: [:] ใฏๆๅพใงใชใใใฐใใใพใใ" -#: ../eval.c:2439 msgid "E709: [:] requires a List value" msgstr "E709: [:] ใซใฏใชในใๅใฎๅคใๅฟ
่ฆใงใ" -#: ../eval.c:2674 msgid "E710: List value has more items than target" msgstr "E710: ใชในใๅๅคๆฐใซใฟใผใฒใใใใใๅคใ่ฆ็ด ใใใใพใ" -#: ../eval.c:2678 msgid "E711: List value has not enough items" msgstr "E711: ใชในใๅๅคๆฐใซๅๅใชๆฐใฎ่ฆ็ด ใใใใพใใ" # -#: ../eval.c:2867 msgid "E690: Missing \"in\" after :for" msgstr "E690: :for ใฎๅพใซ \"in\" ใใใใพใใ" -#: ../eval.c:3063 -#, c-format -msgid "E107: Missing parentheses: %s" -msgstr "E107: ใซใใณ '(' ใใใใพใใ: %s" - -#: ../eval.c:3263 #, c-format msgid "E108: No such variable: \"%s\"" msgstr "E108: ใใฎๅคๆฐใฏใใใพใใ: \"%s\"" -#: ../eval.c:3333 msgid "E743: variable nested too deep for (un)lock" msgstr "E743: (ใขใณ)ใญใใฏใใใซใฏๅคๆฐใฎๅ
ฅใๅญใๆทฑ้ใใพใ" -#: ../eval.c:3630 msgid "E109: Missing ':' after '?'" msgstr "E109: '?' ใฎๅพใซ ':' ใใใใพใใ" -#: ../eval.c:3893 msgid "E691: Can only compare List with List" msgstr "E691: ใชในใๅใฏใชในใๅใจใใๆฏ่ผใงใใพใใ" -#: ../eval.c:3895 -msgid "E692: Invalid operation for Lists" +msgid "E692: Invalid operation for List" msgstr "E692: ใชในใๅใซใฏ็กๅนใชๆไฝใงใ" -#: ../eval.c:3915 msgid "E735: Can only compare Dictionary with Dictionary" msgstr "E735: ่พๆธๅใฏ่พๆธๅใจใใๆฏ่ผใงใใพใใ" -#: ../eval.c:3917 msgid "E736: Invalid operation for Dictionary" msgstr "E736: ่พๆธๅใซใฏ็กๅนใชๆไฝใงใ" -#: ../eval.c:3932 -msgid "E693: Can only compare Funcref with Funcref" -msgstr "E693: ้ขๆฐๅ็
งๅใฏ้ขๆฐๅ็
งๅใจใใๆฏ่ผใงใใพใใ" - -#: ../eval.c:3934 msgid "E694: Invalid operation for Funcrefs" msgstr "E694: ้ขๆฐๅ็
งๅใซใฏ็กๅนใชๆไฝใงใ" -#: ../eval.c:4277 msgid "E804: Cannot use '%' with Float" msgstr "E804: '%' ใๆตฎๅๅฐๆฐ็นๆฐใจ็ตใฟๅใใใฆใฏไฝฟใใพใใ" -#: ../eval.c:4478 msgid "E110: Missing ')'" msgstr "E110: ')' ใ่ฆใคใใใพใใ" -#: ../eval.c:4609 msgid "E695: Cannot index a Funcref" msgstr "E695: ้ขๆฐๅ็
งๅใฏใคใณใใใฏในใงใใพใใ" -#: ../eval.c:4839 +msgid "E909: Cannot index a special variable" +msgstr "E909: ็นๆฎๅคๆฐใฏใคใณใใใฏในใงใใพใใ" + #, c-format msgid "E112: Option name missing: %s" msgstr "E112: ใชใใทใงใณๅใใใใพใใ: %s" -#: ../eval.c:4855 #, c-format msgid "E113: Unknown option: %s" msgstr "E113: ๆช็ฅใฎใชใใทใงใณใงใ: %s" -#: ../eval.c:4904 #, c-format msgid "E114: Missing quote: %s" msgstr "E114: ๅผ็จ็ฌฆ (\") ใใใใพใใ: %s" -#: ../eval.c:5020 #, c-format msgid "E115: Missing quote: %s" msgstr "E115: ๅผ็จ็ฌฆ (') ใใใใพใใ: %s" -#: ../eval.c:5084 -#, c-format -msgid "E696: Missing comma in List: %s" -msgstr "E696: ใชในใๅใซใซใณใใใใใพใใ: %s" - -#: ../eval.c:5091 -#, c-format -msgid "E697: Missing end of List ']': %s" -msgstr "E697: ใชในใๅใฎๆๅพใซ ']' ใใใใพใใ: %s" - msgid "Not enough memory to set references, garbage collection aborted!" msgstr "" "ใฌใผใใใธใณใฌใฏใทใงใณใไธญๆญขใใพใใ! ๅ็
งใไฝๆใใใฎใซใกใขใชใไธ่ถณใใพใใ" -#: ../eval.c:6475 -#, c-format -msgid "E720: Missing colon in Dictionary: %s" -msgstr "E720: ่พๆธๅใซใณใญใณใใใใพใใ: %s" - -#: ../eval.c:6499 -#, c-format -msgid "E721: Duplicate key in Dictionary: \"%s\"" -msgstr "E721: ่พๆธๅใซ้่คใญใผใใใใพใ: \"%s\"" - -#: ../eval.c:6517 -#, c-format -msgid "E722: Missing comma in Dictionary: %s" -msgstr "E722: ่พๆธๅใซใซใณใใใใใพใใ: %s" - -#: ../eval.c:6524 -#, c-format -msgid "E723: Missing end of Dictionary '}': %s" -msgstr "E723: ่พๆธๅใฎๆๅพใซ '}' ใใใใพใใ: %s" - -#: ../eval.c:6555 msgid "E724: variable nested too deep for displaying" msgstr "E724: ่กจ็คบใใใซใฏๅคๆฐใฎๅ
ฅใๅญใๆทฑ้ใใพใ" -#: ../eval.c:7188 -#, c-format -msgid "E740: Too many arguments for function %s" -msgstr "E740: ้ขๆฐใฎๅผๆฐใๅค้ใใพใ: %s" - -#: ../eval.c:7190 -#, c-format -msgid "E116: Invalid arguments for function %s" -msgstr "E116: ้ขๆฐใฎ็กๅนใชๅผๆฐใงใ: %s" - -#: ../eval.c:7377 -#, c-format -msgid "E117: Unknown function: %s" -msgstr "E117: ๆช็ฅใฎ้ขๆฐใงใ: %s" - -#: ../eval.c:7383 -#, c-format -msgid "E119: Not enough arguments for function: %s" -msgstr "E119: ้ขๆฐใฎๅผๆฐใ่ถณใใพใใ: %s" - -#: ../eval.c:7387 -#, c-format -msgid "E120: Using <SID> not in a script context: %s" -msgstr "E120: ในใฏใชใใไปฅๅคใง<SID>ใไฝฟใใใพใใ: %s" - -#: ../eval.c:7391 -#, c-format -msgid "E725: Calling dict function without Dictionary: %s" -msgstr "E725: ่พๆธ็จ้ขๆฐใๅผใฐใใพใใใ่พๆธใใใใพใใ: %s" - -#: ../eval.c:7453 -msgid "E808: Number or Float required" -msgstr "E808: ๆฐๅคใๆตฎๅๅฐๆฐ็นๆฐใๅฟ
่ฆใงใ" - -#: ../eval.c:7503 -msgid "add() argument" -msgstr "add() ใฎๅผๆฐ" - -#: ../eval.c:7907 -msgid "E699: Too many arguments" -msgstr "E699: ๅผๆฐใๅค้ใใพใ" - -#: ../eval.c:8073 -msgid "E785: complete() can only be used in Insert mode" -msgstr "E785: complete() ใฏๆฟๅ
ฅใขใผใใงใใๅฉ็จใงใใพใใ" - -#: ../eval.c:8156 -msgid "&Ok" -msgstr "&Ok" - -#: ../eval.c:8676 -#, c-format -msgid "E737: Key already exists: %s" -msgstr "E737: ใญใผใฏๆขใซๅญๅจใใพใ: %s" - -#: ../eval.c:8692 -msgid "extend() argument" -msgstr "extend() ใฎๅผๆฐ" - -#: ../eval.c:8915 -msgid "map() argument" -msgstr "map() ใฎๅผๆฐ" - -#: ../eval.c:8916 -msgid "filter() argument" -msgstr "filter() ใฎๅผๆฐ" - -#: ../eval.c:9229 -#, c-format -msgid "+-%s%3ld lines: " -msgstr "+-%s%3ld ่ก: " - -#: ../eval.c:9291 -#, c-format -msgid "E700: Unknown function: %s" -msgstr "E700: ๆช็ฅใฎ้ขๆฐใงใ: %s" - -#: ../eval.c:10729 -msgid "called inputrestore() more often than inputsave()" -msgstr "inputrestore() ใ inputsave() ใใใๅคใๅผใฐใใพใใ" - -#: ../eval.c:10771 -msgid "insert() argument" -msgstr "insert() ใฎๅผๆฐ" - -#: ../eval.c:10841 -msgid "E786: Range not allowed" -msgstr "E786: ็ฏๅฒๆๅฎใฏ่จฑๅฏใใใฆใใพใใ" - -#: ../eval.c:11140 -msgid "E701: Invalid type for len()" -msgstr "E701: len() ใซใฏ็กๅนใชๅใงใ" - -#: ../eval.c:11980 -msgid "E726: Stride is zero" -msgstr "E726: ในใใฉใคใ(ๅ้ฒ้)ใ 0 ใงใ" - -#: ../eval.c:11982 -msgid "E727: Start past end" -msgstr "E727: ้ๅงไฝ็ฝฎใ็ตไบไฝ็ฝฎใ่ถใใพใใ" - -#: ../eval.c:12024 ../eval.c:15297 -msgid "<empty>" -msgstr "<็ฉบ>" - -#: ../eval.c:12282 -msgid "remove() argument" -msgstr "remove() ใฎๅผๆฐ" - -# Added at 10-Mar-2004. -#: ../eval.c:12466 -msgid "E655: Too many symbolic links (cycle?)" -msgstr "E655: ใทใณใใชใใฏใชใณใฏใๅค้ใใพใ (ๅพช็ฐใใฆใใๅฏ่ฝๆงใใใใพใ)" - -#: ../eval.c:12593 -msgid "reverse() argument" -msgstr "reverse() ใฎๅผๆฐ" - -#: ../eval.c:13721 -msgid "sort() argument" -msgstr "sort() ใฎๅผๆฐ" - -#: ../eval.c:13721 -msgid "uniq() argument" -msgstr "uniq() ใฎๅผๆฐ" - -#: ../eval.c:13776 -msgid "E702: Sort compare function failed" -msgstr "E702: ใฝใผใใฎๆฏ่ผ้ขๆฐใๅคฑๆใใพใใ" - -#: ../eval.c:13806 -msgid "E882: Uniq compare function failed" -msgstr "E882: Uniq ใฎๆฏ่ผ้ขๆฐใๅคฑๆใใพใใ" - -#: ../eval.c:14085 -msgid "(Invalid)" -msgstr "(็กๅน)" - -#: ../eval.c:14590 -msgid "E677: Error writing temp file" -msgstr "E677: ไธๆใใกใคใซๆธ่พผไธญใซใจใฉใผใ็บ็ใใพใใ" - -#: ../eval.c:16159 msgid "E805: Using a Float as a Number" msgstr "E805: ๆตฎๅๅฐๆฐ็นๆฐใๆฐๅคใจใใฆๆฑใฃใฆใใพใ" -#: ../eval.c:16162 msgid "E703: Using a Funcref as a Number" msgstr "E703: ้ขๆฐๅ็
งๅใๆฐๅคใจใใฆๆฑใฃใฆใใพใใ" -#: ../eval.c:16170 msgid "E745: Using a List as a Number" msgstr "E745: ใชในใๅใๆฐๅคใจใใฆๆฑใฃใฆใใพใ" -#: ../eval.c:16173 msgid "E728: Using a Dictionary as a Number" msgstr "E728: ่พๆธๅใๆฐๅคใจใใฆๆฑใฃใฆใใพใ" +msgid "E910: Using a Job as a Number" +msgstr "E910: ใธใงใใๆฐๅคใจใใฆๆฑใฃใฆใใพใ" + +msgid "E913: Using a Channel as a Number" +msgstr "E913: ใใฃใณใใซใๆฐๅคใจใใฆๆฑใฃใฆใใพใใ" + msgid "E891: Using a Funcref as a Float" msgstr "E891: ้ขๆฐๅ็
งๅใๆตฎๅๅฐๆฐ็นๆฐใจใใฆๆฑใฃใฆใใพใใ" @@ -877,265 +605,280 @@ msgstr "E893: ใชในใๅใๆตฎๅๅฐๆฐ็นๆฐใจใใฆๆฑใฃใฆใใพใ" msgid "E894: Using a Dictionary as a Float" msgstr "E894: ่พๆธๅใๆตฎๅๅฐๆฐ็นๆฐใจใใฆๆฑใฃใฆใใพใ" -#: ../eval.c:16259 +msgid "E907: Using a special value as a Float" +msgstr "E907: ็นๆฎๅคใๆตฎๅๅฐๆฐ็นๆฐใจใใฆๆฑใฃใฆใใพใ" + +msgid "E911: Using a Job as a Float" +msgstr "E911: ใธใงใใๆตฎๅๅฐๆฐ็นๆฐใจใใฆๆฑใฃใฆใใพใ" + +msgid "E914: Using a Channel as a Float" +msgstr "E914: ใใฃใณใใซใๆตฎๅๅฐๆฐ็นๆฐใจใใฆๆฑใฃใฆใใพใใ" + msgid "E729: using Funcref as a String" msgstr "E729: ้ขๆฐๅ็
งๅใๆๅญๅใจใใฆๆฑใฃใฆใใพใ" -#: ../eval.c:16262 msgid "E730: using List as a String" msgstr "E730: ใชในใๅใๆๅญๅใจใใฆๆฑใฃใฆใใพใ" -#: ../eval.c:16265 msgid "E731: using Dictionary as a String" msgstr "E731: ่พๆธๅใๆๅญๅใจใใฆๆฑใฃใฆใใพใ" -#: ../eval.c:16619 -#, c-format -msgid "E706: Variable type mismatch for: %s" -msgstr "E706: ๅคๆฐใฎๅใไธ่ดใใพใใ: %s" +msgid "E908: using an invalid value as a String" +msgstr "E908: ็กๅนใชๅคใๆๅญๅใจใใฆๆฑใฃใฆใใพใ" -#: ../eval.c:16705 #, c-format msgid "E795: Cannot delete variable %s" msgstr "E795: ๅคๆฐ %s ใๅ้คใงใใพใใ" -#: ../eval.c:16724 #, c-format msgid "E704: Funcref variable name must start with a capital: %s" msgstr "E704: ้ขๆฐๅ็
งๅๅคๆฐๅใฏๅคงๆๅญใงๅงใพใใชใใใฐใชใใพใใ: %s" -#: ../eval.c:16732 #, c-format msgid "E705: Variable name conflicts with existing function: %s" msgstr "E705: ๅคๆฐๅใๆขๅญใฎ้ขๆฐๅใจ่ก็ชใใพใ: %s" -#: ../eval.c:16763 #, c-format msgid "E741: Value is locked: %s" msgstr "E741: ๅคใใญใใฏใใใฆใใพใ: %s" -#: ../eval.c:16764 ../eval.c:16769 ../message.c:1839 msgid "Unknown" msgstr "ไธๆ" -#: ../eval.c:16768 #, c-format msgid "E742: Cannot change value of %s" msgstr "E742: %s ใฎๅคใๅคๆดใงใใพใใ" -#: ../eval.c:16838 msgid "E698: variable nested too deep for making a copy" msgstr "E698: ใณใใผใๅใใซใฏๅคๆฐใฎๅ
ฅใๅญใๆทฑ้ใใพใ" -#: ../eval.c:17249 -#, c-format -msgid "E123: Undefined function: %s" -msgstr "E123: ๆชๅฎ็พฉใฎ้ขๆฐใงใ: %s" +msgid "" +"\n" +"# global variables:\n" +msgstr "" +"\n" +"# ใฐใญใผใใซๅคๆฐ:\n" -#: ../eval.c:17260 -#, c-format -msgid "E124: Missing '(': %s" -msgstr "E124: '(' ใใใใพใใ: %s" +msgid "" +"\n" +"\tLast set from " +msgstr "" +"\n" +"\tๆๅพใซใปใใใใในใฏใชใใ: " -#: ../eval.c:17293 -msgid "E862: Cannot use g: here" -msgstr "E862: ใใใงใฏ g: ใฏไฝฟใใพใใ" +msgid "map() argument" +msgstr "map() ใฎๅผๆฐ" -#: ../eval.c:17312 -#, c-format -msgid "E125: Illegal argument: %s" -msgstr "E125: ไธๆญฃใชๅผๆฐใงใ: %s" +msgid "filter() argument" +msgstr "filter() ใฎๅผๆฐ" -#: ../eval.c:17323 #, c-format -msgid "E853: Duplicate argument name: %s" -msgstr "E853: ๅผๆฐๅใ้่คใใฆใใพใ: %s" +msgid "E686: Argument of %s must be a List" +msgstr "E686: %s ใฎๅผๆฐใฏใชในใๅใงใชใใใฐใชใใพใใ" -#: ../eval.c:17416 -msgid "E126: Missing :endfunction" -msgstr "E126: :endfunction ใใใใพใใ" +msgid "E928: String required" +msgstr "E928: ๆๅญๅใๅฟ
่ฆใงใ" -#: ../eval.c:17537 -#, c-format -msgid "E707: Function name conflicts with variable: %s" -msgstr "E707: ้ขๆฐๅใๅคๆฐๅใจ่ก็ชใใพใ: %s" +msgid "E808: Number or Float required" +msgstr "E808: ๆฐๅคใๆตฎๅๅฐๆฐ็นๆฐใๅฟ
่ฆใงใ" -#: ../eval.c:17549 -#, c-format -msgid "E127: Cannot redefine function %s: It is in use" -msgstr "E127: ้ขๆฐ %s ใๅๅฎ็พฉใงใใพใใ: ไฝฟ็จไธญใงใ" +msgid "add() argument" +msgstr "add() ใฎๅผๆฐ" -#: ../eval.c:17604 -#, c-format -msgid "E746: Function name does not match script file name: %s" -msgstr "E746: ้ขๆฐๅใในใฏใชใใใฎใใกใคใซๅใจไธ่ดใใพใใ: %s" +msgid "E785: complete() can only be used in Insert mode" +msgstr "E785: complete() ใฏๆฟๅ
ฅใขใผใใงใใๅฉ็จใงใใพใใ" -#: ../eval.c:17716 -msgid "E129: Function name required" -msgstr "E129: ้ขๆฐๅใ่ฆๆฑใใใพใ" +#. +#. * Yes this is ugly, I don't particularly like it either. But doing it +#. * this way has the compelling advantage that translations need not to +#. * be touched at all. See below what 'ok' and 'ync' are used for. +#. +msgid "&Ok" +msgstr "&Ok" -#: ../eval.c:17824 #, c-format -msgid "E128: Function name must start with a capital or \"s:\": %s" -msgstr "E128: ้ขๆฐๅใฏๅคงๆๅญใ \"s:\" ใงๅงใพใใชใใใฐใชใใพใใ: %s" +msgid "+-%s%3ld line: " +msgid_plural "+-%s%3ld lines: " +msgstr[0] "+-%s%3ld ่ก: " -#: ../eval.c:17833 #, c-format -msgid "E884: Function name cannot contain a colon: %s" -msgstr "E884: ้ขๆฐๅใซใฏใณใญใณใฏๅซใใใใพใใ: %s" +msgid "E700: Unknown function: %s" +msgstr "E700: ๆช็ฅใฎ้ขๆฐใงใ: %s" -#: ../eval.c:18336 -#, c-format -msgid "E131: Cannot delete function %s: It is in use" -msgstr "E131: ้ขๆฐ %s ใๅ้คใงใใพใใ: ไฝฟ็จไธญใงใ" +msgid "E922: expected a dict" +msgstr "E922: ่พๆธใๆๅพ
ใใใฆใใพใ" -#: ../eval.c:18441 -msgid "E132: Function call depth is higher than 'maxfuncdepth'" -msgstr "E132: ้ขๆฐๅผๅบใฎๅ
ฅใๅญๆฐใ 'maxfuncdepth' ใ่ถ
ใใพใใ" +msgid "E923: Second argument of function() must be a list or a dict" +msgstr "E923: function() ใฎ็ฌฌ 2 ๅผๆฐใฏใชในใๅใพใใฏ่พๆธๅใงใชใใใฐใชใใพใใ" -#: ../eval.c:18568 -#, c-format -msgid "calling %s" -msgstr "%s ใๅฎ่กไธญใงใ" +msgid "" +"&OK\n" +"&Cancel" +msgstr "" +"ๆฑบๅฎ(&O)\n" +"ใญใฃใณใปใซ(&C)" -#: ../eval.c:18651 -#, c-format -msgid "%s aborted" -msgstr "%s ใไธญๆญใใใพใใ" +msgid "called inputrestore() more often than inputsave()" +msgstr "inputrestore() ใ inputsave() ใใใๅคใๅผใฐใใพใใ" + +msgid "insert() argument" +msgstr "insert() ใฎๅผๆฐ" + +msgid "E786: Range not allowed" +msgstr "E786: ็ฏๅฒๆๅฎใฏ่จฑๅฏใใใฆใใพใใ" + +msgid "E916: not a valid job" +msgstr "E916: ๆๅนใชใธใงใใงใฏใใใพใใ" + +msgid "E701: Invalid type for len()" +msgstr "E701: len() ใซใฏ็กๅนใชๅใงใ" -#: ../eval.c:18653 #, c-format -msgid "%s returning #%<PRId64>" -msgstr "%s ใ #%<PRId64> ใ่ฟใใพใใ" +msgid "E798: ID is reserved for \":match\": %ld" +msgstr "E798: ID ใฏ \":match\" ใฎใใใซไบ็ดใใใฆใใพใ: %ld" + +msgid "E726: Stride is zero" +msgstr "E726: ในใใฉใคใ(ๅ้ฒ้)ใ 0 ใงใ" + +msgid "E727: Start past end" +msgstr "E727: ้ๅงไฝ็ฝฎใ็ตไบไฝ็ฝฎใ่ถใใพใใ" + +msgid "<empty>" +msgstr "<็ฉบ>" + +msgid "E240: No connection to Vim server" +msgstr "E240: Vim ใตใผใใผใธใฎๆฅ็ถใใใใพใใ" -#: ../eval.c:18670 #, c-format -msgid "%s returning %s" -msgstr "%s ใ %s ใ่ฟใใพใใ" +msgid "E241: Unable to send to %s" +msgstr "E241: %s ใธ้ใใใจใใงใใพใใ" + +msgid "E277: Unable to read a server reply" +msgstr "E277: ใตใผใใผใฎๅฟ็ญใใใใพใใ" + +msgid "remove() argument" +msgstr "remove() ใฎๅผๆฐ" + +# Added at 10-Mar-2004. +msgid "E655: Too many symbolic links (cycle?)" +msgstr "E655: ใทใณใใชใใฏใชใณใฏใๅค้ใใพใ (ๅพช็ฐใใฆใใๅฏ่ฝๆงใใใใพใ)" + +msgid "reverse() argument" +msgstr "reverse() ใฎๅผๆฐ" + +msgid "E258: Unable to send to client" +msgstr "E258: ใฏใฉใคใขใณใใธ้ใใใจใใงใใพใใ" -#: ../eval.c:18691 ../ex_cmds2.c:2695 #, c-format -msgid "continuing in %s" -msgstr "%s ใฎๅฎ่กใ็ถ็ถไธญใงใ" +msgid "E927: Invalid action: '%s'" +msgstr "E927: ็กๅนใชๆไฝใงใ: %s" -#: ../eval.c:18795 -msgid "E133: :return not inside a function" -msgstr "E133: ้ขๆฐๅคใซ :return ใใใใพใใ" +msgid "sort() argument" +msgstr "sort() ใฎๅผๆฐ" -#: ../eval.c:19159 -msgid "" -"\n" -"# global variables:\n" -msgstr "" -"\n" -"# ใฐใญใผใใซๅคๆฐ:\n" +msgid "uniq() argument" +msgstr "uniq() ใฎๅผๆฐ" -#: ../eval.c:19254 -msgid "" -"\n" -"\tLast set from " -msgstr "" -"\n" -"\tLast set from " +msgid "E702: Sort compare function failed" +msgstr "E702: ใฝใผใใฎๆฏ่ผ้ขๆฐใๅคฑๆใใพใใ" -#: ../eval.c:19272 -msgid "No old files" -msgstr "ๅคใใใกใคใซใฏใใใพใใ" +msgid "E882: Uniq compare function failed" +msgstr "E882: Uniq ใฎๆฏ่ผ้ขๆฐใๅคฑๆใใพใใ" + +msgid "(Invalid)" +msgstr "(็กๅน)" + +#, c-format +msgid "E935: invalid submatch number: %d" +msgstr "E935: ็กๅนใชใตใใใใ็ชๅท: %d" + +msgid "E677: Error writing temp file" +msgstr "E677: ไธๆใใกใคใซๆธ่พผไธญใซใจใฉใผใ็บ็ใใพใใ" + +msgid "E921: Invalid callback argument" +msgstr "E921: ็กๅนใชใณใผใซใใใฏๅผๆฐใงใ" -#: ../ex_cmds.c:122 #, c-format msgid "<%s>%s%s %d, Hex %02x, Octal %03o" msgstr "<%s>%s%s %d, 16้ฒๆฐ %02x, 8้ฒๆฐ %03o" -#: ../ex_cmds.c:145 #, c-format msgid "> %d, Hex %04x, Octal %o" msgstr "> %d, 16้ฒๆฐ %04x, 8้ฒๆฐ %o" -#: ../ex_cmds.c:146 #, c-format msgid "> %d, Hex %08x, Octal %o" msgstr "> %d, 16้ฒๆฐ %08x, 8้ฒๆฐ %o" -#: ../ex_cmds.c:684 msgid "E134: Move lines into themselves" msgstr "E134: ่กใใใ่ช่บซใซใฏ็งปๅใงใใพใใ" -#: ../ex_cmds.c:747 msgid "1 line moved" msgstr "1 ่กใ็งปๅใใใพใใ" -#: ../ex_cmds.c:749 #, c-format -msgid "%<PRId64> lines moved" -msgstr "%<PRId64> ่กใ็งปๅใใใพใใ" +msgid "%ld lines moved" +msgstr "%ld ่กใ็งปๅใใใพใใ" -#: ../ex_cmds.c:1175 #, c-format -msgid "%<PRId64> lines filtered" -msgstr "%<PRId64> ่กใใใฃใซใฟๅฆ็ใใใพใใ" +msgid "%ld lines filtered" +msgstr "%ld ่กใใใฃใซใฟๅฆ็ใใใพใใ" -#: ../ex_cmds.c:1194 msgid "E135: *Filter* Autocommands must not change current buffer" msgstr "E135: *ใใฃใซใฟ* autocommandใฏ็พๅจใฎใใใใกใๅคๆดใใฆใฏใใใพใใ" -#: ../ex_cmds.c:1244 msgid "[No write since last change]\n" msgstr "[ๆๅพใฎๅคๆดใไฟๅญใใใฆใใพใใ]\n" -#: ../ex_cmds.c:1424 #, c-format msgid "%sviminfo: %s in line: " msgstr "%sviminfo: %s ่ก็ฎ: " -#: ../ex_cmds.c:1431 msgid "E136: viminfo: Too many errors, skipping rest of file" msgstr "E136: viminfo: ใจใฉใผใๅค้ใใใฎใง, ไปฅ้ใฏในใญใใใใพใ" -#: ../ex_cmds.c:1458 #, c-format msgid "Reading viminfo file \"%s\"%s%s%s" msgstr "viminfoใใกใคใซ \"%s\"%s%s%s ใ่ชญ่พผใฟไธญ" -#: ../ex_cmds.c:1460 msgid " info" msgstr " ๆ
ๅ ฑ" -#: ../ex_cmds.c:1461 msgid " marks" msgstr " ใใผใฏ" -#: ../ex_cmds.c:1462 msgid " oldfiles" msgstr " ๆงใใกใคใซ็พค" -#: ../ex_cmds.c:1463 msgid " FAILED" msgstr " ๅคฑๆ" #. avoid a wait_return for this message, it's annoying -#: ../ex_cmds.c:1541 #, c-format msgid "E137: Viminfo file is not writable: %s" msgstr "E137: viminfoใใกใคใซใๆธ่พผใฟใงใใพใใ: %s" -#: ../ex_cmds.c:1626 +#, c-format +msgid "E929: Too many viminfo temp files, like %s!" +msgstr "E929: ไธๆviminfoใใกใคใซใๅค้ใใพใ! ไพ: %s" + #, c-format msgid "E138: Can't write viminfo file %s!" msgstr "E138: viminfoใใกใคใซ %s ใไฟๅญใงใใพใใ!" -#: ../ex_cmds.c:1635 #, c-format msgid "Writing viminfo file \"%s\"" msgstr "viminfoใใกใคใซ \"%s\" ใๆธ่พผใฟไธญ" +#, c-format +msgid "E886: Can't rename viminfo file to %s!" +msgstr "E886: viminfoใใกใคใซใ %s ใธๅๅๅคๆดใงใใพใใ!" + #. Write the info: -#: ../ex_cmds.c:1720 #, c-format msgid "# This viminfo file was generated by Vim %s.\n" msgstr "# ใใฎ viminfo ใใกใคใซใฏ Vim %s ใซใใฃใฆ็ๆใใใพใใ.\n" -#: ../ex_cmds.c:1722 msgid "" "# You may edit it if you're careful!\n" "\n" @@ -1143,47 +886,47 @@ msgstr "" "# ๅคๆดใใ้ใซใฏๅๅๆณจๆใใฆใใ ใใ!\n" "\n" -#: ../ex_cmds.c:1723 msgid "# Value of 'encoding' when this file was written\n" msgstr "# ใใฎใใกใคใซใๆธใใใๆใฎ 'encoding' ใฎๅค\n" -#: ../ex_cmds.c:1800 msgid "Illegal starting char" msgstr "ไธๆญฃใชๅ
้ ญๆๅญใงใ" -#: ../ex_cmds.c:2162 +msgid "" +"\n" +"# Bar lines, copied verbatim:\n" +msgstr "" +"\n" +"# '|' ใงๅงใพใ่กใฎใๆๅญ้ใใฎใณใใผ:\n" + +msgid "Save As" +msgstr "ๅฅๅใงไฟๅญ" + msgid "Write partial file?" msgstr "ใใกใคใซใ้จๅ็ใซไฟๅญใใพใใ?" -#: ../ex_cmds.c:2166 msgid "E140: Use ! to write partial buffer" msgstr "E140: ใใใใกใ้จๅ็ใซไฟๅญใใใซใฏ ! ใไฝฟใฃใฆใใ ใใ" -#: ../ex_cmds.c:2281 #, c-format msgid "Overwrite existing file \"%s\"?" msgstr "ๆขๅญใฎใใกใคใซ \"%s\" ใไธๆธใใใพใใ?" -#: ../ex_cmds.c:2317 #, c-format msgid "Swap file \"%s\" exists, overwrite anyway?" msgstr "ในใฏใใใใกใคใซ \"%s\" ใๅญๅจใใพใ. ไธๆธใใๅผทๅถใใพใใ?" -#: ../ex_cmds.c:2326 #, c-format msgid "E768: Swap file exists: %s (:silent! overrides)" msgstr "E768: ในใฏใใใใกใคใซใๅญๅจใใพใ: %s (:silent! ใ่ฟฝๅ ใงไธๆธ)" -#: ../ex_cmds.c:2381 #, c-format -msgid "E141: No file name for buffer %<PRId64>" -msgstr "E141: ใใใใก %<PRId64> ใซใฏๅๅใใใใพใใ" +msgid "E141: No file name for buffer %ld" +msgstr "E141: ใใใใก %ld ใซใฏๅๅใใใใพใใ" -#: ../ex_cmds.c:2412 msgid "E142: File not written: Writing is disabled by 'write' option" msgstr "E142: ใใกใคใซใฏไฟๅญใใใพใใใงใใ: 'write' ใชใใทใงใณใซใใ็กๅนใงใ" -#: ../ex_cmds.c:2434 #, c-format msgid "" "'readonly' option is set for \"%s\".\n" @@ -1192,7 +935,6 @@ msgstr "" "\"%s\" ใซใฏ 'readonly' ใชใใทใงใณใ่จญๅฎใใใฆใใพใ.\n" "ไธๆธใๅผทๅถใใใพใใ?" -#: ../ex_cmds.c:2439 #, c-format msgid "" "File permissions of \"%s\" are read-only.\n" @@ -1203,83 +945,68 @@ msgstr "" "ใใใงใๆใใๆธใ่พผใใใจใฏๅฏ่ฝใงใ.\n" "็ถ็ถใใพใใ?" -#: ../ex_cmds.c:2451 #, c-format msgid "E505: \"%s\" is read-only (add ! to override)" msgstr "E505: \"%s\" ใฏ่ชญ่พผๅฐ็จใงใ (ๅผทๅถๆธ่พผใซใฏ ! ใ่ฟฝๅ )" -#: ../ex_cmds.c:3120 +msgid "Edit File" +msgstr "ใใกใคใซใ็ทจ้" + #, c-format msgid "E143: Autocommands unexpectedly deleted new buffer %s" msgstr "E143: autocommandใไบๆใใๆฐใใใใใใก %s ใๅ้คใใพใใ" -#: ../ex_cmds.c:3313 msgid "E144: non-numeric argument to :z" msgstr "E144: ๆฐใงใฏใชใๅผๆฐใ :z ใซๆธกใใใพใใ" -#: ../ex_cmds.c:3404 msgid "E145: Shell commands not allowed in rvim" msgstr "E145: rvimใงใฏใทใงใซใณใใณใใไฝฟใใพใใ" -#: ../ex_cmds.c:3498 msgid "E146: Regular expressions can't be delimited by letters" msgstr "E146: ๆญฃ่ฆ่กจ็พใฏๆๅญใงๅบๅใใใจใใงใใพใใ" -#: ../ex_cmds.c:3964 #, c-format msgid "replace with %s (y/n/a/q/l/^E/^Y)?" msgstr "%s ใซ็ฝฎๆใใพใใ? (y/n/a/q/l/^E/^Y)" -#: ../ex_cmds.c:4379 msgid "(Interrupted) " msgstr "(ๅฒ่พผใพใใพใใ) " -#: ../ex_cmds.c:4384 msgid "1 match" msgstr "1 ็ฎๆ่ฉฒๅฝใใพใใ" -#: ../ex_cmds.c:4384 msgid "1 substitution" msgstr "1 ็ฎๆ็ฝฎๆใใพใใ" -#: ../ex_cmds.c:4387 #, c-format -msgid "%<PRId64> matches" -msgstr "%<PRId64> ็ฎๆ่ฉฒๅฝใใพใใ" +msgid "%ld matches" +msgstr "%ld ็ฎๆ่ฉฒๅฝใใพใใ" -#: ../ex_cmds.c:4388 #, c-format -msgid "%<PRId64> substitutions" -msgstr "%<PRId64> ็ฎๆ็ฝฎๆใใพใใ" +msgid "%ld substitutions" +msgstr "%ld ็ฎๆ็ฝฎๆใใพใใ" -#: ../ex_cmds.c:4392 msgid " on 1 line" msgstr " (่จ 1 ่กๅ
)" -#: ../ex_cmds.c:4395 #, c-format -msgid " on %<PRId64> lines" -msgstr " (่จ %<PRId64> ่กๅ
)" +msgid " on %ld lines" +msgstr " (่จ %ld ่กๅ
)" -#: ../ex_cmds.c:4438 msgid "E147: Cannot do :global recursive" msgstr "E147: :global ใๅๅธฐ็ใซใฏไฝฟใใพใใ" -#: ../ex_cmds.c:4467 msgid "E148: Regular expression missing from global" msgstr "E148: globalใณใใณใใซๆญฃ่ฆ่กจ็พใๆๅฎใใใฆใใพใใ" -#: ../ex_cmds.c:4508 #, c-format msgid "Pattern found in every line: %s" msgstr "ใใฟใผใณใๅ
จใฆใฎ่กใง่ฆใคใใใพใใ: %s" -#: ../ex_cmds.c:4510 #, c-format msgid "Pattern not found: %s" msgstr "ใใฟใผใณใฏ่ฆใคใใใพใใใงใใ: %s" -#: ../ex_cmds.c:4587 msgid "" "\n" "# Last Substitute String:\n" @@ -1289,110 +1016,102 @@ msgstr "" "# ๆๅพใซ็ฝฎๆใใใๆๅญๅ:\n" "$" -#: ../ex_cmds.c:4679 msgid "E478: Don't panic!" msgstr "E478: ๆ
ใฆใชใใงใใ ใใ" -#: ../ex_cmds.c:4717 #, c-format msgid "E661: Sorry, no '%s' help for %s" msgstr "E661: ๆฎๅฟตใงใใ '%s' ใฎใใซใใ %s ใซใฏใใใพใใ" -#: ../ex_cmds.c:4719 #, c-format msgid "E149: Sorry, no help for %s" msgstr "E149: ๆฎๅฟตใงใใ %s ใซใฏใใซใใใใใพใใ" -#: ../ex_cmds.c:4751 #, c-format msgid "Sorry, help file \"%s\" not found" msgstr "ๆฎๅฟตใงใใใใซใใใกใคใซ \"%s\" ใ่ฆใคใใใพใใ" -#: ../ex_cmds.c:5323 #, c-format -msgid "E150: Not a directory: %s" -msgstr "E150: ใใฃใฌใฏใใชใงใฏใใใพใใ: %s" +msgid "E151: No match: %s" +msgstr "E151: ใใใใฏใใใพใใ: %s" -#: ../ex_cmds.c:5446 #, c-format msgid "E152: Cannot open %s for writing" msgstr "E152: ๆธ่พผใฟ็จใซ %s ใ้ใใพใใ" -#: ../ex_cmds.c:5471 #, c-format msgid "E153: Unable to open %s for reading" msgstr "E153: ่ชญ่พผ็จใซ %s ใ้ใใพใใ" # Added at 29-Apr-2004. -#: ../ex_cmds.c:5500 #, c-format msgid "E670: Mix of help file encodings within a language: %s" msgstr "E670: 1ใคใฎ่จ่ชใฎใใซใใใกใคใซใซ่คๆฐใฎใจใณใณใผใใๆททๅจใใฆใใพใ: %s" -#: ../ex_cmds.c:5565 #, c-format msgid "E154: Duplicate tag \"%s\" in file %s/%s" msgstr "E154: ใฟใฐ \"%s\" ใใใกใคใซ %s/%s ใซ้่คใใฆใใพใ" -#: ../ex_cmds.c:5687 +#, c-format +msgid "E150: Not a directory: %s" +msgstr "E150: ใใฃใฌใฏใใชใงใฏใใใพใใ: %s" + #, c-format msgid "E160: Unknown sign command: %s" msgstr "E160: ๆช็ฅใฎsignใณใใณใใงใ: %s" -#: ../ex_cmds.c:5704 msgid "E156: Missing sign name" msgstr "E156: signๅใใใใพใใ" -#: ../ex_cmds.c:5746 msgid "E612: Too many signs defined" msgstr "E612: signใฎๅฎ็พฉใๅคๆฐ่ฆใคใใใพใใ" -#: ../ex_cmds.c:5813 #, c-format msgid "E239: Invalid sign text: %s" msgstr "E239: ็กๅนใชsignใฎใใญในใใงใ: %s" -#: ../ex_cmds.c:5844 ../ex_cmds.c:6035 #, c-format msgid "E155: Unknown sign: %s" msgstr "E155: ๆช็ฅใฎsignใงใ: %s" -#: ../ex_cmds.c:5877 msgid "E159: Missing sign number" msgstr "E159: signใฎ็ชๅทใใใใพใใ" -#: ../ex_cmds.c:5971 #, c-format msgid "E158: Invalid buffer name: %s" msgstr "E158: ็กๅนใชใใใใกๅใงใ: %s" -#: ../ex_cmds.c:6008 +msgid "E934: Cannot jump to a buffer that does not have a name" +msgstr "E934: ๅๅใฎ็กใใใใใกใธใฏใธใฃใณใใงใใพใใ" + #, c-format -msgid "E157: Invalid sign ID: %<PRId64>" -msgstr "E157: ็กๅนใชsign่ญๅฅๅญใงใ: %<PRId64>" +msgid "E157: Invalid sign ID: %ld" +msgstr "E157: ็กๅนใชsign่ญๅฅๅญใงใ: %ld" #, c-format msgid "E885: Not possible to change sign %s" msgstr "E885: ๅคๆดใงใใชใ sign ใงใ: %s" -#: ../ex_cmds.c:6066 +# Added at 27-Jan-2004. +msgid " (NOT FOUND)" +msgstr " (่ฆใคใใใพใใ)" + msgid " (not supported)" msgstr " (้ใตใใผใ)" -#: ../ex_cmds.c:6169 msgid "[Deleted]" msgstr "[ๅ้คๆธ]" -#: ../ex_cmds2.c:139 +msgid "No old files" +msgstr "ๅคใใใกใคใซใฏใใใพใใ" + msgid "Entering Debug mode. Type \"cont\" to continue." msgstr "ใใใใฐใขใผใใซๅ
ฅใใพใ. ็ถใใใซใฏ \"cont\" ใจๅ
ฅๅใใฆใใ ใใ." -#: ../ex_cmds2.c:143 ../ex_docmd.c:759 #, c-format -msgid "line %<PRId64>: %s" -msgstr "่ก %<PRId64>: %s" +msgid "line %ld: %s" +msgstr "่ก %ld: %s" -#: ../ex_cmds2.c:145 #, c-format msgid "cmd: %s" msgstr "ใณใใณใ: %s" @@ -1404,232 +1123,184 @@ msgstr "ใใฌใผใ ใ 0 ใงใ" msgid "frame at highest level: %d" msgstr "ๆ้ซใฌใใซใฎใใฌใผใ : %d" -#: ../ex_cmds2.c:322 #, c-format -msgid "Breakpoint in \"%s%s\" line %<PRId64>" -msgstr "ใใฌใผใฏใใคใณใ \"%s%s\" ่ก %<PRId64>" +msgid "Breakpoint in \"%s%s\" line %ld" +msgstr "ใใฌใผใฏใใคใณใ \"%s%s\" ่ก %ld" -#: ../ex_cmds2.c:581 #, c-format msgid "E161: Breakpoint not found: %s" msgstr "E161: ใใฌใผใฏใใคใณใใ่ฆใคใใใพใใ: %s" -#: ../ex_cmds2.c:611 msgid "No breakpoints defined" msgstr "ใใฌใผใฏใใคใณใใๅฎ็พฉใใใฆใใพใใ" -#: ../ex_cmds2.c:617 #, c-format -msgid "%3d %s %s line %<PRId64>" -msgstr "%3d %s %s ่ก %<PRId64>" +msgid "%3d %s %s line %ld" +msgstr "%3d %s %s ่ก %ld" -#: ../ex_cmds2.c:942 msgid "E750: First use \":profile start {fname}\"" msgstr "E750: ๅใใซ \":profile start {fname}\" ใๅฎ่กใใฆใใ ใใ" -#: ../ex_cmds2.c:1269 #, c-format msgid "Save changes to \"%s\"?" msgstr "ๅคๆดใ \"%s\" ใซไฟๅญใใพใใ?" -#: ../ex_cmds2.c:1271 ../ex_docmd.c:8851 msgid "Untitled" msgstr "็ก้ก" -#: ../ex_cmds2.c:1421 #, c-format msgid "E162: No write since last change for buffer \"%s\"" msgstr "E162: ใใใใก \"%s\" ใฎๅคๆดใฏไฟๅญใใใฆใใพใใ" -#: ../ex_cmds2.c:1480 msgid "Warning: Entered other buffer unexpectedly (check autocommands)" msgstr "่ญฆๅ: ไบๆใใไปใใใใกใธ็งปๅใใพใใ (autocommands ใ่ชฟในใฆใใ ใใ)" -#: ../ex_cmds2.c:1826 msgid "E163: There is only one file to edit" msgstr "E163: ็ทจ้ใใใใกใคใซใฏ1ใคใใใใใพใใ" -#: ../ex_cmds2.c:1828 msgid "E164: Cannot go before first file" msgstr "E164: ๆๅใฎใใกใคใซใใๅใซใฏ่กใใพใใ" -#: ../ex_cmds2.c:1830 msgid "E165: Cannot go beyond last file" msgstr "E165: ๆๅพใฎใใกใคใซใ่ถใใฆๅพใซใฏ่กใใพใใ" -#: ../ex_cmds2.c:2175 #, c-format msgid "E666: compiler not supported: %s" msgstr "E666: ใใฎใณใณใใคใฉใซใฏๅฏพๅฟใใฆใใพใใ: %s" -#: ../ex_cmds2.c:2257 #, c-format msgid "Searching for \"%s\" in \"%s\"" msgstr "\"%s\" ใ \"%s\" ใใๆค็ดขไธญ" -#: ../ex_cmds2.c:2284 #, c-format msgid "Searching for \"%s\"" msgstr "\"%s\" ใๆค็ดขไธญ" -#: ../ex_cmds2.c:2307 #, c-format -msgid "not found in 'runtimepath': \"%s\"" -msgstr "'runtimepath' ใฎไธญใซใฏ่ฆใคใใใพใใ: \"%s\"" +msgid "not found in '%s': \"%s\"" +msgstr "'%s' ใฎไธญใซใฏใใใพใใ: \"%s\"" + +msgid "Source Vim script" +msgstr "Vimในใฏใชใใใฎๅ่พผใฟ" -#: ../ex_cmds2.c:2472 #, c-format msgid "Cannot source a directory: \"%s\"" msgstr "ใใฃใฌใฏใใชใฏๅ่พผใใพใใ: \"%s\"" -#: ../ex_cmds2.c:2518 #, c-format msgid "could not source \"%s\"" msgstr "\"%s\" ใๅ่พผใใพใใ" -#: ../ex_cmds2.c:2520 #, c-format -msgid "line %<PRId64>: could not source \"%s\"" -msgstr "่ก %<PRId64>: \"%s\" ใๅ่พผใใพใใ" +msgid "line %ld: could not source \"%s\"" +msgstr "่ก %ld: \"%s\" ใๅ่พผใใพใใ" -#: ../ex_cmds2.c:2535 #, c-format msgid "sourcing \"%s\"" msgstr "\"%s\" ใๅ่พผไธญ" -#: ../ex_cmds2.c:2537 #, c-format -msgid "line %<PRId64>: sourcing \"%s\"" -msgstr "่ก %<PRId64>: %s ใๅ่พผไธญ" +msgid "line %ld: sourcing \"%s\"" +msgstr "่ก %ld: %s ใๅ่พผไธญ" -#: ../ex_cmds2.c:2693 #, c-format msgid "finished sourcing %s" msgstr "%s ใฎๅ่พผใๅฎไบ" -#: ../ex_cmds2.c:2765 +#, c-format +msgid "continuing in %s" +msgstr "%s ใฎๅฎ่กใ็ถ็ถไธญใงใ" + msgid "modeline" msgstr "ใขใผใ่ก" -#: ../ex_cmds2.c:2767 msgid "--cmd argument" msgstr "--cmd ๅผๆฐ" -#: ../ex_cmds2.c:2769 msgid "-c argument" msgstr "-c ๅผๆฐ" -#: ../ex_cmds2.c:2771 msgid "environment variable" msgstr "็ฐๅขๅคๆฐ" -#: ../ex_cmds2.c:2773 msgid "error handler" msgstr "ใจใฉใผใใณใใฉ" -#: ../ex_cmds2.c:3020 msgid "W15: Warning: Wrong line separator, ^M may be missing" msgstr "W15: ่ญฆๅ: ่กๅบๅใไธๆญฃใงใ. ^M ใใชใใฎใงใใใ" -#: ../ex_cmds2.c:3139 msgid "E167: :scriptencoding used outside of a sourced file" msgstr "E167: :scriptencoding ใๅ่พผในใฏใชใใไปฅๅคใงไฝฟ็จใใใพใใ" -#: ../ex_cmds2.c:3166 msgid "E168: :finish used outside of a sourced file" msgstr "E168: :finish ใๅ่พผในใฏใชใใไปฅๅคใงไฝฟ็จใใใพใใ" -#: ../ex_cmds2.c:3389 #, c-format msgid "Current %slanguage: \"%s\"" msgstr "็พๅจใฎ %s่จ่ช: \"%s\"" -#: ../ex_cmds2.c:3404 #, c-format msgid "E197: Cannot set language to \"%s\"" msgstr "E197: ่จ่ชใ \"%s\" ใซ่จญๅฎใงใใพใใ" -#. don't redisplay the window -#. don't wait for return -#: ../ex_docmd.c:387 msgid "Entering Ex mode. Type \"visual\" to go to Normal mode." msgstr "" "Exใขใผใใซๅ
ฅใใพใ. ใใผใใซใขใผใใซๆปใใซใฏ\"visual\"ใจๅ
ฅๅใใฆใใ ใใ." -#: ../ex_docmd.c:428 msgid "E501: At end-of-file" msgstr "E501: ใใกใคใซใฎ็ตไบไฝ็ฝฎ" -#: ../ex_docmd.c:513 msgid "E169: Command too recursive" msgstr "E169: ใณใใณใใๅๅธฐ็้ใใพใ" -#: ../ex_docmd.c:1006 #, c-format msgid "E605: Exception not caught: %s" msgstr "E605: ไพๅคใๆๆใใใพใใใงใใ: %s" -#: ../ex_docmd.c:1085 msgid "End of sourced file" msgstr "ๅ่พผใใกใคใซใฎๆๅพใงใ" -#: ../ex_docmd.c:1086 msgid "End of function" msgstr "้ขๆฐใฎๆๅพใงใ" -#: ../ex_docmd.c:1628 msgid "E464: Ambiguous use of user-defined command" msgstr "E464: ใฆใผใถใผๅฎ็พฉใณใใณใใฎใใใพใใชไฝฟ็จใงใ" -#: ../ex_docmd.c:1638 msgid "E492: Not an editor command" msgstr "E492: ใจใใฃใฟใฎใณใใณใใงใฏใใใพใใ" -#: ../ex_docmd.c:1729 msgid "E493: Backwards range given" msgstr "E493: ้ใใพใฎ็ฏๅฒใๆๅฎใใใพใใ" -#: ../ex_docmd.c:1733 msgid "Backwards range given, OK to swap" msgstr "้ใใพใฎ็ฏๅฒใๆๅฎใใใพใใ, ๅ
ฅๆฟใใพใใ?" -#. append -#. typed wrong -#: ../ex_docmd.c:1787 msgid "E494: Use w or w>>" msgstr "E494: w ใใใใฏ w>> ใไฝฟ็จใใฆใใ ใใ" -#: ../ex_docmd.c:3454 -msgid "E319: The command is not available in this version" +msgid "E319: Sorry, the command is not available in this version" msgstr "E319: ใใฎใใผใธใงใณใงใฏใใฎใณใใณใใฏๅฉ็จใงใใพใใ, ใใใใชใใ" -#: ../ex_docmd.c:3752 msgid "E172: Only one file name allowed" msgstr "E172: ใใกใคใซๅใฏ 1 ใคใซใใฆใใ ใใ" -#: ../ex_docmd.c:4238 msgid "1 more file to edit. Quit anyway?" msgstr "็ทจ้ใในใใใกใคใซใ 1 ๅใใใพใใ, ็ตไบใใพใใ?" -#: ../ex_docmd.c:4242 #, c-format msgid "%d more files to edit. Quit anyway?" msgstr "็ทจ้ใในใใใกใคใซใใใจ %d ๅใใใพใใ, ็ตไบใใพใใ?" -#: ../ex_docmd.c:4248 msgid "E173: 1 more file to edit" msgstr "E173: ็ทจ้ใในใใใกใคใซใ 1 ๅใใใพใ" -#: ../ex_docmd.c:4250 #, c-format -msgid "E173: %<PRId64> more files to edit" -msgstr "E173: ็ทจ้ใในใใใกใคใซใใใจ %<PRId64> ๅใใใพใ" +msgid "E173: %ld more files to edit" +msgstr "E173: ็ทจ้ใในใใใกใคใซใใใจ %ld ๅใใใพใ" -#: ../ex_docmd.c:4320 msgid "E174: Command already exists: add ! to replace it" msgstr "E174: ใณใใณใใๆขใซใใใพใ: ๅๅฎ็พฉใใใซใฏ ! ใ่ฟฝๅ ใใฆใใ ใใ" -#: ../ex_docmd.c:4432 msgid "" "\n" " Name Args Address Complete Definition" @@ -1637,51 +1308,40 @@ msgstr "" "\n" " ๅๅ ๅผๆฐ ใขใใฌใน ่ฃๅฎ ๅฎ็พฉ" -#: ../ex_docmd.c:4516 msgid "No user-defined commands found" msgstr "ใฆใผใถใผๅฎ็พฉใณใใณใใ่ฆใคใใใพใใใงใใ" -#: ../ex_docmd.c:4538 msgid "E175: No attribute specified" msgstr "E175: ๅฑๆงใฏๅฎ็พฉใใใฆใใพใใ" -#: ../ex_docmd.c:4583 msgid "E176: Invalid number of arguments" msgstr "E176: ๅผๆฐใฎๆฐใ็กๅนใงใ" -#: ../ex_docmd.c:4594 msgid "E177: Count cannot be specified twice" msgstr "E177: ใซใฆใณใใ2้ๆๅฎใใใใจใฏใงใใพใใ" -#: ../ex_docmd.c:4603 msgid "E178: Invalid default value for count" msgstr "E178: ใซใฆใณใใฎ็็ฅๅคใ็กๅนใงใ" -#: ../ex_docmd.c:4625 msgid "E179: argument required for -complete" msgstr "E179: -complete ใซใฏๅผๆฐใๅฟ
่ฆใงใ" msgid "E179: argument required for -addr" msgstr "E179: -addr ใซใฏๅผๆฐใๅฟ
่ฆใงใ" -#: ../ex_docmd.c:4635 #, c-format msgid "E181: Invalid attribute: %s" msgstr "E181: ็กๅนใชๅฑๆงใงใ: %s" -#: ../ex_docmd.c:4678 msgid "E182: Invalid command name" msgstr "E182: ็กๅนใชใณใใณใๅใงใ" -#: ../ex_docmd.c:4691 msgid "E183: User defined commands must start with an uppercase letter" msgstr "E183: ใฆใผใถใผๅฎ็พฉใณใใณใใฏ่ฑๅคงๆๅญใงๅงใพใใชใใใฐใชใใพใใ" -#: ../ex_docmd.c:4696 msgid "E841: Reserved name, cannot be used for user defined command" msgstr "E841: ไบ็ดๅใชใฎใง, ใฆใผใถใผๅฎ็พฉใณใใณใใซๅฉ็จใงใใพใใ" -#: ../ex_docmd.c:4751 #, c-format msgid "E184: No such user-defined command: %s" msgstr "E184: ใใฎใฆใผใถใผๅฎ็พฉใณใใณใใฏใใใพใใ: %s" @@ -1690,293 +1350,261 @@ msgstr "E184: ใใฎใฆใผใถใผๅฎ็พฉใณใใณใใฏใใใพใใ: %s" msgid "E180: Invalid address type value: %s" msgstr "E180: ็กๅนใชใขใใฌในใฟใคใๅคใงใ: %s" -#: ../ex_docmd.c:5219 #, c-format msgid "E180: Invalid complete value: %s" msgstr "E180: ็กๅนใช่ฃๅฎๆๅฎใงใ: %s" -#: ../ex_docmd.c:5225 msgid "E468: Completion argument only allowed for custom completion" msgstr "E468: ่ฃๅฎๅผๆฐใฏใซในใฟใ ่ฃๅฎใงใใไฝฟ็จใงใใพใใ" -#: ../ex_docmd.c:5231 msgid "E467: Custom completion requires a function argument" msgstr "E467: ใซในใฟใ ่ฃๅฎใซใฏๅผๆฐใจใใฆ้ขๆฐใๅฟ
่ฆใงใ" -#: ../ex_docmd.c:5257 +msgid "unknown" +msgstr "ไธๆ" + #, c-format msgid "E185: Cannot find color scheme '%s'" msgstr "E185: ใซใฉใผในใญใผใ '%s' ใ่ฆใคใใใพใใ" -#: ../ex_docmd.c:5263 msgid "Greetings, Vim user!" msgstr "Vim ไฝฟใใใใใใ!" -#: ../ex_docmd.c:5431 msgid "E784: Cannot close last tab page" msgstr "E784: ๆๅพใฎใฟใใใผใธใ้ใใใใจใฏใงใใพใใ" -#: ../ex_docmd.c:5462 msgid "Already only one tab page" msgstr "ๆขใซใฟใใใผใธใฏ1ใคใใใใใพใใ" -#: ../ex_docmd.c:6004 +msgid "Edit File in new window" +msgstr "ๆฐใใใฆใฃใณใใฆใงใใกใคใซใ็ทจ้ใใพใ" + #, c-format msgid "Tab page %d" msgstr "ใฟใใใผใธ %d" -#: ../ex_docmd.c:6295 msgid "No swap file" msgstr "ในใฏใใใใกใคใซใใใใพใใ" -#: ../ex_docmd.c:6478 +msgid "Append File" +msgstr "่ฟฝๅ ใใกใคใซ" + msgid "E747: Cannot change directory, buffer is modified (add ! to override)" msgstr "" "E747: ใใใใกใไฟฎๆญฃใใใฆใใใฎใง, ใใฃใฌใฏใใชใๅคๆดใงใใพใใ (! ใ่ฟฝๅ ใง" "ไธๆธ)" -#: ../ex_docmd.c:6485 msgid "E186: No previous directory" msgstr "E186: ๅใฎใใฃใฌใฏใใชใฏใใใพใใ" -#: ../ex_docmd.c:6530 msgid "E187: Unknown" msgstr "E187: ๆช็ฅ" -#: ../ex_docmd.c:6610 msgid "E465: :winsize requires two number arguments" msgstr "E465: :winsize ใซใฏ2ใคใฎๆฐๅคใฎๅผๆฐใๅฟ
่ฆใงใ" -#: ../ex_docmd.c:6655 +#, c-format +msgid "Window position: X %d, Y %d" +msgstr "ใฆใฃใณใใฆไฝ็ฝฎ: X %d, Y %d" + msgid "E188: Obtaining window position not implemented for this platform" msgstr "" "E188: ใใฎใใฉใใใใผใ ใซใฏใฆใฃใณใใฆไฝ็ฝฎใฎๅๅพๆฉ่ฝใฏๅฎ่ฃ
ใใใฆใใพใใ" -#: ../ex_docmd.c:6662 msgid "E466: :winpos requires two number arguments" msgstr "E466: :winpos ใซใฏ2ใคใฎๆฐๅคใฎๅผๆฐใๅฟ
่ฆใงใ" -#: ../ex_docmd.c:7241 +msgid "E930: Cannot use :redir inside execute()" +msgstr "E930: execute() ใฎไธญใงใฏ :redir ใฏไฝฟใใพใใ" + +msgid "Save Redirection" +msgstr "ใชใใคใฌใฏใใไฟๅญใใพใ" + +msgid "Save View" +msgstr "ใใฅใผใไฟๅญใใพใ" + +msgid "Save Session" +msgstr "ใปใใทใงใณๆ
ๅ ฑใไฟๅญใใพใ" + +msgid "Save Setup" +msgstr "่จญๅฎใไฟๅญใใพใ" + #, c-format msgid "E739: Cannot create directory: %s" msgstr "E739: ใใฃใฌใฏใใชใไฝๆใงใใพใใ: %s" -#: ../ex_docmd.c:7268 #, c-format msgid "E189: \"%s\" exists (add ! to override)" msgstr "E189: \"%s\" ใๅญๅจใใพใ (ไธๆธใใใซใฏ ! ใ่ฟฝๅ ใใฆใใ ใใ)" -#: ../ex_docmd.c:7273 #, c-format msgid "E190: Cannot open \"%s\" for writing" msgstr "E190: \"%s\" ใๆธ่พผใฟ็จใจใใฆ้ใใพใใ" #. set mark -#: ../ex_docmd.c:7294 msgid "E191: Argument must be a letter or forward/backward quote" msgstr "E191: ๅผๆฐใฏ1ๆๅญใฎ่ฑๅญใๅผ็จ็ฌฆ (' ใ `) ใงใชใใใฐใใใพใใ" -#: ../ex_docmd.c:7333 msgid "E192: Recursive use of :normal too deep" msgstr "E192: :normal ใฎๅๅธฐๅฉ็จใๆทฑใใชใ้ใใพใใ" -#: ../ex_docmd.c:7807 +msgid "E809: #< is not available without the +eval feature" +msgstr "E809: #< ใฏ +eval ๆฉ่ฝใ็กใใจๅฉ็จใงใใพใใ" + msgid "E194: No alternate file name to substitute for '#'" msgstr "E194: '#'ใ็ฝฎใๆใใๅฏใใกใคใซใฎๅๅใใใใพใใ" -#: ../ex_docmd.c:7841 msgid "E495: no autocommand file name to substitute for \"<afile>\"" msgstr "E495: \"<afile>\"ใ็ฝฎใๆใใautocommandใฎใใกใคใซๅใใใใพใใ" -#: ../ex_docmd.c:7850 msgid "E496: no autocommand buffer number to substitute for \"<abuf>\"" msgstr "E496: \"<abuf>\"ใ็ฝฎใๆใใautocommandใใใใก็ชๅทใใใใพใใ" -#: ../ex_docmd.c:7861 msgid "E497: no autocommand match name to substitute for \"<amatch>\"" msgstr "E497: \"<amatch>\"ใ็ฝฎใๆใใautocommandใฎ่ฉฒๅฝๅใใใใพใใ" -#: ../ex_docmd.c:7870 msgid "E498: no :source file name to substitute for \"<sfile>\"" msgstr "E498: \"<sfile>\"ใ็ฝฎใๆใใ :source ๅฏพ่ฑกใใกใคใซๅใใใใพใใ" -#: ../ex_docmd.c:7876 msgid "E842: no line number to use for \"<slnum>\"" msgstr "E842: \"<slnum>\"ใ็ฝฎใๆใใ่ก็ชๅทใใใใพใใ" -#: ../ex_docmd.c:7903 -#, fuzzy, c-format +#, no-c-format msgid "E499: Empty file name for '%' or '#', only works with \":p:h\"" msgstr "" "E499: '%' ใ '#' ใ็กๅใใกใคใซใชใฎใง \":p:h\" ใไผดใใชใไฝฟใๆนใฏใงใใพใใ" -#: ../ex_docmd.c:7905 msgid "E500: Evaluates to an empty string" msgstr "E500: ็ฉบๆๅญๅใจใใฆ่ฉไพกใใใพใใ" -#: ../ex_docmd.c:8838 msgid "E195: Cannot open viminfo file for reading" msgstr "E195: viminfoใใกใคใซใ่ชญ่พผ็จใจใใฆ้ใใพใใ" -#: ../ex_eval.c:464 +msgid "E196: No digraphs in this version" +msgstr "E196: ใใฎใใผใธใงใณใซๅๅญใฏใใใพใใ" + msgid "E608: Cannot :throw exceptions with 'Vim' prefix" msgstr "E608: 'Vim' ใงๅงใพใไพๅคใฏ :throw ใงใใพใใ" #. always scroll up, don't overwrite -#: ../ex_eval.c:496 #, c-format msgid "Exception thrown: %s" msgstr "ไพๅคใ็บ็ใใพใใ: %s" -#: ../ex_eval.c:545 #, c-format msgid "Exception finished: %s" msgstr "ไพๅคใๅๆใใพใใ: %s" -#: ../ex_eval.c:546 #, c-format msgid "Exception discarded: %s" msgstr "ไพๅคใ็ ดๆฃใใใพใใ: %s" -#: ../ex_eval.c:588 ../ex_eval.c:634 #, c-format -msgid "%s, line %<PRId64>" -msgstr "%s, ่ก %<PRId64>" +msgid "%s, line %ld" +msgstr "%s, ่ก %ld" #. always scroll up, don't overwrite -#: ../ex_eval.c:608 #, c-format msgid "Exception caught: %s" msgstr "ไพๅคใๆๆใใใพใใ: %s" -#: ../ex_eval.c:676 #, c-format msgid "%s made pending" msgstr "%s ใซใใๆชๆฑบๅฎ็ถๆ
ใ็ใใพใใ" -#: ../ex_eval.c:679 #, c-format msgid "%s resumed" msgstr "%s ใๅ้ใใพใใ" -#: ../ex_eval.c:683 #, c-format msgid "%s discarded" msgstr "%s ใ็ ดๆฃใใใพใใ" -#: ../ex_eval.c:708 msgid "Exception" msgstr "ไพๅค" -#: ../ex_eval.c:713 msgid "Error and interrupt" msgstr "ใจใฉใผใจๅฒ่พผใฟ" -#: ../ex_eval.c:715 msgid "Error" msgstr "ใจใฉใผ" #. if (pending & CSTP_INTERRUPT) -#: ../ex_eval.c:717 msgid "Interrupt" msgstr "ๅฒ่พผใฟ" -#: ../ex_eval.c:795 msgid "E579: :if nesting too deep" msgstr "E579: :if ใฎๅ
ฅใๅญใๆทฑ้ใใพใ" -#: ../ex_eval.c:830 msgid "E580: :endif without :if" msgstr "E580: :if ใฎใชใ :endif ใใใใพใ" -#: ../ex_eval.c:873 msgid "E581: :else without :if" msgstr "E581: :if ใฎใชใ :else ใใใใพใ" -#: ../ex_eval.c:876 msgid "E582: :elseif without :if" msgstr "E582: :if ใฎใชใ :elseif ใใใใพใ" -#: ../ex_eval.c:880 msgid "E583: multiple :else" msgstr "E583: ่คๆฐใฎ :else ใใใใพใ" -#: ../ex_eval.c:883 msgid "E584: :elseif after :else" msgstr "E584: :else ใฎๅพใซ :elseif ใใใใพใ" -#: ../ex_eval.c:941 msgid "E585: :while/:for nesting too deep" msgstr "E585: :while ใ :for ใฎๅ
ฅใๅญใๆทฑ้ใใพใ" -#: ../ex_eval.c:1028 msgid "E586: :continue without :while or :for" msgstr "E586: :while ใ :for ใฎใชใ :continue ใใใใพใ" -#: ../ex_eval.c:1061 msgid "E587: :break without :while or :for" msgstr "E587: :while ใ :for ใฎใชใ :break ใใใใพใ" -#: ../ex_eval.c:1102 msgid "E732: Using :endfor with :while" msgstr "E732: :endfor ใ :while ใจ็ตใฟๅใใใฆใใพใ" -#: ../ex_eval.c:1104 msgid "E733: Using :endwhile with :for" msgstr "E733: :endwhile ใ :for ใจ็ตใฟๅใใใฆใใพใ" -#: ../ex_eval.c:1247 msgid "E601: :try nesting too deep" msgstr "E601: :try ใฎๅ
ฅใๅญใๆทฑ้ใใพใ" -#: ../ex_eval.c:1317 msgid "E603: :catch without :try" msgstr "E603: :try ใฎใชใ :catch ใใใใพใ" #. Give up for a ":catch" after ":finally" and ignore it. #. * Just parse. -#: ../ex_eval.c:1332 msgid "E604: :catch after :finally" msgstr "E604: :finally ใฎๅพใซ :catch ใใใใพใ" -#: ../ex_eval.c:1451 msgid "E606: :finally without :try" msgstr "E606: :try ใฎใชใ :finally ใใใใพใ" #. Give up for a multiple ":finally" and ignore it. -#: ../ex_eval.c:1467 msgid "E607: multiple :finally" msgstr "E607: ่คๆฐใฎ :finally ใใใใพใ" -#: ../ex_eval.c:1571 msgid "E602: :endtry without :try" msgstr "E602: :try ใฎใชใ :endtry ใงใ" -#: ../ex_eval.c:2026 msgid "E193: :endfunction not inside a function" msgstr "E193: ้ขๆฐใฎๅคใซ :endfunction ใใใใพใใ" -#: ../ex_getln.c:1643 msgid "E788: Not allowed to edit another buffer now" msgstr "E788: ็พๅจใฏไปใฎใใใใกใ็ทจ้ใใใใจใฏ่จฑใใใพใใ" -#: ../ex_getln.c:1656 msgid "E811: Not allowed to change buffer information now" msgstr "E811: ็พๅจใฏใใใใกๆ
ๅ ฑใๅคๆดใใใใจใฏ่จฑใใใพใใ" -#: ../ex_getln.c:3178 msgid "tagname" msgstr "ใฟใฐๅ" -#: ../ex_getln.c:3181 msgid " kind file\n" msgstr " ใใกใคใซ็จฎ้ก\n" -#: ../ex_getln.c:4799 msgid "'history' option is zero" msgstr "ใชใใทใงใณ 'history' ใใผใญใงใ" -#: ../ex_getln.c:5046 #, c-format msgid "" "\n" @@ -1985,303 +1613,224 @@ msgstr "" "\n" "# %s ้
็ฎใฎๅฑฅๆญด (ๆฐใใใใฎใใๅคใใใฎใธ):\n" -#: ../ex_getln.c:5047 msgid "Command Line" msgstr "ใณใใณใใฉใคใณ" -#: ../ex_getln.c:5048 msgid "Search String" msgstr "ๆค็ดขๆๅญๅ" -#: ../ex_getln.c:5049 msgid "Expression" msgstr "ๅผ" -#: ../ex_getln.c:5050 msgid "Input Line" msgstr "ๅ
ฅๅ่ก" -#: ../ex_getln.c:5117 +msgid "Debug Line" +msgstr "ใใใใฐ่ก" + msgid "E198: cmd_pchar beyond the command length" msgstr "E198: cmd_pchar ใใณใใณใ้ทใ่ถ
ใใพใใ" -#: ../ex_getln.c:5279 msgid "E199: Active window or buffer deleted" msgstr "E199: ใขใฏใใฃใใชใฆใฃใณใใฆใใใใใกใๅ้คใใใพใใ" -#: ../file_search.c:203 -msgid "E854: path too long for completion" -msgstr "E854: ใในใ้ท้ใใฆ่ฃๅฎใงใใพใใ" - -#: ../file_search.c:446 -#, c-format -msgid "" -"E343: Invalid path: '**[number]' must be at the end of the path or be " -"followed by '%s'." -msgstr "" -"E343: ็กๅนใชใในใงใ: '**[ๆฐๅค]' ใฏpathใฎๆๅพใ '%s' ใ็ถใใฆใชใใจใใใพใ" -"ใ." - -#: ../file_search.c:1505 -#, c-format -msgid "E344: Can't find directory \"%s\" in cdpath" -msgstr "E344: cdpathใซใฏ \"%s\" ใจใใใใกใคใซใใใใพใใ" - -#: ../file_search.c:1508 -#, c-format -msgid "E345: Can't find file \"%s\" in path" -msgstr "E345: pathใซใฏ \"%s\" ใจใใใใกใคใซใใใใพใใ" - -#: ../file_search.c:1512 -#, c-format -msgid "E346: No more directory \"%s\" found in cdpath" -msgstr "E346: cdpathใซใฏใใไปฅไธ \"%s\" ใจใใใใกใคใซใใใใพใใ" - -#: ../file_search.c:1515 -#, c-format -msgid "E347: No more file \"%s\" found in path" -msgstr "E347: ใในใซใฏใใไปฅไธ \"%s\" ใจใใใใกใคใซใใใใพใใ" - -#: ../fileio.c:137 msgid "E812: Autocommands changed buffer or buffer name" msgstr "E812: autocommandใใใใใกใใใใใกๅใๅคๆดใใพใใ" -#: ../fileio.c:368 msgid "Illegal file name" msgstr "ไธๆญฃใชใใกใคใซๅ" -#: ../fileio.c:395 ../fileio.c:476 ../fileio.c:2543 ../fileio.c:2578 msgid "is a directory" msgstr "ใฏใใฃใฌใฏใใชใงใ" -#: ../fileio.c:397 msgid "is not a file" msgstr "ใฏใใกใคใซใงใฏใใใพใใ" -#: ../fileio.c:508 ../fileio.c:3522 +msgid "is a device (disabled with 'opendevice' option)" +msgstr "ใฏใใใคในใงใ ('opendevice' ใชใใทใงใณใงๅ้ฟใงใใพใ)" + msgid "[New File]" msgstr "[ๆฐใใกใคใซ]" -#: ../fileio.c:511 msgid "[New DIRECTORY]" msgstr "[ๆฐ่ฆใใฃใฌใฏใใช]" -#: ../fileio.c:529 ../fileio.c:532 msgid "[File too big]" msgstr "[ใใกใคใซ้ๅคง]" -#: ../fileio.c:534 msgid "[Permission Denied]" msgstr "[ๆจฉ้ใใใใพใใ]" -#: ../fileio.c:653 msgid "E200: *ReadPre autocommands made the file unreadable" msgstr "E200: *ReadPre autocommand ใใใกใคใซใ่ชญ่พผไธๅฏใซใใพใใ" -#: ../fileio.c:655 msgid "E201: *ReadPre autocommands must not change current buffer" msgstr "E201: *ReadPre autocommand ใฏ็พๅจใฎใใใใกใๅคใใใใพใใ" -#: ../fileio.c:672 -msgid "Nvim: Reading from stdin...\n" +msgid "Vim: Reading from stdin...\n" msgstr "Vim: ๆจๆบๅ
ฅๅใใ่ชญ่พผไธญ...\n" +msgid "Reading from stdin..." +msgstr "ๆจๆบๅ
ฅๅใใ่ชญ่พผใฟไธญ..." + #. Re-opening the original file failed! -#: ../fileio.c:909 msgid "E202: Conversion made file unreadable!" msgstr "E202: ๅคๆใใใกใคใซใ่ชญ่พผไธๅฏใซใใพใใ" -#. fifo or socket -#: ../fileio.c:1782 msgid "[fifo/socket]" msgstr "[FIFO/ใฝใฑใใ]" -#. fifo -#: ../fileio.c:1788 msgid "[fifo]" msgstr "[FIFO]" -#. or socket -#: ../fileio.c:1794 msgid "[socket]" msgstr "[ใฝใฑใใ]" -#. or character special -#: ../fileio.c:1801 msgid "[character special]" msgstr "[ใญใฃใฉใฏใฟใปใใใคใน]" -#: ../fileio.c:1815 msgid "[CR missing]" msgstr "[CR็ก]" -#: ../fileio.c:1819 msgid "[long lines split]" msgstr "[้ท่กๅๅฒ]" -#: ../fileio.c:1823 ../fileio.c:3512 msgid "[NOT converted]" msgstr "[ๆชๅคๆ]" -#: ../fileio.c:1826 ../fileio.c:3515 msgid "[converted]" msgstr "[ๅคๆๆธ]" -#: ../fileio.c:1831 #, c-format -msgid "[CONVERSION ERROR in line %<PRId64>]" -msgstr "[%<PRId64> ่ก็ฎใงๅคๆใจใฉใผ]" +msgid "[CONVERSION ERROR in line %ld]" +msgstr "[%ld ่ก็ฎใงๅคๆใจใฉใผ]" -#: ../fileio.c:1835 #, c-format -msgid "[ILLEGAL BYTE in line %<PRId64>]" -msgstr "[%<PRId64> ่ก็ฎใฎไธๆญฃใชใใคใ]" +msgid "[ILLEGAL BYTE in line %ld]" +msgstr "[%ld ่ก็ฎใฎไธๆญฃใชใใคใ]" -#: ../fileio.c:1838 msgid "[READ ERRORS]" msgstr "[่ชญ่พผใจใฉใผ]" -#: ../fileio.c:2104 msgid "Can't find temp file for conversion" msgstr "ๅคๆใซๅฟ
่ฆใชไธๆใใกใคใซใ่ฆใคใใใพใใ" -#: ../fileio.c:2110 msgid "Conversion with 'charconvert' failed" msgstr "'charconvert' ใซใใๅคๆใๅคฑๆใใพใใ" -#: ../fileio.c:2113 msgid "can't read output of 'charconvert'" msgstr "'charconvert' ใฎๅบๅใ่ชญ่พผใใพใใใงใใ" -#: ../fileio.c:2437 msgid "E676: No matching autocommands for acwrite buffer" msgstr "E676: acwriteใใใใกใฎ่ฉฒๅฝใใautocommandใฏๅญๅจใใพใใ" -#: ../fileio.c:2466 msgid "E203: Autocommands deleted or unloaded buffer to be written" msgstr "E203: ไฟๅญใใใใใใกใautocommandใๅ้คใ่งฃๆพใใพใใ" -#: ../fileio.c:2486 msgid "E204: Autocommand changed number of lines in unexpected way" msgstr "E204: autocommandใไบๆใใฌๆนๆณใง่กๆฐใๅคๆดใใพใใ" -#: ../fileio.c:2548 ../fileio.c:2565 +# Added at 19-Jan-2004. +msgid "NetBeans disallows writes of unmodified buffers" +msgstr "NetBeansใฏๆชๅคๆดใฎใใใใกใไธๆธใใใใจใฏ่จฑๅฏใใฆใใพใใ" + +msgid "Partial writes disallowed for NetBeans buffers" +msgstr "NetBeansใใใใกใฎไธ้จใๆธใๅบใใใจใฏใงใใพใใ" + msgid "is not a file or writable device" msgstr "ใฏใใกใคใซใงใๆธ่พผใฟๅฏ่ฝใใใคในใงใใใใพใใ" -#: ../fileio.c:2601 +msgid "writing to device disabled with 'opendevice' option" +msgstr "'opendevice' ใชใใทใงใณใซใใใใใคในใธใฎๆธใ่พผใฟใฏใงใใพใใ" + msgid "is read-only (add ! to override)" msgstr "ใฏ่ชญ่พผๅฐ็จใงใ (ๅผทๅถๆธ่พผใซใฏ ! ใ่ฟฝๅ )" -#: ../fileio.c:2886 msgid "E506: Can't write to backup file (add ! to override)" msgstr "E506: ใใใฏใขใใใใกใคใซใไฟๅญใงใใพใใ (! ใ่ฟฝๅ ใงๅผทๅถไฟๅญ)" -#: ../fileio.c:2898 msgid "E507: Close error for backup file (add ! to override)" msgstr "" "E507: ใใใฏใขใใใใกใคใซใ้ใใ้ใซใจใฉใผใ็บ็ใใพใใ (! ใ่ฟฝๅ ใงๅผทๅถ)" -#: ../fileio.c:2901 msgid "E508: Can't read file for backup (add ! to override)" msgstr "E508: ใใใฏใขใใ็จใใกใคใซใ่ชญ่พผใใพใใ (! ใ่ฟฝๅ ใงๅผทๅถ่ชญ่พผ)" -#: ../fileio.c:2923 msgid "E509: Cannot create backup file (add ! to override)" msgstr "E509: ใใใฏใขใใใใกใคใซใไฝใใพใใ (! ใ่ฟฝๅ ใงๅผทๅถไฝๆ)" -#: ../fileio.c:3008 msgid "E510: Can't make backup file (add ! to override)" msgstr "E510: ใใใฏใขใใใใกใคใซใไฝใใพใใ (! ใ่ฟฝๅ ใงๅผทๅถไฝๆ)" -#. Can't write without a tempfile! -#: ../fileio.c:3121 +msgid "E460: The resource fork would be lost (add ! to override)" +msgstr "E460: ใชใฝใผในใใฉใผใฏใๅคฑใใใใใใใใพใใ (! ใ่ฟฝๅ ใงๅผทๅถ)" + msgid "E214: Can't find temp file for writing" msgstr "E214: ไฟๅญ็จไธๆใใกใคใซใ่ฆใคใใใพใใ" -#: ../fileio.c:3134 msgid "E213: Cannot convert (add ! to write without conversion)" msgstr "E213: ๅคๆใงใใพใใ (! ใ่ฟฝๅ ใงๅคๆใใใซไฟๅญ)" -#: ../fileio.c:3169 msgid "E166: Can't open linked file for writing" msgstr "E166: ใชใณใฏใใใใใกใคใซใซๆธ่พผใใพใใ" -#: ../fileio.c:3173 msgid "E212: Can't open file for writing" msgstr "E212: ๆธ่พผใฟ็จใซใใกใคใซใ้ใใพใใ" -#: ../fileio.c:3363 msgid "E667: Fsync failed" msgstr "E667: fsync ใซๅคฑๆใใพใใ" -#: ../fileio.c:3398 msgid "E512: Close failed" msgstr "E512: ้ใใใใจใซๅคฑๆ" -#: ../fileio.c:3436 msgid "E513: write error, conversion failed (make 'fenc' empty to override)" msgstr "E513: ๆธ่พผใฟใจใฉใผ, ๅคๆๅคฑๆ (ไธๆธใใใซใฏ 'fenc' ใ็ฉบใซใใฆใใ ใใ)" -#: ../fileio.c:3441 #, c-format msgid "" -"E513: write error, conversion failed in line %<PRId64> (make 'fenc' empty to " +"E513: write error, conversion failed in line %ld (make 'fenc' empty to " "override)" msgstr "" -"E513: ๆธ่พผใฟใจใฉใผ, ๅคๆๅคฑๆ, ่กๆฐ %<PRId64> (ไธๆธใใใซใฏ 'fenc' ใ็ฉบใซใใฆ" -"ใใ ใใ)" +"E513: ๆธ่พผใฟใจใฉใผ, ๅคๆๅคฑๆ, ่กๆฐ %ld (ไธๆธใใใซใฏ 'fenc' ใ็ฉบใซใใฆใใ ใ" +"ใ)" -#: ../fileio.c:3448 msgid "E514: write error (file system full?)" msgstr "E514: ๆธ่พผใฟใจใฉใผ, (ใใกใคใซใทในใใ ใๆบๆฏ?)" -#: ../fileio.c:3506 msgid " CONVERSION ERROR" msgstr " ๅคๆใจใฉใผ" -#: ../fileio.c:3509 #, c-format -msgid " in line %<PRId64>;" -msgstr " ่ก %<PRId64>;" +msgid " in line %ld;" +msgstr " ่ก %ld;" -#: ../fileio.c:3519 msgid "[Device]" msgstr "[ใใใคใน]" -#: ../fileio.c:3522 msgid "[New]" msgstr "[ๆฐ]" -#: ../fileio.c:3535 msgid " [a]" msgstr " [a]" -#: ../fileio.c:3535 msgid " appended" msgstr " ่ฟฝๅ " -#: ../fileio.c:3537 msgid " [w]" msgstr " [w]" -#: ../fileio.c:3537 msgid " written" msgstr " ๆธ่พผใฟ" -#: ../fileio.c:3579 msgid "E205: Patchmode: can't save original file" msgstr "E205: patchmode: ๅๆฌใใกใคใซใไฟๅญใงใใพใใ" -#: ../fileio.c:3602 msgid "E206: patchmode: can't touch empty original file" msgstr "E206: patchmode: ็ฉบใฎๅๆฌใใกใคใซใtouchใงใใพใใ" -#: ../fileio.c:3616 msgid "E207: Can't delete backup file" msgstr "E207: ใใใฏใขใใใใกใคใซใๆถใใพใใ" -#: ../fileio.c:3672 msgid "" "\n" "WARNING: Original file may be lost or damaged\n" @@ -2289,134 +1838,105 @@ msgstr "" "\n" "่ญฆๅ: ๅๆฌใใกใคใซใๅคฑใใใใๅคๆดใใใพใใ\n" -#: ../fileio.c:3675 msgid "don't quit the editor until the file is successfully written!" msgstr "ใใกใคใซใฎไฟๅญใซๆๅใใใพใงใจใใฃใฟใ็ตไบใใชใใงใใ ใใ!" -#: ../fileio.c:3795 msgid "[dos]" msgstr "[dos]" -#: ../fileio.c:3795 msgid "[dos format]" msgstr "[dosใใฉใผใใใ]" -#: ../fileio.c:3801 msgid "[mac]" msgstr "[mac]" -#: ../fileio.c:3801 msgid "[mac format]" msgstr "[macใใฉใผใใใ]" -#: ../fileio.c:3807 msgid "[unix]" msgstr "[unix]" -#: ../fileio.c:3807 msgid "[unix format]" msgstr "[unixใใฉใผใใใ]" -#: ../fileio.c:3831 msgid "1 line, " msgstr "1 ่ก, " -#: ../fileio.c:3833 #, c-format -msgid "%<PRId64> lines, " -msgstr "%<PRId64> ่ก, " +msgid "%ld lines, " +msgstr "%ld ่ก, " -#: ../fileio.c:3836 msgid "1 character" msgstr "1 ๆๅญ" -#: ../fileio.c:3838 #, c-format -msgid "%<PRId64> characters" -msgstr "%<PRId64> ๆๅญ" +msgid "%lld characters" +msgstr "%lld ๆๅญ" -#: ../fileio.c:3849 msgid "[noeol]" msgstr "[noeol]" -#: ../fileio.c:3849 msgid "[Incomplete last line]" msgstr "[ๆ็ต่กใไธๅฎๅ
จ]" #. don't overwrite messages here #. must give this prompt #. don't use emsg() here, don't want to flush the buffers -#: ../fileio.c:3865 msgid "WARNING: The file has been changed since reading it!!!" msgstr "่ญฆๅ: ่ชญ่พผใใ ๅพใซใใกใคใซใซๅคๆดใใใใพใใ!!!" -#: ../fileio.c:3867 msgid "Do you really want to write to it" msgstr "ๆฌๅฝใซไธๆธใใใพใใ" -#: ../fileio.c:4648 #, c-format msgid "E208: Error writing to \"%s\"" msgstr "E208: \"%s\" ใๆธ่พผใฟไธญใฎใจใฉใผใงใ" -#: ../fileio.c:4655 #, c-format msgid "E209: Error closing \"%s\"" msgstr "E209: \"%s\" ใ้ใใๆใซใจใฉใผใงใ" -#: ../fileio.c:4657 #, c-format msgid "E210: Error reading \"%s\"" msgstr "E210: \"%s\" ใ่ชญ่พผไธญใฎใจใฉใผใงใ" -#: ../fileio.c:4883 msgid "E246: FileChangedShell autocommand deleted buffer" msgstr "E246: autocommand ใฎ FileChangedShell ใใใใใกใๅ้คใใพใใ" -#: ../fileio.c:4894 #, c-format msgid "E211: File \"%s\" no longer available" msgstr "E211: ใใกใคใซ \"%s\" ใฏๆขใซๅญๅจใใพใใ" -#: ../fileio.c:4906 #, c-format msgid "" "W12: Warning: File \"%s\" has changed and the buffer was changed in Vim as " "well" msgstr "W12: ่ญฆๅ: ใใกใคใซ \"%s\" ใๅคๆดใใVimใฎใใใใกใๅคๆดใใใพใใ" -#: ../fileio.c:4907 msgid "See \":help W12\" for more info." msgstr "่ฉณ็ดฐใฏ \":help W12\" ใๅ็
งใใฆใใ ใใ" -#: ../fileio.c:4910 #, c-format msgid "W11: Warning: File \"%s\" has changed since editing started" msgstr "W11: ่ญฆๅ: ใใกใคใซ \"%s\" ใฏ็ทจ้้ๅงๅพใซๅคๆดใใใพใใ" -#: ../fileio.c:4911 msgid "See \":help W11\" for more info." msgstr "่ฉณ็ดฐใฏ \":help W11\" ใๅ็
งใใฆใใ ใใ" -#: ../fileio.c:4914 #, c-format msgid "W16: Warning: Mode of file \"%s\" has changed since editing started" msgstr "W16: ่ญฆๅ: ใใกใคใซ \"%s\" ใฎใขใผใใ็ทจ้้ๅงๅพใซๅคๆดใใใพใใ" -#: ../fileio.c:4915 msgid "See \":help W16\" for more info." msgstr "่ฉณ็ดฐใฏ \":help W16\" ใๅ็
งใใฆใใ ใใ" -#: ../fileio.c:4927 #, c-format msgid "W13: Warning: File \"%s\" has been created after editing started" msgstr "W13: ่ญฆๅ: ใใกใคใซ \"%s\" ใฏ็ทจ้้ๅงๅพใซไฝๆใใใพใใ" -#: ../fileio.c:4947 msgid "Warning" msgstr "่ญฆๅ" -#: ../fileio.c:4948 msgid "" "&OK\n" "&Load File" @@ -2424,48 +1944,45 @@ msgstr "" "&OK\n" "ใใกใคใซ่ชญ่พผ(&L)" -#: ../fileio.c:5065 #, c-format msgid "E462: Could not prepare for reloading \"%s\"" msgstr "E462: \"%s\" ใใชใญใผใใใๆบๅใใงใใพใใใงใใ" -#: ../fileio.c:5078 #, c-format msgid "E321: Could not reload \"%s\"" msgstr "E321: \"%s\" ใฏใชใญใผใใงใใพใใใงใใ" -#: ../fileio.c:5601 msgid "--Deleted--" msgstr "--ๅ้คๆธ--" -#: ../fileio.c:5732 #, c-format msgid "auto-removing autocommand: %s <buffer=%d>" msgstr "autocommand: %s <ใใใใก=%d> ใ่ชๅ็ใซๅ้คใใใพใ" #. the group doesn't exist -#: ../fileio.c:5772 #, c-format msgid "E367: No such group: \"%s\"" msgstr "E367: ใใฎใฐใซใผใใฏใใใพใใ: \"%s\"" -#: ../fileio.c:5897 +msgid "E936: Cannot delete the current group" +msgstr "E936: ็พๅจใฎใฐใซใผใใฏๅ้คใงใใพใใ" + +msgid "W19: Deleting augroup that is still in use" +msgstr "W19: ไฝฟ็จไธญใฎ augroup ใๆถใใใจใใฆใใพใ" + #, c-format msgid "E215: Illegal character after *: %s" msgstr "E215: * ใฎๅพใซไธๆญฃใชๆๅญใใใใพใใ: %s" -#: ../fileio.c:5905 #, c-format msgid "E216: No such event: %s" msgstr "E216: ใใฎใใใชใคใใณใใฏใใใพใใ: %s" -#: ../fileio.c:5907 #, c-format msgid "E216: No such group or event: %s" msgstr "E216: ใใฎใใใชใฐใซใผใใใใใฏใคใใณใใฏใใใพใใ: %s" #. Highlight title -#: ../fileio.c:6090 msgid "" "\n" "--- Auto-Commands ---" @@ -2473,756 +1990,555 @@ msgstr "" "\n" "--- Auto-Commands ---" -#: ../fileio.c:6293 #, c-format msgid "E680: <buffer=%d>: invalid buffer number " msgstr "E680: <ใใใใก=%d>: ็กๅนใชใใใใก็ชๅทใงใ " -#: ../fileio.c:6370 msgid "E217: Can't execute autocommands for ALL events" msgstr "E217: ๅ
จใฆใฎใคใใณใใซๅฏพใใฆใฎautocommandใฏๅฎ่กใงใใพใใ" -#: ../fileio.c:6393 msgid "No matching autocommands" msgstr "่ฉฒๅฝใใautocommandใฏๅญๅจใใพใใ" -#: ../fileio.c:6831 msgid "E218: autocommand nesting too deep" msgstr "E218: autocommandใฎๅ
ฅใๅญใๆทฑ้ใใพใ" -#: ../fileio.c:7143 #, c-format msgid "%s Auto commands for \"%s\"" msgstr "%s Auto commands for \"%s\"" -#: ../fileio.c:7149 #, c-format msgid "Executing %s" msgstr "%s ใๅฎ่กใใฆใใพใ" -#: ../fileio.c:7211 #, c-format msgid "autocommand %s" msgstr "autocommand %s" -#: ../fileio.c:7795 msgid "E219: Missing {." msgstr "E219: { ใใใใพใใ." -#: ../fileio.c:7797 msgid "E220: Missing }." msgstr "E220: } ใใใใพใใ." -#: ../fold.c:93 msgid "E490: No fold found" msgstr "E490: ๆ็ณใฟใใใใพใใ" -#: ../fold.c:544 msgid "E350: Cannot create fold with current 'foldmethod'" msgstr "E350: ็พๅจใฎ 'foldmethod' ใงใฏๆ็ณใฟใไฝๆใงใใพใใ" -#: ../fold.c:546 msgid "E351: Cannot delete fold with current 'foldmethod'" msgstr "E351: ็พๅจใฎ 'foldmethod' ใงใฏๆ็ณใฟใๅ้คใงใใพใใ" -#: ../fold.c:1784 #, c-format -msgid "+--%3ld lines folded " -msgstr "+--%3ld ่กใๆ็ณใพใใพใใ " +msgid "+--%3ld line folded " +msgid_plural "+--%3ld lines folded " +msgstr[0] "+--%3ld ่กใๆ็ณใพใใพใใ " -#. buffer has already been read -#: ../getchar.c:273 msgid "E222: Add to read buffer" msgstr "E222: ่ชญ่พผใใใใกใธ่ฟฝๅ " -#: ../getchar.c:2040 msgid "E223: recursive mapping" msgstr "E223: ๅๅธฐ็ใใใใณใฐ" -#: ../getchar.c:2849 #, c-format msgid "E224: global abbreviation already exists for %s" msgstr "E224: %s ใจใใใฐใญใผใใซ็ญ็ธฎๅ
ฅๅใฏๆขใซๅญๅจใใพใ" -#: ../getchar.c:2852 #, c-format msgid "E225: global mapping already exists for %s" msgstr "E225: %s ใจใใใฐใญใผใใซใใใใณใฐใฏๆขใซๅญๅจใใพใ" -#: ../getchar.c:2952 #, c-format msgid "E226: abbreviation already exists for %s" msgstr "E226: %s ใจใใ็ญ็ธฎๅ
ฅๅใฏๆขใซๅญๅจใใพใ" -#: ../getchar.c:2955 #, c-format msgid "E227: mapping already exists for %s" msgstr "E227: %s ใจใใใใใใณใฐใฏๆขใซๅญๅจใใพใ" -#: ../getchar.c:3008 msgid "No abbreviation found" msgstr "็ญ็ธฎๅ
ฅๅใฏ่ฆใคใใใพใใใงใใ" -#: ../getchar.c:3010 msgid "No mapping found" msgstr "ใใใใณใฐใฏ่ฆใคใใใพใใใงใใ" -#: ../getchar.c:3974 msgid "E228: makemap: Illegal mode" msgstr "E228: makemap: ไธๆญฃใชใขใผใ" -#. key value of 'cedit' option -#. type of cmdline window or 0 -#. result of cmdline window or 0 -#: ../globals.h:924 -msgid "--No lines in buffer--" -msgstr "--ใใใใกใซ่กใใใใพใใ--" +msgid "E851: Failed to create a new process for the GUI" +msgstr "E851: GUI็จใฎใใญใปในใฎ่ตทๅใซๅคฑๆใใพใใ" -#. -#. * The error messages that can be shared are included here. -#. * Excluded are errors that are only used once and debugging messages. -#. -#: ../globals.h:996 -msgid "E470: Command aborted" -msgstr "E470: ใณใใณใใไธญๆญใใใพใใ" +msgid "E852: The child process failed to start the GUI" +msgstr "E852: ๅญใใญใปในใGUIใฎ่ตทๅใซๅคฑๆใใพใใ" -#: ../globals.h:997 -msgid "E471: Argument required" -msgstr "E471: ๅผๆฐใๅฟ
่ฆใงใ" +msgid "E229: Cannot start the GUI" +msgstr "E229: GUIใ้ๅงใงใใพใใ" -#: ../globals.h:998 -msgid "E10: \\ should be followed by /, ? or &" -msgstr "E10: \\ ใฎๅพใฏ / ใ ? ใ & ใงใชใใใฐใชใใพใใ" +#, c-format +msgid "E230: Cannot read from \"%s\"" +msgstr "E230: \"%s\"ใใ่ชญ่พผใใใจใใงใใพใใ" -#: ../globals.h:1000 -msgid "E11: Invalid in command-line window; <CR> executes, CTRL-C quits" -msgstr "E11: ใณใใณใใฉใคใณใงใฏ็กๅนใงใ; <CR>ใงๅฎ่ก, CTRL-Cใงใใใ" +msgid "E665: Cannot start GUI, no valid font found" +msgstr "E665: ๆๅนใชใใฉใณใใ่ฆใคใใใชใใฎใง, GUIใ้ๅงใงใใพใใ" -#: ../globals.h:1002 -msgid "E12: Command not allowed from exrc/vimrc in current dir or tag search" -msgstr "" -"E12: ็พๅจใฎใใฃใฌใฏใใชใใฟใฐๆค็ดขใงใฏexrc/vimrcใฎใณใใณใใฏ่จฑๅฏใใใพใใ" +msgid "E231: 'guifontwide' invalid" +msgstr "E231: 'guifontwide' ใ็กๅนใงใ" -#: ../globals.h:1003 -msgid "E171: Missing :endif" -msgstr "E171: :endif ใใใใพใใ" +msgid "E599: Value of 'imactivatekey' is invalid" +msgstr "E599: 'imactivatekey' ใซ่จญๅฎใใใๅคใ็กๅนใงใ" -#: ../globals.h:1004 -msgid "E600: Missing :endtry" -msgstr "E600: :endtry ใใใใพใใ" +#, c-format +msgid "E254: Cannot allocate color %s" +msgstr "E254: %s ใฎ่ฒใๅฒใๅฝใฆใใใพใใ" -#: ../globals.h:1005 -msgid "E170: Missing :endwhile" -msgstr "E170: :endwhile ใใใใพใใ" +msgid "No match at cursor, finding next" +msgstr "ใซใผใฝใซใฎไฝ็ฝฎใซใใใใฏใใใพใใ, ๆฌกใๆค็ดขใใฆใใพใ" -#: ../globals.h:1006 -msgid "E170: Missing :endfor" -msgstr "E170: :endfor ใใใใพใใ" - -#: ../globals.h:1007 -msgid "E588: :endwhile without :while" -msgstr "E588: :while ใฎใชใ :endwhile ใใใใพใ" +msgid "<cannot open> " +msgstr "<้ใใพใใ> " -#: ../globals.h:1008 -msgid "E588: :endfor without :for" -msgstr "E588: :endfor ใฎใชใ :for ใใใใพใ" +#, c-format +msgid "E616: vim_SelFile: can't get font %s" +msgstr "E616: vim_SelFile: ใใฉใณใ %s ใๅๅพใงใใพใใ" -#: ../globals.h:1009 -msgid "E13: File exists (add ! to override)" -msgstr "E13: ใใกใคใซใๅญๅจใใพใ (! ใ่ฟฝๅ ใงไธๆธ)" +msgid "E614: vim_SelFile: can't return to current directory" +msgstr "E614: vim_SelFile: ็พๅจใฎใใฃใฌใฏใใชใซๆปใใพใใ" -#: ../globals.h:1010 -msgid "E472: Command failed" -msgstr "E472: ใณใใณใใๅคฑๆใใพใใ" +msgid "Pathname:" +msgstr "ใในๅ:" -#: ../globals.h:1011 -msgid "E473: Internal error" -msgstr "E473: ๅ
้จใจใฉใผใงใ" +msgid "E615: vim_SelFile: can't get current directory" +msgstr "E615: vim_SelFile: ็พๅจใฎใใฃใฌใฏใใชใๅๅพใงใใพใใ" -#: ../globals.h:1012 -msgid "Interrupted" -msgstr "ๅฒ่พผใพใใพใใ" +msgid "OK" +msgstr "OK" -#: ../globals.h:1013 -msgid "E14: Invalid address" -msgstr "E14: ็กๅนใชใขใใฌในใงใ" +msgid "Cancel" +msgstr "ใญใฃใณใปใซ" -#: ../globals.h:1014 -msgid "E474: Invalid argument" -msgstr "E474: ็กๅนใชๅผๆฐใงใ" +msgid "Scrollbar Widget: Could not get geometry of thumb pixmap." +msgstr "ในใฏใญใผใซใใผ: ็ปๅใๅๅพใงใใพใใใงใใ." -#: ../globals.h:1015 -#, c-format -msgid "E475: Invalid argument: %s" -msgstr "E475: ็กๅนใชๅผๆฐใงใ: %s" +msgid "Vim dialog" +msgstr "Vim ใใคใขใญใฐ" -#: ../globals.h:1016 -#, c-format -msgid "E15: Invalid expression: %s" -msgstr "E15: ็กๅนใชๅผใงใ: %s" +msgid "E232: Cannot create BalloonEval with both message and callback" +msgstr "E232: ใกใใปใผใธใจใณใผใซใใใฏใฎใใ BalloonEval ใไฝๆใงใใพใใ" -#: ../globals.h:1017 -msgid "E16: Invalid range" -msgstr "E16: ็กๅนใช็ฏๅฒใงใ" +msgid "_Cancel" +msgstr "ใญใฃใณใปใซ(_C)" -#: ../globals.h:1018 -msgid "E476: Invalid command" -msgstr "E476: ็กๅนใชใณใใณใใงใ" +msgid "_Save" +msgstr "ไฟๅญ(_S)" -#: ../globals.h:1019 -#, c-format -msgid "E17: \"%s\" is a directory" -msgstr "E17: \"%s\" ใฏใใฃใฌใฏใใชใงใ" +msgid "_Open" +msgstr "้ใ(_O)" -#: ../globals.h:1020 -#, fuzzy -msgid "E900: Invalid job id" -msgstr "E49: ็กๅนใชในใฏใญใผใซ้ใงใ" +msgid "_OK" +msgstr "_OK" -#: ../globals.h:1021 -msgid "E901: Job table is full" +msgid "" +"&Yes\n" +"&No\n" +"&Cancel" msgstr "" +"ใฏใ(&Y)\n" +"ใใใ(&N)\n" +"ใญใฃใณใปใซ(&C)" -#: ../globals.h:1024 -#, c-format -msgid "E364: Library call failed for \"%s()\"" -msgstr "E364: \"%s\"() ใฎใฉใคใใฉใชๅผๅบใซๅคฑๆใใพใใ" +msgid "Yes" +msgstr "ใฏใ" -#: ../globals.h:1026 -msgid "E19: Mark has invalid line number" -msgstr "E19: ใใผใฏใซ็กๅนใช่ก็ชๅทใๆๅฎใใใฆใใพใใ" +msgid "No" +msgstr "ใใใ" -#: ../globals.h:1027 -msgid "E20: Mark not set" -msgstr "E20: ใใผใฏใฏ่จญๅฎใใใฆใใพใใ" +msgid "Input _Methods" +msgstr "ใคใณใใใใกใฝใใ" -#: ../globals.h:1029 -msgid "E21: Cannot make changes, 'modifiable' is off" -msgstr "E21: 'modifiable' ใใชใใชใฎใง, ๅคๆดใงใใพใใ" +msgid "VIM - Search and Replace..." +msgstr "VIM - ๆค็ดขใจ็ฝฎๆ..." -#: ../globals.h:1030 -msgid "E22: Scripts nested too deep" -msgstr "E22: ในใฏใชใใใฎๅ
ฅใๅญใๆทฑ้ใใพใ" +msgid "VIM - Search..." +msgstr "VIM - ๆค็ดข..." -#: ../globals.h:1031 -msgid "E23: No alternate file" -msgstr "E23: ๅฏใใกใคใซใฏใใใพใใ" +msgid "Find what:" +msgstr "ๆค็ดขๆๅญๅ:" -#: ../globals.h:1032 -msgid "E24: No such abbreviation" -msgstr "E24: ใใฎใใใช็ญ็ธฎๅ
ฅๅใฏใใใพใใ" +msgid "Replace with:" +msgstr "็ฝฎๆๆๅญๅ:" -#: ../globals.h:1033 -msgid "E477: No ! allowed" -msgstr "E477: ! ใฏ่จฑๅฏใใใฆใใพใใ" +#. whole word only button +msgid "Match whole word only" +msgstr "ๆญฃ็ขบใซ่ฉฒๅฝใใใใฎใ ใ" -#: ../globals.h:1035 -msgid "E25: Nvim does not have a built-in GUI" -msgstr "E25: GUIใฏไฝฟ็จไธๅฏ่ฝใงใ: ใณใณใใคใซๆใซ็กๅนใซใใใฆใใพใ" +#. match case button +msgid "Match case" +msgstr "ๅคงๆๅญ/ๅฐๆๅญใๅบๅฅใใ" -#: ../globals.h:1036 -#, c-format -msgid "E28: No such highlight group name: %s" -msgstr "E28: ใใฎใใใชๅใฎใใคใฉใคใใฐใซใผใใฏใใใพใใ: %s" +msgid "Direction" +msgstr "ๆนๅ" -#: ../globals.h:1037 -msgid "E29: No inserted text yet" -msgstr "E29: ใพใ ใใญในใใๆฟๅ
ฅใใใฆใใพใใ" +#. 'Up' and 'Down' buttons +msgid "Up" +msgstr "ไธ" -#: ../globals.h:1038 -msgid "E30: No previous command line" -msgstr "E30: ไปฅๅใซใณใใณใ่กใใใใพใใ" +msgid "Down" +msgstr "ไธ" -#: ../globals.h:1039 -msgid "E31: No such mapping" -msgstr "E31: ใใฎใใใชใใใใณใฐใฏใใใพใใ" +msgid "Find Next" +msgstr "ๆฌกใๆค็ดข" -#: ../globals.h:1040 -msgid "E479: No match" -msgstr "E479: ่ฉฒๅฝใฏใใใพใใ" +msgid "Replace" +msgstr "็ฝฎๆ" -#: ../globals.h:1041 -#, c-format -msgid "E480: No match: %s" -msgstr "E480: ่ฉฒๅฝใฏใใใพใใ: %s" +msgid "Replace All" +msgstr "ๅ
จใฆ็ฝฎๆ" -#: ../globals.h:1042 -msgid "E32: No file name" -msgstr "E32: ใใกใคใซๅใใใใพใใ" +msgid "_Close" +msgstr "้ใใ(_C)" -#: ../globals.h:1044 -msgid "E33: No previous substitute regular expression" -msgstr "E33: ๆญฃ่ฆ่กจ็พ็ฝฎๆใใพใ ๅฎ่กใใใฆใใพใใ" +msgid "Vim: Received \"die\" request from session manager\n" +msgstr "Vim: ใปใใทใงใณใใใผใธใฃใใ \"die\" ่ฆๆฑใๅใๅใใพใใ\n" -#: ../globals.h:1045 -msgid "E34: No previous command" -msgstr "E34: ใณใใณใใใพใ ๅฎ่กใใใฆใใพใใ" +msgid "Close tab" +msgstr "ใฟใใใผใธใ้ใใ" -#: ../globals.h:1046 -msgid "E35: No previous regular expression" -msgstr "E35: ๆญฃ่ฆ่กจ็พใใพใ ๅฎ่กใใใฆใใพใใ" +msgid "New tab" +msgstr "ๆฐ่ฆใฟใใใผใธ" -#: ../globals.h:1047 -msgid "E481: No range allowed" -msgstr "E481: ็ฏๅฒๆๅฎใฏ่จฑๅฏใใใฆใใพใใ" +msgid "Open Tab..." +msgstr "ใฟใใใผใธใ้ใ..." -#: ../globals.h:1048 -msgid "E36: Not enough room" -msgstr "E36: ใฆใฃใณใใฆใซๅๅใช้ซใใใใใฏๅน
ใใใใพใใ" +msgid "Vim: Main window unexpectedly destroyed\n" +msgstr "Vim: ใกใคใณใฆใฃใณใใฆใไธๆใซ็ ดๅฃใใใพใใ\n" -#: ../globals.h:1049 -#, c-format -msgid "E482: Can't create file %s" -msgstr "E482: ใใกใคใซ %s ใไฝๆใงใใพใใ" +msgid "&Filter" +msgstr "ใใฃใซใฟ(&F)" -#: ../globals.h:1050 -msgid "E483: Can't get temp file name" -msgstr "E483: ไธๆใใกใคใซใฎๅๅใๅๅพใงใใพใใ" +msgid "&Cancel" +msgstr "ใญใฃใณใปใซ(&C)" -#: ../globals.h:1051 -#, c-format -msgid "E484: Can't open file %s" -msgstr "E484: ใใกใคใซ \"%s\" ใ้ใใพใใ" +msgid "Directories" +msgstr "ใใฃใฌใฏใใช" -#: ../globals.h:1052 -#, c-format -msgid "E485: Can't read file %s" -msgstr "E485: ใใกใคใซ %s ใ่ชญ่พผใใพใใ" +msgid "Filter" +msgstr "ใใฃใซใฟ" -#: ../globals.h:1054 -msgid "E37: No write since last change (add ! to override)" -msgstr "E37: ๆๅพใฎๅคๆดใไฟๅญใใใฆใใพใใ (! ใ่ฟฝๅ ใงๅคๆดใ็ ดๆฃ)" +msgid "&Help" +msgstr "ใใซใ(&H)" -#: ../globals.h:1055 -msgid "E37: No write since last change" -msgstr "E37: ๆๅพใฎๅคๆดใไฟๅญใใใฆใใพใใ" +msgid "Files" +msgstr "ใใกใคใซ" -#: ../globals.h:1056 -msgid "E38: Null argument" -msgstr "E38: ๅผๆฐใ็ฉบใงใ" +msgid "&OK" +msgstr "&OK" -#: ../globals.h:1057 -msgid "E39: Number expected" -msgstr "E39: ๆฐๅคใ่ฆๆฑใใใฆใใพใ" +msgid "Selection" +msgstr "้ธๆ" -#: ../globals.h:1058 -#, c-format -msgid "E40: Can't open errorfile %s" -msgstr "E40: ใจใฉใผใใกใคใซ %s ใ้ใใพใใ" +msgid "Find &Next" +msgstr "ๆฌกใๆค็ดข(&N)" -#: ../globals.h:1059 -msgid "E41: Out of memory!" -msgstr "E41: ใกใขใชใๅฐฝใๆใฆใพใใ!" +msgid "&Replace" +msgstr "็ฝฎๆ(&R)" -#: ../globals.h:1060 -msgid "Pattern not found" -msgstr "ใใฟใผใณใฏ่ฆใคใใใพใใใงใใ" +msgid "Replace &All" +msgstr "ๅ
จใฆ็ฝฎๆ(&A)" -#: ../globals.h:1061 -#, c-format -msgid "E486: Pattern not found: %s" -msgstr "E486: ใใฟใผใณใฏ่ฆใคใใใพใใใงใใ: %s" +msgid "&Undo" +msgstr "ใขใณใใฅ(&U)" -#: ../globals.h:1062 -msgid "E487: Argument must be positive" -msgstr "E487: ๅผๆฐใฏๆญฃใฎๅคใงใชใใใฐใชใใพใใ" +msgid "Open tab..." +msgstr "ใฟใใใผใธใ้ใ" -#: ../globals.h:1064 -msgid "E459: Cannot go back to previous directory" -msgstr "E459: ๅใฎใใฃใฌใฏใใชใซๆปใใพใใ" +msgid "Find string (use '\\\\' to find a '\\')" +msgstr "ๆค็ดขๆๅญๅ ('\\' ใๆค็ดขใใใซใฏ '\\\\')" -#: ../globals.h:1066 -msgid "E42: No Errors" -msgstr "E42: ใจใฉใผใฏใใใพใใ" +msgid "Find & Replace (use '\\\\' to find a '\\')" +msgstr "ๆค็ดขใป็ฝฎๆ ('\\' ใๆค็ดขใใใซใฏ '\\\\')" -#: ../globals.h:1067 -msgid "E776: No location list" -msgstr "E776: ใญใฑใผใทใงใณใชในใใฏใใใพใใ" - -#: ../globals.h:1068 -msgid "E43: Damaged match string" -msgstr "E43: ่ฉฒๅฝๆๅญๅใ็ ดๆใใฆใใพใ" +#. We fake this: Use a filter that doesn't select anything and a default +#. * file name that won't be used. +msgid "Not Used" +msgstr "ไฝฟใใใพใใ" -#: ../globals.h:1069 -msgid "E44: Corrupted regexp program" -msgstr "E44: ไธๆญฃใชๆญฃ่ฆ่กจ็พใใญใฐใฉใ ใงใ" +msgid "Directory\t*.nothing\n" +msgstr "ใใฃใฌใฏใใช\t*.nothing\n" -#: ../globals.h:1071 -msgid "E45: 'readonly' option is set (add ! to override)" -msgstr "E45: 'readonly' ใชใใทใงใณใ่จญๅฎใใใฆใใพใ (! ใ่ฟฝๅ ใงไธๆธใ)" - -#: ../globals.h:1073 #, c-format -msgid "E46: Cannot change read-only variable \"%s\"" -msgstr "E46: ่ชญๅๅฐ็จๅคๆฐ \"%s\" ใซใฏๅคใ่จญๅฎใงใใพใใ" +msgid "E671: Cannot find window title \"%s\"" +msgstr "E671: ใฟใคใใซใ \"%s\" ใฎใฆใฃใณใใฆใฏ่ฆใคใใใพใใ" -#: ../globals.h:1075 #, c-format -msgid "E794: Cannot set variable in the sandbox: \"%s\"" -msgstr "E794: ใตใณใใใใฏในใงใฏๅคๆฐ \"%s\" ใซๅคใ่จญๅฎใงใใพใใ" - -#: ../globals.h:1076 -msgid "E47: Error while reading errorfile" -msgstr "E47: ใจใฉใผใใกใคใซใฎ่ชญ่พผไธญใซใจใฉใผใ็บ็ใใพใใ" - -#: ../globals.h:1078 -msgid "E48: Not allowed in sandbox" -msgstr "E48: ใตใณใใใใฏในใงใฏ่จฑใใใพใใ" - -#: ../globals.h:1080 -msgid "E523: Not allowed here" -msgstr "E523: ใใใงใฏ่จฑๅฏใใใพใใ" +msgid "E243: Argument not supported: \"-%s\"; Use the OLE version." +msgstr "E243: ๅผๆฐใฏใตใใผใใใใพใใ: \"-%s\"; OLE็ใไฝฟ็จใใฆใใ ใใ." -#: ../globals.h:1082 -msgid "E359: Screen mode setting not supported" -msgstr "E359: ในใฏใชใผใณใขใผใใฎ่จญๅฎใซใฏๅฏพๅฟใใฆใใพใใ" +msgid "E672: Unable to open window inside MDI application" +msgstr "E672: MDIใขใใชใฎไธญใงใฏใฆใฃใณใใฆใ้ใใพใใ" -#: ../globals.h:1083 -msgid "E49: Invalid scroll size" -msgstr "E49: ็กๅนใชในใฏใญใผใซ้ใงใ" +msgid "Vim E458: Cannot allocate colormap entry, some colors may be incorrect" +msgstr "Vim E458: ่ฒๆๅฎใๆญฃใใใชใใฎใงใจใณใใชใๅฒใๅฝใฆใใใพใใ" -#: ../globals.h:1084 -msgid "E91: 'shell' option is empty" -msgstr "E91: 'shell' ใชใใทใงใณใ็ฉบใงใ" +#, c-format +msgid "E250: Fonts for the following charsets are missing in fontset %s:" +msgstr "E250: ไปฅไธใฎๆๅญใปใใใฎใใฉใณใใใใใพใใ %s:" -#: ../globals.h:1085 -msgid "E255: Couldn't read in sign data!" -msgstr "E255: sign ใฎใใผใฟใ่ชญ่พผใใพใใใงใใ" +#, c-format +msgid "E252: Fontset name: %s" +msgstr "E252: ใใฉใณใใปใใๅ: %s" -#: ../globals.h:1086 -msgid "E72: Close error on swap file" -msgstr "E72: ในใฏใใใใกใคใซใฎใฏใญใผใบๆใจใฉใผใงใ" +#, c-format +msgid "Font '%s' is not fixed-width" +msgstr "ใใฉใณใ '%s' ใฏๅบๅฎๅน
ใงใฏใใใพใใ" -#: ../globals.h:1087 -msgid "E73: tag stack empty" -msgstr "E73: ใฟใฐในใฟใใฏใ็ฉบใงใ" +#, c-format +msgid "E253: Fontset name: %s" +msgstr "E253: ใใฉใณใใปใใๅ: %s" -#: ../globals.h:1088 -msgid "E74: Command too complex" -msgstr "E74: ใณใใณใใ่ค้้ใใพใ" +#, c-format +msgid "Font0: %s" +msgstr "ใใฉใณใ0: %s" -#: ../globals.h:1089 -msgid "E75: Name too long" -msgstr "E75: ๅๅใ้ท้ใใพใ" +#, c-format +msgid "Font1: %s" +msgstr "ใใฉใณใ1: %s" -#: ../globals.h:1090 -msgid "E76: Too many [" -msgstr "E76: [ ใๅค้ใใพใ" +#, c-format +msgid "Font%ld width is not twice that of font0" +msgstr "ใใฉใณใ%ld ใฎๅน
ใใใฉใณใ0ใฎ2ๅใงใฏใใใพใใ" -#: ../globals.h:1091 -msgid "E77: Too many file names" -msgstr "E77: ใใกใคใซๅใๅค้ใใพใ" +#, c-format +msgid "Font0 width: %ld" +msgstr "ใใฉใณใ0ใฎๅน
: %ld" -#: ../globals.h:1092 -msgid "E488: Trailing characters" -msgstr "E488: ไฝๅใชๆๅญใๅพใใซใใใพใ" +#, c-format +msgid "Font1 width: %ld" +msgstr "ใใฉใณใ1ใฎๅน
: %ld" -#: ../globals.h:1093 -msgid "E78: Unknown mark" -msgstr "E78: ๆช็ฅใฎใใผใฏ" +msgid "Invalid font specification" +msgstr "็กๅนใชใใฉใณใๆๅฎใงใ" -#: ../globals.h:1094 -msgid "E79: Cannot expand wildcards" -msgstr "E79: ใฏใคใซใใซใผใใๅฑ้ใงใใพใใ" +msgid "&Dismiss" +msgstr "ๅดไธใใ(&D)" -#: ../globals.h:1096 -msgid "E591: 'winheight' cannot be smaller than 'winminheight'" -msgstr "E591: 'winheight' ใฏ 'winminheight' ใใๅฐใใใงใใพใใ" +msgid "no specific match" +msgstr "ใใใใใใใฎใใใใพใใ" -#: ../globals.h:1098 -msgid "E592: 'winwidth' cannot be smaller than 'winminwidth'" -msgstr "E592: 'winwidth' ใฏ 'winminwidth' ใใๅฐใใใงใใพใใ" +msgid "Vim - Font Selector" +msgstr "Vim - ใใฉใณใ้ธๆ" -#: ../globals.h:1099 -msgid "E80: Error while writing" -msgstr "E80: ๆธ่พผใฟไธญใฎใจใฉใผ" +msgid "Name:" +msgstr "ๅๅ:" -#: ../globals.h:1100 -msgid "Zero count" -msgstr "ใผใญใซใฆใณใ" +#. create toggle button +msgid "Show size in Points" +msgstr "ใตใคใบใใใคใณใใง่กจ็คบใใ" -#: ../globals.h:1101 -msgid "E81: Using <SID> not in a script context" -msgstr "E81: ในใฏใชใใไปฅๅคใง<SID>ใไฝฟใใใพใใ" +msgid "Encoding:" +msgstr "ใจใณใณใผใ:" -#: ../globals.h:1102 -#, c-format -msgid "E685: Internal error: %s" -msgstr "E685: ๅ
้จใจใฉใผใงใ: %s" +msgid "Font:" +msgstr "ใใฉใณใ:" -#: ../globals.h:1104 -msgid "E363: pattern uses more memory than 'maxmempattern'" -msgstr "E363: ใใฟใผใณใ 'maxmempattern' ไปฅไธใฎใกใขใชใไฝฟ็จใใพใ" +msgid "Style:" +msgstr "ในใฟใคใซ:" -#: ../globals.h:1105 -msgid "E749: empty buffer" -msgstr "E749: ใใใใกใ็ฉบใงใ" +msgid "Size:" +msgstr "ใตใคใบ:" -#: ../globals.h:1108 -msgid "E682: Invalid search pattern or delimiter" -msgstr "E682: ๆค็ดขใใฟใผใณใๅบๅใ่จๅทใไธๆญฃใงใ" +msgid "E256: Hangul automata ERROR" +msgstr "E256: ใใณใฐใซใชใผใใใใณใจใฉใผ" -#: ../globals.h:1109 -msgid "E139: File is loaded in another buffer" -msgstr "E139: ๅใๅๅใฎใใกใคใซใไปใฎใใใใกใง่ชญ่พผใพใใฆใใพใ" - -#: ../globals.h:1110 -#, c-format -msgid "E764: Option '%s' is not set" -msgstr "E764: ใชใใทใงใณ '%s' ใฏ่จญๅฎใใใฆใใพใใ" - -#: ../globals.h:1111 -msgid "E850: Invalid register name" -msgstr "E850: ็กๅนใชใฌใธในใฟๅใงใ" - -#: ../globals.h:1114 -msgid "search hit TOP, continuing at BOTTOM" -msgstr "ไธใพใงๆค็ดขใใใฎใงไธใซๆปใใพใ" - -#: ../globals.h:1115 -msgid "search hit BOTTOM, continuing at TOP" -msgstr "ไธใพใงๆค็ดขใใใฎใงไธใซๆปใใพใ" - -#: ../hardcopy.c:240 msgid "E550: Missing colon" msgstr "E550: ใณใญใณใใใใพใใ" -#: ../hardcopy.c:252 msgid "E551: Illegal component" msgstr "E551: ไธๆญฃใชๆงๆ่ฆ็ด ใงใ" -#: ../hardcopy.c:259 msgid "E552: digit expected" msgstr "E552: ๆฐๅคใๅฟ
่ฆใงใ" -#: ../hardcopy.c:473 #, c-format msgid "Page %d" msgstr "%d ใใผใธ" -#: ../hardcopy.c:597 msgid "No text to be printed" msgstr "ๅฐๅทใใใใญในใใใใใพใใ" -#: ../hardcopy.c:668 #, c-format msgid "Printing page %d (%d%%)" msgstr "ๅฐๅทไธญ: ใใผใธ %d (%d%%)" -#: ../hardcopy.c:680 #, c-format msgid " Copy %d of %d" msgstr " ใณใใผ %d (ๅ
จ %d ไธญ)" -#: ../hardcopy.c:733 #, c-format msgid "Printed: %s" msgstr "ๅฐๅทใใพใใ: %s" -#: ../hardcopy.c:740 msgid "Printing aborted" msgstr "ๅฐๅทใไธญๆญขใใใพใใ" -#: ../hardcopy.c:1365 msgid "E455: Error writing to PostScript output file" msgstr "E455: PostScriptๅบๅใใกใคใซใฎๆธ่พผใฟใจใฉใผใงใ" -#: ../hardcopy.c:1747 #, c-format msgid "E624: Can't open file \"%s\"" msgstr "E624: ใใกใคใซ \"%s\" ใ้ใใพใใ" -#: ../hardcopy.c:1756 ../hardcopy.c:2470 #, c-format msgid "E457: Can't read PostScript resource file \"%s\"" msgstr "E457: PostScriptใฎใชใฝใผในใใกใคใซ \"%s\" ใ่ชญ่พผใใพใใ" -#: ../hardcopy.c:1772 #, c-format msgid "E618: file \"%s\" is not a PostScript resource file" msgstr "E618: ใใกใคใซ \"%s\" ใฏ PostScript ใชใฝใผในใใกใคใซใงใฏใใใพใใ" -#: ../hardcopy.c:1788 ../hardcopy.c:1805 ../hardcopy.c:1844 #, c-format msgid "E619: file \"%s\" is not a supported PostScript resource file" msgstr "E619: ใใกใคใซ \"%s\" ใฏๅฏพๅฟใใฆใใชใ PostScript ใชใฝใผในใใกใคใซใงใ" -#: ../hardcopy.c:1856 #, c-format msgid "E621: \"%s\" resource file has wrong version" msgstr "E621: ใชใฝใผในใใกใคใซ \"%s\" ใฏใใผใธใงใณใ็ฐใชใใพใ" -#: ../hardcopy.c:2225 msgid "E673: Incompatible multi-byte encoding and character set." msgstr "E673: ไบๆๆงใฎ็กใใใซใใใคใใจใณใณใผใใฃใณใฐใจๆๅญใปใใใงใ" -#: ../hardcopy.c:2238 msgid "E674: printmbcharset cannot be empty with multi-byte encoding." msgstr "E674: ใใซใใใคใใจใณใณใผใใฃใณใฐใงใฏ printmbcharset ใ็ฉบใซใงใใพใใ" -#: ../hardcopy.c:2254 msgid "E675: No default font specified for multi-byte printing." msgstr "" "E675: ใใซใใใคใๆๅญใๅฐๅทใใใใใฎใใใฉใซใใใฉใณใใๆๅฎใใใฆใใพใใ" -#: ../hardcopy.c:2426 msgid "E324: Can't open PostScript output file" msgstr "E324: PostScriptๅบๅ็จใฎใใกใคใซใ้ใใพใใ" -#: ../hardcopy.c:2458 #, c-format msgid "E456: Can't open file \"%s\"" msgstr "E456: ใใกใคใซ \"%s\" ใ้ใใพใใ" -#: ../hardcopy.c:2583 msgid "E456: Can't find PostScript resource file \"prolog.ps\"" msgstr "E456: PostScriptใฎใชใฝใผในใใกใคใซ \"prolog.ps\" ใ่ฆใคใใใพใใ" -#: ../hardcopy.c:2593 msgid "E456: Can't find PostScript resource file \"cidfont.ps\"" msgstr "E456: PostScriptใฎใชใฝใผในใใกใคใซ \"cidfont.ps\" ใ่ฆใคใใใพใใ" -#: ../hardcopy.c:2622 ../hardcopy.c:2639 ../hardcopy.c:2665 #, c-format msgid "E456: Can't find PostScript resource file \"%s.ps\"" msgstr "E456: PostScriptใฎใชใฝใผในใใกใคใซ \"%s.ps\" ใ่ฆใคใใใพใใ" -#: ../hardcopy.c:2654 #, c-format msgid "E620: Unable to convert to print encoding \"%s\"" msgstr "E620: ๅฐๅทใจใณใณใผใ \"%s\" ใธๅคๆใงใใพใใ" -#: ../hardcopy.c:2877 msgid "Sending to printer..." msgstr "ใใชใณใฟใซ้ไฟกไธญ..." -#: ../hardcopy.c:2881 msgid "E365: Failed to print PostScript file" msgstr "E365: PostScriptใใกใคใซใฎๅฐๅทใซๅคฑๆใใพใใ" -#: ../hardcopy.c:2883 msgid "Print job sent." msgstr "ๅฐๅทใธใงใใ้ไฟกใใพใใ." -#: ../if_cscope.c:85 msgid "Add a new database" msgstr "ๆฐใใผใฟใใผในใ่ฟฝๅ " -#: ../if_cscope.c:87 msgid "Query for a pattern" msgstr "ใใฟใผใณใฎใฏใจใชใผใ่ฟฝๅ " -#: ../if_cscope.c:89 msgid "Show this message" msgstr "ใใฎใกใใปใผใธใ่กจ็คบใใ" -#: ../if_cscope.c:91 msgid "Kill a connection" msgstr "ๆฅ็ถใ็ตไบใใ" -#: ../if_cscope.c:93 msgid "Reinit all connections" msgstr "ๅ
จใฆใฎๆฅ็ถใๅๅๆๅใใ" -#: ../if_cscope.c:95 msgid "Show connections" msgstr "ๆฅ็ถใ่กจ็คบใใ" -#: ../if_cscope.c:101 #, c-format msgid "E560: Usage: cs[cope] %s" msgstr "E560: ไฝฟ็จๆนๆณ: cs[cope] %s" -#: ../if_cscope.c:225 msgid "This cscope command does not support splitting the window.\n" msgstr "ใใฎcscopeใณใใณใใฏๅๅฒใฆใฃใณใใฆใงใฏใตใใผใใใใพใใ.\n" -#: ../if_cscope.c:266 msgid "E562: Usage: cstag <ident>" msgstr "E562: ไฝฟ็จๆณ: cstag <ident>" -#: ../if_cscope.c:313 msgid "E257: cstag: tag not found" msgstr "E257: cstag: ใฟใฐใ่ฆใคใใใพใใ" -#: ../if_cscope.c:461 #, c-format msgid "E563: stat(%s) error: %d" msgstr "E563: stat(%s) ใจใฉใผ: %d" -#: ../if_cscope.c:551 +msgid "E563: stat error" +msgstr "E563: stat ใจใฉใผ" + #, c-format msgid "E564: %s is not a directory or a valid cscope database" msgstr "E564: %s ใฏใใฃใฌใฏใใชๅใณๆๅนใชcscopeใฎใใผใฟใใผในใงใฏใใใพใใ" -#: ../if_cscope.c:566 #, c-format msgid "Added cscope database %s" msgstr "cscopeใใผใฟใใผใน %s ใ่ฟฝๅ " -#: ../if_cscope.c:616 #, c-format -msgid "E262: error reading cscope connection %<PRId64>" -msgstr "E262: cscopeใฎๆฅ็ถ %<PRId64> ใ่ชญ่พผใฟไธญใฎใจใฉใผใงใ" +msgid "E262: error reading cscope connection %ld" +msgstr "E262: cscopeใฎๆฅ็ถ %ld ใ่ชญ่พผใฟไธญใฎใจใฉใผใงใ" -#: ../if_cscope.c:711 msgid "E561: unknown cscope search type" msgstr "E561: ๆช็ฅใฎcscopeๆค็ดขๅใงใ" -#: ../if_cscope.c:752 ../if_cscope.c:789 msgid "E566: Could not create cscope pipes" msgstr "E566: cscopeใใคใใไฝๆใงใใพใใใงใใ" -#: ../if_cscope.c:767 msgid "E622: Could not fork for cscope" msgstr "E622: cscopeใฎ่ตทๅๆบๅ(fork)ใซๅคฑๆใใพใใ" -#: ../if_cscope.c:849 msgid "cs_create_connection setpgid failed" msgstr "cs_create_connection ใธใฎ setpgid ใซๅคฑๆใใพใใ" -#: ../if_cscope.c:853 ../if_cscope.c:889 msgid "cs_create_connection exec failed" msgstr "cs_create_connection ใฎๅฎ่กใซๅคฑๆใใพใใ" -#: ../if_cscope.c:863 ../if_cscope.c:902 msgid "cs_create_connection: fdopen for to_fp failed" msgstr "cs_create_connection: to_fp ใฎ fdopen ใซๅคฑๆใใพใใ" -#: ../if_cscope.c:865 ../if_cscope.c:906 msgid "cs_create_connection: fdopen for fr_fp failed" msgstr "cs_create_connection: fr_fp ใฎ fdopen ใซๅคฑๆใใพใใ" -#: ../if_cscope.c:890 msgid "E623: Could not spawn cscope process" msgstr "E623: cscopeใใญใปในใ่ตทๅใงใใพใใใงใใ" -#: ../if_cscope.c:932 msgid "E567: no cscope connections" msgstr "E567: cscopeๆฅ็ถใซๅคฑๆใใพใใ" -#: ../if_cscope.c:1009 #, c-format msgid "E469: invalid cscopequickfix flag %c for %c" msgstr "E469: ็กๅนใช cscopequickfix ใใฉใฐ %c ใฎ %c ใงใ" -#: ../if_cscope.c:1058 #, c-format msgid "E259: no matches found for cscope query %s of %s" msgstr "E259: cscopeใฏใจใชใผ %s of %s ใซ่ฉฒๅฝใใใใพใใใงใใ" -#: ../if_cscope.c:1142 msgid "cscope commands:\n" msgstr "cscopeใณใใณใ:\n" -#: ../if_cscope.c:1150 #, c-format msgid "%-5s: %s%*s (Usage: %s)" msgstr "%-5s: %s%*s (ไฝฟ็จๆณ: %s)" -#: ../if_cscope.c:1155 msgid "" "\n" +" a: Find assignments to this symbol\n" " c: Find functions calling this function\n" " d: Find functions called by this function\n" " e: Find this egrep pattern\n" @@ -3233,6 +2549,7 @@ msgid "" " t: Find this text string\n" msgstr "" "\n" +" a: ใใฎใทใณใใซใซๅฏพใใไปฃๅ
ฅใๆขใ\n" " c: ใใฎ้ขๆฐใๅผใใงใใ้ขๆฐใๆขใ\n" " d: ใใฎ้ขๆฐใใๅผใใงใใ้ขๆฐใๆขใ\n" " e: ใใฎegrepใใฟใผใณใๆขใ\n" @@ -3242,31 +2559,32 @@ msgstr "" " s: ใใฎCใทใณใใซใๆขใ\n" " t: ใใฎใใญในใๆๅญๅใๆขใ\n" -#: ../if_cscope.c:1226 +#, c-format +msgid "E625: cannot open cscope database: %s" +msgstr "E625: cscopeใใผใฟใใผใน: %s ใ้ใใใจใใงใใพใใ" + +msgid "E626: cannot get cscope database information" +msgstr "E626: cscopeใใผใฟใใผในใฎๆ
ๅ ฑใๅๅพใงใใพใใ" + msgid "E568: duplicate cscope database not added" msgstr "E568: ้่คใใcscopeใใผใฟใใผในใฏ่ฟฝๅ ใใใพใใใงใใ" -#: ../if_cscope.c:1335 #, c-format msgid "E261: cscope connection %s not found" msgstr "E261: cscopeๆฅ็ถ %s ใ่ฆใคใใใพใใใงใใ" -#: ../if_cscope.c:1364 #, c-format msgid "cscope connection %s closed" msgstr "cscopeๆฅ็ถ %s ใ้ใใใใพใใ" #. should not reach here -#: ../if_cscope.c:1486 msgid "E570: fatal error in cs_manage_matches" msgstr "E570: cs_manage_matches ใง่ดๅฝ็ใชใจใฉใผใงใ" -#: ../if_cscope.c:1693 #, c-format msgid "Cscope tag: %s" msgstr "Cscope ใฟใฐ: %s" -#: ../if_cscope.c:1711 msgid "" "\n" " # line" @@ -3274,87 +2592,300 @@ msgstr "" "\n" " # ่ก็ชๅท" -#: ../if_cscope.c:1713 msgid "filename / context / line\n" msgstr "ใใกใคใซๅ / ๆ่ / ่ก\n" -#: ../if_cscope.c:1809 #, c-format msgid "E609: Cscope error: %s" msgstr "E609: cscopeใจใฉใผ: %s" -#: ../if_cscope.c:2053 msgid "All cscope databases reset" msgstr "ๅ
จใฆใฎcscopeใใผใฟใใผในใใชใปใใใใพใ" -#: ../if_cscope.c:2123 msgid "no cscope connections\n" msgstr "cscopeๆฅ็ถใใใใพใใ\n" -#: ../if_cscope.c:2126 msgid " # pid database name prepend path\n" msgstr " # pid ใใผใฟใใผในๅ prepend ใใน\n" -#: ../main.c:144 +msgid "Lua library cannot be loaded." +msgstr "Luaใฉใคใใฉใชใใญใผใใงใใพใใ." + +msgid "cannot save undo information" +msgstr "ใขใณใใฅๆ
ๅ ฑใไฟๅญใงใใพใใ" + +msgid "" +"E815: Sorry, this command is disabled, the MzScheme libraries could not be " +"loaded." +msgstr "E815: ใใฎใณใใณใใฏ็กๅนใงใ. MzScheme ใฉใคใใฉใชใใญใผใใงใใพใใ." + +msgid "" +"E895: Sorry, this command is disabled, the MzScheme's racket/base module " +"could not be loaded." +msgstr "" +"E895: ใใฎใณใใณใใฏ็กๅนใงใ,ใใใใชใใ. MzScheme ใฎ racket/base ใขใธใฅใผใซ" +"ใใญใผใใงใใพใใใงใใ." + +msgid "invalid expression" +msgstr "็กๅนใชๅผใงใ" + +msgid "expressions disabled at compile time" +msgstr "ๅผใฏใณใณใใคใซๆใซ็กๅนใซใใใฆใใพใ" + +msgid "hidden option" +msgstr "้ ใใชใใทใงใณ" + +msgid "unknown option" +msgstr "ๆช็ฅใฎใชใใทใงใณใงใ" + +msgid "window index is out of range" +msgstr "็ฏๅฒๅคใฎใฆใฃใณใใฆ็ชๅทใงใ" + +msgid "couldn't open buffer" +msgstr "ใใใใกใ้ใใพใใ" + +msgid "cannot delete line" +msgstr "่กใๆถใใพใใ" + +msgid "cannot replace line" +msgstr "่กใ็ฝฎๆใงใใพใใ" + +msgid "cannot insert line" +msgstr "่กใๆฟๅ
ฅใงใใพใใ" + +msgid "string cannot contain newlines" +msgstr "ๆๅญๅใซใฏๆน่กๆๅญใๅซใใใใพใใ" + +msgid "error converting Scheme values to Vim" +msgstr "SchemeๅคใฎVimใธใฎๅคๆใจใฉใผ" + +msgid "Vim error: ~a" +msgstr "Vim ใจใฉใผ: ~a" + +msgid "Vim error" +msgstr "Vim ใจใฉใผ" + +msgid "buffer is invalid" +msgstr "ใใใใกใฏ็กๅนใงใ" + +msgid "window is invalid" +msgstr "ใฆใฃใณใใฆใฏ็กๅนใงใ" + +msgid "linenr out of range" +msgstr "็ฏๅฒๅคใฎ่ก็ชๅทใงใ" + +msgid "not allowed in the Vim sandbox" +msgstr "ใตใณใใใใฏในใงใฏ่จฑใใใพใใ" + +msgid "E836: This Vim cannot execute :python after using :py3" +msgstr "E836: ใใฎVimใงใฏ :py3 ใไฝฟใฃใๅพใซ :python ใไฝฟใใพใใ" + +msgid "" +"E263: Sorry, this command is disabled, the Python library could not be " +"loaded." +msgstr "" +"E263: ใใฎใณใใณใใฏ็กๅนใงใ,ใใใใชใใ: Pythonใฉใคใใฉใชใใญใผใใงใใพใใ" +"ใงใใ." + +msgid "" +"E887: Sorry, this command is disabled, the Python's site module could not be " +"loaded." +msgstr "" +"E887: ใใฎใณใใณใใฏ็กๅนใงใ,ใใใใชใใ. Python ใฎ site ใขใธใฅใผใซใใญใผใ" +"ใงใใพใใใงใใ." + +# Added at 07-Feb-2004. +msgid "E659: Cannot invoke Python recursively" +msgstr "E659: Python ใๅๅธฐ็ใซๅฎ่กใใใใจใฏใงใใพใใ" + +msgid "E837: This Vim cannot execute :py3 after using :python" +msgstr "E837: ใใฎVimใงใฏ :python ใไฝฟใฃใๅพใซ :py3 ใไฝฟใใพใใ" + +msgid "E265: $_ must be an instance of String" +msgstr "E265: $_ ใฏๆๅญๅใฎใคใณในใฟใณในใงใชใใใฐใชใใพใใ" + +msgid "" +"E266: Sorry, this command is disabled, the Ruby library could not be loaded." +msgstr "" +"E266: ใใฎใณใใณใใฏ็กๅนใงใ,ใใใใชใใ: Rubyใฉใคใใฉใชใใญใผใใงใใพใใใง" +"ใใ." + +msgid "E267: unexpected return" +msgstr "E267: ไบๆใใฌ return ใงใ" + +msgid "E268: unexpected next" +msgstr "E268: ไบๆใใฌ next ใงใ" + +msgid "E269: unexpected break" +msgstr "E269: ไบๆใใฌ break ใงใ" + +msgid "E270: unexpected redo" +msgstr "E270: ไบๆใใฌ redo ใงใ" + +msgid "E271: retry outside of rescue clause" +msgstr "E271: rescue ใฎๅคใฎ retry ใงใ" + +msgid "E272: unhandled exception" +msgstr "E272: ๅใๆฑใใใชใใฃใไพๅคใใใใพใ" + +#, c-format +msgid "E273: unknown longjmp status %d" +msgstr "E273: ๆช็ฅใฎlongjmp็ถๆ
: %d" + +msgid "invalid buffer number" +msgstr "็กๅนใชใใใใก็ชๅทใงใ" + +msgid "not implemented yet" +msgstr "ใพใ ๅฎ่ฃ
ใใใฆใใพใใ" + +#. ??? +msgid "cannot set line(s)" +msgstr "่กใ่จญๅฎใงใใพใใ" + +msgid "invalid mark name" +msgstr "็กๅนใชใใผใฏๅใงใ" + +msgid "mark not set" +msgstr "ใใผใฏใฏ่จญๅฎใใใฆใใพใใ" + +#, c-format +msgid "row %d column %d" +msgstr "่ก %d ๅ %d" + +msgid "cannot insert/append line" +msgstr "่กใฎๆฟๅ
ฅ/่ฟฝๅ ใใงใใพใใ" + +msgid "line number out of range" +msgstr "็ฏๅฒๅคใฎ่ก็ชๅทใงใ" + +msgid "unknown flag: " +msgstr "ๆช็ฅใฎใใฉใฐ: " + +msgid "unknown vimOption" +msgstr "ๆช็ฅใฎ vimOption ใงใ" + +msgid "keyboard interrupt" +msgstr "ใญใผใใผใๅฒ่พผใฟ" + +msgid "vim error" +msgstr "vim ใจใฉใผ" + +msgid "cannot create buffer/window command: object is being deleted" +msgstr "" +"ใใใใก/ใฆใฃใณใใฆไฝๆใณใใณใใไฝๆใงใใพใใ: ใชใใธใงใฏใใๆถๅปใใใฆใใพ" +"ใใ" + +msgid "" +"cannot register callback command: buffer/window is already being deleted" +msgstr "" +"ใณใผใซใใใฏใณใใณใใ็ป้ฒใงใใพใใ: ใใใใก/ใฆใฃใณใใฆใๆขใซๆถๅปใใใพใใ" + +#. This should never happen. Famous last word? +msgid "" +"E280: TCL FATAL ERROR: reflist corrupt!? Please report this to vim-dev@vim." +"org" +msgstr "" +"E280: TCL ่ดๅฝ็ใจใฉใผ: reflist ๆฑๆ!? vim-dev@vim.org ใซๅ ฑๅใใฆใใ ใใ" + +msgid "cannot register callback command: buffer/window reference not found" +msgstr "" +"ใณใผใซใใใฏใณใใณใใ็ป้ฒใงใใพใใ: ใใใใก/ใฆใฃใณใใฆใฎๅ็
งใ่ฆใคใใใพใ" +"ใ" + +msgid "" +"E571: Sorry, this command is disabled: the Tcl library could not be loaded." +msgstr "" +"E571: ใใฎใณใใณใใฏ็กๅนใงใ,ใใใใชใใ: Tclใฉใคใใฉใชใใญใผใใงใใพใใใง" +"ใใ." + +#, c-format +msgid "E572: exit code %d" +msgstr "E572: ็ตไบใณใผใ %d" + +msgid "cannot get line" +msgstr "่กใๅๅพใงใใพใใ" + +msgid "Unable to register a command server name" +msgstr "ๅฝไปคใตใผใใผใฎๅๅใ็ป้ฒใงใใพใใ" + +msgid "E248: Failed to send command to the destination program" +msgstr "E248: ็ฎ็ใฎใใญใฐใฉใ ใธใฎใณใใณใ้ไฟกใซๅคฑๆใใพใใ" + +#, c-format +msgid "E573: Invalid server id used: %s" +msgstr "E573: ็กๅนใชใตใผใใผIDใไฝฟใใใพใใ: %s" + +msgid "E251: VIM instance registry property is badly formed. Deleted!" +msgstr "E251: VIM ๅฎไฝใฎ็ป้ฒใใญใใใฃใไธๆญฃใงใ. ๆถๅปใใพใใ!" + +#, c-format +msgid "E696: Missing comma in List: %s" +msgstr "E696: ใชในใๅใซใซใณใใใใใพใใ: %s" + +#, c-format +msgid "E697: Missing end of List ']': %s" +msgstr "E697: ใชในใๅใฎๆๅพใซ ']' ใใใใพใใ: %s" + msgid "Unknown option argument" msgstr "ๆช็ฅใฎใชใใทใงใณๅผๆฐใงใ" -#: ../main.c:146 msgid "Too many edit arguments" msgstr "็ทจ้ๅผๆฐใๅค้ใใพใ" -#: ../main.c:148 msgid "Argument missing after" msgstr "ๅผๆฐใใใใพใใ" -#: ../main.c:150 msgid "Garbage after option argument" msgstr "ใชใใทใงใณๅผๆฐใฎๅพใซใดใใใใใพใ" -#: ../main.c:152 msgid "Too many \"+command\", \"-c command\" or \"--cmd command\" arguments" msgstr "\"+command\", \"-c command\", \"--cmd command\" ใฎๅผๆฐใๅค้ใใพใ" -#: ../main.c:154 msgid "Invalid argument for" msgstr "็กๅนใชๅผๆฐใงใ: " -#: ../main.c:294 #, c-format msgid "%d files to edit\n" msgstr "%d ๅใฎใใกใคใซใ็ทจ้ใๆงใใฆใใพใ\n" -#: ../main.c:1342 +msgid "netbeans is not supported with this GUI\n" +msgstr "netbeans ใฏใใฎGUIใงใฏๅฉ็จใงใใพใใ\n" + +msgid "'-nb' cannot be used: not enabled at compile time\n" +msgstr "'-nb' ไฝฟ็จไธๅฏ่ฝใงใ: ใณใณใใคใซๆใซ็กๅนใซใใใฆใใพใ\n" + +msgid "This Vim was not compiled with the diff feature." +msgstr "ใใฎVimใซใฏdiffๆฉ่ฝใใใใพใใ(ใณใณใใคใซๆ่จญๅฎ)." + msgid "Attempt to open script file again: \"" msgstr "ในใฏใชใใใใกใคใซใๅใณ้ใใฆใฟใพใ: \"" -#: ../main.c:1350 msgid "Cannot open for reading: \"" msgstr "่ชญ่พผ็จใจใใฆ้ใใพใใ" -#: ../main.c:1393 msgid "Cannot open for script output: \"" msgstr "ในใฏใชใใๅบๅ็จใ้ใใพใใ" -#: ../main.c:1622 +msgid "Vim: Error: Failure to start gvim from NetBeans\n" +msgstr "Vim: ใจใฉใผ: NetBeansใใgvimใในใฟใผใใงใใพใใ\n" + +msgid "Vim: Error: This version of Vim does not run in a Cygwin terminal\n" +msgstr "Vim: ใจใฉใผ: ใใฎใใผใธใงใณใฎVimใฏCygwin็ซฏๆซใงใฏๅไฝใใพใใ\n" + msgid "Vim: Warning: Output is not to a terminal\n" msgstr "Vim: ่ญฆๅ: ็ซฏๆซใธใฎๅบๅใงใฏใใใพใใ\n" -#: ../main.c:1624 msgid "Vim: Warning: Input is not from a terminal\n" msgstr "Vim: ่ญฆๅ: ็ซฏๆซใใใฎๅ
ฅๅใงใฏใใใพใใ\n" #. just in case.. -#: ../main.c:1891 msgid "pre-vimrc command line" msgstr "vimrcๅใฎใณใใณใใฉใคใณ" -#: ../main.c:1964 #, c-format msgid "E282: Cannot read from \"%s\"" msgstr "E282: \"%s\"ใใ่ชญ่พผใใใจใใงใใพใใ" -#: ../main.c:2149 msgid "" "\n" "More info with: \"vim -h\"\n" @@ -3362,23 +2893,18 @@ msgstr "" "\n" "ใใ่ฉณ็ดฐใชๆ
ๅ ฑใฏ: \"vim -h\"\n" -#: ../main.c:2178 msgid "[file ..] edit specified file(s)" msgstr "[ใใกใคใซ..] ใใใใกใคใซใ็ทจ้ใใ" -#: ../main.c:2179 msgid "- read text from stdin" msgstr "- ๆจๆบๅ
ฅๅใใใใญในใใ่ชญ่พผใ" -#: ../main.c:2180 msgid "-t tag edit file where tag is defined" msgstr "-t ใฟใฐ ใฟใฐใๅฎ็พฉใใใใจใใใใ็ทจ้ใใ" -#: ../main.c:2181 msgid "-q [errorfile] edit file with first error" msgstr "-q [errorfile] ๆๅใฎใจใฉใผใง็ทจ้ใใ" -#: ../main.c:2187 msgid "" "\n" "\n" @@ -3388,11 +2914,9 @@ msgstr "" "\n" "ไฝฟ็จๆณ:" -#: ../main.c:2189 msgid " vim [arguments] " msgstr " vim [ๅผๆฐ] " -#: ../main.c:2193 msgid "" "\n" " or:" @@ -3400,7 +2924,13 @@ msgstr "" "\n" " ใใใใฏ:" -#: ../main.c:2196 +msgid "" +"\n" +"Where case is ignored prepend / to make flag upper case" +msgstr "" +"\n" +"ๅคงๅฐๆๅญใ็ก่ฆใใใๅ ดๅใฏๅคงๆๅญใซใใใใใซ / ใๅ็ฝฎใใฆใใ ใใ" + msgid "" "\n" "\n" @@ -3410,189 +2940,319 @@ msgstr "" "\n" "ๅผๆฐ:\n" -#: ../main.c:2197 msgid "--\t\t\tOnly file names after this" msgstr "--\t\t\tใใฎใใจใซใฏใใกใคใซๅใ ใ" -#: ../main.c:2199 msgid "--literal\t\tDon't expand wildcards" msgstr "--literal\t\tใฏใคใซใใซใผใใๅฑ้ใใชใ" -#: ../main.c:2201 +msgid "-register\t\tRegister this gvim for OLE" +msgstr "-register\t\tใใฎgvimใOLEใจใใฆ็ป้ฒใใ" + +msgid "-unregister\t\tUnregister gvim for OLE" +msgstr "-unregister\t\tgvimใฎOLE็ป้ฒใ่งฃ้คใใ" + +msgid "-g\t\t\tRun using GUI (like \"gvim\")" +msgstr "-g\t\t\tGUIใง่ตทๅใใ (\"gvim\" ใจๅใ)" + +msgid "-f or --nofork\tForeground: Don't fork when starting GUI" +msgstr "-f or --nofork\tใใฉใขใฐใฉใฆใณใ: GUIใๅงใใใจใใซforkใใชใ" + msgid "-v\t\t\tVi mode (like \"vi\")" msgstr "-v\t\t\tViใขใผใ (\"vi\" ใจๅใ)" -#: ../main.c:2202 msgid "-e\t\t\tEx mode (like \"ex\")" msgstr "-e\t\t\tExใขใผใ (\"ex\" ใจๅใ)" -#: ../main.c:2203 msgid "-E\t\t\tImproved Ex mode" msgstr "-E\t\t\tๆน่ฏExใขใผใ" -#: ../main.c:2204 msgid "-s\t\t\tSilent (batch) mode (only for \"ex\")" msgstr "-s\t\t\tใตใคใฌใณใ(ใใใ)ใขใผใ (\"ex\" ๅฐ็จ)" -#: ../main.c:2205 msgid "-d\t\t\tDiff mode (like \"vimdiff\")" msgstr "-d\t\t\tๅทฎๅใขใผใ (\"vidiff\" ใจๅใ)" -#: ../main.c:2206 msgid "-y\t\t\tEasy mode (like \"evim\", modeless)" msgstr "-y\t\t\tใคใผใธใผใขใผใ (\"evim\" ใจๅใ, ใขใผใ็ก)" -#: ../main.c:2207 msgid "-R\t\t\tReadonly mode (like \"view\")" msgstr "-R\t\t\t่ชญ่พผๅฐ็จใขใผใ (\"view\" ใจๅใ)" -#: ../main.c:2208 msgid "-Z\t\t\tRestricted mode (like \"rvim\")" msgstr "-Z\t\t\tๅถ้ใขใผใ (\"rvim\" ใจๅใ)" -#: ../main.c:2209 msgid "-m\t\t\tModifications (writing files) not allowed" msgstr "-m\t\t\tๅคๆด (ใใกใคใซไฟๅญๆ) ใใงใใชใใใใซใใ" -#: ../main.c:2210 msgid "-M\t\t\tModifications in text not allowed" msgstr "-M\t\t\tใใญในใใฎ็ทจ้ใ่กใชใใชใใใใซใใ" -#: ../main.c:2211 msgid "-b\t\t\tBinary mode" msgstr "-b\t\t\tใใคใใชใขใผใ" -#: ../main.c:2212 msgid "-l\t\t\tLisp mode" msgstr "-l\t\t\tLispใขใผใ" -#: ../main.c:2213 msgid "-C\t\t\tCompatible with Vi: 'compatible'" msgstr "-C\t\t\tViไบๆใขใผใ: 'compatible'" -#: ../main.c:2214 msgid "-N\t\t\tNot fully Vi compatible: 'nocompatible'" msgstr "-N\t\t\tVi้ไบๆใขใผใ: 'nocompatible" -#: ../main.c:2215 msgid "-V[N][fname]\t\tBe verbose [level N] [log messages to fname]" msgstr "-V[N][fname]\t\tใญใฐๅบๅ่จญๅฎ [ใฌใใซ N] [ใญใฐใใกใคใซๅ fname]" -#: ../main.c:2216 msgid "-D\t\t\tDebugging mode" msgstr "-D\t\t\tใใใใฐใขใผใ" -#: ../main.c:2217 msgid "-n\t\t\tNo swap file, use memory only" msgstr "-n\t\t\tในใฏใใใใกใคใซใไฝฟ็จใใใกใขใชใ ใ" -#: ../main.c:2218 msgid "-r\t\t\tList swap files and exit" msgstr "-r\t\t\tในใฏใใใใกใคใซใๅๆใ็ตไบ" -#: ../main.c:2219 msgid "-r (with file name)\tRecover crashed session" msgstr "-r (ใใกใคใซๅ)\tใฏใฉใใทใฅใใใปใใทใงใณใๅพฉๅธฐ" -#: ../main.c:2220 msgid "-L\t\t\tSame as -r" msgstr "-L\t\t\t-rใจๅใ" -#: ../main.c:2221 +msgid "-f\t\t\tDon't use newcli to open window" +msgstr "-f\t\t\tใฆใฃใณใใฆใ้ใใฎใซ newcli ใไฝฟ็จใใชใ" + +msgid "-dev <device>\t\tUse <device> for I/O" +msgstr "-dev <device>\t\tI/Oใซ <device> ใไฝฟ็จใใ" + msgid "-A\t\t\tstart in Arabic mode" msgstr "-A\t\t\tใขใฉใใข่ชใขใผใใง่ตทๅใใ" -#: ../main.c:2222 msgid "-H\t\t\tStart in Hebrew mode" msgstr "-H\t\t\tใใใฉใค่ชใขใผใใง่ตทๅใใ" -#: ../main.c:2223 msgid "-F\t\t\tStart in Farsi mode" msgstr "-F\t\t\tใใซใทใข่ชใขใผใใง่ตทๅใใ" -#: ../main.c:2224 msgid "-T <terminal>\tSet terminal type to <terminal>" msgstr "-T <terminal>\t็ซฏๆซใ <terminal> ใซ่จญๅฎใใ" -#: ../main.c:2225 +msgid "--not-a-term\t\tSkip warning for input/output not being a terminal" +msgstr "--not-a-term\t\tๅ
ฅๅบๅใ็ซฏๆซใงใชใใจใฎ่ญฆๅใในใญใใใใ" + msgid "-u <vimrc>\t\tUse <vimrc> instead of any .vimrc" msgstr "-u <vimrc>\t\t.vimrcใฎไปฃใใใซ <vimrc> ใไฝฟใ" -#: ../main.c:2226 +msgid "-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc" +msgstr "-U <gvimrc>\t\t.gvimrcใฎไปฃใใใซ <gvimrc> ใไฝฟใ" + msgid "--noplugin\t\tDon't load plugin scripts" msgstr "--noplugin\t\tใใฉใฐใคใณในใฏใชใใใใญใผใใใชใ" -#: ../main.c:2227 msgid "-p[N]\t\tOpen N tab pages (default: one for each file)" msgstr "-p[N]\t\tN ๅใฟใใใผใธใ้ใ(็็ฅๅค: ใใกใคใซใซใคใ1ๅ)" -#: ../main.c:2228 msgid "-o[N]\t\tOpen N windows (default: one for each file)" msgstr "-o[N]\t\tN ๅใฆใฃใณใใฆใ้ใ(็็ฅๅค: ใใกใคใซใซใคใ1ๅ)" -#: ../main.c:2229 msgid "-O[N]\t\tLike -o but split vertically" msgstr "-O[N]\t\t-oใจๅใใ ใๅ็ดๅๅฒ" -#: ../main.c:2230 msgid "+\t\t\tStart at end of file" msgstr "+\t\t\tใใกใคใซใฎๆๅพใใใฏใใใ" -#: ../main.c:2231 msgid "+<lnum>\t\tStart at line <lnum>" msgstr "+<lnum>\t\t<lnum> ่กใใใฏใใใ" -#: ../main.c:2232 msgid "--cmd <command>\tExecute <command> before loading any vimrc file" msgstr "--cmd <command>\tvimrcใใญใผใใใๅใซ <command> ใๅฎ่กใใ" -#: ../main.c:2233 msgid "-c <command>\t\tExecute <command> after loading the first file" msgstr "-c <command>\t\tๆๅใฎใใกใคใซใใญใผใๅพ <command> ใๅฎ่กใใ" -#: ../main.c:2235 msgid "-S <session>\t\tSource file <session> after loading the first file" msgstr "-S <session>\t\tๆๅใฎใใกใคใซใใญใผใๅพใใกใคใซ <session> ใๅ่พผใ" -#: ../main.c:2236 msgid "-s <scriptin>\tRead Normal mode commands from file <scriptin>" msgstr "-s <scriptin>\tใใกใคใซ <scriptin> ใใใใผใใซใณใใณใใ่ชญ่พผใ" -#: ../main.c:2237 msgid "-w <scriptout>\tAppend all typed commands to file <scriptout>" msgstr "-w <scriptout>\tๅ
ฅๅใใๅ
จใณใใณใใใใกใคใซ <scriptout> ใซ่ฟฝๅ ใใ" -#: ../main.c:2238 msgid "-W <scriptout>\tWrite all typed commands to file <scriptout>" msgstr "-W <scriptout>\tๅ
ฅๅใใๅ
จใณใใณใใใใกใคใซ <scriptout> ใซไฟๅญใใ" -#: ../main.c:2240 +msgid "-x\t\t\tEdit encrypted files" +msgstr "-x\t\t\tๆๅทๅใใใใใกใคใซใ็ทจ้ใใ" + +msgid "-display <display>\tConnect vim to this particular X-server" +msgstr "-display <display>\tvimใๆๅฎใใ X ใตใผใใผใซๆฅ็ถใใ" + +msgid "-X\t\t\tDo not connect to X server" +msgstr "-X\t\t\tXใตใผใใผใซๆฅ็ถใใชใ" + +msgid "--remote <files>\tEdit <files> in a Vim server if possible" +msgstr "--remote <files>\tๅฏ่ฝใชใใฐVimใตใผใใผใง <files> ใ็ทจ้ใใ" + +msgid "--remote-silent <files> Same, don't complain if there is no server" +msgstr "--remote-silent <files> ๅไธ, ใตใผใใผใ็กใใฆใ่ญฆๅๆใๅบๅใใชใ" + +msgid "" +"--remote-wait <files> As --remote but wait for files to have been edited" +msgstr "--remote-wait <files>\t--remoteๅพ ใใกใคใซใฎ็ทจ้ใ็ตใใใฎใๅพ
ใค" + +msgid "" +"--remote-wait-silent <files> Same, don't complain if there is no server" +msgstr "" +"--remote-wait-silent <files> ๅไธ, ใตใผใใผใ็กใใฆใ่ญฆๅๆใๅบๅใใชใ" + +msgid "" +"--remote-tab[-wait][-silent] <files> As --remote but use tab page per file" +msgstr "" +"--remote-tab[-wait][-silent] <files> --remoteใงใใกใคใซ1ใคใซใคใ1ใคใฎใฟใ" +"ใใผใธใ้ใ" + +msgid "--remote-send <keys>\tSend <keys> to a Vim server and exit" +msgstr "--remote-send <keys>\tVimใตใผใใผใซ <keys> ใ้ไฟกใใฆ็ตไบใใ" + +msgid "--remote-expr <expr>\tEvaluate <expr> in a Vim server and print result" +msgstr "--remote-expr <expr>\tใตใผใใผใง <expr> ใๅฎ่กใใฆ็ตๆใ่กจ็คบใใ" + +msgid "--serverlist\t\tList available Vim server names and exit" +msgstr "--serverlist\t\tVimใตใผใใผๅใฎไธ่ฆงใ่กจ็คบใใฆ็ตไบใใ" + +msgid "--servername <name>\tSend to/become the Vim server <name>" +msgstr "--servername <name>\tVimใตใผใใผ <name> ใซ้ไฟก/ๅๅ่จญๅฎใใ" + msgid "--startuptime <file>\tWrite startup timing messages to <file>" msgstr "--startuptime <file>\t่ตทๅใซใใใฃใๆ้ใฎ่ฉณ็ดฐใ <file> ใธๅบๅใใ" -#: ../main.c:2242 msgid "-i <viminfo>\t\tUse <viminfo> instead of .viminfo" msgstr "-i <viminfo>\t\t.viminfoใฎไปฃใใใซ <viminfo> ใไฝฟใ" -#: ../main.c:2243 msgid "-h or --help\tPrint Help (this message) and exit" msgstr "-h or --help\tใใซใ(ใใฎใกใใปใผใธ)ใ่กจ็คบใ็ตไบใใ" -#: ../main.c:2244 msgid "--version\t\tPrint version information and exit" msgstr "--version\t\tใใผใธใงใณๆ
ๅ ฑใ่กจ็คบใ็ตไบใใ" -#: ../mark.c:676 +msgid "" +"\n" +"Arguments recognised by gvim (Motif version):\n" +msgstr "" +"\n" +"gvimใซใใฃใฆ่งฃ้ใใใๅผๆฐ(Motifใใผใธใงใณ):\n" + +msgid "" +"\n" +"Arguments recognised by gvim (neXtaw version):\n" +msgstr "" +"\n" +"gvimใซใใฃใฆ่งฃ้ใใใๅผๆฐ(neXtawใใผใธใงใณ):\n" + +msgid "" +"\n" +"Arguments recognised by gvim (Athena version):\n" +msgstr "" +"\n" +"gvimใซใใฃใฆ่งฃ้ใใใๅผๆฐ(Athenaใใผใธใงใณ):\n" + +msgid "-display <display>\tRun vim on <display>" +msgstr "-display <display>\t<display> ใงvimใๅฎ่กใใ" + +msgid "-iconic\t\tStart vim iconified" +msgstr "-iconic\t\tๆๅฐๅใใ็ถๆ
ใงvimใ่ตทๅใใ" + +msgid "-background <color>\tUse <color> for the background (also: -bg)" +msgstr "-background <color>\t่ๆฏ่ฒใซ <color> ใไฝฟใ(ๅ็พฉ: -bg)" + +msgid "-foreground <color>\tUse <color> for normal text (also: -fg)" +msgstr "-foreground <color>\tๅๆฏ่ฒใซ <color> ใไฝฟใ(ๅ็พฉ: -fg)" + +msgid "-font <font>\t\tUse <font> for normal text (also: -fn)" +msgstr "-font <font>\t\tใใญในใ่กจ็คบใซ <font> ใไฝฟใ(ๅ็พฉ: -fn)" + +msgid "-boldfont <font>\tUse <font> for bold text" +msgstr "-boldfont <font>\tๅคชๅญใซ <font> ใไฝฟใ" + +msgid "-italicfont <font>\tUse <font> for italic text" +msgstr "-italicfont <for>\tๆไฝๅญใซ <font> ใไฝฟใ" + +msgid "-geometry <geom>\tUse <geom> for initial geometry (also: -geom)" +msgstr "-geometry <geom>\tๅๆ้
็ฝฎใซ <geom> ใไฝฟใ(ๅ็พฉ: -geom)" + +msgid "-borderwidth <width>\tUse a border width of <width> (also: -bw)" +msgstr "-borderwidth <width>\tๅข็ใฎๅน
ใ <width> ใซใใ(ๅ็พฉ: -bw)" + +msgid "-scrollbarwidth <width> Use a scrollbar width of <width> (also: -sw)" +msgstr "" +"-scrollbarwidth <width> ในใฏใญใผใซใใผใฎๅน
ใ <width> ใซใใ(ๅ็พฉ: -sw)" + +msgid "-menuheight <height>\tUse a menu bar height of <height> (also: -mh)" +msgstr "-menuheight <height>\tใกใใฅใผใใผใฎ้ซใใ <height> ใซใใ(ๅ็พฉ: -mh)" + +msgid "-reverse\t\tUse reverse video (also: -rv)" +msgstr "-reverse\t\tๅ่ปขๆ ๅใไฝฟ็จใใ(ๅ็พฉ: -rv)" + +msgid "+reverse\t\tDon't use reverse video (also: +rv)" +msgstr "+reverse\t\tๅ่ปขๆ ๅใไฝฟ็จใใชใ(ๅ็พฉ: +rv)" + +msgid "-xrm <resource>\tSet the specified resource" +msgstr "-xrm <resource>\t็นๅฎใฎใชใฝใผในใไฝฟ็จใใ" + +msgid "" +"\n" +"Arguments recognised by gvim (GTK+ version):\n" +msgstr "" +"\n" +"gvimใซใใฃใฆ่งฃ้ใใใๅผๆฐ(GTK+ใใผใธใงใณ):\n" + +msgid "-display <display>\tRun vim on <display> (also: --display)" +msgstr "-display <display>\t<display> ใงvimใๅฎ่กใใ(ๅ็พฉ: --display)" + +msgid "--role <role>\tSet a unique role to identify the main window" +msgstr "--role <role>\tใกใคใณใฆใฃใณใใฆใ่ญๅฅใใไธๆใชๅฝนๅฒ(role)ใ่จญๅฎใใ" + +msgid "--socketid <xid>\tOpen Vim inside another GTK widget" +msgstr "--socketid <xid>\t็ฐใชใGTK widgetใงVimใ้ใ" + +msgid "--echo-wid\t\tMake gvim echo the Window ID on stdout" +msgstr "--echo-wid\t\tใฆใฃใณใใฆIDใๆจๆบๅบๅใซๅบๅใใ" + +msgid "-P <parent title>\tOpen Vim inside parent application" +msgstr "-P <่ฆชใฎใฟใคใใซ>\tVimใ่ฆชใขใใชใฑใผใทใงใณใฎไธญใง่ตทๅใใ" + +msgid "--windowid <HWND>\tOpen Vim inside another win32 widget" +msgstr "--windowid <HWND>\t็ฐใชใWin32 widgetใฎๅ
้จใซVimใ้ใ" + +msgid "No display" +msgstr "ใใฃในใใฌใคใ่ฆใคใใใพใใ" + +#. Failed to send, abort. +msgid ": Send failed.\n" +msgstr ": ้ไฟกใซๅคฑๆใใพใใ.\n" + +#. Let vim start normally. +msgid ": Send failed. Trying to execute locally\n" +msgstr ": ้ไฟกใซๅคฑๆใใพใใ. ใญใผใซใซใงใฎๅฎ่กใ่ฉฆใฟใฆใใพใ\n" + +#, c-format +msgid "%d of %d edited" +msgstr "%d ๅ (%d ๅไธญ) ใฎใใกใคใซใ็ทจ้ใใพใใ" + +msgid "No display: Send expression failed.\n" +msgstr "ใใฃในใใฌใคใใใใพใใ: ๅผใฎ้ไฟกใซๅคฑๆใใพใใ.\n" + +msgid ": Send expression failed.\n" +msgstr ": ๅผใฎ้ไฟกใซๅคฑๆใใพใใ.\n" + msgid "No marks set" msgstr "ใใผใฏใ่จญๅฎใใใฆใใพใใ" -#: ../mark.c:678 #, c-format msgid "E283: No marks matching \"%s\"" msgstr "E283: \"%s\" ใซ่ฉฒๅฝใใใใผใฏใใใใพใใ" #. Highlight title -#: ../mark.c:687 msgid "" "\n" "mark line col file/text" @@ -3601,7 +3261,6 @@ msgstr "" "mark ่ก ๅ ใใกใคใซ/ใใญในใ" #. Highlight title -#: ../mark.c:789 msgid "" "\n" " jump line col file/text" @@ -3610,7 +3269,6 @@ msgstr "" " jump ่ก ๅ ใใกใคใซ/ใใญในใ" #. Highlight title -#: ../mark.c:831 msgid "" "\n" "change line col text" @@ -3618,7 +3276,6 @@ msgstr "" "\n" "ๅคๆด ่ก ๅ ใใญในใ" -#: ../mark.c:1238 msgid "" "\n" "# File marks:\n" @@ -3627,7 +3284,6 @@ msgstr "" "# ใใกใคใซใใผใฏ:\n" #. Write the jumplist with -' -#: ../mark.c:1271 msgid "" "\n" "# Jumplist (newest first):\n" @@ -3635,7 +3291,6 @@ msgstr "" "\n" "# ใธใฃใณใใชในใ (ๆฐใใใใฎใๅ
):\n" -#: ../mark.c:1352 msgid "" "\n" "# History of marks within files (newest to oldest):\n" @@ -3643,84 +3298,88 @@ msgstr "" "\n" "# ใใกใคใซๅ
ใใผใฏใฎๅฑฅๆญด (ๆฐใใใใฎใใๅคใใใฎ):\n" -#: ../mark.c:1431 msgid "Missing '>'" msgstr "'>' ใ่ฆใคใใใพใใ" -#: ../memfile.c:426 +msgid "E543: Not a valid codepage" +msgstr "E543: ็กๅนใชใณใผใใใผใธใงใ" + +msgid "E284: Cannot set IC values" +msgstr "E284: ICใฎๅคใ่จญๅฎใงใใพใใ" + +msgid "E285: Failed to create input context" +msgstr "E285: ใคใณใใใใณใณใใญในใใฎไฝๆใซๅคฑๆใใพใใ" + +msgid "E286: Failed to open input method" +msgstr "E286: ใคใณใใใใกใฝใใใฎใชใผใใณใซๅคฑๆใใพใใ" + +msgid "E287: Warning: Could not set destroy callback to IM" +msgstr "E287: ่ญฆๅ: IMใฎ็ ดๅฃใณใผใซใใใฏใ่จญๅฎใงใใพใใใงใใ" + +msgid "E288: input method doesn't support any style" +msgstr "E288: ใคใณใใใใกใฝใใใฏใฉใใชในใฟใคใซใใตใใผใใใพใใ" + +msgid "E289: input method doesn't support my preedit type" +msgstr "E289: ใคใณใใใใกใฝใใใฏ my preedit type ใใตใใผใใใพใใ" + msgid "E293: block was not locked" msgstr "E293: ใใญใใฏใใญใใฏใใใฆใใพใใ" -#: ../memfile.c:799 msgid "E294: Seek error in swap file read" msgstr "E294: ในใฏใใใใกใคใซ่ชญ่พผๆใซใทใผใฏใจใฉใผใงใ" -#: ../memfile.c:803 msgid "E295: Read error in swap file" msgstr "E295: ในใฏใใใใกใคใซใฎ่ชญ่พผใฟใจใฉใผใงใ" -#: ../memfile.c:849 msgid "E296: Seek error in swap file write" msgstr "E296: ในใฏใใใใกใคใซๆธ่พผใฟๆใซใทใผใฏใจใฉใผใงใ" -#: ../memfile.c:865 msgid "E297: Write error in swap file" msgstr "E297: ในใฏใใใใกใคใซใฎๆธ่พผใฟใจใฉใผใงใ" -#: ../memfile.c:1036 msgid "E300: Swap file already exists (symlink attack?)" msgstr "E300: ในใฏใใใใกใคใซใๆขใซๅญๅจใใพใ (symlinkใซใใๆปๆ?)" -#: ../memline.c:318 msgid "E298: Didn't get block nr 0?" msgstr "E298: ใใญใใฏ 0 ใๅๅพใงใใพใใ?" -#: ../memline.c:361 msgid "E298: Didn't get block nr 1?" msgstr "E298: ใใญใใฏ 1 ใๅๅพใงใใพใใ?" -#: ../memline.c:377 msgid "E298: Didn't get block nr 2?" msgstr "E298: ใใญใใฏ 2 ใๅๅพใงใใพใใ?" +msgid "E843: Error while updating swap file crypt" +msgstr "E843: ในใฏใใใใกใคใซใฎๆๅทใๆดๆฐไธญใซใจใฉใผใ็บ็ใใพใใ" + #. could not (re)open the swap file, what can we do???? -#: ../memline.c:465 msgid "E301: Oops, lost the swap file!!!" msgstr "E301: ใใฃใจ, ในใฏใใใใกใคใซใๅคฑใใใพใใ!!!" -#: ../memline.c:477 msgid "E302: Could not rename swap file" msgstr "E302: ในใฏใใใใกใคใซใฎๅๅใๅคใใใใพใใ" -#: ../memline.c:554 #, c-format msgid "E303: Unable to open swap file for \"%s\", recovery impossible" msgstr "E303: \"%s\" ใฎในใฏใใใใกใคใซใ้ใใชใใฎใงใชใซใใชใฏไธๅฏ่ฝใงใ" -#: ../memline.c:666 msgid "E304: ml_upd_block0(): Didn't get block 0??" msgstr "E304: ml_upd_block0(): ใใญใใฏ 0 ใๅๅพใงใใพใใใงใใ??" -#. no swap files found -#: ../memline.c:830 #, c-format msgid "E305: No swap file found for %s" msgstr "E305: %s ใซใฏในใฏใใใใกใคใซใ่ฆใคใใใพใใ" -#: ../memline.c:839 msgid "Enter number of swap file to use (0 to quit): " msgstr "ไฝฟ็จใใในใฏใใใใกใคใซใฎ็ชๅทใๅ
ฅๅใใฆใใ ใใ(0 ใง็ตไบ): " -#: ../memline.c:879 #, c-format msgid "E306: Cannot open %s" msgstr "E306: %s ใ้ใใพใใ" -#: ../memline.c:897 msgid "Unable to read block 0 from " msgstr "ใใญใใฏ 0 ใ่ชญ่พผใใพใใ " -#: ../memline.c:900 msgid "" "\n" "Maybe no changes were made or Vim did not update the swap file." @@ -3728,28 +3387,22 @@ msgstr "" "\n" "ๆใใๅคๆดใใใใฆใใชใใVimใในใฏใใใใกใคใซใๆดๆฐใใฆใใพใใ." -#: ../memline.c:909 msgid " cannot be used with this version of Vim.\n" msgstr " Vimใฎใใฎใใผใธใงใณใงใฏไฝฟ็จใงใใพใใ.\n" -#: ../memline.c:911 msgid "Use Vim version 3.0.\n" msgstr "Vimใฎใใผใธใงใณ3.0ใไฝฟ็จใใฆใใ ใใ.\n" -#: ../memline.c:916 #, c-format msgid "E307: %s does not look like a Vim swap file" msgstr "E307: %s ใฏVimใฎในใฏใใใใกใคใซใงใฏใชใใใใงใ" -#: ../memline.c:922 msgid " cannot be used on this computer.\n" msgstr " ใใฎใณใณใใฅใผใฟใงใฏไฝฟ็จใงใใพใใ.\n" -#: ../memline.c:924 msgid "The file was created on " msgstr "ใใฎใใกใคใซใฏๆฌกใฎๅ ดๆใงไฝใใใพใใ " -#: ../memline.c:928 msgid "" ",\n" "or the file has been damaged." @@ -3757,85 +3410,104 @@ msgstr "" ",\n" "ใใใใฏใใกใคใซใๆๅทใใฆใใพใ." -#: ../memline.c:945 +#, c-format +msgid "" +"E833: %s is encrypted and this version of Vim does not support encryption" +msgstr "" +"E833: %s ใฏใใฎใใผใธใงใณใฎVimใงใตใใผใใใฆใใชใๅฝขๅผใงๆๅทๅใใใฆใใพใ" + msgid " has been damaged (page size is smaller than minimum value).\n" msgstr " ใฏๆๅทใใฆใใพใ (ใใผใธใตใคใบใๆๅฐๅคใไธๅใฃใฆใใพใ).\n" -#: ../memline.c:974 #, c-format msgid "Using swap file \"%s\"" msgstr "ในใฏใใใใกใคใซ \"%s\" ใไฝฟ็จไธญ" -#: ../memline.c:980 #, c-format msgid "Original file \"%s\"" msgstr "ๅๆฌใใกใคใซ \"%s\"" -#: ../memline.c:995 msgid "E308: Warning: Original file may have been changed" msgstr "E308: ่ญฆๅ: ๅๆฌใใกใคใซใๅคๆดใใใฆใใพใ" -#: ../memline.c:1061 +#, c-format +msgid "Swap file is encrypted: \"%s\"" +msgstr "ในใฏใใใใกใคใซใฏๆๅทๅใใใฆใใพใ: \"%s\"" + +msgid "" +"\n" +"If you entered a new crypt key but did not write the text file," +msgstr "" +"\n" +"ๆฐใใๆๅทใญใผใๅ
ฅๅใใใใจใซใใญในใใใกใคใซใไฟๅญใใฆใใชใๅ ดๅใฏ," + +msgid "" +"\n" +"enter the new crypt key." +msgstr "" +"\n" +"ๆฐใใๆๅทใญใผใๅ
ฅๅใใฆใใ ใใ." + +msgid "" +"\n" +"If you wrote the text file after changing the crypt key press enter" +msgstr "" +"\n" +"ๆๅทใญใผใๅคใใใใจใซใใญในใใใกใคใซใไฟๅญใใๅ ดๅใฏ, ใใญในใใใกใคใซใจ" + +msgid "" +"\n" +"to use the same key for text file and swap file" +msgstr "" +"\n" +"ในใฏใใใใกใคใซใซๅใๆๅทใญใผใไฝฟใใใใซenterใ ใใๆผใใฆใใ ใใ." + #, c-format msgid "E309: Unable to read block 1 from %s" msgstr "E309: %s ใใใใญใใฏ 1 ใ่ชญ่พผใใพใใ" -#: ../memline.c:1065 msgid "???MANY LINES MISSING" msgstr "???ๅคใใฎ่กใๅคฑใใใฆใใพใ" -#: ../memline.c:1076 msgid "???LINE COUNT WRONG" msgstr "???่กๆฐใ้้ใฃใฆใใพใ" -#: ../memline.c:1082 msgid "???EMPTY BLOCK" msgstr "???ใใญใใฏใ็ฉบใงใ" -#: ../memline.c:1103 msgid "???LINES MISSING" msgstr "???่กใๅคฑใใใฆใใพใ" -#: ../memline.c:1128 #, c-format msgid "E310: Block 1 ID wrong (%s not a .swp file?)" msgstr "E310: ใใญใใฏ 1 ใฎIDใ้้ใฃใฆใใพใ(%s ใ.swpใใกใคใซใงใชใ?)" -#: ../memline.c:1133 msgid "???BLOCK MISSING" msgstr "???ใใญใใฏใใใใพใใ" -#: ../memline.c:1147 msgid "??? from here until ???END lines may be messed up" msgstr "??? ใใใใ ???END ใพใงใฎ่กใ็ ดๅฃใใใฆใใใใใงใ" -#: ../memline.c:1164 msgid "??? from here until ???END lines may have been inserted/deleted" msgstr "??? ใใใใ ???END ใพใงใฎ่กใๆฟๅ
ฅใๅ้คใใใใใใงใ" -#: ../memline.c:1181 msgid "???END" msgstr "???END" -#: ../memline.c:1238 msgid "E311: Recovery Interrupted" msgstr "E311: ใชใซใใชใๅฒ่พผใพใใพใใ" -#: ../memline.c:1243 msgid "" "E312: Errors detected while recovering; look for lines starting with ???" msgstr "" "E312: ใชใซใใชใฎๆไธญใซใจใฉใผใๆคๅบใใใพใใ; ???ใงๅงใพใ่กใๅ็
งใใฆใใ ใใ" -#: ../memline.c:1245 msgid "See \":help E312\" for more information." msgstr "่ฉณ็ดฐใฏ \":help E312\" ใๅ็
งใใฆใใ ใใ" -#: ../memline.c:1249 msgid "Recovery completed. You should check if everything is OK." msgstr "ใชใซใใชใ็ตไบใใพใใ. ๅ
จใฆใๆญฃใใใใใงใใฏใใฆใใ ใใ." -#: ../memline.c:1251 msgid "" "\n" "(You might want to write out this file under another name\n" @@ -3843,15 +3515,12 @@ msgstr "" "\n" "(ๅคๆดใใใงใใฏใใใใใซ, ใใฎใใกใคใซใๅฅใฎๅๅใงไฟๅญใใไธใง\n" -#: ../memline.c:1252 msgid "and run diff with the original file to check for changes)" msgstr "ๅๆฌใใกใคใซใจใฎ diff ใๅฎ่กใใใจ่ฏใใงใใใ)" -#: ../memline.c:1254 msgid "Recovery completed. Buffer contents equals file contents." msgstr "ๅพฉๅ
ๅฎไบ. ใใใใกใฎๅ
ๅฎนใฏใใกใคใซใจๅใใซใชใใพใใ." -#: ../memline.c:1255 msgid "" "\n" "You may want to delete the .swp file now.\n" @@ -3861,52 +3530,43 @@ msgstr "" "ๅ
ใฎ.swpใใกใคใซใฏๅ้คใใฆใๆงใใพใใ\n" "\n" +msgid "Using crypt key from swap file for the text file.\n" +msgstr "ในใฏใใใใกใคใซใใๅๅพใใๆๅทใญใผใใใญในใใใกใคใซใซไฝฟใใพใ.\n" + #. use msg() to start the scrolling properly -#: ../memline.c:1327 msgid "Swap files found:" msgstr "ในใฏใใใใกใคใซใ่คๆฐ่ฆใคใใใพใใ:" -#: ../memline.c:1446 msgid " In current directory:\n" msgstr " ็พๅจใฎใใฃใฌใฏใใช:\n" -#: ../memline.c:1448 msgid " Using specified name:\n" msgstr " ไปฅไธใฎๅๅใไฝฟ็จไธญ:\n" -#: ../memline.c:1450 msgid " In directory " msgstr " ใใฃใฌใฏใใช " -#: ../memline.c:1465 msgid " -- none --\n" msgstr " -- ใชใ --\n" -#: ../memline.c:1527 msgid " owned by: " msgstr " ๆๆ่
: " -#: ../memline.c:1529 msgid " dated: " msgstr " ๆฅไป: " -#: ../memline.c:1532 ../memline.c:3231 msgid " dated: " msgstr " ๆฅไป: " -#: ../memline.c:1548 msgid " [from Vim version 3.0]" msgstr " [from Vim version 3.0]" -#: ../memline.c:1550 msgid " [does not look like a Vim swap file]" msgstr " [Vimใฎในใฏใใใใกใคใซใงใฏใชใใใใงใ]" -#: ../memline.c:1552 msgid " file name: " msgstr " ใใกใคใซๅ: " -#: ../memline.c:1558 msgid "" "\n" " modified: " @@ -3914,15 +3574,12 @@ msgstr "" "\n" " ๅคๆด็ถๆ
: " -#: ../memline.c:1559 msgid "YES" msgstr "ใใ" -#: ../memline.c:1559 msgid "no" msgstr "ใชใ" -#: ../memline.c:1562 msgid "" "\n" " user name: " @@ -3930,11 +3587,9 @@ msgstr "" "\n" " ใฆใผใถใผๅ: " -#: ../memline.c:1568 msgid " host name: " msgstr " ใในใๅ: " -#: ../memline.c:1570 msgid "" "\n" " host name: " @@ -3942,7 +3597,6 @@ msgstr "" "\n" " ใในใๅ: " -#: ../memline.c:1575 msgid "" "\n" " process ID: " @@ -3950,11 +3604,16 @@ msgstr "" "\n" " ใใญใปในID: " -#: ../memline.c:1579 msgid " (still running)" msgstr " (ใพใ ๅฎ่กไธญ)" -#: ../memline.c:1586 +msgid "" +"\n" +" [not usable with this version of Vim]" +msgstr "" +"\n" +" [ใใฎVimใใผใธใงใณใงใฏไฝฟ็จใงใใพใใ]" + msgid "" "\n" " [not usable on this computer]" @@ -3962,97 +3621,75 @@ msgstr "" "\n" " [ใใฎใณใณใใฅใผใฟใงใฏไฝฟ็จใงใใพใใ]" -#: ../memline.c:1590 msgid " [cannot be read]" msgstr " [่ชญ่พผใใพใใ]" -#: ../memline.c:1593 msgid " [cannot be opened]" msgstr " [้ใใพใใ]" -#: ../memline.c:1698 msgid "E313: Cannot preserve, there is no swap file" msgstr "E313: ในใฏใใใใกใคใซใ็กใใฎใง็ถญๆใงใใพใใ" -#: ../memline.c:1747 msgid "File preserved" msgstr "ใใกใคใซใ็ถญๆใใใพใ" -#: ../memline.c:1749 msgid "E314: Preserve failed" msgstr "E314: ็ถญๆใซๅคฑๆใใพใใ" -#: ../memline.c:1819 #, c-format -msgid "E315: ml_get: invalid lnum: %<PRId64>" -msgstr "E315: ml_get: ็กๅนใชlnumใงใ: %<PRId64>" +msgid "E315: ml_get: invalid lnum: %ld" +msgstr "E315: ml_get: ็กๅนใชlnumใงใ: %ld" -#: ../memline.c:1851 #, c-format -msgid "E316: ml_get: cannot find line %<PRId64>" -msgstr "E316: ml_get: ่ก %<PRId64> ใ่ฆใคใใใใพใใ" +msgid "E316: ml_get: cannot find line %ld" +msgstr "E316: ml_get: ่ก %ld ใ่ฆใคใใใใพใใ" -#: ../memline.c:2236 msgid "E317: pointer block id wrong 3" msgstr "E317: ใใคใณใฟใใญใใฏใฎIDใ้้ใฃใฆใใพใ 3" -#: ../memline.c:2311 msgid "stack_idx should be 0" msgstr "stack_idx ใฏ 0 ใงใใในใใงใ" -#: ../memline.c:2369 msgid "E318: Updated too many blocks?" msgstr "E318: ๆดๆฐใใใใใญใใฏใๅค้ใใใใ?" -#: ../memline.c:2511 msgid "E317: pointer block id wrong 4" msgstr "E317: ใใคใณใฟใใญใใฏใฎIDใ้้ใฃใฆใใพใ 4" -#: ../memline.c:2536 msgid "deleted block 1?" msgstr "ใใญใใฏ 1 ใฏๆถใใใ?" -#: ../memline.c:2707 #, c-format -msgid "E320: Cannot find line %<PRId64>" -msgstr "E320: ่ก %<PRId64> ใ่ฆใคใใใพใใ" +msgid "E320: Cannot find line %ld" +msgstr "E320: ่ก %ld ใ่ฆใคใใใพใใ" -#: ../memline.c:2916 msgid "E317: pointer block id wrong" msgstr "E317: ใใคใณใฟใใญใใฏใฎIDใ้้ใฃใฆใใพใ" -#: ../memline.c:2930 msgid "pe_line_count is zero" msgstr "pe_line_count ใใผใญใงใ" -#: ../memline.c:2955 #, c-format -msgid "E322: line number out of range: %<PRId64> past the end" -msgstr "E322: ่ก็ชๅทใ็ฏๅฒๅคใงใ: %<PRId64> ่ถ
ใใฆใใพใ" +msgid "E322: line number out of range: %ld past the end" +msgstr "E322: ่ก็ชๅทใ็ฏๅฒๅคใงใ: %ld ่ถ
ใใฆใใพใ" -#: ../memline.c:2959 #, c-format -msgid "E323: line count wrong in block %<PRId64>" -msgstr "E323: ใใญใใฏ %<PRId64> ใฎ่กใซใฆใณใใ้้ใฃใฆใใพใ" +msgid "E323: line count wrong in block %ld" +msgstr "E323: ใใญใใฏ %ld ใฎ่กใซใฆใณใใ้้ใฃใฆใใพใ" -#: ../memline.c:2999 msgid "Stack size increases" msgstr "ในใฟใใฏใตใคใบใๅขใใพใ" -#: ../memline.c:3038 msgid "E317: pointer block id wrong 2" msgstr "E317: ใใคใณใฟใใญใใฏใฎIDใ้้ใฃใฆใใพใ 2" -#: ../memline.c:3070 #, c-format msgid "E773: Symlink loop for \"%s\"" msgstr "E773: \"%s\" ใฎใทใณใใชใใฏใชใณใฏใใซใผใใซใชใฃใฆใใพใ" -#: ../memline.c:3221 msgid "E325: ATTENTION" msgstr "E325: ๆณจๆ" -#: ../memline.c:3222 msgid "" "\n" "Found a swap file by the name \"" @@ -4060,39 +3697,32 @@ msgstr "" "\n" "ๆฌกใฎๅๅใงในใฏใใใใกใคใซใ่ฆใคใใพใใ \"" -#: ../memline.c:3226 msgid "While opening file \"" msgstr "ๆฌกใฎใใกใคใซใ้ใใฆใใๆไธญ \"" -#: ../memline.c:3239 msgid " NEWER than swap file!\n" msgstr " ในใฏใใใใกใคใซใใใๆฐใใใงใ!\n" -#: ../memline.c:3244 +#. Some of these messages are long to allow translation to +#. * other languages. msgid "" "\n" "(1) Another program may be editing the same file. If this is the case,\n" " be careful not to end up with two different instances of the same\n" -" file when making changes." +" file when making changes. Quit, or continue with caution.\n" msgstr "" "\n" "(1) ๅฅใฎใใญใฐใฉใ ใๅใใใกใคใซใ็ทจ้ใใฆใใใใใใใพใใ.\n" " ใใฎๅ ดๅใซใฏ, ๅคๆดใใใฆใใพใใจ1ใคใฎใใกใคใซใซๅฏพใใฆ็ฐใชใ2ใคใฎ\n" -" ใคใณในใฟใณในใใงใใฆใใพใใฎใง, ใใใใชใใใใซๆฐใใคใใฆใใ ใใ." - -#: ../memline.c:3245 -msgid " Quit, or continue with caution.\n" -msgstr " ็ตไบใใใ, ๆณจๆใใชใใ็ถใใฆใใ ใใ.\n" +" ใคใณในใฟใณในใใงใใฆใใพใใฎใง, ใใใใชใใใใซๆฐใใคใใฆใใ ใใ.\n" +" ็ตไบใใใ, ๆณจๆใใชใใ็ถใใฆใใ ใใ.\n" -#: ../memline.c:3246 msgid "(2) An edit session for this file crashed.\n" msgstr "(2) ใใฎใใกใคใซใฎ็ทจ้ใปใใทใงใณใใฏใฉใใทใฅใใ.\n" -#: ../memline.c:3247 msgid " If this is the case, use \":recover\" or \"vim -r " msgstr " ใใฎๅ ดๅใซใฏ \":recover\" ใ \"vim -r " -#: ../memline.c:3249 msgid "" "\"\n" " to recover the changes (see \":help recovery\").\n" @@ -4100,11 +3730,9 @@ msgstr "" "\"\n" " ใไฝฟ็จใใฆๅคๆดใใชใซใใผใใพใ(\":help recovery\" ใๅ็
ง).\n" -#: ../memline.c:3250 msgid " If you did this already, delete the swap file \"" msgstr " ๆขใซใใใ่กใชใฃใใฎใชใใฐ, ในใฏใใใใกใคใซ \"" -#: ../memline.c:3252 msgid "" "\"\n" " to avoid this message.\n" @@ -4112,23 +3740,18 @@ msgstr "" "\"\n" " ใๆถใใฐใใฎใกใใปใผใธใๅ้ฟใงใใพใ.\n" -#: ../memline.c:3450 ../memline.c:3452 msgid "Swap file \"" msgstr "ในใฏใใใใกใคใซ \"" -#: ../memline.c:3451 ../memline.c:3455 msgid "\" already exists!" msgstr "\" ใๆขใซใใใพใ!" -#: ../memline.c:3457 msgid "VIM - ATTENTION" msgstr "VIM - ๆณจๆ" -#: ../memline.c:3459 msgid "Swap file already exists!" msgstr "ในใฏใใใใกใคใซใๆขใซๅญๅจใใพใ!" -#: ../memline.c:3464 msgid "" "&Open Read-Only\n" "&Edit anyway\n" @@ -4142,7 +3765,6 @@ msgstr "" "็ตไบใใ(&Q)\n" "ไธญๆญขใใ(&A)" -#: ../memline.c:3467 msgid "" "&Open Read-Only\n" "&Edit anyway\n" @@ -4158,56 +3780,34 @@ msgstr "" "็ตไบใใ(&Q)\n" "ไธญๆญขใใ(&A)" -#. -#. * Change the ".swp" extension to find another file that can be used. -#. * First decrement the last char: ".swo", ".swn", etc. -#. * If that still isn't enough decrement the last but one char: ".svz" -#. * Can happen when editing many "No Name" buffers. -#. -#. ".s?a" -#. ".saa": tried enough, give up -#: ../memline.c:3528 msgid "E326: Too many swap files found" msgstr "E326: ในใฏใใใใกใคใซใๅคๆฐ่ฆใคใใใพใใ" -#: ../memory.c:227 -#, c-format -msgid "E342: Out of memory! (allocating %<PRIu64> bytes)" -msgstr "E342: ใกใขใชใ่ถณใใพใใ! (%<PRIu64> ใใคใใๅฒๅฝ่ฆๆฑ)" - -#: ../menu.c:62 msgid "E327: Part of menu-item path is not sub-menu" msgstr "E327: ใกใใฅใผใขใคใใ ใฎใในใฎ้จๅใใตใใกใใฅใผใงใฏใใใพใใ" -#: ../menu.c:63 msgid "E328: Menu only exists in another mode" msgstr "E328: ใกใใฅใผใฏไปใฎใขใผใใซใ ใใใใพใ" -#: ../menu.c:64 #, c-format msgid "E329: No menu \"%s\"" msgstr "E329: \"%s\" ใจใใใกใใฅใผใฏใใใพใใ" #. Only a mnemonic or accelerator is not valid. -#: ../menu.c:329 msgid "E792: Empty menu name" msgstr "E792: ใกใใฅใผๅใ็ฉบใงใ" -#: ../menu.c:340 msgid "E330: Menu path must not lead to a sub-menu" msgstr "E330: ใกใใฅใผใในใฏใตใใกใใฅใผใ็ใใในใใงใฏใใใพใใ" -#: ../menu.c:365 msgid "E331: Must not add menu items directly to menu bar" msgstr "E331: ใกใใฅใผใใผใซใฏ็ดๆฅใกใใฅใผใขใคใใ ใ่ฟฝๅ ใงใใพใใ" -#: ../menu.c:370 msgid "E332: Separator cannot be part of a menu path" msgstr "E332: ๅบๅใใฏใกใใฅใผใในใฎไธ้จใงใฏใใใพใใ" #. Now we have found the matching menu, and we list the mappings #. Highlight title -#: ../menu.c:762 msgid "" "\n" "--- Menus ---" @@ -4215,69 +3815,60 @@ msgstr "" "\n" "--- ใกใใฅใผ ---" -#: ../menu.c:1313 +msgid "Tear off this menu" +msgstr "ใใฎใกใใฅใผใๅใๅใ" + msgid "E333: Menu path must lead to a menu item" msgstr "E333: ใกใใฅใผใในใฏใกใใฅใผใขใคใใ ใ็ใใชใใใฐใใใพใใ" -#: ../menu.c:1330 #, c-format msgid "E334: Menu not found: %s" msgstr "E334: ใกใใฅใผใ่ฆใคใใใพใใ: %s" -#: ../menu.c:1396 #, c-format msgid "E335: Menu not defined for %s mode" msgstr "E335: %s ใซใฏใกใใฅใผใๅฎ็พฉใใใฆใใพใใ" -#: ../menu.c:1426 msgid "E336: Menu path must lead to a sub-menu" msgstr "E336: ใกใใฅใผใในใฏใตใใกใใฅใผใ็ใใชใใใฐใใใพใใ" -#: ../menu.c:1447 msgid "E337: Menu not found - check menu names" msgstr "E337: ใกใใฅใผใ่ฆใคใใใพใใ - ใกใใฅใผๅใ็ขบ่ชใใฆใใ ใใ" -#: ../message.c:423 #, c-format msgid "Error detected while processing %s:" msgstr "%s ใฎๅฆ็ไธญใซใจใฉใผใๆคๅบใใใพใใ:" -#: ../message.c:445 #, c-format msgid "line %4ld:" msgstr "่ก %4ld:" -#: ../message.c:617 #, c-format msgid "E354: Invalid register name: '%s'" msgstr "E354: ็กๅนใชใฌใธในใฟๅ: '%s'" -#: ../message.c:986 +msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>" +msgstr "ๆฅๆฌ่ชใกใใปใผใธ็ฟป่จณ/็ฃไฟฎ: ๆๅฒก ๅคช้ <koron.kaoriya@gmail.com>" + msgid "Interrupt: " msgstr "ๅฒ่พผใฟ: " -#: ../message.c:988 msgid "Press ENTER or type command to continue" msgstr "็ถใใใซใฏENTERใๆผใใใณใใณใใๅ
ฅๅใใฆใใ ใใ" -#: ../message.c:1843 #, c-format -msgid "%s line %<PRId64>" -msgstr "%s ่ก %<PRId64>" +msgid "%s line %ld" +msgstr "%s ่ก %ld" -#: ../message.c:2392 msgid "-- More --" msgstr "-- ็ถ็ถ --" -#: ../message.c:2398 msgid " SPACE/d/j: screen/page/line down, b/u/k: up, q: quit " msgstr " SPACE/d/j: ็ป้ข/ใใผใธ/่ก ไธ, b/u/k: ไธ, q: ็ตไบ " -#: ../message.c:3021 ../message.c:3031 msgid "Question" msgstr "่ณชๅ" -#: ../message.c:3023 msgid "" "&Yes\n" "&No" @@ -4285,17 +3876,6 @@ msgstr "" "ใฏใ(&Y)\n" "ใใใ(&N)" -#: ../message.c:3033 -msgid "" -"&Yes\n" -"&No\n" -"&Cancel" -msgstr "" -"ใฏใ(&Y)\n" -"ใใใ(&N)\n" -"ใญใฃใณใปใซ(&C)" - -#: ../message.c:3045 msgid "" "&Yes\n" "&No\n" @@ -4309,175 +3889,247 @@ msgstr "" "ๅ
จใฆๆพๆฃ(&D)\n" "ใญใฃใณใปใซ(&C)" -#: ../message.c:3058 +msgid "Select Directory dialog" +msgstr "ใใฃใฌใฏใใช้ธๆใใคใขใญใฐ" + +msgid "Save File dialog" +msgstr "ใใกใคใซไฟๅญใใคใขใญใฐ" + +msgid "Open File dialog" +msgstr "ใใกใคใซ่ชญ่พผใใคใขใญใฐ" + +#. TODO: non-GUI file selector here +msgid "E338: Sorry, no file browser in console mode" +msgstr "E338: ใณใณใฝใผใซใขใผใใงใฏใใกใคใซใใฉใฆใถใไฝฟใใพใใ, ใใใใชใใ" + msgid "E766: Insufficient arguments for printf()" msgstr "E766: printf() ใฎๅผๆฐใไธๅๅใงใ" -#: ../message.c:3119 msgid "E807: Expected Float argument for printf()" msgstr "E807: printf() ใฎๅผๆฐใซใฏๆตฎๅๅฐๆฐ็นๆฐใๆๅพ
ใใใฆใใพใ" -#: ../message.c:3873 msgid "E767: Too many arguments to printf()" msgstr "E767: printf() ใฎๅผๆฐใๅค้ใใพใ" -#: ../misc1.c:2256 msgid "W10: Warning: Changing a readonly file" msgstr "W10: ่ญฆๅ: ่ชญ่พผๅฐ็จใใกใคใซใๅคๆดใใพใ" -#: ../misc1.c:2537 msgid "Type number and <Enter> or click with mouse (empty cancels): " msgstr "" "็ชๅทใจ<Enter>ใๅ
ฅๅใใใใใฆในใงใฏใชใใฏใใฆใใ ใใ (็ฉบใงใญใฃใณใปใซ): " -#: ../misc1.c:2539 msgid "Type number and <Enter> (empty cancels): " msgstr "็ชๅทใจ<Enter>ใๅ
ฅๅใใฆใใ ใใ (็ฉบใงใญใฃใณใปใซ): " -#: ../misc1.c:2585 msgid "1 more line" msgstr "1 ่ก ่ฟฝๅ ใใพใใ" -#: ../misc1.c:2588 msgid "1 line less" msgstr "1 ่ก ๅ้คใใพใใ" -#: ../misc1.c:2593 #, c-format -msgid "%<PRId64> more lines" -msgstr "%<PRId64> ่ก ่ฟฝๅ ใใพใใ" +msgid "%ld more lines" +msgstr "%ld ่ก ่ฟฝๅ ใใพใใ" -#: ../misc1.c:2596 #, c-format -msgid "%<PRId64> fewer lines" -msgstr "%<PRId64> ่ก ๅ้คใใพใใ" +msgid "%ld fewer lines" +msgstr "%ld ่ก ๅ้คใใพใใ" -#: ../misc1.c:2599 msgid " (Interrupted)" msgstr " (ๅฒ่พผใพใใพใใ)" -#: ../misc1.c:2635 msgid "Beep!" msgstr "ใใผใ!" -#: ../misc2.c:738 +msgid "ERROR: " +msgstr "ใจใฉใผ: " + +#, c-format +msgid "" +"\n" +"[bytes] total alloc-freed %lu-%lu, in use %lu, peak use %lu\n" +msgstr "" +"\n" +"[ใกใขใช(ใใคใ)] ็ทๅฒๅฝ-่งฃๆพ้ %lu-%lu, ไฝฟ็จ้ %lu, ใใผใฏๆ %lu\n" + +#, c-format +msgid "" +"[calls] total re/malloc()'s %lu, total free()'s %lu\n" +"\n" +msgstr "" +"[ๅผๅบ] ็ท re/malloc() ๅๆฐ %lu, ็ท free() ๅๆฐ %lu\n" +"\n" + +msgid "E340: Line is becoming too long" +msgstr "E340: ่กใ้ทใใชใ้ใใพใใ" + +#, c-format +msgid "E341: Internal error: lalloc(%ld, )" +msgstr "E341: ๅ
้จใจใฉใผ: lalloc(%ld,)" + +#, c-format +msgid "E342: Out of memory! (allocating %lu bytes)" +msgstr "E342: ใกใขใชใ่ถณใใพใใ! (%lu ใใคใใๅฒๅฝ่ฆๆฑ)" + #, c-format msgid "Calling shell to execute: \"%s\"" msgstr "ๅฎ่กใฎใใใซใทใงใซใๅผๅบใไธญ: \"%s\"" -#: ../normal.c:183 +msgid "E545: Missing colon" +msgstr "E545: ใณใญใณใใใใพใใ" + +msgid "E546: Illegal mode" +msgstr "E546: ไธๆญฃใชใขใผใใงใ" + +msgid "E547: Illegal mouseshape" +msgstr "E547: ไธๆญฃใช 'mouseshape' ใงใ" + +msgid "E548: digit expected" +msgstr "E548: ๆฐๅคใๅฟ
่ฆใงใ" + +msgid "E549: Illegal percentage" +msgstr "E549: ไธๆญฃใชใใผใปใณใใผใธใงใ" + +msgid "E854: path too long for completion" +msgstr "E854: ใในใ้ท้ใใฆ่ฃๅฎใงใใพใใ" + +#, c-format +msgid "" +"E343: Invalid path: '**[number]' must be at the end of the path or be " +"followed by '%s'." +msgstr "" +"E343: ็กๅนใชใในใงใ: '**[ๆฐๅค]' ใฏpathใฎๆๅพใ '%s' ใ็ถใใฆใชใใจใใใพใ" +"ใ." + +#, c-format +msgid "E344: Can't find directory \"%s\" in cdpath" +msgstr "E344: cdpathใซใฏ \"%s\" ใจใใใใกใคใซใใใใพใใ" + +#, c-format +msgid "E345: Can't find file \"%s\" in path" +msgstr "E345: pathใซใฏ \"%s\" ใจใใใใกใคใซใใใใพใใ" + +#, c-format +msgid "E346: No more directory \"%s\" found in cdpath" +msgstr "E346: cdpathใซใฏใใไปฅไธ \"%s\" ใจใใใใกใคใซใใใใพใใ" + +#, c-format +msgid "E347: No more file \"%s\" found in path" +msgstr "E347: ใในใซใฏใใไปฅไธ \"%s\" ใจใใใใกใคใซใใใใพใใ" + +#, c-format +msgid "E668: Wrong access mode for NetBeans connection info file: \"%s\"" +msgstr "" +"E668: NetBeansใฎๆฅ็ถๆ
ๅ ฑใใกใคใซใฎใขใฏใปในใขใผใใซๅ้กใใใใพใ: \"%s\"" + +#, c-format +msgid "E658: NetBeans connection lost for buffer %ld" +msgstr "E658: ใใใใก %ld ใฎ NetBeans ๆฅ็ถใๅคฑใใใพใใ" + +msgid "E838: netbeans is not supported with this GUI" +msgstr "E838: NetBeansใฏใใฎGUIใซใฏๅฏพๅฟใใฆใใพใใ" + +msgid "E511: netbeans already connected" +msgstr "E511: NetBeansใฏๆขใซๆฅ็ถใใฆใใพใ" + +#, c-format +msgid "E505: %s is read-only (add ! to override)" +msgstr "E505: %s ใฏ่ชญ่พผๅฐ็จใงใ (ๅผทๅถๆธ่พผใซใฏ ! ใ่ฟฝๅ )" + msgid "E349: No identifier under cursor" msgstr "E349: ใซใผใฝใซใฎไฝ็ฝฎใซใฏ่ญๅฅๅญใใใใพใใ" -#: ../normal.c:1866 msgid "E774: 'operatorfunc' is empty" msgstr "E774: 'operatorfunc' ใชใใทใงใณใ็ฉบใงใ" -#: ../normal.c:2637 +msgid "E775: Eval feature not available" +msgstr "E775: ๅผ่ฉไพกๆฉ่ฝใ็กๅนใซใชใฃใฆใใพใ" + msgid "Warning: terminal cannot highlight" msgstr "่ญฆๅ: ไฝฟ็จใใฆใใ็ซฏๆซใฏใใคใฉใคใใงใใพใใ" -#: ../normal.c:2807 msgid "E348: No string under cursor" msgstr "E348: ใซใผใฝใซใฎไฝ็ฝฎใซใฏๆๅญๅใใใใพใใ" -#: ../normal.c:3937 msgid "E352: Cannot erase folds with current 'foldmethod'" msgstr "E352: ็พๅจใฎ 'foldmethod' ใงใฏๆ็ณใฟใๆถๅปใงใใพใใ" -#: ../normal.c:5897 msgid "E664: changelist is empty" msgstr "E664: ๅคๆดใชในใใ็ฉบใงใ" -#: ../normal.c:5899 msgid "E662: At start of changelist" msgstr "E662: ๅคๆดใชในใใฎๅ
้ ญ" -#: ../normal.c:5901 msgid "E663: At end of changelist" msgstr "E663: ๅคๆดใชในใใฎๆซๅฐพ" -#: ../normal.c:7053 -msgid "Type :quit<Enter> to exit Nvim" +msgid "Type :quit<Enter> to exit Vim" msgstr "Vimใ็ตไบใใใซใฏ :quit<Enter> ใจๅ
ฅๅใใฆใใ ใใ" -#: ../ops.c:248 #, c-format msgid "1 line %sed 1 time" msgstr "1 ่กใ %s ใง 1 ๅๅฆ็ใใใพใใ" -#: ../ops.c:250 #, c-format msgid "1 line %sed %d times" msgstr "1 ่กใ %s ใง %d ๅๅฆ็ใใใพใใ" -#: ../ops.c:253 #, c-format -msgid "%<PRId64> lines %sed 1 time" -msgstr "%<PRId64> ่กใ %s ใง 1 ๅๅฆ็ใใใพใใ" +msgid "%ld lines %sed 1 time" +msgstr "%ld ่กใ %s ใง 1 ๅๅฆ็ใใใพใใ" -#: ../ops.c:256 #, c-format -msgid "%<PRId64> lines %sed %d times" -msgstr "%<PRId64> ่กใ %s ใง %d ๅๅฆ็ใใใพใใ" +msgid "%ld lines %sed %d times" +msgstr "%ld ่กใ %s ใง %d ๅๅฆ็ใใใพใใ" -#: ../ops.c:592 #, c-format -msgid "%<PRId64> lines to indent... " -msgstr "%<PRId64> ่กใใคใณใใณใใใใพใ... " +msgid "%ld lines to indent... " +msgstr "%ld ่กใใคใณใใณใใใใพใ... " -#: ../ops.c:634 msgid "1 line indented " msgstr "1 ่กใใคใณใใณใใใพใใ " -#: ../ops.c:636 #, c-format -msgid "%<PRId64> lines indented " -msgstr "%<PRId64> ่กใใคใณใใณใใใพใใ " +msgid "%ld lines indented " +msgstr "%ld ่กใใคใณใใณใใใพใใ " -#: ../ops.c:938 msgid "E748: No previously used register" msgstr "E748: ใพใ ใฌใธในใฟใไฝฟ็จใใฆใใพใใ" #. must display the prompt -#: ../ops.c:1433 msgid "cannot yank; delete anyway" msgstr "ใคใณใฏใงใใพใใ; ใจใซใใๆถๅป" -#: ../ops.c:1929 msgid "1 line changed" msgstr "1 ่กใๅคๆดใใใพใใ" -#: ../ops.c:1931 #, c-format -msgid "%<PRId64> lines changed" -msgstr "%<PRId64> ่กใๅคๆดใใใพใใ" +msgid "%ld lines changed" +msgstr "%ld ่กใๅคๆดใใใพใใ" + +#, c-format +msgid "freeing %ld lines" +msgstr "%ld ่กใ่งฃๆพไธญ" -#: ../ops.c:2521 msgid "block of 1 line yanked" msgstr "1 ่กใฎใใญใใฏใใคใณใฏใใใพใใ" -#: ../ops.c:2523 msgid "1 line yanked" msgstr "1 ่กใใคใณใฏใใใพใใ" -#: ../ops.c:2525 #, c-format -msgid "block of %<PRId64> lines yanked" -msgstr "%<PRId64> ่กใฎใใญใใฏใใคใณใฏใใใพใใ" +msgid "block of %ld lines yanked" +msgstr "%ld ่กใฎใใญใใฏใใคใณใฏใใใพใใ" -#: ../ops.c:2528 #, c-format -msgid "%<PRId64> lines yanked" -msgstr "%<PRId64> ่กใใคใณใฏใใใพใใ" +msgid "%ld lines yanked" +msgstr "%ld ่กใใคใณใฏใใใพใใ" -#: ../ops.c:2710 #, c-format msgid "E353: Nothing in register %s" msgstr "E353: ใฌใธในใฟ %s ใซใฏไฝใใใใพใใ" #. Highlight title -#: ../ops.c:3185 msgid "" "\n" "--- Registers ---" @@ -4485,11 +4137,9 @@ msgstr "" "\n" "--- ใฌใธในใฟ ---" -#: ../ops.c:4455 msgid "Illegal register name" msgstr "ไธๆญฃใชใฌใธในใฟๅ" -#: ../ops.c:4533 msgid "" "\n" "# Registers:\n" @@ -4497,7 +4147,6 @@ msgstr "" "\n" "# ใฌใธในใฟ:\n" -#: ../ops.c:4575 #, c-format msgid "E574: Unknown register type %d" msgstr "E574: ๆช็ฅใฎใฌใธในใฟๅ %d ใงใ" @@ -4507,86 +4156,61 @@ msgid "" "lines" msgstr "E883: ๆค็ดขใใฟใผใณใจๅผใฌใธในใฟใซใฏ2่กไปฅไธใๅซใใใใพใใ" -#: ../ops.c:5089 #, c-format -msgid "%<PRId64> Cols; " -msgstr "%<PRId64> ๅ; " +msgid "%ld Cols; " +msgstr "%ld ๅ; " -#: ../ops.c:5097 #, c-format -msgid "" -"Selected %s%<PRId64> of %<PRId64> Lines; %<PRId64> of %<PRId64> Words; " -"%<PRId64> of %<PRId64> Bytes" -msgstr "" -"้ธๆ %s%<PRId64> / %<PRId64> ่ก; %<PRId64> / %<PRId64> ๅ่ช; %<PRId64> / " -"%<PRId64> ใใคใ" +msgid "Selected %s%ld of %ld Lines; %lld of %lld Words; %lld of %lld Bytes" +msgstr "้ธๆ %s%ld / %ld ่ก; %lld / %lld ๅ่ช; %lld / %lld ใใคใ" -#: ../ops.c:5105 #, c-format msgid "" -"Selected %s%<PRId64> of %<PRId64> Lines; %<PRId64> of %<PRId64> Words; " -"%<PRId64> of %<PRId64> Chars; %<PRId64> of %<PRId64> Bytes" +"Selected %s%ld of %ld Lines; %lld of %lld Words; %lld of %lld Chars; %lld of " +"%lld Bytes" msgstr "" -"้ธๆ %s%<PRId64> / %<PRId64> ่ก; %<PRId64> / %<PRId64> ๅ่ช; %<PRId64> / " -"%<PRId64> ๆๅญ; %<PRId64> / %<PRId64> ใใคใ" +"้ธๆ %s%ld / %ld ่ก; %lld / %lld ๅ่ช; %lld / %lld ๆๅญ; %lld / %lld ใใคใ" -#: ../ops.c:5123 #, c-format -msgid "" -"Col %s of %s; Line %<PRId64> of %<PRId64>; Word %<PRId64> of %<PRId64>; Byte " -"%<PRId64> of %<PRId64>" -msgstr "" -"ๅ %s / %s; ่ก %<PRId64> of %<PRId64>; ๅ่ช %<PRId64> / %<PRId64>; ใใคใ " -"%<PRId64> / %<PRId64>" +msgid "Col %s of %s; Line %ld of %ld; Word %lld of %lld; Byte %lld of %lld" +msgstr "ๅ %s / %s; ่ก %ld of %ld; ๅ่ช %lld / %lld; ใใคใ %lld / %lld" -#: ../ops.c:5133 #, c-format msgid "" -"Col %s of %s; Line %<PRId64> of %<PRId64>; Word %<PRId64> of %<PRId64>; Char " -"%<PRId64> of %<PRId64>; Byte %<PRId64> of %<PRId64>" +"Col %s of %s; Line %ld of %ld; Word %lld of %lld; Char %lld of %lld; Byte " +"%lld of %lld" msgstr "" -"ๅ %s / %s; ่ก %<PRId64> / %<PRId64>; ๅ่ช %<PRId64> / %<PRId64>; ๆๅญ " -"%<PRId64> / %<PRId64>; ใใคใ %<PRId64> of %<PRId64>" +"ๅ %s / %s; ่ก %ld / %ld; ๅ่ช %lld / %lld; ๆๅญ %lld / %lld; ใใคใ %lld of " +"%lld" -#: ../ops.c:5146 #, c-format -msgid "(+%<PRId64> for BOM)" -msgstr "(+%<PRId64> for BOM)" +msgid "(+%ld for BOM)" +msgstr "(+%ld for BOM)" -#: ../option.c:1238 msgid "%<%f%h%m%=Page %N" msgstr "%<%f%h%m%=%N ใใผใธ" -#: ../option.c:1574 msgid "Thanks for flying Vim" msgstr "Vim ใไฝฟใฃใฆใใใฆใใใใจใ" -#. found a mismatch: skip -#: ../option.c:2698 msgid "E518: Unknown option" msgstr "E518: ๆช็ฅใฎใชใใทใงใณใงใ" -#: ../option.c:2709 msgid "E519: Option not supported" msgstr "E519: ใชใใทใงใณใฏใตใใผใใใใฆใใพใใ" -#: ../option.c:2740 msgid "E520: Not allowed in a modeline" msgstr "E520: modeline ใงใฏ่จฑๅฏใใใพใใ" -#: ../option.c:2815 msgid "E846: Key code not set" msgstr "E846: ใญใผใณใผใใ่จญๅฎใใใฆใใพใใ" -#: ../option.c:2924 msgid "E521: Number required after =" msgstr "E521: = ใฎๅพใซใฏๆฐๅญใๅฟ
่ฆใงใ" -#: ../option.c:3226 ../option.c:3864 msgid "E522: Not found in termcap" msgstr "E522: termcap ๅ
ใซ่ฆใคใใใพใใ" -#: ../option.c:3335 #, c-format msgid "E539: Illegal character <%s>" msgstr "E539: ไธๆญฃใชๆๅญใงใ <%s>" @@ -4595,93 +4219,99 @@ msgstr "E539: ไธๆญฃใชๆๅญใงใ <%s>" msgid "For option %s" msgstr "ใชใใทใงใณ: %s" -#: ../option.c:3862 msgid "E529: Cannot set 'term' to empty string" msgstr "E529: 'term' ใซใฏ็ฉบๆๅญๅใ่จญๅฎใงใใพใใ" -#: ../option.c:3885 +msgid "E530: Cannot change term in GUI" +msgstr "E530: GUIใงใฏ 'term' ใๅคๆดใงใใพใใ" + +msgid "E531: Use \":gui\" to start the GUI" +msgstr "E531: GUIใในใฟใผใใใใซใฏ \":gui\" ใไฝฟ็จใใฆใใ ใใ" + msgid "E589: 'backupext' and 'patchmode' are equal" msgstr "E589: 'backupext' ใจ 'patchmode' ใๅใใงใ" -#: ../option.c:3964 msgid "E834: Conflicts with value of 'listchars'" msgstr "E834: 'listchars'ใฎๅคใซ็็พใใใใพใ" -#: ../option.c:3966 msgid "E835: Conflicts with value of 'fillchars'" msgstr "E835: 'fillchars'ใฎๅคใซ็็พใใใใพใ" -#: ../option.c:4163 +msgid "E617: Cannot be changed in the GTK+ 2 GUI" +msgstr "E617: GTK+2 GUIใงใฏๅคๆดใงใใพใใ" + msgid "E524: Missing colon" msgstr "E524: ใณใญใณใใใใพใใ" -#: ../option.c:4165 msgid "E525: Zero length string" msgstr "E525: ๆๅญๅใฎ้ทใใใผใญใงใ" -#: ../option.c:4220 #, c-format msgid "E526: Missing number after <%s>" msgstr "E526: <%s> ใฎๅพใซๆฐๅญใใใใพใใ" -#: ../option.c:4232 msgid "E527: Missing comma" msgstr "E527: ใซใณใใใใใพใใ" -#: ../option.c:4239 msgid "E528: Must specify a ' value" msgstr "E528: ' ใฎๅคใๆๅฎใใชใใใฐใชใใพใใ" -#: ../option.c:4271 msgid "E595: contains unprintable or wide character" msgstr "E595: ่กจ็คบใงใใชใๆๅญใใฏใคใๆๅญใๅซใใงใใพใ" -#: ../option.c:4469 +msgid "E596: Invalid font(s)" +msgstr "E596: ็กๅนใชใใฉใณใใงใ" + +msgid "E597: can't select fontset" +msgstr "E597: ใใฉใณใใปใใใ้ธๆใงใใพใใ" + +msgid "E598: Invalid fontset" +msgstr "E598: ็กๅนใชใใฉใณใใปใใใงใ" + +msgid "E533: can't select wide font" +msgstr "E533: ใฏใคใใใฉใณใใ้ธๆใงใใพใใ" + +msgid "E534: Invalid wide font" +msgstr "E534: ็กๅนใชใฏใคใใใฉใณใใงใ" + #, c-format msgid "E535: Illegal character after <%c>" msgstr "E535: <%c> ใฎๅพใซไธๆญฃใชๆๅญใใใใพใ" -#: ../option.c:4534 msgid "E536: comma required" msgstr "E536: ใซใณใใๅฟ
่ฆใงใ" -#: ../option.c:4543 #, c-format msgid "E537: 'commentstring' must be empty or contain %s" msgstr "E537: 'commentstring' ใฏ็ฉบใงใใใ %s ใๅซใๅฟ
่ฆใใใใพใ" -#: ../option.c:4928 +msgid "E538: No mouse support" +msgstr "E538: ใใฆในใฏใตใใผใใใใพใใ" + msgid "E540: Unclosed expression sequence" msgstr "E540: ๅผใ็ตไบใใฆใใพใใ" -#: ../option.c:4932 msgid "E541: too many items" msgstr "E541: ่ฆ็ด ใๅค้ใใพใ" -#: ../option.c:4934 msgid "E542: unbalanced groups" msgstr "E542: ใฐใซใผใใ้ฃๅใใพใใ" -#: ../option.c:5148 msgid "E590: A preview window already exists" msgstr "E590: ใใฌใใฅใผใฆใฃใณใใฆใๆขใซๅญๅจใใพใ" -#: ../option.c:5311 msgid "W17: Arabic requires UTF-8, do ':set encoding=utf-8'" msgstr "" "W17: ใขใฉใใขๆๅญใซใฏUTF-8ใๅฟ
่ฆใชใฎใง, ':set encoding=utf-8' ใใฆใใ ใใ" -#: ../option.c:5623 #, c-format msgid "E593: Need at least %d lines" msgstr "E593: ๆไฝ %d ใฎ่กๆฐใๅฟ
่ฆใงใ" -#: ../option.c:5631 #, c-format msgid "E594: Need at least %d columns" msgstr "E594: ๆไฝ %d ใฎใซใฉใ ๅน
ใๅฟ
่ฆใงใ" -#: ../option.c:6011 #, c-format msgid "E355: Unknown option: %s" msgstr "E355: ๆช็ฅใฎใชใใทใงใณใงใ: %s" @@ -4689,12 +4319,10 @@ msgstr "E355: ๆช็ฅใฎใชใใทใงใณใงใ: %s" #. There's another character after zeros or the string #. * is empty. In both cases, we are trying to set a #. * num option using a string. -#: ../option.c:6037 #, c-format msgid "E521: Number required: &%s = '%s'" msgstr "E521: ๆฐๅญใๅฟ
่ฆใงใ: &%s = '%s'" -#: ../option.c:6149 msgid "" "\n" "--- Terminal codes ---" @@ -4702,7 +4330,6 @@ msgstr "" "\n" "--- ็ซฏๆซใณใผใ ---" -#: ../option.c:6151 msgid "" "\n" "--- Global option values ---" @@ -4710,7 +4337,6 @@ msgstr "" "\n" "--- ใฐใญใผใใซใชใใทใงใณๅค ---" -#: ../option.c:6153 msgid "" "\n" "--- Local option values ---" @@ -4718,7 +4344,6 @@ msgstr "" "\n" "--- ใญใผใซใซใชใใทใงใณๅค ---" -#: ../option.c:6155 msgid "" "\n" "--- Options ---" @@ -4726,37 +4351,119 @@ msgstr "" "\n" "--- ใชใใทใงใณ ---" -#: ../option.c:6816 msgid "E356: get_varp ERROR" msgstr "E356: get_varp ใจใฉใผ" -#: ../option.c:7696 #, c-format msgid "E357: 'langmap': Matching character missing for %s" msgstr "E357: 'langmap': %s ใซๅฏพๅฟใใๆๅญใใใใพใใ" -#: ../option.c:7715 #, c-format msgid "E358: 'langmap': Extra characters after semicolon: %s" msgstr "E358: 'langmap': ใปใใณใญใณใฎๅพใซไฝๅใชๆๅญใใใใพใ: %s" -#: ../os/shell.c:194 -msgid "" -"\n" -"Cannot execute shell " -msgstr "" -"\n" -"ใทใงใซใๅฎ่กใงใใพใใ " +msgid "cannot open " +msgstr "้ใใพใใ " + +msgid "VIM: Can't open window!\n" +msgstr "VIM: ใฆใฃใณใใฆใ้ใใพใใ!\n" + +msgid "Need Amigados version 2.04 or later\n" +msgstr "Amigadosใฎใใผใธใงใณ 2.04ใใใไปฅ้ใๅฟ
่ฆใงใ\n" + +#, c-format +msgid "Need %s version %ld\n" +msgstr "%s ใฎใใผใธใงใณ %ld ใๅฟ
่ฆใงใ\n" + +msgid "Cannot open NIL:\n" +msgstr "NILใ้ใใพใใ:\n" + +msgid "Cannot create " +msgstr "ไฝๆใงใใพใใ " + +#, c-format +msgid "Vim exiting with %d\n" +msgstr "Vimใฏ %d ใง็ตไบใใพใ\n" + +msgid "cannot change console mode ?!\n" +msgstr "ใณใณใฝใผใซใขใผใใๅคๆดใงใใพใใ?!\n" + +msgid "mch_get_shellsize: not a console??\n" +msgstr "mch_get_shellsize: ใณใณใฝใผใซใงใฏใชใ??\n" + +#. if Vim opened a window: Executing a shell may cause crashes +msgid "E360: Cannot execute shell with -f option" +msgstr "E360: -f ใชใใทใงใณใงใทใงใซใๅฎ่กใงใใพใใ" + +msgid "Cannot execute " +msgstr "ๅฎ่กใงใใพใใ " + +msgid "shell " +msgstr "ใทใงใซ " + +msgid " returned\n" +msgstr " ๆปใใพใใ\n" + +msgid "ANCHOR_BUF_SIZE too small." +msgstr "ANCHOR_BUF_SIZE ใๅฐใ้ใใพใ." + +msgid "I/O ERROR" +msgstr "ๅ
ฅๅบๅใจใฉใผ" + +msgid "Message" +msgstr "ใกใใปใผใธ" + +msgid "'columns' is not 80, cannot execute external commands" +msgstr "'columns' ใ 80 ใงใฏใชใใใใๅค้จใณใใณใใๅฎ่กใงใใพใใ" + +msgid "E237: Printer selection failed" +msgstr "E237: ใใชใณใฟใฎ้ธๆใซๅคฑๆใใพใใ" + +#, c-format +msgid "to %s on %s" +msgstr "%s ใธ (%s ไธใฎ)" + +#, c-format +msgid "E613: Unknown printer font: %s" +msgstr "E613: ๆช็ฅใฎใใชใณใฟใชใใทใงใณใงใ: %s" + +#, c-format +msgid "E238: Print error: %s" +msgstr "E238: ๅฐๅทใจใฉใผ: %s" + +#, c-format +msgid "Printing '%s'" +msgstr "ๅฐๅทใใฆใใพใ: '%s'" + +#, c-format +msgid "E244: Illegal charset name \"%s\" in font name \"%s\"" +msgstr "E244: ๆๅญใปใใๅ \"%s\" ใฏไธๆญฃใงใ (ใใฉใณใๅ \"%s\")" + +#, c-format +msgid "E244: Illegal quality name \"%s\" in font name \"%s\"" +msgstr "E244: ๅ่ณชๅ \"%s\" ใฏไธๆญฃใงใ (ใใฉใณใๅ \"%s\")" + +#, c-format +msgid "E245: Illegal char '%c' in font name \"%s\"" +msgstr "E245: '%c' ใฏไธๆญฃใชๆๅญใงใ (ใใฉใณใๅ \"%s\")" + +#, c-format +msgid "Opening the X display took %ld msec" +msgstr "Xใตใผใใผใธใฎๆฅ็ถใซ %ld ใใช็งใใใใพใใ" -#: ../os/shell.c:439 msgid "" "\n" -"shell returned " +"Vim: Got X error\n" msgstr "" "\n" -"ใทใงใซใๅคใ่ฟใใพใใ " +"Vim: X ใฎใจใฉใผใๆคๅบใใพใใr\n" + +msgid "Testing the X display failed" +msgstr "X display ใฎใใงใใฏใซๅคฑๆใใพใใ" + +msgid "Opening the X display timed out" +msgstr "X display ใฎ open ใใฟใคใ ใขใฆใใใพใใ" -#: ../os_unix.c:465 ../os_unix.c:471 msgid "" "\n" "Could not get security context for " @@ -4764,7 +4471,6 @@ msgstr "" "\n" "ใปใญใฅใชใใฃใณใณใใญในใใๅๅพใงใใพใใ " -#: ../os_unix.c:479 msgid "" "\n" "Could not set security context for " @@ -4780,223 +4486,293 @@ msgstr "ใปใญใฅใชใใฃใณใณใใญในใ %s ใ %s ใซ่จญๅฎใงใใพใใ" msgid "Could not get security context %s for %s. Removing it!" msgstr "ใปใญใฅใชใใฃใณใณใใญในใ %s ใ %s ใใๅๅพใงใใพใใ. ๅ้คใใพใ!" -#: ../os_unix.c:1558 ../os_unix.c:1647 +msgid "" +"\n" +"Cannot execute shell sh\n" +msgstr "" +"\n" +"sh ใทใงใซใๅฎ่กใงใใพใใ\n" + +msgid "" +"\n" +"shell returned " +msgstr "" +"\n" +"ใทใงใซใๅคใ่ฟใใพใใ " + +msgid "" +"\n" +"Cannot create pipes\n" +msgstr "" +"\n" +"ใใคใใไฝๆใงใใพใใ\n" + +msgid "" +"\n" +"Cannot fork\n" +msgstr "" +"\n" +"fork ใงใใพใใ\n" + +msgid "" +"\n" +"Cannot execute shell " +msgstr "" +"\n" +"ใทใงใซใๅฎ่กใงใใพใใ " + +msgid "" +"\n" +"Command terminated\n" +msgstr "" +"\n" +"ใณใใณใใไธญๆญใใพใใ\n" + +msgid "XSMP lost ICE connection" +msgstr "XSMP ใICEๆฅ็ถใๅคฑใใพใใ" + #, c-format msgid "dlerror = \"%s\"" msgstr "dlerror = \"%s\"" -#: ../path.c:1449 +msgid "Opening the X display failed" +msgstr "X display ใฎ open ใซๅคฑๆใใพใใ" + +msgid "XSMP handling save-yourself request" +msgstr "XSMP ใsave-yourself่ฆๆฑใๅฆ็ใใฆใใพใ" + +msgid "XSMP opening connection" +msgstr "XSMP ใๆฅ็ถใ้ๅงใใฆใใพใ" + +msgid "XSMP ICE connection watch failed" +msgstr "XSMP ICEๆฅ็ถใๅคฑๆใใใใใงใ" + #, c-format -msgid "E447: Can't find file \"%s\" in path" -msgstr "E447: pathใซใฏ \"%s\" ใจใใใใกใคใซใใใใพใใ" +msgid "XSMP SmcOpenConnection failed: %s" +msgstr "XSMP SmcOpenConnectionใๅคฑๆใใพใใ: %s" + +msgid "At line" +msgstr "่ก" + +msgid "Could not load vim32.dll!" +msgstr "vim32.dll ใใญใผใใงใใพใใใงใใ" + +msgid "VIM Error" +msgstr "VIMใจใฉใผ" + +msgid "Could not fix up function pointers to the DLL!" +msgstr "DLLใใ้ขๆฐใใคใณใฟใๅๅพใงใใพใใใงใใ" + +#, c-format +msgid "Vim: Caught %s event\n" +msgstr "Vim: ใคใใณใ %s ใๆค็ฅ\n" + +msgid "close" +msgstr "้ใใ" + +msgid "logoff" +msgstr "ใญใฐใชใ" + +msgid "shutdown" +msgstr "ใทใฃใใใใฆใณ" + +msgid "E371: Command not found" +msgstr "E371: ใณใใณใใใใใพใใ" + +msgid "" +"VIMRUN.EXE not found in your $PATH.\n" +"External commands will not pause after completion.\n" +"See :help win32-vimrun for more information." +msgstr "" +"VIMRUN.EXEใ $PATH ใฎไธญใซ่ฆใคใใใพใใ.\n" +"ๅค้จใณใใณใใฎ็ตไบๅพใซไธๆๅๆญขใใใพใใ.\n" +"่ฉณ็ดฐใฏ :help win32-vimrun ใๅ็
งใใฆใใ ใใ." + +msgid "Vim Warning" +msgstr "Vimใฎ่ญฆๅ" + +#, c-format +msgid "shell returned %d" +msgstr "ใทใงใซใใณใผใ %d ใง็ตไบใใพใใ" -#: ../quickfix.c:359 #, c-format msgid "E372: Too many %%%c in format string" msgstr "E372: ใใฉใผใใใๆๅญๅใซ %%%c ใๅค้ใใพใ" -#: ../quickfix.c:371 #, c-format msgid "E373: Unexpected %%%c in format string" msgstr "E373: ใใฉใผใใใๆๅญๅใซไบๆใใฌ %%%c ใใใใพใใ" -#: ../quickfix.c:420 msgid "E374: Missing ] in format string" msgstr "E374: ใใฉใผใใใๆๅญๅใซ ] ใใใใพใใ" -#: ../quickfix.c:431 #, c-format msgid "E375: Unsupported %%%c in format string" msgstr "E375: ใใฉใผใใใๆๅญๅใงใฏ %%%c ใฏใตใใผใใใใพใใ" -#: ../quickfix.c:448 #, c-format msgid "E376: Invalid %%%c in format string prefix" msgstr "E376: ใใฉใผใใใๆๅญๅใฎๅ็ฝฎใซ็กๅนใช %%%c ใใใใพใ" -#: ../quickfix.c:454 #, c-format msgid "E377: Invalid %%%c in format string" msgstr "E377: ใใฉใผใใใๆๅญๅใซ็กๅนใช %%%c ใใใใพใ" #. nothing found -#: ../quickfix.c:477 msgid "E378: 'errorformat' contains no pattern" msgstr "E378: 'errorformat' ใซใใฟใผใณใๆๅฎใใใฆใใพใใ" -#: ../quickfix.c:695 msgid "E379: Missing or empty directory name" msgstr "E379: ใใฃใฌใฏใใชๅใ็กใใ็ฉบใงใ" -#: ../quickfix.c:1305 msgid "E553: No more items" msgstr "E553: ่ฆ็ด ใใใใใใพใใ" -#: ../quickfix.c:1674 +msgid "E924: Current window was closed" +msgstr "E924: ็พๅจใฎใฆใฃใณใใฆใ้ใใใใพใใ" + +msgid "E925: Current quickfix was changed" +msgstr "E925: ็พๅจใฎ quickfix ใๅคๆดใใใพใใ" + +msgid "E926: Current location list was changed" +msgstr "E926: ็พๅจใฎใญใฑใผใทใงใณใชในใใๅคๆดใใใพใใ" + #, c-format msgid "(%d of %d)%s%s: " msgstr "(%d of %d)%s%s: " -#: ../quickfix.c:1676 msgid " (line deleted)" msgstr " (่กใๅ้คใใใพใใ)" -#: ../quickfix.c:1863 +#, c-format +msgid "%serror list %d of %d; %d errors " +msgstr "%s ใจใฉใผไธ่ฆง %d of %d; %d ๅใจใฉใผ" + msgid "E380: At bottom of quickfix stack" msgstr "E380: quickfix ในใฟใใฏใฎๆซๅฐพใงใ" -#: ../quickfix.c:1869 msgid "E381: At top of quickfix stack" msgstr "E381: quickfix ในใฟใใฏใฎๅ
้ ญใงใ" -#: ../quickfix.c:1880 -#, c-format -msgid "error list %d of %d; %d errors" -msgstr "ใจใฉใผไธ่ฆง %d of %d; %d ๅใจใฉใผ" +msgid "No entries" +msgstr "ใจใณใใชใใใใพใใ" -#: ../quickfix.c:2427 msgid "E382: Cannot write, 'buftype' option is set" msgstr "E382: 'buftype' ใชใใทใงใณใ่จญๅฎใใใฆใใใฎใงๆธ่พผใฟใพใใ" -#: ../quickfix.c:2812 +msgid "Error file" +msgstr "ใจใฉใผใใกใคใซ" + msgid "E683: File name missing or invalid pattern" msgstr "E683: ใใกใคใซๅใ็กใใ็กๅนใชใใฟใผใณใงใ" -#: ../quickfix.c:2911 #, c-format msgid "Cannot open file \"%s\"" msgstr "ใใกใคใซ \"%s\" ใ้ใใพใใ" -#: ../quickfix.c:3429 msgid "E681: Buffer is not loaded" msgstr "E681: ใใใใกใฏ่ชญใฟ่พผใพใใพใใใงใใ" -#: ../quickfix.c:3487 msgid "E777: String or List expected" msgstr "E777: ๆๅญๅใใชในใใๅฟ
่ฆใงใ" -#: ../regexp.c:359 #, c-format msgid "E369: invalid item in %s%%[]" msgstr "E369: ็กๅนใช้
็ฎใงใ: %s%%[]" # -#: ../regexp.c:374 #, c-format msgid "E769: Missing ] after %s[" msgstr "E769: %s[ ใฎๅพใซ ] ใใใใพใใ" -#: ../regexp.c:375 #, c-format msgid "E53: Unmatched %s%%(" msgstr "E53: %s%%( ใ้ฃใๅใฃใฆใใพใใ" -#: ../regexp.c:376 #, c-format msgid "E54: Unmatched %s(" msgstr "E54: %s( ใ้ฃใๅใฃใฆใใพใใ" -#: ../regexp.c:377 #, c-format msgid "E55: Unmatched %s)" msgstr "E55: %s) ใ้ฃใๅใฃใฆใใพใใ" # -#: ../regexp.c:378 msgid "E66: \\z( not allowed here" msgstr "E66: \\z( ใฏใณใณใงใฏ่จฑๅฏใใใฆใใพใใ" # -#: ../regexp.c:379 msgid "E67: \\z1 et al. not allowed here" msgstr "E67: \\z1 ใใฎไปใฏใณใณใงใฏ่จฑๅฏใใใฆใใพใใ" # -#: ../regexp.c:380 #, c-format msgid "E69: Missing ] after %s%%[" msgstr "E69: %s%%[ ใฎๅพใซ ] ใใใใพใใ" -#: ../regexp.c:381 #, c-format msgid "E70: Empty %s%%[]" msgstr "E70: %s%%[] ใ็ฉบใงใ" -#: ../regexp.c:1209 ../regexp.c:1224 msgid "E339: Pattern too long" msgstr "E339: ใใฟใผใณใ้ท้ใใพใ" -#: ../regexp.c:1371 msgid "E50: Too many \\z(" msgstr "E50: \\z( ใๅค้ใใพใ" -#: ../regexp.c:1378 #, c-format msgid "E51: Too many %s(" msgstr "E51: %s( ใๅค้ใใพใ" -#: ../regexp.c:1427 msgid "E52: Unmatched \\z(" msgstr "E52: \\z( ใ้ฃใๅใฃใฆใใพใใ" -#: ../regexp.c:1637 #, c-format msgid "E59: invalid character after %s@" msgstr "E59: %s@ ใฎๅพใซไธๆญฃใชๆๅญใใใใพใใ" -#: ../regexp.c:1672 #, c-format msgid "E60: Too many complex %s{...}s" msgstr "E60: ่ค้ใช %s{...} ใๅค้ใใพใ" -#: ../regexp.c:1687 #, c-format msgid "E61: Nested %s*" msgstr "E61:%s* ใๅ
ฅใๅญใซใชใฃใฆใใพใ" -#: ../regexp.c:1690 #, c-format msgid "E62: Nested %s%c" msgstr "E62:%s%c ใๅ
ฅใๅญใซใชใฃใฆใใพใ" # -#: ../regexp.c:1800 msgid "E63: invalid use of \\_" msgstr "E63: \\_ ใฎ็กๅนใชไฝฟ็จๆนๆณใงใ" -#: ../regexp.c:1850 #, c-format msgid "E64: %s%c follows nothing" msgstr "E64:%s%c ใฎๅพใซใชใซใใใใพใใ" # -#: ../regexp.c:1902 msgid "E65: Illegal back reference" msgstr "E65: ไธๆญฃใชๅพๆนๅ็
งใงใ" # -#: ../regexp.c:1943 msgid "E68: Invalid character after \\z" msgstr "E68: \\z ใฎๅพใซไธๆญฃใชๆๅญใใใใพใใ" # -#: ../regexp.c:2049 ../regexp_nfa.c:1296 #, c-format msgid "E678: Invalid character after %s%%[dxouU]" msgstr "E678: %s%%[dxouU] ใฎๅพใซไธๆญฃใชๆๅญใใใใพใใ" # -#: ../regexp.c:2107 #, c-format msgid "E71: Invalid character after %s%%" msgstr "E71: %s%% ใฎๅพใซไธๆญฃใชๆๅญใใใใพใใ" -#: ../regexp.c:3017 #, c-format msgid "E554: Syntax error in %s{...}" msgstr "E554: %s{...} ๅ
ใซๆๆณใจใฉใผใใใใพใ" -#: ../regexp.c:3805 msgid "External submatches:\n" msgstr "ๅค้จใฎ้จๅ่ฉฒๅฝ:\n" @@ -5004,7 +4780,6 @@ msgstr "ๅค้จใฎ้จๅ่ฉฒๅฝ:\n" msgid "E888: (NFA regexp) cannot repeat %s" msgstr "E888: (NFA ๆญฃ่ฆ่กจ็พ) ็นฐใ่ฟใใพใใ %s" -#: ../regexp.c:7022 msgid "" "E864: \\%#= can only be followed by 0, 1, or 2. The automatic engine will be " "used " @@ -5015,62 +4790,54 @@ msgstr "" msgid "Switching to backtracking RE engine for pattern: " msgstr "ๆฌกใฎใใฟใผใณใซใใใฏใใฉใใญใณใฐ RE ใจใณใธใณใ้ฉ็จใใพใ: " -#: ../regexp_nfa.c:239 msgid "E865: (NFA) Regexp end encountered prematurely" msgstr "E865: (NFA) ๆๅพ
ใใๆฉใๆญฃ่ฆ่กจ็พใฎ็ต็ซฏใซๅฐ้ใใพใใ" -#: ../regexp_nfa.c:240 #, c-format msgid "E866: (NFA regexp) Misplaced %c" msgstr "E866: (NFA ๆญฃ่ฆ่กจ็พ) ไฝ็ฝฎใ่ชคใฃใฆใใพใ: %c" -#: ../regexp_nfa.c:242 +# #, c-format -msgid "E877: (NFA regexp) Invalid character class: %<PRId64>" -msgstr "E877: (NFA ๆญฃ่ฆ่กจ็พ) ็กๅนใชๆๅญใฏใฉใน: %<PRId64>" +msgid "E877: (NFA regexp) Invalid character class: %ld" +msgstr "E877: (NFA ๆญฃ่ฆ่กจ็พ) ็กๅนใชๆๅญใฏใฉใน: %ld" -#: ../regexp_nfa.c:1261 #, c-format msgid "E867: (NFA) Unknown operator '\\z%c'" msgstr "E867: (NFA) ๆช็ฅใฎใชใใฌใผใฟใงใ: '\\z%c'" -#: ../regexp_nfa.c:1387 #, c-format msgid "E867: (NFA) Unknown operator '\\%%%c'" msgstr "E867: (NFA) ๆช็ฅใฎใชใใฌใผใฟใงใ: '\\%%%c'" -#: ../regexp_nfa.c:1802 +#. should never happen +msgid "E868: Error building NFA with equivalence class!" +msgstr "E868: ็ญไพกใฏใฉในใๅซใNFAๆง็ฏใซๅคฑๆใใพใใ!" + #, c-format msgid "E869: (NFA) Unknown operator '\\@%c'" msgstr "E869: (NFA) ๆช็ฅใฎใชใใฌใผใฟใงใ: '\\@%c'" -#: ../regexp_nfa.c:1831 msgid "E870: (NFA regexp) Error reading repetition limits" msgstr "E870: (NFA ๆญฃ่ฆ่กจ็พ) ็นฐใ่ฟใใฎๅถ้ๅๆฐใ่ชญ่พผไธญใซใจใฉใผ" #. Can't have a multi follow a multi. -#: ../regexp_nfa.c:1895 msgid "E871: (NFA regexp) Can't have a multi follow a multi !" msgstr "E871: (NFA ๆญฃ่ฆ่กจ็พ) ็นฐใ่ฟใ ใฎๅพใซ ็นฐใ่ฟใ ใฏใงใใพใใ!" #. Too many `(' -#: ../regexp_nfa.c:2037 msgid "E872: (NFA regexp) Too many '('" msgstr "E872: (NFA ๆญฃ่ฆ่กจ็พ) '(' ใๅค้ใใพใ" -#: ../regexp_nfa.c:2042 msgid "E879: (NFA regexp) Too many \\z(" msgstr "E879: (NFA ๆญฃ่ฆ่กจ็พ) \\z( ใๅค้ใใพใ" -#: ../regexp_nfa.c:2066 msgid "E873: (NFA regexp) proper termination error" msgstr "E873: (NFA ๆญฃ่ฆ่กจ็พ) ็ต็ซฏ่จๅทใใใใพใใ" -#: ../regexp_nfa.c:2599 msgid "E874: (NFA) Could not pop the stack !" msgstr "E874: (NFA) ในใฟใใฏใใใใใงใใพใใ!" -#: ../regexp_nfa.c:3298 msgid "" "E875: (NFA regexp) (While converting from postfix to NFA), too many states " "left on stack" @@ -5078,177 +4845,136 @@ msgstr "" "E875: (NFA ๆญฃ่ฆ่กจ็พ) (ๅพ็ฝฎๆๅญๅใNFAใซๅคๆไธญใซ) ในใฟใใฏใซๆฎใใใในใใผใใ" "ๅค้ใใพใ" -#: ../regexp_nfa.c:3302 msgid "E876: (NFA regexp) Not enough space to store the whole NFA " msgstr "E876: (NFA ๆญฃ่ฆ่กจ็พ) NFAๅ
จไฝใไฟๅญใใใซใฏ็ฉบใในใใผในใ่ถณใใพใใ" -#: ../regexp_nfa.c:4571 ../regexp_nfa.c:4869 +msgid "E878: (NFA) Could not allocate memory for branch traversal!" +msgstr "E878: (NFA) ็พๅจๆจชๆญไธญใฎใใฉใณใใซๅๅใชใกใขใชใๅฒใๅฝใฆใใใพใใ!" + msgid "" "Could not open temporary log file for writing, displaying on stderr ... " msgstr "" "NFAๆญฃ่ฆ่กจ็พใจใณใธใณ็จใฎใญใฐใใกใคใซใๆธ่พผ็จใจใใฆ้ใใพใใใใญใฐใฏๆจๆบๅบๅใซ" "ๅบๅใใพใใ" -#: ../regexp_nfa.c:4840 #, c-format msgid "(NFA) COULD NOT OPEN %s !" msgstr "(NFA) ใญใฐใใกใคใซ %s ใ้ใใพใใ!" -#: ../regexp_nfa.c:6049 msgid "Could not open temporary log file for writing " msgstr "NFAๆญฃ่ฆ่กจ็พใจใณใธใณ็จใฎใญใฐใใกใคใซใๆธ่พผ็จใจใใฆ้ใใพใใใ" -#: ../screen.c:7435 msgid " VREPLACE" msgstr " ไปฎๆณ็ฝฎๆ" -#: ../screen.c:7437 msgid " REPLACE" msgstr " ็ฝฎๆ" -#: ../screen.c:7440 msgid " REVERSE" msgstr " ๅ่ปข" -#: ../screen.c:7441 msgid " INSERT" msgstr " ๆฟๅ
ฅ" -#: ../screen.c:7443 msgid " (insert)" msgstr " (ๆฟๅ
ฅ)" -#: ../screen.c:7445 msgid " (replace)" msgstr " (็ฝฎๆ)" -#: ../screen.c:7447 msgid " (vreplace)" msgstr " (ไปฎๆณ็ฝฎๆ)" -#: ../screen.c:7449 msgid " Hebrew" msgstr " ใใใฉใค" -#: ../screen.c:7454 msgid " Arabic" msgstr " ใขใฉใใข" -#: ../screen.c:7456 -msgid " (lang)" -msgstr " (่จ่ช)" - -#: ../screen.c:7459 msgid " (paste)" msgstr " (่ฒผใไปใ)" -#: ../screen.c:7469 msgid " VISUAL" msgstr " ใใธใฅใขใซ" -#: ../screen.c:7470 msgid " VISUAL LINE" msgstr " ใใธใฅใขใซ ่ก" -#: ../screen.c:7471 msgid " VISUAL BLOCK" msgstr " ใใธใฅใขใซ ็ฉๅฝข" -#: ../screen.c:7472 msgid " SELECT" msgstr " ใปใฌใฏใ" -#: ../screen.c:7473 msgid " SELECT LINE" msgstr " ่กๆๅ้ธๆ" -#: ../screen.c:7474 msgid " SELECT BLOCK" msgstr " ็ฉๅฝข้ธๆ" -#: ../screen.c:7486 ../screen.c:7541 msgid "recording" msgstr "่จ้ฒไธญ" -#: ../search.c:487 #, c-format msgid "E383: Invalid search string: %s" msgstr "E383: ็กๅนใชๆค็ดขๆๅญๅใงใ: %s" -#: ../search.c:832 #, c-format msgid "E384: search hit TOP without match for: %s" msgstr "E384: ไธใพใงๆค็ดขใใพใใใ่ฉฒๅฝ็ฎๆใฏใใใพใใ: %s" -#: ../search.c:835 #, c-format msgid "E385: search hit BOTTOM without match for: %s" msgstr "E385: ไธใพใงๆค็ดขใใพใใใ่ฉฒๅฝ็ฎๆใฏใใใพใใ: %s" -#: ../search.c:1200 msgid "E386: Expected '?' or '/' after ';'" msgstr "E386: ';' ใฎใใจใซใฏ '?' ใ '/' ใๆๅพ
ใใใฆใใ" -#: ../search.c:4085 msgid " (includes previously listed match)" msgstr " (ๅใซๅๆใใ่ฉฒๅฝ็ฎๆใๅซใ)" #. cursor at status line -#: ../search.c:4104 msgid "--- Included files " msgstr "--- ใคใณใฏใซใผใใใใใใกใคใซ " -#: ../search.c:4106 msgid "not found " msgstr "่ฆใคใใใพใใ " -#: ../search.c:4107 msgid "in path ---\n" msgstr "ใในใซ ----\n" -#: ../search.c:4168 msgid " (Already listed)" msgstr " (ๆขใซๅๆ)" -#: ../search.c:4170 msgid " NOT FOUND" msgstr " ่ฆใคใใใพใใ" -#: ../search.c:4211 #, c-format msgid "Scanning included file: %s" msgstr "ใคใณใฏใซใผใใใใใใกใคใซใในใญใฃใณไธญ: %s" -#: ../search.c:4216 #, c-format msgid "Searching included file %s" msgstr "ใคใณใฏใซใผใใใใใใกใคใซใในใญใฃใณไธญ %s" -#: ../search.c:4405 msgid "E387: Match is on current line" msgstr "E387: ็พๅจ่กใซ่ฉฒๅฝใใใใพใ" -#: ../search.c:4517 msgid "All included files were found" msgstr "ๅ
จใฆใฎใคใณใฏใซใผใใใใใใกใคใซใ่ฆใคใใใพใใ" -#: ../search.c:4519 msgid "No included files" msgstr "ใคใณใฏใซใผใใใกใคใซใฏใใใพใใ" -#: ../search.c:4527 msgid "E388: Couldn't find definition" msgstr "E388: ๅฎ็พฉใ่ฆใคใใใใพใใ" -#: ../search.c:4529 msgid "E389: Couldn't find pattern" msgstr "E389: ใใฟใผใณใ่ฆใคใใใใพใใ" -#: ../search.c:4668 msgid "Substitute " msgstr "Substitute " -#: ../search.c:4681 #, c-format msgid "" "\n" @@ -5259,99 +4985,131 @@ msgstr "" "# ๆๅพใฎ %sๆค็ดขใใฟใผใณ:\n" "~" -#: ../spell.c:951 -msgid "E759: Format error in spell file" -msgstr "E759: ในใใซใใกใคใซใฎๆธๅผใจใฉใผใงใ" +msgid "E756: Spell checking is not enabled" +msgstr "E756: ในใใซใใงใใฏใฏ็กๅนๅใใใฆใใพใ" + +#, c-format +msgid "Warning: Cannot find word list \"%s_%s.spl\" or \"%s_ascii.spl\"" +msgstr "" +"่ญฆๅ: ๅ่ชใชในใ \"%s_%s.spl\" ใใใณ \"%s_ascii.spl\" ใฏ่ฆใคใใใพใใ" + +#, c-format +msgid "Warning: Cannot find word list \"%s.%s.spl\" or \"%s.ascii.spl\"" +msgstr "" +"่ญฆๅ: ๅ่ชใชในใ \"%s.%s.spl\" ใใใณ \"%s.ascii.spl\" ใฏ่ฆใคใใใพใใ" + +msgid "E797: SpellFileMissing autocommand deleted buffer" +msgstr "E797: autocommand ใฎ SpellFileMissing ใใใใใกใๅ้คใใพใใ" + +#, c-format +msgid "Warning: region %s not supported" +msgstr "่ญฆๅ9: %s ใจใใ็ฏๅฒใฏใตใใผใใใใฆใใพใใ" + +msgid "Sorry, no suggestions" +msgstr "ๆฎๅฟตใงใใ, ไฟฎๆญฃๅ่ฃใฏใใใพใใ" + +#, c-format +msgid "Sorry, only %ld suggestions" +msgstr "ๆฎๅฟตใงใใ, ไฟฎๆญฃๅ่ฃใฏ %ld ๅใใใใใพใใ" + +#. for when 'cmdheight' > 1 +#. avoid more prompt +#, c-format +msgid "Change \"%.*s\" to:" +msgstr "\"%.*s\" ใๆฌกใธๅคๆ:" + +#, c-format +msgid " < \"%.*s\"" +msgstr " < \"%.*s\"" + +msgid "E752: No previous spell replacement" +msgstr "E752: ในใใซ็ฝฎๆใใพใ ๅฎ่กใใใฆใใพใใ" + +#, c-format +msgid "E753: Not found: %s" +msgstr "E753: ่ฆใคใใใพใใ: %s" -#: ../spell.c:952 msgid "E758: Truncated spell file" msgstr "E758: ในใใซใใกใคใซใๅๅใใใฆใใใใใงใ" -#: ../spell.c:953 #, c-format msgid "Trailing text in %s line %d: %s" msgstr "%s (%d ่ก็ฎ) ใซ็ถใใใญในใ: %s" -#: ../spell.c:954 #, c-format msgid "Affix name too long in %s line %d: %s" msgstr "%s (%d ่ก็ฎ) ใฎ affix ๅใ้ท้ใใพใ: %s" -#: ../spell.c:955 msgid "E761: Format error in affix file FOL, LOW or UPP" msgstr "" "E761: affixใใกใคใซใฎ FOL, LOW ใใใใฏ UPP ใฎใใฉใผใใใใซใจใฉใผใใใใพใ" -#: ../spell.c:957 msgid "E762: Character in FOL, LOW or UPP is out of range" msgstr "E762: FOL, LOW ใใใใฏ UPP ใฎๆๅญใ็ฏๅฒๅคใงใ" -#: ../spell.c:958 msgid "Compressing word tree..." msgstr "ๅ่ชใใชใผใๅง็ธฎใใฆใใพใ..." -#: ../spell.c:1951 -msgid "E756: Spell checking is not enabled" -msgstr "E756: ในใใซใใงใใฏใฏ็กๅนๅใใใฆใใพใ" - -#: ../spell.c:2249 -#, c-format -msgid "Warning: Cannot find word list \"%s.%s.spl\" or \"%s.ascii.spl\"" -msgstr "" -"่ญฆๅ: ๅ่ชใชในใ \"%s.%s.spl\" ใใใณ \"%s.ascii.spl\" ใฏ่ฆใคใใใพใใ" - -#: ../spell.c:2473 #, c-format msgid "Reading spell file \"%s\"" msgstr "ในใใซใใกใคใซ \"%s\" ใ่ชญ่พผไธญ" -#: ../spell.c:2496 msgid "E757: This does not look like a spell file" msgstr "E757: ในใใซใใกใคใซใงใฏใชใใใใงใ" -#: ../spell.c:2501 msgid "E771: Old spell file, needs to be updated" msgstr "E771: ๅคใในใใซใใกใคใซใชใฎใง, ใขใใใใผใใใฆใใ ใใ" -#: ../spell.c:2504 msgid "E772: Spell file is for newer version of Vim" msgstr "E772: ใใๆฐใใใใผใธใงใณใฎ Vim ็จใฎในใใซใใกใคใซใงใ" -#: ../spell.c:2602 msgid "E770: Unsupported section in spell file" msgstr "E770: ในใใซใใกใคใซใซใตใใผใใใฆใใชใใปใฏใทใงใณใใใใพใ" -#: ../spell.c:3762 #, c-format -msgid "Warning: region %s not supported" -msgstr "่ญฆๅ9: %s ใจใใ็ฏๅฒใฏใตใใผใใใใฆใใพใใ" +msgid "E778: This does not look like a .sug file: %s" +msgstr "E778: .sug ใใกใคใซใงใฏใชใใใใงใ: %s" + +#, c-format +msgid "E779: Old .sug file, needs to be updated: %s" +msgstr "E779: ๅคใ .sug ใใกใคใซใชใฎใง, ใขใใใใผใใใฆใใ ใใ: %s" + +#, c-format +msgid "E780: .sug file is for newer version of Vim: %s" +msgstr "E780: ใใๆฐใใใใผใธใงใณใฎ Vim ็จใฎ .sug ใใกใคใซใงใ: %s" + +#, c-format +msgid "E781: .sug file doesn't match .spl file: %s" +msgstr "E781: .sug ใใกใคใซใ .spl ใใกใคใซใจไธ่ดใใพใใ: %s" + +#, c-format +msgid "E782: error while reading .sug file: %s" +msgstr "E782: .sug ใใกใคใซใฎ่ชญ่พผไธญใซใจใฉใผใ็บ็ใใพใใ: %s" -#: ../spell.c:4550 #, c-format msgid "Reading affix file %s ..." msgstr "affix ใใกใคใซ %s ใ่ชญ่พผไธญ..." -#: ../spell.c:4589 ../spell.c:5635 ../spell.c:6140 #, c-format msgid "Conversion failure for word in %s line %d: %s" msgstr "%s (%d ่ก็ฎ) ใฎๅ่ชใๅคๆใงใใพใใใงใใ: %s" -#: ../spell.c:4630 ../spell.c:6170 #, c-format msgid "Conversion in %s not supported: from %s to %s" msgstr "%s ๅ
ใฎๆฌกใฎๅคๆใฏใตใใผใใใใฆใใพใใ: %s ใใ %s ใธ" -#: ../spell.c:4642 +#, c-format +msgid "Conversion in %s not supported" +msgstr "%s ๅ
ใฎๅคๆใฏใตใใผใใใใฆใใพใใ" + #, c-format msgid "Invalid value for FLAG in %s line %d: %s" msgstr "%s ๅ
ใฎ %d ่ก็ฎใฎ FLAG ใซ็กๅนใชๅคใใใใพใ: %s" -#: ../spell.c:4655 #, c-format msgid "FLAG after using flags in %s line %d: %s" msgstr "%s ๅ
ใฎ %d ่ก็ฎใซใใฉใฐใฎไบ้ไฝฟ็จใใใใพใ: %s" -#: ../spell.c:4723 #, c-format msgid "" "Defining COMPOUNDFORBIDFLAG after PFX item may give wrong results in %s line " @@ -5360,7 +5118,6 @@ msgstr "" "%s ใฎ %d ่ก็ฎใฎ PFX ้
็ฎใฎๅพใฎ COMPOUNDFORBIDFLAG ใฎๅฎ็พฉใฏ่ชคใฃใ็ตๆใ็ใใ" "ใใจใใใใพใ" -#: ../spell.c:4731 #, c-format msgid "" "Defining COMPOUNDPERMITFLAG after PFX item may give wrong results in %s line " @@ -5369,43 +5126,35 @@ msgstr "" "%s ใฎ %d ่ก็ฎใฎ PFX ้
็ฎใฎๅพใฎ COMPOUNDPERMITFLAG ใฎๅฎ็พฉใฏ่ชคใฃใ็ตๆใ็ใใ" "ใใจใใใใพใ" -#: ../spell.c:4747 #, c-format msgid "Wrong COMPOUNDRULES value in %s line %d: %s" msgstr "COMPOUNDRULES ใฎๅคใซ่ชคใใใใใพใ. ใใกใคใซ %s ใฎ %d ่ก็ฎ: %s" -#: ../spell.c:4771 #, c-format msgid "Wrong COMPOUNDWORDMAX value in %s line %d: %s" msgstr "%s ใฎ %d ่ก็ฎใฎ COMPOUNDWORDMAX ใฎๅคใซ่ชคใใใใใพใ: %s" -#: ../spell.c:4777 #, c-format msgid "Wrong COMPOUNDMIN value in %s line %d: %s" msgstr "%s ใฎ %d ่ก็ฎใฎ COMPOUNDMIN ใฎๅคใซ่ชคใใใใใพใ: %s" -#: ../spell.c:4783 #, c-format msgid "Wrong COMPOUNDSYLMAX value in %s line %d: %s" msgstr "%s ใฎ %d ่ก็ฎใฎ COMPOUNDSYLMAX ใฎๅคใซ่ชคใใใใใพใ: %s" -#: ../spell.c:4795 #, c-format msgid "Wrong CHECKCOMPOUNDPATTERN value in %s line %d: %s" msgstr "%s ใฎ %d ่ก็ฎใฎ CHECKCOMPOUNDPATTERN ใฎๅคใซ่ชคใใใใใพใ: %s" -#: ../spell.c:4847 #, c-format msgid "Different combining flag in continued affix block in %s line %d: %s" msgstr "" "%s ใฎ %d ่ก็ฎใฎ ้ฃ็ถ affix ใใญใใฏใฎใใฉใฐใฎ็ตๅใใซ้ใใใใใพใ: %s" -#: ../spell.c:4850 #, c-format msgid "Duplicate affix in %s line %d: %s" msgstr "%s ใฎ %d ่ก็ฎใซ ้่คใใ affix ใๆคๅบใใพใใ: %s" -#: ../spell.c:4871 #, c-format msgid "" "Affix also used for BAD/RARE/KEEPCASE/NEEDAFFIX/NEEDCOMPOUND/NOSUGGEST in %s " @@ -5414,308 +5163,206 @@ msgstr "" "%s ใฎ %d ่ก็ฎใฎ affix ใฏ BAD/RARE/KEEPCASE/NEEDAFFIX/NEEDCOMPOUND/NOSUGGEST " "ใซไฝฟ็จใใฆใใ ใใ: %s" -#: ../spell.c:4893 #, c-format msgid "Expected Y or N in %s line %d: %s" msgstr "%s ใฎ %d ่ก็ฎใงใฏ Y ใ N ใๅฟ
่ฆใงใ: %s" -#: ../spell.c:4968 #, c-format msgid "Broken condition in %s line %d: %s" msgstr "%s ใฎ %d ่ก็ฎใฎ ๆกไปถใฏๅฃใใฆใใพใ: %s" -#: ../spell.c:5091 #, c-format msgid "Expected REP(SAL) count in %s line %d" msgstr "%s ใฎ %d ่ก็ฎใซใฏ REP(SAL) ใฎๅๆฐใๅฟ
่ฆใงใ" -#: ../spell.c:5120 #, c-format msgid "Expected MAP count in %s line %d" msgstr "%s ใฎ %d ่ก็ฎใซใฏ MAP ใฎๅๆฐใๅฟ
่ฆใงใ" -#: ../spell.c:5132 #, c-format msgid "Duplicate character in MAP in %s line %d" msgstr "%s ใฎ %d ่ก็ฎใฎ MAP ใซ้่คใใๆๅญใใใใพใ" -#: ../spell.c:5176 #, c-format msgid "Unrecognized or duplicate item in %s line %d: %s" msgstr "%s ใฎ %d ่ก็ฎใซ ่ช่ญใงใใชใใ้่คใใ้
็ฎใใใใพใ: %s" -#: ../spell.c:5197 #, c-format msgid "Missing FOL/LOW/UPP line in %s" msgstr "%s ่ก็ฎใซ FOL/LOW/UPP ใใใใพใใ" -#: ../spell.c:5220 msgid "COMPOUNDSYLMAX used without SYLLABLE" msgstr "SYLLABLE ใๆๅฎใใใชใ COMPOUNDSYLMAX" -#: ../spell.c:5236 msgid "Too many postponed prefixes" msgstr "้
ๅปถๅพ็ฝฎๅญใๅค้ใใพใ" -#: ../spell.c:5238 msgid "Too many compound flags" msgstr "่คๅใใฉใฐใๅค้ใใพใ" -#: ../spell.c:5240 msgid "Too many postponed prefixes and/or compound flags" msgstr "้
ๅปถๅพ็ฝฎๅญ ใจ/ใใใใฏ ่คๅใใฉใฐใๅค้ใใพใ" -#: ../spell.c:5250 #, c-format msgid "Missing SOFO%s line in %s" msgstr "SOFO%s ่กใ %s ใซใใใพใใ" -#: ../spell.c:5253 #, c-format msgid "Both SAL and SOFO lines in %s" msgstr "SAL่ก ใจ SOFO่ก ใ %s ใงไธกๆนๆๅฎใใใฆใใพใ" -#: ../spell.c:5331 #, c-format msgid "Flag is not a number in %s line %d: %s" msgstr "%s ใฎ %d ่กใฎ ใใฉใฐใๆฐๅคใงใฏใใใพใใ: %s" -#: ../spell.c:5334 #, c-format msgid "Illegal flag in %s line %d: %s" msgstr "%s ใฎ %d ่ก็ฎใฎ ใใฉใฐใไธๆญฃใงใ: %s" -#: ../spell.c:5493 ../spell.c:5501 #, c-format msgid "%s value differs from what is used in another .aff file" msgstr "ๅค %s ใฏไปใฎ .aff ใใกใคใซใงไฝฟ็จใใใใฎใจ็ฐใชใใพใ" -#: ../spell.c:5602 #, c-format msgid "Reading dictionary file %s ..." msgstr "่พๆธใใกใคใซ %s ใในใญใฃใณไธญ..." -#: ../spell.c:5611 #, c-format msgid "E760: No word count in %s" msgstr "E760: %s ใซใฏๅ่ชๆฐใใใใพใใ" -#: ../spell.c:5669 #, c-format msgid "line %6d, word %6d - %s" msgstr "่ก %6d, ๅ่ช %6d - %s" -#: ../spell.c:5691 #, c-format msgid "Duplicate word in %s line %d: %s" msgstr "%s ใฎ %d ่ก็ฎใง ้่คๅ่ชใ่ฆใคใใใพใใ: %s" -#: ../spell.c:5694 #, c-format msgid "First duplicate word in %s line %d: %s" msgstr "้่คใฎใใกๆๅใฎๅ่ชใฏ %s ใฎ %d ่ก็ฎใงใ: %s" -#: ../spell.c:5746 #, c-format msgid "%d duplicate word(s) in %s" msgstr "%d ๅใฎๅ่ชใ่ฆใคใใใพใใ (%s ๅ
)" -#: ../spell.c:5748 #, c-format msgid "Ignored %d word(s) with non-ASCII characters in %s" msgstr "้ASCIIๆๅญใๅซใ %d ๅใฎๅ่ชใ็ก่ฆใใพใใ (%s ๅ
)" -#: ../spell.c:6115 #, c-format msgid "Reading word file %s ..." msgstr "ๆจๆบๅ
ฅๅใใ่ชญ่พผใฟไธญ %s ..." -#: ../spell.c:6155 #, c-format msgid "Duplicate /encoding= line ignored in %s line %d: %s" msgstr "%s ใฎ %d ่ก็ฎใฎ ้่คใใ /encoding= ่กใ็ก่ฆใใพใใ: %s" -#: ../spell.c:6159 #, c-format msgid "/encoding= line after word ignored in %s line %d: %s" msgstr "%s ใฎ %d ่ก็ฎใฎ ๅ่ชใฎๅพใฎ /encoding= ่กใ็ก่ฆใใพใใ: %s" -#: ../spell.c:6180 #, c-format msgid "Duplicate /regions= line ignored in %s line %d: %s" msgstr "%s ใฎ %d ่ก็ฎใฎ ้่คใใ /regions= ่กใ็ก่ฆใใพใใ: %s" -#: ../spell.c:6185 #, c-format msgid "Too many regions in %s line %d: %s" msgstr "%s ใฎ %d ่ก็ฎ, ็ฏๅฒๆๅฎใๅค้ใใพใ: %s" -#: ../spell.c:6198 #, c-format msgid "/ line ignored in %s line %d: %s" msgstr "%s ใฎ %d ่ก็ฎใฎ ้่คใใ / ่กใ็ก่ฆใใพใใ: %s" -#: ../spell.c:6224 #, c-format msgid "Invalid region nr in %s line %d: %s" msgstr "%s ใฎ %d ่ก็ฎ ็กๅนใช nr ้ ๅใงใ: %s" -#: ../spell.c:6230 #, c-format msgid "Unrecognized flags in %s line %d: %s" msgstr "%s ใฎ %d ่ก็ฎ ่ช่ญไธ่ฝใชใใฉใฐใงใ: %s" -#: ../spell.c:6257 #, c-format msgid "Ignored %d words with non-ASCII characters" msgstr "้ASCIIๆๅญใๅซใ %d ๅใฎๅ่ชใ็ก่ฆใใพใใ" -#: ../spell.c:6656 +msgid "E845: Insufficient memory, word list will be incomplete" +msgstr "E845: ใกใขใชใ่ถณใใชใใฎใงใๅ่ชใชในใใฏไธๅฎๅ
จใงใ" + #, c-format msgid "Compressed %d of %d nodes; %d (%d%%) remaining" msgstr "ใใผใ %d ๅ(ๅ
จ %d ๅไธญ) ใๅง็ธฎใใพใใ; ๆฎใ %d (%d%%)" -#: ../spell.c:7340 msgid "Reading back spell file..." msgstr "ในใใซใใกใคใซใ้่ชญ่พผไธญ" -#. Go through the trie of good words, soundfold each word and add it to -#. the soundfold trie. -#: ../spell.c:7357 +#. +#. * Go through the trie of good words, soundfold each word and add it to +#. * the soundfold trie. +#. msgid "Performing soundfolding..." msgstr "้ณๅฃฐ็ณ่พผใฟใๅฎ่กไธญ..." -#: ../spell.c:7368 #, c-format -msgid "Number of words after soundfolding: %<PRId64>" -msgstr "้ณๅฃฐ็ณ่พผใฟๅพใฎ็ทๅ่ชๆฐ: %<PRId64>" +msgid "Number of words after soundfolding: %ld" +msgstr "้ณๅฃฐ็ณ่พผใฟๅพใฎ็ทๅ่ชๆฐ: %ld" -#: ../spell.c:7476 #, c-format msgid "Total number of words: %d" msgstr "็ทๅ่ชๆฐ: %d" -#: ../spell.c:7655 #, c-format msgid "Writing suggestion file %s ..." msgstr "ไฟฎๆญฃๅ่ฃใใกใคใซ \"%s\" ใๆธ่พผใฟไธญ..." -#: ../spell.c:7707 ../spell.c:7927 #, c-format msgid "Estimated runtime memory use: %d bytes" msgstr "ๆจๅฎใกใขใชไฝฟ็จ้: %d ใใคใ" -#: ../spell.c:7820 msgid "E751: Output file name must not have region name" msgstr "E751: ๅบๅใใกใคใซๅใซใฏ็ฏๅฒๅใๅซใใใใพใใ" -#: ../spell.c:7822 msgid "E754: Only up to 8 regions supported" msgstr "E754: ็ฏๅฒใฏ 8 ๅใพใงใใใตใใผใใใใฆใใพใใ" -#: ../spell.c:7846 #, c-format msgid "E755: Invalid region in %s" msgstr "E755: ็กๅนใช็ฏๅฒใงใ: %s" -#: ../spell.c:7907 msgid "Warning: both compounding and NOBREAK specified" msgstr "่ญฆๅ: ่คๅใใฉใฐใจ NOBREAK ใไธกๆนใจใๆๅฎใใใพใใ" -#: ../spell.c:7920 #, c-format msgid "Writing spell file %s ..." msgstr "ในใใซใใกใคใซ %s ใๆธ่พผใฟไธญ..." -#: ../spell.c:7925 msgid "Done!" msgstr "ๅฎ่กใใพใใ!" -#: ../spell.c:8034 #, c-format -msgid "E765: 'spellfile' does not have %<PRId64> entries" -msgstr "E765: 'spellfile' ใซใฏ %<PRId64> ๅใฎใจใณใใชใฏใใใพใใ" +msgid "E765: 'spellfile' does not have %ld entries" +msgstr "E765: 'spellfile' ใซใฏ %ld ๅใฎใจใณใใชใฏใใใพใใ" -#: ../spell.c:8074 #, c-format msgid "Word '%.*s' removed from %s" msgstr "ๅ่ช '%.*s' ใ %s ใใๅ้คใใใพใใ" -#: ../spell.c:8117 #, c-format msgid "Word '%.*s' added to %s" msgstr "ๅ่ช '%.*s' ใ %s ใธ่ฟฝๅ ใใใพใใ" -#: ../spell.c:8381 msgid "E763: Word characters differ between spell files" msgstr "E763: ๅ่ชใฎๆๅญใในใใซใใกใคใซใจ็ฐใชใใพใ" -#: ../spell.c:8684 -msgid "Sorry, no suggestions" -msgstr "ๆฎๅฟตใงใใ, ไฟฎๆญฃๅ่ฃใฏใใใพใใ" - -#: ../spell.c:8687 -#, c-format -msgid "Sorry, only %<PRId64> suggestions" -msgstr "ๆฎๅฟตใงใใ, ไฟฎๆญฃๅ่ฃใฏ %<PRId64> ๅใใใใใพใใ" - -#. for when 'cmdheight' > 1 -#. avoid more prompt -#: ../spell.c:8704 -#, c-format -msgid "Change \"%.*s\" to:" -msgstr "\"%.*s\" ใๆฌกใธๅคๆ:" - -#: ../spell.c:8737 -#, c-format -msgid " < \"%.*s\"" -msgstr " < \"%.*s\"" - -#: ../spell.c:8882 -msgid "E752: No previous spell replacement" -msgstr "E752: ในใใซ็ฝฎๆใใพใ ๅฎ่กใใใฆใใพใใ" - -#: ../spell.c:8925 -#, c-format -msgid "E753: Not found: %s" -msgstr "E753: ่ฆใคใใใพใใ: %s" - -#: ../spell.c:9276 -#, c-format -msgid "E778: This does not look like a .sug file: %s" -msgstr "E778: .sug ใใกใคใซใงใฏใชใใใใงใ: %s" - -#: ../spell.c:9282 -#, c-format -msgid "E779: Old .sug file, needs to be updated: %s" -msgstr "E779: ๅคใ .sug ใใกใคใซใชใฎใง, ใขใใใใผใใใฆใใ ใใ: %s" - -#: ../spell.c:9286 -#, c-format -msgid "E780: .sug file is for newer version of Vim: %s" -msgstr "E780: ใใๆฐใใใใผใธใงใณใฎ Vim ็จใฎ .sug ใใกใคใซใงใ: %s" - -#: ../spell.c:9295 -#, c-format -msgid "E781: .sug file doesn't match .spl file: %s" -msgstr "E781: .sug ใใกใคใซใ .spl ใใกใคใซใจไธ่ดใใพใใ: %s" - -#: ../spell.c:9305 -#, c-format -msgid "E782: error while reading .sug file: %s" -msgstr "E782: .sug ใใกใคใซใฎ่ชญ่พผไธญใซใจใฉใผใ็บ็ใใพใใ: %s" - #. This should have been checked when generating the .spl -#. file. -#: ../spell.c:11575 +#. * file. msgid "E783: duplicate char in MAP entry" msgstr "E783: MAP ใจใณใใชใซ้่คๆๅญใๅญๅจใใพใ" -#: ../syntax.c:266 msgid "No Syntax items defined for this buffer" msgstr "ใใฎใใใใกใซๅฎ็พฉใใใๆงๆ่ฆ็ด ใฏใใใพใใ" -#: ../syntax.c:3083 ../syntax.c:3104 ../syntax.c:3127 #, c-format msgid "E390: Illegal argument: %s" msgstr "E390: ไธๆญฃใชๅผๆฐใงใ: %s" @@ -5723,28 +5370,22 @@ msgstr "E390: ไธๆญฃใชๅผๆฐใงใ: %s" msgid "syntax iskeyword " msgstr "ใทใณใฟใใฏใน็จ iskeyword " -#: ../syntax.c:3299 #, c-format msgid "E391: No such syntax cluster: %s" msgstr "E391: ใใฎใใใชๆงๆใฏใฉในใฟใฏใใใพใใ: %s" -#: ../syntax.c:3433 msgid "syncing on C-style comments" msgstr "C่จ่ช้ขจใณใกใณใใใๅๆไธญ" -#: ../syntax.c:3439 msgid "no syncing" msgstr "้ๅๆ" -#: ../syntax.c:3441 msgid "syncing starts " msgstr "ๅๆ้ๅง " -#: ../syntax.c:3443 ../syntax.c:3506 msgid " lines before top line" msgstr " ่กๅ(ใใใ่กใใใ)" -#: ../syntax.c:3448 msgid "" "\n" "--- Syntax sync items ---" @@ -5752,7 +5393,6 @@ msgstr "" "\n" "--- ๆงๆๅๆ่ฆ็ด ---" -#: ../syntax.c:3452 msgid "" "\n" "syncing on items" @@ -5760,7 +5400,6 @@ msgstr "" "\n" "่ฆ็ด ไธใงๅๆไธญ" -#: ../syntax.c:3457 msgid "" "\n" "--- Syntax items ---" @@ -5768,53 +5407,41 @@ msgstr "" "\n" "--- ๆงๆ่ฆ็ด ---" -#: ../syntax.c:3475 #, c-format msgid "E392: No such syntax cluster: %s" msgstr "E392: ใใฎใใใชๆงๆใฏใฉในใฟใฏใใใพใใ: %s" -#: ../syntax.c:3497 msgid "minimal " msgstr "minimal " -#: ../syntax.c:3503 msgid "maximal " msgstr "maximal " -#: ../syntax.c:3513 msgid "; match " msgstr "; ่ฉฒๅฝ " -#: ../syntax.c:3515 msgid " line breaks" msgstr " ๅใฎๆน่ก" -#: ../syntax.c:4076 msgid "E395: contains argument not accepted here" msgstr "E395: ใใฎๅ ดๆใงใฏๅผๆฐcontainsใฏ่จฑๅฏใใใฆใใพใใ" -#: ../syntax.c:4096 msgid "E844: invalid cchar value" msgstr "E844: ็กๅนใชccharใฎๅคใงใ" -#: ../syntax.c:4107 msgid "E393: group[t]here not accepted here" msgstr "E393: ใใใงใฏใฐใซใผใใฏ่จฑๅฏใใใพใใ" -#: ../syntax.c:4126 #, c-format msgid "E394: Didn't find region item for %s" msgstr "E394: %s ใฎ็ฏๅฒ่ฆ็ด ใ่ฆใคใใใพใใ" -#: ../syntax.c:4188 msgid "E397: Filename required" msgstr "E397: ใใกใคใซๅใๅฟ
่ฆใงใ" -#: ../syntax.c:4221 msgid "E847: Too many syntax includes" msgstr "E847: ๆงๆใฎๅใ่พผใฟ(include)ใๅค้ใใพใ" -#: ../syntax.c:4303 #, c-format msgid "E789: Missing ']': %s" msgstr "E789: ']' ใใใใพใใ: %s" @@ -5823,221 +5450,173 @@ msgstr "E789: ']' ใใใใพใใ: %s" msgid "E890: trailing char after ']': %s]%s" msgstr "E890: ']' ใฎๅพใใซไฝๅใชๆๅญใใใใพใ: %s]%s" -#: ../syntax.c:4531 #, c-format msgid "E398: Missing '=': %s" msgstr "E398: '=' ใใใใพใใ: %s" -#: ../syntax.c:4666 #, c-format msgid "E399: Not enough arguments: syntax region %s" msgstr "E399: ๅผๆฐใ่ถณใใพใใ: ๆงๆ็ฏๅฒ %s" -#: ../syntax.c:4870 msgid "E848: Too many syntax clusters" msgstr "E848: ๆงๆใฏใฉในใฟใๅค้ใใพใ" -#: ../syntax.c:4954 msgid "E400: No cluster specified" msgstr "E400: ใฏใฉในใฟใๆๅฎใใใฆใใพใใ" -#. end delimiter not found -#: ../syntax.c:4986 #, c-format msgid "E401: Pattern delimiter not found: %s" msgstr "E401: ใใฟใผใณๅบๅใใ่ฆใคใใใพใใ: %s" -#: ../syntax.c:5049 #, c-format msgid "E402: Garbage after pattern: %s" msgstr "E402: ใใฟใผใณใฎใใจใซใดใใใใใพใ: %s" -#: ../syntax.c:5120 msgid "E403: syntax sync: line continuations pattern specified twice" msgstr "E403: ๆงๆๅๆ: ้ฃ็ถ่กใใฟใผใณใ2ๅบฆๆๅฎใใใพใใ" -#: ../syntax.c:5169 #, c-format msgid "E404: Illegal arguments: %s" msgstr "E404: ไธๆญฃใชๅผๆฐใงใ: %s" -#: ../syntax.c:5217 #, c-format msgid "E405: Missing equal sign: %s" msgstr "E405: ็ญๅทใใใใพใใ: %s" -#: ../syntax.c:5222 #, c-format msgid "E406: Empty argument: %s" msgstr "E406: ็ฉบใฎๅผๆฐ: %s" -#: ../syntax.c:5240 #, c-format msgid "E407: %s not allowed here" msgstr "E407: %s ใฏใณใณใงใฏ่จฑๅฏใใใฆใใพใใ" -#: ../syntax.c:5246 #, c-format msgid "E408: %s must be first in contains list" msgstr "E408: %s ใฏๅ
ๅฎนใชในใใฎๅ
้ ญใงใชใใใฐใชใใชใ" -#: ../syntax.c:5304 #, c-format msgid "E409: Unknown group name: %s" msgstr "E409: ๆช็ฅใฎใฐใซใผใๅ: %s" -#: ../syntax.c:5512 #, c-format msgid "E410: Invalid :syntax subcommand: %s" msgstr "E410: ็กๅนใช :syntax ใฎใตใใณใใณใ: %s" -#: ../syntax.c:5854 msgid "" " TOTAL COUNT MATCH SLOWEST AVERAGE NAME PATTERN" msgstr "" " TOTAL COUNT MATCH SLOWEST AVERAGE NAME PATTERN" -#: ../syntax.c:6146 msgid "E679: recursive loop loading syncolor.vim" msgstr "E679: syncolor.vim ใฎๅๅธฐๅผใณๅบใใๆคๅบใใพใใ" -#: ../syntax.c:6256 #, c-format msgid "E411: highlight group not found: %s" msgstr "E411: ใใคใฉใคใใฐใซใผใใ่ฆใคใใใพใใ: %s" -#: ../syntax.c:6278 #, c-format msgid "E412: Not enough arguments: \":highlight link %s\"" msgstr "E412: ๅผๆฐใๅ
ๅใงใฏใชใ: \":highlight link %s\"" -#: ../syntax.c:6284 #, c-format msgid "E413: Too many arguments: \":highlight link %s\"" msgstr "E413: ๅผๆฐใๅค้ใใพใ: \":highlight link %s\"" -#: ../syntax.c:6302 msgid "E414: group has settings, highlight link ignored" msgstr "E414: ใฐใซใผใใ่จญๅฎใใใฆใใใฎใงใใคใฉใคใใชใณใฏใฏ็ก่ฆใใใพใ" -#: ../syntax.c:6367 #, c-format msgid "E415: unexpected equal sign: %s" msgstr "E415: ไบๆใใฌ็ญๅทใงใ: %s" -#: ../syntax.c:6395 #, c-format msgid "E416: missing equal sign: %s" msgstr "E416: ็ญๅทใใใใพใใ: %s" -#: ../syntax.c:6418 #, c-format msgid "E417: missing argument: %s" msgstr "E417: ๅผๆฐใใใใพใใ: %s" -#: ../syntax.c:6446 #, c-format msgid "E418: Illegal value: %s" msgstr "E418: ไธๆญฃใชๅคใงใ: %s" -#: ../syntax.c:6496 msgid "E419: FG color unknown" msgstr "E419: ๆช็ฅใฎๅๆฏ่ฒใงใ" -#: ../syntax.c:6504 msgid "E420: BG color unknown" msgstr "E420: ๆช็ฅใฎ่ๆฏ่ฒใงใ" -#: ../syntax.c:6564 #, c-format msgid "E421: Color name or number not recognized: %s" msgstr "E421: ใซใฉใผๅใ็ชๅทใ่ช่ญใงใใพใใ: %s" -#: ../syntax.c:6714 #, c-format msgid "E422: terminal code too long: %s" msgstr "E422: ็ต็ซฏใณใผใใ้ท้ใใพใ: %s" -#: ../syntax.c:6753 #, c-format msgid "E423: Illegal argument: %s" msgstr "E423: ไธๆญฃใชๅผๆฐใงใ: %s" -#: ../syntax.c:6925 msgid "E424: Too many different highlighting attributes in use" msgstr "E424: ๅคใใฎ็ฐใชใใใคใฉใคใๅฑๆงใไฝฟใใ้ใใฆใใพใ" -#: ../syntax.c:7427 msgid "E669: Unprintable character in group name" msgstr "E669: ใฐใซใผใๅใซๅฐๅทไธๅฏ่ฝใชๆๅญใใใใพใ" -#: ../syntax.c:7434 msgid "W18: Invalid character in group name" msgstr "W18: ใฐใซใผใๅใซไธๆญฃใชๆๅญใใใใพใ" -#: ../syntax.c:7448 msgid "E849: Too many highlight and syntax groups" msgstr "E849: ใใคใฉใคใใจๆงๆใฐใซใผใใๅค้ใใพใ" -#: ../tag.c:104 msgid "E555: at bottom of tag stack" msgstr "E555: ใฟใฐในใฟใใฏใฎๆซๅฐพใงใ" -#: ../tag.c:105 msgid "E556: at top of tag stack" msgstr "E556: ใฟใฐในใฟใใฏใฎๅ
้ ญใงใ" -#: ../tag.c:380 msgid "E425: Cannot go before first matching tag" msgstr "E425: ๆๅใฎ่ฉฒๅฝใฟใฐใ่ถ
ใใฆๆปใใใจใฏใงใใพใใ" -#: ../tag.c:504 #, c-format msgid "E426: tag not found: %s" msgstr "E426: ใฟใฐใ่ฆใคใใใพใใ: %s" -#: ../tag.c:528 msgid " # pri kind tag" msgstr " # pri kind tag" -#: ../tag.c:531 msgid "file\n" msgstr "ใใกใคใซ\n" -#: ../tag.c:829 msgid "E427: There is only one matching tag" msgstr "E427: ่ฉฒๅฝใฟใฐใ1ใคใ ใใใใใใพใใ" -#: ../tag.c:831 msgid "E428: Cannot go beyond last matching tag" msgstr "E428: ๆๅพใซ่ฉฒๅฝใใใฟใฐใ่ถ
ใใฆ้ฒใใใจใฏใงใใพใใ" -#: ../tag.c:850 #, c-format msgid "File \"%s\" does not exist" msgstr "ใใกใคใซ \"%s\" ใใใใพใใ" #. Give an indication of the number of matching tags -#: ../tag.c:859 #, c-format msgid "tag %d of %d%s" msgstr "ใฟใฐ %d (ๅ
จ%d%s)" -#: ../tag.c:862 msgid " or more" msgstr " ใใใไปฅไธ" -#: ../tag.c:864 msgid " Using tag with different case!" msgstr " ใฟใฐใ็ฐใชใcaseใงไฝฟ็จใใพใ!" -#: ../tag.c:909 #, c-format msgid "E429: File \"%s\" does not exist" msgstr "E429: ใใกใคใซ \"%s\" ใใใใพใใ" #. Highlight title -#: ../tag.c:960 msgid "" "\n" " # TO tag FROM line in file/text" @@ -6045,79 +5624,66 @@ msgstr "" "\n" " # TO ใฟใฐ FROM ่ก in file/text" -#: ../tag.c:1303 #, c-format msgid "Searching tags file %s" msgstr "ใฟใฐใใกใคใซ %s ใๆค็ดขไธญ" -#: ../tag.c:1545 +#, c-format +msgid "E430: Tag file path truncated for %s\n" +msgstr "E430: ใฟใฐใใกใคใซใฎใในใ %s ใซๅใๆจใฆใใใพใใ\n" + msgid "Ignoring long line in tags file" msgstr "ใฟใฐใใกใคใซๅ
ใฎ้ทใ่กใ็ก่ฆใใพใ" -#: ../tag.c:1915 #, c-format msgid "E431: Format error in tags file \"%s\"" msgstr "E431: ใฟใฐใใกใคใซ \"%s\" ใฎใใฉใผใใใใซใจใฉใผใใใใพใ" -#: ../tag.c:1917 #, c-format -msgid "Before byte %<PRId64>" -msgstr "็ดๅใฎ %<PRId64> ใใคใ" +msgid "Before byte %ld" +msgstr "็ดๅใฎ %ld ใใคใ" -#: ../tag.c:1929 #, c-format msgid "E432: Tags file not sorted: %s" msgstr "E432: ใฟใฐใใกใคใซใใฝใผใใใใฆใใพใใ: %s" #. never opened any tags file -#: ../tag.c:1960 msgid "E433: No tags file" msgstr "E433: ใฟใฐใใกใคใซใใใใพใใ" -#: ../tag.c:2536 msgid "E434: Can't find tag pattern" msgstr "E434: ใฟใฐใใฟใผใณใ่ฆใคใใใใพใใ" -#: ../tag.c:2544 msgid "E435: Couldn't find tag, just guessing!" msgstr "E435: ใฟใฐใ่ฆใคใใใใชใใฎใงๅใซๆจๆธฌใใพใ!" -#: ../tag.c:2797 #, c-format msgid "Duplicate field name: %s" msgstr "้่คใใใใฃใผใซใๅ: %s" -#: ../term.c:1442 msgid "' not known. Available builtin terminals are:" msgstr "' ใฏๆช็ฅใงใ. ็พ่กใฎ็ตใฟ่พผใฟ็ซฏๆซใฏๆฌกใฎใจใใใงใ:" -#: ../term.c:1463 msgid "defaulting to '" msgstr "็็ฅๅคใๆฌกใฎใใใซ่จญๅฎใใพใ '" -#: ../term.c:1731 msgid "E557: Cannot open termcap file" msgstr "E557: termcapใใกใคใซใ้ใใพใใ" -#: ../term.c:1735 msgid "E558: Terminal entry not found in terminfo" msgstr "E558: terminfoใซ็ซฏๆซใจใณใใชใ่ฆใคใใใใพใใ" -#: ../term.c:1737 msgid "E559: Terminal entry not found in termcap" msgstr "E559: termcapใซ็ซฏๆซใจใณใใชใ่ฆใคใใใใพใใ" -#: ../term.c:1878 #, c-format msgid "E436: No \"%s\" entry in termcap" msgstr "E436: termcapใซ \"%s\" ใฎใจใณใใชใใใใพใใ" -#: ../term.c:2249 msgid "E437: terminal capability \"cm\" required" msgstr "E437: ็ซฏๆซใซ \"cm\" ๆฉ่ฝใๅฟ
่ฆใงใ" #. Highlight title -#: ../term.c:4376 msgid "" "\n" "--- Terminal keys ---" @@ -6125,168 +5691,347 @@ msgstr "" "\n" "--- ็ซฏๆซใญใผ ---" -#: ../ui.c:481 +msgid "Cannot open $VIMRUNTIME/rgb.txt" +msgstr "$VIMRUNTIME/rgb.txtใ้ใใพใใ" + +msgid "new shell started\n" +msgstr "ๆฐใใใทใงใซใ่ตทๅใใพใ\n" + msgid "Vim: Error reading input, exiting...\n" msgstr "Vim: ๅ
ฅๅใ่ชญ่พผใฟไธญใฎใจใฉใผใซใใ็ตไบใใพใ...\n" +msgid "Used CUT_BUFFER0 instead of empty selection" +msgstr "็ฉบใฎ้ธๆ้ ๅใฎใใใใซCUT_BUFFER0ใไฝฟ็จใใใพใใ" + #. This happens when the FileChangedRO autocommand changes the #. * file in a way it becomes shorter. -#: ../undo.c:379 msgid "E881: Line count changed unexpectedly" msgstr "E881: ไบๆใใ่กใซใฆใณใใๅคใใใพใใ" -#: ../undo.c:627 +#. must display the prompt +msgid "No undo possible; continue anyway" +msgstr "ๅฏ่ฝใชใขใณใใฅใฏใใใพใใ: ใจใใใใ็ถใใพใ" + #, c-format msgid "E828: Cannot open undo file for writing: %s" msgstr "E828: ๆธ่พผใฟ็จใซใขใณใใฅใใกใคใซใ้ใใพใใ: %s" -#: ../undo.c:717 #, c-format msgid "E825: Corrupted undo file (%s): %s" msgstr "E825: ใขใณใใฅใใกใคใซใๅฃใใฆใใพใ (%s): %s" -#: ../undo.c:1039 msgid "Cannot write undo file in any directory in 'undodir'" msgstr "'undodir'ใฎใใฃใฌใฏใใชใซใขใณใใฅใใกใคใซใๆธใ่พผใใพใใ" -#: ../undo.c:1074 #, c-format msgid "Will not overwrite with undo file, cannot read: %s" msgstr "ใขใณใใฅใใกใคใซใจใใฆ่ชญใฟ่พผใใชใใฎใงไธๆธใใใพใใ: %s" -#: ../undo.c:1092 #, c-format msgid "Will not overwrite, this is not an undo file: %s" msgstr "ใขใณใใฅใใกใคใซใงใฏใชใใฎใงไธๆธใใใพใใ: %s" -#: ../undo.c:1108 msgid "Skipping undo file write, nothing to undo" msgstr "ๅฏพ่ฑกใใชใใฎใงใขใณใใฅใใกใคใซใฎๆธใ่พผใฟใในใญใใใใพใ" -#: ../undo.c:1121 #, c-format msgid "Writing undo file: %s" msgstr "ใขใณใใฅใใกใคใซๆธใ่พผใฟไธญ: %s" -#: ../undo.c:1213 #, c-format msgid "E829: write error in undo file: %s" msgstr "E829: ใขใณใใฅใใกใคใซใฎๆธใ่พผใฟใจใฉใผใงใ: %s" -#: ../undo.c:1280 #, c-format msgid "Not reading undo file, owner differs: %s" msgstr "ใชใผใใผใ็ฐใชใใฎใงใขใณใใฅใใกใคใซใ่ชญใฟ่พผใฟใพใใ: %s" -#: ../undo.c:1292 #, c-format msgid "Reading undo file: %s" msgstr "ใขใณใใฅใใกใคใซ่ชญ่พผไธญ: %s" -#: ../undo.c:1299 #, c-format msgid "E822: Cannot open undo file for reading: %s" msgstr "E822: ใขใณใใฅใใกใคใซใ่ชญ่พผ็จใจใใฆ้ใใพใใ: %s" -#: ../undo.c:1308 #, c-format msgid "E823: Not an undo file: %s" msgstr "E823: ใขใณใใฅใใกใคใซใงใฏใใใพใใ: %s" -#: ../undo.c:1313 +#, c-format +msgid "E832: Non-encrypted file has encrypted undo file: %s" +msgstr "E832: ้ๆๅทๅใใกใคใซใๆๅทๅใใใใขใณใใฅใใกใคใซใไฝฟใฃใฆใพใ: %s" + +#, c-format +msgid "E826: Undo file decryption failed: %s" +msgstr "E826: ๆๅทๅใใใใขใณใใฅใใกใคใซใฎ่งฃ่ชญใซๅคฑๆใใพใใ: %s" + +#, c-format +msgid "E827: Undo file is encrypted: %s" +msgstr "E827: ใขใณใใฅใใกใคใซใๆๅทๅใใใฆใใพใ: %s" + #, c-format msgid "E824: Incompatible undo file: %s" msgstr "E824: ไบๆๆงใฎ็กใใขใณใใฅใใกใคใซใงใ: %s" -#: ../undo.c:1328 msgid "File contents changed, cannot use undo info" msgstr "ใใกใคใซใฎๅ
ๅฎนใๅคใใฃใฆใใใใใใขใณใใฅๆ
ๅ ฑใๅฉ็จใงใใพใใ" -#: ../undo.c:1497 #, c-format msgid "Finished reading undo file %s" msgstr "ใขใณใใฅใใกใคใซ %s ใฎๅ่พผใๅฎไบ" -#: ../undo.c:1586 ../undo.c:1812 msgid "Already at oldest change" msgstr "ๆขใซไธ็ชๅคใๅคๆดใงใ" -#: ../undo.c:1597 ../undo.c:1814 msgid "Already at newest change" msgstr "ๆขใซไธ็ชๆฐใใๅคๆดใงใ" -#: ../undo.c:1806 #, c-format -msgid "E830: Undo number %<PRId64> not found" -msgstr "E830: ใขใณใใฅ็ชๅท %<PRId64> ใฏ่ฆใคใใใพใใ" +msgid "E830: Undo number %ld not found" +msgstr "E830: ใขใณใใฅ็ชๅท %ld ใฏ่ฆใคใใใพใใ" -#: ../undo.c:1979 msgid "E438: u_undo: line numbers wrong" msgstr "E438: u_undo: ่ก็ชๅทใ้้ใฃใฆใใพใ" -#: ../undo.c:2183 msgid "more line" msgstr "่ก ่ฟฝๅ ใใพใใ" -#: ../undo.c:2185 msgid "more lines" msgstr "่ก ่ฟฝๅ ใใพใใ" -#: ../undo.c:2187 msgid "line less" msgstr "่ก ๅ้คใใพใใ" -#: ../undo.c:2189 msgid "fewer lines" msgstr "่ก ๅ้คใใพใใ" -#: ../undo.c:2193 msgid "change" msgstr "็ฎๆๅคๆดใใพใใ" -#: ../undo.c:2195 msgid "changes" msgstr "็ฎๆๅคๆดใใพใใ" -#: ../undo.c:2225 #, c-format -msgid "%<PRId64> %s; %s #%<PRId64> %s" -msgstr "%<PRId64> %s; %s #%<PRId64> %s" +msgid "%ld %s; %s #%ld %s" +msgstr "%ld %s; %s #%ld %s" -#: ../undo.c:2228 msgid "before" msgstr "ๅๆน" -#: ../undo.c:2228 msgid "after" msgstr "ๅพๆน" -#: ../undo.c:2325 msgid "Nothing to undo" msgstr "ใขใณใใฅๅฏพ่ฑกใใใใพใใ" -#: ../undo.c:2330 msgid "number changes when saved" msgstr "้็ช ๅคๆดๆฐ ๅคๆดๆๆ ไฟๅญๆธ" -#: ../undo.c:2360 #, c-format -msgid "%<PRId64> seconds ago" -msgstr "%<PRId64> ็ง็ต้ใใฆใใพใ" +msgid "%ld seconds ago" +msgstr "%ld ็ง็ต้ใใฆใใพใ" -#: ../undo.c:2372 msgid "E790: undojoin is not allowed after undo" msgstr "E790: undo ใฎ็ดๅพใซ undojoin ใฏใงใใพใใ" -#: ../undo.c:2466 msgid "E439: undo list corrupt" msgstr "E439: ใขใณใใฅใชในใใๅฃใใฆใใพใ" -#: ../undo.c:2495 msgid "E440: undo line missing" msgstr "E440: ใขใณใใฅ่กใใใใพใใ" -#: ../version.c:600 +#, c-format +msgid "E122: Function %s already exists, add ! to replace it" +msgstr "E122: ้ขๆฐ %s ใฏๅฎ็พฉๆธใงใ, ๅๅฎ็พฉใใใซใฏ ! ใ่ฟฝๅ ใใฆใใ ใใ" + +msgid "E717: Dictionary entry already exists" +msgstr "E717: ่พๆธๅๅ
ใซใจใณใใชใๆขใซๅญๅจใใพใ" + +msgid "E718: Funcref required" +msgstr "E718: ้ขๆฐๅ็
งๅใ่ฆๆฑใใใพใ" + +#, c-format +msgid "E130: Unknown function: %s" +msgstr "E130: ๆช็ฅใฎ้ขๆฐใงใ: %s" + +#, c-format +msgid "E125: Illegal argument: %s" +msgstr "E125: ไธๆญฃใชๅผๆฐใงใ: %s" + +#, c-format +msgid "E853: Duplicate argument name: %s" +msgstr "E853: ๅผๆฐๅใ้่คใใฆใใพใ: %s" + +#, c-format +msgid "E740: Too many arguments for function %s" +msgstr "E740: ้ขๆฐใฎๅผๆฐใๅค้ใใพใ: %s" + +#, c-format +msgid "E116: Invalid arguments for function %s" +msgstr "E116: ้ขๆฐใฎ็กๅนใชๅผๆฐใงใ: %s" + +msgid "E132: Function call depth is higher than 'maxfuncdepth'" +msgstr "E132: ้ขๆฐๅผๅบใฎๅ
ฅใๅญๆฐใ 'maxfuncdepth' ใ่ถ
ใใพใใ" + +#, c-format +msgid "calling %s" +msgstr "%s ใๅฎ่กไธญใงใ" + +#, c-format +msgid "%s aborted" +msgstr "%s ใไธญๆญใใใพใใ" + +#, c-format +msgid "%s returning #%ld" +msgstr "%s ใ #%ld ใ่ฟใใพใใ" + +#, c-format +msgid "%s returning %s" +msgstr "%s ใ %s ใ่ฟใใพใใ" + +msgid "E699: Too many arguments" +msgstr "E699: ๅผๆฐใๅค้ใใพใ" + +#, c-format +msgid "E117: Unknown function: %s" +msgstr "E117: ๆช็ฅใฎ้ขๆฐใงใ: %s" + +#, c-format +msgid "E933: Function was deleted: %s" +msgstr "E933: ้ขๆฐใฏๅ้คใใใพใใ: %s" + +#, c-format +msgid "E119: Not enough arguments for function: %s" +msgstr "E119: ้ขๆฐใฎๅผๆฐใ่ถณใใพใใ: %s" + +#, c-format +msgid "E120: Using <SID> not in a script context: %s" +msgstr "E120: ในใฏใชใใไปฅๅคใง<SID>ใไฝฟใใใพใใ: %s" + +#, c-format +msgid "E725: Calling dict function without Dictionary: %s" +msgstr "E725: ่พๆธ็จ้ขๆฐใๅผใฐใใพใใใ่พๆธใใใใพใใ: %s" + +msgid "E129: Function name required" +msgstr "E129: ้ขๆฐๅใ่ฆๆฑใใใพใ" + +#, c-format +msgid "E128: Function name must start with a capital or \"s:\": %s" +msgstr "E128: ้ขๆฐๅใฏๅคงๆๅญใ \"s:\" ใงๅงใพใใชใใใฐใชใใพใใ: %s" + +#, c-format +msgid "E884: Function name cannot contain a colon: %s" +msgstr "E884: ้ขๆฐๅใซใฏใณใญใณใฏๅซใใใใพใใ: %s" + +#, c-format +msgid "E123: Undefined function: %s" +msgstr "E123: ๆชๅฎ็พฉใฎ้ขๆฐใงใ: %s" + +#, c-format +msgid "E124: Missing '(': %s" +msgstr "E124: '(' ใใใใพใใ: %s" + +msgid "E862: Cannot use g: here" +msgstr "E862: ใใใงใฏ g: ใฏไฝฟใใพใใ" + +#, c-format +msgid "E932: Closure function should not be at top level: %s" +msgstr "E932: ใฏใญใผใธใฃใผ้ขๆฐใฏใใใใฌใใซใซ่จ่ฟฐใงใใพใใ: %s" + +msgid "E126: Missing :endfunction" +msgstr "E126: :endfunction ใใใใพใใ" + +#, c-format +msgid "E707: Function name conflicts with variable: %s" +msgstr "E707: ้ขๆฐๅใๅคๆฐๅใจ่ก็ชใใพใ: %s" + +#, c-format +msgid "E127: Cannot redefine function %s: It is in use" +msgstr "E127: ้ขๆฐ %s ใๅๅฎ็พฉใงใใพใใ: ไฝฟ็จไธญใงใ" + +#, c-format +msgid "E746: Function name does not match script file name: %s" +msgstr "E746: ้ขๆฐๅใในใฏใชใใใฎใใกใคใซๅใจไธ่ดใใพใใ: %s" + +#, c-format +msgid "E131: Cannot delete function %s: It is in use" +msgstr "E131: ้ขๆฐ %s ใๅ้คใงใใพใใ: ไฝฟ็จไธญใงใ" + +msgid "E133: :return not inside a function" +msgstr "E133: ้ขๆฐๅคใซ :return ใใใใพใใ" + +#, c-format +msgid "E107: Missing parentheses: %s" +msgstr "E107: ใซใใณ '(' ใใใใพใใ: %s" + +#. Only MS VC 4.1 and earlier can do Win32s +msgid "" +"\n" +"MS-Windows 16/32-bit GUI version" +msgstr "" +"\n" +"MS-Windows 16/32 ใใใ GUI ็" + +msgid "" +"\n" +"MS-Windows 64-bit GUI version" +msgstr "" +"\n" +"MS-Windows 64 ใใใ GUI ็" + +msgid "" +"\n" +"MS-Windows 32-bit GUI version" +msgstr "" +"\n" +"MS-Windows 32 ใใใ GUI ็" + +msgid " with OLE support" +msgstr " with OLE ใตใใผใ" + +msgid "" +"\n" +"MS-Windows 64-bit console version" +msgstr "" +"\n" +"MS-Windows 64 ใใใ ใณใณใฝใผใซ ็" + +msgid "" +"\n" +"MS-Windows 32-bit console version" +msgstr "" +"\n" +"MS-Windows 32 ใใใ ใณใณใฝใผใซ ็" + +msgid "" +"\n" +"MacOS X (unix) version" +msgstr "" +"\n" +"MacOS X (unix) ็" + +msgid "" +"\n" +"MacOS X version" +msgstr "" +"\n" +"MacOS X ็" + +msgid "" +"\n" +"MacOS version" +msgstr "" +"\n" +"MacOS ็" + +msgid "" +"\n" +"OpenVMS version" +msgstr "" +"\n" +"OpenVMS ็" + msgid "" "\n" "Included patches: " @@ -6294,7 +6039,6 @@ msgstr "" "\n" "้ฉ็จๆธใใใ: " -#: ../version.c:627 msgid "" "\n" "Extra patches: " @@ -6302,11 +6046,9 @@ msgstr "" "\n" "่ฟฝๅ ๆกๅผตใใใ: " -#: ../version.c:639 ../version.c:864 msgid "Modified by " msgstr "Modified by " -#: ../version.c:646 msgid "" "\n" "Compiled " @@ -6314,11 +6056,9 @@ msgstr "" "\n" "Compiled " -#: ../version.c:649 msgid "by " msgstr "by " -#: ../version.c:660 msgid "" "\n" "Huge version " @@ -6326,1886 +6066,926 @@ msgstr "" "\n" "Huge ็ " -#: ../version.c:661 +msgid "" +"\n" +"Big version " +msgstr "" +"\n" +"Big ็ " + +msgid "" +"\n" +"Normal version " +msgstr "" +"\n" +"้ๅธธ ็ " + +msgid "" +"\n" +"Small version " +msgstr "" +"\n" +"Small ็ " + +msgid "" +"\n" +"Tiny version " +msgstr "" +"\n" +"Tiny ็ " + msgid "without GUI." msgstr "without GUI." -#: ../version.c:662 +msgid "with GTK3 GUI." +msgstr "with GTK3 GUI." + +msgid "with GTK2-GNOME GUI." +msgstr "with GTK2-GNOME GUI." + +msgid "with GTK2 GUI." +msgstr "with GTK2 GUI." + +msgid "with X11-Motif GUI." +msgstr "with X11-Motif GUI." + +msgid "with X11-neXtaw GUI." +msgstr "with X11-neXtaw GUI." + +msgid "with X11-Athena GUI." +msgstr "with X11-Athena GUI." + +msgid "with Photon GUI." +msgstr "with Photon GUI." + +msgid "with GUI." +msgstr "with GUI." + +msgid "with Carbon GUI." +msgstr "with Carbon GUI." + +msgid "with Cocoa GUI." +msgstr "with Cocoa GUI." + +msgid "with (classic) GUI." +msgstr "with (ใฏใฉใทใใฏ) GUI." + msgid " Features included (+) or not (-):\n" msgstr " ๆฉ่ฝใฎไธ่ฆง ๆๅน(+)/็กๅน(-)\n" -#: ../version.c:667 msgid " system vimrc file: \"" msgstr " ใทในใใ vimrc: \"" -#: ../version.c:672 msgid " user vimrc file: \"" msgstr " ใฆใผใถใผ vimrc: \"" -#: ../version.c:677 msgid " 2nd user vimrc file: \"" msgstr " ็ฌฌ2ใฆใผใถใผ vimrc: \"" -#: ../version.c:682 msgid " 3rd user vimrc file: \"" msgstr " ็ฌฌ3ใฆใผใถใผ vimrc: \"" -#: ../version.c:687 msgid " user exrc file: \"" msgstr " ใฆใผใถใผ exrc: \"" -#: ../version.c:692 msgid " 2nd user exrc file: \"" msgstr " ็ฌฌ2ใฆใผใถใผ exrc: \"" -#: ../version.c:699 +msgid " system gvimrc file: \"" +msgstr " ใทในใใ gvimrc: \"" + +msgid " user gvimrc file: \"" +msgstr " ใฆใผใถใผ gvimrc: \"" + +msgid "2nd user gvimrc file: \"" +msgstr " ็ฌฌ2ใฆใผใถใผ gvimrc: \"" + +msgid "3rd user gvimrc file: \"" +msgstr " ็ฌฌ3ใฆใผใถใผ gvimrc: \"" + +msgid " defaults file: \"" +msgstr " ใใใฉใซใใใกใคใซ: \"" + +msgid " system menu file: \"" +msgstr " ใทในใใ ใกใใฅใผ: \"" + msgid " fall-back for $VIM: \"" msgstr " ็็ฅๆใฎ $VIM: \"" -#: ../version.c:705 msgid " f-b for $VIMRUNTIME: \"" msgstr "็็ฅๆใฎ $VIMRUNTIME: \"" -#: ../version.c:709 msgid "Compilation: " msgstr "ใณใณใใคใซ: " -#: ../version.c:712 +msgid "Compiler: " +msgstr "ใณใณใใคใฉ: " + msgid "Linking: " msgstr "ใชใณใฏ: " -#: ../version.c:717 msgid " DEBUG BUILD" msgstr "ใใใใฐใใซใ" -#: ../version.c:767 msgid "VIM - Vi IMproved" msgstr "VIM - Vi IMproved" -#: ../version.c:769 msgid "version " msgstr "version " -#: ../version.c:770 msgid "by Bram Moolenaar et al." msgstr "by Bram Moolenaar ไป." -#: ../version.c:774 msgid "Vim is open source and freely distributable" msgstr "Vim ใฏใชใผใใณใฝใผในใงใใ่ช็ฑใซ้
ๅธๅฏ่ฝใงใ" -#: ../version.c:776 msgid "Help poor children in Uganda!" msgstr "ใฆใฌใณใใฎๆตใพใใชใๅญไพใใกใซๆดๅฉใ!" -#: ../version.c:777 msgid "type :help iccf<Enter> for information " msgstr "่ฉณ็ดฐใชๆ
ๅ ฑใฏ :help iccf<Enter> " -#: ../version.c:779 msgid "type :q<Enter> to exit " msgstr "็ตไบใใใซใฏ :q<Enter> " -#: ../version.c:780 msgid "type :help<Enter> or <F1> for on-line help" msgstr "ใชใณใฉใคใณใใซใใฏ :help<Enter> ใ <F1> " -#: ../version.c:781 -msgid "type :help version7<Enter> for version info" -msgstr "ใใผใธใงใณๆ
ๅ ฑใฏ :help version7<Enter> " +msgid "type :help version8<Enter> for version info" +msgstr "ใใผใธใงใณๆ
ๅ ฑใฏ :help version8<Enter> " -#: ../version.c:784 msgid "Running in Vi compatible mode" msgstr "Viไบๆใขใผใใงๅไฝไธญ" -#: ../version.c:785 msgid "type :set nocp<Enter> for Vim defaults" msgstr "Vimๆจๅฅจๅคใซใใใซใฏ :set nocp<Enter> " -#: ../version.c:786 msgid "type :help cp-default<Enter> for info on this" msgstr "่ฉณ็ดฐใชๆ
ๅ ฑใฏ :help cp-default<Enter>" -#: ../version.c:827 +msgid "menu Help->Orphans for information " +msgstr "่ฉณ็ดฐใฏใกใใฅใผใฎ ใใซใ->ๅญคๅ
ใๅ็
งใใฆไธใใ " + +msgid "Running modeless, typed text is inserted" +msgstr "ใขใผใ็กใงๅฎ่กไธญ, ใฟใคใใใๆๅญใๆฟๅ
ฅใใใพใ" + +msgid "menu Edit->Global Settings->Toggle Insert Mode " +msgstr "ใกใใฅใผใฎ ็ทจ้->ๅ
จไฝ่จญๅฎ->ๆฟๅ
ฅ(ๅๅฟ่
)ใขใผใๅๆฟ " + +msgid " for two modes " +msgstr " ใงใขใผใๆใซ " + +msgid "menu Edit->Global Settings->Toggle Vi Compatible" +msgstr "ใกใใฅใผใฎ ็ทจ้->ๅ
จไฝ่จญๅฎ->Viไบๆใขใผใๅๆฟ " + +msgid " for Vim defaults " +msgstr " ใงVimใจใใฆๅไฝ " + msgid "Sponsor Vim development!" msgstr "Vimใฎ้็บใๅฟๆดใใฆใใ ใใ!" -#: ../version.c:828 msgid "Become a registered Vim user!" msgstr "Vimใฎ็ป้ฒใฆใผใถใผใซใชใฃใฆใใ ใใ!" -#: ../version.c:831 msgid "type :help sponsor<Enter> for information " msgstr "่ฉณ็ดฐใชๆ
ๅ ฑใฏ :help sponsor<Enter> " -#: ../version.c:832 msgid "type :help register<Enter> for information " msgstr "่ฉณ็ดฐใชๆ
ๅ ฑใฏ :help register<Enter> " -#: ../version.c:834 msgid "menu Help->Sponsor/Register for information " msgstr "่ฉณ็ดฐใฏใกใใฅใผใฎ ใใซใ->ในใใณใตใผ/็ป้ฒ ใๅ็
งใใฆไธใใ" -#: ../window.c:119 +msgid "WARNING: Windows 95/98/ME detected" +msgstr "่ญฆๅ: Windows 95/98/ME ใๆคๅบใใพใใ" + +msgid "type :help windows95<Enter> for info on this" +msgstr "่ฉณ็ดฐใชๆ
ๅ ฑใฏ :help windows95<Enter>" + msgid "Already only one window" msgstr "ๆขใซใฆใฃใณใใฆใฏ1ใคใใใใใพใใ" -#: ../window.c:224 msgid "E441: There is no preview window" msgstr "E441: ใใฌใใฅใผใฆใฃใณใใฆใใใใพใใ" -#: ../window.c:559 msgid "E442: Can't split topleft and botright at the same time" msgstr "E442: ๅทฆไธใจๅณไธใๅๆใซๅๅฒใใใใจใฏใงใใพใใ" -#: ../window.c:1228 msgid "E443: Cannot rotate when another window is split" msgstr "E443: ไปใฎใฆใฃใณใใฆใๅๅฒใใใฆใใๆใซใฏ้ ๅใงใใพใใ" -#: ../window.c:1803 msgid "E444: Cannot close last window" msgstr "E444: ๆๅพใฎใฆใฃใณใใฆใ้ใใใใจใฏใงใใพใใ" -#: ../window.c:1810 msgid "E813: Cannot close autocmd window" msgstr "E813: autocmdใฆใฃใณใใฆใฏ้ใใใใพใใ" -#: ../window.c:1814 msgid "E814: Cannot close window, only autocmd window would remain" msgstr "E814: autocmdใฆใฃใณใใฆใใๆฎใใชใใใใใฆใฃใณใใฆใฏ้ใใใใพใใ" -#: ../window.c:2717 msgid "E445: Other window contains changes" msgstr "E445: ไปใฎใฆใฃใณใใฆใซใฏๅคๆดใใใใพใ" -#: ../window.c:4805 msgid "E446: No file name under cursor" msgstr "E446: ใซใผใฝใซใฎไธใซใใกใคใซๅใใใใพใใ" -msgid "List or number required" -msgstr "ใชในใใๆฐๅคใๅฟ
่ฆใงใ" - -#~ msgid "E831: bf_key_init() called with empty password" -#~ msgstr "E831: bf_key_init() ใ็ฉบใในใฏใผใใงๅผใณๅบใใใพใใ" - -#~ msgid "E820: sizeof(uint32_t) != 4" -#~ msgstr "E820: sizeof(uint32_t) != 4" - -#~ msgid "E817: Blowfish big/little endian use wrong" -#~ msgstr "E817: Blowfishๆๅทใฎใใใฐ/ใชใใซใจใณใใฃใขใณใ้้ใฃใฆใใพใ" - -#~ msgid "E818: sha256 test failed" -#~ msgstr "E818: sha256ใฎใในใใซๅคฑๆใใพใใ" - -#~ msgid "E819: Blowfish test failed" -#~ msgstr "E819: Blowfishๆๅทใฎใในใใซๅคฑๆใใพใใ" - -#~ msgid "Patch file" -#~ msgstr "ใใใใใกใคใซ" - -#~ msgid "" -#~ "&OK\n" -#~ "&Cancel" -#~ msgstr "" -#~ "ๆฑบๅฎ(&O)\n" -#~ "ใญใฃใณใปใซ(&C)" - -#~ msgid "E240: No connection to Vim server" -#~ msgstr "E240: Vim ใตใผใใธใฎๆฅ็ถใใใใพใใ" - -#~ msgid "E241: Unable to send to %s" -#~ msgstr "E241: %s ใธ้ใใใจใใงใใพใใ" - -#~ msgid "E277: Unable to read a server reply" -#~ msgstr "E277: ใตใผใใฎๅฟ็ญใใใใพใใ" - -#~ msgid "E258: Unable to send to client" -#~ msgstr "E258: ใฏใฉใคใขใณใใธ้ใใใจใใงใใพใใ" - -#~ msgid "Save As" -#~ msgstr "ๅฅๅใงไฟๅญ" - -#~ msgid "Edit File" -#~ msgstr "ใใกใคใซใ็ทจ้" - -# Added at 27-Jan-2004. -#~ msgid " (NOT FOUND)" -#~ msgstr " (่ฆใคใใใพใใ)" - -#~ msgid "Source Vim script" -#~ msgstr "Vimในใฏใชใใใฎๅ่พผใฟ" - -#~ msgid "unknown" -#~ msgstr "ไธๆ" - -#~ msgid "Edit File in new window" -#~ msgstr "ๆฐใใใฆใฃใณใใฆใงใใกใคใซใ็ทจ้ใใพใ" - -#~ msgid "Append File" -#~ msgstr "่ฟฝๅ ใใกใคใซ" - -#~ msgid "Window position: X %d, Y %d" -#~ msgstr "ใฆใฃใณใใฆไฝ็ฝฎ: X %d, Y %d" - -#~ msgid "Save Redirection" -#~ msgstr "ใชใใคใฌใฏใใไฟๅญใใพใ" - -#~ msgid "Save View" -#~ msgstr "ใใฅใผใไฟๅญใใพใ" - -#~ msgid "Save Session" -#~ msgstr "ใปใใทใงใณๆ
ๅ ฑใไฟๅญใใพใ" - -#~ msgid "Save Setup" -#~ msgstr "่จญๅฎใไฟๅญใใพใ" - -#~ msgid "E809: #< is not available without the +eval feature" -#~ msgstr "E809: #< ใฏ +eval ๆฉ่ฝใ็กใใจๅฉ็จใงใใพใใ" - -#~ msgid "E196: No digraphs in this version" -#~ msgstr "E196: ใใฎใใผใธใงใณใซๅๅญใฏใใใพใใ" - -#~ msgid "is a device (disabled with 'opendevice' option)" -#~ msgstr " ใฏใใใคในใงใ ('opendevice' ใชใใทใงใณใงๅ้ฟใงใใพใ)" - -#~ msgid "Reading from stdin..." -#~ msgstr "ๆจๆบๅ
ฅๅใใ่ชญ่พผใฟไธญ..." - -#~ msgid "[blowfish]" -#~ msgstr "[blowfishๆๅทๅ]" - -#~ msgid "[crypted]" -#~ msgstr "[ๆๅทๅ]" - -#~ msgid "E821: File is encrypted with unknown method" -#~ msgstr "E821: ใใกใคใซใๆช็ฅใฎๆนๆณใงๆๅทๅใใใฆใใพใ" - -# Added at 19-Jan-2004. -#~ msgid "NetBeans disallows writes of unmodified buffers" -#~ msgstr "NetBeansใฏๆชๅคๆดใฎใใใใกใไธๆธใใใใจใฏ่จฑๅฏใใฆใใพใใ" - -#~ msgid "Partial writes disallowed for NetBeans buffers" -#~ msgstr "NetBeansใใใใกใฎไธ้จใๆธใๅบใใใจใฏใงใใพใใ" - -#~ msgid "writing to device disabled with 'opendevice' option" -#~ msgstr "'opendevice' ใชใใทใงใณใซใใใใใคในใธใฎๆธใ่พผใฟใฏใงใใพใใ" - -#~ msgid "E460: The resource fork would be lost (add ! to override)" -#~ msgstr "E460: ใชใฝใผในใใฉใผใฏใๅคฑใใใใใใใใพใใ (! ใ่ฟฝๅ ใงๅผทๅถ)" - -#~ msgid "E851: Failed to create a new process for the GUI" -#~ msgstr "E851: GUI็จใฎใใญใปในใฎ่ตทๅใซๅคฑๆใใพใใ" - -#~ msgid "E852: The child process failed to start the GUI" -#~ msgstr "E852: ๅญใใญใปในใGUIใฎ่ตทๅใซๅคฑๆใใพใใ" - -#~ msgid "E229: Cannot start the GUI" -#~ msgstr "E229: GUIใ้ๅงใงใใพใใ" - -#~ msgid "E230: Cannot read from \"%s\"" -#~ msgstr "E230: \"%s\"ใใ่ชญ่พผใใใจใใงใใพใใ" - -#~ msgid "E665: Cannot start GUI, no valid font found" -#~ msgstr "E665: ๆๅนใชใใฉใณใใ่ฆใคใใใชใใฎใง, GUIใ้ๅงใงใใพใใ" - -#~ msgid "E231: 'guifontwide' invalid" -#~ msgstr "E231: 'guifontwide' ใ็กๅนใงใ" - -#~ msgid "E599: Value of 'imactivatekey' is invalid" -#~ msgstr "E599: 'imactivatekey' ใซ่จญๅฎใใใๅคใ็กๅนใงใ" - -#~ msgid "E254: Cannot allocate color %s" -#~ msgstr "E254: %s ใฎ่ฒใๅฒใๅฝใฆใใใพใใ" - -#~ msgid "No match at cursor, finding next" -#~ msgstr "ใซใผใฝใซใฎไฝ็ฝฎใซใใใใฏใใใพใใ, ๆฌกใๆค็ดขใใฆใใพใ" - -#~ msgid "<cannot open> " -#~ msgstr "<้ใใพใใ> " - -#~ msgid "E616: vim_SelFile: can't get font %s" -#~ msgstr "E616: vim_SelFile: ใใฉใณใ %s ใๅๅพใงใใพใใ" - -#~ msgid "E614: vim_SelFile: can't return to current directory" -#~ msgstr "E614: vim_SelFile: ็พๅจใฎใใฃใฌใฏใใชใซๆปใใพใใ" - -#~ msgid "Pathname:" -#~ msgstr "ใในๅ:" - -#~ msgid "E615: vim_SelFile: can't get current directory" -#~ msgstr "E615: vim_SelFile: ็พๅจใฎใใฃใฌใฏใใชใๅๅพใงใใพใใ" - -#~ msgid "OK" -#~ msgstr "OK" - -#~ msgid "Cancel" -#~ msgstr "ใญใฃใณใปใซ" - -#~ msgid "Scrollbar Widget: Could not get geometry of thumb pixmap." -#~ msgstr "ในใฏใญใผใซใใผ: ็ปๅใๅๅพใงใใพใใใงใใ." - -#~ msgid "Vim dialog" -#~ msgstr "Vim ใใคใขใญใฐ" - -#~ msgid "E232: Cannot create BalloonEval with both message and callback" -#~ msgstr "E232: ใกใใปใผใธใจใณใผใซใใใฏใฎใใ BalloonEval ใไฝๆใงใใพใใ" - -#~ msgid "Input _Methods" -#~ msgstr "ใคใณใใใใกใฝใใ" - -#~ msgid "VIM - Search and Replace..." -#~ msgstr "VIM - ๆค็ดขใจ็ฝฎๆ..." - -#~ msgid "VIM - Search..." -#~ msgstr "VIM - ๆค็ดข..." - -#~ msgid "Find what:" -#~ msgstr "ๆค็ดขๆๅญๅ:" - -#~ msgid "Replace with:" -#~ msgstr "็ฝฎๆๆๅญๅ:" - -#~ msgid "Match whole word only" -#~ msgstr "ๆญฃ็ขบใซ่ฉฒๅฝใใใใฎใ ใ" - -#~ msgid "Match case" -#~ msgstr "ๅคงๆๅญ/ๅฐๆๅญใๅบๅฅใใ" - -#~ msgid "Direction" -#~ msgstr "ๆนๅ" - -#~ msgid "Up" -#~ msgstr "ไธ" - -#~ msgid "Down" -#~ msgstr "ไธ" - -#~ msgid "Find Next" -#~ msgstr "ๆฌกใๆค็ดข" - -#~ msgid "Replace" -#~ msgstr "็ฝฎๆ" - -#~ msgid "Replace All" -#~ msgstr "ๅ
จใฆ็ฝฎๆ" - -#~ msgid "Vim: Received \"die\" request from session manager\n" -#~ msgstr "Vim: ใปใใทใงใณใใใผใธใฃใใ \"die\" ่ฆๆฑใๅใๅใใพใใ\n" - -#~ msgid "Close" -#~ msgstr "้ใใ" - -#~ msgid "New tab" -#~ msgstr "ๆฐ่ฆใฟใใใผใธ" - -#~ msgid "Open Tab..." -#~ msgstr "ใฟใใใผใธใ้ใ..." - -#~ msgid "Vim: Main window unexpectedly destroyed\n" -#~ msgstr "Vim: ใกใคใณใฆใฃใณใใฆใไธๆใซ็ ดๅฃใใใพใใ\n" - -#~ msgid "&Filter" -#~ msgstr "ใใฃใซใฟ(&F)" - -#~ msgid "&Cancel" -#~ msgstr "ใญใฃใณใปใซ(&C)" - -#~ msgid "Directories" -#~ msgstr "ใใฃใฌใฏใใช" - -#~ msgid "Filter" -#~ msgstr "ใใฃใซใฟ" - -#~ msgid "&Help" -#~ msgstr "ใใซใ(&H)" - -#~ msgid "Files" -#~ msgstr "ใใกใคใซ" - -#~ msgid "&OK" -#~ msgstr "&OK" - -#~ msgid "Selection" -#~ msgstr "้ธๆ" - -#~ msgid "Find &Next" -#~ msgstr "ๆฌกใๆค็ดข(&N)" - -#~ msgid "&Replace" -#~ msgstr "็ฝฎๆ(&R)" - -#~ msgid "Replace &All" -#~ msgstr "ๅ
จใฆ็ฝฎๆ(&A)" - -#~ msgid "&Undo" -#~ msgstr "ใขใณใใฅ(&U)" - -#~ msgid "E671: Cannot find window title \"%s\"" -#~ msgstr "E671: ใฟใคใใซใ \"%s\" ใฎใฆใฃใณใใฆใฏ่ฆใคใใใพใใ" - -#~ msgid "E243: Argument not supported: \"-%s\"; Use the OLE version." -#~ msgstr "E243: ๅผๆฐใฏใตใใผใใใใพใใ: \"-%s\"; OLE็ใไฝฟ็จใใฆใใ ใใ." - -#~ msgid "E672: Unable to open window inside MDI application" -#~ msgstr "E672: MDIใขใใชใฎไธญใงใฏใฆใฃใณใใฆใ้ใใพใใ" - -#~ msgid "Close tab" -#~ msgstr "ใฟใใใผใธใ้ใใ" - -#~ msgid "Open tab..." -#~ msgstr "ใฟใใใผใธใ้ใ" - -#~ msgid "Find string (use '\\\\' to find a '\\')" -#~ msgstr "ๆค็ดขๆๅญๅ ('\\' ใๆค็ดขใใใซใฏ '\\\\')" - -#~ msgid "Find & Replace (use '\\\\' to find a '\\')" -#~ msgstr "ๆค็ดขใป็ฝฎๆ ('\\' ใๆค็ดขใใใซใฏ '\\\\')" - -#~ msgid "Not Used" -#~ msgstr "ไฝฟใใใพใใ" - -#~ msgid "Directory\t*.nothing\n" -#~ msgstr "ใใฃใฌใฏใใช\t*.nothing\n" - -#~ msgid "" -#~ "Vim E458: Cannot allocate colormap entry, some colors may be incorrect" -#~ msgstr "Vim E458: ่ฒๆๅฎใๆญฃใใใชใใฎใงใจใณใใชใๅฒใๅฝใฆใใใพใใ" - -#~ msgid "E250: Fonts for the following charsets are missing in fontset %s:" -#~ msgstr "E250: ไปฅไธใฎๆๅญใปใใใฎใใฉใณใใใใใพใใ %s:" - -#~ msgid "E252: Fontset name: %s" -#~ msgstr "E252: ใใฉใณใใปใใๅ: %s" - -#~ msgid "Font '%s' is not fixed-width" -#~ msgstr "ใใฉใณใ '%s' ใฏๅบๅฎๅน
ใงใฏใใใพใใ" - -#~ msgid "E253: Fontset name: %s" -#~ msgstr "E253: ใใฉใณใใปใใๅ: %s" - -#~ msgid "Font0: %s" -#~ msgstr "ใใฉใณใ0: %s" - -#~ msgid "Font1: %s" -#~ msgstr "ใใฉใณใ1: %s" - -#~ msgid "Font%<PRId64> width is not twice that of font0" -#~ msgstr "ใใฉใณใ%<PRId64> ใฎๅน
ใใใฉใณใ0ใฎ2ๅใงใฏใใใพใใ" - -#~ msgid "Font0 width: %<PRId64>" -#~ msgstr "ใใฉใณใ0ใฎๅน
: %<PRId64>" - -#~ msgid "Font1 width: %<PRId64>" -#~ msgstr "ใใฉใณใ1ใฎๅน
: %<PRId64>" - -#~ msgid "Invalid font specification" -#~ msgstr "็กๅนใชใใฉใณใๆๅฎใงใ" - -#~ msgid "&Dismiss" -#~ msgstr "ๅดไธใใ(&D)" - -#~ msgid "no specific match" -#~ msgstr "ใใใใใใใฎใใใใพใใ" - -#~ msgid "Vim - Font Selector" -#~ msgstr "Vim - ใใฉใณใ้ธๆ" - -#~ msgid "Name:" -#~ msgstr "ๅๅ:" - -#~ msgid "Show size in Points" -#~ msgstr "ใตใคใบใใใคใณใใง่กจ็คบใใ" - -#~ msgid "Encoding:" -#~ msgstr "ใจใณใณใผใ:" - -#~ msgid "Font:" -#~ msgstr "ใใฉใณใ:" - -#~ msgid "Style:" -#~ msgstr "ในใฟใคใซ:" - -#~ msgid "Size:" -#~ msgstr "ใตใคใบ:" - -#~ msgid "E256: Hangul automata ERROR" -#~ msgstr "E256: ใใณใฐใซใชใผใใใใณใจใฉใผ" - -#~ msgid "E563: stat error" -#~ msgstr "E563: stat ใจใฉใผ" - -#~ msgid "E625: cannot open cscope database: %s" -#~ msgstr "E625: cscopeใใผใฟใใผใน: %s ใ้ใใใจใใงใใพใใ" - -#~ msgid "E626: cannot get cscope database information" -#~ msgstr "E626: cscopeใใผใฟใใผในใฎๆ
ๅ ฑใๅๅพใงใใพใใ" - -#~ msgid "Lua library cannot be loaded." -#~ msgstr "Luaใฉใคใใฉใชใใญใผใใงใใพใใ." - -#~ msgid "cannot save undo information" -#~ msgstr "ใขใณใใฅๆ
ๅ ฑใไฟๅญใงใใพใใ" - -#~ msgid "" -#~ "E815: Sorry, this command is disabled, the MzScheme libraries could not " -#~ "be loaded." -#~ msgstr "" -#~ "E815: ใใฎใณใใณใใฏ็กๅนใงใ. MzScheme ใฉใคใใฉใชใใญใผใใงใใพใใ." - -#~ msgid "invalid expression" -#~ msgstr "็กๅนใชๅผใงใ" - -#~ msgid "expressions disabled at compile time" -#~ msgstr "ๅผใฏใณใณใใคใซๆใซ็กๅนใซใใใฆใใพใ" - -#~ msgid "hidden option" -#~ msgstr "้ ใใชใใทใงใณ" - -#~ msgid "unknown option" -#~ msgstr "ๆช็ฅใฎใชใใทใงใณใงใ" - -#~ msgid "window index is out of range" -#~ msgstr "็ฏๅฒๅคใฎใฆใฃใณใใฆ็ชๅทใงใ" - -#~ msgid "couldn't open buffer" -#~ msgstr "ใใใใกใ้ใใพใใ" - -#~ msgid "cannot delete line" -#~ msgstr "่กใๆถใใพใใ" - -#~ msgid "cannot replace line" -#~ msgstr "่กใ็ฝฎๆใงใใพใใ" - -#~ msgid "cannot insert line" -#~ msgstr "่กใๆฟๅ
ฅใงใใพใใ" - -#~ msgid "string cannot contain newlines" -#~ msgstr "ๆๅญๅใซใฏๆน่กๆๅญใๅซใใใใพใใ" - -#~ msgid "error converting Scheme values to Vim" -#~ msgstr "SchemeๅคใฎVimใธใฎๅคๆใจใฉใผ" - -#~ msgid "Vim error: ~a" -#~ msgstr "Vim ใจใฉใผ: ~a" - -#~ msgid "Vim error" -#~ msgstr "Vim ใจใฉใผ" - -#~ msgid "buffer is invalid" -#~ msgstr "ใใใใกใฏ็กๅนใงใ" - -#~ msgid "window is invalid" -#~ msgstr "ใฆใฃใณใใฆใฏ็กๅนใงใ" - -#~ msgid "linenr out of range" -#~ msgstr "็ฏๅฒๅคใฎ่ก็ชๅทใงใ" - -#~ msgid "not allowed in the Vim sandbox" -#~ msgstr "ใตใณใใใใฏในใงใฏ่จฑใใใพใใ" - -#~ msgid "E370: Could not load library %s" -#~ msgstr "E370: ใฉใคใใฉใช %s ใใญใผใใงใใพใใใงใใ" - -#~ msgid "" -#~ "Sorry, this command is disabled: the Perl library could not be loaded." -#~ msgstr "" -#~ "ใใฎใณใใณใใฏ็กๅนใงใ, ใใใใชใใ: Perlใฉใคใใฉใชใใญใผใใงใใพใใใงใ" -#~ "ใ." - -#~ msgid "E299: Perl evaluation forbidden in sandbox without the Safe module" -#~ msgstr "" -#~ "E299: ใตใณใใใใฏในใงใฏ Safe ใขใธใฅใผใซใไฝฟ็จใใชใPerlในใฏใชใใใฏ็ฆใใ" -#~ "ใใฆใใพใ" - -#~ msgid "E836: This Vim cannot execute :python after using :py3" -#~ msgstr "E836: ใใฎVimใงใฏ :py3 ใไฝฟใฃใๅพใซ :python ใไฝฟใใพใใ" - -#~ msgid "" -#~ "E263: Sorry, this command is disabled, the Python library could not be " -#~ "loaded." -#~ msgstr "" -#~ "E263: ใใฎใณใใณใใฏ็กๅนใงใ,ใใใใชใใ: Pythonใฉใคใใฉใชใใญใผใใงใใพ" -#~ "ใใใงใใ." - -# Added at 07-Feb-2004. -#~ msgid "E659: Cannot invoke Python recursively" -#~ msgstr "E659: Python ใๅๅธฐ็ใซๅฎ่กใใใใจใฏใงใใพใใ" - -#~ msgid "E837: This Vim cannot execute :py3 after using :python" -#~ msgstr "E837: ใใฎVimใงใฏ :python ใไฝฟใฃใๅพใซ :py3 ใไฝฟใใพใใ" - -#~ msgid "E265: $_ must be an instance of String" -#~ msgstr "E265: $_ ใฏๆๅญๅใฎใคใณในใฟใณในใงใชใใใฐใชใใพใใ" - -#~ msgid "" -#~ "E266: Sorry, this command is disabled, the Ruby library could not be " -#~ "loaded." -#~ msgstr "" -#~ "E266: ใใฎใณใใณใใฏ็กๅนใงใ,ใใใใชใใ: Rubyใฉใคใใฉใชใใญใผใใงใใพใ" -#~ "ใใงใใ." - -#~ msgid "E267: unexpected return" -#~ msgstr "E267: ไบๆใใฌ return ใงใ" - -#~ msgid "E268: unexpected next" -#~ msgstr "E268: ไบๆใใฌ next ใงใ" - -#~ msgid "E269: unexpected break" -#~ msgstr "E269: ไบๆใใฌ break ใงใ" - -#~ msgid "E270: unexpected redo" -#~ msgstr "E270: ไบๆใใฌ redo ใงใ" - -#~ msgid "E271: retry outside of rescue clause" -#~ msgstr "E271: rescue ใฎๅคใฎ retry ใงใ" - -#~ msgid "E272: unhandled exception" -#~ msgstr "E272: ๅใๆฑใใใชใใฃใไพๅคใใใใพใ" - -#~ msgid "E273: unknown longjmp status %d" -#~ msgstr "E273: ๆช็ฅใฎlongjmp็ถๆ
: %d" - -#~ msgid "Toggle implementation/definition" -#~ msgstr "ๅฎ่ฃ
ใจๅฎ็พฉใๅใๆฟใใ" - -#~ msgid "Show base class of" -#~ msgstr "ๆฌกใฎใฏใฉในใฎๅบๅบใ่กจ็คบ" - -#~ msgid "Show overridden member function" -#~ msgstr "ใชใผใใผใฉใคใใใใใกใณใ้ขๆฐใ่กจ็คบ" - -#~ msgid "Retrieve from file" -#~ msgstr "ใใกใคใซใใๅๅพฉใใ" - -#~ msgid "Retrieve from project" -#~ msgstr "ใใญใธใงใฏใใใๅๅพฉใใ" - -#~ msgid "Retrieve from all projects" -#~ msgstr "ๅ
จใฆใฎใใญใธใงใฏใใใๅๅพฉใใ" - -#~ msgid "Retrieve" -#~ msgstr "ๅๅพฉ" - -#~ msgid "Show source of" -#~ msgstr "ๆฌกใฎใฝใผในใ่กจ็คบใใ" - -#~ msgid "Find symbol" -#~ msgstr "่ฆใคใใใทใณใใซ" - -#~ msgid "Browse class" -#~ msgstr "ใฏใฉในใๅ็
ง" - -#~ msgid "Show class in hierarchy" -#~ msgstr "้ๅฑคใงใฏใฉในใ่กจ็คบ" - -#~ msgid "Show class in restricted hierarchy" -#~ msgstr "้ๅฎใใใ้ๅฑคใงใฏใฉในใ่กจ็คบ" - -#~ msgid "Xref refers to" -#~ msgstr "Xref ใฎๅ็
งๅ
" - -#~ msgid "Xref referred by" -#~ msgstr "Xref ใๅ็
งใใใ" - -#~ msgid "Xref has a" -#~ msgstr "Xref ใๆฌกใฎใใฎใใใฃใฆใใพใ" - -#~ msgid "Xref used by" -#~ msgstr "Xref ใไฝฟ็จใใใ" - -#~ msgid "Show docu of" -#~ msgstr "ๆฌกใฎๆ็ซ ใ่กจ็คบ" - -#~ msgid "Generate docu for" -#~ msgstr "ๆฌกใฎๆ็ซ ใ็ๆ" - -#~ msgid "" -#~ "Cannot connect to SNiFF+. Check environment (sniffemacs must be found in " -#~ "$PATH).\n" -#~ msgstr "" -#~ "SNiFF+ใซๆฅ็ถใงใใพใใ. ็ฐๅขใใใงใใฏใใฆใใ ใใ(sniffemacs ใ $PATH ใซ" -#~ "ใชใใใฐใชใใพใใ).\n" - -#~ msgid "E274: Sniff: Error during read. Disconnected" -#~ msgstr "E274: Sniff: ่ชญ่พผไธญใซใจใฉใผใ็บ็ใใพใใ. ๅๆญใใพใใ" - -#~ msgid "SNiFF+ is currently " -#~ msgstr "็พๅจSNiFF+ ใฎ็ถๆ
ใฏใ" - -#~ msgid "not " -#~ msgstr "ๆช" - -#~ msgid "connected" -#~ msgstr "ๆฅ็ถใใงใ" - -#~ msgid "E275: Unknown SNiFF+ request: %s" -#~ msgstr "E275: ๆช็ฅใฎ SNiFF+ ใชใฏใจในใใงใ: %s" - -#~ msgid "E276: Error connecting to SNiFF+" -#~ msgstr "E276: SNiFF+ ใธใฎๆฅ็ถไธญใฎใจใฉใผใงใ" - -#~ msgid "E278: SNiFF+ not connected" -#~ msgstr "E278: SNiFF+ ใซๆฅ็ถใใใฆใใพใใ" - -#~ msgid "E279: Not a SNiFF+ buffer" -#~ msgstr "E279: SNiFF+ ใใใใกใใใใพใใ" - -#~ msgid "Sniff: Error during write. Disconnected" -#~ msgstr "Sniff: ๆธ่พผใฟไธญใซใจใฉใผใ็บ็ใใใฎใงๅๆญใใพใใ" - -#~ msgid "invalid buffer number" -#~ msgstr "็กๅนใชใใใใก็ชๅทใงใ" - -#~ msgid "not implemented yet" -#~ msgstr "ใพใ ๅฎ่ฃ
ใใใฆใใพใใ" - -#~ msgid "cannot set line(s)" -#~ msgstr "่กใ่จญๅฎใงใใพใใ" - -#~ msgid "invalid mark name" -#~ msgstr "็กๅนใชใใผใฏๅใงใ" - -#~ msgid "mark not set" -#~ msgstr "ใใผใฏใฏ่จญๅฎใใใฆใใพใใ" - -#~ msgid "row %d column %d" -#~ msgstr "่ก %d ๅ %d" - -#~ msgid "cannot insert/append line" -#~ msgstr "่กใฎๆฟๅ
ฅ/่ฟฝๅ ใใงใใพใใ" - -#~ msgid "line number out of range" -#~ msgstr "็ฏๅฒๅคใฎ่ก็ชๅทใงใ" - -#~ msgid "unknown flag: " -#~ msgstr "ๆช็ฅใฎใใฉใฐ: " - -#~ msgid "unknown vimOption" -#~ msgstr "ๆช็ฅใฎ vimOption ใงใ" - -#~ msgid "keyboard interrupt" -#~ msgstr "ใญใผใใผใๅฒ่พผใฟ" - -#~ msgid "vim error" -#~ msgstr "vim ใจใฉใผ" - -#~ msgid "cannot create buffer/window command: object is being deleted" -#~ msgstr "" -#~ "ใใใใก/ใฆใฃใณใใฆไฝๆใณใใณใใไฝๆใงใใพใใ: ใชใใธใงใฏใใๆถๅปใใใฆ" -#~ "ใใพใใ" - -#~ msgid "" -#~ "cannot register callback command: buffer/window is already being deleted" -#~ msgstr "" -#~ "ใณใผใซใใใฏใณใใณใใ็ป้ฒใงใใพใใ: ใใใใก/ใฆใฃใณใใฆใๆขใซๆถๅปใใใพ" -#~ "ใใ" - -#~ msgid "" -#~ "E280: TCL FATAL ERROR: reflist corrupt!? Please report this to vim-" -#~ "dev@vim.org" -#~ msgstr "" -#~ "E280: TCL ่ดๅฝ็ใจใฉใผ: reflist ๆฑๆ!? vim-dev@vim.org ใซๅ ฑๅใใฆใใ ใใ" - -#~ msgid "cannot register callback command: buffer/window reference not found" -#~ msgstr "" -#~ "ใณใผใซใใใฏใณใใณใใ็ป้ฒใงใใพใใ: ใใใใก/ใฆใฃใณใใฆใฎๅ็
งใ่ฆใคใใ" -#~ "ใพใใ" - -#~ msgid "" -#~ "E571: Sorry, this command is disabled: the Tcl library could not be " -#~ "loaded." -#~ msgstr "" -#~ "E571: ใใฎใณใใณใใฏ็กๅนใงใ,ใใใใชใใ: Tclใฉใคใใฉใชใใญใผใใงใใพใใ" -#~ "ใงใใ." - -#~ msgid "E572: exit code %d" -#~ msgstr "E572: ็ตไบใณใผใ %d" - -#~ msgid "cannot get line" -#~ msgstr "่กใๅๅพใงใใพใใ" - -#~ msgid "Unable to register a command server name" -#~ msgstr "ๅฝไปคใตใผใใฎๅๅใ็ป้ฒใงใใพใใ" - -#~ msgid "E248: Failed to send command to the destination program" -#~ msgstr "E248: ็ฎ็ใฎใใญใฐใฉใ ใธใฎใณใใณใ้ไฟกใซๅคฑๆใใพใใ" - -#~ msgid "E573: Invalid server id used: %s" -#~ msgstr "E573: ็กๅนใชใตใผใIDใไฝฟใใใพใใ: %s" - -#~ msgid "E251: VIM instance registry property is badly formed. Deleted!" -#~ msgstr "E251: VIM ๅฎไฝใฎ็ป้ฒใใญใใใฃใไธๆญฃใงใ. ๆถๅปใใพใใ!" - -#~ msgid "netbeans is not supported with this GUI\n" -#~ msgstr "netbeans ใฏใใฎGUIใงใฏๅฉ็จใงใใพใใ\n" - -#~ msgid "This Vim was not compiled with the diff feature." -#~ msgstr "ใใฎVimใซใฏdiffๆฉ่ฝใใใใพใใ(ใณใณใใคใซๆ่จญๅฎ)." - -#~ msgid "'-nb' cannot be used: not enabled at compile time\n" -#~ msgstr "'-nb' ไฝฟ็จไธๅฏ่ฝใงใ: ใณใณใใคใซๆใซ็กๅนใซใใใฆใใพใ\n" - -#~ msgid "Vim: Error: Failure to start gvim from NetBeans\n" -#~ msgstr "Vim: ใจใฉใผ: NetBeansใใgvimใในใฟใผใใงใใพใใ\n" - -#~ msgid "" -#~ "\n" -#~ "Where case is ignored prepend / to make flag upper case" -#~ msgstr "" -#~ "\n" -#~ "ๅคงๅฐๆๅญใ็ก่ฆใใใๅ ดๅใฏๅคงๆๅญใซใใใใใซ / ใๅ็ฝฎใใฆใใ ใใ" - -#~ msgid "-register\t\tRegister this gvim for OLE" -#~ msgstr "-register\t\tใใฎgvimใOLEใจใใฆ็ป้ฒใใ" - -#~ msgid "-unregister\t\tUnregister gvim for OLE" -#~ msgstr "-unregister\t\tgvimใฎOLE็ป้ฒใ่งฃ้คใใ" - -#~ msgid "-g\t\t\tRun using GUI (like \"gvim\")" -#~ msgstr "-g\t\t\tGUIใง่ตทๅใใ (\"gvim\" ใจๅใ)" - -#~ msgid "-f or --nofork\tForeground: Don't fork when starting GUI" -#~ msgstr "-f or --nofork\tใใฉใขใฐใฉใฆใณใ: GUIใๅงใใใจใใซforkใใชใ" - -#~ msgid "-f\t\t\tDon't use newcli to open window" -#~ msgstr "-f\t\t\tใฆใฃใณใใฆใ้ใใฎใซ newcli ใไฝฟ็จใใชใ" - -#~ msgid "-dev <device>\t\tUse <device> for I/O" -#~ msgstr "-dev <device>\t\tI/Oใซ <device> ใไฝฟ็จใใ" - -#~ msgid "-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc" -#~ msgstr "-U <gvimrc>\t\t.gvimrcใฎไปฃใใใซ <gvimrc> ใไฝฟใ" - -#~ msgid "-x\t\t\tEdit encrypted files" -#~ msgstr "-x\t\t\tๆๅทๅใใใใใกใคใซใ็ทจ้ใใ" - -#~ msgid "-display <display>\tConnect vim to this particular X-server" -#~ msgstr "-display <display>\tvimใๆๅฎใใ X ใตใผใใซๆฅ็ถใใ" - -#~ msgid "-X\t\t\tDo not connect to X server" -#~ msgstr "-X\t\t\tXใตใผใใซๆฅ็ถใใชใ" - -#~ msgid "--remote <files>\tEdit <files> in a Vim server if possible" -#~ msgstr "--remote <files>\tๅฏ่ฝใชใใฐVimใตใผใใง <files> ใ็ทจ้ใใ" - -#~ msgid "--remote-silent <files> Same, don't complain if there is no server" -#~ msgstr "--remote-silent <files> ๅไธ, ใตใผใใ็กใใฆใ่ญฆๅๆใๅบๅใใชใ" - -#~ msgid "" -#~ "--remote-wait <files> As --remote but wait for files to have been edited" -#~ msgstr "--remote-wait <files>\t--remoteๅพ ใใกใคใซใฎ็ทจ้ใ็ตใใใฎใๅพ
ใค" - -#~ msgid "" -#~ "--remote-wait-silent <files> Same, don't complain if there is no server" -#~ msgstr "" -#~ "--remote-wait-silent <files> ๅไธ, ใตใผใใ็กใใฆใ่ญฆๅๆใๅบๅใใชใ" - -#~ msgid "" -#~ "--remote-tab[-wait][-silent] <files> As --remote but use tab page per " -#~ "file" -#~ msgstr "" -#~ "--remote-tab[-wait][-silent] <files> --remoteใงใใกใคใซ1ใคใซใคใ1ใคใฎใฟใ" -#~ "ใใผใธใ้ใ" - -#~ msgid "--remote-send <keys>\tSend <keys> to a Vim server and exit" -#~ msgstr "--remote-send <keys>\tVimใตใผใใซ <keys> ใ้ไฟกใใฆ็ตไบใใ" - -#~ msgid "" -#~ "--remote-expr <expr>\tEvaluate <expr> in a Vim server and print result" -#~ msgstr "--remote-expr <expr>\tใตใผใใง <expr> ใๅฎ่กใใฆ็ตๆใ่กจ็คบใใ" - -#~ msgid "--serverlist\t\tList available Vim server names and exit" -#~ msgstr "--serverlist\t\tVimใตใผใๅใฎไธ่ฆงใ่กจ็คบใใฆ็ตไบใใ" - -#~ msgid "--servername <name>\tSend to/become the Vim server <name>" -#~ msgstr "--servername <name>\tVimใตใผใ <name> ใซ้ไฟก/ๅๅ่จญๅฎใใ" - -#~ msgid "" -#~ "\n" -#~ "Arguments recognised by gvim (Motif version):\n" -#~ msgstr "" -#~ "\n" -#~ "gvimใซใใฃใฆ่งฃ้ใใใๅผๆฐ(Motifใใผใธใงใณ):\n" - -#~ msgid "" -#~ "\n" -#~ "Arguments recognised by gvim (neXtaw version):\n" -#~ msgstr "" -#~ "\n" -#~ "gvimใซใใฃใฆ่งฃ้ใใใๅผๆฐ(neXtawใใผใธใงใณ):\n" - -#~ msgid "" -#~ "\n" -#~ "Arguments recognised by gvim (Athena version):\n" -#~ msgstr "" -#~ "\n" -#~ "gvimใซใใฃใฆ่งฃ้ใใใๅผๆฐ(Athenaใใผใธใงใณ):\n" - -#~ msgid "-display <display>\tRun vim on <display>" -#~ msgstr "-display <display>\t<display> ใงvimใๅฎ่กใใ" - -#~ msgid "-iconic\t\tStart vim iconified" -#~ msgstr "-iconic\t\tๆๅฐๅใใ็ถๆ
ใงvimใ่ตทๅใใ" - -#~ msgid "-background <color>\tUse <color> for the background (also: -bg)" -#~ msgstr "-background <color>\t่ๆฏ่ฒใซ <color> ใไฝฟใ(ๅ็พฉ: -bg)" - -#~ msgid "-foreground <color>\tUse <color> for normal text (also: -fg)" -#~ msgstr "-foreground <color>\tๅๆฏ่ฒใซ <color> ใไฝฟใ(ๅ็พฉ: -fg)" - -#~ msgid "-font <font>\t\tUse <font> for normal text (also: -fn)" -#~ msgstr "-font <font>\t\tใใญในใ่กจ็คบใซ <font> ใไฝฟใ(ๅ็พฉ: -fn)" - -#~ msgid "-boldfont <font>\tUse <font> for bold text" -#~ msgstr "-boldfont <font>\tๅคชๅญใซ <font> ใไฝฟใ" - -#~ msgid "-italicfont <font>\tUse <font> for italic text" -#~ msgstr "-italicfont <for>\tๆไฝๅญใซ <font> ใไฝฟใ" - -#~ msgid "-geometry <geom>\tUse <geom> for initial geometry (also: -geom)" -#~ msgstr "-geometry <geom>\tๅๆ้
็ฝฎใซ <geom> ใไฝฟใ(ๅ็พฉ: -geom)" - -#~ msgid "-borderwidth <width>\tUse a border width of <width> (also: -bw)" -#~ msgstr "-borderwidth <width>\tๅข็ใฎๅน
ใ <width> ใซใใ(ๅ็พฉ: -bw)" - -#~ msgid "" -#~ "-scrollbarwidth <width> Use a scrollbar width of <width> (also: -sw)" -#~ msgstr "" -#~ "-scrollbarwidth <width> ในใฏใญใผใซใใผใฎๅน
ใ <width> ใซใใ(ๅ็พฉ: -sw)" - -#~ msgid "-menuheight <height>\tUse a menu bar height of <height> (also: -mh)" -#~ msgstr "" -#~ "-menuheight <height>\tใกใใฅใผใใผใฎ้ซใใ <height> ใซใใ(ๅ็พฉ: -mh)" - -#~ msgid "-reverse\t\tUse reverse video (also: -rv)" -#~ msgstr "-reverse\t\tๅ่ปขๆ ๅใไฝฟ็จใใ(ๅ็พฉ: -rv)" - -#~ msgid "+reverse\t\tDon't use reverse video (also: +rv)" -#~ msgstr "+reverse\t\tๅ่ปขๆ ๅใไฝฟ็จใใชใ(ๅ็พฉ: +rv)" - -#~ msgid "-xrm <resource>\tSet the specified resource" -#~ msgstr "-xrm <resource>\t็นๅฎใฎใชใฝใผในใไฝฟ็จใใ" - -#~ msgid "" -#~ "\n" -#~ "Arguments recognised by gvim (GTK+ version):\n" -#~ msgstr "" -#~ "\n" -#~ "gvimใซใใฃใฆ่งฃ้ใใใๅผๆฐ(GTK+ใใผใธใงใณ):\n" - -#~ msgid "-display <display>\tRun vim on <display> (also: --display)" -#~ msgstr "-display <display>\t<display> ใงvimใๅฎ่กใใ(ๅ็พฉ: --display)" - -#~ msgid "--role <role>\tSet a unique role to identify the main window" -#~ msgstr "--role <role>\tใกใคใณใฆใฃใณใใฆใ่ญๅฅใใไธๆใชๅฝนๅฒ(role)ใ่จญๅฎใใ" - -#~ msgid "--socketid <xid>\tOpen Vim inside another GTK widget" -#~ msgstr "--socketid <xid>\t็ฐใชใGTK widgetใงVimใ้ใ" - -#~ msgid "--echo-wid\t\tMake gvim echo the Window ID on stdout" -#~ msgstr "--echo-wid\t\tใฆใฃใณใใฆIDใๆจๆบๅบๅใซๅบๅใใ" - -#~ msgid "-P <parent title>\tOpen Vim inside parent application" -#~ msgstr "-P <่ฆชใฎใฟใคใใซ>\tVimใ่ฆชใขใใชใฑใผใทใงใณใฎไธญใง่ตทๅใใ" - -#~ msgid "--windowid <HWND>\tOpen Vim inside another win32 widget" -#~ msgstr "--windowid <HWND>\t็ฐใชใWin32 widgetใฎๅ
้จใซVimใ้ใ" - -#~ msgid "No display" -#~ msgstr "ใใฃในใใฌใคใ่ฆใคใใใพใใ" - -#~ msgid ": Send failed.\n" -#~ msgstr ": ้ไฟกใซๅคฑๆใใพใใ.\n" - -#~ msgid ": Send failed. Trying to execute locally\n" -#~ msgstr ": ้ไฟกใซๅคฑๆใใพใใ. ใญใผใซใซใงใฎๅฎ่กใ่ฉฆใฟใฆใใพใ\n" - -#~ msgid "%d of %d edited" -#~ msgstr "%d ๅ (%d ๅไธญ) ใฎใใกใคใซใ็ทจ้ใใพใใ" - -#~ msgid "No display: Send expression failed.\n" -#~ msgstr "ใใฃในใใฌใคใใใใพใใ: ๅผใฎ้ไฟกใซๅคฑๆใใพใใ.\n" - -#~ msgid ": Send expression failed.\n" -#~ msgstr ": ๅผใฎ้ไฟกใซๅคฑๆใใพใใ.\n" - -#~ msgid "E543: Not a valid codepage" -#~ msgstr "E543: ็กๅนใชใณใผใใใผใธใงใ" - -#~ msgid "E284: Cannot set IC values" -#~ msgstr "E284: ICใฎๅคใ่จญๅฎใงใใพใใ" - -#~ msgid "E285: Failed to create input context" -#~ msgstr "E285: ใคใณใใใใณใณใใญในใใฎไฝๆใซๅคฑๆใใพใใ" - -#~ msgid "E286: Failed to open input method" -#~ msgstr "E286: ใคใณใใใใกใฝใใใฎใชใผใใณใซๅคฑๆใใพใใ" - -#~ msgid "E287: Warning: Could not set destroy callback to IM" -#~ msgstr "E287: ่ญฆๅ: IMใฎ็ ดๅฃใณใผใซใใใฏใ่จญๅฎใงใใพใใใงใใ" - -#~ msgid "E288: input method doesn't support any style" -#~ msgstr "E288: ใคใณใใใใกใฝใใใฏใฉใใชในใฟใคใซใใตใใผใใใพใใ" - -#~ msgid "E289: input method doesn't support my preedit type" -#~ msgstr "E289: ใคใณใใใใกใฝใใใฏ my preedit type ใใตใใผใใใพใใ" +#, c-format +msgid "E447: Can't find file \"%s\" in path" +msgstr "E447: pathใซใฏ \"%s\" ใจใใใใกใคใซใใใใพใใ" -#~ msgid "E843: Error while updating swap file crypt" -#~ msgstr "E843: ในใฏใใใใกใคใซใฎๆๅทใๆดๆฐไธญใซใจใฉใผใ็บ็ใใพใใ" +#, c-format +msgid "E799: Invalid ID: %ld (must be greater than or equal to 1)" +msgstr "E799: ็กๅนใช ID: %ld (1 ไปฅไธใงใชใใใฐใชใใพใใ)" -#~ msgid "" -#~ "E833: %s is encrypted and this version of Vim does not support encryption" -#~ msgstr "" -#~ "E833: %s ใฏใใฎใใผใธใงใณใฎVimใงใตใใผใใใฆใใชใๅฝขๅผใงๆๅทๅใใใฆใใพใ" +#, c-format +msgid "E801: ID already taken: %ld" +msgstr "E801: ID ใฏใใงใซๅฉ็จไธญใงใ: %ld" -#~ msgid "Swap file is encrypted: \"%s\"" -#~ msgstr "ในใฏใใใใกใคใซใฏๆๅทๅใใใฆใใพใ: \"%s\"" +msgid "List or number required" +msgstr "ใชในใใๆฐๅคใๅฟ
่ฆใงใ" -#~ msgid "" -#~ "\n" -#~ "If you entered a new crypt key but did not write the text file," -#~ msgstr "" -#~ "\n" -#~ "ๆฐใใๆๅทใญใผใๅ
ฅๅใใใใจใซใใญในใใใกใคใซใไฟๅญใใฆใใชใๅ ดๅใฏ," +#, c-format +msgid "E802: Invalid ID: %ld (must be greater than or equal to 1)" +msgstr "E802: ็กๅนใช ID: %ld (1 ไปฅไธใงใชใใใฐใชใใพใใ)" -#~ msgid "" -#~ "\n" -#~ "enter the new crypt key." -#~ msgstr "" -#~ "\n" -#~ "ๆฐใใๆๅทใญใผใๅ
ฅๅใใฆใใ ใใ." +#, c-format +msgid "E803: ID not found: %ld" +msgstr "E803: ID ใฏใใใพใใ: %ld" -#~ msgid "" -#~ "\n" -#~ "If you wrote the text file after changing the crypt key press enter" -#~ msgstr "" -#~ "\n" -#~ "ๆๅทใญใผใๅคใใใใจใซใใญในใใใกใคใซใไฟๅญใใๅ ดๅใฏ, ใใญในใใใกใคใซใจ" +#, c-format +msgid "E370: Could not load library %s" +msgstr "E370: ใฉใคใใฉใช %s ใใญใผใใงใใพใใใงใใ" -#~ msgid "" -#~ "\n" -#~ "to use the same key for text file and swap file" -#~ msgstr "" -#~ "\n" -#~ "ในใฏใใใใกใคใซใซๅใๆๅทใญใผใไฝฟใใใใซenterใ ใใๆผใใฆใใ ใใ." +msgid "Sorry, this command is disabled: the Perl library could not be loaded." +msgstr "" +"ใใฎใณใใณใใฏ็กๅนใงใ, ใใใใชใใ: Perlใฉใคใใฉใชใใญใผใใงใใพใใใงใใ." -#~ msgid "Using crypt key from swap file for the text file.\n" -#~ msgstr "ในใฏใใใใกใคใซใใๅๅพใใๆๅทใญใผใใใญในใใใกใคใซใซไฝฟใใพใ.\n" +msgid "E299: Perl evaluation forbidden in sandbox without the Safe module" +msgstr "" +"E299: ใตใณใใใใฏในใงใฏ Safe ใขใธใฅใผใซใไฝฟ็จใใชใPerlในใฏใชใใใฏ็ฆใใใ" +"ใฆใใพใ" -#~ msgid "" -#~ "\n" -#~ " [not usable with this version of Vim]" -#~ msgstr "" -#~ "\n" -#~ " [ใใฎVimใใผใธใงใณใงใฏไฝฟ็จใงใใพใใ]" +msgid "Edit with &multiple Vims" +msgstr "่คๆฐใฎVimใง็ทจ้ใใ (&M)" -#~ msgid "Tear off this menu" -#~ msgstr "ใใฎใกใใฅใผใๅใๅใ" +msgid "Edit with single &Vim" +msgstr "1ใคใฎVimใง็ทจ้ใใ (&V)" -#~ msgid "Select Directory dialog" -#~ msgstr "ใใฃใฌใฏใใช้ธๆใใคใขใญใฐ" +msgid "Diff with Vim" +msgstr "Vimใงๅทฎๅใ่กจ็คบใใ" -#~ msgid "Save File dialog" -#~ msgstr "ใใกใคใซไฟๅญใใคใขใญใฐ" +msgid "Edit with &Vim" +msgstr "Vimใง็ทจ้ใใ (&V)" -#~ msgid "Open File dialog" -#~ msgstr "ใใกใคใซ่ชญ่พผใใคใขใญใฐ" +#. Now concatenate +msgid "Edit with existing Vim - " +msgstr "่ตทๅๆธใฎVimใง็ทจ้ใใ - " -#~ msgid "E338: Sorry, no file browser in console mode" -#~ msgstr "" -#~ "E338: ใณใณใฝใผใซใขใผใใงใฏใใกใคใซใใฉใฆใถใไฝฟใใพใใ, ใใใใชใใ" +msgid "Edits the selected file(s) with Vim" +msgstr "้ธๆใใใใกใคใซใVimใง็ทจ้ใใ" -#~ msgid "Vim: preserving files...\n" -#~ msgstr "Vim: ใใกใคใซใไฟๅญไธญ...\n" +msgid "Error creating process: Check if gvim is in your path!" +msgstr "ใใญใปในใฎไฝๆใซๅคฑๆ: gvimใ็ฐๅขๅคๆฐPATHไธใซใใใ็ขบ่ชใใฆใใ ใใ!" -#~ msgid "Vim: Finished.\n" -#~ msgstr "Vim: ็ตไบใใพใใ.\n" +msgid "gvimext.dll error" +msgstr "gvimext.dll ใจใฉใผ" -#~ msgid "ERROR: " -#~ msgstr "ใจใฉใผ: " +msgid "Path length too long!" +msgstr "ใในใ้ท้ใใพใ!" -#~ msgid "" -#~ "\n" -#~ "[bytes] total alloc-freed %<PRIu64>-%<PRIu64>, in use %<PRIu64>, peak use " -#~ "%<PRIu64>\n" -#~ msgstr "" -#~ "\n" -#~ "[ใกใขใช(ใใคใ)] ็ทๅฒๅฝ-่งฃๆพ้ %<PRIu64>-%<PRIu64>, ไฝฟ็จ้ %<PRIu64>, ใใผ" -#~ "ใฏๆ %<PRIu64>\n" +msgid "--No lines in buffer--" +msgstr "--ใใใใกใซ่กใใใใพใใ--" -#~ msgid "" -#~ "[calls] total re/malloc()'s %<PRIu64>, total free()'s %<PRIu64>\n" -#~ "\n" -#~ msgstr "" -#~ "[ๅผๅบ] ็ท re/malloc() ๅๆฐ %<PRIu64>, ็ท free() ๅๆฐ %<PRIu64>\n" -#~ "\n" +#. +#. * The error messages that can be shared are included here. +#. * Excluded are errors that are only used once and debugging messages. +#. +msgid "E470: Command aborted" +msgstr "E470: ใณใใณใใไธญๆญใใใพใใ" -#~ msgid "E340: Line is becoming too long" -#~ msgstr "E340: ่กใ้ทใใชใ้ใใพใใ" +msgid "E471: Argument required" +msgstr "E471: ๅผๆฐใๅฟ
่ฆใงใ" -#~ msgid "E341: Internal error: lalloc(%<PRId64>, )" -#~ msgstr "E341: ๅ
้จใจใฉใผ: lalloc(%<PRId64>,)" +msgid "E10: \\ should be followed by /, ? or &" +msgstr "E10: \\ ใฎๅพใฏ / ใ ? ใ & ใงใชใใใฐใชใใพใใ" -#~ msgid "E547: Illegal mouseshape" -#~ msgstr "E547: ไธๆญฃใช 'mouseshape' ใงใ" +msgid "E11: Invalid in command-line window; <CR> executes, CTRL-C quits" +msgstr "E11: ใณใใณใใฉใคใณใงใฏ็กๅนใงใ; <CR>ใงๅฎ่ก, CTRL-Cใงใใใ" -#~ msgid "Enter encryption key: " -#~ msgstr "ๆๅทๅ็จใฎใญใผใๅ
ฅๅใใฆใใ ใใ: " +msgid "E12: Command not allowed from exrc/vimrc in current dir or tag search" +msgstr "" +"E12: ็พๅจใฎใใฃใฌใฏใใชใใฟใฐๆค็ดขใงใฏexrc/vimrcใฎใณใใณใใฏ่จฑๅฏใใใพใใ" -#~ msgid "Enter same key again: " -#~ msgstr "ใใไธๅบฆๅใใญใผใๅ
ฅๅใใฆใใ ใใ: " +msgid "E171: Missing :endif" +msgstr "E171: :endif ใใใใพใใ" -#~ msgid "Keys don't match!" -#~ msgstr "ใญใผใไธ่ดใใพใใ" +msgid "E600: Missing :endtry" +msgstr "E600: :endtry ใใใใพใใ" -#~ msgid "Cannot connect to Netbeans #2" -#~ msgstr "Netbeans #2 ใซๆฅ็ถใงใใพใใ" +msgid "E170: Missing :endwhile" +msgstr "E170: :endwhile ใใใใพใใ" -#~ msgid "Cannot connect to Netbeans" -#~ msgstr "Netbeans ใซๆฅ็ถใงใใพใใ" +msgid "E170: Missing :endfor" +msgstr "E170: :endfor ใใใใพใใ" -#~ msgid "E668: Wrong access mode for NetBeans connection info file: \"%s\"" -#~ msgstr "" -#~ "E668: NetBeansใฎๆฅ็ถๆ
ๅ ฑใใกใคใซใฎใขใฏใปในใขใผใใซๅ้กใใใใพใ: \"%s\"" +msgid "E588: :endwhile without :while" +msgstr "E588: :while ใฎใชใ :endwhile ใใใใพใ" -#~ msgid "read from Netbeans socket" -#~ msgstr "Netbeans ใฎใฝใฑใใใ่ชญ่พผใฟ" +msgid "E588: :endfor without :for" +msgstr "E588: :endfor ใฎใชใ :for ใใใใพใ" -#~ msgid "E658: NetBeans connection lost for buffer %<PRId64>" -#~ msgstr "E658: ใใใใก %<PRId64> ใฎ NetBeans ๆฅ็ถใๅคฑใใใพใใ" +msgid "E13: File exists (add ! to override)" +msgstr "E13: ใใกใคใซใๅญๅจใใพใ (! ใ่ฟฝๅ ใงไธๆธ)" -#~ msgid "E838: netbeans is not supported with this GUI" -#~ msgstr "E838: NetBeansใฏใใฎGUIใซใฏๅฏพๅฟใใฆใใพใใ" +msgid "E472: Command failed" +msgstr "E472: ใณใใณใใๅคฑๆใใพใใ" -#~ msgid "E511: netbeans already connected" -#~ msgstr "E511: NetBeansใฏๆขใซๆฅ็ถใใฆใใพใ" +#, c-format +msgid "E234: Unknown fontset: %s" +msgstr "E234: ๆช็ฅใฎใใฉใณใใปใใ: %s" -#~ msgid "E505: %s is read-only (add ! to override)" -#~ msgstr "E505: %s ใฏ่ชญ่พผๅฐ็จใงใ (ๅผทๅถๆธ่พผใซใฏ ! ใ่ฟฝๅ )" +#, c-format +msgid "E235: Unknown font: %s" +msgstr "E235: ๆช็ฅใฎใใฉใณใ: %s" -#~ msgid "E775: Eval feature not available" -#~ msgstr "E775: ๅผ่ฉไพกๆฉ่ฝใ็กๅนใซใชใฃใฆใใพใ" +#, c-format +msgid "E236: Font \"%s\" is not fixed-width" +msgstr "E236: ใใฉใณใ \"%s\" ใฏๅบๅฎๅน
ใงใฏใใใพใใ" -#~ msgid "freeing %<PRId64> lines" -#~ msgstr "%<PRId64> ่กใ่งฃๆพไธญ" +msgid "E473: Internal error" +msgstr "E473: ๅ
้จใจใฉใผใงใ" -#~ msgid "E530: Cannot change term in GUI" -#~ msgstr "E530: GUIใงใฏ 'term' ใๅคๆดใงใใพใใ" +msgid "Interrupted" +msgstr "ๅฒ่พผใพใใพใใ" -#~ msgid "E531: Use \":gui\" to start the GUI" -#~ msgstr "E531: GUIใในใฟใผใใใใซใฏ \":gui\" ใไฝฟ็จใใฆใใ ใใ" +msgid "E14: Invalid address" +msgstr "E14: ็กๅนใชใขใใฌในใงใ" -#~ msgid "E617: Cannot be changed in the GTK+ 2 GUI" -#~ msgstr "E617: GTK+2 GUIใงใฏๅคๆดใงใใพใใ" +msgid "E474: Invalid argument" +msgstr "E474: ็กๅนใชๅผๆฐใงใ" -#~ msgid "E596: Invalid font(s)" -#~ msgstr "E596: ็กๅนใชใใฉใณใใงใ" +#, c-format +msgid "E475: Invalid argument: %s" +msgstr "E475: ็กๅนใชๅผๆฐใงใ: %s" -#~ msgid "E597: can't select fontset" -#~ msgstr "E597: ใใฉใณใใปใใใ้ธๆใงใใพใใ" +#, c-format +msgid "E15: Invalid expression: %s" +msgstr "E15: ็กๅนใชๅผใงใ: %s" -#~ msgid "E598: Invalid fontset" -#~ msgstr "E598: ็กๅนใชใใฉใณใใปใใใงใ" +msgid "E16: Invalid range" +msgstr "E16: ็กๅนใช็ฏๅฒใงใ" -#~ msgid "E533: can't select wide font" -#~ msgstr "E533: ใฏใคใใใฉใณใใ้ธๆใงใใพใใ" +msgid "E476: Invalid command" +msgstr "E476: ็กๅนใชใณใใณใใงใ" -#~ msgid "E534: Invalid wide font" -#~ msgstr "E534: ็กๅนใชใฏใคใใใฉใณใใงใ" +#, c-format +msgid "E17: \"%s\" is a directory" +msgstr "E17: \"%s\" ใฏใใฃใฌใฏใใชใงใ" -#~ msgid "E538: No mouse support" -#~ msgstr "E538: ใใฆในใฏใตใใผใใใใพใใ" +#, c-format +msgid "E364: Library call failed for \"%s()\"" +msgstr "E364: \"%s\"() ใฎใฉใคใใฉใชๅผๅบใซๅคฑๆใใพใใ" -#~ msgid "cannot open " -#~ msgstr "้ใใพใใ " +#, c-format +msgid "E448: Could not load library function %s" +msgstr "E448: ใฉใคใใฉใชใฎ้ขๆฐ %s ใใญใผใใงใใพใใใงใใ" -#~ msgid "VIM: Can't open window!\n" -#~ msgstr "VIM: ใฆใฃใณใใฆใ้ใใพใใ!\n" +msgid "E19: Mark has invalid line number" +msgstr "E19: ใใผใฏใซ็กๅนใช่ก็ชๅทใๆๅฎใใใฆใใพใใ" -#~ msgid "Need Amigados version 2.04 or later\n" -#~ msgstr "Amigadosใฎใใผใธใงใณ 2.04ใใใไปฅ้ใๅฟ
่ฆใงใ\n" +msgid "E20: Mark not set" +msgstr "E20: ใใผใฏใฏ่จญๅฎใใใฆใใพใใ" -#~ msgid "Need %s version %<PRId64>\n" -#~ msgstr "%s ใฎใใผใธใงใณ %<PRId64> ใๅฟ
่ฆใงใ\n" +msgid "E21: Cannot make changes, 'modifiable' is off" +msgstr "E21: 'modifiable' ใใชใใชใฎใง, ๅคๆดใงใใพใใ" -#~ msgid "Cannot open NIL:\n" -#~ msgstr "NILใ้ใใพใใ:\n" +msgid "E22: Scripts nested too deep" +msgstr "E22: ในใฏใชใใใฎๅ
ฅใๅญใๆทฑ้ใใพใ" -#~ msgid "Cannot create " -#~ msgstr "ไฝๆใงใใพใใ " +msgid "E23: No alternate file" +msgstr "E23: ๅฏใใกใคใซใฏใใใพใใ" -#~ msgid "Vim exiting with %d\n" -#~ msgstr "Vimใฏ %d ใง็ตไบใใพใ\n" +msgid "E24: No such abbreviation" +msgstr "E24: ใใฎใใใช็ญ็ธฎๅ
ฅๅใฏใใใพใใ" -#~ msgid "cannot change console mode ?!\n" -#~ msgstr "ใณใณใฝใผใซใขใผใใๅคๆดใงใใพใใ?!\n" +msgid "E477: No ! allowed" +msgstr "E477: ! ใฏ่จฑๅฏใใใฆใใพใใ" -#~ msgid "mch_get_shellsize: not a console??\n" -#~ msgstr "mch_get_shellsize: ใณใณใฝใผใซใงใฏใชใ??\n" +msgid "E25: GUI cannot be used: Not enabled at compile time" +msgstr "E25: GUIใฏไฝฟ็จไธๅฏ่ฝใงใ: ใณใณใใคใซๆใซ็กๅนใซใใใฆใใพใ" -#~ msgid "E360: Cannot execute shell with -f option" -#~ msgstr "E360: -f ใชใใทใงใณใงใทใงใซใๅฎ่กใงใใพใใ" +msgid "E26: Hebrew cannot be used: Not enabled at compile time\n" +msgstr "E26: ใใใฉใค่ชใฏไฝฟ็จไธๅฏ่ฝใงใ: ใณใณใใคใซๆใซ็กๅนใซใใใฆใใพใ\n" -#~ msgid "Cannot execute " -#~ msgstr "ๅฎ่กใงใใพใใ " +msgid "E27: Farsi cannot be used: Not enabled at compile time\n" +msgstr "E27: ใใซใทใข่ชใฏไฝฟ็จไธๅฏ่ฝใงใ: ใณใณใใคใซๆใซ็กๅนใซใใใฆใใพใ\n" -#~ msgid "shell " -#~ msgstr "ใทใงใซ " +msgid "E800: Arabic cannot be used: Not enabled at compile time\n" +msgstr "E800: ใขใฉใใข่ชใฏไฝฟ็จไธๅฏ่ฝใงใ: ใณใณใใคใซๆใซ็กๅนใซใใใฆใใพใ\n" -#~ msgid " returned\n" -#~ msgstr " ๆปใใพใใ\n" +#, c-format +msgid "E28: No such highlight group name: %s" +msgstr "E28: ใใฎใใใชๅใฎใใคใฉใคใใฐใซใผใใฏใใใพใใ: %s" -#~ msgid "ANCHOR_BUF_SIZE too small." -#~ msgstr "ANCHOR_BUF_SIZE ใๅฐใ้ใใพใ." +msgid "E29: No inserted text yet" +msgstr "E29: ใพใ ใใญในใใๆฟๅ
ฅใใใฆใใพใใ" -#~ msgid "I/O ERROR" -#~ msgstr "ๅ
ฅๅบๅใจใฉใผ" +msgid "E30: No previous command line" +msgstr "E30: ไปฅๅใซใณใใณใ่กใใใใพใใ" -#~ msgid "Message" -#~ msgstr "ใกใใปใผใธ" +msgid "E31: No such mapping" +msgstr "E31: ใใฎใใใชใใใใณใฐใฏใใใพใใ" -#~ msgid "'columns' is not 80, cannot execute external commands" -#~ msgstr "'columns' ใ80ใงใฏใชใใใ, ๅค้จใณใใณใใๅฎ่กใงใใพใใ" +msgid "E479: No match" +msgstr "E479: ่ฉฒๅฝใฏใใใพใใ" -#~ msgid "E237: Printer selection failed" -#~ msgstr "E237: ใใชใณใฟใฎ้ธๆใซๅคฑๆใใพใใ" +#, c-format +msgid "E480: No match: %s" +msgstr "E480: ่ฉฒๅฝใฏใใใพใใ: %s" -#~ msgid "to %s on %s" -#~ msgstr "%s ใธ (%s ไธใฎ)" +msgid "E32: No file name" +msgstr "E32: ใใกใคใซๅใใใใพใใ" -#~ msgid "E613: Unknown printer font: %s" -#~ msgstr "E613: ๆช็ฅใฎใใชใณใฟใชใใทใงใณใงใ: %s" +msgid "E33: No previous substitute regular expression" +msgstr "E33: ๆญฃ่ฆ่กจ็พ็ฝฎๆใใพใ ๅฎ่กใใใฆใใพใใ" -#~ msgid "E238: Print error: %s" -#~ msgstr "E238: ๅฐๅทใจใฉใผ: %s" +msgid "E34: No previous command" +msgstr "E34: ใณใใณใใใพใ ๅฎ่กใใใฆใใพใใ" -#~ msgid "Printing '%s'" -#~ msgstr "ๅฐๅทใใฆใใพใ: '%s'" +msgid "E35: No previous regular expression" +msgstr "E35: ๆญฃ่ฆ่กจ็พใใพใ ๅฎ่กใใใฆใใพใใ" -#~ msgid "E244: Illegal charset name \"%s\" in font name \"%s\"" -#~ msgstr "E244: ๆๅญใปใใๅ \"%s\" ใฏไธๆญฃใงใ (ใใฉใณใๅ \"%s\")" +msgid "E481: No range allowed" +msgstr "E481: ็ฏๅฒๆๅฎใฏ่จฑๅฏใใใฆใใพใใ" -#~ msgid "E245: Illegal char '%c' in font name \"%s\"" -#~ msgstr "E245: '%c' ใฏไธๆญฃใชๆๅญใงใ (ใใฉใณใๅ \"%s\")" +msgid "E36: Not enough room" +msgstr "E36: ใฆใฃใณใใฆใซๅๅใช้ซใใใใใฏๅน
ใใใใพใใ" -#~ msgid "Vim: Double signal, exiting\n" -#~ msgstr "Vim: 2้ใฎใทใฐใใซใฎใใ, ็ตไบใใพใ\n" +#, c-format +msgid "E247: no registered server named \"%s\"" +msgstr "E247: %s ใจใใๅๅใฎ็ป้ฒใใใใตใผใใผใฏใใใพใใ" -#~ msgid "Vim: Caught deadly signal %s\n" -#~ msgstr "Vim: ่ดๅฝ็ใทใฐใใซ %s ใๆค็ฅใใพใใ\n" +#, c-format +msgid "E482: Can't create file %s" +msgstr "E482: ใใกใคใซ %s ใไฝๆใงใใพใใ" -#~ msgid "Vim: Caught deadly signal\n" -#~ msgstr "Vim: ่ดๅฝ็ใทใฐใใซใๆค็ฅใใพใใ\n" +msgid "E483: Can't get temp file name" +msgstr "E483: ไธๆใใกใคใซใฎๅๅใๅๅพใงใใพใใ" -#~ msgid "Opening the X display took %<PRId64> msec" -#~ msgstr "Xใตใผใใธใฎๆฅ็ถใซ %<PRId64> ใใช็งใใใใพใใ" +#, c-format +msgid "E484: Can't open file %s" +msgstr "E484: ใใกใคใซ \"%s\" ใ้ใใพใใ" -#~ msgid "" -#~ "\n" -#~ "Vim: Got X error\n" -#~ msgstr "" -#~ "\n" -#~ "Vim: X ใฎใจใฉใผใๆคๅบใใพใใr\n" +#, c-format +msgid "E485: Can't read file %s" +msgstr "E485: ใใกใคใซ %s ใ่ชญ่พผใใพใใ" -#~ msgid "Testing the X display failed" -#~ msgstr "X display ใฎใใงใใฏใซๅคฑๆใใพใใ" +msgid "E37: No write since last change (add ! to override)" +msgstr "E37: ๆๅพใฎๅคๆดใไฟๅญใใใฆใใพใใ (! ใ่ฟฝๅ ใงๅคๆดใ็ ดๆฃ)" -#~ msgid "Opening the X display timed out" -#~ msgstr "X display ใฎ open ใใฟใคใ ใขใฆใใใพใใ" +msgid "E37: No write since last change" +msgstr "E37: ๆๅพใฎๅคๆดใไฟๅญใใใฆใใพใใ" -#~ msgid "" -#~ "\n" -#~ "Cannot execute shell sh\n" -#~ msgstr "" -#~ "\n" -#~ "sh ใทใงใซใๅฎ่กใงใใพใใ\n" +msgid "E38: Null argument" +msgstr "E38: ๅผๆฐใ็ฉบใงใ" -#~ msgid "" -#~ "\n" -#~ "Cannot create pipes\n" -#~ msgstr "" -#~ "\n" -#~ "ใใคใใไฝๆใงใใพใใ\n" +msgid "E39: Number expected" +msgstr "E39: ๆฐๅคใ่ฆๆฑใใใฆใใพใ" -#~ msgid "" -#~ "\n" -#~ "Cannot fork\n" -#~ msgstr "" -#~ "\n" -#~ "fork ใงใใพใใ\n" +#, c-format +msgid "E40: Can't open errorfile %s" +msgstr "E40: ใจใฉใผใใกใคใซ %s ใ้ใใพใใ" -#~ msgid "" -#~ "\n" -#~ "Command terminated\n" -#~ msgstr "" -#~ "\n" -#~ "ใณใใณใใไธญๆญใใพใใ\n" +msgid "E233: cannot open display" +msgstr "E233: ใใฃในใใฌใคใ้ใใพใใ" -#~ msgid "XSMP lost ICE connection" -#~ msgstr "XSMP ใICEๆฅ็ถใๅคฑใใพใใ" +msgid "E41: Out of memory!" +msgstr "E41: ใกใขใชใๅฐฝใๆใฆใพใใ!" -#~ msgid "Opening the X display failed" -#~ msgstr "X display ใฎ open ใซๅคฑๆใใพใใ" +msgid "Pattern not found" +msgstr "ใใฟใผใณใฏ่ฆใคใใใพใใใงใใ" -#~ msgid "XSMP handling save-yourself request" -#~ msgstr "XSMP ใsave-yourself่ฆๆฑใๅฆ็ใใฆใใพใ" +#, c-format +msgid "E486: Pattern not found: %s" +msgstr "E486: ใใฟใผใณใฏ่ฆใคใใใพใใใงใใ: %s" -#~ msgid "XSMP opening connection" -#~ msgstr "XSMP ใๆฅ็ถใ้ๅงใใฆใใพใ" +msgid "E487: Argument must be positive" +msgstr "E487: ๅผๆฐใฏๆญฃใฎๅคใงใชใใใฐใชใใพใใ" -#~ msgid "XSMP ICE connection watch failed" -#~ msgstr "XSMP ICEๆฅ็ถใๅคฑๆใใใใใงใ" +msgid "E459: Cannot go back to previous directory" +msgstr "E459: ๅใฎใใฃใฌใฏใใชใซๆปใใพใใ" -#~ msgid "XSMP SmcOpenConnection failed: %s" -#~ msgstr "XSMP SmcOpenConnectionใๅคฑๆใใพใใ: %s" +msgid "E42: No Errors" +msgstr "E42: ใจใฉใผใฏใใใพใใ" -#~ msgid "At line" -#~ msgstr "่ก" +msgid "E776: No location list" +msgstr "E776: ใญใฑใผใทใงใณใชในใใฏใใใพใใ" -#~ msgid "Could not load vim32.dll!" -#~ msgstr "vim32.dll ใใญใผใใงใใพใใใงใใ" +msgid "E43: Damaged match string" +msgstr "E43: ่ฉฒๅฝๆๅญๅใ็ ดๆใใฆใใพใ" -#~ msgid "VIM Error" -#~ msgstr "VIMใจใฉใผ" +msgid "E44: Corrupted regexp program" +msgstr "E44: ไธๆญฃใชๆญฃ่ฆ่กจ็พใใญใฐใฉใ ใงใ" -#~ msgid "Could not fix up function pointers to the DLL!" -#~ msgstr "DLLใใ้ขๆฐใใคใณใฟใๅๅพใงใใพใใใงใใ" +msgid "E45: 'readonly' option is set (add ! to override)" +msgstr "E45: 'readonly' ใชใใทใงใณใ่จญๅฎใใใฆใใพใ (! ใ่ฟฝๅ ใงไธๆธใ)" -#~ msgid "shell returned %d" -#~ msgstr "ใทใงใซใใณใผใ %d ใง็ตไบใใพใใ" +#, c-format +msgid "E46: Cannot change read-only variable \"%s\"" +msgstr "E46: ่ชญๅๅฐ็จๅคๆฐ \"%s\" ใซใฏๅคใ่จญๅฎใงใใพใใ" -#~ msgid "Vim: Caught %s event\n" -#~ msgstr "Vim: ใคใใณใ %s ใๆค็ฅ\n" +#, c-format +msgid "E794: Cannot set variable in the sandbox: \"%s\"" +msgstr "E794: ใตใณใใใใฏในใงใฏๅคๆฐ \"%s\" ใซๅคใ่จญๅฎใงใใพใใ" -#~ msgid "close" -#~ msgstr "้ใใ" +msgid "E713: Cannot use empty key for Dictionary" +msgstr "E713: ่พๆธๅใซ็ฉบใฎใญใผใไฝฟใใใจใฏใงใใพใใ" -#~ msgid "logoff" -#~ msgstr "ใญใฐใชใ" +msgid "E715: Dictionary required" +msgstr "E715: ่พๆธๅใๅฟ
่ฆใงใ" -#~ msgid "shutdown" -#~ msgstr "ใทใฃใใใใฆใณ" +#, c-format +msgid "E684: list index out of range: %ld" +msgstr "E684: ใชในใใฎใคใณใใใฏในใ็ฏๅฒๅคใงใ: %ld" -#~ msgid "E371: Command not found" -#~ msgstr "E371: ใณใใณใใใใใพใใ" - -#~ msgid "" -#~ "VIMRUN.EXE not found in your $PATH.\n" -#~ "External commands will not pause after completion.\n" -#~ "See :help win32-vimrun for more information." -#~ msgstr "" -#~ "VIMRUN.EXEใ $PATH ใฎไธญใซ่ฆใคใใใพใใ.\n" -#~ "ๅค้จใณใใณใใฎ็ตไบๅพใซไธๆๅๆญขใใใพใใ.\n" -#~ "่ฉณ็ดฐใฏ :help win32-vimrun ใๅ็
งใใฆใใ ใใ." - -#~ msgid "Vim Warning" -#~ msgstr "Vimใฎ่ญฆๅ" - -#~ msgid "Error file" -#~ msgstr "ใจใฉใผใใกใคใซ" - -#~ msgid "E868: Error building NFA with equivalence class!" -#~ msgstr "E868: ็ญไพกใฏใฉในใๅซใNFAๆง็ฏใซๅคฑๆใใพใใ!" - -#~ msgid "E878: (NFA) Could not allocate memory for branch traversal!" -#~ msgstr "E878: (NFA) ็พๅจๆจชๆญไธญใฎใใฉใณใใซๅๅใชใกใขใชใๅฒใๅฝใฆใใใพใใ!" - -#~ msgid "Warning: Cannot find word list \"%s_%s.spl\" or \"%s_ascii.spl\"" -#~ msgstr "" -#~ "่ญฆๅ: ๅ่ชใชในใ \"%s_%s.spl\" ใใใณ \"%s_ascii.spl\" ใฏ่ฆใคใใใพใใ" - -#~ msgid "Conversion in %s not supported" -#~ msgstr "%s ๅ
ใฎๅคๆใฏใตใใผใใใใฆใใพใใ" - -#~ msgid "E845: Insufficient memory, word list will be incomplete" -#~ msgstr "E845: ใกใขใชใ่ถณใใชใใฎใงใๅ่ชใชในใใฏไธๅฎๅ
จใงใ" - -#~ msgid "E430: Tag file path truncated for %s\n" -#~ msgstr "E430: ใฟใฐใใกใคใซใฎใในใ %s ใซๅใๆจใฆใใใพใใ\n" - -#~ msgid "new shell started\n" -#~ msgstr "ๆฐใใใทใงใซใ่ตทๅใใพใ\n" - -#~ msgid "Used CUT_BUFFER0 instead of empty selection" -#~ msgstr "็ฉบใฎ้ธๆ้ ๅใฎใใใใซCUT_BUFFER0ใไฝฟ็จใใใพใใ" - -#~ msgid "No undo possible; continue anyway" -#~ msgstr "ๅฏ่ฝใชใขใณใใฅใฏใใใพใใ: ใจใใใใ็ถใใพใ" - -#~ msgid "E832: Non-encrypted file has encrypted undo file: %s" -#~ msgstr "" -#~ "E832: ้ๆๅทๅใใกใคใซใๆๅทๅใใใใขใณใใฅใใกใคใซใไฝฟใฃใฆใพใ: %s" - -#~ msgid "E826: Undo file decryption failed: %s" -#~ msgstr "E826: ๆๅทๅใใใใขใณใใฅใใกใคใซใฎ่งฃ่ชญใซๅคฑๆใใพใใ: %s" - -#~ msgid "E827: Undo file is encrypted: %s" -#~ msgstr "E827: ใขใณใใฅใใกใคใซใๆๅทๅใใใฆใใพใ: %s" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 16/32-bit GUI version" -#~ msgstr "" -#~ "\n" -#~ "MS-Windows 16/32 ใใใ GUI ็" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 64-bit GUI version" -#~ msgstr "" -#~ "\n" -#~ "MS-Windows 64 ใใใ GUI ็" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 32-bit GUI version" -#~ msgstr "" -#~ "\n" -#~ "MS-Windows 32 ใใใ GUI ็" - -#~ msgid " in Win32s mode" -#~ msgstr " in Win32s ใขใผใ" - -#~ msgid " with OLE support" -#~ msgstr " with OLE ใตใใผใ" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 64-bit console version" -#~ msgstr "" -#~ "\n" -#~ "MS-Windows 64 ใใใ ใณใณใฝใผใซ ็" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 32-bit console version" -#~ msgstr "" -#~ "\n" -#~ "MS-Windows 32 ใใใ ใณใณใฝใผใซ ็" - -#~ msgid "" -#~ "\n" -#~ "MS-Windows 16-bit version" -#~ msgstr "" -#~ "\n" -#~ "MS-Windows 16 ใใใ ็" - -#~ msgid "" -#~ "\n" -#~ "32-bit MS-DOS version" -#~ msgstr "" -#~ "\n" -#~ "32 ใใใ MS-DOS ็" - -#~ msgid "" -#~ "\n" -#~ "16-bit MS-DOS version" -#~ msgstr "" -#~ "\n" -#~ "16 ใใใ MS-DOS ็" - -#~ msgid "" -#~ "\n" -#~ "MacOS X (unix) version" -#~ msgstr "" -#~ "\n" -#~ "MacOS X (unix) ็" - -#~ msgid "" -#~ "\n" -#~ "MacOS X version" -#~ msgstr "" -#~ "\n" -#~ "MacOS X ็" - -#~ msgid "" -#~ "\n" -#~ "MacOS version" -#~ msgstr "" -#~ "\n" -#~ "MacOS ็" - -#~ msgid "" -#~ "\n" -#~ "OpenVMS version" -#~ msgstr "" -#~ "\n" -#~ "OpenVMS ็" - -#~ msgid "" -#~ "\n" -#~ "Big version " -#~ msgstr "" -#~ "\n" -#~ "Big ็ " - -#~ msgid "" -#~ "\n" -#~ "Normal version " -#~ msgstr "" -#~ "\n" -#~ "้ๅธธ ็ " - -#~ msgid "" -#~ "\n" -#~ "Small version " -#~ msgstr "" -#~ "\n" -#~ "Small ็ " - -#~ msgid "" -#~ "\n" -#~ "Tiny version " -#~ msgstr "" -#~ "\n" -#~ "Tiny ็ " - -#~ msgid "with GTK2-GNOME GUI." -#~ msgstr "with GTK2-GNOME GUI." +#, c-format +msgid "E118: Too many arguments for function: %s" +msgstr "E118: ้ขๆฐใฎๅผๆฐใๅค้ใใพใ: %s" -#~ msgid "with GTK2 GUI." -#~ msgstr "with GTK2 GUI." +#, c-format +msgid "E716: Key not present in Dictionary: %s" +msgstr "E716: ่พๆธๅใซใญใผใๅญๅจใใพใใ: %s" -#~ msgid "with X11-Motif GUI." -#~ msgstr "with X11-Motif GUI." +msgid "E714: List required" +msgstr "E714: ใชในใๅใๅฟ
่ฆใงใ" -#~ msgid "with X11-neXtaw GUI." -#~ msgstr "with X11-neXtaw GUI." +#, c-format +msgid "E712: Argument of %s must be a List or Dictionary" +msgstr "E712: %s ใฎๅผๆฐใฏใชในใๅใพใใฏ่พๆธๅใงใชใใใฐใชใใพใใ" -#~ msgid "with X11-Athena GUI." -#~ msgstr "with X11-Athena GUI." +msgid "E47: Error while reading errorfile" +msgstr "E47: ใจใฉใผใใกใคใซใฎ่ชญ่พผไธญใซใจใฉใผใ็บ็ใใพใใ" -#~ msgid "with Photon GUI." -#~ msgstr "with Photon GUI." +msgid "E48: Not allowed in sandbox" +msgstr "E48: ใตใณใใใใฏในใงใฏ่จฑใใใพใใ" -#~ msgid "with GUI." -#~ msgstr "with GUI." +msgid "E523: Not allowed here" +msgstr "E523: ใใใงใฏ่จฑๅฏใใใพใใ" -#~ msgid "with Carbon GUI." -#~ msgstr "with Carbon GUI." +msgid "E359: Screen mode setting not supported" +msgstr "E359: ในใฏใชใผใณใขใผใใฎ่จญๅฎใซใฏๅฏพๅฟใใฆใใพใใ" -#~ msgid "with Cocoa GUI." -#~ msgstr "with Cocoa GUI." +msgid "E49: Invalid scroll size" +msgstr "E49: ็กๅนใชในใฏใญใผใซ้ใงใ" -#~ msgid "with (classic) GUI." -#~ msgstr "with (ใฏใฉใทใใฏ) GUI." +msgid "E91: 'shell' option is empty" +msgstr "E91: 'shell' ใชใใทใงใณใ็ฉบใงใ" -#~ msgid " system gvimrc file: \"" -#~ msgstr " ใทในใใ gvimrc: \"" +msgid "E255: Couldn't read in sign data!" +msgstr "E255: sign ใฎใใผใฟใ่ชญ่พผใใพใใใงใใ" -#~ msgid " user gvimrc file: \"" -#~ msgstr " ใฆใผใถ gvimrc: \"" +msgid "E72: Close error on swap file" +msgstr "E72: ในใฏใใใใกใคใซใฎใฏใญใผใบๆใจใฉใผใงใ" -#~ msgid "2nd user gvimrc file: \"" -#~ msgstr " ็ฌฌ2ใฆใผใถ gvimrc: \"" +msgid "E73: tag stack empty" +msgstr "E73: ใฟใฐในใฟใใฏใ็ฉบใงใ" -#~ msgid "3rd user gvimrc file: \"" -#~ msgstr " ็ฌฌ3ใฆใผใถ gvimrc: \"" +msgid "E74: Command too complex" +msgstr "E74: ใณใใณใใ่ค้้ใใพใ" -#~ msgid " system menu file: \"" -#~ msgstr " ใทในใใ ใกใใฅใผ: \"" +msgid "E75: Name too long" +msgstr "E75: ๅๅใ้ท้ใใพใ" -#~ msgid "Compiler: " -#~ msgstr "ใณใณใใคใฉ: " +msgid "E76: Too many [" +msgstr "E76: [ ใๅค้ใใพใ" -#~ msgid "menu Help->Orphans for information " -#~ msgstr "่ฉณ็ดฐใฏใกใใฅใผใฎ ใใซใโๅญคๅ
ใๅ็
งใใฆไธใใ " +msgid "E77: Too many file names" +msgstr "E77: ใใกใคใซๅใๅค้ใใพใ" -#~ msgid "Running modeless, typed text is inserted" -#~ msgstr "ใขใผใ็กใงๅฎ่กไธญ, ใฟใคใใใๆๅญใๆฟๅ
ฅใใใพใ" +msgid "E488: Trailing characters" +msgstr "E488: ไฝๅใชๆๅญใๅพใใซใใใพใ" -#~ msgid "menu Edit->Global Settings->Toggle Insert Mode " -#~ msgstr "ใกใใฅใผใฎ ็ทจ้โๅ
จไฝ่จญๅฎโๆฟๅ
ฅ(ๅๅฟ่
)ใขใผใๅๆฟ " +msgid "E78: Unknown mark" +msgstr "E78: ๆช็ฅใฎใใผใฏ" -#~ msgid " for two modes " -#~ msgstr " ใงใขใผใๆใซ " +msgid "E79: Cannot expand wildcards" +msgstr "E79: ใฏใคใซใใซใผใใๅฑ้ใงใใพใใ" -#~ msgid "menu Edit->Global Settings->Toggle Vi Compatible" -#~ msgstr "ใกใใฅใผใฎ ็ทจ้โๅ
จไฝ่จญๅฎโViไบๆใขใผใๅๆฟ " +msgid "E591: 'winheight' cannot be smaller than 'winminheight'" +msgstr "E591: 'winheight' ใฏ 'winminheight' ใใๅฐใใใงใใพใใ" -#~ msgid " for Vim defaults " -#~ msgstr " ใงVimใจใใฆๅไฝ " +msgid "E592: 'winwidth' cannot be smaller than 'winminwidth'" +msgstr "E592: 'winwidth' ใฏ 'winminwidth' ใใๅฐใใใงใใพใใ" -#~ msgid "WARNING: Windows 95/98/ME detected" -#~ msgstr " ่ญฆๅ: Windows 95/98/Me ใๆคๅบ " +msgid "E80: Error while writing" +msgstr "E80: ๆธ่พผใฟไธญใฎใจใฉใผ" -#~ msgid "type :help windows95<Enter> for info on this" -#~ msgstr " ่ฉณ็ดฐใชๆ
ๅ ฑใฏ :help windows95<Enter> " +msgid "Zero count" +msgstr "ใผใญใซใฆใณใ" -#~ msgid "Edit with &multiple Vims" -#~ msgstr "่คๆฐใฎVimใง็ทจ้ใใ (&M)" +msgid "E81: Using <SID> not in a script context" +msgstr "E81: ในใฏใชใใไปฅๅคใง<SID>ใไฝฟใใใพใใ" -#~ msgid "Edit with single &Vim" -#~ msgstr "1ใคใฎVimใง็ทจ้ใใ (&V)" +msgid "E449: Invalid expression received" +msgstr "E449: ็กๅนใชๅผใๅใๅใใพใใ" -#~ msgid "Diff with Vim" -#~ msgstr "Vimใงๅทฎๅใ่กจ็คบใใ" +msgid "E463: Region is guarded, cannot modify" +msgstr "E463: ้ ๅใไฟ่ญทใใใฆใใใฎใง, ๅคๆดใงใใพใใ" -#~ msgid "Edit with &Vim" -#~ msgstr "Vimใง็ทจ้ใใ (&V)" +msgid "E744: NetBeans does not allow changes in read-only files" +msgstr "E744: NetBeans ใฏ่ชญ่พผๅฐ็จใใกใคใซใๅคๆดใใใใจใ่จฑใใพใใ" -#~ msgid "Edit with existing Vim - " -#~ msgstr "่ตทๅๆธใฎVimใง็ทจ้ใใ - " +#, c-format +msgid "E685: Internal error: %s" +msgstr "E685: ๅ
้จใจใฉใผใงใ: %s" -#~ msgid "Edits the selected file(s) with Vim" -#~ msgstr "้ธๆใใใใกใคใซใVimใง็ทจ้ใใ" +msgid "E363: pattern uses more memory than 'maxmempattern'" +msgstr "E363: ใใฟใผใณใ 'maxmempattern' ไปฅไธใฎใกใขใชใไฝฟ็จใใพใ" -#~ msgid "Error creating process: Check if gvim is in your path!" -#~ msgstr "ใใญใปในใฎไฝๆใซๅคฑๆ: gvimใ็ฐๅขๅคๆฐPATHไธใซใใใ็ขบ่ชใใฆใใ ใใ!" +msgid "E749: empty buffer" +msgstr "E749: ใใใใกใ็ฉบใงใ" -#~ msgid "gvimext.dll error" -#~ msgstr "gvimext.dll ใจใฉใผ" +#, c-format +msgid "E86: Buffer %ld does not exist" +msgstr "E86: ใใใใก %ld ใฏใใใพใใ" -#~ msgid "Path length too long!" -#~ msgstr "ใในใ้ทใใใพใ!" +msgid "E682: Invalid search pattern or delimiter" +msgstr "E682: ๆค็ดขใใฟใผใณใๅบๅใ่จๅทใไธๆญฃใงใ" -#~ msgid "E234: Unknown fontset: %s" -#~ msgstr "E234: ๆช็ฅใฎใใฉใณใใปใใ: %s" +msgid "E139: File is loaded in another buffer" +msgstr "E139: ๅใๅๅใฎใใกใคใซใไปใฎใใใใกใง่ชญ่พผใพใใฆใใพใ" -#~ msgid "E235: Unknown font: %s" -#~ msgstr "E235: ๆช็ฅใฎใใฉใณใ: %s" +#, c-format +msgid "E764: Option '%s' is not set" +msgstr "E764: ใชใใทใงใณ '%s' ใฏ่จญๅฎใใใฆใใพใใ" -#~ msgid "E236: Font \"%s\" is not fixed-width" -#~ msgstr "E236: ใใฉใณใ \"%s\" ใฏๅบๅฎๅน
ใงใฏใใใพใใ" +msgid "E850: Invalid register name" +msgstr "E850: ็กๅนใชใฌใธในใฟๅใงใ" -#~ msgid "E448: Could not load library function %s" -#~ msgstr "E448: ใฉใคใใฉใชใฎ้ขๆฐ %s ใใญใผใใงใใพใใใงใใ" +#, c-format +msgid "E919: Directory not found in '%s': \"%s\"" +msgstr "E919: ใใฃใฌใฏใใชใ '%s' ใฎไธญใซใใใพใใ: \"%s\"" -#~ msgid "E26: Hebrew cannot be used: Not enabled at compile time\n" -#~ msgstr "E26: ใใใฉใค่ชใฏไฝฟ็จไธๅฏ่ฝใงใ: ใณใณใใคใซๆใซ็กๅนใซใใใฆใใพใ\n" +msgid "search hit TOP, continuing at BOTTOM" +msgstr "ไธใพใงๆค็ดขใใใฎใงไธใซๆปใใพใ" -#~ msgid "E27: Farsi cannot be used: Not enabled at compile time\n" -#~ msgstr "E27: ใใซใทใข่ชใฏไฝฟ็จไธๅฏ่ฝใงใ: ใณใณใใคใซๆใซ็กๅนใซใใใฆใใพใ\n" +msgid "search hit BOTTOM, continuing at TOP" +msgstr "ไธใพใงๆค็ดขใใใฎใงไธใซๆปใใพใ" -#~ msgid "E800: Arabic cannot be used: Not enabled at compile time\n" -#~ msgstr "" -#~ "E800: ใขใฉใใข่ชใฏไฝฟ็จไธๅฏ่ฝใงใ: ใณใณใใคใซๆใซ็กๅนใซใใใฆใใพใ\n" +#, c-format +msgid "Need encryption key for \"%s\"" +msgstr "ๆๅทใญใผใๅฟ
่ฆใงใ: \"%s\"" -#~ msgid "E247: no registered server named \"%s\"" -#~ msgstr "E247: %s ใจใใๅๅใฎ็ป้ฒใใใใตใผใใฏใใใพใใ" +msgid "empty keys are not allowed" +msgstr "็ฉบใฎใญใผใฏ่จฑๅฏใใใฆใใพใใ" -#~ msgid "E233: cannot open display" -#~ msgstr "E233: ใใฃในใใฌใคใ้ใใพใใ" +msgid "dictionary is locked" +msgstr "่พๆธใฏใญใใฏใใใฆใใพใ" -#~ msgid "E449: Invalid expression received" -#~ msgstr "E449: ็กๅนใชๅผใๅใๅใใพใใ" +msgid "list is locked" +msgstr "ใชในใใฏใญใใฏใใใฆใใพใ" -#~ msgid "E463: Region is guarded, cannot modify" -#~ msgstr "E463: ้ ๅใไฟ่ญทใใใฆใใใฎใง, ๅคๆดใงใใพใใ" +#, c-format +msgid "failed to add key '%s' to dictionary" +msgstr "่พๆธใซใญใผ '%s' ใ่ฟฝๅ ใใใฎใซๅคฑๆใใพใใ" -#~ msgid "E744: NetBeans does not allow changes in read-only files" -#~ msgstr "E744: NetBeans ใฏ่ชญ่พผๅฐ็จใใกใคใซใๅคๆดใใใใจใ่จฑใใพใใ" +#, c-format +msgid "index must be int or slice, not %s" +msgstr "ใคใณใใใฏในใฏ %s ใงใฏใชใๆดๆฐใในใฉใคในใซใใฆใใ ใใ" -#~ msgid "Need encryption key for \"%s\"" -#~ msgstr "ๆๅทใญใผใๅฟ
่ฆใงใ: \"%s\"" +#, c-format +msgid "expected str() or unicode() instance, but got %s" +msgstr "str() ใใใใฏ unicode() ใฎใคใณในใฟใณในใๆๅพ
ใใใฆใใใฎใซ %s ใงใใ" -#~ msgid "empty keys are not allowed" -#~ msgstr "็ฉบใฎใญใผใฏ่จฑๅฏใใใฆใใพใใ" +#, c-format +msgid "expected bytes() or str() instance, but got %s" +msgstr "bytes() ใใใใฏ str() ใฎใคใณในใฟใณในใๆๅพ
ใใใฆใใใฎใซ %s ใงใใ" -#~ msgid "dictionary is locked" -#~ msgstr "่พๆธใฏใญใใฏใใใฆใใพใ" +#, c-format +msgid "" +"expected int(), long() or something supporting coercing to long(), but got %s" +msgstr "long() ใใใใธๅคๆๅฏ่ฝใชใใฎใๆๅพ
ใใใฆใใใฎใซ %s ใงใใ" -#~ msgid "list is locked" -#~ msgstr "ใชในใใฏใญใใฏใใใฆใใพใ" +#, c-format +msgid "expected int() or something supporting coercing to int(), but got %s" +msgstr "int() ใใใใธๅคๆๅฏ่ฝใชใใฎใๆๅพ
ใใใฆใใใฎใซ %s ใงใใ" -#~ msgid "failed to add key '%s' to dictionary" -#~ msgstr "่พๆธใซใญใผ '%s' ใ่ฟฝๅ ใใใฎใซๅคฑๆใใพใใ" +msgid "value is too large to fit into C int type" +msgstr "C่จ่ชใฎ int ๅใจใใฆใฏๅคใๅคงใ้ใใพใ" -#~ msgid "index must be int or slice, not %s" -#~ msgstr "ใคใณใใใฏในใฏ %s ใงใฏใชใๆดๆฐใในใฉใคในใซใใฆใใ ใใ" +msgid "value is too small to fit into C int type" +msgstr "C่จ่ชใฎ int ๅใจใใฆใฏๅคใๅฐใ้ใใพใ" -#~ msgid "expected str() or unicode() instance, but got %s" -#~ msgstr "" -#~ "str() ใใใใฏ unicode() ใฎใคใณในใฟใณในใๆๅพ
ใใใฆใใใฎใซ %s ใงใใ" +msgid "number must be greater than zero" +msgstr "ๆฐๅคใฏ 0 ใใๅคงใใใชใใใฐใชใใพใใ" -#~ msgid "expected bytes() or str() instance, but got %s" -#~ msgstr "bytes() ใใใใฏ str() ใฎใคใณในใฟใณในใๆๅพ
ใใใฆใใใฎใซ %s ใงใใ" +msgid "number must be greater or equal to zero" +msgstr "ๆฐๅคใฏ 0 ใใใไปฅไธใงใชใใใฐใชใใพใใ" -#~ msgid "" -#~ "expected int(), long() or something supporting coercing to long(), but " -#~ "got %s" -#~ msgstr "long() ใใใใธๅคๆๅฏ่ฝใชใใฎใๆๅพ
ใใใฆใใใฎใซ %s ใงใใ" +msgid "can't delete OutputObject attributes" +msgstr "OutputObjectๅฑๆงใๆถใใพใใ" -#~ msgid "expected int() or something supporting coercing to int(), but got %s" -#~ msgstr "int() ใใใใธๅคๆๅฏ่ฝใชใใฎใๆๅพ
ใใใฆใใใฎใซ %s ใงใใ" +#, c-format +msgid "invalid attribute: %s" +msgstr "็กๅนใชๅฑๆงใงใ: %s" -#~ msgid "value is too large to fit into C int type" -#~ msgstr "C่จ่ชใฎ int ๅใจใใฆใฏๅคใๅคงใ้ใใพใ" +msgid "E264: Python: Error initialising I/O objects" +msgstr "E264: Python: I/Oใชใใธใงใฏใใฎๅๆๅใจใฉใผ" -#~ msgid "value is too small to fit into C int type" -#~ msgstr "C่จ่ชใฎ int ๅใจใใฆใฏๅคใๅฐใ้ใใพใ" +msgid "failed to change directory" +msgstr "่พๆธใฎๅคๆดใซๅคฑๆใใพใใ" -#~ msgid "number must be greater then zero" -#~ msgstr "ๆฐๅคใฏ 0 ใใๅคงใใใชใใใฐใชใใพใใ" +#, c-format +msgid "expected 3-tuple as imp.find_module() result, but got %s" +msgstr "imp.find_module() ใ %s ใ่ฟใใพใใ (ๆๅพ
ๅค: 3 ่ฆ็ด ใฎใฟใใซ)" -#~ msgid "number must be greater or equal to zero" -#~ msgstr "ๆฐๅคใฏ 0 ใใใไปฅไธใงใชใใใฐใชใใพใใ" +#, c-format +msgid "expected 3-tuple as imp.find_module() result, but got tuple of size %d" +msgstr "imp.find_module() ใ %d ่ฆ็ด ใฎใฟใใซใ่ฟใใพใใ (ๆๅพ
ๅค: 3)" -#~ msgid "can't delete OutputObject attributes" -#~ msgstr "OutputObjectๅฑๆงใๆถใใพใใ" +msgid "internal error: imp.find_module returned tuple with NULL" +msgstr "ๅ
้จใจใฉใผ: imp.find_module ใ NULL ใๅซใใฟใใซใ่ฟใใพใใ" -#~ msgid "invalid attribute: %s" -#~ msgstr "็กๅนใชๅฑๆงใงใ: %s" +msgid "cannot delete vim.Dictionary attributes" +msgstr "vim.Dictionaryๅฑๆงใฏๆถใใพใใ" -#~ msgid "E264: Python: Error initialising I/O objects" -#~ msgstr "E264: Python: I/Oใชใใธใงใฏใใฎๅๆๅใจใฉใผ" +msgid "cannot modify fixed dictionary" +msgstr "ๅบๅฎใใใ่พๆธใฏๅคๆดใงใใพใใ" -#~ msgid "failed to change directory" -#~ msgstr "่พๆธใฎๅคๆดใซๅคฑๆใใพใใ" +#, c-format +msgid "cannot set attribute %s" +msgstr "ๅฑๆง %s ใฏ่จญๅฎใงใใพใใ" -#~ msgid "expected 3-tuple as imp.find_module() result, but got %s" -#~ msgstr "imp.find_module() ใ %s ใ่ฟใใพใใ (ๆๅพ
ๅค: 2 ่ฆ็ด ใฎใฟใใซ)" +msgid "hashtab changed during iteration" +msgstr "ใคใใฌใผใทใงใณไธญใซ hashtab ใๅคๆดใใใพใใ" -#~ msgid "" -#~ "expected 3-tuple as imp.find_module() result, but got tuple of size %d" -#~ msgstr "impl.find_module() ใ %d ่ฆ็ด ใฎใฟใใซใ่ฟใใพใใ (ๆๅพ
ๅค: 2)" +#, c-format +msgid "expected sequence element of size 2, but got sequence of size %d" +msgstr "ใทใผใฑใณในใฎ่ฆ็ด ๆฐใซใฏ 2 ใๆๅพ
ใใใฆใใพใใใ %d ใงใใ" -#~ msgid "internal error: imp.find_module returned tuple with NULL" -#~ msgstr "ๅ
้จใจใฉใผ: imp.find_module ใ NULL ใๅซใใฟใใซใ่ฟใใพใใ" +msgid "list constructor does not accept keyword arguments" +msgstr "ใชในใใฎใณใณในใใฉใฏใฟใฏใญใผใฏใผใๅผๆฐใๅใไปใใพใใ" -#~ msgid "cannot delete vim.Dictionary attributes" -#~ msgstr "vim.Dictionaryๅฑๆงใฏๆถใใพใใ" +msgid "list index out of range" +msgstr "ใชในใ็ฏๅฒๅคใฎใคใณใใใฏในใงใ" -#~ msgid "cannot modify fixed dictionary" -#~ msgstr "ๅบๅฎใใใ่พๆธใฏๅคๆดใงใใพใใ" +#. No more suitable format specifications in python-2.3 +#, c-format +msgid "internal error: failed to get vim list item %d" +msgstr "ๅ
้จใจใฉใผ: vimใฎใชในใ่ฆ็ด %d ใฎๅๅพใซๅคฑๆใใพใใ" -#~ msgid "cannot set attribute %s" -#~ msgstr "ๅฑๆง %s ใฏ่จญๅฎใงใใพใใ" +msgid "slice step cannot be zero" +msgstr "ในใฉใคในใฎในใใใใซ 0 ใฏๆๅฎใงใใพใใ" -#~ msgid "hashtab changed during iteration" -#~ msgstr "ใคใใฌใผใทใงใณไธญใซ hashtab ใๅคๆดใใใพใใ" +#, c-format +msgid "attempt to assign sequence of size greater than %d to extended slice" +msgstr "้ทใ %d ใฎๆกๅผตในใฉใคในใซใใใ้ทใในใฉใคในใๅฒใๅฝใฆใใใจใใพใใ" -#~ msgid "expected sequence element of size 2, but got sequence of size %d" -#~ msgstr "ใทใผใฑใณในใฎ่ฆ็ด ๆฐใซใฏ 2 ใๆๅพ
ใใใฆใใพใใใ %d ใงใใ" +#, c-format +msgid "internal error: no vim list item %d" +msgstr "ๅ
้จใจใฉใผ: vimใฎใชในใ่ฆ็ด %d ใฏใใใพใใ" -#~ msgid "list constructor does not accept keyword arguments" -#~ msgstr "ใชในใใฎใณใณในใใฉใฏใฟใฏใญใผใฏใผใๅผๆฐใๅใไปใใพใใ" +msgid "internal error: not enough list items" +msgstr "ๅ
้จใจใฉใผ: ใชในใใซๅๅใช่ฆ็ด ใใใใพใใ" -#~ msgid "list index out of range" -#~ msgstr "ใชในใ็ฏๅฒๅคใฎใคใณใใใฏในใงใ" +msgid "internal error: failed to add item to list" +msgstr "ๅ
้จใจใฉใผ: ใชในใใธใฎ่ฆ็ด ่ฟฝๅ ใซๅคฑๆใใพใใ" -#~ msgid "internal error: failed to get vim list item %d" -#~ msgstr "ๅ
้จใจใฉใผ: vimใฎใชในใ่ฆ็ด %d ใฎๅๅพใซๅคฑๆใใพใใ" +#, c-format +msgid "attempt to assign sequence of size %d to extended slice of size %d" +msgstr "้ทใ %d ใฎในใฉใคในใ %d ใฎๆกๅผตในใฉใคในใซๅฒใๅฝใฆใใใจใใพใใ" -#~ msgid "failed to add item to list" -#~ msgstr "ใชในใใธใฎ่ฆ็ด ่ฟฝๅ ใซๅคฑๆใใพใใ" +msgid "failed to add item to list" +msgstr "ใชในใใธใฎ่ฆ็ด ่ฟฝๅ ใซๅคฑๆใใพใใ" -#~ msgid "internal error: no vim list item %d" -#~ msgstr "ๅ
้จใจใฉใผ: vimใฎใชในใ่ฆ็ด %d ใฏใใใพใใ" +msgid "cannot delete vim.List attributes" +msgstr "vim.List ๅฑๆงใฏๆถใใพใใ" -#~ msgid "internal error: failed to add item to list" -#~ msgstr "ๅ
้จใจใฉใผ: ใชในใใธใฎ่ฆ็ด ่ฟฝๅ ใซๅคฑๆใใพใใ" +msgid "cannot modify fixed list" +msgstr "ๅบๅฎใใใใชในใใฏๅคๆดใงใใพใใ" -#~ msgid "cannot delete vim.List attributes" -#~ msgstr "vim.List ๅฑๆงใฏๆถใใพใใ" +#, c-format +msgid "unnamed function %s does not exist" +msgstr "็กๅ้ขๆฐ %s ใฏๅญๅจใใพใใ" -#~ msgid "cannot modify fixed list" -#~ msgstr "ๅบๅฎใใใใชในใใฏๅคๆดใงใใพใใ" +#, c-format +msgid "function %s does not exist" +msgstr "้ขๆฐ %s ใใใใพใใ" -#~ msgid "unnamed function %s does not exist" -#~ msgstr "็กๅ้ขๆฐ %s ใฏๅญๅจใใพใใ" +#, c-format +msgid "failed to run function %s" +msgstr "้ขๆฐ %s ใฎๅฎ่กใซๅคฑๆใใพใใ" -#~ msgid "function %s does not exist" -#~ msgstr "้ขๆฐ %s ใใใใพใใ" +msgid "unable to get option value" +msgstr "ใชใใทใงใณใฎๅคใฏๅๅพใงใใพใใ" -#~ msgid "function constructor does not accept keyword arguments" -#~ msgstr "้ขๆฐใฎใณใณในใใฉใฏใฟใฏใญใผใฏใผใๅผๆฐใๅใไปใใพใใ" +msgid "internal error: unknown option type" +msgstr "ๅ
้จใจใฉใผ: ๆช็ฅใฎใชใใทใงใณๅใงใ" -#~ msgid "failed to run function %s" -#~ msgstr "้ขๆฐ %s ใฎๅฎ่กใซๅคฑๆใใพใใ" +msgid "problem while switching windows" +msgstr "ใฆใฃใณใใฆใๅๆไธญใซๅ้กใ็บ็ใใพใใ" -#~ msgid "problem while switching windows" -#~ msgstr "ใฆใฃใณใใฆใๅๆไธญใซๅ้กใ็บ็ใใพใใ" +#, c-format +msgid "unable to unset global option %s" +msgstr "ใฐใญใผใใซใชใใทใงใณ %s ใฎ่จญๅฎ่งฃ้คใฏใงใใพใใ" -#~ msgid "unable to unset global option %s" -#~ msgstr "ใฐใญใผใใซใชใใทใงใณ %s ใฎ่จญๅฎ่งฃ้คใฏใงใใพใใ" +#, c-format +msgid "unable to unset option %s which does not have global value" +msgstr "ใฐใญใผใใซใชๅคใฎ็กใใชใใทใงใณ %s ใฎ่จญๅฎ่งฃ้คใฏใงใใพใใ" -#~ msgid "unable to unset option %s which does not have global value" -#~ msgstr "ใฐใญใผใใซใชๅคใฎ็กใใชใใทใงใณ %s ใฎ่จญๅฎ่งฃ้คใฏใงใใพใใ" +msgid "attempt to refer to deleted tab page" +msgstr "ๅ้คใใใใฟใใๅ็
งใใใใจใใพใใ" -#~ msgid "attempt to refer to deleted tab page" -#~ msgstr "ๅ้คใใใใฟใใๅ็
งใใใใจใใพใใ" +msgid "no such tab page" +msgstr "ใใฎใใใชใฟใใใผใธใฏใใใพใใ" -#~ msgid "no such tab page" -#~ msgstr "ใใฎใใใชใฟใใใผใธใฏใใใพใใ" +msgid "attempt to refer to deleted window" +msgstr "ๅ้คใใใใฆใฃใณใใฆใๅ็
งใใใใจใใพใใ" -#~ msgid "attempt to refer to deleted window" -#~ msgstr "ๅ้คใใใใฆใฃใณใใฆใๅ็
งใใใใจใใพใใ" +msgid "readonly attribute: buffer" +msgstr "่ชญ่พผๅฐ็จๅฑๆง: ใใใใกใผ" -#~ msgid "readonly attribute: buffer" -#~ msgstr "่ชญ่พผๅฐ็จๅฑๆง: ใใใใกใผ" +msgid "cursor position outside buffer" +msgstr "ใซใผใฝใซไฝ็ฝฎใใใใใกใฎๅคๅดใงใ" -#~ msgid "cursor position outside buffer" -#~ msgstr "ใซใผใฝใซไฝ็ฝฎใใใใใกใฎๅคๅดใงใ" +msgid "no such window" +msgstr "ใใฎใใใชใฆใฃใณใใฆใฏใใใพใใ" -#~ msgid "no such window" -#~ msgstr "ใใฎใใใชใฆใฃใณใใฆใฏใใใพใใ" +msgid "attempt to refer to deleted buffer" +msgstr "ๅ้คใใใใใใใกใๅ็
งใใใใจใใพใใ" -#~ msgid "attempt to refer to deleted buffer" -#~ msgstr "ๅ้คใใใใใใใกใๅ็
งใใใใจใใพใใ" +msgid "failed to rename buffer" +msgstr "ใใใใกๅใฎๅคๆดใซๅคฑๆใใพใใ" -#~ msgid "failed to rename buffer" -#~ msgstr "ใใใใกๅใฎๅคๆดใซๅคฑๆใใพใใ" +msgid "mark name must be a single character" +msgstr "ใใผใฏๅใฏ1ๆๅญใฎใขใซใใกใใใใงใชใใใฐใชใใพใใ" -#~ msgid "mark name must be a single character" -#~ msgstr "ใใผใฏๅใฏ1ๆๅญใฎใขใซใใกใใใใงใชใใใฐใชใใพใใ" +#, c-format +msgid "expected vim.Buffer object, but got %s" +msgstr "vim.Bufferใชใใธใงใฏใใๆๅพ
ใใใฆใใใฎใซ %s ใงใใ" -#~ msgid "expected vim.Buffer object, but got %s" -#~ msgstr "vim.Bufferใชใใธใงใฏใใๆๅพ
ใใใฆใใใฎใซ %s ใงใใ" +#, c-format +msgid "failed to switch to buffer %d" +msgstr "ๆๅฎใใใใใใใก %d ใธใฎๅใๆฟใใซๅคฑๆใใพใใ" -#~ msgid "failed to switch to buffer %d" -#~ msgstr "ๆๅฎใใใใใใใก %d ใธใฎๅใๆฟใใซๅคฑๆใใพใใ" +#, c-format +msgid "expected vim.Window object, but got %s" +msgstr "vim.Windowใชใใธใงใฏใใๆๅพ
ใใใฆใใใฎใซ %s ใงใใ" -#~ msgid "expected vim.Window object, but got %s" -#~ msgstr "vim.Windowใชใใธใงใฏใใๆๅพ
ใใใฆใใใฎใซ %s ใงใใ" +msgid "failed to find window in the current tab page" +msgstr "็พๅจใฎใฟใใซใฏๆๅฎใใใใฆใฃใณใใฆใใใใพใใใงใใ" -#~ msgid "failed to find window in the current tab page" -#~ msgstr "็พๅจใฎใฟใใซใฏๆๅฎใใใใฆใฃใณใใฆใใใใพใใใงใใ" +msgid "did not switch to the specified window" +msgstr "ๆๅฎใใใใฆใฃใณใใฆใซๅใๆฟใใพใใใงใใ" -#~ msgid "did not switch to the specified window" -#~ msgstr "ๆๅฎใใใใฆใฃใณใใฆใซๅใๆฟใใพใใใงใใ" +#, c-format +msgid "expected vim.TabPage object, but got %s" +msgstr "vim.TabPageใชใใธใงใฏใใๆๅพ
ใใใฆใใใฎใซ %s ใงใใ" -#~ msgid "expected vim.TabPage object, but got %s" -#~ msgstr "vim.TabPageใชใใธใงใฏใใๆๅพ
ใใใฆใใใฎใซ %s ใงใใ" +msgid "did not switch to the specified tab page" +msgstr "ๆๅฎใใใใฟใใใผใธใซๅใๆฟใใพใใใงใใ" -#~ msgid "did not switch to the specified tab page" -#~ msgstr "ๆๅฎใใใใฟใใใผใธใซๅใๆฟใใพใใใงใใ" +msgid "failed to run the code" +msgstr "ใณใผใใฎๅฎ่กใซๅคฑๆใใพใใ" -#~ msgid "failed to run the code" -#~ msgstr "ใณใผใใฎๅฎ่กใซๅคฑๆใใพใใ" +msgid "E858: Eval did not return a valid python object" +msgstr "E858: ๅผ่ฉไพกใฏๆๅนใชpythonใชใใธใงใฏใใ่ฟใใพใใใงใใ" -#~ msgid "E858: Eval did not return a valid python object" -#~ msgstr "E858: ๅผ่ฉไพกใฏๆๅนใชpythonใชใใธใงใฏใใ่ฟใใพใใใงใใ" +msgid "E859: Failed to convert returned python object to vim value" +msgstr "E859: ่ฟใใใpythonใชใใธใงใฏใใvimใฎๅคใซๅคๆใงใใพใใใงใใ" -#~ msgid "E859: Failed to convert returned python object to vim value" -#~ msgstr "E859: ่ฟใใใpythonใชใใธใงใฏใใvimใฎๅคใซๅคๆใงใใพใใใงใใ" +#, c-format +msgid "unable to convert %s to vim dictionary" +msgstr "%s vimใฎ่พๆธๅใซๅคๆใงใใพใใ" -#~ msgid "unable to convert %s to vim dictionary" -#~ msgstr "%s vimใฎ่พๆธๅใซๅคๆใงใใพใใ" +#, c-format +msgid "unable to convert %s to vim list" +msgstr "%s ใvimใฎใชในใใซๅคๆใงใใพใใ" -#~ msgid "unable to convert %s to vim structure" -#~ msgstr "%s ใvimใฎๆง้ ไฝใซๅคๆใงใใพใใ" +#, c-format +msgid "unable to convert %s to vim structure" +msgstr "%s ใvimใฎๆง้ ไฝใซๅคๆใงใใพใใ" -#~ msgid "internal error: NULL reference passed" -#~ msgstr "ๅ
้จใจใฉใผ: NULLๅ็
งใๆธกใใใพใใ" +msgid "internal error: NULL reference passed" +msgstr "ๅ
้จใจใฉใผ: NULLๅ็
งใๆธกใใใพใใ" -#~ msgid "internal error: invalid value type" -#~ msgstr "ๅ
้จใจใฉใผ: ็กๅนใชๅคๅใงใ" +msgid "internal error: invalid value type" +msgstr "ๅ
้จใจใฉใผ: ็กๅนใชๅคๅใงใ" -#~ msgid "" -#~ "Failed to set path hook: sys.path_hooks is not a list\n" -#~ "You should now do the following:\n" -#~ "- append vim.path_hook to sys.path_hooks\n" -#~ "- append vim.VIM_SPECIAL_PATH to sys.path\n" -#~ msgstr "" -#~ "ใในใใใฏใฎ่จญๅฎใซๅคฑๆใใพใใ: sys.path_hooks ใใชในใใงใฏใใใพใใ\n" -#~ "ใใใซไธ่จใๅฎๆฝใใฆใใ ใใ:\n" -#~ "- vim.path_hooks ใ sys.path_hooks ใธ่ฟฝๅ \n" -#~ "- vim.VIM_SPECIAL_PATH ใ sys.path ใธ่ฟฝๅ \n" +msgid "" +"Failed to set path hook: sys.path_hooks is not a list\n" +"You should now do the following:\n" +"- append vim.path_hook to sys.path_hooks\n" +"- append vim.VIM_SPECIAL_PATH to sys.path\n" +msgstr "" +"ใในใใใฏใฎ่จญๅฎใซๅคฑๆใใพใใ: sys.path_hooks ใใชในใใงใฏใใใพใใ\n" +"ใใใซไธ่จใๅฎๆฝใใฆใใ ใใ:\n" +"- vim.path_hooks ใ sys.path_hooks ใธ่ฟฝๅ \n" +"- vim.VIM_SPECIAL_PATH ใ sys.path ใธ่ฟฝๅ \n" -#~ msgid "" -#~ "Failed to set path: sys.path is not a list\n" -#~ "You should now append vim.VIM_SPECIAL_PATH to sys.path" -#~ msgstr "" -#~ "ใในใฎ่จญๅฎใซๅคฑๆใใพใใ: sys.path ใใชในใใงใฏใใใพใใ\n" -#~ "ใใใซ vim.VIM_SPECIAL_PATH ใ sys.path ใซ่ฟฝๅ ใใฆใใ ใใ" +msgid "" +"Failed to set path: sys.path is not a list\n" +"You should now append vim.VIM_SPECIAL_PATH to sys.path" +msgstr "" +"ใในใฎ่จญๅฎใซๅคฑๆใใพใใ: sys.path ใใชในใใงใฏใใใพใใ\n" +"ใใใซ vim.VIM_SPECIAL_PATH ใ sys.path ใซ่ฟฝๅ ใใฆใใ ใใ" diff --git a/src/nvim/po/uk.po b/src/nvim/po/uk.po index cff140508b..2c203f808f 100644 --- a/src/nvim/po/uk.po +++ b/src/nvim/po/uk.po @@ -82,7 +82,7 @@ msgid "Key length is too high" msgstr "ะะพะฒะถะธะฝะฐ ะบะปััะฐ ะทะฐะฒะตะปะธะบะฐ" #, c-format -msgid "Key \"%s\" doesn't exist" +msgid "Key does not exist: %s" msgstr "ะะปัั ยซ%sยป ะฝะต ััะฝัั" msgid "Empty option name" @@ -3719,7 +3719,7 @@ msgid "Calling shell to execute: \"%s\"" msgstr "ะะธะบะปะธะบะฐััััั ะพะฑะพะปะพะฝะบะฐ ัะพะฑ ะฒะธะบะพะฝะฐัะธ: ยซ%sยป" #, c-format -msgid "Invalid channel \"%<PRIu64>\"" +msgid "Invalid channel: %<PRIu64>" msgstr "ะะตะบะพัะตะบัะฝะธะน ะบะฐะฝะฐะป ยซ%<PRIu64>ยป" msgid "Message is not an array" @@ -3734,7 +3734,7 @@ msgstr "ะะพะฒัะดะพะผะปะตะฝะฝั ะผะฐั ะฑััะธ ััะปะธะผ ัะธัะปะพะผ" msgid "Unknown message type" msgstr "ะะตะฒัะดะพะผะธะน ัะธะฟ ะฟะพะฒัะดะพะผะปะตะฝะฝั" -msgid "Request array size should be 4 (request) or 3 (notification)" +msgid "Request array size must be 4 (request) or 3 (notification)" msgstr "ะ ะพะทะผัั ะผะฐัะธะฒั ะทะฐะฟะธัั ะผะฐั ะฑััะธ 4 (ะทะฐะฟะธั) ัะธ 3 (ะฟะพะฒัะดะพะผะปะตะฝะฝั)" msgid "ID must be a positive integer" diff --git a/src/nvim/popupmnu.c b/src/nvim/popupmnu.c index 89180f76de..2462975c9b 100644 --- a/src/nvim/popupmnu.c +++ b/src/nvim/popupmnu.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + /// @file popupmnu.c /// /// Popup menu (PUM) @@ -38,9 +41,7 @@ static int pum_row; // top row of pum static int pum_col; // left column of pum static bool pum_is_visible = false; - static bool pum_external = false; -static bool pum_wants_external = false; #ifdef INCLUDE_GENERATED_DECLARATIONS # include "popupmnu.c.generated.h" @@ -73,12 +74,11 @@ void pum_display(pumitem_T *array, int size, int selected, bool array_changed) int above_row; int below_row; int redo_count = 0; - win_T *pvwin; if (!pum_is_visible) { // To keep the code simple, we only allow changing the // draw mode when the popup menu is not being displayed - pum_external = pum_wants_external; + pum_external = ui_is_external(kUIPopupmenu); } redo: @@ -98,7 +98,6 @@ redo: } if (pum_external) { - Array args = ARRAY_DICT_INIT; if (array_changed) { Array arr = ARRAY_DICT_INIT; for (i = 0; i < size; i++) { @@ -109,14 +108,9 @@ redo: ADD(item, STRING_OBJ(cstr_to_string((char *)array[i].pum_info))); ADD(arr, ARRAY_OBJ(item)); } - ADD(args, ARRAY_OBJ(arr)); - ADD(args, INTEGER_OBJ(selected)); - ADD(args, INTEGER_OBJ(row)); - ADD(args, INTEGER_OBJ(col)); - ui_event("popupmenu_show", args); + ui_call_popupmenu_show(arr, selected, row, col); } else { - ADD(args, INTEGER_OBJ(selected)); - ui_event("popupmenu_select", args); + ui_call_popupmenu_select(selected); } return; } @@ -126,8 +120,10 @@ redo: kind_width = 0; extra_width = 0; - FOR_ALL_WINDOWS(pvwin) { - if (pvwin->w_p_pvw) { + win_T *pvwin = NULL; + FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { + if (wp->w_p_pvw) { + pvwin = wp; break; } } @@ -311,10 +307,10 @@ void pum_redraw(void) { int row = pum_row; int col; - int attr_norm = highlight_attr[HLF_PNI]; - int attr_select = highlight_attr[HLF_PSI]; - int attr_scroll = highlight_attr[HLF_PSB]; - int attr_thumb = highlight_attr[HLF_PST]; + int attr_norm = win_hl_attr(curwin, HLF_PNI); + int attr_select = win_hl_attr(curwin, HLF_PSI); + int attr_scroll = win_hl_attr(curwin, HLF_PSB); + int attr_thumb = win_hl_attr(curwin, HLF_PST); int attr; int i; int idx; @@ -609,13 +605,10 @@ static int pum_set_selected(int n, int repeat) if (res == OK) { // Edit a new, empty buffer. Set options for a "wipeout" // buffer. - set_option_value((char_u *)"swf", 0L, NULL, OPT_LOCAL); - set_option_value((char_u *)"bt", 0L, - (char_u *)"nofile", OPT_LOCAL); - set_option_value((char_u *)"bh", 0L, - (char_u *)"wipe", OPT_LOCAL); - set_option_value((char_u *)"diff", 0L, - NULL, OPT_LOCAL); + set_option_value("swf", 0L, NULL, OPT_LOCAL); + set_option_value("bt", 0L, "nofile", OPT_LOCAL); + set_option_value("bh", 0L, "wipe", OPT_LOCAL); + set_option_value("diff", 0L, NULL, OPT_LOCAL); } } @@ -714,8 +707,7 @@ void pum_undisplay(void) pum_array = NULL; if (pum_external) { - Array args = ARRAY_DICT_INIT; - ui_event("popupmenu_hide", args); + ui_call_popupmenu_hide(); } else { redraw_all_later(SOME_VALID); redraw_tabline = true; @@ -750,8 +742,3 @@ int pum_get_height(void) { return pum_height; } - -void pum_set_external(bool external) -{ - pum_wants_external = external; -} diff --git a/src/nvim/popupmnu.h b/src/nvim/popupmnu.h index 2b181f2c4a..7e1588dbdd 100644 --- a/src/nvim/popupmnu.h +++ b/src/nvim/popupmnu.h @@ -1,6 +1,8 @@ #ifndef NVIM_POPUPMNU_H #define NVIM_POPUPMNU_H +#include "nvim/types.h" + /// Used for popup menu items. typedef struct { char_u *pum_text; // main menu text diff --git a/src/nvim/pos.h b/src/nvim/pos.h index 864f3fe866..966255e6a4 100644 --- a/src/nvim/pos.h +++ b/src/nvim/pos.h @@ -2,6 +2,8 @@ #define NVIM_POS_H typedef long linenr_T; // line number type +/// Format used to print values which have linenr_T type +#define PRIdLINENR "ld" /// Column number type typedef int colnr_T; diff --git a/src/nvim/profile.c b/src/nvim/profile.c index 97d7d77359..8fb8e92add 100644 --- a/src/nvim/profile.c +++ b/src/nvim/profile.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #include <stdio.h> #include <math.h> #include <assert.h> diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index 33a84660c1..e6b1e7b95a 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + /* * quickfix.c: functions for quickfix mode, using a file with error messages */ @@ -137,6 +140,40 @@ struct efm_S { int conthere; /* %> used */ }; +enum { + QF_FAIL = 0, + QF_OK = 1, + QF_END_OF_INPUT = 2, + QF_NOMEM = 3, + QF_IGNORE_LINE = 4 +}; + +typedef struct { + char_u *linebuf; + size_t linelen; + char_u *growbuf; + size_t growbufsiz; + FILE *fd; + typval_T *tv; + char_u *p_str; + listitem_T *p_li; + buf_T *buf; + linenr_T buflnum; + linenr_T lnumlast; +} qfstate_T; + +typedef struct { + char_u *namebuf; + char_u *errmsg; + size_t errmsglen; + long lnum; + int col; + bool use_viscol; + char_u *pattern; + int enr; + char_u type; + bool valid; +} qffields_T; #ifdef INCLUDE_GENERATED_DECLARATIONS # include "quickfix.c.generated.h" @@ -151,6 +188,11 @@ struct efm_S { */ #define GET_LOC_LIST(wp) (IS_LL_WINDOW(wp) ? wp->w_llist_ref : wp->w_llist) +// Looking up a buffer can be slow if there are many. Remember the last one +// to make this a lot faster if there are multiple matches in the same file. +static char_u *qf_last_bufname = NULL; +static bufref_T qf_last_bufref = { NULL, 0, 0 }; + /* * Read the errorfile "efile" into memory, line by line, building the error * list. Set the error list's title to qf_title. @@ -179,22 +221,6 @@ qf_init ( // Maximum number of bytes allowed per line while reading an errorfile. static const size_t LINE_MAXLEN = 4096; -static char_u *qf_grow_linebuf(char_u **growbuf, size_t *growbufsiz, - size_t newsz, size_t *allocsz) -{ - // If the line exceeds LINE_MAXLEN exclude the last - // byte since it's not a NL character. - *allocsz = newsz > LINE_MAXLEN ? LINE_MAXLEN - 1 : newsz; - if (*growbuf == NULL) { - *growbuf = xmalloc(*allocsz + 1); - *growbufsiz = *allocsz; - } else if (*allocsz > *growbufsiz) { - *growbuf = xrealloc(*growbuf, *allocsz + 1); - *growbufsiz = *allocsz; - } - return *growbuf; -} - static struct fmtpattern { char_u convchar; @@ -357,6 +383,8 @@ static int efm_to_regpat(char_u *efm, int len, efm_T *fmt_ptr, return 0; } +static efm_T *fmt_start = NULL; // cached across qf_parse_line() calls + static void free_efm_list(efm_T **efm_first) { for (efm_T *efm_ptr = *efm_first; efm_ptr != NULL; efm_ptr = *efm_first) { @@ -364,6 +392,8 @@ static void free_efm_list(efm_T **efm_first) vim_regfree(efm_ptr->prog); xfree(efm_ptr); } + + fmt_start = NULL; } // Parse 'errorformat' option @@ -428,6 +458,495 @@ parse_efm_end: return fmt_first; } +static char_u *qf_grow_linebuf(qfstate_T *state, size_t newsz) +{ + // If the line exceeds LINE_MAXLEN exclude the last + // byte since it's not a NL character. + state->linelen = newsz > LINE_MAXLEN ? LINE_MAXLEN - 1 : newsz; + if (state->growbuf == NULL) { + state->growbuf = xmalloc(state->linelen + 1); + state->growbufsiz = state->linelen; + } else if (state->linelen > state->growbufsiz) { + state->growbuf = xrealloc(state->growbuf, state->linelen + 1); + state->growbufsiz = state->linelen; + } + return state->growbuf; +} + +/// Get the next string (separated by newline) from state->p_str. +static int qf_get_next_str_line(qfstate_T *state) +{ + // Get the next line from the supplied string + char_u *p_str = state->p_str; + char_u *p; + size_t len; + + if (*p_str == NUL) { // Reached the end of the string + return QF_END_OF_INPUT; + } + + p = vim_strchr(p_str, '\n'); + if (p != NULL) { + len = (size_t)(p - p_str) + 1; + } else { + len = STRLEN(p_str); + } + + if (len > IOSIZE - 2) { + state->linebuf = qf_grow_linebuf(state, len); + } else { + state->linebuf = IObuff; + state->linelen = len; + } + STRLCPY(state->linebuf, p_str, state->linelen + 1); + + // Increment using len in order to discard the rest of the line if it + // exceeds LINE_MAXLEN. + p_str += len; + state->p_str = p_str; + + return QF_OK; +} + +/// Get the next string from state->p_Li. +static int qf_get_next_list_line(qfstate_T *state) +{ + listitem_T *p_li = state->p_li; + size_t len; + + // Get the next line from the supplied list + while (p_li != NULL + && (p_li->li_tv.v_type != VAR_STRING + || p_li->li_tv.vval.v_string == NULL)) { + p_li = p_li->li_next; // Skip non-string items + } + + if (p_li == NULL) { // End of the list + state->p_li = NULL; + return QF_END_OF_INPUT; + } + + len = STRLEN(p_li->li_tv.vval.v_string); + if (len > IOSIZE - 2) { + state->linebuf = qf_grow_linebuf(state, len); + } else { + state->linebuf = IObuff; + state->linelen = len; + } + + STRLCPY(state->linebuf, p_li->li_tv.vval.v_string, state->linelen + 1); + + state->p_li = p_li->li_next; // next item + return QF_OK; +} + +/// Get the next string from state->buf. +static int qf_get_next_buf_line(qfstate_T *state) +{ + char_u *p_buf = NULL; + size_t len; + + // Get the next line from the supplied buffer + if (state->buflnum > state->lnumlast) { + return QF_END_OF_INPUT; + } + p_buf = ml_get_buf(state->buf, state->buflnum, false); + state->buflnum += 1; + + len = STRLEN(p_buf); + if (len > IOSIZE - 2) { + state->linebuf = qf_grow_linebuf(state, len); + } else { + state->linebuf = IObuff; + state->linelen = len; + } + STRLCPY(state->linebuf, p_buf, state->linelen + 1); + + return QF_OK; +} + +/// Get the next string from file state->fd. +static int qf_get_next_file_line(qfstate_T *state) +{ + size_t growbuflen; + + if (fgets((char *)IObuff, IOSIZE, state->fd) == NULL) { + return QF_END_OF_INPUT; + } + + bool discard = false; + state->linelen = STRLEN(IObuff); + if (state->linelen == IOSIZE - 1 + && !(IObuff[state->linelen - 1] == '\n')) { + // The current line exceeds IObuff, continue reading using growbuf + // until EOL or LINE_MAXLEN bytes is read. + if (state->growbuf == NULL) { + state->growbufsiz = 2 * (IOSIZE - 1); + state->growbuf = xmalloc(state->growbufsiz); + } + + // Copy the read part of the line, excluding null-terminator + memcpy(state->growbuf, IObuff, IOSIZE - 1); + growbuflen = state->linelen; + + for (;;) { + if (fgets((char *)state->growbuf + growbuflen, + (int)(state->growbufsiz - growbuflen), state->fd) == NULL) { + break; + } + state->linelen = STRLEN(state->growbuf + growbuflen); + growbuflen += state->linelen; + if (state->growbuf[growbuflen - 1] == '\n') { + break; + } + if (state->growbufsiz == LINE_MAXLEN) { + discard = true; + break; + } + + state->growbufsiz = (2 * state->growbufsiz < LINE_MAXLEN) + ? 2 * state->growbufsiz : LINE_MAXLEN; + state->growbuf = xrealloc(state->growbuf, state->growbufsiz); + } + + while (discard) { + // The current line is longer than LINE_MAXLEN, continue reading but + // discard everything until EOL or EOF is reached. + if (fgets((char *)IObuff, IOSIZE, state->fd) == NULL + || STRLEN(IObuff) < IOSIZE - 1 + || IObuff[IOSIZE - 1] == '\n') { + break; + } + } + + state->linebuf = state->growbuf; + state->linelen = growbuflen; + } else { + state->linebuf = IObuff; + } + return QF_OK; +} + +/// Get the next string from a file/buffer/list/string. +static int qf_get_nextline(qfstate_T *state) +{ + int status = QF_FAIL; + + if (state->fd == NULL) { + if (state->tv != NULL) { + if (state->tv->v_type == VAR_STRING) { + // Get the next line from the supplied string + status = qf_get_next_str_line(state); + } else if (state->tv->v_type == VAR_LIST) { + // Get the next line from the supplied list + status = qf_get_next_list_line(state); + } + } else { + // Get the next line from the supplied buffer + status = qf_get_next_buf_line(state); + } + } else { + // Get the next line from the supplied file + status = qf_get_next_file_line(state); + } + + if (status != QF_OK) { + return status; + } + + if (state->linelen > 0 && state->linebuf[state->linelen - 1] == '\n') { + state->linebuf[state->linelen - 1] = NUL; +#ifdef USE_CRNL + if (state->linelen > 1 && state->linebuf[state->linelen - 2] == '\r') { + state->linebuf[state->linelen - 2] = NUL; + } +#endif + } + + remove_bom(state->linebuf); + + return QF_OK; +} + + +/// Parse a line and get the quickfix fields. +/// Return the QF_ status. +static int qf_parse_line(qf_info_T *qi, char_u *linebuf, size_t linelen, + efm_T *fmt_first, qffields_T *fields) +{ + efm_T *fmt_ptr; + size_t len; + int i; + int idx = 0; + char_u *tail = NULL; + regmatch_T regmatch; + + + // Always ignore case when looking for a matching error. + regmatch.rm_ic = true; + + // If there was no %> item start at the first pattern + if (fmt_start == NULL) { + fmt_ptr = fmt_first; + } else { + fmt_ptr = fmt_start; + fmt_start = NULL; + } + + // Try to match each part of 'errorformat' until we find a complete + // match or no match. + fields->valid = true; +restofline: + for (; fmt_ptr != NULL; fmt_ptr = fmt_ptr->next) { + idx = fmt_ptr->prefix; + if (qi->qf_multiscan && vim_strchr((char_u *)"OPQ", idx) == NULL) { + continue; + } + fields->namebuf[0] = NUL; + fields->pattern[0] = NUL; + if (!qi->qf_multiscan) { + fields->errmsg[0] = NUL; + } + fields->lnum = 0; + fields->col = 0; + fields->use_viscol = false; + fields->enr = -1; + fields->type = 0; + tail = NULL; + + regmatch.regprog = fmt_ptr->prog; + int r = vim_regexec(®match, linebuf, (colnr_T)0); + fmt_ptr->prog = regmatch.regprog; + if (r) { + if ((idx == 'C' || idx == 'Z') && !qi->qf_multiline) { + continue; + } + if (vim_strchr((char_u *)"EWI", idx) != NULL) { + fields->type = (char_u)idx; + } else { + fields->type = 0; + } + // Extract error message data from matched line. + // We check for an actual submatch, because "\[" and "\]" in + // the 'errorformat' may cause the wrong submatch to be used. + if ((i = (int)fmt_ptr->addr[0]) > 0) { // %f + if (regmatch.startp[i] == NULL || regmatch.endp[i] == NULL) { + continue; + } + // Expand ~/file and $HOME/file to full path. + char_u c = *regmatch.endp[i]; + *regmatch.endp[i] = NUL; + expand_env(regmatch.startp[i], fields->namebuf, CMDBUFFSIZE); + *regmatch.endp[i] = c; + + if (vim_strchr((char_u *)"OPQ", idx) != NULL + && !os_path_exists(fields->namebuf)) { + continue; + } + } + if ((i = (int)fmt_ptr->addr[1]) > 0) { // %n + if (regmatch.startp[i] == NULL) { + continue; + } + fields->enr = (int)atol((char *)regmatch.startp[i]); + } + if ((i = (int)fmt_ptr->addr[2]) > 0) { // %l + if (regmatch.startp[i] == NULL) { + continue; + } + fields->lnum = atol((char *)regmatch.startp[i]); + } + if ((i = (int)fmt_ptr->addr[3]) > 0) { // %c + if (regmatch.startp[i] == NULL) { + continue; + } + fields->col = (int)atol((char *)regmatch.startp[i]); + } + if ((i = (int)fmt_ptr->addr[4]) > 0) { // %t + if (regmatch.startp[i] == NULL) { + continue; + } + fields->type = *regmatch.startp[i]; + } + if (fmt_ptr->flags == '+' && !qi->qf_multiscan) { // %+ + if (linelen > fields->errmsglen) { + // linelen + null terminator + fields->errmsg = xrealloc(fields->errmsg, linelen + 1); + fields->errmsglen = linelen + 1; + } + STRLCPY(fields->errmsg, linebuf, linelen + 1); + } else if ((i = (int)fmt_ptr->addr[5]) > 0) { // %m + if (regmatch.startp[i] == NULL || regmatch.endp[i] == NULL) { + continue; + } + len = (size_t)(regmatch.endp[i] - regmatch.startp[i]); + if (len > fields->errmsglen) { + // len + null terminator + fields->errmsg = xrealloc(fields->errmsg, len + 1); + fields->errmsglen = len + 1; + } + STRLCPY(fields->errmsg, regmatch.startp[i], len + 1); + } + if ((i = (int)fmt_ptr->addr[6]) > 0) { // %r + if (regmatch.startp[i] == NULL) { + continue; + } + tail = regmatch.startp[i]; + } + if ((i = (int)fmt_ptr->addr[7]) > 0) { // %p + char_u *match_ptr; + + if (regmatch.startp[i] == NULL || regmatch.endp[i] == NULL) { + continue; + } + fields->col = 0; + for (match_ptr = regmatch.startp[i]; + match_ptr != regmatch.endp[i]; match_ptr++) { + fields->col++; + if (*match_ptr == TAB) { + fields->col += 7; + fields->col -= fields->col % 8; + } + } + fields->col++; + fields->use_viscol = true; + } + if ((i = (int)fmt_ptr->addr[8]) > 0) { // %v + if (regmatch.startp[i] == NULL) { + continue; + } + fields->col = (int)atol((char *)regmatch.startp[i]); + fields->use_viscol = true; + } + if ((i = (int)fmt_ptr->addr[9]) > 0) { // %s + if (regmatch.startp[i] == NULL || regmatch.endp[i] == NULL) { + continue; + } + len = (size_t)(regmatch.endp[i] - regmatch.startp[i]); + if (len > CMDBUFFSIZE - 5) { + len = CMDBUFFSIZE - 5; + } + STRCPY(fields->pattern, "^\\V"); + xstrlcat((char *)fields->pattern, (char *)regmatch.startp[i], + CMDBUFFSIZE+1); + fields->pattern[len + 3] = '\\'; + fields->pattern[len + 4] = '$'; + fields->pattern[len + 5] = NUL; + } + break; + } + } + qi->qf_multiscan = false; + + if (fmt_ptr == NULL || idx == 'D' || idx == 'X') { + if (fmt_ptr != NULL) { + if (idx == 'D') { // enter directory + if (*fields->namebuf == NUL) { + EMSG(_("E379: Missing or empty directory name")); + return QF_FAIL; + } + qi->qf_directory = qf_push_dir(fields->namebuf, &qi->qf_dir_stack, + false); + if (qi->qf_directory == NULL) { + return QF_FAIL; + } + } else if (idx == 'X') { // leave directory + qi->qf_directory = qf_pop_dir(&qi->qf_dir_stack); + } + } + fields->namebuf[0] = NUL; // no match found, remove file name + fields->lnum = 0; // don't jump to this line + fields->valid = false; + if (linelen > fields->errmsglen) { + // linelen + null terminator + fields->errmsg = xrealloc(fields->errmsg, linelen + 1); + fields->errmsglen = linelen + 1; + } + // copy whole line to error message + STRLCPY(fields->errmsg, linebuf, linelen + 1); + if (fmt_ptr == NULL) { + qi->qf_multiline = qi->qf_multiignore = false; + } + } else { + // honor %> item + if (fmt_ptr->conthere) { + fmt_start = fmt_ptr; + } + + if (vim_strchr((char_u *)"AEWI", idx) != NULL) { + qi->qf_multiline = true; // start of a multi-line message + qi->qf_multiignore = false; // reset continuation + } else if (vim_strchr((char_u *)"CZ", idx) + != NULL) { // continuation of multi-line msg + if (!qi->qf_multiignore) { + qfline_T *qfprev = qi->qf_lists[qi->qf_curlist].qf_last; + if (qfprev == NULL) { + return QF_FAIL; + } + if (*fields->errmsg && !qi->qf_multiignore) { + size_t len = STRLEN(qfprev->qf_text); + qfprev->qf_text = xrealloc(qfprev->qf_text, + len + STRLEN(fields->errmsg) + 2); + qfprev->qf_text[len] = '\n'; + STRCPY(qfprev->qf_text + len + 1, fields->errmsg); + } + if (qfprev->qf_nr == -1) { + qfprev->qf_nr = fields->enr; + } + if (vim_isprintc(fields->type) && !qfprev->qf_type) { + qfprev->qf_type = fields->type; // only printable chars allowed + } + if (!qfprev->qf_lnum) { + qfprev->qf_lnum = fields->lnum; + } + if (!qfprev->qf_col) { + qfprev->qf_col = fields->col; + } + qfprev->qf_viscol = fields->use_viscol; + if (!qfprev->qf_fnum) { + qfprev->qf_fnum = qf_get_fnum(qi, qi->qf_directory, + *fields->namebuf || qi->qf_directory + ? fields->namebuf + : qi->qf_currfile && fields->valid + ? qi->qf_currfile : 0); + } + } + if (idx == 'Z') { + qi->qf_multiline = qi->qf_multiignore = false; + } + + line_breakcheck(); + return QF_IGNORE_LINE; + } else if (vim_strchr((char_u *)"OPQ", idx) != NULL) { + // global file names + fields->valid = false; + if (*fields->namebuf == NUL || os_path_exists(fields->namebuf)) { + if (*fields->namebuf && idx == 'P') { + qi->qf_currfile = qf_push_dir(fields->namebuf, &qi->qf_file_stack, + true); + } else if (idx == 'Q') { + qi->qf_currfile = qf_pop_dir(&qi->qf_file_stack); + } + *fields->namebuf = NUL; + if (tail && *tail) { + STRMOVE(IObuff, skipwhite(tail)); + qi->qf_multiscan = true; + goto restofline; + } + } + } + if (fmt_ptr->flags == '-') { // generally exclude this line + if (qi->qf_multiline) { + // also exclude continuation lines + qi->qf_multiignore = true; + } + return QF_IGNORE_LINE; + } + } + + return QF_OK; +} + // Read the errorfile "efile" into memory, line by line, building the error // list. // Alternative: when "efile" is NULL read errors from buffer "buf". @@ -449,45 +968,27 @@ qf_init_ext( char_u *qf_title ) { - char_u *namebuf; - char_u *errmsg; - size_t errmsglen; - char_u *pattern; - char_u *growbuf = NULL; - size_t growbuflen; - size_t growbufsiz = 0; - char_u *linebuf = NULL; - size_t linelen = 0; - bool discard; - int col = 0; - bool use_viscol = false; - char_u type = 0; - linenr_T buflnum = lnumfirst; - long lnum = 0L; - int enr = 0; - FILE *fd = NULL; + qfstate_T state = { NULL, 0, NULL, 0, NULL, NULL, NULL, NULL, + NULL, 0, 0 }; + qffields_T fields = { NULL, NULL, 0, 0L, 0, false, NULL, 0, 0, 0 }; qfline_T *old_last = NULL; + bool adding = false; static efm_T *fmt_first = NULL; - efm_T *fmt_ptr; - efm_T *fmt_start = NULL; char_u *efm; static char_u *last_efm = NULL; - size_t len; - int i; - int idx = 0; int retval = -1; // default: return error flag - char_u *tail = NULL; - char_u *p_buf = NULL; - char_u *p_str = NULL; - listitem_T *p_li = NULL; - regmatch_T regmatch; + int status; - namebuf = xmalloc(CMDBUFFSIZE + 1); - errmsglen = CMDBUFFSIZE + 1; - errmsg = xmalloc(errmsglen); - pattern = xmalloc(CMDBUFFSIZE + 1); + // Do not used the cached buffer, it may have been wiped out. + xfree(qf_last_bufname); + qf_last_bufname = NULL; - if (efile != NULL && (fd = mch_fopen((char *)efile, "r")) == NULL) { + fields.namebuf = xmalloc(CMDBUFFSIZE + 1); + fields.errmsglen = CMDBUFFSIZE + 1; + fields.errmsg = xmalloc(fields.errmsglen); + fields.pattern = xmalloc(CMDBUFFSIZE + 1); + + if (efile != NULL && (state.fd = mch_fopen((char *)efile, "r")) == NULL) { EMSG2(_(e_openerrf), efile); goto qf_init_end; } @@ -497,18 +998,16 @@ qf_init_ext( qf_new_list(qi, qf_title); } else if (qi->qf_lists[qi->qf_curlist].qf_count > 0) { // Adding to existing list, use last entry. + adding = true; old_last = qi->qf_lists[qi->qf_curlist].qf_last; } - /* - * Each part of the format string is copied and modified from errorformat to - * regex prog. Only a few % characters are allowed. - */ - /* Use the local value of 'errorformat' if it's set. */ - if (errorformat == p_efm && tv == NULL && *buf->b_p_efm != NUL) + // Use the local value of 'errorformat' if it's set. + if (errorformat == p_efm && tv == NULL && buf && *buf->b_p_efm != NUL) { efm = buf->b_p_efm; - else + } else { efm = errorformat; + } // If we are not adding or adding to another list: clear the state. if (newlist || qi->qf_curlist != qi->qf_dir_curlist) { @@ -547,424 +1046,57 @@ qf_init_ext( */ got_int = FALSE; - /* Always ignore case when looking for a matching error. */ - regmatch.rm_ic = TRUE; - if (tv != NULL) { - if (tv->v_type == VAR_STRING) - p_str = tv->vval.v_string; - else if (tv->v_type == VAR_LIST) - p_li = tv->vval.v_list->lv_first; + if (tv->v_type == VAR_STRING) { + state.p_str = tv->vval.v_string; + } else if (tv->v_type == VAR_LIST) { + state.p_li = tv->vval.v_list->lv_first; + } + state.tv = tv; } + state.buf = buf; + state.buflnum = lnumfirst; + state.lnumlast = lnumlast; /* * Read the lines in the error file one by one. * Try to recognize one of the error formats in each line. */ while (!got_int) { - /* Get the next line. */ - if (fd == NULL) { - if (tv != NULL) { - if (tv->v_type == VAR_STRING) { - /* Get the next line from the supplied string */ - char_u *p; - - if (*p_str == NUL) { // Reached the end of the string - break; - } - - p = vim_strchr(p_str, '\n'); - if (p != NULL) { - len = (size_t)(p - p_str) + 1; - } else { - len = STRLEN(p_str); - } - - if (len > IOSIZE - 2) { - linebuf = qf_grow_linebuf(&growbuf, &growbufsiz, len, &linelen); - } else { - linebuf = IObuff; - linelen = len; - } - STRLCPY(linebuf, p_str, linelen + 1); - - // Increment using len in order to discard the rest of the line if it - // exceeds LINE_MAXLEN. - p_str += len; - } else if (tv->v_type == VAR_LIST) { - // Get the next line from the supplied list - while (p_li != NULL - && (p_li->li_tv.v_type != VAR_STRING - || p_li->li_tv.vval.v_string == NULL)) { - p_li = p_li->li_next; // Skip non-string items - } - - if (p_li == NULL) { // End of the list - break; - } - - len = STRLEN(p_li->li_tv.vval.v_string); - if (len > IOSIZE - 2) { - linebuf = qf_grow_linebuf(&growbuf, &growbufsiz, len, &linelen); - } else { - linebuf = IObuff; - linelen = len; - } - - STRLCPY(linebuf, p_li->li_tv.vval.v_string, linelen + 1); - - p_li = p_li->li_next; /* next item */ - } - } else { - /* Get the next line from the supplied buffer */ - if (buflnum > lnumlast) - break; - p_buf = ml_get_buf(buf, buflnum++, false); - len = STRLEN(p_buf); - if (len > IOSIZE - 2) { - linebuf = qf_grow_linebuf(&growbuf, &growbufsiz, len, &linelen); - } else { - linebuf = IObuff; - linelen = len; - } - STRLCPY(linebuf, p_buf, linelen + 1); - } - } else { - if (fgets((char *)IObuff, IOSIZE, fd) == NULL) { - break; - } - - discard = false; - linelen = STRLEN(IObuff); - if (linelen == IOSIZE - 1 && !(IObuff[linelen - 1] == '\n' -#ifdef USE_CRNL - || IObuff[linelen - 1] == '\r' -#endif - )) { // NOLINT(whitespace/parens) - // The current line exceeds IObuff, continue reading using growbuf - // until EOL or LINE_MAXLEN bytes is read. - if (growbuf == NULL) { - growbufsiz = 2 * (IOSIZE - 1); - growbuf = xmalloc(growbufsiz); - } - - // Copy the read part of the line, excluding null-terminator - memcpy(growbuf, IObuff, IOSIZE - 1); - growbuflen = linelen; - - for (;;) { - if (fgets((char *)growbuf + growbuflen, - (int)(growbufsiz - growbuflen), fd) == NULL) { - break; - } - linelen = STRLEN(growbuf + growbuflen); - growbuflen += linelen; - if (growbuf[growbuflen - 1] == '\n' -#ifdef USE_CRNL - || growbuf[growbuflen - 1] == '\r' -#endif - ) { - break; - } - if (growbufsiz == LINE_MAXLEN) { - discard = true; - break; - } - - growbufsiz = (2 * growbufsiz < LINE_MAXLEN) - ? 2 * growbufsiz : LINE_MAXLEN; - growbuf = xrealloc(growbuf, 2 * growbufsiz); - } - - while (discard) { - // The current line is longer than LINE_MAXLEN, continue reading but - // discard everything until EOL or EOF is reached. - if (fgets((char *)IObuff, IOSIZE, fd) == NULL - || STRLEN(IObuff) < IOSIZE - 1 - || IObuff[IOSIZE - 1] == '\n' -#ifdef USE_CRNL - || IObuff[IOSIZE - 1] == '\r' -#endif - ) { - break; - } - } - - linebuf = growbuf; - linelen = growbuflen; - } else { - linebuf = IObuff; - } - } - - if (linelen > 0 && linebuf[linelen - 1] == '\n') { - linebuf[linelen - 1] = NUL; - } -#ifdef USE_CRNL - if (linelen > 0 && linebuf[linelen - 1] == '\r') { - linebuf[linelen - 1] = NUL; - } -#endif - - remove_bom(linebuf); - - /* If there was no %> item start at the first pattern */ - if (fmt_start == NULL) - fmt_ptr = fmt_first; - else { - fmt_ptr = fmt_start; - fmt_start = NULL; + // Get the next line from a file/buffer/list/string + status = qf_get_nextline(&state); + if (status == QF_END_OF_INPUT) { // end of input + break; } - // Try to match each part of 'errorformat' until we find a complete - // match or no match. - bool valid = true; -restofline: - for (; fmt_ptr != NULL; fmt_ptr = fmt_ptr->next) { - idx = fmt_ptr->prefix; - if (qi->qf_multiscan && vim_strchr((char_u *)"OPQ", idx) == NULL) { - continue; - } - namebuf[0] = NUL; - pattern[0] = NUL; - if (!qi->qf_multiscan) { - errmsg[0] = NUL; - } - lnum = 0; - col = 0; - use_viscol = false; - enr = -1; - type = 0; - tail = NULL; - - regmatch.regprog = fmt_ptr->prog; - int r = vim_regexec(®match, linebuf, (colnr_T)0); - fmt_ptr->prog = regmatch.regprog; - if (r) { - if ((idx == 'C' || idx == 'Z') && !qi->qf_multiline) { - continue; - } - if (vim_strchr((char_u *)"EWI", idx) != NULL) { - type = (char_u)idx; - } else { - type = 0; - } - // Extract error message data from matched line. - // We check for an actual submatch, because "\[" and "\]" in - // the 'errorformat' may cause the wrong submatch to be used. - if ((i = (int)fmt_ptr->addr[0]) > 0) { // %f - if (regmatch.startp[i] == NULL || regmatch.endp[i] == NULL) { - continue; - } - // Expand ~/file and $HOME/file to full path. - char_u c = *regmatch.endp[i]; - *regmatch.endp[i] = NUL; - expand_env(regmatch.startp[i], namebuf, CMDBUFFSIZE); - *regmatch.endp[i] = c; - - if (vim_strchr((char_u *)"OPQ", idx) != NULL - && !os_path_exists(namebuf)) { - continue; - } - } - if ((i = (int)fmt_ptr->addr[1]) > 0) { /* %n */ - if (regmatch.startp[i] == NULL) - continue; - enr = (int)atol((char *)regmatch.startp[i]); - } - if ((i = (int)fmt_ptr->addr[2]) > 0) { /* %l */ - if (regmatch.startp[i] == NULL) - continue; - lnum = atol((char *)regmatch.startp[i]); - } - if ((i = (int)fmt_ptr->addr[3]) > 0) { /* %c */ - if (regmatch.startp[i] == NULL) - continue; - col = (int)atol((char *)regmatch.startp[i]); - } - if ((i = (int)fmt_ptr->addr[4]) > 0) { /* %t */ - if (regmatch.startp[i] == NULL) - continue; - type = *regmatch.startp[i]; - } - if (fmt_ptr->flags == '+' && !qi->qf_multiscan) { // %+ - if (linelen > errmsglen) { - // linelen + null terminator - errmsg = xrealloc(errmsg, linelen + 1); - errmsglen = linelen + 1; - } - STRLCPY(errmsg, linebuf, linelen + 1); - } else if ((i = (int)fmt_ptr->addr[5]) > 0) { // %m - if (regmatch.startp[i] == NULL || regmatch.endp[i] == NULL) { - continue; - } - len = (size_t)(regmatch.endp[i] - regmatch.startp[i]); - if (len > errmsglen) { - // len + null terminator - errmsg = xrealloc(errmsg, len + 1); - errmsglen = len + 1; - } - STRLCPY(errmsg, regmatch.startp[i], len + 1); - } - if ((i = (int)fmt_ptr->addr[6]) > 0) { /* %r */ - if (regmatch.startp[i] == NULL) - continue; - tail = regmatch.startp[i]; - } - if ((i = (int)fmt_ptr->addr[7]) > 0) { /* %p */ - char_u *match_ptr; - - if (regmatch.startp[i] == NULL || regmatch.endp[i] == NULL) - continue; - col = 0; - for (match_ptr = regmatch.startp[i]; - match_ptr != regmatch.endp[i]; ++match_ptr) { - ++col; - if (*match_ptr == TAB) { - col += 7; - col -= col % 8; - } - } - col++; - use_viscol = true; - } - if ((i = (int)fmt_ptr->addr[8]) > 0) { /* %v */ - if (regmatch.startp[i] == NULL) - continue; - col = (int)atol((char *)regmatch.startp[i]); - use_viscol = true; - } - if ((i = (int)fmt_ptr->addr[9]) > 0) { /* %s */ - if (regmatch.startp[i] == NULL || regmatch.endp[i] == NULL) - continue; - len = (size_t)(regmatch.endp[i] - regmatch.startp[i]); - if (len > CMDBUFFSIZE - 5) { - len = CMDBUFFSIZE - 5; - } - STRCPY(pattern, "^\\V"); - STRNCAT(pattern, regmatch.startp[i], len); - pattern[len + 3] = '\\'; - pattern[len + 4] = '$'; - pattern[len + 5] = NUL; - } - break; - } + status = qf_parse_line(qi, state.linebuf, state.linelen, fmt_first, + &fields); + if (status == QF_FAIL) { + goto error2; } - qi->qf_multiscan = false; - - if (fmt_ptr == NULL || idx == 'D' || idx == 'X') { - if (fmt_ptr != NULL) { - if (idx == 'D') { /* enter directory */ - if (*namebuf == NUL) { - EMSG(_("E379: Missing or empty directory name")); - goto error2; - } - qi->qf_directory = qf_push_dir(namebuf, &qi->qf_dir_stack, false); - if (qi->qf_directory == NULL) { - goto error2; - } - } else if (idx == 'X') { // leave directory - qi->qf_directory = qf_pop_dir(&qi->qf_dir_stack); - } - } - namebuf[0] = NUL; // no match found, remove file name - lnum = 0; // don't jump to this line - valid = false; - if (linelen > errmsglen) { - // linelen + null terminator - errmsg = xrealloc(errmsg, linelen + 1); - } - // copy whole line to error message - STRLCPY(errmsg, linebuf, linelen + 1); - if (fmt_ptr == NULL) { - qi->qf_multiline = qi->qf_multiignore = false; - } - } else if (fmt_ptr != NULL) { - /* honor %> item */ - if (fmt_ptr->conthere) - fmt_start = fmt_ptr; - - if (vim_strchr((char_u *)"AEWI", idx) != NULL) { - qi->qf_multiline = true; // start of a multi-line message - qi->qf_multiignore = false; // reset continuation - } else if (vim_strchr((char_u *)"CZ", idx) - != NULL) { // continuation of multi-line msg - qfline_T *qfprev = qi->qf_lists[qi->qf_curlist].qf_last; - if (qfprev == NULL) { - goto error2; - } - if (*errmsg && !qi->qf_multiignore) { - size_t len = STRLEN(qfprev->qf_text); - qfprev->qf_text = xrealloc(qfprev->qf_text, len + STRLEN(errmsg) + 2); - qfprev->qf_text[len] = '\n'; - STRCPY(qfprev->qf_text + len + 1, errmsg); - } - if (qfprev->qf_nr == -1) - qfprev->qf_nr = enr; - if (vim_isprintc(type) && !qfprev->qf_type) - qfprev->qf_type = type; /* only printable chars allowed */ - if (!qfprev->qf_lnum) - qfprev->qf_lnum = lnum; - if (!qfprev->qf_col) - qfprev->qf_col = col; - qfprev->qf_viscol = use_viscol; - if (!qfprev->qf_fnum) { - qfprev->qf_fnum = qf_get_fnum(qi, qi->qf_directory, - *namebuf - || qi->qf_directory - ? namebuf : qi->qf_currfile - && valid ? qi->qf_currfile : 0); - } - if (idx == 'Z') { - qi->qf_multiline = qi->qf_multiignore = false; - } - line_breakcheck(); - continue; - } else if (vim_strchr((char_u *)"OPQ", idx) != NULL) { - // global file names - valid = false; - if (*namebuf == NUL || os_path_exists(namebuf)) { - if (*namebuf && idx == 'P') { - qi->qf_currfile = qf_push_dir(namebuf, &qi->qf_file_stack, true); - } else if (idx == 'Q') { - qi->qf_currfile = qf_pop_dir(&qi->qf_file_stack); - } - *namebuf = NUL; - if (tail && *tail) { - STRMOVE(IObuff, skipwhite(tail)); - qi->qf_multiscan = true; - goto restofline; - } - } - } - if (fmt_ptr->flags == '-') { // generally exclude this line - if (qi->qf_multiline) { - // also exclude continuation lines - qi->qf_multiignore = true; - } - continue; - } + if (status == QF_IGNORE_LINE) { + continue; } if (qf_add_entry(qi, qi->qf_directory, - (*namebuf || qi->qf_directory) - ? namebuf : ((qi->qf_currfile && valid) - ? qi->qf_currfile : (char_u *)NULL), + (*fields.namebuf || qi->qf_directory) + ? fields.namebuf : ((qi->qf_currfile && fields.valid) + ? qi->qf_currfile : (char_u *)NULL), 0, - errmsg, - lnum, - col, - use_viscol, - pattern, - enr, - type, - valid) == FAIL) { + fields.errmsg, + fields.lnum, + fields.col, + fields.use_viscol, + fields.pattern, + fields.enr, + fields.type, + fields.valid) == FAIL) { goto error2; } line_breakcheck(); } - if (fd == NULL || !ferror(fd)) { + if (state.fd == NULL || !ferror(state.fd)) { if (qi->qf_lists[qi->qf_curlist].qf_index == 0) { /* no valid entry found */ qi->qf_lists[qi->qf_curlist].qf_ptr = @@ -983,19 +1115,21 @@ restofline: } EMSG(_(e_readerrf)); error2: - qf_free(qi, qi->qf_curlist); - qi->qf_listcount--; - if (qi->qf_curlist > 0) { - qi->qf_curlist--; + if (!adding) { + qf_free(qi, qi->qf_curlist); + qi->qf_listcount--; + if (qi->qf_curlist > 0) { + qi->qf_curlist--; + } } qf_init_end: - if (fd != NULL) { - fclose(fd); + if (state.fd != NULL) { + fclose(state.fd); } - xfree(namebuf); - xfree(errmsg); - xfree(pattern); - xfree(growbuf); + xfree(fields.namebuf); + xfree(fields.errmsg); + xfree(fields.pattern); + xfree(state.growbuf); qf_update_buffer(qi, old_last); @@ -1105,7 +1239,8 @@ static int qf_add_entry(qf_info_T *qi, char_u *dir, char_u *fname, int bufnum, qfp->qf_fnum = bufnum; if (buf != NULL) { - buf->b_has_qf_entry = true; + buf->b_has_qf_entry |= + (qi == &ql_info) ? BUF_HAS_QF_ENTRY : BUF_HAS_LL_ENTRY; } } else { qfp->qf_fnum = qf_get_fnum(qi, dir, fname); @@ -1122,7 +1257,7 @@ static int qf_add_entry(qf_info_T *qi, char_u *dir, char_u *fname, int bufnum, qfp->qf_nr = nr; if (type != 1 && !vim_isprintc(type)) /* only printable chars allowed */ type = 0; - qfp->qf_type = type; + qfp->qf_type = (char_u)type; qfp->qf_valid = valid; lastp = &qi->qf_lists[qi->qf_curlist].qf_last; @@ -1282,11 +1417,12 @@ void copy_loclist(win_T *from, win_T *to) to->w_llist->qf_curlist = qi->qf_curlist; /* current list */ } -// Get buffer number for file "dir.name". +// Get buffer number for file "directory/fname". // Also sets the b_has_qf_entry flag. static int qf_get_fnum(qf_info_T *qi, char_u *directory, char_u *fname) { - char_u *ptr; + char_u *ptr = NULL; + char_u *bufname; buf_T *buf; if (fname == NULL || *fname == NUL) { // no file name return 0; @@ -1313,16 +1449,28 @@ static int qf_get_fnum(qf_info_T *qi, char_u *directory, char_u *fname) ptr = vim_strsave(fname); } } - // Use concatenated directory name and file name - buf = buflist_new(ptr, NULL, (linenr_T)0, 0); + // Use concatenated directory name and file name. + bufname = ptr; + } else { + bufname = fname; + } + + if (qf_last_bufname != NULL + && STRCMP(bufname, qf_last_bufname) == 0 + && bufref_valid(&qf_last_bufref)) { + buf = qf_last_bufref.br_buf; xfree(ptr); } else { - buf = buflist_new(fname, NULL, (linenr_T)0, 0); + xfree(qf_last_bufname); + buf = buflist_new(bufname, NULL, (linenr_T)0, BLN_NOOPT); + qf_last_bufname = (bufname == ptr) ? bufname : vim_strsave(bufname); + set_bufref(&qf_last_bufref, buf); } if (buf == NULL) { return 0; } - buf->b_has_qf_entry = true; + buf->b_has_qf_entry = + (qi == &ql_info) ? BUF_HAS_QF_ENTRY : BUF_HAS_LL_ENTRY; return buf->b_fnum; } @@ -1730,7 +1878,7 @@ win_found: * If there is only one window and it is the quickfix window, create a * new one above the quickfix window. */ - if (((firstwin == lastwin) && bt_quickfix(curbuf)) || !usable_win) { + if ((ONE_WINDOW && bt_quickfix(curbuf)) || !usable_win) { flags = WSP_ABOVE; if (ll_ref != NULL) flags |= WSP_NEWLOC; @@ -1843,7 +1991,7 @@ win_found: ok = buflist_getfile(qf_ptr->qf_fnum, (linenr_T)1, GETF_SETMARK | GETF_SWITCH, forceit); - if (qi != &ql_info && !win_valid(oldwin)) { + if (qi != &ql_info && !win_valid_any_tab(oldwin)) { EMSG(_("E924: Current window was closed")); is_abort = true; opened_window = false; @@ -2049,21 +2197,20 @@ void qf_list(exarg_T *eap) if (qfp->qf_lnum == 0) { IObuff[0] = NUL; } else if (qfp->qf_col == 0) { - vim_snprintf((char *)IObuff, IOSIZE, ":%" PRId64, - (int64_t)qfp->qf_lnum); + vim_snprintf((char *)IObuff, IOSIZE, ":%" PRIdLINENR, qfp->qf_lnum); } else { - vim_snprintf((char *)IObuff, IOSIZE, ":%" PRId64 " col %d", - (int64_t)qfp->qf_lnum, qfp->qf_col); + vim_snprintf((char *)IObuff, IOSIZE, ":%" PRIdLINENR " col %d", + qfp->qf_lnum, qfp->qf_col); } vim_snprintf((char *)IObuff + STRLEN(IObuff), IOSIZE, "%s:", (char *)qf_types(qfp->qf_type, qfp->qf_nr)); - msg_puts_attr(IObuff, hl_attr(HLF_N)); + msg_puts_attr((const char *)IObuff, hl_attr(HLF_N)); if (qfp->qf_pattern != NULL) { qf_fmt_text(qfp->qf_pattern, IObuff, IOSIZE); - STRCAT(IObuff, ":"); - msg_puts(IObuff); + xstrlcat((char *)IObuff, ":", IOSIZE); + msg_puts((const char *)IObuff); } - msg_puts((char_u *)" "); + msg_puts(" "); /* Remove newlines and leading whitespace from the text. For an * unrecognized line keep the indent, the compiler may mark a word @@ -2105,6 +2252,31 @@ static void qf_fmt_text(char_u *text, char_u *buf, int bufsize) buf[i] = NUL; } +static void qf_msg(qf_info_T *qi, int which, char *lead) +{ + char *title = (char *)qi->qf_lists[which].qf_title; + int count = qi->qf_lists[which].qf_count; + char_u buf[IOSIZE]; + + vim_snprintf((char *)buf, IOSIZE, _("%serror list %d of %d; %d errors "), + lead, + which + 1, + qi->qf_listcount, + count); + + if (title != NULL) { + size_t len = STRLEN(buf); + + if (len < 34) { + memset(buf + len, ' ', 34 - len); + buf[34] = NUL; + } + xstrlcat((char *)buf, title, IOSIZE); + } + trunc_string(buf, buf, (int)Columns - 1, IOSIZE); + msg(buf); +} + /* * ":colder [count]": Up in the quickfix stack. * ":cnewer [count]": Down in the quickfix stack. @@ -2145,20 +2317,29 @@ void qf_age(exarg_T *eap) ++qi->qf_curlist; } } - qf_msg(qi); + qf_msg(qi, qi->qf_curlist, ""); + qf_update_buffer(qi, NULL); } -static void qf_msg(qf_info_T *qi) +void qf_history(exarg_T *eap) { - smsg(_("error list %d of %d; %d errors"), - qi->qf_curlist + 1, qi->qf_listcount, - qi->qf_lists[qi->qf_curlist].qf_count); - qf_update_buffer(qi, NULL); + qf_info_T *qi = &ql_info; + int i; + + if (eap->cmdidx == CMD_lhistory) { + qi = GET_LOC_LIST(curwin); + } + if (qi == NULL || (qi->qf_listcount == 0 + && qi->qf_lists[qi->qf_curlist].qf_count == 0)) { + MSG(_("No entries")); + } else { + for (i = 0; i < qi->qf_listcount; i++) { + qf_msg(qi, i, i == qi->qf_curlist ? "> " : " "); + } + } } -/* - * Free error list "idx". - */ +/// Free all the entries in the error list "idx". static void qf_free(qf_info_T *qi, int idx) { qfline_T *qfp; @@ -2190,7 +2371,9 @@ static void qf_free(qf_info_T *qi, int idx) qi->qf_lists[idx].qf_index = 0; qf_clean_dir_stack(&qi->qf_dir_stack); + qi->qf_directory = NULL; qf_clean_dir_stack(&qi->qf_file_stack); + qi->qf_currfile = NULL; } /* @@ -2203,8 +2386,9 @@ void qf_mark_adjust(win_T *wp, linenr_T line1, linenr_T line2, long amount, long int idx; qf_info_T *qi = &ql_info; bool found_one = false; + int buf_has_flag = wp == NULL ? BUF_HAS_QF_ENTRY : BUF_HAS_LL_ENTRY; - if (!curbuf->b_has_qf_entry) { + if (!(curbuf->b_has_qf_entry & buf_has_flag)) { return; } if (wp != NULL) { @@ -2231,7 +2415,7 @@ void qf_mark_adjust(win_T *wp, linenr_T line1, linenr_T line2, long amount, long } if (!found_one) { - curbuf->b_has_qf_entry = false; + curbuf->b_has_qf_entry &= ~buf_has_flag; } } @@ -2413,15 +2597,13 @@ void ex_copen(exarg_T *eap) else { /* Create a new quickfix buffer */ (void)do_ecmd(0, NULL, NULL, NULL, ECMD_ONE, ECMD_HIDE, oldwin); - /* switch off 'swapfile' */ - set_option_value((char_u *)"swf", 0L, NULL, OPT_LOCAL); - set_option_value((char_u *)"bt", 0L, (char_u *)"quickfix", - OPT_LOCAL); - set_option_value((char_u *)"bh", 0L, (char_u *)"wipe", OPT_LOCAL); + // Switch off 'swapfile'. + set_option_value("swf", 0L, NULL, OPT_LOCAL); + set_option_value("bt", 0L, "quickfix", OPT_LOCAL); + set_option_value("bh", 0L, "wipe", OPT_LOCAL); RESET_BINDING(curwin); - curwin->w_p_diff = FALSE; - set_option_value((char_u *)"fdm", 0L, (char_u *)"manual", - OPT_LOCAL); + curwin->w_p_diff = false; + set_option_value("fdm", 0L, "manual", OPT_LOCAL); } /* Only set the height when still in the same tab page and there is no @@ -2582,6 +2764,19 @@ static buf_T *qf_find_buf(qf_info_T *qi) return NULL; } +/// Update the w:quickfix_title variable in the quickfix/location list window +static void qf_update_win_titlevar(qf_info_T *qi) +{ + win_T *win; + + if ((win = qf_find_win(qi)) != NULL) { + win_T *curwin_save = curwin; + curwin = win; + qf_set_title_var(qi); + curwin = curwin_save; + } +} + /* * Find the quickfix buffer. If it exists, update the contents. */ @@ -2589,7 +2784,6 @@ static void qf_update_buffer(qf_info_T *qi, qfline_T *old_last) { buf_T *buf; win_T *win; - win_T *curwin_save; aco_save_T aco; /* Check if a buffer for the quickfix list exists. Update it. */ @@ -2602,12 +2796,7 @@ static void qf_update_buffer(qf_info_T *qi, qfline_T *old_last) aucmd_prepbuf(&aco, buf); } - if ((win = qf_find_win(qi)) != NULL) { - curwin_save = curwin; - curwin = win; - qf_set_title_var(qi); - curwin = curwin_save; - } + qf_update_win_titlevar(qi); qf_fill_buffer(qi, buf, old_last); @@ -2726,14 +2915,14 @@ static void qf_fill_buffer(qf_info_T *qi, buf_T *buf, qfline_T *old_last) } } - /* correct cursor position */ - check_lnums(TRUE); + // Correct cursor position. + check_lnums(true); if (old_last == NULL) { // Set the 'filetype' to "qf" each time after filling the buffer. This // resembles reading a file into a buffer, it's more logical when using // autocommands. - set_option_value((char_u *)"ft", 0L, (char_u *)"qf", OPT_LOCAL); + set_option_value("ft", 0L, "qf", OPT_LOCAL); curbuf->b_p_ma = false; keep_filetype = true; // don't detect 'filetype' @@ -2837,11 +3026,11 @@ void ex_make(exarg_T *eap) case CMD_lgrepadd: au_name = (char_u *)"lgrepadd"; break; default: break; } - if (au_name != NULL) { - apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name, - curbuf->b_fname, TRUE, curbuf); - if (did_throw || force_abort) + if (au_name != NULL && apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name, + curbuf->b_fname, true, curbuf)) { + if (aborting()) { return; + } } if (eap->cmdidx == CMD_lmake || eap->cmdidx == CMD_lgrep @@ -2938,7 +3127,7 @@ static char_u *get_mef_name(void) STRCPY(name, p_mef); sprintf((char *)name + (p - p_mef), "%d%d", start, off); STRCAT(name, p + 2); - // Don't accept a symbolic link, its a security risk. + // Don't accept a symbolic link, it's a security risk. FileInfo file_info; bool file_or_link_found = os_fileinfo_link((char *)name, &file_info); if (!file_or_link_found) { @@ -3111,7 +3300,6 @@ void ex_cc(exarg_T *eap) || eap->cmdidx == CMD_lrewind || eap->cmdidx == CMD_lfirst || eap->cmdidx == CMD_llast - || eap->cmdidx == CMD_llast || eap->cmdidx == CMD_ldo || eap->cmdidx == CMD_lfdo) { qi = GET_LOC_LIST(curwin); @@ -3168,7 +3356,6 @@ void ex_cnext(exarg_T *eap) || eap->cmdidx == CMD_lnfile || eap->cmdidx == CMD_lNfile || eap->cmdidx == CMD_lpfile - || eap->cmdidx == CMD_lpfile || eap->cmdidx == CMD_ldo || eap->cmdidx == CMD_lfdo) { qi = GET_LOC_LIST(curwin); @@ -3301,11 +3488,11 @@ void ex_vimgrep(exarg_T *eap) case CMD_lgrepadd: au_name = (char_u *)"lgrepadd"; break; default: break; } - if (au_name != NULL) { - apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name, - curbuf->b_fname, TRUE, curbuf); - if (did_throw || force_abort) + if (au_name != NULL && apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name, + curbuf->b_fname, true, curbuf)) { + if (aborting()) { return; + } } if (eap->cmdidx == CMD_lgrep @@ -3451,10 +3638,13 @@ void ex_vimgrep(exarg_T *eap) col = 0; while (vim_regexec_multi(®match, curwin, buf, lnum, col, NULL) > 0) { + // Pass the buffer number so that it gets used even for a + // dummy buffer, unless duplicate_name is set, then the + // buffer will be wiped out below. if (qf_add_entry(qi, NULL, // dir fname, - 0, + duplicate_name ? 0 : buf->b_fnum, ml_get_buf(buf, regmatch.startpos[0].lnum + lnum, false), regmatch.startpos[0].lnum + lnum, @@ -3508,17 +3698,23 @@ void ex_vimgrep(exarg_T *eap) buf = NULL; } else if (buf != first_match_buf || (flags & VGR_NOJUMP)) { unload_dummy_buffer(buf, dirname_start); + // Keeping the buffer, remove the dummy flag. + buf->b_flags &= ~BF_DUMMY; buf = NULL; } } if (buf != NULL) { - /* If the buffer is still loaded we need to use the - * directory we jumped to below. */ + // Keeping the buffer, remove the dummy flag. + buf->b_flags &= ~BF_DUMMY; + + // If the buffer is still loaded we need to use the + // directory we jumped to below. if (buf == first_match_buf && target_dir == NULL - && STRCMP(dirname_start, dirname_now) != 0) + && STRCMP(dirname_start, dirname_now) != 0) { target_dir = vim_strsave(dirname_now); + } /* The buffer is still loaded, the Filetype autocommands * need to be done now, in that buffer. And the modelines @@ -3583,52 +3779,6 @@ theend: } /* - * Skip over the pattern argument of ":vimgrep /pat/[g][j]". - * Put the start of the pattern in "*s", unless "s" is NULL. - * If "flags" is not NULL put the flags in it: VGR_GLOBAL, VGR_NOJUMP. - * If "s" is not NULL terminate the pattern with a NUL. - * Return a pointer to the char just past the pattern plus flags. - */ -char_u *skip_vimgrep_pat(char_u *p, char_u **s, int *flags) -{ - int c; - - if (vim_isIDc(*p)) { - /* ":vimgrep pattern fname" */ - if (s != NULL) - *s = p; - p = skiptowhite(p); - if (s != NULL && *p != NUL) - *p++ = NUL; - } else { - /* ":vimgrep /pattern/[g][j] fname" */ - if (s != NULL) - *s = p + 1; - c = *p; - p = skip_regexp(p + 1, c, TRUE, NULL); - if (*p != c) - return NULL; - - /* Truncate the pattern. */ - if (s != NULL) - *p = NUL; - ++p; - - /* Find the flags */ - while (*p == 'g' || *p == 'j') { - if (flags != NULL) { - if (*p == 'g') - *flags |= VGR_GLOBAL; - else - *flags |= VGR_NOJUMP; - } - ++p; - } - } - return p; -} - -/* * Restore current working directory to "dirname_start" if they differ, taking * into account whether it is set locally or globally. */ @@ -3669,8 +3819,9 @@ load_dummy_buffer ( ) { buf_T *newbuf; - buf_T *newbuf_to_wipe = NULL; - int failed = TRUE; + bufref_T newbufref; + bufref_T newbuf_to_wipe; + int failed = true; aco_save_T aco; // Allocate a buffer without putting it in the buffer list. @@ -3678,6 +3829,7 @@ load_dummy_buffer ( if (newbuf == NULL) { return NULL; } + set_bufref(&newbufref, newbuf); /* Init the options. */ buf_copy_options(newbuf, BCO_ENTER | BCO_NOHELP); @@ -3697,6 +3849,7 @@ load_dummy_buffer ( * work. */ curbuf->b_flags &= ~BF_DUMMY; + newbuf_to_wipe.br_buf = NULL; if (readfile(fname, NULL, (linenr_T)0, (linenr_T)0, (linenr_T)MAXLNUM, NULL, READ_NEW | READ_DUMMY) == OK @@ -3704,19 +3857,24 @@ load_dummy_buffer ( && !(curbuf->b_flags & BF_NEW)) { failed = FALSE; if (curbuf != newbuf) { - /* Bloody autocommands changed the buffer! Can happen when - * using netrw and editing a remote file. Use the current - * buffer instead, delete the dummy one after restoring the - * window stuff. */ - newbuf_to_wipe = newbuf; + // Bloody autocommands changed the buffer! Can happen when + // using netrw and editing a remote file. Use the current + // buffer instead, delete the dummy one after restoring the + // window stuff. + set_bufref(&newbuf_to_wipe, newbuf); newbuf = curbuf; } } - /* restore curwin/curbuf and a few other things */ + // Restore curwin/curbuf and a few other things. aucmd_restbuf(&aco); - if (newbuf_to_wipe != NULL && buf_valid(newbuf_to_wipe)) - wipe_buffer(newbuf_to_wipe, FALSE); + if (newbuf_to_wipe.br_buf != NULL && bufref_valid(&newbuf_to_wipe)) { + wipe_buffer(newbuf_to_wipe.br_buf, false); + } + + // Add back the "dummy" flag, otherwise buflist_findname_file_id() + // won't skip it. + newbuf->b_flags |= BF_DUMMY; } /* @@ -3727,8 +3885,9 @@ load_dummy_buffer ( os_dirname(resulting_dir, MAXPATHL); restore_start_dir(dirname_start); - if (!buf_valid(newbuf)) + if (!bufref_valid(&newbufref)) { return NULL; + } if (failed) { wipe_dummy_buffer(newbuf, dirname_start); return NULL; @@ -3776,13 +3935,11 @@ static void unload_dummy_buffer(buf_T *buf, char_u *dirname_start) } } -/* - * Add each quickfix error to list "list" as a dictionary. - */ -int get_errorlist(win_T *wp, list_T *list) +/// Add each quickfix error to list "list" as a dictionary. +/// If qf_idx is -1, use the current list. Otherwise, use the specified list. +int get_errorlist(win_T *wp, int qf_idx, list_T *list) { qf_info_T *qi = &ql_info; - dict_T *dict; char_u buf[2]; qfline_T *qfp; int i; @@ -3794,34 +3951,50 @@ int get_errorlist(win_T *wp, list_T *list) return FAIL; } - if (qi->qf_curlist >= qi->qf_listcount - || qi->qf_lists[qi->qf_curlist].qf_count == 0) + if (qf_idx == -1) { + qf_idx = qi->qf_curlist; + } + + if (qf_idx >= qi->qf_listcount + || qi->qf_lists[qf_idx].qf_count == 0) { return FAIL; + } - qfp = qi->qf_lists[qi->qf_curlist].qf_start; - for (i = 1; !got_int && i <= qi->qf_lists[qi->qf_curlist].qf_count; ++i) { - /* Handle entries with a non-existing buffer number. */ + qfp = qi->qf_lists[qf_idx].qf_start; + for (i = 1; !got_int && i <= qi->qf_lists[qf_idx].qf_count; i++) { + // Handle entries with a non-existing buffer number. bufnum = qfp->qf_fnum; if (bufnum != 0 && (buflist_findnr(bufnum) == NULL)) bufnum = 0; - dict = dict_alloc(); - list_append_dict(list, dict); + dict_T *const dict = tv_dict_alloc(); + tv_list_append_dict(list, dict); buf[0] = qfp->qf_type; buf[1] = NUL; - if ( dict_add_nr_str(dict, "bufnr", (long)bufnum, NULL) == FAIL - || dict_add_nr_str(dict, "lnum", (long)qfp->qf_lnum, NULL) == FAIL - || dict_add_nr_str(dict, "col", (long)qfp->qf_col, NULL) == FAIL - || dict_add_nr_str(dict, "vcol", (long)qfp->qf_viscol, NULL) == FAIL - || dict_add_nr_str(dict, "nr", (long)qfp->qf_nr, NULL) == FAIL - || dict_add_nr_str(dict, "pattern", 0L, - qfp->qf_pattern == NULL ? (char_u *)"" : qfp->qf_pattern) == FAIL - || dict_add_nr_str(dict, "text", 0L, - qfp->qf_text == NULL ? (char_u *)"" : qfp->qf_text) == FAIL - || dict_add_nr_str(dict, "type", 0L, buf) == FAIL - || dict_add_nr_str(dict, "valid", (long)qfp->qf_valid, NULL) == FAIL) - return FAIL; + if (tv_dict_add_nr(dict, S_LEN("bufnr"), (varnumber_T)bufnum) == FAIL + || (tv_dict_add_nr(dict, S_LEN("lnum"), (varnumber_T)qfp->qf_lnum) + == FAIL) + || (tv_dict_add_nr(dict, S_LEN("col"), (varnumber_T)qfp->qf_col) + == FAIL) + || (tv_dict_add_nr(dict, S_LEN("vcol"), (varnumber_T)qfp->qf_viscol) + == FAIL) + || (tv_dict_add_nr(dict, S_LEN("nr"), (varnumber_T)qfp->qf_nr) == FAIL) + || tv_dict_add_str(dict, S_LEN("pattern"), + (qfp->qf_pattern == NULL + ? "" + : (const char *)qfp->qf_pattern)) == FAIL + || tv_dict_add_str(dict, S_LEN("text"), + (qfp->qf_text == NULL + ? "" + : (const char *)qfp->qf_text)) == FAIL + || tv_dict_add_str(dict, S_LEN("type"), (const char *)buf) == FAIL + || (tv_dict_add_nr(dict, S_LEN("valid"), (varnumber_T)qfp->qf_valid) + == FAIL)) { + // tv_dict_add* fail only if key already exist, but this is a newly + // allocated dictionary which is thus guaranteed to have no existing keys. + assert(false); + } qfp = qfp->qf_next; if (qfp == NULL) { @@ -3831,22 +4004,94 @@ int get_errorlist(win_T *wp, list_T *list) return OK; } -// Populate the quickfix list with the items supplied in the list -// of dictionaries. "title" will be copied to w:quickfix_title -// "action" is 'a' for add, 'r' for replace. Otherwise create a new list. -int set_errorlist(win_T *wp, list_T *list, int action, char_u *title) +/// Flags used by getqflist()/getloclist() to determine which fields to return. +enum { + QF_GETLIST_NONE = 0x0, + QF_GETLIST_TITLE = 0x1, + QF_GETLIST_ITEMS = 0x2, + QF_GETLIST_NR = 0x4, + QF_GETLIST_WINID = 0x8, + QF_GETLIST_ALL = 0xFF +}; + +/// Return quickfix/location list details (title) as a +/// dictionary. 'what' contains the details to return. If 'list_idx' is -1, +/// then current list is used. Otherwise the specified list is used. +int get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict) +{ + qf_info_T *qi = &ql_info; + + if (wp != NULL) { + qi = GET_LOC_LIST(wp); + if (qi == NULL) { + return FAIL; + } + } + + int status = OK; + dictitem_T *di; + int flags = QF_GETLIST_NONE; + + int qf_idx = qi->qf_curlist; // default is the current list + if ((di = tv_dict_find(what, S_LEN("nr"))) != NULL) { + // Use the specified quickfix/location list + if (di->di_tv.v_type == VAR_NUMBER) { + // for zero use the current list + if (di->di_tv.vval.v_number != 0) { + qf_idx = (int)di->di_tv.vval.v_number - 1; + if (qf_idx < 0 || qf_idx >= qi->qf_listcount) { + return FAIL; + } + } + flags |= QF_GETLIST_NR; + } else { + return FAIL; + } + } + + if (tv_dict_find(what, S_LEN("all")) != NULL) { + flags |= QF_GETLIST_ALL; + } + + if (tv_dict_find(what, S_LEN("title")) != NULL) { + flags |= QF_GETLIST_TITLE; + } + + if (tv_dict_find(what, S_LEN("winid")) != NULL) { + flags |= QF_GETLIST_WINID; + } + + if (flags & QF_GETLIST_TITLE) { + char_u *t = qi->qf_lists[qf_idx].qf_title; + if (t == NULL) { + t = (char_u *)""; + } + status = tv_dict_add_str(retdict, S_LEN("title"), (const char *)t); + } + if ((status == OK) && (flags & QF_GETLIST_NR)) { + status = tv_dict_add_nr(retdict, S_LEN("nr"), qf_idx + 1); + } + if ((status == OK) && (flags & QF_GETLIST_WINID)) { + win_T *win = qf_find_win(qi); + if (win != NULL) { + status = tv_dict_add_nr(retdict, S_LEN("winid"), win->handle); + } + } + + return status; +} + +/// Add list of entries to quickfix/location list. Each list entry is +/// a dictionary with item information. +static int qf_add_entries(qf_info_T *qi, list_T *list, char_u *title, + int action) { listitem_T *li; dict_T *d; qfline_T *old_last = NULL; int retval = OK; - qf_info_T *qi = &ql_info; bool did_bufnr_emsg = false; - if (wp != NULL) { - qi = ll_get_or_alloc_list(wp); - } - if (action == ' ' || qi->qf_curlist == qi->qf_listcount) { // make place for a new list qf_new_list(qi, title); @@ -3866,17 +4111,18 @@ int set_errorlist(win_T *wp, list_T *list, int action, char_u *title) if (d == NULL) continue; - char_u *filename = get_dict_string(d, "filename", true); - int bufnum = (int)get_dict_number(d, "bufnr"); - long lnum = get_dict_number(d, "lnum"); - int col = (int)get_dict_number(d, "col"); - char_u vcol = (char_u)get_dict_number(d, "vcol"); - int nr = (int)get_dict_number(d, "nr"); - char_u *type = get_dict_string(d, "type", true); - char_u *pattern = get_dict_string(d, "pattern", true); - char_u *text = get_dict_string(d, "text", true); + char *const filename = tv_dict_get_string(d, "filename", true); + int bufnum = (int)tv_dict_get_number(d, "bufnr"); + long lnum = (long)tv_dict_get_number(d, "lnum"); + int col = (int)tv_dict_get_number(d, "col"); + char_u vcol = (char_u)tv_dict_get_number(d, "vcol"); + int nr = (int)tv_dict_get_number(d, "nr"); + const char *type_str = tv_dict_get_string(d, "type", false); + const char_u type = (char_u)(uint8_t)(type_str == NULL ? NUL : *type_str); + char *const pattern = tv_dict_get_string(d, "pattern", true); + char *text = tv_dict_get_string(d, "text", true); if (text == NULL) { - text = vim_strsave((char_u *)""); + text = xcalloc(1, 1); } bool valid = true; if ((filename == NULL && bufnum == 0) || (lnum == 0 && pattern == NULL)) { @@ -3896,21 +4142,20 @@ int set_errorlist(win_T *wp, list_T *list, int action, char_u *title) int status = qf_add_entry(qi, NULL, // dir - filename, + (char_u *)filename, bufnum, - text, + (char_u *)text, lnum, col, vcol, // vis_col - pattern, // search pattern + (char_u *)pattern, // search pattern nr, - (char_u)(type == NULL ? NUL : *type), + type, valid); xfree(filename); xfree(pattern); xfree(text); - xfree(type); if (status == FAIL) { retval = FAIL; @@ -3937,6 +4182,71 @@ int set_errorlist(win_T *wp, list_T *list, int action, char_u *title) return retval; } +static int qf_set_properties(qf_info_T *qi, dict_T *what, int action) +{ + dictitem_T *di; + int retval = FAIL; + int newlist = false; + + if (action == ' ' || qi->qf_curlist == qi->qf_listcount) { + newlist = true; + } + int qf_idx = qi->qf_curlist; // default is the current list + if ((di = tv_dict_find(what, S_LEN("nr"))) != NULL) { + // Use the specified quickfix/location list + if (di->di_tv.v_type == VAR_NUMBER) { + qf_idx = (int)di->di_tv.vval.v_number - 1; + if (qf_idx < 0 || qf_idx >= qi->qf_listcount) { + return FAIL; + } + } else { + return FAIL; + } + newlist = false; // use the specified list + } + + if (newlist) { + qf_new_list(qi, NULL); + qf_idx = qi->qf_curlist; + } + + if ((di = tv_dict_find(what, S_LEN("title"))) != NULL) { + if (di->di_tv.v_type == VAR_STRING) { + xfree(qi->qf_lists[qf_idx].qf_title); + qi->qf_lists[qf_idx].qf_title = (char_u *)tv_dict_get_string( + what, "title", true); + if (qf_idx == qi->qf_curlist) { + qf_update_win_titlevar(qi); + } + retval = OK; + } + } + + return retval; +} + +// Populate the quickfix list with the items supplied in the list +// of dictionaries. "title" will be copied to w:quickfix_title +// "action" is 'a' for add, 'r' for replace. Otherwise create a new list. +int set_errorlist(win_T *wp, list_T *list, int action, char_u *title, + dict_T *what) +{ + qf_info_T *qi = &ql_info; + int retval = OK; + + if (wp != NULL) { + qi = ll_get_or_alloc_list(wp); + } + + if (what != NULL) { + retval = qf_set_properties(qi, what, action); + } else { + retval = qf_add_entries(qi, list, title, action); + } + + return retval; +} + /* * ":[range]cbuffer [bufnr]" command. * ":[range]caddbuffer [bufnr]" command. @@ -3947,14 +4257,45 @@ int set_errorlist(win_T *wp, list_T *list, int action, char_u *title) */ void ex_cbuffer(exarg_T *eap) { - buf_T *buf = NULL; - qf_info_T *qi = &ql_info; + buf_T *buf = NULL; + qf_info_T *qi = &ql_info; + const char *au_name = NULL; if (eap->cmdidx == CMD_lbuffer || eap->cmdidx == CMD_lgetbuffer || eap->cmdidx == CMD_laddbuffer) { qi = ll_get_or_alloc_list(curwin); } + switch (eap->cmdidx) { + case CMD_cbuffer: + au_name = "cbuffer"; + break; + case CMD_cgetbuffer: + au_name = "cgetbuffer"; + break; + case CMD_caddbuffer: + au_name = "caddbuffer"; + break; + case CMD_lbuffer: + au_name = "lbuffer"; + break; + case CMD_lgetbuffer: + au_name = "lgetbuffer"; + break; + case CMD_laddbuffer: + au_name = "laddbuffer"; + break; + default: + break; + } + + if (au_name != NULL && apply_autocmds(EVENT_QUICKFIXCMDPRE, (char_u *)au_name, + curbuf->b_fname, true, curbuf)) { + if (aborting()) { + return; + } + } + if (*eap->arg == NUL) buf = curbuf; else if (*skipwhite(skipdigits(eap->arg)) == NUL) @@ -3981,13 +4322,17 @@ void ex_cbuffer(exarg_T *eap) } if (qf_init_ext(qi, NULL, buf, NULL, p_efm, - (eap->cmdidx != CMD_caddbuffer - && eap->cmdidx != CMD_laddbuffer), - eap->line1, eap->line2, - qf_title) > 0 - && (eap->cmdidx == CMD_cbuffer - || eap->cmdidx == CMD_lbuffer)) - qf_jump(qi, 0, 0, eap->forceit); /* display first error */ + (eap->cmdidx != CMD_caddbuffer + && eap->cmdidx != CMD_laddbuffer), + eap->line1, eap->line2, qf_title) > 0) { + if (au_name != NULL) { + apply_autocmds(EVENT_QUICKFIXCMDPOST, (char_u *)au_name, + curbuf->b_fname, true, curbuf); + } + if (eap->cmdidx == CMD_cbuffer || eap->cmdidx == CMD_lbuffer) { + qf_jump(qi, 0, 0, eap->forceit); // display first error + } + } } } } @@ -3998,30 +4343,65 @@ void ex_cbuffer(exarg_T *eap) */ void ex_cexpr(exarg_T *eap) { - typval_T *tv; - qf_info_T *qi = &ql_info; + qf_info_T *qi = &ql_info; + const char *au_name = NULL; if (eap->cmdidx == CMD_lexpr || eap->cmdidx == CMD_lgetexpr || eap->cmdidx == CMD_laddexpr) { qi = ll_get_or_alloc_list(curwin); } + switch (eap->cmdidx) { + case CMD_cexpr: + au_name = "cexpr"; + break; + case CMD_cgetexpr: + au_name = "cgetexpr"; + break; + case CMD_caddexpr: + au_name = "caddexpr"; + break; + case CMD_lexpr: + au_name = "lexpr"; + break; + case CMD_lgetexpr: + au_name = "lgetexpr"; + break; + case CMD_laddexpr: + au_name = "laddexpr"; + break; + default: + break; + } + if (au_name != NULL && apply_autocmds(EVENT_QUICKFIXCMDPRE, (char_u *)au_name, + curbuf->b_fname, true, curbuf)) { + if (aborting()) { + return; + } + } + /* Evaluate the expression. When the result is a string or a list we can * use it to fill the errorlist. */ - tv = eval_expr(eap->arg, NULL); - if (tv != NULL) { - if ((tv->v_type == VAR_STRING && tv->vval.v_string != NULL) - || (tv->v_type == VAR_LIST && tv->vval.v_list != NULL)) { - if (qf_init_ext(qi, NULL, NULL, tv, p_efm, - (eap->cmdidx != CMD_caddexpr - && eap->cmdidx != CMD_laddexpr), - (linenr_T)0, (linenr_T)0, *eap->cmdlinep) > 0 - && (eap->cmdidx == CMD_cexpr - || eap->cmdidx == CMD_lexpr)) - qf_jump(qi, 0, 0, eap->forceit); /* display first error */ - } else + typval_T tv; + if (eval0(eap->arg, &tv, NULL, true) != FAIL) { + if ((tv.v_type == VAR_STRING && tv.vval.v_string != NULL) + || (tv.v_type == VAR_LIST && tv.vval.v_list != NULL)) { + if (qf_init_ext(qi, NULL, NULL, &tv, p_efm, + (eap->cmdidx != CMD_caddexpr + && eap->cmdidx != CMD_laddexpr), + (linenr_T)0, (linenr_T)0, *eap->cmdlinep) > 0) { + if (au_name != NULL) { + apply_autocmds(EVENT_QUICKFIXCMDPOST, (char_u *)au_name, + curbuf->b_fname, true, curbuf); + } + if (eap->cmdidx == CMD_cexpr || eap->cmdidx == CMD_lexpr) { + qf_jump(qi, 0, 0, eap->forceit); // display first error + } + } + } else { EMSG(_("E777: String or List expected")); - free_tv(tv); + } + tv_clear(&tv); } } @@ -4051,11 +4431,11 @@ void ex_helpgrep(exarg_T *eap) case CMD_lhelpgrep: au_name = (char_u *)"lhelpgrep"; break; default: break; } - if (au_name != NULL) { - apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name, - curbuf->b_fname, TRUE, curbuf); - if (did_throw || force_abort) + if (au_name != NULL && apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name, + curbuf->b_fname, true, curbuf)) { + if (aborting()) { return; + } } /* Make 'cpoptions' empty, the 'l' flag should not be used here. */ diff --git a/src/nvim/quickfix.h b/src/nvim/quickfix.h index bb9c2c3193..fdeb8d1a2f 100644 --- a/src/nvim/quickfix.h +++ b/src/nvim/quickfix.h @@ -1,6 +1,9 @@ #ifndef NVIM_QUICKFIX_H #define NVIM_QUICKFIX_H +#include "nvim/types.h" +#include "nvim/ex_cmds_defs.h" + /* flags for skip_vimgrep_pat() */ #define VGR_GLOBAL 1 #define VGR_NOJUMP 2 diff --git a/src/nvim/rbuffer.c b/src/nvim/rbuffer.c index 111af0d0fb..18d453cbe9 100644 --- a/src/nvim/rbuffer.c +++ b/src/nvim/rbuffer.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #include <assert.h> #include <stddef.h> #include <string.h> diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c index 6613d284d7..847b2f273e 100644 --- a/src/nvim/regexp.c +++ b/src/nvim/regexp.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + /* * Handling of regular expressions: vim_regcomp(), vim_regexec(), vim_regsub() * @@ -2221,10 +2224,11 @@ collection: if (*regparse == '[') endc = get_coll_element(®parse); if (endc == 0) { - if (has_mbyte) - endc = mb_ptr2char_adv(®parse); - else + if (has_mbyte) { + endc = mb_ptr2char_adv((const char_u **)®parse); + } else { endc = *regparse++; + } } /* Handle \o40, \x20 and \u20AC style sequences */ @@ -2349,7 +2353,7 @@ collection: break; case CLASS_LOWER: for (cu = 1; cu <= 255; cu++) { - if (vim_islower(cu) && cu != 170 && cu != 186) { + if (mb_islower(cu) && cu != 170 && cu != 186) { regmbc(cu); } } @@ -2375,7 +2379,7 @@ collection: break; case CLASS_UPPER: for (cu = 1; cu <= 255; cu++) { - if (vim_isupper(cu)) { + if (mb_isupper(cu)) { regmbc(cu); } } @@ -2397,7 +2401,7 @@ collection: regc('\b'); break; case CLASS_ESCAPE: - regc('\033'); + regc(ESC); break; } } else { @@ -2922,13 +2926,8 @@ static void skipchr(void) else prevchr_len = 0; if (regparse[prevchr_len] != NUL) { - if (enc_utf8) - /* exclude composing chars that mb_ptr2len does include */ - prevchr_len += utf_ptr2len(regparse + prevchr_len); - else if (has_mbyte) - prevchr_len += (*mb_ptr2len)(regparse + prevchr_len); - else - ++prevchr_len; + // Exclude composing chars that utfc_ptr2len does include. + prevchr_len += utf_ptr2len(regparse + prevchr_len); } regparse += prevchr_len; prev_at_start = at_start; @@ -3051,7 +3050,7 @@ static int getoctchrs(void) int c; int i; - for (i = 0; i < 3 && nr < 040; ++i) { + for (i = 0; i < 3 && nr < 040; i++) { // -V536 c = regparse[0]; if (c < '0' || c > '7') break; @@ -3173,61 +3172,56 @@ static int need_clear_zsubexpr = FALSE; /* extmatch subexpressions int regnarrate = 0; #endif -/* - * Internal copy of 'ignorecase'. It is set at each call to vim_regexec(). - * Normally it gets the value of "rm_ic" or "rmm_ic", but when the pattern - * contains '\c' or '\C' the value is overruled. - */ -static int ireg_ic; - -/* - * Similar to ireg_ic, but only for 'combining' characters. Set with \Z flag - * in the regexp. Defaults to false, always. - */ -static int ireg_icombine; - -/* - * Copy of "rmm_maxcol": maximum column to search for a match. Zero when - * there is no maximum. - */ -static colnr_T ireg_maxcol; - -/* - * Sometimes need to save a copy of a line. Since alloc()/free() is very - * slow, we keep one allocated piece of memory and only re-allocate it when - * it's too small. It's freed in bt_regexec_both() when finished. - */ +// Sometimes need to save a copy of a line. Since alloc()/free() is very +// slow, we keep one allocated piece of memory and only re-allocate it when +// it's too small. It's freed in bt_regexec_both() when finished. static char_u *reg_tofree = NULL; static unsigned reg_tofreelen; -/* - * These variables are set when executing a regexp to speed up the execution. - * Which ones are set depends on whether a single-line or multi-line match is - * done: - * single-line multi-line - * reg_match ®match_T NULL - * reg_mmatch NULL ®mmatch_T - * reg_startp reg_match->startp <invalid> - * reg_endp reg_match->endp <invalid> - * reg_startpos <invalid> reg_mmatch->startpos - * reg_endpos <invalid> reg_mmatch->endpos - * reg_win NULL window in which to search - * reg_buf curbuf buffer in which to search - * reg_firstlnum <invalid> first line in which to search - * reg_maxline 0 last line nr - * reg_line_lbr FALSE or TRUE FALSE - */ -static regmatch_T *reg_match; -static regmmatch_T *reg_mmatch; -static char_u **reg_startp = NULL; -static char_u **reg_endp = NULL; -static lpos_T *reg_startpos = NULL; -static lpos_T *reg_endpos = NULL; -static win_T *reg_win; -static buf_T *reg_buf; -static linenr_T reg_firstlnum; -static linenr_T reg_maxline; -static int reg_line_lbr; /* "\n" in string is line break */ +// Structure used to store the execution state of the regex engine. +// Which ones are set depends on whether a single-line or multi-line match is +// done: +// single-line multi-line +// reg_match ®match_T NULL +// reg_mmatch NULL ®mmatch_T +// reg_startp reg_match->startp <invalid> +// reg_endp reg_match->endp <invalid> +// reg_startpos <invalid> reg_mmatch->startpos +// reg_endpos <invalid> reg_mmatch->endpos +// reg_win NULL window in which to search +// reg_buf curbuf buffer in which to search +// reg_firstlnum <invalid> first line in which to search +// reg_maxline 0 last line nr +// reg_line_lbr false or true false +typedef struct { + regmatch_T *reg_match; + regmmatch_T *reg_mmatch; + char_u **reg_startp; + char_u **reg_endp; + lpos_T *reg_startpos; + lpos_T *reg_endpos; + win_T *reg_win; + buf_T *reg_buf; + linenr_T reg_firstlnum; + linenr_T reg_maxline; + bool reg_line_lbr; // "\n" in string is line break + + // Internal copy of 'ignorecase'. It is set at each call to vim_regexec(). + // Normally it gets the value of "rm_ic" or "rmm_ic", but when the pattern + // contains '\c' or '\C' the value is overruled. + bool reg_ic; + + // Similar to rex.reg_ic, but only for 'combining' characters. Set with \Z + // flag in the regexp. Defaults to false, always. + bool reg_icombine; + + // Copy of "rmm_maxcol": maximum column to search for a match. Zero when + // there is no maximum. + colnr_T reg_maxcol; +} regexec_T; + +static regexec_T rex; +static bool rex_in_use = false; /* * "regstack" and "backpos" are used by regmatch(). They are kept over calls @@ -3269,14 +3263,16 @@ void free_regexp_stuff(void) */ static char_u *reg_getline(linenr_T lnum) { - /* when looking behind for a match/no-match lnum is negative. But we - * can't go before line 1 */ - if (reg_firstlnum + lnum < 1) + // when looking behind for a match/no-match lnum is negative. But we + // can't go before line 1 + if (rex.reg_firstlnum + lnum < 1) { return NULL; - if (lnum > reg_maxline) - /* Must have matched the "\n" in the last line. */ + } + if (lnum > rex.reg_maxline) { + // Must have matched the "\n" in the last line. return (char_u *)""; - return ml_get_buf(reg_buf, reg_firstlnum + lnum, FALSE); + } + return ml_get_buf(rex.reg_buf, rex.reg_firstlnum + lnum, false); } static regsave_T behind_pos; @@ -3286,9 +3282,8 @@ static char_u *reg_endzp[NSUBEXP]; /* and end of \z(...\) matches */ static lpos_T reg_startzpos[NSUBEXP]; /* idem, beginning pos */ static lpos_T reg_endzpos[NSUBEXP]; /* idem, end pos */ -/* TRUE if using multi-line regexp. */ -#define REG_MULTI (reg_match == NULL) - +// TRUE if using multi-line regexp. +#define REG_MULTI (rex.reg_match == NULL) /* * Match a regexp against a string. @@ -3306,15 +3301,15 @@ bt_regexec_nl ( bool line_lbr ) { - reg_match = rmp; - reg_mmatch = NULL; - reg_maxline = 0; - reg_line_lbr = line_lbr; - reg_buf = curbuf; - reg_win = NULL; - ireg_ic = rmp->rm_ic; - ireg_icombine = FALSE; - ireg_maxcol = 0; + rex.reg_match = rmp; + rex.reg_mmatch = NULL; + rex.reg_maxline = 0; + rex.reg_line_lbr = line_lbr; + rex.reg_buf = curbuf; + rex.reg_win = NULL; + rex.reg_ic = rmp->rm_ic; + rex.reg_icombine = false; + rex.reg_maxcol = 0; long r = bt_regexec_both(line, col, NULL); assert(r <= INT_MAX); @@ -3337,16 +3332,16 @@ bt_regexec_nl ( static long bt_regexec_multi(regmmatch_T *rmp, win_T *win, buf_T *buf, linenr_T lnum, colnr_T col, proftime_T *tm) { - reg_match = NULL; - reg_mmatch = rmp; - reg_buf = buf; - reg_win = win; - reg_firstlnum = lnum; - reg_maxline = reg_buf->b_ml.ml_line_count - lnum; - reg_line_lbr = FALSE; - ireg_ic = rmp->rmm_ic; - ireg_icombine = FALSE; - ireg_maxcol = rmp->rmm_maxcol; + rex.reg_match = NULL; + rex.reg_mmatch = rmp; + rex.reg_buf = buf; + rex.reg_win = win; + rex.reg_firstlnum = lnum; + rex.reg_maxline = rex.reg_buf->b_ml.ml_line_count - lnum; + rex.reg_line_lbr = false; + rex.reg_ic = rmp->rmm_ic; + rex.reg_icombine = false; + rex.reg_maxcol = rmp->rmm_maxcol; return bt_regexec_both(NULL, col, tm); } @@ -3384,14 +3379,14 @@ static long bt_regexec_both(char_u *line, } if (REG_MULTI) { - prog = (bt_regprog_T *)reg_mmatch->regprog; + prog = (bt_regprog_T *)rex.reg_mmatch->regprog; line = reg_getline((linenr_T)0); - reg_startpos = reg_mmatch->startpos; - reg_endpos = reg_mmatch->endpos; + rex.reg_startpos = rex.reg_mmatch->startpos; + rex.reg_endpos = rex.reg_mmatch->endpos; } else { - prog = (bt_regprog_T *)reg_match->regprog; - reg_startp = reg_match->startp; - reg_endp = reg_match->endp; + prog = (bt_regprog_T *)rex.reg_match->regprog; + rex.reg_startp = rex.reg_match->startp; + rex.reg_endp = rex.reg_match->endp; } /* Be paranoid... */ @@ -3404,19 +3399,22 @@ static long bt_regexec_both(char_u *line, if (prog_magic_wrong()) goto theend; - /* If the start column is past the maximum column: no need to try. */ - if (ireg_maxcol > 0 && col >= ireg_maxcol) + // If the start column is past the maximum column: no need to try. + if (rex.reg_maxcol > 0 && col >= rex.reg_maxcol) { goto theend; + } - /* If pattern contains "\c" or "\C": overrule value of ireg_ic */ - if (prog->regflags & RF_ICASE) - ireg_ic = TRUE; - else if (prog->regflags & RF_NOICASE) - ireg_ic = FALSE; + // If pattern contains "\c" or "\C": overrule value of rex.reg_ic + if (prog->regflags & RF_ICASE) { + rex.reg_ic = true; + } else if (prog->regflags & RF_NOICASE) { + rex.reg_ic = false; + } - /* If pattern contains "\Z" overrule value of ireg_icombine */ - if (prog->regflags & RF_ICOMBINE) - ireg_icombine = TRUE; + // If pattern contains "\Z" overrule value of rex.reg_icombine + if (prog->regflags & RF_ICOMBINE) { + rex.reg_icombine = true; + } /* If there is a "must appear" string, look for it. */ if (prog->regmust != NULL) { @@ -3428,32 +3426,26 @@ static long bt_regexec_both(char_u *line, c = *prog->regmust; s = line + col; - /* - * This is used very often, esp. for ":global". Use three versions of - * the loop to avoid overhead of conditions. - */ - if (!ireg_ic - && !has_mbyte - ) - while ((s = vim_strbyte(s, c)) != NULL) { - if (cstrncmp(s, prog->regmust, &prog->regmlen) == 0) - break; /* Found it. */ - ++s; - } - else if (!ireg_ic || (!enc_utf8 && mb_char2len(c) > 1)) + // This is used very often, esp. for ":global". Use two versions of + // the loop to avoid overhead of conditions. + if (!rex.reg_ic) { while ((s = vim_strchr(s, c)) != NULL) { - if (cstrncmp(s, prog->regmust, &prog->regmlen) == 0) - break; /* Found it. */ + if (cstrncmp(s, prog->regmust, &prog->regmlen) == 0) { + break; // Found it. + } mb_ptr_adv(s); } - else + } else { while ((s = cstrchr(s, c)) != NULL) { - if (cstrncmp(s, prog->regmust, &prog->regmlen) == 0) - break; /* Found it. */ + if (cstrncmp(s, prog->regmust, &prog->regmlen) == 0) { + break; // Found it. + } mb_ptr_adv(s); } - if (s == NULL) /* Not present. */ + } + if (s == NULL) { // Not present. goto theend; + } } regline = line; @@ -3470,10 +3462,10 @@ static long bt_regexec_both(char_u *line, c = regline[col]; if (prog->regstart == NUL || prog->regstart == c - || (ireg_ic + || (rex.reg_ic && (((enc_utf8 && utf_fold(prog->regstart) == utf_fold(c))) || (c < 255 && prog->regstart < 255 - && vim_tolower(prog->regstart) == vim_tolower(c))))) { + && mb_tolower(prog->regstart) == mb_tolower(c))))) { retval = regtry(prog, col); } else { retval = 0; @@ -3483,14 +3475,8 @@ static long bt_regexec_both(char_u *line, /* Messy cases: unanchored match. */ while (!got_int) { if (prog->regstart != NUL) { - /* Skip until the char we know it must start with. - * Used often, do some work to avoid call overhead. */ - if (!ireg_ic - && !has_mbyte - ) - s = vim_strbyte(regline + col, prog->regstart); - else - s = cstrchr(regline + col, prog->regstart); + // Skip until the char we know it must start with. + s = cstrchr(regline + col, prog->regstart); if (s == NULL) { retval = 0; break; @@ -3498,8 +3484,8 @@ static long bt_regexec_both(char_u *line, col = (int)(s - regline); } - /* Check for maximum column to try. */ - if (ireg_maxcol > 0 && col >= ireg_maxcol) { + // Check for maximum column to try. + if (rex.reg_maxcol > 0 && col >= rex.reg_maxcol) { retval = 0; break; } @@ -3596,21 +3582,24 @@ static long regtry(bt_regprog_T *prog, colnr_T col) cleanup_subexpr(); if (REG_MULTI) { - if (reg_startpos[0].lnum < 0) { - reg_startpos[0].lnum = 0; - reg_startpos[0].col = col; + if (rex.reg_startpos[0].lnum < 0) { + rex.reg_startpos[0].lnum = 0; + rex.reg_startpos[0].col = col; + } + if (rex.reg_endpos[0].lnum < 0) { + rex.reg_endpos[0].lnum = reglnum; + rex.reg_endpos[0].col = (int)(reginput - regline); + } else { + // Use line number of "\ze". + reglnum = rex.reg_endpos[0].lnum; } - if (reg_endpos[0].lnum < 0) { - reg_endpos[0].lnum = reglnum; - reg_endpos[0].col = (int)(reginput - regline); - } else - /* Use line number of "\ze". */ - reglnum = reg_endpos[0].lnum; } else { - if (reg_startp[0] == NULL) - reg_startp[0] = regline + col; - if (reg_endp[0] == NULL) - reg_endp[0] = reginput; + if (rex.reg_startp[0] == NULL) { + rex.reg_startp[0] = regline + col; + } + if (rex.reg_endp[0] == NULL) { + rex.reg_endp[0] = reginput; + } } /* Package any found \z(...\) matches for export. Default is none. */ unref_extmatch(re_extmatch_out); @@ -3645,34 +3634,33 @@ static long regtry(bt_regprog_T *prog, colnr_T col) } -/* - * Get class of previous character. - */ +// Get class of previous character. static int reg_prev_class(void) { - if (reginput > regline) - return mb_get_class_buf(reginput - 1 - - (*mb_head_off)(regline, reginput - 1), reg_buf); + if (reginput > regline) { + return mb_get_class_tab(reginput - 1 - (*mb_head_off)(regline, + reginput - 1), + rex.reg_buf->b_chartab); + } return -1; } -/* - * Return TRUE if the current reginput position matches the Visual area. - */ +// Return TRUE if the current reginput position matches the Visual area. static int reg_match_visual(void) { pos_T top, bot; linenr_T lnum; colnr_T col; - win_T *wp = reg_win == NULL ? curwin : reg_win; + win_T *wp = rex.reg_win == NULL ? curwin : rex.reg_win; int mode; colnr_T start, end; colnr_T start2, end2; - /* Check if the buffer is the current buffer. */ - if (reg_buf != curbuf || VIsual.lnum == 0) - return FALSE; + // Check if the buffer is the current buffer. + if (rex.reg_buf != curbuf || VIsual.lnum == 0) { + return false; + } if (VIsual_active) { if (lt(VIsual, wp->w_cursor)) { @@ -3693,9 +3681,10 @@ static int reg_match_visual(void) } mode = curbuf->b_visual.vi_mode; } - lnum = reglnum + reg_firstlnum; - if (lnum < top.lnum || lnum > bot.lnum) - return FALSE; + lnum = reglnum + rex.reg_firstlnum; + if (lnum < top.lnum || lnum > bot.lnum) { + return false; + } if (mode == 'v') { col = (colnr_T)(reginput - regline); @@ -3814,11 +3803,11 @@ regmatch ( next = regnext(scan); op = OP(scan); - /* Check for character class with NL added. */ - if (!reg_line_lbr && WITH_NL(op) && REG_MULTI - && *reginput == NUL && reglnum <= reg_maxline) { + // Check for character class with NL added. + if (!rex.reg_line_lbr && WITH_NL(op) && REG_MULTI + && *reginput == NUL && reglnum <= rex.reg_maxline) { reg_nextline(); - } else if (reg_line_lbr && WITH_NL(op) && *reginput == '\n') { + } else if (rex.reg_line_lbr && WITH_NL(op) && *reginput == '\n') { ADVANCE_REGINPUT(); } else { if (WITH_NL(op)) @@ -3839,26 +3828,29 @@ regmatch ( break; case RE_BOF: - /* We're not at the beginning of the file when below the first - * line where we started, not at the start of the line or we - * didn't start at the first line of the buffer. */ + // We're not at the beginning of the file when below the first + // line where we started, not at the start of the line or we + // didn't start at the first line of the buffer. if (reglnum != 0 || reginput != regline - || (REG_MULTI && reg_firstlnum > 1)) + || (REG_MULTI && rex.reg_firstlnum > 1)) { status = RA_NOMATCH; + } break; case RE_EOF: - if (reglnum != reg_maxline || c != NUL) + if (reglnum != rex.reg_maxline || c != NUL) { status = RA_NOMATCH; + } break; case CURSOR: - /* Check if the buffer is in a window and compare the - * reg_win->w_cursor position to the match position. */ - if (reg_win == NULL - || (reglnum + reg_firstlnum != reg_win->w_cursor.lnum) - || ((colnr_T)(reginput - regline) != reg_win->w_cursor.col)) + // Check if the buffer is in a window and compare the + // rex.reg_win->w_cursor position to the match position. + if (rex.reg_win == NULL + || (reglnum + rex.reg_firstlnum != rex.reg_win->w_cursor.lnum) + || ((colnr_T)(reginput - regline) != rex.reg_win->w_cursor.col)) { status = RA_NOMATCH; + } break; case RE_MARK: @@ -3868,19 +3860,20 @@ regmatch ( int cmp = OPERAND(scan)[1]; pos_T *pos; - pos = getmark_buf(reg_buf, mark, FALSE); - if (pos == NULL /* mark doesn't exist */ - || pos->lnum <= 0 /* mark isn't set in reg_buf */ - || (pos->lnum == reglnum + reg_firstlnum + pos = getmark_buf(rex.reg_buf, mark, false); + if (pos == NULL // mark doesn't exist + || pos->lnum <= 0 // mark isn't set in reg_buf + || (pos->lnum == reglnum + rex.reg_firstlnum ? (pos->col == (colnr_T)(reginput - regline) ? (cmp == '<' || cmp == '>') : (pos->col < (colnr_T)(reginput - regline) ? cmp != '>' : cmp != '<')) - : (pos->lnum < reglnum + reg_firstlnum + : (pos->lnum < reglnum + rex.reg_firstlnum ? cmp != '>' - : cmp != '<'))) + : cmp != '<'))) { status = RA_NOMATCH; + } } break; @@ -3890,11 +3883,12 @@ regmatch ( break; case RE_LNUM: - assert(reglnum + reg_firstlnum >= 0 - && (uintmax_t)(reglnum + reg_firstlnum) <= UINT32_MAX); - if (!REG_MULTI || !re_num_cmp((uint32_t)(reglnum + reg_firstlnum), - scan)) + assert(reglnum + rex.reg_firstlnum >= 0 + && (uintmax_t)(reglnum + rex.reg_firstlnum) <= UINT32_MAX); + if (!REG_MULTI + || !re_num_cmp((uint32_t)(reglnum + rex.reg_firstlnum), scan)) { status = RA_NOMATCH; + } break; case RE_COL: @@ -3905,11 +3899,13 @@ regmatch ( break; case RE_VCOL: - if (!re_num_cmp(win_linetabsize(reg_win == NULL ? curwin : reg_win, + if (!re_num_cmp(win_linetabsize(rex.reg_win == NULL + ? curwin : rex.reg_win, regline, (colnr_T)(reginput - regline)) + 1, - scan)) + scan)) { status = RA_NOMATCH; + } break; case BOW: /* \<word; reginput points to w */ @@ -3918,17 +3914,19 @@ regmatch ( else if (has_mbyte) { int this_class; - /* Get class of current and previous char (if it exists). */ - this_class = mb_get_class_buf(reginput, reg_buf); - if (this_class <= 1) - status = RA_NOMATCH; /* not on a word at all */ - else if (reg_prev_class() == this_class) - status = RA_NOMATCH; /* previous char is in same word */ + // Get class of current and previous char (if it exists). + this_class = mb_get_class_tab(reginput, rex.reg_buf->b_chartab); + if (this_class <= 1) { + status = RA_NOMATCH; // Not on a word at all. + } else if (reg_prev_class() == this_class) { + status = RA_NOMATCH; // Previous char is in same word. + } } else { - if (!vim_iswordc_buf(c, reg_buf) || (reginput > regline - && vim_iswordc_buf(reginput[-1 - ], reg_buf))) + if (!vim_iswordc_buf(c, rex.reg_buf) + || (reginput > regline + && vim_iswordc_buf(reginput[-1], rex.reg_buf))) { status = RA_NOMATCH; + } } break; @@ -3938,16 +3936,17 @@ regmatch ( else if (has_mbyte) { int this_class, prev_class; - /* Get class of current and previous char (if it exists). */ - this_class = mb_get_class_buf(reginput, reg_buf); + // Get class of current and previous char (if it exists). + this_class = mb_get_class_tab(reginput, rex.reg_buf->b_chartab); prev_class = reg_prev_class(); if (this_class == prev_class || prev_class == 0 || prev_class == 1) status = RA_NOMATCH; } else { - if (!vim_iswordc_buf(reginput[-1], reg_buf) - || (reginput[0] != NUL && vim_iswordc_buf(c, reg_buf))) + if (!vim_iswordc_buf(reginput[-1], rex.reg_buf) + || (reginput[0] != NUL && vim_iswordc_buf(c, rex.reg_buf))) { status = RA_NOMATCH; + } } break; /* Matched with EOW */ @@ -3974,17 +3973,20 @@ regmatch ( break; case KWORD: - if (!vim_iswordp_buf(reginput, reg_buf)) + if (!vim_iswordp_buf(reginput, rex.reg_buf)) { status = RA_NOMATCH; - else + } else { ADVANCE_REGINPUT(); + } break; case SKWORD: - if (ascii_isdigit(*reginput) || !vim_iswordp_buf(reginput, reg_buf)) + if (ascii_isdigit(*reginput) + || !vim_iswordp_buf(reginput, rex.reg_buf)) { status = RA_NOMATCH; - else + } else { ADVANCE_REGINPUT(); + } break; case FNAME: @@ -4149,16 +4151,16 @@ regmatch ( opnd = OPERAND(scan); // Inline the first byte, for speed. if (*opnd != *reginput - && (!ireg_ic + && (!rex.reg_ic || (!enc_utf8 - && vim_tolower(*opnd) != vim_tolower(*reginput)))) { + && mb_tolower(*opnd) != mb_tolower(*reginput)))) { status = RA_NOMATCH; } else if (*opnd == NUL) { // match empty string always works; happens when "~" is // empty. } else { - if (opnd[1] == NUL && !(enc_utf8 && ireg_ic)) { - len = 1; /* matched a single byte above */ + if (opnd[1] == NUL && !(enc_utf8 && rex.reg_ic)) { + len = 1; // matched a single byte above } else { // Need to match first byte again for multi-byte. len = (int)STRLEN(opnd); @@ -4170,7 +4172,7 @@ regmatch ( // follows (skips over all composing chars). if (status != RA_NOMATCH && enc_utf8 && UTF_COMPOSINGLIKE(reginput, reginput + len) - && !ireg_icombine + && !rex.reg_icombine && OP(next) != RE_COMPOSING) { // raaron: This code makes a composing character get // ignored, which is the correct behavior (sometimes) @@ -4294,9 +4296,9 @@ regmatch ( status = RA_FAIL; else { rp->rs_no = no; - save_se(&rp->rs_un.sesave, ®_startpos[no], - ®_startp[no]); - /* We simply continue and handle the result when done. */ + save_se(&rp->rs_un.sesave, &rex.reg_startpos[no], + &rex.reg_startp[no]); + // We simply continue and handle the result when done. } } break; @@ -4346,12 +4348,12 @@ regmatch ( no = op - MCLOSE; cleanup_subexpr(); rp = regstack_push(RS_MCLOSE, scan); - if (rp == NULL) + if (rp == NULL) { status = RA_FAIL; - else { + } else { rp->rs_no = no; - save_se(&rp->rs_un.sesave, ®_endpos[no], ®_endp[no]); - /* We simply continue and handle the result when done. */ + save_se(&rp->rs_un.sesave, &rex.reg_endpos[no], &rex.reg_endp[no]); + // We simply continue and handle the result when done. } } break; @@ -4394,41 +4396,40 @@ regmatch ( no = op - BACKREF; cleanup_subexpr(); - if (!REG_MULTI) { /* Single-line regexp */ - if (reg_startp[no] == NULL || reg_endp[no] == NULL) { - /* Backref was not set: Match an empty string. */ + if (!REG_MULTI) { // Single-line regexp + if (rex.reg_startp[no] == NULL || rex.reg_endp[no] == NULL) { + // Backref was not set: Match an empty string. len = 0; } else { - /* Compare current input with back-ref in the same - * line. */ - len = (int)(reg_endp[no] - reg_startp[no]); - if (cstrncmp(reg_startp[no], reginput, &len) != 0) + // Compare current input with back-ref in the same line. + len = (int)(rex.reg_endp[no] - rex.reg_startp[no]); + if (cstrncmp(rex.reg_startp[no], reginput, &len) != 0) { status = RA_NOMATCH; + } } - } else { /* Multi-line regexp */ - if (reg_startpos[no].lnum < 0 || reg_endpos[no].lnum < 0) { - /* Backref was not set: Match an empty string. */ + } else { // Multi-line regexp + if (rex.reg_startpos[no].lnum < 0 || rex.reg_endpos[no].lnum < 0) { + // Backref was not set: Match an empty string. len = 0; } else { - if (reg_startpos[no].lnum == reglnum - && reg_endpos[no].lnum == reglnum) { - /* Compare back-ref within the current line. */ - len = reg_endpos[no].col - reg_startpos[no].col; - if (cstrncmp(regline + reg_startpos[no].col, - reginput, &len) != 0) + if (rex.reg_startpos[no].lnum == reglnum + && rex.reg_endpos[no].lnum == reglnum) { + // Compare back-ref within the current line. + len = rex.reg_endpos[no].col - rex.reg_startpos[no].col; + if (cstrncmp(regline + rex.reg_startpos[no].col, + reginput, &len) != 0) { status = RA_NOMATCH; + } } else { - /* Messy situation: Need to compare between two - * lines. */ - int r = match_with_backref( - reg_startpos[no].lnum, - reg_startpos[no].col, - reg_endpos[no].lnum, - reg_endpos[no].col, - &len); - - if (r != RA_MATCH) + // Messy situation: Need to compare between two lines. + int r = match_with_backref(rex.reg_startpos[no].lnum, + rex.reg_startpos[no].col, + rex.reg_endpos[no].lnum, + rex.reg_endpos[no].col, + &len); + if (r != RA_MATCH) { status = r; + } } } } @@ -4568,13 +4569,15 @@ regmatch ( */ if (OP(next) == EXACTLY) { rst.nextb = *OPERAND(next); - if (ireg_ic) { - if (vim_isupper(rst.nextb)) - rst.nextb_ic = vim_tolower(rst.nextb); - else - rst.nextb_ic = vim_toupper(rst.nextb); - } else + if (rex.reg_ic) { + if (mb_isupper(rst.nextb)) { + rst.nextb_ic = mb_tolower(rst.nextb); + } else { + rst.nextb_ic = mb_toupper(rst.nextb); + } + } else { rst.nextb_ic = rst.nextb; + } } else { rst.nextb = NUL; rst.nextb_ic = NUL; @@ -4673,13 +4676,14 @@ regmatch ( break; case NEWL: - if ((c != NUL || !REG_MULTI || reglnum > reg_maxline - || reg_line_lbr) && (c != '\n' || !reg_line_lbr)) + if ((c != NUL || !REG_MULTI || reglnum > rex.reg_maxline + || rex.reg_line_lbr) && (c != '\n' || !rex.reg_line_lbr)) { status = RA_NOMATCH; - else if (reg_line_lbr) + } else if (rex.reg_line_lbr) { ADVANCE_REGINPUT(); - else + } else { reg_nextline(); + } break; case END: @@ -4718,10 +4722,11 @@ regmatch ( break; case RS_MOPEN: - /* Pop the state. Restore pointers when there is no match. */ - if (status == RA_NOMATCH) - restore_se(&rp->rs_un.sesave, ®_startpos[rp->rs_no], - ®_startp[rp->rs_no]); + // Pop the state. Restore pointers when there is no match. + if (status == RA_NOMATCH) { + restore_se(&rp->rs_un.sesave, &rex.reg_startpos[rp->rs_no], + &rex.reg_startp[rp->rs_no]); + } regstack_pop(&scan); break; @@ -4734,10 +4739,11 @@ regmatch ( break; case RS_MCLOSE: - /* Pop the state. Restore pointers when there is no match. */ - if (status == RA_NOMATCH) - restore_se(&rp->rs_un.sesave, ®_endpos[rp->rs_no], - ®_endp[rp->rs_no]); + // Pop the state. Restore pointers when there is no match. + if (status == RA_NOMATCH) { + restore_se(&rp->rs_un.sesave, &rex.reg_endpos[rp->rs_no], + &rex.reg_endp[rp->rs_no]); + } regstack_pop(&scan); break; @@ -5117,10 +5123,11 @@ regrepeat ( ++count; mb_ptr_adv(scan); } - if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > reg_maxline - || reg_line_lbr || count == maxcount) + if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > rex.reg_maxline + || rex.reg_line_lbr || count == maxcount) { break; - ++count; /* count the line-break */ + } + count++; // count the line-break reg_nextline(); scan = reginput; if (got_int) @@ -5138,17 +5145,19 @@ regrepeat ( if (vim_isIDc(PTR2CHAR(scan)) && (testval || !ascii_isdigit(*scan))) { mb_ptr_adv(scan); } else if (*scan == NUL) { - if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > reg_maxline - || reg_line_lbr) + if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > rex.reg_maxline + || rex.reg_line_lbr) { break; + } reg_nextline(); scan = reginput; if (got_int) break; - } else if (reg_line_lbr && *scan == '\n' && WITH_NL(OP(p))) - ++scan; - else + } else if (rex.reg_line_lbr && *scan == '\n' && WITH_NL(OP(p))) { + scan++; + } else { break; + } ++count; } break; @@ -5160,22 +5169,25 @@ regrepeat ( case SKWORD: case SKWORD + ADD_NL: while (count < maxcount) { - if (vim_iswordp_buf(scan, reg_buf) + if (vim_iswordp_buf(scan, rex.reg_buf) && (testval || !ascii_isdigit(*scan))) { mb_ptr_adv(scan); } else if (*scan == NUL) { - if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > reg_maxline - || reg_line_lbr) + if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > rex.reg_maxline + || rex.reg_line_lbr) { break; + } reg_nextline(); scan = reginput; - if (got_int) + if (got_int) { break; - } else if (reg_line_lbr && *scan == '\n' && WITH_NL(OP(p))) - ++scan; - else + } + } else if (rex.reg_line_lbr && *scan == '\n' && WITH_NL(OP(p))) { + scan++; + } else { break; - ++count; + } + count++; } break; @@ -5189,18 +5201,21 @@ regrepeat ( if (vim_isfilec(PTR2CHAR(scan)) && (testval || !ascii_isdigit(*scan))) { mb_ptr_adv(scan); } else if (*scan == NUL) { - if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > reg_maxline - || reg_line_lbr) + if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > rex.reg_maxline + || rex.reg_line_lbr) { break; + } reg_nextline(); scan = reginput; - if (got_int) + if (got_int) { break; - } else if (reg_line_lbr && *scan == '\n' && WITH_NL(OP(p))) - ++scan; - else + } + } else if (rex.reg_line_lbr && *scan == '\n' && WITH_NL(OP(p))) { + scan++; + } else { break; - ++count; + } + count++; } break; @@ -5212,21 +5227,24 @@ regrepeat ( case SPRINT + ADD_NL: while (count < maxcount) { if (*scan == NUL) { - if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > reg_maxline - || reg_line_lbr) + if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > rex.reg_maxline + || rex.reg_line_lbr) { break; + } reg_nextline(); scan = reginput; - if (got_int) + if (got_int) { break; + } } else if (vim_isprintc(PTR2CHAR(scan)) == 1 && (testval || !ascii_isdigit(*scan))) { mb_ptr_adv(scan); - } else if (reg_line_lbr && *scan == '\n' && WITH_NL(OP(p))) - ++scan; - else + } else if (rex.reg_line_lbr && *scan == '\n' && WITH_NL(OP(p))) { + scan++; + } else { break; - ++count; + } + count++; } break; @@ -5237,9 +5255,10 @@ do_class: while (count < maxcount) { int l; if (*scan == NUL) { - if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > reg_maxline - || reg_line_lbr) + if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > rex.reg_maxline + || rex.reg_line_lbr) { break; + } reg_nextline(); scan = reginput; if (got_int) @@ -5248,12 +5267,13 @@ do_class: if (testval != 0) break; scan += l; - } else if ((class_tab[*scan] & mask) == testval) - ++scan; - else if (reg_line_lbr && *scan == '\n' && WITH_NL(OP(p))) - ++scan; - else + } else if ((class_tab[*scan] & mask) == testval) { + scan++; + } else if (rex.reg_line_lbr && *scan == '\n' && WITH_NL(OP(p))) { + scan++; + } else { break; + } ++count; } break; @@ -5331,12 +5351,12 @@ do_class: { int cu, cl; - /* This doesn't do a multi-byte character, because a MULTIBYTECODE - * would have been used for it. It does handle single-byte - * characters, such as latin1. */ - if (ireg_ic) { - cu = vim_toupper(*opnd); - cl = vim_tolower(*opnd); + // This doesn't do a multi-byte character, because a MULTIBYTECODE + // would have been used for it. It does handle single-byte + // characters, such as latin1. + if (rex.reg_ic) { + cu = mb_toupper(*opnd); + cl = mb_tolower(*opnd); while (count < maxcount && (*scan == cu || *scan == cl)) { count++; scan++; @@ -5358,17 +5378,19 @@ do_class: /* Safety check (just in case 'encoding' was changed since * compiling the program). */ if ((len = (*mb_ptr2len)(opnd)) > 1) { - if (ireg_ic && enc_utf8) + if (rex.reg_ic && enc_utf8) { cf = utf_fold(utf_ptr2char(opnd)); + } while (count < maxcount && (*mb_ptr2len)(scan) >= len) { for (i = 0; i < len; ++i) { if (opnd[i] != scan[i]) { break; } } - if (i < len && (!ireg_ic || !enc_utf8 - || utf_fold(utf_ptr2char(scan)) != cf)) + if (i < len && (!rex.reg_ic || !enc_utf8 + || utf_fold(utf_ptr2char(scan)) != cf)) { break; + } scan += len; ++count; } @@ -5386,18 +5408,21 @@ do_class: while (count < maxcount) { int len; if (*scan == NUL) { - if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > reg_maxline - || reg_line_lbr) + if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > rex.reg_maxline + || rex.reg_line_lbr) { break; + } reg_nextline(); scan = reginput; - if (got_int) + if (got_int) { break; - } else if (reg_line_lbr && *scan == '\n' && WITH_NL(OP(p))) - ++scan; - else if (has_mbyte && (len = (*mb_ptr2len)(scan)) > 1) { - if ((cstrchr(opnd, (*mb_ptr2char)(scan)) == NULL) == testval) + } + } else if (rex.reg_line_lbr && *scan == '\n' && WITH_NL(OP(p))) { + scan++; + } else if (has_mbyte && (len = (*mb_ptr2len)(scan)) > 1) { + if ((cstrchr(opnd, (*mb_ptr2char)(scan)) == NULL) == testval) { break; + } scan += len; } else { if ((cstrchr(opnd, *scan) == NULL) == testval) @@ -5410,13 +5435,14 @@ do_class: case NEWL: while (count < maxcount - && ((*scan == NUL && reglnum <= reg_maxline && !reg_line_lbr - && REG_MULTI) || (*scan == '\n' && reg_line_lbr))) { + && ((*scan == NUL && reglnum <= rex.reg_maxline && !rex.reg_line_lbr + && REG_MULTI) || (*scan == '\n' && rex.reg_line_lbr))) { count++; - if (reg_line_lbr) + if (rex.reg_line_lbr) { ADVANCE_REGINPUT(); - else + } else { reg_nextline(); + } scan = reginput; if (got_int) break; @@ -5466,10 +5492,11 @@ static int prog_magic_wrong(void) { regprog_T *prog; - prog = REG_MULTI ? reg_mmatch->regprog : reg_match->regprog; - if (prog->engine == &nfa_regengine) - /* For NFA matcher we don't check the magic */ - return FALSE; + prog = REG_MULTI ? rex.reg_mmatch->regprog : rex.reg_match->regprog; + if (prog->engine == &nfa_regengine) { + // For NFA matcher we don't check the magic + return false; + } if (UCHARAT(((bt_regprog_T *)prog)->program) != REGMAGIC) { EMSG(_(e_re_corr)); @@ -5487,12 +5514,12 @@ static void cleanup_subexpr(void) { if (need_clear_subexpr) { if (REG_MULTI) { - /* Use 0xff to set lnum to -1 */ - memset(reg_startpos, 0xff, sizeof(lpos_T) * NSUBEXP); - memset(reg_endpos, 0xff, sizeof(lpos_T) * NSUBEXP); + // Use 0xff to set lnum to -1 + memset(rex.reg_startpos, 0xff, sizeof(lpos_T) * NSUBEXP); + memset(rex.reg_endpos, 0xff, sizeof(lpos_T) * NSUBEXP); } else { - memset(reg_startp, 0, sizeof(char_u *) * NSUBEXP); - memset(reg_endp, 0, sizeof(char_u *) * NSUBEXP); + memset(rex.reg_startp, 0, sizeof(char_u *) * NSUBEXP); + memset(rex.reg_endp, 0, sizeof(char_u *) * NSUBEXP); } need_clear_subexpr = FALSE; } @@ -5521,17 +5548,17 @@ static void save_subexpr(regbehind_T *bp) { int i; - /* When "need_clear_subexpr" is set we don't need to save the values, only - * remember that this flag needs to be set again when restoring. */ + // When "need_clear_subexpr" is set we don't need to save the values, only + // remember that this flag needs to be set again when restoring. bp->save_need_clear_subexpr = need_clear_subexpr; if (!need_clear_subexpr) { for (i = 0; i < NSUBEXP; ++i) { if (REG_MULTI) { - bp->save_start[i].se_u.pos = reg_startpos[i]; - bp->save_end[i].se_u.pos = reg_endpos[i]; + bp->save_start[i].se_u.pos = rex.reg_startpos[i]; + bp->save_end[i].se_u.pos = rex.reg_endpos[i]; } else { - bp->save_start[i].se_u.ptr = reg_startp[i]; - bp->save_end[i].se_u.ptr = reg_endp[i]; + bp->save_start[i].se_u.ptr = rex.reg_startp[i]; + bp->save_end[i].se_u.ptr = rex.reg_endp[i]; } } } @@ -5549,11 +5576,11 @@ static void restore_subexpr(regbehind_T *bp) if (!need_clear_subexpr) { for (i = 0; i < NSUBEXP; ++i) { if (REG_MULTI) { - reg_startpos[i] = bp->save_start[i].se_u.pos; - reg_endpos[i] = bp->save_end[i].se_u.pos; + rex.reg_startpos[i] = bp->save_start[i].se_u.pos; + rex.reg_endpos[i] = bp->save_end[i].se_u.pos; } else { - reg_startp[i] = bp->save_start[i].se_u.ptr; - reg_endp[i] = bp->save_end[i].se_u.ptr; + rex.reg_startp[i] = bp->save_start[i].se_u.ptr; + rex.reg_endp[i] = bp->save_end[i].se_u.ptr; } } } @@ -5689,10 +5716,12 @@ static int match_with_backref(linenr_T start_lnum, colnr_T start_col, linenr_T e return RA_NOMATCH; /* doesn't match */ if (bytelen != NULL) *bytelen += len; - if (clnum == end_lnum) - break; /* match and at end! */ - if (reglnum >= reg_maxline) - return RA_NOMATCH; /* text too short */ + if (clnum == end_lnum) { + break; // match and at end! + } + if (reglnum >= rex.reg_maxline) { + return RA_NOMATCH; // text too short + } /* Advance to next line. */ reg_nextline(); @@ -6240,24 +6269,22 @@ static void mb_decompose(int c, int *c1, int *c2, int *c3) } } -/* - * Compare two strings, ignore case if ireg_ic set. - * Return 0 if strings match, non-zero otherwise. - * Correct the length "*n" when composing characters are ignored. - */ +// Compare two strings, ignore case if rex.reg_ic set. +// Return 0 if strings match, non-zero otherwise. +// Correct the length "*n" when composing characters are ignored. static int cstrncmp(char_u *s1, char_u *s2, int *n) { int result; - if (!ireg_ic) + if (!rex.reg_ic) { result = STRNCMP(s1, s2, *n); - else { + } else { assert(*n >= 0); result = mb_strnicmp(s1, s2, (size_t)*n); } - /* if it failed and it's utf8 and we want to combineignore: */ - if (result != 0 && enc_utf8 && ireg_icombine) { + // if it failed and it's utf8 and we want to combineignore: + if (result != 0 && enc_utf8 && rex.reg_icombine) { char_u *str1, *str2; int c1, c2, c11, c12; int junk; @@ -6268,20 +6295,21 @@ static int cstrncmp(char_u *s1, char_u *s2, int *n) str2 = s2; c1 = c2 = 0; while ((int)(str1 - s1) < *n) { - c1 = mb_ptr2char_adv(&str1); - c2 = mb_ptr2char_adv(&str2); + c1 = mb_ptr2char_adv((const char_u **)&str1); + c2 = mb_ptr2char_adv((const char_u **)&str2); /* decompose the character if necessary, into 'base' characters * because I don't care about Arabic, I will hard-code the Hebrew * which I *do* care about! So sue me... */ - if (c1 != c2 && (!ireg_ic || utf_fold(c1) != utf_fold(c2))) { - /* decomposition necessary? */ + if (c1 != c2 && (!rex.reg_ic || utf_fold(c1) != utf_fold(c2))) { + // decomposition necessary? mb_decompose(c1, &c11, &junk, &junk); mb_decompose(c2, &c12, &junk, &junk); c1 = c11; c2 = c12; - if (c11 != c12 && (!ireg_ic || utf_fold(c11) != utf_fold(c12))) + if (c11 != c12 && (!rex.reg_ic || utf_fold(c11) != utf_fold(c12))) { break; + } } } result = c2 - c1; @@ -6295,43 +6323,37 @@ static int cstrncmp(char_u *s1, char_u *s2, int *n) /* * cstrchr: This function is used a lot for simple searches, keep it fast! */ -static char_u *cstrchr(char_u *s, int c) +static inline char_u *cstrchr(const char_u *const s, const int c) + FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL + FUNC_ATTR_ALWAYS_INLINE { - char_u *p; - int cc; - - if (!ireg_ic - || (!enc_utf8 && mb_char2len(c) > 1) - ) - return vim_strchr(s, c); - - /* tolower() and toupper() can be slow, comparing twice should be a lot - * faster (esp. when using MS Visual C++!). - * For UTF-8 need to use folded case. */ - if (enc_utf8 && c > 0x80) - cc = utf_fold(c); - else if (vim_isupper(c)) - cc = vim_tolower(c); - else if (vim_islower(c)) - cc = vim_toupper(c); - else + if (!rex.reg_ic) { return vim_strchr(s, c); + } - if (has_mbyte) { - for (p = s; *p != NUL; p += (*mb_ptr2len)(p)) { - if (enc_utf8 && c > 0x80) { - if (utf_fold(utf_ptr2char(p)) == cc) - return p; - } else if (*p == c || *p == cc) - return p; + // Use folded case for UTF-8, slow! For ASCII use libc strpbrk which is + // expected to be highly optimized. + if (c > 0x80) { + const int folded_c = utf_fold(c); + for (const char_u *p = s; *p != NUL; p += utfc_ptr2len(p)) { + if (utf_fold(utf_ptr2char(p)) == folded_c) { + return (char_u *)p; + } } - } else - /* Faster version for when there are no multi-byte characters. */ - for (p = s; *p != NUL; ++p) - if (*p == c || *p == cc) - return p; + return NULL; + } + + int cc; + if (ASCII_ISUPPER(c)) { + cc = TOLOWER_ASC(c); + } else if (ASCII_ISLOWER(c)) { + cc = TOUPPER_ASC(c); + } else { + return vim_strchr(s, c); + } - return NULL; + char tofind[] = { (char)c, (char)cc, NUL }; + return (char_u *)strpbrk((const char *)s, tofind); } /*************************************************************** @@ -6344,28 +6366,28 @@ static char_u *cstrchr(char_u *s, int c) static fptr_T do_upper(int *d, int c) { - *d = vim_toupper(c); + *d = mb_toupper(c); return (fptr_T)NULL; } static fptr_T do_Upper(int *d, int c) { - *d = vim_toupper(c); + *d = mb_toupper(c); return (fptr_T)do_Upper; } static fptr_T do_lower(int *d, int c) { - *d = vim_tolower(c); + *d = mb_tolower(c); return (fptr_T)NULL; } static fptr_T do_Lower(int *d, int c) { - *d = vim_tolower(c); + *d = mb_tolower(c); return (fptr_T)do_Lower; } @@ -6433,55 +6455,132 @@ char_u *regtilde(char_u *source, int magic) static int can_f_submatch = FALSE; /* TRUE when submatch() can be used */ -/* These pointers are used instead of reg_match and reg_mmatch for - * reg_submatch(). Needed for when the substitution string is an expression - * that contains a call to substitute() and submatch(). */ -static regmatch_T *submatch_match; -static regmmatch_T *submatch_mmatch; -static linenr_T submatch_firstlnum; -static linenr_T submatch_maxline; -static int submatch_line_lbr; +// These pointers are used for reg_submatch(). Needed for when the +// substitution string is an expression that contains a call to substitute() +// and submatch(). +typedef struct { + regmatch_T *sm_match; + regmmatch_T *sm_mmatch; + linenr_T sm_firstlnum; + linenr_T sm_maxline; + int sm_line_lbr; +} regsubmatch_T; + +static regsubmatch_T rsm; // can only be used when can_f_submatch is true + +/// Put the submatches in "argv[0]" which is a list passed into call_func() by +/// vim_regsub_both(). +static int fill_submatch_list(int argc, typval_T *argv, int argcount) +{ + listitem_T *li; + int i; + char_u *s; -/* - * vim_regsub() - perform substitutions after a vim_regexec() or - * vim_regexec_multi() match. - * - * If "copy" is TRUE really copy into "dest". - * If "copy" is FALSE nothing is copied, this is just to find out the length - * of the result. - * - * If "backslash" is TRUE, a backslash will be removed later, need to double - * them to keep them, and insert a backslash before a CR to avoid it being - * replaced with a line break later. - * - * Note: The matched text must not change between the call of - * vim_regexec()/vim_regexec_multi() and vim_regsub()! It would make the back - * references invalid! - * - * Returns the size of the replacement, including terminating NUL. - */ -int vim_regsub(regmatch_T *rmp, char_u *source, char_u *dest, int copy, int magic, int backslash) + if (argcount == 0) { + // called function doesn't take an argument + return 0; + } + + // Relies on sl_list to be the first item in staticList10_T. + init_static_list((staticList10_T *)(argv->vval.v_list)); + + // There are always 10 list items in staticList10_T. + li = argv->vval.v_list->lv_first; + for (i = 0; i < 10; i++) { + s = rsm.sm_match->startp[i]; + if (s == NULL || rsm.sm_match->endp[i] == NULL) { + s = NULL; + } else { + s = vim_strnsave(s, (int)(rsm.sm_match->endp[i] - s)); + } + li->li_tv.v_type = VAR_STRING; + li->li_tv.vval.v_string = s; + li = li->li_next; + } + return 1; +} + +static void clear_submatch_list(staticList10_T *sl) +{ + int i; + + for (i = 0; i < 10; i++) { + xfree(sl->sl_items[i].li_tv.vval.v_string); + } +} + +/// vim_regsub() - perform substitutions after a vim_regexec() or +/// vim_regexec_multi() match. +/// +/// If "copy" is TRUE really copy into "dest". +/// If "copy" is FALSE nothing is copied, this is just to find out the length +/// of the result. +/// +/// If "backslash" is TRUE, a backslash will be removed later, need to double +/// them to keep them, and insert a backslash before a CR to avoid it being +/// replaced with a line break later. +/// +/// Note: The matched text must not change between the call of +/// vim_regexec()/vim_regexec_multi() and vim_regsub()! It would make the back +/// references invalid! +/// +/// Returns the size of the replacement, including terminating NUL. +int vim_regsub(regmatch_T *rmp, char_u *source, typval_T *expr, char_u *dest, + int copy, int magic, int backslash) { - reg_match = rmp; - reg_mmatch = NULL; - reg_maxline = 0; - reg_buf = curbuf; - reg_line_lbr = TRUE; - return vim_regsub_both(source, dest, copy, magic, backslash); + regexec_T rex_save; + bool rex_in_use_save = rex_in_use; + + if (rex_in_use) { + // Being called recursively, save the state. + rex_save = rex; + } + rex_in_use = true; + + rex.reg_match = rmp; + rex.reg_mmatch = NULL; + rex.reg_maxline = 0; + rex.reg_buf = curbuf; + rex.reg_line_lbr = true; + int result = vim_regsub_both(source, expr, dest, copy, magic, backslash); + + rex_in_use = rex_in_use_save; + if (rex_in_use) { + rex = rex_save; + } + + return result; } int vim_regsub_multi(regmmatch_T *rmp, linenr_T lnum, char_u *source, char_u *dest, int copy, int magic, int backslash) { - reg_match = NULL; - reg_mmatch = rmp; - reg_buf = curbuf; /* always works on the current buffer! */ - reg_firstlnum = lnum; - reg_maxline = curbuf->b_ml.ml_line_count - lnum; - reg_line_lbr = FALSE; - return vim_regsub_both(source, dest, copy, magic, backslash); + regexec_T rex_save; + bool rex_in_use_save = rex_in_use; + + if (rex_in_use) { + // Being called recursively, save the state. + rex_save = rex; + } + rex_in_use = true; + + rex.reg_match = NULL; + rex.reg_mmatch = rmp; + rex.reg_buf = curbuf; // always works on the current buffer! + rex.reg_firstlnum = lnum; + rex.reg_maxline = curbuf->b_ml.ml_line_count - lnum; + rex.reg_line_lbr = false; + int result = vim_regsub_both(source, NULL, dest, copy, magic, backslash); + + rex_in_use = rex_in_use_save; + if (rex_in_use) { + rex = rex_save; + } + + return result; } -static int vim_regsub_both(char_u *source, char_u *dest, int copy, int magic, int backslash) +static int vim_regsub_both(char_u *source, typval_T *expr, char_u *dest, + int copy, int magic, int backslash) { char_u *src; char_u *dst; @@ -6495,8 +6594,8 @@ static int vim_regsub_both(char_u *source, char_u *dest, int copy, int magic, in int len = 0; /* init for GCC */ static char_u *eval_result = NULL; - /* Be paranoid... */ - if (source == NULL || dest == NULL) { + // Be paranoid... + if ((source == NULL && expr == NULL) || dest == NULL) { EMSG(_(e_null)); return 0; } @@ -6505,16 +6604,12 @@ static int vim_regsub_both(char_u *source, char_u *dest, int copy, int magic, in src = source; dst = dest; - /* - * When the substitute part starts with "\=" evaluate it as an expression. - */ - if (source[0] == '\\' && source[1] == '=' - && !can_f_submatch /* can't do this recursively */ - ) { - /* To make sure that the length doesn't change between checking the - * length and copying the string, and to speed up things, the - * resulting string is saved from the call with "copy" == FALSE to the - * call with "copy" == TRUE. */ + // When the substitute part starts with "\=" evaluate it as an expression. + if (expr != NULL || (source[0] == '\\' && source[1] == '=')) { + // To make sure that the length doesn't change between checking the + // length and copying the string, and to speed up things, the + // resulting string is saved from the call with "copy" == FALSE to the + // call with "copy" == TRUE. if (copy) { if (eval_result != NULL) { STRCPY(dest, eval_result); @@ -6523,45 +6618,83 @@ static int vim_regsub_both(char_u *source, char_u *dest, int copy, int magic, in eval_result = NULL; } } else { - win_T *save_reg_win; - int save_ireg_ic; + int prev_can_f_submatch = can_f_submatch; + regsubmatch_T rsm_save; xfree(eval_result); - /* The expression may contain substitute(), which calls us - * recursively. Make sure submatch() gets the text from the first - * level. Don't need to save "reg_buf", because - * vim_regexec_multi() can't be called recursively. */ - submatch_match = reg_match; - submatch_mmatch = reg_mmatch; - submatch_firstlnum = reg_firstlnum; - submatch_maxline = reg_maxline; - submatch_line_lbr = reg_line_lbr; - save_reg_win = reg_win; - save_ireg_ic = ireg_ic; - can_f_submatch = TRUE; - - eval_result = eval_to_string(source + 2, NULL, TRUE); + // The expression may contain substitute(), which calls us + // recursively. Make sure submatch() gets the text from the first + // level. + if (can_f_submatch) { + rsm_save = rsm; + } + can_f_submatch = true; + rsm.sm_match = rex.reg_match; + rsm.sm_mmatch = rex.reg_mmatch; + rsm.sm_firstlnum = rex.reg_firstlnum; + rsm.sm_maxline = rex.reg_maxline; + rsm.sm_line_lbr = rex.reg_line_lbr; + + if (expr != NULL) { + typval_T argv[2]; + int dummy; + typval_T rettv; + staticList10_T matchList; + + rettv.v_type = VAR_STRING; + rettv.vval.v_string = NULL; + argv[0].v_type = VAR_LIST; + argv[0].vval.v_list = &matchList.sl_list; + matchList.sl_list.lv_len = 0; + if (expr->v_type == VAR_FUNC) { + s = expr->vval.v_string; + call_func(s, (int)STRLEN(s), &rettv, 1, argv, + fill_submatch_list, 0L, 0L, &dummy, + true, NULL, NULL); + } else if (expr->v_type == VAR_PARTIAL) { + partial_T *partial = expr->vval.v_partial; + + s = partial_name(partial); + call_func(s, (int)STRLEN(s), &rettv, 1, argv, + fill_submatch_list, 0L, 0L, &dummy, + true, partial, NULL); + } + if (matchList.sl_list.lv_len > 0) { + // fill_submatch_list() was called. + clear_submatch_list(&matchList); + } + char buf[NUMBUFLEN]; + eval_result = (char_u *)tv_get_string_buf_chk(&rettv, buf); + if (eval_result != NULL) { + eval_result = vim_strsave(eval_result); + } + tv_clear(&rettv); + } else { + eval_result = eval_to_string(source + 2, NULL, true); + } + if (eval_result != NULL) { int had_backslash = FALSE; for (s = eval_result; *s != NUL; mb_ptr_adv(s)) { - /* Change NL to CR, so that it becomes a line break, - * unless called from vim_regexec_nl(). - * Skip over a backslashed character. */ - if (*s == NL && !submatch_line_lbr) + // Change NL to CR, so that it becomes a line break, + // unless called from vim_regexec_nl(). + // Skip over a backslashed character. + if (*s == NL && !rsm.sm_line_lbr) { *s = CAR; - else if (*s == '\\' && s[1] != NUL) { - ++s; + } else if (*s == '\\' && s[1] != NUL) { + s++; /* Change NL to CR here too, so that this works: * :s/abc\\\ndef/\="aaa\\\nbbb"/ on text: * abc\ * def * Not when called from vim_regexec_nl(). */ - if (*s == NL && !submatch_line_lbr) + if (*s == NL && !rsm.sm_line_lbr) { *s = CAR; - had_backslash = TRUE; + } + had_backslash = true; } } if (had_backslash && backslash) { @@ -6574,14 +6707,10 @@ static int vim_regsub_both(char_u *source, char_u *dest, int copy, int magic, in dst += STRLEN(eval_result); } - reg_match = submatch_match; - reg_mmatch = submatch_mmatch; - reg_firstlnum = submatch_firstlnum; - reg_maxline = submatch_maxline; - reg_line_lbr = submatch_line_lbr; - reg_win = save_reg_win; - ireg_ic = save_ireg_ic; - can_f_submatch = FALSE; + can_f_submatch = prev_can_f_submatch; + if (can_f_submatch) { + rsm = rsm_save; + } } } else while ((c = *src++) != NUL) { @@ -6679,43 +6808,50 @@ static int vim_regsub_both(char_u *source, char_u *dest, int copy, int magic, in dst++; } else { if (REG_MULTI) { - clnum = reg_mmatch->startpos[no].lnum; - if (clnum < 0 || reg_mmatch->endpos[no].lnum < 0) + clnum = rex.reg_mmatch->startpos[no].lnum; + if (clnum < 0 || rex.reg_mmatch->endpos[no].lnum < 0) { s = NULL; - else { - s = reg_getline(clnum) + reg_mmatch->startpos[no].col; - if (reg_mmatch->endpos[no].lnum == clnum) - len = reg_mmatch->endpos[no].col - - reg_mmatch->startpos[no].col; - else + } else { + s = reg_getline(clnum) + rex.reg_mmatch->startpos[no].col; + if (rex.reg_mmatch->endpos[no].lnum == clnum) { + len = rex.reg_mmatch->endpos[no].col + - rex.reg_mmatch->startpos[no].col; + } else { len = (int)STRLEN(s); + } } } else { - s = reg_match->startp[no]; - if (reg_match->endp[no] == NULL) + s = rex.reg_match->startp[no]; + if (rex.reg_match->endp[no] == NULL) { s = NULL; - else - len = (int)(reg_match->endp[no] - s); + } else { + len = (int)(rex.reg_match->endp[no] - s); + } } if (s != NULL) { for (;; ) { if (len == 0) { if (REG_MULTI) { - if (reg_mmatch->endpos[no].lnum == clnum) + if (rex.reg_mmatch->endpos[no].lnum == clnum) { break; - if (copy) + } + if (copy) { *dst = CAR; - ++dst; + } + dst++; s = reg_getline(++clnum); - if (reg_mmatch->endpos[no].lnum == clnum) - len = reg_mmatch->endpos[no].col; - else + if (rex.reg_mmatch->endpos[no].lnum == clnum) { + len = rex.reg_mmatch->endpos[no].col; + } else { len = (int)STRLEN(s); - } else + } + } else { break; - } else if (*s == NUL) { /* we hit NUL. */ - if (copy) + } + } else if (*s == NUL) { // we hit NUL. + if (copy) { EMSG(_(e_re_damg)); + } goto exit; } else { if (backslash && (*s == CAR || *s == '\\')) { @@ -6789,16 +6925,16 @@ exit: static char_u *reg_getline_submatch(linenr_T lnum) { char_u *s; - linenr_T save_first = reg_firstlnum; - linenr_T save_max = reg_maxline; + linenr_T save_first = rex.reg_firstlnum; + linenr_T save_max = rex.reg_maxline; - reg_firstlnum = submatch_firstlnum; - reg_maxline = submatch_maxline; + rex.reg_firstlnum = rsm.sm_firstlnum; + rex.reg_maxline = rsm.sm_maxline; s = reg_getline(lnum); - reg_firstlnum = save_first; - reg_maxline = save_max; + rex.reg_firstlnum = save_first; + rex.reg_maxline = save_max; return s; } @@ -6817,39 +6953,41 @@ char_u *reg_submatch(int no) if (!can_f_submatch || no < 0) return NULL; - if (submatch_match == NULL) { + if (rsm.sm_match == NULL) { ssize_t len; /* * First round: compute the length and allocate memory. * Second round: copy the text. */ - for (round = 1; round <= 2; ++round) { - lnum = submatch_mmatch->startpos[no].lnum; - if (lnum < 0 || submatch_mmatch->endpos[no].lnum < 0) + for (round = 1; round <= 2; round++) { + lnum = rsm.sm_mmatch->startpos[no].lnum; + if (lnum < 0 || rsm.sm_mmatch->endpos[no].lnum < 0) { return NULL; + } - s = reg_getline_submatch(lnum) + submatch_mmatch->startpos[no].col; - if (s == NULL) /* anti-crash check, cannot happen? */ + s = reg_getline_submatch(lnum) + rsm.sm_mmatch->startpos[no].col; + if (s == NULL) { // anti-crash check, cannot happen? break; - if (submatch_mmatch->endpos[no].lnum == lnum) { - /* Within one line: take form start to end col. */ - len = submatch_mmatch->endpos[no].col - - submatch_mmatch->startpos[no].col; - if (round == 2) + } + if (rsm.sm_mmatch->endpos[no].lnum == lnum) { + // Within one line: take form start to end col. + len = rsm.sm_mmatch->endpos[no].col - rsm.sm_mmatch->startpos[no].col; + if (round == 2) { STRLCPY(retval, s, len + 1); - ++len; + } + len++; } else { - /* Multiple lines: take start line from start col, middle - * lines completely and end line up to end col. */ - len = STRLEN(s); + // Multiple lines: take start line from start col, middle + // lines completely and end line up to end col. + len = (ssize_t)STRLEN(s); if (round == 2) { STRCPY(retval, s); retval[len] = '\n'; } - ++len; - ++lnum; - while (lnum < submatch_mmatch->endpos[no].lnum) { + len++; + lnum++; + while (lnum < rsm.sm_mmatch->endpos[no].lnum) { s = reg_getline_submatch(lnum++); if (round == 2) STRCPY(retval + len, s); @@ -6858,13 +6996,15 @@ char_u *reg_submatch(int no) retval[len] = '\n'; ++len; } - if (round == 2) + if (round == 2) { STRNCPY(retval + len, reg_getline_submatch(lnum), - submatch_mmatch->endpos[no].col); - len += submatch_mmatch->endpos[no].col; - if (round == 2) - retval[len] = NUL; - ++len; + rsm.sm_mmatch->endpos[no].col); + } + len += rsm.sm_mmatch->endpos[no].col; + if (round == 2) { + retval[len] = NUL; // -V595 + } + len++; } if (retval == NULL) { @@ -6872,11 +7012,12 @@ char_u *reg_submatch(int no) } } } else { - s = submatch_match->startp[no]; - if (s == NULL || submatch_match->endp[no] == NULL) + s = rsm.sm_match->startp[no]; + if (s == NULL || rsm.sm_match->endp[no] == NULL) { retval = NULL; - else - retval = vim_strnsave(s, (int)(submatch_match->endp[no] - s)); + } else { + retval = vim_strnsave(s, (int)(rsm.sm_match->endp[no] - s)); + } } return retval; @@ -6896,39 +7037,39 @@ list_T *reg_submatch_list(int no) linenr_T slnum; linenr_T elnum; list_T *list; - char_u *s; + const char *s; - if (submatch_match == NULL) { - slnum = submatch_mmatch->startpos[no].lnum; - elnum = submatch_mmatch->endpos[no].lnum; + if (rsm.sm_match == NULL) { + slnum = rsm.sm_mmatch->startpos[no].lnum; + elnum = rsm.sm_mmatch->endpos[no].lnum; if (slnum < 0 || elnum < 0) { return NULL; } - colnr_T scol = submatch_mmatch->startpos[no].col; - colnr_T ecol = submatch_mmatch->endpos[no].col; + colnr_T scol = rsm.sm_mmatch->startpos[no].col; + colnr_T ecol = rsm.sm_mmatch->endpos[no].col; - list = list_alloc(); + list = tv_list_alloc(); - s = reg_getline_submatch(slnum) + scol; + s = (const char *)reg_getline_submatch(slnum) + scol; if (slnum == elnum) { - list_append_string(list, s, ecol - scol); + tv_list_append_string(list, s, ecol - scol); } else { - list_append_string(list, s, -1); + tv_list_append_string(list, s, -1); for (int i = 1; i < elnum - slnum; i++) { - s = reg_getline_submatch(slnum + i); - list_append_string(list, s, -1); + s = (const char *)reg_getline_submatch(slnum + i); + tv_list_append_string(list, s, -1); } - s = reg_getline_submatch(elnum); - list_append_string(list, s, ecol); + s = (const char *)reg_getline_submatch(elnum); + tv_list_append_string(list, s, ecol); } } else { - s = submatch_match->startp[no]; - if (s == NULL || submatch_match->endp[no] == NULL) { + s = (const char *)rsm.sm_match->startp[no]; + if (s == NULL || rsm.sm_match->endp[no] == NULL) { return NULL; } - list = list_alloc(); - list_append_string(list, s, (int)(submatch_match->endp[no] - s)); + list = tv_list_alloc(); + tv_list_append_string(list, s, (const char *)rsm.sm_match->endp[no] - s); } return list; @@ -7082,6 +7223,19 @@ static void report_re_switch(char_u *pat) /// @return TRUE if there is a match, FALSE if not. static int vim_regexec_both(regmatch_T *rmp, char_u *line, colnr_T col, bool nl) { + regexec_T rex_save; + bool rex_in_use_save = rex_in_use; + + if (rex_in_use) { + // Being called recursively, save the state. + rex_save = rex; + } + rex_in_use = true; + rex.reg_startp = NULL; + rex.reg_endp = NULL; + rex.reg_startpos = NULL; + rex.reg_endpos = NULL; + int result = rmp->regprog->engine->regexec_nl(rmp, line, col, nl); // NFA engine aborted because it's very slow, use backtracking engine instead. @@ -7103,6 +7257,11 @@ static int vim_regexec_both(regmatch_T *rmp, char_u *line, colnr_T col, bool nl) p_re = save_p_re; } + rex_in_use = rex_in_use_save; + if (rex_in_use) { + rex = rex_save; + } + return result > 0; } @@ -7150,6 +7309,15 @@ long vim_regexec_multi( proftime_T *tm /* timeout limit or NULL */ ) { + regexec_T rex_save; + bool rex_in_use_save = rex_in_use; + + if (rex_in_use) { + // Being called recursively, save the state. + rex_save = rex; + } + rex_in_use = true; + int result = rmp->regprog->engine->regexec_multi(rmp, win, buf, lnum, col, tm); @@ -7173,5 +7341,10 @@ long vim_regexec_multi( p_re = save_p_re; } + rex_in_use = rex_in_use_save; + if (rex_in_use) { + rex = rex_save; + } + return result <= 0 ? 0 : result; } diff --git a/src/nvim/regexp.h b/src/nvim/regexp.h index 37513d8c27..97595c4d29 100644 --- a/src/nvim/regexp.h +++ b/src/nvim/regexp.h @@ -1,6 +1,10 @@ #ifndef NVIM_REGEXP_H #define NVIM_REGEXP_H +#include "nvim/types.h" +#include "nvim/buffer_defs.h" +#include "nvim/regexp_defs.h" + /* Second argument for vim_regcomp(). */ #define RE_MAGIC 1 /* 'magic' option */ #define RE_STRING 2 /* match in string instead of buffer text */ diff --git a/src/nvim/regexp_nfa.c b/src/nvim/regexp_nfa.c index 474f3df32a..93ba9ce097 100644 --- a/src/nvim/regexp_nfa.c +++ b/src/nvim/regexp_nfa.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + /* * NFA regular expression implementation. * @@ -53,13 +56,13 @@ enum { NFA_RANGE_MIN, /* low end of a range */ NFA_RANGE_MAX, /* high end of a range */ - NFA_CONCAT, /* concatenate two previous items (postfix - * only) */ - NFA_OR, /* \| (postfix only) */ - NFA_STAR, /* greedy * (posfix only) */ - NFA_STAR_NONGREEDY, /* non-greedy * (postfix only) */ - NFA_QUEST, /* greedy \? (postfix only) */ - NFA_QUEST_NONGREEDY, /* non-greedy \? (postfix only) */ + NFA_CONCAT, // concatenate two previous items (postfix + // only) + NFA_OR, // \| (postfix only) + NFA_STAR, // greedy * (postfix only) + NFA_STAR_NONGREEDY, // non-greedy * (postfix only) + NFA_QUEST, // greedy \? (postfix only) + NFA_QUEST_NONGREEDY, // non-greedy \? (postfix only) NFA_BOL, /* ^ Begin line */ NFA_EOL, /* $ End line */ @@ -631,6 +634,7 @@ static int nfa_recognize_char_class(char_u *start, char_u *end, int extra_newl) config |= CLASS_o7; break; } + return FAIL; case 'a': if (*(p + 2) == 'z') { config |= CLASS_az; @@ -639,6 +643,7 @@ static int nfa_recognize_char_class(char_u *start, char_u *end, int extra_newl) config |= CLASS_af; break; } + return FAIL; case 'A': if (*(p + 2) == 'Z') { config |= CLASS_AZ; @@ -647,7 +652,7 @@ static int nfa_recognize_char_class(char_u *start, char_u *end, int extra_newl) config |= CLASS_AF; break; } - /* FALLTHROUGH */ + return FAIL; default: return FAIL; } @@ -1983,7 +1988,7 @@ static int nfa_regpiece(void) // The engine is very inefficient (uses too many states) when the maximum // is much larger than the minimum and when the maximum is large. Bail out // if we can use the other engine. - if ((nfa_re_flags & RE_AUTO) && (maxval > minval + 200 || maxval > 500)) { + if ((nfa_re_flags & RE_AUTO) && (maxval > 500 || maxval > minval + 200)) { return FAIL; } @@ -2772,15 +2777,10 @@ static int nfa_max_width(nfa_state_T *startstate, int depth) case NFA_ANY: case NFA_START_COLL: case NFA_START_NEG_COLL: - /* matches some character, including composing chars */ - if (enc_utf8) - len += MB_MAXBYTES; - else if (has_mbyte) - len += 2; - else - ++len; + // Matches some character, including composing chars. + len += MB_MAXBYTES; if (state->c != NFA_ANY) { - /* skip over the characters */ + // Skip over the characters. state = state->out1->out; continue; } @@ -3893,23 +3893,27 @@ state_in_list ( return FALSE; } -/* - * Add "state" and possibly what follows to state list ".". - * Returns "subs_arg", possibly copied into temp_subs. - */ +// Offset used for "off" by addstate_here(). +#define ADDSTATE_HERE_OFFSET 10 +// Add "state" and possibly what follows to state list ".". +// Returns "subs_arg", possibly copied into temp_subs. static regsubs_T * addstate ( nfa_list_T *l, /* runtime state list */ nfa_state_T *state, /* state to update */ regsubs_T *subs_arg, /* pointers to subexpressions */ nfa_pim_T *pim, /* postponed look-behind match */ - int off /* byte offset, when -1 go to next line */ -) + int off_arg) /* byte offset, when -1 go to next line */ { int subidx; + int off = off_arg; + int add_here = FALSE; + int listindex = 0; + int k; + int found = FALSE; nfa_thread_T *thread; - lpos_T save_lpos; + struct multipos save_multipos; int save_in_use; char_u *save_ptr; int i; @@ -3920,6 +3924,12 @@ addstate ( int did_print = FALSE; #endif + if (off_arg <= -ADDSTATE_HERE_OFFSET) { + add_here = true; + off = 0; + listindex = -(off_arg + ADDSTATE_HERE_OFFSET); + } + switch (state->c) { case NFA_NCLOSE: case NFA_MCLOSE: @@ -3996,13 +4006,28 @@ addstate ( * lower position is preferred. */ if (!nfa_has_backref && pim == NULL && !l->has_pim && state->c != NFA_MATCH) { + + /* When called from addstate_here() do insert before + * existing states. */ + if (add_here) { + for (k = 0; k < l->n && k < listindex; ++k) { + if (l->t[k].state->id == state->id) { + found = TRUE; + break; + } + } + } + + if (!add_here || found) { skip_add: #ifdef REGEXP_DEBUG - nfa_set_code(state->c); - fprintf(log_fd, "> Not adding state %d to list %d. char %d: %s\n", - abs(state->id), l->id, state->c, code); + nfa_set_code(state->c); + fprintf(log_fd, "> Not adding state %d to list %d. char %d: %s pim: %s has_pim: %d found: %d\n", + abs(state->id), l->id, state->c, code, + pim == NULL ? "NULL" : "yes", l->has_pim, found); #endif return subs; + } } /* Do not add the state again when it exists with the same @@ -4058,14 +4083,14 @@ skip_add: case NFA_SPLIT: /* order matters here */ - subs = addstate(l, state->out, subs, pim, off); - subs = addstate(l, state->out1, subs, pim, off); + subs = addstate(l, state->out, subs, pim, off_arg); + subs = addstate(l, state->out1, subs, pim, off_arg); break; case NFA_EMPTY: case NFA_NOPEN: case NFA_NCLOSE: - subs = addstate(l, state->out, subs, pim, off); + subs = addstate(l, state->out, subs, pim, off_arg); break; case NFA_MOPEN: @@ -4102,15 +4127,13 @@ skip_add: /* avoid compiler warnings */ save_ptr = NULL; - save_lpos.lnum = 0; - save_lpos.col = 0; + memset(&save_multipos, 0, sizeof(save_multipos)); /* Set the position (with "off" added) in the subexpression. Save * and restore it when it was in use. Otherwise fill any gap. */ if (REG_MULTI) { if (subidx < sub->in_use) { - save_lpos.lnum = sub->list.multi[subidx].start_lnum; - save_lpos.col = sub->list.multi[subidx].start_col; + save_multipos = sub->list.multi[subidx]; save_in_use = -1; } else { save_in_use = sub->in_use; @@ -4145,7 +4168,7 @@ skip_add: sub->list.line[subidx].start = reginput + off; } - subs = addstate(l, state->out, subs, pim, off); + subs = addstate(l, state->out, subs, pim, off_arg); /* "subs" may have changed, need to set "sub" again */ if (state->c >= NFA_ZOPEN && state->c <= NFA_ZOPEN9) sub = &subs->synt; @@ -4153,9 +4176,8 @@ skip_add: sub = &subs->norm; if (save_in_use == -1) { - if (REG_MULTI){ - sub->list.multi[subidx].start_lnum = save_lpos.lnum; - sub->list.multi[subidx].start_col = save_lpos.col; + if (REG_MULTI) { + sub->list.multi[subidx] = save_multipos; } else sub->list.line[subidx].start = save_ptr; @@ -4168,9 +4190,10 @@ skip_add: ? subs->norm.list.multi[0].end_lnum >= 0 : subs->norm.list.line[0].end != NULL)) { /* Do not overwrite the position set by \ze. */ - subs = addstate(l, state->out, subs, pim, off); + subs = addstate(l, state->out, subs, pim, off_arg); break; } + // fallthrough case NFA_MCLOSE1: case NFA_MCLOSE2: case NFA_MCLOSE3: @@ -4208,8 +4231,7 @@ skip_add: if (sub->in_use <= subidx) sub->in_use = subidx + 1; if (REG_MULTI) { - save_lpos.lnum = sub->list.multi[subidx].end_lnum; - save_lpos.col = sub->list.multi[subidx].end_col; + save_multipos = sub->list.multi[subidx]; if (off == -1) { sub->list.multi[subidx].end_lnum = reglnum + 1; sub->list.multi[subidx].end_col = 0; @@ -4223,21 +4245,19 @@ skip_add: } else { save_ptr = sub->list.line[subidx].end; sub->list.line[subidx].end = reginput + off; - /* avoid compiler warnings */ - save_lpos.lnum = 0; - save_lpos.col = 0; + // avoid compiler warnings + memset(&save_multipos, 0, sizeof(save_multipos)); } - subs = addstate(l, state->out, subs, pim, off); + subs = addstate(l, state->out, subs, pim, off_arg); /* "subs" may have changed, need to set "sub" again */ if (state->c >= NFA_ZCLOSE && state->c <= NFA_ZCLOSE9) sub = &subs->synt; else sub = &subs->norm; - if (REG_MULTI){ - sub->list.multi[subidx].end_lnum = save_lpos.lnum; - sub->list.multi[subidx].end_col = save_lpos.col; + if (REG_MULTI) { + sub->list.multi[subidx] = save_multipos; } else sub->list.line[subidx].end = save_ptr; @@ -4266,8 +4286,10 @@ addstate_here ( int count; int listidx = *ip; - /* first add the state(s) at the end, so that we know how many there are */ - addstate(l, state, subs, pim, 0); + /* First add the state(s) at the end, so that we know how many there are. + * Pass the listidx as offset (avoids adding another argument to + * addstate(). */ + addstate(l, state, subs, pim, -listidx - ADDSTATE_HERE_OFFSET); /* when "*ip" was at the end of the list, nothing to do */ if (listidx + 1 == tlen) @@ -4346,7 +4368,7 @@ static int check_char_class(int class, int c) return OK; break; case NFA_CLASS_LOWER: - if (vim_islower(c) && c != 170 && c != 186) { + if (mb_islower(c) && c != 170 && c != 186) { return OK; } break; @@ -4364,8 +4386,9 @@ static int check_char_class(int class, int c) return OK; break; case NFA_CLASS_UPPER: - if (vim_isupper(c)) + if (mb_isupper(c)) { return OK; + } break; case NFA_CLASS_XDIGIT: if (ascii_isxdigit(c)) @@ -4384,8 +4407,9 @@ static int check_char_class(int class, int c) return OK; break; case NFA_CLASS_ESCAPE: - if (c == '\033') + if (c == ESC) { return OK; + } break; default: @@ -4828,17 +4852,10 @@ static int failure_chance(nfa_state_T *state, int depth) */ static int skip_to_start(int c, colnr_T *colp) { - char_u *s; - - /* Used often, do some work to avoid call overhead. */ - if (!ireg_ic - && !has_mbyte - ) - s = vim_strbyte(regline + *colp, c); - else - s = cstrchr(regline + *colp, c); - if (s == NULL) + const char_u *const s = cstrchr(regline + *colp, c); + if (s == NULL) { return FAIL; + } *colp = (int)(s - regline); return OK; } @@ -4865,7 +4882,7 @@ static long find_match_text(colnr_T startcol, int regstart, char_u *match_text) int c2_len = PTR2LEN(s2); int c2 = PTR2CHAR(s2); - if ((c1 != c2 && (!ireg_ic || vim_tolower(c1) != vim_tolower(c2))) + if ((c1 != c2 && (!rex.reg_ic || mb_tolower(c1) != mb_tolower(c2))) || c1_len != c2_len) { match = false; break; @@ -4878,13 +4895,13 @@ static long find_match_text(colnr_T startcol, int regstart, char_u *match_text) && !(enc_utf8 && utf_iscomposing(PTR2CHAR(s2)))) { cleanup_subexpr(); if (REG_MULTI) { - reg_startpos[0].lnum = reglnum; - reg_startpos[0].col = col; - reg_endpos[0].lnum = reglnum; - reg_endpos[0].col = s2 - regline; + rex.reg_startpos[0].lnum = reglnum; + rex.reg_startpos[0].col = col; + rex.reg_endpos[0].lnum = reglnum; + rex.reg_endpos[0].col = s2 - regline; } else { - reg_startp[0] = regline + col; - reg_endp[0] = s2; + rex.reg_startp[0] = regline + col; + rex.reg_endp[0] = s2; } return 1L; } @@ -5099,8 +5116,8 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, case NFA_MATCH: { // If the match ends before a composing characters and - // ireg_icombine is not set, that is not really a match. - if (enc_utf8 && !ireg_icombine && utf_iscomposing(curc)) { + // rex.reg_icombine is not set, that is not really a match. + if (enc_utf8 && !rex.reg_icombine && utf_iscomposing(curc)) { break; } nfa_match = true; @@ -5383,15 +5400,15 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, int this_class; // Get class of current and previous char (if it exists). - this_class = mb_get_class_buf(reginput, reg_buf); + this_class = mb_get_class_tab(reginput, rex.reg_buf->b_chartab); if (this_class <= 1) { result = false; } else if (reg_prev_class() == this_class) { result = false; } - } else if (!vim_iswordc_buf(curc, reg_buf) + } else if (!vim_iswordc_buf(curc, rex.reg_buf) || (reginput > regline - && vim_iswordc_buf(reginput[-1], reg_buf))) { + && vim_iswordc_buf(reginput[-1], rex.reg_buf))) { result = false; } if (result) { @@ -5408,15 +5425,15 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, int this_class, prev_class; // Get class of current and previous char (if it exists). - this_class = mb_get_class_buf(reginput, reg_buf); + this_class = mb_get_class_tab(reginput, rex.reg_buf->b_chartab); prev_class = reg_prev_class(); if (this_class == prev_class || prev_class == 0 || prev_class == 1) { result = false; } - } else if (!vim_iswordc_buf(reginput[-1], reg_buf) + } else if (!vim_iswordc_buf(reginput[-1], rex.reg_buf) || (reginput[0] != NUL - && vim_iswordc_buf(curc, reg_buf))) { + && vim_iswordc_buf(curc, rex.reg_buf))) { result = false; } if (result) { @@ -5427,14 +5444,14 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, case NFA_BOF: if (reglnum == 0 && reginput == regline - && (!REG_MULTI || reg_firstlnum == 1)) { + && (!REG_MULTI || rex.reg_firstlnum == 1)) { add_here = true; add_state = t->state->out; } break; case NFA_EOF: - if (reglnum == reg_maxline && curc == NUL) { + if (reglnum == rex.reg_maxline && curc == NUL) { add_here = true; add_state = t->state->out; } @@ -5458,7 +5475,7 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, // (no preceding character). len += mb_char2len(mc); } - if (ireg_icombine && len == 0) { + if (rex.reg_icombine && len == 0) { // If \Z was present, then ignore composing characters. // When ignoring the base character this always matches. if (sta->c != curc) { @@ -5509,14 +5526,14 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, } case NFA_NEWL: - if (curc == NUL && !reg_line_lbr && REG_MULTI - && reglnum <= reg_maxline) { + if (curc == NUL && !rex.reg_line_lbr && REG_MULTI + && reglnum <= rex.reg_maxline) { go_to_nextline = true; // Pass -1 for the offset, which means taking the position // at the start of the next line. add_state = t->state->out; add_off = -1; - } else if (curc == '\n' && reg_line_lbr) { + } else if (curc == '\n' && rex.reg_line_lbr) { // match \n as if it is an ordinary character add_state = t->state->out; add_off = 1; @@ -5557,23 +5574,25 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, result = result_if_matched; break; } - if (ireg_ic) { - int curc_low = vim_tolower(curc); - int done = FALSE; + if (rex.reg_ic) { + int curc_low = mb_tolower(curc); + int done = false; - for (; c1 <= c2; ++c1) - if (vim_tolower(c1) == curc_low) { + for (; c1 <= c2; c1++) { + if (mb_tolower(c1) == curc_low) { result = result_if_matched; done = TRUE; break; } - if (done) + } + if (done) { break; + } } } else if (state->c < 0 ? check_char_class(state->c, curc) : (curc == state->c - || (ireg_ic && vim_tolower(curc) - == vim_tolower(state->c)))) { + || (rex.reg_ic && mb_tolower(curc) + == mb_tolower(state->c)))) { result = result_if_matched; break; } @@ -5620,13 +5639,13 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, break; case NFA_KWORD: // \k - result = vim_iswordp_buf(reginput, reg_buf); + result = vim_iswordp_buf(reginput, rex.reg_buf); ADD_STATE_IF_MATCH(t->state); break; case NFA_SKWORD: // \K result = !ascii_isdigit(curc) - && vim_iswordp_buf(reginput, reg_buf); + && vim_iswordp_buf(reginput, rex.reg_buf); ADD_STATE_IF_MATCH(t->state); break; @@ -5741,24 +5760,24 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, break; case NFA_LOWER_IC: // [a-z] - result = ri_lower(curc) || (ireg_ic && ri_upper(curc)); + result = ri_lower(curc) || (rex.reg_ic && ri_upper(curc)); ADD_STATE_IF_MATCH(t->state); break; case NFA_NLOWER_IC: // [^a-z] result = curc != NUL - && !(ri_lower(curc) || (ireg_ic && ri_upper(curc))); + && !(ri_lower(curc) || (rex.reg_ic && ri_upper(curc))); ADD_STATE_IF_MATCH(t->state); break; case NFA_UPPER_IC: // [A-Z] - result = ri_upper(curc) || (ireg_ic && ri_lower(curc)); + result = ri_upper(curc) || (rex.reg_ic && ri_lower(curc)); ADD_STATE_IF_MATCH(t->state); break; case NFA_NUPPER_IC: // [^A-Z] result = curc != NUL - && !(ri_upper(curc) || (ireg_ic && ri_lower(curc))); + && !(ri_upper(curc) || (rex.reg_ic && ri_lower(curc))); ADD_STATE_IF_MATCH(t->state); break; @@ -5832,13 +5851,15 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, case NFA_LNUM_GT: case NFA_LNUM_LT: assert(t->state->val >= 0 - && !((reg_firstlnum > 0 && reglnum > LONG_MAX - reg_firstlnum) - || (reg_firstlnum <0 && reglnum < LONG_MIN + reg_firstlnum)) - && reglnum + reg_firstlnum >= 0); + && !((rex.reg_firstlnum > 0 + && reglnum > LONG_MAX - rex.reg_firstlnum) + || (rex.reg_firstlnum < 0 + && reglnum < LONG_MIN + rex.reg_firstlnum)) + && reglnum + rex.reg_firstlnum >= 0); result = (REG_MULTI && nfa_re_num_cmp((uintmax_t)t->state->val, t->state->c - NFA_LNUM, - (uintmax_t)(reglnum + reg_firstlnum))); + (uintmax_t)(reglnum + rex.reg_firstlnum))); if (result) { add_here = true; add_state = t->state->out; @@ -5874,7 +5895,7 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, } result = false; - win_T *wp = reg_win == NULL ? curwin : reg_win; + win_T *wp = rex.reg_win == NULL ? curwin : rex.reg_win; if (op == 1 && col - 1 > t->state->val && col > 100) { long ts = wp->w_buffer->b_p_ts; @@ -5901,18 +5922,18 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, case NFA_MARK_GT: case NFA_MARK_LT: { - pos_T *pos = getmark_buf(reg_buf, t->state->val, FALSE); + pos_T *pos = getmark_buf(rex.reg_buf, t->state->val, false); // Compare the mark position to the match position. result = (pos != NULL // mark doesn't exist && pos->lnum > 0 // mark isn't set in reg_buf - && (pos->lnum == reglnum + reg_firstlnum + && (pos->lnum == reglnum + rex.reg_firstlnum ? (pos->col == (colnr_T)(reginput - regline) ? t->state->c == NFA_MARK : (pos->col < (colnr_T)(reginput - regline) ? t->state->c == NFA_MARK_GT : t->state->c == NFA_MARK_LT)) - : (pos->lnum < reglnum + reg_firstlnum + : (pos->lnum < reglnum + rex.reg_firstlnum ? t->state->c == NFA_MARK_GT : t->state->c == NFA_MARK_LT))); if (result) { @@ -5923,10 +5944,10 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, } case NFA_CURSOR: - result = (reg_win != NULL - && (reglnum + reg_firstlnum == reg_win->w_cursor.lnum) + result = (rex.reg_win != NULL + && (reglnum + rex.reg_firstlnum == rex.reg_win->w_cursor.lnum) && ((colnr_T)(reginput - regline) - == reg_win->w_cursor.col)); + == rex.reg_win->w_cursor.col)); if (result) { add_here = true; add_state = t->state->out; @@ -5976,12 +5997,13 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, #endif result = (c == curc); - if (!result && ireg_ic) - result = vim_tolower(c) == vim_tolower(curc); + if (!result && rex.reg_ic) { + result = mb_tolower(c) == mb_tolower(curc); + } - // If ireg_icombine is not set only skip over the character + // If rex.reg_icombine is not set only skip over the character // itself. When it is set skip over composing characters. - if (result && enc_utf8 && !ireg_icombine) { + if (result && enc_utf8 && !rex.reg_icombine) { clen = utf_ptr2len(reginput); } @@ -6089,8 +6111,8 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, && ((toplevel && reglnum == 0 && clen != 0 - && (ireg_maxcol == 0 - || (colnr_T)(reginput - regline) < ireg_maxcol)) + && (rex.reg_maxcol == 0 + || (colnr_T)(reginput - regline) < rex.reg_maxcol)) || (nfa_endp != NULL && (REG_MULTI ? (reglnum < nfa_endp->se_u.pos.lnum @@ -6125,8 +6147,8 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, // Checking if the required start character matches is // cheaper than adding a state that won't match. c = PTR2CHAR(reginput + clen); - if (c != prog->regstart && (!ireg_ic || vim_tolower(c) - != vim_tolower(prog->regstart))) { + if (c != prog->regstart && (!rex.reg_ic || mb_tolower(c) + != mb_tolower(prog->regstart))) { #ifdef REGEXP_DEBUG fprintf(log_fd, " Skipping start state, regstart does not match\n"); @@ -6251,34 +6273,37 @@ static long nfa_regtry(nfa_regprog_T *prog, colnr_T col, proftime_T *tm) cleanup_subexpr(); if (REG_MULTI) { for (i = 0; i < subs.norm.in_use; i++) { - reg_startpos[i].lnum = subs.norm.list.multi[i].start_lnum; - reg_startpos[i].col = subs.norm.list.multi[i].start_col; + rex.reg_startpos[i].lnum = subs.norm.list.multi[i].start_lnum; + rex.reg_startpos[i].col = subs.norm.list.multi[i].start_col; - reg_endpos[i].lnum = subs.norm.list.multi[i].end_lnum; - reg_endpos[i].col = subs.norm.list.multi[i].end_col; + rex.reg_endpos[i].lnum = subs.norm.list.multi[i].end_lnum; + rex.reg_endpos[i].col = subs.norm.list.multi[i].end_col; } - if (reg_startpos[0].lnum < 0) { - reg_startpos[0].lnum = 0; - reg_startpos[0].col = col; + if (rex.reg_startpos[0].lnum < 0) { + rex.reg_startpos[0].lnum = 0; + rex.reg_startpos[0].col = col; + } + if (rex.reg_endpos[0].lnum < 0) { + // pattern has a \ze but it didn't match, use current end + rex.reg_endpos[0].lnum = reglnum; + rex.reg_endpos[0].col = (int)(reginput - regline); + } else { + // Use line number of "\ze". + reglnum = rex.reg_endpos[0].lnum; } - if (reg_endpos[0].lnum < 0) { - /* pattern has a \ze but it didn't match, use current end */ - reg_endpos[0].lnum = reglnum; - reg_endpos[0].col = (int)(reginput - regline); - } else - /* Use line number of "\ze". */ - reglnum = reg_endpos[0].lnum; } else { for (i = 0; i < subs.norm.in_use; i++) { - reg_startp[i] = subs.norm.list.line[i].start; - reg_endp[i] = subs.norm.list.line[i].end; + rex.reg_startp[i] = subs.norm.list.line[i].start; + rex.reg_endp[i] = subs.norm.list.line[i].end; } - if (reg_startp[0] == NULL) - reg_startp[0] = regline + col; - if (reg_endp[0] == NULL) - reg_endp[0] = reginput; + if (rex.reg_startp[0] == NULL) { + rex.reg_startp[0] = regline + col; + } + if (rex.reg_endp[0] == NULL) { + rex.reg_endp[0] = reginput; + } } /* Package any found \z(...\) matches for export. Default is none. */ @@ -6332,14 +6357,14 @@ static long nfa_regexec_both(char_u *line, colnr_T startcol, proftime_T *tm) colnr_T col = startcol; if (REG_MULTI) { - prog = (nfa_regprog_T *)reg_mmatch->regprog; - line = reg_getline((linenr_T)0); /* relative to the cursor */ - reg_startpos = reg_mmatch->startpos; - reg_endpos = reg_mmatch->endpos; + prog = (nfa_regprog_T *)rex.reg_mmatch->regprog; + line = reg_getline((linenr_T)0); // relative to the cursor + rex.reg_startpos = rex.reg_mmatch->startpos; + rex.reg_endpos = rex.reg_mmatch->endpos; } else { - prog = (nfa_regprog_T *)reg_match->regprog; - reg_startp = reg_match->startp; - reg_endp = reg_match->endp; + prog = (nfa_regprog_T *)rex.reg_match->regprog; + rex.reg_startp = rex.reg_match->startp; + rex.reg_endp = rex.reg_match->endp; } /* Be paranoid... */ @@ -6348,15 +6373,17 @@ static long nfa_regexec_both(char_u *line, colnr_T startcol, proftime_T *tm) goto theend; } - /* If pattern contains "\c" or "\C": overrule value of ireg_ic */ - if (prog->regflags & RF_ICASE) - ireg_ic = TRUE; - else if (prog->regflags & RF_NOICASE) - ireg_ic = FALSE; + // If pattern contains "\c" or "\C": overrule value of rex.reg_ic + if (prog->regflags & RF_ICASE) { + rex.reg_ic = true; + } else if (prog->regflags & RF_NOICASE) { + rex.reg_ic = false; + } - /* If pattern contains "\Z" overrule value of ireg_icombine */ - if (prog->regflags & RF_ICOMBINE) - ireg_icombine = TRUE; + // If pattern contains "\Z" overrule value of rex.reg_icombine + if (prog->regflags & RF_ICOMBINE) { + rex.reg_icombine = true; + } regline = line; reglnum = 0; /* relative to line */ @@ -6385,17 +6412,17 @@ static long nfa_regexec_both(char_u *line, colnr_T startcol, proftime_T *tm) if (skip_to_start(prog->regstart, &col) == FAIL) return 0L; - /* If match_text is set it contains the full text that must match. - * Nothing else to try. Doesn't handle combining chars well. */ - if (prog->match_text != NULL - && !ireg_icombine - ) + // If match_text is set it contains the full text that must match. + // Nothing else to try. Doesn't handle combining chars well. + if (prog->match_text != NULL && !rex.reg_icombine) { return find_match_text(col, prog->regstart, prog->match_text); + } } - /* If the start column is past the maximum column: no need to try. */ - if (ireg_maxcol > 0 && col >= ireg_maxcol) + // If the start column is past the maximum column: no need to try. + if (rex.reg_maxcol > 0 && col >= rex.reg_maxcol) { goto theend; + } nstate = prog->nstate; for (i = 0; i < nstate; ++i) { @@ -6547,15 +6574,15 @@ nfa_regexec_nl ( bool line_lbr ) { - reg_match = rmp; - reg_mmatch = NULL; - reg_maxline = 0; - reg_line_lbr = line_lbr; - reg_buf = curbuf; - reg_win = NULL; - ireg_ic = rmp->rm_ic; - ireg_icombine = FALSE; - ireg_maxcol = 0; + rex.reg_match = rmp; + rex.reg_mmatch = NULL; + rex.reg_maxline = 0; + rex.reg_line_lbr = line_lbr; + rex.reg_buf = curbuf; + rex.reg_win = NULL; + rex.reg_ic = rmp->rm_ic; + rex.reg_icombine = false; + rex.reg_maxcol = 0; return nfa_regexec_both(line, col, NULL); } @@ -6596,16 +6623,16 @@ nfa_regexec_nl ( static long nfa_regexec_multi(regmmatch_T *rmp, win_T *win, buf_T *buf, linenr_T lnum, colnr_T col, proftime_T *tm) { - reg_match = NULL; - reg_mmatch = rmp; - reg_buf = buf; - reg_win = win; - reg_firstlnum = lnum; - reg_maxline = reg_buf->b_ml.ml_line_count - lnum; - reg_line_lbr = FALSE; - ireg_ic = rmp->rmm_ic; - ireg_icombine = FALSE; - ireg_maxcol = rmp->rmm_maxcol; + rex.reg_match = NULL; + rex.reg_mmatch = rmp; + rex.reg_buf = buf; + rex.reg_win = win; + rex.reg_firstlnum = lnum; + rex.reg_maxline = rex.reg_buf->b_ml.ml_line_count - lnum; + rex.reg_line_lbr = false; + rex.reg_ic = rmp->rmm_ic; + rex.reg_icombine = false; + rex.reg_maxcol = rmp->rmm_maxcol; return nfa_regexec_both(NULL, col, tm); } diff --git a/src/nvim/screen.c b/src/nvim/screen.c index 41acc48f97..95973354bc 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + /* * screen.c: code for displaying on the screen * @@ -83,6 +86,7 @@ #include <stdbool.h> #include <string.h> +#include "nvim/log.h" #include "nvim/vim.h" #include "nvim/ascii.h" #include "nvim/arabic.h" @@ -102,6 +106,7 @@ #include "nvim/indent.h" #include "nvim/getchar.h" #include "nvim/main.h" +#include "nvim/mark.h" #include "nvim/mbyte.h" #include "nvim/memline.h" #include "nvim/memory.h" @@ -128,6 +133,7 @@ #include "nvim/version.h" #include "nvim/window.h" #include "nvim/os/time.h" +#include "nvim/api/private/helpers.h" #define MB_FILLER_CHAR '<' /* character used when a double-width character * doesn't fit. */ @@ -150,7 +156,6 @@ static schar_T *current_ScreenLine; StlClickDefinition *tab_page_click_defs = NULL; long tab_page_click_defs_size = 0; -# define SCREEN_LINE(r, o, e, c, rl) screen_line((r), (o), (e), (c), (rl)) #ifdef INCLUDE_GENERATED_DECLARATIONS # include "screen.c.generated.h" #endif @@ -375,15 +380,24 @@ void update_screen(int type) )) curwin->w_redr_type = type; - /* Redraw the tab pages line if needed. */ - if (redraw_tabline || type >= NOT_VALID) + // Redraw the tab pages line if needed. + if (redraw_tabline || type >= NOT_VALID) { + update_window_hl(curwin, type >= NOT_VALID); + FOR_ALL_TABS(tp) { + if (tp != curtab) { + update_window_hl(tp->tp_curwin, type >= NOT_VALID); + } + } draw_tabline(); + } /* * Correct stored syntax highlighting info for changes in each displayed * buffer. Each buffer must only be done once. */ FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { + update_window_hl(wp, type >= NOT_VALID); + if (wp->w_buffer->b_mod_set) { win_T *wwp; @@ -487,9 +501,10 @@ void update_single_line(win_T *wp, linenr_T lnum) int j; // Don't do anything if the screen structures are (not yet) valid. - if (!screen_valid(true)) { + if (!screen_valid(true) || updating_screen) { return; } + updating_screen = true; if (lnum >= wp->w_topline && lnum < wp->w_botline && foldedCount(wp, lnum, &win_foldinfo) == 0) { @@ -506,7 +521,8 @@ void update_single_line(win_T *wp, linenr_T lnum) row += wp->w_lines[j].wl_size; } } - need_cursor_line_redraw = FALSE; + need_cursor_line_redraw = false; + updating_screen = false; } @@ -976,7 +992,7 @@ static void win_update(win_T *wp) * first. */ if (mid_start == 0) { mid_end = wp->w_height; - if (lastwin == firstwin) { + if (ONE_WINDOW) { /* Clear the screen when it was not done by win_del_lines() or * win_ins_lines() above, "screen_cleared" is FALSE or MAYBE * then. */ @@ -1013,14 +1029,10 @@ static void win_update(win_T *wp) linenr_T from, to; if (VIsual_active) { - if (VIsual_active - && (VIsual_mode != wp->w_old_visual_mode - || type == INVERTED_ALL)) { - /* - * If the type of Visual selection changed, redraw the whole - * selection. Also when the ownership of the X selection is - * gained or lost. - */ + if (VIsual_mode != wp->w_old_visual_mode || type == INVERTED_ALL) { + // If the type of Visual selection changed, redraw the whole + // selection. Also when the ownership of the X selection is + // gained or lost. if (curwin->w_cursor.lnum < VIsual.lnum) { from = curwin->w_cursor.lnum; to = VIsual.lnum; @@ -1485,11 +1497,11 @@ static void win_update(win_T *wp) // Last line isn't finished: Display "@@@" in the last screen line. screen_puts_len((char_u *)"@@", 2, scr_row, wp->w_wincol, - hl_attr(HLF_AT)); + win_hl_attr(wp, HLF_AT)); screen_fill(scr_row, scr_row + 1, (int)wp->w_wincol + 2, (int)W_ENDCOL(wp), - '@', ' ', hl_attr(HLF_AT)); + '@', ' ', win_hl_attr(wp, HLF_AT)); set_empty_rows(wp, srow); wp->w_botline = lnum; } else if (dy_flags & DY_LASTLINE) { // 'display' has "lastline" @@ -1497,7 +1509,7 @@ static void win_update(win_T *wp) screen_fill(wp->w_winrow + wp->w_height - 1, wp->w_winrow + wp->w_height, W_ENDCOL(wp) - 3, W_ENDCOL(wp), - '@', '@', hl_attr(HLF_AT)); + '@', '@', win_hl_attr(wp, HLF_AT)); set_empty_rows(wp, srow); wp->w_botline = lnum; } else { @@ -1581,6 +1593,8 @@ static void win_draw_end(win_T *wp, int c1, int c2, int row, int endrow, hlf_T h # define FDC_OFF n int fdc = compute_foldcolumn(wp, 0); + int attr = win_hl_attr(wp, hl); + if (wp->w_p_rl) { // No check for cmdline window: should never be right-left. n = fdc; @@ -1591,7 +1605,7 @@ static void win_draw_end(win_T *wp, int c1, int c2, int row, int endrow, hlf_T h n = wp->w_width; screen_fill(wp->w_winrow + row, wp->w_winrow + endrow, W_ENDCOL(wp) - n, W_ENDCOL(wp), - ' ', ' ', hl_attr(HLF_FC)); + ' ', ' ', win_hl_attr(wp, HLF_FC)); } if (signcolumn_on(wp)) { @@ -1603,16 +1617,16 @@ static void win_draw_end(win_T *wp, int c1, int c2, int row, int endrow, hlf_T h } screen_fill(wp->w_winrow + row, wp->w_winrow + endrow, W_ENDCOL(wp) - nn, W_ENDCOL(wp) - n, - ' ', ' ', hl_attr(HLF_SC)); + ' ', ' ', win_hl_attr(wp, HLF_SC)); n = nn; } screen_fill(wp->w_winrow + row, wp->w_winrow + endrow, wp->w_wincol, W_ENDCOL(wp) - 1 - FDC_OFF, - c2, c2, hl_attr(hl)); + c2, c2, attr); screen_fill(wp->w_winrow + row, wp->w_winrow + endrow, W_ENDCOL(wp) - 1 - FDC_OFF, W_ENDCOL(wp) - FDC_OFF, - c1, c2, hl_attr(hl)); + c1, c2, attr); } else { if (cmdwin_type != 0 && wp == curwin) { /* draw the cmdline character in the leftmost column */ @@ -1621,7 +1635,7 @@ static void win_draw_end(win_T *wp, int c1, int c2, int row, int endrow, hlf_T h n = wp->w_width; screen_fill(wp->w_winrow + row, wp->w_winrow + endrow, wp->w_wincol, wp->w_wincol + n, - cmdwin_type, ' ', hl_attr(HLF_AT)); + cmdwin_type, ' ', win_hl_attr(wp, HLF_AT)); } if (fdc > 0) { int nn = n + fdc; @@ -1631,7 +1645,7 @@ static void win_draw_end(win_T *wp, int c1, int c2, int row, int endrow, hlf_T h nn = wp->w_width; screen_fill(wp->w_winrow + row, wp->w_winrow + endrow, wp->w_wincol + n, wp->w_wincol + nn, - ' ', ' ', hl_attr(HLF_FC)); + ' ', ' ', win_hl_attr(wp, HLF_FC)); n = nn; } @@ -1644,13 +1658,13 @@ static void win_draw_end(win_T *wp, int c1, int c2, int row, int endrow, hlf_T h } screen_fill(wp->w_winrow + row, wp->w_winrow + endrow, wp->w_wincol + n, wp->w_wincol + nn, - ' ', ' ', hl_attr(HLF_SC)); + ' ', ' ', win_hl_attr(wp, HLF_SC)); n = nn; } screen_fill(wp->w_winrow + row, wp->w_winrow + endrow, wp->w_wincol + FDC_OFF, W_ENDCOL(wp), - c1, c2, hl_attr(hl)); + c1, c2, attr); } set_empty_rows(wp, row); } @@ -1685,7 +1699,7 @@ static int compute_foldcolumn(win_T *wp, int col) */ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T lnum, int row) { - char_u buf[51]; + char_u buf[FOLD_TEXT_LEN]; pos_T *top, *bot; linenr_T lnume = lnum + fold_count - 1; int len; @@ -1712,10 +1726,9 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T */ if (cmdwin_type != 0 && wp == curwin) { ScreenLines[off] = cmdwin_type; - ScreenAttrs[off] = hl_attr(HLF_AT); - if (enc_utf8) - ScreenLinesUC[off] = 0; - ++col; + ScreenAttrs[off] = win_hl_attr(wp, HLF_AT); + ScreenLinesUC[off] = 0; + col++; } // 2. Add the 'foldcolumn' @@ -1727,12 +1740,14 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T int i; copy_text_attr(off + wp->w_width - fdc - col, buf, fdc, - hl_attr(HLF_FC)); - /* reverse the fold column */ - for (i = 0; i < fdc; ++i) + win_hl_attr(wp, HLF_FC)); + // reverse the fold column + for (i = 0; i < fdc; i++) { ScreenLines[off + wp->w_width - i - 1 - col] = buf[i]; - } else - copy_text_attr(off + col, buf, fdc, hl_attr(HLF_FC)); + } + } else { + copy_text_attr(off + col, buf, fdc, win_hl_attr(wp, HLF_FC)); + } col += fdc; } @@ -1745,7 +1760,7 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T /* Set all attributes of the 'number' or 'relativenumber' column and the * text */ - RL_MEMSET(col, hl_attr(HLF_FL), wp->w_width - col); + RL_MEMSET(col, win_hl_attr(wp, HLF_FL), wp->w_width - col); // If signs are being displayed, add two spaces. if (signcolumn_on(wp)) { @@ -1754,7 +1769,8 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T if (len > 2) { len = 2; } - copy_text_attr(off + col, (char_u *)" ", len, hl_attr(HLF_FL)); + copy_text_attr(off + col, (char_u *)" ", len, + win_hl_attr(wp, HLF_FL)); col += len; } } @@ -1786,13 +1802,14 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T } } - sprintf((char *)buf, fmt, w, num); - if (wp->w_p_rl) - /* the line number isn't reversed */ + snprintf((char *)buf, FOLD_TEXT_LEN, fmt, w, num); + if (wp->w_p_rl) { + // the line number isn't reversed copy_text_attr(off + wp->w_width - len - col, buf, len, - hl_attr(HLF_FL)); - else - copy_text_attr(off + col, buf, len, hl_attr(HLF_FL)); + win_hl_attr(wp, HLF_FL)); + } else { + copy_text_attr(off + col, buf, len, win_hl_attr(wp, HLF_FL)); + } col += len; } } @@ -1907,10 +1924,15 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T if (fill_fold >= 0x80) { ScreenLinesUC[off + col] = fill_fold; ScreenLinesC[0][off + col] = 0; - } else + ScreenLines[off + col] = 0x80; // avoid storing zero + } else { ScreenLinesUC[off + col] = 0; + ScreenLines[off + col] = fill_fold; + } + col++; + } else { + ScreenLines[off + col++] = fill_fold; } - ScreenLines[off + col++] = fill_fold; } if (text != buf) @@ -1950,12 +1972,12 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T len = wp->w_old_cursor_lcol; else len = wp->w_width - txtcol; - RL_MEMSET(wp->w_old_cursor_fcol + txtcol, hl_attr(HLF_V), - len - (int)wp->w_old_cursor_fcol); + RL_MEMSET(wp->w_old_cursor_fcol + txtcol, win_hl_attr(wp, HLF_V), + len - (int)wp->w_old_cursor_fcol); } } else { - /* Set all attributes of the text */ - RL_MEMSET(txtcol, hl_attr(HLF_V), wp->w_width - txtcol); + // Set all attributes of the text + RL_MEMSET(txtcol, win_hl_attr(wp, HLF_V), wp->w_width - txtcol); } } } @@ -1975,7 +1997,7 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T } if (txtcol >= 0 && txtcol < wp->w_width) { ScreenAttrs[off + txtcol] = - hl_combine_attr(ScreenAttrs[off + txtcol], hl_attr(HLF_MC)); + hl_combine_attr(ScreenAttrs[off + txtcol], win_hl_attr(wp, HLF_MC)); } txtcol = old_txtcol; j = wp->w_p_cc_cols[++i]; @@ -1991,11 +2013,11 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T txtcol -= wp->w_leftcol; if (txtcol >= 0 && txtcol < wp->w_width) ScreenAttrs[off + txtcol] = hl_combine_attr( - ScreenAttrs[off + txtcol], hl_attr(HLF_CUC)); + ScreenAttrs[off + txtcol], win_hl_attr(wp, HLF_CUC)); } - SCREEN_LINE(row + wp->w_winrow, wp->w_wincol, wp->w_width, - wp->w_width, FALSE); + screen_line(row + wp->w_winrow, wp->w_wincol, wp->w_width, + wp->w_width, false, wp); /* * Update w_cline_height and w_cline_folded if the cursor line was @@ -2095,16 +2117,16 @@ win_line ( bool nochange /* not updating for changed text */ ) { - int col; /* visual column on screen */ - unsigned off; /* offset in ScreenLines/ScreenAttrs */ - int c = 0; /* init for GCC */ - long vcol = 0; /* virtual column (for tabs) */ + int col = 0; // visual column on screen + unsigned off; // offset in ScreenLines/ScreenAttrs + int c = 0; // init for GCC + long vcol = 0; // virtual column (for tabs) long vcol_sbr = -1; // virtual column after showbreak - long vcol_prev = -1; /* "vcol" of previous character */ - char_u *line; /* current line */ - char_u *ptr; /* current position in "line" */ - int row; /* row in the window, excl w_winrow */ - int screen_row; /* row on the screen, incl w_winrow */ + long vcol_prev = -1; // "vcol" of previous character + char_u *line; // current line + char_u *ptr; // current position in "line" + int row; // row in the window, excl w_winrow + int screen_row; // row on the screen, incl w_winrow char_u extra[18]; /* line number and 'fdc' must fit in here */ int n_extra = 0; /* number of extra chars */ @@ -2178,7 +2200,7 @@ win_line ( int change_start = MAXCOL; /* first col of changed area */ int change_end = -1; /* last col of changed area */ colnr_T trailcol = MAXCOL; /* start of trailing spaces */ - int need_showbreak = FALSE; + int need_showbreak = false; // overlong line, skip first x chars int line_attr = 0; /* attribute for the whole line */ matchitem_T *cur; /* points to the match list */ match_T *shl; /* points to search_hl or a match */ @@ -2191,9 +2213,10 @@ win_line ( int prev_c1 = 0; /* first composing char for prev_c */ int did_line_attr = 0; - bool has_bufhl = false; // this buffer has highlight matches + bool search_attr_from_match = false; // if search_attr is from :match + bool has_bufhl = false; // this buffer has highlight matches int bufhl_attr = 0; // attributes desired by bufhl - bufhl_lineinfo_T bufhl_info; // bufhl data for this line + BufhlLineInfo bufhl_info; // bufhl data for this line /* draw_state: items that are drawn in sequence: */ #define WL_START 0 /* nothing done yet */ @@ -2209,7 +2232,7 @@ win_line ( int syntax_flags = 0; int syntax_seqnr = 0; int prev_syntax_id = 0; - int conceal_attr = hl_attr(HLF_CONCEAL); + int conceal_attr = win_hl_attr(wp, HLF_CONCEAL); int is_concealing = false; int boguscols = 0; ///< nonexistent columns added to ///< force wrapping @@ -2357,8 +2380,8 @@ win_line ( /* if inverting in this line set area_highlighting */ if (fromcol >= 0) { - area_highlighting = TRUE; - attr = hl_attr(HLF_V); + area_highlighting = true; + attr = win_hl_attr(wp, HLF_V); } } /* @@ -2382,8 +2405,8 @@ win_line ( /* do at least one character; happens when past end of line */ if (fromcol == tocol) tocol = fromcol + 1; - area_highlighting = TRUE; - attr = hl_attr(HLF_I); + area_highlighting = true; + attr = win_hl_attr(wp, HLF_I); } filler_lines = diff_check(wp, lnum); @@ -2411,7 +2434,11 @@ win_line ( // Highlight the current line in the quickfix window. if (bt_quickfix(wp->w_buffer) && qf_current_entry(wp) == lnum) { - line_attr = hl_attr(HLF_QFL); + line_attr = win_hl_attr(wp, HLF_QFL); + } + + if (wp->w_hl_attr_normal != 0) { + line_attr = hl_combine_attr(wp->w_hl_attr_normal, line_attr); } if (line_attr != 0) { @@ -2445,7 +2472,7 @@ win_line ( } else { /* Long line, use only the last SPWORDLEN bytes. */ nextlinecol = v - SPWORDLEN; - memmove(nextline, line + nextlinecol, SPWORDLEN); + memmove(nextline, line + nextlinecol, SPWORDLEN); // -V512 nextline_idx = SPWORDLEN + 1; } } @@ -2500,7 +2527,11 @@ win_line ( if (vcol > v) { vcol -= c; ptr = prev_ptr; - n_skip = v - vcol; + // If the character fits on the screen, don't need to skip it. + // Except for a TAB. + if (((*mb_ptr2cells)(ptr) >= c || *ptr == TAB) && col == 0) { + n_skip = v - vcol; + } } /* @@ -2577,13 +2608,14 @@ win_line ( * Do this for both search_hl and the match list. */ cur = wp->w_match_head; - shl_flag = FALSE; - while (cur != NULL || shl_flag == FALSE) { - if (shl_flag == FALSE) { + shl_flag = false; + while (cur != NULL || !shl_flag) { + if (!shl_flag) { shl = &search_hl; - shl_flag = TRUE; - } else - shl = &cur->hl; + shl_flag = true; + } else { + shl = &cur->hl; // -V595 + } shl->startcol = MAXCOL; shl->endcol = MAXCOL; shl->attr_cur = 0; @@ -2623,6 +2655,7 @@ win_line ( if ((long)shl->startcol < v) { // match at leftcol shl->attr_cur = shl->attr; search_attr = shl->attr; + search_attr_from_match = shl != &search_hl; } area_highlighting = true; } @@ -2637,9 +2670,9 @@ win_line ( && !(wp == curwin && VIsual_active)) { if (line_attr != 0 && !(State & INSERT) && bt_quickfix(wp->w_buffer) && qf_current_entry(wp) == lnum) { - line_attr = hl_combine_attr(hl_attr(HLF_CUL), line_attr); + line_attr = hl_combine_attr(win_hl_attr(wp, HLF_CUL), line_attr); } else { - line_attr = hl_attr(HLF_CUL); + line_attr = win_hl_attr(wp, HLF_CUL); } area_highlighting = true; } @@ -2672,7 +2705,7 @@ win_line ( /* Draw the cmdline character. */ n_extra = 1; c_extra = cmdwin_type; - char_attr = hl_attr(HLF_AT); + char_attr = win_hl_attr(wp, HLF_AT); } } @@ -2681,13 +2714,16 @@ win_line ( draw_state = WL_FOLD; if (fdc > 0) { - // Draw the 'foldcolumn'. - fill_foldcolumn(extra, wp, false, lnum); + // Draw the 'foldcolumn'. Allocate a buffer, "extra" may + // already be in use. + xfree(p_extra_free); + p_extra_free = xmalloc(12 + 1); + fill_foldcolumn(p_extra_free, wp, false, lnum); n_extra = fdc; - p_extra = extra; - p_extra[n_extra] = NUL; + p_extra_free[n_extra] = NUL; + p_extra = p_extra_free; c_extra = NUL; - char_attr = hl_attr(HLF_FC); + char_attr = win_hl_attr(wp, HLF_FC); } } @@ -2700,7 +2736,7 @@ win_line ( int text_sign; /* Draw two cells with the sign value or blank. */ c_extra = ' '; - char_attr = hl_attr(HLF_SC); + char_attr = win_hl_attr(wp, HLF_SC); n_extra = 2; if (row == startrow + filler_lines && filler_todo <= 0) { @@ -2757,14 +2793,15 @@ win_line ( } else c_extra = ' '; n_extra = number_width(wp) + 1; - char_attr = hl_attr(HLF_N); - /* When 'cursorline' is set highlight the line number of - * the current line differently. - * TODO: Can we use CursorLine instead of CursorLineNr - * when CursorLineNr isn't set? */ + char_attr = win_hl_attr(wp, HLF_N); + // When 'cursorline' is set highlight the line number of + // the current line differently. + // TODO(vim): Can we use CursorLine instead of CursorLineNr + // when CursorLineNr isn't set? if ((wp->w_p_cul || wp->w_p_rnu) - && lnum == wp->w_cursor.lnum) - char_attr = hl_attr(HLF_CLN); + && lnum == wp->w_cursor.lnum) { + char_attr = win_hl_attr(wp, HLF_CLN); + } } } @@ -2780,13 +2817,15 @@ win_line ( // draw 'breakindent': indent wrapped text accodringly if (draw_state == WL_BRI - 1 && n_extra == 0) { draw_state = WL_BRI; - if (wp->w_p_bri && n_extra == 0 && row != startrow && filler_lines == 0) { - char_attr = 0; // was: hl_attr(HLF_AT); + // if need_showbreak is set, breakindent also applies + if (wp->w_p_bri && (row != startrow || need_showbreak) + && filler_lines == 0) { + char_attr = wp->w_hl_attr_normal; if (diff_hlf != (hlf_T)0) { - char_attr = hl_attr(diff_hlf); + char_attr = win_hl_attr(wp, diff_hlf); if (wp->w_p_cul && lnum == wp->w_cursor.lnum) { - char_attr = hl_combine_attr(char_attr, hl_attr(HLF_CUL)); + char_attr = hl_combine_attr(char_attr, win_hl_attr(wp, HLF_CUL)); } } p_extra = NULL; @@ -2811,15 +2850,15 @@ win_line ( n_extra = col + 1; else n_extra = wp->w_width - col; - char_attr = hl_attr(HLF_DED); + char_attr = win_hl_attr(wp, HLF_DED); } if (*p_sbr != NUL && need_showbreak) { /* Draw 'showbreak' at the start of each broken line. */ p_extra = p_sbr; c_extra = NUL; n_extra = (int)STRLEN(p_sbr); - char_attr = hl_attr(HLF_AT); - need_showbreak = FALSE; + char_attr = win_hl_attr(wp, HLF_AT); + need_showbreak = false; vcol_sbr = vcol + MB_CHARLEN(p_sbr); /* Correct end of highlighted area for 'showbreak', * required when 'linebreak' is also set. */ @@ -2827,7 +2866,7 @@ win_line ( tocol += n_extra; /* combine 'showbreak' with 'cursorline' */ if (wp->w_p_cul && lnum == wp->w_cursor.lnum) { - char_attr = hl_combine_attr(char_attr, hl_attr(HLF_CUL)); + char_attr = hl_combine_attr(char_attr, win_hl_attr(wp, HLF_CUL)); } } } @@ -2840,8 +2879,9 @@ win_line ( c_extra = saved_c_extra; p_extra = saved_p_extra; char_attr = saved_char_attr; - } else - char_attr = 0; + } else { + char_attr = wp->w_hl_attr_normal; + } } } @@ -2850,13 +2890,14 @@ win_line ( && lnum == wp->w_cursor.lnum && vcol >= (long)wp->w_virtcol && filler_todo <= 0 ) { - SCREEN_LINE(screen_row, wp->w_wincol, col, -wp->w_width, wp->w_p_rl); - /* Pretend we have finished updating the window. Except when - * 'cursorcolumn' is set. */ - if (wp->w_p_cuc) + screen_line(screen_row, wp->w_wincol, col, -wp->w_width, wp->w_p_rl, wp); + // Pretend we have finished updating the window. Except when + // 'cursorcolumn' is set. + if (wp->w_p_cuc) { row = wp->w_cline_row + wp->w_cline_height; - else + } else { row = wp->w_height; + } break; } @@ -2920,7 +2961,6 @@ win_line ( } } else if (v == (long)shl->endcol) { shl->attr_cur = 0; - prev_syntax_id = 0; next_search_hl(wp, shl, lnum, (colnr_T)v, shl == &search_hl ? NULL : cur); @@ -2961,6 +3001,7 @@ win_line ( /* Use attributes from match with highest priority among * 'search_hl' and the match list. */ + search_attr_from_match = false; search_attr = search_hl.attr_cur; cur = wp->w_match_head; shl_flag = FALSE; @@ -2973,8 +3014,10 @@ win_line ( shl_flag = TRUE; } else shl = &cur->hl; - if (shl->attr_cur != 0) + if (shl->attr_cur != 0) { search_attr = shl->attr_cur; + search_attr_from_match = shl != &search_hl; + } if (shl != &search_hl && cur != NULL) cur = cur->next; } @@ -2982,14 +3025,16 @@ win_line ( if (diff_hlf != (hlf_T)0) { if (diff_hlf == HLF_CHD && ptr - line >= change_start - && n_extra == 0) - diff_hlf = HLF_TXD; /* changed text */ + && n_extra == 0) { + diff_hlf = HLF_TXD; // changed text + } if (diff_hlf == HLF_TXD && ptr - line > change_end - && n_extra == 0) - diff_hlf = HLF_CHD; /* changed line */ - line_attr = hl_attr(diff_hlf); + && n_extra == 0) { + diff_hlf = HLF_CHD; // changed line + } + line_attr = win_hl_attr(wp, diff_hlf); if (wp->w_p_cul && lnum == wp->w_cursor.lnum) { - line_attr = hl_combine_attr(line_attr, hl_attr(HLF_CUL)); + line_attr = hl_combine_attr(line_attr, win_hl_attr(wp, HLF_CUL)); } } @@ -3005,14 +3050,15 @@ win_line ( // (area_attr may be 0 when "noinvcur" is set). else if (line_attr != 0 && ((fromcol == -10 && tocol == MAXCOL) || vcol < fromcol || vcol_prev < fromcol_prev - || vcol >= tocol)) + || vcol >= tocol)) { char_attr = line_attr; - else { - attr_pri = FALSE; - if (has_syntax) + } else { + attr_pri = false; + if (has_syntax) { char_attr = syntax_attr; - else - char_attr = 0; + } else { + char_attr = wp->w_hl_attr_normal; + } } } @@ -3073,12 +3119,13 @@ win_line ( c = '>'; mb_c = c; mb_l = 1; - mb_utf8 = FALSE; - multi_attr = hl_attr(HLF_AT); - /* put the pointer back to output the double-width - * character at the start of the next line. */ - ++n_extra; - --p_extra; + mb_utf8 = false; + multi_attr = win_hl_attr(wp, HLF_AT); + + // put the pointer back to output the double-width + // character at the start of the next line. + n_extra++; + p_extra--; } else { n_extra -= mb_l - 1; p_extra += mb_l - 1; @@ -3135,14 +3182,14 @@ win_line ( p_extra = extra; c = *p_extra; - mb_c = mb_ptr2char_adv(&p_extra); + mb_c = mb_ptr2char_adv((const char_u **)&p_extra); mb_utf8 = (c >= 0x80); n_extra = (int)STRLEN(p_extra); c_extra = NUL; if (area_attr == 0 && search_attr == 0) { n_attr = n_extra + 1; - extra_attr = hl_attr(HLF_8); - saved_attr2 = char_attr; /* save current attr */ + extra_attr = win_hl_attr(wp, HLF_8); + saved_attr2 = char_attr; // save current attr } } else if (mb_l == 0) /* at the NUL at end-of-line */ mb_l = 1; @@ -3194,8 +3241,8 @@ win_line ( c = *p_extra++; if (area_attr == 0 && search_attr == 0) { n_attr = n_extra + 1; - extra_attr = hl_attr(HLF_8); - saved_attr2 = char_attr; /* save current attr */ + extra_attr = win_hl_attr(wp, HLF_8); + saved_attr2 = char_attr; // save current attr } mb_c = c; } @@ -3212,12 +3259,13 @@ win_line ( mb_c = c; mb_utf8 = FALSE; mb_l = 1; - multi_attr = hl_attr(HLF_AT); - /* Put pointer back so that the character will be - * displayed at the start of the next line. */ - --ptr; - } else if (*ptr != NUL) + multi_attr = win_hl_attr(wp, HLF_AT); + // Put pointer back so that the character will be + // displayed at the start of the next line. + ptr--; + } else if (*ptr != NUL) { ptr += mb_l - 1; + } /* If a double-width char doesn't fit at the left side display * a '<' in the first column. Don't do this for unprintable @@ -3228,8 +3276,8 @@ win_line ( c = ' '; if (area_attr == 0 && search_attr == 0) { n_attr = n_extra + 1; - extra_attr = hl_attr(HLF_AT); - saved_attr2 = char_attr; /* save current attr */ + extra_attr = win_hl_attr(wp, HLF_AT); + saved_attr2 = char_attr; // save current attr } mb_c = c; mb_utf8 = FALSE; @@ -3277,7 +3325,7 @@ win_line ( else syntax_flags = get_syntax_info(&syntax_seqnr); } else if (!attr_pri) { - char_attr = 0; + char_attr = wp->w_hl_attr_normal; } /* Check spelling (unless at the end of the line). @@ -3403,7 +3451,7 @@ win_line ( || (c == ' ' && lcs_space && ptr - line <= trailcol))) { c = (c == ' ') ? lcs_space : lcs_nbsp; n_attr = 1; - extra_attr = hl_attr(HLF_8); + extra_attr = win_hl_attr(wp, HLF_0); saved_attr2 = char_attr; // save current attr mb_c = c; if (enc_utf8 && (*mb_char2len)(c) > 1) { @@ -3418,7 +3466,7 @@ win_line ( if (trailcol != MAXCOL && ptr > line + trailcol && c == ' ') { c = lcs_trail; n_attr = 1; - extra_attr = hl_attr(HLF_8); + extra_attr = win_hl_attr(wp, HLF_0); saved_attr2 = char_attr; // save current attr mb_c = c; if (enc_utf8 && (*mb_char2len)(c) > 1) { @@ -3476,6 +3524,7 @@ win_line ( p = xmalloc(len + 1); memset(p, ' ', len); p[len] = NUL; + xfree(p_extra_free); p_extra_free = p; for (i = 0; i < tab_len; i++) { mb_char2bytes(lcs_tab2, p); @@ -3519,8 +3568,8 @@ win_line ( c_extra = lcs_tab2; } n_attr = tab_len + 1; - extra_attr = hl_attr(HLF_8); - saved_attr2 = char_attr; /* save current attr */ + extra_attr = win_hl_attr(wp, HLF_0); + saved_attr2 = char_attr; // save current attr mb_c = c; if (enc_utf8 && (*mb_char2len)(c) > 1) { mb_utf8 = TRUE; @@ -3566,7 +3615,7 @@ win_line ( } lcs_eol_one = -1; ptr--; // put it back at the NUL - extra_attr = hl_attr(HLF_AT); + extra_attr = win_hl_attr(wp, HLF_AT); n_attr = 1; mb_c = c; if (enc_utf8 && (*mb_char2len)(c) > 1) { @@ -3591,13 +3640,14 @@ win_line ( memset(p, ' ', n_extra); STRNCPY(p, p_extra + 1, STRLEN(p_extra) - 1); p[n_extra] = NUL; + xfree(p_extra_free); p_extra_free = p_extra = p; } else { n_extra = byte2cells(c) - 1; c = *p_extra++; } n_attr = n_extra + 1; - extra_attr = hl_attr(HLF_8); + extra_attr = win_hl_attr(wp, HLF_8); saved_attr2 = char_attr; // save current attr mb_utf8 = false; // don't draw as UTF-8 } else if (VIsual_active @@ -3629,9 +3679,10 @@ win_line ( if (diff_hlf == HLF_TXD) { diff_hlf = HLF_CHD; if (attr == 0 || char_attr != attr) { - char_attr = hl_attr(diff_hlf); + char_attr = win_hl_attr(wp, diff_hlf); if (wp->w_p_cul && lnum == wp->w_cursor.lnum) { - char_attr = hl_combine_attr(char_attr, hl_attr(HLF_CUL)); + char_attr = hl_combine_attr(char_attr, + win_hl_attr(wp, HLF_CUL)); } } } @@ -3710,7 +3761,7 @@ win_line ( } // Don't override visual selection highlighting. - if (n_attr > 0 && draw_state == WL_LINE) { + if (n_attr > 0 && draw_state == WL_LINE && !search_attr_from_match) { char_attr = hl_combine_attr(char_attr, extra_attr); } @@ -3733,7 +3784,7 @@ win_line ( c_extra = MB_FILLER_CHAR; n_extra = 1; n_attr = 2; - extra_attr = hl_attr(HLF_AT); + extra_attr = win_hl_attr(wp, HLF_AT); } mb_c = c; if (enc_utf8 && (*mb_char2len)(c) > 1) { @@ -3744,7 +3795,7 @@ win_line ( mb_utf8 = false; // don't draw as UTF-8 } saved_attr3 = char_attr; // save current attr - char_attr = hl_attr(HLF_AT); // later copied to char_attr + char_attr = win_hl_attr(wp, HLF_AT); // overwriting char_attr n_attr3 = 1; } @@ -3828,6 +3879,10 @@ win_line ( } } } + + if (wp->w_hl_attr_normal != 0) { + char_attr = hl_combine_attr(wp->w_hl_attr_normal, char_attr); + } ScreenAttrs[off] = char_attr; if (wp->w_p_rl) { --col; @@ -3889,6 +3944,9 @@ win_line ( if (rightmost_vcol < color_cols[i]) rightmost_vcol = color_cols[i]; + int cuc_attr = win_hl_attr(wp, HLF_CUC); + int mc_attr = win_hl_attr(wp, HLF_MC); + while (col < wp->w_width) { ScreenLines[off] = ' '; if (enc_utf8) @@ -3898,12 +3956,13 @@ win_line ( draw_color_col = advance_color_col(VCOL_HLC, &color_cols); - if (wp->w_p_cuc && VCOL_HLC == (long)wp->w_virtcol) - ScreenAttrs[off++] = hl_attr(HLF_CUC); - else if (draw_color_col && VCOL_HLC == *color_cols) - ScreenAttrs[off++] = hl_attr(HLF_MC); - else - ScreenAttrs[off++] = 0; + if (wp->w_p_cuc && VCOL_HLC == (long)wp->w_virtcol) { + ScreenAttrs[off++] = cuc_attr; + } else if (draw_color_col && VCOL_HLC == *color_cols) { + ScreenAttrs[off++] = mc_attr; + } else { + ScreenAttrs[off++] = wp->w_hl_attr_normal; + } if (VCOL_HLC >= rightmost_vcol) break; @@ -3912,6 +3971,7 @@ win_line ( } } + // TODO(bfredl): integrate with the common beyond-the-end-loop if (wp->w_buffer->terminal) { // terminal buffers may need to highlight beyond the end of the // logical line @@ -3924,7 +3984,7 @@ win_line ( col++; } } - SCREEN_LINE(screen_row, wp->w_wincol, col, wp->w_width, wp->w_p_rl); + screen_line(screen_row, wp->w_wincol, col, wp->w_width, wp->w_p_rl, wp); row++; /* @@ -3952,7 +4012,7 @@ win_line ( || (wp->w_p_list && lcs_eol_one > 0) || (n_extra && (c_extra != NUL || *p_extra != NUL)))) { c = lcs_ext; - char_attr = hl_attr(HLF_AT); + char_attr = win_hl_attr(wp, HLF_AT); mb_c = c; if (enc_utf8 && (*mb_char2len)(c) > 1) { mb_utf8 = TRUE; @@ -3975,10 +4035,10 @@ win_line ( if (wp->w_p_cuc && VCOL_HLC == (long)wp->w_virtcol && lnum != wp->w_cursor.lnum) { vcol_save_attr = char_attr; - char_attr = hl_combine_attr(char_attr, hl_attr(HLF_CUC)); + char_attr = hl_combine_attr(char_attr, win_hl_attr(wp, HLF_CUC)); } else if (draw_color_col && VCOL_HLC == *color_cols) { vcol_save_attr = char_attr; - char_attr = hl_combine_attr(char_attr, hl_attr(HLF_MC)); + char_attr = hl_combine_attr(char_attr, win_hl_attr(wp, HLF_MC)); } } @@ -4146,8 +4206,8 @@ win_line ( || (wp->w_p_list && lcs_eol != NUL && p_extra != at_end_str) || (n_extra != 0 && (c_extra != NUL || *p_extra != NUL))) ) { - SCREEN_LINE(screen_row, wp->w_wincol, col - boguscols, - wp->w_width, wp->w_p_rl); + screen_line(screen_row, wp->w_wincol, col - boguscols, + wp->w_width, wp->w_p_rl, wp); boguscols = 0; ++row; ++screen_row; @@ -4187,7 +4247,6 @@ win_line ( * (regardless of the xn,am settings). * Only do this if the cursor is on the current line * (something has been written in it). - * Don't do this for the GUI. * Don't do this for double-width characters. * Don't do this for a window not at the right screen border. */ @@ -4255,6 +4314,7 @@ win_line ( cap_col = 0; } + xfree(p_extra_free); return row; } @@ -4315,7 +4375,8 @@ static int char_needs_redraw(int off_from, int off_to, int cols) * When TRUE and "clear_width" > 0, clear columns 0 to "endcol" * When FALSE and "clear_width" > 0, clear columns "endcol" to "clear_width" */ -static void screen_line(int row, int coloff, int endcol, int clear_width, int rlflag) +static void screen_line(int row, int coloff, int endcol, + int clear_width, int rlflag, win_T *wp) { unsigned off_from; unsigned off_to; @@ -4477,11 +4538,11 @@ static void screen_line(int row, int coloff, int endcol, int clear_width, int rl } if (clear_width > 0) { - /* For a window that's left of another, draw the separator char. */ - if (col + coloff < Columns) { + // For a window that's left of another, draw the separator char. + if (col + coloff < Columns && wp->w_vsep_width > 0) { int c; - c = fillchar_vsep(&hl); + c = fillchar_vsep(wp, &hl); if (ScreenLines[off_to] != (schar_T)c || (enc_utf8 && (int)ScreenLinesUC[off_to] != (c >= 0x80 ? c : 0)) @@ -4586,8 +4647,8 @@ static void draw_vsep_win(win_T *wp, int row) int c; if (wp->w_vsep_width) { - /* draw the vertical separator right of this window */ - c = fillchar_vsep(&hl); + // draw the vertical separator right of this window + c = fillchar_vsep(wp, &hl); screen_fill(wp->w_winrow + row, wp->w_winrow + wp->w_height, W_ENDCOL(wp), W_ENDCOL(wp) + 1, c, ' ', hl); @@ -4717,7 +4778,7 @@ win_redr_status_matches ( --first_match; } - fillchar = fillchar_status(&attr, TRUE); + fillchar = fillchar_status(&attr, curwin); if (first_match == 0) { *buf = NUL; @@ -4831,11 +4892,14 @@ void win_redr_status(win_T *wp) int this_ru_col; static int busy = FALSE; - /* It's possible to get here recursively when 'statusline' (indirectly) - * invokes ":redrawstatus". Simply ignore the call then. */ - if (busy) + // May get here recursively when 'statusline' (indirectly) + // invokes ":redrawstatus". Simply ignore the call then. + if (busy + // Also ignore if wildmenu is showing. + || (wild_menu_showing != 0 && !ui_is_external(kUIWildmenu))) { return; - busy = TRUE; + } + busy = true; wp->w_redr_status = FALSE; if (wp->w_status_height == 0) { @@ -4849,7 +4913,7 @@ void win_redr_status(win_T *wp) /* redraw custom status line */ redraw_custom_statusline(wp); } else { - fillchar = fillchar_status(&attr, wp == curwin); + fillchar = fillchar_status(&attr, wp); get_trans_bufname(wp->w_buffer); p = NameBuff; @@ -4874,37 +4938,34 @@ void win_redr_status(win_T *wp) } if (wp->w_buffer->b_p_ro) { STRCPY(p + len, _("[RO]")); - len += 4; + len += (int)STRLEN(p + len); } this_ru_col = ru_col - (Columns - wp->w_width); - if (this_ru_col < (wp->w_width + 1) / 2) + if (this_ru_col < (wp->w_width + 1) / 2) { this_ru_col = (wp->w_width + 1) / 2; + } if (this_ru_col <= 1) { - p = (char_u *)"<"; /* No room for file name! */ + p = (char_u *)"<"; // No room for file name! len = 1; - } else if (has_mbyte) { + } else { int clen = 0, i; - /* Count total number of display cells. */ - clen = (int) mb_string2cells(p); + // Count total number of display cells. + clen = (int)mb_string2cells(p); - /* Find first character that will fit. - * Going from start to end is much faster for DBCS. */ + // Find first character that will fit. + // Going from start to end is much faster for DBCS. for (i = 0; p[i] != NUL && clen >= this_ru_col - 1; - i += (*mb_ptr2len)(p + i)) + i += (*mb_ptr2len)(p + i)) { clen -= (*mb_ptr2cells)(p + i); + } len = clen; if (i > 0) { p = p + i - 1; *p = '<'; ++len; } - - } else if (len > this_ru_col - 1) { - p += len - (this_ru_col - 1); - *p = '<'; - len = this_ru_col - 1; } row = wp->w_winrow + wp->w_height; @@ -4912,7 +4973,7 @@ void win_redr_status(win_T *wp) screen_fill(row, row + 1, len + wp->w_wincol, this_ru_col + wp->w_wincol, fillchar, fillchar, attr); - if (get_keymap_str(wp, NameBuff, MAXPATHL) + if (get_keymap_str(wp, (char_u *)"<%s>", NameBuff, MAXPATHL) && this_ru_col - len > (int)(STRLEN(NameBuff) + 1)) screen_puts(NameBuff, row, (int)(this_ru_col - STRLEN(NameBuff) - 1 + wp->w_wincol), attr); @@ -4924,10 +4985,11 @@ void win_redr_status(win_T *wp) * May need to draw the character below the vertical separator. */ if (wp->w_vsep_width != 0 && wp->w_status_height != 0 && redrawing()) { - if (stl_connected(wp)) - fillchar = fillchar_status(&attr, wp == curwin); - else - fillchar = fillchar_vsep(&attr); + if (stl_connected(wp)) { + fillchar = fillchar_status(&attr, wp); + } else { + fillchar = fillchar_vsep(wp, &attr); + } screen_putchar(fillchar, wp->w_winrow + wp->w_height, W_ENDCOL(wp), attr); } @@ -4993,8 +5055,9 @@ int stl_connected(win_T *wp) int get_keymap_str ( win_T *wp, - char_u *buf, /* buffer for the result */ - int len /* length of buffer */ + char_u *fmt, // format string containing one %s item + char_u *buf, // buffer for the result + int len // length of buffer ) { char_u *p; @@ -5021,10 +5084,9 @@ get_keymap_str ( else p = (char_u *)"lang"; } - if ((int)(STRLEN(p) + 3) < len) - sprintf((char *)buf, "<%s>", p); - else + if (vim_snprintf((char *)buf, len, (char *)fmt, p) > len - 1) { buf[0] = NUL; + } xfree(s); } return buf[0] != NUL; @@ -5077,7 +5139,7 @@ win_redr_custom ( use_sandbox = was_set_insecurely((char_u *)"tabline", 0); } else { row = wp->w_winrow + wp->w_height; - fillchar = fillchar_status(&attr, wp == curwin); + fillchar = fillchar_status(&attr, wp); maxwidth = wp->w_width; if (draw_ruler) { @@ -5327,43 +5389,39 @@ void screen_puts_len(char_u *text, int textlen, int row, int col, int attr) c = *ptr; /* check if this is the first byte of a multibyte */ if (l_has_mbyte) { - if (l_enc_utf8 && len > 0) + if (len > 0) { mbyte_blen = utfc_ptr2len_len(ptr, (int)((text + len) - ptr)); - else - mbyte_blen = (*mb_ptr2len)(ptr); - if (l_enc_dbcs == DBCS_JPNU && c == 0x8e) - mbyte_cells = 1; - else if (l_enc_dbcs != 0) - mbyte_cells = mbyte_blen; - else { /* enc_utf8 */ - if (len >= 0) - u8c = utfc_ptr2char_len(ptr, u8cc, - (int)((text + len) - ptr)); - else - u8c = utfc_ptr2char(ptr, u8cc); - mbyte_cells = utf_char2cells(u8c); - if (p_arshape && !p_tbidi && arabic_char(u8c)) { - /* Do Arabic shaping. */ - if (len >= 0 && (int)(ptr - text) + mbyte_blen >= len) { - /* Past end of string to be displayed. */ - nc = NUL; - nc1 = NUL; - } else { - nc = utfc_ptr2char_len(ptr + mbyte_blen, pcc, - (int)((text + len) - ptr - mbyte_blen)); - nc1 = pcc[0]; - } - pc = prev_c; - prev_c = u8c; - u8c = arabic_shape(u8c, &c, &u8cc[0], nc, nc1, pc); - } else - prev_c = u8c; - if (col + mbyte_cells > screen_Columns) { - /* Only 1 cell left, but character requires 2 cells: - * display a '>' in the last column to avoid wrapping. */ - c = '>'; - mbyte_cells = 1; + } else { + mbyte_blen = utfc_ptr2len(ptr); + } + if (len >= 0) { + u8c = utfc_ptr2char_len(ptr, u8cc, (int)((text + len) - ptr)); + } else { + u8c = utfc_ptr2char(ptr, u8cc); + } + mbyte_cells = utf_char2cells(u8c); + if (p_arshape && !p_tbidi && arabic_char(u8c)) { + // Do Arabic shaping. + if (len >= 0 && (int)(ptr - text) + mbyte_blen >= len) { + // Past end of string to be displayed. + nc = NUL; + nc1 = NUL; + } else { + nc = utfc_ptr2char_len(ptr + mbyte_blen, pcc, + (int)((text + len) - ptr - mbyte_blen)); + nc1 = pcc[0]; } + pc = prev_c; + prev_c = u8c; + u8c = arabic_shape(u8c, &c, &u8cc[0], nc, nc1, pc); + } else { + prev_c = u8c; + } + if (col + mbyte_cells > screen_Columns) { + // Only 1 cell left, but character requires 2 cells: + // display a '>' in the last column to avoid wrapping. */ + c = '>'; + mbyte_cells = 1; } } @@ -5371,16 +5429,11 @@ void screen_puts_len(char_u *text, int textlen, int row, int col, int attr) force_redraw_next = FALSE; need_redraw = ScreenLines[off] != c - || (mbyte_cells == 2 - && ScreenLines[off + 1] != (l_enc_dbcs ? ptr[1] : 0)) - || (l_enc_dbcs == DBCS_JPNU - && c == 0x8e - && ScreenLines2[off] != ptr[1]) - || (l_enc_utf8 - && (ScreenLinesUC[off] != - (u8char_T)(c < 0x80 && u8cc[0] == 0 ? 0 : u8c) - || (ScreenLinesUC[off] != 0 - && screen_comp_differs(off, u8cc)))) + || (mbyte_cells == 2 && ScreenLines[off + 1] != 0) + || (ScreenLinesUC[off] != + (u8char_T)(c < 0x80 && u8cc[0] == 0 ? 0 : u8c) + || (ScreenLinesUC[off] != 0 + && screen_comp_differs(off, u8cc))) || ScreenAttrs[off] != attr || exmode_active; @@ -5471,8 +5524,7 @@ static void start_search_hl(void) { if (p_hls && !no_hlsearch) { last_pat_prog(&search_hl.rm); - search_hl.attr = hl_attr(HLF_L); - /* Set the time limit to 'redrawtime'. */ + // Set the time limit to 'redrawtime'. search_hl.tm = profile_setlimit(p_rdt); } } @@ -5488,6 +5540,42 @@ static void end_search_hl(void) } } +static void update_window_hl(win_T *wp, bool invalid) +{ + if (!wp->w_hl_needs_update && !invalid) { + return; + } + wp->w_hl_needs_update = false; + + // determine window specific background set in 'winhighlight' + if (wp != curwin && wp->w_hl_ids[HLF_INACTIVE] > 0) { + wp->w_hl_attr_normal = syn_id2attr(wp->w_hl_ids[HLF_INACTIVE]); + } else if (wp->w_hl_id_normal > 0) { + wp->w_hl_attr_normal = syn_id2attr(wp->w_hl_id_normal); + } else { + wp->w_hl_attr_normal = 0; + } + if (wp != curwin) { + wp->w_hl_attr_normal = hl_combine_attr(hl_attr(HLF_INACTIVE), + wp->w_hl_attr_normal); + } + + for (int hlf = 0; hlf < (int)HLF_COUNT; hlf++) { + int attr; + if (wp->w_hl_ids[hlf] > 0) { + attr = syn_id2attr(wp->w_hl_ids[hlf]); + } else { + attr = hl_attr(hlf); + } + if (wp->w_hl_attr_normal != 0) { + attr = hl_combine_attr(wp->w_hl_attr_normal, attr); + } + wp->w_hl_attrs[hlf] = attr; + } +} + + + /* * Init for calling prepare_search_hl(). */ @@ -5514,7 +5602,9 @@ static void init_search_hl(win_T *wp) search_hl.buf = wp->w_buffer; search_hl.lnum = 0; search_hl.first_lnum = 0; - /* time limit is set at the toplevel, for all windows */ + search_hl.attr = win_hl_attr(wp, HLF_L); + + // time limit is set at the toplevel, for all windows } /* @@ -5534,13 +5624,14 @@ static void prepare_search_hl(win_T *wp, linenr_T lnum) * Do this both for search_hl and the match list. */ cur = wp->w_match_head; - shl_flag = FALSE; - while (cur != NULL || shl_flag == FALSE) { - if (shl_flag == FALSE) { + shl_flag = false; + while (cur != NULL || shl_flag == false) { + if (shl_flag == false) { shl = &search_hl; - shl_flag = TRUE; - } else - shl = &cur->hl; + shl_flag = true; + } else { + shl = &cur->hl; // -V595 + } if (shl->rm.regprog != NULL && shl->lnum == 0 && re_multiline(shl->rm.regprog)) { @@ -5775,12 +5866,12 @@ static void screen_char(unsigned off, int row, int col) if (row >= screen_Rows || col >= screen_Columns) return; - /* Outputting the last character on the screen may scrollup the screen. - * Don't to it! Mark the character invalid (update it when scrolled up) */ + // Outputting the last character on the screen may scrollup the screen. + // Don't to it! Mark the character invalid (update it when scrolled up) + // FIXME: The premise here is not actually true (cf. deferred wrap). if (row == screen_Rows - 1 && col == screen_Columns - 1 - /* account for first command-line character in rightleft mode */ - && !cmdmsg_rl - ) { + // account for first command-line character in rightleft mode + && !cmdmsg_rl) { ScreenAttrs[off] = (sattr_T)-1; return; } @@ -5906,7 +5997,7 @@ void screen_fill(int start_row, int end_row, int start_col, int end_col, int c1, col = off - LineOffset[row]; screen_stop_highlight(); ui_cursor_goto(row, col); // clear rest of this screen line - ui_eol_clear(); + ui_call_eol_clear(); col = end_col - col; while (col--) { /* clear chars in ScreenLines */ ScreenLines[off] = ' '; @@ -6099,8 +6190,7 @@ retry: if (new_ScreenLinesC[i] == NULL) break; if (new_ScreenLines == NULL - || (l_enc_utf8 && (new_ScreenLinesUC == NULL || i != p_mco)) - || (l_enc_dbcs == DBCS_JPNU && new_ScreenLines2 == NULL) + || (new_ScreenLinesUC == NULL || i != p_mco) || new_ScreenAttrs == NULL || new_LineOffset == NULL || new_LineWraps == NULL @@ -6185,13 +6275,14 @@ retry: ScreenLinesC[i] + LineOffset[old_row], (size_t)len * sizeof(u8char_T)); } - if (l_enc_dbcs == DBCS_JPNU && ScreenLines2 != NULL) + if (ScreenLines2 != NULL) { memmove(new_ScreenLines2 + new_LineOffset[new_row], - ScreenLines2 + LineOffset[old_row], - (size_t)len * sizeof(schar_T)); + ScreenLines2 + LineOffset[old_row], + (size_t)len * sizeof(schar_T)); + } memmove(new_ScreenAttrs + new_LineOffset[new_row], - ScreenAttrs + LineOffset[old_row], - (size_t)len * sizeof(sattr_T)); + ScreenAttrs + LineOffset[old_row], + (size_t)len * sizeof(sattr_T)); } } } @@ -6295,10 +6386,10 @@ static void screenclear2(void) LineWraps[i] = FALSE; } - ui_clear(); // clear the display - clear_cmdline = FALSE; - mode_displayed = FALSE; - screen_cleared = TRUE; /* can use contents of ScreenLines now */ + ui_call_clear(); // clear the display + clear_cmdline = false; + mode_displayed = false; + screen_cleared = true; // can use contents of ScreenLines now win_rest_invalid(firstwin); redraw_cmdline = TRUE; @@ -6371,13 +6462,11 @@ void setcursor(void) } } -/* - * insert 'line_count' lines at 'row' in window 'wp' - * if 'invalid' is TRUE the wp->w_lines[].wl_lnum is invalidated. - * if 'mayclear' is TRUE the screen will be cleared if it is faster than - * scrolling. - * Returns FAIL if the lines are not inserted, OK for success. - */ +/// Insert 'line_count' lines at 'row' in window 'wp'. +/// If 'invalid' is TRUE the wp->w_lines[].wl_lnum is invalidated. +/// If 'mayclear' is TRUE the screen will be cleared if it is faster than +/// scrolling. +/// Returns FAIL if the lines are not inserted, OK for success. int win_ins_lines(win_T *wp, int row, int line_count, int invalid, int mayclear) { int did_delete; @@ -6440,13 +6529,11 @@ int win_ins_lines(win_T *wp, int row, int line_count, int invalid, int mayclear) return OK; } -/* - * delete "line_count" window lines at "row" in window "wp" - * If "invalid" is TRUE curwin->w_lines[] is invalidated. - * If "mayclear" is TRUE the screen will be cleared if it is faster than - * scrolling - * Return OK for success, FAIL if the lines are not deleted. - */ +/// Delete "line_count" window lines at "row" in window "wp". +/// If "invalid" is TRUE curwin->w_lines[] is invalidated. +/// If "mayclear" is TRUE the screen will be cleared if it is faster than +/// scrolling +/// Return OK for success, FAIL if the lines are not deleted. int win_del_lines(win_T *wp, int row, int line_count, int invalid, int mayclear) { int retval; @@ -6597,7 +6684,7 @@ int screen_ins_lines ( } } - ui_append_lines(line_count); + ui_call_scroll(-line_count); return OK; } @@ -6652,7 +6739,7 @@ int screen_del_lines ( } } - ui_delete_lines(line_count); + ui_call_scroll(line_count); return OK; } @@ -6717,17 +6804,19 @@ int showmode(void) if (edit_submode_pre != NULL) length -= vim_strsize(edit_submode_pre); if (length - vim_strsize(edit_submode) > 0) { - if (edit_submode_pre != NULL) - msg_puts_attr(edit_submode_pre, attr); - msg_puts_attr(edit_submode, attr); + if (edit_submode_pre != NULL) { + msg_puts_attr((const char *)edit_submode_pre, attr); + } + msg_puts_attr((const char *)edit_submode, attr); } if (edit_submode_extra != NULL) { - MSG_PUTS_ATTR(" ", attr); /* add a space in between */ - if ((int)edit_submode_highl < (int)HLF_COUNT) - sub_attr = hl_attr(edit_submode_highl); - else + MSG_PUTS_ATTR(" ", attr); // Add a space in between. + if ((int)edit_submode_highl < (int)HLF_COUNT) { + sub_attr = win_hl_attr(curwin, edit_submode_highl); + } else { sub_attr = attr; - msg_puts_attr(edit_submode_extra, sub_attr); + } + msg_puts_attr((const char *)edit_submode_extra, sub_attr); } } } else { @@ -6752,10 +6841,12 @@ int showmode(void) if (p_fkmap) MSG_PUTS_ATTR(farsi_text_5, attr); if (State & LANGMAP) { - if (curwin->w_p_arab) + if (curwin->w_p_arab) { MSG_PUTS_ATTR(_(" Arabic"), attr); - else - MSG_PUTS_ATTR(_(" (lang)"), attr); + } else if (get_keymap_str(curwin, (char_u *)" (%s)", + NameBuff, MAXPATHL)) { + MSG_PUTS_ATTR(NameBuff, attr); + } } if ((State & INSERT) && p_paste) MSG_PUTS_ATTR(_(" (paste)"), attr); @@ -6874,7 +6965,6 @@ static void draw_tabline(void) int modified; int c; int len; - int attr_sel = hl_attr(HLF_TPS); int attr_nosel = hl_attr(HLF_TP); int attr_fill = hl_attr(HLF_TPF); char_u *p; @@ -6882,8 +6972,15 @@ static void draw_tabline(void) int use_sep_chars = (t_colors < 8 ); - redraw_tabline = FALSE; + if (ScreenLines == NULL) { + return; + } + redraw_tabline = false; + if (ui_is_external(kUITabline)) { + ui_ext_tabline_update(); + return; + } if (tabline_height() < 1) return; @@ -6929,16 +7026,6 @@ static void draw_tabline(void) scol = col; - if (tp->tp_topframe == topframe) - attr = attr_sel; - if (use_sep_chars && col > 0) - screen_putchar('|', 0, col++, attr); - - if (tp->tp_topframe != topframe) - attr = attr_nosel; - - screen_putchar(' ', 0, col++, attr); - if (tp == curtab) { cwp = curwin; wp = firstwin; @@ -6947,10 +7034,29 @@ static void draw_tabline(void) wp = tp->tp_firstwin; } - modified = FALSE; - for (wincount = 0; wp != NULL; wp = wp->w_next, ++wincount) - if (bufIsChanged(wp->w_buffer)) - modified = TRUE; + + if (tp->tp_topframe == topframe) { + attr = win_hl_attr(cwp, HLF_TPS); + } + if (use_sep_chars && col > 0) { + screen_putchar('|', 0, col++, attr); + } + + if (tp->tp_topframe != topframe) { + attr = win_hl_attr(cwp, HLF_TP); + } + + screen_putchar(' ', 0, col++, attr); + + modified = false; + + for (wincount = 0; wp != NULL; wp = wp->w_next, ++wincount) { + if (bufIsChanged(wp->w_buffer)) { + modified = true; + } + } + + if (modified || wincount > 1) { if (wincount > 1) { vim_snprintf((char *)NameBuff, MAXPATHL, "%d", wincount); @@ -6958,7 +7064,7 @@ static void draw_tabline(void) if (col + len >= Columns - 3) break; screen_puts_len(NameBuff, len, 0, col, - hl_combine_attr(attr, hl_attr(HLF_T))); + hl_combine_attr(attr, win_hl_attr(cwp, HLF_T))); col += len; } if (modified) @@ -7024,6 +7130,22 @@ static void draw_tabline(void) redraw_tabline = FALSE; } +void ui_ext_tabline_update(void) +{ + Array tabs = ARRAY_DICT_INIT; + FOR_ALL_TABS(tp) { + Dictionary tab_info = ARRAY_DICT_INIT; + PUT(tab_info, "tab", TABPAGE_OBJ(tp->handle)); + + win_T *cwp = (tp == curtab) ? curwin : tp->tp_curwin; + get_trans_bufname(cwp->w_buffer); + PUT(tab_info, "name", STRING_OBJ(cstr_to_string((char *)NameBuff))); + + ADD(tabs, DICTIONARY_OBJ(tab_info)); + } + ui_call_tabline_update(curtab->handle, tabs); +} + /* * Get buffer name for "buf" into NameBuff[]. * Takes care of special buffer names and translates special characters. @@ -7040,25 +7162,28 @@ void get_trans_bufname(buf_T *buf) /* * Get the character to use in a status line. Get its attributes in "*attr". */ -static int fillchar_status(int *attr, int is_curwin) +static int fillchar_status(int *attr, win_T *wp) { int fill; + bool is_curwin = (wp == curwin); if (is_curwin) { - *attr = hl_attr(HLF_S); + *attr = win_hl_attr(wp, HLF_S); fill = fill_stl; } else { - *attr = hl_attr(HLF_SNC); + *attr = win_hl_attr(wp, HLF_SNC); fill = fill_stlnc; } /* Use fill when there is highlighting, and highlighting of current * window differs, or the fillchars differ, or this is not the * current window */ - if (*attr != 0 && ((hl_attr(HLF_S) != hl_attr(HLF_SNC) - || !is_curwin || firstwin == lastwin) - || (fill_stl != fill_stlnc))) + if (*attr != 0 && ((win_hl_attr(wp, HLF_S) != win_hl_attr(wp, HLF_SNC) + || !is_curwin || ONE_WINDOW) + || (fill_stl != fill_stlnc))) { return fill; - if (is_curwin) + } + if (is_curwin) { return '^'; + } return '='; } @@ -7066,13 +7191,14 @@ static int fillchar_status(int *attr, int is_curwin) * Get the character to use in a separator between vertically split windows. * Get its attributes in "*attr". */ -static int fillchar_vsep(int *attr) +static int fillchar_vsep(win_T *wp, int *attr) { - *attr = hl_attr(HLF_C); - if (*attr == 0 && fill_vert == ' ') + *attr = win_hl_attr(wp, HLF_C); + if (*attr == 0 && fill_vert == ' ') { return '|'; - else + } else { return fill_vert; + } } /* @@ -7107,8 +7233,9 @@ void showruler(int always) } if ((*p_stl != NUL || *curwin->w_p_stl != NUL) && curwin->w_status_height) { redraw_custom_statusline(curwin); - } else + } else { win_redr_ruler(curwin, always); + } if (need_maketitle || (p_icon && (stl_syntax & STL_IN_ICON)) @@ -7186,7 +7313,7 @@ static void win_redr_ruler(win_T *wp, int always) if (wp->w_status_height) { row = wp->w_winrow + wp->w_height; - fillchar = fillchar_status(&attr, wp == curwin); + fillchar = fillchar_status(&attr, wp); off = wp->w_wincol; width = wp->w_width; } else { @@ -7313,23 +7440,16 @@ int number_width(win_T *wp) return n; } -/* - * Set size of the Vim shell. - * If 'mustset' is TRUE, we must set Rows and Columns, do not get the real - * window size (this is used for the :win command). - * If 'mustset' is FALSE, we may try to get the real window size and if - * it fails use 'width' and 'height'. - */ +/// Set dimensions of the Nvim application "shell". void screen_resize(int width, int height) { static int busy = FALSE; - /* - * Avoid recursiveness, can happen when setting the window size causes - * another window-changed signal. - */ - if (busy) + // Avoid recursiveness, can happen when setting the window size causes + // another window-changed signal. + if (updating_screen || busy) { return; + } if (width < 0 || height < 0) /* just checking... */ return; @@ -7405,8 +7525,8 @@ void screen_resize(int width, int height) --busy; } -// Check if the new shell size is valid, correct it if it's too small or way -// too big. +/// Check if the new Nvim application "shell" dimensions are valid. +/// Correct it if it's too small or way too big. void check_shellsize(void) { if (Rows < min_rows()) { diff --git a/src/nvim/screen.h b/src/nvim/screen.h index 81a8b9ed4c..17515d4253 100644 --- a/src/nvim/screen.h +++ b/src/nvim/screen.h @@ -3,6 +3,10 @@ #include <stdbool.h> +#include "nvim/types.h" +#include "nvim/buffer_defs.h" +#include "nvim/pos.h" + /* * flags for update_screen() * The higher the value, the higher the priority diff --git a/src/nvim/search.c b/src/nvim/search.c index 2a087276e7..1bf2317d2a 100644 --- a/src/nvim/search.c +++ b/src/nvim/search.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + /* * search.c: code for normal mode searching commands */ @@ -282,7 +285,7 @@ void restore_search_patterns(void) static inline void free_spat(struct spat *const spat) { xfree(spat->pat); - dict_unref(spat->additional_data); + tv_dict_unref(spat->additional_data); } #if defined(EXITFREE) @@ -308,13 +311,19 @@ void free_search_patterns(void) */ int ignorecase(char_u *pat) { - int ic = p_ic; + return ignorecase_opt(pat, p_ic, p_scs); +} - if (ic && !no_smartcase && p_scs +/// As ignorecase() put pass the "ic" and "scs" flags. +int ignorecase_opt(char_u *pat, int ic_in, int scs) +{ + int ic = ic_in; + if (ic && !no_smartcase && scs && !(ctrl_x_mode && curbuf->b_p_inf) - ) + ) { ic = !pat_has_uppercase(pat); - no_smartcase = FALSE; + } + no_smartcase = false; return ic; } @@ -329,30 +338,34 @@ int pat_has_uppercase(char_u *pat) while (*p != NUL) { int l; - if (has_mbyte && (l = (*mb_ptr2len)(p)) > 1) { - if (enc_utf8 && utf_isupper(utf_ptr2char(p))) - return TRUE; + if ((l = mb_ptr2len(p)) > 1) { + if (mb_isupper(utf_ptr2char(p))) { + return true; + } p += l; } else if (*p == '\\') { - if (p[1] == '_' && p[2] != NUL) /* skip "\_X" */ + if (p[1] == '_' && p[2] != NUL) { // skip "\_X" p += 3; - else if (p[1] == '%' && p[2] != NUL) /* skip "\%X" */ + } else if (p[1] == '%' && p[2] != NUL) { // skip "\%X" p += 3; - else if (p[1] != NUL) /* skip "\X" */ + } else if (p[1] != NUL) { // skip "\X" p += 2; - else + } else { p += 1; - } else if (vim_isupper(*p)) - return TRUE; - else - ++p; + } + } else if (mb_isupper(*p)) { + return true; + } else { + p++; + } } return FALSE; } -char_u *last_csearch(void) +const char *last_csearch(void) + FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT { - return lastc_bytes; + return (const char *)lastc_bytes; } int last_csearch_forward(void) @@ -603,7 +616,7 @@ int searchit( * otherwise "/$" will get stuck on end of line. */ while (matchpos.lnum == 0 - && ((options & SEARCH_END) && first_match + && (((options & SEARCH_END) && first_match) ? (nmatched == 1 && (int)endpos.col - 1 < (int)start_pos.col + extra_col) @@ -992,14 +1005,13 @@ int do_search( dircp = NULL; /* use previous pattern */ if (pat == NULL || *pat == NUL || *pat == dirc) { - if (spats[RE_SEARCH].pat == NULL) { /* no previous pattern */ - pat = spats[RE_SUBST].pat; - if (pat == NULL) { + if (spats[RE_SEARCH].pat == NULL) { // no previous pattern + searchstr = spats[RE_SUBST].pat; + if (searchstr == NULL) { EMSG(_(e_noprevre)); retval = 0; goto end_do_search; } - searchstr = pat; } else { /* make search_regcomp() use spats[RE_SEARCH].pat */ searchstr = (char_u *)""; @@ -1284,10 +1296,11 @@ int search_for_exact_line(buf_T *buf, pos_T *pos, int dir, char_u *pat) * ignored because we are interested in the next line -- Acevedo */ if ((compl_cont_status & CONT_ADDING) && !(compl_cont_status & CONT_SOL)) { - if ((p_ic ? mb_stricmp(p, pat) : STRCMP(p, pat)) == 0) + if (mb_strcmp_ic((bool)p_ic, (const char *)p, (const char *)pat) == 0) { return OK; - } else if (*p != NUL) { /* ignore empty lines */ - /* expanding lines or words */ + } + } else if (*p != NUL) { // Ignore empty lines. + // Expanding lines or words. assert(compl_length >= 0); if ((p_ic ? mb_strnicmp(p, pat, (size_t)compl_length) : STRNCMP(p, pat, compl_length)) == 0) @@ -2411,32 +2424,20 @@ static int cls(void) int c; c = gchar_cursor(); - if (p_altkeymap && c == F_BLANK) - return 0; - if (c == ' ' || c == '\t' || c == NUL) + if (p_altkeymap && c == F_BLANK) { return 0; - if (enc_dbcs != 0 && c > 0xFF) { - /* If cls_bigword, report multi-byte chars as class 1. */ - if (enc_dbcs == DBCS_KOR && cls_bigword) - return 1; - - /* process code leading/trailing bytes */ - return dbcs_class(((unsigned)c >> 8), (c & 0xFF)); } - if (enc_utf8) { - c = utf_class(c); - if (c != 0 && cls_bigword) - return 1; - return c; + if (c == ' ' || c == '\t' || c == NUL) { + return 0; } - /* If cls_bigword is TRUE, report all non-blanks as class 1. */ - if (cls_bigword) - return 1; + c = utf_class(c); - if (vim_iswordc(c)) - return 2; - return 1; + // If cls_bigword is TRUE, report all non-blanks as class 1. + if (c != 0 && cls_bigword) { + return 1; + } + return c; } /* @@ -3022,7 +3023,8 @@ extend: ++curwin->w_cursor.col; VIsual = start_pos; VIsual_mode = 'v'; - redraw_curbuf_later(INVERTED); /* update the inversion */ + redraw_cmdline = true; // show mode later + redraw_curbuf_later(INVERTED); // update the inversion } else { /* include a newline after the sentence, if there is one */ if (incl(&curwin->w_cursor) == -1) @@ -4656,12 +4658,12 @@ static void show_pat_in_path(char_u *line, int type, int did_show, int action, F *(p + 1) = NUL; } if (action == ACTION_SHOW_ALL) { - sprintf((char *)IObuff, "%3ld: ", count); /* show match nr */ - msg_puts(IObuff); - sprintf((char *)IObuff, "%4ld", *lnum); /* show line nr */ - /* Highlight line numbers */ - msg_puts_attr(IObuff, hl_attr(HLF_N)); - MSG_PUTS(" "); + snprintf((char *)IObuff, IOSIZE, "%3ld: ", count); // Show match nr. + msg_puts((const char *)IObuff); + snprintf((char *)IObuff, IOSIZE, "%4ld", *lnum); // Show line nr. + // Highlight line numbers. + msg_puts_attr((const char *)IObuff, hl_attr(HLF_N)); + msg_puts(" "); } msg_prt_line(line, FALSE); ui_flush(); /* show one line at a time */ diff --git a/src/nvim/search.h b/src/nvim/search.h index d4e40cb287..cb50742990 100644 --- a/src/nvim/search.h +++ b/src/nvim/search.h @@ -4,6 +4,12 @@ #include <stdbool.h> #include <stdint.h> +#include "nvim/types.h" +#include "nvim/buffer_defs.h" +#include "nvim/eval/typval.h" +#include "nvim/normal.h" +#include "nvim/os/time.h" + /* Values for the find_pattern_in_path() function args 'type' and 'action': */ #define FIND_ANY 1 #define FIND_DEFINE 2 diff --git a/src/nvim/sha256.c b/src/nvim/sha256.c index 7670b64468..a2378cc202 100644 --- a/src/nvim/sha256.c +++ b/src/nvim/sha256.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + /// @file sha256.c /// /// FIPS-180-2 compliant SHA-256 implementation @@ -259,11 +262,11 @@ void sha256_finish(context_sha256_T *ctx, char_u digest[SHA256_SUM_SIZE]) /// /// @returns hex digest of "buf[buf_len]" in a static array. /// if "salt" is not NULL also do "salt[salt_len]". -char_u *sha256_bytes(const char_u *restrict buf, size_t buf_len, - const char_u *restrict salt, size_t salt_len) +const char *sha256_bytes(const uint8_t *restrict buf, size_t buf_len, + const uint8_t *restrict salt, size_t salt_len) { char_u sha256sum[SHA256_SUM_SIZE]; - static char_u hexit[SHA256_BUFFER_SIZE + 1]; // buf size + NULL + static char hexit[SHA256_BUFFER_SIZE + 1]; // buf size + NULL context_sha256_T ctx; sha256_self_test(); @@ -277,7 +280,7 @@ char_u *sha256_bytes(const char_u *restrict buf, size_t buf_len, sha256_finish(&ctx, sha256sum); for (size_t j = 0; j < SHA256_SUM_SIZE; j++) { - snprintf((char *) hexit + j * SHA_STEP, SHA_STEP+1, "%02x", sha256sum[j]); + snprintf(hexit + j * SHA_STEP, SHA_STEP + 1, "%02x", sha256sum[j]); } hexit[sizeof(hexit) - 1] = '\0'; return hexit; @@ -308,7 +311,7 @@ bool sha256_self_test(void) context_sha256_T ctx; char_u buf[1000]; char_u sha256sum[SHA256_SUM_SIZE]; - char_u *hexit; + const char *hexit; static bool sha256_self_tested = false; static bool failures = false; @@ -320,8 +323,8 @@ bool sha256_self_test(void) for (size_t i = 0; i < 3; i++) { if (i < 2) { - hexit = sha256_bytes((char_u *) sha_self_test_msg[i], - STRLEN(sha_self_test_msg[i]), + hexit = sha256_bytes((uint8_t *)sha_self_test_msg[i], + strlen(sha_self_test_msg[i]), NULL, 0); STRCPY(output, hexit); } else { diff --git a/src/nvim/sha256.h b/src/nvim/sha256.h index a118826542..deb881a288 100644 --- a/src/nvim/sha256.h +++ b/src/nvim/sha256.h @@ -2,6 +2,7 @@ #define NVIM_SHA256_H #include <stdint.h> // for uint32_t +#include <stddef.h> #include "nvim/types.h" // for char_u diff --git a/src/nvim/shada.c b/src/nvim/shada.c index 8cf5976e8b..736d6bf162 100644 --- a/src/nvim/shada.c +++ b/src/nvim/shada.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #include <stdlib.h> #include <stddef.h> #include <stdbool.h> @@ -30,7 +33,7 @@ #include "nvim/ex_getln.h" #include "nvim/search.h" #include "nvim/regexp.h" -#include "nvim/eval_defs.h" +#include "nvim/eval/typval.h" #include "nvim/version.h" #include "nvim/path.h" #include "nvim/fileio.h" @@ -73,17 +76,10 @@ KHASH_SET_INIT_STR(strset) (vim_rename((char_u *)a, (char_u *)b)) #define mb_strnicmp(a, b, c) \ (mb_strnicmp((char_u *)a, (char_u *)b, c)) -#define has_non_ascii(a) (has_non_ascii((char_u *)a)) -#define string_convert(a, b, c) \ - ((char *)string_convert((vimconv_T *)a, (char_u *)b, c)) #define path_shorten_fname_if_possible(b) \ ((char *)path_shorten_fname_if_possible((char_u *)b)) #define buflist_new(ffname, sfname, ...) \ (buflist_new((char_u *)ffname, (char_u *)sfname, __VA_ARGS__)) -#define convert_setup(vcp, from, to) \ - (convert_setup(vcp, (char_u *)from, (char_u *)to)) -#define os_getperm(f) \ - (os_getperm((char_u *) f)) #define os_isdir(f) (os_isdir((char_u *) f)) #define regtilde(s, m) ((char *) regtilde((char_u *) s, m)) #define path_tail_with_sep(f) ((char *) path_tail_with_sep((char_u *)f)) @@ -102,6 +98,7 @@ KHASH_SET_INIT_STR(strset) #define REG_KEY_TYPE "rt" #define REG_KEY_WIDTH "rw" #define REG_KEY_CONTENTS "rc" +#define REG_KEY_UNNAMED "ru" #define KEY_LNUM "l" #define KEY_COL "c" @@ -288,6 +285,7 @@ typedef struct { char name; MotionType type; char **contents; + bool is_unnamed; size_t contents_size; size_t width; dict_T *additional_data; @@ -415,8 +413,6 @@ typedef struct sd_read_def { const char *error; ///< Error message in case of error. uintmax_t fpos; ///< Current position (amount of bytes read since ///< reader structure initialization). May overflow. - vimconv_T sd_conv; ///< Structure used for converting encodings of some - ///< items. } ShaDaReadDef; struct sd_write_def; @@ -437,8 +433,6 @@ typedef struct sd_write_def { ShaDaWriteCloser close; ///< Close function. void *cookie; ///< Data describing object written to. const char *error; ///< Error message in case of error. - vimconv_T sd_conv; ///< Structure used for converting encodings of some - ///< items. } ShaDaWriteDef; #ifdef INCLUDE_GENERATED_DECLARATIONS @@ -481,6 +475,7 @@ static const ShadaEntry sd_default_values[] = { .type = kMTCharWise, .contents = NULL, .contents_size = 0, + .is_unnamed = false, .width = 0, .additional_data = NULL), DEF_SDE(Variable, global_var, @@ -805,7 +800,7 @@ static int open_shada_file_for_reading(const char *const fname, return error; } - convert_setup(&sd_reader->sd_conv, "utf-8", p_enc); + assert(STRCMP(p_enc, "utf-8") == 0); return 0; } @@ -813,7 +808,7 @@ static int open_shada_file_for_reading(const char *const fname, /// Wrapper for closing file descriptors static void close_file(void *cookie) { - const int error = file_free(cookie); + const int error = file_free(cookie, true); if (error != 0) { emsgf(_(SERR "System error while closing ShaDa file: %s"), os_strerror(error)); @@ -1223,7 +1218,7 @@ static void shada_read(ShaDaReadDef *const sd_reader, const int flags) khash_t(fnamebufs) fname_bufs = KHASH_EMPTY_TABLE(fnamebufs); khash_t(strset) oldfiles_set = KHASH_EMPTY_TABLE(strset); if (get_old_files && (oldfiles_list == NULL || force)) { - oldfiles_list = list_alloc(); + oldfiles_list = tv_list_alloc(); set_vim_var_list(VV_OLDFILES, oldfiles_list); } ShaDaReadResult srni_ret; @@ -1285,8 +1280,6 @@ static void shada_read(ShaDaReadDef *const sd_reader, const int flags) if (cur_entry.data.search_pattern.is_last_used) { set_last_used_pattern( cur_entry.data.search_pattern.is_substitute_pattern); - } - if (cur_entry.data.search_pattern.is_last_used) { SET_NO_HLSEARCH(!cur_entry.data.search_pattern.highlighted); } // Do not free shada entry: its allocated memory was saved above. @@ -1345,7 +1338,7 @@ static void shada_read(ShaDaReadDef *const sd_reader, const int flags) .y_width = (colnr_T) cur_entry.data.reg.width, .timestamp = cur_entry.timestamp, .additional_data = cur_entry.data.reg.additional_data, - })) { + }, cur_entry.data.reg.is_unnamed)) { shada_free_shada_entry(&cur_entry); } // Do not free shada entry: its allocated memory was saved above. @@ -1435,8 +1428,8 @@ static void shada_read(ShaDaReadDef *const sd_reader, const int flags) fname = xstrdup(fname); } int kh_ret; - (void) kh_put(strset, &oldfiles_set, fname, &kh_ret); - list_append_allocated_string(oldfiles_list, fname); + (void)kh_put(strset, &oldfiles_set, fname, &kh_ret); + tv_list_append_allocated_string(oldfiles_list, fname); if (!want_marks) { // Avoid free because this string was already used. cur_entry.data.filemark.fname = NULL; @@ -1573,7 +1566,9 @@ static char *shada_filename(const char *file) do { \ const String s_ = (s); \ msgpack_pack_str(spacker, s_.size); \ - msgpack_pack_str_body(spacker, s_.data, s_.size); \ + if (s_.size) { \ + msgpack_pack_str_body(spacker, s_.data, s_.size); \ + } \ } while (0) #define PACK_BIN(s) \ do { \ @@ -1621,10 +1616,10 @@ static ShaDaWriteResult shada_pack_entry(msgpack_packer *const packer, for (const hashitem_T *hi= d->dv_hashtab.ht_array; todo; hi++) { \ if (!HASHITEM_EMPTY(hi)) { \ todo--; \ - dictitem_T *const di = HI2DI(hi); \ - const size_t key_len = strlen((const char *) hi->hi_key); \ + dictitem_T *const di = TV_DICT_HI2DI(hi); \ + const size_t key_len = strlen((const char *)hi->hi_key); \ msgpack_pack_str(spacker, key_len); \ - msgpack_pack_str_body(spacker, (const char *) hi->hi_key, key_len); \ + msgpack_pack_str_body(spacker, (const char *)hi->hi_key, key_len); \ if (encode_vim_to_msgpack(spacker, &di->di_tv, \ _("additional data of ShaDa " what)) \ == FAIL) { \ @@ -1788,6 +1783,7 @@ static ShaDaWriteResult shada_pack_entry(msgpack_packer *const packer, 2 // Register contents and name + ONE_IF_NOT_DEFAULT(entry, reg.type) + ONE_IF_NOT_DEFAULT(entry, reg.width) + + ONE_IF_NOT_DEFAULT(entry, reg.is_unnamed) // Additional entries, if any: + (size_t) (entry.data.reg.additional_data == NULL ? 0 @@ -1808,6 +1804,14 @@ static ShaDaWriteResult shada_pack_entry(msgpack_packer *const packer, PACK_STATIC_STR(REG_KEY_WIDTH); msgpack_pack_uint64(spacker, (uint64_t) entry.data.reg.width); } + if (!CHECK_DEFAULT(entry, reg.is_unnamed)) { + PACK_STATIC_STR(REG_KEY_UNNAMED); + if (entry.data.reg.is_unnamed) { + msgpack_pack_true(spacker); + } else { + msgpack_pack_false(spacker); + } + } DUMP_ADDITIONAL_DATA(entry.data.reg.additional_data, "register item"); break; } @@ -1899,127 +1903,24 @@ shada_pack_entry_error: } #undef PACK_STRING -/// Write single ShaDa entry, converting it if needed +/// Write single ShaDa entry and free it afterwards /// -/// @warning Frees entry after packing. +/// Will not free if entry could not be freed. /// /// @param[in] packer Packer used to write entry. -/// @param[in] sd_conv Conversion definitions. -/// @param[in] entry Entry written. If entry.can_free_entry is false then -/// it assumes that entry was not converted, otherwise it -/// is assumed that entry was already converted. +/// @param[in] entry Entry written. /// @param[in] max_kbyte Maximum size of an item in KiB. Zero means no /// restrictions. -static ShaDaWriteResult shada_pack_encoded_entry(msgpack_packer *const packer, - const vimconv_T *const sd_conv, - PossiblyFreedShadaEntry entry, - const size_t max_kbyte) - FUNC_ATTR_NONNULL_ALL +static inline ShaDaWriteResult shada_pack_pfreed_entry( + msgpack_packer *const packer, PossiblyFreedShadaEntry entry, + const size_t max_kbyte) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_ALWAYS_INLINE { ShaDaWriteResult ret = kSDWriteSuccessfull; + ret = shada_pack_entry(packer, entry.data, max_kbyte); if (entry.can_free_entry) { - ret = shada_pack_entry(packer, entry.data, max_kbyte); shada_free_shada_entry(&entry.data); - return ret; } -#define RUN_WITH_CONVERTED_STRING(cstr, code) \ - do { \ - bool did_convert = false; \ - if (sd_conv->vc_type != CONV_NONE && has_non_ascii((cstr))) { \ - char *const converted_string = string_convert(sd_conv, (cstr), NULL); \ - if (converted_string != NULL) { \ - (cstr) = converted_string; \ - did_convert = true; \ - } \ - } \ - code \ - if (did_convert) { \ - xfree((cstr)); \ - } \ - } while (0) - switch (entry.data.type) { - case kSDItemUnknown: - case kSDItemMissing: { - assert(false); - } - case kSDItemSearchPattern: { - RUN_WITH_CONVERTED_STRING(entry.data.data.search_pattern.pat, { - ret = shada_pack_entry(packer, entry.data, max_kbyte); - }); - break; - } - case kSDItemHistoryEntry: { - RUN_WITH_CONVERTED_STRING(entry.data.data.history_item.string, { - ret = shada_pack_entry(packer, entry.data, max_kbyte); - }); - break; - } - case kSDItemSubString: { - RUN_WITH_CONVERTED_STRING(entry.data.data.sub_string.sub, { - ret = shada_pack_entry(packer, entry.data, max_kbyte); - }); - break; - } - case kSDItemVariable: { - if (sd_conv->vc_type != CONV_NONE) { - typval_T tgttv; - var_item_copy(sd_conv, &entry.data.data.global_var.value, &tgttv, - true, 0); - clear_tv(&entry.data.data.global_var.value); - entry.data.data.global_var.value = tgttv; - } - ret = shada_pack_entry(packer, entry.data, max_kbyte); - break; - } - case kSDItemRegister: { - bool did_convert = false; - if (sd_conv->vc_type != CONV_NONE) { - size_t first_non_ascii = 0; - for (size_t i = 0; i < entry.data.data.reg.contents_size; i++) { - if (has_non_ascii(entry.data.data.reg.contents[i])) { - first_non_ascii = i; - did_convert = true; - break; - } - } - if (did_convert) { - entry.data.data.reg.contents = - xmemdup(entry.data.data.reg.contents, - (entry.data.data.reg.contents_size - * sizeof(entry.data.data.reg.contents))); - for (size_t i = 0; i < entry.data.data.reg.contents_size; i++) { - if (i >= first_non_ascii) { - entry.data.data.reg.contents[i] = get_converted_string( - sd_conv, - entry.data.data.reg.contents[i], - strlen(entry.data.data.reg.contents[i])); - } else { - entry.data.data.reg.contents[i] = - xstrdup(entry.data.data.reg.contents[i]); - } - } - } - } - ret = shada_pack_entry(packer, entry.data, max_kbyte); - if (did_convert) { - for (size_t i = 0; i < entry.data.data.reg.contents_size; i++) { - xfree(entry.data.data.reg.contents[i]); - } - xfree(entry.data.data.reg.contents); - } - break; - } - case kSDItemHeader: - case kSDItemGlobalMark: - case kSDItemJump: - case kSDItemBufferList: - case kSDItemLocalMark: - case kSDItemChange: { - ret = shada_pack_entry(packer, entry.data, max_kbyte); - break; - } - } -#undef RUN_WITH_CONVERTED_STRING return ret; } @@ -2156,7 +2057,7 @@ static inline ShaDaWriteResult shada_read_when_writing( } case kSDReadStatusNotShaDa: { ret = kSDWriteReadNotShada; - // fallthrough + FALLTHROUGH; } case kSDReadStatusReadError: { return ret; @@ -2429,6 +2330,48 @@ static inline void add_search_pattern(PossiblyFreedShadaEntry *const ret_pse, } } +/// Initialize registers for writing to the ShaDa file +/// +/// @param[in] wms The WriteMergerState used when writing. +/// @param[in] max_reg_lines The maximum number of register lines. +static inline void shada_initialize_registers(WriteMergerState *const wms, + int max_reg_lines) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_ALWAYS_INLINE +{ + const void *reg_iter = NULL; + const bool limit_reg_lines = max_reg_lines >= 0; + do { + yankreg_T reg; + char name = NUL; + bool is_unnamed = false; + reg_iter = op_register_iter(reg_iter, &name, ®, &is_unnamed); + if (name == NUL) { + break; + } + if (limit_reg_lines && reg.y_size > (size_t)max_reg_lines) { + continue; + } + wms->registers[op_reg_index(name)] = (PossiblyFreedShadaEntry) { + .can_free_entry = false, + .data = { + .type = kSDItemRegister, + .timestamp = reg.timestamp, + .data = { + .reg = { + .contents = (char **)reg.y_array, + .contents_size = (size_t)reg.y_size, + .type = reg.y_type, + .width = (size_t)(reg.y_type == kMTBlockWise ? reg.y_width : 0), + .additional_data = reg.additional_data, + .name = name, + .is_unnamed = is_unnamed, + } + } + } + }; + } while (reg_iter != NULL); +} + /// Write ShaDa file /// /// @param[in] sd_writer Structure containing file writer definition. @@ -2455,7 +2398,6 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, if (max_reg_lines < 0) { max_reg_lines = get_shada_parameter('"'); } - const bool limit_reg_lines = max_reg_lines >= 0; const bool dump_registers = (max_reg_lines != 0); khash_t(bufset) removable_bufs = KHASH_EMPTY_TABLE(bufset); const size_t max_kbyte = (size_t) max_kbyte_i; @@ -2556,11 +2498,7 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, break; } typval_T tgttv; - if (sd_writer->sd_conv.vc_type != CONV_NONE) { - var_item_copy(&sd_writer->sd_conv, &vartv, &tgttv, true, 0); - } else { - copy_tv(&vartv, &tgttv); - } + tv_copy(&vartv, &tgttv); ShaDaWriteResult spe_ret; if ((spe_ret = shada_pack_entry(packer, (ShadaEntry) { .type = kSDItemVariable, @@ -2573,13 +2511,13 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, } } }, max_kbyte)) == kSDWriteFailed) { - clear_tv(&vartv); - clear_tv(&tgttv); + tv_clear(&vartv); + tv_clear(&tgttv); ret = kSDWriteFailed; goto shada_write_exit; } - clear_tv(&vartv); - clear_tv(&tgttv); + tv_clear(&vartv); + tv_clear(&tgttv); if (spe_ret == kSDWriteSuccessfull) { int kh_ret; (void) kh_put(strset, &wms->dumped_variables, name, &kh_ret); @@ -2702,35 +2640,7 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, // Initialize registers if (dump_registers) { - const void *reg_iter = NULL; - do { - yankreg_T reg; - char name = NUL; - reg_iter = op_register_iter(reg_iter, &name, ®); - if (name == NUL) { - break; - } - if (limit_reg_lines && reg.y_size > (size_t)max_reg_lines) { - continue; - } - wms->registers[op_reg_index(name)] = (PossiblyFreedShadaEntry) { - .can_free_entry = false, - .data = { - .type = kSDItemRegister, - .timestamp = reg.timestamp, - .data = { - .reg = { - .contents = (char **) reg.y_array, - .contents_size = (size_t) reg.y_size, - .type = reg.y_type, - .width = (size_t) (reg.y_type == kMTBlockWise ? reg.y_width : 0), - .additional_data = reg.additional_data, - .name = name, - } - } - } - }; - } while (reg_iter != NULL); + shada_initialize_registers(wms, max_reg_lines); } // Initialize buffers @@ -2811,9 +2721,8 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, do { \ for (size_t i_ = 0; i_ < ARRAY_SIZE(wms_array); i_++) { \ if (wms_array[i_].data.type != kSDItemMissing) { \ - if (shada_pack_encoded_entry(packer, &sd_writer->sd_conv, \ - wms_array[i_], \ - max_kbyte) == kSDWriteFailed) { \ + if (shada_pack_pfreed_entry(packer, wms_array[i_], max_kbyte) \ + == kSDWriteFailed) { \ ret = kSDWriteFailed; \ goto shada_write_exit; \ } \ @@ -2823,8 +2732,8 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, PACK_WMS_ARRAY(wms->global_marks); PACK_WMS_ARRAY(wms->registers); for (size_t i = 0; i < wms->jumps_size; i++) { - if (shada_pack_encoded_entry(packer, &sd_writer->sd_conv, wms->jumps[i], - max_kbyte) == kSDWriteFailed) { + if (shada_pack_pfreed_entry(packer, wms->jumps[i], max_kbyte) + == kSDWriteFailed) { ret = kSDWriteFailed; goto shada_write_exit; } @@ -2832,8 +2741,8 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, #define PACK_WMS_ENTRY(wms_entry) \ do { \ if (wms_entry.data.type != kSDItemMissing) { \ - if (shada_pack_encoded_entry(packer, &sd_writer->sd_conv, wms_entry, \ - max_kbyte) == kSDWriteFailed) { \ + if (shada_pack_pfreed_entry(packer, wms_entry, max_kbyte) \ + == kSDWriteFailed) { \ ret = kSDWriteFailed; \ goto shada_write_exit; \ } \ @@ -2860,9 +2769,8 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, for (size_t i = 0; i < file_markss_to_dump; i++) { PACK_WMS_ARRAY(all_file_markss[i]->marks); for (size_t j = 0; j < all_file_markss[i]->changes_size; j++) { - if (shada_pack_encoded_entry(packer, &sd_writer->sd_conv, - all_file_markss[i]->changes[j], - max_kbyte) == kSDWriteFailed) { + if (shada_pack_pfreed_entry(packer, all_file_markss[i]->changes[j], + max_kbyte) == kSDWriteFailed) { ret = kSDWriteFailed; goto shada_write_exit; } @@ -2886,8 +2794,8 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, if (dump_one_history[i]) { hms_insert_whole_neovim_history(&wms->hms[i]); HMS_ITER(&wms->hms[i], cur_entry, { - if (shada_pack_encoded_entry( - packer, &sd_writer->sd_conv, (PossiblyFreedShadaEntry) { + if (shada_pack_pfreed_entry( + packer, (PossiblyFreedShadaEntry) { .data = cur_entry->data, .can_free_entry = cur_entry->can_free_entry, }, max_kbyte) == kSDWriteFailed) { @@ -3038,8 +2946,6 @@ shada_write_file_nomerge: {} verbose_leave(); } - convert_setup(&sd_writer.sd_conv, p_enc, "utf-8"); - const ShaDaWriteResult sw_ret = shada_write(&sd_writer, (nomerge ? NULL : &sd_reader)); @@ -3154,17 +3060,17 @@ static void shada_free_shada_entry(ShadaEntry *const entry) case kSDItemJump: case kSDItemGlobalMark: case kSDItemLocalMark: { - dict_unref(entry->data.filemark.additional_data); + tv_dict_unref(entry->data.filemark.additional_data); xfree(entry->data.filemark.fname); break; } case kSDItemSearchPattern: { - dict_unref(entry->data.search_pattern.additional_data); + tv_dict_unref(entry->data.search_pattern.additional_data); xfree(entry->data.search_pattern.pat); break; } case kSDItemRegister: { - dict_unref(entry->data.reg.additional_data); + tv_dict_unref(entry->data.reg.additional_data); for (size_t i = 0; i < entry->data.reg.contents_size; i++) { xfree(entry->data.reg.contents[i]); } @@ -3172,25 +3078,25 @@ static void shada_free_shada_entry(ShadaEntry *const entry) break; } case kSDItemHistoryEntry: { - list_unref(entry->data.history_item.additional_elements); + tv_list_unref(entry->data.history_item.additional_elements); xfree(entry->data.history_item.string); break; } case kSDItemVariable: { - list_unref(entry->data.global_var.additional_elements); + tv_list_unref(entry->data.global_var.additional_elements); xfree(entry->data.global_var.name); - clear_tv(&entry->data.global_var.value); + tv_clear(&entry->data.global_var.value); break; } case kSDItemSubString: { - list_unref(entry->data.sub_string.additional_elements); + tv_list_unref(entry->data.sub_string.additional_elements); xfree(entry->data.sub_string.sub); break; } case kSDItemBufferList: { for (size_t i = 0; i < entry->data.buffer_list.size; i++) { xfree(entry->data.buffer_list.buffers[i].fname); - dict_unref(entry->data.buffer_list.buffers[i].additional_data); + tv_dict_unref(entry->data.buffer_list.buffers[i].additional_data); } xfree(entry->data.buffer_list.buffers); break; @@ -3327,29 +3233,6 @@ static ShaDaReadResult msgpack_read_uint64(ShaDaReadDef *const sd_reader, return kSDReadStatusSuccess; } -/// Convert or copy and return a string -/// -/// @param[in] sd_conv Conversion definition. -/// @param[in] str String to convert. -/// @param[in] len String length. -/// -/// @return [allocated] converted string or copy of the original string. -static inline char *get_converted_string(const vimconv_T *const sd_conv, - const char *const str, - const size_t len) - FUNC_ATTR_NONNULL_ALL FUNC_ATTR_MALLOC FUNC_ATTR_WARN_UNUSED_RESULT -{ - if (!has_non_ascii_len(str, len)) { - return xmemdupz(str, len); - } - size_t new_len = len; - char *const new_str = string_convert(sd_conv, str, &new_len); - if (new_str == NULL) { - return xmemdupz(str, len); - } - return new_str; -} - #define READERR(entry_name, error_desc) \ RERR "Error while reading ShaDa file: " \ entry_name " entry at position %" PRIu64 " " \ @@ -3427,10 +3310,7 @@ static inline char *get_converted_string(const vimconv_T *const sd_conv, sizeof(*unpacked.data.via.map.ptr)); \ ad_ga.ga_len++; \ } -#define CONVERTED(str, len) ( \ - sd_reader->sd_conv.vc_type != CONV_NONE \ - ? get_converted_string(&sd_reader->sd_conv, (str), (len)) \ - : xmemdupz((str), (len))) +#define CONVERTED(str, len) (xmemdupz((str), (len))) #define BIN_CONVERTED(b) CONVERTED(b.ptr, b.size) #define SET_ADDITIONAL_DATA(tgt, name) \ do { \ @@ -3451,7 +3331,7 @@ static inline char *get_converted_string(const vimconv_T *const sd_conv, "cannot be converted to a VimL dictionary")), \ initial_fpos); \ ga_clear(&ad_ga); \ - clear_tv(&adtv); \ + tv_clear(&adtv); \ goto shada_read_next_item_error; \ } \ tgt = adtv.vval.v_dict; \ @@ -3474,7 +3354,7 @@ static inline char *get_converted_string(const vimconv_T *const sd_conv, if (msgpack_to_vim(obj, &aetv) == FAIL) { \ emsgf(_(READERR(name, "cannot be converted to a VimL list")), \ initial_fpos); \ - clear_tv(&aetv); \ + tv_clear(&aetv); \ goto shada_read_next_item_error; \ } \ assert(aetv.v_type == VAR_LIST); \ @@ -3533,8 +3413,16 @@ shada_read_next_item_start: return mru_ret; } - const size_t length = (size_t) length_u64; - entry->timestamp = (Timestamp) timestamp_u64; + if (length_u64 > PTRDIFF_MAX) { + emsgf(_(RCERR "Error while reading ShaDa file: " + "there is an item at position %" PRIu64 " " + "that is stated to be too long"), + initial_fpos); + return kSDReadStatusNotShaDa; + } + + const size_t length = (size_t)length_u64; + entry->timestamp = (Timestamp)timestamp_u64; if (type_u64 == 0) { // kSDItemUnknown cannot possibly pass that far because it is -1 and that @@ -3739,6 +3627,7 @@ shada_read_next_item_start: entry->data.reg.contents[i] = BIN_CONVERTED(arr.ptr[i].via.bin); } } + BOOLEAN_KEY("register", REG_KEY_UNNAMED, entry->data.reg.is_unnamed) TYPED_KEY("register", REG_KEY_TYPE, "an unsigned integer", entry->data.reg.type, POSITIVE_INTEGER, u64, TOU8) TYPED_KEY("register", KEY_NAME_CHAR, "an unsigned integer", @@ -3803,30 +3692,14 @@ shada_read_next_item_start: (char) unpacked.data.via.array.ptr[2].via.u64; } size_t strsize; - if (sd_reader->sd_conv.vc_type == CONV_NONE - || !has_non_ascii_len(unpacked.data.via.array.ptr[1].via.bin.ptr, - unpacked.data.via.array.ptr[1].via.bin.size)) { -shada_read_next_item_hist_no_conv: - strsize = ( - unpacked.data.via.array.ptr[1].via.bin.size - + 1 // Zero byte - + 1); // Separator character - entry->data.history_item.string = xmalloc(strsize); - memcpy(entry->data.history_item.string, - unpacked.data.via.array.ptr[1].via.bin.ptr, - unpacked.data.via.array.ptr[1].via.bin.size); - } else { - size_t len = unpacked.data.via.array.ptr[1].via.bin.size; - char *const converted = string_convert( - &sd_reader->sd_conv, unpacked.data.via.array.ptr[1].via.bin.ptr, - &len); - if (converted != NULL) { - strsize = len + 2; - entry->data.history_item.string = xrealloc(converted, strsize); - } else { - goto shada_read_next_item_hist_no_conv; - } - } + strsize = ( + unpacked.data.via.array.ptr[1].via.bin.size + + 1 // Zero byte + + 1); // Separator character + entry->data.history_item.string = xmalloc(strsize); + memcpy(entry->data.history_item.string, + unpacked.data.via.array.ptr[1].via.bin.ptr, + unpacked.data.via.array.ptr[1].via.bin.size); entry->data.history_item.string[strsize - 2] = 0; entry->data.history_item.string[strsize - 1] = entry->data.history_item.sep; @@ -3859,16 +3732,6 @@ shada_read_next_item_hist_no_conv: "be converted to the VimL value")), initial_fpos); goto shada_read_next_item_error; } - if (sd_reader->sd_conv.vc_type != CONV_NONE) { - typval_T tgttv; - var_item_copy(&sd_reader->sd_conv, - &entry->data.global_var.value, - &tgttv, - true, - 0); - clear_tv(&entry->data.global_var.value); - entry->data.global_var.value = tgttv; - } SET_ADDITIONAL_ELEMENTS(unpacked.data.via.array, 2, entry->data.global_var.additional_elements, "variable"); diff --git a/src/nvim/sign_defs.h b/src/nvim/sign_defs.h index 7288a48e21..3778f4287e 100644 --- a/src/nvim/sign_defs.h +++ b/src/nvim/sign_defs.h @@ -1,6 +1,8 @@ #ifndef NVIM_SIGN_DEFS_H #define NVIM_SIGN_DEFS_H +#include "nvim/pos.h" + // signs: line annotations typedef struct signlist signlist_T; diff --git a/src/nvim/spell.c b/src/nvim/spell.c index 7119ac6dc1..42c9bcc0ee 100644 --- a/src/nvim/spell.c +++ b/src/nvim/spell.c @@ -1,5 +1,10 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + // spell.c: code for spell checking // +// See spellfile.c for the Vim spell file format. +// // The spell checking mechanism uses a tree (aka trie). Each node in the tree // has a list of bytes that can appear (siblings). For each byte there is a // pointer to the node with the byte that follows in the word (child). @@ -63,226 +68,6 @@ // compute the maximum word score that can be used. #define MAXSCORE(word_score, sound_score) ((4 * word_score - sound_score) / 3) -// Vim spell file format: <HEADER> -// <SECTIONS> -// <LWORDTREE> -// <KWORDTREE> -// <PREFIXTREE> -// -// <HEADER>: <fileID> <versionnr> -// -// <fileID> 8 bytes "VIMspell" -// <versionnr> 1 byte VIMSPELLVERSION -// -// -// Sections make it possible to add information to the .spl file without -// making it incompatible with previous versions. There are two kinds of -// sections: -// 1. Not essential for correct spell checking. E.g. for making suggestions. -// These are skipped when not supported. -// 2. Optional information, but essential for spell checking when present. -// E.g. conditions for affixes. When this section is present but not -// supported an error message is given. -// -// <SECTIONS>: <section> ... <sectionend> -// -// <section>: <sectionID> <sectionflags> <sectionlen> (section contents) -// -// <sectionID> 1 byte number from 0 to 254 identifying the section -// -// <sectionflags> 1 byte SNF_REQUIRED: this section is required for correct -// spell checking -// -// <sectionlen> 4 bytes length of section contents, MSB first -// -// <sectionend> 1 byte SN_END -// -// -// sectionID == SN_INFO: <infotext> -// <infotext> N bytes free format text with spell file info (version, -// website, etc) -// -// sectionID == SN_REGION: <regionname> ... -// <regionname> 2 bytes Up to 8 region names: ca, au, etc. Lower case. -// First <regionname> is region 1. -// -// sectionID == SN_CHARFLAGS: <charflagslen> <charflags> -// <folcharslen> <folchars> -// <charflagslen> 1 byte Number of bytes in <charflags> (should be 128). -// <charflags> N bytes List of flags (first one is for character 128): -// 0x01 word character CF_WORD -// 0x02 upper-case character CF_UPPER -// <folcharslen> 2 bytes Number of bytes in <folchars>. -// <folchars> N bytes Folded characters, first one is for character 128. -// -// sectionID == SN_MIDWORD: <midword> -// <midword> N bytes Characters that are word characters only when used -// in the middle of a word. -// -// sectionID == SN_PREFCOND: <prefcondcnt> <prefcond> ... -// <prefcondcnt> 2 bytes Number of <prefcond> items following. -// <prefcond> : <condlen> <condstr> -// <condlen> 1 byte Length of <condstr>. -// <condstr> N bytes Condition for the prefix. -// -// sectionID == SN_REP: <repcount> <rep> ... -// <repcount> 2 bytes number of <rep> items, MSB first. -// <rep> : <repfromlen> <repfrom> <reptolen> <repto> -// <repfromlen> 1 byte length of <repfrom> -// <repfrom> N bytes "from" part of replacement -// <reptolen> 1 byte length of <repto> -// <repto> N bytes "to" part of replacement -// -// sectionID == SN_REPSAL: <repcount> <rep> ... -// just like SN_REP but for soundfolded words -// -// sectionID == SN_SAL: <salflags> <salcount> <sal> ... -// <salflags> 1 byte flags for soundsalike conversion: -// SAL_F0LLOWUP -// SAL_COLLAPSE -// SAL_REM_ACCENTS -// <salcount> 2 bytes number of <sal> items following -// <sal> : <salfromlen> <salfrom> <saltolen> <salto> -// <salfromlen> 1 byte length of <salfrom> -// <salfrom> N bytes "from" part of soundsalike -// <saltolen> 1 byte length of <salto> -// <salto> N bytes "to" part of soundsalike -// -// sectionID == SN_SOFO: <sofofromlen> <sofofrom> <sofotolen> <sofoto> -// <sofofromlen> 2 bytes length of <sofofrom> -// <sofofrom> N bytes "from" part of soundfold -// <sofotolen> 2 bytes length of <sofoto> -// <sofoto> N bytes "to" part of soundfold -// -// sectionID == SN_SUGFILE: <timestamp> -// <timestamp> 8 bytes time in seconds that must match with .sug file -// -// sectionID == SN_NOSPLITSUGS: nothing -// -// sectionID == SN_NOCOMPOUNDSUGS: nothing -// -// sectionID == SN_WORDS: <word> ... -// <word> N bytes NUL terminated common word -// -// sectionID == SN_MAP: <mapstr> -// <mapstr> N bytes String with sequences of similar characters, -// separated by slashes. -// -// sectionID == SN_COMPOUND: <compmax> <compminlen> <compsylmax> <compoptions> -// <comppatcount> <comppattern> ... <compflags> -// <compmax> 1 byte Maximum nr of words in compound word. -// <compminlen> 1 byte Minimal word length for compounding. -// <compsylmax> 1 byte Maximum nr of syllables in compound word. -// <compoptions> 2 bytes COMP_ flags. -// <comppatcount> 2 bytes number of <comppattern> following -// <compflags> N bytes Flags from COMPOUNDRULE items, separated by -// slashes. -// -// <comppattern>: <comppatlen> <comppattext> -// <comppatlen> 1 byte length of <comppattext> -// <comppattext> N bytes end or begin chars from CHECKCOMPOUNDPATTERN -// -// sectionID == SN_NOBREAK: (empty, its presence is what matters) -// -// sectionID == SN_SYLLABLE: <syllable> -// <syllable> N bytes String from SYLLABLE item. -// -// <LWORDTREE>: <wordtree> -// -// <KWORDTREE>: <wordtree> -// -// <PREFIXTREE>: <wordtree> -// -// -// <wordtree>: <nodecount> <nodedata> ... -// -// <nodecount> 4 bytes Number of nodes following. MSB first. -// -// <nodedata>: <siblingcount> <sibling> ... -// -// <siblingcount> 1 byte Number of siblings in this node. The siblings -// follow in sorted order. -// -// <sibling>: <byte> [ <nodeidx> <xbyte> -// | <flags> [<flags2>] [<region>] [<affixID>] -// | [<pflags>] <affixID> <prefcondnr> ] -// -// <byte> 1 byte Byte value of the sibling. Special cases: -// BY_NOFLAGS: End of word without flags and for all -// regions. -// For PREFIXTREE <affixID> and -// <prefcondnr> follow. -// BY_FLAGS: End of word, <flags> follow. -// For PREFIXTREE <pflags>, <affixID> -// and <prefcondnr> follow. -// BY_FLAGS2: End of word, <flags> and <flags2> -// follow. Not used in PREFIXTREE. -// BY_INDEX: Child of sibling is shared, <nodeidx> -// and <xbyte> follow. -// -// <nodeidx> 3 bytes Index of child for this sibling, MSB first. -// -// <xbyte> 1 byte Byte value of the sibling. -// -// <flags> 1 byte Bitmask of: -// WF_ALLCAP word must have only capitals -// WF_ONECAP first char of word must be capital -// WF_KEEPCAP keep-case word -// WF_FIXCAP keep-case word, all caps not allowed -// WF_RARE rare word -// WF_BANNED bad word -// WF_REGION <region> follows -// WF_AFX <affixID> follows -// -// <flags2> 1 byte Bitmask of: -// WF_HAS_AFF >> 8 word includes affix -// WF_NEEDCOMP >> 8 word only valid in compound -// WF_NOSUGGEST >> 8 word not used for suggestions -// WF_COMPROOT >> 8 word already a compound -// WF_NOCOMPBEF >> 8 no compounding before this word -// WF_NOCOMPAFT >> 8 no compounding after this word -// -// <pflags> 1 byte Bitmask of: -// WFP_RARE rare prefix -// WFP_NC non-combining prefix -// WFP_UP letter after prefix made upper case -// -// <region> 1 byte Bitmask for regions in which word is valid. When -// omitted it's valid in all regions. -// Lowest bit is for region 1. -// -// <affixID> 1 byte ID of affix that can be used with this word. In -// PREFIXTREE used for the required prefix ID. -// -// <prefcondnr> 2 bytes Prefix condition number, index in <prefcond> list -// from HEADER. -// -// All text characters are in 'encoding', but stored as single bytes. - -// Vim .sug file format: <SUGHEADER> -// <SUGWORDTREE> -// <SUGTABLE> -// -// <SUGHEADER>: <fileID> <versionnr> <timestamp> -// -// <fileID> 6 bytes "VIMsug" -// <versionnr> 1 byte VIMSUGVERSION -// <timestamp> 8 bytes timestamp that must match with .spl file -// -// -// <SUGWORDTREE>: <wordtree> (see above, no flags or region used) -// -// -// <SUGTABLE>: <sugwcount> <sugline> ... -// -// <sugwcount> 4 bytes number of <sugline> following -// -// <sugline>: <sugnr> ... NUL -// -// <sugnr>: X bytes word number that results in this soundfolded word, -// stored as an offset to the previous number in as -// few bytes as possible, see offset2bytes()) - #include <assert.h> #include <inttypes.h> #include <limits.h> @@ -292,6 +77,9 @@ #include <stdlib.h> #include <wctype.h> +/* for offsetof() */ +#include <stddef.h> + #include "nvim/vim.h" #include "nvim/ascii.h" #include "nvim/spell.h" @@ -307,6 +95,7 @@ #include "nvim/func_attr.h" #include "nvim/getchar.h" #include "nvim/hashtab.h" +#include "nvim/mark.h" #include "nvim/mbyte.h" #include "nvim/memline.h" #include "nvim/memory.h" @@ -320,254 +109,18 @@ #include "nvim/regexp.h" #include "nvim/screen.h" #include "nvim/search.h" +#include "nvim/spellfile.h" #include "nvim/strings.h" #include "nvim/syntax.h" -#include "nvim/ui.h" #include "nvim/undo.h" #include "nvim/os/os.h" #include "nvim/os/input.h" -#ifndef UNIX // it's in os/unix_defs.h for Unix -# include <time.h> // for time_t -#endif - -#define MAXWLEN 254 // Assume max. word len is this many bytes. - // Some places assume a word length fits in a - // byte, thus it can't be above 255. - -// Type used for indexes in the word tree need to be at least 4 bytes. If int -// is 8 bytes we could use something smaller, but what? -typedef int idx_T; - -# define SPL_FNAME_TMPL "%s.%s.spl" -# define SPL_FNAME_ADD ".add." -# define SPL_FNAME_ASCII ".ascii." - -// Flags used for a word. Only the lowest byte can be used, the region byte -// comes above it. -#define WF_REGION 0x01 // region byte follows -#define WF_ONECAP 0x02 // word with one capital (or all capitals) -#define WF_ALLCAP 0x04 // word must be all capitals -#define WF_RARE 0x08 // rare word -#define WF_BANNED 0x10 // bad word -#define WF_AFX 0x20 // affix ID follows -#define WF_FIXCAP 0x40 // keep-case word, allcap not allowed -#define WF_KEEPCAP 0x80 // keep-case word - -// for <flags2>, shifted up one byte to be used in wn_flags -#define WF_HAS_AFF 0x0100 // word includes affix -#define WF_NEEDCOMP 0x0200 // word only valid in compound -#define WF_NOSUGGEST 0x0400 // word not to be suggested -#define WF_COMPROOT 0x0800 // already compounded word, COMPOUNDROOT -#define WF_NOCOMPBEF 0x1000 // no compounding before this word -#define WF_NOCOMPAFT 0x2000 // no compounding after this word - // only used for su_badflags #define WF_MIXCAP 0x20 // mix of upper and lower case: macaRONI #define WF_CAPMASK (WF_ONECAP | WF_ALLCAP | WF_KEEPCAP | WF_FIXCAP) -// flags for <pflags> -#define WFP_RARE 0x01 // rare prefix -#define WFP_NC 0x02 // prefix is not combining -#define WFP_UP 0x04 // to-upper prefix -#define WFP_COMPPERMIT 0x08 // prefix with COMPOUNDPERMITFLAG -#define WFP_COMPFORBID 0x10 // prefix with COMPOUNDFORBIDFLAG - -// Flags for postponed prefixes in "sl_pidxs". Must be above affixID (one -// byte) and prefcondnr (two bytes). -#define WF_RAREPFX (WFP_RARE << 24) // rare postponed prefix -#define WF_PFX_NC (WFP_NC << 24) // non-combining postponed prefix -#define WF_PFX_UP (WFP_UP << 24) // to-upper postponed prefix -#define WF_PFX_COMPPERMIT (WFP_COMPPERMIT << 24) // postponed prefix with - // COMPOUNDPERMITFLAG -#define WF_PFX_COMPFORBID (WFP_COMPFORBID << 24) // postponed prefix with - // COMPOUNDFORBIDFLAG - - -// flags for <compoptions> -#define COMP_CHECKDUP 1 // CHECKCOMPOUNDDUP -#define COMP_CHECKREP 2 // CHECKCOMPOUNDREP -#define COMP_CHECKCASE 4 // CHECKCOMPOUNDCASE -#define COMP_CHECKTRIPLE 8 // CHECKCOMPOUNDTRIPLE - -// Special byte values for <byte>. Some are only used in the tree for -// postponed prefixes, some only in the other trees. This is a bit messy... -#define BY_NOFLAGS 0 // end of word without flags or region; for - // postponed prefix: no <pflags> -#define BY_INDEX 1 // child is shared, index follows -#define BY_FLAGS 2 // end of word, <flags> byte follows; for - // postponed prefix: <pflags> follows -#define BY_FLAGS2 3 // end of word, <flags> and <flags2> bytes - // follow; never used in prefix tree -#define BY_SPECIAL BY_FLAGS2 // highest special byte value - -// Info from "REP", "REPSAL" and "SAL" entries in ".aff" file used in si_rep, -// si_repsal, sl_rep, and si_sal. Not for sl_sal! -// One replacement: from "ft_from" to "ft_to". -typedef struct fromto_S { - char_u *ft_from; - char_u *ft_to; -} fromto_T; - -// Info from "SAL" entries in ".aff" file used in sl_sal. -// The info is split for quick processing by spell_soundfold(). -// Note that "sm_oneof" and "sm_rules" point into sm_lead. -typedef struct salitem_S { - char_u *sm_lead; // leading letters - int sm_leadlen; // length of "sm_lead" - char_u *sm_oneof; // letters from () or NULL - char_u *sm_rules; // rules like ^, $, priority - char_u *sm_to; // replacement. - int *sm_lead_w; // wide character copy of "sm_lead" - int *sm_oneof_w; // wide character copy of "sm_oneof" - int *sm_to_w; // wide character copy of "sm_to" -} salitem_T; - -typedef int salfirst_T; - -// Values for SP_*ERROR are negative, positive values are used by -// read_cnt_string(). -#define SP_TRUNCERROR -1 // spell file truncated error -#define SP_FORMERROR -2 // format error in spell file -#define SP_OTHERERROR -3 // other error while reading spell file - -// Structure used to store words and other info for one language, loaded from -// a .spl file. -// The main access is through the tree in "sl_fbyts/sl_fidxs", storing the -// case-folded words. "sl_kbyts/sl_kidxs" is for keep-case words. -// -// The "byts" array stores the possible bytes in each tree node, preceded by -// the number of possible bytes, sorted on byte value: -// <len> <byte1> <byte2> ... -// The "idxs" array stores the index of the child node corresponding to the -// byte in "byts". -// Exception: when the byte is zero, the word may end here and "idxs" holds -// the flags, region mask and affixID for the word. There may be several -// zeros in sequence for alternative flag/region/affixID combinations. -typedef struct slang_S slang_T; - -struct slang_S { - slang_T *sl_next; // next language - char_u *sl_name; // language name "en", "en.rare", "nl", etc. - char_u *sl_fname; // name of .spl file - bool sl_add; // true if it's a .add file. - - char_u *sl_fbyts; // case-folded word bytes - idx_T *sl_fidxs; // case-folded word indexes - char_u *sl_kbyts; // keep-case word bytes - idx_T *sl_kidxs; // keep-case word indexes - char_u *sl_pbyts; // prefix tree word bytes - idx_T *sl_pidxs; // prefix tree word indexes - - char_u *sl_info; // infotext string or NULL - - char_u sl_regions[17]; // table with up to 8 region names plus NUL - - char_u *sl_midword; // MIDWORD string or NULL - - hashtab_T sl_wordcount; // hashtable with word count, wordcount_T - - int sl_compmax; // COMPOUNDWORDMAX (default: MAXWLEN) - int sl_compminlen; // COMPOUNDMIN (default: 0) - int sl_compsylmax; // COMPOUNDSYLMAX (default: MAXWLEN) - int sl_compoptions; // COMP_* flags - garray_T sl_comppat; // CHECKCOMPOUNDPATTERN items - regprog_T *sl_compprog; // COMPOUNDRULE turned into a regexp progrm - // (NULL when no compounding) - char_u *sl_comprules; // all COMPOUNDRULE concatenated (or NULL) - char_u *sl_compstartflags; // flags for first compound word - char_u *sl_compallflags; // all flags for compound words - bool sl_nobreak; // When true: no spaces between words - char_u *sl_syllable; // SYLLABLE repeatable chars or NULL - garray_T sl_syl_items; // syllable items - - int sl_prefixcnt; // number of items in "sl_prefprog" - regprog_T **sl_prefprog; // table with regprogs for prefixes - - garray_T sl_rep; // list of fromto_T entries from REP lines - int16_t sl_rep_first[256]; // indexes where byte first appears, -1 if - // there is none - garray_T sl_sal; // list of salitem_T entries from SAL lines - salfirst_T sl_sal_first[256]; // indexes where byte first appears, -1 if - // there is none - bool sl_followup; // SAL followup - bool sl_collapse; // SAL collapse_result - bool sl_rem_accents; // SAL remove_accents - bool sl_sofo; // SOFOFROM and SOFOTO instead of SAL items: - // "sl_sal_first" maps chars, when has_mbyte - // "sl_sal" is a list of wide char lists. - garray_T sl_repsal; // list of fromto_T entries from REPSAL lines - int16_t sl_repsal_first[256]; // sl_rep_first for REPSAL lines - bool sl_nosplitsugs; // don't suggest splitting a word - bool sl_nocompoundsugs; // don't suggest compounding - - // Info from the .sug file. Loaded on demand. - time_t sl_sugtime; // timestamp for .sug file - char_u *sl_sbyts; // soundfolded word bytes - idx_T *sl_sidxs; // soundfolded word indexes - buf_T *sl_sugbuf; // buffer with word number table - bool sl_sugloaded; // true when .sug file was loaded or failed to - // load - - bool sl_has_map; // true, if there is a MAP line - hashtab_T sl_map_hash; // MAP for multi-byte chars - int sl_map_array[256]; // MAP for first 256 chars - hashtab_T sl_sounddone; // table with soundfolded words that have - // handled, see add_sound_suggest() -}; - -// First language that is loaded, start of the linked list of loaded -// languages. -static slang_T *first_lang = NULL; - -// Flags used in .spl file for soundsalike flags. -#define SAL_F0LLOWUP 1 -#define SAL_COLLAPSE 2 -#define SAL_REM_ACCENTS 4 - -// Structure used in "b_langp", filled from 'spelllang'. -typedef struct langp_S { - slang_T *lp_slang; // info for this language - slang_T *lp_sallang; // language used for sound folding or NULL - slang_T *lp_replang; // language used for REP items or NULL - int lp_region; // bitmask for region or REGION_ALL -} langp_T; - -#define LANGP_ENTRY(ga, i) (((langp_T *)(ga).ga_data) + (i)) - -#define REGION_ALL 0xff // word valid in all regions - -#define VIMSPELLMAGIC "VIMspell" // string at start of Vim spell file -#define VIMSPELLMAGICL 8 -#define VIMSPELLVERSION 50 - -#define VIMSUGMAGIC "VIMsug" // string at start of Vim .sug file -#define VIMSUGMAGICL 6 -#define VIMSUGVERSION 1 - -// Section IDs. Only renumber them when VIMSPELLVERSION changes! -#define SN_REGION 0 // <regionname> section -#define SN_CHARFLAGS 1 // charflags section -#define SN_MIDWORD 2 // <midword> section -#define SN_PREFCOND 3 // <prefcond> section -#define SN_REP 4 // REP items section -#define SN_SAL 5 // SAL items section -#define SN_SOFO 6 // soundfolding section -#define SN_MAP 7 // MAP items section -#define SN_COMPOUND 8 // compound words section -#define SN_SYLLABLE 9 // syllable section -#define SN_NOBREAK 10 // NOBREAK section -#define SN_SUGFILE 11 // timestamp for .sug file -#define SN_REPSAL 12 // REPSAL items section -#define SN_WORDS 13 // common words -#define SN_NOSPLITSUGS 14 // don't split word for suggestions -#define SN_INFO 15 // info section -#define SN_NOCOMPOUNDSUGS 16 // don't compound for suggestions -#define SN_END 255 // end of sections - -#define SNF_REQUIRED 1 // <sectionflags>: required section - // Result values. Lower number is accepted over higher one. #define SP_BANNED -1 #define SP_RARE 0 @@ -575,17 +128,20 @@ typedef struct langp_S { #define SP_LOCAL 2 #define SP_BAD 3 +// First language that is loaded, start of the linked list of loaded +// languages. +slang_T *first_lang = NULL; + // file used for "zG" and "zW" -static char_u *int_wordlist = NULL; +char_u *int_wordlist = NULL; typedef struct wordcount_S { uint16_t wc_count; // nr of times word was seen char_u wc_word[1]; // word, actually longer } wordcount_T; -static wordcount_T dumwc; -#define WC_KEY_OFF (unsigned)(dumwc.wc_word - (char_u *)&dumwc) -#define HI2WC(hi) ((wordcount_T *)((hi)->hi_key - WC_KEY_OFF)) +#define WC_KEY_OFF offsetof(wordcount_T, wc_word) +#define HI2WC(hi) ((wordcount_T *)((hi)->hi_key - WC_KEY_OFF)) #define MAXWORDCOUNT 0xffff // Information used when looking for suggestions. @@ -716,65 +272,6 @@ typedef struct matchinf_S { char_u *mi_end2; // "mi_end" without following word } matchinf_T; -// The tables used for recognizing word characters according to spelling. -// These are only used for the first 256 characters of 'encoding'. -typedef struct { - bool st_isw[256]; // flags: is word char - bool st_isu[256]; // flags: is uppercase char - char_u st_fold[256]; // chars: folded case - char_u st_upper[256]; // chars: upper case -} spelltab_T; - -// For finding suggestions: At each node in the tree these states are tried: -typedef enum { - STATE_START = 0, // At start of node check for NUL bytes (goodword - // ends); if badword ends there is a match, otherwise - // try splitting word. - STATE_NOPREFIX, // try without prefix - STATE_SPLITUNDO, // Undo splitting. - STATE_ENDNUL, // Past NUL bytes at start of the node. - STATE_PLAIN, // Use each byte of the node. - STATE_DEL, // Delete a byte from the bad word. - STATE_INS_PREP, // Prepare for inserting bytes. - STATE_INS, // Insert a byte in the bad word. - STATE_SWAP, // Swap two bytes. - STATE_UNSWAP, // Undo swap two characters. - STATE_SWAP3, // Swap two characters over three. - STATE_UNSWAP3, // Undo Swap two characters over three. - STATE_UNROT3L, // Undo rotate three characters left - STATE_UNROT3R, // Undo rotate three characters right - STATE_REP_INI, // Prepare for using REP items. - STATE_REP, // Use matching REP items from the .aff file. - STATE_REP_UNDO, // Undo a REP item replacement. - STATE_FINAL // End of this node. -} state_T; - -// Struct to keep the state at each level in suggest_try_change(). -typedef struct trystate_S { - state_T ts_state; // state at this level, STATE_ - int ts_score; // score - idx_T ts_arridx; // index in tree array, start of node - short ts_curi; // index in list of child nodes - char_u ts_fidx; // index in fword[], case-folded bad word - char_u ts_fidxtry; // ts_fidx at which bytes may be changed - char_u ts_twordlen; // valid length of tword[] - char_u ts_prefixdepth; // stack depth for end of prefix or - // PFD_PREFIXTREE or PFD_NOPREFIX - char_u ts_flags; // TSF_ flags - char_u ts_tcharlen; // number of bytes in tword character - char_u ts_tcharidx; // current byte index in tword character - char_u ts_isdiff; // DIFF_ values - char_u ts_fcharstart; // index in fword where badword char started - char_u ts_prewordlen; // length of word in "preword[]" - char_u ts_splitoff; // index in "tword" after last split - char_u ts_splitfidx; // "ts_fidx" at word split - char_u ts_complen; // nr of compound words used - char_u ts_compsplit; // index for "compflags" where word was spit - char_u ts_save_badflags; // su_badflags saved here - char_u ts_delidx; // index in fword for char that was deleted, - // valid when "ts_flags" has TSF_DIDDEL -} trystate_T; - // Structure used for the cookie argument of do_in_runtimepath(). typedef struct spelload_S { char_u sl_lang[MAXWLEN + 1]; // language name @@ -788,200 +285,8 @@ typedef struct syl_item_S { int sy_len; } syl_item_T; -#define MAXLINELEN 500 // Maximum length in bytes of a line in a .aff - // and .dic file. -// Main structure to store the contents of a ".aff" file. -typedef struct afffile_S { - char_u *af_enc; // "SET", normalized, alloc'ed string or NULL - int af_flagtype; // AFT_CHAR, AFT_LONG, AFT_NUM or AFT_CAPLONG - unsigned af_rare; // RARE ID for rare word - unsigned af_keepcase; // KEEPCASE ID for keep-case word - unsigned af_bad; // BAD ID for banned word - unsigned af_needaffix; // NEEDAFFIX ID - unsigned af_circumfix; // CIRCUMFIX ID - unsigned af_needcomp; // NEEDCOMPOUND ID - unsigned af_comproot; // COMPOUNDROOT ID - unsigned af_compforbid; // COMPOUNDFORBIDFLAG ID - unsigned af_comppermit; // COMPOUNDPERMITFLAG ID - unsigned af_nosuggest; // NOSUGGEST ID - int af_pfxpostpone; // postpone prefixes without chop string and - // without flags - bool af_ignoreextra; // IGNOREEXTRA present - hashtab_T af_pref; // hashtable for prefixes, affheader_T - hashtab_T af_suff; // hashtable for suffixes, affheader_T - hashtab_T af_comp; // hashtable for compound flags, compitem_T -} afffile_T; - -#define AFT_CHAR 0 // flags are one character -#define AFT_LONG 1 // flags are two characters -#define AFT_CAPLONG 2 // flags are one or two characters -#define AFT_NUM 3 // flags are numbers, comma separated - -typedef struct affentry_S affentry_T; -// Affix entry from ".aff" file. Used for prefixes and suffixes. -struct affentry_S { - affentry_T *ae_next; // next affix with same name/number - char_u *ae_chop; // text to chop off basic word (can be NULL) - char_u *ae_add; // text to add to basic word (can be NULL) - char_u *ae_flags; // flags on the affix (can be NULL) - char_u *ae_cond; // condition (NULL for ".") - regprog_T *ae_prog; // regexp program for ae_cond or NULL - char ae_compforbid; // COMPOUNDFORBIDFLAG found - char ae_comppermit; // COMPOUNDPERMITFLAG found -}; - -# define AH_KEY_LEN 17 // 2 x 8 bytes + NUL - -// Affix header from ".aff" file. Used for af_pref and af_suff. -typedef struct affheader_S { - char_u ah_key[AH_KEY_LEN]; // key for hashtab == name of affix - unsigned ah_flag; // affix name as number, uses "af_flagtype" - int ah_newID; // prefix ID after renumbering; 0 if not used - int ah_combine; // suffix may combine with prefix - int ah_follows; // another affix block should be following - affentry_T *ah_first; // first affix entry -} affheader_T; - -#define HI2AH(hi) ((affheader_T *)(hi)->hi_key) - -// Flag used in compound items. -typedef struct compitem_S { - char_u ci_key[AH_KEY_LEN]; // key for hashtab == name of compound - unsigned ci_flag; // affix name as number, uses "af_flagtype" - int ci_newID; // affix ID after renumbering. -} compitem_T; - -#define HI2CI(hi) ((compitem_T *)(hi)->hi_key) - -// Structure that is used to store the items in the word tree. This avoids -// the need to keep track of each allocated thing, everything is freed all at -// once after ":mkspell" is done. -// Note: "sb_next" must be just before "sb_data" to make sure the alignment of -// "sb_data" is correct for systems where pointers must be aligned on -// pointer-size boundaries and sizeof(pointer) > sizeof(int) (e.g., Sparc). -#define SBLOCKSIZE 16000 // size of sb_data -typedef struct sblock_S sblock_T; -struct sblock_S { - int sb_used; // nr of bytes already in use - sblock_T *sb_next; // next block in list - char_u sb_data[1]; // data, actually longer -}; - -// A node in the tree. -typedef struct wordnode_S wordnode_T; -struct wordnode_S { - union // shared to save space - { - char_u hashkey[6]; // the hash key, only used while compressing - int index; // index in written nodes (valid after first - // round) - } wn_u1; - union // shared to save space - { - wordnode_T *next; // next node with same hash key - wordnode_T *wnode; // parent node that will write this node - } wn_u2; - wordnode_T *wn_child; // child (next byte in word) - wordnode_T *wn_sibling; // next sibling (alternate byte in word, - // always sorted) - int wn_refs; // Nr. of references to this node. Only - // relevant for first node in a list of - // siblings, in following siblings it is - // always one. - char_u wn_byte; // Byte for this node. NUL for word end - - // Info for when "wn_byte" is NUL. - // In PREFIXTREE "wn_region" is used for the prefcondnr. - // In the soundfolded word tree "wn_flags" has the MSW of the wordnr and - // "wn_region" the LSW of the wordnr. - char_u wn_affixID; // supported/required prefix ID or 0 - uint16_t wn_flags; // WF_ flags - short wn_region; // region mask - -#ifdef SPELL_PRINTTREE - int wn_nr; // sequence nr for printing -#endif -}; - -#define WN_MASK 0xffff // mask relevant bits of "wn_flags" - -#define HI2WN(hi) (wordnode_T *)((hi)->hi_key) - -// Info used while reading the spell files. -typedef struct spellinfo_S { - wordnode_T *si_foldroot; // tree with case-folded words - long si_foldwcount; // nr of words in si_foldroot - - wordnode_T *si_keeproot; // tree with keep-case words - long si_keepwcount; // nr of words in si_keeproot - - wordnode_T *si_prefroot; // tree with postponed prefixes - - long si_sugtree; // creating the soundfolding trie - - sblock_T *si_blocks; // memory blocks used - long si_blocks_cnt; // memory blocks allocated - int si_did_emsg; // TRUE when ran out of memory - - long si_compress_cnt; // words to add before lowering - // compression limit - wordnode_T *si_first_free; // List of nodes that have been freed during - // compression, linked by "wn_child" field. - long si_free_count; // number of nodes in si_first_free -#ifdef SPELL_PRINTTREE - int si_wordnode_nr; // sequence nr for nodes -#endif - buf_T *si_spellbuf; // buffer used to store soundfold word table - - int si_ascii; // handling only ASCII words - int si_add; // addition file - int si_clear_chartab; // when TRUE clear char tables - int si_region; // region mask - vimconv_T si_conv; // for conversion to 'encoding' - int si_memtot; // runtime memory used - int si_verbose; // verbose messages - int si_msg_count; // number of words added since last message - char_u *si_info; // info text chars or NULL - int si_region_count; // number of regions supported (1 when there - // are no regions) - char_u si_region_name[17]; // region names; used only if - // si_region_count > 1) - - garray_T si_rep; // list of fromto_T entries from REP lines - garray_T si_repsal; // list of fromto_T entries from REPSAL lines - garray_T si_sal; // list of fromto_T entries from SAL lines - char_u *si_sofofr; // SOFOFROM text - char_u *si_sofoto; // SOFOTO text - int si_nosugfile; // NOSUGFILE item found - int si_nosplitsugs; // NOSPLITSUGS item found - int si_nocompoundsugs; // NOCOMPOUNDSUGS item found - int si_followup; // soundsalike: ? - int si_collapse; // soundsalike: ? - hashtab_T si_commonwords; // hashtable for common words - time_t si_sugtime; // timestamp for .sug file - int si_rem_accents; // soundsalike: remove accents - garray_T si_map; // MAP info concatenated - char_u *si_midword; // MIDWORD chars or NULL - int si_compmax; // max nr of words for compounding - int si_compminlen; // minimal length for compounding - int si_compsylmax; // max nr of syllables for compounding - int si_compoptions; // COMP_ flags - garray_T si_comppat; // CHECKCOMPOUNDPATTERN items, each stored as - // a string - char_u *si_compflags; // flags used for compounding - char_u si_nobreak; // NOBREAK - char_u *si_syllable; // syllable string - garray_T si_prefcond; // table with conditions for postponed - // prefixes, each stored as a string - int si_newprefID; // current value for ah_newID - int si_newcompID; // current value for compound ID -} spellinfo_T; - -static spelltab_T spelltab; -static int did_set_spelltab; - -#define CF_WORD 0x01 -#define CF_UPPER 0x02 +spelltab_T spelltab; +int did_set_spelltab; // structure used to store soundfolded words that add_sound_suggest() has // handled already. @@ -1023,34 +328,7 @@ typedef struct { #define FIND_COMPOUND 3 // find case-folded compound word #define FIND_KEEPCOMPOUND 4 // find keep-case compound word - -// Use our own character-case definitions, because the current locale may -// differ from what the .spl file uses. -// These must not be called with negative number! -#include <wchar.h> // for towupper() and towlower() -// Multi-byte implementation. For Unicode we can call utf_*(), but don't do -// that for ASCII, because we don't want to use 'casemap' here. Otherwise use -// the "w" library function for characters above 255. -#define SPELL_TOFOLD(c) (enc_utf8 && (c) >= 128 ? utf_fold(c) \ - : (c) < \ - 256 ? (int)spelltab.st_fold[c] : (int)towlower(c)) - -#define SPELL_TOUPPER(c) (enc_utf8 && (c) >= 128 ? utf_toupper(c) \ - : (c) < \ - 256 ? (int)spelltab.st_upper[c] : (int)towupper(c)) - -#define SPELL_ISUPPER(c) (enc_utf8 && (c) >= 128 ? utf_isupper(c) \ - : (c) < 256 ? spelltab.st_isu[c] : iswupper(c)) - - -static char *e_format = N_("E759: Format error in spell file"); -static char *e_spell_trunc = N_("E758: Truncated spell file"); -static char *e_afftrailing = N_("Trailing text in %s line %d: %s"); -static char *e_affname = N_("Affix name too long in %s line %d: %s"); -static char *e_affform = N_("E761: Format error in affix file FOL, LOW or UPP"); -static char *e_affrange = N_( - "E762: Character in FOL, LOW or UPP is out of range"); -static char *msg_compressing = N_("Compressing word tree..."); +char *e_format = N_("E759: Format error in spell file"); // Remember what "z?" replaced. static char_u *repl_from = NULL; @@ -2155,12 +1433,10 @@ spell_move_to ( // the cursor. if (dir == BACKWARD || lnum != wp->w_cursor.lnum - || (lnum == wp->w_cursor.lnum - && (wrapped - || ((colnr_T)(curline - ? p - buf + (ptrdiff_t)len - : p - buf) - > wp->w_cursor.col)))) { + || wrapped + || ((colnr_T)(curline + ? p - buf + (ptrdiff_t)len + : p - buf) > wp->w_cursor.col)) { if (has_syntax) { col = (int)(p - buf); (void)syn_get_id(wp, lnum, (colnr_T)col, @@ -2357,7 +1633,7 @@ static void spell_load_lang(char_u *lang) // Return the encoding used for spell checking: Use 'encoding', except that we // use "latin1" for "latin9". And limit to 60 characters (just in case). -static char_u *spell_enc(void) +char_u *spell_enc(void) { if (STRLEN(p_enc) < 60 && STRCMP(p_enc, "iso-8859-15") != 0) @@ -2375,7 +1651,7 @@ static void int_wordlist_spl(char_u *fname) // Allocate a new slang_T for language "lang". "lang" can be NULL. // Caller must fill "sl_next". -static slang_T *slang_alloc(char_u *lang) +slang_T *slang_alloc(char_u *lang) { slang_T *lp = xcalloc(1, sizeof(slang_T)); @@ -2391,7 +1667,7 @@ static slang_T *slang_alloc(char_u *lang) } // Free the contents of an slang_T and the structure itself. -static void slang_free(slang_T *lp) +void slang_free(slang_T *lp) { xfree(lp->sl_name); xfree(lp->sl_fname); @@ -2416,7 +1692,7 @@ static void free_fromto(fromto_T *ftp) { } // Clear an slang_T so that the file can be reloaded. -static void slang_clear(slang_T *lp) +void slang_clear(slang_T *lp) { garray_T *gap; @@ -2489,7 +1765,7 @@ static void slang_clear(slang_T *lp) } // Clear the info from the .sug file in "lp". -static void slang_clear_sug(slang_T *lp) +void slang_clear_sug(slang_T *lp) { xfree(lp->sl_sbyts); lp->sl_sbyts = NULL; @@ -2521,562 +1797,14 @@ static void spell_load_cb(char_u *fname, void *cookie) } } -// Load one spell file and store the info into a slang_T. -// -// This is invoked in three ways: -// - From spell_load_cb() to load a spell file for the first time. "lang" is -// the language name, "old_lp" is NULL. Will allocate an slang_T. -// - To reload a spell file that was changed. "lang" is NULL and "old_lp" -// points to the existing slang_T. -// - Just after writing a .spl file; it's read back to produce the .sug file. -// "old_lp" is NULL and "lang" is NULL. Will allocate an slang_T. -// -// Returns the slang_T the spell file was loaded into. NULL for error. -static slang_T * -spell_load_file ( - char_u *fname, - char_u *lang, - slang_T *old_lp, - bool silent // no error if file doesn't exist -) -{ - FILE *fd; - char_u buf[VIMSPELLMAGICL]; - char_u *p; - int i; - int n; - int len; - char_u *save_sourcing_name = sourcing_name; - linenr_T save_sourcing_lnum = sourcing_lnum; - slang_T *lp = NULL; - int c = 0; - int res; - - fd = mch_fopen((char *)fname, "r"); - if (fd == NULL) { - if (!silent) - EMSG2(_(e_notopen), fname); - else if (p_verbose > 2) { - verbose_enter(); - smsg((char *)e_notopen, fname); - verbose_leave(); - } - goto endFAIL; - } - if (p_verbose > 2) { - verbose_enter(); - smsg(_("Reading spell file \"%s\""), fname); - verbose_leave(); - } - - if (old_lp == NULL) { - lp = slang_alloc(lang); - - // Remember the file name, used to reload the file when it's updated. - lp->sl_fname = vim_strsave(fname); - - // Check for .add.spl. - lp->sl_add = strstr((char *)path_tail(fname), SPL_FNAME_ADD) != NULL; - } else - lp = old_lp; - - // Set sourcing_name, so that error messages mention the file name. - sourcing_name = fname; - sourcing_lnum = 0; - - // <HEADER>: <fileID> - for (i = 0; i < VIMSPELLMAGICL; ++i) - buf[i] = getc(fd); // <fileID> - if (STRNCMP(buf, VIMSPELLMAGIC, VIMSPELLMAGICL) != 0) { - EMSG(_("E757: This does not look like a spell file")); - goto endFAIL; - } - c = getc(fd); // <versionnr> - if (c < VIMSPELLVERSION) { - EMSG(_("E771: Old spell file, needs to be updated")); - goto endFAIL; - } else if (c > VIMSPELLVERSION) { - EMSG(_("E772: Spell file is for newer version of Vim")); - goto endFAIL; - } - - - // <SECTIONS>: <section> ... <sectionend> - // <section>: <sectionID> <sectionflags> <sectionlen> (section contents) - for (;; ) { - n = getc(fd); // <sectionID> or <sectionend> - if (n == SN_END) - break; - c = getc(fd); // <sectionflags> - len = get4c(fd); // <sectionlen> - if (len < 0) - goto truncerr; - - res = 0; - switch (n) { - case SN_INFO: - lp->sl_info = READ_STRING(fd, len); // <infotext> - if (lp->sl_info == NULL) - goto endFAIL; - break; - - case SN_REGION: - res = read_region_section(fd, lp, len); - break; - - case SN_CHARFLAGS: - res = read_charflags_section(fd); - break; - - case SN_MIDWORD: - lp->sl_midword = READ_STRING(fd, len); // <midword> - if (lp->sl_midword == NULL) - goto endFAIL; - break; - - case SN_PREFCOND: - res = read_prefcond_section(fd, lp); - break; - - case SN_REP: - res = read_rep_section(fd, &lp->sl_rep, lp->sl_rep_first); - break; - - case SN_REPSAL: - res = read_rep_section(fd, &lp->sl_repsal, lp->sl_repsal_first); - break; - - case SN_SAL: - res = read_sal_section(fd, lp); - break; - - case SN_SOFO: - res = read_sofo_section(fd, lp); - break; - - case SN_MAP: - p = READ_STRING(fd, len); // <mapstr> - if (p == NULL) - goto endFAIL; - set_map_str(lp, p); - xfree(p); - break; - - case SN_WORDS: - res = read_words_section(fd, lp, len); - break; - - case SN_SUGFILE: - lp->sl_sugtime = get8ctime(fd); // <timestamp> - break; - - case SN_NOSPLITSUGS: - lp->sl_nosplitsugs = true; - break; - - case SN_NOCOMPOUNDSUGS: - lp->sl_nocompoundsugs = true; - break; - - case SN_COMPOUND: - res = read_compound(fd, lp, len); - break; - - case SN_NOBREAK: - lp->sl_nobreak = true; - break; - - case SN_SYLLABLE: - lp->sl_syllable = READ_STRING(fd, len); // <syllable> - if (lp->sl_syllable == NULL) - goto endFAIL; - if (init_syl_tab(lp) == FAIL) - goto endFAIL; - break; - - default: - // Unsupported section. When it's required give an error - // message. When it's not required skip the contents. - if (c & SNF_REQUIRED) { - EMSG(_("E770: Unsupported section in spell file")); - goto endFAIL; - } - while (--len >= 0) - if (getc(fd) < 0) - goto truncerr; - break; - } -someerror: - if (res == SP_FORMERROR) { - EMSG(_(e_format)); - goto endFAIL; - } - if (res == SP_TRUNCERROR) { -truncerr: - EMSG(_(e_spell_trunc)); - goto endFAIL; - } - if (res == SP_OTHERERROR) - goto endFAIL; - } - - // <LWORDTREE> - res = spell_read_tree(fd, &lp->sl_fbyts, &lp->sl_fidxs, false, 0); - if (res != 0) - goto someerror; - - // <KWORDTREE> - res = spell_read_tree(fd, &lp->sl_kbyts, &lp->sl_kidxs, false, 0); - if (res != 0) - goto someerror; - - // <PREFIXTREE> - res = spell_read_tree(fd, &lp->sl_pbyts, &lp->sl_pidxs, true, - lp->sl_prefixcnt); - if (res != 0) - goto someerror; - - // For a new file link it in the list of spell files. - if (old_lp == NULL && lang != NULL) { - lp->sl_next = first_lang; - first_lang = lp; - } - - goto endOK; - -endFAIL: - if (lang != NULL) - // truncating the name signals the error to spell_load_lang() - *lang = NUL; - if (lp != NULL && old_lp == NULL) - slang_free(lp); - lp = NULL; - -endOK: - if (fd != NULL) - fclose(fd); - sourcing_name = save_sourcing_name; - sourcing_lnum = save_sourcing_lnum; - - return lp; -} - -// Read a length field from "fd" in "cnt_bytes" bytes. -// Allocate memory, read the string into it and add a NUL at the end. -// Returns NULL when the count is zero. -// Sets "*cntp" to SP_*ERROR when there is an error, length of the result -// otherwise. -static char_u *read_cnt_string(FILE *fd, int cnt_bytes, int *cntp) -{ - int cnt = 0; - int i; - char_u *str; - - // read the length bytes, MSB first - for (i = 0; i < cnt_bytes; ++i) - cnt = (cnt << 8) + getc(fd); - if (cnt < 0) { - *cntp = SP_TRUNCERROR; - return NULL; - } - *cntp = cnt; - if (cnt == 0) - return NULL; // nothing to read, return NULL - - str = READ_STRING(fd, cnt); - if (str == NULL) - *cntp = SP_OTHERERROR; - return str; -} - -// Read SN_REGION: <regionname> ... -// Return SP_*ERROR flags. -static int read_region_section(FILE *fd, slang_T *lp, int len) -{ - int i; - - if (len > 16) - return SP_FORMERROR; - for (i = 0; i < len; ++i) - lp->sl_regions[i] = getc(fd); // <regionname> - lp->sl_regions[len] = NUL; - return 0; -} - -// Read SN_CHARFLAGS section: <charflagslen> <charflags> -// <folcharslen> <folchars> -// Return SP_*ERROR flags. -static int read_charflags_section(FILE *fd) -{ - char_u *flags; - char_u *fol; - int flagslen, follen; - - // <charflagslen> <charflags> - flags = read_cnt_string(fd, 1, &flagslen); - if (flagslen < 0) - return flagslen; - - // <folcharslen> <folchars> - fol = read_cnt_string(fd, 2, &follen); - if (follen < 0) { - xfree(flags); - return follen; - } - - // Set the word-char flags and fill SPELL_ISUPPER() table. - if (flags != NULL && fol != NULL) - set_spell_charflags(flags, flagslen, fol); - - xfree(flags); - xfree(fol); - - // When <charflagslen> is zero then <fcharlen> must also be zero. - if ((flags == NULL) != (fol == NULL)) - return SP_FORMERROR; - return 0; -} - -// Read SN_PREFCOND section. -// Return SP_*ERROR flags. -static int read_prefcond_section(FILE *fd, slang_T *lp) -{ - int cnt; - int i; - int n; - char_u *p; - char_u buf[MAXWLEN + 1]; - - // <prefcondcnt> <prefcond> ... - cnt = get2c(fd); // <prefcondcnt> - if (cnt <= 0) - return SP_FORMERROR; - - lp->sl_prefprog = xcalloc(cnt, sizeof(regprog_T *)); - lp->sl_prefixcnt = cnt; - - for (i = 0; i < cnt; ++i) { - // <prefcond> : <condlen> <condstr> - n = getc(fd); // <condlen> - if (n < 0 || n >= MAXWLEN) - return SP_FORMERROR; - - // When <condlen> is zero we have an empty condition. Otherwise - // compile the regexp program used to check for the condition. - if (n > 0) { - buf[0] = '^'; // always match at one position only - p = buf + 1; - while (n-- > 0) - *p++ = getc(fd); // <condstr> - *p = NUL; - lp->sl_prefprog[i] = vim_regcomp(buf, RE_MAGIC + RE_STRING); - } - } - return 0; -} - -// Read REP or REPSAL items section from "fd": <repcount> <rep> ... -// Return SP_*ERROR flags. -static int read_rep_section(FILE *fd, garray_T *gap, int16_t *first) -{ - int cnt; - fromto_T *ftp; - - cnt = get2c(fd); // <repcount> - if (cnt < 0) - return SP_TRUNCERROR; - - ga_grow(gap, cnt); - - // <rep> : <repfromlen> <repfrom> <reptolen> <repto> - for (; gap->ga_len < cnt; ++gap->ga_len) { - int c; - ftp = &((fromto_T *)gap->ga_data)[gap->ga_len]; - ftp->ft_from = read_cnt_string(fd, 1, &c); - if (c < 0) - return c; - if (c == 0) - return SP_FORMERROR; - ftp->ft_to = read_cnt_string(fd, 1, &c); - if (c <= 0) { - xfree(ftp->ft_from); - if (c < 0) - return c; - return SP_FORMERROR; - } - } - - // Fill the first-index table. - for (int i = 0; i < 256; ++i) { - first[i] = -1; - } - for (int i = 0; i < gap->ga_len; ++i) { - ftp = &((fromto_T *)gap->ga_data)[i]; - if (first[*ftp->ft_from] == -1) - first[*ftp->ft_from] = i; - } - return 0; -} - -// Read SN_SAL section: <salflags> <salcount> <sal> ... -// Return SP_*ERROR flags. -static int read_sal_section(FILE *fd, slang_T *slang) -{ - int i; - int cnt; - garray_T *gap; - salitem_T *smp; - int ccnt; - char_u *p; - int c = NUL; - - slang->sl_sofo = false; - - i = getc(fd); // <salflags> - if (i & SAL_F0LLOWUP) - slang->sl_followup = true; - if (i & SAL_COLLAPSE) - slang->sl_collapse = true; - if (i & SAL_REM_ACCENTS) - slang->sl_rem_accents = true; - - cnt = get2c(fd); // <salcount> - if (cnt < 0) - return SP_TRUNCERROR; - - gap = &slang->sl_sal; - ga_init(gap, sizeof(salitem_T), 10); - ga_grow(gap, cnt + 1); - - // <sal> : <salfromlen> <salfrom> <saltolen> <salto> - for (; gap->ga_len < cnt; ++gap->ga_len) { - smp = &((salitem_T *)gap->ga_data)[gap->ga_len]; - ccnt = getc(fd); // <salfromlen> - if (ccnt < 0) - return SP_TRUNCERROR; - p = xmalloc(ccnt + 2); - smp->sm_lead = p; - - // Read up to the first special char into sm_lead. - for (i = 0; i < ccnt; ++i) { - c = getc(fd); // <salfrom> - if (vim_strchr((char_u *)"0123456789(-<^$", c) != NULL) - break; - *p++ = c; - } - smp->sm_leadlen = (int)(p - smp->sm_lead); - *p++ = NUL; - - // Put (abc) chars in sm_oneof, if any. - if (c == '(') { - smp->sm_oneof = p; - for (++i; i < ccnt; ++i) { - c = getc(fd); // <salfrom> - if (c == ')') - break; - *p++ = c; - } - *p++ = NUL; - if (++i < ccnt) - c = getc(fd); - } else - smp->sm_oneof = NULL; - - // Any following chars go in sm_rules. - smp->sm_rules = p; - if (i < ccnt) - // store the char we got while checking for end of sm_lead - *p++ = c; - for (++i; i < ccnt; ++i) - *p++ = getc(fd); // <salfrom> - *p++ = NUL; - - // <saltolen> <salto> - smp->sm_to = read_cnt_string(fd, 1, &ccnt); - if (ccnt < 0) { - xfree(smp->sm_lead); - return ccnt; - } - - if (has_mbyte) { - // convert the multi-byte strings to wide char strings - smp->sm_lead_w = mb_str2wide(smp->sm_lead); - smp->sm_leadlen = mb_charlen(smp->sm_lead); - if (smp->sm_oneof == NULL) - smp->sm_oneof_w = NULL; - else - smp->sm_oneof_w = mb_str2wide(smp->sm_oneof); - if (smp->sm_to == NULL) - smp->sm_to_w = NULL; - else - smp->sm_to_w = mb_str2wide(smp->sm_to); - } - } - - if (!GA_EMPTY(gap)) { - // Add one extra entry to mark the end with an empty sm_lead. Avoids - // that we need to check the index every time. - smp = &((salitem_T *)gap->ga_data)[gap->ga_len]; - p = xmalloc(1); - p[0] = NUL; - smp->sm_lead = p; - smp->sm_leadlen = 0; - smp->sm_oneof = NULL; - smp->sm_rules = p; - smp->sm_to = NULL; - if (has_mbyte) { - smp->sm_lead_w = mb_str2wide(smp->sm_lead); - smp->sm_leadlen = 0; - smp->sm_oneof_w = NULL; - smp->sm_to_w = NULL; - } - ++gap->ga_len; - } - - // Fill the first-index table. - set_sal_first(slang); - - return 0; -} - -// Read SN_WORDS: <word> ... -// Return SP_*ERROR flags. -static int read_words_section(FILE *fd, slang_T *lp, int len) -{ - int done = 0; - int i; - int c; - char_u word[MAXWLEN]; - - while (done < len) { - // Read one word at a time. - for (i = 0;; ++i) { - c = getc(fd); - if (c == EOF) - return SP_TRUNCERROR; - word[i] = c; - if (word[i] == NUL) - break; - if (i == MAXWLEN - 1) - return SP_FORMERROR; - } - - // Init the count to 10. - count_common_word(lp, word, -1, 10); - done += i + 1; - } - return 0; -} - -// Add a word to the hashtable of common words. -// If it's already there then the counter is increased. -static void -count_common_word ( - slang_T *lp, - char_u *word, - int len, // word length, -1 for upto NUL - int count // 1 to count once, 10 to init -) +/// Add a word to the hashtable of common words. +/// If it's already there then the counter is increased. +/// +/// @param[in] lp +/// @param[in] word added to common words hashtable +/// @param[in] len length of word or -1 for NUL terminated +/// @param[in] count 1 to count once, 10 to init +void count_common_word(slang_T *lp, char_u *word, int len, int count) { hash_T hash; hashitem_T *hi; @@ -3092,10 +1820,11 @@ count_common_word ( } hash = hash_hash(p); - hi = hash_lookup(&lp->sl_wordcount, p, hash); + const size_t p_len = STRLEN(p); + hi = hash_lookup(&lp->sl_wordcount, (const char *)p, p_len, hash); if (HASHITEM_EMPTY(hi)) { - wc = xmalloc(sizeof(wordcount_T) + STRLEN(p)); - STRCPY(wc->wc_word, p); + wc = xmalloc(sizeof(wordcount_T) + p_len); + memcpy(wc->wc_word, p, p_len + 1); wc->wc_count = count; hash_add_item(&lp->sl_wordcount, hi, wc->wc_word, hash); } else { @@ -3139,209 +1868,9 @@ score_wordcount_adj ( return score; } -// SN_SOFO: <sofofromlen> <sofofrom> <sofotolen> <sofoto> -// Return SP_*ERROR flags. -static int read_sofo_section(FILE *fd, slang_T *slang) -{ - int cnt; - char_u *from, *to; - int res; - - slang->sl_sofo = true; - - // <sofofromlen> <sofofrom> - from = read_cnt_string(fd, 2, &cnt); - if (cnt < 0) - return cnt; - - // <sofotolen> <sofoto> - to = read_cnt_string(fd, 2, &cnt); - if (cnt < 0) { - xfree(from); - return cnt; - } - - // Store the info in slang->sl_sal and/or slang->sl_sal_first. - if (from != NULL && to != NULL) - res = set_sofo(slang, from, to); - else if (from != NULL || to != NULL) - res = SP_FORMERROR; // only one of two strings is an error - else - res = 0; - - xfree(from); - xfree(to); - return res; -} - -// Read the compound section from the .spl file: -// <compmax> <compminlen> <compsylmax> <compoptions> <compflags> -// Returns SP_*ERROR flags. -static int read_compound(FILE *fd, slang_T *slang, int len) -{ - int todo = len; - int c; - int atstart; - char_u *pat; - char_u *pp; - char_u *cp; - char_u *ap; - char_u *crp; - int cnt; - garray_T *gap; - - if (todo < 2) - return SP_FORMERROR; // need at least two bytes - - --todo; - c = getc(fd); // <compmax> - if (c < 2) - c = MAXWLEN; - slang->sl_compmax = c; - - --todo; - c = getc(fd); // <compminlen> - if (c < 1) - c = 0; - slang->sl_compminlen = c; - - --todo; - c = getc(fd); // <compsylmax> - if (c < 1) - c = MAXWLEN; - slang->sl_compsylmax = c; - - c = getc(fd); // <compoptions> - if (c != 0) - ungetc(c, fd); // be backwards compatible with Vim 7.0b - else { - --todo; - c = getc(fd); // only use the lower byte for now - --todo; - slang->sl_compoptions = c; - - gap = &slang->sl_comppat; - c = get2c(fd); // <comppatcount> - todo -= 2; - ga_init(gap, sizeof(char_u *), c); - ga_grow(gap, c); - while (--c >= 0) { - ((char_u **)(gap->ga_data))[gap->ga_len++] = - read_cnt_string(fd, 1, &cnt); - // <comppatlen> <comppattext> - if (cnt < 0) - return cnt; - todo -= cnt + 1; - } - } - if (todo < 0) - return SP_FORMERROR; - - // Turn the COMPOUNDRULE items into a regexp pattern: - // "a[bc]/a*b+" -> "^\(a[bc]\|a*b\+\)$". - // Inserting backslashes may double the length, "^\(\)$<Nul>" is 7 bytes. - // Conversion to utf-8 may double the size. - c = todo * 2 + 7; - if (enc_utf8) - c += todo * 2; - pat = xmalloc(c); - - // We also need a list of all flags that can appear at the start and one - // for all flags. - cp = xmalloc(todo + 1); - slang->sl_compstartflags = cp; - *cp = NUL; - - ap = xmalloc(todo + 1); - slang->sl_compallflags = ap; - *ap = NUL; - - // And a list of all patterns in their original form, for checking whether - // compounding may work in match_compoundrule(). This is freed when we - // encounter a wildcard, the check doesn't work then. - crp = xmalloc(todo + 1); - slang->sl_comprules = crp; - - pp = pat; - *pp++ = '^'; - *pp++ = '\\'; - *pp++ = '('; - - atstart = 1; - while (todo-- > 0) { - c = getc(fd); // <compflags> - if (c == EOF) { - xfree(pat); - return SP_TRUNCERROR; - } - - // Add all flags to "sl_compallflags". - if (vim_strchr((char_u *)"?*+[]/", c) == NULL - && !byte_in_str(slang->sl_compallflags, c)) { - *ap++ = c; - *ap = NUL; - } - - if (atstart != 0) { - // At start of item: copy flags to "sl_compstartflags". For a - // [abc] item set "atstart" to 2 and copy up to the ']'. - if (c == '[') - atstart = 2; - else if (c == ']') - atstart = 0; - else { - if (!byte_in_str(slang->sl_compstartflags, c)) { - *cp++ = c; - *cp = NUL; - } - if (atstart == 1) - atstart = 0; - } - } - - // Copy flag to "sl_comprules", unless we run into a wildcard. - if (crp != NULL) { - if (c == '?' || c == '+' || c == '*') { - xfree(slang->sl_comprules); - slang->sl_comprules = NULL; - crp = NULL; - } else - *crp++ = c; - } - - if (c == '/') { // slash separates two items - *pp++ = '\\'; - *pp++ = '|'; - atstart = 1; - } else { // normal char, "[abc]" and '*' are copied as-is - if (c == '?' || c == '+' || c == '~') - *pp++ = '\\'; // "a?" becomes "a\?", "a+" becomes "a\+" - if (enc_utf8) - pp += mb_char2bytes(c, pp); - else - *pp++ = c; - } - } - - *pp++ = '\\'; - *pp++ = ')'; - *pp++ = '$'; - *pp = NUL; - - if (crp != NULL) - *crp = NUL; - - slang->sl_compprog = vim_regcomp(pat, RE_MAGIC + RE_STRING + RE_STRICT); - xfree(pat); - if (slang->sl_compprog == NULL) - return SP_FORMERROR; - - return 0; -} - // Returns true if byte "n" appears in "str". // Like strchr() but independent of locale. -static bool byte_in_str(char_u *str, int n) +bool byte_in_str(char_u *str, int n) { char_u *p; @@ -3353,7 +1882,7 @@ static bool byte_in_str(char_u *str, int n) // Truncate "slang->sl_syllable" at the first slash and put the following items // in "slang->sl_syl_items". -static int init_syl_tab(slang_T *slang) +int init_syl_tab(slang_T *slang) { char_u *p; char_u *s; @@ -3430,294 +1959,6 @@ static int count_syllables(slang_T *slang, char_u *word) return cnt; } -// Set the SOFOFROM and SOFOTO items in language "lp". -// Returns SP_*ERROR flags when there is something wrong. -static int set_sofo(slang_T *lp, char_u *from, char_u *to) -{ - int i; - - garray_T *gap; - char_u *s; - char_u *p; - int c; - int *inp; - - if (has_mbyte) { - // Use "sl_sal" as an array with 256 pointers to a list of wide - // characters. The index is the low byte of the character. - // The list contains from-to pairs with a terminating NUL. - // sl_sal_first[] is used for latin1 "from" characters. - gap = &lp->sl_sal; - ga_init(gap, sizeof(int *), 1); - ga_grow(gap, 256); - memset(gap->ga_data, 0, sizeof(int *) * 256); - gap->ga_len = 256; - - // First count the number of items for each list. Temporarily use - // sl_sal_first[] for this. - for (p = from, s = to; *p != NUL && *s != NUL; ) { - c = mb_cptr2char_adv(&p); - mb_cptr_adv(s); - if (c >= 256) - ++lp->sl_sal_first[c & 0xff]; - } - if (*p != NUL || *s != NUL) // lengths differ - return SP_FORMERROR; - - // Allocate the lists. - for (i = 0; i < 256; ++i) - if (lp->sl_sal_first[i] > 0) { - p = xmalloc(sizeof(int) * (lp->sl_sal_first[i] * 2 + 1)); - ((int **)gap->ga_data)[i] = (int *)p; - *(int *)p = 0; - } - - // Put the characters up to 255 in sl_sal_first[] the rest in a sl_sal - // list. - memset(lp->sl_sal_first, 0, sizeof(salfirst_T) * 256); - for (p = from, s = to; *p != NUL && *s != NUL; ) { - c = mb_cptr2char_adv(&p); - i = mb_cptr2char_adv(&s); - if (c >= 256) { - // Append the from-to chars at the end of the list with - // the low byte. - inp = ((int **)gap->ga_data)[c & 0xff]; - while (*inp != 0) - ++inp; - *inp++ = c; // from char - *inp++ = i; // to char - *inp++ = NUL; // NUL at the end - } else - // mapping byte to char is done in sl_sal_first[] - lp->sl_sal_first[c] = i; - } - } else { - // mapping bytes to bytes is done in sl_sal_first[] - if (STRLEN(from) != STRLEN(to)) - return SP_FORMERROR; - - for (i = 0; to[i] != NUL; ++i) - lp->sl_sal_first[from[i]] = to[i]; - lp->sl_sal.ga_len = 1; // indicates we have soundfolding - } - - return 0; -} - -// Fill the first-index table for "lp". -static void set_sal_first(slang_T *lp) -{ - salfirst_T *sfirst; - salitem_T *smp; - int c; - garray_T *gap = &lp->sl_sal; - - sfirst = lp->sl_sal_first; - for (int i = 0; i < 256; ++i) { - sfirst[i] = -1; - } - smp = (salitem_T *)gap->ga_data; - for (int i = 0; i < gap->ga_len; ++i) { - if (has_mbyte) - // Use the lowest byte of the first character. For latin1 it's - // the character, for other encodings it should differ for most - // characters. - c = *smp[i].sm_lead_w & 0xff; - else - c = *smp[i].sm_lead; - if (sfirst[c] == -1) { - sfirst[c] = i; - if (has_mbyte) { - int n; - - // Make sure all entries with this byte are following each - // other. Move the ones that are in the wrong position. Do - // keep the same ordering! - while (i + 1 < gap->ga_len - && (*smp[i + 1].sm_lead_w & 0xff) == c) - // Skip over entry with same index byte. - ++i; - - for (n = 1; i + n < gap->ga_len; ++n) - if ((*smp[i + n].sm_lead_w & 0xff) == c) { - salitem_T tsal; - - // Move entry with same index byte after the entries - // we already found. - ++i; - --n; - tsal = smp[i + n]; - memmove(smp + i + 1, smp + i, - sizeof(salitem_T) * n); - smp[i] = tsal; - } - } - } - } -} - -// Turn a multi-byte string into a wide character string. -// Return it in allocated memory. -static int *mb_str2wide(char_u *s) -{ - int i = 0; - - int *res = xmalloc((mb_charlen(s) + 1) * sizeof(int)); - for (char_u *p = s; *p != NUL; ) - res[i++] = mb_ptr2char_adv(&p); - res[i] = NUL; - - return res; -} - -// Reads a tree from the .spl or .sug file. -// Allocates the memory and stores pointers in "bytsp" and "idxsp". -// This is skipped when the tree has zero length. -// Returns zero when OK, SP_ value for an error. -static int -spell_read_tree ( - FILE *fd, - char_u **bytsp, - idx_T **idxsp, - bool prefixtree, // true for the prefix tree - int prefixcnt // when "prefixtree" is true: prefix count -) -{ - int idx; - char_u *bp; - idx_T *ip; - - // The tree size was computed when writing the file, so that we can - // allocate it as one long block. <nodecount> - int len = get4c(fd); - if (len < 0) - return SP_TRUNCERROR; - if (len > 0) { - // Allocate the byte array. - bp = xmalloc(len); - *bytsp = bp; - - // Allocate the index array. - ip = xcalloc(len, sizeof(*ip)); - *idxsp = ip; - - // Recursively read the tree and store it in the array. - idx = read_tree_node(fd, bp, ip, len, 0, prefixtree, prefixcnt); - if (idx < 0) - return idx; - } - return 0; -} - -// Read one row of siblings from the spell file and store it in the byte array -// "byts" and index array "idxs". Recursively read the children. -// -// NOTE: The code here must match put_node()! -// -// Returns the index (>= 0) following the siblings. -// Returns SP_TRUNCERROR if the file is shorter than expected. -// Returns SP_FORMERROR if there is a format error. -static idx_T -read_tree_node ( - FILE *fd, - char_u *byts, - idx_T *idxs, - int maxidx, // size of arrays - idx_T startidx, // current index in "byts" and "idxs" - bool prefixtree, // true for reading PREFIXTREE - int maxprefcondnr // maximum for <prefcondnr> -) -{ - int len; - int i; - int n; - idx_T idx = startidx; - int c; - int c2; -#define SHARED_MASK 0x8000000 - - len = getc(fd); // <siblingcount> - if (len <= 0) - return SP_TRUNCERROR; - - if (startidx + len >= maxidx) - return SP_FORMERROR; - byts[idx++] = len; - - // Read the byte values, flag/region bytes and shared indexes. - for (i = 1; i <= len; ++i) { - c = getc(fd); // <byte> - if (c < 0) - return SP_TRUNCERROR; - if (c <= BY_SPECIAL) { - if (c == BY_NOFLAGS && !prefixtree) { - // No flags, all regions. - idxs[idx] = 0; - c = 0; - } else if (c != BY_INDEX) { - if (prefixtree) { - // Read the optional pflags byte, the prefix ID and the - // condition nr. In idxs[] store the prefix ID in the low - // byte, the condition index shifted up 8 bits, the flags - // shifted up 24 bits. - if (c == BY_FLAGS) - c = getc(fd) << 24; // <pflags> - else - c = 0; - - c |= getc(fd); // <affixID> - - n = get2c(fd); // <prefcondnr> - if (n >= maxprefcondnr) - return SP_FORMERROR; - c |= (n << 8); - } else { // c must be BY_FLAGS or BY_FLAGS2 - // Read flags and optional region and prefix ID. In - // idxs[] the flags go in the low two bytes, region above - // that and prefix ID above the region. - c2 = c; - c = getc(fd); // <flags> - if (c2 == BY_FLAGS2) - c = (getc(fd) << 8) + c; // <flags2> - if (c & WF_REGION) - c = (getc(fd) << 16) + c; // <region> - if (c & WF_AFX) - c = (getc(fd) << 24) + c; // <affixID> - } - - idxs[idx] = c; - c = 0; - } else { // c == BY_INDEX - // <nodeidx> - n = get3c(fd); - if (n < 0 || n >= maxidx) - return SP_FORMERROR; - idxs[idx] = n + SHARED_MASK; - c = getc(fd); // <xbyte> - } - } - byts[idx++] = c; - } - - // Recursively read the children for non-shared siblings. - // Skip the end-of-word ones (zero byte value) and the shared ones (and - // remove SHARED_MASK) - for (i = 1; i <= len; ++i) - if (byts[startidx + i] != 0) { - if (idxs[startidx + i] & SHARED_MASK) - idxs[startidx + i] &= ~SHARED_MASK; - else { - idxs[startidx + i] = idx; - idx = read_tree_node(fd, byts, idxs, maxidx, idx, - prefixtree, maxprefcondnr); - if (idx < 0) - break; - } - } - - return idx; -} - // Parse 'spelllang' and set w_s->b_langp accordingly. // Returns NULL if it's OK, an error message otherwise. char_u *did_set_spelllang(win_T *wp) @@ -3744,6 +1985,9 @@ char_u *did_set_spelllang(win_T *wp) char_u *ret_msg = NULL; char_u *spl_copy; + bufref_T bufref; + set_bufref(&bufref, wp->w_buffer); + // We don't want to do this recursively. May happen when a language is // not available and the SpellFileMissing autocommand opens a new buffer // in which 'spell' is set. @@ -3822,9 +2066,9 @@ char_u *did_set_spelllang(win_T *wp) spell_load_lang(lang); // SpellFileMissing autocommands may do anything, including // destroying the buffer we are using... - if (!buf_valid(wp->w_buffer)) { + if (!bufref_valid(&bufref)) { ret_msg = - (char_u *)"E797: SpellFileMissing autocommand deleted buffer"; + (char_u *)N_("E797: SpellFileMissing autocommand deleted buffer"); goto theend; } } @@ -4045,16 +2289,17 @@ static int find_region(char_u *rp, char_u *region) return i / 2; } -// Return case type of word: -// w word 0 -// Word WF_ONECAP -// W WORD WF_ALLCAP -// WoRd wOrd WF_KEEPCAP -static int -captype ( - char_u *word, - char_u *end // When NULL use up to NUL byte. -) +/// Return case type of word: +/// w word 0 +/// Word WF_ONECAP +/// W WORD WF_ALLCAP +/// WoRd wOrd WF_KEEPCAP +/// +/// @param[in] word +/// @param[in] end End of word or NULL for NUL delimited string +/// +/// @returns Case type of word +int captype(char_u *word, char_u *end) { char_u *p; int c; @@ -4066,10 +2311,11 @@ captype ( for (p = word; !spell_iswordp_nmw(p, curwin); mb_ptr_adv(p)) if (end == NULL ? *p == NUL : p >= end) return 0; // only non-word characters, illegal word - if (has_mbyte) - c = mb_ptr2char_adv(&p); - else + if (has_mbyte) { + c = mb_ptr2char_adv((const char_u **)&p); + } else { c = *p++; + } firstcap = allcap = SPELL_ISUPPER(c); // Need to check all letters to find a word with mixed upper/lower. @@ -4196,3221 +2442,6 @@ void spell_reload(void) } } -// Reload the spell file "fname" if it's loaded. -static void -spell_reload_one ( - char_u *fname, - bool added_word // invoked through "zg" -) -{ - slang_T *slang; - bool didit = false; - - for (slang = first_lang; slang != NULL; slang = slang->sl_next) { - if (path_full_compare(fname, slang->sl_fname, FALSE) == kEqualFiles) { - slang_clear(slang); - if (spell_load_file(fname, NULL, slang, false) == NULL) - // reloading failed, clear the language - slang_clear(slang); - redraw_all_later(SOME_VALID); - didit = true; - } - } - - // When "zg" was used and the file wasn't loaded yet, should redo - // 'spelllang' to load it now. - if (added_word && !didit) - did_set_spelllang(curwin); -} - - -// Functions for ":mkspell". - - -// In the postponed prefixes tree wn_flags is used to store the WFP_ flags, -// but it must be negative to indicate the prefix tree to tree_add_word(). -// Use a negative number with the lower 8 bits zero. -#define PFX_FLAGS -256 - -// flags for "condit" argument of store_aff_word() -#define CONDIT_COMB 1 // affix must combine -#define CONDIT_CFIX 2 // affix must have CIRCUMFIX flag -#define CONDIT_SUF 4 // add a suffix for matching flags -#define CONDIT_AFF 8 // word already has an affix - -// Tunable parameters for when the tree is compressed. See 'mkspellmem'. -static long compress_start = 30000; // memory / SBLOCKSIZE -static long compress_inc = 100; // memory / SBLOCKSIZE -static long compress_added = 500000; // word count - -#ifdef SPELL_PRINTTREE -// For debugging the tree code: print the current tree in a (more or less) -// readable format, so that we can see what happens when adding a word and/or -// compressing the tree. -// Based on code from Olaf Seibert. -#define PRINTLINESIZE 1000 -#define PRINTWIDTH 6 - -#define PRINTSOME(l, depth, fmt, a1, a2) vim_snprintf(l + depth * PRINTWIDTH, \ - PRINTLINESIZE - PRINTWIDTH * depth, fmt, a1, a2) - -static char line1[PRINTLINESIZE]; -static char line2[PRINTLINESIZE]; -static char line3[PRINTLINESIZE]; - -static void spell_clear_flags(wordnode_T *node) -{ - wordnode_T *np; - - for (np = node; np != NULL; np = np->wn_sibling) { - np->wn_u1.index = FALSE; - spell_clear_flags(np->wn_child); - } -} - -static void spell_print_node(wordnode_T *node, int depth) -{ - if (node->wn_u1.index) { - // Done this node before, print the reference. - PRINTSOME(line1, depth, "(%d)", node->wn_nr, 0); - PRINTSOME(line2, depth, " ", 0, 0); - PRINTSOME(line3, depth, " ", 0, 0); - msg((char_u *)line1); - msg((char_u *)line2); - msg((char_u *)line3); - } else { - node->wn_u1.index = TRUE; - - if (node->wn_byte != NUL) { - if (node->wn_child != NULL) - PRINTSOME(line1, depth, " %c -> ", node->wn_byte, 0); - else - // Cannot happen? - PRINTSOME(line1, depth, " %c ???", node->wn_byte, 0); - } else - PRINTSOME(line1, depth, " $ ", 0, 0); - - PRINTSOME(line2, depth, "%d/%d ", node->wn_nr, node->wn_refs); - - if (node->wn_sibling != NULL) - PRINTSOME(line3, depth, " | ", 0, 0); - else - PRINTSOME(line3, depth, " ", 0, 0); - - if (node->wn_byte == NUL) { - msg((char_u *)line1); - msg((char_u *)line2); - msg((char_u *)line3); - } - - // do the children - if (node->wn_byte != NUL && node->wn_child != NULL) - spell_print_node(node->wn_child, depth + 1); - - // do the siblings - if (node->wn_sibling != NULL) { - // get rid of all parent details except | - STRCPY(line1, line3); - STRCPY(line2, line3); - spell_print_node(node->wn_sibling, depth); - } - } -} - -static void spell_print_tree(wordnode_T *root) -{ - if (root != NULL) { - // Clear the "wn_u1.index" fields, used to remember what has been - // done. - spell_clear_flags(root); - - // Recursively print the tree. - spell_print_node(root, 0); - } -} - -#endif // SPELL_PRINTTREE - -// Reads the affix file "fname". -// Returns an afffile_T, NULL for complete failure. -static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname) -{ - FILE *fd; - afffile_T *aff; - char_u rline[MAXLINELEN]; - char_u *line; - char_u *pc = NULL; -#define MAXITEMCNT 30 - char_u *(items[MAXITEMCNT]); - int itemcnt; - char_u *p; - int lnum = 0; - affheader_T *cur_aff = NULL; - bool did_postpone_prefix = false; - int aff_todo = 0; - hashtab_T *tp; - char_u *low = NULL; - char_u *fol = NULL; - char_u *upp = NULL; - int do_rep; - int do_repsal; - int do_sal; - int do_mapline; - bool found_map = false; - hashitem_T *hi; - int l; - int compminlen = 0; // COMPOUNDMIN value - int compsylmax = 0; // COMPOUNDSYLMAX value - int compoptions = 0; // COMP_ flags - int compmax = 0; // COMPOUNDWORDMAX value - char_u *compflags = NULL; // COMPOUNDFLAG and COMPOUNDRULE - // concatenated - char_u *midword = NULL; // MIDWORD value - char_u *syllable = NULL; // SYLLABLE value - char_u *sofofrom = NULL; // SOFOFROM value - char_u *sofoto = NULL; // SOFOTO value - - // Open the file. - fd = mch_fopen((char *)fname, "r"); - if (fd == NULL) { - EMSG2(_(e_notopen), fname); - return NULL; - } - - vim_snprintf((char *)IObuff, IOSIZE, _("Reading affix file %s ..."), fname); - spell_message(spin, IObuff); - - // Only do REP lines when not done in another .aff file already. - do_rep = GA_EMPTY(&spin->si_rep); - - // Only do REPSAL lines when not done in another .aff file already. - do_repsal = GA_EMPTY(&spin->si_repsal); - - // Only do SAL lines when not done in another .aff file already. - do_sal = GA_EMPTY(&spin->si_sal); - - // Only do MAP lines when not done in another .aff file already. - do_mapline = GA_EMPTY(&spin->si_map); - - // Allocate and init the afffile_T structure. - aff = (afffile_T *)getroom(spin, sizeof(afffile_T), true); - if (aff == NULL) { - fclose(fd); - return NULL; - } - hash_init(&aff->af_pref); - hash_init(&aff->af_suff); - hash_init(&aff->af_comp); - - // Read all the lines in the file one by one. - while (!vim_fgets(rline, MAXLINELEN, fd) && !got_int) { - line_breakcheck(); - ++lnum; - - // Skip comment lines. - if (*rline == '#') - continue; - - // Convert from "SET" to 'encoding' when needed. - xfree(pc); - if (spin->si_conv.vc_type != CONV_NONE) { - pc = string_convert(&spin->si_conv, rline, NULL); - if (pc == NULL) { - smsg(_("Conversion failure for word in %s line %d: %s"), - fname, lnum, rline); - continue; - } - line = pc; - } else { - pc = NULL; - line = rline; - } - - // Split the line up in white separated items. Put a NUL after each - // item. - itemcnt = 0; - for (p = line;; ) { - while (*p != NUL && *p <= ' ') // skip white space and CR/NL - ++p; - if (*p == NUL) - break; - if (itemcnt == MAXITEMCNT) // too many items - break; - items[itemcnt++] = p; - // A few items have arbitrary text argument, don't split them. - if (itemcnt == 2 && spell_info_item(items[0])) - while (*p >= ' ' || *p == TAB) // skip until CR/NL - ++p; - else - while (*p > ' ') // skip until white space or CR/NL - ++p; - if (*p == NUL) - break; - *p++ = NUL; - } - - // Handle non-empty lines. - if (itemcnt > 0) { - if (is_aff_rule(items, itemcnt, "SET", 2) && aff->af_enc == NULL) { - // Setup for conversion from "ENC" to 'encoding'. - aff->af_enc = enc_canonize(items[1]); - if (!spin->si_ascii - && convert_setup(&spin->si_conv, aff->af_enc, - p_enc) == FAIL) - smsg(_("Conversion in %s not supported: from %s to %s"), - fname, aff->af_enc, p_enc); - spin->si_conv.vc_fail = true; - } else if (is_aff_rule(items, itemcnt, "FLAG", 2) - && aff->af_flagtype == AFT_CHAR) { - if (STRCMP(items[1], "long") == 0) - aff->af_flagtype = AFT_LONG; - else if (STRCMP(items[1], "num") == 0) - aff->af_flagtype = AFT_NUM; - else if (STRCMP(items[1], "caplong") == 0) - aff->af_flagtype = AFT_CAPLONG; - else - smsg(_("Invalid value for FLAG in %s line %d: %s"), - fname, lnum, items[1]); - if (aff->af_rare != 0 - || aff->af_keepcase != 0 - || aff->af_bad != 0 - || aff->af_needaffix != 0 - || aff->af_circumfix != 0 - || aff->af_needcomp != 0 - || aff->af_comproot != 0 - || aff->af_nosuggest != 0 - || compflags != NULL - || aff->af_suff.ht_used > 0 - || aff->af_pref.ht_used > 0) - smsg(_("FLAG after using flags in %s line %d: %s"), - fname, lnum, items[1]); - } else if (spell_info_item(items[0]) && itemcnt > 1) { - p = (char_u *)getroom(spin, - (spin->si_info == NULL ? 0 : STRLEN(spin->si_info)) - + STRLEN(items[0]) - + STRLEN(items[1]) + 3, false); - if (p != NULL) { - if (spin->si_info != NULL) { - STRCPY(p, spin->si_info); - STRCAT(p, "\n"); - } - STRCAT(p, items[0]); - STRCAT(p, " "); - STRCAT(p, items[1]); - spin->si_info = p; - } - } else if (is_aff_rule(items, itemcnt, "MIDWORD", 2) - && midword == NULL) { - midword = getroom_save(spin, items[1]); - } else if (is_aff_rule(items, itemcnt, "TRY", 2)) { - // ignored, we look in the tree for what chars may appear - } - // TODO: remove "RAR" later - else if ((is_aff_rule(items, itemcnt, "RAR", 2) - || is_aff_rule(items, itemcnt, "RARE", 2)) - && aff->af_rare == 0) { - aff->af_rare = affitem2flag(aff->af_flagtype, items[1], - fname, lnum); - } - // TODO: remove "KEP" later - else if ((is_aff_rule(items, itemcnt, "KEP", 2) - || is_aff_rule(items, itemcnt, "KEEPCASE", 2)) - && aff->af_keepcase == 0) { - aff->af_keepcase = affitem2flag(aff->af_flagtype, items[1], - fname, lnum); - } else if ((is_aff_rule(items, itemcnt, "BAD", 2) - || is_aff_rule(items, itemcnt, "FORBIDDENWORD", 2)) - && aff->af_bad == 0) { - aff->af_bad = affitem2flag(aff->af_flagtype, items[1], - fname, lnum); - } else if (is_aff_rule(items, itemcnt, "NEEDAFFIX", 2) - && aff->af_needaffix == 0) { - aff->af_needaffix = affitem2flag(aff->af_flagtype, items[1], - fname, lnum); - } else if (is_aff_rule(items, itemcnt, "CIRCUMFIX", 2) - && aff->af_circumfix == 0) { - aff->af_circumfix = affitem2flag(aff->af_flagtype, items[1], - fname, lnum); - } else if (is_aff_rule(items, itemcnt, "NOSUGGEST", 2) - && aff->af_nosuggest == 0) { - aff->af_nosuggest = affitem2flag(aff->af_flagtype, items[1], - fname, lnum); - } else if ((is_aff_rule(items, itemcnt, "NEEDCOMPOUND", 2) - || is_aff_rule(items, itemcnt, "ONLYINCOMPOUND", 2)) - && aff->af_needcomp == 0) { - aff->af_needcomp = affitem2flag(aff->af_flagtype, items[1], - fname, lnum); - } else if (is_aff_rule(items, itemcnt, "COMPOUNDROOT", 2) - && aff->af_comproot == 0) { - aff->af_comproot = affitem2flag(aff->af_flagtype, items[1], - fname, lnum); - } else if (is_aff_rule(items, itemcnt, "COMPOUNDFORBIDFLAG", 2) - && aff->af_compforbid == 0) { - aff->af_compforbid = affitem2flag(aff->af_flagtype, items[1], - fname, lnum); - if (aff->af_pref.ht_used > 0) - smsg(_("Defining COMPOUNDFORBIDFLAG after PFX item may give wrong results in %s line %d"), - fname, lnum); - } else if (is_aff_rule(items, itemcnt, "COMPOUNDPERMITFLAG", 2) - && aff->af_comppermit == 0) { - aff->af_comppermit = affitem2flag(aff->af_flagtype, items[1], - fname, lnum); - if (aff->af_pref.ht_used > 0) - smsg(_("Defining COMPOUNDPERMITFLAG after PFX item may give wrong results in %s line %d"), - fname, lnum); - } else if (is_aff_rule(items, itemcnt, "COMPOUNDFLAG", 2) - && compflags == NULL) { - // Turn flag "c" into COMPOUNDRULE compatible string "c+", - // "Na" into "Na+", "1234" into "1234+". - p = getroom(spin, STRLEN(items[1]) + 2, false); - STRCPY(p, items[1]); - STRCAT(p, "+"); - compflags = p; - } else if (is_aff_rule(items, itemcnt, "COMPOUNDRULES", 2)) { - // We don't use the count, but do check that it's a number and - // not COMPOUNDRULE mistyped. - if (atoi((char *)items[1]) == 0) - smsg(_("Wrong COMPOUNDRULES value in %s line %d: %s"), - fname, lnum, items[1]); - } else if (is_aff_rule(items, itemcnt, "COMPOUNDRULE", 2)) { - // Don't use the first rule if it is a number. - if (compflags != NULL || *skipdigits(items[1]) != NUL) { - // Concatenate this string to previously defined ones, - // using a slash to separate them. - l = (int)STRLEN(items[1]) + 1; - if (compflags != NULL) - l += (int)STRLEN(compflags) + 1; - p = getroom(spin, l, false); - if (compflags != NULL) { - STRCPY(p, compflags); - STRCAT(p, "/"); - } - STRCAT(p, items[1]); - compflags = p; - } - } else if (is_aff_rule(items, itemcnt, "COMPOUNDWORDMAX", 2) - && compmax == 0) { - compmax = atoi((char *)items[1]); - if (compmax == 0) - smsg(_("Wrong COMPOUNDWORDMAX value in %s line %d: %s"), - fname, lnum, items[1]); - } else if (is_aff_rule(items, itemcnt, "COMPOUNDMIN", 2) - && compminlen == 0) { - compminlen = atoi((char *)items[1]); - if (compminlen == 0) - smsg(_("Wrong COMPOUNDMIN value in %s line %d: %s"), - fname, lnum, items[1]); - } else if (is_aff_rule(items, itemcnt, "COMPOUNDSYLMAX", 2) - && compsylmax == 0) { - compsylmax = atoi((char *)items[1]); - if (compsylmax == 0) - smsg(_("Wrong COMPOUNDSYLMAX value in %s line %d: %s"), - fname, lnum, items[1]); - } else if (is_aff_rule(items, itemcnt, "CHECKCOMPOUNDDUP", 1)) { - compoptions |= COMP_CHECKDUP; - } else if (is_aff_rule(items, itemcnt, "CHECKCOMPOUNDREP", 1)) { - compoptions |= COMP_CHECKREP; - } else if (is_aff_rule(items, itemcnt, "CHECKCOMPOUNDCASE", 1)) { - compoptions |= COMP_CHECKCASE; - } else if (is_aff_rule(items, itemcnt, "CHECKCOMPOUNDTRIPLE", 1)) { - compoptions |= COMP_CHECKTRIPLE; - } else if (is_aff_rule(items, itemcnt, "CHECKCOMPOUNDPATTERN", 2)) { - if (atoi((char *)items[1]) == 0) - smsg(_("Wrong CHECKCOMPOUNDPATTERN value in %s line %d: %s"), - fname, lnum, items[1]); - } else if (is_aff_rule(items, itemcnt, "CHECKCOMPOUNDPATTERN", 3)) { - garray_T *gap = &spin->si_comppat; - int i; - - // Only add the couple if it isn't already there. - for (i = 0; i < gap->ga_len - 1; i += 2) - if (STRCMP(((char_u **)(gap->ga_data))[i], items[1]) == 0 - && STRCMP(((char_u **)(gap->ga_data))[i + 1], - items[2]) == 0) - break; - if (i >= gap->ga_len) { - ga_grow(gap, 2); - ((char_u **)(gap->ga_data))[gap->ga_len++] - = getroom_save(spin, items[1]); - ((char_u **)(gap->ga_data))[gap->ga_len++] - = getroom_save(spin, items[2]); - } - } else if (is_aff_rule(items, itemcnt, "SYLLABLE", 2) - && syllable == NULL) { - syllable = getroom_save(spin, items[1]); - } else if (is_aff_rule(items, itemcnt, "NOBREAK", 1)) { - spin->si_nobreak = true; - } else if (is_aff_rule(items, itemcnt, "NOSPLITSUGS", 1)) { - spin->si_nosplitsugs = true; - } else if (is_aff_rule(items, itemcnt, "NOCOMPOUNDSUGS", 1)) { - spin->si_nocompoundsugs = true; - } else if (is_aff_rule(items, itemcnt, "NOSUGFILE", 1)) { - spin->si_nosugfile = true; - } else if (is_aff_rule(items, itemcnt, "PFXPOSTPONE", 1)) { - aff->af_pfxpostpone = true; - } else if (is_aff_rule(items, itemcnt, "IGNOREEXTRA", 1)) { - aff->af_ignoreextra = true; - } else if ((STRCMP(items[0], "PFX") == 0 - || STRCMP(items[0], "SFX") == 0) - && aff_todo == 0 - && itemcnt >= 4) { - int lasti = 4; - char_u key[AH_KEY_LEN]; - - if (*items[0] == 'P') - tp = &aff->af_pref; - else - tp = &aff->af_suff; - - // Myspell allows the same affix name to be used multiple - // times. The affix files that do this have an undocumented - // "S" flag on all but the last block, thus we check for that - // and store it in ah_follows. - STRLCPY(key, items[1], AH_KEY_LEN); - hi = hash_find(tp, key); - if (!HASHITEM_EMPTY(hi)) { - cur_aff = HI2AH(hi); - if (cur_aff->ah_combine != (*items[2] == 'Y')) - smsg(_("Different combining flag in continued affix block in %s line %d: %s"), - fname, lnum, items[1]); - if (!cur_aff->ah_follows) - smsg(_("Duplicate affix in %s line %d: %s"), - fname, lnum, items[1]); - } else { - // New affix letter. - cur_aff = (affheader_T *)getroom(spin, - sizeof(affheader_T), true); - if (cur_aff == NULL) - break; - cur_aff->ah_flag = affitem2flag(aff->af_flagtype, items[1], - fname, lnum); - if (cur_aff->ah_flag == 0 || STRLEN(items[1]) >= AH_KEY_LEN) - break; - if (cur_aff->ah_flag == aff->af_bad - || cur_aff->ah_flag == aff->af_rare - || cur_aff->ah_flag == aff->af_keepcase - || cur_aff->ah_flag == aff->af_needaffix - || cur_aff->ah_flag == aff->af_circumfix - || cur_aff->ah_flag == aff->af_nosuggest - || cur_aff->ah_flag == aff->af_needcomp - || cur_aff->ah_flag == aff->af_comproot) - smsg(_("Affix also used for " - "BAD/RARE/KEEPCASE/NEEDAFFIX/NEEDCOMPOUND/NOSUGGEST" - "in %s line %d: %s"), - fname, lnum, items[1]); - STRCPY(cur_aff->ah_key, items[1]); - hash_add(tp, cur_aff->ah_key); - - cur_aff->ah_combine = (*items[2] == 'Y'); - } - - // Check for the "S" flag, which apparently means that another - // block with the same affix name is following. - if (itemcnt > lasti && STRCMP(items[lasti], "S") == 0) { - ++lasti; - cur_aff->ah_follows = true; - } else - cur_aff->ah_follows = false; - - // Myspell allows extra text after the item, but that might - // mean mistakes go unnoticed. Require a comment-starter, - // unless IGNOREEXTRA is used. Hunspell uses a "-" item. - if (itemcnt > lasti - && !aff->af_ignoreextra - && *items[lasti] != '#') - smsg(_(e_afftrailing), fname, lnum, items[lasti]); - - if (STRCMP(items[2], "Y") != 0 && STRCMP(items[2], "N") != 0) - smsg(_("Expected Y or N in %s line %d: %s"), - fname, lnum, items[2]); - - if (*items[0] == 'P' && aff->af_pfxpostpone) { - if (cur_aff->ah_newID == 0) { - // Use a new number in the .spl file later, to be able - // to handle multiple .aff files. - check_renumber(spin); - cur_aff->ah_newID = ++spin->si_newprefID; - - // We only really use ah_newID if the prefix is - // postponed. We know that only after handling all - // the items. - did_postpone_prefix = false; - } else - // Did use the ID in a previous block. - did_postpone_prefix = true; - } - - aff_todo = atoi((char *)items[3]); - } else if ((STRCMP(items[0], "PFX") == 0 - || STRCMP(items[0], "SFX") == 0) - && aff_todo > 0 - && STRCMP(cur_aff->ah_key, items[1]) == 0 - && itemcnt >= 5) { - affentry_T *aff_entry; - bool upper = false; - int lasti = 5; - - // Myspell allows extra text after the item, but that might - // mean mistakes go unnoticed. Require a comment-starter. - // Hunspell uses a "-" item. - if (itemcnt > lasti && *items[lasti] != '#' - && (STRCMP(items[lasti], "-") != 0 - || itemcnt != lasti + 1)) - smsg(_(e_afftrailing), fname, lnum, items[lasti]); - - // New item for an affix letter. - --aff_todo; - aff_entry = (affentry_T *)getroom(spin, - sizeof(affentry_T), true); - if (aff_entry == NULL) - break; - - if (STRCMP(items[2], "0") != 0) - aff_entry->ae_chop = getroom_save(spin, items[2]); - if (STRCMP(items[3], "0") != 0) { - aff_entry->ae_add = getroom_save(spin, items[3]); - - // Recognize flags on the affix: abcd/XYZ - aff_entry->ae_flags = vim_strchr(aff_entry->ae_add, '/'); - if (aff_entry->ae_flags != NULL) { - *aff_entry->ae_flags++ = NUL; - aff_process_flags(aff, aff_entry); - } - } - - // Don't use an affix entry with non-ASCII characters when - // "spin->si_ascii" is true. - if (!spin->si_ascii || !(has_non_ascii(aff_entry->ae_chop) - || has_non_ascii(aff_entry->ae_add))) { - aff_entry->ae_next = cur_aff->ah_first; - cur_aff->ah_first = aff_entry; - - if (STRCMP(items[4], ".") != 0) { - char_u buf[MAXLINELEN]; - - aff_entry->ae_cond = getroom_save(spin, items[4]); - if (*items[0] == 'P') - sprintf((char *)buf, "^%s", items[4]); - else - sprintf((char *)buf, "%s$", items[4]); - aff_entry->ae_prog = vim_regcomp(buf, - RE_MAGIC + RE_STRING + RE_STRICT); - if (aff_entry->ae_prog == NULL) - smsg(_("Broken condition in %s line %d: %s"), - fname, lnum, items[4]); - } - - // For postponed prefixes we need an entry in si_prefcond - // for the condition. Use an existing one if possible. - // Can't be done for an affix with flags, ignoring - // COMPOUNDFORBIDFLAG and COMPOUNDPERMITFLAG. - if (*items[0] == 'P' && aff->af_pfxpostpone - && aff_entry->ae_flags == NULL) { - // When the chop string is one lower-case letter and - // the add string ends in the upper-case letter we set - // the "upper" flag, clear "ae_chop" and remove the - // letters from "ae_add". The condition must either - // be empty or start with the same letter. - if (aff_entry->ae_chop != NULL - && aff_entry->ae_add != NULL - && aff_entry->ae_chop[(*mb_ptr2len)( - aff_entry->ae_chop)] == NUL - ) { - int c, c_up; - - c = PTR2CHAR(aff_entry->ae_chop); - c_up = SPELL_TOUPPER(c); - if (c_up != c - && (aff_entry->ae_cond == NULL - || PTR2CHAR(aff_entry->ae_cond) == c)) { - p = aff_entry->ae_add - + STRLEN(aff_entry->ae_add); - mb_ptr_back(aff_entry->ae_add, p); - if (PTR2CHAR(p) == c_up) { - upper = true; - aff_entry->ae_chop = NULL; - *p = NUL; - - // The condition is matched with the - // actual word, thus must check for the - // upper-case letter. - if (aff_entry->ae_cond != NULL) { - char_u buf[MAXLINELEN]; - if (has_mbyte) { - onecap_copy(items[4], buf, true); - aff_entry->ae_cond = getroom_save( - spin, buf); - } else - *aff_entry->ae_cond = c_up; - if (aff_entry->ae_cond != NULL) { - sprintf((char *)buf, "^%s", - aff_entry->ae_cond); - vim_regfree(aff_entry->ae_prog); - aff_entry->ae_prog = vim_regcomp( - buf, RE_MAGIC + RE_STRING); - } - } - } - } - } - - if (aff_entry->ae_chop == NULL - && aff_entry->ae_flags == NULL) { - int idx; - char_u **pp; - int n; - - // Find a previously used condition. - for (idx = spin->si_prefcond.ga_len - 1; idx >= 0; - --idx) { - p = ((char_u **)spin->si_prefcond.ga_data)[idx]; - if (str_equal(p, aff_entry->ae_cond)) - break; - } - if (idx < 0) { - // Not found, add a new condition. - idx = spin->si_prefcond.ga_len; - pp = GA_APPEND_VIA_PTR(char_u *, &spin->si_prefcond); - *pp = (aff_entry->ae_cond == NULL) ? - NULL : getroom_save(spin, aff_entry->ae_cond); - } - - // Add the prefix to the prefix tree. - if (aff_entry->ae_add == NULL) - p = (char_u *)""; - else - p = aff_entry->ae_add; - - // PFX_FLAGS is a negative number, so that - // tree_add_word() knows this is the prefix tree. - n = PFX_FLAGS; - if (!cur_aff->ah_combine) - n |= WFP_NC; - if (upper) - n |= WFP_UP; - if (aff_entry->ae_comppermit) - n |= WFP_COMPPERMIT; - if (aff_entry->ae_compforbid) - n |= WFP_COMPFORBID; - tree_add_word(spin, p, spin->si_prefroot, n, - idx, cur_aff->ah_newID); - did_postpone_prefix = true; - } - - // Didn't actually use ah_newID, backup si_newprefID. - if (aff_todo == 0 && !did_postpone_prefix) { - --spin->si_newprefID; - cur_aff->ah_newID = 0; - } - } - } - } else if (is_aff_rule(items, itemcnt, "FOL", 2) && fol == NULL) { - fol = vim_strsave(items[1]); - } else if (is_aff_rule(items, itemcnt, "LOW", 2) && low == NULL) { - low = vim_strsave(items[1]); - } else if (is_aff_rule(items, itemcnt, "UPP", 2) && upp == NULL) { - upp = vim_strsave(items[1]); - } else if (is_aff_rule(items, itemcnt, "REP", 2) - || is_aff_rule(items, itemcnt, "REPSAL", 2)) { - /* Ignore REP/REPSAL count */; - if (!isdigit(*items[1])) - smsg(_("Expected REP(SAL) count in %s line %d"), - fname, lnum); - } else if ((STRCMP(items[0], "REP") == 0 - || STRCMP(items[0], "REPSAL") == 0) - && itemcnt >= 3) { - // REP/REPSAL item - // Myspell ignores extra arguments, we require it starts with - // # to detect mistakes. - if (itemcnt > 3 && items[3][0] != '#') - smsg(_(e_afftrailing), fname, lnum, items[3]); - if (items[0][3] == 'S' ? do_repsal : do_rep) { - // Replace underscore with space (can't include a space - // directly). - for (p = items[1]; *p != NUL; mb_ptr_adv(p)) - if (*p == '_') - *p = ' '; - for (p = items[2]; *p != NUL; mb_ptr_adv(p)) - if (*p == '_') - *p = ' '; - add_fromto(spin, items[0][3] == 'S' - ? &spin->si_repsal - : &spin->si_rep, items[1], items[2]); - } - } else if (is_aff_rule(items, itemcnt, "MAP", 2)) { - // MAP item or count - if (!found_map) { - // First line contains the count. - found_map = true; - if (!isdigit(*items[1])) - smsg(_("Expected MAP count in %s line %d"), - fname, lnum); - } else if (do_mapline) { - int c; - - // Check that every character appears only once. - for (p = items[1]; *p != NUL; ) { - c = mb_ptr2char_adv(&p); - if ((!GA_EMPTY(&spin->si_map) - && vim_strchr(spin->si_map.ga_data, c) - != NULL) - || vim_strchr(p, c) != NULL) - smsg(_("Duplicate character in MAP in %s line %d"), - fname, lnum); - } - - // We simply concatenate all the MAP strings, separated by - // slashes. - ga_concat(&spin->si_map, items[1]); - ga_append(&spin->si_map, '/'); - } - } - // Accept "SAL from to" and "SAL from to #comment". - else if (is_aff_rule(items, itemcnt, "SAL", 3)) { - if (do_sal) { - // SAL item (sounds-a-like) - // Either one of the known keys or a from-to pair. - if (STRCMP(items[1], "followup") == 0) - spin->si_followup = sal_to_bool(items[2]); - else if (STRCMP(items[1], "collapse_result") == 0) - spin->si_collapse = sal_to_bool(items[2]); - else if (STRCMP(items[1], "remove_accents") == 0) - spin->si_rem_accents = sal_to_bool(items[2]); - else - // when "to" is "_" it means empty - add_fromto(spin, &spin->si_sal, items[1], - STRCMP(items[2], "_") == 0 ? (char_u *)"" - : items[2]); - } - } else if (is_aff_rule(items, itemcnt, "SOFOFROM", 2) - && sofofrom == NULL) { - sofofrom = getroom_save(spin, items[1]); - } else if (is_aff_rule(items, itemcnt, "SOFOTO", 2) - && sofoto == NULL) { - sofoto = getroom_save(spin, items[1]); - } else if (STRCMP(items[0], "COMMON") == 0) { - int i; - - for (i = 1; i < itemcnt; ++i) { - if (HASHITEM_EMPTY(hash_find(&spin->si_commonwords, - items[i]))) { - p = vim_strsave(items[i]); - hash_add(&spin->si_commonwords, p); - } - } - } else - smsg(_("Unrecognized or duplicate item in %s line %d: %s"), - fname, lnum, items[0]); - } - } - - if (fol != NULL || low != NULL || upp != NULL) { - if (spin->si_clear_chartab) { - // Clear the char type tables, don't want to use any of the - // currently used spell properties. - init_spell_chartab(); - spin->si_clear_chartab = false; - } - - // Don't write a word table for an ASCII file, so that we don't check - // for conflicts with a word table that matches 'encoding'. - // Don't write one for utf-8 either, we use utf_*() and - // mb_get_class(), the list of chars in the file will be incomplete. - if (!spin->si_ascii - && !enc_utf8 - ) { - if (fol == NULL || low == NULL || upp == NULL) - smsg(_("Missing FOL/LOW/UPP line in %s"), fname); - else - (void)set_spell_chartab(fol, low, upp); - } - - xfree(fol); - xfree(low); - xfree(upp); - } - - // Use compound specifications of the .aff file for the spell info. - if (compmax != 0) { - aff_check_number(spin->si_compmax, compmax, "COMPOUNDWORDMAX"); - spin->si_compmax = compmax; - } - - if (compminlen != 0) { - aff_check_number(spin->si_compminlen, compminlen, "COMPOUNDMIN"); - spin->si_compminlen = compminlen; - } - - if (compsylmax != 0) { - if (syllable == NULL) - smsg(_("COMPOUNDSYLMAX used without SYLLABLE")); - aff_check_number(spin->si_compsylmax, compsylmax, "COMPOUNDSYLMAX"); - spin->si_compsylmax = compsylmax; - } - - if (compoptions != 0) { - aff_check_number(spin->si_compoptions, compoptions, "COMPOUND options"); - spin->si_compoptions |= compoptions; - } - - if (compflags != NULL) - process_compflags(spin, aff, compflags); - - // Check that we didn't use too many renumbered flags. - if (spin->si_newcompID < spin->si_newprefID) { - if (spin->si_newcompID == 127 || spin->si_newcompID == 255) - MSG(_("Too many postponed prefixes")); - else if (spin->si_newprefID == 0 || spin->si_newprefID == 127) - MSG(_("Too many compound flags")); - else - MSG(_("Too many postponed prefixes and/or compound flags")); - } - - if (syllable != NULL) { - aff_check_string(spin->si_syllable, syllable, "SYLLABLE"); - spin->si_syllable = syllable; - } - - if (sofofrom != NULL || sofoto != NULL) { - if (sofofrom == NULL || sofoto == NULL) - smsg(_("Missing SOFO%s line in %s"), - sofofrom == NULL ? "FROM" : "TO", fname); - else if (!GA_EMPTY(&spin->si_sal)) - smsg(_("Both SAL and SOFO lines in %s"), fname); - else { - aff_check_string(spin->si_sofofr, sofofrom, "SOFOFROM"); - aff_check_string(spin->si_sofoto, sofoto, "SOFOTO"); - spin->si_sofofr = sofofrom; - spin->si_sofoto = sofoto; - } - } - - if (midword != NULL) { - aff_check_string(spin->si_midword, midword, "MIDWORD"); - spin->si_midword = midword; - } - - xfree(pc); - fclose(fd); - return aff; -} - -// Returns true when items[0] equals "rulename", there are "mincount" items or -// a comment is following after item "mincount". -static bool is_aff_rule(char_u **items, int itemcnt, char *rulename, int mincount) -{ - return STRCMP(items[0], rulename) == 0 - && (itemcnt == mincount - || (itemcnt > mincount && items[mincount][0] == '#')); -} - -// For affix "entry" move COMPOUNDFORBIDFLAG and COMPOUNDPERMITFLAG from -// ae_flags to ae_comppermit and ae_compforbid. -static void aff_process_flags(afffile_T *affile, affentry_T *entry) -{ - char_u *p; - char_u *prevp; - unsigned flag; - - if (entry->ae_flags != NULL - && (affile->af_compforbid != 0 || affile->af_comppermit != 0)) { - for (p = entry->ae_flags; *p != NUL; ) { - prevp = p; - flag = get_affitem(affile->af_flagtype, &p); - if (flag == affile->af_comppermit || flag == affile->af_compforbid) { - STRMOVE(prevp, p); - p = prevp; - if (flag == affile->af_comppermit) - entry->ae_comppermit = true; - else - entry->ae_compforbid = true; - } - if (affile->af_flagtype == AFT_NUM && *p == ',') - ++p; - } - if (*entry->ae_flags == NUL) - entry->ae_flags = NULL; // nothing left - } -} - -// Returns true if "s" is the name of an info item in the affix file. -static bool spell_info_item(char_u *s) -{ - return STRCMP(s, "NAME") == 0 - || STRCMP(s, "HOME") == 0 - || STRCMP(s, "VERSION") == 0 - || STRCMP(s, "AUTHOR") == 0 - || STRCMP(s, "EMAIL") == 0 - || STRCMP(s, "COPYRIGHT") == 0; -} - -// Turn an affix flag name into a number, according to the FLAG type. -// returns zero for failure. -static unsigned affitem2flag(int flagtype, char_u *item, char_u *fname, int lnum) -{ - unsigned res; - char_u *p = item; - - res = get_affitem(flagtype, &p); - if (res == 0) { - if (flagtype == AFT_NUM) - smsg(_("Flag is not a number in %s line %d: %s"), - fname, lnum, item); - else - smsg(_("Illegal flag in %s line %d: %s"), - fname, lnum, item); - } - if (*p != NUL) { - smsg(_(e_affname), fname, lnum, item); - return 0; - } - - return res; -} - -// Get one affix name from "*pp" and advance the pointer. -// Returns zero for an error, still advances the pointer then. -static unsigned get_affitem(int flagtype, char_u **pp) -{ - int res; - - if (flagtype == AFT_NUM) { - if (!ascii_isdigit(**pp)) { - ++*pp; // always advance, avoid getting stuck - return 0; - } - res = getdigits_int(pp); - } else { - res = mb_ptr2char_adv(pp); - if (flagtype == AFT_LONG || (flagtype == AFT_CAPLONG - && res >= 'A' && res <= 'Z')) { - if (**pp == NUL) - return 0; - res = mb_ptr2char_adv(pp) + (res << 16); - } - } - return res; -} - -// Process the "compflags" string used in an affix file and append it to -// spin->si_compflags. -// The processing involves changing the affix names to ID numbers, so that -// they fit in one byte. -static void process_compflags(spellinfo_T *spin, afffile_T *aff, char_u *compflags) -{ - char_u *p; - char_u *prevp; - unsigned flag; - compitem_T *ci; - int id; - int len; - char_u *tp; - char_u key[AH_KEY_LEN]; - hashitem_T *hi; - - // Make room for the old and the new compflags, concatenated with a / in - // between. Processing it makes it shorter, but we don't know by how - // much, thus allocate the maximum. - len = (int)STRLEN(compflags) + 1; - if (spin->si_compflags != NULL) - len += (int)STRLEN(spin->si_compflags) + 1; - p = getroom(spin, len, false); - if (spin->si_compflags != NULL) { - STRCPY(p, spin->si_compflags); - STRCAT(p, "/"); - } - spin->si_compflags = p; - tp = p + STRLEN(p); - - for (p = compflags; *p != NUL; ) { - if (vim_strchr((char_u *)"/?*+[]", *p) != NULL) - // Copy non-flag characters directly. - *tp++ = *p++; - else { - // First get the flag number, also checks validity. - prevp = p; - flag = get_affitem(aff->af_flagtype, &p); - if (flag != 0) { - // Find the flag in the hashtable. If it was used before, use - // the existing ID. Otherwise add a new entry. - STRLCPY(key, prevp, p - prevp + 1); - hi = hash_find(&aff->af_comp, key); - if (!HASHITEM_EMPTY(hi)) - id = HI2CI(hi)->ci_newID; - else { - ci = (compitem_T *)getroom(spin, sizeof(compitem_T), true); - if (ci == NULL) - break; - STRCPY(ci->ci_key, key); - ci->ci_flag = flag; - // Avoid using a flag ID that has a special meaning in a - // regexp (also inside []). - do { - check_renumber(spin); - id = spin->si_newcompID--; - } while (vim_strchr((char_u *)"/?*+[]\\-^", id) != NULL); - ci->ci_newID = id; - hash_add(&aff->af_comp, ci->ci_key); - } - *tp++ = id; - } - if (aff->af_flagtype == AFT_NUM && *p == ',') - ++p; - } - } - - *tp = NUL; -} - -// Check that the new IDs for postponed affixes and compounding don't overrun -// each other. We have almost 255 available, but start at 0-127 to avoid -// using two bytes for utf-8. When the 0-127 range is used up go to 128-255. -// When that is used up an error message is given. -static void check_renumber(spellinfo_T *spin) -{ - if (spin->si_newprefID == spin->si_newcompID && spin->si_newcompID < 128) { - spin->si_newprefID = 127; - spin->si_newcompID = 255; - } -} - -// Returns true if flag "flag" appears in affix list "afflist". -static bool flag_in_afflist(int flagtype, char_u *afflist, unsigned flag) -{ - char_u *p; - unsigned n; - - switch (flagtype) { - case AFT_CHAR: - return vim_strchr(afflist, flag) != NULL; - - case AFT_CAPLONG: - case AFT_LONG: - for (p = afflist; *p != NUL; ) { - n = mb_ptr2char_adv(&p); - if ((flagtype == AFT_LONG || (n >= 'A' && n <= 'Z')) - && *p != NUL) - n = mb_ptr2char_adv(&p) + (n << 16); - if (n == flag) - return true; - } - break; - - case AFT_NUM: - for (p = afflist; *p != NUL; ) { - int digits = getdigits_int(&p); - assert(digits >= 0); - n = (unsigned int)digits; - if (n == flag) - return true; - if (*p != NUL) // skip over comma - ++p; - } - break; - } - return false; -} - -// Give a warning when "spinval" and "affval" numbers are set and not the same. -static void aff_check_number(int spinval, int affval, char *name) -{ - if (spinval != 0 && spinval != affval) - smsg(_("%s value differs from what is used in another .aff file"), - name); -} - -// Give a warning when "spinval" and "affval" strings are set and not the same. -static void aff_check_string(char_u *spinval, char_u *affval, char *name) -{ - if (spinval != NULL && STRCMP(spinval, affval) != 0) - smsg(_("%s value differs from what is used in another .aff file"), - name); -} - -// Returns true if strings "s1" and "s2" are equal. Also consider both being -// NULL as equal. -static bool str_equal(char_u *s1, char_u *s2) -{ - if (s1 == NULL || s2 == NULL) - return s1 == s2; - return STRCMP(s1, s2) == 0; -} - -// Add a from-to item to "gap". Used for REP and SAL items. -// They are stored case-folded. -static void add_fromto(spellinfo_T *spin, garray_T *gap, char_u *from, char_u *to) -{ - char_u word[MAXWLEN]; - - fromto_T *ftp = GA_APPEND_VIA_PTR(fromto_T, gap); - (void)spell_casefold(from, (int)STRLEN(from), word, MAXWLEN); - ftp->ft_from = getroom_save(spin, word); - (void)spell_casefold(to, (int)STRLEN(to), word, MAXWLEN); - ftp->ft_to = getroom_save(spin, word); -} - -// Converts a boolean argument in a SAL line to true or false; -static bool sal_to_bool(char_u *s) -{ - return STRCMP(s, "1") == 0 || STRCMP(s, "true") == 0; -} - -// Free the structure filled by spell_read_aff(). -static void spell_free_aff(afffile_T *aff) -{ - hashtab_T *ht; - hashitem_T *hi; - int todo; - affheader_T *ah; - affentry_T *ae; - - xfree(aff->af_enc); - - // All this trouble to free the "ae_prog" items... - for (ht = &aff->af_pref;; ht = &aff->af_suff) { - todo = (int)ht->ht_used; - for (hi = ht->ht_array; todo > 0; ++hi) { - if (!HASHITEM_EMPTY(hi)) { - --todo; - ah = HI2AH(hi); - for (ae = ah->ah_first; ae != NULL; ae = ae->ae_next) - vim_regfree(ae->ae_prog); - } - } - if (ht == &aff->af_suff) - break; - } - - hash_clear(&aff->af_pref); - hash_clear(&aff->af_suff); - hash_clear(&aff->af_comp); -} - -// Read dictionary file "fname". -// Returns OK or FAIL; -static int spell_read_dic(spellinfo_T *spin, char_u *fname, afffile_T *affile) -{ - hashtab_T ht; - char_u line[MAXLINELEN]; - char_u *p; - char_u *afflist; - char_u store_afflist[MAXWLEN]; - int pfxlen; - bool need_affix; - char_u *dw; - char_u *pc; - char_u *w; - int l; - hash_T hash; - hashitem_T *hi; - FILE *fd; - int lnum = 1; - int non_ascii = 0; - int retval = OK; - char_u message[MAXLINELEN + MAXWLEN]; - int flags; - int duplicate = 0; - - // Open the file. - fd = mch_fopen((char *)fname, "r"); - if (fd == NULL) { - EMSG2(_(e_notopen), fname); - return FAIL; - } - - // The hashtable is only used to detect duplicated words. - hash_init(&ht); - - vim_snprintf((char *)IObuff, IOSIZE, - _("Reading dictionary file %s ..."), fname); - spell_message(spin, IObuff); - - // start with a message for the first line - spin->si_msg_count = 999999; - - // Read and ignore the first line: word count. - (void)vim_fgets(line, MAXLINELEN, fd); - if (!ascii_isdigit(*skipwhite(line))) - EMSG2(_("E760: No word count in %s"), fname); - - // Read all the lines in the file one by one. - // The words are converted to 'encoding' here, before being added to - // the hashtable. - while (!vim_fgets(line, MAXLINELEN, fd) && !got_int) { - line_breakcheck(); - ++lnum; - if (line[0] == '#' || line[0] == '/') - continue; // comment line - - // Remove CR, LF and white space from the end. White space halfway through - // the word is kept to allow multi-word terms like "et al.". - l = (int)STRLEN(line); - while (l > 0 && line[l - 1] <= ' ') - --l; - if (l == 0) - continue; // empty line - line[l] = NUL; - - // Convert from "SET" to 'encoding' when needed. - if (spin->si_conv.vc_type != CONV_NONE) { - pc = string_convert(&spin->si_conv, line, NULL); - if (pc == NULL) { - smsg(_("Conversion failure for word in %s line %d: %s"), - fname, lnum, line); - continue; - } - w = pc; - } else { - pc = NULL; - w = line; - } - - // Truncate the word at the "/", set "afflist" to what follows. - // Replace "\/" by "/" and "\\" by "\". - afflist = NULL; - for (p = w; *p != NUL; mb_ptr_adv(p)) { - if (*p == '\\' && (p[1] == '\\' || p[1] == '/')) - STRMOVE(p, p + 1); - else if (*p == '/') { - *p = NUL; - afflist = p + 1; - break; - } - } - - // Skip non-ASCII words when "spin->si_ascii" is true. - if (spin->si_ascii && has_non_ascii(w)) { - ++non_ascii; - xfree(pc); - continue; - } - - // This takes time, print a message every 10000 words. - if (spin->si_verbose && spin->si_msg_count > 10000) { - spin->si_msg_count = 0; - vim_snprintf((char *)message, sizeof(message), - _("line %6d, word %6d - %s"), - lnum, spin->si_foldwcount + spin->si_keepwcount, w); - msg_start(); - msg_puts_long_attr(message, 0); - msg_clr_eos(); - msg_didout = FALSE; - msg_col = 0; - ui_flush(); - } - - // Store the word in the hashtable to be able to find duplicates. - dw = getroom_save(spin, w); - if (dw == NULL) { - retval = FAIL; - xfree(pc); - break; - } - - hash = hash_hash(dw); - hi = hash_lookup(&ht, dw, hash); - if (!HASHITEM_EMPTY(hi)) { - if (p_verbose > 0) - smsg(_("Duplicate word in %s line %d: %s"), - fname, lnum, dw); - else if (duplicate == 0) - smsg(_("First duplicate word in %s line %d: %s"), - fname, lnum, dw); - ++duplicate; - } else - hash_add_item(&ht, hi, dw, hash); - - flags = 0; - store_afflist[0] = NUL; - pfxlen = 0; - need_affix = false; - if (afflist != NULL) { - // Extract flags from the affix list. - flags |= get_affix_flags(affile, afflist); - - if (affile->af_needaffix != 0 && flag_in_afflist( - affile->af_flagtype, afflist, affile->af_needaffix)) - need_affix = true; - - if (affile->af_pfxpostpone) - // Need to store the list of prefix IDs with the word. - pfxlen = get_pfxlist(affile, afflist, store_afflist); - - if (spin->si_compflags != NULL) - // Need to store the list of compound flags with the word. - // Concatenate them to the list of prefix IDs. - get_compflags(affile, afflist, store_afflist + pfxlen); - } - - // Add the word to the word tree(s). - if (store_word(spin, dw, flags, spin->si_region, - store_afflist, need_affix) == FAIL) - retval = FAIL; - - if (afflist != NULL) { - // Find all matching suffixes and add the resulting words. - // Additionally do matching prefixes that combine. - if (store_aff_word(spin, dw, afflist, affile, - &affile->af_suff, &affile->af_pref, - CONDIT_SUF, flags, store_afflist, pfxlen) == FAIL) - retval = FAIL; - - // Find all matching prefixes and add the resulting words. - if (store_aff_word(spin, dw, afflist, affile, - &affile->af_pref, NULL, - CONDIT_SUF, flags, store_afflist, pfxlen) == FAIL) - retval = FAIL; - } - - xfree(pc); - } - - if (duplicate > 0) - smsg(_("%d duplicate word(s) in %s"), duplicate, fname); - if (spin->si_ascii && non_ascii > 0) - smsg(_("Ignored %d word(s) with non-ASCII characters in %s"), - non_ascii, fname); - hash_clear(&ht); - - fclose(fd); - return retval; -} - -// Check for affix flags in "afflist" that are turned into word flags. -// Return WF_ flags. -static int get_affix_flags(afffile_T *affile, char_u *afflist) -{ - int flags = 0; - - if (affile->af_keepcase != 0 && flag_in_afflist( - affile->af_flagtype, afflist, affile->af_keepcase)) - flags |= WF_KEEPCAP | WF_FIXCAP; - if (affile->af_rare != 0 && flag_in_afflist( - affile->af_flagtype, afflist, affile->af_rare)) - flags |= WF_RARE; - if (affile->af_bad != 0 && flag_in_afflist( - affile->af_flagtype, afflist, affile->af_bad)) - flags |= WF_BANNED; - if (affile->af_needcomp != 0 && flag_in_afflist( - affile->af_flagtype, afflist, affile->af_needcomp)) - flags |= WF_NEEDCOMP; - if (affile->af_comproot != 0 && flag_in_afflist( - affile->af_flagtype, afflist, affile->af_comproot)) - flags |= WF_COMPROOT; - if (affile->af_nosuggest != 0 && flag_in_afflist( - affile->af_flagtype, afflist, affile->af_nosuggest)) - flags |= WF_NOSUGGEST; - return flags; -} - -// Get the list of prefix IDs from the affix list "afflist". -// Used for PFXPOSTPONE. -// Put the resulting flags in "store_afflist[MAXWLEN]" with a terminating NUL -// and return the number of affixes. -static int get_pfxlist(afffile_T *affile, char_u *afflist, char_u *store_afflist) -{ - char_u *p; - char_u *prevp; - int cnt = 0; - int id; - char_u key[AH_KEY_LEN]; - hashitem_T *hi; - - for (p = afflist; *p != NUL; ) { - prevp = p; - if (get_affitem(affile->af_flagtype, &p) != 0) { - // A flag is a postponed prefix flag if it appears in "af_pref" - // and it's ID is not zero. - STRLCPY(key, prevp, p - prevp + 1); - hi = hash_find(&affile->af_pref, key); - if (!HASHITEM_EMPTY(hi)) { - id = HI2AH(hi)->ah_newID; - if (id != 0) - store_afflist[cnt++] = id; - } - } - if (affile->af_flagtype == AFT_NUM && *p == ',') - ++p; - } - - store_afflist[cnt] = NUL; - return cnt; -} - -// Get the list of compound IDs from the affix list "afflist" that are used -// for compound words. -// Puts the flags in "store_afflist[]". -static void get_compflags(afffile_T *affile, char_u *afflist, char_u *store_afflist) -{ - char_u *p; - char_u *prevp; - int cnt = 0; - char_u key[AH_KEY_LEN]; - hashitem_T *hi; - - for (p = afflist; *p != NUL; ) { - prevp = p; - if (get_affitem(affile->af_flagtype, &p) != 0) { - // A flag is a compound flag if it appears in "af_comp". - STRLCPY(key, prevp, p - prevp + 1); - hi = hash_find(&affile->af_comp, key); - if (!HASHITEM_EMPTY(hi)) - store_afflist[cnt++] = HI2CI(hi)->ci_newID; - } - if (affile->af_flagtype == AFT_NUM && *p == ',') - ++p; - } - - store_afflist[cnt] = NUL; -} - -// Apply affixes to a word and store the resulting words. -// "ht" is the hashtable with affentry_T that need to be applied, either -// prefixes or suffixes. -// "xht", when not NULL, is the prefix hashtable, to be used additionally on -// the resulting words for combining affixes. -// -// Returns FAIL when out of memory. -static int -store_aff_word ( - spellinfo_T *spin, // spell info - char_u *word, // basic word start - char_u *afflist, // list of names of supported affixes - afffile_T *affile, - hashtab_T *ht, - hashtab_T *xht, - int condit, // CONDIT_SUF et al. - int flags, // flags for the word - char_u *pfxlist, // list of prefix IDs - int pfxlen // nr of flags in "pfxlist" for prefixes, rest - // is compound flags -) -{ - int todo; - hashitem_T *hi; - affheader_T *ah; - affentry_T *ae; - char_u newword[MAXWLEN]; - int retval = OK; - int i, j; - char_u *p; - int use_flags; - char_u *use_pfxlist; - int use_pfxlen; - bool need_affix; - char_u store_afflist[MAXWLEN]; - char_u pfx_pfxlist[MAXWLEN]; - size_t wordlen = STRLEN(word); - int use_condit; - - todo = (int)ht->ht_used; - for (hi = ht->ht_array; todo > 0 && retval == OK; ++hi) { - if (!HASHITEM_EMPTY(hi)) { - --todo; - ah = HI2AH(hi); - - // Check that the affix combines, if required, and that the word - // supports this affix. - if (((condit & CONDIT_COMB) == 0 || ah->ah_combine) - && flag_in_afflist(affile->af_flagtype, afflist, - ah->ah_flag)) { - // Loop over all affix entries with this name. - for (ae = ah->ah_first; ae != NULL; ae = ae->ae_next) { - // Check the condition. It's not logical to match case - // here, but it is required for compatibility with - // Myspell. - // Another requirement from Myspell is that the chop - // string is shorter than the word itself. - // For prefixes, when "PFXPOSTPONE" was used, only do - // prefixes with a chop string and/or flags. - // When a previously added affix had CIRCUMFIX this one - // must have it too, if it had not then this one must not - // have one either. - if ((xht != NULL || !affile->af_pfxpostpone - || ae->ae_chop != NULL - || ae->ae_flags != NULL) - && (ae->ae_chop == NULL - || STRLEN(ae->ae_chop) < wordlen) - && (ae->ae_prog == NULL - || vim_regexec_prog(&ae->ae_prog, false, word, (colnr_T)0)) - && (((condit & CONDIT_CFIX) == 0) - == ((condit & CONDIT_AFF) == 0 - || ae->ae_flags == NULL - || !flag_in_afflist(affile->af_flagtype, - ae->ae_flags, affile->af_circumfix)))) { - // Match. Remove the chop and add the affix. - if (xht == NULL) { - // prefix: chop/add at the start of the word - if (ae->ae_add == NULL) - *newword = NUL; - else - STRLCPY(newword, ae->ae_add, MAXWLEN); - p = word; - if (ae->ae_chop != NULL) { - // Skip chop string. - if (has_mbyte) { - i = mb_charlen(ae->ae_chop); - for (; i > 0; --i) - mb_ptr_adv(p); - } else - p += STRLEN(ae->ae_chop); - } - STRCAT(newword, p); - } else { - // suffix: chop/add at the end of the word - STRLCPY(newword, word, MAXWLEN); - if (ae->ae_chop != NULL) { - // Remove chop string. - p = newword + STRLEN(newword); - i = (int)MB_CHARLEN(ae->ae_chop); - for (; i > 0; --i) - mb_ptr_back(newword, p); - *p = NUL; - } - if (ae->ae_add != NULL) - STRCAT(newword, ae->ae_add); - } - - use_flags = flags; - use_pfxlist = pfxlist; - use_pfxlen = pfxlen; - need_affix = false; - use_condit = condit | CONDIT_COMB | CONDIT_AFF; - if (ae->ae_flags != NULL) { - // Extract flags from the affix list. - use_flags |= get_affix_flags(affile, ae->ae_flags); - - if (affile->af_needaffix != 0 && flag_in_afflist( - affile->af_flagtype, ae->ae_flags, - affile->af_needaffix)) - need_affix = true; - - // When there is a CIRCUMFIX flag the other affix - // must also have it and we don't add the word - // with one affix. - if (affile->af_circumfix != 0 && flag_in_afflist( - affile->af_flagtype, ae->ae_flags, - affile->af_circumfix)) { - use_condit |= CONDIT_CFIX; - if ((condit & CONDIT_CFIX) == 0) - need_affix = true; - } - - if (affile->af_pfxpostpone - || spin->si_compflags != NULL) { - if (affile->af_pfxpostpone) - // Get prefix IDS from the affix list. - use_pfxlen = get_pfxlist(affile, - ae->ae_flags, store_afflist); - else - use_pfxlen = 0; - use_pfxlist = store_afflist; - - // Combine the prefix IDs. Avoid adding the - // same ID twice. - for (i = 0; i < pfxlen; ++i) { - for (j = 0; j < use_pfxlen; ++j) - if (pfxlist[i] == use_pfxlist[j]) - break; - if (j == use_pfxlen) - use_pfxlist[use_pfxlen++] = pfxlist[i]; - } - - if (spin->si_compflags != NULL) - // Get compound IDS from the affix list. - get_compflags(affile, ae->ae_flags, - use_pfxlist + use_pfxlen); - else - use_pfxlist[use_pfxlen] = NUL; - - // Combine the list of compound flags. - // Concatenate them to the prefix IDs list. - // Avoid adding the same ID twice. - for (i = pfxlen; pfxlist[i] != NUL; ++i) { - for (j = use_pfxlen; - use_pfxlist[j] != NUL; ++j) - if (pfxlist[i] == use_pfxlist[j]) - break; - if (use_pfxlist[j] == NUL) { - use_pfxlist[j++] = pfxlist[i]; - use_pfxlist[j] = NUL; - } - } - } - } - - // Obey a "COMPOUNDFORBIDFLAG" of the affix: don't - // use the compound flags. - if (use_pfxlist != NULL && ae->ae_compforbid) { - STRLCPY(pfx_pfxlist, use_pfxlist, use_pfxlen + 1); - use_pfxlist = pfx_pfxlist; - } - - // When there are postponed prefixes... - if (spin->si_prefroot != NULL - && spin->si_prefroot->wn_sibling != NULL) { - // ... add a flag to indicate an affix was used. - use_flags |= WF_HAS_AFF; - - // ... don't use a prefix list if combining - // affixes is not allowed. But do use the - // compound flags after them. - if (!ah->ah_combine && use_pfxlist != NULL) - use_pfxlist += use_pfxlen; - } - - // When compounding is supported and there is no - // "COMPOUNDPERMITFLAG" then forbid compounding on the - // side where the affix is applied. - if (spin->si_compflags != NULL && !ae->ae_comppermit) { - if (xht != NULL) - use_flags |= WF_NOCOMPAFT; - else - use_flags |= WF_NOCOMPBEF; - } - - // Store the modified word. - if (store_word(spin, newword, use_flags, - spin->si_region, use_pfxlist, - need_affix) == FAIL) - retval = FAIL; - - // When added a prefix or a first suffix and the affix - // has flags may add a(nother) suffix. RECURSIVE! - if ((condit & CONDIT_SUF) && ae->ae_flags != NULL) - if (store_aff_word(spin, newword, ae->ae_flags, - affile, &affile->af_suff, xht, - use_condit & (xht == NULL - ? ~0 : ~CONDIT_SUF), - use_flags, use_pfxlist, pfxlen) == FAIL) - retval = FAIL; - - // When added a suffix and combining is allowed also - // try adding a prefix additionally. Both for the - // word flags and for the affix flags. RECURSIVE! - if (xht != NULL && ah->ah_combine) { - if (store_aff_word(spin, newword, - afflist, affile, - xht, NULL, use_condit, - use_flags, use_pfxlist, - pfxlen) == FAIL - || (ae->ae_flags != NULL - && store_aff_word(spin, newword, - ae->ae_flags, affile, - xht, NULL, use_condit, - use_flags, use_pfxlist, - pfxlen) == FAIL)) - retval = FAIL; - } - } - } - } - } - } - - return retval; -} - -// Read a file with a list of words. -static int spell_read_wordfile(spellinfo_T *spin, char_u *fname) -{ - FILE *fd; - long lnum = 0; - char_u rline[MAXLINELEN]; - char_u *line; - char_u *pc = NULL; - char_u *p; - int l; - int retval = OK; - bool did_word = false; - int non_ascii = 0; - int flags; - int regionmask; - - // Open the file. - fd = mch_fopen((char *)fname, "r"); - if (fd == NULL) { - EMSG2(_(e_notopen), fname); - return FAIL; - } - - vim_snprintf((char *)IObuff, IOSIZE, _("Reading word file %s ..."), fname); - spell_message(spin, IObuff); - - // Read all the lines in the file one by one. - while (!vim_fgets(rline, MAXLINELEN, fd) && !got_int) { - line_breakcheck(); - ++lnum; - - // Skip comment lines. - if (*rline == '#') - continue; - - // Remove CR, LF and white space from the end. - l = (int)STRLEN(rline); - while (l > 0 && rline[l - 1] <= ' ') - --l; - if (l == 0) - continue; // empty or blank line - rline[l] = NUL; - - // Convert from "/encoding={encoding}" to 'encoding' when needed. - xfree(pc); - if (spin->si_conv.vc_type != CONV_NONE) { - pc = string_convert(&spin->si_conv, rline, NULL); - if (pc == NULL) { - smsg(_("Conversion failure for word in %s line %d: %s"), - fname, lnum, rline); - continue; - } - line = pc; - } else { - pc = NULL; - line = rline; - } - - if (*line == '/') { - ++line; - if (STRNCMP(line, "encoding=", 9) == 0) { - if (spin->si_conv.vc_type != CONV_NONE) - smsg(_("Duplicate /encoding= line ignored in %s line %d: %s"), - fname, lnum, line - 1); - else if (did_word) - smsg(_("/encoding= line after word ignored in %s line %d: %s"), - fname, lnum, line - 1); - else { - char_u *enc; - - // Setup for conversion to 'encoding'. - line += 9; - enc = enc_canonize(line); - if (!spin->si_ascii - && convert_setup(&spin->si_conv, enc, - p_enc) == FAIL) - smsg(_("Conversion in %s not supported: from %s to %s"), - fname, line, p_enc); - xfree(enc); - spin->si_conv.vc_fail = true; - } - continue; - } - - if (STRNCMP(line, "regions=", 8) == 0) { - if (spin->si_region_count > 1) - smsg(_("Duplicate /regions= line ignored in %s line %d: %s"), - fname, lnum, line); - else { - line += 8; - if (STRLEN(line) > 16) - smsg(_("Too many regions in %s line %d: %s"), - fname, lnum, line); - else { - spin->si_region_count = (int)STRLEN(line) / 2; - STRCPY(spin->si_region_name, line); - - // Adjust the mask for a word valid in all regions. - spin->si_region = (1 << spin->si_region_count) - 1; - } - } - continue; - } - - smsg(_("/ line ignored in %s line %d: %s"), - fname, lnum, line - 1); - continue; - } - - flags = 0; - regionmask = spin->si_region; - - // Check for flags and region after a slash. - p = vim_strchr(line, '/'); - if (p != NULL) { - *p++ = NUL; - while (*p != NUL) { - if (*p == '=') // keep-case word - flags |= WF_KEEPCAP | WF_FIXCAP; - else if (*p == '!') // Bad, bad, wicked word. - flags |= WF_BANNED; - else if (*p == '?') // Rare word. - flags |= WF_RARE; - else if (ascii_isdigit(*p)) { // region number(s) - if ((flags & WF_REGION) == 0) // first one - regionmask = 0; - flags |= WF_REGION; - - l = *p - '0'; - if (l > spin->si_region_count) { - smsg(_("Invalid region nr in %s line %d: %s"), - fname, lnum, p); - break; - } - regionmask |= 1 << (l - 1); - } else { - smsg(_("Unrecognized flags in %s line %d: %s"), - fname, lnum, p); - break; - } - ++p; - } - } - - // Skip non-ASCII words when "spin->si_ascii" is true. - if (spin->si_ascii && has_non_ascii(line)) { - ++non_ascii; - continue; - } - - // Normal word: store it. - if (store_word(spin, line, flags, regionmask, NULL, false) == FAIL) { - retval = FAIL; - break; - } - did_word = true; - } - - xfree(pc); - fclose(fd); - - if (spin->si_ascii && non_ascii > 0) { - vim_snprintf((char *)IObuff, IOSIZE, - _("Ignored %d words with non-ASCII characters"), non_ascii); - spell_message(spin, IObuff); - } - - return retval; -} - -/// Get part of an sblock_T, "len" bytes long. -/// This avoids calling free() for every little struct we use (and keeping -/// track of them). -/// The memory is cleared to all zeros. -/// -/// @param len Length needed (<= SBLOCKSIZE). -/// @param align Align for pointer. -/// @return Pointer into block data. -static void *getroom(spellinfo_T *spin, size_t len, bool align) - FUNC_ATTR_NONNULL_RET -{ - char_u *p; - sblock_T *bl = spin->si_blocks; - - assert(len <= SBLOCKSIZE); - - if (align && bl != NULL) - // Round size up for alignment. On some systems structures need to be - // aligned to the size of a pointer (e.g., SPARC). - bl->sb_used = (bl->sb_used + sizeof(char *) - 1) - & ~(sizeof(char *) - 1); - - if (bl == NULL || bl->sb_used + len > SBLOCKSIZE) { - // Allocate a block of memory. It is not freed until much later. - bl = xcalloc(1, (sizeof(sblock_T) + SBLOCKSIZE)); - bl->sb_next = spin->si_blocks; - spin->si_blocks = bl; - bl->sb_used = 0; - ++spin->si_blocks_cnt; - } - - p = bl->sb_data + bl->sb_used; - bl->sb_used += (int)len; - - return p; -} - -// Make a copy of a string into memory allocated with getroom(). -// Returns NULL when out of memory. -static char_u *getroom_save(spellinfo_T *spin, char_u *s) -{ - char_u *sc; - - sc = (char_u *)getroom(spin, STRLEN(s) + 1, false); - if (sc != NULL) - STRCPY(sc, s); - return sc; -} - - -// Free the list of allocated sblock_T. -static void free_blocks(sblock_T *bl) -{ - sblock_T *next; - - while (bl != NULL) { - next = bl->sb_next; - xfree(bl); - bl = next; - } -} - -// Allocate the root of a word tree. -// Returns NULL when out of memory. -static wordnode_T *wordtree_alloc(spellinfo_T *spin) -{ - return (wordnode_T *)getroom(spin, sizeof(wordnode_T), true); -} - -// Store a word in the tree(s). -// Always store it in the case-folded tree. For a keep-case word this is -// useful when the word can also be used with all caps (no WF_FIXCAP flag) and -// used to find suggestions. -// For a keep-case word also store it in the keep-case tree. -// When "pfxlist" is not NULL store the word for each postponed prefix ID and -// compound flag. -static int -store_word ( - spellinfo_T *spin, - char_u *word, - int flags, // extra flags, WF_BANNED - int region, // supported region(s) - char_u *pfxlist, // list of prefix IDs or NULL - bool need_affix // only store word with affix ID -) -{ - int len = (int)STRLEN(word); - int ct = captype(word, word + len); - char_u foldword[MAXWLEN]; - int res = OK; - char_u *p; - - (void)spell_casefold(word, len, foldword, MAXWLEN); - for (p = pfxlist; res == OK; ++p) { - if (!need_affix || (p != NULL && *p != NUL)) - res = tree_add_word(spin, foldword, spin->si_foldroot, ct | flags, - region, p == NULL ? 0 : *p); - if (p == NULL || *p == NUL) - break; - } - ++spin->si_foldwcount; - - if (res == OK && (ct == WF_KEEPCAP || (flags & WF_KEEPCAP))) { - for (p = pfxlist; res == OK; ++p) { - if (!need_affix || (p != NULL && *p != NUL)) - res = tree_add_word(spin, word, spin->si_keeproot, flags, - region, p == NULL ? 0 : *p); - if (p == NULL || *p == NUL) - break; - } - ++spin->si_keepwcount; - } - return res; -} - -// Add word "word" to a word tree at "root". -// When "flags" < 0 we are adding to the prefix tree where "flags" is used for -// "rare" and "region" is the condition nr. -// Returns FAIL when out of memory. -static int tree_add_word(spellinfo_T *spin, char_u *word, wordnode_T *root, int flags, int region, int affixID) -{ - wordnode_T *node = root; - wordnode_T *np; - wordnode_T *copyp, **copyprev; - wordnode_T **prev = NULL; - int i; - - // Add each byte of the word to the tree, including the NUL at the end. - for (i = 0;; ++i) { - // When there is more than one reference to this node we need to make - // a copy, so that we can modify it. Copy the whole list of siblings - // (we don't optimize for a partly shared list of siblings). - if (node != NULL && node->wn_refs > 1) { - --node->wn_refs; - copyprev = prev; - for (copyp = node; copyp != NULL; copyp = copyp->wn_sibling) { - // Allocate a new node and copy the info. - np = get_wordnode(spin); - if (np == NULL) - return FAIL; - np->wn_child = copyp->wn_child; - if (np->wn_child != NULL) - ++np->wn_child->wn_refs; // child gets extra ref - np->wn_byte = copyp->wn_byte; - if (np->wn_byte == NUL) { - np->wn_flags = copyp->wn_flags; - np->wn_region = copyp->wn_region; - np->wn_affixID = copyp->wn_affixID; - } - - // Link the new node in the list, there will be one ref. - np->wn_refs = 1; - if (copyprev != NULL) - *copyprev = np; - copyprev = &np->wn_sibling; - - // Let "node" point to the head of the copied list. - if (copyp == node) - node = np; - } - } - - // Look for the sibling that has the same character. They are sorted - // on byte value, thus stop searching when a sibling is found with a - // higher byte value. For zero bytes (end of word) the sorting is - // done on flags and then on affixID. - while (node != NULL - && (node->wn_byte < word[i] - || (node->wn_byte == NUL - && (flags < 0 - ? node->wn_affixID < (unsigned)affixID - : (node->wn_flags < (unsigned)(flags & WN_MASK) - || (node->wn_flags == (flags & WN_MASK) - && (spin->si_sugtree - ? (node->wn_region & 0xffff) < region - : node->wn_affixID - < (unsigned)affixID))))))) { - prev = &node->wn_sibling; - node = *prev; - } - if (node == NULL - || node->wn_byte != word[i] - || (word[i] == NUL - && (flags < 0 - || spin->si_sugtree - || node->wn_flags != (flags & WN_MASK) - || node->wn_affixID != affixID))) { - // Allocate a new node. - np = get_wordnode(spin); - if (np == NULL) - return FAIL; - np->wn_byte = word[i]; - - // If "node" is NULL this is a new child or the end of the sibling - // list: ref count is one. Otherwise use ref count of sibling and - // make ref count of sibling one (matters when inserting in front - // of the list of siblings). - if (node == NULL) - np->wn_refs = 1; - else { - np->wn_refs = node->wn_refs; - node->wn_refs = 1; - } - if (prev != NULL) - *prev = np; - np->wn_sibling = node; - node = np; - } - - if (word[i] == NUL) { - node->wn_flags = flags; - node->wn_region |= region; - node->wn_affixID = affixID; - break; - } - prev = &node->wn_child; - node = *prev; - } -#ifdef SPELL_PRINTTREE - smsg((char_u *)"Added \"%s\"", word); - spell_print_tree(root->wn_sibling); -#endif - - // count nr of words added since last message - ++spin->si_msg_count; - - if (spin->si_compress_cnt > 1) { - if (--spin->si_compress_cnt == 1) - // Did enough words to lower the block count limit. - spin->si_blocks_cnt += compress_inc; - } - - // When we have allocated lots of memory we need to compress the word tree - // to free up some room. But compression is slow, and we might actually - // need that room, thus only compress in the following situations: - // 1. When not compressed before (si_compress_cnt == 0): when using - // "compress_start" blocks. - // 2. When compressed before and used "compress_inc" blocks before - // adding "compress_added" words (si_compress_cnt > 1). - // 3. When compressed before, added "compress_added" words - // (si_compress_cnt == 1) and the number of free nodes drops below the - // maximum word length. -#ifndef SPELL_COMPRESS_ALLWAYS - if (spin->si_compress_cnt == 1 // NOLINT(readability/braces) - ? spin->si_free_count < MAXWLEN - : spin->si_blocks_cnt >= compress_start) -#endif - { - // Decrement the block counter. The effect is that we compress again - // when the freed up room has been used and another "compress_inc" - // blocks have been allocated. Unless "compress_added" words have - // been added, then the limit is put back again. - spin->si_blocks_cnt -= compress_inc; - spin->si_compress_cnt = compress_added; - - if (spin->si_verbose) { - msg_start(); - msg_puts((char_u *)_(msg_compressing)); - msg_clr_eos(); - msg_didout = FALSE; - msg_col = 0; - ui_flush(); - } - - // Compress both trees. Either they both have many nodes, which makes - // compression useful, or one of them is small, which means - // compression goes fast. But when filling the soundfold word tree - // there is no keep-case tree. - wordtree_compress(spin, spin->si_foldroot); - if (affixID >= 0) - wordtree_compress(spin, spin->si_keeproot); - } - - return OK; -} - -// Check the 'mkspellmem' option. Return FAIL if it's wrong. -// Sets "sps_flags". -int spell_check_msm(void) -{ - char_u *p = p_msm; - long start = 0; - long incr = 0; - long added = 0; - - if (!ascii_isdigit(*p)) - return FAIL; - // block count = (value * 1024) / SBLOCKSIZE (but avoid overflow) - start = (getdigits_long(&p) * 10) / (SBLOCKSIZE / 102); - if (*p != ',') - return FAIL; - ++p; - if (!ascii_isdigit(*p)) - return FAIL; - incr = (getdigits_long(&p) * 102) / (SBLOCKSIZE / 10); - if (*p != ',') - return FAIL; - ++p; - if (!ascii_isdigit(*p)) - return FAIL; - added = getdigits_long(&p) * 1024; - if (*p != NUL) - return FAIL; - - if (start == 0 || incr == 0 || added == 0 || incr > start) - return FAIL; - - compress_start = start; - compress_inc = incr; - compress_added = added; - return OK; -} - -// Get a wordnode_T, either from the list of previously freed nodes or -// allocate a new one. -// Returns NULL when out of memory. -static wordnode_T *get_wordnode(spellinfo_T *spin) -{ - wordnode_T *n; - - if (spin->si_first_free == NULL) - n = (wordnode_T *)getroom(spin, sizeof(wordnode_T), true); - else { - n = spin->si_first_free; - spin->si_first_free = n->wn_child; - memset(n, 0, sizeof(wordnode_T)); - --spin->si_free_count; - } -#ifdef SPELL_PRINTTREE - if (n != NULL) - n->wn_nr = ++spin->si_wordnode_nr; -#endif - return n; -} - -// Decrement the reference count on a node (which is the head of a list of -// siblings). If the reference count becomes zero free the node and its -// siblings. -// Returns the number of nodes actually freed. -static int deref_wordnode(spellinfo_T *spin, wordnode_T *node) -{ - wordnode_T *np; - int cnt = 0; - - if (--node->wn_refs == 0) { - for (np = node; np != NULL; np = np->wn_sibling) { - if (np->wn_child != NULL) - cnt += deref_wordnode(spin, np->wn_child); - free_wordnode(spin, np); - ++cnt; - } - ++cnt; // length field - } - return cnt; -} - -// Free a wordnode_T for re-use later. -// Only the "wn_child" field becomes invalid. -static void free_wordnode(spellinfo_T *spin, wordnode_T *n) -{ - n->wn_child = spin->si_first_free; - spin->si_first_free = n; - ++spin->si_free_count; -} - -// Compress a tree: find tails that are identical and can be shared. -static void wordtree_compress(spellinfo_T *spin, wordnode_T *root) -{ - hashtab_T ht; - int n; - int tot = 0; - int perc; - - // Skip the root itself, it's not actually used. The first sibling is the - // start of the tree. - if (root->wn_sibling != NULL) { - hash_init(&ht); - n = node_compress(spin, root->wn_sibling, &ht, &tot); - -#ifndef SPELL_PRINTTREE - if (spin->si_verbose || p_verbose > 2) -#endif - { - if (tot > 1000000) - perc = (tot - n) / (tot / 100); - else if (tot == 0) - perc = 0; - else - perc = (tot - n) * 100 / tot; - vim_snprintf((char *)IObuff, IOSIZE, - _("Compressed %d of %d nodes; %d (%d%%) remaining"), - n, tot, tot - n, perc); - spell_message(spin, IObuff); - } -#ifdef SPELL_PRINTTREE - spell_print_tree(root->wn_sibling); -#endif - hash_clear(&ht); - } -} - -// Compress a node, its siblings and its children, depth first. -// Returns the number of compressed nodes. -static int -node_compress ( - spellinfo_T *spin, - wordnode_T *node, - hashtab_T *ht, - int *tot // total count of nodes before compressing, - // incremented while going through the tree -) -{ - wordnode_T *np; - wordnode_T *tp; - wordnode_T *child; - hash_T hash; - hashitem_T *hi; - int len = 0; - unsigned nr, n; - int compressed = 0; - - // Go through the list of siblings. Compress each child and then try - // finding an identical child to replace it. - // Note that with "child" we mean not just the node that is pointed to, - // but the whole list of siblings of which the child node is the first. - for (np = node; np != NULL && !got_int; np = np->wn_sibling) { - ++len; - if ((child = np->wn_child) != NULL) { - // Compress the child first. This fills hashkey. - compressed += node_compress(spin, child, ht, tot); - - // Try to find an identical child. - hash = hash_hash(child->wn_u1.hashkey); - hi = hash_lookup(ht, child->wn_u1.hashkey, hash); - if (!HASHITEM_EMPTY(hi)) { - // There are children we encountered before with a hash value - // identical to the current child. Now check if there is one - // that is really identical. - for (tp = HI2WN(hi); tp != NULL; tp = tp->wn_u2.next) - if (node_equal(child, tp)) { - // Found one! Now use that child in place of the - // current one. This means the current child and all - // its siblings is unlinked from the tree. - ++tp->wn_refs; - compressed += deref_wordnode(spin, child); - np->wn_child = tp; - break; - } - if (tp == NULL) { - // No other child with this hash value equals the child of - // the node, add it to the linked list after the first - // item. - tp = HI2WN(hi); - child->wn_u2.next = tp->wn_u2.next; - tp->wn_u2.next = child; - } - } else - // No other child has this hash value, add it to the - // hashtable. - hash_add_item(ht, hi, child->wn_u1.hashkey, hash); - } - } - *tot += len + 1; // add one for the node that stores the length - - // Make a hash key for the node and its siblings, so that we can quickly - // find a lookalike node. This must be done after compressing the sibling - // list, otherwise the hash key would become invalid by the compression. - node->wn_u1.hashkey[0] = len; - nr = 0; - for (np = node; np != NULL; np = np->wn_sibling) { - if (np->wn_byte == NUL) - // end node: use wn_flags, wn_region and wn_affixID - n = np->wn_flags + (np->wn_region << 8) + (np->wn_affixID << 16); - else - // byte node: use the byte value and the child pointer - n = (unsigned)(np->wn_byte + ((uintptr_t)np->wn_child << 8)); - nr = nr * 101 + n; - } - - // Avoid NUL bytes, it terminates the hash key. - n = nr & 0xff; - node->wn_u1.hashkey[1] = n == 0 ? 1 : n; - n = (nr >> 8) & 0xff; - node->wn_u1.hashkey[2] = n == 0 ? 1 : n; - n = (nr >> 16) & 0xff; - node->wn_u1.hashkey[3] = n == 0 ? 1 : n; - n = (nr >> 24) & 0xff; - node->wn_u1.hashkey[4] = n == 0 ? 1 : n; - node->wn_u1.hashkey[5] = NUL; - - // Check for CTRL-C pressed now and then. - fast_breakcheck(); - - return compressed; -} - -// Returns true when two nodes have identical siblings and children. -static bool node_equal(wordnode_T *n1, wordnode_T *n2) -{ - wordnode_T *p1; - wordnode_T *p2; - - for (p1 = n1, p2 = n2; p1 != NULL && p2 != NULL; - p1 = p1->wn_sibling, p2 = p2->wn_sibling) - if (p1->wn_byte != p2->wn_byte - || (p1->wn_byte == NUL - ? (p1->wn_flags != p2->wn_flags - || p1->wn_region != p2->wn_region - || p1->wn_affixID != p2->wn_affixID) - : (p1->wn_child != p2->wn_child))) - break; - - return p1 == NULL && p2 == NULL; -} - - -// Function given to qsort() to sort the REP items on "from" string. -static int rep_compare(const void *s1, const void *s2) -{ - fromto_T *p1 = (fromto_T *)s1; - fromto_T *p2 = (fromto_T *)s2; - - return STRCMP(p1->ft_from, p2->ft_from); -} - -// Write the Vim .spl file "fname". -// Return OK/FAIL. -static int write_vim_spell(spellinfo_T *spin, char_u *fname) -{ - int retval = OK; - int regionmask; - - FILE *fd = mch_fopen((char *)fname, "w"); - if (fd == NULL) { - EMSG2(_(e_notopen), fname); - return FAIL; - } - - // <HEADER>: <fileID> <versionnr> - // <fileID> - size_t fwv = fwrite(VIMSPELLMAGIC, VIMSPELLMAGICL, 1, fd); - if (fwv != (size_t)1) - // Catch first write error, don't try writing more. - goto theend; - - putc(VIMSPELLVERSION, fd); // <versionnr> - - // <SECTIONS>: <section> ... <sectionend> - - // SN_INFO: <infotext> - if (spin->si_info != NULL) { - putc(SN_INFO, fd); // <sectionID> - putc(0, fd); // <sectionflags> - size_t i = STRLEN(spin->si_info); - put_bytes(fd, i, 4); // <sectionlen> - fwv &= fwrite(spin->si_info, i, 1, fd); // <infotext> - } - - // SN_REGION: <regionname> ... - // Write the region names only if there is more than one. - if (spin->si_region_count > 1) { - putc(SN_REGION, fd); // <sectionID> - putc(SNF_REQUIRED, fd); // <sectionflags> - size_t l = (size_t)spin->si_region_count * 2; - put_bytes(fd, l, 4); // <sectionlen> - fwv &= fwrite(spin->si_region_name, l, 1, fd); - // <regionname> ... - regionmask = (1 << spin->si_region_count) - 1; - } else - regionmask = 0; - - // SN_CHARFLAGS: <charflagslen> <charflags> <folcharslen> <folchars> - // - // The table with character flags and the table for case folding. - // This makes sure the same characters are recognized as word characters - // when generating an when using a spell file. - // Skip this for ASCII, the table may conflict with the one used for - // 'encoding'. - // Also skip this for an .add.spl file, the main spell file must contain - // the table (avoids that it conflicts). File is shorter too. - if (!spin->si_ascii && !spin->si_add) { - char_u folchars[128 * 8]; - int flags; - - putc(SN_CHARFLAGS, fd); // <sectionID> - putc(SNF_REQUIRED, fd); // <sectionflags> - - // Form the <folchars> string first, we need to know its length. - size_t l = 0; - for (size_t i = 128; i < 256; ++i) { - if (has_mbyte) - l += (size_t)mb_char2bytes(spelltab.st_fold[i], folchars + l); - else - folchars[l++] = spelltab.st_fold[i]; - } - put_bytes(fd, 1 + 128 + 2 + l, 4); // <sectionlen> - - fputc(128, fd); // <charflagslen> - for (size_t i = 128; i < 256; ++i) { - flags = 0; - if (spelltab.st_isw[i]) - flags |= CF_WORD; - if (spelltab.st_isu[i]) - flags |= CF_UPPER; - fputc(flags, fd); // <charflags> - } - - put_bytes(fd, l, 2); // <folcharslen> - fwv &= fwrite(folchars, l, 1, fd); // <folchars> - } - - // SN_MIDWORD: <midword> - if (spin->si_midword != NULL) { - putc(SN_MIDWORD, fd); // <sectionID> - putc(SNF_REQUIRED, fd); // <sectionflags> - - size_t i = STRLEN(spin->si_midword); - put_bytes(fd, i, 4); // <sectionlen> - fwv &= fwrite(spin->si_midword, i, 1, fd); - // <midword> - } - - // SN_PREFCOND: <prefcondcnt> <prefcond> ... - if (!GA_EMPTY(&spin->si_prefcond)) { - putc(SN_PREFCOND, fd); // <sectionID> - putc(SNF_REQUIRED, fd); // <sectionflags> - - size_t l = (size_t)write_spell_prefcond(NULL, &spin->si_prefcond); - put_bytes(fd, l, 4); // <sectionlen> - - write_spell_prefcond(fd, &spin->si_prefcond); - } - - // SN_REP: <repcount> <rep> ... - // SN_SAL: <salflags> <salcount> <sal> ... - // SN_REPSAL: <repcount> <rep> ... - - // round 1: SN_REP section - // round 2: SN_SAL section (unless SN_SOFO is used) - // round 3: SN_REPSAL section - for (unsigned int round = 1; round <= 3; ++round) { - garray_T *gap; - if (round == 1) - gap = &spin->si_rep; - else if (round == 2) { - // Don't write SN_SAL when using a SN_SOFO section - if (spin->si_sofofr != NULL && spin->si_sofoto != NULL) - continue; - gap = &spin->si_sal; - } else - gap = &spin->si_repsal; - - // Don't write the section if there are no items. - if (GA_EMPTY(gap)) - continue; - - // Sort the REP/REPSAL items. - if (round != 2) - qsort(gap->ga_data, (size_t)gap->ga_len, - sizeof(fromto_T), rep_compare); - - int i = round == 1 ? SN_REP : (round == 2 ? SN_SAL : SN_REPSAL); - putc(i, fd); // <sectionID> - - // This is for making suggestions, section is not required. - putc(0, fd); // <sectionflags> - - // Compute the length of what follows. - size_t l = 2; // count <repcount> or <salcount> - assert(gap->ga_len >= 0); - for (size_t i = 0; i < (size_t)gap->ga_len; ++i) { - fromto_T *ftp = &((fromto_T *)gap->ga_data)[i]; - l += 1 + STRLEN(ftp->ft_from); // count <*fromlen> and <*from> - l += 1 + STRLEN(ftp->ft_to); // count <*tolen> and <*to> - } - if (round == 2) - ++l; // count <salflags> - put_bytes(fd, l, 4); // <sectionlen> - - if (round == 2) { - int i = 0; - if (spin->si_followup) - i |= SAL_F0LLOWUP; - if (spin->si_collapse) - i |= SAL_COLLAPSE; - if (spin->si_rem_accents) - i |= SAL_REM_ACCENTS; - putc(i, fd); // <salflags> - } - - put_bytes(fd, (uintmax_t)gap->ga_len, 2); // <repcount> or <salcount> - for (size_t i = 0; i < (size_t)gap->ga_len; ++i) { - // <rep> : <repfromlen> <repfrom> <reptolen> <repto> - // <sal> : <salfromlen> <salfrom> <saltolen> <salto> - fromto_T *ftp = &((fromto_T *)gap->ga_data)[i]; - for (unsigned int rr = 1; rr <= 2; ++rr) { - char_u *p = rr == 1 ? ftp->ft_from : ftp->ft_to; - l = STRLEN(p); - assert(l < INT_MAX); - putc((int)l, fd); - if (l > 0) - fwv &= fwrite(p, l, 1, fd); - } - } - - } - - // SN_SOFO: <sofofromlen> <sofofrom> <sofotolen> <sofoto> - // This is for making suggestions, section is not required. - if (spin->si_sofofr != NULL && spin->si_sofoto != NULL) { - putc(SN_SOFO, fd); // <sectionID> - putc(0, fd); // <sectionflags> - - size_t l = STRLEN(spin->si_sofofr); - put_bytes(fd, l + STRLEN(spin->si_sofoto) + 4, 4); // <sectionlen> - - put_bytes(fd, l, 2); // <sofofromlen> - fwv &= fwrite(spin->si_sofofr, l, 1, fd); // <sofofrom> - - l = STRLEN(spin->si_sofoto); - put_bytes(fd, l, 2); // <sofotolen> - fwv &= fwrite(spin->si_sofoto, l, 1, fd); // <sofoto> - } - - // SN_WORDS: <word> ... - // This is for making suggestions, section is not required. - if (spin->si_commonwords.ht_used > 0) { - putc(SN_WORDS, fd); // <sectionID> - putc(0, fd); // <sectionflags> - - // round 1: count the bytes - // round 2: write the bytes - for (unsigned int round = 1; round <= 2; ++round) { - size_t todo; - size_t len = 0; - hashitem_T *hi; - - todo = spin->si_commonwords.ht_used; - for (hi = spin->si_commonwords.ht_array; todo > 0; ++hi) - if (!HASHITEM_EMPTY(hi)) { - size_t l = STRLEN(hi->hi_key) + 1; - len += l; - if (round == 2) // <word> - fwv &= fwrite(hi->hi_key, l, 1, fd); - --todo; - } - if (round == 1) - put_bytes(fd, len, 4); // <sectionlen> - } - } - - // SN_MAP: <mapstr> - // This is for making suggestions, section is not required. - if (!GA_EMPTY(&spin->si_map)) { - putc(SN_MAP, fd); // <sectionID> - putc(0, fd); // <sectionflags> - size_t l = (size_t)spin->si_map.ga_len; - put_bytes(fd, l, 4); // <sectionlen> - fwv &= fwrite(spin->si_map.ga_data, l, 1, fd); // <mapstr> - } - - // SN_SUGFILE: <timestamp> - // This is used to notify that a .sug file may be available and at the - // same time allows for checking that a .sug file that is found matches - // with this .spl file. That's because the word numbers must be exactly - // right. - if (!spin->si_nosugfile - && (!GA_EMPTY(&spin->si_sal) - || (spin->si_sofofr != NULL && spin->si_sofoto != NULL))) { - putc(SN_SUGFILE, fd); // <sectionID> - putc(0, fd); // <sectionflags> - put_bytes(fd, 8, 4); // <sectionlen> - - // Set si_sugtime and write it to the file. - spin->si_sugtime = time(NULL); - put_time(fd, spin->si_sugtime); // <timestamp> - } - - // SN_NOSPLITSUGS: nothing - // This is used to notify that no suggestions with word splits are to be - // made. - if (spin->si_nosplitsugs) { - putc(SN_NOSPLITSUGS, fd); // <sectionID> - putc(0, fd); // <sectionflags> - put_bytes(fd, 0, 4); // <sectionlen> - } - - // SN_NOCOMPUNDSUGS: nothing - // This is used to notify that no suggestions with compounds are to be - // made. - if (spin->si_nocompoundsugs) { - putc(SN_NOCOMPOUNDSUGS, fd); // <sectionID> - putc(0, fd); // <sectionflags> - put_bytes(fd, 0, 4); // <sectionlen> - } - - // SN_COMPOUND: compound info. - // We don't mark it required, when not supported all compound words will - // be bad words. - if (spin->si_compflags != NULL) { - putc(SN_COMPOUND, fd); // <sectionID> - putc(0, fd); // <sectionflags> - - size_t l = STRLEN(spin->si_compflags); - assert(spin->si_comppat.ga_len >= 0); - for (size_t i = 0; i < (size_t)spin->si_comppat.ga_len; ++i) { - l += STRLEN(((char_u **)(spin->si_comppat.ga_data))[i]) + 1; - } - put_bytes(fd, l + 7, 4); // <sectionlen> - - putc(spin->si_compmax, fd); // <compmax> - putc(spin->si_compminlen, fd); // <compminlen> - putc(spin->si_compsylmax, fd); // <compsylmax> - putc(0, fd); // for Vim 7.0b compatibility - putc(spin->si_compoptions, fd); // <compoptions> - put_bytes(fd, (uintmax_t)spin->si_comppat.ga_len, 2); // <comppatcount> - for (size_t i = 0; i < (size_t)spin->si_comppat.ga_len; ++i) { - char_u *p = ((char_u **)(spin->si_comppat.ga_data))[i]; - assert(STRLEN(p) < INT_MAX); - putc((int)STRLEN(p), fd); // <comppatlen> - fwv &= fwrite(p, STRLEN(p), 1, fd); // <comppattext> - } - // <compflags> - fwv &= fwrite(spin->si_compflags, STRLEN(spin->si_compflags), 1, fd); - } - - // SN_NOBREAK: NOBREAK flag - if (spin->si_nobreak) { - putc(SN_NOBREAK, fd); // <sectionID> - putc(0, fd); // <sectionflags> - - // It's empty, the presence of the section flags the feature. - put_bytes(fd, 0, 4); // <sectionlen> - } - - // SN_SYLLABLE: syllable info. - // We don't mark it required, when not supported syllables will not be - // counted. - if (spin->si_syllable != NULL) { - putc(SN_SYLLABLE, fd); // <sectionID> - putc(0, fd); // <sectionflags> - - size_t l = STRLEN(spin->si_syllable); - put_bytes(fd, l, 4); // <sectionlen> - fwv &= fwrite(spin->si_syllable, l, 1, fd); // <syllable> - } - - // end of <SECTIONS> - putc(SN_END, fd); // <sectionend> - - - // <LWORDTREE> <KWORDTREE> <PREFIXTREE> - spin->si_memtot = 0; - for (unsigned int round = 1; round <= 3; ++round) { - wordnode_T *tree; - if (round == 1) - tree = spin->si_foldroot->wn_sibling; - else if (round == 2) - tree = spin->si_keeproot->wn_sibling; - else - tree = spin->si_prefroot->wn_sibling; - - // Clear the index and wnode fields in the tree. - clear_node(tree); - - // Count the number of nodes. Needed to be able to allocate the - // memory when reading the nodes. Also fills in index for shared - // nodes. - size_t nodecount = (size_t)put_node(NULL, tree, 0, regionmask, round == 3); - - // number of nodes in 4 bytes - put_bytes(fd, nodecount, 4); // <nodecount> - assert(nodecount + nodecount * sizeof(int) < INT_MAX); - spin->si_memtot += (int)(nodecount + nodecount * sizeof(int)); - - // Write the nodes. - (void)put_node(fd, tree, 0, regionmask, round == 3); - } - - // Write another byte to check for errors (file system full). - if (putc(0, fd) == EOF) - retval = FAIL; -theend: - if (fclose(fd) == EOF) - retval = FAIL; - - if (fwv != (size_t)1) - retval = FAIL; - if (retval == FAIL) - EMSG(_(e_write)); - - return retval; -} - -// Clear the index and wnode fields of "node", it siblings and its -// children. This is needed because they are a union with other items to save -// space. -static void clear_node(wordnode_T *node) -{ - wordnode_T *np; - - if (node != NULL) - for (np = node; np != NULL; np = np->wn_sibling) { - np->wn_u1.index = 0; - np->wn_u2.wnode = NULL; - - if (np->wn_byte != NUL) - clear_node(np->wn_child); - } -} - - -// Dump a word tree at node "node". -// -// This first writes the list of possible bytes (siblings). Then for each -// byte recursively write the children. -// -// NOTE: The code here must match the code in read_tree_node(), since -// assumptions are made about the indexes (so that we don't have to write them -// in the file). -// -// Returns the number of nodes used. -static int -put_node ( - FILE *fd, // NULL when only counting - wordnode_T *node, - int idx, - int regionmask, - bool prefixtree // true for PREFIXTREE -) -{ - // If "node" is zero the tree is empty. - if (node == NULL) - return 0; - - // Store the index where this node is written. - node->wn_u1.index = idx; - - // Count the number of siblings. - int siblingcount = 0; - for (wordnode_T *np = node; np != NULL; np = np->wn_sibling) - ++siblingcount; - - // Write the sibling count. - if (fd != NULL) - putc(siblingcount, fd); // <siblingcount> - - // Write each sibling byte and optionally extra info. - for (wordnode_T *np = node; np != NULL; np = np->wn_sibling) { - if (np->wn_byte == 0) { - if (fd != NULL) { - // For a NUL byte (end of word) write the flags etc. - if (prefixtree) { - // In PREFIXTREE write the required affixID and the - // associated condition nr (stored in wn_region). The - // byte value is misused to store the "rare" and "not - // combining" flags - if (np->wn_flags == (uint16_t)PFX_FLAGS) - putc(BY_NOFLAGS, fd); // <byte> - else { - putc(BY_FLAGS, fd); // <byte> - putc(np->wn_flags, fd); // <pflags> - } - putc(np->wn_affixID, fd); // <affixID> - put_bytes(fd, (uintmax_t)np->wn_region, 2); // <prefcondnr> - } else { - // For word trees we write the flag/region items. - int flags = np->wn_flags; - if (regionmask != 0 && np->wn_region != regionmask) - flags |= WF_REGION; - if (np->wn_affixID != 0) - flags |= WF_AFX; - if (flags == 0) { - // word without flags or region - putc(BY_NOFLAGS, fd); // <byte> - } else { - if (np->wn_flags >= 0x100) { - putc(BY_FLAGS2, fd); // <byte> - putc(flags, fd); // <flags> - putc((int)((unsigned)flags >> 8), fd); // <flags2> - } else { - putc(BY_FLAGS, fd); // <byte> - putc(flags, fd); // <flags> - } - if (flags & WF_REGION) - putc(np->wn_region, fd); // <region> - if (flags & WF_AFX) - putc(np->wn_affixID, fd); // <affixID> - } - } - } - } else { - if (np->wn_child->wn_u1.index != 0 - && np->wn_child->wn_u2.wnode != node) { - // The child is written elsewhere, write the reference. - if (fd != NULL) { - putc(BY_INDEX, fd); // <byte> - put_bytes(fd, (uintmax_t)np->wn_child->wn_u1.index, 3); // <nodeidx> - } - } else if (np->wn_child->wn_u2.wnode == NULL) - // We will write the child below and give it an index. - np->wn_child->wn_u2.wnode = node; - - if (fd != NULL) - if (putc(np->wn_byte, fd) == EOF) { // <byte> or <xbyte> - EMSG(_(e_write)); - return 0; - } - } - } - - // Space used in the array when reading: one for each sibling and one for - // the count. - int newindex = idx + siblingcount + 1; - - // Recursively dump the children of each sibling. - for (wordnode_T *np = node; np != NULL; np = np->wn_sibling) - if (np->wn_byte != 0 && np->wn_child->wn_u2.wnode == node) - newindex = put_node(fd, np->wn_child, newindex, regionmask, - prefixtree); - - return newindex; -} - - -// ":mkspell [-ascii] outfile infile ..." -// ":mkspell [-ascii] addfile" -void ex_mkspell(exarg_T *eap) -{ - int fcount; - char_u **fnames; - char_u *arg = eap->arg; - bool ascii = false; - - if (STRNCMP(arg, "-ascii", 6) == 0) { - ascii = true; - arg = skipwhite(arg + 6); - } - - // Expand all the remaining arguments (e.g., $VIMRUNTIME). - if (get_arglist_exp(arg, &fcount, &fnames, false) == OK) { - mkspell(fcount, fnames, ascii, eap->forceit, false); - FreeWild(fcount, fnames); - } -} - -// Create the .sug file. -// Uses the soundfold info in "spin". -// Writes the file with the name "wfname", with ".spl" changed to ".sug". -static void spell_make_sugfile(spellinfo_T *spin, char_u *wfname) -{ - char_u *fname = NULL; - int len; - slang_T *slang; - bool free_slang = false; - - // Read back the .spl file that was written. This fills the required - // info for soundfolding. This also uses less memory than the - // pointer-linked version of the trie. And it avoids having two versions - // of the code for the soundfolding stuff. - // It might have been done already by spell_reload_one(). - for (slang = first_lang; slang != NULL; slang = slang->sl_next) - if (path_full_compare(wfname, slang->sl_fname, FALSE) == kEqualFiles) - break; - if (slang == NULL) { - spell_message(spin, (char_u *)_("Reading back spell file...")); - slang = spell_load_file(wfname, NULL, NULL, false); - if (slang == NULL) - return; - free_slang = true; - } - - // Clear the info in "spin" that is used. - spin->si_blocks = NULL; - spin->si_blocks_cnt = 0; - spin->si_compress_cnt = 0; // will stay at 0 all the time - spin->si_free_count = 0; - spin->si_first_free = NULL; - spin->si_foldwcount = 0; - - // Go through the trie of good words, soundfold each word and add it to - // the soundfold trie. - spell_message(spin, (char_u *)_("Performing soundfolding...")); - if (sug_filltree(spin, slang) == FAIL) - goto theend; - - // Create the table which links each soundfold word with a list of the - // good words it may come from. Creates buffer "spin->si_spellbuf". - // This also removes the wordnr from the NUL byte entries to make - // compression possible. - if (sug_maketable(spin) == FAIL) - goto theend; - - smsg(_("Number of words after soundfolding: %" PRId64), - (int64_t)spin->si_spellbuf->b_ml.ml_line_count); - - // Compress the soundfold trie. - spell_message(spin, (char_u *)_(msg_compressing)); - wordtree_compress(spin, spin->si_foldroot); - - // Write the .sug file. - // Make the file name by changing ".spl" to ".sug". - fname = xmalloc(MAXPATHL); - STRLCPY(fname, wfname, MAXPATHL); - len = (int)STRLEN(fname); - fname[len - 2] = 'u'; - fname[len - 1] = 'g'; - sug_write(spin, fname); - -theend: - xfree(fname); - if (free_slang) - slang_free(slang); - free_blocks(spin->si_blocks); - close_spellbuf(spin->si_spellbuf); -} - -// Build the soundfold trie for language "slang". -static int sug_filltree(spellinfo_T *spin, slang_T *slang) -{ - char_u *byts; - idx_T *idxs; - int depth; - idx_T arridx[MAXWLEN]; - int curi[MAXWLEN]; - char_u tword[MAXWLEN]; - char_u tsalword[MAXWLEN]; - int c; - idx_T n; - unsigned words_done = 0; - int wordcount[MAXWLEN]; - - // We use si_foldroot for the soundfolded trie. - spin->si_foldroot = wordtree_alloc(spin); - if (spin->si_foldroot == NULL) - return FAIL; - - // Let tree_add_word() know we're adding to the soundfolded tree - spin->si_sugtree = true; - - // Go through the whole case-folded tree, soundfold each word and put it - // in the trie. - byts = slang->sl_fbyts; - idxs = slang->sl_fidxs; - - arridx[0] = 0; - curi[0] = 1; - wordcount[0] = 0; - - depth = 0; - while (depth >= 0 && !got_int) { - if (curi[depth] > byts[arridx[depth]]) { - // Done all bytes at this node, go up one level. - idxs[arridx[depth]] = wordcount[depth]; - if (depth > 0) - wordcount[depth - 1] += wordcount[depth]; - - --depth; - line_breakcheck(); - } else { - - // Do one more byte at this node. - n = arridx[depth] + curi[depth]; - ++curi[depth]; - - c = byts[n]; - if (c == 0) { - // Sound-fold the word. - tword[depth] = NUL; - spell_soundfold(slang, tword, true, tsalword); - - // We use the "flags" field for the MSB of the wordnr, - // "region" for the LSB of the wordnr. - if (tree_add_word(spin, tsalword, spin->si_foldroot, - words_done >> 16, words_done & 0xffff, - 0) == FAIL) - return FAIL; - - ++words_done; - ++wordcount[depth]; - - // Reset the block count each time to avoid compression - // kicking in. - spin->si_blocks_cnt = 0; - - // Skip over any other NUL bytes (same word with different - // flags). - while (byts[n + 1] == 0) { - ++n; - ++curi[depth]; - } - } else { - // Normal char, go one level deeper. - tword[depth++] = c; - arridx[depth] = idxs[n]; - curi[depth] = 1; - wordcount[depth] = 0; - } - } - } - - smsg(_("Total number of words: %d"), words_done); - - return OK; -} - -// Make the table that links each word in the soundfold trie to the words it -// can be produced from. -// This is not unlike lines in a file, thus use a memfile to be able to access -// the table efficiently. -// Returns FAIL when out of memory. -static int sug_maketable(spellinfo_T *spin) -{ - garray_T ga; - int res = OK; - - // Allocate a buffer, open a memline for it and create the swap file - // (uses a temp file, not a .swp file). - spin->si_spellbuf = open_spellbuf(); - - // Use a buffer to store the line info, avoids allocating many small - // pieces of memory. - ga_init(&ga, 1, 100); - - // recursively go through the tree - if (sug_filltable(spin, spin->si_foldroot->wn_sibling, 0, &ga) == -1) - res = FAIL; - - ga_clear(&ga); - return res; -} - -// Fill the table for one node and its children. -// Returns the wordnr at the start of the node. -// Returns -1 when out of memory. -static int -sug_filltable ( - spellinfo_T *spin, - wordnode_T *node, - int startwordnr, - garray_T *gap // place to store line of numbers -) -{ - wordnode_T *p, *np; - int wordnr = startwordnr; - int nr; - int prev_nr; - - for (p = node; p != NULL; p = p->wn_sibling) { - if (p->wn_byte == NUL) { - gap->ga_len = 0; - prev_nr = 0; - for (np = p; np != NULL && np->wn_byte == NUL; np = np->wn_sibling) { - ga_grow(gap, 10); - - nr = (np->wn_flags << 16) + (np->wn_region & 0xffff); - // Compute the offset from the previous nr and store the - // offset in a way that it takes a minimum number of bytes. - // It's a bit like utf-8, but without the need to mark - // following bytes. - nr -= prev_nr; - prev_nr += nr; - gap->ga_len += offset2bytes(nr, - (char_u *)gap->ga_data + gap->ga_len); - } - - // add the NUL byte - ((char_u *)gap->ga_data)[gap->ga_len++] = NUL; - - if (ml_append_buf(spin->si_spellbuf, (linenr_T)wordnr, - gap->ga_data, gap->ga_len, TRUE) == FAIL) - return -1; - ++wordnr; - - // Remove extra NUL entries, we no longer need them. We don't - // bother freeing the nodes, the won't be reused anyway. - while (p->wn_sibling != NULL && p->wn_sibling->wn_byte == NUL) - p->wn_sibling = p->wn_sibling->wn_sibling; - - // Clear the flags on the remaining NUL node, so that compression - // works a lot better. - p->wn_flags = 0; - p->wn_region = 0; - } else { - wordnr = sug_filltable(spin, p->wn_child, wordnr, gap); - if (wordnr == -1) - return -1; - } - } - return wordnr; -} - -// Convert an offset into a minimal number of bytes. -// Similar to utf_char2byters, but use 8 bits in followup bytes and avoid NUL -// bytes. -static int offset2bytes(int nr, char_u *buf) -{ - int rem; - int b1, b2, b3, b4; - - // Split the number in parts of base 255. We need to avoid NUL bytes. - b1 = nr % 255 + 1; - rem = nr / 255; - b2 = rem % 255 + 1; - rem = rem / 255; - b3 = rem % 255 + 1; - b4 = rem / 255 + 1; - - if (b4 > 1 || b3 > 0x1f) { // 4 bytes - buf[0] = 0xe0 + b4; - buf[1] = b3; - buf[2] = b2; - buf[3] = b1; - return 4; - } - if (b3 > 1 || b2 > 0x3f ) { // 3 bytes - buf[0] = 0xc0 + b3; - buf[1] = b2; - buf[2] = b1; - return 3; - } - if (b2 > 1 || b1 > 0x7f ) { // 2 bytes - buf[0] = 0x80 + b2; - buf[1] = b1; - return 2; - } - // 1 byte - buf[0] = b1; - return 1; -} // Opposite of offset2bytes(). // "pp" points to the bytes and is advanced over it. @@ -7442,86 +2473,12 @@ static int bytes2offset(char_u **pp) return nr; } -// Write the .sug file in "fname". -static void sug_write(spellinfo_T *spin, char_u *fname) -{ - // Create the file. Note that an existing file is silently overwritten! - FILE *fd = mch_fopen((char *)fname, "w"); - if (fd == NULL) { - EMSG2(_(e_notopen), fname); - return; - } - - vim_snprintf((char *)IObuff, IOSIZE, - _("Writing suggestion file %s ..."), fname); - spell_message(spin, IObuff); - - // <SUGHEADER>: <fileID> <versionnr> <timestamp> - if (fwrite(VIMSUGMAGIC, VIMSUGMAGICL, (size_t)1, fd) != 1) { // <fileID> - EMSG(_(e_write)); - goto theend; - } - putc(VIMSUGVERSION, fd); // <versionnr> - - // Write si_sugtime to the file. - put_time(fd, spin->si_sugtime); // <timestamp> - - // <SUGWORDTREE> - spin->si_memtot = 0; - wordnode_T *tree = spin->si_foldroot->wn_sibling; - - // Clear the index and wnode fields in the tree. - clear_node(tree); - - // Count the number of nodes. Needed to be able to allocate the - // memory when reading the nodes. Also fills in index for shared - // nodes. - size_t nodecount = (size_t)put_node(NULL, tree, 0, 0, false); - - // number of nodes in 4 bytes - put_bytes(fd, nodecount, 4); // <nodecount> - assert(nodecount + nodecount * sizeof(int) < INT_MAX); - spin->si_memtot += (int)(nodecount + nodecount * sizeof(int)); - - // Write the nodes. - (void)put_node(fd, tree, 0, 0, false); - - // <SUGTABLE>: <sugwcount> <sugline> ... - linenr_T wcount = spin->si_spellbuf->b_ml.ml_line_count; - assert(wcount >= 0); - put_bytes(fd, (uintmax_t)wcount, 4); // <sugwcount> - - for (linenr_T lnum = 1; lnum <= wcount; ++lnum) { - // <sugline>: <sugnr> ... NUL - char_u *line = ml_get_buf(spin->si_spellbuf, lnum, FALSE); - size_t len = STRLEN(line) + 1; - if (fwrite(line, len, 1, fd) == 0) { - EMSG(_(e_write)); - goto theend; - } - assert((size_t)spin->si_memtot + len <= INT_MAX); - spin->si_memtot += (int)len; - } - - // Write another byte to check for errors. - if (putc(0, fd) == EOF) - EMSG(_(e_write)); - - vim_snprintf((char *)IObuff, IOSIZE, - _("Estimated runtime memory use: %d bytes"), spin->si_memtot); - spell_message(spin, IObuff); - -theend: - // close the file - fclose(fd); -} - // Open a spell buffer. This is a nameless buffer that is not in the buffer // list and only contains text lines. Can use a swapfile to reduce memory // use. // Most other fields are invalid! Esp. watch out for string options being // NULL and there is no undo info. -static buf_T *open_spellbuf(void) +buf_T *open_spellbuf(void) { buf_T *buf = xcalloc(1, sizeof(buf_T)); @@ -7534,7 +2491,7 @@ static buf_T *open_spellbuf(void) } // Close the buffer used for spell info. -static void close_spellbuf(buf_T *buf) +void close_spellbuf(buf_T *buf) { if (buf != NULL) { ml_close(buf, TRUE); @@ -7542,471 +2499,8 @@ static void close_spellbuf(buf_T *buf) } } - -// Create a Vim spell file from one or more word lists. -// "fnames[0]" is the output file name. -// "fnames[fcount - 1]" is the last input file name. -// Exception: when "fnames[0]" ends in ".add" it's used as the input file name -// and ".spl" is appended to make the output file name. -static void -mkspell ( - int fcount, - char_u **fnames, - bool ascii, // -ascii argument given - bool over_write, // overwrite existing output file - bool added_word // invoked through "zg" -) -{ - char_u *fname = NULL; - char_u *wfname; - char_u **innames; - int incount; - afffile_T *(afile[8]); - int i; - int len; - bool error = false; - spellinfo_T spin; - - memset(&spin, 0, sizeof(spin)); - spin.si_verbose = !added_word; - spin.si_ascii = ascii; - spin.si_followup = true; - spin.si_rem_accents = true; - ga_init(&spin.si_rep, (int)sizeof(fromto_T), 20); - ga_init(&spin.si_repsal, (int)sizeof(fromto_T), 20); - ga_init(&spin.si_sal, (int)sizeof(fromto_T), 20); - ga_init(&spin.si_map, (int)sizeof(char_u), 100); - ga_init(&spin.si_comppat, (int)sizeof(char_u *), 20); - ga_init(&spin.si_prefcond, (int)sizeof(char_u *), 50); - hash_init(&spin.si_commonwords); - spin.si_newcompID = 127; // start compound ID at first maximum - - // default: fnames[0] is output file, following are input files - innames = &fnames[1]; - incount = fcount - 1; - - wfname = xmalloc(MAXPATHL); - - if (fcount >= 1) { - len = (int)STRLEN(fnames[0]); - if (fcount == 1 && len > 4 && STRCMP(fnames[0] + len - 4, ".add") == 0) { - // For ":mkspell path/en.latin1.add" output file is - // "path/en.latin1.add.spl". - innames = &fnames[0]; - incount = 1; - vim_snprintf((char *)wfname, MAXPATHL, "%s.spl", fnames[0]); - } else if (fcount == 1) { - // For ":mkspell path/vim" output file is "path/vim.latin1.spl". - innames = &fnames[0]; - incount = 1; - vim_snprintf((char *)wfname, MAXPATHL, SPL_FNAME_TMPL, - fnames[0], spin.si_ascii ? (char_u *)"ascii" : spell_enc()); - } else if (len > 4 && STRCMP(fnames[0] + len - 4, ".spl") == 0) { - // Name ends in ".spl", use as the file name. - STRLCPY(wfname, fnames[0], MAXPATHL); - } else - // Name should be language, make the file name from it. - vim_snprintf((char *)wfname, MAXPATHL, SPL_FNAME_TMPL, - fnames[0], spin.si_ascii ? (char_u *)"ascii" : spell_enc()); - - // Check for .ascii.spl. - if (strstr((char *)path_tail(wfname), SPL_FNAME_ASCII) != NULL) - spin.si_ascii = true; - - // Check for .add.spl. - if (strstr((char *)path_tail(wfname), SPL_FNAME_ADD) != NULL) - spin.si_add = true; - } - - if (incount <= 0) - EMSG(_(e_invarg)); // need at least output and input names - else if (vim_strchr(path_tail(wfname), '_') != NULL) - EMSG(_("E751: Output file name must not have region name")); - else if (incount > 8) - EMSG(_("E754: Only up to 8 regions supported")); - else { - // Check for overwriting before doing things that may take a lot of - // time. - if (!over_write && os_path_exists(wfname)) { - EMSG(_(e_exists)); - goto theend; - } - if (os_isdir(wfname)) { - EMSG2(_(e_isadir2), wfname); - goto theend; - } - - fname = xmalloc(MAXPATHL); - - // Init the aff and dic pointers. - // Get the region names if there are more than 2 arguments. - for (i = 0; i < incount; ++i) { - afile[i] = NULL; - - if (incount > 1) { - len = (int)STRLEN(innames[i]); - if (STRLEN(path_tail(innames[i])) < 5 - || innames[i][len - 3] != '_') { - EMSG2(_("E755: Invalid region in %s"), innames[i]); - goto theend; - } - spin.si_region_name[i * 2] = TOLOWER_ASC(innames[i][len - 2]); - spin.si_region_name[i * 2 + 1] = - TOLOWER_ASC(innames[i][len - 1]); - } - } - spin.si_region_count = incount; - - spin.si_foldroot = wordtree_alloc(&spin); - spin.si_keeproot = wordtree_alloc(&spin); - spin.si_prefroot = wordtree_alloc(&spin); - if (spin.si_foldroot == NULL - || spin.si_keeproot == NULL - || spin.si_prefroot == NULL) { - free_blocks(spin.si_blocks); - goto theend; - } - - // When not producing a .add.spl file clear the character table when - // we encounter one in the .aff file. This means we dump the current - // one in the .spl file if the .aff file doesn't define one. That's - // better than guessing the contents, the table will match a - // previously loaded spell file. - if (!spin.si_add) - spin.si_clear_chartab = true; - - // Read all the .aff and .dic files. - // Text is converted to 'encoding'. - // Words are stored in the case-folded and keep-case trees. - for (i = 0; i < incount && !error; ++i) { - spin.si_conv.vc_type = CONV_NONE; - spin.si_region = 1 << i; - - vim_snprintf((char *)fname, MAXPATHL, "%s.aff", innames[i]); - if (os_path_exists(fname)) { - // Read the .aff file. Will init "spin->si_conv" based on the - // "SET" line. - afile[i] = spell_read_aff(&spin, fname); - if (afile[i] == NULL) - error = true; - else { - // Read the .dic file and store the words in the trees. - vim_snprintf((char *)fname, MAXPATHL, "%s.dic", - innames[i]); - if (spell_read_dic(&spin, fname, afile[i]) == FAIL) - error = true; - } - } else { - // No .aff file, try reading the file as a word list. Store - // the words in the trees. - if (spell_read_wordfile(&spin, innames[i]) == FAIL) - error = true; - } - - // Free any conversion stuff. - convert_setup(&spin.si_conv, NULL, NULL); - } - - if (spin.si_compflags != NULL && spin.si_nobreak) - MSG(_("Warning: both compounding and NOBREAK specified")); - - if (!error && !got_int) { - // Combine tails in the tree. - spell_message(&spin, (char_u *)_(msg_compressing)); - wordtree_compress(&spin, spin.si_foldroot); - wordtree_compress(&spin, spin.si_keeproot); - wordtree_compress(&spin, spin.si_prefroot); - } - - if (!error && !got_int) { - // Write the info in the spell file. - vim_snprintf((char *)IObuff, IOSIZE, - _("Writing spell file %s ..."), wfname); - spell_message(&spin, IObuff); - - error = write_vim_spell(&spin, wfname) == FAIL; - - spell_message(&spin, (char_u *)_("Done!")); - vim_snprintf((char *)IObuff, IOSIZE, - _("Estimated runtime memory use: %d bytes"), spin.si_memtot); - spell_message(&spin, IObuff); - - // If the file is loaded need to reload it. - if (!error) - spell_reload_one(wfname, added_word); - } - - // Free the allocated memory. - ga_clear(&spin.si_rep); - ga_clear(&spin.si_repsal); - ga_clear(&spin.si_sal); - ga_clear(&spin.si_map); - ga_clear(&spin.si_comppat); - ga_clear(&spin.si_prefcond); - hash_clear_all(&spin.si_commonwords, 0); - - // Free the .aff file structures. - for (i = 0; i < incount; ++i) - if (afile[i] != NULL) - spell_free_aff(afile[i]); - - // Free all the bits and pieces at once. - free_blocks(spin.si_blocks); - - // If there is soundfolding info and no NOSUGFILE item create the - // .sug file with the soundfolded word trie. - if (spin.si_sugtime != 0 && !error && !got_int) - spell_make_sugfile(&spin, wfname); - - } - -theend: - xfree(fname); - xfree(wfname); -} - -// Display a message for spell file processing when 'verbose' is set or using -// ":mkspell". "str" can be IObuff. -static void spell_message(spellinfo_T *spin, char_u *str) -{ - if (spin->si_verbose || p_verbose > 2) { - if (!spin->si_verbose) - verbose_enter(); - MSG(str); - ui_flush(); - if (!spin->si_verbose) - verbose_leave(); - } -} - -// ":[count]spellgood {word}" -// ":[count]spellwrong {word}" -// ":[count]spellundo {word}" -void ex_spell(exarg_T *eap) -{ - spell_add_word(eap->arg, (int)STRLEN(eap->arg), eap->cmdidx == CMD_spellwrong, - eap->forceit ? 0 : (int)eap->line2, - eap->cmdidx == CMD_spellundo); -} - -// Add "word[len]" to 'spellfile' as a good or bad word. -void -spell_add_word ( - char_u *word, - int len, - int bad, - int idx, // "zG" and "zW": zero, otherwise index in - // 'spellfile' - bool undo // true for "zug", "zuG", "zuw" and "zuW" -) -{ - FILE *fd = NULL; - buf_T *buf = NULL; - bool new_spf = false; - char_u *fname; - char_u *fnamebuf = NULL; - char_u line[MAXWLEN * 2]; - long fpos, fpos_next = 0; - int i; - char_u *spf; - - if (idx == 0) { // use internal wordlist - if (int_wordlist == NULL) { - int_wordlist = vim_tempname(); - if (int_wordlist == NULL) - return; - } - fname = int_wordlist; - } else { - // If 'spellfile' isn't set figure out a good default value. - if (*curwin->w_s->b_p_spf == NUL) { - init_spellfile(); - new_spf = true; - } - - if (*curwin->w_s->b_p_spf == NUL) { - EMSG2(_(e_notset), "spellfile"); - return; - } - fnamebuf = xmalloc(MAXPATHL); - - for (spf = curwin->w_s->b_p_spf, i = 1; *spf != NUL; ++i) { - copy_option_part(&spf, fnamebuf, MAXPATHL, ","); - if (i == idx) - break; - if (*spf == NUL) { - EMSGN(_("E765: 'spellfile' does not have %" PRId64 " entries"), idx); - xfree(fnamebuf); - return; - } - } - - // Check that the user isn't editing the .add file somewhere. - buf = buflist_findname_exp(fnamebuf); - if (buf != NULL && buf->b_ml.ml_mfp == NULL) - buf = NULL; - if (buf != NULL && bufIsChanged(buf)) { - EMSG(_(e_bufloaded)); - xfree(fnamebuf); - return; - } - - fname = fnamebuf; - } - - if (bad || undo) { - // When the word appears as good word we need to remove that one, - // since its flags sort before the one with WF_BANNED. - fd = mch_fopen((char *)fname, "r"); - if (fd != NULL) { - while (!vim_fgets(line, MAXWLEN * 2, fd)) { - fpos = fpos_next; - fpos_next = ftell(fd); - if (STRNCMP(word, line, len) == 0 - && (line[len] == '/' || line[len] < ' ')) { - // Found duplicate word. Remove it by writing a '#' at - // the start of the line. Mixing reading and writing - // doesn't work for all systems, close the file first. - fclose(fd); - fd = mch_fopen((char *)fname, "r+"); - if (fd == NULL) - break; - if (fseek(fd, fpos, SEEK_SET) == 0) { - fputc('#', fd); - if (undo) { - home_replace(NULL, fname, NameBuff, MAXPATHL, TRUE); - smsg(_("Word '%.*s' removed from %s"), - len, word, NameBuff); - } - } - fseek(fd, fpos_next, SEEK_SET); - } - } - if (fd != NULL) - fclose(fd); - } - } - - if (!undo) { - fd = mch_fopen((char *)fname, "a"); - if (fd == NULL && new_spf) { - char_u *p; - - // We just initialized the 'spellfile' option and can't open the - // file. We may need to create the "spell" directory first. We - // already checked the runtime directory is writable in - // init_spellfile(). - if (!dir_of_file_exists(fname) && (p = path_tail_with_sep(fname)) != fname) { - int c = *p; - - // The directory doesn't exist. Try creating it and opening - // the file again. - *p = NUL; - os_mkdir((char *)fname, 0755); - *p = c; - fd = mch_fopen((char *)fname, "a"); - } - } - - if (fd == NULL) - EMSG2(_(e_notopen), fname); - else { - if (bad) - fprintf(fd, "%.*s/!\n", len, word); - else - fprintf(fd, "%.*s\n", len, word); - fclose(fd); - - home_replace(NULL, fname, NameBuff, MAXPATHL, TRUE); - smsg(_("Word '%.*s' added to %s"), len, word, NameBuff); - } - } - - if (fd != NULL) { - // Update the .add.spl file. - mkspell(1, &fname, false, true, true); - - // If the .add file is edited somewhere, reload it. - if (buf != NULL) - buf_reload(buf, buf->b_orig_mode); - - redraw_all_later(SOME_VALID); - } - xfree(fnamebuf); -} - -// Initialize 'spellfile' for the current buffer. -static void init_spellfile(void) -{ - char_u *buf; - int l; - char_u *fname; - char_u *rtp; - char_u *lend; - bool aspath = false; - char_u *lstart = curbuf->b_s.b_p_spl; - - if (*curwin->w_s->b_p_spl != NUL && !GA_EMPTY(&curwin->w_s->b_langp)) { - buf = xmalloc(MAXPATHL); - - // Find the end of the language name. Exclude the region. If there - // is a path separator remember the start of the tail. - for (lend = curwin->w_s->b_p_spl; *lend != NUL - && vim_strchr((char_u *)",._", *lend) == NULL; ++lend) - if (vim_ispathsep(*lend)) { - aspath = true; - lstart = lend + 1; - } - - // Loop over all entries in 'runtimepath'. Use the first one where we - // are allowed to write. - rtp = p_rtp; - while (*rtp != NUL) { - if (aspath) - // Use directory of an entry with path, e.g., for - // "/dir/lg.utf-8.spl" use "/dir". - STRLCPY(buf, curbuf->b_s.b_p_spl, - lstart - curbuf->b_s.b_p_spl); - else - // Copy the path from 'runtimepath' to buf[]. - copy_option_part(&rtp, buf, MAXPATHL, ","); - if (os_file_is_writable((char *)buf) == 2) { - // Use the first language name from 'spelllang' and the - // encoding used in the first loaded .spl file. - if (aspath) - STRLCPY(buf, curbuf->b_s.b_p_spl, - lend - curbuf->b_s.b_p_spl + 1); - else { - // Create the "spell" directory if it doesn't exist yet. - l = (int)STRLEN(buf); - vim_snprintf((char *)buf + l, MAXPATHL - l, "/spell"); - if (os_file_is_writable((char *)buf) != 2) { - os_mkdir((char *)buf, 0755); - } - - l = (int)STRLEN(buf); - vim_snprintf((char *)buf + l, MAXPATHL - l, - "/%.*s", (int)(lend - lstart), lstart); - } - l = (int)STRLEN(buf); - fname = LANGP_ENTRY(curwin->w_s->b_langp, 0) - ->lp_slang->sl_fname; - vim_snprintf((char *)buf + l, MAXPATHL - l, ".%s.add", - fname != NULL - && strstr((char *)path_tail(fname), ".ascii.") != NULL - ? (char_u *)"ascii" : spell_enc()); - set_option_value((char_u *)"spellfile", 0L, buf, OPT_LOCAL); - break; - } - aspath = false; - } - - xfree(buf); - } -} - // Init the chartab used for spelling for ASCII. -static void clear_spell_chartab(spelltab_T *sp) +void clear_spell_chartab(spelltab_T *sp) { int i; @@ -8034,8 +2528,7 @@ static void clear_spell_chartab(spelltab_T *sp) } } -// Init the chartab used for spelling. Only depends on 'encoding'. -// Called once while starting up and when 'encoding' changes. +// Init the chartab used for spelling. Called once while starting up. // The default is to use isalpha(), but the spell file should define the word // characters to make it possible that 'encoding' differs from the current // locale. For utf-8 we don't use isalpha() but our own functions. @@ -8045,154 +2538,18 @@ void init_spell_chartab(void) did_set_spelltab = false; clear_spell_chartab(&spelltab); - if (enc_dbcs) { - // DBCS: assume double-wide characters are word characters. - for (i = 128; i <= 255; ++i) - if (MB_BYTE2LEN(i) == 2) - spelltab.st_isw[i] = true; - } else if (enc_utf8) { - for (i = 128; i < 256; ++i) { - int f = utf_fold(i); - int u = utf_toupper(i); - - spelltab.st_isu[i] = utf_isupper(i); - spelltab.st_isw[i] = spelltab.st_isu[i] || utf_islower(i); - // The folded/upper-cased value is different between latin1 and - // utf8 for 0xb5, causing E763 for no good reason. Use the latin1 - // value for utf-8 to avoid this. - spelltab.st_fold[i] = (f < 256) ? f : i; - spelltab.st_upper[i] = (u < 256) ? u : i; - } - } else { - // Rough guess: use locale-dependent library functions. - for (i = 128; i < 256; ++i) { - if (vim_isupper(i)) { - spelltab.st_isw[i] = true; - spelltab.st_isu[i] = true; - spelltab.st_fold[i] = vim_tolower(i); - } else if (vim_islower(i)) { - spelltab.st_isw[i] = true; - spelltab.st_upper[i] = vim_toupper(i); - } - } - } -} - -// Set the spell character tables from strings in the affix file. -static int set_spell_chartab(char_u *fol, char_u *low, char_u *upp) -{ - // We build the new tables here first, so that we can compare with the - // previous one. - spelltab_T new_st; - char_u *pf = fol, *pl = low, *pu = upp; - int f, l, u; - - clear_spell_chartab(&new_st); - - while (*pf != NUL) { - if (*pl == NUL || *pu == NUL) { - EMSG(_(e_affform)); - return FAIL; - } - f = mb_ptr2char_adv(&pf); - l = mb_ptr2char_adv(&pl); - u = mb_ptr2char_adv(&pu); - // Every character that appears is a word character. - if (f < 256) - new_st.st_isw[f] = true; - if (l < 256) - new_st.st_isw[l] = true; - if (u < 256) - new_st.st_isw[u] = true; - - // if "LOW" and "FOL" are not the same the "LOW" char needs - // case-folding - if (l < 256 && l != f) { - if (f >= 256) { - EMSG(_(e_affrange)); - return FAIL; - } - new_st.st_fold[l] = f; - } - - // if "UPP" and "FOL" are not the same the "UPP" char needs - // case-folding, it's upper case and the "UPP" is the upper case of - // "FOL" . - if (u < 256 && u != f) { - if (f >= 256) { - EMSG(_(e_affrange)); - return FAIL; - } - new_st.st_fold[u] = f; - new_st.st_isu[u] = true; - new_st.st_upper[f] = u; - } - } + for (i = 128; i < 256; i++) { + int f = utf_fold(i); + int u = mb_toupper(i); - if (*pl != NUL || *pu != NUL) { - EMSG(_(e_affform)); - return FAIL; + spelltab.st_isu[i] = mb_isupper(i); + spelltab.st_isw[i] = spelltab.st_isu[i] || mb_islower(i); + // The folded/upper-cased value is different between latin1 and + // utf8 for 0xb5, causing E763 for no good reason. Use the latin1 + // value for utf-8 to avoid this. + spelltab.st_fold[i] = (f < 256) ? f : i; + spelltab.st_upper[i] = (u < 256) ? u : i; } - - return set_spell_finish(&new_st); -} - -// Set the spell character tables from strings in the .spl file. -static void -set_spell_charflags ( - char_u *flags, - int cnt, // length of "flags" - char_u *fol -) -{ - // We build the new tables here first, so that we can compare with the - // previous one. - spelltab_T new_st; - int i; - char_u *p = fol; - int c; - - clear_spell_chartab(&new_st); - - for (i = 0; i < 128; ++i) { - if (i < cnt) { - new_st.st_isw[i + 128] = (flags[i] & CF_WORD) != 0; - new_st.st_isu[i + 128] = (flags[i] & CF_UPPER) != 0; - } - - if (*p != NUL) { - c = mb_ptr2char_adv(&p); - new_st.st_fold[i + 128] = c; - if (i + 128 != c && new_st.st_isu[i + 128] && c < 256) - new_st.st_upper[c] = i + 128; - } - } - - (void)set_spell_finish(&new_st); -} - -static int set_spell_finish(spelltab_T *new_st) -{ - int i; - - if (did_set_spelltab) { - // check that it's the same table - for (i = 0; i < 256; ++i) { - if (spelltab.st_isw[i] != new_st->st_isw[i] - || spelltab.st_isu[i] != new_st->st_isu[i] - || spelltab.st_fold[i] != new_st->st_fold[i] - || spelltab.st_upper[i] != new_st->st_upper[i]) { - EMSG(_("E763: Word characters differ between spell files")); - return FAIL; - } - } - } else { - // copy the new spelltab into the one being used - spelltab = *new_st; - did_set_spelltab = true; - } - - return OK; } /// Returns true if "p" points to a word character. @@ -8233,14 +2590,15 @@ static bool spell_iswordp(char_u *p, win_T *wp) // Returns true if "p" points to a word character. // Unlike spell_iswordp() this doesn't check for "midword" characters. -static bool spell_iswordp_nmw(char_u *p, win_T *wp) +bool spell_iswordp_nmw(const char_u *p, win_T *wp) { int c; if (has_mbyte) { c = mb_ptr2char(p); - if (c > 255) + if (c > 255) { return spell_mb_isword_class(mb_get_class(p), wp); + } return spelltab.st_isw[c]; } return spelltab.st_isw[*p]; @@ -8249,7 +2607,7 @@ static bool spell_iswordp_nmw(char_u *p, win_T *wp) // Returns true if word class indicates a word character. // Only for characters above 255. // Unicode subscript and superscript are not considered word characters. -// See also dbcs_class() and utf_class() in mbyte.c. +// See also utf_class() in mbyte.c. static bool spell_mb_isword_class(int cl, win_T *wp) { if (wp->w_s->b_cjk) @@ -8272,51 +2630,16 @@ static bool spell_iswordp_w(int *p, win_T *wp) s = p; if (*s > 255) { - if (enc_utf8) - return spell_mb_isword_class(utf_class(*s), wp); - if (enc_dbcs) - return spell_mb_isword_class( - dbcs_class((unsigned)*s >> 8, *s & 0xff), wp); - return false; + return spell_mb_isword_class(utf_class(*s), wp); } return spelltab.st_isw[*s]; } -// Write the table with prefix conditions to the .spl file. -// When "fd" is NULL only count the length of what is written. -static int write_spell_prefcond(FILE *fd, garray_T *gap) -{ - assert(gap->ga_len >= 0); - - if (fd != NULL) - put_bytes(fd, (uintmax_t)gap->ga_len, 2); // <prefcondcnt> - - size_t totlen = 2 + (size_t)gap->ga_len; // <prefcondcnt> and <condlen> bytes - size_t x = 1; // collect return value of fwrite() - for (int i = 0; i < gap->ga_len; ++i) { - // <prefcond> : <condlen> <condstr> - char_u *p = ((char_u **)gap->ga_data)[i]; - if (p != NULL) { - size_t len = STRLEN(p); - if (fd != NULL) { - assert(len <= INT_MAX); - fputc((int)len, fd); - x &= fwrite(p, len, 1, fd); - } - totlen += len; - } else if (fd != NULL) - fputc(0, fd); - } - - assert(totlen <= INT_MAX); - return (int)totlen; -} - // Case-fold "str[len]" into "buf[buflen]". The result is NUL terminated. // Uses the character definitions from the .spl file. // When using a multi-byte 'encoding' the length may change! // Returns FAIL when something wrong. -static int spell_casefold(char_u *str, int len, char_u *buf, int buflen) +int spell_casefold(char_u *str, int len, char_u *buf, int buflen) { int i; @@ -8336,7 +2659,7 @@ static int spell_casefold(char_u *str, int len, char_u *buf, int buflen) buf[outi] = NUL; return FAIL; } - c = mb_cptr2char_adv(&p); + c = mb_cptr2char_adv((const char_u **)&p); outi += mb_char2bytes(SPELL_TOFOLD(c), buf + outi); } buf[outi] = NUL; @@ -8510,7 +2833,7 @@ void spell_suggest(int count) vim_snprintf((char *)IObuff, IOSIZE, ":ot \"%.*s\" egnahC", sug.su_badlen, sug.su_badptr); } - msg_puts(IObuff); + msg_puts((const char *)IObuff); msg_clr_eos(); msg_putchar('\n'); @@ -8526,18 +2849,19 @@ void spell_suggest(int count) sug.su_badptr + stp->st_orglen, sug.su_badlen - stp->st_orglen + 1); vim_snprintf((char *)IObuff, IOSIZE, "%2d", i + 1); - if (cmdmsg_rl) + if (cmdmsg_rl) { rl_mirror(IObuff); - msg_puts(IObuff); + } + msg_puts((const char *)IObuff); vim_snprintf((char *)IObuff, IOSIZE, " \"%s\"", wcopy); - msg_puts(IObuff); + msg_puts((const char *)IObuff); // The word may replace more than "su_badlen". if (sug.su_badlen < stp->st_orglen) { vim_snprintf((char *)IObuff, IOSIZE, _(" < \"%.*s\""), - stp->st_orglen, sug.su_badptr); - msg_puts(IObuff); + stp->st_orglen, sug.su_badptr); + msg_puts((const char *)IObuff); } if (p_verbose > 0) { @@ -8553,7 +2877,7 @@ void spell_suggest(int count) // Mirror the numbers, but keep the leading space. rl_mirror(IObuff + 1); msg_advance(30); - msg_puts(IObuff); + msg_puts((const char *)IObuff); } msg_putchar('\n'); } @@ -8597,7 +2921,7 @@ void spell_suggest(int count) // For redo we use a change-word command. ResetRedobuff(); - AppendToRedobuff((char_u *)"ciw"); + AppendToRedobuff("ciw"); AppendToRedobuffLit(p + c, stp->st_wordlen + sug.su_badlen - stp->st_orglen); AppendCharToRedobuff(ESC); @@ -8892,7 +3216,7 @@ static void spell_suggest_expr(suginfo_T *su, char_u *expr) list_T *list; listitem_T *li; int score; - char_u *p; + const char *p; // The work is split up in a few parts to avoid having to export // suginfo_T. @@ -8904,11 +3228,12 @@ static void spell_suggest_expr(suginfo_T *su, char_u *expr) if (li->li_tv.v_type == VAR_LIST) { // Get the word and the score from the items. score = get_spellword(li->li_tv.vval.v_list, &p); - if (score >= 0 && score <= su->su_maxscore) - add_suggestion(su, &su->su_ga, p, su->su_badlen, - score, 0, true, su->su_sallang, false); + if (score >= 0 && score <= su->su_maxscore) { + add_suggestion(su, &su->su_ga, (const char_u *)p, su->su_badlen, + score, 0, true, su->su_sallang, false); + } } - list_unref(list); + tv_list_unref(list); } // Remove bogus suggestions, sort and truncate at "maxcount". @@ -9039,174 +3364,6 @@ static void spell_suggest_intern(suginfo_T *su, bool interactive) } } -// Load the .sug files for languages that have one and weren't loaded yet. -static void suggest_load_files(void) -{ - langp_T *lp; - slang_T *slang; - char_u *dotp; - FILE *fd; - char_u buf[MAXWLEN]; - int i; - time_t timestamp; - int wcount; - int wordnr; - garray_T ga; - int c; - - // Do this for all languages that support sound folding. - for (int lpi = 0; lpi < curwin->w_s->b_langp.ga_len; ++lpi) { - lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi); - slang = lp->lp_slang; - if (slang->sl_sugtime != 0 && !slang->sl_sugloaded) { - // Change ".spl" to ".sug" and open the file. When the file isn't - // found silently skip it. Do set "sl_sugloaded" so that we - // don't try again and again. - slang->sl_sugloaded = true; - - dotp = vim_strrchr(slang->sl_fname, '.'); - if (dotp == NULL || fnamecmp(dotp, ".spl") != 0) - continue; - STRCPY(dotp, ".sug"); - fd = mch_fopen((char *)slang->sl_fname, "r"); - if (fd == NULL) - goto nextone; - - // <SUGHEADER>: <fileID> <versionnr> <timestamp> - for (i = 0; i < VIMSUGMAGICL; ++i) - buf[i] = getc(fd); // <fileID> - if (STRNCMP(buf, VIMSUGMAGIC, VIMSUGMAGICL) != 0) { - EMSG2(_("E778: This does not look like a .sug file: %s"), - slang->sl_fname); - goto nextone; - } - c = getc(fd); // <versionnr> - if (c < VIMSUGVERSION) { - EMSG2(_("E779: Old .sug file, needs to be updated: %s"), - slang->sl_fname); - goto nextone; - } else if (c > VIMSUGVERSION) { - EMSG2(_("E780: .sug file is for newer version of Vim: %s"), - slang->sl_fname); - goto nextone; - } - - // Check the timestamp, it must be exactly the same as the one in - // the .spl file. Otherwise the word numbers won't match. - timestamp = get8ctime(fd); // <timestamp> - if (timestamp != slang->sl_sugtime) { - EMSG2(_("E781: .sug file doesn't match .spl file: %s"), - slang->sl_fname); - goto nextone; - } - - // <SUGWORDTREE>: <wordtree> - // Read the trie with the soundfolded words. - if (spell_read_tree(fd, &slang->sl_sbyts, &slang->sl_sidxs, - false, 0) != 0) { -someerror: - EMSG2(_("E782: error while reading .sug file: %s"), - slang->sl_fname); - slang_clear_sug(slang); - goto nextone; - } - - // <SUGTABLE>: <sugwcount> <sugline> ... - // - // Read the table with word numbers. We use a file buffer for - // this, because it's so much like a file with lines. Makes it - // possible to swap the info and save on memory use. - slang->sl_sugbuf = open_spellbuf(); - - // <sugwcount> - wcount = get4c(fd); - if (wcount < 0) - goto someerror; - - // Read all the wordnr lists into the buffer, one NUL terminated - // list per line. - ga_init(&ga, 1, 100); - for (wordnr = 0; wordnr < wcount; ++wordnr) { - ga.ga_len = 0; - for (;; ) { - c = getc(fd); // <sugline> - if (c < 0) { - goto someerror; - } - GA_APPEND(char_u, &ga, c); - if (c == NUL) - break; - } - if (ml_append_buf(slang->sl_sugbuf, (linenr_T)wordnr, - ga.ga_data, ga.ga_len, TRUE) == FAIL) - goto someerror; - } - ga_clear(&ga); - - // Need to put word counts in the word tries, so that we can find - // a word by its number. - tree_count_words(slang->sl_fbyts, slang->sl_fidxs); - tree_count_words(slang->sl_sbyts, slang->sl_sidxs); - -nextone: - if (fd != NULL) - fclose(fd); - STRCPY(dotp, ".spl"); - } - } -} - -// Fill in the wordcount fields for a trie. -// Returns the total number of words. -static void tree_count_words(char_u *byts, idx_T *idxs) -{ - int depth; - idx_T arridx[MAXWLEN]; - int curi[MAXWLEN]; - int c; - idx_T n; - int wordcount[MAXWLEN]; - - arridx[0] = 0; - curi[0] = 1; - wordcount[0] = 0; - depth = 0; - while (depth >= 0 && !got_int) { - if (curi[depth] > byts[arridx[depth]]) { - // Done all bytes at this node, go up one level. - idxs[arridx[depth]] = wordcount[depth]; - if (depth > 0) - wordcount[depth - 1] += wordcount[depth]; - - --depth; - fast_breakcheck(); - } else { - // Do one more byte at this node. - n = arridx[depth] + curi[depth]; - ++curi[depth]; - - c = byts[n]; - if (c == 0) { - // End of word, count it. - ++wordcount[depth]; - - // Skip over any other NUL bytes (same word with different - // flags). - while (byts[n + 1] == 0) { - ++n; - ++curi[depth]; - } - } else { - // Normal char, go one level deeper to count the words. - ++depth; - arridx[depth] = idxs[n]; - curi[depth] = 1; - wordcount[depth] = 0; - } - } - } -} - // Free the info put in "*su" by spell_find_suggest(). static void spell_find_cleanup(suginfo_T *su) { @@ -9219,32 +3376,33 @@ static void spell_find_cleanup(suginfo_T *su) hash_clear_all(&su->su_banned, 0); } -// Make a copy of "word", with the first letter upper or lower cased, to -// "wcopy[MAXWLEN]". "word" must not be empty. -// The result is NUL terminated. -static void -onecap_copy ( - char_u *word, - char_u *wcopy, - bool upper // true: first letter made upper case -) +/// Make a copy of "word", with the first letter upper or lower cased, to +/// "wcopy[MAXWLEN]". "word" must not be empty. +/// The result is NUL terminated. +/// +/// @param[in] word source string to copy +/// @param[in,out] wcopy copied string, with case of first letter changed +/// @param[in] upper True to upper case, otherwise lower case +void onecap_copy(char_u *word, char_u *wcopy, bool upper) { char_u *p; int c; int l; p = word; - if (has_mbyte) - c = mb_cptr2char_adv(&p); - else + if (has_mbyte) { + c = mb_cptr2char_adv((const char_u **)&p); + } else { c = *p++; - if (upper) + } + if (upper) { c = SPELL_TOUPPER(c); - else + } else { c = SPELL_TOFOLD(c); - if (has_mbyte) + } + if (has_mbyte) { l = mb_char2bytes(c, wcopy); - else { + } else { l = 1; wcopy[0] = c; } @@ -9261,10 +3419,11 @@ static void allcap_copy(char_u *word, char_u *wcopy) d = wcopy; for (s = word; *s != NUL; ) { - if (has_mbyte) - c = mb_cptr2char_adv(&s); - else + if (has_mbyte) { + c = mb_cptr2char_adv((const char_u **)&s); + } else { c = *s++; + } if (c == 0xdf) { c = 'S'; @@ -9474,7 +3633,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so // word). depth = 0; sp = &stack[0]; - memset(sp, 0, sizeof(trystate_T)); + memset(sp, 0, sizeof(trystate_T)); // -V512 sp->ts_curi = 1; if (soundfold) { @@ -10330,7 +4489,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so } if (has_mbyte) { - n = mb_cptr2len(p); + n = MB_CPTR2LEN(p); c = mb_ptr2char(p); if (p[n] == NUL) c2 = NUL; @@ -10407,9 +4566,9 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so // "fword" here, it's changed back afterwards at STATE_UNSWAP3. p = fword + sp->ts_fidx; if (has_mbyte) { - n = mb_cptr2len(p); + n = MB_CPTR2LEN(p); c = mb_ptr2char(p); - fl = mb_cptr2len(p + n); + fl = MB_CPTR2LEN(p + n); c2 = mb_ptr2char(p + n); if (!soundfold && !spell_iswordp(p + n + fl, curwin)) c3 = c; // don't swap non-word char @@ -10505,10 +4664,10 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so ++depth; p = fword + sp->ts_fidx; if (has_mbyte) { - n = mb_cptr2len(p); + n = MB_CPTR2LEN(p); c = mb_ptr2char(p); - fl = mb_cptr2len(p + n); - fl += mb_cptr2len(p + n + fl); + fl = MB_CPTR2LEN(p + n); + fl += MB_CPTR2LEN(p + n + fl); memmove(p, p + n, fl); mb_char2bytes(c, p + fl); stack[depth].ts_fidxtry = sp->ts_fidx + n + fl; @@ -10557,10 +4716,10 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so ++depth; p = fword + sp->ts_fidx; if (has_mbyte) { - n = mb_cptr2len(p); - n += mb_cptr2len(p + n); + n = MB_CPTR2LEN(p); + n += MB_CPTR2LEN(p + n); c = mb_ptr2char(p + n); - tl = mb_cptr2len(p + n); + tl = MB_CPTR2LEN(p + n); memmove(p + tl, p, n); mb_char2bytes(c, p); stack[depth].ts_fidxtry = sp->ts_fidx + n + tl; @@ -10803,10 +4962,11 @@ static void find_keepcap_word(slang_T *slang, char_u *fword, char_u *kword) // round[depth] == 1: Try using the folded-case character. // round[depth] == 2: Try using the upper-case character. if (has_mbyte) { - flen = mb_cptr2len(fword + fwordidx[depth]); - ulen = mb_cptr2len(uword + uwordidx[depth]); - } else + flen = MB_CPTR2LEN(fword + fwordidx[depth]); + ulen = MB_CPTR2LEN(uword + uwordidx[depth]); + } else { ulen = flen = 1; + } if (round[depth] == 1) { p = fword + fwordidx[depth]; l = flen; @@ -11177,11 +5337,13 @@ add_sound_suggest ( // the words that have a better score than before. Use a hashtable to // remember the words that have been done. hash = hash_hash(goodword); - hi = hash_lookup(&slang->sl_sounddone, goodword, hash); + const size_t goodword_len = STRLEN(goodword); + hi = hash_lookup(&slang->sl_sounddone, (const char *)goodword, goodword_len, + hash); if (HASHITEM_EMPTY(hi)) { - sft = xmalloc(sizeof(sftword_T) + STRLEN(goodword)); + sft = xmalloc(sizeof(sftword_T) + goodword_len); sft->sft_score = score; - STRCPY(sft->sft_word, goodword); + memcpy(sft->sft_word, goodword, goodword_len + 1); hash_add_item(&slang->sl_sounddone, hi, sft->sft_word, hash); } else { sft = HI2SFT(hi); @@ -11402,67 +5564,6 @@ static void make_case_word(char_u *fword, char_u *cword, int flags) STRCPY(cword, fword); } -// Use map string "map" for languages "lp". -static void set_map_str(slang_T *lp, char_u *map) -{ - char_u *p; - int headc = 0; - int c; - int i; - - if (*map == NUL) { - lp->sl_has_map = false; - return; - } - lp->sl_has_map = true; - - // Init the array and hash tables empty. - for (i = 0; i < 256; ++i) - lp->sl_map_array[i] = 0; - hash_init(&lp->sl_map_hash); - - // The similar characters are stored separated with slashes: - // "aaa/bbb/ccc/". Fill sl_map_array[c] with the character before c and - // before the same slash. For characters above 255 sl_map_hash is used. - for (p = map; *p != NUL; ) { - c = mb_cptr2char_adv(&p); - if (c == '/') - headc = 0; - else { - if (headc == 0) - headc = c; - - // Characters above 255 don't fit in sl_map_array[], put them in - // the hash table. Each entry is the char, a NUL the headchar and - // a NUL. - if (c >= 256) { - int cl = mb_char2len(c); - int headcl = mb_char2len(headc); - char_u *b; - hash_T hash; - hashitem_T *hi; - - b = xmalloc(cl + headcl + 2); - mb_char2bytes(c, b); - b[cl] = NUL; - mb_char2bytes(headc, b + cl + 1); - b[cl + 1 + headcl] = NUL; - hash = hash_hash(b); - hi = hash_lookup(&lp->sl_map_hash, b, hash); - if (HASHITEM_EMPTY(hi)) - hash_add_item(&lp->sl_map_hash, hi, b, hash); - else { - // This should have been checked when generating the .spl - // file. - EMSG(_("E783: duplicate char in MAP entry")); - xfree(b); - } - } else - lp->sl_map_array[c] = headc; - } - } -} - // Returns true if "c1" and "c2" are similar characters according to the MAP // lines in the .aff file. static bool similar_chars(slang_T *slang, int c1, int c2) @@ -11503,7 +5604,7 @@ static void add_suggestion ( suginfo_T *su, garray_T *gap, // either su_ga or su_sga - char_u *goodword, + const char_u *goodword, int badlenarg, // len of bad word replaced with "goodword" int score, int altscore, @@ -11517,13 +5618,11 @@ add_suggestion ( int badlen; // len of bad word changed suggest_T *stp; suggest_T new_sug; - int i; - char_u *pgood, *pbad; // Minimize "badlen" for consistency. Avoids that changing "the the" to // "thee the" is added next to changing the first "the" the "thee". - pgood = goodword + STRLEN(goodword); - pbad = su->su_badptr + badlenarg; + const char_u *pgood = goodword + STRLEN(goodword); + char_u *pbad = su->su_badptr + badlenarg; for (;; ) { goodlen = (int)(pgood - goodword); badlen = (int)(pbad - su->su_badptr); @@ -11543,9 +5642,10 @@ add_suggestion ( // the first "the" to itself. return; - if (GA_EMPTY(gap)) + int i; + if (GA_EMPTY(gap)) { i = -1; - else { + } else { // Check if the word is already there. Also check the length that is // being replaced "thes," -> "these" is a different suggestion from // "thes" -> "these". @@ -11656,9 +5756,10 @@ static void add_banned(suginfo_T *su, char_u *word) hashitem_T *hi; hash = hash_hash(word); - hi = hash_lookup(&su->su_banned, word, hash); + const size_t word_len = STRLEN(word); + hi = hash_lookup(&su->su_banned, (const char *)word, word_len, hash); if (HASHITEM_EMPTY(hi)) { - s = vim_strsave(word); + s = xmemdupz(word, word_len); hash_add_item(&su->su_banned, hi, s, hash); } } @@ -11743,46 +5844,49 @@ cleanup_suggestions ( return maxscore; } -// Soundfold a string, for soundfold(). -// Result is in allocated memory, NULL for an error. -char_u *eval_soundfold(char_u *word) +/// Soundfold a string, for soundfold() +/// +/// @param[in] word Word to soundfold. +/// +/// @return [allocated] soundfolded string or NULL in case of error. May return +/// copy of the input string if soundfolding is not +/// supported by any of the languages in &spellang. +char *eval_soundfold(const char *const word) + FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL { - langp_T *lp; - char_u sound[MAXWLEN]; - if (curwin->w_p_spell && *curwin->w_s->b_p_spl != NUL) { // Use the sound-folding of the first language that supports it. - for (int lpi = 0; lpi < curwin->w_s->b_langp.ga_len; ++lpi) { - lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi); + for (int lpi = 0; lpi < curwin->w_s->b_langp.ga_len; lpi++) { + langp_T *const lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi); if (!GA_EMPTY(&lp->lp_slang->sl_sal)) { // soundfold the word - spell_soundfold(lp->lp_slang, word, false, sound); - return vim_strsave(sound); + char_u sound[MAXWLEN]; + spell_soundfold(lp->lp_slang, (char_u *)word, false, sound); + return xstrdup((const char *)sound); } } } // No language with sound folding, return word as-is. - return vim_strsave(word); + return xstrdup(word); } -// Turn "inword" into its sound-a-like equivalent in "res[MAXWLEN]". -// -// There are many ways to turn a word into a sound-a-like representation. The -// oldest is Soundex (1918!). A nice overview can be found in "Approximate -// swedish name matching - survey and test of different algorithms" by Klas -// Erikson. -// -// We support two methods: -// 1. SOFOFROM/SOFOTO do a simple character mapping. -// 2. SAL items define a more advanced sound-folding (and much slower). -static void -spell_soundfold ( - slang_T *slang, - char_u *inword, - bool folded, // "inword" is already case-folded - char_u *res -) +/// Turn "inword" into its sound-a-like equivalent in "res[MAXWLEN]". +/// +/// There are many ways to turn a word into a sound-a-like representation. The +/// oldest is Soundex (1918!). A nice overview can be found in "Approximate +/// swedish name matching - survey and test of different algorithms" by Klas +/// Erikson. +/// +/// We support two methods: +/// 1. SOFOFROM/SOFOTO do a simple character mapping. +/// 2. SAL items define a more advanced sound-folding (and much slower). +/// +/// @param[in] slang +/// @param[in] inword word to soundfold +/// @param[in] folded whether inword is already case-folded +/// @param[in,out] res destination for soundfolded word +void spell_soundfold(slang_T *slang, char_u *inword, bool folded, char_u *res) { char_u fword[MAXWLEN]; char_u *word; @@ -11821,12 +5925,12 @@ static void spell_soundfold_sofo(slang_T *slang, char_u *inword, char_u *res) // The sl_sal_first[] table contains the translation for chars up to // 255, sl_sal the rest. for (s = inword; *s != NUL; ) { - c = mb_cptr2char_adv(&s); - if (enc_utf8 ? utf_class(c) == 0 : ascii_iswhite(c)) + c = mb_cptr2char_adv((const char_u **)&s); + if (enc_utf8 ? utf_class(c) == 0 : ascii_iswhite(c)) { c = ' '; - else if (c < 256) + } else if (c < 256) { c = slang->sl_sal_first[c]; - else { + } else { ip = ((int **)slang->sl_sal.ga_data)[c & 0xff]; if (ip == NULL) // empty list, can't match c = NUL; @@ -12111,9 +6215,7 @@ static void spell_soundfold_wsal(slang_T *slang, char_u *inword, char_u *res) int word[MAXWLEN]; int wres[MAXWLEN]; int l; - char_u *s; int *ws; - char_u *t; int *pf; int i, j, z; int reslen; @@ -12133,9 +6235,9 @@ static void spell_soundfold_wsal(slang_T *slang, char_u *inword, char_u *res) // Remove accents, if wanted. We actually remove all non-word characters. // But keep white space. wordlen = 0; - for (s = inword; *s != NUL; ) { - t = s; - c = mb_cptr2char_adv(&s); + for (const char_u *s = inword; *s != NUL; ) { + const char_u *t = s; + c = mb_cptr2char_adv((const char_u **)&s); if (slang->sl_rem_accents) { if (enc_utf8 ? utf_class(c) == 0 : ascii_iswhite(c)) { if (did_white) @@ -12144,8 +6246,9 @@ static void spell_soundfold_wsal(slang_T *slang, char_u *inword, char_u *res) did_white = true; } else { did_white = false; - if (!spell_iswordp_nmw(t, curwin)) + if (!spell_iswordp_nmw(t, curwin)) { continue; + } } } word[wordlen++] = c; @@ -12192,7 +6295,7 @@ static void spell_soundfold_wsal(slang_T *slang, char_u *inword, char_u *res) continue; ++k; } - s = smp[n].sm_rules; + char_u *s = smp[n].sm_rules; pri = 5; // default priority p0 = *s; @@ -12591,25 +6694,30 @@ soundalike_score ( // support multi-byte characters. static int spell_edit_score(slang_T *slang, char_u *badword, char_u *goodword) { - int *cnt; - int badlen, goodlen; // lengths including NUL + int *cnt; int j, i; int t; int bc, gc; int pbc, pgc; - char_u *p; int wbadword[MAXWLEN]; int wgoodword[MAXWLEN]; const bool l_has_mbyte = has_mbyte; + // Lengths with NUL. + int badlen; + int goodlen; if (l_has_mbyte) { // Get the characters from the multi-byte strings and put them in an // int array for easy access. - for (p = badword, badlen = 0; *p != NUL; ) + badlen = 0; + for (const char_u *p = badword; *p != NUL; ) { wbadword[badlen++] = mb_cptr2char_adv(&p); + } wbadword[badlen++] = 0; - for (p = goodword, goodlen = 0; *p != NUL; ) + goodlen = 0; + for (const char_u *p = goodword; *p != NUL; ) { wgoodword[goodlen++] = mb_cptr2char_adv(&p); + } wgoodword[goodlen++] = 0; } else { badlen = (int)STRLEN(badword) + 1; @@ -12843,19 +6951,20 @@ static int spell_edit_score_limit_w(slang_T *slang, char_u *badword, char_u *goo int score_off; int minscore; int round; - char_u *p; int wbadword[MAXWLEN]; int wgoodword[MAXWLEN]; // Get the characters from the multi-byte strings and put them in an // int array for easy access. bi = 0; - for (p = badword; *p != NUL; ) + for (const char_u *p = badword; *p != NUL; ) { wbadword[bi++] = mb_cptr2char_adv(&p); + } wbadword[bi++] = 0; gi = 0; - for (p = goodword; *p != NUL; ) + for (const char_u *p = goodword; *p != NUL; ) { wgoodword[gi++] = mb_cptr2char_adv(&p); + } wgoodword[gi++] = 0; // The idea is to go from start to end over the words. So long as @@ -12990,19 +7099,17 @@ pop: // ":spellinfo" void ex_spellinfo(exarg_T *eap) { - langp_T *lp; - char_u *p; - - if (no_spell_checking(curwin)) + if (no_spell_checking(curwin)) { return; + } msg_start(); - for (int lpi = 0; lpi < curwin->w_s->b_langp.ga_len && !got_int; ++lpi) { - lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi); - msg_puts((char_u *)"file: "); - msg_puts(lp->lp_slang->sl_fname); + for (int lpi = 0; lpi < curwin->w_s->b_langp.ga_len && !got_int; lpi++) { + langp_T *const lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi); + msg_puts("file: "); + msg_puts((const char *)lp->lp_slang->sl_fname); msg_putchar('\n'); - p = lp->lp_slang->sl_info; + const char *const p = (const char *)lp->lp_slang->sl_info; if (p != NULL) { msg_puts(p); msg_putchar('\n'); @@ -13023,20 +7130,22 @@ void ex_spelldump(exarg_T *eap) char_u *spl; long dummy; - if (no_spell_checking(curwin)) + if (no_spell_checking(curwin)) { return; - get_option_value((char_u*)"spl", &dummy, &spl, OPT_LOCAL); + } + get_option_value((char_u *)"spl", &dummy, &spl, OPT_LOCAL); // Create a new empty buffer in a new window. do_cmdline_cmd("new"); // enable spelling locally in the new window - set_option_value((char_u*)"spell", true, (char_u*)"", OPT_LOCAL); - set_option_value((char_u*)"spl", dummy, spl, OPT_LOCAL); + set_option_value("spell", true, "", OPT_LOCAL); + set_option_value("spl", dummy, (char *)spl, OPT_LOCAL); xfree(spl); - if (!bufempty() || !buf_valid(curbuf)) + if (!bufempty()) { return; + } spell_dump_compl(NULL, 0, NULL, eap->forceit ? DUMPFLAG_COUNT : 0); diff --git a/src/nvim/spell.h b/src/nvim/spell.h index 3a03cb2ef6..ad66df4c5d 100644 --- a/src/nvim/spell.h +++ b/src/nvim/spell.h @@ -3,6 +3,10 @@ #include <stdbool.h> +#include "nvim/spell_defs.h" +#include "nvim/ex_cmds_defs.h" +#include "nvim/globals.h" + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "spell.h.generated.h" #endif diff --git a/src/nvim/spell_defs.h b/src/nvim/spell_defs.h new file mode 100644 index 0000000000..ddd54c724e --- /dev/null +++ b/src/nvim/spell_defs.h @@ -0,0 +1,287 @@ +#ifndef NVIM_SPELL_DEFS_H +#define NVIM_SPELL_DEFS_H + +#include <stdbool.h> +#include <stdint.h> + +#include "nvim/buffer_defs.h" +#include "nvim/garray.h" +#include "nvim/regexp_defs.h" +#include "nvim/types.h" + +#define MAXWLEN 254 // Assume max. word len is this many bytes. + // Some places assume a word length fits in a + // byte, thus it can't be above 255. + +// Type used for indexes in the word tree need to be at least 4 bytes. If int +// is 8 bytes we could use something smaller, but what? +typedef int idx_T; + +# define SPL_FNAME_TMPL "%s.%s.spl" +# define SPL_FNAME_ADD ".add." +# define SPL_FNAME_ASCII ".ascii." + +// Flags used for a word. Only the lowest byte can be used, the region byte +// comes above it. +#define WF_REGION 0x01 // region byte follows +#define WF_ONECAP 0x02 // word with one capital (or all capitals) +#define WF_ALLCAP 0x04 // word must be all capitals +#define WF_RARE 0x08 // rare word +#define WF_BANNED 0x10 // bad word +#define WF_AFX 0x20 // affix ID follows +#define WF_FIXCAP 0x40 // keep-case word, allcap not allowed +#define WF_KEEPCAP 0x80 // keep-case word + +// for <flags2>, shifted up one byte to be used in wn_flags +#define WF_HAS_AFF 0x0100 // word includes affix +#define WF_NEEDCOMP 0x0200 // word only valid in compound +#define WF_NOSUGGEST 0x0400 // word not to be suggested +#define WF_COMPROOT 0x0800 // already compounded word, COMPOUNDROOT +#define WF_NOCOMPBEF 0x1000 // no compounding before this word +#define WF_NOCOMPAFT 0x2000 // no compounding after this word + +// flags for <pflags> +#define WFP_RARE 0x01 // rare prefix +#define WFP_NC 0x02 // prefix is not combining +#define WFP_UP 0x04 // to-upper prefix +#define WFP_COMPPERMIT 0x08 // prefix with COMPOUNDPERMITFLAG +#define WFP_COMPFORBID 0x10 // prefix with COMPOUNDFORBIDFLAG + +// Flags for postponed prefixes in "sl_pidxs". Must be above affixID (one +// byte) and prefcondnr (two bytes). +#define WF_RAREPFX (WFP_RARE << 24) // rare postponed prefix +#define WF_PFX_NC (WFP_NC << 24) // non-combining postponed prefix +#define WF_PFX_UP (WFP_UP << 24) // to-upper postponed prefix +#define WF_PFX_COMPPERMIT (WFP_COMPPERMIT << 24) // postponed prefix with + // COMPOUNDPERMITFLAG +#define WF_PFX_COMPFORBID (WFP_COMPFORBID << 24) // postponed prefix with + // COMPOUNDFORBIDFLAG + + +// flags for <compoptions> +#define COMP_CHECKDUP 1 // CHECKCOMPOUNDDUP +#define COMP_CHECKREP 2 // CHECKCOMPOUNDREP +#define COMP_CHECKCASE 4 // CHECKCOMPOUNDCASE +#define COMP_CHECKTRIPLE 8 // CHECKCOMPOUNDTRIPLE + +// Info from "REP", "REPSAL" and "SAL" entries in ".aff" file used in si_rep, +// si_repsal, sl_rep, and si_sal. Not for sl_sal! +// One replacement: from "ft_from" to "ft_to". +typedef struct fromto_S { + char_u *ft_from; + char_u *ft_to; +} fromto_T; + +// Info from "SAL" entries in ".aff" file used in sl_sal. +// The info is split for quick processing by spell_soundfold(). +// Note that "sm_oneof" and "sm_rules" point into sm_lead. +typedef struct salitem_S { + char_u *sm_lead; // leading letters + int sm_leadlen; // length of "sm_lead" + char_u *sm_oneof; // letters from () or NULL + char_u *sm_rules; // rules like ^, $, priority + char_u *sm_to; // replacement. + int *sm_lead_w; // wide character copy of "sm_lead" + int *sm_oneof_w; // wide character copy of "sm_oneof" + int *sm_to_w; // wide character copy of "sm_to" +} salitem_T; + +typedef int salfirst_T; + +// Values for SP_*ERROR are negative, positive values are used by +// read_cnt_string(). +#define SP_TRUNCERROR -1 // spell file truncated error +#define SP_FORMERROR -2 // format error in spell file +#define SP_OTHERERROR -3 // other error while reading spell file + +// Structure used to store words and other info for one language, loaded from +// a .spl file. +// The main access is through the tree in "sl_fbyts/sl_fidxs", storing the +// case-folded words. "sl_kbyts/sl_kidxs" is for keep-case words. +// +// The "byts" array stores the possible bytes in each tree node, preceded by +// the number of possible bytes, sorted on byte value: +// <len> <byte1> <byte2> ... +// The "idxs" array stores the index of the child node corresponding to the +// byte in "byts". +// Exception: when the byte is zero, the word may end here and "idxs" holds +// the flags, region mask and affixID for the word. There may be several +// zeros in sequence for alternative flag/region/affixID combinations. +typedef struct slang_S slang_T; + +struct slang_S { + slang_T *sl_next; // next language + char_u *sl_name; // language name "en", "en.rare", "nl", etc. + char_u *sl_fname; // name of .spl file + bool sl_add; // true if it's a .add file. + + char_u *sl_fbyts; // case-folded word bytes + idx_T *sl_fidxs; // case-folded word indexes + char_u *sl_kbyts; // keep-case word bytes + idx_T *sl_kidxs; // keep-case word indexes + char_u *sl_pbyts; // prefix tree word bytes + idx_T *sl_pidxs; // prefix tree word indexes + + char_u *sl_info; // infotext string or NULL + + char_u sl_regions[17]; // table with up to 8 region names plus NUL + + char_u *sl_midword; // MIDWORD string or NULL + + hashtab_T sl_wordcount; // hashtable with word count, wordcount_T + + int sl_compmax; // COMPOUNDWORDMAX (default: MAXWLEN) + int sl_compminlen; // COMPOUNDMIN (default: 0) + int sl_compsylmax; // COMPOUNDSYLMAX (default: MAXWLEN) + int sl_compoptions; // COMP_* flags + garray_T sl_comppat; // CHECKCOMPOUNDPATTERN items + regprog_T *sl_compprog; // COMPOUNDRULE turned into a regexp progrm + // (NULL when no compounding) + char_u *sl_comprules; // all COMPOUNDRULE concatenated (or NULL) + char_u *sl_compstartflags; // flags for first compound word + char_u *sl_compallflags; // all flags for compound words + bool sl_nobreak; // When true: no spaces between words + char_u *sl_syllable; // SYLLABLE repeatable chars or NULL + garray_T sl_syl_items; // syllable items + + int sl_prefixcnt; // number of items in "sl_prefprog" + regprog_T **sl_prefprog; // table with regprogs for prefixes + + garray_T sl_rep; // list of fromto_T entries from REP lines + int16_t sl_rep_first[256]; // indexes where byte first appears, -1 if + // there is none + garray_T sl_sal; // list of salitem_T entries from SAL lines + salfirst_T sl_sal_first[256]; // indexes where byte first appears, -1 if + // there is none + bool sl_followup; // SAL followup + bool sl_collapse; // SAL collapse_result + bool sl_rem_accents; // SAL remove_accents + bool sl_sofo; // SOFOFROM and SOFOTO instead of SAL items: + // "sl_sal_first" maps chars, when has_mbyte + // "sl_sal" is a list of wide char lists. + garray_T sl_repsal; // list of fromto_T entries from REPSAL lines + int16_t sl_repsal_first[256]; // sl_rep_first for REPSAL lines + bool sl_nosplitsugs; // don't suggest splitting a word + bool sl_nocompoundsugs; // don't suggest compounding + + // Info from the .sug file. Loaded on demand. + time_t sl_sugtime; // timestamp for .sug file + char_u *sl_sbyts; // soundfolded word bytes + idx_T *sl_sidxs; // soundfolded word indexes + buf_T *sl_sugbuf; // buffer with word number table + bool sl_sugloaded; // true when .sug file was loaded or failed to + // load + + bool sl_has_map; // true, if there is a MAP line + hashtab_T sl_map_hash; // MAP for multi-byte chars + int sl_map_array[256]; // MAP for first 256 chars + hashtab_T sl_sounddone; // table with soundfolded words that have + // handled, see add_sound_suggest() +}; + +// Structure used in "b_langp", filled from 'spelllang'. +typedef struct langp_S { + slang_T *lp_slang; // info for this language + slang_T *lp_sallang; // language used for sound folding or NULL + slang_T *lp_replang; // language used for REP items or NULL + int lp_region; // bitmask for region or REGION_ALL +} langp_T; + +#define LANGP_ENTRY(ga, i) (((langp_T *)(ga).ga_data) + (i)) + +#define VIMSUGMAGIC "VIMsug" // string at start of Vim .sug file +#define VIMSUGMAGICL 6 +#define VIMSUGVERSION 1 + +#define REGION_ALL 0xff // word valid in all regions + +// The tables used for recognizing word characters according to spelling. +// These are only used for the first 256 characters of 'encoding'. +typedef struct { + bool st_isw[256]; // flags: is word char + bool st_isu[256]; // flags: is uppercase char + char_u st_fold[256]; // chars: folded case + char_u st_upper[256]; // chars: upper case +} spelltab_T; + +// For finding suggestions: At each node in the tree these states are tried: +typedef enum { + STATE_START = 0, // At start of node check for NUL bytes (goodword + // ends); if badword ends there is a match, otherwise + // try splitting word. + STATE_NOPREFIX, // try without prefix + STATE_SPLITUNDO, // Undo splitting. + STATE_ENDNUL, // Past NUL bytes at start of the node. + STATE_PLAIN, // Use each byte of the node. + STATE_DEL, // Delete a byte from the bad word. + STATE_INS_PREP, // Prepare for inserting bytes. + STATE_INS, // Insert a byte in the bad word. + STATE_SWAP, // Swap two bytes. + STATE_UNSWAP, // Undo swap two characters. + STATE_SWAP3, // Swap two characters over three. + STATE_UNSWAP3, // Undo Swap two characters over three. + STATE_UNROT3L, // Undo rotate three characters left + STATE_UNROT3R, // Undo rotate three characters right + STATE_REP_INI, // Prepare for using REP items. + STATE_REP, // Use matching REP items from the .aff file. + STATE_REP_UNDO, // Undo a REP item replacement. + STATE_FINAL // End of this node. +} state_T; + +// Struct to keep the state at each level in suggest_try_change(). +typedef struct trystate_S { + state_T ts_state; // state at this level, STATE_ + int ts_score; // score + idx_T ts_arridx; // index in tree array, start of node + short ts_curi; // index in list of child nodes + char_u ts_fidx; // index in fword[], case-folded bad word + char_u ts_fidxtry; // ts_fidx at which bytes may be changed + char_u ts_twordlen; // valid length of tword[] + char_u ts_prefixdepth; // stack depth for end of prefix or + // PFD_PREFIXTREE or PFD_NOPREFIX + char_u ts_flags; // TSF_ flags + char_u ts_tcharlen; // number of bytes in tword character + char_u ts_tcharidx; // current byte index in tword character + char_u ts_isdiff; // DIFF_ values + char_u ts_fcharstart; // index in fword where badword char started + char_u ts_prewordlen; // length of word in "preword[]" + char_u ts_splitoff; // index in "tword" after last split + char_u ts_splitfidx; // "ts_fidx" at word split + char_u ts_complen; // nr of compound words used + char_u ts_compsplit; // index for "compflags" where word was spit + char_u ts_save_badflags; // su_badflags saved here + char_u ts_delidx; // index in fword for char that was deleted, + // valid when "ts_flags" has TSF_DIDDEL +} trystate_T; + +// Use our own character-case definitions, because the current locale may +// differ from what the .spl file uses. +// These must not be called with negative number! +#include <wchar.h> // for towupper() and towlower() +// Multi-byte implementation. For Unicode we can call utf_*(), but don't do +// that for ASCII, because we don't want to use 'casemap' here. Otherwise use +// the "w" library function for characters above 255. +#define SPELL_TOFOLD(c) (enc_utf8 && (c) >= 128 ? utf_fold(c) \ + : (c) < \ + 256 ? (int)spelltab.st_fold[c] : (int)towlower(c)) + +#define SPELL_TOUPPER(c) (enc_utf8 && (c) >= 128 ? mb_toupper(c) \ + : (c) < \ + 256 ? (int)spelltab.st_upper[c] : (int)towupper(c)) + +#define SPELL_ISUPPER(c) (enc_utf8 && (c) >= 128 ? mb_isupper(c) \ + : (c) < 256 ? spelltab.st_isu[c] : iswupper(c)) + +// First language that is loaded, start of the linked list of loaded +// languages. +extern slang_T *first_lang; + +// file used for "zG" and "zW" +extern char_u *int_wordlist; + +extern spelltab_T spelltab; +extern int did_set_spelltab; + +extern char *e_format; + +#endif // NVIM_SPELL_DEFS_H diff --git a/src/nvim/spellfile.c b/src/nvim/spellfile.c new file mode 100644 index 0000000000..1f7f616782 --- /dev/null +++ b/src/nvim/spellfile.c @@ -0,0 +1,5741 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + +// spellfile.c: code for reading and writing spell files. +// +// See spell.c for information about spell checking. + +// Vim spell file format: <HEADER> +// <SECTIONS> +// <LWORDTREE> +// <KWORDTREE> +// <PREFIXTREE> +// +// <HEADER>: <fileID> <versionnr> +// +// <fileID> 8 bytes "VIMspell" +// <versionnr> 1 byte VIMSPELLVERSION +// +// +// Sections make it possible to add information to the .spl file without +// making it incompatible with previous versions. There are two kinds of +// sections: +// 1. Not essential for correct spell checking. E.g. for making suggestions. +// These are skipped when not supported. +// 2. Optional information, but essential for spell checking when present. +// E.g. conditions for affixes. When this section is present but not +// supported an error message is given. +// +// <SECTIONS>: <section> ... <sectionend> +// +// <section>: <sectionID> <sectionflags> <sectionlen> (section contents) +// +// <sectionID> 1 byte number from 0 to 254 identifying the section +// +// <sectionflags> 1 byte SNF_REQUIRED: this section is required for correct +// spell checking +// +// <sectionlen> 4 bytes length of section contents, MSB first +// +// <sectionend> 1 byte SN_END +// +// +// sectionID == SN_INFO: <infotext> +// <infotext> N bytes free format text with spell file info (version, +// website, etc) +// +// sectionID == SN_REGION: <regionname> ... +// <regionname> 2 bytes Up to 8 region names: ca, au, etc. Lower case. +// First <regionname> is region 1. +// +// sectionID == SN_CHARFLAGS: <charflagslen> <charflags> +// <folcharslen> <folchars> +// <charflagslen> 1 byte Number of bytes in <charflags> (should be 128). +// <charflags> N bytes List of flags (first one is for character 128): +// 0x01 word character CF_WORD +// 0x02 upper-case character CF_UPPER +// <folcharslen> 2 bytes Number of bytes in <folchars>. +// <folchars> N bytes Folded characters, first one is for character 128. +// +// sectionID == SN_MIDWORD: <midword> +// <midword> N bytes Characters that are word characters only when used +// in the middle of a word. +// +// sectionID == SN_PREFCOND: <prefcondcnt> <prefcond> ... +// <prefcondcnt> 2 bytes Number of <prefcond> items following. +// <prefcond> : <condlen> <condstr> +// <condlen> 1 byte Length of <condstr>. +// <condstr> N bytes Condition for the prefix. +// +// sectionID == SN_REP: <repcount> <rep> ... +// <repcount> 2 bytes number of <rep> items, MSB first. +// <rep> : <repfromlen> <repfrom> <reptolen> <repto> +// <repfromlen> 1 byte length of <repfrom> +// <repfrom> N bytes "from" part of replacement +// <reptolen> 1 byte length of <repto> +// <repto> N bytes "to" part of replacement +// +// sectionID == SN_REPSAL: <repcount> <rep> ... +// just like SN_REP but for soundfolded words +// +// sectionID == SN_SAL: <salflags> <salcount> <sal> ... +// <salflags> 1 byte flags for soundsalike conversion: +// SAL_F0LLOWUP +// SAL_COLLAPSE +// SAL_REM_ACCENTS +// <salcount> 2 bytes number of <sal> items following +// <sal> : <salfromlen> <salfrom> <saltolen> <salto> +// <salfromlen> 1 byte length of <salfrom> +// <salfrom> N bytes "from" part of soundsalike +// <saltolen> 1 byte length of <salto> +// <salto> N bytes "to" part of soundsalike +// +// sectionID == SN_SOFO: <sofofromlen> <sofofrom> <sofotolen> <sofoto> +// <sofofromlen> 2 bytes length of <sofofrom> +// <sofofrom> N bytes "from" part of soundfold +// <sofotolen> 2 bytes length of <sofoto> +// <sofoto> N bytes "to" part of soundfold +// +// sectionID == SN_SUGFILE: <timestamp> +// <timestamp> 8 bytes time in seconds that must match with .sug file +// +// sectionID == SN_NOSPLITSUGS: nothing +// +// sectionID == SN_NOCOMPOUNDSUGS: nothing +// +// sectionID == SN_WORDS: <word> ... +// <word> N bytes NUL terminated common word +// +// sectionID == SN_MAP: <mapstr> +// <mapstr> N bytes String with sequences of similar characters, +// separated by slashes. +// +// sectionID == SN_COMPOUND: <compmax> <compminlen> <compsylmax> <compoptions> +// <comppatcount> <comppattern> ... <compflags> +// <compmax> 1 byte Maximum nr of words in compound word. +// <compminlen> 1 byte Minimal word length for compounding. +// <compsylmax> 1 byte Maximum nr of syllables in compound word. +// <compoptions> 2 bytes COMP_ flags. +// <comppatcount> 2 bytes number of <comppattern> following +// <compflags> N bytes Flags from COMPOUNDRULE items, separated by +// slashes. +// +// <comppattern>: <comppatlen> <comppattext> +// <comppatlen> 1 byte length of <comppattext> +// <comppattext> N bytes end or begin chars from CHECKCOMPOUNDPATTERN +// +// sectionID == SN_NOBREAK: (empty, its presence is what matters) +// +// sectionID == SN_SYLLABLE: <syllable> +// <syllable> N bytes String from SYLLABLE item. +// +// <LWORDTREE>: <wordtree> +// +// <KWORDTREE>: <wordtree> +// +// <PREFIXTREE>: <wordtree> +// +// +// <wordtree>: <nodecount> <nodedata> ... +// +// <nodecount> 4 bytes Number of nodes following. MSB first. +// +// <nodedata>: <siblingcount> <sibling> ... +// +// <siblingcount> 1 byte Number of siblings in this node. The siblings +// follow in sorted order. +// +// <sibling>: <byte> [ <nodeidx> <xbyte> +// | <flags> [<flags2>] [<region>] [<affixID>] +// | [<pflags>] <affixID> <prefcondnr> ] +// +// <byte> 1 byte Byte value of the sibling. Special cases: +// BY_NOFLAGS: End of word without flags and for all +// regions. +// For PREFIXTREE <affixID> and +// <prefcondnr> follow. +// BY_FLAGS: End of word, <flags> follow. +// For PREFIXTREE <pflags>, <affixID> +// and <prefcondnr> follow. +// BY_FLAGS2: End of word, <flags> and <flags2> +// follow. Not used in PREFIXTREE. +// BY_INDEX: Child of sibling is shared, <nodeidx> +// and <xbyte> follow. +// +// <nodeidx> 3 bytes Index of child for this sibling, MSB first. +// +// <xbyte> 1 byte Byte value of the sibling. +// +// <flags> 1 byte Bitmask of: +// WF_ALLCAP word must have only capitals +// WF_ONECAP first char of word must be capital +// WF_KEEPCAP keep-case word +// WF_FIXCAP keep-case word, all caps not allowed +// WF_RARE rare word +// WF_BANNED bad word +// WF_REGION <region> follows +// WF_AFX <affixID> follows +// +// <flags2> 1 byte Bitmask of: +// WF_HAS_AFF >> 8 word includes affix +// WF_NEEDCOMP >> 8 word only valid in compound +// WF_NOSUGGEST >> 8 word not used for suggestions +// WF_COMPROOT >> 8 word already a compound +// WF_NOCOMPBEF >> 8 no compounding before this word +// WF_NOCOMPAFT >> 8 no compounding after this word +// +// <pflags> 1 byte Bitmask of: +// WFP_RARE rare prefix +// WFP_NC non-combining prefix +// WFP_UP letter after prefix made upper case +// +// <region> 1 byte Bitmask for regions in which word is valid. When +// omitted it's valid in all regions. +// Lowest bit is for region 1. +// +// <affixID> 1 byte ID of affix that can be used with this word. In +// PREFIXTREE used for the required prefix ID. +// +// <prefcondnr> 2 bytes Prefix condition number, index in <prefcond> list +// from HEADER. +// +// All text characters are in 'encoding', but stored as single bytes. + +// Vim .sug file format: <SUGHEADER> +// <SUGWORDTREE> +// <SUGTABLE> +// +// <SUGHEADER>: <fileID> <versionnr> <timestamp> +// +// <fileID> 6 bytes "VIMsug" +// <versionnr> 1 byte VIMSUGVERSION +// <timestamp> 8 bytes timestamp that must match with .spl file +// +// +// <SUGWORDTREE>: <wordtree> (see above, no flags or region used) +// +// +// <SUGTABLE>: <sugwcount> <sugline> ... +// +// <sugwcount> 4 bytes number of <sugline> following +// +// <sugline>: <sugnr> ... NUL +// +// <sugnr>: X bytes word number that results in this soundfolded word, +// stored as an offset to the previous number in as +// few bytes as possible, see offset2bytes()) + +#include <stdio.h> +#include <stdint.h> +#include <wctype.h> +#include <strings.h> + +#include "nvim/vim.h" +#include "nvim/spell_defs.h" +#include "nvim/ascii.h" +#include "nvim/buffer.h" +#include "nvim/charset.h" +#include "nvim/ex_cmds2.h" +#include "nvim/fileio.h" +#include "nvim/memory.h" +#include "nvim/memline.h" +#include "nvim/misc1.h" +#include "nvim/option.h" +#include "nvim/os/os.h" +#include "nvim/path.h" +#include "nvim/regexp.h" +#include "nvim/screen.h" +#include "nvim/spell.h" +#include "nvim/spellfile.h" +#include "nvim/ui.h" +#include "nvim/undo.h" + +#ifndef UNIX // it's in os/unix_defs.h for Unix +# include <time.h> // for time_t +#endif + +// Special byte values for <byte>. Some are only used in the tree for +// postponed prefixes, some only in the other trees. This is a bit messy... +#define BY_NOFLAGS 0 // end of word without flags or region; for + // postponed prefix: no <pflags> +#define BY_INDEX 1 // child is shared, index follows +#define BY_FLAGS 2 // end of word, <flags> byte follows; for + // postponed prefix: <pflags> follows +#define BY_FLAGS2 3 // end of word, <flags> and <flags2> bytes + // follow; never used in prefix tree +#define BY_SPECIAL BY_FLAGS2 // highest special byte value + +// Flags used in .spl file for soundsalike flags. +#define SAL_F0LLOWUP 1 +#define SAL_COLLAPSE 2 +#define SAL_REM_ACCENTS 4 + +#define VIMSPELLMAGIC "VIMspell" // string at start of Vim spell file +#define VIMSPELLMAGICL (sizeof(VIMSPELLMAGIC) - 1) +#define VIMSPELLVERSION 50 + +// Section IDs. Only renumber them when VIMSPELLVERSION changes! +#define SN_REGION 0 // <regionname> section +#define SN_CHARFLAGS 1 // charflags section +#define SN_MIDWORD 2 // <midword> section +#define SN_PREFCOND 3 // <prefcond> section +#define SN_REP 4 // REP items section +#define SN_SAL 5 // SAL items section +#define SN_SOFO 6 // soundfolding section +#define SN_MAP 7 // MAP items section +#define SN_COMPOUND 8 // compound words section +#define SN_SYLLABLE 9 // syllable section +#define SN_NOBREAK 10 // NOBREAK section +#define SN_SUGFILE 11 // timestamp for .sug file +#define SN_REPSAL 12 // REPSAL items section +#define SN_WORDS 13 // common words +#define SN_NOSPLITSUGS 14 // don't split word for suggestions +#define SN_INFO 15 // info section +#define SN_NOCOMPOUNDSUGS 16 // don't compound for suggestions +#define SN_END 255 // end of sections + +#define SNF_REQUIRED 1 // <sectionflags>: required section + +#define CF_WORD 0x01 +#define CF_UPPER 0x02 + +static char *e_spell_trunc = N_("E758: Truncated spell file"); +static char *e_afftrailing = N_("Trailing text in %s line %d: %s"); +static char *e_affname = N_("Affix name too long in %s line %d: %s"); +static char *e_affform = N_("E761: Format error in affix file FOL, LOW or UPP"); +static char *e_affrange = N_( + "E762: Character in FOL, LOW or UPP is out of range"); +static char *msg_compressing = N_("Compressing word tree..."); + +#define MAXLINELEN 500 // Maximum length in bytes of a line in a .aff + // and .dic file. +// Main structure to store the contents of a ".aff" file. +typedef struct afffile_S { + char_u *af_enc; // "SET", normalized, alloc'ed string or NULL + int af_flagtype; // AFT_CHAR, AFT_LONG, AFT_NUM or AFT_CAPLONG + unsigned af_rare; // RARE ID for rare word + unsigned af_keepcase; // KEEPCASE ID for keep-case word + unsigned af_bad; // BAD ID for banned word + unsigned af_needaffix; // NEEDAFFIX ID + unsigned af_circumfix; // CIRCUMFIX ID + unsigned af_needcomp; // NEEDCOMPOUND ID + unsigned af_comproot; // COMPOUNDROOT ID + unsigned af_compforbid; // COMPOUNDFORBIDFLAG ID + unsigned af_comppermit; // COMPOUNDPERMITFLAG ID + unsigned af_nosuggest; // NOSUGGEST ID + int af_pfxpostpone; // postpone prefixes without chop string and + // without flags + bool af_ignoreextra; // IGNOREEXTRA present + hashtab_T af_pref; // hashtable for prefixes, affheader_T + hashtab_T af_suff; // hashtable for suffixes, affheader_T + hashtab_T af_comp; // hashtable for compound flags, compitem_T +} afffile_T; + +#define AFT_CHAR 0 // flags are one character +#define AFT_LONG 1 // flags are two characters +#define AFT_CAPLONG 2 // flags are one or two characters +#define AFT_NUM 3 // flags are numbers, comma separated + +typedef struct affentry_S affentry_T; +// Affix entry from ".aff" file. Used for prefixes and suffixes. +struct affentry_S { + affentry_T *ae_next; // next affix with same name/number + char_u *ae_chop; // text to chop off basic word (can be NULL) + char_u *ae_add; // text to add to basic word (can be NULL) + char_u *ae_flags; // flags on the affix (can be NULL) + char_u *ae_cond; // condition (NULL for ".") + regprog_T *ae_prog; // regexp program for ae_cond or NULL + char ae_compforbid; // COMPOUNDFORBIDFLAG found + char ae_comppermit; // COMPOUNDPERMITFLAG found +}; + +# define AH_KEY_LEN 17 // 2 x 8 bytes + NUL + +// Affix header from ".aff" file. Used for af_pref and af_suff. +typedef struct affheader_S { + char_u ah_key[AH_KEY_LEN]; // key for hashtab == name of affix + unsigned ah_flag; // affix name as number, uses "af_flagtype" + int ah_newID; // prefix ID after renumbering; 0 if not used + int ah_combine; // suffix may combine with prefix + int ah_follows; // another affix block should be following + affentry_T *ah_first; // first affix entry +} affheader_T; + +#define HI2AH(hi) ((affheader_T *)(hi)->hi_key) + +// Flag used in compound items. +typedef struct compitem_S { + char_u ci_key[AH_KEY_LEN]; // key for hashtab == name of compound + unsigned ci_flag; // affix name as number, uses "af_flagtype" + int ci_newID; // affix ID after renumbering. +} compitem_T; + +#define HI2CI(hi) ((compitem_T *)(hi)->hi_key) + +// Structure that is used to store the items in the word tree. This avoids +// the need to keep track of each allocated thing, everything is freed all at +// once after ":mkspell" is done. +// Note: "sb_next" must be just before "sb_data" to make sure the alignment of +// "sb_data" is correct for systems where pointers must be aligned on +// pointer-size boundaries and sizeof(pointer) > sizeof(int) (e.g., Sparc). +#define SBLOCKSIZE 16000 // size of sb_data +typedef struct sblock_S sblock_T; +struct sblock_S { + int sb_used; // nr of bytes already in use + sblock_T *sb_next; // next block in list + char_u sb_data[1]; // data, actually longer +}; + +// A node in the tree. +typedef struct wordnode_S wordnode_T; +struct wordnode_S { + union { // shared to save space + char_u hashkey[6]; // the hash key, only used while compressing + int index; // index in written nodes (valid after first + // round) + } wn_u1; + union { // shared to save space + wordnode_T *next; // next node with same hash key + wordnode_T *wnode; // parent node that will write this node + } wn_u2; + wordnode_T *wn_child; // child (next byte in word) + wordnode_T *wn_sibling; // next sibling (alternate byte in word, + // always sorted) + int wn_refs; // Nr. of references to this node. Only + // relevant for first node in a list of + // siblings, in following siblings it is + // always one. + char_u wn_byte; // Byte for this node. NUL for word end + + // Info for when "wn_byte" is NUL. + // In PREFIXTREE "wn_region" is used for the prefcondnr. + // In the soundfolded word tree "wn_flags" has the MSW of the wordnr and + // "wn_region" the LSW of the wordnr. + char_u wn_affixID; // supported/required prefix ID or 0 + uint16_t wn_flags; // WF_ flags + short wn_region; // region mask + +#ifdef SPELL_PRINTTREE + int wn_nr; // sequence nr for printing +#endif +}; + +#define WN_MASK 0xffff // mask relevant bits of "wn_flags" + +#define HI2WN(hi) (wordnode_T *)((hi)->hi_key) + +// Info used while reading the spell files. +typedef struct spellinfo_S { + wordnode_T *si_foldroot; // tree with case-folded words + long si_foldwcount; // nr of words in si_foldroot + + wordnode_T *si_keeproot; // tree with keep-case words + long si_keepwcount; // nr of words in si_keeproot + + wordnode_T *si_prefroot; // tree with postponed prefixes + + long si_sugtree; // creating the soundfolding trie + + sblock_T *si_blocks; // memory blocks used + long si_blocks_cnt; // memory blocks allocated + int si_did_emsg; // TRUE when ran out of memory + + long si_compress_cnt; // words to add before lowering + // compression limit + wordnode_T *si_first_free; // List of nodes that have been freed during + // compression, linked by "wn_child" field. + long si_free_count; // number of nodes in si_first_free +#ifdef SPELL_PRINTTREE + int si_wordnode_nr; // sequence nr for nodes +#endif + buf_T *si_spellbuf; // buffer used to store soundfold word table + + int si_ascii; // handling only ASCII words + int si_add; // addition file + int si_clear_chartab; // when TRUE clear char tables + int si_region; // region mask + vimconv_T si_conv; // for conversion to 'encoding' + int si_memtot; // runtime memory used + int si_verbose; // verbose messages + int si_msg_count; // number of words added since last message + char_u *si_info; // info text chars or NULL + int si_region_count; // number of regions supported (1 when there + // are no regions) + char_u si_region_name[17]; // region names; used only if + // si_region_count > 1) + + garray_T si_rep; // list of fromto_T entries from REP lines + garray_T si_repsal; // list of fromto_T entries from REPSAL lines + garray_T si_sal; // list of fromto_T entries from SAL lines + char_u *si_sofofr; // SOFOFROM text + char_u *si_sofoto; // SOFOTO text + int si_nosugfile; // NOSUGFILE item found + int si_nosplitsugs; // NOSPLITSUGS item found + int si_nocompoundsugs; // NOCOMPOUNDSUGS item found + int si_followup; // soundsalike: ? + int si_collapse; // soundsalike: ? + hashtab_T si_commonwords; // hashtable for common words + time_t si_sugtime; // timestamp for .sug file + int si_rem_accents; // soundsalike: remove accents + garray_T si_map; // MAP info concatenated + char_u *si_midword; // MIDWORD chars or NULL + int si_compmax; // max nr of words for compounding + int si_compminlen; // minimal length for compounding + int si_compsylmax; // max nr of syllables for compounding + int si_compoptions; // COMP_ flags + garray_T si_comppat; // CHECKCOMPOUNDPATTERN items, each stored as + // a string + char_u *si_compflags; // flags used for compounding + char_u si_nobreak; // NOBREAK + char_u *si_syllable; // syllable string + garray_T si_prefcond; // table with conditions for postponed + // prefixes, each stored as a string + int si_newprefID; // current value for ah_newID + int si_newcompID; // current value for compound ID +} spellinfo_T; + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "spellfile.c.generated.h" +#endif + +/// Read n bytes from fd to buf, returning on errors +/// +/// @param[out] buf Buffer to read to, must be at least n bytes long. +/// @param[in] n Amount of bytes to read. +/// @param fd FILE* to read from. +/// @param exit_code Code to run before returning. +/// +/// @return Allows to proceed if everything is OK, returns SP_TRUNCERROR if +/// there are not enough bytes, returns SP_OTHERERROR if reading failed. +#define SPELL_READ_BYTES(buf, n, fd, exit_code) \ + do { \ + const size_t n__SPRB = (n); \ + FILE *const fd__SPRB = (fd); \ + char *const buf__SPRB = (buf); \ + const size_t read_bytes__SPRB = fread(buf__SPRB, 1, n__SPRB, fd__SPRB); \ + if (read_bytes__SPRB != n__SPRB) { \ + exit_code; \ + return feof(fd__SPRB) ? SP_TRUNCERROR : SP_OTHERERROR; \ + } \ + } while (0) + +/// Like #SPELL_READ_BYTES, but also error out if NUL byte was read +/// +/// @return Allows to proceed if everything is OK, returns SP_TRUNCERROR if +/// there are not enough bytes, returns SP_OTHERERROR if reading failed, +/// returns SP_FORMERROR if read out a NUL byte. +#define SPELL_READ_NONNUL_BYTES(buf, n, fd, exit_code) \ + do { \ + const size_t n__SPRNB = (n); \ + FILE *const fd__SPRNB = (fd); \ + char *const buf__SPRNB = (buf); \ + SPELL_READ_BYTES(buf__SPRNB, n__SPRNB, fd__SPRNB, exit_code); \ + if (memchr(buf__SPRNB, NUL, (size_t)n__SPRNB)) { \ + exit_code; \ + return SP_FORMERROR; \ + } \ + } while (0) + +/// Check that spell file starts with a magic string +/// +/// Does not check for version of the file. +/// +/// @param fd File to check. +/// +/// @return 0 in case of success, SP_TRUNCERROR if file contains not enough +/// bytes, SP_FORMERROR if it does not match magic string and +/// SP_OTHERERROR if reading file failed. +static inline int spell_check_magic_string(FILE *const fd) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_ALWAYS_INLINE +{ + char buf[VIMSPELLMAGICL]; + SPELL_READ_BYTES(buf, VIMSPELLMAGICL, fd, ;); + if (memcmp(buf, VIMSPELLMAGIC, VIMSPELLMAGICL) != 0) { + return SP_FORMERROR; + } + return 0; +} + +// Load one spell file and store the info into a slang_T. +// +// This is invoked in three ways: +// - From spell_load_cb() to load a spell file for the first time. "lang" is +// the language name, "old_lp" is NULL. Will allocate an slang_T. +// - To reload a spell file that was changed. "lang" is NULL and "old_lp" +// points to the existing slang_T. +// - Just after writing a .spl file; it's read back to produce the .sug file. +// "old_lp" is NULL and "lang" is NULL. Will allocate an slang_T. +// +// Returns the slang_T the spell file was loaded into. NULL for error. +slang_T * +spell_load_file ( + char_u *fname, + char_u *lang, + slang_T *old_lp, + bool silent // no error if file doesn't exist +) +{ + FILE *fd; + char_u *p; + int n; + int len; + char_u *save_sourcing_name = sourcing_name; + linenr_T save_sourcing_lnum = sourcing_lnum; + slang_T *lp = NULL; + int c = 0; + int res; + + fd = mch_fopen((char *)fname, "r"); + if (fd == NULL) { + if (!silent) + EMSG2(_(e_notopen), fname); + else if (p_verbose > 2) { + verbose_enter(); + smsg((char *)e_notopen, fname); + verbose_leave(); + } + goto endFAIL; + } + if (p_verbose > 2) { + verbose_enter(); + smsg(_("Reading spell file \"%s\""), fname); + verbose_leave(); + } + + if (old_lp == NULL) { + lp = slang_alloc(lang); + + // Remember the file name, used to reload the file when it's updated. + lp->sl_fname = vim_strsave(fname); + + // Check for .add.spl. + lp->sl_add = strstr((char *)path_tail(fname), SPL_FNAME_ADD) != NULL; + } else + lp = old_lp; + + // Set sourcing_name, so that error messages mention the file name. + sourcing_name = fname; + sourcing_lnum = 0; + + // <HEADER>: <fileID> + const int scms_ret = spell_check_magic_string(fd); + switch (scms_ret) { + case SP_FORMERROR: + case SP_TRUNCERROR: { + emsgf(_("E757: This does not look like a spell file")); + goto endFAIL; + } + case SP_OTHERERROR: { + emsgf(_("E5042: Failed to read spell file %s: %s"), + fname, strerror(ferror(fd))); + } + case 0: { + break; + } + } + c = getc(fd); // <versionnr> + if (c < VIMSPELLVERSION) { + EMSG(_("E771: Old spell file, needs to be updated")); + goto endFAIL; + } else if (c > VIMSPELLVERSION) { + EMSG(_("E772: Spell file is for newer version of Vim")); + goto endFAIL; + } + + + // <SECTIONS>: <section> ... <sectionend> + // <section>: <sectionID> <sectionflags> <sectionlen> (section contents) + for (;; ) { + n = getc(fd); // <sectionID> or <sectionend> + if (n == SN_END) + break; + c = getc(fd); // <sectionflags> + len = get4c(fd); // <sectionlen> + if (len < 0) + goto truncerr; + + res = 0; + switch (n) { + case SN_INFO: + lp->sl_info = READ_STRING(fd, len); // <infotext> + if (lp->sl_info == NULL) + goto endFAIL; + break; + + case SN_REGION: + res = read_region_section(fd, lp, len); + break; + + case SN_CHARFLAGS: + res = read_charflags_section(fd); + break; + + case SN_MIDWORD: + lp->sl_midword = READ_STRING(fd, len); // <midword> + if (lp->sl_midword == NULL) + goto endFAIL; + break; + + case SN_PREFCOND: + res = read_prefcond_section(fd, lp); + break; + + case SN_REP: + res = read_rep_section(fd, &lp->sl_rep, lp->sl_rep_first); + break; + + case SN_REPSAL: + res = read_rep_section(fd, &lp->sl_repsal, lp->sl_repsal_first); + break; + + case SN_SAL: + res = read_sal_section(fd, lp); + break; + + case SN_SOFO: + res = read_sofo_section(fd, lp); + break; + + case SN_MAP: + p = READ_STRING(fd, len); // <mapstr> + if (p == NULL) + goto endFAIL; + set_map_str(lp, p); + xfree(p); + break; + + case SN_WORDS: + res = read_words_section(fd, lp, len); + break; + + case SN_SUGFILE: + lp->sl_sugtime = get8ctime(fd); // <timestamp> + break; + + case SN_NOSPLITSUGS: + lp->sl_nosplitsugs = true; + break; + + case SN_NOCOMPOUNDSUGS: + lp->sl_nocompoundsugs = true; + break; + + case SN_COMPOUND: + res = read_compound(fd, lp, len); + break; + + case SN_NOBREAK: + lp->sl_nobreak = true; + break; + + case SN_SYLLABLE: + lp->sl_syllable = READ_STRING(fd, len); // <syllable> + if (lp->sl_syllable == NULL) + goto endFAIL; + if (init_syl_tab(lp) == FAIL) + goto endFAIL; + break; + + default: + // Unsupported section. When it's required give an error + // message. When it's not required skip the contents. + if (c & SNF_REQUIRED) { + EMSG(_("E770: Unsupported section in spell file")); + goto endFAIL; + } + while (--len >= 0) + if (getc(fd) < 0) + goto truncerr; + break; + } +someerror: + if (res == SP_FORMERROR) { + EMSG(_(e_format)); + goto endFAIL; + } + if (res == SP_TRUNCERROR) { +truncerr: + EMSG(_(e_spell_trunc)); + goto endFAIL; + } + if (res == SP_OTHERERROR) + goto endFAIL; + } + + // <LWORDTREE> + res = spell_read_tree(fd, &lp->sl_fbyts, &lp->sl_fidxs, false, 0); + if (res != 0) + goto someerror; + + // <KWORDTREE> + res = spell_read_tree(fd, &lp->sl_kbyts, &lp->sl_kidxs, false, 0); + if (res != 0) + goto someerror; + + // <PREFIXTREE> + res = spell_read_tree(fd, &lp->sl_pbyts, &lp->sl_pidxs, true, + lp->sl_prefixcnt); + if (res != 0) + goto someerror; + + // For a new file link it in the list of spell files. + if (old_lp == NULL && lang != NULL) { + lp->sl_next = first_lang; + first_lang = lp; + } + + goto endOK; + +endFAIL: + if (lang != NULL) + // truncating the name signals the error to spell_load_lang() + *lang = NUL; + if (lp != NULL && old_lp == NULL) + slang_free(lp); + lp = NULL; + +endOK: + if (fd != NULL) + fclose(fd); + sourcing_name = save_sourcing_name; + sourcing_lnum = save_sourcing_lnum; + + return lp; +} + +// Fill in the wordcount fields for a trie. +// Returns the total number of words. +static void tree_count_words(char_u *byts, idx_T *idxs) +{ + int depth; + idx_T arridx[MAXWLEN]; + int curi[MAXWLEN]; + int c; + idx_T n; + int wordcount[MAXWLEN]; + + arridx[0] = 0; + curi[0] = 1; + wordcount[0] = 0; + depth = 0; + while (depth >= 0 && !got_int) { + if (curi[depth] > byts[arridx[depth]]) { + // Done all bytes at this node, go up one level. + idxs[arridx[depth]] = wordcount[depth]; + if (depth > 0) + wordcount[depth - 1] += wordcount[depth]; + + --depth; + fast_breakcheck(); + } else { + // Do one more byte at this node. + n = arridx[depth] + curi[depth]; + ++curi[depth]; + + c = byts[n]; + if (c == 0) { + // End of word, count it. + ++wordcount[depth]; + + // Skip over any other NUL bytes (same word with different + // flags). + while (byts[n + 1] == 0) { + ++n; + ++curi[depth]; + } + } else { + // Normal char, go one level deeper to count the words. + ++depth; + arridx[depth] = idxs[n]; + curi[depth] = 1; + wordcount[depth] = 0; + } + } + } +} + +// Load the .sug files for languages that have one and weren't loaded yet. +void suggest_load_files(void) +{ + langp_T *lp; + slang_T *slang; + char_u *dotp; + FILE *fd; + char_u buf[MAXWLEN]; + int i; + time_t timestamp; + int wcount; + int wordnr; + garray_T ga; + int c; + + // Do this for all languages that support sound folding. + for (int lpi = 0; lpi < curwin->w_s->b_langp.ga_len; ++lpi) { + lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi); + slang = lp->lp_slang; + if (slang->sl_sugtime != 0 && !slang->sl_sugloaded) { + // Change ".spl" to ".sug" and open the file. When the file isn't + // found silently skip it. Do set "sl_sugloaded" so that we + // don't try again and again. + slang->sl_sugloaded = true; + + dotp = vim_strrchr(slang->sl_fname, '.'); + if (dotp == NULL || fnamecmp(dotp, ".spl") != 0) + continue; + STRCPY(dotp, ".sug"); + fd = mch_fopen((char *)slang->sl_fname, "r"); + if (fd == NULL) + goto nextone; + + // <SUGHEADER>: <fileID> <versionnr> <timestamp> + for (i = 0; i < VIMSUGMAGICL; ++i) + buf[i] = getc(fd); // <fileID> + if (STRNCMP(buf, VIMSUGMAGIC, VIMSUGMAGICL) != 0) { + EMSG2(_("E778: This does not look like a .sug file: %s"), + slang->sl_fname); + goto nextone; + } + c = getc(fd); // <versionnr> + if (c < VIMSUGVERSION) { + EMSG2(_("E779: Old .sug file, needs to be updated: %s"), + slang->sl_fname); + goto nextone; + } else if (c > VIMSUGVERSION) { + EMSG2(_("E780: .sug file is for newer version of Vim: %s"), + slang->sl_fname); + goto nextone; + } + + // Check the timestamp, it must be exactly the same as the one in + // the .spl file. Otherwise the word numbers won't match. + timestamp = get8ctime(fd); // <timestamp> + if (timestamp != slang->sl_sugtime) { + EMSG2(_("E781: .sug file doesn't match .spl file: %s"), + slang->sl_fname); + goto nextone; + } + + // <SUGWORDTREE>: <wordtree> + // Read the trie with the soundfolded words. + if (spell_read_tree(fd, &slang->sl_sbyts, &slang->sl_sidxs, + false, 0) != 0) { +someerror: + EMSG2(_("E782: error while reading .sug file: %s"), + slang->sl_fname); + slang_clear_sug(slang); + goto nextone; + } + + // <SUGTABLE>: <sugwcount> <sugline> ... + // + // Read the table with word numbers. We use a file buffer for + // this, because it's so much like a file with lines. Makes it + // possible to swap the info and save on memory use. + slang->sl_sugbuf = open_spellbuf(); + + // <sugwcount> + wcount = get4c(fd); + if (wcount < 0) + goto someerror; + + // Read all the wordnr lists into the buffer, one NUL terminated + // list per line. + ga_init(&ga, 1, 100); + for (wordnr = 0; wordnr < wcount; ++wordnr) { + ga.ga_len = 0; + for (;; ) { + c = getc(fd); // <sugline> + if (c < 0) { + goto someerror; + } + GA_APPEND(char_u, &ga, c); + if (c == NUL) + break; + } + if (ml_append_buf(slang->sl_sugbuf, (linenr_T)wordnr, + ga.ga_data, ga.ga_len, TRUE) == FAIL) + goto someerror; + } + ga_clear(&ga); + + // Need to put word counts in the word tries, so that we can find + // a word by its number. + tree_count_words(slang->sl_fbyts, slang->sl_fidxs); + tree_count_words(slang->sl_sbyts, slang->sl_sidxs); + +nextone: + if (fd != NULL) + fclose(fd); + STRCPY(dotp, ".spl"); + } + } +} + + +// Read a length field from "fd" in "cnt_bytes" bytes. +// Allocate memory, read the string into it and add a NUL at the end. +// Returns NULL when the count is zero. +// Sets "*cntp" to SP_*ERROR when there is an error, length of the result +// otherwise. +static char_u *read_cnt_string(FILE *fd, int cnt_bytes, int *cntp) +{ + int cnt = 0; + int i; + char_u *str; + + // read the length bytes, MSB first + for (i = 0; i < cnt_bytes; ++i) + cnt = (cnt << 8) + getc(fd); + if (cnt < 0) { + *cntp = SP_TRUNCERROR; + return NULL; + } + *cntp = cnt; + if (cnt == 0) + return NULL; // nothing to read, return NULL + + str = READ_STRING(fd, cnt); + if (str == NULL) + *cntp = SP_OTHERERROR; + return str; +} + +// Read SN_REGION: <regionname> ... +// Return SP_*ERROR flags. +static int read_region_section(FILE *fd, slang_T *lp, int len) +{ + if (len > 16) { + return SP_FORMERROR; + } + SPELL_READ_NONNUL_BYTES((char *)lp->sl_regions, (size_t)len, fd, ;); + lp->sl_regions[len] = NUL; + return 0; +} + +// Read SN_CHARFLAGS section: <charflagslen> <charflags> +// <folcharslen> <folchars> +// Return SP_*ERROR flags. +static int read_charflags_section(FILE *fd) +{ + char_u *flags; + char_u *fol; + int flagslen, follen; + + // <charflagslen> <charflags> + flags = read_cnt_string(fd, 1, &flagslen); + if (flagslen < 0) + return flagslen; + + // <folcharslen> <folchars> + fol = read_cnt_string(fd, 2, &follen); + if (follen < 0) { + xfree(flags); + return follen; + } + + // Set the word-char flags and fill SPELL_ISUPPER() table. + if (flags != NULL && fol != NULL) + set_spell_charflags(flags, flagslen, fol); + + xfree(flags); + xfree(fol); + + // When <charflagslen> is zero then <fcharlen> must also be zero. + if ((flags == NULL) != (fol == NULL)) + return SP_FORMERROR; + return 0; +} + +// Read SN_PREFCOND section. +// Return SP_*ERROR flags. +static int read_prefcond_section(FILE *fd, slang_T *lp) +{ + // <prefcondcnt> <prefcond> ... + const int cnt = get2c(fd); // <prefcondcnt> + if (cnt <= 0) { + return SP_FORMERROR; + } + + lp->sl_prefprog = xcalloc(cnt, sizeof(regprog_T *)); + lp->sl_prefixcnt = cnt; + + for (int i = 0; i < cnt; i++) { + // <prefcond> : <condlen> <condstr> + const int n = getc(fd); // <condlen> + if (n < 0 || n >= MAXWLEN) { + return SP_FORMERROR; + } + + // When <condlen> is zero we have an empty condition. Otherwise + // compile the regexp program used to check for the condition. + if (n > 0) { + char buf[MAXWLEN + 1]; + buf[0] = '^'; // always match at one position only + SPELL_READ_NONNUL_BYTES(buf + 1, (size_t)n, fd, ;); + buf[n + 1] = NUL; + lp->sl_prefprog[i] = vim_regcomp((char_u *)buf, RE_MAGIC | RE_STRING); + } + } + return 0; +} + +// Read REP or REPSAL items section from "fd": <repcount> <rep> ... +// Return SP_*ERROR flags. +static int read_rep_section(FILE *fd, garray_T *gap, int16_t *first) +{ + int cnt; + fromto_T *ftp; + + cnt = get2c(fd); // <repcount> + if (cnt < 0) + return SP_TRUNCERROR; + + ga_grow(gap, cnt); + + // <rep> : <repfromlen> <repfrom> <reptolen> <repto> + for (; gap->ga_len < cnt; ++gap->ga_len) { + int c; + ftp = &((fromto_T *)gap->ga_data)[gap->ga_len]; + ftp->ft_from = read_cnt_string(fd, 1, &c); + if (c < 0) + return c; + if (c == 0) + return SP_FORMERROR; + ftp->ft_to = read_cnt_string(fd, 1, &c); + if (c <= 0) { + xfree(ftp->ft_from); + if (c < 0) + return c; + return SP_FORMERROR; + } + } + + // Fill the first-index table. + for (int i = 0; i < 256; ++i) { + first[i] = -1; + } + for (int i = 0; i < gap->ga_len; ++i) { + ftp = &((fromto_T *)gap->ga_data)[i]; + if (first[*ftp->ft_from] == -1) + first[*ftp->ft_from] = i; + } + return 0; +} + +// Read SN_SAL section: <salflags> <salcount> <sal> ... +// Return SP_*ERROR flags. +static int read_sal_section(FILE *fd, slang_T *slang) +{ + int cnt; + garray_T *gap; + salitem_T *smp; + int ccnt; + char_u *p; + int c = NUL; + + slang->sl_sofo = false; + + const int flags = getc(fd); // <salflags> + if (flags & SAL_F0LLOWUP) { + slang->sl_followup = true; + } + if (flags & SAL_COLLAPSE) { + slang->sl_collapse = true; + } + if (flags & SAL_REM_ACCENTS) { + slang->sl_rem_accents = true; + } + + cnt = get2c(fd); // <salcount> + if (cnt < 0) + return SP_TRUNCERROR; + + gap = &slang->sl_sal; + ga_init(gap, sizeof(salitem_T), 10); + ga_grow(gap, cnt + 1); + + // <sal> : <salfromlen> <salfrom> <saltolen> <salto> + for (; gap->ga_len < cnt; ++gap->ga_len) { + smp = &((salitem_T *)gap->ga_data)[gap->ga_len]; + ccnt = getc(fd); // <salfromlen> + if (ccnt < 0) + return SP_TRUNCERROR; + p = xmalloc(ccnt + 2); + smp->sm_lead = p; + + // Read up to the first special char into sm_lead. + int i = 0; + for (; i < ccnt; ++i) { + c = getc(fd); // <salfrom> + if (vim_strchr((char_u *)"0123456789(-<^$", c) != NULL) + break; + *p++ = c; + } + smp->sm_leadlen = (int)(p - smp->sm_lead); + *p++ = NUL; + + // Put (abc) chars in sm_oneof, if any. + if (c == '(') { + smp->sm_oneof = p; + for (++i; i < ccnt; ++i) { + c = getc(fd); // <salfrom> + if (c == ')') + break; + *p++ = c; + } + *p++ = NUL; + if (++i < ccnt) + c = getc(fd); + } else + smp->sm_oneof = NULL; + + // Any following chars go in sm_rules. + smp->sm_rules = p; + if (i < ccnt) { + // store the char we got while checking for end of sm_lead + *p++ = c; + } + i++; + if (i < ccnt) { + SPELL_READ_NONNUL_BYTES( // <salfrom> + (char *)p, (size_t)(ccnt - i), fd, xfree(smp->sm_lead)); + p += (ccnt - i); + i = ccnt; + } + *p++ = NUL; + + // <saltolen> <salto> + smp->sm_to = read_cnt_string(fd, 1, &ccnt); + if (ccnt < 0) { + xfree(smp->sm_lead); + return ccnt; + } + + if (has_mbyte) { + // convert the multi-byte strings to wide char strings + smp->sm_lead_w = mb_str2wide(smp->sm_lead); + smp->sm_leadlen = mb_charlen(smp->sm_lead); + if (smp->sm_oneof == NULL) + smp->sm_oneof_w = NULL; + else + smp->sm_oneof_w = mb_str2wide(smp->sm_oneof); + if (smp->sm_to == NULL) + smp->sm_to_w = NULL; + else + smp->sm_to_w = mb_str2wide(smp->sm_to); + } + } + + if (!GA_EMPTY(gap)) { + // Add one extra entry to mark the end with an empty sm_lead. Avoids + // that we need to check the index every time. + smp = &((salitem_T *)gap->ga_data)[gap->ga_len]; + p = xmalloc(1); + p[0] = NUL; + smp->sm_lead = p; + smp->sm_leadlen = 0; + smp->sm_oneof = NULL; + smp->sm_rules = p; + smp->sm_to = NULL; + if (has_mbyte) { + smp->sm_lead_w = mb_str2wide(smp->sm_lead); + smp->sm_leadlen = 0; + smp->sm_oneof_w = NULL; + smp->sm_to_w = NULL; + } + ++gap->ga_len; + } + + // Fill the first-index table. + set_sal_first(slang); + + return 0; +} + +// Read SN_WORDS: <word> ... +// Return SP_*ERROR flags. +static int read_words_section(FILE *fd, slang_T *lp, int len) +{ + int done = 0; + int i; + int c; + char_u word[MAXWLEN]; + + while (done < len) { + // Read one word at a time. + for (i = 0;; ++i) { + c = getc(fd); + if (c == EOF) + return SP_TRUNCERROR; + word[i] = c; + if (word[i] == NUL) + break; + if (i == MAXWLEN - 1) + return SP_FORMERROR; + } + + // Init the count to 10. + count_common_word(lp, word, -1, 10); + done += i + 1; + } + return 0; +} + +// SN_SOFO: <sofofromlen> <sofofrom> <sofotolen> <sofoto> +// Return SP_*ERROR flags. +static int read_sofo_section(FILE *fd, slang_T *slang) +{ + int cnt; + char_u *from, *to; + int res; + + slang->sl_sofo = true; + + // <sofofromlen> <sofofrom> + from = read_cnt_string(fd, 2, &cnt); + if (cnt < 0) + return cnt; + + // <sofotolen> <sofoto> + to = read_cnt_string(fd, 2, &cnt); + if (cnt < 0) { + xfree(from); + return cnt; + } + + // Store the info in slang->sl_sal and/or slang->sl_sal_first. + if (from != NULL && to != NULL) + res = set_sofo(slang, from, to); + else if (from != NULL || to != NULL) + res = SP_FORMERROR; // only one of two strings is an error + else + res = 0; + + xfree(from); + xfree(to); + return res; +} + +// Read the compound section from the .spl file: +// <compmax> <compminlen> <compsylmax> <compoptions> <compflags> +// Returns SP_*ERROR flags. +static int read_compound(FILE *fd, slang_T *slang, int len) +{ + int todo = len; + int c; + int atstart; + char_u *pat; + char_u *pp; + char_u *cp; + char_u *ap; + char_u *crp; + int cnt; + garray_T *gap; + + if (todo < 2) + return SP_FORMERROR; // need at least two bytes + + --todo; + c = getc(fd); // <compmax> + if (c < 2) + c = MAXWLEN; + slang->sl_compmax = c; + + --todo; + c = getc(fd); // <compminlen> + if (c < 1) + c = 0; + slang->sl_compminlen = c; + + --todo; + c = getc(fd); // <compsylmax> + if (c < 1) + c = MAXWLEN; + slang->sl_compsylmax = c; + + c = getc(fd); // <compoptions> + if (c != 0) + ungetc(c, fd); // be backwards compatible with Vim 7.0b + else { + --todo; + c = getc(fd); // only use the lower byte for now + --todo; + slang->sl_compoptions = c; + + gap = &slang->sl_comppat; + c = get2c(fd); // <comppatcount> + todo -= 2; + ga_init(gap, sizeof(char_u *), c); + ga_grow(gap, c); + while (--c >= 0) { + ((char_u **)(gap->ga_data))[gap->ga_len++] = + read_cnt_string(fd, 1, &cnt); + // <comppatlen> <comppattext> + if (cnt < 0) + return cnt; + todo -= cnt + 1; + } + } + if (todo < 0) + return SP_FORMERROR; + + // Turn the COMPOUNDRULE items into a regexp pattern: + // "a[bc]/a*b+" -> "^\(a[bc]\|a*b\+\)$". + // Inserting backslashes may double the length, "^\(\)$<Nul>" is 7 bytes. + // Conversion to utf-8 may double the size. + c = todo * 2 + 7; + if (enc_utf8) + c += todo * 2; + pat = xmalloc(c); + + // We also need a list of all flags that can appear at the start and one + // for all flags. + cp = xmalloc(todo + 1); + slang->sl_compstartflags = cp; + *cp = NUL; + + ap = xmalloc(todo + 1); + slang->sl_compallflags = ap; + *ap = NUL; + + // And a list of all patterns in their original form, for checking whether + // compounding may work in match_compoundrule(). This is freed when we + // encounter a wildcard, the check doesn't work then. + crp = xmalloc(todo + 1); + slang->sl_comprules = crp; + + pp = pat; + *pp++ = '^'; + *pp++ = '\\'; + *pp++ = '('; + + atstart = 1; + while (todo-- > 0) { + c = getc(fd); // <compflags> + if (c == EOF) { + xfree(pat); + return SP_TRUNCERROR; + } + + // Add all flags to "sl_compallflags". + if (vim_strchr((char_u *)"?*+[]/", c) == NULL + && !byte_in_str(slang->sl_compallflags, c)) { + *ap++ = c; + *ap = NUL; + } + + if (atstart != 0) { + // At start of item: copy flags to "sl_compstartflags". For a + // [abc] item set "atstart" to 2 and copy up to the ']'. + if (c == '[') + atstart = 2; + else if (c == ']') + atstart = 0; + else { + if (!byte_in_str(slang->sl_compstartflags, c)) { + *cp++ = c; + *cp = NUL; + } + if (atstart == 1) + atstart = 0; + } + } + + // Copy flag to "sl_comprules", unless we run into a wildcard. + if (crp != NULL) { + if (c == '?' || c == '+' || c == '*') { + xfree(slang->sl_comprules); + slang->sl_comprules = NULL; + crp = NULL; + } else + *crp++ = c; + } + + if (c == '/') { // slash separates two items + *pp++ = '\\'; + *pp++ = '|'; + atstart = 1; + } else { // normal char, "[abc]" and '*' are copied as-is + if (c == '?' || c == '+' || c == '~') + *pp++ = '\\'; // "a?" becomes "a\?", "a+" becomes "a\+" + if (enc_utf8) + pp += mb_char2bytes(c, pp); + else + *pp++ = c; + } + } + + *pp++ = '\\'; + *pp++ = ')'; + *pp++ = '$'; + *pp = NUL; + + if (crp != NULL) + *crp = NUL; + + slang->sl_compprog = vim_regcomp(pat, RE_MAGIC + RE_STRING + RE_STRICT); + xfree(pat); + if (slang->sl_compprog == NULL) + return SP_FORMERROR; + + return 0; +} + +// Set the SOFOFROM and SOFOTO items in language "lp". +// Returns SP_*ERROR flags when there is something wrong. +static int set_sofo(slang_T *lp, char_u *from, char_u *to) +{ + int i; + + garray_T *gap; + char_u *s; + char_u *p; + int c; + int *inp; + + if (has_mbyte) { + // Use "sl_sal" as an array with 256 pointers to a list of wide + // characters. The index is the low byte of the character. + // The list contains from-to pairs with a terminating NUL. + // sl_sal_first[] is used for latin1 "from" characters. + gap = &lp->sl_sal; + ga_init(gap, sizeof(int *), 1); + ga_grow(gap, 256); + memset(gap->ga_data, 0, sizeof(int *) * 256); + gap->ga_len = 256; + + // First count the number of items for each list. Temporarily use + // sl_sal_first[] for this. + for (p = from, s = to; *p != NUL && *s != NUL; ) { + c = mb_cptr2char_adv((const char_u **)&p); + mb_cptr_adv(s); + if (c >= 256) + ++lp->sl_sal_first[c & 0xff]; + } + if (*p != NUL || *s != NUL) // lengths differ + return SP_FORMERROR; + + // Allocate the lists. + for (i = 0; i < 256; ++i) + if (lp->sl_sal_first[i] > 0) { + p = xmalloc(sizeof(int) * (lp->sl_sal_first[i] * 2 + 1)); + ((int **)gap->ga_data)[i] = (int *)p; + *(int *)p = 0; + } + + // Put the characters up to 255 in sl_sal_first[] the rest in a sl_sal + // list. + memset(lp->sl_sal_first, 0, sizeof(salfirst_T) * 256); + for (p = from, s = to; *p != NUL && *s != NUL; ) { + c = mb_cptr2char_adv((const char_u **)&p); + i = mb_cptr2char_adv((const char_u **)&s); + if (c >= 256) { + // Append the from-to chars at the end of the list with + // the low byte. + inp = ((int **)gap->ga_data)[c & 0xff]; + while (*inp != 0) + ++inp; + *inp++ = c; // from char + *inp++ = i; // to char + *inp++ = NUL; // NUL at the end + } else + // mapping byte to char is done in sl_sal_first[] + lp->sl_sal_first[c] = i; + } + } else { + // mapping bytes to bytes is done in sl_sal_first[] + if (STRLEN(from) != STRLEN(to)) + return SP_FORMERROR; + + for (i = 0; to[i] != NUL; ++i) + lp->sl_sal_first[from[i]] = to[i]; + lp->sl_sal.ga_len = 1; // indicates we have soundfolding + } + + return 0; +} + +// Fill the first-index table for "lp". +static void set_sal_first(slang_T *lp) +{ + salfirst_T *sfirst; + salitem_T *smp; + int c; + garray_T *gap = &lp->sl_sal; + + sfirst = lp->sl_sal_first; + for (int i = 0; i < 256; ++i) { + sfirst[i] = -1; + } + smp = (salitem_T *)gap->ga_data; + for (int i = 0; i < gap->ga_len; ++i) { + if (has_mbyte) + // Use the lowest byte of the first character. For latin1 it's + // the character, for other encodings it should differ for most + // characters. + c = *smp[i].sm_lead_w & 0xff; + else + c = *smp[i].sm_lead; + if (sfirst[c] == -1) { + sfirst[c] = i; + if (has_mbyte) { + int n; + + // Make sure all entries with this byte are following each + // other. Move the ones that are in the wrong position. Do + // keep the same ordering! + while (i + 1 < gap->ga_len + && (*smp[i + 1].sm_lead_w & 0xff) == c) + // Skip over entry with same index byte. + ++i; + + for (n = 1; i + n < gap->ga_len; ++n) + if ((*smp[i + n].sm_lead_w & 0xff) == c) { + salitem_T tsal; + + // Move entry with same index byte after the entries + // we already found. + ++i; + --n; + tsal = smp[i + n]; + memmove(smp + i + 1, smp + i, + sizeof(salitem_T) * n); + smp[i] = tsal; + } + } + } + } +} + +// Turn a multi-byte string into a wide character string. +// Return it in allocated memory. +static int *mb_str2wide(char_u *s) +{ + int i = 0; + + int *res = xmalloc((mb_charlen(s) + 1) * sizeof(int)); + for (char_u *p = s; *p != NUL; ) { + res[i++] = mb_ptr2char_adv((const char_u **)&p); + } + res[i] = NUL; + + return res; +} + +// Reads a tree from the .spl or .sug file. +// Allocates the memory and stores pointers in "bytsp" and "idxsp". +// This is skipped when the tree has zero length. +// Returns zero when OK, SP_ value for an error. +static int +spell_read_tree ( + FILE *fd, + char_u **bytsp, + idx_T **idxsp, + bool prefixtree, // true for the prefix tree + int prefixcnt // when "prefixtree" is true: prefix count +) +{ + int idx; + char_u *bp; + idx_T *ip; + + // The tree size was computed when writing the file, so that we can + // allocate it as one long block. <nodecount> + long len = get4c(fd); + if (len < 0) { + return SP_TRUNCERROR; + } + if ((size_t)len >= SIZE_MAX / sizeof(int)) { + // Invalid length, multiply with sizeof(int) would overflow. + return SP_FORMERROR; + } + if (len > 0) { + // Allocate the byte array. + bp = xmalloc(len); + *bytsp = bp; + + // Allocate the index array. + ip = xcalloc(len, sizeof(*ip)); + *idxsp = ip; + + // Recursively read the tree and store it in the array. + idx = read_tree_node(fd, bp, ip, len, 0, prefixtree, prefixcnt); + if (idx < 0) + return idx; + } + return 0; +} + +// Read one row of siblings from the spell file and store it in the byte array +// "byts" and index array "idxs". Recursively read the children. +// +// NOTE: The code here must match put_node()! +// +// Returns the index (>= 0) following the siblings. +// Returns SP_TRUNCERROR if the file is shorter than expected. +// Returns SP_FORMERROR if there is a format error. +static idx_T +read_tree_node ( + FILE *fd, + char_u *byts, + idx_T *idxs, + int maxidx, // size of arrays + idx_T startidx, // current index in "byts" and "idxs" + bool prefixtree, // true for reading PREFIXTREE + int maxprefcondnr // maximum for <prefcondnr> +) +{ + int len; + int i; + int n; + idx_T idx = startidx; + int c; + int c2; +#define SHARED_MASK 0x8000000 + + len = getc(fd); // <siblingcount> + if (len <= 0) + return SP_TRUNCERROR; + + if (startidx + len >= maxidx) + return SP_FORMERROR; + byts[idx++] = len; + + // Read the byte values, flag/region bytes and shared indexes. + for (i = 1; i <= len; ++i) { + c = getc(fd); // <byte> + if (c < 0) + return SP_TRUNCERROR; + if (c <= BY_SPECIAL) { + if (c == BY_NOFLAGS && !prefixtree) { + // No flags, all regions. + idxs[idx] = 0; + c = 0; + } else if (c != BY_INDEX) { + if (prefixtree) { + // Read the optional pflags byte, the prefix ID and the + // condition nr. In idxs[] store the prefix ID in the low + // byte, the condition index shifted up 8 bits, the flags + // shifted up 24 bits. + if (c == BY_FLAGS) + c = getc(fd) << 24; // <pflags> + else + c = 0; + + c |= getc(fd); // <affixID> + + n = get2c(fd); // <prefcondnr> + if (n >= maxprefcondnr) + return SP_FORMERROR; + c |= (n << 8); + } else { // c must be BY_FLAGS or BY_FLAGS2 + // Read flags and optional region and prefix ID. In + // idxs[] the flags go in the low two bytes, region above + // that and prefix ID above the region. + c2 = c; + c = getc(fd); // <flags> + if (c2 == BY_FLAGS2) + c = (getc(fd) << 8) + c; // <flags2> + if (c & WF_REGION) + c = (getc(fd) << 16) + c; // <region> + if (c & WF_AFX) + c = (getc(fd) << 24) + c; // <affixID> + } + + idxs[idx] = c; + c = 0; + } else { // c == BY_INDEX + // <nodeidx> + n = get3c(fd); + if (n < 0 || n >= maxidx) + return SP_FORMERROR; + idxs[idx] = n + SHARED_MASK; + c = getc(fd); // <xbyte> + } + } + byts[idx++] = c; + } + + // Recursively read the children for non-shared siblings. + // Skip the end-of-word ones (zero byte value) and the shared ones (and + // remove SHARED_MASK) + for (i = 1; i <= len; ++i) + if (byts[startidx + i] != 0) { + if (idxs[startidx + i] & SHARED_MASK) + idxs[startidx + i] &= ~SHARED_MASK; + else { + idxs[startidx + i] = idx; + idx = read_tree_node(fd, byts, idxs, maxidx, idx, + prefixtree, maxprefcondnr); + if (idx < 0) + break; + } + } + + return idx; +} + +// Reload the spell file "fname" if it's loaded. +static void +spell_reload_one ( + char_u *fname, + bool added_word // invoked through "zg" +) +{ + slang_T *slang; + bool didit = false; + + for (slang = first_lang; slang != NULL; slang = slang->sl_next) { + if (path_full_compare(fname, slang->sl_fname, FALSE) == kEqualFiles) { + slang_clear(slang); + if (spell_load_file(fname, NULL, slang, false) == NULL) + // reloading failed, clear the language + slang_clear(slang); + redraw_all_later(SOME_VALID); + didit = true; + } + } + + // When "zg" was used and the file wasn't loaded yet, should redo + // 'spelllang' to load it now. + if (added_word && !didit) + did_set_spelllang(curwin); +} + +// Functions for ":mkspell". + +// In the postponed prefixes tree wn_flags is used to store the WFP_ flags, +// but it must be negative to indicate the prefix tree to tree_add_word(). +// Use a negative number with the lower 8 bits zero. +#define PFX_FLAGS -256 + +// flags for "condit" argument of store_aff_word() +#define CONDIT_COMB 1 // affix must combine +#define CONDIT_CFIX 2 // affix must have CIRCUMFIX flag +#define CONDIT_SUF 4 // add a suffix for matching flags +#define CONDIT_AFF 8 // word already has an affix + +// Tunable parameters for when the tree is compressed. See 'mkspellmem'. +static long compress_start = 30000; // memory / SBLOCKSIZE +static long compress_inc = 100; // memory / SBLOCKSIZE +static long compress_added = 500000; // word count + +// Check the 'mkspellmem' option. Return FAIL if it's wrong. +// Sets "sps_flags". +int spell_check_msm(void) +{ + char_u *p = p_msm; + long start = 0; + long incr = 0; + long added = 0; + + if (!ascii_isdigit(*p)) + return FAIL; + // block count = (value * 1024) / SBLOCKSIZE (but avoid overflow) + start = (getdigits_long(&p) * 10) / (SBLOCKSIZE / 102); + if (*p != ',') + return FAIL; + ++p; + if (!ascii_isdigit(*p)) + return FAIL; + incr = (getdigits_long(&p) * 102) / (SBLOCKSIZE / 10); + if (*p != ',') + return FAIL; + ++p; + if (!ascii_isdigit(*p)) + return FAIL; + added = getdigits_long(&p) * 1024; + if (*p != NUL) + return FAIL; + + if (start == 0 || incr == 0 || added == 0 || incr > start) + return FAIL; + + compress_start = start; + compress_inc = incr; + compress_added = added; + return OK; +} + +#ifdef SPELL_PRINTTREE +// For debugging the tree code: print the current tree in a (more or less) +// readable format, so that we can see what happens when adding a word and/or +// compressing the tree. +// Based on code from Olaf Seibert. +#define PRINTLINESIZE 1000 +#define PRINTWIDTH 6 + +#define PRINTSOME(l, depth, fmt, a1, a2) vim_snprintf(l + depth * PRINTWIDTH, \ + PRINTLINESIZE - PRINTWIDTH * depth, fmt, a1, a2) + +static char line1[PRINTLINESIZE]; +static char line2[PRINTLINESIZE]; +static char line3[PRINTLINESIZE]; + +static void spell_clear_flags(wordnode_T *node) +{ + wordnode_T *np; + + for (np = node; np != NULL; np = np->wn_sibling) { + np->wn_u1.index = FALSE; + spell_clear_flags(np->wn_child); + } +} + +static void spell_print_node(wordnode_T *node, int depth) +{ + if (node->wn_u1.index) { + // Done this node before, print the reference. + PRINTSOME(line1, depth, "(%d)", node->wn_nr, 0); + PRINTSOME(line2, depth, " ", 0, 0); + PRINTSOME(line3, depth, " ", 0, 0); + msg((char_u *)line1); + msg((char_u *)line2); + msg((char_u *)line3); + } else { + node->wn_u1.index = TRUE; + + if (node->wn_byte != NUL) { + if (node->wn_child != NULL) + PRINTSOME(line1, depth, " %c -> ", node->wn_byte, 0); + else + // Cannot happen? + PRINTSOME(line1, depth, " %c ???", node->wn_byte, 0); + } else + PRINTSOME(line1, depth, " $ ", 0, 0); + + PRINTSOME(line2, depth, "%d/%d ", node->wn_nr, node->wn_refs); + + if (node->wn_sibling != NULL) + PRINTSOME(line3, depth, " | ", 0, 0); + else + PRINTSOME(line3, depth, " ", 0, 0); + + if (node->wn_byte == NUL) { + msg((char_u *)line1); + msg((char_u *)line2); + msg((char_u *)line3); + } + + // do the children + if (node->wn_byte != NUL && node->wn_child != NULL) + spell_print_node(node->wn_child, depth + 1); + + // do the siblings + if (node->wn_sibling != NULL) { + // get rid of all parent details except | + STRCPY(line1, line3); + STRCPY(line2, line3); + spell_print_node(node->wn_sibling, depth); + } + } +} + +static void spell_print_tree(wordnode_T *root) +{ + if (root != NULL) { + // Clear the "wn_u1.index" fields, used to remember what has been + // done. + spell_clear_flags(root); + + // Recursively print the tree. + spell_print_node(root, 0); + } +} + +#endif // SPELL_PRINTTREE + +// Reads the affix file "fname". +// Returns an afffile_T, NULL for complete failure. +static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname) +{ + FILE *fd; + afffile_T *aff; + char_u rline[MAXLINELEN]; + char_u *line; + char_u *pc = NULL; +#define MAXITEMCNT 30 + char_u *(items[MAXITEMCNT]); + int itemcnt; + char_u *p; + int lnum = 0; + affheader_T *cur_aff = NULL; + bool did_postpone_prefix = false; + int aff_todo = 0; + hashtab_T *tp; + char_u *low = NULL; + char_u *fol = NULL; + char_u *upp = NULL; + int do_rep; + int do_repsal; + int do_sal; + int do_mapline; + bool found_map = false; + hashitem_T *hi; + int l; + int compminlen = 0; // COMPOUNDMIN value + int compsylmax = 0; // COMPOUNDSYLMAX value + int compoptions = 0; // COMP_ flags + int compmax = 0; // COMPOUNDWORDMAX value + char_u *compflags = NULL; // COMPOUNDFLAG and COMPOUNDRULE + // concatenated + char_u *midword = NULL; // MIDWORD value + char_u *syllable = NULL; // SYLLABLE value + char_u *sofofrom = NULL; // SOFOFROM value + char_u *sofoto = NULL; // SOFOTO value + + // Open the file. + fd = mch_fopen((char *)fname, "r"); + if (fd == NULL) { + EMSG2(_(e_notopen), fname); + return NULL; + } + + vim_snprintf((char *)IObuff, IOSIZE, _("Reading affix file %s ..."), fname); + spell_message(spin, IObuff); + + // Only do REP lines when not done in another .aff file already. + do_rep = GA_EMPTY(&spin->si_rep); + + // Only do REPSAL lines when not done in another .aff file already. + do_repsal = GA_EMPTY(&spin->si_repsal); + + // Only do SAL lines when not done in another .aff file already. + do_sal = GA_EMPTY(&spin->si_sal); + + // Only do MAP lines when not done in another .aff file already. + do_mapline = GA_EMPTY(&spin->si_map); + + // Allocate and init the afffile_T structure. + aff = (afffile_T *)getroom(spin, sizeof(afffile_T), true); + if (aff == NULL) { + fclose(fd); + return NULL; + } + hash_init(&aff->af_pref); + hash_init(&aff->af_suff); + hash_init(&aff->af_comp); + + // Read all the lines in the file one by one. + while (!vim_fgets(rline, MAXLINELEN, fd) && !got_int) { + line_breakcheck(); + ++lnum; + + // Skip comment lines. + if (*rline == '#') + continue; + + // Convert from "SET" to 'encoding' when needed. + xfree(pc); + if (spin->si_conv.vc_type != CONV_NONE) { + pc = string_convert(&spin->si_conv, rline, NULL); + if (pc == NULL) { + smsg(_("Conversion failure for word in %s line %d: %s"), + fname, lnum, rline); + continue; + } + line = pc; + } else { + pc = NULL; + line = rline; + } + + // Split the line up in white separated items. Put a NUL after each + // item. + itemcnt = 0; + for (p = line;; ) { + while (*p != NUL && *p <= ' ') // skip white space and CR/NL + ++p; + if (*p == NUL) + break; + if (itemcnt == MAXITEMCNT) // too many items + break; + items[itemcnt++] = p; + // A few items have arbitrary text argument, don't split them. + if (itemcnt == 2 && spell_info_item(items[0])) + while (*p >= ' ' || *p == TAB) // skip until CR/NL + ++p; + else + while (*p > ' ') // skip until white space or CR/NL + ++p; + if (*p == NUL) + break; + *p++ = NUL; + } + + // Handle non-empty lines. + if (itemcnt > 0) { + if (is_aff_rule(items, itemcnt, "SET", 2) && aff->af_enc == NULL) { + // Setup for conversion from "ENC" to 'encoding'. + aff->af_enc = enc_canonize(items[1]); + if (!spin->si_ascii + && convert_setup(&spin->si_conv, aff->af_enc, + p_enc) == FAIL) + smsg(_("Conversion in %s not supported: from %s to %s"), + fname, aff->af_enc, p_enc); + spin->si_conv.vc_fail = true; + } else if (is_aff_rule(items, itemcnt, "FLAG", 2) + && aff->af_flagtype == AFT_CHAR) { + if (STRCMP(items[1], "long") == 0) + aff->af_flagtype = AFT_LONG; + else if (STRCMP(items[1], "num") == 0) + aff->af_flagtype = AFT_NUM; + else if (STRCMP(items[1], "caplong") == 0) + aff->af_flagtype = AFT_CAPLONG; + else + smsg(_("Invalid value for FLAG in %s line %d: %s"), + fname, lnum, items[1]); + if (aff->af_rare != 0 + || aff->af_keepcase != 0 + || aff->af_bad != 0 + || aff->af_needaffix != 0 + || aff->af_circumfix != 0 + || aff->af_needcomp != 0 + || aff->af_comproot != 0 + || aff->af_nosuggest != 0 + || compflags != NULL + || aff->af_suff.ht_used > 0 + || aff->af_pref.ht_used > 0) + smsg(_("FLAG after using flags in %s line %d: %s"), + fname, lnum, items[1]); + } else if (spell_info_item(items[0]) && itemcnt > 1) { + p = (char_u *)getroom(spin, + (spin->si_info == NULL ? 0 : STRLEN(spin->si_info)) + + STRLEN(items[0]) + + STRLEN(items[1]) + 3, false); + if (p != NULL) { + if (spin->si_info != NULL) { + STRCPY(p, spin->si_info); + STRCAT(p, "\n"); + } + STRCAT(p, items[0]); + STRCAT(p, " "); + STRCAT(p, items[1]); + spin->si_info = p; + } + } else if (is_aff_rule(items, itemcnt, "MIDWORD", 2) + && midword == NULL) { + midword = getroom_save(spin, items[1]); + } else if (is_aff_rule(items, itemcnt, "TRY", 2)) { + // ignored, we look in the tree for what chars may appear + } + // TODO: remove "RAR" later + else if ((is_aff_rule(items, itemcnt, "RAR", 2) + || is_aff_rule(items, itemcnt, "RARE", 2)) + && aff->af_rare == 0) { + aff->af_rare = affitem2flag(aff->af_flagtype, items[1], + fname, lnum); + } + // TODO: remove "KEP" later + else if ((is_aff_rule(items, itemcnt, "KEP", 2) + || is_aff_rule(items, itemcnt, "KEEPCASE", 2)) + && aff->af_keepcase == 0) { + aff->af_keepcase = affitem2flag(aff->af_flagtype, items[1], + fname, lnum); + } else if ((is_aff_rule(items, itemcnt, "BAD", 2) + || is_aff_rule(items, itemcnt, "FORBIDDENWORD", 2)) + && aff->af_bad == 0) { + aff->af_bad = affitem2flag(aff->af_flagtype, items[1], + fname, lnum); + } else if (is_aff_rule(items, itemcnt, "NEEDAFFIX", 2) + && aff->af_needaffix == 0) { + aff->af_needaffix = affitem2flag(aff->af_flagtype, items[1], + fname, lnum); + } else if (is_aff_rule(items, itemcnt, "CIRCUMFIX", 2) + && aff->af_circumfix == 0) { + aff->af_circumfix = affitem2flag(aff->af_flagtype, items[1], + fname, lnum); + } else if (is_aff_rule(items, itemcnt, "NOSUGGEST", 2) + && aff->af_nosuggest == 0) { + aff->af_nosuggest = affitem2flag(aff->af_flagtype, items[1], + fname, lnum); + } else if ((is_aff_rule(items, itemcnt, "NEEDCOMPOUND", 2) + || is_aff_rule(items, itemcnt, "ONLYINCOMPOUND", 2)) + && aff->af_needcomp == 0) { + aff->af_needcomp = affitem2flag(aff->af_flagtype, items[1], + fname, lnum); + } else if (is_aff_rule(items, itemcnt, "COMPOUNDROOT", 2) + && aff->af_comproot == 0) { + aff->af_comproot = affitem2flag(aff->af_flagtype, items[1], + fname, lnum); + } else if (is_aff_rule(items, itemcnt, "COMPOUNDFORBIDFLAG", 2) + && aff->af_compforbid == 0) { + aff->af_compforbid = affitem2flag(aff->af_flagtype, items[1], + fname, lnum); + if (aff->af_pref.ht_used > 0) + smsg(_("Defining COMPOUNDFORBIDFLAG after PFX item may give wrong results in %s line %d"), + fname, lnum); + } else if (is_aff_rule(items, itemcnt, "COMPOUNDPERMITFLAG", 2) + && aff->af_comppermit == 0) { + aff->af_comppermit = affitem2flag(aff->af_flagtype, items[1], + fname, lnum); + if (aff->af_pref.ht_used > 0) + smsg(_("Defining COMPOUNDPERMITFLAG after PFX item may give wrong results in %s line %d"), + fname, lnum); + } else if (is_aff_rule(items, itemcnt, "COMPOUNDFLAG", 2) + && compflags == NULL) { + // Turn flag "c" into COMPOUNDRULE compatible string "c+", + // "Na" into "Na+", "1234" into "1234+". + p = getroom(spin, STRLEN(items[1]) + 2, false); + STRCPY(p, items[1]); + STRCAT(p, "+"); + compflags = p; + } else if (is_aff_rule(items, itemcnt, "COMPOUNDRULES", 2)) { + // We don't use the count, but do check that it's a number and + // not COMPOUNDRULE mistyped. + if (atoi((char *)items[1]) == 0) + smsg(_("Wrong COMPOUNDRULES value in %s line %d: %s"), + fname, lnum, items[1]); + } else if (is_aff_rule(items, itemcnt, "COMPOUNDRULE", 2)) { + // Don't use the first rule if it is a number. + if (compflags != NULL || *skipdigits(items[1]) != NUL) { + // Concatenate this string to previously defined ones, + // using a slash to separate them. + l = (int)STRLEN(items[1]) + 1; + if (compflags != NULL) + l += (int)STRLEN(compflags) + 1; + p = getroom(spin, l, false); + if (compflags != NULL) { + STRCPY(p, compflags); + STRCAT(p, "/"); + } + STRCAT(p, items[1]); + compflags = p; + } + } else if (is_aff_rule(items, itemcnt, "COMPOUNDWORDMAX", 2) + && compmax == 0) { + compmax = atoi((char *)items[1]); + if (compmax == 0) + smsg(_("Wrong COMPOUNDWORDMAX value in %s line %d: %s"), + fname, lnum, items[1]); + } else if (is_aff_rule(items, itemcnt, "COMPOUNDMIN", 2) + && compminlen == 0) { + compminlen = atoi((char *)items[1]); + if (compminlen == 0) + smsg(_("Wrong COMPOUNDMIN value in %s line %d: %s"), + fname, lnum, items[1]); + } else if (is_aff_rule(items, itemcnt, "COMPOUNDSYLMAX", 2) + && compsylmax == 0) { + compsylmax = atoi((char *)items[1]); + if (compsylmax == 0) + smsg(_("Wrong COMPOUNDSYLMAX value in %s line %d: %s"), + fname, lnum, items[1]); + } else if (is_aff_rule(items, itemcnt, "CHECKCOMPOUNDDUP", 1)) { + compoptions |= COMP_CHECKDUP; + } else if (is_aff_rule(items, itemcnt, "CHECKCOMPOUNDREP", 1)) { + compoptions |= COMP_CHECKREP; + } else if (is_aff_rule(items, itemcnt, "CHECKCOMPOUNDCASE", 1)) { + compoptions |= COMP_CHECKCASE; + } else if (is_aff_rule(items, itemcnt, "CHECKCOMPOUNDTRIPLE", 1)) { + compoptions |= COMP_CHECKTRIPLE; + } else if (is_aff_rule(items, itemcnt, "CHECKCOMPOUNDPATTERN", 2)) { + if (atoi((char *)items[1]) == 0) + smsg(_("Wrong CHECKCOMPOUNDPATTERN value in %s line %d: %s"), + fname, lnum, items[1]); + } else if (is_aff_rule(items, itemcnt, "CHECKCOMPOUNDPATTERN", 3)) { + garray_T *gap = &spin->si_comppat; + int i; + + // Only add the couple if it isn't already there. + for (i = 0; i < gap->ga_len - 1; i += 2) + if (STRCMP(((char_u **)(gap->ga_data))[i], items[1]) == 0 + && STRCMP(((char_u **)(gap->ga_data))[i + 1], + items[2]) == 0) + break; + if (i >= gap->ga_len) { + ga_grow(gap, 2); + ((char_u **)(gap->ga_data))[gap->ga_len++] + = getroom_save(spin, items[1]); + ((char_u **)(gap->ga_data))[gap->ga_len++] + = getroom_save(spin, items[2]); + } + } else if (is_aff_rule(items, itemcnt, "SYLLABLE", 2) + && syllable == NULL) { + syllable = getroom_save(spin, items[1]); + } else if (is_aff_rule(items, itemcnt, "NOBREAK", 1)) { + spin->si_nobreak = true; + } else if (is_aff_rule(items, itemcnt, "NOSPLITSUGS", 1)) { + spin->si_nosplitsugs = true; + } else if (is_aff_rule(items, itemcnt, "NOCOMPOUNDSUGS", 1)) { + spin->si_nocompoundsugs = true; + } else if (is_aff_rule(items, itemcnt, "NOSUGFILE", 1)) { + spin->si_nosugfile = true; + } else if (is_aff_rule(items, itemcnt, "PFXPOSTPONE", 1)) { + aff->af_pfxpostpone = true; + } else if (is_aff_rule(items, itemcnt, "IGNOREEXTRA", 1)) { + aff->af_ignoreextra = true; + } else if ((STRCMP(items[0], "PFX") == 0 + || STRCMP(items[0], "SFX") == 0) + && aff_todo == 0 + && itemcnt >= 4) { + int lasti = 4; + char_u key[AH_KEY_LEN]; + + if (*items[0] == 'P') + tp = &aff->af_pref; + else + tp = &aff->af_suff; + + // Myspell allows the same affix name to be used multiple + // times. The affix files that do this have an undocumented + // "S" flag on all but the last block, thus we check for that + // and store it in ah_follows. + STRLCPY(key, items[1], AH_KEY_LEN); + hi = hash_find(tp, key); + if (!HASHITEM_EMPTY(hi)) { + cur_aff = HI2AH(hi); + if (cur_aff->ah_combine != (*items[2] == 'Y')) + smsg(_("Different combining flag in continued affix block in %s line %d: %s"), + fname, lnum, items[1]); + if (!cur_aff->ah_follows) + smsg(_("Duplicate affix in %s line %d: %s"), + fname, lnum, items[1]); + } else { + // New affix letter. + cur_aff = (affheader_T *)getroom(spin, + sizeof(affheader_T), true); + if (cur_aff == NULL) + break; + cur_aff->ah_flag = affitem2flag(aff->af_flagtype, items[1], + fname, lnum); + if (cur_aff->ah_flag == 0 || STRLEN(items[1]) >= AH_KEY_LEN) + break; + if (cur_aff->ah_flag == aff->af_bad + || cur_aff->ah_flag == aff->af_rare + || cur_aff->ah_flag == aff->af_keepcase + || cur_aff->ah_flag == aff->af_needaffix + || cur_aff->ah_flag == aff->af_circumfix + || cur_aff->ah_flag == aff->af_nosuggest + || cur_aff->ah_flag == aff->af_needcomp + || cur_aff->ah_flag == aff->af_comproot) + smsg(_("Affix also used for " + "BAD/RARE/KEEPCASE/NEEDAFFIX/NEEDCOMPOUND/NOSUGGEST" + "in %s line %d: %s"), + fname, lnum, items[1]); + STRCPY(cur_aff->ah_key, items[1]); + hash_add(tp, cur_aff->ah_key); + + cur_aff->ah_combine = (*items[2] == 'Y'); + } + + // Check for the "S" flag, which apparently means that another + // block with the same affix name is following. + if (itemcnt > lasti && STRCMP(items[lasti], "S") == 0) { + ++lasti; + cur_aff->ah_follows = true; + } else + cur_aff->ah_follows = false; + + // Myspell allows extra text after the item, but that might + // mean mistakes go unnoticed. Require a comment-starter, + // unless IGNOREEXTRA is used. Hunspell uses a "-" item. + if (itemcnt > lasti + && !aff->af_ignoreextra + && *items[lasti] != '#') + smsg(_(e_afftrailing), fname, lnum, items[lasti]); + + if (STRCMP(items[2], "Y") != 0 && STRCMP(items[2], "N") != 0) + smsg(_("Expected Y or N in %s line %d: %s"), + fname, lnum, items[2]); + + if (*items[0] == 'P' && aff->af_pfxpostpone) { + if (cur_aff->ah_newID == 0) { + // Use a new number in the .spl file later, to be able + // to handle multiple .aff files. + check_renumber(spin); + cur_aff->ah_newID = ++spin->si_newprefID; + + // We only really use ah_newID if the prefix is + // postponed. We know that only after handling all + // the items. + did_postpone_prefix = false; + } else + // Did use the ID in a previous block. + did_postpone_prefix = true; + } + + aff_todo = atoi((char *)items[3]); + } else if ((STRCMP(items[0], "PFX") == 0 + || STRCMP(items[0], "SFX") == 0) + && aff_todo > 0 + && STRCMP(cur_aff->ah_key, items[1]) == 0 + && itemcnt >= 5) { + affentry_T *aff_entry; + bool upper = false; + int lasti = 5; + + // Myspell allows extra text after the item, but that might + // mean mistakes go unnoticed. Require a comment-starter. + // Hunspell uses a "-" item. + if (itemcnt > lasti && *items[lasti] != '#' + && (STRCMP(items[lasti], "-") != 0 + || itemcnt != lasti + 1)) + smsg(_(e_afftrailing), fname, lnum, items[lasti]); + + // New item for an affix letter. + --aff_todo; + aff_entry = (affentry_T *)getroom(spin, + sizeof(affentry_T), true); + if (aff_entry == NULL) + break; + + if (STRCMP(items[2], "0") != 0) + aff_entry->ae_chop = getroom_save(spin, items[2]); + if (STRCMP(items[3], "0") != 0) { + aff_entry->ae_add = getroom_save(spin, items[3]); + + // Recognize flags on the affix: abcd/XYZ + aff_entry->ae_flags = vim_strchr(aff_entry->ae_add, '/'); + if (aff_entry->ae_flags != NULL) { + *aff_entry->ae_flags++ = NUL; + aff_process_flags(aff, aff_entry); + } + } + + // Don't use an affix entry with non-ASCII characters when + // "spin->si_ascii" is true. + if (!spin->si_ascii || !(has_non_ascii(aff_entry->ae_chop) + || has_non_ascii(aff_entry->ae_add))) { + aff_entry->ae_next = cur_aff->ah_first; + cur_aff->ah_first = aff_entry; + + if (STRCMP(items[4], ".") != 0) { + char_u buf[MAXLINELEN]; + + aff_entry->ae_cond = getroom_save(spin, items[4]); + if (*items[0] == 'P') + sprintf((char *)buf, "^%s", items[4]); + else + sprintf((char *)buf, "%s$", items[4]); + aff_entry->ae_prog = vim_regcomp(buf, + RE_MAGIC + RE_STRING + RE_STRICT); + if (aff_entry->ae_prog == NULL) + smsg(_("Broken condition in %s line %d: %s"), + fname, lnum, items[4]); + } + + // For postponed prefixes we need an entry in si_prefcond + // for the condition. Use an existing one if possible. + // Can't be done for an affix with flags, ignoring + // COMPOUNDFORBIDFLAG and COMPOUNDPERMITFLAG. + if (*items[0] == 'P' && aff->af_pfxpostpone + && aff_entry->ae_flags == NULL) { + // When the chop string is one lower-case letter and + // the add string ends in the upper-case letter we set + // the "upper" flag, clear "ae_chop" and remove the + // letters from "ae_add". The condition must either + // be empty or start with the same letter. + if (aff_entry->ae_chop != NULL + && aff_entry->ae_add != NULL + && aff_entry->ae_chop[(*mb_ptr2len)( + aff_entry->ae_chop)] == NUL + ) { + int c, c_up; + + c = PTR2CHAR(aff_entry->ae_chop); + c_up = SPELL_TOUPPER(c); + if (c_up != c + && (aff_entry->ae_cond == NULL + || PTR2CHAR(aff_entry->ae_cond) == c)) { + p = aff_entry->ae_add + + STRLEN(aff_entry->ae_add); + mb_ptr_back(aff_entry->ae_add, p); + if (PTR2CHAR(p) == c_up) { + upper = true; + aff_entry->ae_chop = NULL; + *p = NUL; + + // The condition is matched with the + // actual word, thus must check for the + // upper-case letter. + if (aff_entry->ae_cond != NULL) { + char_u buf[MAXLINELEN]; + if (has_mbyte) { + onecap_copy(items[4], buf, true); + aff_entry->ae_cond = getroom_save( + spin, buf); + } else + *aff_entry->ae_cond = c_up; + if (aff_entry->ae_cond != NULL) { + sprintf((char *)buf, "^%s", + aff_entry->ae_cond); + vim_regfree(aff_entry->ae_prog); + aff_entry->ae_prog = vim_regcomp( + buf, RE_MAGIC + RE_STRING); + } + } + } + } + } + + if (aff_entry->ae_chop == NULL) { + int idx; + char_u **pp; + int n; + + // Find a previously used condition. + for (idx = spin->si_prefcond.ga_len - 1; idx >= 0; + --idx) { + p = ((char_u **)spin->si_prefcond.ga_data)[idx]; + if (str_equal(p, aff_entry->ae_cond)) + break; + } + if (idx < 0) { + // Not found, add a new condition. + idx = spin->si_prefcond.ga_len; + pp = GA_APPEND_VIA_PTR(char_u *, &spin->si_prefcond); + *pp = (aff_entry->ae_cond == NULL) ? + NULL : getroom_save(spin, aff_entry->ae_cond); + } + + // Add the prefix to the prefix tree. + if (aff_entry->ae_add == NULL) + p = (char_u *)""; + else + p = aff_entry->ae_add; + + // PFX_FLAGS is a negative number, so that + // tree_add_word() knows this is the prefix tree. + n = PFX_FLAGS; + if (!cur_aff->ah_combine) + n |= WFP_NC; + if (upper) + n |= WFP_UP; + if (aff_entry->ae_comppermit) + n |= WFP_COMPPERMIT; + if (aff_entry->ae_compforbid) + n |= WFP_COMPFORBID; + tree_add_word(spin, p, spin->si_prefroot, n, + idx, cur_aff->ah_newID); + did_postpone_prefix = true; + } + + // Didn't actually use ah_newID, backup si_newprefID. + if (aff_todo == 0 && !did_postpone_prefix) { + --spin->si_newprefID; + cur_aff->ah_newID = 0; + } + } + } + } else if (is_aff_rule(items, itemcnt, "FOL", 2) && fol == NULL) { + fol = vim_strsave(items[1]); + } else if (is_aff_rule(items, itemcnt, "LOW", 2) && low == NULL) { + low = vim_strsave(items[1]); + } else if (is_aff_rule(items, itemcnt, "UPP", 2) && upp == NULL) { + upp = vim_strsave(items[1]); + } else if (is_aff_rule(items, itemcnt, "REP", 2) + || is_aff_rule(items, itemcnt, "REPSAL", 2)) { + /* Ignore REP/REPSAL count */; + if (!isdigit(*items[1])) + smsg(_("Expected REP(SAL) count in %s line %d"), + fname, lnum); + } else if ((STRCMP(items[0], "REP") == 0 + || STRCMP(items[0], "REPSAL") == 0) + && itemcnt >= 3) { + // REP/REPSAL item + // Myspell ignores extra arguments, we require it starts with + // # to detect mistakes. + if (itemcnt > 3 && items[3][0] != '#') + smsg(_(e_afftrailing), fname, lnum, items[3]); + if (items[0][3] == 'S' ? do_repsal : do_rep) { + // Replace underscore with space (can't include a space + // directly). + for (p = items[1]; *p != NUL; mb_ptr_adv(p)) + if (*p == '_') + *p = ' '; + for (p = items[2]; *p != NUL; mb_ptr_adv(p)) + if (*p == '_') + *p = ' '; + add_fromto(spin, items[0][3] == 'S' + ? &spin->si_repsal + : &spin->si_rep, items[1], items[2]); + } + } else if (is_aff_rule(items, itemcnt, "MAP", 2)) { + // MAP item or count + if (!found_map) { + // First line contains the count. + found_map = true; + if (!isdigit(*items[1])) + smsg(_("Expected MAP count in %s line %d"), + fname, lnum); + } else if (do_mapline) { + int c; + + // Check that every character appears only once. + for (p = items[1]; *p != NUL; ) { + c = mb_ptr2char_adv((const char_u **)&p); + if ((!GA_EMPTY(&spin->si_map) + && vim_strchr(spin->si_map.ga_data, c) + != NULL) + || vim_strchr(p, c) != NULL) { + smsg(_("Duplicate character in MAP in %s line %d"), + fname, lnum); + } + } + + // We simply concatenate all the MAP strings, separated by + // slashes. + ga_concat(&spin->si_map, items[1]); + ga_append(&spin->si_map, '/'); + } + } + // Accept "SAL from to" and "SAL from to #comment". + else if (is_aff_rule(items, itemcnt, "SAL", 3)) { + if (do_sal) { + // SAL item (sounds-a-like) + // Either one of the known keys or a from-to pair. + if (STRCMP(items[1], "followup") == 0) + spin->si_followup = sal_to_bool(items[2]); + else if (STRCMP(items[1], "collapse_result") == 0) + spin->si_collapse = sal_to_bool(items[2]); + else if (STRCMP(items[1], "remove_accents") == 0) + spin->si_rem_accents = sal_to_bool(items[2]); + else + // when "to" is "_" it means empty + add_fromto(spin, &spin->si_sal, items[1], + STRCMP(items[2], "_") == 0 ? (char_u *)"" + : items[2]); + } + } else if (is_aff_rule(items, itemcnt, "SOFOFROM", 2) + && sofofrom == NULL) { + sofofrom = getroom_save(spin, items[1]); + } else if (is_aff_rule(items, itemcnt, "SOFOTO", 2) + && sofoto == NULL) { + sofoto = getroom_save(spin, items[1]); + } else if (STRCMP(items[0], "COMMON") == 0) { + int i; + + for (i = 1; i < itemcnt; ++i) { + if (HASHITEM_EMPTY(hash_find(&spin->si_commonwords, + items[i]))) { + p = vim_strsave(items[i]); + hash_add(&spin->si_commonwords, p); + } + } + } else + smsg(_("Unrecognized or duplicate item in %s line %d: %s"), + fname, lnum, items[0]); + } + } + + if (fol != NULL || low != NULL || upp != NULL) { + if (spin->si_clear_chartab) { + // Clear the char type tables, don't want to use any of the + // currently used spell properties. + init_spell_chartab(); + spin->si_clear_chartab = false; + } + + // Don't write a word table for an ASCII file, so that we don't check + // for conflicts with a word table that matches 'encoding'. + // Don't write one for utf-8 either, we use utf_*() and + // mb_get_class(), the list of chars in the file will be incomplete. + if (!spin->si_ascii + && !enc_utf8 + ) { + if (fol == NULL || low == NULL || upp == NULL) + smsg(_("Missing FOL/LOW/UPP line in %s"), fname); + else + (void)set_spell_chartab(fol, low, upp); + } + + xfree(fol); + xfree(low); + xfree(upp); + } + + // Use compound specifications of the .aff file for the spell info. + if (compmax != 0) { + aff_check_number(spin->si_compmax, compmax, "COMPOUNDWORDMAX"); + spin->si_compmax = compmax; + } + + if (compminlen != 0) { + aff_check_number(spin->si_compminlen, compminlen, "COMPOUNDMIN"); + spin->si_compminlen = compminlen; + } + + if (compsylmax != 0) { + if (syllable == NULL) + smsg(_("COMPOUNDSYLMAX used without SYLLABLE")); + aff_check_number(spin->si_compsylmax, compsylmax, "COMPOUNDSYLMAX"); + spin->si_compsylmax = compsylmax; + } + + if (compoptions != 0) { + aff_check_number(spin->si_compoptions, compoptions, "COMPOUND options"); + spin->si_compoptions |= compoptions; + } + + if (compflags != NULL) + process_compflags(spin, aff, compflags); + + // Check that we didn't use too many renumbered flags. + if (spin->si_newcompID < spin->si_newprefID) { + if (spin->si_newcompID == 127 || spin->si_newcompID == 255) + MSG(_("Too many postponed prefixes")); + else if (spin->si_newprefID == 0 || spin->si_newprefID == 127) + MSG(_("Too many compound flags")); + else + MSG(_("Too many postponed prefixes and/or compound flags")); + } + + if (syllable != NULL) { + aff_check_string(spin->si_syllable, syllable, "SYLLABLE"); + spin->si_syllable = syllable; + } + + if (sofofrom != NULL || sofoto != NULL) { + if (sofofrom == NULL || sofoto == NULL) + smsg(_("Missing SOFO%s line in %s"), + sofofrom == NULL ? "FROM" : "TO", fname); + else if (!GA_EMPTY(&spin->si_sal)) + smsg(_("Both SAL and SOFO lines in %s"), fname); + else { + aff_check_string(spin->si_sofofr, sofofrom, "SOFOFROM"); + aff_check_string(spin->si_sofoto, sofoto, "SOFOTO"); + spin->si_sofofr = sofofrom; + spin->si_sofoto = sofoto; + } + } + + if (midword != NULL) { + aff_check_string(spin->si_midword, midword, "MIDWORD"); + spin->si_midword = midword; + } + + xfree(pc); + fclose(fd); + return aff; +} + +// Returns true when items[0] equals "rulename", there are "mincount" items or +// a comment is following after item "mincount". +static bool is_aff_rule(char_u **items, int itemcnt, char *rulename, int mincount) +{ + return STRCMP(items[0], rulename) == 0 + && (itemcnt == mincount + || (itemcnt > mincount && items[mincount][0] == '#')); +} + +// For affix "entry" move COMPOUNDFORBIDFLAG and COMPOUNDPERMITFLAG from +// ae_flags to ae_comppermit and ae_compforbid. +static void aff_process_flags(afffile_T *affile, affentry_T *entry) +{ + char_u *p; + char_u *prevp; + unsigned flag; + + if (entry->ae_flags != NULL + && (affile->af_compforbid != 0 || affile->af_comppermit != 0)) { + for (p = entry->ae_flags; *p != NUL; ) { + prevp = p; + flag = get_affitem(affile->af_flagtype, &p); + if (flag == affile->af_comppermit || flag == affile->af_compforbid) { + STRMOVE(prevp, p); + p = prevp; + if (flag == affile->af_comppermit) + entry->ae_comppermit = true; + else + entry->ae_compforbid = true; + } + if (affile->af_flagtype == AFT_NUM && *p == ',') + ++p; + } + if (*entry->ae_flags == NUL) + entry->ae_flags = NULL; // nothing left + } +} + +// Returns true if "s" is the name of an info item in the affix file. +static bool spell_info_item(char_u *s) +{ + return STRCMP(s, "NAME") == 0 + || STRCMP(s, "HOME") == 0 + || STRCMP(s, "VERSION") == 0 + || STRCMP(s, "AUTHOR") == 0 + || STRCMP(s, "EMAIL") == 0 + || STRCMP(s, "COPYRIGHT") == 0; +} + +// Turn an affix flag name into a number, according to the FLAG type. +// returns zero for failure. +static unsigned affitem2flag(int flagtype, char_u *item, char_u *fname, int lnum) +{ + unsigned res; + char_u *p = item; + + res = get_affitem(flagtype, &p); + if (res == 0) { + if (flagtype == AFT_NUM) + smsg(_("Flag is not a number in %s line %d: %s"), + fname, lnum, item); + else + smsg(_("Illegal flag in %s line %d: %s"), + fname, lnum, item); + } + if (*p != NUL) { + smsg(_(e_affname), fname, lnum, item); + return 0; + } + + return res; +} + +// Get one affix name from "*pp" and advance the pointer. +// Returns zero for an error, still advances the pointer then. +static unsigned get_affitem(int flagtype, char_u **pp) +{ + int res; + + if (flagtype == AFT_NUM) { + if (!ascii_isdigit(**pp)) { + ++*pp; // always advance, avoid getting stuck + return 0; + } + res = getdigits_int(pp); + } else { + res = mb_ptr2char_adv((const char_u **)pp); + if (flagtype == AFT_LONG || (flagtype == AFT_CAPLONG + && res >= 'A' && res <= 'Z')) { + if (**pp == NUL) + return 0; + res = mb_ptr2char_adv((const char_u **)pp) + (res << 16); + } + } + return res; +} + +// Process the "compflags" string used in an affix file and append it to +// spin->si_compflags. +// The processing involves changing the affix names to ID numbers, so that +// they fit in one byte. +static void process_compflags(spellinfo_T *spin, afffile_T *aff, char_u *compflags) +{ + char_u *p; + char_u *prevp; + unsigned flag; + compitem_T *ci; + int id; + int len; + char_u *tp; + char_u key[AH_KEY_LEN]; + hashitem_T *hi; + + // Make room for the old and the new compflags, concatenated with a / in + // between. Processing it makes it shorter, but we don't know by how + // much, thus allocate the maximum. + len = (int)STRLEN(compflags) + 1; + if (spin->si_compflags != NULL) + len += (int)STRLEN(spin->si_compflags) + 1; + p = getroom(spin, len, false); + if (spin->si_compflags != NULL) { + STRCPY(p, spin->si_compflags); + STRCAT(p, "/"); + } + spin->si_compflags = p; + tp = p + STRLEN(p); + + for (p = compflags; *p != NUL; ) { + if (vim_strchr((char_u *)"/?*+[]", *p) != NULL) + // Copy non-flag characters directly. + *tp++ = *p++; + else { + // First get the flag number, also checks validity. + prevp = p; + flag = get_affitem(aff->af_flagtype, &p); + if (flag != 0) { + // Find the flag in the hashtable. If it was used before, use + // the existing ID. Otherwise add a new entry. + STRLCPY(key, prevp, p - prevp + 1); + hi = hash_find(&aff->af_comp, key); + if (!HASHITEM_EMPTY(hi)) + id = HI2CI(hi)->ci_newID; + else { + ci = (compitem_T *)getroom(spin, sizeof(compitem_T), true); + if (ci == NULL) + break; + STRCPY(ci->ci_key, key); + ci->ci_flag = flag; + // Avoid using a flag ID that has a special meaning in a + // regexp (also inside []). + do { + check_renumber(spin); + id = spin->si_newcompID--; + } while (vim_strchr((char_u *)"/?*+[]\\-^", id) != NULL); + ci->ci_newID = id; + hash_add(&aff->af_comp, ci->ci_key); + } + *tp++ = id; + } + if (aff->af_flagtype == AFT_NUM && *p == ',') + ++p; + } + } + + *tp = NUL; +} + +// Check that the new IDs for postponed affixes and compounding don't overrun +// each other. We have almost 255 available, but start at 0-127 to avoid +// using two bytes for utf-8. When the 0-127 range is used up go to 128-255. +// When that is used up an error message is given. +static void check_renumber(spellinfo_T *spin) +{ + if (spin->si_newprefID == spin->si_newcompID && spin->si_newcompID < 128) { + spin->si_newprefID = 127; + spin->si_newcompID = 255; + } +} + +// Returns true if flag "flag" appears in affix list "afflist". +static bool flag_in_afflist(int flagtype, char_u *afflist, unsigned flag) +{ + char_u *p; + unsigned n; + + switch (flagtype) { + case AFT_CHAR: + return vim_strchr(afflist, flag) != NULL; + + case AFT_CAPLONG: + case AFT_LONG: + for (p = afflist; *p != NUL; ) { + n = mb_ptr2char_adv((const char_u **)&p); + if ((flagtype == AFT_LONG || (n >= 'A' && n <= 'Z')) + && *p != NUL) { + n = mb_ptr2char_adv((const char_u **)&p) + (n << 16); + } + if (n == flag) { + return true; + } + } + break; + + case AFT_NUM: + for (p = afflist; *p != NUL; ) { + int digits = getdigits_int(&p); + assert(digits >= 0); + n = (unsigned int)digits; + if (n == flag) + return true; + if (*p != NUL) // skip over comma + ++p; + } + break; + } + return false; +} + +// Give a warning when "spinval" and "affval" numbers are set and not the same. +static void aff_check_number(int spinval, int affval, char *name) +{ + if (spinval != 0 && spinval != affval) + smsg(_("%s value differs from what is used in another .aff file"), + name); +} + +// Give a warning when "spinval" and "affval" strings are set and not the same. +static void aff_check_string(char_u *spinval, char_u *affval, char *name) +{ + if (spinval != NULL && STRCMP(spinval, affval) != 0) + smsg(_("%s value differs from what is used in another .aff file"), + name); +} + +// Returns true if strings "s1" and "s2" are equal. Also consider both being +// NULL as equal. +static bool str_equal(char_u *s1, char_u *s2) +{ + if (s1 == NULL || s2 == NULL) + return s1 == s2; + return STRCMP(s1, s2) == 0; +} + +// Add a from-to item to "gap". Used for REP and SAL items. +// They are stored case-folded. +static void add_fromto(spellinfo_T *spin, garray_T *gap, char_u *from, char_u *to) +{ + char_u word[MAXWLEN]; + + fromto_T *ftp = GA_APPEND_VIA_PTR(fromto_T, gap); + (void)spell_casefold(from, (int)STRLEN(from), word, MAXWLEN); + ftp->ft_from = getroom_save(spin, word); + (void)spell_casefold(to, (int)STRLEN(to), word, MAXWLEN); + ftp->ft_to = getroom_save(spin, word); +} + +// Converts a boolean argument in a SAL line to true or false; +static bool sal_to_bool(char_u *s) +{ + return STRCMP(s, "1") == 0 || STRCMP(s, "true") == 0; +} + +// Free the structure filled by spell_read_aff(). +static void spell_free_aff(afffile_T *aff) +{ + hashtab_T *ht; + hashitem_T *hi; + int todo; + affheader_T *ah; + affentry_T *ae; + + xfree(aff->af_enc); + + // All this trouble to free the "ae_prog" items... + for (ht = &aff->af_pref;; ht = &aff->af_suff) { + todo = (int)ht->ht_used; + for (hi = ht->ht_array; todo > 0; ++hi) { + if (!HASHITEM_EMPTY(hi)) { + --todo; + ah = HI2AH(hi); + for (ae = ah->ah_first; ae != NULL; ae = ae->ae_next) + vim_regfree(ae->ae_prog); + } + } + if (ht == &aff->af_suff) + break; + } + + hash_clear(&aff->af_pref); + hash_clear(&aff->af_suff); + hash_clear(&aff->af_comp); +} + +// Read dictionary file "fname". +// Returns OK or FAIL; +static int spell_read_dic(spellinfo_T *spin, char_u *fname, afffile_T *affile) +{ + hashtab_T ht; + char_u line[MAXLINELEN]; + char_u *p; + char_u *afflist; + char_u store_afflist[MAXWLEN]; + int pfxlen; + bool need_affix; + char_u *dw; + char_u *pc; + char_u *w; + int l; + hash_T hash; + hashitem_T *hi; + FILE *fd; + int lnum = 1; + int non_ascii = 0; + int retval = OK; + char_u message[MAXLINELEN + MAXWLEN]; + int flags; + int duplicate = 0; + + // Open the file. + fd = mch_fopen((char *)fname, "r"); + if (fd == NULL) { + EMSG2(_(e_notopen), fname); + return FAIL; + } + + // The hashtable is only used to detect duplicated words. + hash_init(&ht); + + vim_snprintf((char *)IObuff, IOSIZE, + _("Reading dictionary file %s ..."), fname); + spell_message(spin, IObuff); + + // start with a message for the first line + spin->si_msg_count = 999999; + + // Read and ignore the first line: word count. + (void)vim_fgets(line, MAXLINELEN, fd); + if (!ascii_isdigit(*skipwhite(line))) + EMSG2(_("E760: No word count in %s"), fname); + + // Read all the lines in the file one by one. + // The words are converted to 'encoding' here, before being added to + // the hashtable. + while (!vim_fgets(line, MAXLINELEN, fd) && !got_int) { + line_breakcheck(); + ++lnum; + if (line[0] == '#' || line[0] == '/') + continue; // comment line + + // Remove CR, LF and white space from the end. White space halfway through + // the word is kept to allow multi-word terms like "et al.". + l = (int)STRLEN(line); + while (l > 0 && line[l - 1] <= ' ') + --l; + if (l == 0) + continue; // empty line + line[l] = NUL; + + // Convert from "SET" to 'encoding' when needed. + if (spin->si_conv.vc_type != CONV_NONE) { + pc = string_convert(&spin->si_conv, line, NULL); + if (pc == NULL) { + smsg(_("Conversion failure for word in %s line %d: %s"), + fname, lnum, line); + continue; + } + w = pc; + } else { + pc = NULL; + w = line; + } + + // Truncate the word at the "/", set "afflist" to what follows. + // Replace "\/" by "/" and "\\" by "\". + afflist = NULL; + for (p = w; *p != NUL; mb_ptr_adv(p)) { + if (*p == '\\' && (p[1] == '\\' || p[1] == '/')) + STRMOVE(p, p + 1); + else if (*p == '/') { + *p = NUL; + afflist = p + 1; + break; + } + } + + // Skip non-ASCII words when "spin->si_ascii" is true. + if (spin->si_ascii && has_non_ascii(w)) { + ++non_ascii; + xfree(pc); + continue; + } + + // This takes time, print a message every 10000 words. + if (spin->si_verbose && spin->si_msg_count > 10000) { + spin->si_msg_count = 0; + vim_snprintf((char *)message, sizeof(message), + _("line %6d, word %6d - %s"), + lnum, spin->si_foldwcount + spin->si_keepwcount, w); + msg_start(); + msg_puts_long_attr(message, 0); + msg_clr_eos(); + msg_didout = FALSE; + msg_col = 0; + ui_flush(); + } + + // Store the word in the hashtable to be able to find duplicates. + dw = getroom_save(spin, w); + if (dw == NULL) { + retval = FAIL; + xfree(pc); + break; + } + + hash = hash_hash(dw); + hi = hash_lookup(&ht, (const char *)dw, STRLEN(dw), hash); + if (!HASHITEM_EMPTY(hi)) { + if (p_verbose > 0) + smsg(_("Duplicate word in %s line %d: %s"), + fname, lnum, dw); + else if (duplicate == 0) + smsg(_("First duplicate word in %s line %d: %s"), + fname, lnum, dw); + ++duplicate; + } else + hash_add_item(&ht, hi, dw, hash); + + flags = 0; + store_afflist[0] = NUL; + pfxlen = 0; + need_affix = false; + if (afflist != NULL) { + // Extract flags from the affix list. + flags |= get_affix_flags(affile, afflist); + + if (affile->af_needaffix != 0 && flag_in_afflist( + affile->af_flagtype, afflist, affile->af_needaffix)) + need_affix = true; + + if (affile->af_pfxpostpone) + // Need to store the list of prefix IDs with the word. + pfxlen = get_pfxlist(affile, afflist, store_afflist); + + if (spin->si_compflags != NULL) + // Need to store the list of compound flags with the word. + // Concatenate them to the list of prefix IDs. + get_compflags(affile, afflist, store_afflist + pfxlen); + } + + // Add the word to the word tree(s). + if (store_word(spin, dw, flags, spin->si_region, + store_afflist, need_affix) == FAIL) + retval = FAIL; + + if (afflist != NULL) { + // Find all matching suffixes and add the resulting words. + // Additionally do matching prefixes that combine. + if (store_aff_word(spin, dw, afflist, affile, + &affile->af_suff, &affile->af_pref, + CONDIT_SUF, flags, store_afflist, pfxlen) == FAIL) + retval = FAIL; + + // Find all matching prefixes and add the resulting words. + if (store_aff_word(spin, dw, afflist, affile, + &affile->af_pref, NULL, + CONDIT_SUF, flags, store_afflist, pfxlen) == FAIL) + retval = FAIL; + } + + xfree(pc); + } + + if (duplicate > 0) + smsg(_("%d duplicate word(s) in %s"), duplicate, fname); + if (spin->si_ascii && non_ascii > 0) + smsg(_("Ignored %d word(s) with non-ASCII characters in %s"), + non_ascii, fname); + hash_clear(&ht); + + fclose(fd); + return retval; +} + +// Check for affix flags in "afflist" that are turned into word flags. +// Return WF_ flags. +static int get_affix_flags(afffile_T *affile, char_u *afflist) +{ + int flags = 0; + + if (affile->af_keepcase != 0 && flag_in_afflist( + affile->af_flagtype, afflist, affile->af_keepcase)) + flags |= WF_KEEPCAP | WF_FIXCAP; + if (affile->af_rare != 0 && flag_in_afflist( + affile->af_flagtype, afflist, affile->af_rare)) + flags |= WF_RARE; + if (affile->af_bad != 0 && flag_in_afflist( + affile->af_flagtype, afflist, affile->af_bad)) + flags |= WF_BANNED; + if (affile->af_needcomp != 0 && flag_in_afflist( + affile->af_flagtype, afflist, affile->af_needcomp)) + flags |= WF_NEEDCOMP; + if (affile->af_comproot != 0 && flag_in_afflist( + affile->af_flagtype, afflist, affile->af_comproot)) + flags |= WF_COMPROOT; + if (affile->af_nosuggest != 0 && flag_in_afflist( + affile->af_flagtype, afflist, affile->af_nosuggest)) + flags |= WF_NOSUGGEST; + return flags; +} + +// Get the list of prefix IDs from the affix list "afflist". +// Used for PFXPOSTPONE. +// Put the resulting flags in "store_afflist[MAXWLEN]" with a terminating NUL +// and return the number of affixes. +static int get_pfxlist(afffile_T *affile, char_u *afflist, char_u *store_afflist) +{ + char_u *p; + char_u *prevp; + int cnt = 0; + int id; + char_u key[AH_KEY_LEN]; + hashitem_T *hi; + + for (p = afflist; *p != NUL; ) { + prevp = p; + if (get_affitem(affile->af_flagtype, &p) != 0) { + // A flag is a postponed prefix flag if it appears in "af_pref" + // and it's ID is not zero. + STRLCPY(key, prevp, p - prevp + 1); + hi = hash_find(&affile->af_pref, key); + if (!HASHITEM_EMPTY(hi)) { + id = HI2AH(hi)->ah_newID; + if (id != 0) + store_afflist[cnt++] = id; + } + } + if (affile->af_flagtype == AFT_NUM && *p == ',') + ++p; + } + + store_afflist[cnt] = NUL; + return cnt; +} + +// Get the list of compound IDs from the affix list "afflist" that are used +// for compound words. +// Puts the flags in "store_afflist[]". +static void get_compflags(afffile_T *affile, char_u *afflist, char_u *store_afflist) +{ + char_u *p; + char_u *prevp; + int cnt = 0; + char_u key[AH_KEY_LEN]; + hashitem_T *hi; + + for (p = afflist; *p != NUL; ) { + prevp = p; + if (get_affitem(affile->af_flagtype, &p) != 0) { + // A flag is a compound flag if it appears in "af_comp". + STRLCPY(key, prevp, p - prevp + 1); + hi = hash_find(&affile->af_comp, key); + if (!HASHITEM_EMPTY(hi)) + store_afflist[cnt++] = HI2CI(hi)->ci_newID; + } + if (affile->af_flagtype == AFT_NUM && *p == ',') + ++p; + } + + store_afflist[cnt] = NUL; +} + +// Apply affixes to a word and store the resulting words. +// "ht" is the hashtable with affentry_T that need to be applied, either +// prefixes or suffixes. +// "xht", when not NULL, is the prefix hashtable, to be used additionally on +// the resulting words for combining affixes. +// +// Returns FAIL when out of memory. +static int +store_aff_word ( + spellinfo_T *spin, // spell info + char_u *word, // basic word start + char_u *afflist, // list of names of supported affixes + afffile_T *affile, + hashtab_T *ht, + hashtab_T *xht, + int condit, // CONDIT_SUF et al. + int flags, // flags for the word + char_u *pfxlist, // list of prefix IDs + int pfxlen // nr of flags in "pfxlist" for prefixes, rest + // is compound flags +) +{ + int todo; + hashitem_T *hi; + affheader_T *ah; + affentry_T *ae; + char_u newword[MAXWLEN]; + int retval = OK; + int i, j; + char_u *p; + int use_flags; + char_u *use_pfxlist; + int use_pfxlen; + bool need_affix; + char_u store_afflist[MAXWLEN]; + char_u pfx_pfxlist[MAXWLEN]; + size_t wordlen = STRLEN(word); + int use_condit; + + todo = (int)ht->ht_used; + for (hi = ht->ht_array; todo > 0 && retval == OK; ++hi) { + if (!HASHITEM_EMPTY(hi)) { + --todo; + ah = HI2AH(hi); + + // Check that the affix combines, if required, and that the word + // supports this affix. + if (((condit & CONDIT_COMB) == 0 || ah->ah_combine) + && flag_in_afflist(affile->af_flagtype, afflist, + ah->ah_flag)) { + // Loop over all affix entries with this name. + for (ae = ah->ah_first; ae != NULL; ae = ae->ae_next) { + // Check the condition. It's not logical to match case + // here, but it is required for compatibility with + // Myspell. + // Another requirement from Myspell is that the chop + // string is shorter than the word itself. + // For prefixes, when "PFXPOSTPONE" was used, only do + // prefixes with a chop string and/or flags. + // When a previously added affix had CIRCUMFIX this one + // must have it too, if it had not then this one must not + // have one either. + if ((xht != NULL || !affile->af_pfxpostpone + || ae->ae_chop != NULL + || ae->ae_flags != NULL) + && (ae->ae_chop == NULL + || STRLEN(ae->ae_chop) < wordlen) + && (ae->ae_prog == NULL + || vim_regexec_prog(&ae->ae_prog, false, word, (colnr_T)0)) + && (((condit & CONDIT_CFIX) == 0) + == ((condit & CONDIT_AFF) == 0 + || ae->ae_flags == NULL + || !flag_in_afflist(affile->af_flagtype, + ae->ae_flags, affile->af_circumfix)))) { + // Match. Remove the chop and add the affix. + if (xht == NULL) { + // prefix: chop/add at the start of the word + if (ae->ae_add == NULL) + *newword = NUL; + else + STRLCPY(newword, ae->ae_add, MAXWLEN); + p = word; + if (ae->ae_chop != NULL) { + // Skip chop string. + if (has_mbyte) { + i = mb_charlen(ae->ae_chop); + for (; i > 0; --i) + mb_ptr_adv(p); + } else + p += STRLEN(ae->ae_chop); + } + STRCAT(newword, p); + } else { + // suffix: chop/add at the end of the word + STRLCPY(newword, word, MAXWLEN); + if (ae->ae_chop != NULL) { + // Remove chop string. + p = newword + STRLEN(newword); + i = (int)MB_CHARLEN(ae->ae_chop); + for (; i > 0; --i) + mb_ptr_back(newword, p); + *p = NUL; + } + if (ae->ae_add != NULL) + STRCAT(newword, ae->ae_add); + } + + use_flags = flags; + use_pfxlist = pfxlist; + use_pfxlen = pfxlen; + need_affix = false; + use_condit = condit | CONDIT_COMB | CONDIT_AFF; + if (ae->ae_flags != NULL) { + // Extract flags from the affix list. + use_flags |= get_affix_flags(affile, ae->ae_flags); + + if (affile->af_needaffix != 0 && flag_in_afflist( + affile->af_flagtype, ae->ae_flags, + affile->af_needaffix)) + need_affix = true; + + // When there is a CIRCUMFIX flag the other affix + // must also have it and we don't add the word + // with one affix. + if (affile->af_circumfix != 0 && flag_in_afflist( + affile->af_flagtype, ae->ae_flags, + affile->af_circumfix)) { + use_condit |= CONDIT_CFIX; + if ((condit & CONDIT_CFIX) == 0) + need_affix = true; + } + + if (affile->af_pfxpostpone + || spin->si_compflags != NULL) { + if (affile->af_pfxpostpone) + // Get prefix IDS from the affix list. + use_pfxlen = get_pfxlist(affile, + ae->ae_flags, store_afflist); + else + use_pfxlen = 0; + use_pfxlist = store_afflist; + + // Combine the prefix IDs. Avoid adding the + // same ID twice. + for (i = 0; i < pfxlen; ++i) { + for (j = 0; j < use_pfxlen; ++j) + if (pfxlist[i] == use_pfxlist[j]) + break; + if (j == use_pfxlen) + use_pfxlist[use_pfxlen++] = pfxlist[i]; + } + + if (spin->si_compflags != NULL) + // Get compound IDS from the affix list. + get_compflags(affile, ae->ae_flags, + use_pfxlist + use_pfxlen); + else + use_pfxlist[use_pfxlen] = NUL; + + // Combine the list of compound flags. + // Concatenate them to the prefix IDs list. + // Avoid adding the same ID twice. + for (i = pfxlen; pfxlist[i] != NUL; ++i) { + for (j = use_pfxlen; + use_pfxlist[j] != NUL; ++j) + if (pfxlist[i] == use_pfxlist[j]) + break; + if (use_pfxlist[j] == NUL) { + use_pfxlist[j++] = pfxlist[i]; + use_pfxlist[j] = NUL; + } + } + } + } + + // Obey a "COMPOUNDFORBIDFLAG" of the affix: don't + // use the compound flags. + if (use_pfxlist != NULL && ae->ae_compforbid) { + STRLCPY(pfx_pfxlist, use_pfxlist, use_pfxlen + 1); + use_pfxlist = pfx_pfxlist; + } + + // When there are postponed prefixes... + if (spin->si_prefroot != NULL + && spin->si_prefroot->wn_sibling != NULL) { + // ... add a flag to indicate an affix was used. + use_flags |= WF_HAS_AFF; + + // ... don't use a prefix list if combining + // affixes is not allowed. But do use the + // compound flags after them. + if (!ah->ah_combine && use_pfxlist != NULL) + use_pfxlist += use_pfxlen; + } + + // When compounding is supported and there is no + // "COMPOUNDPERMITFLAG" then forbid compounding on the + // side where the affix is applied. + if (spin->si_compflags != NULL && !ae->ae_comppermit) { + if (xht != NULL) + use_flags |= WF_NOCOMPAFT; + else + use_flags |= WF_NOCOMPBEF; + } + + // Store the modified word. + if (store_word(spin, newword, use_flags, + spin->si_region, use_pfxlist, + need_affix) == FAIL) + retval = FAIL; + + // When added a prefix or a first suffix and the affix + // has flags may add a(nother) suffix. RECURSIVE! + if ((condit & CONDIT_SUF) && ae->ae_flags != NULL) + if (store_aff_word(spin, newword, ae->ae_flags, + affile, &affile->af_suff, xht, + use_condit & (xht == NULL + ? ~0 : ~CONDIT_SUF), + use_flags, use_pfxlist, pfxlen) == FAIL) + retval = FAIL; + + // When added a suffix and combining is allowed also + // try adding a prefix additionally. Both for the + // word flags and for the affix flags. RECURSIVE! + if (xht != NULL && ah->ah_combine) { + if (store_aff_word(spin, newword, + afflist, affile, + xht, NULL, use_condit, + use_flags, use_pfxlist, + pfxlen) == FAIL + || (ae->ae_flags != NULL + && store_aff_word(spin, newword, + ae->ae_flags, affile, + xht, NULL, use_condit, + use_flags, use_pfxlist, + pfxlen) == FAIL)) + retval = FAIL; + } + } + } + } + } + } + + return retval; +} + +// Read a file with a list of words. +static int spell_read_wordfile(spellinfo_T *spin, char_u *fname) +{ + FILE *fd; + long lnum = 0; + char_u rline[MAXLINELEN]; + char_u *line; + char_u *pc = NULL; + char_u *p; + int l; + int retval = OK; + bool did_word = false; + int non_ascii = 0; + int flags; + int regionmask; + + // Open the file. + fd = mch_fopen((char *)fname, "r"); + if (fd == NULL) { + EMSG2(_(e_notopen), fname); + return FAIL; + } + + vim_snprintf((char *)IObuff, IOSIZE, _("Reading word file %s ..."), fname); + spell_message(spin, IObuff); + + // Read all the lines in the file one by one. + while (!vim_fgets(rline, MAXLINELEN, fd) && !got_int) { + line_breakcheck(); + ++lnum; + + // Skip comment lines. + if (*rline == '#') + continue; + + // Remove CR, LF and white space from the end. + l = (int)STRLEN(rline); + while (l > 0 && rline[l - 1] <= ' ') + --l; + if (l == 0) + continue; // empty or blank line + rline[l] = NUL; + + // Convert from "/encoding={encoding}" to 'encoding' when needed. + xfree(pc); + if (spin->si_conv.vc_type != CONV_NONE) { + pc = string_convert(&spin->si_conv, rline, NULL); + if (pc == NULL) { + smsg(_("Conversion failure for word in %s line %d: %s"), + fname, lnum, rline); + continue; + } + line = pc; + } else { + pc = NULL; + line = rline; + } + + if (*line == '/') { + ++line; + if (STRNCMP(line, "encoding=", 9) == 0) { + if (spin->si_conv.vc_type != CONV_NONE) + smsg(_("Duplicate /encoding= line ignored in %s line %d: %s"), + fname, lnum, line - 1); + else if (did_word) + smsg(_("/encoding= line after word ignored in %s line %d: %s"), + fname, lnum, line - 1); + else { + char_u *enc; + + // Setup for conversion to 'encoding'. + line += 9; + enc = enc_canonize(line); + if (!spin->si_ascii + && convert_setup(&spin->si_conv, enc, + p_enc) == FAIL) + smsg(_("Conversion in %s not supported: from %s to %s"), + fname, line, p_enc); + xfree(enc); + spin->si_conv.vc_fail = true; + } + continue; + } + + if (STRNCMP(line, "regions=", 8) == 0) { + if (spin->si_region_count > 1) + smsg(_("Duplicate /regions= line ignored in %s line %d: %s"), + fname, lnum, line); + else { + line += 8; + if (STRLEN(line) > 16) + smsg(_("Too many regions in %s line %d: %s"), + fname, lnum, line); + else { + spin->si_region_count = (int)STRLEN(line) / 2; + STRCPY(spin->si_region_name, line); + + // Adjust the mask for a word valid in all regions. + spin->si_region = (1 << spin->si_region_count) - 1; + } + } + continue; + } + + smsg(_("/ line ignored in %s line %d: %s"), + fname, lnum, line - 1); + continue; + } + + flags = 0; + regionmask = spin->si_region; + + // Check for flags and region after a slash. + p = vim_strchr(line, '/'); + if (p != NULL) { + *p++ = NUL; + while (*p != NUL) { + if (*p == '=') // keep-case word + flags |= WF_KEEPCAP | WF_FIXCAP; + else if (*p == '!') // Bad, bad, wicked word. + flags |= WF_BANNED; + else if (*p == '?') // Rare word. + flags |= WF_RARE; + else if (ascii_isdigit(*p)) { // region number(s) + if ((flags & WF_REGION) == 0) // first one + regionmask = 0; + flags |= WF_REGION; + + l = *p - '0'; + if (l > spin->si_region_count) { + smsg(_("Invalid region nr in %s line %d: %s"), + fname, lnum, p); + break; + } + regionmask |= 1 << (l - 1); + } else { + smsg(_("Unrecognized flags in %s line %d: %s"), + fname, lnum, p); + break; + } + ++p; + } + } + + // Skip non-ASCII words when "spin->si_ascii" is true. + if (spin->si_ascii && has_non_ascii(line)) { + ++non_ascii; + continue; + } + + // Normal word: store it. + if (store_word(spin, line, flags, regionmask, NULL, false) == FAIL) { + retval = FAIL; + break; + } + did_word = true; + } + + xfree(pc); + fclose(fd); + + if (spin->si_ascii && non_ascii > 0) { + vim_snprintf((char *)IObuff, IOSIZE, + _("Ignored %d words with non-ASCII characters"), non_ascii); + spell_message(spin, IObuff); + } + + return retval; +} + +/// Get part of an sblock_T, "len" bytes long. +/// This avoids calling free() for every little struct we use (and keeping +/// track of them). +/// The memory is cleared to all zeros. +/// +/// @param len Length needed (<= SBLOCKSIZE). +/// @param align Align for pointer. +/// @return Pointer into block data. +static void *getroom(spellinfo_T *spin, size_t len, bool align) + FUNC_ATTR_NONNULL_RET +{ + char_u *p; + sblock_T *bl = spin->si_blocks; + + assert(len <= SBLOCKSIZE); + + if (align && bl != NULL) + // Round size up for alignment. On some systems structures need to be + // aligned to the size of a pointer (e.g., SPARC). + bl->sb_used = (bl->sb_used + sizeof(char *) - 1) + & ~(sizeof(char *) - 1); + + if (bl == NULL || bl->sb_used + len > SBLOCKSIZE) { + // Allocate a block of memory. It is not freed until much later. + bl = xcalloc(1, (sizeof(sblock_T) + SBLOCKSIZE)); + bl->sb_next = spin->si_blocks; + spin->si_blocks = bl; + bl->sb_used = 0; + ++spin->si_blocks_cnt; + } + + p = bl->sb_data + bl->sb_used; + bl->sb_used += (int)len; + + return p; +} + +// Make a copy of a string into memory allocated with getroom(). +// Returns NULL when out of memory. +static char_u *getroom_save(spellinfo_T *spin, char_u *s) +{ + char_u *sc; + + sc = (char_u *)getroom(spin, STRLEN(s) + 1, false); + if (sc != NULL) + STRCPY(sc, s); + return sc; +} + + +// Free the list of allocated sblock_T. +static void free_blocks(sblock_T *bl) +{ + sblock_T *next; + + while (bl != NULL) { + next = bl->sb_next; + xfree(bl); + bl = next; + } +} + +// Allocate the root of a word tree. +// Returns NULL when out of memory. +static wordnode_T *wordtree_alloc(spellinfo_T *spin) +{ + return (wordnode_T *)getroom(spin, sizeof(wordnode_T), true); +} + +// Store a word in the tree(s). +// Always store it in the case-folded tree. For a keep-case word this is +// useful when the word can also be used with all caps (no WF_FIXCAP flag) and +// used to find suggestions. +// For a keep-case word also store it in the keep-case tree. +// When "pfxlist" is not NULL store the word for each postponed prefix ID and +// compound flag. +static int +store_word ( + spellinfo_T *spin, + char_u *word, + int flags, // extra flags, WF_BANNED + int region, // supported region(s) + char_u *pfxlist, // list of prefix IDs or NULL + bool need_affix // only store word with affix ID +) +{ + int len = (int)STRLEN(word); + int ct = captype(word, word + len); + char_u foldword[MAXWLEN]; + int res = OK; + char_u *p; + + (void)spell_casefold(word, len, foldword, MAXWLEN); + for (p = pfxlist; res == OK; ++p) { + if (!need_affix || (p != NULL && *p != NUL)) + res = tree_add_word(spin, foldword, spin->si_foldroot, ct | flags, + region, p == NULL ? 0 : *p); + if (p == NULL || *p == NUL) + break; + } + ++spin->si_foldwcount; + + if (res == OK && (ct == WF_KEEPCAP || (flags & WF_KEEPCAP))) { + for (p = pfxlist; res == OK; ++p) { + if (!need_affix || (p != NULL && *p != NUL)) + res = tree_add_word(spin, word, spin->si_keeproot, flags, + region, p == NULL ? 0 : *p); + if (p == NULL || *p == NUL) + break; + } + ++spin->si_keepwcount; + } + return res; +} + +// Add word "word" to a word tree at "root". +// When "flags" < 0 we are adding to the prefix tree where "flags" is used for +// "rare" and "region" is the condition nr. +// Returns FAIL when out of memory. +static int tree_add_word(spellinfo_T *spin, char_u *word, wordnode_T *root, int flags, int region, int affixID) +{ + wordnode_T *node = root; + wordnode_T *np; + wordnode_T *copyp, **copyprev; + wordnode_T **prev = NULL; + int i; + + // Add each byte of the word to the tree, including the NUL at the end. + for (i = 0;; ++i) { + // When there is more than one reference to this node we need to make + // a copy, so that we can modify it. Copy the whole list of siblings + // (we don't optimize for a partly shared list of siblings). + if (node != NULL && node->wn_refs > 1) { + --node->wn_refs; + copyprev = prev; + for (copyp = node; copyp != NULL; copyp = copyp->wn_sibling) { + // Allocate a new node and copy the info. + np = get_wordnode(spin); + if (np == NULL) + return FAIL; + np->wn_child = copyp->wn_child; + if (np->wn_child != NULL) + ++np->wn_child->wn_refs; // child gets extra ref + np->wn_byte = copyp->wn_byte; + if (np->wn_byte == NUL) { + np->wn_flags = copyp->wn_flags; + np->wn_region = copyp->wn_region; + np->wn_affixID = copyp->wn_affixID; + } + + // Link the new node in the list, there will be one ref. + np->wn_refs = 1; + if (copyprev != NULL) + *copyprev = np; + copyprev = &np->wn_sibling; + + // Let "node" point to the head of the copied list. + if (copyp == node) + node = np; + } + } + + // Look for the sibling that has the same character. They are sorted + // on byte value, thus stop searching when a sibling is found with a + // higher byte value. For zero bytes (end of word) the sorting is + // done on flags and then on affixID. + while (node != NULL + && (node->wn_byte < word[i] + || (node->wn_byte == NUL + && (flags < 0 + ? node->wn_affixID < (unsigned)affixID + : (node->wn_flags < (unsigned)(flags & WN_MASK) + || (node->wn_flags == (flags & WN_MASK) + && (spin->si_sugtree + ? (node->wn_region & 0xffff) < region + : node->wn_affixID + < (unsigned)affixID))))))) { + prev = &node->wn_sibling; + node = *prev; + } + if (node == NULL + || node->wn_byte != word[i] + || (word[i] == NUL + && (flags < 0 + || spin->si_sugtree + || node->wn_flags != (flags & WN_MASK) + || node->wn_affixID != affixID))) { + // Allocate a new node. + np = get_wordnode(spin); + if (np == NULL) + return FAIL; + np->wn_byte = word[i]; + + // If "node" is NULL this is a new child or the end of the sibling + // list: ref count is one. Otherwise use ref count of sibling and + // make ref count of sibling one (matters when inserting in front + // of the list of siblings). + if (node == NULL) + np->wn_refs = 1; + else { + np->wn_refs = node->wn_refs; + node->wn_refs = 1; + } + if (prev != NULL) + *prev = np; + np->wn_sibling = node; + node = np; + } + + if (word[i] == NUL) { + node->wn_flags = flags; + node->wn_region |= region; + node->wn_affixID = affixID; + break; + } + prev = &node->wn_child; + node = *prev; + } +#ifdef SPELL_PRINTTREE + smsg((char_u *)"Added \"%s\"", word); + spell_print_tree(root->wn_sibling); +#endif + + // count nr of words added since last message + ++spin->si_msg_count; + + if (spin->si_compress_cnt > 1) { + if (--spin->si_compress_cnt == 1) + // Did enough words to lower the block count limit. + spin->si_blocks_cnt += compress_inc; + } + + // When we have allocated lots of memory we need to compress the word tree + // to free up some room. But compression is slow, and we might actually + // need that room, thus only compress in the following situations: + // 1. When not compressed before (si_compress_cnt == 0): when using + // "compress_start" blocks. + // 2. When compressed before and used "compress_inc" blocks before + // adding "compress_added" words (si_compress_cnt > 1). + // 3. When compressed before, added "compress_added" words + // (si_compress_cnt == 1) and the number of free nodes drops below the + // maximum word length. +#ifndef SPELL_COMPRESS_ALLWAYS + if (spin->si_compress_cnt == 1 // NOLINT(readability/braces) + ? spin->si_free_count < MAXWLEN + : spin->si_blocks_cnt >= compress_start) +#endif + { + // Decrement the block counter. The effect is that we compress again + // when the freed up room has been used and another "compress_inc" + // blocks have been allocated. Unless "compress_added" words have + // been added, then the limit is put back again. + spin->si_blocks_cnt -= compress_inc; + spin->si_compress_cnt = compress_added; + + if (spin->si_verbose) { + msg_start(); + msg_puts(_(msg_compressing)); + msg_clr_eos(); + msg_didout = FALSE; + msg_col = 0; + ui_flush(); + } + + // Compress both trees. Either they both have many nodes, which makes + // compression useful, or one of them is small, which means + // compression goes fast. But when filling the soundfold word tree + // there is no keep-case tree. + wordtree_compress(spin, spin->si_foldroot); + if (affixID >= 0) + wordtree_compress(spin, spin->si_keeproot); + } + + return OK; +} + +// Get a wordnode_T, either from the list of previously freed nodes or +// allocate a new one. +// Returns NULL when out of memory. +static wordnode_T *get_wordnode(spellinfo_T *spin) +{ + wordnode_T *n; + + if (spin->si_first_free == NULL) + n = (wordnode_T *)getroom(spin, sizeof(wordnode_T), true); + else { + n = spin->si_first_free; + spin->si_first_free = n->wn_child; + memset(n, 0, sizeof(wordnode_T)); + --spin->si_free_count; + } +#ifdef SPELL_PRINTTREE + if (n != NULL) + n->wn_nr = ++spin->si_wordnode_nr; +#endif + return n; +} + +// Decrement the reference count on a node (which is the head of a list of +// siblings). If the reference count becomes zero free the node and its +// siblings. +// Returns the number of nodes actually freed. +static int deref_wordnode(spellinfo_T *spin, wordnode_T *node) +{ + wordnode_T *np; + int cnt = 0; + + if (--node->wn_refs == 0) { + for (np = node; np != NULL; np = np->wn_sibling) { + if (np->wn_child != NULL) + cnt += deref_wordnode(spin, np->wn_child); + free_wordnode(spin, np); + ++cnt; + } + ++cnt; // length field + } + return cnt; +} + +// Free a wordnode_T for re-use later. +// Only the "wn_child" field becomes invalid. +static void free_wordnode(spellinfo_T *spin, wordnode_T *n) +{ + n->wn_child = spin->si_first_free; + spin->si_first_free = n; + ++spin->si_free_count; +} + +// Compress a tree: find tails that are identical and can be shared. +static void wordtree_compress(spellinfo_T *spin, wordnode_T *root) +{ + hashtab_T ht; + int n; + int tot = 0; + int perc; + + // Skip the root itself, it's not actually used. The first sibling is the + // start of the tree. + if (root->wn_sibling != NULL) { + hash_init(&ht); + n = node_compress(spin, root->wn_sibling, &ht, &tot); + +#ifndef SPELL_PRINTTREE + if (spin->si_verbose || p_verbose > 2) +#endif + { + if (tot > 1000000) + perc = (tot - n) / (tot / 100); + else if (tot == 0) + perc = 0; + else + perc = (tot - n) * 100 / tot; + vim_snprintf((char *)IObuff, IOSIZE, + _("Compressed %d of %d nodes; %d (%d%%) remaining"), + n, tot, tot - n, perc); + spell_message(spin, IObuff); + } +#ifdef SPELL_PRINTTREE + spell_print_tree(root->wn_sibling); +#endif + hash_clear(&ht); + } +} + +// Compress a node, its siblings and its children, depth first. +// Returns the number of compressed nodes. +static int +node_compress ( + spellinfo_T *spin, + wordnode_T *node, + hashtab_T *ht, + int *tot // total count of nodes before compressing, + // incremented while going through the tree +) +{ + wordnode_T *np; + wordnode_T *tp; + wordnode_T *child; + hash_T hash; + hashitem_T *hi; + int len = 0; + unsigned nr, n; + int compressed = 0; + + // Go through the list of siblings. Compress each child and then try + // finding an identical child to replace it. + // Note that with "child" we mean not just the node that is pointed to, + // but the whole list of siblings of which the child node is the first. + for (np = node; np != NULL && !got_int; np = np->wn_sibling) { + ++len; + if ((child = np->wn_child) != NULL) { + // Compress the child first. This fills hashkey. + compressed += node_compress(spin, child, ht, tot); + + // Try to find an identical child. + hash = hash_hash(child->wn_u1.hashkey); + hi = hash_lookup(ht, (const char *)child->wn_u1.hashkey, + STRLEN(child->wn_u1.hashkey), hash); + if (!HASHITEM_EMPTY(hi)) { + // There are children we encountered before with a hash value + // identical to the current child. Now check if there is one + // that is really identical. + for (tp = HI2WN(hi); tp != NULL; tp = tp->wn_u2.next) + if (node_equal(child, tp)) { + // Found one! Now use that child in place of the + // current one. This means the current child and all + // its siblings is unlinked from the tree. + ++tp->wn_refs; + compressed += deref_wordnode(spin, child); + np->wn_child = tp; + break; + } + if (tp == NULL) { + // No other child with this hash value equals the child of + // the node, add it to the linked list after the first + // item. + tp = HI2WN(hi); + child->wn_u2.next = tp->wn_u2.next; + tp->wn_u2.next = child; + } + } else + // No other child has this hash value, add it to the + // hashtable. + hash_add_item(ht, hi, child->wn_u1.hashkey, hash); + } + } + *tot += len + 1; // add one for the node that stores the length + + // Make a hash key for the node and its siblings, so that we can quickly + // find a lookalike node. This must be done after compressing the sibling + // list, otherwise the hash key would become invalid by the compression. + node->wn_u1.hashkey[0] = len; + nr = 0; + for (np = node; np != NULL; np = np->wn_sibling) { + if (np->wn_byte == NUL) + // end node: use wn_flags, wn_region and wn_affixID + n = np->wn_flags + (np->wn_region << 8) + (np->wn_affixID << 16); + else + // byte node: use the byte value and the child pointer + n = (unsigned)(np->wn_byte + ((uintptr_t)np->wn_child << 8)); + nr = nr * 101 + n; + } + + // Avoid NUL bytes, it terminates the hash key. + n = nr & 0xff; + node->wn_u1.hashkey[1] = n == 0 ? 1 : n; + n = (nr >> 8) & 0xff; + node->wn_u1.hashkey[2] = n == 0 ? 1 : n; + n = (nr >> 16) & 0xff; + node->wn_u1.hashkey[3] = n == 0 ? 1 : n; + n = (nr >> 24) & 0xff; + node->wn_u1.hashkey[4] = n == 0 ? 1 : n; + node->wn_u1.hashkey[5] = NUL; + + // Check for CTRL-C pressed now and then. + fast_breakcheck(); + + return compressed; +} + +// Returns true when two nodes have identical siblings and children. +static bool node_equal(wordnode_T *n1, wordnode_T *n2) +{ + wordnode_T *p1; + wordnode_T *p2; + + for (p1 = n1, p2 = n2; p1 != NULL && p2 != NULL; + p1 = p1->wn_sibling, p2 = p2->wn_sibling) + if (p1->wn_byte != p2->wn_byte + || (p1->wn_byte == NUL + ? (p1->wn_flags != p2->wn_flags + || p1->wn_region != p2->wn_region + || p1->wn_affixID != p2->wn_affixID) + : (p1->wn_child != p2->wn_child))) + break; + + return p1 == NULL && p2 == NULL; +} + + +// Function given to qsort() to sort the REP items on "from" string. +static int rep_compare(const void *s1, const void *s2) +{ + fromto_T *p1 = (fromto_T *)s1; + fromto_T *p2 = (fromto_T *)s2; + + return STRCMP(p1->ft_from, p2->ft_from); +} + +// Write the Vim .spl file "fname". +// Return OK/FAIL. +static int write_vim_spell(spellinfo_T *spin, char_u *fname) +{ + int retval = OK; + int regionmask; + + FILE *fd = mch_fopen((char *)fname, "w"); + if (fd == NULL) { + EMSG2(_(e_notopen), fname); + return FAIL; + } + + // <HEADER>: <fileID> <versionnr> + // <fileID> + size_t fwv = fwrite(VIMSPELLMAGIC, VIMSPELLMAGICL, 1, fd); + if (fwv != (size_t)1) + // Catch first write error, don't try writing more. + goto theend; + + putc(VIMSPELLVERSION, fd); // <versionnr> + + // <SECTIONS>: <section> ... <sectionend> + + // SN_INFO: <infotext> + if (spin->si_info != NULL) { + putc(SN_INFO, fd); // <sectionID> + putc(0, fd); // <sectionflags> + size_t i = STRLEN(spin->si_info); + put_bytes(fd, i, 4); // <sectionlen> + fwv &= fwrite(spin->si_info, i, 1, fd); // <infotext> + } + + // SN_REGION: <regionname> ... + // Write the region names only if there is more than one. + if (spin->si_region_count > 1) { + putc(SN_REGION, fd); // <sectionID> + putc(SNF_REQUIRED, fd); // <sectionflags> + size_t l = (size_t)spin->si_region_count * 2; + put_bytes(fd, l, 4); // <sectionlen> + fwv &= fwrite(spin->si_region_name, l, 1, fd); + // <regionname> ... + regionmask = (1 << spin->si_region_count) - 1; + } else + regionmask = 0; + + // SN_CHARFLAGS: <charflagslen> <charflags> <folcharslen> <folchars> + // + // The table with character flags and the table for case folding. + // This makes sure the same characters are recognized as word characters + // when generating an when using a spell file. + // Skip this for ASCII, the table may conflict with the one used for + // 'encoding'. + // Also skip this for an .add.spl file, the main spell file must contain + // the table (avoids that it conflicts). File is shorter too. + if (!spin->si_ascii && !spin->si_add) { + char_u folchars[128 * 8]; + int flags; + + putc(SN_CHARFLAGS, fd); // <sectionID> + putc(SNF_REQUIRED, fd); // <sectionflags> + + // Form the <folchars> string first, we need to know its length. + size_t l = 0; + for (size_t i = 128; i < 256; ++i) { + if (has_mbyte) + l += (size_t)mb_char2bytes(spelltab.st_fold[i], folchars + l); + else + folchars[l++] = spelltab.st_fold[i]; + } + put_bytes(fd, 1 + 128 + 2 + l, 4); // <sectionlen> + + fputc(128, fd); // <charflagslen> + for (size_t i = 128; i < 256; ++i) { + flags = 0; + if (spelltab.st_isw[i]) + flags |= CF_WORD; + if (spelltab.st_isu[i]) + flags |= CF_UPPER; + fputc(flags, fd); // <charflags> + } + + put_bytes(fd, l, 2); // <folcharslen> + fwv &= fwrite(folchars, l, 1, fd); // <folchars> + } + + // SN_MIDWORD: <midword> + if (spin->si_midword != NULL) { + putc(SN_MIDWORD, fd); // <sectionID> + putc(SNF_REQUIRED, fd); // <sectionflags> + + size_t i = STRLEN(spin->si_midword); + put_bytes(fd, i, 4); // <sectionlen> + fwv &= fwrite(spin->si_midword, i, 1, fd); + // <midword> + } + + // SN_PREFCOND: <prefcondcnt> <prefcond> ... + if (!GA_EMPTY(&spin->si_prefcond)) { + putc(SN_PREFCOND, fd); // <sectionID> + putc(SNF_REQUIRED, fd); // <sectionflags> + + size_t l = (size_t)write_spell_prefcond(NULL, &spin->si_prefcond); + put_bytes(fd, l, 4); // <sectionlen> + + write_spell_prefcond(fd, &spin->si_prefcond); + } + + // SN_REP: <repcount> <rep> ... + // SN_SAL: <salflags> <salcount> <sal> ... + // SN_REPSAL: <repcount> <rep> ... + + // round 1: SN_REP section + // round 2: SN_SAL section (unless SN_SOFO is used) + // round 3: SN_REPSAL section + for (unsigned int round = 1; round <= 3; ++round) { + garray_T *gap; + if (round == 1) + gap = &spin->si_rep; + else if (round == 2) { + // Don't write SN_SAL when using a SN_SOFO section + if (spin->si_sofofr != NULL && spin->si_sofoto != NULL) + continue; + gap = &spin->si_sal; + } else + gap = &spin->si_repsal; + + // Don't write the section if there are no items. + if (GA_EMPTY(gap)) + continue; + + // Sort the REP/REPSAL items. + if (round != 2) + qsort(gap->ga_data, (size_t)gap->ga_len, + sizeof(fromto_T), rep_compare); + + int i = round == 1 ? SN_REP : (round == 2 ? SN_SAL : SN_REPSAL); + putc(i, fd); // <sectionID> + + // This is for making suggestions, section is not required. + putc(0, fd); // <sectionflags> + + // Compute the length of what follows. + size_t l = 2; // count <repcount> or <salcount> + assert(gap->ga_len >= 0); + for (size_t i = 0; i < (size_t)gap->ga_len; ++i) { + fromto_T *ftp = &((fromto_T *)gap->ga_data)[i]; + l += 1 + STRLEN(ftp->ft_from); // count <*fromlen> and <*from> + l += 1 + STRLEN(ftp->ft_to); // count <*tolen> and <*to> + } + if (round == 2) + ++l; // count <salflags> + put_bytes(fd, l, 4); // <sectionlen> + + if (round == 2) { + int i = 0; + if (spin->si_followup) + i |= SAL_F0LLOWUP; + if (spin->si_collapse) + i |= SAL_COLLAPSE; + if (spin->si_rem_accents) + i |= SAL_REM_ACCENTS; + putc(i, fd); // <salflags> + } + + put_bytes(fd, (uintmax_t)gap->ga_len, 2); // <repcount> or <salcount> + for (size_t i = 0; i < (size_t)gap->ga_len; ++i) { + // <rep> : <repfromlen> <repfrom> <reptolen> <repto> + // <sal> : <salfromlen> <salfrom> <saltolen> <salto> + fromto_T *ftp = &((fromto_T *)gap->ga_data)[i]; + for (unsigned int rr = 1; rr <= 2; ++rr) { + char_u *p = rr == 1 ? ftp->ft_from : ftp->ft_to; + l = STRLEN(p); + assert(l < INT_MAX); + putc((int)l, fd); + if (l > 0) + fwv &= fwrite(p, l, 1, fd); + } + } + + } + + // SN_SOFO: <sofofromlen> <sofofrom> <sofotolen> <sofoto> + // This is for making suggestions, section is not required. + if (spin->si_sofofr != NULL && spin->si_sofoto != NULL) { + putc(SN_SOFO, fd); // <sectionID> + putc(0, fd); // <sectionflags> + + size_t l = STRLEN(spin->si_sofofr); + put_bytes(fd, l + STRLEN(spin->si_sofoto) + 4, 4); // <sectionlen> + + put_bytes(fd, l, 2); // <sofofromlen> + fwv &= fwrite(spin->si_sofofr, l, 1, fd); // <sofofrom> + + l = STRLEN(spin->si_sofoto); + put_bytes(fd, l, 2); // <sofotolen> + fwv &= fwrite(spin->si_sofoto, l, 1, fd); // <sofoto> + } + + // SN_WORDS: <word> ... + // This is for making suggestions, section is not required. + if (spin->si_commonwords.ht_used > 0) { + putc(SN_WORDS, fd); // <sectionID> + putc(0, fd); // <sectionflags> + + // round 1: count the bytes + // round 2: write the bytes + for (unsigned int round = 1; round <= 2; ++round) { + size_t todo; + size_t len = 0; + hashitem_T *hi; + + todo = spin->si_commonwords.ht_used; + for (hi = spin->si_commonwords.ht_array; todo > 0; ++hi) + if (!HASHITEM_EMPTY(hi)) { + size_t l = STRLEN(hi->hi_key) + 1; + len += l; + if (round == 2) // <word> + fwv &= fwrite(hi->hi_key, l, 1, fd); + --todo; + } + if (round == 1) + put_bytes(fd, len, 4); // <sectionlen> + } + } + + // SN_MAP: <mapstr> + // This is for making suggestions, section is not required. + if (!GA_EMPTY(&spin->si_map)) { + putc(SN_MAP, fd); // <sectionID> + putc(0, fd); // <sectionflags> + size_t l = (size_t)spin->si_map.ga_len; + put_bytes(fd, l, 4); // <sectionlen> + fwv &= fwrite(spin->si_map.ga_data, l, 1, fd); // <mapstr> + } + + // SN_SUGFILE: <timestamp> + // This is used to notify that a .sug file may be available and at the + // same time allows for checking that a .sug file that is found matches + // with this .spl file. That's because the word numbers must be exactly + // right. + if (!spin->si_nosugfile + && (!GA_EMPTY(&spin->si_sal) + || (spin->si_sofofr != NULL && spin->si_sofoto != NULL))) { + putc(SN_SUGFILE, fd); // <sectionID> + putc(0, fd); // <sectionflags> + put_bytes(fd, 8, 4); // <sectionlen> + + // Set si_sugtime and write it to the file. + spin->si_sugtime = time(NULL); + put_time(fd, spin->si_sugtime); // <timestamp> + } + + // SN_NOSPLITSUGS: nothing + // This is used to notify that no suggestions with word splits are to be + // made. + if (spin->si_nosplitsugs) { + putc(SN_NOSPLITSUGS, fd); // <sectionID> + putc(0, fd); // <sectionflags> + put_bytes(fd, 0, 4); // <sectionlen> + } + + // SN_NOCOMPUNDSUGS: nothing + // This is used to notify that no suggestions with compounds are to be + // made. + if (spin->si_nocompoundsugs) { + putc(SN_NOCOMPOUNDSUGS, fd); // <sectionID> + putc(0, fd); // <sectionflags> + put_bytes(fd, 0, 4); // <sectionlen> + } + + // SN_COMPOUND: compound info. + // We don't mark it required, when not supported all compound words will + // be bad words. + if (spin->si_compflags != NULL) { + putc(SN_COMPOUND, fd); // <sectionID> + putc(0, fd); // <sectionflags> + + size_t l = STRLEN(spin->si_compflags); + assert(spin->si_comppat.ga_len >= 0); + for (size_t i = 0; i < (size_t)spin->si_comppat.ga_len; ++i) { + l += STRLEN(((char_u **)(spin->si_comppat.ga_data))[i]) + 1; + } + put_bytes(fd, l + 7, 4); // <sectionlen> + + putc(spin->si_compmax, fd); // <compmax> + putc(spin->si_compminlen, fd); // <compminlen> + putc(spin->si_compsylmax, fd); // <compsylmax> + putc(0, fd); // for Vim 7.0b compatibility + putc(spin->si_compoptions, fd); // <compoptions> + put_bytes(fd, (uintmax_t)spin->si_comppat.ga_len, 2); // <comppatcount> + for (size_t i = 0; i < (size_t)spin->si_comppat.ga_len; ++i) { + char_u *p = ((char_u **)(spin->si_comppat.ga_data))[i]; + assert(STRLEN(p) < INT_MAX); + putc((int)STRLEN(p), fd); // <comppatlen> + fwv &= fwrite(p, STRLEN(p), 1, fd); // <comppattext> + } + // <compflags> + fwv &= fwrite(spin->si_compflags, STRLEN(spin->si_compflags), 1, fd); + } + + // SN_NOBREAK: NOBREAK flag + if (spin->si_nobreak) { + putc(SN_NOBREAK, fd); // <sectionID> + putc(0, fd); // <sectionflags> + + // It's empty, the presence of the section flags the feature. + put_bytes(fd, 0, 4); // <sectionlen> + } + + // SN_SYLLABLE: syllable info. + // We don't mark it required, when not supported syllables will not be + // counted. + if (spin->si_syllable != NULL) { + putc(SN_SYLLABLE, fd); // <sectionID> + putc(0, fd); // <sectionflags> + + size_t l = STRLEN(spin->si_syllable); + put_bytes(fd, l, 4); // <sectionlen> + fwv &= fwrite(spin->si_syllable, l, 1, fd); // <syllable> + } + + // end of <SECTIONS> + putc(SN_END, fd); // <sectionend> + + + // <LWORDTREE> <KWORDTREE> <PREFIXTREE> + spin->si_memtot = 0; + for (unsigned int round = 1; round <= 3; ++round) { + wordnode_T *tree; + if (round == 1) + tree = spin->si_foldroot->wn_sibling; + else if (round == 2) + tree = spin->si_keeproot->wn_sibling; + else + tree = spin->si_prefroot->wn_sibling; + + // Clear the index and wnode fields in the tree. + clear_node(tree); + + // Count the number of nodes. Needed to be able to allocate the + // memory when reading the nodes. Also fills in index for shared + // nodes. + size_t nodecount = (size_t)put_node(NULL, tree, 0, regionmask, round == 3); + + // number of nodes in 4 bytes + put_bytes(fd, nodecount, 4); // <nodecount> + assert(nodecount + nodecount * sizeof(int) < INT_MAX); + spin->si_memtot += (int)(nodecount + nodecount * sizeof(int)); + + // Write the nodes. + (void)put_node(fd, tree, 0, regionmask, round == 3); + } + + // Write another byte to check for errors (file system full). + if (putc(0, fd) == EOF) + retval = FAIL; +theend: + if (fclose(fd) == EOF) + retval = FAIL; + + if (fwv != (size_t)1) + retval = FAIL; + if (retval == FAIL) + EMSG(_(e_write)); + + return retval; +} + +// Clear the index and wnode fields of "node", it siblings and its +// children. This is needed because they are a union with other items to save +// space. +static void clear_node(wordnode_T *node) +{ + wordnode_T *np; + + if (node != NULL) + for (np = node; np != NULL; np = np->wn_sibling) { + np->wn_u1.index = 0; + np->wn_u2.wnode = NULL; + + if (np->wn_byte != NUL) + clear_node(np->wn_child); + } +} + + +// Dump a word tree at node "node". +// +// This first writes the list of possible bytes (siblings). Then for each +// byte recursively write the children. +// +// NOTE: The code here must match the code in read_tree_node(), since +// assumptions are made about the indexes (so that we don't have to write them +// in the file). +// +// Returns the number of nodes used. +static int +put_node ( + FILE *fd, // NULL when only counting + wordnode_T *node, + int idx, + int regionmask, + bool prefixtree // true for PREFIXTREE +) +{ + // If "node" is zero the tree is empty. + if (node == NULL) + return 0; + + // Store the index where this node is written. + node->wn_u1.index = idx; + + // Count the number of siblings. + int siblingcount = 0; + for (wordnode_T *np = node; np != NULL; np = np->wn_sibling) + ++siblingcount; + + // Write the sibling count. + if (fd != NULL) + putc(siblingcount, fd); // <siblingcount> + + // Write each sibling byte and optionally extra info. + for (wordnode_T *np = node; np != NULL; np = np->wn_sibling) { + if (np->wn_byte == 0) { + if (fd != NULL) { + // For a NUL byte (end of word) write the flags etc. + if (prefixtree) { + // In PREFIXTREE write the required affixID and the + // associated condition nr (stored in wn_region). The + // byte value is misused to store the "rare" and "not + // combining" flags + if (np->wn_flags == (uint16_t)PFX_FLAGS) + putc(BY_NOFLAGS, fd); // <byte> + else { + putc(BY_FLAGS, fd); // <byte> + putc(np->wn_flags, fd); // <pflags> + } + putc(np->wn_affixID, fd); // <affixID> + put_bytes(fd, (uintmax_t)np->wn_region, 2); // <prefcondnr> + } else { + // For word trees we write the flag/region items. + int flags = np->wn_flags; + if (regionmask != 0 && np->wn_region != regionmask) + flags |= WF_REGION; + if (np->wn_affixID != 0) + flags |= WF_AFX; + if (flags == 0) { + // word without flags or region + putc(BY_NOFLAGS, fd); // <byte> + } else { + if (np->wn_flags >= 0x100) { + putc(BY_FLAGS2, fd); // <byte> + putc(flags, fd); // <flags> + putc((int)((unsigned)flags >> 8), fd); // <flags2> + } else { + putc(BY_FLAGS, fd); // <byte> + putc(flags, fd); // <flags> + } + if (flags & WF_REGION) + putc(np->wn_region, fd); // <region> + if (flags & WF_AFX) + putc(np->wn_affixID, fd); // <affixID> + } + } + } + } else { + if (np->wn_child->wn_u1.index != 0 + && np->wn_child->wn_u2.wnode != node) { + // The child is written elsewhere, write the reference. + if (fd != NULL) { + putc(BY_INDEX, fd); // <byte> + put_bytes(fd, (uintmax_t)np->wn_child->wn_u1.index, 3); // <nodeidx> + } + } else if (np->wn_child->wn_u2.wnode == NULL) + // We will write the child below and give it an index. + np->wn_child->wn_u2.wnode = node; + + if (fd != NULL) + if (putc(np->wn_byte, fd) == EOF) { // <byte> or <xbyte> + EMSG(_(e_write)); + return 0; + } + } + } + + // Space used in the array when reading: one for each sibling and one for + // the count. + int newindex = idx + siblingcount + 1; + + // Recursively dump the children of each sibling. + for (wordnode_T *np = node; np != NULL; np = np->wn_sibling) + if (np->wn_byte != 0 && np->wn_child->wn_u2.wnode == node) + newindex = put_node(fd, np->wn_child, newindex, regionmask, + prefixtree); + + return newindex; +} + + +// ":mkspell [-ascii] outfile infile ..." +// ":mkspell [-ascii] addfile" +void ex_mkspell(exarg_T *eap) +{ + int fcount; + char_u **fnames; + char_u *arg = eap->arg; + bool ascii = false; + + if (STRNCMP(arg, "-ascii", 6) == 0) { + ascii = true; + arg = skipwhite(arg + 6); + } + + // Expand all the remaining arguments (e.g., $VIMRUNTIME). + if (get_arglist_exp(arg, &fcount, &fnames, false) == OK) { + mkspell(fcount, fnames, ascii, eap->forceit, false); + FreeWild(fcount, fnames); + } +} + +// Create the .sug file. +// Uses the soundfold info in "spin". +// Writes the file with the name "wfname", with ".spl" changed to ".sug". +static void spell_make_sugfile(spellinfo_T *spin, char_u *wfname) +{ + char_u *fname = NULL; + int len; + slang_T *slang; + bool free_slang = false; + + // Read back the .spl file that was written. This fills the required + // info for soundfolding. This also uses less memory than the + // pointer-linked version of the trie. And it avoids having two versions + // of the code for the soundfolding stuff. + // It might have been done already by spell_reload_one(). + for (slang = first_lang; slang != NULL; slang = slang->sl_next) + if (path_full_compare(wfname, slang->sl_fname, FALSE) == kEqualFiles) + break; + if (slang == NULL) { + spell_message(spin, (char_u *)_("Reading back spell file...")); + slang = spell_load_file(wfname, NULL, NULL, false); + if (slang == NULL) + return; + free_slang = true; + } + + // Clear the info in "spin" that is used. + spin->si_blocks = NULL; + spin->si_blocks_cnt = 0; + spin->si_compress_cnt = 0; // will stay at 0 all the time + spin->si_free_count = 0; + spin->si_first_free = NULL; + spin->si_foldwcount = 0; + + // Go through the trie of good words, soundfold each word and add it to + // the soundfold trie. + spell_message(spin, (char_u *)_("Performing soundfolding...")); + if (sug_filltree(spin, slang) == FAIL) + goto theend; + + // Create the table which links each soundfold word with a list of the + // good words it may come from. Creates buffer "spin->si_spellbuf". + // This also removes the wordnr from the NUL byte entries to make + // compression possible. + if (sug_maketable(spin) == FAIL) + goto theend; + + smsg(_("Number of words after soundfolding: %" PRId64), + (int64_t)spin->si_spellbuf->b_ml.ml_line_count); + + // Compress the soundfold trie. + spell_message(spin, (char_u *)_(msg_compressing)); + wordtree_compress(spin, spin->si_foldroot); + + // Write the .sug file. + // Make the file name by changing ".spl" to ".sug". + fname = xmalloc(MAXPATHL); + STRLCPY(fname, wfname, MAXPATHL); + len = (int)STRLEN(fname); + fname[len - 2] = 'u'; + fname[len - 1] = 'g'; + sug_write(spin, fname); + +theend: + xfree(fname); + if (free_slang) + slang_free(slang); + free_blocks(spin->si_blocks); + close_spellbuf(spin->si_spellbuf); +} + +// Build the soundfold trie for language "slang". +static int sug_filltree(spellinfo_T *spin, slang_T *slang) +{ + char_u *byts; + idx_T *idxs; + int depth; + idx_T arridx[MAXWLEN]; + int curi[MAXWLEN]; + char_u tword[MAXWLEN]; + char_u tsalword[MAXWLEN]; + int c; + idx_T n; + unsigned words_done = 0; + int wordcount[MAXWLEN]; + + // We use si_foldroot for the soundfolded trie. + spin->si_foldroot = wordtree_alloc(spin); + if (spin->si_foldroot == NULL) + return FAIL; + + // Let tree_add_word() know we're adding to the soundfolded tree + spin->si_sugtree = true; + + // Go through the whole case-folded tree, soundfold each word and put it + // in the trie. + byts = slang->sl_fbyts; + idxs = slang->sl_fidxs; + + arridx[0] = 0; + curi[0] = 1; + wordcount[0] = 0; + + depth = 0; + while (depth >= 0 && !got_int) { + if (curi[depth] > byts[arridx[depth]]) { + // Done all bytes at this node, go up one level. + idxs[arridx[depth]] = wordcount[depth]; + if (depth > 0) + wordcount[depth - 1] += wordcount[depth]; + + --depth; + line_breakcheck(); + } else { + + // Do one more byte at this node. + n = arridx[depth] + curi[depth]; + ++curi[depth]; + + c = byts[n]; + if (c == 0) { + // Sound-fold the word. + tword[depth] = NUL; + spell_soundfold(slang, tword, true, tsalword); + + // We use the "flags" field for the MSB of the wordnr, + // "region" for the LSB of the wordnr. + if (tree_add_word(spin, tsalword, spin->si_foldroot, + words_done >> 16, words_done & 0xffff, + 0) == FAIL) + return FAIL; + + ++words_done; + ++wordcount[depth]; + + // Reset the block count each time to avoid compression + // kicking in. + spin->si_blocks_cnt = 0; + + // Skip over any other NUL bytes (same word with different + // flags). + while (byts[n + 1] == 0) { + ++n; + ++curi[depth]; + } + } else { + // Normal char, go one level deeper. + tword[depth++] = c; + arridx[depth] = idxs[n]; + curi[depth] = 1; + wordcount[depth] = 0; + } + } + } + + smsg(_("Total number of words: %d"), words_done); + + return OK; +} + +// Make the table that links each word in the soundfold trie to the words it +// can be produced from. +// This is not unlike lines in a file, thus use a memfile to be able to access +// the table efficiently. +// Returns FAIL when out of memory. +static int sug_maketable(spellinfo_T *spin) +{ + garray_T ga; + int res = OK; + + // Allocate a buffer, open a memline for it and create the swap file + // (uses a temp file, not a .swp file). + spin->si_spellbuf = open_spellbuf(); + + // Use a buffer to store the line info, avoids allocating many small + // pieces of memory. + ga_init(&ga, 1, 100); + + // recursively go through the tree + if (sug_filltable(spin, spin->si_foldroot->wn_sibling, 0, &ga) == -1) + res = FAIL; + + ga_clear(&ga); + return res; +} + +// Fill the table for one node and its children. +// Returns the wordnr at the start of the node. +// Returns -1 when out of memory. +static int +sug_filltable ( + spellinfo_T *spin, + wordnode_T *node, + int startwordnr, + garray_T *gap // place to store line of numbers +) +{ + wordnode_T *p, *np; + int wordnr = startwordnr; + int nr; + int prev_nr; + + for (p = node; p != NULL; p = p->wn_sibling) { + if (p->wn_byte == NUL) { + gap->ga_len = 0; + prev_nr = 0; + for (np = p; np != NULL && np->wn_byte == NUL; np = np->wn_sibling) { + ga_grow(gap, 10); + + nr = (np->wn_flags << 16) + (np->wn_region & 0xffff); + // Compute the offset from the previous nr and store the + // offset in a way that it takes a minimum number of bytes. + // It's a bit like utf-8, but without the need to mark + // following bytes. + nr -= prev_nr; + prev_nr += nr; + gap->ga_len += offset2bytes(nr, + (char_u *)gap->ga_data + gap->ga_len); + } + + // add the NUL byte + ((char_u *)gap->ga_data)[gap->ga_len++] = NUL; + + if (ml_append_buf(spin->si_spellbuf, (linenr_T)wordnr, + gap->ga_data, gap->ga_len, TRUE) == FAIL) + return -1; + ++wordnr; + + // Remove extra NUL entries, we no longer need them. We don't + // bother freeing the nodes, the won't be reused anyway. + while (p->wn_sibling != NULL && p->wn_sibling->wn_byte == NUL) + p->wn_sibling = p->wn_sibling->wn_sibling; + + // Clear the flags on the remaining NUL node, so that compression + // works a lot better. + p->wn_flags = 0; + p->wn_region = 0; + } else { + wordnr = sug_filltable(spin, p->wn_child, wordnr, gap); + if (wordnr == -1) + return -1; + } + } + return wordnr; +} + +// Convert an offset into a minimal number of bytes. +// Similar to utf_char2byters, but use 8 bits in followup bytes and avoid NUL +// bytes. +static int offset2bytes(int nr, char_u *buf) +{ + int rem; + int b1, b2, b3, b4; + + // Split the number in parts of base 255. We need to avoid NUL bytes. + b1 = nr % 255 + 1; + rem = nr / 255; + b2 = rem % 255 + 1; + rem = rem / 255; + b3 = rem % 255 + 1; + b4 = rem / 255 + 1; + + if (b4 > 1 || b3 > 0x1f) { // 4 bytes + buf[0] = 0xe0 + b4; + buf[1] = b3; + buf[2] = b2; + buf[3] = b1; + return 4; + } + if (b3 > 1 || b2 > 0x3f ) { // 3 bytes + buf[0] = 0xc0 + b3; + buf[1] = b2; + buf[2] = b1; + return 3; + } + if (b2 > 1 || b1 > 0x7f ) { // 2 bytes + buf[0] = 0x80 + b2; + buf[1] = b1; + return 2; + } + // 1 byte + buf[0] = b1; + return 1; +} + +// Write the .sug file in "fname". +static void sug_write(spellinfo_T *spin, char_u *fname) +{ + // Create the file. Note that an existing file is silently overwritten! + FILE *fd = mch_fopen((char *)fname, "w"); + if (fd == NULL) { + EMSG2(_(e_notopen), fname); + return; + } + + vim_snprintf((char *)IObuff, IOSIZE, + _("Writing suggestion file %s ..."), fname); + spell_message(spin, IObuff); + + // <SUGHEADER>: <fileID> <versionnr> <timestamp> + if (fwrite(VIMSUGMAGIC, VIMSUGMAGICL, (size_t)1, fd) != 1) { // <fileID> + EMSG(_(e_write)); + goto theend; + } + putc(VIMSUGVERSION, fd); // <versionnr> + + // Write si_sugtime to the file. + put_time(fd, spin->si_sugtime); // <timestamp> + + // <SUGWORDTREE> + spin->si_memtot = 0; + wordnode_T *tree = spin->si_foldroot->wn_sibling; + + // Clear the index and wnode fields in the tree. + clear_node(tree); + + // Count the number of nodes. Needed to be able to allocate the + // memory when reading the nodes. Also fills in index for shared + // nodes. + size_t nodecount = (size_t)put_node(NULL, tree, 0, 0, false); + + // number of nodes in 4 bytes + put_bytes(fd, nodecount, 4); // <nodecount> + assert(nodecount + nodecount * sizeof(int) < INT_MAX); + spin->si_memtot += (int)(nodecount + nodecount * sizeof(int)); + + // Write the nodes. + (void)put_node(fd, tree, 0, 0, false); + + // <SUGTABLE>: <sugwcount> <sugline> ... + linenr_T wcount = spin->si_spellbuf->b_ml.ml_line_count; + assert(wcount >= 0); + put_bytes(fd, (uintmax_t)wcount, 4); // <sugwcount> + + for (linenr_T lnum = 1; lnum <= wcount; ++lnum) { + // <sugline>: <sugnr> ... NUL + char_u *line = ml_get_buf(spin->si_spellbuf, lnum, FALSE); + size_t len = STRLEN(line) + 1; + if (fwrite(line, len, 1, fd) == 0) { + EMSG(_(e_write)); + goto theend; + } + assert((size_t)spin->si_memtot + len <= INT_MAX); + spin->si_memtot += (int)len; + } + + // Write another byte to check for errors. + if (putc(0, fd) == EOF) + EMSG(_(e_write)); + + vim_snprintf((char *)IObuff, IOSIZE, + _("Estimated runtime memory use: %d bytes"), spin->si_memtot); + spell_message(spin, IObuff); + +theend: + // close the file + fclose(fd); +} + + +// Create a Vim spell file from one or more word lists. +// "fnames[0]" is the output file name. +// "fnames[fcount - 1]" is the last input file name. +// Exception: when "fnames[0]" ends in ".add" it's used as the input file name +// and ".spl" is appended to make the output file name. +static void +mkspell ( + int fcount, + char_u **fnames, + bool ascii, // -ascii argument given + bool over_write, // overwrite existing output file + bool added_word // invoked through "zg" +) +{ + char_u *fname = NULL; + char_u *wfname; + char_u **innames; + int incount; + afffile_T *(afile[8]); + int i; + int len; + bool error = false; + spellinfo_T spin; + + memset(&spin, 0, sizeof(spin)); + spin.si_verbose = !added_word; + spin.si_ascii = ascii; + spin.si_followup = true; + spin.si_rem_accents = true; + ga_init(&spin.si_rep, (int)sizeof(fromto_T), 20); + ga_init(&spin.si_repsal, (int)sizeof(fromto_T), 20); + ga_init(&spin.si_sal, (int)sizeof(fromto_T), 20); + ga_init(&spin.si_map, (int)sizeof(char_u), 100); + ga_init(&spin.si_comppat, (int)sizeof(char_u *), 20); + ga_init(&spin.si_prefcond, (int)sizeof(char_u *), 50); + hash_init(&spin.si_commonwords); + spin.si_newcompID = 127; // start compound ID at first maximum + + // default: fnames[0] is output file, following are input files + innames = &fnames[1]; + incount = fcount - 1; + + wfname = xmalloc(MAXPATHL); + + if (fcount >= 1) { + len = (int)STRLEN(fnames[0]); + if (fcount == 1 && len > 4 && STRCMP(fnames[0] + len - 4, ".add") == 0) { + // For ":mkspell path/en.latin1.add" output file is + // "path/en.latin1.add.spl". + innames = &fnames[0]; + incount = 1; + vim_snprintf((char *)wfname, MAXPATHL, "%s.spl", fnames[0]); + } else if (fcount == 1) { + // For ":mkspell path/vim" output file is "path/vim.latin1.spl". + innames = &fnames[0]; + incount = 1; + vim_snprintf((char *)wfname, MAXPATHL, SPL_FNAME_TMPL, + fnames[0], spin.si_ascii ? (char_u *)"ascii" : spell_enc()); + } else if (len > 4 && STRCMP(fnames[0] + len - 4, ".spl") == 0) { + // Name ends in ".spl", use as the file name. + STRLCPY(wfname, fnames[0], MAXPATHL); + } else + // Name should be language, make the file name from it. + vim_snprintf((char *)wfname, MAXPATHL, SPL_FNAME_TMPL, + fnames[0], spin.si_ascii ? (char_u *)"ascii" : spell_enc()); + + // Check for .ascii.spl. + if (strstr((char *)path_tail(wfname), SPL_FNAME_ASCII) != NULL) + spin.si_ascii = true; + + // Check for .add.spl. + if (strstr((char *)path_tail(wfname), SPL_FNAME_ADD) != NULL) + spin.si_add = true; + } + + if (incount <= 0) + EMSG(_(e_invarg)); // need at least output and input names + else if (vim_strchr(path_tail(wfname), '_') != NULL) + EMSG(_("E751: Output file name must not have region name")); + else if (incount > 8) + EMSG(_("E754: Only up to 8 regions supported")); + else { + // Check for overwriting before doing things that may take a lot of + // time. + if (!over_write && os_path_exists(wfname)) { + EMSG(_(e_exists)); + goto theend; + } + if (os_isdir(wfname)) { + EMSG2(_(e_isadir2), wfname); + goto theend; + } + + fname = xmalloc(MAXPATHL); + + // Init the aff and dic pointers. + // Get the region names if there are more than 2 arguments. + for (i = 0; i < incount; ++i) { + afile[i] = NULL; + + if (incount > 1) { + len = (int)STRLEN(innames[i]); + if (STRLEN(path_tail(innames[i])) < 5 + || innames[i][len - 3] != '_') { + EMSG2(_("E755: Invalid region in %s"), innames[i]); + goto theend; + } + spin.si_region_name[i * 2] = TOLOWER_ASC(innames[i][len - 2]); + spin.si_region_name[i * 2 + 1] = + TOLOWER_ASC(innames[i][len - 1]); + } + } + spin.si_region_count = incount; + + spin.si_foldroot = wordtree_alloc(&spin); + spin.si_keeproot = wordtree_alloc(&spin); + spin.si_prefroot = wordtree_alloc(&spin); + if (spin.si_foldroot == NULL + || spin.si_keeproot == NULL + || spin.si_prefroot == NULL) { + free_blocks(spin.si_blocks); + goto theend; + } + + // When not producing a .add.spl file clear the character table when + // we encounter one in the .aff file. This means we dump the current + // one in the .spl file if the .aff file doesn't define one. That's + // better than guessing the contents, the table will match a + // previously loaded spell file. + if (!spin.si_add) + spin.si_clear_chartab = true; + + // Read all the .aff and .dic files. + // Text is converted to 'encoding'. + // Words are stored in the case-folded and keep-case trees. + for (i = 0; i < incount && !error; ++i) { + spin.si_conv.vc_type = CONV_NONE; + spin.si_region = 1 << i; + + vim_snprintf((char *)fname, MAXPATHL, "%s.aff", innames[i]); + if (os_path_exists(fname)) { + // Read the .aff file. Will init "spin->si_conv" based on the + // "SET" line. + afile[i] = spell_read_aff(&spin, fname); + if (afile[i] == NULL) + error = true; + else { + // Read the .dic file and store the words in the trees. + vim_snprintf((char *)fname, MAXPATHL, "%s.dic", + innames[i]); + if (spell_read_dic(&spin, fname, afile[i]) == FAIL) + error = true; + } + } else { + // No .aff file, try reading the file as a word list. Store + // the words in the trees. + if (spell_read_wordfile(&spin, innames[i]) == FAIL) + error = true; + } + + // Free any conversion stuff. + convert_setup(&spin.si_conv, NULL, NULL); + } + + if (spin.si_compflags != NULL && spin.si_nobreak) + MSG(_("Warning: both compounding and NOBREAK specified")); + + if (!error && !got_int) { + // Combine tails in the tree. + spell_message(&spin, (char_u *)_(msg_compressing)); + wordtree_compress(&spin, spin.si_foldroot); + wordtree_compress(&spin, spin.si_keeproot); + wordtree_compress(&spin, spin.si_prefroot); + } + + if (!error && !got_int) { + // Write the info in the spell file. + vim_snprintf((char *)IObuff, IOSIZE, + _("Writing spell file %s ..."), wfname); + spell_message(&spin, IObuff); + + error = write_vim_spell(&spin, wfname) == FAIL; + + spell_message(&spin, (char_u *)_("Done!")); + vim_snprintf((char *)IObuff, IOSIZE, + _("Estimated runtime memory use: %d bytes"), spin.si_memtot); + spell_message(&spin, IObuff); + + // If the file is loaded need to reload it. + if (!error) + spell_reload_one(wfname, added_word); + } + + // Free the allocated memory. + ga_clear(&spin.si_rep); + ga_clear(&spin.si_repsal); + ga_clear(&spin.si_sal); + ga_clear(&spin.si_map); + ga_clear(&spin.si_comppat); + ga_clear(&spin.si_prefcond); + hash_clear_all(&spin.si_commonwords, 0); + + // Free the .aff file structures. + for (i = 0; i < incount; ++i) + if (afile[i] != NULL) + spell_free_aff(afile[i]); + + // Free all the bits and pieces at once. + free_blocks(spin.si_blocks); + + // If there is soundfolding info and no NOSUGFILE item create the + // .sug file with the soundfolded word trie. + if (spin.si_sugtime != 0 && !error && !got_int) + spell_make_sugfile(&spin, wfname); + + } + +theend: + xfree(fname); + xfree(wfname); +} + +// Display a message for spell file processing when 'verbose' is set or using +// ":mkspell". "str" can be IObuff. +static void spell_message(spellinfo_T *spin, char_u *str) +{ + if (spin->si_verbose || p_verbose > 2) { + if (!spin->si_verbose) + verbose_enter(); + MSG(str); + ui_flush(); + if (!spin->si_verbose) + verbose_leave(); + } +} + +// ":[count]spellgood {word}" +// ":[count]spellwrong {word}" +// ":[count]spellundo {word}" +void ex_spell(exarg_T *eap) +{ + spell_add_word(eap->arg, (int)STRLEN(eap->arg), eap->cmdidx == CMD_spellwrong, + eap->forceit ? 0 : (int)eap->line2, + eap->cmdidx == CMD_spellundo); +} + +// Add "word[len]" to 'spellfile' as a good or bad word. +void +spell_add_word ( + char_u *word, + int len, + int bad, + int idx, // "zG" and "zW": zero, otherwise index in + // 'spellfile' + bool undo // true for "zug", "zuG", "zuw" and "zuW" +) +{ + FILE *fd = NULL; + buf_T *buf = NULL; + bool new_spf = false; + char_u *fname; + char_u *fnamebuf = NULL; + char_u line[MAXWLEN * 2]; + long fpos, fpos_next = 0; + int i; + char_u *spf; + + if (idx == 0) { // use internal wordlist + if (int_wordlist == NULL) { + int_wordlist = vim_tempname(); + if (int_wordlist == NULL) + return; + } + fname = int_wordlist; + } else { + // If 'spellfile' isn't set figure out a good default value. + if (*curwin->w_s->b_p_spf == NUL) { + init_spellfile(); + new_spf = true; + } + + if (*curwin->w_s->b_p_spf == NUL) { + EMSG2(_(e_notset), "spellfile"); + return; + } + fnamebuf = xmalloc(MAXPATHL); + + for (spf = curwin->w_s->b_p_spf, i = 1; *spf != NUL; ++i) { + copy_option_part(&spf, fnamebuf, MAXPATHL, ","); + if (i == idx) + break; + if (*spf == NUL) { + EMSGN(_("E765: 'spellfile' does not have %" PRId64 " entries"), idx); + xfree(fnamebuf); + return; + } + } + + // Check that the user isn't editing the .add file somewhere. + buf = buflist_findname_exp(fnamebuf); + if (buf != NULL && buf->b_ml.ml_mfp == NULL) + buf = NULL; + if (buf != NULL && bufIsChanged(buf)) { + EMSG(_(e_bufloaded)); + xfree(fnamebuf); + return; + } + + fname = fnamebuf; + } + + if (bad || undo) { + // When the word appears as good word we need to remove that one, + // since its flags sort before the one with WF_BANNED. + fd = mch_fopen((char *)fname, "r"); + if (fd != NULL) { + while (!vim_fgets(line, MAXWLEN * 2, fd)) { + fpos = fpos_next; + fpos_next = ftell(fd); + if (STRNCMP(word, line, len) == 0 + && (line[len] == '/' || line[len] < ' ')) { + // Found duplicate word. Remove it by writing a '#' at + // the start of the line. Mixing reading and writing + // doesn't work for all systems, close the file first. + fclose(fd); + fd = mch_fopen((char *)fname, "r+"); + if (fd == NULL) + break; + if (fseek(fd, fpos, SEEK_SET) == 0) { + fputc('#', fd); + if (undo) { + home_replace(NULL, fname, NameBuff, MAXPATHL, TRUE); + smsg(_("Word '%.*s' removed from %s"), + len, word, NameBuff); + } + } + fseek(fd, fpos_next, SEEK_SET); + } + } + if (fd != NULL) + fclose(fd); + } + } + + if (!undo) { + fd = mch_fopen((char *)fname, "a"); + if (fd == NULL && new_spf) { + char_u *p; + + // We just initialized the 'spellfile' option and can't open the + // file. We may need to create the "spell" directory first. We + // already checked the runtime directory is writable in + // init_spellfile(). + if (!dir_of_file_exists(fname) && (p = path_tail_with_sep(fname)) != fname) { + int c = *p; + + // The directory doesn't exist. Try creating it and opening + // the file again. + *p = NUL; + os_mkdir((char *)fname, 0755); + *p = c; + fd = mch_fopen((char *)fname, "a"); + } + } + + if (fd == NULL) + EMSG2(_(e_notopen), fname); + else { + if (bad) + fprintf(fd, "%.*s/!\n", len, word); + else + fprintf(fd, "%.*s\n", len, word); + fclose(fd); + + home_replace(NULL, fname, NameBuff, MAXPATHL, TRUE); + smsg(_("Word '%.*s' added to %s"), len, word, NameBuff); + } + } + + if (fd != NULL) { + // Update the .add.spl file. + mkspell(1, &fname, false, true, true); + + // If the .add file is edited somewhere, reload it. + if (buf != NULL) + buf_reload(buf, buf->b_orig_mode); + + redraw_all_later(SOME_VALID); + } + xfree(fnamebuf); +} + +// Initialize 'spellfile' for the current buffer. +static void init_spellfile(void) +{ + char_u *buf; + int l; + char_u *fname; + char_u *rtp; + char_u *lend; + bool aspath = false; + char_u *lstart = curbuf->b_s.b_p_spl; + + if (*curwin->w_s->b_p_spl != NUL && !GA_EMPTY(&curwin->w_s->b_langp)) { + buf = xmalloc(MAXPATHL); + + // Find the end of the language name. Exclude the region. If there + // is a path separator remember the start of the tail. + for (lend = curwin->w_s->b_p_spl; *lend != NUL + && vim_strchr((char_u *)",._", *lend) == NULL; ++lend) + if (vim_ispathsep(*lend)) { + aspath = true; + lstart = lend + 1; + } + + // Loop over all entries in 'runtimepath'. Use the first one where we + // are allowed to write. + rtp = p_rtp; + while (*rtp != NUL) { + if (aspath) + // Use directory of an entry with path, e.g., for + // "/dir/lg.utf-8.spl" use "/dir". + STRLCPY(buf, curbuf->b_s.b_p_spl, + lstart - curbuf->b_s.b_p_spl); + else + // Copy the path from 'runtimepath' to buf[]. + copy_option_part(&rtp, buf, MAXPATHL, ","); + if (os_file_is_writable((char *)buf) == 2) { + // Use the first language name from 'spelllang' and the + // encoding used in the first loaded .spl file. + if (aspath) + STRLCPY(buf, curbuf->b_s.b_p_spl, + lend - curbuf->b_s.b_p_spl + 1); + else { + // Create the "spell" directory if it doesn't exist yet. + l = (int)STRLEN(buf); + vim_snprintf((char *)buf + l, MAXPATHL - l, "/spell"); + if (os_file_is_writable((char *)buf) != 2) { + os_mkdir((char *)buf, 0755); + } + + l = (int)STRLEN(buf); + vim_snprintf((char *)buf + l, MAXPATHL - l, + "/%.*s", (int)(lend - lstart), lstart); + } + l = (int)STRLEN(buf); + fname = LANGP_ENTRY(curwin->w_s->b_langp, 0) + ->lp_slang->sl_fname; + vim_snprintf((char *)buf + l, MAXPATHL - l, ".%s.add", + ((fname != NULL + && strstr((char *)path_tail(fname), ".ascii.") != NULL) + ? "ascii" + : (const char *)spell_enc())); + set_option_value("spellfile", 0L, (const char *)buf, OPT_LOCAL); + break; + } + aspath = false; + } + + xfree(buf); + } +} + +// Set the spell character tables from strings in the affix file. +static int set_spell_chartab(char_u *fol, char_u *low, char_u *upp) +{ + // We build the new tables here first, so that we can compare with the + // previous one. + spelltab_T new_st; + char_u *pf = fol, *pl = low, *pu = upp; + int f, l, u; + + clear_spell_chartab(&new_st); + + while (*pf != NUL) { + if (*pl == NUL || *pu == NUL) { + EMSG(_(e_affform)); + return FAIL; + } + f = mb_ptr2char_adv((const char_u **)&pf); + l = mb_ptr2char_adv((const char_u **)&pl); + u = mb_ptr2char_adv((const char_u **)&pu); + // Every character that appears is a word character. + if (f < 256) + new_st.st_isw[f] = true; + if (l < 256) + new_st.st_isw[l] = true; + if (u < 256) + new_st.st_isw[u] = true; + + // if "LOW" and "FOL" are not the same the "LOW" char needs + // case-folding + if (l < 256 && l != f) { + if (f >= 256) { + EMSG(_(e_affrange)); + return FAIL; + } + new_st.st_fold[l] = f; + } + + // if "UPP" and "FOL" are not the same the "UPP" char needs + // case-folding, it's upper case and the "UPP" is the upper case of + // "FOL" . + if (u < 256 && u != f) { + if (f >= 256) { + EMSG(_(e_affrange)); + return FAIL; + } + new_st.st_fold[u] = f; + new_st.st_isu[u] = true; + new_st.st_upper[f] = u; + } + } + + if (*pl != NUL || *pu != NUL) { + EMSG(_(e_affform)); + return FAIL; + } + + return set_spell_finish(&new_st); +} + +// Set the spell character tables from strings in the .spl file. +static void +set_spell_charflags ( + char_u *flags, + int cnt, // length of "flags" + char_u *fol +) +{ + // We build the new tables here first, so that we can compare with the + // previous one. + spelltab_T new_st; + int i; + char_u *p = fol; + int c; + + clear_spell_chartab(&new_st); + + for (i = 0; i < 128; ++i) { + if (i < cnt) { + new_st.st_isw[i + 128] = (flags[i] & CF_WORD) != 0; + new_st.st_isu[i + 128] = (flags[i] & CF_UPPER) != 0; + } + + if (*p != NUL) { + c = mb_ptr2char_adv((const char_u **)&p); + new_st.st_fold[i + 128] = c; + if (i + 128 != c && new_st.st_isu[i + 128] && c < 256) + new_st.st_upper[c] = i + 128; + } + } + + (void)set_spell_finish(&new_st); +} + +static int set_spell_finish(spelltab_T *new_st) +{ + int i; + + if (did_set_spelltab) { + // check that it's the same table + for (i = 0; i < 256; ++i) { + if (spelltab.st_isw[i] != new_st->st_isw[i] + || spelltab.st_isu[i] != new_st->st_isu[i] + || spelltab.st_fold[i] != new_st->st_fold[i] + || spelltab.st_upper[i] != new_st->st_upper[i]) { + EMSG(_("E763: Word characters differ between spell files")); + return FAIL; + } + } + } else { + // copy the new spelltab into the one being used + spelltab = *new_st; + did_set_spelltab = true; + } + + return OK; +} + +// Write the table with prefix conditions to the .spl file. +// When "fd" is NULL only count the length of what is written. +static int write_spell_prefcond(FILE *fd, garray_T *gap) +{ + assert(gap->ga_len >= 0); + + if (fd != NULL) + put_bytes(fd, (uintmax_t)gap->ga_len, 2); // <prefcondcnt> + + size_t totlen = 2 + (size_t)gap->ga_len; // <prefcondcnt> and <condlen> bytes + size_t x = 1; // collect return value of fwrite() + for (int i = 0; i < gap->ga_len; ++i) { + // <prefcond> : <condlen> <condstr> + char_u *p = ((char_u **)gap->ga_data)[i]; + if (p != NULL) { + size_t len = STRLEN(p); + if (fd != NULL) { + assert(len <= INT_MAX); + fputc((int)len, fd); + x &= fwrite(p, len, 1, fd); + } + totlen += len; + } else if (fd != NULL) + fputc(0, fd); + } + + assert(totlen <= INT_MAX); + return (int)totlen; +} + +// Use map string "map" for languages "lp". +static void set_map_str(slang_T *lp, char_u *map) +{ + char_u *p; + int headc = 0; + int c; + int i; + + if (*map == NUL) { + lp->sl_has_map = false; + return; + } + lp->sl_has_map = true; + + // Init the array and hash tables empty. + for (i = 0; i < 256; ++i) + lp->sl_map_array[i] = 0; + hash_init(&lp->sl_map_hash); + + // The similar characters are stored separated with slashes: + // "aaa/bbb/ccc/". Fill sl_map_array[c] with the character before c and + // before the same slash. For characters above 255 sl_map_hash is used. + for (p = map; *p != NUL; ) { + c = mb_cptr2char_adv((const char_u **)&p); + if (c == '/') { + headc = 0; + } else { + if (headc == 0) { + headc = c; + } + + // Characters above 255 don't fit in sl_map_array[], put them in + // the hash table. Each entry is the char, a NUL the headchar and + // a NUL. + if (c >= 256) { + int cl = mb_char2len(c); + int headcl = mb_char2len(headc); + char_u *b; + hash_T hash; + hashitem_T *hi; + + b = xmalloc(cl + headcl + 2); + mb_char2bytes(c, b); + b[cl] = NUL; + mb_char2bytes(headc, b + cl + 1); + b[cl + 1 + headcl] = NUL; + hash = hash_hash(b); + hi = hash_lookup(&lp->sl_map_hash, (const char *)b, STRLEN(b), hash); + if (HASHITEM_EMPTY(hi)) { + hash_add_item(&lp->sl_map_hash, hi, b, hash); + } else { + // This should have been checked when generating the .spl + // file. + EMSG(_("E783: duplicate char in MAP entry")); + xfree(b); + } + } else + lp->sl_map_array[c] = headc; + } + } +} + diff --git a/src/nvim/spellfile.h b/src/nvim/spellfile.h new file mode 100644 index 0000000000..633ee014a7 --- /dev/null +++ b/src/nvim/spellfile.h @@ -0,0 +1,13 @@ +#ifndef NVIM_SPELLFILE_H +#define NVIM_SPELLFILE_H + +#include <stdbool.h> + +#include "nvim/spell_defs.h" +#include "nvim/types.h" +#include "nvim/ex_cmds_defs.h" + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "spellfile.h.generated.h" +#endif +#endif // NVIM_SPELLFILE_H diff --git a/src/nvim/state.c b/src/nvim/state.c index 44c6441e40..eb0b590a9b 100644 --- a/src/nvim/state.c +++ b/src/nvim/state.c @@ -1,8 +1,12 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #include <assert.h> #include "nvim/lib/kvec.h" #include "nvim/ascii.h" +#include "nvim/log.h" #include "nvim/state.h" #include "nvim/vim.h" #include "nvim/main.h" @@ -95,3 +99,52 @@ int get_real_state(void) return State; } +/// @returns[allocated] mode string +char *get_mode(void) +{ + char *buf = xcalloc(3, sizeof(char)); + + if (VIsual_active) { + if (VIsual_select) { + buf[0] = (char)(VIsual_mode + 's' - 'v'); + } else { + buf[0] = (char)VIsual_mode; + } + } else if (State == HITRETURN || State == ASKMORE || State == SETWSIZE + || State == CONFIRM) { + buf[0] = 'r'; + if (State == ASKMORE) { + buf[1] = 'm'; + } else if (State == CONFIRM) { + buf[1] = '?'; + } + } else if (State == EXTERNCMD) { + buf[0] = '!'; + } else if (State & INSERT) { + if (State & VREPLACE_FLAG) { + buf[0] = 'R'; + buf[1] = 'v'; + } else if (State & REPLACE_FLAG) { + buf[0] = 'R'; + } else { + buf[0] = 'i'; + } + } else if (State & CMDLINE) { + buf[0] = 'c'; + if (exmode_active) { + buf[1] = 'v'; + } + } else if (exmode_active) { + buf[0] = 'c'; + buf[1] = 'e'; + } else if (State & TERM_FOCUS) { + buf[0] = 't'; + } else { + buf[0] = 'n'; + if (finish_op) { + buf[1] = 'o'; + } + } + + return buf; +} diff --git a/src/nvim/strings.c b/src/nvim/strings.c index c1800a0639..687f734742 100644 --- a/src/nvim/strings.c +++ b/src/nvim/strings.c @@ -1,7 +1,14 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #include <inttypes.h> +#include <stdarg.h> #include <stdbool.h> #include <string.h> +#include <math.h> +#include <assert.h> +#include "nvim/assert.h" #include "nvim/vim.h" #include "nvim/ascii.h" #include "nvim/strings.h" @@ -41,6 +48,7 @@ #include "nvim/window.h" #include "nvim/os/os.h" #include "nvim/os/shell.h" +#include "nvim/eval/encode.h" /* * Copy "string" into newly allocated memory. @@ -51,15 +59,14 @@ char_u *vim_strsave(const char_u *string) return (char_u *)xstrdup((char *)string); } -/* - * Copy up to "len" bytes of "string" into newly allocated memory and - * terminate with a NUL. - * The allocated memory always has size "len + 1", also when "string" is - * shorter. - */ +/// Copy up to `len` bytes of `string` into newly allocated memory and +/// terminate with a NUL. The allocated memory always has size `len + 1`, even +/// when `string` is shorter. char_u *vim_strnsave(const char_u *string, size_t len) FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL { + // strncpy is intentional: some parts of Vim use `string` shorter than `len` + // and expect the remainder to be zeroed out. return (char_u *)strncpy(xmallocz(len), (char *)string, len); } @@ -194,8 +201,16 @@ char_u *vim_strsave_shellescape(const char_u *string, /* First count the number of extra bytes required. */ size_t length = STRLEN(string) + 3; // two quotes and a trailing NUL for (const char_u *p = string; *p != NUL; mb_ptr_adv(p)) { - if (*p == '\'') - length += 3; /* ' => '\'' */ +#ifdef WIN32 + if (!p_ssl) { + if (*p == '"') { + length++; // " -> "" + } + } else +#endif + if (*p == '\'') { + length += 3; // ' => '\'' + } if ((*p == '\n' && (csh_like || do_newline)) || (*p == '!' && (csh_like || do_special))) { ++length; /* insert backslash */ @@ -212,10 +227,25 @@ char_u *vim_strsave_shellescape(const char_u *string, escaped_string = xmalloc(length); d = escaped_string; - /* add opening quote */ + // add opening quote +#ifdef WIN32 + if (!p_ssl) { + *d++ = '"'; + } else +#endif *d++ = '\''; for (const char_u *p = string; *p != NUL; ) { +#ifdef WIN32 + if (!p_ssl) { + if (*p == '"') { + *d++ = '"'; + *d++ = '"'; + p++; + continue; + } + } else +#endif if (*p == '\'') { *d++ = '\''; *d++ = '\\'; @@ -242,7 +272,12 @@ char_u *vim_strsave_shellescape(const char_u *string, MB_COPY_CHAR(p, d); } - /* add terminating quote and finish with a NUL */ + // add terminating quote and finish with a NUL +# ifdef WIN32 + if (!p_ssl) { + *d++ = '"'; + } else +# endif *d++ = '\''; *d = NUL; @@ -287,45 +322,42 @@ void vim_strup(char_u *p) } } -/* - * Make string "s" all upper-case and return it in allocated memory. - * Handles multi-byte characters as well as possible. - */ -char_u *strup_save(const char_u *orig) +/// Make given string all upper-case or all lower-case +/// +/// Handles multi-byte characters as good as possible. +/// +/// @param[in] orig Input string. +/// @param[in] upper If true make uppercase, otherwise lowercase +/// +/// @return [allocated] upper-cased string. +char *strcase_save(const char *const orig, bool upper) FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL { - char_u *res = vim_strsave(orig); + char *res = xstrdup(orig); - char_u *p = res; + char *p = res; while (*p != NUL) { int l; - if (enc_utf8) { - int c = utf_ptr2char(p); - int uc = utf_toupper(c); - - /* Reallocate string when byte count changes. This is rare, - * thus it's OK to do another malloc()/free(). */ - l = utf_ptr2len(p); - int newl = utf_char2len(uc); - if (newl != l) { - // TODO(philix): use xrealloc() in strup_save() - char_u *s = xmalloc(STRLEN(res) + (size_t)(1 + newl - l)); - memcpy(s, res, (size_t)(p - res)); - STRCPY(s + (p - res) + newl, p + l); - p = s + (p - res); - xfree(res); - res = s; - } + int c = utf_ptr2char((const char_u *)p); + int uc = upper ? mb_toupper(c) : mb_tolower(c); - utf_char2bytes(uc, p); - p += newl; - } else if (has_mbyte && (l = (*mb_ptr2len)(p)) > 1) - p += l; /* skip multi-byte character */ - else { - *p = (char_u) TOUPPER_LOC(*p); // note that toupper() can be a macro - p++; + // Reallocate string when byte count changes. This is rare, + // thus it's OK to do another malloc()/free(). + l = utf_ptr2len((const char_u *)p); + int newl = utf_char2len(uc); + if (newl != l) { + // TODO(philix): use xrealloc() in strup_save() + char *s = xmalloc(STRLEN(res) + (size_t)(1 + newl - l)); + memcpy(s, res, (size_t)(p - res)); + STRCPY(s + (p - res) + newl, p + l); + p = s + (p - res); + xfree(res); + res = s; } + + utf_char2bytes(uc, (char_u *)p); + p += newl; } return res; @@ -344,24 +376,6 @@ void del_trailing_spaces(char_u *ptr) *q = NUL; } -/* - * Like strcat(), but make sure the result fits in "tosize" bytes and is - * always NUL terminated. - */ -void vim_strcat(char_u *restrict to, const char_u *restrict from, - size_t tosize) - FUNC_ATTR_NONNULL_ALL -{ - size_t tolen = STRLEN(to); - size_t fromlen = STRLEN(from); - - if (tolen + fromlen + 1 > tosize) { - memcpy(to + tolen, from, tosize - tolen - 1); - to[tosize - 1] = NUL; - } else - STRCPY(to + tolen, from); -} - #if (!defined(HAVE_STRCASECMP) && !defined(HAVE_STRICMP)) /* * Compare two strings, ignoring case, using current locale. @@ -411,72 +425,27 @@ int vim_strnicmp(const char *s1, const char *s2, size_t len) } #endif -/* - * Version of strchr() and strrchr() that handle unsigned char strings - * with characters from 128 to 255 correctly. It also doesn't return a - * pointer to the NUL at the end of the string. - */ -char_u *vim_strchr(const char_u *string, int c) - FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE +/// strchr() version which handles multibyte strings +/// +/// @param[in] string String to search in. +/// @param[in] c Character to search for. +/// +/// @return Pointer to the first byte of the found character in string or NULL +/// if it was not found or character is invalid. NUL character is never +/// found, use `strlen()` instead. +char_u *vim_strchr(const char_u *const string, const int c) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT { - int b; - - const char_u *p = string; - if (enc_utf8 && c >= 0x80) { - while (*p != NUL) { - int l = (*mb_ptr2len)(p); - - // Avoid matching an illegal byte here. - if (l > 1 && utf_ptr2char(p) == c) { - return (char_u *) p; - } - p += l; - } + if (c <= 0) { return NULL; + } else if (c < 0x80) { + return (char_u *)strchr((const char *)string, c); + } else { + char u8char[MB_MAXBYTES + 1]; + const int len = utf_char2bytes(c, (char_u *)u8char); + u8char[len] = NUL; + return (char_u *)strstr((const char *)string, u8char); } - if (enc_dbcs != 0 && c > 255) { - int n2 = c & 0xff; - - c = ((unsigned)c >> 8) & 0xff; - while ((b = *p) != NUL) { - if (b == c && p[1] == n2) - return (char_u *) p; - p += (*mb_ptr2len)(p); - } - return NULL; - } - if (has_mbyte) { - while ((b = *p) != NUL) { - if (b == c) - return (char_u *) p; - p += (*mb_ptr2len)(p); - } - return NULL; - } - while ((b = *p) != NUL) { - if (b == c) - return (char_u *) p; - ++p; - } - return NULL; -} - -/* - * Version of strchr() that only works for bytes and handles unsigned char - * strings with characters above 128 correctly. It also doesn't return a - * pointer to the NUL at the end of the string. - */ -char_u *vim_strbyte(const char_u *string, int c) - FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE -{ - const char_u *p = string; - - while (*p != NUL) { - if (*p == c) - return (char_u *) p; - ++p; - } - return NULL; } /* @@ -560,3 +529,905 @@ char_u *concat_str(const char_u *restrict str1, const char_u *restrict str2) return dest; } + +static const char *const e_printf = + N_("E766: Insufficient arguments for printf()"); + +/// Get number argument from idxp entry in tvs +/// +/// Will give an error message for VimL entry with invalid type or for +/// insufficient entries. +/// +/// @param[in] tvs List of VimL values. List is terminated by VAR_UNKNOWN +/// value. +/// @param[in,out] idxp Index in a list. Will be incremented. Indexing starts +/// at 1. +/// +/// @return Number value or 0 in case of error. +static varnumber_T tv_nr(typval_T *tvs, int *idxp) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ + int idx = *idxp - 1; + varnumber_T n = 0; + + if (tvs[idx].v_type == VAR_UNKNOWN) { + EMSG(_(e_printf)); + } else { + (*idxp)++; + bool err = false; + n = tv_get_number_chk(&tvs[idx], &err); + if (err) { + n = 0; + } + } + return n; +} + +/// Get string argument from idxp entry in tvs +/// +/// Will give an error message for VimL entry with invalid type or for +/// insufficient entries. +/// +/// @param[in] tvs List of VimL values. List is terminated by VAR_UNKNOWN +/// value. +/// @param[in,out] idxp Index in a list. Will be incremented. +/// @param[out] tofree If the idxp entry in tvs is not a String or a Number, +/// it will be converted to String in the same format +/// as ":echo" and stored in "*tofree". The caller must +/// free "*tofree". +/// +/// @return String value or NULL in case of error. +static const char *tv_str(typval_T *tvs, int *idxp, char **const tofree) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ + int idx = *idxp - 1; + const char *s = NULL; + + if (tvs[idx].v_type == VAR_UNKNOWN) { + EMSG(_(e_printf)); + } else { + (*idxp)++; + if (tvs[idx].v_type == VAR_STRING || tvs[idx].v_type == VAR_NUMBER) { + s = tv_get_string_chk(&tvs[idx]); + *tofree = NULL; + } else { + s = *tofree = encode_tv2echo(&tvs[idx], NULL); + } + } + return s; +} + +/// Get pointer argument from the next entry in tvs +/// +/// Will give an error message for VimL entry with invalid type or for +/// insufficient entries. +/// +/// @param[in] tvs List of typval_T values. +/// @param[in,out] idxp Pointer to the index of the current value. +/// +/// @return Pointer stored in typval_T or NULL. +static const void *tv_ptr(const typval_T *const tvs, int *const idxp) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ +#define OFF(attr) offsetof(union typval_vval_union, attr) + STATIC_ASSERT( + OFF(v_string) == OFF(v_list) + && OFF(v_string) == OFF(v_dict) + && OFF(v_string) == OFF(v_partial) + && sizeof(tvs[0].vval.v_string) == sizeof(tvs[0].vval.v_list) + && sizeof(tvs[0].vval.v_string) == sizeof(tvs[0].vval.v_dict) + && sizeof(tvs[0].vval.v_string) == sizeof(tvs[0].vval.v_partial), + "Strings, dictionaries, lists and partials are expected to be pointers, " + "so that all three of them can be accessed via v_string"); +#undef OFF + const int idx = *idxp - 1; + if (tvs[idx].v_type == VAR_UNKNOWN) { + EMSG(_(e_printf)); + return NULL; + } else { + (*idxp)++; + return tvs[idx].vval.v_string; + } +} + +/// Get float argument from idxp entry in tvs +/// +/// Will give an error message for VimL entry with invalid type or for +/// insufficient entries. +/// +/// @param[in] tvs List of VimL values. List is terminated by VAR_UNKNOWN +/// value. +/// @param[in,out] idxp Index in a list. Will be incremented. +/// +/// @return Floating-point value or zero in case of error. +static float_T tv_float(typval_T *const tvs, int *const idxp) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ + int idx = *idxp - 1; + float_T f = 0; + + if (tvs[idx].v_type == VAR_UNKNOWN) { + EMSG(_(e_printf)); + } else { + (*idxp)++; + if (tvs[idx].v_type == VAR_FLOAT) { + f = tvs[idx].vval.v_float; + } else if (tvs[idx].v_type == VAR_NUMBER) { + f = (float_T)tvs[idx].vval.v_number; + } else { + EMSG(_("E807: Expected Float argument for printf()")); + } + } + return f; +} + +// This code was included to provide a portable vsnprintf() and snprintf(). +// Some systems may provide their own, but we always use this one for +// consistency. +// +// This code is based on snprintf.c - a portable implementation of snprintf +// by Mark Martinec <mark.martinec@ijs.si>, Version 2.2, 2000-10-06. +// Included with permission. It was heavily modified to fit in Vim. +// The original code, including useful comments, can be found here: +// +// http://www.ijs.si/software/snprintf/ +// +// This snprintf() only supports the following conversion specifiers: +// s, c, b, B, d, u, o, x, X, p (and synonyms: i, D, U, O - see below) +// with flags: '-', '+', ' ', '0' and '#'. +// An asterisk is supported for field width as well as precision. +// +// Limited support for floating point was added: 'f', 'e', 'E', 'g', 'G'. +// +// Length modifiers 'h' (short int), 'l' (long int) and "ll" (long long int) are +// supported. +// +// The locale is not used, the string is used as a byte string. This is only +// relevant for double-byte encodings where the second byte may be '%'. +// +// It is permitted for "str_m" to be zero, and it is permitted to specify NULL +// pointer for resulting string argument if "str_m" is zero (as per ISO C99). +// +// The return value is the number of characters which would be generated +// for the given input, excluding the trailing NUL. If this value +// is greater or equal to "str_m", not all characters from the result +// have been stored in str, output bytes beyond the ("str_m"-1) -th character +// are discarded. If "str_m" is greater than zero it is guaranteed +// the resulting string will be NUL-terminated. + +// vim_vsnprintf() can be invoked with either "va_list" or a list of +// "typval_T". When the latter is not used it must be NULL. + +/// Append a formatted value to the string +/// +/// @see vim_vsnprintf(). +int vim_snprintf_add(char *str, size_t str_m, char *fmt, ...) +{ + const size_t len = strlen(str); + size_t space; + + if (str_m <= len) { + space = 0; + } else { + space = str_m - len; + } + va_list ap; + va_start(ap, fmt); + const int str_l = vim_vsnprintf(str + len, space, fmt, ap, NULL); + va_end(ap); + return str_l; +} + +/// Write formatted value to the string +/// +/// @param[out] str String to write to. +/// @param[in] str_m String length. +/// @param[in] fmt String format. +/// +/// @return Number of bytes excluding NUL byte that would be written to the +/// string if str_m was greater or equal to the return value. +int vim_snprintf(char *str, size_t str_m, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + const int str_l = vim_vsnprintf(str, str_m, fmt, ap, NULL); + va_end(ap); + return str_l; +} + +// Return the representation of infinity for printf() function: +// "-inf", "inf", "+inf", " inf", "-INF", "INF", "+INF" or " INF". +static const char *infinity_str(bool positive, char fmt_spec, + int force_sign, int space_for_positive) +{ + static const char *table[] = { + "-inf", "inf", "+inf", " inf", + "-INF", "INF", "+INF", " INF" + }; + int idx = positive * (1 + force_sign + force_sign * space_for_positive); + if (ASCII_ISUPPER(fmt_spec)) { + idx += 4; + } + return table[idx]; +} + + +/// Write formatted value to the string +/// +/// @param[out] str String to write to. +/// @param[in] str_m String length. +/// @param[in] fmt String format. +/// @param[in] ap Values that should be formatted. Ignored if tvs is not NULL. +/// @param[in] tvs Values that should be formatted, for printf() VimL +/// function. Must be NULL in other cases. +/// +/// @return Number of bytes excluding NUL byte that would be written to the +/// string if str_m was greater or equal to the return value. +int vim_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap, + typval_T *const tvs) +{ + size_t str_l = 0; + bool str_avail = str_l < str_m; + const char *p = fmt; + int arg_idx = 1; + + if (!p) { + p = ""; + } + while (*p) { + if (*p != '%') { + // copy up to the next '%' or NUL without any changes + size_t n = (size_t)(xstrchrnul(p + 1, '%') - p); + if (str_avail) { + size_t avail = str_m - str_l; + memmove(str + str_l, p, MIN(n, avail)); + str_avail = n < avail; + } + p += n; + assert(n <= SIZE_MAX - str_l); + str_l += n; + } else { + size_t min_field_width = 0, precision = 0; + int zero_padding = 0, precision_specified = 0, justify_left = 0; + int alternate_form = 0, force_sign = 0; + + // if both ' ' and '+' flags appear, ' ' flag should be ignored + int space_for_positive = 1; + + // allowed values: \0, h, l, 2 (for ll), z, L + char length_modifier = '\0'; + + // temporary buffer for simple numeric->string conversion +# define TMP_LEN 350 // 1e308 seems reasonable as the maximum printable + char tmp[TMP_LEN]; + + // string address in case of string argument + const char *str_arg = NULL; + + // natural field width of arg without padding and sign + size_t str_arg_l; + + // unsigned char argument value (only defined for c conversion); + // standard explicitly states the char argument for the c + // conversion is unsigned + unsigned char uchar_arg; + + // number of zeros to be inserted for numeric conversions as + // required by the precision or minimal field width + size_t number_of_zeros_to_pad = 0; + + // index into tmp where zero padding is to be inserted + size_t zero_padding_insertion_ind = 0; + + // current conversion specifier character + char fmt_spec = '\0'; + + // buffer for 's' and 'S' specs + char *tofree = NULL; + + p++; // skip '%' + + // parse flags + while (true) { + switch (*p) { + case '0': zero_padding = 1; p++; continue; + case '-': justify_left = 1; p++; continue; + // if both '0' and '-' flags appear, '0' should be ignored + case '+': force_sign = 1; space_for_positive = 0; p++; continue; + case ' ': force_sign = 1; p++; continue; + // if both ' ' and '+' flags appear, ' ' should be ignored + case '#': alternate_form = 1; p++; continue; + case '\'': p++; continue; + default: break; + } + break; + } + + // parse field width + if (*p == '*') { + p++; + const int j = tvs ? (int)tv_nr(tvs, &arg_idx) : va_arg(ap, int); + if (j >= 0) { + min_field_width = (size_t)j; + } else { + min_field_width = (size_t)-j; + justify_left = 1; + } + } else if (ascii_isdigit((int)(*p))) { + // size_t could be wider than unsigned int; make sure we treat + // argument like common implementations do + unsigned int uj = (unsigned)(*p++ - '0'); + + while (ascii_isdigit((int)(*p))) { + uj = 10 * uj + (unsigned int)(*p++ - '0'); + } + min_field_width = uj; + } + + // parse precision + if (*p == '.') { + p++; + precision_specified = 1; + if (*p == '*') { + const int j = tvs ? (int)tv_nr(tvs, &arg_idx) : va_arg(ap, int); + p++; + if (j >= 0) { + precision = (size_t)j; + } else { + precision_specified = 0; + precision = 0; + } + } else if (ascii_isdigit((int)(*p))) { + // size_t could be wider than unsigned int; make sure we + // treat argument like common implementations do + unsigned int uj = (unsigned)(*p++ - '0'); + + while (ascii_isdigit((int)(*p))) { + uj = 10 * uj + (unsigned int)(*p++ - '0'); + } + precision = uj; + } + } + + // parse 'h', 'l', 'll' and 'z' length modifiers + if (*p == 'h' || *p == 'l' || *p == 'z') { + length_modifier = *p; + p++; + if (length_modifier == 'l' && *p == 'l') { // ll, encoded as 2 + length_modifier = '2'; + p++; + } + } + + fmt_spec = *p; + + // common synonyms + switch (fmt_spec) { + case 'i': fmt_spec = 'd'; break; + case 'D': fmt_spec = 'd'; length_modifier = 'l'; break; + case 'U': fmt_spec = 'u'; length_modifier = 'l'; break; + case 'O': fmt_spec = 'o'; length_modifier = 'l'; break; + default: break; + } + + switch (fmt_spec) { + case 'd': case 'u': case 'o': case 'x': case 'X': + if (tvs && length_modifier == '\0') { + length_modifier = '2'; + } + } + + // get parameter value, do initial processing + switch (fmt_spec) { + // '%' and 'c' behave similar to 's' regarding flags and field widths + case '%': case 'c': case 's': case 'S': + str_arg_l = 1; + switch (fmt_spec) { + case '%': + str_arg = p; + break; + + case 'c': { + const int j = tvs ? (int)tv_nr(tvs, &arg_idx) : va_arg(ap, int); + // standard demands unsigned char + uchar_arg = (unsigned char)j; + str_arg = (char *)&uchar_arg; + break; + } + + case 's': + case 'S': + str_arg = tvs ? tv_str(tvs, &arg_idx, &tofree) + : va_arg(ap, const char *); + if (!str_arg) { + str_arg = "[NULL]"; + str_arg_l = 6; + } else if (!precision_specified) { + // make sure not to address string beyond the specified + // precision + str_arg_l = strlen(str_arg); + } else if (precision == 0) { + // truncate string if necessary as requested by precision + str_arg_l = 0; + } else { + // memchr on HP does not like n > 2^31 + // TODO(elmart): check if this still holds / is relevant + str_arg_l = (size_t)((char *)xmemscan(str_arg, + NUL, + MIN(precision, + 0x7fffffff)) + - str_arg); + } + if (fmt_spec == 'S') { + if (min_field_width != 0) { + min_field_width += (strlen(str_arg) + - mb_string2cells((char_u *)str_arg)); + } + if (precision) { + const char *p1 = str_arg; + for (size_t i = 0; i < precision && *p1; i++) { + p1 += mb_ptr2len((const char_u *)p1); + } + str_arg_l = precision = (size_t)(p1 - str_arg); + } + } + break; + + default: + break; + } + break; + + case 'd': + case 'u': + case 'b': case 'B': + case 'o': + case 'x': case 'X': + case 'p': { + // u, b, B, o, x, X and p conversion specifiers imply + // the value is unsigned; d implies a signed value + + // 0 if numeric argument is zero (or if pointer is NULL for 'p'), + // +1 if greater than zero (or non NULL for 'p'), + // -1 if negative (unsigned argument is never negative) + int arg_sign = 0; + + intmax_t arg = 0; + uintmax_t uarg = 0; + + // only defined for p conversion + const void *ptr_arg = NULL; + + if (fmt_spec == 'p') { + ptr_arg = tvs ? tv_ptr(tvs, &arg_idx) : va_arg(ap, void *); + if (ptr_arg) { + arg_sign = 1; + } + } else if (fmt_spec == 'd') { + // signed + switch (length_modifier) { + case '\0': + case 'h': { + // char and short arguments are passed as int + arg = (tvs ? (int)tv_nr(tvs, &arg_idx) : va_arg(ap, int)); + break; + } + case 'l': { + arg = (tvs ? (long)tv_nr(tvs, &arg_idx) : va_arg(ap, long)); + break; + } + case '2': { + arg = ( + tvs + ? (long long)tv_nr(tvs, &arg_idx) // NOLINT (runtime/int) + : va_arg(ap, long long)); // NOLINT (runtime/int) + break; + } + case 'z': { + arg = (tvs + ? (ptrdiff_t)tv_nr(tvs, &arg_idx) + : va_arg(ap, ptrdiff_t)); + break; + } + } + if (arg > 0) { + arg_sign = 1; + } else if (arg < 0) { + arg_sign = -1; + } + } else { + // unsigned + switch (length_modifier) { + case '\0': + case 'h': { + uarg = (tvs + ? (unsigned)tv_nr(tvs, &arg_idx) + : va_arg(ap, unsigned)); + break; + } + case 'l': { + uarg = (tvs + ? (unsigned long)tv_nr(tvs, &arg_idx) + : va_arg(ap, unsigned long)); + break; + } + case '2': { + uarg = (uintmax_t)(unsigned long long)( // NOLINT (runtime/int) + tvs + ? ((unsigned long long) // NOLINT (runtime/int) + tv_nr(tvs, &arg_idx)) + : va_arg(ap, unsigned long long)); // NOLINT (runtime/int) + break; + } + case 'z': { + uarg = (tvs + ? (size_t)tv_nr(tvs, &arg_idx) + : va_arg(ap, size_t)); + break; + } + } + arg_sign = (uarg != 0); + } + + str_arg = tmp; + str_arg_l = 0; + + // For d, i, u, o, x, and X conversions, if precision is specified, + // '0' flag should be ignored. This is so with Solaris 2.6, Digital + // UNIX 4.0, HPUX 10, Linux, FreeBSD, NetBSD; but not with Perl. + if (precision_specified) { + zero_padding = 0; + } + + if (fmt_spec == 'd') { + if (force_sign && arg_sign >= 0) { + tmp[str_arg_l++] = space_for_positive ? ' ' : '+'; + } + // leave negative numbers for snprintf to handle, to + // avoid handling tricky cases like (short int)-32768 + } else if (alternate_form) { + if (arg_sign != 0 && (fmt_spec == 'x' || fmt_spec == 'X' + || fmt_spec == 'b' || fmt_spec == 'B')) { + tmp[str_arg_l++] = '0'; + tmp[str_arg_l++] = fmt_spec; + } + // alternate form should have no effect for p * conversion, but ... + } + + zero_padding_insertion_ind = str_arg_l; + if (!precision_specified) { + precision = 1; // default precision is 1 + } + if (precision == 0 && arg_sign == 0) { + // when zero value is formatted with an explicit precision 0, + // resulting formatted string is empty (d, i, u, b, B, o, x, X, p) + } else { + switch (fmt_spec) { + case 'p': { // pointer + str_arg_l += (size_t)snprintf(tmp + str_arg_l, + sizeof(tmp) - str_arg_l, + "%p", ptr_arg); + break; + } + case 'd': { // signed + str_arg_l += (size_t)snprintf(tmp + str_arg_l, + sizeof(tmp) - str_arg_l, + "%" PRIdMAX, arg); + break; + } + case 'b': case 'B': { // binary + size_t bits = 0; + for (bits = sizeof(uintmax_t) * 8; bits > 0; bits--) { + if ((uarg >> (bits - 1)) & 0x1) { + break; + } + } + + while (bits > 0) { + tmp[str_arg_l++] = ((uarg >> --bits) & 0x1) ? '1' : '0'; + } + break; + } + default: { // unsigned + // construct a simple format string for snprintf + char f[] = "%" PRIuMAX; + f[sizeof("%" PRIuMAX) - 1 - 1] = fmt_spec; + assert(PRIuMAX[sizeof(PRIuMAX) - 1 - 1] == 'u'); + str_arg_l += (size_t)snprintf(tmp + str_arg_l, + sizeof(tmp) - str_arg_l, + f, uarg); + break; + } + assert(str_arg_l < sizeof(tmp)); + } + + // include the optional minus sign and possible "0x" in the region + // before the zero padding insertion point + if (zero_padding_insertion_ind < str_arg_l + && tmp[zero_padding_insertion_ind] == '-') { + zero_padding_insertion_ind++; + } + if (zero_padding_insertion_ind + 1 < str_arg_l + && tmp[zero_padding_insertion_ind] == '0' + && (tmp[zero_padding_insertion_ind + 1] == 'x' + || tmp[zero_padding_insertion_ind + 1] == 'X' + || tmp[zero_padding_insertion_ind + 1] == 'b' + || tmp[zero_padding_insertion_ind + 1] == 'B')) { + zero_padding_insertion_ind += 2; + } + } + + { + size_t num_of_digits = str_arg_l - zero_padding_insertion_ind; + + if (alternate_form && fmt_spec == 'o' + // unless zero is already the first character + && !(zero_padding_insertion_ind < str_arg_l + && tmp[zero_padding_insertion_ind] == '0')) { + // assure leading zero for alternate-form octal numbers + if (!precision_specified + || precision < num_of_digits + 1) { + // precision is increased to force the first character to be + // zero, except if a zero value is formatted with an explicit + // precision of zero + precision = num_of_digits + 1; + } + } + // zero padding to specified precision? + if (num_of_digits < precision) { + number_of_zeros_to_pad = precision - num_of_digits; + } + } + // zero padding to specified minimal field width? + if (!justify_left && zero_padding) { + const int n = (int)(min_field_width - (str_arg_l + + number_of_zeros_to_pad)); + if (n > 0) { + number_of_zeros_to_pad += (size_t)n; + } + } + break; + } + + case 'f': + case 'F': + case 'e': + case 'E': + case 'g': + case 'G': + { + // floating point + char format[40]; + int remove_trailing_zeroes = false; + + double f = tvs ? tv_float(tvs, &arg_idx) : va_arg(ap, double); + double abs_f = f < 0 ? -f : f; + + if (fmt_spec == 'g' || fmt_spec == 'G') { + // can't use %g directly, cause it prints "1.0" as "1" + if ((abs_f >= 0.001 && abs_f < 10000000.0) || abs_f == 0.0) { + fmt_spec = ASCII_ISUPPER(fmt_spec) ? 'F' : 'f'; + } else { + fmt_spec = fmt_spec == 'g' ? 'e' : 'E'; + } + remove_trailing_zeroes = true; + } + + if (isinf(f) + || (strchr("fF", fmt_spec) != NULL && abs_f > 1.0e307)) { + xstrlcpy(tmp, infinity_str(f > 0.0, fmt_spec, + force_sign, space_for_positive), + sizeof(tmp)); + str_arg_l = strlen(tmp); + zero_padding = 0; + } else if (isnan(f)) { + // Not a number: nan or NAN + memmove(tmp, ASCII_ISUPPER(fmt_spec) ? "NAN" : "nan", 4); + str_arg_l = 3; + zero_padding = 0; + } else { + format[0] = '%'; + size_t l = 1; + if (force_sign) { + format[l++] = space_for_positive ? ' ' : '+'; + } + if (precision_specified) { + size_t max_prec = TMP_LEN - 10; + + // make sure we don't get more digits than we have room for + if ((fmt_spec == 'f' || fmt_spec == 'F') && abs_f > 1.0) { + max_prec -= (size_t)log10(abs_f); + } + if (precision > max_prec) { + precision = max_prec; + } + l += (size_t)snprintf(format + l, sizeof(format) - l, ".%d", + (int)precision); + } + + // Cast to char to avoid a conversion warning on Ubuntu 12.04. + format[l] = (char)(fmt_spec == 'F' ? 'f' : fmt_spec); + format[l + 1] = NUL; + + // Regular float number + assert(l + 1 < sizeof(format)); + str_arg_l = (size_t)snprintf(tmp, sizeof(tmp), format, f); + assert(str_arg_l < sizeof(tmp)); + + if (remove_trailing_zeroes) { + int i; + char *tp; + + // using %g or %G: remove superfluous zeroes + if (fmt_spec == 'f' || fmt_spec == 'F') { + tp = tmp + str_arg_l - 1; + } else { + tp = (char *)vim_strchr((char_u *)tmp, + fmt_spec == 'e' ? 'e' : 'E'); + if (tp) { + // remove superfluous '+' and leading zeroes from exponent + if (tp[1] == '+') { + // change "1.0e+07" to "1.0e07" + STRMOVE(tp + 1, tp + 2); + str_arg_l--; + } + i = (tp[1] == '-') ? 2 : 1; + while (tp[i] == '0') { + // change "1.0e07" to "1.0e7" + STRMOVE(tp + i, tp + i + 1); + str_arg_l--; + } + tp--; + } + } + + if (tp != NULL && !precision_specified) { + // remove trailing zeroes, but keep the one just after a dot + while (tp > tmp + 2 && *tp == '0' && tp[-1] != '.') { + STRMOVE(tp, tp + 1); + tp--; + str_arg_l--; + } + } + } else { + // Be consistent: some printf("%e") use 1.0e+12 and some + // 1.0e+012; remove one zero in the last case. + char *tp = (char *)vim_strchr((char_u *)tmp, + fmt_spec == 'e' ? 'e' : 'E'); + if (tp && (tp[1] == '+' || tp[1] == '-') && tp[2] == '0' + && ascii_isdigit(tp[3]) && ascii_isdigit(tp[4])) { + STRMOVE(tp + 2, tp + 3); + str_arg_l--; + } + } + } + if (zero_padding && min_field_width > str_arg_l + && (tmp[0] == '-' || force_sign)) { + // Padding 0's should be inserted after the sign. + number_of_zeros_to_pad = min_field_width - str_arg_l; + zero_padding_insertion_ind = 1; + } + str_arg = tmp; + break; + } + + default: + // unrecognized conversion specifier, keep format string as-is + zero_padding = 0; // turn zero padding off for non-numeric conversion + justify_left = 1; + min_field_width = 0; // reset flags + + // discard the unrecognized conversion, just keep + // the unrecognized conversion character + str_arg = p; + str_arg_l = 0; + if (*p) { + str_arg_l++; // include invalid conversion specifier + } + // unchanged if not at end-of-string + break; + } + + if (*p) { + p++; // step over the just processed conversion specifier + } + + // insert padding to the left as requested by min_field_width; + // this does not include the zero padding in case of numerical conversions + if (!justify_left) { + assert(str_arg_l <= SIZE_MAX - number_of_zeros_to_pad); + if (min_field_width > str_arg_l + number_of_zeros_to_pad) { + // left padding with blank or zero + size_t pn = min_field_width - (str_arg_l + number_of_zeros_to_pad); + if (str_avail) { + size_t avail = str_m - str_l; + memset(str + str_l, zero_padding ? '0' : ' ', MIN(pn, avail)); + str_avail = pn < avail; + } + assert(pn <= SIZE_MAX - str_l); + str_l += pn; + } + } + + // zero padding as requested by the precision or by the minimal + // field width for numeric conversions required? + if (number_of_zeros_to_pad == 0) { + // will not copy first part of numeric right now, + // force it to be copied later in its entirety + zero_padding_insertion_ind = 0; + } else { + // insert first part of numerics (sign or '0x') before zero padding + if (zero_padding_insertion_ind > 0) { + size_t zn = zero_padding_insertion_ind; + if (str_avail) { + size_t avail = str_m - str_l; + memmove(str + str_l, str_arg, MIN(zn, avail)); + str_avail = zn < avail; + } + assert(zn <= SIZE_MAX - str_l); + str_l += zn; + } + + // insert zero padding as requested by precision or min field width + if (number_of_zeros_to_pad > 0) { + size_t zn = number_of_zeros_to_pad; + if (str_avail) { + size_t avail = str_m - str_l; + memset(str + str_l, '0', MIN(zn, avail)); + str_avail = zn < avail; + } + assert(zn <= SIZE_MAX - str_l); + str_l += zn; + } + } + + // insert formatted string + // (or as-is conversion specifier for unknown conversions) + if (str_arg_l > zero_padding_insertion_ind) { + size_t sn = str_arg_l - zero_padding_insertion_ind; + if (str_avail) { + size_t avail = str_m - str_l; + memmove(str + str_l, + str_arg + zero_padding_insertion_ind, + MIN(sn, avail)); + str_avail = sn < avail; + } + assert(sn <= SIZE_MAX - str_l); + str_l += sn; + } + + // insert right padding + if (justify_left) { + assert(str_arg_l <= SIZE_MAX - number_of_zeros_to_pad); + if (min_field_width > str_arg_l + number_of_zeros_to_pad) { + // right blank padding to the field width + size_t pn = min_field_width - (str_arg_l + number_of_zeros_to_pad); + if (str_avail) { + size_t avail = str_m - str_l; + memset(str + str_l, ' ', MIN(pn, avail)); + str_avail = pn < avail; + } + assert(pn <= SIZE_MAX - str_l); + str_l += pn; + } + } + + xfree(tofree); + } + } + + if (str_m > 0) { + // make sure the string is nul-terminated even at the expense of + // overwriting the last character (shouldn't happen, but just in case) + str[str_l <= str_m - 1 ? str_l : str_m - 1] = '\0'; + } + + if (tvs && tvs[arg_idx - 1].v_type != VAR_UNKNOWN) { + EMSG(_("E767: Too many arguments to printf()")); + } + + // return the number of characters formatted (excluding trailing nul + // character); that is, the number of characters that would have been + // written to the buffer if it were large enough. + return (int)str_l; +} diff --git a/src/nvim/strings.h b/src/nvim/strings.h index 3f0f0c8d6a..59b8701a3f 100644 --- a/src/nvim/strings.h +++ b/src/nvim/strings.h @@ -2,6 +2,10 @@ #define NVIM_STRINGS_H #include <stdbool.h> +#include <stdarg.h> + +#include "nvim/types.h" +#include "nvim/eval/typval.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "strings.h.generated.h" diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c index aded08faee..65c0e2464a 100644 --- a/src/nvim/syntax.c +++ b/src/nvim/syntax.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + /* * syntax.c: code for syntax highlighting */ @@ -42,39 +45,46 @@ static bool did_syntax_onoff = false; -// Structure that stores information about a highlight group. -// The ID of a highlight group is also called group ID. It is the index in -// the highlight_ga array PLUS ONE. +/// Structure that stores information about a highlight group. +/// The ID of a highlight group is also called group ID. It is the index in +/// the highlight_ga array PLUS ONE. struct hl_group { - char_u *sg_name; // highlight group name - char_u *sg_name_u; // uppercase of sg_name - int sg_attr; // Screen attr - int sg_link; // link to this highlight group ID - int sg_set; // combination of SG_* flags - scid_T sg_scriptID; // script in which the group was last set + char_u *sg_name; ///< highlight group name + char_u *sg_name_u; ///< uppercase of sg_name + int sg_attr; ///< Screen attr @see ATTR_ENTRY + int sg_link; ///< link to this highlight group ID + int sg_set; ///< combination of flags in \ref SG_SET + scid_T sg_scriptID; ///< script in which the group was last set // for terminal UIs - int sg_cterm; // "cterm=" highlighting attr - int sg_cterm_fg; // terminal fg color number + 1 - int sg_cterm_bg; // terminal bg color number + 1 - int sg_cterm_bold; // bold attr was set for light color + int sg_cterm; ///< "cterm=" highlighting attr + int sg_cterm_fg; ///< terminal fg color number + 1 + int sg_cterm_bg; ///< terminal bg color number + 1 + int sg_cterm_bold; ///< bold attr was set for light color // for RGB UIs - int sg_gui; // "gui=" highlighting attributes - RgbValue sg_rgb_fg; // RGB foreground color - RgbValue sg_rgb_bg; // RGB background color - RgbValue sg_rgb_sp; // RGB special color - uint8_t *sg_rgb_fg_name; // RGB foreground color name - uint8_t *sg_rgb_bg_name; // RGB background color name - uint8_t *sg_rgb_sp_name; // RGB special color name + int sg_gui; ///< "gui=" highlighting attributes + ///< (combination of \ref HL_ATTRIBUTES) + RgbValue sg_rgb_fg; ///< RGB foreground color + RgbValue sg_rgb_bg; ///< RGB background color + RgbValue sg_rgb_sp; ///< RGB special color + uint8_t *sg_rgb_fg_name; ///< RGB foreground color name + uint8_t *sg_rgb_bg_name; ///< RGB background color name + uint8_t *sg_rgb_sp_name; ///< RGB special color name }; +/// \addtogroup SG_SET +/// @{ #define SG_CTERM 2 // cterm has been set #define SG_GUI 4 // gui has been set #define SG_LINK 8 // link has been set +/// @} // highlight groups for 'highlight' option static garray_T highlight_ga = GA_EMPTY_INIT_VALUE; -#define HL_TABLE() ((struct hl_group *)((highlight_ga.ga_data))) +static inline struct hl_group * HL_TABLE(void) +{ + return ((struct hl_group *)((highlight_ga.ga_data))); +} #define MAX_HL_ID 20000 /* maximum value for a highlight ID. */ @@ -93,10 +103,8 @@ static int include_none = 0; /* when 1 include "nvim/None" */ static int include_default = 0; /* when 1 include "nvim/default" */ static int include_link = 0; /* when 2 include "nvim/link" and "clear" */ -/* - * The "term", "cterm" and "gui" arguments can be any combination of the - * following names, separated by commas (but no spaces!). - */ +/// The "term", "cterm" and "gui" arguments can be any combination of the +/// following names, separated by commas (but no spaces!). static char *(hl_name_table[]) = {"bold", "standout", "underline", "undercurl", "italic", "reverse", "inverse", "NONE"}; @@ -302,6 +310,8 @@ static keyentry_T dumkey; #define HIKEY2KE(p) ((keyentry_T *)((p) - (dumkey.keyword - (char_u *)&dumkey))) #define HI2KE(hi) HIKEY2KE((hi)->hi_key) +// -V:HI2KE:782 + /* * To reduce the time spent in keepend(), remember at which level in the state * stack the first item with "keepend" is present. When "-1", there is no @@ -1406,14 +1416,14 @@ static int syn_stack_equal(synstate_T *sp) /* If the pointer is different it can still be the * same text. Compare the strings, ignore case when * the start item has the sp_ic flag set. */ - if (bsx->matches[j] == NULL - || six->matches[j] == NULL) + if (bsx->matches[j] == NULL || six->matches[j] == NULL) { break; - if ((SYN_ITEMS(syn_block)[CUR_STATE(i).si_idx]).sp_ic - ? mb_stricmp(bsx->matches[j], - six->matches[j]) != 0 - : STRCMP(bsx->matches[j], six->matches[j]) != 0) + } + if (mb_strcmp_ic((SYN_ITEMS(syn_block)[CUR_STATE(i).si_idx]).sp_ic, + (const char *)bsx->matches[j], + (const char *)six->matches[j]) != 0) { break; + } } } if (j != NSUBEXP) @@ -1657,8 +1667,9 @@ syn_current_attr ( * If we found a match after the last column, use it. */ if (next_match_idx >= 0 && next_match_col >= (int)current_col - && next_match_col != MAXCOL) - (void)push_next_match(NULL); + && next_match_col != MAXCOL) { + (void)push_next_match(); + } current_finished = TRUE; current_state_stored = FALSE; @@ -1765,8 +1776,9 @@ syn_current_attr ( cur_si->si_trans_id = CUR_STATE( current_state.ga_len - 2).si_trans_id; } - } else + } else { cur_si->si_attr = syn_id2attr(syn_id); + } cur_si->si_cont_list = NULL; cur_si->si_next_list = next_list; check_keepend(); @@ -1976,9 +1988,10 @@ syn_current_attr ( * endless loop). */ GA_APPEND(int, &zero_width_next_ga, next_match_idx); next_match_idx = -1; - } else - cur_si = push_next_match(cur_si); - found_match = TRUE; + } else { + cur_si = push_next_match(); + } + found_match = true; } } } @@ -2158,9 +2171,10 @@ static int did_match_already(int idx, garray_T *gap) /* * Push the next match onto the stack. */ -static stateitem_T *push_next_match(stateitem_T *cur_si) +static stateitem_T *push_next_match(void) { - synpat_T *spp; + stateitem_T *cur_si; + synpat_T *spp; int save_flags; spp = &(SYN_ITEMS(syn_block)[next_match_idx]); @@ -3259,9 +3273,10 @@ static void syn_cmd_clear(exarg_T *eap, int syncing) syntax_sync_clear(); else { syntax_clear(curwin->w_s); - if (curwin->w_s == &curwin->w_buffer->b_s) - do_unlet((char_u *)"b:current_syntax", TRUE); - do_unlet((char_u *)"w:current_syntax", TRUE); + if (curwin->w_s == &curwin->w_buffer->b_s) { + do_unlet(S_LEN("b:current_syntax"), true); + } + do_unlet(S_LEN("w:current_syntax"), true); } } else { /* @@ -3337,7 +3352,7 @@ static void syn_cmd_enable(exarg_T *eap, int syncing) { set_internal_string_var((char_u *)"syntax_cmd", (char_u *)"enable"); syn_cmd_onoff(eap, "syntax"); - do_unlet((char_u *)"g:syntax_cmd", TRUE); + do_unlet(S_LEN("g:syntax_cmd"), true); } /* @@ -3350,7 +3365,7 @@ static void syn_cmd_reset(exarg_T *eap, int syncing) if (!eap->skip) { set_internal_string_var((char_u *)"syntax_cmd", (char_u *)"reset"); do_cmdline_cmd("runtime! syntax/syncolor.vim"); - do_unlet((char_u *)"g:syntax_cmd", TRUE); + do_unlet(S_LEN("g:syntax_cmd"), true); } } @@ -3377,7 +3392,7 @@ static void syn_cmd_onoff(exarg_T *eap, char *name) eap->nextcmd = check_nextcmd(eap->arg); if (!eap->skip) { char buf[100]; - strncpy(buf, "so ", 4); + memcpy(buf, "so ", 4); vim_snprintf(buf + 3, sizeof(buf) - 3, SYNTAX_FNAME, name); do_cmdline_cmd(buf); } @@ -3576,22 +3591,24 @@ syn_list_one ( } syn_list_flags(namelist1, spp->sp_flags, attr); - if (spp->sp_cont_list != NULL) - put_id_list((char_u *)"contains", spp->sp_cont_list, attr); + if (spp->sp_cont_list != NULL) { + put_id_list("contains", spp->sp_cont_list, attr); + } - if (spp->sp_syn.cont_in_list != NULL) - put_id_list((char_u *)"containedin", - spp->sp_syn.cont_in_list, attr); + if (spp->sp_syn.cont_in_list != NULL) { + put_id_list("containedin", spp->sp_syn.cont_in_list, attr); + } if (spp->sp_next_list != NULL) { - put_id_list((char_u *)"nextgroup", spp->sp_next_list, attr); + put_id_list("nextgroup", spp->sp_next_list, attr); syn_list_flags(namelist2, spp->sp_flags, attr); } if (spp->sp_flags & (HL_SYNC_HERE|HL_SYNC_THERE)) { - if (spp->sp_flags & HL_SYNC_HERE) - msg_puts_attr((char_u *)"grouphere", attr); - else - msg_puts_attr((char_u *)"groupthere", attr); + if (spp->sp_flags & HL_SYNC_HERE) { + msg_puts_attr("grouphere", attr); + } else { + msg_puts_attr("groupthere", attr); + } msg_putchar(' '); if (spp->sp_sync_idx >= 0) msg_outtrans(HL_TABLE()[SYN_ITEMS(curwin->w_s) @@ -3605,7 +3622,7 @@ syn_list_one ( /* list the link, if there is one */ if (HL_TABLE()[id - 1].sg_link && (did_header || link_only) && !got_int) { (void)syn_list_header(did_header, 999, id); - msg_puts_attr((char_u *)"links to", attr); + msg_puts_attr("links to", attr); msg_putchar(' '); msg_outtrans(HL_TABLE()[HL_TABLE()[id - 1].sg_link - 1].sg_name); } @@ -3617,7 +3634,7 @@ static void syn_list_flags(struct name_list *nlist, int flags, int attr) for (i = 0; nlist[i].flag != 0; ++i) if (flags & nlist[i].flag) { - msg_puts_attr((char_u *)nlist[i].name, attr); + msg_puts_attr(nlist[i].name, attr); msg_putchar(' '); } } @@ -3640,15 +3657,16 @@ static void syn_list_cluster(int id) msg_advance(endcol); if (SYN_CLSTR(curwin->w_s)[id].scl_list != NULL) { - put_id_list((char_u *)"cluster", SYN_CLSTR(curwin->w_s)[id].scl_list, - hl_attr(HLF_D)); + put_id_list("cluster", SYN_CLSTR(curwin->w_s)[id].scl_list, hl_attr(HLF_D)); } else { - msg_puts_attr((char_u *)"cluster", hl_attr(HLF_D)); - msg_puts((char_u *)"=NONE"); + msg_puts_attr("cluster", hl_attr(HLF_D)); + msg_puts("=NONE"); } } -static void put_id_list(char_u *name, short *list, int attr) +static void put_id_list(const char *name, + short *list, // NOLINT(runtime/int) + int attr) { short *p; @@ -3656,14 +3674,15 @@ static void put_id_list(char_u *name, short *list, int attr) msg_putchar('='); for (p = list; *p; ++p) { if (*p >= SYNID_ALLBUT && *p < SYNID_TOP) { - if (p[1]) - MSG_PUTS("ALLBUT"); - else - MSG_PUTS("ALL"); + if (p[1]) { + msg_puts("ALLBUT"); + } else { + msg_puts("ALL"); + } } else if (*p >= SYNID_TOP && *p < SYNID_CONTAINED) { - MSG_PUTS("TOP"); + msg_puts("TOP"); } else if (*p >= SYNID_CONTAINED && *p < SYNID_CLUSTER) { - MSG_PUTS("CONTAINED"); + msg_puts("CONTAINED"); } else if (*p >= SYNID_CLUSTER) { short scl_id = *p - SYNID_CLUSTER; @@ -3688,7 +3707,7 @@ static void put_pattern(char *s, int c, synpat_T *spp, int attr) /* May have to write "matchgroup=group" */ if (last_matchgroup != spp->sp_syn_match_id) { last_matchgroup = spp->sp_syn_match_id; - msg_puts_attr((char_u *)"matchgroup", attr); + msg_puts_attr("matchgroup", attr); msg_putchar('='); if (last_matchgroup == 0) msg_outtrans((char_u *)"NONE"); @@ -3697,8 +3716,8 @@ static void put_pattern(char *s, int c, synpat_T *spp, int attr) msg_putchar(' '); } - /* output the name of the pattern and an '=' or ' ' */ - msg_puts_attr((char_u *)s, attr); + // Output the name of the pattern and an '=' or ' '. + msg_puts_attr(s, attr); msg_putchar(c); /* output the pattern, in between a char that is not in the pattern */ @@ -3718,9 +3737,10 @@ static void put_pattern(char *s, int c, synpat_T *spp, int attr) if (!(spp->sp_off_flags & (mask + (mask << SPO_COUNT)))) { continue; } - if (!first) - msg_putchar(','); /* separate with commas */ - msg_puts((char_u *)spo_name_tab[i]); + if (!first) { + msg_putchar(','); // Separate with commas. + } + msg_puts(spo_name_tab[i]); n = spp->sp_offsets[i]; if (i != SPO_LC_OFF) { if (spp->sp_off_flags & mask) @@ -3792,32 +3812,31 @@ syn_list_keywords ( } did_header = TRUE; if (prev_contained != (kp->flags & HL_CONTAINED)) { - msg_puts_attr((char_u *)"contained", attr); + msg_puts_attr("contained", attr); msg_putchar(' '); prev_contained = (kp->flags & HL_CONTAINED); } if (kp->k_syn.cont_in_list != prev_cont_in_list) { - put_id_list((char_u *)"containedin", - kp->k_syn.cont_in_list, attr); + put_id_list("containedin", kp->k_syn.cont_in_list, attr); msg_putchar(' '); prev_cont_in_list = kp->k_syn.cont_in_list; } if (kp->next_list != prev_next_list) { - put_id_list((char_u *)"nextgroup", kp->next_list, attr); + put_id_list("nextgroup", kp->next_list, attr); msg_putchar(' '); prev_next_list = kp->next_list; if (kp->flags & HL_SKIPNL) { - msg_puts_attr((char_u *)"skipnl", attr); + msg_puts_attr("skipnl", attr); msg_putchar(' '); prev_skipnl = (kp->flags & HL_SKIPNL); } if (kp->flags & HL_SKIPWHITE) { - msg_puts_attr((char_u *)"skipwhite", attr); + msg_puts_attr("skipwhite", attr); msg_putchar(' '); prev_skipwhite = (kp->flags & HL_SKIPWHITE); } if (kp->flags & HL_SKIPEMPTY) { - msg_puts_attr((char_u *)"skipempty", attr); + msg_puts_attr("skipempty", attr); msg_putchar(' '); prev_skipempty = (kp->flags & HL_SKIPEMPTY); } @@ -3929,7 +3948,8 @@ static void add_keyword(char_u *name, hash_T hash = hash_hash(kp->keyword); hashtab_T *ht = (curwin->w_s->b_syn_ic) ? &curwin->w_s->b_keywtab_ic : &curwin->w_s->b_keywtab; - hashitem_T *hi = hash_lookup(ht, kp->keyword, hash); + hashitem_T *hi = hash_lookup(ht, (const char *)kp->keyword, + STRLEN(kp->keyword), hash); // even though it looks like only the kp->keyword member is // being used here, vim uses some pointer trickery to get the orignal @@ -4236,83 +4256,81 @@ static void syn_cmd_keyword(exarg_T *eap, int syncing) if (rest != NULL) { syn_id = syn_check_group(arg, (int)(group_name_end - arg)); - if (syn_id != 0) - /* allocate a buffer, for removing backslashes in the keyword */ + if (syn_id != 0) { + // Allocate a buffer, for removing backslashes in the keyword. keyword_copy = xmalloc(STRLEN(rest) + 1); - syn_opt_arg.flags = 0; - syn_opt_arg.keyword = TRUE; - syn_opt_arg.sync_idx = NULL; - syn_opt_arg.has_cont_list = FALSE; - syn_opt_arg.cont_in_list = NULL; - syn_opt_arg.next_list = NULL; - - /* - * The options given apply to ALL keywords, so all options must be - * found before keywords can be created. - * 1: collect the options and copy the keywords to keyword_copy. - */ - cnt = 0; - p = keyword_copy; - for (; rest != NULL && !ends_excmd(*rest); rest = skipwhite(rest)) { - rest = get_syn_options(rest, &syn_opt_arg, &conceal_char); - if (rest == NULL || ends_excmd(*rest)) - break; - /* Copy the keyword, removing backslashes, and add a NUL. */ - while (*rest != NUL && !ascii_iswhite(*rest)) { - if (*rest == '\\' && rest[1] != NUL) - ++rest; - *p++ = *rest++; - } - *p++ = NUL; - ++cnt; } + if (keyword_copy != NULL) { + syn_opt_arg.flags = 0; + syn_opt_arg.keyword = true; + syn_opt_arg.sync_idx = NULL; + syn_opt_arg.has_cont_list = false; + syn_opt_arg.cont_in_list = NULL; + syn_opt_arg.next_list = NULL; + + // The options given apply to ALL keywords, so all options must be + // found before keywords can be created. + // 1: collect the options and copy the keywords to keyword_copy. + cnt = 0; + p = keyword_copy; + for (; rest != NULL && !ends_excmd(*rest); rest = skipwhite(rest)) { + rest = get_syn_options(rest, &syn_opt_arg, &conceal_char); + if (rest == NULL || ends_excmd(*rest)) { + break; + } + // Copy the keyword, removing backslashes, and add a NUL. + while (*rest != NUL && !ascii_iswhite(*rest)) { + if (*rest == '\\' && rest[1] != NUL) { + rest++; + } + *p++ = *rest++; + } + *p++ = NUL; + cnt++; + } - if (!eap->skip) { - /* Adjust flags for use of ":syn include". */ - syn_incl_toplevel(syn_id, &syn_opt_arg.flags); + if (!eap->skip) { + // Adjust flags for use of ":syn include". + syn_incl_toplevel(syn_id, &syn_opt_arg.flags); - /* - * 2: Add an entry for each keyword. - */ - for (kw = keyword_copy; --cnt >= 0; kw += STRLEN(kw) + 1) { - for (p = vim_strchr(kw, '[');; ) { - if (p != NULL) - *p = NUL; - add_keyword(kw, syn_id, syn_opt_arg.flags, - syn_opt_arg.cont_in_list, - syn_opt_arg.next_list, conceal_char); - if (p == NULL) - break; - if (p[1] == NUL) { - EMSG2(_("E789: Missing ']': %s"), kw); - goto error; - } - if (p[1] == ']') { - if (p[2] != NUL) { - EMSG3(_("E890: trailing char after ']': %s]%s"), - kw, &p[2]); + // 2: Add an entry for each keyword. + for (kw = keyword_copy; --cnt >= 0; kw += STRLEN(kw) + 1) { + for (p = vim_strchr(kw, '[');; ) { + if (p != NULL) { + *p = NUL; + } + add_keyword(kw, syn_id, syn_opt_arg.flags, + syn_opt_arg.cont_in_list, + syn_opt_arg.next_list, conceal_char); + if (p == NULL) { + break; + } + if (p[1] == NUL) { + emsgf(_("E789: Missing ']': %s"), kw); goto error; } - kw = p + 1; - break; // skip over the "]" - } - if (has_mbyte) { - int l = (*mb_ptr2len)(p + 1); + if (p[1] == ']') { + if (p[2] != NUL) { + emsgf(_("E890: trailing char after ']': %s]%s"), + kw, &p[2]); + goto error; + } + kw = p + 1; + break; // skip over the "]" + } + const int l = (*mb_ptr2len)(p + 1); memmove(p, p + 1, l); p += l; - } else { - p[0] = p[1]; - ++p; } } } - } error: - xfree(keyword_copy); - xfree(syn_opt_arg.cont_in_list); - xfree(syn_opt_arg.next_list); + xfree(keyword_copy); + xfree(syn_opt_arg.cont_in_list); + xfree(syn_opt_arg.next_list); + } } if (rest != NULL) @@ -5236,12 +5254,10 @@ get_id_list ( /* * Handle full group name. */ - if (vim_strpbrk(name + 1, (char_u *)"\\.*^$~[") == NULL) + if (vim_strpbrk(name + 1, (char_u *)"\\.*^$~[") == NULL) { id = syn_check_group(name + 1, (int)(end - p)); - else { - /* - * Handle match of regexp with group names. - */ + } else { + // Handle match of regexp with group names. *name = '^'; STRCAT(name, "$"); regmatch.regprog = vim_regcomp(name, RE_MAGIC); @@ -5516,24 +5532,26 @@ void ex_ownsyntax(exarg_T *eap) clear_string_option(&curwin->w_s->b_syn_isk); } - /* save value of b:current_syntax */ - old_value = get_var_value((char_u *)"b:current_syntax"); - if (old_value != NULL) + // Save value of b:current_syntax. + old_value = get_var_value("b:current_syntax"); + if (old_value != NULL) { old_value = vim_strsave(old_value); + } /* Apply the "syntax" autocommand event, this finds and loads the syntax * file. */ apply_autocmds(EVENT_SYNTAX, eap->arg, curbuf->b_fname, TRUE, curbuf); - /* move value of b:current_syntax to w:current_syntax */ - new_value = get_var_value((char_u *)"b:current_syntax"); - if (new_value != NULL) + // Move value of b:current_syntax to w:current_syntax. + new_value = get_var_value("b:current_syntax"); + if (new_value != NULL) { set_internal_string_var((char_u *)"w:current_syntax", new_value); + } - /* restore value of b:current_syntax */ - if (old_value == NULL) - do_unlet((char_u *)"b:current_syntax", TRUE); - else { + // Restore value of b:current_syntax. + if (old_value == NULL) { + do_unlet(S_LEN("b:current_syntax"), true); + } else { set_internal_string_var((char_u *)"b:current_syntax", old_value); xfree(old_value); } @@ -5566,43 +5584,42 @@ void reset_expand_highlight(void) * Handle command line completion for :match and :echohl command: Add "None" * as highlight group. */ -void set_context_in_echohl_cmd(expand_T *xp, char_u *arg) +void set_context_in_echohl_cmd(expand_T *xp, const char *arg) { xp->xp_context = EXPAND_HIGHLIGHT; - xp->xp_pattern = arg; + xp->xp_pattern = (char_u *)arg; include_none = 1; } /* * Handle command line completion for :syntax command. */ -void set_context_in_syntax_cmd(expand_T *xp, char_u *arg) +void set_context_in_syntax_cmd(expand_T *xp, const char *arg) { - char_u *p; - - /* Default: expand subcommands */ + // Default: expand subcommands. xp->xp_context = EXPAND_SYNTAX; expand_what = EXP_SUBCMD; - xp->xp_pattern = arg; + xp->xp_pattern = (char_u *)arg; include_link = 0; include_default = 0; /* (part of) subcommand already typed */ if (*arg != NUL) { - p = skiptowhite(arg); - if (*p != NUL) { /* past first word */ - xp->xp_pattern = skipwhite(p); - if (*skiptowhite(xp->xp_pattern) != NUL) + const char *p = (const char *)skiptowhite((const char_u *)arg); + if (*p != NUL) { // Past first word. + xp->xp_pattern = skipwhite((const char_u *)p); + if (*skiptowhite(xp->xp_pattern) != NUL) { xp->xp_context = EXPAND_NOTHING; - else if (STRNICMP(arg, "case", p - arg) == 0) + } else if (STRNICMP(arg, "case", p - arg) == 0) { expand_what = EXP_CASE; - else if ( STRNICMP(arg, "keyword", p - arg) == 0 + } else if (STRNICMP(arg, "keyword", p - arg) == 0 || STRNICMP(arg, "region", p - arg) == 0 || STRNICMP(arg, "match", p - arg) == 0 - || STRNICMP(arg, "list", p - arg) == 0) + || STRNICMP(arg, "list", p - arg) == 0) { xp->xp_context = EXPAND_HIGHLIGHT; - else + } else { xp->xp_context = EXPAND_NOTHING; + } } } } @@ -5889,6 +5906,8 @@ static void syntime_report(void) static char *highlight_init_both[] = { "Conceal ctermbg=DarkGrey ctermfg=LightGrey guibg=DarkGrey guifg=LightGrey", + "Cursor guibg=fg guifg=bg", + "lCursor guibg=fg guifg=bg", "DiffText cterm=bold ctermbg=Red gui=bold guibg=Red", "ErrorMsg ctermbg=DarkRed ctermfg=White guibg=Red guifg=White", "IncSearch cterm=reverse gui=reverse", @@ -5905,6 +5924,7 @@ static char *highlight_init_both[] = "default link EndOfBuffer NonText", "default link QuickFixLine Search", "default link Substitute Search", + "default link Whitespace NonText", NULL }; @@ -5938,6 +5958,7 @@ static char *highlight_init_light[] = "Title ctermfg=DarkMagenta gui=bold guifg=Magenta", "Visual guibg=LightGrey", "WarningMsg ctermfg=DarkRed guifg=Red", + "Normal gui=NONE", NULL }; @@ -5971,24 +5992,26 @@ static char *highlight_init_dark[] = "Title ctermfg=LightMagenta gui=bold guifg=Magenta", "Visual guibg=DarkGrey", "WarningMsg ctermfg=LightRed guifg=Red", + "Normal gui=NONE", NULL }; -void -init_highlight ( - int both, /* include groups where 'bg' doesn't matter */ - int reset /* clear group first */ -) + +/// Load colors from a file if "g:colors_name" is set, otherwise load builtin +/// colors +/// +/// @param both include groups where 'bg' doesn't matter +/// @param reset clear groups first +void +init_highlight(int both, int reset) { int i; char **pp; static int had_both = FALSE; - /* - * Try finding the color scheme file. Used when a color file was loaded - * and 'background' or 't_Co' is changed. - */ - char_u *p = get_var_value((char_u *)"g:colors_name"); + // Try finding the color scheme file. Used when a color file was loaded + // and 'background' or 't_Co' is changed. + char_u *p = get_var_value("g:colors_name"); if (p != NULL) { // Value of g:colors_name could be freed in load_colors() and make // p invalid, so copy it. @@ -6006,33 +6029,34 @@ init_highlight ( if (both) { had_both = TRUE; pp = highlight_init_both; - for (i = 0; pp[i] != NULL; ++i) - do_highlight((char_u *)pp[i], reset, TRUE); - } else if (!had_both) - /* Don't do anything before the call with both == TRUE from main(). - * Not everything has been setup then, and that call will overrule - * everything anyway. */ + for (i = 0; pp[i] != NULL; i++) { + do_highlight((char_u *)pp[i], reset, true); + } + } else if (!had_both) { + // Don't do anything before the call with both == TRUE from main(). + // Not everything has been setup then, and that call will overrule + // everything anyway. return; + } - if (*p_bg == 'l') - pp = highlight_init_light; - else - pp = highlight_init_dark; - for (i = 0; pp[i] != NULL; ++i) - do_highlight((char_u *)pp[i], reset, TRUE); + pp = (*p_bg == 'l') ? highlight_init_light : highlight_init_dark; + + for (i = 0; pp[i] != NULL; i++) { + do_highlight((char_u *)pp[i], reset, true); + } /* Reverse looks ugly, but grey may not work for 8 colors. Thus let it * depend on the number of colors available. * With 8 colors brown is equal to yellow, need to use black for Search fg * to avoid Statement highlighted text disappears. * Clear the attributes, needed when changing the t_Co value. */ - if (t_colors > 8) + if (t_colors > 8) { do_highlight( (char_u *)(*p_bg == 'l' ? "Visual cterm=NONE ctermbg=LightGrey" - : "Visual cterm=NONE ctermbg=DarkGrey"), FALSE, - TRUE); - else { + : "Visual cterm=NONE ctermbg=DarkGrey"), false, + true); + } else { do_highlight((char_u *)"Visual cterm=reverse ctermbg=NONE", FALSE, TRUE); if (*p_bg == 'l') @@ -6042,7 +6066,7 @@ init_highlight ( /* * If syntax highlighting is enabled load the highlighting for it. */ - if (get_var_value((char_u *)"g:syntax_on") != NULL) { + if (get_var_value("g:syntax_on") != NULL) { static int recursive = 0; if (recursive >= 5) { @@ -6086,18 +6110,13 @@ int load_colors(char_u *name) return retval; } -/* - * Handle the ":highlight .." command. - * When using ":hi clear" this is called recursively for each group with - * "forceit" and "init" both TRUE. - */ -void -do_highlight ( - char_u *line, - int forceit, - int init /* TRUE when called for initializing */ -) -{ + +/// Handle the ":highlight .." command. +/// When using ":hi clear" this is called recursively for each group with +/// "forceit" and "init" both TRUE. +/// @param init TRUE when called for initializing +void +do_highlight(char_u *line, int forceit, int init) { char_u *name_end; char_u *linep; char_u *key_start; @@ -6114,15 +6133,16 @@ do_highlight ( int dolink = FALSE; int error = FALSE; int color; - int is_normal_group = FALSE; /* "Normal" group */ + bool is_normal_group = false; // "Normal" group /* * If no argument, list current highlighting. */ if (ends_excmd(*line)) { - for (int i = 1; i <= highlight_ga.ga_len && !got_int; ++i) - /* TODO: only call when the group has attributes set */ + for (int i = 1; i <= highlight_ga.ga_len && !got_int; i++) { + // todo(vim): only call when the group has attributes set highlight_list_one(i); + } return; } @@ -6224,7 +6244,7 @@ do_highlight ( */ line = linep; if (ends_excmd(*line)) { - do_unlet((char_u *)"colors_name", TRUE); + do_unlet(S_LEN("colors_name"), true); restore_cterm_colors(); /* @@ -6250,12 +6270,12 @@ do_highlight ( return; idx = id - 1; /* index is ID minus one */ - /* Return if "default" was used and the group already has settings. */ - if (dodefault && hl_has_settings(idx, TRUE)) + // Return if "default" was used and the group already has settings + if (dodefault && hl_has_settings(idx, true)) { return; + } - if (STRCMP(HL_TABLE()[idx].sg_name_u, "NORMAL") == 0) - is_normal_group = TRUE; + is_normal_group = (STRCMP(HL_TABLE()[idx].sg_name_u, "NORMAL") == 0); /* Clear the highlighting for ":hi clear {group}" and ":hi clear". */ if (doclear || (forceit && init)) { @@ -6264,7 +6284,7 @@ do_highlight ( HL_TABLE()[idx].sg_set = 0; } - if (!doclear) + if (!doclear) { while (!ends_excmd(*linep)) { key_start = linep; if (*linep == '=') { @@ -6370,12 +6390,12 @@ do_highlight ( } } } else if (STRCMP(key, "FONT") == 0) { - /* in non-GUI fonts are simply ignored */ - } else if (STRCMP(key, - "CTERMFG") == 0 || STRCMP(key, "CTERMBG") == 0) { + // in non-GUI fonts are simply ignored + } else if (STRCMP(key, "CTERMFG") == 0 || STRCMP(key, "CTERMBG") == 0) { if (!init || !(HL_TABLE()[idx].sg_set & SG_CTERM)) { - if (!init) + if (!init) { HL_TABLE()[idx].sg_set |= SG_CTERM; + } /* When setting the foreground color, and previously the "bold" * flag was set for a light color, reset it now */ @@ -6469,9 +6489,10 @@ do_highlight ( * colors (on some terminals, e.g. "linux") */ if (color & 8) { HL_TABLE()[idx].sg_cterm |= HL_BOLD; - HL_TABLE()[idx].sg_cterm_bold = TRUE; - } else + HL_TABLE()[idx].sg_cterm_bold = true; + } else { HL_TABLE()[idx].sg_cterm &= ~HL_BOLD; + } } color &= 7; // truncate to 8 colors } else if (t_colors == 16 || t_colors == 88 || t_colors >= 256) { @@ -6503,16 +6524,16 @@ do_highlight ( if (!ui_rgb_attached()) { must_redraw = CLEAR; if (color >= 0) { - if (t_colors < 16) + if (t_colors < 16) { i = (color == 0 || color == 4); - else + } else { i = (color < 7 || color == 8); - /* Set the 'background' option if the value is - * wrong. */ - if (i != (*p_bg == 'd')) - set_option_value((char_u *)"bg", 0L, - i ? (char_u *)"dark" - : (char_u *)"light", 0); + } + // Set the 'background' option if the value is + // wrong. + if (i != (*p_bg == 'd')) { + set_option_value("bg", 0L, (i ? "dark" : "light"), 0); + } } } } @@ -6583,21 +6604,23 @@ do_highlight ( /* * When highlighting has been given for a group, don't link it. */ - if (!init || !(HL_TABLE()[idx].sg_set & SG_LINK)) + if (!init || !(HL_TABLE()[idx].sg_set & SG_LINK)) { HL_TABLE()[idx].sg_link = 0; + } /* * Continue with next argument. */ linep = skipwhite(linep); } + } /* * If there is an error, and it's a new entry, remove it from the table. */ - if (error && idx == highlight_ga.ga_len) + if (error && idx == highlight_ga.ga_len) { syn_unadd_group(); - else { + } else { if (is_normal_group) { HL_TABLE()[idx].sg_attr = 0; // Need to update all groups, because they might be using "bg" and/or @@ -6605,16 +6628,17 @@ do_highlight ( highlight_attr_set_all(); // If the normal group has changed, it is simpler to refresh every UI ui_refresh(); - } else + } else { set_hl_attr(idx); + } HL_TABLE()[idx].sg_scriptID = current_SID; redraw_all_later(NOT_VALID); } xfree(key); xfree(arg); - /* Only call highlight_changed() once, after sourcing a syntax file */ - need_highlight_changed = TRUE; + // Only call highlight_changed() once, after sourcing a syntax file + need_highlight_changed = true; } #if defined(EXITFREE) @@ -6687,22 +6711,21 @@ static void highlight_clear(int idx) } -/* - * Table with the specifications for an attribute number. - * Note that this table is used by ALL buffers. This is required because the - * GUI can redraw at any time for any buffer. - */ +/// Table with the specifications for an attribute number. +/// Note that this table is used by ALL buffers. This is required because the +/// GUI can redraw at any time for any buffer. static garray_T attr_table = GA_EMPTY_INIT_VALUE; -#define ATTR_ENTRY(idx) ((attrentry_T *)attr_table.ga_data)[idx] +static inline attrentry_T * ATTR_ENTRY(int idx) +{ + return &((attrentry_T *)attr_table.ga_data)[idx]; +} -/* - * Return the attr number for a set of colors and font. - * Add a new entry to the term_attr_table, attr_table or gui_attr_table - * if the combination is new. - * Return 0 for error. - */ +/// Return the attr number for a set of colors and font. +/// Add a new entry to the term_attr_table, attr_table or gui_attr_table +/// if the combination is new. +/// @return 0 for error. int get_attr_entry(attrentry_T *aep) { garray_T *table = &attr_table; @@ -6786,7 +6809,7 @@ int hl_combine_attr(int char_attr, int prim_attr) { attrentry_T *char_aep = NULL; attrentry_T *spell_aep; - attrentry_T new_en; + attrentry_T new_en = ATTRENTRY_INIT; if (char_attr == 0) { return prim_attr; @@ -6834,17 +6857,24 @@ int hl_combine_attr(int char_attr, int prim_attr) return get_attr_entry(&new_en); } +/// \note this function does not apply exclusively to cterm attr contrary +/// to what its name implies attrentry_T *syn_cterm_attr2entry(int attr) { attr -= ATTR_OFF; - if (attr >= attr_table.ga_len) /* did ":syntax clear" */ + if (attr >= attr_table.ga_len) { + // did ":syntax clear" return NULL; - return &(ATTR_ENTRY(attr)); + } + return ATTR_ENTRY(attr); } +/// \addtogroup LIST_XXX +/// @{ #define LIST_ATTR 1 #define LIST_STRING 2 #define LIST_INT 3 +/// @} static void highlight_list_one(int id) { @@ -6871,8 +6901,8 @@ static void highlight_list_one(int id) if (sgp->sg_link && !got_int) { (void)syn_list_header(didh, 9999, id); - didh = TRUE; - msg_puts_attr((char_u *)"links to", hl_attr(HLF_D)); + didh = true; + msg_puts_attr("links to", hl_attr(HLF_D)); msg_putchar(' '); msg_outtrans(HL_TABLE()[HL_TABLE()[id - 1].sg_link - 1].sg_name); } @@ -6883,7 +6913,13 @@ static void highlight_list_one(int id) last_set_msg(sgp->sg_scriptID); } -static int highlight_list_arg(int id, int didh, int type, int iarg, char_u *sarg, char *name) +/// Outputs a highlight when doing ":hi MyHighlight" +/// +/// @param type one of \ref LIST_XXX +/// @param iarg integer argument used if \p type == LIST_INT +/// @param sarg string used if \p type == LIST_STRING +static int highlight_list_arg(int id, int didh, int type, int iarg, + char_u *sarg, const char *name) { char_u buf[100]; char_u *ts; @@ -6902,8 +6938,8 @@ static int highlight_list_arg(int id, int didh, int type, int iarg, char_u *sarg for (i = 0; hl_attr_table[i] != 0; ++i) { if (iarg & hl_attr_table[i]) { if (buf[0] != NUL) - vim_strcat(buf, (char_u *)",", 100); - vim_strcat(buf, (char_u *)hl_name_table[i], 100); + xstrlcat((char *)buf, ",", 100); + xstrlcat((char *)buf, hl_name_table[i], 100); iarg &= ~hl_attr_table[i]; /* don't want "inverse" */ } } @@ -6923,21 +6959,21 @@ static int highlight_list_arg(int id, int didh, int type, int iarg, char_u *sarg return didh; } -/* - * Return "1" if highlight group "id" has attribute "flag". - * Return NULL otherwise. - */ -char_u * -highlight_has_attr ( - int id, - int flag, - int modec // 'g' for GUI, 'c' for cterm -) +/// Check whether highlight group has attribute +/// +/// @param[in] id Highlight group to check. +/// @param[in] flag Attribute to check. +/// @param[in] modec 'g' for GUI, 'c' for term. +/// +/// @return "1" if highlight group has attribute, NULL otherwise. +const char *highlight_has_attr(const int id, const int flag, const int modec) + FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE { int attr; - if (id <= 0 || id > highlight_ga.ga_len) + if (id <= 0 || id > highlight_ga.ga_len) { return NULL; + } if (modec == 'g') { attr = HL_TABLE()[id - 1].sg_gui; @@ -6945,39 +6981,42 @@ highlight_has_attr ( attr = HL_TABLE()[id - 1].sg_cterm; } - if (attr & flag) - return (char_u *)"1"; - return NULL; + return (attr & flag) ? "1" : NULL; } -/* - * Return color name of highlight group "id". - */ -char_u * -highlight_color ( - int id, - char_u *what, /* "font", "fg", "bg", "sp", "fg#", "bg#" or "sp#" */ - int modec /* 'g' for GUI, 'c' for cterm, 't' for term */ -) +/// Return color name of the given highlight group +/// +/// @param[in] id Highlight group to work with. +/// @param[in] what What to return: one of "font", "fg", "bg", "sp", "fg#", +/// "bg#" or "sp#". +/// @param[in] modec 'g' for GUI, 'c' for cterm and 't' for term. +/// +/// @return color name, possibly in a static buffer. Buffer will be overwritten +/// on next highlight_color() call. May return NULL. +const char *highlight_color(const int id, const char *const what, + const int modec) + FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL { - static char_u name[20]; + static char name[20]; int n; - int fg = FALSE; - int sp = FALSE; - int font = FALSE; + bool fg = false; + bool sp = false; + bool font = false; - if (id <= 0 || id > highlight_ga.ga_len) + if (id <= 0 || id > highlight_ga.ga_len) { return NULL; + } - if (TOLOWER_ASC(what[0]) == 'f' && TOLOWER_ASC(what[1]) == 'g') - fg = TRUE; - else if (TOLOWER_ASC(what[0]) == 'f' && TOLOWER_ASC(what[1]) == 'o' - && TOLOWER_ASC(what[2]) == 'n' && TOLOWER_ASC(what[3]) == 't') - font = TRUE; - else if (TOLOWER_ASC(what[0]) == 's' && TOLOWER_ASC(what[1]) == 'p') - sp = TRUE; - else if (!(TOLOWER_ASC(what[0]) == 'b' && TOLOWER_ASC(what[1]) == 'g')) + if (TOLOWER_ASC(what[0]) == 'f' && TOLOWER_ASC(what[1]) == 'g') { + fg = true; + } else if (TOLOWER_ASC(what[0]) == 'f' && TOLOWER_ASC(what[1]) == 'o' + && TOLOWER_ASC(what[2]) == 'n' && TOLOWER_ASC(what[3]) == 't') { + font = true; + } else if (TOLOWER_ASC(what[0]) == 's' && TOLOWER_ASC(what[1]) == 'p') { + sp = true; + } else if (!(TOLOWER_ASC(what[0]) == 'b' && TOLOWER_ASC(what[1]) == 'g')) { return NULL; + } if (modec == 'g') { if (what[2] == '#' && ui_rgb_attached()) { if (fg) { @@ -6990,19 +7029,20 @@ highlight_color ( if (n < 0 || n > 0xffffff) { return NULL; } - snprintf((char *)name, sizeof(name), "#%06x", n); + snprintf(name, sizeof(name), "#%06x", n); return name; } if (fg) { - return HL_TABLE()[id - 1].sg_rgb_fg_name; + return (const char *)HL_TABLE()[id - 1].sg_rgb_fg_name; } if (sp) { - return HL_TABLE()[id - 1].sg_rgb_sp_name; + return (const char *)HL_TABLE()[id - 1].sg_rgb_sp_name; } - return HL_TABLE()[id - 1].sg_rgb_bg_name; + return (const char *)HL_TABLE()[id - 1].sg_rgb_bg_name; } - if (font || sp) + if (font || sp) { return NULL; + } if (modec == 'c') { if (fg) { n = HL_TABLE()[id - 1].sg_cterm_fg - 1; @@ -7012,31 +7052,30 @@ highlight_color ( if (n < 0) { return NULL; } - snprintf((char *)name, sizeof(name), "%d", n); + snprintf(name, sizeof(name), "%d", n); return name; } - /* term doesn't have color */ + // term doesn't have color. return NULL; } -/* - * Output the syntax list header. - * Return TRUE when started a new line. - */ -static int -syn_list_header ( - int did_header, /* did header already */ - int outlen, /* length of string that comes */ - int id /* highlight group id */ -) +/// Output the syntax list header. +/// +/// @param did_header did header already +/// @param outlen length of string that comes +/// @param id highlight group id +/// @return true when started a new line. +static int +syn_list_header(int did_header, int outlen, int id) { int endcol = 19; int newline = TRUE; if (!did_header) { msg_putchar('\n'); - if (got_int) - return TRUE; + if (got_int) { + return true; + } msg_outtrans(HL_TABLE()[id - 1].sg_name); endcol = 15; } else if (msg_col + outlen + 1 >= Columns) { @@ -7057,7 +7096,7 @@ syn_list_header ( /* Show "xxx" with the attributes. */ if (!did_header) { - msg_puts_attr((char_u *)"xxx", syn_id2attr(id)); + msg_puts_attr("xxx", syn_id2attr(id)); msg_putchar(' '); } @@ -7073,12 +7112,13 @@ set_hl_attr ( int idx /* index in array */ ) { - attrentry_T at_en; + attrentry_T at_en = ATTRENTRY_INIT; struct hl_group *sgp = HL_TABLE() + idx; - /* The "Normal" group doesn't need an attribute number */ - if (sgp->sg_name_u != NULL && STRCMP(sgp->sg_name_u, "NORMAL") == 0) + // The "Normal" group doesn't need an attribute number + if (sgp->sg_name_u != NULL && STRCMP(sgp->sg_name_u, "NORMAL") == 0) { return; + } at_en.cterm_ae_attr = sgp->sg_cterm; at_en.cterm_fg_color = sgp->sg_cterm_fg; @@ -7102,11 +7142,11 @@ set_hl_attr ( } } -/* - * Lookup a highlight group name and return it's ID. - * If it is not found, 0 is returned. - */ -int syn_name2id(char_u *name) +/// Lookup a highlight group name and return its ID. +/// +/// @param highlight name e.g. 'Cursor', 'Normal' +/// @return the highlight id, else 0 if \p name does not exist +int syn_name2id(const char_u *name) { int i; char_u name_u[200]; @@ -7126,7 +7166,7 @@ int syn_name2id(char_u *name) /* * Return TRUE if highlight group "name" exists. */ -int highlight_exists(char_u *name) +int highlight_exists(const char_u *name) { return syn_name2id(name) > 0; } @@ -7154,12 +7194,13 @@ int syn_namen2id(char_u *linep, int len) return id; } -/* - * Find highlight group name in the table and return it's ID. - * The argument is a pointer to the name and the length of the name. - * If it doesn't exist yet, a new entry is created. - * Return 0 for failure. - */ +/// Find highlight group name in the table and return its ID. +/// If it doesn't exist yet, a new entry is created. +/// +/// @param pp Highlight group name +/// @param len length of \p pp +/// +/// @return 0 for failure else the id of the group int syn_check_group(char_u *pp, int len) { char_u *name = vim_strnsave(pp, len); @@ -7172,11 +7213,11 @@ int syn_check_group(char_u *pp, int len) return id; } -/* - * Add new highlight group and return it's ID. - * "name" must be an allocated string, it will be consumed. - * Return 0 for failure. - */ +/// Add new highlight group and return it's ID. +/// +/// @param name must be an allocated string, it will be consumed. +/// @return 0 for failure, else the allocated group id +/// @see syn_check_group syn_unadd_group static int syn_add_group(char_u *name) { char_u *p; @@ -7214,25 +7255,26 @@ static int syn_add_group(char_u *name) struct hl_group* hlgp = GA_APPEND_VIA_PTR(struct hl_group, &highlight_ga); memset(hlgp, 0, sizeof(*hlgp)); hlgp->sg_name = name; + hlgp->sg_rgb_bg = -1; + hlgp->sg_rgb_fg = -1; + hlgp->sg_rgb_sp = -1; hlgp->sg_name_u = vim_strsave_up(name); return highlight_ga.ga_len; /* ID is index plus one */ } -/* - * When, just after calling syn_add_group(), an error is discovered, this - * function deletes the new name. - */ +/// When, just after calling syn_add_group(), an error is discovered, this +/// function deletes the new name. static void syn_unadd_group(void) { - --highlight_ga.ga_len; + highlight_ga.ga_len--; xfree(HL_TABLE()[highlight_ga.ga_len].sg_name); xfree(HL_TABLE()[highlight_ga.ga_len].sg_name_u); } -/* - * Translate a group ID to highlight attributes. - */ + +/// Translate a group ID to highlight attributes. +/// @see syn_cterm_attr2entry int syn_id2attr(int hl_id) { struct hl_group *sgp; @@ -7286,110 +7328,34 @@ static void highlight_attr_set_all(void) } } -/* - * Translate the 'highlight' option into attributes in highlight_attr[] and - * set up the user highlights User1..9. A set of - * corresponding highlights to use on top of HLF_SNC is computed. - * Called only when the 'highlight' option has been changed and upon first - * screen redraw after any :highlight command. - * Return FAIL when an invalid flag is found in 'highlight'. OK otherwise. - */ -int highlight_changed(void) +/// Tranlate highlight groups into attributes in highlight_attr[] and set up +/// the user highlights User1..9. A set of corresponding highlights to use on +/// top of HLF_SNC is computed. Called only when nvim starts and upon first +/// screen redraw after any :highlight command. +void highlight_changed(void) { - int hlf; - int i; - char_u *p; int attr; - char_u *end; int id; char_u userhl[10]; int id_SNC = -1; int id_S = -1; int hlcnt; - static int hl_flags[HLF_COUNT] = HL_FLAGS; need_highlight_changed = FALSE; - /* - * Clear all attributes. - */ - for (hlf = 0; hlf < (int)HLF_COUNT; ++hlf) - highlight_attr[hlf] = 0; - - /* - * First set all attributes to their default value. - * Then use the attributes from the 'highlight' option. - */ - for (i = 0; i < 2; ++i) { - if (i) - p = p_hl; - else - p = get_highlight_default(); - if (p == NULL) /* just in case */ - continue; - - while (*p) { - for (hlf = 0; hlf < (int)HLF_COUNT; ++hlf) - if (hl_flags[hlf] == *p) - break; - ++p; - if (hlf == (int)HLF_COUNT || *p == NUL) - return FAIL; - - /* - * Allow several hl_flags to be combined, like "bu" for - * bold-underlined. - */ - attr = 0; - bool colon = false; - for (; *p && *p != ','; ++p) { // parse upto comma - if (ascii_iswhite(*p)) { // ignore white space - continue; - } - - if (colon) /* Combination with ':' is not allowed. */ - return FAIL; - - switch (*p) { - case 'b': attr |= HL_BOLD; - break; - case 'i': attr |= HL_ITALIC; - break; - case '-': - case 'n': /* no highlighting */ - break; - case 'r': attr |= HL_INVERSE; - break; - case 's': attr |= HL_STANDOUT; - break; - case 'u': attr |= HL_UNDERLINE; - break; - case 'c': attr |= HL_UNDERCURL; - break; - case ':': ++p; /* highlight group name */ - if (attr || *p == NUL) /* no combinations */ - return FAIL; - colon = true; - end = vim_strchr(p, ','); - if (end == NULL) - end = p + STRLEN(p); - id = syn_check_group(p, (int)(end - p)); - if (id == 0) - return FAIL; - attr = syn_id2attr(id); - p = end - 1; - if (hlf == (int)HLF_SNC) - id_SNC = syn_get_final_id(id); - else if (hlf == (int)HLF_S) - id_S = syn_get_final_id(id); - break; - default: return FAIL; - } - } - highlight_attr[hlf] = attr; - - p = skip_to_option_part(p); /* skip comma and spaces */ + /// Translate builtin highlight groups into attributes for quick lookup. + for (int hlf = 0; hlf < (int)HLF_COUNT; hlf++) { + id = syn_check_group((char_u *)hlf_names[hlf], STRLEN(hlf_names[hlf])); + if (id == 0) { + abort(); + } + attr = syn_id2attr(id); + if (hlf == (int)HLF_SNC) { + id_SNC = syn_get_final_id(id); + } else if (hlf == (int)HLF_S) { + id_S = syn_get_final_id(id); } + highlight_attr[hlf] = attr; } /* Setup the user highlights @@ -7454,49 +7420,47 @@ int highlight_changed(void) } } highlight_ga.ga_len = hlcnt; - - return OK; } /* * Handle command line completion for :highlight command. */ -void set_context_in_highlight_cmd(expand_T *xp, char_u *arg) +void set_context_in_highlight_cmd(expand_T *xp, const char *arg) { - char_u *p; - - /* Default: expand group names */ + // Default: expand group names. xp->xp_context = EXPAND_HIGHLIGHT; - xp->xp_pattern = arg; + xp->xp_pattern = (char_u *)arg; include_link = 2; include_default = 1; /* (part of) subcommand already typed */ if (*arg != NUL) { - p = skiptowhite(arg); - if (*p != NUL) { /* past "default" or group name */ + const char *p = (const char *)skiptowhite((const char_u *)arg); + if (*p != NUL) { // Past "default" or group name. include_default = 0; - if (STRNCMP("default", arg, p - arg) == 0) { - arg = skipwhite(p); - xp->xp_pattern = arg; - p = skiptowhite(arg); + if (strncmp("default", arg, p - arg) == 0) { + arg = (const char *)skipwhite((const char_u *)p); + xp->xp_pattern = (char_u *)arg; + p = (const char *)skiptowhite((const char_u *)arg); } if (*p != NUL) { /* past group name */ include_link = 0; - if (arg[1] == 'i' && arg[0] == 'N') + if (arg[1] == 'i' && arg[0] == 'N') { highlight_list(); - if (STRNCMP("link", arg, p - arg) == 0 - || STRNCMP("clear", arg, p - arg) == 0) { - xp->xp_pattern = skipwhite(p); - p = skiptowhite(xp->xp_pattern); - if (*p != NUL) { /* past first group name */ - xp->xp_pattern = skipwhite(p); - p = skiptowhite(xp->xp_pattern); + } + if (strncmp("link", arg, p - arg) == 0 + || strncmp("clear", arg, p - arg) == 0) { + xp->xp_pattern = skipwhite((const char_u *)p); + p = (const char *)skiptowhite(xp->xp_pattern); + if (*p != NUL) { // Past first group name. + xp->xp_pattern = skipwhite((const char_u *)p); + p = (const char *)skiptowhite(xp->xp_pattern); } } - if (*p != NUL) /* past group name(s) */ + if (*p != NUL) { // Past group name(s). xp->xp_context = EXPAND_NOTHING; + } } } } @@ -7517,7 +7481,7 @@ static void highlight_list(void) static void highlight_list_two(int cnt, int attr) { - msg_puts_attr((char_u *)&("N \bI \b! \b"[cnt / 11]), attr); + msg_puts_attr(&("N \bI \b! \b"[cnt / 11]), attr); msg_clr_eos(); ui_flush(); os_delay(cnt == 99 ? 40L : (long)cnt * 50L, false); @@ -7528,22 +7492,25 @@ static void highlight_list_two(int cnt, int attr) * Function given to ExpandGeneric() to obtain the list of group names. * Also used for synIDattr() function. */ -char_u *get_highlight_name(expand_T *xp, int idx) -{ - //TODO: 'xp' is unused - if (idx == highlight_ga.ga_len && include_none != 0) - return (char_u *)"none"; - if (idx == highlight_ga.ga_len + include_none && include_default != 0) - return (char_u *)"default"; - if (idx == highlight_ga.ga_len + include_none + include_default - && include_link != 0) - return (char_u *)"link"; - if (idx == highlight_ga.ga_len + include_none + include_default + 1 - && include_link != 0) - return (char_u *)"clear"; - if (idx < 0 || idx >= highlight_ga.ga_len) +const char *get_highlight_name(expand_T *const xp, const int idx) + FUNC_ATTR_WARN_UNUSED_RESULT +{ + // TODO(justinmk): 'xp' is unused + if (idx == highlight_ga.ga_len && include_none != 0) { + return "none"; + } else if (idx == highlight_ga.ga_len + include_none + && include_default != 0) { + return "default"; + } else if (idx == highlight_ga.ga_len + include_none + include_default + && include_link != 0) { + return "link"; + } else if (idx == highlight_ga.ga_len + include_none + include_default + 1 + && include_link != 0) { + return "clear"; + } else if (idx < 0 || idx >= highlight_ga.ga_len) { return NULL; - return HL_TABLE()[idx].sg_name; + } + return (const char *)HL_TABLE()[idx].sg_name; } color_name_table_T color_name_table[] = { @@ -8230,7 +8197,14 @@ color_name_table_T color_name_table[] = { { NULL, 0 }, }; -RgbValue name_to_color(uint8_t *name) + +/// Translate to RgbValue if \p name is an hex value (e.g. #XXXXXX), +/// else look into color_name_table to translate a color name to its +/// hex value +/// +/// @param[in] name string value to convert to RGB +/// return the hex value or -1 if could not find a correct value +RgbValue name_to_color(const uint8_t *name) { if (name[0] == '#' && isxdigit(name[1]) && isxdigit(name[2]) diff --git a/src/nvim/syntax.h b/src/nvim/syntax.h index af2ac719c6..bb733ead30 100644 --- a/src/nvim/syntax.h +++ b/src/nvim/syntax.h @@ -4,11 +4,12 @@ #include <stdbool.h> #include "nvim/buffer_defs.h" +#include "nvim/ex_cmds_defs.h" -/* - * Terminal highlighting attribute bits. - * Attributes above HL_ALL are used for syntax highlighting. - */ +/// Terminal highlighting attribute bits. +/// Attributes above HL_ALL are used for syntax highlighting. +/// \addtogroup HL_ATTRIBUTES +/// @{ #define HL_NORMAL 0x00 #define HL_INVERSE 0x01 #define HL_BOLD 0x02 @@ -16,6 +17,7 @@ #define HL_UNDERLINE 0x08 #define HL_UNDERCURL 0x10 #define HL_STANDOUT 0x20 +/// @} #define HL_CONTAINED 0x01 /* not used on toplevel */ #define HL_TRANSP 0x02 /* has no highlighting */ diff --git a/src/nvim/syntax_defs.h b/src/nvim/syntax_defs.h index 8d207e6286..56fadbe7f6 100644 --- a/src/nvim/syntax_defs.h +++ b/src/nvim/syntax_defs.h @@ -1,10 +1,9 @@ #ifndef NVIM_SYNTAX_DEFS_H #define NVIM_SYNTAX_DEFS_H +#include "nvim/highlight_defs.h" #include "nvim/regexp_defs.h" -typedef int32_t RgbValue; - # define SST_MIN_ENTRIES 150 /* minimal size for state stack array */ # define SST_MAX_ENTRIES 1000 /* maximal size for state stack array */ # define SST_FIX_STATES 7 /* size of sst_stack[]. */ @@ -74,4 +73,14 @@ typedef struct attr_entry { int cterm_fg_color, cterm_bg_color; } attrentry_T; +#define ATTRENTRY_INIT { \ + .rgb_ae_attr = 0, \ + .cterm_ae_attr = 0, \ + .rgb_fg_color = -1, \ + .rgb_bg_color = -1, \ + .rgb_sp_color = -1, \ + .cterm_fg_color = 0, \ + .cterm_bg_color = 0, \ +} + #endif // NVIM_SYNTAX_DEFS_H diff --git a/src/nvim/tag.c b/src/nvim/tag.c index 0b76e36a6b..be9d621c7d 100644 --- a/src/nvim/tag.c +++ b/src/nvim/tag.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + /* * Code to handle tags and the tag stack */ @@ -72,23 +75,18 @@ typedef struct { regmatch_T regmatch; /* regexp program, may be NULL */ } pat_T; -/* - * The matching tags are first stored in ga_match[]. In which one depends on - * the priority of the match. - * At the end, the matches from ga_match[] are concatenated, to make a list - * sorted on priority. - */ -#define MT_ST_CUR 0 /* static match in current file */ -#define MT_GL_CUR 1 /* global match in current file */ -#define MT_GL_OTH 2 /* global match in other file */ -#define MT_ST_OTH 3 /* static match in other file */ -#define MT_IC_ST_CUR 4 /* icase static match in current file */ -#define MT_IC_GL_CUR 5 /* icase global match in current file */ -#define MT_IC_GL_OTH 6 /* icase global match in other file */ -#define MT_IC_ST_OTH 7 /* icase static match in other file */ -#define MT_IC_OFF 4 /* add for icase match */ -#define MT_RE_OFF 8 /* add for regexp match */ -#define MT_MASK 7 /* mask for printing priority */ +// The matching tags are first stored in one of the hash tables. In +// which one depends on the priority of the match. +// ht_match[] is used to find duplicates, ga_match[] to keep them in sequence. +// At the end, the matches from ga_match[] are concatenated, to make a list +// sorted on priority. +#define MT_ST_CUR 0 // static match in current file +#define MT_GL_CUR 1 // global match in current file +#define MT_GL_OTH 2 // global match in other file +#define MT_ST_OTH 3 // static match in other file +#define MT_IC_OFF 4 // add for icase match +#define MT_RE_OFF 8 // add for regexp match +#define MT_MASK 7 // mask for printing priority #define MT_COUNT 16 static char *mt_names[MT_COUNT/2] = @@ -108,15 +106,6 @@ static char_u *topmsg = (char_u *)N_("E556: at top of tag stack"); static char_u *tagmatchname = NULL; /* name of last used tag */ /* - * We use ftello() here, if available. It returns off_t instead of long, - * which helps if long is 32 bit and off_t is 64 bit. - * We assume that when fseeko() is available then ftello() is too. - */ -#ifdef HAVE_FSEEKO -# define ftell ftello -#endif - -/* * Tag for preview window is remembered separately, to avoid messing up the * normal tagstack. */ @@ -210,10 +199,9 @@ do_tag ( clearpos(&saved_fmark.mark); /* shutup gcc 4.0 */ saved_fmark.fnum = 0; - /* - * Don't add a tag to the tagstack if 'tagstack' has been reset. - */ - if (!p_tgst && *tag != NUL) { + // Don't add a tag to the tagstack if 'tagstack' has been reset. + assert(tag != NULL); + if (!p_tgst && *tag != NUL) { // -V522 use_tagstack = false; new_tag = true; if (g_do_tagpreview != 0) { @@ -540,10 +528,11 @@ do_tag ( } vim_snprintf((char *)IObuff + 1, IOSIZE - 1, "%2d %s ", i + 1, mt_names[matches[i][0] & MT_MASK]); - msg_puts(IObuff); - if (tagp.tagkind != NULL) + msg_puts((const char *)IObuff); + if (tagp.tagkind != NULL) { msg_outtrans_len(tagp.tagkind, - (int)(tagp.tagkind_end - tagp.tagkind)); + (int)(tagp.tagkind_end - tagp.tagkind)); + } msg_advance(13); msg_outtrans_len_attr(tagp.tagname, (int)(tagp.tagname_end - tagp.tagname), @@ -595,7 +584,7 @@ do_tag ( } p = msg_outtrans_one(p, attr); if (*p == TAB) { - msg_puts_attr((char_u *)" ", attr); + msg_puts_attr(" ", attr); break; } if (*p == ':') @@ -678,7 +667,7 @@ do_tag ( fname = xmalloc(MAXPATHL + 1); cmd = xmalloc(CMDBUFFSIZE + 1); - list = list_alloc(); + list = tv_list_alloc(); for (i = 0; i < num_matches; ++i) { int len, cmd_len; @@ -777,20 +766,21 @@ do_tag ( cmd[len] = NUL; } - dict = dict_alloc(); - list_append_dict(list, dict); + dict = tv_dict_alloc(); + tv_list_append_dict(list, dict); - dict_add_nr_str(dict, "text", 0L, tag_name); - dict_add_nr_str(dict, "filename", 0L, fname); - dict_add_nr_str(dict, "lnum", lnum, NULL); - if (lnum == 0) - dict_add_nr_str(dict, "pattern", 0L, cmd); + tv_dict_add_str(dict, S_LEN("text"), (const char *)tag_name); + tv_dict_add_str(dict, S_LEN("filename"), (const char *)fname); + tv_dict_add_nr(dict, S_LEN("lnum"), lnum); + if (lnum == 0) { + tv_dict_add_str(dict, S_LEN("pattern"), (const char *)cmd); + } } vim_snprintf((char *)IObuff, IOSIZE, "ltag %s", tag); - set_errorlist(curwin, list, ' ', IObuff); + set_errorlist(curwin, list, ' ', IObuff, NULL); - list_free(list); + tv_list_free(list); xfree(fname); xfree(cmd); @@ -858,13 +848,15 @@ do_tag ( STRCAT(IObuff, _(" Using tag with different case!")); if ((num_matches > prev_num_matches || new_tag) && num_matches > 1) { - if (ic) - msg_attr(IObuff, hl_attr(HLF_W)); - else + if (ic) { + msg_attr((const char *)IObuff, hl_attr(HLF_W)); + } else { msg(IObuff); - msg_scroll = TRUE; /* don't overwrite this message */ - } else + } + msg_scroll = true; // Don't overwrite this message. + } else { give_warning(IObuff, ic); + } if (ic && !msg_scrolled && msg_silent == 0) { ui_flush(); os_delay(1000L, true); @@ -916,7 +908,8 @@ end_do_tag: /* Only store the new index when using the tagstack and it's valid. */ if (use_tagstack && tagstackidx <= curwin->w_tagstacklen) curwin->w_tagstackidx = tagstackidx; - postponed_split = 0; /* don't split next time */ + postponed_split = 0; // don't split next time + g_do_tagpreview = 0; // don't do tag preview next time return jumped_to_tag; } @@ -1057,6 +1050,7 @@ static void prepare_pats(pat_T *pats, int has_re) * TAG_REGEXP use "pat" as a regexp * TAG_NOIC don't always ignore case * TAG_KEEP_LANG keep language + * TAG_CSCOPE use cscope results for tags */ int find_tags ( @@ -1085,22 +1079,21 @@ find_tags ( char_u *p; char_u *s; int i; - int tag_file_sorted = NUL; /* !_TAG_FILE_SORTED value */ - struct tag_search_info /* Binary search file offsets */ - { - off_t low_offset; /* offset for first char of first line that - could match */ - off_t high_offset; /* offset of char after last line that could - match */ - off_t curr_offset; /* Current file offset in search range */ - off_t curr_offset_used; /* curr_offset used when skipping back */ - off_t match_offset; /* Where the binary search found a tag */ - int low_char; /* first char at low_offset */ - int high_char; /* first char at high_offset */ + int tag_file_sorted = NUL; // !_TAG_FILE_SORTED value + struct tag_search_info { // Binary search file offsets + off_T low_offset; // offset for first char of first line that + // could match + off_T high_offset; // offset of char after last line that could + // match + off_T curr_offset; // Current file offset in search range + off_T curr_offset_used; // curr_offset used when skipping back + off_T match_offset; // Where the binary search found a tag + int low_char; // first char at low_offset + int high_char; // first char at high_offset } search_info; - off_t filesize; + off_T filesize; int tagcmp; - off_t offset; + off_T offset; int round; enum { TS_START, /* at start of file */ @@ -1118,19 +1111,19 @@ find_tags ( int save_emsg_off; - struct match_found { - int len; /* nr of chars of match[] to be compared */ - char_u match[1]; /* actually longer */ - } *mfp, *mfp2; - garray_T ga_match[MT_COUNT]; - int match_count = 0; /* number of matches found */ + char_u *mfp; + garray_T ga_match[MT_COUNT]; // stores matches in sequence + hashtab_T ht_match[MT_COUNT]; // stores matches by key + hash_T hash = 0; + int match_count = 0; // number of matches found char_u **matches; int mtt; int help_save; int help_pri = 0; - char_u *help_lang_find = NULL; /* lang to be found */ - char_u help_lang[3]; /* lang of current tags file */ - char_u *saved_pat = NULL; /* copy of pat[] */ + char_u *help_lang_find = NULL; // lang to be found + char_u help_lang[3]; // lang of current tags file + char_u *saved_pat = NULL; // copy of pat[] + bool is_txt = false; pat_T orgpat; /* holds unconverted pattern info */ vimconv_T vimconv; @@ -1161,6 +1154,12 @@ find_tags ( case TC_MATCH: p_ic = false; break; + case TC_FOLLOWSCS: + p_ic = ignorecase(pat); + break; + case TC_SMART: + p_ic = ignorecase_opt(pat, true, true); + break; default: assert(false); } @@ -1174,16 +1173,23 @@ find_tags ( */ lbuf = xmalloc(lbuf_size); tag_fname = xmalloc(MAXPATHL + 1); - for (mtt = 0; mtt < MT_COUNT; ++mtt) - ga_init(&ga_match[mtt], (int)sizeof(struct match_found *), 100); + for (mtt = 0; mtt < MT_COUNT; mtt++) { + ga_init(&ga_match[mtt], sizeof(char_u *), 100); + hash_init(&ht_match[mtt]); + } STRCPY(tag_fname, "from cscope"); /* for error messages */ /* * Initialize a few variables */ - if (help_only) /* want tags from help file */ - curbuf->b_help = true; /* will be restored later */ + if (help_only) { // want tags from help file + curbuf->b_help = true; // will be restored later + } else if (use_cscope) { + // Make sure we don't mix help and cscope, confuses Coverity. + help_only = false; + curbuf->b_help = false; + } orgpat.len = (int)STRLEN(pat); if (curbuf->b_help) { @@ -1208,9 +1214,9 @@ find_tags ( if (has_re && orgpat.regmatch.regprog == NULL) goto findtag_end; - /* This is only to avoid a compiler warning for using search_info - * uninitialised. */ - memset(&search_info, 0, (size_t)1); + // This is only to avoid a compiler warning for using search_info + // uninitialised. + memset(&search_info, 0, 1); // -V512 /* * When finding a specified number of matches, first try with matching @@ -1222,6 +1228,14 @@ find_tags ( * When the tag file is case-fold sorted, it is either one or the other. * Only ignore case when TAG_NOIC not used or 'ignorecase' set. */ + // Set a flag if the file extension is .txt + if ((flags & TAG_KEEP_LANG) + && help_lang_find == NULL + && curbuf->b_fname != NULL + && (i = (int)STRLEN(curbuf->b_fname)) > 4 + && STRICMP(curbuf->b_fname + i - 4, ".txt") == 0) { + is_txt = true; + } orgpat.regmatch.rm_ic = ((p_ic || !noic) && (findall || orgpat.headlen == 0 || !p_tbs)); for (round = 1; round <= 2; ++round) { @@ -1237,13 +1251,19 @@ find_tags ( fp = NULL; // avoid GCC warning } else { if (curbuf->b_help) { - /* Prefer help tags according to 'helplang'. Put the - * two-letter language name in help_lang[]. */ - i = (int)STRLEN(tag_fname); - if (i > 3 && tag_fname[i - 3] == '-') - STRCPY(help_lang, tag_fname + i - 2); - else + // Keep en if the file extension is .txt + if (is_txt) { STRCPY(help_lang, "en"); + } else { + // Prefer help tags according to 'helplang'. Put the + // two-letter language name in help_lang[]. + i = (int)STRLEN(tag_fname); + if (i > 3 && tag_fname[i - 3] == '-') { + STRCPY(help_lang, tag_fname + i - 2); + } else { + STRCPY(help_lang, "en"); + } + } /* When searching for a specific language skip tags files * for other languages. */ @@ -1348,36 +1368,28 @@ find_tags ( if (state == TS_BINARY || state == TS_SKIP_BACK) { /* Adjust the search file offset to the correct position */ search_info.curr_offset_used = search_info.curr_offset; -#ifdef HAVE_FSEEKO - fseeko(fp, search_info.curr_offset, SEEK_SET); -#else - fseek(fp, (long)search_info.curr_offset, SEEK_SET); -#endif + vim_fseek(fp, search_info.curr_offset, SEEK_SET); eof = vim_fgets(lbuf, LSIZE, fp); if (!eof && search_info.curr_offset != 0) { /* The explicit cast is to work around a bug in gcc 3.4.2 * (repeated below). */ - search_info.curr_offset = ftell(fp); + search_info.curr_offset = vim_ftell(fp); if (search_info.curr_offset == search_info.high_offset) { - /* oops, gone a bit too far; try from low offset */ -#ifdef HAVE_FSEEKO - fseeko(fp, search_info.low_offset, SEEK_SET); -#else - fseek(fp, (long)search_info.low_offset, SEEK_SET); -#endif + // oops, gone a bit too far; try from low offset + vim_fseek(fp, search_info.low_offset, SEEK_SET); search_info.curr_offset = search_info.low_offset; } eof = vim_fgets(lbuf, LSIZE, fp); } /* skip empty and blank lines */ while (!eof && vim_isblankline(lbuf)) { - search_info.curr_offset = ftell(fp); + search_info.curr_offset = vim_ftell(fp); eof = vim_fgets(lbuf, LSIZE, fp); } if (eof) { /* Hit end of file. Skip backwards. */ state = TS_SKIP_BACK; - search_info.match_offset = ftell(fp); + search_info.match_offset = vim_ftell(fp); search_info.curr_offset = search_info.curr_offset_used; continue; } @@ -1493,10 +1505,10 @@ line_read_in: */ if (state == TS_BINARY) { // Get the tag file size. - if ((filesize = lseek(fileno(fp), (off_t)0L, SEEK_END)) <= 0) { + if ((filesize = vim_lseek(fileno(fp), (off_T)0L, SEEK_END)) <= 0) { state = TS_LINEAR; } else { - lseek(fileno(fp), (off_t)0L, SEEK_SET); + vim_lseek(fileno(fp), (off_T)0L, SEEK_SET); /* Calculate the first read offset in the file. Start * the search in the middle of the file. */ @@ -1534,11 +1546,7 @@ parse_line: /* Avoid getting stuck. */ linear = TRUE; state = TS_LINEAR; -# ifdef HAVE_FSEEKO - fseeko(fp, search_info.low_offset, SEEK_SET); -# else - fseek(fp, (long)search_info.low_offset, SEEK_SET); -# endif + vim_fseek(fp, search_info.low_offset, SEEK_SET); } continue; } @@ -1617,7 +1625,7 @@ parse_line: continue; } if (tagcmp < 0) { - search_info.curr_offset = ftell(fp); + search_info.curr_offset = vim_ftell(fp); if (search_info.curr_offset < search_info.high_offset) { search_info.low_offset = search_info.curr_offset; if (sortic) @@ -1653,10 +1661,11 @@ parse_line: } else if (state == TS_STEP_FORWARD) { assert(cmplen >= 0); if (mb_strnicmp(tagp.tagname, orgpat.head, (size_t)cmplen) != 0) { - if ((off_t)ftell(fp) > search_info.match_offset) - break; /* past last match */ - else - continue; /* before first match */ + if ((off_T)vim_ftell(fp) > search_info.match_offset) { + break; // past last match + } else { + continue; // before first match + } } } else /* skip this match if it can't match */ @@ -1727,10 +1736,10 @@ parse_line: match_re = TRUE; } - /* - * If a match is found, add it to ga_match[]. - */ + // If a match is found, add it to ht_match[] and ga_match[]. if (match) { + int len = 0; + if (use_cscope) { /* Don't change the ordering, always use the same table. */ mtt = MT_GL_OTH; @@ -1765,116 +1774,109 @@ parse_line: mtt += MT_RE_OFF; } - /* - * Add the found match in ga_match[mtt], avoiding duplicates. - * Store the info we need later, which depends on the kind of - * tags we are dealing with. - */ - ga_grow(&ga_match[mtt], 1); - { - int len; - - if (help_only) { + // Add the found match in ht_match[mtt] and ga_match[mtt]. + // Store the info we need later, which depends on the kind of + // tags we are dealing with. + if (help_only) { # define ML_EXTRA 3 - /* - * Append the help-heuristic number after the - * tagname, for sorting it later. - */ - *tagp.tagname_end = NUL; - len = (int)(tagp.tagname_end - tagp.tagname); - mfp = xmalloc(sizeof(struct match_found) + len + 10 + ML_EXTRA); - /* "len" includes the language and the NUL, but - * not the priority. */ - mfp->len = len + ML_EXTRA + 1; -#define ML_HELP_LEN 6 - p = mfp->match; - STRCPY(p, tagp.tagname); - p[len] = '@'; - STRCPY(p + len + 1, help_lang); - sprintf((char *)p + len + 1 + ML_EXTRA, "%06d", - help_heuristic(tagp.tagname, - match_re ? matchoff : 0, !match_no_ic) - + help_pri - ); - - *tagp.tagname_end = TAB; - } else if (name_only) { - if (get_it_again) { - char_u *temp_end = tagp.command; - - if (*temp_end == '/') - while (*temp_end && *temp_end != '\r' - && *temp_end != '\n' - && *temp_end != '$') - temp_end++; - - if (tagp.command + 2 < temp_end) { - len = (int)(temp_end - tagp.command - 2); - mfp = xmalloc(sizeof(struct match_found) + len); - mfp->len = len + 1; /* include the NUL */ - p = mfp->match; - STRLCPY(p, tagp.command + 2, len + 1); - } else - mfp = NULL; - get_it_again = FALSE; + // Append the help-heuristic number after the tagname, for + // sorting it later. The heuristic is ignored for + // detecting duplicates. + // The format is {tagname}@{lang}NUL{heuristic}NUL + *tagp.tagname_end = NUL; + len = (int)(tagp.tagname_end - tagp.tagname); + mfp = xmalloc(sizeof(char_u) + len + 10 + ML_EXTRA + 1); + + p = mfp; + STRCPY(p, tagp.tagname); + p[len] = '@'; + STRCPY(p + len + 1, help_lang); + snprintf((char *)p + len + 1 + ML_EXTRA, 10, "%06d", + help_heuristic(tagp.tagname, + match_re ? matchoff : 0, !match_no_ic) + + help_pri); + + *tagp.tagname_end = TAB; + } else if (name_only) { + if (get_it_again) { + char_u *temp_end = tagp.command; + + if (*temp_end == '/') { + while (*temp_end && *temp_end != '\r' + && *temp_end != '\n' + && *temp_end != '$') { + temp_end++; + } + } + + if (tagp.command + 2 < temp_end) { + len = (int)(temp_end - tagp.command - 2); + mfp = xmalloc(len + 2); + STRLCPY(mfp, tagp.command + 2, len + 1); } else { - len = (int)(tagp.tagname_end - tagp.tagname); - mfp = xmalloc(sizeof(struct match_found) + len); - mfp->len = len + 1; /* include the NUL */ - p = mfp->match; - STRLCPY(p, tagp.tagname, len + 1); - - /* if wanted, re-read line to get long form too */ - if (State & INSERT) - get_it_again = p_sft; + mfp = NULL; } + get_it_again = false; } else { - /* Save the tag in a buffer. - * Emacs tag: <mtt><tag_fname><NUL><ebuf><NUL><lbuf> - * other tag: <mtt><tag_fname><NUL><NUL><lbuf> - * without Emacs tags: <mtt><tag_fname><NUL><lbuf> - */ - len = (int)STRLEN(tag_fname) - + (int)STRLEN(lbuf) + 3; - mfp = xmalloc(sizeof(struct match_found) + len); - mfp->len = len; - p = mfp->match; - p[0] = mtt; - STRCPY(p + 1, tag_fname); + len = (int)(tagp.tagname_end - tagp.tagname); + mfp = xmalloc(sizeof(char_u) + len + 1); + STRLCPY(mfp, tagp.tagname, len + 1); + + // if wanted, re-read line to get long form too + if (State & INSERT) { + get_it_again = p_sft; + } + } + } else { +#define TAG_SEP 0x02 + size_t tag_fname_len = STRLEN(tag_fname); + // Save the tag in a buffer. + // Use 0x02 to separate fields (Can't use NUL, because the + // hash key is terminated by NUL). + // Emacs tag: <mtt><tag_fname><0x02><ebuf><0x02><lbuf><NUL> + // other tag: <mtt><tag_fname><0x02><0x02><lbuf><NUL> + // without Emacs tags: <mtt><tag_fname><0x02><lbuf><NUL> + // Here <mtt> is the "mtt" value plus 1 to avoid NUL. + len = (int)tag_fname_len + (int)STRLEN(lbuf) + 3; + mfp = xmalloc(sizeof(char_u) + len + 1); + p = mfp; + p[0] = mtt + 1; + STRCPY(p + 1, tag_fname); #ifdef BACKSLASH_IN_FILENAME - /* Ignore differences in slashes, avoid adding - * both path/file and path\file. */ - slash_adjust(p + 1); + // Ignore differences in slashes, avoid adding + // both path/file and path\file. + slash_adjust(p + 1); #endif - s = p + 1 + STRLEN(tag_fname) + 1; - STRCPY(s, lbuf); - } + p[tag_fname_len + 1] = TAG_SEP; + s = p + 1 + tag_fname_len + 1; + STRCPY(s, lbuf); + } - if (mfp != NULL) { - /* - * Don't add identical matches. - * This can take a lot of time when finding many - * matches, check for CTRL-C now and then. - * Add all cscope tags, because they are all listed. - */ - if (use_cscope) - i = -1; - else - for (i = ga_match[mtt].ga_len; --i >= 0 && !got_int; ) { - mfp2 = ((struct match_found **) - (ga_match[mtt].ga_data))[i]; - if (mfp2->len == mfp->len - && memcmp(mfp2->match, mfp->match, - (size_t)mfp->len) == 0) - break; - fast_breakcheck(); - } - if (i < 0) { - ((struct match_found **)(ga_match[mtt].ga_data)) + if (mfp != NULL) { + hashitem_T *hi; + + // Don't add identical matches. + // Add all cscope tags, because they are all listed. + // "mfp" is used as a hash key, there is a NUL byte to end + // the part matters for comparing, more bytes may follow + // after it. E.g. help tags store the priority after the + // NUL. + if (use_cscope) { + hash++; + } else { + hash = hash_hash(mfp); + } + hi = hash_lookup(&ht_match[mtt], (const char *)mfp, + STRLEN(mfp), hash); + if (HASHITEM_EMPTY(hi)) { + hash_add_item(&ht_match[mtt], hi, mfp, hash); + ga_grow(&ga_match[mtt], 1); + ((char_u **)(ga_match[mtt].ga_data)) [ga_match[mtt].ga_len++] = mfp; - ++match_count; - } else - xfree(mfp); + match_count++; + } else { + // duplicate tag, drop it + xfree(mfp); } } } @@ -1884,10 +1886,11 @@ parse_line: if (line_error) { EMSG2(_("E431: Format error in tags file \"%s\""), tag_fname); - if (!use_cscope) - EMSGN(_("Before byte %" PRId64), ftell(fp)); - stop_searching = TRUE; - line_error = FALSE; + if (!use_cscope) { + EMSGN(_("Before byte %" PRId64), vim_ftell(fp)); + } + stop_searching = true; + line_error = false; } if (!use_cscope) @@ -1949,21 +1952,29 @@ findtag_end: else matches = NULL; match_count = 0; - for (mtt = 0; mtt < MT_COUNT; ++mtt) { - for (int i = 0; i < ga_match[mtt].ga_len; ++i) { - mfp = ((struct match_found **)(ga_match[mtt].ga_data))[i]; - if (matches == NULL) + for (mtt = 0; mtt < MT_COUNT; mtt++) { + for (i = 0; i < ga_match[mtt].ga_len; i++) { + mfp = ((char_u **)(ga_match[mtt].ga_data))[i]; + if (matches == NULL) { xfree(mfp); - else { - /* To avoid allocating memory again we turn the struct - * match_found into a string. For help the priority was not - * included in the length. */ - memmove(mfp, mfp->match, - (size_t)(mfp->len + (help_only ? ML_HELP_LEN : 0))); + } else { + if (!name_only) { + // Change mtt back to zero-based. + *mfp = *mfp - 1; + + // change the TAG_SEP back to NUL + for (p = mfp + 1; *p != NUL; p++) { + if (*p == TAG_SEP) { + *p = NUL; + } + } + } matches[match_count++] = (char_u *)mfp; } } + ga_clear(&ga_match[mtt]); + hash_clear(&ht_match[mtt]); } *matchesp = matches; @@ -2175,7 +2186,7 @@ parse_tag_line ( * Return TRUE if it is a static tag and adjust *tagname to the real tag. * Return FALSE if it is not a static tag. */ -static int test_for_static(tagptrs_T *tagp) +static bool test_for_static(tagptrs_T *tagp) { char_u *p; @@ -2505,7 +2516,7 @@ jumpto_tag ( } } p_ws = save_p_ws; - p_ic = save_p_ic; + p_ic = save_p_ic; // -V519 p_scs = save_p_scs; /* A search command may have positioned the cursor beyond the end @@ -2740,8 +2751,8 @@ add_tag_field ( int len = 0; int retval; - /* check that the field name doesn't exist yet */ - if (dict_find(dict, (char_u *)field_name, -1) != NULL) { + // Check that the field name doesn't exist yet. + if (tv_dict_find(dict, field_name, -1) != NULL) { if (p_verbose > 0) { verbose_enter(); smsg(_("Duplicate field name: %s"), field_name); @@ -2762,26 +2773,25 @@ add_tag_field ( STRLCPY(buf, start, len + 1); } buf[len] = NUL; - retval = dict_add_nr_str(dict, field_name, 0L, buf); + retval = tv_dict_add_str(dict, field_name, STRLEN(field_name), + (const char *)buf); xfree(buf); return retval; } -/* - * Add the tags matching the specified pattern to the list "list" - * as a dictionary - */ -int get_tags(list_T *list, char_u *pat) +/// Add the tags matching the specified pattern "pat" to the list "list" +/// as a dictionary. Use "buf_fname" for priority, unless NULL. +int get_tags(list_T *list, char_u *pat, char_u *buf_fname) { int num_matches, i, ret; char_u **matches, *p; char_u *full_fname; dict_T *dict; tagptrs_T tp; - long is_static; + bool is_static; ret = find_tags(pat, &num_matches, &matches, - TAG_REGEXP | TAG_NOIC, (int)MAXCOL, NULL); + TAG_REGEXP | TAG_NOIC, (int)MAXCOL, buf_fname); if (ret == OK && num_matches > 0) { for (i = 0; i < num_matches; ++i) { int parse_result = parse_match(matches[i], &tp); @@ -2796,19 +2806,18 @@ int get_tags(list_T *list, char_u *pat) if (STRNCMP(tp.tagname, "!_TAG_", 6) == 0) continue; - dict = dict_alloc(); - list_append_dict(list, dict); + dict = tv_dict_alloc(); + tv_list_append_dict(list, dict); full_fname = tag_full_fname(&tp); if (add_tag_field(dict, "name", tp.tagname, tp.tagname_end) == FAIL - || add_tag_field(dict, "filename", full_fname, - NULL) == FAIL - || add_tag_field(dict, "cmd", tp.command, - tp.command_end) == FAIL + || add_tag_field(dict, "filename", full_fname, NULL) == FAIL + || add_tag_field(dict, "cmd", tp.command, tp.command_end) == FAIL || add_tag_field(dict, "kind", tp.tagkind, - tp.tagkind ? tp.tagkind_end : NULL) == FAIL - || dict_add_nr_str(dict, "static", is_static, NULL) == FAIL) + tp.tagkind ? tp.tagkind_end : NULL) == FAIL + || tv_dict_add_nr(dict, S_LEN("static"), is_static) == FAIL) { ret = FAIL; + } xfree(full_fname); diff --git a/src/nvim/tag.h b/src/nvim/tag.h index 5d4bcddf94..a8fddd05da 100644 --- a/src/nvim/tag.h +++ b/src/nvim/tag.h @@ -1,6 +1,9 @@ #ifndef NVIM_TAG_H #define NVIM_TAG_H +#include "nvim/types.h" +#include "nvim/ex_cmds_defs.h" + /* * Values for do_tag(). */ diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c index 30556a3835..3b278dc666 100644 --- a/src/nvim/terminal.c +++ b/src/nvim/terminal.c @@ -1,18 +1,20 @@ -// VT220/xterm-like terminal emulator implementation for nvim. Powered by -// libvterm (http://www.leonerd.org.uk/code/libvterm/). +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + +// VT220/xterm-like terminal emulator. +// Powered by libvterm http://www.leonerd.org.uk/code/libvterm // // libvterm is a pure C99 terminal emulation library with abstract input and // display. This means that the library needs to read data from the master fd // and feed VTerm instances, which will invoke user callbacks with screen // update instructions that must be mirrored to the real display. // -// Keys are pressed in VTerm instances by calling +// Keys are sent to VTerm instances by calling // vterm_keyboard_key/vterm_keyboard_unichar, which generates byte streams that // must be fed back to the master fd. // -// This implementation uses nvim buffers as the display mechanism for both -// the visible screen and the scrollback buffer. When focused, the window -// "pins" to the bottom of the buffer and mirrors libvterm screen state. +// Nvim buffers are used as the display mechanism for both the visible screen +// and the scrollback buffer. // // When a line becomes invisible due to a decrease in screen height or because // a line was pushed up during normal terminal output, we store the line @@ -23,18 +25,17 @@ // scrollback buffer, which is mirrored in the nvim buffer displaying lines // that were previously invisible. // -// The vterm->nvim synchronization is performed in intervals of 10 -// milliseconds. This is done to minimize screen updates when receiving large -// bursts of data. +// The vterm->nvim synchronization is performed in intervals of 10 milliseconds, +// to minimize screen updates when receiving large bursts of data. // // This module is decoupled from the processes that normally feed it data, so // it's possible to use it as a general purpose console buffer (possibly as a // log/display mechanism for nvim in the future) // -// Inspired by vimshell (http://www.wana.at/vimshell/) and -// Conque (https://code.google.com/p/conque/). Libvterm usage instructions (plus -// some extra code) were taken from -// pangoterm (http://www.leonerd.org.uk/code/pangoterm/) +// Inspired by: vimshell http://www.wana.at/vimshell +// Conque https://code.google.com/p/conque +// Some code from pangoterm http://www.leonerd.org.uk/code/pangoterm + #include <assert.h> #include <stdio.h> #include <stdint.h> @@ -42,6 +43,7 @@ #include <vterm.h> +#include "nvim/log.h" #include "nvim/vim.h" #include "nvim/terminal.h" #include "nvim/message.h" @@ -80,17 +82,15 @@ typedef struct terminal_state { Terminal *term; int save_rd; // saved value of RedrawingDisabled bool close; - bool got_bs; // if the last input was <C-\> + bool got_bsl; // if the last input was <C-\> } TerminalState; #ifdef INCLUDE_GENERATED_DECLARATIONS # include "terminal.c.generated.h" #endif -#define SCROLLBACK_BUFFER_DEFAULT_SIZE 1000 // Delay for refreshing the terminal buffer after receiving updates from -// libvterm. This is greatly improves performance when receiving large bursts -// of data. +// libvterm. Improves performance when receiving large bursts of data. #define REFRESH_DELAY 10 static TimeWatcher refresh_timer; @@ -102,27 +102,23 @@ typedef struct { } ScrollbackLine; struct terminal { - // options passed to terminal_open - TerminalOptions opts; - // libvterm structures + TerminalOptions opts; // options passed to terminal_open VTerm *vt; VTermScreen *vts; // buffer used to: // - convert VTermScreen cell arrays into utf8 strings // - receive data from libvterm as a result of key presses. char textbuf[0x1fff]; - // Scrollback buffer storage for libvterm. - // TODO(tarruda): Use a doubly-linked list - ScrollbackLine **sb_buffer; - // number of rows pushed to sb_buffer - size_t sb_current; - // sb_buffer size; - size_t sb_size; + + ScrollbackLine **sb_buffer; // Scrollback buffer storage for libvterm + size_t sb_current; // number of rows pushed to sb_buffer + size_t sb_size; // sb_buffer size // "virtual index" that points to the first sb_buffer row that we need to // push to the terminal buffer when refreshing the scrollback. When negative, // it actually points to entries that are no longer in sb_buffer (because the // window height has increased) and must be deleted from the terminal buffer int sb_pending; + // buf_T instance that acts as a "drawing surface" for libvterm // we can't store a direct reference to the buffer because the // refresh_timer_cb may be called after the buffer was freed, and there's @@ -130,20 +126,18 @@ struct terminal { handle_T buf_handle; // program exited bool closed, destroy; + // some vterm properties bool forward_mouse; - // invalid rows libvterm screen - int invalid_start, invalid_end; + int invalid_start, invalid_end; // invalid rows in libvterm screen struct { int row, col; bool visible; } cursor; - // which mouse button is pressed - int pressed_button; - // pending width/height - bool pending_resize; - // With a reference count of 0 the terminal can be freed. - size_t refcount; + int pressed_button; // which mouse button is pressed + bool pending_resize; // pending width/height + + size_t refcount; // reference count }; static VTermScreenCallbacks vterm_screen_callbacks = { @@ -174,7 +168,7 @@ void terminal_init(void) VTerm *vt = vterm_new(24, 80); VTermState *state = vterm_obtain_state(vt); - for (int color_index = 0; color_index < 256; color_index++) { + for (int color_index = 255; color_index >= 0; color_index--) { VTermColor color; // Some of the default 16 colors has the same color as the later // 240 colors. To avoid collisions, we will use the custom colors @@ -236,26 +230,26 @@ Terminal *terminal_open(TerminalOptions opts) rv->invalid_start = 0; rv->invalid_end = opts.height; refresh_screen(rv, curbuf); - set_option_value((uint8_t *)"buftype", 0, (uint8_t *)"terminal", OPT_LOCAL); - // some sane settings for terminal buffers - set_option_value((uint8_t *)"wrap", false, NULL, OPT_LOCAL); - set_option_value((uint8_t *)"number", false, NULL, OPT_LOCAL); - set_option_value((uint8_t *)"relativenumber", false, NULL, OPT_LOCAL); + set_option_value("buftype", 0, "terminal", OPT_LOCAL); // -V666 + + // Default settings for terminal buffers + curbuf->b_p_ma = false; // 'nomodifiable' + curbuf->b_p_ul = -1; // 'undolevels' + curbuf->b_p_scbk = p_scbk; // 'scrollback' + curbuf->b_p_tw = 0; // 'textwidth' + set_option_value("wrap", false, NULL, OPT_LOCAL); + set_option_value("list", false, NULL, OPT_LOCAL); buf_set_term_title(curbuf, (char *)curbuf->b_ffname); RESET_BINDING(curwin); - // Apply TermOpen autocmds so the user can configure the terminal + // Reset cursor in current window. + curwin->w_cursor = (pos_T){ .lnum = 1, .col = 0, .coladd = 0 }; + + // Apply TermOpen autocmds _before_ configuring the scrollback buffer. apply_autocmds(EVENT_TERMOPEN, NULL, NULL, false, curbuf); - // Configure the scrollback buffer. Try to get the size from: - // - // - b:terminal_scrollback_buffer_size - // - g:terminal_scrollback_buffer_size - // - SCROLLBACK_BUFFER_DEFAULT_SIZE - // - // but limit to 100k. - int size = get_config_int("terminal_scrollback_buffer_size"); - rv->sb_size = size > 0 ? (size_t)size : SCROLLBACK_BUFFER_DEFAULT_SIZE; - rv->sb_size = MIN(rv->sb_size, 100000); + // Configure the scrollback buffer. + rv->sb_size = curbuf->b_p_scbk < 0 + ? SB_MAX : (size_t)MAX(1, curbuf->b_p_scbk); rv->sb_buffer = xmalloc(sizeof(ScrollbackLine *) * rv->sb_size); if (!true_color) { @@ -307,8 +301,16 @@ void terminal_close(Terminal *term, char *msg) } term->forward_mouse = false; - term->closed = true; + + // flush any pending changes to the buffer + if (!exiting) { + block_autocmds(); + refresh_terminal(term); + unblock_autocmds(); + } + buf_T *buf = handle_get_buffer(term->buf_handle); + term->closed = true; if (!msg || exiting) { // If no msg was given, this was called by close_buffer(buffer.c). Or if @@ -334,22 +336,22 @@ void terminal_close(Terminal *term, char *msg) void terminal_resize(Terminal *term, uint16_t width, uint16_t height) { if (term->closed) { - // will be called after exited if two windows display the same terminal and - // one of the is closed as a consequence of pressing a key. + // If two windows display the same terminal and one is closed by keypress. return; } + bool force = width == UINT16_MAX || height == UINT16_MAX; int curwidth, curheight; vterm_get_size(term->vt, &curheight, &curwidth); - if (!width) { + if (force || !width) { width = (uint16_t)curwidth; } - if (!height) { + if (force || !height) { height = (uint16_t)curheight; } - if (curheight == height && curwidth == width) { + if (!force && curheight == height && curwidth == width) { return; } @@ -381,8 +383,18 @@ void terminal_enter(void) State = TERM_FOCUS; mapped_ctrl_c |= TERM_FOCUS; // Always map CTRL-C to avoid interrupt. RedrawingDisabled = false; - // go to the bottom when the terminal is focused - adjust_topline(s->term, buf, false); + + // Disable these options in terminal-mode. They are nonsense because cursor is + // placed at end of buffer to "follow" output. + win_T *save_curwin = curwin; + int save_w_p_cul = curwin->w_p_cul; + int save_w_p_cuc = curwin->w_p_cuc; + int save_w_p_rnu = curwin->w_p_rnu; + curwin->w_p_cul = false; + curwin->w_p_cuc = false; + curwin->w_p_rnu = false; + + adjust_topline(s->term, buf, 0); // scroll to end // erase the unfocused cursor invalidate_terminal(s->term, s->term->cursor.row, s->term->cursor.row + 1); showmode(); @@ -395,6 +407,12 @@ void terminal_enter(void) restart_edit = 0; State = save_state; RedrawingDisabled = s->save_rd; + if (save_curwin == curwin) { // save_curwin may be invalid (window closed)! + curwin->w_p_cul = save_w_p_cul; + curwin->w_p_cuc = save_w_p_cuc; + curwin->w_p_rnu = save_w_p_rnu; + } + // draw the unfocused cursor invalidate_terminal(s->term, s->term->cursor.row, s->term->cursor.row + 1); unshowmode(true); @@ -454,14 +472,14 @@ static int terminal_execute(VimState *state, int key) break; case Ctrl_N: - if (s->got_bs) { + if (s->got_bsl) { return 0; } // FALLTHROUGH default: - if (key == Ctrl_BSL && !s->got_bs) { - s->got_bs = true; + if (key == Ctrl_BSL && !s->got_bsl) { + s->got_bsl = true; break; } if (s->term->closed) { @@ -469,7 +487,7 @@ static int terminal_execute(VimState *state, int key) return 0; } - s->got_bs = false; + s->got_bsl = false; terminal_send_key(s->term, key); } @@ -590,8 +608,10 @@ void terminal_get_line_attributes(Terminal *term, win_T *wp, int linenr, if (term->cursor.visible && term->cursor.row == row && term->cursor.col == col) { - attr_id = hl_combine_attr(attr_id, is_focused(term) && wp == curwin ? - hl_attr(HLF_TERM) : hl_attr(HLF_TERMNC)); + attr_id = hl_combine_attr(attr_id, + is_focused(term) && wp == curwin + ? win_hl_attr(wp, HLF_TERM) + : win_hl_attr(wp, HLF_TERMNC)); } term_attrs[col] = attr_id; @@ -626,15 +646,16 @@ static int term_movecursor(VTermPos new, VTermPos old, int visible, } static void buf_set_term_title(buf_T *buf, char *title) - FUNC_ATTR_NONNULL_ALL + FUNC_ATTR_NONNULL_ALL { - Error err; - dict_set_value(buf->b_vars, - cstr_as_string("term_title"), - STRING_OBJ(cstr_as_string(title)), - false, - false, - &err); + Error err = ERROR_INIT; + dict_set_var(buf->b_vars, + STATIC_CSTR_AS_STRING("term_title"), + STRING_OBJ(cstr_as_string(title)), + false, + false, + &err); + api_clear_error(&err); } static int term_settermprop(VTermProp prop, VTermValue *val, void *data) @@ -669,14 +690,19 @@ static int term_settermprop(VTermProp prop, VTermValue *val, void *data) static int term_bell(void *data) { - ui_putc('\x07'); + ui_call_bell(); return 1; } -// the scrollback push/pop handlers were copied almost verbatim from pangoterm +// Scrollback push handler (from pangoterm). static int term_sb_push(int cols, const VTermScreenCell *cells, void *data) { Terminal *term = data; + + if (!term->sb_size) { + return 0; + } + // copy vterm cells into sb_buffer size_t c = (size_t)cols; ScrollbackLine *sbrow = NULL; @@ -688,10 +714,12 @@ static int term_sb_push(int cols, const VTermScreenCell *cells, void *data) xfree(term->sb_buffer[term->sb_current - 1]); } + // Make room at the start by shifting to the right. memmove(term->sb_buffer + 1, term->sb_buffer, sizeof(term->sb_buffer[0]) * (term->sb_current - 1)); } else if (term->sb_current > 0) { + // Make room at the start by shifting to the right. memmove(term->sb_buffer + 1, term->sb_buffer, sizeof(term->sb_buffer[0]) * term->sb_current); } @@ -701,6 +729,7 @@ static int term_sb_push(int cols, const VTermScreenCell *cells, void *data) sbrow->cols = c; } + // New row is added at the start of the storage buffer. term->sb_buffer[0] = sbrow; if (term->sb_current < term->sb_size) { term->sb_current++; @@ -716,6 +745,11 @@ static int term_sb_push(int cols, const VTermScreenCell *cells, void *data) return 1; } +/// Scrollback pop handler (from pangoterm). +/// +/// @param cols +/// @param cells VTerm state to update. +/// @param data Terminal static int term_sb_pop(int cols, VTermScreenCell *cells, void *data) { Terminal *term = data; @@ -728,24 +762,24 @@ static int term_sb_pop(int cols, VTermScreenCell *cells, void *data) term->sb_pending--; } - // restore vterm state - size_t c = (size_t)cols; ScrollbackLine *sbrow = term->sb_buffer[0]; term->sb_current--; + // Forget the "popped" row by shifting the rest onto it. memmove(term->sb_buffer, term->sb_buffer + 1, sizeof(term->sb_buffer[0]) * (term->sb_current)); - size_t cols_to_copy = c; + size_t cols_to_copy = (size_t)cols; if (cols_to_copy > sbrow->cols) { cols_to_copy = sbrow->cols; } // copy to vterm state memcpy(cells, sbrow->cells, sizeof(cells[0]) * cols_to_copy); - for (size_t col = cols_to_copy; col < c; col++) { + for (size_t col = cols_to_copy; col < (size_t)cols; col++) { cells[col].chars[0] = 0; cells[col].width = 1; } + xfree(sbrow); pmap_put(ptr_t)(invalidated_terminals, term, NULL); @@ -976,7 +1010,7 @@ static bool send_mouse_event(Terminal *term, int c) // terminal buffer refresh & misc {{{ -void fetch_row(Terminal *term, int row, int end_col) +static void fetch_row(Terminal *term, int row, int end_col) { int col = 0; size_t line_len = 0; @@ -1049,28 +1083,29 @@ static void refresh_terminal(Terminal *term) buf_T *buf = handle_get_buffer(term->buf_handle); bool valid = true; if (!buf || !(valid = buf_valid(buf))) { - // destroyed by `close_buffer`. Dont do anything else + // Destroyed by `close_buffer`. Do not do anything else. if (!valid) { term->buf_handle = 0; } return; } - bool pending_resize = term->pending_resize; + long ml_before = buf->b_ml.ml_line_count; WITH_BUFFER(buf, { refresh_size(term, buf); refresh_scrollback(term, buf); refresh_screen(term, buf); redraw_buf_later(buf, NOT_VALID); }); - adjust_topline(term, buf, pending_resize); + long ml_added = buf->b_ml.ml_line_count - ml_before; + adjust_topline(term, buf, ml_added); } -// libuv timer callback. This will enqueue on_refresh to be processed as an -// event. +// Calls refresh_terminal() on all invalidated_terminals. static void refresh_timer_cb(TimeWatcher *watcher, void *data) { - if (exiting) { - // bad things can happen if we redraw when exiting, and there's no need to - // update the buffer. + if (exiting // Cannot redraw (requires event loop) during teardown/exit. + // WM_LIST (^D) is not redrawn, unlike the normal wildmenu. So we must + // skip redraws to keep it visible. + || wild_menu_showing == WM_LIST) { goto end; } Terminal *term; @@ -1080,9 +1115,12 @@ static void refresh_timer_cb(TimeWatcher *watcher, void *data) map_foreach(invalidated_terminals, term, stub, { refresh_terminal(term); }); + bool any_visible = is_term_visible(); pmap_clear(ptr_t)(invalidated_terminals); unblock_autocmds(); - redraw(true); + if (any_visible) { + redraw(true); + } end: refresh_pending = false; } @@ -1101,7 +1139,37 @@ static void refresh_size(Terminal *term, buf_T *buf) term->opts.resize_cb((uint16_t)width, (uint16_t)height, term->opts.data); } -// Refresh the scrollback of a invalidated terminal +/// Adjusts scrollback storage after 'scrollback' option changed. +static void on_scrollback_option_changed(Terminal *term, buf_T *buf) +{ + const size_t scbk = curbuf->b_p_scbk < 0 + ? SB_MAX : (size_t)MAX(1, curbuf->b_p_scbk); + assert(term->sb_current < SIZE_MAX); + if (term->sb_pending > 0) { // Pending rows must be processed first. + abort(); + } + + // Delete lines exceeding the new 'scrollback' limit. + if (scbk < term->sb_current) { + size_t diff = term->sb_current - scbk; + for (size_t i = 0; i < diff; i++) { + ml_delete(1, false); + term->sb_current--; + xfree(term->sb_buffer[term->sb_current]); + } + deleted_lines(1, (long)diff); + } + + // Resize the scrollback storage. + size_t sb_region = sizeof(ScrollbackLine *) * scbk; + if (scbk != term->sb_size) { + term->sb_buffer = xrealloc(term->sb_buffer, sb_region); + } + + term->sb_size = scbk; +} + +// Refresh the scrollback of an invalidated terminal. static void refresh_scrollback(Terminal *term, buf_T *buf) { int width, height; @@ -1130,9 +1198,11 @@ static void refresh_scrollback(Terminal *term, buf_T *buf) ml_delete(buf->b_ml.ml_line_count, false); deleted_lines(buf->b_ml.ml_line_count, 1); } + + on_scrollback_option_changed(term, buf); } -// Refresh the screen(visible part of the buffer when the terminal is +// Refresh the screen (visible part of the buffer when the terminal is // focused) of a invalidated terminal static void refresh_screen(Terminal *term, buf_T *buf) { @@ -1141,8 +1211,7 @@ static void refresh_screen(Terminal *term, buf_T *buf) int height; int width; vterm_get_size(term->vt, &height, &width); - // It's possible that the terminal height decreased and `term->invalid_end` - // doesn't reflect it yet + // Terminal height may have decreased before `invalid_end` reflects it. term->invalid_end = MIN(term->invalid_end, height); for (int r = term->invalid_start, linenr = row_to_linenr(term, r); @@ -1165,6 +1234,18 @@ static void refresh_screen(Terminal *term, buf_T *buf) term->invalid_end = -1; } +/// @return true if any invalidated terminal buffer is visible to the user +static bool is_term_visible(void) +{ + FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { + if (wp->w_buffer->terminal + && pmap_has(ptr_t)(invalidated_terminals, wp->w_buffer->terminal)) { + return true; + } + } + return false; +} + static void redraw(bool restore_cursor) { Terminal *term = curbuf->terminal; @@ -1181,55 +1262,47 @@ static void redraw(bool restore_cursor) save_col = ui_current_col(); } block_autocmds(); - validate_cursor(); if (must_redraw) { update_screen(0); } - redraw_statuslines(); - - if (need_maketitle) { - maketitle(); - } - - showruler(false); - - if (term && is_focused(term)) { - curwin->w_wrow = term->cursor.row; - curwin->w_wcol = term->cursor.col + win_col_off(curwin); - setcursor(); - } else if (restore_cursor) { + if (restore_cursor) { ui_cursor_goto(save_row, save_col); } else if (term) { - // exiting terminal focus, put the window cursor in a valid position - int height, width; - vterm_get_size(term->vt, &height, &width); - curwin->w_wrow = height - 1; - curwin->w_wcol = 0; - setcursor(); + curwin->w_wrow = term->cursor.row; + curwin->w_wcol = term->cursor.col + win_col_off(curwin); + curwin->w_cursor.lnum = MIN(curbuf->b_ml.ml_line_count, + row_to_linenr(term, term->cursor.row)); + // Nudge cursor when returning to normal-mode. + int off = is_focused(term) ? 0 : (curwin->w_p_rl ? 1 : -1); + curwin->w_cursor.col = MAX(0, term->cursor.col + win_col_off(curwin) + off); + curwin->w_cursor.coladd = 0; + mb_check_adjust_col(curwin); } unblock_autocmds(); ui_flush(); } -static void adjust_topline(Terminal *term, buf_T *buf, bool force) +static void adjust_topline(Terminal *term, buf_T *buf, long added) { int height, width; vterm_get_size(term->vt, &height, &width); FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { if (wp->w_buffer == buf) { - // for every window that displays a terminal, ensure the cursor is in a - // valid line - wp->w_cursor.lnum = MIN(wp->w_cursor.lnum, buf->b_ml.ml_line_count); - if (force || curbuf != buf || is_focused(term)) { - // if the terminal is not in the current window or if it's focused, - // adjust topline/cursor so the window will "follow" the terminal - // output - wp->w_cursor.lnum = buf->b_ml.ml_line_count; + linenr_T ml_end = buf->b_ml.ml_line_count; + bool following = ml_end == wp->w_cursor.lnum + added; // cursor at end? + + if (following || (wp == curwin && is_focused(term))) { + // "Follow" the terminal output + wp->w_cursor.lnum = ml_end; set_topline(wp, MAX(wp->w_cursor.lnum - height + 1, 1)); + } else { + // Ensure valid cursor for each window displaying this terminal. + wp->w_cursor.lnum = MIN(wp->w_cursor.lnum, ml_end); } + mb_check_adjust_col(wp); } } } @@ -1251,12 +1324,14 @@ static bool is_focused(Terminal *term) #define GET_CONFIG_VALUE(k, o) \ do { \ - Error err; \ + Error err = ERROR_INIT; \ /* Only called from terminal_open where curbuf->terminal is the */ \ /* context */ \ o = dict_get_value(curbuf->b_vars, cstr_as_string(k), &err); \ + api_clear_error(&err); \ if (o.type == kObjectTypeNil) { \ o = dict_get_value(&globvardict, cstr_as_string(k), &err); \ + api_clear_error(&err); \ } \ } while (0) @@ -1271,17 +1346,6 @@ static char *get_config_string(char *key) return NULL; } -static int get_config_int(char *key) -{ - Object obj; - GET_CONFIG_VALUE(key, obj); - if (obj.type == kObjectTypeInteger) { - return (int)obj.data.integer; - } - api_free_object(obj); - return 0; -} - // }}} // vim: foldmethod=marker diff --git a/src/nvim/testdir/Makefile b/src/nvim/testdir/Makefile index 814c0bc3cb..96de7224c5 100644 --- a/src/nvim/testdir/Makefile +++ b/src/nvim/testdir/Makefile @@ -1,14 +1,16 @@ -# +# vim: noet ts=8 # Makefile to run all tests for Vim # -export SHELL := sh - -VIMPROG := ../../../build/bin/nvim +NVIM_PRG ?= ../../../build/bin/nvim +TMPDIR ?= Xtest-tmpdir SCRIPTSOURCE := ../../../runtime -SCRIPTS := \ - test8.out \ +export SHELL := sh +export NVIM_PRG := $(NVIM_PRG) +export TMPDIR + +SCRIPTS ?= \ test13.out \ test14.out \ test17.out \ @@ -22,33 +24,60 @@ SCRIPTS := \ test52.out \ test53.out \ test64.out \ - test69.out \ test73.out \ test79.out \ - test_marks.out \ -# Tests using runtest.vim.vim. +# Tests using runtest.vim. # Keep test_alot*.res as the last one, sort the others. -NEW_TESTS = \ +NEW_TESTS ?= \ + test_autocmd.res \ test_bufwintabinfo.res \ + test_charsearch.res \ test_cmdline.res \ + test_command_count.res \ test_cscope.res \ + test_digraph.res \ test_diffmode.res \ + test_farsi.res \ + test_filter_map.res \ + test_fnameescape.res \ + test_fold.res \ + test_glob2regpat.res \ + test_gf.res \ test_gn.res \ test_hardcopy.res \ test_help_tagjump.res \ + test_hide.res \ test_history.res \ + test_hlsearch.res \ + test_increment.res \ + test_increment_dbcs.res \ + test_lambda.res \ test_langmap.res \ + test_marks.res \ test_match.res \ test_matchadd_conceal.res \ + test_matchadd_conceal_utf8.res \ + test_nested_function.res \ + test_normal.res \ test_quickfix.res \ + test_search.res \ test_signs.res \ + test_smartindent.res \ + test_stat.res \ + test_startup.res \ + test_startup_utf8.res \ + test_substitute.res \ test_syntax.res \ + test_tabpage.res \ + test_textobjects.res \ test_timers.res \ + test_undo.res \ test_usercommands.res \ - test_viml.res \ + test_vimscript.res \ test_visual.res \ test_window_id.res \ + test_writefile.res \ test_alot.res SCRIPTS_GUI := test16.out @@ -100,13 +129,13 @@ report: echo ALL DONE; \ fi" -test1.out: $(VIMPROG) +test1.out: $(NVIM_PRG) -$(SCRIPTS) $(SCRIPTS_GUI): $(VIMPROG) test1.out +$(SCRIPTS) $(SCRIPTS_GUI): $(NVIM_PRG) test1.out RM_ON_RUN := test.out X* viminfo RM_ON_START := test.ok -RUN_VIM := VIMRUNTIME=$(SCRIPTSOURCE); export VIMRUNTIME; $(TOOL) $(VIMPROG) -u unix.vim -U NONE -i viminfo --noplugin -s dotest.in +RUN_VIM := VIMRUNTIME=$(SCRIPTSOURCE); export VIMRUNTIME; $(TOOL) $(NVIM_PRG) -u unix.vim -U NONE -i viminfo --headless --noplugin -s dotest.in clean: -rm -rf *.out \ @@ -122,10 +151,12 @@ clean: .*.swp \ .*.swo \ .gdbinit \ + $(TMPDIR) \ del test1.out: .gdbinit test1.in -rm -rf $*.failed $(RM_ON_RUN) $(RM_ON_START) wrongtermsize + mkdir -p $(TMPDIR) $(RUN_VIM) $*.in @/bin/sh -c "if test -e wrongtermsize; then \ echo; \ @@ -143,6 +174,7 @@ test1.out: .gdbinit test1.in %.out: %.in .gdbinit -rm -rf $*.failed test.ok $(RM_ON_RUN) + mkdir -p $(TMPDIR) cp $*.ok test.ok # Sleep a moment to avoid that the xterm title is messed up. # 200 msec is sufficient, but only modern sleep supports a fraction of @@ -175,7 +207,7 @@ nolog: # New style of tests uses Vim script with assert calls. These are easier # to write and a lot easier to read and debug. # Limitation: Only works with the +eval feature. -RUN_VIMTEST = VIMRUNTIME=$(SCRIPTSOURCE); export VIMRUNTIME; $(VALGRIND) $(VIMPROG) -u unix.vim -U NONE --noplugin +RUN_VIMTEST = VIMRUNTIME=$(SCRIPTSOURCE); export VIMRUNTIME; $(TOOL) $(NVIM_PRG) -u unix.vim -U NONE --headless --noplugin newtests: newtestssilent @/bin/sh -c "if test -f messages && grep -q 'FAILED' messages; then \ @@ -185,4 +217,5 @@ newtests: newtestssilent newtestssilent: $(NEW_TESTS) %.res: %.vim .gdbinit + mkdir -p $(TMPDIR) $(RUN_VIMTEST) -u NONE -S runtest.vim $*.vim diff --git a/src/nvim/testdir/runtest.vim b/src/nvim/testdir/runtest.vim index 20863bbaf3..39ffabc024 100644 --- a/src/nvim/testdir/runtest.vim +++ b/src/nvim/testdir/runtest.vim @@ -39,6 +39,9 @@ if &lines < 24 || &columns < 80 cquit endif +" Common with all tests on all systems. +source setup.vim + " This also enables use of line continuation. set viminfo+=nviminfo @@ -62,14 +65,25 @@ set shellslash " Make sure $HOME does not get read or written. let $HOME = '/does/not/exist' -" Align with vim defaults. +" Prepare for calling garbagecollect_for_testing(). +let v:testing = 1 + +" Align Nvim defaults to Vim. set directory^=. -set nohidden +set backspace= +set nohidden smarttab noautoindent noautoread complete-=i noruler noshowcmd +set listchars=eol:$ +" Prevent Nvim log from writing to stderr. +let $NVIM_LOG_FILE = exists($NVIM_LOG_FILE) ? $NVIM_LOG_FILE : 'Xnvim.log' -function RunTheTest(test) +func RunTheTest(test) echo 'Executing ' . a:test if exists("*SetUp") - call SetUp() + try + call SetUp() + catch + call add(v:errors, 'Caught exception in SetUp() before ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint) + endtry endif call add(s:messages, 'Executing ' . a:test) @@ -84,16 +98,83 @@ function RunTheTest(test) endtry if exists("*TearDown") - call TearDown() + try + call TearDown() + catch + call add(v:errors, 'Caught exception in TearDown() after ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint) + endtry endif " Close any extra windows and make the current one not modified. - while winnr('$') > 1 + while 1 + let wincount = winnr('$') + if wincount == 1 + break + endif bwipe! + if wincount == winnr('$') + " Did not manage to close a window. + only! + break + endif endwhile set nomodified endfunc +func AfterTheTest() + if len(v:errors) > 0 + let s:fail += 1 + call add(s:errors, 'Found errors in ' . s:test . ':') + call extend(s:errors, v:errors) + let v:errors = [] + endif +endfunc + +" This function can be called by a test if it wants to abort testing. +func FinishTesting() + call AfterTheTest() + + " Don't write viminfo on exit. + set viminfo= + + if s:fail == 0 + " Success, create the .res file so that make knows it's done. + exe 'split ' . fnamemodify(g:testname, ':r') . '.res' + write + endif + + if len(s:errors) > 0 + " Append errors to test.log + split test.log + call append(line('$'), '') + call append(line('$'), 'From ' . g:testname . ':') + call append(line('$'), s:errors) + write + endif + + let message = 'Executed ' . s:done . (s:done > 1 ? ' tests' : ' test') + echo message + call add(s:messages, message) + if s:fail > 0 + let message = s:fail . ' FAILED:' + echo message + call add(s:messages, message) + call extend(s:messages, s:errors) + endif + + " Add SKIPPED messages + call extend(s:messages, s:skipped) + + " Append messages to the file "messages" + split messages + call append(line('$'), '') + call append(line('$'), 'From ' . g:testname . ':') + call append(line('$'), s:messages) + write + + qall! +endfunc + " Source the test script. First grab the file name, in case the script " navigates away. g:testname can be used by the tests. let g:testname = expand('%') @@ -102,7 +183,7 @@ let s:fail = 0 let s:errors = [] let s:messages = [] let s:skipped = [] -if expand('%') =~ 'test_viml.vim' +if expand('%') =~ 'test_vimscript.vim' " this test has intentional s:errors, don't use try/catch. source % else @@ -115,7 +196,11 @@ else endif " Names of flaky tests. -let s:flaky = [] +let s:flaky = [ + \ 'Test_with_partial_callback()', + \ 'Test_oneshot()', + \ 'Test_lambda_with_timer()', + \ ] " Locate Test_ functions and execute them. set nomore @@ -134,56 +219,14 @@ for s:test in sort(s:tests) call RunTheTest(s:test) if len(v:errors) > 0 && index(s:flaky, s:test) >= 0 - call add(s:messages, 'Flaky test failed, running it again') - let v:errors = [] - call RunTheTest(s:test) - endif - - if len(v:errors) > 0 - let s:fail += 1 - call add(s:errors, 'Found errors in ' . s:test . ':') - call extend(s:errors, v:errors) + call add(s:messages, 'Flaky test failed, running it again') let v:errors = [] + call RunTheTest(s:test) endif + call AfterTheTest() endfor -" Don't write viminfo on exit. -set viminfo= - -if s:fail == 0 - " Success, create the .res file so that make knows it's done. - exe 'split ' . fnamemodify(g:testname, ':r') . '.res' - write -endif - -if len(s:errors) > 0 - " Append errors to test.log - split test.log - call append(line('$'), '') - call append(line('$'), 'From ' . g:testname . ':') - call append(line('$'), s:errors) - write -endif - -let message = 'Executed ' . s:done . (s:done > 1 ? ' tests': ' test') -echo message -call add(s:messages, message) -if s:fail > 0 - let message = s:fail . ' FAILED' - echo message - call add(s:messages, message) - call extend(s:messages, s:errors) -endif - -" Add SKIPPED messages -call extend(s:messages, s:skipped) - -" Append messages to the file "messages" -split messages -call append(line('$'), '') -call append(line('$'), 'From ' . g:testname . ':') -call append(line('$'), s:messages) -write +call FinishTesting() -qall! +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/samples/memfile_test.c b/src/nvim/testdir/samples/memfile_test.c new file mode 100644 index 0000000000..3c8f108255 --- /dev/null +++ b/src/nvim/testdir/samples/memfile_test.c @@ -0,0 +1,146 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + +/* vi:set ts=8 sts=4 sw=4 noet: + * + * VIM - Vi IMproved by Bram Moolenaar + * + * Do ":help uganda" in Vim to read copying and usage conditions. + * Do ":help credits" in Vim to see a list of people who contributed. + * See README.txt for an overview of the Vim source code. + */ + +/* + * memfile_test.c: Unittests for memfile.c + * Mostly by Ivan Krasilnikov. + */ + +#undef NDEBUG +#include <assert.h> + +/* Must include main.c because it contains much more than just main() */ +#define NO_VIM_MAIN +#include "main.c" + +/* This file has to be included because the tested functions are static */ +#include "memfile.c" + +#define index_to_key(i) ((i) ^ 15167) +#define TEST_COUNT 50000 + +/* + * Test mf_hash_*() functions. + */ + static void +test_mf_hash(void) +{ + mf_hashtab_T ht; + mf_hashitem_T *item; + blocknr_T key; + long_u i; + long_u num_buckets; + + mf_hash_init(&ht); + + /* insert some items and check invariants */ + for (i = 0; i < TEST_COUNT; i++) + { + assert(ht.mht_count == i); + + /* check that number of buckets is a power of 2 */ + num_buckets = ht.mht_mask + 1; + assert(num_buckets > 0 && (num_buckets & (num_buckets - 1)) == 0); + + /* check load factor */ + assert(ht.mht_count <= (num_buckets << MHT_LOG_LOAD_FACTOR)); + + if (i < (MHT_INIT_SIZE << MHT_LOG_LOAD_FACTOR)) + { + /* first expansion shouldn't have occurred yet */ + assert(num_buckets == MHT_INIT_SIZE); + assert(ht.mht_buckets == ht.mht_small_buckets); + } + else + { + assert(num_buckets > MHT_INIT_SIZE); + assert(ht.mht_buckets != ht.mht_small_buckets); + } + + key = index_to_key(i); + assert(mf_hash_find(&ht, key) == NULL); + + /* allocate and add new item */ + item = (mf_hashitem_T *)lalloc_clear(sizeof(mf_hashtab_T), FALSE); + assert(item != NULL); + item->mhi_key = key; + mf_hash_add_item(&ht, item); + + assert(mf_hash_find(&ht, key) == item); + + if (ht.mht_mask + 1 != num_buckets) + { + /* hash table was expanded */ + assert(ht.mht_mask + 1 == num_buckets * MHT_GROWTH_FACTOR); + assert(i + 1 == (num_buckets << MHT_LOG_LOAD_FACTOR)); + } + } + + /* check presence of inserted items */ + for (i = 0; i < TEST_COUNT; i++) + { + key = index_to_key(i); + item = mf_hash_find(&ht, key); + assert(item != NULL); + assert(item->mhi_key == key); + } + + /* delete some items */ + for (i = 0; i < TEST_COUNT; i++) + { + if (i % 100 < 70) + { + key = index_to_key(i); + item = mf_hash_find(&ht, key); + assert(item != NULL); + assert(item->mhi_key == key); + + mf_hash_rem_item(&ht, item); + assert(mf_hash_find(&ht, key) == NULL); + + mf_hash_add_item(&ht, item); + assert(mf_hash_find(&ht, key) == item); + + mf_hash_rem_item(&ht, item); + assert(mf_hash_find(&ht, key) == NULL); + + vim_free(item); + } + } + + /* check again */ + for (i = 0; i < TEST_COUNT; i++) + { + key = index_to_key(i); + item = mf_hash_find(&ht, key); + + if (i % 100 < 70) + { + assert(item == NULL); + } + else + { + assert(item != NULL); + assert(item->mhi_key == key); + } + } + + /* free hash table and all remaining items */ + mf_hash_free_all(&ht); +} + + int +main(void) +{ + test_mf_hash(); + return 0; +} diff --git a/src/nvim/testdir/setup.vim b/src/nvim/testdir/setup.vim new file mode 100644 index 0000000000..06f2199214 --- /dev/null +++ b/src/nvim/testdir/setup.vim @@ -0,0 +1,12 @@ +" Common preparations for running tests. + +set noruler +set noshowcmd +set belloff= + +" Make sure 'runtimepath' and 'packpath' does not include $HOME. +set rtp=$VIM/vimfiles,$VIMRUNTIME,$VIM/vimfiles/after +let &packpath = &rtp + +" Make sure $HOME does not get read or written. +let $HOME = '/does/not/exist' diff --git a/src/nvim/testdir/shared.vim b/src/nvim/testdir/shared.vim new file mode 100644 index 0000000000..72cfea96c6 --- /dev/null +++ b/src/nvim/testdir/shared.vim @@ -0,0 +1,214 @@ +" Functions shared by several tests. + +" Get the name of the Python executable. +" Also keeps it in s:python. +func PythonProg() + " This test requires the Python command to run the test server. + " This most likely only works on Unix and Windows. + if has('unix') + " We also need the job feature or the pkill command to make sure the server + " can be stopped. + if !(executable('python') && (has('job') || executable('pkill'))) + return '' + endif + let s:python = 'python' + elseif has('win32') + " Use Python Launcher for Windows (py.exe) if available. + if executable('py.exe') + let s:python = 'py.exe' + elseif executable('python.exe') + let s:python = 'python.exe' + else + return '' + endif + else + return '' + endif + return s:python +endfunc + +" Run "cmd". Returns the job if using a job. +func RunCommand(cmd) + let job = 0 + if has('job') + let job = job_start(a:cmd, {"stoponexit": "hup"}) + call job_setoptions(job, {"stoponexit": "kill"}) + elseif has('win32') + exe 'silent !start cmd /c start "test_channel" ' . a:cmd + else + exe 'silent !' . a:cmd . '&' + endif + return job +endfunc + +" Read the port number from the Xportnr file. +func GetPort() + let l = [] + for i in range(200) + try + let l = readfile("Xportnr") + catch + endtry + if len(l) >= 1 + break + endif + sleep 10m + endfor + call delete("Xportnr") + + if len(l) == 0 + " Can't make the connection, give up. + return 0 + endif + return l[0] +endfunc + +" Run a Python server for "cmd" and call "testfunc". +" Always kills the server before returning. +func RunServer(cmd, testfunc, args) + " The Python program writes the port number in Xportnr. + call delete("Xportnr") + + if len(a:args) == 1 + let arg = ' ' . a:args[0] + else + let arg = '' + endif + let pycmd = s:python . " " . a:cmd . arg + + try + let g:currentJob = RunCommand(pycmd) + + " Wait for up to 2 seconds for the port number to be there. + let port = GetPort() + if port == 0 + call assert_false(1, "Can't start " . a:cmd) + return + endif + + call call(function(a:testfunc), [port]) + catch + call assert_false(1, 'Caught exception: "' . v:exception . '" in ' . v:throwpoint) + finally + call s:kill_server(a:cmd) + endtry +endfunc + +func s:kill_server(cmd) + if has('job') + if exists('g:currentJob') + call job_stop(g:currentJob) + unlet g:currentJob + endif + elseif has('win32') + let cmd = substitute(a:cmd, ".py", '', '') + call system('taskkill /IM ' . s:python . ' /T /F /FI "WINDOWTITLE eq ' . cmd . '"') + else + call system("pkill -f " . a:cmd) + endif +endfunc + +" Wait for up to a second for "expr" to become true. +" Return time slept in milliseconds. With the +reltime feature this can be +" more than the actual waiting time. Without +reltime it can also be less. +func WaitFor(expr) + " using reltime() is more accurate, but not always available + if has('reltime') + let start = reltime() + else + let slept = 0 + endif + for i in range(100) + try + if eval(a:expr) + if has('reltime') + return float2nr(reltimefloat(reltime(start)) * 1000) + endif + return slept + endif + catch + endtry + if !has('reltime') + let slept += 10 + endif + sleep 10m + endfor + return 1000 +endfunc + +" Wait for up to a given milliseconds. +" With the +timers feature this waits for key-input by getchar(), Resume() +" feeds key-input and resumes process. Return time waited in milliseconds. +" Without +timers it uses simply :sleep. +func Standby(msec) + if has('timers') + let start = reltime() + let g:_standby_timer = timer_start(a:msec, function('s:feedkeys')) + call getchar() + return float2nr(reltimefloat(reltime(start)) * 1000) + else + execute 'sleep ' a:msec . 'm' + return a:msec + endif +endfunc + +func Resume() + if exists('g:_standby_timer') + call timer_stop(g:_standby_timer) + call s:feedkeys(0) + unlet g:_standby_timer + endif +endfunc + +func s:feedkeys(timer) + call feedkeys('x', 'nt') +endfunc + +" Get the command to run Vim, with -u NONE and --headless arguments. +" Returns an empty string on error. +func GetVimCommand() + let cmd = v:progpath + let cmd = substitute(cmd, '-u \f\+', '-u NONE', '') + if cmd !~ '-u NONE' + let cmd = cmd . ' -u NONE' + endif + let cmd .= ' --headless -i NONE' + let cmd = substitute(cmd, 'VIMRUNTIME=.*VIMRUNTIME;', '', '') + return cmd +endfunc + +" Run Vim, using the "vimcmd" file and "-u NORC". +" "before" is a list of Vim commands to be executed before loading plugins. +" "after" is a list of Vim commands to be executed after loading plugins. +" Plugins are not loaded, unless 'loadplugins' is set in "before". +" Return 1 if Vim could be executed. +func RunVim(before, after, arguments) + return RunVimPiped(a:before, a:after, a:arguments, '') +endfunc + +func RunVimPiped(before, after, arguments, pipecmd) + let $NVIM_LOG_FILE = exists($NVIM_LOG_FILE) ? $NVIM_LOG_FILE : 'Xnvim.log' + let cmd = GetVimCommand() + if cmd == '' + return 0 + endif + let args = '' + if len(a:before) > 0 + call writefile(a:before, 'Xbefore.vim') + let args .= ' --cmd "so Xbefore.vim"' + endif + if len(a:after) > 0 + call writefile(a:after, 'Xafter.vim') + let args .= ' -S Xafter.vim' + endif + + exe "silent !" . a:pipecmd . cmd . args . ' ' . a:arguments + + if len(a:before) > 0 + call delete('Xbefore.vim') + endif + if len(a:after) > 0 + call delete('Xafter.vim') + endif + return 1 +endfunc diff --git a/src/nvim/testdir/test13.in b/src/nvim/testdir/test13.in deleted file mode 100644 index fa9ba312b7..0000000000 --- a/src/nvim/testdir/test13.in +++ /dev/null @@ -1,63 +0,0 @@ -Tests for autocommands on :close command - -Write three files and open them, each in a window. -Then go to next window, with autocommand that deletes the previous one. -Do this twice, writing the file. - -Also test deleting the buffer on a Unload event. If this goes wrong there -will be the ATTENTION prompt. - -Also test changing buffers in a BufDel autocommand. If this goes wrong there -are ml_line errors and/or a Crash. - -STARTTEST -:/^start of testfile/,/^end of testfile/w! Xtestje1 -:/^start of testfile/,/^end of testfile/w! Xtestje2 -:/^start of testfile/,/^end of testfile/w! Xtestje3 -:e Xtestje1 -otestje1 -:w -:sp Xtestje2 -otestje2 -:w -:sp Xtestje3 -otestje3 -:w - -:au WinLeave Xtestje2 bwipe - -:w! test.out -:au WinLeave Xtestje1 bwipe Xtestje3 -:close -:w >>test.out -:e Xtestje1 -:bwipe Xtestje2 Xtestje3 test.out -:au! -:au! BufUnload Xtestje1 bwipe -:e Xtestje3 -:w >>test.out -:e Xtestje2 -:sp Xtestje1 -:e -:w >>test.out -:au! -:only -:e Xtestje1 -:bwipe Xtestje2 Xtestje3 test.out test13.in -:au BufWipeout Xtestje1 buf Xtestje1 -:bwipe -:w >>test.out -:only -:new|set buftype=help -:wincmd w -:1quit -:$put ='Final line' -:$w >>test.out -:qa! -ENDTEST - -start of testfile - contents - contents - contents -end of testfile diff --git a/src/nvim/testdir/test13.ok b/src/nvim/testdir/test13.ok deleted file mode 100644 index 66ebce63f7..0000000000 --- a/src/nvim/testdir/test13.ok +++ /dev/null @@ -1,31 +0,0 @@ -start of testfile -testje1 - contents - contents - contents -end of testfile -start of testfile -testje1 - contents - contents - contents -end of testfile -start of testfile -testje3 - contents - contents - contents -end of testfile -start of testfile -testje2 - contents - contents - contents -end of testfile -start of testfile -testje1 - contents - contents - contents -end of testfile -Final line diff --git a/src/nvim/testdir/test17.in b/src/nvim/testdir/test17.in index 83abe17770..1a4ac6b6d1 100644 --- a/src/nvim/testdir/test17.in +++ b/src/nvim/testdir/test17.in @@ -4,13 +4,7 @@ Tests for: STARTTEST :set isfname=@,48-57,/,.,-,_,+,,,$,:,~,{,} -:function! DeleteDirectory(dir) -: if has("win16") || has("win32") || has("win64") || has("dos16") || has("dos32") -: exec "silent !rmdir /Q /S " . a:dir -: else -: exec "silent !rm -rf " . a:dir -: endif -:endfun +:" :if has("unix") :let $CDIR = "." /CDIR @@ -36,7 +30,7 @@ STARTTEST :" check for 'include' without \zs or \ze :lang C :call delete("./Xbase.a") -:call DeleteDirectory("Xdir1") +:call delete("Xdir1", "rf") :!mkdir Xdir1 :!mkdir "Xdir1/dir2" :e! Xdir1/dir2/foo.a @@ -61,7 +55,7 @@ ENDTEST STARTTEST :" check for 'include' with \zs and \ze :call delete("./Xbase.b") -:call DeleteDirectory("Xdir1") +:call delete("Xdir1", "rf") :!mkdir Xdir1 :!mkdir "Xdir1/dir2" :let &include='^\s*%inc\s*/\zs[^/]\+\ze' @@ -91,7 +85,7 @@ ENDTEST STARTTEST :" check for 'include' with \zs and no \ze :call delete("./Xbase.c") -:call DeleteDirectory("Xdir1") +:call delete("Xdir1", "rf") :!mkdir Xdir1 :!mkdir "Xdir1/dir2" :let &include='^\s*%inc\s*\%([[:upper:]][^[:space:]]*\s\+\)\?\zs\S\+\ze' diff --git a/src/nvim/testdir/test49.vim b/src/nvim/testdir/test49.vim index edd49a2b63..467abcd9b9 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 -es" . redirect . + exec "!echo '" . debug_quits . "q' | $NVIM_PRG -u NONE -N -es" . redirect . \ " -c 'debuggreedy|set viminfo+=nviminfo'" . \ " -c 'let ExtraVimBegin = " . extra_begin . "'" . \ " -c 'let ExtraVimResult = \"" . resultfile . "\"'" . breakpoints . @@ -608,7 +608,7 @@ com! -nargs=1 -bar ExecAsScript call ExecAsScript(<f-args>) " END_OF_TEST_ENVIRONMENT - do not change or remove this line. -" Tests 1 to 15 were moved to test_viml.vim +" Tests 1 to 15 were moved to test_vimscript.vim let Xtest = 16 "------------------------------------------------------------------------------- diff --git a/src/nvim/testdir/test69.in b/src/nvim/testdir/test69.in deleted file mode 100644 index 39b360fc81..0000000000 --- a/src/nvim/testdir/test69.in +++ /dev/null @@ -1,191 +0,0 @@ -Test for multi-byte text formatting. -Also test, that 'mps' with multibyte chars works. -And test "ra" on multi-byte characters. -Also test byteidx() and byteidxcomp() - -STARTTEST -: -ENDTEST - -Results of test69: - -STARTTEST -/^{/+1 -:set tw=2 fo=t -gqgqjgqgqo -๏ผธ๏ผน๏ผบ -abc ๏ผธ๏ผน๏ผบ -ENDTEST - -{ -๏ผธ๏ผน๏ผบ -abc ๏ผธ๏ผน๏ผบ -} - -STARTTEST -/^{/+1 -:set tw=1 fo=tm -gqgqjgqgqjgqgqjgqgqjgqgqo -๏ผธ -๏ผธa -๏ผธ a -๏ผธ๏ผน -๏ผธ ๏ผน -ENDTEST - -{ -๏ผธ -๏ผธa -๏ผธ a -๏ผธ๏ผน -๏ผธ ๏ผน -} - -STARTTEST -/^{/+1 -:set tw=2 fo=tm -gqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqo -๏ผธ -๏ผธa -๏ผธ a -๏ผธ๏ผน -๏ผธ ๏ผน -a๏ผธ -ab๏ผธ -abc๏ผธ -ab๏ผธ c -ab๏ผธ๏ผน -ENDTEST - -{ -๏ผธ -๏ผธa -๏ผธ a -๏ผธ๏ผน -๏ผธ ๏ผน -a๏ผธ -ab๏ผธ -abc๏ผธ -ab๏ผธ c -ab๏ผธ๏ผน -} - -STARTTEST -/^{/+1 -:set ai tw=2 fo=tm -gqgqjgqgqo -๏ผธ -๏ผธa -ENDTEST - -{ - ๏ผธ - ๏ผธa -} - -STARTTEST -/^{/+1 -:set noai tw=2 fo=tm -gqgqjgqgqo - ๏ผธ - ๏ผธa -ENDTEST - -{ - ๏ผธ - ๏ผธa -} - -STARTTEST -/^{/+1 -:set tw=2 fo=cqm comments=n:๏ผธ -gqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqo -๏ผธ -๏ผธa -๏ผธa๏ผน -๏ผธ๏ผน -๏ผธ๏ผน๏ผบ -๏ผธ ๏ผน -๏ผธ ๏ผน๏ผบ -๏ผธ๏ผธ -๏ผธ๏ผธa -๏ผธ๏ผธ๏ผน -ENDTEST - -{ -๏ผธ -๏ผธa -๏ผธa๏ผน -๏ผธ๏ผน -๏ผธ๏ผน๏ผบ -๏ผธ ๏ผน -๏ผธ ๏ผน๏ผบ -๏ผธ๏ผธ -๏ผธ๏ผธa -๏ผธ๏ผธ๏ผน -} - -STARTTEST -/^{/+1 -:set tw=2 fo=tm -R๏ผธa -ENDTEST - -{ - -} - -STARTTEST -/^{/+1 -:set mps+=u2018:u2019 -d% -ENDTEST - -{ -โ two three โ four -} -STARTTEST -/^ra test -jVjra -ENDTEST - -ra test -๏ฝbb๏ฝ -๏ฝ๏ฝb - -STARTTEST -:set whichwrap+=h -/^x -dh -:set whichwrap-=h -ENDTEST - -รก -x - -STARTTEST -:let a = '.รฉ.' " one char of two bytes -:let b = '.eฬ.' " normal e with composing char -/^byteidx -:put =string([byteidx(a, 0), byteidx(a, 1), byteidx(a, 2), byteidx(a, 3), byteidx(a, 4)]) -:put =string([byteidx(b, 0), byteidx(b, 1), byteidx(b, 2), byteidx(b, 3), byteidx(b, 4)]) -/^byteidxcomp -:put =string([byteidxcomp(a, 0), byteidxcomp(a, 1), byteidxcomp(a, 2), byteidxcomp(a, 3), byteidxcomp(a, 4)]) -:let b = '.eฬ.' -:put =string([byteidxcomp(b, 0), byteidxcomp(b, 1), byteidxcomp(b, 2), byteidxcomp(b, 3), byteidxcomp(b, 4), byteidxcomp(b, 5)]) -ENDTEST - -byteidx -byteidxcomp - -STARTTEST -/^substitute -:let y = substitute('๏ผ๏ผ๏ผ', '\zs', 'a', 'g') | put =y -ENDTEST - -substitute - -STARTTEST -:g/^STARTTEST/.,/^ENDTEST/d -:1;/^Results/,$wq! test.out -ENDTEST diff --git a/src/nvim/testdir/test69.ok b/src/nvim/testdir/test69.ok deleted file mode 100644 index af8befb0c7..0000000000 --- a/src/nvim/testdir/test69.ok +++ /dev/null @@ -1,166 +0,0 @@ -Results of test69: - - -{ -๏ผธ๏ผน๏ผบ -abc -๏ผธ๏ผน๏ผบ - -๏ผธ๏ผน๏ผบ -abc -๏ผธ๏ผน๏ผบ -} - - -{ -๏ผธ -๏ผธ -a -๏ผธ -a -๏ผธ -๏ผน -๏ผธ -๏ผน - -๏ผธ -๏ผธ -a -๏ผธ -a -๏ผธ -๏ผน -๏ผธ -๏ผน -} - - -{ -๏ผธ -๏ผธ -a -๏ผธ -a -๏ผธ -๏ผน -๏ผธ -๏ผน -a -๏ผธ -ab -๏ผธ -abc -๏ผธ -ab -๏ผธ -c -ab -๏ผธ -๏ผน - -๏ผธ -๏ผธ -a -๏ผธ -a -๏ผธ -๏ผน -๏ผธ -๏ผน -a -๏ผธ -ab -๏ผธ -abc -๏ผธ -ab -๏ผธ -c -ab -๏ผธ -๏ผน -} - - -{ - ๏ผธ - ๏ผธ - a - - ๏ผธ - ๏ผธ - a -} - - -{ - ๏ผธ - ๏ผธ -a - - ๏ผธ - ๏ผธ -a -} - - -{ -๏ผธ -๏ผธa -๏ผธa -๏ผธ๏ผน -๏ผธ๏ผน -๏ผธ๏ผน -๏ผธ๏ผบ -๏ผธ ๏ผน -๏ผธ ๏ผน -๏ผธ ๏ผบ -๏ผธ๏ผธ -๏ผธ๏ผธa -๏ผธ๏ผธ๏ผน - -๏ผธ -๏ผธa -๏ผธa -๏ผธ๏ผน -๏ผธ๏ผน -๏ผธ๏ผน -๏ผธ๏ผบ -๏ผธ ๏ผน -๏ผธ ๏ผน -๏ผธ ๏ผบ -๏ผธ๏ผธ -๏ผธ๏ผธa -๏ผธ๏ผธ๏ผน -} - - -{ -๏ผธ -a -} - - -{ - four -} - -ra test -aaaa -aaa - - -รกx - - -byteidx -[0, 1, 3, 4, -1] -[0, 1, 4, 5, -1] -byteidxcomp -[0, 1, 3, 4, -1] -[0, 1, 2, 4, 5, -1] - - -substitute -a๏ผa๏ผa๏ผa - diff --git a/src/nvim/testdir/test73.in b/src/nvim/testdir/test73.in index 7d6c7287a5..9d50f7a789 100644 --- a/src/nvim/testdir/test73.in +++ b/src/nvim/testdir/test73.in @@ -8,16 +8,9 @@ STARTTEST :" This will cause a few errors, do it silently. :set visualbell :" -:function! DeleteDirectory(dir) -: if has("win16") || has("win32") || has("win64") || has("dos16") || has("dos32") -: exec "silent !rmdir /Q /S " . a:dir -: else -: exec "silent !rm -rf " . a:dir -: endif -:endfun :" On windows a stale "Xfind" directory may exist, remove it so that :" we start from a clean state. -:call DeleteDirectory("Xfind") +:call delete("Xfind", "rf") :new :let cwd=getcwd() :let test_out = cwd . '/test.out' @@ -169,7 +162,7 @@ SVoyager 2:w :exec "w >>" . test_out :q :exec "cd " . cwd -:call DeleteDirectory("Xfind") +:call delete("Xfind", "rf") :qa! ENDTEST diff --git a/src/nvim/testdir/test8.in b/src/nvim/testdir/test8.in deleted file mode 100644 index a5e6034782..0000000000 --- a/src/nvim/testdir/test8.in +++ /dev/null @@ -1,43 +0,0 @@ -Test for BufWritePre autocommand that deletes or unloads the buffer. -Test for BufUnload autocommand that unloads all other buffers. - -STARTTEST -:au BufWritePre Xxx1 bunload -:au BufWritePre Xxx2 bwipe -/^start of -A1:.,/end of/w! Xxx1 " write test file Xxx1 -$r2:.,/end of/w! Xxx2 " write test file Xxx2 -:e! Xxx2 " edit Xxx2 -:bdel test8.in " delete this file from the buffer list -:e Xxx1 " edit Xxx1 -:w " write it, will unload it and give an error msg -:w! test.out " Write contents of this file -:e! Xxx2 " start editing Xxx2 -:bwipe test.out " remove test.out from the buffer list -:w " write it, will delete the buffer and give an error msg -:w >>test.out " Append contents of this file -:au! BufWritePre -:func CloseAll() - let i = 0 - while i <= bufnr('$') - if i != bufnr('%') && bufloaded(i) - exe i . "bunload" - endif - let i += 1 - endwhile -endfunc -:func WriteToOut() - edit! test.out - $put ='VimLeave done' - write -endfunc -:set shada='100 -:au BufUnload * call CloseAll() -:au VimLeave * call WriteToOut() -:q -:qa! -ENDTEST - -start of Xxx - test -end of Xxx diff --git a/src/nvim/testdir/test8.ok b/src/nvim/testdir/test8.ok deleted file mode 100644 index adecb2f4be..0000000000 --- a/src/nvim/testdir/test8.ok +++ /dev/null @@ -1,7 +0,0 @@ -start of Xxx2 - test -end of Xxx -start of Xxx1 - test -end of Xxx -VimLeave done diff --git a/src/nvim/testdir/test_alot.vim b/src/nvim/testdir/test_alot.vim index 60248bf430..d55170c27c 100644 --- a/src/nvim/testdir/test_alot.vim +++ b/src/nvim/testdir/test_alot.vim @@ -2,27 +2,36 @@ " This makes testing go faster, since Vim doesn't need to restart. source test_assign.vim -source test_autocmd.vim source test_cursor_func.vim source test_execute_func.vim source test_ex_undo.vim source test_expr.vim source test_expr_utf8.vim source test_feedkeys.vim +source test_filter_cmd.vim +source test_filter_map.vim +source test_float_func.vim +source test_functions.vim source test_goto.vim source test_jumps.vim -source test_match.vim -source test_matchadd_conceal_utf8.vim +source test_fileformat.vim +source test_lambda.vim source test_menu.vim +source test_mapping.vim source test_messages.vim source test_options.vim source test_partial.vim source test_popup.vim source test_regexp_utf8.vim +source test_source_utf8.vim source test_statusline.vim source test_syn_attr.vim source test_tabline.vim -source test_tabpage.vim +" source test_tabpage.vim +source test_tagcase.vim source test_tagjump.vim +source test_taglist.vim +source test_true_false.vim source test_unlet.vim +source test_utf8.vim source test_window_cmd.vim diff --git a/src/nvim/testdir/test_autocmd.vim b/src/nvim/testdir/test_autocmd.vim index 5675697dc4..835df42a10 100644 --- a/src/nvim/testdir/test_autocmd.vim +++ b/src/nvim/testdir/test_autocmd.vim @@ -1,5 +1,15 @@ " Tests for autocommands +set belloff=all + +function! s:cleanup_buffers() abort + for bnr in range(1, bufnr('$')) + if bufloaded(bnr) && bufnr('%') != bnr + execute 'bd! ' . bnr + endif + endfor +endfunction + func Test_vim_did_enter() call assert_false(v:vim_did_enter) @@ -13,6 +23,9 @@ if has('timers') endfunc func Test_cursorhold_insert() + " Need to move the cursor. + call feedkeys("ggG", "xt") + let g:triggered = 0 au CursorHoldI * let g:triggered += 1 set updatetime=20 @@ -20,6 +33,7 @@ if has('timers') call feedkeys('a', 'x!') call assert_equal(1, g:triggered) au! CursorHoldI + set updatetime& endfunc func Test_cursorhold_insert_ctrl_x() @@ -31,6 +45,7 @@ if has('timers') call feedkeys("a\<C-X>", 'x!') call assert_equal(0, g:triggered) au! CursorHoldI + set updatetime& endfunc endif @@ -64,6 +79,115 @@ function Test_bufunload() augroup! test_bufunload_group endfunc +" SEGV occurs in older versions. (At least 7.4.2005 or older) +function Test_autocmd_bufunload_with_tabnext() + tabedit + tabfirst + + augroup test_autocmd_bufunload_with_tabnext_group + autocmd! + autocmd BufUnload <buffer> tabnext + augroup END + + quit + call assert_equal(2, tabpagenr('$')) + + autocmd! test_autocmd_bufunload_with_tabnext_group + augroup! test_autocmd_bufunload_with_tabnext_group + tablast + quit +endfunc + +function Test_autocmd_bufwinleave_with_tabfirst() + tabedit + augroup sample + autocmd! + autocmd BufWinLeave <buffer> tabfirst + augroup END + call setline(1, ['a', 'b', 'c']) + edit! a.txt + tabclose +endfunc + +" SEGV occurs in older versions. (At least 7.4.2321 or older) +function Test_autocmd_bufunload_avoiding_SEGV_01() + split aa.txt + let lastbuf = bufnr('$') + + augroup test_autocmd_bufunload + autocmd! + exe 'autocmd BufUnload <buffer> ' . (lastbuf + 1) . 'bwipeout!' + augroup END + + call assert_fails('edit bb.txt', 'E937:') + + autocmd! test_autocmd_bufunload + augroup! test_autocmd_bufunload + bwipe! aa.txt + bwipe! bb.txt +endfunc + +" SEGV occurs in older versions. (At least 7.4.2321 or older) +function Test_autocmd_bufunload_avoiding_SEGV_02() + setlocal buftype=nowrite + let lastbuf = bufnr('$') + + augroup test_autocmd_bufunload + autocmd! + exe 'autocmd BufUnload <buffer> ' . (lastbuf + 1) . 'bwipeout!' + augroup END + + normal! i1 + call assert_fails('edit a.txt', 'E517:') + call feedkeys("\<CR>") + + autocmd! test_autocmd_bufunload + augroup! test_autocmd_bufunload + bwipe! a.txt +endfunc + +func Test_win_tab_autocmd() + let g:record = [] + + augroup testing + au WinNew * call add(g:record, 'WinNew') + au WinEnter * call add(g:record, 'WinEnter') + au WinLeave * call add(g:record, 'WinLeave') + au TabNew * call add(g:record, 'TabNew') + au TabClosed * call add(g:record, 'TabClosed') + au TabEnter * call add(g:record, 'TabEnter') + au TabLeave * call add(g:record, 'TabLeave') + augroup END + + split + tabnew + close + close + + call assert_equal([ + \ 'WinLeave', 'WinNew', 'WinEnter', + \ 'WinLeave', 'TabLeave', 'WinNew', 'WinEnter', 'TabNew', 'TabEnter', + \ 'WinLeave', 'TabLeave', 'TabClosed', 'WinEnter', 'TabEnter', + \ 'WinLeave', 'WinEnter' + \ ], g:record) + + let g:record = [] + tabnew somefile + tabnext + bwipe somefile + + call assert_equal([ + \ 'WinLeave', 'TabLeave', 'WinNew', 'WinEnter', 'TabNew', 'TabEnter', + \ 'WinLeave', 'TabLeave', 'WinEnter', 'TabEnter', + \ 'TabClosed' + \ ], g:record) + + augroup testing + au! + augroup END + unlet g:record +endfunc + func s:AddAnAutocmd() augroup vimBarTest au BufReadCmd * echo 'hello' @@ -91,3 +215,208 @@ func Test_early_bar() au! vimBarTest|echo 'hello' call assert_equal(1, len(split(execute('au vimBarTest'), "\n"))) endfunc + +func RemoveGroup() + autocmd! StartOK + augroup! StartOK +endfunc + +func Test_augroup_warning() + augroup TheWarning + au VimEnter * echo 'entering' + augroup END + call assert_true(match(execute('au VimEnter'), "TheWarning.*VimEnter") >= 0) + redir => res + augroup! TheWarning + redir END + call assert_true(match(res, "W19:") >= 0) + call assert_true(match(execute('au VimEnter'), "-Deleted-.*VimEnter") >= 0) + + " check "Another" does not take the pace of the deleted entry + augroup Another + augroup END + call assert_true(match(execute('au VimEnter'), "-Deleted-.*VimEnter") >= 0) + augroup! Another + + " no warning for postpone aucmd delete + augroup StartOK + au VimEnter * call RemoveGroup() + augroup END + call assert_true(match(execute('au VimEnter'), "StartOK.*VimEnter") >= 0) + redir => res + doautocmd VimEnter + redir END + call assert_true(match(res, "W19:") < 0) + au! VimEnter +endfunc + +func Test_augroup_deleted() + " This caused a crash before E936 was introduced + augroup x + call assert_fails('augroup! x', 'E936:') + au VimEnter * echo + augroup end + augroup! x + call assert_true(match(execute('au VimEnter'), "-Deleted-.*VimEnter") >= 0) + au! VimEnter +endfunc + +" Tests for autocommands on :close command. +" This used to be in test13. +func Test_three_windows() + " Clean up buffers, because in some cases this function fails. + call s:cleanup_buffers() + + " Write three files and open them, each in a window. + " Then go to next window, with autocommand that deletes the previous one. + " Do this twice, writing the file. + e! Xtestje1 + call setline(1, 'testje1') + w + sp Xtestje2 + call setline(1, 'testje2') + w + sp Xtestje3 + call setline(1, 'testje3') + w + wincmd w + au WinLeave Xtestje2 bwipe + wincmd w + call assert_equal('Xtestje1', expand('%')) + + au WinLeave Xtestje1 bwipe Xtestje3 + close + call assert_equal('Xtestje1', expand('%')) + + " Test deleting the buffer on a Unload event. If this goes wrong there + " will be the ATTENTION prompt. + e Xtestje1 + au! + au! BufUnload Xtestje1 bwipe + call assert_fails('e Xtestje3', 'E937:') + call assert_equal('Xtestje3', expand('%')) + + e Xtestje2 + sp Xtestje1 + call assert_fails('e', 'E937:') + call assert_equal('Xtestje2', expand('%')) + + " Test changing buffers in a BufWipeout autocommand. If this goes wrong + " there are ml_line errors and/or a Crash. + au! + only + e Xanother + e Xtestje1 + bwipe Xtestje2 + bwipe Xtestje3 + au BufWipeout Xtestje1 buf Xtestje1 + bwipe + call assert_equal('Xanother', expand('%')) + + only + + helptags ALL + help + wincmd w + 1quit + call assert_equal('Xanother', expand('%')) + + au! + enew + bwipe! Xtestje1 + call delete('Xtestje1') + call delete('Xtestje2') + call delete('Xtestje3') +endfunc + +func Test_BufEnter() + au! BufEnter + au Bufenter * let val = val . '+' + let g:val = '' + split NewFile + call assert_equal('+', g:val) + bwipe! + call assert_equal('++', g:val) + + " Also get BufEnter when editing a directory + call mkdir('Xdir') + split Xdir + call assert_equal('+++', g:val) + + " On MS-Windows we can't edit the directory, make sure we wipe the right + " buffer. + bwipe! Xdir + + call delete('Xdir', 'd') + au! BufEnter +endfunc + +" Closing a window might cause an endless loop +" E814 for older Vims +function Test_autocmd_bufwipe_in_SessLoadPost() + tabnew + set noswapfile + mksession! + + let content = ['set nocp noswapfile', + \ 'let v:swapchoice="e"', + \ 'augroup test_autocmd_sessionload', + \ 'autocmd!', + \ 'autocmd SessionLoadPost * 4bw!', + \ 'augroup END', + \ '', + \ 'func WriteErrors()', + \ ' call writefile([execute("messages")], "Xerrors")', + \ 'endfunc', + \ 'au VimLeave * call WriteErrors()', + \ ] + call writefile(content, 'Xvimrc') + call system(v:progpath. ' --headless -i NONE -u Xvimrc --noplugins -S Session.vim -c cq') + let errors = join(readfile('Xerrors')) + call assert_match('E814', errors) + + set swapfile + for file in ['Session.vim', 'Xvimrc', 'Xerrors'] + call delete(file) + endfor +endfunc + +" SEGV occurs in older versions. +function Test_autocmd_bufwipe_in_SessLoadPost2() + tabnew + set noswapfile + mksession! + + let content = ['set nocp noswapfile', + \ 'function! DeleteInactiveBufs()', + \ ' tabfirst', + \ ' let tabblist = []', + \ ' for i in range(1, tabpagenr(''$''))', + \ ' call extend(tabblist, tabpagebuflist(i))', + \ ' endfor', + \ ' for b in range(1, bufnr(''$''))', + \ ' if bufexists(b) && buflisted(b) && (index(tabblist, b) == -1 || bufname(b) =~# ''^$'')', + \ ' exec ''bwipeout '' . b', + \ ' endif', + \ ' endfor', + \ ' echomsg "SessionLoadPost DONE"', + \ 'endfunction', + \ 'au SessionLoadPost * call DeleteInactiveBufs()', + \ '', + \ 'func WriteErrors()', + \ ' call writefile([execute("messages")], "Xerrors")', + \ 'endfunc', + \ 'au VimLeave * call WriteErrors()', + \ ] + call writefile(content, 'Xvimrc') + call system(v:progpath. ' --headless -i NONE -u Xvimrc --noplugins -S Session.vim -c cq') + let errors = join(readfile('Xerrors')) + " This probably only ever matches on unix. + call assert_notmatch('Caught deadly signal SEGV', errors) + call assert_match('SessionLoadPost DONE', errors) + + set swapfile + for file in ['Session.vim', 'Xvimrc', 'Xerrors'] + call delete(file) + endfor +endfunc diff --git a/src/nvim/testdir/test_breakindent.vim b/src/nvim/testdir/test_breakindent.vim new file mode 100644 index 0000000000..7deffbe452 --- /dev/null +++ b/src/nvim/testdir/test_breakindent.vim @@ -0,0 +1,298 @@ +" Test for breakindent +" +" Note: if you get strange failures when adding new tests, it might be that +" while the test is run, the breakindent cacheing gets in its way. +" It helps to change the tabstop setting and force a redraw (e.g. see +" Test_breakindent08()) +if !exists('+breakindent') + finish +endif + +source view_util.vim + +let s:input ="\tabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP" + +function s:screen_lines(lnum, width) abort + return ScreenLines([a:lnum, a:lnum + 2], a:width) +endfunction + +function! s:compare_lines(expect, actual) + call assert_equal(join(a:expect, "\n"), join(a:actual, "\n")) +endfunction + +function s:test_windows(...) + call NewWindow(10, 20) + setl ts=4 sw=4 sts=4 breakindent + put =s:input + exe get(a:000, 0, '') +endfunction + +function s:close_windows(...) + call CloseWindow() + exe get(a:000, 0, '') +endfunction + +function Test_breakindent01() + " simple breakindent test + call s:test_windows('setl briopt=min:0') + let lines=s:screen_lines(line('.'),8) + let expect=[ +\ " abcd", +\ " qrst", +\ " GHIJ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunction + +function Test_breakindent02() + " simple breakindent test with showbreak set + call s:test_windows('setl briopt=min:0 sbr=>>') + let lines=s:screen_lines(line('.'),8) + let expect=[ +\ " abcd", +\ " >>qr", +\ " >>EF", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows('set sbr=') +endfunction + +function Test_breakindent03() + " simple breakindent test with showbreak set and briopt including sbr + call s:test_windows('setl briopt=sbr,min:0 sbr=++') + let lines=s:screen_lines(line('.'),8) + let expect=[ +\ " abcd", +\ "++ qrst", +\ "++ GHIJ", +\ ] + call s:compare_lines(expect, lines) + " clean up + call s:close_windows('set sbr=') +endfunction + +function Test_breakindent04() + " breakindent set with min width 18 + call s:test_windows('setl sbr= briopt=min:18') + let lines=s:screen_lines(line('.'),8) + let expect=[ +\ " abcd", +\ " qrstuv", +\ " IJKLMN", +\ ] + call s:compare_lines(expect, lines) + " clean up + call s:close_windows('set sbr=') +endfunction + +function Test_breakindent05() + " breakindent set and shift by 2 + call s:test_windows('setl briopt=shift:2,min:0') + let lines=s:screen_lines(line('.'),8) + let expect=[ +\ " abcd", +\ " qr", +\ " EF", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunction + +function Test_breakindent06() + " breakindent set and shift by -1 + call s:test_windows('setl briopt=shift:-1,min:0') + let lines=s:screen_lines(line('.'),8) + let expect=[ +\ " abcd", +\ " qrstu", +\ " HIJKL", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunction + +function Test_breakindent07() + " breakindent set and shift by 1, Number set sbr=? and briopt:sbr + call s:test_windows('setl briopt=shift:1,sbr,min:0 nu sbr=? nuw=4 cpo+=n') + let lines=s:screen_lines(line('.'),10) + let expect=[ +\ " 2 ab", +\ "? m", +\ "? x", +\ ] + call s:compare_lines(expect, lines) + " clean up + call s:close_windows('set sbr= cpo-=n') +endfunction + +function Test_breakindent07a() + " breakindent set and shift by 1, Number set sbr=? and briopt:sbr + call s:test_windows('setl briopt=shift:1,sbr,min:0 nu sbr=? nuw=4') + let lines=s:screen_lines(line('.'),10) + let expect=[ +\ " 2 ab", +\ " ? m", +\ " ? x", +\ ] + call s:compare_lines(expect, lines) + " clean up + call s:close_windows('set sbr=') +endfunction + +function Test_breakindent08() + " breakindent set and shift by 1, Number and list set sbr=# and briopt:sbr + call s:test_windows('setl briopt=shift:1,sbr,min:0 nu nuw=4 sbr=# list cpo+=n ts=4') + " make sure, cache is invalidated! + set ts=8 + redraw! + set ts=4 + redraw! + let lines=s:screen_lines(line('.'),10) + let expect=[ +\ " 2 ^Iabcd", +\ "# opq", +\ "# BCD", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows('set sbr= cpo-=n') +endfunction + +function Test_breakindent08a() + " breakindent set and shift by 1, Number and list set sbr=# and briopt:sbr + call s:test_windows('setl briopt=shift:1,sbr,min:0 nu nuw=4 sbr=# list') + let lines=s:screen_lines(line('.'),10) + let expect=[ +\ " 2 ^Iabcd", +\ " # opq", +\ " # BCD", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows('set sbr=') +endfunction + +function Test_breakindent09() + " breakindent set and shift by 1, Number and list set sbr=# + call s:test_windows('setl briopt=shift:1,min:0 nu nuw=4 sbr=# list') + let lines=s:screen_lines(line('.'),10) + let expect=[ +\ " 2 ^Iabcd", +\ " #op", +\ " #AB", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows('set sbr=') +endfunction + +function Test_breakindent10() + " breakindent set, Number set sbr=~ + call s:test_windows('setl cpo+=n sbr=~ nu nuw=4 nolist briopt=sbr,min:0') + " make sure, cache is invalidated! + set ts=8 + redraw! + set ts=4 + redraw! + let lines=s:screen_lines(line('.'),10) + let expect=[ +\ " 2 ab", +\ "~ mn", +\ "~ yz", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows('set sbr= cpo-=n') +endfunction + +function Test_breakindent11() + " test strdisplaywidth() + call s:test_windows('setl cpo-=n sbr=>> nu nuw=4 nolist briopt= ts=4') + let text=getline(2) + let width = strlen(text[1:])+indent(2)+strlen(&sbr)*3 " text wraps 3 times + call assert_equal(width, strdisplaywidth(text)) + call s:close_windows('set sbr=') +endfunction + +function Test_breakindent12() + " test breakindent with long indent + let s:input="\t\t\t\t\t{" + call s:test_windows('setl breakindent linebreak briopt=min:10 nu numberwidth=3 ts=4 list listchars=tab:>-') + let lines=s:screen_lines(2,16) + let expect=[ +\ " 2 >--->--->--->", +\ " ---{ ", +\ "~ ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows('set nuw=4 listchars=') +endfunction + +function Test_breakindent13() + let s:input="" + call s:test_windows('setl breakindent briopt=min:10 ts=8') + vert resize 20 + call setline(1, [" a\tb\tc\td\te", " z y x w v"]) + 1 + norm! fbgj"ayl + 2 + norm! fygj"byl + call assert_equal('d', @a) + call assert_equal('w', @b) + call s:close_windows() +endfunction + +function Test_breakindent14() + let s:input="" + call s:test_windows('setl breakindent briopt= ts=8') + vert resize 30 + norm! 3a1234567890 + norm! a abcde + exec "norm! 0\<C-V>tex" + let lines=s:screen_lines(line('.'),8) + let expect=[ +\ "e ", +\ "~ ", +\ "~ ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunction + +function Test_breakindent15() + let s:input="" + call s:test_windows('setl breakindent briopt= ts=8 sw=8') + vert resize 30 + norm! 4a1234567890 + exe "normal! >>\<C-V>3f0x" + let lines=s:screen_lines(line('.'),20) + let expect=[ +\ " 1234567890 ", +\ "~ ", +\ "~ ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunction + +function Test_breakindent16() + " Check that overlong lines are indented correctly. + let s:input="" + call s:test_windows('setl breakindent briopt=min:0 ts=4') + call setline(1, "\t".repeat("1234567890", 10)) + resize 6 + norm! 1gg$ + redraw! + let lines=s:screen_lines(1,10) + let expect=[ +\ " 789012", +\ " 345678", +\ " 901234", +\ ] + call s:compare_lines(expect, lines) + let lines=s:screen_lines(4,10) + let expect=[ +\ " 567890", +\ " 123456", +\ " 7890 ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunction diff --git a/src/nvim/testdir/test_bufwintabinfo.vim b/src/nvim/testdir/test_bufwintabinfo.vim index 5c916e2dd7..1c9350c416 100644 --- a/src/nvim/testdir/test_bufwintabinfo.vim +++ b/src/nvim/testdir/test_bufwintabinfo.vim @@ -87,9 +87,17 @@ function Test_get_buf_options() endfunc function Test_get_win_options() + if has('folding') + set foldlevel=999 + endif + set list let opts = getwinvar(1, '&') call assert_equal(v:t_dict, type(opts)) call assert_equal(0, opts.linebreak) + call assert_equal(1, opts.list) + if has('folding') + call assert_equal(999, opts.foldlevel) + endif if has('signs') call assert_equal('auto', opts.signcolumn) endif @@ -97,7 +105,12 @@ function Test_get_win_options() let opts = gettabwinvar(1, 1, '&') call assert_equal(v:t_dict, type(opts)) call assert_equal(0, opts.linebreak) + call assert_equal(1, opts.list) if has('signs') call assert_equal('auto', opts.signcolumn) endif + set list& + if has('folding') + set foldlevel=0 + endif endfunc diff --git a/src/nvim/testdir/test_charsearch.vim b/src/nvim/testdir/test_charsearch.vim new file mode 100644 index 0000000000..8b313b5a35 --- /dev/null +++ b/src/nvim/testdir/test_charsearch.vim @@ -0,0 +1,62 @@ + +function! Test_charsearch() + enew! + call append(0, ['Xabcdefghijkemnopqretuvwxyz', + \ 'Yabcdefghijkemnopqretuvwxyz', + \ 'Zabcdefghijkemnokqretkvwxyz']) + " check that "fe" and ";" work + 1 + normal! ylfep;;p,,p + call assert_equal('XabcdeXfghijkeXmnopqreXtuvwxyz', getline(1)) + " check that save/restore works + 2 + normal! ylfep + let csave = getcharsearch() + normal! fip + call setcharsearch(csave) + normal! ;p;p + call assert_equal('YabcdeYfghiYjkeYmnopqreYtuvwxyz', getline(2)) + + " check that setcharsearch() changes the settings. + 3 + normal! ylfep + call setcharsearch({'char': 'k'}) + normal! ;p + call setcharsearch({'forward': 0}) + normal! $;p + call setcharsearch({'until': 1}) + set cpo-=; + normal! ;;p + call assert_equal('ZabcdeZfghijkZZemnokqretkZvwxyz', getline(3)) + enew! +endfunction + +" Test for t,f,F,T movement commands and 'cpo-;' setting +function! Test_search_cmds() + enew! + call append(0, ["aaa two three four", " zzz", "yyy ", + \ "bbb yee yoo four", "ccc two three four", + \ "ddd yee yoo four"]) + set cpo-=; + 1 + normal! 0tt;D + 2 + normal! 0fz;D + 3 + normal! $Fy;D + 4 + normal! $Ty;D + set cpo+=; + 5 + normal! 0tt;;D + 6 + normal! $Ty;;D + + call assert_equal('aaa two', getline(1)) + call assert_equal(' z', getline(2)) + call assert_equal('y', getline(3)) + call assert_equal('bbb y', getline(4)) + call assert_equal('ccc', getline(5)) + call assert_equal('ddd yee y', getline(6)) + enew! +endfunction diff --git a/src/nvim/testdir/test_cmdline.vim b/src/nvim/testdir/test_cmdline.vim index 21bb057fe1..2facffb067 100644 --- a/src/nvim/testdir/test_cmdline.vim +++ b/src/nvim/testdir/test_cmdline.vim @@ -2,7 +2,7 @@ func Test_complete_tab() call writefile(['testfile'], 'Xtestfile') - call feedkeys(":e Xtest\t\r", "tx") + call feedkeys(":e Xtestf\t\r", "tx") call assert_equal('testfile', getline(1)) call delete('Xtestfile') endfunc @@ -17,7 +17,7 @@ func Test_complete_wildmenu() call writefile(['testfile1'], 'Xtestfile1') call writefile(['testfile2'], 'Xtestfile2') set wildmenu - call feedkeys(":e Xtest\t\t\r", "tx") + call feedkeys(":e Xtestf\t\t\r", "tx") call assert_equal('testfile2', getline(1)) call delete('Xtestfile1') @@ -85,6 +85,11 @@ func Test_getcompletion() let l = getcompletion('paint', 'function') call assert_equal([], l) + let Flambda = {-> 'hello'} + let l = getcompletion('', 'function') + let l = filter(l, {i, v -> v =~ 'lambda'}) + call assert_equal(0, len(l)) + let l = getcompletion('run', 'file') call assert_true(index(l, 'runtest.vim') >= 0) let l = getcompletion('walk', 'file') @@ -125,6 +130,11 @@ func Test_getcompletion() let l = getcompletion('dark', 'highlight') call assert_equal([], l) + let l = getcompletion('', 'messages') + call assert_true(index(l, 'clear') >= 0) + let l = getcompletion('not', 'messages') + call assert_equal([], l) + if has('cscope') let l = getcompletion('', 'cscope') let cmds = ['add', 'find', 'help', 'kill', 'reset', 'show'] @@ -151,6 +161,20 @@ func Test_getcompletion() call assert_equal(['Testing'], l) endif + " Command line completion tests + let l = getcompletion('cd ', 'cmdline') + call assert_true(index(l, 'sautest/') >= 0) + let l = getcompletion('cd NoMatch', 'cmdline') + call assert_equal([], l) + let l = getcompletion('let v:n', 'cmdline') + call assert_true(index(l, 'v:null') >= 0) + let l = getcompletion('let v:notexists', 'cmdline') + call assert_equal([], l) + let l = getcompletion('call tag', 'cmdline') + call assert_true(index(l, 'taglist(') >= 0) + let l = getcompletion('call paint', 'cmdline') + call assert_equal([], l) + " For others test if the name is recognized. let names = ['buffer', 'environment', 'file_in_path', \ 'mapping', 'shellcmd', 'tag', 'tag_listfiles', 'user'] @@ -182,5 +206,53 @@ func Test_expand_star_star() call writefile(['asdfasdf'], 'a/b/fileXname') call feedkeys(":find **/fileXname\<Tab>\<CR>", 'xt') call assert_equal('find a/b/fileXname', getreg(':')) + bwipe! call delete('a', 'rf') endfunc + +func Test_paste_in_cmdline() + let @a = "def" + call feedkeys(":abc \<C-R>a ghi\<C-B>\"\<CR>", 'tx') + call assert_equal('"abc def ghi', @:) + + new + call setline(1, 'asdf.x /tmp/some verylongword a;b-c*d ') + + call feedkeys(":aaa \<C-R>\<C-W> bbb\<C-B>\"\<CR>", 'tx') + call assert_equal('"aaa asdf bbb', @:) + + call feedkeys("ft:aaa \<C-R>\<C-F> bbb\<C-B>\"\<CR>", 'tx') + call assert_equal('"aaa /tmp/some bbb', @:) + + set incsearch + call feedkeys("fy:aaa veryl\<C-R>\<C-W> bbb\<C-B>\"\<CR>", 'tx') + call assert_equal('"aaa verylongword bbb', @:) + + call feedkeys("f;:aaa \<C-R>\<C-A> bbb\<C-B>\"\<CR>", 'tx') + call assert_equal('"aaa a;b-c*d bbb', @:) + + call feedkeys(":\<C-\>etoupper(getline(1))\<CR>\<C-B>\"\<CR>", 'tx') + call assert_equal('"ASDF.X /TMP/SOME VERYLONGWORD A;B-C*D ', @:) + bwipe! +endfunc + +func Test_remove_char_in_cmdline() + call feedkeys(":abc def\<S-Left>\<Del>\<C-B>\"\<CR>", 'tx') + call assert_equal('"abc ef', @:) + + call feedkeys(":abc def\<S-Left>\<BS>\<C-B>\"\<CR>", 'tx') + call assert_equal('"abcdef', @:) + + call feedkeys(":abc def ghi\<S-Left>\<C-W>\<C-B>\"\<CR>", 'tx') + call assert_equal('"abc ghi', @:) + + call feedkeys(":abc def\<S-Left>\<C-U>\<C-B>\"\<CR>", 'tx') + call assert_equal('"def', @:) +endfunc + +func Test_illegal_address() + new + 2;'( + 2;') + quit +endfunc diff --git a/src/nvim/testdir/test_command_count.vim b/src/nvim/testdir/test_command_count.vim new file mode 100644 index 0000000000..e438a8b077 --- /dev/null +++ b/src/nvim/testdir/test_command_count.vim @@ -0,0 +1,191 @@ +" Test for user command counts. + +func Test_command_count_0() + set hidden + set noswapfile + + split DoesNotExistEver + let lastbuf = bufnr('$') + call setline(1, 'asdf') + quit! + + command! -range -addr=loaded_buffers RangeLoadedBuffers :let lines = [<line1>, <line2>] + command! -range=% -addr=loaded_buffers RangeLoadedBuffersAll :let lines = [<line1>, <line2>] + command! -range -addr=buffers RangeBuffers :let lines = [<line1>, <line2>] + command! -range=% -addr=buffers RangeBuffersAll :let lines = [<line1>, <line2>] + + .,$RangeLoadedBuffers + call assert_equal([1, 1], lines) + %RangeLoadedBuffers + call assert_equal([1, 1], lines) + RangeLoadedBuffersAll + call assert_equal([1, 1], lines) + .,$RangeBuffers + call assert_equal([1, lastbuf], lines) + %RangeBuffers + call assert_equal([1, lastbuf], lines) + RangeBuffersAll + call assert_equal([1, lastbuf], lines) + + delcommand RangeLoadedBuffers + delcommand RangeLoadedBuffersAll + delcommand RangeBuffers + delcommand RangeBuffersAll + + set hidden& + set swapfile& +endfunc + +func Test_command_count_1() + silent! %argd + arga a b c d e + argdo echo "loading buffers" + argu 3 + command! -range -addr=arguments RangeArguments :let lines = [<line1>, <line2>] + command! -range=% -addr=arguments RangeArgumentsAll :let lines = [<line1>, <line2>] + .-,$-RangeArguments + call assert_equal([2, 4], lines) + %RangeArguments + call assert_equal([1, 5], lines) + RangeArgumentsAll + call assert_equal([1, 5], lines) + N + .RangeArguments + call assert_equal([2, 2], lines) + delcommand RangeArguments + delcommand RangeArgumentsAll + + split|split|split|split + 3wincmd w + command! -range -addr=windows RangeWindows :let lines = [<line1>, <line2>] + .,$RangeWindows + call assert_equal([3, 5], lines) + %RangeWindows + call assert_equal([1, 5], lines) + delcommand RangeWindows + + command! -range=% -addr=windows RangeWindowsAll :let lines = [<line1>, <line2>] + RangeWindowsAll + call assert_equal([1, 5], lines) + delcommand RangeWindowsAll + only + blast|bd + + tabe|tabe|tabe|tabe + normal 2gt + command! -range -addr=tabs RangeTabs :let lines = [<line1>, <line2>] + .,$RangeTabs + call assert_equal([2, 5], lines) + %RangeTabs + call assert_equal([1, 5], lines) + delcommand RangeTabs + + command! -range=% -addr=tabs RangeTabsAll :let lines = [<line1>, <line2>] + RangeTabsAll + call assert_equal([1, 5], lines) + delcommand RangeTabsAll + 1tabonly + + s/\n/\r\r\r\r\r/ + 2ma< + $-ma> + command! -range=% RangeLines :let lines = [<line1>, <line2>] + '<,'>RangeLines + call assert_equal([2, 5], lines) + delcommand RangeLines + + command! -range=% -buffer LocalRangeLines :let lines = [<line1>, <line2>] + '<,'>LocalRangeLines + call assert_equal([2, 5], lines) + delcommand LocalRangeLines +endfunc + +func Test_command_count_2() + silent! %argd + arga a b c d + call assert_fails('5argu', 'E16:') + + $argu + call assert_equal('d', expand('%:t')) + + 1argu + call assert_equal('a', expand('%:t')) + + call assert_fails('300b', 'E16:') + + split|split|split|split + 0close + + $wincmd w + $close + call assert_equal(3, winnr()) + + call assert_fails('$+close', 'E16:') + + $tabe + call assert_equal(2, tabpagenr()) + + call assert_fails('$+tabe', 'E16:') + + only! + e x + 0tabm + normal 1gt + call assert_equal('x', expand('%:t')) + + tabonly! + only! +endfunc + +func Test_command_count_3() + se nohidden + e aaa + let buf_aaa = bufnr('%') + e bbb + let buf_bbb = bufnr('%') + e ccc + let buf_ccc = bufnr('%') + buf 1 + call assert_equal([1, 1, 1], [buflisted(buf_aaa), buflisted(buf_bbb), buflisted(buf_ccc)]) + exe buf_bbb . "," . buf_ccc . "bdelete" + call assert_equal([1, 0, 0], [buflisted(buf_aaa), buflisted(buf_bbb), buflisted(buf_ccc)]) + exe buf_aaa . "bdelete" + call assert_equal([0, 0, 0], [buflisted(buf_aaa), buflisted(buf_bbb), buflisted(buf_ccc)]) +endfunc + +func Test_command_count_4() + %argd + let bufnr = bufnr('$') + 1 + arga aa bb cc dd ee ff + 3argu + let args = [] + .,$-argdo call add(args, expand('%')) + call assert_equal(['cc', 'dd', 'ee'], args) + + " create windows to get 5 + split|split|split|split + 2wincmd w + let windows = [] + .,$-windo call add(windows, winnr()) + call assert_equal([2, 3, 4], windows) + only! + + exe bufnr . 'buf' + let buffers = [] + .,$-bufdo call add(buffers, bufnr('%')) + call assert_equal([bufnr, bufnr + 1, bufnr + 2, bufnr + 3, bufnr + 4], buffers) + + exe (bufnr + 3) . 'bdel' + let buffers = [] + exe (bufnr + 2) . ',' . (bufnr + 5) . "bufdo call add(buffers, bufnr('%'))" + call assert_equal([bufnr + 2, bufnr + 4, bufnr + 5], buffers) + + " create tabpages to get 5 + tabe|tabe|tabe|tabe + normal! 2gt + let tabpages = [] + .,$-tabdo call add(tabpages, tabpagenr()) + call assert_equal([2, 3, 4], tabpages) + tabonly! + bwipe! +endfunc diff --git a/src/nvim/testdir/test_cscope.vim b/src/nvim/testdir/test_cscope.vim index b6d70f0765..01a9a3f9ad 100644 --- a/src/nvim/testdir/test_cscope.vim +++ b/src/nvim/testdir/test_cscope.vim @@ -1,9 +1,262 @@ " Test for cscope commands. -if !has('cscope') +if !has('cscope') || !executable('cscope') || !has('quickfix') finish endif +func CscopeSetupOrClean(setup) + if a:setup + noa sp samples/memfile_test.c + saveas! Xmemfile_test.c + call system('cscope -bk -fXcscope.out Xmemfile_test.c') + call system('cscope -bk -fXcscope2.out Xmemfile_test.c') + cscope add Xcscope.out + set cscopequickfix=s-,g-,d-,c-,t-,e-,f-,i-,a- + else + cscope kill -1 + for file in ['Xcscope.out', 'Xcscope2.out', 'Xmemfile_test.c'] + call delete(file) + endfo + endif +endfunc + +func Test_cscopeWithCscopeConnections() + call CscopeSetupOrClean(1) + " Test 0: E568: duplicate cscope database not added + try + set nocscopeverbose + cscope add Xcscope.out + set cscopeverbose + catch + call assert_report('exception thrown') + endtry + call assert_fails('cscope add', 'E560') + call assert_fails('cscope add Xcscope.out', 'E568') + call assert_fails('cscope add doesnotexist.out', 'E563') + + " Test 1: Find this C-Symbol + for cmd in ['cs find s main', 'cs find 0 main'] + let a=execute(cmd) + " Test 1.1 test where it moves the cursor + call assert_equal('main(void)', getline('.')) + " Test 1.2 test the output of the :cs command + call assert_match('\n(1 of 1): <<main>> main(void )', a) + endfor + + " Test 2: Find this definition + for cmd in ['cs find g test_mf_hash', 'cs find 1 test_mf_hash'] + exe cmd + call assert_equal(['', '/*', ' * Test mf_hash_*() functions.', ' */', ' static void', 'test_mf_hash(void)', '{'], getline(line('.')-5, line('.')+1)) + endfor + + " Test 3: Find functions called by this function + for cmd in ['cs find d test_mf_hash', 'cs find 2 test_mf_hash'] + let a=execute(cmd) + call assert_match('\n(1 of 42): <<mf_hash_init>> mf_hash_init(&ht);', a) + call assert_equal(' mf_hash_init(&ht);', getline('.')) + endfor + + " Test 4: Find functions calling this function + for cmd in ['cs find c test_mf_hash', 'cs find 3 test_mf_hash'] + let a=execute(cmd) + call assert_match('\n(1 of 1): <<main>> test_mf_hash();', a) + call assert_equal(' test_mf_hash();', getline('.')) + endfor + + " Test 5: Find this text string + for cmd in ['cs find t Bram', 'cs find 4 Bram'] + let a=execute(cmd) + call assert_match('(1 of 1): <<<unknown>>> \* VIM - Vi IMproved^Iby Bram Moolenaar', a) + call assert_equal(' * VIM - Vi IMproved by Bram Moolenaar', getline('.')) + endfor + + " Test 6: Find this egrep pattern + " test all matches returned by cscope + for cmd in ['cs find e ^\#includ.', 'cs find 6 ^\#includ.'] + let a=execute(cmd) + call assert_match('\n(1 of 3): <<<unknown>>> #include <assert.h>', a) + call assert_equal('#include <assert.h>', getline('.')) + cnext + call assert_equal('#include "main.c"', getline('.')) + cnext + call assert_equal('#include "memfile.c"', getline('.')) + call assert_fails('cnext', 'E553:') + endfor + + " Test 7: Find the same egrep pattern using lcscope this time. + let a=execute('lcs find e ^\#includ.') + call assert_match('\n(1 of 3): <<<unknown>>> #include <assert.h>', a) + call assert_equal('#include <assert.h>', getline('.')) + lnext + call assert_equal('#include "main.c"', getline('.')) + lnext + call assert_equal('#include "memfile.c"', getline('.')) + call assert_fails('lnext', 'E553:') + + " Test 8: Find this file + for cmd in ['cs find f Xmemfile_test.c', 'cs find 7 Xmemfile_test.c'] + enew + let a=execute(cmd) + call assert_true(a =~ '"Xmemfile_test.c" \d\+L, \d\+C') + call assert_equal('Xmemfile_test.c', @%) + endfor + + " Test 9: Find files #including this file + for cmd in ['cs find i assert.h', 'cs find 8 assert.h'] + enew + let a=execute(cmd) + let alines = split(a, '\n', 1) + call assert_equal('', alines[0]) + call assert_true(alines[1] =~ '"Xmemfile_test.c" \d\+L, \d\+C') + call assert_equal('(1 of 1): <<global>> #include <assert.h>', alines[2]) + call assert_equal('#include <assert.h>', getline('.')) + endfor + + " Test 10: Invalid find command + call assert_fails('cs find x', 'E560:') + + " Test 11: Find places where this symbol is assigned a value + " this needs a cscope >= 15.8 + " unfortunately, Travis has cscope version 15.7 + let cscope_version=systemlist('cscope --version')[0] + let cs_version=str2float(matchstr(cscope_version, '\d\+\(\.\d\+\)\?')) + if cs_version >= 15.8 + for cmd in ['cs find a item', 'cs find 9 item'] + let a=execute(cmd) + call assert_equal(['', '(1 of 4): <<test_mf_hash>> item = (mf_hashitem_T *)lalloc_clear(sizeof(mf_hashtab_T), FALSE);'], split(a, '\n', 1)) + call assert_equal(' item = (mf_hashitem_T *)lalloc_clear(sizeof(mf_hashtab_T), FALSE);', getline('.')) + cnext + call assert_equal(' item = mf_hash_find(&ht, key);', getline('.')) + cnext + call assert_equal(' item = mf_hash_find(&ht, key);', getline('.')) + cnext + call assert_equal(' item = mf_hash_find(&ht, key);', getline('.')) + endfor + endif + + " Test 12: leading whitespace is not removed for cscope find text + let a=execute('cscope find t test_mf_hash') + call assert_equal(['', '(1 of 1): <<<unknown>>> test_mf_hash();'], split(a, '\n', 1)) + call assert_equal(' test_mf_hash();', getline('.')) + + " Test 13: test with scscope + let a=execute('scs find t Bram') + call assert_match('(1 of 1): <<<unknown>>> \* VIM - Vi IMproved^Iby Bram Moolenaar', a) + call assert_equal(' * VIM - Vi IMproved by Bram Moolenaar', getline('.')) + + " Test 14: cscope help + for cmd in ['cs', 'cs help', 'cs xxx'] + let a=execute(cmd) + call assert_match('^cscope commands:\n', a) + call assert_match('\nadd :', a) + call assert_match('\nfind :', a) + call assert_match('\nhelp : Show this message', a) + call assert_match('\nkill : Kill a connection', a) + call assert_match('\nreset: Reinit all connections', a) + call assert_match('\nshow : Show connections', a) + endfor + let a=execute('scscope help') + call assert_match('This cscope command does not support splitting the window\.', a) + + " Test 15: reset connections + let a=execute('cscope reset') + call assert_match('\nAdded cscope database.*Xcscope.out (#0)', a) + call assert_match('\nAll cscope databases reset', a) + + " Test 16: cscope show + let a=execute('cscope show') + call assert_match('\n 0 \d\+.*Xcscope.out\s*<none>', a) + + " Test 17: cstag and 'csto' option + set csto=0 + let a=execute('cstag TEST_COUNT') + call assert_match('(1 of 1): <<TEST_COUNT>> #define TEST_COUNT 50000', a) + call assert_equal('#define TEST_COUNT 50000', getline('.')) + set csto=1 + let a=execute('cstag index_to_key') + call assert_match('(1 of 1): <<index_to_key>> #define index_to_key(i) ((i) ^ 15167)', a) + call assert_equal('#define index_to_key(i) ((i) ^ 15167)', getline('.')) + call assert_fails('cstag xxx', 'E257:') + call assert_fails('cstag', 'E562:') + + " Test 18: 'cst' option + set nocst + call assert_fails('tag TEST_COUNT', 'E426:') + set cst + let a=execute('tag TEST_COUNT') + call assert_match('(1 of 1): <<TEST_COUNT>> #define TEST_COUNT 50000', a) + call assert_equal('#define TEST_COUNT 50000', getline('.')) + let a=execute('tags') + call assert_match('1 1 TEST_COUNT\s\+\d\+\s\+#define index_to_key', a) + + " Test 19: this should trigger call to cs_print_tags() + " Unclear how to check result though, we just exercise the code. + set cst cscopequickfix=s0 + call feedkeys(":cs find s main\<CR>", 't') + + " Test 20: cscope kill + call assert_fails('cscope kill 2', 'E261:') + call assert_fails('cscope kill xxx', 'E261:') + + let a=execute('cscope kill 0') + call assert_match('cscope connection 0 closed', a) + + cscope add Xcscope.out + let a=execute('cscope kill Xcscope.out') + call assert_match('cscope connection Xcscope.out closed', a) + + cscope add Xcscope.out . + let a=execute('cscope kill -1') + call assert_match('cscope connection .*Xcscope.out closed', a) + let a=execute('cscope kill -1') + call assert_equal('', a) + + " Test 21: 'csprg' option + call assert_equal('cscope', &csprg) + set csprg=doesnotexist + call assert_fails('cscope add Xcscope2.out', 'E609:') + set csprg=cscope + + " Test 22: multiple cscope connections + cscope add Xcscope.out + cscope add Xcscope2.out . -C + let a=execute('cscope show') + call assert_match('\n 0 \d\+.*Xcscope.out\s*<none>', a) + call assert_match('\n 1 \d\+.*Xcscope2.out\s*\.', a) + + " Test 23: test Ex command line completion + call feedkeys(":cs \<C-A>\<C-B>\"\<CR>", 'tx') + call assert_equal('"cs add find help kill reset show', @:) + + call feedkeys(":scs \<C-A>\<C-B>\"\<CR>", 'tx') + call assert_equal('"scs find', @:) + + call feedkeys(":cs find \<C-A>\<C-B>\"\<CR>", 'tx') + call assert_equal('"cs find a c d e f g i s t', @:) + + call feedkeys(":cs kill \<C-A>\<C-B>\"\<CR>", 'tx') + call assert_equal('"cs kill -1 0 1', @:) + + call feedkeys(":cs add Xcscope\<C-A>\<C-B>\"\<CR>", 'tx') + call assert_equal('"cs add Xcscope.out Xcscope2.out', @:) + + " Test 24: cscope_connection() + call assert_equal(cscope_connection(), 1) + call assert_equal(cscope_connection(0, 'out'), 1) + call assert_equal(cscope_connection(0, 'xxx'), 1) + call assert_equal(cscope_connection(1, 'out'), 1) + call assert_equal(cscope_connection(1, 'xxx'), 0) + call assert_equal(cscope_connection(2, 'out'), 0) + call assert_equal(cscope_connection(3, 'xxx', '..'), 0) + call assert_equal(cscope_connection(3, 'out', 'xxx'), 0) + call assert_equal(cscope_connection(3, 'out', '.'), 1) + call assert_equal(cscope_connection(4, 'out', '.'), 0) + + " CleanUp + call CscopeSetupOrClean(0) + +endfunc + func Test_cscopequickfix() set cscopequickfix=s-,g-,d+,c-,t+,e-,f0,i-,a- call assert_equal('s-,g-,d+,c-,t+,e-,f0,i-,a-', &cscopequickfix) @@ -13,3 +266,14 @@ func Test_cscopequickfix() call assert_fails('set cscopequickfix=s7', 'E474:') call assert_fails('set cscopequickfix=s-a', 'E474:') endfunc + +func Test_withoutCscopeConnection() + call assert_equal(cscope_connection(), 0) + + call assert_fails('cscope find s main', 'E567:') + let a=execute('cscope show') + call assert_match('no cscope connections', a) +endfunc + + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_cursor_func.vim b/src/nvim/testdir/test_cursor_func.vim index d819b7b092..e1b9651c84 100644 --- a/src/nvim/testdir/test_cursor_func.vim +++ b/src/nvim/testdir/test_cursor_func.vim @@ -1,13 +1,7 @@ " Tests for cursor(). func Test_wrong_arguments() - try - call cursor(1. 3) - " not reached - call assert_false(1) - catch - call assert_exception('E474:') - endtry + call assert_fails('call cursor(1. 3)', 'E474:') endfunc func Test_move_cursor() diff --git a/src/nvim/testdir/test_diffmode.vim b/src/nvim/testdir/test_diffmode.vim index 7666594862..f40e06ff33 100644 --- a/src/nvim/testdir/test_diffmode.vim +++ b/src/nvim/testdir/test_diffmode.vim @@ -202,3 +202,36 @@ func Test_diffget_diffput() bwipe! enew! endfunc + +func Test_diffoff() + enew! + call setline(1, ['Two', 'Three']) + let normattr = screenattr(1, 1) + diffthis + botright vert new + call setline(1, ['One', '', 'Two', 'Three']) + diffthis + redraw + diffoff! + redraw + call assert_equal(normattr, screenattr(1, 1)) + bwipe! + bwipe! +endfunc + +func Test_setting_cursor() + new Xtest1 + put =range(1,90) + wq + new Xtest2 + put =range(1,100) + wq + + tabe Xtest2 + $ + diffsp Xtest1 + tabclose + + call delete('Xtest1') + call delete('Xtest2') +endfunc diff --git a/src/nvim/testdir/test_digraph.vim b/src/nvim/testdir/test_digraph.vim new file mode 100644 index 0000000000..6290680305 --- /dev/null +++ b/src/nvim/testdir/test_digraph.vim @@ -0,0 +1,461 @@ +" Tests for digraphs + +if !has("digraphs") || !has("multi_byte") + finish +endif + +func! Put_Dig(chars) + exe "norm! o\<c-k>".a:chars +endfu + +func! Put_Dig_BS(char1, char2) + exe "norm! o".a:char1."\<bs>".a:char2 +endfu + +func! Test_digraphs() + new + call Put_Dig("00") + call assert_equal("โ", getline('.')) + " not a digraph + call Put_Dig("el") + call assert_equal("l", getline('.')) + call Put_Dig("ht") + call assert_equal("รพ", getline('.')) + " digraph "ab" is the same as "ba" + call Put_Dig("ab") + call Put_Dig("ba") + call assert_equal(["ใฐ","ใฐ"], getline(line('.')-1,line('.'))) + " Euro sign + call Put_Dig("e=") + call Put_Dig("=e") + call Put_Dig("Eu") + call Put_Dig("uE") + call assert_equal(['ะต']+repeat(["โฌ"],3), getline(line('.')-3,line('.'))) + " Rouble sign + call Put_Dig("R=") + call Put_Dig("=R") + call Put_Dig("=P") + call Put_Dig("P=") + call assert_equal(['ะ ']+repeat(["โฝ"],2)+['ะ'], getline(line('.')-3,line('.'))) + " Not a digraph + call Put_Dig("a\<bs>") + call Put_Dig("\<bs>a") + call assert_equal(["<BS>", "<BS>a"], getline(line('.')-1,line('.'))) + " Grave + call Put_Dig("a!") + call Put_Dig("!e") + call Put_Dig("b!") " not defined + call assert_equal(["ร ", "รจ", "!"], getline(line('.')-2,line('.'))) + " Acute accent + call Put_Dig("a'") + call Put_Dig("'e") + call Put_Dig("b'") " not defined + call assert_equal(["รก", "รฉ", "'"], getline(line('.')-2,line('.'))) + " Cicumflex + call Put_Dig("a>") + call Put_Dig(">e") + call Put_Dig("b>") " not defined + call assert_equal(['รข', 'รช', '>'], getline(line('.')-2,line('.'))) + " Tilde + call Put_Dig("o~") + call Put_Dig("~u") " not defined + call Put_Dig("z~") " not defined + call assert_equal(['รต', 'u', '~'], getline(line('.')-2,line('.'))) + " Tilde + call Put_Dig("o?") + call Put_Dig("?u") + call Put_Dig("z?") " not defined + call assert_equal(['รต', 'ลฉ', '?'], getline(line('.')-2,line('.'))) + " Macron + call Put_Dig("o-") + call Put_Dig("-u") + call Put_Dig("z-") " not defined + call assert_equal(['ล', 'ลซ', '-'], getline(line('.')-2,line('.'))) + " Breve + call Put_Dig("o(") + call Put_Dig("(u") + call Put_Dig("z(") " not defined + call assert_equal(['ล', 'ลญ', '('], getline(line('.')-2,line('.'))) + " Dot above + call Put_Dig("b.") + call Put_Dig(".e") + call Put_Dig("a.") " not defined + call assert_equal(['แธ', 'ฤ', '.'], getline(line('.')-2,line('.'))) + " Diaresis + call Put_Dig("a:") + call Put_Dig(":u") + call Put_Dig("b:") " not defined + call assert_equal(['รค', 'รผ', ':'], getline(line('.')-2,line('.'))) + " Cedilla + call Put_Dig("',") + call Put_Dig(",C") + call Put_Dig("b,") " not defined + call assert_equal(['ยธ', 'ร', ','], getline(line('.')-2,line('.'))) + " Underline + call Put_Dig("B_") + call Put_Dig("_t") + call Put_Dig("a_") " not defined + call assert_equal(['แธ', 'แนฏ', '_'], getline(line('.')-2,line('.'))) + " Stroke + call Put_Dig("j/") + call Put_Dig("/l") + call Put_Dig("b/") " not defined + call assert_equal(['/', 'ล', '/'], getline(line('.')-2,line('.'))) + " Double acute + call Put_Dig('O"') + call Put_Dig('"y') + call Put_Dig('b"') " not defined + call assert_equal(['ล', 'รฟ', '"'], getline(line('.')-2,line('.'))) + " Ogonek + call Put_Dig('u;') + call Put_Dig(';E') + call Put_Dig('b;') " not defined + call assert_equal(['ลณ', 'ฤ', ';'], getline(line('.')-2,line('.'))) + " Caron + call Put_Dig('u<') + call Put_Dig('<E') + call Put_Dig('b<') " not defined + call assert_equal(['ว', 'ฤ', '<'], getline(line('.')-2,line('.'))) + " Ring above + call Put_Dig('u0') + call Put_Dig('0E') " not defined + call Put_Dig('b0') " not defined + call assert_equal(['ลฏ', 'E', '0'], getline(line('.')-2,line('.'))) + " Hook + call Put_Dig('u2') + call Put_Dig('2E') + call Put_Dig('b2') " not defined + call assert_equal(['แปง', 'แบบ', '2'], getline(line('.')-2,line('.'))) + " Horn + call Put_Dig('u9') + call Put_Dig('9E') " not defined + call Put_Dig('b9') " not defined + call assert_equal(['ฦฐ', 'E', '9'], getline(line('.')-2,line('.'))) + " Cyrillic + call Put_Dig('u=') + call Put_Dig('=b') + call Put_Dig('=_') + call assert_equal(['ั', 'ะฑ', 'ใ'], getline(line('.')-2,line('.'))) + " Greek + call Put_Dig('u*') + call Put_Dig('*b') + call Put_Dig('*_') + call assert_equal(['ฯ
', 'ฮฒ', 'ใ
'], getline(line('.')-2,line('.'))) + " Greek/Cyrillic special + call Put_Dig('u%') + call Put_Dig('%b') " not defined + call Put_Dig('%_') " not defined + call assert_equal(['ฯ', 'b', '_'], getline(line('.')-2,line('.'))) + " Arabic + call Put_Dig('u+') + call Put_Dig('+b') + call Put_Dig('+_') " japanese industrial symbol + call assert_equal(['+', 'ุจ', 'ใ'], getline(line('.')-2,line('.'))) + " Hebrew + call Put_Dig('Q+') + call Put_Dig('+B') + call Put_Dig('+X') + call assert_equal(['ืง', 'ื', 'ื'], getline(line('.')-2,line('.'))) + " Latin + call Put_Dig('a3') + call Put_Dig('A3') + call Put_Dig('3X') + call assert_equal(['วฃ', 'วข', 'X'], getline(line('.')-2,line('.'))) + " Bopomofo + call Put_Dig('a4') + call Put_Dig('A4') + call Put_Dig('4X') + call assert_equal(['ใ', '4', 'X'], getline(line('.')-2,line('.'))) + " Hiragana + call Put_Dig('a5') + call Put_Dig('A5') + call Put_Dig('5X') + call assert_equal(['ใ', 'ใ', 'X'], getline(line('.')-2,line('.'))) + " Katakana + call Put_Dig('a6') + call Put_Dig('A6') + call Put_Dig('6X') + call assert_equal(['ใก', 'ใข', 'X'], getline(line('.')-2,line('.'))) + " Superscripts + call Put_Dig('1S') + call Put_Dig('2S') + call Put_Dig('3S') + call assert_equal(['ยน', 'ยฒ', 'ยณ'], getline(line('.')-2,line('.'))) + " Subscripts + call Put_Dig('1s') + call Put_Dig('2s') + call Put_Dig('3s') + call assert_equal(['โ', 'โ', 'โ'], getline(line('.')-2,line('.'))) + " Eszet (only lowercase) + call Put_Dig("ss") + call Put_Dig("SS") " start of string + call assert_equal(["ร", "ย"], getline(line('.')-1,line('.'))) + " High bit set + call Put_Dig("a ") + call Put_Dig(" A") + call assert_equal(['รก', 'ร'], getline(line('.')-1,line('.'))) + " Escape is not part of a digraph + call Put_Dig("a\<esc>") + call Put_Dig("\<esc>A") + call assert_equal(['', 'A'], getline(line('.')-1,line('.'))) + " define some custom digraphs + " old: 00 โ + " old: el l + digraph 00 9216 + digraph el 0252 + call Put_Dig("00") + call Put_Dig("el") + " Reset digraphs + digraph 00 8734 + digraph el 108 + call Put_Dig("00") + call Put_Dig("el") + call assert_equal(['โ', 'รผ', 'โ', 'l'], getline(line('.')-3,line('.'))) + bw! +endfunc + +func! Test_digraphs_option() + " reset whichwrap option, so that testing <esc><bs>A works, + " without moving up a line + set digraph ww= + new + call Put_Dig_BS("0","0") + call assert_equal("โ", getline('.')) + " not a digraph + call Put_Dig_BS("e","l") + call assert_equal("l", getline('.')) + call Put_Dig_BS("h","t") + call assert_equal("รพ", getline('.')) + " digraph "ab" is the same as "ba" + call Put_Dig_BS("a","b") + call Put_Dig_BS("b","a") + call assert_equal(["ใฐ","ใฐ"], getline(line('.')-1,line('.'))) + " Euro sign + call Put_Dig_BS("e","=") + call Put_Dig_BS("=","e") + call Put_Dig_BS("E","u") + call Put_Dig_BS("u","E") + call assert_equal(['ะต']+repeat(["โฌ"],3), getline(line('.')-3,line('.'))) + " Rouble sign + call Put_Dig_BS("R","=") + call Put_Dig_BS("=","R") + call Put_Dig_BS("=","P") + call Put_Dig_BS("P","=") + call assert_equal(['ะ ']+repeat(["โฝ"],2)+['ะ'], getline(line('.')-3,line('.'))) + " Not a digraph: this is different from <c-k>! + call Put_Dig_BS("a","\<bs>") + call Put_Dig_BS("\<bs>","a") + call assert_equal(['','a'], getline(line('.')-1,line('.'))) + " Grave + call Put_Dig_BS("a","!") + call Put_Dig_BS("!","e") + call Put_Dig_BS("b","!") " not defined + call assert_equal(["ร ", "รจ", "!"], getline(line('.')-2,line('.'))) + " Acute accent + call Put_Dig_BS("a","'") + call Put_Dig_BS("'","e") + call Put_Dig_BS("b","'") " not defined + call assert_equal(["รก", "รฉ", "'"], getline(line('.')-2,line('.'))) + " Cicumflex + call Put_Dig_BS("a",">") + call Put_Dig_BS(">","e") + call Put_Dig_BS("b",">") " not defined + call assert_equal(['รข', 'รช', '>'], getline(line('.')-2,line('.'))) + " Tilde + call Put_Dig_BS("o","~") + call Put_Dig_BS("~","u") " not defined + call Put_Dig_BS("z","~") " not defined + call assert_equal(['รต', 'u', '~'], getline(line('.')-2,line('.'))) + " Tilde + call Put_Dig_BS("o","?") + call Put_Dig_BS("?","u") + call Put_Dig_BS("z","?") " not defined + call assert_equal(['รต', 'ลฉ', '?'], getline(line('.')-2,line('.'))) + " Macron + call Put_Dig_BS("o","-") + call Put_Dig_BS("-","u") + call Put_Dig_BS("z","-") " not defined + call assert_equal(['ล', 'ลซ', '-'], getline(line('.')-2,line('.'))) + " Breve + call Put_Dig_BS("o","(") + call Put_Dig_BS("(","u") + call Put_Dig_BS("z","(") " not defined + call assert_equal(['ล', 'ลญ', '('], getline(line('.')-2,line('.'))) + " Dot above + call Put_Dig_BS("b",".") + call Put_Dig_BS(".","e") + call Put_Dig_BS("a",".") " not defined + call assert_equal(['แธ', 'ฤ', '.'], getline(line('.')-2,line('.'))) + " Diaresis + call Put_Dig_BS("a",":") + call Put_Dig_BS(":","u") + call Put_Dig_BS("b",":") " not defined + call assert_equal(['รค', 'รผ', ':'], getline(line('.')-2,line('.'))) + " Cedilla + call Put_Dig_BS("'",",") + call Put_Dig_BS(",","C") + call Put_Dig_BS("b",",") " not defined + call assert_equal(['ยธ', 'ร', ','], getline(line('.')-2,line('.'))) + " Underline + call Put_Dig_BS("B","_") + call Put_Dig_BS("_","t") + call Put_Dig_BS("a","_") " not defined + call assert_equal(['แธ', 'แนฏ', '_'], getline(line('.')-2,line('.'))) + " Stroke + call Put_Dig_BS("j","/") + call Put_Dig_BS("/","l") + call Put_Dig_BS("b","/") " not defined + call assert_equal(['/', 'ล', '/'], getline(line('.')-2,line('.'))) + " Double acute + call Put_Dig_BS('O','"') + call Put_Dig_BS('"','y') + call Put_Dig_BS('b','"') " not defined + call assert_equal(['ล', 'รฟ', '"'], getline(line('.')-2,line('.'))) + " Ogonek + call Put_Dig_BS('u',';') + call Put_Dig_BS(';','E') + call Put_Dig_BS('b',';') " not defined + call assert_equal(['ลณ', 'ฤ', ';'], getline(line('.')-2,line('.'))) + " Caron + call Put_Dig_BS('u','<') + call Put_Dig_BS('<','E') + call Put_Dig_BS('b','<') " not defined + call assert_equal(['ว', 'ฤ', '<'], getline(line('.')-2,line('.'))) + " Ring above + call Put_Dig_BS('u','0') + call Put_Dig_BS('0','E') " not defined + call Put_Dig_BS('b','0') " not defined + call assert_equal(['ลฏ', 'E', '0'], getline(line('.')-2,line('.'))) + " Hook + call Put_Dig_BS('u','2') + call Put_Dig_BS('2','E') + call Put_Dig_BS('b','2') " not defined + call assert_equal(['แปง', 'แบบ', '2'], getline(line('.')-2,line('.'))) + " Horn + call Put_Dig_BS('u','9') + call Put_Dig_BS('9','E') " not defined + call Put_Dig_BS('b','9') " not defined + call assert_equal(['ฦฐ', 'E', '9'], getline(line('.')-2,line('.'))) + " Cyrillic + call Put_Dig_BS('u','=') + call Put_Dig_BS('=','b') + call Put_Dig_BS('=','_') + call assert_equal(['ั', 'ะฑ', 'ใ'], getline(line('.')-2,line('.'))) + " Greek + call Put_Dig_BS('u','*') + call Put_Dig_BS('*','b') + call Put_Dig_BS('*','_') + call assert_equal(['ฯ
', 'ฮฒ', 'ใ
'], getline(line('.')-2,line('.'))) + " Greek/Cyrillic special + call Put_Dig_BS('u','%') + call Put_Dig_BS('%','b') " not defined + call Put_Dig_BS('%','_') " not defined + call assert_equal(['ฯ', 'b', '_'], getline(line('.')-2,line('.'))) + " Arabic + call Put_Dig_BS('u','+') + call Put_Dig_BS('+','b') + call Put_Dig_BS('+','_') " japanese industrial symbol + call assert_equal(['+', 'ุจ', 'ใ'], getline(line('.')-2,line('.'))) + " Hebrew + call Put_Dig_BS('Q','+') + call Put_Dig_BS('+','B') + call Put_Dig_BS('+','X') + call assert_equal(['ืง', 'ื', 'ื'], getline(line('.')-2,line('.'))) + " Latin + call Put_Dig_BS('a','3') + call Put_Dig_BS('A','3') + call Put_Dig_BS('3','X') + call assert_equal(['วฃ', 'วข', 'X'], getline(line('.')-2,line('.'))) + " Bopomofo + call Put_Dig_BS('a','4') + call Put_Dig_BS('A','4') + call Put_Dig_BS('4','X') + call assert_equal(['ใ', '4', 'X'], getline(line('.')-2,line('.'))) + " Hiragana + call Put_Dig_BS('a','5') + call Put_Dig_BS('A','5') + call Put_Dig_BS('5','X') + call assert_equal(['ใ', 'ใ', 'X'], getline(line('.')-2,line('.'))) + " Katakana + call Put_Dig_BS('a','6') + call Put_Dig_BS('A','6') + call Put_Dig_BS('6','X') + call assert_equal(['ใก', 'ใข', 'X'], getline(line('.')-2,line('.'))) + " Superscripts + call Put_Dig_BS('1','S') + call Put_Dig_BS('2','S') + call Put_Dig_BS('3','S') + call assert_equal(['ยน', 'ยฒ', 'ยณ'], getline(line('.')-2,line('.'))) + " Subscripts + call Put_Dig_BS('1','s') + call Put_Dig_BS('2','s') + call Put_Dig_BS('3','s') + call assert_equal(['โ', 'โ', 'โ'], getline(line('.')-2,line('.'))) + " Eszet (only lowercase) + call Put_Dig_BS("s","s") + call Put_Dig_BS("S","S") " start of string + call assert_equal(["ร", "ย"], getline(line('.')-1,line('.'))) + " High bit set (different from <c-k>) + call Put_Dig_BS("a"," ") + call Put_Dig_BS(" ","A") + call assert_equal([' ', 'A'], getline(line('.')-1,line('.'))) + " Escape is not part of a digraph (different from <c-k>) + call Put_Dig_BS("a","\<esc>") + call Put_Dig_BS("\<esc>","A") + call assert_equal(['', ''], getline(line('.')-1,line('.'))) + " define some custom digraphs + " old: 00 โ + " old: el l + digraph 00 9216 + digraph el 0252 + call Put_Dig_BS("0","0") + call Put_Dig_BS("e","l") + " Reset digraphs + digraph 00 8734 + digraph el 108 + call Put_Dig_BS("0","0") + call Put_Dig_BS("e","l") + call assert_equal(['โ', 'รผ', 'โ', 'l'], getline(line('.')-3,line('.'))) + set nodigraph ww&vim + bw! +endfunc + +func! Test_digraphs_output() + new + let out = execute(':digraph') + call assert_equal('Eu โฌ 8364', matchstr(out, '\C\<Eu\D*8364\>')) + call assert_equal('=e โฌ 8364', matchstr(out, '\C=e\D*8364\>')) + call assert_equal('=R โฝ 8381', matchstr(out, '\C=R\D*8381\>')) + call assert_equal('=P โฝ 8381', matchstr(out, '\C=P\D*8381\>')) + call assert_equal('o: รถ 246', matchstr(out, '\C\<o:\D*246\>')) + call assert_equal('v4 ใช 12586', matchstr(out, '\C\<v4\D*12586\>')) + call assert_equal("'0 ห 730", matchstr(out, '\C''0\D*730\>')) + call assert_equal('Z% ะ 1046', matchstr(out, '\C\<Z%\D*1046\>')) + call assert_equal('u- ลซ 363', matchstr(out, '\C\<u-\D*363\>')) + call assert_equal('SH ^A 1', matchstr(out, '\C\<SH\D*1\>')) + bw! +endfunc + +func! Test_loadkeymap() + if !has('keymap') + return + endif + new + set keymap=czech + set iminsert=0 + call feedkeys("o|\<c-^>|01234567890|\<esc>", 'tx') + call assert_equal("|'รฉ+ฤลกฤลลพรฝรกรญรฉ'", getline('.')) + " reset keymap and encoding option + set keymap= + bw! +endfunc + +func! Test_digraph_cmndline() + " Create digraph on commandline + " This is a hack, to let Vim create the digraph in commandline mode + let s = '' + exe "sil! norm! :let s.='\<c-k>Eu'\<cr>" + call assert_equal("โฌ", s) +endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_display.vim b/src/nvim/testdir/test_display.vim new file mode 100644 index 0000000000..0ed672d577 --- /dev/null +++ b/src/nvim/testdir/test_display.vim @@ -0,0 +1,71 @@ +" Test for displaying stuff + +" Nvim: `:set term` is not supported. +" if !has('gui_running') && has('unix') +" set term=ansi +" endif + +source view_util.vim + +func! Test_display_foldcolumn() + if !has("folding") + return + endif + new + vnew + vert resize 25 + call assert_equal(25, winwidth(winnr())) + set isprint=@ + + 1put='e more noise blah blahย more stuff here' + + let expect = [ + \ "e more noise blah blah<82", + \ "> more stuff here " + \ ] + + call cursor(2, 1) + norm! zt + let lines=ScreenLines([1,2], winwidth(0)) + call assert_equal(expect, lines) + set fdc=2 + let lines=ScreenLines([1,2], winwidth(0)) + let expect = [ + \ " e more noise blah blah<", + \ " 82> more stuff here " + \ ] + call assert_equal(expect, lines) + + quit! + quit! +endfunc + +func! Test_display_foldtext_mbyte() + if !has("folding") || !has("multi_byte") + return + endif + call NewWindow(10, 40) + call append(0, range(1,20)) + exe "set foldmethod=manual foldtext=foldtext() fillchars=fold:\u2500,vert:\u2502 fdc=2" + call cursor(2, 1) + norm! zf13G + let lines=ScreenLines([1,3], winwidth(0)+1) + let expect=[ + \ " 1 \u2502", + \ "+ +-- 12 lines: 2". repeat("\u2500", 23). "\u2502", + \ " 14 \u2502", + \ ] + call assert_equal(expect, lines) + + set fillchars=fold:-,vert:\| + let lines=ScreenLines([1,3], winwidth(0)+1) + let expect=[ + \ " 1 |", + \ "+ +-- 12 lines: 2". repeat("-", 23). "|", + \ " 14 |", + \ ] + call assert_equal(expect, lines) + + set foldtext& fillchars& foldmethod& fdc& + bw! +endfunc diff --git a/src/nvim/testdir/test_expr.vim b/src/nvim/testdir/test_expr.vim index 7483973fca..d32facaa98 100644 --- a/src/nvim/testdir/test_expr.vim +++ b/src/nvim/testdir/test_expr.vim @@ -1,20 +1,5 @@ " Tests for expressions. -func Test_version() - call assert_true(has('patch-7.4.001')) - call assert_true(has('patch-7.4.01')) - call assert_true(has('patch-7.4.1')) - call assert_true(has('patch-6.9.999')) - call assert_true(has('patch-7.1.999')) - call assert_true(has('patch-7.4.123')) - - call assert_false(has('patch-7')) - call assert_false(has('patch-7.4')) - call assert_false(has('patch-7.4.')) - call assert_false(has('patch-9.1.0')) - call assert_false(has('patch-9.9.1')) -endfunc - func Test_equal() let base = {} func base.method() @@ -37,6 +22,35 @@ func Test_equal() call assert_fails('echo base.method > instance.method') endfunc +func Test_version() + call assert_true(has('patch-7.4.001')) + call assert_true(has('patch-7.4.01')) + call assert_true(has('patch-7.4.1')) + call assert_true(has('patch-6.9.999')) + call assert_true(has('patch-7.1.999')) + call assert_true(has('patch-7.4.123')) + + call assert_false(has('patch-7')) + call assert_false(has('patch-7.4')) + call assert_false(has('patch-7.4.')) + call assert_false(has('patch-9.1.0')) + call assert_false(has('patch-9.9.1')) +endfunc + +func Test_dict() + let d = {'': 'empty', 'a': 'a', 0: 'zero'} + call assert_equal('empty', d['']) + call assert_equal('a', d['a']) + call assert_equal('zero', d[0]) + call assert_true(has_key(d, '')) + call assert_true(has_key(d, 'a')) + + let d[''] = 'none' + let d['a'] = 'aaa' + call assert_equal('none', d['']) + call assert_equal('aaa', d['a']) +endfunc + func Test_strgetchar() call assert_equal(char2nr('a'), strgetchar('axb', 0)) call assert_equal(char2nr('x'), strgetchar('axb', 1)) @@ -61,24 +75,10 @@ func Test_strcharpart() call assert_equal('a', strcharpart('axb', -1, 2)) endfunc -func Test_dict() - let d = {'': 'empty', 'a': 'a', 0: 'zero'} - call assert_equal('empty', d['']) - call assert_equal('a', d['a']) - call assert_equal('zero', d[0]) - call assert_true(has_key(d, '')) - call assert_true(has_key(d, 'a')) - - let d[''] = 'none' - let d['a'] = 'aaa' - call assert_equal('none', d['']) - call assert_equal('aaa', d['a']) -endfunc - func Test_loop_over_null_list() let null_list = submatch(1, 1) for i in null_list - call assert_true(0, 'should not get here') + call assert_report('should not get here') endfor endfunc @@ -92,3 +92,350 @@ endfunc func Test_set_reg_null_list() call setreg('x', v:_null_list) endfunc + +func Test_special_char() + " The failure is only visible using valgrind. + call assert_fails('echo "\<C-">') +endfunc + +func Test_option_value() + " boolean + set bri + call assert_equal(1, &bri) + set nobri + call assert_equal(0, &bri) + + " number + set ts=1 + call assert_equal(1, &ts) + set ts=8 + call assert_equal(8, &ts) + + " string + exe "set cedit=\<Esc>" + call assert_equal("\<Esc>", &cedit) + set cpo= + call assert_equal("", &cpo) + set cpo=abcdefi + call assert_equal("abcdefi", &cpo) + set cpo&vim +endfunc + +function Test_printf_64bit() + if has('num64') + call assert_equal("123456789012345", printf('%d', 123456789012345)) + endif +endfunc + +func Test_setmatches() + hi def link 1 Comment + hi def link 2 PreProc + let set = [{"group": 1, "pattern": 2, "id": 3, "priority": 4}] + let exp = [{"group": '1', "pattern": '2', "id": 3, "priority": 4}] + if has('conceal') + let set[0]['conceal'] = 5 + let exp[0]['conceal'] = '5' + endif + call setmatches(set) + call assert_equal(exp, getmatches()) +endfunc + +function Test_printf_spec_s() + " number + call assert_equal("1234567890", printf('%s', 1234567890)) + + " string + call assert_equal("abcdefgi", printf('%s', "abcdefgi")) + + " float + call assert_equal("1.23", printf('%s', 1.23)) + + " list + let value = [1, 'two', ['three', 4]] + call assert_equal(string(value), printf('%s', value)) + + " dict + let value = {'key1' : 'value1', 'key2' : ['list', 'value'], 'key3' : {'dict' : 'value'}} + call assert_equal(string(value), printf('%s', value)) + + " funcref + call assert_equal('printf', printf('%s', function('printf'))) + + " partial + call assert_equal(string(function('printf', ['%s'])), printf('%s', function('printf', ['%s']))) +endfunc + +function Test_printf_misc() + call assert_equal('123', printf('%d', 123)) + call assert_equal('123', printf('%i', 123)) + call assert_equal('123', printf('%D', 123)) + call assert_equal('123', printf('%U', 123)) + call assert_equal('173', printf('%o', 123)) + call assert_equal('173', printf('%O', 123)) + call assert_equal('7b', printf('%x', 123)) + call assert_equal('7B', printf('%X', 123)) + call assert_equal('{', printf('%c', 123)) + call assert_equal('abc', printf('%s', 'abc')) + call assert_equal('abc', printf('%S', 'abc')) + + call assert_equal('+123', printf('%+d', 123)) + call assert_equal('-123', printf('%+d', -123)) + call assert_equal('+123', printf('%+ d', 123)) + call assert_equal(' 123', printf('% d', 123)) + call assert_equal(' 123', printf('% d', 123)) + call assert_equal('-123', printf('% d', -123)) + + call assert_equal('123', printf('%2d', 123)) + call assert_equal(' 123', printf('%6d', 123)) + call assert_equal('000123', printf('%06d', 123)) + call assert_equal('+00123', printf('%+06d', 123)) + call assert_equal(' 00123', printf('% 06d', 123)) + call assert_equal(' +123', printf('%+6d', 123)) + call assert_equal(' 123', printf('% 6d', 123)) + call assert_equal(' -123', printf('% 6d', -123)) + + " Test left adjusted. + call assert_equal('123 ', printf('%-6d', 123)) + call assert_equal('+123 ', printf('%-+6d', 123)) + call assert_equal(' 123 ', printf('%- 6d', 123)) + call assert_equal('-123 ', printf('%- 6d', -123)) + + call assert_equal(' 00123', printf('%7.5d', 123)) + call assert_equal(' -00123', printf('%7.5d', -123)) + call assert_equal(' +00123', printf('%+7.5d', 123)) + " Precision field should not be used when combined with %0 + call assert_equal(' 00123', printf('%07.5d', 123)) + call assert_equal(' -00123', printf('%07.5d', -123)) + + call assert_equal(' 123', printf('%*d', 5, 123)) + call assert_equal('123 ', printf('%*d', -5, 123)) + call assert_equal('00123', printf('%.*d', 5, 123)) + call assert_equal(' 123', printf('% *d', 5, 123)) + call assert_equal(' +123', printf('%+ *d', 5, 123)) + + " Simple quote (thousand grouping char) is ignored. + call assert_equal('+00123456', printf("%+'09d", 123456)) + + " Unrecognized format specifier kept as-is. + call assert_equal('_123', printf("%_%d", 123)) + + " Test alternate forms. + call assert_equal('0x7b', printf('%#x', 123)) + call assert_equal('0X7B', printf('%#X', 123)) + call assert_equal('0173', printf('%#o', 123)) + call assert_equal('0173', printf('%#O', 123)) + call assert_equal('abc', printf('%#s', 'abc')) + call assert_equal('abc', printf('%#S', 'abc')) + call assert_equal(' 0173', printf('%#6o', 123)) + call assert_equal(' 00173', printf('%#6.5o', 123)) + call assert_equal(' 0173', printf('%#6.2o', 123)) + call assert_equal(' 0173', printf('%#6.2o', 123)) + call assert_equal('0173', printf('%#2.2o', 123)) + + call assert_equal(' 00123', printf('%6.5d', 123)) + call assert_equal(' 0007b', printf('%6.5x', 123)) + + call assert_equal('abc', printf('%2s', 'abc')) + call assert_equal('abc', printf('%2S', 'abc')) + call assert_equal('abc', printf('%.4s', 'abc')) + call assert_equal('abc', printf('%.4S', 'abc')) + call assert_equal('ab', printf('%.2s', 'abc')) + call assert_equal('ab', printf('%.2S', 'abc')) + call assert_equal('', printf('%.0s', 'abc')) + call assert_equal('', printf('%.s', 'abc')) + call assert_equal(' abc', printf('%4s', 'abc')) + call assert_equal(' abc', printf('%4S', 'abc')) + call assert_equal('0abc', printf('%04s', 'abc')) + call assert_equal('0abc', printf('%04S', 'abc')) + call assert_equal('abc ', printf('%-4s', 'abc')) + call assert_equal('abc ', printf('%-4S', 'abc')) + + call assert_equal('1%', printf('%d%%', 1)) +endfunc + +function Test_printf_float() + call assert_equal('1.000000', printf('%f', 1)) + call assert_equal('1.230000', printf('%f', 1.23)) + call assert_equal('1.230000', printf('%F', 1.23)) + call assert_equal('9999999.9', printf('%g', 9999999.9)) + call assert_equal('9999999.9', printf('%G', 9999999.9)) + call assert_equal('1.00000001e7', printf('%.8g', 10000000.1)) + call assert_equal('1.00000001E7', printf('%.8G', 10000000.1)) + call assert_equal('1.230000e+00', printf('%e', 1.23)) + call assert_equal('1.230000E+00', printf('%E', 1.23)) + call assert_equal('1.200000e-02', printf('%e', 0.012)) + call assert_equal('-1.200000e-02', printf('%e', -0.012)) + call assert_equal('0.33', printf('%.2f', 1.0/3.0)) + call assert_equal(' 0.33', printf('%6.2f', 1.0/3.0)) + call assert_equal(' -0.33', printf('%6.2f', -1.0/3.0)) + call assert_equal('000.33', printf('%06.2f', 1.0/3.0)) + call assert_equal('-00.33', printf('%06.2f', -1.0/3.0)) + call assert_equal('-00.33', printf('%+06.2f', -1.0/3.0)) + call assert_equal('+00.33', printf('%+06.2f', 1.0/3.0)) + call assert_equal(' 00.33', printf('% 06.2f', 1.0/3.0)) + call assert_equal('000.33', printf('%06.2g', 1.0/3.0)) + call assert_equal('-00.33', printf('%06.2g', -1.0/3.0)) + call assert_equal('0.33', printf('%3.2f', 1.0/3.0)) + call assert_equal('003.33e-01', printf('%010.2e', 1.0/3.0)) + call assert_equal(' 03.33e-01', printf('% 010.2e', 1.0/3.0)) + call assert_equal('+03.33e-01', printf('%+010.2e', 1.0/3.0)) + call assert_equal('-03.33e-01', printf('%010.2e', -1.0/3.0)) + + " When precision is 0, the dot should be omitted. + call assert_equal(' 2', printf('%3.f', 7.0/3.0)) + call assert_equal(' 2', printf('%3.g', 7.0/3.0)) + call assert_equal(' 2e+00', printf('%7.e', 7.0/3.0)) + + " Float zero can be signed. + call assert_equal('+0.000000', printf('%+f', 0.0)) + call assert_equal('0.000000', printf('%f', 1.0/(1.0/0.0))) + call assert_equal('-0.000000', printf('%f', 1.0/(-1.0/0.0))) + call assert_equal('0.0', printf('%s', 1.0/(1.0/0.0))) + call assert_equal('-0.0', printf('%s', 1.0/(-1.0/0.0))) + call assert_equal('0.0', printf('%S', 1.0/(1.0/0.0))) + call assert_equal('-0.0', printf('%S', 1.0/(-1.0/0.0))) + + " Float infinity can be signed. + call assert_equal('inf', printf('%f', 1.0/0.0)) + call assert_equal('-inf', printf('%f', -1.0/0.0)) + call assert_equal('inf', printf('%g', 1.0/0.0)) + call assert_equal('-inf', printf('%g', -1.0/0.0)) + call assert_equal('inf', printf('%e', 1.0/0.0)) + call assert_equal('-inf', printf('%e', -1.0/0.0)) + call assert_equal('INF', printf('%F', 1.0/0.0)) + call assert_equal('-INF', printf('%F', -1.0/0.0)) + call assert_equal('INF', printf('%E', 1.0/0.0)) + call assert_equal('-INF', printf('%E', -1.0/0.0)) + call assert_equal('INF', printf('%E', 1.0/0.0)) + call assert_equal('-INF', printf('%G', -1.0/0.0)) + call assert_equal('+inf', printf('%+f', 1.0/0.0)) + call assert_equal('-inf', printf('%+f', -1.0/0.0)) + call assert_equal(' inf', printf('% f', 1.0/0.0)) + call assert_equal(' inf', printf('%6f', 1.0/0.0)) + call assert_equal(' -inf', printf('%6f', -1.0/0.0)) + call assert_equal(' inf', printf('%6g', 1.0/0.0)) + call assert_equal(' -inf', printf('%6g', -1.0/0.0)) + call assert_equal(' +inf', printf('%+6f', 1.0/0.0)) + call assert_equal(' inf', printf('% 6f', 1.0/0.0)) + call assert_equal(' +inf', printf('%+06f', 1.0/0.0)) + call assert_equal('inf ', printf('%-6f', 1.0/0.0)) + call assert_equal('-inf ', printf('%-6f', -1.0/0.0)) + call assert_equal('+inf ', printf('%-+6f', 1.0/0.0)) + call assert_equal(' inf ', printf('%- 6f', 1.0/0.0)) + call assert_equal('-INF ', printf('%-6F', -1.0/0.0)) + call assert_equal('+INF ', printf('%-+6F', 1.0/0.0)) + call assert_equal(' INF ', printf('%- 6F', 1.0/0.0)) + call assert_equal('INF ', printf('%-6G', 1.0/0.0)) + call assert_equal('-INF ', printf('%-6G', -1.0/0.0)) + call assert_equal('INF ', printf('%-6E', 1.0/0.0)) + call assert_equal('-INF ', printf('%-6E', -1.0/0.0)) + call assert_equal("str2float('inf')", printf('%s', 1.0/0.0)) + call assert_equal("-str2float('inf')", printf('%s', -1.0/0.0)) + + " Float nan (not a number) has no sign. + call assert_equal('nan', printf('%f', sqrt(-1.0))) + call assert_equal('nan', printf('%f', 0.0/0.0)) + call assert_equal('nan', printf('%f', -0.0/0.0)) + call assert_equal('nan', printf('%g', 0.0/0.0)) + call assert_equal('nan', printf('%e', 0.0/0.0)) + call assert_equal('NAN', printf('%F', 0.0/0.0)) + call assert_equal('NAN', printf('%G', 0.0/0.0)) + call assert_equal('NAN', printf('%E', 0.0/0.0)) + call assert_equal('NAN', printf('%F', -0.0/0.0)) + call assert_equal('NAN', printf('%G', -0.0/0.0)) + call assert_equal('NAN', printf('%E', -0.0/0.0)) + call assert_equal(' nan', printf('%6f', 0.0/0.0)) + call assert_equal(' nan', printf('%06f', 0.0/0.0)) + call assert_equal('nan ', printf('%-6f', 0.0/0.0)) + call assert_equal('nan ', printf('%- 6f', 0.0/0.0)) + call assert_equal("str2float('nan')", printf('%s', 0.0/0.0)) + call assert_equal("str2float('nan')", printf('%s', -0.0/0.0)) + call assert_equal("str2float('nan')", printf('%S', 0.0/0.0)) + call assert_equal("str2float('nan')", printf('%S', -0.0/0.0)) + + call assert_fails('echo printf("%f", "a")', 'E807:') +endfunc + +function Test_printf_errors() + call assert_fails('echo printf("%d", {})', 'E728:') + call assert_fails('echo printf("%d", [])', 'E745:') + call assert_fails('echo printf("%d", 1, 2)', 'E767:') + call assert_fails('echo printf("%*d", 1)', 'E766:') + call assert_fails('echo printf("%d", 1.2)', 'E805:') +endfunc + +function Test_max_min_errors() + call assert_fails('call max(v:true)', 'E712:') + call assert_fails('call max(v:true)', 'max()') + call assert_fails('call min(v:true)', 'E712:') + call assert_fails('call min(v:true)', 'min()') +endfunc + +func Test_substitute_expr() + let g:val = 'XXX' + call assert_equal('XXX', substitute('yyy', 'y*', '\=g:val', '')) + call assert_equal('XXX', substitute('yyy', 'y*', {-> g:val}, '')) + call assert_equal("-\u1b \uf2-", substitute("-%1b %f2-", '%\(\x\x\)', + \ '\=nr2char("0x" . submatch(1))', 'g')) + call assert_equal("-\u1b \uf2-", substitute("-%1b %f2-", '%\(\x\x\)', + \ {-> nr2char("0x" . submatch(1))}, 'g')) + + call assert_equal('231', substitute('123', '\(.\)\(.\)\(.\)', + \ {-> submatch(2) . submatch(3) . submatch(1)}, '')) + + func Recurse() + return substitute('yyy', 'y\(.\)y', {-> submatch(1)}, '') + endfunc + " recursive call works + call assert_equal('-y-x-', substitute('xxx', 'x\(.\)x', {-> '-' . Recurse() . '-' . submatch(1) . '-'}, '')) +endfunc + +func Test_invalid_submatch() + " This was causing invalid memory access in Vim-7.4.2232 and older + call assert_fails("call substitute('x', '.', {-> submatch(10)}, '')", 'E935:') +endfunc + +func Test_substitute_expr_arg() + call assert_equal('123456789-123456789=', substitute('123456789', + \ '\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)', + \ {m -> m[0] . '-' . m[1] . m[2] . m[3] . m[4] . m[5] . m[6] . m[7] . m[8] . m[9] . '='}, '')) + + call assert_equal('123456-123456=789', substitute('123456789', + \ '\(.\)\(.\)\(.\)\(a*\)\(n*\)\(.\)\(.\)\(.\)\(x*\)', + \ {m -> m[0] . '-' . m[1] . m[2] . m[3] . m[4] . m[5] . m[6] . m[7] . m[8] . m[9] . '='}, '')) + + call assert_equal('123456789-123456789x=', substitute('123456789', + \ '\(.\)\(.\)\(.*\)', + \ {m -> m[0] . '-' . m[1] . m[2] . m[3] . 'x' . m[4] . m[5] . m[6] . m[7] . m[8] . m[9] . '='}, '')) + + call assert_fails("call substitute('xxx', '.', {m -> string(add(m, 'x'))}, '')", 'E742:') + call assert_fails("call substitute('xxx', '.', {m -> string(insert(m, 'x'))}, '')", 'E742:') + call assert_fails("call substitute('xxx', '.', {m -> string(extend(m, ['x']))}, '')", 'E742:') + call assert_fails("call substitute('xxx', '.', {m -> string(remove(m, 1))}, '')", 'E742:') +endfunc + +func Test_function_with_funcref() + let s:f = function('type') + let s:fref = function(s:f) + call assert_equal(v:t_string, s:fref('x')) + call assert_fails("call function('s:f')", 'E700:') + + call assert_fails("call function('foo()')", 'E475:') + call assert_fails("call function('foo()')", 'foo()') +endfunc + +func Test_funcref() + func! One() + return 1 + endfunc + let OneByName = function('One') + let OneByRef = funcref('One') + func! One() + return 2 + endfunc + call assert_equal(2, OneByName()) + call assert_equal(1, OneByRef()) + let OneByRef = funcref('One') + call assert_equal(2, OneByRef()) + call assert_fails('echo funcref("{")', 'E475:') +endfunc diff --git a/src/nvim/testdir/test_expr_utf8.vim b/src/nvim/testdir/test_expr_utf8.vim index 097d708329..9ea6d8872b 100644 --- a/src/nvim/testdir/test_expr_utf8.vim +++ b/src/nvim/testdir/test_expr_utf8.vim @@ -35,60 +35,3 @@ func Test_strcharpart_utf8() call assert_equal('ฬ', strcharpart('aฬxb', 1, 1)) call assert_equal('x', strcharpart('aฬxb', 2, 1)) endfunc - -func s:classes_test() - set isprint=@,161-255 - call assert_equal('Motรถrhead', matchstr('Motรถrhead', '[[:print:]]\+')) - - let alphachars = '' - let lowerchars = '' - let upperchars = '' - let alnumchars = '' - let printchars = '' - let punctchars = '' - let xdigitchars = '' - let i = 1 - while i <= 255 - let c = nr2char(i) - if c =~ '[[:alpha:]]' - let alphachars .= c - endif - if c =~ '[[:lower:]]' - let lowerchars .= c - endif - if c =~ '[[:upper:]]' - let upperchars .= c - endif - if c =~ '[[:alnum:]]' - let alnumchars .= c - endif - if c =~ '[[:print:]]' - let printchars .= c - endif - if c =~ '[[:punct:]]' - let punctchars .= c - endif - if c =~ '[[:xdigit:]]' - let xdigitchars .= c - endif - let i += 1 - endwhile - - call assert_equal('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', alphachars) - call assert_equal('abcdefghijklmnopqrstuvwxyzยตรร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรธรนรบรปรผรฝรพรฟ', lowerchars) - call assert_equal('ABCDEFGHIJKLMNOPQRSTUVWXYZรรรรรร
รรรรรรรรรรรรรรรรรรรรรรรร', upperchars) - call assert_equal('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', alnumchars) - call assert_equal(' !"#$%&''()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ย ยกยขยฃยคยฅยฆยงยจยฉยชยซยฌยญยฎยฏยฐยฑยฒยณยดยตยถยทยธยนยบยปยผยฝยพยฟรรรรรร
รรรรรรรรรรรรรรรรรรรรรรรรรรร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรทรธรนรบรปรผรฝรพรฟ', printchars) - call assert_equal('!"#$%&''()*+,-./:;<=>?@[\]^_`{|}~', punctchars) - call assert_equal('0123456789ABCDEFabcdef', xdigitchars) -endfunc - -func Test_classes_re1() - set re=1 - call s:classes_test() -endfunc - -func Test_classes_re2() - set re=2 - call s:classes_test() -endfunc diff --git a/src/nvim/testdir/test_farsi.vim b/src/nvim/testdir/test_farsi.vim new file mode 100644 index 0000000000..e094191599 --- /dev/null +++ b/src/nvim/testdir/test_farsi.vim @@ -0,0 +1,84 @@ +" Simplistic testing of Farsi mode. + +if !has('farsi') || has('nvim') " Not supported in Nvim. #6192 + finish +endif +" Farsi uses a single byte encoding. +set enc=latin1 + +func Test_farsi_toggle() + new + + set altkeymap + call assert_equal(0, &fkmap) + call assert_equal(0, &rl) + call feedkeys("\<F8>", 'x') + call assert_equal(1, &fkmap) + call assert_equal(1, &rl) + call feedkeys("\<F8>", 'x') + call assert_equal(0, &fkmap) + call assert_equal(0, &rl) + + set rl + " conversion from Farsi 3342 to Farsi VIM. + call setline(1, join(map(range(0x80, 0xff), 'nr2char(v:val)'), '')) + call feedkeys("\<F9>", 'x') + let exp = [0xfc, 0xf8, 0xc1, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + \ 0xc8, 0xc9, 0xca, 0xd0, 0xd1, 0xd2, 0xd3, 0xd6, + \ 0xd6, 0xd6, 0xd7, 0xd7, 0xd7, 0xd8, 0xd9, 0xda, + \ 0xdb, 0xdc, 0xdc, 0xc1, 0xdd, 0xde, 0xe0, 0xe0, + \ 0xe1, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, + \ 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, + \ 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, + \ 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, + \ 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, + \ 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, + \ 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, + \ 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, + \ 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, + \ 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xfb, 0xfb, 0xfe, + \ 0xfe, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, + \ 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xe1, + \ ] + call assert_equal(join(map(exp, 'nr2char(v:val)'), ''), getline(1)) + + " conversion from Farsi VIM to Farsi 3342. + call setline(1, join(map(range(0x80, 0xff), 'nr2char(v:val)'), '')) + call feedkeys("\<F9>", 'x') + let exp = [0xfc, 0xf8, 0xc1, 0x83, 0x84, 0x85, 0x86, 0x87, + \ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x90, + \ 0x90, 0x90, 0x92, 0x93, 0x93, 0x95, 0x96, 0x97, + \ 0x98, 0xdc, 0x9a, 0x9b, 0x9c, 0x9e, 0x9e, 0xff, + \ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + \ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + \ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + \ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + \ 0xc0, 0xc1, 0xc2, 0x83, 0x84, 0x85, 0x86, 0x87, + \ 0x88, 0x89, 0x8a, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + \ 0x8b, 0x8c, 0x8d, 0x8e, 0xd4, 0xd5, 0x90, 0x93, + \ 0x95, 0x96, 0x97, 0x98, 0x99, 0x9b, 0x9c, 0xdf, + \ 0x9d, 0xff, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + \ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xec, 0xee, 0xef, + \ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + \ 0xf8, 0xf9, 0xfa, 0xec, 0x80, 0xfd, 0xee, 0xff, + \ ] + call assert_equal(join(map(exp, 'nr2char(v:val)'), ''), getline(1)) + + bwipe! +endfunc + +func Test_farsi_map() + new + + set altkeymap + set rl + " RHS of mapping is reversed. + imap xyz abc + call feedkeys("axyz\<Esc>", 'tx') + call assert_equal('cba', getline(1)) + + set norl + iunmap xyz + set noaltkeymap + bwipe! +endfunc diff --git a/src/nvim/testdir/test_fileformat.vim b/src/nvim/testdir/test_fileformat.vim new file mode 100644 index 0000000000..584f20cdfc --- /dev/null +++ b/src/nvim/testdir/test_fileformat.vim @@ -0,0 +1,17 @@ +" Test behavior of fileformat after bwipeout of last buffer + +func Test_fileformat_after_bw() + bwipeout + set fileformat& + if &fileformat == 'dos' + let test_fileformats = 'unix' + elseif &fileformat == 'unix' + let test_fileformats = 'mac' + else " must be mac + let test_fileformats = 'dos' + endif + exec 'set fileformats='.test_fileformats + bwipeout! + call assert_equal(test_fileformats, &fileformat) + set fileformats& +endfunc diff --git a/src/nvim/testdir/test_filter_cmd.vim b/src/nvim/testdir/test_filter_cmd.vim new file mode 100644 index 0000000000..5aa5fa64df --- /dev/null +++ b/src/nvim/testdir/test_filter_cmd.vim @@ -0,0 +1,76 @@ +" Test the :filter command modifier + +func Test_filter() + edit Xdoesnotmatch + edit Xwillmatch + call assert_equal('"Xwillmatch"', substitute(execute('filter willma ls'), '[^"]*\(".*"\)[^"]*', '\1', '')) + bwipe Xdoesnotmatch + bwipe Xwillmatch + + new + call setline(1, ['foo1', 'foo2', 'foo3', 'foo4', 'foo5']) + call assert_equal("\nfoo2\nfoo4", execute('filter /foo[24]/ 1,$print')) + call assert_equal("\n 2 foo2\n 4 foo4", execute('filter /foo[24]/ 1,$number')) + call assert_equal("\nfoo2$\nfoo4$", execute('filter /foo[24]/ 1,$list')) + + call assert_equal("\nfoo1$\nfoo3$\nfoo5$", execute('filter! /foo[24]/ 1,$list')) + bwipe! + + command XTryThis echo 'this' + command XTryThat echo 'that' + command XDoThat echo 'that' + let lines = split(execute('filter XTry command'), "\n") + call assert_equal(3, len(lines)) + call assert_match("XTryThat", lines[1]) + call assert_match("XTryThis", lines[2]) + delcommand XTryThis + delcommand XTryThat + delcommand XDoThat + + map f1 the first key + map f2 the second key + map f3 not a key + let lines = split(execute('filter the map f'), "\n") + call assert_equal(2, len(lines)) + call assert_match("f2", lines[0]) + call assert_match("f1", lines[1]) + unmap f1 + unmap f2 + unmap f3 +endfunc + +func Test_filter_fails() + call assert_fails('filter', 'E471:') + call assert_fails('filter pat', 'E476:') + call assert_fails('filter /pat', 'E476:') + call assert_fails('filter /pat/', 'E476:') + call assert_fails('filter /pat/ asdf', 'E492:') + + call assert_fails('filter!', 'E471:') + call assert_fails('filter! pat', 'E476:') + call assert_fails('filter! /pat', 'E476:') + call assert_fails('filter! /pat/', 'E476:') + call assert_fails('filter! /pat/ asdf', 'E492:') +endfunc + +function s:complete_filter_cmd(filtcmd) + let keystroke = "\<TAB>\<C-R>=execute('let cmdline = getcmdline()')\<CR>\<C-C>" + let cmdline = '' + call feedkeys(':' . a:filtcmd . keystroke, 'ntx') + return cmdline +endfunction + +func Test_filter_cmd_completion() + " Do not complete pattern + call assert_equal("filter \t", s:complete_filter_cmd('filter ')) + call assert_equal("filter pat\t", s:complete_filter_cmd('filter pat')) + call assert_equal("filter /pat\t", s:complete_filter_cmd('filter /pat')) + call assert_equal("filter /pat/\t", s:complete_filter_cmd('filter /pat/')) + + " Complete after string pattern + call assert_equal('filter pat print', s:complete_filter_cmd('filter pat pri')) + + " Complete after regexp pattern + call assert_equal('filter /pat/ print', s:complete_filter_cmd('filter /pat/ pri')) + call assert_equal('filter #pat# print', s:complete_filter_cmd('filter #pat# pri')) +endfunc diff --git a/src/nvim/testdir/test_filter_map.vim b/src/nvim/testdir/test_filter_map.vim new file mode 100644 index 0000000000..c8d64ce0a4 --- /dev/null +++ b/src/nvim/testdir/test_filter_map.vim @@ -0,0 +1,81 @@ +" Test filter() and map() + +" list with expression string +func Test_filter_map_list_expr_string() + " filter() + call assert_equal([2, 3, 4], filter([1, 2, 3, 4], 'v:val > 1')) + call assert_equal([3, 4], filter([1, 2, 3, 4], 'v:key > 1')) + call assert_equal([], filter([1, 2, 3, 4], 0)) + + " map() + call assert_equal([2, 4, 6, 8], map([1, 2, 3, 4], 'v:val * 2')) + call assert_equal([0, 2, 4, 6], map([1, 2, 3, 4], 'v:key * 2')) + call assert_equal([9, 9, 9, 9], map([1, 2, 3, 4], 9)) +endfunc + +" dict with expression string +func Test_filter_map_dict_expr_string() + let dict = {"foo": 1, "bar": 2, "baz": 3} + + " filter() + call assert_equal({"bar": 2, "baz": 3}, filter(copy(dict), 'v:val > 1')) + call assert_equal({"foo": 1, "baz": 3}, filter(copy(dict), 'v:key > "bar"')) + call assert_equal({}, filter(copy(dict), 0)) + + " map() + call assert_equal({"foo": 2, "bar": 4, "baz": 6}, map(copy(dict), 'v:val * 2')) + call assert_equal({"foo": "f", "bar": "b", "baz": "b"}, map(copy(dict), 'v:key[0]')) + call assert_equal({"foo": 9, "bar": 9, "baz": 9}, map(copy(dict), 9)) +endfunc + +" list with funcref +func Test_filter_map_list_expr_funcref() + " filter() + func! s:filter1(index, val) abort + return a:val > 1 + endfunc + call assert_equal([2, 3, 4], filter([1, 2, 3, 4], function('s:filter1'))) + + func! s:filter2(index, val) abort + return a:index > 1 + endfunc + call assert_equal([3, 4], filter([1, 2, 3, 4], function('s:filter2'))) + + " map() + func! s:filter3(index, val) abort + return a:val * 2 + endfunc + call assert_equal([2, 4, 6, 8], map([1, 2, 3, 4], function('s:filter3'))) + + func! s:filter4(index, val) abort + return a:index * 2 + endfunc + call assert_equal([0, 2, 4, 6], map([1, 2, 3, 4], function('s:filter4'))) +endfunc + +" dict with funcref +func Test_filter_map_dict_expr_funcref() + let dict = {"foo": 1, "bar": 2, "baz": 3} + + " filter() + func! s:filter1(key, val) abort + return a:val > 1 + endfunc + call assert_equal({"bar": 2, "baz": 3}, filter(copy(dict), function('s:filter1'))) + + func! s:filter2(key, val) abort + return a:key > "bar" + endfunc + call assert_equal({"foo": 1, "baz": 3}, filter(copy(dict), function('s:filter2'))) + + " map() + func! s:filter3(key, val) abort + return a:val * 2 + endfunc + call assert_equal({"foo": 2, "bar": 4, "baz": 6}, map(copy(dict), function('s:filter3'))) + + func! s:filter4(key, val) abort + return a:key[0] + endfunc + call assert_equal({"foo": "f", "bar": "b", "baz": "b"}, map(copy(dict), function('s:filter4'))) +endfunc diff --git a/src/nvim/testdir/test_float_func.vim b/src/nvim/testdir/test_float_func.vim new file mode 100644 index 0000000000..5ea5192994 --- /dev/null +++ b/src/nvim/testdir/test_float_func.vim @@ -0,0 +1,332 @@ +" test float functions + +if !has('float') + finish +end + +func Test_abs() + call assert_equal('1.23', string(abs(1.23))) + call assert_equal('1.23', string(abs(-1.23))) + call assert_equal('0.0', string(abs(0.0))) + call assert_equal('0.0', string(abs(1.0/(1.0/0.0)))) + call assert_equal('0.0', string(abs(-1.0/(1.0/0.0)))) + call assert_equal("str2float('inf')", string(abs(1.0/0.0))) + call assert_equal("str2float('inf')", string(abs(-1.0/0.0))) + call assert_equal("str2float('nan')", string(abs(0.0/0.0))) + call assert_equal('12', string(abs('-12abc'))) + call assert_fails("call abs([])", 'E745:') + call assert_fails("call abs({})", 'E728:') + call assert_fails("call abs(function('string'))", 'E703:') +endfunc + +func Test_sqrt() + call assert_equal('0.0', string(sqrt(0.0))) + call assert_equal('1.414214', string(sqrt(2.0))) + call assert_equal("str2float('inf')", string(sqrt(1.0/0.0))) + call assert_equal("str2float('nan')", string(sqrt(-1.0))) + call assert_equal("str2float('nan')", string(sqrt(0.0/0.0))) + call assert_fails('call sqrt("")', 'E808:') +endfunc + +func Test_log() + call assert_equal('0.0', string(log(1.0))) + call assert_equal('-0.693147', string(log(0.5))) + call assert_equal("-str2float('inf')", string(log(0.0))) + call assert_equal("str2float('nan')", string(log(-1.0))) + call assert_equal("str2float('inf')", string(log(1.0/0.0))) + call assert_equal("str2float('nan')", string(log(0.0/0.0))) + call assert_fails('call log("")', 'E808:') +endfunc + +func Test_log10() + call assert_equal('0.0', string(log10(1.0))) + call assert_equal('2.0', string(log10(100.0))) + call assert_equal('2.079181', string(log10(120.0))) + call assert_equal("-str2float('inf')", string(log10(0.0))) + call assert_equal("str2float('nan')", string(log10(-1.0))) + call assert_equal("str2float('inf')", string(log10(1.0/0.0))) + call assert_equal("str2float('nan')", string(log10(0.0/0.0))) + call assert_fails('call log10("")', 'E808:') +endfunc + +func Test_exp() + call assert_equal('1.0', string(exp(0.0))) + call assert_equal('7.389056', string(exp(2.0))) + call assert_equal('0.367879', string(exp(-1.0))) + call assert_equal("str2float('inf')", string(exp(1.0/0.0))) + call assert_equal('0.0', string(exp(-1.0/0.0))) + call assert_equal("str2float('nan')", string(exp(0.0/0.0))) + call assert_fails('call exp("")', 'E808:') +endfunc + +func Test_sin() + call assert_equal('0.0', string(sin(0.0))) + call assert_equal('0.841471', string(sin(1.0))) + call assert_equal('-0.479426', string(sin(-0.5))) + call assert_equal("str2float('nan')", string(sin(0.0/0.0))) + call assert_equal("str2float('nan')", string(sin(1.0/0.0))) + call assert_equal('0.0', string(sin(1.0/(1.0/0.0)))) + call assert_equal('-0.0', string(sin(-1.0/(1.0/0.0)))) + call assert_fails('call sin("")', 'E808:') +endfunc + +func Test_asin() + call assert_equal('0.0', string(asin(0.0))) + call assert_equal('1.570796', string(asin(1.0))) + call assert_equal('-0.523599', string(asin(-0.5))) + call assert_equal("str2float('nan')", string(asin(1.1))) + call assert_equal("str2float('nan')", string(asin(1.0/0.0))) + call assert_equal("str2float('nan')", string(asin(0.0/0.0))) + call assert_fails('call asin("")', 'E808:') +endfunc + +func Test_sinh() + call assert_equal('0.0', string(sinh(0.0))) + call assert_equal('0.521095', string(sinh(0.5))) + call assert_equal('-1.026517', string(sinh(-0.9))) + call assert_equal("str2float('inf')", string(sinh(1.0/0.0))) + call assert_equal("-str2float('inf')", string(sinh(-1.0/0.0))) + call assert_equal("str2float('nan')", string(sinh(0.0/0.0))) + call assert_fails('call sinh("")', 'E808:') +endfunc + +func Test_cos() + call assert_equal('1.0', string(cos(0.0))) + call assert_equal('0.540302', string(cos(1.0))) + call assert_equal('0.877583', string(cos(-0.5))) + call assert_equal("str2float('nan')", string(cos(0.0/0.0))) + call assert_equal("str2float('nan')", string(cos(1.0/0.0))) + call assert_fails('call cos("")', 'E808:') +endfunc + +func Test_acos() + call assert_equal('1.570796', string(acos(0.0))) + call assert_equal('0.0', string(acos(1.0))) + call assert_equal('3.141593', string(acos(-1.0))) + call assert_equal('2.094395', string(acos(-0.5))) + call assert_equal("str2float('nan')", string(acos(1.1))) + call assert_equal("str2float('nan')", string(acos(1.0/0.0))) + call assert_equal("str2float('nan')", string(acos(0.0/0.0))) + call assert_fails('call acos("")', 'E808:') +endfunc + +func Test_cosh() + call assert_equal('1.0', string(cosh(0.0))) + call assert_equal('1.127626', string(cosh(0.5))) + call assert_equal("str2float('inf')", string(cosh(1.0/0.0))) + call assert_equal("str2float('inf')", string(cosh(-1.0/0.0))) + call assert_equal("str2float('nan')", string(cosh(0.0/0.0))) + call assert_fails('call cosh("")', 'E808:') +endfunc + +func Test_tan() + call assert_equal('0.0', string(tan(0.0))) + call assert_equal('0.546302', string(tan(0.5))) + call assert_equal('-0.546302', string(tan(-0.5))) + call assert_equal("str2float('nan')", string(tan(1.0/0.0))) + call assert_equal("str2float('nan')", string(cos(0.0/0.0))) + call assert_equal('0.0', string(tan(1.0/(1.0/0.0)))) + call assert_equal('-0.0', string(tan(-1.0/(1.0/0.0)))) + call assert_fails('call tan("")', 'E808:') +endfunc + +func Test_atan() + call assert_equal('0.0', string(atan(0.0))) + call assert_equal('0.463648', string(atan(0.5))) + call assert_equal('-0.785398', string(atan(-1.0))) + call assert_equal('1.570796', string(atan(1.0/0.0))) + call assert_equal('-1.570796', string(atan(-1.0/0.0))) + call assert_equal("str2float('nan')", string(atan(0.0/0.0))) + call assert_fails('call atan("")', 'E808:') +endfunc + +func Test_atan2() + call assert_equal('-2.356194', string(atan2(-1, -1))) + call assert_equal('2.356194', string(atan2(1, -1))) + call assert_equal('0.0', string(atan2(1.0, 1.0/0.0))) + call assert_equal('1.570796', string(atan2(1.0/0.0, 1.0))) + call assert_equal("str2float('nan')", string(atan2(0.0/0.0, 1.0))) + call assert_fails('call atan2("", -1)', 'E808:') + call assert_fails('call atan2(-1, "")', 'E808:') +endfunc + +func Test_tanh() + call assert_equal('0.0', string(tanh(0.0))) + call assert_equal('0.462117', string(tanh(0.5))) + call assert_equal('-0.761594', string(tanh(-1.0))) + call assert_equal('1.0', string(tanh(1.0/0.0))) + call assert_equal('-1.0', string(tanh(-1.0/0.0))) + call assert_equal("str2float('nan')", string(tanh(0.0/0.0))) + call assert_fails('call tanh("")', 'E808:') +endfunc + +func Test_fmod() + call assert_equal('0.13', string(fmod(12.33, 1.22))) + call assert_equal('-0.13', string(fmod(-12.33, 1.22))) + call assert_equal("str2float('nan')", string(fmod(1.0/0.0, 1.0))) + " On Windows we get "nan" instead of 1.0, accept both. + let res = string(fmod(1.0, 1.0/0.0)) + if res != "str2float('nan')" + call assert_equal('1.0', res) + endif + call assert_equal("str2float('nan')", string(fmod(1.0, 0.0))) + call assert_fails("call fmod('', 1.22)", 'E808:') + call assert_fails("call fmod(12.33, '')", 'E808:') +endfunc + +func Test_pow() + call assert_equal('1.0', string(pow(0.0, 0.0))) + call assert_equal('8.0', string(pow(2.0, 3.0))) + call assert_equal("str2float('nan')", string(pow(2.0, 0.0/0.0))) + call assert_equal("str2float('nan')", string(pow(0.0/0.0, 3.0))) + call assert_equal("str2float('nan')", string(pow(0.0/0.0, 3.0))) + call assert_equal("str2float('inf')", string(pow(2.0, 1.0/0.0))) + call assert_equal("str2float('inf')", string(pow(1.0/0.0, 3.0))) + call assert_fails("call pow('', 2.0)", 'E808:') + call assert_fails("call pow(2.0, '')", 'E808:') +endfunc + +func Test_str2float() + call assert_equal('1.0', string(str2float('1'))) + call assert_equal('1.0', string(str2float(' 1 '))) + call assert_equal('1.0', string(str2float(' 1.0 '))) + call assert_equal('1.23', string(str2float('1.23'))) + call assert_equal('1.23', string(str2float('1.23abc'))) + call assert_equal('1.0e40', string(str2float('1e40'))) + call assert_equal('-1.23', string(str2float('-1.23'))) + call assert_equal('1.23', string(str2float(' + 1.23 '))) + + call assert_equal('1.0', string(str2float('+1'))) + call assert_equal('1.0', string(str2float('+1'))) + call assert_equal('1.0', string(str2float(' +1 '))) + call assert_equal('1.0', string(str2float(' + 1 '))) + + call assert_equal('-1.0', string(str2float('-1'))) + call assert_equal('-1.0', string(str2float('-1'))) + call assert_equal('-1.0', string(str2float(' -1 '))) + call assert_equal('-1.0', string(str2float(' - 1 '))) + + call assert_equal('0.0', string(str2float('+0.0'))) + call assert_equal('-0.0', string(str2float('-0.0'))) + call assert_equal("str2float('inf')", string(str2float('1e1000'))) + call assert_equal("str2float('inf')", string(str2float('inf'))) + call assert_equal("-str2float('inf')", string(str2float('-inf'))) + call assert_equal("str2float('inf')", string(str2float('+inf'))) + call assert_equal("str2float('inf')", string(str2float('Inf'))) + call assert_equal("str2float('inf')", string(str2float(' +inf '))) + call assert_equal("str2float('nan')", string(str2float('nan'))) + call assert_equal("str2float('nan')", string(str2float('NaN'))) + call assert_equal("str2float('nan')", string(str2float(' nan '))) + + call assert_fails("call str2float(1.2)", 'E806:') + call assert_fails("call str2float([])", 'E730:') + call assert_fails("call str2float({})", 'E731:') + call assert_fails("call str2float(function('string'))", 'E729:') +endfunc + +func Test_float2nr() + call assert_equal(1, float2nr(1.234)) + call assert_equal(123, float2nr(1.234e2)) + call assert_equal(12, float2nr(123.4e-1)) + let max_number = 1/0 + let min_number = -max_number + call assert_equal(max_number/2+1, float2nr(pow(2, 62))) + call assert_equal(max_number, float2nr(pow(2, 63))) + call assert_equal(max_number, float2nr(pow(2, 64))) + call assert_equal(min_number/2-1, float2nr(-pow(2, 62))) + call assert_equal(min_number, float2nr(-pow(2, 63))) + call assert_equal(min_number, float2nr(-pow(2, 64))) +endfunc + +func Test_floor() + call assert_equal('2.0', string(floor(2.0))) + call assert_equal('2.0', string(floor(2.11))) + call assert_equal('2.0', string(floor(2.99))) + call assert_equal('-3.0', string(floor(-2.11))) + call assert_equal('-3.0', string(floor(-2.99))) + call assert_equal("str2float('nan')", string(floor(0.0/0.0))) + call assert_equal("str2float('inf')", string(floor(1.0/0.0))) + call assert_equal("-str2float('inf')", string(floor(-1.0/0.0))) + call assert_fails("call floor('')", 'E808:') +endfunc + +func Test_ceil() + call assert_equal('2.0', string(ceil(2.0))) + call assert_equal('3.0', string(ceil(2.11))) + call assert_equal('3.0', string(ceil(2.99))) + call assert_equal('-2.0', string(ceil(-2.11))) + call assert_equal('-2.0', string(ceil(-2.99))) + call assert_equal("str2float('nan')", string(ceil(0.0/0.0))) + call assert_equal("str2float('inf')", string(ceil(1.0/0.0))) + call assert_equal("-str2float('inf')", string(ceil(-1.0/0.0))) + call assert_fails("call ceil('')", 'E808:') +endfunc + +func Test_round() + call assert_equal('2.0', string(round(2.1))) + call assert_equal('3.0', string(round(2.5))) + call assert_equal('3.0', string(round(2.9))) + call assert_equal('-2.0', string(round(-2.1))) + call assert_equal('-3.0', string(round(-2.5))) + call assert_equal('-3.0', string(round(-2.9))) + call assert_equal("str2float('nan')", string(round(0.0/0.0))) + call assert_equal("str2float('inf')", string(round(1.0/0.0))) + call assert_equal("-str2float('inf')", string(round(-1.0/0.0))) + call assert_fails("call round('')", 'E808:') +endfunc + +func Test_trunc() + call assert_equal('2.0', string(trunc(2.1))) + call assert_equal('2.0', string(trunc(2.5))) + call assert_equal('2.0', string(trunc(2.9))) + call assert_equal('-2.0', string(trunc(-2.1))) + call assert_equal('-2.0', string(trunc(-2.5))) + call assert_equal('-2.0', string(trunc(-2.9))) + call assert_equal("str2float('nan')", string(trunc(0.0/0.0))) + call assert_equal("str2float('inf')", string(trunc(1.0/0.0))) + call assert_equal("-str2float('inf')", string(trunc(-1.0/0.0))) + call assert_fails("call trunc('')", 'E808:') +endfunc + +func Test_isnan() + throw 'skipped: Nvim does not support isnan()' + call assert_equal(0, isnan(1.0)) + call assert_equal(1, isnan(0.0/0.0)) + call assert_equal(0, isnan(1.0/0.0)) + call assert_equal(0, isnan('a')) + call assert_equal(0, isnan([])) + call assert_equal(0, isnan({})) +endfunc + +" This was converted from test65 +func Test_float_misc() + call assert_equal('123.456000', printf('%f', 123.456)) + call assert_equal('1.234560e+02', printf('%e', 123.456)) + call assert_equal('123.456', printf('%g', 123.456)) + " += + let v = 1.234 + let v += 6.543 + call assert_equal('7.777', printf('%g', v)) + let v = 1.234 + let v += 5 + call assert_equal('6.234', printf('%g', v)) + let v = 5 + let v += 3.333 + call assert_equal('8.333', string(v)) + " == + let v = 1.234 + call assert_true(v == 1.234) + call assert_false(v == 1.2341) + " add-subtract + call assert_equal('5.234', printf('%g', 4 + 1.234)) + call assert_equal('-6.766', printf('%g', 1.234 - 8)) + " mult-div + call assert_equal('4.936', printf('%g', 4 * 1.234)) + call assert_equal('0.003241', printf('%g', 4.0 / 1234)) + " dict + call assert_equal("{'x': 1.234, 'y': -2.0e20}", string({'x': 1.234, 'y': -2.0e20})) + " list + call assert_equal('[-123.4, 2.0e-20]', string([-123.4, 2.0e-20])) +endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_fnameescape.vim b/src/nvim/testdir/test_fnameescape.vim new file mode 100644 index 0000000000..cdff0dfbd9 --- /dev/null +++ b/src/nvim/testdir/test_fnameescape.vim @@ -0,0 +1,21 @@ + +" Test if fnameescape is correct for special chars like ! +function! Test_fnameescape() + let fname = 'Xspa ce' + let status = v:false + try + exe "w! " . fnameescape(fname) + let status = v:true + endtry + call assert_true(status, "Space") + call delete(fname) + + let fname = 'Xemark!' + let status = v:false + try + exe "w! " . fnameescape(fname) + let status = v:true + endtry + call assert_true(status, "ExclamationMark") + call delete(fname) +endfunction diff --git a/src/nvim/testdir/test_fold.vim b/src/nvim/testdir/test_fold.vim new file mode 100644 index 0000000000..46c54e8614 --- /dev/null +++ b/src/nvim/testdir/test_fold.vim @@ -0,0 +1,362 @@ +" Test for folding + +func! PrepIndent(arg) + return [a:arg] + repeat(["\t".a:arg], 5) +endfu + +func! Test_address_fold() + new + call setline(1, ['int FuncName() {/*{{{*/', 1, 2, 3, 4, 5, '}/*}}}*/', + \ 'after fold 1', 'after fold 2', 'after fold 3']) + setl fen fdm=marker + " The next ccommands should all copy the same part of the buffer, + " regardless of the adressing type, since the part to be copied + " is folded away + :1y + call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1)) + :.y + call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1)) + :.+y + call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1)) + :.,.y + call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1)) + :sil .1,.y + call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1)) + " use silent to make E493 go away + :sil .+,.y + call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1)) + :,y + call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1)) + :,+y + call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/','after fold 1'], getreg(0,1,1)) + " using .+3 as second address should copy the whole folded line + the next 3 + " lines + :.,+3y + call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/', + \ 'after fold 1', 'after fold 2', 'after fold 3'], getreg(0,1,1)) + :sil .,-2y + call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1)) + + " now test again with folding disabled + set nofoldenable + :1y + call assert_equal(['int FuncName() {/*{{{*/'], getreg(0,1,1)) + :.y + call assert_equal(['int FuncName() {/*{{{*/'], getreg(0,1,1)) + :.+y + call assert_equal(['1'], getreg(0,1,1)) + :.,.y + call assert_equal(['int FuncName() {/*{{{*/'], getreg(0,1,1)) + " use silent to make E493 go away + :sil .1,.y + call assert_equal(['int FuncName() {/*{{{*/', '1'], getreg(0,1,1)) + " use silent to make E493 go away + :sil .+,.y + call assert_equal(['int FuncName() {/*{{{*/', '1'], getreg(0,1,1)) + :,y + call assert_equal(['int FuncName() {/*{{{*/'], getreg(0,1,1)) + :,+y + call assert_equal(['int FuncName() {/*{{{*/', '1'], getreg(0,1,1)) + " using .+3 as second address should copy the whole folded line + the next 3 + " lines + :.,+3y + call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3'], getreg(0,1,1)) + :7 + :sil .,-2y + call assert_equal(['4', '5', '}/*}}}*/'], getreg(0,1,1)) + + quit! +endfunc + +func! Test_indent_fold() + new + call setline(1, ['', 'a', ' b', ' c']) + setl fen fdm=indent + 2 + norm! >> + let a=map(range(1,4), 'foldclosed(v:val)') + call assert_equal([-1,-1,-1,-1], a) +endfunc + +func! Test_indent_fold() + new + call setline(1, ['', 'a', ' b', ' c']) + setl fen fdm=indent + 2 + norm! >> + let a=map(range(1,4), 'foldclosed(v:val)') + call assert_equal([-1,-1,-1,-1], a) + bw! +endfunc + +func! Test_indent_fold2() + new + call setline(1, ['', '{{{', '}}}', '{{{', '}}}']) + setl fen fdm=marker + 2 + norm! >> + let a=map(range(1,5), 'foldclosed(v:val)') + call assert_equal([-1,-1,-1,4,4], a) + bw! +endfunc + +func Test_manual_fold_with_filter() + if !executable('cat') + return + endif + for type in ['manual', 'marker'] + exe 'set foldmethod=' . type + new + call setline(1, range(1, 20)) + 4,$fold + %foldopen + 10,$fold + %foldopen + " This filter command should not have an effect + 1,8! cat + call feedkeys('5ggzdzMGdd', 'xt') + call assert_equal(['1', '2', '3', '4', '5', '6', '7', '8', '9'], getline(1, '$')) + + bwipe! + set foldmethod& + endfor +endfunc + +func! Test_indent_fold_with_read() + new + set foldmethod=indent + call setline(1, repeat(["\<Tab>a"], 4)) + for n in range(1, 4) + call assert_equal(1, foldlevel(n)) + endfor + + call writefile(["a", "", "\<Tab>a"], 'Xfile') + foldopen + 2read Xfile + %foldclose + call assert_equal(1, foldlevel(1)) + call assert_equal(2, foldclosedend(1)) + call assert_equal(0, foldlevel(3)) + call assert_equal(0, foldlevel(4)) + call assert_equal(1, foldlevel(5)) + call assert_equal(7, foldclosedend(5)) + + bwipe! + set foldmethod& + call delete('Xfile') +endfunc + +func Test_combining_folds_indent() + new + let one = "\<Tab>a" + let zero = 'a' + call setline(1, [one, one, zero, zero, zero, one, one, one]) + set foldmethod=indent + 3,5d + %foldclose + call assert_equal(5, foldclosedend(1)) + + set foldmethod& + bwipe! +endfunc + +func Test_combining_folds_marker() + new + call setline(1, ['{{{', '}}}', '', '', '', '{{{', '', '}}}']) + set foldmethod=marker + 3,5d + %foldclose + call assert_equal(2, foldclosedend(1)) + + set foldmethod& + bwipe! +endfunc + +func Test_folds_marker_in_comment() + new + call setline(1, ['" foo', 'bar', 'baz']) + setl fen fdm=marker + setl com=sO:\"\ -,mO:\"\ \ ,eO:\"\",:\" cms=\"%s + norm! zf2j + setl nofen + :1y + call assert_equal(['" foo{{{'], getreg(0,1,1)) + :+2y + call assert_equal(['baz"}}}'], getreg(0,1,1)) + + set foldmethod& + bwipe! +endfunc + +func s:TestFoldExpr(lnum) + let thisline = getline(a:lnum) + if thisline == 'a' + return 1 + elseif thisline == 'b' + return 0 + elseif thisline == 'c' + return '<1' + elseif thisline == 'd' + return '>1' + endif + return 0 +endfunction + +func Test_update_folds_expr_read() + new + call setline(1, ['a', 'a', 'a', 'a', 'a', 'a']) + set foldmethod=expr + set foldexpr=s:TestFoldExpr(v:lnum) + 2 + foldopen + call writefile(['b', 'b', 'a', 'a', 'd', 'a', 'a', 'c'], 'Xfile') + read Xfile + %foldclose + call assert_equal(2, foldclosedend(1)) + call assert_equal(0, foldlevel(3)) + call assert_equal(0, foldlevel(4)) + call assert_equal(6, foldclosedend(5)) + call assert_equal(10, foldclosedend(7)) + call assert_equal(14, foldclosedend(11)) + + call delete('Xfile') + bwipe! + set foldmethod& foldexpr& +endfunc + +func! Test_move_folds_around_manual() + new + let input = PrepIndent("a") + PrepIndent("b") + PrepIndent("c") + call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c")) + let folds=[-1, 2, 2, 2, 2, 2, -1, 8, 8, 8, 8, 8, -1, 14, 14, 14, 14, 14] + " all folds closed + set foldenable foldlevel=0 fdm=indent + " needs a forced redraw + redraw! + set fdm=manual + call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)')) + call assert_equal(input, getline(1, '$')) + 7,12m0 + call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$')) + call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)')) + 10,12m0 + call assert_equal(PrepIndent("a")[1:] + PrepIndent("b") + ["a"] + PrepIndent("c"), getline(1, '$')) + call assert_equal([1, 1, 1, 1, 1, -1, 7, 7, 7, 7, 7, -1, -1, 14, 14, 14, 14, 14], map(range(1, line('$')), 'foldclosed(v:val)')) + " moving should not close the folds + %d + call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c")) + set fdm=indent + redraw! + set fdm=manual + call cursor(2, 1) + %foldopen + 7,12m0 + let folds=repeat([-1], 18) + call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$')) + call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)')) + norm! zM + " folds are not corrupted and all have been closed + call assert_equal([-1, 2, 2, 2, 2, 2, -1, 8, 8, 8, 8, 8, -1, 14, 14, 14, 14, 14], map(range(1, line('$')), 'foldclosed(v:val)')) + %d + call setline(1, ["a", "\tb", "\tc", "\td", "\te"]) + set fdm=indent + redraw! + set fdm=manual + %foldopen + 3m4 + %foldclose + call assert_equal(["a", "\tb", "\td", "\tc", "\te"], getline(1, '$')) + call assert_equal([-1, 5, 5, 5, 5], map(range(1, line('$')), 'foldclosedend(v:val)')) + %d + call setline(1, ["a", "\tb", "\tc", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"]) + set fdm=indent foldlevel=0 + set fdm=manual + %foldopen + 3m1 + %foldclose + call assert_equal(["a", "\tc", "\tb", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"], getline(1, '$')) + call assert_equal(0, foldlevel(2)) + call assert_equal(5, foldclosedend(3)) + call assert_equal([-1, -1, 3, 3, 3, -1, 7, 7, 7, 7], map(range(1, line('$')), 'foldclosed(v:val)')) + 2,6m$ + %foldclose + call assert_equal(5, foldclosedend(2)) + call assert_equal(0, foldlevel(6)) + call assert_equal(9, foldclosedend(7)) + call assert_equal([-1, 2, 2, 2, 2, -1, 7, 7, 7, -1], map(range(1, line('$')), 'foldclosed(v:val)')) + %d + " Ensure moving around the edges still works. + call setline(1, PrepIndent("a") + repeat(["a"], 3) + ["\ta"]) + set fdm=indent foldlevel=0 + set fdm=manual + %foldopen + 6m$ + " The first fold has been truncated to the 5'th line. + " Second fold has been moved up because the moved line is now below it. + call assert_equal([0, 1, 1, 1, 1, 0, 0, 0, 1, 0], map(range(1, line('$')), 'foldlevel(v:val)')) + bw! +endfunc + +func! Test_move_folds_around_indent() + new + let input = PrepIndent("a") + PrepIndent("b") + PrepIndent("c") + call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c")) + let folds=[-1, 2, 2, 2, 2, 2, -1, 8, 8, 8, 8, 8, -1, 14, 14, 14, 14, 14] + " all folds closed + set fdm=indent + call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)')) + call assert_equal(input, getline(1, '$')) + 7,12m0 + call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$')) + call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)')) + 10,12m0 + call assert_equal(PrepIndent("a")[1:] + PrepIndent("b") + ["a"] + PrepIndent("c"), getline(1, '$')) + call assert_equal([1, 1, 1, 1, 1, -1, 7, 7, 7, 7, 7, -1, -1, 14, 14, 14, 14, 14], map(range(1, line('$')), 'foldclosed(v:val)')) + " moving should not close the folds + %d + call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c")) + set fdm=indent + call cursor(2, 1) + %foldopen + 7,12m0 + let folds=repeat([-1], 18) + call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$')) + call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)')) + norm! zM + " folds are not corrupted and all have been closed + call assert_equal([-1, 2, 2, 2, 2, 2, -1, 8, 8, 8, 8, 8, -1, 14, 14, 14, 14, 14], map(range(1, line('$')), 'foldclosed(v:val)')) + %d + call setline(1, ["a", "\tb", "\tc", "\td", "\te"]) + set fdm=indent + %foldopen + 3m4 + %foldclose + call assert_equal(["a", "\tb", "\td", "\tc", "\te"], getline(1, '$')) + call assert_equal([-1, 5, 5, 5, 5], map(range(1, line('$')), 'foldclosedend(v:val)')) + %d + call setline(1, ["a", "\tb", "\tc", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"]) + set fdm=indent foldlevel=0 + %foldopen + 3m1 + %foldclose + call assert_equal(["a", "\tc", "\tb", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"], getline(1, '$')) + call assert_equal(1, foldlevel(2)) + call assert_equal(5, foldclosedend(3)) + call assert_equal([-1, 2, 2, 2, 2, -1, 7, 7, 7, 7], map(range(1, line('$')), 'foldclosed(v:val)')) + 2,6m$ + %foldclose + call assert_equal(9, foldclosedend(2)) + call assert_equal(1, foldlevel(6)) + call assert_equal(9, foldclosedend(7)) + call assert_equal([-1, 2, 2, 2, 2, 2, 2, 2, 2, -1], map(range(1, line('$')), 'foldclosed(v:val)')) + " Ensure moving around the edges still works. + %d + call setline(1, PrepIndent("a") + repeat(["a"], 3) + ["\ta"]) + set fdm=indent foldlevel=0 + %foldopen + 6m$ + " The first fold has been truncated to the 5'th line. + " Second fold has been moved up because the moved line is now below it. + call assert_equal([0, 1, 1, 1, 1, 0, 0, 0, 1, 1], map(range(1, line('$')), 'foldlevel(v:val)')) + bw! +endfunc diff --git a/src/nvim/testdir/test_functions.vim b/src/nvim/testdir/test_functions.vim new file mode 100644 index 0000000000..237a2dc820 --- /dev/null +++ b/src/nvim/testdir/test_functions.vim @@ -0,0 +1,194 @@ +" Tests for various functions. + +func Test_str2nr() + call assert_equal(0, str2nr('')) + call assert_equal(1, str2nr('1')) + call assert_equal(1, str2nr(' 1 ')) + + call assert_equal(1, str2nr('+1')) + call assert_equal(1, str2nr('+ 1')) + call assert_equal(1, str2nr(' + 1 ')) + + call assert_equal(-1, str2nr('-1')) + call assert_equal(-1, str2nr('- 1')) + call assert_equal(-1, str2nr(' - 1 ')) + + call assert_equal(123456789, str2nr('123456789')) + call assert_equal(-123456789, str2nr('-123456789')) +endfunc + +func Test_setbufvar_options() + " This tests that aucmd_prepbuf() and aucmd_restbuf() properly restore the + " window layout. + call assert_equal(1, winnr('$')) + split dummy_preview + resize 2 + set winfixheight winfixwidth + let prev_id = win_getid() + + wincmd j + let wh = winheight('.') + let dummy_buf = bufnr('dummy_buf1', v:true) + call setbufvar(dummy_buf, '&buftype', 'nofile') + execute 'belowright vertical split #' . dummy_buf + call assert_equal(wh, winheight('.')) + let dum1_id = win_getid() + + wincmd h + let wh = winheight('.') + let dummy_buf = bufnr('dummy_buf2', v:true) + call setbufvar(dummy_buf, '&buftype', 'nofile') + execute 'belowright vertical split #' . dummy_buf + call assert_equal(wh, winheight('.')) + + bwipe! + call win_gotoid(prev_id) + bwipe! + call win_gotoid(dum1_id) + bwipe! +endfunc + +func Test_tolower() + call assert_equal("", tolower("")) + + " Test with all printable ASCII characters. + call assert_equal(' !"#$%&''()*+,-./0123456789:;<=>?@abcdefghijklmnopqrstuvwxyz[\]^_`abcdefghijklmnopqrstuvwxyz{|}~', + \ tolower(' !"#$%&''()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~')) + + if !has('multi_byte') + return + endif + + " Test with a few uppercase diacritics. + call assert_equal("aร รกรขรฃรครฅฤฤฤ
วววกแบฃ", tolower("Aรรรรรร
ฤฤฤววว แบข")) + call assert_equal("bแธแธ", tolower("Bแธแธ")) + call assert_equal("cรงฤฤฤฤ", tolower("Cรฤฤฤฤ")) + call assert_equal("dฤฤแธแธแธ", tolower("Dฤฤแธแธแธ")) + call assert_equal("eรจรฉรชรซฤฤฤฤฤแบปแบฝ", tolower("Eรรรรฤฤฤฤฤแบบแบผ")) + call assert_equal("fแธ ", tolower("Fแธ ")) + call assert_equal("gฤฤฤกฤฃวฅวงวตแธก", tolower("Gฤฤฤ ฤขวควฆวดแธ ")) + call assert_equal("hฤฅฤงแธฃแธงแธฉ", tolower("Hฤคฤฆแธขแธฆแธจ")) + call assert_equal("iรฌรญรฎรฏฤฉฤซฤญฤฏiวแป", tolower("Iรรรรฤจฤชฤฌฤฎฤฐวแป")) + call assert_equal("jฤต", tolower("Jฤด")) + call assert_equal("kฤทวฉแธฑแธต", tolower("Kฤถวจแธฐแธด")) + call assert_equal("lฤบฤผฤพลลแธป", tolower("Lฤนฤปฤฝฤฟลแธบ")) + call assert_equal("mแธฟแน", tolower("Mแธพแน")) + call assert_equal("nรฑลลลแน
แน", tolower("Nรลล
ลแนแน")) + call assert_equal("oรฒรณรดรตรถรธลลลฦกววซวญแป", tolower("Oรรรรรรลลลฦ ววชวฌแป")) + call assert_equal("pแนแน", tolower("Pแนแน")) + call assert_equal("q", tolower("Q")) + call assert_equal("rลลลแนแน", tolower("Rลลลแนแน")) + call assert_equal("sลลลลกแนก", tolower("Sลลลล แน ")) + call assert_equal("tลฃลฅลงแนซแนฏ", tolower("Tลขลคลฆแนชแนฎ")) + call assert_equal("uรนรบรปรผลฉลซลญลฏลฑลณฦฐวแปง", tolower("Uรรรรลจลชลฌลฎลฐลฒฦฏวแปฆ")) + call assert_equal("vแนฝ", tolower("Vแนผ")) + call assert_equal("wลตแบแบแบ
แบ", tolower("Wลดแบแบแบแบ")) + call assert_equal("xแบแบ", tolower("Xแบแบ")) + call assert_equal("yรฝลทรฟแบแปณแปทแปน", tolower("Yรลถลธแบแปฒแปถแปธ")) + call assert_equal("zลบลผลพฦถแบแบ", tolower("Zลนลปลฝฦตแบแบ")) + + " Test with a few lowercase diacritics, which should remain unchanged. + call assert_equal("aร รกรขรฃรครฅฤฤฤ
วววกแบฃ", tolower("aร รกรขรฃรครฅฤฤฤ
วววกแบฃ")) + call assert_equal("bแธแธ", tolower("bแธแธ")) + call assert_equal("cรงฤฤฤฤ", tolower("cรงฤฤฤฤ")) + call assert_equal("dฤฤแธแธแธ", tolower("dฤฤแธแธแธ")) + call assert_equal("eรจรฉรชรซฤฤฤฤฤแบปแบฝ", tolower("eรจรฉรชรซฤฤฤฤฤแบปแบฝ")) + call assert_equal("fแธ", tolower("fแธ")) + call assert_equal("gฤฤฤกฤฃวฅวงวตแธก", tolower("gฤฤฤกฤฃวฅวงวตแธก")) + call assert_equal("hฤฅฤงแธฃแธงแธฉแบ", tolower("hฤฅฤงแธฃแธงแธฉแบ")) + call assert_equal("iรฌรญรฎรฏฤฉฤซฤญฤฏวแป", tolower("iรฌรญรฎรฏฤฉฤซฤญฤฏวแป")) + call assert_equal("jฤตวฐ", tolower("jฤตวฐ")) + call assert_equal("kฤทวฉแธฑแธต", tolower("kฤทวฉแธฑแธต")) + call assert_equal("lฤบฤผฤพลลแธป", tolower("lฤบฤผฤพลลแธป")) + call assert_equal("mแธฟแน ", tolower("mแธฟแน ")) + call assert_equal("nรฑลลลลแน
แน", tolower("nรฑลลลลแน
แน")) + call assert_equal("oรฒรณรดรตรถรธลลลฦกววซวญแป", tolower("oรฒรณรดรตรถรธลลลฦกววซวญแป")) + call assert_equal("pแนแน", tolower("pแนแน")) + call assert_equal("q", tolower("q")) + call assert_equal("rลลลแนแน", tolower("rลลลแนแน")) + call assert_equal("sลลลลกแนก", tolower("sลลลลกแนก")) + call assert_equal("tลฃลฅลงแนซแนฏแบ", tolower("tลฃลฅลงแนซแนฏแบ")) + call assert_equal("uรนรบรปรผลฉลซลญลฏลฑลณฦฐวแปง", tolower("uรนรบรปรผลฉลซลญลฏลฑลณฦฐวแปง")) + call assert_equal("vแนฝ", tolower("vแนฝ")) + call assert_equal("wลตแบแบแบ
แบแบ", tolower("wลตแบแบแบ
แบแบ")) + call assert_equal("แบแบ", tolower("แบแบ")) + call assert_equal("yรฝรฟลทแบแบแปณแปทแปน", tolower("yรฝรฟลทแบแบแปณแปทแปน")) + call assert_equal("zลบลผลพฦถแบแบ", tolower("zลบลผลพฦถแบแบ")) + + " According to https://twitter.com/jifa/status/625776454479970304 + " ศบ (U+023A) and ศพ (U+023E) are the *only* code points to increase + " in length (2 to 3 bytes) when lowercased. So let's test them. + call assert_equal("โฑฅ โฑฆ", tolower("ศบ ศพ")) +endfunc + +func Test_toupper() + call assert_equal("", toupper("")) + + " Test with all printable ASCII characters. + call assert_equal(' !"#$%&''()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~', + \ toupper(' !"#$%&''()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~')) + + if !has('multi_byte') + return + endif + + " Test with a few lowercase diacritics. + call assert_equal("Aรรรรรร
ฤฤฤววว แบข", toupper("aร รกรขรฃรครฅฤฤฤ
วววกแบฃ")) + call assert_equal("Bแธแธ", toupper("bแธแธ")) + call assert_equal("Cรฤฤฤฤ", toupper("cรงฤฤฤฤ")) + call assert_equal("Dฤฤแธแธแธ", toupper("dฤฤแธแธแธ")) + call assert_equal("Eรรรรฤฤฤฤฤแบบแบผ", toupper("eรจรฉรชรซฤฤฤฤฤแบปแบฝ")) + call assert_equal("Fแธ", toupper("fแธ")) + call assert_equal("Gฤฤฤ ฤขวควฆวดแธ ", toupper("gฤฤฤกฤฃวฅวงวตแธก")) + call assert_equal("Hฤคฤฆแธขแธฆแธจแบ", toupper("hฤฅฤงแธฃแธงแธฉแบ")) + call assert_equal("Iรรรรฤจฤชฤฌฤฎวแป", toupper("iรฌรญรฎรฏฤฉฤซฤญฤฏวแป")) + call assert_equal("Jฤดวฐ", toupper("jฤตวฐ")) + call assert_equal("Kฤถวจแธฐแธด", toupper("kฤทวฉแธฑแธต")) + call assert_equal("Lฤนฤปฤฝฤฟลแธบ", toupper("lฤบฤผฤพลลแธป")) + call assert_equal("Mแธพแน ", toupper("mแธฟแน ")) + call assert_equal("Nรลล
ลลแนแน", toupper("nรฑลลลลแน
แน")) + call assert_equal("Oรรรรรรลลลฦ ววชวฌแป", toupper("oรฒรณรดรตรถรธลลลฦกววซวญแป")) + call assert_equal("Pแนแน", toupper("pแนแน")) + call assert_equal("Q", toupper("q")) + call assert_equal("Rลลลแนแน", toupper("rลลลแนแน")) + call assert_equal("Sลลลล แน ", toupper("sลลลลกแนก")) + call assert_equal("Tลขลคลฆแนชแนฎแบ", toupper("tลฃลฅลงแนซแนฏแบ")) + call assert_equal("Uรรรรลจลชลฌลฎลฐลฒฦฏวแปฆ", toupper("uรนรบรปรผลฉลซลญลฏลฑลณฦฐวแปง")) + call assert_equal("Vแนผ", toupper("vแนฝ")) + call assert_equal("Wลดแบแบแบแบแบ", toupper("wลตแบแบแบ
แบแบ")) + call assert_equal("แบแบ", toupper("แบแบ")) + call assert_equal("Yรลธลถแบแบแปฒแปถแปธ", toupper("yรฝรฟลทแบแบแปณแปทแปน")) + call assert_equal("Zลนลปลฝฦตแบแบ", toupper("zลบลผลพฦถแบแบ")) + + " Test that uppercase diacritics, which should remain unchanged. + call assert_equal("Aรรรรรร
ฤฤฤววว แบข", toupper("Aรรรรรร
ฤฤฤววว แบข")) + call assert_equal("Bแธแธ", toupper("Bแธแธ")) + call assert_equal("Cรฤฤฤฤ", toupper("Cรฤฤฤฤ")) + call assert_equal("Dฤฤแธแธแธ", toupper("Dฤฤแธแธแธ")) + call assert_equal("Eรรรรฤฤฤฤฤแบบแบผ", toupper("Eรรรรฤฤฤฤฤแบบแบผ")) + call assert_equal("Fแธ ", toupper("Fแธ ")) + call assert_equal("Gฤฤฤ ฤขวควฆวดแธ ", toupper("Gฤฤฤ ฤขวควฆวดแธ ")) + call assert_equal("Hฤคฤฆแธขแธฆแธจ", toupper("Hฤคฤฆแธขแธฆแธจ")) + call assert_equal("Iรรรรฤจฤชฤฌฤฎฤฐวแป", toupper("Iรรรรฤจฤชฤฌฤฎฤฐวแป")) + call assert_equal("Jฤด", toupper("Jฤด")) + call assert_equal("Kฤถวจแธฐแธด", toupper("Kฤถวจแธฐแธด")) + call assert_equal("Lฤนฤปฤฝฤฟลแธบ", toupper("Lฤนฤปฤฝฤฟลแธบ")) + call assert_equal("Mแธพแน", toupper("Mแธพแน")) + call assert_equal("Nรลล
ลแนแน", toupper("Nรลล
ลแนแน")) + call assert_equal("Oรรรรรรลลลฦ ววชวฌแป", toupper("Oรรรรรรลลลฦ ววชวฌแป")) + call assert_equal("Pแนแน", toupper("Pแนแน")) + call assert_equal("Q", toupper("Q")) + call assert_equal("Rลลลแนแน", toupper("Rลลลแนแน")) + call assert_equal("Sลลลล แน ", toupper("Sลลลล แน ")) + call assert_equal("Tลขลคลฆแนชแนฎ", toupper("Tลขลคลฆแนชแนฎ")) + call assert_equal("Uรรรรลจลชลฌลฎลฐลฒฦฏวแปฆ", toupper("Uรรรรลจลชลฌลฎลฐลฒฦฏวแปฆ")) + call assert_equal("Vแนผ", toupper("Vแนผ")) + call assert_equal("Wลดแบแบแบแบ", toupper("Wลดแบแบแบแบ")) + call assert_equal("Xแบแบ", toupper("Xแบแบ")) + call assert_equal("Yรลถลธแบแปฒแปถแปธ", toupper("Yรลถลธแบแปฒแปถแปธ")) + call assert_equal("Zลนลปลฝฦตแบแบ", toupper("Zลนลปลฝฦตแบแบ")) + + call assert_equal("โฑฅ โฑฆ", tolower("ศบ ศพ")) +endfunc + + diff --git a/src/nvim/testdir/test_gf.vim b/src/nvim/testdir/test_gf.vim new file mode 100644 index 0000000000..c4aa6f9218 --- /dev/null +++ b/src/nvim/testdir/test_gf.vim @@ -0,0 +1,33 @@ + +" This is a test if a URL is recognized by "gf", with the cursor before and +" after the "://". Also test ":\\". +function! Test_gf_url() + enew! + call append(0, [ + \ "first test for URL://machine.name/tmp/vimtest2a and other text", + \ "second test for URL://machine.name/tmp/vimtest2b. And other text", + \ "third test for URL:\\\\machine.name\\vimtest2c and other text", + \ "fourth test for URL:\\\\machine.name\\tmp\\vimtest2d, and other text" + \ ]) + call cursor(1,1) + call search("^first") + call search("tmp") + call assert_equal("URL://machine.name/tmp/vimtest2a", expand("<cfile>")) + call search("^second") + call search("URL") + call assert_equal("URL://machine.name/tmp/vimtest2b", expand("<cfile>")) + if has("ebcdic") + set isf=@,240-249,/,.,-,_,+,,,$,:,~,\ + else + set isf=@,48-57,/,.,-,_,+,,,$,:,~,\ + endif + call search("^third") + call search("name") + call assert_equal("URL:\\\\machine.name\\vimtest2c", expand("<cfile>")) + call search("^fourth") + call search("URL") + call assert_equal("URL:\\\\machine.name\\tmp\\vimtest2d", expand("<cfile>")) + + set isf&vim + enew! +endfunction diff --git a/src/nvim/testdir/test_glob2regpat.vim b/src/nvim/testdir/test_glob2regpat.vim new file mode 100644 index 0000000000..fdf17946b6 --- /dev/null +++ b/src/nvim/testdir/test_glob2regpat.vim @@ -0,0 +1,30 @@ +" Test glob2regpat() + +func Test_invalid() + call assert_fails('call glob2regpat(1.33)', 'E806:') + call assert_fails('call glob2regpat("}")', 'E219:') + call assert_fails('call glob2regpat("{")', 'E220:') +endfunc + +func Test_valid() + call assert_equal('^foo\.', glob2regpat('foo.*')) + call assert_equal('^foo.$', glob2regpat('foo?')) + call assert_equal('\.vim$', glob2regpat('*.vim')) + call assert_equal('^[abc]$', glob2regpat('[abc]')) + call assert_equal('^foo bar$', glob2regpat('foo\ bar')) + call assert_equal('^foo,bar$', glob2regpat('foo,bar')) + call assert_equal('^\(foo\|bar\)$', glob2regpat('{foo,bar}')) + call assert_equal('.*', glob2regpat('**')) + + if exists('+shellslash') + call assert_equal('^foo[\/].$', glob2regpat('foo\?')) + call assert_equal('^\(foo[\/]\|bar\|foobar\)$', glob2regpat('{foo\,bar,foobar}')) + call assert_equal('^[\/]\(foo\|bar[\/]\)$', glob2regpat('\{foo,bar\}')) + call assert_equal('^[\/][\/]\(foo\|bar[\/][\/]\)$', glob2regpat('\\{foo,bar\\}')) + else + call assert_equal('^foo?$', glob2regpat('foo\?')) + call assert_equal('^\(foo,bar\|foobar\)$', glob2regpat('{foo\,bar,foobar}')) + call assert_equal('^{foo,bar}$', glob2regpat('\{foo,bar\}')) + call assert_equal('^\\\(foo\|bar\\\)$', glob2regpat('\\{foo,bar\\}')) + endif +endfunc diff --git a/src/nvim/testdir/test_gn.vim b/src/nvim/testdir/test_gn.vim index 3eca99bd99..7a5cdabaa3 100644 --- a/src/nvim/testdir/test_gn.vim +++ b/src/nvim/testdir/test_gn.vim @@ -90,4 +90,4 @@ func Test_gn_command() sil! %d _ endfu -" vim: tabstop=2 shiftwidth=0 expandtab +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_goto.vim b/src/nvim/testdir/test_goto.vim index 2afd96b296..2573401707 100644 --- a/src/nvim/testdir/test_goto.vim +++ b/src/nvim/testdir/test_goto.vim @@ -1,20 +1,290 @@ " Test commands that jump somewhere. -func Test_geeDEE() +" Create a new buffer using "lines" and place the cursor on the word after the +" first occurrence of return and invoke "cmd". The cursor should now be +" positioned at the given line and col. +func XTest_goto_decl(cmd, lines, line, col) new - call setline(1, ["Filename x;", "", "int Filename", "int func() {", "Filename y;"]) - /y;/ - normal gD - call assert_equal(1, line('.')) + call setline(1, a:lines) + /return/ + normal! W + execute 'norm! ' . a:cmd + call assert_equal(a:line, line('.')) + call assert_equal(a:col, col('.')) quit! endfunc -func Test_gee_dee() +func Test_gD() + let lines = [ + \ 'int x;', + \ '', + \ 'int func(void)', + \ '{', + \ ' return x;', + \ '}', + \ ] + call XTest_goto_decl('gD', lines, 1, 5) +endfunc + +func Test_gD_too() + let lines = [ + \ 'Filename x;', + \ '', + \ 'int Filename', + \ 'int func() {', + \ ' Filename x;', + \ ' return x;', + \ ] + call XTest_goto_decl('gD', lines, 1, 10) +endfunc + +func Test_gD_comment() + let lines = [ + \ '/* int x; */', + \ 'int x;', + \ '', + \ 'int func(void)', + \ '{', + \ ' return x;', + \ '}', + \ ] + call XTest_goto_decl('gD', lines, 2, 5) +endfunc + +func Test_gD_inline_comment() + let lines = [ + \ 'int y /* , x */;', + \ 'int x;', + \ '', + \ 'int func(void)', + \ '{', + \ ' return x;', + \ '}', + \ ] + call XTest_goto_decl('gD', lines, 2, 5) +endfunc + +func Test_gD_string() + let lines = [ + \ 'char *s[] = "x";', + \ 'int x = 1;', + \ '', + \ 'int func(void)', + \ '{', + \ ' return x;', + \ '}', + \ ] + call XTest_goto_decl('gD', lines, 2, 5) +endfunc + +func Test_gD_string_same_line() + let lines = [ + \ 'char *s[] = "x", int x = 1;', + \ '', + \ 'int func(void)', + \ '{', + \ ' return x;', + \ '}', + \ ] + call XTest_goto_decl('gD', lines, 1, 22) +endfunc + +func Test_gD_char() + let lines = [ + \ "char c = 'x';", + \ 'int x = 1;', + \ '', + \ 'int func(void)', + \ '{', + \ ' return x;', + \ '}', + \ ] + call XTest_goto_decl('gD', lines, 2, 5) +endfunc + +func Test_gd() + let lines = [ + \ 'int x;', + \ '', + \ 'int func(int x)', + \ '{', + \ ' return x;', + \ '}', + \ ] + call XTest_goto_decl('gd', lines, 3, 14) +endfunc + +func Test_gd_not_local() + let lines = [ + \ 'int func1(void)', + \ '{', + \ ' return x;', + \ '}', + \ '', + \ 'int func2(int x)', + \ '{', + \ ' return x;', + \ '}', + \ ] + call XTest_goto_decl('gd', lines, 3, 10) +endfunc + +func Test_gd_kr_style() + let lines = [ + \ 'int func(x)', + \ ' int x;', + \ '{', + \ ' return x;', + \ '}', + \ ] + call XTest_goto_decl('gd', lines, 2, 7) +endfunc + +func Test_gd_missing_braces() + let lines = [ + \ 'def func1(a)', + \ ' a + 1', + \ 'end', + \ '', + \ 'a = 1', + \ '', + \ 'def func2()', + \ ' return a', + \ 'end', + \ ] + call XTest_goto_decl('gd', lines, 1, 11) +endfunc + +func Test_gd_comment() + let lines = [ + \ 'int func(void)', + \ '{', + \ ' /* int x; */', + \ ' int x;', + \ ' return x;', + \ '}', + \] + call XTest_goto_decl('gd', lines, 4, 7) +endfunc + +func Test_gd_comment_in_string() + let lines = [ + \ 'int func(void)', + \ '{', + \ ' char *s ="//"; int x;', + \ ' int x;', + \ ' return x;', + \ '}', + \] + call XTest_goto_decl('gd', lines, 3, 22) +endfunc + +func Test_gd_string_in_comment() + set comments= + let lines = [ + \ 'int func(void)', + \ '{', + \ ' /* " */ int x;', + \ ' int x;', + \ ' return x;', + \ '}', + \] + call XTest_goto_decl('gd', lines, 3, 15) + set comments& +endfunc + +func Test_gd_inline_comment() + let lines = [ + \ 'int func(/* x is an int */ int x)', + \ '{', + \ ' return x;', + \ '}', + \ ] + call XTest_goto_decl('gd', lines, 1, 32) +endfunc + +func Test_gd_inline_comment_only() + let lines = [ + \ 'int func(void) /* one lonely x */', + \ '{', + \ ' return x;', + \ '}', + \ ] + call XTest_goto_decl('gd', lines, 3, 10) +endfunc + +func Test_gd_inline_comment_body() + let lines = [ + \ 'int func(void)', + \ '{', + \ ' int y /* , x */;', + \ '', + \ ' for (/* int x = 0 */; y < 2; y++);', + \ '', + \ ' int x = 0;', + \ '', + \ ' return x;', + \ '}', + \ ] + call XTest_goto_decl('gd', lines, 7, 7) +endfunc + +func Test_gd_trailing_multiline_comment() + let lines = [ + \ 'int func(int x) /* x is an int */', + \ '{', + \ ' return x;', + \ '}', + \ ] + call XTest_goto_decl('gd', lines, 1, 14) +endfunc + +func Test_gd_trailing_comment() + let lines = [ + \ 'int func(int x) // x is an int', + \ '{', + \ ' return x;', + \ '}', + \ ] + call XTest_goto_decl('gd', lines, 1, 14) +endfunc + +func Test_gd_string() + let lines = [ + \ 'int func(void)', + \ '{', + \ ' char *s = "x";', + \ ' int x = 1;', + \ '', + \ ' return x;', + \ '}', + \ ] + call XTest_goto_decl('gd', lines, 4, 7) +endfunc + +func Test_gd_string_only() + let lines = [ + \ 'int func(void)', + \ '{', + \ ' char *s = "x";', + \ '', + \ ' return x;', + \ '}', + \ ] + call XTest_goto_decl('gd', lines, 5, 10) +endfunc + +" Check that setting 'cursorline' does not change curswant +func Test_cursorline_keep_col() new - call setline(1, ["int x;", "", "int func(int x)", "{", " return x;", "}"]) - /return/ - normal $hgd - call assert_equal(3, line('.')) - call assert_equal(14, col('.')) - quit! + call setline(1, ['long long long line', 'short line']) + normal ggfi + let pos = getcurpos() + normal j + set cursorline + normal k + call assert_equal(pos, getcurpos()) + bwipe! + set nocursorline endfunc + diff --git a/src/nvim/testdir/test_help.vim b/src/nvim/testdir/test_help.vim new file mode 100644 index 0000000000..26edc16107 --- /dev/null +++ b/src/nvim/testdir/test_help.vim @@ -0,0 +1,16 @@ + +" Tests for :help + +func Test_help_restore_snapshot() + help + set buftype= + help + edit x + help + helpclose +endfunc + +func Test_help_errors() + call assert_fails('help doesnotexist', 'E149:') + call assert_fails('help!', 'E478:') +endfunc diff --git a/src/nvim/testdir/test_help_tagjump.vim b/src/nvim/testdir/test_help_tagjump.vim index cc1c81c7f6..1ca0f722cf 100644 --- a/src/nvim/testdir/test_help_tagjump.vim +++ b/src/nvim/testdir/test_help_tagjump.vim @@ -162,4 +162,36 @@ func Test_help_complete() endtry endfunc -" vim: et sw=2: +func Test_help_respect_current_file_lang() + try + let list = [] + call s:doc_config_setup() + + if has('multi_lang') + function s:check_help_file_ext(help_keyword, ext) + exec 'help ' . a:help_keyword + call assert_equal(a:ext, expand('%:e')) + call feedkeys("\<C-]>", 'tx') + call assert_equal(a:ext, expand('%:e')) + pop + helpclose + endfunc + + set rtp+=Xdir1/doc-ab + set rtp+=Xdir1/doc-ja + + set helplang=ab + call s:check_help_file_ext('test-char', 'abx') + call s:check_help_file_ext('test-char@ja', 'jax') + set helplang=ab,ja + call s:check_help_file_ext('test-char@ja', 'jax') + call s:check_help_file_ext('test-char@en', 'txt') + endif + catch + call assert_exception('X') + finally + call s:doc_config_teardown() + endtry +endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_hide.vim b/src/nvim/testdir/test_hide.vim new file mode 100644 index 0000000000..128b8ff945 --- /dev/null +++ b/src/nvim/testdir/test_hide.vim @@ -0,0 +1,97 @@ +" Tests for :hide command/modifier and 'hidden' option + +function SetUp() + let s:save_hidden = &hidden + let s:save_bufhidden = &bufhidden + let s:save_autowrite = &autowrite + set nohidden + set bufhidden= + set noautowrite +endfunc + +function TearDown() + let &hidden = s:save_hidden + let &bufhidden = s:save_bufhidden + let &autowrite = s:save_autowrite +endfunc + +function Test_hide() + let orig_bname = bufname('') + let orig_winnr = winnr('$') + + new Xf1 + set modified + call assert_fails('edit Xf2') + bwipeout! Xf1 + + new Xf1 + set modified + edit! Xf2 + call assert_equal(['Xf2', 2], [bufname(''), winnr('$')]) + call assert_equal([1, 0], [buflisted('Xf1'), bufloaded('Xf1')]) + bwipeout! Xf1 + bwipeout! Xf2 + + new Xf1 + set modified + " :hide as a command + hide + call assert_equal([orig_bname, orig_winnr], [bufname(''), winnr('$')]) + call assert_equal([1, 1], [buflisted('Xf1'), bufloaded('Xf1')]) + bwipeout! Xf1 + + new Xf1 + set modified + " :hide as a command with trailing comment + hide " comment + call assert_equal([orig_bname, orig_winnr], [bufname(''), winnr('$')]) + call assert_equal([1, 1], [buflisted('Xf1'), bufloaded('Xf1')]) + bwipeout! Xf1 + + new Xf1 + set modified + " :hide as a command with bar + hide | new Xf2 " comment + call assert_equal(['Xf2', 2], [bufname(''), winnr('$')]) + call assert_equal([1, 1], [buflisted('Xf1'), bufloaded('Xf1')]) + bwipeout! Xf1 + bwipeout! Xf2 + + new Xf1 + set modified + " :hide as a modifier with trailing comment + hide edit Xf2 " comment + call assert_equal(['Xf2', 2], [bufname(''), winnr('$')]) + call assert_equal([1, 1], [buflisted('Xf1'), bufloaded('Xf1')]) + bwipeout! Xf1 + bwipeout! Xf2 + + new Xf1 + set modified + " To check that the bar is not recognized to separate commands + hide echo "one|two" + call assert_equal(['Xf1', 2], [bufname(''), winnr('$')]) + call assert_equal([1, 1], [buflisted('Xf1'), bufloaded('Xf1')]) + bwipeout! Xf1 + + " set hidden + new Xf1 + set hidden + set modified + edit Xf2 " comment + call assert_equal(['Xf2', 2], [bufname(''), winnr('$')]) + call assert_equal([1, 1], [buflisted('Xf1'), bufloaded('Xf1')]) + bwipeout! Xf1 + bwipeout! Xf2 + + " set hidden bufhidden=wipe + new Xf1 + set bufhidden=wipe + set modified + hide edit! Xf2 " comment + call assert_equal(['Xf2', 2], [bufname(''), winnr('$')]) + call assert_equal([0, 0], [buflisted('Xf1'), bufloaded('Xf1')]) + bwipeout! Xf2 +endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_history.vim b/src/nvim/testdir/test_history.vim index ee6acfffc3..ca31e3f06c 100644 --- a/src/nvim/testdir/test_history.vim +++ b/src/nvim/testdir/test_history.vim @@ -31,6 +31,30 @@ function History_Tests(hist) call assert_equal('ls', histget(a:hist, -1)) call assert_equal(4, histnr(a:hist)) + let a=execute('history ' . a:hist) + call assert_match("^\n # \\S* history\n 3 buffers\n> 4 ls$", a) + let a=execute('history all') + call assert_match("^\n # .* history\n 3 buffers\n> 4 ls", a) + + if len(a:hist) > 0 + let a=execute('history ' . a:hist . ' 2') + call assert_match("^\n # \\S* history$", a) + let a=execute('history ' . a:hist . ' 3') + call assert_match("^\n # \\S* history\n 3 buffers$", a) + let a=execute('history ' . a:hist . ' 4') + call assert_match("^\n # \\S* history\n> 4 ls$", a) + let a=execute('history ' . a:hist . ' 3,4') + call assert_match("^\n # \\S* history\n 3 buffers\n> 4 ls$", a) + let a=execute('history ' . a:hist . ' -1') + call assert_match("^\n # \\S* history\n> 4 ls$", a) + let a=execute('history ' . a:hist . ' -2') + call assert_match("^\n # \\S* history\n 3 buffers$", a) + let a=execute('history ' . a:hist . ' -2,') + call assert_match("^\n # \\S* history\n 3 buffers\n> 4 ls$", a) + let a=execute('history ' . a:hist . ' -3') + call assert_match("^\n # \\S* history$", a) + endif + " Test for removing entries matching a pattern for i in range(1, 3) call histadd(a:hist, 'text_' . i) @@ -63,3 +87,20 @@ function Test_History() call assert_equal(-1, histnr('abc')) call assert_fails('call histnr([])', 'E730:') endfunction + +function Test_Search_history_window() + new + call setline(1, ['a', 'b', 'a', 'b']) + 1 + call feedkeys("/a\<CR>", 'xt') + call assert_equal('a', getline('.')) + 1 + call feedkeys("/b\<CR>", 'xt') + call assert_equal('b', getline('.')) + 1 + " select the previous /a command + call feedkeys("q/kk\<CR>", 'x!') + call assert_equal('a', getline('.')) + call assert_equal('a', @/) + bwipe! +endfunc diff --git a/src/nvim/testdir/test_hlsearch.vim b/src/nvim/testdir/test_hlsearch.vim new file mode 100644 index 0000000000..066fdd0250 --- /dev/null +++ b/src/nvim/testdir/test_hlsearch.vim @@ -0,0 +1,34 @@ +" Test for v:hlsearch + +function! Test_hlsearch() + new + call setline(1, repeat(['aaa'], 10)) + set hlsearch nolazyredraw + let r=[] + " redraw is needed to make hlsearch highlight the matches + exe "normal! /aaa\<CR>" | redraw + let r1 = screenattr(1, 1) + nohlsearch | redraw + call assert_notequal(r1, screenattr(1,1)) + let v:hlsearch=1 | redraw + call assert_equal(r1, screenattr(1,1)) + let v:hlsearch=0 | redraw + call assert_notequal(r1, screenattr(1,1)) + set hlsearch | redraw + call assert_equal(r1, screenattr(1,1)) + let v:hlsearch=0 | redraw + call assert_notequal(r1, screenattr(1,1)) + exe "normal! n" | redraw + call assert_equal(r1, screenattr(1,1)) + let v:hlsearch=0 | redraw + call assert_notequal(r1, screenattr(1,1)) + exe "normal! /\<CR>" | redraw + call assert_equal(r1, screenattr(1,1)) + set nohls + exe "normal! /\<CR>" | redraw + call assert_notequal(r1, screenattr(1,1)) + call assert_fails('let v:hlsearch=[]', 'E745') + call garbagecollect(1) + call getchar(1) + enew! +endfunction diff --git a/src/nvim/testdir/test_increment.vim b/src/nvim/testdir/test_increment.vim new file mode 100644 index 0000000000..8bfd95d810 --- /dev/null +++ b/src/nvim/testdir/test_increment.vim @@ -0,0 +1,760 @@ +" Tests for using Ctrl-A/Ctrl-X on visual selections + +func SetUp() + new dummy + set nrformats&vim +endfunc + +func TearDown() + bwipe! +endfunc + +" 1) Ctrl-A on visually selected number +" Text: +" foobar-10 +" Expected: +" 1) Ctrl-A on start of line: +" foobar-9 +" 2) Ctrl-A on visually selected "-10": +" foobar-9 +" 3) Ctrl-A on visually selected "10": +" foobar-11 +" 4) Ctrl-X on visually selected "-10" +" foobar-11 +" 5) Ctrl-X on visually selected "10" +" foobar-9 +func Test_visual_increment_01() + call setline(1, repeat(["foobaar-10"], 5)) + + call cursor(1, 1) + exec "norm! \<C-A>" + call assert_equal("foobaar-9", getline('.')) + call assert_equal([0, 1, 9, 0], getpos('.')) + + call cursor(2, 1) + exec "norm! f-v$\<C-A>" + call assert_equal("foobaar-9", getline('.')) + call assert_equal([0, 2, 8, 0], getpos('.')) + + call cursor(3, 1) + exec "norm! f1v$\<C-A>" + call assert_equal("foobaar-11", getline('.')) + call assert_equal([0, 3, 9, 0], getpos('.')) + + call cursor(4, 1) + exec "norm! f-v$\<C-X>" + call assert_equal("foobaar-11", getline('.')) + call assert_equal([0, 4, 8, 0], getpos('.')) + + call cursor(5, 1) + exec "norm! f1v$\<C-X>" + call assert_equal("foobaar-9", getline('.')) + call assert_equal([0, 5, 9, 0], getpos('.')) +endfunc + +" 2) Ctrl-A on visually selected lines +" Text: +" 10 +" 20 +" 30 +" 40 +" +" Expected: +" 1) Ctrl-A on visually selected lines: +" 11 +" 21 +" 31 +" 41 +" +" 2) Ctrl-X on visually selected lines: +" 9 +" 19 +" 29 +" 39 +func Test_visual_increment_02() + call setline(1, ["10", "20", "30", "40"]) + exec "norm! GV3k$\<C-A>" + call assert_equal(["11", "21", "31", "41"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) + + call setline(1, ["10", "20", "30", "40"]) + exec "norm! GV3k$\<C-X>" + call assert_equal(["9", "19", "29", "39"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" 3) g Ctrl-A on visually selected lines, with non-numbers in between +" Text: +" 10 +" +" 20 +" +" 30 +" +" 40 +" +" Expected: +" 1) 2 g Ctrl-A on visually selected lines: +" 12 +" +" 24 +" +" 36 +" +" 48 +" 2) 2 g Ctrl-X on visually selected lines +" 8 +" +" 16 +" +" 24 +" +" 32 +func Test_visual_increment_03() + call setline(1, ["10", "", "20", "", "30", "", "40"]) + exec "norm! GV6k2g\<C-A>" + call assert_equal(["12", "", "24", "", "36", "", "48"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) + + call setline(1, ["10", "", "20", "", "30", "", "40"]) + exec "norm! GV6k2g\<C-X>" + call assert_equal(["8", "", "16", "", "24", "", "32"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" 4) Ctrl-A on non-number +" Text: +" foobar-10 +" Expected: +" 1) visually select foobar: +" foobar-10 +func Test_visual_increment_04() + call setline(1, ["foobar-10"]) + exec "norm! vf-\<C-A>" + call assert_equal(["foobar-10"], getline(1, '$')) + " NOTE: I think this is correct behavior... + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" 5) g<Ctrl-A> on letter +" Test: +" a +" a +" a +" a +" Expected: +" 1) g Ctrl-A on visually selected lines +" b +" c +" d +" e +func Test_visual_increment_05() + set nrformats+=alpha + call setline(1, repeat(["a"], 4)) + exec "norm! GV3kg\<C-A>" + call assert_equal(["b", "c", "d", "e"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" 6) g<Ctrl-A> on letter +" Test: +" z +" z +" z +" z +" Expected: +" 1) g Ctrl-X on visually selected lines +" y +" x +" w +" v +func Test_visual_increment_06() + set nrformats+=alpha + call setline(1, repeat(["z"], 4)) + exec "norm! GV3kg\<C-X>" + call assert_equal(["y", "x", "w", "v"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" 7) <Ctrl-A> on letter +" Test: +" 2 +" 1 +" 0 +" -1 +" -2 +" +" Expected: +" 1) Ctrl-A on visually selected lines +" 3 +" 2 +" 1 +" 0 +" -1 +" +" 2) Ctrl-X on visually selected lines +" 1 +" 0 +" -1 +" -2 +" -3 +func Test_visual_increment_07() + call setline(1, ["2", "1", "0", "-1", "-2"]) + exec "norm! GV4k\<C-A>" + call assert_equal(["3", "2", "1", "0", "-1"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) + + call setline(1, ["2", "1", "0", "-1", "-2"]) + exec "norm! GV4k\<C-X>" + call assert_equal(["1", "0", "-1", "-2", "-3"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" 8) Block increment on 0x9 +" Text: +" 0x9 +" 0x9 +" Expected: +" 1) Ctrl-A on visually block selected region (cursor at beginning): +" 0xa +" 0xa +" 2) Ctrl-A on visually block selected region (cursor at end) +" 0xa +" 0xa +func Test_visual_increment_08() + call setline(1, repeat(["0x9"], 2)) + exec "norm! \<C-V>j$\<C-A>" + call assert_equal(["0xa", "0xa"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) + + call setline(1, repeat(["0x9"], 2)) + exec "norm! gg$\<C-V>+\<C-A>" + call assert_equal(["0xa", "0xa"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" 9) Increment and redo +" Text: +" 2 +" 2 +" +" 3 +" 3 +" +" Expected: +" 1) 2 Ctrl-A on first 2 visually selected lines +" 4 +" 4 +" 2) redo (.) on 3 +" 5 +" 5 +func Test_visual_increment_09() + call setline(1, ["2", "2", "", "3", "3", ""]) + exec "norm! ggVj2\<C-A>" + call assert_equal(["4", "4", "", "3", "3", ""], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) + + exec "norm! 3j." + call assert_equal(["4", "4", "", "5", "5", ""], getline(1, '$')) + call assert_equal([0, 4, 1, 0], getpos('.')) +endfunc + +" 10) sequentially decrement 1 +" Text: +" 1 +" 1 +" 1 +" 1 +" Expected: +" 1) g Ctrl-X on visually selected lines +" 0 +" -1 +" -2 +" -3 +func Test_visual_increment_10() + call setline(1, repeat(["1"], 4)) + exec "norm! GV3kg\<C-X>" + call assert_equal(["0", "-1", "-2", "-3"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" 11) visually block selected indented lines +" Text: +" 1 +" 1 +" 1 +" 1 +" Expexted: +" 1) g Ctrl-A on block selected indented lines +" 2 +" 1 +" 3 +" 4 +func Test_visual_increment_11() + call setline(1, [" 1", "1", " 1", " 1"]) + exec "norm! f1\<C-V>3jg\<C-A>" + call assert_equal([" 2", "1", " 3", " 4"], getline(1, '$')) + call assert_equal([0, 1, 5, 0], getpos('.')) +endfunc + +" 12) visually selected several columns +" Text: +" 0 0 +" 0 0 +" 0 0 +" Expected: +" 1) 'v' select last zero and first zeroes +" 0 1 +" 1 0 +" 1 0 +func Test_visual_increment_12() + call setline(1, repeat(["0 0"], 3)) + exec "norm! $v++\<C-A>" + call assert_equal(["0 1", "1 0", "1 0"], getline(1, '$')) + call assert_equal([0, 1, 3, 0], getpos('.')) +endfunc + +" 13) visually selected part of columns +" Text: +" max: 100px +" max: 200px +" max: 300px +" max: 400px +" Expected: +" 1) 'v' on first two numbers Ctrl-A +" max: 110px +" max: 220px +" max: 330px +" max: 400px +" 2) 'v' on first two numbers Ctrl-X +" max: 90px +" max: 190px +" max: 290px +" max: 400px +func Test_visual_increment_13() + call setline(1, ["max: 100px", "max: 200px", "max: 300px", "max: 400px"]) + exec "norm! f1\<C-V>l2j\<C-A>" + call assert_equal(["max: 110px", "max: 210px", "max: 310px", "max: 400px"], getline(1, '$')) + call assert_equal([0, 1, 6, 0], getpos('.')) + + call setline(1, ["max: 100px", "max: 200px", "max: 300px", "max: 400px"]) + exec "norm! ggf1\<C-V>l2j\<C-X>" + call assert_equal(["max: 90px", "max: 190px", "max: 290px", "max: 400px"], getline(1, '$')) + call assert_equal([0, 1, 6, 0], getpos('.')) +endfunc + +" 14) redo in block mode +" Text: +" 1 1 +" 1 1 +" Expected: +" 1) Ctrl-a on first column, redo on second column +" 2 2 +" 2 2 +func Test_visual_increment_14() + call setline(1, repeat(["1 1"], 2)) + exec "norm! G\<C-V>k\<C-A>w." + call assert_equal(["2 2", "2 2"], getline(1, '$')) + call assert_equal([0, 1, 3, 0], getpos('.')) +endfunc + +" 15) block select single numbers +" Text: +" 101 +" Expected: +" 1) Ctrl-a on visually selected zero +" 111 +func Test_visual_increment_15() + call setline(1, ["101"]) + exec "norm! lv\<C-A>" + call assert_equal(["111"], getline(1, '$')) + call assert_equal([0, 1, 2, 0], getpos('.')) +endfunc + +" 16) increment right aligned numbers +" Text: +" 1 +" 19 +" 119 +" Expected: +" 1) Ctrl-a on line selected region +" 2 +" 20 +" 120 +func Test_visual_increment_16() + call setline(1, [" 1", " 19", " 119"]) + exec "norm! VG\<C-A>" + call assert_equal([" 2", " 20", " 120"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" 17) block-wise increment and redo +" Text: +" 100 +" 1 +" +" 100 +" 1 +" +" Expected: +" 1) Ctrl-V j $ on first block, afterwards '.' on second +" 101 +" 2 +" +" 101 +" 2 +func Test_visual_increment_17() + call setline(1, [" 100", " 1", "", " 100", " 1"]) + exec "norm! \<C-V>j$\<C-A>2j." + call assert_equal([" 101", " 2", "", " 101", " 1"], getline(1, '$')) + call assert_equal([0, 3, 1, 0], getpos('.')) +endfunc + +" 18) repeat of g<Ctrl-a> +" Text: +" 0 +" 0 +" 0 +" 0 +" +" Expected: +" 1) V 4j g<ctrl-a>, repeat twice afterwards with . +" 3 +" 6 +" 9 +" 12 +func Test_visual_increment_18() + call setline(1, repeat(["0"], 4)) + exec "norm! GV3kg\<C-A>" + exec "norm! .." + call assert_equal(["3", "6", "9", "12"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" 19) increment on number with nrformat including alpha +" Text: +" 1 +" 1a +" +" Expected: +" 1) <Ctrl-V>j$ <ctrl-a> +" 2 +" 2a +func Test_visual_increment_19() + set nrformats+=alpha + call setline(1, ["1", "1a"]) + exec "norm! \<C-V>G$\<C-A>" + call assert_equal(["2", "2a"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" 20) increment a single letter +" Text: +" a +" +" Expected: +" 1) <Ctrl-a> and cursor is on a +" b +func Test_visual_increment_20() + set nrformats+=alpha + call setline(1, ["a"]) + exec "norm! \<C-A>" + call assert_equal(["b"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" 21) block-wise increment on part of hexadecimal +" Text: +" 0x123456 +" +" Expected: +" 1) Ctrl-V f3 <ctrl-a> +" 0x124456 +func Test_visual_increment_21() + call setline(1, ["0x123456"]) + exec "norm! \<C-V>f3\<C-A>" + call assert_equal(["0x124456"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" 22) Block increment on 0b0 +" Text: +" 0b1 +" 0b1 +" Expected: +" 1) Ctrl-A on visually block selected region (cursor at beginning): +" 0b10 +" 0b10 +" 2) Ctrl-A on visually block selected region (cursor at end) +" 0b10 +" 0b10 +func Test_visual_increment_22() + call setline(1, repeat(["0b1"], 2)) + exec "norm! \<C-V>j$\<C-A>" + call assert_equal(repeat(["0b10"], 2), getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) + + call setline(1, repeat(["0b1"], 2)) + exec "norm! $\<C-V>+\<C-A>" + call assert_equal(repeat(["0b10"], 2), getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" 23) block-wise increment on part of binary +" Text: +" 0b1001 +" +" Expected: +" 1) Ctrl-V 5l <ctrl-a> +" 0b1011 +func Test_visual_increment_23() + call setline(1, ["0b1001"]) + exec "norm! \<C-V>4l\<C-A>" + call assert_equal(["0b1011"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" 24) increment hexadecimal +" Text: +" 0x0b1001 +" +" Expected: +" 1) <ctrl-a> +" 0x0b1002 +func Test_visual_increment_24() + call setline(1, ["0x0b1001"]) + exec "norm! \<C-V>$\<C-A>" + call assert_equal(["0x0b1002"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" 25) increment binary with nrformats including alpha +" Text: +" 0b1001a +" +" Expected: +" 1) <ctrl-a> +" 0b1010a +func Test_visual_increment_25() + set nrformats+=alpha + call setline(1, ["0b1001a"]) + exec "norm! \<C-V>$\<C-A>" + call assert_equal(["0b1010a"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" 26) increment binary with 32 bits +" Text: +" 0b11111111111111111111111111111110 +" +" Expected: +" 1) <ctrl-a> +" 0b11111111111111111111111111111111 +func Test_visual_increment_26() + set nrformats+=alpha + call setline(1, ["0b11111111111111111111111111111110"]) + exec "norm! \<C-V>$\<C-A>" + call assert_equal(["0b11111111111111111111111111111111"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) + set nrformats-=alpha +endfunc + +" 27) increment with 'rightreft', if supported +func Test_visual_increment_27() + if exists('+rightleft') + set rightleft + call setline(1, ["1234 56"]) + + exec "norm! $\<C-A>" + call assert_equal(["1234 57"], getline(1, '$')) + call assert_equal([0, 1, 7, 0], getpos('.')) + + exec "norm! \<C-A>" + call assert_equal(["1234 58"], getline(1, '$')) + call assert_equal([0, 1, 7, 0], getpos('.')) + set norightleft + endif +endfunc + +" Tab code and linewise-visual inc/dec +func Test_visual_increment_28() + call setline(1, ["x\<TAB>10", "\<TAB>-1"]) + exec "norm! Vj\<C-A>" + call assert_equal(["x\<TAB>11", "\<TAB>0"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) + + call setline(1, ["x\<TAB>10", "\<TAB>-1"]) + exec "norm! ggVj\<C-X>" + call assert_equal(["x\<TAB>9", "\<TAB>-2"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" Tab code and linewise-visual inc/dec with 'nrformats'+=alpha +func Test_visual_increment_29() + set nrformats+=alpha + call setline(1, ["x\<TAB>10", "\<TAB>-1"]) + exec "norm! Vj\<C-A>" + call assert_equal(["y\<TAB>10", "\<TAB>0"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) + + call setline(1, ["x\<TAB>10", "\<TAB>-1"]) + exec "norm! ggVj\<C-X>" + call assert_equal(["w\<TAB>10", "\<TAB>-2"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" Tab code and character-visual inc/dec +func Test_visual_increment_30() + call setline(1, ["x\<TAB>10", "\<TAB>-1"]) + exec "norm! f1vjf1\<C-A>" + call assert_equal(["x\<TAB>11", "\<TAB>0"], getline(1, '$')) + call assert_equal([0, 1, 3, 0], getpos('.')) + + call setline(1, ["x\<TAB>10", "\<TAB>-1"]) + exec "norm! ggf1vjf1\<C-X>" + call assert_equal(["x\<TAB>9", "\<TAB>-2"], getline(1, '$')) + call assert_equal([0, 1, 3, 0], getpos('.')) +endfunc + +" Tab code and blockwise-visual inc/dec +func Test_visual_increment_31() + call setline(1, ["x\<TAB>10", "\<TAB>-1"]) + exec "norm! f1\<C-V>jl\<C-A>" + call assert_equal(["x\<TAB>11", "\<TAB>0"], getline(1, '$')) + call assert_equal([0, 1, 3, 0], getpos('.')) + + call setline(1, ["x\<TAB>10", "\<TAB>-1"]) + exec "norm! ggf1\<C-V>jl\<C-X>" + call assert_equal(["x\<TAB>9", "\<TAB>-2"], getline(1, '$')) + call assert_equal([0, 1, 3, 0], getpos('.')) +endfunc + +" Tab code and blockwise-visual decrement with 'linebreak' and 'showbreak' +func Test_visual_increment_32() + 28vnew dummy_31 + set linebreak showbreak=+ + call setline(1, ["x\<TAB>\<TAB>\<TAB>10", "\<TAB>\<TAB>\<TAB>\<TAB>-1"]) + exec "norm! ggf0\<C-V>jg_\<C-X>" + call assert_equal(["x\<TAB>\<TAB>\<TAB>1-1", "\<TAB>\<TAB>\<TAB>\<TAB>-2"], getline(1, '$')) + call assert_equal([0, 1, 6, 0], getpos('.')) + bwipe! +endfunc + +" Tab code and blockwise-visual increment with $ +func Test_visual_increment_33() + call setline(1, ["\<TAB>123", "456"]) + exec "norm! gg0\<C-V>j$\<C-A>" + call assert_equal(["\<TAB>124", "457"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" Tab code and blockwise-visual increment and redo +func Test_visual_increment_34() + call setline(1, ["\<TAB>123", " 456789"]) + exec "norm! gg0\<C-V>j\<C-A>" + call assert_equal(["\<TAB>123", " 457789"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) + + exec "norm! .." + call assert_equal(["\<TAB>123", " 459789"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" Tab code, spaces and character-visual increment and redo +func Test_visual_increment_35() + call setline(1, ["\<TAB>123", " 123", "\<TAB>123", "\<TAB>123"]) + exec "norm! ggvjf3\<C-A>..." + call assert_equal(["\<TAB>127", " 127", "\<TAB>123", "\<TAB>123"], getline(1, '$')) + call assert_equal([0, 1, 2, 0], getpos('.')) +endfunc + +" Tab code, spaces and blockwise-visual increment and redo +func Test_visual_increment_36() + call setline(1, [" 123", "\<TAB>456789"]) + exec "norm! G0\<C-V>kl\<C-A>" + call assert_equal([" 123", "\<TAB>556789"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) + + exec "norm! ..." + call assert_equal([" 123", "\<TAB>856789"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" block-wise increment and dot-repeat +" Text: +" 1 23 +" 4 56 +" +" Expected: +" 1) f2 Ctrl-V jl <ctrl-a>, repeat twice afterwards with . +" 1 26 +" 4 59 +" +" Try with and without indent. +func Test_visual_increment_37() + call setline(1, [" 1 23", " 4 56"]) + exec "norm! ggf2\<C-V>jl\<C-A>.." + call assert_equal([" 1 26", " 4 59"], getline(1, 2)) + + call setline(1, ["1 23", "4 56"]) + exec "norm! ggf2\<C-V>jl\<C-A>.." + call assert_equal(["1 26", "4 59"], getline(1, 2)) +endfunc + +" Check redo after the normal mode increment +func Test_visual_increment_38() + exec "norm! i10\<ESC>5\<C-A>." + call assert_equal(["20"], getline(1, '$')) + call assert_equal([0, 1, 2, 0], getpos('.')) +endfunc + +" Test what patch 7.3.414 fixed. Ctrl-A on "000" drops the leading zeros. +func Test_normal_increment_01() + call setline(1, "000") + exec "norm! gg0\<C-A>" + call assert_equal("001", getline(1)) + + call setline(1, "000") + exec "norm! gg$\<C-A>" + call assert_equal("001", getline(1)) + + call setline(1, "001") + exec "norm! gg0\<C-A>" + call assert_equal("002", getline(1)) + + call setline(1, "001") + exec "norm! gg$\<C-A>" + call assert_equal("002", getline(1)) +endfunc + +" Test a regression of patch 7.4.1087 fixed. +func Test_normal_increment_02() + call setline(1, ["hello 10", "world"]) + exec "norm! ggl\<C-A>jx" + call assert_equal(["hello 11", "worl"], getline(1, '$')) + call assert_equal([0, 2, 4, 0], getpos('.')) +endfunc + +" The test35 unified to this file. +func Test_normal_increment_03() + call setline(1, ["100 0x100 077 0", + \ "100 0x100 077 ", + \ "100 0x100 077 0xfF 0xFf", + \ "100 0x100 077 "]) + set nrformats=octal,hex + exec "norm! gg\<C-A>102\<C-X>\<C-A>l\<C-X>l\<C-A>64\<C-A>128\<C-X>$\<C-X>" + set nrformats=octal + exec "norm! j0\<C-A>102\<C-X>\<C-A>l\<C-X>2\<C-A>w65\<C-A>129\<C-X>blx6lD" + set nrformats=hex + exec "norm! j0101\<C-X>l257\<C-X>\<C-A>Txldt \<C-A> \<C-X> \<C-X>" + set nrformats= + exec "norm! j0200\<C-X>l100\<C-X>w78\<C-X>\<C-A>k" + call assert_equal(["0 0x0ff 0000 -1", + \ "0 1x100 0777777", + \ "-1 0x0 078 0xFE 0xfe", + \ "-100 -100x100 000 "], getline(1, '$')) + call assert_equal([0, 3, 25, 0], getpos('.')) +endfunc + + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_increment_dbcs.vim b/src/nvim/testdir/test_increment_dbcs.vim new file mode 100644 index 0000000000..474a16feeb --- /dev/null +++ b/src/nvim/testdir/test_increment_dbcs.vim @@ -0,0 +1,29 @@ +" Tests for using Ctrl-A/Ctrl-X using DBCS. +if !has('multi_byte') + finish +endif +scriptencoding cp932 + +func SetUp() + new + set nrformats& +endfunc + +func TearDown() + bwipe! +endfunc + +func Test_increment_dbcs_1() + set nrformats+=alpha + call setline(1, ["R1"]) + exec "norm! 0\<C-A>" + call assert_equal(["R2"], getline(1, '$')) + call assert_equal([0, 1, 4, 0], getpos('.')) + + call setline(1, ["`ab0xDEe"]) + exec "norm! 0\<C-X>" + call assert_equal(["`ab0xDDe"], getline(1, '$')) + call assert_equal([0, 1, 13, 0], getpos('.')) +endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_lambda.vim b/src/nvim/testdir/test_lambda.vim new file mode 100644 index 0000000000..311cc6e2cb --- /dev/null +++ b/src/nvim/testdir/test_lambda.vim @@ -0,0 +1,287 @@ +" Test for lambda and closure + +function! Test_lambda_feature() + call assert_equal(1, has('lambda')) +endfunction + +function! Test_lambda_with_filter() + let s:x = 2 + call assert_equal([2, 3], filter([1, 2, 3], {i, v -> v >= s:x})) +endfunction + +function! Test_lambda_with_map() + let s:x = 1 + call assert_equal([2, 3, 4], map([1, 2, 3], {i, v -> v + s:x})) +endfunction + +function! Test_lambda_with_sort() + call assert_equal([1, 2, 3, 4, 7], sort([3,7,2,1,4], {a, b -> a - b})) +endfunction + +function! Test_lambda_with_timer() + if !has('timers') + return + endif + + let s:n = 0 + let s:timer_id = 0 + function! s:Foo() + "let n = 0 + let s:timer_id = timer_start(50, {-> execute("let s:n += 1 | echo s:n", "")}, {"repeat": -1}) + endfunction + + call s:Foo() + sleep 200ms + " do not collect lambda + call garbagecollect() + let m = s:n + sleep 200ms + call timer_stop(s:timer_id) + call assert_true(m > 1) + call assert_true(s:n > m + 1) + call assert_true(s:n < 9) +endfunction + +function! Test_lambda_with_partial() + let l:Cb = function({... -> ['zero', a:1, a:2, a:3]}, ['one', 'two']) + call assert_equal(['zero', 'one', 'two', 'three'], l:Cb('three')) +endfunction + +function Test_lambda_fails() + call assert_equal(3, {a, b -> a + b}(1, 2)) + call assert_fails('echo {a, a -> a + a}(1, 2)', 'E15:') + call assert_fails('echo {a, b -> a + b)}(1, 2)', 'E15:') +endfunc + +func Test_not_lambda() + let x = {'>' : 'foo'} + call assert_equal('foo', x['>']) +endfunc + +function! Test_lambda_capture_by_reference() + let v = 1 + let l:F = {x -> x + v} + let v = 2 + call assert_equal(12, l:F(10)) +endfunction + +function! Test_lambda_side_effect() + function! s:update_and_return(arr) + let a:arr[1] = 5 + return a:arr + endfunction + + function! s:foo(arr) + return {-> s:update_and_return(a:arr)} + endfunction + + let arr = [3,2,1] + call assert_equal([3, 5, 1], s:foo(arr)()) +endfunction + +function! Test_lambda_refer_local_variable_from_other_scope() + function! s:foo(X) + return a:X() " refer l:x in s:bar() + endfunction + + function! s:bar() + let x = 123 + return s:foo({-> x}) + endfunction + + call assert_equal(123, s:bar()) +endfunction + +function! Test_lambda_do_not_share_local_variable() + function! s:define_funcs() + let l:One = {-> split(execute("let a = 'abc' | echo a"))[0]} + let l:Two = {-> exists("a") ? a : "no"} + return [l:One, l:Two] + endfunction + + let l:F = s:define_funcs() + + call assert_equal('no', l:F[1]()) + call assert_equal('abc', l:F[0]()) + call assert_equal('no', l:F[1]()) +endfunction + +function! Test_lambda_closure_counter() + function! s:foo() + let x = 0 + return {-> [execute("let x += 1"), x][-1]} + endfunction + + let l:F = s:foo() + call garbagecollect() + call assert_equal(1, l:F()) + call assert_equal(2, l:F()) + call assert_equal(3, l:F()) + call assert_equal(4, l:F()) +endfunction + +function! Test_lambda_with_a_var() + function! s:foo() + let x = 2 + return {... -> a:000 + [x]} + endfunction + function! s:bar() + return s:foo()(1) + endfunction + + call assert_equal([1, 2], s:bar()) +endfunction + +function! Test_lambda_call_lambda_from_lambda() + function! s:foo(x) + let l:F1 = {-> {-> a:x}} + return {-> l:F1()} + endfunction + + let l:F = s:foo(1) + call assert_equal(1, l:F()()) +endfunction + +function! Test_lambda_delfunc() + function! s:gen() + let pl = l: + let l:Foo = {-> get(pl, "Foo", get(pl, "Bar", {-> 0}))} + let l:Bar = l:Foo + delfunction l:Foo + return l:Bar + endfunction + + let l:F = s:gen() + call assert_fails(':call l:F()', 'E933:') +endfunction + +function! Test_lambda_scope() + function! s:NewCounter() + let c = 0 + return {-> [execute('let c += 1'), c][-1]} + endfunction + + function! s:NewCounter2() + return {-> [execute('let c += 100'), c][-1]} + endfunction + + let l:C = s:NewCounter() + let l:D = s:NewCounter2() + + call assert_equal(1, l:C()) + call assert_fails(':call l:D()', 'E15:') " E121: then E15: + call assert_equal(2, l:C()) +endfunction + +function! Test_lambda_share_scope() + function! s:New() + let c = 0 + let l:Inc0 = {-> [execute('let c += 1'), c][-1]} + let l:Dec0 = {-> [execute('let c -= 1'), c][-1]} + return [l:Inc0, l:Dec0] + endfunction + + let [l:Inc, l:Dec] = s:New() + + call assert_equal(1, l:Inc()) + call assert_equal(2, l:Inc()) + call assert_equal(1, l:Dec()) +endfunction + +function! Test_lambda_circular_reference() + function! s:Foo() + let d = {} + let d.f = {-> d} + return d.f + endfunction + + call s:Foo() + call garbagecollect() + let i = 0 | while i < 10000 | call s:Foo() | let i+= 1 | endwhile + call garbagecollect() +endfunction + +function! Test_lambda_combination() + call assert_equal(2, {x -> {x -> x}}(1)(2)) + call assert_equal(10, {y -> {x -> x(y)(10)}({y -> y})}({z -> z})) + call assert_equal(5.0, {x -> {y -> x / y}}(10)(2.0)) + call assert_equal(6, {x -> {y -> {z -> x + y + z}}}(1)(2)(3)) + + call assert_equal(6, {x -> {f -> f(x)}}(3)({x -> x * 2})) + call assert_equal(6, {f -> {x -> f(x)}}({x -> x * 2})(3)) + + " Z combinator + let Z = {f -> {x -> f({y -> x(x)(y)})}({x -> f({y -> x(x)(y)})})} + let Fact = {f -> {x -> x == 0 ? 1 : x * f(x - 1)}} + call assert_equal(120, Z(Fact)(5)) +endfunction + +function! Test_closure_counter() + function! s:foo() + let x = 0 + function! s:bar() closure + let x += 1 + return x + endfunction + return function('s:bar') + endfunction + + let l:F = s:foo() + call garbagecollect() + call assert_equal(1, l:F()) + call assert_equal(2, l:F()) + call assert_equal(3, l:F()) + call assert_equal(4, l:F()) +endfunction + +function! Test_closure_unlet() + function! s:foo() + let x = 1 + function! s:bar() closure + unlet x + endfunction + call s:bar() + return l: + endfunction + + call assert_false(has_key(s:foo(), 'x')) + call garbagecollect() +endfunction + +function! LambdaFoo() + let x = 0 + function! LambdaBar() closure + let x += 1 + return x + endfunction + return function('LambdaBar') +endfunction + +func Test_closure_refcount() + let g:Count = LambdaFoo() + call test_garbagecollect_now() + call assert_equal(1, g:Count()) + let g:Count2 = LambdaFoo() + call test_garbagecollect_now() + call assert_equal(1, g:Count2()) + call assert_equal(2, g:Count()) + call assert_equal(3, g:Count2()) + + delfunc LambdaFoo + delfunc LambdaBar +endfunc + +" This test is causing a use-after-free on shutdown. +func Test_named_function_closure() + func! Afoo() + let x = 14 + func! s:Abar() closure + return x + endfunc + call assert_equal(14, s:Abar()) + endfunc + call Afoo() + call assert_equal(14, s:Abar()) + call garbagecollect() + call assert_equal(14, s:Abar()) +endfunc diff --git a/src/nvim/testdir/test_largefile.vim b/src/nvim/testdir/test_largefile.vim new file mode 100644 index 0000000000..1b3e02a0c8 --- /dev/null +++ b/src/nvim/testdir/test_largefile.vim @@ -0,0 +1,34 @@ +" Tests for large files +" This is only executed manually: "make test_largefile". +" This is not run as part of "make test". + +func Test_largefile() + let fname = 'Xlarge.txt' + + call delete(fname) + exe "e" fname + " Make sure that a line break is 1 byte (LF). + set ff=unix + set undolevels=-1 + " Input 99 'A's. The line becomes 100 bytes including a line break. + exe "normal 99iA\<Esc>" + yank + " Put 39,999,999 times. The file becomes 4,000,000,000 bytes. + normal 39999999p + " Moving around in the file randomly. + normal G + normal 10% + normal 90% + normal 50% + normal gg + w + " Check if the file size is 4,000,000,000 bytes. + let fsize=getfsize(fname) + if has('num64') + call assert_true(fsize == 4000000000) + else + " getfsize() returns -2 if a Number is 32 bits. + call assert_true(fsize == -2) + endif + call delete(fname) +endfunc diff --git a/src/nvim/testdir/test_listlbr.vim b/src/nvim/testdir/test_listlbr.vim new file mode 100644 index 0000000000..7856ee82ab --- /dev/null +++ b/src/nvim/testdir/test_listlbr.vim @@ -0,0 +1,235 @@ +" Test for linebreak and list option (non-utf8) + +set encoding=latin1 +scriptencoding latin1 + +if !exists("+linebreak") || !has("conceal") + finish +endif + +source view_util.vim + +function s:screen_lines(lnum, width) abort + return ScreenLines(a:lnum, a:width) +endfunction + +function! s:compare_lines(expect, actual) + call assert_equal(join(a:expect, "\n"), join(a:actual, "\n")) +endfunction + +function s:test_windows(...) + call NewWindow(10, 20) + setl ts=8 sw=4 sts=4 linebreak sbr= wrap + exe get(a:000, 0, '') +endfunction + +function s:close_windows(...) + call CloseWindow() + exe get(a:000, 0, '') +endfunction + +func Test_set_linebreak() + call s:test_windows('setl ts=4 sbr=+') + call setline(1, "\tabcdef hijklmn\tpqrstuvwxyz_1060ABCDEFGHIJKLMNOP ") + let lines = s:screen_lines([1, 4], winwidth(0)) + let expect = [ +\ " abcdef ", +\ "+hijklmn ", +\ "+pqrstuvwxyz_1060ABC", +\ "+DEFGHIJKLMNOP ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_linebreak_with_list() + call s:test_windows('setl ts=4 sbr=+ list listchars=') + call setline(1, "\tabcdef hijklmn\tpqrstuvwxyz_1060ABCDEFGHIJKLMNOP ") + let lines = s:screen_lines([1, 4], winwidth(0)) + let expect = [ +\ "^Iabcdef hijklmn^I ", +\ "+pqrstuvwxyz_1060ABC", +\ "+DEFGHIJKLMNOP ", +\ "~ ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_linebreak_with_nolist() + call s:test_windows('setl ts=4 sbr=+ nolist') + call setline(1, "\tabcdef hijklmn\tpqrstuvwxyz_1060ABCDEFGHIJKLMNOP ") + let lines = s:screen_lines([1, 4], winwidth(0)) + let expect = [ +\ " abcdef ", +\ "+hijklmn ", +\ "+pqrstuvwxyz_1060ABC", +\ "+DEFGHIJKLMNOP ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_should_break() + call s:test_windows('setl sbr=+ nolist') + call setline(1, "1\t" . repeat('a', winwidth(0)-2)) + let lines = s:screen_lines([1, 4], winwidth(0)) + let expect = [ +\ "1 ", +\ "+aaaaaaaaaaaaaaaaaa ", +\ "~ ", +\ "~ ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_linebreak_with_conceal() + call s:test_windows('setl cpo&vim sbr=+ list conceallevel=2 concealcursor=nv listchars=tab:ab') + call setline(1, "_S_\t bla") + syn match ConcealVar contained /_/ conceal + syn match All /.*/ contains=ConcealVar + let lines = s:screen_lines([1, 4], winwidth(0)) + let expect = [ +\ "Sabbbbbb bla ", +\ "~ ", +\ "~ ", +\ "~ ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_virtual_block() + call s:test_windows('setl sbr=+') + call setline(1, [ +\ "REMOVE: this not", +\ "REMOVE: aaaaaaaaaaaaa", +\ ]) + exe "norm! 1/^REMOVE:" + exe "norm! 0\<C-V>jf x" + $put + let lines = s:screen_lines([1, 4], winwidth(0)) + let expect = [ +\ "this not ", +\ "aaaaaaaaaaaaa ", +\ "REMOVE: ", +\ "REMOVE: ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_virtual_block_and_vbA() + call s:test_windows() + call setline(1, "long line: " . repeat("foobar ", 40) . "TARGET at end") + exe "norm! $3B\<C-v>eAx\<Esc>" + let lines = s:screen_lines([1, 10], winwidth(0)) + let expect = [ +\ "foobar foobar ", +\ "foobar foobar ", +\ "foobar foobar ", +\ "foobar foobar ", +\ "foobar foobar ", +\ "foobar foobar ", +\ "foobar foobar ", +\ "foobar foobar ", +\ "foobar foobar ", +\ "foobar TARGETx at ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_virtual_char_and_block() + call s:test_windows() + call setline(1, "1111-1111-1111-11-1111-1111-1111") + exe "norm! 0f-lv3lc2222\<Esc>bgj." + let lines = s:screen_lines([1, 2], winwidth(0)) + let expect = [ +\ "1111-2222-1111-11- ", +\ "1111-2222-1111 ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_undo_after_block_visual() + call s:test_windows() + call setline(1, ["aaa", "aaa", "a"]) + exe "norm! gg\<C-V>2j~e." + let lines = s:screen_lines([1, 3], winwidth(0)) + let expect = [ +\ "AaA ", +\ "AaA ", +\ "A ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_norm_after_block_visual() + call s:test_windows() + call setline(1, ["abcd{ef", "ghijklm", "no}pgrs"]) + exe "norm! ggf{\<C-V>\<C-V>c%" + let lines = s:screen_lines([1, 3], winwidth(0)) + let expect = [ +\ "abcdpgrs ", +\ "~ ", +\ "~ ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_block_replace_after_wrapping() + call s:test_windows() + call setline(1, repeat("a", 150)) + exe "norm! 0yypk147|\<C-V>jr0" + call assert_equal(repeat("a", 146) . "0aaa", getline(1)) + call assert_equal(repeat("a", 146) . "0aaa", getline(2)) + let lines = s:screen_lines([1, 10], winwidth(0)) + let expect = [ +\ "aaaaaaaaaaaaaaaaaaaa", +\ "aaaaaaaaaaaaaaaaaaaa", +\ "aaaaaaaaaaaaaaaaaaaa", +\ "aaaaaaaaaaaaaaaaaaaa", +\ "aaaaaaaaaaaaaaaaaaaa", +\ "aaaaaaaaaaaaaaaaaaaa", +\ "aaaaaaaaaaaaaaaaaaaa", +\ "aaaaaa0aaa ", +\ "@ ", +\ "@ ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_list_with_listchars() + call s:test_windows('setl list listchars=space:_,trail:-,tab:>-,eol:$') + call setline(1, "a aaaaaaaaaaaaaaaaaaaaaa\ta ") + let lines = s:screen_lines([1, 3], winwidth(0)) + let expect = [ +\ "a_ ", +\ "aaaaaaaaaaaaaaaaaaaa", +\ "aa>-----a-$ ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_list_with_tab_and_skipping_first_chars() + call s:test_windows('setl list listchars=tab:>- ts=70 nowrap') + call setline(1, ["iiiiiiiiiiiiiiii\taaaaaaaaaaaaaaaaaa", "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii\taaaaaaaaaaaaaaaaaa", "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii\taaaaaaaaaaaaaaaaaa", "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii\taaaaaaaaaaaaaaaaaa"]) + call cursor(4,64) + norm! 2zl + let lines = s:screen_lines([1, 4], winwidth(0)) + let expect = [ +\ "---------------aaaaa", +\ "---------------aaaaa", +\ "---------------aaaaa", +\ "iiiiiiiii>-----aaaaa", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfu diff --git a/src/nvim/testdir/test_listlbr_utf8.vim b/src/nvim/testdir/test_listlbr_utf8.vim new file mode 100644 index 0000000000..980d67d49d --- /dev/null +++ b/src/nvim/testdir/test_listlbr_utf8.vim @@ -0,0 +1,229 @@ +" Test for linebreak and list option in utf-8 mode + +set encoding=utf-8 +scriptencoding utf-8 + +if !exists("+linebreak") || !has("conceal") || !has("signs") + finish +endif + +source view_util.vim + +function s:screen_lines(lnum, width) abort + return ScreenLines(a:lnum, a:width) +endfunction + +function! s:compare_lines(expect, actual) + call assert_equal(a:expect, a:actual) +endfunction + +function s:screen_attr(lnum, chars, ...) abort + let line = getline(a:lnum) + let attr = [] + let prefix = get(a:000, 0, 0) + for i in range(a:chars[0], a:chars[1]) + let scol = strdisplaywidth(strcharpart(line, 0, i-1)) + 1 + let attr += [screenattr(a:lnum, scol + prefix)] + endfor + return attr +endfunction + +function s:test_windows(...) + call NewWindow(10, 20) + setl ts=4 sw=4 sts=4 linebreak sbr=+ wrap + exe get(a:000, 0, '') +endfunction + +function s:close_windows(...) + call CloseWindow() + exe get(a:000, 0, '') +endfunction + +func Test_linebreak_with_fancy_listchars() + call s:test_windows("setl list listchars=nbsp:\u2423,tab:\u2595\u2014,trail:\u02d1,eol:\ub6") + call setline(1, "\tabcdef hijklmn\tpqrstuvwxyz\u00a01060ABCDEFGHIJKLMNOP ") + redraw! + let lines = s:screen_lines([1, 4], winwidth(0)) + let expect = [ +\ "โโโโabcdef ", +\ "+hijklmnโโโโ ", +\ "+pqrstuvwxyzโฃ1060ABC", +\ "+DEFGHIJKLMNOPหยถ ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_nolinebreak_with_list() + call s:test_windows("setl nolinebreak list listchars=nbsp:\u2423,tab:\u2595\u2014,trail:\u02d1,eol:\ub6") + call setline(1, "\tabcdef hijklmn\tpqrstuvwxyz\u00a01060ABCDEFGHIJKLMNOP ") + redraw! + let lines = s:screen_lines([1, 4], winwidth(0)) + let expect = [ +\ "โโโโabcdef hijklmnโโ", +\ "+pqrstuvwxyzโฃ1060ABC", +\ "+DEFGHIJKLMNOPหยถ ", +\ "~ ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_linebreak_with_nolist() + call s:test_windows('setl nolist') + call setline(1, "\t*mask = nil;") + redraw! + let lines = s:screen_lines([1, 4], winwidth(0)) + let expect = [ +\ " *mask = nil; ", +\ "~ ", +\ "~ ", +\ "~ ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_list_and_concealing1() + call s:test_windows('setl list listchars=tab:>- cole=1') + call setline(1, [ +\ "#define ABCDE\t\t1", +\ "#define ABCDEF\t\t1", +\ "#define ABCDEFG\t\t1", +\ "#define ABCDEFGH\t1", +\ "#define MSG_MODE_FILE\t\t\t1", +\ "#define MSG_MODE_CONSOLE\t\t2", +\ "#define MSG_MODE_FILE_AND_CONSOLE\t3", +\ "#define MSG_MODE_FILE_THEN_CONSOLE\t4", +\ ]) + vert resize 40 + syn match Conceal conceal cchar=>'AB\|MSG_MODE' + redraw! + let lines = s:screen_lines([1, 7], winwidth(0)) + let expect = [ +\ "#define ABCDE>-->---1 ", +\ "#define >CDEF>-->---1 ", +\ "#define >CDEFG>->---1 ", +\ "#define >CDEFGH>----1 ", +\ "#define >_FILE>--------->--->---1 ", +\ "#define >_CONSOLE>---------->---2 ", +\ "#define >_FILE_AND_CONSOLE>---------3 ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_list_and_concealing2() + call s:test_windows('setl nowrap ts=2 list listchars=tab:>- cole=2 concealcursor=n') + call setline(1, "bbeeeeee\t\t;\tsome text") + vert resize 40 + syn clear + syn match meaning /;\s*\zs.*/ + syn match hasword /^\x\{8}/ contains=word + syn match word /\<\x\{8}\>/ contains=beginword,endword contained + syn match beginword /\<\x\x/ contained conceal + syn match endword /\x\{6}\>/ contained + hi meaning guibg=blue + hi beginword guibg=green + hi endword guibg=red + redraw! + let lines = s:screen_lines([1, 1], winwidth(0)) + let expect = [ +\ "eeeeee>--->-;>some text ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_screenattr_for_comment() + call s:test_windows("setl ft=c ts=7 list listchars=nbsp:\u2423,tab:\u2595\u2014,trail:\u02d1,eol:\ub6") + call setline(1, " /*\t\t and some more */") + norm! gg0 + syntax on + hi SpecialKey term=underline ctermfg=red guifg=red + redraw! + let line = getline(1) + let attr = s:screen_attr(1, [1, 6]) + call assert_notequal(attr[0], attr[1]) + call assert_notequal(attr[1], attr[3]) + call assert_notequal(attr[3], attr[5]) + call s:close_windows() +endfunc + +func Test_visual_block_and_selection_exclusive() + call s:test_windows('setl selection=exclusive') + call setline(1, "long line: " . repeat("foobar ", 40) . "TARGETร' at end") + exe "norm! $3B\<C-v>eAx\<Esc>" + let lines = s:screen_lines([1, 10], winwidth(0)) + let expect = [ +\ "+foobar foobar ", +\ "+foobar foobar ", +\ "+foobar foobar ", +\ "+foobar foobar ", +\ "+foobar foobar ", +\ "+foobar foobar ", +\ "+foobar foobar ", +\ "+foobar foobar ", +\ "+foobar foobar ", +\ "+foobar TARGETรx' ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_multibyte_sign_and_colorcolumn() + call s:test_windows("setl nolinebreak cc=3 list listchars=nbsp:\u2423,tab:\u2595\u2014,trail:\u02d1,eol:\ub6") + call setline(1, ["", "a b c", "a b c"]) + exe "sign define foo text=\uff0b" + exe "sign place 1 name=foo line=2 buffer=" . bufnr('%') + redraw! + norm! ggj0 + let signwidth = strdisplaywidth("\uff0b") + let attr1 = s:screen_attr(2, [1, 3], signwidth) + let attr2 = s:screen_attr(3, [1, 3], signwidth) + call assert_equal(attr1[0], attr2[0]) + call assert_equal(attr1[1], attr2[1]) + call assert_equal(attr1[2], attr2[2]) + let lines = s:screen_lines([1, 3], winwidth(0)) + let expect = [ +\ " ยถ ", +\ "๏ผa b cยถ ", +\ " a b cยถ ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_chinese_char_on_wrap_column() + call s:test_windows("setl nolbr wrap sbr=") + syntax off + call setline(1, [ +\ 'aaaaaaaaaaaaaaaaaaaไธญ'. +\ 'aaaaaaaaaaaaaaaaaไธญ'. +\ 'aaaaaaaaaaaaaaaaaไธญ'. +\ 'aaaaaaaaaaaaaaaaaไธญ'. +\ 'aaaaaaaaaaaaaaaaaไธญ'. +\ 'aaaaaaaaaaaaaaaaaไธญ'. +\ 'aaaaaaaaaaaaaaaaaไธญ'. +\ 'aaaaaaaaaaaaaaaaaไธญ'. +\ 'aaaaaaaaaaaaaaaaaไธญ'. +\ 'aaaaaaaaaaaaaaaaaไธญ'. +\ 'hello']) + call cursor(1,1) + norm! $ + redraw! + let expect=[ +\ 'ไธญaaaaaaaaaaaaaaaaa>', +\ 'ไธญaaaaaaaaaaaaaaaaa>', +\ 'ไธญaaaaaaaaaaaaaaaaa>', +\ 'ไธญaaaaaaaaaaaaaaaaa>', +\ 'ไธญaaaaaaaaaaaaaaaaa>', +\ 'ไธญaaaaaaaaaaaaaaaaa>', +\ 'ไธญaaaaaaaaaaaaaaaaa>', +\ 'ไธญaaaaaaaaaaaaaaaaa>', +\ 'ไธญaaaaaaaaaaaaaaaaa>', +\ 'ไธญhello '] + let lines = s:screen_lines([1, 10], winwidth(0)) + call s:compare_lines(expect, lines) + call s:close_windows() +endfu diff --git a/src/nvim/testdir/test_mapping.vim b/src/nvim/testdir/test_mapping.vim new file mode 100644 index 0000000000..7f93ddd56e --- /dev/null +++ b/src/nvim/testdir/test_mapping.vim @@ -0,0 +1,160 @@ +" Tests for mappings and abbreviations + +if !has('multi_byte') + finish +endif + +func Test_abbreviation() + " abbreviation with 0x80 should work + inoreab ัะบะฟั vim + call feedkeys("Goัะบะฟั \<Esc>", "xt") + call assert_equal('vim ', getline('$')) + iunab ัะบะฟั + set nomodified +endfunc + +func Test_map_ctrl_c_insert() + " mapping of ctrl-c in Insert mode + set cpo-=< cpo-=k + inoremap <c-c> <ctrl-c> + cnoremap <c-c> dummy + cunmap <c-c> + call feedkeys("GoTEST2: CTRL-C |\<C-C>A|\<Esc>", "xt") + call assert_equal('TEST2: CTRL-C |<ctrl-c>A|', getline('$')) + unmap! <c-c> + set nomodified +endfunc + +func Test_map_ctrl_c_visual() + " mapping of ctrl-c in Visual mode + vnoremap <c-c> :<C-u>$put ='vmap works' + call feedkeys("GV\<C-C>\<CR>", "xt") + call assert_equal('vmap works', getline('$')) + vunmap <c-c> + set nomodified +endfunc + +func Test_map_langmap() + if !has('langmap') + return + endif + + " check langmap applies in normal mode + set langmap=+- nolangremap + new + call setline(1, ['a', 'b', 'c']) + 2 + call assert_equal('b', getline('.')) + call feedkeys("+", "xt") + call assert_equal('a', getline('.')) + + " check no remapping + map x + + 2 + call feedkeys("x", "xt") + call assert_equal('c', getline('.')) + + " check with remapping + set langremap + 2 + call feedkeys("x", "xt") + call assert_equal('a', getline('.')) + + unmap x + bwipe! + + " 'langnoremap' follows 'langremap' and vise versa + set langremap + set langnoremap + call assert_equal(0, &langremap) + set langremap + call assert_equal(0, &langnoremap) + set nolangremap + call assert_equal(1, &langnoremap) + + " check default values + set langnoremap& + call assert_equal(1, &langnoremap) + call assert_equal(0, &langremap) + set langremap& + call assert_equal(1, &langnoremap) + call assert_equal(0, &langremap) + + " langmap should not apply in insert mode, 'langremap' doesn't matter + set langmap=+{ nolangremap + call feedkeys("Go+\<Esc>", "xt") + call assert_equal('+', getline('$')) + set langmap=+{ langremap + call feedkeys("Go+\<Esc>", "xt") + call assert_equal('+', getline('$')) + + " langmap used for register name in insert mode. + call setreg('a', 'aaaa') + call setreg('b', 'bbbb') + call setreg('c', 'cccc') + set langmap=ab langremap + call feedkeys("Go\<C-R>a\<Esc>", "xt") + call assert_equal('bbbb', getline('$')) + call feedkeys("Go\<C-R>\<C-R>a\<Esc>", "xt") + call assert_equal('bbbb', getline('$')) + " mapping does not apply + imap c a + call feedkeys("Go\<C-R>c\<Esc>", "xt") + call assert_equal('cccc', getline('$')) + imap a c + call feedkeys("Go\<C-R>a\<Esc>", "xt") + call assert_equal('bbbb', getline('$')) + + " langmap should not apply in Command-line mode + set langmap=+{ nolangremap + call feedkeys(":call append(line('$'), '+')\<CR>", "xt") + call assert_equal('+', getline('$')) + + set nomodified +endfunc + +func Test_map_feedkeys() + " issue #212 (feedkeys insert mapping at current position) + nnoremap . :call feedkeys(".", "in")<cr> + call setline('$', ['a b c d', 'a b c d']) + $-1 + call feedkeys("0qqdw.ifoo\<Esc>qj0@q\<Esc>", "xt") + call assert_equal(['fooc d', 'fooc d'], getline(line('$') - 1, line('$'))) + unmap . + set nomodified +endfunc + +func Test_map_cursor() + " <c-g>U<cursor> works only within a single line + imapclear + imap ( ()<c-g>U<left> + call feedkeys("G2o\<Esc>ki\<CR>Test1: text with a (here some more text\<Esc>k.", "xt") + call assert_equal('Test1: text with a (here some more text)', getline(line('$') - 2)) + call assert_equal('Test1: text with a (here some more text)', getline(line('$') - 1)) + + " test undo + call feedkeys("G2o\<Esc>ki\<CR>Test2: text wit a (here some more text [und undo]\<C-G>u\<Esc>k.u", "xt") + call assert_equal('', getline(line('$') - 2)) + call assert_equal('Test2: text wit a (here some more text [und undo])', getline(line('$') - 1)) + set nomodified + imapclear +endfunc + +" This isn't actually testing a mapping, but similar use of CTRL-G U as above. +func Test_break_undo() + :set whichwrap=<,>,[,] + call feedkeys("G4o2k", "xt") + exe ":norm! iTest3: text with a (parenthesis here\<C-G>U\<Right>new line here\<esc>\<up>\<up>." + call assert_equal('new line here', getline(line('$') - 3)) + call assert_equal('Test3: text with a (parenthesis here', getline(line('$') - 2)) + call assert_equal('new line here', getline(line('$') - 1)) + set nomodified +endfunc + +func Test_map_meta_quotes() + imap <M-"> foo + call feedkeys("Go-\<M-\">-\<Esc>", "xt") + call assert_equal("-foo-", getline('$')) + set nomodified + iunmap <M-"> +endfunc diff --git a/src/nvim/testdir/test_marks.vim b/src/nvim/testdir/test_marks.vim new file mode 100644 index 0000000000..d00b1ddc88 --- /dev/null +++ b/src/nvim/testdir/test_marks.vim @@ -0,0 +1,26 @@ + +" Test that a deleted mark is restored after delete-undo-redo-undo. +function! Test_Restore_DelMark() + enew! + call append(0, [" textline A", " textline B", " textline C"]) + normal! 2gg + set nocp viminfo+=nviminfo + exe "normal! i\<C-G>u\<Esc>" + exe "normal! maddu\<C-R>u" + let pos = getpos("'a") + call assert_equal(2, pos[1]) + call assert_equal(1, pos[2]) + enew! +endfunction + +" Test that CTRL-A and CTRL-X updates last changed mark '[, ']. +function! Test_Incr_Marks() + enew! + call append(0, ["123 123 123", "123 123 123", "123 123 123"]) + normal! gg + execute "normal! \<C-A>`[v`]rAjwvjw\<C-X>`[v`]rX" + call assert_equal("AAA 123 123", getline(1)) + call assert_equal("123 XXXXXXX", getline(2)) + call assert_equal("XXX 123 123", getline(3)) + enew! +endfunction diff --git a/src/nvim/testdir/test_match.vim b/src/nvim/testdir/test_match.vim index 7748dee87f..066bb2f6a1 100644 --- a/src/nvim/testdir/test_match.vim +++ b/src/nvim/testdir/test_match.vim @@ -198,6 +198,16 @@ func Test_matchaddpos() call assert_equal(screenattr(2,2), screenattr(1,10)) call assert_notequal(screenattr(2,2), screenattr(1,11)) + " Check overlapping pos + call clearmatches() + call setline(1, ['1234567890', 'NH']) + call matchaddpos('Error', [[1,1,5], [1,3,5], [2,2]]) + redraw! + call assert_notequal(screenattr(2,2), 0) + call assert_equal(screenattr(2,2), screenattr(1,5)) + call assert_equal(screenattr(2,2), screenattr(1,7)) + call assert_notequal(screenattr(2,2), screenattr(1,8)) + nohl call clearmatches() syntax off @@ -231,4 +241,4 @@ func Test_matchaddpos_using_negative_priority() set hlsearch& endfunc -" vim: et ts=2 sw=2 +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_matchadd_conceal.vim b/src/nvim/testdir/test_matchadd_conceal.vim index bc1c28d6e9..c11f1a84a9 100644 --- a/src/nvim/testdir/test_matchadd_conceal.vim +++ b/src/nvim/testdir/test_matchadd_conceal.vim @@ -260,3 +260,26 @@ function! Test_matchadd_repeat_conceal_with_syntax_off() quit! endfunction + +function! Test_matchadd_and_syn_conceal() + new + let cnt='Inductive bool : Type := | true : bool | false : bool.' + let expect = 'Inductive - : Type := | true : - | false : -.' + 0put =cnt + " set filetype and :syntax on to change screenattr() + set cole=1 cocu=nv + hi link CheckedByCoq WarningMsg + syntax on + syntax keyword coqKwd bool conceal cchar=- + redraw! + call assert_equal(expect, s:screenline(1)) + call assert_notequal(screenattr(1, 10) , screenattr(1, 11)) + call assert_notequal(screenattr(1, 11) , screenattr(1, 12)) + call assert_equal(screenattr(1, 11) , screenattr(1, 32)) + call matchadd('CheckedByCoq', '\%<2l\%>9c\%<16c') + redraw! + call assert_equal(expect, s:screenline(1)) + call assert_notequal(screenattr(1, 10) , screenattr(1, 11)) + call assert_notequal(screenattr(1, 11) , screenattr(1, 12)) + call assert_equal(screenattr(1, 11) , screenattr(1, 32)) +endfunction diff --git a/src/nvim/testdir/test_menu.vim b/src/nvim/testdir/test_menu.vim index be559467c8..af18760065 100644 --- a/src/nvim/testdir/test_menu.vim +++ b/src/nvim/testdir/test_menu.vim @@ -4,6 +4,6 @@ func Test_load_menu() try source $VIMRUNTIME/menu.vim catch - call assert_false(1, 'error while loading menus: ' . v:exception) + call assert_report('error while loading menus: ' . v:exception) endtry endfunc diff --git a/src/nvim/testdir/test_nested_function.vim b/src/nvim/testdir/test_nested_function.vim new file mode 100644 index 0000000000..afaaea6ceb --- /dev/null +++ b/src/nvim/testdir/test_nested_function.vim @@ -0,0 +1,63 @@ +"Tests for nested functions +" +func NestedFunc() + func! Func1() + let g:text .= 'Func1 ' + endfunc + call Func1() + func! s:func2() + let g:text .= 's:func2 ' + endfunc + call s:func2() + func! s:_func3() + let g:text .= 's:_func3 ' + endfunc + call s:_func3() + let fn = 'Func4' + func! {fn}() + let g:text .= 'Func4 ' + endfunc + call {fn}() + let fn = 'func5' + func! s:{fn}() + let g:text .= 's:func5' + endfunc + call s:{fn}() +endfunc + +func Test_nested_functions() + let g:text = '' + call NestedFunc() + call assert_equal('Func1 s:func2 s:_func3 Func4 s:func5', g:text) +endfunction + +func Test_nested_argument() + func g:X() + let g:Y = function('sort') + endfunc + let g:Y = function('sort') + echo g:Y([], g:X()) + delfunc g:X + unlet g:Y +endfunc + +func Recurse(count) + if a:count > 0 + call Recurse(a:count - 1) + endif +endfunc + +func Test_max_nesting() + let call_depth_here = 2 + let ex_depth_here = 5 + set mfd& + + call Recurse(99 - call_depth_here) + call assert_fails('call Recurse(' . (100 - call_depth_here) . ')', 'E132:') + + set mfd=210 + call Recurse(209 - ex_depth_here) + call assert_fails('call Recurse(' . (210 - ex_depth_here) . ')', 'E169:') + + set mfd& +endfunc diff --git a/src/nvim/testdir/test_normal.vim b/src/nvim/testdir/test_normal.vim new file mode 100644 index 0000000000..4747d5704d --- /dev/null +++ b/src/nvim/testdir/test_normal.vim @@ -0,0 +1,2337 @@ +" Test for various Normal mode commands + +func! Setup_NewWindow() + 10new + call setline(1, range(1,100)) +endfunc + +func! MyFormatExpr() + " Adds '->$' at lines having numbers followed by trailing whitespace + for ln in range(v:lnum, v:lnum+v:count-1) + let line = getline(ln) + if getline(ln) =~# '\d\s\+$' + call setline(ln, substitute(line, '\s\+$', '', '') . '->$') + endif + endfor +endfunc + +func! CountSpaces(type, ...) + " for testing operatorfunc + " will count the number of spaces + " and return the result in g:a + let sel_save = &selection + let &selection = "inclusive" + let reg_save = @@ + + if a:0 " Invoked from Visual mode, use gv command. + silent exe "normal! gvy" + elseif a:type == 'line' + silent exe "normal! '[V']y" + else + silent exe "normal! `[v`]y" + endif + let g:a=strlen(substitute(@@, '[^ ]', '', 'g')) + let &selection = sel_save + let @@ = reg_save +endfunc + +func! OpfuncDummy(type, ...) + " for testing operatorfunc + let g:opt=&linebreak + + if a:0 " Invoked from Visual mode, use gv command. + silent exe "normal! gvy" + elseif a:type == 'line' + silent exe "normal! '[V']y" + else + silent exe "normal! `[v`]y" + endif + " Create a new dummy window + new + let g:bufnr=bufnr('%') +endfunc + +fun! Test_normal00_optrans() + new + call append(0, ['1 This is a simple test: abcd', '2 This is the second line', '3 this is the third line']) + 1 + exe "norm! Sfoobar\<esc>" + call assert_equal(['foobar', '2 This is the second line', '3 this is the third line', ''], getline(1,'$')) + 2 + exe "norm! $vbsone" + call assert_equal(['foobar', '2 This is the second one', '3 this is the third line', ''], getline(1,'$')) + norm! VS Second line here + call assert_equal(['foobar', ' Second line here', '3 this is the third line', ''], getline(1, '$')) + %d + call append(0, ['4 This is a simple test: abcd', '5 This is the second line', '6 this is the third line']) + call append(0, ['1 This is a simple test: abcd', '2 This is the second line', '3 this is the third line']) + + 1 + norm! 2D + call assert_equal(['3 this is the third line', '4 This is a simple test: abcd', '5 This is the second line', '6 this is the third line', ''], getline(1,'$')) + " Nvim: no "#" flag in 'cpoptions'. + " set cpo+=# + " norm! 4D + " call assert_equal(['', '4 This is a simple test: abcd', '5 This is the second line', '6 this is the third line', ''], getline(1,'$')) + + " clean up + set cpo-=# + bw! +endfunc + +func! Test_normal01_keymodel() + throw "skipped: Nvim regression: 'keymodel'" + call Setup_NewWindow() + " Test 1: depending on 'keymodel' <s-down> does something different + 50 + call feedkeys("V\<S-Up>y", 'tx') + call assert_equal(['47', '48', '49', '50'], getline("'<", "'>")) + set keymodel=startsel + 50 + call feedkeys("V\<S-Up>y", 'tx') + call assert_equal(['49', '50'], getline("'<", "'>")) + " Start visual mode when keymodel = startsel + 50 + call feedkeys("\<S-Up>y", 'tx') + call assert_equal(['49', '5'], getreg(0, 0, 1)) + " Do not start visual mode when keymodel= + set keymodel= + 50 + call feedkeys("\<S-Up>y$", 'tx') + call assert_equal(['42'], getreg(0, 0, 1)) + " Stop visual mode when keymodel=stopsel + set keymodel=stopsel + 50 + call feedkeys("Vkk\<Up>yy", 'tx') + call assert_equal(['47'], getreg(0, 0, 1)) + + set keymodel= + 50 + call feedkeys("Vkk\<Up>yy", 'tx') + call assert_equal(['47', '48', '49', '50'], getreg(0, 0, 1)) + + " clean up + bw! +endfunc + +func! Test_normal02_selectmode() + " some basic select mode tests + call Setup_NewWindow() + 50 + norm! gHy + call assert_equal('y51', getline('.')) + call setline(1, range(1,100)) + 50 + exe ":norm! V9jo\<c-g>y" + call assert_equal('y60', getline('.')) + " clean up + bw! +endfunc + +func! Test_normal02_selectmode2() + " some basic select mode tests + call Setup_NewWindow() + 50 + call feedkeys(":set im\n\<c-o>gHc\<c-o>:set noim\n", 'tx') + call assert_equal('c51', getline('.')) + " clean up + bw! +endfunc + +func! Test_normal03_join() + " basic join test + call Setup_NewWindow() + 50 + norm! VJ + call assert_equal('50 51', getline('.')) + $ + norm! J + call assert_equal('100', getline('.')) + $ + norm! V9-gJ + call assert_equal('919293949596979899100', getline('.')) + call setline(1, range(1,100)) + $ + :j 10 + call assert_equal('100', getline('.')) + " clean up + bw! +endfunc + +func! Test_normal04_filter() + " basic filter test + " only test on non windows platform + if has('win32') + return + endif + call Setup_NewWindow() + 1 + call feedkeys("!!sed -e 's/^/| /'\n", 'tx') + call assert_equal('| 1', getline('.')) + 90 + :sil :!echo one + call feedkeys('.', 'tx') + call assert_equal('| 90', getline('.')) + 95 + set cpo+=! + " 2 <CR>, 1: for executing the command, + " 2: clear hit-enter-prompt + call feedkeys("!!\n", 'tx') + call feedkeys(":!echo one\n\n", 'tx') + call feedkeys(".", 'tx') + call assert_equal('one', getline('.')) + set cpo-=! + bw! +endfunc + +func! Test_normal05_formatexpr() + " basic formatexpr test + call Setup_NewWindow() + %d_ + call setline(1, ['here: 1 ', '2', 'here: 3 ', '4', 'not here: ']) + 1 + set formatexpr=MyFormatExpr() + norm! gqG + call assert_equal(['here: 1->$', '2', 'here: 3->$', '4', 'not here: '], getline(1,'$')) + set formatexpr= + bw! +endfunc + +func Test_normal05_formatexpr_newbuf() + " Edit another buffer in the 'formatexpr' function + new + func! Format() + edit another + endfunc + set formatexpr=Format() + norm gqG + bw! + set formatexpr= +endfunc + +func Test_normal05_formatexpr_setopt() + " Change the 'formatexpr' value in the function + new + func! Format() + set formatexpr= + endfunc + set formatexpr=Format() + norm gqG + bw! + set formatexpr= +endfunc + +func! Test_normal06_formatprg() + " basic test for formatprg + " only test on non windows platform + if has('win32') + return + endif + + " uses sed to number non-empty lines + call writefile(['#!/bin/sh', 'sed ''/./=''|sed ''/./{', 'N', 's/\n/ /', '}'''], 'Xsed_format.sh') + call system('chmod +x ./Xsed_format.sh') + let text = ['a', '', 'c', '', ' ', 'd', 'e'] + let expected = ['1 a', '', '3 c', '', '5 ', '6 d', '7 e'] + + 10new + call setline(1, text) + set formatprg=./Xsed_format.sh + norm! gggqG + call assert_equal(expected, getline(1, '$')) + bw! + + 10new + call setline(1, text) + set formatprg=donothing + setlocal formatprg=./Xsed_format.sh + norm! gggqG + call assert_equal(expected, getline(1, '$')) + bw! + + " clean up + set formatprg= + setlocal formatprg= + call delete('Xsed_format.sh') +endfunc + +func! Test_normal07_internalfmt() + " basic test for internal formmatter to textwidth of 12 + let list=range(1,11) + call map(list, 'v:val." "') + 10new + call setline(1, list) + set tw=12 + norm! gggqG + call assert_equal(['1 2 3', '4 5 6', '7 8 9', '10 11 '], getline(1, '$')) + " clean up + set tw=0 + bw! +endfunc + +func! Test_normal08_fold() + " basic tests for foldopen/folddelete + if !has("folding") + return + endif + call Setup_NewWindow() + 50 + setl foldenable fdm=marker + " First fold + norm! V4jzf + " check that folds have been created + call assert_equal(['50/*{{{*/', '51', '52', '53', '54/*}}}*/'], getline(50,54)) + " Second fold + 46 + norm! V10jzf + " check that folds have been created + call assert_equal('46/*{{{*/', getline(46)) + call assert_equal('60/*}}}*/', getline(60)) + norm! k + call assert_equal('45', getline('.')) + norm! j + call assert_equal('46/*{{{*/', getline('.')) + norm! j + call assert_equal('61', getline('.')) + norm! k + " open a fold + norm! Vzo + norm! k + call assert_equal('45', getline('.')) + norm! j + call assert_equal('46/*{{{*/', getline('.')) + norm! j + call assert_equal('47', getline('.')) + norm! k + norm! zcVzO + call assert_equal('46/*{{{*/', getline('.')) + norm! j + call assert_equal('47', getline('.')) + norm! j + call assert_equal('48', getline('.')) + norm! j + call assert_equal('49', getline('.')) + norm! j + call assert_equal('50/*{{{*/', getline('.')) + norm! j + call assert_equal('51', getline('.')) + " delete folds + :46 + " collapse fold + norm! V14jzC + " delete all folds recursively + norm! VzD + call assert_equal(['46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '60'], getline(46,60)) + + " clean up + setl nofoldenable fdm=marker + bw! +endfunc + +func! Test_normal09_operatorfunc() + " Test operatorfunc + call Setup_NewWindow() + " Add some spaces for counting + 50,60s/$/ / + unlet! g:a + let g:a=0 + nmap <buffer><silent> ,, :set opfunc=CountSpaces<CR>g@ + vmap <buffer><silent> ,, :<C-U>call CountSpaces(visualmode(), 1)<CR> + 50 + norm V2j,, + call assert_equal(6, g:a) + norm V,, + call assert_equal(2, g:a) + norm ,,l + call assert_equal(0, g:a) + 50 + exe "norm 0\<c-v>10j2l,," + call assert_equal(11, g:a) + 50 + norm V10j,, + call assert_equal(22, g:a) + + " clean up + unmap <buffer> ,, + set opfunc= + unlet! g:a + bw! +endfunc + +func! Test_normal09a_operatorfunc() + " Test operatorfunc + call Setup_NewWindow() + " Add some spaces for counting + 50,60s/$/ / + unlet! g:opt + set linebreak + nmap <buffer><silent> ,, :set opfunc=OpfuncDummy<CR>g@ + 50 + norm ,,j + exe "bd!" g:bufnr + call assert_true(&linebreak) + call assert_equal(g:opt, &linebreak) + set nolinebreak + norm ,,j + exe "bd!" g:bufnr + call assert_false(&linebreak) + call assert_equal(g:opt, &linebreak) + + " clean up + unmap <buffer> ,, + set opfunc= + bw! + unlet! g:opt +endfunc + +func! Test_normal10_expand() + " Test for expand() + 10new + call setline(1, ['1', 'ifooar,,cbar']) + 2 + norm! $ + let a=expand('<cword>') + let b=expand('<cWORD>') + call assert_equal('cbar', a) + call assert_equal('ifooar,,cbar', b) + " clean up + bw! +endfunc + +func! Test_normal11_showcmd() + " test for 'showcmd' + 10new + exe "norm! ofoobar\<esc>" + call assert_equal(2, line('$')) + set showcmd + exe "norm! ofoobar2\<esc>" + call assert_equal(3, line('$')) + exe "norm! VAfoobar3\<esc>" + call assert_equal(3, line('$')) + exe "norm! 0d3\<del>2l" + call assert_equal('obar2foobar3', getline('.')) + bw! +endfunc + +func! Test_normal12_nv_error() + " Test for nv_error + 10new + call setline(1, range(1,5)) + " should not do anything, just beep + exe "norm! <c-k>" + call assert_equal(map(range(1,5), 'string(v:val)'), getline(1,'$')) + bw! +endfunc + +func! Test_normal13_help() + " Test for F1 + call assert_equal(1, winnr()) + call feedkeys("\<f1>", 'txi') + call assert_match('help\.txt', bufname('%')) + call assert_equal(2, winnr('$')) + bw! +endfunc + +func! Test_normal14_page() + " basic test for Ctrl-F and Ctrl-B + call Setup_NewWindow() + exe "norm! \<c-f>" + call assert_equal('9', getline('.')) + exe "norm! 2\<c-f>" + call assert_equal('25', getline('.')) + exe "norm! 2\<c-b>" + call assert_equal('18', getline('.')) + 1 + set scrolloff=5 + exe "norm! 2\<c-f>" + call assert_equal('21', getline('.')) + exe "norm! \<c-b>" + call assert_equal('13', getline('.')) + 1 + set scrolloff=99 + exe "norm! \<c-f>" + call assert_equal('13', getline('.')) + set scrolloff=0 + 100 + exe "norm! $\<c-b>" + call assert_equal('92', getline('.')) + call assert_equal([0, 92, 1, 0, 1], getcurpos()) + 100 + set nostartofline + exe "norm! $\<c-b>" + call assert_equal('92', getline('.')) + call assert_equal([0, 92, 2, 0, 2147483647], getcurpos()) + " cleanup + set startofline + bw! +endfunc + +func! Test_normal14_page_eol() + 10new + norm oxxxxxxx + exe "norm 2\<c-f>" + " check with valgrind that cursor is put back in column 1 + exe "norm 2\<c-b>" + bw! +endfunc + +func! Test_normal15_z_scroll_vert() + " basic test for z commands that scroll the window + call Setup_NewWindow() + 100 + norm! >> + " Test for z<cr> + exe "norm! z\<cr>" + call assert_equal(' 100', getline('.')) + call assert_equal(100, winsaveview()['topline']) + call assert_equal([0, 100, 2, 0, 9], getcurpos()) + + " Test for zt + 21 + norm! >>0zt + call assert_equal(' 21', getline('.')) + call assert_equal(21, winsaveview()['topline']) + call assert_equal([0, 21, 1, 0, 8], getcurpos()) + + " Test for zb + 30 + norm! >>$ztzb + call assert_equal(' 30', getline('.')) + call assert_equal(30, winsaveview()['topline']+winheight(0)-1) + call assert_equal([0, 30, 3, 0, 2147483647], getcurpos()) + + " Test for z- + 1 + 30 + norm! 0z- + call assert_equal(' 30', getline('.')) + call assert_equal(30, winsaveview()['topline']+winheight(0)-1) + call assert_equal([0, 30, 2, 0, 9], getcurpos()) + + " Test for z{height}<cr> + call assert_equal(10, winheight(0)) + exe "norm! z12\<cr>" + call assert_equal(12, winheight(0)) + exe "norm! z10\<cr>" + call assert_equal(10, winheight(0)) + + " Test for z. + 1 + 21 + norm! 0z. + call assert_equal(' 21', getline('.')) + call assert_equal(17, winsaveview()['topline']) + call assert_equal([0, 21, 2, 0, 9], getcurpos()) + + " Test for zz + 1 + 21 + norm! 0zz + call assert_equal(' 21', getline('.')) + call assert_equal(17, winsaveview()['topline']) + call assert_equal([0, 21, 1, 0, 8], getcurpos()) + + " Test for z+ + 11 + norm! zt + norm! z+ + call assert_equal(' 21', getline('.')) + call assert_equal(21, winsaveview()['topline']) + call assert_equal([0, 21, 2, 0, 9], getcurpos()) + + " Test for [count]z+ + 1 + norm! 21z+ + call assert_equal(' 21', getline('.')) + call assert_equal(21, winsaveview()['topline']) + call assert_equal([0, 21, 2, 0, 9], getcurpos()) + + " Test for z^ + norm! 22z+0 + norm! z^ + call assert_equal(' 21', getline('.')) + call assert_equal(12, winsaveview()['topline']) + call assert_equal([0, 21, 2, 0, 9], getcurpos()) + + " Test for [count]z^ + 1 + norm! 30z^ + call assert_equal(' 21', getline('.')) + call assert_equal(12, winsaveview()['topline']) + call assert_equal([0, 21, 2, 0, 9], getcurpos()) + + " cleanup + bw! +endfunc + +func! Test_normal16_z_scroll_hor() + " basic test for z commands that scroll the window + 10new + 15vsp + set nowrap listchars= + let lineA='abcdefghijklmnopqrstuvwxyz' + let lineB='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' + $put =lineA + $put =lineB + 1d + + " Test for zl + 1 + norm! 5zl + call assert_equal(lineA, getline('.')) + call assert_equal(6, col('.')) + call assert_equal(5, winsaveview()['leftcol']) + norm! yl + call assert_equal('f', @0) + + " Test for zh + norm! 2zh + call assert_equal(lineA, getline('.')) + call assert_equal(6, col('.')) + norm! yl + call assert_equal('f', @0) + call assert_equal(3, winsaveview()['leftcol']) + + " Test for zL + norm! zL + call assert_equal(11, col('.')) + norm! yl + call assert_equal('k', @0) + call assert_equal(10, winsaveview()['leftcol']) + norm! 2zL + call assert_equal(25, col('.')) + norm! yl + call assert_equal('y', @0) + call assert_equal(24, winsaveview()['leftcol']) + + " Test for zH + norm! 2zH + call assert_equal(25, col('.')) + call assert_equal(10, winsaveview()['leftcol']) + norm! yl + call assert_equal('y', @0) + + " Test for zs + norm! $zs + call assert_equal(26, col('.')) + call assert_equal(25, winsaveview()['leftcol']) + norm! yl + call assert_equal('z', @0) + + " Test for ze + norm! ze + call assert_equal(26, col('.')) + call assert_equal(11, winsaveview()['leftcol']) + norm! yl + call assert_equal('z', @0) + + " cleanup + set wrap listchars=eol:$ + bw! +endfunc + +func! Test_normal17_z_scroll_hor2() + " basic test for z commands that scroll the window + " using 'sidescrolloff' setting + 10new + 20vsp + set nowrap listchars= sidescrolloff=5 + let lineA='abcdefghijklmnopqrstuvwxyz' + let lineB='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' + $put =lineA + $put =lineB + 1d + + " Test for zl + 1 + norm! 5zl + call assert_equal(lineA, getline('.')) + call assert_equal(11, col('.')) + call assert_equal(5, winsaveview()['leftcol']) + norm! yl + call assert_equal('k', @0) + + " Test for zh + norm! 2zh + call assert_equal(lineA, getline('.')) + call assert_equal(11, col('.')) + norm! yl + call assert_equal('k', @0) + call assert_equal(3, winsaveview()['leftcol']) + + " Test for zL + norm! 0zL + call assert_equal(16, col('.')) + norm! yl + call assert_equal('p', @0) + call assert_equal(10, winsaveview()['leftcol']) + norm! 2zL + call assert_equal(26, col('.')) + norm! yl + call assert_equal('z', @0) + call assert_equal(15, winsaveview()['leftcol']) + + " Test for zH + norm! 2zH + call assert_equal(15, col('.')) + call assert_equal(0, winsaveview()['leftcol']) + norm! yl + call assert_equal('o', @0) + + " Test for zs + norm! $zs + call assert_equal(26, col('.')) + call assert_equal(20, winsaveview()['leftcol']) + norm! yl + call assert_equal('z', @0) + + " Test for ze + norm! ze + call assert_equal(26, col('.')) + call assert_equal(11, winsaveview()['leftcol']) + norm! yl + call assert_equal('z', @0) + + " cleanup + set wrap listchars=eol:$ sidescrolloff=0 + bw! +endfunc + +func! Test_normal18_z_fold() + " basic tests for foldopen/folddelete + if !has("folding") + return + endif + call Setup_NewWindow() + 50 + setl foldenable fdm=marker foldlevel=5 + + " Test for zF + " First fold + norm! 4zF + " check that folds have been created + call assert_equal(['50/*{{{*/', '51', '52', '53/*}}}*/'], getline(50,53)) + + " Test for zd + 51 + norm! 2zF + call assert_equal(2, foldlevel('.')) + norm! kzd + call assert_equal(['50', '51/*{{{*/', '52/*}}}*/', '53'], getline(50,53)) + norm! j + call assert_equal(1, foldlevel('.')) + + " Test for zD + " also deletes partially selected folds recursively + 51 + norm! zF + call assert_equal(2, foldlevel('.')) + norm! kV2jzD + call assert_equal(['50', '51', '52', '53'], getline(50,53)) + + " Test for zE + 85 + norm! 4zF + 86 + norm! 2zF + 90 + norm! 4zF + call assert_equal(['85/*{{{*/', '86/*{{{*/', '87/*}}}*/', '88/*}}}*/', '89', '90/*{{{*/', '91', '92', '93/*}}}*/'], getline(85,93)) + norm! zE + call assert_equal(['85', '86', '87', '88', '89', '90', '91', '92', '93'], getline(85,93)) + + " Test for zn + 50 + set foldlevel=0 + norm! 2zF + norm! zn + norm! k + call assert_equal('49', getline('.')) + norm! j + call assert_equal('50/*{{{*/', getline('.')) + norm! j + call assert_equal('51/*}}}*/', getline('.')) + norm! j + call assert_equal('52', getline('.')) + call assert_equal(0, &foldenable) + + " Test for zN + 49 + norm! zN + call assert_equal('49', getline('.')) + norm! j + call assert_equal('50/*{{{*/', getline('.')) + norm! j + call assert_equal('52', getline('.')) + call assert_equal(1, &foldenable) + + " Test for zi + norm! zi + call assert_equal(0, &foldenable) + norm! zi + call assert_equal(1, &foldenable) + norm! zi + call assert_equal(0, &foldenable) + norm! zi + call assert_equal(1, &foldenable) + + " Test for za + 50 + norm! za + norm! k + call assert_equal('49', getline('.')) + norm! j + call assert_equal('50/*{{{*/', getline('.')) + norm! j + call assert_equal('51/*}}}*/', getline('.')) + norm! j + call assert_equal('52', getline('.')) + 50 + norm! za + norm! k + call assert_equal('49', getline('.')) + norm! j + call assert_equal('50/*{{{*/', getline('.')) + norm! j + call assert_equal('52', getline('.')) + + 49 + norm! 5zF + norm! k + call assert_equal('48', getline('.')) + norm! j + call assert_equal('49/*{{{*/', getline('.')) + norm! j + call assert_equal('55', getline('.')) + 49 + norm! za + call assert_equal('49/*{{{*/', getline('.')) + norm! j + call assert_equal('50/*{{{*/', getline('.')) + norm! j + call assert_equal('52', getline('.')) + set nofoldenable + " close fold and set foldenable + norm! za + call assert_equal(1, &foldenable) + + 50 + " have to use {count}za to open all folds and make the cursor visible + norm! 2za + norm! 2k + call assert_equal('48', getline('.')) + norm! j + call assert_equal('49/*{{{*/', getline('.')) + norm! j + call assert_equal('50/*{{{*/', getline('.')) + norm! j + call assert_equal('51/*}}}*/', getline('.')) + norm! j + call assert_equal('52', getline('.')) + + " Test for zA + 49 + set foldlevel=0 + 50 + norm! zA + norm! 2k + call assert_equal('48', getline('.')) + norm! j + call assert_equal('49/*{{{*/', getline('.')) + norm! j + call assert_equal('50/*{{{*/', getline('.')) + norm! j + call assert_equal('51/*}}}*/', getline('.')) + norm! j + call assert_equal('52', getline('.')) + + " zA on a opened fold when foldenale is not set + 50 + set nofoldenable + norm! zA + call assert_equal(1, &foldenable) + norm! k + call assert_equal('48', getline('.')) + norm! j + call assert_equal('49/*{{{*/', getline('.')) + norm! j + call assert_equal('55', getline('.')) + + " Test for zc + norm! zE + 50 + norm! 2zF + 49 + norm! 5zF + set nofoldenable + 50 + " There most likely is a bug somewhere: + " https://groups.google.com/d/msg/vim_dev/v2EkfJ_KQjI/u-Cvv94uCAAJ + " TODO: Should this only close the inner most fold or both folds? + norm! zc + call assert_equal(1, &foldenable) + norm! k + call assert_equal('48', getline('.')) + norm! j + call assert_equal('49/*{{{*/', getline('.')) + norm! j + call assert_equal('55', getline('.')) + set nofoldenable + 50 + norm! Vjzc + norm! k + call assert_equal('48', getline('.')) + norm! j + call assert_equal('49/*{{{*/', getline('.')) + norm! j + call assert_equal('55', getline('.')) + + " Test for zC + set nofoldenable + 50 + norm! zCk + call assert_equal('48', getline('.')) + norm! j + call assert_equal('49/*{{{*/', getline('.')) + norm! j + call assert_equal('55', getline('.')) + + " Test for zx + " 1) close folds at line 49-54 + set nofoldenable + 48 + norm! zx + call assert_equal(1, &foldenable) + norm! j + call assert_equal('49/*{{{*/', getline('.')) + norm! j + call assert_equal('55', getline('.')) + + " 2) do not close fold under curser + 51 + set nofoldenable + norm! zx + call assert_equal(1, &foldenable) + norm! 3k + call assert_equal('48', getline('.')) + norm! j + call assert_equal('49/*{{{*/', getline('.')) + norm! j + call assert_equal('50/*{{{*/', getline('.')) + norm! j + call assert_equal('51/*}}}*/', getline('.')) + norm! j + call assert_equal('52', getline('.')) + norm! j + call assert_equal('53', getline('.')) + norm! j + call assert_equal('54/*}}}*/', getline('.')) + norm! j + call assert_equal('55', getline('.')) + + " 3) close one level of folds + 48 + set nofoldenable + set foldlevel=1 + norm! zx + call assert_equal(1, &foldenable) + call assert_equal('48', getline('.')) + norm! j + call assert_equal('49/*{{{*/', getline('.')) + norm! j + call assert_equal('50/*{{{*/', getline('.')) + norm! j + call assert_equal('52', getline('.')) + norm! j + call assert_equal('53', getline('.')) + norm! j + call assert_equal('54/*}}}*/', getline('.')) + norm! j + call assert_equal('55', getline('.')) + + " Test for zX + " Close all folds + set foldlevel=0 nofoldenable + 50 + norm! zX + call assert_equal(1, &foldenable) + norm! k + call assert_equal('48', getline('.')) + norm! j + call assert_equal('49/*{{{*/', getline('.')) + norm! j + call assert_equal('55', getline('.')) + + " Test for zm + 50 + set nofoldenable foldlevel=2 + norm! zm + call assert_equal(1, &foldenable) + call assert_equal(1, &foldlevel) + norm! zm + call assert_equal(0, &foldlevel) + norm! zm + call assert_equal(0, &foldlevel) + norm! k + call assert_equal('48', getline('.')) + norm! j + call assert_equal('49/*{{{*/', getline('.')) + norm! j + call assert_equal('55', getline('.')) + + " Test for zM + 48 + set nofoldenable foldlevel=99 + norm! zM + call assert_equal(1, &foldenable) + call assert_equal(0, &foldlevel) + call assert_equal('48', getline('.')) + norm! j + call assert_equal('49/*{{{*/', getline('.')) + norm! j + call assert_equal('55', getline('.')) + + " Test for zr + 48 + set nofoldenable foldlevel=0 + norm! zr + call assert_equal(0, &foldenable) + call assert_equal(1, &foldlevel) + set foldlevel=0 foldenable + norm! zr + call assert_equal(1, &foldenable) + call assert_equal(1, &foldlevel) + norm! zr + call assert_equal(2, &foldlevel) + call assert_equal('48', getline('.')) + norm! j + call assert_equal('49/*{{{*/', getline('.')) + norm! j + call assert_equal('50/*{{{*/', getline('.')) + norm! j + call assert_equal('51/*}}}*/', getline('.')) + norm! j + call assert_equal('52', getline('.')) + + " Test for zR + 48 + set nofoldenable foldlevel=0 + norm! zR + call assert_equal(0, &foldenable) + call assert_equal(2, &foldlevel) + set foldenable foldlevel=0 + norm! zR + call assert_equal(1, &foldenable) + call assert_equal(2, &foldlevel) + call assert_equal('48', getline('.')) + norm! j + call assert_equal('49/*{{{*/', getline('.')) + norm! j + call assert_equal('50/*{{{*/', getline('.')) + norm! j + call assert_equal('51/*}}}*/', getline('.')) + norm! j + call assert_equal('52', getline('.')) + call append(50, ['a /*{{{*/', 'b /*}}}*/']) + 48 + call assert_equal('48', getline('.')) + norm! j + call assert_equal('49/*{{{*/', getline('.')) + norm! j + call assert_equal('50/*{{{*/', getline('.')) + norm! j + call assert_equal('a /*{{{*/', getline('.')) + norm! j + call assert_equal('51/*}}}*/', getline('.')) + norm! j + call assert_equal('52', getline('.')) + 48 + norm! zR + call assert_equal(1, &foldenable) + call assert_equal(3, &foldlevel) + call assert_equal('48', getline('.')) + norm! j + call assert_equal('49/*{{{*/', getline('.')) + norm! j + call assert_equal('50/*{{{*/', getline('.')) + norm! j + call assert_equal('a /*{{{*/', getline('.')) + norm! j + call assert_equal('b /*}}}*/', getline('.')) + norm! j + call assert_equal('51/*}}}*/', getline('.')) + norm! j + call assert_equal('52', getline('.')) + + " clean up + setl nofoldenable fdm=marker foldlevel=0 + bw! +endfunc + +func! Test_normal19_z_spell() + throw "skipped: Nvim 'spell' requires download" + if !has("spell") || !has('syntax') + return + endif + new + call append(0, ['1 good', '2 goood', '3 goood']) + set spell spellfile=./Xspellfile.add spelllang=en + let oldlang=v:lang + lang C + + " Test for zg + 1 + norm! ]s + call assert_equal('2 goood', getline('.')) + norm! zg + 1 + let a=execute('unsilent :norm! ]s') + call assert_equal('1 good', getline('.')) + call assert_equal('search hit BOTTOM, continuing at TOP', a[1:]) + let cnt=readfile('./Xspellfile.add') + call assert_equal('goood', cnt[0]) + + " Test for zw + 2 + norm! $zw + 1 + norm! ]s + call assert_equal('2 goood', getline('.')) + let cnt=readfile('./Xspellfile.add') + call assert_equal('#oood', cnt[0]) + call assert_equal('goood/!', cnt[1]) + + " Test for zg in visual mode + let a=execute('unsilent :norm! V$zg') + call assert_equal("Word '2 goood' added to ./Xspellfile.add", a[1:]) + 1 + norm! ]s + call assert_equal('3 goood', getline('.')) + let cnt=readfile('./Xspellfile.add') + call assert_equal('2 goood', cnt[2]) + " Remove "2 good" from spellfile + 2 + let a=execute('unsilent norm! V$zw') + call assert_equal("Word '2 goood' added to ./Xspellfile.add", a[1:]) + let cnt=readfile('./Xspellfile.add') + call assert_equal('2 goood/!', cnt[3]) + + " Test for zG + let a=execute('unsilent norm! V$zG') + call assert_match("Word '2 goood' added to .*", a) + let fname=matchstr(a, 'to\s\+\zs\f\+$') + let cnt=readfile(fname) + call assert_equal('2 goood', cnt[0]) + + " Test for zW + let a=execute('unsilent norm! V$zW') + call assert_match("Word '2 goood' added to .*", a) + let cnt=readfile(fname) + call assert_equal('# goood', cnt[0]) + call assert_equal('2 goood/!', cnt[1]) + + " Test for zuW + let a=execute('unsilent norm! V$zuW') + call assert_match("Word '2 goood' removed from .*", a) + let cnt=readfile(fname) + call assert_equal('# goood', cnt[0]) + call assert_equal('# goood/!', cnt[1]) + + " Test for zuG + let a=execute('unsilent norm! $zG') + call assert_match("Word 'goood' added to .*", a) + let cnt=readfile(fname) + call assert_equal('# goood', cnt[0]) + call assert_equal('# goood/!', cnt[1]) + call assert_equal('goood', cnt[2]) + let a=execute('unsilent norm! $zuG') + let cnt=readfile(fname) + call assert_match("Word 'goood' removed from .*", a) + call assert_equal('# goood', cnt[0]) + call assert_equal('# goood/!', cnt[1]) + call assert_equal('#oood', cnt[2]) + " word not found in wordlist + let a=execute('unsilent norm! V$zuG') + let cnt=readfile(fname) + call assert_match("", a) + call assert_equal('# goood', cnt[0]) + call assert_equal('# goood/!', cnt[1]) + call assert_equal('#oood', cnt[2]) + + " Test for zug + call delete('./Xspellfile.add') + 2 + let a=execute('unsilent norm! $zg') + let cnt=readfile('./Xspellfile.add') + call assert_equal('goood', cnt[0]) + let a=execute('unsilent norm! $zug') + call assert_match("Word 'goood' removed from \./Xspellfile.add", a) + let cnt=readfile('./Xspellfile.add') + call assert_equal('#oood', cnt[0]) + " word not in wordlist + let a=execute('unsilent norm! V$zug') + call assert_match('', a) + let cnt=readfile('./Xspellfile.add') + call assert_equal('#oood', cnt[0]) + + " Test for zuw + call delete('./Xspellfile.add') + 2 + let a=execute('unsilent norm! Vzw') + let cnt=readfile('./Xspellfile.add') + call assert_equal('2 goood/!', cnt[0]) + let a=execute('unsilent norm! Vzuw') + call assert_match("Word '2 goood' removed from \./Xspellfile.add", a) + let cnt=readfile('./Xspellfile.add') + call assert_equal('# goood/!', cnt[0]) + " word not in wordlist + let a=execute('unsilent norm! $zug') + call assert_match('', a) + let cnt=readfile('./Xspellfile.add') + call assert_equal('# goood/!', cnt[0]) + + " add second entry to spellfile setting + set spellfile=./Xspellfile.add,./Xspellfile2.add + call delete('./Xspellfile.add') + 2 + let a=execute('unsilent norm! $2zg') + let cnt=readfile('./Xspellfile2.add') + call assert_match("Word 'goood' added to ./Xspellfile2.add", a) + call assert_equal('goood', cnt[0]) + + " clean up + exe "lang" oldlang + call delete("./Xspellfile.add") + call delete("./Xspellfile2.add") + call delete("./Xspellfile.add.spl") + call delete("./Xspellfile2.add.spl") + + " zux -> no-op + 2 + norm! $zux + call assert_equal([], glob('Xspellfile.add',0,1)) + call assert_equal([], glob('Xspellfile2.add',0,1)) + + set spellfile= + bw! +endfunc + +func! Test_normal20_exmode() + if !has("unix") + " Reading from redirected file doesn't work on MS-Windows + return + endif + call writefile(['1a', 'foo', 'bar', '.', 'w! Xfile2', 'q!'], 'Xscript') + call writefile(['1', '2'], 'Xfile') + call system(v:progpath .' -e -s < Xscript Xfile') + let a=readfile('Xfile2') + call assert_equal(['1', 'foo', 'bar', '2'], a) + + " clean up + for file in ['Xfile', 'Xfile2', 'Xscript'] + call delete(file) + endfor + bw! +endfunc + +func! Test_normal21_nv_hat() + set hidden + new + " to many buffers opened already, will not work + "call assert_fails(":b#", 'E23') + "call assert_equal('', @#) + e Xfoobar + e Xfile2 + call feedkeys("\<c-^>", 't') + call assert_equal("Xfile2", fnamemodify(bufname('%'), ':t')) + call feedkeys("f\<c-^>", 't') + call assert_equal("Xfile2", fnamemodify(bufname('%'), ':t')) + " clean up + set nohidden + bw! +endfunc + +func! Test_normal22_zet() + " Test for ZZ + " let shell = &shell + " let &shell = 'sh' + + " Remove any stale test files from previous run. + for file in ['Xfile_Test_normal22_zet'] + call delete(file) + endfor + + call writefile(['1', '2'], 'Xfile_Test_normal22_zet') + let args = ' --headless -u NONE -N -U NONE -i NONE --noplugins' + call system(v:progpath . args . ' -c "%d" -c ":norm! ZZ" Xfile_Test_normal22_zet') + let a = readfile('Xfile_Test_normal22_zet') + call assert_equal([], a) + " Test for ZQ + call writefile(['1', '2'], 'Xfile_Test_normal22_zet') + call system(v:progpath . args . ' -c "%d" -c ":norm! ZQ" Xfile_Test_normal22_zet') + let a = readfile('Xfile_Test_normal22_zet') + call assert_equal(['1', '2'], a) + + " Nvim: This sometimes hangs the TSAN build. + " for file in ['Xfile_Test_normal22_zet'] + " call delete(file) + " endfor + " let &shell = shell +endfunc + +func! Test_normal23_K() + " Test for K command + new + call append(0, ['helphelp.txt', 'man', 'aa%bb', 'cc|dd']) + let k = &keywordprg + set keywordprg=:help + 1 + norm! VK + call assert_equal('helphelp.txt', fnamemodify(bufname('%'), ':t')) + call assert_equal('help', &ft) + call assert_match('\*helphelp.txt\*', getline('.')) + helpclose + norm! 0K + call assert_equal('helphelp.txt', fnamemodify(bufname('%'), ':t')) + call assert_equal('help', &ft) + call assert_match('Help on help files', getline('.')) + helpclose + + set keywordprg=:new + set iskeyword+=% + set iskeyword+=\| + 2 + norm! K + call assert_equal('man', fnamemodify(bufname('%'), ':t')) + bwipe! + 3 + norm! K + call assert_equal('aa%bb', fnamemodify(bufname('%'), ':t')) + bwipe! + if !has('win32') + 4 + norm! K + call assert_equal('cc|dd', fnamemodify(bufname('%'), ':t')) + bwipe! + endif + set iskeyword-=% + set iskeyword-=\| + + " Only expect "man" to work on Unix + if !has("unix") + let &keywordprg = k + bw! + return + endif + set keywordprg=man\ --pager=cat + " Test for using man + 2 + let a = execute('unsilent norm! K') + call assert_match("man --pager=cat 'man'", a) + + " clean up + let &keywordprg = k + bw! +endfunc + +func! Test_normal24_rot13() + " This test uses multi byte characters + if !has("multi_byte") + return + endif + " Testing for g?? g?g? + new + call append(0, 'abcdefghijklmnopqrstuvwxyzรครผรถ') + 1 + norm! g?? + call assert_equal('nopqrstuvwxyzabcdefghijklmรครผรถ', getline('.')) + norm! g?g? + call assert_equal('abcdefghijklmnopqrstuvwxyzรครผรถ', getline('.')) + + " clean up + bw! +endfunc + +func! Test_normal25_tag() + " Testing for CTRL-] g CTRL-] g] + " CTRL-W g] CTRL-W CTRL-] CTRL-W g CTRL-] + h + " Test for CTRL-] + call search('\<x\>$') + exe "norm! \<c-]>" + call assert_equal("change.txt", fnamemodify(bufname('%'), ':t')) + norm! yiW + call assert_equal("*x*", @0) + exe ":norm \<c-o>" + + " Test for g_CTRL-] + call search('\<v_u\>$') + exe "norm! g\<c-]>" + call assert_equal("change.txt", fnamemodify(bufname('%'), ':t')) + norm! yiW + call assert_equal("*v_u*", @0) + exe ":norm \<c-o>" + + " Test for g] + call search('\<i_<Esc>$') + let a = execute(":norm! g]") + call assert_match('i_<Esc>.*insert.txt', a) + + if !empty(exepath('cscope')) && has('cscope') + " setting cscopetag changes how g] works + set cst + exe "norm! g]" + call assert_equal("insert.txt", fnamemodify(bufname('%'), ':t')) + norm! yiW + call assert_equal("*i_<Esc>*", @0) + exe ":norm \<c-o>" + " Test for CTRL-W g] + exe "norm! \<C-W>g]" + call assert_equal("insert.txt", fnamemodify(bufname('%'), ':t')) + norm! yiW + call assert_equal("*i_<Esc>*", @0) + call assert_equal(3, winnr('$')) + helpclose + set nocst + endif + + " Test for CTRL-W g] + let a = execute("norm! \<C-W>g]") + call assert_match('i_<Esc>.*insert.txt', a) + + " Test for CTRL-W CTRL-] + exe "norm! \<C-W>\<C-]>" + call assert_equal("insert.txt", fnamemodify(bufname('%'), ':t')) + norm! yiW + call assert_equal("*i_<Esc>*", @0) + call assert_equal(3, winnr('$')) + helpclose + + " Test for CTRL-W g CTRL-] + exe "norm! \<C-W>g\<C-]>" + call assert_equal("insert.txt", fnamemodify(bufname('%'), ':t')) + norm! yiW + call assert_equal("*i_<Esc>*", @0) + call assert_equal(3, winnr('$')) + helpclose + + " clean up + helpclose +endfunc + +func! Test_normal26_put() + " Test for ]p ]P [p and [P + new + call append(0, ['while read LINE', 'do', ' ((count++))', ' if [ $? -ne 0 ]; then', " echo 'Error writing file'", ' fi', 'done']) + 1 + /Error/y a + 2 + norm! "a]pj"a[p + call assert_equal(['do', "echo 'Error writing file'", " echo 'Error writing file'", ' ((count++))'], getline(2,5)) + 1 + /^\s\{4}/ + exe "norm! \"a]P3Eldt'" + exe "norm! j\"a[P2Eldt'" + call assert_equal([' if [ $? -ne 0 ]; then', " echo 'Error writing'", " echo 'Error'", " echo 'Error writing file'", ' fi'], getline(6,10)) + + " clean up + bw! +endfunc + +func! Test_normal27_bracket() + " Test for [' [` ]' ]` + call Setup_NewWindow() + 1,21s/.\+/ & b/ + 1 + norm! $ma + 5 + norm! $mb + 10 + norm! $mc + 15 + norm! $md + 20 + norm! $me + + " Test for [' + 9 + norm! 2[' + call assert_equal(' 1 b', getline('.')) + call assert_equal(1, line('.')) + call assert_equal(3, col('.')) + + " Test for ]' + norm! ]' + call assert_equal(' 5 b', getline('.')) + call assert_equal(5, line('.')) + call assert_equal(3, col('.')) + + " No mark after line 21, cursor moves to first non blank on current line + 21 + norm! $]' + call assert_equal(' 21 b', getline('.')) + call assert_equal(21, line('.')) + call assert_equal(3, col('.')) + + " Test for [` + norm! 2[` + call assert_equal(' 15 b', getline('.')) + call assert_equal(15, line('.')) + call assert_equal(8, col('.')) + + " Test for ]` + norm! ]` + call assert_equal(' 20 b', getline('.')) + call assert_equal(20, line('.')) + call assert_equal(8, col('.')) + + " clean up + bw! +endfunc + +func! Test_normal28_parenthesis() + " basic testing for ( and ) + new + call append(0, ['This is a test. With some sentences!', '', 'Even with a question? And one more. And no sentence here']) + + $ + norm! d( + call assert_equal(['This is a test. With some sentences!', '', 'Even with a question? And one more. ', ''], getline(1, '$')) + norm! 2d( + call assert_equal(['This is a test. With some sentences!', '', ' ', ''], getline(1, '$')) + 1 + norm! 0d) + call assert_equal(['With some sentences!', '', ' ', ''], getline(1, '$')) + + call append('$', ['This is a long sentence', '', 'spanning', 'over several lines. ']) + $ + norm! $d( + call assert_equal(['With some sentences!', '', ' ', '', 'This is a long sentence', ''], getline(1, '$')) + + " clean up + bw! +endfunc + +fun! Test_normal29_brace() + " basic test for { and } movements + let text= ['A paragraph begins after each empty line, and also at each of a set of', + \ 'paragraph macros, specified by the pairs of characters in the ''paragraphs''', + \ 'option. The default is "IPLPPPQPP TPHPLIPpLpItpplpipbp", which corresponds to', + \ 'the macros ".IP", ".LP", etc. (These are nroff macros, so the dot must be in', + \ 'the first column). A section boundary is also a paragraph boundary.', + \ 'Note that a blank line (only containing white space) is NOT a paragraph', + \ 'boundary.', + \ '', + \ '', + \ 'Also note that this does not include a ''{'' or ''}'' in the first column. When', + \ 'the ''{'' flag is in ''cpoptions'' then ''{'' in the first column is used as a', + \ 'paragraph boundary |posix|.', + \ '{', + \ 'This is no paragaraph', + \ 'unless the ''{'' is set', + \ 'in ''cpoptions''', + \ '}', + \ '.IP', + \ 'The nroff macros IP seperates a paragraph', + \ 'That means, it must be a ''.''', + \ 'followed by IP', + \ '.LPIt does not matter, if afterwards some', + \ 'more characters follow.', + \ '.SHAlso section boundaries from the nroff', + \ 'macros terminate a paragraph. That means', + \ 'a character like this:', + \ '.NH', + \ 'End of text here'] + new + call append(0, text) + 1 + norm! 0d2} + call assert_equal(['.IP', + \ 'The nroff macros IP seperates a paragraph', 'That means, it must be a ''.''', 'followed by IP', + \ '.LPIt does not matter, if afterwards some', 'more characters follow.', '.SHAlso section boundaries from the nroff', + \ 'macros terminate a paragraph. That means', 'a character like this:', '.NH', 'End of text here', ''], getline(1,'$')) + norm! 0d} + call assert_equal(['.LPIt does not matter, if afterwards some', 'more characters follow.', + \ '.SHAlso section boundaries from the nroff', 'macros terminate a paragraph. That means', + \ 'a character like this:', '.NH', 'End of text here', ''], getline(1, '$')) + $ + norm! d{ + call assert_equal(['.LPIt does not matter, if afterwards some', 'more characters follow.', + \ '.SHAlso section boundaries from the nroff', 'macros terminate a paragraph. That means', 'a character like this:', ''], getline(1, '$')) + norm! d{ + call assert_equal(['.LPIt does not matter, if afterwards some', 'more characters follow.', ''], getline(1,'$')) + " Test with { in cpooptions + %d + call append(0, text) + " Nvim: no "{" flag in 'cpoptions'. + " set cpo+={ + " 1 + " norm! 0d2} + " call assert_equal(['{', 'This is no paragaraph', 'unless the ''{'' is set', 'in ''cpoptions''', '}', + " \ '.IP', 'The nroff macros IP seperates a paragraph', 'That means, it must be a ''.''', + " \ 'followed by IP', '.LPIt does not matter, if afterwards some', 'more characters follow.', + " \ '.SHAlso section boundaries from the nroff', 'macros terminate a paragraph. That means', + " \ 'a character like this:', '.NH', 'End of text here', ''], getline(1,'$')) + " $ + " norm! d} + " call assert_equal(['{', 'This is no paragaraph', 'unless the ''{'' is set', 'in ''cpoptions''', '}', + " \ '.IP', 'The nroff macros IP seperates a paragraph', 'That means, it must be a ''.''', + " \ 'followed by IP', '.LPIt does not matter, if afterwards some', 'more characters follow.', + " \ '.SHAlso section boundaries from the nroff', 'macros terminate a paragraph. That means', + " \ 'a character like this:', '.NH', 'End of text here', ''], getline(1,'$')) + " norm! gg} + " norm! d5} + " call assert_equal(['{', 'This is no paragaraph', 'unless the ''{'' is set', 'in ''cpoptions''', '}', ''], getline(1,'$')) + + " clean up + set cpo-={ + bw! +endfunc + +fun! Test_normal30_changecase() + " This test uses multi byte characters + if !has("multi_byte") + return + endif + new + call append(0, 'This is a simple test: รครผรถร') + norm! 1ggVu + call assert_equal('this is a simple test: รครผรถร', getline('.')) + norm! VU + call assert_equal('THIS IS A SIMPLE TEST: รรรSS', getline('.')) + norm! guu + call assert_equal('this is a simple test: รครผรถss', getline('.')) + norm! gUgU + call assert_equal('THIS IS A SIMPLE TEST: รรรSS', getline('.')) + norm! gugu + call assert_equal('this is a simple test: รครผรถss', getline('.')) + norm! gUU + call assert_equal('THIS IS A SIMPLE TEST: รรรSS', getline('.')) + norm! 010~ + call assert_equal('this is a SIMPLE TEST: รรรSS', getline('.')) + norm! V~ + call assert_equal('THIS IS A simple test: รครผรถss', getline('.')) + + " Turkish ASCII turns to multi-byte. On some systems Turkish locale + " is available but toupper()/tolower() don't do the right thing. + try + lang tr_TR.UTF-8 + set casemap= + let iupper = toupper('i') + if iupper == "\u0130" + call setline(1, 'iI') + 1normal gUU + call assert_equal("\u0130I", getline(1)) + call assert_equal("\u0130I", toupper("iI")) + + call setline(1, 'iI') + 1normal guu + call assert_equal("i\u0131", getline(1)) + call assert_equal("i\u0131", tolower("iI")) + elseif iupper == "I" + call setline(1, 'iI') + 1normal gUU + call assert_equal("II", getline(1)) + call assert_equal("II", toupper("iI")) + + call setline(1, 'iI') + 1normal guu + call assert_equal("ii", getline(1)) + call assert_equal("ii", tolower("iI")) + else + call assert_true(false, "expected toupper('i') to be either 'I' or '\u0131'") + endif + set casemap& + call setline(1, 'iI') + 1normal gUU + call assert_equal("II", getline(1)) + call assert_equal("II", toupper("iI")) + + call setline(1, 'iI') + 1normal guu + call assert_equal("ii", getline(1)) + call assert_equal("ii", tolower("iI")) + + lang en_US.UTF-8 + catch /E197:/ + " can't use Turkish locale + throw 'Skipped: Turkish locale not available' + endtry + + " clean up + bw! +endfunc + +fun! Test_normal31_r_cmd() + " Test for r command + new + call append(0, 'This is a simple test: abcd') + exe "norm! 1gg$r\<cr>" + call assert_equal(['This is a simple test: abc', '', ''], getline(1,'$')) + exe "norm! 1gg2wlr\<cr>" + call assert_equal(['This is a', 'simple test: abc', '', ''], getline(1,'$')) + exe "norm! 2gg0W5r\<cr>" + call assert_equal(['This is a', 'simple ', ' abc', '', ''], getline('1', '$')) + set autoindent + call setline(2, ['simple test: abc', '']) + exe "norm! 2gg0W5r\<cr>" + call assert_equal(['This is a', 'simple ', 'abc', '', '', ''], getline('1', '$')) + exe "norm! 1ggVr\<cr>" + call assert_equal('^M^M^M^M^M^M^M^M^M', strtrans(getline(1))) + call setline(1, 'This is a') + exe "norm! 1gg05rf" + call assert_equal('fffffis a', getline(1)) + + " clean up + set noautoindent + bw! +endfunc + +func! Test_normal32_g_cmd1() + " Test for g*, g# + new + call append(0, ['abc.x_foo', 'x_foobar.abc']) + 1 + norm! $g* + call assert_equal('x_foo', @/) + call assert_equal('x_foobar.abc', getline('.')) + norm! $g# + call assert_equal('abc', @/) + call assert_equal('abc.x_foo', getline('.')) + + " clean up + bw! +endfunc + +fun! Test_normal33_g_cmd2() + if !has("jumplist") + return + endif + " Tests for g cmds + call Setup_NewWindow() + " Test for g` + clearjumps + norm! ma10j + let a=execute(':jumps') + " empty jumplist + call assert_equal('>', a[-1:]) + norm! g`a + call assert_equal('>', a[-1:]) + call assert_equal(1, line('.')) + call assert_equal('1', getline('.')) + + " Test for g; and g, + norm! g; + " there is only one change in the changelist + " currently, when we setup the window + call assert_equal(2, line('.')) + call assert_fails(':norm! g;', 'E662') + call assert_fails(':norm! g,', 'E663') + let &ul=&ul + call append('$', ['a', 'b', 'c', 'd']) + let &ul=&ul + call append('$', ['Z', 'Y', 'X', 'W']) + let a = execute(':changes') + call assert_match('2\s\+0\s\+2', a) + call assert_match('101\s\+0\s\+a', a) + call assert_match('105\s\+0\s\+Z', a) + norm! 3g; + call assert_equal(2, line('.')) + norm! 2g, + call assert_equal(105, line('.')) + + " Test for g& - global substitute + %d + call setline(1, range(1,10)) + call append('$', ['a', 'b', 'c', 'd']) + $s/\w/&&/g + exe "norm! /[1-8]\<cr>" + norm! g& + call assert_equal(['11', '22', '33', '44', '55', '66', '77', '88', '9', '110', 'a', 'b', 'c', 'dd'], getline(1, '$')) + + " Test for gv + %d + call append('$', repeat(['abcdefgh'], 8)) + exe "norm! 2gg02l\<c-v>2j2ly" + call assert_equal(['cde', 'cde', 'cde'], getreg(0, 1, 1)) + " in visual mode, gv swaps current and last selected region + exe "norm! G0\<c-v>4k4lgvd" + call assert_equal(['', 'abfgh', 'abfgh', 'abfgh', 'abcdefgh', 'abcdefgh', 'abcdefgh', 'abcdefgh', 'abcdefgh'], getline(1,'$')) + exe "norm! G0\<c-v>4k4ly" + exe "norm! gvood" + call assert_equal(['', 'abfgh', 'abfgh', 'abfgh', 'fgh', 'fgh', 'fgh', 'fgh', 'fgh'], getline(1,'$')) + + " Test for gk/gj + %d + 15vsp + set wrap listchars= sbr= + let lineA='abcdefghijklmnopqrstuvwxyz' + let lineB='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' + $put =lineA + $put =lineB + + norm! 3gg0dgk + call assert_equal(['', 'abcdefghijklmno', '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'], getline(1, '$')) + set nu + norm! 3gg0gjdgj + call assert_equal(['', 'abcdefghijklmno', '0123456789AMNOPQRSTUVWXYZ'], getline(1,'$')) + + " Test for gJ + norm! 2gggJ + call assert_equal(['', 'abcdefghijklmno0123456789AMNOPQRSTUVWXYZ'], getline(1,'$')) + call assert_equal(16, col('.')) + " shouldn't do anything + norm! 10gJ + call assert_equal(1, col('.')) + + " Test for g0 g^ gm g$ + exe "norm! 2gg0gji " + call assert_equal(['', 'abcdefghijk lmno0123456789AMNOPQRSTUVWXYZ'], getline(1,'$')) + norm! g0yl + call assert_equal(12, col('.')) + call assert_equal(' ', getreg(0)) + norm! g$yl + call assert_equal(22, col('.')) + call assert_equal('3', getreg(0)) + norm! gmyl + call assert_equal(17, col('.')) + call assert_equal('n', getreg(0)) + norm! g^yl + call assert_equal(15, col('.')) + call assert_equal('l', getreg(0)) + + " Test for g Ctrl-G + set ff=unix + let a=execute(":norm! g\<c-g>") + call assert_match('Col 15 of 43; Line 2 of 2; Word 2 of 2; Byte 16 of 45', a) + + " Test for gI + norm! gIfoo + call assert_equal(['', 'fooabcdefghijk lmno0123456789AMNOPQRSTUVWXYZ'], getline(1,'$')) + + " Test for gi + wincmd c + %d + set tw=0 + call setline(1, ['foobar', 'new line']) + norm! A next word + $put ='third line' + norm! gi another word + call assert_equal(['foobar next word another word', 'new line', 'third line'], getline(1,'$')) + + " clean up + bw! +endfunc + +fun! Test_normal34_g_cmd3() + if !has("multi_byte") + return + endif + " Test for g8 + new + call append(0, 'abcdefghijklmnopqrstuvwxyzรครผรถ') + let a=execute(':norm! 1gg$g8') + call assert_equal('c3 b6 ', a[1:]) + + " Test for gp gP + call append(1, range(1,10)) + " clean up + bw! +endfunc + +fun! Test_normal35_g_cmd4() + " Test for g< + " Cannot capture its output, + " probably a bug, therefore, test disabled: + throw "Skipped: output of g< can't be tested currently" + echo "a\nb\nc\nd" + let b=execute(':norm! g<') + call assert_true(!empty(b), 'failed `execute(g<)`') +endfunc + +fun! Test_normal36_g_cmd5() + new + call append(0, 'abcdefghijklmnopqrstuvwxyz') + set ff=unix + " Test for gp gP + call append(1, range(1,10)) + 1 + norm! 1yy + 3 + norm! gp + call assert_equal([0, 5, 1, 0, 1], getcurpos()) + $ + norm! gP + call assert_equal([0, 14, 1, 0, 1], getcurpos()) + + " Test for go + norm! 26go + call assert_equal([0, 1, 26, 0, 26], getcurpos()) + norm! 27go + call assert_equal([0, 1, 26, 0, 26], getcurpos()) + norm! 28go + call assert_equal([0, 2, 1, 0, 1], getcurpos()) + set ff=dos + norm! 29go + call assert_equal([0, 2, 1, 0, 1], getcurpos()) + set ff=unix + norm! gg0 + norm! 101go + call assert_equal([0, 13, 26, 0, 26], getcurpos()) + norm! 103go + call assert_equal([0, 14, 1, 0, 1], getcurpos()) + " count > buffer content + norm! 120go + call assert_equal([0, 14, 1, 0, 2147483647], getcurpos()) + " clean up + bw! +endfunc + +fun! Test_normal37_g_cmd6() + " basic test for gt and gT + tabnew 1.txt + tabnew 2.txt + tabnew 3.txt + norm! 1gt + call assert_equal(1, tabpagenr()) + norm! 3gt + call assert_equal(3, tabpagenr()) + norm! 1gT + " count gT goes not to the absolute tabpagenumber + " but, but goes to the count previous tabpagenumber + call assert_equal(2, tabpagenr()) + " wrap around + norm! 3gT + call assert_equal(3, tabpagenr()) + " gt does not wrap around + norm! 5gt + call assert_equal(3, tabpagenr()) + + for i in range(3) + tabclose + endfor + " clean up + call assert_fails(':tabclose', 'E784') +endfunc + +fun! Test_normal38_nvhome() + " Test for <Home> and <C-Home> key + new + call setline(1, range(10)) + $ + setl et sw=2 + norm! V10>$ + " count is ignored + exe "norm! 10\<home>" + call assert_equal(1, col('.')) + exe "norm! \<home>" + call assert_equal([0, 10, 1, 0, 1], getcurpos()) + exe "norm! 5\<c-home>" + call assert_equal([0, 5, 1, 0, 1], getcurpos()) + exe "norm! \<c-home>" + call assert_equal([0, 1, 1, 0, 1], getcurpos()) + + " clean up + bw! +endfunc + +fun! Test_normal39_cw() + " Test for cw and cW on whitespace + " and cpo+=w setting + new + set tw=0 + call append(0, 'here are some words') + norm! 1gg0elcwZZZ + call assert_equal('hereZZZare some words', getline('.')) + norm! 1gg0elcWYYY + call assert_equal('hereZZZareYYYsome words', getline('.')) + " Nvim: no "w" flag in 'cpoptions'. + " set cpo+=w + " call setline(1, 'here are some words') + " norm! 1gg0elcwZZZ + " call assert_equal('hereZZZ are some words', getline('.')) + " norm! 1gg2elcWYYY + " call assert_equal('hereZZZ areYYY some words', getline('.')) + set cpo-=w + norm! 2gg0cwfoo + call assert_equal('foo', getline('.')) + + " clean up + bw! +endfunc + +fun! Test_normal40_ctrl_bsl() + " Basic test for CTRL-\ commands + new + call append(0, 'here are some words') + exe "norm! 1gg0a\<C-\>\<C-N>" + call assert_equal('n', mode()) + call assert_equal(1, col('.')) + call assert_equal('', visualmode()) + exe "norm! 1gg0viw\<C-\>\<C-N>" + call assert_equal('n', mode()) + call assert_equal(4, col('.')) + exe "norm! 1gg0a\<C-\>\<C-G>" + call assert_equal('n', mode()) + call assert_equal(1, col('.')) + "imap <buffer> , <c-\><c-n> + set im + exe ":norm! \<c-\>\<c-n>dw" + set noim + call assert_equal('are some words', getline(1)) + call assert_false(&insertmode) + + " clean up + bw! +endfunc + +fun! Test_normal41_insert_reg() + " Test for <c-r>=, <c-r><c-r>= and <c-r><c-o>= + " in insert mode + new + set sts=2 sw=2 ts=8 tw=0 + call append(0, ["aaa\tbbb\tccc", '', '', '']) + let a=getline(1) + norm! 2gg0 + exe "norm! a\<c-r>=a\<cr>" + norm! 3gg0 + exe "norm! a\<c-r>\<c-r>=a\<cr>" + norm! 4gg0 + exe "norm! a\<c-r>\<c-o>=a\<cr>" + call assert_equal(['aaa bbb ccc', 'aaa bbb ccc', 'aaa bbb ccc', 'aaa bbb ccc', ''], getline(1, '$')) + + " clean up + set sts=0 sw=8 ts=8 + bw! +endfunc + +func! Test_normal42_halfpage() + " basic test for Ctrl-D and Ctrl-U + call Setup_NewWindow() + call assert_equal(5, &scroll) + exe "norm! \<c-d>" + call assert_equal('6', getline('.')) + exe "norm! 2\<c-d>" + call assert_equal('8', getline('.')) + call assert_equal(2, &scroll) + set scroll=5 + exe "norm! \<c-u>" + call assert_equal('3', getline('.')) + 1 + set scrolloff=5 + exe "norm! \<c-d>" + call assert_equal('10', getline('.')) + exe "norm! \<c-u>" + call assert_equal('5', getline('.')) + 1 + set scrolloff=99 + exe "norm! \<c-d>" + call assert_equal('10', getline('.')) + set scrolloff=0 + 100 + exe "norm! $\<c-u>" + call assert_equal('95', getline('.')) + call assert_equal([0, 95, 1, 0, 1], getcurpos()) + 100 + set nostartofline + exe "norm! $\<c-u>" + call assert_equal('95', getline('.')) + call assert_equal([0, 95, 2, 0, 2147483647], getcurpos()) + " cleanup + set startofline + bw! +endfunc + +fun! Test_normal43_textobject1() + " basic tests for text object aw + new + call append(0, ['foobar,eins,foobar', 'foo,zwei,foo ']) + " diw + norm! 1gg0diw + call assert_equal([',eins,foobar', 'foo,zwei,foo ', ''], getline(1,'$')) + " daw + norm! 2ggEdaw + call assert_equal([',eins,foobar', 'foo,zwei,', ''], getline(1, '$')) + %d + call append(0, ["foo\teins\tfoobar", "foo\tzwei\tfoo "]) + " diW + norm! 2ggwd2iW + call assert_equal(['foo eins foobar', 'foo foo ', ''], getline(1,'$')) + " daW + norm! 1ggd2aW + call assert_equal(['foobar', 'foo foo ', ''], getline(1,'$')) + + %d + call append(0, ["foo\teins\tfoobar", "foo\tzwei\tfoo "]) + " aw in visual line mode switches to characterwise mode + norm! 2gg$Vawd + call assert_equal(['foo eins foobar', 'foo zwei foo'], getline(1,'$')) + norm! 1gg$Viwd + call assert_equal(['foo eins ', 'foo zwei foo'], getline(1,'$')) + + " clean up + bw! +endfunc + +func! Test_normal44_textobjects2() + " basic testing for is and as text objects + new + call append(0, ['This is a test. With some sentences!', '', 'Even with a question? And one more. And no sentence here']) + " Test for dis - does not remove trailing whitespace + norm! 1gg0dis + call assert_equal([' With some sentences!', '', 'Even with a question? And one more. And no sentence here', ''], getline(1,'$')) + " Test for das - removes leading whitespace + norm! 3ggf?ldas + call assert_equal([' With some sentences!', '', 'Even with a question? And no sentence here', ''], getline(1,'$')) + " when used in visual mode, is made characterwise + norm! 3gg$Visy + call assert_equal('v', visualmode()) + " reset visualmode() + norm! 3ggVy + norm! 3gg$Vasy + call assert_equal('v', visualmode()) + " basic testing for textobjects a< and at + %d + call setline(1, ['<div> ','<a href="foobar" class="foo">xyz</a>',' </div>', ' ']) + " a< + norm! 1gg0da< + call assert_equal([' ', '<a href="foobar" class="foo">xyz</a>', ' </div>', ' '], getline(1,'$')) + norm! 1pj + call assert_equal([' <div>', '<a href="foobar" class="foo">xyz</a>', ' </div>', ' '], getline(1,'$')) + " at + norm! d2at + call assert_equal([' '], getline(1,'$')) + %d + call setline(1, ['<div> ','<a href="foobar" class="foo">xyz</a>',' </div>', ' ']) + " i< + norm! 1gg0di< + call assert_equal(['<> ', '<a href="foobar" class="foo">xyz</a>', ' </div>', ' '], getline(1,'$')) + norm! 1Pj + call assert_equal(['<div> ', '<a href="foobar" class="foo">xyz</a>', ' </div>', ' '], getline(1,'$')) + norm! d2it + call assert_equal(['<div></div>',' '], getline(1,'$')) + " basic testing for a[ and i[ text object + %d + call setline(1, [' ', '[', 'one [two]', 'thre', ']']) + norm! 3gg0di[ + call assert_equal([' ', '[', ']'], getline(1,'$')) + call setline(1, [' ', '[', 'one [two]', 'thre', ']']) + norm! 3gg0ftd2a[ + call assert_equal([' '], getline(1,'$')) + %d + " Test for i" when cursor is in front of a quoted object + call append(0, 'foo "bar"') + norm! 1gg0di" + call assert_equal(['foo ""', ''], getline(1,'$')) + + " clean up + bw! +endfunc + +func! Test_normal45_drop() + if !has("dnd") + return + endif + " basic test for :drop command + " unfortunately, without a gui, we can't really test much here, + " so simply test that ~p fails (which uses the drop register) + new + call assert_fails(':norm! "~p', 'E353') + call assert_equal([], getreg('~', 1, 1)) + " the ~ register is read only + call assert_fails(':let @~="1"', 'E354') + bw! +endfunc + +func! Test_normal46_ignore() + " This test uses multi byte characters + if !has("multi_byte") + return + endif + + new + " How to test this? + " let's just for now test, that the buffer + " does not change + call feedkeys("\<c-s>", 't') + call assert_equal([''], getline(1,'$')) + + " no valid commands + exe "norm! \<char-0x100>" + call assert_equal([''], getline(1,'$')) + + exe "norm! รค" + call assert_equal([''], getline(1,'$')) + + " clean up + bw! +endfunc + +func! Test_normal47_visual_buf_wipe() + " This was causing a crash or ml_get error. + enew! + call setline(1,'xxx') + normal $ + new + call setline(1, range(1,2)) + 2 + exe "norm \<C-V>$" + bw! + norm yp + set nomodified +endfunc + +func! Test_normal47_autocmd() + " disabled, does not seem to be possible currently + throw "Skipped: not possible to test cursorhold autocmd while waiting for input in normal_cmd" + new + call append(0, repeat('-',20)) + au CursorHold * call feedkeys('2l', '') + 1 + set updatetime=20 + " should delete 12 chars (d12l) + call feedkeys('d1', '!') + call assert_equal('--------', getline(1)) + + " clean up + au! CursorHold + set updatetime=4000 + bw! +endfunc + +func! Test_normal48_wincmd() + new + exe "norm! \<c-w>c" + call assert_equal(1, winnr('$')) + call assert_fails(":norm! \<c-w>c", "E444") +endfunc + +func! Test_normal49_counts() + new + call setline(1, 'one two three four five six seven eight nine ten') + 1 + norm! 3d2w + call assert_equal('seven eight nine ten', getline(1)) + bw! +endfunc + +func! Test_normal50_commandline() + if !has("timers") || !has("cmdline_hist") || !has("vertsplit") + return + endif + func! DoTimerWork(id) + call assert_equal('[Command Line]', bufname('')) + " should fail, with E11, but does fail with E23? + "call feedkeys("\<c-^>", 'tm') + + " should also fail with E11 + call assert_fails(":wincmd p", 'E11') + " return from commandline window + call feedkeys("\<cr>") + endfunc + + let oldlang=v:lang + lang C + set updatetime=20 + call timer_start(100, 'DoTimerWork') + try + " throws E23, for whatever reason... + call feedkeys('q:', 'x!') + catch /E23/ + " no-op + endtry + " clean up + set updatetime=4000 + exe "lang" oldlang + bw! +endfunc + +func! Test_normal51_FileChangedRO() + if !has("autocmd") + return + endif + call writefile(['foo'], 'Xreadonly.log') + new Xreadonly.log + setl ro + au FileChangedRO <buffer> :call feedkeys("\<c-^>", 'tix') + call assert_fails(":norm! Af", 'E788') + call assert_equal(['foo'], getline(1,'$')) + call assert_equal('Xreadonly.log', bufname('')) + + " cleanup + bw! + call delete("Xreadonly.log") +endfunc + +func! Test_normal52_rl() + if !has("rightleft") + return + endif + new + call setline(1, 'abcde fghij klmnopq') + norm! 1gg$ + set rl + call assert_equal(19, col('.')) + call feedkeys('l', 'tx') + call assert_equal(18, col('.')) + call feedkeys('h', 'tx') + call assert_equal(19, col('.')) + call feedkeys("\<right>", 'tx') + call assert_equal(18, col('.')) + call feedkeys("\<s-right>", 'tx') + call assert_equal(13, col('.')) + call feedkeys("\<c-right>", 'tx') + call assert_equal(7, col('.')) + call feedkeys("\<c-left>", 'tx') + call assert_equal(13, col('.')) + call feedkeys("\<s-left>", 'tx') + call assert_equal(19, col('.')) + call feedkeys("<<", 'tx') + call assert_equal(' abcde fghij klmnopq',getline(1)) + call feedkeys(">>", 'tx') + call assert_equal('abcde fghij klmnopq',getline(1)) + + " cleanup + set norl + bw! +endfunc + +func! Test_normal53_digraph() + if !has('digraphs') + return + endif + new + call setline(1, 'abcdefgh|') + exe "norm! 1gg0f\<c-k>!!" + call assert_equal(9, col('.')) + set cpo+=D + exe "norm! 1gg0f\<c-k>!!" + call assert_equal(1, col('.')) + + set cpo-=D + bw! +endfunc + +func! Test_normal54_Ctrl_bsl() + new + call setline(1, 'abcdefghijklmn') + exe "norm! df\<c-\>\<c-n>" + call assert_equal(['abcdefghijklmn'], getline(1,'$')) + exe "norm! df\<c-\>\<c-g>" + call assert_equal(['abcdefghijklmn'], getline(1,'$')) + exe "norm! df\<c-\>m" + call assert_equal(['abcdefghijklmn'], getline(1,'$')) + if !has("multi_byte") + return + endif + call setline(2, 'abcdefghijklmnฤf') + norm! 2gg0 + exe "norm! df\<Char-0x101>" + call assert_equal(['abcdefghijklmn', 'f'], getline(1,'$')) + norm! 1gg0 + exe "norm! df\<esc>" + call assert_equal(['abcdefghijklmn', 'f'], getline(1,'$')) + + " clean up + bw! +endfunc diff --git a/src/nvim/testdir/test_partial.vim b/src/nvim/testdir/test_partial.vim index 3a6e162453..de5c26c2dd 100644 --- a/src/nvim/testdir/test_partial.vim +++ b/src/nvim/testdir/test_partial.vim @@ -14,6 +14,14 @@ func MySort(up, one, two) return a:one < a:two ? 1 : -1 endfunc +func MyMap(sub, index, val) + return a:val - a:sub +endfunc + +func MyFilter(threshold, index, val) + return a:val > a:threshold +endfunc + func Test_partial_args() let Cb = function('MyFunc', ["foo", "bar"]) @@ -36,6 +44,16 @@ func Test_partial_args() call assert_equal([1, 2, 3], sort([3, 1, 2], Sort)) let Sort = function('MySort', [0]) call assert_equal([3, 2, 1], sort([3, 1, 2], Sort)) + + let Map = function('MyMap', [2]) + call assert_equal([-1, 0, 1], map([1, 2, 3], Map)) + let Map = function('MyMap', [3]) + call assert_equal([-2, -1, 0], map([1, 2, 3], Map)) + + let Filter = function('MyFilter', [1]) + call assert_equal([2, 3], filter([1, 2, 3], Filter)) + let Filter = function('MyFilter', [2]) + call assert_equal([3], filter([1, 2, 3], Filter)) endfunc func MyDictFunc(arg1, arg2) dict @@ -59,6 +77,9 @@ func Test_partial_dict() call assert_equal("hello/xxx/yyy", Cb("xxx", "yyy")) call assert_fails('Cb("fff")', 'E492:') + let Cb = function('MyDictFunc', dict) + call assert_equal({"foo": "hello/foo/1", "bar": "hello/bar/2"}, map({"foo": 1, "bar": 2}, Cb)) + let dict = {"tr": function('tr', ['hello', 'h', 'H'])} call assert_equal("Hello", dict.tr()) endfunc diff --git a/src/nvim/testdir/test_popup.vim b/src/nvim/testdir/test_popup.vim index 50110dd622..e1ba142d1c 100644 --- a/src/nvim/testdir/test_popup.vim +++ b/src/nvim/testdir/test_popup.vim @@ -7,10 +7,10 @@ func! ListMonths() if g:setting != '' exe ":set" g:setting endif - let mth=copy(g:months) + let mth = copy(g:months) let entered = strcharpart(getline('.'),0,col('.')) if !empty(entered) - let mth=filter(mth, 'v:val=~"^".entered') + let mth = filter(mth, 'v:val=~"^".entered') endif call complete(1, mth) return '' @@ -468,7 +468,7 @@ endfunc " auto-wrap text. func Test_completion_ctrl_e_without_autowrap() new - let tw_save=&tw + let tw_save = &tw set tw=78 let li = [ \ '" zzz', @@ -478,8 +478,96 @@ func Test_completion_ctrl_e_without_autowrap() call feedkeys("A\<C-X>\<C-N>\<C-E>\<Esc>", "tx") call assert_equal(li, getline(1, '$')) - let &tw=tw_save + let &tw = tw_save q! endfunc +func Test_completion_respect_bs_option() + new + let li = ["aaa", "aaa12345", "aaaabcdef", "aaaABC"] + + set bs=indent,eol + call setline(1, li) + 1 + call feedkeys("A\<C-X>\<C-N>\<C-P>\<BS>\<BS>\<BS>\<Esc>", "tx") + call assert_equal('aaa', getline(1)) + + %d + set bs=indent,eol,start + call setline(1, li) + 1 + call feedkeys("A\<C-X>\<C-N>\<C-P>\<BS>\<BS>\<BS>\<Esc>", "tx") + call assert_equal('', getline(1)) + + bw! +endfunc + +func CompleteUndo() abort + call complete(1, g:months) + return '' +endfunc + +func Test_completion_can_undo() + inoremap <Right> <c-r>=CompleteUndo()<cr> + set completeopt+=noinsert,noselect + + new + call feedkeys("a\<Right>a\<Esc>", 'xt') + call assert_equal('a', getline(1)) + undo + call assert_equal('', getline(1)) + + bwipe! + set completeopt& + iunmap <Right> +endfunc + +func Test_completion_comment_formatting() + new + setl formatoptions=tcqro + call feedkeys("o/*\<cr>\<cr>/\<esc>", 'tx') + call assert_equal(['', '/*', ' *', ' */'], getline(1,4)) + %d + call feedkeys("o/*\<cr>foobar\<cr>/\<esc>", 'tx') + call assert_equal(['', '/*', ' * foobar', ' */'], getline(1,4)) + %d + try + call feedkeys("o/*\<cr>\<cr>\<c-x>\<c-u>/\<esc>", 'tx') + call assert_report('completefunc not set, should have failed') + catch + call assert_exception('E764:') + endtry + call assert_equal(['', '/*', ' *', ' */'], getline(1,4)) + bwipe! +endfunc + +function! DummyCompleteSix() + call complete(1, ['Hello', 'World']) + return '' +endfunction + +" complete() correctly clears the list of autocomplete candidates +func Test_completion_clear_candidate_list() + new + %d + " select first entry from the completion popup + call feedkeys("a xxx\<C-N>\<C-R>=DummyCompleteSix()\<CR>", "tx") + call assert_equal('Hello', getline(1)) + %d + " select second entry from the completion popup + call feedkeys("a xxx\<C-N>\<C-R>=DummyCompleteSix()\<CR>\<C-N>", "tx") + call assert_equal('World', getline(1)) + %d + " select original text + call feedkeys("a xxx\<C-N>\<C-R>=DummyCompleteSix()\<CR>\<C-N>\<C-N>", "tx") + call assert_equal(' xxx', getline(1)) + %d + " back at first entry from completion list + call feedkeys("a xxx\<C-N>\<C-R>=DummyCompleteSix()\<CR>\<C-N>\<C-N>\<C-N>", "tx") + call assert_equal('Hello', getline(1)) + + bw! +endfunc + + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_quickfix.vim b/src/nvim/testdir/test_quickfix.vim index f30902b915..aff5fc2eed 100644 --- a/src/nvim/testdir/test_quickfix.vim +++ b/src/nvim/testdir/test_quickfix.vim @@ -6,7 +6,7 @@ endif set encoding=utf-8 -function! s:setup_commands(cchar) +func s:setup_commands(cchar) if a:cchar == 'c' command! -nargs=* -bang Xlist <mods>clist<bang> <args> command! -nargs=* Xgetexpr <mods>cgetexpr <args> @@ -68,10 +68,10 @@ function! s:setup_commands(cchar) let g:Xgetlist = function('getloclist', [0]) let g:Xsetlist = function('setloclist', [0]) endif -endfunction +endfunc " Tests for the :clist and :llist commands -function XlistTests(cchar) +func XlistTests(cchar) call s:setup_commands(a:cchar) " With an empty list, command should return error @@ -128,17 +128,17 @@ function XlistTests(cchar) let l = split(result, "\n") call assert_equal([' 2 Xtestfile1:1 col 3: Line1', \ ' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2'], l) -endfunction +endfunc -function Test_clist() +func Test_clist() call XlistTests('c') call XlistTests('l') -endfunction +endfunc " Tests for the :colder, :cnewer, :lolder and :lnewer commands " Note that this test assumes that a quickfix/location list is " already set by the caller. -function XageTests(cchar) +func XageTests(cchar) call s:setup_commands(a:cchar) " Jumping to a non existent list should return error @@ -171,20 +171,20 @@ function XageTests(cchar) Xnewer 2 let l = g:Xgetlist() call assert_equal('Line3', l[0].text) -endfunction +endfunc -function Test_cage() +func Test_cage() let list = [{'bufnr': 1, 'lnum': 1}] call setqflist(list) call XageTests('c') call setloclist(0, list) call XageTests('l') -endfunction +endfunc " Tests for the :cwindow, :lwindow :cclose, :lclose, :copen and :lopen " commands -function XwindowTests(cchar) +func XwindowTests(cchar) call s:setup_commands(a:cchar) " Create a list with no valid entries @@ -227,16 +227,16 @@ function XwindowTests(cchar) " Calling cwindow should close the quickfix window with no valid errors Xwindow call assert_true(winnr('$') == 1) -endfunction +endfunc -function Test_cwindow() +func Test_cwindow() call XwindowTests('c') call XwindowTests('l') -endfunction +endfunc " Tests for the :cfile, :lfile, :caddfile, :laddfile, :cgetfile and :lgetfile " commands. -function XfileTests(cchar) +func XfileTests(cchar) call s:setup_commands(a:cchar) call writefile(['Xtestfile1:700:10:Line 700', @@ -275,16 +275,16 @@ function XfileTests(cchar) \ l[1].lnum == 333 && l[1].col == 88 && l[1].text ==# 'Line 333') call delete('Xqftestfile1') -endfunction +endfunc -function Test_cfile() +func Test_cfile() call XfileTests('c') call XfileTests('l') -endfunction +endfunc " Tests for the :cbuffer, :lbuffer, :caddbuffer, :laddbuffer, :cgetbuffer and " :lgetbuffer commands. -function XbufferTests(cchar) +func XbufferTests(cchar) call s:setup_commands(a:cchar) enew! @@ -316,26 +316,26 @@ function XbufferTests(cchar) \ l[3].lnum == 750 && l[3].col == 25 && l[3].text ==# 'Line 750') enew! -endfunction +endfunc -function Test_cbuffer() +func Test_cbuffer() call XbufferTests('c') call XbufferTests('l') -endfunction +endfunc -function XexprTests(cchar) +func XexprTests(cchar) call s:setup_commands(a:cchar) call assert_fails('Xexpr 10', 'E777:') -endfunction +endfunc -function Test_cexpr() +func Test_cexpr() call XexprTests('c') call XexprTests('l') -endfunction +endfunc " Tests for :cnext, :cprev, :cfirst, :clast commands -function Xtest_browse(cchar) +func Xtest_browse(cchar) call s:setup_commands(a:cchar) call s:create_test_file('Xqftestfile1') @@ -366,14 +366,14 @@ function Xtest_browse(cchar) call delete('Xqftestfile1') call delete('Xqftestfile2') -endfunction +endfunc -function Test_browse() +func Test_browse() call Xtest_browse('c') call Xtest_browse('l') -endfunction +endfunc -function! s:test_xhelpgrep(cchar) +func s:test_xhelpgrep(cchar) call s:setup_commands(a:cchar) Xhelpgrep quickfix Xopen @@ -385,10 +385,11 @@ function! s:test_xhelpgrep(cchar) call assert_true(w:quickfix_title =~ title_text, w:quickfix_title) " This wipes out the buffer, make sure that doesn't cause trouble. Xclose -endfunction +endfunc -function Test_helpgrep() +func Test_helpgrep() call s:test_xhelpgrep('c') + helpclose call s:test_xhelpgrep('l') endfunc @@ -424,7 +425,7 @@ func Test_vimgreptitle() augroup! QfBufWinEnter endfunc -function XqfTitleTests(cchar) +func XqfTitleTests(cchar) call s:setup_commands(a:cchar) Xgetexpr ['file:1:1:message'] @@ -443,16 +444,16 @@ function XqfTitleTests(cchar) endif call assert_equal(title, w:quickfix_title) Xclose -endfunction +endfunc " Tests for quickfix window's title -function Test_qf_title() +func Test_qf_title() call XqfTitleTests('c') call XqfTitleTests('l') -endfunction +endfunc " Tests for 'errorformat' -function Test_efm() +func Test_efm() let save_efm = &efm set efm=%EEEE%m,%WWWW%m,%+CCCC%.%#,%-GGGG%.%# cgetexpr ['WWWW', 'EEEE', 'CCCC'] @@ -465,7 +466,7 @@ function Test_efm() let l = strtrans(string(map(getqflist(), '[v:val.text, v:val.valid]'))) call assert_equal("[['W', 1], ['ZZZZ', 0], ['E^@CCCC', 1], ['YYYY', 0]]", l) let &efm = save_efm -endfunction +endfunc " This will test for problems in quickfix: " A. incorrectly copying location lists which caused the location list to show @@ -476,7 +477,7 @@ endfunction " window it belongs to. " " Set up the test environment: -function! ReadTestProtocol(name) +func ReadTestProtocol(name) let base = substitute(a:name, '\v^test://(.*)%(\.[^.]+)?', '\1', '') let word = substitute(base, '\v(.*)\..*', '\1', '') @@ -495,9 +496,9 @@ function! ReadTestProtocol(name) setl nomodifiable setl readonly exe 'doautocmd BufRead ' . substitute(a:name, '\v^test://(.*)', '\1', '') -endfunction +endfunc -function Test_locationlist() +func Test_locationlist() enew augroup testgroup @@ -577,15 +578,15 @@ function Test_locationlist() wincmd n | only augroup! testgroup -endfunction + endfunc -function Test_locationlist_curwin_was_closed() +func Test_locationlist_curwin_was_closed() augroup testgroup au! autocmd BufReadCmd test_curwin.txt call R(expand("<amatch>")) augroup END - function! R(n) + func! R(n) quit endfunc @@ -596,10 +597,26 @@ function Test_locationlist_curwin_was_closed() call assert_fails('lrewind', 'E924:') augroup! testgroup -endfunction + endfunc + +func Test_locationlist_cross_tab_jump() + call writefile(['loclistfoo'], 'loclistfoo') + call writefile(['loclistbar'], 'loclistbar') + set switchbuf=usetab + + edit loclistfoo + tabedit loclistbar + silent lgrep loclistfoo loclist* + call assert_equal(1, tabpagenr()) + + enew | only | tabonly + set switchbuf&vim + call delete('loclistfoo') + call delete('loclistbar') +endfunc " More tests for 'errorformat' -function! Test_efm1() +func Test_efm1() if !has('unix') " The 'errorformat' setting is different on non-Unix systems. " This test works only on Unix-like systems. @@ -717,10 +734,10 @@ function! Test_efm1() call delete('Xerrorfile1') call delete('Xerrorfile2') call delete('Xtestfile') -endfunction + endfunc " Test for quickfix directory stack support -function! s:dir_stack_tests(cchar) +func s:dir_stack_tests(cchar) call s:setup_commands(a:cchar) let save_efm=&efm @@ -762,10 +779,10 @@ function! s:dir_stack_tests(cchar) call assert_equal(5, qf[11].lnum) let &efm=save_efm -endfunction +endfunc " Tests for %D and %X errorformat options -function! Test_efm_dirstack() +func Test_efm_dirstack() " Create the directory stack and files call mkdir('dir1') call mkdir('dir1/a') @@ -797,10 +814,33 @@ function! Test_efm_dirstack() call delete('dir1', 'rf') call delete('dir2', 'rf') call delete('habits1.txt') -endfunction +endfunc + +" Test for resync after continuing an ignored message +func Xefm_ignore_continuations(cchar) + call s:setup_commands(a:cchar) + + let save_efm = &efm + + let &efm = + \ '%Eerror %m %l,' . + \ '%-Wignored %m %l,' . + \ '%+Cmore ignored %m %l,' . + \ '%Zignored end' + Xgetexpr ['ignored warning 1', 'more ignored continuation 2', 'ignored end', 'error resync 4'] + let l = map(g:Xgetlist(), '[v:val.text, v:val.valid, v:val.lnum, v:val.type]') + call assert_equal([['resync', 1, 4, 'E']], l) + + let &efm = save_efm +endfunc + +func Test_efm_ignore_continuations() + call Xefm_ignore_continuations('c') + call Xefm_ignore_continuations('l') +endfunc " Tests for invalid error format specifies -function Xinvalid_efm_Tests(cchar) +func Xinvalid_efm_Tests(cchar) call s:setup_commands(a:cchar) let save_efm = &efm @@ -833,17 +873,17 @@ function Xinvalid_efm_Tests(cchar) call assert_fails('Xexpr ["Entering dir abc", "abc.txt:1:Hello world"]', 'E379:') let &efm = save_efm -endfunction +endfunc -function Test_invalid_efm() +func Test_invalid_efm() call Xinvalid_efm_Tests('c') call Xinvalid_efm_Tests('l') -endfunction +endfunc " TODO: " Add tests for the following formats in 'errorformat' " %r %O -function! Test_efm2() +func Test_efm2() let save_efm = &efm " Test for %s format in efm @@ -904,20 +944,44 @@ function! Test_efm2() call assert_equal('E', l[0].type) call assert_equal("\nunknown variable 'i'", l[0].text) + " Test for %A, %C and other formats + let lines = [ + \"==============================================================", + \"FAIL: testGetTypeIdCachesResult (dbfacadeTest.DjsDBFacadeTest)", + \"--------------------------------------------------------------", + \"Traceback (most recent call last):", + \' File "unittests/dbfacadeTest.py", line 89, in testFoo', + \" self.assertEquals(34, dtid)", + \' File "/usr/lib/python2.2/unittest.py", line 286, in', + \" failUnlessEqual", + \" raise self.failureException, \\", + \"AssertionError: 34 != 33", + \"", + \"--------------------------------------------------------------", + \"Ran 27 tests in 0.063s" + \] + set efm=%C\ %.%#,%A\ \ File\ \"%f\"\\,\ line\ %l%.%#,%Z%[%^\ ]%\\@=%m + cgetexpr lines + let l = getqflist() + call assert_equal(8, len(l)) + call assert_equal(89, l[4].lnum) + call assert_equal(1, l[4].valid) + call assert_equal('unittests/dbfacadeTest.py', bufname(l[4].bufnr)) + let &efm = save_efm -endfunction +endfunc -function XquickfixChangedByAutocmd(cchar) +func XquickfixChangedByAutocmd(cchar) call s:setup_commands(a:cchar) if a:cchar == 'c' let ErrorNr = 'E925' - function! ReadFunc() + func! ReadFunc() colder cgetexpr [] endfunc else let ErrorNr = 'E926' - function! ReadFunc() + func! ReadFunc() lolder lgetexpr [] endfunc @@ -940,10 +1004,10 @@ function XquickfixChangedByAutocmd(cchar) augroup! testgroup endfunc -function Test_quickfix_was_changed_by_autocmd() +func Test_quickfix_was_changed_by_autocmd() call XquickfixChangedByAutocmd('c') call XquickfixChangedByAutocmd('l') -endfunction +endfunc func Test_caddbuffer_to_empty() helpgr quickfix @@ -965,7 +1029,7 @@ func Test_cgetexpr_works() endfunc " Tests for the setqflist() and setloclist() functions -function SetXlistTests(cchar, bnum) +func SetXlistTests(cchar, bnum) call s:setup_commands(a:cchar) call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 1}, @@ -1000,9 +1064,9 @@ function SetXlistTests(cchar, bnum) call g:Xsetlist([]) let l = g:Xgetlist() call assert_equal(0, len(l)) -endfunction +endfunc -function Test_setqflist() +func Test_setqflist() new Xtestfile | only let bnum = bufnr('%') call setline(1, range(1,5)) @@ -1012,9 +1076,9 @@ function Test_setqflist() enew! call delete('Xtestfile') -endfunction +endfunc -function Xlist_empty_middle(cchar) +func Xlist_empty_middle(cchar) call s:setup_commands(a:cchar) " create three quickfix lists @@ -1037,12 +1101,12 @@ function Xlist_empty_middle(cchar) call assert_equal(matchlen, len(g:Xgetlist())) endfunc -function Test_setqflist_empty_middle() +func Test_setqflist_empty_middle() call Xlist_empty_middle('c') call Xlist_empty_middle('l') -endfunction +endfunc -function Xlist_empty_older(cchar) +func Xlist_empty_older(cchar) call s:setup_commands(a:cchar) " create three quickfix lists @@ -1063,14 +1127,14 @@ function Xlist_empty_older(cchar) call assert_equal(twolen, len(g:Xgetlist())) Xnewer call assert_equal(threelen, len(g:Xgetlist())) -endfunction +endfunc -function Test_setqflist_empty_older() +func Test_setqflist_empty_older() call Xlist_empty_older('c') call Xlist_empty_older('l') -endfunction +endfunc -function! XquickfixSetListWithAct(cchar) +func XquickfixSetListWithAct(cchar) call s:setup_commands(a:cchar) let list1 = [{'filename': 'fnameA', 'text': 'A'}, @@ -1144,12 +1208,12 @@ function! XquickfixSetListWithAct(cchar) call assert_fails("call g:Xsetlist(list1, 0)", 'E928:') endfunc -function Test_quickfix_set_list_with_act() +func Test_quickfix_set_list_with_act() call XquickfixSetListWithAct('c') call XquickfixSetListWithAct('l') -endfunction +endfunc -function XLongLinesTests(cchar) +func XLongLinesTests(cchar) let l = g:Xgetlist() call assert_equal(4, len(l)) @@ -1167,9 +1231,9 @@ function XLongLinesTests(cchar) call assert_equal(10, len(l[3].text)) call g:Xsetlist([], 'r') -endfunction +endfunc -function s:long_lines_tests(cchar) +func s:long_lines_tests(cchar) call s:setup_commands(a:cchar) let testfile = 'samples/quickfix.txt' @@ -1190,22 +1254,22 @@ function s:long_lines_tests(cchar) exe 'edit' testfile exe 'Xbuffer' bufnr('%') call XLongLinesTests(a:cchar) -endfunction +endfunc -function Test_long_lines() +func Test_long_lines() call s:long_lines_tests('c') call s:long_lines_tests('l') -endfunction +endfunc -function! s:create_test_file(filename) +func s:create_test_file(filename) let l = [] for i in range(1, 20) call add(l, 'Line' . i) endfor call writefile(l, a:filename) -endfunction +endfunc -function! Test_switchbuf() +func Test_switchbuf() call s:create_test_file('Xqftestfile1') call s:create_test_file('Xqftestfile2') call s:create_test_file('Xqftestfile3') @@ -1292,20 +1356,21 @@ function! Test_switchbuf() call delete('Xqftestfile1') call delete('Xqftestfile2') call delete('Xqftestfile3') -endfunction +endfunc -function! Xadjust_qflnum(cchar) +func Xadjust_qflnum(cchar) call s:setup_commands(a:cchar) enew | only - call s:create_test_file('Xqftestfile') - edit Xqftestfile + let fname = 'Xqftestfile' . a:cchar + call s:create_test_file(fname) + exe 'edit ' . fname - Xgetexpr ['Xqftestfile:5:Line5', - \ 'Xqftestfile:10:Line10', - \ 'Xqftestfile:15:Line15', - \ 'Xqftestfile:20:Line20'] + Xgetexpr [fname . ':5:Line5', + \ fname . ':10:Line10', + \ fname . ':15:Line15', + \ fname . ':20:Line20'] 6,14delete call append(6, ['Buffer', 'Window']) @@ -1317,16 +1382,18 @@ function! Xadjust_qflnum(cchar) call assert_equal(13, l[3].lnum) enew! - call delete('Xqftestfile') -endfunction + call delete(fname) +endfunc -function! Test_adjust_lnum() +func Test_adjust_lnum() + call setloclist(0, []) call Xadjust_qflnum('c') + call setqflist([]) call Xadjust_qflnum('l') -endfunction +endfunc " Tests for the :grep/:lgrep and :grepadd/:lgrepadd commands -function! s:test_xgrep(cchar) +func s:test_xgrep(cchar) call s:setup_commands(a:cchar) " The following lines are used for the grep test. Don't remove. @@ -1345,9 +1412,9 @@ function! s:test_xgrep(cchar) set makeef=Temp_File_## silent Xgrepadd GrepAdd_Test_Text: test_quickfix.vim call assert_true(len(g:Xgetlist()) == 6) -endfunction +endfunc -function! Test_grep() +func Test_grep() if !has('unix') " The grepprg may not be set on non-Unix systems return @@ -1355,9 +1422,9 @@ function! Test_grep() call s:test_xgrep('c') call s:test_xgrep('l') -endfunction +endfunc -function! Test_two_windows() +func Test_two_windows() " Use one 'errorformat' for two windows. Add an expression to each of them, " make sure they each keep their own state. set efm=%DEntering\ dir\ '%f',%f:%l:%m,%XLeaving\ dir\ '%f' @@ -1383,12 +1450,10 @@ function! Test_two_windows() laddexpr 'one.txt:3:one one one' let loc_one = getloclist(one_id) -echo string(loc_one) call assert_equal('Xone/a/one.txt', bufname(loc_one[1].bufnr)) call assert_equal(3, loc_one[1].lnum) let loc_two = getloclist(two_id) -echo string(loc_two) call assert_equal('Xtwo/a/two.txt', bufname(loc_two[1].bufnr)) call assert_equal(5, loc_two[1].lnum) @@ -1400,7 +1465,7 @@ echo string(loc_two) call delete('Xtwo', 'rf') endfunc -function XbottomTests(cchar) +func XbottomTests(cchar) call s:setup_commands(a:cchar) call g:Xsetlist([{'filename': 'foo', 'lnum': 42}]) @@ -1416,7 +1481,195 @@ function XbottomTests(cchar) endfunc " Tests for the :cbottom and :lbottom commands -function Test_cbottom() +func Test_cbottom() call XbottomTests('c') call XbottomTests('l') -endfunction +endfunc + +func HistoryTest(cchar) + call s:setup_commands(a:cchar) + + call assert_fails(a:cchar . 'older 99', 'E380:') + " clear all lists after the first one, then replace the first one. + call g:Xsetlist([]) + Xolder + let entry = {'filename': 'foo', 'lnum': 42} + call g:Xsetlist([entry], 'r') + call g:Xsetlist([entry, entry]) + call g:Xsetlist([entry, entry, entry]) + let res = split(execute(a:cchar . 'hist'), "\n") + call assert_equal(3, len(res)) + let common = 'errors :set' . (a:cchar == 'c' ? 'qf' : 'loc') . 'list()' + call assert_equal(' error list 1 of 3; 1 ' . common, res[0]) + call assert_equal(' error list 2 of 3; 2 ' . common, res[1]) + call assert_equal('> error list 3 of 3; 3 ' . common, res[2]) +endfunc + +func Test_history() + call HistoryTest('c') + call HistoryTest('l') +endfunc + +func Test_duplicate_buf() + " make sure we can get the highest buffer number + edit DoesNotExist + edit DoesNotExist2 + let last_buffer = bufnr("$") + + " make sure only one buffer is created + call writefile(['this one', 'that one'], 'Xgrepthis') + vimgrep one Xgrepthis + vimgrep one Xgrepthis + call assert_equal(last_buffer + 1, bufnr("$")) + + call delete('Xgrepthis') +endfunc + +" Quickfix/Location list set/get properties tests +func Xproperty_tests(cchar) + call s:setup_commands(a:cchar) + + " Error cases + call assert_fails('call g:Xgetlist(99)', 'E715:') + call assert_fails('call g:Xsetlist(99)', 'E714:') + call assert_fails('call g:Xsetlist([], "a", [])', 'E715:') + + " Set and get the title + Xopen + wincmd p + call g:Xsetlist([{'filename':'foo', 'lnum':27}]) + call g:Xsetlist([], 'a', {'title' : 'Sample'}) + let d = g:Xgetlist({"title":1}) + call assert_equal('Sample', d.title) + + Xopen + call assert_equal('Sample', w:quickfix_title) + Xclose + + " Tests for action argument + silent! Xolder 999 + let qfnr = g:Xgetlist({'all':1}).nr + call g:Xsetlist([], 'r', {'title' : 'N1'}) + call assert_equal('N1', g:Xgetlist({'all':1}).title) + call g:Xsetlist([], ' ', {'title' : 'N2'}) + call assert_equal(qfnr + 1, g:Xgetlist({'all':1}).nr) + + let res = g:Xgetlist({'nr': 0}) + call assert_equal(qfnr + 1, res.nr) + call assert_equal(['nr'], keys(res)) + + call g:Xsetlist([], ' ', {'title' : 'N3'}) + call assert_equal('N2', g:Xgetlist({'nr':2, 'title':1}).title) + + " Invalid arguments + call assert_fails('call g:Xgetlist([])', 'E715') + call assert_fails('call g:Xsetlist([], "a", [])', 'E715') + let s = g:Xsetlist([], 'a', {'abc':1}) + call assert_equal(-1, s) + + call assert_equal({}, g:Xgetlist({'abc':1})) + + if a:cchar == 'l' + call assert_equal({}, getloclist(99, {'title': 1})) + endif + endfunc + +func Test_qf_property() + call Xproperty_tests('c') + call Xproperty_tests('l') + endfunc + +" Tests for the QuickFixCmdPre/QuickFixCmdPost autocommands +func QfAutoCmdHandler(loc, cmd) + call add(g:acmds, a:loc . a:cmd) +endfunc + +func Test_Autocmd() + autocmd QuickFixCmdPre * call QfAutoCmdHandler('pre', expand('<amatch>')) + autocmd QuickFixCmdPost * call QfAutoCmdHandler('post', expand('<amatch>')) + + let g:acmds = [] + cexpr "F1:10:Line 10" + caddexpr "F1:20:Line 20" + cgetexpr "F1:30:Line 30" + enew! | call append(0, "F2:10:Line 10") + cbuffer! + enew! | call append(0, "F2:20:Line 20") + cgetbuffer + enew! | call append(0, "F2:30:Line 30") + caddbuffer + + let l = ['precexpr', + \ 'postcexpr', + \ 'precaddexpr', + \ 'postcaddexpr', + \ 'precgetexpr', + \ 'postcgetexpr', + \ 'precbuffer', + \ 'postcbuffer', + \ 'precgetbuffer', + \ 'postcgetbuffer', + \ 'precaddbuffer', + \ 'postcaddbuffer'] + call assert_equal(l, g:acmds) +endfunc + +func Test_Autocmd_Exception() + set efm=%m + lgetexpr '?' + + try + call DoesNotExit() + catch + lgetexpr '1' + finally + lgetexpr '1' + endtry + + call assert_equal('1', getloclist(0)[0].text) + + set efm&vim +endfunc + +func Test_caddbuffer_wrong() + " This used to cause a memory access in freed memory. + let save_efm = &efm + set efm=%EEEE%m,%WWWW,%+CCCC%>%#,%GGGG%.# + cgetexpr ['WWWW', 'EEEE', 'CCCC'] + let &efm = save_efm + caddbuffer + bwipe! +endfunc + +func Test_caddexpr_wrong() + " This used to cause a memory access in freed memory. + cbuffer + cbuffer + copen + let save_efm = &efm + set efm=% + call assert_fails('caddexpr ""', 'E376:') + let &efm = save_efm +endfunc + +func Test_dirstack_cleanup() + " This used to cause a memory access in freed memory. + let save_efm = &efm + lexpr '0' + lopen + fun X(c) + let save_efm=&efm + set efm=%D%f + if a:c == 'c' + caddexpr '::' + else + laddexpr ':0:0' + endif + let &efm=save_efm + endfun + call X('c') + call X('l') + call setqflist([], 'r') + caddbuffer + let &efm = save_efm +endfunc diff --git a/src/nvim/testdir/test_regexp_utf8.vim b/src/nvim/testdir/test_regexp_utf8.vim index ecb03a0f8c..a2f4286d4f 100644 --- a/src/nvim/testdir/test_regexp_utf8.vim +++ b/src/nvim/testdir/test_regexp_utf8.vim @@ -31,6 +31,65 @@ func Test_equivalence_re2() set re=0 endfunc +func s:classes_test() + set isprint=@,161-255 + call assert_equal('Motรถrhead', matchstr('Motรถrhead', '[[:print:]]\+')) + + let alphachars = '' + let lowerchars = '' + let upperchars = '' + let alnumchars = '' + let printchars = '' + let punctchars = '' + let xdigitchars = '' + let i = 1 + while i <= 255 + let c = nr2char(i) + if c =~ '[[:alpha:]]' + let alphachars .= c + endif + if c =~ '[[:lower:]]' + let lowerchars .= c + endif + if c =~ '[[:upper:]]' + let upperchars .= c + endif + if c =~ '[[:alnum:]]' + let alnumchars .= c + endif + if c =~ '[[:print:]]' + let printchars .= c + endif + if c =~ '[[:punct:]]' + let punctchars .= c + endif + if c =~ '[[:xdigit:]]' + let xdigitchars .= c + endif + let i += 1 + endwhile + + call assert_equal('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', alphachars) + call assert_equal('abcdefghijklmnopqrstuvwxyzยตรร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรธรนรบรปรผรฝรพรฟ', lowerchars) + call assert_equal('ABCDEFGHIJKLMNOPQRSTUVWXYZรรรรรร
รรรรรรรรรรรรรรรรรรรรรรรร', upperchars) + call assert_equal('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', alnumchars) + call assert_equal(' !"#$%&''()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ย ยกยขยฃยคยฅยฆยงยจยฉยชยซยฌยญยฎยฏยฐยฑยฒยณยดยตยถยทยธยนยบยปยผยฝยพยฟรรรรรร
รรรรรรรรรรรรรรรรรรรรรรรรรรร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรทรธรนรบรปรผรฝรพรฟ', printchars) + call assert_equal('!"#$%&''()*+,-./:;<=>?@[\]^_`{|}~', punctchars) + call assert_equal('0123456789ABCDEFabcdef', xdigitchars) +endfunc + +func Test_classes_re1() + set re=1 + call s:classes_test() + set re=0 +endfunc + +func Test_classes_re2() + set re=2 + call s:classes_test() + set re=0 +endfunc + func Test_recursive_substitute() new s/^/\=execute("s#^##gn") @@ -38,3 +97,27 @@ func Test_recursive_substitute() call setwinvar(1, 'myvar', 1) bwipe! endfunc + +func Test_nested_backrefs() + " Check example in change.txt. + new + for re in range(0, 2) + exe 'set re=' . re + call setline(1, 'aa ab x') + 1s/\(\(a[a-d] \)*\)\(x\)/-\1- -\2- -\3-/ + call assert_equal('-aa ab - -ab - -x-', getline(1)) + + call assert_equal('-aa ab - -ab - -x-', substitute('aa ab x', '\(\(a[a-d] \)*\)\(x\)', '-\1- -\2- -\3-', '')) + endfor + bwipe! + set re=0 +endfunc + +func Test_eow_with_optional() + let expected = ['abc def', 'abc', 'def', '', '', '', '', '', '', ''] + for re in range(0, 2) + exe 'set re=' . re + let actual = matchlist('abc def', '\(abc\>\)\?\s*\(def\)') + call assert_equal(expected, actual) + endfor +endfunc diff --git a/src/nvim/testdir/test_search.vim b/src/nvim/testdir/test_search.vim new file mode 100644 index 0000000000..a333e7f206 --- /dev/null +++ b/src/nvim/testdir/test_search.vim @@ -0,0 +1,300 @@ +" Test for the search command + +func Test_search_cmdline() + " See test/functional/legacy/search_spec.lua + throw 'skipped: Nvim does not support test_disable_char_avail()' + if !exists('+incsearch') + return + endif + " need to disable char_avail, + " so that expansion of commandline works + call test_disable_char_avail(1) + new + call setline(1, [' 1', ' 2 these', ' 3 the', ' 4 their', ' 5 there', ' 6 their', ' 7 the', ' 8 them', ' 9 these', ' 10 foobar']) + " Test 1 + " CTRL-N / CTRL-P skips through the previous search history + set noincsearch + :1 + call feedkeys("/foobar\<cr>", 'tx') + call feedkeys("/the\<cr>",'tx') + call assert_equal('the', @/) + call feedkeys("/thes\<C-P>\<C-P>\<cr>",'tx') + call assert_equal('foobar', @/) + + " Test 2 + " Ctrl-G goes from one match to the next + " until the end of the buffer + set incsearch nowrapscan + :1 + " first match + call feedkeys("/the\<cr>", 'tx') + call assert_equal(' 2 these', getline('.')) + :1 + " second match + call feedkeys("/the\<C-G>\<cr>", 'tx') + call assert_equal(' 3 the', getline('.')) + call assert_equal([0, 0, 0, 0], getpos('"')) + :1 + " third match + call feedkeys("/the".repeat("\<C-G>", 2)."\<cr>", 'tx') + call assert_equal(' 4 their', getline('.')) + :1 + " fourth match + call feedkeys("/the".repeat("\<C-G>", 3)."\<cr>", 'tx') + call assert_equal(' 5 there', getline('.')) + :1 + " fifth match + call feedkeys("/the".repeat("\<C-G>", 4)."\<cr>", 'tx') + call assert_equal(' 6 their', getline('.')) + :1 + " sixth match + call feedkeys("/the".repeat("\<C-G>", 5)."\<cr>", 'tx') + call assert_equal(' 7 the', getline('.')) + :1 + " seventh match + call feedkeys("/the".repeat("\<C-G>", 6)."\<cr>", 'tx') + call assert_equal(' 8 them', getline('.')) + :1 + " eigth match + call feedkeys("/the".repeat("\<C-G>", 7)."\<cr>", 'tx') + call assert_equal(' 9 these', getline('.')) + :1 + " no further match + call feedkeys("/the".repeat("\<C-G>", 8)."\<cr>", 'tx') + call assert_equal(' 9 these', getline('.')) + call assert_equal([0, 0, 0, 0], getpos('"')) + + " Test 3 + " Ctrl-G goes from one match to the next + " and continues back at the top + set incsearch wrapscan + :1 + " first match + call feedkeys("/the\<cr>", 'tx') + call assert_equal(' 2 these', getline('.')) + :1 + " second match + call feedkeys("/the\<C-G>\<cr>", 'tx') + call assert_equal(' 3 the', getline('.')) + :1 + " third match + call feedkeys("/the".repeat("\<C-G>", 2)."\<cr>", 'tx') + call assert_equal(' 4 their', getline('.')) + :1 + " fourth match + call feedkeys("/the".repeat("\<C-G>", 3)."\<cr>", 'tx') + call assert_equal(' 5 there', getline('.')) + :1 + " fifth match + call feedkeys("/the".repeat("\<C-G>", 4)."\<cr>", 'tx') + call assert_equal(' 6 their', getline('.')) + :1 + " sixth match + call feedkeys("/the".repeat("\<C-G>", 5)."\<cr>", 'tx') + call assert_equal(' 7 the', getline('.')) + :1 + " seventh match + call feedkeys("/the".repeat("\<C-G>", 6)."\<cr>", 'tx') + call assert_equal(' 8 them', getline('.')) + :1 + " eigth match + call feedkeys("/the".repeat("\<C-G>", 7)."\<cr>", 'tx') + call assert_equal(' 9 these', getline('.')) + :1 + " back at first match + call feedkeys("/the".repeat("\<C-G>", 8)."\<cr>", 'tx') + call assert_equal(' 2 these', getline('.')) + + " Test 4 + " CTRL-T goes to the previous match + set incsearch nowrapscan + $ + " first match + call feedkeys("?the\<cr>", 'tx') + call assert_equal(' 9 these', getline('.')) + $ + " first match + call feedkeys("?the\<C-G>\<cr>", 'tx') + call assert_equal(' 9 these', getline('.')) + $ + " second match + call feedkeys("?the".repeat("\<C-T>", 1)."\<cr>", 'tx') + call assert_equal(' 8 them', getline('.')) + $ + " last match + call feedkeys("?the".repeat("\<C-T>", 7)."\<cr>", 'tx') + call assert_equal(' 2 these', getline('.')) + $ + " last match + call feedkeys("?the".repeat("\<C-T>", 8)."\<cr>", 'tx') + call assert_equal(' 2 these', getline('.')) + + " Test 5 + " CTRL-T goes to the previous match + set incsearch wrapscan + $ + " first match + call feedkeys("?the\<cr>", 'tx') + call assert_equal(' 9 these', getline('.')) + $ + " first match at the top + call feedkeys("?the\<C-G>\<cr>", 'tx') + call assert_equal(' 2 these', getline('.')) + $ + " second match + call feedkeys("?the".repeat("\<C-T>", 1)."\<cr>", 'tx') + call assert_equal(' 8 them', getline('.')) + $ + " last match + call feedkeys("?the".repeat("\<C-T>", 7)."\<cr>", 'tx') + call assert_equal(' 2 these', getline('.')) + $ + " back at the bottom of the buffer + call feedkeys("?the".repeat("\<C-T>", 8)."\<cr>", 'tx') + call assert_equal(' 9 these', getline('.')) + + " Test 6 + " CTRL-L adds to the search pattern + set incsearch wrapscan + 1 + " first match + call feedkeys("/the\<c-l>\<cr>", 'tx') + call assert_equal(' 2 these', getline('.')) + 1 + " go to next match of 'thes' + call feedkeys("/the\<c-l>\<C-G>\<cr>", 'tx') + call assert_equal(' 9 these', getline('.')) + 1 + " wrap around + call feedkeys("/the\<c-l>\<C-G>\<C-G>\<cr>", 'tx') + call assert_equal(' 2 these', getline('.')) + 1 + " wrap around + set nowrapscan + call feedkeys("/the\<c-l>\<C-G>\<C-G>\<cr>", 'tx') + call assert_equal(' 9 these', getline('.')) + + " Test 7 + " <bs> remove from match, but stay at current match + set incsearch wrapscan + 1 + " first match + call feedkeys("/thei\<cr>", 'tx') + call assert_equal(' 4 their', getline('.')) + 1 + " delete one char, add another + call feedkeys("/thei\<bs>s\<cr>", 'tx') + call assert_equal(' 2 these', getline('.')) + 1 + " delete one char, add another, go to previous match, add one char + call feedkeys("/thei\<bs>s\<bs>\<C-T>\<c-l>\<cr>", 'tx') + call assert_equal(' 9 these', getline('.')) + 1 + " delete all chars, start from the beginning again + call feedkeys("/them". repeat("\<bs>",4).'the\>'."\<cr>", 'tx') + call assert_equal(' 3 the', getline('.')) + + " clean up + call test_disable_char_avail(0) + bw! +endfunc + +func Test_search_cmdline2() + " See test/functional/legacy/search_spec.lua + throw 'skipped: Nvim does not support test_disable_char_avail()' + if !exists('+incsearch') + return + endif + " need to disable char_avail, + " so that expansion of commandline works + call test_disable_char_avail(1) + new + call setline(1, [' 1', ' 2 these', ' 3 the theother']) + " Test 1 + " Ctrl-T goes correctly back and forth + set incsearch + 1 + " first match + call feedkeys("/the\<cr>", 'tx') + call assert_equal(' 2 these', getline('.')) + 1 + " go to next match (on next line) + call feedkeys("/the\<C-G>\<cr>", 'tx') + call assert_equal(' 3 the theother', getline('.')) + 1 + " go to next match (still on line 3) + call feedkeys("/the\<C-G>\<C-G>\<cr>", 'tx') + call assert_equal(' 3 the theother', getline('.')) + 1 + " go to next match (still on line 3) + call feedkeys("/the\<C-G>\<C-G>\<C-G>\<cr>", 'tx') + call assert_equal(' 3 the theother', getline('.')) + 1 + " go to previous match (on line 3) + call feedkeys("/the\<C-G>\<C-G>\<C-G>\<C-T>\<cr>", 'tx') + call assert_equal(' 3 the theother', getline('.')) + 1 + " go to previous match (on line 3) + call feedkeys("/the\<C-G>\<C-G>\<C-G>\<C-T>\<C-T>\<cr>", 'tx') + call assert_equal(' 3 the theother', getline('.')) + 1 + " go to previous match (on line 2) + call feedkeys("/the\<C-G>\<C-G>\<C-G>\<C-T>\<C-T>\<C-T>\<cr>", 'tx') + call assert_equal(' 2 these', getline('.')) + + " Test 2: keep the view, + " after deleting a character from the search cmd + call setline(1, [' 1', ' 2 these', ' 3 the', ' 4 their', ' 5 there', ' 6 their', ' 7 the', ' 8 them', ' 9 these', ' 10 foobar']) + resize 5 + 1 + call feedkeys("/foo\<bs>\<cr>", 'tx') + redraw + call assert_equal({'lnum': 10, 'leftcol': 0, 'col': 4, 'topfill': 0, 'topline': 6, 'coladd': 0, 'skipcol': 0, 'curswant': 4}, winsaveview()) + + " remove all history entries + for i in range(10) + call histdel('/') + endfor + + " Test 3: reset the view, + " after deleting all characters from the search cmd + norm! 1gg0 + " unfortunately, neither "/foo\<c-w>\<cr>", nor "/foo\<bs>\<bs>\<bs>\<cr>", + " nor "/foo\<c-u>\<cr>" works to delete the commandline. + " In that case Vim should return "E35 no previous regular expression", + " but it looks like Vim still sees /foo and therefore the test fails. + " Therefore, disableing this test + "call assert_fails(feedkeys("/foo\<c-w>\<cr>", 'tx'), 'E35') + "call assert_equal({'lnum': 1, 'leftcol': 0, 'col': 0, 'topfill': 0, 'topline': 1, 'coladd': 0, 'skipcol': 0, 'curswant': 0}, winsaveview()) + + " clean up + set noincsearch + call test_disable_char_avail(0) + bw! +endfunc + +func Test_use_sub_pat() + split + let @/ = '' + func X() + s/^/a/ + / + endfunc + call X() + bwipe! +endfunc + +func Test_searchpair() + new + call setline(1, ['other code here', '', '[', '" cursor here', ']']) + 4 + let a=searchpair('\[','',']','bW') + call assert_equal(3, a) + set nomagic + 4 + let a=searchpair('\[','',']','bW') + call assert_equal(3, a) + set magic + q! +endfunc + diff --git a/src/nvim/testdir/test_smartindent.vim b/src/nvim/testdir/test_smartindent.vim new file mode 100644 index 0000000000..d00eac9798 --- /dev/null +++ b/src/nvim/testdir/test_smartindent.vim @@ -0,0 +1,14 @@ + +" Tests for not doing smart indenting when it isn't set. +function! Test_nosmartindent() + new + call append(0, [" some test text", + \ " test text", + \ "test text", + \ " test text"]) + set nocindent nosmartindent autoindent + exe "normal! gg/some\<CR>" + exe "normal! 2cc#test\<Esc>" + call assert_equal(" #test", getline(1)) + enew! | close +endfunction diff --git a/src/nvim/testdir/test_source_utf8.vim b/src/nvim/testdir/test_source_utf8.vim new file mode 100644 index 0000000000..edb76fc43d --- /dev/null +++ b/src/nvim/testdir/test_source_utf8.vim @@ -0,0 +1,33 @@ +" Test the :source! command +if !has('multi_byte') + finish +endif + +func Test_source_utf8() + " check that sourcing a script with 0x80 as second byte works + new + call setline(1, [':%s/ร x/--ร 1234--/g', ':%s/รx/--ร1234--/g']) + write! Xscript + bwipe! + new + call setline(1, [' ร x ', ' รx ']) + source! Xscript | echo + call assert_equal(' --ร 1234-- ', getline(1)) + call assert_equal(' --ร1234-- ', getline(2)) + bwipe! + call delete('Xscript') +endfunc + +func Test_source_latin() + " check that sourcing a latin1 script with a 0xc0 byte works + new + call setline(1, ["call feedkeys('r')", "call feedkeys('\xc0', 'xt')"]) + write! Xscript + bwipe! + new + call setline(1, ['xxx']) + source Xscript + call assert_equal("\u00c0xx", getline(1)) + bwipe! + call delete('Xscript') +endfunc diff --git a/src/nvim/testdir/test_startup.vim b/src/nvim/testdir/test_startup.vim new file mode 100644 index 0000000000..11e26d03aa --- /dev/null +++ b/src/nvim/testdir/test_startup.vim @@ -0,0 +1,242 @@ +" Tests for startup. + +source shared.vim + +" Check that loading startup.vim works. +func Test_startup_script() + throw 'skipped: Nvim does not need defaults.vim' + set compatible + source $VIMRUNTIME/defaults.vim + + call assert_equal(0, &compatible) +endfunc + +" Verify the order in which plugins are loaded: +" 1. plugins in non-after directories +" 2. packages +" 3. plugins in after directories +func Test_after_comes_later() + if !has('packages') + return + endif + let before = [ + \ 'set nocp viminfo+=nviminfo', + \ 'set guioptions+=M', + \ 'let $HOME = "/does/not/exist"', + \ 'set loadplugins', + \ 'set rtp=Xhere,Xafter,Xanother', + \ 'set packpath=Xhere,Xafter', + \ 'set nomore', + \ 'let g:sequence = ""', + \ ] + let after = [ + \ 'redir! > Xtestout', + \ 'scriptnames', + \ 'redir END', + \ 'redir! > Xsequence', + \ 'echo g:sequence', + \ 'redir END', + \ 'quit', + \ ] + call mkdir('Xhere/plugin', 'p') + call writefile(['let g:sequence .= "here "'], 'Xhere/plugin/here.vim') + call mkdir('Xanother/plugin', 'p') + call writefile(['let g:sequence .= "another "'], 'Xanother/plugin/another.vim') + call mkdir('Xhere/pack/foo/start/foobar/plugin', 'p') + call writefile(['let g:sequence .= "pack "'], 'Xhere/pack/foo/start/foobar/plugin/foo.vim') + + call mkdir('Xafter/plugin', 'p') + call writefile(['let g:sequence .= "after "'], 'Xafter/plugin/later.vim') + + if RunVim(before, after, '') + + let lines = readfile('Xtestout') + let expected = ['Xbefore.vim', 'here.vim', 'another.vim', 'foo.vim', 'later.vim', 'Xafter.vim'] + let found = [] + for line in lines + for one in expected + if line =~ one + call add(found, one) + endif + endfor + endfor + call assert_equal(expected, found) + endif + + call assert_equal('here another pack after', substitute(join(readfile('Xsequence', 1), ''), '\s\+$', '', '')) + + call delete('Xtestout') + call delete('Xsequence') + call delete('Xhere', 'rf') + call delete('Xanother', 'rf') + call delete('Xafter', 'rf') +endfunc + +func Test_pack_in_rtp_when_plugins_run() + if !has('packages') + return + endif + let before = [ + \ 'set nocp viminfo+=nviminfo', + \ 'set guioptions+=M', + \ 'let $HOME = "/does/not/exist"', + \ 'set loadplugins', + \ 'set rtp=Xhere', + \ 'set packpath=Xhere', + \ 'set nomore', + \ ] + let after = [ + \ 'quit', + \ ] + call mkdir('Xhere/plugin', 'p') + call writefile(['redir! > Xtestout', 'silent set runtimepath?', 'silent! call foo#Trigger()', 'redir END'], 'Xhere/plugin/here.vim') + call mkdir('Xhere/pack/foo/start/foobar/autoload', 'p') + call writefile(['function! foo#Trigger()', 'echo "autoloaded foo"', 'endfunction'], 'Xhere/pack/foo/start/foobar/autoload/foo.vim') + + if RunVim(before, after, '') + + let lines = filter(readfile('Xtestout'), '!empty(v:val)') + call assert_match('Xhere[/\\]pack[/\\]foo[/\\]start[/\\]foobar', get(lines, 0)) + call assert_match('autoloaded foo', get(lines, 1)) + endif + + call delete('Xtestout') + call delete('Xhere', 'rf') +endfunc + +func Test_help_arg() + if !has('unix') && has('gui') + " this doesn't work with gvim on MS-Windows + return + endif + if RunVim([], [], '--help >Xtestout') + let lines = readfile('Xtestout') + call assert_true(len(lines) > 20) + call assert_match('Usage:', lines[0]) + + " check if couple of lines are there + let found = [] + for line in lines + if line =~ '-R.*Read-only mode' + call add(found, 'Readonly mode') + endif + " Watch out for a second --version line in the Gnome version. + if line =~ '--version.*Print version information' + call add(found, "--version") + endif + endfor + call assert_equal(['Readonly mode', '--version'], found) + endif + call delete('Xtestout') +endfunc + +func Test_compatible_args() + throw "skipped: Nvim is always 'nocompatible'" + let after = [ + \ 'call writefile([string(&compatible)], "Xtestout")', + \ 'set viminfo+=nviminfo', + \ 'quit', + \ ] + if RunVim([], after, '-C') + let lines = readfile('Xtestout') + call assert_equal('1', lines[0]) + endif + + if RunVim([], after, '-N') + let lines = readfile('Xtestout') + call assert_equal('0', lines[0]) + endif + + call delete('Xtestout') +endfunc + +func Test_file_args() + let after = [ + \ 'call writefile(argv(), "Xtestout")', + \ 'qall', + \ ] + if RunVim([], after, '') + let lines = readfile('Xtestout') + call assert_equal(0, len(lines)) + endif + + if RunVim([], after, 'one') + let lines = readfile('Xtestout') + call assert_equal(1, len(lines)) + call assert_equal('one', lines[0]) + endif + + if RunVim([], after, 'one two three') + let lines = readfile('Xtestout') + call assert_equal(3, len(lines)) + call assert_equal('one', lines[0]) + call assert_equal('two', lines[1]) + call assert_equal('three', lines[2]) + endif + + if RunVim([], after, 'one -c echo two') + let lines = readfile('Xtestout') + call assert_equal(2, len(lines)) + call assert_equal('one', lines[0]) + call assert_equal('two', lines[1]) + endif + + if RunVim([], after, 'one -- -c echo two') + let lines = readfile('Xtestout') + call assert_equal(4, len(lines)) + call assert_equal('one', lines[0]) + call assert_equal('-c', lines[1]) + call assert_equal('echo', lines[2]) + call assert_equal('two', lines[3]) + endif + + call delete('Xtestout') +endfunc + +func Test_startuptime() + if !has('startuptime') + return + endif + let after = ['qall'] + if RunVim([], after, '--startuptime Xtestout one') + let lines = readfile('Xtestout') + let expected = ['parsing arguments', 'inits 3', 'opening buffers'] + let found = [] + for line in lines + for exp in expected + if line =~ exp + call add(found, exp) + endif + endfor + endfor + call assert_equal(expected, found) + endif + call delete('Xtestout') +endfunc + +func Test_read_stdin() + let after = [ + \ 'write Xtestout', + \ 'quit!', + \ ] + if RunVimPiped([], after, '-', 'echo something | ') + let lines = readfile('Xtestout') + " MS-Windows adds a space after the word + call assert_equal(['something'], split(lines[0])) + endif + call delete('Xtestout') +endfunc + +func Test_progpath() + " Tests normally run with "./vim" or "../vim", these must have been expanded + " to a full path. + if has('unix') + call assert_equal('/', v:progpath[0]) + elseif has('win32') + call assert_equal(':', v:progpath[1]) + call assert_match('[/\\]', v:progpath[2]) + endif + + " Only expect "vim" to appear in v:progname. + call assert_match('vim\c', v:progname) +endfunc diff --git a/src/nvim/testdir/test_startup_utf8.vim b/src/nvim/testdir/test_startup_utf8.vim new file mode 100644 index 0000000000..d179a4cc79 --- /dev/null +++ b/src/nvim/testdir/test_startup_utf8.vim @@ -0,0 +1,64 @@ +" Tests for startup using utf-8. +if !has('multi_byte') + finish +endif + +source shared.vim + +func Test_read_stdin_utf8() + let linesin = ['ใในใ', 'โฌรรรรร'] + call writefile(linesin, 'Xtestin') + let before = [ + \ 'set enc=utf-8', + \ 'set fencs=cp932,utf-8', + \ ] + let after = [ + \ 'write ++enc=utf-8 Xtestout', + \ 'quit!', + \ ] + if has('win32') + let pipecmd = 'type Xtestin | ' + else + let pipecmd = 'cat Xtestin | ' + endif + if RunVimPiped(before, after, '-', pipecmd) + let lines = readfile('Xtestout') + call assert_equal(linesin, lines) + else + call assert_equal('', 'RunVimPiped failed.') + endif + call delete('Xtestout') + call delete('Xtestin') +endfunc + +func Test_read_fifo_utf8() + if !has('unix') + return + endif + " Using bash/zsh's process substitution. + if executable('bash') + set shell=bash + elseif executable('zsh') + set shell=zsh + else + return + endif + let linesin = ['ใในใ', 'โฌรรรรร'] + call writefile(linesin, 'Xtestin') + let before = [ + \ 'set enc=utf-8', + \ 'set fencs=cp932,utf-8', + \ ] + let after = [ + \ 'write ++enc=utf-8 Xtestout', + \ 'quit!', + \ ] + if RunVim(before, after, '<(cat Xtestin)') + let lines = readfile('Xtestout') + call assert_equal(linesin, lines) + else + call assert_equal('', 'RunVim failed.') + endif + call delete('Xtestout') + call delete('Xtestin') +endfunc diff --git a/src/nvim/testdir/test_stat.vim b/src/nvim/testdir/test_stat.vim new file mode 100644 index 0000000000..89ca9ef379 --- /dev/null +++ b/src/nvim/testdir/test_stat.vim @@ -0,0 +1,64 @@ +" Tests for stat functions and checktime + +func Test_existent_file() + let fname='Xtest.tmp' + + let ts=localtime() + sleep 1 + let fl=['Hello World!'] + call writefile(fl, fname) + let tf=getftime(fname) + sleep 1 + let te=localtime() + + call assert_true(ts <= tf && tf <= te) + call assert_equal(strlen(fl[0] . "\n"), getfsize(fname)) + call assert_equal('file', getftype(fname)) + call assert_equal('rw-', getfperm(fname)[0:2]) +endfunc + +func Test_existent_directory() + let dname='.' + + call assert_equal(0, getfsize(dname)) + call assert_equal('dir', getftype(dname)) + call assert_equal('rwx', getfperm(dname)[0:2]) +endfunc + +func Test_checktime() + let fname='Xtest.tmp' + + let fl=['Hello World!'] + call writefile(fl, fname) + set autoread + exec 'e' fname + sleep 2 + let fl=readfile(fname) + let fl[0] .= ' - checktime' + call writefile(fl, fname) + checktime + call assert_equal(fl[0], getline(1)) +endfunc + +func Test_nonexistent_file() + let fname='Xtest.tmp' + + call delete(fname) + call assert_equal(-1, getftime(fname)) + call assert_equal(-1, getfsize(fname)) + call assert_equal('', getftype(fname)) + call assert_equal('', getfperm(fname)) +endfunc + +func Test_win32_symlink_dir() + " On Windows, non-admin users cannot create symlinks. + " So we use an existing symlink for this test. + if has('win32') + " Check if 'C:\Users\All Users' is a symlink to a directory. + let res=system('dir C:\Users /a') + if match(res, '\C<SYMLINKD> *All Users') >= 0 + " Get the filetype of the symlink. + call assert_equal('dir', getftype('C:\Users\All Users')) + endif + endif +endfunc diff --git a/src/nvim/testdir/test_substitute.vim b/src/nvim/testdir/test_substitute.vim new file mode 100644 index 0000000000..e2b6de03c3 --- /dev/null +++ b/src/nvim/testdir/test_substitute.vim @@ -0,0 +1,41 @@ +" Tests for multi-line regexps with ":s". + +function! Test_multiline_subst() + enew! + call append(0, ["1 aa", + \ "bb", + \ "cc", + \ "2 dd", + \ "ee", + \ "3 ef", + \ "gh", + \ "4 ij", + \ "5 a8", + \ "8b c9", + \ "9d", + \ "6 e7", + \ "77f", + \ "xxxxx"]) + + 1 + " test if replacing a line break works with a back reference + /^1/,/^2/s/\n\(.\)/ \1/ + " test if inserting a line break works with a back reference + /^3/,/^4/s/\(.\)$/\r\1/ + " test if replacing a line break with another line break works + /^5/,/^6/s/\(\_d\{3}\)/x\1x/ + call assert_equal('1 aa bb cc 2 dd ee', getline(1)) + call assert_equal('3 e', getline(2)) + call assert_equal('f', getline(3)) + call assert_equal('g', getline(4)) + call assert_equal('h', getline(5)) + call assert_equal('4 i', getline(6)) + call assert_equal('j', getline(7)) + call assert_equal('5 ax8', getline(8)) + call assert_equal('8xb cx9', getline(9)) + call assert_equal('9xd', getline(10)) + call assert_equal('6 ex7', getline(11)) + call assert_equal('7x7f', getline(12)) + call assert_equal('xxxxx', getline(13)) + enew! +endfunction diff --git a/src/nvim/testdir/test_syn_attr.vim b/src/nvim/testdir/test_syn_attr.vim index 94d6b8735f..64aab3411d 100644 --- a/src/nvim/testdir/test_syn_attr.vim +++ b/src/nvim/testdir/test_syn_attr.vim @@ -20,7 +20,7 @@ func Test_missing_attr() if fontname == '' let fontname = 'something' endif - exe 'hi Mine guifg=blue guibg=red font=' . escape(fontname, ' \') + exe "hi Mine guifg=blue guibg=red font='" . fontname . "'" call assert_equal('blue', synIDattr(hlID("Mine"), "fg", 'gui')) call assert_equal('red', synIDattr(hlID("Mine"), "bg", 'gui')) call assert_equal(fontname, synIDattr(hlID("Mine"), "font", 'gui')) diff --git a/src/nvim/testdir/test_tabpage.vim b/src/nvim/testdir/test_tabpage.vim index 7c3039ba24..33139fcda0 100644 --- a/src/nvim/testdir/test_tabpage.vim +++ b/src/nvim/testdir/test_tabpage.vim @@ -11,6 +11,7 @@ function Test_tabpage() 0tabnew 1tabnew $tabnew + %del tabdo call append(line('$'), tabpagenr()) tabclose! 2 tabrewind @@ -93,10 +94,6 @@ function Test_tabpage() call assert_equal(7, tabpagenr()) tabmove call assert_equal(10, tabpagenr()) - tabmove -20 - call assert_equal(1, tabpagenr()) - tabmove +20 - call assert_equal(10, tabpagenr()) 0tabmove call assert_equal(1, tabpagenr()) $tabmove @@ -109,7 +106,16 @@ function Test_tabpage() call assert_equal(4, tabpagenr()) 7tabmove 5 call assert_equal(5, tabpagenr()) + call assert_fails("99tabmove", 'E16:') + call assert_fails("+99tabmove", 'E16:') + call assert_fails("-99tabmove", 'E16:') call assert_fails("tabmove foo", 'E474:') + call assert_fails("tabmove 99", 'E474:') + call assert_fails("tabmove +99", 'E474:') + call assert_fails("tabmove -99", 'E474:') + call assert_fails("tabmove -3+", 'E474:') + call assert_fails("tabmove $3", 'E474:') + 1tabonly! endfunc " Test autocommands @@ -117,7 +123,6 @@ function Test_tabpage_with_autocmd() if !has('autocmd') return endif - tabonly! command -nargs=1 -bar C :call add(s:li, '=== ' . <q-args> . ' ===')|<args> augroup TestTabpageGroup au! @@ -182,8 +187,10 @@ function Test_tabpage_with_autocmd() autocmd TabDestructive TabEnter * nested :C tabnext 2 | C tabclose 3 let s:li = [] - C tabnext 3 - call assert_equal(['=== tabnext 3 ===', 'BufLeave', 'WinLeave', 'TabLeave', 'WinEnter', 'TabEnter', '=== tabnext 2 ===', 'BufLeave', 'WinLeave', 'TabLeave', 'WinEnter', 'TabEnter', '=== tabnext 2 ===', '=== tabclose 3 ===', 'BufEnter', '=== tabclose 3 ==='], s:li) + call assert_equal(3, tabpagenr('$')) + C tabnext 2 + call assert_equal(2, tabpagenr('$')) + call assert_equal(['=== tabnext 2 ===', 'WinLeave', 'TabLeave', 'WinEnter', 'TabEnter', '=== tabnext 2 ===', '=== tabclose 3 ==='], s:li) call assert_equal(['2/2'], [tabpagenr().'/'.tabpagenr('$')]) delcommand C @@ -191,8 +198,7 @@ function Test_tabpage_with_autocmd() augroup! TabDestructive autocmd! TestTabpageGroup augroup! TestTabpageGroup - tabonly! - bw! + 1tabonly! endfunction function Test_tabpage_with_tab_modifier() @@ -204,7 +210,7 @@ function Test_tabpage_with_tab_modifier() exec 'tabnext ' . a:pre_nr exec a:cmd call assert_equal(a:post_nr, tabpagenr()) - call assert_equal('help', &filetype) + call assert_equal('help', &buftype) helpclose endfunc @@ -223,8 +229,223 @@ function Test_tabpage_with_tab_modifier() call assert_fails('-99tab help', 'E16:') delfunction s:check_tab - tabonly! - bw! + 1tabonly! +endfunction + +function Check_tab_count(pre_nr, cmd, post_nr) + exec 'tabnext' a:pre_nr + normal! G + exec a:cmd + call assert_equal(a:post_nr, tabpagenr(), a:cmd) +endfunc + +" Test for [count] of tabnext +function Test_tabpage_with_tabnext() + for n in range(4) + tabedit + call setline(1, ['', '', '3']) + endfor + + call Check_tab_count(1, 'tabnext', 2) + call Check_tab_count(1, '3tabnext', 3) + call Check_tab_count(1, '.tabnext', 1) + call Check_tab_count(1, '.+1tabnext', 2) + call Check_tab_count(2, '+tabnext', 3) + call Check_tab_count(2, '+2tabnext', 4) + call Check_tab_count(4, '-tabnext', 3) + call Check_tab_count(4, '-2tabnext', 2) + call Check_tab_count(3, '$tabnext', 5) + call assert_fails('0tabnext', 'E16:') + call assert_fails('99tabnext', 'E16:') + call assert_fails('+99tabnext', 'E16:') + call assert_fails('-99tabnext', 'E16:') + call Check_tab_count(1, 'tabnext 3', 3) + call Check_tab_count(2, 'tabnext +', 3) + call Check_tab_count(2, 'tabnext +2', 4) + call Check_tab_count(4, 'tabnext -', 3) + call Check_tab_count(4, 'tabnext -2', 2) + call Check_tab_count(3, 'tabnext $', 5) + call assert_fails('tabnext 0', 'E474:') + call assert_fails('tabnext .', 'E474:') + call assert_fails('tabnext -+', 'E474:') + call assert_fails('tabnext +2-', 'E474:') + call assert_fails('tabnext $3', 'E474:') + call assert_fails('tabnext 99', 'E474:') + call assert_fails('tabnext +99', 'E474:') + call assert_fails('tabnext -99', 'E474:') + + 1tabonly! +endfunction + +" Test for [count] of tabprevious +function Test_tabpage_with_tabprevious() + for n in range(5) + tabedit + call setline(1, ['', '', '3']) + endfor + + for cmd in ['tabNext', 'tabprevious'] + call Check_tab_count(6, cmd, 5) + call Check_tab_count(6, '3' . cmd, 3) + call Check_tab_count(6, '8' . cmd, 4) + call Check_tab_count(6, cmd . ' 3', 3) + call Check_tab_count(6, cmd . ' 8', 4) + for n in range(2) + for c in ['0', '.+3', '+', '+2' , '-', '-2' , '$', '+99', '-99'] + if n == 0 " pre count + let entire_cmd = c . cmd + let err_code = 'E16:' + else + let entire_cmd = cmd . ' ' . c + let err_code = 'E474:' + endif + call assert_fails(entire_cmd, err_code) + endfor + endfor + endfor + + 1tabonly! +endfunction + +function s:reconstruct_tabpage_for_test(nr) + let n = (a:nr > 2) ? a:nr - 2 : 1 + 1tabonly! + 0tabedit n0 + for n in range(1, n) + exec '$tabedit n' . n + if n == 1 + call setline(1, ['', '', '3']) + endif + endfor +endfunc + +" Test for [count] of tabclose +function Test_tabpage_with_tabclose() + + " pre count + call s:reconstruct_tabpage_for_test(6) + call Check_tab_count(3, 'tabclose!', 3) + call Check_tab_count(1, '3tabclose', 1) + call Check_tab_count(4, '4tabclose', 3) + call Check_tab_count(3, '1tabclose', 2) + call Check_tab_count(2, 'tabclose', 1) + call assert_equal(1, tabpagenr('$')) + call assert_equal('', bufname('')) + + call s:reconstruct_tabpage_for_test(6) + call Check_tab_count(2, '$tabclose', 2) + call Check_tab_count(4, '.tabclose', 4) + call Check_tab_count(3, '.+tabclose', 3) + call Check_tab_count(3, '.-2tabclose', 2) + call Check_tab_count(1, '.+1tabclose!', 1) + call assert_equal(1, tabpagenr('$')) + call assert_equal('', bufname('')) + + " post count + call s:reconstruct_tabpage_for_test(6) + call Check_tab_count(3, 'tabclose!', 3) + call Check_tab_count(1, 'tabclose 3', 1) + call Check_tab_count(4, 'tabclose 4', 3) + call Check_tab_count(3, 'tabclose 1', 2) + call Check_tab_count(2, 'tabclose', 1) + call assert_equal(1, tabpagenr('$')) + call assert_equal('', bufname('')) + + call s:reconstruct_tabpage_for_test(6) + call Check_tab_count(2, 'tabclose $', 2) + call Check_tab_count(4, 'tabclose', 4) + call Check_tab_count(3, 'tabclose +', 3) + call Check_tab_count(3, 'tabclose -2', 2) + call Check_tab_count(1, 'tabclose! +1', 1) + call assert_equal(1, tabpagenr('$')) + call assert_equal('', bufname('')) + + call s:reconstruct_tabpage_for_test(6) + for n in range(2) + for c in ['0', '$3', '99', '+99', '-99'] + if n == 0 " pre count + let entire_cmd = c . 'tabclose' + let err_code = 'E16:' + else + let entire_cmd = 'tabclose ' . c + let err_code = 'E474:' + endif + call assert_fails(entire_cmd, err_code) + call assert_equal(6, tabpagenr('$')) + endfor + endfor + + call assert_fails('3tabclose', 'E37:') + call assert_fails('tabclose 3', 'E37:') + call assert_fails('tabclose -+', 'E474:') + call assert_fails('tabclose +2-', 'E474:') + call assert_equal(6, tabpagenr('$')) + + 1tabonly! +endfunction + +" Test for [count] of tabonly +function Test_tabpage_with_tabonly() + + " Test for the normal behavior (pre count only) + let tc = [ [4, '.', '!'], [2, '.+', ''], [3, '.-2', '!'], [1, '.+1', '!'] ] + for c in tc + call s:reconstruct_tabpage_for_test(6) + let entire_cmd = c[1] . 'tabonly' . c[2] + call Check_tab_count(c[0], entire_cmd, 1) + call assert_equal(1, tabpagenr('$')) + endfor + + " Test for the normal behavior + let tc2 = [ [3, '', ''], [1, '3', ''], [4, '4', '!'], [3, '1', '!'], + \ [2, '', '!'], + \ [2, '$', '!'], [3, '+', '!'], [3, '-2', '!'], [3, '+1', '!'] + \ ] + for n in range(2) + for c in tc2 + call s:reconstruct_tabpage_for_test(6) + if n == 0 " pre count + let entire_cmd = c[1] . 'tabonly' . c[2] + else + let entire_cmd = 'tabonly' . c[2] . ' ' . c[1] + endif + call Check_tab_count(c[0], entire_cmd, 1) + call assert_equal(1, tabpagenr('$')) + endfor + endfor + + " Test for the error behavior + for n in range(2) + for c in ['0', '$3', '99', '+99', '-99'] + call s:reconstruct_tabpage_for_test(6) + if n == 0 " pre count + let entire_cmd = c . 'tabonly' + let err_code = 'E16:' + else + let entire_cmd = 'tabonly ' . c + let err_code = 'E474:' + endif + call assert_fails(entire_cmd, err_code) + call assert_equal(6, tabpagenr('$')) + endfor + endfor + + " Test for the error behavior (post count only) + for c in tc + call s:reconstruct_tabpage_for_test(6) + let entire_cmd = 'tabonly' . c[2] . ' ' . c[1] + let err_code = 'E474:' + call assert_fails(entire_cmd, err_code) + call assert_equal(6, tabpagenr('$')) + endfor + + call assert_fails('tabonly -+', 'E474:') + call assert_fails('tabonly +2-', 'E474:') + call assert_equal(6, tabpagenr('$')) + + 1tabonly! + new + only! endfunction func Test_tabnext_on_buf_unload1() diff --git a/src/nvim/testdir/test_tagcase.vim b/src/nvim/testdir/test_tagcase.vim new file mode 100644 index 0000000000..833cb9f990 --- /dev/null +++ b/src/nvim/testdir/test_tagcase.vim @@ -0,0 +1,73 @@ +" test 'tagcase' option + +func Test_tagcase() + call writefile(["Bar\tXtext\t3", "Foo\tXtext\t2", "foo\tXtext\t4"], 'Xtags') + set tags=Xtags + e Xtext + + for &ic in [0, 1] + for &scs in [0, 1] + for &g:tc in ["followic", "ignore", "match", "followscs", "smart"] + for &l:tc in ["", "followic", "ignore", "match", "followscs", "smart"] + let smart = 0 + if &l:tc != '' + let tc = &l:tc + else + let tc = &g:tc + endif + if tc == 'followic' + let ic = &ic + elseif tc == 'ignore' + let ic = 1 + elseif tc == 'followscs' + let ic = &ic + let smart = &scs + elseif tc == 'smart' + let ic = 1 + let smart = 1 + else + let ic = 0 + endif + if ic && smart + call assert_equal(['foo', 'Foo'], map(taglist("^foo$"), {i, v -> v.name})) + call assert_equal(['Foo'], map(taglist("^Foo$"), {i, v -> v.name})) + elseif ic + call assert_equal(['foo', 'Foo'], map(taglist("^foo$"), {i, v -> v.name})) + call assert_equal(['Foo', 'foo'], map(taglist("^Foo$"), {i, v -> v.name})) + else + call assert_equal(['foo'], map(taglist("^foo$"), {i, v -> v.name})) + call assert_equal(['Foo'], map(taglist("^Foo$"), {i, v -> v.name})) + endif + endfor + endfor + endfor + endfor + + call delete('Xtags') + set ic& + setg tc& + setl tc& + set scs& +endfunc + +func Test_set_tagcase() + " Verify default values. + set ic& + setg tc& + setl tc& + call assert_equal(0, &ic) + call assert_equal('followic', &g:tc) + call assert_equal('followic', &l:tc) + call assert_equal('followic', &tc) + + " Verify that the local setting accepts <empty> but that the global setting + " does not. The first of these (setting the local value to <empty>) should + " succeed; the other two should fail. + setl tc= + call assert_fails('setg tc=', 'E474:') + call assert_fails('set tc=', 'E474:') + + set ic& + setg tc& + setl tc& +endfunc diff --git a/src/nvim/testdir/test_tagjump.vim b/src/nvim/testdir/test_tagjump.vim index d8a333f44c..0d697b3f3e 100644 --- a/src/nvim/testdir/test_tagjump.vim +++ b/src/nvim/testdir/test_tagjump.vim @@ -6,4 +6,93 @@ func Test_ptag_with_notagstack() call assert_fails('ptag does_not_exist_tag_name', 'E426') set tagstack&vim endfunc -" vim: sw=2 et + +func Test_cancel_ptjump() + set tags=Xtags + call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", + \ "word\tfile1\tcmd1", + \ "word\tfile2\tcmd2"], + \ 'Xtags') + + only! + call feedkeys(":ptjump word\<CR>\<CR>", "xt") + help + call assert_equal(2, winnr('$')) + + call delete('Xtags') + quit +endfunc + +func Test_static_tagjump() + set tags=Xtags + call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", + \ "one\tXfile1\t/^one/;\"\tf\tfile:\tsignature:(void)", + \ "word\tXfile2\tcmd2"], + \ 'Xtags') + new Xfile1 + call setline(1, ['empty', 'one()', 'empty']) + write + tag one + call assert_equal(2, line('.')) + + bwipe! + set tags& + call delete('Xtags') + call delete('Xfile1') +endfunc + +func Test_duplicate_tagjump() + set tags=Xtags + call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", + \ "thesame\tXfile1\t1;\"\td\tfile:", + \ "thesame\tXfile1\t2;\"\td\tfile:", + \ "thesame\tXfile1\t3;\"\td\tfile:", + \ ], + \ 'Xtags') + new Xfile1 + call setline(1, ['thesame one', 'thesame two', 'thesame three']) + write + tag thesame + call assert_equal(1, line('.')) + tnext + call assert_equal(2, line('.')) + tnext + call assert_equal(3, line('.')) + + bwipe! + set tags& + call delete('Xtags') + call delete('Xfile1') +endfunc + +" Tests for [ CTRL-I and CTRL-W CTRL-I commands +function Test_keyword_jump() + call writefile(["#include Xinclude", "", + \ "", + \ "/* test text test tex start here", + \ " some text", + \ " test text", + \ " start OK if found this line", + \ " start found wrong line", + \ "test text"], 'Xtestfile') + call writefile(["/* test text test tex start here", + \ " some text", + \ " test text", + \ " start OK if found this line", + \ " start found wrong line", + \ "test text"], 'Xinclude') + new Xtestfile + call cursor(1,1) + call search("start") + exe "normal! 5[\<C-I>" + call assert_equal(" start OK if found this line", getline('.')) + call cursor(1,1) + call search("start") + exe "normal! 5\<C-W>\<C-I>" + call assert_equal(" start OK if found this line", getline('.')) + enew! | only + call delete('Xtestfile') + call delete('Xinclude') +endfunction + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_taglist.vim b/src/nvim/testdir/test_taglist.vim new file mode 100644 index 0000000000..2d1557ebd9 --- /dev/null +++ b/src/nvim/testdir/test_taglist.vim @@ -0,0 +1,58 @@ +" test 'taglist' function + +func Test_taglist() + call writefile([ + \ "FFoo\tXfoo\t1", + \ "FBar\tXfoo\t2", + \ "BFoo\tXbar\t1", + \ "BBar\tXbar\t2" + \ ], 'Xtags') + set tags=Xtags + split Xtext + + call assert_equal(['FFoo', 'BFoo'], map(taglist("Foo"), {i, v -> v.name})) + call assert_equal(['FFoo', 'BFoo'], map(taglist("Foo", "Xtext"), {i, v -> v.name})) + call assert_equal(['FFoo', 'BFoo'], map(taglist("Foo", "Xfoo"), {i, v -> v.name})) + call assert_equal(['BFoo', 'FFoo'], map(taglist("Foo", "Xbar"), {i, v -> v.name})) + + call delete('Xtags') + bwipe +endfunc + +func Test_taglist_native_etags() + if !has('emacs_tags') + return + endif + call writefile([ + \ "\x0c", + \ "src/os_unix.c,13491", + \ "set_signals(\x7f1335,32699", + \ "reset_signals(\x7f1407,34136", + \ ], 'Xtags') + + set tags=Xtags + + call assert_equal([['set_signals', '1335,32699'], ['reset_signals', '1407,34136']], + \ map(taglist('set_signals'), {i, v -> [v.name, v.cmd]})) + + call delete('Xtags') +endfunc + +func Test_taglist_ctags_etags() + if !has('emacs_tags') + return + endif + call writefile([ + \ "\x0c", + \ "src/os_unix.c,13491", + \ "set_signals(void)\x7fset_signals\x011335,32699", + \ "reset_signals(void)\x7freset_signals\x011407,34136", + \ ], 'Xtags') + + set tags=Xtags + + call assert_equal([['set_signals', '1335,32699'], ['reset_signals', '1407,34136']], + \ map(taglist('set_signals'), {i, v -> [v.name, v.cmd]})) + + call delete('Xtags') +endfunc diff --git a/src/nvim/testdir/test_textobjects.vim b/src/nvim/testdir/test_textobjects.vim new file mode 100644 index 0000000000..630ae5d3a4 --- /dev/null +++ b/src/nvim/testdir/test_textobjects.vim @@ -0,0 +1,43 @@ +" Test for textobjects + +if !has('textobjects') + finish +endif + +function! CpoM(line, useM, expected) + new + + if a:useM + set cpoptions+=M + else + set cpoptions-=M + endif + + call setline(1, a:line) + + call setreg('"', '') + normal! ggfrmavi)y + call assert_equal(getreg('"'), a:expected[0]) + + call setreg('"', '') + normal! `afbmavi)y + call assert_equal(getreg('"'), a:expected[1]) + + call setreg('"', '') + normal! `afgmavi)y + call assert_equal(getreg('"'), a:expected[2]) + + q! +endfunction + +function! Test_inner_block_without_cpo_M() + call CpoM('(red \(blue) green)', 0, ['red \(blue', 'red \(blue', '']) +endfunction + +function! Test_inner_block_with_cpo_M_left_backslash() + call CpoM('(red \(blue) green)', 1, ['red \(blue) green', 'blue', 'red \(blue) green']) +endfunction + +function! Test_inner_block_with_cpo_M_right_backslash() + call CpoM('(red (blue\) green)', 1, ['red (blue\) green', 'blue\', 'red (blue\) green']) +endfunction diff --git a/src/nvim/testdir/test_timers.vim b/src/nvim/testdir/test_timers.vim index d92cbe6897..d377062780 100644 --- a/src/nvim/testdir/test_timers.vim +++ b/src/nvim/testdir/test_timers.vim @@ -4,8 +4,10 @@ if !has('timers') finish endif +source shared.vim + func MyHandler(timer) - let s:val += 1 + let g:val += 1 endfunc func MyHandlerWithLists(lists, timer) @@ -13,43 +15,159 @@ func MyHandlerWithLists(lists, timer) endfunc func Test_oneshot() - let s:val = 0 + let g:val = 0 let timer = timer_start(50, 'MyHandler') - sleep 200m - call assert_equal(1, s:val) + let slept = WaitFor('g:val == 1') + call assert_equal(1, g:val) + if has('reltime') + call assert_inrange(40, 100, slept) + else + call assert_inrange(20, 100, slept) + endif endfunc func Test_repeat_three() - let s:val = 0 + let g:val = 0 let timer = timer_start(50, 'MyHandler', {'repeat': 3}) - sleep 500m - call assert_equal(3, s:val) + let slept = WaitFor('g:val == 3') + call assert_equal(3, g:val) + if has('reltime') + call assert_inrange(120, 250, slept) + else + call assert_inrange(80, 200, slept) + endif endfunc func Test_repeat_many() - let s:val = 0 + let g:val = 0 let timer = timer_start(50, 'MyHandler', {'repeat': -1}) sleep 200m call timer_stop(timer) - call assert_true(s:val > 1) - call assert_true(s:val < 5) + call assert_inrange(2, 4, g:val) endfunc func Test_with_partial_callback() - let s:val = 0 - let s:meow = {} - function s:meow.bite(...) - let s:val += 1 + let g:val = 0 + let meow = {'one': 1} + function meow.bite(...) + let g:val += self.one endfunction - call timer_start(50, s:meow.bite) - sleep 200m - call assert_equal(1, s:val) + call timer_start(50, meow.bite) + let slept = WaitFor('g:val == 1') + call assert_equal(1, g:val) + if has('reltime') + call assert_inrange(40, 130, slept) + else + call assert_inrange(20, 100, slept) + endif endfunc func Test_retain_partial() - call timer_start(100, function('MyHandlerWithLists', [['a']])) + call timer_start(50, function('MyHandlerWithLists', [['a']])) call garbagecollect() + sleep 100m +endfunc + +func Test_info() + let id = timer_start(1000, 'MyHandler') + let info = timer_info(id) + call assert_equal(id, info[0]['id']) + call assert_equal(1000, info[0]['time']) + call assert_equal("function('MyHandler')", string(info[0]['callback'])) + + let found = 0 + for info in timer_info() + if info['id'] == id + let found += 1 + endif + endfor + call assert_equal(1, found) + + call timer_stop(id) + call assert_equal([], timer_info(id)) +endfunc + +func Test_stopall() + let id1 = timer_start(1000, 'MyHandler') + let id2 = timer_start(2000, 'MyHandler') + let info = timer_info() + call assert_equal(2, len(info)) + + call timer_stopall() + let info = timer_info() + call assert_equal(0, len(info)) +endfunc + +func Test_paused() + let g:val = 0 + + let id = timer_start(50, 'MyHandler') + let info = timer_info(id) + call assert_equal(0, info[0]['paused']) + + call timer_pause(id, 1) + let info = timer_info(id) + call assert_equal(1, info[0]['paused']) sleep 200m + call assert_equal(0, g:val) + + call timer_pause(id, 0) + let info = timer_info(id) + call assert_equal(0, info[0]['paused']) + + let slept = WaitFor('g:val == 1') + call assert_equal(1, g:val) + if has('reltime') + call assert_inrange(0, 60, slept) + else + call assert_inrange(0, 10, slept) + endif endfunc -" vim: ts=2 sw=0 et + +func StopMyself(timer) + let g:called += 1 + if g:called == 2 + call timer_stop(a:timer) + endif +endfunc + +func Test_delete_myself() + let g:called = 0 + let t = timer_start(10, 'StopMyself', {'repeat': -1}) + call WaitFor('g:called == 2') + call assert_equal(2, g:called) + call assert_equal([], timer_info(t)) +endfunc + +func StopTimer1(timer) + let g:timer2 = timer_start(10, 'StopTimer2') + " avoid maxfuncdepth error + call timer_pause(g:timer1, 1) + sleep 40m +endfunc + +func StopTimer2(timer) + call timer_stop(g:timer1) +endfunc + +func Test_stop_in_callback() + let g:timer1 = timer_start(10, 'StopTimer1') + sleep 40m +endfunc + +func StopTimerAll(timer) + call timer_stopall() +endfunc + +func Test_stop_all_in_callback() + let g:timer1 = timer_start(10, 'StopTimerAll') + let info = timer_info() + call assert_equal(1, len(info)) + sleep 40m + let info = timer_info() + call assert_equal(0, len(info)) +endfunc + + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_true_false.vim b/src/nvim/testdir/test_true_false.vim new file mode 100644 index 0000000000..84aca737ac --- /dev/null +++ b/src/nvim/testdir/test_true_false.vim @@ -0,0 +1,150 @@ +" Test behavior of boolean-like values. + +" Test what is explained at ":help TRUE" and ":help FALSE". +func Test_if() + if v:false + call assert_true(false, 'v:false is false') + endif + if 0 + call assert_true(false, 'zero is false') + endif + if "0" + call assert_true(false, 'zero string is false') + endif + if "foo" + call assert_true(false, 'foo is false') + endif + if " " + call assert_true(false, 'space is false') + endif + if empty("foo") + call assert_true(false, 'foo is not empty') + endif + + if v:true + else + call assert_true(false, 'v:true is true') + endif + if 1 + else + call assert_true(false, 'one is true') + endif + if "1" + else + call assert_true(false, 'one string is true') + endif + if "1foo" + else + call assert_true(false, 'one in string is true') + endif + + call assert_fails('if [1]', 'E745') + call assert_fails('if {1: 1}', 'E728') + call assert_fails('if function("string")', 'E703') + call assert_fails('if 1.3")', 'E805') +endfunc + +function Try_arg_true_false(expr, false_val, true_val) + for v in ['v:false', '0', '"0"', '"foo"', '" "'] + let r = eval(substitute(a:expr, '%v%', v, '')) + call assert_equal(a:false_val, r, 'result for ' . v . ' is not ' . string(a:false_val) . ' but ' . string(r)) + endfor + for v in ['v:true', '1', '"1"', '"1foo"'] + let r = eval(substitute(a:expr, '%v%', v, '')) + call assert_equal(a:true_val, r, 'result for ' . v . ' is not ' . string(a:true_val) . ' but ' . string(r)) + endfor +endfunc + +" Test using TRUE or FALSE values for an argument. +func Test_true_false_arg() + call Try_arg_true_false('count(["a", "A"], "a", %v%)', 1, 2) + + set wildignore=*.swp + call Try_arg_true_false('expand("foo.swp", %v%)', "", "foo.swp") + call Try_arg_true_false('expand("foo.vim", 0, %v%)', "foo.vim", ["foo.vim"]) + + call setreg('a', ['x', 'y']) + call Try_arg_true_false('getreg("a", 1, %v%)', "x\ny\n", ['x', 'y']) + + set wildignore=*.vim + call Try_arg_true_false('glob("runtest.vim", %v%)', "", "runtest.vim") + set wildignore=*.swp + call Try_arg_true_false('glob("runtest.vim", 0, %v%)', "runtest.vim", ["runtest.vim"]) + if has('unix') + silent !ln -s doesntexit Xlink + call Try_arg_true_false('glob("Xlink", 0, 0, %v%)', "", "Xlink") + silent !rm Xlink + endif + + set wildignore=*.vim + call Try_arg_true_false('globpath(".", "runtest.vim", %v%)', "", "./runtest.vim") + set wildignore=*.swp + call Try_arg_true_false('globpath(".", "runtest.vim", 0, %v%)', "./runtest.vim", ["./runtest.vim"]) + if has('unix') + silent !ln -s doesntexit Xlink + call Try_arg_true_false('globpath(".", "Xlink", 0, 0, %v%)', "", "./Xlink") + silent !rm Xlink + endif + + abbr asdf asdff + call Try_arg_true_false('hasmapto("asdff", "i", %v%)', 0, 1) + + call Try_arg_true_false('index(["a", "A"], "A", 0, %v%)', 1, 0) + + function FilterMapArg(d) + if type(a:d) == type({}) + return filter(a:d, 'v:key == "rhs"') + endif + return a:d + endfunction + call Try_arg_true_false('maparg("asdf", "i", %v%)', "", "asdff") + call Try_arg_true_false('FilterMapArg(maparg("asdf", "i", 1, %v%))', "asdff", {'rhs': 'asdff'}) + + call Try_arg_true_false('hasmapto("asdf", "i", %v%)', 0, 1) + + new colored + call setline(1, '<here>') + syn match brackets "<.*>" + syn match here "here" transparent + let brackets_id = synID(1, 1, 0) + let here_id = synID(1, 3, 0) + call Try_arg_true_false('synID(1, 3, %v%)', here_id, brackets_id) + bwipe! +endfunc + +function Try_arg_non_zero(expr, false_val, true_val) + for v in ['v:false', '0', '[1]', '{2:3}', '3.4'] + let r = eval(substitute(a:expr, '%v%', v, '')) + call assert_equal(a:false_val, r, 'result for ' . v . ' is not ' . a:false_val . ' but ' . r) + endfor + for v in ['v:true', '1', '" "', '"0"'] + let r = eval(substitute(a:expr, '%v%', v, '')) + call assert_equal(a:true_val, r, 'result for ' . v . ' is not ' . a:true_val . ' but ' . r) + endfor +endfunc + + +" Test using non-zero-arg for an argument. +func Test_non_zero_arg() + " call test_settime(93784) + " call Try_arg_non_zero("mode(%v%)", 'x', 'x!') + " call test_settime(0) + + call Try_arg_non_zero("shellescape('foo%', %v%)", "'foo%'", "'foo\\%'") + + " visualmode() needs to be called twice to check + for v in [v:false, 0, [1], {2:3}, 3.4] + normal vv + let r = visualmode(v) + call assert_equal('v', r, 'result for ' . string(v) . ' is not "v" but ' . r) + let r = visualmode(v) + call assert_equal('v', r, 'result for ' . string(v) . ' is not "v" but ' . r) + endfor + for v in [v:true, 1, " ", "0"] + normal vv + let r = visualmode(v) + call assert_equal('v', r, 'result for ' . v . ' is not "v" but ' . r) + let r = visualmode(v) + call assert_equal('', r, 'result for ' . v . ' is not "" but ' . r) + endfor +endfunc diff --git a/src/nvim/testdir/test_undo.vim b/src/nvim/testdir/test_undo.vim new file mode 100644 index 0000000000..171618f6f7 --- /dev/null +++ b/src/nvim/testdir/test_undo.vim @@ -0,0 +1,267 @@ +" Tests for the undo tree. +" Since this script is sourced we need to explicitly break changes up in +" undo-able pieces. Do that by setting 'undolevels'. +" Also tests :earlier and :later. + +func Test_undotree() + exe "normal Aabc\<Esc>" + set ul=100 + exe "normal Adef\<Esc>" + set ul=100 + undo + let d = undotree() + call assert_true(d.seq_last > 0) + call assert_true(d.seq_cur > 0) + call assert_true(d.seq_cur < d.seq_last) + call assert_true(len(d.entries) > 0) + " TODO: check more members of d + + w! Xtest + call assert_equal(d.save_last + 1, undotree().save_last) + call delete('Xtest') + bwipe Xtest +endfunc + +func FillBuffer() + for i in range(1,13) + put=i + " Set 'undolevels' to split undo. + exe "setg ul=" . &g:ul + endfor +endfunc + +func Test_global_local_undolevels() + new one + set undolevels=5 + call FillBuffer() + " will only undo the last 5 changes, end up with 13 - (5 + 1) = 7 lines + earlier 10 + call assert_equal(5, &g:undolevels) + call assert_equal(-123456, &l:undolevels) + call assert_equal('7', getline('$')) + + new two + setlocal undolevels=2 + call FillBuffer() + " will only undo the last 2 changes, end up with 13 - (2 + 1) = 10 lines + earlier 10 + call assert_equal(5, &g:undolevels) + call assert_equal(2, &l:undolevels) + call assert_equal('10', getline('$')) + + setlocal ul=10 + call assert_equal(5, &g:undolevels) + call assert_equal(10, &l:undolevels) + + " Setting local value in "two" must not change local value in "one" + wincmd p + call assert_equal(5, &g:undolevels) + call assert_equal(-123456, &l:undolevels) + + new three + setglobal ul=50 + call assert_equal(50, &g:undolevels) + call assert_equal(-123456, &l:undolevels) + + " Drop created windows + set ul& + new + only! +endfunc + +func BackOne(expected) + call feedkeys('g-', 'xt') + call assert_equal(a:expected, getline(1)) +endfunc + +func Test_undo_del_chars() + throw 'skipped: Nvim does not support test_settime()' + + " Setup a buffer without creating undo entries + new + set ul=-1 + call setline(1, ['123-456']) + set ul=100 + 1 + call test_settime(100) + + " Delete three characters and undo with g- + call feedkeys('x', 'xt') + call feedkeys('x', 'xt') + call feedkeys('x', 'xt') + call assert_equal('-456', getline(1)) + call BackOne('3-456') + call BackOne('23-456') + call BackOne('123-456') + call assert_fails("BackOne('123-456')") + + :" Delete three other characters and go back in time with g- + call feedkeys('$x', 'xt') + call feedkeys('x', 'xt') + call feedkeys('x', 'xt') + call assert_equal('123-', getline(1)) + call test_settime(101) + + call BackOne('123-4') + call BackOne('123-45') + " skips '123-456' because it's older + call BackOne('-456') + call BackOne('3-456') + call BackOne('23-456') + call BackOne('123-456') + call assert_fails("BackOne('123-456')") + normal 10g+ + call assert_equal('123-', getline(1)) + + :" Jump two seconds and go some seconds forward and backward + call test_settime(103) + call feedkeys("Aa\<Esc>", 'xt') + call feedkeys("Ab\<Esc>", 'xt') + call feedkeys("Ac\<Esc>", 'xt') + call assert_equal('123-abc', getline(1)) + earlier 1s + call assert_equal('123-', getline(1)) + earlier 3s + call assert_equal('123-456', getline(1)) + later 1s + call assert_equal('123-', getline(1)) + later 1h + call assert_equal('123-abc', getline(1)) + + close! +endfunc + +func Test_undolist() + new + set ul=100 + + let a=execute('undolist') + call assert_equal("\nNothing to undo", a) + + " 1 leaf (2 changes). + call feedkeys('achange1', 'xt') + call feedkeys('achange2', 'xt') + let a=execute('undolist') + call assert_match("^\nnumber changes when *saved\n *2 *2 .*$", a) + + " 2 leaves. + call feedkeys('u', 'xt') + call feedkeys('achange3\<Esc>', 'xt') + let a=execute('undolist') + call assert_match("^\nnumber changes when *saved\n *2 *2 *.*\n *3 *2 .*$", a) + close! +endfunc + +func Test_U_command() + new + set ul=100 + call feedkeys("achange1\<Esc>", 'xt') + call feedkeys("achange2\<Esc>", 'xt') + norm! U + call assert_equal('', getline(1)) + norm! U + call assert_equal('change1change2', getline(1)) + close! +endfunc + +func Test_undojoin() + new + call feedkeys("Goaaaa\<Esc>", 'xt') + call feedkeys("obbbb\<Esc>", 'xt') + call assert_equal(['aaaa', 'bbbb'], getline(2, '$')) + call feedkeys("u", 'xt') + call assert_equal(['aaaa'], getline(2, '$')) + call feedkeys("obbbb\<Esc>", 'xt') + undojoin + " Note: next change must not be as if typed + call feedkeys("occcc\<Esc>", 'x') + call assert_equal(['aaaa', 'bbbb', 'cccc'], getline(2, '$')) + call feedkeys("u", 'xt') + call assert_equal(['aaaa'], getline(2, '$')) + close! +endfunc + +func Test_undo_write() + split Xtest + call feedkeys("ione one one\<Esc>", 'xt') + w! + call feedkeys("otwo\<Esc>", 'xt') + call feedkeys("otwo\<Esc>", 'xt') + w + call feedkeys("othree\<Esc>", 'xt') + call assert_equal(['one one one', 'two', 'two', 'three'], getline(1, '$')) + earlier 1f + call assert_equal(['one one one', 'two', 'two'], getline(1, '$')) + earlier 1f + call assert_equal(['one one one'], getline(1, '$')) + earlier 1f + call assert_equal([''], getline(1, '$')) + later 1f + call assert_equal(['one one one'], getline(1, '$')) + later 1f + call assert_equal(['one one one', 'two', 'two'], getline(1, '$')) + later 1f + call assert_equal(['one one one', 'two', 'two', 'three'], getline(1, '$')) + + close! + call delete('Xtest') + bwipe! Xtest +endfunc + +func Test_insert_expr() + new + " calling setline() triggers undo sync + call feedkeys("oa\<Esc>", 'xt') + call feedkeys("ob\<Esc>", 'xt') + set ul=100 + call feedkeys("o1\<Esc>a2\<C-R>=setline('.','1234')\<CR>\<CR>\<Esc>", 'x') + call assert_equal(['a', 'b', '120', '34'], getline(2, '$')) + call feedkeys("u", 'x') + call assert_equal(['a', 'b', '12'], getline(2, '$')) + call feedkeys("u", 'x') + call assert_equal(['a', 'b'], getline(2, '$')) + + call feedkeys("oc\<Esc>", 'xt') + set ul=100 + call feedkeys("o1\<Esc>a2\<C-R>=setline('.','1234')\<CR>\<CR>\<Esc>", 'x') + call assert_equal(['a', 'b', 'c', '120', '34'], getline(2, '$')) + call feedkeys("u", 'x') + call assert_equal(['a', 'b', 'c', '12'], getline(2, '$')) + + call feedkeys("od\<Esc>", 'xt') + set ul=100 + call feedkeys("o1\<Esc>a2\<C-R>=string(123)\<CR>\<Esc>", 'x') + call assert_equal(['a', 'b', 'c', '12', 'd', '12123'], getline(2, '$')) + call feedkeys("u", 'x') + call assert_equal(['a', 'b', 'c', '12', 'd'], getline(2, '$')) + + close! +endfunc + +func Test_undofile_earlier() + throw 'skipped: Nvim does not support test_settime()' + + let t0 = localtime() - 43200 + call test_settime(t0) + new Xfile + call feedkeys("ione\<Esc>", 'xt') + set ul=100 + call test_settime(t0 + 1) + call feedkeys("otwo\<Esc>", 'xt') + set ul=100 + call test_settime(t0 + 2) + call feedkeys("othree\<Esc>", 'xt') + set ul=100 + w + wundo Xundofile + bwipe! + " restore normal timestamps. + call test_settime(0) + new Xfile + rundo Xundofile + earlier 1d + call assert_equal('', getline(1)) + bwipe! + call delete('Xfile') + call delete('Xundofile') +endfunc diff --git a/src/nvim/testdir/test_utf8.vim b/src/nvim/testdir/test_utf8.vim new file mode 100644 index 0000000000..24e3db86fb --- /dev/null +++ b/src/nvim/testdir/test_utf8.vim @@ -0,0 +1,65 @@ +" Tests for Unicode manipulations +if !has('multi_byte') + finish +endif + + +" Visual block Insert adjusts for multi-byte char +func Test_visual_block_insert() + new + call setline(1, ["aaa", "ใใใ", "bbb"]) + exe ":norm! gg0l\<C-V>jjIx\<Esc>" + call assert_equal(['axaa', 'xใใใ', 'bxbb'], getline(1, '$')) + bwipeout! +endfunc + +" Test for built-in function strchars() +func Test_strchars() + let inp = ["a", "ใใa", "A\u20dd", "A\u20dd\u20dd", "\u20dd"] + let exp = [[1, 1, 1], [3, 3, 3], [2, 2, 1], [3, 3, 1], [1, 1, 1]] + for i in range(len(inp)) + call assert_equal(exp[i][0], strchars(inp[i])) + call assert_equal(exp[i][1], strchars(inp[i], 0)) + call assert_equal(exp[i][2], strchars(inp[i], 1)) + endfor +endfunc + +" Test for customlist completion +function! CustomComplete1(lead, line, pos) + return ['ใ', 'ใ'] +endfunction + +function! CustomComplete2(lead, line, pos) + return ['ใใใ', 'ใใใพ', 'ใใใใ'] +endfunction + +function! CustomComplete3(lead, line, pos) + return ['Nใ', 'Nใ', 'Nใถ'] +endfunction + +func Test_customlist_completion() + command -nargs=1 -complete=customlist,CustomComplete1 Test1 echo + call feedkeys(":Test1 \<C-L>\<C-B>\"\<CR>", 'itx') + call assert_equal('"Test1 ', getreg(':')) + + command -nargs=1 -complete=customlist,CustomComplete2 Test2 echo + call feedkeys(":Test2 \<C-L>\<C-B>\"\<CR>", 'itx') + call assert_equal('"Test2 ใใ', getreg(':')) + + command -nargs=1 -complete=customlist,CustomComplete3 Test3 echo + call feedkeys(":Test3 \<C-L>\<C-B>\"\<CR>", 'itx') + call assert_equal('"Test3 N', getreg(':')) + + call garbagecollect(1) +endfunc + +" Yank one 3 byte character and check the mark columns. +func Test_getvcol() + new + call setline(1, "x\u2500x") + normal 0lvy + call assert_equal(2, col("'[")) + call assert_equal(4, col("']")) + call assert_equal(2, virtcol("'[")) + call assert_equal(2, virtcol("']")) +endfunc diff --git a/src/nvim/testdir/test_viml.vim b/src/nvim/testdir/test_vimscript.vim index a2997b6d4d..4e0f1bbd2f 100644 --- a/src/nvim/testdir/test_viml.vim +++ b/src/nvim/testdir/test_vimscript.vim @@ -1062,6 +1062,157 @@ func Test_echo_and_string() call assert_equal(["{'a': [], 'b': []}", \ "{'a': [], 'b': []}"], l) +"------------------------------------------------------------------------------- +" Test 94: 64-bit Numbers {{{1 +"------------------------------------------------------------------------------- + +func Test_num64() + if !has('num64') + return + endif + + call assert_notequal( 4294967296, 0) + call assert_notequal(-4294967296, 0) + call assert_equal( 4294967296, 0xFFFFffff + 1) + call assert_equal(-4294967296, -0xFFFFffff - 1) + + call assert_equal( 9223372036854775807, 1 / 0) + call assert_equal(-9223372036854775807, -1 / 0) + call assert_equal(-9223372036854775807 - 1, 0 / 0) + + call assert_equal( 0x7FFFffffFFFFffff, float2nr( 1.0e150)) + call assert_equal(-0x7FFFffffFFFFffff, float2nr(-1.0e150)) + + let rng = range(0xFFFFffff, 0x100000001) + call assert_equal([0xFFFFffff, 0x100000000, 0x100000001], rng) + call assert_equal(0x100000001, max(rng)) + call assert_equal(0xFFFFffff, min(rng)) + call assert_equal(rng, sort(range(0x100000001, 0xFFFFffff, -1), 'N')) +endfunc + +"------------------------------------------------------------------------------- +" Test 95: lines of :append, :change, :insert {{{1 +"------------------------------------------------------------------------------- + +function! DefineFunction(name, body) + let func = join(['function! ' . a:name . '()'] + a:body + ['endfunction'], "\n") + exec func +endfunction + +func Test_script_lines() + " :append + try + call DefineFunction('T_Append', [ + \ 'append', + \ 'py <<EOS', + \ '.', + \ ]) + catch + call assert_report("Can't define function") + endtry + try + call DefineFunction('T_Append', [ + \ 'append', + \ 'abc', + \ ]) + call assert_report("Shouldn't be able to define function") + catch + call assert_exception('Vim(function):E126: Missing :endfunction') + endtry + + " :change + try + call DefineFunction('T_Change', [ + \ 'change', + \ 'py <<EOS', + \ '.', + \ ]) + catch + call assert_report("Can't define function") + endtry + try + call DefineFunction('T_Change', [ + \ 'change', + \ 'abc', + \ ]) + call assert_report("Shouldn't be able to define function") + catch + call assert_exception('Vim(function):E126: Missing :endfunction') + endtry + + " :insert + try + call DefineFunction('T_Insert', [ + \ 'insert', + \ 'py <<EOS', + \ '.', + \ ]) + catch + call assert_report("Can't define function") + endtry + try + call DefineFunction('T_Insert', [ + \ 'insert', + \ 'abc', + \ ]) + call assert_report("Shouldn't be able to define function") + catch + call assert_exception('Vim(function):E126: Missing :endfunction') + endtry +endfunc + +"------------------------------------------------------------------------------- +" Test 96: line continuation {{{1 +" +" Undefined behavior was detected by ubsan with line continuation +" after an empty line. +"------------------------------------------------------------------------------- +func Test_script_emty_line_continuation() + + \ +endfunc + +"------------------------------------------------------------------------------- +" Test 97: bitwise functions {{{1 +"------------------------------------------------------------------------------- +func Test_bitwise_functions() + " and + call assert_equal(127, and(127, 127)) + call assert_equal(16, and(127, 16)) + call assert_equal(0, and(127, 128)) + call assert_fails("call and(1.0, 1)", 'E805:') + call assert_fails("call and([], 1)", 'E745:') + call assert_fails("call and({}, 1)", 'E728:') + call assert_fails("call and(1, 1.0)", 'E805:') + call assert_fails("call and(1, [])", 'E745:') + call assert_fails("call and(1, {})", 'E728:') + " or + call assert_equal(23, or(16, 7)) + call assert_equal(15, or(8, 7)) + call assert_equal(123, or(0, 123)) + call assert_fails("call or(1.0, 1)", 'E805:') + call assert_fails("call or([], 1)", 'E745:') + call assert_fails("call or({}, 1)", 'E728:') + call assert_fails("call or(1, 1.0)", 'E805:') + call assert_fails("call or(1, [])", 'E745:') + call assert_fails("call or(1, {})", 'E728:') + " xor + call assert_equal(0, xor(127, 127)) + call assert_equal(111, xor(127, 16)) + call assert_equal(255, xor(127, 128)) + call assert_fails("call xor(1.0, 1)", 'E805:') + call assert_fails("call xor([], 1)", 'E745:') + call assert_fails("call xor({}, 1)", 'E728:') + call assert_fails("call xor(1, 1.0)", 'E805:') + call assert_fails("call xor(1, [])", 'E745:') + call assert_fails("call xor(1, {})", 'E728:') + " invert + call assert_equal(65408, and(invert(127), 65535)) + call assert_equal(65519, and(invert(16), 65535)) + call assert_equal(65407, and(invert(128), 65535)) + call assert_fails("call invert(1.0)", 'E805:') + call assert_fails("call invert([])", 'E745:') + call assert_fails("call invert({})", 'E728:') endfunc "------------------------------------------------------------------------------- diff --git a/src/nvim/testdir/test_window_cmd.vim b/src/nvim/testdir/test_window_cmd.vim index b7f41a711b..9d61921988 100644 --- a/src/nvim/testdir/test_window_cmd.vim +++ b/src/nvim/testdir/test_window_cmd.vim @@ -67,4 +67,360 @@ function Test_window_cmd_wincmd_gf() augroup! test_window_cmd_wincmd_gf endfunc -" vim: sw=2 et +func Test_next_split_all() + " This was causing an illegal memory access. + n x + norm axxx + split + split + s/x + s/x + all + bwipe! +endfunc + +func Test_window_quit() + e Xa + split Xb + call assert_equal(2, winnr('$')) + call assert_equal('Xb', bufname(winbufnr(1))) + call assert_equal('Xa', bufname(winbufnr(2))) + + wincmd q + call assert_equal(1, winnr('$')) + call assert_equal('Xa', bufname(winbufnr(1))) + + bw Xa Xb +endfunc + +func Test_window_horizontal_split() + call assert_equal(1, winnr('$')) + 3wincmd s + call assert_equal(2, winnr('$')) + call assert_equal(3, winheight(0)) + call assert_equal(winwidth(1), winwidth(2)) + + call assert_fails('botright topleft wincmd s', 'E442:') + bw +endfunc + +func Test_window_vertical_split() + call assert_equal(1, winnr('$')) + 3wincmd v + call assert_equal(2, winnr('$')) + call assert_equal(3, winwidth(0)) + call assert_equal(winheight(1), winheight(2)) + + call assert_fails('botright topleft wincmd v', 'E442:') + bw +endfunc + +func Test_window_split_edit_alternate() + e Xa + e Xb + + wincmd ^ + call assert_equal('Xa', bufname(winbufnr(1))) + call assert_equal('Xb', bufname(winbufnr(2))) + + bw Xa Xb +endfunc + +func Test_window_preview() + " Open a preview window + pedit Xa + call assert_equal(2, winnr('$')) + call assert_equal(0, &previewwindow) + + " Go to the preview window + wincmd P + call assert_equal(1, &previewwindow) + + " Close preview window + wincmd z + call assert_equal(1, winnr('$')) + call assert_equal(0, &previewwindow) + + call assert_fails('wincmd P', 'E441:') +endfunc + +func Test_window_exchange() + e Xa + + " Nothing happens with window exchange when there is 1 window + wincmd x + call assert_equal(1, winnr('$')) + + split Xb + split Xc + + call assert_equal('Xc', bufname(winbufnr(1))) + call assert_equal('Xb', bufname(winbufnr(2))) + call assert_equal('Xa', bufname(winbufnr(3))) + + " Exchange current window 1 with window 3 + 3wincmd x + call assert_equal('Xa', bufname(winbufnr(1))) + call assert_equal('Xb', bufname(winbufnr(2))) + call assert_equal('Xc', bufname(winbufnr(3))) + + " Exchange window with next when at the top window + wincmd x + call assert_equal('Xb', bufname(winbufnr(1))) + call assert_equal('Xa', bufname(winbufnr(2))) + call assert_equal('Xc', bufname(winbufnr(3))) + + " Exchange window with next when at the middle window + wincmd j + wincmd x + call assert_equal('Xb', bufname(winbufnr(1))) + call assert_equal('Xc', bufname(winbufnr(2))) + call assert_equal('Xa', bufname(winbufnr(3))) + + " Exchange window with next when at the bottom window. + " When there is no next window, it exchanges with the previous window. + wincmd j + wincmd x + call assert_equal('Xb', bufname(winbufnr(1))) + call assert_equal('Xa', bufname(winbufnr(2))) + call assert_equal('Xc', bufname(winbufnr(3))) + + bw Xa Xb Xc +endfunc + +func Test_window_rotate() + e Xa + split Xb + split Xc + call assert_equal('Xc', bufname(winbufnr(1))) + call assert_equal('Xb', bufname(winbufnr(2))) + call assert_equal('Xa', bufname(winbufnr(3))) + + " Rotate downwards + wincmd r + call assert_equal('Xa', bufname(winbufnr(1))) + call assert_equal('Xc', bufname(winbufnr(2))) + call assert_equal('Xb', bufname(winbufnr(3))) + + 2wincmd r + call assert_equal('Xc', bufname(winbufnr(1))) + call assert_equal('Xb', bufname(winbufnr(2))) + call assert_equal('Xa', bufname(winbufnr(3))) + + " Rotate upwards + wincmd R + call assert_equal('Xb', bufname(winbufnr(1))) + call assert_equal('Xa', bufname(winbufnr(2))) + call assert_equal('Xc', bufname(winbufnr(3))) + + 2wincmd R + call assert_equal('Xc', bufname(winbufnr(1))) + call assert_equal('Xb', bufname(winbufnr(2))) + call assert_equal('Xa', bufname(winbufnr(3))) + + bot vsplit + call assert_fails('wincmd R', 'E443:') + + bw Xa Xb Xc +endfunc + +func Test_window_height() + e Xa + split Xb + + let [wh1, wh2] = [winheight(1), winheight(2)] + " Active window (1) should have the same height or 1 more + " than the other window. + call assert_inrange(wh2, wh2 + 1, wh1) + + wincmd - + call assert_equal(wh1 - 1, winheight(1)) + call assert_equal(wh2 + 1, winheight(2)) + + wincmd + + call assert_equal(wh1, winheight(1)) + call assert_equal(wh2, winheight(2)) + + 2wincmd _ + call assert_equal(2, winheight(1)) + call assert_equal(wh1 + wh2 - 2, winheight(2)) + + wincmd = + call assert_equal(wh1, winheight(1)) + call assert_equal(wh2, winheight(2)) + + 2wincmd _ + set winfixheight + split Xc + let [wh1, wh2, wh3] = [winheight(1), winheight(2), winheight(3)] + call assert_equal(2, winheight(2)) + call assert_inrange(wh3, wh3 + 1, wh1) + 3wincmd + + call assert_equal(2, winheight(2)) + call assert_equal(wh1 + 3, winheight(1)) + call assert_equal(wh3 - 3, winheight(3)) + wincmd = + call assert_equal(2, winheight(2)) + call assert_equal(wh1, winheight(1)) + call assert_equal(wh3, winheight(3)) + + wincmd j + set winfixheight& + + wincmd = + let [wh1, wh2, wh3] = [winheight(1), winheight(2), winheight(3)] + " Current window (2) should have the same height or 1 more + " than the other windows. + call assert_inrange(wh1, wh1 + 1, wh2) + call assert_inrange(wh3, wh3 + 1, wh2) + + bw Xa Xb Xc +endfunc + +func Test_window_width() + e Xa + vsplit Xb + + let [ww1, ww2] = [winwidth(1), winwidth(2)] + " Active window (1) should have the same width or 1 more + " than the other window. + call assert_inrange(ww2, ww2 + 1, ww1) + + wincmd < + call assert_equal(ww1 - 1, winwidth(1)) + call assert_equal(ww2 + 1, winwidth(2)) + + wincmd > + call assert_equal(ww1, winwidth(1)) + call assert_equal(ww2, winwidth(2)) + + 2wincmd | + call assert_equal(2, winwidth(1)) + call assert_equal(ww1 + ww2 - 2, winwidth(2)) + + wincmd = + call assert_equal(ww1, winwidth(1)) + call assert_equal(ww2, winwidth(2)) + + 2wincmd | + set winfixwidth + vsplit Xc + let [ww1, ww2, ww3] = [winwidth(1), winwidth(2), winwidth(3)] + " FIXME: commented out: I would expect the width of 2nd window to + " remain 2 but it's actually 1?! + "call assert_equal(2, winwidth(2)) + call assert_inrange(ww3, ww3 + 1, ww1) + 3wincmd > + " FIXME: commented out: I would expect the width of 2nd window to + " remain 2 but it's actually 1?! + "call assert_equal(2, winwidth(2)) + call assert_equal(ww1 + 3, winwidth(1)) + call assert_equal(ww3 - 3, winwidth(3)) + wincmd = + " FIXME: commented out: I would expect the width of 2nd window to + " remain 2 but it's actually 1?! + "call assert_equal(2, winwidth(2)) + call assert_equal(ww1, winwidth(1)) + call assert_equal(ww3, winwidth(3)) + + wincmd l + set winfixwidth& + + wincmd = + let [ww1, ww2, ww3] = [winwidth(1), winwidth(2), winwidth(3)] + " Current window (2) should have the same width or 1 more + " than the other windows. + call assert_inrange(ww1, ww1 + 1, ww2) + call assert_inrange(ww3, ww3 + 1, ww2) + + bw Xa Xb Xc +endfunc + +func Test_equalalways_on_close() + set equalalways + vsplit + windo split + split + wincmd J + " now we have a frame top-left with two windows, a frame top-right with two + " windows and a frame at the bottom, full-width. + let height_1 = winheight(1) + let height_2 = winheight(2) + let height_3 = winheight(3) + let height_4 = winheight(4) + " closing the bottom window causes all windows to be resized. + close + call assert_notequal(height_1, winheight(1)) + call assert_notequal(height_2, winheight(2)) + call assert_notequal(height_3, winheight(3)) + call assert_notequal(height_4, winheight(4)) + call assert_equal(winheight(1), winheight(3)) + call assert_equal(winheight(2), winheight(4)) + + 1wincmd w + split + 4wincmd w + resize + 5 + " left column has three windows, equalized heights. + " right column has two windows, top one a bit higher + let height_1 = winheight(1) + let height_2 = winheight(2) + let height_4 = winheight(4) + let height_5 = winheight(5) + 3wincmd w + " closing window in left column equalizes heights in left column but not in + " the right column + close + call assert_notequal(height_1, winheight(1)) + call assert_notequal(height_2, winheight(2)) + call assert_equal(height_4, winheight(3)) + call assert_equal(height_5, winheight(4)) + + only + set equalalways& +endfunc + +func Test_window_jump_tag() + help + /iccf + call assert_match('^|iccf|', getline('.')) + call assert_equal(2, winnr('$')) + 2wincmd } + call assert_equal(3, winnr('$')) + call assert_match('^|iccf|', getline('.')) + wincmd k + call assert_match('\*iccf\*', getline('.')) + call assert_equal(2, winheight(0)) + + wincmd z + set previewheight=4 + help + /bugs + wincmd } + wincmd k + call assert_match('\*bugs\*', getline('.')) + call assert_equal(4, winheight(0)) + set previewheight& + + %bw! +endfunc + +func Test_window_newtab() + e Xa + + call assert_equal(1, tabpagenr('$')) + call assert_equal("\nAlready only one window", execute('wincmd T')) + + split Xb + split Xc + + wincmd T + call assert_equal(2, tabpagenr('$')) + call assert_equal(['Xb', 'Xa'], map(tabpagebuflist(1), 'bufname(v:val)')) + call assert_equal(['Xc' ], map(tabpagebuflist(2), 'bufname(v:val)')) + + %bw! +endfunc + + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_window_id.vim b/src/nvim/testdir/test_window_id.vim index 66656e1d0a..b3b506d04d 100644 --- a/src/nvim/testdir/test_window_id.vim +++ b/src/nvim/testdir/test_window_id.vim @@ -92,3 +92,12 @@ func Test_win_getid() only! endfunc + +func Test_win_getid_curtab() + tabedit X + tabfirst + copen + only + call assert_equal(win_getid(1), win_getid(1, 1)) + tabclose! +endfunc diff --git a/src/nvim/testdir/test_writefile.vim b/src/nvim/testdir/test_writefile.vim new file mode 100644 index 0000000000..d820c580ac --- /dev/null +++ b/src/nvim/testdir/test_writefile.vim @@ -0,0 +1,16 @@ + +function! Test_WriteFile() + let f = tempname() + call writefile(["over","written"], f, "b") + call writefile(["hello","world"], f, "b") + call writefile(["!", "good"], f, "a") + call writefile(["morning"], f, "ab") + call writefile(["", "vimmers"], f, "ab") + let l = readfile(f) + call assert_equal("hello", l[0]) + call assert_equal("world!", l[1]) + call assert_equal("good", l[2]) + call assert_equal("morning", l[3]) + call assert_equal("vimmers", l[4]) + call delete(f) +endfunction diff --git a/src/nvim/testdir/view_util.vim b/src/nvim/testdir/view_util.vim new file mode 100644 index 0000000000..eb92630761 --- /dev/null +++ b/src/nvim/testdir/view_util.vim @@ -0,0 +1,30 @@ +" Functions about view shared by several tests + +" ScreenLines(lnum, width) or +" ScreenLines([start, end], width) +function! ScreenLines(lnum, width) abort + redraw! + if type(a:lnum) == v:t_list + let start = a:lnum[0] + let end = a:lnum[1] + else + let start = a:lnum + let end = a:lnum + endif + let lines = [] + for l in range(start, end) + let lines += [join(map(range(1, a:width), 'nr2char(screenchar(l, v:val))'), '')] + endfor + return lines +endfunction + +function! NewWindow(height, width) abort + exe a:height . 'new' + exe a:width . 'vsp' + redraw! +endfunction + +function! CloseWindow() abort + bw! + redraw! +endfunction diff --git a/src/nvim/tui/input.c b/src/nvim/tui/input.c index 8e5adb14f9..03587d68f0 100644 --- a/src/nvim/tui/input.c +++ b/src/nvim/tui/input.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #include "nvim/tui/input.h" #include "nvim/vim.h" @@ -44,7 +47,13 @@ void term_input_init(TermInput *input, Loop *loop) int curflags = termkey_get_canonflags(input->tk); termkey_set_canonflags(input->tk, curflags | TERMKEY_CANON_DELBS); // setup input handle +#ifdef WIN32 + uv_tty_init(loop, &input->tty_in, 0, 1); + uv_tty_set_mode(&input->tty_in, UV_TTY_MODE_RAW); + rstream_init_stream(&input->read_stream, &input->tty_in, 0xfff); +#else rstream_init_fd(loop, &input->read_stream, input->in_fd, 0xfff); +#endif // initialize a timer handle for handling ESC with libtermkey time_watcher_init(loop, &input->timer_handle, input); } @@ -99,7 +108,7 @@ static void flush_input(TermInput *input, bool wait_until_empty) size_t drain_boundary = wait_until_empty ? 0 : 0xff; do { uv_mutex_lock(&input->key_buffer_mutex); - loop_schedule(&main_loop, event_create(1, wait_input_enqueue, 1, input)); + loop_schedule(&main_loop, event_create(wait_input_enqueue, 1, input)); input->waiting = true; while (input->waiting) { uv_cond_wait(&input->key_buffer_cond, &input->key_buffer_mutex); @@ -220,12 +229,14 @@ static int get_key_code_timeout(void) { Integer ms = -1; // Check 'ttimeout' to determine if we should send ESC after 'ttimeoutlen'. - // See :help 'ttimeout' for more information Error err = ERROR_INIT; if (nvim_get_option(cstr_as_string("ttimeout"), &err).data.boolean) { - ms = nvim_get_option(cstr_as_string("ttimeoutlen"), &err).data.integer; + Object rv = nvim_get_option(cstr_as_string("ttimeoutlen"), &err); + if (!ERROR_SET(&err)) { + ms = rv.data.integer; + } } - + api_clear_error(&err); return (int)ms; } @@ -347,7 +358,7 @@ static void read_cb(Stream *stream, RBuffer *buf, size_t c, void *data, stream_close(&input->read_stream, NULL, NULL); multiqueue_put(input->loop->fast_events, restart_reading, 1, input); } else { - loop_schedule(&main_loop, event_create(1, input_done_event, 0)); + loop_schedule(&main_loop, event_create(input_done_event, 0)); } return; } diff --git a/src/nvim/tui/input.h b/src/nvim/tui/input.h index 7d59cf5c6a..573cc9d683 100644 --- a/src/nvim/tui/input.h +++ b/src/nvim/tui/input.h @@ -17,6 +17,9 @@ typedef struct term_input { #endif TimeWatcher timer_handle; Loop *loop; +#ifdef WIN32 + uv_tty_t tty_in; +#endif Stream read_stream; RBuffer *key_buffer; uv_mutex_t key_buffer_mutex; diff --git a/src/nvim/tui/terminfo.c b/src/nvim/tui/terminfo.c new file mode 100644 index 0000000000..586fafba97 --- /dev/null +++ b/src/nvim/tui/terminfo.c @@ -0,0 +1,123 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + +// Built-in fallback terminfo entries. + +#include <unibilium.h> + +#include "nvim/tui/terminfo.h" +#include "nvim/tui/tui.h" + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "tui/terminfo.c.generated.h" +#endif + +// One creates the dumps from terminfo.src by using +// od -t d1 -w | cut -c9- | sed -e 's/\>/,/g' +// on the compiled files. + +// Taken from Dickey ncurses terminfo.src dated 2017-04-22. +// This is a 256-colour terminfo description that lacks true-colour and +// DECSTBM/DECSLRM/DECLRMM capabilities that xterm actually has. +static const signed char xterm_256colour_terminfo[] = { + 26, 1, 37, 0, 29, 0, 15, 0, 105, 1, -42, 5, 120, 116, 101, 114, 109, 45, 50, 53, 54, 99, 111, 108, 111, 114, 124, 120, 116, 101, 114, 109, 32, 119, 105, 116, 104, 32, 50, 53, 54, 32, 99, 111, 108, 111, 114, 115, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 80, 0, 8, 0, 24, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, -1, 127, 0, 0, 4, 0, 6, 0, 8, 0, 25, 0, 30, 0, 38, 0, 42, 0, 46, 0, -1, -1, 57, 0, 74, 0, 76, 0, 80, 0, 87, 0, -1, -1, 89, 0, 102, 0, -1, -1, 106, 0, 110, 0, 120, 0, 124, 0, -1, -1, -1, -1,-128, 0,-124, 0,-119, 0,-114, 0, -1, -1,-105, 0,-100, 0, -95, 0, -1, -1, -90, 0, -85, 0, -80, 0, -75, 0, -66, 0, -62, 0, -55, 0, -1, -1, -46, 0, -41, 0, -35, 0, -29, 0, -1, -1, -1, -1, -1, -1, -11, 0, -1, -1, -1, -1, -1, -1, 7, 1, -1, -1, 11, 1, -1, -1, -1, -1, -1, -1, 13, 1, -1, -1, 18, 1, -1, -1, -1, -1, -1, -1, -1, -1, 22, 1, 26, 1, 32, 1, 36, 1, 40, 1, 44, 1, 50, 1, 56, 1, 62, 1, 68, 1, 74, 1, 78, 1, -1, -1, 83, 1, -1, -1, 87, 1, 92, 1, 97, 1, 101, 1, 108, 1, -1, -1, 115, 1, 119, 1, 127, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,-121, 1,-112, 1, -1, -1, -1, -1,-103, 1, -94, 1, -85, 1, -76, 1, -67, 1, -58, 1, -49, 1, -40, 1, -31, 1, -22, 1, -1, -1, -1, -1, -1, -1, -13, 1, -9, 1, -4, 1, -1, -1, 1, 2, 10, 2, -1, -1, -1, -1, 28, 2, 31, 2, 42, 2, 45, 2, 47, 2, 50, 2,-113, 2, -1, -1,-110, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,-108, 2, -1, -1, -1, -1, -1, -1, -1, -1,-104, 2, -1, -1, -51, 2, -1, -1, -1, -1, -47, 2, -41, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -35, 2, -31, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -27, 2, -1, -1, -1, -1, -20, 2, -1, -1, -1, -1, -1, -1, -1, -1, -13, 2, -6, 2, 1, 3, -1, -1, -1, -1, 8, 3, -1, -1, 15, 3, -1, -1, -1, -1, -1, -1, 22, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 29, 3, 35, 3, 41, 3, 48, 3, 55, 3, 62, 3, 69, 3, 77, 3, 85, 3, 93, 3, 101, 3, 109, 3, 117, 3, 125, 3,-123, 3,-116, 3,-109, 3,-102, 3, -95, 3, -87, 3, -79, 3, -71, 3, -63, 3, -55, 3, -47, 3, -39, 3, -31, 3, -24, 3, -17, 3, -10, 3, -3, 3, 5, 4, 13, 4, 21, 4, 29, 4, 37, 4, 45, 4, 53, 4, 61, 4, 68, 4, 75, 4, 82, 4, 89, 4, 97, 4, 105, 4, 113, 4, 121, 4,-127, 4,-119, 4,-111, 4,-103, 4, -96, 4, -89, 4, -82, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -77, 4, -66, 4, -61, 4, -42, 4, -38, 4, -29, 4, -22, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 72, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 77, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 83, 5, -1, -1, -1, -1, -1, -1, 87, 5,-106, 5, 27, 91, 90, 0, 7, 0, 13, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 59, 37, 112, 50, 37, 100, 114, 0, 27, 91, 51, 103, 0, 27, 91, 72, 27, 91, 50, 74, 0, 27, 91, 75, 0, 27, 91, 74, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 71, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 59, 37, 112, 50, 37, 100, 72, 0, 10, 0, 27, 91, 72, 0, 27, 91, 63, 50, 53, 108, 0, 8, 0, 27, 91, 63, 49, 50, 108, 27, 91, 63, 50, 53, 104, 0, 27, 91, 67, 0, 27, 91, 65, 0, 27, 91, 63, 49, 50, 59, 50, 53, 104, 0, 27, 91, 80, 0, 27, 91, 77, 0, 27, 40, 48, 0, 27, 91, 53, 109, 0, 27, 91, 49, 109, 0, 27, 91, 63, 49, 48, 52, 57, 104, 0, 27, 91, 50, 109, 0, 27, 91, 52, 104, 0, 27, 91, 56, 109, 0, 27, 91, 55, 109, 0, 27, 91, 55, 109, 0, 27, 91, 52, 109, 0, 27, 91, 37, 112, 49, 37, 100, 88, 0, 27, 40, 66, 0, 27, 40, 66, 27, 91, 109, 0, 27, 91, 63, 49, 48, 52, 57, 108, 0, 27, 91, 52, 108, 0, 27, 91, 50, 55, 109, 0, 27, 91, 50, 52, 109, 0, 27, 91, 63, 53, 104, 36, 60, 49, 48, 48, 47, 62, 27, 91, 63, 53, 108, 0, 27, 91, 33, 112, 27, 91, 63, 51, 59, 52, 108, 27, 91, 52, 108, 27, 62, 0, 27, 91, 76, 0, 8, 0, 27, 91, 51, 126, 0, 27, 79, 66, 0, 27, 79, 80, 0, 27, 91, 50, 49, 126, 0, 27, 79, 81, 0, 27, 79, 82, 0, 27, 79, 83, 0, 27, 91, 49, 53, 126, 0, 27, 91, 49, 55, 126, 0, 27, 91, 49, 56, 126, 0, 27, 91, 49, 57, 126, 0, 27, 91, 50, 48, 126, 0, 27, 79, 72, 0, 27, 91, 50, 126, 0, 27, 79, 68, 0, 27, 91, 54, 126, 0, 27, 91, 53, 126, 0, 27, 79, 67, 0, 27, 91, 49, 59, 50, 66, 0, 27, 91, 49, 59, 50, 65, 0, 27, 79, 65, 0, 27, 91, 63, 49, 108, 27, 62, 0, 27, 91, 63, 49, 104, 27, 61, 0, 27, 91, 63, 49, 48, 51, 52, 108, 0, 27, 91, 63, 49, 48, 51, 52, 104, 0, 27, 91, 37, 112, 49, 37, 100, 80, 0, 27, 91, 37, 112, 49, 37, 100, 77, 0, 27, 91, 37, 112, 49, 37, 100, 66, 0, 27, 91, 37, 112, 49, 37, 100, 64, 0, 27, 91, 37, 112, 49, 37, 100, 83, 0, 27, 91, 37, 112, 49, 37, 100, 76, 0, 27, 91, 37, 112, 49, 37, 100, 68, 0, 27, 91, 37, 112, 49, 37, 100, 67, 0, 27, 91, 37, 112, 49, 37, 100, 84, 0, 27, 91, 37, 112, 49, 37, 100, 65, 0, 27, 91, 105, 0, 27, 91, 52, 105, 0, 27, 91, 53, 105, 0, 27, 99, 27, 93, 49, 48, 52, 7, 0, 27, 91, 33, 112, 27, 91, 63, 51, 59, 52, 108, 27, 91, 52, 108, 27, 62, 0, 27, 56, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 100, 0, 27, 55, 0, 10, 0, 27, 77, 0, 37, 63, 37, 112, 57, 37, 116, 27, 40, 48, 37, 101, 27, 40, 66, 37, 59, 27, 91, 48, 37, 63, 37, 112, 54, 37, 116, 59, 49, 37, 59, 37, 63, 37, 112, 53, 37, 116, 59, 50, 37, 59, 37, 63, 37, 112, 50, 37, 116, 59, 52, 37, 59, 37, 63, 37, 112, 49, 37, 112, 51, 37, 124, 37, 116, 59, 55, 37, 59, 37, 63, 37, 112, 52, 37, 116, 59, 53, 37, 59, 37, 63, 37, 112, 55, 37, 116, 59, 56, 37, 59, 109, 0, 27, 72, 0, 9, 0, 27, 79, 69, 0, 96, 96, 97, 97, 102, 102, 103, 103, 105, 105, 106, 106, 107, 107, 108, 108, 109, 109, 110, 110, 111, 111, 112, 112, 113, 113, 114, 114, 115, 115, 116, 116, 117, 117, 118, 118, 119, 119, 120, 120, 121, 121, 122, 122, 123, 123, 124, 124, 125, 125, 126, 126, 0, 27, 91, 90, 0, 27, 91, 63, 55, 104, 0, 27, 91, 63, 55, 108, 0, 27, 79, 70, 0, 27, 79, 77, 0, 27, 91, 51, 59, 50, 126, 0, 27, 91, 49, 59, 50, 70, 0, 27, 91, 49, 59, 50, 72, 0, 27, 91, 50, 59, 50, 126, 0, 27, 91, 49, 59, 50, 68, 0, 27, 91, 54, 59, 50, 126, 0, 27, 91, 53, 59, 50, 126, 0, 27, 91, 49, 59, 50, 67, 0, 27, 91, 50, 51, 126, 0, 27, 91, 50, 52, 126, 0, 27, 91, 49, 59, 50, 80, 0, 27, 91, 49, 59, 50, 81, 0, 27, 91, 49, 59, 50, 82, 0, 27, 91, 49, 59, 50, 83, 0, 27, 91, 49, 53, 59, 50, 126, 0, 27, 91, 49, 55, 59, 50, 126, 0, 27, 91, 49, 56, 59, 50, 126, 0, 27, 91, 49, 57, 59, 50, 126, 0, 27, 91, 50, 48, 59, 50, 126, 0, 27, 91, 50, 49, 59, 50, 126, 0, 27, 91, 50, 51, 59, 50, 126, 0, 27, 91, 50, 52, 59, 50, 126, 0, 27, 91, 49, 59, 53, 80, 0, 27, 91, 49, 59, 53, 81, 0, 27, 91, 49, 59, 53, 82, 0, 27, 91, 49, 59, 53, 83, 0, 27, 91, 49, 53, 59, 53, 126, 0, 27, 91, 49, 55, 59, 53, 126, 0, 27, 91, 49, 56, 59, 53, 126, 0, 27, 91, 49, 57, 59, 53, 126, 0, 27, 91, 50, 48, 59, 53, 126, 0, 27, 91, 50, 49, 59, 53, 126, 0, 27, 91, 50, 51, 59, 53, 126, 0, 27, 91, 50, 52, 59, 53, 126, 0, 27, 91, 49, 59, 54, 80, 0, 27, 91, 49, 59, 54, 81, 0, 27, 91, 49, 59, 54, 82, 0, 27, 91, 49, 59, 54, 83, 0, 27, 91, 49, 53, 59, 54, 126, 0, 27, 91, 49, 55, 59, 54, 126, 0, 27, 91, 49, 56, 59, 54, 126, 0, 27, 91, 49, 57, 59, 54, 126, 0, 27, 91, 50, 48, 59, 54, 126, 0, 27, 91, 50, 49, 59, 54, 126, 0, 27, 91, 50, 51, 59, 54, 126, 0, 27, 91, 50, 52, 59, 54, 126, 0, 27, 91, 49, 59, 51, 80, 0, 27, 91, 49, 59, 51, 81, 0, 27, 91, 49, 59, 51, 82, 0, 27, 91, 49, 59, 51, 83, 0, 27, 91, 49, 53, 59, 51, 126, 0, 27, 91, 49, 55, 59, 51, 126, 0, 27, 91, 49, 56, 59, 51, 126, 0, 27, 91, 49, 57, 59, 51, 126, 0, 27, 91, 50, 48, 59, 51, 126, 0, 27, 91, 50, 49, 59, 51, 126, 0, 27, 91, 50, 51, 59, 51, 126, 0, 27, 91, 50, 52, 59, 51, 126, 0, 27, 91, 49, 59, 52, 80, 0, 27, 91, 49, 59, 52, 81, 0, 27, 91, 49, 59, 52, 82, 0, 27, 91, 49, 75, 0, 27, 91, 37, 105, 37, 100, 59, 37, 100, 82, 0, 27, 91, 54, 110, 0, 27, 91, 63, 37, 91, 59, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 93, 99, 0, 27, 91, 99, 0, 27, 91, 51, 57, 59, 52, 57, 109, 0, 27, 93, 49, 48, 52, 7, 0, 27, 93, 52, 59, 37, 112, 49, 37, 100, 59, 114, 103, 98, 58, 37, 112, 50, 37, 123, 50, 53, 53, 125, 37, 42, 37, 123, 49, 48, 48, 48, 125, 37, 47, 37, 50, 46, 50, 88, 47, 37, 112, 51, 37, 123, 50, 53, 53, 125, 37, 42, 37, 123, 49, 48, 48, 48, 125, 37, 47, 37, 50, 46, 50, 88, 47, 37, 112, 52, 37, 123, 50, 53, 53, 125, 37, 42, 37, 123, 49, 48, 48, 48, 125, 37, 47, 37, 50, 46, 50, 88, 27, 92, 0, 27, 91, 51, 109, 0, 27, 91, 50, 51, 109, 0, 27, 91, 77, 0, 27, 91, 37, 63, 37, 112, 49, 37, 123, 56, 125, 37, 60, 37, 116, 51, 37, 112, 49, 37, 100, 37, 101, 37, 112, 49, 37, 123, 49, 54, 125, 37, 60, 37, 116, 57, 37, 112, 49, 37, 123, 56, 125, 37, 45, 37, 100, 37, 101, 51, 56, 59, 53, 59, 37, 112, 49, 37, 100, 37, 59, 109, 0, 27, 91, 37, 63, 37, 112, 49, 37, 123, 56, 125, 37, 60, 37, 116, 52, 37, 112, 49, 37, 100, 37, 101, 37, 112, 49, 37, 123, 49, 54, 125, 37, 60, 37, 116, 49, 48, 37, 112, 49, 37, 123, 56, 125, 37, 45, 37, 100, 37, 101, 52, 56, 59, 53, 59, 37, 112, 49, 37, 100, 37, 59, 109, 0 +}; +// Taken from unibilium/t/static_tmux.c as of 2015-08-14. +// This is an 256-colour terminfo description that lacks +// status line capabilities that tmux actually has. +static const signed char tmux_256colour_terminfo[] = { + 26, 1, 56, 0, 15, 0, 15, 0, 105, 1, -48, 2, 116, 109, 117, 120, 124, 86, 84, 32, 49, 48, 48, 47, 65, 78, 83, 73, 32, 88, 51, 46, 54, 52, 32, 118, 105, 114, 116, 117, 97, 108, 32, 116, 101, 114, 109, 105, 110, 97, 108, 32, 119, 105, 116, 104, 32, 50, 53, 54, 32, 99, 111, 108, 111, 114, 115, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 80, 0, 8, 0, 24, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, -1, 127, 0, 0, 4, 0, 6, 0, 8, 0, 25, 0, 30, 0, 37, 0, 41, 0, -1, -1, -1, -1, 45, 0, 62, 0, 64, 0, 68, 0, 75, 0, -1, -1, 77, 0, 89, 0, -1, -1, 93, 0, 96, 0, 102, 0, 106, 0, -1, -1, -1, -1, 110, 0, 112, 0, 117, 0, 122, 0, -1, -1, -1, -1, 123, 0, -1, -1, -1, -1, -128, 0, -123, 0, -118, 0, -1, -1, -113, 0, -111, 0, -106, 0, -1, -1, -105, 0, -100, 0, -94, 0, -88, 0, -1, -1, -1, -1, -1, -1, -85, 0, -1, -1, -1, -1, -1, -1, -81, 0, -1, -1, -77, 0, -1, -1, -1, -1, -1, -1, -75, 0, -1, -1, -70, 0, -1, -1, -1, -1, -1, -1, -1, -1, -66, 0, -62, 0, -56, 0, -52, 0, -48, 0, -44, 0, -38, 0, -32, 0, -26, 0, -20, 0, -14, 0, -9, 0, -1, -1, -4, 0, -1, -1, 0, 1, 5, 1, 10, 1, -1, -1, -1, -1, -1, -1, 14, 1, 18, 1, 26, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 34, 1, -1, -1, 37, 1, 46, 1, 55, 1, 64, 1, -1, -1, 73, 1, 82, 1, 91, 1, -1, -1, 100, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 109, 1, -1, -1, -1, -1, 126, 1, -1, -1, -127, 1, -124, 1, -122, 1, -119, 1, -46, 1, -1, -1, -43, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -41, 1, -1, -1, 24, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 28, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 35, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 40, 2, 46, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 52, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 57, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 66, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 71, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 77, 2, -1, -1, -1, -1, -1, -1, 81, 2, -112, 2, 27, 91, 90, 0, 7, 0, 13, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 59, 37, 112, 50, 37, 100, 114, 0, 27, 91, 51, 103, 0, 27, 91, 72, 27, 91, 74, 0, 27, 91, 75, 0, 27, 91, 74, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 59, 37, 112, 50, 37, 100, 72, 0, 10, 0, 27, 91, 72, 0, 27, 91, 63, 50, 53, 108, 0, 8, 0, 27, 91, 51, 52, 104, 27, 91, 63, 50, 53, 104, 0, 27, 91, 67, 0, 27, 77, 0, 27, 91, 51, 52, 108, 0, 27, 91, 80, 0, 27, 91, 77, 0, 14, 0, 27, 91, 53, 109, 0, 27, 91, 49, 109, 0, 0, 27, 91, 52, 104, 0, 27, 91, 55, 109, 0, 27, 91, 55, 109, 0, 27, 91, 52, 109, 0, 15, 0, 27, 91, 109, 15, 0, 0, 27, 91, 52, 108, 0, 27, 91, 50, 55, 109, 0, 27, 91, 50, 52, 109, 0, 27, 103, 0, 27, 41, 48, 0, 27, 91, 76, 0, 8, 0, 27, 91, 51, 126, 0, 27, 79, 66, 0, 27, 79, 80, 0, 27, 91, 50, 49, 126, 0, 27, 79, 81, 0, 27, 79, 82, 0, 27, 79, 83, 0, 27, 91, 49, 53, 126, 0, 27, 91, 49, 55, 126, 0, 27, 91, 49, 56, 126, 0, 27, 91, 49, 57, 126, 0, 27, 91, 50, 48, 126, 0, 27, 91, 49, 126, 0, 27, 91, 50, 126, 0, 27, 79, 68, 0, 27, 91, 54, 126, 0, 27, 91, 53, 126, 0, 27, 79, 67, 0, 27, 79, 65, 0, 27, 91, 63, 49, 108, 27, 62, 0, 27, 91, 63, 49, 104, 27, 61, 0, 27, 69, 0, 27, 91, 37, 112, 49, 37, 100, 80, 0, 27, 91, 37, 112, 49, 37, 100, 77, 0, 27, 91, 37, 112, 49, 37, 100, 66, 0, 27, 91, 37, 112, 49, 37, 100, 64, 0, 27, 91, 37, 112, 49, 37, 100, 76, 0, 27, 91, 37, 112, 49, 37, 100, 68, 0, 27, 91, 37, 112, 49, 37, 100, 67, 0, 27, 91, 37, 112, 49, 37, 100, 65, 0, 27, 99, 27, 91, 63, 49, 48, 48, 48, 108, 27, 91, 63, 50, 53, 104, 0, 27, 56, 0, 27, 55, 0, 10, 0, 27, 77, 0, 27, 91, 48, 37, 63, 37, 112, 54, 37, 116, 59, 49, 37, 59, 37, 63, 37, 112, 49, 37, 116, 59, 55, 37, 59, 37, 63, 37, 112, 50, 37, 116, 59, 52, 37, 59, 37, 63, 37, 112, 51, 37, 116, 59, 55, 37, 59, 37, 63, 37, 112, 52, 37, 116, 59, 53, 37, 59, 109, 37, 63, 37, 112, 57, 37, 116, 14, 37, 101, 15, 37, 59, 0, 27, 72, 0, 9, 0, 43, 43, 44, 44, 45, 45, 46, 46, 48, 48, 96, 96, 97, 97, 102, 102, 103, 103, 104, 104, 105, 105, 106, 106, 107, 107, 108, 108, 109, 109, 110, 110, 111, 111, 112, 112, 113, 113, 114, 114, 115, 115, 116, 116, 117, 117, 118, 118, 119, 119, 120, 120, 121, 121, 122, 122, 123, 123, 124, 124, 125, 125, 126, 126, 0, 27, 91, 90, 0, 27, 40, 66, 27, 41, 48, 0, 27, 91, 52, 126, 0, 27, 91, 50, 51, 126, 0, 27, 91, 50, 52, 126, 0, 27, 91, 49, 75, 0, 27, 91, 51, 57, 59, 52, 57, 109, 0, 27, 91, 51, 109, 0, 27, 91, 50, 51, 109, 0, 27, 91, 77, 0, 27, 91, 37, 63, 37, 112, 49, 37, 123, 56, 125, 37, 60, 37, 116, 51, 37, 112, 49, 37, 100, 37, 101, 37, 112, 49, 37, 123, 49, 54, 125, 37, 60, 37, 116, 57, 37, 112, 49, 37, 123, 56, 125, 37, 45, 37, 100, 37, 101, 51, 56, 59, 53, 59, 37, 112, 49, 37, 100, 37, 59, 109, 0, 27, 91, 37, 63, 37, 112, 49, 37, 123, 56, 125, 37, 60, 37, 116, 52, 37, 112, 49, 37, 100, 37, 101, 37, 112, 49, 37, 123, 49, 54, 125, 37, 60, 37, 116, 49, 48, 37, 112, 49, 37, 123, 56, 125, 37, 45, 37, 100, 37, 101, 52, 56, 59, 53, 59, 37, 112, 49, 37, 100, 37, 59, 109, 0 +}; +// Taken from unibilium/t/static_screen-256color.c as of 2015-08-14. +// This is an 256-colour terminfo description that lacks +// status line capabilities that screen actually has. +static const signed char screen_256colour_terminfo[] = { + 26, 1, 43, 0, 43, 0, 15, 0, 105, 1, -43, 2, 115, 99, 114, 101, 101, 110, 45, 50, 53, 54, 99, 111, 108, 111, 114, 124, 71, 78, 85, 32, 83, 99, 114, 101, 101, 110, 32, 119, 105, 116, 104, 32, 50, 53, 54, 32, 99, 111, 108, 111, 114, 115, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 80, 0, 8, 0, 24, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, -1, 127, 0, 0, 4, 0, 6, 0, 8, 0, 25, 0, 30, 0, 37, 0, 41, 0, -1, -1, -1, -1, 45, 0, 62, 0, 64, 0, 68, 0, 75, 0, -1, -1, 77, 0, 89, 0, -1, -1, 93, 0, 96, 0, 102, 0, 106, 0, -1, -1, -1, -1, 110, 0, 112, 0, 117, 0, 122, 0, -1, -1, -1, -1, -125, 0, -1, -1, -1, -1, -120, 0, -115, 0, -110, 0, -1, -1, -105, 0, -103, 0, -98, 0, -1, -1, -89, 0, -84, 0, -78, 0, -72, 0, -1, -1, -1, -1, -1, -1, -69, 0, -1, -1, -1, -1, -1, -1, -65, 0, -1, -1, -61, 0, -1, -1, -1, -1, -1, -1, -59, 0, -1, -1, -54, 0, -1, -1, -1, -1, -1, -1, -1, -1, -50, 0, -46, 0, -40, 0, -36, 0, -32, 0, -28, 0, -22, 0, -16, 0, -10, 0, -4, 0, 2, 1, 7, 1, -1, -1, 12, 1, -1, -1, 16, 1, 21, 1, 26, 1, -1, -1, -1, -1, -1, -1, 30, 1, 34, 1, 42, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 50, 1, -1, -1, 53, 1, 62, 1, 71, 1, 80, 1, -1, -1, 89, 1, 98, 1, 107, 1, -1, -1, 116, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 125, 1, -1, -1, -1, -1, -114, 1, -1, -1, -111, 1, -108, 1, -106, 1, -103, 1, -30, 1, -1, -1, -27, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -25, 1, -1, -1, 40, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 44, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 51, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 56, 2, 62, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 68, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 73, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 82, 2, -1, -1, -1, -1, -1, -1, 86, 2, -107, 2, 27, 91, 90, 0, 7, 0, 13, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 59, 37, 112, 50, 37, 100, 114, 0, 27, 91, 51, 103, 0, 27, 91, 72, 27, 91, 74, 0, 27, 91, 75, 0, 27, 91, 74, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 59, 37, 112, 50, 37, 100, 72, 0, 10, 0, 27, 91, 72, 0, 27, 91, 63, 50, 53, 108, 0, 8, 0, 27, 91, 51, 52, 104, 27, 91, 63, 50, 53, 104, 0, 27, 91, 67, 0, 27, 77, 0, 27, 91, 51, 52, 108, 0, 27, 91, 80, 0, 27, 91, 77, 0, 14, 0, 27, 91, 53, 109, 0, 27, 91, 49, 109, 0, 27, 91, 63, 49, 48, 52, 57, 104, 0, 27, 91, 52, 104, 0, 27, 91, 55, 109, 0, 27, 91, 51, 109, 0, 27, 91, 52, 109, 0, 15, 0, 27, 91, 109, 15, 0, 27, 91, 63, 49, 48, 52, 57, 108, 0, 27, 91, 52, 108, 0, 27, 91, 50, 51, 109, 0, 27, 91, 50, 52, 109, 0, 27, 103, 0, 27, 41, 48, 0, 27, 91, 76, 0, 8, 0, 27, 91, 51, 126, 0, 27, 79, 66, 0, 27, 79, 80, 0, 27, 91, 50, 49, 126, 0, 27, 79, 81, 0, 27, 79, 82, 0, 27, 79, 83, 0, 27, 91, 49, 53, 126, 0, 27, 91, 49, 55, 126, 0, 27, 91, 49, 56, 126, 0, 27, 91, 49, 57, 126, 0, 27, 91, 50, 48, 126, 0, 27, 91, 49, 126, 0, 27, 91, 50, 126, 0, 27, 79, 68, 0, 27, 91, 54, 126, 0, 27, 91, 53, 126, 0, 27, 79, 67, 0, 27, 79, 65, 0, 27, 91, 63, 49, 108, 27, 62, 0, 27, 91, 63, 49, 104, 27, 61, 0, 27, 69, 0, 27, 91, 37, 112, 49, 37, 100, 80, 0, 27, 91, 37, 112, 49, 37, 100, 77, 0, 27, 91, 37, 112, 49, 37, 100, 66, 0, 27, 91, 37, 112, 49, 37, 100, 64, 0, 27, 91, 37, 112, 49, 37, 100, 76, 0, 27, 91, 37, 112, 49, 37, 100, 68, 0, 27, 91, 37, 112, 49, 37, 100, 67, 0, 27, 91, 37, 112, 49, 37, 100, 65, 0, 27, 99, 27, 91, 63, 49, 48, 48, 48, 108, 27, 91, 63, 50, 53, 104, 0, 27, 56, 0, 27, 55, 0, 10, 0, 27, 77, 0, 27, 91, 48, 37, 63, 37, 112, 54, 37, 116, 59, 49, 37, 59, 37, 63, 37, 112, 49, 37, 116, 59, 51, 37, 59, 37, 63, 37, 112, 50, 37, 116, 59, 52, 37, 59, 37, 63, 37, 112, 51, 37, 116, 59, 55, 37, 59, 37, 63, 37, 112, 52, 37, 116, 59, 53, 37, 59, 109, 37, 63, 37, 112, 57, 37, 116, 14, 37, 101, 15, 37, 59, 0, 27, 72, 0, 9, 0, 43, 43, 44, 44, 45, 45, 46, 46, 48, 48, 96, 96, 97, 97, 102, 102, 103, 103, 104, 104, 105, 105, 106, 106, 107, 107, 108, 108, 109, 109, 110, 110, 111, 111, 112, 112, 113, 113, 114, 114, 115, 115, 116, 116, 117, 117, 118, 118, 119, 119, 120, 120, 121, 121, 122, 122, 123, 123, 124, 124, 125, 125, 126, 126, 0, 27, 91, 90, 0, 27, 40, 66, 27, 41, 48, 0, 27, 91, 52, 126, 0, 27, 91, 50, 51, 126, 0, 27, 91, 50, 52, 126, 0, 27, 91, 49, 75, 0, 27, 91, 51, 57, 59, 52, 57, 109, 0, 27, 91, 77, 0, 27, 91, 37, 63, 37, 112, 49, 37, 123, 56, 125, 37, 60, 37, 116, 51, 37, 112, 49, 37, 100, 37, 101, 37, 112, 49, 37, 123, 49, 54, 125, 37, 60, 37, 116, 57, 37, 112, 49, 37, 123, 56, 125, 37, 45, 37, 100, 37, 101, 51, 56, 59, 53, 59, 37, 112, 49, 37, 100, 37, 59, 109, 0, 27, 91, 37, 63, 37, 112, 49, 37, 123, 56, 125, 37, 60, 37, 116, 52, 37, 112, 49, 37, 100, 37, 101, 37, 112, 49, 37, 123, 49, 54, 125, 37, 60, 37, 116, 49, 48, 37, 112, 49, 37, 123, 56, 125, 37, 45, 37, 100, 37, 101, 52, 56, 59, 53, 59, 37, 112, 49, 37, 100, 37, 59, 109, 0, 0, 3, 0, 1, 0, 24, 0, 52, 0, -112, 0, 1, 1, 0, 0, 1, 0, 0, 0, 4, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 3, 0, 6, 0, 9, 0, 12, 0, 15, 0, 18, 0, 23, 0, 28, 0, 32, 0, 37, 0, 43, 0, 49, 0, 55, 0, 61, 0, 66, 0, 71, 0, 77, 0, 83, 0, 89, 0, 95, 0, 101, 0, 107, 0, 111, 0, 116, 0, 120, 0, 124, 0, -128, 0, 27, 40, 66, 0, 27, 40, 37, 112, 49, 37, 99, 0, 65, 88, 0, 71, 48, 0, 88, 84, 0, 85, 56, 0, 69, 48, 0, 83, 48, 0, 107, 68, 67, 53, 0, 107, 68, 67, 54, 0, 107, 68, 78, 0, 107, 68, 78, 53, 0, 107, 69, 78, 68, 53, 0, 107, 69, 78, 68, 54, 0, 107, 72, 79, 77, 53, 0, 107, 72, 79, 77, 54, 0, 107, 73, 67, 53, 0, 107, 73, 67, 54, 0, 107, 76, 70, 84, 53, 0, 107, 78, 88, 84, 53, 0, 107, 78, 88, 84, 54, 0, 107, 80, 82, 86, 53, 0, 107, 80, 82, 86, 54, 0, 107, 82, 73, 84, 53, 0, 107, 85, 80, 0, 107, 85, 80, 53, 0, 107, 97, 50, 0, 107, 98, 49, 0, 107, 98, 51, 0, 107, 99, 50, 0 +}; +// Taken from Dickey ncurses terminfo.src dated 2017-04-22. +static const signed char iterm_256colour_terminfo[] = { + 26, 1, 57, 0, 29, 0, 15, 0, 105, 1, 73, 3, 105, 84, 101, 114, 109, 46, 97, 112, 112, 124, 105, 116, 101, 114, 109, 124, 105, 84, 101, 114, 109, 46, 97, 112, 112, 32, 116, 101, 114, 109, 105, 110, 97, 108, 32, 101, 109, 117, 108, 97, 116, 111, 114, 32, 102, 111, 114, 32, 77, 97, 99, 32, 79, 83, 32, 88, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 80, 0, 8, 0, 24, 0, -1, -1, -1, -1, -1, -1, -1, -1, 50, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, -1, 127, -1, -1, 0, 0, 2, 0, -2, -1, 4, 0, 9, 0, 16, 0, 20, 0, 24, 0, -1, -1, 35, 0, 52, 0, 54, 0, 58, 0, 65, 0, -1, -1, 67, 0, 74, 0, -1, -1, 78, 0, -1, -1, 82, 0, 86, 0, 90, 0, -1, -1, 96, 0, 98, 0, 103, 0, 108, 0, -1, -1, -2, -1, 117, 0, 122, 0, -1, -1, 127, 0,-124, 0,-119, 0, -1, -1,-114, 0,-112, 0,-107, 0, -1, -1, -94, 0, -89, 0, -85, 0, -81, 0, -1, -1, -63, 0, -1, -1, -1, -1, -1, -1, -1, -1, -61, 0, -57, 0, -1, -1, -53, 0, -1, -1, -1, -1, -1, -1, -51, 0, -1, -1, -46, 0, -1, -1, -1, -1, -1, -1, -1, -1, -42, 0, -38, 0, -32, 0, -28, 0, -24, 0, -20, 0, -14, 0, -8, 0, -2, 0, 4, 1, 10, 1, -1, -1, -1, -1, 14, 1, -1, -1, 18, 1, 23, 1, 28, 1, -1, -1, -1, -1, -1, -1, 32, 1, 36, 1, 44, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 52, 1, 61, 1, 70, 1, 79, 1, -1, -1, 88, 1, 97, 1, 106, 1, -1, -1, 115, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 124, 1, -1, -1, -1, -1,-104, 1,-101, 1, -90, 1, -87, 1, -85, 1, -82, 1, -4, 1, -1, -1, -1, 1, 1, 2, -1, -1, -1, -1, -1, -1, 6, 2, 10, 2, 14, 2, 18, 2, 22, 2, -1, -1, -1, -1, 26, 2, -1, -1, -1, -1, -1, -1, -1, -1, 77, 2, 83, 2, -1, -1, -1, -1, 89, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 96, 2, 100, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 104, 2, 110, 2, 116, 2, 122, 2,-128, 2,-122, 2,-116, 2,-110, 2, 104, 2, -98, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -92, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -87, 2, -76, 2, -71, 2, -63, 2, -59, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -54, 2, 9, 3, 7, 0, 13, 0, 27, 91, 51, 103, 0, 27, 91, 72, 27, 91, 74, 0, 27, 91, 75, 0, 27, 91, 74, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 71, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 59, 37, 112, 50, 37, 100, 72, 0, 10, 0, 27, 91, 72, 0, 27, 91, 63, 50, 53, 108, 0, 8, 0, 27, 91, 63, 50, 53, 104, 0, 27, 91, 67, 0, 27, 91, 65, 0, 27, 91, 80, 0, 27, 91, 77, 0, 27, 93, 50, 59, 7, 0, 14, 0, 27, 91, 53, 109, 0, 27, 91, 49, 109, 0, 27, 55, 27, 91, 63, 52, 55, 104, 0, 27, 91, 52, 104, 0, 27, 91, 56, 109, 0, 27, 91, 55, 109, 0, 27, 91, 55, 109, 0, 27, 91, 52, 109, 0, 15, 0, 27, 91, 109, 15, 0, 27, 91, 50, 74, 27, 91, 63, 52, 55, 108, 27, 56, 0, 27, 91, 52, 108, 0, 27, 91, 109, 0, 27, 91, 109, 0, 27, 91, 63, 53, 104, 36, 60, 50, 48, 48, 47, 62, 27, 91, 63, 53, 108, 0, 7, 0, 27, 91, 64, 0, 27, 91, 76, 0, 127, 0, 27, 91, 51, 126, 0, 27, 79, 66, 0, 27, 79, 80, 0, 27, 91, 50, 49, 126, 0, 27, 79, 81, 0, 27, 79, 82, 0, 27, 79, 83, 0, 27, 91, 49, 53, 126, 0, 27, 91, 49, 55, 126, 0, 27, 91, 49, 56, 126, 0, 27, 91, 49, 57, 126, 0, 27, 91, 50, 48, 126, 0, 27, 79, 72, 0, 27, 79, 68, 0, 27, 91, 54, 126, 0, 27, 91, 53, 126, 0, 27, 79, 67, 0, 27, 79, 65, 0, 27, 91, 63, 49, 108, 27, 62, 0, 27, 91, 63, 49, 104, 27, 61, 0, 27, 91, 37, 112, 49, 37, 100, 80, 0, 27, 91, 37, 112, 49, 37, 100, 77, 0, 27, 91, 37, 112, 49, 37, 100, 66, 0, 27, 91, 37, 112, 49, 37, 100, 64, 0, 27, 91, 37, 112, 49, 37, 100, 76, 0, 27, 91, 37, 112, 49, 37, 100, 68, 0, 27, 91, 37, 112, 49, 37, 100, 67, 0, 27, 91, 37, 112, 49, 37, 100, 65, 0, 27, 62, 27, 91, 63, 51, 108, 27, 91, 63, 52, 108, 27, 91, 63, 53, 108, 27, 91, 63, 55, 104, 27, 91, 63, 56, 104, 0, 27, 56, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 100, 0, 27, 55, 0, 10, 0, 27, 77, 0, 27, 91, 48, 37, 63, 37, 112, 54, 37, 116, 59, 49, 37, 59, 37, 63, 37, 112, 50, 37, 116, 59, 52, 37, 59, 37, 63, 37, 112, 49, 37, 112, 51, 37, 124, 37, 116, 59, 55, 37, 59, 37, 63, 37, 112, 52, 37, 116, 59, 53, 37, 59, 37, 63, 37, 112, 55, 37, 116, 59, 56, 37, 59, 109, 37, 63, 37, 112, 57, 37, 116, 14, 37, 101, 15, 37, 59, 0, 27, 72, 0, 9, 0, 27, 93, 50, 59, 0, 27, 79, 113, 0, 27, 79, 115, 0, 27, 79, 114, 0, 27, 79, 112, 0, 27, 79, 110, 0, 96, 96, 97, 97, 102, 102, 103, 103, 106, 106, 107, 107, 108, 108, 109, 109, 110, 110, 111, 111, 112, 112, 113, 113, 114, 114, 115, 115, 116, 116, 117, 117, 118, 118, 119, 119, 120, 120, 121, 121, 122, 122, 123, 123, 124, 124, 125, 125, 126, 126, 0, 27, 91, 63, 55, 104, 0, 27, 91, 63, 55, 108, 0, 27, 40, 66, 27, 41, 48, 0, 27, 79, 70, 0, 27, 79, 77, 0, 27, 91, 50, 51, 126, 0, 27, 91, 50, 52, 126, 0, 27, 91, 50, 53, 126, 0, 27, 91, 50, 54, 126, 0, 27, 91, 50, 56, 126, 0, 27, 91, 50, 57, 126, 0, 27, 91, 51, 49, 126, 0, 27, 91, 50, 50, 126, 0, 27, 91, 51, 51, 126, 0, 27, 91, 51, 52, 126, 0, 27, 91, 49, 75, 0, 27, 91, 37, 105, 37, 100, 59, 37, 100, 82, 0, 27, 91, 54, 110, 0, 27, 91, 63, 49, 59, 50, 99, 0, 27, 91, 99, 0, 27, 91, 48, 109, 0, 27, 91, 37, 63, 37, 112, 49, 37, 123, 56, 125, 37, 60, 37, 116, 51, 37, 112, 49, 37, 100, 37, 101, 37, 112, 49, 37, 123, 49, 54, 125, 37, 60, 37, 116, 57, 37, 112, 49, 37, 123, 56, 125, 37, 45, 37, 100, 37, 101, 51, 56, 59, 53, 59, 37, 112, 49, 37, 100, 37, 59, 109, 0, 27, 91, 37, 63, 37, 112, 49, 37, 123, 56, 125, 37, 60, 37, 116, 52, 37, 112, 49, 37, 100, 37, 101, 37, 112, 49, 37, 123, 49, 54, 125, 37, 60, 37, 116, 49, 48, 37, 112, 49, 37, 123, 56, 125, 37, 45, 37, 100, 37, 101, 52, 56, 59, 53, 59, 37, 112, 49, 37, 100, 37, 59, 109, 0 +}; +// Taken from Dickey ncurses terminfo.src dated 2017-04-22. +// This is a 256-colour terminfo description that lacks true-colour +// capabilities that rxvt actually has. +static const signed char rxvt_256colour_terminfo[] = { + 26, 1, 47, 0, 29, 0, 15, 0, 110, 1, -31, 4, 114, 120, 118, 116, 45, 50, 53, 54, 99, 111, 108, 111, 114, 124, 114, 120, 118, 116, 32, 50, 46, 55, 46, 57, 32, 119, 105, 116, 104, 32, 120, 116, 101, 114, 109, 32, 50, 53, 54, 45, 99, 111, 108, 111, 114, 115, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 80, 0, 8, 0, 24, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, -1, 127, -1, -1, 0, 0, 2, 0, 4, 0, 21, 0, 26, 0, 34, 0, 38, 0, 42, 0, -1, -1, 53, 0, 70, 0, 72, 0, 76, 0, 83, 0, -1, -1, 85, 0, 92, 0, -1, -1, 96, 0, -1, -1, -1, -1, 100, 0, -1, -1, -1, -1, 104, 0, 106, 0, 111, 0, 116, 0, -1, -1, -1, -1, 125, 0, -1, -1, -1, -1,-126, 0,-121, 0,-116, 0, -1, -1,-111, 0,-109, 0,-104, 0, -1, -1, -91, 0, -86, 0, -80, 0, -74, 0, -1, -1, -1, -1, -56, 0, -42, 0, -1, -1, -1, -1, -8, 0, -4, 0, -1, -1, 0, 1, -1, -1, -1, -1, -1, -1, 2, 1, -1, -1, 7, 1, -1, -1, 11, 1, -1, -1, 16, 1, 22, 1, 28, 1, 34, 1, 40, 1, 46, 1, 52, 1, 58, 1, 64, 1, 70, 1, 76, 1, 82, 1, 87, 1, -1, -1, 92, 1, -1, -1, 96, 1, 101, 1, 106, 1, 110, 1, 114, 1, -1, -1, 118, 1, 122, 1, 125, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,-128, 1,-119, 1,-110, 1, -1, -1,-101, 1, -92, 1, -83, 1, -1, -1, -74, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -65, 1, -32, 1, -1, -1, -1, -1, 18, 2, 21, 2, 32, 2, 35, 2, 37, 2, 40, 2, 107, 2, -1, -1, 110, 2, -1, -1, -1, -1, -1, -1, -1, -1, 112, 2, 116, 2, 120, 2, 124, 2,-128, 2, -1, -1, -1, -1,-124, 2, -1, -1, -73, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -69, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -62, 2, -57, 2, -1, -1, -53, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -48, 2, -1, -1, -43, 2, -38, 2, -1, -1, -1, -1, -1, -1, -1, -1, -33, 2, -28, 2, -23, 2, -1, -1, -1, -1, -19, 2, -1, -1, -14, 2, -1, -1, -1, -1, -1, -1, -9, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -5, 2, 1, 3, 7, 3, 13, 3, 19, 3, 25, 3, 31, 3, 37, 3, 43, 3, 49, 3, 55, 3, 61, 3, 67, 3, 73, 3, 79, 3, 85, 3, 91, 3, 97, 3, 103, 3, 109, 3, 115, 3, 121, 3, 127, 3,-123, 3,-117, 3,-111, 3,-105, 3, -99, 3, -93, 3, -87, 3, -81, 3, -75, 3, -69, 3, -63, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -57, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -52, 3, -41, 3, -36, 3, -28, 3, -24, 3, -15, 3, -8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 86, 4, -1, -1, -1, -1, -1, -1, 90, 4,-103, 4, -1, -1, -1, -1, -1, -1, -39, 4, -35, 4, 7, 0, 13, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 59, 37, 112, 50, 37, 100, 114, 0, 27, 91, 51, 103, 0, 27, 91, 72, 27, 91, 50, 74, 0, 27, 91, 75, 0, 27, 91, 74, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 71, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 59, 37, 112, 50, 37, 100, 72, 0, 10, 0, 27, 91, 72, 0, 27, 91, 63, 50, 53, 108, 0, 8, 0, 27, 91, 63, 50, 53, 104, 0, 27, 91, 67, 0, 27, 91, 65, 0, 27, 91, 77, 0, 14, 0, 27, 91, 53, 109, 0, 27, 91, 49, 109, 0, 27, 55, 27, 91, 63, 52, 55, 104, 0, 27, 91, 52, 104, 0, 27, 91, 55, 109, 0, 27, 91, 55, 109, 0, 27, 91, 52, 109, 0, 15, 0, 27, 91, 109, 15, 0, 27, 91, 50, 74, 27, 91, 63, 52, 55, 108, 27, 56, 0, 27, 91, 52, 108, 0, 27, 91, 50, 55, 109, 0, 27, 91, 50, 52, 109, 0, 27, 91, 63, 53, 104, 36, 60, 49, 48, 48, 47, 62, 27, 91, 63, 53, 108, 0, 27, 91, 63, 52, 55, 108, 27, 61, 27, 91, 63, 49, 108, 0, 27, 91, 114, 27, 91, 109, 27, 91, 50, 74, 27, 91, 72, 27, 91, 63, 55, 104, 27, 91, 63, 49, 59, 51, 59, 52, 59, 54, 108, 27, 91, 52, 108, 0, 27, 91, 64, 0, 27, 91, 76, 0, 8, 0, 27, 91, 51, 126, 0, 27, 91, 66, 0, 27, 91, 56, 94, 0, 27, 91, 50, 49, 126, 0, 27, 91, 49, 49, 126, 0, 27, 91, 50, 49, 126, 0, 27, 91, 49, 50, 126, 0, 27, 91, 49, 51, 126, 0, 27, 91, 49, 52, 126, 0, 27, 91, 49, 53, 126, 0, 27, 91, 49, 55, 126, 0, 27, 91, 49, 56, 126, 0, 27, 91, 49, 57, 126, 0, 27, 91, 50, 48, 126, 0, 27, 91, 55, 126, 0, 27, 91, 50, 126, 0, 27, 91, 68, 0, 27, 91, 54, 126, 0, 27, 91, 53, 126, 0, 27, 91, 67, 0, 27, 91, 97, 0, 27, 91, 98, 0, 27, 91, 65, 0, 27, 62, 0, 27, 61, 0, 27, 91, 37, 112, 49, 37, 100, 77, 0, 27, 91, 37, 112, 49, 37, 100, 66, 0, 27, 91, 37, 112, 49, 37, 100, 64, 0, 27, 91, 37, 112, 49, 37, 100, 76, 0, 27, 91, 37, 112, 49, 37, 100, 68, 0, 27, 91, 37, 112, 49, 37, 100, 67, 0, 27, 91, 37, 112, 49, 37, 100, 65, 0, 27, 62, 27, 91, 49, 59, 51, 59, 52, 59, 53, 59, 54, 108, 27, 91, 63, 55, 104, 27, 91, 109, 27, 91, 114, 27, 91, 50, 74, 27, 91, 72, 0, 27, 91, 114, 27, 91, 109, 27, 91, 50, 74, 27, 91, 72, 27, 91, 63, 55, 104, 27, 91, 63, 49, 59, 51, 59, 52, 59, 54, 108, 27, 91, 52, 108, 27, 62, 27, 91, 63, 49, 48, 48, 48, 108, 27, 91, 63, 50, 53, 104, 0, 27, 56, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 100, 0, 27, 55, 0, 10, 0, 27, 77, 0, 27, 91, 48, 37, 63, 37, 112, 54, 37, 116, 59, 49, 37, 59, 37, 63, 37, 112, 50, 37, 116, 59, 52, 37, 59, 37, 63, 37, 112, 49, 37, 112, 51, 37, 124, 37, 116, 59, 55, 37, 59, 37, 63, 37, 112, 52, 37, 116, 59, 53, 37, 59, 109, 37, 63, 37, 112, 57, 37, 116, 14, 37, 101, 15, 37, 59, 0, 27, 72, 0, 9, 0, 27, 79, 119, 0, 27, 79, 121, 0, 27, 79, 117, 0, 27, 79, 113, 0, 27, 79, 115, 0, 96, 96, 97, 97, 102, 102, 103, 103, 106, 106, 107, 107, 108, 108, 109, 109, 110, 110, 111, 111, 112, 112, 113, 113, 114, 114, 115, 115, 116, 116, 117, 117, 118, 118, 119, 119, 120, 120, 121, 121, 122, 122, 123, 123, 124, 124, 125, 125, 126, 126, 0, 27, 91, 90, 0, 27, 40, 66, 27, 41, 48, 0, 27, 91, 56, 126, 0, 27, 79, 77, 0, 27, 91, 49, 126, 0, 27, 91, 51, 36, 0, 27, 91, 52, 126, 0, 27, 91, 56, 36, 0, 27, 91, 55, 36, 0, 27, 91, 50, 36, 0, 27, 91, 100, 0, 27, 91, 54, 36, 0, 27, 91, 53, 36, 0, 27, 91, 99, 0, 27, 91, 50, 51, 126, 0, 27, 91, 50, 52, 126, 0, 27, 91, 50, 53, 126, 0, 27, 91, 50, 54, 126, 0, 27, 91, 50, 56, 126, 0, 27, 91, 50, 57, 126, 0, 27, 91, 51, 49, 126, 0, 27, 91, 51, 50, 126, 0, 27, 91, 51, 51, 126, 0, 27, 91, 51, 52, 126, 0, 27, 91, 50, 51, 36, 0, 27, 91, 50, 52, 36, 0, 27, 91, 49, 49, 94, 0, 27, 91, 49, 50, 94, 0, 27, 91, 49, 51, 94, 0, 27, 91, 49, 52, 94, 0, 27, 91, 49, 53, 94, 0, 27, 91, 49, 55, 94, 0, 27, 91, 49, 56, 94, 0, 27, 91, 49, 57, 94, 0, 27, 91, 50, 48, 94, 0, 27, 91, 50, 49, 94, 0, 27, 91, 50, 51, 94, 0, 27, 91, 50, 52, 94, 0, 27, 91, 50, 53, 94, 0, 27, 91, 50, 54, 94, 0, 27, 91, 50, 56, 94, 0, 27, 91, 50, 57, 94, 0, 27, 91, 51, 49, 94, 0, 27, 91, 51, 50, 94, 0, 27, 91, 51, 51, 94, 0, 27, 91, 51, 52, 94, 0, 27, 91, 50, 51, 64, 0, 27, 91, 50, 52, 64, 0, 27, 91, 49, 75, 0, 27, 91, 37, 105, 37, 100, 59, 37, 100, 82, 0, 27, 91, 54, 110, 0, 27, 91, 63, 49, 59, 50, 99, 0, 27, 91, 99, 0, 27, 91, 51, 57, 59, 52, 57, 109, 0, 27, 93, 49, 48, 52, 7, 0, 27, 93, 52, 59, 37, 112, 49, 37, 100, 59, 114, 103, 98, 58, 37, 112, 50, 37, 123, 50, 53, 53, 125, 37, 42, 37, 123, 49, 48, 48, 48, 125, 37, 47, 37, 50, 46, 50, 88, 47, 37, 112, 51, 37, 123, 50, 53, 53, 125, 37, 42, 37, 123, 49, 48, 48, 48, 125, 37, 47, 37, 50, 46, 50, 88, 47, 37, 112, 52, 37, 123, 50, 53, 53, 125, 37, 42, 37, 123, 49, 48, 48, 48, 125, 37, 47, 37, 50, 46, 50, 88, 27, 92, 0, 27, 91, 77, 0, 27, 91, 37, 63, 37, 112, 49, 37, 123, 56, 125, 37, 60, 37, 116, 51, 37, 112, 49, 37, 100, 37, 101, 37, 112, 49, 37, 123, 49, 54, 125, 37, 60, 37, 116, 57, 37, 112, 49, 37, 123, 56, 125, 37, 45, 37, 100, 37, 101, 51, 56, 59, 53, 59, 37, 112, 49, 37, 100, 37, 59, 109, 0, 27, 91, 37, 63, 37, 112, 49, 37, 123, 56, 125, 37, 60, 37, 116, 52, 37, 112, 49, 37, 100, 37, 101, 37, 112, 49, 37, 123, 49, 54, 125, 37, 60, 37, 116, 49, 48, 37, 112, 49, 37, 123, 56, 125, 37, 45, 37, 100, 37, 101, 52, 56, 59, 53, 59, 37, 112, 49, 37, 100, 37, 59, 109, 0, 27, 40, 66, 0, 27, 40, 48, 0 +}; +// Taken from Dickey ncurses terminfo.src dated 2017-04-22. +// This is a 16-colour terminfo description that lacks true-colour +// and 256-colour capabilities that linux (4.8+) actually has. +static const signed char linux_16colour_terminfo[] = { + 26, 1, 43, 0, 29, 0, 16, 0, 125, 1, 125, 3, 108, 105, 110, 117, 120, 45, 49, 54, 99, 111, 108, 111, 114, 124, 108, 105, 110, 117, 120, 32, 99, 111, 110, 115, 111, 108, 101, 32, 119, 105, 116, 104, 32, 49, 54, 32, 99, 111, 108, 111, 114, 115, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, -1, -1, 8, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 16, 0, 0, 1, 42, 0, -1, -1, 0, 0, 2, 0, 4, 0, 21, 0, 26, 0, 33, 0, 37, 0, 41, 0, -1, -1, 52, 0, 69, 0, 71, 0, 75, 0, 87, 0, -1, -1, 89, 0, 101, 0, -1, -1, 105, 0, 109, 0, 121, 0, 125, 0, -1, -1, -1, -1,-127, 0,-125, 0,-120, 0, -1, -1, -1, -1,-115, 0,-110, 0, -1, -1, -1, -1,-105, 0,-100, 0, -95, 0, -90, 0, -81, 0, -79, 0, -1, -1, -1, -1, -74, 0, -69, 0, -63, 0, -57, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -39, 0, -35, 0, -1, -1, -31, 0, -1, -1, -1, -1, -1, -1, -29, 0, -1, -1, -24, 0, -1, -1, -1, -1, -1, -1, -1, -1, -20, 0, -15, 0, -9, 0, -4, 0, 1, 1, 6, 1, 11, 1, 17, 1, 23, 1, 29, 1, 35, 1, 40, 1, -1, -1, 45, 1, -1, -1, 49, 1, 54, 1, 59, 1, -1, -1, -1, -1, -1, -1, 63, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 67, 1, -1, -1, 70, 1, 79, 1, 88, 1, 97, 1, -1, -1, 106, 1, 115, 1, 124, 1, -1, -1,-123, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,-114, 1, -1, -1, -1, -1, -1, -1,-108, 1,-105, 1, -94, 1, -91, 1, -89, 1, -86, 1, 1, 2, -1, -1, 4, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, 10, 2, -1, -1, 77, 2, -1, -1, -1, -1, 81, 2, 87, 2, -1, -1, -1, -1, 93, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 97, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 102, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 104, 2, 110, 2, 116, 2, 122, 2,-128, 2,-122, 2,-116, 2,-110, 2,-104, 2, -98, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -92, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -87, 2, -76, 2, -71, 2, -65, 2, -61, 2, -52, 2, -48, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 33, 3, -1, -1, -1, -1, -1, -1, 37, 3, 75, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 113, 3, 119, 3, 7, 0, 13, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 59, 37, 112, 50, 37, 100, 114, 0, 27, 91, 51, 103, 0, 27, 91, 72, 27, 91, 74, 0, 27, 91, 75, 0, 27, 91, 74, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 71, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 59, 37, 112, 50, 37, 100, 72, 0, 10, 0, 27, 91, 72, 0, 27, 91, 63, 50, 53, 108, 27, 91, 63, 49, 99, 0, 8, 0, 27, 91, 63, 50, 53, 104, 27, 91, 63, 48, 99, 0, 27, 91, 67, 0, 27, 91, 65, 0, 27, 91, 63, 50, 53, 104, 27, 91, 63, 56, 99, 0, 27, 91, 80, 0, 27, 91, 77, 0, 14, 0, 27, 91, 53, 109, 0, 27, 91, 49, 109, 0, 27, 91, 50, 109, 0, 27, 91, 52, 104, 0, 27, 91, 55, 109, 0, 27, 91, 55, 109, 0, 27, 91, 52, 109, 0, 27, 91, 37, 112, 49, 37, 100, 88, 0, 15, 0, 27, 91, 109, 15, 0, 27, 91, 52, 108, 0, 27, 91, 50, 55, 109, 0, 27, 91, 50, 52, 109, 0, 27, 91, 63, 53, 104, 36, 60, 50, 48, 48, 47, 62, 27, 91, 63, 53, 108, 0, 27, 91, 64, 0, 27, 91, 76, 0, 127, 0, 27, 91, 51, 126, 0, 27, 91, 66, 0, 27, 91, 91, 65, 0, 27, 91, 50, 49, 126, 0, 27, 91, 91, 66, 0, 27, 91, 91, 67, 0, 27, 91, 91, 68, 0, 27, 91, 91, 69, 0, 27, 91, 49, 55, 126, 0, 27, 91, 49, 56, 126, 0, 27, 91, 49, 57, 126, 0, 27, 91, 50, 48, 126, 0, 27, 91, 49, 126, 0, 27, 91, 50, 126, 0, 27, 91, 68, 0, 27, 91, 54, 126, 0, 27, 91, 53, 126, 0, 27, 91, 67, 0, 27, 91, 65, 0, 13, 10, 0, 27, 91, 37, 112, 49, 37, 100, 80, 0, 27, 91, 37, 112, 49, 37, 100, 77, 0, 27, 91, 37, 112, 49, 37, 100, 66, 0, 27, 91, 37, 112, 49, 37, 100, 64, 0, 27, 91, 37, 112, 49, 37, 100, 76, 0, 27, 91, 37, 112, 49, 37, 100, 68, 0, 27, 91, 37, 112, 49, 37, 100, 67, 0, 27, 91, 37, 112, 49, 37, 100, 65, 0, 27, 99, 27, 93, 82, 0, 27, 56, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 100, 0, 27, 55, 0, 10, 0, 27, 77, 0, 27, 91, 48, 59, 49, 48, 37, 63, 37, 112, 49, 37, 116, 59, 55, 37, 59, 37, 63, 37, 112, 50, 37, 116, 59, 52, 37, 59, 37, 63, 37, 112, 51, 37, 116, 59, 55, 37, 59, 37, 63, 37, 112, 52, 37, 116, 59, 53, 37, 59, 37, 63, 37, 112, 53, 37, 116, 59, 50, 37, 59, 37, 63, 37, 112, 54, 37, 116, 59, 49, 37, 59, 109, 37, 63, 37, 112, 57, 37, 116, 14, 37, 101, 15, 37, 59, 0, 27, 72, 0, 9, 0, 27, 91, 71, 0, 43, 43, 44, 44, 45, 45, 46, 46, 48, 48, 95, 95, 96, 96, 97, 97, 102, 102, 103, 103, 104, 104, 105, 105, 106, 106, 107, 107, 108, 108, 109, 109, 110, 110, 111, 111, 112, 112, 113, 113, 114, 114, 115, 115, 116, 116, 117, 117, 118, 118, 119, 119, 120, 120, 121, 121, 122, 122, 123, 123, 124, 124, 125, 99, 126, 126, 0, 27, 91, 90, 0, 27, 91, 63, 55, 104, 0, 27, 91, 63, 55, 108, 0, 27, 41, 48, 0, 27, 91, 52, 126, 0, 26, 0, 27, 91, 50, 51, 126, 0, 27, 91, 50, 52, 126, 0, 27, 91, 50, 53, 126, 0, 27, 91, 50, 54, 126, 0, 27, 91, 50, 56, 126, 0, 27, 91, 50, 57, 126, 0, 27, 91, 51, 49, 126, 0, 27, 91, 51, 50, 126, 0, 27, 91, 51, 51, 126, 0, 27, 91, 51, 52, 126, 0, 27, 91, 49, 75, 0, 27, 91, 37, 105, 37, 100, 59, 37, 100, 82, 0, 27, 91, 54, 110, 0, 27, 91, 63, 54, 99, 0, 27, 91, 99, 0, 27, 91, 51, 57, 59, 52, 57, 109, 0, 27, 93, 82, 0, 27, 93, 80, 37, 112, 49, 37, 120, 37, 112, 50, 37, 123, 50, 53, 53, 125, 37, 42, 37, 123, 49, 48, 48, 48, 125, 37, 47, 37, 48, 50, 120, 37, 112, 51, 37, 123, 50, 53, 53, 125, 37, 42, 37, 123, 49, 48, 48, 48, 125, 37, 47, 37, 48, 50, 120, 37, 112, 52, 37, 123, 50, 53, 53, 125, 37, 42, 37, 123, 49, 48, 48, 48, 125, 37, 47, 37, 48, 50, 120, 0, 27, 91, 77, 0, 27, 91, 51, 37, 112, 49, 37, 123, 56, 125, 37, 109, 37, 100, 37, 63, 37, 112, 49, 37, 123, 55, 125, 37, 62, 37, 116, 59, 49, 37, 101, 59, 50, 49, 37, 59, 109, 0, 27, 91, 52, 37, 112, 49, 37, 123, 56, 125, 37, 109, 37, 100, 37, 63, 37, 112, 49, 37, 123, 55, 125, 37, 62, 37, 116, 59, 53, 37, 101, 59, 50, 53, 37, 59, 109, 0, 27, 91, 49, 49, 109, 0, 27, 91, 49, 48, 109, 0 +}; +// Taken from Dickey ncurses terminfo.src dated 2017-04-22. +static const signed char putty_256colour_terminfo[] = { + 26, 1, 48, 0, 29, 0, 16, 0, 125, 1,-106, 4, 112, 117, 116, 116, 121, 45, 50, 53, 54, 99, 111, 108, 111, 114, 124, 80, 117, 84, 84, 89, 32, 48, 46, 53, 56, 32, 119, 105, 116, 104, 32, 120, 116, 101, 114, 109, 32, 50, 53, 54, 45, 99, 111, 108, 111, 114, 115, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, -1, -1, 8, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, -1, 127, 22, 0, 0, 0, 4, 0, 6, 0, 8, 0, 25, 0, 30, 0, 37, 0, 41, 0, 45, 0, -1, -1, 56, 0, 73, 0, 76, 0, 80, 0, 87, 0, -1, -1, 89, 0, 96, 0, -1, -1, 100, 0, -1, -1, 103, 0, 107, 0, 111, 0, -1, -1, 117, 0, 119, 0, 124, 0,-127, 0, -1, -1, -1, -1,-120, 0, -1, -1, -1, -1,-115, 0,-110, 0,-105, 0,-100, 0, -91, 0, -89, 0, -84, 0, -1, -1, -73, 0, -68, 0, -62, 0, -56, 0, -1, -1, -38, 0, -1, -1, -36, 0, -1, -1, -1, -1, -1, -1, -2, 0, -1, -1, 2, 1, -1, -1, -1, -1, -1, -1, 4, 1, -1, -1, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, 13, 1, 19, 1, 25, 1, 31, 1, 37, 1, 43, 1, 49, 1, 55, 1, 61, 1, 67, 1, 73, 1, 78, 1, -1, -1, 83, 1, -1, -1, 87, 1, 92, 1, 97, 1, 101, 1, 105, 1, -1, -1, 109, 1, 113, 1, 121, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,-127, 1, -1, -1,-124, 1,-115, 1,-106, 1, -1, -1, -97, 1, -88, 1, -79, 1, -70, 1, -61, 1, -52, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -43, 1, -1, -1, -1, -1, -10, 1, -7, 1, 4, 2, 7, 2, 9, 2, 12, 2, 84, 2, -1, -1, 87, 2, 89, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 94, 2, -1, -1, -1, -1, -1, -1, -1, -1, 98, 2, -1, -1,-107, 2, -1, -1, -1, -1,-103, 2, -97, 2, -1, -1, -1, -1, -91, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -84, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -79, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -77, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -73, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -69, 2, -63, 2, -57, 2, -51, 2, -45, 2, -39, 2, -33, 2, -27, 2, -21, 2, -15, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -9, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -4, 2, 7, 3, 12, 3, 18, 3, 22, 3, 31, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 35, 3, -1, -1, -1, -1, -1, -1, 39, 3, 102, 3, -1, -1, -1, -1, -1, -1, -90, 3, -84, 3, -78, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -72, 3,-118, 4,-112, 4, 27, 91, 90, 0, 7, 0, 13, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 59, 37, 112, 50, 37, 100, 114, 0, 27, 91, 51, 103, 0, 27, 91, 72, 27, 91, 74, 0, 27, 91, 75, 0, 27, 91, 74, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 71, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 59, 37, 112, 50, 37, 100, 72, 0, 27, 68, 0, 27, 91, 72, 0, 27, 91, 63, 50, 53, 108, 0, 8, 0, 27, 91, 63, 50, 53, 104, 0, 27, 91, 67, 0, 27, 77, 0, 27, 91, 80, 0, 27, 91, 77, 0, 27, 93, 48, 59, 7, 0, 14, 0, 27, 91, 53, 109, 0, 27, 91, 49, 109, 0, 27, 91, 63, 52, 55, 104, 0, 27, 91, 52, 104, 0, 27, 91, 55, 109, 0, 27, 91, 55, 109, 0, 27, 91, 52, 109, 0, 27, 91, 37, 112, 49, 37, 100, 88, 0, 15, 0, 27, 91, 109, 15, 0, 27, 91, 50, 74, 27, 91, 63, 52, 55, 108, 0, 27, 91, 52, 108, 0, 27, 91, 50, 55, 109, 0, 27, 91, 50, 52, 109, 0, 27, 91, 63, 53, 104, 36, 60, 49, 48, 48, 47, 62, 27, 91, 63, 53, 108, 0, 7, 0, 27, 55, 27, 91, 114, 27, 91, 109, 27, 91, 63, 55, 104, 27, 91, 63, 49, 59, 52, 59, 54, 108, 27, 91, 52, 108, 27, 56, 27, 62, 27, 93, 82, 0, 27, 91, 76, 0, 127, 0, 27, 91, 51, 126, 0, 27, 79, 66, 0, 27, 91, 49, 49, 126, 0, 27, 91, 50, 49, 126, 0, 27, 91, 49, 50, 126, 0, 27, 91, 49, 51, 126, 0, 27, 91, 49, 52, 126, 0, 27, 91, 49, 53, 126, 0, 27, 91, 49, 55, 126, 0, 27, 91, 49, 56, 126, 0, 27, 91, 49, 57, 126, 0, 27, 91, 50, 48, 126, 0, 27, 91, 49, 126, 0, 27, 91, 50, 126, 0, 27, 79, 68, 0, 27, 91, 54, 126, 0, 27, 91, 53, 126, 0, 27, 79, 67, 0, 27, 91, 66, 0, 27, 91, 65, 0, 27, 79, 65, 0, 27, 91, 63, 49, 108, 27, 62, 0, 27, 91, 63, 49, 104, 27, 61, 0, 13, 10, 0, 27, 91, 37, 112, 49, 37, 100, 80, 0, 27, 91, 37, 112, 49, 37, 100, 77, 0, 27, 91, 37, 112, 49, 37, 100, 66, 0, 27, 91, 37, 112, 49, 37, 100, 83, 0, 27, 91, 37, 112, 49, 37, 100, 76, 0, 27, 91, 37, 112, 49, 37, 100, 68, 0, 27, 91, 37, 112, 49, 37, 100, 67, 0, 27, 91, 37, 112, 49, 37, 100, 84, 0, 27, 91, 37, 112, 49, 37, 100, 65, 0, 27, 60, 27, 91, 34, 112, 27, 91, 53, 48, 59, 54, 34, 112, 27, 99, 27, 91, 63, 51, 108, 27, 93, 82, 27, 91, 63, 49, 48, 48, 48, 108, 0, 27, 56, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 100, 0, 27, 55, 0, 10, 0, 27, 77, 0, 27, 91, 48, 37, 63, 37, 112, 49, 37, 112, 54, 37, 124, 37, 116, 59, 49, 37, 59, 37, 63, 37, 112, 50, 37, 116, 59, 52, 37, 59, 37, 63, 37, 112, 49, 37, 112, 51, 37, 124, 37, 116, 59, 55, 37, 59, 37, 63, 37, 112, 52, 37, 116, 59, 53, 37, 59, 109, 37, 63, 37, 112, 57, 37, 116, 14, 37, 101, 15, 37, 59, 0, 27, 72, 0, 9, 0, 27, 93, 48, 59, 0, 27, 91, 71, 0, 96, 96, 97, 97, 102, 102, 103, 103, 106, 106, 107, 107, 108, 108, 109, 109, 110, 110, 111, 111, 112, 112, 113, 113, 114, 114, 115, 115, 116, 116, 117, 117, 118, 118, 119, 119, 120, 120, 121, 121, 122, 122, 123, 123, 124, 124, 125, 125, 126, 126, 0, 27, 91, 90, 0, 27, 91, 63, 55, 104, 0, 27, 91, 63, 55, 108, 0, 27, 40, 66, 27, 41, 48, 0, 27, 91, 52, 126, 0, 26, 0, 27, 91, 68, 0, 27, 91, 67, 0, 27, 91, 50, 51, 126, 0, 27, 91, 50, 52, 126, 0, 27, 91, 50, 53, 126, 0, 27, 91, 50, 54, 126, 0, 27, 91, 50, 56, 126, 0, 27, 91, 50, 57, 126, 0, 27, 91, 51, 49, 126, 0, 27, 91, 51, 50, 126, 0, 27, 91, 51, 51, 126, 0, 27, 91, 51, 52, 126, 0, 27, 91, 49, 75, 0, 27, 91, 37, 105, 37, 100, 59, 37, 100, 82, 0, 27, 91, 54, 110, 0, 27, 91, 63, 54, 99, 0, 27, 91, 99, 0, 27, 91, 51, 57, 59, 52, 57, 109, 0, 27, 93, 82, 0, 27, 91, 77, 0, 27, 91, 37, 63, 37, 112, 49, 37, 123, 56, 125, 37, 60, 37, 116, 51, 37, 112, 49, 37, 100, 37, 101, 37, 112, 49, 37, 123, 49, 54, 125, 37, 60, 37, 116, 57, 37, 112, 49, 37, 123, 56, 125, 37, 45, 37, 100, 37, 101, 51, 56, 59, 53, 59, 37, 112, 49, 37, 100, 37, 59, 109, 0, 27, 91, 37, 63, 37, 112, 49, 37, 123, 56, 125, 37, 60, 37, 116, 52, 37, 112, 49, 37, 100, 37, 101, 37, 112, 49, 37, 123, 49, 54, 125, 37, 60, 37, 116, 49, 48, 37, 112, 49, 37, 123, 56, 125, 37, 45, 37, 100, 37, 101, 52, 56, 59, 53, 59, 37, 112, 49, 37, 100, 37, 59, 109, 0, 27, 91, 49, 48, 109, 0, 27, 91, 49, 49, 109, 0, 27, 91, 49, 50, 109, 0, 37, 63, 37, 112, 49, 37, 123, 56, 125, 37, 61, 37, 116, 27, 37, 37, 71, -30,-105,-104, 27, 37, 37, 64, 37, 101, 37, 112, 49, 37, 123, 49, 48, 125, 37, 61, 37, 116, 27, 37, 37, 71, -30,-105,-103, 27, 37, 37, 64, 37, 101, 37, 112, 49, 37, 123, 49, 50, 125, 37, 61, 37, 116, 27, 37, 37, 71, -30,-103,-128, 27, 37, 37, 64, 37, 101, 37, 112, 49, 37, 123, 49, 51, 125, 37, 61, 37, 116, 27, 37, 37, 71, -30,-103, -86, 27, 37, 37, 64, 37, 101, 37, 112, 49, 37, 123, 49, 52, 125, 37, 61, 37, 116, 27, 37, 37, 71, -30,-103, -85, 27, 37, 37, 64, 37, 101, 37, 112, 49, 37, 123, 49, 53, 125, 37, 61, 37, 116, 27, 37, 37, 71, -30,-104, -68, 27, 37, 37, 64, 37, 101, 37, 112, 49, 37, 123, 50, 55, 125, 37, 61, 37, 116, 27, 37, 37, 71, -30,-122,-112, 27, 37, 37, 64, 37, 101, 37, 112, 49, 37, 123, 49, 53, 53, 125, 37, 61, 37, 116, 27, 37, 37, 71, -32,-126, -94, 27, 37, 37, 64, 37, 101, 37, 112, 49, 37, 99, 37, 59, 0, 27, 91, 49, 49, 109, 0, 27, 91, 49, 48, 109, 0 +}; +// Taken from Dickey ncurses terminfo.src dated 2017-04-22. +static const signed char interix_8colour_terminfo[] = { + 26, 1, 82, 0, 15, 0, 16, 0, 105, 1, 123, 2, 105, 110, 116, 101, 114, 105, 120, 124, 111, 112, 101, 110, 110, 116, 124, 111, 112, 101, 110, 110, 116, 45, 50, 53, 124, 110, 116, 99, 111, 110, 115, 111, 108, 101, 124, 110, 116, 99, 111, 110, 115, 111, 108, 101, 45, 50, 53, 124, 79, 112, 101, 110, 78, 84, 45, 116, 101, 114, 109, 32, 99, 111, 109, 112, 97, 116, 105, 98, 108, 101, 32, 119, 105, 116, 104, 32, 99, 111, 108, 111, 114, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 80, 0, -1, -1, 25, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8, 0, 64, 0, 3, 0, 0, 0, 4, 0, -1, -1, -1, -1, -1, -1, 6, 0, 11, 0, 15, 0, -1, -1, -1, -1, 19, 0, 36, 0, 38, 0, -1, -1, 42, 0, -1, -1, -1, -1, 46, 0, 50, 0, 54, 0, -1, -1, -1, -1, 58, 0, -1, -1, -1, -1, -1, -1, -1, -1, 62, 0, 67, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 75, 0, 80, 0, 85, 0, -1, -1, -1, -1, 90, 0, 95, 0, -1, -1, -1, -1, 107, 0, 111, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 115, 0, -1, -1, 119, 0, -1, -1, -1, -1, -1, -1, 121, 0, -1, -1, 125, 0, -1, -1, -1, -1, -1, -1,-127, 0,-123, 0,-119, 0,-115, 0,-111, 0,-107, 0,-103, 0, -99, 0, -95, 0, -91, 0, -87, 0, -1, -1, -83, 0, -1, -1, -79, 0, -75, 0, -71, 0, -67, 0, -63, 0, -1, -1, -1, -1, -1, -1, -59, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -55, 0, -1, -1, -1, -1, -52, 0, -43, 0, -1, -1, -34, 0, -25, 0, -16, 0, -7, 0, 2, 1, 11, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 20, 1, -1, -1, -1, -1, -1, -1, 23, 1, -1, -1, 27, 1, 31, 1, 35, 1, -1, -1, -1, -1, -1, -1, 39, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 41, 1, -1, -1, 104, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 108, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 112, 1, 116, 1, 120, 1, 124, 1,-128, 1,-124, 1,-120, 1,-116, 1,-112, 1,-108, 1,-104, 1,-100, 1, -96, 1, -92, 1, -88, 1, -84, 1, -80, 1, -76, 1, -72, 1, -68, 1, -64, 1, -60, 1, -56, 1, -52, 1, -48, 1, -44, 1, -40, 1, -36, 1, -32, 1, -28, 1, -24, 1, -20, 1, -16, 1, -12, 1, -8, 1, -4, 1, 0, 2, 4, 2, 8, 2, 12, 2, 16, 2, 20, 2, 24, 2, 28, 2, 32, 2, 36, 2, 40, 2, 44, 2, 48, 2, 52, 2, 56, 2, 60, 2, 64, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 68, 2, -1, -1, -1, -1, -1, -1, -1, -1, 72, 2, 88, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 103, 2, 113, 2, 27, 91, 90, 0, 7, 0, 27, 91, 50, 74, 0, 27, 91, 75, 0, 27, 91, 74, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 59, 37, 112, 50, 37, 100, 72, 0, 10, 0, 27, 91, 72, 0, 27, 91, 68, 0, 27, 91, 67, 0, 27, 91, 85, 0, 27, 91, 65, 0, 27, 91, 77, 0, 27, 91, 49, 109, 0, 27, 91, 115, 27, 91, 49, 98, 0, 27, 91, 55, 109, 0, 27, 91, 55, 109, 0, 27, 91, 52, 109, 0, 27, 91, 48, 109, 0, 27, 91, 50, 98, 27, 91, 117, 13, 27, 91, 75, 0, 27, 91, 109, 0, 27, 91, 109, 0, 27, 91, 76, 0, 8, 0, 27, 91, 77, 0, 27, 91, 66, 0, 27, 70, 65, 0, 27, 70, 49, 0, 27, 70, 65, 0, 27, 70, 50, 0, 27, 70, 51, 0, 27, 70, 52, 0, 27, 70, 53, 0, 27, 70, 54, 0, 27, 70, 55, 0, 27, 70, 56, 0, 27, 70, 57, 0, 27, 91, 76, 0, 27, 91, 68, 0, 27, 91, 85, 0, 27, 91, 84, 0, 27, 91, 83, 0, 27, 91, 67, 0, 27, 91, 65, 0, 13, 10, 0, 27, 91, 37, 112, 49, 37, 100, 77, 0, 27, 91, 37, 112, 49, 37, 100, 66, 0, 27, 91, 37, 112, 49, 37, 100, 83, 0, 27, 91, 37, 112, 49, 37, 100, 76, 0, 27, 91, 37, 112, 49, 37, 100, 68, 0, 27, 91, 37, 112, 49, 37, 100, 67, 0, 27, 91, 37, 112, 49, 37, 100, 84, 0, 27, 91, 37, 112, 49, 37, 100, 65, 0, 27, 99, 0, 27, 91, 117, 0, 27, 91, 115, 0, 27, 91, 83, 0, 27, 91, 84, 0, 9, 0, 43, 16, 44, 17, 45, 24, 46, 25, 48, -37, 96, 4, 97, -79, 102, -8, 103, -15, 104, -80, 106, -39, 107, -65, 108, -38, 109, -64, 110, -59, 111, 126, 112, -60, 113, -60, 114, -60, 115, 95, 116, -61, 117, -76, 118, -63, 119, -62, 120, -77, 121, -13, 122, -14, 123, -29, 124, -40, 125,-100, 126, -2, 0, 27, 91, 90, 0, 27, 91, 85, 0, 27, 70, 66, 0, 27, 70, 67, 0, 27, 70, 68, 0, 27, 70, 69, 0, 27, 70, 70, 0, 27, 70, 71, 0, 27, 70, 72, 0, 27, 70, 73, 0, 27, 70, 74, 0, 27, 70, 75, 0, 27, 70, 76, 0, 27, 70, 77, 0, 27, 70, 78, 0, 27, 70, 79, 0, 27, 70, 80, 0, 27, 70, 81, 0, 27, 70, 82, 0, 27, 70, 83, 0, 27, 70, 84, 0, 27, 70, 85, 0, 27, 70, 86, 0, 27, 70, 87, 0, 27, 70, 88, 0, 27, 70, 89, 0, 27, 70, 90, 0, 27, 70, 97, 0, 27, 70, 98, 0, 27, 70, 99, 0, 27, 70, 100, 0, 27, 70, 101, 0, 27, 70, 102, 0, 27, 70, 103, 0, 27, 70, 104, 0, 27, 70, 105, 0, 27, 70, 106, 0, 27, 70, 107, 0, 27, 70, 109, 0, 27, 70, 110, 0, 27, 70, 111, 0, 27, 70, 112, 0, 27, 70, 113, 0, 27, 70, 114, 0, 27, 70, 115, 0, 27, 70, 116, 0, 27, 70, 117, 0, 27, 70, 118, 0, 27, 70, 119, 0, 27, 70, 120, 0, 27, 70, 121, 0, 27, 70, 122, 0, 27, 70, 43, 0, 27, 70, 45, 0, 27, 70, 12, 0, 27, 91, 109, 0, 27, 91, 37, 112, 49, 37, 123, 51, 48, 125, 37, 43, 37, 100, 109, 0, 27, 91, 37, 112, 49, 37, 39, 40, 39, 37, 43, 37, 100, 109, 0, 27, 91, 51, 37, 112, 49, 37, 100, 109, 0, 27, 91, 52, 37, 112, 49, 37, 100, 109, 0 +}; +// Taken from Dickey ncurses terminfo.src dated 2017-04-22. +// This is a 256-colour terminfo description that lacks true-colour +// capabilities that stterm actually has. +static const signed char st_256colour_terminfo[] = { + 26, 1, 55, 0, 29, 0, 15, 0, 105, 1, 117, 5, 115, 116, 45, 50, 53, 54, 99, 111, 108, 111, 114, 124, 115, 116, 116, 101, 114, 109, 45, 50, 53, 54, 99, 111, 108, 111, 114, 124, 115, 105, 109, 112, 108, 101, 116, 101, 114, 109, 32, 119, 105, 116, 104, 32, 50, 53, 54, 32, 99, 111, 108, 111, 114, 115, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 80, 0, 8, 0, 24, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, -1, 127, 0, 0, 4, 0, 6, 0, 8, 0, 25, 0, 30, 0, 38, 0, 42, 0, 46, 0, -1, -1, 57, 0, 74, 0, 76, 0, 80, 0, 87, 0, -1, -1, 89, 0, 102, 0, -1, -1, 106, 0, 110, 0, 117, 0, 121, 0, -1, -1, -1, -1, 125, 0,-127, 0,-122, 0,-117, 0, -1, -1, -1, -1,-108, 0,-103, 0, -1, -1, -98, 0, -93, 0, -88, 0, -83, 0, -74, 0, -70, 0, -65, 0, -1, -1, -56, 0, -51, 0, -45, 0, -39, 0, -1, -1, -21, 0, -1, -1, -19, 0, -1, -1, -1, -1, -1, -1, -4, 0, -1, -1, 0, 1, -1, -1, 2, 1, -1, -1, 9, 1, 14, 1, 21, 1, 25, 1, 32, 1, 39, 1, -1, -1, 46, 1, 50, 1, 56, 1, 60, 1, 64, 1, 68, 1, 74, 1, 80, 1, 86, 1, 92, 1, 98, 1, 103, 1, 108, 1, 115, 1, -1, -1, 119, 1, 124, 1,-127, 1,-123, 1,-116, 1, -1, -1,-109, 1,-105, 1, -97, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -89, 1, -80, 1, -71, 1, -62, 1, -53, 1, -44, 1, -35, 1, -26, 1, -1, -1, -17, 1, -1, -1, -1, -1, -1, -1, -8, 1, -4, 1, 1, 2, -1, -1, 6, 2, 9, 2, -1, -1, -1, -1, 24, 2, 27, 2, 38, 2, 41, 2, 43, 2, 46, 2,-128, 2, -1, -1,-125, 2,-123, 2, -1, -1, -1, -1, -1, -1,-118, 2,-113, 2,-108, 2,-104, 2, -99, 2, -1, -1, -1, -1, -94, 2, -1, -1, -29, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -25, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -21, 2, -16, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -12, 2, -1, -1, -1, -1, -5, 2, -1, -1, -1, -1, -1, -1, -1, -1, 2, 3, 9, 3, 16, 3, -1, -1, -1, -1, 23, 3, -1, -1, 30, 3, -1, -1, -1, -1, -1, -1, 37, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 44, 3, 50, 3, 56, 3, 63, 3, 70, 3, 77, 3, 84, 3, 92, 3, 100, 3, 108, 3, 116, 3, 124, 3,-124, 3,-116, 3,-108, 3,-101, 3, -94, 3, -87, 3, -80, 3, -72, 3, -64, 3, -56, 3, -48, 3, -40, 3, -32, 3, -24, 3, -16, 3, -9, 3, -2, 3, 5, 4, 12, 4, 20, 4, 28, 4, 36, 4, 44, 4, 52, 4, 60, 4, 68, 4, 76, 4, 83, 4, 90, 4, 97, 4, 104, 4, 112, 4, 120, 4,-128, 4,-120, 4,-112, 4,-104, 4, -96, 4, -88, 4, -81, 4, -74, 4, -67, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -62, 4, -51, 4, -46, 4, -38, 4, -34, 4, -2, -1, -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -25, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -20, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -14, 4, -1, -1, -1, -1, -1, -1, -10, 4, 53, 5, 27, 91, 90, 0, 7, 0, 13, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 59, 37, 112, 50, 37, 100, 114, 0, 27, 91, 51, 103, 0, 27, 91, 72, 27, 91, 50, 74, 0, 27, 91, 75, 0, 27, 91, 74, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 71, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 59, 37, 112, 50, 37, 100, 72, 0, 10, 0, 27, 91, 72, 0, 27, 91, 63, 50, 53, 108, 0, 8, 0, 27, 91, 63, 49, 50, 108, 27, 91, 63, 50, 53, 104, 0, 27, 91, 67, 0, 27, 91, 65, 0, 27, 91, 63, 50, 53, 104, 0, 27, 91, 80, 0, 27, 91, 77, 0, 27, 40, 48, 0, 27, 91, 53, 109, 0, 27, 91, 49, 109, 0, 27, 91, 63, 49, 48, 52, 57, 104, 0, 27, 91, 52, 104, 0, 27, 91, 56, 109, 0, 27, 91, 55, 109, 0, 27, 91, 55, 109, 0, 27, 91, 52, 109, 0, 27, 91, 37, 112, 49, 37, 100, 88, 0, 27, 40, 66, 0, 27, 91, 48, 109, 0, 27, 91, 63, 49, 48, 52, 57, 108, 0, 27, 91, 52, 108, 0, 27, 91, 50, 55, 109, 0, 27, 91, 50, 52, 109, 0, 27, 91, 63, 53, 104, 36, 60, 49, 48, 48, 47, 62, 27, 91, 63, 53, 108, 0, 7, 0, 27, 91, 52, 108, 27, 62, 27, 91, 63, 49, 48, 51, 52, 108, 0, 27, 91, 76, 0, 127, 0, 27, 91, 51, 59, 53, 126, 0, 27, 91, 51, 126, 0, 27, 91, 51, 59, 50, 126, 0, 27, 79, 66, 0, 27, 91, 50, 59, 50, 126, 0, 27, 91, 49, 59, 50, 70, 0, 27, 91, 49, 59, 53, 70, 0, 27, 79, 80, 0, 27, 91, 50, 49, 126, 0, 27, 79, 81, 0, 27, 79, 82, 0, 27, 79, 83, 0, 27, 91, 49, 53, 126, 0, 27, 91, 49, 55, 126, 0, 27, 91, 49, 56, 126, 0, 27, 91, 49, 57, 126, 0, 27, 91, 50, 48, 126, 0, 27, 91, 49, 126, 0, 27, 91, 50, 126, 0, 27, 91, 50, 59, 53, 126, 0, 27, 79, 68, 0, 27, 91, 54, 126, 0, 27, 91, 53, 126, 0, 27, 79, 67, 0, 27, 91, 49, 59, 50, 66, 0, 27, 91, 49, 59, 50, 65, 0, 27, 79, 65, 0, 27, 91, 63, 49, 108, 27, 62, 0, 27, 91, 63, 49, 104, 27, 61, 0, 27, 91, 37, 112, 49, 37, 100, 80, 0, 27, 91, 37, 112, 49, 37, 100, 77, 0, 27, 91, 37, 112, 49, 37, 100, 66, 0, 27, 91, 37, 112, 49, 37, 100, 64, 0, 27, 91, 37, 112, 49, 37, 100, 83, 0, 27, 91, 37, 112, 49, 37, 100, 76, 0, 27, 91, 37, 112, 49, 37, 100, 68, 0, 27, 91, 37, 112, 49, 37, 100, 67, 0, 27, 91, 37, 112, 49, 37, 100, 65, 0, 27, 91, 105, 0, 27, 91, 52, 105, 0, 27, 91, 53, 105, 0, 27, 99, 0, 27, 91, 52, 108, 27, 62, 27, 91, 63, 49, 48, 51, 52, 108, 0, 27, 56, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 100, 0, 27, 55, 0, 10, 0, 27, 77, 0, 37, 63, 37, 112, 57, 37, 116, 27, 40, 48, 37, 101, 27, 40, 66, 37, 59, 27, 91, 48, 37, 63, 37, 112, 54, 37, 116, 59, 49, 37, 59, 37, 63, 37, 112, 50, 37, 116, 59, 52, 37, 59, 37, 63, 37, 112, 49, 37, 112, 51, 37, 124, 37, 116, 59, 55, 37, 59, 37, 63, 37, 112, 52, 37, 116, 59, 53, 37, 59, 37, 63, 37, 112, 55, 37, 116, 59, 56, 37, 59, 109, 0, 27, 72, 0, 9, 0, 27, 93, 48, 59, 0, 27, 91, 49, 126, 0, 27, 91, 53, 126, 0, 27, 79, 117, 0, 27, 91, 52, 126, 0, 27, 91, 54, 126, 0, 43, 67, 44, 68, 45, 65, 46, 66, 48, 69, 96, 96, 97, 97, 102, 102, 103, 103, 104, 70, 105, 71, 106, 106, 107, 107, 108, 108, 109, 109, 110, 110, 111, 111, 112, 112, 113, 113, 114, 114, 115, 115, 116, 116, 117, 117, 118, 118, 119, 119, 120, 120, 121, 121, 122, 122, 123, 123, 124, 124, 125, 125, 126, 126, 0, 27, 91, 90, 0, 27, 41, 48, 0, 27, 91, 52, 126, 0, 27, 79, 77, 0, 27, 91, 51, 59, 50, 126, 0, 27, 91, 49, 59, 50, 70, 0, 27, 91, 49, 59, 50, 72, 0, 27, 91, 50, 59, 50, 126, 0, 27, 91, 49, 59, 50, 68, 0, 27, 91, 54, 59, 50, 126, 0, 27, 91, 53, 59, 50, 126, 0, 27, 91, 49, 59, 50, 67, 0, 27, 91, 50, 51, 126, 0, 27, 91, 50, 52, 126, 0, 27, 91, 49, 59, 50, 80, 0, 27, 91, 49, 59, 50, 81, 0, 27, 91, 49, 59, 50, 82, 0, 27, 91, 49, 59, 50, 83, 0, 27, 91, 49, 53, 59, 50, 126, 0, 27, 91, 49, 55, 59, 50, 126, 0, 27, 91, 49, 56, 59, 50, 126, 0, 27, 91, 49, 57, 59, 50, 126, 0, 27, 91, 50, 48, 59, 50, 126, 0, 27, 91, 50, 49, 59, 50, 126, 0, 27, 91, 50, 51, 59, 50, 126, 0, 27, 91, 50, 52, 59, 50, 126, 0, 27, 91, 49, 59, 53, 80, 0, 27, 91, 49, 59, 53, 81, 0, 27, 91, 49, 59, 53, 82, 0, 27, 91, 49, 59, 53, 83, 0, 27, 91, 49, 53, 59, 53, 126, 0, 27, 91, 49, 55, 59, 53, 126, 0, 27, 91, 49, 56, 59, 53, 126, 0, 27, 91, 49, 57, 59, 53, 126, 0, 27, 91, 50, 48, 59, 53, 126, 0, 27, 91, 50, 49, 59, 53, 126, 0, 27, 91, 50, 51, 59, 53, 126, 0, 27, 91, 50, 52, 59, 53, 126, 0, 27, 91, 49, 59, 54, 80, 0, 27, 91, 49, 59, 54, 81, 0, 27, 91, 49, 59, 54, 82, 0, 27, 91, 49, 59, 54, 83, 0, 27, 91, 49, 53, 59, 54, 126, 0, 27, 91, 49, 55, 59, 54, 126, 0, 27, 91, 49, 56, 59, 54, 126, 0, 27, 91, 49, 57, 59, 54, 126, 0, 27, 91, 50, 48, 59, 54, 126, 0, 27, 91, 50, 49, 59, 54, 126, 0, 27, 91, 50, 51, 59, 54, 126, 0, 27, 91, 50, 52, 59, 54, 126, 0, 27, 91, 49, 59, 51, 80, 0, 27, 91, 49, 59, 51, 81, 0, 27, 91, 49, 59, 51, 82, 0, 27, 91, 49, 59, 51, 83, 0, 27, 91, 49, 53, 59, 51, 126, 0, 27, 91, 49, 55, 59, 51, 126, 0, 27, 91, 49, 56, 59, 51, 126, 0, 27, 91, 49, 57, 59, 51, 126, 0, 27, 91, 50, 48, 59, 51, 126, 0, 27, 91, 50, 49, 59, 51, 126, 0, 27, 91, 50, 51, 59, 51, 126, 0, 27, 91, 50, 52, 59, 51, 126, 0, 27, 91, 49, 59, 52, 80, 0, 27, 91, 49, 59, 52, 81, 0, 27, 91, 49, 59, 52, 82, 0, 27, 91, 49, 75, 0, 27, 91, 37, 105, 37, 100, 59, 37, 100, 82, 0, 27, 91, 54, 110, 0, 27, 91, 63, 49, 59, 50, 99, 0, 27, 91, 99, 0, 27, 91, 51, 57, 59, 52, 57, 109, 0, 27, 91, 51, 109, 0, 27, 91, 50, 51, 109, 0, 27, 91, 77, 0, 27, 91, 37, 63, 37, 112, 49, 37, 123, 56, 125, 37, 60, 37, 116, 51, 37, 112, 49, 37, 100, 37, 101, 37, 112, 49, 37, 123, 49, 54, 125, 37, 60, 37, 116, 57, 37, 112, 49, 37, 123, 56, 125, 37, 45, 37, 100, 37, 101, 51, 56, 59, 53, 59, 37, 112, 49, 37, 100, 37, 59, 109, 0, 27, 91, 37, 63, 37, 112, 49, 37, 123, 56, 125, 37, 60, 37, 116, 52, 37, 112, 49, 37, 100, 37, 101, 37, 112, 49, 37, 123, 49, 54, 125, 37, 60, 37, 116, 49, 48, 37, 112, 49, 37, 123, 56, 125, 37, 45, 37, 100, 37, 101, 52, 56, 59, 53, 59, 37, 112, 49, 37, 100, 37, 59, 109, 0 +}; +// Taken from Dickey ncurses terminfo.src dated 2017-04-22. +// This is a 256-colour terminfo description that lacks true-colour +// capabilities that gnome actually has. +static const signed char vte_256colour_terminfo[] = { + 26, 1, 52, 0, 29, 0, 15, 0, 105, 1, -55, 5, 103, 110, 111, 109, 101, 45, 50, 53, 54, 99, 111, 108, 111, 114, 124, 71, 78, 79, 77, 69, 32, 84, 101, 114, 109, 105, 110, 97, 108, 32, 119, 105, 116, 104, 32, 120, 116, 101, 114, 109, 32, 50, 53, 54, 45, 99, 111, 108, 111, 114, 115, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 80, 0, 8, 0, 24, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, -1, 127, 0, 0, 4, 0, 6, 0, 8, 0, 25, 0, 30, 0, 38, 0, 42, 0, 46, 0, -1, -1, 57, 0, 74, 0, 76, 0, 80, 0, 87, 0, -1, -1, 89, 0, 96, 0, -1, -1, 100, 0, -1, -1, 104, 0, 108, 0, -1, -1, -1, -1, 112, 0, -1, -1, 114, 0, 119, 0, -1, -1, -128, 0, -123, 0, -118, 0, -1, -1,-113, 0, -108, 0, -103, 0, -98, 0, -89, 0, -87, 0, -81, 0, -1, -1, -68, 0, -63, 0, -57, 0, -51, 0, -1, -1, -1, -1, -1, -1, -33, 0, -1, -1, -1, -1, -1, -1, 0, 1, -1, -1, 4, 1, -1, -1, -1, -1, -1, -1, 6, 1, -1, -1, 11, 1, -1, -1, -1, -1, -1, -1, -1, -1, 15, 1, 19, 1, 25, 1, 29, 1, 33, 1, 37, 1, 43, 1, 49, 1, 55, 1, 61, 1, 67, 1, 71, 1, -1, -1, 76, 1, -1, -1, 80, 1, 85, 1, 90, 1, 94, 1, 101, 1, -1, -1, 108, 1, 112, 1, 120, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -128, 1,-119, 1, -110, 1, -101, 1, -92, 1, -83, 1, -74, 1, -65, 1, -56, 1, -47, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -38, 1, -35, 1, -1, -1, -1, -1, 16, 2, 19, 2, 30, 2, 33, 2, 35, 2, 38, 2, 116, 2, -1, -1, 119, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 121, 2, -1, -1, -1, -1, -1, -1, -1, -1, 125, 2, -1, -1, -78, 2, -1, -1, -1, -1, -74, 2, -68, 2, -1, -1, -1, -1, -62, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -58, 2, -54, 2, -1, -1, -50, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -45, 2, -1, -1, -38, 2, -33, 2, -1, -1, -1, -1, -1, -1, -1, -1, -26, 2, -19, 2, -12, 2, -1, -1, -1, -1, -5, 2, -1, -1, 2, 3, -1, -1, -1, -1, -1, -1, 9, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 16, 3, 22, 3, 28, 3, 35, 3, 42, 3, 49, 3, 56, 3, 64, 3, 72, 3, 80, 3, 88, 3, 96, 3, 104, 3, 112, 3, 120, 3, 127, 3, -122, 3, -115, 3,-108, 3, -100, 3, -92, 3, -84, 3, -76, 3, -68, 3, -60, 3, -52, 3, -44, 3, -37, 3, -30, 3, -23, 3, -16, 3, -8, 3, 0, 4, 8, 4, 16, 4, 24, 4, 32, 4, 40, 4, 48, 4, 55, 4, 62, 4, 69, 4, 76, 4, 84, 4, 92, 4, 100, 4, 108, 4, 116, 4, 124, 4, -124, 4,-116, 4, -109, 4, -102, 4, -95, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -90, 4, -79, 4, -74, 4, -55, 4, -51, 4, -42, 4, -35, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 59, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 64, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 70, 5, -1, -1, -1, -1, -1, -1, 74, 5, -119, 5, 27, 91, 90, 0, 7, 0, 13, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 59, 37, 112, 50, 37, 100, 114, 0, 27, 91, 51, 103, 0, 27, 91, 72, 27, 91, 50, 74, 0, 27, 91, 75, 0, 27, 91, 74, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 71, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 59, 37, 112, 50, 37, 100, 72, 0, 10, 0, 27, 91, 72, 0, 27, 91, 63, 50, 53, 108, 0, 8, 0, 27, 91, 63, 50, 53, 104, 0, 27, 91, 67, 0, 27, 91, 65, 0, 27, 91, 80, 0, 27, 91, 77, 0, 14, 0, 27, 91, 49, 109, 0, 27, 55, 27, 91, 63, 52, 55, 104, 0, 27, 91, 50, 109, 0, 27, 91, 52, 104, 0, 27, 91, 56, 109, 0, 27, 91, 55, 109, 0, 27, 91, 55, 109, 0, 27, 91, 52, 109, 0, 27, 91, 37, 112, 49, 37, 100, 88, 0, 15, 0, 27, 91, 48, 109, 15, 0, 27, 91, 50, 74, 27, 91, 63, 52, 55, 108, 27, 56, 0, 27, 91, 52, 108, 0, 27, 91, 50, 55, 109, 0, 27, 91, 50, 52, 109, 0, 27, 91, 63, 53, 104, 36, 60, 49, 48, 48, 47, 62, 27, 91, 63, 53, 108, 0, 27, 91, 109, 27, 91, 63, 55, 104, 27, 91, 52, 108, 27, 62, 27, 55, 27, 91, 114, 27, 91, 63, 49, 59, 51, 59, 52, 59, 54, 108, 27, 56, 0, 27, 91, 76, 0, 127, 0, 27, 91, 51, 126, 0, 27, 79, 66, 0, 27, 79, 80, 0, 27, 91, 50, 49, 126, 0, 27, 79, 81, 0, 27, 79, 82, 0, 27, 79, 83, 0, 27, 91, 49, 53, 126, 0, 27, 91, 49, 55, 126, 0, 27, 91, 49, 56, 126, 0, 27, 91, 49, 57, 126, 0, 27, 91, 50, 48, 126, 0, 27, 79, 72, 0, 27, 91, 50, 126, 0, 27, 79, 68, 0, 27, 91, 54, 126, 0, 27, 91, 53, 126, 0, 27, 79, 67, 0, 27, 91, 49, 59, 50, 66, 0, 27, 91, 49, 59, 50, 65, 0, 27, 79, 65, 0, 27, 91, 63, 49, 108, 27, 62, 0, 27, 91, 63, 49, 104, 27, 61, 0, 27, 91, 37, 112, 49, 37, 100, 80, 0, 27, 91, 37, 112, 49, 37, 100, 77, 0, 27, 91, 37, 112, 49, 37, 100, 66, 0, 27, 91, 37, 112, 49, 37, 100, 64, 0, 27, 91, 37, 112, 49, 37, 100, 83, 0, 27, 91, 37, 112, 49, 37, 100, 76, 0, 27, 91, 37, 112, 49, 37, 100, 68, 0, 27, 91, 37, 112, 49, 37, 100, 67, 0, 27, 91, 37, 112, 49, 37, 100, 84, 0, 27, 91, 37, 112, 49, 37, 100, 65, 0, 27, 99, 0, 27, 55, 27, 91, 114, 27, 56, 27, 91, 109, 27, 91, 63, 55, 104, 27, 91, 33, 112, 27, 91, 63, 49, 59, 51, 59, 52, 59, 54, 108, 27, 91, 52, 108, 27, 62, 27, 91, 63, 49, 48, 48, 48, 108, 27, 91, 63, 50, 53, 104, 0, 27, 56, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 100, 0, 27, 55, 0, 10, 0, 27, 77, 0, 27, 91, 48, 37, 63, 37, 112, 54, 37, 116, 59, 49, 37, 59, 37, 63, 37, 112, 50, 37, 116, 59, 52, 37, 59, 37, 63, 37, 112, 53, 37, 116, 59, 50, 37, 59, 37, 63, 37, 112, 55, 37, 116, 59, 56, 37, 59, 37, 63, 37, 112, 49, 37, 112, 51, 37, 124, 37, 116, 59, 55, 37, 59, 109, 37, 63, 37, 112, 57, 37, 116, 14, 37, 101, 15, 37, 59, 0, 27, 72, 0, 9, 0, 27, 91, 69, 0, 96, 96, 97, 97, 102, 102, 103, 103, 105, 105, 106, 106, 107, 107, 108, 108, 109, 109, 110, 110, 111, 111, 112, 112, 113, 113, 114, 114, 115, 115, 116, 116, 117, 117, 118, 118, 119, 119, 120, 120, 121, 121, 122, 122, 123, 123, 124, 124, 125, 125, 126, 126, 0, 27, 91, 90, 0, 27, 91, 63, 55, 104, 0, 27, 91, 63, 55, 108, 0, 27, 41, 48, 0, 27, 79, 70, 0, 27, 79, 77, 0, 27, 91, 49, 126, 0, 27, 91, 51, 59, 50, 126, 0, 27, 91, 52, 126, 0, 27, 91, 49, 59, 50, 70, 0, 27, 91, 49, 59, 50, 72, 0, 27, 91, 50, 59, 50, 126, 0, 27, 91, 49, 59, 50, 68, 0, 27, 91, 54, 59, 50, 126, 0, 27, 91, 53, 59, 50, 126, 0, 27, 91, 49, 59, 50, 67, 0, 27, 91, 50, 51, 126, 0, 27, 91, 50, 52, 126, 0, 27, 91, 49, 59, 50, 80, 0, 27, 91, 49, 59, 50, 81, 0, 27, 91, 49, 59, 50, 82, 0, 27, 91, 49, 59, 50, 83, 0, 27, 91, 49, 53, 59, 50, 126, 0, 27, 91, 49, 55, 59, 50, 126, 0, 27, 91, 49, 56, 59, 50, 126, 0, 27, 91, 49, 57, 59, 50, 126, 0, 27, 91, 50, 48, 59, 50, 126, 0, 27, 91, 50, 49, 59, 50, 126, 0, 27, 91, 50, 51, 59, 50, 126, 0, 27, 91, 50, 52, 59, 50, 126, 0, 27, 91, 49, 59, 53, 80, 0, 27, 91, 49, 59, 53, 81, 0, 27, 91, 49, 59, 53, 82, 0, 27, 91, 49, 59, 53, 83, 0, 27, 91, 49, 53, 59, 53, 126, 0, 27, 91, 49, 55, 59, 53, 126, 0, 27, 91, 49, 56, 59, 53, 126, 0, 27, 91, 49, 57, 59, 53, 126, 0, 27, 91, 50, 48, 59, 53, 126, 0, 27, 91, 50, 49, 59, 53, 126, 0, 27, 91, 50, 51, 59, 53, 126, 0, 27, 91, 50, 52, 59, 53, 126, 0, 27, 91, 49, 59, 54, 80, 0, 27, 91, 49, 59, 54, 81, 0, 27, 91, 49, 59, 54, 82, 0, 27, 91, 49, 59, 54, 83, 0, 27, 91, 49, 53, 59, 54, 126, 0, 27, 91, 49, 55, 59, 54, 126, 0, 27, 91, 49, 56, 59, 54, 126, 0, 27, 91, 49, 57, 59, 54, 126, 0, 27, 91, 50, 48, 59, 54, 126, 0, 27, 91, 50, 49, 59, 54, 126, 0, 27, 91, 50, 51, 59, 54, 126, 0, 27, 91, 50, 52, 59, 54, 126, 0, 27, 91, 49, 59, 51, 80, 0, 27, 91, 49, 59, 51, 81, 0, 27, 91, 49, 59, 51, 82, 0, 27, 91, 49, 59, 51, 83, 0, 27, 91, 49, 53, 59, 51, 126, 0, 27, 91, 49, 55, 59, 51, 126, 0, 27, 91, 49, 56, 59, 51, 126, 0, 27, 91, 49, 57, 59, 51, 126, 0, 27, 91, 50, 48, 59, 51, 126, 0, 27, 91, 50, 49, 59, 51, 126, 0, 27, 91, 50, 51, 59, 51, 126, 0, 27, 91, 50, 52, 59, 51, 126, 0, 27, 91, 49, 59, 52, 80, 0, 27, 91, 49, 59, 52, 81, 0, 27, 91, 49, 59, 52, 82, 0, 27, 91, 49, 75, 0, 27, 91, 37, 105, 37, 100, 59, 37, 100, 82, 0, 27, 91, 54, 110, 0, 27, 91, 63, 37, 91, 59, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 93, 99, 0, 27, 91, 99, 0, 27, 91, 51, 57, 59, 52, 57, 109, 0, 27, 93, 49, 48, 52, 7, 0, 27, 93, 52, 59, 37, 112, 49, 37, 100, 59, 114, 103, 98, 58, 37, 112, 50, 37, 123, 50, 53, 53, 125, 37, 42, 37, 123, 49, 48, 48, 48, 125, 37, 47, 37, 50, 46, 50, 88, 47, 37, 112, 51, 37, 123, 50, 53, 53, 125, 37, 42, 37, 123, 49, 48, 48, 48, 125, 37, 47, 37, 50, 46, 50, 88, 47, 37, 112, 52, 37, 123, 50, 53, 53, 125, 37, 42, 37, 123, 49, 48, 48, 48, 125, 37, 47, 37, 50, 46, 50, 88, 27, 92, 0, 27, 91, 51, 109, 0, 27, 91, 50, 51, 109, 0, 27, 91, 77, 0, 27, 91, 37, 63, 37, 112, 49, 37, 123, 56, 125, 37, 60, 37, 116, 51, 37, 112, 49, 37, 100, 37, 101, 37, 112, 49, 37, 123, 49, 54, 125, 37, 60, 37, 116, 57, 37, 112, 49, 37, 123, 56, 125, 37, 45, 37, 100, 37, 101, 51, 56, 59, 53, 59, 37, 112, 49, 37, 100, 37, 59, 109, 0, 27, 91, 37, 63, 37, 112, 49, 37, 123, 56, 125, 37, 60, 37, 116, 52, 37, 112, 49, 37, 100, 37, 101, 37, 112, 49, 37, 123, 49, 54, 125, 37, 60, 37, 116, 49, 48, 37, 112, 49, 37, 123, 56, 125, 37, 45, 37, 100, 37, 101, 52, 56, 59, 53, 59, 37, 112, 49, 37, 100, 37, 59, 109, 0 +}; +// Taken from Dickey ncurses terminfo.src dated 2017-04-22. +static const signed char ansi_terminfo[] = { + 26, 1, 40, 0, 23, 0, 16, 0, 125, 1, 68, 2, 97, 110, 115, 105, 124, 97, 110, 115, 105, 47, 112, 99, 45, 116, 101, 114, 109, 32, 99, 111, 109, 112, 97, 116, 105, 98, 108, 101, 32, 119, 105, 116, 104, 32, 99, 111, 108, 111, 114, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 80, 0, 8, 0, 24, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8, 0, 64, 0, 3, 0, 0, 0, 4, 0, 6, 0, -1, -1, 8, 0, 13, 0, 20, 0, 24, 0, 28, 0, -1, -1, 39, 0, 56, 0, 60, 0, -1, -1, 64, 0, -1, -1, -1, -1, 68, 0, -1, -1, 72, 0, -1, -1, 76, 0, 80, 0, -1, -1, -1, -1, 84, 0, 90, 0, 95, 0, -1, -1, -1, -1, -1, -1, -1, -1, 100, 0, -1, -1, 105, 0, 110, 0, 115, 0, 120, 0,-127, 0,-121, 0, -1, -1, -1, -1, -1, -1,-113, 0,-109, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,-105, 0, -1, -1,-101, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -99, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -95, 0, -91, 0, -1, -1, -87, 0, -1, -1, -1, -1, -1, -1, -83, 0, -1, -1, -1, -1, -1, -1, -79, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -75, 0, -1, -1, -70, 0, -61, 0, -52, 0, -43, 0, -34, 0, -25, 0, -16, 0, -7, 0, 2, 1, 11, 1, -1, -1, -1, -1, -1, -1, -1, -1, 20, 1, 25, 1, 30, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 50, 1, -1, -1, 61, 1, -1, -1, 63, 1,-107, 1, -1, -1,-104, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,-100, 1, -1, -1, -37, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -33, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -28, 1, -17, 1, -12, 1, 7, 2, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 20, 2, 30, 2, -1, -1, -1, -1, -1, -1, 40, 2, 44, 2, 48, 2, 52, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 56, 2, 62, 2, 27, 91, 90, 0, 7, 0, 13, 0, 27, 91, 51, 103, 0, 27, 91, 72, 27, 91, 74, 0, 27, 91, 75, 0, 27, 91, 74, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 71, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 59, 37, 112, 50, 37, 100, 72, 0, 27, 91, 66, 0, 27, 91, 72, 0, 27, 91, 68, 0, 27, 91, 67, 0, 27, 91, 65, 0, 27, 91, 80, 0, 27, 91, 77, 0, 27, 91, 49, 49, 109, 0, 27, 91, 53, 109, 0, 27, 91, 49, 109, 0, 27, 91, 56, 109, 0, 27, 91, 55, 109, 0, 27, 91, 55, 109, 0, 27, 91, 52, 109, 0, 27, 91, 37, 112, 49, 37, 100, 88, 0, 27, 91, 49, 48, 109, 0, 27, 91, 48, 59, 49, 48, 109, 0, 27, 91, 109, 0, 27, 91, 109, 0, 27, 91, 76, 0, 8, 0, 27, 91, 66, 0, 27, 91, 72, 0, 27, 91, 76, 0, 27, 91, 68, 0, 27, 91, 67, 0, 27, 91, 65, 0, 13, 27, 91, 83, 0, 27, 91, 37, 112, 49, 37, 100, 80, 0, 27, 91, 37, 112, 49, 37, 100, 77, 0, 27, 91, 37, 112, 49, 37, 100, 66, 0, 27, 91, 37, 112, 49, 37, 100, 64, 0, 27, 91, 37, 112, 49, 37, 100, 83, 0, 27, 91, 37, 112, 49, 37, 100, 76, 0, 27, 91, 37, 112, 49, 37, 100, 68, 0, 27, 91, 37, 112, 49, 37, 100, 67, 0, 27, 91, 37, 112, 49, 37, 100, 84, 0, 27, 91, 37, 112, 49, 37, 100, 65, 0, 27, 91, 52, 105, 0, 27, 91, 53, 105, 0, 37, 112, 49, 37, 99, 27, 91, 37, 112, 50, 37, 123, 49, 125, 37, 45, 37, 100, 98, 0, 27, 91, 37, 105, 37, 112, 49, 37, 100, 100, 0, 10, 0, 27, 91, 48, 59, 49, 48, 37, 63, 37, 112, 49, 37, 116, 59, 55, 37, 59, 37, 63, 37, 112, 50, 37, 116, 59, 52, 37, 59, 37, 63, 37, 112, 51, 37, 116, 59, 55, 37, 59, 37, 63, 37, 112, 52, 37, 116, 59, 53, 37, 59, 37, 63, 37, 112, 54, 37, 116, 59, 49, 37, 59, 37, 63, 37, 112, 55, 37, 116, 59, 56, 37, 59, 37, 63, 37, 112, 57, 37, 116, 59, 49, 49, 37, 59, 109, 0, 27, 72, 0, 27, 91, 73, 0, 43, 16, 44, 17, 45, 24, 46, 25, 48, -37, 96, 4, 97, -79, 102, -8, 103, -15, 104, -80, 106, -39, 107, -65, 108, -38, 109, -64, 110, -59, 111, 126, 112, -60, 113, -60, 114, -60, 115, 95, 116, -61, 117, -76, 118, -63, 119, -62, 120, -77, 121, -13, 122, -14, 123, -29, 124, -40, 125,-100, 126, -2, 0, 27, 91, 90, 0, 27, 91, 49, 75, 0, 27, 91, 37, 105, 37, 100, 59, 37, 100, 82, 0, 27, 91, 54, 110, 0, 27, 91, 63, 37, 91, 59, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 93, 99, 0, 27, 91, 99, 0, 27, 91, 51, 57, 59, 52, 57, 109, 0, 27, 91, 51, 37, 112, 49, 37, 100, 109, 0, 27, 91, 52, 37, 112, 49, 37, 100, 109, 0, 27, 40, 66, 0, 27, 41, 66, 0, 27, 42, 66, 0, 27, 43, 66, 0, 27, 91, 49, 49, 109, 0, 27, 91, 49, 48, 109, 0 +}; + +/// Load one of the built-in terminfo entries when unibilium has failed to +/// load a terminfo record from an external database, as it does on termcap- +/// -only systems. We do not do any fancy recognition of xterm pretenders +/// here. An external terminfo database would not do that, and we want to +/// behave as much like an external terminfo database as possible. +unibi_term *load_builtin_terminfo(const char * term) +{ + if (terminfo_is_term_family(term, "xterm")) { + return unibi_from_mem((const char *)xterm_256colour_terminfo, + sizeof xterm_256colour_terminfo); + } else if (terminfo_is_term_family(term, "screen")) { + return unibi_from_mem((const char *)screen_256colour_terminfo, + sizeof screen_256colour_terminfo); + } else if (terminfo_is_term_family(term, "tmux")) { + return unibi_from_mem((const char *)tmux_256colour_terminfo, + sizeof tmux_256colour_terminfo); + } else if (terminfo_is_term_family(term, "rxvt")) { + return unibi_from_mem((const char *)rxvt_256colour_terminfo, + sizeof rxvt_256colour_terminfo); + } else if (terminfo_is_term_family(term, "putty")) { + return unibi_from_mem((const char *)putty_256colour_terminfo, + sizeof putty_256colour_terminfo); + } else if (terminfo_is_term_family(term, "linux")) { + return unibi_from_mem((const char *)linux_16colour_terminfo, + sizeof linux_16colour_terminfo); + } else if (terminfo_is_term_family(term, "interix")) { + return unibi_from_mem((const char *)interix_8colour_terminfo, + sizeof interix_8colour_terminfo); + } else if (terminfo_is_term_family(term, "iterm") + || terminfo_is_term_family(term, "iterm2") + || terminfo_is_term_family(term, "iTerm.app") + || terminfo_is_term_family(term, "iTerm2.app")) { + return unibi_from_mem((const char *)iterm_256colour_terminfo, + sizeof iterm_256colour_terminfo); + } else if (terminfo_is_term_family(term, "st")) { + return unibi_from_mem((const char *)st_256colour_terminfo, + sizeof st_256colour_terminfo); + } else if (terminfo_is_term_family(term, "gnome") + || terminfo_is_term_family(term, "vte")) { + return unibi_from_mem((const char *)vte_256colour_terminfo, + sizeof vte_256colour_terminfo); + } else { + return unibi_from_mem((const char *)ansi_terminfo, + sizeof ansi_terminfo); + } +} diff --git a/src/nvim/tui/terminfo.h b/src/nvim/tui/terminfo.h new file mode 100644 index 0000000000..099df8967f --- /dev/null +++ b/src/nvim/tui/terminfo.h @@ -0,0 +1,10 @@ +#ifndef NVIM_TUI_TERMINFO_H +#define NVIM_TUI_TERMINFO_H + +#include <unibilium.h> + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "tui/terminfo.h.generated.h" +#endif + +#endif // NVIM_TUI_TERMINFO_H diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c index 74187e07c0..1cbd02dfd9 100644 --- a/src/nvim/tui/tui.c +++ b/src/nvim/tui/tui.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + // Terminal UI functions. Invoked (by ui_bridge.c) on the TUI thread. #include <assert.h> @@ -31,13 +34,37 @@ #include "nvim/ugrid.h" #include "nvim/tui/input.h" #include "nvim/tui/tui.h" +#include "nvim/tui/terminfo.h" +#include "nvim/cursor_shape.h" +#include "nvim/syntax.h" +#include "nvim/macros.h" -// Space reserved in the output buffer to restore the cursor to normal when -// flushing. No existing terminal will require 32 bytes to do that. +// Space reserved in two output buffers to make the cursor normal or invisible +// when flushing. No existing terminal will require 32 bytes to do that. #define CNORM_COMMAND_MAX_SIZE 32 #define OUTBUF_SIZE 0xffff #define TOO_MANY_EVENTS 1000000 +#define STARTS_WITH(str, prefix) (strlen(str) >= (sizeof(prefix) - 1) \ + && 0 == memcmp((str), (prefix), sizeof(prefix) - 1)) +#define TMUX_WRAP(is_tmux, seq) ((is_tmux) \ + ? "\x1bPtmux;\x1b" seq "\x1b\\" : seq) +#define LINUXSET0C "\x1b[?0c" +#define LINUXSET1C "\x1b[?1c" + +// Per the commentary in terminfo, only a minus sign is a true suffix +// separator. +bool terminfo_is_term_family(const char *term, const char *family) +{ + if (!term) { + return false; + } + size_t tlen = strlen(term); + size_t flen = strlen(family); + return tlen >= flen + && 0 == memcmp(term, family, flen) \ + && ('\0' == term[flen] || '-' == term[flen]); +} typedef struct { int top, bot, left, right; @@ -49,7 +76,10 @@ typedef struct { bool stop; unibi_var_t params[9]; char buf[OUTBUF_SIZE]; - size_t bufpos, bufsize; + size_t bufpos; + char norm[CNORM_COMMAND_MAX_SIZE]; + char invis[CNORM_COMMAND_MAX_SIZE]; + size_t normlen, invislen; TermInput input; uv_loop_t write_loop; unibi_term *ut; @@ -60,27 +90,35 @@ typedef struct { bool out_isatty; SignalWatcher winch_handle, cont_handle; bool cont_received; - // Event scheduled by the ui bridge. Since the main thread suspends until - // the event is handled, it is fine to use a single field instead of a queue - Event scheduled_event; UGrid grid; kvec_t(Rect) invalid_regions; int out_fd; - bool can_use_terminal_scroll; + bool scroll_region_is_full_screen; + bool can_change_scroll_region; + bool can_set_lr_margin; + bool can_set_left_right_margin; + bool immediate_wrap_after_last_column; bool mouse_enabled; - bool busy; + bool busy, is_invisible; + cursorentry_T cursor_shapes[SHAPE_IDX_COUNT]; HlAttrs print_attrs; - int showing_mode; + bool default_attr; + ModeShape showing_mode; struct { int enable_mouse, disable_mouse; int enable_bracketed_paste, disable_bracketed_paste; - int set_cursor_shape_bar, set_cursor_shape_ul, set_cursor_shape_block; + int enable_lr_margin, disable_lr_margin; int set_rgb_foreground, set_rgb_background; + int set_cursor_color; int enable_focus_reporting, disable_focus_reporting; + int resize_screen; + int reset_scroll_region; + int set_cursor_style, reset_cursor_style; } unibi_ext; } TUIData; static bool volatile got_winch = false; +static bool cursor_style_enabled = false; #ifdef INCLUDE_GENERATED_DECLARATIONS # include "tui/tui.c.generated.h" @@ -92,11 +130,11 @@ UI *tui_start(void) UI *ui = xcalloc(1, sizeof(UI)); ui->stop = tui_stop; ui->rgb = p_tgc; - ui->pum_external = false; ui->resize = tui_resize; ui->clear = tui_clear; ui->eol_clear = tui_eol_clear; ui->cursor_goto = tui_cursor_goto; + ui->mode_info_set = tui_mode_info_set; ui->update_menu = tui_update_menu; ui->busy_start = tui_busy_start; ui->busy_stop = tui_busy_stop; @@ -117,50 +155,96 @@ UI *tui_start(void) ui->set_title = tui_set_title; ui->set_icon = tui_set_icon; ui->event = tui_event; + + memset(ui->ui_ext, 0, sizeof(ui->ui_ext)); + return ui_bridge_attach(ui, tui_main, tui_scheduler); } +static size_t unibi_pre_fmt_str(TUIData *data, unsigned int unibi_index, + char * buf, size_t len) +{ + const char *str = unibi_get_str(data->ut, unibi_index); + if (!str) { + return 0U; + } + return unibi_run(str, data->params, buf, len); +} + static void terminfo_start(UI *ui) { TUIData *data = ui->data; - data->can_use_terminal_scroll = true; + data->scroll_region_is_full_screen = true; data->bufpos = 0; - data->bufsize = sizeof(data->buf) - CNORM_COMMAND_MAX_SIZE; - data->showing_mode = 0; + data->default_attr = false; + data->is_invisible = true; + data->busy = false; + data->showing_mode = SHAPE_IDX_N; data->unibi_ext.enable_mouse = -1; data->unibi_ext.disable_mouse = -1; + data->unibi_ext.set_cursor_color = -1; data->unibi_ext.enable_bracketed_paste = -1; data->unibi_ext.disable_bracketed_paste = -1; - data->unibi_ext.set_cursor_shape_bar = -1; - data->unibi_ext.set_cursor_shape_ul = -1; - data->unibi_ext.set_cursor_shape_block = -1; + data->unibi_ext.enable_lr_margin = -1; + data->unibi_ext.disable_lr_margin = -1; data->unibi_ext.enable_focus_reporting = -1; data->unibi_ext.disable_focus_reporting = -1; + data->unibi_ext.resize_screen = -1; + data->unibi_ext.reset_scroll_region = -1; + data->unibi_ext.set_cursor_style = -1; + data->unibi_ext.reset_cursor_style = -1; data->out_fd = 1; data->out_isatty = os_isatty(data->out_fd); // setup unibilium + const char *term = os_getenv("TERM"); data->ut = unibi_from_env(); if (!data->ut) { - // For some reason could not read terminfo file, use a dummy entry that - // will be populated with common values by fix_terminfo below - data->ut = unibi_dummy(); + data->ut = load_builtin_terminfo(term); } - fix_terminfo(data); - // Initialize the cursor shape. - unibi_out(ui, data->unibi_ext.set_cursor_shape_block); + // None of the following work over SSH; see :help TERM . + const char *colorterm = os_getenv("COLORTERM"); + const char *termprg = os_getenv("TERM_PROGRAM"); + const char *vte_version_env = os_getenv("VTE_VERSION"); + long vte_version = vte_version_env ? strtol(vte_version_env, NULL, 10) : 0; + bool iterm_env = termprg && strstr(termprg, "iTerm.app"); + bool konsole = os_getenv("KONSOLE_PROFILE_NAME") + || os_getenv("KONSOLE_DBUS_SESSION"); + + patch_terminfo_bugs(data, term, colorterm, vte_version, konsole, iterm_env); + augment_terminfo(data, term, colorterm, vte_version, konsole, iterm_env); + data->can_change_scroll_region = + !!unibi_get_str(data->ut, unibi_change_scroll_region); + data->can_set_lr_margin = + !!unibi_get_str(data->ut, unibi_set_lr_margin); + data->can_set_left_right_margin = + !!unibi_get_str(data->ut, unibi_set_left_margin_parm) + && !!unibi_get_str(data->ut, unibi_set_right_margin_parm); + data->immediate_wrap_after_last_column = + terminfo_is_term_family(term, "cygwin") + || terminfo_is_term_family(term, "interix"); + data->normlen = unibi_pre_fmt_str(data, unibi_cursor_normal, + data->norm, sizeof data->norm); + data->invislen = unibi_pre_fmt_str(data, unibi_cursor_invisible, + data->invis, sizeof data->invis); // Set 't_Co' from the result of unibilium & fix_terminfo. t_colors = unibi_get_num(data->ut, unibi_max_colors); // Enter alternate screen and clear + // NOTE: Do this *before* changing terminal settings. #6433 unibi_out(ui, unibi_enter_ca_mode); + unibi_out(ui, unibi_keypad_xmit); unibi_out(ui, unibi_clear_screen); // Enable bracketed paste - unibi_out(ui, data->unibi_ext.enable_bracketed_paste); + unibi_out_ext(ui, data->unibi_ext.enable_bracketed_paste); // Enable focus reporting - unibi_out(ui, data->unibi_ext.enable_focus_reporting); + unibi_out_ext(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); +#ifdef WIN32 uv_tty_set_mode(&data->output_handle.tty, UV_TTY_MODE_RAW); +#else + uv_tty_set_mode(&data->output_handle.tty, UV_TTY_MODE_IO); +#endif } else { uv_pipe_init(&data->write_loop, &data->output_handle.pipe, 0); uv_pipe_open(&data->output_handle.pipe, data->out_fd); @@ -171,16 +255,17 @@ static void terminfo_stop(UI *ui) { TUIData *data = ui->data; // Destroy output stuff - tui_mode_change(ui, NORMAL); + tui_mode_change(ui, (String)STRING_INIT, SHAPE_IDX_N); tui_mouse_off(ui); unibi_out(ui, unibi_exit_attribute_mode); // cursor should be set to normal before exiting alternate screen unibi_out(ui, unibi_cursor_normal); + unibi_out(ui, unibi_keypad_local); unibi_out(ui, unibi_exit_ca_mode); // Disable bracketed paste - unibi_out(ui, data->unibi_ext.disable_bracketed_paste); + unibi_out_ext(ui, data->unibi_ext.disable_bracketed_paste); // Disable focus reporting - unibi_out(ui, data->unibi_ext.disable_focus_reporting); + unibi_out_ext(ui, data->unibi_ext.disable_focus_reporting); flush_buf(ui, true); uv_tty_reset_mode(); uv_close((uv_handle_t *)&data->output_handle, NULL); @@ -199,11 +284,6 @@ static void tui_terminal_start(UI *ui) terminfo_start(ui); update_size(ui); signal_watcher_start(&data->winch_handle, sigwinch_cb, SIGWINCH); - -#if TERMKEY_VERSION_MAJOR > 0 || TERMKEY_VERSION_MINOR > 18 - data->input.tk_ti_hook_fn = tui_tk_ti_getstr; -#endif - term_input_init(&data->input, data->loop); term_input_start(&data->input); } @@ -235,9 +315,17 @@ static void tui_main(UIBridgeData *bridge, UI *ui) kv_init(data->invalid_regions); signal_watcher_init(data->loop, &data->winch_handle, ui); signal_watcher_init(data->loop, &data->cont_handle, data); +#ifdef UNIX signal_watcher_start(&data->cont_handle, sigcont_cb, SIGCONT); +#endif + +#if TERMKEY_VERSION_MAJOR > 0 || TERMKEY_VERSION_MINOR > 18 + data->input.tk_ti_hook_fn = tui_tk_ti_getstr; +#endif + term_input_init(&data->input, &tui_loop); tui_terminal_start(ui); data->stop = false; + // allow the main thread to continue, we are ready to start handling UI // callbacks CONTINUE(bridge); @@ -264,10 +352,12 @@ static void tui_scheduler(Event event, void *d) loop_schedule(data->loop, event); } +#ifdef UNIX static void sigcont_cb(SignalWatcher *watcher, int signum, void *data) { ((TUIData *)data)->cont_received = true; } +#endif static void sigwinch_cb(SignalWatcher *watcher, int signum, void *data) { @@ -294,25 +384,56 @@ static void update_attrs(UI *ui, HlAttrs attrs) } data->print_attrs = attrs; - unibi_out(ui, unibi_exit_attribute_mode); UGrid *grid = &data->grid; int fg = attrs.foreground != -1 ? attrs.foreground : grid->fg; int bg = attrs.background != -1 ? attrs.background : grid->bg; + if (unibi_get_str(data->ut, unibi_set_attributes)) { + if (attrs.bold || attrs.reverse || attrs.underline || attrs.undercurl) { + data->params[0].i = 0; // standout + data->params[1].i = attrs.underline || attrs.undercurl; + data->params[2].i = attrs.reverse; + data->params[3].i = 0; // blink + data->params[4].i = 0; // dim + data->params[5].i = attrs.bold; + data->params[6].i = 0; // blank + data->params[7].i = 0; // protect + data->params[8].i = 0; // alternate character set + unibi_out(ui, unibi_set_attributes); + } else if (!data->default_attr) { + unibi_out(ui, unibi_exit_attribute_mode); + } + } else { + if (!data->default_attr) { + unibi_out(ui, unibi_exit_attribute_mode); + } + if (attrs.bold) { + unibi_out(ui, unibi_enter_bold_mode); + } + if (attrs.underline || attrs.undercurl) { + unibi_out(ui, unibi_enter_underline_mode); + } + if (attrs.reverse) { + unibi_out(ui, unibi_enter_reverse_mode); + } + } + if (attrs.italic) { + unibi_out(ui, unibi_enter_italics_mode); + } if (ui->rgb) { if (fg != -1) { data->params[0].i = (fg >> 16) & 0xff; // red data->params[1].i = (fg >> 8) & 0xff; // green data->params[2].i = fg & 0xff; // blue - unibi_out(ui, data->unibi_ext.set_rgb_foreground); + unibi_out_ext(ui, data->unibi_ext.set_rgb_foreground); } if (bg != -1) { data->params[0].i = (bg >> 16) & 0xff; // red data->params[1].i = (bg >> 8) & 0xff; // green data->params[2].i = bg & 0xff; // blue - unibi_out(ui, data->unibi_ext.set_rgb_background); + unibi_out_ext(ui, data->unibi_ext.set_rgb_background); } } else { if (fg != -1) { @@ -326,30 +447,173 @@ static void update_attrs(UI *ui, HlAttrs attrs) } } - if (attrs.bold) { - unibi_out(ui, unibi_enter_bold_mode); - } - if (attrs.italic) { - unibi_out(ui, unibi_enter_italics_mode); - } - if (attrs.underline || attrs.undercurl) { - unibi_out(ui, unibi_enter_underline_mode); - } - if (attrs.reverse) { - unibi_out(ui, unibi_enter_reverse_mode); + data->default_attr = fg == -1 && bg == -1 + && !attrs.bold && !attrs.italic && !attrs.underline && !attrs.undercurl + && !attrs.reverse; +} + +static void final_column_wrap(UI *ui) +{ + TUIData *data = ui->data; + UGrid *grid = &data->grid; + if (grid->col == ui->width) { + grid->col = 0; + if (grid->row < ui->height) { + grid->row++; + } } } +/// It is undocumented, but in the majority of terminals and terminal emulators +/// printing at the right margin does not cause an automatic wrap until the +/// next character is printed, holding the cursor in place until then. static void print_cell(UI *ui, UCell *ptr) { + TUIData *data = ui->data; + UGrid *grid = &data->grid; + if (!data->immediate_wrap_after_last_column) { + // Printing the next character finally advances the cursor. + final_column_wrap(ui); + } update_attrs(ui, ptr->attrs); out(ui, ptr->data, strlen(ptr->data)); + grid->col++; + if (data->immediate_wrap_after_last_column) { + // Printing at the right margin immediately advances the cursor. + final_column_wrap(ui); + } +} + +static bool cheap_to_print(UI *ui, int row, int col, int next) +{ + TUIData *data = ui->data; + UGrid *grid = &data->grid; + UCell *cell = grid->cells[row] + col; + while (next) { + next--; + if (attrs_differ(cell->attrs, data->print_attrs)) { + if (data->default_attr) { + return false; + } + } + if (strlen(cell->data) > 1) { + return false; + } + cell++; + } + return true; +} + +/// This optimizes several cases where it is cheaper to do something other +/// than send a full cursor positioning control sequence. However, there are +/// some further optimizations that may seem obvious but that will not work. +/// +/// We cannot use VT (ASCII 0/11) for moving the cursor up, because VT means +/// move the cursor down on a DEC terminal. Similarly, on a DEC terminal FF +/// (ASCII 0/12) means the same thing and does not mean home. VT, CVT, and +/// TAB also stop at software-defined tabulation stops, not at a fixed set +/// of row/column positions. +static void cursor_goto(UI *ui, int row, int col) +{ + TUIData *data = ui->data; + UGrid *grid = &data->grid; + if (row == grid->row && col == grid->col) { + return; + } + if (0 == row && 0 == col) { + unibi_out(ui, unibi_cursor_home); + ugrid_goto(grid, row, col); + return; + } + if (0 == col ? col != grid->col : + row != grid->row ? false : + 1 == col ? 2 < grid->col && cheap_to_print(ui, grid->row, 0, col) : + 2 == col ? 5 < grid->col && cheap_to_print(ui, grid->row, 0, col) : + false) { + // Motion to left margin from anywhere else, or CR + printing chars is + // even less expensive than using BSes or CUB. + unibi_out(ui, unibi_carriage_return); + ugrid_goto(grid, grid->row, 0); + } else if (col > grid->col) { + int n = col - grid->col; + if (n <= (row == grid->row ? 4 : 2) + && cheap_to_print(ui, grid->row, grid->col, n)) { + UGRID_FOREACH_CELL(grid, grid->row, grid->row, + grid->col, col - 1, { + print_cell(ui, cell); + }); + } + } + if (row == grid->row) { + if (col < grid->col + // Deferred right margin wrap terminals have inconsistent ideas about + // where the cursor actually is during a deferred wrap. Relative + // motion calculations have OBOEs that cannot be compensated for, + // because two terminals that claim to be the same will implement + // different cursor positioning rules. + && (data->immediate_wrap_after_last_column || grid->col < ui->width)) { + int n = grid->col - col; + if (n <= 4) { // This might be just BS, so it is considered really cheap. + while (n--) { + unibi_out(ui, unibi_cursor_left); + } + } else { + data->params[0].i = n; + unibi_out(ui, unibi_parm_left_cursor); + } + ugrid_goto(grid, row, col); + return; + } else if (col > grid->col) { + int n = col - grid->col; + if (n <= 2) { + while (n--) { + unibi_out(ui, unibi_cursor_right); + } + } else { + data->params[0].i = n; + unibi_out(ui, unibi_parm_right_cursor); + } + ugrid_goto(grid, row, col); + return; + } + } + if (col == grid->col) { + if (row > grid->row) { + int n = row - grid->row; + if (n <= 4) { // This might be just LF, so it is considered really cheap. + while (n--) { + unibi_out(ui, unibi_cursor_down); + } + } else { + data->params[0].i = n; + unibi_out(ui, unibi_parm_down_cursor); + } + ugrid_goto(grid, row, col); + return; + } else if (row < grid->row) { + int n = grid->row - row; + if (n <= 2) { + while (n--) { + unibi_out(ui, unibi_cursor_up); + } + } else { + data->params[0].i = n; + unibi_out(ui, unibi_parm_up_cursor); + } + ugrid_goto(grid, row, col); + return; + } + } + unibi_goto(ui, row, col); + ugrid_goto(grid, row, col); } static void clear_region(UI *ui, int top, int bot, int left, int right) { TUIData *data = ui->data; UGrid *grid = &data->grid; + int saved_row = grid->row; + int saved_col = grid->col; bool cleared = false; if (grid->bg == -1 && right == ui->width -1) { @@ -363,8 +627,9 @@ static void clear_region(UI *ui, int top, int bot, int left, int right) if (bot == ui->height - 1) { if (top == 0) { unibi_out(ui, unibi_clear_screen); + ugrid_goto(&data->grid, top, left); } else { - unibi_goto(ui, top, 0); + cursor_goto(ui, top, 0); unibi_out(ui, unibi_clr_eos); } cleared = true; @@ -373,8 +638,8 @@ static void clear_region(UI *ui, int top, int bot, int left, int right) if (!cleared) { // iterate through each line and clear with clr_eol - for (int row = top; row <= bot; ++row) { - unibi_goto(ui, row, left); + for (int row = top; row <= bot; row++) { + cursor_goto(ui, row, left); unibi_out(ui, unibi_clr_eol); } cleared = true; @@ -383,29 +648,93 @@ static void clear_region(UI *ui, int top, int bot, int left, int right) if (!cleared) { // could not clear using faster terminal codes, refresh the whole region - int currow = -1; UGRID_FOREACH_CELL(grid, top, bot, left, right, { - if (currow != row) { - unibi_goto(ui, row, col); - currow = row; - } + cursor_goto(ui, row, col); print_cell(ui, cell); }); } // restore cursor + cursor_goto(ui, saved_row, saved_col); +} + +static bool can_use_scroll(UI * ui) +{ + TUIData *data = ui->data; + UGrid *grid = &data->grid; + + return data->scroll_region_is_full_screen + || (data->can_change_scroll_region + && ((grid->left == 0 && grid->right == ui->width - 1) + || data->can_set_lr_margin + || data->can_set_left_right_margin)); +} + +static void set_scroll_region(UI *ui) +{ + TUIData *data = ui->data; + UGrid *grid = &data->grid; + + data->params[0].i = grid->top; + data->params[1].i = grid->bot; + unibi_out(ui, unibi_change_scroll_region); + if (grid->left != 0 || grid->right != ui->width - 1) { + unibi_out_ext(ui, data->unibi_ext.enable_lr_margin); + if (data->can_set_lr_margin) { + data->params[0].i = grid->left; + data->params[1].i = grid->right; + unibi_out(ui, unibi_set_lr_margin); + } else { + data->params[0].i = grid->left; + unibi_out(ui, unibi_set_left_margin_parm); + data->params[0].i = grid->right; + unibi_out(ui, unibi_set_right_margin_parm); + } + } unibi_goto(ui, grid->row, grid->col); } -static void tui_resize(UI *ui, int width, int height) +static void reset_scroll_region(UI *ui) { TUIData *data = ui->data; - ugrid_resize(&data->grid, width, height); + UGrid *grid = &data->grid; + + if (0 <= data->unibi_ext.reset_scroll_region) { + unibi_out_ext(ui, data->unibi_ext.reset_scroll_region); + } else { + data->params[0].i = 0; + data->params[1].i = ui->height - 1; + unibi_out(ui, unibi_change_scroll_region); + } + if (grid->left != 0 || grid->right != ui->width - 1) { + if (data->can_set_lr_margin) { + data->params[0].i = 0; + data->params[1].i = ui->width - 1; + unibi_out(ui, unibi_set_lr_margin); + } else { + data->params[0].i = 0; + unibi_out(ui, unibi_set_left_margin_parm); + data->params[0].i = ui->width - 1; + unibi_out(ui, unibi_set_right_margin_parm); + } + unibi_out_ext(ui, data->unibi_ext.disable_lr_margin); + } + unibi_goto(ui, grid->row, grid->col); +} + +static void tui_resize(UI *ui, Integer width, Integer height) +{ + TUIData *data = ui->data; + ugrid_resize(&data->grid, (int)width, (int)height); if (!got_winch) { // Try to resize the terminal window. - char r[16]; // enough for 9999x9999 - snprintf(r, sizeof(r), "\x1b[8;%d;%dt", height, width); - out(ui, r, strlen(r)); + data->params[0].i = (int)height; + data->params[1].i = (int)width; + unibi_out_ext(ui, data->unibi_ext.resize_screen); + // DECSLPP does not reset the scroll region. + if (data->scroll_region_is_full_screen) { + reset_scroll_region(ui); + } } else { // Already handled the SIGWINCH signal; avoid double-resize. got_winch = false; } @@ -427,11 +756,65 @@ static void tui_eol_clear(UI *ui) clear_region(ui, grid->row, grid->row, grid->col, grid->right); } -static void tui_cursor_goto(UI *ui, int row, int col) +static void tui_cursor_goto(UI *ui, Integer row, Integer col) +{ + cursor_goto(ui, (int)row, (int)col); +} + +CursorShape tui_cursor_decode_shape(const char *shape_str) { + CursorShape shape = 0; + if (strequal(shape_str, "block")) { + shape = SHAPE_BLOCK; + } else if (strequal(shape_str, "vertical")) { + shape = SHAPE_VER; + } else if (strequal(shape_str, "horizontal")) { + shape = SHAPE_HOR; + } else { + EMSG2(_(e_invarg2), shape_str); + } + return shape; +} + +static cursorentry_T decode_cursor_entry(Dictionary args) +{ + cursorentry_T r; + + for (size_t i = 0; i < args.size; i++) { + char *key = args.items[i].key.data; + Object value = args.items[i].value; + + if (strequal(key, "cursor_shape")) { + r.shape = tui_cursor_decode_shape(args.items[i].value.data.string.data); + } else if (strequal(key, "blinkon")) { + r.blinkon = (int)value.data.integer; + } else if (strequal(key, "blinkoff")) { + r.blinkoff = (int)value.data.integer; + } else if (strequal(key, "hl_id")) { + r.id = (int)value.data.integer; + } + } + return r; +} + +static void tui_mode_info_set(UI *ui, bool guicursor_enabled, Array args) +{ + cursor_style_enabled = guicursor_enabled; + if (!guicursor_enabled) { + return; // Do not send cursor style control codes. + } TUIData *data = ui->data; - ugrid_goto(&data->grid, row, col); - unibi_goto(ui, row, col); + + assert(args.size); + + // cursor style entries as defined by `shape_table`. + for (size_t i = 0; i < args.size; i++) { + assert(args.items[i].type == kObjectTypeDictionary); + cursorentry_T r = decode_cursor_entry(args.items[i].data.dictionary); + data->cursor_shapes[i] = r; + } + + tui_set_mode(ui, data->showing_mode); } static void tui_update_menu(UI *ui) @@ -452,106 +835,119 @@ static void tui_busy_stop(UI *ui) static void tui_mouse_on(UI *ui) { TUIData *data = ui->data; - unibi_out(ui, data->unibi_ext.enable_mouse); - data->mouse_enabled = true; + if (!data->mouse_enabled) { + unibi_out_ext(ui, data->unibi_ext.enable_mouse); + data->mouse_enabled = true; + } } static void tui_mouse_off(UI *ui) { TUIData *data = ui->data; - unibi_out(ui, data->unibi_ext.disable_mouse); - data->mouse_enabled = false; + if (data->mouse_enabled) { + unibi_out_ext(ui, data->unibi_ext.disable_mouse); + data->mouse_enabled = false; + } } -static void tui_mode_change(UI *ui, int mode) +static void tui_set_mode(UI *ui, ModeShape mode) { + if (!cursor_style_enabled) { + return; + } TUIData *data = ui->data; - - if (mode == INSERT) { - if (data->showing_mode != INSERT) { - unibi_out(ui, data->unibi_ext.set_cursor_shape_bar); - } - } else if (mode == CMDLINE) { - if (data->showing_mode != CMDLINE) { - unibi_out(ui, data->unibi_ext.set_cursor_shape_bar); - } - } else if (mode == REPLACE) { - if (data->showing_mode != REPLACE) { - unibi_out(ui, data->unibi_ext.set_cursor_shape_ul); - } - } else { - assert(mode == NORMAL); - if (data->showing_mode != NORMAL) { - unibi_out(ui, data->unibi_ext.set_cursor_shape_block); + cursorentry_T c = data->cursor_shapes[mode]; + int shape = c.shape; + + if (c.id != 0 && ui->rgb) { + int attr = syn_id2attr(c.id); + if (attr > 0) { + attrentry_T *aep = syn_cterm_attr2entry(attr); + data->params[0].i = aep->rgb_bg_color; + unibi_out_ext(ui, data->unibi_ext.set_cursor_color); } } - data->showing_mode = mode; + + switch (shape) { + case SHAPE_BLOCK: shape = 1; break; + case SHAPE_HOR: shape = 3; break; + case SHAPE_VER: shape = 5; break; + default: WLOG("Unknown shape value %d", shape); break; + } + data->params[0].i = shape + (int)(c.blinkon == 0); + unibi_out_ext(ui, data->unibi_ext.set_cursor_style); +} + +/// @param mode editor mode +static void tui_mode_change(UI *ui, String mode, Integer mode_idx) +{ + TUIData *data = ui->data; + tui_set_mode(ui, (ModeShape)mode_idx); + data->showing_mode = (ModeShape)mode_idx; } -static void tui_set_scroll_region(UI *ui, int top, int bot, int left, - int right) +static void tui_set_scroll_region(UI *ui, Integer top, Integer bot, + Integer left, Integer right) { TUIData *data = ui->data; - ugrid_set_scroll_region(&data->grid, top, bot, left, right); - data->can_use_terminal_scroll = + ugrid_set_scroll_region(&data->grid, (int)top, (int)bot, + (int)left, (int)right); + data->scroll_region_is_full_screen = left == 0 && right == ui->width - 1 - && ((top == 0 && bot == ui->height - 1) - || unibi_get_str(data->ut, unibi_change_scroll_region)); + && top == 0 && bot == ui->height - 1; } -static void tui_scroll(UI *ui, int count) +static void tui_scroll(UI *ui, Integer count) { TUIData *data = ui->data; UGrid *grid = &data->grid; int clear_top, clear_bot; - ugrid_scroll(grid, count, &clear_top, &clear_bot); + ugrid_scroll(grid, (int)count, &clear_top, &clear_bot); + + if (can_use_scroll(ui)) { + int saved_row = grid->row; + int saved_col = grid->col; + bool scroll_clears_to_current_colour = + unibi_get_bool(data->ut, unibi_back_color_erase); - if (data->can_use_terminal_scroll) { // Change terminal scroll region and move cursor to the top - data->params[0].i = grid->top; - data->params[1].i = grid->bot; - unibi_out(ui, unibi_change_scroll_region); - unibi_goto(ui, grid->top, grid->left); + if (!data->scroll_region_is_full_screen) { + set_scroll_region(ui); + } + cursor_goto(ui, grid->top, grid->left); // also set default color attributes or some terminals can become funny - HlAttrs clear_attrs = EMPTY_ATTRS; - clear_attrs.foreground = grid->fg; - clear_attrs.background = grid->bg; - update_attrs(ui, clear_attrs); - } + if (scroll_clears_to_current_colour) { + HlAttrs clear_attrs = EMPTY_ATTRS; + clear_attrs.foreground = grid->fg; + clear_attrs.background = grid->bg; + update_attrs(ui, clear_attrs); + } - if (count > 0) { - if (data->can_use_terminal_scroll) { + if (count > 0) { if (count == 1) { unibi_out(ui, unibi_delete_line); } else { - data->params[0].i = count; + data->params[0].i = (int)count; unibi_out(ui, unibi_parm_delete_line); } - } - - } else { - if (data->can_use_terminal_scroll) { + } else { if (count == -1) { unibi_out(ui, unibi_insert_line); } else { - data->params[0].i = -count; + data->params[0].i = -(int)count; unibi_out(ui, unibi_parm_insert_line); } } - } - if (data->can_use_terminal_scroll) { // Restore terminal scroll region and cursor - data->params[0].i = 0; - data->params[1].i = ui->height - 1; - unibi_out(ui, unibi_change_scroll_region); - unibi_goto(ui, grid->row, grid->col); + if (!data->scroll_region_is_full_screen) { + reset_scroll_region(ui); + } + cursor_goto(ui, saved_row, saved_col); - if (grid->bg != -1) { - // Update the cleared area of the terminal if its builtin scrolling - // facility was used and the background color is not the default. This is - // required because scrolling may leave wrong background in the cleared - // area. + if (!scroll_clears_to_current_colour) { + // This is required because scrolling will leave wrong background in the + // cleared area on non-bge terminals. clear_region(ui, clear_top, clear_bot, grid->left, grid->right); } } else { @@ -565,10 +961,18 @@ static void tui_highlight_set(UI *ui, HlAttrs attrs) ((TUIData *)ui->data)->grid.attrs = attrs; } -static void tui_put(UI *ui, uint8_t *text, size_t size) +static void tui_put(UI *ui, String text) { TUIData *data = ui->data; - print_cell(ui, ugrid_put(&data->grid, text, size)); + UGrid *grid = &data->grid; + UCell *cell; + + cell = ugrid_put(&data->grid, (uint8_t *)text.data, text.size); + // ugrid_put does not advance the cursor correctly, as the actual terminal + // will when we print. Its cursor motion model is simplistic and wrong. So + // we have to undo what it has just done before doing it right. + grid->col--; + print_cell(ui, cell); } static void tui_bell(UI *ui) @@ -581,17 +985,17 @@ static void tui_visual_bell(UI *ui) unibi_out(ui, unibi_flash_screen); } -static void tui_update_fg(UI *ui, int fg) +static void tui_update_fg(UI *ui, Integer fg) { - ((TUIData *)ui->data)->grid.fg = fg; + ((TUIData *)ui->data)->grid.fg = (int)fg; } -static void tui_update_bg(UI *ui, int bg) +static void tui_update_bg(UI *ui, Integer bg) { - ((TUIData *)ui->data)->grid.bg = bg; + ((TUIData *)ui->data)->grid.bg = (int)bg; } -static void tui_update_sp(UI *ui, int sp) +static void tui_update_sp(UI *ui, Integer sp) { // Do nothing; 'special' color is for GUI only } @@ -603,7 +1007,7 @@ static void tui_flush(UI *ui) size_t nrevents = loop_size(data->loop); if (nrevents > TOO_MANY_EVENTS) { - ILOG("TUI event-queue flooded (thread_events=%zu); purging", nrevents); + WLOG("TUI event-queue flooded (thread_events=%zu); purging", nrevents); // Back-pressure: UI events may accumulate much faster than the terminal // device can serve them. Even if SIGINT/CTRL-C is received, user must still // wait for the TUI event-queue to drain, and if there are ~millions of @@ -613,23 +1017,23 @@ static void tui_flush(UI *ui) tui_busy_stop(ui); // avoid hidden cursor } + int saved_row = grid->row; + int saved_col = grid->col; + while (kv_size(data->invalid_regions)) { Rect r = kv_pop(data->invalid_regions); - int currow = -1; UGRID_FOREACH_CELL(grid, r.top, r.bot, r.left, r.right, { - if (currow != row) { - unibi_goto(ui, row, col); - currow = row; - } + cursor_goto(ui, row, col); print_cell(ui, cell); }); } - unibi_goto(ui, grid->row, grid->col); + cursor_goto(ui, saved_row, saved_col); flush_buf(ui, true); } +#ifdef UNIX static void suspend_event(void **argv) { UI *ui = argv[0]; @@ -651,30 +1055,33 @@ static void suspend_event(void **argv) // resume the main thread CONTINUE(data->bridge); } +#endif static void tui_suspend(UI *ui) { +#ifdef UNIX TUIData *data = ui->data; // kill(0, SIGTSTP) won't stop the UI thread, so we must poll for SIGCONT // before continuing. This is done in another callback to avoid // loop_poll_events recursion multiqueue_put_event(data->loop->fast_events, - event_create(1, suspend_event, 1, ui)); + event_create(suspend_event, 1, ui)); +#endif } -static void tui_set_title(UI *ui, char *title) +static void tui_set_title(UI *ui, String title) { TUIData *data = ui->data; - if (!(title && unibi_get_str(data->ut, unibi_to_status_line) + if (!(title.data && unibi_get_str(data->ut, unibi_to_status_line) && unibi_get_str(data->ut, unibi_from_status_line))) { return; } unibi_out(ui, unibi_to_status_line); - out(ui, title, strlen(title)); + out(ui, title.data, title.size); unibi_out(ui, unibi_from_status_line); } -static void tui_set_icon(UI *ui, char *icon) +static void tui_set_icon(UI *ui, String icon) { } @@ -775,31 +1182,33 @@ static void unibi_goto(UI *ui, int row, int col) unibi_out(ui, unibi_cursor_address); } +#define UNIBI_OUT(fn) \ + do { \ + TUIData *data = ui->data; \ + const char *str = NULL; \ + if (unibi_index >= 0) { \ + str = fn(data->ut, (unsigned)unibi_index); \ + } \ + if (str) { \ + unibi_var_t vars[26 + 26] = { { 0 } }; \ + unibi_format(vars, vars + 26, str, data->params, out, ui, NULL, NULL); \ + } \ + } while (0) static void unibi_out(UI *ui, int unibi_index) { - TUIData *data = ui->data; - - const char *str = NULL; - - if (unibi_index >= 0) { - if (unibi_index < unibi_string_begin_) { - str = unibi_get_ext_str(data->ut, (unsigned)unibi_index); - } else { - str = unibi_get_str(data->ut, (unsigned)unibi_index); - } - } - - if (str) { - unibi_var_t vars[26 + 26] = {{0}}; - unibi_format(vars, vars + 26, str, data->params, out, ui, NULL, NULL); - } + UNIBI_OUT(unibi_get_str); +} +static void unibi_out_ext(UI *ui, int unibi_index) +{ + UNIBI_OUT(unibi_get_ext_str); } +#undef UNIBI_OUT static void out(void *ctx, const char *str, size_t len) { UI *ui = ctx; TUIData *data = ui->data; - size_t available = data->bufsize - data->bufpos; + size_t available = sizeof(data->buf) - data->bufpos; if (len > available) { flush_buf(ui, false); @@ -817,152 +1226,453 @@ static void unibi_set_if_empty(unibi_term *ut, enum unibi_string str, } } -static void fix_terminfo(TUIData *data) +static int unibi_find_ext_str(unibi_term *ut, const char *name) { - unibi_term *ut = data->ut; + size_t max = unibi_count_ext_str(ut); + for (size_t i = 0; i < max; i++) { + const char * n = unibi_get_ext_str_name(ut, i); + if (n && 0 == strcmp(n, name)) { + return (int)i; + } + } + return -1; +} - const char *term = os_getenv("TERM"); - const char *colorterm = os_getenv("COLORTERM"); - if (!term) { - goto end; +/// Several entries in terminfo are known to be deficient or outright wrong, +/// unfortunately; and several terminal emulators falsely announce incorrect +/// terminal types. So patch the terminfo records after loading from an +/// external or a built-in database. In an ideal world, the real terminfo data +/// would be correct and complete, and this function would be almost empty. +static void patch_terminfo_bugs(TUIData *data, const char *term, + const char *colorterm, long vte_version, + bool konsole, bool iterm_env) +{ + unibi_term *ut = data->ut; + const char * xterm_version = os_getenv("XTERM_VERSION"); +#if 0 // We don't need to identify this specifically, for now. + bool roxterm = !!os_getenv("ROXTERM_ID"); +#endif + bool xterm = terminfo_is_term_family(term, "xterm"); + bool linuxvt = terminfo_is_term_family(term, "linux"); + bool rxvt = terminfo_is_term_family(term, "rxvt"); + bool teraterm = terminfo_is_term_family(term, "teraterm"); + bool putty = terminfo_is_term_family(term, "putty"); + bool screen = terminfo_is_term_family(term, "screen"); + bool tmux = terminfo_is_term_family(term, "tmux") || !!os_getenv("TMUX"); + bool st = terminfo_is_term_family(term, "st"); + bool gnome = terminfo_is_term_family(term, "gnome") + || terminfo_is_term_family(term, "vte"); + bool iterm = terminfo_is_term_family(term, "iterm") + || terminfo_is_term_family(term, "iterm2") + || terminfo_is_term_family(term, "iTerm.app") + || terminfo_is_term_family(term, "iTerm2.app"); + // None of the following work over SSH; see :help TERM . + bool iterm_pretending_xterm = xterm && iterm_env; + bool konsole_pretending_xterm = xterm && konsole; + bool gnome_pretending_xterm = xterm && colorterm + && strstr(colorterm, "gnome-terminal"); + bool mate_pretending_xterm = xterm && colorterm + && strstr(colorterm, "mate-terminal"); + bool true_xterm = xterm && !!xterm_version; + + char *fix_normal = (char *)unibi_get_str(ut, unibi_cursor_normal); + if (fix_normal) { + if (STARTS_WITH(fix_normal, "\x1b[?12l")) { + // terminfo typically includes DECRST 12 as part of setting up the + // normal cursor, which interferes with the user's control via + // set_cursor_style. When DECRST 12 is present, skip over it, but honor + // the rest of the cnorm setting. + fix_normal += sizeof "\x1b[?12l" - 1; + unibi_set_str(ut, unibi_cursor_normal, fix_normal); + } + if (linuxvt + && strlen(fix_normal) >= (sizeof LINUXSET0C - 1) + && !memcmp(strchr(fix_normal, 0) - (sizeof LINUXSET0C - 1), + LINUXSET0C, sizeof LINUXSET0C - 1)) { + // The Linux terminfo entry similarly includes a Linux-idiosyncractic + // cursor shape reset in cnorm, which similarly interferes with + // set_cursor_style. + fix_normal[strlen(fix_normal) - (sizeof LINUXSET0C - 1)] = 0; + } + } + char *fix_invisible = (char *)unibi_get_str(ut, unibi_cursor_invisible); + if (fix_invisible) { + if (linuxvt + && strlen(fix_invisible) >= (sizeof LINUXSET1C - 1) + && !memcmp(strchr(fix_invisible, 0) - (sizeof LINUXSET1C - 1), + LINUXSET1C, sizeof LINUXSET1C - 1)) { + // The Linux terminfo entry similarly includes a Linux-idiosyncractic + // cursor shape reset in cinvis, which similarly interferes with + // set_cursor_style. + fix_invisible[strlen(fix_invisible) - (sizeof LINUXSET1C - 1)] = 0; + } } - bool inside_tmux = os_getenv("TMUX") != NULL; + if (xterm) { + // Termit, LXTerminal, GTKTerm2, GNOME Terminal, MATE Terminal, roxterm, + // and EvilVTE falsely claim to be xterm and do not support important xterm + // control sequences that we use. In an ideal world, these would have + // their own terminal types and terminfo entries, like PuTTY does, and not + // claim to be xterm. Or they would mimic xterm properly enough to be + // treatable as xterm. -#define STARTS_WITH(str, prefix) (!memcmp(str, prefix, sizeof(prefix) - 1)) + // 2017-04 terminfo.src lacks these. genuine Xterm has them, as have + // the false claimants. + unibi_set_if_empty(ut, unibi_to_status_line, "\x1b]0;"); + unibi_set_if_empty(ut, unibi_from_status_line, "\x07"); + unibi_set_if_empty(ut, unibi_set_tb_margin, "\x1b[%i%p1%d;%p2%dr"); - if (STARTS_WITH(term, "rxvt")) { - unibi_set_if_empty(ut, unibi_exit_attribute_mode, "\x1b[m\x1b(B"); - unibi_set_if_empty(ut, unibi_flash_screen, "\x1b[?5h$<20/>\x1b[?5l"); + if (true_xterm) { + // 2017-04 terminfo.src lacks these. genuine Xterm has them. + unibi_set_if_empty(ut, unibi_set_lr_margin, "\x1b[%i%p1%d;%p2%ds"); + unibi_set_if_empty(ut, unibi_set_left_margin_parm, "\x1b[%i%p1%ds"); + unibi_set_if_empty(ut, unibi_set_right_margin_parm, "\x1b[%i;%p2%ds"); + } + if (true_xterm + || iterm_pretending_xterm + || gnome_pretending_xterm + || konsole_pretending_xterm) { + // Apple's outdated copy of terminfo.src for MacOS lacks these. + // genuine Xterm and three false claimants have them. + unibi_set_if_empty(ut, unibi_enter_italics_mode, "\x1b[3m"); + unibi_set_if_empty(ut, unibi_exit_italics_mode, "\x1b[23m"); + } + } else if (rxvt) { + // 2017-04 terminfo.src lacks these. Unicode rxvt has them. unibi_set_if_empty(ut, unibi_enter_italics_mode, "\x1b[3m"); + unibi_set_if_empty(ut, unibi_exit_italics_mode, "\x1b[23m"); unibi_set_if_empty(ut, unibi_to_status_line, "\x1b]2"); - } else if (STARTS_WITH(term, "xterm")) { - unibi_set_if_empty(ut, unibi_to_status_line, "\x1b]0;"); - } else if (STARTS_WITH(term, "screen") || STARTS_WITH(term, "tmux")) { + unibi_set_if_empty(ut, unibi_from_status_line, "\x07"); + // 2017-04 terminfo.src has older control sequences. + unibi_set_str(ut, unibi_enter_ca_mode, "\x1b[?1049h"); + unibi_set_str(ut, unibi_exit_ca_mode, "\x1b[?1049l"); + } else if (screen) { + // per the screen manual; 2017-04 terminfo.src lacks these. unibi_set_if_empty(ut, unibi_to_status_line, "\x1b_"); unibi_set_if_empty(ut, unibi_from_status_line, "\x1b\\"); + } else if (tmux) { + unibi_set_if_empty(ut, unibi_to_status_line, "\x1b_"); + unibi_set_if_empty(ut, unibi_from_status_line, "\x1b\\"); + } else if (terminfo_is_term_family(term, "interix")) { + // 2017-04 terminfo.src lacks this. + unibi_set_if_empty(ut, unibi_carriage_return, "\x0d"); + } else if (linuxvt) { + // Apple's outdated copy of terminfo.src for MacOS lacks these. + unibi_set_if_empty(ut, unibi_parm_up_cursor, "\x1b[%p1%dA"); + unibi_set_if_empty(ut, unibi_parm_down_cursor, "\x1b[%p1%dB"); + unibi_set_if_empty(ut, unibi_parm_right_cursor, "\x1b[%p1%dC"); + unibi_set_if_empty(ut, unibi_parm_left_cursor, "\x1b[%p1%dD"); + } else if (putty) { + // No bugs in the vanilla terminfo for our purposes. + } else if (iterm) { + // 2017-04 terminfo.src has older control sequences. + unibi_set_str(ut, unibi_enter_ca_mode, "\x1b[?1049h"); + unibi_set_str(ut, unibi_exit_ca_mode, "\x1b[?1049l"); + // 2017-04 terminfo.src lacks these. + unibi_set_if_empty(ut, unibi_set_tb_margin, "\x1b[%i%p1%d;%p2%dr"); + unibi_set_if_empty(ut, unibi_orig_pair, "\x1b[39;49m"); + unibi_set_if_empty(ut, unibi_enter_dim_mode, "\x1b[2m"); + unibi_set_if_empty(ut, unibi_enter_italics_mode, "\x1b[3m"); + unibi_set_if_empty(ut, unibi_exit_italics_mode, "\x1b[23m"); + unibi_set_if_empty(ut, unibi_exit_underline_mode, "\x1b[24m"); + unibi_set_if_empty(ut, unibi_exit_standout_mode, "\x1b[27m"); + } else if (st) { + // No bugs in the vanilla terminfo for our purposes. } - if (STARTS_WITH(term, "xterm") || STARTS_WITH(term, "rxvt")) { - unibi_set_if_empty(ut, unibi_cursor_normal, "\x1b[?12l\x1b[?25h"); - unibi_set_if_empty(ut, unibi_cursor_invisible, "\x1b[?25l"); - unibi_set_if_empty(ut, unibi_flash_screen, "\x1b[?5h$<100/>\x1b[?5l"); - unibi_set_if_empty(ut, unibi_exit_attribute_mode, "\x1b(B\x1b[m"); - unibi_set_if_empty(ut, unibi_change_scroll_region, "\x1b[%i%p1%d;%p2%dr"); - unibi_set_if_empty(ut, unibi_clear_screen, "\x1b[H\x1b[2J"); - unibi_set_if_empty(ut, unibi_from_status_line, "\x07"); - } - - data->unibi_ext.enable_bracketed_paste = (int)unibi_add_ext_str(ut, NULL, - "\x1b[?2004h"); - data->unibi_ext.disable_bracketed_paste = (int)unibi_add_ext_str(ut, NULL, - "\x1b[?2004l"); +// At this time (2017-07-12) it seems like all terminals that support 256 +// color codes can use semicolons in the terminal code and be fine. +// However, this is not correct according to the spec. So to reward those +// terminals that also support colons, we output the code that way on these +// specific ones. - 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"); +// using colons like ISO 8613-6:1994/ITU T.416:1993 says. +#define XTERM_SETAF_256_COLON \ + "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38:5:%p1%d%;m" +#define XTERM_SETAB_256_COLON \ + "\x1b[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48:5:%p1%d%;m" -#define XTERM_SETAF \ +#define XTERM_SETAF_256 \ "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m" -#define XTERM_SETAB \ +#define XTERM_SETAB_256 \ "\x1b[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m" +#define XTERM_SETAF_16 \ + "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e39%;m" +#define XTERM_SETAB_16 \ + "\x1b[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e39%;m" + + // Terminals where there is actually 256-colour SGR support despite what + // the terminfo record may say. + if (unibi_get_num(ut, unibi_max_colors) < 256) { + // See http://fedoraproject.org/wiki/Features/256_Color_Terminals for + // more on this. + if (true_xterm || iterm || iterm_pretending_xterm) { + unibi_set_num(ut, unibi_max_colors, 256); + unibi_set_str(ut, unibi_set_a_foreground, XTERM_SETAF_256_COLON); + unibi_set_str(ut, unibi_set_a_background, XTERM_SETAB_256_COLON); + } else if (konsole || xterm || gnome || rxvt || st || putty + || linuxvt // Linux 4.8+ supports 256-colour SGR. + || mate_pretending_xterm || gnome_pretending_xterm + || tmux + || (colorterm && strstr(colorterm, "256")) + || (term && strstr(term, "256"))) { + unibi_set_num(ut, unibi_max_colors, 256); + unibi_set_str(ut, unibi_set_a_foreground, XTERM_SETAF_256); + unibi_set_str(ut, unibi_set_a_background, XTERM_SETAB_256); + } + } + // Terminals where there is actually 16-colour SGR support despite what + // the terminfo record may say. + if (unibi_get_num(ut, unibi_max_colors) < 16) { + if (colorterm) { + unibi_set_num(ut, unibi_max_colors, 16); + unibi_set_if_empty(ut, unibi_set_a_foreground, XTERM_SETAF_16); + unibi_set_if_empty(ut, unibi_set_a_background, XTERM_SETAB_16); + } + } - if ((colorterm && strstr(colorterm, "256")) - || strstr(term, "256") - || strstr(term, "xterm")) { - // Assume TERM~=xterm or COLORTERM~=256 supports 256 colors. - unibi_set_num(ut, unibi_max_colors, 256); - unibi_set_str(ut, unibi_set_a_foreground, XTERM_SETAF); - unibi_set_str(ut, unibi_set_a_background, XTERM_SETAB); + // Some terminals can not currently be trusted to report if they support + // DECSCUSR or not. So we need to have a blacklist for when we should not + // trust the reported features. + if (!((vte_version != 0 && vte_version < 3900) || konsole)) { + // Dickey ncurses terminfo has included the Ss and Se capabilities, + // pioneered by tmux, since 2011-07-14. So adding them to terminal types, + // that do actually have such control sequences but lack the correct + // definitions in terminfo, is a fixup, not an augmentation. + data->unibi_ext.reset_cursor_style = unibi_find_ext_str(ut, "Se"); + data->unibi_ext.set_cursor_style = unibi_find_ext_str(ut, "Ss"); } + if (-1 == data->unibi_ext.set_cursor_style) { + // The DECSCUSR sequence to change the cursor shape is widely + // supported by several terminal types and should be in many + // teminfo entries. See + // https://github.com/gnachman/iTerm2/pull/92 for more. + // xterm even has an extended version that has a vertical bar. + if (!konsole && (true_xterm // per xterm ctlseqs doco (since version 282) + // per MinTTY 0.4.3-1 release notes from 2009 + || putty + // per https://bugzilla.gnome.org/show_bug.cgi?id=720821 + || (vte_version >= 3900) + || tmux // per tmux manual page + // https://lists.gnu.org/archive/html/screen-devel/2013-03/msg00000.html + || screen + || rxvt // per command.C + // per analysis of VT100Terminal.m + || iterm || iterm_pretending_xterm + || teraterm // per TeraTerm "Supported Control Functions" doco + // Allows forcing the use of DECSCUSR on linux type terminals, such as + // console-terminal-emulator from the nosh toolset, which does indeed + // implement the xterm extension: + || (linuxvt && (xterm_version || (vte_version > 0) || colorterm)))) { + data->unibi_ext.set_cursor_style = + (int)unibi_add_ext_str(ut, "Ss", "\x1b[%p1%d q"); + if (-1 == data->unibi_ext.reset_cursor_style) { + data->unibi_ext.reset_cursor_style = (int)unibi_add_ext_str(ut, "Se", + ""); + } + unibi_set_ext_str(ut, (size_t)data->unibi_ext.reset_cursor_style, + "\x1b[ q"); + } else if (linuxvt) { + // Linux uses an idiosyncratic escape code to set the cursor shape and + // does not support DECSCUSR. + // See http://linuxgazette.net/137/anonymous.html for more info + data->unibi_ext.set_cursor_style = (int)unibi_add_ext_str(ut, "Ss", + "\x1b[?" + "%?" + // The parameter passed to Ss is the DECSCUSR parameter, so the + // terminal capability has to translate into the Linux idiosyncratic + // parameter. + // + // linuxvt only supports block and underline. It is also only + // possible to have a steady block (no steady underline) + "%p1%{2}%<" "%t%{8}" // blink block + "%e%p1%{2}%=" "%t%{112}" // steady block + "%e%p1%{3}%=" "%t%{4}" // blink underline (set to half block) + "%e%p1%{4}%=" "%t%{4}" // steady underline + "%e%p1%{5}%=" "%t%{2}" // blink bar (set to underline) + "%e%p1%{6}%=" "%t%{2}" // steady bar + "%e%{0}" // anything else + "%;" "%dc"); + if (-1 == data->unibi_ext.reset_cursor_style) { + data->unibi_ext.reset_cursor_style = (int)unibi_add_ext_str(ut, "Se", + ""); + } + unibi_set_ext_str(ut, (size_t)data->unibi_ext.reset_cursor_style, + "\x1b[?c"); + } else if (konsole) { + // Konsole uses an idiosyncratic escape code to set the cursor shape and + // does not support DECSCUSR. This makes Konsole set up and apply a + // nonce profile, which has side-effects on temporary font resizing. + // In an ideal world, Konsole would just support DECSCUSR. + data->unibi_ext.set_cursor_style = (int)unibi_add_ext_str(ut, "Ss", + TMUX_WRAP(tmux, "\x1b]50;CursorShape=%?" + "%p1%{3}%<" "%t%{0}" // block + "%e%p1%{5}%<" "%t%{2}" // underline + "%e%{1}" // everything else is bar + "%;%d;BlinkingCursorEnabled=%?" + "%p1%{1}%<" "%t%{1}" // Fortunately if we exclude zero as special, + "%e%p1%{1}%&" // in all other cases we can treat bit #0 as a flag. + "%;%d\x07")); + if (-1 == data->unibi_ext.reset_cursor_style) { + data->unibi_ext.reset_cursor_style = (int)unibi_add_ext_str(ut, "Se", + ""); + } + unibi_set_ext_str(ut, (size_t)data->unibi_ext.reset_cursor_style, + "\x1b]50;\x07"); + } + } +} - if (os_getenv("NVIM_TUI_ENABLE_CURSOR_SHAPE") == NULL) { - goto end; +/// This adds stuff that is not in standard terminfo as extended unibilium +/// capabilities. +static void augment_terminfo(TUIData *data, const char *term, + const char *colorterm, long vte_version, bool konsole, bool iterm_env) +{ + unibi_term *ut = data->ut; + bool xterm = terminfo_is_term_family(term, "xterm"); + bool dtterm = terminfo_is_term_family(term, "dtterm"); + bool rxvt = terminfo_is_term_family(term, "rxvt"); + bool teraterm = terminfo_is_term_family(term, "teraterm"); + bool putty = terminfo_is_term_family(term, "putty"); + bool screen = terminfo_is_term_family(term, "screen"); + bool tmux = terminfo_is_term_family(term, "tmux") || !!os_getenv("TMUX"); + bool iterm = terminfo_is_term_family(term, "iterm") + || terminfo_is_term_family(term, "iterm2") + || terminfo_is_term_family(term, "iTerm.app") + || terminfo_is_term_family(term, "iTerm2.app"); + // None of the following work over SSH; see :help TERM . + bool iterm_pretending_xterm = xterm && iterm_env; + + const char * xterm_version = os_getenv("XTERM_VERSION"); + bool true_xterm = xterm && !!xterm_version; + + // Only define this capability for terminal types that we know understand it. + if (dtterm // originated this extension + || xterm // per xterm ctlseqs doco + || konsole // per commentary in VT102Emulation.cpp + || teraterm // per TeraTerm "Supported Control Functions" doco + || rxvt) { // per command.C + data->unibi_ext.resize_screen = (int)unibi_add_ext_str(ut, NULL, + "\x1b[8;%p1%d;%p2%dt"); + } + if (putty || xterm || rxvt) { + data->unibi_ext.reset_scroll_region = (int)unibi_add_ext_str(ut, NULL, + "\x1b[r"); + } + + // Dickey ncurses terminfo does not include the setrgbf and setrgbb + // capabilities, proposed by Rรผdiger Sonderfeld on 2013-10-15. So adding + // them to terminal types, that do actually have such control sequences but + // lack the correct definitions in terminfo, is an augmentation, not a + // fixup. See https://gist.github.com/XVilka/8346728 for more about this. + + // At this time (2017-07-12) it seems like all terminals that support rgb + // color codes can use semicolons in the terminal code and be fine. + // However, this is not correct according to the spec. So to reward those + // terminals that also support colons, we output the code that way on these + // specific ones. + + // can use colons like ISO 8613-6:1994/ITU T.416:1993 says. + bool has_colon_rgb = !tmux && !screen + && ((vte_version >= 3600) // per GNOME bug #685759, #704449 + || iterm || iterm_pretending_xterm // per analysis of VT100Terminal.m + // per http://invisible-island.net/xterm/xterm.log.html#xterm_282 + || true_xterm); + + data->unibi_ext.set_rgb_foreground = unibi_find_ext_str(ut, "setrgbf"); + if (-1 == data->unibi_ext.set_rgb_foreground) { + if (has_colon_rgb) { + data->unibi_ext.set_rgb_foreground = (int)unibi_add_ext_str(ut, "setrgbf", + "\x1b[38:2:%p1%d:%p2%d:%p3%dm"); + } else { + data->unibi_ext.set_rgb_foreground = (int)unibi_add_ext_str(ut, "setrgbf", + "\x1b[38;2;%p1%d;%p2%d;%p3%dm"); + } + } + data->unibi_ext.set_rgb_background = unibi_find_ext_str(ut, "setrgbb"); + if (-1 == data->unibi_ext.set_rgb_background) { + if (has_colon_rgb) { + data->unibi_ext.set_rgb_background = (int)unibi_add_ext_str(ut, "setrgbb", + "\x1b[48:2:%p1%d:%p2%d:%p3%dm"); + } else { + data->unibi_ext.set_rgb_background = (int)unibi_add_ext_str(ut, "setrgbb", + "\x1b[48;2;%p1%d;%p2%d;%p3%dm"); + } } -#define TMUX_WRAP(seq) (inside_tmux ? "\x1bPtmux;\x1b" seq "\x1b\\" : seq) - // Support changing cursor shape on some popular terminals. - const char *term_prog = os_getenv("TERM_PROGRAM"); - const char *vte_version = os_getenv("VTE_VERSION"); - - if ((term_prog && !strcmp(term_prog, "Konsole")) - || os_getenv("KONSOLE_DBUS_SESSION") != NULL) { - // Konsole uses a proprietary escape code to set the cursor shape - // and does not support DECSCUSR. - data->unibi_ext.set_cursor_shape_bar = (int)unibi_add_ext_str(ut, NULL, - TMUX_WRAP("\x1b]50;CursorShape=1;BlinkingCursorEnabled=1\x07")); - data->unibi_ext.set_cursor_shape_ul = (int)unibi_add_ext_str(ut, NULL, - TMUX_WRAP("\x1b]50;CursorShape=2;BlinkingCursorEnabled=1\x07")); - data->unibi_ext.set_cursor_shape_block = (int)unibi_add_ext_str(ut, NULL, - TMUX_WRAP("\x1b]50;CursorShape=0;BlinkingCursorEnabled=0\x07")); - } else if (!vte_version || atoi(vte_version) >= 3900) { - // Assume that the terminal supports DECSCUSR unless it is an - // old VTE based terminal. This should not get wrapped for tmux, - // which will handle it via its Ss/Se terminfo extension - usually - // according to its terminal-overrides. - data->unibi_ext.set_cursor_shape_bar = - (int)unibi_add_ext_str(ut, NULL, "\x1b[5 q"); - data->unibi_ext.set_cursor_shape_ul = - (int)unibi_add_ext_str(ut, NULL, "\x1b[3 q"); - data->unibi_ext.set_cursor_shape_block = - (int)unibi_add_ext_str(ut, NULL, "\x1b[2 q"); + if (iterm || iterm_pretending_xterm) { + // FIXME: Bypassing tmux like this affects the cursor colour globally, in + // all panes, which is not particularly desirable. A better approach + // would use a tmux control sequence and an extra if(screen) test. + data->unibi_ext.set_cursor_color = (int)unibi_add_ext_str( + ut, NULL, TMUX_WRAP(tmux, "\033]Pl%p1%06x\033\\")); + } else if (xterm || (vte_version != 0) || rxvt) { + // This seems to be supported for a long time in VTE + // urxvt also supports this + data->unibi_ext.set_cursor_color = (int)unibi_add_ext_str( + ut, NULL, "\033]12;#%p1%06x\007"); } -end: - // Fill some empty slots with common terminal strings + /// Terminals generally ignore private modes that they do not recognize, + /// and there is no known ambiguity with these modes from terminal type to + /// terminal type, so we can afford to just set these unconditionally. + data->unibi_ext.enable_lr_margin = (int)unibi_add_ext_str(ut, NULL, + "\x1b[?69h"); + data->unibi_ext.disable_lr_margin = (int)unibi_add_ext_str(ut, NULL, + "\x1b[?69l"); + data->unibi_ext.enable_bracketed_paste = (int)unibi_add_ext_str(ut, NULL, + "\x1b[?2004h"); + 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"); data->unibi_ext.enable_mouse = (int)unibi_add_ext_str(ut, NULL, "\x1b[?1002h\x1b[?1006h"); data->unibi_ext.disable_mouse = (int)unibi_add_ext_str(ut, NULL, "\x1b[?1002l\x1b[?1006l"); - data->unibi_ext.set_rgb_foreground = (int)unibi_add_ext_str(ut, NULL, - "\x1b[38;2;%p1%d;%p2%d;%p3%dm"); - data->unibi_ext.set_rgb_background = (int)unibi_add_ext_str(ut, NULL, - "\x1b[48;2;%p1%d;%p2%d;%p3%dm"); - unibi_set_if_empty(ut, unibi_cursor_address, "\x1b[%i%p1%d;%p2%dH"); - unibi_set_if_empty(ut, unibi_exit_attribute_mode, "\x1b[0;10m"); - unibi_set_if_empty(ut, unibi_set_a_foreground, XTERM_SETAF); - unibi_set_if_empty(ut, unibi_set_a_background, XTERM_SETAB); - unibi_set_if_empty(ut, unibi_enter_bold_mode, "\x1b[1m"); - unibi_set_if_empty(ut, unibi_enter_underline_mode, "\x1b[4m"); - unibi_set_if_empty(ut, unibi_enter_reverse_mode, "\x1b[7m"); - unibi_set_if_empty(ut, unibi_bell, "\x07"); - unibi_set_if_empty(data->ut, unibi_enter_ca_mode, "\x1b[?1049h"); - unibi_set_if_empty(data->ut, unibi_exit_ca_mode, "\x1b[?1049l"); - unibi_set_if_empty(ut, unibi_delete_line, "\x1b[M"); - unibi_set_if_empty(ut, unibi_parm_delete_line, "\x1b[%p1%dM"); - unibi_set_if_empty(ut, unibi_insert_line, "\x1b[L"); - unibi_set_if_empty(ut, unibi_parm_insert_line, "\x1b[%p1%dL"); - unibi_set_if_empty(ut, unibi_clear_screen, "\x1b[H\x1b[J"); - unibi_set_if_empty(ut, unibi_clr_eol, "\x1b[K"); - unibi_set_if_empty(ut, unibi_clr_eos, "\x1b[J"); } static void flush_buf(UI *ui, bool toggle_cursor) { uv_write_t req; - uv_buf_t buf; + uv_buf_t bufs[3]; + uv_buf_t *bufp = bufs; TUIData *data = ui->data; - if (toggle_cursor && !data->busy) { - // not busy and the cursor is invisible(see below). Append a "cursor - // normal" command to the end of the buffer. - data->bufsize += CNORM_COMMAND_MAX_SIZE; - unibi_out(ui, unibi_cursor_normal); - data->bufsize -= CNORM_COMMAND_MAX_SIZE; + if (data->bufpos <= 0 && data->busy == data->is_invisible) { + return; + } + + if (toggle_cursor && !data->is_invisible) { + // cursor is visible. Write a "cursor invisible" command before writing the + // buffer. + bufp->base = data->invis; + bufp->len = data->invislen; + bufp++; + data->is_invisible = true; } - buf.base = data->buf; - buf.len = data->bufpos; - uv_write(&req, (uv_stream_t *)&data->output_handle, &buf, 1, NULL); - uv_run(&data->write_loop, UV_RUN_DEFAULT); - data->bufpos = 0; + if (data->bufpos > 0) { + bufp->base = data->buf; + bufp->len = data->bufpos; + bufp++; + } - if (toggle_cursor && !data->busy) { - // not busy and cursor is visible(see above), append a "cursor invisible" - // command to the beginning of the buffer for the next flush - unibi_out(ui, unibi_cursor_invisible); + if (toggle_cursor && !data->busy && data->is_invisible) { + // not busy and the cursor is invisible. Write a "cursor normal" command + // after writing the buffer. + bufp->base = data->norm; + bufp->len = data->normlen; + bufp++; + data->is_invisible = data->busy; } + + uv_write(&req, STRUCT_CAST(uv_stream_t, &data->output_handle), + bufs, (unsigned)(bufp - bufs), NULL); + uv_run(&data->write_loop, UV_RUN_DEFAULT); + data->bufpos = 0; } #if TERMKEY_VERSION_MAJOR > 0 || TERMKEY_VERSION_MINOR > 18 @@ -979,7 +1689,7 @@ static const char *tui_get_stty_erase(void) if (tcgetattr(input_global_fd(), &t) != -1) { stty_erase[0] = (char)t.c_cc[VERASE]; stty_erase[1] = '\0'; - ILOG("stty/termios:erase=%s", stty_erase); + DLOG("stty/termios:erase=%s", stty_erase); } #endif return stty_erase; @@ -995,16 +1705,16 @@ static const char *tui_tk_ti_getstr(const char *name, const char *value, stty_erase = tui_get_stty_erase(); } - if (strcmp(name, "key_backspace") == 0) { - ILOG("libtermkey:kbs=%s", value); - if (stty_erase != NULL && stty_erase[0] != 0) { + if (strequal(name, "key_backspace")) { + DLOG("libtermkey:kbs=%s", value); + if (stty_erase[0] != 0) { return stty_erase; } - } else if (strcmp(name, "key_dc") == 0) { - ILOG("libtermkey:kdch1=%s", value); + } else if (strequal(name, "key_dc")) { + DLOG("libtermkey:kdch1=%s", value); // Vim: "If <BS> and <DEL> are now the same, redefine <DEL>." - if (stty_erase != NULL && strcmp(stty_erase, value) == 0) { - return stty_erase[0] == DEL ? (char *)CTRL_H_STR : (char *)DEL_STR; + if (value != NULL && strequal(stty_erase, value)) { + return stty_erase[0] == DEL ? CTRL_H_STR : DEL_STR; } } diff --git a/src/nvim/tui/tui.h b/src/nvim/tui/tui.h index 07523bc124..996496ee60 100644 --- a/src/nvim/tui/tui.h +++ b/src/nvim/tui/tui.h @@ -1,6 +1,9 @@ #ifndef NVIM_TUI_TUI_H #define NVIM_TUI_TUI_H +#include "nvim/cursor_shape.h" +#include "nvim/ui.h" + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "tui/tui.h.generated.h" #endif diff --git a/src/nvim/types.h b/src/nvim/types.h index 35a5d1e2bd..317bead3bb 100644 --- a/src/nvim/types.h +++ b/src/nvim/types.h @@ -14,4 +14,5 @@ typedef unsigned char char_u; typedef uint32_t u8char_T; typedef struct expand expand_T; + #endif // NVIM_TYPES_H diff --git a/src/nvim/ugrid.c b/src/nvim/ugrid.c index 127b18feb6..7a0a16687e 100644 --- a/src/nvim/ugrid.c +++ b/src/nvim/ugrid.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #include <assert.h> #include <stdbool.h> #include <stdio.h> diff --git a/src/nvim/ui.c b/src/nvim/ui.c index d3784b6cd3..b85a01814d 100644 --- a/src/nvim/ui.c +++ b/src/nvim/ui.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #include <assert.h> #include <inttypes.h> #include <stdbool.h> @@ -5,6 +8,7 @@ #include <limits.h> #include "nvim/vim.h" +#include "nvim/log.h" #include "nvim/ui.h" #include "nvim/charset.h" #include "nvim/cursor.h" @@ -29,6 +33,7 @@ #include "nvim/screen.h" #include "nvim/syntax.h" #include "nvim/window.h" +#include "nvim/cursor_shape.h" #ifdef FEAT_TUI # include "nvim/tui/tui.h" #else @@ -43,6 +48,7 @@ #define MAX_UI_COUNT 16 static UI *uis[MAX_UI_COUNT]; +static bool ui_ext[UI_WIDGETS] = { 0 }; static size_t ui_count = 0; static int row = 0, col = 0; static struct { @@ -52,6 +58,28 @@ static int current_attr_code = 0; static bool pending_cursor_update = false; static int busy = 0; static int height, width; +static int old_mode_idx = -1; + +#if MIN_LOG_LEVEL > DEBUG_LOG_LEVEL +# define UI_LOG(funname, ...) +#else +static size_t uilog_seen = 0; +static char uilog_last_event[1024] = { 0 }; +# define UI_LOG(funname, ...) \ + do { \ + if (strequal(uilog_last_event, STR(funname))) { \ + uilog_seen++; \ + } else { \ + if (uilog_seen > 0) { \ + do_log(DEBUG_LOG_LEVEL, "ui", 0, true, \ + "%s (+%zu times...)", uilog_last_event, uilog_seen); \ + } \ + DLOG("ui: " STR(funname)); \ + uilog_seen = 0; \ + xstrlcpy(uilog_last_event, STR(funname), sizeof(uilog_last_event)); \ + } \ + } while (0) +#endif // UI_CALL invokes a function on all registered UI instances. The functions can // have 0-5 arguments (configurable by SELECT_NTH). @@ -61,6 +89,7 @@ static int height, width; # define UI_CALL(funname, ...) \ do { \ flush_cursor_update(); \ + UI_LOG(funname, 0); \ for (size_t i = 0; i < ui_count; i++) { \ UI *ui = uis[i]; \ UI_CALL_MORE(funname, __VA_ARGS__); \ @@ -70,6 +99,7 @@ static int height, width; # define UI_CALL(...) \ do { \ flush_cursor_update(); \ + UI_LOG(__VA_ARGS__, 0); \ for (size_t i = 0; i < ui_count; i++) { \ UI *ui = uis[i]; \ UI_CALL_HELPER(CNT(__VA_ARGS__), __VA_ARGS__); \ @@ -79,10 +109,15 @@ static int height, width; #define CNT(...) SELECT_NTH(__VA_ARGS__, MORE, MORE, MORE, MORE, ZERO, ignore) #define SELECT_NTH(a1, a2, a3, a4, a5, a6, ...) a6 #define UI_CALL_HELPER(c, ...) UI_CALL_HELPER2(c, __VA_ARGS__) +// Resolves to UI_CALL_MORE or UI_CALL_ZERO. #define UI_CALL_HELPER2(c, ...) UI_CALL_##c(__VA_ARGS__) #define UI_CALL_MORE(method, ...) if (ui->method) ui->method(ui, __VA_ARGS__) #define UI_CALL_ZERO(method) if (ui->method) ui->method(ui) +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "ui_events_call.generated.h" +#endif + void ui_builtin_start(void) { #ifdef FEAT_TUI @@ -122,24 +157,6 @@ bool ui_active(void) return ui_count != 0; } -void ui_suspend(void) -{ - UI_CALL(suspend); - UI_CALL(flush); -} - -void ui_set_title(char *title) -{ - UI_CALL(set_title, title); - UI_CALL(flush); -} - -void ui_set_icon(char *icon) -{ - UI_CALL(set_icon, icon); - UI_CALL(flush); -} - void ui_event(char *name, Array args) { bool args_consumed = false; @@ -149,31 +166,45 @@ void ui_event(char *name, Array args) } } -// May update the shape of the cursor. -void ui_cursor_shape(void) -{ - ui_mode_change(); -} - void ui_refresh(void) { if (!ui_active()) { return; } + if (updating_screen) { + ui_schedule_refresh(); + return; + } + int width = INT_MAX, height = INT_MAX; - bool pum_external = true; + bool ext_widgets[UI_WIDGETS]; + for (UIWidget i = 0; (int)i < UI_WIDGETS; i++) { + ext_widgets[i] = true; + } for (size_t i = 0; i < ui_count; i++) { UI *ui = uis[i]; width = MIN(ui->width, width); height = MIN(ui->height, height); - pum_external &= ui->pum_external; + for (UIWidget i = 0; (int)i < UI_WIDGETS; i++) { + ext_widgets[i] &= ui->ui_ext[i]; + } } row = col = 0; + + int save_p_lz = p_lz; + p_lz = false; // convince redrawing() to return true ... screen_resize(width, height); - pum_set_external(pum_external); + p_lz = save_p_lz; + + for (UIWidget i = 0; (int)i < UI_WIDGETS; i++) { + ui_set_external(i, ext_widgets[i]); + } + ui_mode_info_set(); + old_mode_idx = -1; + ui_cursor_shape(); } static void ui_refresh_event(void **argv) @@ -183,7 +214,7 @@ static void ui_refresh_event(void **argv) void ui_schedule_refresh(void) { - loop_schedule(&main_loop, event_create(1, ui_refresh_event, 0)); + loop_schedule(&main_loop, event_create(ui_refresh_event, 0)); } void ui_resize(int new_width, int new_height) @@ -199,33 +230,23 @@ void ui_resize(int new_width, int new_height) sr.bot = height - 1; sr.left = 0; sr.right = width - 1; - UI_CALL(resize, width, height); + ui_call_resize(width, height); } void ui_busy_start(void) { if (!(busy++)) { - UI_CALL(busy_start); + ui_call_busy_start(); } } void ui_busy_stop(void) { if (!(--busy)) { - UI_CALL(busy_stop); + ui_call_busy_stop(); } } -void ui_mouse_on(void) -{ - UI_CALL(mouse_on); -} - -void ui_mouse_off(void) -{ - UI_CALL(mouse_off); -} - void ui_attach_impl(UI *ui) { if (ui_count == MAX_UI_COUNT) { @@ -258,16 +279,14 @@ void ui_detach_impl(UI *ui) shift_index++; } - if (--ui_count) { + if (--ui_count + // During teardown/exit the loop was already destroyed, cannot schedule. + // https://github.com/neovim/neovim/pull/5119#issuecomment-258667046 + && !exiting) { ui_schedule_refresh(); } } -void ui_clear(void) -{ - UI_CALL(clear); -} - // Set scrolling region for window 'wp'. // The region starts 'off' lines from the start of the window. // Also set the vertical scroll region for a vertically split window. Always @@ -282,7 +301,7 @@ void ui_set_scroll_region(win_T *wp, int off) sr.right = wp->w_wincol + wp->w_width - 1; } - UI_CALL(set_scroll_region, sr.top, sr.bot, sr.left, sr.right); + ui_call_set_scroll_region(sr.top, sr.bot, sr.left, sr.right); } // Reset scrolling region to the whole screen. @@ -292,22 +311,7 @@ void ui_reset_scroll_region(void) sr.bot = (int)Rows - 1; sr.left = 0; sr.right = (int)Columns - 1; - UI_CALL(set_scroll_region, sr.top, sr.bot, sr.left, sr.right); -} - -void ui_append_lines(int count) -{ - UI_CALL(scroll, -count); -} - -void ui_delete_lines(int count) -{ - UI_CALL(scroll, count); -} - -void ui_eol_clear(void) -{ - UI_CALL(eol_clear); + ui_call_set_scroll_region(sr.top, sr.bot, sr.left, sr.right); } void ui_start_highlight(int attr_code) @@ -332,23 +336,31 @@ void ui_stop_highlight(void) set_highlight_args(current_attr_code); } -void ui_visual_bell(void) -{ - UI_CALL(visual_bell); -} - void ui_puts(uint8_t *str) { - uint8_t *ptr = str; + uint8_t *p = str; uint8_t c; - while ((c = *ptr)) { + while ((c = *p)) { if (c < 0x20) { - parse_control_character(c); - ptr++; - } else { - send_output(&ptr); + abort(); + } + + size_t clen = (size_t)mb_ptr2len(p); + ui_call_put((String){ .data = (char *)p, .size = clen }); + col++; + if (mb_ptr2cells(p) > 1) { + // double cell character, blank the next cell + ui_call_put((String)STRING_INIT); + col++; + } + if (utf_ambiguous_width(utf_ptr2char(p))) { + pending_cursor_update = true; + } + if (col >= width) { + ui_linefeed(); } + p += clen; } } @@ -368,9 +380,12 @@ void ui_cursor_goto(int new_row, int new_col) pending_cursor_update = true; } -void ui_update_menu(void) +void ui_mode_info_set(void) { - UI_CALL(update_menu); + Array style = mode_style_array(); + bool enabled = (*p_guicursor != NUL); + ui_call_mode_info_set(enabled, style); + api_free_array(style); } int ui_current_row(void) @@ -385,47 +400,7 @@ int ui_current_col(void) void ui_flush(void) { - UI_CALL(flush); -} - -static void send_output(uint8_t **ptr) -{ - uint8_t *p = *ptr; - - while (*p >= 0x20) { - size_t clen = (size_t)mb_ptr2len(p); - UI_CALL(put, p, (size_t)clen); - col++; - if (mb_ptr2cells(p) > 1) { - // double cell character, blank the next cell - UI_CALL(put, NULL, 0); - col++; - } - if (utf_ambiguous_width(utf_ptr2char(p))) { - pending_cursor_update = true; - } - if (col >= width) { - ui_linefeed(); - } - p += clen; - } - - *ptr = p; -} - -static void parse_control_character(uint8_t c) -{ - if (c == '\n') { - ui_linefeed(); - } else if (c == '\r') { - ui_carriage_return(); - } else if (c == '\b') { - ui_cursor_left(); - } else if (c == Ctrl_L) { - ui_cursor_right(); - } else if (c == Ctrl_G) { - UI_CALL(bell); - } + ui_call_flush(); } static void set_highlight_args(int attr_code) @@ -483,65 +458,53 @@ end: UI_CALL(highlight_set, (ui->rgb ? rgb_attrs : cterm_attrs)); } -static void ui_linefeed(void) +void ui_linefeed(void) { int new_col = 0; int new_row = row; if (new_row < sr.bot) { new_row++; } else { - UI_CALL(scroll, 1); + ui_call_scroll(1); } ui_cursor_goto(new_row, new_col); } -static void ui_carriage_return(void) -{ - int new_col = 0; - ui_cursor_goto(row, new_col); -} - -static void ui_cursor_left(void) -{ - int new_col = col - 1; - assert(new_col >= 0); - ui_cursor_goto(row, new_col); -} - -static void ui_cursor_right(void) -{ - int new_col = col + 1; - assert(new_col < width); - ui_cursor_goto(row, new_col); -} - static void flush_cursor_update(void) { if (pending_cursor_update) { pending_cursor_update = false; - UI_CALL(cursor_goto, row, col); + ui_call_cursor_goto(row, col); } } -// Notify that the current mode has changed. Can be used to change cursor -// shape, for example. -static void ui_mode_change(void) +/// Check if current mode has changed. +/// May update the shape of the cursor. +void ui_cursor_shape(void) { - int mode; if (!full_screen) { return; } - // Get a simple UI mode out of State. - if ((State & REPLACE) == REPLACE) { - mode = REPLACE; - } else if (State & INSERT) { - mode = INSERT; - } else if (State & CMDLINE) { - mode = CMDLINE; - } else { - mode = NORMAL; + int mode_idx = cursor_get_mode_idx(); + + if (old_mode_idx != mode_idx) { + old_mode_idx = mode_idx; + char *full_name = shape_table[mode_idx].full_name; + ui_call_mode_change(cstr_as_string(full_name), mode_idx); } - UI_CALL(mode_change, mode); conceal_check_cursur_line(); } +/// Returns true if `widget` is externalized. +bool ui_is_external(UIWidget widget) +{ + return ui_ext[widget]; +} + +/// Sets `widget` as "external". +/// Such widgets are not drawn by Nvim; external UIs are expected to handle +/// higher-level UI events and present the data. +void ui_set_external(UIWidget widget, bool external) +{ + ui_ext[widget] = external; +} diff --git a/src/nvim/ui.h b/src/nvim/ui.h index d14bc5812c..064f77fee1 100644 --- a/src/nvim/ui.h +++ b/src/nvim/ui.h @@ -6,6 +6,15 @@ #include <stdint.h> #include "api/private/defs.h" +#include "nvim/buffer_defs.h" + +typedef enum { + kUICmdline = 0, + kUIPopupmenu, + kUITabline, + kUIWildmenu, +} UIWidget; +#define UI_WIDGETS (kUIWildmenu + 1) typedef struct { bool bold, underline, undercurl, italic, reverse; @@ -15,37 +24,21 @@ typedef struct { typedef struct ui_t UI; struct ui_t { - bool rgb, pum_external; + bool rgb; + bool ui_ext[UI_WIDGETS]; ///< Externalized widgets int width, height; void *data; - void (*resize)(UI *ui, int rows, int columns); - void (*clear)(UI *ui); - void (*eol_clear)(UI *ui); - void (*cursor_goto)(UI *ui, int row, int col); - void (*update_menu)(UI *ui); - void (*busy_start)(UI *ui); - void (*busy_stop)(UI *ui); - void (*mouse_on)(UI *ui); - void (*mouse_off)(UI *ui); - void (*mode_change)(UI *ui, int mode); - void (*set_scroll_region)(UI *ui, int top, int bot, int left, int right); - void (*scroll)(UI *ui, int count); - void (*highlight_set)(UI *ui, HlAttrs attrs); - void (*put)(UI *ui, uint8_t *str, size_t len); - void (*bell)(UI *ui); - void (*visual_bell)(UI *ui); - void (*flush)(UI *ui); - void (*update_fg)(UI *ui, int fg); - void (*update_bg)(UI *ui, int bg); - void (*update_sp)(UI *ui, int sp); - void (*suspend)(UI *ui); - void (*set_title)(UI *ui, char *title); - void (*set_icon)(UI *ui, char *icon); + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "ui_events.generated.h" +#endif + void (*event)(UI *ui, char *name, Array args, bool *args_consumed); void (*stop)(UI *ui); }; #ifdef INCLUDE_GENERATED_DECLARATIONS # include "ui.h.generated.h" +# include "ui_events_call.h.generated.h" #endif #endif // NVIM_UI_H diff --git a/src/nvim/ui_bridge.c b/src/nvim/ui_bridge.c index 25861abc1b..5585886612 100644 --- a/src/nvim/ui_bridge.c +++ b/src/nvim/ui_bridge.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + // UI wrapper that sends requests to the UI thread. // Used by the built-in TUI and libnvim-based UIs. @@ -13,6 +16,7 @@ #include "nvim/memory.h" #include "nvim/ui_bridge.h" #include "nvim/ugrid.h" +#include "nvim/api/private/helpers.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "ui_bridge.c.generated.h" @@ -20,45 +24,29 @@ #define UI(b) (((UIBridgeData *)b)->ui) -#if MIN_LOG_LEVEL <= DEBUG_LOG_LEVEL -static size_t uilog_seen = 0; -static argv_callback uilog_event = NULL; -#define UI_CALL(ui, name, argc, ...) \ - do { \ - if (uilog_event == ui_bridge_##name##_event) { \ - uilog_seen++; \ - } else { \ - if (uilog_seen > 0) { \ - DLOG("UI bridge: ...%zu times", uilog_seen); \ - } \ - DLOG("UI bridge: " STR(name)); \ - uilog_seen = 0; \ - uilog_event = ui_bridge_##name##_event; \ - } \ - ((UIBridgeData *)ui)->scheduler( \ - event_create(1, ui_bridge_##name##_event, argc, __VA_ARGS__), UI(ui)); \ - } while (0) -#else // Schedule a function call on the UI bridge thread. -#define UI_CALL(ui, name, argc, ...) \ +#define UI_BRIDGE_CALL(ui, name, argc, ...) \ ((UIBridgeData *)ui)->scheduler( \ - event_create(1, ui_bridge_##name##_event, argc, __VA_ARGS__), UI(ui)) -#endif + event_create(ui_bridge_##name##_event, argc, __VA_ARGS__), UI(ui)) + +#define INT2PTR(i) ((void *)(intptr_t)i) +#define PTR2INT(p) ((Integer)(intptr_t)p) -#define INT2PTR(i) ((void *)(uintptr_t)i) -#define PTR2INT(p) ((int)(uintptr_t)p) +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "ui_events_bridge.generated.h" +#endif UI *ui_bridge_attach(UI *ui, ui_main_fn ui_main, event_scheduler scheduler) { UIBridgeData *rv = xcalloc(1, sizeof(UIBridgeData)); rv->ui = ui; rv->bridge.rgb = ui->rgb; - rv->bridge.pum_external = ui->pum_external; rv->bridge.stop = ui_bridge_stop; rv->bridge.resize = ui_bridge_resize; rv->bridge.clear = ui_bridge_clear; rv->bridge.eol_clear = ui_bridge_eol_clear; rv->bridge.cursor_goto = ui_bridge_cursor_goto; + rv->bridge.mode_info_set = ui_bridge_mode_info_set; rv->bridge.update_menu = ui_bridge_update_menu; rv->bridge.busy_start = ui_bridge_busy_start; rv->bridge.busy_stop = ui_bridge_busy_stop; @@ -80,6 +68,10 @@ UI *ui_bridge_attach(UI *ui, ui_main_fn ui_main, event_scheduler scheduler) rv->bridge.set_icon = ui_bridge_set_icon; rv->scheduler = scheduler; + for (UIWidget i = 0; (int)i < UI_WIDGETS; i++) { + rv->bridge.ui_ext[i] = ui->ui_ext[i]; + } + rv->ui_main = ui_main; uv_mutex_init(&rv->mutex); uv_cond_init(&rv->cond); @@ -116,7 +108,7 @@ static void ui_bridge_stop(UI *b) { UIBridgeData *bridge = (UIBridgeData *)b; bool stopped = bridge->stopped = false; - UI_CALL(b, stop, 1, b); + UI_BRIDGE_CALL(b, stop, 1, b); for (;;) { uv_mutex_lock(&bridge->mutex); stopped = bridge->stopped; @@ -138,134 +130,11 @@ static void ui_bridge_stop_event(void **argv) ui->stop(ui); } -static void ui_bridge_resize(UI *b, int width, int height) -{ - UI_CALL(b, resize, 3, b, INT2PTR(width), INT2PTR(height)); -} -static void ui_bridge_resize_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->resize(ui, PTR2INT(argv[1]), PTR2INT(argv[2])); -} - -static void ui_bridge_clear(UI *b) -{ - UI_CALL(b, clear, 1, b); -} -static void ui_bridge_clear_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->clear(ui); -} - -static void ui_bridge_eol_clear(UI *b) -{ - UI_CALL(b, eol_clear, 1, b); -} -static void ui_bridge_eol_clear_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->eol_clear(ui); -} - -static void ui_bridge_cursor_goto(UI *b, int row, int col) -{ - UI_CALL(b, cursor_goto, 3, b, INT2PTR(row), INT2PTR(col)); -} -static void ui_bridge_cursor_goto_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->cursor_goto(ui, PTR2INT(argv[1]), PTR2INT(argv[2])); -} - -static void ui_bridge_update_menu(UI *b) -{ - UI_CALL(b, update_menu, 1, b); -} -static void ui_bridge_update_menu_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->update_menu(ui); -} - -static void ui_bridge_busy_start(UI *b) -{ - UI_CALL(b, busy_start, 1, b); -} -static void ui_bridge_busy_start_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->busy_start(ui); -} - -static void ui_bridge_busy_stop(UI *b) -{ - UI_CALL(b, busy_stop, 1, b); -} -static void ui_bridge_busy_stop_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->busy_stop(ui); -} - -static void ui_bridge_mouse_on(UI *b) -{ - UI_CALL(b, mouse_on, 1, b); -} -static void ui_bridge_mouse_on_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->mouse_on(ui); -} - -static void ui_bridge_mouse_off(UI *b) -{ - UI_CALL(b, mouse_off, 1, b); -} -static void ui_bridge_mouse_off_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->mouse_off(ui); -} - -static void ui_bridge_mode_change(UI *b, int mode) -{ - UI_CALL(b, mode_change, 2, b, INT2PTR(mode)); -} -static void ui_bridge_mode_change_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->mode_change(ui, PTR2INT(argv[1])); -} - -static void ui_bridge_set_scroll_region(UI *b, int top, int bot, int left, - int right) -{ - UI_CALL(b, set_scroll_region, 5, b, INT2PTR(top), INT2PTR(bot), - INT2PTR(left), INT2PTR(right)); -} -static void ui_bridge_set_scroll_region_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->set_scroll_region(ui, PTR2INT(argv[1]), PTR2INT(argv[2]), - PTR2INT(argv[3]), PTR2INT(argv[4])); -} - -static void ui_bridge_scroll(UI *b, int count) -{ - UI_CALL(b, scroll, 2, b, INT2PTR(count)); -} -static void ui_bridge_scroll_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->scroll(ui, PTR2INT(argv[1])); -} - static void ui_bridge_highlight_set(UI *b, HlAttrs attrs) { HlAttrs *a = xmalloc(sizeof(HlAttrs)); *a = attrs; - UI_CALL(b, highlight_set, 2, b, a); + UI_BRIDGE_CALL(b, highlight_set, 2, b, a); } static void ui_bridge_highlight_set_event(void **argv) { @@ -274,87 +143,11 @@ static void ui_bridge_highlight_set_event(void **argv) xfree(argv[1]); } -static void ui_bridge_put(UI *b, uint8_t *text, size_t size) -{ - uint8_t *t = NULL; - if (text) { - t = xmalloc(sizeof(((UCell *)0)->data)); - memcpy(t, text, size); - } - UI_CALL(b, put, 3, b, t, INT2PTR(size)); -} -static void ui_bridge_put_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->put(ui, (uint8_t *)argv[1], (size_t)(uintptr_t)argv[2]); - xfree(argv[1]); -} - -static void ui_bridge_bell(UI *b) -{ - UI_CALL(b, bell, 1, b); -} -static void ui_bridge_bell_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->bell(ui); -} - -static void ui_bridge_visual_bell(UI *b) -{ - UI_CALL(b, visual_bell, 1, b); -} -static void ui_bridge_visual_bell_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->visual_bell(ui); -} - -static void ui_bridge_update_fg(UI *b, int fg) -{ - UI_CALL(b, update_fg, 2, b, INT2PTR(fg)); -} -static void ui_bridge_update_fg_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->update_fg(ui, PTR2INT(argv[1])); -} - -static void ui_bridge_update_bg(UI *b, int bg) -{ - UI_CALL(b, update_bg, 2, b, INT2PTR(bg)); -} -static void ui_bridge_update_bg_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->update_bg(ui, PTR2INT(argv[1])); -} - -static void ui_bridge_update_sp(UI *b, int sp) -{ - UI_CALL(b, update_sp, 2, b, INT2PTR(sp)); -} -static void ui_bridge_update_sp_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->update_sp(ui, PTR2INT(argv[1])); -} - -static void ui_bridge_flush(UI *b) -{ - UI_CALL(b, flush, 1, b); -} -static void ui_bridge_flush_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->flush(ui); -} - static void ui_bridge_suspend(UI *b) { UIBridgeData *data = (UIBridgeData *)b; uv_mutex_lock(&data->mutex); - UI_CALL(b, suspend, 1, b); + UI_BRIDGE_CALL(b, suspend, 1, b); data->ready = false; // suspend the main thread until CONTINUE is called by the UI thread while (!data->ready) { @@ -367,25 +160,3 @@ static void ui_bridge_suspend_event(void **argv) UI *ui = UI(argv[0]); ui->suspend(ui); } - -static void ui_bridge_set_title(UI *b, char *title) -{ - UI_CALL(b, set_title, 2, b, title ? xstrdup(title) : NULL); -} -static void ui_bridge_set_title_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->set_title(ui, argv[1]); - xfree(argv[1]); -} - -static void ui_bridge_set_icon(UI *b, char *icon) -{ - UI_CALL(b, set_icon, 2, b, icon ? xstrdup(icon) : NULL); -} -static void ui_bridge_set_icon_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->set_icon(ui, argv[1]); - xfree(argv[1]); -} diff --git a/src/nvim/undo.c b/src/nvim/undo.c index 4d56046bc1..3d7ebc8837 100644 --- a/src/nvim/undo.c +++ b/src/nvim/undo.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + /* * undo.c: multi level undo facility * @@ -76,12 +79,14 @@ #include <inttypes.h> #include <limits.h> #include <stdbool.h> +#include <stdint.h> #include <string.h> #include <fcntl.h> #include "nvim/vim.h" #include "nvim/ascii.h" #include "nvim/undo.h" +#include "nvim/macros.h" #include "nvim/cursor.h" #include "nvim/edit.h" #include "nvim/eval.h" @@ -305,23 +310,19 @@ bool undo_allowed(void) return true; } -/* - * Get the undolevle value for the current buffer. - */ +/// Get the 'undolevels' value for the current buffer. static long get_undolevel(void) { - if (curbuf->terminal) { - return -1; - } - if (curbuf->b_p_ul == NO_LOCAL_UNDOLEVEL) + if (curbuf->b_p_ul == NO_LOCAL_UNDOLEVEL) { return p_ul; + } return curbuf->b_p_ul; } static inline void zero_fmark_additional_data(fmark_T *fmarks) { for (size_t i = 0; i < NMARKS; i++) { - dict_unref(fmarks[i].additional_data); + tv_dict_unref(fmarks[i].additional_data); fmarks[i].additional_data = NULL; } } @@ -969,12 +970,12 @@ static u_entry_T *unserialize_uep(bufinfo_T * bi, bool *error, uep->ue_lcount = undo_read_4c(bi); uep->ue_size = undo_read_4c(bi); - char_u **array; + char_u **array = NULL; if (uep->ue_size > 0) { - array = xmalloc(sizeof(char_u *) * (size_t)uep->ue_size); - memset(array, 0, sizeof(char_u *) * (size_t)uep->ue_size); - } else { - array = NULL; + if ((size_t)uep->ue_size < SIZE_MAX / sizeof(char_u *)) { + array = xmalloc(sizeof(char_u *) * (size_t)uep->ue_size); + memset(array, 0, sizeof(char_u *) * (size_t)uep->ue_size); + } } uep->ue_array = array; @@ -1084,7 +1085,7 @@ void u_write_undo(const char *const name, const bool forceit, buf_T *const buf, */ perm = 0600; if (buf->b_ffname != NULL) { - perm = os_getperm(buf->b_ffname); + perm = os_getperm((const char *)buf->b_ffname); if (perm < 0) { perm = 0600; } @@ -1143,7 +1144,7 @@ void u_write_undo(const char *const name, const bool forceit, buf_T *const buf, EMSG2(_(e_not_open), file_name); goto theend; } - (void)os_setperm((char_u *)file_name, perm); + (void)os_setperm(file_name, perm); if (p_verbose > 0) { verbose_enter(); smsg(_("Writing undo file: %s"), file_name); @@ -1168,7 +1169,7 @@ void u_write_undo(const char *const name, const bool forceit, buf_T *const buf, && os_fileinfo(file_name, &file_info_new) && file_info_old.stat.st_gid != file_info_new.stat.st_gid && os_fchown(fd, (uv_uid_t)-1, (uv_gid_t)file_info_old.stat.st_gid)) { - os_setperm((char_u *)file_name, (perm & 0707) | ((perm & 07) << 3)); + os_setperm(file_name, (perm & 0707) | ((perm & 07) << 3)); } # ifdef HAVE_SELINUX if (buf->b_ffname != NULL) @@ -1403,7 +1404,9 @@ void u_read_undo(char *name, char_u *hash, char_u *orig_name) // sequence numbers of the headers. // When there are no headers uhp_table is NULL. if (num_head > 0) { - uhp_table = xmalloc((size_t)num_head * sizeof(u_header_T *)); + if ((size_t)num_head < SIZE_MAX / sizeof(*uhp_table)) { + uhp_table = xmalloc((size_t)num_head * sizeof(*uhp_table)); + } } long num_read_uhps = 0; @@ -1710,7 +1713,8 @@ bool u_undo_and_forget(int count) if (curbuf->b_u_curhead) { to_forget->uh_alt_next.ptr = NULL; curbuf->b_u_curhead->uh_alt_prev.ptr = to_forget->uh_alt_prev.ptr; - curbuf->b_u_seq_cur = curbuf->b_u_curhead->uh_seq-1; + curbuf->b_u_seq_cur = curbuf->b_u_curhead->uh_next.ptr ? + curbuf->b_u_curhead->uh_next.ptr->uh_seq : 0; } else if (curbuf->b_u_newhead) { curbuf->b_u_seq_cur = curbuf->b_u_newhead->uh_seq; } @@ -1834,11 +1838,9 @@ void undo_time(long step, int sec, int file, int absolute) } closest = -1; } else { - /* When doing computations with time_t subtract starttime, because - * time_t converted to a long may result in a wrong number. */ - if (dosec) - target = (long)(curbuf->b_u_time_cur - starttime) + step; - else if (dofile) { + if (dosec) { + target = (long)(curbuf->b_u_time_cur) + step; + } else if (dofile) { if (step < 0) { /* Going back to a previous write. If there were changes after * the last write, count that as moving one file-write, so @@ -1876,14 +1878,16 @@ void undo_time(long step, int sec, int file, int absolute) target = 0; closest = -1; } else { - if (dosec) - closest = (long)(time(NULL) - starttime + 1); - else if (dofile) + if (dosec) { + closest = (long)(os_time() + 1); + } else if (dofile) { closest = curbuf->b_u_save_nr_last + 2; - else + } else { closest = curbuf->b_u_seq_last + 2; - if (target >= closest) + } + if (target >= closest) { target = closest - 1; + } } } closest_start = closest; @@ -1912,12 +1916,13 @@ void undo_time(long step, int sec, int file, int absolute) while (uhp != NULL) { uhp->uh_walk = mark; - if (dosec) - val = (long)(uhp->uh_time - starttime); - else if (dofile) + if (dosec) { + val = (long)(uhp->uh_time); + } else if (dofile) { val = uhp->uh_save_nr; - else + } else { val = uhp->uh_seq; + } if (round == 1 && !(dofile && val == 0)) { /* Remember the header that is closest to the target. @@ -2228,11 +2233,13 @@ static void u_undoredo(int undo) /* adjust marks */ if (oldsize != newsize) { mark_adjust(top + 1, top + oldsize, (long)MAXLNUM, - (long)newsize - (long)oldsize); - if (curbuf->b_op_start.lnum > top + oldsize) + (long)newsize - (long)oldsize, false); + if (curbuf->b_op_start.lnum > top + oldsize) { curbuf->b_op_start.lnum += newsize - oldsize; - if (curbuf->b_op_end.lnum > top + oldsize) + } + if (curbuf->b_op_end.lnum > top + oldsize) { curbuf->b_op_end.lnum += newsize - oldsize; + } } changed_lines(top + 1, 0, bot, newsize - oldsize); @@ -2321,7 +2328,8 @@ static void u_undoredo(int undo) if (undo) /* We are below the previous undo. However, to make ":earlier 1s" * work we compute this as being just above the just undone change. */ - --curbuf->b_u_seq_cur; + curbuf->b_u_seq_cur = curhead->uh_next.ptr ? + curhead->uh_next.ptr->uh_seq : 0; /* Remember where we are for ":earlier 1f" and ":later 1f". */ if (curhead->uh_save_nr != 0) { @@ -2510,13 +2518,14 @@ void ex_undolist(exarg_T *eap) sort_strings((char_u **)ga.ga_data, ga.ga_len); msg_start(); - msg_puts_attr((char_u *)_("number changes when saved"), - hl_attr(HLF_T)); - for (int i = 0; i < ga.ga_len && !got_int; ++i) { + msg_puts_attr(_("number changes when saved"), + hl_attr(HLF_T)); + for (int i = 0; i < ga.ga_len && !got_int; i++) { msg_putchar('\n'); - if (got_int) + if (got_int) { break; - msg_puts(((char_u **)ga.ga_data)[i]); + } + msg_puts(((const char **)ga.ga_data)[i]); } msg_end(); @@ -2549,20 +2558,20 @@ static void u_add_time(char_u *buf, size_t buflen, time_t tt) */ void ex_undojoin(exarg_T *eap) { - if (curbuf->b_u_newhead == NULL) - return; /* nothing changed before */ + if (curbuf->b_u_newhead == NULL) { + return; // nothing changed before + } if (curbuf->b_u_curhead != NULL) { EMSG(_("E790: undojoin is not allowed after undo")); return; } - if (!curbuf->b_u_synced) - return; /* already unsynced */ - if (get_undolevel() < 0) - return; /* no entries, nothing to do */ - else { - /* Go back to the last entry */ - curbuf->b_u_curhead = curbuf->b_u_newhead; - curbuf->b_u_synced = false; /* no entries, nothing to do */ + if (!curbuf->b_u_synced) { + return; // already unsynced + } + if (get_undolevel() < 0) { + return; // no entries, nothing to do + } else { + curbuf->b_u_synced = false; // Append next change to last entry } } @@ -2942,25 +2951,28 @@ void u_eval_tree(u_header_T *first_uhp, list_T *list) dict_T *dict; while (uhp != NULL) { - dict = dict_alloc(); - dict_add_nr_str(dict, "seq", uhp->uh_seq, NULL); - dict_add_nr_str(dict, "time", (long)uhp->uh_time, NULL); - if (uhp == curbuf->b_u_newhead) - dict_add_nr_str(dict, "newhead", 1, NULL); - if (uhp == curbuf->b_u_curhead) - dict_add_nr_str(dict, "curhead", 1, NULL); - if (uhp->uh_save_nr > 0) - dict_add_nr_str(dict, "save", uhp->uh_save_nr, NULL); + dict = tv_dict_alloc(); + tv_dict_add_nr(dict, S_LEN("seq"), (varnumber_T)uhp->uh_seq); + tv_dict_add_nr(dict, S_LEN("time"), (varnumber_T)uhp->uh_time); + if (uhp == curbuf->b_u_newhead) { + tv_dict_add_nr(dict, S_LEN("newhead"), 1); + } + if (uhp == curbuf->b_u_curhead) { + tv_dict_add_nr(dict, S_LEN("curhead"), 1); + } + if (uhp->uh_save_nr > 0) { + tv_dict_add_nr(dict, S_LEN("save"), (varnumber_T)uhp->uh_save_nr); + } if (uhp->uh_alt_next.ptr != NULL) { - list_T *alt_list = list_alloc(); + list_T *alt_list = tv_list_alloc(); - /* Recursive call to add alternate undo tree. */ + // Recursive call to add alternate undo tree. u_eval_tree(uhp->uh_alt_next.ptr, alt_list); - dict_add_list(dict, "alt", alt_list); + tv_dict_add_list(dict, S_LEN("alt"), alt_list); } - list_append_dict(list, dict); + tv_list_append_dict(list, dict); uhp = uhp->uh_prev.ptr; } } diff --git a/src/nvim/version.c b/src/nvim/version.c index 3e9cccda20..6e24e30a09 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + /// @file version.c /// /// Nvim was forked from Vim 7.4.160. @@ -25,8 +28,9 @@ // 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 +#define NVIM_VERSION_MEDIUM "v" STR(NVIM_VERSION_MAJOR)\ + "." STR(NVIM_VERSION_MINOR) "." STR(NVIM_VERSION_PATCH)\ + NVIM_VERSION_PRERELEASE #endif #define NVIM_VERSION_LONG "NVIM " NVIM_VERSION_MEDIUM @@ -72,2371 +76,878 @@ static char *features[] = { }; // clang-format off -static int included_patches[] = { - // 2367, - // 2366 NA - // 2365 NA - // 2364, - // 2363 NA - // 2362, - // 2361 NA - // 2360, - // 2359 NA - // 2358 NA - // 2357, - // 2356, - // 2355, - // 2354, - // 2353, - // 2352 NA - // 2351 NA - // 2350, - // 2349, - // 2348, - // 2347, - // 2346, - // 2345 NA - // 2344 NA - // 2343, - // 2342 NA - // 2341, - // 2340 NA - // 2339, - // 2338 NA - 2337, - // 2336, - 2335, - // 2334, - // 2333, - // 2332 NA - 2331, - // 2330, - // 2329, - // 2328, - // 2327 NA - // 2326, - // 2325 NA - // 2324, - // 2323, - // 2322, - 2321, - // 2320, - // 2319 NA - // 2318, - // 2317, - // 2316 NA - // 2315, - // 2314, - // 2313, - 2312, - // 2311 NA - // 2310 NA - 2309, - // 2308 NA - // 2307, - // 2306, - // 2305, - // 2304 NA - // 2303, - // 2302 NA - // 2301 NA - // 2300, - // 2299, - // 2298 NA - // 2297 NA - // 2296, - // 2295, - 2294, - // 2293, - // 2292, - // 2291, - // 2290 NA - // 2289 NA - // 2288 NA - // 2287 NA - // 2286 NA - // 2285 NA - 2284, - // 2283, - // 2282 NA - // 2281 NA - // 2280, - // 2279, - // 2278 NA - 2277, - // 2276, - // 2275, - 2274, - 2273, - 2272, - // 2271 NA - // 2270 NA - // 2269, - // 2268, - // 2267 NA - // 2266, - // 2265, - // 2264, - // 2263, - // 2262 NA - // 2261 NA - // 2260 NA - // 2259, - // 2258 NA - // 2257 NA - // 2256, - // 2255, - // 2254 NA - // 2253 NA - // 2252 NA - 2251, - // 2250, - // 2249, - // 2248, - // 2247 NA - // 2246, - // 2245, - // 2244, - // 2243 NA - // 2242, - // 2241, - // 2240, - // 2239, - // 2238 NA - 2237, - // 2236, - // 2235, - // 2234 NA - // 2233, - // 2232 NA - // 2231, - // 2230, - // 2229, - // 2228, - 2227, - 2226, - 2225, - // 2224, - // 2223, - // 2222, - // 2221, - // 2220, - 2219, - // 2218 NA - 2217, - // 2216 NA - 2215, - // 2214 NA - 2213, - 2212, - // 2211 NA - // 2210 NA - // 2209, - // 2208, - // 2207 NA - // 2206 NA - 2205, - 2204, - // 2203 NA - // 2202 NA - 2201, - // 2200, - // 2199 NA - // 2198 NA - // 2197, - // 2196, - // 2195 NA - 2194, - // 2193 NA - // 2192 NA - // 2191 NA - // 2190, - // 2189, - 2188, - // 2187, - // 2186 NA - // 2185, - // 2184, - 2183, - // 2182 NA - // 2181, - // 2180, - // 2179, - // 2178, - // 2177, - // 2176 NA - // 2175, - 2174, - // 2173, - // 2172, - // 2171, - // 2170, - // 2169, - // 2168 NA - // 2167 NA - // 2166 NA - // 2165, - // 2164, - 2163, - 2162, - // 2161, - // 2160, - // 2159, - 2158, - // 2157 NA - // 2156 NA - // 2155 NA - // 2154 NA - // 2153 NA - // 2152, - // 2151, - // 2150 NA - 2149, - // 2148, - 2147, - 2146, - // 2145 NA - // 2144, - // 2143, - // 2142, - // 2141, - // 2140 NA - // 2139, - // 2138 NA - // 2137, - // 2136, - // 2135, - // 2134, - // 2133 NA - // 2132 NA - // 2131 NA - // 2130 NA - // 2129 NA - 2128, - 2127, - 2126, - // 2125 NA - 2124, - 2123, - // 2122 NA - // 2121, - // 2120, - // 2119, - // 2118 NA - // 2117, - // 2116 NA - // 2115 NA - // 2114 NA - // 2113, - 2112, - // 2111, - 2110, - 2109, - // 2108 NA - // 2107, - // 2106, - // 2105 NA - // 2104, - 2103, - // 2102 NA - // 2101, - 2100, - // 2099, - // 2098, - // 2097, - // 2096, - // 2095, - // 2094 NA - // 2093 NA - // 2092 NA - // 2091 NA - // 2090, - // 2089 NA - // 2088, - // 2087, - 2086, - // 2085, - // 2084, - // 2083, - // 2082, - // 2081, - // 2080, - // 2079 NA - // 2078 NA - // 2077, - // 2076, - // 2075, - // 2074, - // 2073 NA - // 2072, - 2071, - // 2070 NA - // 2069, - // 2068, - // 2067, - 2066, - // 2065, - // 2064, - // 2063 NA - // 2062, - // 2061, - // 2060 NA - // 2059 NA - // 2058, - // 2057 NA - // 2056 NA - // 2055 NA - // 2054 NA - // 2053 NA - // 2052 NA - // 2051, - // 2050, - // 2049, - // 2048 NA - // 2047, - // 2046, - // 2045 NA - // 2044, - 2043, - // 2042 NA - // 2041 NA - // 2040 NA - // 2039 NA - // 2038 NA - // 2037 NA - // 2036, - // 2035 NA - // 2034 NA - 2033, - // 2032 NA - // 2031, - // 2030 NA - // 2029, - 2028, - // 2027 NA - // 2026 NA - // 2025 NA - // 2024, - // 2023, - // 2022, - // 2021, - // 2020 NA - 2019, - // 2018, - // 2017, - // 2016 NA - 2015, - 2014, - 2013, - 2012, - 2011, - 2010, - 2009, - 2008, - 2007, - // 2006, - 2005, - // 2004 NA - // 2003 NA - // 2002, - // 2001 NA - 2000, - 1999, - // 1998 NA - 1997, - 1996, - // 1995 NA - // 1994, - // 1993, - // 1992, - // 1991, - 1990, - // 1989, - // 1988 NA - // 1987 NA - // 1986, - // 1985 NA - 1984, - // 1983 NA - // 1982 NA - // 1981, - 1980, - // 1979, - // 1978, - // 1977, - // 1976, - // 1975, - // 1974 NA - 1973, - // 1972 NA - 1971, - 1970, - // 1969 NA - // 1968, - 1967, - 1966, - // 1965 NA - 1964, - // 1963 NA - // 1962, - 1961, - 1960, - // 1959 NA - // 1958 NA - // 1957 NA - 1956, - // 1955 NA - // 1954, - 1953, - 1952, - // 1951 NA - 1950, - 1949, - // 1948, - // 1947 NA - // 1946 NA - // 1945 NA - // 1944 NA - // 1943 NA - // 1942 NA - 1941, - 1940, - // 1939 NA - // 1938 NA - 1937, - // 1936 NA - // 1935 NA - // 1934 NA - // 1933 NA - // 1932 NA - // 1931 NA - // 1930 NA - // 1929 NA - 1928, - // 1927 NA - // 1926 NA - 1925, - // 1924 NA - 1923, - // 1922 NA - // 1921 NA - // 1920 NA - // 1919 NA - // 1918 NA - // 1917 NA - // 1916 NA - // 1915 NA - // 1914, - 1913, - 1912, - // 1911 NA - // 1910, - 1909, - // 1908 NA - // 1907 NA - // 1906 NA - // 1905 NA - // 1904 NA - // 1903 NA - // 1902 NA - // 1901 NA - 1900, - // 1899 NA - 1898, - 1897, - 1896, - 1895, - 1894, - 1893, - 1892, - // 1891 NA - // 1890 NA - 1889, - // 1888 NA - // 1887 NA - // 1886 NA - // 1885 NA - 1884, - // 1883 NA - 1882, - 1881, - // 1880 NA - // 1879 NA - // 1878 NA - // 1877 NA - 1876, - 1875, - // 1874 NA - // 1873 NA - // 1872 NA - 1871, - // 1870 NA - // 1869 NA - 1868, - 1867, - 1866, - // 1865 NA - // 1864 NA - // 1863 NA - // 1862 NA - 1861, - 1860, - // 1859 NA - // 1858 NA - // 1857 NA - // 1856 NA - // 1855 NA - // 1854 NA - // 1853 NA - // 1852 NA - // 1851, - // 1850 NA - // 1849 NA - // 1848 NA - 1847, - // 1846 NA - // 1845 NA - // 1844 NA - // 1843 NA - 1842, - 1841, - 1840, - 1839, - 1838, - 1837, - 1836, - 1835, - 1834, - 1833, - 1832, - 1831, - // 1830 NA - // 1829 NA - // 1828 NA - // 1827 NA - // 1826 NA - // 1825 NA - // 1824 NA - 1823, - // 1822 NA - 1821, - 1820, - // 1819 NA - 1818, - // 1817 NA - 1816, - 1815, - // 1814 NA - 1813, - // 1812 NA - // 1811 NA - // 1810 NA - 1809, - 1808, - // 1807 NA - 1806, - // 1805 NA - // 1804 NA - // 1803 NA - 1802, - // 1801 NA - // 1800 NA - 1799, - // 1798 NA - // 1797 NA - // 1796 NA - // 1795 NA - // 1794 NA - 1793, - // 1792 NA - // 1791 NA - // 1790 NA - // 1789 NA - // 1789 NA - // 1788 NA - // 1787 NA - // 1786 NA - 1785, - // 1784 NA - 1783, - 1782, - 1781, - 1780, - 1779, - // 1778 NA - // 1777 NA - // 1776 NA - // 1775 NA - // 1774 NA - // 1773 NA - // 1772 NA - // 1771 NA - // 1770 NA - // 1769 NA - 1768, - // 1767 NA - // 1766 NA - 1765, - // 1764 NA - 1763, - // 1762 NA - // 1761 NA - // 1760 NA - 1759, - 1758, - 1757, - // 1756 NA - 1755, - 1754, - 1753, - 1752, - 1751, - // 1750 NA - // 1749 NA - 1748, - // 1747 NA - // 1746 NA - // 1745 NA - // 1744 NA - // 1743 NA - 1742, - 1741, - 1740, - 1739, - 1738, - // 1737 NA - // 1736 NA - 1735, - 1734, - // 1733 NA - 1732, - // 1731 NA - 1730, - // 1729 NA - 1728, - // 1727 NA - // 1726 NA - // 1725 NA - // 1724 NA - 1723, - // 1722 NA - // 1721 NA - // 1720 NA - 1719, - 1718, - // 1717 NA - 1716, - 1715, - 1714, - // 1713 NA - 1712, - 1711, - // 1710 NA - // 1709 NA - 1708, - 1707, - // 1706 NA - // 1705 NA - 1704, - 1703, - 1702, - 1701, - 1700, - 1699, - // 1698 NA - 1697, - 1696, - 1695, - // 1694 NA - // 1693 NA - 1692, - 1691, - // 1690 NA - // 1689 NA - // 1688 NA - // 1687 NA - 1686, - 1685, - // 1684 NA - // 1683 NA - 1682, - 1681, - // 1680 NA - 1679, - // 1678 NA - // 1677 NA - 1676, - 1675, - // 1674 NA - 1673, - // 1672 NA - 1671, - 1670, - // 1669 NA - // 1668 NA - // 1667 NA - // 1666 NA - // 1665 NA - 1664, - 1663, - // 1662 NA - // 1661 NA - 1660, - // 1659 NA - 1658, - // 1657 NA - 1656, - // 1655 NA - 1654, - // 1653 NA - 1652, - // 1651 NA - 1650, - 1649, - 1648, - 1647, - // 1646 NA - 1645, - // 1644 NA - 1643, - 1642, - 1641, - 1640, - 1639, - 1638, - // 1637 NA - // 1636 NA - // 1635 NA - 1634, - // 1633 NA - // 1632 NA - // 1631 NA - 1630, - 1629, - // 1628 NA - // 1627 NA - // 1626 NA - // 1625 NA - // 1624 NA - // 1623 NA - // 1622 NA - // 1621 NA - 1620, - 1619, - // 1618 NA - // 1617 NA - // 1616 NA - // 1615 NA - 1614, - // 1613 NA - // 1612 NA - // 1611 NA - // 1610 NA - // 1609 NA - 1608, - 1607, - 1606, - 1605, - 1604, - 1603, - // 1602 NA - // 1601 NA - // 1600 NA - // 1599 NA - // 1598 NA - // 1597 NA - 1596, - // 1595 NA - // 1594 NA - // 1593 NA - 1592, - 1591, - 1590, - 1589, - 1588, - // 1587 NA - 1586, - 1585, - // 1584 NA - // 1583 NA - 1582, - 1581, - 1580, - // 1579 NA - 1578, - 1577, - 1576, - // 1575 NA - 1574, - // 1573 NA - // 1572 NA - 1571, - 1570, - 1569, - 1568, - 1567, - // 1566 NA - 1565, - 1564, - 1563, - // 1562 NA - // 1561 NA - // 1560 NA - 1559, - 1558, - 1557, - // 1556 NA - // 1555 NA - 1554, - 1553, - 1552, - 1551, - 1550, - 1549, - 1548, - 1547, - 1546, - // 1545 NA - // 1544 NA - // 1543 NA - // 1542 NA - // 1541 NA - // 1540 NA - // 1539 NA - // 1538 NA - // 1537 NA - // 1536 NA - 1535, - // 1534 NA - 1533, - // 1532 NA - // 1531 NA - // 1530 NA - // 1529 NA - 1528, - // 1527 NA - // 1526 NA - // 1525 NA - // 1524 NA - // 1523 NA - // 1522 NA - 1521, - // 1520 NA - // 1519 NA - // 1518 NA - // 1517 NA - 1516, - // 1515 NA - // 1514 NA - 1513, - // 1512 NA - 1511, - // 1510 NA - // 1509 NA - // 1508 NA - // 1507 NA - // 1506 NA - // 1505 NA - // 1504 NA - // 1503 NA - // 1502 NA - // 1501 NA - 1500, - 1499, - // 1498 NA - // 1497 NA - // 1496 NA - // 1495 NA - 1494, - // 1493 NA - 1492, - 1491, - // 1490 NA - // 1489 NA - // 1488 NA - // 1487 NA - 1486, - // 1485 NA - // 1484 NA - // 1483 NA - // 1482 NA - // 1481 NA - 1480, - 1479, - 1478, - 1477, - // 1476 NA - // 1475 NA - // 1474 NA - // 1473 NA - // 1472 NA - // 1471 NA - // 1470 NA - // 1469 NA - 1468, - // 1467 NA - // 1466 NA - // 1465 NA - 1464, - // 1463 NA - // 1462 NA - // 1461 NA - // 1460 NA - // 1459 NA - // 1458 NA - // 1457 NA - // 1456 NA - // 1455 NA - // 1454 NA - // 1453 NA - // 1452 NA - // 1451 NA - // 1450 NA - // 1449 NA - // 1448 NA - // 1447 NA - // 1446 NA - // 1445 NA - // 1444 NA - // 1443 NA - // 1442 NA - // 1441 NA - // 1440 NA - // 1439 NA - // 1438 NA - // 1437 NA - // 1436 NA - // 1435 NA - // 1434 NA - // 1433 NA - // 1432 NA - // 1431 NA - // 1430 NA - // 1429 NA - // 1428 NA - // 1427 NA - // 1426 NA - 1425, - // 1424 NA - // 1423 NA - // 1422 NA - // 1421 NA - // 1420 NA - // 1419 NA - // 1418 NA - // 1417 NA - // 1416 NA - // 1415 NA - // 1414 NA - // 1413 NA - // 1412 NA - // 1411 NA - 1410, - // 1409 NA - // 1408 NA - // 1407 NA - 1406, - 1405, - // 1404 NA - // 1403 NA - // 1402 NA - 1401, - // 1400 NA - // 1399 NA - // 1398 NA - 1397, - 1396, - // 1395 NA - 1394, - // 1393 NA - // 1392 NA - // 1391 NA - // 1390 NA - // 1389 NA - 1388, - // 1387 NA - // 1386 NA - // 1385 NA - 1384, - // 1383 NA - // 1382 NA - // 1381 NA - // 1380 NA - // 1379 NA - // 1378 NA - // 1377 NA - // 1376 NA - // 1375 NA - // 1374 NA - // 1373 NA - // 1372 NA - // 1371 NA - // 1370 NA - // 1369 NA - // 1368 NA - // 1367 NA - 1366, - 1365, - // 1364 NA - // 1363 NA - // 1362 NA - // 1361 NA - // 1360 NA - // 1359 NA - // 1358 NA - // 1357 NA - // 1356 NA - // 1355 NA - // 1354 NA - // 1353 NA - 1352, - // 1351 NA - // 1350 NA - // 1349 NA - // 1348 NA - 1347, - 1346, - // 1345 NA - // 1344 NA - // 1343 NA - // 1342 NA - // 1341 NA - // 1340 NA - // 1339 NA - // 1338 NA - // 1337 NA - // 1336 NA - // 1335 NA - // 1334 NA - // 1333 NA - // 1332 NA - // 1331 NA - // 1330 NA - // 1329 NA - // 1328 NA - // 1327 NA - // 1326 NA - // 1325 NA - // 1324 NA - // 1323 NA - // 1322 NA - // 1321 NA - // 1320 NA - // 1319 NA - // 1318 NA - // 1317 NA - // 1316 NA - // 1315 NA - // 1314 NA - // 1313 NA - // 1312 NA - // 1311 NA - // 1310 NA - 1309, - // 1308 NA - // 1307 NA - // 1306 NA - 1305, - 1304, - // 1303 NA - // 1302 NA - // 1301 NA - // 1300 NA - // 1299 NA - // 1298 NA - // 1297 NA - 1296, - // 1295 NA - // 1294 NA - // 1293 NA - 1292, - // 1291 NA - // 1290 NA - // 1289 NA - // 1288 NA - // 1287 NA - // 1286 NA - 1285, - 1284, - // 1283 NA - 1282, - 1281, - // 1280 NA - // 1279 NA - // 1278 NA - // 1277 NA - 1276, - // 1275 NA - // 1274 NA - // 1273 NA - // 1272 NA - 1271, - // 1270 NA - 1269, - // 1268 NA - 1267, - 1266, - // 1265 NA - // 1264 NA - // 1263 NA - // 1262 NA - // 1261 NA - // 1260 NA - 1259, - // 1258 NA - // 1257 NA - // 1256 NA - // 1255 NA - // 1254 NA - // 1253 NA - // 1252 NA - // 1251 NA - // 1250 NA - // 1249 NA - // 1248 NA - // 1247 NA - // 1246 NA - // 1245 NA - // 1244 NA - // 1243 NA - // 1242 NA - // 1241 NA - // 1240 NA - // 1239 NA - // 1238 NA - 1237, - 1236, - // 1235 NA - // 1234 NA - // 1233 NA - // 1232 NA - // 1231 NA - // 1230 NA - // 1229 NA - 1228, - // 1227 NA - // 1226 NA - // 1225 NA - // 1224 NA - 1223, - // 1222 NA - // 1221 NA - // 1220 NA - // 1219 NA - // 1218 NA - // 1217 NA - // 1216 NA - // 1215 NA - // 1214 NA - // 1213 NA - // 1212 NA - // 1211 NA - // 1210 NA - // 1209 NA - // 1208 NA - // 1207 NA - // 1206 NA - // 1205 NA - // 1204 NA - // 1203 NA - // 1202 NA - // 1201 NA - // 1200 NA - // 1199 NA - // 1198 NA - // 1197 NA - // 1196 NA - // 1195 NA - // 1194 NA - // 1193 NA - // 1192 NA - // 1191 NA - // 1190 NA - // 1189 NA - // 1188 NA - // 1187 NA - // 1186 NA - // 1185 NA - // 1184 NA - // 1183 NA - // 1182 NA - 1181, - 1180, - 1179, - 1178, - // 1177 NA - // 1176 NA - // 1175 NA - // 1174 NA - 1173, - // 1172 NA - // 1171 NA - // 1170 NA - // 1169 NA - 1168, - 1167, - 1166, - // 1165 NA - 1164, - 1163, - // 1162 NA - 1161, - 1160, - // 1159 NA - // 1158 NA - 1157, - // 1156 NA - // 1155 NA - // 1154 NA - 1153, - // 1152 NA - 1151, - 1150, - 1149, - // 1148 NA - 1147, - // 1146 NA - // 1145 NA - 1144, - 1143, - 1142, - 1141, - 1140, - // 1139 NA - // 1138 NA - 1137, - 1136, - // 1135 NA - // 1134 NA - // 1133 NA - 1132, - // 1131 NA - // 1130 NA - // 1129 NA - // 1128 NA - // 1127 NA - 1126, - // 1125 NA - // 1124 NA - 1123, - // 1122 NA - 1121, - 1120, - 1119, - 1118, - 1117, - 1116, - // 1115 NA - 1114, - 1113, - 1112, - 1111, - 1110, - // 1109 NA - 1108, - 1107, - // 1106 NA - 1105, - // 1104 NA - // 1103 NA - 1102, - 1101, - // 1100 NA - // 1099 NA - // 1098 NA - // 1097 NA - 1096, - // 1095 NA - 1094, - 1093, - 1092, - 1091, - 1090, - 1089, - 1088, - 1087, - 1086, - 1085, - 1084, - // 1083 NA - // 1082 NA - 1081, - // 1080 NA - // 1079 NA - // 1078 NA - // 1077 NA - 1076, - 1075, - // 1074 NA - // 1073 NA - 1072, - 1071, - // 1070 NA - // 1069 NA - 1068, - // 1067 NA - // 1066 NA - 1065, - 1064, - // 1063 NA - // 1062 NA - 1061, - // 1060 NA - 1059, - // 1058 NA - 1057, - 1056, - 1055, - 1054, - 1053, - 1052, - 1051, - 1050, - 1049, - 1048, - 1047, - 1046, - // 1045 NA - // 1044 NA - // 1043 NA - 1042, - 1041, - // 1040 NA - // 1039 NA - // 1038 NA - 1037, - 1036, - 1035, - 1034, - // 1033 NA - 1032, - // 1031 NA - 1030, - 1029, - // 1028 NA - 1027, - // 1026 NA - // 1025 NA - // 1024 NA - // 1023 NA - // 1022 NA - // 1021 NA - // 1020 NA - // 1019 NA - 1018, - 1017, - // 1016 NA - 1015, - // 1014 NA - 1013, - // 1012 NA - // 1011 NA - // 1010 NA - // 1009 NA - // 1008 NA - 1007, - 1006, - // 1005 NA - // 1004 NA - // 1003 NA - // 1002 NA - 1001, - 1000, - // 999 NA - 998, - // 997 NA - // 996 NA - // 995 NA - // 994 NA - // 993 NA - // 992 NA - 991, - // 990 NA - 989, - // 988 NA - // 987 NA - // 986 NA - // 985 NA - 984, - // 983 NA - // 982 NA - 981, - 980, - // 979 NA - 978, - 977, - // 976 NA - 975, - 974, - 973, - 972, - // 971 NA - // 970 NA - // 969 NA - // 968 NA - // 967 NA - // 966 NA - // 965 NA - // 964 NA - 963, - // 962 NA - 961, - // 960 NA - // 959 NA - 958, - 957, - // 956 NA - 955, - // 954 NA - 953, - 952, - 951, - 950, - 949, - // 948 NA - // 947 NA - 946, - 945, - 944, - // 943 NA - 942, - 941, - // 940 NA - 939, - // 938 NA - 937, - 936, - // 935 NA - // 934 NA - 933, - 932, - // 931 NA - // 930 NA - 929, - // 928 NA - // 927 NA - 926, - 925, - // 924 NA - // 923 NA - 922, - // 921 NA - // 920 NA - // 919 NA - // 918 NA - // 917 NA - 916, - 915, - // 914 NA - // 913 NA - 912, - // 911 NA - // 910 NA - // 909 NA - // 908 NA - // 907 NA - // 906 NA - // 905 NA - // 904 NA - 903, - // 902 NA - 901, - // 900 NA - // 899 NA - 898, - // 897 NA - 896, - 895, - // 894 NA - 893, - // 892 NA - 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 NA - // 872 NA - 871, - 870, - // 869 NA - 868, - // 867 NA - // 866 NA - // 865 NA - // 864 NA - // 863 NA - // 862 NA - // 861 NA - // 860 NA - 859, - 858, - 857, - 856, - // 855 NA - // 854 NA - 853, - // 852 NA - // 851 NA - // 850 NA - 849, - 848, - 847, - // 846 NA - 845, - 844, - 843, - // 842 NA - // 841 NA - // 840 NA - // 839 NA - // 838 NA - // 837 NA - 836, - 835, - 834, - 833, - 832, - 831, - 830, - // 829 NA - 828, - // 827 NA - 826, - 825, - // 824 NA - 823, - 822, - // 821 NA - 820, - 819, - 818, - 817, - 816, - 815, - 814, - 813, - // 812 NA - 811, - 810, - 809, - // 808 NA - 807, - 806, - 805, - // 804 NA - 803, - 802, - 801, - 800, - 799, - 798, - // 797 NA - // 796 NA - 795, - // 794 NA - 793, - 792, - 791, - 790, - 789, - // 788 NA - 787, - 786, - 785, - 784, - // 783 NA - 782, - 781, - 780, - 779, - 778, - // 777 NA - 776, - 775, - 774, - 773, - // 772 NA - 771, - // 770 NA - 769, - 768, - // 767 NA - // 766 NA - 765, - 764, - // 763 NA - // 762 NA - // 761 NA - 760, - // 759 NA - 758, - // 757 NA - // 756 NA - 755, - 754, - 753, - // 752 NA - // 751 NA - // 750 NA - 749, - 748, - 747, - 746, - 745, - // 744 NA - 743, - 742, - 741, - 740, - 739, - // 738 NA - 737, - 736, - // 735 NA - 734, - // 733 NA - 732, - // 731 NA - // 730 NA - 729, - // 728 NA - // 727 NA - // 726 NA - // 725 NA - // 724 NA - 723, - 722, - 721, - // 720 NA - 719, - 718, - 717, - 716, - 715, - 714, - 713, - 712, - 711, +static const int included_patches[] = { + // 875, + // 874, + // 873, + // 872, + // 871, + // 870, + // 869, + // 868, + // 867, + // 866, + // 865, + // 864, + // 863, + // 862, + // 861, + // 860, + // 859, + // 858, + // 857, + // 856, + // 855, + // 854, + // 853, + // 852, + // 851, + // 850, + // 849, + // 848, + // 847, + // 846, + // 845, + // 844, + // 843, + // 842, + // 841, + // 840, + // 839, + // 838, + // 837, + // 836, + // 835, + // 834, + // 833, + // 832, + // 831, + // 830, + // 829, + // 828, + // 827, + // 826, + // 825, + // 824, + // 823, + // 822, + // 821, + // 820, + // 819, + // 818, + // 817, + // 816, + // 815, + // 814, + // 813, + // 812, + // 811, + // 810, + // 809, + // 808, + // 807, + // 806, + // 805, + // 804, + // 803, + // 802, + // 801, + // 800, + // 799, + // 798, + // 797, + // 796, + // 795, + // 794, + // 793, + // 792, + // 791, + // 790, + // 789, + // 788, + // 787, + // 786, + // 785, + // 784, + // 783, + // 782, + // 781, + // 780, + // 779, + // 778, + // 777, + // 776, + // 775, + // 774, + // 773, + // 772, + // 771, + // 770, + // 769, + // 768, + // 767, + // 766, + // 765, + // 764, + // 763, + // 762, + // 761, + // 760, + // 759, + // 758, + // 757, + // 756, + // 755, + // 754, + // 753, + // 752, + // 751, + // 750, + // 749, + // 748, + // 747, + // 746, + // 745, + // 744, + // 743, + // 742, + // 741, + // 740, + // 739, + // 738, + // 737, + // 736, + // 735, + // 734, + // 733, + // 732, + // 731, + // 730, + // 729, + // 728, + // 727, + // 726, + // 725, + // 724, + // 723, + // 722, + // 721, + // 720, + // 719, + // 718, + // 717, + // 716, + // 715, + // 714, + // 713, + // 712, + // 711, 710, - 709, - 708, - 707, - 706, - // 705 NA - 704, - // 703 NA - 702, - // 701 NA - 700, - 699, - 698, - 697, - 696, - 695, - 694, - 693, - // 692 NA - // 691 NA - 690, - 689, - 688, - // 687 NA - 686, - 685, - // 684 NA - // 683 NA - 682, - // 681 NA + // 709, + // 708, + // 707, + // 706, + // 705, + // 704, + // 703, + // 702, + // 701, + // 700, + // 699, + // 698, + // 697, + // 696, + // 695, + // 694, + // 693, + // 692, + // 691, + // 690, + // 689, + // 688, + // 687, + // 686, + // 685, + // 684, + // 683, + // 682, + // 681, 680, - // 679 NA - // 678 NA - // 677 NA - // 676 NA - 675, - // 674 NA - 673, - 672, - 671, - 670, - // 669 NA - 668, - 667, - // 666 NA - 665, - // 664 NA - // 663 NA - 662, - // 661 NA - 660, - 659, - 658, - // 657 NA - 656, - 655, - 654, - 653, - // 652 NA - 651, - // 650 NA - 649, - // 648 NA - // 647 NA - 646, - 645, - // 644 NA - 643, - 642, - // 641 NA - 640, - 639, - // 638 NA - 637, - 636, - 635, - 634, - 633, - // 632 NA - 631, - 630, - 629, - // 628 NA - // 627 NA - // 626 NA - // 625 NA - // 624 NA - 623, - // 622 NA - // 621 NA - // 620 NA - // 619 NA - // 618 NA - 617, - 616, - 615, + 679, + 678, + // 677, + // 676, + // 675, + // 674, + // 673, + // 672, + // 671, + // 670, + // 669, + // 668, + // 667, + // 666, + // 665, + // 664, + // 663, + // 662, + // 661, + // 660, + // 659, + // 658, + // 657, + // 656, + // 655, + // 654, + // 653, + 652, + // 651, + // 650, + // 649, + // 648, + // 647, + // 646, + // 645, + // 644, + // 643, + // 642, + // 641, + // 640, + // 639, + // 638, + // 637, + // 636, + // 635, + // 634, + // 633, + // 632, + // 631, + // 630, + // 629, + // 628, + // 627, + // 626, + // 625, + // 624, + // 623, + // 622, + // 621, + // 620, + // 619, + 618, + // 617, + // 616, + // 615, 614, - 613, + // 613, 612, - // 611 NA - // 610 NA - 609, - 608, - // 607 NA - 606, + // 611, + // 610, + // 609, + // 608, + 607, + // 606, 605, - 604, - 603, - 602, - 601, - 600, - 599, - 598, - 597, - // 596 NA - 595, - 594, - 593, - // 592 NA - // 591 NA - 590, - // 589 NA - 588, - 587, - // 586 NA - 585, - // 584 NA - // 583 NA - 582, - // 581 NA - 580, - 579, - 578, - 577, - 576, - 575, - 574, - 573, - 572, - // 571 NA - // 570 NA - 569, - 568, - 567, - 566, - 565, - // 564 NA - 563, - 562, + // 604, + // 603, + // 602, + // 601, + // 600, + // 599, + // 598, + // 597, + // 596, + // 595, + // 594, + // 593, + // 592, + // 591, + // 590, + // 589, + // 588, + // 587, + // 586, + // 585, + // 584, + // 583, + // 582, + // 581, + // 580, + // 579, + // 578, + // 577, + // 576, + // 575, + // 574, + // 573, + // 572, + 571, + // 570, + // 569, + // 568, + // 567, + // 566, + // 565, + // 564, + // 563, + // 562, 561, - // 560 NA - 559, - // 558 NA - // 557 NA - // 556 NA - // 555 NA + // 560, + // 559, + // 558, + // 557, + // 556, + 555, 554, 553, 552, - 551, + // 551, 550, - 549, - // 548 NA - 547, - 546, - 545, - // 544 NA - 543, - 542, - 541, - // 540 NA - 539, - 538, - 537, - 536, - 535, - // 534 NA - 533, - 532, - 531, - 530, - 529, - 528, - 527, - 526, - 525, + // 549, + // 548, + // 547, + // 546, + // 545, + // 544, + // 543, + // 542, + // 541, + // 540, + // 539, + // 538, + // 537, + // 536, + // 535, + // 534, + // 533, + // 532, + // 531, + // 530, + // 529, + // 528, + // 527, + // 526, + // 525, 524, - // 523 NA - // 522 NA - 521, - 520, - 519, + // 523, + // 522, + // 521, + // 520, + // 519, 518, - 517, - 516, - 515, - 514, - 513, - // 512 NA - // 511 NA - // 510 NA - // 509 NA - 508, - // 507 NA - // 506 NA - // 505 NA - // 504 NA - 503, + // 517, + // 516, + // 515, + // 514, + // 513, + // 512, + // 511, + // 510, + // 509, + // 508, + // 507, + // 506, + // 505, + // 504, + // 503, 502, - // 501 NA - 500, + // 501, + // 500, 499, - // 498 NA - 497, - // 496 NA - // 495 NA - 494, - 493, - 492, - 491, - 490, - 489, - 488, + 498, + // 497, + // 496, + // 495, + // 494, + // 493, + // 492, + // 491, + // 490, + // 489, + // 488, 487, 486, 485, - // 484 NA + // 484, 483, - // 482 NA - // 481 NA - // 480 NA - // 479 NA + 482, + // 481, + // 480, + // 479, 478, 477, - // 476 NA - // 475 NA - 474, - 473, - 472, - // 471 NA - 470, - // 469 NA - 468, - 467, - 466, - // 465 NA - // 464 NA - 463, - 462, - // 461 NA - // 460 NA - // 459 NA - 458, + // 476, + // 475, + // 474, + // 473, + // 472, + // 471, + // 470, + // 469, + // 468, + // 467, + // 466, + 465, + // 464, + // 463, + // 462, + 461, + // 460, + 459, + // 458, 457, - 456, - 455, - 454, - // 453 NA - 452, - // 451 NA - 450, - 449, - // 448 NA - 447, - 446, - 445, - 444, - // 443 NA - 442, - 441, - 440, - 439, - 438, + // 456, + // 455, + // 454, + 453, + // 452, + // 451, + // 450, + // 449, + // 448, + // 447, + // 446, + // 445, + // 444, + // 443, + // 442, + // 441, + // 440, + // 439, + // 438, 437, - 436, - 435, - 434, - 433, - // 432 NA - // 431 NA - // 430 NA - // 429 NA - // 428 NA - 427, - // 426 NA - 425, - // 424 NA - 423, - 422, - 421, - // 420 NA - 419, - 418, - 417, - 416, - 415, - 414, - // 413 NA - // 412 NA - 411, - 410, - // 409 NA + // 436, + // 435, + // 434, + // 433, + // 432, + // 431, + // 430, + // 429, + // 428, + // 427, + // 426, + // 425, + // 424, + // 423, + // 422, + // 421, + // 420, + // 419, + // 418, + // 417, + // 416, + // 415, + // 414, + // 413, + // 412, + // 411, + // 410, + // 409, 408, 407, - 406, - 405, - // 404 NA - // 403 NA - // 402 NA - // 401 NA + // 406, + // 405 NA + // 404, + // 403, + // 402, + // 401, // 400 NA - // 399 NA - // 398 NA - 397, - 396, - 395, - // 394 NA - // 393 NA - 392, - 391, + // 399, + // 398, + // 397, + // 396, + // 395, + 394, + 393, + // 392, + // 391, 390, - 389, + // 389, 388, - 387, - 386, - // 385 NA - // 384 NA - 383, - 382, - 381, - // 380 NA - 379, + // 387, + // 386, + // 385, + // 384, + // 383, + // 382, + // 381, + // 380, + // 379, 378, 377, 376, - 375, - 374, - 373, - 372, - 371, - 370, - 369, - 368, - 367, - // 366 NA - 365, - 364, - // 363 NA - 362, - 361, + // 375, + // 374, + // 373, + // 372, + // 371, + // 370, + // 369, + // 368, + // 367, + // 366, + // 365, + // 364, + // 363, + // 362, + // 361, 360, - 359, - 358, - 357, - // 356 NA - 355, - // 354 NA + // 359, + // 358, + // 357, + // 356, + // 355, + // 354, 353, - 352, - 351, - 350, - 349, - 348, + // 352, + // 351, + // 350, + // 349, + // 348, 347, - 346, + // 346, 345, - 344, + // 344, 343, - // 342 NA + // 342, 341, - // 340 NA - 339, - 338, - 337, - 336, - 335, - 334, - // 333 NA - // 332 NA + // 340, + // 339, + // 338, + // 337, + // 336, + // 335, + // 334, + // 333, + // 332, 331, - 330, - 329, - 328, - 327, - // 326 NA + // 330, + // 329, + // 328, + // 327, + 326, 325, - 324, - 323, - // 322 NA - // 321 NA - 320, - // 319 NA - 318, - 317, - // 316 NA - 315, - 314, - 313, - 312, + // 324, + // 323, + 322, + // 321, + // 320, + 319, + // 318, + // 317, + // 316, + // 315, + // 314, + // 313, + // 312, 311, - 310, - 309, + // 310, + // 309, 308, - // 307 NA - 306, - 305, - // 304 NA - 303, - 302, - 301, - // 300 NA - // 299 NA - 298, + 307, + // 306, + // 305, + // 304, + // 303, + // 302, + // 301, + // 300, + // 299, + // 298, 297, - 296, - 295, - 294, - 293, - 292, - 291, + // 296, + // 295, + // 294, + // 293, + // 292, + // 291, 290, - 289, - 288, - // 287 NA - 286, - 285, - 284, - // 283 NA - 282, - 281, + // 289, + // 288 NA + // 287, + // 286, + // 285 NA + // 284 NA + // 283, + // 282, + // 281 NA 280, - 279, - 278, - 277, - 276, + // 279 NA + // 278 NA + // 277 NA + // 276 NA 275, 274, // 273 NA - 272, + // 272 NA // 271 NA // 270 NA - 269, - 268, - 267, + // 269 NA + // 268 NA + // 267 NA 266, - 265, - 264, - // 263 NA - 262, - 261, - 260, - // 259 NA - // 258 NA + // 265, + // 264, + // 263, + // 262, + // 261, + // 260 NA + 259, + // 258, // 257 NA - 256, - // 255 NA - // 254 NA - 253, - // 252 NA - 251, - // 250 NA - 249, - 248, + // 256, + // 255, + // 254, + // 253, + // 252, + // 251, + 250, + // 249 NA + // 248, 247, // 246 NA - 245, - // 244 NA + // 245, + // 244, 243, - 242, - 241, - 240, - 239, - // 238 NA - 237, - 236, + // 242, + // 241 NA + // 240 NA + // 239 NA + // 238, + // 237, + // 236, 235, - 234, - 233, - 232, - 231, - 230, + // 234, + // 233, + // 232 NA + // 231, + // 230, 229, - // 228 NA - // 227 NA - 226, - // 225 NA - // 224 NA - // 223 NA - // 222 NA - 221, - 220, + // 228, + // 227, + // 226, + // 225, + // 224, + 223, + // 222, + // 221 NA + // 220, 219, - 218, + // 218, // 217 NA - // 216 NA - 215, - // 214 NA - 213, - // 212 NA - 211, - 210, + // 216, + // 215, + // 214, + // 213 NA + // 212, + // 211 NA + // 210, 209, - // 208 NA - 207, - // 206 NA + 208, + // 207, + // 206, 205, - 204, - 203, - // 202 NA - 201, - // 200 NA - 199, - // 198 NA - // 197 NA - // 196 NA - // 195 NA - // 194 NA - 193, - 192, - 191, - // 190 NA - // 189 NA - // 188 NA - 187, - 186, - // 185 NA - 184, - // 183 NA - // 182 NA - 181, - // 180 NA - // 179 NA + // 204, + // 203 NA + // 202, + // 201, + // 200, + // 199 NA + // 198, + // 197, + // 196, + 195, + // 194, + // 193 NA + // 192 NA + // 191 NA + 190, + // 189, + // 188, + // 187 NA + // 186, + // 185, + // 184, + // 183, + // 182, + // 181, + // 180, + 179, 178, - // 177 NA - // 176 NA - // 175 NA - // 174 NA - 173, + 177, + 176, + // 175, + 174, + // 173 NA 172, - 171, - 170, - 169, - // 168 NA + // 171, + // 170, + // 169, + 168, 167, - 166, + // 166, 165, - // 164 NA + // 164, // 163 NA // 162 NA // 161 NA - 160, + // 160, 159, 158, - 157, + // 157, 156, - 155, - 154, - 153, - 152, - 151, + // 155, + // 154, + // 153, + // 152 NA + // 151, 150, 149, - 148, + // 148, 147, 146, - 145, - 144, + // 145 NA + // 144 NA 143, - 142, - 141, - 140, - 139, - 138, + // 142, + // 141, + // 140, + // 139 NA + // 138 NA 137, 136, 135, 134, 133, - 132, - 131, - 130, - 129, + // 132, + // 131, + // 130 NA + // 129 NA 128, 127, 126, 125, 124, - 123, - 122, + // 123 NA + // 122 NA 121, - 120, + // 120 NA 119, - 118, - 117, + // 118, + // 117 NA 116, - 115, - 114, - 113, - 112, + // 115 NA + // 114 NA + // 113 NA + // 112, 111, 110, - 109, - 108, - 107, - 106, - 105, - 104, - 103, - 102, - 101, + // 109 NA + // 108 NA + // 107 NA + // 106, + // 105 NA + // 104, + // 103 NA + // 102, + // 101, 100, 99, - 98, - 97, - 96, - 95, - 94, - 93, + // 98 NA + // 97 NA + // 96, + // 95 NA + // 94 NA + // 93 NA 92, - 91, + // 91, 90, - 89, + // 89 NA 88, - 87, + // 87 NA 86, 85, 84, 83, - 82, + // 82 NA 81, - 80, + // 80 NA 79, 78, - 77, - 76, + // 77 NA + // 76 NA 75, - 74, + // 74, 73, - 72, - 71, - 70, + // 72 NA + // 71 NA + // 70 NA 69, 68, - 67, + // 67 NA 66, - 65, + // 65 NA 64, - 63, + // 63 NA 62, - 61, + // 61 NA 60, - 59, + // 59 NA 58, 57, 56, - 55, - 54, + // 55 NA + // 54 NA 53, 52, - 51, - 50, + // 51 NA + // 50 NA 49, - 48, + // 48 NA 47, 46, - 45, + // 45 NA 44, 43, 42, 41, 40, - 39, + // 39 NA 38, 37, - 36, + // 36 NA 35, 34, 33, 32, 31, - 30, - 29, - 28, - 27, + // 30 NA + // 29 NA + // 28 NA + // 27 NA 26, 25, - 24, + // 24 NA 23, - 22, - 21, + // 22 NA + // 21, 20, 19, - 18, + // 18, 17, - 16, - 15, - 14, - 13, + // 16 NA + // 15 NA + // 14 NA + // 13 NA 12, - 11, - 10, - 9, + // 11 NA + // 10 NA + // 9 NA 8, - 7, + // 7 NA 6, - 5, + // 5 NA 4, 3, 2, @@ -2460,10 +971,10 @@ static char *(extra_patches[]) = { /// @param version Version string like "1.3.42" /// /// @return true if Nvim is at or above the version. -bool has_nvim_version(char *version_str) - FUNC_ATTR_NONNULL_ALL +bool has_nvim_version(const char *const version_str) + FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL { - char *p = version_str; + const char *p = version_str; int major = 0; int minor = 0; int patch = 0; @@ -2472,7 +983,7 @@ bool has_nvim_version(char *version_str) return false; } major = atoi(p); - p = strchr(p, '.'); // Find the next dot. + p = strchr(p, '.'); // Find the next dot. if (p) { p++; // Advance past the dot. @@ -2480,7 +991,7 @@ bool has_nvim_version(char *version_str) return false; } minor = atoi(p); - p = strchr(p, '.'); + p = strchr(p, '.'); if (p) { p++; if (!ascii_isdigit(*p)) { @@ -2572,19 +1083,13 @@ static void list_features(void) int idx = (i / ncol) + (i % ncol) * nrow; if (idx < nfeat) { int last_col = (i + 1) % ncol == 0; - msg_puts((char_u *)features[idx]); + msg_puts(features[idx]); if (last_col) { if (msg_col > 0) { msg_putchar('\n'); } } else { - while (msg_col % width) { - int old_msg_col = msg_col; - msg_putchar(' '); - if (old_msg_col == msg_col) { - break; // XXX: Avoid infinite loop. - } - } + msg_putchar(' '); } } else { if (msg_col > 0) { @@ -2592,7 +1097,7 @@ static void list_features(void) } } } - MSG_PUTS("For differences from Vim, see :help vim-differences\n\n"); + MSG_PUTS("See \":help feature-compile\"\n\n"); } void list_version(void) @@ -2633,7 +1138,7 @@ void list_version(void) } #endif // ifdef HAVE_PATHDEF - version_msg(_("\n\nOptional features included (+) or not (-): ")); + version_msg(_("\n\nFeatures: ")); list_features(); @@ -2705,7 +1210,6 @@ void intro_message(int colon) static char *(lines[]) = { N_(NVIM_VERSION_LONG), "", - N_("by Bram Moolenaar et al."), N_("Nvim is open source and freely distributable"), N_("https://neovim.io/community"), "", diff --git a/src/nvim/version.h b/src/nvim/version.h index 1de809e539..c10f6fa534 100644 --- a/src/nvim/version.h +++ b/src/nvim/version.h @@ -1,6 +1,8 @@ #ifndef NVIM_VERSION_H #define NVIM_VERSION_H +#include "nvim/ex_cmds_defs.h" + // defined in version.c extern char* Version; extern char* longVersion; @@ -8,14 +10,14 @@ extern char* longVersion; // // Vim version number, name, etc. Patchlevel is defined in version.c. // -#define VIM_VERSION_MAJOR 7 -#define VIM_VERSION_MINOR 4 +#define VIM_VERSION_MAJOR 8 +#define VIM_VERSION_MINOR 0 #define VIM_VERSION_100 (VIM_VERSION_MAJOR * 100 + VIM_VERSION_MINOR) // used for the runtime directory name -#define VIM_VERSION_NODOT "vim74" +#define VIM_VERSION_NODOT "vim80" // swap file compatibility (max. length is 6 chars) -#define VIM_VERSION_SHORT "7.4" +#define VIM_VERSION_SHORT "8.0" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "version.h.generated.h" diff --git a/src/nvim/vim.h b/src/nvim/vim.h index 8271abda8d..62ffc7433e 100644 --- a/src/nvim/vim.h +++ b/src/nvim/vim.h @@ -11,26 +11,22 @@ #define RUNTIME_DIRNAME "runtime" /* end */ -/* ============ the header file puzzle (ca. 50-100 pieces) ========= */ - -#ifdef HAVE_CONFIG_H /* GNU autoconf (or something else) was here */ -# include "auto/config.h" -# define HAVE_PATHDEF +#include "auto/config.h" +#define HAVE_PATHDEF /* * Check if configure correctly managed to find sizeof(int). If this failed, * it becomes zero. This is likely a problem of not being able to run the * test program. Other items from configure may also be wrong then! */ -# if (SIZEOF_INT == 0) -Error: configure did not run properly.Check auto/config.log. -# endif +#if (SIZEOF_INT == 0) +# error Configure did not run properly. #endif #include "nvim/os/os_defs.h" /* bring lots of system header files */ /// length of a buffer to store a number in ASCII (64 bits binary + NUL) -#define NUMBUFLEN 65 +enum { NUMBUFLEN = 65 }; // flags for vim_str2nr() #define STR2NR_BIN 1 @@ -46,27 +42,7 @@ Error: configure did not run properly.Check auto/config.log. #include "nvim/keymap.h" #include "nvim/macros.h" - - - -/* ================ end of the header file puzzle =============== */ - -#ifdef HAVE_WORKING_LIBINTL -# include <libintl.h> -# define _(x) gettext((char *)(x)) -// XXX do we actually need this? -# ifdef gettext_noop -# define N_(x) gettext_noop(x) -# else -# define N_(x) x -# endif -#else -# define _(x) ((char *)(x)) -# define N_(x) x -# define bindtextdomain(x, y) /* empty */ -# define bind_textdomain_codeset(x, y) /* empty */ -# define textdomain(x) /* empty */ -#endif +#include "nvim/gettext.h" /* special attribute addition: Put message in history */ #define MSG_HIST 0x1000 @@ -109,11 +85,14 @@ Error: configure did not run properly.Check auto/config.log. // all mode bits used for mapping #define MAP_ALL_MODES (0x3f | SELECTMODE | TERM_FOCUS) -/* directions */ -#define FORWARD 1 -#define BACKWARD (-1) -#define FORWARD_FILE 3 -#define BACKWARD_FILE (-3) +/// Directions. +typedef enum { + kDirectionNotSet = 0, + FORWARD = 1, + BACKWARD = (-1), + FORWARD_FILE = 3, + BACKWARD_FILE = (-3), +} Direction; /* return values for functions */ #if !(defined(OK) && (OK == 1)) @@ -184,6 +163,7 @@ enum { EXPAND_SYNTIME, EXPAND_USER_ADDR_TYPE, EXPAND_PACKADD, + EXPAND_MESSAGES, }; @@ -225,6 +205,8 @@ enum { #define DIALOG_MSG_SIZE 1000 /* buffer size for dialog_msg() */ +enum { FOLD_TEXT_LEN = 51 }; //!< buffer size for get_foldtext() + /* * Maximum length of key sequence to be mapped. * Must be able to hold an Amiga resize report. @@ -269,6 +251,7 @@ enum { #define STRCAT(d, s) strcat((char *)(d), (char *)(s)) #define STRNCAT(d, s, n) strncat((char *)(d), (char *)(s), (size_t)(n)) +#define STRLCAT(d, s, n) xstrlcat((char *)(d), (char *)(s), (size_t)(n)) # define vim_strpbrk(s, cs) (char_u *)strpbrk((char *)(s), (char *)(cs)) @@ -281,15 +264,22 @@ enum { #define SHOWCMD_COLS 10 /* columns needed by shown command */ #define STL_MAX_ITEM 80 /* max nr of %<flag> in statusline */ -/* - * fnamecmp() is used to compare file names. - * On some systems case in a file name does not matter, on others it does. - * (this does not account for maximum name lengths and things like "../dir", - * thus it is not 100% accurate!) - */ -#define fnamecmp(x, y) vim_fnamecmp((char_u *)(x), (char_u *)(y)) -#define fnamencmp(x, y, n) vim_fnamencmp((char_u *)(x), (char_u *)(y), \ - (size_t)(n)) +/// Compare file names +/// +/// On some systems case in a file name does not matter, on others it does. +/// +/// @note Does not account for maximum name lengths and things like "../dir", +/// thus it is not 100% accurate. OS may also use different algorythm for +/// case-insensitive comparison. +/// +/// @param[in] x First file name to compare. +/// @param[in] y Second file name to compare. +/// +/// @return 0 for equal file names, non-zero otherwise. +#define fnamecmp(x, y) path_fnamecmp((const char *)(x), (const char *)(y)) +#define fnamencmp(x, y, n) path_fnamencmp((const char *)(x), \ + (const char *)(y), \ + (size_t)(n)) /* * Enums need a typecast to be used as array index (for Ultrix). @@ -324,8 +314,14 @@ enum { #define DIP_START 0x08 // also use "start" directory in 'packpath' #define DIP_OPT 0x10 // also use "opt" directory in 'packpath' #define DIP_NORTP 0x20 // do not use 'runtimepath' +#define DIP_NOAFTER 0x40 // skip "after" directories +#define DIP_AFTER 0x80 // only use "after" directories // Lowest number used for window ID. Cannot have this many windows per tab. #define LOWEST_WIN_ID 1000 +#if (defined(__FreeBSD__) || defined(__FreeBSD_kernel__)) && defined(S_ISCHR) +# define OPEN_CHR_FILES +#endif + #endif /* NVIM_VIM_H */ diff --git a/src/nvim/window.c b/src/nvim/window.c index 00229ccca9..c2d0a9b3b1 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #include <assert.h> #include <inttypes.h> #include <stdbool.h> @@ -45,6 +48,7 @@ #include "nvim/syntax.h" #include "nvim/terminal.h" #include "nvim/undo.h" +#include "nvim/ui.h" #include "nvim/os/os.h" @@ -129,9 +133,10 @@ newwindow: vim_snprintf(cbuf, sizeof(cbuf) - 5, "%" PRId64, (int64_t)Prenum); else cbuf[0] = NUL; - if (nchar == 'v' || nchar == Ctrl_V) - strcat(cbuf, "v"); - strcat(cbuf, "new"); + if (nchar == 'v' || nchar == Ctrl_V) { + xstrlcat(cbuf, "v", sizeof(cbuf)); + } + xstrlcat(cbuf, "new", sizeof(cbuf)); do_cmdline_cmd(cbuf); break; @@ -160,13 +165,18 @@ newwindow: /* cursor to preview window */ case 'P': - for (wp = firstwin; wp != NULL; wp = wp->w_next) - if (wp->w_p_pvw) + wp = NULL; + FOR_ALL_WINDOWS_IN_TAB(wp2, curtab) { + if (wp2->w_p_pvw) { + wp = wp2; break; - if (wp == NULL) + } + } + if (wp == NULL) { EMSG(_("E441: There is no preview window")); - else + } else { win_goto(wp); + } break; /* close all but current window */ @@ -183,7 +193,7 @@ newwindow: /* cursor to previous window with wrap around */ case 'W': CHECK_CMDWIN - if (firstwin == lastwin && Prenum != 1) /* just one window */ + if (ONE_WINDOW && Prenum != 1) /* just one window */ beep_flush(); else { if (Prenum) { /* go to specified window */ @@ -441,13 +451,12 @@ wingotofile: case 'g': case Ctrl_G: CHECK_CMDWIN - ++ no_mapping; - ++allow_keys; /* no mapping for xchar, but allow key codes */ - if (xchar == NUL) + no_mapping++; + if (xchar == NUL) { xchar = plain_vgetc(); - LANGMAP_ADJUST(xchar, TRUE); - --no_mapping; - --allow_keys; + } + LANGMAP_ADJUST(xchar, true); + no_mapping--; (void)add_to_showcmd(xchar); switch (xchar) { case '}': @@ -565,7 +574,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir) oldwin = curwin; /* add a status line when p_ls == 1 and splitting the first window */ - if (lastwin == firstwin && p_ls == 1 && oldwin->w_status_height == 0) { + if (ONE_WINDOW && p_ls == 1 && oldwin->w_status_height == 0) { if (oldwin->w_height <= p_wmh && new_wp == NULL) { EMSG(_(e_noroom)); return FAIL; @@ -973,11 +982,12 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir) /* * make the new window the current window */ - win_enter(wp, false); - if (flags & WSP_VERT) + win_enter_ext(wp, false, false, true, true, true); + if (flags & WSP_VERT) { p_wiw = i; - else + } else { p_wh = i; + } return OK; } @@ -1033,7 +1043,7 @@ static void win_init(win_T *newp, win_T *oldp, int flags) win_init_some(newp, oldp); - check_colorcolumn(newp); + didset_window_options(newp); } /* @@ -1172,7 +1182,7 @@ static void win_exchange(long Prenum) win_T *wp2; int temp; - if (lastwin == firstwin) { /* just one window */ + if (ONE_WINDOW) { /* just one window */ beep_flush(); return; } @@ -1261,7 +1271,7 @@ static void win_rotate(int upwards, int count) frame_T *frp; int n; - if (firstwin == lastwin) { /* nothing to do */ + if (ONE_WINDOW) { /* nothing to do */ beep_flush(); return; } @@ -1333,7 +1343,7 @@ static void win_totop(int size, int flags) int dir; int height = curwin->w_height; - if (lastwin == firstwin) { + if (ONE_WINDOW) { beep_flush(); return; } @@ -1707,25 +1717,24 @@ static void win_equal_rec( } } -/* - * close all windows for buffer 'buf' - */ -void -close_windows ( - buf_T *buf, - int keep_curwin /* don't close "curwin" */ -) +/// Closes all windows for buffer `buf`. +/// +/// @param keep_curwin don't close `curwin` +void close_windows(buf_T *buf, int keep_curwin) { tabpage_T *tp, *nexttp; int h = tabline_height(); + int count = tabpage_index(NULL); ++RedrawingDisabled; - for (win_T *wp = firstwin; wp != NULL && lastwin != firstwin; ) { + for (win_T *wp = firstwin; wp != NULL && !ONE_WINDOW; ) { if (wp->w_buffer == buf && (!keep_curwin || wp != curwin) - && !(wp->w_closing || wp->w_buffer->b_closing) - ) { - win_close(wp, FALSE); + && !(wp->w_closing || wp->w_buffer->b_locked > 0)) { + if (win_close(wp, false) == FAIL) { + // If closing the window fails give up, to avoid looping forever. + break; + } /* Start all over, autocommands may change the window layout. */ wp = firstwin; @@ -1739,9 +1748,8 @@ close_windows ( if (tp != curtab) { FOR_ALL_WINDOWS_IN_TAB(wp, tp) { if (wp->w_buffer == buf - && !(wp->w_closing || wp->w_buffer->b_closing) - ) { - win_close_othertab(wp, FALSE, tp); + && !(wp->w_closing || wp->w_buffer->b_locked > 0)) { + win_close_othertab(wp, false, tp); /* Start all over, the tab page may be closed and * autocommands may change the window layout. */ @@ -1754,9 +1762,14 @@ close_windows ( --RedrawingDisabled; - redraw_tabline = TRUE; - if (h != tabline_height()) + if (count != tabpage_index(NULL)) { + apply_autocmds(EVENT_TABCLOSED, NULL, NULL, false, curbuf); + } + + redraw_tabline = true; + if (h != tabline_height()) { shell_new_rows(); + } } /// Check that current window is the last one. @@ -1797,7 +1810,7 @@ static bool close_last_window_tabpage(win_T *win, bool free_buf, tabpage_T *prev_curtab) FUNC_ATTR_NONNULL_ARG(1) { - if (firstwin != lastwin) { + if (!ONE_WINDOW) { return false; } buf_T *old_curbuf = curbuf; @@ -1865,14 +1878,17 @@ int win_close(win_T *win, int free_buf) int dir; int help_window = FALSE; tabpage_T *prev_curtab = curtab; + frame_T *win_frame = win->w_frame->fr_parent; if (last_window()) { EMSG(_("E444: Cannot close last window")); return FAIL; } - if (win->w_closing || (win->w_buffer != NULL && win->w_buffer->b_closing)) - return FAIL; /* window is already being closed */ + if (win->w_closing + || (win->w_buffer != NULL && win->w_buffer->b_locked > 0)) { + return FAIL; // window is already being closed + } if (win == aucmd_win) { EMSG(_("E813: Cannot close autocmd window")); return FAIL; @@ -1937,6 +1953,8 @@ int win_close(win_T *win, int free_buf) * Close the link to the buffer. */ if (win->w_buffer != NULL) { + bufref_T bufref; + set_bufref(&bufref, curbuf); win->w_closing = true; close_buffer(win, win->w_buffer, free_buf ? DOBUF_UNLOAD : 0, true); if (win_valid_any_tab(win)) { @@ -1945,7 +1963,7 @@ int win_close(win_T *win, int free_buf) // Make sure curbuf is valid. It can become invalid if 'bufhidden' is // "wipe". - if (!buf_valid(curbuf)) { + if (!bufref_valid(&bufref)) { curbuf = firstbuf; } } @@ -2004,20 +2022,25 @@ int win_close(win_T *win, int free_buf) } curbuf = curwin->w_buffer; close_curwin = TRUE; + + // The cursor position may be invalid if the buffer changed after last + // using the window. + check_cursor(); } - if (p_ea - && (*p_ead == 'b' || *p_ead == dir) - ) { - win_equal(curwin, true, dir); + if (p_ea && (*p_ead == 'b' || *p_ead == dir)) { + // If the frame of the closed window contains the new current window, + // only resize that frame. Otherwise resize all windows. + win_equal(curwin, curwin->w_frame->fr_parent == win_frame, dir); } else { win_comp_pos(); } if (close_curwin) { - win_enter_ext(wp, false, TRUE, TRUE, TRUE); - if (other_buffer) - /* careful: after this wp and win may be invalid! */ - apply_autocmds(EVENT_BUFENTER, NULL, NULL, FALSE, curbuf); + win_enter_ext(wp, false, true, false, true, true); + if (other_buffer) { + // careful: after this wp and win may be invalid! + apply_autocmds(EVENT_BUFENTER, NULL, NULL, false, curbuf); + } } /* @@ -2050,7 +2073,8 @@ void win_close_othertab(win_T *win, int free_buf, tabpage_T *tp) // Get here with win->w_buffer == NULL when win_close() detects the tab page // changed. - if (win->w_closing || (win->w_buffer != NULL && win->w_buffer->b_closing)) { + if (win->w_closing + || (win->w_buffer != NULL && win->w_buffer->b_locked > 0)) { return; // window is already being closed } @@ -2173,7 +2197,7 @@ winframe_remove ( /* * If there is only one window there is nothing to remove. */ - if (tp == NULL ? firstwin == lastwin : tp->tp_firstwin == tp->tp_lastwin) + if (tp == NULL ? ONE_WINDOW : tp->tp_firstwin == tp->tp_lastwin) return NULL; /* @@ -2310,7 +2334,7 @@ win_altframe ( frame_T *frp; int b; - if (tp == NULL ? firstwin == lastwin : tp->tp_firstwin == tp->tp_lastwin) + if (tp == NULL ? ONE_WINDOW : tp->tp_firstwin == tp->tp_lastwin) /* Last window in this tab page, will go to next tab page. */ return alt_tabpage()->tp_curwin->w_frame; @@ -2830,7 +2854,7 @@ close_others ( win_close(wp, !P_HID(wp->w_buffer) && !bufIsChanged(wp->w_buffer)); } - if (message && lastwin != firstwin) + if (message && !ONE_WINDOW) EMSG(_("E445: Other window contains changes")); } @@ -2966,8 +2990,8 @@ static tabpage_T *alloc_tabpage(void) tp->handle = ++last_tp_handle; handle_register_tabpage(tp); - /* init t: variables */ - tp->tp_vars = dict_alloc(); + // Init t: variables. + tp->tp_vars = tv_dict_alloc(); init_var_dict(tp->tp_vars, &tp->tp_winvar, VAR_SCOPE); tp->tp_diff_invalid = TRUE; tp->tp_ch_used = p_ch; @@ -2987,8 +3011,7 @@ void free_tabpage(tabpage_T *tp) hash_init(&tp->tp_vars->dv_hashtab); unref_var_dict(tp->tp_vars); - - xfree(tp->localdir); // Free tab-local working directory + xfree(tp->tp_localdir); xfree(tp); } @@ -3014,7 +3037,7 @@ int win_new_tabpage(int after, char_u *filename) return FAIL; } - newtp->localdir = tp->localdir ? vim_strsave(tp->localdir) : NULL; + newtp->tp_localdir = tp->tp_localdir ? vim_strsave(tp->tp_localdir) : NULL; curtab = newtp; @@ -3045,8 +3068,9 @@ int win_new_tabpage(int after, char_u *filename) redraw_all_later(CLEAR); - apply_autocmds(EVENT_TABNEW, filename, filename, false, curbuf); + apply_autocmds(EVENT_WINNEW, NULL, NULL, false, curbuf); apply_autocmds(EVENT_WINENTER, NULL, NULL, false, curbuf); + apply_autocmds(EVENT_TABNEW, filename, filename, false, curbuf); apply_autocmds(EVENT_TABENTER, NULL, NULL, false, curbuf); return OK; @@ -3118,6 +3142,45 @@ bool valid_tabpage(tabpage_T *tpc) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT return false; } +/// Returns true when `tpc` is valid and at least one window is valid. +int valid_tabpage_win(tabpage_T *tpc) +{ + FOR_ALL_TABS(tp) { + if (tp == tpc) { + FOR_ALL_WINDOWS_IN_TAB(wp, tp) { + if (win_valid_any_tab(wp)) { + return true; + } + } + return false; + } + } + // shouldn't happen + return false; +} + +/// Close tabpage `tab`, assuming it has no windows in it. +/// There must be another tabpage or this will crash. +void close_tabpage(tabpage_T *tab) +{ + tabpage_T *ptp; + + if (tab == first_tabpage) { + first_tabpage = tab->tp_next; + ptp = first_tabpage; + } else { + for (ptp = first_tabpage; ptp != NULL && ptp->tp_next != tab; + ptp = ptp->tp_next) { + // do nothing + } + assert(ptp != NULL); + ptp->tp_next = tab->tp_next; + } + + goto_tabpage_tp(ptp, false, false); + free_tabpage(tab); +} + /* * Find tab page "n" (first one is 1). Returns NULL when not found. */ @@ -3204,8 +3267,8 @@ static void enter_tabpage(tabpage_T *tp, buf_T *old_curbuf, int trigger_enter_au /* We would like doing the TabEnter event first, but we don't have a * valid current window yet, which may break some commands. * This triggers autocommands, thus may make "tp" invalid. */ - win_enter_ext(tp->tp_curwin, false, TRUE, - trigger_enter_autocmds, trigger_leave_autocmds); + win_enter_ext(tp->tp_curwin, false, true, false, + trigger_enter_autocmds, trigger_leave_autocmds); prevwin = next_prevwin; last_status(FALSE); /* status line may appear or disappear */ @@ -3350,15 +3413,20 @@ void tabpage_move(int nr) tp_dst = tp; - /* Remove the current tab page from the list of tab pages. */ - if (curtab == first_tabpage) + // Remove the current tab page from the list of tab pages. + if (curtab == first_tabpage) { first_tabpage = curtab->tp_next; - else { - for (tp = first_tabpage; tp != NULL; tp = tp->tp_next) - if (tp->tp_next == curtab) + } else { + tp = NULL; + FOR_ALL_TABS(tp2) { + if (tp2->tp_next == curtab) { + tp = tp2; break; - if (tp == NULL) /* "cannot happen" */ + } + } + if (tp == NULL) { // "cannot happen" return; + } tp->tp_next = curtab->tp_next; } @@ -3546,7 +3614,7 @@ end: */ void win_enter(win_T *wp, bool undo_sync) { - win_enter_ext(wp, undo_sync, FALSE, TRUE, TRUE); + win_enter_ext(wp, undo_sync, false, false, true, true); } /* @@ -3554,7 +3622,9 @@ void win_enter(win_T *wp, bool undo_sync) * Can be called with "curwin_invalid" TRUE, which means that curwin has just * been closed and isn't valid. */ -static void win_enter_ext(win_T *wp, bool undo_sync, int curwin_invalid, int trigger_enter_autocmds, int trigger_leave_autocmds) +static void win_enter_ext(win_T *wp, bool undo_sync, int curwin_invalid, + int trigger_new_autocmds, int trigger_enter_autocmds, + int trigger_leave_autocmds) { int other_buffer = FALSE; @@ -3603,33 +3673,46 @@ static void win_enter_ext(win_T *wp, bool undo_sync, int curwin_invalid, int tri curwin->w_cursor.coladd = 0; changed_line_abv_curs(); /* assume cursor position needs updating */ - // The new directory is either the local directory of the window, of the tab - // or NULL. - char_u *new_dir = curwin->w_localdir ? curwin->w_localdir : curtab->localdir; + // New directory is either the local directory of the window, tab or NULL. + char *new_dir = (char *)(curwin->w_localdir + ? curwin->w_localdir : curtab->tp_localdir); + + char cwd[MAXPATHL]; + if (os_dirname((char_u *)cwd, MAXPATHL) != OK) { + cwd[0] = NUL; + } if (new_dir) { // Window/tab has a local directory: Save current directory as global - // directory (unless that was done already) and change to the local - // directory. + // (unless that was done already) and change to the local directory. if (globaldir == NULL) { - char_u cwd[MAXPATHL]; - - if (os_dirname(cwd, MAXPATHL) == OK) { - globaldir = vim_strsave(cwd); + if (cwd[0] != NUL) { + globaldir = (char_u *)xstrdup(cwd); } } - if (os_chdir((char *)new_dir) == 0) { + if (os_chdir(new_dir) == 0) { + if (!p_acd && !strequal(new_dir, cwd)) { + do_autocmd_dirchanged(new_dir, curwin->w_localdir + ? kCdScopeWindow : kCdScopeTab); + } shorten_fnames(true); } } else if (globaldir != NULL) { - /* Window doesn't have a local directory and we are not in the global - * directory: Change to the global directory. */ - ignored = os_chdir((char *)globaldir); + // Window doesn't have a local directory and we are not in the global + // directory: Change to the global directory. + if (os_chdir((char *)globaldir) == 0) { + if (!p_acd && !strequal((char *)globaldir, cwd)) { + do_autocmd_dirchanged((char *)globaldir, kCdScopeGlobal); + } + } xfree(globaldir); globaldir = NULL; shorten_fnames(TRUE); } + if (trigger_new_autocmds) { + apply_autocmds(EVENT_WINNEW, NULL, NULL, false, curbuf); + } if (trigger_enter_autocmds) { apply_autocmds(EVENT_WINENTER, NULL, NULL, FALSE, curbuf); if (other_buffer) @@ -3642,6 +3725,12 @@ static void win_enter_ext(win_T *wp, bool undo_sync, int curwin_invalid, int tri if (restart_edit) redraw_later(VALID); /* causes status line redraw */ + if (hl_attr(HLF_INACTIVE) + || (prevwin && prevwin->w_hl_ids[HLF_INACTIVE]) + || curwin->w_hl_ids[HLF_INACTIVE]) { + redraw_all_later(NOT_VALID); + } + /* set window height to desired minimal value */ if (curwin->w_height < p_wh && !curwin->w_p_wfh) win_setheight((int)p_wh); @@ -3735,8 +3824,8 @@ static win_T *win_alloc(win_T *after, int hidden) new_wp->handle = ++last_win_id; handle_register_window(new_wp); - /* init w: variables */ - new_wp->w_vars = dict_alloc(); + // Init w: variables. + new_wp->w_vars = tv_dict_alloc(); init_var_dict(new_wp->w_vars, &new_wp->w_winvar, VAR_SCOPE); /* Don't execute autocommands while the window is not properly @@ -4700,8 +4789,6 @@ void set_fraction(win_T *wp) */ void win_new_height(win_T *wp, int height) { - linenr_T lnum; - int sline, line_size; int prev_height = wp->w_height; /* Don't want a negative height. Happens when splitting a tiny window. @@ -4728,6 +4815,19 @@ void win_new_height(win_T *wp, int height) wp->w_height = height; wp->w_skipcol = 0; + // There is no point in adjusting the scroll position when exiting. Some + // values might be invalid. + if (!exiting) { + scroll_to_fraction(wp, prev_height); + } +} + +void scroll_to_fraction(win_T *wp, int prev_height) +{ + linenr_T lnum; + int sline, line_size; + int height = wp->w_height; + /* Don't change w_topline when height is zero. Don't set w_topline when * 'scrollbind' is set and this isn't the current window. */ if (height > 0 @@ -4824,7 +4924,7 @@ void win_new_height(win_T *wp, int height) if (wp->w_buffer->terminal) { terminal_resize(wp->w_buffer->terminal, 0, wp->w_height); - redraw_win_later(wp, CLEAR); + redraw_win_later(wp, NOT_VALID); } } @@ -4848,7 +4948,6 @@ void win_new_width(win_T *wp, int width) if (wp->w_height != 0) { terminal_resize(wp->w_buffer->terminal, wp->w_width, 0); } - redraw_win_later(wp, CLEAR); } } @@ -5077,7 +5176,7 @@ last_status ( { /* Don't make a difference between horizontal or vertical split. */ last_status_rec(topframe, (p_ls == 2 - || (p_ls == 1 && (morewin || lastwin != firstwin)))); + || (p_ls == 1 && (morewin || !ONE_WINDOW)))); } static void last_status_rec(frame_T *fr, int statusline) @@ -5134,6 +5233,9 @@ static void last_status_rec(frame_T *fr, int statusline) */ int tabline_height(void) { + if (ui_is_external(kUITabline)) { + return 0; + } assert(first_tabpage); switch (p_stal) { case 0: return 0; @@ -5283,10 +5385,8 @@ restore_snapshot ( clear_snapshot(curtab, idx); } -/* - * Check if frames "sn" and "fr" have the same layout, same following frames - * and same children. - */ +/// Check if frames "sn" and "fr" have the same layout, same following frames +/// and same children. And the window pointer is valid. static int check_snapshot_rec(frame_T *sn, frame_T *fr) { if (sn->fr_layout != fr->fr_layout @@ -5295,7 +5395,8 @@ static int check_snapshot_rec(frame_T *sn, frame_T *fr) || (sn->fr_next != NULL && check_snapshot_rec(sn->fr_next, fr->fr_next) == FAIL) || (sn->fr_child != NULL - && check_snapshot_rec(sn->fr_child, fr->fr_child) == FAIL)) + && check_snapshot_rec(sn->fr_child, fr->fr_child) == FAIL) + || (sn->fr_win != NULL && !win_valid(sn->fr_win))) return FAIL; return OK; } @@ -5386,44 +5487,45 @@ void restore_win(win_T *save_curwin, tabpage_T *save_curtab, int no_display) unblock_autocmds(); } -/* - * Make "buf" the current buffer. restore_buffer() MUST be called to undo. - * No autocommands will be executed. Use aucmd_prepbuf() if there are any. - */ -void switch_buffer(buf_T **save_curbuf, buf_T *buf) +/// Make "buf" the current buffer. +/// +/// restore_buffer() MUST be called to undo. +/// No autocommands will be executed. Use aucmd_prepbuf() if there are any. +void switch_buffer(bufref_T *save_curbuf, buf_T *buf) { block_autocmds(); - *save_curbuf = curbuf; - --curbuf->b_nwindows; + set_bufref(save_curbuf, curbuf); + curbuf->b_nwindows--; curbuf = buf; curwin->w_buffer = buf; - ++curbuf->b_nwindows; + curbuf->b_nwindows++; } -/* - * Restore the current buffer after using switch_buffer(). - */ -void restore_buffer(buf_T *save_curbuf) +/// Restore the current buffer after using switch_buffer(). +void restore_buffer(bufref_T *save_curbuf) { unblock_autocmds(); - /* Check for valid buffer, just in case. */ - if (buf_valid(save_curbuf)) { - --curbuf->b_nwindows; - curwin->w_buffer = save_curbuf; - curbuf = save_curbuf; - ++curbuf->b_nwindows; + // Check for valid buffer, just in case. + if (bufref_valid(save_curbuf)) { + curbuf->b_nwindows--; + curwin->w_buffer = save_curbuf->br_buf; + curbuf = save_curbuf->br_buf; + curbuf->b_nwindows++; } } -// Add match to the match list of window 'wp'. The pattern 'pat' will be -// highlighted with the group 'grp' with priority 'prio'. -// Optionally, a desired ID 'id' can be specified (greater than or equal to 1). -// If no particular ID is desired, -1 must be specified for 'id'. -// Return ID of added match, -1 on failure. -int match_add(win_T *wp, char_u *grp, char_u *pat, +/// Add match to the match list of window 'wp'. The pattern 'pat' will be +/// highlighted with the group 'grp' with priority 'prio'. +/// Optionally, a desired ID 'id' can be specified (greater than or equal to 1). +/// +/// @param[in] id a desired ID 'id' can be specified +/// (greater than or equal to 1). -1 must be specified if no +/// particular ID is desired +/// @return ID of added match, -1 on failure. +int match_add(win_T *wp, const char *const grp, const char *const pat, int prio, int id, list_T *pos_list, - char_u *conceal_char) + const char *const conceal_char) { matchitem_T *cur; matchitem_T *prev; @@ -5436,8 +5538,8 @@ int match_add(win_T *wp, char_u *grp, char_u *pat, return -1; } if (id < -1 || id == 0) { - EMSGN("E799: Invalid ID: %" PRId64 - " (must be greater than or equal to 1)", + EMSGN(_("E799: Invalid ID: %" PRId64 + " (must be greater than or equal to 1)"), id); return -1; } @@ -5445,17 +5547,17 @@ int match_add(win_T *wp, char_u *grp, char_u *pat, cur = wp->w_match_head; while (cur != NULL) { if (cur->id == id) { - EMSGN("E801: ID already taken: %" PRId64, id); + EMSGN(_("E801: ID already taken: %" PRId64), id); return -1; } cur = cur->next; } } - if ((hlg_id = syn_namen2id(grp, (int)STRLEN(grp))) == 0) { + if ((hlg_id = syn_name2id((const char_u *)grp)) == 0) { EMSG2(_(e_nogroup), grp); return -1; } - if (pat != NULL && (regprog = vim_regcomp(pat, RE_MAGIC)) == NULL) { + if (pat != NULL && (regprog = vim_regcomp((char_u *)pat, RE_MAGIC)) == NULL) { EMSG2(_(e_invarg2), pat); return -1; } @@ -5474,14 +5576,14 @@ int match_add(win_T *wp, char_u *grp, char_u *pat, m = xcalloc(1, sizeof(matchitem_T)); m->id = id; m->priority = prio; - m->pattern = pat == NULL ? NULL: vim_strsave(pat); + m->pattern = pat == NULL ? NULL: (char_u *)xstrdup(pat); m->hlg_id = hlg_id; m->match.regprog = regprog; m->match.rmm_ic = FALSE; m->match.rmm_maxcol = 0; m->conceal_char = 0; if (conceal_char != NULL) { - m->conceal_char = (*mb_ptr2char)(conceal_char); + m->conceal_char = (*mb_ptr2char)((const char_u *)conceal_char); } // Set up position matches @@ -5499,7 +5601,7 @@ int match_add(win_T *wp, char_u *grp, char_u *pat, int len = 1; list_T *subl; listitem_T *subli; - int error = false; + bool error = false; if (li->li_tv.v_type == VAR_LIST) { subl = li->li_tv.vval.v_list; @@ -5510,8 +5612,8 @@ int match_add(win_T *wp, char_u *grp, char_u *pat, if (subli == NULL) { goto fail; } - lnum = get_tv_number_chk(&subli->li_tv, &error); - if (error == true) { + lnum = tv_get_number_chk(&subli->li_tv, &error); + if (error) { goto fail; } if (lnum == 0) { @@ -5521,13 +5623,14 @@ int match_add(win_T *wp, char_u *grp, char_u *pat, m->pos.pos[i].lnum = lnum; subli = subli->li_next; if (subli != NULL) { - col = get_tv_number_chk(&subli->li_tv, &error); - if (error == true) + col = tv_get_number_chk(&subli->li_tv, &error); + if (error) { goto fail; + } subli = subli->li_next; if (subli != NULL) { - len = get_tv_number_chk(&subli->li_tv, &error); - if (error == true) { + len = tv_get_number_chk(&subli->li_tv, &error); + if (error) { goto fail; } } @@ -5597,10 +5700,9 @@ fail: return -1; } -/* - * Delete match with ID 'id' in the match list of window 'wp'. - * Print error messages if 'perr' is TRUE. - */ + +/// Delete match with ID 'id' in the match list of window 'wp'. +/// Print error messages if 'perr' is TRUE. int match_delete(win_T *wp, int id, int perr) { matchitem_T *cur = wp->w_match_head; @@ -5608,10 +5710,11 @@ int match_delete(win_T *wp, int id, int perr) int rtype = SOME_VALID; if (id < 1) { - if (perr == TRUE) - EMSGN("E802: Invalid ID: %" PRId64 - " (must be greater than or equal to 1)", + if (perr) { + EMSGN(_("E802: Invalid ID: %" PRId64 + " (must be greater than or equal to 1)"), id); + } return -1; } while (cur != NULL && cur->id != id) { @@ -5619,8 +5722,9 @@ int match_delete(win_T *wp, int id, int perr) cur = cur->next; } if (cur == NULL) { - if (perr == TRUE) - EMSGN("E803: ID not found: %" PRId64, id); + if (perr) { + EMSGN(_("E803: ID not found: %" PRId64), id); + } return -1; } if (cur == prev) @@ -5726,23 +5830,28 @@ int win_getid(typval_T *argvars) if (argvars[0].v_type == VAR_UNKNOWN) { return curwin->handle; } - int winnr = get_tv_number(&argvars[0]); + int winnr = tv_get_number(&argvars[0]); win_T *wp; if (winnr > 0) { if (argvars[1].v_type == VAR_UNKNOWN) { wp = firstwin; } else { - tabpage_T *tp; - int tabnr = get_tv_number(&argvars[1]); - for (tp = first_tabpage; tp != NULL; tp = tp->tp_next) { + tabpage_T *tp = NULL; + int tabnr = tv_get_number(&argvars[1]); + FOR_ALL_TABS(tp2) { if (--tabnr == 0) { + tp = tp2; break; } } if (tp == NULL) { return -1; } - wp = tp->tp_firstwin; + if (tp == curtab) { + wp = firstwin; + } else { + wp = tp->tp_firstwin; + } } for ( ; wp != NULL; wp = wp->w_next) { if (--winnr == 0) { @@ -5755,7 +5864,7 @@ int win_getid(typval_T *argvars) int win_gotoid(typval_T *argvars) { - int id = get_tv_number(&argvars[0]); + int id = tv_get_number(&argvars[0]); FOR_ALL_TAB_WINDOWS(tp, wp) { if (wp->handle == id) { @@ -5790,16 +5899,16 @@ void win_id2tabwin(typval_T *argvars, list_T *list) { int winnr = 1; int tabnr = 1; - int id = get_tv_number(&argvars[0]); + handle_T id = (handle_T)tv_get_number(&argvars[0]); win_get_tabwin(id, &tabnr, &winnr); - list_append_number(list, tabnr); - list_append_number(list, winnr); + tv_list_append_number(list, tabnr); + tv_list_append_number(list, winnr); } win_T * win_id2wp(typval_T *argvars) { - int id = get_tv_number(&argvars[0]); + int id = tv_get_number(&argvars[0]); FOR_ALL_TAB_WINDOWS(tp, wp) { if (wp->handle == id) { @@ -5812,11 +5921,10 @@ win_T * win_id2wp(typval_T *argvars) int win_id2win(typval_T *argvars) { - win_T *wp; int nr = 1; - int id = get_tv_number(&argvars[0]); + int id = tv_get_number(&argvars[0]); - for (wp = firstwin; wp != NULL; wp = wp->w_next) { + FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { if (wp->handle == id) { return nr; } @@ -5827,14 +5935,11 @@ int win_id2win(typval_T *argvars) void win_findbuf(typval_T *argvars, list_T *list) { - int bufnr = get_tv_number(&argvars[0]); + int bufnr = tv_get_number(&argvars[0]); - for (tabpage_T *tp = first_tabpage; tp != NULL; tp = tp->tp_next) { - for (win_T *wp = tp == curtab ? firstwin : tp->tp_firstwin; - wp != NULL; wp = wp->w_next) { - if (wp->w_buffer->b_fnum == bufnr) { - list_append_number(list, wp->handle); - } + FOR_ALL_TAB_WINDOWS(tp, wp) { + if (wp->w_buffer->b_fnum == bufnr) { + tv_list_append_number(list, wp->handle); } } } diff --git a/src/nvim/window.h b/src/nvim/window.h index 2ac4c00c28..82b3fe5e88 100644 --- a/src/nvim/window.h +++ b/src/nvim/window.h @@ -3,6 +3,8 @@ #include <stdbool.h> +#include "nvim/buffer_defs.h" + /* Values for file_name_in_line() */ #define FNAME_MESS 1 /* give error message */ #define FNAME_EXP 2 /* expand to path */ diff --git a/test/.luacheckrc b/test/.luacheckrc index 1c98d096a4..034b4f10df 100644 --- a/test/.luacheckrc +++ b/test/.luacheckrc @@ -12,5 +12,9 @@ self = false -- Rerun tests only if their modification time changed. cache = true +ignore = { + "631", -- max_line_length +} + -- Ignore whitespace issues in converted Vim legacy tests. files["functional/legacy"] = {ignore = { "611", "612", "613", "621" }} diff --git a/test/README.md b/test/README.md new file mode 100644 index 0000000000..01db5960cd --- /dev/null +++ b/test/README.md @@ -0,0 +1,112 @@ +# Tests + +Tests are run by `/cmake/RunTests.cmake` file, using busted. + +For some failures, `.nvimlog` (or `$NVIM_LOG_FILE`) may provide insight. + +## Directory structure + +Directories with tests: `/test/benchmark` for benchmarks, `/test/functional` for +functional tests, `/test/unit` for unit tests. `/test/config` contains `*.in` +files (currently a single one) which are transformed into `*.lua` files using +`configure_file` CMake command: this is for acessing CMake variables in lua +tests. `/test/includes` contains include files for use by luajit `ffi.cdef` +C definitions parser: normally used to make macros not accessible via this +mechanism accessible the other way. + +Files `/test/*/preload.lua` contain modules which will be preloaded by busted, +via `--helper` option. `/test/**/helpers.lua` contain various โlibraryโ +functions, (intended to be) used by a number of tests and not just a single one. + +`/test/*/**/*_spec.lua` are files containing actual tests. Files that do not end +with a `_spec.lua` are libraries like `/test/**/helpers.lua`, except that they +have some common topic. + +Tests inside `/test/unit` and `/test/functional` are normally divided into +groups by the semantic component they are testing. + +## Environment variables + +Test behaviour is affected by environment variables. Currently supported +(Functional, Unit, Benchmarks) (when Defined; when set to _1_; when defined, +treated as Integer; when defined, treated as String; when defined, treated as +Number; !must be defined to function properly): + +`GDB` (F) (D): makes nvim instances to be run under `gdbserver`. It will be +accessible on `localhost:7777`: use `gdb build/bin/nvim`, type `target remote +:7777` inside. + +`GDBSERVER_PORT` (F) (I): overrides port used for `GDB`. + +`VALGRIND` (F) (D): makes nvim instances to be run under `valgrind`. Log files +are named `valgrind-%p.log` in this case. Note that non-empty valgrind log may +fail tests. Valgrind arguments may be seen in `/test/functional/helpers.lua`. +May be used in conjunction with `GDB`. + +`VALGRIND_LOG` (F) (S): overrides valgrind log file name used for `VALGRIND`. + +`TEST_SKIP_FRAGILE` (F) (D): makes test suite skip some fragile tests. + +`NVIM_PROG`, `NVIM_PRG` (F) (S): override path to Neovim executable (default to +`build/bin/nvim`). + +`CC` (U) (S): specifies which C compiler to use to preprocess files. Currently +only compilers with gcc-compatible arguments are supported. + +`NVIM_TEST_MAIN_CDEFS` (U) (1): makes `ffi.cdef` run in main process. This +raises a possibility of bugs due to conflicts in header definitions, despite the +counters, but greatly speeds up unit tests by not requiring `ffi.cdef` to do +parsing of big strings with C definitions. + +`NVIM_TEST_PRINT_I` (U) (1): makes `cimport` print preprocessed, but not yet +filtered through `formatc` headers. Used to debug `formatc`. Printing is done +with the line numbers. + +`NVIM_TEST_PRINT_CDEF` (U) (1): makes `cimport` print final lines which will be +then passed to `ffi.cdef`. Used to debug errors `ffi.cdef` happens to throw +sometimes. + +`NVIM_TEST_PRINT_SYSCALLS` (U) (1): makes it print to stderr when syscall +wrappers are called and what they returned. Used to debug code which makes unit +tests be executed in separate processes. + +`NVIM_TEST_RUN_FAILING_TESTS` (U) (1): makes `itp` run tests which are known to +fail (marked by setting third argument to `true`). + +`LOG_DIR` (FU) (S!): specifies where to seek for valgrind and ASAN log files. + +`NVIM_TEST_CORE_*` (FU) (S): a set of environment variables which specify where +to search for core files. Are supposed to be defined all at once. + +`NVIM_TEST_CORE_GLOB_DIRECTORY` (FU) (S): directory where core files are +located. May be `.`. This directory is then recursively searched for core files. +Note: this variable must be defined for any of the following to have any effect. + +`NVIM_TEST_CORE_GLOB_RE` (FU) (S): regular expression which must be matched by +core files. E.g. `/core[^/]*$`. May be absent, in which case any file is +considered to be matched. + +`NVIM_TEST_CORE_EXC_RE` (FU) (S): regular expression which excludes certain +directories from searching for core files inside. E.g. use `^/%.deps$` to not +search inside `/.deps`. If absent, nothing is excluded. + +`NVIM_TEST_CORE_DB_CMD` (FU) (S): command to get backtrace out of the debugger. +E.g. `gdb -n -batch -ex "thread apply all bt full" "$_NVIM_TEST_APP" -c +"$_NVIM_TEST_CORE"`. Defaults to the example command. This debug command may use +environment variables `_NVIM_TEST_APP` (path to application which is being +debugged: normally either nvim or luajit) and `_NVIM_TEST_CORE` (core file to +get backtrace from). + +`NVIM_TEST_CORE_RANDOM_SKIP` (FU) (D): makes `check_cores` not check cores after +approximately 90% of the tests. Should be used when finding cores is too hard +for some reason. Normally (on OS X or when `NVIM_TEST_CORE_GLOB_DIRECTORY` is +defined and this variable is not) cores are checked for after each test. + +`NVIM_TEST_RUN_TESTTEST` (U) (1): allows running `test/unit/testtest_spec.lua` +used to check how testing infrastructure works. + +`NVIM_TEST_TRACE_LEVEL` (U) (N): specifies unit tests tracing level: `0` +disables tracing (the fastest, but you get no data if tests crash and there was +no core dump generated), `1` or empty/undefined leaves only C function cals and +returns in the trace (faster then recording everything), `2` records all +function calls, returns and lua source lines exuecuted. diff --git a/test/benchmark/bench_re_freeze_spec.lua b/test/benchmark/bench_re_freeze_spec.lua index 53041b042b..ea41953014 100644 --- a/test/benchmark/bench_re_freeze_spec.lua +++ b/test/benchmark/bench_re_freeze_spec.lua @@ -1,8 +1,8 @@ -- Test for benchmarking RE engine. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local insert, source = helpers.insert, helpers.source -local clear, execute, wait = helpers.clear, helpers.execute, helpers.wait +local clear, command = helpers.clear, helpers.command -- Temporary file for gathering benchmarking results for each regexp engine. local result_file = 'benchmark.out' @@ -31,7 +31,7 @@ describe('regexp search', function() clear() source(measure_script) insert('" Benchmark_results:') - execute('write! ' .. result_file) + command('write! ' .. result_file) end) -- At the end of the test run we just print the contents of the result file @@ -46,22 +46,19 @@ describe('regexp search', function() it('is working with regexpengine=0', function() local regexpengine = 0 - execute(string.format(measure_cmd, regexpengine)) - execute('write') - wait() + command(string.format(measure_cmd, regexpengine)) + command('write') end) it('is working with regexpengine=1', function() local regexpengine = 1 - execute(string.format(measure_cmd, regexpengine)) - execute('write') - wait() + command(string.format(measure_cmd, regexpengine)) + command('write') end) it('is working with regexpengine=2', function() local regexpengine = 2 - execute(string.format(measure_cmd, regexpengine)) - execute('write') - wait() + command(string.format(measure_cmd, regexpengine)) + command('write') end) end) diff --git a/test/config/paths.lua.in b/test/config/paths.lua.in index 80cc5629d1..7fe5d8ad80 100644 --- a/test/config/paths.lua.in +++ b/test/config/paths.lua.in @@ -5,9 +5,19 @@ for p in ("${TEST_INCLUDE_DIRS}" .. ";"):gmatch("[^;]+") do table.insert(module.include_paths, p) end -module.test_include_path = "${CMAKE_BINARY_DIR}/test/includes/post" +module.test_build_dir = "${CMAKE_BINARY_DIR}" +module.test_include_path = module.test_build_dir .. "/test/includes/post" module.test_libnvim_path = "${TEST_LIBNVIM_PATH}" module.test_source_path = "${CMAKE_SOURCE_DIR}" +module.test_lua_prg = "${LUA_PRG}" +module.test_luajit_prg = "" +if module.test_luajit_prg == '' then + if module.test_lua_prg:sub(-6) == 'luajit' then + module.test_luajit_prg = module.test_lua_prg + else + module.test_luajit_prg = nil + end +end table.insert(module.include_paths, "${CMAKE_BINARY_DIR}/include") return module diff --git a/test/functional/api/buffer_spec.lua b/test/functional/api/buffer_spec.lua index 3d3a2bb046..823c134ebd 100644 --- a/test/functional/api/buffer_spec.lua +++ b/test/functional/api/buffer_spec.lua @@ -2,8 +2,15 @@ local helpers = require('test.functional.helpers')(after_each) local clear, nvim, buffer = helpers.clear, helpers.nvim, helpers.buffer local curbuf, curwin, eq = helpers.curbuf, helpers.curwin, helpers.eq local curbufmeths, ok = helpers.curbufmeths, helpers.ok -local funcs, request = helpers.funcs, helpers.request +local funcs = helpers.funcs +local request = helpers.request +local exc_exec = helpers.exc_exec +local feed_command = helpers.feed_command +local insert = helpers.insert local NIL = helpers.NIL +local meth_pcall = helpers.meth_pcall +local command = helpers.command +local bufmeths = helpers.bufmeths describe('api/buf', function() before_each(clear) @@ -115,6 +122,15 @@ describe('api/buf', function() local get_lines, set_lines = curbufmeths.get_lines, curbufmeths.set_lines local line_count = curbufmeths.line_count + it('fails correctly when input is not valid', function() + eq(1, curbufmeths.get_number()) + local err, emsg = pcall(bufmeths.set_lines, 1, 1, 2, false, {'b\na'}) + eq(false, err) + local exp_emsg = 'String cannot contain newlines' + -- Expected {filename}:{lnum}: {exp_emsg} + eq(': ' .. exp_emsg, emsg:sub(-#exp_emsg - 2)) + end) + it('has correct line_count when inserting and deleting', function() eq(1, line_count()) set_lines(-1, -1, true, {'line'}) @@ -239,6 +255,22 @@ describe('api/buf', function() eq({'e', 'a', 'b', 'c', 'd'}, get_lines(0, -1, true)) end) + it("set_line on alternate buffer does not access invalid line (E315)", function() + feed_command('set hidden') + insert('Initial file') + command('enew') + insert([[ + More + Lines + Than + In + The + Other + Buffer]]) + feed_command('$') + local retval = exc_exec("call nvim_buf_set_lines(1, 0, 1, v:false, ['test'])") + eq(0, retval) + end) end) describe('{get,set,del}_var', function() @@ -249,6 +281,24 @@ describe('api/buf', function() eq(1, funcs.exists('b:lua')) curbufmeths.del_var('lua') eq(0, funcs.exists('b:lua')) + eq({false, 'Key does not exist: lua'}, meth_pcall(curbufmeths.del_var, 'lua')) + curbufmeths.set_var('lua', 1) + command('lockvar b:lua') + eq({false, 'Key is locked: lua'}, meth_pcall(curbufmeths.del_var, 'lua')) + eq({false, 'Key is locked: lua'}, meth_pcall(curbufmeths.set_var, 'lua', 1)) + eq({false, 'Key is read-only: changedtick'}, + meth_pcall(curbufmeths.del_var, 'changedtick')) + eq({false, 'Key is read-only: changedtick'}, + meth_pcall(curbufmeths.set_var, 'changedtick', 1)) + end) + end) + + describe('get_changedtick', function() + it('works', function() + eq(2, curbufmeths.get_changedtick()) + curbufmeths.set_lines(0, 1, false, {'abc\0', '\0def', 'ghi'}) + eq(3, curbufmeths.get_changedtick()) + eq(3, curbufmeths.get_var('changedtick')) end) it('buffer_set_var returns the old value', function() diff --git a/test/functional/api/keymap_spec.lua b/test/functional/api/keymap_spec.lua new file mode 100644 index 0000000000..3a10f9c60f --- /dev/null +++ b/test/functional/api/keymap_spec.lua @@ -0,0 +1,310 @@ +local helpers = require('test.functional.helpers')(after_each) +local global_helpers = require('test.helpers') + +local clear = helpers.clear +local command = helpers.command +local curbufmeths = helpers.curbufmeths +local eq = helpers.eq +local funcs = helpers.funcs +local meths = helpers.meths +local source = helpers.source + +local shallowcopy = global_helpers.shallowcopy + +describe('get_keymap', function() + before_each(clear) + + -- Basic mapping and table to be used to describe results + local foo_bar_string = 'nnoremap foo bar' + local foo_bar_map_table = { + lhs='foo', + silent=0, + rhs='bar', + expr=0, + sid=0, + buffer=0, + nowait=0, + mode='n', + noremap=1, + } + + it('returns empty list when no map', function() + eq({}, meths.get_keymap('n')) + end) + + it('returns list of all applicable mappings', function() + command(foo_bar_string) + -- Only one mapping available + -- Should be the same as the dictionary we supplied earlier + -- and the dictionary you would get from maparg + -- since this is a global map, and not script local + eq({foo_bar_map_table}, meths.get_keymap('n')) + eq({funcs.maparg('foo', 'n', false, true)}, + meths.get_keymap('n') + ) + + -- Add another mapping + command('nnoremap foo_longer bar_longer') + local foolong_bar_map_table = shallowcopy(foo_bar_map_table) + foolong_bar_map_table['lhs'] = 'foo_longer' + foolong_bar_map_table['rhs'] = 'bar_longer' + + eq({foolong_bar_map_table, foo_bar_map_table}, + meths.get_keymap('n') + ) + + -- Remove a mapping + command('unmap foo_longer') + eq({foo_bar_map_table}, + meths.get_keymap('n') + ) + end) + + it('works for other modes', function() + -- Add two mappings, one in insert and one normal + -- We'll only check the insert mode one + command('nnoremap not_going to_check') + + command('inoremap foo bar') + -- The table will be the same except for the mode + local insert_table = shallowcopy(foo_bar_map_table) + insert_table['mode'] = 'i' + + eq({insert_table}, meths.get_keymap('i')) + end) + + it('considers scope', function() + -- change the map slightly + command('nnoremap foo_longer bar_longer') + local foolong_bar_map_table = shallowcopy(foo_bar_map_table) + foolong_bar_map_table['lhs'] = 'foo_longer' + foolong_bar_map_table['rhs'] = 'bar_longer' + + local buffer_table = shallowcopy(foo_bar_map_table) + buffer_table['buffer'] = 1 + + command('nnoremap <buffer> foo bar') + + -- The buffer mapping should not show up + eq({foolong_bar_map_table}, meths.get_keymap('n')) + eq({buffer_table}, curbufmeths.get_keymap('n')) + end) + + it('considers scope for overlapping maps', function() + command('nnoremap foo bar') + + local buffer_table = shallowcopy(foo_bar_map_table) + buffer_table['buffer'] = 1 + + command('nnoremap <buffer> foo bar') + + eq({foo_bar_map_table}, meths.get_keymap('n')) + eq({buffer_table}, curbufmeths.get_keymap('n')) + end) + + it('can retrieve mapping for different buffers', function() + local original_buffer = curbufmeths.get_number() + -- Place something in each of the buffers to make sure they stick around + -- and set hidden so we can leave them + command('set hidden') + command('new') + command('normal! ihello 2') + command('new') + command('normal! ihello 3') + + local final_buffer = curbufmeths.get_number() + + command('nnoremap <buffer> foo bar') + -- Final buffer will have buffer mappings + local buffer_table = shallowcopy(foo_bar_map_table) + buffer_table['buffer'] = final_buffer + eq({buffer_table}, meths.buf_get_keymap(final_buffer, 'n')) + eq({buffer_table}, meths.buf_get_keymap(0, 'n')) + + command('buffer ' .. original_buffer) + eq(original_buffer, curbufmeths.get_number()) + -- Original buffer won't have any mappings + eq({}, meths.get_keymap('n')) + eq({}, curbufmeths.get_keymap('n')) + eq({buffer_table}, meths.buf_get_keymap(final_buffer, 'n')) + end) + + -- Test toggle switches for basic options + -- @param option The key represented in the `maparg()` result dict + local function global_and_buffer_test(map, + option, + option_token, + global_on_result, + buffer_on_result, + global_off_result, + buffer_off_result, + new_windows) + + local function make_new_windows(number_of_windows) + if new_windows == nil then + return nil + end + + for _=1,number_of_windows do + command('new') + end + end + + local mode = string.sub(map, 1,1) + -- Don't run this for the <buffer> mapping, since it doesn't make sense + if option_token ~= '<buffer>' then + it(string.format( 'returns %d for the key "%s" when %s is used globally with %s (%s)', + global_on_result, option, option_token, map, mode), function() + make_new_windows(new_windows) + command(map .. ' ' .. option_token .. ' foo bar') + local result = meths.get_keymap(mode)[1][option] + eq(global_on_result, result) + end) + end + + it(string.format('returns %d for the key "%s" when %s is used for buffers with %s (%s)', + buffer_on_result, option, option_token, map, mode), function() + make_new_windows(new_windows) + command(map .. ' <buffer> ' .. option_token .. ' foo bar') + local result = curbufmeths.get_keymap(mode)[1][option] + eq(buffer_on_result, result) + end) + + -- Don't run these for the <buffer> mapping, since it doesn't make sense + if option_token ~= '<buffer>' then + it(string.format('returns %d for the key "%s" when %s is not used globally with %s (%s)', + global_off_result, option, option_token, map, mode), function() + make_new_windows(new_windows) + command(map .. ' baz bat') + local result = meths.get_keymap(mode)[1][option] + eq(global_off_result, result) + end) + + it(string.format('returns %d for the key "%s" when %s is not used for buffers with %s (%s)', + buffer_off_result, option, option_token, map, mode), function() + make_new_windows(new_windows) + command(map .. ' <buffer> foo bar') + + local result = curbufmeths.get_keymap(mode)[1][option] + eq(buffer_off_result, result) + end) + end + end + + -- Standard modes and returns the same values in the dictionary as maparg() + local mode_list = {'nnoremap', 'nmap', 'imap', 'inoremap', 'cnoremap'} + for mode in pairs(mode_list) do + global_and_buffer_test(mode_list[mode], 'silent', '<silent>', 1, 1, 0, 0) + global_and_buffer_test(mode_list[mode], 'nowait', '<nowait>', 1, 1, 0, 0) + global_and_buffer_test(mode_list[mode], 'expr', '<expr>', 1, 1, 0, 0) + end + + -- noremap will now be 2 if script was used, which is not the same as maparg() + global_and_buffer_test('nmap', 'noremap', '<script>', 2, 2, 0, 0) + global_and_buffer_test('nnoremap', 'noremap', '<script>', 2, 2, 1, 1) + + -- buffer will return the buffer ID, which is not the same as maparg() + -- Three of these tests won't run + global_and_buffer_test('nnoremap', 'buffer', '<buffer>', nil, 3, nil, nil, 2) + + it('returns script numbers for global maps', function() + source([[ + function! s:maparg_test_function() abort + return 'testing' + endfunction + + nnoremap fizz :call <SID>maparg_test_function()<CR> + ]]) + local sid_result = meths.get_keymap('n')[1]['sid'] + eq(1, sid_result) + eq('testing', meths.call_function('<SNR>' .. sid_result .. '_maparg_test_function', {})) + end) + + it('returns script numbers for buffer maps', function() + source([[ + function! s:maparg_test_function() abort + return 'testing' + endfunction + + nnoremap <buffer> fizz :call <SID>maparg_test_function()<CR> + ]]) + local sid_result = curbufmeths.get_keymap('n')[1]['sid'] + eq(1, sid_result) + eq('testing', meths.call_function('<SNR>' .. sid_result .. '_maparg_test_function', {})) + end) + + it('works with <F12> and others', function() + command('nnoremap <F12> :let g:maparg_test_var = 1<CR>') + eq('<F12>', meths.get_keymap('n')[1]['lhs']) + eq(':let g:maparg_test_var = 1<CR>', meths.get_keymap('n')[1]['rhs']) + end) + + it('works correctly despite various &cpo settings', function() + local cpo_table = { + silent=0, + expr=0, + sid=0, + buffer=0, + nowait=0, + noremap=1, + } + local function cpomap(lhs, rhs, mode) + local ret = shallowcopy(cpo_table) + ret.lhs = lhs + ret.rhs = rhs + ret.mode = mode + return ret + end + + command('set cpo+=B') + command('nnoremap \\<C-a><C-a><LT>C-a>\\ \\<C-b><C-b><LT>C-b>\\') + command('nnoremap <special> \\<C-c><C-c><LT>C-c>\\ \\<C-d><C-d><LT>C-d>\\') + + command('set cpo+=B') + command('xnoremap \\<C-a><C-a><LT>C-a>\\ \\<C-b><C-b><LT>C-b>\\') + command('xnoremap <special> \\<C-c><C-c><LT>C-c>\\ \\<C-d><C-d><LT>C-d>\\') + + command('set cpo-=B') + command('snoremap \\<C-a><C-a><LT>C-a>\\ \\<C-b><C-b><LT>C-b>\\') + command('snoremap <special> \\<C-c><C-c><LT>C-c>\\ \\<C-d><C-d><LT>C-d>\\') + + command('set cpo-=B') + command('onoremap \\<C-a><C-a><LT>C-a>\\ \\<C-b><C-b><LT>C-b>\\') + command('onoremap <special> \\<C-c><C-c><LT>C-c>\\ \\<C-d><C-d><LT>C-d>\\') + + for _, cmd in ipairs({ + 'set cpo-=B', + 'set cpo+=B', + }) do + command(cmd) + eq({cpomap('\\<C-C><C-C><lt>C-c>\\', '\\<C-D><C-D><lt>C-d>\\', 'n'), + cpomap('\\<C-A><C-A><lt>C-a>\\', '\\<C-B><C-B><lt>C-b>\\', 'n')}, + meths.get_keymap('n')) + eq({cpomap('\\<C-C><C-C><lt>C-c>\\', '\\<C-D><C-D><lt>C-d>\\', 'x'), + cpomap('\\<C-A><C-A><lt>C-a>\\', '\\<C-B><C-B><lt>C-b>\\', 'x')}, + meths.get_keymap('x')) + eq({cpomap('<lt>C-c><C-C><lt>C-c> ', '<lt>C-d><C-D><lt>C-d>', 's'), + cpomap('<lt>C-a><C-A><lt>C-a> ', '<lt>C-b><C-B><lt>C-b>', 's')}, + meths.get_keymap('s')) + eq({cpomap('<lt>C-c><C-C><lt>C-c> ', '<lt>C-d><C-D><lt>C-d>', 'o'), + cpomap('<lt>C-a><C-A><lt>C-a> ', '<lt>C-b><C-B><lt>C-b>', 'o')}, + meths.get_keymap('o')) + end + end) + + it('always uses space for space and bar for bar', function() + local space_table = { + lhs='| |', + rhs='| |', + mode='n', + silent=0, + expr=0, + sid=0, + buffer=0, + nowait=0, + noremap=1, + } + command('nnoremap \\|<Char-0x20><Char-32><Space><Bar> \\|<Char-0x20><Char-32><Space> <Bar>') + eq({space_table}, meths.get_keymap('n')) + end) +end) diff --git a/test/functional/api/server_notifications_spec.lua b/test/functional/api/server_notifications_spec.lua index 78639d7ed7..9d7cfb9b78 100644 --- a/test/functional/api/server_notifications_spec.lua +++ b/test/functional/api/server_notifications_spec.lua @@ -1,6 +1,6 @@ local helpers = require('test.functional.helpers')(after_each) -local eq, clear, eval, execute, nvim, next_message = - helpers.eq, helpers.clear, helpers.eval, helpers.execute, helpers.nvim, +local eq, clear, eval, command, nvim, next_message = + helpers.eq, helpers.clear, helpers.eval, helpers.command, helpers.nvim, helpers.next_message local meths = helpers.meths @@ -16,8 +16,8 @@ describe('notify', function() it('sends the notification/args to the corresponding channel', function() eval('rpcnotify('..channel..', "test-event", 1, 2, 3)') eq({'notification', 'test-event', {1, 2, 3}}, next_message()) - execute('au FileType lua call rpcnotify('..channel..', "lua!")') - execute('set filetype=lua') + command('au FileType lua call rpcnotify('..channel..', "lua!")') + command('set filetype=lua') eq({'notification', 'lua!', {}}, next_message()) end) end) diff --git a/test/functional/api/server_requests_spec.lua b/test/functional/api/server_requests_spec.lua index 3245e1b52d..9f245d913b 100644 --- a/test/functional/api/server_requests_spec.lua +++ b/test/functional/api/server_requests_spec.lua @@ -1,14 +1,16 @@ --- Tests for some server->client RPC scenarios. Note that unlike with --- `rpcnotify`, to evaluate `rpcrequest` calls we need the client event loop to --- be running. +-- Test server -> client RPC scenarios. Note: unlike `rpcnotify`, to evaluate +-- `rpcrequest` calls we need the client event loop to be running. local helpers = require('test.functional.helpers')(after_each) +local Paths = require('test.config.paths') + local clear, nvim, eval = helpers.clear, helpers.nvim, helpers.eval local eq, neq, run, stop = helpers.eq, helpers.neq, helpers.run, helpers.stop local nvim_prog, command, funcs = helpers.nvim_prog, helpers.command, helpers.funcs local source, next_message = helpers.source, helpers.next_message +local ok = helpers.ok local meths = helpers.meths - -if helpers.pending_win32(pending) then return end +local spawn, nvim_argv = helpers.spawn, helpers.nvim_argv +local set_session = helpers.set_session describe('server -> client', function() local cid @@ -18,6 +20,22 @@ describe('server -> client', function() cid = nvim('get_api_info')[1] end) + it('handles unexpected closed stream while preparing RPC response', function() + source([[ + let g:_nvim_args = [v:progpath, '--embed', '-n', '-u', 'NONE', '-i', 'NONE', ] + let ch1 = jobstart(g:_nvim_args, {'rpc': v:true}) + let child1_ch = rpcrequest(ch1, "nvim_get_api_info")[0] + call rpcnotify(ch1, 'nvim_eval', 'rpcrequest('.child1_ch.', "nvim_get_api_info")') + + let ch2 = jobstart(g:_nvim_args, {'rpc': v:true}) + let child2_ch = rpcrequest(ch2, "nvim_get_api_info")[0] + call rpcnotify(ch2, 'nvim_eval', 'rpcrequest('.child2_ch.', "nvim_get_api_info")') + + call jobstop(ch1) + ]]) + eq(2, eval("1+1")) -- Still alive? + end) + describe('simple call', function() it('works', function() local function on_setup() @@ -139,7 +157,7 @@ describe('server -> client', function() end) end) - describe('when the client is a recursive vim instance', function() + describe('recursive (child) nvim client', function() if os.getenv("TRAVIS") and helpers.os_name() == "osx" then -- XXX: Hangs Travis macOS since e9061117a5b8f195c3f26a5cb94e18ddd7752d86. pending("[Hangs on Travis macOS. #5002]", function() end) @@ -153,7 +171,7 @@ describe('server -> client', function() after_each(function() command('call rpcstop(vim)') end) - it('can send/recieve notifications and make requests', function() + it('can send/receive notifications and make requests', function() nvim('command', "call rpcnotify(vim, 'vim_set_current_line', 'SOME TEXT')") -- Wait for the notification to complete. @@ -182,11 +200,11 @@ describe('server -> client', function() it('returns an error if the request failed', function() local status, err = pcall(eval, "rpcrequest(vim, 'does-not-exist')") eq(false, status) - eq(true, string.match(err, ': (.*)') == 'Failed to evaluate expression') + ok(nil ~= string.match(err, 'Failed to evaluate expression')) end) end) - describe('when using jobstart', function() + describe('jobstart()', function() local jobid before_each(function() local channel = nvim('get_api_info')[1] @@ -202,7 +220,7 @@ describe('server -> client', function() \ 'rpc': v:true \ } ]]) - local lua_prog = arg[-1] + local lua_prog = Paths.test_lua_prg meths.set_var("args", {lua_prog, 'test/functional/api/rpc_fixture.lua'}) jobid = eval("jobstart(g:args, g:job_opts)") neq(0, 'jobid') @@ -212,6 +230,8 @@ describe('server -> client', function() funcs.jobstop(jobid) end) + if helpers.pending_win32(pending) then return end + it('rpc and text stderr can be combined', function() eq("ok",funcs.rpcrequest(jobid, "poll")) funcs.rpcnotify(jobid, "ping") @@ -223,4 +243,80 @@ describe('server -> client', function() end) end) + describe('connecting to another (peer) nvim', function() + local function connect_test(server, mode, address) + local serverpid = funcs.getpid() + local client = spawn(nvim_argv) + set_session(client, true) + local clientpid = funcs.getpid() + neq(serverpid, clientpid) + local id = funcs.sockconnect(mode, address, {rpc=true}) + ok(id > 0) + + funcs.rpcrequest(id, 'nvim_set_current_line', 'hello') + local client_id = funcs.rpcrequest(id, 'nvim_get_api_info')[1] + + set_session(server, true) + eq(serverpid, funcs.getpid()) + eq('hello', meths.get_current_line()) + + -- method calls work both ways + funcs.rpcrequest(client_id, 'nvim_set_current_line', 'howdy!') + eq(id, funcs.rpcrequest(client_id, 'nvim_get_api_info')[1]) + + set_session(client, true) + eq(clientpid, funcs.getpid()) + eq('howdy!', meths.get_current_line()) + + server:close() + client:close() + end + + it('via named pipe', function() + local server = spawn(nvim_argv) + set_session(server) + local address = funcs.serverlist()[1] + local first = string.sub(address,1,1) + ok(first == '/' or first == '\\') + connect_test(server, 'pipe', address) + end) + + it('via ip address', function() + local server = spawn(nvim_argv) + set_session(server) + local address = funcs.serverstart("127.0.0.1:") + eq('127.0.0.1:', string.sub(address,1,10)) + connect_test(server, 'tcp', address) + end) + + it('via hostname', function() + local server = spawn(nvim_argv) + set_session(server) + local address = funcs.serverstart("localhost:") + eq('localhost:', string.sub(address,1,10)) + connect_test(server, 'tcp', address) + end) + end) + + describe('connecting to its own pipe address', function() + it('does not deadlock', function() + if not os.getenv("TRAVIS") and helpers.os_name() == "osx" then + -- It does, in fact, deadlock on QuickBuild. #6851 + pending("deadlocks on QuickBuild", function() end) + return + end + local address = funcs.serverlist()[1] + local first = string.sub(address,1,1) + ok(first == '/' or first == '\\') + local serverpid = funcs.getpid() + + local id = funcs.sockconnect('pipe', address, {rpc=true}) + + funcs.rpcrequest(id, 'nvim_set_current_line', 'hello') + eq('hello', meths.get_current_line()) + eq(serverpid, funcs.rpcrequest(id, "nvim_eval", "getpid()")) + + eq(id, funcs.rpcrequest(id, 'nvim_get_api_info')[1]) + end) + end) end) diff --git a/test/functional/api/tabpage_spec.lua b/test/functional/api/tabpage_spec.lua index e10f30085f..260a91a80c 100644 --- a/test/functional/api/tabpage_spec.lua +++ b/test/functional/api/tabpage_spec.lua @@ -6,6 +6,8 @@ local curtabmeths = helpers.curtabmeths local funcs = helpers.funcs local request = helpers.request local NIL = helpers.NIL +local meth_pcall = helpers.meth_pcall +local command = helpers.command describe('api/tabpage', function() before_each(clear) @@ -32,6 +34,11 @@ describe('api/tabpage', function() eq(1, funcs.exists('t:lua')) curtabmeths.del_var('lua') eq(0, funcs.exists('t:lua')) + eq({false, 'Key does not exist: lua'}, meth_pcall(curtabmeths.del_var, 'lua')) + curtabmeths.set_var('lua', 1) + command('lockvar t:lua') + eq({false, 'Key is locked: lua'}, meth_pcall(curtabmeths.del_var, 'lua')) + eq({false, 'Key is locked: lua'}, meth_pcall(curtabmeths.set_var, 'lua', 1)) end) it('tabpage_set_var returns the old value', function() diff --git a/test/functional/api/version_spec.lua b/test/functional/api/version_spec.lua index 3efd00ddbe..d23f058f69 100644 --- a/test/functional/api/version_spec.lua +++ b/test/functional/api/version_spec.lua @@ -4,26 +4,16 @@ local clear, funcs, eq = helpers.clear, helpers.funcs, helpers.eq local function read_mpack_file(fname) local fd = io.open(fname, 'rb') + if fd == nil then + return nil + end + local data = fd:read('*a') fd:close() local unpack = mpack.Unpacker() return unpack(data) end --- Remove metadata that is not essential to backwards-compatibility. -local function remove_function_metadata(fspec) - fspec['can_fail'] = nil - fspec['async'] = nil - fspec['method'] = nil - fspec['since'] = nil - fspec['deprecated_since'] = nil - fspec['receives_channel_id'] = nil - for idx, _ in ipairs(fspec['parameters']) do - fspec['parameters'][idx][2] = '' -- Remove parameter name. - end - return fspec -end - describe("api_info()['version']", function() before_each(clear) @@ -49,23 +39,111 @@ describe("api_info()['version']", function() eq(0, funcs.has("nvim-"..major.."."..(minor + 1).."."..patch)) eq(0, funcs.has("nvim-"..(major + 1).."."..minor.."."..patch)) end) +end) + + +describe("api functions", function() + before_each(clear) + + local function func_table(metadata) + local functions = {} + for _,f in ipairs(metadata.functions) do + functions[f.name] = f + end + return functions + end + + -- Remove metadata that is not essential to backwards-compatibility. + local function filter_function_metadata(f) + f.deprecated_since = nil + for idx, _ in ipairs(f.parameters) do + f.parameters[idx][2] = '' -- Remove parameter name. + end + + if string.sub(f.name, 1, 4) ~= "nvim" then + f.method = nil + end + return f + end - it("api_compatible level is valid", function() - local api = helpers.call('api_info') - local compat = api['version']['api_compatible'] - local path = 'test/functional/fixtures/api_level_' - ..tostring(compat)..'.mpack' - - -- Verify that the current API function signatures match those of the API - -- level for which we claim compatibility. - local old_api = read_mpack_file(path) - for _, fn_old in ipairs(old_api['functions']) do - for _, fn_new in ipairs(api['functions']) do - if fn_old['name'] == fn_new['name'] then - eq(remove_function_metadata(fn_old), - remove_function_metadata(fn_new)) + -- Level 0 represents methods from 0.1.5 and earlier, when 'since' was not + -- yet defined, and metadata was not filtered of internal keys like 'async'. + local function clean_level_0(metadata) + for _, f in ipairs(metadata.functions) do + f.can_fail = nil + f.async = nil + f.receives_channel_id = nil + f.since = 0 + end + end + + it("are compatible with old metadata or have new level", function() + local api = helpers.call('api_info') + local compat = api.version.api_compatible + local api_level = api.version.api_level + local stable + if api.version.api_prerelease then + stable = api_level-1 + else + stable = api_level + end + + local funcs_new = func_table(api) + local funcs_compat = {} + for level = compat, stable do + local path = ('test/functional/fixtures/api_level_'.. + tostring(level)..'.mpack') + local old_api = read_mpack_file(path) + if old_api == nil then + local errstr = "missing metadata fixture for stable level "..level..". " + if level == api_level and not api.version.api_prerelease then + errstr = (errstr.."If NVIM_API_CURRENT was bumped, ".. + "don't forget to set NVIM_API_PRERELEASE to true.") + end + error(errstr) + end + + if level == 0 then + clean_level_0(old_api) + end + + for _,f in ipairs(old_api.functions) do + if funcs_new[f.name] == nil then + if f.since >= compat then + error('function '..f.name..' was removed but exists in level '.. + f.since..' which nvim should be compatible with') + end + else + eq(filter_function_metadata(f), + filter_function_metadata(funcs_new[f.name])) + end + end + + funcs_compat[level] = func_table(old_api) + end + + for _,f in ipairs(api.functions) do + if f.since <= stable then + local f_old = funcs_compat[f.since][f.name] + if f_old == nil then + if string.sub(f.name, 1, 4) == "nvim" then + local errstr = ("function "..f.name.." has too low since value. ".. + "For new functions set it to "..(stable+1)..".") + if not api.version.api_prerelease then + errstr = (errstr.." Also bump NVIM_API_CURRENT and set ".. + "NVIM_API_PRERELEASE to true in CMakeLists.txt.") + end + error(errstr) + else + error("function name '"..f.name.."' doesn't begin with 'nvim_'") + end end + elseif f.since > api_level then + error("function "..f.name.." has since value > api_level. ".. + "Please bump NVIM_API_CURRENT and set ".. + "NVIM_API_PRERELEASE to true in CMakeLists.txt.") end end end) + end) diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index ce6c52e334..a4b643589a 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -7,6 +7,8 @@ local os_name = helpers.os_name local meths = helpers.meths local funcs = helpers.funcs local request = helpers.request +local meth_pcall = helpers.meth_pcall +local command = helpers.command describe('api', function() before_each(clear) @@ -43,7 +45,7 @@ describe('api', function() it('works', function() nvim('command', 'let g:v1 = "a"') nvim('command', 'let g:v2 = [1, 2, {"v3": 3}]') - eq({v1 = 'a', v2 = {1, 2, {v3 = 3}}}, nvim('eval', 'g:')) + eq({v1 = 'a', v2 = { 1, 2, { v3 = 3 } } }, nvim('eval', 'g:')) end) it('handles NULL-initialized strings correctly', function() @@ -65,7 +67,7 @@ describe('api', function() describe('nvim_call_function', function() it('works', function() - nvim('call_function', 'setqflist', {{{ filename = 'something', lnum = 17}}, 'r'}) + nvim('call_function', 'setqflist', { { { filename = 'something', lnum = 17 } }, 'r' }) eq(17, nvim('call_function', 'getqflist', {})[1].lnum) eq(17, nvim('call_function', 'eval', {17})) eq('foo', nvim('call_function', 'simplify', {'this/./is//redundant/../../../foo'})) @@ -79,6 +81,36 @@ describe('api', function() end) end) + describe('nvim_execute_lua', function() + it('works', function() + meths.execute_lua('vim.api.nvim_set_var("test", 3)', {}) + eq(3, meths.get_var('test')) + + eq(17, meths.execute_lua('a, b = ...\nreturn a + b', {10,7})) + + eq(NIL, meths.execute_lua('function xx(a,b)\nreturn a..b\nend',{})) + eq("xy", meths.execute_lua('return xx(...)', {'x','y'})) + end) + + it('reports errors', function() + eq({false, 'Error loading lua: [string "<nvim>"]:1: '.. + "'=' expected near '+'"}, + meth_pcall(meths.execute_lua, 'a+*b', {})) + + eq({false, 'Error loading lua: [string "<nvim>"]:1: '.. + "unexpected symbol near '1'"}, + meth_pcall(meths.execute_lua, '1+2', {})) + + eq({false, 'Error loading lua: [string "<nvim>"]:1: '.. + "unexpected symbol"}, + meth_pcall(meths.execute_lua, 'aa=bb\0', {})) + + eq({false, 'Error executing lua: [string "<nvim>"]:1: '.. + "attempt to call global 'bork' (a nil value)"}, + meth_pcall(meths.execute_lua, 'bork()', {})) + end) + end) + describe('nvim_input', function() it("VimL error: does NOT fail, updates v:errmsg", function() local status, _ = pcall(nvim, "input", ":call bogus_fn()<CR>") @@ -117,6 +149,11 @@ describe('api', function() eq(1, funcs.exists('g:lua')) meths.del_var('lua') eq(0, funcs.exists('g:lua')) + eq({false, 'Key does not exist: lua'}, meth_pcall(meths.del_var, 'lua')) + meths.set_var('lua', 1) + command('lockvar lua') + eq({false, 'Key is locked: lua'}, meth_pcall(meths.del_var, 'lua')) + eq({false, 'Key is locked: lua'}, meth_pcall(meths.set_var, 'lua', 1)) end) it('vim_set_var returns the old value', function() @@ -146,6 +183,28 @@ describe('api', function() nvim('set_option', 'equalalways', false) ok(not nvim('get_option', 'equalalways')) end) + + it('works to get global value of local options', function() + eq(false, nvim('get_option', 'lisp')) + eq(8, nvim('get_option', 'shiftwidth')) + end) + + it('works to set global value of local options', function() + nvim('set_option', 'lisp', true) + eq(true, nvim('get_option', 'lisp')) + eq(false, helpers.curbuf('get_option', 'lisp')) + eq(nil, nvim('command_output', 'setglobal lisp?'):match('nolisp')) + eq('nolisp', nvim('command_output', 'setlocal lisp?'):match('nolisp')) + nvim('set_option', 'shiftwidth', 20) + eq('20', nvim('command_output', 'setglobal shiftwidth?'):match('%d+')) + eq('8', nvim('command_output', 'setlocal shiftwidth?'):match('%d+')) + end) + + it('most window-local options have no global value', function() + local status, err = pcall(nvim, 'get_option', 'foldcolumn') + eq(false, status) + ok(err:match('Invalid option name') ~= nil) + end) end) describe('nvim_{get,set}_current_buf, nvim_list_bufs', function() @@ -192,6 +251,152 @@ describe('api', function() end) end) + describe('nvim_get_mode', function() + it("during normal-mode `g` returns blocking=true", function() + nvim("input", "o") -- add a line + eq({mode='i', blocking=false}, nvim("get_mode")) + nvim("input", [[<C-\><C-N>]]) + eq(2, nvim("eval", "line('.')")) + eq({mode='n', blocking=false}, nvim("get_mode")) + + nvim("input", "g") + eq({mode='n', blocking=true}, nvim("get_mode")) + + nvim("input", "k") -- complete the operator + eq(1, nvim("eval", "line('.')")) -- verify the completed operator + eq({mode='n', blocking=false}, nvim("get_mode")) + end) + + it("returns the correct result multiple consecutive times", function() + for _ = 1,5 do + eq({mode='n', blocking=false}, nvim("get_mode")) + end + nvim("input", "g") + for _ = 1,4 do + eq({mode='n', blocking=true}, nvim("get_mode")) + end + nvim("input", "g") + for _ = 1,7 do + eq({mode='n', blocking=false}, nvim("get_mode")) + end + end) + + it("during normal-mode CTRL-W, returns blocking=true", function() + nvim("input", "<C-W>") + eq({mode='n', blocking=true}, nvim("get_mode")) + + nvim("input", "s") -- complete the operator + eq(2, nvim("eval", "winnr('$')")) -- verify the completed operator + eq({mode='n', blocking=false}, nvim("get_mode")) + end) + + it("during press-enter prompt returns blocking=true", function() + eq({mode='n', blocking=false}, nvim("get_mode")) + command("echom 'msg1'") + command("echom 'msg2'") + command("echom 'msg3'") + command("echom 'msg4'") + command("echom 'msg5'") + eq({mode='n', blocking=false}, nvim("get_mode")) + nvim("input", ":messages<CR>") + eq({mode='r', blocking=true}, nvim("get_mode")) + end) + + it("during getchar() returns blocking=false", function() + nvim("input", ":let g:test_input = nr2char(getchar())<CR>") + -- Events are enabled during getchar(), RPC calls are *not* blocked. #5384 + eq({mode='n', blocking=false}, nvim("get_mode")) + eq(0, nvim("eval", "exists('g:test_input')")) + nvim("input", "J") + eq("J", nvim("eval", "g:test_input")) + eq({mode='n', blocking=false}, nvim("get_mode")) + end) + + -- TODO: bug #6247#issuecomment-286403810 + it("batched with input", function() + eq({mode='n', blocking=false}, nvim("get_mode")) + command("echom 'msg1'") + command("echom 'msg2'") + command("echom 'msg3'") + command("echom 'msg4'") + command("echom 'msg5'") + + local req = { + {'nvim_get_mode', {}}, + {'nvim_input', {':messages<CR>'}}, + {'nvim_get_mode', {}}, + {'nvim_eval', {'1'}}, + } + eq({ { {mode='n', blocking=false}, + 13, + {mode='n', blocking=false}, -- TODO: should be blocked=true ? + 1 }, + NIL}, meths.call_atomic(req)) + eq({mode='r', blocking=true}, nvim("get_mode")) + end) + it("during insert-mode map-pending, returns blocking=true #6166", function() + command("inoremap xx foo") + nvim("input", "ix") + eq({mode='i', blocking=true}, nvim("get_mode")) + end) + it("during normal-mode gU, returns blocking=false #6166", function() + nvim("input", "gu") + eq({mode='no', blocking=false}, nvim("get_mode")) + end) + end) + + describe('RPC (K_EVENT) #6166', function() + it('does not complete ("interrupt") normal-mode operator-pending', function() + helpers.insert([[ + FIRST LINE + SECOND LINE]]) + nvim('input', 'gg') + nvim('input', 'gu') + -- Make any RPC request (can be non-async: op-pending does not block). + nvim('get_current_buf') + -- Buffer should not change. + helpers.expect([[ + FIRST LINE + SECOND LINE]]) + -- Now send input to complete the operator. + nvim('input', 'j') + helpers.expect([[ + first line + second line]]) + end) + it('does not complete ("interrupt") normal-mode map-pending', function() + command("nnoremap dd :let g:foo='it worked...'<CR>") + helpers.insert([[ + FIRST LINE + SECOND LINE]]) + nvim('input', 'gg') + nvim('input', 'd') + -- Make any RPC request (must be async, because map-pending blocks). + nvim('get_api_info') + -- Send input to complete the mapping. + nvim('input', 'd') + helpers.expect([[ + FIRST LINE + SECOND LINE]]) + eq('it worked...', helpers.eval('g:foo')) + end) + it('does not complete ("interrupt") insert-mode map-pending', function() + command('inoremap xx foo') + command('set timeoutlen=9999') + helpers.insert([[ + FIRST LINE + SECOND LINE]]) + nvim('input', 'ix') + -- Make any RPC request (must be async, because map-pending blocks). + nvim('get_api_info') + -- Send input to complete the mapping. + nvim('input', 'x') + helpers.expect([[ + FIRST LINE + SECOND LINfooE]]) + end) + end) + describe('nvim_replace_termcodes', function() it('escapes K_SPECIAL as K_SPECIAL KS_SPECIAL KE_FILLER', function() eq('\128\254X', helpers.nvim('replace_termcodes', '\128', true, true, true)) @@ -212,6 +417,27 @@ describe('api', function() eq('\128\253\44', helpers.nvim('replace_termcodes', '<LeftMouse>', true, true, true)) end) + + it('converts keycodes', function() + eq('\nx\27x\rx<x', helpers.nvim('replace_termcodes', + '<NL>x<Esc>x<CR>x<lt>x', true, true, true)) + end) + + it('does not convert keycodes if special=false', function() + eq('<NL>x<Esc>x<CR>x<lt>x', helpers.nvim('replace_termcodes', + '<NL>x<Esc>x<CR>x<lt>x', true, true, false)) + end) + + it('does not crash when transforming an empty string', function() + -- Actually does not test anything, because current code will use NULL for + -- an empty string. + -- + -- Problem here is that if String argument has .data in allocated memory + -- then `return str` in vim_replace_termcodes body will make Neovim free + -- `str.data` twice: once when freeing arguments, then when freeing return + -- value. + eq('', meths.replace_termcodes('', true, true, true)) + end) end) describe('nvim_feedkeys', function() @@ -220,13 +446,13 @@ describe('api', function() -- notice the special char(โฆ) \xe2\80\xa6 nvim('feedkeys', ':let x1="โฆ"\n', '', true) - -- Both replace_termcodes and feedkeys escape \x80 + -- Both nvim_replace_termcodes and nvim_feedkeys escape \x80 local inp = helpers.nvim('replace_termcodes', ':let x2="โฆ"<CR>', true, true, true) - nvim('feedkeys', inp, '', true) + nvim('feedkeys', inp, '', true) -- escape_csi=true - -- Disabling CSI escaping in feedkeys + -- nvim_feedkeys with CSI escaping disabled inp = helpers.nvim('replace_termcodes', ':let x3="โฆ"<CR>', true, true, true) - nvim('feedkeys', inp, '', false) + nvim('feedkeys', inp, '', false) -- escape_csi=false helpers.stop() end @@ -383,7 +609,7 @@ describe('api', function() eq(5, meths.get_var('avar')) end) - it('throws error on malformated arguments', function() + it('throws error on malformed arguments', function() local req = { {'nvim_set_var', {'avar', 1}}, {'nvim_set_var'}, @@ -396,7 +622,7 @@ describe('api', function() eq(1, meths.get_var('avar')) req = { - {'nvim_set_var', {'bvar', {2,3}}}, + { 'nvim_set_var', { 'bvar', { 2, 3 } } }, 12, } status, err = pcall(meths.call_atomic, req) @@ -410,20 +636,57 @@ describe('api', function() } status, err = pcall(meths.call_atomic, req) eq(false, status) - ok(err:match('args must be Array') ~= nil) + ok(err:match('Args must be Array') ~= nil) -- call before was done, but not after eq(1, meths.get_var('avar')) eq({''}, meths.buf_get_lines(0, 0, -1, true)) end) end) + describe('list_runtime_paths', function() + it('returns nothing with empty &runtimepath', function() + meths.set_option('runtimepath', '') + eq({}, meths.list_runtime_paths()) + end) + it('returns single runtimepath', function() + meths.set_option('runtimepath', 'a') + eq({'a'}, meths.list_runtime_paths()) + end) + it('returns two runtimepaths', function() + meths.set_option('runtimepath', 'a,b') + eq({'a', 'b'}, meths.list_runtime_paths()) + end) + it('returns empty strings when appropriate', function() + meths.set_option('runtimepath', 'a,,b') + eq({'a', '', 'b'}, meths.list_runtime_paths()) + meths.set_option('runtimepath', ',a,b') + eq({'', 'a', 'b'}, meths.list_runtime_paths()) + meths.set_option('runtimepath', 'a,b,') + eq({'a', 'b', ''}, meths.list_runtime_paths()) + end) + it('truncates too long paths', function() + local long_path = ('/a'):rep(8192) + meths.set_option('runtimepath', long_path) + local paths_list = meths.list_runtime_paths() + neq({long_path}, paths_list) + eq({long_path:sub(1, #(paths_list[1]))}, paths_list) + end) + end) + it('can throw exceptions', function() local status, err = pcall(nvim, 'get_option', 'invalid-option') eq(false, status) ok(err:match('Invalid option name') ~= nil) end) - it("doesn't leak memory on incorrect argument types", function() + it('does not truncate error message <1 MB #5984', function() + local very_long_name = 'A'..('x'):rep(10000)..'Z' + local status, err = pcall(nvim, 'get_option', very_long_name) + eq(false, status) + eq(very_long_name, err:match('Ax+Z?')) + end) + + it("does not leak memory on incorrect argument types", function() local status, err = pcall(nvim, 'set_current_dir',{'not', 'a', 'dir'}) eq(false, status) ok(err:match(': Wrong type for argument 1, expecting String') ~= nil) diff --git a/test/functional/api/window_spec.lua b/test/functional/api/window_spec.lua index 465bda6bc9..8a65d3f71e 100644 --- a/test/functional/api/window_spec.lua +++ b/test/functional/api/window_spec.lua @@ -8,6 +8,9 @@ local curwinmeths = helpers.curwinmeths local funcs = helpers.funcs local request = helpers.request local NIL = helpers.NIL +local meth_pcall = helpers.meth_pcall +local meths = helpers.meths +local command = helpers.command -- check if str is visible at the beginning of some line local function is_visible(str) @@ -53,6 +56,12 @@ describe('api/win', function() eq('typing\n some dumb text', curbuf_contents()) end) + it('does not leak memory when using invalid window ID with invalid pos', + function() + eq({false, 'Invalid window id'}, + meth_pcall(meths.win_set_cursor, 1, {"b\na"})) + end) + it('updates the screen, and also when the window is unfocused', function() insert("prologue") feed('100o<esc>') @@ -137,6 +146,11 @@ describe('api/win', function() eq(1, funcs.exists('w:lua')) curwinmeths.del_var('lua') eq(0, funcs.exists('w:lua')) + eq({false, 'Key does not exist: lua'}, meth_pcall(curwinmeths.del_var, 'lua')) + curwinmeths.set_var('lua', 1) + command('lockvar w:lua') + eq({false, 'Key is locked: lua'}, meth_pcall(curwinmeths.del_var, 'lua')) + eq({false, 'Key is locked: lua'}, meth_pcall(curwinmeths.set_var, 'lua', 1)) end) it('window_set_var returns the old value', function() diff --git a/test/functional/autocmd/autocmd_spec.lua b/test/functional/autocmd/autocmd_spec.lua index 162e112047..8ee9462a8d 100644 --- a/test/functional/autocmd/autocmd_spec.lua +++ b/test/functional/autocmd/autocmd_spec.lua @@ -1,9 +1,13 @@ local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear -local command = helpers.command local eq = helpers.eq local eval = helpers.eval +local clear = helpers.clear +local meths = helpers.meths +local expect = helpers.expect +local command = helpers.command +local exc_exec = helpers.exc_exec +local curbufmeths = helpers.curbufmeths describe('autocmds:', function() before_each(clear) @@ -12,8 +16,8 @@ describe('autocmds:', function() local expected = { 'WinLeave', 'TabLeave', - 'TabNew', 'WinEnter', + 'TabNew', 'TabEnter', 'BufLeave', 'BufEnter' @@ -33,4 +37,22 @@ describe('autocmds:', function() it('v:vim_did_enter is 1 after VimEnter', function() eq(1, eval('v:vim_did_enter')) end) + + describe('BufLeave autocommand', function() + it('can wipe out the buffer created by :edit which triggered autocmd', + function() + meths.set_option('hidden', true) + curbufmeths.set_lines(0, 1, false, { + 'start of test file xx', + 'end of test file xx'}) + + command('autocmd BufLeave * bwipeout yy') + eq('Vim(edit):E143: Autocommands unexpectedly deleted new buffer yy', + exc_exec('edit yy')) + + expect([[ + start of test file xx + end of test file xx]]) + end) + end) end) diff --git a/test/functional/autocmd/bufenter_spec.lua b/test/functional/autocmd/bufenter_spec.lua new file mode 100644 index 0000000000..fef9838050 --- /dev/null +++ b/test/functional/autocmd/bufenter_spec.lua @@ -0,0 +1,34 @@ +local helpers = require('test.functional.helpers')(after_each) + +local clear = helpers.clear +local command = helpers.command +local eq = helpers.eq +local eval = helpers.eval +local request = helpers.request +local source = helpers.source + +describe('autocmd BufEnter', function() + before_each(clear) + + it("triggered by nvim_command('edit <dir>')", function() + command("autocmd BufEnter * if isdirectory(expand('<afile>')) | let g:dir_bufenter = 1 | endif") + request("nvim_command", "split .") + eq(1, eval("exists('g:dir_bufenter')")) -- Did BufEnter for the directory. + eq(2, eval("bufnr('%')")) -- Switched to the dir buffer. + end) + + it('triggered by "try|:split <dir>|endtry" in a function', function() + command("autocmd BufEnter * if isdirectory(expand('<afile>')) | let g:dir_bufenter = 1 | endif") + source([[ + function! Test() + try + exe 'split .' + catch + endtry + endfunction + ]]) + command("call Test()") + eq(1, eval("exists('g:dir_bufenter')")) -- Did BufEnter for the directory. + eq(2, eval("bufnr('%')")) -- Switched to the dir buffer. + end) +end) diff --git a/test/functional/autocmd/dirchanged_spec.lua b/test/functional/autocmd/dirchanged_spec.lua new file mode 100644 index 0000000000..63cf0bc410 --- /dev/null +++ b/test/functional/autocmd/dirchanged_spec.lua @@ -0,0 +1,157 @@ +local lfs = require('lfs') +local h = require('test.functional.helpers')(after_each) + +local clear = h.clear +local command = h.command +local eq = h.eq +local eval = h.eval +local request = h.request + +describe('autocmd DirChanged', function() + local curdir = string.gsub(lfs.currentdir(), '\\', '/') + local dirs = { + curdir .. '/Xtest-functional-autocmd-dirchanged.dir1', + curdir .. '/Xtest-functional-autocmd-dirchanged.dir2', + curdir .. '/Xtest-functional-autocmd-dirchanged.dir3', + } + + setup(function() for _, dir in pairs(dirs) do h.mkdir(dir) end end) + teardown(function() for _, dir in pairs(dirs) do h.rmdir(dir) end end) + + before_each(function() + clear() + command('autocmd DirChanged * let [g:getcwd, g:ev, g:amatch, g:cdcount] ' + ..' = [getcwd(), copy(v:event), expand("<amatch>"), 1 + get(g:, "cdcount", 0)]') + -- Normalize path separators. + command([[autocmd DirChanged * let g:ev['cwd'] = substitute(g:ev['cwd'], '\\', '/', 'g')]]) + command([[autocmd DirChanged * let g:getcwd = substitute(g:getcwd, '\\', '/', 'g')]]) + end) + + it('sets v:event', function() + command('lcd '..dirs[1]) + eq({cwd=dirs[1], scope='window'}, eval('g:ev')) + eq(1, eval('g:cdcount')) + + command('tcd '..dirs[2]) + eq({cwd=dirs[2], scope='tab'}, eval('g:ev')) + eq(2, eval('g:cdcount')) + + command('cd '..dirs[3]) + eq({cwd=dirs[3], scope='global'}, eval('g:ev')) + eq(3, eval('g:cdcount')) + end) + + it('sets getcwd() during event #6260', function() + command('lcd '..dirs[1]) + eq(dirs[1], eval('g:getcwd')) + + command('tcd '..dirs[2]) + eq(dirs[2], eval('g:getcwd')) + + command('cd '..dirs[3]) + eq(dirs[3], eval('g:getcwd')) + end) + + it('disallows recursion', function() + command('set shellslash') + -- Set up a _nested_ handler. + command('autocmd DirChanged * nested lcd '..dirs[3]) + command('lcd '..dirs[1]) + eq({cwd=dirs[1], scope='window'}, eval('g:ev')) + eq(1, eval('g:cdcount')) + -- autocmd changed to dirs[3], but did NOT trigger another DirChanged. + eq(dirs[3], eval('getcwd()')) + end) + + it('sets <amatch> to CWD "scope"', function() + command('lcd '..dirs[1]) + eq('window', eval('g:amatch')) + + command('tcd '..dirs[2]) + eq('tab', eval('g:amatch')) + + command('cd '..dirs[3]) + eq('global', eval('g:amatch')) + end) + + it('does not trigger if :cd fails', function() + command('let g:ev = {}') + + local status1, err1 = pcall(function() + command('lcd '..dirs[1] .. '/doesnotexist') + end) + eq({}, eval('g:ev')) + + local status2, err2 = pcall(function() + command('lcd '..dirs[2] .. '/doesnotexist') + end) + eq({}, eval('g:ev')) + + local status3, err3 = pcall(function() + command('lcd '..dirs[3] .. '/doesnotexist') + end) + eq({}, eval('g:ev')) + + eq(false, status1) + eq(false, status2) + eq(false, status3) + + eq('E344:', string.match(err1, "E%d*:")) + eq('E344:', string.match(err2, "E%d*:")) + eq('E344:', string.match(err3, "E%d*:")) + end) + + it("is triggered by 'autochdir'", function() + command('set autochdir') + + command('split '..dirs[1]..'/foo') + eq({cwd=dirs[1], scope='window'}, eval('g:ev')) + + command('split '..dirs[2]..'/bar') + eq({cwd=dirs[2], scope='window'}, eval('g:ev')) + + eq(2, eval('g:cdcount')) + end) + + it("is triggered by switching to win/tab with different CWD #6054", function() + command('lcd '..dirs[3]) -- window 3 + command('split '..dirs[2]..'/foo') -- window 2 + command('lcd '..dirs[2]) + command('split '..dirs[1]..'/bar') -- window 1 + command('lcd '..dirs[1]) + + command('2wincmd w') -- window 2 + eq({cwd=dirs[2], scope='window'}, eval('g:ev')) + + eq(4, eval('g:cdcount')) + command('tabnew') -- tab 2 (tab-local CWD) + eq(4, eval('g:cdcount')) -- same CWD, no DirChanged event + command('tcd '..dirs[3]) + command('tabnext') -- tab 1 (no tab-local CWD) + eq({cwd=dirs[2], scope='window'}, eval('g:ev')) + command('tabnext') -- tab 2 + eq({cwd=dirs[3], scope='tab'}, eval('g:ev')) + eq(7, eval('g:cdcount')) + + command('tabnext') -- tab 1 + command('3wincmd w') -- window 3 + eq(9, eval('g:cdcount')) + command('tabnext') -- tab 2 (has the *same* CWD) + eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event + end) + + it('is triggered by nvim_set_current_dir()', function() + request('nvim_set_current_dir', dirs[1]) + eq({cwd=dirs[1], scope='global'}, eval('g:ev')) + + request('nvim_set_current_dir', dirs[2]) + eq({cwd=dirs[2], scope='global'}, eval('g:ev')) + + local status, err = pcall(function() + request('nvim_set_current_dir', '/doesnotexist') + end) + eq(false, status) + eq('Failed to change directory', string.match(err, ': (.*)')) + eq({cwd=dirs[2], scope='global'}, eval('g:ev')) + end) +end) diff --git a/test/functional/autocmd/tabnew_spec.lua b/test/functional/autocmd/tabnew_spec.lua index 2148b21832..ad40954f76 100644 --- a/test/functional/autocmd/tabnew_spec.lua +++ b/test/functional/autocmd/tabnew_spec.lua @@ -5,8 +5,6 @@ local command = helpers.command local eq = helpers.eq local eval = helpers.eval -if helpers.pending_win32(pending) then return end - describe('autocmd TabNew', function() before_each(clear) @@ -19,12 +17,11 @@ describe('autocmd TabNew', function() end) it('matches when opening a new tab for FILE', function() - local tmp_path = helpers.funcs.tempname() command('let g:test = "foo"') - command('autocmd! TabNew ' .. tmp_path .. ' let g:test = "bar"') - command('tabnew ' .. tmp_path ..'X') + command('autocmd! TabNew Xtest-tabnew let g:test = "bar"') + command('tabnew Xtest-tabnewX') eq('foo', eval('g:test')) - command('tabnew ' .. tmp_path) + command('tabnew Xtest-tabnew') eq('bar', eval('g:test')) end) end) diff --git a/test/functional/autocmd/tabnewentered_spec.lua b/test/functional/autocmd/tabnewentered_spec.lua index f033bd5fe4..bdbe677132 100644 --- a/test/functional/autocmd/tabnewentered_spec.lua +++ b/test/functional/autocmd/tabnewentered_spec.lua @@ -1,8 +1,6 @@ local helpers = require('test.functional.helpers')(after_each) local clear, nvim, eq = helpers.clear, helpers.nvim, helpers.eq -if helpers.pending_win32(pending) then return end - describe('TabNewEntered', function() describe('au TabNewEntered', function() describe('with * as <afile>', function() @@ -15,9 +13,9 @@ describe('TabNewEntered', function() end) describe('with FILE as <afile>', function() it('matches when opening a new tab for FILE', function() - local tmp_path = nvim('eval', 'tempname()') - nvim('command', 'au! TabNewEntered '..tmp_path..' echom "tabnewentered:match"') - eq("\n\""..tmp_path.."\" [New File]\ntabnewentered:4:4\ntabnewentered:match", nvim('command_output', 'tabnew '..tmp_path)) + nvim('command', 'au! TabNewEntered Xtest-tabnewentered echom "tabnewentered:match"') + eq('\n"Xtest-tabnewentered" [New File]\ntabnewentered:4:4\ntabnewentered:match', + nvim('command_output', 'tabnew Xtest-tabnewentered')) end) end) describe('with CTRL-W T', function() diff --git a/test/functional/autocmd/termclose_spec.lua b/test/functional/autocmd/termclose_spec.lua index 6871711058..c6c30494dd 100644 --- a/test/functional/autocmd/termclose_spec.lua +++ b/test/functional/autocmd/termclose_spec.lua @@ -1,46 +1,81 @@ local helpers = require('test.functional.helpers')(after_each) -local Screen = require('test.functional.ui.screen') -local clear, execute, feed, nvim, nvim_dir = helpers.clear, -helpers.execute, helpers.feed, helpers.nvim, helpers.nvim_dir -local eval, eq = helpers.eval, helpers.eq +local clear, command, nvim, nvim_dir = + helpers.clear, helpers.command, helpers.nvim, helpers.nvim_dir +local eval, eq, retry = + helpers.eval, helpers.eq, helpers.retry if helpers.pending_win32(pending) then return end describe('TermClose event', function() - local screen before_each(function() clear() nvim('set_option', 'shell', nvim_dir .. '/shell-test') nvim('set_option', 'shellcmdflag', 'EXE') - screen = Screen.new(20, 4) - screen:attach({rgb=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! | - ]]) + it('triggers when fast-exiting terminal job stops', function() + command('autocmd TermClose * let g:test_termclose = 23') + command('terminal') + command('call jobstop(b:terminal_job_id)') + retry(nil, nil, function() eq(23, eval('g:test_termclose')) end) + end) + + it('triggers when long-running terminal job gets stopped', function() + nvim('set_option', 'shell', 'sh') + command('autocmd TermClose * let g:test_termclose = 23') + command('terminal') + command('call jobstop(b:terminal_job_id)') + retry(nil, nil, function() eq(23, eval('g:test_termclose')) end) + end) + + it('kills job trapping SIGTERM', function() + nvim('set_option', 'shell', 'sh') + nvim('set_option', 'shellcmdflag', '-c') + command([[ let g:test_job = jobstart('trap "" TERM && echo 1 && sleep 60', { ]] + .. [[ 'on_stdout': {-> execute('let g:test_job_started = 1')}, ]] + .. [[ 'on_exit': {-> execute('let g:test_job_exited = 1')}}) ]]) + retry(nil, nil, function() eq(1, eval('get(g:, "test_job_started", 0)')) end) + + local start = os.time() + command('call jobstop(g:test_job)') + retry(nil, nil, function() eq(1, eval('get(g:, "test_job_exited", 0)')) end) + local duration = os.time() - start + eq(2, duration) + end) + + it('kills pty job trapping SIGHUP and SIGTERM', function() + nvim('set_option', 'shell', 'sh') + nvim('set_option', 'shellcmdflag', '-c') + command([[ let g:test_job = jobstart('trap "" HUP TERM && echo 1 && sleep 60', { ]] + .. [[ 'pty': 1,]] + .. [[ 'on_stdout': {-> execute('let g:test_job_started = 1')}, ]] + .. [[ 'on_exit': {-> execute('let g:test_job_exited = 1')}}) ]]) + retry(nil, nil, function() eq(1, eval('get(g:, "test_job_started", 0)')) end) + + local start = os.time() + command('call jobstop(g:test_job)') + retry(nil, nil, function() eq(1, eval('get(g:, "test_job_exited", 0)')) end) + local duration = os.time() - start + -- nvim starts sending kill after 2*KILL_TIMEOUT_MS + helpers.ok(4 <= duration) + helpers.ok(duration <= 7) -- <= 4 + delta because of slow CI end) it('reports the correct <abuf>', function() - execute('set hidden') - execute('autocmd TermClose * let g:abuf = expand("<abuf>")') - execute('edit foo') - execute('edit bar') + command('set hidden') + command('autocmd TermClose * let g:abuf = expand("<abuf>")') + command('edit foo') + command('edit bar') eq(2, eval('bufnr("%")')) - execute('terminal') - feed('<c-\\><c-n>') - eq(3, eval('bufnr("%")')) - execute('buffer 1') - eq(1, eval('bufnr("%")')) - execute('3bdelete!') - eq('3', eval('g:abuf')) + + command('terminal') + retry(nil, nil, function() eq(3, eval('bufnr("%")')) end) + + command('buffer 1') + retry(nil, nil, function() eq(1, eval('bufnr("%")')) end) + + command('3bdelete!') + retry(nil, nil, function() eq('3', eval('g:abuf')) end) end) end) diff --git a/test/functional/autocmd/textyankpost_spec.lua b/test/functional/autocmd/textyankpost_spec.lua index bd5f1912c5..486a3346b1 100644 --- a/test/functional/autocmd/textyankpost_spec.lua +++ b/test/functional/autocmd/textyankpost_spec.lua @@ -1,6 +1,6 @@ local helpers = require('test.functional.helpers')(after_each) local clear, eval, eq = helpers.clear, helpers.eval, helpers.eq -local feed, execute, expect, command = helpers.feed, helpers.execute, helpers.expect, helpers.command +local feed, command, expect = helpers.feed, helpers.command, helpers.expect local curbufmeths, funcs, neq = helpers.curbufmeths, helpers.funcs, helpers.neq describe('TextYankPost', function() @@ -8,11 +8,11 @@ describe('TextYankPost', function() clear() -- emulate the clipboard so system clipboard isn't affected - execute('let &rtp = "test/functional/fixtures,".&rtp') + command('let &rtp = "test/functional/fixtures,".&rtp') - execute('let g:count = 0') - execute('autocmd TextYankPost * let g:event = copy(v:event)') - execute('autocmd TextYankPost * let g:count += 1') + command('let g:count = 0') + command('autocmd TextYankPost * let g:event = copy(v:event)') + command('autocmd TextYankPost * let g:count += 1') curbufmeths.set_lines(0, -1, true, { 'foo\0bar', @@ -61,27 +61,27 @@ describe('TextYankPost', function() regtype = 'V' }, eval('g:event')) - execute('set debug=msg') + command('set debug=msg') -- the regcontents should not be changed without copy. local status, err = pcall(command,'call extend(g:event.regcontents, ["more text"])') eq(status,false) neq(nil, string.find(err, ':E742:')) -- can't mutate keys inside the autocommand - execute('autocmd! TextYankPost * let v:event.regcontents = 0') + command('autocmd! TextYankPost * let v:event.regcontents = 0') status, err = pcall(command,'normal yy') eq(status,false) neq(nil, string.find(err, ':E46:')) -- can't add keys inside the autocommand - execute('autocmd! TextYankPost * let v:event.mykey = 0') + command('autocmd! TextYankPost * let v:event.mykey = 0') status, err = pcall(command,'normal yy') eq(status,false) neq(nil, string.find(err, ':E742:')) end) it('is not invoked recursively', function() - execute('autocmd TextYankPost * normal "+yy') + command('autocmd TextYankPost * normal "+yy') feed('yy') eq({ operator = 'y', @@ -134,7 +134,7 @@ describe('TextYankPost', function() feed('"_yy') eq(0, eval('g:count')) - execute('delete _') + command('delete _') eq(0, eval('g:count')) end) @@ -155,7 +155,7 @@ describe('TextYankPost', function() regtype = 'V' }, eval('g:event')) - execute("set clipboard=unnamed") + command("set clipboard=unnamed") -- regname still shows the name the user requested feed('yy') @@ -176,7 +176,7 @@ describe('TextYankPost', function() end) it('works with Ex commands', function() - execute('1delete +') + command('1delete +') eq({ operator = 'd', regcontents = { 'foo\nbar' }, @@ -185,7 +185,7 @@ describe('TextYankPost', function() }, eval('g:event')) eq(1, eval('g:count')) - execute('yank') + command('yank') eq({ operator = 'y', regcontents = { 'baz text' }, @@ -194,7 +194,7 @@ describe('TextYankPost', function() }, eval('g:event')) eq(2, eval('g:count')) - execute('normal yw') + command('normal yw') eq({ operator = 'y', regcontents = { 'baz ' }, @@ -203,7 +203,7 @@ describe('TextYankPost', function() }, eval('g:event')) eq(3, eval('g:count')) - execute('normal! dd') + command('normal! dd') eq({ operator = 'd', regcontents = { 'baz text' }, diff --git a/test/functional/clipboard/clipboard_provider_spec.lua b/test/functional/clipboard/clipboard_provider_spec.lua index 6424b39e13..f66fbf7c94 100644 --- a/test/functional/clipboard/clipboard_provider_spec.lua +++ b/test/functional/clipboard/clipboard_provider_spec.lua @@ -3,9 +3,9 @@ local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local execute, expect, eq, eval = helpers.execute, helpers.expect, helpers.eq, helpers.eval - -if helpers.pending_win32(pending) then return end +local feed_command, expect, eq, eval = helpers.feed_command, helpers.expect, helpers.eq, helpers.eval +local command = helpers.command +local meths = helpers.meths local function basic_register_test(noblock) insert("some words") @@ -82,22 +82,112 @@ local function basic_register_test(noblock) expect("two and three and one") end -describe('the unnamed register', function() +describe('clipboard', function() before_each(clear) - it('works without provider', function() + + it('unnamed register works without provider', function() eq('"', eval('v:register')) basic_register_test() end) + + it('`:redir @+>` with invalid g:clipboard shows exactly one error #7184', + function() + local screen = Screen.new(72, 4) + screen:attach() + command("let g:clipboard = 'bogus'") + feed_command('redir @+> | :silent echo system("cat CONTRIBUTING.md") | redir END') + screen:expect([[ + ^ | + ~ | + ~ | + clipboard: No provider. Try ":CheckHealth" or ":h clipboard". | + ]], nil, {{bold = true, foreground = Screen.colors.Blue}}) + end) + + it('`:redir @+>|bogus_cmd|redir END` + invalid g:clipboard must not recurse #7184', + function() + local screen = Screen.new(72, 4) + screen:attach() + command("let g:clipboard = 'bogus'") + feed_command('redir @+> | bogus_cmd | redir END') + screen:expect([[ + ~ | + clipboard: No provider. Try ":CheckHealth" or ":h clipboard". | + E492: Not an editor command: bogus_cmd | redir END | + Press ENTER or type command to continue^ | + ]], nil, {{bold = true, foreground = Screen.colors.Blue}}) + end) + + it('invalid g:clipboard shows hint if :redir is not active', function() + command("let g:clipboard = 'bogus'") + eq('', eval('provider#clipboard#Executable()')) + eq('clipboard: invalid g:clipboard', eval('provider#clipboard#Error()')) + + local screen = Screen.new(72, 4) + screen:attach() + command("let g:clipboard = 'bogus'") + -- Explicit clipboard attempt, should show a hint message. + feed_command('let @+="foo"') + screen:expect([[ + ^ | + ~ | + ~ | + clipboard: No provider. Try ":CheckHealth" or ":h clipboard". | + ]], nil, {{bold = true, foreground = Screen.colors.Blue}}) + end) + + it('valid g:clipboard', function() + -- provider#clipboard#Executable() only checks the structure. + meths.set_var('clipboard', { + ['name'] = 'clippy!', + ['copy'] = { ['+'] = 'any command', ['*'] = 'some other' }, + ['paste'] = { ['+'] = 'any command', ['*'] = 'some other' }, + }) + eq('clippy!', eval('provider#clipboard#Executable()')) + eq('', eval('provider#clipboard#Error()')) + end) end) -describe('clipboard usage', function() +describe('clipboard', function() + local function reset(...) + clear('--cmd', 'let &rtp = "test/functional/fixtures,".&rtp', ...) + end + before_each(function() - clear() - execute('let &rtp = "test/functional/fixtures,".&rtp') - execute('call getreg("*")') -- force load of provider + reset() + feed_command('call getreg("*")') -- force load of provider + end) + + it('`:redir @+>` invokes clipboard once-per-message', function() + eq(0, eval("g:clip_called_set")) + feed_command('redir @+> | :silent echo system("cat CONTRIBUTING.md") | redir END') + -- Assuming CONTRIBUTING.md has >100 lines. + assert(eval("g:clip_called_set") > 100) + end) + + it('`:redir @">` does NOT invoke clipboard', function() + -- :redir to a non-clipboard register, with `:set clipboard=unnamed` does + -- NOT propagate to the clipboard. This is consistent with Vim. + command("set clipboard=unnamedplus") + eq(0, eval("g:clip_called_set")) + feed_command('redir @"> | :silent echo system("cat CONTRIBUTING.md") | redir END') + eq(0, eval("g:clip_called_set")) + end) + + it('`:redir @+>|bogus_cmd|redir END` must not recurse #7184', + function() + local screen = Screen.new(72, 4) + screen:attach() + feed_command('redir @+> | bogus_cmd | redir END') + screen:expect([[ + ^ | + ~ | + ~ | + E492: Not an editor command: bogus_cmd | redir END | + ]], nil, {{bold = true, foreground = Screen.colors.Blue}}) end) - it('has independent "* and unnamed registers per default', function() + it('has independent "* and unnamed registers by default', function() insert("some words") feed('^"*dwdw"*P') expect('some ') @@ -138,9 +228,9 @@ describe('clipboard usage', function() eq({'some\ntext', '\nvery binary\n'}, eval("getreg('*', 1, 1)")) end) - it('support autodectection of regtype', function() - execute("let g:test_clip['*'] = ['linewise stuff','']") - execute("let g:test_clip['+'] = ['charwise','stuff']") + it('autodetects regtype', function() + feed_command("let g:test_clip['*'] = ['linewise stuff','']") + feed_command("let g:test_clip['+'] = ['charwise','stuff']") eq("V", eval("getregtype('*')")) eq("v", eval("getregtype('+')")) insert("just some text") @@ -155,7 +245,7 @@ describe('clipboard usage', function() insert([[ much text]]) - execute("let g:test_clip['*'] = [['very','block'],'b']") + feed_command("let g:test_clip['*'] = [['very','block'],'b']") feed('gg"*P') expect([[ very much @@ -168,16 +258,16 @@ describe('clipboard usage', function() eq({{' much', 'ktext', ''}, 'b'}, eval("g:test_clip['+']")) end) - it('supports setreg', function() - execute('call setreg("*", "setted\\ntext", "c")') - execute('call setreg("+", "explicitly\\nlines", "l")') + it('supports setreg()', function() + feed_command('call setreg("*", "setted\\ntext", "c")') + feed_command('call setreg("+", "explicitly\\nlines", "l")') feed('"+P"*p') expect([[ esetted textxplicitly lines ]]) - execute('call setreg("+", "blocky\\nindeed", "b")') + feed_command('call setreg("+", "blocky\\nindeed", "b")') feed('"+p') expect([[ esblockyetted @@ -186,14 +276,14 @@ describe('clipboard usage', function() ]]) end) - it('supports let @+ (issue #1427)', function() - execute("let @+ = 'some'") - execute("let @* = ' other stuff'") + it('supports :let @+ (issue #1427)', function() + feed_command("let @+ = 'some'") + feed_command("let @* = ' other stuff'") eq({{'some'}, 'v'}, eval("g:test_clip['+']")) eq({{' other stuff'}, 'v'}, eval("g:test_clip['*']")) feed('"+p"*p') expect('some other stuff') - execute("let @+ .= ' more'") + feed_command("let @+ .= ' more'") feed('dd"+p') expect('some more') end) @@ -201,7 +291,7 @@ describe('clipboard usage', function() it('pastes unnamed register if the provider fails', function() insert('the text') feed('yy') - execute("let g:cliperror = 1") + feed_command("let g:cliperror = 1") feed('"*p') expect([[ the text @@ -213,7 +303,7 @@ describe('clipboard usage', function() -- the basic behavior of unnamed register should be the same -- even when handled by clipboard provider before_each(function() - execute('set clipboard=unnamed') + feed_command('set clipboard=unnamed') end) it('works', function() @@ -221,7 +311,7 @@ describe('clipboard usage', function() end) it('works with pure text clipboard', function() - execute("let g:cliplossy = 1") + feed_command("let g:cliplossy = 1") -- expect failure for block mode basic_register_test(true) end) @@ -236,7 +326,7 @@ describe('clipboard usage', function() -- "+ shouldn't have changed eq({''}, eval("g:test_clip['+']")) - execute("let g:test_clip['*'] = ['linewise stuff','']") + feed_command("let g:test_clip['*'] = ['linewise stuff','']") feed('p') expect([[ words @@ -246,7 +336,7 @@ describe('clipboard usage', function() it('does not clobber "0 when pasting', function() insert('a line') feed('yy') - execute("let g:test_clip['*'] = ['b line','']") + feed_command("let g:test_clip['*'] = ['b line','']") feed('"0pp"0p') expect([[ a line @@ -257,20 +347,20 @@ describe('clipboard usage', function() it('supports v:register and getreg() without parameters', function() eq('*', eval('v:register')) - execute("let g:test_clip['*'] = [['some block',''], 'b']") + feed_command("let g:test_clip['*'] = [['some block',''], 'b']") eq('some block', eval('getreg()')) eq('\02210', eval('getregtype()')) end) it('yanks visual selection when pasting', function() insert("indeed visual") - execute("let g:test_clip['*'] = [['clipboard'], 'c']") + feed_command("let g:test_clip['*'] = [['clipboard'], 'c']") feed("viwp") eq({{'visual'}, 'v'}, eval("g:test_clip['*']")) expect("indeed clipboard") -- explicit "* should do the same - execute("let g:test_clip['*'] = [['star'], 'c']") + feed_command("let g:test_clip['*'] = [['star'], 'c']") feed('viw"*p') eq({{'clipboard'}, 'v'}, eval("g:test_clip['*']")) expect("indeed star") @@ -279,7 +369,7 @@ describe('clipboard usage', function() it('unamed operations work even if the provider fails', function() insert('the text') feed('yy') - execute("let g:cliperror = 1") + feed_command("let g:cliperror = 1") feed('p') expect([[ the text @@ -293,20 +383,20 @@ describe('clipboard usage', function() match text ]]) - execute('g/match/d') + feed_command('g/match/d') eq('match\n', eval('getreg("*")')) feed('u') eval('setreg("*", "---")') - execute('g/test/') + feed_command('g/test/') feed('<esc>') eq('---', eval('getreg("*")')) end) end) - describe('with clipboard=unnamedplus', function() + describe('clipboard=unnamedplus', function() before_each(function() - execute('set clipboard=unnamedplus') + feed_command('set clipboard=unnamedplus') end) it('links the "+ and unnamed registers', function() @@ -319,13 +409,13 @@ describe('clipboard usage', function() -- "* shouldn't have changed eq({''}, eval("g:test_clip['*']")) - execute("let g:test_clip['+'] = ['three']") + feed_command("let g:test_clip['+'] = ['three']") feed('p') expect('twothree') end) it('and unnamed, yanks to both', function() - execute('set clipboard=unnamedplus,unnamed') + feed_command('set clipboard=unnamedplus,unnamed') insert([[ really unnamed text]]) @@ -339,8 +429,8 @@ describe('clipboard usage', function() -- unnamedplus takes predecence when pasting eq('+', eval('v:register')) - execute("let g:test_clip['+'] = ['the plus','']") - execute("let g:test_clip['*'] = ['the star','']") + feed_command("let g:test_clip['+'] = ['the plus','']") + feed_command("let g:test_clip['*'] = ['the star','']") feed("p") expect([[ text @@ -348,6 +438,7 @@ describe('clipboard usage', function() really unnamed the plus]]) end) + it('is updated on global changes', function() insert([[ text @@ -355,25 +446,32 @@ describe('clipboard usage', function() match text ]]) - execute('g/match/d') + feed_command('g/match/d') eq('match\n', eval('getreg("+")')) feed('u') eval('setreg("+", "---")') - execute('g/test/') + feed_command('g/test/') feed('<esc>') eq('---', eval('getreg("+")')) end) end) + it('sets v:register after startup', function() + reset() + eq('"', eval('v:register')) + reset('--cmd', 'set clipboard=unnamed') + eq('*', eval('v:register')) + end) + it('supports :put', function() insert("a line") - execute("let g:test_clip['*'] = ['some text']") - execute("let g:test_clip['+'] = ['more', 'text', '']") - execute(":put *") + feed_command("let g:test_clip['*'] = ['some text']") + feed_command("let g:test_clip['+'] = ['more', 'text', '']") + feed_command(":put *") expect([[ a line some text]]) - execute(":put +") + feed_command(":put +") expect([[ a line some text @@ -384,9 +482,9 @@ describe('clipboard usage', function() it('supports "+ and "* in registers', function() local screen = Screen.new(60, 10) screen:attach() - execute("let g:test_clip['*'] = ['some', 'star data','']") - execute("let g:test_clip['+'] = ['such', 'plus', 'stuff']") - execute("registers") + feed_command("let g:test_clip['*'] = ['some', 'star data','']") + feed_command("let g:test_clip['+'] = ['such', 'plus', 'stuff']") + feed_command("registers") screen:expect([[ ~ | ~ | @@ -410,17 +508,17 @@ describe('clipboard usage', function() insert('s/s/t/') feed('gg"*y$:<c-r>*<cr>') expect('t/s/t/') - execute("let g:test_clip['*'] = ['s/s/u']") + feed_command("let g:test_clip['*'] = ['s/s/u']") feed(':<c-r>*<cr>') expect('t/u/t/') end) it('supports :redir @*>', function() - execute("let g:test_clip['*'] = ['stuff']") - execute('redir @*>') + feed_command("let g:test_clip['*'] = ['stuff']") + feed_command('redir @*>') -- it is made empty eq({{''}, 'v'}, eval("g:test_clip['*']")) - execute('let g:test = doesnotexist') + feed_command('let g:test = doesnotexist') feed('<cr>') eq({{ '', @@ -428,7 +526,7 @@ describe('clipboard usage', function() 'E121: Undefined variable: doesnotexist', 'E15: Invalid expression: doesnotexist', }, 'v'}, eval("g:test_clip['*']")) - execute(':echo "Howdy!"') + feed_command(':echo "Howdy!"') eq({{ '', '', @@ -440,6 +538,8 @@ describe('clipboard usage', function() end) it('handles middleclick correctly', function() + feed_command('set mouse=a') + local screen = Screen.new(30, 5) screen:attach() insert([[ @@ -461,7 +561,7 @@ describe('clipboard usage', function() the a target]]) -- on error, fall back to unnamed register - execute("let g:cliperror = 1") + feed_command("let g:cliperror = 1") feed('<MiddleMouse><6,1>') expect([[ the source diff --git a/test/functional/cmdline/ctrl_r_spec.lua b/test/functional/cmdline/ctrl_r_spec.lua new file mode 100644 index 0000000000..d2dad23e98 --- /dev/null +++ b/test/functional/cmdline/ctrl_r_spec.lua @@ -0,0 +1,34 @@ +local helpers = require('test.functional.helpers')(after_each) +local clear, insert, funcs, eq, feed = + helpers.clear, helpers.insert, helpers.funcs, helpers.eq, helpers.feed + +describe('cmdline CTRL-R', function() + before_each(clear) + + it('pasting non-special register inserts <CR> *between* lines', function() + insert([[ + line1abc + line2somemoretext + ]]) + -- Yank 2 lines linewise, then paste to cmdline. + feed([[<C-\><C-N>gg0yj:<C-R>0]]) + -- <CR> inserted between lines, NOT after the final line. + eq('line1abc\rline2somemoretext', funcs.getcmdline()) + + -- Yank 2 lines characterwise, then paste to cmdline. + feed([[<C-\><C-N>gg05lyvj:<C-R>0]]) + -- <CR> inserted between lines, NOT after the final line. + eq('abc\rline2', funcs.getcmdline()) + + -- Yank 1 line linewise, then paste to cmdline. + feed([[<C-\><C-N>ggyy:<C-R>0]]) + -- No <CR> inserted. + eq('line1abc', funcs.getcmdline()) + end) + + it('pasting special register inserts <CR>, <NL>', function() + feed([[:<C-R>="foo\nbar\rbaz"<CR>]]) + eq('foo\nbar\rbaz', funcs.getcmdline()) + end) +end) + diff --git a/test/functional/ex_getln/history_spec.lua b/test/functional/cmdline/history_spec.lua index 20f9cf06a2..20f9cf06a2 100644 --- a/test/functional/ex_getln/history_spec.lua +++ b/test/functional/cmdline/history_spec.lua diff --git a/test/functional/core/job_partial_spec.lua b/test/functional/core/job_partial_spec.lua deleted file mode 100644 index b60f239db9..0000000000 --- a/test/functional/core/job_partial_spec.lua +++ /dev/null @@ -1,27 +0,0 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear, eq, next_msg, nvim, source = helpers.clear, helpers.eq, - helpers.next_message, helpers.nvim, helpers.source - -if helpers.pending_win32(pending) then return end - -describe('jobs with partials', function() - local channel - - before_each(function() - clear() - channel = nvim('get_api_info')[1] - nvim('set_var', 'channel', channel) - end) - - it('works correctly', function() - source([[ - function PrintArgs(a1, a2, id, data, event) - call rpcnotify(g:channel, '1', a:a1, a:a2, a:data, a:event) - endfunction - let Callback = function('PrintArgs', ["foo", "bar"]) - let g:job_opts = {'on_stdout': Callback} - call jobstart(['echo'], g:job_opts) - ]]) - eq({'notification', '1', {'foo', 'bar', {'', ''}, 'stdout'}}, next_msg()) - end) -end) diff --git a/test/functional/core/job_spec.lua b/test/functional/core/job_spec.lua index 75b50aad0a..1b8a5b1b95 100644 --- a/test/functional/core/job_spec.lua +++ b/test/functional/core/job_spec.lua @@ -1,27 +1,38 @@ local helpers = require('test.functional.helpers')(after_each) -local clear, eq, eval, execute, feed, insert, neq, next_msg, nvim, +local clear, eq, eval, exc_exec, feed_command, feed, insert, neq, next_msg, nvim, nvim_dir, ok, source, write_file, mkdir, rmdir = helpers.clear, - helpers.eq, helpers.eval, helpers.execute, helpers.feed, + helpers.eq, helpers.eval, helpers.exc_exec, helpers.feed_command, helpers.feed, helpers.insert, helpers.neq, helpers.next_message, helpers.nvim, helpers.nvim_dir, helpers.ok, helpers.source, helpers.write_file, helpers.mkdir, helpers.rmdir local command = helpers.command local wait = helpers.wait +local iswin = helpers.iswin +local get_pathsep = helpers.get_pathsep +local nvim_set = helpers.nvim_set local Screen = require('test.functional.ui.screen') -if helpers.pending_win32(pending) then return end - describe('jobs', function() local channel before_each(function() clear() + if iswin() then + helpers.set_shell_powershell() + end channel = nvim('get_api_info')[1] nvim('set_var', 'channel', channel) source([[ + function! Normalize(data) abort + " Windows: remove ^M + return type([]) == type(a:data) + \ ? map(a:data, 'substitute(v:val, "\r", "", "g")') + \ : a:data + endfunction function! s:OnEvent(id, data, event) dict let userdata = get(self, 'user') - call rpcnotify(g:channel, a:event, userdata, a:data) + let data = Normalize(a:data) + call rpcnotify(g:channel, a:event, userdata, data) endfunction let g:job_opts = { \ 'on_stdout': function('s:OnEvent'), @@ -34,23 +45,36 @@ describe('jobs', function() it('uses &shell and &shellcmdflag if passed a string', function() nvim('command', "let $VAR = 'abc'") - nvim('command', "let j = jobstart('echo $VAR', g:job_opts)") + if iswin() then + nvim('command', "let j = jobstart('echo $env:VAR', g:job_opts)") + else + nvim('command', "let j = jobstart('echo $VAR', g:job_opts)") + end eq({'notification', 'stdout', {0, {'abc', ''}}}, next_msg()) eq({'notification', 'exit', {0, 0}}, next_msg()) end) it('changes to given / directory', function() nvim('command', "let g:job_opts.cwd = '/'") - nvim('command', "let j = jobstart('pwd', g:job_opts)") - eq({'notification', 'stdout', {0, {'/', ''}}}, next_msg()) + if iswin() then + nvim('command', "let j = jobstart('pwd|%{$_.Path}', g:job_opts)") + else + nvim('command', "let j = jobstart('pwd', g:job_opts)") + end + eq({'notification', 'stdout', + {0, {(iswin() and [[C:\]] or '/'), ''}}}, next_msg()) eq({'notification', 'exit', {0, 0}}, next_msg()) end) it('changes to given `cwd` directory', function() - local dir = eval('resolve(tempname())') + local dir = eval("resolve(tempname())"):gsub("/", get_pathsep()) mkdir(dir) nvim('command', "let g:job_opts.cwd = '" .. dir .. "'") - nvim('command', "let j = jobstart('pwd', g:job_opts)") + if iswin() then + nvim('command', "let j = jobstart('pwd|%{$_.Path}', g:job_opts)") + else + nvim('command', "let j = jobstart('pwd', g:job_opts)") + end eq({'notification', 'stdout', {0, {dir, ''}}}, next_msg()) eq({'notification', 'exit', {0, 0}}, next_msg()) rmdir(dir) @@ -60,20 +84,27 @@ describe('jobs', function() local dir = eval('resolve(tempname())."-bogus"') local _, err = pcall(function() nvim('command', "let g:job_opts.cwd = '" .. dir .. "'") - nvim('command', "let j = jobstart('pwd', g:job_opts)") + if iswin() then + nvim('command', "let j = jobstart('pwd|%{$_.Path}', g:job_opts)") + else + nvim('command', "let j = jobstart('pwd', g:job_opts)") + end end) ok(string.find(err, "E475: Invalid argument: expected valid directory$") ~= nil) end) it('returns 0 when it fails to start', function() eq("", eval("v:errmsg")) - execute("let g:test_jobid = jobstart([])") + feed_command("let g:test_jobid = jobstart([])") eq(0, eval("g:test_jobid")) eq("E474:", string.match(eval("v:errmsg"), "E%d*:")) end) it('returns -1 when target is not executable #5465', function() - local function new_job() return eval([[jobstart(['echo', 'foo'])]]) end + if helpers.pending_win32(pending) then return end + local function new_job() + return eval([[jobstart('')]]) + end local executable_jobid = new_job() local nonexecutable_jobid = eval( "jobstart(['./test/functional/fixtures/non_executable.txt'])") @@ -85,12 +116,15 @@ describe('jobs', function() end) it('invokes callbacks when the job writes and exits', function() - nvim('command', "call jobstart(['echo'], g:job_opts)") + -- TODO: hangs on Windows + if helpers.pending_win32(pending) then return end + nvim('command', "call jobstart('echo', g:job_opts)") eq({'notification', 'stdout', {0, {'', ''}}}, next_msg()) eq({'notification', 'exit', {0, 0}}, next_msg()) end) it('allows interactive commands', function() + if helpers.pending_win32(pending) then return end -- TODO: Need `cat`. nvim('command', "let j = jobstart(['cat', '-'], g:job_opts)") neq(0, eval('j')) nvim('command', 'call jobsend(j, "abc\\n")') @@ -104,6 +138,7 @@ describe('jobs', function() end) it('preserves NULs', function() + if helpers.pending_win32(pending) then return end -- TODO: Need `cat`. -- Make a file with NULs in it. local filename = helpers.tmpname() write_file(filename, "abc\0def\n") @@ -121,6 +156,7 @@ describe('jobs', function() end) it("will not buffer data if it doesn't end in newlines", function() + if helpers.pending_win32(pending) then return end -- TODO: Need `cat`. if os.getenv("TRAVIS") and os.getenv("CC") == "gcc-4.9" and helpers.os_name() == "osx" then -- XXX: Hangs Travis macOS since e9061117a5b8f195c3f26a5cb94e18ddd7752d86. @@ -136,6 +172,7 @@ describe('jobs', function() end) it('preserves newlines', function() + if helpers.pending_win32(pending) then return end -- TODO: Need `cat`. nvim('command', "let j = jobstart(['cat', '-'], g:job_opts)") nvim('command', 'call jobsend(j, "a\\n\\nc\\n\\n\\n\\nb\\n\\n")') eq({'notification', 'stdout', @@ -143,6 +180,7 @@ describe('jobs', function() end) it('preserves NULs', function() + if helpers.pending_win32(pending) then return end -- TODO: Need `cat`. nvim('command', "let j = jobstart(['cat', '-'], g:job_opts)") nvim('command', 'call jobsend(j, ["\n123\n", "abc\\nxyz\n", ""])') eq({'notification', 'stdout', {0, {'\n123\n', 'abc\nxyz\n', ''}}}, @@ -152,6 +190,7 @@ describe('jobs', function() end) it('avoids sending final newline', function() + if helpers.pending_win32(pending) then return end -- TODO: Need `cat`. nvim('command', "let j = jobstart(['cat', '-'], g:job_opts)") nvim('command', 'call jobsend(j, ["some data", "without\nfinal nl"])') eq({'notification', 'stdout', {0, {'some data', 'without\nfinal nl'}}}, @@ -161,12 +200,14 @@ describe('jobs', function() end) it('closes the job streams with jobclose', function() + if helpers.pending_win32(pending) then return end -- TODO: Need `cat`. nvim('command', "let j = jobstart(['cat', '-'], g:job_opts)") nvim('command', 'call jobclose(j, "stdin")') eq({'notification', 'exit', {0, 0}}, next_msg()) end) it("disallows jobsend on a job that closed stdin", function() + if helpers.pending_win32(pending) then return end -- TODO: Need `cat`. nvim('command', "let j = jobstart(['cat', '-'], g:job_opts)") nvim('command', 'call jobclose(j, "stdin")') eq(false, pcall(function() @@ -180,17 +221,20 @@ describe('jobs', function() end) it('disallows jobstop twice on the same job', function() + if helpers.pending_win32(pending) then return end -- TODO: Need `cat`. nvim('command', "let j = jobstart(['cat', '-'], g:job_opts)") neq(0, eval('j')) eq(true, pcall(eval, "jobstop(j)")) eq(false, pcall(eval, "jobstop(j)")) end) - it('will not cause a memory leak if we leave a job running', function() + it('will not leak memory if we leave a job running', function() + if helpers.pending_win32(pending) then return end -- TODO: Need `cat`. nvim('command', "call jobstart(['cat', '-'], g:job_opts)") end) it('can get the pid value using getpid', function() + if helpers.pending_win32(pending) then return end -- TODO: Need `cat`. nvim('command', "let j = jobstart(['cat', '-'], g:job_opts)") local pid = eval('jobpid(j)') eq(0,os.execute('ps -p '..pid..' > /dev/null')) @@ -199,19 +243,21 @@ describe('jobs', function() neq(0,os.execute('ps -p '..pid..' > /dev/null')) end) - it("doesn't survive the exit of nvim", function() + it("do not survive the exit of nvim", function() + if helpers.pending_win32(pending) then return end -- use sleep, which doesn't die on stdin close - nvim('command', "let j = jobstart(['sleep', '1000'], g:job_opts)") - local pid = eval('jobpid(j)') + nvim('command', "let g:j = jobstart(['sleep', '1000'], g:job_opts)") + local pid = eval('jobpid(g:j)') eq(0,os.execute('ps -p '..pid..' > /dev/null')) clear() neq(0,os.execute('ps -p '..pid..' > /dev/null')) end) it('can survive the exit of nvim with "detach"', function() + if helpers.pending_win32(pending) then return end nvim('command', 'let g:job_opts.detach = 1') - nvim('command', "let j = jobstart(['sleep', '1000'], g:job_opts)") - local pid = eval('jobpid(j)') + nvim('command', "let g:j = jobstart(['sleep', '1000'], g:job_opts)") + local pid = eval('jobpid(g:j)') eq(0,os.execute('ps -p '..pid..' > /dev/null')) clear() eq(0,os.execute('ps -p '..pid..' > /dev/null')) @@ -221,13 +267,14 @@ describe('jobs', function() it('can pass user data to the callback', function() nvim('command', 'let g:job_opts.user = {"n": 5, "s": "str", "l": [1]}') - nvim('command', "call jobstart(['echo'], g:job_opts)") + nvim('command', [[call jobstart('echo "foo"', g:job_opts)]]) local data = {n = 5, s = 'str', l = {1}} - eq({'notification', 'stdout', {data, {'', ''}}}, next_msg()) + eq({'notification', 'stdout', {data, {'foo', ''}}}, next_msg()) eq({'notification', 'exit', {data, 0}}, next_msg()) end) it('can omit options', function() + if helpers.pending_win32(pending) then return end neq(0, nvim('eval', 'delete(".Xtestjob")')) nvim('command', "call jobstart(['touch', '.Xtestjob'])") nvim('command', "sleep 100m") @@ -238,20 +285,20 @@ describe('jobs', function() nvim('command', 'unlet g:job_opts.on_stdout') nvim('command', 'unlet g:job_opts.on_stderr') nvim('command', 'let g:job_opts.user = 5') - nvim('command', "call jobstart(['echo'], g:job_opts)") + nvim('command', [[call jobstart('echo "foo"', g:job_opts)]]) eq({'notification', 'exit', {5, 0}}, next_msg()) end) it('can omit exit callback', function() nvim('command', 'unlet g:job_opts.on_exit') nvim('command', 'let g:job_opts.user = 5') - nvim('command', "call jobstart(['echo'], g:job_opts)") - eq({'notification', 'stdout', {5, {'', ''}}}, next_msg()) + nvim('command', [[call jobstart('echo "foo"', g:job_opts)]]) + eq({'notification', 'stdout', {5, {'foo', ''}}}, next_msg()) end) it('will pass return code with the exit event', function() nvim('command', 'let g:job_opts.user = 5') - nvim('command', "call jobstart([&sh, '-c', 'exit 55'], g:job_opts)") + nvim('command', "call jobstart('exit 55', g:job_opts)") eq({'notification', 'exit', {5, 55}}, next_msg()) end) @@ -261,12 +308,13 @@ describe('jobs', function() function g:dict.on_exit(id, code, event) call rpcnotify(g:channel, a:event, a:code, self.id) endfunction - call jobstart([&sh, '-c', 'exit 45'], g:dict) + call jobstart('exit 45', g:dict) ]]) eq({'notification', 'exit', {45, 10}}, next_msg()) end) it('can redefine callbacks being used by a job', function() + if helpers.pending_win32(pending) then return end -- TODO: Need `cat`. local screen = Screen.new() screen:attach() screen:set_default_attr_ids({ @@ -298,7 +346,7 @@ describe('jobs', function() function! s:OnEvent(id, data, event) dict let g:job_result = get(self, 'user') endfunction - let s:job = jobstart(['echo'], { + let s:job = jobstart('echo "foo"', { \ 'on_stdout': 's:OnEvent', \ 'on_stderr': 's:OnEvent', \ 'on_exit': 's:OnEvent', @@ -312,14 +360,68 @@ describe('jobs', function() end) end) + it('does not repeat output with slow output handlers', function() + if helpers.pending_win32(pending) then return end + source([[ + let d = {'data': []} + function! d.on_stdout(job, data, event) dict + call add(self.data, a:data) + sleep 200m + endfunction + if has('win32') + let cmd = '1,2,3,4,5 | foreach-object -process {echo $_; sleep 0.1}' + else + let cmd = ['sh', '-c', 'for i in $(seq 1 5); do echo $i; sleep 0.1; done'] + endif + call jobwait([jobstart(cmd, d)]) + call rpcnotify(g:channel, 'data', d.data) + ]]) + eq({'notification', 'data', {{{'1', ''}, {'2', ''}, {'3', ''}, {'4', ''}, {'5', ''}}}}, next_msg()) + end) + + it('jobstart() works with partial functions', function() + source([[ + function PrintArgs(a1, a2, id, data, event) + " Windows: remove ^M + let normalized = map(a:data, 'substitute(v:val, "\r", "", "g")') + call rpcnotify(g:channel, '1', a:a1, a:a2, normalized, a:event) + endfunction + let Callback = function('PrintArgs', ["foo", "bar"]) + let g:job_opts = {'on_stdout': Callback} + call jobstart('echo "some text"', g:job_opts) + ]]) + eq({'notification', '1', {'foo', 'bar', {'some text', ''}, 'stdout'}}, next_msg()) + end) + + it('jobstart() works with closures', function() + source([[ + fun! MkFun() + let a1 = 'foo' + let a2 = 'bar' + return {id, data, event -> rpcnotify(g:channel, '1', a1, a2, Normalize(data), event)} + endfun + let g:job_opts = {'on_stdout': MkFun()} + call jobstart('echo "some text"', g:job_opts) + ]]) + eq({'notification', '1', {'foo', 'bar', {'some text', ''}, 'stdout'}}, next_msg()) + end) + + it('jobstart() works when closure passed directly to `jobstart`', function() + source([[ + let g:job_opts = {'on_stdout': {id, data, event -> rpcnotify(g:channel, '1', 'foo', 'bar', Normalize(data), event)}} + call jobstart('echo "some text"', g:job_opts) + ]]) + eq({'notification', '1', {'foo', 'bar', {'some text', ''}, 'stdout'}}, next_msg()) + end) + describe('jobwait', function() it('returns a list of status codes', function() source([[ call rpcnotify(g:channel, 'wait', jobwait([ - \ jobstart([&sh, '-c', 'sleep 0.10; exit 4']), - \ jobstart([&sh, '-c', 'sleep 0.110; exit 5']), - \ jobstart([&sh, '-c', 'sleep 0.210; exit 6']), - \ jobstart([&sh, '-c', 'sleep 0.310; exit 7']) + \ jobstart('sleep 0.10; exit 4'), + \ jobstart('sleep 0.110; exit 5'), + \ jobstart('sleep 0.210; exit 6'), + \ jobstart('sleep 0.310; exit 7') \ ])) ]]) eq({'notification', 'wait', {{4, 5, 6, 7}}}, next_msg()) @@ -336,10 +438,10 @@ describe('jobs', function() let g:exits += 1 endfunction call jobwait([ - \ jobstart([&sh, '-c', 'sleep 0.010; exit 5'], g:dict), - \ jobstart([&sh, '-c', 'sleep 0.030; exit 5'], g:dict), - \ jobstart([&sh, '-c', 'sleep 0.050; exit 5'], g:dict), - \ jobstart([&sh, '-c', 'sleep 0.070; exit 5'], g:dict) + \ jobstart('sleep 0.010; exit 5', g:dict), + \ jobstart('sleep 0.030; exit 5', g:dict), + \ jobstart('sleep 0.050; exit 5', g:dict), + \ jobstart('sleep 0.070; exit 5', g:dict) \ ]) call rpcnotify(g:channel, 'wait', g:exits) ]]) @@ -349,10 +451,10 @@ describe('jobs', function() it('will return status codes in the order of passed ids', function() source([[ call rpcnotify(g:channel, 'wait', jobwait([ - \ jobstart([&sh, '-c', 'sleep 0.070; exit 4']), - \ jobstart([&sh, '-c', 'sleep 0.050; exit 5']), - \ jobstart([&sh, '-c', 'sleep 0.030; exit 6']), - \ jobstart([&sh, '-c', 'sleep 0.010; exit 7']) + \ jobstart('sleep 0.070; exit 4'), + \ jobstart('sleep 0.050; exit 5'), + \ jobstart('sleep 0.030; exit 6'), + \ jobstart('sleep 0.010; exit 7') \ ])) ]]) eq({'notification', 'wait', {{4, 5, 6, 7}}}, next_msg()) @@ -362,22 +464,23 @@ describe('jobs', function() source([[ call rpcnotify(g:channel, 'wait', jobwait([ \ -10, - \ jobstart([&sh, '-c', 'sleep 0.01; exit 5']), + \ jobstart('sleep 0.01; exit 5'), \ ])) ]]) eq({'notification', 'wait', {{-3, 5}}}, next_msg()) end) it('will return -2 when interrupted', function() - execute('call rpcnotify(g:channel, "ready") | '.. + feed_command('call rpcnotify(g:channel, "ready") | '.. 'call rpcnotify(g:channel, "wait", '.. - 'jobwait([jobstart([&sh, "-c", "sleep 10; exit 55"])]))') + 'jobwait([jobstart("sleep 10; exit 55")]))') eq({'notification', 'ready', {}}, next_msg()) feed('<c-c>') eq({'notification', 'wait', {{-2}}}, next_msg()) end) it('can be called recursively', function() + if helpers.pending_win32(pending) then return end -- TODO: Need `cat`. source([[ let g:opts = {} let g:counter = 0 @@ -408,11 +511,11 @@ describe('jobs', function() let j.state = 0 let j.counter = g:counter call jobwait([ - \ jobstart([&sh, '-c', 'echo ready; cat -'], j), + \ jobstart('echo ready; cat -', j), \ ]) endfunction ]]) - execute('call Run()') + feed_command('call Run()') local r for i = 10, 1, -1 do r = next_msg() @@ -424,11 +527,12 @@ describe('jobs', function() end) describe('with timeout argument', function() + if helpers.pending_win32(pending) then return end it('will return -1 if the wait timed out', function() source([[ call rpcnotify(g:channel, 'wait', jobwait([ - \ jobstart([&sh, '-c', 'exit 4']), - \ jobstart([&sh, '-c', 'sleep 10; exit 5']), + \ jobstart('exit 4'), + \ jobstart('sleep 10; exit 5'), \ ], 100)) ]]) eq({'notification', 'wait', {{4, -1}}}, next_msg()) @@ -437,8 +541,8 @@ describe('jobs', function() it('can pass 0 to check if a job exists', function() source([[ call rpcnotify(g:channel, 'wait', jobwait([ - \ jobstart([&sh, '-c', 'sleep 0.05; exit 4']), - \ jobstart([&sh, '-c', 'sleep 0.3; exit 5']), + \ jobstart('sleep 0.05; exit 4'), + \ jobstart('sleep 0.3; exit 5'), \ ], 0)) ]]) eq({'notification', 'wait', {{-1, -1}}}, next_msg()) @@ -457,6 +561,7 @@ describe('jobs', function() end) it('cannot have both rpc and pty options', function() + if helpers.pending_win32(pending) then return end -- TODO: Need `cat`. command("let g:job_opts.pty = v:true") command("let g:job_opts.rpc = v:true") local _, err = pcall(command, "let j = jobstart(['cat', '-'], g:job_opts)") @@ -464,6 +569,7 @@ describe('jobs', function() end) describe('running tty-test program', function() + if helpers.pending_win32(pending) then return end local function next_chunk() local rv while true do @@ -486,8 +592,14 @@ describe('jobs', function() end before_each(function() - -- the full path to tty-test seems to be required when running on travis. - insert(nvim_dir .. '/tty-test') + -- Redefine Normalize() so that TTY data is not munged. + source([[ + function! Normalize(data) abort + return a:data + endfunction + ]]) + local ext = iswin() and '.exe' or '' + insert(nvim_dir..'/tty-test'..ext) -- Full path to tty-test. nvim('command', 'let g:job_opts.pty = 1') nvim('command', 'let exec = [expand("<cfile>:p")]') nvim('command', "let j = jobstart(exec, g:job_opts)") @@ -512,6 +624,26 @@ describe('jobs', function() msg = (msg[2] == 'stdout') and next_msg() or msg -- Skip stdout, if any. eq({'notification', 'exit', {0, 42}}, msg) end) + + it('jobstart() does not keep ptmx file descriptor open', function() + -- Start another job (using libuv) + command('let g:job_opts.pty = 0') + local other_jobid = eval("jobstart(['cat', '-'], g:job_opts)") + local other_pid = eval('jobpid(' .. other_jobid .. ')') + + -- Other job doesn't block first job from recieving SIGHUP on jobclose() + command('call jobclose(j)') + -- Have to wait so that the SIGHUP can be processed by tty-test on time. + -- Can't wait for the next message in case this test fails, if it fails + -- there won't be any more messages, and the test would hang. + helpers.sleep(100) + local err = exc_exec('call jobpid(j)') + eq('Vim(call):E900: Invalid job id', err) + + -- cleanup + eq(other_pid, eval('jobpid(' .. other_jobid .. ')')) + command('call jobstop(' .. other_jobid .. ')') + end) end) end) @@ -535,20 +667,22 @@ describe("pty process teardown", function() end) it("does not prevent/delay exit. #4798 #4900", function() + if helpers.pending_win32(pending) then return end -- Use a nested nvim (in :term) to test without --headless. - execute(":terminal '"..helpers.nvim_prog + feed_command(":terminal '"..helpers.nvim_prog + .."' -u NONE -i NONE --cmd '"..nvim_set.."' " -- Use :term again in the _nested_ nvim to get a PTY process. -- Use `sleep` to simulate a long-running child of the PTY. - .."' +terminal +'!(sleep 300 &)' +qa") + .."+terminal +'!(sleep 300 &)' +qa") -- Exiting should terminate all descendants (PTY, its children, ...). screen:expect([[ - | + ^ | [Process exited 0] | | | | - -- TERMINAL -- | + | ]]) end) end) diff --git a/test/functional/eval/api_functions_spec.lua b/test/functional/eval/api_functions_spec.lua index 21dd228145..fea4a87a26 100644 --- a/test/functional/eval/api_functions_spec.lua +++ b/test/functional/eval/api_functions_spec.lua @@ -1,7 +1,7 @@ local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') local lfs = require('lfs') -local neq, eq, execute = helpers.neq, helpers.eq, helpers.execute +local neq, eq, command = helpers.neq, helpers.eq, helpers.command local clear, curbufmeths = helpers.clear, helpers.curbufmeths local exc_exec, expect, eval = helpers.exc_exec, helpers.expect, helpers.eval local insert = helpers.insert @@ -10,17 +10,17 @@ describe('api functions', function() before_each(clear) it("work", function() - execute("call nvim_command('let g:test = 1')") + command("call nvim_command('let g:test = 1')") eq(1, eval("nvim_get_var('test')")) local buf = eval("nvim_get_current_buf()") - execute("call nvim_buf_set_lines("..buf..", 0, -1, v:true, ['aa', 'bb'])") + command("call nvim_buf_set_lines("..buf..", 0, -1, v:true, ['aa', 'bb'])") expect([[ aa bb]]) - execute("call nvim_win_set_cursor(0, [1, 1])") - execute("call nvim_input('ax<esc>')") + command("call nvim_win_set_cursor(0, [1, 1])") + command("call nvim_input('ax<esc>')") expect([[ aax bb]]) @@ -57,7 +57,7 @@ describe('api functions', function() eq(bnr, bhnd) eq(wid, whnd) - execute("new") -- creates new buffer and new window + command("new") -- creates new buffer and new window local bnr2 = eval("bufnr('')") local bhnd2 = eval("nvim_get_current_buf()") local wid2 = eval("win_getid()") @@ -69,7 +69,7 @@ describe('api functions', function() -- 0 is synonymous to the current buffer eq(bnr2, eval("nvim_buf_get_number(0)")) - execute("bn") -- show old buffer in new window + command("bn") -- show old buffer in new window eq(bnr, eval("nvim_get_current_buf()")) eq(bnr, eval("bufnr('')")) eq(bnr, eval("nvim_buf_get_number(0)")) @@ -81,7 +81,7 @@ describe('api functions', function() curbufmeths.set_lines(0, -1, true, {"aa\0", "b\0b"}) eq({'aa\n', 'b\nb'}, eval("nvim_buf_get_lines(0, 0, -1, 1)")) - execute('call nvim_buf_set_lines(0, 1, 2, v:true, ["xx", "\\nyy"])') + command('call nvim_buf_set_lines(0, 1, 2, v:true, ["xx", "\\nyy"])') eq({'aa\0', 'xx', '\0yy'}, curbufmeths.get_lines(0, -1, 1)) end) @@ -106,7 +106,7 @@ describe('api functions', function() it('have metadata accessible with api_info()', function() local api_keys = eval("sort(keys(api_info()))") - eq({'error_types', 'functions', 'types', 'version'}, api_keys) + eq({'error_types', 'functions', 'types', 'ui_events', 'version'}, api_keys) end) it('are highlighted by vim.vim syntax file', function() @@ -124,9 +124,9 @@ describe('api functions', function() [5] = {bold = true, foreground = Screen.colors.Blue}, }) - execute("set ft=vim") - execute("let &rtp='build/runtime/,'.&rtp") - execute("syntax on") + command("set ft=vim") + command("let &rtp='build/runtime/,'.&rtp") + command("syntax on") insert([[ call bufnr('%') call nvim_input('typing...') diff --git a/test/functional/eval/backtick_expansion_spec.lua b/test/functional/eval/backtick_expansion_spec.lua new file mode 100644 index 0000000000..81e8e295fa --- /dev/null +++ b/test/functional/eval/backtick_expansion_spec.lua @@ -0,0 +1,42 @@ +local lfs = require('lfs') +local helpers = require('test.functional.helpers')(after_each) +local clear, command, eval, eq = helpers.clear, helpers.command, helpers.eval, helpers.eq +local write_file = helpers.write_file + +describe("backtick expansion", function() + setup(function() + clear() + lfs.mkdir("test-backticks") + write_file("test-backticks/file1", "test file 1") + write_file("test-backticks/file2", "test file 2") + write_file("test-backticks/file3", "test file 3") + lfs.mkdir("test-backticks/subdir") + write_file("test-backticks/subdir/file4", "test file 4") + -- Long path might cause "Press ENTER" prompt; use :silent to avoid it. + command('silent cd test-backticks') + end) + + teardown(function() + helpers.rmdir('test-backticks') + end) + + it("with default 'shell'", function() + if helpers.pending_win32(pending) then return end -- Need win32 shell fixes + command(":silent args `echo ***2`") + eq({ "file2", }, eval("argv()")) + command(":silent args `echo */*4`") + eq({ "subdir/file4", }, eval("argv()")) + end) + + it("with shell=fish", function() + if eval("executable('fish')") == 0 then + pending('missing "fish" command') + return + end + command("set shell=fish") + command(":silent args `echo ***2`") + eq({ "file2", }, eval("argv()")) + command(":silent args `echo */*4`") + eq({ "subdir/file4", }, eval("argv()")) + end) +end) diff --git a/test/functional/eval/buf_functions_spec.lua b/test/functional/eval/buf_functions_spec.lua new file mode 100644 index 0000000000..db50874c53 --- /dev/null +++ b/test/functional/eval/buf_functions_spec.lua @@ -0,0 +1,302 @@ +local helpers = require('test.functional.helpers')(after_each) + +local lfs = require('lfs') + +local eq = helpers.eq +local clear = helpers.clear +local funcs = helpers.funcs +local meths = helpers.meths +local command = helpers.command +local exc_exec = helpers.exc_exec +local bufmeths = helpers.bufmeths +local winmeths = helpers.winmeths +local curbufmeths = helpers.curbufmeths +local curwinmeths = helpers.curwinmeths +local curtabmeths = helpers.curtabmeths +local get_pathsep = helpers.get_pathsep + +local fname = 'Xtest-functional-eval-buf_functions' +local fname2 = fname .. '.2' +local dirname = fname .. '.d' + +before_each(clear) + +for _, func in ipairs({'bufname(%s)', 'bufnr(%s)', 'bufwinnr(%s)', + 'getbufline(%s, 1)', 'getbufvar(%s, "changedtick")', + 'setbufvar(%s, "f", 0)'}) do + local funcname = func:match('%w+') + describe(funcname .. '() function', function() + it('errors out when receives v:true/v:false/v:null', function() + -- Not compatible with Vim: in Vim it always results in buffer not found + -- without any error messages. + for _, var in ipairs({'v:true', 'v:false', 'v:null'}) do + eq('Vim(call):E5300: Expected a Number or a String', + exc_exec('call ' .. func:format(var))) + end + end) + it('errors out when receives invalid argument', function() + eq('Vim(call):E745: Expected a Number or a String, List found', + exc_exec('call ' .. func:format('[]'))) + eq('Vim(call):E728: Expected a Number or a String, Dictionary found', + exc_exec('call ' .. func:format('{}'))) + eq('Vim(call):E805: Expected a Number or a String, Float found', + exc_exec('call ' .. func:format('0.0'))) + eq('Vim(call):E703: Expected a Number or a String, Funcref found', + exc_exec('call ' .. func:format('function("tr")'))) + end) + end) +end + +describe('bufname() function', function() + it('returns empty string when buffer was not found', function() + command('file ' .. fname) + eq('', funcs.bufname(2)) + eq('', funcs.bufname('non-existent-buffer')) + eq('', funcs.bufname('#')) + command('edit ' .. fname2) + eq(2, funcs.bufnr('%')) + eq('', funcs.bufname('X')) + end) + before_each(function() + lfs.mkdir(dirname) + end) + after_each(function() + lfs.rmdir(dirname) + end) + it('returns expected buffer name', function() + eq('', funcs.bufname('%')) -- Buffer has no name yet + command('file ' .. fname) + local wd = lfs.currentdir() + local sep = get_pathsep() + local curdirname = funcs.fnamemodify(wd, ':t') + for _, arg in ipairs({'%', 1, 'X', wd}) do + eq(fname, funcs.bufname(arg)) + meths.set_current_dir('..') + eq(curdirname .. sep .. fname, funcs.bufname(arg)) + meths.set_current_dir(curdirname) + meths.set_current_dir(dirname) + eq(wd .. sep .. fname, funcs.bufname(arg)) + meths.set_current_dir('..') + eq(fname, funcs.bufname(arg)) + command('enew') + end + eq('', funcs.bufname('%')) + eq('', funcs.bufname('$')) + eq(2, funcs.bufnr('%')) + end) +end) + +describe('bufnr() function', function() + it('returns -1 when buffer was not found', function() + command('file ' .. fname) + eq(-1, funcs.bufnr(2)) + eq(-1, funcs.bufnr('non-existent-buffer')) + eq(-1, funcs.bufnr('#')) + command('edit ' .. fname2) + eq(2, funcs.bufnr('%')) + eq(-1, funcs.bufnr('X')) + end) + it('returns expected buffer number', function() + eq(1, funcs.bufnr('%')) + command('file ' .. fname) + local wd = lfs.currentdir() + local curdirname = funcs.fnamemodify(wd, ':t') + eq(1, funcs.bufnr(fname)) + eq(1, funcs.bufnr(wd)) + eq(1, funcs.bufnr(curdirname)) + eq(1, funcs.bufnr('X')) + end) + it('returns number of last buffer with "$"', function() + eq(1, funcs.bufnr('$')) + command('new') + eq(2, funcs.bufnr('$')) + command('new') + eq(3, funcs.bufnr('$')) + command('only') + eq(3, funcs.bufnr('$')) + eq(3, funcs.bufnr('%')) + command('buffer 1') + eq(3, funcs.bufnr('$')) + eq(1, funcs.bufnr('%')) + command('bwipeout 2') + eq(3, funcs.bufnr('$')) + eq(1, funcs.bufnr('%')) + command('bwipeout 3') + eq(1, funcs.bufnr('$')) + eq(1, funcs.bufnr('%')) + command('new') + eq(4, funcs.bufnr('$')) + end) +end) + +describe('bufwinnr() function', function() + it('returns -1 when buffer was not found', function() + command('file ' .. fname) + eq(-1, funcs.bufwinnr(2)) + eq(-1, funcs.bufwinnr('non-existent-buffer')) + eq(-1, funcs.bufwinnr('#')) + command('split ' .. fname2) -- It would be OK if there was one window + eq(2, funcs.bufnr('%')) + eq(-1, funcs.bufwinnr('X')) + end) + before_each(function() + lfs.mkdir(dirname) + end) + after_each(function() + lfs.rmdir(dirname) + end) + it('returns expected window number', function() + eq(1, funcs.bufwinnr('%')) + command('file ' .. fname) + command('vsplit') + command('split ' .. fname2) + eq(2, funcs.bufwinnr(fname)) + eq(1, funcs.bufwinnr(fname2)) + eq(-1, funcs.bufwinnr(fname:sub(1, #fname - 1))) + meths.set_current_dir(dirname) + eq(2, funcs.bufwinnr(fname)) + eq(1, funcs.bufwinnr(fname2)) + eq(-1, funcs.bufwinnr(fname:sub(1, #fname - 1))) + eq(1, funcs.bufwinnr('%')) + eq(2, funcs.bufwinnr(1)) + eq(1, funcs.bufwinnr(2)) + eq(-1, funcs.bufwinnr(3)) + eq(1, funcs.bufwinnr('$')) + end) +end) + +describe('getbufline() function', function() + it('returns empty list when buffer was not found', function() + command('file ' .. fname) + eq({}, funcs.getbufline(2, 1)) + eq({}, funcs.getbufline('non-existent-buffer', 1)) + eq({}, funcs.getbufline('#', 1)) + command('edit ' .. fname2) + eq(2, funcs.bufnr('%')) + eq({}, funcs.getbufline('X', 1)) + end) + it('returns empty list when range is invalid', function() + eq({}, funcs.getbufline(1, 0)) + curbufmeths.set_lines(0, 1, false, {'foo', 'bar', 'baz'}) + eq({}, funcs.getbufline(1, 2, 1)) + eq({}, funcs.getbufline(1, -10, -20)) + eq({}, funcs.getbufline(1, -2, -1)) + eq({}, funcs.getbufline(1, -1, 9999)) + end) + it('returns expected lines', function() + meths.set_option('hidden', true) + command('file ' .. fname) + curbufmeths.set_lines(0, 1, false, {'foo\0', '\0bar', 'baz'}) + command('edit ' .. fname2) + curbufmeths.set_lines(0, 1, false, {'abc\0', '\0def', 'ghi'}) + eq({'foo\n', '\nbar', 'baz'}, funcs.getbufline(1, 1, 9999)) + eq({'abc\n', '\ndef', 'ghi'}, funcs.getbufline(2, 1, 9999)) + eq({'foo\n', '\nbar', 'baz'}, funcs.getbufline(1, 1, '$')) + eq({'baz'}, funcs.getbufline(1, '$', '$')) + eq({'baz'}, funcs.getbufline(1, '$', 9999)) + end) +end) + +describe('getbufvar() function', function() + it('returns empty list when buffer was not found', function() + command('file ' .. fname) + eq('', funcs.getbufvar(2, '&autoindent')) + eq('', funcs.getbufvar('non-existent-buffer', '&autoindent')) + eq('', funcs.getbufvar('#', '&autoindent')) + command('edit ' .. fname2) + eq(2, funcs.bufnr('%')) + eq('', funcs.getbufvar('X', '&autoindent')) + end) + it('returns empty list when variable/option/etc was not found', function() + command('file ' .. fname) + eq('', funcs.getbufvar(1, '&autondent')) + eq('', funcs.getbufvar(1, 'changedtic')) + end) + it('returns expected option value', function() + eq(0, funcs.getbufvar(1, '&autoindent')) + eq(0, funcs.getbufvar(1, '&l:autoindent')) + eq(0, funcs.getbufvar(1, '&g:autoindent')) + -- Also works with global-only options + eq(0, funcs.getbufvar(1, '&hidden')) + eq(0, funcs.getbufvar(1, '&l:hidden')) + eq(0, funcs.getbufvar(1, '&g:hidden')) + -- Also works with window-local options + eq(0, funcs.getbufvar(1, '&number')) + eq(0, funcs.getbufvar(1, '&l:number')) + eq(0, funcs.getbufvar(1, '&g:number')) + command('new') + -- But with window-local options it probably does not what you expect + curwinmeths.set_option('number', true) + -- (note that current windowโs buffer is 2, but getbufvar() receives 1) + eq(2, bufmeths.get_number(curwinmeths.get_buf())) + eq(1, funcs.getbufvar(1, '&number')) + eq(1, funcs.getbufvar(1, '&l:number')) + -- You can get global value though, if you find this useful. + eq(0, funcs.getbufvar(1, '&g:number')) + end) + it('returns expected variable value', function() + eq(2, funcs.getbufvar(1, 'changedtick')) + curbufmeths.set_lines(0, 1, false, {'abc\0', '\0def', 'ghi'}) + eq(3, funcs.getbufvar(1, 'changedtick')) + curbufmeths.set_var('test', true) + eq(true, funcs.getbufvar(1, 'test')) + eq({test=true, changedtick=3}, funcs.getbufvar(1, '')) + command('new') + eq(3, funcs.getbufvar(1, 'changedtick')) + eq(true, funcs.getbufvar(1, 'test')) + eq({test=true, changedtick=3}, funcs.getbufvar(1, '')) + end) +end) + +describe('setbufvar() function', function() + it('throws the error or ignores the input when buffer was not found', function() + command('file ' .. fname) + eq(0, + exc_exec('call setbufvar(2, "&autoindent", 0)')) + eq('Vim(call):E94: No matching buffer for non-existent-buffer', + exc_exec('call setbufvar("non-existent-buffer", "&autoindent", 0)')) + eq(0, + exc_exec('call setbufvar("#", "&autoindent", 0)')) + command('edit ' .. fname2) + eq(2, funcs.bufnr('%')) + eq('Vim(call):E93: More than one match for X', + exc_exec('call setbufvar("X", "&autoindent", 0)')) + end) + it('may set options, including window-local and global values', function() + local buf1 = meths.get_current_buf() + eq(false, curwinmeths.get_option('number')) + command('split') + command('new') + eq(2, bufmeths.get_number(curwinmeths.get_buf())) + funcs.setbufvar(1, '&number', true) + local windows = curtabmeths.list_wins() + eq(false, winmeths.get_option(windows[1], 'number')) + eq(true, winmeths.get_option(windows[2], 'number')) + eq(false, winmeths.get_option(windows[3], 'number')) + eq(false, winmeths.get_option(meths.get_current_win(), 'number')) + + eq(false, meths.get_option('hidden')) + funcs.setbufvar(1, '&hidden', true) + eq(true, meths.get_option('hidden')) + + eq(false, bufmeths.get_option(buf1, 'autoindent')) + funcs.setbufvar(1, '&autoindent', true) + eq(true, bufmeths.get_option(buf1, 'autoindent')) + eq('Vim(call):E355: Unknown option: xxx', + exc_exec('call setbufvar(1, "&xxx", 0)')) + end) + it('may set variables', function() + local buf1 = meths.get_current_buf() + command('split') + command('new') + eq(2, curbufmeths.get_number()) + funcs.setbufvar(1, 'number', true) + eq(true, bufmeths.get_var(buf1, 'number')) + eq('Vim(call):E461: Illegal variable name: b:', + exc_exec('call setbufvar(1, "", 0)')) + eq(true, bufmeths.get_var(buf1, 'number')) + funcs.setbufvar(1, 'changedtick', true) + -- eq(true, bufmeths.get_var(buf1, 'changedtick')) + eq(2, funcs.getbufvar(1, 'changedtick')) + end) +end) diff --git a/test/functional/eval/changedtick_spec.lua b/test/functional/eval/changedtick_spec.lua new file mode 100644 index 0000000000..60ea9fa12b --- /dev/null +++ b/test/functional/eval/changedtick_spec.lua @@ -0,0 +1,142 @@ +local helpers = require('test.functional.helpers')(after_each) + +local eq = helpers.eq +local eval = helpers.eval +local feed = helpers.feed +local clear = helpers.clear +local funcs = helpers.funcs +local meths = helpers.meths +local command = helpers.command +local exc_exec = helpers.exc_exec +local redir_exec = helpers.redir_exec +local meth_pcall = helpers.meth_pcall +local curbufmeths = helpers.curbufmeths + +before_each(clear) + +local function changedtick() + local ct = curbufmeths.get_changedtick() + eq(ct, curbufmeths.get_var('changedtick')) + eq(ct, curbufmeths.get_var('changedtick')) + eq(ct, eval('b:changedtick')) + eq(ct, eval('b:["changedtick"]')) + eq(ct, eval('b:.changedtick')) + eq(ct, funcs.getbufvar('%', 'changedtick')) + eq(ct, funcs.getbufvar('%', '').changedtick) + eq(ct, eval('b:').changedtick) + return ct +end + +describe('b:changedtick', function() + -- Ported tests from Vim-8.0.333 + it('increments', function() -- Test_changedtick_increments + -- New buffer has an empty line, tick starts at 2 + eq(2, changedtick()) + funcs.setline(1, 'hello') + eq(3, changedtick()) + eq(0, exc_exec('undo')) + -- Somehow undo counts as two changes + eq(5, changedtick()) + end) + it('is present in b: dictionary', function() + eq(2, changedtick()) + command('let d = b:') + eq(2, meths.get_var('d').changedtick) + end) + it('increments at bdel', function() + command('new') + eq(2, changedtick()) + local bnr = curbufmeths.get_number() + eq(2, bnr) + command('bdel') + eq(3, funcs.getbufvar(bnr, 'changedtick')) + eq(1, curbufmeths.get_number()) + end) + it('fails to be changed by user', function() + local ct = changedtick() + local ctn = ct + 100500 + eq(0, exc_exec('let d = b:')) + eq('\nE46: Cannot change read-only variable "b:changedtick"', + redir_exec('let b:changedtick = ' .. ctn)) + eq('\nE46: Cannot change read-only variable "b:["changedtick"]"', + redir_exec('let b:["changedtick"] = ' .. ctn)) + eq('\nE46: Cannot change read-only variable "b:.changedtick"', + redir_exec('let b:.changedtick = ' .. ctn)) + eq('\nE46: Cannot change read-only variable "d.changedtick"', + redir_exec('let d.changedtick = ' .. ctn)) + eq({false, 'Key is read-only: changedtick'}, + meth_pcall(curbufmeths.set_var, 'changedtick', ctn)) + + eq('\nE795: Cannot delete variable b:changedtick', + redir_exec('unlet b:changedtick')) + eq('\nE46: Cannot change read-only variable "b:.changedtick"', + redir_exec('unlet b:.changedtick')) + eq('\nE46: Cannot change read-only variable "b:["changedtick"]"', + redir_exec('unlet b:["changedtick"]')) + eq('\nE46: Cannot change read-only variable "d.changedtick"', + redir_exec('unlet d.changedtick')) + eq({false, 'Key is read-only: changedtick'}, + meth_pcall(curbufmeths.del_var, 'changedtick')) + eq(ct, changedtick()) + + eq('\nE46: Cannot change read-only variable "b:["changedtick"]"', + redir_exec('let b:["changedtick"] += ' .. ctn)) + eq('\nE46: Cannot change read-only variable "b:["changedtick"]"', + redir_exec('let b:["changedtick"] -= ' .. ctn)) + eq('\nE46: Cannot change read-only variable "b:["changedtick"]"', + redir_exec('let b:["changedtick"] .= ' .. ctn)) + + eq(ct, changedtick()) + + funcs.setline(1, 'hello') + + eq(ct + 1, changedtick()) + end) + it('is listed in :let output', function() + eq('\nb:changedtick #2', + redir_exec(':let b:')) + end) + it('fails to unlock b:changedtick', function() + eq(0, exc_exec('let d = b:')) + eq(0, funcs.islocked('b:changedtick')) + eq(0, funcs.islocked('d.changedtick')) + eq('\nE940: Cannot lock or unlock variable b:changedtick', + redir_exec('unlockvar b:changedtick')) + eq('\nE46: Cannot change read-only variable "d.changedtick"', + redir_exec('unlockvar d.changedtick')) + eq(0, funcs.islocked('b:changedtick')) + eq(0, funcs.islocked('d.changedtick')) + eq('\nE940: Cannot lock or unlock variable b:changedtick', + redir_exec('lockvar b:changedtick')) + eq('\nE46: Cannot change read-only variable "d.changedtick"', + redir_exec('lockvar d.changedtick')) + eq(0, funcs.islocked('b:changedtick')) + eq(0, funcs.islocked('d.changedtick')) + end) + it('is being completed', function() + feed(':echo b:<Tab><Home>let cmdline="<End>"<CR>') + eq('echo b:changedtick', meths.get_var('cmdline')) + end) + it('cannot be changed by filter() or map()', function() + eq(2, changedtick()) + eq('\nE795: Cannot delete variable filter() argument', + redir_exec('call filter(b:, 0)')) + eq('\nE742: Cannot change value of map() argument', + redir_exec('call map(b:, 0)')) + eq('\nE742: Cannot change value of map() argument', + redir_exec('call map(b:, "v:val")')) + eq(2, changedtick()) + end) + it('cannot be remove()d', function() + eq(2, changedtick()) + eq('\nE795: Cannot delete variable remove() argument', + redir_exec('call remove(b:, "changedtick")')) + eq(2, changedtick()) + end) + it('does not inherit VAR_FIXED when copying dictionary over', function() + eq(2, changedtick()) + eq('', redir_exec('let d1 = copy(b:)|let d1.changedtick = 42')) + eq('', redir_exec('let d2 = copy(b:)|unlet d2.changedtick')) + eq(2, changedtick()) + end) +end) diff --git a/test/functional/eval/container_functions_spec.lua b/test/functional/eval/container_functions_spec.lua new file mode 100644 index 0000000000..04a3248c49 --- /dev/null +++ b/test/functional/eval/container_functions_spec.lua @@ -0,0 +1,24 @@ +local helpers = require('test.functional.helpers')(after_each) + +local eq = helpers.eq +local eval = helpers.eval +local meths = helpers.meths +local clear = helpers.clear + +before_each(clear) + +describe('extend()', function() + it('suceeds to extend list with itself', function() + meths.set_var('l', {1, {}}) + eq({1, {}, 1, {}}, eval('extend(l, l)')) + eq({1, {}, 1, {}}, meths.get_var('l')) + + meths.set_var('l', {1, {}}) + eq({1, {}, 1, {}}, eval('extend(l, l, 0)')) + eq({1, {}, 1, {}}, meths.get_var('l')) + + meths.set_var('l', {1, {}}) + eq({1, 1, {}, {}}, eval('extend(l, l, 1)')) + eq({1, 1, {}, {}}, meths.get_var('l')) + end) +end) diff --git a/test/functional/eval/executable_spec.lua b/test/functional/eval/executable_spec.lua new file mode 100644 index 0000000000..c931b47221 --- /dev/null +++ b/test/functional/eval/executable_spec.lua @@ -0,0 +1,156 @@ +local helpers = require('test.functional.helpers')(after_each) +local eq, clear, call, iswin, write_file = + helpers.eq, helpers.clear, helpers.call, helpers.iswin, helpers.write_file + +describe('executable()', function() + before_each(clear) + + it('returns 1 for commands in $PATH', function() + local exe = iswin() and 'ping' or 'ls' + eq(1, call('executable', exe)) + end) + + it('returns 0 for non-existent files', function() + eq(0, call('executable', 'no_such_file_exists_209ufq23f')) + end) + + it('sibling to nvim binary', function() + -- Some executable in build/bin/, *not* in $PATH nor CWD. + local sibling_exe = 'printargs-test' + -- Windows: siblings are in Nvim's "pseudo-$PATH". + local expected = iswin() and 1 or 0 + if iswin() then + -- $PATH on AppVeyor CI might be oversized, redefine it to a minimal one. + clear({env={PATH=[[C:\Windows\system32;C:\Windows]]}}) + eq('arg1=lemon;arg2=sky;arg3=tree;', + call('system', sibling_exe..' lemon sky tree')) + end + local is_executable = call('executable', sibling_exe) + if iswin() and is_executable ~= expected then + pending('XXX: sometimes fails on AppVeyor') + end + end) + + describe('exec-bit', function() + setup(function() + clear() + write_file('Xtest_not_executable', 'non-executable file') + write_file('Xtest_executable', 'executable file (exec-bit set)') + if not iswin() then -- N/A for Windows. + call('system', {'chmod', '-x', 'Xtest_not_executable'}) + call('system', {'chmod', '+x', 'Xtest_executable'}) + end + end) + + teardown(function() + os.remove('Xtest_not_executable') + os.remove('Xtest_executable') + end) + + it('not set', function() + local expected = iswin() and 1 or 0 + eq(expected, call('executable', 'Xtest_not_executable')) + eq(expected, call('executable', './Xtest_not_executable')) + end) + + it('set, unqualified and not in $PATH', function() + local expected = iswin() and 1 or 0 + eq(expected, call('executable', 'Xtest_executable')) + end) + + it('set, qualified as a path', function() + eq(1, call('executable', './Xtest_executable')) + end) + end) +end) + +describe('executable() (Windows)', function() + if not iswin() then return end -- N/A for Unix. + + local exts = {'bat', 'exe', 'com', 'cmd'} + setup(function() + for _, ext in ipairs(exts) do + write_file('test_executable_'..ext..'.'..ext, '') + end + write_file('test_executable_zzz.zzz', '') + end) + + teardown(function() + for _, ext in ipairs(exts) do + os.remove('test_executable_'..ext..'.'..ext) + end + os.remove('test_executable_zzz.zzz') + end) + + it('tries default extensions on a filename if $PATHEXT is empty', function() + -- Empty $PATHEXT defaults to ".com;.exe;.bat;.cmd". + clear({env={PATHEXT=''}}) + for _,ext in ipairs(exts) do + eq(1, call('executable', 'test_executable_'..ext)) + end + eq(0, call('executable', 'test_executable_zzz')) + end) + + it('tries default extensions on a filepath if $PATHEXT is empty', function() + -- Empty $PATHEXT defaults to ".com;.exe;.bat;.cmd". + clear({env={PATHEXT=''}}) + for _,ext in ipairs(exts) do + eq(1, call('executable', '.\\test_executable_'..ext)) + end + eq(0, call('executable', '.\\test_executable_zzz')) + end) + + it('full path with extension', function() + -- Some executable we can expect in the test env. + local exe = 'printargs-test' + local exedir = helpers.eval("fnamemodify(v:progpath, ':h')") + local exepath = exedir..'/'..exe..'.exe' + eq(1, call('executable', exepath)) + eq('arg1=lemon;arg2=sky;arg3=tree;', + call('system', exepath..' lemon sky tree')) + end) + + it('full path without extension', function() + -- Some executable we can expect in the test env. + local exe = 'printargs-test' + local exedir = helpers.eval("fnamemodify(v:progpath, ':h')") + local exepath = exedir..'/'..exe + eq('arg1=lemon;arg2=sky;arg3=tree;', + call('system', exepath..' lemon sky tree')) + eq(1, call('executable', exepath)) + end) + + it('respects $PATHEXT when trying extensions on a filename', function() + clear({env={PATHEXT='.zzz'}}) + for _,ext in ipairs(exts) do + eq(0, call('executable', 'test_executable_'..ext)) + end + eq(1, call('executable', 'test_executable_zzz')) + end) + + it('respects $PATHEXT when trying extensions on a filepath', function() + clear({env={PATHEXT='.zzz'}}) + for _,ext in ipairs(exts) do + eq(0, call('executable', '.\\test_executable_'..ext)) + end + eq(1, call('executable', '.\\test_executable_zzz')) + end) + + it('returns 1 for any existing filename', function() + clear({env={PATHEXT=''}}) + for _,ext in ipairs(exts) do + eq(1, call('executable', 'test_executable_'..ext..'.'..ext)) + end + eq(1, call('executable', 'test_executable_zzz.zzz')) + end) + + it('returns 1 for any existing path (backslashes)', function() + clear({env={PATHEXT=''}}) + for _,ext in ipairs(exts) do + eq(1, call('executable', '.\\test_executable_'..ext..'.'..ext)) + eq(1, call('executable', './test_executable_'..ext..'.'..ext)) + end + eq(1, call('executable', '.\\test_executable_zzz.zzz')) + eq(1, call('executable', './test_executable_zzz.zzz')) + end) +end) diff --git a/test/functional/eval/execute_spec.lua b/test/functional/eval/execute_spec.lua index cc9b61b842..91966ed3dd 100644 --- a/test/functional/eval/execute_spec.lua +++ b/test/functional/eval/execute_spec.lua @@ -8,6 +8,7 @@ local exc_exec = helpers.exc_exec local funcs = helpers.funcs local Screen = require('test.functional.ui.screen') local command = helpers.command +local feed = helpers.feed describe('execute()', function() before_each(clear) @@ -21,7 +22,11 @@ describe('execute()', function() eq("\nfoo\nbar", funcs.execute({'echo "foo"', 'echo "bar"'})) end) - it('supports nested redirection', function() + it('supports nested execute("execute(...)")', function() + eq('42', funcs.execute([[echon execute("echon execute('echon 42')")]])) + end) + + it('supports nested :redir to a variable', function() source([[ function! g:Foo() let a = '' @@ -33,14 +38,39 @@ describe('execute()', function() function! g:Bar() let a = '' redir => a + silent echon "bar1" call g:Foo() + silent echon "bar2" redir END + silent echon "bar3" return a endfunction ]]) - eq('foo', funcs.execute('call g:Bar()')) + eq('top1bar1foobar2bar3', funcs.execute('echon "top1"|call g:Bar()')) + end) - eq('42', funcs.execute([[echon execute("echon execute('echon 42')")]])) + it('supports nested :redir to a register', function() + source([[ + let @a = '' + function! g:Foo() + redir @a>> + silent echon "foo" + redir END + return @a + endfunction + function! g:Bar() + redir @a>> + silent echon "bar1" + call g:Foo() + silent echon "bar2" + redir END + silent echon "bar3" + return @a + endfunction + ]]) + eq('top1bar1foobar2bar3', funcs.execute('echon "top1"|call g:Bar()')) + -- :redir itself doesn't nest, so the redirection ends in g:Foo + eq('bar1foo', eval('@a')) end) it('captures a transformed string', function() @@ -69,6 +99,25 @@ describe('execute()', function() eq('Vim:E729: using Funcref as a String', ret) end) + it('captures output with highlights', function() + eq('\nErrorMsg xxx ctermfg=15 ctermbg=1 guifg=White guibg=Red', + eval('execute("hi ErrorMsg")')) + end) + + it('does not corrupt the command display #5422', function() + local screen = Screen.new(70, 5) + screen:attach() + feed(':echo execute("hi ErrorMsg")<CR>') + screen:expect([[ + ~ | + ~ | + :echo execute("hi ErrorMsg") | + ErrorMsg xxx ctermfg=15 ctermbg=1 guifg=White guibg=Red | + Press ENTER or type command to continue^ | + ]]) + feed('<CR>') + end) + -- This matches Vim behavior. it('does not capture shell-command output', function() eq('\n:!echo "foo"\13\n', funcs.execute('!echo "foo"')) diff --git a/test/functional/eval/function_spec.lua b/test/functional/eval/function_spec.lua new file mode 100644 index 0000000000..776e760aaf --- /dev/null +++ b/test/functional/eval/function_spec.lua @@ -0,0 +1,29 @@ +local helpers = require('test.functional.helpers')(after_each) + +local clear = helpers.clear +local eq = helpers.eq +local exc_exec = helpers.exc_exec + +describe('Up to MAX_FUNC_ARGS arguments are handled by', function() + local max_func_args = 20 -- from eval.h + local range = helpers.funcs.range + + before_each(clear) + + it('printf()', function() + local printf = helpers.funcs.printf + local rep = helpers.funcs['repeat'] + local expected = '2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,' + eq(expected, printf(rep('%d,', max_func_args-1), unpack(range(2, max_func_args)))) + local ret = exc_exec('call printf("", 2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21)') + eq('Vim(call):E740: Too many arguments for function printf', ret) + end) + + it('rpcnotify()', function() + local rpcnotify = helpers.funcs.rpcnotify + local ret = rpcnotify(0, 'foo', unpack(range(3, max_func_args))) + eq(1, ret) + ret = exc_exec('call rpcnotify(0, "foo", 3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21)') + eq('Vim(call):E740: Too many arguments for function rpcnotify', ret) + end) +end) diff --git a/test/functional/eval/glob_spec.lua b/test/functional/eval/glob_spec.lua index 599b3dcdc3..b8807ecfcc 100644 --- a/test/functional/eval/glob_spec.lua +++ b/test/functional/eval/glob_spec.lua @@ -1,13 +1,13 @@ local lfs = require('lfs') local helpers = require('test.functional.helpers')(after_each) -local clear, execute, eval, eq = helpers.clear, helpers.execute, helpers.eval, helpers.eq +local clear, command, eval, eq = helpers.clear, helpers.command, helpers.eval, helpers.eq before_each(function() clear() lfs.mkdir('test-glob') -- Long path might cause "Press ENTER" prompt; use :silent to avoid it. - execute('silent cd test-glob') + command('silent cd test-glob') end) after_each(function() diff --git a/test/functional/eval/has_spec.lua b/test/functional/eval/has_spec.lua index 97b3b0e620..78c4e08fde 100644 --- a/test/functional/eval/has_spec.lua +++ b/test/functional/eval/has_spec.lua @@ -2,6 +2,7 @@ local helpers = require('test.functional.helpers')(after_each) local eq = helpers.eq local clear = helpers.clear local funcs = helpers.funcs +local iswin = helpers.iswin describe('has()', function() before_each(clear) @@ -49,4 +50,11 @@ describe('has()', function() eq(1, funcs.has("nvim-00.001.05")) end) + it('"unnamedplus"', function() + if (not iswin()) and funcs.has("clipboard") == 1 then + eq(1, funcs.has("unnamedplus")) + else + eq(0, funcs.has("unnamedplus")) + end + end) end) diff --git a/test/functional/eval/hostname_spec.lua b/test/functional/eval/hostname_spec.lua new file mode 100644 index 0000000000..6d5b64b929 --- /dev/null +++ b/test/functional/eval/hostname_spec.lua @@ -0,0 +1,17 @@ +local helpers = require('test.functional.helpers')(after_each) +local ok = helpers.ok +local call = helpers.call +local clear = helpers.clear + +describe('hostname()', function() + before_each(clear) + + it('returns hostname string', function() + local actual = call('hostname') + ok(string.len(actual) > 0) + if call('executable', 'hostname') == 1 then + local expected = string.gsub(call('system', 'hostname'), '[\n\r]', '') + helpers.eq(expected, actual) + end + end) +end) diff --git a/test/functional/eval/input_spec.lua b/test/functional/eval/input_spec.lua new file mode 100644 index 0000000000..5ae23e17d0 --- /dev/null +++ b/test/functional/eval/input_spec.lua @@ -0,0 +1,421 @@ +local helpers = require('test.functional.helpers')(after_each) +local Screen = require('test.functional.ui.screen') + +local eq = helpers.eq +local feed = helpers.feed +local meths = helpers.meths +local clear = helpers.clear +local source = helpers.source +local command = helpers.command +local exc_exec = helpers.exc_exec + +local screen + +before_each(function() + clear() + screen = Screen.new(25, 5) + screen:attach() + source([[ + hi Test ctermfg=Red guifg=Red term=bold + function CustomCompl(...) + return 'TEST' + endfunction + function CustomListCompl(...) + return ['FOO'] + endfunction + + highlight RBP1 guibg=Red + highlight RBP2 guibg=Yellow + highlight RBP3 guibg=Green + highlight RBP4 guibg=Blue + let g:NUM_LVLS = 4 + function Redraw() + redraw! + return '' + endfunction + cnoremap <expr> {REDRAW} Redraw() + function RainBowParens(cmdline) + let ret = [] + let i = 0 + let lvl = 0 + while i < len(a:cmdline) + if a:cmdline[i] is# '(' + call add(ret, [i, i + 1, 'RBP' . ((lvl % g:NUM_LVLS) + 1)]) + let lvl += 1 + elseif a:cmdline[i] is# ')' + let lvl -= 1 + call add(ret, [i, i + 1, 'RBP' . ((lvl % g:NUM_LVLS) + 1)]) + endif + let i += 1 + endwhile + return ret + endfunction + ]]) + screen:set_default_attr_ids({ + EOB={bold = true, foreground = Screen.colors.Blue1}, + T={foreground=Screen.colors.Red}, + RBP1={background=Screen.colors.Red}, + RBP2={background=Screen.colors.Yellow}, + RBP3={background=Screen.colors.Green}, + RBP4={background=Screen.colors.Blue}, + }) +end) + +describe('input()', function() + it('works with multiline prompts', function() + feed([[:call input("Test\nFoo")<CR>]]) + screen:expect([[ + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + Test | + Foo^ | + ]]) + end) + it('works with multiline prompts and :echohl', function() + feed([[:echohl Test | call input("Test\nFoo")<CR>]]) + screen:expect([[ + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {T:Test} | + {T:Foo}^ | + ]]) + command('redraw!') + screen:expect([[ + | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {T:Foo}^ | + ]]) + end) + it('allows unequal numeric arguments when using multiple args', function() + command('echohl Test') + feed([[:call input(1, 2)<CR>]]) + screen:expect([[ + | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {T:1}2^ | + ]]) + feed('<BS>') + screen:expect([[ + | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {T:1}^ | + ]]) + end) + it('allows unequal numeric values when using {opts} dictionary', function() + command('echohl Test') + meths.set_var('opts', {prompt=1, default=2, cancelreturn=3}) + feed([[:echo input(opts)<CR>]]) + screen:expect([[ + | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {T:1}2^ | + ]]) + feed('<BS>') + screen:expect([[ + | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {T:1}^ | + ]]) + feed('<Esc>') + screen:expect([[ + ^ | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {T:3} | + ]]) + end) + it('works with redraw', function() + command('echohl Test') + meths.set_var('opts', {prompt='Foo>', default='Bar'}) + feed([[:echo inputdialog(opts)<CR>]]) + screen:expect([[ + | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {T:Foo>}Bar^ | + ]]) + command('redraw!') + screen:expect([[ + | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {T:Foo>}Bar^ | + ]]) + feed('<BS>') + screen:expect([[ + | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {T:Foo>}Ba^ | + ]]) + command('redraw!') + screen:expect([[ + | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {T:Foo>}Ba^ | + ]]) + end) + it('allows omitting everything with dictionary argument', function() + command('echohl Test') + feed([[:call input({})<CR>]]) + screen:expect([[ + | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + ^ | + ]]) + end) + it('supports completion', function() + feed(':let var = input("", "", "custom,CustomCompl")<CR>') + feed('<Tab><CR>') + eq('TEST', meths.get_var('var')) + + feed(':let var = input({"completion": "customlist,CustomListCompl"})<CR>') + feed('<Tab><CR>') + eq('FOO', meths.get_var('var')) + end) + it('supports cancelreturn', function() + feed(':let var = input({"cancelreturn": "BAR"})<CR>') + feed('<Esc>') + eq('BAR', meths.get_var('var')) + end) + it('supports default string', function() + feed(':let var = input("", "DEF1")<CR>') + feed('<CR>') + eq('DEF1', meths.get_var('var')) + + feed(':let var = input({"default": "DEF2"})<CR>') + feed('<CR>') + eq('DEF2', meths.get_var('var')) + end) + it('errors out on invalid inputs', function() + eq('Vim(call):E730: using List as a String', + exc_exec('call input([])')) + eq('Vim(call):E730: using List as a String', + exc_exec('call input("", [])')) + eq('Vim(call):E730: using List as a String', + exc_exec('call input("", "", [])')) + eq('Vim(call):E730: using List as a String', + exc_exec('call input({"prompt": []})')) + eq('Vim(call):E730: using List as a String', + exc_exec('call input({"cancelreturn": []})')) + eq('Vim(call):E730: using List as a String', + exc_exec('call input({"default": []})')) + eq('Vim(call):E730: using List as a String', + exc_exec('call input({"completion": []})')) + eq('Vim(call):E5050: {opts} must be the only argument', + exc_exec('call input({}, "default")')) + eq('Vim(call):E118: Too many arguments for function: input', + exc_exec('call input("prompt> ", "default", "file", "extra")')) + end) + it('supports highlighting', function() + command('nnoremap <expr> X input({"highlight": "RainBowParens"})[-1]') + feed([[X]]) + feed('(())') + screen:expect([[ + | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {RBP1:(}{RBP2:()}{RBP1:)}^ | + ]]) + end) +end) +describe('inputdialog()', function() + it('works with multiline prompts', function() + feed([[:call inputdialog("Test\nFoo")<CR>]]) + screen:expect([[ + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + Test | + Foo^ | + ]]) + end) + it('works with multiline prompts and :echohl', function() + feed([[:echohl Test | call inputdialog("Test\nFoo")<CR>]]) + screen:expect([[ + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {T:Test} | + {T:Foo}^ | + ]]) + command('redraw!') + screen:expect([[ + | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {T:Foo}^ | + ]]) + end) + it('allows unequal numeric arguments when using multiple args', function() + command('echohl Test') + feed([[:call inputdialog(1, 2)<CR>]]) + screen:expect([[ + | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {T:1}2^ | + ]]) + feed('<BS>') + screen:expect([[ + | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {T:1}^ | + ]]) + end) + it('allows unequal numeric values when using {opts} dictionary', function() + command('echohl Test') + meths.set_var('opts', {prompt=1, default=2, cancelreturn=3}) + feed([[:echo input(opts)<CR>]]) + screen:expect([[ + | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {T:1}2^ | + ]]) + feed('<BS>') + screen:expect([[ + | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {T:1}^ | + ]]) + feed('<Esc>') + screen:expect([[ + ^ | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {T:3} | + ]]) + end) + it('works with redraw', function() + command('echohl Test') + meths.set_var('opts', {prompt='Foo>', default='Bar'}) + feed([[:echo input(opts)<CR>]]) + screen:expect([[ + | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {T:Foo>}Bar^ | + ]]) + command('redraw!') + screen:expect([[ + | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {T:Foo>}Bar^ | + ]]) + feed('<BS>') + screen:expect([[ + | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {T:Foo>}Ba^ | + ]]) + command('redraw!') + screen:expect([[ + | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {T:Foo>}Ba^ | + ]]) + end) + it('allows omitting everything with dictionary argument', function() + command('echohl Test') + feed(':echo inputdialog({})<CR>') + screen:expect([[ + | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + ^ | + ]]) + end) + it('supports completion', function() + feed(':let var = inputdialog({"completion": "customlist,CustomListCompl"})<CR>') + feed('<Tab><CR>') + eq('FOO', meths.get_var('var')) + end) + it('supports cancelreturn', function() + feed(':let var = inputdialog("", "", "CR1")<CR>') + feed('<Esc>') + eq('CR1', meths.get_var('var')) + + feed(':let var = inputdialog({"cancelreturn": "BAR"})<CR>') + feed('<Esc>') + eq('BAR', meths.get_var('var')) + end) + it('supports default string', function() + feed(':let var = inputdialog("", "DEF1")<CR>') + feed('<CR>') + eq('DEF1', meths.get_var('var')) + + feed(':let var = inputdialog({"default": "DEF2"})<CR>') + feed('<CR>') + eq('DEF2', meths.get_var('var')) + end) + it('errors out on invalid inputs', function() + eq('Vim(call):E730: using List as a String', + exc_exec('call inputdialog([])')) + eq('Vim(call):E730: using List as a String', + exc_exec('call inputdialog("", [])')) + eq('Vim(call):E730: using List as a String', + exc_exec('call inputdialog("", "", [])')) + eq('Vim(call):E730: using List as a String', + exc_exec('call inputdialog({"prompt": []})')) + eq('Vim(call):E730: using List as a String', + exc_exec('call inputdialog({"cancelreturn": []})')) + eq('Vim(call):E730: using List as a String', + exc_exec('call inputdialog({"default": []})')) + eq('Vim(call):E730: using List as a String', + exc_exec('call inputdialog({"completion": []})')) + eq('Vim(call):E5050: {opts} must be the only argument', + exc_exec('call inputdialog({}, "default")')) + eq('Vim(call):E118: Too many arguments for function: inputdialog', + exc_exec('call inputdialog("prompt> ", "default", "file", "extra")')) + end) + it('supports highlighting', function() + command('nnoremap <expr> X inputdialog({"highlight": "RainBowParens"})[-1]') + feed([[X]]) + feed('(())') + screen:expect([[ + | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {RBP1:(}{RBP2:()}{RBP1:)}^ | + ]]) + end) +end) diff --git a/test/functional/eval/json_functions_spec.lua b/test/functional/eval/json_functions_spec.lua index fc0a19bdfa..4d34cde849 100644 --- a/test/functional/eval/json_functions_spec.lua +++ b/test/functional/eval/json_functions_spec.lua @@ -4,16 +4,17 @@ local funcs = helpers.funcs local meths = helpers.meths local eq = helpers.eq local eval = helpers.eval -local execute = helpers.execute +local command = helpers.command local exc_exec = helpers.exc_exec local redir_exec = helpers.redir_exec local NIL = helpers.NIL +local source = helpers.source describe('json_decode() function', function() local restart = function(...) clear(...) - execute('language C') - execute([[ + source([[ + language C function Eq(exp, act) let act = a:act let exp = a:exp @@ -45,8 +46,6 @@ describe('json_decode() function', function() endif return 1 endfunction - ]]) - execute([[ function EvalEq(exp, act_expr) let act = eval(a:act_expr) if Eq(a:exp, act) @@ -441,7 +440,7 @@ describe('json_decode() function', function() local sp_decode_eq = function(expected, json) meths.set_var('__json', json) speq(expected, 'json_decode(g:__json)') - execute('unlet! g:__json') + command('unlet! g:__json') end it('parses strings with NUL properly', function() @@ -527,7 +526,7 @@ end) describe('json_encode() function', function() before_each(function() clear() - execute('language C') + command('language C') end) it('dumps strings', function() @@ -576,94 +575,94 @@ describe('json_encode() function', function() it('cannot dump generic mapping with generic mapping keys and values', function() - execute('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": []}') - execute('let todumpv1 = {"_TYPE": v:msgpack_types.map, "_VAL": []}') - execute('let todumpv2 = {"_TYPE": v:msgpack_types.map, "_VAL": []}') - execute('call add(todump._VAL, [todumpv1, todumpv2])') + command('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": []}') + command('let todumpv1 = {"_TYPE": v:msgpack_types.map, "_VAL": []}') + command('let todumpv2 = {"_TYPE": v:msgpack_types.map, "_VAL": []}') + command('call add(todump._VAL, [todumpv1, todumpv2])') eq('Vim(call):E474: Invalid key in special dictionary', exc_exec('call json_encode(todump)')) end) it('cannot dump generic mapping with ext key', function() - execute('let todump = {"_TYPE": v:msgpack_types.ext, "_VAL": [5, ["",""]]}') - execute('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": [[todump, 1]]}') + command('let todump = {"_TYPE": v:msgpack_types.ext, "_VAL": [5, ["",""]]}') + command('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": [[todump, 1]]}') eq('Vim(call):E474: Invalid key in special dictionary', exc_exec('call json_encode(todump)')) end) it('cannot dump generic mapping with array key', function() - execute('let todump = {"_TYPE": v:msgpack_types.array, "_VAL": [5, [""]]}') - execute('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": [[todump, 1]]}') + command('let todump = {"_TYPE": v:msgpack_types.array, "_VAL": [5, [""]]}') + command('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": [[todump, 1]]}') eq('Vim(call):E474: Invalid key in special dictionary', exc_exec('call json_encode(todump)')) end) it('cannot dump generic mapping with UINT64_MAX key', function() - execute('let todump = {"_TYPE": v:msgpack_types.integer}') - execute('let todump._VAL = [1, 3, 0x7FFFFFFF, 0x7FFFFFFF]') - execute('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": [[todump, 1]]}') + command('let todump = {"_TYPE": v:msgpack_types.integer}') + command('let todump._VAL = [1, 3, 0x7FFFFFFF, 0x7FFFFFFF]') + command('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": [[todump, 1]]}') eq('Vim(call):E474: Invalid key in special dictionary', exc_exec('call json_encode(todump)')) end) it('cannot dump generic mapping with floating-point key', function() - execute('let todump = {"_TYPE": v:msgpack_types.float, "_VAL": 0.125}') - execute('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": [[todump, 1]]}') + command('let todump = {"_TYPE": v:msgpack_types.float, "_VAL": 0.125}') + command('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": [[todump, 1]]}') eq('Vim(call):E474: Invalid key in special dictionary', exc_exec('call json_encode(todump)')) end) it('can dump generic mapping with STR special key and NUL', function() - execute('let todump = {"_TYPE": v:msgpack_types.string, "_VAL": ["\\n"]}') - execute('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": [[todump, 1]]}') + command('let todump = {"_TYPE": v:msgpack_types.string, "_VAL": ["\\n"]}') + command('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": [[todump, 1]]}') eq('{"\\u0000": 1}', eval('json_encode(todump)')) end) it('can dump generic mapping with BIN special key and NUL', function() - execute('let todump = {"_TYPE": v:msgpack_types.binary, "_VAL": ["\\n"]}') - execute('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": [[todump, 1]]}') + command('let todump = {"_TYPE": v:msgpack_types.binary, "_VAL": ["\\n"]}') + command('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": [[todump, 1]]}') eq('{"\\u0000": 1}', eval('json_encode(todump)')) end) it('can dump STR special mapping with NUL and NL', function() - execute('let todump = {"_TYPE": v:msgpack_types.string, "_VAL": ["\\n", ""]}') + command('let todump = {"_TYPE": v:msgpack_types.string, "_VAL": ["\\n", ""]}') eq('"\\u0000\\n"', eval('json_encode(todump)')) end) it('can dump BIN special mapping with NUL and NL', function() - execute('let todump = {"_TYPE": v:msgpack_types.binary, "_VAL": ["\\n", ""]}') + command('let todump = {"_TYPE": v:msgpack_types.binary, "_VAL": ["\\n", ""]}') eq('"\\u0000\\n"', eval('json_encode(todump)')) end) it('cannot dump special ext mapping', function() - execute('let todump = {"_TYPE": v:msgpack_types.ext, "_VAL": [5, ["",""]]}') + command('let todump = {"_TYPE": v:msgpack_types.ext, "_VAL": [5, ["",""]]}') eq('Vim(call):E474: Unable to convert EXT string to JSON', exc_exec('call json_encode(todump)')) end) it('can dump special array mapping', function() - execute('let todump = {"_TYPE": v:msgpack_types.array, "_VAL": [5, [""]]}') + command('let todump = {"_TYPE": v:msgpack_types.array, "_VAL": [5, [""]]}') eq('[5, [""]]', eval('json_encode(todump)')) end) it('can dump special UINT64_MAX mapping', function() - execute('let todump = {"_TYPE": v:msgpack_types.integer}') - execute('let todump._VAL = [1, 3, 0x7FFFFFFF, 0x7FFFFFFF]') + command('let todump = {"_TYPE": v:msgpack_types.integer}') + command('let todump._VAL = [1, 3, 0x7FFFFFFF, 0x7FFFFFFF]') eq('18446744073709551615', eval('json_encode(todump)')) end) it('can dump special INT64_MIN mapping', function() - execute('let todump = {"_TYPE": v:msgpack_types.integer}') - execute('let todump._VAL = [-1, 2, 0, 0]') + command('let todump = {"_TYPE": v:msgpack_types.integer}') + command('let todump._VAL = [-1, 2, 0, 0]') eq('-9223372036854775808', eval('json_encode(todump)')) end) it('can dump special BOOLEAN true mapping', function() - execute('let todump = {"_TYPE": v:msgpack_types.boolean, "_VAL": 1}') + command('let todump = {"_TYPE": v:msgpack_types.boolean, "_VAL": 1}') eq('true', eval('json_encode(todump)')) end) it('can dump special BOOLEAN false mapping', function() - execute('let todump = {"_TYPE": v:msgpack_types.boolean, "_VAL": 0}') + command('let todump = {"_TYPE": v:msgpack_types.boolean, "_VAL": 0}') eq('false', eval('json_encode(todump)')) end) it('can dump special NIL mapping', function() - execute('let todump = {"_TYPE": v:msgpack_types.nil, "_VAL": 0}') + command('let todump = {"_TYPE": v:msgpack_types.nil, "_VAL": 0}') eq('null', eval('json_encode(todump)')) end) @@ -673,7 +672,7 @@ describe('json_encode() function', function() end) it('fails to dump a partial', function() - execute('function T() dict\nendfunction') + command('function T() dict\nendfunction') eq('Vim(call):E474: Error while dumping encode_tv2json() argument, itself: attempt to dump function reference', exc_exec('call json_encode(function("T", [1, 2], {}))')) end) @@ -684,56 +683,56 @@ describe('json_encode() function', function() end) it('fails to dump a recursive list', function() - execute('let todump = [[[]]]') - execute('call add(todump[0][0], todump)') + command('let todump = [[[]]]') + command('call add(todump[0][0], todump)') eq('Vim(call):E724: unable to correctly dump variable with self-referencing container', exc_exec('call json_encode(todump)')) end) it('fails to dump a recursive dict', function() - execute('let todump = {"d": {"d": {}}}') - execute('call extend(todump.d.d, {"d": todump})') + command('let todump = {"d": {"d": {}}}') + command('call extend(todump.d.d, {"d": todump})') eq('Vim(call):E724: unable to correctly dump variable with self-referencing container', exc_exec('call json_encode([todump])')) end) it('can dump dict with two same dicts inside', function() - execute('let inter = {}') - execute('let todump = {"a": inter, "b": inter}') + command('let inter = {}') + command('let todump = {"a": inter, "b": inter}') eq('{"a": {}, "b": {}}', eval('json_encode(todump)')) end) it('can dump list with two same lists inside', function() - execute('let inter = []') - execute('let todump = [inter, inter]') + command('let inter = []') + command('let todump = [inter, inter]') eq('[[], []]', eval('json_encode(todump)')) end) it('fails to dump a recursive list in a special dict', function() - execute('let todump = {"_TYPE": v:msgpack_types.array, "_VAL": []}') - execute('call add(todump._VAL, todump)') + command('let todump = {"_TYPE": v:msgpack_types.array, "_VAL": []}') + command('call add(todump._VAL, todump)') eq('Vim(call):E724: unable to correctly dump variable with self-referencing container', exc_exec('call json_encode(todump)')) end) it('fails to dump a recursive (val) map in a special dict', function() - execute('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": []}') - execute('call add(todump._VAL, ["", todump])') + command('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": []}') + command('call add(todump._VAL, ["", todump])') eq('Vim(call):E724: unable to correctly dump variable with self-referencing container', exc_exec('call json_encode([todump])')) end) it('fails to dump a recursive (val) map in a special dict, _VAL reference', function() - execute('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": [["", []]]}') - execute('call add(todump._VAL[0][1], todump._VAL)') + command('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": [["", []]]}') + command('call add(todump._VAL[0][1], todump._VAL)') eq('Vim(call):E724: unable to correctly dump variable with self-referencing container', exc_exec('call json_encode(todump)')) end) it('fails to dump a recursive (val) special list in a special dict', function() - execute('let todump = {"_TYPE": v:msgpack_types.array, "_VAL": []}') - execute('call add(todump._VAL, ["", todump._VAL])') + command('let todump = {"_TYPE": v:msgpack_types.array, "_VAL": []}') + command('call add(todump._VAL, ["", todump._VAL])') eq('Vim(call):E724: unable to correctly dump variable with self-referencing container', exc_exec('call json_encode(todump)')) end) diff --git a/test/functional/eval/let_spec.lua b/test/functional/eval/let_spec.lua new file mode 100644 index 0000000000..1bd3405698 --- /dev/null +++ b/test/functional/eval/let_spec.lua @@ -0,0 +1,45 @@ +local helpers = require('test.functional.helpers')(after_each) + +local eq = helpers.eq +local clear = helpers.clear +local meths = helpers.meths +local redir_exec = helpers.redir_exec +local source = helpers.source + +before_each(clear) + +describe(':let command', function() + it('correctly lists variables with curly-braces', function() + meths.set_var('v', {0}) + eq('\nv [0]', redir_exec('let {"v"}')) + end) + + it('correctly lists variables with subscript', function() + meths.set_var('v', {0}) + eq('\nv[0] #0', redir_exec('let v[0]')) + eq('\ng:["v"][0] #0', redir_exec('let g:["v"][0]')) + eq('\n{"g:"}["v"][0] #0', redir_exec('let {"g:"}["v"][0]')) + end) + + it(":unlet self-referencing node in a List graph #6070", function() + -- :unlet-ing a self-referencing List must not allow GC on indirectly + -- referenced in-scope Lists. Before #6070 this caused use-after-free. + source([=[ + let [l1, l2] = [[], []] + echo 'l1:' . id(l1) + echo 'l2:' . id(l2) + echo '' + let [l3, l4] = [[], []] + call add(l4, l4) + call add(l4, l3) + call add(l3, 1) + call add(l2, l2) + call add(l2, l1) + call add(l1, 1) + unlet l2 + unlet l4 + call garbagecollect(1) + call feedkeys(":\e:echo l1 l3\n:echo 42\n:cq\n", "t") + ]=]) + end) +end) diff --git a/test/functional/eval/map_functions_spec.lua b/test/functional/eval/map_functions_spec.lua new file mode 100644 index 0000000000..e914f674aa --- /dev/null +++ b/test/functional/eval/map_functions_spec.lua @@ -0,0 +1,159 @@ +local helpers = require('test.functional.helpers')(after_each) + +local clear = helpers.clear +local eq = helpers.eq +local eval = helpers.eval +local funcs = helpers.funcs +local nvim = helpers.nvim +local source = helpers.source +local command = helpers.command + +describe('maparg()', function() + before_each(clear) + + local foo_bar_map_table = { + lhs='foo', + silent=0, + rhs='bar', + expr=0, + sid=0, + buffer=0, + nowait=0, + mode='n', + noremap=1, + } + + it('returns a dictionary', function() + nvim('command', 'nnoremap foo bar') + eq('bar', funcs.maparg('foo')) + eq(foo_bar_map_table, funcs.maparg('foo', 'n', false, true)) + end) + + it('returns 1 for silent when <silent> is used', function() + nvim('command', 'nnoremap <silent> foo bar') + eq(1, funcs.maparg('foo', 'n', false, true)['silent']) + + nvim('command', 'nnoremap baz bat') + eq(0, funcs.maparg('baz', 'n', false, true)['silent']) + end) + + it('returns an empty string when no map is present', function() + eq('', funcs.maparg('not a mapping')) + end) + + it('returns an empty dictionary when no map is present and dict is requested', function() + eq({}, funcs.maparg('not a mapping', 'n', false, true)) + end) + + it('returns the same value for noremap and <script>', function() + nvim('command', 'inoremap <script> hello world') + nvim('command', 'inoremap this that') + eq( + funcs.maparg('hello', 'i', false, true)['noremap'], + funcs.maparg('this', 'i', false, true)['noremap'] + ) + end) + + it('returns a boolean for buffer', function() + -- Open enough windows to know we aren't on buffer number 1 + nvim('command', 'new') + nvim('command', 'new') + nvim('command', 'new') + nvim('command', 'cnoremap <buffer> this that') + eq(1, funcs.maparg('this', 'c', false, true)['buffer']) + + -- Global will return 0 always + nvim('command', 'nnoremap other another') + eq(0, funcs.maparg('other', 'n', false, true)['buffer']) + end) + + it('returns script numbers', function() + source([[ + function! s:maparg_test_function() abort + return 'testing' + endfunction + + nnoremap fizz :call <SID>maparg_test_function()<CR> + ]]) + eq(1, funcs.maparg('fizz', 'n', false, true)['sid']) + eq('testing', nvim('call_function', '<SNR>1_maparg_test_function', {})) + end) + + it('works with <F12> and others', function() + source([[ + let g:maparg_test_var = 0 + + nnoremap <F12> :let g:maparg_test_var = 1<CR> + ]]) + eq(0, eval('g:maparg_test_var')) + source([[ + call feedkeys("\<F12>") + ]]) + eq(1, eval('g:maparg_test_var')) + + eq(':let g:maparg_test_var = 1<CR>', funcs.maparg('<F12>', 'n', false, true)['rhs']) + end) + + it('works with <expr>', function() + source([[ + let counter = 0 + inoremap <expr> <C-L> ListItem() + inoremap <expr> <C-R> ListReset() + + func ListItem() + let g:counter += 1 + return g:counter . '. ' + endfunc + + func ListReset() + let g:counter = 0 + return '' + endfunc + + call feedkeys("i\<C-L>") + ]]) + eq(1, eval('g:counter')) + + local map_dict = funcs.maparg('<C-L>', 'i', false, true) + eq(1, map_dict['expr']) + eq('i', map_dict['mode']) + end) + + it('works with combining characters', function() + -- Using addacutes to make combining character better visible + local function ac(s) + local acute = '\204\129' -- U+0301 COMBINING ACUTE ACCENT + local ret = s:gsub('`', acute) + return ret + end + command(ac([[ + nnoremap a b` + nnoremap c` d + nnoremap e` f` + ]])) + eq(ac('b`'), funcs.maparg(ac('a'))) + eq(ac(''), funcs.maparg(ac('c'))) + eq(ac('d'), funcs.maparg(ac('c`'))) + eq(ac('f`'), funcs.maparg(ac('e`'))) + + local function acmap(lhs, rhs) + return { + lhs = ac(lhs), + rhs = ac(rhs), + + buffer = 0, + expr = 0, + mode = 'n', + noremap = 1, + nowait = 0, + sid = 0, + silent = 0, + } + end + + eq({}, funcs.maparg(ac('c'), 'n', 0, 1)) + eq(acmap('a', 'b`'), funcs.maparg(ac('a'), 'n', 0, 1)) + eq(acmap('c`', 'd'), funcs.maparg(ac('c`'), 'n', 0, 1)) + eq(acmap('e`', 'f`'), funcs.maparg(ac('e`'), 'n', 0, 1)) + end) +end) diff --git a/test/functional/eval/match_functions_spec.lua b/test/functional/eval/match_functions_spec.lua new file mode 100644 index 0000000000..3150d89f62 --- /dev/null +++ b/test/functional/eval/match_functions_spec.lua @@ -0,0 +1,61 @@ +local helpers = require('test.functional.helpers')(after_each) + +local eq = helpers.eq +local clear = helpers.clear +local funcs = helpers.funcs +local command = helpers.command + +before_each(clear) + +describe('setmatches()', function() + it('correctly handles case when both group and pattern entries are numbers', + function() + command('hi def link 1 PreProc') + eq(0, funcs.setmatches({{group=1, pattern=2, id=3, priority=4}})) + eq({{ + group='1', + pattern='2', + id=3, + priority=4, + }}, funcs.getmatches()) + eq(0, funcs.setmatches({{group=1, pattern=2, id=3, priority=4, conceal=5}})) + eq({{ + group='1', + pattern='2', + id=3, + priority=4, + conceal='5', + }}, funcs.getmatches()) + eq(0, funcs.setmatches({{group=1, pos1={2}, pos2={6}, id=3, priority=4, conceal=5}})) + eq({{ + group='1', + pos1={2}, + pos2={6}, + id=3, + priority=4, + conceal='5', + }}, funcs.getmatches()) + end) + + it('fails with -1 if highlight group is not defined', function() + eq(-1, funcs.setmatches({{group=1, pattern=2, id=3, priority=4}})) + eq({}, funcs.getmatches()) + eq(-1, funcs.setmatches({{group=1, pos1={2}, pos2={6}, id=3, priority=4, conceal=5}})) + eq({}, funcs.getmatches()) + end) +end) + +describe('matchadd()', function() + it('correctly works when first two arguments and conceal are numbers at once', + function() + command('hi def link 1 PreProc') + eq(4, funcs.matchadd(1, 2, 3, 4, {conceal=5})) + eq({{ + group='1', + pattern='2', + priority=3, + id=4, + conceal='5', + }}, funcs.getmatches()) + end) +end) diff --git a/test/functional/eval/minmax_functions_spec.lua b/test/functional/eval/minmax_functions_spec.lua new file mode 100644 index 0000000000..c6eb754f91 --- /dev/null +++ b/test/functional/eval/minmax_functions_spec.lua @@ -0,0 +1,51 @@ +local helpers = require('test.functional.helpers')(after_each) + +local eq = helpers.eq +local eval = helpers.eval +local clear = helpers.clear +local funcs = helpers.funcs +local redir_exec = helpers.redir_exec + +before_each(clear) +for _, func in ipairs({'min', 'max'}) do + describe(func .. '()', function() + it('gives a single error message when multiple values failed conversions', + function() + eq('\nE745: Using a List as a Number\n0', + redir_exec('echo ' .. func .. '([-5, [], [], [], 5])')) + eq('\nE745: Using a List as a Number\n0', + redir_exec('echo ' .. func .. '({1:-5, 2:[], 3:[], 4:[], 5:5})')) + for errmsg, errinput in pairs({ + ['E745: Using a List as a Number'] = '[]', + ['E805: Using a Float as a Number'] = '0.0', + ['E703: Using a Funcref as a Number'] = 'function("tr")', + ['E728: Using a Dictionary as a Number'] = '{}', + }) do + eq('\n' .. errmsg .. '\n0', + redir_exec('echo ' .. func .. '([' .. errinput .. '])')) + eq('\n' .. errmsg .. '\n0', + redir_exec('echo ' .. func .. '({1:' .. errinput .. '})')) + end + end) + it('works with arrays/dictionaries with zero items', function() + eq(0, funcs[func]({})) + eq(0, eval(func .. '({})')) + end) + it('works with arrays/dictionaries with one item', function() + eq(5, funcs[func]({5})) + eq(5, funcs[func]({test=5})) + end) + it('works with NULL arrays/dictionaries', function() + eq(0, eval(func .. '(v:_null_list)')) + eq(0, eval(func .. '(v:_null_dict)')) + end) + it('errors out for invalid types', function() + for _, errinput in ipairs({'1', 'v:true', 'v:false', 'v:null', + 'function("tr")', '""'}) do + eq(('\nE712: Argument of %s() must be a List or Dictionary\n0'):format( + func), + redir_exec('echo ' .. func .. '(' .. errinput .. ')')) + end + end) + end) +end diff --git a/test/functional/eval/modeline_spec.lua b/test/functional/eval/modeline_spec.lua index 0be7210a76..c5bb798f4a 100644 --- a/test/functional/eval/modeline_spec.lua +++ b/test/functional/eval/modeline_spec.lua @@ -1,5 +1,5 @@ local helpers = require('test.functional.helpers')(after_each) -local clear, execute, write_file = helpers.clear, helpers.execute, helpers.write_file +local clear, command, write_file = helpers.clear, helpers.command, helpers.write_file local eq, eval = helpers.eq, helpers.eval describe("modeline", function() @@ -12,7 +12,7 @@ describe("modeline", function() it('does not crash with a large version number', function() write_file(tempfile, 'vim100000000000000000000000') - execute('e! ' .. tempfile) + command('e! ' .. tempfile) eq(2, eval('1+1')) -- Still alive? end) diff --git a/test/functional/eval/msgpack_functions_spec.lua b/test/functional/eval/msgpack_functions_spec.lua index 44c01d2226..b241635dfe 100644 --- a/test/functional/eval/msgpack_functions_spec.lua +++ b/test/functional/eval/msgpack_functions_spec.lua @@ -2,7 +2,7 @@ local helpers = require('test.functional.helpers')(after_each) local clear = helpers.clear local funcs = helpers.funcs local eval, eq = helpers.eval, helpers.eq -local execute = helpers.execute +local command = helpers.command local nvim = helpers.nvim local exc_exec = helpers.exc_exec @@ -331,13 +331,14 @@ describe('msgpack*() functions', function() obj_test('are able to dump and restore floating-point value', {0.125}) it('can restore and dump UINT64_MAX', function() - execute('let dumped = ["\\xCF" . repeat("\\xFF", 8)]') - execute('let parsed = msgpackparse(dumped)') - execute('let dumped2 = msgpackdump(parsed)') + command('let dumped = ["\\xCF" . repeat("\\xFF", 8)]') + command('let parsed = msgpackparse(dumped)') + command('let dumped2 = msgpackdump(parsed)') eq(1, eval('type(parsed[0]) == type(0) ' .. '|| parsed[0]._TYPE is v:msgpack_types.integer')) if eval('type(parsed[0]) == type(0)') == 1 then - eq(1, eval('0xFFFFFFFFFFFFFFFF == parsed[0]')) + command('call assert_equal(0xFFFFFFFFFFFFFFFF, parsed[0])') + eq({}, eval('v:errors')) else eq({_TYPE={}, _VAL={1, 3, 0x7FFFFFFF, 0x7FFFFFFF}}, eval('parsed[0]')) end @@ -345,13 +346,14 @@ describe('msgpack*() functions', function() end) it('can restore and dump INT64_MIN', function() - execute('let dumped = ["\\xD3\\x80" . repeat("\\n", 7)]') - execute('let parsed = msgpackparse(dumped)') - execute('let dumped2 = msgpackdump(parsed)') + command('let dumped = ["\\xD3\\x80" . repeat("\\n", 7)]') + command('let parsed = msgpackparse(dumped)') + command('let dumped2 = msgpackdump(parsed)') eq(1, eval('type(parsed[0]) == type(0) ' .. '|| parsed[0]._TYPE is v:msgpack_types.integer')) if eval('type(parsed[0]) == type(0)') == 1 then - eq(1, eval('-0x8000000000000000 == parsed[0]')) + command('call assert_equal(-0x7fffffffffffffff - 1, parsed[0])') + eq({}, eval('v:errors')) else eq({_TYPE={}, _VAL={-1, 2, 0, 0}}, eval('parsed[0]')) end @@ -359,33 +361,33 @@ describe('msgpack*() functions', function() end) it('can restore and dump BIN string with zero byte', function() - execute('let dumped = ["\\xC4\\x01\\n"]') - execute('let parsed = msgpackparse(dumped)') - execute('let dumped2 = msgpackdump(parsed)') + command('let dumped = ["\\xC4\\x01\\n"]') + command('let parsed = msgpackparse(dumped)') + command('let dumped2 = msgpackdump(parsed)') eq({{_TYPE={}, _VAL={'\n'}}}, eval('parsed')) eq(1, eval('parsed[0]._TYPE is v:msgpack_types.binary')) eq(1, eval('dumped ==# dumped2')) end) it('can restore and dump STR string with zero byte', function() - execute('let dumped = ["\\xA1\\n"]') - execute('let parsed = msgpackparse(dumped)') - execute('let dumped2 = msgpackdump(parsed)') + command('let dumped = ["\\xA1\\n"]') + command('let parsed = msgpackparse(dumped)') + command('let dumped2 = msgpackdump(parsed)') eq({{_TYPE={}, _VAL={'\n'}}}, eval('parsed')) eq(1, eval('parsed[0]._TYPE is v:msgpack_types.string')) eq(1, eval('dumped ==# dumped2')) end) it('can restore and dump BIN string with NL', function() - execute('let dumped = ["\\xC4\\x01", ""]') - execute('let parsed = msgpackparse(dumped)') - execute('let dumped2 = msgpackdump(parsed)') + command('let dumped = ["\\xC4\\x01", ""]') + command('let parsed = msgpackparse(dumped)') + command('let dumped2 = msgpackdump(parsed)') eq({"\n"}, eval('parsed')) eq(1, eval('dumped ==# dumped2')) end) it('dump and restore special mapping with floating-point value', function() - execute('let todump = {"_TYPE": v:msgpack_types.float, "_VAL": 0.125}') + command('let todump = {"_TYPE": v:msgpack_types.float, "_VAL": 0.125}') eq({0.125}, eval('msgpackparse(msgpackdump([todump]))')) end) end) @@ -394,52 +396,53 @@ describe('msgpackparse() function', function() before_each(clear) it('restores nil as v:null', function() - execute('let dumped = ["\\xC0"]') - execute('let parsed = msgpackparse(dumped)') + command('let dumped = ["\\xC0"]') + command('let parsed = msgpackparse(dumped)') eq('[v:null]', eval('string(parsed)')) end) it('restores boolean false as v:false', function() - execute('let dumped = ["\\xC2"]') - execute('let parsed = msgpackparse(dumped)') + command('let dumped = ["\\xC2"]') + command('let parsed = msgpackparse(dumped)') eq({false}, eval('parsed')) end) it('restores boolean true as v:true', function() - execute('let dumped = ["\\xC3"]') - execute('let parsed = msgpackparse(dumped)') + command('let dumped = ["\\xC3"]') + command('let parsed = msgpackparse(dumped)') eq({true}, eval('parsed')) end) it('restores FIXSTR as special dict', function() - execute('let dumped = ["\\xa2ab"]') - execute('let parsed = msgpackparse(dumped)') + command('let dumped = ["\\xa2ab"]') + command('let parsed = msgpackparse(dumped)') eq({{_TYPE={}, _VAL={'ab'}}}, eval('parsed')) eq(1, eval('g:parsed[0]._TYPE is v:msgpack_types.string')) end) it('restores BIN 8 as string', function() - execute('let dumped = ["\\xC4\\x02ab"]') + command('let dumped = ["\\xC4\\x02ab"]') eq({'ab'}, eval('msgpackparse(dumped)')) end) it('restores FIXEXT1 as special dictionary', function() - execute('let dumped = ["\\xD4\\x10", ""]') - execute('let parsed = msgpackparse(dumped)') + command('let dumped = ["\\xD4\\x10", ""]') + command('let parsed = msgpackparse(dumped)') eq({{_TYPE={}, _VAL={0x10, {"", ""}}}}, eval('parsed')) eq(1, eval('g:parsed[0]._TYPE is v:msgpack_types.ext')) end) it('restores MAP with BIN key as special dictionary', function() - execute('let dumped = ["\\x81\\xC4\\x01a\\xC4\\n"]') - execute('let parsed = msgpackparse(dumped)') + command('let dumped = ["\\x81\\xC4\\x01a\\xC4\\n"]') + command('let parsed = msgpackparse(dumped)') eq({{_TYPE={}, _VAL={{'a', ''}}}}, eval('parsed')) eq(1, eval('g:parsed[0]._TYPE is v:msgpack_types.map')) end) it('restores MAP with duplicate STR keys as special dictionary', function() - execute('let dumped = ["\\x82\\xA1a\\xC4\\n\\xA1a\\xC4\\n"]') - execute('let parsed = msgpackparse(dumped)') + command('let dumped = ["\\x82\\xA1a\\xC4\\n\\xA1a\\xC4\\n"]') + -- FIXME Internal error bug + command('silent! let parsed = msgpackparse(dumped)') eq({{_TYPE={}, _VAL={ {{_TYPE={}, _VAL={'a'}}, ''}, {{_TYPE={}, _VAL={'a'}}, ''}}} }, eval('parsed')) eq(1, eval('g:parsed[0]._TYPE is v:msgpack_types.map')) @@ -448,8 +451,8 @@ describe('msgpackparse() function', function() end) it('restores MAP with MAP key as special dictionary', function() - execute('let dumped = ["\\x81\\x80\\xC4\\n"]') - execute('let parsed = msgpackparse(dumped)') + command('let dumped = ["\\x81\\x80\\xC4\\n"]') + command('let parsed = msgpackparse(dumped)') eq({{_TYPE={}, _VAL={{{}, ''}}}}, eval('parsed')) eq(1, eval('g:parsed[0]._TYPE is v:msgpack_types.map')) end) @@ -460,7 +463,7 @@ describe('msgpackparse() function', function() eval(cmd) eval(cmd) -- do it again (try to force segfault) local api_info = eval(cmd) -- do it again - eq({'error_types', 'functions', 'types', 'version'}, api_info) + eq({'error_types', 'functions', 'types', 'ui_events', 'version'}, api_info) end) it('fails when called with no arguments', function() @@ -494,7 +497,7 @@ describe('msgpackparse() function', function() end) it('fails to parse a partial', function() - execute('function T() dict\nendfunction') + command('function T() dict\nendfunction') eq('Vim(call):E686: Argument of msgpackparse() must be a List', exc_exec('call msgpackparse(function("T", [1, 2], {}))')) end) @@ -514,10 +517,10 @@ describe('msgpackdump() function', function() end) it('can dump generic mapping with generic mapping keys and values', function() - execute('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": []}') - execute('let todumpv1 = {"_TYPE": v:msgpack_types.map, "_VAL": []}') - execute('let todumpv2 = {"_TYPE": v:msgpack_types.map, "_VAL": []}') - execute('call add(todump._VAL, [todumpv1, todumpv2])') + command('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": []}') + command('let todumpv1 = {"_TYPE": v:msgpack_types.map, "_VAL": []}') + command('let todumpv2 = {"_TYPE": v:msgpack_types.map, "_VAL": []}') + command('call add(todump._VAL, [todumpv1, todumpv2])') eq({'\129\128\128'}, eval('msgpackdump([todump])')) end) @@ -530,130 +533,130 @@ describe('msgpackdump() function', function() end) it('can v:null', function() - execute('let todump = v:null') + command('let todump = v:null') end) it('can dump special bool mapping (true)', function() - execute('let todump = {"_TYPE": v:msgpack_types.boolean, "_VAL": 1}') + command('let todump = {"_TYPE": v:msgpack_types.boolean, "_VAL": 1}') eq({'\195'}, eval('msgpackdump([todump])')) end) it('can dump special bool mapping (false)', function() - execute('let todump = {"_TYPE": v:msgpack_types.boolean, "_VAL": 0}') + command('let todump = {"_TYPE": v:msgpack_types.boolean, "_VAL": 0}') eq({'\194'}, eval('msgpackdump([todump])')) end) it('can dump special nil mapping', function() - execute('let todump = {"_TYPE": v:msgpack_types.nil, "_VAL": 0}') + command('let todump = {"_TYPE": v:msgpack_types.nil, "_VAL": 0}') eq({'\192'}, eval('msgpackdump([todump])')) end) it('can dump special ext mapping', function() - execute('let todump = {"_TYPE": v:msgpack_types.ext, "_VAL": [5, ["",""]]}') + command('let todump = {"_TYPE": v:msgpack_types.ext, "_VAL": [5, ["",""]]}') eq({'\212\005', ''}, eval('msgpackdump([todump])')) end) it('can dump special array mapping', function() - execute('let todump = {"_TYPE": v:msgpack_types.array, "_VAL": [5, [""]]}') + command('let todump = {"_TYPE": v:msgpack_types.array, "_VAL": [5, [""]]}') eq({'\146\005\145\196\n'}, eval('msgpackdump([todump])')) end) it('can dump special UINT64_MAX mapping', function() - execute('let todump = {"_TYPE": v:msgpack_types.integer}') - execute('let todump._VAL = [1, 3, 0x7FFFFFFF, 0x7FFFFFFF]') + command('let todump = {"_TYPE": v:msgpack_types.integer}') + command('let todump._VAL = [1, 3, 0x7FFFFFFF, 0x7FFFFFFF]') eq({'\207\255\255\255\255\255\255\255\255'}, eval('msgpackdump([todump])')) end) it('can dump special INT64_MIN mapping', function() - execute('let todump = {"_TYPE": v:msgpack_types.integer}') - execute('let todump._VAL = [-1, 2, 0, 0]') + command('let todump = {"_TYPE": v:msgpack_types.integer}') + command('let todump._VAL = [-1, 2, 0, 0]') eq({'\211\128\n\n\n\n\n\n\n'}, eval('msgpackdump([todump])')) end) it('fails to dump a function reference', function() - execute('let Todump = function("tr")') + command('let Todump = function("tr")') eq('Vim(call):E5004: Error while dumping msgpackdump() argument, index 0, itself: attempt to dump function reference', exc_exec('call msgpackdump([Todump])')) end) it('fails to dump a partial', function() - execute('function T() dict\nendfunction') - execute('let Todump = function("T", [1, 2], {})') + command('function T() dict\nendfunction') + command('let Todump = function("T", [1, 2], {})') eq('Vim(call):E5004: Error while dumping msgpackdump() argument, index 0, itself: attempt to dump function reference', exc_exec('call msgpackdump([Todump])')) end) it('fails to dump a function reference in a list', function() - execute('let todump = [function("tr")]') + command('let todump = [function("tr")]') eq('Vim(call):E5004: Error while dumping msgpackdump() argument, index 0, index 0: attempt to dump function reference', exc_exec('call msgpackdump([todump])')) end) it('fails to dump a recursive list', function() - execute('let todump = [[[]]]') - execute('call add(todump[0][0], todump)') + command('let todump = [[[]]]') + command('call add(todump[0][0], todump)') eq('Vim(call):E5005: Unable to dump msgpackdump() argument, index 0: container references itself in index 0, index 0, index 0', exc_exec('call msgpackdump([todump])')) end) it('fails to dump a recursive dict', function() - execute('let todump = {"d": {"d": {}}}') - execute('call extend(todump.d.d, {"d": todump})') + command('let todump = {"d": {"d": {}}}') + command('call extend(todump.d.d, {"d": todump})') eq('Vim(call):E5005: Unable to dump msgpackdump() argument, index 0: container references itself in key \'d\', key \'d\', key \'d\'', exc_exec('call msgpackdump([todump])')) end) it('can dump dict with two same dicts inside', function() - execute('let inter = {}') - execute('let todump = {"a": inter, "b": inter}') + command('let inter = {}') + command('let todump = {"a": inter, "b": inter}') eq({"\130\161a\128\161b\128"}, eval('msgpackdump([todump])')) end) it('can dump list with two same lists inside', function() - execute('let inter = []') - execute('let todump = [inter, inter]') + command('let inter = []') + command('let todump = [inter, inter]') eq({"\146\144\144"}, eval('msgpackdump([todump])')) end) it('fails to dump a recursive list in a special dict', function() - execute('let todump = {"_TYPE": v:msgpack_types.array, "_VAL": []}') - execute('call add(todump._VAL, todump)') + command('let todump = {"_TYPE": v:msgpack_types.array, "_VAL": []}') + command('call add(todump._VAL, todump)') eq('Vim(call):E5005: Unable to dump msgpackdump() argument, index 0: container references itself in index 0', exc_exec('call msgpackdump([todump])')) end) it('fails to dump a recursive (key) map in a special dict', function() - execute('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": []}') - execute('call add(todump._VAL, [todump, 0])') + command('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": []}') + command('call add(todump._VAL, [todump, 0])') eq('Vim(call):E5005: Unable to dump msgpackdump() argument, index 0: container references itself in index 1', exc_exec('call msgpackdump([todump])')) end) it('fails to dump a recursive (val) map in a special dict', function() - execute('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": []}') - execute('call add(todump._VAL, [0, todump])') + command('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": []}') + command('call add(todump._VAL, [0, todump])') eq('Vim(call):E5005: Unable to dump msgpackdump() argument, index 0: container references itself in key 0 at index 0 from special map', exc_exec('call msgpackdump([todump])')) end) it('fails to dump a recursive (key) map in a special dict, _VAL reference', function() - execute('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": [[[], []]]}') - execute('call add(todump._VAL[0][0], todump._VAL)') + command('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": [[[], []]]}') + command('call add(todump._VAL[0][0], todump._VAL)') eq('Vim(call):E5005: Unable to dump msgpackdump() argument, index 0: container references itself in key [[[[...@0], []]]] at index 0 from special map, index 0', exc_exec('call msgpackdump([todump])')) end) it('fails to dump a recursive (val) map in a special dict, _VAL reference', function() - execute('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": [[[], []]]}') - execute('call add(todump._VAL[0][1], todump._VAL)') + command('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": [[[], []]]}') + command('call add(todump._VAL[0][1], todump._VAL)') eq('Vim(call):E5005: Unable to dump msgpackdump() argument, index 0: container references itself in key [] at index 0 from special map, index 0', exc_exec('call msgpackdump([todump])')) end) it('fails to dump a recursive (val) special list in a special dict', function() - execute('let todump = {"_TYPE": v:msgpack_types.array, "_VAL": []}') - execute('call add(todump._VAL, [0, todump._VAL])') + command('let todump = {"_TYPE": v:msgpack_types.array, "_VAL": []}') + command('call add(todump._VAL, [0, todump._VAL])') eq('Vim(call):E5005: Unable to dump msgpackdump() argument, index 0: container references itself in index 0, index 1', exc_exec('call msgpackdump([todump])')) end) @@ -689,7 +692,7 @@ describe('msgpackdump() function', function() end) it('fails to dump a partial', function() - execute('function T() dict\nendfunction') + command('function T() dict\nendfunction') eq('Vim(call):E686: Argument of msgpackdump() must be a List', exc_exec('call msgpackdump(function("T", [1, 2], {}))')) end) diff --git a/test/functional/eval/null_spec.lua b/test/functional/eval/null_spec.lua new file mode 100644 index 0000000000..6fd30caec9 --- /dev/null +++ b/test/functional/eval/null_spec.lua @@ -0,0 +1,138 @@ +local helpers = require('test.functional.helpers')(after_each) + +local curbufmeths = helpers.curbufmeths +local redir_exec = helpers.redir_exec +local exc_exec = helpers.exc_exec +local command = helpers.command +local clear = helpers.clear +local meths = helpers.meths +local funcs = helpers.funcs +local eq = helpers.eq + +describe('NULL', function() + before_each(function() + clear() + command('let L = v:_null_list') + command('let D = v:_null_dict') + command('let S = $XXX_NONEXISTENT_VAR_XXX') + end) + local tmpfname = 'Xtest-functional-viml-null' + after_each(function() + os.remove(tmpfname) + end) + local null_test = function(name, cmd, err) + it(name, function() + eq(err, exc_exec(cmd)) + end) + end + local null_expr_test = function(name, expr, err, val, after) + it(name, function() + eq((err == 0) and ('') or ('\n' .. err), + redir_exec('let g:_var = ' .. expr)) + if val == nil then + eq(0, funcs.exists('g:_var')) + else + eq(val, meths.get_var('_var')) + end + if after ~= nil then + after() + end + end) + end + describe('list', function() + -- Incorrect behaviour + + -- FIXME map() should not return 0 without error + null_expr_test('does not crash map()', 'map(L, "v:val")', 0, 0) + -- FIXME map() should not return 0 without error + null_expr_test('does not crash filter()', 'filter(L, "1")', 0, 0) + -- FIXME map() should at least return L + null_expr_test('makes map() return v:_null_list', 'map(L, "v:val") is# L', 0, 0) + -- FIXME filter() should at least return L + null_expr_test('makes filter() return v:_null_list', 'map(L, "1") is# L', 0, 0) + -- FIXME add() should not return 1 at all + null_expr_test('does not crash add()', 'add(L, 0)', 0, 1) + null_expr_test('does not crash extend()', 'extend(L, [1])', 'E742: Cannot change value of extend() argument', 0) + null_expr_test('does not crash extend() (second position)', 'extend([1], L)', 0, {1}) + -- FIXME should be accepted by inputlist() + null_expr_test('is accepted as an empty list by inputlist()', + '[feedkeys("\\n"), inputlist(L)]', 'E686: Argument of inputlist() must be a List', {0, 0}) + -- FIXME should be accepted by writefile(), return {0, {}} + null_expr_test('is accepted as an empty list by writefile()', + ('[writefile(L, "%s"), readfile("%s")]'):format(tmpfname, tmpfname), + 'E484: Can\'t open file ' .. tmpfname, {0, {}}) + -- FIXME should give error message + null_expr_test('does not crash remove()', 'remove(L, 0)', 0, 0) + -- FIXME should return 0 + null_expr_test('is accepted by setqflist()', 'setqflist(L)', 0, -1) + -- FIXME should return 0 + null_expr_test('is accepted by setloclist()', 'setloclist(1, L)', 0, -1) + -- FIXME should return 0 + null_expr_test('is accepted by setmatches()', 'setmatches(L)', 0, -1) + -- FIXME should return empty list or error out + null_expr_test('is accepted by sort()', 'sort(L)', 0, 0) + -- FIXME Should return 1 + null_expr_test('is accepted by sort()', 'sort(L) is L', 0, 0) + -- FIXME should not error out + null_test('is accepted by :cexpr', 'cexpr L', 'Vim(cexpr):E777: String or List expected') + -- FIXME should not error out + null_test('is accepted by :lexpr', 'lexpr L', 'Vim(lexpr):E777: String or List expected') + null_test('is accepted by :for', 'for x in L|throw x|endfor', 0) + + -- Subjectable behaviour + + -- FIXME Should return 1 + null_expr_test('is equal to empty list', 'L == []', 0, 0) + -- FIXME Should return 1 + null_expr_test('is equal to empty list (reverse order)', '[] == L', 0, 0) + -- FIXME Should return 1 + null_expr_test('is not locked', 'islocked("v:_null_list")', 0, 0) + + -- Crashes + + -- null_expr_test('does not crash setreg', 'setreg("x", L)', 0, 0) + -- null_expr_test('does not crash setline', 'setline(1, L)', 0, 0) + -- null_expr_test('does not crash system()', 'system("cat", L)', 0, '') + -- null_expr_test('does not crash systemlist()', 'systemlist("cat", L)', 0, {}) + + -- Correct behaviour + null_expr_test('does not crash append()', 'append(1, L)', 0, 0, function() + eq({''}, curbufmeths.get_lines(0, -1, false)) + end) + null_expr_test('is identical to itself', 'L is L', 0, 1) + null_expr_test('can be sliced', 'L[:]', 0, {}) + null_expr_test('can be copied', 'copy(L)', 0, {}) + null_expr_test('can be deepcopied', 'deepcopy(L)', 0, {}) + null_expr_test('does not crash when indexed', 'L[1]', + 'E684: list index out of range: 1\nE15: Invalid expression: L[1]', nil) + null_expr_test('does not crash call()', 'call("arglistid", L)', 0, 0) + null_expr_test('does not crash col()', 'col(L)', 0, 0) + null_expr_test('does not crash virtcol()', 'virtcol(L)', 0, 0) + null_expr_test('does not crash line()', 'line(L)', 0, 0) + null_expr_test('does not crash count()', 'count(L, 1)', 0, 0) + null_expr_test('does not crash cursor()', 'cursor(L)', 'E474: Invalid argument', -1) + null_expr_test('is empty', 'empty(L)', 0, 1) + null_expr_test('does not crash get()', 'get(L, 1, 10)', 0, 10) + null_expr_test('has zero length', 'len(L)', 0, 0) + null_expr_test('is accepted as an empty list by max()', 'max(L)', 0, 0) + null_expr_test('is accepted as an empty list by min()', 'min(L)', 0, 0) + null_expr_test('is stringified correctly', 'string(L)', 0, '[]') + null_expr_test('is JSON encoded correctly', 'json_encode(L)', 0, '[]') + null_test('does not crash lockvar', 'lockvar! L', 0) + null_expr_test('can be added to itself', '(L + L)', 0, {}) + null_expr_test('can be added to itself', '(L + L) is L', 0, 1) + null_expr_test('can be added to non-empty list', '([1] + L)', 0, {1}) + null_expr_test('can be added to non-empty list (reversed)', '(L + [1])', 0, {1}) + null_expr_test('is equal to itself', 'L == L', 0, 1) + null_expr_test('is not not equal to itself', 'L != L', 0, 0) + null_expr_test('counts correctly', 'count([L], L)', 0, 1) + end) + describe('dict', function() + it('does not crash when indexing NULL dict', function() + eq('\nE716: Key not present in Dictionary: test\nE15: Invalid expression: v:_null_dict.test', + redir_exec('echo v:_null_dict.test')) + end) + null_expr_test('makes extend error out', 'extend(D, {})', 'E742: Cannot change value of extend() argument', 0) + null_expr_test('makes extend do nothing', 'extend({1: 2}, D)', 0, {['1']=2}) + end) +end) diff --git a/test/functional/eval/printf_spec.lua b/test/functional/eval/printf_spec.lua index c84290ceef..27e24c4118 100644 --- a/test/functional/eval/printf_spec.lua +++ b/test/functional/eval/printf_spec.lua @@ -1,7 +1,10 @@ local helpers = require('test.functional.helpers')(after_each) + local clear = helpers.clear local eq = helpers.eq +local eval = helpers.eval local funcs = helpers.funcs +local meths = helpers.meths local exc_exec = helpers.exc_exec describe('printf()', function() @@ -57,4 +60,33 @@ describe('printf()', function() it('errors out when %b modifier is used for a float', function() eq('Vim(call):E805: Using a Float as a Number', exc_exec('call printf("%b", 3.1415926535)')) end) + it('works with %p correctly', function() + local null_ret = nil + local seen_rets = {} + -- Collect all args in an array to avoid possible allocation of the same + -- address after freeing unreferenced values. + meths.set_var('__args', {}) + local function check_printf(expr, is_null) + eq(0, exc_exec('call add(__args, ' .. expr .. ')')) + eq(0, exc_exec('let __result = printf("%p", __args[-1])')) + local id_ret = eval('id(__args[-1])') + eq(id_ret, meths.get_var('__result')) + if is_null then + if null_ret then + eq(null_ret, id_ret) + else + null_ret = id_ret + end + else + eq(nil, seen_rets[id_ret]) + seen_rets[id_ret] = expr + end + meths.del_var('__result') + end + check_printf('v:_null_list', true) + check_printf('v:_null_dict', true) + check_printf('[]') + check_printf('{}') + check_printf('function("tr", ["a"])') + end) end) diff --git a/test/functional/eval/reltime_spec.lua b/test/functional/eval/reltime_spec.lua index 0b19d372ec..0181f09024 100644 --- a/test/functional/eval/reltime_spec.lua +++ b/test/functional/eval/reltime_spec.lua @@ -1,6 +1,6 @@ local helpers = require('test.functional.helpers')(after_each) local clear, eq, ok = helpers.clear, helpers.eq, helpers.ok -local neq, execute, funcs = helpers.neq, helpers.execute, helpers.funcs +local neq, command, funcs = helpers.neq, helpers.command, helpers.funcs local reltime, reltimestr, reltimefloat = funcs.reltime, funcs.reltimestr, funcs.reltimefloat describe('reltimestr(), reltimefloat()', function() @@ -8,7 +8,7 @@ describe('reltimestr(), reltimefloat()', function() it('Checks', function() local now = reltime() - execute('sleep 10m') + command('sleep 10m') local later = reltime() local elapsed = reltime(now) diff --git a/test/functional/eval/server_spec.lua b/test/functional/eval/server_spec.lua index d2c985e894..115114c3c3 100644 --- a/test/functional/eval/server_spec.lua +++ b/test/functional/eval/server_spec.lua @@ -1,22 +1,27 @@ local helpers = require('test.functional.helpers')(after_each) -local nvim, eq, neq, eval = helpers.nvim, helpers.eq, helpers.neq, helpers.eval +local eq, neq, eval = helpers.eq, helpers.neq, helpers.eval +local command = helpers.command local clear, funcs, meths = helpers.clear, helpers.funcs, helpers.meths local os_name = helpers.os_name -if helpers.pending_win32(pending) then return end +local function clear_serverlist() + for _, server in pairs(funcs.serverlist()) do + funcs.serverstop(server) + end +end describe('serverstart(), serverstop()', function() before_each(clear) it('sets $NVIM_LISTEN_ADDRESS on first invocation', function() -- Unset $NVIM_LISTEN_ADDRESS - nvim('command', 'let $NVIM_LISTEN_ADDRESS = ""') + command('let $NVIM_LISTEN_ADDRESS = ""') local s = eval('serverstart()') assert(s ~= nil and s:len() > 0, "serverstart() returned empty") eq(s, eval('$NVIM_LISTEN_ADDRESS')) - nvim('command', "call serverstop('"..s.."')") + command("call serverstop('"..s.."')") eq('', eval('$NVIM_LISTEN_ADDRESS')) end) @@ -42,17 +47,45 @@ describe('serverstart(), serverstop()', function() -- v:servername will take the next available server. local servername = (os_name() == 'windows' - and [[\\.\pipe\Xtest-functional-server-server-pipe]] - or 'Xtest-functional-server-server-socket') + and [[\\.\pipe\Xtest-functional-server-pipe]] + or 'Xtest-functional-server-socket') funcs.serverstart(servername) eq(servername, meths.get_vvar('servername')) end) it('serverstop() ignores invalid input', function() - nvim('command', "call serverstop('')") - nvim('command', "call serverstop('bogus-socket-name')") + command("call serverstop('')") + command("call serverstop('bogus-socket-name')") end) + it('parses endpoints correctly', function() + clear_serverlist() + eq({}, funcs.serverlist()) + + local s = funcs.serverstart('127.0.0.1:0') -- assign random port + assert(string.match(s, '127.0.0.1:%d+')) + eq(s, funcs.serverlist()[1]) + clear_serverlist() + + s = funcs.serverstart('127.0.0.1:') -- assign random port + assert(string.match(s, '127.0.0.1:%d+')) + eq(s, funcs.serverlist()[1]) + clear_serverlist() + + funcs.serverstart('127.0.0.1:12345') + funcs.serverstart('127.0.0.1:12345') -- exists already; ignore + funcs.serverstart('::1:12345') + funcs.serverstart('::1:12345') -- exists already; ignore + local expected = { + '127.0.0.1:12345', + '::1:12345', + } + eq(expected, funcs.serverlist()) + clear_serverlist() + + funcs.serverstart('127.0.0.1:65536') -- invalid port + eq({}, funcs.serverlist()) + end) end) describe('serverlist()', function() @@ -63,9 +96,11 @@ describe('serverlist()', function() local n = eval('len(serverlist())') -- Add a few - local servs = {'should-not-exist', 'another-one-that-shouldnt'} + local servs = (os_name() == 'windows' + and { [[\\.\pipe\Xtest-pipe0934]], [[\\.\pipe\Xtest-pipe4324]] } + or { [[Xtest-pipe0934]], [[Xtest-pipe4324]] }) for _, s in ipairs(servs) do - eq(s, eval('serverstart("'..s..'")')) + eq(s, eval("serverstart('"..s.."')")) end local new_servs = eval('serverlist()') @@ -75,10 +110,9 @@ describe('serverlist()', function() -- The new servers should be at the end of the list. for i = 1, #servs do eq(servs[i], new_servs[i + n]) - nvim('command', 'call serverstop("'..servs[i]..'")') + command("call serverstop('"..servs[i].."')") end - -- After calling serverstop() on the new servers, they should no longer be - -- in the list. + -- After serverstop() the servers should NOT be in the list. eq(n, eval('len(serverlist())')) end) end) diff --git a/test/functional/eval/setpos_spec.lua b/test/functional/eval/setpos_spec.lua new file mode 100644 index 0000000000..6a8b3a8732 --- /dev/null +++ b/test/functional/eval/setpos_spec.lua @@ -0,0 +1,65 @@ +local helpers = require('test.functional.helpers')(after_each) +local setpos = helpers.funcs.setpos +local getpos = helpers.funcs.getpos +local insert = helpers.insert +local clear = helpers.clear +local command = helpers.command +local eval = helpers.eval +local eq = helpers.eq +local exc_exec = helpers.exc_exec + + +describe('setpos() function', function() + before_each(function() + clear() + insert([[ + First line of text + Second line of text + Third line of text]]) + command('new') + insert([[ + Line of text 1 + Line of text 2 + Line of text 3]]) + end) + it('can set the current cursor position', function() + setpos(".", {0, 2, 1, 0}) + eq(getpos("."), {0, 2, 1, 0}) + setpos(".", {2, 1, 1, 0}) + eq(getpos("."), {0, 1, 1, 0}) + -- Ensure get an error attempting to set position to another buffer + local ret = exc_exec('call setpos(".", [1, 1, 1, 0])') + eq('Vim(call):E474: Invalid argument', ret) + end) + it('can set lowercase marks in the current buffer', function() + setpos("'d", {0, 2, 1, 0}) + eq(getpos("'d"), {0, 2, 1, 0}) + command('undo') + command('call setpos("\'d", [2, 3, 1, 0])') + eq(getpos("'d"), {0, 3, 1, 0}) + end) + it('can set lowercase marks in other buffers', function() + local retval = setpos("'d", {1, 2, 1, 0}) + eq(0, retval) + setpos("'d", {1, 2, 1, 0}) + eq(getpos("'d"), {0, 0, 0, 0}) + command('wincmd w') + eq(eval('bufnr("%")'), 1) + eq(getpos("'d"), {0, 2, 1, 0}) + end) + it("fails when setting a mark in a buffer that doesn't exist", function() + local retval = setpos("'d", {3, 2, 1, 0}) + eq(-1, retval) + eq(getpos("'d"), {0, 0, 0, 0}) + retval = setpos("'D", {3, 2, 1, 0}) + eq(-1, retval) + eq(getpos("'D"), {0, 0, 0, 0}) + end) + it('can set uppercase marks', function() + setpos("'D", {2, 2, 3, 0}) + eq(getpos("'D"), {2, 2, 3, 0}) + -- Can set a mark in another buffer + setpos("'D", {1, 2, 2, 0}) + eq(getpos("'D"), {1, 2, 2, 0}) + end) +end) diff --git a/test/functional/eval/sort_spec.lua b/test/functional/eval/sort_spec.lua new file mode 100644 index 0000000000..4e5a0afba4 --- /dev/null +++ b/test/functional/eval/sort_spec.lua @@ -0,0 +1,41 @@ +local helpers = require('test.functional.helpers')(after_each) + +local eq = helpers.eq +local NIL = helpers.NIL +local eval = helpers.eval +local clear = helpers.clear +local meths = helpers.meths +local funcs = helpers.funcs +local command = helpers.command +local exc_exec = helpers.exc_exec + +before_each(clear) + +describe('sort()', function() + it('errors out when sorting special values', function() + eq('Vim(call):E907: Using a special value as a Float', + exc_exec('call sort([v:true, v:false], "f")')) + end) + + it('sorts โwrongโ values between -0.0001 and 0.0001, preserving order', + function() + meths.set_var('list', {true, false, NIL, {}, {a=42}, 'check', + 0.0001, -0.0001}) + command('call insert(g:list, function("tr"))') + local error_lines = funcs.split( + funcs.execute('silent! call sort(g:list, "f")'), '\n') + local errors = {} + for _, err in ipairs(error_lines) do + errors[err] = true + end + eq({ + ['E891: Using a Funcref as a Float']=true, + ['E892: Using a String as a Float']=true, + ['E893: Using a List as a Float']=true, + ['E894: Using a Dictionary as a Float']=true, + ['E907: Using a special value as a Float']=true, + }, errors) + eq('[-1.0e-4, function(\'tr\'), v:true, v:false, v:null, [], {\'a\': 42}, \'check\', 1.0e-4]', + eval('string(g:list)')) + end) +end) diff --git a/test/functional/eval/special_vars_spec.lua b/test/functional/eval/special_vars_spec.lua index 4c5d63ce23..3d9358447e 100644 --- a/test/functional/eval/special_vars_spec.lua +++ b/test/functional/eval/special_vars_spec.lua @@ -1,6 +1,6 @@ local helpers = require('test.functional.helpers')(after_each) local exc_exec = helpers.exc_exec -local execute = helpers.execute +local command = helpers.command local funcs = helpers.funcs local clear = helpers.clear local eval = helpers.eval @@ -12,7 +12,7 @@ describe('Special values', function() before_each(clear) it('do not cause error when freed', function() - execute([[ + command([[ function Test() try return v:true @@ -109,7 +109,7 @@ describe('Special values', function() it('does not work with +=/-=/.=', function() meths.set_var('true', true) meths.set_var('false', false) - execute('let null = v:null') + command('let null = v:null') eq('Vim(let):E734: Wrong variable type for +=', exc_exec('let true += 1')) eq('Vim(let):E734: Wrong variable type for +=', exc_exec('let false += 1')) diff --git a/test/functional/eval/string_spec.lua b/test/functional/eval/string_spec.lua index f6279e85e8..adc1af9b8e 100644 --- a/test/functional/eval/string_spec.lua +++ b/test/functional/eval/string_spec.lua @@ -7,7 +7,6 @@ local eval = helpers.eval local exc_exec = helpers.exc_exec local redir_exec = helpers.redir_exec local funcs = helpers.funcs -local write_file = helpers.write_file local NIL = helpers.NIL local source = helpers.source local dedent = helpers.dedent @@ -105,10 +104,8 @@ describe('string() function', function() end) describe('used to represent funcrefs', function() - local fname = 'Xtest-functional-eval-string_spec-fref-script.vim' - before_each(function() - write_file(fname, [[ + source([[ function Test1() endfunction @@ -120,11 +117,6 @@ describe('string() function', function() let g:Test2_f = function('s:Test2') ]]) - command('source ' .. fname) - end) - - after_each(function() - os.remove(fname) end) it('dumps references to built-in functions', function() diff --git a/test/functional/eval/system_spec.lua b/test/functional/eval/system_spec.lua index 6393477260..7e213e2156 100644 --- a/test/functional/eval/system_spec.lua +++ b/test/functional/eval/system_spec.lua @@ -1,11 +1,13 @@ local helpers = require('test.functional.helpers')(after_each) -local eq, clear, eval, execute, feed, nvim = - helpers.eq, helpers.clear, helpers.eval, helpers.execute, helpers.feed, - helpers.nvim -local Screen = require('test.functional.ui.screen') +local nvim_dir = helpers.nvim_dir +local eq, call, clear, eval, feed_command, feed, nvim = + helpers.eq, helpers.call, helpers.clear, helpers.eval, helpers.feed_command, + helpers.feed, helpers.nvim +local command = helpers.command +local iswin = helpers.iswin -if helpers.pending_win32(pending) then return end +local Screen = require('test.functional.ui.screen') local function create_file_with_nuls(name) return function() @@ -31,15 +33,88 @@ end describe('system()', function() before_each(clear) - it('sets the v:shell_error variable', function() - eval([[system("sh -c 'exit'")]]) - eq(0, eval('v:shell_error')) - eval([[system("sh -c 'exit 1'")]]) - eq(1, eval('v:shell_error')) - eval([[system("sh -c 'exit 5'")]]) - eq(5, eval('v:shell_error')) - eval([[system('this-should-not-exist')]]) - eq(127, eval('v:shell_error')) + describe('command passed as a List', function() + local function printargs_path() + return nvim_dir..'/printargs-test' .. (iswin() and '.exe' or '') + end + + it('sets v:shell_error if cmd[0] is not executable', function() + call('system', { 'this-should-not-exist' }) + eq(-1, eval('v:shell_error')) + end) + + it('parameter validation does NOT modify v:shell_error', function() + -- 1. Call system() with invalid parameters. + -- 2. Assert that v:shell_error was NOT set. + feed_command('call system({})') + eq('E475: Invalid argument: expected String or List', eval('v:errmsg')) + eq(0, eval('v:shell_error')) + feed_command('call system([])') + eq('E474: Invalid argument', eval('v:errmsg')) + eq(0, eval('v:shell_error')) + + -- Provoke a non-zero v:shell_error. + call('system', { 'this-should-not-exist' }) + local old_val = eval('v:shell_error') + eq(-1, old_val) + + -- 1. Call system() with invalid parameters. + -- 2. Assert that v:shell_error was NOT modified. + feed_command('call system({})') + eq(old_val, eval('v:shell_error')) + feed_command('call system([])') + eq(old_val, eval('v:shell_error')) + end) + + it('quotes arguments correctly #5280', function() + local out = call('system', + { printargs_path(), [[1]], [[2 "3]], [[4 ' 5]], [[6 ' 7']] }) + + eq(0, eval('v:shell_error')) + eq([[arg1=1;arg2=2 "3;arg3=4 ' 5;arg4=6 ' 7';]], out) + + out = call('system', { printargs_path(), [['1]], [[2 "3]] }) + eq(0, eval('v:shell_error')) + eq([[arg1='1;arg2=2 "3;]], out) + + out = call('system', { printargs_path(), "A\nB" }) + eq(0, eval('v:shell_error')) + eq("arg1=A\nB;", out) + end) + + it('calls executable in $PATH', function() + if 0 == eval("executable('python')") then pending("missing `python`") end + eq("foo\n", eval([[system(['python', '-c', 'print("foo")'])]])) + eq(0, eval('v:shell_error')) + end) + + it('does NOT run in shell', function() + if not iswin() then + eq("* $PATH %PATH%\n", eval("system(['echo', '*', '$PATH', '%PATH%'])")) + end + end) + end) + + it('sets v:shell_error', function() + if iswin() then + eval([[system("cmd.exe /c exit")]]) + eq(0, eval('v:shell_error')) + eval([[system("cmd.exe /c exit 1")]]) + eq(1, eval('v:shell_error')) + eval([[system("cmd.exe /c exit 5")]]) + eq(5, eval('v:shell_error')) + eval([[system('this-should-not-exist')]]) + eq(1, eval('v:shell_error')) + else + eval([[system("sh -c 'exit'")]]) + eq(0, eval('v:shell_error')) + eval([[system("sh -c 'exit 1'")]]) + eq(1, eval('v:shell_error')) + eval([[system("sh -c 'exit 5'")]]) + eq(5, eval('v:shell_error')) + eval([[system('this-should-not-exist')]]) + eq(127, eval('v:shell_error')) + end end) describe('executes shell function if passed a string', function() @@ -55,6 +130,40 @@ describe('system()', function() screen:detach() end) + if iswin() then + it('with shell=cmd.exe', function() + command('set shell=cmd.exe') + eq('""\n', eval([[system('echo ""')]])) + eq('"a b"\n', eval([[system('echo "a b"')]])) + eq('a \nb\n', eval([[system('echo a & echo b')]])) + eq('a \n', eval([[system('echo a 2>&1')]])) + eval([[system('cd "C:\Program Files"')]]) + eq(0, eval('v:shell_error')) + end) + + it('with shell=cmd', function() + command('set shell=cmd') + eq('"a b"\n', eval([[system('echo "a b"')]])) + end) + + it('with shell=$COMSPEC', function() + local comspecshell = eval("fnamemodify($COMSPEC, ':t')") + if comspecshell == 'cmd.exe' then + command('set shell=$COMSPEC') + eq('"a b"\n', eval([[system('echo "a b"')]])) + else + pending('$COMSPEC is not cmd.exe: ' .. comspecshell) + end + end) + + it('works with powershell', function() + helpers.set_shell_powershell() + eq('a\nb\n', eval([[system('echo a b')]])) + eq('C:\\\n', eval([[system('cd c:\; (Get-Location).Path')]])) + eq('a b\n', eval([[system('echo "a b"')]])) + end) + end + it('`echo` and waits for its return', function() feed(':call system("echo")<cr>') screen:expect([[ @@ -115,11 +224,15 @@ describe('system()', function() describe('passing no input', function() it('returns the program output', function() - eq("echoed", eval('system("echo -n echoed")')) + if iswin() then + eq("echoed\n", eval('system("echo echoed")')) + else + eq("echoed", eval('system("echo -n echoed")')) + end end) it('to backgrounded command does not crash', function() -- This is indeterminate, just exercise the codepath. May get E5677. - execute('call system("echo -n echoed &")') + feed_command('call system("echo -n echoed &")') local v_errnum = string.match(eval("v:errmsg"), "^E%d*:") if v_errnum then eq("E5677:", v_errnum) @@ -134,7 +247,7 @@ describe('system()', function() end) it('to backgrounded command does not crash', function() -- This is indeterminate, just exercise the codepath. May get E5677. - execute('call system("cat - &")') + feed_command('call system("cat - &")') local v_errnum = string.match(eval("v:errmsg"), "^E%d*:") if v_errnum then eq("E5677:", v_errnum) @@ -158,7 +271,7 @@ describe('system()', function() end) end) - describe('passing number as input', function() + describe('input passed as Number', function() it('stringifies the input', function() eq('1', eval('system("cat", 1)')) end) @@ -175,8 +288,8 @@ describe('system()', function() end) end) - describe('passing list as input', function() - it('joins list items with linefeed characters', function() + describe('input passed as List', function() + it('joins List items with linefeed characters', function() eq('line1\nline2\nline3', eval("system('cat -', ['line1', 'line2', 'line3'])")) end) @@ -185,7 +298,7 @@ describe('system()', function() -- is inconsistent and is a good reason for the existence of the -- `systemlist()` function, where input and output map to the same -- characters(see the following tests with `systemlist()` below) - describe('with linefeed characters inside list items', function() + describe('with linefeed characters inside List items', function() it('converts linefeed characters to NULs', function() eq('l1\001p2\nline2\001a\001b\nl3', eval([[system('cat -', ["l1\np2", "line2\na\nb", 'l3'])]])) @@ -202,37 +315,40 @@ describe('system()', function() describe("with a program that doesn't close stdout", function() if not xclip then - pending('skipped (missing xclip)', function() end) + pending('missing `xclip`', function() end) else it('will exit properly after passing input', function() - eq('', eval([[system('xclip -i -selection clipboard', 'clip-data')]])) + eq('', eval([[system('xclip -i -loops 1 -selection clipboard', 'clip-data')]])) eq('clip-data', eval([[system('xclip -o -selection clipboard')]])) end) end end) - - describe('command passed as a list', function() - it('does not execute &shell', function() - eq('* $NOTHING ~/file', - eval("system(['echo', '-n', '*', '$NOTHING', '~/file'])")) - end) - end) end) describe('systemlist()', function() - -- behavior is similar to `system()` but it returns a list instead of a - -- string. + -- Similar to `system()`, but returns List instead of String. before_each(clear) - it('sets the v:shell_error variable', function() - eval([[systemlist("sh -c 'exit'")]]) - eq(0, eval('v:shell_error')) - eval([[systemlist("sh -c 'exit 1'")]]) - eq(1, eval('v:shell_error')) - eval([[systemlist("sh -c 'exit 5'")]]) - eq(5, eval('v:shell_error')) - eval([[systemlist('this-should-not-exist')]]) - eq(127, eval('v:shell_error')) + it('sets v:shell_error', function() + if iswin() then + eval([[systemlist("cmd.exe /c exit")]]) + eq(0, eval('v:shell_error')) + eval([[systemlist("cmd.exe /c exit 1")]]) + eq(1, eval('v:shell_error')) + eval([[systemlist("cmd.exe /c exit 5")]]) + eq(5, eval('v:shell_error')) + eval([[systemlist('this-should-not-exist')]]) + eq(1, eval('v:shell_error')) + else + eval([[systemlist("sh -c 'exit'")]]) + eq(0, eval('v:shell_error')) + eval([[systemlist("sh -c 'exit 1'")]]) + eq(1, eval('v:shell_error')) + eval([[systemlist("sh -c 'exit 5'")]]) + eq(5, eval('v:shell_error')) + eval([[systemlist('this-should-not-exist')]]) + eq(127, eval('v:shell_error')) + end end) describe('exectues shell function', function() @@ -330,18 +446,19 @@ describe('systemlist()', function() after_each(delete_file(fname)) it('replaces NULs by newline characters', function() + if helpers.pending_win32(pending) then return end eq({'part1\npart2\npart3'}, eval('systemlist("cat '..fname..'")')) end) end) - describe('passing list as input', function() + describe('input passed as List', function() it('joins list items with linefeed characters', function() eq({'line1', 'line2', 'line3'}, eval("systemlist('cat -', ['line1', 'line2', 'line3'])")) end) -- Unlike `system()` which uses SOH to represent NULs, with `systemlist()` - -- input and ouput are the same + -- input and ouput are the same. describe('with linefeed characters inside list items', function() it('converts linefeed characters to NULs', function() eq({'l1\np2', 'line2\na\nb', 'l3'}, @@ -381,11 +498,11 @@ describe('systemlist()', function() describe("with a program that doesn't close stdout", function() if not xclip then - pending('skipped (missing xclip)', function() end) + pending('missing `xclip`', function() end) else it('will exit properly after passing input', function() eq({}, eval( - "systemlist('xclip -i -selection clipboard', ['clip', 'data'])")) + "systemlist('xclip -i -loops 1 -selection clipboard', ['clip', 'data'])")) eq({'clip', 'data'}, eval( "systemlist('xclip -o -selection clipboard')")) end) diff --git a/test/functional/eval/timer_spec.lua b/test/functional/eval/timer_spec.lua index fba9466b78..2dd9968a01 100644 --- a/test/functional/eval/timer_spec.lua +++ b/test/functional/eval/timer_spec.lua @@ -2,7 +2,7 @@ local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') local ok, feed, eq, eval = helpers.ok, helpers.feed, helpers.eq, helpers.eval local source, nvim_async, run = helpers.source, helpers.nvim_async, helpers.run -local clear, execute, funcs = helpers.clear, helpers.execute, helpers.funcs +local clear, command, funcs = helpers.clear, helpers.command, helpers.funcs local curbufmeths = helpers.curbufmeths describe('timers', function() @@ -17,14 +17,14 @@ describe('timers', function() end) it('works one-shot', function() - execute("call timer_start(50, 'MyHandler')") + command("call timer_start(50, 'MyHandler')") eq(0,eval("g:val")) run(nil, nil, nil, 200) eq(1,eval("g:val")) end) it('works one-shot when repeat=0', function() - execute("call timer_start(50, 'MyHandler', {'repeat': 0})") + command("call timer_start(50, 'MyHandler', {'repeat': 0})") eq(0,eval("g:val")) run(nil, nil, nil, 200) eq(1,eval("g:val")) @@ -32,14 +32,14 @@ describe('timers', function() it('works with repeat two', function() - execute("call timer_start(50, 'MyHandler', {'repeat': 2})") + command("call timer_start(50, 'MyHandler', {'repeat': 2})") eq(0,eval("g:val")) run(nil, nil, nil, 300) eq(2,eval("g:val")) end) it('are triggered during sleep', function() - execute("call timer_start(50, 'MyHandler', {'repeat': 2})") + command("call timer_start(50, 'MyHandler', {'repeat': 2})") nvim_async("command", "sleep 10") eq(0,eval("g:val")) run(nil, nil, nil, 300) @@ -49,7 +49,7 @@ describe('timers', function() it('works with zero timeout', function() -- timer_start does still not invoke the callback immediately eq(0,eval("[timer_start(0, 'MyHandler', {'repeat': 1000}), g:val][1]")) - run(nil, nil, nil, 300) + run(nil, nil, nil, 400) eq(1000,eval("g:val")) end) @@ -63,12 +63,12 @@ describe('timers', function() end) it('are paused when event processing is disabled', function() - execute("call timer_start(50, 'MyHandler', {'repeat': -1})") + command("call timer_start(50, 'MyHandler', {'repeat': -1})") run(nil, nil, nil, 100) local count = eval("g:val") -- shows two line error message and thus invokes the return prompt. -- if we start to allow event processing here, we need to change this test. - execute("throw 'fatal error'") + feed(':throw "fatal error"<CR>') run(nil, nil, nil, 300) feed("<cr>") local diff = eval("g:val") - count @@ -76,12 +76,12 @@ describe('timers', function() end) it('are triggered in blocking getchar() call', function() - execute("call timer_start(50, 'MyHandler', {'repeat': -1})") + command("call timer_start(50, 'MyHandler', {'repeat': -1})") nvim_async("command", "let g:c = getchar()") run(nil, nil, nil, 300) feed("c") local count = eval("g:val") - ok(count >= 5) + ok(count >= 4) eq(99, eval("g:c")) end) @@ -157,7 +157,7 @@ describe('timers', function() endif endfunc ]]) - execute("call timer_start(50, 'MyHandler', {'repeat': -1})") + command("call timer_start(50, 'MyHandler', {'repeat': -1})") eq(0,eval("g:val")) run(nil, nil, nil, 300) eq(3,eval("g:val")) @@ -170,8 +170,8 @@ describe('timers', function() let g:val2 += 1 endfunc ]]) - execute("call timer_start(50, 'MyHandler', {'repeat': 3})") - execute("call timer_start(100, 'MyHandler2', {'repeat': 2})") + command("call timer_start(50, 'MyHandler', {'repeat': 3})") + command("call timer_start(100, 'MyHandler2', {'repeat': 2})") run(nil, nil, nil, 300) eq(3,eval("g:val")) eq(2,eval("g:val2")) @@ -186,7 +186,7 @@ describe('timers', function() let g:val += 1 endfunc ]]) - execute("call timer_start(5, 'MyHandler', {'repeat': 1})") + command("call timer_start(5, 'MyHandler', {'repeat': 1})") run(nil, nil, nil, 300) eq(1,eval("g:val")) end) @@ -201,7 +201,7 @@ describe('timers', function() echo "evil" endfunc ]]) - execute("call timer_start(100, 'MyHandler', {'repeat': 1})") + command("call timer_start(100, 'MyHandler', {'repeat': 1})") feed(":good") screen:sleep(200) screen:expect([[ diff --git a/test/functional/eval/writefile_spec.lua b/test/functional/eval/writefile_spec.lua new file mode 100644 index 0000000000..2f84114b9b --- /dev/null +++ b/test/functional/eval/writefile_spec.lua @@ -0,0 +1,149 @@ +local helpers = require('test.functional.helpers')(after_each) +local lfs = require('lfs') + +local clear = helpers.clear +local eq = helpers.eq +local funcs = helpers.funcs +local meths = helpers.meths +local exc_exec = helpers.exc_exec +local read_file = helpers.read_file +local write_file = helpers.write_file +local redir_exec = helpers.redir_exec + +local fname = 'Xtest-functional-eval-writefile' +local dname = fname .. '.d' +local dfname_tail = '1' +local dfname = dname .. '/' .. dfname_tail +local ddname_tail = '2' +local ddname = dname .. '/' .. ddname_tail + +before_each(function() + lfs.mkdir(dname) + lfs.mkdir(ddname) + clear() +end) + +after_each(function() + os.remove(fname) + os.remove(dfname) + lfs.rmdir(ddname) + lfs.rmdir(dname) +end) + +describe('writefile()', function() + it('writes empty list to a file', function() + eq(nil, read_file(fname)) + eq(0, funcs.writefile({}, fname)) + eq('', read_file(fname)) + os.remove(fname) + eq(nil, read_file(fname)) + eq(0, funcs.writefile({}, fname, 'b')) + eq('', read_file(fname)) + os.remove(fname) + eq(nil, read_file(fname)) + eq(0, funcs.writefile({}, fname, 'ab')) + eq('', read_file(fname)) + os.remove(fname) + eq(nil, read_file(fname)) + eq(0, funcs.writefile({}, fname, 'a')) + eq('', read_file(fname)) + end) + + it('writes list with an empty string to a file', function() + eq(0, exc_exec( + ('call writefile([$XXX_NONEXISTENT_VAR_XXX], "%s", "b")'):format( + fname))) + eq('', read_file(fname)) + eq(0, exc_exec(('call writefile([$XXX_NONEXISTENT_VAR_XXX], "%s")'):format( + fname))) + eq('\n', read_file(fname)) + end) + + it('appends to a file', function() + eq(nil, read_file(fname)) + eq(0, funcs.writefile({'abc', 'def', 'ghi'}, fname)) + eq('abc\ndef\nghi\n', read_file(fname)) + eq(0, funcs.writefile({'jkl'}, fname, 'a')) + eq('abc\ndef\nghi\njkl\n', read_file(fname)) + os.remove(fname) + eq(nil, read_file(fname)) + eq(0, funcs.writefile({'abc', 'def', 'ghi'}, fname, 'b')) + eq('abc\ndef\nghi', read_file(fname)) + eq(0, funcs.writefile({'jkl'}, fname, 'ab')) + eq('abc\ndef\nghijkl', read_file(fname)) + end) + + it('correctly treats NLs', function() + eq(0, funcs.writefile({'\na\nb\n'}, fname, 'b')) + eq('\0a\0b\0', read_file(fname)) + eq(0, funcs.writefile({'a\n\n\nb'}, fname, 'b')) + eq('a\0\0\0b', read_file(fname)) + end) + + it('writes with s and S', function() + eq(0, funcs.writefile({'\na\nb\n'}, fname, 'bs')) + eq('\0a\0b\0', read_file(fname)) + eq(0, funcs.writefile({'a\n\n\nb'}, fname, 'bS')) + eq('a\0\0\0b', read_file(fname)) + end) + + it('correctly overwrites file', function() + eq(0, funcs.writefile({'\na\nb\n'}, fname, 'b')) + eq('\0a\0b\0', read_file(fname)) + eq(0, funcs.writefile({'a\n'}, fname, 'b')) + eq('a\0', read_file(fname)) + end) + + it('shows correct file name when supplied numbers', function() + meths.set_current_dir(dname) + eq('\nE482: Can\'t open file 2 for writing: illegal operation on a directory', + redir_exec(('call writefile([42], %s)'):format(ddname_tail))) + end) + + it('errors out with invalid arguments', function() + write_file(fname, 'TEST') + eq('\nE119: Not enough arguments for function: writefile', + redir_exec('call writefile()')) + eq('\nE119: Not enough arguments for function: writefile', + redir_exec('call writefile([])')) + eq('\nE118: Too many arguments for function: writefile', + redir_exec(('call writefile([], "%s", "b", 1)'):format(fname))) + for _, arg in ipairs({'0', '0.0', 'function("tr")', '{}', '"test"'}) do + eq('\nE686: Argument of writefile() must be a List', + redir_exec(('call writefile(%s, "%s", "b")'):format(arg, fname))) + end + for _, args in ipairs({'[], %s, "b"', '[], "' .. fname .. '", %s'}) do + eq('\nE806: using Float as a String', + redir_exec(('call writefile(%s)'):format(args:format('0.0')))) + eq('\nE730: using List as a String', + redir_exec(('call writefile(%s)'):format(args:format('[]')))) + eq('\nE731: using Dictionary as a String', + redir_exec(('call writefile(%s)'):format(args:format('{}')))) + eq('\nE729: using Funcref as a String', + redir_exec(('call writefile(%s)'):format(args:format('function("tr")')))) + end + eq('\nE5060: Unknown flag: ยซยป', + redir_exec(('call writefile([], "%s", "bsยซยป")'):format(fname))) + eq('TEST', read_file(fname)) + end) + + it('stops writing to file after error in list', function() + local args = '["tset"] + repeat([%s], 3), "' .. fname .. '"' + eq('\nE806: using Float as a String', + redir_exec(('call writefile(%s)'):format(args:format('0.0')))) + eq('tset\n', read_file(fname)) + write_file(fname, 'TEST') + eq('\nE730: using List as a String', + redir_exec(('call writefile(%s)'):format(args:format('[]')))) + eq('tset\n', read_file(fname)) + write_file(fname, 'TEST') + eq('\nE731: using Dictionary as a String', + redir_exec(('call writefile(%s)'):format(args:format('{}')))) + eq('tset\n', read_file(fname)) + write_file(fname, 'TEST') + eq('\nE729: using Funcref as a String', + redir_exec(('call writefile(%s)'):format(args:format('function("tr")')))) + eq('tset\n', read_file(fname)) + write_file(fname, 'TEST') + end) +end) diff --git a/test/functional/ex_cmds/arg_spec.lua b/test/functional/ex_cmds/arg_spec.lua index e11b90532f..6d31f05c2a 100644 --- a/test/functional/ex_cmds/arg_spec.lua +++ b/test/functional/ex_cmds/arg_spec.lua @@ -1,5 +1,5 @@ local helpers = require("test.functional.helpers")(after_each) -local eq, execute, funcs = helpers.eq, helpers.execute, helpers.funcs +local eq, command, funcs = helpers.eq, helpers.command, helpers.funcs local ok = helpers.ok local clear = helpers.clear @@ -9,15 +9,15 @@ describe(":argument", function() end) it("does not restart :terminal buffer", function() - execute("terminal") + command("terminal") helpers.feed([[<C-\><C-N>]]) - execute("argadd") + command("argadd") helpers.feed([[<C-\><C-N>]]) local bufname_before = funcs.bufname("%") local bufnr_before = funcs.bufnr("%") helpers.ok(nil ~= string.find(bufname_before, "^term://")) -- sanity - execute("argument 1") + command("argument 1") helpers.feed([[<C-\><C-N>]]) local bufname_after = funcs.bufname("%") diff --git a/test/functional/ex_cmds/bang_filter_spec.lua b/test/functional/ex_cmds/bang_filter_spec.lua index a320e6d018..aaec983b73 100644 --- a/test/functional/ex_cmds/bang_filter_spec.lua +++ b/test/functional/ex_cmds/bang_filter_spec.lua @@ -1,7 +1,7 @@ -- Specs for bang/filter commands local helpers = require('test.functional.helpers')(after_each) -local feed, execute, clear = helpers.feed, helpers.execute, helpers.clear +local feed, command, clear = helpers.feed, helpers.command, helpers.clear local mkdir, write_file, rmdir = helpers.mkdir, helpers.write_file, helpers.rmdir if helpers.pending_win32(pending) then return end @@ -28,7 +28,7 @@ describe('issues', function() end) it('#3269 Last line of shell output is not truncated', function() - execute([[nnoremap <silent>\l :!ls bang_filter_spec<cr>]]) + command([[nnoremap <silent>\l :!ls bang_filter_spec<cr>]]) feed([[\l]]) screen:expect([[ ~ | diff --git a/test/functional/ex_cmds/cd_spec.lua b/test/functional/ex_cmds/cd_spec.lua index 5bf4d22d0f..059cb26d5d 100644 --- a/test/functional/ex_cmds/cd_spec.lua +++ b/test/functional/ex_cmds/cd_spec.lua @@ -6,7 +6,7 @@ local helpers = require('test.functional.helpers')(after_each) local eq = helpers.eq local call = helpers.call local clear = helpers.clear -local execute = helpers.execute +local command = helpers.command local exc_exec = helpers.exc_exec if helpers.pending_win32(pending) then return end @@ -58,7 +58,7 @@ for _, cmd in ipairs {'cd', 'chdir'} do eq(0, lwd(globalwin)) eq(0, lwd(globalwin, tabnr)) - execute('bot split') + command('bot split') local localwin = call('winnr') -- Initial window is still using globalDir eq(globalDir, cwd(localwin)) @@ -66,7 +66,7 @@ for _, cmd in ipairs {'cd', 'chdir'} do eq(0, lwd(globalwin)) eq(0, lwd(globalwin, tabnr)) - execute('silent l' .. cmd .. ' ' .. directories.window) + command('silent l' .. cmd .. ' ' .. directories.window) -- From window with local dir, the original window -- is still reporting the global dir eq(globalDir, cwd(globalwin)) @@ -80,7 +80,7 @@ for _, cmd in ipairs {'cd', 'chdir'} do eq(1, lwd(localwin)) eq(1, lwd(localwin, tabnr)) - execute('tabnew') + command('tabnew') -- From new tab page, original window reports global dir eq(globalDir, cwd(globalwin, tabnr)) eq(0, lwd(globalwin, tabnr)) @@ -100,8 +100,8 @@ for _, cmd in ipairs {'cd', 'chdir'} do eq(0, lwd(-1, 0)) eq(0, lwd(-1, globaltab)) - execute('tabnew') - execute('silent t' .. cmd .. ' ' .. directories.tab) + command('tabnew') + command('silent t' .. cmd .. ' ' .. directories.tab) local localtab = call('tabpagenr') -- From local tab page, original tab reports globalDir @@ -114,7 +114,7 @@ for _, cmd in ipairs {'cd', 'chdir'} do eq(1, lwd(-1, 0)) eq(1, lwd(-1, localtab)) - execute('tabnext') + command('tabnext') -- From original tab page, local reports as such eq(globalDir .. '/' .. directories.tab, cwd(-1, localtab)) eq(1, lwd(-1, localtab)) @@ -128,13 +128,13 @@ for _, cmd in ipairs {'cd', 'chdir'} do end) it('works with tab-local pwd', function() - execute('silent t' .. cmd .. ' ' .. directories.tab) + command('silent t' .. cmd .. ' ' .. directories.tab) eq(directories.start, cwd(-1, -1)) eq(0, lwd(-1, -1)) end) it('works with window-local pwd', function() - execute('silent l' .. cmd .. ' ' .. directories.window) + command('silent l' .. cmd .. ' ' .. directories.window) eq(directories.start, cwd(-1, -1)) eq(0, lwd(-1, -1)) end) @@ -145,18 +145,18 @@ for _, cmd in ipairs {'cd', 'chdir'} do local globalDir = directories.start -- Create a new tab and change directory - execute('tabnew') - execute('silent t' .. cmd .. ' ' .. directories.tab) + command('tabnew') + command('silent t' .. cmd .. ' ' .. directories.tab) eq(globalDir .. '/' .. directories.tab, tcwd()) -- Create a new tab and verify it has inherited the directory - execute('tabnew') + command('tabnew') eq(globalDir .. '/' .. directories.tab, tcwd()) -- Change tab and change back, verify that directories are correct - execute('tabnext') + command('tabnext') eq(globalDir, tcwd()) - execute('tabprevious') + command('tabprevious') eq(globalDir .. '/' .. directories.tab, tcwd()) end) end) @@ -164,7 +164,7 @@ for _, cmd in ipairs {'cd', 'chdir'} do it('works', function() local globalDir = directories.start -- Create a new tab first and verify that is has the same working dir - execute('tabnew') + command('tabnew') eq(globalDir, cwd()) eq(globalDir, tcwd()) -- has no tab-local directory eq(0, tlwd()) @@ -172,7 +172,7 @@ for _, cmd in ipairs {'cd', 'chdir'} do eq(0, wlwd()) -- Change tab-local working directory and verify it is different - execute('silent t' .. cmd .. ' ' .. directories.tab) + command('silent t' .. cmd .. ' ' .. directories.tab) eq(globalDir .. '/' .. directories.tab, cwd()) eq(cwd(), tcwd()) -- working directory maches tab directory eq(1, tlwd()) @@ -180,46 +180,46 @@ for _, cmd in ipairs {'cd', 'chdir'} do eq(0, wlwd()) -- Create a new window in this tab to test `:lcd` - execute('new') + command('new') eq(1, tlwd()) -- Still tab-local working directory eq(0, wlwd()) -- Still no window-local working directory eq(globalDir .. '/' .. directories.tab, cwd()) - execute('silent l' .. cmd .. ' ../' .. directories.window) + command('silent l' .. cmd .. ' ../' .. directories.window) eq(globalDir .. '/' .. directories.window, cwd()) eq(globalDir .. '/' .. directories.tab, tcwd()) eq(1, wlwd()) -- Verify the first window still has the tab local directory - execute('wincmd w') + command('wincmd w') eq(globalDir .. '/' .. directories.tab, cwd()) eq(globalDir .. '/' .. directories.tab, tcwd()) eq(0, wlwd()) -- No window-local directory -- Change back to initial tab and verify working directory has stayed - execute('tabnext') + command('tabnext') eq(globalDir, cwd() ) eq(0, tlwd()) eq(0, wlwd()) -- Verify global changes don't affect local ones - execute('silent ' .. cmd .. ' ' .. directories.global) + command('silent ' .. cmd .. ' ' .. directories.global) eq(globalDir .. '/' .. directories.global, cwd()) - execute('tabnext') + command('tabnext') eq(globalDir .. '/' .. directories.tab, cwd()) eq(globalDir .. '/' .. directories.tab, tcwd()) eq(0, wlwd()) -- Still no window-local directory in this window -- Unless the global change happened in a tab with local directory - execute('silent ' .. cmd .. ' ..') + command('silent ' .. cmd .. ' ..') eq(globalDir, cwd() ) eq(0 , tlwd()) eq(0 , wlwd()) -- Which also affects the first tab - execute('tabnext') + command('tabnext') eq(globalDir, cwd()) -- But not in a window with its own local directory - execute('tabnext | wincmd w') + command('tabnext | wincmd w') eq(globalDir .. '/' .. directories.window, cwd() ) eq(0 , tlwd()) eq(globalDir .. '/' .. directories.window, wcwd()) @@ -280,8 +280,8 @@ describe("getcwd()", function () end) it("returns empty string if working directory does not exist", function() - execute("cd "..directories.global) - execute("call delete('../"..directories.global.."', 'd')") + command("cd "..directories.global) + command("call delete('../"..directories.global.."', 'd')") eq("", helpers.eval("getcwd()")) end) end) diff --git a/test/functional/ex_cmds/ctrl_c_spec.lua b/test/functional/ex_cmds/ctrl_c_spec.lua index b0acb02000..091a008814 100644 --- a/test/functional/ex_cmds/ctrl_c_spec.lua +++ b/test/functional/ex_cmds/ctrl_c_spec.lua @@ -1,9 +1,7 @@ local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') local clear, feed, source = helpers.clear, helpers.feed, helpers.source -local execute = helpers.execute - -if helpers.pending_win32(pending) then return end +local command = helpers.command describe("CTRL-C (mapped)", function() before_each(function() @@ -11,9 +9,9 @@ describe("CTRL-C (mapped)", function() end) it("interrupts :global", function() + -- Crashes luajit. if helpers.skip_fragile(pending, - (os.getenv("TRAVIS") and os.getenv("CLANG_SANITIZER") == "ASAN_UBSAN")) - then + os.getenv("TRAVIS") or os.getenv("APPVEYOR")) then return end @@ -22,7 +20,7 @@ describe("CTRL-C (mapped)", function() nnoremap <C-C> <NOP> ]]) - execute("silent edit! test/functional/fixtures/bigfile.txt") + command("silent edit! test/functional/fixtures/bigfile.txt") local screen = Screen.new(52, 6) screen:attach() screen:set_default_attr_ids({ @@ -43,13 +41,13 @@ describe("CTRL-C (mapped)", function() local function test_ctrl_c(ms) feed(":global/^/p<CR>") - helpers.sleep(ms) + screen:sleep(ms) feed("<C-C>") screen:expect([[Interrupt]], nil, nil, nil, true) end -- The test is time-sensitive. Try different sleep values. - local ms_values = {1, 10, 100} + local ms_values = {1, 10, 100, 1000, 10000} for i, ms in ipairs(ms_values) do if i < #ms_values then local status, _ = pcall(test_ctrl_c, ms) diff --git a/test/functional/ex_cmds/dict_notifications_spec.lua b/test/functional/ex_cmds/dict_notifications_spec.lua index e6f7609016..e3b4a1c504 100644 --- a/test/functional/ex_cmds/dict_notifications_spec.lua +++ b/test/functional/ex_cmds/dict_notifications_spec.lua @@ -3,12 +3,13 @@ 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 local command = helpers.command +local eval = helpers.eval describe('dictionary change notifications', function() local channel - setup(function() + before_each(function() clear() channel = nvim('get_api_info')[1] nvim('set_var', 'channel', channel) @@ -17,19 +18,15 @@ describe('dictionary change notifications', function() -- 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 gentests(dict_expr, dict_init) local function update(opval, key) if not key then key = 'watched' end if opval == '' then - nvim('command', "unlet "..dict_expr..dict_expr_suffix..key) + command(('unlet %s[\'%s\']'):format(dict_expr, key)) else - nvim('command', "let "..dict_expr..dict_expr_suffix..key.." "..opval) + command(('let %s[\'%s\'] %s'):format(dict_expr, key, opval)) end end @@ -47,9 +44,9 @@ describe('dictionary change notifications', function() eq({'notification', 'values', {key, vals}}, next_msg()) end - describe('watcher', function() + describe(dict_expr .. ' watcher', function() if dict_init then - setup(function() + before_each(function() source(dict_init) end) end @@ -57,7 +54,7 @@ describe('dictionary change notifications', function() before_each(function() source([[ function! g:Changed(dict, key, value) - if a:dict != ]]..dict_expr..[[ | + if a:dict isnot ]]..dict_expr..[[ | throw 'invalid dict' endif call rpcnotify(g:channel, 'values', a:key, a:value) @@ -142,6 +139,32 @@ describe('dictionary change notifications', function() ]]) end) + it('is triggered for empty keys', function() + command([[ + call dictwatcheradd(]]..dict_expr..[[, "", "g:Changed") + ]]) + update('= 1', '') + verify_value({new = 1}, '') + update('= 2', '') + verify_value({old = 1, new = 2}, '') + command([[ + call dictwatcherdel(]]..dict_expr..[[, "", "g:Changed") + ]]) + end) + + it('is triggered for empty keys when using catch-all *', function() + command([[ + call dictwatcheradd(]]..dict_expr..[[, "*", "g:Changed") + ]]) + update('= 1', '') + verify_value({new = 1}, '') + update('= 2', '') + verify_value({old = 1, new = 2}, '') + command([[ + 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) @@ -189,10 +212,10 @@ describe('dictionary change notifications', function() gentests('b:') gentests('w:') gentests('t:') - gentests('g:dict_var', '.', 'let g:dict_var = {}') + gentests('g:dict_var', 'let g:dict_var = {}') describe('multiple watchers on the same dict/key', function() - setup(function() + before_each(function() source([[ function! g:Watcher1(dict, key, value) call rpcnotify(g:channel, '1', a:key, a:value) @@ -212,13 +235,37 @@ describe('dictionary change notifications', function() end) it('only removes watchers that fully match dict, key and callback', function() + nvim('command', 'let g:key = "value"') + eq({'notification', '1', {'key', {new = 'value'}}}, next_msg()) + eq({'notification', '2', {'key', {new = 'value'}}}, next_msg()) 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) + it('errors out when adding to v:_null_dict', function() + command([[ + function! g:Watcher1(dict, key, value) + call rpcnotify(g:channel, '1', a:key, a:value) + endfunction + ]]) + eq('Vim(call):E46: Cannot change read-only variable "dictwatcheradd() argument"', + exc_exec('call dictwatcheradd(v:_null_dict, "x", "g:Watcher1")')) + end) + describe('errors', function() + before_each(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 + ]]) + end) + -- 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", @@ -235,15 +282,24 @@ describe('dictionary change notifications', function() command('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")')) + it('fails to remove watcher from v:_null_dict', function() + eq("Vim(call):Couldn't find a watcher matching key and callback", + exc_exec('call dictwatcherdel(v:_null_dict, "x", "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('does not fail to replace a watcher function', function() source([[ + let g:key = 'v2' + call dictwatcheradd(g:, "key", "g:Watcher2") function! g:ReplaceWatcher2() function! g:Watcher2(dict, key, value) call rpcnotify(g:channel, '2b', a:key, a:value) @@ -253,7 +309,33 @@ describe('dictionary change notifications', function() command('call g:ReplaceWatcher2()') command('let g:key = "value"') eq({'notification', '2b', {'key', {old = 'v2', new = 'value'}}}, next_msg()) + end) + it('does not crash when freeing a watched dictionary', function() + source([[ + function! Watcher(dict, key, value) + echo a:key string(a:value) + endfunction + + function! MakeWatch() + let d = {'foo': 'bar'} + call dictwatcheradd(d, 'foo', function('Watcher')) + endfunction + ]]) + + command('call MakeWatch()') + eq(2, eval('1+1')) -- Still alive? + end) + end) + + describe('with lambdas', function() + it('works correctly', function() + source([[ + let d = {'foo': 'baz'} + call dictwatcheradd(d, 'foo', {dict, key, value -> rpcnotify(g:channel, '2', key, value)}) + let d.foo = 'bar' + ]]) + eq({'notification', '2', {'foo', {old = 'baz', new = 'bar'}}}, next_msg()) end) end) end) diff --git a/test/functional/ex_cmds/drop_spec.lua b/test/functional/ex_cmds/drop_spec.lua index 99db5ea333..9105b84367 100644 --- a/test/functional/ex_cmds/drop_spec.lua +++ b/test/functional/ex_cmds/drop_spec.lua @@ -1,6 +1,6 @@ local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') -local clear, feed, execute = helpers.clear, helpers.feed, helpers.execute +local clear, feed, feed_command = helpers.clear, helpers.feed, helpers.feed_command describe(":drop", function() local screen @@ -15,7 +15,7 @@ describe(":drop", function() [2] = {reverse = true}, [3] = {bold = true}, }) - execute("set laststatus=2") + feed_command("set laststatus=2") end) after_each(function() @@ -23,7 +23,7 @@ describe(":drop", function() end) it("works like :e when called with only one window open", function() - execute("drop tmp1.vim") + feed_command("drop tmp1.vim") screen:expect([[ ^ | {0:~ }| @@ -39,10 +39,10 @@ describe(":drop", function() end) it("switches to an open window showing the buffer", function() - execute("edit tmp1") - execute("vsplit") - execute("edit tmp2") - execute("drop tmp1") + feed_command("edit tmp1") + feed_command("vsplit") + feed_command("edit tmp2") + feed_command("drop tmp1") screen:expect([[ {2:|}^ | {0:~ }{2:|}{0:~ }| @@ -58,11 +58,11 @@ describe(":drop", function() end) it("splits off a new window when a buffer can't be abandoned", function() - execute("edit tmp1") - execute("vsplit") - execute("edit tmp2") + feed_command("edit tmp1") + feed_command("vsplit") + feed_command("edit tmp2") feed("iABC<esc>") - execute("drop tmp3") + feed_command("drop tmp3") screen:expect([[ ^ {2:|} | {0:~ }{2:|}{0:~ }| diff --git a/test/functional/ex_cmds/echo_spec.lua b/test/functional/ex_cmds/echo_spec.lua new file mode 100644 index 0000000000..10c7230896 --- /dev/null +++ b/test/functional/ex_cmds/echo_spec.lua @@ -0,0 +1,321 @@ +local helpers = require('test.functional.helpers')(after_each) + +local eq = helpers.eq +local NIL = helpers.NIL +local eval = helpers.eval +local clear = helpers.clear +local meths = helpers.meths +local funcs = helpers.funcs +local source = helpers.source +local dedent = helpers.dedent +local command = helpers.command +local exc_exec = helpers.exc_exec +local redir_exec = helpers.redir_exec + +describe(':echo', function() + before_each(function() + clear() + source([[ + function String(s) + return execute('echo a:s')[1:] + endfunction + ]]) + end) + + describe('used to represent floating-point values', function() + it('dumps NaN values', function() + eq('str2float(\'nan\')', eval('String(str2float(\'nan\'))')) + end) + + it('dumps infinite values', function() + eq('str2float(\'inf\')', eval('String(str2float(\'inf\'))')) + eq('-str2float(\'inf\')', eval('String(str2float(\'-inf\'))')) + end) + + it('dumps regular values', function() + eq('1.5', funcs.String(1.5)) + eq('1.56e-20', funcs.String(1.56000e-020)) + eq('0.0', eval('String(0.0)')) + end) + + it('dumps special v: values', function() + eq('v:true', eval('String(v:true)')) + eq('v:false', eval('String(v:false)')) + eq('v:null', eval('String(v:null)')) + eq('v:true', funcs.String(true)) + eq('v:false', funcs.String(false)) + eq('v:null', funcs.String(NIL)) + end) + + it('dumps values with at most six digits after the decimal point', + function() + eq('1.234568e-20', funcs.String(1.23456789123456789123456789e-020)) + eq('1.234568', funcs.String(1.23456789123456789123456789)) + end) + + it('dumps values with at most seven digits before the decimal point', + function() + eq('1234567.891235', funcs.String(1234567.89123456789123456789)) + eq('1.234568e7', funcs.String(12345678.9123456789123456789)) + end) + + it('dumps negative values', function() + eq('-1.5', funcs.String(-1.5)) + eq('-1.56e-20', funcs.String(-1.56000e-020)) + eq('-1.234568e-20', funcs.String(-1.23456789123456789123456789e-020)) + eq('-1.234568', funcs.String(-1.23456789123456789123456789)) + eq('-1234567.891235', funcs.String(-1234567.89123456789123456789)) + eq('-1.234568e7', funcs.String(-12345678.9123456789123456789)) + end) + end) + + describe('used to represent numbers', function() + it('dumps regular values', function() + eq('0', funcs.String(0)) + eq('-1', funcs.String(-1)) + eq('1', funcs.String(1)) + end) + + it('dumps large values', function() + eq('2147483647', funcs.String(2^31-1)) + eq('-2147483648', funcs.String(-2^31)) + end) + end) + + describe('used to represent strings', function() + it('dumps regular strings', function() + eq('test', funcs.String('test')) + end) + + it('dumps empty strings', function() + eq('', funcs.String('')) + end) + + it('dumps strings with \' inside', function() + eq('\'\'\'', funcs.String('\'\'\'')) + eq('a\'b\'\'', funcs.String('a\'b\'\'')) + eq('\'b\'\'d', funcs.String('\'b\'\'d')) + eq('a\'b\'c\'d', funcs.String('a\'b\'c\'d')) + end) + + it('dumps NULL strings', function() + eq('', eval('String($XXX_UNEXISTENT_VAR_XXX)')) + end) + + it('dumps NULL lists', function() + eq('[]', eval('String(v:_null_list)')) + end) + + it('dumps NULL dictionaries', function() + eq('{}', eval('String(v:_null_dict)')) + end) + end) + + describe('used to represent funcrefs', function() + before_each(function() + source([[ + function Test1() + endfunction + + function s:Test2() dict + endfunction + + function g:Test3() dict + endfunction + + let g:Test2_f = function('s:Test2') + ]]) + end) + + it('dumps references to built-in functions', function() + eq('function', eval('String(function("function"))')) + end) + + it('dumps references to user functions', function() + eq('Test1', eval('String(function("Test1"))')) + eq('g:Test3', eval('String(function("g:Test3"))')) + end) + + it('dumps references to script functions', function() + eq('<SNR>2_Test2', eval('String(Test2_f)')) + end) + + it('dumps partials with self referencing a partial', function() + source([[ + function TestDict() dict + endfunction + let d = {} + let TestDictRef = function('TestDict', d) + let d.tdr = TestDictRef + ]]) + eq(dedent([[ + + function('TestDict', {'tdr': function('TestDict', {...@1})}) + function('TestDict', {'tdr': function('TestDict', {...@1})})]]), + redir_exec('echo String(d.tdr)')) + end) + + it('dumps automatically created partials', function() + eq('function(\'<SNR>2_Test2\', {\'f\': function(\'<SNR>2_Test2\')})', + eval('String({"f": Test2_f}.f)')) + eq('function(\'<SNR>2_Test2\', [1], {\'f\': function(\'<SNR>2_Test2\', [1])})', + eval('String({"f": function(Test2_f, [1])}.f)')) + end) + + it('dumps manually created partials', function() + eq('function(\'Test3\', [1, 2], {})', + eval('String(function("Test3", [1, 2], {}))')) + eq('function(\'Test3\', {})', + eval('String(function("Test3", {}))')) + eq('function(\'Test3\', [1, 2])', + eval('String(function("Test3", [1, 2]))')) + end) + + it('does not crash or halt when dumping partials with reference cycles in self', + function() + meths.set_var('d', {v=true}) + eq(dedent([[ + + {'p': function('<SNR>2_Test2', {...@0}), 'f': function('<SNR>2_Test2'), 'v': v:true} + {'p': function('<SNR>2_Test2', {...@0}), 'f': function('<SNR>2_Test2'), 'v': v:true}]]), + redir_exec('echo String(extend(extend(g:d, {"f": g:Test2_f}), {"p": g:d.f}))')) + end) + + it('does not show errors when dumping partials referencing the same dictionary', + function() + command('let d = {}') + -- Regression for โeval/typval_encode: Dump empty dictionary before + -- checking for refcycleโ, results in error. + eq('[function(\'tr\', {}), function(\'tr\', {})]', eval('String([function("tr", d), function("tr", d)])')) + -- Regression for โeval: Work with reference cycles in partials (self) + -- properlyโ, results in crash. + eval('extend(d, {"a": 1})') + eq('[function(\'tr\', {\'a\': 1}), function(\'tr\', {\'a\': 1})]', eval('String([function("tr", d), function("tr", d)])')) + end) + + it('does not crash or halt when dumping partials with reference cycles in arguments', + function() + meths.set_var('l', {}) + eval('add(l, l)') + -- Regression: the below line used to crash (add returns original list and + -- there was error in dumping partials). Tested explicitly in + -- test/unit/api/private_helpers_spec.lua. + eval('add(l, function("Test1", l))') + eq(dedent([=[ + + function('Test1', [[[...@2], function('Test1', [[...@2]])], function('Test1', [[[...@4], function('Test1', [[...@4]])]])]) + function('Test1', [[[...@2], function('Test1', [[...@2]])], function('Test1', [[[...@4], function('Test1', [[...@4]])]])])]=]), + redir_exec('echo String(function("Test1", l))')) + end) + + it('does not crash or halt when dumping partials with reference cycles in self and arguments', + function() + meths.set_var('d', {v=true}) + meths.set_var('l', {}) + eval('add(l, l)') + eval('add(l, function("Test1", l))') + eval('add(l, function("Test1", d))') + eq(dedent([=[ + + {'p': function('<SNR>2_Test2', [[[...@3], function('Test1', [[...@3]]), function('Test1', {...@0})], function('Test1', [[[...@5], function('Test1', [[...@5]]), function('Test1', {...@0})]]), function('Test1', {...@0})], {...@0}), 'f': function('<SNR>2_Test2'), 'v': v:true} + {'p': function('<SNR>2_Test2', [[[...@3], function('Test1', [[...@3]]), function('Test1', {...@0})], function('Test1', [[[...@5], function('Test1', [[...@5]]), function('Test1', {...@0})]]), function('Test1', {...@0})], {...@0}), 'f': function('<SNR>2_Test2'), 'v': v:true}]=]), + redir_exec('echo String(extend(extend(g:d, {"f": g:Test2_f}), {"p": function(g:d.f, l)}))')) + end) + end) + + describe('used to represent lists', function() + it('dumps empty list', function() + eq('[]', funcs.String({})) + end) + + it('dumps nested lists', function() + eq('[[[[[]]]]]', funcs.String({{{{{}}}}})) + end) + + it('dumps nested non-empty lists', function() + eq('[1, [[3, [[5], 4]], 2]]', funcs.String({1, {{3, {{5}, 4}}, 2}})) + end) + + it('does not error when dumping recursive lists', function() + meths.set_var('l', {}) + eval('add(l, l)') + eq(0, exc_exec('echo String(l)')) + end) + + it('dumps recursive lists without error', function() + meths.set_var('l', {}) + eval('add(l, l)') + eq('\n[[...@0]]\n[[...@0]]', redir_exec('echo String(l)')) + eq('\n[[[...@1]]]\n[[[...@1]]]', redir_exec('echo String([l])')) + end) + end) + + describe('used to represent dictionaries', function() + it('dumps empty dictionary', function() + eq('{}', eval('String({})')) + end) + + it('dumps list with two same empty dictionaries, also in partials', function() + command('let d = {}') + eq('[{}, {}]', eval('String([d, d])')) + eq('[function(\'tr\', {}), {}]', eval('String([function("tr", d), d])')) + eq('[{}, function(\'tr\', {})]', eval('String([d, function("tr", d)])')) + end) + + it('dumps non-empty dictionary', function() + eq('{\'t\'\'est\': 1}', funcs.String({['t\'est']=1})) + end) + + it('does not error when dumping recursive dictionaries', function() + meths.set_var('d', {d=1}) + eval('extend(d, {"d": d})') + eq(0, exc_exec('echo String(d)')) + end) + + it('dumps recursive dictionaries without the error', function() + meths.set_var('d', {d=1}) + eval('extend(d, {"d": d})') + eq('\n{\'d\': {...@0}}\n{\'d\': {...@0}}', + redir_exec('echo String(d)')) + eq('\n{\'out\': {\'d\': {...@1}}}\n{\'out\': {\'d\': {...@1}}}', + redir_exec('echo String({"out": d})')) + end) + end) + + describe('used to represent special values', function() + local function chr(n) + return ('%c'):format(n) + end + local function ctrl(c) + return ('%c'):format(c:upper():byte() - 0x40) + end + it('displays hex as hex', function() + -- Regression: due to missing (uint8_t) cast \x80 was represented as + -- ~@<80>. + eq('<80>', funcs.String(chr(0x80))) + eq('<81>', funcs.String(chr(0x81))) + eq('<8e>', funcs.String(chr(0x8e))) + eq('<c2>', funcs.String(('ยซ'):sub(1, 1))) + eq('ยซ', funcs.String(('ยซ'):sub(1, 2))) + end) + it('displays ASCII control characters using ^X notation', function() + eq('^C', funcs.String(ctrl('c'))) + eq('^A', funcs.String(ctrl('a'))) + eq('^F', funcs.String(ctrl('f'))) + end) + it('prints CR, NL and tab as-is', function() + eq('\n', funcs.String('\n')) + eq('\r', funcs.String('\r')) + eq('\t', funcs.String('\t')) + end) + it('prints non-printable UTF-8 in <> notation', function() + -- SINGLE SHIFT TWO, unicode control + eq('<8e>', funcs.String(funcs.nr2char(0x8E))) + -- Surrogate pair: U+1F0A0 PLAYING CARD BACK is represented in UTF-16 as + -- 0xD83C 0xDCA0. This is not valid in UTF-8. + eq('<d83c>', funcs.String(funcs.nr2char(0xD83C))) + eq('<dca0>', funcs.String(funcs.nr2char(0xDCA0))) + eq('<d83c><dca0>', funcs.String(funcs.nr2char(0xD83C) .. funcs.nr2char(0xDCA0))) + end) + end) +end) diff --git a/test/functional/ex_cmds/edit_spec.lua b/test/functional/ex_cmds/edit_spec.lua index 3cc5f5fb95..6ed500a293 100644 --- a/test/functional/ex_cmds/edit_spec.lua +++ b/test/functional/ex_cmds/edit_spec.lua @@ -1,7 +1,8 @@ local helpers = require("test.functional.helpers")(after_each) -local eq, execute, funcs = helpers.eq, helpers.execute, helpers.funcs +local eq, command, funcs = helpers.eq, helpers.command, helpers.funcs local ok = helpers.ok local clear = helpers.clear +local feed = helpers.feed describe(":edit", function() before_each(function() @@ -9,13 +10,13 @@ describe(":edit", function() end) it("without arguments does not restart :terminal buffer", function() - execute("terminal") - helpers.feed([[<C-\><C-N>]]) + command("terminal") + feed([[<C-\><C-N>]]) local bufname_before = funcs.bufname("%") local bufnr_before = funcs.bufnr("%") helpers.ok(nil ~= string.find(bufname_before, "^term://")) -- sanity - execute("edit") + command("edit") local bufname_after = funcs.bufname("%") local bufnr_after = funcs.bufnr("%") diff --git a/test/functional/ex_cmds/encoding_spec.lua b/test/functional/ex_cmds/encoding_spec.lua index 87ed7a2d0a..7f2bd78a47 100644 --- a/test/functional/ex_cmds/encoding_spec.lua +++ b/test/functional/ex_cmds/encoding_spec.lua @@ -1,5 +1,5 @@ local helpers = require('test.functional.helpers')(after_each) -local clear, execute, feed = helpers.clear, helpers.execute, helpers.feed +local clear, feed_command, feed = helpers.clear, helpers.feed_command, helpers.feed local eq, neq, eval = helpers.eq, helpers.neq, helpers.eval describe('&encoding', function() @@ -12,10 +12,10 @@ describe('&encoding', function() end) it('cannot be changed after setup', function() - execute('set encoding=latin1') + feed_command('set encoding=latin1') -- error message expected feed('<cr>') - neq(nil, string.find(eval('v:errmsg'), '^E474:')) + neq(nil, string.find(eval('v:errmsg'), '^E519:')) eq('utf-8', eval('&encoding')) -- check nvim is still in utf-8 mode eq(3, eval('strwidth("Bรคr")')) @@ -25,13 +25,13 @@ describe('&encoding', function() clear('--cmd', 'set enc=latin1') -- error message expected feed('<cr>') - neq(nil, string.find(eval('v:errmsg'), '^E474:')) + neq(nil, string.find(eval('v:errmsg'), '^E519:')) eq('utf-8', eval('&encoding')) eq(3, eval('strwidth("Bรคr")')) end) it('can be set to utf-8 without error', function() - execute('set encoding=utf-8') + feed_command('set encoding=utf-8') eq("", eval('v:errmsg')) clear('--cmd', 'set enc=utf-8') diff --git a/test/functional/ex_cmds/file_spec.lua b/test/functional/ex_cmds/file_spec.lua new file mode 100644 index 0000000000..771c283134 --- /dev/null +++ b/test/functional/ex_cmds/file_spec.lua @@ -0,0 +1,35 @@ +local helpers = require('test.functional.helpers')(after_each) +local lfs = require('lfs') +local clear = helpers.clear +local command = helpers.command +local eq = helpers.eq +local funcs = helpers.funcs +local rmdir = helpers.rmdir + +describe(':file', function() + local swapdir = lfs.currentdir()..'/Xtest-file_spec' + before_each(function() + clear() + rmdir(swapdir) + lfs.mkdir(swapdir) + end) + after_each(function() + command('%bwipeout!') + rmdir(swapdir) + end) + + it("rename does not lose swapfile #6487", function() + local testfile = 'test-file_spec' + local testfile_renamed = testfile..'-renamed' + -- Note: `set swapfile` *must* go after `set directory`: otherwise it may + -- attempt to create a swapfile in different directory. + command('set directory^='..swapdir..'//') + command('set swapfile fileformat=unix undolevels=-1') + + command('edit! '..testfile) + -- Before #6487 this gave "E301: Oops, lost the swap file !!!" on Windows. + command('file '..testfile_renamed) + eq(testfile_renamed..'.swp', + string.match(funcs.execute('swapname'), '[^%%]+$')) + end) +end) diff --git a/test/functional/ex_cmds/grep_spec.lua b/test/functional/ex_cmds/grep_spec.lua index 13f88b7e03..43ef1bd424 100644 --- a/test/functional/ex_cmds/grep_spec.lua +++ b/test/functional/ex_cmds/grep_spec.lua @@ -1,6 +1,6 @@ local helpers = require('test.functional.helpers')(after_each) -local clear, execute, feed, ok, eval = - helpers.clear, helpers.execute, helpers.feed, helpers.ok, helpers.eval +local clear, feed_command, feed, ok, eval = + helpers.clear, helpers.feed_command, helpers.feed, helpers.ok, helpers.eval describe(':grep', function() before_each(clear) @@ -11,10 +11,10 @@ describe(':grep', function() return end - execute([[set grepprg=grep\ -r]]) + feed_command([[set grepprg=grep\ -r]]) -- Change to test directory so that the test does not run too long. - execute('cd test') - execute('grep a **/*') + feed_command('cd test') + feed_command('grep a **/*') feed('<cr>') -- Press ENTER ok(eval('len(getqflist())') > 9000) -- IT'S OVER 9000!!1 end) diff --git a/test/functional/ex_cmds/menu_spec.lua b/test/functional/ex_cmds/menu_spec.lua index 52df9e1592..55da8da8dc 100644 --- a/test/functional/ex_cmds/menu_spec.lua +++ b/test/functional/ex_cmds/menu_spec.lua @@ -1,23 +1,25 @@ local helpers = require('test.functional.helpers')(after_each) -local clear, execute, nvim = helpers.clear, helpers.execute, helpers.nvim -local expect, feed, command = helpers.expect, helpers.feed, helpers.command +local clear, command, nvim = helpers.clear, helpers.command, helpers.nvim +local expect, feed = helpers.expect, helpers.feed local eq, eval = helpers.eq, helpers.eval +local funcs = helpers.funcs + describe(':emenu', function() before_each(function() clear() - execute('nnoremenu Test.Test inormal<ESC>') - execute('inoremenu Test.Test insert') - execute('vnoremenu Test.Test x') - execute('cnoremenu Test.Test cmdmode') + command('nnoremenu Test.Test inormal<ESC>') + command('inoremenu Test.Test insert') + command('vnoremenu Test.Test x') + command('cnoremenu Test.Test cmdmode') - execute('nnoremenu Edit.Paste p') - execute('cnoremenu Edit.Paste <C-R>"') + command('nnoremenu Edit.Paste p') + command('cnoremenu Edit.Paste <C-R>"') end) it('executes correct bindings in normal mode without using API', function() - execute('emenu Test.Test') + command('emenu Test.Test') expect('normal') end) @@ -56,3 +58,326 @@ describe(':emenu', function() eq('thiscmdmode', eval('getcmdline()')) end) end) + +describe('menu_get', function() + + before_each(function() + clear() + command('nnoremenu &Test.Test inormal<ESC>') + command('inoremenu Test.Test insert') + command('vnoremenu Test.Test x') + command('cnoremenu Test.Test cmdmode') + command('menu Test.Nested.test level1') + command('menu Test.Nested.Nested2 level2') + + command('nnoremenu <script> Export.Script p') + command('tmenu Export.Script This is the tooltip') + command('menu ]Export.hidden thisoneshouldbehidden') + + command('nnoremenu Edit.Paste p') + command('cnoremenu Edit.Paste <C-R>"') + end) + + it("path='', modes='a'", function() + local m = funcs.menu_get("","a"); + -- HINT: To print the expected table and regenerate the tests: + -- print(require('pl.pretty').dump(m)) + local expected = { + { + shortcut = "T", + hidden = 0, + submenus = { + { + mappings = { + i = { + sid = 1, + noremap = 1, + enabled = 1, + rhs = "insert", + silent = 0 + }, + s = { + sid = 1, + noremap = 1, + enabled = 1, + rhs = "x", + silent = 0 + }, + n = { + sid = 1, + noremap = 1, + enabled = 1, + rhs = "inormal\27", + silent = 0 + }, + v = { + sid = 1, + noremap = 1, + enabled = 1, + rhs = "x", + silent = 0 + }, + c = { + sid = 1, + noremap = 1, + enabled = 1, + rhs = "cmdmode", + silent = 0 + } + }, + priority = 500, + name = "Test", + hidden = 0 + }, + { + priority = 500, + name = "Nested", + submenus = { + { + mappings = { + o = { + sid = 0, + noremap = 0, + enabled = 1, + rhs = "level1", + silent = 0 + }, + v = { + sid = 0, + noremap = 0, + enabled = 1, + rhs = "level1", + silent = 0 + }, + s = { + sid = 0, + noremap = 0, + enabled = 1, + rhs = "level1", + silent = 0 + }, + n = { + sid = 0, + noremap = 0, + enabled = 1, + rhs = "level1", + silent = 0 + } + }, + priority = 500, + name = "test", + hidden = 0 + }, + { + mappings = { + o = { + sid = 0, + noremap = 0, + enabled = 1, + rhs = "level2", + silent = 0 + }, + v = { + sid = 0, + noremap = 0, + enabled = 1, + rhs = "level2", + silent = 0 + }, + s = { + sid = 0, + noremap = 0, + enabled = 1, + rhs = "level2", + silent = 0 + }, + n = { + sid = 0, + noremap = 0, + enabled = 1, + rhs = "level2", + silent = 0 + } + }, + priority = 500, + name = "Nested2", + hidden = 0 + } + }, + hidden = 0 + } + }, + priority = 500, + name = "Test" + }, + { + priority = 500, + name = "Export", + submenus = { + { + tooltip = "This is the tooltip", + hidden = 0, + name = "Script", + priority = 500, + mappings = { + n = { + sid = 1, + noremap = 1, + enabled = 1, + rhs = "p", + silent = 0 + } + } + } + }, + hidden = 0 + }, + { + priority = 500, + name = "Edit", + submenus = { + { + mappings = { + c = { + sid = 1, + noremap = 1, + enabled = 1, + rhs = "\18\"", + silent = 0 + }, + n = { + sid = 1, + noremap = 1, + enabled = 1, + rhs = "p", + silent = 0 + } + }, + priority = 500, + name = "Paste", + hidden = 0 + } + }, + hidden = 0 + }, + { + priority = 500, + name = "]Export", + submenus = { + { + mappings = { + o = { + sid = 0, + noremap = 0, + enabled = 1, + rhs = "thisoneshouldbehidden", + silent = 0 + }, + v = { + sid = 0, + noremap = 0, + enabled = 1, + rhs = "thisoneshouldbehidden", + silent = 0 + }, + s = { + sid = 0, + noremap = 0, + enabled = 1, + rhs = "thisoneshouldbehidden", + silent = 0 + }, + n = { + sid = 0, + noremap = 0, + enabled = 1, + rhs = "thisoneshouldbehidden", + silent = 0 + } + }, + priority = 500, + name = "hidden", + hidden = 0 + } + }, + hidden = 1 + } + } + eq(expected, m) + end) + + it('matching path, default modes', function() + local m = funcs.menu_get("Export", "a") + local expected = { + { + tooltip = "This is the tooltip", + hidden = 0, + name = "Script", + priority = 500, + mappings = { + n = { + sid = 1, + noremap = 1, + enabled = 1, + rhs = "p", + silent = 0 + } + } + } + } + eq(expected, m) + end) + + it('no path, matching modes', function() + local m = funcs.menu_get("","i") + local expected = { + { + shortcut = "T", + hidden = 0, + submenus = { + { + mappings = { + i = { + sid = 1, + noremap = 1, + enabled = 1, + rhs = "insert", + silent = 0 + } + }, + priority = 500, + name = "Test", + hidden = 0 + }, + { + } + }, + priority = 500, + name = "Test" + } + } + eq(expected, m) + end) + + it('matching path and modes', function() + local m = funcs.menu_get("Test","i") + local expected = { + { + mappings = { + i = { + sid = 1, + noremap = 1, + enabled = 1, + rhs = "insert", + silent = 0 + } + }, + priority = 500, + name = "Test", + hidden = 0 + } + } + eq(expected, m) + end) + +end) diff --git a/test/functional/ex_cmds/mksession_spec.lua b/test/functional/ex_cmds/mksession_spec.lua new file mode 100644 index 0000000000..5d658f10bb --- /dev/null +++ b/test/functional/ex_cmds/mksession_spec.lua @@ -0,0 +1,49 @@ +local lfs = require('lfs') +local helpers = require('test.functional.helpers')(after_each) + +local clear = helpers.clear +local command = helpers.command +local get_pathsep = helpers.get_pathsep +local eq = helpers.eq +local funcs = helpers.funcs + +local file_prefix = 'Xtest-functional-ex_cmds-mksession_spec' + +describe(':mksession', function() + local session_file = file_prefix .. '.vim' + local tab_dir = file_prefix .. '.d' + + before_each(function() + clear() + lfs.mkdir(tab_dir) + end) + + after_each(function() + os.remove(session_file) + lfs.rmdir(tab_dir) + end) + + it('restores tab-local working directories', function() + local tmpfile_base = file_prefix .. '-tmpfile' + local cwd_dir = funcs.getcwd() + + -- :mksession does not save empty tabs, so create some buffers. + command('edit ' .. tmpfile_base .. '1') + command('tabnew') + command('edit ' .. tmpfile_base .. '2') + command('tcd ' .. tab_dir) + command('tabfirst') + command('mksession ' .. session_file) + + -- Create a new test instance of Nvim. + clear() + + command('source ' .. session_file) + -- First tab should have the original working directory. + command('tabnext 1') + eq(cwd_dir, funcs.getcwd()) + -- Second tab should have the tab-local working directory. + command('tabnext 2') + eq(cwd_dir .. get_pathsep() .. tab_dir, funcs.getcwd()) + end) +end) diff --git a/test/functional/ex_cmds/oldfiles_spec.lua b/test/functional/ex_cmds/oldfiles_spec.lua index a218bb6633..4002855c24 100644 --- a/test/functional/ex_cmds/oldfiles_spec.lua +++ b/test/functional/ex_cmds/oldfiles_spec.lua @@ -1,20 +1,18 @@ local Screen = require('test.functional.ui.screen') local helpers = require('test.functional.helpers')(after_each) -local buf, eq, execute = helpers.curbufmeths, helpers.eq, helpers.execute +local buf, eq, feed_command = helpers.curbufmeths, helpers.eq, helpers.feed_command local feed, nvim_prog, wait = helpers.feed, helpers.nvim_prog, helpers.wait local ok, set_session, spawn = helpers.ok, helpers.set_session, helpers.spawn +local eval = helpers.eval -local shada_file = 'test.shada' +local shada_file = 'Xtest.shada' --- --- helpers.clear() uses "-i NONE", which is not useful for this test. --- local function _clear() - set_session(spawn({nvim_prog, - '-u', 'NONE', - '--cmd', 'set noswapfile undodir=. directory=. viewdir=. backupdir=.', - '--embed'})) + set_session(spawn({nvim_prog, '--embed', '-u', 'NONE', + -- Need shada for these tests. + '-i', shada_file, + '--cmd', 'set noswapfile undodir=. directory=. viewdir=. backupdir=. belloff= noshowcmd noruler'})) end describe(':oldfiles', function() @@ -31,12 +29,12 @@ describe(':oldfiles', function() it('shows most recently used files', function() local screen = Screen.new(100, 5) screen:attach() - execute('edit testfile1') - execute('edit testfile2') - execute('wshada ' .. shada_file) - execute('rshada! ' .. shada_file) + feed_command('edit testfile1') + feed_command('edit testfile2') + feed_command('wshada') + feed_command('rshada!') local oldfiles = helpers.meths.get_vvar('oldfiles') - execute('oldfiles') + feed_command('oldfiles') screen:expect([[ testfile2 | 1: ]].. add_padding(oldfiles[1]) ..[[ | @@ -45,6 +43,38 @@ describe(':oldfiles', function() Press ENTER or type command to continue^ | ]]) end) + + it('can be filtered with :filter', function() + feed_command('edit file_one.txt') + local file1 = buf.get_name() + feed_command('edit file_two.txt') + local file2 = buf.get_name() + feed_command('edit another.txt') + local another = buf.get_name() + feed_command('wshada') + feed_command('rshada!') + + local function get_oldfiles(cmd) + local t = eval([[split(execute(']]..cmd..[['), "\n")]]) + for i, _ in ipairs(t) do + t[i] = t[i]:gsub('^%d+:%s+', '') + end + table.sort(t) + return t + end + + local oldfiles = get_oldfiles('oldfiles') + eq({another, file1, file2}, oldfiles) + + oldfiles = get_oldfiles('filter file_ oldfiles') + eq({file1, file2}, oldfiles) + + oldfiles = get_oldfiles('filter /another/ oldfiles') + eq({another}, oldfiles) + + oldfiles = get_oldfiles('filter! file_ oldfiles') + eq({another}, oldfiles) + end) end) describe(':browse oldfiles', function() @@ -54,16 +84,15 @@ describe(':browse oldfiles', function() before_each(function() _clear() - execute('edit testfile1') + feed_command('edit testfile1') filename = buf.get_name() - execute('edit testfile2') + feed_command('edit testfile2') filename2 = buf.get_name() - execute('wshada ' .. shada_file) + feed_command('wshada') wait() _clear() - execute('rshada! ' .. shada_file) - -- Ensure nvim is out of "Press ENTER..." screen + -- Ensure nvim is out of "Press ENTER..." prompt. feed('<cr>') -- Ensure v:oldfiles isn't busted. Since things happen so fast, @@ -74,7 +103,7 @@ describe(':browse oldfiles', function() ok(filename == oldfiles[1] or filename == oldfiles[2]) ok(filename2 == oldfiles[1] or filename2 == oldfiles[2]) - execute('browse oldfiles') + feed_command('browse oldfiles') end) after_each(function() diff --git a/test/functional/ex_cmds/print_commands_spec.lua b/test/functional/ex_cmds/print_commands_spec.lua new file mode 100644 index 0000000000..98c0f74635 --- /dev/null +++ b/test/functional/ex_cmds/print_commands_spec.lua @@ -0,0 +1,12 @@ +local helpers = require('test.functional.helpers')(after_each) +local clear, eq, command, funcs = + helpers.clear, helpers.eq, helpers.command, helpers.funcs + +describe(':z^', function() + before_each(clear) + + it('correctly sets the cursor after :z^', function() + command('z^') + eq(1, funcs.line('.')) + end) +end) diff --git a/test/functional/ex_cmds/quickfix_commands_spec.lua b/test/functional/ex_cmds/quickfix_commands_spec.lua new file mode 100644 index 0000000000..5ab34db3fb --- /dev/null +++ b/test/functional/ex_cmds/quickfix_commands_spec.lua @@ -0,0 +1,83 @@ +local helpers = require('test.functional.helpers')(after_each) + +local eq = helpers.eq +local clear = helpers.clear +local funcs = helpers.funcs +local command = helpers.command +local exc_exec = helpers.exc_exec +local write_file = helpers.write_file +local curbufmeths = helpers.curbufmeths + +local file_base = 'Xtest-functional-ex_cmds-quickfix_commands' + +before_each(clear) + +for _, c in ipairs({'l', 'c'}) do + local file = ('%s.%s'):format(file_base, c) + local filecmd = c .. 'file' + local getfcmd = c .. 'getfile' + local addfcmd = c .. 'addfile' + local getlist = (c == 'c') and funcs.getqflist or ( + function() return funcs.getloclist(0) end) + + describe((':%s*file commands'):format(c), function() + before_each(function() + write_file(file, ([[ + %s-1.res:700:10:Line 700 + %s-2.res:800:15:Line 800 + ]]):format(file, file)) + end) + after_each(function() + os.remove(file) + end) + + it('work', function() + command(('%s %s'):format(filecmd, file)) + -- Second line of each entry (i.e. `nr=-1, โฆ`) was obtained from actual + -- results. First line (i.e. `{lnum=โฆ`) was obtained from legacy test. + local list = { + {lnum=700, col=10, text='Line 700', + nr=-1, bufnr=2, valid=1, pattern='', vcol=0, ['type']=''}, + {lnum=800, col=15, text='Line 800', + nr=-1, bufnr=3, valid=1, pattern='', vcol=0, ['type']=''}, + } + eq(list, getlist()) + eq(('%s-1.res'):format(file), funcs.bufname(list[1].bufnr)) + eq(('%s-2.res'):format(file), funcs.bufname(list[2].bufnr)) + + -- Run cfile/lfile from a modified buffer + command('enew!') + curbufmeths.set_lines(1, 1, true, {'Quickfix'}) + eq(('Vim(%s):E37: No write since last change (add ! to override)'):format( + filecmd), + exc_exec(('%s %s'):format(filecmd, file))) + + write_file(file, ([[ + %s-3.res:900:30:Line 900 + ]]):format(file)) + command(('%s %s'):format(addfcmd, file)) + list[#list + 1] = { + lnum=900, col=30, text='Line 900', + nr=-1, bufnr=5, valid=1, pattern='', vcol=0, ['type']='', + } + eq(list, getlist()) + eq(('%s-3.res'):format(file), funcs.bufname(list[3].bufnr)) + + write_file(file, ([[ + %s-1.res:222:77:Line 222 + %s-2.res:333:88:Line 333 + ]]):format(file, file)) + command('enew!') + command(('%s %s'):format(getfcmd, file)) + list = { + {lnum=222, col=77, text='Line 222', + nr=-1, bufnr=2, valid=1, pattern='', vcol=0, ['type']=''}, + {lnum=333, col=88, text='Line 333', + nr=-1, bufnr=3, valid=1, pattern='', vcol=0, ['type']=''}, + } + eq(list, getlist()) + eq(('%s-1.res'):format(file), funcs.bufname(list[1].bufnr)) + eq(('%s-2.res'):format(file), funcs.bufname(list[2].bufnr)) + end) + end) +end diff --git a/test/functional/ex_cmds/recover_spec.lua b/test/functional/ex_cmds/recover_spec.lua index af1296c94c..cb68c29b9a 100644 --- a/test/functional/ex_cmds/recover_spec.lua +++ b/test/functional/ex_cmds/recover_spec.lua @@ -1,19 +1,18 @@ --- Tests for :recover - local helpers = require('test.functional.helpers')(after_each) local lfs = require('lfs') -local execute, eq, clear, eval, feed, expect, source = - helpers.execute, helpers.eq, helpers.clear, helpers.eval, helpers.feed, +local feed_command, eq, clear, eval, feed, expect, source = + helpers.feed_command, helpers.eq, helpers.clear, helpers.eval, helpers.feed, helpers.expect, helpers.source - -if helpers.pending_win32(pending) then return end +local command = helpers.command +local ok = helpers.ok +local rmdir = helpers.rmdir describe(':recover', function() before_each(clear) it('fails if given a non-existent swapfile', function() local swapname = 'bogus-swapfile' - execute('recover '..swapname) -- This should not segfault. #2117 + feed_command('recover '..swapname) -- This should not segfault. #2117 eq('E305: No swap file found for '..swapname, eval('v:errmsg')) end) @@ -23,30 +22,29 @@ describe(':preserve', function() local swapdir = lfs.currentdir()..'/testdir_recover_spec' before_each(function() clear() - helpers.rmdir(swapdir) + rmdir(swapdir) lfs.mkdir(swapdir) end) after_each(function() - helpers.rmdir(swapdir) + command('%bwipeout!') + rmdir(swapdir) end) it("saves to custom 'directory' and (R)ecovers (issue #1836)", function() local testfile = 'testfile_recover_spec' + -- Put swapdir at the start of the 'directory' list. #1836 -- Note: `set swapfile` *must* go after `set directory`: otherwise it may -- attempt to create a swapfile in different directory. local init = [[ - set directory^=]]..swapdir..[[// + set directory^=]]..swapdir:gsub([[\]], [[\\]])..[[// set swapfile fileformat=unix undolevels=-1 ]] source(init) - execute('set swapfile fileformat=unix undolevels=-1') - -- Put swapdir at the start of the 'directory' list. #1836 - execute('set directory^='..swapdir..'//') - execute('edit '..testfile) + command('edit! '..testfile) feed('isometext<esc>') - execute('preserve') - source('redir => g:swapname | swapname | redir END') + command('preserve') + source('redir => g:swapname | silent swapname | redir END') local swappath1 = eval('g:swapname') @@ -59,19 +57,20 @@ describe(':preserve', function() source(init) -- Use the "SwapExists" event to choose the (R)ecover choice at the dialog. - execute('autocmd SwapExists * let v:swapchoice = "r"') - execute('silent edit '..testfile) - source('redir => g:swapname | swapname | redir END') + command('autocmd SwapExists * let v:swapchoice = "r"') + command('silent edit! '..testfile) + source('redir => g:swapname | silent swapname | redir END') local swappath2 = eval('g:swapname') + expect('sometext') -- swapfile from session 1 should end in .swp - assert(testfile..'.swp' == string.match(swappath1, '[^%%]+$')) - + eq(testfile..'.swp', string.match(swappath1, '[^%%]+$')) -- swapfile from session 2 should end in .swo - assert(testfile..'.swo' == string.match(swappath2, '[^%%]+$')) - - expect('sometext') + eq(testfile..'.swo', string.match(swappath2, '[^%%]+$')) + -- Verify that :swapname was not truncated (:help 'shortmess'). + ok(nil == string.find(swappath1, '%.%.%.')) + ok(nil == string.find(swappath2, '%.%.%.')) end) end) diff --git a/test/functional/ex_cmds/script_spec.lua b/test/functional/ex_cmds/script_spec.lua new file mode 100644 index 0000000000..4e57d2755d --- /dev/null +++ b/test/functional/ex_cmds/script_spec.lua @@ -0,0 +1,75 @@ +local helpers = require('test.functional.helpers')(after_each) + +local eq = helpers.eq +local neq = helpers.neq +local meths = helpers.meths +local clear = helpers.clear +local dedent = helpers.dedent +local source = helpers.source +local exc_exec = helpers.exc_exec +local missing_provider = helpers.missing_provider + +before_each(clear) + +describe('script_get-based command', function() + local garbage = ')}{+*({}]*[;(+}{&[]}{*])(' + + local function test_garbage_exec(cmd, check_neq) + describe(cmd, function() + it('works correctly when skipping oneline variant', function() + eq(true, pcall(source, (dedent([[ + if 0 + %s %s + endif + ]])):format(cmd, garbage))) + eq('', meths.command_output('messages')) + if check_neq then + neq(0, exc_exec(dedent([[ + %s %s + ]])):format(cmd, garbage)) + end + end) + it('works correctly when skipping HEREdoc variant', function() + eq(true, pcall(source, (dedent([[ + if 0 + %s << EOF + %s + EOF + endif + ]])):format(cmd, garbage))) + eq('', meths.command_output('messages')) + if check_neq then + eq(true, pcall(source, (dedent([[ + let g:exc = 0 + try + %s << EOF + %s + EOF + catch + let g:exc = v:exception + endtry + ]])):format(cmd, garbage))) + neq(0, meths.get_var('exc')) + end + end) + end) + end + + clear() + + -- Built-in scripts + test_garbage_exec('lua', true) + + -- Provider-based scripts + test_garbage_exec('ruby', not missing_provider('ruby')) + test_garbage_exec('python', not missing_provider('python')) + test_garbage_exec('python3', not missing_provider('python3')) + + -- Missing scripts + test_garbage_exec('tcl', false) + test_garbage_exec('mzscheme', false) + test_garbage_exec('perl', false) + + -- Not really a script + test_garbage_exec('xxxinvalidlanguagexxx', true) +end) diff --git a/test/functional/ex_cmds/syntax_spec.lua b/test/functional/ex_cmds/syntax_spec.lua new file mode 100644 index 0000000000..c9e96703de --- /dev/null +++ b/test/functional/ex_cmds/syntax_spec.lua @@ -0,0 +1,17 @@ +local helpers = require('test.functional.helpers')(after_each) + +local eq = helpers.eq +local clear = helpers.clear +local exc_exec = helpers.exc_exec + +describe(':syntax', function() + before_each(clear) + + describe('keyword', function() + it('does not crash when group name contains unprintable characters', + function() + eq('Vim(syntax):E669: Unprintable character in group name', + exc_exec('syntax keyword \024 foo bar')) + end) + end) +end) diff --git a/test/functional/ex_cmds/undojoin_spec.lua b/test/functional/ex_cmds/undojoin_spec.lua new file mode 100644 index 0000000000..7803906619 --- /dev/null +++ b/test/functional/ex_cmds/undojoin_spec.lua @@ -0,0 +1,38 @@ +local helpers = require('test.functional.helpers')(after_each) + +local eq = helpers.eq +local clear = helpers.clear +local insert = helpers.insert +local feed = helpers.feed +local expect = helpers.expect +local feed_command = helpers.feed_command +local exc_exec = helpers.exc_exec + +describe(':undojoin command', function() + before_each(function() + clear() + insert([[ + Line of text 1 + Line of text 2]]) + feed_command('goto 1') + end) + it('joins changes in a buffer', function() + feed_command('undojoin | delete') + expect([[ + Line of text 2]]) + feed('u') + expect([[ + ]]) + end) + it('does not corrupt undolist when connected with redo', function() + feed('ixx<esc>') + feed_command('undojoin | redo') + expect([[ + xxLine of text 1 + Line of text 2]]) + end) + it('does not raise an error when called twice', function() + local ret = exc_exec('undojoin | undojoin') + eq(0, ret) + end) +end) diff --git a/test/functional/ex_cmds/write_spec.lua b/test/functional/ex_cmds/write_spec.lua index 4ac9f312ef..863d439080 100644 --- a/test/functional/ex_cmds/write_spec.lua +++ b/test/functional/ex_cmds/write_spec.lua @@ -1,15 +1,29 @@ local helpers = require('test.functional.helpers')(after_each) -local eq, eval, clear, write_file, execute, source, insert = +local lfs = require('lfs') +local eq, eval, clear, write_file, source, insert = helpers.eq, helpers.eval, helpers.clear, helpers.write_file, - helpers.execute, helpers.source, helpers.insert + helpers.source, helpers.insert +local redir_exec = helpers.redir_exec +local exc_exec = helpers.exc_exec +local command = helpers.command +local feed_command = helpers.feed_command +local funcs = helpers.funcs +local meths = helpers.meths if helpers.pending_win32(pending) then return end +local fname = 'Xtest-functional-ex_cmds-write' +local fname_bak = fname .. '~' +local fname_broken = fname_bak .. 'broken' + describe(':write', function() local function cleanup() os.remove('test_bkc_file.txt') os.remove('test_bkc_link.txt') os.remove('test_fifo') + os.remove(fname) + os.remove(fname_bak) + os.remove(fname_broken) end before_each(function() clear() @@ -20,9 +34,9 @@ describe(':write', function() end) it('&backupcopy=auto preserves symlinks', function() - execute('set backupcopy=auto') + command('set backupcopy=auto') write_file('test_bkc_file.txt', 'content0') - execute("silent !ln -s test_bkc_file.txt test_bkc_link.txt") + command("silent !ln -s test_bkc_file.txt test_bkc_link.txt") source([[ edit test_bkc_link.txt call setline(1, ['content1']) @@ -33,9 +47,9 @@ describe(':write', function() end) it('&backupcopy=no replaces symlink with new file', function() - execute('set backupcopy=no') + command('set backupcopy=no') write_file('test_bkc_file.txt', 'content0') - execute("silent !ln -s test_bkc_file.txt test_bkc_link.txt") + command("silent !ln -s test_bkc_file.txt test_bkc_link.txt") source([[ edit test_bkc_link.txt call setline(1, ['content1']) @@ -56,11 +70,41 @@ describe(':write', function() insert(text) -- Blocks until a consumer reads the FIFO. - execute("write >> test_fifo") + feed_command("write >> test_fifo") -- Read the FIFO, this will unblock the :write above. local fifo = assert(io.open("test_fifo")) eq(text.."\n", fifo:read("*all")) fifo:close() end) + + it('errors out correctly', function() + command('let $HOME=""') + eq(funcs.fnamemodify('.', ':p:h'), funcs.fnamemodify('.', ':p:h:~')) + -- Message from check_overwrite + eq(('\nE17: "'..funcs.fnamemodify('.', ':p:h')..'" is a directory'), + redir_exec('write .')) + meths.set_option('writeany', true) + -- Message from buf_write + eq(('\nE502: "." is a directory'), + redir_exec('write .')) + funcs.mkdir(fname_bak) + meths.set_option('backupdir', '.') + meths.set_option('backup', true) + write_file(fname, 'content0') + eq(0, exc_exec('edit ' .. fname)) + funcs.setline(1, 'TTY') + eq('Vim(write):E510: Can\'t make backup file (add ! to override)', + exc_exec('write')) + meths.set_option('backup', false) + funcs.setfperm(fname, 'r--------') + eq('Vim(write):E505: "Xtest-functional-ex_cmds-write" is read-only (add ! to override)', + exc_exec('write')) + os.remove(fname) + os.remove(fname_bak) + write_file(fname_bak, 'TTYX') + lfs.link(fname_bak .. ('/xxxxx'):rep(20), fname, true) + eq('Vim(write):E166: Can\'t open linked file for writing', + exc_exec('write!')) + end) end) diff --git a/test/functional/ex_cmds/wundo_spec.lua b/test/functional/ex_cmds/wundo_spec.lua index e1216fa5d4..b6fcae0cf4 100644 --- a/test/functional/ex_cmds/wundo_spec.lua +++ b/test/functional/ex_cmds/wundo_spec.lua @@ -1,20 +1,21 @@ -- Specs for :wundo and underlying functions local helpers = require('test.functional.helpers')(after_each) -local execute, clear, eval, feed, spawn, nvim_prog, set_session = - helpers.execute, helpers.clear, helpers.eval, helpers.feed, helpers.spawn, +local command, clear, eval, spawn, nvim_prog, set_session = + helpers.command, helpers.clear, helpers.eval, helpers.spawn, helpers.nvim_prog, helpers.set_session describe(':wundo', function() before_each(clear) + after_each(function() + os.remove(eval('getcwd()') .. '/foo') + end) it('safely fails on new, non-empty buffer', function() - feed('iabc<esc>') - execute('wundo foo') -- This should not segfault. #1027 + command('normal! iabc') + command('wundo foo') -- This should not segfault. #1027 --TODO: check messages for error message - - os.remove(eval('getcwd()') .. '/foo') --cleanup end) end) @@ -23,7 +24,7 @@ describe('u_* functions', 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 + command('echo "True"') -- Should not error out due to crashed Neovim session:close() end) end) diff --git a/test/functional/ex_cmds/wviminfo_spec.lua b/test/functional/ex_cmds/wviminfo_spec.lua index 37f45da2d4..eebbd70f2b 100644 --- a/test/functional/ex_cmds/wviminfo_spec.lua +++ b/test/functional/ex_cmds/wviminfo_spec.lua @@ -1,8 +1,8 @@ local helpers = require('test.functional.helpers')(after_each) local lfs = require('lfs') -local execute, eq, neq, spawn, nvim_prog, set_session, wait, write_file - = helpers.execute, helpers.eq, helpers.neq, helpers.spawn, - helpers.nvim_prog, helpers.set_session, helpers.wait, helpers.write_file +local command, eq, neq, spawn, nvim_prog, set_session, write_file = + helpers.command, helpers.eq, helpers.neq, helpers.spawn, + helpers.nvim_prog, helpers.set_session, helpers.write_file describe(':wshada', function() local shada_file = 'wshada_test' @@ -24,8 +24,7 @@ describe(':wshada', function() it('creates a shada file', function() -- file should _not_ exist eq(nil, lfs.attributes(shada_file)) - execute('wsh! '..shada_file) - wait() + command('wsh! '..shada_file) -- file _should_ exist neq(nil, lfs.attributes(shada_file)) end) @@ -40,8 +39,7 @@ describe(':wshada', function() eq(text, io.open(shada_file):read()) neq(nil, lfs.attributes(shada_file)) - execute('wsh! '..shada_file) - wait() + command('wsh! '..shada_file) -- File should have been overwritten with a shada file. local fp = io.open(shada_file, 'r') diff --git a/test/functional/fixtures/CMakeLists.txt b/test/functional/fixtures/CMakeLists.txt index 70aee6efa9..8537ea390f 100644 --- a/test/functional/fixtures/CMakeLists.txt +++ b/test/functional/fixtures/CMakeLists.txt @@ -2,3 +2,4 @@ add_executable(tty-test tty-test.c) target_link_libraries(tty-test ${LIBUV_LIBRARIES}) add_executable(shell-test shell-test.c) +add_executable(printargs-test printargs-test.c) diff --git a/test/functional/fixtures/api_level_1.mpack b/test/functional/fixtures/api_level_1.mpack Binary files differnew file mode 100644 index 0000000000..66ea9c2e5d --- /dev/null +++ b/test/functional/fixtures/api_level_1.mpack diff --git a/test/functional/fixtures/api_level_2.mpack b/test/functional/fixtures/api_level_2.mpack Binary files differnew file mode 100644 index 0000000000..0ca2ba8866 --- /dev/null +++ b/test/functional/fixtures/api_level_2.mpack diff --git a/test/functional/fixtures/autoload/provider/clipboard.vim b/test/functional/fixtures/autoload/provider/clipboard.vim index 411e095c71..6d777255c8 100644 --- a/test/functional/fixtures/autoload/provider/clipboard.vim +++ b/test/functional/fixtures/autoload/provider/clipboard.vim @@ -5,7 +5,13 @@ let s:methods = {} let g:cliplossy = 0 let g:cliperror = 0 +" Count how many times the clipboard was invoked. +let g:clip_called_get = 0 +let g:clip_called_set = 0 + function! s:methods.get(reg) + let g:clip_called_get += 1 + if g:cliperror return 0 end @@ -19,6 +25,8 @@ function! s:methods.get(reg) endfunction function! s:methods.set(lines, regtype, reg) + let g:clip_called_set += 1 + if a:reg == '"' call s:methods.set(a:lines,a:regtype,'+') call s:methods.set(a:lines,a:regtype,'*') diff --git a/test/functional/fixtures/bigfile_oneline.txt b/test/functional/fixtures/bigfile_oneline.txt new file mode 100644 index 0000000000..263e81ebf0 --- /dev/null +++ b/test/functional/fixtures/bigfile_oneline.txt @@ -0,0 +1,593 @@ +0000;<control>;Cc;0;BN;;;;;N;NULL;;;; 0001;<control>;Cc;0;BN;;;;;N;START OF HEADING;;;; 0002;<control>;Cc;0;BN;;;;;N;START OF TEXT;;;; 0003;<control>;Cc;0;BN;;;;;N;END OF TEXT;;;; 0004;<control>;Cc;0;BN;;;;;N;END OF TRANSMISSION;;;; 0005;<control>;Cc;0;BN;;;;;N;ENQUIRY;;;; 0006;<control>;Cc;0;BN;;;;;N;ACKNOWLEDGE;;;; 0007;<control>;Cc;0;BN;;;;;N;BELL;;;; 0008;<control>;Cc;0;BN;;;;;N;BACKSPACE;;;; 0009;<control>;Cc;0;S;;;;;N;CHARACTER TABULATION;;;; 000A;<control>;Cc;0;B;;;;;N;LINE FEED (LF);;;; 000B;<control>;Cc;0;S;;;;;N;LINE TABULATION;;;; 000C;<control>;Cc;0;WS;;;;;N;FORM FEED (FF);;;; 000D;<control>;Cc;0;B;;;;;N;CARRIAGE RETURN (CR);;;; 000E;<control>;Cc;0;BN;;;;;N;SHIFT OUT;;;; 000F;<control>;Cc;0;BN;;;;;N;SHIFT IN;;;; 0010;<control>;Cc;0;BN;;;;;N;DATA LINK ESCAPE;;;; 0011;<control>;Cc;0;BN;;;;;N;DEVICE CONTROL ONE;;;; 0012;<control>;Cc;0;BN;;;;;N;DEVICE CONTROL TWO;;;; 0013;<control>;Cc;0;BN;;;;;N;DEVICE CONTROL THREE;;;; 0014;<control>;Cc;0;BN;;;;;N;DEVICE CONTROL FOUR;;;; 0015;<control>;Cc;0;BN;;;;;N;NEGATIVE ACKNOWLEDGE;;;; 0016;<control>;Cc;0;BN;;;;;N;SYNCHRONOUS IDLE;;;; 0017;<control>;Cc;0;BN;;;;;N;END OF TRANSMISSION BLOCK;;;; 0018;<control>;Cc;0;BN;;;;;N;CANCEL;;;; 0019;<control>;Cc;0;BN;;;;;N;END OF MEDIUM;;;; 001A;<control>;Cc;0;BN;;;;;N;SUBSTITUTE;;;; 001B;<control>;Cc;0;BN;;;;;N;ESCAPE;;;; 001C;<control>;Cc;0;B;;;;;N;INFORMATION SEPARATOR FOUR;;;; 001D;<control>;Cc;0;B;;;;;N;INFORMATION SEPARATOR THREE;;;; 001E;<control>;Cc;0;B;;;;;N;INFORMATION SEPARATOR TWO;;;; 001F;<control>;Cc;0;S;;;;;N;INFORMATION SEPARATOR ONE;;;; 0020;SPACE;Zs;0;WS;;;;;N;;;;; 0021;EXCLAMATION MARK;Po;0;ON;;;;;N;;;;; 0022;QUOTATION MARK;Po;0;ON;;;;;N;;;;; 0023;NUMBER SIGN;Po;0;ET;;;;;N;;;;; 0024;DOLLAR SIGN;Sc;0;ET;;;;;N;;;;; 0025;PERCENT SIGN;Po;0;ET;;;;;N;;;;; 0026;AMPERSAND;Po;0;ON;;;;;N;;;;; 0027;APOSTROPHE;Po;0;ON;;;;;N;APOSTROPHE-QUOTE;;;; 0028;LEFT PARENTHESIS;Ps;0;ON;;;;;Y;OPENING PARENTHESIS;;;; 0029;RIGHT PARENTHESIS;Pe;0;ON;;;;;Y;CLOSING PARENTHESIS;;;; 002A;ASTERISK;Po;0;ON;;;;;N;;;;; 002B;PLUS SIGN;Sm;0;ES;;;;;N;;;;; 002C;COMMA;Po;0;CS;;;;;N;;;;; 002D;HYPHEN-MINUS;Pd;0;ES;;;;;N;;;;; 002E;FULL STOP;Po;0;CS;;;;;N;PERIOD;;;; 002F;SOLIDUS;Po;0;CS;;;;;N;SLASH;;;; 0030;DIGIT ZERO;Nd;0;EN;;0;0;0;N;;;;; 0031;DIGIT ONE;Nd;0;EN;;1;1;1;N;;;;; 0032;DIGIT TWO;Nd;0;EN;;2;2;2;N;;;;; 0033;DIGIT THREE;Nd;0;EN;;3;3;3;N;;;;; 0034;DIGIT FOUR;Nd;0;EN;;4;4;4;N;;;;; 0035;DIGIT FIVE;Nd;0;EN;;5;5;5;N;;;;; 0036;DIGIT SIX;Nd;0;EN;;6;6;6;N;;;;; 0037;DIGIT SEVEN;Nd;0;EN;;7;7;7;N;;;;; 0038;DIGIT EIGHT;Nd;0;EN;;8;8;8;N;;;;; 0039;DIGIT NINE;Nd;0;EN;;9;9;9;N;;;;; 003A;COLON;Po;0;CS;;;;;N;;;;; 003B;SEMICOLON;Po;0;ON;;;;;N;;;;; 003C;LESS-THAN SIGN;Sm;0;ON;;;;;Y;;;;; 003D;EQUALS SIGN;Sm;0;ON;;;;;N;;;;; 003E;GREATER-THAN SIGN;Sm;0;ON;;;;;Y;;;;; 003F;QUESTION MARK;Po;0;ON;;;;;N;;;;; 0040;COMMERCIAL AT;Po;0;ON;;;;;N;;;;; 0041;LATIN CAPITAL LETTER A;Lu;0;L;;;;;N;;;;0061; 0042;LATIN CAPITAL LETTER B;Lu;0;L;;;;;N;;;;0062; 0043;LATIN CAPITAL LETTER C;Lu;0;L;;;;;N;;;;0063; 0044;LATIN CAPITAL LETTER D;Lu;0;L;;;;;N;;;;0064; 0045;LATIN CAPITAL LETTER E;Lu;0;L;;;;;N;;;;0065; 0046;LATIN CAPITAL LETTER F;Lu;0;L;;;;;N;;;;0066; 0047;LATIN CAPITAL LETTER G;Lu;0;L;;;;;N;;;;0067; 0048;LATIN CAPITAL LETTER H;Lu;0;L;;;;;N;;;;0068; 0049;LATIN CAPITAL LETTER I;Lu;0;L;;;;;N;;;;0069; 004A;LATIN CAPITAL LETTER J;Lu;0;L;;;;;N;;;;006A; 004B;LATIN CAPITAL LETTER K;Lu;0;L;;;;;N;;;;006B; 004C;LATIN CAPITAL LETTER L;Lu;0;L;;;;;N;;;;006C; 004D;LATIN CAPITAL LETTER M;Lu;0;L;;;;;N;;;;006D; 004E;LATIN CAPITAL LETTER N;Lu;0;L;;;;;N;;;;006E; 004F;LATIN CAPITAL LETTER O;Lu;0;L;;;;;N;;;;006F; 0050;LATIN CAPITAL LETTER P;Lu;0;L;;;;;N;;;;0070; 0051;LATIN CAPITAL LETTER Q;Lu;0;L;;;;;N;;;;0071; 0052;LATIN CAPITAL LETTER R;Lu;0;L;;;;;N;;;;0072; 0053;LATIN CAPITAL LETTER S;Lu;0;L;;;;;N;;;;0073; 0054;LATIN CAPITAL LETTER T;Lu;0;L;;;;;N;;;;0074; 0055;LATIN CAPITAL LETTER U;Lu;0;L;;;;;N;;;;0075; 0056;LATIN CAPITAL LETTER V;Lu;0;L;;;;;N;;;;0076; 0057;LATIN CAPITAL LETTER W;Lu;0;L;;;;;N;;;;0077; 0058;LATIN CAPITAL LETTER X;Lu;0;L;;;;;N;;;;0078; 0059;LATIN CAPITAL LETTER Y;Lu;0;L;;;;;N;;;;0079; 005A;LATIN CAPITAL LETTER Z;Lu;0;L;;;;;N;;;;007A; 005B;LEFT SQUARE BRACKET;Ps;0;ON;;;;;Y;OPENING SQUARE BRACKET;;;; 005C;REVERSE SOLIDUS;Po;0;ON;;;;;N;BACKSLASH;;;; 005D;RIGHT SQUARE BRACKET;Pe;0;ON;;;;;Y;CLOSING SQUARE BRACKET;;;; 005E;CIRCUMFLEX ACCENT;Sk;0;ON;;;;;N;SPACING CIRCUMFLEX;;;; 005F;LOW LINE;Pc;0;ON;;;;;N;SPACING UNDERSCORE;;;; 0060;GRAVE ACCENT;Sk;0;ON;;;;;N;SPACING GRAVE;;;; 0061;LATIN SMALL LETTER A;Ll;0;L;;;;;N;;;0041;;0041 0062;LATIN SMALL LETTER B;Ll;0;L;;;;;N;;;0042;;0042 0063;LATIN SMALL LETTER C;Ll;0;L;;;;;N;;;0043;;0043 0064;LATIN SMALL LETTER D;Ll;0;L;;;;;N;;;0044;;0044 0065;LATIN SMALL LETTER E;Ll;0;L;;;;;N;;;0045;;0045 0066;LATIN SMALL LETTER F;Ll;0;L;;;;;N;;;0046;;0046 0067;LATIN SMALL LETTER G;Ll;0;L;;;;;N;;;0047;;0047 0068;LATIN SMALL LETTER H;Ll;0;L;;;;;N;;;0048;;0048 0069;LATIN SMALL LETTER I;Ll;0;L;;;;;N;;;0049;;0049 006A;LATIN SMALL LETTER J;Ll;0;L;;;;;N;;;004A;;004A 006B;LATIN SMALL LETTER K;Ll;0;L;;;;;N;;;004B;;004B 006C;LATIN SMALL LETTER L;Ll;0;L;;;;;N;;;004C;;004C 006D;LATIN SMALL LETTER M;Ll;0;L;;;;;N;;;004D;;004D 006E;LATIN SMALL LETTER N;Ll;0;L;;;;;N;;;004E;;004E 006F;LATIN SMALL LETTER O;Ll;0;L;;;;;N;;;004F;;004F 0070;LATIN SMALL LETTER P;Ll;0;L;;;;;N;;;0050;;0050 0071;LATIN SMALL LETTER Q;Ll;0;L;;;;;N;;;0051;;0051 0072;LATIN SMALL LETTER R;Ll;0;L;;;;;N;;;0052;;0052 0073;LATIN SMALL LETTER S;Ll;0;L;;;;;N;;;0053;;0053 0074;LATIN SMALL LETTER T;Ll;0;L;;;;;N;;;0054;;0054 0075;LATIN SMALL LETTER U;Ll;0;L;;;;;N;;;0055;;0055 0076;LATIN SMALL LETTER V;Ll;0;L;;;;;N;;;0056;;0056 0077;LATIN SMALL LETTER W;Ll;0;L;;;;;N;;;0057;;0057 0078;LATIN SMALL LETTER X;Ll;0;L;;;;;N;;;0058;;0058 0079;LATIN SMALL LETTER Y;Ll;0;L;;;;;N;;;0059;;0059 007A;LATIN SMALL LETTER Z;Ll;0;L;;;;;N;;;005A;;005A 007B;LEFT CURLY BRACKET;Ps;0;ON;;;;;Y;OPENING CURLY BRACKET;;;; 007C;VERTICAL LINE;Sm;0;ON;;;;;N;VERTICAL BAR;;;; 007D;RIGHT CURLY BRACKET;Pe;0;ON;;;;;Y;CLOSING CURLY BRACKET;;;; 007E;TILDE;Sm;0;ON;;;;;N;;;;; 007F;<control>;Cc;0;BN;;;;;N;DELETE;;;; 0080;<control>;Cc;0;BN;;;;;N;;;;; 0081;<control>;Cc;0;BN;;;;;N;;;;; 0082;<control>;Cc;0;BN;;;;;N;BREAK PERMITTED HERE;;;; 0083;<control>;Cc;0;BN;;;;;N;NO BREAK HERE;;;; 0084;<control>;Cc;0;BN;;;;;N;;;;; 0085;<control>;Cc;0;B;;;;;N;NEXT LINE (NEL);;;; 0086;<control>;Cc;0;BN;;;;;N;START OF SELECTED AREA;;;; 0087;<control>;Cc;0;BN;;;;;N;END OF SELECTED AREA;;;; 0088;<control>;Cc;0;BN;;;;;N;CHARACTER TABULATION SET;;;; 0089;<control>;Cc;0;BN;;;;;N;CHARACTER TABULATION WITH JUSTIFICATION;;;; 008A;<control>;Cc;0;BN;;;;;N;LINE TABULATION SET;;;; 008B;<control>;Cc;0;BN;;;;;N;PARTIAL LINE FORWARD;;;; 008C;<control>;Cc;0;BN;;;;;N;PARTIAL LINE BACKWARD;;;; 008D;<control>;Cc;0;BN;;;;;N;REVERSE LINE FEED;;;; 008E;<control>;Cc;0;BN;;;;;N;SINGLE SHIFT TWO;;;; 008F;<control>;Cc;0;BN;;;;;N;SINGLE SHIFT THREE;;;; 0090;<control>;Cc;0;BN;;;;;N;DEVICE CONTROL STRING;;;; 0091;<control>;Cc;0;BN;;;;;N;PRIVATE USE ONE;;;; 0092;<control>;Cc;0;BN;;;;;N;PRIVATE USE TWO;;;; 0093;<control>;Cc;0;BN;;;;;N;SET TRANSMIT STATE;;;; 0094;<control>;Cc;0;BN;;;;;N;CANCEL CHARACTER;;;; 0095;<control>;Cc;0;BN;;;;;N;MESSAGE WAITING;;;; 0096;<control>;Cc;0;BN;;;;;N;START OF GUARDED AREA;;;; 0097;<control>;Cc;0;BN;;;;;N;END OF GUARDED AREA;;;; 0098;<control>;Cc;0;BN;;;;;N;START OF STRING;;;; 0099;<control>;Cc;0;BN;;;;;N;;;;; 009A;<control>;Cc;0;BN;;;;;N;SINGLE CHARACTER INTRODUCER;;;; 009B;<control>;Cc;0;BN;;;;;N;CONTROL SEQUENCE INTRODUCER;;;; 009C;<control>;Cc;0;BN;;;;;N;STRING TERMINATOR;;;; 009D;<control>;Cc;0;BN;;;;;N;OPERATING SYSTEM COMMAND;;;; 009E;<control>;Cc;0;BN;;;;;N;PRIVACY MESSAGE;;;; 009F;<control>;Cc;0;BN;;;;;N;APPLICATION PROGRAM COMMAND;;;; 00A0;NO-BREAK SPACE;Zs;0;CS;<noBreak> 0020;;;;N;NON-BREAKING SPACE;;;; 00A1;INVERTED EXCLAMATION MARK;Po;0;ON;;;;;N;;;;; 00A2;CENT SIGN;Sc;0;ET;;;;;N;;;;; 00A3;POUND SIGN;Sc;0;ET;;;;;N;;;;; 00A4;CURRENCY SIGN;Sc;0;ET;;;;;N;;;;; 00A5;YEN SIGN;Sc;0;ET;;;;;N;;;;; 00A6;BROKEN BAR;So;0;ON;;;;;N;BROKEN VERTICAL BAR;;;; 00A7;SECTION SIGN;Po;0;ON;;;;;N;;;;; 00A8;DIAERESIS;Sk;0;ON;<compat> 0020 0308;;;;N;SPACING DIAERESIS;;;; 00A9;COPYRIGHT SIGN;So;0;ON;;;;;N;;;;; 00AA;FEMININE ORDINAL INDICATOR;Lo;0;L;<super> 0061;;;;N;;;;; 00AB;LEFT-POINTING DOUBLE ANGLE QUOTATION MARK;Pi;0;ON;;;;;Y;LEFT POINTING GUILLEMET;;;; 00AC;NOT SIGN;Sm;0;ON;;;;;N;;;;; 00AD;SOFT HYPHEN;Cf;0;BN;;;;;N;;;;; 00AE;REGISTERED SIGN;So;0;ON;;;;;N;REGISTERED TRADE MARK SIGN;;;; 00AF;MACRON;Sk;0;ON;<compat> 0020 0304;;;;N;SPACING MACRON;;;; 00B0;DEGREE SIGN;So;0;ET;;;;;N;;;;; 00B1;PLUS-MINUS SIGN;Sm;0;ET;;;;;N;PLUS-OR-MINUS SIGN;;;; 00B2;SUPERSCRIPT TWO;No;0;EN;<super> 0032;;2;2;N;SUPERSCRIPT DIGIT TWO;;;; 00B3;SUPERSCRIPT THREE;No;0;EN;<super> 0033;;3;3;N;SUPERSCRIPT DIGIT THREE;;;; 00B4;ACUTE ACCENT;Sk;0;ON;<compat> 0020 0301;;;;N;SPACING ACUTE;;;; 00B5;MICRO SIGN;Ll;0;L;<compat> 03BC;;;;N;;;039C;;039C 00B6;PILCROW SIGN;Po;0;ON;;;;;N;PARAGRAPH SIGN;;;; 00B7;MIDDLE DOT;Po;0;ON;;;;;N;;;;; 00B8;CEDILLA;Sk;0;ON;<compat> 0020 0327;;;;N;SPACING CEDILLA;;;; 00B9;SUPERSCRIPT ONE;No;0;EN;<super> 0031;;1;1;N;SUPERSCRIPT DIGIT ONE;;;; 00BA;MASCULINE ORDINAL INDICATOR;Lo;0;L;<super> 006F;;;;N;;;;; 00BB;RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK;Pf;0;ON;;;;;Y;RIGHT POINTING GUILLEMET;;;; 00BC;VULGAR FRACTION ONE QUARTER;No;0;ON;<fraction> 0031 2044 0034;;;1/4;N;FRACTION ONE QUARTER;;;; 00BD;VULGAR FRACTION ONE HALF;No;0;ON;<fraction> 0031 2044 0032;;;1/2;N;FRACTION ONE HALF;;;; 00BE;VULGAR FRACTION THREE QUARTERS;No;0;ON;<fraction> 0033 2044 0034;;;3/4;N;FRACTION THREE QUARTERS;;;; 00BF;INVERTED QUESTION MARK;Po;0;ON;;;;;N;;;;; 00C0;LATIN CAPITAL LETTER A WITH GRAVE;Lu;0;L;0041 0300;;;;N;LATIN CAPITAL LETTER A GRAVE;;;00E0; 00C1;LATIN CAPITAL LETTER A WITH ACUTE;Lu;0;L;0041 0301;;;;N;LATIN CAPITAL LETTER A ACUTE;;;00E1; 00C2;LATIN CAPITAL LETTER A WITH CIRCUMFLEX;Lu;0;L;0041 0302;;;;N;LATIN CAPITAL LETTER A CIRCUMFLEX;;;00E2; 00C3;LATIN CAPITAL LETTER A WITH TILDE;Lu;0;L;0041 0303;;;;N;LATIN CAPITAL LETTER A TILDE;;;00E3; 00C4;LATIN CAPITAL LETTER A WITH DIAERESIS;Lu;0;L;0041 0308;;;;N;LATIN CAPITAL LETTER A DIAERESIS;;;00E4; 00C5;LATIN CAPITAL LETTER A WITH RING ABOVE;Lu;0;L;0041 030A;;;;N;LATIN CAPITAL LETTER A RING;;;00E5; 00C6;LATIN CAPITAL LETTER AE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER A E;;;00E6; 00C7;LATIN CAPITAL LETTER C WITH CEDILLA;Lu;0;L;0043 0327;;;;N;LATIN CAPITAL LETTER C CEDILLA;;;00E7; 00C8;LATIN CAPITAL LETTER E WITH GRAVE;Lu;0;L;0045 0300;;;;N;LATIN CAPITAL LETTER E GRAVE;;;00E8; 00C9;LATIN CAPITAL LETTER E WITH ACUTE;Lu;0;L;0045 0301;;;;N;LATIN CAPITAL LETTER E ACUTE;;;00E9; 00CA;LATIN CAPITAL LETTER E WITH CIRCUMFLEX;Lu;0;L;0045 0302;;;;N;LATIN CAPITAL LETTER E CIRCUMFLEX;;;00EA; 00CB;LATIN CAPITAL LETTER E WITH DIAERESIS;Lu;0;L;0045 0308;;;;N;LATIN CAPITAL LETTER E DIAERESIS;;;00EB; 00CC;LATIN CAPITAL LETTER I WITH GRAVE;Lu;0;L;0049 0300;;;;N;LATIN CAPITAL LETTER I GRAVE;;;00EC; 00CD;LATIN CAPITAL LETTER I WITH ACUTE;Lu;0;L;0049 0301;;;;N;LATIN CAPITAL LETTER I ACUTE;;;00ED; 00CE;LATIN CAPITAL LETTER I WITH CIRCUMFLEX;Lu;0;L;0049 0302;;;;N;LATIN CAPITAL LETTER I CIRCUMFLEX;;;00EE; 00CF;LATIN CAPITAL LETTER I WITH DIAERESIS;Lu;0;L;0049 0308;;;;N;LATIN CAPITAL LETTER I DIAERESIS;;;00EF; 00D0;LATIN CAPITAL LETTER ETH;Lu;0;L;;;;;N;;;;00F0; 00D1;LATIN CAPITAL LETTER N WITH TILDE;Lu;0;L;004E 0303;;;;N;LATIN CAPITAL LETTER N TILDE;;;00F1; 00D2;LATIN CAPITAL LETTER O WITH GRAVE;Lu;0;L;004F 0300;;;;N;LATIN CAPITAL LETTER O GRAVE;;;00F2; 00D3;LATIN CAPITAL LETTER O WITH ACUTE;Lu;0;L;004F 0301;;;;N;LATIN CAPITAL LETTER O ACUTE;;;00F3; 00D4;LATIN CAPITAL LETTER O WITH CIRCUMFLEX;Lu;0;L;004F 0302;;;;N;LATIN CAPITAL LETTER O CIRCUMFLEX;;;00F4; 00D5;LATIN CAPITAL LETTER O WITH TILDE;Lu;0;L;004F 0303;;;;N;LATIN CAPITAL LETTER O TILDE;;;00F5; 00D6;LATIN CAPITAL LETTER O WITH DIAERESIS;Lu;0;L;004F 0308;;;;N;LATIN CAPITAL LETTER O DIAERESIS;;;00F6; 00D7;MULTIPLICATION SIGN;Sm;0;ON;;;;;N;;;;; 00D8;LATIN CAPITAL LETTER O WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER O SLASH;;;00F8; 00D9;LATIN CAPITAL LETTER U WITH GRAVE;Lu;0;L;0055 0300;;;;N;LATIN CAPITAL LETTER U GRAVE;;;00F9; 00DA;LATIN CAPITAL LETTER U WITH ACUTE;Lu;0;L;0055 0301;;;;N;LATIN CAPITAL LETTER U ACUTE;;;00FA; 00DB;LATIN CAPITAL LETTER U WITH CIRCUMFLEX;Lu;0;L;0055 0302;;;;N;LATIN CAPITAL LETTER U CIRCUMFLEX;;;00FB; 00DC;LATIN CAPITAL LETTER U WITH DIAERESIS;Lu;0;L;0055 0308;;;;N;LATIN CAPITAL LETTER U DIAERESIS;;;00FC; 00DD;LATIN CAPITAL LETTER Y WITH ACUTE;Lu;0;L;0059 0301;;;;N;LATIN CAPITAL LETTER Y ACUTE;;;00FD; 00DE;LATIN CAPITAL LETTER THORN;Lu;0;L;;;;;N;;;;00FE; 00DF;LATIN SMALL LETTER SHARP S;Ll;0;L;;;;;N;;;;; 00E0;LATIN SMALL LETTER A WITH GRAVE;Ll;0;L;0061 0300;;;;N;LATIN SMALL LETTER A GRAVE;;00C0;;00C0 00E1;LATIN SMALL LETTER A WITH ACUTE;Ll;0;L;0061 0301;;;;N;LATIN SMALL LETTER A ACUTE;;00C1;;00C1 00E2;LATIN SMALL LETTER A WITH CIRCUMFLEX;Ll;0;L;0061 0302;;;;N;LATIN SMALL LETTER A CIRCUMFLEX;;00C2;;00C2 00E3;LATIN SMALL LETTER A WITH TILDE;Ll;0;L;0061 0303;;;;N;LATIN SMALL LETTER A TILDE;;00C3;;00C3 00E4;LATIN SMALL LETTER A WITH DIAERESIS;Ll;0;L;0061 0308;;;;N;LATIN SMALL LETTER A DIAERESIS;;00C4;;00C4 00E5;LATIN SMALL LETTER A WITH RING ABOVE;Ll;0;L;0061 030A;;;;N;LATIN SMALL LETTER A RING;;00C5;;00C5 00E6;LATIN SMALL LETTER AE;Ll;0;L;;;;;N;LATIN SMALL LETTER A E;;00C6;;00C6 00E7;LATIN SMALL LETTER C WITH CEDILLA;Ll;0;L;0063 0327;;;;N;LATIN SMALL LETTER C CEDILLA;;00C7;;00C7 00E8;LATIN SMALL LETTER E WITH GRAVE;Ll;0;L;0065 0300;;;;N;LATIN SMALL LETTER E GRAVE;;00C8;;00C8 00E9;LATIN SMALL LETTER E WITH ACUTE;Ll;0;L;0065 0301;;;;N;LATIN SMALL LETTER E ACUTE;;00C9;;00C9 00EA;LATIN SMALL LETTER E WITH CIRCUMFLEX;Ll;0;L;0065 0302;;;;N;LATIN SMALL LETTER E CIRCUMFLEX;;00CA;;00CA 00EB;LATIN SMALL LETTER E WITH DIAERESIS;Ll;0;L;0065 0308;;;;N;LATIN SMALL LETTER E DIAERESIS;;00CB;;00CB 00EC;LATIN SMALL LETTER I WITH GRAVE;Ll;0;L;0069 0300;;;;N;LATIN SMALL LETTER I GRAVE;;00CC;;00CC 00ED;LATIN SMALL LETTER I WITH ACUTE;Ll;0;L;0069 0301;;;;N;LATIN SMALL LETTER I ACUTE;;00CD;;00CD 00EE;LATIN SMALL LETTER I WITH CIRCUMFLEX;Ll;0;L;0069 0302;;;;N;LATIN SMALL LETTER I CIRCUMFLEX;;00CE;;00CE 00EF;LATIN SMALL LETTER I WITH DIAERESIS;Ll;0;L;0069 0308;;;;N;LATIN SMALL LETTER I DIAERESIS;;00CF;;00CF 00F0;LATIN SMALL LETTER ETH;Ll;0;L;;;;;N;;;00D0;;00D0 00F1;LATIN SMALL LETTER N WITH TILDE;Ll;0;L;006E 0303;;;;N;LATIN SMALL LETTER N TILDE;;00D1;;00D1 00F2;LATIN SMALL LETTER O WITH GRAVE;Ll;0;L;006F 0300;;;;N;LATIN SMALL LETTER O GRAVE;;00D2;;00D2 00F3;LATIN SMALL LETTER O WITH ACUTE;Ll;0;L;006F 0301;;;;N;LATIN SMALL LETTER O ACUTE;;00D3;;00D3 00F4;LATIN SMALL LETTER O WITH CIRCUMFLEX;Ll;0;L;006F 0302;;;;N;LATIN SMALL LETTER O CIRCUMFLEX;;00D4;;00D4 00F5;LATIN SMALL LETTER O WITH TILDE;Ll;0;L;006F 0303;;;;N;LATIN SMALL LETTER O TILDE;;00D5;;00D5 00F6;LATIN SMALL LETTER O WITH DIAERESIS;Ll;0;L;006F 0308;;;;N;LATIN SMALL LETTER O DIAERESIS;;00D6;;00D6 00F7;DIVISION SIGN;Sm;0;ON;;;;;N;;;;; 00F8;LATIN SMALL LETTER O WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER O SLASH;;00D8;;00D8 00F9;LATIN SMALL LETTER U WITH GRAVE;Ll;0;L;0075 0300;;;;N;LATIN SMALL LETTER U GRAVE;;00D9;;00D9 00FA;LATIN SMALL LETTER U WITH ACUTE;Ll;0;L;0075 0301;;;;N;LATIN SMALL LETTER U ACUTE;;00DA;;00DA 00FB;LATIN SMALL LETTER U WITH CIRCUMFLEX;Ll;0;L;0075 0302;;;;N;LATIN SMALL LETTER U CIRCUMFLEX;;00DB;;00DB 00FC;LATIN SMALL LETTER U WITH DIAERESIS;Ll;0;L;0075 0308;;;;N;LATIN SMALL LETTER U DIAERESIS;;00DC;;00DC 00FD;LATIN SMALL LETTER Y WITH ACUTE;Ll;0;L;0079 0301;;;;N;LATIN SMALL LETTER Y ACUTE;;00DD;;00DD 00FE;LATIN SMALL LETTER THORN;Ll;0;L;;;;;N;;;00DE;;00DE 00FF;LATIN SMALL LETTER Y WITH DIAERESIS;Ll;0;L;0079 0308;;;;N;LATIN SMALL LETTER Y DIAERESIS;;0178;;0178 0100;LATIN CAPITAL LETTER A WITH MACRON;Lu;0;L;0041 0304;;;;N;LATIN CAPITAL LETTER A MACRON;;;0101; 0101;LATIN SMALL LETTER A WITH MACRON;Ll;0;L;0061 0304;;;;N;LATIN SMALL LETTER A MACRON;;0100;;0100 0102;LATIN CAPITAL LETTER A WITH BREVE;Lu;0;L;0041 0306;;;;N;LATIN CAPITAL LETTER A BREVE;;;0103; 0103;LATIN SMALL LETTER A WITH BREVE;Ll;0;L;0061 0306;;;;N;LATIN SMALL LETTER A BREVE;;0102;;0102 0104;LATIN CAPITAL LETTER A WITH OGONEK;Lu;0;L;0041 0328;;;;N;LATIN CAPITAL LETTER A OGONEK;;;0105; 0105;LATIN SMALL LETTER A WITH OGONEK;Ll;0;L;0061 0328;;;;N;LATIN SMALL LETTER A OGONEK;;0104;;0104 0106;LATIN CAPITAL LETTER C WITH ACUTE;Lu;0;L;0043 0301;;;;N;LATIN CAPITAL LETTER C ACUTE;;;0107; 0107;LATIN SMALL LETTER C WITH ACUTE;Ll;0;L;0063 0301;;;;N;LATIN SMALL LETTER C ACUTE;;0106;;0106 0108;LATIN CAPITAL LETTER C WITH CIRCUMFLEX;Lu;0;L;0043 0302;;;;N;LATIN CAPITAL LETTER C CIRCUMFLEX;;;0109; 0109;LATIN SMALL LETTER C WITH CIRCUMFLEX;Ll;0;L;0063 0302;;;;N;LATIN SMALL LETTER C CIRCUMFLEX;;0108;;0108 010A;LATIN CAPITAL LETTER C WITH DOT ABOVE;Lu;0;L;0043 0307;;;;N;LATIN CAPITAL LETTER C DOT;;;010B; 010B;LATIN SMALL LETTER C WITH DOT ABOVE;Ll;0;L;0063 0307;;;;N;LATIN SMALL LETTER C DOT;;010A;;010A 010C;LATIN CAPITAL LETTER C WITH CARON;Lu;0;L;0043 030C;;;;N;LATIN CAPITAL LETTER C HACEK;;;010D; 010D;LATIN SMALL LETTER C WITH CARON;Ll;0;L;0063 030C;;;;N;LATIN SMALL LETTER C HACEK;;010C;;010C 010E;LATIN CAPITAL LETTER D WITH CARON;Lu;0;L;0044 030C;;;;N;LATIN CAPITAL LETTER D HACEK;;;010F; 010F;LATIN SMALL LETTER D WITH CARON;Ll;0;L;0064 030C;;;;N;LATIN SMALL LETTER D HACEK;;010E;;010E 0110;LATIN CAPITAL LETTER D WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER D BAR;;;0111; 0111;LATIN SMALL LETTER D WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER D BAR;;0110;;0110 0112;LATIN CAPITAL LETTER E WITH MACRON;Lu;0;L;0045 0304;;;;N;LATIN CAPITAL LETTER E MACRON;;;0113; 0113;LATIN SMALL LETTER E WITH MACRON;Ll;0;L;0065 0304;;;;N;LATIN SMALL LETTER E MACRON;;0112;;0112 0114;LATIN CAPITAL LETTER E WITH BREVE;Lu;0;L;0045 0306;;;;N;LATIN CAPITAL LETTER E BREVE;;;0115; 0115;LATIN SMALL LETTER E WITH BREVE;Ll;0;L;0065 0306;;;;N;LATIN SMALL LETTER E BREVE;;0114;;0114 0116;LATIN CAPITAL LETTER E WITH DOT ABOVE;Lu;0;L;0045 0307;;;;N;LATIN CAPITAL LETTER E DOT;;;0117; 0117;LATIN SMALL LETTER E WITH DOT ABOVE;Ll;0;L;0065 0307;;;;N;LATIN SMALL LETTER E DOT;;0116;;0116 0118;LATIN CAPITAL LETTER E WITH OGONEK;Lu;0;L;0045 0328;;;;N;LATIN CAPITAL LETTER E OGONEK;;;0119; 0119;LATIN SMALL LETTER E WITH OGONEK;Ll;0;L;0065 0328;;;;N;LATIN SMALL LETTER E OGONEK;;0118;;0118 011A;LATIN CAPITAL LETTER E WITH CARON;Lu;0;L;0045 030C;;;;N;LATIN CAPITAL LETTER E HACEK;;;011B; 011B;LATIN SMALL LETTER E WITH CARON;Ll;0;L;0065 030C;;;;N;LATIN SMALL LETTER E HACEK;;011A;;011A 011C;LATIN CAPITAL LETTER G WITH CIRCUMFLEX;Lu;0;L;0047 0302;;;;N;LATIN CAPITAL LETTER G CIRCUMFLEX;;;011D; 011D;LATIN SMALL LETTER G WITH CIRCUMFLEX;Ll;0;L;0067 0302;;;;N;LATIN SMALL LETTER G CIRCUMFLEX;;011C;;011C 011E;LATIN CAPITAL LETTER G WITH BREVE;Lu;0;L;0047 0306;;;;N;LATIN CAPITAL LETTER G BREVE;;;011F; 011F;LATIN SMALL LETTER G WITH BREVE;Ll;0;L;0067 0306;;;;N;LATIN SMALL LETTER G BREVE;;011E;;011E 0120;LATIN CAPITAL LETTER G WITH DOT ABOVE;Lu;0;L;0047 0307;;;;N;LATIN CAPITAL LETTER G DOT;;;0121; 0121;LATIN SMALL LETTER G WITH DOT ABOVE;Ll;0;L;0067 0307;;;;N;LATIN SMALL LETTER G DOT;;0120;;0120 0122;LATIN CAPITAL LETTER G WITH CEDILLA;Lu;0;L;0047 0327;;;;N;LATIN CAPITAL LETTER G CEDILLA;;;0123; 0123;LATIN SMALL LETTER G WITH CEDILLA;Ll;0;L;0067 0327;;;;N;LATIN SMALL LETTER G CEDILLA;;0122;;0122 0124;LATIN CAPITAL LETTER H WITH CIRCUMFLEX;Lu;0;L;0048 0302;;;;N;LATIN CAPITAL LETTER H CIRCUMFLEX;;;0125; 0125;LATIN SMALL LETTER H WITH CIRCUMFLEX;Ll;0;L;0068 0302;;;;N;LATIN SMALL LETTER H CIRCUMFLEX;;0124;;0124 0126;LATIN CAPITAL LETTER H WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER H BAR;;;0127; 0127;LATIN SMALL LETTER H WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER H BAR;;0126;;0126 0128;LATIN CAPITAL LETTER I WITH TILDE;Lu;0;L;0049 0303;;;;N;LATIN CAPITAL LETTER I TILDE;;;0129; 0129;LATIN SMALL LETTER I WITH TILDE;Ll;0;L;0069 0303;;;;N;LATIN SMALL LETTER I TILDE;;0128;;0128 012A;LATIN CAPITAL LETTER I WITH MACRON;Lu;0;L;0049 0304;;;;N;LATIN CAPITAL LETTER I MACRON;;;012B; 012B;LATIN SMALL LETTER I WITH MACRON;Ll;0;L;0069 0304;;;;N;LATIN SMALL LETTER I MACRON;;012A;;012A 012C;LATIN CAPITAL LETTER I WITH BREVE;Lu;0;L;0049 0306;;;;N;LATIN CAPITAL LETTER I BREVE;;;012D; 012D;LATIN SMALL LETTER I WITH BREVE;Ll;0;L;0069 0306;;;;N;LATIN SMALL LETTER I BREVE;;012C;;012C 012E;LATIN CAPITAL LETTER I WITH OGONEK;Lu;0;L;0049 0328;;;;N;LATIN CAPITAL LETTER I OGONEK;;;012F; 012F;LATIN SMALL LETTER I WITH OGONEK;Ll;0;L;0069 0328;;;;N;LATIN SMALL LETTER I OGONEK;;012E;;012E 0130;LATIN CAPITAL LETTER I WITH DOT ABOVE;Lu;0;L;0049 0307;;;;N;LATIN CAPITAL LETTER I DOT;;;0069; 0131;LATIN SMALL LETTER DOTLESS I;Ll;0;L;;;;;N;;;0049;;0049 0132;LATIN CAPITAL LIGATURE IJ;Lu;0;L;<compat> 0049 004A;;;;N;LATIN CAPITAL LETTER I J;;;0133; 0133;LATIN SMALL LIGATURE IJ;Ll;0;L;<compat> 0069 006A;;;;N;LATIN SMALL LETTER I J;;0132;;0132 0134;LATIN CAPITAL LETTER J WITH CIRCUMFLEX;Lu;0;L;004A 0302;;;;N;LATIN CAPITAL LETTER J CIRCUMFLEX;;;0135; 0135;LATIN SMALL LETTER J WITH CIRCUMFLEX;Ll;0;L;006A 0302;;;;N;LATIN SMALL LETTER J CIRCUMFLEX;;0134;;0134 0136;LATIN CAPITAL LETTER K WITH CEDILLA;Lu;0;L;004B 0327;;;;N;LATIN CAPITAL LETTER K CEDILLA;;;0137; 0137;LATIN SMALL LETTER K WITH CEDILLA;Ll;0;L;006B 0327;;;;N;LATIN SMALL LETTER K CEDILLA;;0136;;0136 0138;LATIN SMALL LETTER KRA;Ll;0;L;;;;;N;;;;; 0139;LATIN CAPITAL LETTER L WITH ACUTE;Lu;0;L;004C 0301;;;;N;LATIN CAPITAL LETTER L ACUTE;;;013A; 013A;LATIN SMALL LETTER L WITH ACUTE;Ll;0;L;006C 0301;;;;N;LATIN SMALL LETTER L ACUTE;;0139;;0139 013B;LATIN CAPITAL LETTER L WITH CEDILLA;Lu;0;L;004C 0327;;;;N;LATIN CAPITAL LETTER L CEDILLA;;;013C; 013C;LATIN SMALL LETTER L WITH CEDILLA;Ll;0;L;006C 0327;;;;N;LATIN SMALL LETTER L CEDILLA;;013B;;013B 013D;LATIN CAPITAL LETTER L WITH CARON;Lu;0;L;004C 030C;;;;N;LATIN CAPITAL LETTER L HACEK;;;013E; 013E;LATIN SMALL LETTER L WITH CARON;Ll;0;L;006C 030C;;;;N;LATIN SMALL LETTER L HACEK;;013D;;013D 013F;LATIN CAPITAL LETTER L WITH MIDDLE DOT;Lu;0;L;<compat> 004C 00B7;;;;N;;;;0140; 0140;LATIN SMALL LETTER L WITH MIDDLE DOT;Ll;0;L;<compat> 006C 00B7;;;;N;;;013F;;013F 0141;LATIN CAPITAL LETTER L WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER L SLASH;;;0142; 0142;LATIN SMALL LETTER L WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER L SLASH;;0141;;0141 0143;LATIN CAPITAL LETTER N WITH ACUTE;Lu;0;L;004E 0301;;;;N;LATIN CAPITAL LETTER N ACUTE;;;0144; 0144;LATIN SMALL LETTER N WITH ACUTE;Ll;0;L;006E 0301;;;;N;LATIN SMALL LETTER N ACUTE;;0143;;0143 0145;LATIN CAPITAL LETTER N WITH CEDILLA;Lu;0;L;004E 0327;;;;N;LATIN CAPITAL LETTER N CEDILLA;;;0146; 0146;LATIN SMALL LETTER N WITH CEDILLA;Ll;0;L;006E 0327;;;;N;LATIN SMALL LETTER N CEDILLA;;0145;;0145 0147;LATIN CAPITAL LETTER N WITH CARON;Lu;0;L;004E 030C;;;;N;LATIN CAPITAL LETTER N HACEK;;;0148; 0148;LATIN SMALL LETTER N WITH CARON;Ll;0;L;006E 030C;;;;N;LATIN SMALL LETTER N HACEK;;0147;;0147 0149;LATIN SMALL LETTER N PRECEDED BY APOSTROPHE;Ll;0;L;<compat> 02BC 006E;;;;N;LATIN SMALL LETTER APOSTROPHE N;;;; 014A;LATIN CAPITAL LETTER ENG;Lu;0;L;;;;;N;;;;014B; 014B;LATIN SMALL LETTER ENG;Ll;0;L;;;;;N;;;014A;;014A 014C;LATIN CAPITAL LETTER O WITH MACRON;Lu;0;L;004F 0304;;;;N;LATIN CAPITAL LETTER O MACRON;;;014D; 014D;LATIN SMALL LETTER O WITH MACRON;Ll;0;L;006F 0304;;;;N;LATIN SMALL LETTER O MACRON;;014C;;014C 014E;LATIN CAPITAL LETTER O WITH BREVE;Lu;0;L;004F 0306;;;;N;LATIN CAPITAL LETTER O BREVE;;;014F; 014F;LATIN SMALL LETTER O WITH BREVE;Ll;0;L;006F 0306;;;;N;LATIN SMALL LETTER O BREVE;;014E;;014E 0150;LATIN CAPITAL LETTER O WITH DOUBLE ACUTE;Lu;0;L;004F 030B;;;;N;LATIN CAPITAL LETTER O DOUBLE ACUTE;;;0151; 0151;LATIN SMALL LETTER O WITH DOUBLE ACUTE;Ll;0;L;006F 030B;;;;N;LATIN SMALL LETTER O DOUBLE ACUTE;;0150;;0150 0152;LATIN CAPITAL LIGATURE OE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER O E;;;0153; 0153;LATIN SMALL LIGATURE OE;Ll;0;L;;;;;N;LATIN SMALL LETTER O E;;0152;;0152 0154;LATIN CAPITAL LETTER R WITH ACUTE;Lu;0;L;0052 0301;;;;N;LATIN CAPITAL LETTER R ACUTE;;;0155; 0155;LATIN SMALL LETTER R WITH ACUTE;Ll;0;L;0072 0301;;;;N;LATIN SMALL LETTER R ACUTE;;0154;;0154 0156;LATIN CAPITAL LETTER R WITH CEDILLA;Lu;0;L;0052 0327;;;;N;LATIN CAPITAL LETTER R CEDILLA;;;0157; 0157;LATIN SMALL LETTER R WITH CEDILLA;Ll;0;L;0072 0327;;;;N;LATIN SMALL LETTER R CEDILLA;;0156;;0156 0158;LATIN CAPITAL LETTER R WITH CARON;Lu;0;L;0052 030C;;;;N;LATIN CAPITAL LETTER R HACEK;;;0159; 0159;LATIN SMALL LETTER R WITH CARON;Ll;0;L;0072 030C;;;;N;LATIN SMALL LETTER R HACEK;;0158;;0158 015A;LATIN CAPITAL LETTER S WITH ACUTE;Lu;0;L;0053 0301;;;;N;LATIN CAPITAL LETTER S ACUTE;;;015B; 015B;LATIN SMALL LETTER S WITH ACUTE;Ll;0;L;0073 0301;;;;N;LATIN SMALL LETTER S ACUTE;;015A;;015A 015C;LATIN CAPITAL LETTER S WITH CIRCUMFLEX;Lu;0;L;0053 0302;;;;N;LATIN CAPITAL LETTER S CIRCUMFLEX;;;015D; 015D;LATIN SMALL LETTER S WITH CIRCUMFLEX;Ll;0;L;0073 0302;;;;N;LATIN SMALL LETTER S CIRCUMFLEX;;015C;;015C 015E;LATIN CAPITAL LETTER S WITH CEDILLA;Lu;0;L;0053 0327;;;;N;LATIN CAPITAL LETTER S CEDILLA;;;015F; 015F;LATIN SMALL LETTER S WITH CEDILLA;Ll;0;L;0073 0327;;;;N;LATIN SMALL LETTER S CEDILLA;;015E;;015E 0160;LATIN CAPITAL LETTER S WITH CARON;Lu;0;L;0053 030C;;;;N;LATIN CAPITAL LETTER S HACEK;;;0161; 0161;LATIN SMALL LETTER S WITH CARON;Ll;0;L;0073 030C;;;;N;LATIN SMALL LETTER S HACEK;;0160;;0160 0162;LATIN CAPITAL LETTER T WITH CEDILLA;Lu;0;L;0054 0327;;;;N;LATIN CAPITAL LETTER T CEDILLA;;;0163; 0163;LATIN SMALL LETTER T WITH CEDILLA;Ll;0;L;0074 0327;;;;N;LATIN SMALL LETTER T CEDILLA;;0162;;0162 0164;LATIN CAPITAL LETTER T WITH CARON;Lu;0;L;0054 030C;;;;N;LATIN CAPITAL LETTER T HACEK;;;0165; 0165;LATIN SMALL LETTER T WITH CARON;Ll;0;L;0074 030C;;;;N;LATIN SMALL LETTER T HACEK;;0164;;0164 0166;LATIN CAPITAL LETTER T WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER T BAR;;;0167; 0167;LATIN SMALL LETTER T WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER T BAR;;0166;;0166 0168;LATIN CAPITAL LETTER U WITH TILDE;Lu;0;L;0055 0303;;;;N;LATIN CAPITAL LETTER U TILDE;;;0169; 0169;LATIN SMALL LETTER U WITH TILDE;Ll;0;L;0075 0303;;;;N;LATIN SMALL LETTER U TILDE;;0168;;0168 016A;LATIN CAPITAL LETTER U WITH MACRON;Lu;0;L;0055 0304;;;;N;LATIN CAPITAL LETTER U MACRON;;;016B; 016B;LATIN SMALL LETTER U WITH MACRON;Ll;0;L;0075 0304;;;;N;LATIN SMALL LETTER U MACRON;;016A;;016A 016C;LATIN CAPITAL LETTER U WITH BREVE;Lu;0;L;0055 0306;;;;N;LATIN CAPITAL LETTER U BREVE;;;016D; 016D;LATIN SMALL LETTER U WITH BREVE;Ll;0;L;0075 0306;;;;N;LATIN SMALL LETTER U BREVE;;016C;;016C 016E;LATIN CAPITAL LETTER U WITH RING ABOVE;Lu;0;L;0055 030A;;;;N;LATIN CAPITAL LETTER U RING;;;016F; 016F;LATIN SMALL LETTER U WITH RING ABOVE;Ll;0;L;0075 030A;;;;N;LATIN SMALL LETTER U RING;;016E;;016E 0170;LATIN CAPITAL LETTER U WITH DOUBLE ACUTE;Lu;0;L;0055 030B;;;;N;LATIN CAPITAL LETTER U DOUBLE ACUTE;;;0171; 0171;LATIN SMALL LETTER U WITH DOUBLE ACUTE;Ll;0;L;0075 030B;;;;N;LATIN SMALL LETTER U DOUBLE ACUTE;;0170;;0170 0172;LATIN CAPITAL LETTER U WITH OGONEK;Lu;0;L;0055 0328;;;;N;LATIN CAPITAL LETTER U OGONEK;;;0173; 0173;LATIN SMALL LETTER U WITH OGONEK;Ll;0;L;0075 0328;;;;N;LATIN SMALL LETTER U OGONEK;;0172;;0172 0174;LATIN CAPITAL LETTER W WITH CIRCUMFLEX;Lu;0;L;0057 0302;;;;N;LATIN CAPITAL LETTER W CIRCUMFLEX;;;0175; 0175;LATIN SMALL LETTER W WITH CIRCUMFLEX;Ll;0;L;0077 0302;;;;N;LATIN SMALL LETTER W CIRCUMFLEX;;0174;;0174 0176;LATIN CAPITAL LETTER Y WITH CIRCUMFLEX;Lu;0;L;0059 0302;;;;N;LATIN CAPITAL LETTER Y CIRCUMFLEX;;;0177; 0177;LATIN SMALL LETTER Y WITH CIRCUMFLEX;Ll;0;L;0079 0302;;;;N;LATIN SMALL LETTER Y CIRCUMFLEX;;0176;;0176 0178;LATIN CAPITAL LETTER Y WITH DIAERESIS;Lu;0;L;0059 0308;;;;N;LATIN CAPITAL LETTER Y DIAERESIS;;;00FF; 0179;LATIN CAPITAL LETTER Z WITH ACUTE;Lu;0;L;005A 0301;;;;N;LATIN CAPITAL LETTER Z ACUTE;;;017A; 017A;LATIN SMALL LETTER Z WITH ACUTE;Ll;0;L;007A 0301;;;;N;LATIN SMALL LETTER Z ACUTE;;0179;;0179 017B;LATIN CAPITAL LETTER Z WITH DOT ABOVE;Lu;0;L;005A 0307;;;;N;LATIN CAPITAL LETTER Z DOT;;;017C; 017C;LATIN SMALL LETTER Z WITH DOT ABOVE;Ll;0;L;007A 0307;;;;N;LATIN SMALL LETTER Z DOT;;017B;;017B 017D;LATIN CAPITAL LETTER Z WITH CARON;Lu;0;L;005A 030C;;;;N;LATIN CAPITAL LETTER Z HACEK;;;017E; 017E;LATIN SMALL LETTER Z WITH CARON;Ll;0;L;007A 030C;;;;N;LATIN SMALL LETTER Z HACEK;;017D;;017D 017F;LATIN SMALL LETTER LONG S;Ll;0;L;<compat> 0073;;;;N;;;0053;;0053 0180;LATIN SMALL LETTER B WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER B BAR;;0243;;0243 0181;LATIN CAPITAL LETTER B WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER B HOOK;;;0253; 0182;LATIN CAPITAL LETTER B WITH TOPBAR;Lu;0;L;;;;;N;LATIN CAPITAL LETTER B TOPBAR;;;0183; 0183;LATIN SMALL LETTER B WITH TOPBAR;Ll;0;L;;;;;N;LATIN SMALL LETTER B TOPBAR;;0182;;0182 0184;LATIN CAPITAL LETTER TONE SIX;Lu;0;L;;;;;N;;;;0185; 0185;LATIN SMALL LETTER TONE SIX;Ll;0;L;;;;;N;;;0184;;0184 0186;LATIN CAPITAL LETTER OPEN O;Lu;0;L;;;;;N;;;;0254; 0187;LATIN CAPITAL LETTER C WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER C HOOK;;;0188; 0188;LATIN SMALL LETTER C WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER C HOOK;;0187;;0187 0189;LATIN CAPITAL LETTER AFRICAN D;Lu;0;L;;;;;N;;;;0256; 018A;LATIN CAPITAL LETTER D WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER D HOOK;;;0257; 018B;LATIN CAPITAL LETTER D WITH TOPBAR;Lu;0;L;;;;;N;LATIN CAPITAL LETTER D TOPBAR;;;018C; 018C;LATIN SMALL LETTER D WITH TOPBAR;Ll;0;L;;;;;N;LATIN SMALL LETTER D TOPBAR;;018B;;018B 018D;LATIN SMALL LETTER TURNED DELTA;Ll;0;L;;;;;N;;;;; 018E;LATIN CAPITAL LETTER REVERSED E;Lu;0;L;;;;;N;LATIN CAPITAL LETTER TURNED E;;;01DD; 018F;LATIN CAPITAL LETTER SCHWA;Lu;0;L;;;;;N;;;;0259; 0190;LATIN CAPITAL LETTER OPEN E;Lu;0;L;;;;;N;LATIN CAPITAL LETTER EPSILON;;;025B; 0191;LATIN CAPITAL LETTER F WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER F HOOK;;;0192; 0192;LATIN SMALL LETTER F WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER SCRIPT F;;0191;;0191 0193;LATIN CAPITAL LETTER G WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER G HOOK;;;0260; 0194;LATIN CAPITAL LETTER GAMMA;Lu;0;L;;;;;N;;;;0263; 0195;LATIN SMALL LETTER HV;Ll;0;L;;;;;N;LATIN SMALL LETTER H V;;01F6;;01F6 0196;LATIN CAPITAL LETTER IOTA;Lu;0;L;;;;;N;;;;0269; 0197;LATIN CAPITAL LETTER I WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER BARRED I;;;0268; 0198;LATIN CAPITAL LETTER K WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER K HOOK;;;0199; 0199;LATIN SMALL LETTER K WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER K HOOK;;0198;;0198 019A;LATIN SMALL LETTER L WITH BAR;Ll;0;L;;;;;N;LATIN SMALL LETTER BARRED L;;023D;;023D 019B;LATIN SMALL LETTER LAMBDA WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER BARRED LAMBDA;;;; 019C;LATIN CAPITAL LETTER TURNED M;Lu;0;L;;;;;N;;;;026F; 019D;LATIN CAPITAL LETTER N WITH LEFT HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER N HOOK;;;0272; 019E;LATIN SMALL LETTER N WITH LONG RIGHT LEG;Ll;0;L;;;;;N;;;0220;;0220 019F;LATIN CAPITAL LETTER O WITH MIDDLE TILDE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER BARRED O;;;0275; 01A0;LATIN CAPITAL LETTER O WITH HORN;Lu;0;L;004F 031B;;;;N;LATIN CAPITAL LETTER O HORN;;;01A1; 01A1;LATIN SMALL LETTER O WITH HORN;Ll;0;L;006F 031B;;;;N;LATIN SMALL LETTER O HORN;;01A0;;01A0 01A2;LATIN CAPITAL LETTER OI;Lu;0;L;;;;;N;LATIN CAPITAL LETTER O I;;;01A3; 01A3;LATIN SMALL LETTER OI;Ll;0;L;;;;;N;LATIN SMALL LETTER O I;;01A2;;01A2 01A4;LATIN CAPITAL LETTER P WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER P HOOK;;;01A5; 01A5;LATIN SMALL LETTER P WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER P HOOK;;01A4;;01A4 01A6;LATIN LETTER YR;Lu;0;L;;;;;N;LATIN LETTER Y R;;;0280; 01A7;LATIN CAPITAL LETTER TONE TWO;Lu;0;L;;;;;N;;;;01A8; 01A8;LATIN SMALL LETTER TONE TWO;Ll;0;L;;;;;N;;;01A7;;01A7 01A9;LATIN CAPITAL LETTER ESH;Lu;0;L;;;;;N;;;;0283; 01AA;LATIN LETTER REVERSED ESH LOOP;Ll;0;L;;;;;N;;;;; 01AB;LATIN SMALL LETTER T WITH PALATAL HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER T PALATAL HOOK;;;; 01AC;LATIN CAPITAL LETTER T WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER T HOOK;;;01AD; 01AD;LATIN SMALL LETTER T WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER T HOOK;;01AC;;01AC 01AE;LATIN CAPITAL LETTER T WITH RETROFLEX HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER T RETROFLEX HOOK;;;0288; 01AF;LATIN CAPITAL LETTER U WITH HORN;Lu;0;L;0055 031B;;;;N;LATIN CAPITAL LETTER U HORN;;;01B0; 01B0;LATIN SMALL LETTER U WITH HORN;Ll;0;L;0075 031B;;;;N;LATIN SMALL LETTER U HORN;;01AF;;01AF 01B1;LATIN CAPITAL LETTER UPSILON;Lu;0;L;;;;;N;;;;028A; 01B2;LATIN CAPITAL LETTER V WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER SCRIPT V;;;028B; 01B3;LATIN CAPITAL LETTER Y WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER Y HOOK;;;01B4; 01B4;LATIN SMALL LETTER Y WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER Y HOOK;;01B3;;01B3 01B5;LATIN CAPITAL LETTER Z WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER Z BAR;;;01B6; 01B6;LATIN SMALL LETTER Z WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER Z BAR;;01B5;;01B5 01B7;LATIN CAPITAL LETTER EZH;Lu;0;L;;;;;N;LATIN CAPITAL LETTER YOGH;;;0292; 01B8;LATIN CAPITAL LETTER EZH REVERSED;Lu;0;L;;;;;N;LATIN CAPITAL LETTER REVERSED YOGH;;;01B9; 01B9;LATIN SMALL LETTER EZH REVERSED;Ll;0;L;;;;;N;LATIN SMALL LETTER REVERSED YOGH;;01B8;;01B8 01BA;LATIN SMALL LETTER EZH WITH TAIL;Ll;0;L;;;;;N;LATIN SMALL LETTER YOGH WITH TAIL;;;; 01BB;LATIN LETTER TWO WITH STROKE;Lo;0;L;;;;;N;LATIN LETTER TWO BAR;;;; 01BC;LATIN CAPITAL LETTER TONE FIVE;Lu;0;L;;;;;N;;;;01BD; 01BD;LATIN SMALL LETTER TONE FIVE;Ll;0;L;;;;;N;;;01BC;;01BC 01BE;LATIN LETTER INVERTED GLOTTAL STOP WITH STROKE;Ll;0;L;;;;;N;LATIN LETTER INVERTED GLOTTAL STOP BAR;;;; 01BF;LATIN LETTER WYNN;Ll;0;L;;;;;N;;;01F7;;01F7 01C0;LATIN LETTER DENTAL CLICK;Lo;0;L;;;;;N;LATIN LETTER PIPE;;;; 01C1;LATIN LETTER LATERAL CLICK;Lo;0;L;;;;;N;LATIN LETTER DOUBLE PIPE;;;; 01C2;LATIN LETTER ALVEOLAR CLICK;Lo;0;L;;;;;N;LATIN LETTER PIPE DOUBLE BAR;;;; 01C3;LATIN LETTER RETROFLEX CLICK;Lo;0;L;;;;;N;LATIN LETTER EXCLAMATION MARK;;;; 01C4;LATIN CAPITAL LETTER DZ WITH CARON;Lu;0;L;<compat> 0044 017D;;;;N;LATIN CAPITAL LETTER D Z HACEK;;;01C6;01C5 01C5;LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON;Lt;0;L;<compat> 0044 017E;;;;N;LATIN LETTER CAPITAL D SMALL Z HACEK;;01C4;01C6;01C5 01C6;LATIN SMALL LETTER DZ WITH CARON;Ll;0;L;<compat> 0064 017E;;;;N;LATIN SMALL LETTER D Z HACEK;;01C4;;01C5 01C7;LATIN CAPITAL LETTER LJ;Lu;0;L;<compat> 004C 004A;;;;N;LATIN CAPITAL LETTER L J;;;01C9;01C8 01C8;LATIN CAPITAL LETTER L WITH SMALL LETTER J;Lt;0;L;<compat> 004C 006A;;;;N;LATIN LETTER CAPITAL L SMALL J;;01C7;01C9;01C8 01C9;LATIN SMALL LETTER LJ;Ll;0;L;<compat> 006C 006A;;;;N;LATIN SMALL LETTER L J;;01C7;;01C8 01CA;LATIN CAPITAL LETTER NJ;Lu;0;L;<compat> 004E 004A;;;;N;LATIN CAPITAL LETTER N J;;;01CC;01CB 01CB;LATIN CAPITAL LETTER N WITH SMALL LETTER J;Lt;0;L;<compat> 004E 006A;;;;N;LATIN LETTER CAPITAL N SMALL J;;01CA;01CC;01CB 01CC;LATIN SMALL LETTER NJ;Ll;0;L;<compat> 006E 006A;;;;N;LATIN SMALL LETTER N J;;01CA;;01CB 01CD;LATIN CAPITAL LETTER A WITH CARON;Lu;0;L;0041 030C;;;;N;LATIN CAPITAL LETTER A HACEK;;;01CE; 01CE;LATIN SMALL LETTER A WITH CARON;Ll;0;L;0061 030C;;;;N;LATIN SMALL LETTER A HACEK;;01CD;;01CD 01CF;LATIN CAPITAL LETTER I WITH CARON;Lu;0;L;0049 030C;;;;N;LATIN CAPITAL LETTER I HACEK;;;01D0; 01D0;LATIN SMALL LETTER I WITH CARON;Ll;0;L;0069 030C;;;;N;LATIN SMALL LETTER I HACEK;;01CF;;01CF 01D1;LATIN CAPITAL LETTER O WITH CARON;Lu;0;L;004F 030C;;;;N;LATIN CAPITAL LETTER O HACEK;;;01D2; 01D2;LATIN SMALL LETTER O WITH CARON;Ll;0;L;006F 030C;;;;N;LATIN SMALL LETTER O HACEK;;01D1;;01D1 01D3;LATIN CAPITAL LETTER U WITH CARON;Lu;0;L;0055 030C;;;;N;LATIN CAPITAL LETTER U HACEK;;;01D4; 01D4;LATIN SMALL LETTER U WITH CARON;Ll;0;L;0075 030C;;;;N;LATIN SMALL LETTER U HACEK;;01D3;;01D3 01D5;LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON;Lu;0;L;00DC 0304;;;;N;LATIN CAPITAL LETTER U DIAERESIS MACRON;;;01D6; 01D6;LATIN SMALL LETTER U WITH DIAERESIS AND MACRON;Ll;0;L;00FC 0304;;;;N;LATIN SMALL LETTER U DIAERESIS MACRON;;01D5;;01D5 01D7;LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE;Lu;0;L;00DC 0301;;;;N;LATIN CAPITAL LETTER U DIAERESIS ACUTE;;;01D8; 01D8;LATIN SMALL LETTER U WITH DIAERESIS AND ACUTE;Ll;0;L;00FC 0301;;;;N;LATIN SMALL LETTER U DIAERESIS ACUTE;;01D7;;01D7 01D9;LATIN CAPITAL LETTER U WITH DIAERESIS AND CARON;Lu;0;L;00DC 030C;;;;N;LATIN CAPITAL LETTER U DIAERESIS HACEK;;;01DA; 01DA;LATIN SMALL LETTER U WITH DIAERESIS AND CARON;Ll;0;L;00FC 030C;;;;N;LATIN SMALL LETTER U DIAERESIS HACEK;;01D9;;01D9 01DB;LATIN CAPITAL LETTER U WITH DIAERESIS AND GRAVE;Lu;0;L;00DC 0300;;;;N;LATIN CAPITAL LETTER U DIAERESIS GRAVE;;;01DC; 01DC;LATIN SMALL LETTER U WITH DIAERESIS AND GRAVE;Ll;0;L;00FC 0300;;;;N;LATIN SMALL LETTER U DIAERESIS GRAVE;;01DB;;01DB 01DD;LATIN SMALL LETTER TURNED E;Ll;0;L;;;;;N;;;018E;;018E 01DE;LATIN CAPITAL LETTER A WITH DIAERESIS AND MACRON;Lu;0;L;00C4 0304;;;;N;LATIN CAPITAL LETTER A DIAERESIS MACRON;;;01DF; 01DF;LATIN SMALL LETTER A WITH DIAERESIS AND MACRON;Ll;0;L;00E4 0304;;;;N;LATIN SMALL LETTER A DIAERESIS MACRON;;01DE;;01DE 01E0;LATIN CAPITAL LETTER A WITH DOT ABOVE AND MACRON;Lu;0;L;0226 0304;;;;N;LATIN CAPITAL LETTER A DOT MACRON;;;01E1; 01E1;LATIN SMALL LETTER A WITH DOT ABOVE AND MACRON;Ll;0;L;0227 0304;;;;N;LATIN SMALL LETTER A DOT MACRON;;01E0;;01E0 01E2;LATIN CAPITAL LETTER AE WITH MACRON;Lu;0;L;00C6 0304;;;;N;LATIN CAPITAL LETTER A E MACRON;;;01E3; 01E3;LATIN SMALL LETTER AE WITH MACRON;Ll;0;L;00E6 0304;;;;N;LATIN SMALL LETTER A E MACRON;;01E2;;01E2 01E4;LATIN CAPITAL LETTER G WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER G BAR;;;01E5; 01E5;LATIN SMALL LETTER G WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER G BAR;;01E4;;01E4 01E6;LATIN CAPITAL LETTER G WITH CARON;Lu;0;L;0047 030C;;;;N;LATIN CAPITAL LETTER G HACEK;;;01E7; 01E7;LATIN SMALL LETTER G WITH CARON;Ll;0;L;0067 030C;;;;N;LATIN SMALL LETTER G HACEK;;01E6;;01E6 01E8;LATIN CAPITAL LETTER K WITH CARON;Lu;0;L;004B 030C;;;;N;LATIN CAPITAL LETTER K HACEK;;;01E9; 01E9;LATIN SMALL LETTER K WITH CARON;Ll;0;L;006B 030C;;;;N;LATIN SMALL LETTER K HACEK;;01E8;;01E8 01EA;LATIN CAPITAL LETTER O WITH OGONEK;Lu;0;L;004F 0328;;;;N;LATIN CAPITAL LETTER O OGONEK;;;01EB; 01EB;LATIN SMALL LETTER O WITH OGONEK;Ll;0;L;006F 0328;;;;N;LATIN SMALL LETTER O OGONEK;;01EA;;01EA 01EC;LATIN CAPITAL LETTER O WITH OGONEK AND MACRON;Lu;0;L;01EA 0304;;;;N;LATIN CAPITAL LETTER O OGONEK MACRON;;;01ED; 01ED;LATIN SMALL LETTER O WITH OGONEK AND MACRON;Ll;0;L;01EB 0304;;;;N;LATIN SMALL LETTER O OGONEK MACRON;;01EC;;01EC 01EE;LATIN CAPITAL LETTER EZH WITH CARON;Lu;0;L;01B7 030C;;;;N;LATIN CAPITAL LETTER YOGH HACEK;;;01EF; 01EF;LATIN SMALL LETTER EZH WITH CARON;Ll;0;L;0292 030C;;;;N;LATIN SMALL LETTER YOGH HACEK;;01EE;;01EE 01F0;LATIN SMALL LETTER J WITH CARON;Ll;0;L;006A 030C;;;;N;LATIN SMALL LETTER J HACEK;;;; 01F1;LATIN CAPITAL LETTER DZ;Lu;0;L;<compat> 0044 005A;;;;N;;;;01F3;01F2 01F2;LATIN CAPITAL LETTER D WITH SMALL LETTER Z;Lt;0;L;<compat> 0044 007A;;;;N;;;01F1;01F3;01F2 01F3;LATIN SMALL LETTER DZ;Ll;0;L;<compat> 0064 007A;;;;N;;;01F1;;01F2 01F4;LATIN CAPITAL LETTER G WITH ACUTE;Lu;0;L;0047 0301;;;;N;;;;01F5; 01F5;LATIN SMALL LETTER G WITH ACUTE;Ll;0;L;0067 0301;;;;N;;;01F4;;01F4 01F6;LATIN CAPITAL LETTER HWAIR;Lu;0;L;;;;;N;;;;0195; 01F7;LATIN CAPITAL LETTER WYNN;Lu;0;L;;;;;N;;;;01BF; 01F8;LATIN CAPITAL LETTER N WITH GRAVE;Lu;0;L;004E 0300;;;;N;;;;01F9; 01F9;LATIN SMALL LETTER N WITH GRAVE;Ll;0;L;006E 0300;;;;N;;;01F8;;01F8 01FA;LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE;Lu;0;L;00C5 0301;;;;N;;;;01FB; 01FB;LATIN SMALL LETTER A WITH RING ABOVE AND ACUTE;Ll;0;L;00E5 0301;;;;N;;;01FA;;01FA 01FC;LATIN CAPITAL LETTER AE WITH ACUTE;Lu;0;L;00C6 0301;;;;N;;;;01FD; 01FD;LATIN SMALL LETTER AE WITH ACUTE;Ll;0;L;00E6 0301;;;;N;;;01FC;;01FC 01FE;LATIN CAPITAL LETTER O WITH STROKE AND ACUTE;Lu;0;L;00D8 0301;;;;N;;;;01FF; 01FF;LATIN SMALL LETTER O WITH STROKE AND ACUTE;Ll;0;L;00F8 0301;;;;N;;;01FE;;01FE 0200;LATIN CAPITAL LETTER A WITH DOUBLE GRAVE;Lu;0;L;0041 030F;;;;N;;;;0201; 0201;LATIN SMALL LETTER A WITH DOUBLE GRAVE;Ll;0;L;0061 030F;;;;N;;;0200;;0200 0202;LATIN CAPITAL LETTER A WITH INVERTED BREVE;Lu;0;L;0041 0311;;;;N;;;;0203; 0203;LATIN SMALL LETTER A WITH INVERTED BREVE;Ll;0;L;0061 0311;;;;N;;;0202;;0202 0204;LATIN CAPITAL LETTER E WITH DOUBLE GRAVE;Lu;0;L;0045 030F;;;;N;;;;0205; 0205;LATIN SMALL LETTER E WITH DOUBLE GRAVE;Ll;0;L;0065 030F;;;;N;;;0204;;0204 0206;LATIN CAPITAL LETTER E WITH INVERTED BREVE;Lu;0;L;0045 0311;;;;N;;;;0207; 0207;LATIN SMALL LETTER E WITH INVERTED BREVE;Ll;0;L;0065 0311;;;;N;;;0206;;0206 0208;LATIN CAPITAL LETTER I WITH DOUBLE GRAVE;Lu;0;L;0049 030F;;;;N;;;;0209; 0209;LATIN SMALL LETTER I WITH DOUBLE GRAVE;Ll;0;L;0069 030F;;;;N;;;0208;;0208 020A;LATIN CAPITAL LETTER I WITH INVERTED BREVE;Lu;0;L;0049 0311;;;;N;;;;020B; 020B;LATIN SMALL LETTER I WITH INVERTED BREVE;Ll;0;L;0069 0311;;;;N;;;020A;;020A 020C;LATIN CAPITAL LETTER O WITH DOUBLE GRAVE;Lu;0;L;004F 030F;;;;N;;;;020D; 020D;LATIN SMALL LETTER O WITH DOUBLE GRAVE;Ll;0;L;006F 030F;;;;N;;;020C;;020C 020E;LATIN CAPITAL LETTER O WITH INVERTED BREVE;Lu;0;L;004F 0311;;;;N;;;;020F; 020F;LATIN SMALL LETTER O WITH INVERTED BREVE;Ll;0;L;006F 0311;;;;N;;;020E;;020E 0210;LATIN CAPITAL LETTER R WITH DOUBLE GRAVE;Lu;0;L;0052 030F;;;;N;;;;0211; 0211;LATIN SMALL LETTER R WITH DOUBLE GRAVE;Ll;0;L;0072 030F;;;;N;;;0210;;0210 0212;LATIN CAPITAL LETTER R WITH INVERTED BREVE;Lu;0;L;0052 0311;;;;N;;;;0213; 0213;LATIN SMALL LETTER R WITH INVERTED BREVE;Ll;0;L;0072 0311;;;;N;;;0212;;0212 0214;LATIN CAPITAL LETTER U WITH DOUBLE GRAVE;Lu;0;L;0055 030F;;;;N;;;;0215; 0215;LATIN SMALL LETTER U WITH DOUBLE GRAVE;Ll;0;L;0075 030F;;;;N;;;0214;;0214 0216;LATIN CAPITAL LETTER U WITH INVERTED BREVE;Lu;0;L;0055 0311;;;;N;;;;0217; 0217;LATIN SMALL LETTER U WITH INVERTED BREVE;Ll;0;L;0075 0311;;;;N;;;0216;;0216 0218;LATIN CAPITAL LETTER S WITH COMMA BELOW;Lu;0;L;0053 0326;;;;N;;;;0219; 0219;LATIN SMALL LETTER S WITH COMMA BELOW;Ll;0;L;0073 0326;;;;N;;;0218;;0218 021A;LATIN CAPITAL LETTER T WITH COMMA BELOW;Lu;0;L;0054 0326;;;;N;;;;021B; 021B;LATIN SMALL LETTER T WITH COMMA BELOW;Ll;0;L;0074 0326;;;;N;;;021A;;021A 021C;LATIN CAPITAL LETTER YOGH;Lu;0;L;;;;;N;;;;021D; 021D;LATIN SMALL LETTER YOGH;Ll;0;L;;;;;N;;;021C;;021C 021E;LATIN CAPITAL LETTER H WITH CARON;Lu;0;L;0048 030C;;;;N;;;;021F; 021F;LATIN SMALL LETTER H WITH CARON;Ll;0;L;0068 030C;;;;N;;;021E;;021E 0220;LATIN CAPITAL LETTER N WITH LONG RIGHT LEG;Lu;0;L;;;;;N;;;;019E; 0221;LATIN SMALL LETTER D WITH CURL;Ll;0;L;;;;;N;;;;; 0222;LATIN CAPITAL LETTER OU;Lu;0;L;;;;;N;;;;0223; 0223;LATIN SMALL LETTER OU;Ll;0;L;;;;;N;;;0222;;0222 0224;LATIN CAPITAL LETTER Z WITH HOOK;Lu;0;L;;;;;N;;;;0225; 0225;LATIN SMALL LETTER Z WITH HOOK;Ll;0;L;;;;;N;;;0224;;0224 0226;LATIN CAPITAL LETTER A WITH DOT ABOVE;Lu;0;L;0041 0307;;;;N;;;;0227; 0227;LATIN SMALL LETTER A WITH DOT ABOVE;Ll;0;L;0061 0307;;;;N;;;0226;;0226 0228;LATIN CAPITAL LETTER E WITH CEDILLA;Lu;0;L;0045 0327;;;;N;;;;0229; 0229;LATIN SMALL LETTER E WITH CEDILLA;Ll;0;L;0065 0327;;;;N;;;0228;;0228 022A;LATIN CAPITAL LETTER O WITH DIAERESIS AND MACRON;Lu;0;L;00D6 0304;;;;N;;;;022B; 022B;LATIN SMALL LETTER O WITH DIAERESIS AND MACRON;Ll;0;L;00F6 0304;;;;N;;;022A;;022A 022C;LATIN CAPITAL LETTER O WITH TILDE AND MACRON;Lu;0;L;00D5 0304;;;;N;;;;022D; 022D;LATIN SMALL LETTER O WITH TILDE AND MACRON;Ll;0;L;00F5 0304;;;;N;;;022C;;022C 022E;LATIN CAPITAL LETTER O WITH DOT ABOVE;Lu;0;L;004F 0307;;;;N;;;;022F; 022F;LATIN SMALL LETTER O WITH DOT ABOVE;Ll;0;L;006F 0307;;;;N;;;022E;;022E 0230;LATIN CAPITAL LETTER O WITH DOT ABOVE AND MACRON;Lu;0;L;022E 0304;;;;N;;;;0231; 0231;LATIN SMALL LETTER O WITH DOT ABOVE AND MACRON;Ll;0;L;022F 0304;;;;N;;;0230;;0230 0232;LATIN CAPITAL LETTER Y WITH MACRON;Lu;0;L;0059 0304;;;;N;;;;0233; 0233;LATIN SMALL LETTER Y WITH MACRON;Ll;0;L;0079 0304;;;;N;;;0232;;0232 0234;LATIN SMALL LETTER L WITH CURL;Ll;0;L;;;;;N;;;;; 0235;LATIN SMALL LETTER N WITH CURL;Ll;0;L;;;;;N;;;;; 0236;LATIN SMALL LETTER T WITH CURL;Ll;0;L;;;;;N;;;;; 0237;LATIN SMALL LETTER DOTLESS J;Ll;0;L;;;;;N;;;;; 0238;LATIN SMALL LETTER DB DIGRAPH;Ll;0;L;;;;;N;;;;; 0239;LATIN SMALL LETTER QP DIGRAPH;Ll;0;L;;;;;N;;;;; 023A;LATIN CAPITAL LETTER A WITH STROKE;Lu;0;L;;;;;N;;;;2C65; 023B;LATIN CAPITAL LETTER C WITH STROKE;Lu;0;L;;;;;N;;;;023C; 023C;LATIN SMALL LETTER C WITH STROKE;Ll;0;L;;;;;N;;;023B;;023B 023D;LATIN CAPITAL LETTER L WITH BAR;Lu;0;L;;;;;N;;;;019A; 023E;LATIN CAPITAL LETTER T WITH DIAGONAL STROKE;Lu;0;L;;;;;N;;;;2C66; 023F;LATIN SMALL LETTER S WITH SWASH TAIL;Ll;0;L;;;;;N;;;2C7E;;2C7E 0240;LATIN SMALL LETTER Z WITH SWASH TAIL;Ll;0;L;;;;;N;;;2C7F;;2C7F 0241;LATIN CAPITAL LETTER GLOTTAL STOP;Lu;0;L;;;;;N;;;;0242; 0242;LATIN SMALL LETTER GLOTTAL STOP;Ll;0;L;;;;;N;;;0241;;0241 0243;LATIN CAPITAL LETTER B WITH STROKE;Lu;0;L;;;;;N;;;;0180; 0244;LATIN CAPITAL LETTER U BAR;Lu;0;L;;;;;N;;;;0289; 0245;LATIN CAPITAL LETTER TURNED V;Lu;0;L;;;;;N;;;;028C; 0246;LATIN CAPITAL LETTER E WITH STROKE;Lu;0;L;;;;;N;;;;0247; 0247;LATIN SMALL LETTER E WITH STROKE;Ll;0;L;;;;;N;;;0246;;0246 0248;LATIN CAPITAL LETTER J WITH STROKE;Lu;0;L;;;;;N;;;;0249; 0249;LATIN SMALL LETTER J WITH STROKE;Ll;0;L;;;;;N;;;0248;;0248 024A;LATIN CAPITAL LETTER SMALL Q WITH HOOK TAIL;Lu;0;L;;;;;N;;;;024B; 024B;LATIN SMALL LETTER Q WITH HOOK TAIL;Ll;0;L;;;;;N;;;024A;;024A 024C;LATIN CAPITAL LETTER R WITH STROKE;Lu;0;L;;;;;N;;;;024D; 024D;LATIN SMALL LETTER R WITH STROKE;Ll;0;L;;;;;N;;;024C;;024C 024E;LATIN CAPITAL LETTER Y WITH STROKE;Lu;0;L;;;;;N;;;;024F; 024F;LATIN SMALL LETTER Y WITH STROKE;Ll;0;L;;;;;N;;;024E;;024E 0250;LATIN SMALL LETTER TURNED A;Ll;0;L;;;;;N;;;2C6F;;2C6F 0251;LATIN SMALL LETTER ALPHA;Ll;0;L;;;;;N;LATIN SMALL LETTER SCRIPT A;;2C6D;;2C6D 0252;LATIN SMALL LETTER TURNED ALPHA;Ll;0;L;;;;;N;LATIN SMALL LETTER TURNED SCRIPT A;;2C70;;2C70 0253;LATIN SMALL LETTER B WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER B HOOK;;0181;;0181 0254;LATIN SMALL LETTER OPEN O;Ll;0;L;;;;;N;;;0186;;0186 0255;LATIN SMALL LETTER C WITH CURL;Ll;0;L;;;;;N;LATIN SMALL LETTER C CURL;;;; 0256;LATIN SMALL LETTER D WITH TAIL;Ll;0;L;;;;;N;LATIN SMALL LETTER D RETROFLEX HOOK;;0189;;0189 0257;LATIN SMALL LETTER D WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER D HOOK;;018A;;018A 0258;LATIN SMALL LETTER REVERSED E;Ll;0;L;;;;;N;;;;; 0259;LATIN SMALL LETTER SCHWA;Ll;0;L;;;;;N;;;018F;;018F 025A;LATIN SMALL LETTER SCHWA WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER SCHWA HOOK;;;; 025B;LATIN SMALL LETTER OPEN E;Ll;0;L;;;;;N;LATIN SMALL LETTER EPSILON;;0190;;0190 025C;LATIN SMALL LETTER REVERSED OPEN E;Ll;0;L;;;;;N;LATIN SMALL LETTER REVERSED EPSILON;;A7AB;;A7AB 025D;LATIN SMALL LETTER REVERSED OPEN E WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER REVERSED EPSILON HOOK;;;; 025E;LATIN SMALL LETTER CLOSED REVERSED OPEN E;Ll;0;L;;;;;N;LATIN SMALL LETTER CLOSED REVERSED EPSILON;;;; 025F;LATIN SMALL LETTER DOTLESS J WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER DOTLESS J BAR;;;; 0260;LATIN SMALL LETTER G WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER G HOOK;;0193;;0193 0261;LATIN SMALL LETTER SCRIPT G;Ll;0;L;;;;;N;;;A7AC;;A7AC 0262;LATIN LETTER SMALL CAPITAL G;Ll;0;L;;;;;N;;;;; 0263;LATIN SMALL LETTER GAMMA;Ll;0;L;;;;;N;;;0194;;0194 0264;LATIN SMALL LETTER RAMS HORN;Ll;0;L;;;;;N;LATIN SMALL LETTER BABY GAMMA;;;; 0265;LATIN SMALL LETTER TURNED H;Ll;0;L;;;;;N;;;A78D;;A78D 0266;LATIN SMALL LETTER H WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER H HOOK;;A7AA;;A7AA 0267;LATIN SMALL LETTER HENG WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER HENG HOOK;;;; 0268;LATIN SMALL LETTER I WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER BARRED I;;0197;;0197 0269;LATIN SMALL LETTER IOTA;Ll;0;L;;;;;N;;;0196;;0196 026A;LATIN LETTER SMALL CAPITAL I;Ll;0;L;;;;;N;;;A7AE;;A7AE 026B;LATIN SMALL LETTER L WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;2C62;;2C62 026C;LATIN SMALL LETTER L WITH BELT;Ll;0;L;;;;;N;LATIN SMALL LETTER L BELT;;A7AD;;A7AD 026D;LATIN SMALL LETTER L WITH RETROFLEX HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER L RETROFLEX HOOK;;;; 026E;LATIN SMALL LETTER LEZH;Ll;0;L;;;;;N;LATIN SMALL LETTER L YOGH;;;; 026F;LATIN SMALL LETTER TURNED M;Ll;0;L;;;;;N;;;019C;;019C 0270;LATIN SMALL LETTER TURNED M WITH LONG LEG;Ll;0;L;;;;;N;;;;; 0271;LATIN SMALL LETTER M WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER M HOOK;;2C6E;;2C6E 0272;LATIN SMALL LETTER N WITH LEFT HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER N HOOK;;019D;;019D 0273;LATIN SMALL LETTER N WITH RETROFLEX HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER N RETROFLEX HOOK;;;; 0274;LATIN LETTER SMALL CAPITAL N;Ll;0;L;;;;;N;;;;; 0275;LATIN SMALL LETTER BARRED O;Ll;0;L;;;;;N;;;019F;;019F 0276;LATIN LETTER SMALL CAPITAL OE;Ll;0;L;;;;;N;LATIN LETTER SMALL CAPITAL O E;;;; 0277;LATIN SMALL LETTER CLOSED OMEGA;Ll;0;L;;;;;N;;;;; 0278;LATIN SMALL LETTER PHI;Ll;0;L;;;;;N;;;;; 0279;LATIN SMALL LETTER TURNED R;Ll;0;L;;;;;N;;;;; 027A;LATIN SMALL LETTER TURNED R WITH LONG LEG;Ll;0;L;;;;;N;;;;; 027B;LATIN SMALL LETTER TURNED R WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER TURNED R HOOK;;;; 027C;LATIN SMALL LETTER R WITH LONG LEG;Ll;0;L;;;;;N;;;;; 027D;LATIN SMALL LETTER R WITH TAIL;Ll;0;L;;;;;N;LATIN SMALL LETTER R HOOK;;2C64;;2C64 027E;LATIN SMALL LETTER R WITH FISHHOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER FISHHOOK R;;;; 027F;LATIN SMALL LETTER REVERSED R WITH FISHHOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER REVERSED FISHHOOK R;;;; 0280;LATIN LETTER SMALL CAPITAL R;Ll;0;L;;;;;N;;;01A6;;01A6 0281;LATIN LETTER SMALL CAPITAL INVERTED R;Ll;0;L;;;;;N;;;;; 0282;LATIN SMALL LETTER S WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER S HOOK;;;; 0283;LATIN SMALL LETTER ESH;Ll;0;L;;;;;N;;;01A9;;01A9 0284;LATIN SMALL LETTER DOTLESS J WITH STROKE AND HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER DOTLESS J BAR HOOK;;;; 0285;LATIN SMALL LETTER SQUAT REVERSED ESH;Ll;0;L;;;;;N;;;;; 0286;LATIN SMALL LETTER ESH WITH CURL;Ll;0;L;;;;;N;LATIN SMALL LETTER ESH CURL;;;; 0287;LATIN SMALL LETTER TURNED T;Ll;0;L;;;;;N;;;A7B1;;A7B1 0288;LATIN SMALL LETTER T WITH RETROFLEX HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER T RETROFLEX HOOK;;01AE;;01AE 0289;LATIN SMALL LETTER U BAR;Ll;0;L;;;;;N;;;0244;;0244 028A;LATIN SMALL LETTER UPSILON;Ll;0;L;;;;;N;;;01B1;;01B1 028B;LATIN SMALL LETTER V WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER SCRIPT V;;01B2;;01B2 028C;LATIN SMALL LETTER TURNED V;Ll;0;L;;;;;N;;;0245;;0245 028D;LATIN SMALL LETTER TURNED W;Ll;0;L;;;;;N;;;;; 028E;LATIN SMALL LETTER TURNED Y;Ll;0;L;;;;;N;;;;; 028F;LATIN LETTER SMALL CAPITAL Y;Ll;0;L;;;;;N;;;;; 0290;LATIN SMALL LETTER Z WITH RETROFLEX HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER Z RETROFLEX HOOK;;;; 0291;LATIN SMALL LETTER Z WITH CURL;Ll;0;L;;;;;N;LATIN SMALL LETTER Z CURL;;;; 0292;LATIN SMALL LETTER EZH;Ll;0;L;;;;;N;LATIN SMALL LETTER YOGH;;01B7;;01B7 0293;LATIN SMALL LETTER EZH WITH CURL;Ll;0;L;;;;;N;LATIN SMALL LETTER YOGH CURL;;;; 0294;LATIN LETTER GLOTTAL STOP;Lo;0;L;;;;;N;;;;; 0295;LATIN LETTER PHARYNGEAL VOICED FRICATIVE;Ll;0;L;;;;;N;LATIN LETTER REVERSED GLOTTAL STOP;;;; 0296;LATIN LETTER INVERTED GLOTTAL STOP;Ll;0;L;;;;;N;;;;; 0297;LATIN LETTER STRETCHED C;Ll;0;L;;;;;N;;;;; 0298;LATIN LETTER BILABIAL CLICK;Ll;0;L;;;;;N;LATIN LETTER BULLSEYE;;;; 0299;LATIN LETTER SMALL CAPITAL B;Ll;0;L;;;;;N;;;;; 029A;LATIN SMALL LETTER CLOSED OPEN E;Ll;0;L;;;;;N;LATIN SMALL LETTER CLOSED EPSILON;;;; 029B;LATIN LETTER SMALL CAPITAL G WITH HOOK;Ll;0;L;;;;;N;LATIN LETTER SMALL CAPITAL G HOOK;;;; 029C;LATIN LETTER SMALL CAPITAL H;Ll;0;L;;;;;N;;;;; 029D;LATIN SMALL LETTER J WITH CROSSED-TAIL;Ll;0;L;;;;;N;LATIN SMALL LETTER CROSSED-TAIL J;;A7B2;;A7B2 029E;LATIN SMALL LETTER TURNED K;Ll;0;L;;;;;N;;;A7B0;;A7B0 029F;LATIN LETTER SMALL CAPITAL L;Ll;0;L;;;;;N;;;;; 02A0;LATIN SMALL LETTER Q WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER Q HOOK;;;; 02A1;LATIN LETTER GLOTTAL STOP WITH STROKE;Ll;0;L;;;;;N;LATIN LETTER GLOTTAL STOP BAR;;;; 02A2;LATIN LETTER REVERSED GLOTTAL STOP WITH STROKE;Ll;0;L;;;;;N;LATIN LETTER REVERSED GLOTTAL STOP BAR;;;; 02A3;LATIN SMALL LETTER DZ DIGRAPH;Ll;0;L;;;;;N;LATIN SMALL LETTER D Z;;;; 02A4;LATIN SMALL LETTER DEZH DIGRAPH;Ll;0;L;;;;;N;LATIN SMALL LETTER D YOGH;;;; 02A5;LATIN SMALL LETTER DZ DIGRAPH WITH CURL;Ll;0;L;;;;;N;LATIN SMALL LETTER D Z CURL;;;; 02A6;LATIN SMALL LETTER TS DIGRAPH;Ll;0;L;;;;;N;LATIN SMALL LETTER T S;;;; 02A7;LATIN SMALL LETTER TESH DIGRAPH;Ll;0;L;;;;;N;LATIN SMALL LETTER T ESH;;;; 02A8;LATIN SMALL LETTER TC DIGRAPH WITH CURL;Ll;0;L;;;;;N;LATIN SMALL LETTER T C CURL;;;; 02A9;LATIN SMALL LETTER FENG DIGRAPH;Ll;0;L;;;;;N;;;;; 02AA;LATIN SMALL LETTER LS DIGRAPH;Ll;0;L;;;;;N;;;;; 02AB;LATIN SMALL LETTER LZ DIGRAPH;Ll;0;L;;;;;N;;;;; 02AC;LATIN LETTER BILABIAL PERCUSSIVE;Ll;0;L;;;;;N;;;;; 02AD;LATIN LETTER BIDENTAL PERCUSSIVE;Ll;0;L;;;;;N;;;;; 02AE;LATIN SMALL LETTER TURNED H WITH FISHHOOK;Ll;0;L;;;;;N;;;;; 02AF;LATIN SMALL LETTER TURNED H WITH FISHHOOK AND TAIL;Ll;0;L;;;;;N;;;;; 02B0;MODIFIER LETTER SMALL H;Lm;0;L;<super> 0068;;;;N;;;;; 02B1;MODIFIER LETTER SMALL H WITH HOOK;Lm;0;L;<super> 0266;;;;N;MODIFIER LETTER SMALL H HOOK;;;; 02B2;MODIFIER LETTER SMALL J;Lm;0;L;<super> 006A;;;;N;;;;; 02B3;MODIFIER LETTER SMALL R;Lm;0;L;<super> 0072;;;;N;;;;; 02B4;MODIFIER LETTER SMALL TURNED R;Lm;0;L;<super> 0279;;;;N;;;;; 02B5;MODIFIER LETTER SMALL TURNED R WITH HOOK;Lm;0;L;<super> 027B;;;;N;MODIFIER LETTER SMALL TURNED R HOOK;;;; 02B6;MODIFIER LETTER SMALL CAPITAL INVERTED R;Lm;0;L;<super> 0281;;;;N;;;;; 02B7;MODIFIER LETTER SMALL W;Lm;0;L;<super> 0077;;;;N;;;;; 02B8;MODIFIER LETTER SMALL Y;Lm;0;L;<super> 0079;;;;N;;;;; 02B9;MODIFIER LETTER PRIME;Lm;0;ON;;;;;N;;;;; 02BA;MODIFIER LETTER DOUBLE PRIME;Lm;0;ON;;;;;N;;;;; 02BB;MODIFIER LETTER TURNED COMMA;Lm;0;L;;;;;N;;;;; 02BC;MODIFIER LETTER APOSTROPHE;Lm;0;L;;;;;N;;;;; 02BD;MODIFIER LETTER REVERSED COMMA;Lm;0;L;;;;;N;;;;; 02BE;MODIFIER LETTER RIGHT HALF RING;Lm;0;L;;;;;N;;;;; 02BF;MODIFIER LETTER LEFT HALF RING;Lm;0;L;;;;;N;;;;; 02C0;MODIFIER LETTER GLOTTAL STOP;Lm;0;L;;;;;N;;;;; 02C1;MODIFIER LETTER REVERSED GLOTTAL STOP;Lm;0;L;;;;;N;;;;; 02C2;MODIFIER LETTER LEFT ARROWHEAD;Sk;0;ON;;;;;N;;;;; 02C3;MODIFIER LETTER RIGHT ARROWHEAD;Sk;0;ON;;;;;N;;;;; 02C4;MODIFIER LETTER UP ARROWHEAD;Sk;0;ON;;;;;N;;;;; 02C5;MODIFIER LETTER DOWN ARROWHEAD;Sk;0;ON;;;;;N;;;;; 02C6;MODIFIER LETTER CIRCUMFLEX ACCENT;Lm;0;ON;;;;;N;MODIFIER LETTER CIRCUMFLEX;;;; 02C7;CARON;Lm;0;ON;;;;;N;MODIFIER LETTER HACEK;;;; 02C8;MODIFIER LETTER VERTICAL LINE;Lm;0;ON;;;;;N;;;;; 02C9;MODIFIER LETTER MACRON;Lm;0;ON;;;;;N;;;;; 02CA;MODIFIER LETTER ACUTE ACCENT;Lm;0;ON;;;;;N;MODIFIER LETTER ACUTE;;;; 02CB;MODIFIER LETTER GRAVE ACCENT;Lm;0;ON;;;;;N;MODIFIER LETTER GRAVE;;;; 02CC;MODIFIER LETTER LOW VERTICAL LINE;Lm;0;ON;;;;;N;;;;; 02CD;MODIFIER LETTER LOW MACRON;Lm;0;ON;;;;;N;;;;; 02CE;MODIFIER LETTER LOW GRAVE ACCENT;Lm;0;ON;;;;;N;MODIFIER LETTER LOW GRAVE;;;; 02CF;MODIFIER LETTER LOW ACUTE ACCENT;Lm;0;ON;;;;;N;MODIFIER LETTER LOW ACUTE;;;; 02D0;MODIFIER LETTER TRIANGULAR COLON;Lm;0;L;;;;;N;;;;; 02D1;MODIFIER LETTER HALF TRIANGULAR COLON;Lm;0;L;;;;;N;;;;; 02D2;MODIFIER LETTER CENTRED RIGHT HALF RING;Sk;0;ON;;;;;N;MODIFIER LETTER CENTERED RIGHT HALF RING;;;; 02D3;MODIFIER LETTER CENTRED LEFT HALF RING;Sk;0;ON;;;;;N;MODIFIER LETTER CENTERED LEFT HALF RING;;;; 02D4;MODIFIER LETTER UP TACK;Sk;0;ON;;;;;N;;;;; 02D5;MODIFIER LETTER DOWN TACK;Sk;0;ON;;;;;N;;;;; 02D6;MODIFIER LETTER PLUS SIGN;Sk;0;ON;;;;;N;;;;; 02D7;MODIFIER LETTER MINUS SIGN;Sk;0;ON;;;;;N;;;;; 02D8;BREVE;Sk;0;ON;<compat> 0020 0306;;;;N;SPACING BREVE;;;; 02D9;DOT ABOVE;Sk;0;ON;<compat> 0020 0307;;;;N;SPACING DOT ABOVE;;;; 02DA;RING ABOVE;Sk;0;ON;<compat> 0020 030A;;;;N;SPACING RING ABOVE;;;; 02DB;OGONEK;Sk;0;ON;<compat> 0020 0328;;;;N;SPACING OGONEK;;;; 02DC;SMALL TILDE;Sk;0;ON;<compat> 0020 0303;;;;N;SPACING TILDE;;;; 02DD;DOUBLE ACUTE ACCENT;Sk;0;ON;<compat> 0020 030B;;;;N;SPACING DOUBLE ACUTE;;;; 02DE;MODIFIER LETTER RHOTIC HOOK;Sk;0;ON;;;;;N;;;;; 02DF;MODIFIER LETTER CROSS ACCENT;Sk;0;ON;;;;;N;;;;; 02E0;MODIFIER LETTER SMALL GAMMA;Lm;0;L;<super> 0263;;;;N;;;;; 02E1;MODIFIER LETTER SMALL L;Lm;0;L;<super> 006C;;;;N;;;;; 02E2;MODIFIER LETTER SMALL S;Lm;0;L;<super> 0073;;;;N;;;;; 02E3;MODIFIER LETTER SMALL X;Lm;0;L;<super> 0078;;;;N;;;;; 02E4;MODIFIER LETTER SMALL REVERSED GLOTTAL STOP;Lm;0;L;<super> 0295;;;;N;;;;; 02E5;MODIFIER LETTER EXTRA-HIGH TONE BAR;Sk;0;ON;;;;;N;;;;; 02E6;MODIFIER LETTER HIGH TONE BAR;Sk;0;ON;;;;;N;;;;; 02E7;MODIFIER LETTER MID TONE BAR;Sk;0;ON;;;;;N;;;;; 02E8;MODIFIER LETTER LOW TONE BAR;Sk;0;ON;;;;;N;;;;; 02E9;MODIFIER LETTER EXTRA-LOW TONE BAR;Sk;0;ON;;;;;N;;;;; 02EA;MODIFIER LETTER YIN DEPARTING TONE MARK;Sk;0;ON;;;;;N;;;;; 02EB;MODIFIER LETTER YANG DEPARTING TONE MARK;Sk;0;ON;;;;;N;;;;; 02EC;MODIFIER LETTER VOICING;Lm;0;ON;;;;;N;;;;; 02ED;MODIFIER LETTER UNASPIRATED;Sk;0;ON;;;;;N;;;;; 02EE;MODIFIER LETTER DOUBLE APOSTROPHE;Lm;0;L;;;;;N;;;;; 02EF;MODIFIER LETTER LOW DOWN ARROWHEAD;Sk;0;ON;;;;;N;;;;; 02F0;MODIFIER LETTER LOW UP ARROWHEAD;Sk;0;ON;;;;;N;;;;; 02F1;MODIFIER LETTER LOW LEFT ARROWHEAD;Sk;0;ON;;;;;N;;;;; 02F2;MODIFIER LETTER LOW RIGHT ARROWHEAD;Sk;0;ON;;;;;N;;;;; 02F3;MODIFIER LETTER LOW RING;Sk;0;ON;;;;;N;;;;; 02F4;MODIFIER LETTER MIDDLE GRAVE ACCENT;Sk;0;ON;;;;;N;;;;; 02F5;MODIFIER LETTER MIDDLE DOUBLE GRAVE ACCENT;Sk;0;ON;;;;;N;;;;; 02F6;MODIFIER LETTER MIDDLE DOUBLE ACUTE ACCENT;Sk;0;ON;;;;;N;;;;; 02F7;MODIFIER LETTER LOW TILDE;Sk;0;ON;;;;;N;;;;; 02F8;MODIFIER LETTER RAISED COLON;Sk;0;ON;;;;;N;;;;; 02F9;MODIFIER LETTER BEGIN HIGH TONE;Sk;0;ON;;;;;N;;;;; 02FA;MODIFIER LETTER END HIGH TONE;Sk;0;ON;;;;;N;;;;; 02FB;MODIFIER LETTER BEGIN LOW TONE;Sk;0;ON;;;;;N;;;;; 02FC;MODIFIER LETTER END LOW TONE;Sk;0;ON;;;;;N;;;;; 02FD;MODIFIER LETTER SHELF;Sk;0;ON;;;;;N;;;;; 02FE;MODIFIER LETTER OPEN SHELF;Sk;0;ON;;;;;N;;;;; 02FF;MODIFIER LETTER LOW LEFT ARROW;Sk;0;ON;;;;;N;;;;; 0300;COMBINING GRAVE ACCENT;Mn;230;NSM;;;;;N;NON-SPACING GRAVE;;;; 0301;COMBINING ACUTE ACCENT;Mn;230;NSM;;;;;N;NON-SPACING ACUTE;;;; 0302;COMBINING CIRCUMFLEX ACCENT;Mn;230;NSM;;;;;N;NON-SPACING CIRCUMFLEX;;;; 0303;COMBINING TILDE;Mn;230;NSM;;;;;N;NON-SPACING TILDE;;;; 0304;COMBINING MACRON;Mn;230;NSM;;;;;N;NON-SPACING MACRON;;;; 0305;COMBINING OVERLINE;Mn;230;NSM;;;;;N;NON-SPACING OVERSCORE;;;; 0306;COMBINING BREVE;Mn;230;NSM;;;;;N;NON-SPACING BREVE;;;; 0307;COMBINING DOT ABOVE;Mn;230;NSM;;;;;N;NON-SPACING DOT ABOVE;;;; 0308;COMBINING DIAERESIS;Mn;230;NSM;;;;;N;NON-SPACING DIAERESIS;;;; 0309;COMBINING HOOK ABOVE;Mn;230;NSM;;;;;N;NON-SPACING HOOK ABOVE;;;; 030A;COMBINING RING ABOVE;Mn;230;NSM;;;;;N;NON-SPACING RING ABOVE;;;; 030B;COMBINING DOUBLE ACUTE ACCENT;Mn;230;NSM;;;;;N;NON-SPACING DOUBLE ACUTE;;;; 030C;COMBINING CARON;Mn;230;NSM;;;;;N;NON-SPACING HACEK;;;; 030D;COMBINING VERTICAL LINE ABOVE;Mn;230;NSM;;;;;N;NON-SPACING VERTICAL LINE ABOVE;;;; 030E;COMBINING DOUBLE VERTICAL LINE ABOVE;Mn;230;NSM;;;;;N;NON-SPACING DOUBLE VERTICAL LINE ABOVE;;;; 030F;COMBINING DOUBLE GRAVE ACCENT;Mn;230;NSM;;;;;N;NON-SPACING DOUBLE GRAVE;;;; 0310;COMBINING CANDRABINDU;Mn;230;NSM;;;;;N;NON-SPACING CANDRABINDU;;;; 0311;COMBINING INVERTED BREVE;Mn;230;NSM;;;;;N;NON-SPACING INVERTED BREVE;;;; 0312;COMBINING TURNED COMMA ABOVE;Mn;230;NSM;;;;;N;NON-SPACING TURNED COMMA ABOVE;;;; 0313;COMBINING COMMA ABOVE;Mn;230;NSM;;;;;N;NON-SPACING COMMA ABOVE;;;; 0314;COMBINING REVERSED COMMA ABOVE;Mn;230;NSM;;;;;N;NON-SPACING REVERSED COMMA ABOVE;;;; 0315;COMBINING COMMA ABOVE RIGHT;Mn;232;NSM;;;;;N;NON-SPACING COMMA ABOVE RIGHT;;;; 0316;COMBINING GRAVE ACCENT BELOW;Mn;220;NSM;;;;;N;NON-SPACING GRAVE BELOW;;;; 0317;COMBINING ACUTE ACCENT BELOW;Mn;220;NSM;;;;;N;NON-SPACING ACUTE BELOW;;;; 0318;COMBINING LEFT TACK BELOW;Mn;220;NSM;;;;;N;NON-SPACING LEFT TACK BELOW;;;; 0319;COMBINING RIGHT TACK BELOW;Mn;220;NSM;;;;;N;NON-SPACING RIGHT TACK BELOW;;;; 031A;COMBINING LEFT ANGLE ABOVE;Mn;232;NSM;;;;;N;NON-SPACING LEFT ANGLE ABOVE;;;; 031B;COMBINING HORN;Mn;216;NSM;;;;;N;NON-SPACING HORN;;;; 031C;COMBINING LEFT HALF RING BELOW;Mn;220;NSM;;;;;N;NON-SPACING LEFT HALF RING BELOW;;;; 031D;COMBINING UP TACK BELOW;Mn;220;NSM;;;;;N;NON-SPACING UP TACK BELOW;;;; 031E;COMBINING DOWN TACK BELOW;Mn;220;NSM;;;;;N;NON-SPACING DOWN TACK BELOW;;;; 031F;COMBINING PLUS SIGN BELOW;Mn;220;NSM;;;;;N;NON-SPACING PLUS SIGN BELOW;;;; 0320;COMBINING MINUS SIGN BELOW;Mn;220;NSM;;;;;N;NON-SPACING MINUS SIGN BELOW;;;; 0321;COMBINING PALATALIZED HOOK BELOW;Mn;202;NSM;;;;;N;NON-SPACING PALATALIZED HOOK BELOW;;;; 0322;COMBINING RETROFLEX HOOK BELOW;Mn;202;NSM;;;;;N;NON-SPACING RETROFLEX HOOK BELOW;;;; 0323;COMBINING DOT BELOW;Mn;220;NSM;;;;;N;NON-SPACING DOT BELOW;;;; 0324;COMBINING DIAERESIS BELOW;Mn;220;NSM;;;;;N;NON-SPACING DOUBLE DOT BELOW;;;; 0325;COMBINING RING BELOW;Mn;220;NSM;;;;;N;NON-SPACING RING BELOW;;;; 0326;COMBINING COMMA BELOW;Mn;220;NSM;;;;;N;NON-SPACING COMMA BELOW;;;; 0327;COMBINING CEDILLA;Mn;202;NSM;;;;;N;NON-SPACING CEDILLA;;;; 0328;COMBINING OGONEK;Mn;202;NSM;;;;;N;NON-SPACING OGONEK;;;; 0329;COMBINING VERTICAL LINE BELOW;Mn;220;NSM;;;;;N;NON-SPACING VERTICAL LINE BELOW;;;; 032A;COMBINING BRIDGE BELOW;Mn;220;NSM;;;;;N;NON-SPACING BRIDGE BELOW;;;; 032B;COMBINING INVERTED DOUBLE ARCH BELOW;Mn;220;NSM;;;;;N;NON-SPACING INVERTED DOUBLE ARCH BELOW;;;; 032C;COMBINING CARON BELOW;Mn;220;NSM;;;;;N;NON-SPACING HACEK BELOW;;;; 032D;COMBINING CIRCUMFLEX ACCENT BELOW;Mn;220;NSM;;;;;N;NON-SPACING CIRCUMFLEX BELOW;;;; 032E;COMBINING BREVE BELOW;Mn;220;NSM;;;;;N;NON-SPACING BREVE BELOW;;;; 032F;COMBINING INVERTED BREVE BELOW;Mn;220;NSM;;;;;N;NON-SPACING INVERTED BREVE BELOW;;;; 0330;COMBINING TILDE BELOW;Mn;220;NSM;;;;;N;NON-SPACING TILDE BELOW;;;; 0331;COMBINING MACRON BELOW;Mn;220;NSM;;;;;N;NON-SPACING MACRON BELOW;;;; 0332;COMBINING LOW LINE;Mn;220;NSM;;;;;N;NON-SPACING UNDERSCORE;;;; 0333;COMBINING DOUBLE LOW LINE;Mn;220;NSM;;;;;N;NON-SPACING DOUBLE UNDERSCORE;;;; 0334;COMBINING TILDE OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING TILDE OVERLAY;;;; 0335;COMBINING SHORT STROKE OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING SHORT BAR OVERLAY;;;; 0336;COMBINING LONG STROKE OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING LONG BAR OVERLAY;;;; 0337;COMBINING SHORT SOLIDUS OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING SHORT SLASH OVERLAY;;;; 0338;COMBINING LONG SOLIDUS OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING LONG SLASH OVERLAY;;;; 0339;COMBINING RIGHT HALF RING BELOW;Mn;220;NSM;;;;;N;NON-SPACING RIGHT HALF RING BELOW;;;; 033A;COMBINING INVERTED BRIDGE BELOW;Mn;220;NSM;;;;;N;NON-SPACING INVERTED BRIDGE BELOW;;;; 033B;COMBINING SQUARE BELOW;Mn;220;NSM;;;;;N;NON-SPACING SQUARE BELOW;;;; 033C;COMBINING SEAGULL BELOW;Mn;220;NSM;;;;;N;NON-SPACING SEAGULL BELOW;;;; 033D;COMBINING X ABOVE;Mn;230;NSM;;;;;N;NON-SPACING X ABOVE;;;; 033E;COMBINING VERTICAL TILDE;Mn;230;NSM;;;;;N;NON-SPACING VERTICAL TILDE;;;; 033F;COMBINING DOUBLE OVERLINE;Mn;230;NSM;;;;;N;NON-SPACING DOUBLE OVERSCORE;;;; 0340;COMBINING GRAVE TONE MARK;Mn;230;NSM;0300;;;;N;NON-SPACING GRAVE TONE MARK;;;; 0341;COMBINING ACUTE TONE MARK;Mn;230;NSM;0301;;;;N;NON-SPACING ACUTE TONE MARK;;;; 0342;COMBINING GREEK PERISPOMENI;Mn;230;NSM;;;;;N;;;;; 0343;COMBINING GREEK KORONIS;Mn;230;NSM;0313;;;;N;;;;; 0344;COMBINING GREEK DIALYTIKA TONOS;Mn;230;NSM;0308 0301;;;;N;GREEK NON-SPACING DIAERESIS TONOS;;;; 0345;COMBINING GREEK YPOGEGRAMMENI;Mn;240;NSM;;;;;N;GREEK NON-SPACING IOTA BELOW;;0399;;0399 0346;COMBINING BRIDGE ABOVE;Mn;230;NSM;;;;;N;;;;; 0347;COMBINING EQUALS SIGN BELOW;Mn;220;NSM;;;;;N;;;;; 0348;COMBINING DOUBLE VERTICAL LINE BELOW;Mn;220;NSM;;;;;N;;;;; 0349;COMBINING LEFT ANGLE BELOW;Mn;220;NSM;;;;;N;;;;; 034A;COMBINING NOT TILDE ABOVE;Mn;230;NSM;;;;;N;;;;; 034B;COMBINING HOMOTHETIC ABOVE;Mn;230;NSM;;;;;N;;;;; 034C;COMBINING ALMOST EQUAL TO ABOVE;Mn;230;NSM;;;;;N;;;;; 034D;COMBINING LEFT RIGHT ARROW BELOW;Mn;220;NSM;;;;;N;;;;; 034E;COMBINING UPWARDS ARROW BELOW;Mn;220;NSM;;;;;N;;;;; 034F;COMBINING GRAPHEME JOINER;Mn;0;NSM;;;;;N;;;;; 0350;COMBINING RIGHT ARROWHEAD ABOVE;Mn;230;NSM;;;;;N;;;;; 0351;COMBINING LEFT HALF RING ABOVE;Mn;230;NSM;;;;;N;;;;; 0352;COMBINING FERMATA;Mn;230;NSM;;;;;N;;;;; 0353;COMBINING X BELOW;Mn;220;NSM;;;;;N;;;;; 0354;COMBINING LEFT ARROWHEAD BELOW;Mn;220;NSM;;;;;N;;;;; 0355;COMBINING RIGHT ARROWHEAD BELOW;Mn;220;NSM;;;;;N;;;;; 0356;COMBINING RIGHT ARROWHEAD AND UP ARROWHEAD BELOW;Mn;220;NSM;;;;;N;;;;; 0357;COMBINING RIGHT HALF RING ABOVE;Mn;230;NSM;;;;;N;;;;; 0358;COMBINING DOT ABOVE RIGHT;Mn;232;NSM;;;;;N;;;;; 0359;COMBINING ASTERISK BELOW;Mn;220;NSM;;;;;N;;;;; 035A;COMBINING DOUBLE RING BELOW;Mn;220;NSM;;;;;N;;;;; 035B;COMBINING ZIGZAG ABOVE;Mn;230;NSM;;;;;N;;;;; 035C;COMBINING DOUBLE BREVE BELOW;Mn;233;NSM;;;;;N;;;;; 035D;COMBINING DOUBLE BREVE;Mn;234;NSM;;;;;N;;;;; 035E;COMBINING DOUBLE MACRON;Mn;234;NSM;;;;;N;;;;; 035F;COMBINING DOUBLE MACRON BELOW;Mn;233;NSM;;;;;N;;;;; 0360;COMBINING DOUBLE TILDE;Mn;234;NSM;;;;;N;;;;; 0361;COMBINING DOUBLE INVERTED BREVE;Mn;234;NSM;;;;;N;;;;; 0362;COMBINING DOUBLE RIGHTWARDS ARROW BELOW;Mn;233;NSM;;;;;N;;;;; 0363;COMBINING LATIN SMALL LETTER A;Mn;230;NSM;;;;;N;;;;; 0364;COMBINING LATIN SMALL LETTER E;Mn;230;NSM;;;;;N;;;;; 0365;COMBINING LATIN SMALL LETTER I;Mn;230;NSM;;;;;N;;;;; 0366;COMBINING LATIN SMALL LETTER O;Mn;230;NSM;;;;;N;;;;; 0367;COMBINING LATIN SMALL LETTER U;Mn;230;NSM;;;;;N;;;;; 0368;COMBINING LATIN SMALL LETTER C;Mn;230;NSM;;;;;N;;;;; 0369;COMBINING LATIN SMALL LETTER D;Mn;230;NSM;;;;;N;;;;; 036A;COMBINING LATIN SMALL LETTER H;Mn;230;NSM;;;;;N;;;;; 036B;COMBINING LATIN SMALL LETTER M;Mn;230;NSM;;;;;N;;;;; 036C;COMBINING LATIN SMALL LETTER R;Mn;230;NSM;;;;;N;;;;; 036D;COMBINING LATIN SMALL LETTER T;Mn;230;NSM;;;;;N;;;;; 036E;COMBINING LATIN SMALL LETTER V;Mn;230;NSM;;;;;N;;;;; 036F;COMBINING LATIN SMALL LETTER X;Mn;230;NSM;;;;;N;;;;; 0370;GREEK CAPITAL LETTER HETA;Lu;0;L;;;;;N;;;;0371; 0371;GREEK SMALL LETTER HETA;Ll;0;L;;;;;N;;;0370;;0370 0372;GREEK CAPITAL LETTER ARCHAIC SAMPI;Lu;0;L;;;;;N;;;;0373; 0373;GREEK SMALL LETTER ARCHAIC SAMPI;Ll;0;L;;;;;N;;;0372;;0372 0374;GREEK NUMERAL SIGN;Lm;0;ON;02B9;;;;N;GREEK UPPER NUMERAL SIGN;;;; 0375;GREEK LOWER NUMERAL SIGN;Sk;0;ON;;;;;N;;;;; 0376;GREEK CAPITAL LETTER PAMPHYLIAN DIGAMMA;Lu;0;L;;;;;N;;;;0377; 0377;GREEK SMALL LETTER PAMPHYLIAN DIGAMMA;Ll;0;L;;;;;N;;;0376;;0376 037A;GREEK YPOGEGRAMMENI;Lm;0;L;<compat> 0020 0345;;;;N;GREEK SPACING IOTA BELOW;;;; 037B;GREEK SMALL REVERSED LUNATE SIGMA SYMBOL;Ll;0;L;;;;;N;;;03FD;;03FD 037C;GREEK SMALL DOTTED LUNATE SIGMA SYMBOL;Ll;0;L;;;;;N;;;03FE;;03FE 037D;GREEK SMALL REVERSED DOTTED LUNATE SIGMA SYMBOL;Ll;0;L;;;;;N;;;03FF;;03FF 037E;GREEK QUESTION MARK;Po;0;ON;003B;;;;N;;;;; 037F;GREEK CAPITAL LETTER YOT;Lu;0;L;;;;;N;;;;03F3; 0384;GREEK TONOS;Sk;0;ON;<compat> 0020 0301;;;;N;GREEK SPACING TONOS;;;; 0385;GREEK DIALYTIKA TONOS;Sk;0;ON;00A8 0301;;;;N;GREEK SPACING DIAERESIS TONOS;;;; 0386;GREEK CAPITAL LETTER ALPHA WITH TONOS;Lu;0;L;0391 0301;;;;N;GREEK CAPITAL LETTER ALPHA TONOS;;;03AC; 0387;GREEK ANO TELEIA;Po;0;ON;00B7;;;;N;;;;; 0388;GREEK CAPITAL LETTER EPSILON WITH TONOS;Lu;0;L;0395 0301;;;;N;GREEK CAPITAL LETTER EPSILON TONOS;;;03AD; 0389;GREEK CAPITAL LETTER ETA WITH TONOS;Lu;0;L;0397 0301;;;;N;GREEK CAPITAL LETTER ETA TONOS;;;03AE; 038A;GREEK CAPITAL LETTER IOTA WITH TONOS;Lu;0;L;0399 0301;;;;N;GREEK CAPITAL LETTER IOTA TONOS;;;03AF; 038C;GREEK CAPITAL LETTER OMICRON WITH TONOS;Lu;0;L;039F 0301;;;;N;GREEK CAPITAL LETTER OMICRON TONOS;;;03CC; 038E;GREEK CAPITAL LETTER UPSILON WITH TONOS;Lu;0;L;03A5 0301;;;;N;GREEK CAPITAL LETTER UPSILON TONOS;;;03CD; 038F;GREEK CAPITAL LETTER OMEGA WITH TONOS;Lu;0;L;03A9 0301;;;;N;GREEK CAPITAL LETTER OMEGA TONOS;;;03CE; 0390;GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS;Ll;0;L;03CA 0301;;;;N;GREEK SMALL LETTER IOTA DIAERESIS TONOS;;;; 0391;GREEK CAPITAL LETTER ALPHA;Lu;0;L;;;;;N;;;;03B1; 0392;GREEK CAPITAL LETTER BETA;Lu;0;L;;;;;N;;;;03B2; 0393;GREEK CAPITAL LETTER GAMMA;Lu;0;L;;;;;N;;;;03B3; 0394;GREEK CAPITAL LETTER DELTA;Lu;0;L;;;;;N;;;;03B4; 0395;GREEK CAPITAL LETTER EPSILON;Lu;0;L;;;;;N;;;;03B5; 0396;GREEK CAPITAL LETTER ZETA;Lu;0;L;;;;;N;;;;03B6; 0397;GREEK CAPITAL LETTER ETA;Lu;0;L;;;;;N;;;;03B7; 0398;GREEK CAPITAL LETTER THETA;Lu;0;L;;;;;N;;;;03B8; 0399;GREEK CAPITAL LETTER IOTA;Lu;0;L;;;;;N;;;;03B9; 039A;GREEK CAPITAL LETTER KAPPA;Lu;0;L;;;;;N;;;;03BA; 039B;GREEK CAPITAL LETTER LAMDA;Lu;0;L;;;;;N;GREEK CAPITAL LETTER LAMBDA;;;03BB; 039C;GREEK CAPITAL LETTER MU;Lu;0;L;;;;;N;;;;03BC; 039D;GREEK CAPITAL LETTER NU;Lu;0;L;;;;;N;;;;03BD; 039E;GREEK CAPITAL LETTER XI;Lu;0;L;;;;;N;;;;03BE; 039F;GREEK CAPITAL LETTER OMICRON;Lu;0;L;;;;;N;;;;03BF; 03A0;GREEK CAPITAL LETTER PI;Lu;0;L;;;;;N;;;;03C0; 03A1;GREEK CAPITAL LETTER RHO;Lu;0;L;;;;;N;;;;03C1; 03A3;GREEK CAPITAL LETTER SIGMA;Lu;0;L;;;;;N;;;;03C3; 03A4;GREEK CAPITAL LETTER TAU;Lu;0;L;;;;;N;;;;03C4; 03A5;GREEK CAPITAL LETTER UPSILON;Lu;0;L;;;;;N;;;;03C5; 03A6;GREEK CAPITAL LETTER PHI;Lu;0;L;;;;;N;;;;03C6; 03A7;GREEK CAPITAL LETTER CHI;Lu;0;L;;;;;N;;;;03C7; 03A8;GREEK CAPITAL LETTER PSI;Lu;0;L;;;;;N;;;;03C8; 03A9;GREEK CAPITAL LETTER OMEGA;Lu;0;L;;;;;N;;;;03C9; 03AA;GREEK CAPITAL LETTER IOTA WITH DIALYTIKA;Lu;0;L;0399 0308;;;;N;GREEK CAPITAL LETTER IOTA DIAERESIS;;;03CA; 03AB;GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA;Lu;0;L;03A5 0308;;;;N;GREEK CAPITAL LETTER UPSILON DIAERESIS;;;03CB; 03AC;GREEK SMALL LETTER ALPHA WITH TONOS;Ll;0;L;03B1 0301;;;;N;GREEK SMALL LETTER ALPHA TONOS;;0386;;0386 03AD;GREEK SMALL LETTER EPSILON WITH TONOS;Ll;0;L;03B5 0301;;;;N;GREEK SMALL LETTER EPSILON TONOS;;0388;;0388 03AE;GREEK SMALL LETTER ETA WITH TONOS;Ll;0;L;03B7 0301;;;;N;GREEK SMALL LETTER ETA TONOS;;0389;;0389 03AF;GREEK SMALL LETTER IOTA WITH TONOS;Ll;0;L;03B9 0301;;;;N;GREEK SMALL LETTER IOTA TONOS;;038A;;038A 03B0;GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS;Ll;0;L;03CB 0301;;;;N;GREEK SMALL LETTER UPSILON DIAERESIS TONOS;;;; 03B1;GREEK SMALL LETTER ALPHA;Ll;0;L;;;;;N;;;0391;;0391 03B2;GREEK SMALL LETTER BETA;Ll;0;L;;;;;N;;;0392;;0392 03B3;GREEK SMALL LETTER GAMMA;Ll;0;L;;;;;N;;;0393;;0393 03B4;GREEK SMALL LETTER DELTA;Ll;0;L;;;;;N;;;0394;;0394 03B5;GREEK SMALL LETTER EPSILON;Ll;0;L;;;;;N;;;0395;;0395 03B6;GREEK SMALL LETTER ZETA;Ll;0;L;;;;;N;;;0396;;0396 03B7;GREEK SMALL LETTER ETA;Ll;0;L;;;;;N;;;0397;;0397 03B8;GREEK SMALL LETTER THETA;Ll;0;L;;;;;N;;;0398;;0398 03B9;GREEK SMALL LETTER IOTA;Ll;0;L;;;;;N;;;0399;;0399 03BA;GREEK SMALL LETTER KAPPA;Ll;0;L;;;;;N;;;039A;;039A 03BB;GREEK SMALL LETTER LAMDA;Ll;0;L;;;;;N;GREEK SMALL LETTER LAMBDA;;039B;;039B 03BC;GREEK SMALL LETTER MU;Ll;0;L;;;;;N;;;039C;;039C 03BD;GREEK SMALL LETTER NU;Ll;0;L;;;;;N;;;039D;;039D 03BE;GREEK SMALL LETTER XI;Ll;0;L;;;;;N;;;039E;;039E 03BF;GREEK SMALL LETTER OMICRON;Ll;0;L;;;;;N;;;039F;;039F 03C0;GREEK SMALL LETTER PI;Ll;0;L;;;;;N;;;03A0;;03A0 03C1;GREEK SMALL LETTER RHO;Ll;0;L;;;;;N;;;03A1;;03A1 03C2;GREEK SMALL LETTER FINAL SIGMA;Ll;0;L;;;;;N;;;03A3;;03A3 03C3;GREEK SMALL LETTER SIGMA;Ll;0;L;;;;;N;;;03A3;;03A3 03C4;GREEK SMALL LETTER TAU;Ll;0;L;;;;;N;;;03A4;;03A4 03C5;GREEK SMALL LETTER UPSILON;Ll;0;L;;;;;N;;;03A5;;03A5 03C6;GREEK SMALL LETTER PHI;Ll;0;L;;;;;N;;;03A6;;03A6 03C7;GREEK SMALL LETTER CHI;Ll;0;L;;;;;N;;;03A7;;03A7 03C8;GREEK SMALL LETTER PSI;Ll;0;L;;;;;N;;;03A8;;03A8 03C9;GREEK SMALL LETTER OMEGA;Ll;0;L;;;;;N;;;03A9;;03A9 03CA;GREEK SMALL LETTER IOTA WITH DIALYTIKA;Ll;0;L;03B9 0308;;;;N;GREEK SMALL LETTER IOTA DIAERESIS;;03AA;;03AA 03CB;GREEK SMALL LETTER UPSILON WITH DIALYTIKA;Ll;0;L;03C5 0308;;;;N;GREEK SMALL LETTER UPSILON DIAERESIS;;03AB;;03AB 03CC;GREEK SMALL LETTER OMICRON WITH TONOS;Ll;0;L;03BF 0301;;;;N;GREEK SMALL LETTER OMICRON TONOS;;038C;;038C 03CD;GREEK SMALL LETTER UPSILON WITH TONOS;Ll;0;L;03C5 0301;;;;N;GREEK SMALL LETTER UPSILON TONOS;;038E;;038E 03CE;GREEK SMALL LETTER OMEGA WITH TONOS;Ll;0;L;03C9 0301;;;;N;GREEK SMALL LETTER OMEGA TONOS;;038F;;038F 03CF;GREEK CAPITAL KAI SYMBOL;Lu;0;L;;;;;N;;;;03D7; 03D0;GREEK BETA SYMBOL;Ll;0;L;<compat> 03B2;;;;N;GREEK SMALL LETTER CURLED BETA;;0392;;0392 03D1;GREEK THETA SYMBOL;Ll;0;L;<compat> 03B8;;;;N;GREEK SMALL LETTER SCRIPT THETA;;0398;;0398 03D2;GREEK UPSILON WITH HOOK SYMBOL;Lu;0;L;<compat> 03A5;;;;N;GREEK CAPITAL LETTER UPSILON HOOK;;;; 03D3;GREEK UPSILON WITH ACUTE AND HOOK SYMBOL;Lu;0;L;03D2 0301;;;;N;GREEK CAPITAL LETTER UPSILON HOOK TONOS;;;; 03D4;GREEK UPSILON WITH DIAERESIS AND HOOK SYMBOL;Lu;0;L;03D2 0308;;;;N;GREEK CAPITAL LETTER UPSILON HOOK DIAERESIS;;;; 03D5;GREEK PHI SYMBOL;Ll;0;L;<compat> 03C6;;;;N;GREEK SMALL LETTER SCRIPT PHI;;03A6;;03A6 03D6;GREEK PI SYMBOL;Ll;0;L;<compat> 03C0;;;;N;GREEK SMALL LETTER OMEGA PI;;03A0;;03A0 03D7;GREEK KAI SYMBOL;Ll;0;L;;;;;N;;;03CF;;03CF 03D8;GREEK LETTER ARCHAIC KOPPA;Lu;0;L;;;;;N;;;;03D9; 03D9;GREEK SMALL LETTER ARCHAIC KOPPA;Ll;0;L;;;;;N;;;03D8;;03D8 03DA;GREEK LETTER STIGMA;Lu;0;L;;;;;N;GREEK CAPITAL LETTER STIGMA;;;03DB; 03DB;GREEK SMALL LETTER STIGMA;Ll;0;L;;;;;N;;;03DA;;03DA 03DC;GREEK LETTER DIGAMMA;Lu;0;L;;;;;N;GREEK CAPITAL LETTER DIGAMMA;;;03DD; 03DD;GREEK SMALL LETTER DIGAMMA;Ll;0;L;;;;;N;;;03DC;;03DC 03DE;GREEK LETTER KOPPA;Lu;0;L;;;;;N;GREEK CAPITAL LETTER KOPPA;;;03DF; 03DF;GREEK SMALL LETTER KOPPA;Ll;0;L;;;;;N;;;03DE;;03DE 03E0;GREEK LETTER SAMPI;Lu;0;L;;;;;N;GREEK CAPITAL LETTER SAMPI;;;03E1; 03E1;GREEK SMALL LETTER SAMPI;Ll;0;L;;;;;N;;;03E0;;03E0 03E2;COPTIC CAPITAL LETTER SHEI;Lu;0;L;;;;;N;GREEK CAPITAL LETTER SHEI;;;03E3; 03E3;COPTIC SMALL LETTER SHEI;Ll;0;L;;;;;N;GREEK SMALL LETTER SHEI;;03E2;;03E2 03E4;COPTIC CAPITAL LETTER FEI;Lu;0;L;;;;;N;GREEK CAPITAL LETTER FEI;;;03E5; 03E5;COPTIC SMALL LETTER FEI;Ll;0;L;;;;;N;GREEK SMALL LETTER FEI;;03E4;;03E4 03E6;COPTIC CAPITAL LETTER KHEI;Lu;0;L;;;;;N;GREEK CAPITAL LETTER KHEI;;;03E7; 03E7;COPTIC SMALL LETTER KHEI;Ll;0;L;;;;;N;GREEK SMALL LETTER KHEI;;03E6;;03E6 03E8;COPTIC CAPITAL LETTER HORI;Lu;0;L;;;;;N;GREEK CAPITAL LETTER HORI;;;03E9; 03E9;COPTIC SMALL LETTER HORI;Ll;0;L;;;;;N;GREEK SMALL LETTER HORI;;03E8;;03E8 03EA;COPTIC CAPITAL LETTER GANGIA;Lu;0;L;;;;;N;GREEK CAPITAL LETTER GANGIA;;;03EB; 03EB;COPTIC SMALL LETTER GANGIA;Ll;0;L;;;;;N;GREEK SMALL LETTER GANGIA;;03EA;;03EA 03EC;COPTIC CAPITAL LETTER SHIMA;Lu;0;L;;;;;N;GREEK CAPITAL LETTER SHIMA;;;03ED; 03ED;COPTIC SMALL LETTER SHIMA;Ll;0;L;;;;;N;GREEK SMALL LETTER SHIMA;;03EC;;03EC 03EE;COPTIC CAPITAL LETTER DEI;Lu;0;L;;;;;N;GREEK CAPITAL LETTER DEI;;;03EF; 03EF;COPTIC SMALL LETTER DEI;Ll;0;L;;;;;N;GREEK SMALL LETTER DEI;;03EE;;03EE 03F0;GREEK KAPPA SYMBOL;Ll;0;L;<compat> 03BA;;;;N;GREEK SMALL LETTER SCRIPT KAPPA;;039A;;039A 03F1;GREEK RHO SYMBOL;Ll;0;L;<compat> 03C1;;;;N;GREEK SMALL LETTER TAILED RHO;;03A1;;03A1 03F2;GREEK LUNATE SIGMA SYMBOL;Ll;0;L;<compat> 03C2;;;;N;GREEK SMALL LETTER LUNATE SIGMA;;03F9;;03F9 03F3;GREEK LETTER YOT;Ll;0;L;;;;;N;;;037F;;037F 03F4;GREEK CAPITAL THETA SYMBOL;Lu;0;L;<compat> 0398;;;;N;;;;03B8; 03F5;GREEK LUNATE EPSILON SYMBOL;Ll;0;L;<compat> 03B5;;;;N;;;0395;;0395 03F6;GREEK REVERSED LUNATE EPSILON SYMBOL;Sm;0;ON;;;;;N;;;;; 03F7;GREEK CAPITAL LETTER SHO;Lu;0;L;;;;;N;;;;03F8; 03F8;GREEK SMALL LETTER SHO;Ll;0;L;;;;;N;;;03F7;;03F7 03F9;GREEK CAPITAL LUNATE SIGMA SYMBOL;Lu;0;L;<compat> 03A3;;;;N;;;;03F2; 03FA;GREEK CAPITAL LETTER SAN;Lu;0;L;;;;;N;;;;03FB; 03FB;GREEK SMALL LETTER SAN;Ll;0;L;;;;;N;;;03FA;;03FA 03FC;GREEK RHO WITH STROKE SYMBOL;Ll;0;L;;;;;N;;;;; 03FD;GREEK CAPITAL REVERSED LUNATE SIGMA SYMBOL;Lu;0;L;;;;;N;;;;037B; 03FE;GREEK CAPITAL DOTTED LUNATE SIGMA SYMBOL;Lu;0;L;;;;;N;;;;037C; 03FF;GREEK CAPITAL REVERSED DOTTED LUNATE SIGMA SYMBOL;Lu;0;L;;;;;N;;;;037D; 0400;CYRILLIC CAPITAL LETTER IE WITH GRAVE;Lu;0;L;0415 0300;;;;N;;;;0450; 0401;CYRILLIC CAPITAL LETTER IO;Lu;0;L;0415 0308;;;;N;;;;0451; 0402;CYRILLIC CAPITAL LETTER DJE;Lu;0;L;;;;;N;;;;0452; 0403;CYRILLIC CAPITAL LETTER GJE;Lu;0;L;0413 0301;;;;N;;;;0453; 0404;CYRILLIC CAPITAL LETTER UKRAINIAN IE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER E;;;0454; 0405;CYRILLIC CAPITAL LETTER DZE;Lu;0;L;;;;;N;;;;0455; 0406;CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER I;;;0456; 0407;CYRILLIC CAPITAL LETTER YI;Lu;0;L;0406 0308;;;;N;;;;0457; 0408;CYRILLIC CAPITAL LETTER JE;Lu;0;L;;;;;N;;;;0458; 0409;CYRILLIC CAPITAL LETTER LJE;Lu;0;L;;;;;N;;;;0459; 040A;CYRILLIC CAPITAL LETTER NJE;Lu;0;L;;;;;N;;;;045A; 040B;CYRILLIC CAPITAL LETTER TSHE;Lu;0;L;;;;;N;;;;045B; 040C;CYRILLIC CAPITAL LETTER KJE;Lu;0;L;041A 0301;;;;N;;;;045C; 040D;CYRILLIC CAPITAL LETTER I WITH GRAVE;Lu;0;L;0418 0300;;;;N;;;;045D; 040E;CYRILLIC CAPITAL LETTER SHORT U;Lu;0;L;0423 0306;;;;N;;;;045E; 040F;CYRILLIC CAPITAL LETTER DZHE;Lu;0;L;;;;;N;;;;045F; 0410;CYRILLIC CAPITAL LETTER A;Lu;0;L;;;;;N;;;;0430; 0411;CYRILLIC CAPITAL LETTER BE;Lu;0;L;;;;;N;;;;0431; 0412;CYRILLIC CAPITAL LETTER VE;Lu;0;L;;;;;N;;;;0432; 0413;CYRILLIC CAPITAL LETTER GHE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER GE;;;0433; 0414;CYRILLIC CAPITAL LETTER DE;Lu;0;L;;;;;N;;;;0434; 0415;CYRILLIC CAPITAL LETTER IE;Lu;0;L;;;;;N;;;;0435; 0416;CYRILLIC CAPITAL LETTER ZHE;Lu;0;L;;;;;N;;;;0436; 0417;CYRILLIC CAPITAL LETTER ZE;Lu;0;L;;;;;N;;;;0437; 0418;CYRILLIC CAPITAL LETTER I;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER II;;;0438; 0419;CYRILLIC CAPITAL LETTER SHORT I;Lu;0;L;0418 0306;;;;N;CYRILLIC CAPITAL LETTER SHORT II;;;0439; 041A;CYRILLIC CAPITAL LETTER KA;Lu;0;L;;;;;N;;;;043A; 041B;CYRILLIC CAPITAL LETTER EL;Lu;0;L;;;;;N;;;;043B; 041C;CYRILLIC CAPITAL LETTER EM;Lu;0;L;;;;;N;;;;043C; 041D;CYRILLIC CAPITAL LETTER EN;Lu;0;L;;;;;N;;;;043D; 041E;CYRILLIC CAPITAL LETTER O;Lu;0;L;;;;;N;;;;043E; 041F;CYRILLIC CAPITAL LETTER PE;Lu;0;L;;;;;N;;;;043F; 0420;CYRILLIC CAPITAL LETTER ER;Lu;0;L;;;;;N;;;;0440; 0421;CYRILLIC CAPITAL LETTER ES;Lu;0;L;;;;;N;;;;0441; 0422;CYRILLIC CAPITAL LETTER TE;Lu;0;L;;;;;N;;;;0442; 0423;CYRILLIC CAPITAL LETTER U;Lu;0;L;;;;;N;;;;0443; 0424;CYRILLIC CAPITAL LETTER EF;Lu;0;L;;;;;N;;;;0444; 0425;CYRILLIC CAPITAL LETTER HA;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER KHA;;;0445; 0426;CYRILLIC CAPITAL LETTER TSE;Lu;0;L;;;;;N;;;;0446; 0427;CYRILLIC CAPITAL LETTER CHE;Lu;0;L;;;;;N;;;;0447; 0428;CYRILLIC CAPITAL LETTER SHA;Lu;0;L;;;;;N;;;;0448; 0429;CYRILLIC CAPITAL LETTER SHCHA;Lu;0;L;;;;;N;;;;0449; 042A;CYRILLIC CAPITAL LETTER HARD SIGN;Lu;0;L;;;;;N;;;;044A; 042B;CYRILLIC CAPITAL LETTER YERU;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER YERI;;;044B; 042C;CYRILLIC CAPITAL LETTER SOFT SIGN;Lu;0;L;;;;;N;;;;044C; 042D;CYRILLIC CAPITAL LETTER E;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER REVERSED E;;;044D; 042E;CYRILLIC CAPITAL LETTER YU;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER IU;;;044E; 042F;CYRILLIC CAPITAL LETTER YA;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER IA;;;044F; 0430;CYRILLIC SMALL LETTER A;Ll;0;L;;;;;N;;;0410;;0410 0431;CYRILLIC SMALL LETTER BE;Ll;0;L;;;;;N;;;0411;;0411 0432;CYRILLIC SMALL LETTER VE;Ll;0;L;;;;;N;;;0412;;0412 0433;CYRILLIC SMALL LETTER GHE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER GE;;0413;;0413 0434;CYRILLIC SMALL LETTER DE;Ll;0;L;;;;;N;;;0414;;0414 0435;CYRILLIC SMALL LETTER IE;Ll;0;L;;;;;N;;;0415;;0415 0436;CYRILLIC SMALL LETTER ZHE;Ll;0;L;;;;;N;;;0416;;0416 0437;CYRILLIC SMALL LETTER ZE;Ll;0;L;;;;;N;;;0417;;0417 0438;CYRILLIC SMALL LETTER I;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER II;;0418;;0418 0439;CYRILLIC SMALL LETTER SHORT I;Ll;0;L;0438 0306;;;;N;CYRILLIC SMALL LETTER SHORT II;;0419;;0419 043A;CYRILLIC SMALL LETTER KA;Ll;0;L;;;;;N;;;041A;;041A 043B;CYRILLIC SMALL LETTER EL;Ll;0;L;;;;;N;;;041B;;041B 043C;CYRILLIC SMALL LETTER EM;Ll;0;L;;;;;N;;;041C;;041C 043D;CYRILLIC SMALL LETTER EN;Ll;0;L;;;;;N;;;041D;;041D 043E;CYRILLIC SMALL LETTER O;Ll;0;L;;;;;N;;;041E;;041E 043F;CYRILLIC SMALL LETTER PE;Ll;0;L;;;;;N;;;041F;;041F 0440;CYRILLIC SMALL LETTER ER;Ll;0;L;;;;;N;;;0420;;0420 0441;CYRILLIC SMALL LETTER ES;Ll;0;L;;;;;N;;;0421;;0421 0442;CYRILLIC SMALL LETTER TE;Ll;0;L;;;;;N;;;0422;;0422 0443;CYRILLIC SMALL LETTER U;Ll;0;L;;;;;N;;;0423;;0423 0444;CYRILLIC SMALL LETTER EF;Ll;0;L;;;;;N;;;0424;;0424 0445;CYRILLIC SMALL LETTER HA;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER KHA;;0425;;0425 0446;CYRILLIC SMALL LETTER TSE;Ll;0;L;;;;;N;;;0426;;0426 0447;CYRILLIC SMALL LETTER CHE;Ll;0;L;;;;;N;;;0427;;0427 0448;CYRILLIC SMALL LETTER SHA;Ll;0;L;;;;;N;;;0428;;0428 0449;CYRILLIC SMALL LETTER SHCHA;Ll;0;L;;;;;N;;;0429;;0429 044A;CYRILLIC SMALL LETTER HARD SIGN;Ll;0;L;;;;;N;;;042A;;042A 044B;CYRILLIC SMALL LETTER YERU;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER YERI;;042B;;042B 044C;CYRILLIC SMALL LETTER SOFT SIGN;Ll;0;L;;;;;N;;;042C;;042C 044D;CYRILLIC SMALL LETTER E;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER REVERSED E;;042D;;042D 044E;CYRILLIC SMALL LETTER YU;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER IU;;042E;;042E 044F;CYRILLIC SMALL LETTER YA;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER IA;;042F;;042F 0450;CYRILLIC SMALL LETTER IE WITH GRAVE;Ll;0;L;0435 0300;;;;N;;;0400;;0400 0451;CYRILLIC SMALL LETTER IO;Ll;0;L;0435 0308;;;;N;;;0401;;0401 0452;CYRILLIC SMALL LETTER DJE;Ll;0;L;;;;;N;;;0402;;0402 0453;CYRILLIC SMALL LETTER GJE;Ll;0;L;0433 0301;;;;N;;;0403;;0403 0454;CYRILLIC SMALL LETTER UKRAINIAN IE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER E;;0404;;0404 0455;CYRILLIC SMALL LETTER DZE;Ll;0;L;;;;;N;;;0405;;0405 0456;CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER I;;0406;;0406 0457;CYRILLIC SMALL LETTER YI;Ll;0;L;0456 0308;;;;N;;;0407;;0407 0458;CYRILLIC SMALL LETTER JE;Ll;0;L;;;;;N;;;0408;;0408 0459;CYRILLIC SMALL LETTER LJE;Ll;0;L;;;;;N;;;0409;;0409 045A;CYRILLIC SMALL LETTER NJE;Ll;0;L;;;;;N;;;040A;;040A 045B;CYRILLIC SMALL LETTER TSHE;Ll;0;L;;;;;N;;;040B;;040B 045C;CYRILLIC SMALL LETTER KJE;Ll;0;L;043A 0301;;;;N;;;040C;;040C 045D;CYRILLIC SMALL LETTER I WITH GRAVE;Ll;0;L;0438 0300;;;;N;;;040D;;040D 045E;CYRILLIC SMALL LETTER SHORT U;Ll;0;L;0443 0306;;;;N;;;040E;;040E 045F;CYRILLIC SMALL LETTER DZHE;Ll;0;L;;;;;N;;;040F;;040F 0460;CYRILLIC CAPITAL LETTER OMEGA;Lu;0;L;;;;;N;;;;0461; 0461;CYRILLIC SMALL LETTER OMEGA;Ll;0;L;;;;;N;;;0460;;0460 0462;CYRILLIC CAPITAL LETTER YAT;Lu;0;L;;;;;N;;;;0463; 0463;CYRILLIC SMALL LETTER YAT;Ll;0;L;;;;;N;;;0462;;0462 0464;CYRILLIC CAPITAL LETTER IOTIFIED E;Lu;0;L;;;;;N;;;;0465; 0465;CYRILLIC SMALL LETTER IOTIFIED E;Ll;0;L;;;;;N;;;0464;;0464 0466;CYRILLIC CAPITAL LETTER LITTLE YUS;Lu;0;L;;;;;N;;;;0467; 0467;CYRILLIC SMALL LETTER LITTLE YUS;Ll;0;L;;;;;N;;;0466;;0466 0468;CYRILLIC CAPITAL LETTER IOTIFIED LITTLE YUS;Lu;0;L;;;;;N;;;;0469; 0469;CYRILLIC SMALL LETTER IOTIFIED LITTLE YUS;Ll;0;L;;;;;N;;;0468;;0468 046A;CYRILLIC CAPITAL LETTER BIG YUS;Lu;0;L;;;;;N;;;;046B; 046B;CYRILLIC SMALL LETTER BIG YUS;Ll;0;L;;;;;N;;;046A;;046A 046C;CYRILLIC CAPITAL LETTER IOTIFIED BIG YUS;Lu;0;L;;;;;N;;;;046D; 046D;CYRILLIC SMALL LETTER IOTIFIED BIG YUS;Ll;0;L;;;;;N;;;046C;;046C 046E;CYRILLIC CAPITAL LETTER KSI;Lu;0;L;;;;;N;;;;046F; 046F;CYRILLIC SMALL LETTER KSI;Ll;0;L;;;;;N;;;046E;;046E 0470;CYRILLIC CAPITAL LETTER PSI;Lu;0;L;;;;;N;;;;0471; 0471;CYRILLIC SMALL LETTER PSI;Ll;0;L;;;;;N;;;0470;;0470 0472;CYRILLIC CAPITAL LETTER FITA;Lu;0;L;;;;;N;;;;0473; 0473;CYRILLIC SMALL LETTER FITA;Ll;0;L;;;;;N;;;0472;;0472 0474;CYRILLIC CAPITAL LETTER IZHITSA;Lu;0;L;;;;;N;;;;0475; 0475;CYRILLIC SMALL LETTER IZHITSA;Ll;0;L;;;;;N;;;0474;;0474 0476;CYRILLIC CAPITAL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT;Lu;0;L;0474 030F;;;;N;CYRILLIC CAPITAL LETTER IZHITSA DOUBLE GRAVE;;;0477; 0477;CYRILLIC SMALL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT;Ll;0;L;0475 030F;;;;N;CYRILLIC SMALL LETTER IZHITSA DOUBLE GRAVE;;0476;;0476 0478;CYRILLIC CAPITAL LETTER UK;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER UK DIGRAPH;;;0479; 0479;CYRILLIC SMALL LETTER UK;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER UK DIGRAPH;;0478;;0478 047A;CYRILLIC CAPITAL LETTER ROUND OMEGA;Lu;0;L;;;;;N;;;;047B; 047B;CYRILLIC SMALL LETTER ROUND OMEGA;Ll;0;L;;;;;N;;;047A;;047A 047C;CYRILLIC CAPITAL LETTER OMEGA WITH TITLO;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER OMEGA TITLO;;;047D; 047D;CYRILLIC SMALL LETTER OMEGA WITH TITLO;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER OMEGA TITLO;;047C;;047C 047E;CYRILLIC CAPITAL LETTER OT;Lu;0;L;;;;;N;;;;047F; 047F;CYRILLIC SMALL LETTER OT;Ll;0;L;;;;;N;;;047E;;047E 0480;CYRILLIC CAPITAL LETTER KOPPA;Lu;0;L;;;;;N;;;;0481; 0481;CYRILLIC SMALL LETTER KOPPA;Ll;0;L;;;;;N;;;0480;;0480 0482;CYRILLIC THOUSANDS SIGN;So;0;L;;;;;N;;;;; 0483;COMBINING CYRILLIC TITLO;Mn;230;NSM;;;;;N;CYRILLIC NON-SPACING TITLO;;;; 0484;COMBINING CYRILLIC PALATALIZATION;Mn;230;NSM;;;;;N;CYRILLIC NON-SPACING PALATALIZATION;;;; 0485;COMBINING CYRILLIC DASIA PNEUMATA;Mn;230;NSM;;;;;N;CYRILLIC NON-SPACING DASIA PNEUMATA;;;; 0486;COMBINING CYRILLIC PSILI PNEUMATA;Mn;230;NSM;;;;;N;CYRILLIC NON-SPACING PSILI PNEUMATA;;;; 0487;COMBINING CYRILLIC POKRYTIE;Mn;230;NSM;;;;;N;;;;; 0488;COMBINING CYRILLIC HUNDRED THOUSANDS SIGN;Me;0;NSM;;;;;N;;;;; 0489;COMBINING CYRILLIC MILLIONS SIGN;Me;0;NSM;;;;;N;;;;; 048A;CYRILLIC CAPITAL LETTER SHORT I WITH TAIL;Lu;0;L;;;;;N;;;;048B; 048B;CYRILLIC SMALL LETTER SHORT I WITH TAIL;Ll;0;L;;;;;N;;;048A;;048A 048C;CYRILLIC CAPITAL LETTER SEMISOFT SIGN;Lu;0;L;;;;;N;;;;048D; 048D;CYRILLIC SMALL LETTER SEMISOFT SIGN;Ll;0;L;;;;;N;;;048C;;048C 048E;CYRILLIC CAPITAL LETTER ER WITH TICK;Lu;0;L;;;;;N;;;;048F; 048F;CYRILLIC SMALL LETTER ER WITH TICK;Ll;0;L;;;;;N;;;048E;;048E 0490;CYRILLIC CAPITAL LETTER GHE WITH UPTURN;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER GE WITH UPTURN;;;0491; 0491;CYRILLIC SMALL LETTER GHE WITH UPTURN;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER GE WITH UPTURN;;0490;;0490 0492;CYRILLIC CAPITAL LETTER GHE WITH STROKE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER GE BAR;;;0493; 0493;CYRILLIC SMALL LETTER GHE WITH STROKE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER GE BAR;;0492;;0492 0494;CYRILLIC CAPITAL LETTER GHE WITH MIDDLE HOOK;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER GE HOOK;;;0495; 0495;CYRILLIC SMALL LETTER GHE WITH MIDDLE HOOK;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER GE HOOK;;0494;;0494 0496;CYRILLIC CAPITAL LETTER ZHE WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER ZHE WITH RIGHT DESCENDER;;;0497; 0497;CYRILLIC SMALL LETTER ZHE WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER ZHE WITH RIGHT DESCENDER;;0496;;0496 0498;CYRILLIC CAPITAL LETTER ZE WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER ZE CEDILLA;;;0499; 0499;CYRILLIC SMALL LETTER ZE WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER ZE CEDILLA;;0498;;0498 049A;CYRILLIC CAPITAL LETTER KA WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER KA WITH RIGHT DESCENDER;;;049B; 049B;CYRILLIC SMALL LETTER KA WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER KA WITH RIGHT DESCENDER;;049A;;049A 049C;CYRILLIC CAPITAL LETTER KA WITH VERTICAL STROKE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER KA VERTICAL BAR;;;049D; 049D;CYRILLIC SMALL LETTER KA WITH VERTICAL STROKE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER KA VERTICAL BAR;;049C;;049C 049E;CYRILLIC CAPITAL LETTER KA WITH STROKE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER KA BAR;;;049F; 049F;CYRILLIC SMALL LETTER KA WITH STROKE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER KA BAR;;049E;;049E 04A0;CYRILLIC CAPITAL LETTER BASHKIR KA;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER REVERSED GE KA;;;04A1; 04A1;CYRILLIC SMALL LETTER BASHKIR KA;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER REVERSED GE KA;;04A0;;04A0 04A2;CYRILLIC CAPITAL LETTER EN WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER EN WITH RIGHT DESCENDER;;;04A3; 04A3;CYRILLIC SMALL LETTER EN WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER EN WITH RIGHT DESCENDER;;04A2;;04A2 04A4;CYRILLIC CAPITAL LIGATURE EN GHE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER EN GE;;;04A5; 04A5;CYRILLIC SMALL LIGATURE EN GHE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER EN GE;;04A4;;04A4 04A6;CYRILLIC CAPITAL LETTER PE WITH MIDDLE HOOK;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER PE HOOK;;;04A7; 04A7;CYRILLIC SMALL LETTER PE WITH MIDDLE HOOK;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER PE HOOK;;04A6;;04A6 04A8;CYRILLIC CAPITAL LETTER ABKHASIAN HA;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER O HOOK;;;04A9; 04A9;CYRILLIC SMALL LETTER ABKHASIAN HA;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER O HOOK;;04A8;;04A8 04AA;CYRILLIC CAPITAL LETTER ES WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER ES CEDILLA;;;04AB; 04AB;CYRILLIC SMALL LETTER ES WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER ES CEDILLA;;04AA;;04AA 04AC;CYRILLIC CAPITAL LETTER TE WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER TE WITH RIGHT DESCENDER;;;04AD; 04AD;CYRILLIC SMALL LETTER TE WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER TE WITH RIGHT DESCENDER;;04AC;;04AC 04AE;CYRILLIC CAPITAL LETTER STRAIGHT U;Lu;0;L;;;;;N;;;;04AF; 04AF;CYRILLIC SMALL LETTER STRAIGHT U;Ll;0;L;;;;;N;;;04AE;;04AE 04B0;CYRILLIC CAPITAL LETTER STRAIGHT U WITH STROKE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER STRAIGHT U BAR;;;04B1; 04B1;CYRILLIC SMALL LETTER STRAIGHT U WITH STROKE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER STRAIGHT U BAR;;04B0;;04B0 04B2;CYRILLIC CAPITAL LETTER HA WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER KHA WITH RIGHT DESCENDER;;;04B3; 04B3;CYRILLIC SMALL LETTER HA WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER KHA WITH RIGHT DESCENDER;;04B2;;04B2 04B4;CYRILLIC CAPITAL LIGATURE TE TSE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER TE TSE;;;04B5; 04B5;CYRILLIC SMALL LIGATURE TE TSE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER TE TSE;;04B4;;04B4 04B6;CYRILLIC CAPITAL LETTER CHE WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER CHE WITH RIGHT DESCENDER;;;04B7; 04B7;CYRILLIC SMALL LETTER CHE WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER CHE WITH RIGHT DESCENDER;;04B6;;04B6 04B8;CYRILLIC CAPITAL LETTER CHE WITH VERTICAL STROKE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER CHE VERTICAL BAR;;;04B9; 04B9;CYRILLIC SMALL LETTER CHE WITH VERTICAL STROKE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER CHE VERTICAL BAR;;04B8;;04B8 04BA;CYRILLIC CAPITAL LETTER SHHA;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER H;;;04BB; 04BB;CYRILLIC SMALL LETTER SHHA;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER H;;04BA;;04BA 04BC;CYRILLIC CAPITAL LETTER ABKHASIAN CHE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER IE HOOK;;;04BD; 04BD;CYRILLIC SMALL LETTER ABKHASIAN CHE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER IE HOOK;;04BC;;04BC 04BE;CYRILLIC CAPITAL LETTER ABKHASIAN CHE WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER IE HOOK OGONEK;;;04BF; 04BF;CYRILLIC SMALL LETTER ABKHASIAN CHE WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER IE HOOK OGONEK;;04BE;;04BE 04C0;CYRILLIC LETTER PALOCHKA;Lu;0;L;;;;;N;CYRILLIC LETTER I;;;04CF; 04C1;CYRILLIC CAPITAL LETTER ZHE WITH BREVE;Lu;0;L;0416 0306;;;;N;CYRILLIC CAPITAL LETTER SHORT ZHE;;;04C2; 04C2;CYRILLIC SMALL LETTER ZHE WITH BREVE;Ll;0;L;0436 0306;;;;N;CYRILLIC SMALL LETTER SHORT ZHE;;04C1;;04C1 04C3;CYRILLIC CAPITAL LETTER KA WITH HOOK;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER KA HOOK;;;04C4; 04C4;CYRILLIC SMALL LETTER KA WITH HOOK;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER KA HOOK;;04C3;;04C3 04C5;CYRILLIC CAPITAL LETTER EL WITH TAIL;Lu;0;L;;;;;N;;;;04C6; 04C6;CYRILLIC SMALL LETTER EL WITH TAIL;Ll;0;L;;;;;N;;;04C5;;04C5 04C7;CYRILLIC CAPITAL LETTER EN WITH HOOK;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER EN HOOK;;;04C8; 04C8;CYRILLIC SMALL LETTER EN WITH HOOK;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER EN HOOK;;04C7;;04C7 04C9;CYRILLIC CAPITAL LETTER EN WITH TAIL;Lu;0;L;;;;;N;;;;04CA; 04CA;CYRILLIC SMALL LETTER EN WITH TAIL;Ll;0;L;;;;;N;;;04C9;;04C9 04CB;CYRILLIC CAPITAL LETTER KHAKASSIAN CHE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER CHE WITH LEFT DESCENDER;;;04CC; 04CC;CYRILLIC SMALL LETTER KHAKASSIAN CHE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER CHE WITH LEFT DESCENDER;;04CB;;04CB 04CD;CYRILLIC CAPITAL LETTER EM WITH TAIL;Lu;0;L;;;;;N;;;;04CE; 04CE;CYRILLIC SMALL LETTER EM WITH TAIL;Ll;0;L;;;;;N;;;04CD;;04CD 04CF;CYRILLIC SMALL LETTER PALOCHKA;Ll;0;L;;;;;N;;;04C0;;04C0 04D0;CYRILLIC CAPITAL LETTER A WITH BREVE;Lu;0;L;0410 0306;;;;N;;;;04D1; 04D1;CYRILLIC SMALL LETTER A WITH BREVE;Ll;0;L;0430 0306;;;;N;;;04D0;;04D0 04D2;CYRILLIC CAPITAL LETTER A WITH DIAERESIS;Lu;0;L;0410 0308;;;;N;;;;04D3; 04D3;CYRILLIC SMALL LETTER A WITH DIAERESIS;Ll;0;L;0430 0308;;;;N;;;04D2;;04D2 04D4;CYRILLIC CAPITAL LIGATURE A IE;Lu;0;L;;;;;N;;;;04D5; 04D5;CYRILLIC SMALL LIGATURE A IE;Ll;0;L;;;;;N;;;04D4;;04D4 04D6;CYRILLIC CAPITAL LETTER IE WITH BREVE;Lu;0;L;0415 0306;;;;N;;;;04D7; 04D7;CYRILLIC SMALL LETTER IE WITH BREVE;Ll;0;L;0435 0306;;;;N;;;04D6;;04D6 04D8;CYRILLIC CAPITAL LETTER SCHWA;Lu;0;L;;;;;N;;;;04D9; 04D9;CYRILLIC SMALL LETTER SCHWA;Ll;0;L;;;;;N;;;04D8;;04D8 04DA;CYRILLIC CAPITAL LETTER SCHWA WITH DIAERESIS;Lu;0;L;04D8 0308;;;;N;;;;04DB; 04DB;CYRILLIC SMALL LETTER SCHWA WITH DIAERESIS;Ll;0;L;04D9 0308;;;;N;;;04DA;;04DA 04DC;CYRILLIC CAPITAL LETTER ZHE WITH DIAERESIS;Lu;0;L;0416 0308;;;;N;;;;04DD; 04DD;CYRILLIC SMALL LETTER ZHE WITH DIAERESIS;Ll;0;L;0436 0308;;;;N;;;04DC;;04DC 04DE;CYRILLIC CAPITAL LETTER ZE WITH DIAERESIS;Lu;0;L;0417 0308;;;;N;;;;04DF; 04DF;CYRILLIC SMALL LETTER ZE WITH DIAERESIS;Ll;0;L;0437 0308;;;;N;;;04DE;;04DE 04E0;CYRILLIC CAPITAL LETTER ABKHASIAN DZE;Lu;0;L;;;;;N;;;;04E1; 04E1;CYRILLIC SMALL LETTER ABKHASIAN DZE;Ll;0;L;;;;;N;;;04E0;;04E0 04E2;CYRILLIC CAPITAL LETTER I WITH MACRON;Lu;0;L;0418 0304;;;;N;;;;04E3; 04E3;CYRILLIC SMALL LETTER I WITH MACRON;Ll;0;L;0438 0304;;;;N;;;04E2;;04E2 04E4;CYRILLIC CAPITAL LETTER I WITH DIAERESIS;Lu;0;L;0418 0308;;;;N;;;;04E5; 04E5;CYRILLIC SMALL LETTER I WITH DIAERESIS;Ll;0;L;0438 0308;;;;N;;;04E4;;04E4 04E6;CYRILLIC CAPITAL LETTER O WITH DIAERESIS;Lu;0;L;041E 0308;;;;N;;;;04E7; 04E7;CYRILLIC SMALL LETTER O WITH DIAERESIS;Ll;0;L;043E 0308;;;;N;;;04E6;;04E6 04E8;CYRILLIC CAPITAL LETTER BARRED O;Lu;0;L;;;;;N;;;;04E9; 04E9;CYRILLIC SMALL LETTER BARRED O;Ll;0;L;;;;;N;;;04E8;;04E8 04EA;CYRILLIC CAPITAL LETTER BARRED O WITH DIAERESIS;Lu;0;L;04E8 0308;;;;N;;;;04EB; 04EB;CYRILLIC SMALL LETTER BARRED O WITH DIAERESIS;Ll;0;L;04E9 0308;;;;N;;;04EA;;04EA 04EC;CYRILLIC CAPITAL LETTER E WITH DIAERESIS;Lu;0;L;042D 0308;;;;N;;;;04ED; 04ED;CYRILLIC SMALL LETTER E WITH DIAERESIS;Ll;0;L;044D 0308;;;;N;;;04EC;;04EC 04EE;CYRILLIC CAPITAL LETTER U WITH MACRON;Lu;0;L;0423 0304;;;;N;;;;04EF; 04EF;CYRILLIC SMALL LETTER U WITH MACRON;Ll;0;L;0443 0304;;;;N;;;04EE;;04EE 04F0;CYRILLIC CAPITAL LETTER U WITH DIAERESIS;Lu;0;L;0423 0308;;;;N;;;;04F1; 04F1;CYRILLIC SMALL LETTER U WITH DIAERESIS;Ll;0;L;0443 0308;;;;N;;;04F0;;04F0 04F2;CYRILLIC CAPITAL LETTER U WITH DOUBLE ACUTE;Lu;0;L;0423 030B;;;;N;;;;04F3; 04F3;CYRILLIC SMALL LETTER U WITH DOUBLE ACUTE;Ll;0;L;0443 030B;;;;N;;;04F2;;04F2 04F4;CYRILLIC CAPITAL LETTER CHE WITH DIAERESIS;Lu;0;L;0427 0308;;;;N;;;;04F5; 04F5;CYRILLIC SMALL LETTER CHE WITH DIAERESIS;Ll;0;L;0447 0308;;;;N;;;04F4;;04F4 04F6;CYRILLIC CAPITAL LETTER GHE WITH DESCENDER;Lu;0;L;;;;;N;;;;04F7; 04F7;CYRILLIC SMALL LETTER GHE WITH DESCENDER;Ll;0;L;;;;;N;;;04F6;;04F6 04F8;CYRILLIC CAPITAL LETTER YERU WITH DIAERESIS;Lu;0;L;042B 0308;;;;N;;;;04F9; 04F9;CYRILLIC SMALL LETTER YERU WITH DIAERESIS;Ll;0;L;044B 0308;;;;N;;;04F8;;04F8 04FA;CYRILLIC CAPITAL LETTER GHE WITH STROKE AND HOOK;Lu;0;L;;;;;N;;;;04FB; 04FB;CYRILLIC SMALL LETTER GHE WITH STROKE AND HOOK;Ll;0;L;;;;;N;;;04FA;;04FA 04FC;CYRILLIC CAPITAL LETTER HA WITH HOOK;Lu;0;L;;;;;N;;;;04FD; 04FD;CYRILLIC SMALL LETTER HA WITH HOOK;Ll;0;L;;;;;N;;;04FC;;04FC 04FE;CYRILLIC CAPITAL LETTER HA WITH STROKE;Lu;0;L;;;;;N;;;;04FF; 04FF;CYRILLIC SMALL LETTER HA WITH STROKE;Ll;0;L;;;;;N;;;04FE;;04FE 0500;CYRILLIC CAPITAL LETTER KOMI DE;Lu;0;L;;;;;N;;;;0501; 0501;CYRILLIC SMALL LETTER KOMI DE;Ll;0;L;;;;;N;;;0500;;0500 0502;CYRILLIC CAPITAL LETTER KOMI DJE;Lu;0;L;;;;;N;;;;0503; 0503;CYRILLIC SMALL LETTER KOMI DJE;Ll;0;L;;;;;N;;;0502;;0502 0504;CYRILLIC CAPITAL LETTER KOMI ZJE;Lu;0;L;;;;;N;;;;0505; 0505;CYRILLIC SMALL LETTER KOMI ZJE;Ll;0;L;;;;;N;;;0504;;0504 0506;CYRILLIC CAPITAL LETTER KOMI DZJE;Lu;0;L;;;;;N;;;;0507; 0507;CYRILLIC SMALL LETTER KOMI DZJE;Ll;0;L;;;;;N;;;0506;;0506 0508;CYRILLIC CAPITAL LETTER KOMI LJE;Lu;0;L;;;;;N;;;;0509; 0509;CYRILLIC SMALL LETTER KOMI LJE;Ll;0;L;;;;;N;;;0508;;0508 050A;CYRILLIC CAPITAL LETTER KOMI NJE;Lu;0;L;;;;;N;;;;050B; 050B;CYRILLIC SMALL LETTER KOMI NJE;Ll;0;L;;;;;N;;;050A;;050A 050C;CYRILLIC CAPITAL LETTER KOMI SJE;Lu;0;L;;;;;N;;;;050D; 050D;CYRILLIC SMALL LETTER KOMI SJE;Ll;0;L;;;;;N;;;050C;;050C 050E;CYRILLIC CAPITAL LETTER KOMI TJE;Lu;0;L;;;;;N;;;;050F; 050F;CYRILLIC SMALL LETTER KOMI TJE;Ll;0;L;;;;;N;;;050E;;050E 0510;CYRILLIC CAPITAL LETTER REVERSED ZE;Lu;0;L;;;;;N;;;;0511; 0511;CYRILLIC SMALL LETTER REVERSED ZE;Ll;0;L;;;;;N;;;0510;;0510 0512;CYRILLIC CAPITAL LETTER EL WITH HOOK;Lu;0;L;;;;;N;;;;0513; 0513;CYRILLIC SMALL LETTER EL WITH HOOK;Ll;0;L;;;;;N;;;0512;;0512 0514;CYRILLIC CAPITAL LETTER LHA;Lu;0;L;;;;;N;;;;0515; 0515;CYRILLIC SMALL LETTER LHA;Ll;0;L;;;;;N;;;0514;;0514 0516;CYRILLIC CAPITAL LETTER RHA;Lu;0;L;;;;;N;;;;0517; 0517;CYRILLIC SMALL LETTER RHA;Ll;0;L;;;;;N;;;0516;;0516 0518;CYRILLIC CAPITAL LETTER YAE;Lu;0;L;;;;;N;;;;0519; 0519;CYRILLIC SMALL LETTER YAE;Ll;0;L;;;;;N;;;0518;;0518 051A;CYRILLIC CAPITAL LETTER QA;Lu;0;L;;;;;N;;;;051B; 051B;CYRILLIC SMALL LETTER QA;Ll;0;L;;;;;N;;;051A;;051A 051C;CYRILLIC CAPITAL LETTER WE;Lu;0;L;;;;;N;;;;051D; 051D;CYRILLIC SMALL LETTER WE;Ll;0;L;;;;;N;;;051C;;051C 051E;CYRILLIC CAPITAL LETTER ALEUT KA;Lu;0;L;;;;;N;;;;051F; 051F;CYRILLIC SMALL LETTER ALEUT KA;Ll;0;L;;;;;N;;;051E;;051E 0520;CYRILLIC CAPITAL LETTER EL WITH MIDDLE HOOK;Lu;0;L;;;;;N;;;;0521; 0521;CYRILLIC SMALL LETTER EL WITH MIDDLE HOOK;Ll;0;L;;;;;N;;;0520;;0520 0522;CYRILLIC CAPITAL LETTER EN WITH MIDDLE HOOK;Lu;0;L;;;;;N;;;;0523; 0523;CYRILLIC SMALL LETTER EN WITH MIDDLE HOOK;Ll;0;L;;;;;N;;;0522;;0522 0524;CYRILLIC CAPITAL LETTER PE WITH DESCENDER;Lu;0;L;;;;;N;;;;0525; 0525;CYRILLIC SMALL LETTER PE WITH DESCENDER;Ll;0;L;;;;;N;;;0524;;0524 0526;CYRILLIC CAPITAL LETTER SHHA WITH DESCENDER;Lu;0;L;;;;;N;;;;0527; 0527;CYRILLIC SMALL LETTER SHHA WITH DESCENDER;Ll;0;L;;;;;N;;;0526;;0526 0528;CYRILLIC CAPITAL LETTER EN WITH LEFT HOOK;Lu;0;L;;;;;N;;;;0529; 0529;CYRILLIC SMALL LETTER EN WITH LEFT HOOK;Ll;0;L;;;;;N;;;0528;;0528 052A;CYRILLIC CAPITAL LETTER DZZHE;Lu;0;L;;;;;N;;;;052B; 052B;CYRILLIC SMALL LETTER DZZHE;Ll;0;L;;;;;N;;;052A;;052A 052C;CYRILLIC CAPITAL LETTER DCHE;Lu;0;L;;;;;N;;;;052D; 052D;CYRILLIC SMALL LETTER DCHE;Ll;0;L;;;;;N;;;052C;;052C 052E;CYRILLIC CAPITAL LETTER EL WITH DESCENDER;Lu;0;L;;;;;N;;;;052F; 052F;CYRILLIC SMALL LETTER EL WITH DESCENDER;Ll;0;L;;;;;N;;;052E;;052E 0531;ARMENIAN CAPITAL LETTER AYB;Lu;0;L;;;;;N;;;;0561; 0532;ARMENIAN CAPITAL LETTER BEN;Lu;0;L;;;;;N;;;;0562; 0533;ARMENIAN CAPITAL LETTER GIM;Lu;0;L;;;;;N;;;;0563; 0534;ARMENIAN CAPITAL LETTER DA;Lu;0;L;;;;;N;;;;0564; 0535;ARMENIAN CAPITAL LETTER ECH;Lu;0;L;;;;;N;;;;0565; 0536;ARMENIAN CAPITAL LETTER ZA;Lu;0;L;;;;;N;;;;0566; 0537;ARMENIAN CAPITAL LETTER EH;Lu;0;L;;;;;N;;;;0567; 0538;ARMENIAN CAPITAL LETTER ET;Lu;0;L;;;;;N;;;;0568; 0539;ARMENIAN CAPITAL LETTER TO;Lu;0;L;;;;;N;;;;0569; 053A;ARMENIAN CAPITAL LETTER ZHE;Lu;0;L;;;;;N;;;;056A; 053B;ARMENIAN CAPITAL LETTER INI;Lu;0;L;;;;;N;;;;056B; 053C;ARMENIAN CAPITAL LETTER LIWN;Lu;0;L;;;;;N;;;;056C; 053D;ARMENIAN CAPITAL LETTER XEH;Lu;0;L;;;;;N;;;;056D; 053E;ARMENIAN CAPITAL LETTER CA;Lu;0;L;;;;;N;;;;056E; 053F;ARMENIAN CAPITAL LETTER KEN;Lu;0;L;;;;;N;;;;056F; 0540;ARMENIAN CAPITAL LETTER HO;Lu;0;L;;;;;N;;;;0570; 0541;ARMENIAN CAPITAL LETTER JA;Lu;0;L;;;;;N;;;;0571; 0542;ARMENIAN CAPITAL LETTER GHAD;Lu;0;L;;;;;N;ARMENIAN CAPITAL LETTER LAD;;;0572; 0543;ARMENIAN CAPITAL LETTER CHEH;Lu;0;L;;;;;N;;;;0573; 0544;ARMENIAN CAPITAL LETTER MEN;Lu;0;L;;;;;N;;;;0574; 0545;ARMENIAN CAPITAL LETTER YI;Lu;0;L;;;;;N;;;;0575; 0546;ARMENIAN CAPITAL LETTER NOW;Lu;0;L;;;;;N;;;;0576; 0547;ARMENIAN CAPITAL LETTER SHA;Lu;0;L;;;;;N;;;;0577; 0548;ARMENIAN CAPITAL LETTER VO;Lu;0;L;;;;;N;;;;0578; 0549;ARMENIAN CAPITAL LETTER CHA;Lu;0;L;;;;;N;;;;0579; 054A;ARMENIAN CAPITAL LETTER PEH;Lu;0;L;;;;;N;;;;057A; 054B;ARMENIAN CAPITAL LETTER JHEH;Lu;0;L;;;;;N;;;;057B; 054C;ARMENIAN CAPITAL LETTER RA;Lu;0;L;;;;;N;;;;057C; 054D;ARMENIAN CAPITAL LETTER SEH;Lu;0;L;;;;;N;;;;057D; 054E;ARMENIAN CAPITAL LETTER VEW;Lu;0;L;;;;;N;;;;057E; 054F;ARMENIAN CAPITAL LETTER TIWN;Lu;0;L;;;;;N;;;;057F; 0550;ARMENIAN CAPITAL LETTER REH;Lu;0;L;;;;;N;;;;0580; 0551;ARMENIAN CAPITAL LETTER CO;Lu;0;L;;;;;N;;;;0581; 0552;ARMENIAN CAPITAL LETTER YIWN;Lu;0;L;;;;;N;;;;0582; 0553;ARMENIAN CAPITAL LETTER PIWR;Lu;0;L;;;;;N;;;;0583; 0554;ARMENIAN CAPITAL LETTER KEH;Lu;0;L;;;;;N;;;;0584; 0555;ARMENIAN CAPITAL LETTER OH;Lu;0;L;;;;;N;;;;0585; 0556;ARMENIAN CAPITAL LETTER FEH;Lu;0;L;;;;;N;;;;0586; 0559;ARMENIAN MODIFIER LETTER LEFT HALF RING;Lm;0;L;;;;;N;;;;; 055A;ARMENIAN APOSTROPHE;Po;0;L;;;;;N;ARMENIAN MODIFIER LETTER RIGHT HALF RING;;;; 055B;ARMENIAN EMPHASIS MARK;Po;0;L;;;;;N;;;;; 055C;ARMENIAN EXCLAMATION MARK;Po;0;L;;;;;N;;;;; 055D;ARMENIAN COMMA;Po;0;L;;;;;N;;;;; 055E;ARMENIAN QUESTION MARK;Po;0;L;;;;;N;;;;; 055F;ARMENIAN ABBREVIATION MARK;Po;0;L;;;;;N;;;;; 0561;ARMENIAN SMALL LETTER AYB;Ll;0;L;;;;;N;;;0531;;0531 0562;ARMENIAN SMALL LETTER BEN;Ll;0;L;;;;;N;;;0532;;0532 0563;ARMENIAN SMALL LETTER GIM;Ll;0;L;;;;;N;;;0533;;0533 0564;ARMENIAN SMALL LETTER DA;Ll;0;L;;;;;N;;;0534;;0534 0565;ARMENIAN SMALL LETTER ECH;Ll;0;L;;;;;N;;;0535;;0535 0566;ARMENIAN SMALL LETTER ZA;Ll;0;L;;;;;N;;;0536;;0536 0567;ARMENIAN SMALL LETTER EH;Ll;0;L;;;;;N;;;0537;;0537 0568;ARMENIAN SMALL LETTER ET;Ll;0;L;;;;;N;;;0538;;0538 0569;ARMENIAN SMALL LETTER TO;Ll;0;L;;;;;N;;;0539;;0539 056A;ARMENIAN SMALL LETTER ZHE;Ll;0;L;;;;;N;;;053A;;053A 056B;ARMENIAN SMALL LETTER INI;Ll;0;L;;;;;N;;;053B;;053B 056C;ARMENIAN SMALL LETTER LIWN;Ll;0;L;;;;;N;;;053C;;053C 056D;ARMENIAN SMALL LETTER XEH;Ll;0;L;;;;;N;;;053D;;053D 056E;ARMENIAN SMALL LETTER CA;Ll;0;L;;;;;N;;;053E;;053E 056F;ARMENIAN SMALL LETTER KEN;Ll;0;L;;;;;N;;;053F;;053F 0570;ARMENIAN SMALL LETTER HO;Ll;0;L;;;;;N;;;0540;;0540 0571;ARMENIAN SMALL LETTER JA;Ll;0;L;;;;;N;;;0541;;0541 0572;ARMENIAN SMALL LETTER GHAD;Ll;0;L;;;;;N;ARMENIAN SMALL LETTER LAD;;0542;;0542 0573;ARMENIAN SMALL LETTER CHEH;Ll;0;L;;;;;N;;;0543;;0543 0574;ARMENIAN SMALL LETTER MEN;Ll;0;L;;;;;N;;;0544;;0544 0575;ARMENIAN SMALL LETTER YI;Ll;0;L;;;;;N;;;0545;;0545 0576;ARMENIAN SMALL LETTER NOW;Ll;0;L;;;;;N;;;0546;;0546 0577;ARMENIAN SMALL LETTER SHA;Ll;0;L;;;;;N;;;0547;;0547 0578;ARMENIAN SMALL LETTER VO;Ll;0;L;;;;;N;;;0548;;0548 0579;ARMENIAN SMALL LETTER CHA;Ll;0;L;;;;;N;;;0549;;0549 057A;ARMENIAN SMALL LETTER PEH;Ll;0;L;;;;;N;;;054A;;054A 057B;ARMENIAN SMALL LETTER JHEH;Ll;0;L;;;;;N;;;054B;;054B 057C;ARMENIAN SMALL LETTER RA;Ll;0;L;;;;;N;;;054C;;054C 057D;ARMENIAN SMALL LETTER SEH;Ll;0;L;;;;;N;;;054D;;054D 057E;ARMENIAN SMALL LETTER VEW;Ll;0;L;;;;;N;;;054E;;054E 057F;ARMENIAN SMALL LETTER TIWN;Ll;0;L;;;;;N;;;054F;;054F 0580;ARMENIAN SMALL LETTER REH;Ll;0;L;;;;;N;;;0550;;0550 0581;ARMENIAN SMALL LETTER CO;Ll;0;L;;;;;N;;;0551;;0551 0582;ARMENIAN SMALL LETTER YIWN;Ll;0;L;;;;;N;;;0552;;0552 0583;ARMENIAN SMALL LETTER PIWR;Ll;0;L;;;;;N;;;0553;;0553 0584;ARMENIAN SMALL LETTER KEH;Ll;0;L;;;;;N;;;0554;;0554 0585;ARMENIAN SMALL LETTER OH;Ll;0;L;;;;;N;;;0555;;0555 0586;ARMENIAN SMALL LETTER FEH;Ll;0;L;;;;;N;;;0556;;0556 0587;ARMENIAN SMALL LIGATURE ECH YIWN;Ll;0;L;<compat> 0565 0582;;;;N;;;;; 0589;ARMENIAN FULL STOP;Po;0;L;;;;;N;ARMENIAN PERIOD;;;; 058A;ARMENIAN HYPHEN;Pd;0;ON;;;;;N;;;;; 058D;RIGHT-FACING ARMENIAN ETERNITY SIGN;So;0;ON;;;;;N;;;;; 058E;LEFT-FACING ARMENIAN ETERNITY SIGN;So;0;ON;;;;;N;;;;; 058F;ARMENIAN DRAM SIGN;Sc;0;ET;;;;;N;;;;; 0591;HEBREW ACCENT ETNAHTA;Mn;220;NSM;;;;;N;;;;; 0592;HEBREW ACCENT SEGOL;Mn;230;NSM;;;;;N;;;;; 0593;HEBREW ACCENT SHALSHELET;Mn;230;NSM;;;;;N;;;;; 0594;HEBREW ACCENT ZAQEF QATAN;Mn;230;NSM;;;;;N;;;;; 0595;HEBREW ACCENT ZAQEF GADOL;Mn;230;NSM;;;;;N;;;;; 0596;HEBREW ACCENT TIPEHA;Mn;220;NSM;;;;;N;;;;; 0597;HEBREW ACCENT REVIA;Mn;230;NSM;;;;;N;;;;; 0598;HEBREW ACCENT ZARQA;Mn;230;NSM;;;;;N;;;;; 0599;HEBREW ACCENT PASHTA;Mn;230;NSM;;;;;N;;;;; 059A;HEBREW ACCENT YETIV;Mn;222;NSM;;;;;N;;;;; 059B;HEBREW ACCENT TEVIR;Mn;220;NSM;;;;;N;;;;; 059C;HEBREW ACCENT GERESH;Mn;230;NSM;;;;;N;;;;; 059D;HEBREW ACCENT GERESH MUQDAM;Mn;230;NSM;;;;;N;;;;; 059E;HEBREW ACCENT GERSHAYIM;Mn;230;NSM;;;;;N;;;;; 059F;HEBREW ACCENT QARNEY PARA;Mn;230;NSM;;;;;N;;;;; 05A0;HEBREW ACCENT TELISHA GEDOLA;Mn;230;NSM;;;;;N;;;;; 05A1;HEBREW ACCENT PAZER;Mn;230;NSM;;;;;N;;;;; 05A2;HEBREW ACCENT ATNAH HAFUKH;Mn;220;NSM;;;;;N;;;;; 05A3;HEBREW ACCENT MUNAH;Mn;220;NSM;;;;;N;;;;; 05A4;HEBREW ACCENT MAHAPAKH;Mn;220;NSM;;;;;N;;;;; 05A5;HEBREW ACCENT MERKHA;Mn;220;NSM;;;;;N;;;;; 05A6;HEBREW ACCENT MERKHA KEFULA;Mn;220;NSM;;;;;N;;;;; 05A7;HEBREW ACCENT DARGA;Mn;220;NSM;;;;;N;;;;; 05A8;HEBREW ACCENT QADMA;Mn;230;NSM;;;;;N;;;;; 05A9;HEBREW ACCENT TELISHA QETANA;Mn;230;NSM;;;;;N;;;;; 05AA;HEBREW ACCENT YERAH BEN YOMO;Mn;220;NSM;;;;;N;;;;; 05AB;HEBREW ACCENT OLE;Mn;230;NSM;;;;;N;;;;; 05AC;HEBREW ACCENT ILUY;Mn;230;NSM;;;;;N;;;;; 05AD;HEBREW ACCENT DEHI;Mn;222;NSM;;;;;N;;;;; 05AE;HEBREW ACCENT ZINOR;Mn;228;NSM;;;;;N;;;;; 05AF;HEBREW MARK MASORA CIRCLE;Mn;230;NSM;;;;;N;;;;; 05B0;HEBREW POINT SHEVA;Mn;10;NSM;;;;;N;;;;; 05B1;HEBREW POINT HATAF SEGOL;Mn;11;NSM;;;;;N;;;;; 05B2;HEBREW POINT HATAF PATAH;Mn;12;NSM;;;;;N;;;;; 05B3;HEBREW POINT HATAF QAMATS;Mn;13;NSM;;;;;N;;;;; 05B4;HEBREW POINT HIRIQ;Mn;14;NSM;;;;;N;;;;; 05B5;HEBREW POINT TSERE;Mn;15;NSM;;;;;N;;;;; 05B6;HEBREW POINT SEGOL;Mn;16;NSM;;;;;N;;;;; 05B7;HEBREW POINT PATAH;Mn;17;NSM;;;;;N;;;;; 05B8;HEBREW POINT QAMATS;Mn;18;NSM;;;;;N;;;;; 05B9;HEBREW POINT HOLAM;Mn;19;NSM;;;;;N;;;;; 05BA;HEBREW POINT HOLAM HASER FOR VAV;Mn;19;NSM;;;;;N;;;;; 05BB;HEBREW POINT QUBUTS;Mn;20;NSM;;;;;N;;;;; 05BC;HEBREW POINT DAGESH OR MAPIQ;Mn;21;NSM;;;;;N;HEBREW POINT DAGESH;;;; 05BD;HEBREW POINT METEG;Mn;22;NSM;;;;;N;;;;; 05BE;HEBREW PUNCTUATION MAQAF;Pd;0;R;;;;;N;;;;; 05BF;HEBREW POINT RAFE;Mn;23;NSM;;;;;N;;;;; 05C0;HEBREW PUNCTUATION PASEQ;Po;0;R;;;;;N;HEBREW POINT PASEQ;;;; 05C1;HEBREW POINT SHIN DOT;Mn;24;NSM;;;;;N;;;;; 05C2;HEBREW POINT SIN DOT;Mn;25;NSM;;;;;N;;;;; 05C3;HEBREW PUNCTUATION SOF PASUQ;Po;0;R;;;;;N;;;;; 05C4;HEBREW MARK UPPER DOT;Mn;230;NSM;;;;;N;;;;; 05C5;HEBREW MARK LOWER DOT;Mn;220;NSM;;;;;N;;;;; 05C6;HEBREW PUNCTUATION NUN HAFUKHA;Po;0;R;;;;;N;;;;; 05C7;HEBREW POINT QAMATS QATAN;Mn;18;NSM;;;;;N;;;;; 05D0;HEBREW LETTER ALEF;Lo;0;R;;;;;N;;;;; 05D1;HEBREW LETTER BET;Lo;0;R;;;;;N;;;;; 05D2;HEBREW LETTER GIMEL;Lo;0;R;;;;;N;;;;; 05D3;HEBREW LETTER DALET;Lo;0;R;;;;;N;;;;; 05D4;HEBREW LETTER HE;Lo;0;R;;;;;N;;;;; 05D5;HEBREW LETTER VAV;Lo;0;R;;;;;N;;;;; 05D6;HEBREW LETTER ZAYIN;Lo;0;R;;;;;N;;;;; 05D7;HEBREW LETTER HET;Lo;0;R;;;;;N;;;;; 05D8;HEBREW LETTER TET;Lo;0;R;;;;;N;;;;; 05D9;HEBREW LETTER YOD;Lo;0;R;;;;;N;;;;; 05DA;HEBREW LETTER FINAL KAF;Lo;0;R;;;;;N;;;;; 05DB;HEBREW LETTER KAF;Lo;0;R;;;;;N;;;;; 05DC;HEBREW LETTER LAMED;Lo;0;R;;;;;N;;;;; 05DD;HEBREW LETTER FINAL MEM;Lo;0;R;;;;;N;;;;; 05DE;HEBREW LETTER MEM;Lo;0;R;;;;;N;;;;; 05DF;HEBREW LETTER FINAL NUN;Lo;0;R;;;;;N;;;;; 05E0;HEBREW LETTER NUN;Lo;0;R;;;;;N;;;;; 05E1;HEBREW LETTER SAMEKH;Lo;0;R;;;;;N;;;;; 05E2;HEBREW LETTER AYIN;Lo;0;R;;;;;N;;;;; 05E3;HEBREW LETTER FINAL PE;Lo;0;R;;;;;N;;;;; 05E4;HEBREW LETTER PE;Lo;0;R;;;;;N;;;;; 05E5;HEBREW LETTER FINAL TSADI;Lo;0;R;;;;;N;;;;; 05E6;HEBREW LETTER TSADI;Lo;0;R;;;;;N;;;;; 05E7;HEBREW LETTER QOF;Lo;0;R;;;;;N;;;;; 05E8;HEBREW LETTER RESH;Lo;0;R;;;;;N;;;;; 05E9;HEBREW LETTER SHIN;Lo;0;R;;;;;N;;;;; 05EA;HEBREW LETTER TAV;Lo;0;R;;;;;N;;;;; 05F0;HEBREW LIGATURE YIDDISH DOUBLE VAV;Lo;0;R;;;;;N;HEBREW LETTER DOUBLE VAV;;;; 05F1;HEBREW LIGATURE YIDDISH VAV YOD;Lo;0;R;;;;;N;HEBREW LETTER VAV YOD;;;; 05F2;HEBREW LIGATURE YIDDISH DOUBLE YOD;Lo;0;R;;;;;N;HEBREW LETTER DOUBLE YOD;;;; 05F3;HEBREW PUNCTUATION GERESH;Po;0;R;;;;;N;;;;; 05F4;HEBREW PUNCTUATION GERSHAYIM;Po;0;R;;;;;N;;;;; 0600;ARABIC NUMBER SIGN;Cf;0;AN;;;;;N;;;;; 0601;ARABIC SIGN SANAH;Cf;0;AN;;;;;N;;;;; 0602;ARABIC FOOTNOTE MARKER;Cf;0;AN;;;;;N;;;;; 0603;ARABIC SIGN SAFHA;Cf;0;AN;;;;;N;;;;; 0604;ARABIC SIGN SAMVAT;Cf;0;AN;;;;;N;;;;; 0605;ARABIC NUMBER MARK ABOVE;Cf;0;AN;;;;;N;;;;; 0606;ARABIC-INDIC CUBE ROOT;Sm;0;ON;;;;;N;;;;; 0607;ARABIC-INDIC FOURTH ROOT;Sm;0;ON;;;;;N;;;;; 0608;ARABIC RAY;Sm;0;AL;;;;;N;;;;; 0609;ARABIC-INDIC PER MILLE SIGN;Po;0;ET;;;;;N;;;;; 060A;ARABIC-INDIC PER TEN THOUSAND SIGN;Po;0;ET;;;;;N;;;;; 060B;AFGHANI SIGN;Sc;0;AL;;;;;N;;;;; 060C;ARABIC COMMA;Po;0;CS;;;;;N;;;;; 060D;ARABIC DATE SEPARATOR;Po;0;AL;;;;;N;;;;; 060E;ARABIC POETIC VERSE SIGN;So;0;ON;;;;;N;;;;; 060F;ARABIC SIGN MISRA;So;0;ON;;;;;N;;;;; 0610;ARABIC SIGN SALLALLAHOU ALAYHE WASSALLAM;Mn;230;NSM;;;;;N;;;;; 0611;ARABIC SIGN ALAYHE ASSALLAM;Mn;230;NSM;;;;;N;;;;; 0612;ARABIC SIGN RAHMATULLAH ALAYHE;Mn;230;NSM;;;;;N;;;;; 0613;ARABIC SIGN RADI ALLAHOU ANHU;Mn;230;NSM;;;;;N;;;;; 0614;ARABIC SIGN TAKHALLUS;Mn;230;NSM;;;;;N;;;;; 0615;ARABIC SMALL HIGH TAH;Mn;230;NSM;;;;;N;;;;; 0616;ARABIC SMALL HIGH LIGATURE ALEF WITH LAM WITH YEH;Mn;230;NSM;;;;;N;;;;; 0617;ARABIC SMALL HIGH ZAIN;Mn;230;NSM;;;;;N;;;;; 0618;ARABIC SMALL FATHA;Mn;30;NSM;;;;;N;;;;; 0619;ARABIC SMALL DAMMA;Mn;31;NSM;;;;;N;;;;; 061A;ARABIC SMALL KASRA;Mn;32;NSM;;;;;N;;;;; 061B;ARABIC SEMICOLON;Po;0;AL;;;;;N;;;;; 061C;ARABIC LETTER MARK;Cf;0;AL;;;;;N;;;;; 061E;ARABIC TRIPLE DOT PUNCTUATION MARK;Po;0;AL;;;;;N;;;;; 061F;ARABIC QUESTION MARK;Po;0;AL;;;;;N;;;;; 0620;ARABIC LETTER KASHMIRI YEH;Lo;0;AL;;;;;N;;;;; 0621;ARABIC LETTER HAMZA;Lo;0;AL;;;;;N;ARABIC LETTER HAMZAH;;;; 0622;ARABIC LETTER ALEF WITH MADDA ABOVE;Lo;0;AL;0627 0653;;;;N;ARABIC LETTER MADDAH ON ALEF;;;; 0623;ARABIC LETTER ALEF WITH HAMZA ABOVE;Lo;0;AL;0627 0654;;;;N;ARABIC LETTER HAMZAH ON ALEF;;;; 0624;ARABIC LETTER WAW WITH HAMZA ABOVE;Lo;0;AL;0648 0654;;;;N;ARABIC LETTER HAMZAH ON WAW;;;; 0625;ARABIC LETTER ALEF WITH HAMZA BELOW;Lo;0;AL;0627 0655;;;;N;ARABIC LETTER HAMZAH UNDER ALEF;;;; 0626;ARABIC LETTER YEH WITH HAMZA ABOVE;Lo;0;AL;064A 0654;;;;N;ARABIC LETTER HAMZAH ON YA;;;; 0627;ARABIC LETTER ALEF;Lo;0;AL;;;;;N;;;;; 0628;ARABIC LETTER BEH;Lo;0;AL;;;;;N;ARABIC LETTER BAA;;;; 0629;ARABIC LETTER TEH MARBUTA;Lo;0;AL;;;;;N;ARABIC LETTER TAA MARBUTAH;;;; 062A;ARABIC LETTER TEH;Lo;0;AL;;;;;N;ARABIC LETTER TAA;;;; 062B;ARABIC LETTER THEH;Lo;0;AL;;;;;N;ARABIC LETTER THAA;;;; 062C;ARABIC LETTER JEEM;Lo;0;AL;;;;;N;;;;; 062D;ARABIC LETTER HAH;Lo;0;AL;;;;;N;ARABIC LETTER HAA;;;; 062E;ARABIC LETTER KHAH;Lo;0;AL;;;;;N;ARABIC LETTER KHAA;;;; 062F;ARABIC LETTER DAL;Lo;0;AL;;;;;N;;;;; 0630;ARABIC LETTER THAL;Lo;0;AL;;;;;N;;;;; 0631;ARABIC LETTER REH;Lo;0;AL;;;;;N;ARABIC LETTER RA;;;; 0632;ARABIC LETTER ZAIN;Lo;0;AL;;;;;N;;;;; 0633;ARABIC LETTER SEEN;Lo;0;AL;;;;;N;;;;; 0634;ARABIC LETTER SHEEN;Lo;0;AL;;;;;N;;;;; 0635;ARABIC LETTER SAD;Lo;0;AL;;;;;N;;;;; 0636;ARABIC LETTER DAD;Lo;0;AL;;;;;N;;;;; 0637;ARABIC LETTER TAH;Lo;0;AL;;;;;N;;;;; 0638;ARABIC LETTER ZAH;Lo;0;AL;;;;;N;ARABIC LETTER DHAH;;;; 0639;ARABIC LETTER AIN;Lo;0;AL;;;;;N;;;;; 063A;ARABIC LETTER GHAIN;Lo;0;AL;;;;;N;;;;; 063B;ARABIC LETTER KEHEH WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 063C;ARABIC LETTER KEHEH WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;;;;; 063D;ARABIC LETTER FARSI YEH WITH INVERTED V;Lo;0;AL;;;;;N;;;;; 063E;ARABIC LETTER FARSI YEH WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 063F;ARABIC LETTER FARSI YEH WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 0640;ARABIC TATWEEL;Lm;0;AL;;;;;N;;;;; 0641;ARABIC LETTER FEH;Lo;0;AL;;;;;N;ARABIC LETTER FA;;;; 0642;ARABIC LETTER QAF;Lo;0;AL;;;;;N;;;;; 0643;ARABIC LETTER KAF;Lo;0;AL;;;;;N;ARABIC LETTER CAF;;;; 0644;ARABIC LETTER LAM;Lo;0;AL;;;;;N;;;;; 0645;ARABIC LETTER MEEM;Lo;0;AL;;;;;N;;;;; 0646;ARABIC LETTER NOON;Lo;0;AL;;;;;N;;;;; 0647;ARABIC LETTER HEH;Lo;0;AL;;;;;N;ARABIC LETTER HA;;;; 0648;ARABIC LETTER WAW;Lo;0;AL;;;;;N;;;;; 0649;ARABIC LETTER ALEF MAKSURA;Lo;0;AL;;;;;N;ARABIC LETTER ALEF MAQSURAH;;;; 064A;ARABIC LETTER YEH;Lo;0;AL;;;;;N;ARABIC LETTER YA;;;; 064B;ARABIC FATHATAN;Mn;27;NSM;;;;;N;;;;; 064C;ARABIC DAMMATAN;Mn;28;NSM;;;;;N;;;;; 064D;ARABIC KASRATAN;Mn;29;NSM;;;;;N;;;;; 064E;ARABIC FATHA;Mn;30;NSM;;;;;N;ARABIC FATHAH;;;; 064F;ARABIC DAMMA;Mn;31;NSM;;;;;N;ARABIC DAMMAH;;;; 0650;ARABIC KASRA;Mn;32;NSM;;;;;N;ARABIC KASRAH;;;; 0651;ARABIC SHADDA;Mn;33;NSM;;;;;N;ARABIC SHADDAH;;;; 0652;ARABIC SUKUN;Mn;34;NSM;;;;;N;;;;; 0653;ARABIC MADDAH ABOVE;Mn;230;NSM;;;;;N;;;;; 0654;ARABIC HAMZA ABOVE;Mn;230;NSM;;;;;N;;;;; 0655;ARABIC HAMZA BELOW;Mn;220;NSM;;;;;N;;;;; 0656;ARABIC SUBSCRIPT ALEF;Mn;220;NSM;;;;;N;;;;; 0657;ARABIC INVERTED DAMMA;Mn;230;NSM;;;;;N;;;;; 0658;ARABIC MARK NOON GHUNNA;Mn;230;NSM;;;;;N;;;;; 0659;ARABIC ZWARAKAY;Mn;230;NSM;;;;;N;;;;; 065A;ARABIC VOWEL SIGN SMALL V ABOVE;Mn;230;NSM;;;;;N;;;;; 065B;ARABIC VOWEL SIGN INVERTED SMALL V ABOVE;Mn;230;NSM;;;;;N;;;;; 065C;ARABIC VOWEL SIGN DOT BELOW;Mn;220;NSM;;;;;N;;;;; 065D;ARABIC REVERSED DAMMA;Mn;230;NSM;;;;;N;;;;; 065E;ARABIC FATHA WITH TWO DOTS;Mn;230;NSM;;;;;N;;;;; 065F;ARABIC WAVY HAMZA BELOW;Mn;220;NSM;;;;;N;;;;; 0660;ARABIC-INDIC DIGIT ZERO;Nd;0;AN;;0;0;0;N;;;;; 0661;ARABIC-INDIC DIGIT ONE;Nd;0;AN;;1;1;1;N;;;;; 0662;ARABIC-INDIC DIGIT TWO;Nd;0;AN;;2;2;2;N;;;;; 0663;ARABIC-INDIC DIGIT THREE;Nd;0;AN;;3;3;3;N;;;;; 0664;ARABIC-INDIC DIGIT FOUR;Nd;0;AN;;4;4;4;N;;;;; 0665;ARABIC-INDIC DIGIT FIVE;Nd;0;AN;;5;5;5;N;;;;; 0666;ARABIC-INDIC DIGIT SIX;Nd;0;AN;;6;6;6;N;;;;; 0667;ARABIC-INDIC DIGIT SEVEN;Nd;0;AN;;7;7;7;N;;;;; 0668;ARABIC-INDIC DIGIT EIGHT;Nd;0;AN;;8;8;8;N;;;;; 0669;ARABIC-INDIC DIGIT NINE;Nd;0;AN;;9;9;9;N;;;;; 066A;ARABIC PERCENT SIGN;Po;0;ET;;;;;N;;;;; 066B;ARABIC DECIMAL SEPARATOR;Po;0;AN;;;;;N;;;;; 066C;ARABIC THOUSANDS SEPARATOR;Po;0;AN;;;;;N;;;;; 066D;ARABIC FIVE POINTED STAR;Po;0;AL;;;;;N;;;;; 066E;ARABIC LETTER DOTLESS BEH;Lo;0;AL;;;;;N;;;;; 066F;ARABIC LETTER DOTLESS QAF;Lo;0;AL;;;;;N;;;;; 0670;ARABIC LETTER SUPERSCRIPT ALEF;Mn;35;NSM;;;;;N;ARABIC ALEF ABOVE;;;; 0671;ARABIC LETTER ALEF WASLA;Lo;0;AL;;;;;N;ARABIC LETTER HAMZAT WASL ON ALEF;;;; 0672;ARABIC LETTER ALEF WITH WAVY HAMZA ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER WAVY HAMZAH ON ALEF;;;; 0673;ARABIC LETTER ALEF WITH WAVY HAMZA BELOW;Lo;0;AL;;;;;N;ARABIC LETTER WAVY HAMZAH UNDER ALEF;;;; 0674;ARABIC LETTER HIGH HAMZA;Lo;0;AL;;;;;N;ARABIC LETTER HIGH HAMZAH;;;; 0675;ARABIC LETTER HIGH HAMZA ALEF;Lo;0;AL;<compat> 0627 0674;;;;N;ARABIC LETTER HIGH HAMZAH ALEF;;;; 0676;ARABIC LETTER HIGH HAMZA WAW;Lo;0;AL;<compat> 0648 0674;;;;N;ARABIC LETTER HIGH HAMZAH WAW;;;; 0677;ARABIC LETTER U WITH HAMZA ABOVE;Lo;0;AL;<compat> 06C7 0674;;;;N;ARABIC LETTER HIGH HAMZAH WAW WITH DAMMAH;;;; 0678;ARABIC LETTER HIGH HAMZA YEH;Lo;0;AL;<compat> 064A 0674;;;;N;ARABIC LETTER HIGH HAMZAH YA;;;; 0679;ARABIC LETTER TTEH;Lo;0;AL;;;;;N;ARABIC LETTER TAA WITH SMALL TAH;;;; 067A;ARABIC LETTER TTEHEH;Lo;0;AL;;;;;N;ARABIC LETTER TAA WITH TWO DOTS VERTICAL ABOVE;;;; 067B;ARABIC LETTER BEEH;Lo;0;AL;;;;;N;ARABIC LETTER BAA WITH TWO DOTS VERTICAL BELOW;;;; 067C;ARABIC LETTER TEH WITH RING;Lo;0;AL;;;;;N;ARABIC LETTER TAA WITH RING;;;; 067D;ARABIC LETTER TEH WITH THREE DOTS ABOVE DOWNWARDS;Lo;0;AL;;;;;N;ARABIC LETTER TAA WITH THREE DOTS ABOVE DOWNWARD;;;; 067E;ARABIC LETTER PEH;Lo;0;AL;;;;;N;ARABIC LETTER TAA WITH THREE DOTS BELOW;;;; 067F;ARABIC LETTER TEHEH;Lo;0;AL;;;;;N;ARABIC LETTER TAA WITH FOUR DOTS ABOVE;;;; 0680;ARABIC LETTER BEHEH;Lo;0;AL;;;;;N;ARABIC LETTER BAA WITH FOUR DOTS BELOW;;;; 0681;ARABIC LETTER HAH WITH HAMZA ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER HAMZAH ON HAA;;;; 0682;ARABIC LETTER HAH WITH TWO DOTS VERTICAL ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER HAA WITH TWO DOTS VERTICAL ABOVE;;;; 0683;ARABIC LETTER NYEH;Lo;0;AL;;;;;N;ARABIC LETTER HAA WITH MIDDLE TWO DOTS;;;; 0684;ARABIC LETTER DYEH;Lo;0;AL;;;;;N;ARABIC LETTER HAA WITH MIDDLE TWO DOTS VERTICAL;;;; 0685;ARABIC LETTER HAH WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER HAA WITH THREE DOTS ABOVE;;;; 0686;ARABIC LETTER TCHEH;Lo;0;AL;;;;;N;ARABIC LETTER HAA WITH MIDDLE THREE DOTS DOWNWARD;;;; 0687;ARABIC LETTER TCHEHEH;Lo;0;AL;;;;;N;ARABIC LETTER HAA WITH MIDDLE FOUR DOTS;;;; 0688;ARABIC LETTER DDAL;Lo;0;AL;;;;;N;ARABIC LETTER DAL WITH SMALL TAH;;;; 0689;ARABIC LETTER DAL WITH RING;Lo;0;AL;;;;;N;;;;; 068A;ARABIC LETTER DAL WITH DOT BELOW;Lo;0;AL;;;;;N;;;;; 068B;ARABIC LETTER DAL WITH DOT BELOW AND SMALL TAH;Lo;0;AL;;;;;N;;;;; 068C;ARABIC LETTER DAHAL;Lo;0;AL;;;;;N;ARABIC LETTER DAL WITH TWO DOTS ABOVE;;;; 068D;ARABIC LETTER DDAHAL;Lo;0;AL;;;;;N;ARABIC LETTER DAL WITH TWO DOTS BELOW;;;; 068E;ARABIC LETTER DUL;Lo;0;AL;;;;;N;ARABIC LETTER DAL WITH THREE DOTS ABOVE;;;; 068F;ARABIC LETTER DAL WITH THREE DOTS ABOVE DOWNWARDS;Lo;0;AL;;;;;N;ARABIC LETTER DAL WITH THREE DOTS ABOVE DOWNWARD;;;; 0690;ARABIC LETTER DAL WITH FOUR DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 0691;ARABIC LETTER RREH;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH SMALL TAH;;;; 0692;ARABIC LETTER REH WITH SMALL V;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH SMALL V;;;; 0693;ARABIC LETTER REH WITH RING;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH RING;;;; 0694;ARABIC LETTER REH WITH DOT BELOW;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH DOT BELOW;;;; 0695;ARABIC LETTER REH WITH SMALL V BELOW;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH SMALL V BELOW;;;; 0696;ARABIC LETTER REH WITH DOT BELOW AND DOT ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH DOT BELOW AND DOT ABOVE;;;; 0697;ARABIC LETTER REH WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH TWO DOTS ABOVE;;;; 0698;ARABIC LETTER JEH;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH THREE DOTS ABOVE;;;; 0699;ARABIC LETTER REH WITH FOUR DOTS ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH FOUR DOTS ABOVE;;;; 069A;ARABIC LETTER SEEN WITH DOT BELOW AND DOT ABOVE;Lo;0;AL;;;;;N;;;;; 069B;ARABIC LETTER SEEN WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;;;;; 069C;ARABIC LETTER SEEN WITH THREE DOTS BELOW AND THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 069D;ARABIC LETTER SAD WITH TWO DOTS BELOW;Lo;0;AL;;;;;N;;;;; 069E;ARABIC LETTER SAD WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 069F;ARABIC LETTER TAH WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 06A0;ARABIC LETTER AIN WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 06A1;ARABIC LETTER DOTLESS FEH;Lo;0;AL;;;;;N;ARABIC LETTER DOTLESS FA;;;; 06A2;ARABIC LETTER FEH WITH DOT MOVED BELOW;Lo;0;AL;;;;;N;ARABIC LETTER FA WITH DOT MOVED BELOW;;;; 06A3;ARABIC LETTER FEH WITH DOT BELOW;Lo;0;AL;;;;;N;ARABIC LETTER FA WITH DOT BELOW;;;; 06A4;ARABIC LETTER VEH;Lo;0;AL;;;;;N;ARABIC LETTER FA WITH THREE DOTS ABOVE;;;; 06A5;ARABIC LETTER FEH WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;ARABIC LETTER FA WITH THREE DOTS BELOW;;;; 06A6;ARABIC LETTER PEHEH;Lo;0;AL;;;;;N;ARABIC LETTER FA WITH FOUR DOTS ABOVE;;;; 06A7;ARABIC LETTER QAF WITH DOT ABOVE;Lo;0;AL;;;;;N;;;;; 06A8;ARABIC LETTER QAF WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 06A9;ARABIC LETTER KEHEH;Lo;0;AL;;;;;N;ARABIC LETTER OPEN CAF;;;; 06AA;ARABIC LETTER SWASH KAF;Lo;0;AL;;;;;N;ARABIC LETTER SWASH CAF;;;; 06AB;ARABIC LETTER KAF WITH RING;Lo;0;AL;;;;;N;ARABIC LETTER CAF WITH RING;;;; 06AC;ARABIC LETTER KAF WITH DOT ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER CAF WITH DOT ABOVE;;;; 06AD;ARABIC LETTER NG;Lo;0;AL;;;;;N;ARABIC LETTER CAF WITH THREE DOTS ABOVE;;;; 06AE;ARABIC LETTER KAF WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;ARABIC LETTER CAF WITH THREE DOTS BELOW;;;; 06AF;ARABIC LETTER GAF;Lo;0;AL;;;;;N;;;;; 06B0;ARABIC LETTER GAF WITH RING;Lo;0;AL;;;;;N;;;;; 06B1;ARABIC LETTER NGOEH;Lo;0;AL;;;;;N;ARABIC LETTER GAF WITH TWO DOTS ABOVE;;;; 06B2;ARABIC LETTER GAF WITH TWO DOTS BELOW;Lo;0;AL;;;;;N;;;;; 06B3;ARABIC LETTER GUEH;Lo;0;AL;;;;;N;ARABIC LETTER GAF WITH TWO DOTS VERTICAL BELOW;;;; 06B4;ARABIC LETTER GAF WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 06B5;ARABIC LETTER LAM WITH SMALL V;Lo;0;AL;;;;;N;;;;; 06B6;ARABIC LETTER LAM WITH DOT ABOVE;Lo;0;AL;;;;;N;;;;; 06B7;ARABIC LETTER LAM WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 06B8;ARABIC LETTER LAM WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;;;;; 06B9;ARABIC LETTER NOON WITH DOT BELOW;Lo;0;AL;;;;;N;;;;; 06BA;ARABIC LETTER NOON GHUNNA;Lo;0;AL;;;;;N;ARABIC LETTER DOTLESS NOON;;;; 06BB;ARABIC LETTER RNOON;Lo;0;AL;;;;;N;ARABIC LETTER DOTLESS NOON WITH SMALL TAH;;;; 06BC;ARABIC LETTER NOON WITH RING;Lo;0;AL;;;;;N;;;;; 06BD;ARABIC LETTER NOON WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 06BE;ARABIC LETTER HEH DOACHASHMEE;Lo;0;AL;;;;;N;ARABIC LETTER KNOTTED HA;;;; 06BF;ARABIC LETTER TCHEH WITH DOT ABOVE;Lo;0;AL;;;;;N;;;;; 06C0;ARABIC LETTER HEH WITH YEH ABOVE;Lo;0;AL;06D5 0654;;;;N;ARABIC LETTER HAMZAH ON HA;;;; 06C1;ARABIC LETTER HEH GOAL;Lo;0;AL;;;;;N;ARABIC LETTER HA GOAL;;;; 06C2;ARABIC LETTER HEH GOAL WITH HAMZA ABOVE;Lo;0;AL;06C1 0654;;;;N;ARABIC LETTER HAMZAH ON HA GOAL;;;; 06C3;ARABIC LETTER TEH MARBUTA GOAL;Lo;0;AL;;;;;N;ARABIC LETTER TAA MARBUTAH GOAL;;;; 06C4;ARABIC LETTER WAW WITH RING;Lo;0;AL;;;;;N;;;;; 06C5;ARABIC LETTER KIRGHIZ OE;Lo;0;AL;;;;;N;ARABIC LETTER WAW WITH BAR;;;; 06C6;ARABIC LETTER OE;Lo;0;AL;;;;;N;ARABIC LETTER WAW WITH SMALL V;;;; 06C7;ARABIC LETTER U;Lo;0;AL;;;;;N;ARABIC LETTER WAW WITH DAMMAH;;;; 06C8;ARABIC LETTER YU;Lo;0;AL;;;;;N;ARABIC LETTER WAW WITH ALEF ABOVE;;;; 06C9;ARABIC LETTER KIRGHIZ YU;Lo;0;AL;;;;;N;ARABIC LETTER WAW WITH INVERTED SMALL V;;;; 06CA;ARABIC LETTER WAW WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 06CB;ARABIC LETTER VE;Lo;0;AL;;;;;N;ARABIC LETTER WAW WITH THREE DOTS ABOVE;;;; 06CC;ARABIC LETTER FARSI YEH;Lo;0;AL;;;;;N;ARABIC LETTER DOTLESS YA;;;; 06CD;ARABIC LETTER YEH WITH TAIL;Lo;0;AL;;;;;N;ARABIC LETTER YA WITH TAIL;;;; 06CE;ARABIC LETTER YEH WITH SMALL V;Lo;0;AL;;;;;N;ARABIC LETTER YA WITH SMALL V;;;; 06CF;ARABIC LETTER WAW WITH DOT ABOVE;Lo;0;AL;;;;;N;;;;; 06D0;ARABIC LETTER E;Lo;0;AL;;;;;N;ARABIC LETTER YA WITH TWO DOTS VERTICAL BELOW;;;; 06D1;ARABIC LETTER YEH WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;ARABIC LETTER YA WITH THREE DOTS BELOW;;;; 06D2;ARABIC LETTER YEH BARREE;Lo;0;AL;;;;;N;ARABIC LETTER YA BARREE;;;; 06D3;ARABIC LETTER YEH BARREE WITH HAMZA ABOVE;Lo;0;AL;06D2 0654;;;;N;ARABIC LETTER HAMZAH ON YA BARREE;;;; 06D4;ARABIC FULL STOP;Po;0;AL;;;;;N;ARABIC PERIOD;;;; 06D5;ARABIC LETTER AE;Lo;0;AL;;;;;N;;;;; 06D6;ARABIC SMALL HIGH LIGATURE SAD WITH LAM WITH ALEF MAKSURA;Mn;230;NSM;;;;;N;;;;; 06D7;ARABIC SMALL HIGH LIGATURE QAF WITH LAM WITH ALEF MAKSURA;Mn;230;NSM;;;;;N;;;;; 06D8;ARABIC SMALL HIGH MEEM INITIAL FORM;Mn;230;NSM;;;;;N;;;;; 06D9;ARABIC SMALL HIGH LAM ALEF;Mn;230;NSM;;;;;N;;;;; 06DA;ARABIC SMALL HIGH JEEM;Mn;230;NSM;;;;;N;;;;; 06DB;ARABIC SMALL HIGH THREE DOTS;Mn;230;NSM;;;;;N;;;;; 06DC;ARABIC SMALL HIGH SEEN;Mn;230;NSM;;;;;N;;;;; 06DD;ARABIC END OF AYAH;Cf;0;AN;;;;;N;;;;; 06DE;ARABIC START OF RUB EL HIZB;So;0;ON;;;;;N;;;;; 06DF;ARABIC SMALL HIGH ROUNDED ZERO;Mn;230;NSM;;;;;N;;;;; 06E0;ARABIC SMALL HIGH UPRIGHT RECTANGULAR ZERO;Mn;230;NSM;;;;;N;;;;; 06E1;ARABIC SMALL HIGH DOTLESS HEAD OF KHAH;Mn;230;NSM;;;;;N;;;;; 06E2;ARABIC SMALL HIGH MEEM ISOLATED FORM;Mn;230;NSM;;;;;N;;;;; 06E3;ARABIC SMALL LOW SEEN;Mn;220;NSM;;;;;N;;;;; 06E4;ARABIC SMALL HIGH MADDA;Mn;230;NSM;;;;;N;;;;; 06E5;ARABIC SMALL WAW;Lm;0;AL;;;;;N;;;;; 06E6;ARABIC SMALL YEH;Lm;0;AL;;;;;N;;;;; 06E7;ARABIC SMALL HIGH YEH;Mn;230;NSM;;;;;N;;;;; 06E8;ARABIC SMALL HIGH NOON;Mn;230;NSM;;;;;N;;;;; 06E9;ARABIC PLACE OF SAJDAH;So;0;ON;;;;;N;;;;; 06EA;ARABIC EMPTY CENTRE LOW STOP;Mn;220;NSM;;;;;N;;;;; 06EB;ARABIC EMPTY CENTRE HIGH STOP;Mn;230;NSM;;;;;N;;;;; 06EC;ARABIC ROUNDED HIGH STOP WITH FILLED CENTRE;Mn;230;NSM;;;;;N;;;;; 06ED;ARABIC SMALL LOW MEEM;Mn;220;NSM;;;;;N;;;;; 06EE;ARABIC LETTER DAL WITH INVERTED V;Lo;0;AL;;;;;N;;;;; 06EF;ARABIC LETTER REH WITH INVERTED V;Lo;0;AL;;;;;N;;;;; 06F0;EXTENDED ARABIC-INDIC DIGIT ZERO;Nd;0;EN;;0;0;0;N;EASTERN ARABIC-INDIC DIGIT ZERO;;;; 06F1;EXTENDED ARABIC-INDIC DIGIT ONE;Nd;0;EN;;1;1;1;N;EASTERN ARABIC-INDIC DIGIT ONE;;;; 06F2;EXTENDED ARABIC-INDIC DIGIT TWO;Nd;0;EN;;2;2;2;N;EASTERN ARABIC-INDIC DIGIT TWO;;;; 06F3;EXTENDED ARABIC-INDIC DIGIT THREE;Nd;0;EN;;3;3;3;N;EASTERN ARABIC-INDIC DIGIT THREE;;;; 06F4;EXTENDED ARABIC-INDIC DIGIT FOUR;Nd;0;EN;;4;4;4;N;EASTERN ARABIC-INDIC DIGIT FOUR;;;; 06F5;EXTENDED ARABIC-INDIC DIGIT FIVE;Nd;0;EN;;5;5;5;N;EASTERN ARABIC-INDIC DIGIT FIVE;;;; 06F6;EXTENDED ARABIC-INDIC DIGIT SIX;Nd;0;EN;;6;6;6;N;EASTERN ARABIC-INDIC DIGIT SIX;;;; 06F7;EXTENDED ARABIC-INDIC DIGIT SEVEN;Nd;0;EN;;7;7;7;N;EASTERN ARABIC-INDIC DIGIT SEVEN;;;; 06F8;EXTENDED ARABIC-INDIC DIGIT EIGHT;Nd;0;EN;;8;8;8;N;EASTERN ARABIC-INDIC DIGIT EIGHT;;;; 06F9;EXTENDED ARABIC-INDIC DIGIT NINE;Nd;0;EN;;9;9;9;N;EASTERN ARABIC-INDIC DIGIT NINE;;;; 06FA;ARABIC LETTER SHEEN WITH DOT BELOW;Lo;0;AL;;;;;N;;;;; 06FB;ARABIC LETTER DAD WITH DOT BELOW;Lo;0;AL;;;;;N;;;;; 06FC;ARABIC LETTER GHAIN WITH DOT BELOW;Lo;0;AL;;;;;N;;;;; 06FD;ARABIC SIGN SINDHI AMPERSAND;So;0;AL;;;;;N;;;;; 06FE;ARABIC SIGN SINDHI POSTPOSITION MEN;So;0;AL;;;;;N;;;;; 06FF;ARABIC LETTER HEH WITH INVERTED V;Lo;0;AL;;;;;N;;;;; 0700;SYRIAC END OF PARAGRAPH;Po;0;AL;;;;;N;;;;; 0701;SYRIAC SUPRALINEAR FULL STOP;Po;0;AL;;;;;N;;;;; 0702;SYRIAC SUBLINEAR FULL STOP;Po;0;AL;;;;;N;;;;; 0703;SYRIAC SUPRALINEAR COLON;Po;0;AL;;;;;N;;;;; 0704;SYRIAC SUBLINEAR COLON;Po;0;AL;;;;;N;;;;; 0705;SYRIAC HORIZONTAL COLON;Po;0;AL;;;;;N;;;;; 0706;SYRIAC COLON SKEWED LEFT;Po;0;AL;;;;;N;;;;; 0707;SYRIAC COLON SKEWED RIGHT;Po;0;AL;;;;;N;;;;; 0708;SYRIAC SUPRALINEAR COLON SKEWED LEFT;Po;0;AL;;;;;N;;;;; 0709;SYRIAC SUBLINEAR COLON SKEWED RIGHT;Po;0;AL;;;;;N;;;;; 070A;SYRIAC CONTRACTION;Po;0;AL;;;;;N;;;;; 070B;SYRIAC HARKLEAN OBELUS;Po;0;AL;;;;;N;;;;; 070C;SYRIAC HARKLEAN METOBELUS;Po;0;AL;;;;;N;;;;; 070D;SYRIAC HARKLEAN ASTERISCUS;Po;0;AL;;;;;N;;;;; 070F;SYRIAC ABBREVIATION MARK;Cf;0;AL;;;;;N;;;;; 0710;SYRIAC LETTER ALAPH;Lo;0;AL;;;;;N;;;;; 0711;SYRIAC LETTER SUPERSCRIPT ALAPH;Mn;36;NSM;;;;;N;;;;; 0712;SYRIAC LETTER BETH;Lo;0;AL;;;;;N;;;;; 0713;SYRIAC LETTER GAMAL;Lo;0;AL;;;;;N;;;;; 0714;SYRIAC LETTER GAMAL GARSHUNI;Lo;0;AL;;;;;N;;;;; 0715;SYRIAC LETTER DALATH;Lo;0;AL;;;;;N;;;;; 0716;SYRIAC LETTER DOTLESS DALATH RISH;Lo;0;AL;;;;;N;;;;; 0717;SYRIAC LETTER HE;Lo;0;AL;;;;;N;;;;; 0718;SYRIAC LETTER WAW;Lo;0;AL;;;;;N;;;;; 0719;SYRIAC LETTER ZAIN;Lo;0;AL;;;;;N;;;;; 071A;SYRIAC LETTER HETH;Lo;0;AL;;;;;N;;;;; 071B;SYRIAC LETTER TETH;Lo;0;AL;;;;;N;;;;; 071C;SYRIAC LETTER TETH GARSHUNI;Lo;0;AL;;;;;N;;;;; 071D;SYRIAC LETTER YUDH;Lo;0;AL;;;;;N;;;;; 071E;SYRIAC LETTER YUDH HE;Lo;0;AL;;;;;N;;;;; 071F;SYRIAC LETTER KAPH;Lo;0;AL;;;;;N;;;;; 0720;SYRIAC LETTER LAMADH;Lo;0;AL;;;;;N;;;;; 0721;SYRIAC LETTER MIM;Lo;0;AL;;;;;N;;;;; 0722;SYRIAC LETTER NUN;Lo;0;AL;;;;;N;;;;; 0723;SYRIAC LETTER SEMKATH;Lo;0;AL;;;;;N;;;;; 0724;SYRIAC LETTER FINAL SEMKATH;Lo;0;AL;;;;;N;;;;; 0725;SYRIAC LETTER E;Lo;0;AL;;;;;N;;;;; 0726;SYRIAC LETTER PE;Lo;0;AL;;;;;N;;;;; 0727;SYRIAC LETTER REVERSED PE;Lo;0;AL;;;;;N;;;;; 0728;SYRIAC LETTER SADHE;Lo;0;AL;;;;;N;;;;; 0729;SYRIAC LETTER QAPH;Lo;0;AL;;;;;N;;;;; 072A;SYRIAC LETTER RISH;Lo;0;AL;;;;;N;;;;; 072B;SYRIAC LETTER SHIN;Lo;0;AL;;;;;N;;;;; 072C;SYRIAC LETTER TAW;Lo;0;AL;;;;;N;;;;; 072D;SYRIAC LETTER PERSIAN BHETH;Lo;0;AL;;;;;N;;;;; 072E;SYRIAC LETTER PERSIAN GHAMAL;Lo;0;AL;;;;;N;;;;; 072F;SYRIAC LETTER PERSIAN DHALATH;Lo;0;AL;;;;;N;;;;; 0730;SYRIAC PTHAHA ABOVE;Mn;230;NSM;;;;;N;;;;; 0731;SYRIAC PTHAHA BELOW;Mn;220;NSM;;;;;N;;;;; 0732;SYRIAC PTHAHA DOTTED;Mn;230;NSM;;;;;N;;;;; 0733;SYRIAC ZQAPHA ABOVE;Mn;230;NSM;;;;;N;;;;; 0734;SYRIAC ZQAPHA BELOW;Mn;220;NSM;;;;;N;;;;; 0735;SYRIAC ZQAPHA DOTTED;Mn;230;NSM;;;;;N;;;;; 0736;SYRIAC RBASA ABOVE;Mn;230;NSM;;;;;N;;;;; 0737;SYRIAC RBASA BELOW;Mn;220;NSM;;;;;N;;;;; 0738;SYRIAC DOTTED ZLAMA HORIZONTAL;Mn;220;NSM;;;;;N;;;;; 0739;SYRIAC DOTTED ZLAMA ANGULAR;Mn;220;NSM;;;;;N;;;;; 073A;SYRIAC HBASA ABOVE;Mn;230;NSM;;;;;N;;;;; 073B;SYRIAC HBASA BELOW;Mn;220;NSM;;;;;N;;;;; 073C;SYRIAC HBASA-ESASA DOTTED;Mn;220;NSM;;;;;N;;;;; 073D;SYRIAC ESASA ABOVE;Mn;230;NSM;;;;;N;;;;; 073E;SYRIAC ESASA BELOW;Mn;220;NSM;;;;;N;;;;; 073F;SYRIAC RWAHA;Mn;230;NSM;;;;;N;;;;; 0740;SYRIAC FEMININE DOT;Mn;230;NSM;;;;;N;;;;; 0741;SYRIAC QUSHSHAYA;Mn;230;NSM;;;;;N;;;;; 0742;SYRIAC RUKKAKHA;Mn;220;NSM;;;;;N;;;;; 0743;SYRIAC TWO VERTICAL DOTS ABOVE;Mn;230;NSM;;;;;N;;;;; 0744;SYRIAC TWO VERTICAL DOTS BELOW;Mn;220;NSM;;;;;N;;;;; 0745;SYRIAC THREE DOTS ABOVE;Mn;230;NSM;;;;;N;;;;; 0746;SYRIAC THREE DOTS BELOW;Mn;220;NSM;;;;;N;;;;; 0747;SYRIAC OBLIQUE LINE ABOVE;Mn;230;NSM;;;;;N;;;;; 0748;SYRIAC OBLIQUE LINE BELOW;Mn;220;NSM;;;;;N;;;;; 0749;SYRIAC MUSIC;Mn;230;NSM;;;;;N;;;;; 074A;SYRIAC BARREKH;Mn;230;NSM;;;;;N;;;;; 074D;SYRIAC LETTER SOGDIAN ZHAIN;Lo;0;AL;;;;;N;;;;; 074E;SYRIAC LETTER SOGDIAN KHAPH;Lo;0;AL;;;;;N;;;;; 074F;SYRIAC LETTER SOGDIAN FE;Lo;0;AL;;;;;N;;;;; 0750;ARABIC LETTER BEH WITH THREE DOTS HORIZONTALLY BELOW;Lo;0;AL;;;;;N;;;;; 0751;ARABIC LETTER BEH WITH DOT BELOW AND THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 0752;ARABIC LETTER BEH WITH THREE DOTS POINTING UPWARDS BELOW;Lo;0;AL;;;;;N;;;;; 0753;ARABIC LETTER BEH WITH THREE DOTS POINTING UPWARDS BELOW AND TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 0754;ARABIC LETTER BEH WITH TWO DOTS BELOW AND DOT ABOVE;Lo;0;AL;;;;;N;;;;; 0755;ARABIC LETTER BEH WITH INVERTED SMALL V BELOW;Lo;0;AL;;;;;N;;;;; 0756;ARABIC LETTER BEH WITH SMALL V;Lo;0;AL;;;;;N;;;;; 0757;ARABIC LETTER HAH WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 0758;ARABIC LETTER HAH WITH THREE DOTS POINTING UPWARDS BELOW;Lo;0;AL;;;;;N;;;;; 0759;ARABIC LETTER DAL WITH TWO DOTS VERTICALLY BELOW AND SMALL TAH;Lo;0;AL;;;;;N;;;;; 075A;ARABIC LETTER DAL WITH INVERTED SMALL V BELOW;Lo;0;AL;;;;;N;;;;; 075B;ARABIC LETTER REH WITH STROKE;Lo;0;AL;;;;;N;;;;; 075C;ARABIC LETTER SEEN WITH FOUR DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 075D;ARABIC LETTER AIN WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 075E;ARABIC LETTER AIN WITH THREE DOTS POINTING DOWNWARDS ABOVE;Lo;0;AL;;;;;N;;;;; 075F;ARABIC LETTER AIN WITH TWO DOTS VERTICALLY ABOVE;Lo;0;AL;;;;;N;;;;; 0760;ARABIC LETTER FEH WITH TWO DOTS BELOW;Lo;0;AL;;;;;N;;;;; 0761;ARABIC LETTER FEH WITH THREE DOTS POINTING UPWARDS BELOW;Lo;0;AL;;;;;N;;;;; 0762;ARABIC LETTER KEHEH WITH DOT ABOVE;Lo;0;AL;;;;;N;;;;; 0763;ARABIC LETTER KEHEH WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 0764;ARABIC LETTER KEHEH WITH THREE DOTS POINTING UPWARDS BELOW;Lo;0;AL;;;;;N;;;;; 0765;ARABIC LETTER MEEM WITH DOT ABOVE;Lo;0;AL;;;;;N;;;;; 0766;ARABIC LETTER MEEM WITH DOT BELOW;Lo;0;AL;;;;;N;;;;; 0767;ARABIC LETTER NOON WITH TWO DOTS BELOW;Lo;0;AL;;;;;N;;;;; 0768;ARABIC LETTER NOON WITH SMALL TAH;Lo;0;AL;;;;;N;;;;; 0769;ARABIC LETTER NOON WITH SMALL V;Lo;0;AL;;;;;N;;;;; 076A;ARABIC LETTER LAM WITH BAR;Lo;0;AL;;;;;N;;;;; 076B;ARABIC LETTER REH WITH TWO DOTS VERTICALLY ABOVE;Lo;0;AL;;;;;N;;;;; 076C;ARABIC LETTER REH WITH HAMZA ABOVE;Lo;0;AL;;;;;N;;;;; 076D;ARABIC LETTER SEEN WITH TWO DOTS VERTICALLY ABOVE;Lo;0;AL;;;;;N;;;;; 076E;ARABIC LETTER HAH WITH SMALL ARABIC LETTER TAH BELOW;Lo;0;AL;;;;;N;;;;; 076F;ARABIC LETTER HAH WITH SMALL ARABIC LETTER TAH AND TWO DOTS;Lo;0;AL;;;;;N;;;;; 0770;ARABIC LETTER SEEN WITH SMALL ARABIC LETTER TAH AND TWO DOTS;Lo;0;AL;;;;;N;;;;; 0771;ARABIC LETTER REH WITH SMALL ARABIC LETTER TAH AND TWO DOTS;Lo;0;AL;;;;;N;;;;; 0772;ARABIC LETTER HAH WITH SMALL ARABIC LETTER TAH ABOVE;Lo;0;AL;;;;;N;;;;; 0773;ARABIC LETTER ALEF WITH EXTENDED ARABIC-INDIC DIGIT TWO ABOVE;Lo;0;AL;;;;;N;;;;; 0774;ARABIC LETTER ALEF WITH EXTENDED ARABIC-INDIC DIGIT THREE ABOVE;Lo;0;AL;;;;;N;;;;; 0775;ARABIC LETTER FARSI YEH WITH EXTENDED ARABIC-INDIC DIGIT TWO ABOVE;Lo;0;AL;;;;;N;;;;; 0776;ARABIC LETTER FARSI YEH WITH EXTENDED ARABIC-INDIC DIGIT THREE ABOVE;Lo;0;AL;;;;;N;;;;; 0777;ARABIC LETTER FARSI YEH WITH EXTENDED ARABIC-INDIC DIGIT FOUR BELOW;Lo;0;AL;;;;;N;;;;; 0778;ARABIC LETTER WAW WITH EXTENDED ARABIC-INDIC DIGIT TWO ABOVE;Lo;0;AL;;;;;N;;;;; 0779;ARABIC LETTER WAW WITH EXTENDED ARABIC-INDIC DIGIT THREE ABOVE;Lo;0;AL;;;;;N;;;;; 077A;ARABIC LETTER YEH BARREE WITH EXTENDED ARABIC-INDIC DIGIT TWO ABOVE;Lo;0;AL;;;;;N;;;;; 077B;ARABIC LETTER YEH BARREE WITH EXTENDED ARABIC-INDIC DIGIT THREE ABOVE;Lo;0;AL;;;;;N;;;;; 077C;ARABIC LETTER HAH WITH EXTENDED ARABIC-INDIC DIGIT FOUR BELOW;Lo;0;AL;;;;;N;;;;; 077D;ARABIC LETTER SEEN WITH EXTENDED ARABIC-INDIC DIGIT FOUR ABOVE;Lo;0;AL;;;;;N;;;;; 077E;ARABIC LETTER SEEN WITH INVERTED V;Lo;0;AL;;;;;N;;;;; 077F;ARABIC LETTER KAF WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 0780;THAANA LETTER HAA;Lo;0;AL;;;;;N;;;;; 0781;THAANA LETTER SHAVIYANI;Lo;0;AL;;;;;N;;;;; 0782;THAANA LETTER NOONU;Lo;0;AL;;;;;N;;;;; 0783;THAANA LETTER RAA;Lo;0;AL;;;;;N;;;;; 0784;THAANA LETTER BAA;Lo;0;AL;;;;;N;;;;; 0785;THAANA LETTER LHAVIYANI;Lo;0;AL;;;;;N;;;;; 0786;THAANA LETTER KAAFU;Lo;0;AL;;;;;N;;;;; 0787;THAANA LETTER ALIFU;Lo;0;AL;;;;;N;;;;; 0788;THAANA LETTER VAAVU;Lo;0;AL;;;;;N;;;;; 0789;THAANA LETTER MEEMU;Lo;0;AL;;;;;N;;;;; 078A;THAANA LETTER FAAFU;Lo;0;AL;;;;;N;;;;; 078B;THAANA LETTER DHAALU;Lo;0;AL;;;;;N;;;;; 078C;THAANA LETTER THAA;Lo;0;AL;;;;;N;;;;; 078D;THAANA LETTER LAAMU;Lo;0;AL;;;;;N;;;;; 078E;THAANA LETTER GAAFU;Lo;0;AL;;;;;N;;;;; 078F;THAANA LETTER GNAVIYANI;Lo;0;AL;;;;;N;;;;; 0790;THAANA LETTER SEENU;Lo;0;AL;;;;;N;;;;; 0791;THAANA LETTER DAVIYANI;Lo;0;AL;;;;;N;;;;; 0792;THAANA LETTER ZAVIYANI;Lo;0;AL;;;;;N;;;;; 0793;THAANA LETTER TAVIYANI;Lo;0;AL;;;;;N;;;;; 0794;THAANA LETTER YAA;Lo;0;AL;;;;;N;;;;; 0795;THAANA LETTER PAVIYANI;Lo;0;AL;;;;;N;;;;; 0796;THAANA LETTER JAVIYANI;Lo;0;AL;;;;;N;;;;; 0797;THAANA LETTER CHAVIYANI;Lo;0;AL;;;;;N;;;;; 0798;THAANA LETTER TTAA;Lo;0;AL;;;;;N;;;;; 0799;THAANA LETTER HHAA;Lo;0;AL;;;;;N;;;;; 079A;THAANA LETTER KHAA;Lo;0;AL;;;;;N;;;;; 079B;THAANA LETTER THAALU;Lo;0;AL;;;;;N;;;;; 079C;THAANA LETTER ZAA;Lo;0;AL;;;;;N;;;;; 079D;THAANA LETTER SHEENU;Lo;0;AL;;;;;N;;;;; 079E;THAANA LETTER SAADHU;Lo;0;AL;;;;;N;;;;; 079F;THAANA LETTER DAADHU;Lo;0;AL;;;;;N;;;;; 07A0;THAANA LETTER TO;Lo;0;AL;;;;;N;;;;; 07A1;THAANA LETTER ZO;Lo;0;AL;;;;;N;;;;; 07A2;THAANA LETTER AINU;Lo;0;AL;;;;;N;;;;; 07A3;THAANA LETTER GHAINU;Lo;0;AL;;;;;N;;;;; 07A4;THAANA LETTER QAAFU;Lo;0;AL;;;;;N;;;;; 07A5;THAANA LETTER WAAVU;Lo;0;AL;;;;;N;;;;; 07A6;THAANA ABAFILI;Mn;0;NSM;;;;;N;;;;; 07A7;THAANA AABAAFILI;Mn;0;NSM;;;;;N;;;;; 07A8;THAANA IBIFILI;Mn;0;NSM;;;;;N;;;;; 07A9;THAANA EEBEEFILI;Mn;0;NSM;;;;;N;;;;; 07AA;THAANA UBUFILI;Mn;0;NSM;;;;;N;;;;; 07AB;THAANA OOBOOFILI;Mn;0;NSM;;;;;N;;;;; 07AC;THAANA EBEFILI;Mn;0;NSM;;;;;N;;;;; 07AD;THAANA EYBEYFILI;Mn;0;NSM;;;;;N;;;;; 07AE;THAANA OBOFILI;Mn;0;NSM;;;;;N;;;;; 07AF;THAANA OABOAFILI;Mn;0;NSM;;;;;N;;;;; 07B0;THAANA SUKUN;Mn;0;NSM;;;;;N;;;;; 07B1;THAANA LETTER NAA;Lo;0;AL;;;;;N;;;;; 07C0;NKO DIGIT ZERO;Nd;0;R;;0;0;0;N;;;;; 07C1;NKO DIGIT ONE;Nd;0;R;;1;1;1;N;;;;; 07C2;NKO DIGIT TWO;Nd;0;R;;2;2;2;N;;;;; 07C3;NKO DIGIT THREE;Nd;0;R;;3;3;3;N;;;;; 07C4;NKO DIGIT FOUR;Nd;0;R;;4;4;4;N;;;;; 07C5;NKO DIGIT FIVE;Nd;0;R;;5;5;5;N;;;;; 07C6;NKO DIGIT SIX;Nd;0;R;;6;6;6;N;;;;; 07C7;NKO DIGIT SEVEN;Nd;0;R;;7;7;7;N;;;;; 07C8;NKO DIGIT EIGHT;Nd;0;R;;8;8;8;N;;;;; 07C9;NKO DIGIT NINE;Nd;0;R;;9;9;9;N;;;;; 07CA;NKO LETTER A;Lo;0;R;;;;;N;;;;; 07CB;NKO LETTER EE;Lo;0;R;;;;;N;;;;; 07CC;NKO LETTER I;Lo;0;R;;;;;N;;;;; 07CD;NKO LETTER E;Lo;0;R;;;;;N;;;;; 07CE;NKO LETTER U;Lo;0;R;;;;;N;;;;; 07CF;NKO LETTER OO;Lo;0;R;;;;;N;;;;; 07D0;NKO LETTER O;Lo;0;R;;;;;N;;;;; 07D1;NKO LETTER DAGBASINNA;Lo;0;R;;;;;N;;;;; 07D2;NKO LETTER N;Lo;0;R;;;;;N;;;;; 07D3;NKO LETTER BA;Lo;0;R;;;;;N;;;;; 07D4;NKO LETTER PA;Lo;0;R;;;;;N;;;;; 07D5;NKO LETTER TA;Lo;0;R;;;;;N;;;;; 07D6;NKO LETTER JA;Lo;0;R;;;;;N;;;;; 07D7;NKO LETTER CHA;Lo;0;R;;;;;N;;;;; 07D8;NKO LETTER DA;Lo;0;R;;;;;N;;;;; 07D9;NKO LETTER RA;Lo;0;R;;;;;N;;;;; 07DA;NKO LETTER RRA;Lo;0;R;;;;;N;;;;; 07DB;NKO LETTER SA;Lo;0;R;;;;;N;;;;; 07DC;NKO LETTER GBA;Lo;0;R;;;;;N;;;;; 07DD;NKO LETTER FA;Lo;0;R;;;;;N;;;;; 07DE;NKO LETTER KA;Lo;0;R;;;;;N;;;;; 07DF;NKO LETTER LA;Lo;0;R;;;;;N;;;;; 07E0;NKO LETTER NA WOLOSO;Lo;0;R;;;;;N;;;;; 07E1;NKO LETTER MA;Lo;0;R;;;;;N;;;;; 07E2;NKO LETTER NYA;Lo;0;R;;;;;N;;;;; 07E3;NKO LETTER NA;Lo;0;R;;;;;N;;;;; 07E4;NKO LETTER HA;Lo;0;R;;;;;N;;;;; 07E5;NKO LETTER WA;Lo;0;R;;;;;N;;;;; 07E6;NKO LETTER YA;Lo;0;R;;;;;N;;;;; 07E7;NKO LETTER NYA WOLOSO;Lo;0;R;;;;;N;;;;; 07E8;NKO LETTER JONA JA;Lo;0;R;;;;;N;;;;; 07E9;NKO LETTER JONA CHA;Lo;0;R;;;;;N;;;;; 07EA;NKO LETTER JONA RA;Lo;0;R;;;;;N;;;;; 07EB;NKO COMBINING SHORT HIGH TONE;Mn;230;NSM;;;;;N;;;;; 07EC;NKO COMBINING SHORT LOW TONE;Mn;230;NSM;;;;;N;;;;; 07ED;NKO COMBINING SHORT RISING TONE;Mn;230;NSM;;;;;N;;;;; 07EE;NKO COMBINING LONG DESCENDING TONE;Mn;230;NSM;;;;;N;;;;; 07EF;NKO COMBINING LONG HIGH TONE;Mn;230;NSM;;;;;N;;;;; 07F0;NKO COMBINING LONG LOW TONE;Mn;230;NSM;;;;;N;;;;; 07F1;NKO COMBINING LONG RISING TONE;Mn;230;NSM;;;;;N;;;;; 07F2;NKO COMBINING NASALIZATION MARK;Mn;220;NSM;;;;;N;;;;; 07F3;NKO COMBINING DOUBLE DOT ABOVE;Mn;230;NSM;;;;;N;;;;; 07F4;NKO HIGH TONE APOSTROPHE;Lm;0;R;;;;;N;;;;; 07F5;NKO LOW TONE APOSTROPHE;Lm;0;R;;;;;N;;;;; 07F6;NKO SYMBOL OO DENNEN;So;0;ON;;;;;N;;;;; 07F7;NKO SYMBOL GBAKURUNEN;Po;0;ON;;;;;N;;;;; 07F8;NKO COMMA;Po;0;ON;;;;;N;;;;; 07F9;NKO EXCLAMATION MARK;Po;0;ON;;;;;N;;;;; 07FA;NKO LAJANYALAN;Lm;0;R;;;;;N;;;;; 0800;SAMARITAN LETTER ALAF;Lo;0;R;;;;;N;;;;; 0801;SAMARITAN LETTER BIT;Lo;0;R;;;;;N;;;;; 0802;SAMARITAN LETTER GAMAN;Lo;0;R;;;;;N;;;;; 0803;SAMARITAN LETTER DALAT;Lo;0;R;;;;;N;;;;; 0804;SAMARITAN LETTER IY;Lo;0;R;;;;;N;;;;; 0805;SAMARITAN LETTER BAA;Lo;0;R;;;;;N;;;;; 0806;SAMARITAN LETTER ZEN;Lo;0;R;;;;;N;;;;; 0807;SAMARITAN LETTER IT;Lo;0;R;;;;;N;;;;; 0808;SAMARITAN LETTER TIT;Lo;0;R;;;;;N;;;;; 0809;SAMARITAN LETTER YUT;Lo;0;R;;;;;N;;;;; 080A;SAMARITAN LETTER KAAF;Lo;0;R;;;;;N;;;;; 080B;SAMARITAN LETTER LABAT;Lo;0;R;;;;;N;;;;; 080C;SAMARITAN LETTER MIM;Lo;0;R;;;;;N;;;;; 080D;SAMARITAN LETTER NUN;Lo;0;R;;;;;N;;;;; 080E;SAMARITAN LETTER SINGAAT;Lo;0;R;;;;;N;;;;; 080F;SAMARITAN LETTER IN;Lo;0;R;;;;;N;;;;; 0810;SAMARITAN LETTER FI;Lo;0;R;;;;;N;;;;; 0811;SAMARITAN LETTER TSAADIY;Lo;0;R;;;;;N;;;;; 0812;SAMARITAN LETTER QUF;Lo;0;R;;;;;N;;;;; 0813;SAMARITAN LETTER RISH;Lo;0;R;;;;;N;;;;; 0814;SAMARITAN LETTER SHAN;Lo;0;R;;;;;N;;;;; 0815;SAMARITAN LETTER TAAF;Lo;0;R;;;;;N;;;;; 0816;SAMARITAN MARK IN;Mn;230;NSM;;;;;N;;;;; 0817;SAMARITAN MARK IN-ALAF;Mn;230;NSM;;;;;N;;;;; 0818;SAMARITAN MARK OCCLUSION;Mn;230;NSM;;;;;N;;;;; 0819;SAMARITAN MARK DAGESH;Mn;230;NSM;;;;;N;;;;; 081A;SAMARITAN MODIFIER LETTER EPENTHETIC YUT;Lm;0;R;;;;;N;;;;; 081B;SAMARITAN MARK EPENTHETIC YUT;Mn;230;NSM;;;;;N;;;;; 081C;SAMARITAN VOWEL SIGN LONG E;Mn;230;NSM;;;;;N;;;;; 081D;SAMARITAN VOWEL SIGN E;Mn;230;NSM;;;;;N;;;;; 081E;SAMARITAN VOWEL SIGN OVERLONG AA;Mn;230;NSM;;;;;N;;;;; 081F;SAMARITAN VOWEL SIGN LONG AA;Mn;230;NSM;;;;;N;;;;; 0820;SAMARITAN VOWEL SIGN AA;Mn;230;NSM;;;;;N;;;;; 0821;SAMARITAN VOWEL SIGN OVERLONG A;Mn;230;NSM;;;;;N;;;;; 0822;SAMARITAN VOWEL SIGN LONG A;Mn;230;NSM;;;;;N;;;;; 0823;SAMARITAN VOWEL SIGN A;Mn;230;NSM;;;;;N;;;;; 0824;SAMARITAN MODIFIER LETTER SHORT A;Lm;0;R;;;;;N;;;;; 0825;SAMARITAN VOWEL SIGN SHORT A;Mn;230;NSM;;;;;N;;;;; 0826;SAMARITAN VOWEL SIGN LONG U;Mn;230;NSM;;;;;N;;;;; 0827;SAMARITAN VOWEL SIGN U;Mn;230;NSM;;;;;N;;;;; 0828;SAMARITAN MODIFIER LETTER I;Lm;0;R;;;;;N;;;;; 0829;SAMARITAN VOWEL SIGN LONG I;Mn;230;NSM;;;;;N;;;;; 082A;SAMARITAN VOWEL SIGN I;Mn;230;NSM;;;;;N;;;;; 082B;SAMARITAN VOWEL SIGN O;Mn;230;NSM;;;;;N;;;;; 082C;SAMARITAN VOWEL SIGN SUKUN;Mn;230;NSM;;;;;N;;;;; 082D;SAMARITAN MARK NEQUDAA;Mn;230;NSM;;;;;N;;;;; 0830;SAMARITAN PUNCTUATION NEQUDAA;Po;0;R;;;;;N;;;;; 0831;SAMARITAN PUNCTUATION AFSAAQ;Po;0;R;;;;;N;;;;; 0832;SAMARITAN PUNCTUATION ANGED;Po;0;R;;;;;N;;;;; 0833;SAMARITAN PUNCTUATION BAU;Po;0;R;;;;;N;;;;; 0834;SAMARITAN PUNCTUATION ATMAAU;Po;0;R;;;;;N;;;;; 0835;SAMARITAN PUNCTUATION SHIYYAALAA;Po;0;R;;;;;N;;;;; 0836;SAMARITAN ABBREVIATION MARK;Po;0;R;;;;;N;;;;; 0837;SAMARITAN PUNCTUATION MELODIC QITSA;Po;0;R;;;;;N;;;;; 0838;SAMARITAN PUNCTUATION ZIQAA;Po;0;R;;;;;N;;;;; 0839;SAMARITAN PUNCTUATION QITSA;Po;0;R;;;;;N;;;;; 083A;SAMARITAN PUNCTUATION ZAEF;Po;0;R;;;;;N;;;;; 083B;SAMARITAN PUNCTUATION TURU;Po;0;R;;;;;N;;;;; 083C;SAMARITAN PUNCTUATION ARKAANU;Po;0;R;;;;;N;;;;; 083D;SAMARITAN PUNCTUATION SOF MASHFAAT;Po;0;R;;;;;N;;;;; 083E;SAMARITAN PUNCTUATION ANNAAU;Po;0;R;;;;;N;;;;; 0840;MANDAIC LETTER HALQA;Lo;0;R;;;;;N;;;;; 0841;MANDAIC LETTER AB;Lo;0;R;;;;;N;;;;; 0842;MANDAIC LETTER AG;Lo;0;R;;;;;N;;;;; 0843;MANDAIC LETTER AD;Lo;0;R;;;;;N;;;;; 0844;MANDAIC LETTER AH;Lo;0;R;;;;;N;;;;; 0845;MANDAIC LETTER USHENNA;Lo;0;R;;;;;N;;;;; 0846;MANDAIC LETTER AZ;Lo;0;R;;;;;N;;;;; 0847;MANDAIC LETTER IT;Lo;0;R;;;;;N;;;;; 0848;MANDAIC LETTER ATT;Lo;0;R;;;;;N;;;;; 0849;MANDAIC LETTER AKSA;Lo;0;R;;;;;N;;;;; 084A;MANDAIC LETTER AK;Lo;0;R;;;;;N;;;;; 084B;MANDAIC LETTER AL;Lo;0;R;;;;;N;;;;; 084C;MANDAIC LETTER AM;Lo;0;R;;;;;N;;;;; 084D;MANDAIC LETTER AN;Lo;0;R;;;;;N;;;;; 084E;MANDAIC LETTER AS;Lo;0;R;;;;;N;;;;; 084F;MANDAIC LETTER IN;Lo;0;R;;;;;N;;;;; 0850;MANDAIC LETTER AP;Lo;0;R;;;;;N;;;;; 0851;MANDAIC LETTER ASZ;Lo;0;R;;;;;N;;;;; 0852;MANDAIC LETTER AQ;Lo;0;R;;;;;N;;;;; 0853;MANDAIC LETTER AR;Lo;0;R;;;;;N;;;;; 0854;MANDAIC LETTER ASH;Lo;0;R;;;;;N;;;;; 0855;MANDAIC LETTER AT;Lo;0;R;;;;;N;;;;; 0856;MANDAIC LETTER DUSHENNA;Lo;0;R;;;;;N;;;;; 0857;MANDAIC LETTER KAD;Lo;0;R;;;;;N;;;;; 0858;MANDAIC LETTER AIN;Lo;0;R;;;;;N;;;;; 0859;MANDAIC AFFRICATION MARK;Mn;220;NSM;;;;;N;;;;; 085A;MANDAIC VOCALIZATION MARK;Mn;220;NSM;;;;;N;;;;; 085B;MANDAIC GEMINATION MARK;Mn;220;NSM;;;;;N;;;;; 085E;MANDAIC PUNCTUATION;Po;0;R;;;;;N;;;;; 08A0;ARABIC LETTER BEH WITH SMALL V BELOW;Lo;0;AL;;;;;N;;;;; 08A1;ARABIC LETTER BEH WITH HAMZA ABOVE;Lo;0;AL;;;;;N;;;;; 08A2;ARABIC LETTER JEEM WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 08A3;ARABIC LETTER TAH WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 08A4;ARABIC LETTER FEH WITH DOT BELOW AND THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 08A5;ARABIC LETTER QAF WITH DOT BELOW;Lo;0;AL;;;;;N;;;;; 08A6;ARABIC LETTER LAM WITH DOUBLE BAR;Lo;0;AL;;;;;N;;;;; 08A7;ARABIC LETTER MEEM WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; 08A8;ARABIC LETTER YEH WITH TWO DOTS BELOW AND HAMZA ABOVE;Lo;0;AL;;;;;N;;;;; 08A9;ARABIC LETTER YEH WITH TWO DOTS BELOW AND DOT ABOVE;Lo;0;AL;;;;;N;;;;; 08AA;ARABIC LETTER REH WITH LOOP;Lo;0;AL;;;;;N;;;;; 08AB;ARABIC LETTER WAW WITH DOT WITHIN;Lo;0;AL;;;;;N;;;;; 08AC;ARABIC LETTER ROHINGYA YEH;Lo;0;AL;;;;;N;;;;; 08AD;ARABIC LETTER LOW ALEF;Lo;0;AL;;;;;N;;;;; 08AE;ARABIC LETTER DAL WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;;;;; 08AF;ARABIC LETTER SAD WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;;;;; 08B0;ARABIC LETTER GAF WITH INVERTED STROKE;Lo;0;AL;;;;;N;;;;; 08B1;ARABIC LETTER STRAIGHT WAW;Lo;0;AL;;;;;N;;;;; 08B2;ARABIC LETTER ZAIN WITH INVERTED V ABOVE;Lo;0;AL;;;;;N;;;;; 08B3;ARABIC LETTER AIN WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;;;;; 08B4;ARABIC LETTER KAF WITH DOT BELOW;Lo;0;AL;;;;;N;;;;; 08B6;ARABIC LETTER BEH WITH SMALL MEEM ABOVE;Lo;0;AL;;;;;N;;;;; 08B7;ARABIC LETTER PEH WITH SMALL MEEM ABOVE;Lo;0;AL;;;;;N;;;;; 08B8;ARABIC LETTER TEH WITH SMALL TEH ABOVE;Lo;0;AL;;;;;N;;;;; 08B9;ARABIC LETTER REH WITH SMALL NOON ABOVE;Lo;0;AL;;;;;N;;;;; 08BA;ARABIC LETTER YEH WITH TWO DOTS BELOW AND SMALL NOON ABOVE;Lo;0;AL;;;;;N;;;;; 08BB;ARABIC LETTER AFRICAN FEH;Lo;0;AL;;;;;N;;;;; 08BC;ARABIC LETTER AFRICAN QAF;Lo;0;AL;;;;;N;;;;; 08BD;ARABIC LETTER AFRICAN NOON;Lo;0;AL;;;;;N;;;;; 08D4;ARABIC SMALL HIGH WORD AR-RUB;Mn;230;NSM;;;;;N;;;;; 08D5;ARABIC SMALL HIGH SAD;Mn;230;NSM;;;;;N;;;;; 08D6;ARABIC SMALL HIGH AIN;Mn;230;NSM;;;;;N;;;;; 08D7;ARABIC SMALL HIGH QAF;Mn;230;NSM;;;;;N;;;;; 08D8;ARABIC SMALL HIGH NOON WITH KASRA;Mn;230;NSM;;;;;N;;;;; 08D9;ARABIC SMALL LOW NOON WITH KASRA;Mn;230;NSM;;;;;N;;;;; 08DA;ARABIC SMALL HIGH WORD ATH-THALATHA;Mn;230;NSM;;;;;N;;;;; 08DB;ARABIC SMALL HIGH WORD AS-SAJDA;Mn;230;NSM;;;;;N;;;;; 08DC;ARABIC SMALL HIGH WORD AN-NISF;Mn;230;NSM;;;;;N;;;;; 08DD;ARABIC SMALL HIGH WORD SAKTA;Mn;230;NSM;;;;;N;;;;; 08DE;ARABIC SMALL HIGH WORD QIF;Mn;230;NSM;;;;;N;;;;; 08DF;ARABIC SMALL HIGH WORD WAQFA;Mn;230;NSM;;;;;N;;;;; 08E0;ARABIC SMALL HIGH FOOTNOTE MARKER;Mn;230;NSM;;;;;N;;;;; 08E1;ARABIC SMALL HIGH SIGN SAFHA;Mn;230;NSM;;;;;N;;;;; 08E2;ARABIC DISPUTED END OF AYAH;Cf;0;AN;;;;;N;;;;; 08E3;ARABIC TURNED DAMMA BELOW;Mn;220;NSM;;;;;N;;;;; 08E4;ARABIC CURLY FATHA;Mn;230;NSM;;;;;N;;;;; 08E5;ARABIC CURLY DAMMA;Mn;230;NSM;;;;;N;;;;; 08E6;ARABIC CURLY KASRA;Mn;220;NSM;;;;;N;;;;; 08E7;ARABIC CURLY FATHATAN;Mn;230;NSM;;;;;N;;;;; 08E8;ARABIC CURLY DAMMATAN;Mn;230;NSM;;;;;N;;;;; 08E9;ARABIC CURLY KASRATAN;Mn;220;NSM;;;;;N;;;;; 08EA;ARABIC TONE ONE DOT ABOVE;Mn;230;NSM;;;;;N;;;;; 08EB;ARABIC TONE TWO DOTS ABOVE;Mn;230;NSM;;;;;N;;;;; 08EC;ARABIC TONE LOOP ABOVE;Mn;230;NSM;;;;;N;;;;; 08ED;ARABIC TONE ONE DOT BELOW;Mn;220;NSM;;;;;N;;;;; 08EE;ARABIC TONE TWO DOTS BELOW;Mn;220;NSM;;;;;N;;;;; 08EF;ARABIC TONE LOOP BELOW;Mn;220;NSM;;;;;N;;;;; 08F0;ARABIC OPEN FATHATAN;Mn;27;NSM;;;;;N;;;;; 08F1;ARABIC OPEN DAMMATAN;Mn;28;NSM;;;;;N;;;;; 08F2;ARABIC OPEN KASRATAN;Mn;29;NSM;;;;;N;;;;; 08F3;ARABIC SMALL HIGH WAW;Mn;230;NSM;;;;;N;;;;; 08F4;ARABIC FATHA WITH RING;Mn;230;NSM;;;;;N;;;;; 08F5;ARABIC FATHA WITH DOT ABOVE;Mn;230;NSM;;;;;N;;;;; 08F6;ARABIC KASRA WITH DOT BELOW;Mn;220;NSM;;;;;N;;;;; 08F7;ARABIC LEFT ARROWHEAD ABOVE;Mn;230;NSM;;;;;N;;;;; 08F8;ARABIC RIGHT ARROWHEAD ABOVE;Mn;230;NSM;;;;;N;;;;; 08F9;ARABIC LEFT ARROWHEAD BELOW;Mn;220;NSM;;;;;N;;;;; 08FA;ARABIC RIGHT ARROWHEAD BELOW;Mn;220;NSM;;;;;N;;;;; 08FB;ARABIC DOUBLE RIGHT ARROWHEAD ABOVE;Mn;230;NSM;;;;;N;;;;; 08FC;ARABIC DOUBLE RIGHT ARROWHEAD ABOVE WITH DOT;Mn;230;NSM;;;;;N;;;;; 08FD;ARABIC RIGHT ARROWHEAD ABOVE WITH DOT;Mn;230;NSM;;;;;N;;;;; 08FE;ARABIC DAMMA WITH DOT;Mn;230;NSM;;;;;N;;;;; 08FF;ARABIC MARK SIDEWAYS NOON GHUNNA;Mn;230;NSM;;;;;N;;;;; 0900;DEVANAGARI SIGN INVERTED CANDRABINDU;Mn;0;NSM;;;;;N;;;;; 0901;DEVANAGARI SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; 0902;DEVANAGARI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; 0903;DEVANAGARI SIGN VISARGA;Mc;0;L;;;;;N;;;;; 0904;DEVANAGARI LETTER SHORT A;Lo;0;L;;;;;N;;;;; 0905;DEVANAGARI LETTER A;Lo;0;L;;;;;N;;;;; 0906;DEVANAGARI LETTER AA;Lo;0;L;;;;;N;;;;; 0907;DEVANAGARI LETTER I;Lo;0;L;;;;;N;;;;; 0908;DEVANAGARI LETTER II;Lo;0;L;;;;;N;;;;; 0909;DEVANAGARI LETTER U;Lo;0;L;;;;;N;;;;; 090A;DEVANAGARI LETTER UU;Lo;0;L;;;;;N;;;;; 090B;DEVANAGARI LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; 090C;DEVANAGARI LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; 090D;DEVANAGARI LETTER CANDRA E;Lo;0;L;;;;;N;;;;; 090E;DEVANAGARI LETTER SHORT E;Lo;0;L;;;;;N;;;;; 090F;DEVANAGARI LETTER E;Lo;0;L;;;;;N;;;;; 0910;DEVANAGARI LETTER AI;Lo;0;L;;;;;N;;;;; 0911;DEVANAGARI LETTER CANDRA O;Lo;0;L;;;;;N;;;;; 0912;DEVANAGARI LETTER SHORT O;Lo;0;L;;;;;N;;;;; 0913;DEVANAGARI LETTER O;Lo;0;L;;;;;N;;;;; 0914;DEVANAGARI LETTER AU;Lo;0;L;;;;;N;;;;; 0915;DEVANAGARI LETTER KA;Lo;0;L;;;;;N;;;;; 0916;DEVANAGARI LETTER KHA;Lo;0;L;;;;;N;;;;; 0917;DEVANAGARI LETTER GA;Lo;0;L;;;;;N;;;;; 0918;DEVANAGARI LETTER GHA;Lo;0;L;;;;;N;;;;; 0919;DEVANAGARI LETTER NGA;Lo;0;L;;;;;N;;;;; 091A;DEVANAGARI LETTER CA;Lo;0;L;;;;;N;;;;; 091B;DEVANAGARI LETTER CHA;Lo;0;L;;;;;N;;;;; 091C;DEVANAGARI LETTER JA;Lo;0;L;;;;;N;;;;; 091D;DEVANAGARI LETTER JHA;Lo;0;L;;;;;N;;;;; 091E;DEVANAGARI LETTER NYA;Lo;0;L;;;;;N;;;;; 091F;DEVANAGARI LETTER TTA;Lo;0;L;;;;;N;;;;; 0920;DEVANAGARI LETTER TTHA;Lo;0;L;;;;;N;;;;; 0921;DEVANAGARI LETTER DDA;Lo;0;L;;;;;N;;;;; 0922;DEVANAGARI LETTER DDHA;Lo;0;L;;;;;N;;;;; 0923;DEVANAGARI LETTER NNA;Lo;0;L;;;;;N;;;;; 0924;DEVANAGARI LETTER TA;Lo;0;L;;;;;N;;;;; 0925;DEVANAGARI LETTER THA;Lo;0;L;;;;;N;;;;; 0926;DEVANAGARI LETTER DA;Lo;0;L;;;;;N;;;;; 0927;DEVANAGARI LETTER DHA;Lo;0;L;;;;;N;;;;; 0928;DEVANAGARI LETTER NA;Lo;0;L;;;;;N;;;;; 0929;DEVANAGARI LETTER NNNA;Lo;0;L;0928 093C;;;;N;;;;; 092A;DEVANAGARI LETTER PA;Lo;0;L;;;;;N;;;;; 092B;DEVANAGARI LETTER PHA;Lo;0;L;;;;;N;;;;; 092C;DEVANAGARI LETTER BA;Lo;0;L;;;;;N;;;;; 092D;DEVANAGARI LETTER BHA;Lo;0;L;;;;;N;;;;; 092E;DEVANAGARI LETTER MA;Lo;0;L;;;;;N;;;;; 092F;DEVANAGARI LETTER YA;Lo;0;L;;;;;N;;;;; 0930;DEVANAGARI LETTER RA;Lo;0;L;;;;;N;;;;; 0931;DEVANAGARI LETTER RRA;Lo;0;L;0930 093C;;;;N;;;;; 0932;DEVANAGARI LETTER LA;Lo;0;L;;;;;N;;;;; 0933;DEVANAGARI LETTER LLA;Lo;0;L;;;;;N;;;;; 0934;DEVANAGARI LETTER LLLA;Lo;0;L;0933 093C;;;;N;;;;; 0935;DEVANAGARI LETTER VA;Lo;0;L;;;;;N;;;;; 0936;DEVANAGARI LETTER SHA;Lo;0;L;;;;;N;;;;; 0937;DEVANAGARI LETTER SSA;Lo;0;L;;;;;N;;;;; 0938;DEVANAGARI LETTER SA;Lo;0;L;;;;;N;;;;; 0939;DEVANAGARI LETTER HA;Lo;0;L;;;;;N;;;;; 093A;DEVANAGARI VOWEL SIGN OE;Mn;0;NSM;;;;;N;;;;; 093B;DEVANAGARI VOWEL SIGN OOE;Mc;0;L;;;;;N;;;;; 093C;DEVANAGARI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; 093D;DEVANAGARI SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; 093E;DEVANAGARI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 093F;DEVANAGARI VOWEL SIGN I;Mc;0;L;;;;;N;;;;; 0940;DEVANAGARI VOWEL SIGN II;Mc;0;L;;;;;N;;;;; 0941;DEVANAGARI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 0942;DEVANAGARI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 0943;DEVANAGARI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; 0944;DEVANAGARI VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; 0945;DEVANAGARI VOWEL SIGN CANDRA E;Mn;0;NSM;;;;;N;;;;; 0946;DEVANAGARI VOWEL SIGN SHORT E;Mn;0;NSM;;;;;N;;;;; 0947;DEVANAGARI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; 0948;DEVANAGARI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; 0949;DEVANAGARI VOWEL SIGN CANDRA O;Mc;0;L;;;;;N;;;;; 094A;DEVANAGARI VOWEL SIGN SHORT O;Mc;0;L;;;;;N;;;;; 094B;DEVANAGARI VOWEL SIGN O;Mc;0;L;;;;;N;;;;; 094C;DEVANAGARI VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; 094D;DEVANAGARI SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 094E;DEVANAGARI VOWEL SIGN PRISHTHAMATRA E;Mc;0;L;;;;;N;;;;; 094F;DEVANAGARI VOWEL SIGN AW;Mc;0;L;;;;;N;;;;; 0950;DEVANAGARI OM;Lo;0;L;;;;;N;;;;; 0951;DEVANAGARI STRESS SIGN UDATTA;Mn;230;NSM;;;;;N;;;;; 0952;DEVANAGARI STRESS SIGN ANUDATTA;Mn;220;NSM;;;;;N;;;;; 0953;DEVANAGARI GRAVE ACCENT;Mn;230;NSM;;;;;N;;;;; 0954;DEVANAGARI ACUTE ACCENT;Mn;230;NSM;;;;;N;;;;; 0955;DEVANAGARI VOWEL SIGN CANDRA LONG E;Mn;0;NSM;;;;;N;;;;; 0956;DEVANAGARI VOWEL SIGN UE;Mn;0;NSM;;;;;N;;;;; 0957;DEVANAGARI VOWEL SIGN UUE;Mn;0;NSM;;;;;N;;;;; 0958;DEVANAGARI LETTER QA;Lo;0;L;0915 093C;;;;N;;;;; 0959;DEVANAGARI LETTER KHHA;Lo;0;L;0916 093C;;;;N;;;;; 095A;DEVANAGARI LETTER GHHA;Lo;0;L;0917 093C;;;;N;;;;; 095B;DEVANAGARI LETTER ZA;Lo;0;L;091C 093C;;;;N;;;;; 095C;DEVANAGARI LETTER DDDHA;Lo;0;L;0921 093C;;;;N;;;;; 095D;DEVANAGARI LETTER RHA;Lo;0;L;0922 093C;;;;N;;;;; 095E;DEVANAGARI LETTER FA;Lo;0;L;092B 093C;;;;N;;;;; 095F;DEVANAGARI LETTER YYA;Lo;0;L;092F 093C;;;;N;;;;; 0960;DEVANAGARI LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; 0961;DEVANAGARI LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; 0962;DEVANAGARI VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; 0963;DEVANAGARI VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; 0964;DEVANAGARI DANDA;Po;0;L;;;;;N;;;;; 0965;DEVANAGARI DOUBLE DANDA;Po;0;L;;;;;N;;;;; 0966;DEVANAGARI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 0967;DEVANAGARI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 0968;DEVANAGARI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 0969;DEVANAGARI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 096A;DEVANAGARI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 096B;DEVANAGARI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 096C;DEVANAGARI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 096D;DEVANAGARI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 096E;DEVANAGARI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 096F;DEVANAGARI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 0970;DEVANAGARI ABBREVIATION SIGN;Po;0;L;;;;;N;;;;; 0971;DEVANAGARI SIGN HIGH SPACING DOT;Lm;0;L;;;;;N;;;;; 0972;DEVANAGARI LETTER CANDRA A;Lo;0;L;;;;;N;;;;; 0973;DEVANAGARI LETTER OE;Lo;0;L;;;;;N;;;;; 0974;DEVANAGARI LETTER OOE;Lo;0;L;;;;;N;;;;; 0975;DEVANAGARI LETTER AW;Lo;0;L;;;;;N;;;;; 0976;DEVANAGARI LETTER UE;Lo;0;L;;;;;N;;;;; 0977;DEVANAGARI LETTER UUE;Lo;0;L;;;;;N;;;;; 0978;DEVANAGARI LETTER MARWARI DDA;Lo;0;L;;;;;N;;;;; 0979;DEVANAGARI LETTER ZHA;Lo;0;L;;;;;N;;;;; 097A;DEVANAGARI LETTER HEAVY YA;Lo;0;L;;;;;N;;;;; 097B;DEVANAGARI LETTER GGA;Lo;0;L;;;;;N;;;;; 097C;DEVANAGARI LETTER JJA;Lo;0;L;;;;;N;;;;; 097D;DEVANAGARI LETTER GLOTTAL STOP;Lo;0;L;;;;;N;;;;; 097E;DEVANAGARI LETTER DDDA;Lo;0;L;;;;;N;;;;; 097F;DEVANAGARI LETTER BBA;Lo;0;L;;;;;N;;;;; 0980;BENGALI ANJI;Lo;0;L;;;;;N;;;;; 0981;BENGALI SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; 0982;BENGALI SIGN ANUSVARA;Mc;0;L;;;;;N;;;;; 0983;BENGALI SIGN VISARGA;Mc;0;L;;;;;N;;;;; 0985;BENGALI LETTER A;Lo;0;L;;;;;N;;;;; 0986;BENGALI LETTER AA;Lo;0;L;;;;;N;;;;; 0987;BENGALI LETTER I;Lo;0;L;;;;;N;;;;; 0988;BENGALI LETTER II;Lo;0;L;;;;;N;;;;; 0989;BENGALI LETTER U;Lo;0;L;;;;;N;;;;; 098A;BENGALI LETTER UU;Lo;0;L;;;;;N;;;;; 098B;BENGALI LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; 098C;BENGALI LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; 098F;BENGALI LETTER E;Lo;0;L;;;;;N;;;;; 0990;BENGALI LETTER AI;Lo;0;L;;;;;N;;;;; 0993;BENGALI LETTER O;Lo;0;L;;;;;N;;;;; 0994;BENGALI LETTER AU;Lo;0;L;;;;;N;;;;; 0995;BENGALI LETTER KA;Lo;0;L;;;;;N;;;;; 0996;BENGALI LETTER KHA;Lo;0;L;;;;;N;;;;; 0997;BENGALI LETTER GA;Lo;0;L;;;;;N;;;;; 0998;BENGALI LETTER GHA;Lo;0;L;;;;;N;;;;; 0999;BENGALI LETTER NGA;Lo;0;L;;;;;N;;;;; 099A;BENGALI LETTER CA;Lo;0;L;;;;;N;;;;; 099B;BENGALI LETTER CHA;Lo;0;L;;;;;N;;;;; 099C;BENGALI LETTER JA;Lo;0;L;;;;;N;;;;; 099D;BENGALI LETTER JHA;Lo;0;L;;;;;N;;;;; 099E;BENGALI LETTER NYA;Lo;0;L;;;;;N;;;;; 099F;BENGALI LETTER TTA;Lo;0;L;;;;;N;;;;; 09A0;BENGALI LETTER TTHA;Lo;0;L;;;;;N;;;;; 09A1;BENGALI LETTER DDA;Lo;0;L;;;;;N;;;;; 09A2;BENGALI LETTER DDHA;Lo;0;L;;;;;N;;;;; 09A3;BENGALI LETTER NNA;Lo;0;L;;;;;N;;;;; 09A4;BENGALI LETTER TA;Lo;0;L;;;;;N;;;;; 09A5;BENGALI LETTER THA;Lo;0;L;;;;;N;;;;; 09A6;BENGALI LETTER DA;Lo;0;L;;;;;N;;;;; 09A7;BENGALI LETTER DHA;Lo;0;L;;;;;N;;;;; 09A8;BENGALI LETTER NA;Lo;0;L;;;;;N;;;;; 09AA;BENGALI LETTER PA;Lo;0;L;;;;;N;;;;; 09AB;BENGALI LETTER PHA;Lo;0;L;;;;;N;;;;; 09AC;BENGALI LETTER BA;Lo;0;L;;;;;N;;;;; 09AD;BENGALI LETTER BHA;Lo;0;L;;;;;N;;;;; 09AE;BENGALI LETTER MA;Lo;0;L;;;;;N;;;;; 09AF;BENGALI LETTER YA;Lo;0;L;;;;;N;;;;; 09B0;BENGALI LETTER RA;Lo;0;L;;;;;N;;;;; 09B2;BENGALI LETTER LA;Lo;0;L;;;;;N;;;;; 09B6;BENGALI LETTER SHA;Lo;0;L;;;;;N;;;;; 09B7;BENGALI LETTER SSA;Lo;0;L;;;;;N;;;;; 09B8;BENGALI LETTER SA;Lo;0;L;;;;;N;;;;; 09B9;BENGALI LETTER HA;Lo;0;L;;;;;N;;;;; 09BC;BENGALI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; 09BD;BENGALI SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; 09BE;BENGALI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 09BF;BENGALI VOWEL SIGN I;Mc;0;L;;;;;N;;;;; 09C0;BENGALI VOWEL SIGN II;Mc;0;L;;;;;N;;;;; 09C1;BENGALI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 09C2;BENGALI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 09C3;BENGALI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; 09C4;BENGALI VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; 09C7;BENGALI VOWEL SIGN E;Mc;0;L;;;;;N;;;;; 09C8;BENGALI VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; 09CB;BENGALI VOWEL SIGN O;Mc;0;L;09C7 09BE;;;;N;;;;; 09CC;BENGALI VOWEL SIGN AU;Mc;0;L;09C7 09D7;;;;N;;;;; 09CD;BENGALI SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 09CE;BENGALI LETTER KHANDA TA;Lo;0;L;;;;;N;;;;; 09D7;BENGALI AU LENGTH MARK;Mc;0;L;;;;;N;;;;; 09DC;BENGALI LETTER RRA;Lo;0;L;09A1 09BC;;;;N;;;;; 09DD;BENGALI LETTER RHA;Lo;0;L;09A2 09BC;;;;N;;;;; 09DF;BENGALI LETTER YYA;Lo;0;L;09AF 09BC;;;;N;;;;; 09E0;BENGALI LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; 09E1;BENGALI LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; 09E2;BENGALI VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; 09E3;BENGALI VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; 09E6;BENGALI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 09E7;BENGALI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 09E8;BENGALI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 09E9;BENGALI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 09EA;BENGALI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 09EB;BENGALI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 09EC;BENGALI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 09ED;BENGALI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 09EE;BENGALI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 09EF;BENGALI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 09F0;BENGALI LETTER RA WITH MIDDLE DIAGONAL;Lo;0;L;;;;;N;;;;; 09F1;BENGALI LETTER RA WITH LOWER DIAGONAL;Lo;0;L;;;;;N;BENGALI LETTER VA WITH LOWER DIAGONAL;;;; 09F2;BENGALI RUPEE MARK;Sc;0;ET;;;;;N;;;;; 09F3;BENGALI RUPEE SIGN;Sc;0;ET;;;;;N;;;;; 09F4;BENGALI CURRENCY NUMERATOR ONE;No;0;L;;;;1/16;N;;;;; 09F5;BENGALI CURRENCY NUMERATOR TWO;No;0;L;;;;1/8;N;;;;; 09F6;BENGALI CURRENCY NUMERATOR THREE;No;0;L;;;;3/16;N;;;;; 09F7;BENGALI CURRENCY NUMERATOR FOUR;No;0;L;;;;1/4;N;;;;; 09F8;BENGALI CURRENCY NUMERATOR ONE LESS THAN THE DENOMINATOR;No;0;L;;;;3/4;N;;;;; 09F9;BENGALI CURRENCY DENOMINATOR SIXTEEN;No;0;L;;;;16;N;;;;; 09FA;BENGALI ISSHAR;So;0;L;;;;;N;;;;; 09FB;BENGALI GANDA MARK;Sc;0;ET;;;;;N;;;;; 0A01;GURMUKHI SIGN ADAK BINDI;Mn;0;NSM;;;;;N;;;;; 0A02;GURMUKHI SIGN BINDI;Mn;0;NSM;;;;;N;;;;; 0A03;GURMUKHI SIGN VISARGA;Mc;0;L;;;;;N;;;;; 0A05;GURMUKHI LETTER A;Lo;0;L;;;;;N;;;;; 0A06;GURMUKHI LETTER AA;Lo;0;L;;;;;N;;;;; 0A07;GURMUKHI LETTER I;Lo;0;L;;;;;N;;;;; 0A08;GURMUKHI LETTER II;Lo;0;L;;;;;N;;;;; 0A09;GURMUKHI LETTER U;Lo;0;L;;;;;N;;;;; 0A0A;GURMUKHI LETTER UU;Lo;0;L;;;;;N;;;;; 0A0F;GURMUKHI LETTER EE;Lo;0;L;;;;;N;;;;; 0A10;GURMUKHI LETTER AI;Lo;0;L;;;;;N;;;;; 0A13;GURMUKHI LETTER OO;Lo;0;L;;;;;N;;;;; 0A14;GURMUKHI LETTER AU;Lo;0;L;;;;;N;;;;; 0A15;GURMUKHI LETTER KA;Lo;0;L;;;;;N;;;;; 0A16;GURMUKHI LETTER KHA;Lo;0;L;;;;;N;;;;; 0A17;GURMUKHI LETTER GA;Lo;0;L;;;;;N;;;;; 0A18;GURMUKHI LETTER GHA;Lo;0;L;;;;;N;;;;; 0A19;GURMUKHI LETTER NGA;Lo;0;L;;;;;N;;;;; 0A1A;GURMUKHI LETTER CA;Lo;0;L;;;;;N;;;;; 0A1B;GURMUKHI LETTER CHA;Lo;0;L;;;;;N;;;;; 0A1C;GURMUKHI LETTER JA;Lo;0;L;;;;;N;;;;; 0A1D;GURMUKHI LETTER JHA;Lo;0;L;;;;;N;;;;; 0A1E;GURMUKHI LETTER NYA;Lo;0;L;;;;;N;;;;; 0A1F;GURMUKHI LETTER TTA;Lo;0;L;;;;;N;;;;; 0A20;GURMUKHI LETTER TTHA;Lo;0;L;;;;;N;;;;; 0A21;GURMUKHI LETTER DDA;Lo;0;L;;;;;N;;;;; 0A22;GURMUKHI LETTER DDHA;Lo;0;L;;;;;N;;;;; 0A23;GURMUKHI LETTER NNA;Lo;0;L;;;;;N;;;;; 0A24;GURMUKHI LETTER TA;Lo;0;L;;;;;N;;;;; 0A25;GURMUKHI LETTER THA;Lo;0;L;;;;;N;;;;; 0A26;GURMUKHI LETTER DA;Lo;0;L;;;;;N;;;;; 0A27;GURMUKHI LETTER DHA;Lo;0;L;;;;;N;;;;; 0A28;GURMUKHI LETTER NA;Lo;0;L;;;;;N;;;;; 0A2A;GURMUKHI LETTER PA;Lo;0;L;;;;;N;;;;; 0A2B;GURMUKHI LETTER PHA;Lo;0;L;;;;;N;;;;; 0A2C;GURMUKHI LETTER BA;Lo;0;L;;;;;N;;;;; 0A2D;GURMUKHI LETTER BHA;Lo;0;L;;;;;N;;;;; 0A2E;GURMUKHI LETTER MA;Lo;0;L;;;;;N;;;;; 0A2F;GURMUKHI LETTER YA;Lo;0;L;;;;;N;;;;; 0A30;GURMUKHI LETTER RA;Lo;0;L;;;;;N;;;;; 0A32;GURMUKHI LETTER LA;Lo;0;L;;;;;N;;;;; 0A33;GURMUKHI LETTER LLA;Lo;0;L;0A32 0A3C;;;;N;;;;; 0A35;GURMUKHI LETTER VA;Lo;0;L;;;;;N;;;;; 0A36;GURMUKHI LETTER SHA;Lo;0;L;0A38 0A3C;;;;N;;;;; 0A38;GURMUKHI LETTER SA;Lo;0;L;;;;;N;;;;; 0A39;GURMUKHI LETTER HA;Lo;0;L;;;;;N;;;;; 0A3C;GURMUKHI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; 0A3E;GURMUKHI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 0A3F;GURMUKHI VOWEL SIGN I;Mc;0;L;;;;;N;;;;; 0A40;GURMUKHI VOWEL SIGN II;Mc;0;L;;;;;N;;;;; 0A41;GURMUKHI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 0A42;GURMUKHI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 0A47;GURMUKHI VOWEL SIGN EE;Mn;0;NSM;;;;;N;;;;; 0A48;GURMUKHI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; 0A4B;GURMUKHI VOWEL SIGN OO;Mn;0;NSM;;;;;N;;;;; 0A4C;GURMUKHI VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;; 0A4D;GURMUKHI SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 0A51;GURMUKHI SIGN UDAAT;Mn;0;NSM;;;;;N;;;;; 0A59;GURMUKHI LETTER KHHA;Lo;0;L;0A16 0A3C;;;;N;;;;; 0A5A;GURMUKHI LETTER GHHA;Lo;0;L;0A17 0A3C;;;;N;;;;; 0A5B;GURMUKHI LETTER ZA;Lo;0;L;0A1C 0A3C;;;;N;;;;; 0A5C;GURMUKHI LETTER RRA;Lo;0;L;;;;;N;;;;; 0A5E;GURMUKHI LETTER FA;Lo;0;L;0A2B 0A3C;;;;N;;;;; 0A66;GURMUKHI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 0A67;GURMUKHI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 0A68;GURMUKHI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 0A69;GURMUKHI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 0A6A;GURMUKHI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 0A6B;GURMUKHI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 0A6C;GURMUKHI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 0A6D;GURMUKHI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 0A6E;GURMUKHI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 0A6F;GURMUKHI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 0A70;GURMUKHI TIPPI;Mn;0;NSM;;;;;N;;;;; 0A71;GURMUKHI ADDAK;Mn;0;NSM;;;;;N;;;;; 0A72;GURMUKHI IRI;Lo;0;L;;;;;N;;;;; 0A73;GURMUKHI URA;Lo;0;L;;;;;N;;;;; 0A74;GURMUKHI EK ONKAR;Lo;0;L;;;;;N;;;;; 0A75;GURMUKHI SIGN YAKASH;Mn;0;NSM;;;;;N;;;;; 0A81;GUJARATI SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; 0A82;GUJARATI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; 0A83;GUJARATI SIGN VISARGA;Mc;0;L;;;;;N;;;;; 0A85;GUJARATI LETTER A;Lo;0;L;;;;;N;;;;; 0A86;GUJARATI LETTER AA;Lo;0;L;;;;;N;;;;; 0A87;GUJARATI LETTER I;Lo;0;L;;;;;N;;;;; 0A88;GUJARATI LETTER II;Lo;0;L;;;;;N;;;;; 0A89;GUJARATI LETTER U;Lo;0;L;;;;;N;;;;; 0A8A;GUJARATI LETTER UU;Lo;0;L;;;;;N;;;;; 0A8B;GUJARATI LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; 0A8C;GUJARATI LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; 0A8D;GUJARATI VOWEL CANDRA E;Lo;0;L;;;;;N;;;;; 0A8F;GUJARATI LETTER E;Lo;0;L;;;;;N;;;;; 0A90;GUJARATI LETTER AI;Lo;0;L;;;;;N;;;;; 0A91;GUJARATI VOWEL CANDRA O;Lo;0;L;;;;;N;;;;; 0A93;GUJARATI LETTER O;Lo;0;L;;;;;N;;;;; 0A94;GUJARATI LETTER AU;Lo;0;L;;;;;N;;;;; 0A95;GUJARATI LETTER KA;Lo;0;L;;;;;N;;;;; 0A96;GUJARATI LETTER KHA;Lo;0;L;;;;;N;;;;; 0A97;GUJARATI LETTER GA;Lo;0;L;;;;;N;;;;; 0A98;GUJARATI LETTER GHA;Lo;0;L;;;;;N;;;;; 0A99;GUJARATI LETTER NGA;Lo;0;L;;;;;N;;;;; 0A9A;GUJARATI LETTER CA;Lo;0;L;;;;;N;;;;; 0A9B;GUJARATI LETTER CHA;Lo;0;L;;;;;N;;;;; 0A9C;GUJARATI LETTER JA;Lo;0;L;;;;;N;;;;; 0A9D;GUJARATI LETTER JHA;Lo;0;L;;;;;N;;;;; 0A9E;GUJARATI LETTER NYA;Lo;0;L;;;;;N;;;;; 0A9F;GUJARATI LETTER TTA;Lo;0;L;;;;;N;;;;; 0AA0;GUJARATI LETTER TTHA;Lo;0;L;;;;;N;;;;; 0AA1;GUJARATI LETTER DDA;Lo;0;L;;;;;N;;;;; 0AA2;GUJARATI LETTER DDHA;Lo;0;L;;;;;N;;;;; 0AA3;GUJARATI LETTER NNA;Lo;0;L;;;;;N;;;;; 0AA4;GUJARATI LETTER TA;Lo;0;L;;;;;N;;;;; 0AA5;GUJARATI LETTER THA;Lo;0;L;;;;;N;;;;; 0AA6;GUJARATI LETTER DA;Lo;0;L;;;;;N;;;;; 0AA7;GUJARATI LETTER DHA;Lo;0;L;;;;;N;;;;; 0AA8;GUJARATI LETTER NA;Lo;0;L;;;;;N;;;;; 0AAA;GUJARATI LETTER PA;Lo;0;L;;;;;N;;;;; 0AAB;GUJARATI LETTER PHA;Lo;0;L;;;;;N;;;;; 0AAC;GUJARATI LETTER BA;Lo;0;L;;;;;N;;;;; 0AAD;GUJARATI LETTER BHA;Lo;0;L;;;;;N;;;;; 0AAE;GUJARATI LETTER MA;Lo;0;L;;;;;N;;;;; 0AAF;GUJARATI LETTER YA;Lo;0;L;;;;;N;;;;; 0AB0;GUJARATI LETTER RA;Lo;0;L;;;;;N;;;;; 0AB2;GUJARATI LETTER LA;Lo;0;L;;;;;N;;;;; 0AB3;GUJARATI LETTER LLA;Lo;0;L;;;;;N;;;;; 0AB5;GUJARATI LETTER VA;Lo;0;L;;;;;N;;;;; 0AB6;GUJARATI LETTER SHA;Lo;0;L;;;;;N;;;;; 0AB7;GUJARATI LETTER SSA;Lo;0;L;;;;;N;;;;; 0AB8;GUJARATI LETTER SA;Lo;0;L;;;;;N;;;;; 0AB9;GUJARATI LETTER HA;Lo;0;L;;;;;N;;;;; 0ABC;GUJARATI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; 0ABD;GUJARATI SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; 0ABE;GUJARATI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 0ABF;GUJARATI VOWEL SIGN I;Mc;0;L;;;;;N;;;;; 0AC0;GUJARATI VOWEL SIGN II;Mc;0;L;;;;;N;;;;; 0AC1;GUJARATI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 0AC2;GUJARATI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 0AC3;GUJARATI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; 0AC4;GUJARATI VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; 0AC5;GUJARATI VOWEL SIGN CANDRA E;Mn;0;NSM;;;;;N;;;;; 0AC7;GUJARATI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; 0AC8;GUJARATI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; 0AC9;GUJARATI VOWEL SIGN CANDRA O;Mc;0;L;;;;;N;;;;; 0ACB;GUJARATI VOWEL SIGN O;Mc;0;L;;;;;N;;;;; 0ACC;GUJARATI VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; 0ACD;GUJARATI SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 0AD0;GUJARATI OM;Lo;0;L;;;;;N;;;;; 0AE0;GUJARATI LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; 0AE1;GUJARATI LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; 0AE2;GUJARATI VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; 0AE3;GUJARATI VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; 0AE6;GUJARATI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 0AE7;GUJARATI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 0AE8;GUJARATI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 0AE9;GUJARATI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 0AEA;GUJARATI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 0AEB;GUJARATI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 0AEC;GUJARATI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 0AED;GUJARATI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 0AEE;GUJARATI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 0AEF;GUJARATI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 0AF0;GUJARATI ABBREVIATION SIGN;Po;0;L;;;;;N;;;;; 0AF1;GUJARATI RUPEE SIGN;Sc;0;ET;;;;;N;;;;; 0AF9;GUJARATI LETTER ZHA;Lo;0;L;;;;;N;;;;; 0B01;ORIYA SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; 0B02;ORIYA SIGN ANUSVARA;Mc;0;L;;;;;N;;;;; 0B03;ORIYA SIGN VISARGA;Mc;0;L;;;;;N;;;;; 0B05;ORIYA LETTER A;Lo;0;L;;;;;N;;;;; 0B06;ORIYA LETTER AA;Lo;0;L;;;;;N;;;;; 0B07;ORIYA LETTER I;Lo;0;L;;;;;N;;;;; 0B08;ORIYA LETTER II;Lo;0;L;;;;;N;;;;; 0B09;ORIYA LETTER U;Lo;0;L;;;;;N;;;;; 0B0A;ORIYA LETTER UU;Lo;0;L;;;;;N;;;;; 0B0B;ORIYA LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; 0B0C;ORIYA LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; 0B0F;ORIYA LETTER E;Lo;0;L;;;;;N;;;;; 0B10;ORIYA LETTER AI;Lo;0;L;;;;;N;;;;; 0B13;ORIYA LETTER O;Lo;0;L;;;;;N;;;;; 0B14;ORIYA LETTER AU;Lo;0;L;;;;;N;;;;; 0B15;ORIYA LETTER KA;Lo;0;L;;;;;N;;;;; 0B16;ORIYA LETTER KHA;Lo;0;L;;;;;N;;;;; 0B17;ORIYA LETTER GA;Lo;0;L;;;;;N;;;;; 0B18;ORIYA LETTER GHA;Lo;0;L;;;;;N;;;;; 0B19;ORIYA LETTER NGA;Lo;0;L;;;;;N;;;;; 0B1A;ORIYA LETTER CA;Lo;0;L;;;;;N;;;;; 0B1B;ORIYA LETTER CHA;Lo;0;L;;;;;N;;;;; 0B1C;ORIYA LETTER JA;Lo;0;L;;;;;N;;;;; 0B1D;ORIYA LETTER JHA;Lo;0;L;;;;;N;;;;; 0B1E;ORIYA LETTER NYA;Lo;0;L;;;;;N;;;;; 0B1F;ORIYA LETTER TTA;Lo;0;L;;;;;N;;;;; 0B20;ORIYA LETTER TTHA;Lo;0;L;;;;;N;;;;; 0B21;ORIYA LETTER DDA;Lo;0;L;;;;;N;;;;; 0B22;ORIYA LETTER DDHA;Lo;0;L;;;;;N;;;;; 0B23;ORIYA LETTER NNA;Lo;0;L;;;;;N;;;;; 0B24;ORIYA LETTER TA;Lo;0;L;;;;;N;;;;; 0B25;ORIYA LETTER THA;Lo;0;L;;;;;N;;;;; 0B26;ORIYA LETTER DA;Lo;0;L;;;;;N;;;;; 0B27;ORIYA LETTER DHA;Lo;0;L;;;;;N;;;;; 0B28;ORIYA LETTER NA;Lo;0;L;;;;;N;;;;; 0B2A;ORIYA LETTER PA;Lo;0;L;;;;;N;;;;; 0B2B;ORIYA LETTER PHA;Lo;0;L;;;;;N;;;;; 0B2C;ORIYA LETTER BA;Lo;0;L;;;;;N;;;;; 0B2D;ORIYA LETTER BHA;Lo;0;L;;;;;N;;;;; 0B2E;ORIYA LETTER MA;Lo;0;L;;;;;N;;;;; 0B2F;ORIYA LETTER YA;Lo;0;L;;;;;N;;;;; 0B30;ORIYA LETTER RA;Lo;0;L;;;;;N;;;;; 0B32;ORIYA LETTER LA;Lo;0;L;;;;;N;;;;; 0B33;ORIYA LETTER LLA;Lo;0;L;;;;;N;;;;; 0B35;ORIYA LETTER VA;Lo;0;L;;;;;N;;;;; 0B36;ORIYA LETTER SHA;Lo;0;L;;;;;N;;;;; 0B37;ORIYA LETTER SSA;Lo;0;L;;;;;N;;;;; 0B38;ORIYA LETTER SA;Lo;0;L;;;;;N;;;;; 0B39;ORIYA LETTER HA;Lo;0;L;;;;;N;;;;; 0B3C;ORIYA SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; 0B3D;ORIYA SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; 0B3E;ORIYA VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 0B3F;ORIYA VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; 0B40;ORIYA VOWEL SIGN II;Mc;0;L;;;;;N;;;;; 0B41;ORIYA VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 0B42;ORIYA VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 0B43;ORIYA VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; 0B44;ORIYA VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; 0B47;ORIYA VOWEL SIGN E;Mc;0;L;;;;;N;;;;; 0B48;ORIYA VOWEL SIGN AI;Mc;0;L;0B47 0B56;;;;N;;;;; 0B4B;ORIYA VOWEL SIGN O;Mc;0;L;0B47 0B3E;;;;N;;;;; 0B4C;ORIYA VOWEL SIGN AU;Mc;0;L;0B47 0B57;;;;N;;;;; 0B4D;ORIYA SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 0B56;ORIYA AI LENGTH MARK;Mn;0;NSM;;;;;N;;;;; 0B57;ORIYA AU LENGTH MARK;Mc;0;L;;;;;N;;;;; 0B5C;ORIYA LETTER RRA;Lo;0;L;0B21 0B3C;;;;N;;;;; 0B5D;ORIYA LETTER RHA;Lo;0;L;0B22 0B3C;;;;N;;;;; 0B5F;ORIYA LETTER YYA;Lo;0;L;;;;;N;;;;; 0B60;ORIYA LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; 0B61;ORIYA LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; 0B62;ORIYA VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; 0B63;ORIYA VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; 0B66;ORIYA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 0B67;ORIYA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 0B68;ORIYA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 0B69;ORIYA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 0B6A;ORIYA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 0B6B;ORIYA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 0B6C;ORIYA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 0B6D;ORIYA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 0B6E;ORIYA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 0B6F;ORIYA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 0B70;ORIYA ISSHAR;So;0;L;;;;;N;;;;; 0B71;ORIYA LETTER WA;Lo;0;L;;;;;N;;;;; 0B72;ORIYA FRACTION ONE QUARTER;No;0;L;;;;1/4;N;;;;; 0B73;ORIYA FRACTION ONE HALF;No;0;L;;;;1/2;N;;;;; 0B74;ORIYA FRACTION THREE QUARTERS;No;0;L;;;;3/4;N;;;;; 0B75;ORIYA FRACTION ONE SIXTEENTH;No;0;L;;;;1/16;N;;;;; 0B76;ORIYA FRACTION ONE EIGHTH;No;0;L;;;;1/8;N;;;;; 0B77;ORIYA FRACTION THREE SIXTEENTHS;No;0;L;;;;3/16;N;;;;; 0B82;TAMIL SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; 0B83;TAMIL SIGN VISARGA;Lo;0;L;;;;;N;;;;; 0B85;TAMIL LETTER A;Lo;0;L;;;;;N;;;;; 0B86;TAMIL LETTER AA;Lo;0;L;;;;;N;;;;; 0B87;TAMIL LETTER I;Lo;0;L;;;;;N;;;;; 0B88;TAMIL LETTER II;Lo;0;L;;;;;N;;;;; 0B89;TAMIL LETTER U;Lo;0;L;;;;;N;;;;; 0B8A;TAMIL LETTER UU;Lo;0;L;;;;;N;;;;; 0B8E;TAMIL LETTER E;Lo;0;L;;;;;N;;;;; 0B8F;TAMIL LETTER EE;Lo;0;L;;;;;N;;;;; 0B90;TAMIL LETTER AI;Lo;0;L;;;;;N;;;;; 0B92;TAMIL LETTER O;Lo;0;L;;;;;N;;;;; 0B93;TAMIL LETTER OO;Lo;0;L;;;;;N;;;;; 0B94;TAMIL LETTER AU;Lo;0;L;0B92 0BD7;;;;N;;;;; 0B95;TAMIL LETTER KA;Lo;0;L;;;;;N;;;;; 0B99;TAMIL LETTER NGA;Lo;0;L;;;;;N;;;;; 0B9A;TAMIL LETTER CA;Lo;0;L;;;;;N;;;;; 0B9C;TAMIL LETTER JA;Lo;0;L;;;;;N;;;;; 0B9E;TAMIL LETTER NYA;Lo;0;L;;;;;N;;;;; 0B9F;TAMIL LETTER TTA;Lo;0;L;;;;;N;;;;; 0BA3;TAMIL LETTER NNA;Lo;0;L;;;;;N;;;;; 0BA4;TAMIL LETTER TA;Lo;0;L;;;;;N;;;;; 0BA8;TAMIL LETTER NA;Lo;0;L;;;;;N;;;;; 0BA9;TAMIL LETTER NNNA;Lo;0;L;;;;;N;;;;; 0BAA;TAMIL LETTER PA;Lo;0;L;;;;;N;;;;; 0BAE;TAMIL LETTER MA;Lo;0;L;;;;;N;;;;; 0BAF;TAMIL LETTER YA;Lo;0;L;;;;;N;;;;; 0BB0;TAMIL LETTER RA;Lo;0;L;;;;;N;;;;; 0BB1;TAMIL LETTER RRA;Lo;0;L;;;;;N;;;;; 0BB2;TAMIL LETTER LA;Lo;0;L;;;;;N;;;;; 0BB3;TAMIL LETTER LLA;Lo;0;L;;;;;N;;;;; 0BB4;TAMIL LETTER LLLA;Lo;0;L;;;;;N;;;;; 0BB5;TAMIL LETTER VA;Lo;0;L;;;;;N;;;;; 0BB6;TAMIL LETTER SHA;Lo;0;L;;;;;N;;;;; 0BB7;TAMIL LETTER SSA;Lo;0;L;;;;;N;;;;; 0BB8;TAMIL LETTER SA;Lo;0;L;;;;;N;;;;; 0BB9;TAMIL LETTER HA;Lo;0;L;;;;;N;;;;; 0BBE;TAMIL VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 0BBF;TAMIL VOWEL SIGN I;Mc;0;L;;;;;N;;;;; 0BC0;TAMIL VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; 0BC1;TAMIL VOWEL SIGN U;Mc;0;L;;;;;N;;;;; 0BC2;TAMIL VOWEL SIGN UU;Mc;0;L;;;;;N;;;;; 0BC6;TAMIL VOWEL SIGN E;Mc;0;L;;;;;N;;;;; 0BC7;TAMIL VOWEL SIGN EE;Mc;0;L;;;;;N;;;;; 0BC8;TAMIL VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; 0BCA;TAMIL VOWEL SIGN O;Mc;0;L;0BC6 0BBE;;;;N;;;;; 0BCB;TAMIL VOWEL SIGN OO;Mc;0;L;0BC7 0BBE;;;;N;;;;; 0BCC;TAMIL VOWEL SIGN AU;Mc;0;L;0BC6 0BD7;;;;N;;;;; 0BCD;TAMIL SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 0BD0;TAMIL OM;Lo;0;L;;;;;N;;;;; 0BD7;TAMIL AU LENGTH MARK;Mc;0;L;;;;;N;;;;; 0BE6;TAMIL DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 0BE7;TAMIL DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 0BE8;TAMIL DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 0BE9;TAMIL DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 0BEA;TAMIL DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 0BEB;TAMIL DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 0BEC;TAMIL DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 0BED;TAMIL DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 0BEE;TAMIL DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 0BEF;TAMIL DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 0BF0;TAMIL NUMBER TEN;No;0;L;;;;10;N;;;;; 0BF1;TAMIL NUMBER ONE HUNDRED;No;0;L;;;;100;N;;;;; 0BF2;TAMIL NUMBER ONE THOUSAND;No;0;L;;;;1000;N;;;;; 0BF3;TAMIL DAY SIGN;So;0;ON;;;;;N;;;;; 0BF4;TAMIL MONTH SIGN;So;0;ON;;;;;N;;;;; 0BF5;TAMIL YEAR SIGN;So;0;ON;;;;;N;;;;; 0BF6;TAMIL DEBIT SIGN;So;0;ON;;;;;N;;;;; 0BF7;TAMIL CREDIT SIGN;So;0;ON;;;;;N;;;;; 0BF8;TAMIL AS ABOVE SIGN;So;0;ON;;;;;N;;;;; 0BF9;TAMIL RUPEE SIGN;Sc;0;ET;;;;;N;;;;; 0BFA;TAMIL NUMBER SIGN;So;0;ON;;;;;N;;;;; 0C00;TELUGU SIGN COMBINING CANDRABINDU ABOVE;Mn;0;NSM;;;;;N;;;;; 0C01;TELUGU SIGN CANDRABINDU;Mc;0;L;;;;;N;;;;; 0C02;TELUGU SIGN ANUSVARA;Mc;0;L;;;;;N;;;;; 0C03;TELUGU SIGN VISARGA;Mc;0;L;;;;;N;;;;; 0C05;TELUGU LETTER A;Lo;0;L;;;;;N;;;;; 0C06;TELUGU LETTER AA;Lo;0;L;;;;;N;;;;; 0C07;TELUGU LETTER I;Lo;0;L;;;;;N;;;;; 0C08;TELUGU LETTER II;Lo;0;L;;;;;N;;;;; 0C09;TELUGU LETTER U;Lo;0;L;;;;;N;;;;; 0C0A;TELUGU LETTER UU;Lo;0;L;;;;;N;;;;; 0C0B;TELUGU LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; 0C0C;TELUGU LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; 0C0E;TELUGU LETTER E;Lo;0;L;;;;;N;;;;; 0C0F;TELUGU LETTER EE;Lo;0;L;;;;;N;;;;; 0C10;TELUGU LETTER AI;Lo;0;L;;;;;N;;;;; 0C12;TELUGU LETTER O;Lo;0;L;;;;;N;;;;; 0C13;TELUGU LETTER OO;Lo;0;L;;;;;N;;;;; 0C14;TELUGU LETTER AU;Lo;0;L;;;;;N;;;;; 0C15;TELUGU LETTER KA;Lo;0;L;;;;;N;;;;; 0C16;TELUGU LETTER KHA;Lo;0;L;;;;;N;;;;; 0C17;TELUGU LETTER GA;Lo;0;L;;;;;N;;;;; 0C18;TELUGU LETTER GHA;Lo;0;L;;;;;N;;;;; 0C19;TELUGU LETTER NGA;Lo;0;L;;;;;N;;;;; 0C1A;TELUGU LETTER CA;Lo;0;L;;;;;N;;;;; 0C1B;TELUGU LETTER CHA;Lo;0;L;;;;;N;;;;; 0C1C;TELUGU LETTER JA;Lo;0;L;;;;;N;;;;; 0C1D;TELUGU LETTER JHA;Lo;0;L;;;;;N;;;;; 0C1E;TELUGU LETTER NYA;Lo;0;L;;;;;N;;;;; 0C1F;TELUGU LETTER TTA;Lo;0;L;;;;;N;;;;; 0C20;TELUGU LETTER TTHA;Lo;0;L;;;;;N;;;;; 0C21;TELUGU LETTER DDA;Lo;0;L;;;;;N;;;;; 0C22;TELUGU LETTER DDHA;Lo;0;L;;;;;N;;;;; 0C23;TELUGU LETTER NNA;Lo;0;L;;;;;N;;;;; 0C24;TELUGU LETTER TA;Lo;0;L;;;;;N;;;;; 0C25;TELUGU LETTER THA;Lo;0;L;;;;;N;;;;; 0C26;TELUGU LETTER DA;Lo;0;L;;;;;N;;;;; 0C27;TELUGU LETTER DHA;Lo;0;L;;;;;N;;;;; 0C28;TELUGU LETTER NA;Lo;0;L;;;;;N;;;;; 0C2A;TELUGU LETTER PA;Lo;0;L;;;;;N;;;;; 0C2B;TELUGU LETTER PHA;Lo;0;L;;;;;N;;;;; 0C2C;TELUGU LETTER BA;Lo;0;L;;;;;N;;;;; 0C2D;TELUGU LETTER BHA;Lo;0;L;;;;;N;;;;; 0C2E;TELUGU LETTER MA;Lo;0;L;;;;;N;;;;; 0C2F;TELUGU LETTER YA;Lo;0;L;;;;;N;;;;; 0C30;TELUGU LETTER RA;Lo;0;L;;;;;N;;;;; 0C31;TELUGU LETTER RRA;Lo;0;L;;;;;N;;;;; 0C32;TELUGU LETTER LA;Lo;0;L;;;;;N;;;;; 0C33;TELUGU LETTER LLA;Lo;0;L;;;;;N;;;;; 0C34;TELUGU LETTER LLLA;Lo;0;L;;;;;N;;;;; 0C35;TELUGU LETTER VA;Lo;0;L;;;;;N;;;;; 0C36;TELUGU LETTER SHA;Lo;0;L;;;;;N;;;;; 0C37;TELUGU LETTER SSA;Lo;0;L;;;;;N;;;;; 0C38;TELUGU LETTER SA;Lo;0;L;;;;;N;;;;; 0C39;TELUGU LETTER HA;Lo;0;L;;;;;N;;;;; 0C3D;TELUGU SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; 0C3E;TELUGU VOWEL SIGN AA;Mn;0;NSM;;;;;N;;;;; 0C3F;TELUGU VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; 0C40;TELUGU VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; 0C41;TELUGU VOWEL SIGN U;Mc;0;L;;;;;N;;;;; 0C42;TELUGU VOWEL SIGN UU;Mc;0;L;;;;;N;;;;; 0C43;TELUGU VOWEL SIGN VOCALIC R;Mc;0;L;;;;;N;;;;; 0C44;TELUGU VOWEL SIGN VOCALIC RR;Mc;0;L;;;;;N;;;;; 0C46;TELUGU VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; 0C47;TELUGU VOWEL SIGN EE;Mn;0;NSM;;;;;N;;;;; 0C48;TELUGU VOWEL SIGN AI;Mn;0;NSM;0C46 0C56;;;;N;;;;; 0C4A;TELUGU VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; 0C4B;TELUGU VOWEL SIGN OO;Mn;0;NSM;;;;;N;;;;; 0C4C;TELUGU VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;; 0C4D;TELUGU SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 0C55;TELUGU LENGTH MARK;Mn;84;NSM;;;;;N;;;;; 0C56;TELUGU AI LENGTH MARK;Mn;91;NSM;;;;;N;;;;; 0C58;TELUGU LETTER TSA;Lo;0;L;;;;;N;;;;; 0C59;TELUGU LETTER DZA;Lo;0;L;;;;;N;;;;; 0C5A;TELUGU LETTER RRRA;Lo;0;L;;;;;N;;;;; 0C60;TELUGU LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; 0C61;TELUGU LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; 0C62;TELUGU VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; 0C63;TELUGU VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; 0C66;TELUGU DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 0C67;TELUGU DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 0C68;TELUGU DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 0C69;TELUGU DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 0C6A;TELUGU DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 0C6B;TELUGU DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 0C6C;TELUGU DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 0C6D;TELUGU DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 0C6E;TELUGU DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 0C6F;TELUGU DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 0C78;TELUGU FRACTION DIGIT ZERO FOR ODD POWERS OF FOUR;No;0;ON;;;;0;N;;;;; 0C79;TELUGU FRACTION DIGIT ONE FOR ODD POWERS OF FOUR;No;0;ON;;;;1;N;;;;; 0C7A;TELUGU FRACTION DIGIT TWO FOR ODD POWERS OF FOUR;No;0;ON;;;;2;N;;;;; 0C7B;TELUGU FRACTION DIGIT THREE FOR ODD POWERS OF FOUR;No;0;ON;;;;3;N;;;;; 0C7C;TELUGU FRACTION DIGIT ONE FOR EVEN POWERS OF FOUR;No;0;ON;;;;1;N;;;;; 0C7D;TELUGU FRACTION DIGIT TWO FOR EVEN POWERS OF FOUR;No;0;ON;;;;2;N;;;;; 0C7E;TELUGU FRACTION DIGIT THREE FOR EVEN POWERS OF FOUR;No;0;ON;;;;3;N;;;;; 0C7F;TELUGU SIGN TUUMU;So;0;L;;;;;N;;;;; 0C80;KANNADA SIGN SPACING CANDRABINDU;Lo;0;L;;;;;N;;;;; 0C81;KANNADA SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; 0C82;KANNADA SIGN ANUSVARA;Mc;0;L;;;;;N;;;;; 0C83;KANNADA SIGN VISARGA;Mc;0;L;;;;;N;;;;; 0C85;KANNADA LETTER A;Lo;0;L;;;;;N;;;;; 0C86;KANNADA LETTER AA;Lo;0;L;;;;;N;;;;; 0C87;KANNADA LETTER I;Lo;0;L;;;;;N;;;;; 0C88;KANNADA LETTER II;Lo;0;L;;;;;N;;;;; 0C89;KANNADA LETTER U;Lo;0;L;;;;;N;;;;; 0C8A;KANNADA LETTER UU;Lo;0;L;;;;;N;;;;; 0C8B;KANNADA LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; 0C8C;KANNADA LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; 0C8E;KANNADA LETTER E;Lo;0;L;;;;;N;;;;; 0C8F;KANNADA LETTER EE;Lo;0;L;;;;;N;;;;; 0C90;KANNADA LETTER AI;Lo;0;L;;;;;N;;;;; 0C92;KANNADA LETTER O;Lo;0;L;;;;;N;;;;; 0C93;KANNADA LETTER OO;Lo;0;L;;;;;N;;;;; 0C94;KANNADA LETTER AU;Lo;0;L;;;;;N;;;;; 0C95;KANNADA LETTER KA;Lo;0;L;;;;;N;;;;; 0C96;KANNADA LETTER KHA;Lo;0;L;;;;;N;;;;; 0C97;KANNADA LETTER GA;Lo;0;L;;;;;N;;;;; 0C98;KANNADA LETTER GHA;Lo;0;L;;;;;N;;;;; 0C99;KANNADA LETTER NGA;Lo;0;L;;;;;N;;;;; 0C9A;KANNADA LETTER CA;Lo;0;L;;;;;N;;;;; 0C9B;KANNADA LETTER CHA;Lo;0;L;;;;;N;;;;; 0C9C;KANNADA LETTER JA;Lo;0;L;;;;;N;;;;; 0C9D;KANNADA LETTER JHA;Lo;0;L;;;;;N;;;;; 0C9E;KANNADA LETTER NYA;Lo;0;L;;;;;N;;;;; 0C9F;KANNADA LETTER TTA;Lo;0;L;;;;;N;;;;; 0CA0;KANNADA LETTER TTHA;Lo;0;L;;;;;N;;;;; 0CA1;KANNADA LETTER DDA;Lo;0;L;;;;;N;;;;; 0CA2;KANNADA LETTER DDHA;Lo;0;L;;;;;N;;;;; 0CA3;KANNADA LETTER NNA;Lo;0;L;;;;;N;;;;; 0CA4;KANNADA LETTER TA;Lo;0;L;;;;;N;;;;; 0CA5;KANNADA LETTER THA;Lo;0;L;;;;;N;;;;; 0CA6;KANNADA LETTER DA;Lo;0;L;;;;;N;;;;; 0CA7;KANNADA LETTER DHA;Lo;0;L;;;;;N;;;;; 0CA8;KANNADA LETTER NA;Lo;0;L;;;;;N;;;;; 0CAA;KANNADA LETTER PA;Lo;0;L;;;;;N;;;;; 0CAB;KANNADA LETTER PHA;Lo;0;L;;;;;N;;;;; 0CAC;KANNADA LETTER BA;Lo;0;L;;;;;N;;;;; 0CAD;KANNADA LETTER BHA;Lo;0;L;;;;;N;;;;; 0CAE;KANNADA LETTER MA;Lo;0;L;;;;;N;;;;; 0CAF;KANNADA LETTER YA;Lo;0;L;;;;;N;;;;; 0CB0;KANNADA LETTER RA;Lo;0;L;;;;;N;;;;; 0CB1;KANNADA LETTER RRA;Lo;0;L;;;;;N;;;;; 0CB2;KANNADA LETTER LA;Lo;0;L;;;;;N;;;;; 0CB3;KANNADA LETTER LLA;Lo;0;L;;;;;N;;;;; 0CB5;KANNADA LETTER VA;Lo;0;L;;;;;N;;;;; 0CB6;KANNADA LETTER SHA;Lo;0;L;;;;;N;;;;; 0CB7;KANNADA LETTER SSA;Lo;0;L;;;;;N;;;;; 0CB8;KANNADA LETTER SA;Lo;0;L;;;;;N;;;;; 0CB9;KANNADA LETTER HA;Lo;0;L;;;;;N;;;;; 0CBC;KANNADA SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; 0CBD;KANNADA SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; 0CBE;KANNADA VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 0CBF;KANNADA VOWEL SIGN I;Mn;0;L;;;;;N;;;;; 0CC0;KANNADA VOWEL SIGN II;Mc;0;L;0CBF 0CD5;;;;N;;;;; 0CC1;KANNADA VOWEL SIGN U;Mc;0;L;;;;;N;;;;; 0CC2;KANNADA VOWEL SIGN UU;Mc;0;L;;;;;N;;;;; 0CC3;KANNADA VOWEL SIGN VOCALIC R;Mc;0;L;;;;;N;;;;; 0CC4;KANNADA VOWEL SIGN VOCALIC RR;Mc;0;L;;;;;N;;;;; 0CC6;KANNADA VOWEL SIGN E;Mn;0;L;;;;;N;;;;; 0CC7;KANNADA VOWEL SIGN EE;Mc;0;L;0CC6 0CD5;;;;N;;;;; 0CC8;KANNADA VOWEL SIGN AI;Mc;0;L;0CC6 0CD6;;;;N;;;;; 0CCA;KANNADA VOWEL SIGN O;Mc;0;L;0CC6 0CC2;;;;N;;;;; 0CCB;KANNADA VOWEL SIGN OO;Mc;0;L;0CCA 0CD5;;;;N;;;;; 0CCC;KANNADA VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;; 0CCD;KANNADA SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 0CD5;KANNADA LENGTH MARK;Mc;0;L;;;;;N;;;;; 0CD6;KANNADA AI LENGTH MARK;Mc;0;L;;;;;N;;;;; 0CDE;KANNADA LETTER FA;Lo;0;L;;;;;N;;;;; 0CE0;KANNADA LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; 0CE1;KANNADA LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; 0CE2;KANNADA VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; 0CE3;KANNADA VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; 0CE6;KANNADA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 0CE7;KANNADA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 0CE8;KANNADA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 0CE9;KANNADA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 0CEA;KANNADA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 0CEB;KANNADA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 0CEC;KANNADA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 0CED;KANNADA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 0CEE;KANNADA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 0CEF;KANNADA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 0CF1;KANNADA SIGN JIHVAMULIYA;Lo;0;L;;;;;N;;;;; 0CF2;KANNADA SIGN UPADHMANIYA;Lo;0;L;;;;;N;;;;; 0D01;MALAYALAM SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; 0D02;MALAYALAM SIGN ANUSVARA;Mc;0;L;;;;;N;;;;; 0D03;MALAYALAM SIGN VISARGA;Mc;0;L;;;;;N;;;;; 0D05;MALAYALAM LETTER A;Lo;0;L;;;;;N;;;;; 0D06;MALAYALAM LETTER AA;Lo;0;L;;;;;N;;;;; 0D07;MALAYALAM LETTER I;Lo;0;L;;;;;N;;;;; 0D08;MALAYALAM LETTER II;Lo;0;L;;;;;N;;;;; 0D09;MALAYALAM LETTER U;Lo;0;L;;;;;N;;;;; 0D0A;MALAYALAM LETTER UU;Lo;0;L;;;;;N;;;;; 0D0B;MALAYALAM LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; 0D0C;MALAYALAM LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; 0D0E;MALAYALAM LETTER E;Lo;0;L;;;;;N;;;;; 0D0F;MALAYALAM LETTER EE;Lo;0;L;;;;;N;;;;; 0D10;MALAYALAM LETTER AI;Lo;0;L;;;;;N;;;;; 0D12;MALAYALAM LETTER O;Lo;0;L;;;;;N;;;;; 0D13;MALAYALAM LETTER OO;Lo;0;L;;;;;N;;;;; 0D14;MALAYALAM LETTER AU;Lo;0;L;;;;;N;;;;; 0D15;MALAYALAM LETTER KA;Lo;0;L;;;;;N;;;;; 0D16;MALAYALAM LETTER KHA;Lo;0;L;;;;;N;;;;; 0D17;MALAYALAM LETTER GA;Lo;0;L;;;;;N;;;;; 0D18;MALAYALAM LETTER GHA;Lo;0;L;;;;;N;;;;; 0D19;MALAYALAM LETTER NGA;Lo;0;L;;;;;N;;;;; 0D1A;MALAYALAM LETTER CA;Lo;0;L;;;;;N;;;;; 0D1B;MALAYALAM LETTER CHA;Lo;0;L;;;;;N;;;;; 0D1C;MALAYALAM LETTER JA;Lo;0;L;;;;;N;;;;; 0D1D;MALAYALAM LETTER JHA;Lo;0;L;;;;;N;;;;; 0D1E;MALAYALAM LETTER NYA;Lo;0;L;;;;;N;;;;; 0D1F;MALAYALAM LETTER TTA;Lo;0;L;;;;;N;;;;; 0D20;MALAYALAM LETTER TTHA;Lo;0;L;;;;;N;;;;; 0D21;MALAYALAM LETTER DDA;Lo;0;L;;;;;N;;;;; 0D22;MALAYALAM LETTER DDHA;Lo;0;L;;;;;N;;;;; 0D23;MALAYALAM LETTER NNA;Lo;0;L;;;;;N;;;;; 0D24;MALAYALAM LETTER TA;Lo;0;L;;;;;N;;;;; 0D25;MALAYALAM LETTER THA;Lo;0;L;;;;;N;;;;; 0D26;MALAYALAM LETTER DA;Lo;0;L;;;;;N;;;;; 0D27;MALAYALAM LETTER DHA;Lo;0;L;;;;;N;;;;; 0D28;MALAYALAM LETTER NA;Lo;0;L;;;;;N;;;;; 0D29;MALAYALAM LETTER NNNA;Lo;0;L;;;;;N;;;;; 0D2A;MALAYALAM LETTER PA;Lo;0;L;;;;;N;;;;; 0D2B;MALAYALAM LETTER PHA;Lo;0;L;;;;;N;;;;; 0D2C;MALAYALAM LETTER BA;Lo;0;L;;;;;N;;;;; 0D2D;MALAYALAM LETTER BHA;Lo;0;L;;;;;N;;;;; 0D2E;MALAYALAM LETTER MA;Lo;0;L;;;;;N;;;;; 0D2F;MALAYALAM LETTER YA;Lo;0;L;;;;;N;;;;; 0D30;MALAYALAM LETTER RA;Lo;0;L;;;;;N;;;;; 0D31;MALAYALAM LETTER RRA;Lo;0;L;;;;;N;;;;; 0D32;MALAYALAM LETTER LA;Lo;0;L;;;;;N;;;;; 0D33;MALAYALAM LETTER LLA;Lo;0;L;;;;;N;;;;; 0D34;MALAYALAM LETTER LLLA;Lo;0;L;;;;;N;;;;; 0D35;MALAYALAM LETTER VA;Lo;0;L;;;;;N;;;;; 0D36;MALAYALAM LETTER SHA;Lo;0;L;;;;;N;;;;; 0D37;MALAYALAM LETTER SSA;Lo;0;L;;;;;N;;;;; 0D38;MALAYALAM LETTER SA;Lo;0;L;;;;;N;;;;; 0D39;MALAYALAM LETTER HA;Lo;0;L;;;;;N;;;;; 0D3A;MALAYALAM LETTER TTTA;Lo;0;L;;;;;N;;;;; 0D3D;MALAYALAM SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; 0D3E;MALAYALAM VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 0D3F;MALAYALAM VOWEL SIGN I;Mc;0;L;;;;;N;;;;; 0D40;MALAYALAM VOWEL SIGN II;Mc;0;L;;;;;N;;;;; 0D41;MALAYALAM VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 0D42;MALAYALAM VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 0D43;MALAYALAM VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; 0D44;MALAYALAM VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; 0D46;MALAYALAM VOWEL SIGN E;Mc;0;L;;;;;N;;;;; 0D47;MALAYALAM VOWEL SIGN EE;Mc;0;L;;;;;N;;;;; 0D48;MALAYALAM VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; 0D4A;MALAYALAM VOWEL SIGN O;Mc;0;L;0D46 0D3E;;;;N;;;;; 0D4B;MALAYALAM VOWEL SIGN OO;Mc;0;L;0D47 0D3E;;;;N;;;;; 0D4C;MALAYALAM VOWEL SIGN AU;Mc;0;L;0D46 0D57;;;;N;;;;; 0D4D;MALAYALAM SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 0D4E;MALAYALAM LETTER DOT REPH;Lo;0;L;;;;;N;;;;; 0D4F;MALAYALAM SIGN PARA;So;0;L;;;;;N;;;;; 0D54;MALAYALAM LETTER CHILLU M;Lo;0;L;;;;;N;;;;; 0D55;MALAYALAM LETTER CHILLU Y;Lo;0;L;;;;;N;;;;; 0D56;MALAYALAM LETTER CHILLU LLL;Lo;0;L;;;;;N;;;;; 0D57;MALAYALAM AU LENGTH MARK;Mc;0;L;;;;;N;;;;; 0D58;MALAYALAM FRACTION ONE ONE-HUNDRED-AND-SIXTIETH;No;0;L;;;;1/160;N;;;;; 0D59;MALAYALAM FRACTION ONE FORTIETH;No;0;L;;;;1/40;N;;;;; 0D5A;MALAYALAM FRACTION THREE EIGHTIETHS;No;0;L;;;;3/80;N;;;;; 0D5B;MALAYALAM FRACTION ONE TWENTIETH;No;0;L;;;;1/20;N;;;;; 0D5C;MALAYALAM FRACTION ONE TENTH;No;0;L;;;;1/10;N;;;;; 0D5D;MALAYALAM FRACTION THREE TWENTIETHS;No;0;L;;;;3/20;N;;;;; 0D5E;MALAYALAM FRACTION ONE FIFTH;No;0;L;;;;1/5;N;;;;; 0D5F;MALAYALAM LETTER ARCHAIC II;Lo;0;L;;;;;N;;;;; 0D60;MALAYALAM LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; 0D61;MALAYALAM LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; 0D62;MALAYALAM VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; 0D63;MALAYALAM VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; 0D66;MALAYALAM DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 0D67;MALAYALAM DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 0D68;MALAYALAM DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 0D69;MALAYALAM DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 0D6A;MALAYALAM DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 0D6B;MALAYALAM DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 0D6C;MALAYALAM DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 0D6D;MALAYALAM DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 0D6E;MALAYALAM DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 0D6F;MALAYALAM DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 0D70;MALAYALAM NUMBER TEN;No;0;L;;;;10;N;;;;; 0D71;MALAYALAM NUMBER ONE HUNDRED;No;0;L;;;;100;N;;;;; 0D72;MALAYALAM NUMBER ONE THOUSAND;No;0;L;;;;1000;N;;;;; 0D73;MALAYALAM FRACTION ONE QUARTER;No;0;L;;;;1/4;N;;;;; 0D74;MALAYALAM FRACTION ONE HALF;No;0;L;;;;1/2;N;;;;; 0D75;MALAYALAM FRACTION THREE QUARTERS;No;0;L;;;;3/4;N;;;;; 0D76;MALAYALAM FRACTION ONE SIXTEENTH;No;0;L;;;;1/16;N;;;;; 0D77;MALAYALAM FRACTION ONE EIGHTH;No;0;L;;;;1/8;N;;;;; 0D78;MALAYALAM FRACTION THREE SIXTEENTHS;No;0;L;;;;3/16;N;;;;; 0D79;MALAYALAM DATE MARK;So;0;L;;;;;N;;;;; 0D7A;MALAYALAM LETTER CHILLU NN;Lo;0;L;;;;;N;;;;; 0D7B;MALAYALAM LETTER CHILLU N;Lo;0;L;;;;;N;;;;; 0D7C;MALAYALAM LETTER CHILLU RR;Lo;0;L;;;;;N;;;;; 0D7D;MALAYALAM LETTER CHILLU L;Lo;0;L;;;;;N;;;;; 0D7E;MALAYALAM LETTER CHILLU LL;Lo;0;L;;;;;N;;;;; 0D7F;MALAYALAM LETTER CHILLU K;Lo;0;L;;;;;N;;;;; 0D82;SINHALA SIGN ANUSVARAYA;Mc;0;L;;;;;N;;;;; 0D83;SINHALA SIGN VISARGAYA;Mc;0;L;;;;;N;;;;; 0D85;SINHALA LETTER AYANNA;Lo;0;L;;;;;N;;;;; 0D86;SINHALA LETTER AAYANNA;Lo;0;L;;;;;N;;;;; 0D87;SINHALA LETTER AEYANNA;Lo;0;L;;;;;N;;;;; 0D88;SINHALA LETTER AEEYANNA;Lo;0;L;;;;;N;;;;; 0D89;SINHALA LETTER IYANNA;Lo;0;L;;;;;N;;;;; 0D8A;SINHALA LETTER IIYANNA;Lo;0;L;;;;;N;;;;; 0D8B;SINHALA LETTER UYANNA;Lo;0;L;;;;;N;;;;; 0D8C;SINHALA LETTER UUYANNA;Lo;0;L;;;;;N;;;;; 0D8D;SINHALA LETTER IRUYANNA;Lo;0;L;;;;;N;;;;; 0D8E;SINHALA LETTER IRUUYANNA;Lo;0;L;;;;;N;;;;; 0D8F;SINHALA LETTER ILUYANNA;Lo;0;L;;;;;N;;;;; 0D90;SINHALA LETTER ILUUYANNA;Lo;0;L;;;;;N;;;;; 0D91;SINHALA LETTER EYANNA;Lo;0;L;;;;;N;;;;; 0D92;SINHALA LETTER EEYANNA;Lo;0;L;;;;;N;;;;; 0D93;SINHALA LETTER AIYANNA;Lo;0;L;;;;;N;;;;; 0D94;SINHALA LETTER OYANNA;Lo;0;L;;;;;N;;;;; 0D95;SINHALA LETTER OOYANNA;Lo;0;L;;;;;N;;;;; 0D96;SINHALA LETTER AUYANNA;Lo;0;L;;;;;N;;;;; 0D9A;SINHALA LETTER ALPAPRAANA KAYANNA;Lo;0;L;;;;;N;;;;; 0D9B;SINHALA LETTER MAHAAPRAANA KAYANNA;Lo;0;L;;;;;N;;;;; 0D9C;SINHALA LETTER ALPAPRAANA GAYANNA;Lo;0;L;;;;;N;;;;; 0D9D;SINHALA LETTER MAHAAPRAANA GAYANNA;Lo;0;L;;;;;N;;;;; 0D9E;SINHALA LETTER KANTAJA NAASIKYAYA;Lo;0;L;;;;;N;;;;; 0D9F;SINHALA LETTER SANYAKA GAYANNA;Lo;0;L;;;;;N;;;;; 0DA0;SINHALA LETTER ALPAPRAANA CAYANNA;Lo;0;L;;;;;N;;;;; 0DA1;SINHALA LETTER MAHAAPRAANA CAYANNA;Lo;0;L;;;;;N;;;;; 0DA2;SINHALA LETTER ALPAPRAANA JAYANNA;Lo;0;L;;;;;N;;;;; 0DA3;SINHALA LETTER MAHAAPRAANA JAYANNA;Lo;0;L;;;;;N;;;;; 0DA4;SINHALA LETTER TAALUJA NAASIKYAYA;Lo;0;L;;;;;N;;;;; 0DA5;SINHALA LETTER TAALUJA SANYOOGA NAAKSIKYAYA;Lo;0;L;;;;;N;;;;; 0DA6;SINHALA LETTER SANYAKA JAYANNA;Lo;0;L;;;;;N;;;;; 0DA7;SINHALA LETTER ALPAPRAANA TTAYANNA;Lo;0;L;;;;;N;;;;; 0DA8;SINHALA LETTER MAHAAPRAANA TTAYANNA;Lo;0;L;;;;;N;;;;; 0DA9;SINHALA LETTER ALPAPRAANA DDAYANNA;Lo;0;L;;;;;N;;;;; 0DAA;SINHALA LETTER MAHAAPRAANA DDAYANNA;Lo;0;L;;;;;N;;;;; 0DAB;SINHALA LETTER MUURDHAJA NAYANNA;Lo;0;L;;;;;N;;;;; 0DAC;SINHALA LETTER SANYAKA DDAYANNA;Lo;0;L;;;;;N;;;;; 0DAD;SINHALA LETTER ALPAPRAANA TAYANNA;Lo;0;L;;;;;N;;;;; 0DAE;SINHALA LETTER MAHAAPRAANA TAYANNA;Lo;0;L;;;;;N;;;;; 0DAF;SINHALA LETTER ALPAPRAANA DAYANNA;Lo;0;L;;;;;N;;;;; 0DB0;SINHALA LETTER MAHAAPRAANA DAYANNA;Lo;0;L;;;;;N;;;;; 0DB1;SINHALA LETTER DANTAJA NAYANNA;Lo;0;L;;;;;N;;;;; 0DB3;SINHALA LETTER SANYAKA DAYANNA;Lo;0;L;;;;;N;;;;; 0DB4;SINHALA LETTER ALPAPRAANA PAYANNA;Lo;0;L;;;;;N;;;;; 0DB5;SINHALA LETTER MAHAAPRAANA PAYANNA;Lo;0;L;;;;;N;;;;; 0DB6;SINHALA LETTER ALPAPRAANA BAYANNA;Lo;0;L;;;;;N;;;;; 0DB7;SINHALA LETTER MAHAAPRAANA BAYANNA;Lo;0;L;;;;;N;;;;; 0DB8;SINHALA LETTER MAYANNA;Lo;0;L;;;;;N;;;;; 0DB9;SINHALA LETTER AMBA BAYANNA;Lo;0;L;;;;;N;;;;; 0DBA;SINHALA LETTER YAYANNA;Lo;0;L;;;;;N;;;;; 0DBB;SINHALA LETTER RAYANNA;Lo;0;L;;;;;N;;;;; 0DBD;SINHALA LETTER DANTAJA LAYANNA;Lo;0;L;;;;;N;;;;; 0DC0;SINHALA LETTER VAYANNA;Lo;0;L;;;;;N;;;;; 0DC1;SINHALA LETTER TAALUJA SAYANNA;Lo;0;L;;;;;N;;;;; 0DC2;SINHALA LETTER MUURDHAJA SAYANNA;Lo;0;L;;;;;N;;;;; 0DC3;SINHALA LETTER DANTAJA SAYANNA;Lo;0;L;;;;;N;;;;; 0DC4;SINHALA LETTER HAYANNA;Lo;0;L;;;;;N;;;;; 0DC5;SINHALA LETTER MUURDHAJA LAYANNA;Lo;0;L;;;;;N;;;;; 0DC6;SINHALA LETTER FAYANNA;Lo;0;L;;;;;N;;;;; 0DCA;SINHALA SIGN AL-LAKUNA;Mn;9;NSM;;;;;N;;;;; 0DCF;SINHALA VOWEL SIGN AELA-PILLA;Mc;0;L;;;;;N;;;;; 0DD0;SINHALA VOWEL SIGN KETTI AEDA-PILLA;Mc;0;L;;;;;N;;;;; 0DD1;SINHALA VOWEL SIGN DIGA AEDA-PILLA;Mc;0;L;;;;;N;;;;; 0DD2;SINHALA VOWEL SIGN KETTI IS-PILLA;Mn;0;NSM;;;;;N;;;;; 0DD3;SINHALA VOWEL SIGN DIGA IS-PILLA;Mn;0;NSM;;;;;N;;;;; 0DD4;SINHALA VOWEL SIGN KETTI PAA-PILLA;Mn;0;NSM;;;;;N;;;;; 0DD6;SINHALA VOWEL SIGN DIGA PAA-PILLA;Mn;0;NSM;;;;;N;;;;; 0DD8;SINHALA VOWEL SIGN GAETTA-PILLA;Mc;0;L;;;;;N;;;;; 0DD9;SINHALA VOWEL SIGN KOMBUVA;Mc;0;L;;;;;N;;;;; 0DDA;SINHALA VOWEL SIGN DIGA KOMBUVA;Mc;0;L;0DD9 0DCA;;;;N;;;;; 0DDB;SINHALA VOWEL SIGN KOMBU DEKA;Mc;0;L;;;;;N;;;;; 0DDC;SINHALA VOWEL SIGN KOMBUVA HAA AELA-PILLA;Mc;0;L;0DD9 0DCF;;;;N;;;;; 0DDD;SINHALA VOWEL SIGN KOMBUVA HAA DIGA AELA-PILLA;Mc;0;L;0DDC 0DCA;;;;N;;;;; 0DDE;SINHALA VOWEL SIGN KOMBUVA HAA GAYANUKITTA;Mc;0;L;0DD9 0DDF;;;;N;;;;; 0DDF;SINHALA VOWEL SIGN GAYANUKITTA;Mc;0;L;;;;;N;;;;; 0DE6;SINHALA LITH DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 0DE7;SINHALA LITH DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 0DE8;SINHALA LITH DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 0DE9;SINHALA LITH DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 0DEA;SINHALA LITH DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 0DEB;SINHALA LITH DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 0DEC;SINHALA LITH DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 0DED;SINHALA LITH DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 0DEE;SINHALA LITH DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 0DEF;SINHALA LITH DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 0DF2;SINHALA VOWEL SIGN DIGA GAETTA-PILLA;Mc;0;L;;;;;N;;;;; 0DF3;SINHALA VOWEL SIGN DIGA GAYANUKITTA;Mc;0;L;;;;;N;;;;; 0DF4;SINHALA PUNCTUATION KUNDDALIYA;Po;0;L;;;;;N;;;;; 0E01;THAI CHARACTER KO KAI;Lo;0;L;;;;;N;THAI LETTER KO KAI;;;; 0E02;THAI CHARACTER KHO KHAI;Lo;0;L;;;;;N;THAI LETTER KHO KHAI;;;; 0E03;THAI CHARACTER KHO KHUAT;Lo;0;L;;;;;N;THAI LETTER KHO KHUAT;;;; 0E04;THAI CHARACTER KHO KHWAI;Lo;0;L;;;;;N;THAI LETTER KHO KHWAI;;;; 0E05;THAI CHARACTER KHO KHON;Lo;0;L;;;;;N;THAI LETTER KHO KHON;;;; 0E06;THAI CHARACTER KHO RAKHANG;Lo;0;L;;;;;N;THAI LETTER KHO RAKHANG;;;; 0E07;THAI CHARACTER NGO NGU;Lo;0;L;;;;;N;THAI LETTER NGO NGU;;;; 0E08;THAI CHARACTER CHO CHAN;Lo;0;L;;;;;N;THAI LETTER CHO CHAN;;;; 0E09;THAI CHARACTER CHO CHING;Lo;0;L;;;;;N;THAI LETTER CHO CHING;;;; 0E0A;THAI CHARACTER CHO CHANG;Lo;0;L;;;;;N;THAI LETTER CHO CHANG;;;; 0E0B;THAI CHARACTER SO SO;Lo;0;L;;;;;N;THAI LETTER SO SO;;;; 0E0C;THAI CHARACTER CHO CHOE;Lo;0;L;;;;;N;THAI LETTER CHO CHOE;;;; 0E0D;THAI CHARACTER YO YING;Lo;0;L;;;;;N;THAI LETTER YO YING;;;; 0E0E;THAI CHARACTER DO CHADA;Lo;0;L;;;;;N;THAI LETTER DO CHADA;;;; 0E0F;THAI CHARACTER TO PATAK;Lo;0;L;;;;;N;THAI LETTER TO PATAK;;;; 0E10;THAI CHARACTER THO THAN;Lo;0;L;;;;;N;THAI LETTER THO THAN;;;; 0E11;THAI CHARACTER THO NANGMONTHO;Lo;0;L;;;;;N;THAI LETTER THO NANGMONTHO;;;; 0E12;THAI CHARACTER THO PHUTHAO;Lo;0;L;;;;;N;THAI LETTER THO PHUTHAO;;;; 0E13;THAI CHARACTER NO NEN;Lo;0;L;;;;;N;THAI LETTER NO NEN;;;; 0E14;THAI CHARACTER DO DEK;Lo;0;L;;;;;N;THAI LETTER DO DEK;;;; 0E15;THAI CHARACTER TO TAO;Lo;0;L;;;;;N;THAI LETTER TO TAO;;;; 0E16;THAI CHARACTER THO THUNG;Lo;0;L;;;;;N;THAI LETTER THO THUNG;;;; 0E17;THAI CHARACTER THO THAHAN;Lo;0;L;;;;;N;THAI LETTER THO THAHAN;;;; 0E18;THAI CHARACTER THO THONG;Lo;0;L;;;;;N;THAI LETTER THO THONG;;;; 0E19;THAI CHARACTER NO NU;Lo;0;L;;;;;N;THAI LETTER NO NU;;;; 0E1A;THAI CHARACTER BO BAIMAI;Lo;0;L;;;;;N;THAI LETTER BO BAIMAI;;;; 0E1B;THAI CHARACTER PO PLA;Lo;0;L;;;;;N;THAI LETTER PO PLA;;;; 0E1C;THAI CHARACTER PHO PHUNG;Lo;0;L;;;;;N;THAI LETTER PHO PHUNG;;;; 0E1D;THAI CHARACTER FO FA;Lo;0;L;;;;;N;THAI LETTER FO FA;;;; 0E1E;THAI CHARACTER PHO PHAN;Lo;0;L;;;;;N;THAI LETTER PHO PHAN;;;; 0E1F;THAI CHARACTER FO FAN;Lo;0;L;;;;;N;THAI LETTER FO FAN;;;; 0E20;THAI CHARACTER PHO SAMPHAO;Lo;0;L;;;;;N;THAI LETTER PHO SAMPHAO;;;; 0E21;THAI CHARACTER MO MA;Lo;0;L;;;;;N;THAI LETTER MO MA;;;; 0E22;THAI CHARACTER YO YAK;Lo;0;L;;;;;N;THAI LETTER YO YAK;;;; 0E23;THAI CHARACTER RO RUA;Lo;0;L;;;;;N;THAI LETTER RO RUA;;;; 0E24;THAI CHARACTER RU;Lo;0;L;;;;;N;THAI LETTER RU;;;; 0E25;THAI CHARACTER LO LING;Lo;0;L;;;;;N;THAI LETTER LO LING;;;; 0E26;THAI CHARACTER LU;Lo;0;L;;;;;N;THAI LETTER LU;;;; 0E27;THAI CHARACTER WO WAEN;Lo;0;L;;;;;N;THAI LETTER WO WAEN;;;; 0E28;THAI CHARACTER SO SALA;Lo;0;L;;;;;N;THAI LETTER SO SALA;;;; 0E29;THAI CHARACTER SO RUSI;Lo;0;L;;;;;N;THAI LETTER SO RUSI;;;; 0E2A;THAI CHARACTER SO SUA;Lo;0;L;;;;;N;THAI LETTER SO SUA;;;; 0E2B;THAI CHARACTER HO HIP;Lo;0;L;;;;;N;THAI LETTER HO HIP;;;; 0E2C;THAI CHARACTER LO CHULA;Lo;0;L;;;;;N;THAI LETTER LO CHULA;;;; 0E2D;THAI CHARACTER O ANG;Lo;0;L;;;;;N;THAI LETTER O ANG;;;; 0E2E;THAI CHARACTER HO NOKHUK;Lo;0;L;;;;;N;THAI LETTER HO NOK HUK;;;; 0E2F;THAI CHARACTER PAIYANNOI;Lo;0;L;;;;;N;THAI PAI YAN NOI;;;; 0E30;THAI CHARACTER SARA A;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA A;;;; 0E31;THAI CHARACTER MAI HAN-AKAT;Mn;0;NSM;;;;;N;THAI VOWEL SIGN MAI HAN-AKAT;;;; 0E32;THAI CHARACTER SARA AA;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA AA;;;; 0E33;THAI CHARACTER SARA AM;Lo;0;L;<compat> 0E4D 0E32;;;;N;THAI VOWEL SIGN SARA AM;;;; 0E34;THAI CHARACTER SARA I;Mn;0;NSM;;;;;N;THAI VOWEL SIGN SARA I;;;; 0E35;THAI CHARACTER SARA II;Mn;0;NSM;;;;;N;THAI VOWEL SIGN SARA II;;;; 0E36;THAI CHARACTER SARA UE;Mn;0;NSM;;;;;N;THAI VOWEL SIGN SARA UE;;;; 0E37;THAI CHARACTER SARA UEE;Mn;0;NSM;;;;;N;THAI VOWEL SIGN SARA UEE;;;; 0E38;THAI CHARACTER SARA U;Mn;103;NSM;;;;;N;THAI VOWEL SIGN SARA U;;;; 0E39;THAI CHARACTER SARA UU;Mn;103;NSM;;;;;N;THAI VOWEL SIGN SARA UU;;;; 0E3A;THAI CHARACTER PHINTHU;Mn;9;NSM;;;;;N;THAI VOWEL SIGN PHINTHU;;;; 0E3F;THAI CURRENCY SYMBOL BAHT;Sc;0;ET;;;;;N;THAI BAHT SIGN;;;; 0E40;THAI CHARACTER SARA E;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA E;;;; 0E41;THAI CHARACTER SARA AE;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA AE;;;; 0E42;THAI CHARACTER SARA O;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA O;;;; 0E43;THAI CHARACTER SARA AI MAIMUAN;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA MAI MUAN;;;; 0E44;THAI CHARACTER SARA AI MAIMALAI;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA MAI MALAI;;;; 0E45;THAI CHARACTER LAKKHANGYAO;Lo;0;L;;;;;N;THAI LAK KHANG YAO;;;; 0E46;THAI CHARACTER MAIYAMOK;Lm;0;L;;;;;N;THAI MAI YAMOK;;;; 0E47;THAI CHARACTER MAITAIKHU;Mn;0;NSM;;;;;N;THAI VOWEL SIGN MAI TAI KHU;;;; 0E48;THAI CHARACTER MAI EK;Mn;107;NSM;;;;;N;THAI TONE MAI EK;;;; 0E49;THAI CHARACTER MAI THO;Mn;107;NSM;;;;;N;THAI TONE MAI THO;;;; 0E4A;THAI CHARACTER MAI TRI;Mn;107;NSM;;;;;N;THAI TONE MAI TRI;;;; 0E4B;THAI CHARACTER MAI CHATTAWA;Mn;107;NSM;;;;;N;THAI TONE MAI CHATTAWA;;;; 0E4C;THAI CHARACTER THANTHAKHAT;Mn;0;NSM;;;;;N;THAI THANTHAKHAT;;;; 0E4D;THAI CHARACTER NIKHAHIT;Mn;0;NSM;;;;;N;THAI NIKKHAHIT;;;; 0E4E;THAI CHARACTER YAMAKKAN;Mn;0;NSM;;;;;N;THAI YAMAKKAN;;;; 0E4F;THAI CHARACTER FONGMAN;Po;0;L;;;;;N;THAI FONGMAN;;;; 0E50;THAI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 0E51;THAI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 0E52;THAI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 0E53;THAI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 0E54;THAI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 0E55;THAI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 0E56;THAI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 0E57;THAI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 0E58;THAI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 0E59;THAI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 0E5A;THAI CHARACTER ANGKHANKHU;Po;0;L;;;;;N;THAI ANGKHANKHU;;;; 0E5B;THAI CHARACTER KHOMUT;Po;0;L;;;;;N;THAI KHOMUT;;;; 0E81;LAO LETTER KO;Lo;0;L;;;;;N;;;;; 0E82;LAO LETTER KHO SUNG;Lo;0;L;;;;;N;;;;; 0E84;LAO LETTER KHO TAM;Lo;0;L;;;;;N;;;;; 0E87;LAO LETTER NGO;Lo;0;L;;;;;N;;;;; 0E88;LAO LETTER CO;Lo;0;L;;;;;N;;;;; 0E8A;LAO LETTER SO TAM;Lo;0;L;;;;;N;;;;; 0E8D;LAO LETTER NYO;Lo;0;L;;;;;N;;;;; 0E94;LAO LETTER DO;Lo;0;L;;;;;N;;;;; 0E95;LAO LETTER TO;Lo;0;L;;;;;N;;;;; 0E96;LAO LETTER THO SUNG;Lo;0;L;;;;;N;;;;; 0E97;LAO LETTER THO TAM;Lo;0;L;;;;;N;;;;; 0E99;LAO LETTER NO;Lo;0;L;;;;;N;;;;; 0E9A;LAO LETTER BO;Lo;0;L;;;;;N;;;;; 0E9B;LAO LETTER PO;Lo;0;L;;;;;N;;;;; 0E9C;LAO LETTER PHO SUNG;Lo;0;L;;;;;N;;;;; 0E9D;LAO LETTER FO TAM;Lo;0;L;;;;;N;;;;; 0E9E;LAO LETTER PHO TAM;Lo;0;L;;;;;N;;;;; 0E9F;LAO LETTER FO SUNG;Lo;0;L;;;;;N;;;;; 0EA1;LAO LETTER MO;Lo;0;L;;;;;N;;;;; 0EA2;LAO LETTER YO;Lo;0;L;;;;;N;;;;; 0EA3;LAO LETTER LO LING;Lo;0;L;;;;;N;;;;; 0EA5;LAO LETTER LO LOOT;Lo;0;L;;;;;N;;;;; 0EA7;LAO LETTER WO;Lo;0;L;;;;;N;;;;; 0EAA;LAO LETTER SO SUNG;Lo;0;L;;;;;N;;;;; 0EAB;LAO LETTER HO SUNG;Lo;0;L;;;;;N;;;;; 0EAD;LAO LETTER O;Lo;0;L;;;;;N;;;;; 0EAE;LAO LETTER HO TAM;Lo;0;L;;;;;N;;;;; 0EAF;LAO ELLIPSIS;Lo;0;L;;;;;N;;;;; 0EB0;LAO VOWEL SIGN A;Lo;0;L;;;;;N;;;;; 0EB1;LAO VOWEL SIGN MAI KAN;Mn;0;NSM;;;;;N;;;;; 0EB2;LAO VOWEL SIGN AA;Lo;0;L;;;;;N;;;;; 0EB3;LAO VOWEL SIGN AM;Lo;0;L;<compat> 0ECD 0EB2;;;;N;;;;; 0EB4;LAO VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; 0EB5;LAO VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; 0EB6;LAO VOWEL SIGN Y;Mn;0;NSM;;;;;N;;;;; 0EB7;LAO VOWEL SIGN YY;Mn;0;NSM;;;;;N;;;;; 0EB8;LAO VOWEL SIGN U;Mn;118;NSM;;;;;N;;;;; 0EB9;LAO VOWEL SIGN UU;Mn;118;NSM;;;;;N;;;;; 0EBB;LAO VOWEL SIGN MAI KON;Mn;0;NSM;;;;;N;;;;; 0EBC;LAO SEMIVOWEL SIGN LO;Mn;0;NSM;;;;;N;;;;; 0EBD;LAO SEMIVOWEL SIGN NYO;Lo;0;L;;;;;N;;;;; 0EC0;LAO VOWEL SIGN E;Lo;0;L;;;;;N;;;;; 0EC1;LAO VOWEL SIGN EI;Lo;0;L;;;;;N;;;;; 0EC2;LAO VOWEL SIGN O;Lo;0;L;;;;;N;;;;; 0EC3;LAO VOWEL SIGN AY;Lo;0;L;;;;;N;;;;; 0EC4;LAO VOWEL SIGN AI;Lo;0;L;;;;;N;;;;; 0EC6;LAO KO LA;Lm;0;L;;;;;N;;;;; 0EC8;LAO TONE MAI EK;Mn;122;NSM;;;;;N;;;;; 0EC9;LAO TONE MAI THO;Mn;122;NSM;;;;;N;;;;; 0ECA;LAO TONE MAI TI;Mn;122;NSM;;;;;N;;;;; 0ECB;LAO TONE MAI CATAWA;Mn;122;NSM;;;;;N;;;;; 0ECC;LAO CANCELLATION MARK;Mn;0;NSM;;;;;N;;;;; 0ECD;LAO NIGGAHITA;Mn;0;NSM;;;;;N;;;;; 0ED0;LAO DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 0ED1;LAO DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 0ED2;LAO DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 0ED3;LAO DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 0ED4;LAO DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 0ED5;LAO DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 0ED6;LAO DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 0ED7;LAO DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 0ED8;LAO DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 0ED9;LAO DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 0EDC;LAO HO NO;Lo;0;L;<compat> 0EAB 0E99;;;;N;;;;; 0EDD;LAO HO MO;Lo;0;L;<compat> 0EAB 0EA1;;;;N;;;;; 0EDE;LAO LETTER KHMU GO;Lo;0;L;;;;;N;;;;; 0EDF;LAO LETTER KHMU NYO;Lo;0;L;;;;;N;;;;; 0F00;TIBETAN SYLLABLE OM;Lo;0;L;;;;;N;;;;; 0F01;TIBETAN MARK GTER YIG MGO TRUNCATED A;So;0;L;;;;;N;;;;; 0F02;TIBETAN MARK GTER YIG MGO -UM RNAM BCAD MA;So;0;L;;;;;N;;;;; 0F03;TIBETAN MARK GTER YIG MGO -UM GTER TSHEG MA;So;0;L;;;;;N;;;;; 0F04;TIBETAN MARK INITIAL YIG MGO MDUN MA;Po;0;L;;;;;N;TIBETAN SINGLE ORNAMENT;;;; 0F05;TIBETAN MARK CLOSING YIG MGO SGAB MA;Po;0;L;;;;;N;;;;; 0F06;TIBETAN MARK CARET YIG MGO PHUR SHAD MA;Po;0;L;;;;;N;;;;; 0F07;TIBETAN MARK YIG MGO TSHEG SHAD MA;Po;0;L;;;;;N;;;;; 0F08;TIBETAN MARK SBRUL SHAD;Po;0;L;;;;;N;TIBETAN RGYANSHAD;;;; 0F09;TIBETAN MARK BSKUR YIG MGO;Po;0;L;;;;;N;;;;; 0F0A;TIBETAN MARK BKA- SHOG YIG MGO;Po;0;L;;;;;N;;;;; 0F0B;TIBETAN MARK INTERSYLLABIC TSHEG;Po;0;L;;;;;N;TIBETAN TSEG;;;; 0F0C;TIBETAN MARK DELIMITER TSHEG BSTAR;Po;0;L;<noBreak> 0F0B;;;;N;;;;; 0F0D;TIBETAN MARK SHAD;Po;0;L;;;;;N;TIBETAN SHAD;;;; 0F0E;TIBETAN MARK NYIS SHAD;Po;0;L;;;;;N;TIBETAN DOUBLE SHAD;;;; 0F0F;TIBETAN MARK TSHEG SHAD;Po;0;L;;;;;N;;;;; 0F10;TIBETAN MARK NYIS TSHEG SHAD;Po;0;L;;;;;N;;;;; 0F11;TIBETAN MARK RIN CHEN SPUNGS SHAD;Po;0;L;;;;;N;TIBETAN RINCHANPHUNGSHAD;;;; 0F12;TIBETAN MARK RGYA GRAM SHAD;Po;0;L;;;;;N;;;;; 0F13;TIBETAN MARK CARET -DZUD RTAGS ME LONG CAN;So;0;L;;;;;N;;;;; 0F14;TIBETAN MARK GTER TSHEG;Po;0;L;;;;;N;TIBETAN COMMA;;;; 0F15;TIBETAN LOGOTYPE SIGN CHAD RTAGS;So;0;L;;;;;N;;;;; 0F16;TIBETAN LOGOTYPE SIGN LHAG RTAGS;So;0;L;;;;;N;;;;; 0F17;TIBETAN ASTROLOGICAL SIGN SGRA GCAN -CHAR RTAGS;So;0;L;;;;;N;;;;; 0F18;TIBETAN ASTROLOGICAL SIGN -KHYUD PA;Mn;220;NSM;;;;;N;;;;; 0F19;TIBETAN ASTROLOGICAL SIGN SDONG TSHUGS;Mn;220;NSM;;;;;N;;;;; 0F1A;TIBETAN SIGN RDEL DKAR GCIG;So;0;L;;;;;N;;;;; 0F1B;TIBETAN SIGN RDEL DKAR GNYIS;So;0;L;;;;;N;;;;; 0F1C;TIBETAN SIGN RDEL DKAR GSUM;So;0;L;;;;;N;;;;; 0F1D;TIBETAN SIGN RDEL NAG GCIG;So;0;L;;;;;N;;;;; 0F1E;TIBETAN SIGN RDEL NAG GNYIS;So;0;L;;;;;N;;;;; 0F1F;TIBETAN SIGN RDEL DKAR RDEL NAG;So;0;L;;;;;N;;;;; 0F20;TIBETAN DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 0F21;TIBETAN DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 0F22;TIBETAN DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 0F23;TIBETAN DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 0F24;TIBETAN DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 0F25;TIBETAN DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 0F26;TIBETAN DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 0F27;TIBETAN DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 0F28;TIBETAN DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 0F29;TIBETAN DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 0F2A;TIBETAN DIGIT HALF ONE;No;0;L;;;;1/2;N;;;;; 0F2B;TIBETAN DIGIT HALF TWO;No;0;L;;;;3/2;N;;;;; 0F2C;TIBETAN DIGIT HALF THREE;No;0;L;;;;5/2;N;;;;; 0F2D;TIBETAN DIGIT HALF FOUR;No;0;L;;;;7/2;N;;;;; 0F2E;TIBETAN DIGIT HALF FIVE;No;0;L;;;;9/2;N;;;;; 0F2F;TIBETAN DIGIT HALF SIX;No;0;L;;;;11/2;N;;;;; 0F30;TIBETAN DIGIT HALF SEVEN;No;0;L;;;;13/2;N;;;;; 0F31;TIBETAN DIGIT HALF EIGHT;No;0;L;;;;15/2;N;;;;; 0F32;TIBETAN DIGIT HALF NINE;No;0;L;;;;17/2;N;;;;; 0F33;TIBETAN DIGIT HALF ZERO;No;0;L;;;;-1/2;N;;;;; 0F34;TIBETAN MARK BSDUS RTAGS;So;0;L;;;;;N;;;;; 0F35;TIBETAN MARK NGAS BZUNG NYI ZLA;Mn;220;NSM;;;;;N;TIBETAN HONORIFIC UNDER RING;;;; 0F36;TIBETAN MARK CARET -DZUD RTAGS BZHI MIG CAN;So;0;L;;;;;N;;;;; 0F37;TIBETAN MARK NGAS BZUNG SGOR RTAGS;Mn;220;NSM;;;;;N;TIBETAN UNDER RING;;;; 0F38;TIBETAN MARK CHE MGO;So;0;L;;;;;N;;;;; 0F39;TIBETAN MARK TSA -PHRU;Mn;216;NSM;;;;;N;TIBETAN LENITION MARK;;;; 0F3A;TIBETAN MARK GUG RTAGS GYON;Ps;0;ON;;;;;Y;;;;; 0F3B;TIBETAN MARK GUG RTAGS GYAS;Pe;0;ON;;;;;Y;;;;; 0F3C;TIBETAN MARK ANG KHANG GYON;Ps;0;ON;;;;;Y;TIBETAN LEFT BRACE;;;; 0F3D;TIBETAN MARK ANG KHANG GYAS;Pe;0;ON;;;;;Y;TIBETAN RIGHT BRACE;;;; 0F3E;TIBETAN SIGN YAR TSHES;Mc;0;L;;;;;N;;;;; 0F3F;TIBETAN SIGN MAR TSHES;Mc;0;L;;;;;N;;;;; 0F40;TIBETAN LETTER KA;Lo;0;L;;;;;N;;;;; 0F41;TIBETAN LETTER KHA;Lo;0;L;;;;;N;;;;; 0F42;TIBETAN LETTER GA;Lo;0;L;;;;;N;;;;; 0F43;TIBETAN LETTER GHA;Lo;0;L;0F42 0FB7;;;;N;;;;; 0F44;TIBETAN LETTER NGA;Lo;0;L;;;;;N;;;;; 0F45;TIBETAN LETTER CA;Lo;0;L;;;;;N;;;;; 0F46;TIBETAN LETTER CHA;Lo;0;L;;;;;N;;;;; 0F47;TIBETAN LETTER JA;Lo;0;L;;;;;N;;;;; 0F49;TIBETAN LETTER NYA;Lo;0;L;;;;;N;;;;; 0F4A;TIBETAN LETTER TTA;Lo;0;L;;;;;N;TIBETAN LETTER REVERSED TA;;;; 0F4B;TIBETAN LETTER TTHA;Lo;0;L;;;;;N;TIBETAN LETTER REVERSED THA;;;; 0F4C;TIBETAN LETTER DDA;Lo;0;L;;;;;N;TIBETAN LETTER REVERSED DA;;;; 0F4D;TIBETAN LETTER DDHA;Lo;0;L;0F4C 0FB7;;;;N;;;;; 0F4E;TIBETAN LETTER NNA;Lo;0;L;;;;;N;TIBETAN LETTER REVERSED NA;;;; 0F4F;TIBETAN LETTER TA;Lo;0;L;;;;;N;;;;; 0F50;TIBETAN LETTER THA;Lo;0;L;;;;;N;;;;; 0F51;TIBETAN LETTER DA;Lo;0;L;;;;;N;;;;; 0F52;TIBETAN LETTER DHA;Lo;0;L;0F51 0FB7;;;;N;;;;; 0F53;TIBETAN LETTER NA;Lo;0;L;;;;;N;;;;; 0F54;TIBETAN LETTER PA;Lo;0;L;;;;;N;;;;; 0F55;TIBETAN LETTER PHA;Lo;0;L;;;;;N;;;;; 0F56;TIBETAN LETTER BA;Lo;0;L;;;;;N;;;;; 0F57;TIBETAN LETTER BHA;Lo;0;L;0F56 0FB7;;;;N;;;;; 0F58;TIBETAN LETTER MA;Lo;0;L;;;;;N;;;;; 0F59;TIBETAN LETTER TSA;Lo;0;L;;;;;N;;;;; 0F5A;TIBETAN LETTER TSHA;Lo;0;L;;;;;N;;;;; 0F5B;TIBETAN LETTER DZA;Lo;0;L;;;;;N;;;;; 0F5C;TIBETAN LETTER DZHA;Lo;0;L;0F5B 0FB7;;;;N;;;;; 0F5D;TIBETAN LETTER WA;Lo;0;L;;;;;N;;;;; 0F5E;TIBETAN LETTER ZHA;Lo;0;L;;;;;N;;;;; 0F5F;TIBETAN LETTER ZA;Lo;0;L;;;;;N;;;;; 0F60;TIBETAN LETTER -A;Lo;0;L;;;;;N;TIBETAN LETTER AA;;;; 0F61;TIBETAN LETTER YA;Lo;0;L;;;;;N;;;;; 0F62;TIBETAN LETTER RA;Lo;0;L;;;;;N;;;;; 0F63;TIBETAN LETTER LA;Lo;0;L;;;;;N;;;;; 0F64;TIBETAN LETTER SHA;Lo;0;L;;;;;N;;;;; 0F65;TIBETAN LETTER SSA;Lo;0;L;;;;;N;TIBETAN LETTER REVERSED SHA;;;; 0F66;TIBETAN LETTER SA;Lo;0;L;;;;;N;;;;; 0F67;TIBETAN LETTER HA;Lo;0;L;;;;;N;;;;; 0F68;TIBETAN LETTER A;Lo;0;L;;;;;N;;;;; 0F69;TIBETAN LETTER KSSA;Lo;0;L;0F40 0FB5;;;;N;;;;; 0F6A;TIBETAN LETTER FIXED-FORM RA;Lo;0;L;;;;;N;;;;; 0F6B;TIBETAN LETTER KKA;Lo;0;L;;;;;N;;;;; 0F6C;TIBETAN LETTER RRA;Lo;0;L;;;;;N;;;;; 0F71;TIBETAN VOWEL SIGN AA;Mn;129;NSM;;;;;N;;;;; 0F72;TIBETAN VOWEL SIGN I;Mn;130;NSM;;;;;N;;;;; 0F73;TIBETAN VOWEL SIGN II;Mn;0;NSM;0F71 0F72;;;;N;;;;; 0F74;TIBETAN VOWEL SIGN U;Mn;132;NSM;;;;;N;;;;; 0F75;TIBETAN VOWEL SIGN UU;Mn;0;NSM;0F71 0F74;;;;N;;;;; 0F76;TIBETAN VOWEL SIGN VOCALIC R;Mn;0;NSM;0FB2 0F80;;;;N;;;;; 0F77;TIBETAN VOWEL SIGN VOCALIC RR;Mn;0;NSM;<compat> 0FB2 0F81;;;;N;;;;; 0F78;TIBETAN VOWEL SIGN VOCALIC L;Mn;0;NSM;0FB3 0F80;;;;N;;;;; 0F79;TIBETAN VOWEL SIGN VOCALIC LL;Mn;0;NSM;<compat> 0FB3 0F81;;;;N;;;;; 0F7A;TIBETAN VOWEL SIGN E;Mn;130;NSM;;;;;N;;;;; 0F7B;TIBETAN VOWEL SIGN EE;Mn;130;NSM;;;;;N;TIBETAN VOWEL SIGN AI;;;; 0F7C;TIBETAN VOWEL SIGN O;Mn;130;NSM;;;;;N;;;;; 0F7D;TIBETAN VOWEL SIGN OO;Mn;130;NSM;;;;;N;TIBETAN VOWEL SIGN AU;;;; 0F7E;TIBETAN SIGN RJES SU NGA RO;Mn;0;NSM;;;;;N;TIBETAN ANUSVARA;;;; 0F7F;TIBETAN SIGN RNAM BCAD;Mc;0;L;;;;;N;TIBETAN VISARGA;;;; 0F80;TIBETAN VOWEL SIGN REVERSED I;Mn;130;NSM;;;;;N;TIBETAN VOWEL SIGN SHORT I;;;; 0F81;TIBETAN VOWEL SIGN REVERSED II;Mn;0;NSM;0F71 0F80;;;;N;;;;; 0F82;TIBETAN SIGN NYI ZLA NAA DA;Mn;230;NSM;;;;;N;TIBETAN CANDRABINDU WITH ORNAMENT;;;; 0F83;TIBETAN SIGN SNA LDAN;Mn;230;NSM;;;;;N;TIBETAN CANDRABINDU;;;; 0F84;TIBETAN MARK HALANTA;Mn;9;NSM;;;;;N;TIBETAN VIRAMA;;;; 0F85;TIBETAN MARK PALUTA;Po;0;L;;;;;N;TIBETAN CHUCHENYIGE;;;; 0F86;TIBETAN SIGN LCI RTAGS;Mn;230;NSM;;;;;N;;;;; 0F87;TIBETAN SIGN YANG RTAGS;Mn;230;NSM;;;;;N;;;;; 0F88;TIBETAN SIGN LCE TSA CAN;Lo;0;L;;;;;N;;;;; 0F89;TIBETAN SIGN MCHU CAN;Lo;0;L;;;;;N;;;;; 0F8A;TIBETAN SIGN GRU CAN RGYINGS;Lo;0;L;;;;;N;;;;; 0F8B;TIBETAN SIGN GRU MED RGYINGS;Lo;0;L;;;;;N;;;;; 0F8C;TIBETAN SIGN INVERTED MCHU CAN;Lo;0;L;;;;;N;;;;; 0F8D;TIBETAN SUBJOINED SIGN LCE TSA CAN;Mn;0;NSM;;;;;N;;;;; 0F8E;TIBETAN SUBJOINED SIGN MCHU CAN;Mn;0;NSM;;;;;N;;;;; 0F8F;TIBETAN SUBJOINED SIGN INVERTED MCHU CAN;Mn;0;NSM;;;;;N;;;;; 0F90;TIBETAN SUBJOINED LETTER KA;Mn;0;NSM;;;;;N;;;;; 0F91;TIBETAN SUBJOINED LETTER KHA;Mn;0;NSM;;;;;N;;;;; 0F92;TIBETAN SUBJOINED LETTER GA;Mn;0;NSM;;;;;N;;;;; 0F93;TIBETAN SUBJOINED LETTER GHA;Mn;0;NSM;0F92 0FB7;;;;N;;;;; 0F94;TIBETAN SUBJOINED LETTER NGA;Mn;0;NSM;;;;;N;;;;; 0F95;TIBETAN SUBJOINED LETTER CA;Mn;0;NSM;;;;;N;;;;; 0F96;TIBETAN SUBJOINED LETTER CHA;Mn;0;NSM;;;;;N;;;;; 0F97;TIBETAN SUBJOINED LETTER JA;Mn;0;NSM;;;;;N;;;;; 0F99;TIBETAN SUBJOINED LETTER NYA;Mn;0;NSM;;;;;N;;;;; 0F9A;TIBETAN SUBJOINED LETTER TTA;Mn;0;NSM;;;;;N;;;;; 0F9B;TIBETAN SUBJOINED LETTER TTHA;Mn;0;NSM;;;;;N;;;;; 0F9C;TIBETAN SUBJOINED LETTER DDA;Mn;0;NSM;;;;;N;;;;; 0F9D;TIBETAN SUBJOINED LETTER DDHA;Mn;0;NSM;0F9C 0FB7;;;;N;;;;; 0F9E;TIBETAN SUBJOINED LETTER NNA;Mn;0;NSM;;;;;N;;;;; 0F9F;TIBETAN SUBJOINED LETTER TA;Mn;0;NSM;;;;;N;;;;; 0FA0;TIBETAN SUBJOINED LETTER THA;Mn;0;NSM;;;;;N;;;;; 0FA1;TIBETAN SUBJOINED LETTER DA;Mn;0;NSM;;;;;N;;;;; 0FA2;TIBETAN SUBJOINED LETTER DHA;Mn;0;NSM;0FA1 0FB7;;;;N;;;;; 0FA3;TIBETAN SUBJOINED LETTER NA;Mn;0;NSM;;;;;N;;;;; 0FA4;TIBETAN SUBJOINED LETTER PA;Mn;0;NSM;;;;;N;;;;; 0FA5;TIBETAN SUBJOINED LETTER PHA;Mn;0;NSM;;;;;N;;;;; 0FA6;TIBETAN SUBJOINED LETTER BA;Mn;0;NSM;;;;;N;;;;; 0FA7;TIBETAN SUBJOINED LETTER BHA;Mn;0;NSM;0FA6 0FB7;;;;N;;;;; 0FA8;TIBETAN SUBJOINED LETTER MA;Mn;0;NSM;;;;;N;;;;; 0FA9;TIBETAN SUBJOINED LETTER TSA;Mn;0;NSM;;;;;N;;;;; 0FAA;TIBETAN SUBJOINED LETTER TSHA;Mn;0;NSM;;;;;N;;;;; 0FAB;TIBETAN SUBJOINED LETTER DZA;Mn;0;NSM;;;;;N;;;;; 0FAC;TIBETAN SUBJOINED LETTER DZHA;Mn;0;NSM;0FAB 0FB7;;;;N;;;;; 0FAD;TIBETAN SUBJOINED LETTER WA;Mn;0;NSM;;;;;N;;;;; 0FAE;TIBETAN SUBJOINED LETTER ZHA;Mn;0;NSM;;;;;N;;;;; 0FAF;TIBETAN SUBJOINED LETTER ZA;Mn;0;NSM;;;;;N;;;;; 0FB0;TIBETAN SUBJOINED LETTER -A;Mn;0;NSM;;;;;N;;;;; 0FB1;TIBETAN SUBJOINED LETTER YA;Mn;0;NSM;;;;;N;;;;; 0FB2;TIBETAN SUBJOINED LETTER RA;Mn;0;NSM;;;;;N;;;;; 0FB3;TIBETAN SUBJOINED LETTER LA;Mn;0;NSM;;;;;N;;;;; 0FB4;TIBETAN SUBJOINED LETTER SHA;Mn;0;NSM;;;;;N;;;;; 0FB5;TIBETAN SUBJOINED LETTER SSA;Mn;0;NSM;;;;;N;;;;; 0FB6;TIBETAN SUBJOINED LETTER SA;Mn;0;NSM;;;;;N;;;;; 0FB7;TIBETAN SUBJOINED LETTER HA;Mn;0;NSM;;;;;N;;;;; 0FB8;TIBETAN SUBJOINED LETTER A;Mn;0;NSM;;;;;N;;;;; 0FB9;TIBETAN SUBJOINED LETTER KSSA;Mn;0;NSM;0F90 0FB5;;;;N;;;;; 0FBA;TIBETAN SUBJOINED LETTER FIXED-FORM WA;Mn;0;NSM;;;;;N;;;;; 0FBB;TIBETAN SUBJOINED LETTER FIXED-FORM YA;Mn;0;NSM;;;;;N;;;;; 0FBC;TIBETAN SUBJOINED LETTER FIXED-FORM RA;Mn;0;NSM;;;;;N;;;;; 0FBE;TIBETAN KU RU KHA;So;0;L;;;;;N;;;;; 0FBF;TIBETAN KU RU KHA BZHI MIG CAN;So;0;L;;;;;N;;;;; 0FC0;TIBETAN CANTILLATION SIGN HEAVY BEAT;So;0;L;;;;;N;;;;; 0FC1;TIBETAN CANTILLATION SIGN LIGHT BEAT;So;0;L;;;;;N;;;;; 0FC2;TIBETAN CANTILLATION SIGN CANG TE-U;So;0;L;;;;;N;;;;; 0FC3;TIBETAN CANTILLATION SIGN SBUB -CHAL;So;0;L;;;;;N;;;;; 0FC4;TIBETAN SYMBOL DRIL BU;So;0;L;;;;;N;;;;; 0FC5;TIBETAN SYMBOL RDO RJE;So;0;L;;;;;N;;;;; 0FC6;TIBETAN SYMBOL PADMA GDAN;Mn;220;NSM;;;;;N;;;;; 0FC7;TIBETAN SYMBOL RDO RJE RGYA GRAM;So;0;L;;;;;N;;;;; 0FC8;TIBETAN SYMBOL PHUR PA;So;0;L;;;;;N;;;;; 0FC9;TIBETAN SYMBOL NOR BU;So;0;L;;;;;N;;;;; 0FCA;TIBETAN SYMBOL NOR BU NYIS -KHYIL;So;0;L;;;;;N;;;;; 0FCB;TIBETAN SYMBOL NOR BU GSUM -KHYIL;So;0;L;;;;;N;;;;; 0FCC;TIBETAN SYMBOL NOR BU BZHI -KHYIL;So;0;L;;;;;N;;;;; 0FCE;TIBETAN SIGN RDEL NAG RDEL DKAR;So;0;L;;;;;N;;;;; 0FCF;TIBETAN SIGN RDEL NAG GSUM;So;0;L;;;;;N;;;;; 0FD0;TIBETAN MARK BSKA- SHOG GI MGO RGYAN;Po;0;L;;;;;N;;;;; 0FD1;TIBETAN MARK MNYAM YIG GI MGO RGYAN;Po;0;L;;;;;N;;;;; 0FD2;TIBETAN MARK NYIS TSHEG;Po;0;L;;;;;N;;;;; 0FD3;TIBETAN MARK INITIAL BRDA RNYING YIG MGO MDUN MA;Po;0;L;;;;;N;;;;; 0FD4;TIBETAN MARK CLOSING BRDA RNYING YIG MGO SGAB MA;Po;0;L;;;;;N;;;;; 0FD5;RIGHT-FACING SVASTI SIGN;So;0;L;;;;;N;;;;; 0FD6;LEFT-FACING SVASTI SIGN;So;0;L;;;;;N;;;;; 0FD7;RIGHT-FACING SVASTI SIGN WITH DOTS;So;0;L;;;;;N;;;;; 0FD8;LEFT-FACING SVASTI SIGN WITH DOTS;So;0;L;;;;;N;;;;; 0FD9;TIBETAN MARK LEADING MCHAN RTAGS;Po;0;L;;;;;N;;;;; 0FDA;TIBETAN MARK TRAILING MCHAN RTAGS;Po;0;L;;;;;N;;;;; 1000;MYANMAR LETTER KA;Lo;0;L;;;;;N;;;;; 1001;MYANMAR LETTER KHA;Lo;0;L;;;;;N;;;;; 1002;MYANMAR LETTER GA;Lo;0;L;;;;;N;;;;; 1003;MYANMAR LETTER GHA;Lo;0;L;;;;;N;;;;; 1004;MYANMAR LETTER NGA;Lo;0;L;;;;;N;;;;; 1005;MYANMAR LETTER CA;Lo;0;L;;;;;N;;;;; 1006;MYANMAR LETTER CHA;Lo;0;L;;;;;N;;;;; 1007;MYANMAR LETTER JA;Lo;0;L;;;;;N;;;;; 1008;MYANMAR LETTER JHA;Lo;0;L;;;;;N;;;;; 1009;MYANMAR LETTER NYA;Lo;0;L;;;;;N;;;;; 100A;MYANMAR LETTER NNYA;Lo;0;L;;;;;N;;;;; 100B;MYANMAR LETTER TTA;Lo;0;L;;;;;N;;;;; 100C;MYANMAR LETTER TTHA;Lo;0;L;;;;;N;;;;; 100D;MYANMAR LETTER DDA;Lo;0;L;;;;;N;;;;; 100E;MYANMAR LETTER DDHA;Lo;0;L;;;;;N;;;;; 100F;MYANMAR LETTER NNA;Lo;0;L;;;;;N;;;;; 1010;MYANMAR LETTER TA;Lo;0;L;;;;;N;;;;; 1011;MYANMAR LETTER THA;Lo;0;L;;;;;N;;;;; 1012;MYANMAR LETTER DA;Lo;0;L;;;;;N;;;;; 1013;MYANMAR LETTER DHA;Lo;0;L;;;;;N;;;;; 1014;MYANMAR LETTER NA;Lo;0;L;;;;;N;;;;; 1015;MYANMAR LETTER PA;Lo;0;L;;;;;N;;;;; 1016;MYANMAR LETTER PHA;Lo;0;L;;;;;N;;;;; 1017;MYANMAR LETTER BA;Lo;0;L;;;;;N;;;;; 1018;MYANMAR LETTER BHA;Lo;0;L;;;;;N;;;;; 1019;MYANMAR LETTER MA;Lo;0;L;;;;;N;;;;; 101A;MYANMAR LETTER YA;Lo;0;L;;;;;N;;;;; 101B;MYANMAR LETTER RA;Lo;0;L;;;;;N;;;;; 101C;MYANMAR LETTER LA;Lo;0;L;;;;;N;;;;; 101D;MYANMAR LETTER WA;Lo;0;L;;;;;N;;;;; 101E;MYANMAR LETTER SA;Lo;0;L;;;;;N;;;;; 101F;MYANMAR LETTER HA;Lo;0;L;;;;;N;;;;; 1020;MYANMAR LETTER LLA;Lo;0;L;;;;;N;;;;; 1021;MYANMAR LETTER A;Lo;0;L;;;;;N;;;;; 1022;MYANMAR LETTER SHAN A;Lo;0;L;;;;;N;;;;; 1023;MYANMAR LETTER I;Lo;0;L;;;;;N;;;;; 1024;MYANMAR LETTER II;Lo;0;L;;;;;N;;;;; 1025;MYANMAR LETTER U;Lo;0;L;;;;;N;;;;; 1026;MYANMAR LETTER UU;Lo;0;L;1025 102E;;;;N;;;;; 1027;MYANMAR LETTER E;Lo;0;L;;;;;N;;;;; 1028;MYANMAR LETTER MON E;Lo;0;L;;;;;N;;;;; 1029;MYANMAR LETTER O;Lo;0;L;;;;;N;;;;; 102A;MYANMAR LETTER AU;Lo;0;L;;;;;N;;;;; 102B;MYANMAR VOWEL SIGN TALL AA;Mc;0;L;;;;;N;;;;; 102C;MYANMAR VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 102D;MYANMAR VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; 102E;MYANMAR VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; 102F;MYANMAR VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 1030;MYANMAR VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 1031;MYANMAR VOWEL SIGN E;Mc;0;L;;;;;N;;;;; 1032;MYANMAR VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; 1033;MYANMAR VOWEL SIGN MON II;Mn;0;NSM;;;;;N;;;;; 1034;MYANMAR VOWEL SIGN MON O;Mn;0;NSM;;;;;N;;;;; 1035;MYANMAR VOWEL SIGN E ABOVE;Mn;0;NSM;;;;;N;;;;; 1036;MYANMAR SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; 1037;MYANMAR SIGN DOT BELOW;Mn;7;NSM;;;;;N;;;;; 1038;MYANMAR SIGN VISARGA;Mc;0;L;;;;;N;;;;; 1039;MYANMAR SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 103A;MYANMAR SIGN ASAT;Mn;9;NSM;;;;;N;;;;; 103B;MYANMAR CONSONANT SIGN MEDIAL YA;Mc;0;L;;;;;N;;;;; 103C;MYANMAR CONSONANT SIGN MEDIAL RA;Mc;0;L;;;;;N;;;;; 103D;MYANMAR CONSONANT SIGN MEDIAL WA;Mn;0;NSM;;;;;N;;;;; 103E;MYANMAR CONSONANT SIGN MEDIAL HA;Mn;0;NSM;;;;;N;;;;; 103F;MYANMAR LETTER GREAT SA;Lo;0;L;;;;;N;;;;; 1040;MYANMAR DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 1041;MYANMAR DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 1042;MYANMAR DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 1043;MYANMAR DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 1044;MYANMAR DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 1045;MYANMAR DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 1046;MYANMAR DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 1047;MYANMAR DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 1048;MYANMAR DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 1049;MYANMAR DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 104A;MYANMAR SIGN LITTLE SECTION;Po;0;L;;;;;N;;;;; 104B;MYANMAR SIGN SECTION;Po;0;L;;;;;N;;;;; 104C;MYANMAR SYMBOL LOCATIVE;Po;0;L;;;;;N;;;;; 104D;MYANMAR SYMBOL COMPLETED;Po;0;L;;;;;N;;;;; 104E;MYANMAR SYMBOL AFOREMENTIONED;Po;0;L;;;;;N;;;;; 104F;MYANMAR SYMBOL GENITIVE;Po;0;L;;;;;N;;;;; 1050;MYANMAR LETTER SHA;Lo;0;L;;;;;N;;;;; 1051;MYANMAR LETTER SSA;Lo;0;L;;;;;N;;;;; 1052;MYANMAR LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; 1053;MYANMAR LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; 1054;MYANMAR LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; 1055;MYANMAR LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; 1056;MYANMAR VOWEL SIGN VOCALIC R;Mc;0;L;;;;;N;;;;; 1057;MYANMAR VOWEL SIGN VOCALIC RR;Mc;0;L;;;;;N;;;;; 1058;MYANMAR VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; 1059;MYANMAR VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; 105A;MYANMAR LETTER MON NGA;Lo;0;L;;;;;N;;;;; 105B;MYANMAR LETTER MON JHA;Lo;0;L;;;;;N;;;;; 105C;MYANMAR LETTER MON BBA;Lo;0;L;;;;;N;;;;; 105D;MYANMAR LETTER MON BBE;Lo;0;L;;;;;N;;;;; 105E;MYANMAR CONSONANT SIGN MON MEDIAL NA;Mn;0;NSM;;;;;N;;;;; 105F;MYANMAR CONSONANT SIGN MON MEDIAL MA;Mn;0;NSM;;;;;N;;;;; 1060;MYANMAR CONSONANT SIGN MON MEDIAL LA;Mn;0;NSM;;;;;N;;;;; 1061;MYANMAR LETTER SGAW KAREN SHA;Lo;0;L;;;;;N;;;;; 1062;MYANMAR VOWEL SIGN SGAW KAREN EU;Mc;0;L;;;;;N;;;;; 1063;MYANMAR TONE MARK SGAW KAREN HATHI;Mc;0;L;;;;;N;;;;; 1064;MYANMAR TONE MARK SGAW KAREN KE PHO;Mc;0;L;;;;;N;;;;; 1065;MYANMAR LETTER WESTERN PWO KAREN THA;Lo;0;L;;;;;N;;;;; 1066;MYANMAR LETTER WESTERN PWO KAREN PWA;Lo;0;L;;;;;N;;;;; 1067;MYANMAR VOWEL SIGN WESTERN PWO KAREN EU;Mc;0;L;;;;;N;;;;; 1068;MYANMAR VOWEL SIGN WESTERN PWO KAREN UE;Mc;0;L;;;;;N;;;;; 1069;MYANMAR SIGN WESTERN PWO KAREN TONE-1;Mc;0;L;;;;;N;;;;; 106A;MYANMAR SIGN WESTERN PWO KAREN TONE-2;Mc;0;L;;;;;N;;;;; 106B;MYANMAR SIGN WESTERN PWO KAREN TONE-3;Mc;0;L;;;;;N;;;;; 106C;MYANMAR SIGN WESTERN PWO KAREN TONE-4;Mc;0;L;;;;;N;;;;; 106D;MYANMAR SIGN WESTERN PWO KAREN TONE-5;Mc;0;L;;;;;N;;;;; 106E;MYANMAR LETTER EASTERN PWO KAREN NNA;Lo;0;L;;;;;N;;;;; 106F;MYANMAR LETTER EASTERN PWO KAREN YWA;Lo;0;L;;;;;N;;;;; 1070;MYANMAR LETTER EASTERN PWO KAREN GHWA;Lo;0;L;;;;;N;;;;; 1071;MYANMAR VOWEL SIGN GEBA KAREN I;Mn;0;NSM;;;;;N;;;;; 1072;MYANMAR VOWEL SIGN KAYAH OE;Mn;0;NSM;;;;;N;;;;; 1073;MYANMAR VOWEL SIGN KAYAH U;Mn;0;NSM;;;;;N;;;;; 1074;MYANMAR VOWEL SIGN KAYAH EE;Mn;0;NSM;;;;;N;;;;; 1075;MYANMAR LETTER SHAN KA;Lo;0;L;;;;;N;;;;; 1076;MYANMAR LETTER SHAN KHA;Lo;0;L;;;;;N;;;;; 1077;MYANMAR LETTER SHAN GA;Lo;0;L;;;;;N;;;;; 1078;MYANMAR LETTER SHAN CA;Lo;0;L;;;;;N;;;;; 1079;MYANMAR LETTER SHAN ZA;Lo;0;L;;;;;N;;;;; 107A;MYANMAR LETTER SHAN NYA;Lo;0;L;;;;;N;;;;; 107B;MYANMAR LETTER SHAN DA;Lo;0;L;;;;;N;;;;; 107C;MYANMAR LETTER SHAN NA;Lo;0;L;;;;;N;;;;; 107D;MYANMAR LETTER SHAN PHA;Lo;0;L;;;;;N;;;;; 107E;MYANMAR LETTER SHAN FA;Lo;0;L;;;;;N;;;;; 107F;MYANMAR LETTER SHAN BA;Lo;0;L;;;;;N;;;;; 1080;MYANMAR LETTER SHAN THA;Lo;0;L;;;;;N;;;;; 1081;MYANMAR LETTER SHAN HA;Lo;0;L;;;;;N;;;;; 1082;MYANMAR CONSONANT SIGN SHAN MEDIAL WA;Mn;0;NSM;;;;;N;;;;; 1083;MYANMAR VOWEL SIGN SHAN AA;Mc;0;L;;;;;N;;;;; 1084;MYANMAR VOWEL SIGN SHAN E;Mc;0;L;;;;;N;;;;; 1085;MYANMAR VOWEL SIGN SHAN E ABOVE;Mn;0;NSM;;;;;N;;;;; 1086;MYANMAR VOWEL SIGN SHAN FINAL Y;Mn;0;NSM;;;;;N;;;;; 1087;MYANMAR SIGN SHAN TONE-2;Mc;0;L;;;;;N;;;;; 1088;MYANMAR SIGN SHAN TONE-3;Mc;0;L;;;;;N;;;;; 1089;MYANMAR SIGN SHAN TONE-5;Mc;0;L;;;;;N;;;;; 108A;MYANMAR SIGN SHAN TONE-6;Mc;0;L;;;;;N;;;;; 108B;MYANMAR SIGN SHAN COUNCIL TONE-2;Mc;0;L;;;;;N;;;;; 108C;MYANMAR SIGN SHAN COUNCIL TONE-3;Mc;0;L;;;;;N;;;;; 108D;MYANMAR SIGN SHAN COUNCIL EMPHATIC TONE;Mn;220;NSM;;;;;N;;;;; 108E;MYANMAR LETTER RUMAI PALAUNG FA;Lo;0;L;;;;;N;;;;; 108F;MYANMAR SIGN RUMAI PALAUNG TONE-5;Mc;0;L;;;;;N;;;;; 1090;MYANMAR SHAN DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 1091;MYANMAR SHAN DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 1092;MYANMAR SHAN DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 1093;MYANMAR SHAN DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 1094;MYANMAR SHAN DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 1095;MYANMAR SHAN DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 1096;MYANMAR SHAN DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 1097;MYANMAR SHAN DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 1098;MYANMAR SHAN DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 1099;MYANMAR SHAN DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 109A;MYANMAR SIGN KHAMTI TONE-1;Mc;0;L;;;;;N;;;;; 109B;MYANMAR SIGN KHAMTI TONE-3;Mc;0;L;;;;;N;;;;; 109C;MYANMAR VOWEL SIGN AITON A;Mc;0;L;;;;;N;;;;; 109D;MYANMAR VOWEL SIGN AITON AI;Mn;0;NSM;;;;;N;;;;; 109E;MYANMAR SYMBOL SHAN ONE;So;0;L;;;;;N;;;;; 109F;MYANMAR SYMBOL SHAN EXCLAMATION;So;0;L;;;;;N;;;;; 10A0;GEORGIAN CAPITAL LETTER AN;Lu;0;L;;;;;N;;;;2D00; 10A1;GEORGIAN CAPITAL LETTER BAN;Lu;0;L;;;;;N;;;;2D01; 10A2;GEORGIAN CAPITAL LETTER GAN;Lu;0;L;;;;;N;;;;2D02; 10A3;GEORGIAN CAPITAL LETTER DON;Lu;0;L;;;;;N;;;;2D03; 10A4;GEORGIAN CAPITAL LETTER EN;Lu;0;L;;;;;N;;;;2D04; 10A5;GEORGIAN CAPITAL LETTER VIN;Lu;0;L;;;;;N;;;;2D05; 10A6;GEORGIAN CAPITAL LETTER ZEN;Lu;0;L;;;;;N;;;;2D06; 10A7;GEORGIAN CAPITAL LETTER TAN;Lu;0;L;;;;;N;;;;2D07; 10A8;GEORGIAN CAPITAL LETTER IN;Lu;0;L;;;;;N;;;;2D08; 10A9;GEORGIAN CAPITAL LETTER KAN;Lu;0;L;;;;;N;;;;2D09; 10AA;GEORGIAN CAPITAL LETTER LAS;Lu;0;L;;;;;N;;;;2D0A; 10AB;GEORGIAN CAPITAL LETTER MAN;Lu;0;L;;;;;N;;;;2D0B; 10AC;GEORGIAN CAPITAL LETTER NAR;Lu;0;L;;;;;N;;;;2D0C; 10AD;GEORGIAN CAPITAL LETTER ON;Lu;0;L;;;;;N;;;;2D0D; 10AE;GEORGIAN CAPITAL LETTER PAR;Lu;0;L;;;;;N;;;;2D0E; 10AF;GEORGIAN CAPITAL LETTER ZHAR;Lu;0;L;;;;;N;;;;2D0F; 10B0;GEORGIAN CAPITAL LETTER RAE;Lu;0;L;;;;;N;;;;2D10; 10B1;GEORGIAN CAPITAL LETTER SAN;Lu;0;L;;;;;N;;;;2D11; 10B2;GEORGIAN CAPITAL LETTER TAR;Lu;0;L;;;;;N;;;;2D12; 10B3;GEORGIAN CAPITAL LETTER UN;Lu;0;L;;;;;N;;;;2D13; 10B4;GEORGIAN CAPITAL LETTER PHAR;Lu;0;L;;;;;N;;;;2D14; 10B5;GEORGIAN CAPITAL LETTER KHAR;Lu;0;L;;;;;N;;;;2D15; 10B6;GEORGIAN CAPITAL LETTER GHAN;Lu;0;L;;;;;N;;;;2D16; 10B7;GEORGIAN CAPITAL LETTER QAR;Lu;0;L;;;;;N;;;;2D17; 10B8;GEORGIAN CAPITAL LETTER SHIN;Lu;0;L;;;;;N;;;;2D18; 10B9;GEORGIAN CAPITAL LETTER CHIN;Lu;0;L;;;;;N;;;;2D19; 10BA;GEORGIAN CAPITAL LETTER CAN;Lu;0;L;;;;;N;;;;2D1A; 10BB;GEORGIAN CAPITAL LETTER JIL;Lu;0;L;;;;;N;;;;2D1B; 10BC;GEORGIAN CAPITAL LETTER CIL;Lu;0;L;;;;;N;;;;2D1C; 10BD;GEORGIAN CAPITAL LETTER CHAR;Lu;0;L;;;;;N;;;;2D1D; 10BE;GEORGIAN CAPITAL LETTER XAN;Lu;0;L;;;;;N;;;;2D1E; 10BF;GEORGIAN CAPITAL LETTER JHAN;Lu;0;L;;;;;N;;;;2D1F; 10C0;GEORGIAN CAPITAL LETTER HAE;Lu;0;L;;;;;N;;;;2D20; 10C1;GEORGIAN CAPITAL LETTER HE;Lu;0;L;;;;;N;;;;2D21; 10C2;GEORGIAN CAPITAL LETTER HIE;Lu;0;L;;;;;N;;;;2D22; 10C3;GEORGIAN CAPITAL LETTER WE;Lu;0;L;;;;;N;;;;2D23; 10C4;GEORGIAN CAPITAL LETTER HAR;Lu;0;L;;;;;N;;;;2D24; 10C5;GEORGIAN CAPITAL LETTER HOE;Lu;0;L;;;;;N;;;;2D25; 10C7;GEORGIAN CAPITAL LETTER YN;Lu;0;L;;;;;N;;;;2D27; 10CD;GEORGIAN CAPITAL LETTER AEN;Lu;0;L;;;;;N;;;;2D2D; 10D0;GEORGIAN LETTER AN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER AN;;;; 10D1;GEORGIAN LETTER BAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER BAN;;;; 10D2;GEORGIAN LETTER GAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER GAN;;;; 10D3;GEORGIAN LETTER DON;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER DON;;;; 10D4;GEORGIAN LETTER EN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER EN;;;; 10D5;GEORGIAN LETTER VIN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER VIN;;;; 10D6;GEORGIAN LETTER ZEN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER ZEN;;;; 10D7;GEORGIAN LETTER TAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER TAN;;;; 10D8;GEORGIAN LETTER IN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER IN;;;; 10D9;GEORGIAN LETTER KAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER KAN;;;; 10DA;GEORGIAN LETTER LAS;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER LAS;;;; 10DB;GEORGIAN LETTER MAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER MAN;;;; 10DC;GEORGIAN LETTER NAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER NAR;;;; 10DD;GEORGIAN LETTER ON;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER ON;;;; 10DE;GEORGIAN LETTER PAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER PAR;;;; 10DF;GEORGIAN LETTER ZHAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER ZHAR;;;; 10E0;GEORGIAN LETTER RAE;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER RAE;;;; 10E1;GEORGIAN LETTER SAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER SAN;;;; 10E2;GEORGIAN LETTER TAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER TAR;;;; 10E3;GEORGIAN LETTER UN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER UN;;;; 10E4;GEORGIAN LETTER PHAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER PHAR;;;; 10E5;GEORGIAN LETTER KHAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER KHAR;;;; 10E6;GEORGIAN LETTER GHAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER GHAN;;;; 10E7;GEORGIAN LETTER QAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER QAR;;;; 10E8;GEORGIAN LETTER SHIN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER SHIN;;;; 10E9;GEORGIAN LETTER CHIN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER CHIN;;;; 10EA;GEORGIAN LETTER CAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER CAN;;;; 10EB;GEORGIAN LETTER JIL;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER JIL;;;; 10EC;GEORGIAN LETTER CIL;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER CIL;;;; 10ED;GEORGIAN LETTER CHAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER CHAR;;;; 10EE;GEORGIAN LETTER XAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER XAN;;;; 10EF;GEORGIAN LETTER JHAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER JHAN;;;; 10F0;GEORGIAN LETTER HAE;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER HAE;;;; 10F1;GEORGIAN LETTER HE;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER HE;;;; 10F2;GEORGIAN LETTER HIE;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER HIE;;;; 10F3;GEORGIAN LETTER WE;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER WE;;;; 10F4;GEORGIAN LETTER HAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER HAR;;;; 10F5;GEORGIAN LETTER HOE;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER HOE;;;; 10F6;GEORGIAN LETTER FI;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER FI;;;; 10F7;GEORGIAN LETTER YN;Lo;0;L;;;;;N;;;;; 10F8;GEORGIAN LETTER ELIFI;Lo;0;L;;;;;N;;;;; 10F9;GEORGIAN LETTER TURNED GAN;Lo;0;L;;;;;N;;;;; 10FA;GEORGIAN LETTER AIN;Lo;0;L;;;;;N;;;;; 10FB;GEORGIAN PARAGRAPH SEPARATOR;Po;0;L;;;;;N;;;;; 10FC;MODIFIER LETTER GEORGIAN NAR;Lm;0;L;<super> 10DC;;;;N;;;;; 10FD;GEORGIAN LETTER AEN;Lo;0;L;;;;;N;;;;; 10FE;GEORGIAN LETTER HARD SIGN;Lo;0;L;;;;;N;;;;; 10FF;GEORGIAN LETTER LABIAL SIGN;Lo;0;L;;;;;N;;;;; 1100;HANGUL CHOSEONG KIYEOK;Lo;0;L;;;;;N;;;;; 1101;HANGUL CHOSEONG SSANGKIYEOK;Lo;0;L;;;;;N;;;;; 1102;HANGUL CHOSEONG NIEUN;Lo;0;L;;;;;N;;;;; 1103;HANGUL CHOSEONG TIKEUT;Lo;0;L;;;;;N;;;;; 1104;HANGUL CHOSEONG SSANGTIKEUT;Lo;0;L;;;;;N;;;;; 1105;HANGUL CHOSEONG RIEUL;Lo;0;L;;;;;N;;;;; 1106;HANGUL CHOSEONG MIEUM;Lo;0;L;;;;;N;;;;; 1107;HANGUL CHOSEONG PIEUP;Lo;0;L;;;;;N;;;;; 1108;HANGUL CHOSEONG SSANGPIEUP;Lo;0;L;;;;;N;;;;; 1109;HANGUL CHOSEONG SIOS;Lo;0;L;;;;;N;;;;; 110A;HANGUL CHOSEONG SSANGSIOS;Lo;0;L;;;;;N;;;;; 110B;HANGUL CHOSEONG IEUNG;Lo;0;L;;;;;N;;;;; 110C;HANGUL CHOSEONG CIEUC;Lo;0;L;;;;;N;;;;; 110D;HANGUL CHOSEONG SSANGCIEUC;Lo;0;L;;;;;N;;;;; 110E;HANGUL CHOSEONG CHIEUCH;Lo;0;L;;;;;N;;;;; 110F;HANGUL CHOSEONG KHIEUKH;Lo;0;L;;;;;N;;;;; 1110;HANGUL CHOSEONG THIEUTH;Lo;0;L;;;;;N;;;;; 1111;HANGUL CHOSEONG PHIEUPH;Lo;0;L;;;;;N;;;;; 1112;HANGUL CHOSEONG HIEUH;Lo;0;L;;;;;N;;;;; 1113;HANGUL CHOSEONG NIEUN-KIYEOK;Lo;0;L;;;;;N;;;;; 1114;HANGUL CHOSEONG SSANGNIEUN;Lo;0;L;;;;;N;;;;; 1115;HANGUL CHOSEONG NIEUN-TIKEUT;Lo;0;L;;;;;N;;;;; 1116;HANGUL CHOSEONG NIEUN-PIEUP;Lo;0;L;;;;;N;;;;; 1117;HANGUL CHOSEONG TIKEUT-KIYEOK;Lo;0;L;;;;;N;;;;; 1118;HANGUL CHOSEONG RIEUL-NIEUN;Lo;0;L;;;;;N;;;;; 1119;HANGUL CHOSEONG SSANGRIEUL;Lo;0;L;;;;;N;;;;; 111A;HANGUL CHOSEONG RIEUL-HIEUH;Lo;0;L;;;;;N;;;;; 111B;HANGUL CHOSEONG KAPYEOUNRIEUL;Lo;0;L;;;;;N;;;;; 111C;HANGUL CHOSEONG MIEUM-PIEUP;Lo;0;L;;;;;N;;;;; 111D;HANGUL CHOSEONG KAPYEOUNMIEUM;Lo;0;L;;;;;N;;;;; 111E;HANGUL CHOSEONG PIEUP-KIYEOK;Lo;0;L;;;;;N;;;;; 111F;HANGUL CHOSEONG PIEUP-NIEUN;Lo;0;L;;;;;N;;;;; 1120;HANGUL CHOSEONG PIEUP-TIKEUT;Lo;0;L;;;;;N;;;;; 1121;HANGUL CHOSEONG PIEUP-SIOS;Lo;0;L;;;;;N;;;;; 1122;HANGUL CHOSEONG PIEUP-SIOS-KIYEOK;Lo;0;L;;;;;N;;;;; 1123;HANGUL CHOSEONG PIEUP-SIOS-TIKEUT;Lo;0;L;;;;;N;;;;; 1124;HANGUL CHOSEONG PIEUP-SIOS-PIEUP;Lo;0;L;;;;;N;;;;; 1125;HANGUL CHOSEONG PIEUP-SSANGSIOS;Lo;0;L;;;;;N;;;;; 1126;HANGUL CHOSEONG PIEUP-SIOS-CIEUC;Lo;0;L;;;;;N;;;;; 1127;HANGUL CHOSEONG PIEUP-CIEUC;Lo;0;L;;;;;N;;;;; 1128;HANGUL CHOSEONG PIEUP-CHIEUCH;Lo;0;L;;;;;N;;;;; 1129;HANGUL CHOSEONG PIEUP-THIEUTH;Lo;0;L;;;;;N;;;;; 112A;HANGUL CHOSEONG PIEUP-PHIEUPH;Lo;0;L;;;;;N;;;;; 112B;HANGUL CHOSEONG KAPYEOUNPIEUP;Lo;0;L;;;;;N;;;;; 112C;HANGUL CHOSEONG KAPYEOUNSSANGPIEUP;Lo;0;L;;;;;N;;;;; 112D;HANGUL CHOSEONG SIOS-KIYEOK;Lo;0;L;;;;;N;;;;; 112E;HANGUL CHOSEONG SIOS-NIEUN;Lo;0;L;;;;;N;;;;; 112F;HANGUL CHOSEONG SIOS-TIKEUT;Lo;0;L;;;;;N;;;;; 1130;HANGUL CHOSEONG SIOS-RIEUL;Lo;0;L;;;;;N;;;;; 1131;HANGUL CHOSEONG SIOS-MIEUM;Lo;0;L;;;;;N;;;;; 1132;HANGUL CHOSEONG SIOS-PIEUP;Lo;0;L;;;;;N;;;;; 1133;HANGUL CHOSEONG SIOS-PIEUP-KIYEOK;Lo;0;L;;;;;N;;;;; 1134;HANGUL CHOSEONG SIOS-SSANGSIOS;Lo;0;L;;;;;N;;;;; 1135;HANGUL CHOSEONG SIOS-IEUNG;Lo;0;L;;;;;N;;;;; 1136;HANGUL CHOSEONG SIOS-CIEUC;Lo;0;L;;;;;N;;;;; 1137;HANGUL CHOSEONG SIOS-CHIEUCH;Lo;0;L;;;;;N;;;;; 1138;HANGUL CHOSEONG SIOS-KHIEUKH;Lo;0;L;;;;;N;;;;; 1139;HANGUL CHOSEONG SIOS-THIEUTH;Lo;0;L;;;;;N;;;;; 113A;HANGUL CHOSEONG SIOS-PHIEUPH;Lo;0;L;;;;;N;;;;; 113B;HANGUL CHOSEONG SIOS-HIEUH;Lo;0;L;;;;;N;;;;; 113C;HANGUL CHOSEONG CHITUEUMSIOS;Lo;0;L;;;;;N;;;;; 113D;HANGUL CHOSEONG CHITUEUMSSANGSIOS;Lo;0;L;;;;;N;;;;; 113E;HANGUL CHOSEONG CEONGCHIEUMSIOS;Lo;0;L;;;;;N;;;;; 113F;HANGUL CHOSEONG CEONGCHIEUMSSANGSIOS;Lo;0;L;;;;;N;;;;; 1140;HANGUL CHOSEONG PANSIOS;Lo;0;L;;;;;N;;;;; 1141;HANGUL CHOSEONG IEUNG-KIYEOK;Lo;0;L;;;;;N;;;;; 1142;HANGUL CHOSEONG IEUNG-TIKEUT;Lo;0;L;;;;;N;;;;; 1143;HANGUL CHOSEONG IEUNG-MIEUM;Lo;0;L;;;;;N;;;;; 1144;HANGUL CHOSEONG IEUNG-PIEUP;Lo;0;L;;;;;N;;;;; 1145;HANGUL CHOSEONG IEUNG-SIOS;Lo;0;L;;;;;N;;;;; 1146;HANGUL CHOSEONG IEUNG-PANSIOS;Lo;0;L;;;;;N;;;;; 1147;HANGUL CHOSEONG SSANGIEUNG;Lo;0;L;;;;;N;;;;; 1148;HANGUL CHOSEONG IEUNG-CIEUC;Lo;0;L;;;;;N;;;;; 1149;HANGUL CHOSEONG IEUNG-CHIEUCH;Lo;0;L;;;;;N;;;;; 114A;HANGUL CHOSEONG IEUNG-THIEUTH;Lo;0;L;;;;;N;;;;; 114B;HANGUL CHOSEONG IEUNG-PHIEUPH;Lo;0;L;;;;;N;;;;; 114C;HANGUL CHOSEONG YESIEUNG;Lo;0;L;;;;;N;;;;; 114D;HANGUL CHOSEONG CIEUC-IEUNG;Lo;0;L;;;;;N;;;;; 114E;HANGUL CHOSEONG CHITUEUMCIEUC;Lo;0;L;;;;;N;;;;; 114F;HANGUL CHOSEONG CHITUEUMSSANGCIEUC;Lo;0;L;;;;;N;;;;; 1150;HANGUL CHOSEONG CEONGCHIEUMCIEUC;Lo;0;L;;;;;N;;;;; 1151;HANGUL CHOSEONG CEONGCHIEUMSSANGCIEUC;Lo;0;L;;;;;N;;;;; 1152;HANGUL CHOSEONG CHIEUCH-KHIEUKH;Lo;0;L;;;;;N;;;;; 1153;HANGUL CHOSEONG CHIEUCH-HIEUH;Lo;0;L;;;;;N;;;;; 1154;HANGUL CHOSEONG CHITUEUMCHIEUCH;Lo;0;L;;;;;N;;;;; 1155;HANGUL CHOSEONG CEONGCHIEUMCHIEUCH;Lo;0;L;;;;;N;;;;; 1156;HANGUL CHOSEONG PHIEUPH-PIEUP;Lo;0;L;;;;;N;;;;; 1157;HANGUL CHOSEONG KAPYEOUNPHIEUPH;Lo;0;L;;;;;N;;;;; 1158;HANGUL CHOSEONG SSANGHIEUH;Lo;0;L;;;;;N;;;;; 1159;HANGUL CHOSEONG YEORINHIEUH;Lo;0;L;;;;;N;;;;; 115A;HANGUL CHOSEONG KIYEOK-TIKEUT;Lo;0;L;;;;;N;;;;; 115B;HANGUL CHOSEONG NIEUN-SIOS;Lo;0;L;;;;;N;;;;; 115C;HANGUL CHOSEONG NIEUN-CIEUC;Lo;0;L;;;;;N;;;;; 115D;HANGUL CHOSEONG NIEUN-HIEUH;Lo;0;L;;;;;N;;;;; 115E;HANGUL CHOSEONG TIKEUT-RIEUL;Lo;0;L;;;;;N;;;;; 115F;HANGUL CHOSEONG FILLER;Lo;0;L;;;;;N;;;;; 1160;HANGUL JUNGSEONG FILLER;Lo;0;L;;;;;N;;;;; 1161;HANGUL JUNGSEONG A;Lo;0;L;;;;;N;;;;; 1162;HANGUL JUNGSEONG AE;Lo;0;L;;;;;N;;;;; 1163;HANGUL JUNGSEONG YA;Lo;0;L;;;;;N;;;;; 1164;HANGUL JUNGSEONG YAE;Lo;0;L;;;;;N;;;;; 1165;HANGUL JUNGSEONG EO;Lo;0;L;;;;;N;;;;; 1166;HANGUL JUNGSEONG E;Lo;0;L;;;;;N;;;;; 1167;HANGUL JUNGSEONG YEO;Lo;0;L;;;;;N;;;;; 1168;HANGUL JUNGSEONG YE;Lo;0;L;;;;;N;;;;; 1169;HANGUL JUNGSEONG O;Lo;0;L;;;;;N;;;;; 116A;HANGUL JUNGSEONG WA;Lo;0;L;;;;;N;;;;; 116B;HANGUL JUNGSEONG WAE;Lo;0;L;;;;;N;;;;; 116C;HANGUL JUNGSEONG OE;Lo;0;L;;;;;N;;;;; 116D;HANGUL JUNGSEONG YO;Lo;0;L;;;;;N;;;;; 116E;HANGUL JUNGSEONG U;Lo;0;L;;;;;N;;;;; 116F;HANGUL JUNGSEONG WEO;Lo;0;L;;;;;N;;;;; 1170;HANGUL JUNGSEONG WE;Lo;0;L;;;;;N;;;;; 1171;HANGUL JUNGSEONG WI;Lo;0;L;;;;;N;;;;; 1172;HANGUL JUNGSEONG YU;Lo;0;L;;;;;N;;;;; 1173;HANGUL JUNGSEONG EU;Lo;0;L;;;;;N;;;;; 1174;HANGUL JUNGSEONG YI;Lo;0;L;;;;;N;;;;; 1175;HANGUL JUNGSEONG I;Lo;0;L;;;;;N;;;;; 1176;HANGUL JUNGSEONG A-O;Lo;0;L;;;;;N;;;;; 1177;HANGUL JUNGSEONG A-U;Lo;0;L;;;;;N;;;;; 1178;HANGUL JUNGSEONG YA-O;Lo;0;L;;;;;N;;;;; 1179;HANGUL JUNGSEONG YA-YO;Lo;0;L;;;;;N;;;;; 117A;HANGUL JUNGSEONG EO-O;Lo;0;L;;;;;N;;;;; 117B;HANGUL JUNGSEONG EO-U;Lo;0;L;;;;;N;;;;; 117C;HANGUL JUNGSEONG EO-EU;Lo;0;L;;;;;N;;;;; 117D;HANGUL JUNGSEONG YEO-O;Lo;0;L;;;;;N;;;;; 117E;HANGUL JUNGSEONG YEO-U;Lo;0;L;;;;;N;;;;; 117F;HANGUL JUNGSEONG O-EO;Lo;0;L;;;;;N;;;;; 1180;HANGUL JUNGSEONG O-E;Lo;0;L;;;;;N;;;;; 1181;HANGUL JUNGSEONG O-YE;Lo;0;L;;;;;N;;;;; 1182;HANGUL JUNGSEONG O-O;Lo;0;L;;;;;N;;;;; 1183;HANGUL JUNGSEONG O-U;Lo;0;L;;;;;N;;;;; 1184;HANGUL JUNGSEONG YO-YA;Lo;0;L;;;;;N;;;;; 1185;HANGUL JUNGSEONG YO-YAE;Lo;0;L;;;;;N;;;;; 1186;HANGUL JUNGSEONG YO-YEO;Lo;0;L;;;;;N;;;;; 1187;HANGUL JUNGSEONG YO-O;Lo;0;L;;;;;N;;;;; 1188;HANGUL JUNGSEONG YO-I;Lo;0;L;;;;;N;;;;; 1189;HANGUL JUNGSEONG U-A;Lo;0;L;;;;;N;;;;; 118A;HANGUL JUNGSEONG U-AE;Lo;0;L;;;;;N;;;;; 118B;HANGUL JUNGSEONG U-EO-EU;Lo;0;L;;;;;N;;;;; 118C;HANGUL JUNGSEONG U-YE;Lo;0;L;;;;;N;;;;; 118D;HANGUL JUNGSEONG U-U;Lo;0;L;;;;;N;;;;; 118E;HANGUL JUNGSEONG YU-A;Lo;0;L;;;;;N;;;;; 118F;HANGUL JUNGSEONG YU-EO;Lo;0;L;;;;;N;;;;; 1190;HANGUL JUNGSEONG YU-E;Lo;0;L;;;;;N;;;;; 1191;HANGUL JUNGSEONG YU-YEO;Lo;0;L;;;;;N;;;;; 1192;HANGUL JUNGSEONG YU-YE;Lo;0;L;;;;;N;;;;; 1193;HANGUL JUNGSEONG YU-U;Lo;0;L;;;;;N;;;;; 1194;HANGUL JUNGSEONG YU-I;Lo;0;L;;;;;N;;;;; 1195;HANGUL JUNGSEONG EU-U;Lo;0;L;;;;;N;;;;; 1196;HANGUL JUNGSEONG EU-EU;Lo;0;L;;;;;N;;;;; 1197;HANGUL JUNGSEONG YI-U;Lo;0;L;;;;;N;;;;; 1198;HANGUL JUNGSEONG I-A;Lo;0;L;;;;;N;;;;; 1199;HANGUL JUNGSEONG I-YA;Lo;0;L;;;;;N;;;;; 119A;HANGUL JUNGSEONG I-O;Lo;0;L;;;;;N;;;;; 119B;HANGUL JUNGSEONG I-U;Lo;0;L;;;;;N;;;;; 119C;HANGUL JUNGSEONG I-EU;Lo;0;L;;;;;N;;;;; 119D;HANGUL JUNGSEONG I-ARAEA;Lo;0;L;;;;;N;;;;; 119E;HANGUL JUNGSEONG ARAEA;Lo;0;L;;;;;N;;;;; 119F;HANGUL JUNGSEONG ARAEA-EO;Lo;0;L;;;;;N;;;;; 11A0;HANGUL JUNGSEONG ARAEA-U;Lo;0;L;;;;;N;;;;; 11A1;HANGUL JUNGSEONG ARAEA-I;Lo;0;L;;;;;N;;;;; 11A2;HANGUL JUNGSEONG SSANGARAEA;Lo;0;L;;;;;N;;;;; 11A3;HANGUL JUNGSEONG A-EU;Lo;0;L;;;;;N;;;;; 11A4;HANGUL JUNGSEONG YA-U;Lo;0;L;;;;;N;;;;; 11A5;HANGUL JUNGSEONG YEO-YA;Lo;0;L;;;;;N;;;;; 11A6;HANGUL JUNGSEONG O-YA;Lo;0;L;;;;;N;;;;; 11A7;HANGUL JUNGSEONG O-YAE;Lo;0;L;;;;;N;;;;; 11A8;HANGUL JONGSEONG KIYEOK;Lo;0;L;;;;;N;;;;; 11A9;HANGUL JONGSEONG SSANGKIYEOK;Lo;0;L;;;;;N;;;;; 11AA;HANGUL JONGSEONG KIYEOK-SIOS;Lo;0;L;;;;;N;;;;; 11AB;HANGUL JONGSEONG NIEUN;Lo;0;L;;;;;N;;;;; 11AC;HANGUL JONGSEONG NIEUN-CIEUC;Lo;0;L;;;;;N;;;;; 11AD;HANGUL JONGSEONG NIEUN-HIEUH;Lo;0;L;;;;;N;;;;; 11AE;HANGUL JONGSEONG TIKEUT;Lo;0;L;;;;;N;;;;; 11AF;HANGUL JONGSEONG RIEUL;Lo;0;L;;;;;N;;;;; 11B0;HANGUL JONGSEONG RIEUL-KIYEOK;Lo;0;L;;;;;N;;;;; 11B1;HANGUL JONGSEONG RIEUL-MIEUM;Lo;0;L;;;;;N;;;;; 11B2;HANGUL JONGSEONG RIEUL-PIEUP;Lo;0;L;;;;;N;;;;; 11B3;HANGUL JONGSEONG RIEUL-SIOS;Lo;0;L;;;;;N;;;;; 11B4;HANGUL JONGSEONG RIEUL-THIEUTH;Lo;0;L;;;;;N;;;;; 11B5;HANGUL JONGSEONG RIEUL-PHIEUPH;Lo;0;L;;;;;N;;;;; 11B6;HANGUL JONGSEONG RIEUL-HIEUH;Lo;0;L;;;;;N;;;;; 11B7;HANGUL JONGSEONG MIEUM;Lo;0;L;;;;;N;;;;; 11B8;HANGUL JONGSEONG PIEUP;Lo;0;L;;;;;N;;;;; 11B9;HANGUL JONGSEONG PIEUP-SIOS;Lo;0;L;;;;;N;;;;; 11BA;HANGUL JONGSEONG SIOS;Lo;0;L;;;;;N;;;;; 11BB;HANGUL JONGSEONG SSANGSIOS;Lo;0;L;;;;;N;;;;; 11BC;HANGUL JONGSEONG IEUNG;Lo;0;L;;;;;N;;;;; 11BD;HANGUL JONGSEONG CIEUC;Lo;0;L;;;;;N;;;;; 11BE;HANGUL JONGSEONG CHIEUCH;Lo;0;L;;;;;N;;;;; 11BF;HANGUL JONGSEONG KHIEUKH;Lo;0;L;;;;;N;;;;; 11C0;HANGUL JONGSEONG THIEUTH;Lo;0;L;;;;;N;;;;; 11C1;HANGUL JONGSEONG PHIEUPH;Lo;0;L;;;;;N;;;;; 11C2;HANGUL JONGSEONG HIEUH;Lo;0;L;;;;;N;;;;; 11C3;HANGUL JONGSEONG KIYEOK-RIEUL;Lo;0;L;;;;;N;;;;; 11C4;HANGUL JONGSEONG KIYEOK-SIOS-KIYEOK;Lo;0;L;;;;;N;;;;; 11C5;HANGUL JONGSEONG NIEUN-KIYEOK;Lo;0;L;;;;;N;;;;; 11C6;HANGUL JONGSEONG NIEUN-TIKEUT;Lo;0;L;;;;;N;;;;; 11C7;HANGUL JONGSEONG NIEUN-SIOS;Lo;0;L;;;;;N;;;;; 11C8;HANGUL JONGSEONG NIEUN-PANSIOS;Lo;0;L;;;;;N;;;;; 11C9;HANGUL JONGSEONG NIEUN-THIEUTH;Lo;0;L;;;;;N;;;;; 11CA;HANGUL JONGSEONG TIKEUT-KIYEOK;Lo;0;L;;;;;N;;;;; 11CB;HANGUL JONGSEONG TIKEUT-RIEUL;Lo;0;L;;;;;N;;;;; 11CC;HANGUL JONGSEONG RIEUL-KIYEOK-SIOS;Lo;0;L;;;;;N;;;;; 11CD;HANGUL JONGSEONG RIEUL-NIEUN;Lo;0;L;;;;;N;;;;; 11CE;HANGUL JONGSEONG RIEUL-TIKEUT;Lo;0;L;;;;;N;;;;; 11CF;HANGUL JONGSEONG RIEUL-TIKEUT-HIEUH;Lo;0;L;;;;;N;;;;; 11D0;HANGUL JONGSEONG SSANGRIEUL;Lo;0;L;;;;;N;;;;; 11D1;HANGUL JONGSEONG RIEUL-MIEUM-KIYEOK;Lo;0;L;;;;;N;;;;; 11D2;HANGUL JONGSEONG RIEUL-MIEUM-SIOS;Lo;0;L;;;;;N;;;;; 11D3;HANGUL JONGSEONG RIEUL-PIEUP-SIOS;Lo;0;L;;;;;N;;;;; 11D4;HANGUL JONGSEONG RIEUL-PIEUP-HIEUH;Lo;0;L;;;;;N;;;;; 11D5;HANGUL JONGSEONG RIEUL-KAPYEOUNPIEUP;Lo;0;L;;;;;N;;;;; 11D6;HANGUL JONGSEONG RIEUL-SSANGSIOS;Lo;0;L;;;;;N;;;;; 11D7;HANGUL JONGSEONG RIEUL-PANSIOS;Lo;0;L;;;;;N;;;;; 11D8;HANGUL JONGSEONG RIEUL-KHIEUKH;Lo;0;L;;;;;N;;;;; 11D9;HANGUL JONGSEONG RIEUL-YEORINHIEUH;Lo;0;L;;;;;N;;;;; 11DA;HANGUL JONGSEONG MIEUM-KIYEOK;Lo;0;L;;;;;N;;;;; 11DB;HANGUL JONGSEONG MIEUM-RIEUL;Lo;0;L;;;;;N;;;;; 11DC;HANGUL JONGSEONG MIEUM-PIEUP;Lo;0;L;;;;;N;;;;; 11DD;HANGUL JONGSEONG MIEUM-SIOS;Lo;0;L;;;;;N;;;;; 11DE;HANGUL JONGSEONG MIEUM-SSANGSIOS;Lo;0;L;;;;;N;;;;; 11DF;HANGUL JONGSEONG MIEUM-PANSIOS;Lo;0;L;;;;;N;;;;; 11E0;HANGUL JONGSEONG MIEUM-CHIEUCH;Lo;0;L;;;;;N;;;;; 11E1;HANGUL JONGSEONG MIEUM-HIEUH;Lo;0;L;;;;;N;;;;; 11E2;HANGUL JONGSEONG KAPYEOUNMIEUM;Lo;0;L;;;;;N;;;;; 11E3;HANGUL JONGSEONG PIEUP-RIEUL;Lo;0;L;;;;;N;;;;; 11E4;HANGUL JONGSEONG PIEUP-PHIEUPH;Lo;0;L;;;;;N;;;;; 11E5;HANGUL JONGSEONG PIEUP-HIEUH;Lo;0;L;;;;;N;;;;; 11E6;HANGUL JONGSEONG KAPYEOUNPIEUP;Lo;0;L;;;;;N;;;;; 11E7;HANGUL JONGSEONG SIOS-KIYEOK;Lo;0;L;;;;;N;;;;; 11E8;HANGUL JONGSEONG SIOS-TIKEUT;Lo;0;L;;;;;N;;;;; 11E9;HANGUL JONGSEONG SIOS-RIEUL;Lo;0;L;;;;;N;;;;; 11EA;HANGUL JONGSEONG SIOS-PIEUP;Lo;0;L;;;;;N;;;;; 11EB;HANGUL JONGSEONG PANSIOS;Lo;0;L;;;;;N;;;;; 11EC;HANGUL JONGSEONG IEUNG-KIYEOK;Lo;0;L;;;;;N;;;;; 11ED;HANGUL JONGSEONG IEUNG-SSANGKIYEOK;Lo;0;L;;;;;N;;;;; 11EE;HANGUL JONGSEONG SSANGIEUNG;Lo;0;L;;;;;N;;;;; 11EF;HANGUL JONGSEONG IEUNG-KHIEUKH;Lo;0;L;;;;;N;;;;; 11F0;HANGUL JONGSEONG YESIEUNG;Lo;0;L;;;;;N;;;;; 11F1;HANGUL JONGSEONG YESIEUNG-SIOS;Lo;0;L;;;;;N;;;;; 11F2;HANGUL JONGSEONG YESIEUNG-PANSIOS;Lo;0;L;;;;;N;;;;; 11F3;HANGUL JONGSEONG PHIEUPH-PIEUP;Lo;0;L;;;;;N;;;;; 11F4;HANGUL JONGSEONG KAPYEOUNPHIEUPH;Lo;0;L;;;;;N;;;;; 11F5;HANGUL JONGSEONG HIEUH-NIEUN;Lo;0;L;;;;;N;;;;; 11F6;HANGUL JONGSEONG HIEUH-RIEUL;Lo;0;L;;;;;N;;;;; 11F7;HANGUL JONGSEONG HIEUH-MIEUM;Lo;0;L;;;;;N;;;;; 11F8;HANGUL JONGSEONG HIEUH-PIEUP;Lo;0;L;;;;;N;;;;; 11F9;HANGUL JONGSEONG YEORINHIEUH;Lo;0;L;;;;;N;;;;; 11FA;HANGUL JONGSEONG KIYEOK-NIEUN;Lo;0;L;;;;;N;;;;; 11FB;HANGUL JONGSEONG KIYEOK-PIEUP;Lo;0;L;;;;;N;;;;; 11FC;HANGUL JONGSEONG KIYEOK-CHIEUCH;Lo;0;L;;;;;N;;;;; 11FD;HANGUL JONGSEONG KIYEOK-KHIEUKH;Lo;0;L;;;;;N;;;;; 11FE;HANGUL JONGSEONG KIYEOK-HIEUH;Lo;0;L;;;;;N;;;;; 11FF;HANGUL JONGSEONG SSANGNIEUN;Lo;0;L;;;;;N;;;;; 1200;ETHIOPIC SYLLABLE HA;Lo;0;L;;;;;N;;;;; 1201;ETHIOPIC SYLLABLE HU;Lo;0;L;;;;;N;;;;; 1202;ETHIOPIC SYLLABLE HI;Lo;0;L;;;;;N;;;;; 1203;ETHIOPIC SYLLABLE HAA;Lo;0;L;;;;;N;;;;; 1204;ETHIOPIC SYLLABLE HEE;Lo;0;L;;;;;N;;;;; 1205;ETHIOPIC SYLLABLE HE;Lo;0;L;;;;;N;;;;; 1206;ETHIOPIC SYLLABLE HO;Lo;0;L;;;;;N;;;;; 1207;ETHIOPIC SYLLABLE HOA;Lo;0;L;;;;;N;;;;; 1208;ETHIOPIC SYLLABLE LA;Lo;0;L;;;;;N;;;;; 1209;ETHIOPIC SYLLABLE LU;Lo;0;L;;;;;N;;;;; 120A;ETHIOPIC SYLLABLE LI;Lo;0;L;;;;;N;;;;; 120B;ETHIOPIC SYLLABLE LAA;Lo;0;L;;;;;N;;;;; 120C;ETHIOPIC SYLLABLE LEE;Lo;0;L;;;;;N;;;;; 120D;ETHIOPIC SYLLABLE LE;Lo;0;L;;;;;N;;;;; 120E;ETHIOPIC SYLLABLE LO;Lo;0;L;;;;;N;;;;; 120F;ETHIOPIC SYLLABLE LWA;Lo;0;L;;;;;N;;;;; 1210;ETHIOPIC SYLLABLE HHA;Lo;0;L;;;;;N;;;;; 1211;ETHIOPIC SYLLABLE HHU;Lo;0;L;;;;;N;;;;; 1212;ETHIOPIC SYLLABLE HHI;Lo;0;L;;;;;N;;;;; 1213;ETHIOPIC SYLLABLE HHAA;Lo;0;L;;;;;N;;;;; 1214;ETHIOPIC SYLLABLE HHEE;Lo;0;L;;;;;N;;;;; 1215;ETHIOPIC SYLLABLE HHE;Lo;0;L;;;;;N;;;;; 1216;ETHIOPIC SYLLABLE HHO;Lo;0;L;;;;;N;;;;; 1217;ETHIOPIC SYLLABLE HHWA;Lo;0;L;;;;;N;;;;; 1218;ETHIOPIC SYLLABLE MA;Lo;0;L;;;;;N;;;;; 1219;ETHIOPIC SYLLABLE MU;Lo;0;L;;;;;N;;;;; 121A;ETHIOPIC SYLLABLE MI;Lo;0;L;;;;;N;;;;; 121B;ETHIOPIC SYLLABLE MAA;Lo;0;L;;;;;N;;;;; 121C;ETHIOPIC SYLLABLE MEE;Lo;0;L;;;;;N;;;;; 121D;ETHIOPIC SYLLABLE ME;Lo;0;L;;;;;N;;;;; 121E;ETHIOPIC SYLLABLE MO;Lo;0;L;;;;;N;;;;; 121F;ETHIOPIC SYLLABLE MWA;Lo;0;L;;;;;N;;;;; 1220;ETHIOPIC SYLLABLE SZA;Lo;0;L;;;;;N;;;;; 1221;ETHIOPIC SYLLABLE SZU;Lo;0;L;;;;;N;;;;; 1222;ETHIOPIC SYLLABLE SZI;Lo;0;L;;;;;N;;;;; 1223;ETHIOPIC SYLLABLE SZAA;Lo;0;L;;;;;N;;;;; 1224;ETHIOPIC SYLLABLE SZEE;Lo;0;L;;;;;N;;;;; 1225;ETHIOPIC SYLLABLE SZE;Lo;0;L;;;;;N;;;;; 1226;ETHIOPIC SYLLABLE SZO;Lo;0;L;;;;;N;;;;; 1227;ETHIOPIC SYLLABLE SZWA;Lo;0;L;;;;;N;;;;; 1228;ETHIOPIC SYLLABLE RA;Lo;0;L;;;;;N;;;;; 1229;ETHIOPIC SYLLABLE RU;Lo;0;L;;;;;N;;;;; 122A;ETHIOPIC SYLLABLE RI;Lo;0;L;;;;;N;;;;; 122B;ETHIOPIC SYLLABLE RAA;Lo;0;L;;;;;N;;;;; 122C;ETHIOPIC SYLLABLE REE;Lo;0;L;;;;;N;;;;; 122D;ETHIOPIC SYLLABLE RE;Lo;0;L;;;;;N;;;;; 122E;ETHIOPIC SYLLABLE RO;Lo;0;L;;;;;N;;;;; 122F;ETHIOPIC SYLLABLE RWA;Lo;0;L;;;;;N;;;;; 1230;ETHIOPIC SYLLABLE SA;Lo;0;L;;;;;N;;;;; 1231;ETHIOPIC SYLLABLE SU;Lo;0;L;;;;;N;;;;; 1232;ETHIOPIC SYLLABLE SI;Lo;0;L;;;;;N;;;;; 1233;ETHIOPIC SYLLABLE SAA;Lo;0;L;;;;;N;;;;; 1234;ETHIOPIC SYLLABLE SEE;Lo;0;L;;;;;N;;;;; 1235;ETHIOPIC SYLLABLE SE;Lo;0;L;;;;;N;;;;; 1236;ETHIOPIC SYLLABLE SO;Lo;0;L;;;;;N;;;;; 1237;ETHIOPIC SYLLABLE SWA;Lo;0;L;;;;;N;;;;; 1238;ETHIOPIC SYLLABLE SHA;Lo;0;L;;;;;N;;;;; 1239;ETHIOPIC SYLLABLE SHU;Lo;0;L;;;;;N;;;;; 123A;ETHIOPIC SYLLABLE SHI;Lo;0;L;;;;;N;;;;; 123B;ETHIOPIC SYLLABLE SHAA;Lo;0;L;;;;;N;;;;; 123C;ETHIOPIC SYLLABLE SHEE;Lo;0;L;;;;;N;;;;; 123D;ETHIOPIC SYLLABLE SHE;Lo;0;L;;;;;N;;;;; 123E;ETHIOPIC SYLLABLE SHO;Lo;0;L;;;;;N;;;;; 123F;ETHIOPIC SYLLABLE SHWA;Lo;0;L;;;;;N;;;;; 1240;ETHIOPIC SYLLABLE QA;Lo;0;L;;;;;N;;;;; 1241;ETHIOPIC SYLLABLE QU;Lo;0;L;;;;;N;;;;; 1242;ETHIOPIC SYLLABLE QI;Lo;0;L;;;;;N;;;;; 1243;ETHIOPIC SYLLABLE QAA;Lo;0;L;;;;;N;;;;; 1244;ETHIOPIC SYLLABLE QEE;Lo;0;L;;;;;N;;;;; 1245;ETHIOPIC SYLLABLE QE;Lo;0;L;;;;;N;;;;; 1246;ETHIOPIC SYLLABLE QO;Lo;0;L;;;;;N;;;;; 1247;ETHIOPIC SYLLABLE QOA;Lo;0;L;;;;;N;;;;; 1248;ETHIOPIC SYLLABLE QWA;Lo;0;L;;;;;N;;;;; 124A;ETHIOPIC SYLLABLE QWI;Lo;0;L;;;;;N;;;;; 124B;ETHIOPIC SYLLABLE QWAA;Lo;0;L;;;;;N;;;;; 124C;ETHIOPIC SYLLABLE QWEE;Lo;0;L;;;;;N;;;;; 124D;ETHIOPIC SYLLABLE QWE;Lo;0;L;;;;;N;;;;; 1250;ETHIOPIC SYLLABLE QHA;Lo;0;L;;;;;N;;;;; 1251;ETHIOPIC SYLLABLE QHU;Lo;0;L;;;;;N;;;;; 1252;ETHIOPIC SYLLABLE QHI;Lo;0;L;;;;;N;;;;; 1253;ETHIOPIC SYLLABLE QHAA;Lo;0;L;;;;;N;;;;; 1254;ETHIOPIC SYLLABLE QHEE;Lo;0;L;;;;;N;;;;; 1255;ETHIOPIC SYLLABLE QHE;Lo;0;L;;;;;N;;;;; 1256;ETHIOPIC SYLLABLE QHO;Lo;0;L;;;;;N;;;;; 1258;ETHIOPIC SYLLABLE QHWA;Lo;0;L;;;;;N;;;;; 125A;ETHIOPIC SYLLABLE QHWI;Lo;0;L;;;;;N;;;;; 125B;ETHIOPIC SYLLABLE QHWAA;Lo;0;L;;;;;N;;;;; 125C;ETHIOPIC SYLLABLE QHWEE;Lo;0;L;;;;;N;;;;; 125D;ETHIOPIC SYLLABLE QHWE;Lo;0;L;;;;;N;;;;; 1260;ETHIOPIC SYLLABLE BA;Lo;0;L;;;;;N;;;;; 1261;ETHIOPIC SYLLABLE BU;Lo;0;L;;;;;N;;;;; 1262;ETHIOPIC SYLLABLE BI;Lo;0;L;;;;;N;;;;; 1263;ETHIOPIC SYLLABLE BAA;Lo;0;L;;;;;N;;;;; 1264;ETHIOPIC SYLLABLE BEE;Lo;0;L;;;;;N;;;;; 1265;ETHIOPIC SYLLABLE BE;Lo;0;L;;;;;N;;;;; 1266;ETHIOPIC SYLLABLE BO;Lo;0;L;;;;;N;;;;; 1267;ETHIOPIC SYLLABLE BWA;Lo;0;L;;;;;N;;;;; 1268;ETHIOPIC SYLLABLE VA;Lo;0;L;;;;;N;;;;; 1269;ETHIOPIC SYLLABLE VU;Lo;0;L;;;;;N;;;;; 126A;ETHIOPIC SYLLABLE VI;Lo;0;L;;;;;N;;;;; 126B;ETHIOPIC SYLLABLE VAA;Lo;0;L;;;;;N;;;;; 126C;ETHIOPIC SYLLABLE VEE;Lo;0;L;;;;;N;;;;; 126D;ETHIOPIC SYLLABLE VE;Lo;0;L;;;;;N;;;;; 126E;ETHIOPIC SYLLABLE VO;Lo;0;L;;;;;N;;;;; 126F;ETHIOPIC SYLLABLE VWA;Lo;0;L;;;;;N;;;;; 1270;ETHIOPIC SYLLABLE TA;Lo;0;L;;;;;N;;;;; 1271;ETHIOPIC SYLLABLE TU;Lo;0;L;;;;;N;;;;; 1272;ETHIOPIC SYLLABLE TI;Lo;0;L;;;;;N;;;;; 1273;ETHIOPIC SYLLABLE TAA;Lo;0;L;;;;;N;;;;; 1274;ETHIOPIC SYLLABLE TEE;Lo;0;L;;;;;N;;;;; 1275;ETHIOPIC SYLLABLE TE;Lo;0;L;;;;;N;;;;; 1276;ETHIOPIC SYLLABLE TO;Lo;0;L;;;;;N;;;;; 1277;ETHIOPIC SYLLABLE TWA;Lo;0;L;;;;;N;;;;; 1278;ETHIOPIC SYLLABLE CA;Lo;0;L;;;;;N;;;;; 1279;ETHIOPIC SYLLABLE CU;Lo;0;L;;;;;N;;;;; 127A;ETHIOPIC SYLLABLE CI;Lo;0;L;;;;;N;;;;; 127B;ETHIOPIC SYLLABLE CAA;Lo;0;L;;;;;N;;;;; 127C;ETHIOPIC SYLLABLE CEE;Lo;0;L;;;;;N;;;;; 127D;ETHIOPIC SYLLABLE CE;Lo;0;L;;;;;N;;;;; 127E;ETHIOPIC SYLLABLE CO;Lo;0;L;;;;;N;;;;; 127F;ETHIOPIC SYLLABLE CWA;Lo;0;L;;;;;N;;;;; 1280;ETHIOPIC SYLLABLE XA;Lo;0;L;;;;;N;;;;; 1281;ETHIOPIC SYLLABLE XU;Lo;0;L;;;;;N;;;;; 1282;ETHIOPIC SYLLABLE XI;Lo;0;L;;;;;N;;;;; 1283;ETHIOPIC SYLLABLE XAA;Lo;0;L;;;;;N;;;;; 1284;ETHIOPIC SYLLABLE XEE;Lo;0;L;;;;;N;;;;; 1285;ETHIOPIC SYLLABLE XE;Lo;0;L;;;;;N;;;;; 1286;ETHIOPIC SYLLABLE XO;Lo;0;L;;;;;N;;;;; 1287;ETHIOPIC SYLLABLE XOA;Lo;0;L;;;;;N;;;;; 1288;ETHIOPIC SYLLABLE XWA;Lo;0;L;;;;;N;;;;; 128A;ETHIOPIC SYLLABLE XWI;Lo;0;L;;;;;N;;;;; 128B;ETHIOPIC SYLLABLE XWAA;Lo;0;L;;;;;N;;;;; 128C;ETHIOPIC SYLLABLE XWEE;Lo;0;L;;;;;N;;;;; 128D;ETHIOPIC SYLLABLE XWE;Lo;0;L;;;;;N;;;;; 1290;ETHIOPIC SYLLABLE NA;Lo;0;L;;;;;N;;;;; 1291;ETHIOPIC SYLLABLE NU;Lo;0;L;;;;;N;;;;; 1292;ETHIOPIC SYLLABLE NI;Lo;0;L;;;;;N;;;;; 1293;ETHIOPIC SYLLABLE NAA;Lo;0;L;;;;;N;;;;; 1294;ETHIOPIC SYLLABLE NEE;Lo;0;L;;;;;N;;;;; 1295;ETHIOPIC SYLLABLE NE;Lo;0;L;;;;;N;;;;; 1296;ETHIOPIC SYLLABLE NO;Lo;0;L;;;;;N;;;;; 1297;ETHIOPIC SYLLABLE NWA;Lo;0;L;;;;;N;;;;; 1298;ETHIOPIC SYLLABLE NYA;Lo;0;L;;;;;N;;;;; 1299;ETHIOPIC SYLLABLE NYU;Lo;0;L;;;;;N;;;;; 129A;ETHIOPIC SYLLABLE NYI;Lo;0;L;;;;;N;;;;; 129B;ETHIOPIC SYLLABLE NYAA;Lo;0;L;;;;;N;;;;; 129C;ETHIOPIC SYLLABLE NYEE;Lo;0;L;;;;;N;;;;; 129D;ETHIOPIC SYLLABLE NYE;Lo;0;L;;;;;N;;;;; 129E;ETHIOPIC SYLLABLE NYO;Lo;0;L;;;;;N;;;;; 129F;ETHIOPIC SYLLABLE NYWA;Lo;0;L;;;;;N;;;;; 12A0;ETHIOPIC SYLLABLE GLOTTAL A;Lo;0;L;;;;;N;;;;; 12A1;ETHIOPIC SYLLABLE GLOTTAL U;Lo;0;L;;;;;N;;;;; 12A2;ETHIOPIC SYLLABLE GLOTTAL I;Lo;0;L;;;;;N;;;;; 12A3;ETHIOPIC SYLLABLE GLOTTAL AA;Lo;0;L;;;;;N;;;;; 12A4;ETHIOPIC SYLLABLE GLOTTAL EE;Lo;0;L;;;;;N;;;;; 12A5;ETHIOPIC SYLLABLE GLOTTAL E;Lo;0;L;;;;;N;;;;; 12A6;ETHIOPIC SYLLABLE GLOTTAL O;Lo;0;L;;;;;N;;;;; 12A7;ETHIOPIC SYLLABLE GLOTTAL WA;Lo;0;L;;;;;N;;;;; 12A8;ETHIOPIC SYLLABLE KA;Lo;0;L;;;;;N;;;;; 12A9;ETHIOPIC SYLLABLE KU;Lo;0;L;;;;;N;;;;; 12AA;ETHIOPIC SYLLABLE KI;Lo;0;L;;;;;N;;;;; 12AB;ETHIOPIC SYLLABLE KAA;Lo;0;L;;;;;N;;;;; 12AC;ETHIOPIC SYLLABLE KEE;Lo;0;L;;;;;N;;;;; 12AD;ETHIOPIC SYLLABLE KE;Lo;0;L;;;;;N;;;;; 12AE;ETHIOPIC SYLLABLE KO;Lo;0;L;;;;;N;;;;; 12AF;ETHIOPIC SYLLABLE KOA;Lo;0;L;;;;;N;;;;; 12B0;ETHIOPIC SYLLABLE KWA;Lo;0;L;;;;;N;;;;; 12B2;ETHIOPIC SYLLABLE KWI;Lo;0;L;;;;;N;;;;; 12B3;ETHIOPIC SYLLABLE KWAA;Lo;0;L;;;;;N;;;;; 12B4;ETHIOPIC SYLLABLE KWEE;Lo;0;L;;;;;N;;;;; 12B5;ETHIOPIC SYLLABLE KWE;Lo;0;L;;;;;N;;;;; 12B8;ETHIOPIC SYLLABLE KXA;Lo;0;L;;;;;N;;;;; 12B9;ETHIOPIC SYLLABLE KXU;Lo;0;L;;;;;N;;;;; 12BA;ETHIOPIC SYLLABLE KXI;Lo;0;L;;;;;N;;;;; 12BB;ETHIOPIC SYLLABLE KXAA;Lo;0;L;;;;;N;;;;; 12BC;ETHIOPIC SYLLABLE KXEE;Lo;0;L;;;;;N;;;;; 12BD;ETHIOPIC SYLLABLE KXE;Lo;0;L;;;;;N;;;;; 12BE;ETHIOPIC SYLLABLE KXO;Lo;0;L;;;;;N;;;;; 12C0;ETHIOPIC SYLLABLE KXWA;Lo;0;L;;;;;N;;;;; 12C2;ETHIOPIC SYLLABLE KXWI;Lo;0;L;;;;;N;;;;; 12C3;ETHIOPIC SYLLABLE KXWAA;Lo;0;L;;;;;N;;;;; 12C4;ETHIOPIC SYLLABLE KXWEE;Lo;0;L;;;;;N;;;;; 12C5;ETHIOPIC SYLLABLE KXWE;Lo;0;L;;;;;N;;;;; 12C8;ETHIOPIC SYLLABLE WA;Lo;0;L;;;;;N;;;;; 12C9;ETHIOPIC SYLLABLE WU;Lo;0;L;;;;;N;;;;; 12CA;ETHIOPIC SYLLABLE WI;Lo;0;L;;;;;N;;;;; 12CB;ETHIOPIC SYLLABLE WAA;Lo;0;L;;;;;N;;;;; 12CC;ETHIOPIC SYLLABLE WEE;Lo;0;L;;;;;N;;;;; 12CD;ETHIOPIC SYLLABLE WE;Lo;0;L;;;;;N;;;;; 12CE;ETHIOPIC SYLLABLE WO;Lo;0;L;;;;;N;;;;; 12CF;ETHIOPIC SYLLABLE WOA;Lo;0;L;;;;;N;;;;; 12D0;ETHIOPIC SYLLABLE PHARYNGEAL A;Lo;0;L;;;;;N;;;;; 12D1;ETHIOPIC SYLLABLE PHARYNGEAL U;Lo;0;L;;;;;N;;;;; 12D2;ETHIOPIC SYLLABLE PHARYNGEAL I;Lo;0;L;;;;;N;;;;; 12D3;ETHIOPIC SYLLABLE PHARYNGEAL AA;Lo;0;L;;;;;N;;;;; 12D4;ETHIOPIC SYLLABLE PHARYNGEAL EE;Lo;0;L;;;;;N;;;;; 12D5;ETHIOPIC SYLLABLE PHARYNGEAL E;Lo;0;L;;;;;N;;;;; 12D6;ETHIOPIC SYLLABLE PHARYNGEAL O;Lo;0;L;;;;;N;;;;; 12D8;ETHIOPIC SYLLABLE ZA;Lo;0;L;;;;;N;;;;; 12D9;ETHIOPIC SYLLABLE ZU;Lo;0;L;;;;;N;;;;; 12DA;ETHIOPIC SYLLABLE ZI;Lo;0;L;;;;;N;;;;; 12DB;ETHIOPIC SYLLABLE ZAA;Lo;0;L;;;;;N;;;;; 12DC;ETHIOPIC SYLLABLE ZEE;Lo;0;L;;;;;N;;;;; 12DD;ETHIOPIC SYLLABLE ZE;Lo;0;L;;;;;N;;;;; 12DE;ETHIOPIC SYLLABLE ZO;Lo;0;L;;;;;N;;;;; 12DF;ETHIOPIC SYLLABLE ZWA;Lo;0;L;;;;;N;;;;; 12E0;ETHIOPIC SYLLABLE ZHA;Lo;0;L;;;;;N;;;;; 12E1;ETHIOPIC SYLLABLE ZHU;Lo;0;L;;;;;N;;;;; 12E2;ETHIOPIC SYLLABLE ZHI;Lo;0;L;;;;;N;;;;; 12E3;ETHIOPIC SYLLABLE ZHAA;Lo;0;L;;;;;N;;;;; 12E4;ETHIOPIC SYLLABLE ZHEE;Lo;0;L;;;;;N;;;;; 12E5;ETHIOPIC SYLLABLE ZHE;Lo;0;L;;;;;N;;;;; 12E6;ETHIOPIC SYLLABLE ZHO;Lo;0;L;;;;;N;;;;; 12E7;ETHIOPIC SYLLABLE ZHWA;Lo;0;L;;;;;N;;;;; 12E8;ETHIOPIC SYLLABLE YA;Lo;0;L;;;;;N;;;;; 12E9;ETHIOPIC SYLLABLE YU;Lo;0;L;;;;;N;;;;; 12EA;ETHIOPIC SYLLABLE YI;Lo;0;L;;;;;N;;;;; 12EB;ETHIOPIC SYLLABLE YAA;Lo;0;L;;;;;N;;;;; 12EC;ETHIOPIC SYLLABLE YEE;Lo;0;L;;;;;N;;;;; 12ED;ETHIOPIC SYLLABLE YE;Lo;0;L;;;;;N;;;;; 12EE;ETHIOPIC SYLLABLE YO;Lo;0;L;;;;;N;;;;; 12EF;ETHIOPIC SYLLABLE YOA;Lo;0;L;;;;;N;;;;; 12F0;ETHIOPIC SYLLABLE DA;Lo;0;L;;;;;N;;;;; 12F1;ETHIOPIC SYLLABLE DU;Lo;0;L;;;;;N;;;;; 12F2;ETHIOPIC SYLLABLE DI;Lo;0;L;;;;;N;;;;; 12F3;ETHIOPIC SYLLABLE DAA;Lo;0;L;;;;;N;;;;; 12F4;ETHIOPIC SYLLABLE DEE;Lo;0;L;;;;;N;;;;; 12F5;ETHIOPIC SYLLABLE DE;Lo;0;L;;;;;N;;;;; 12F6;ETHIOPIC SYLLABLE DO;Lo;0;L;;;;;N;;;;; 12F7;ETHIOPIC SYLLABLE DWA;Lo;0;L;;;;;N;;;;; 12F8;ETHIOPIC SYLLABLE DDA;Lo;0;L;;;;;N;;;;; 12F9;ETHIOPIC SYLLABLE DDU;Lo;0;L;;;;;N;;;;; 12FA;ETHIOPIC SYLLABLE DDI;Lo;0;L;;;;;N;;;;; 12FB;ETHIOPIC SYLLABLE DDAA;Lo;0;L;;;;;N;;;;; 12FC;ETHIOPIC SYLLABLE DDEE;Lo;0;L;;;;;N;;;;; 12FD;ETHIOPIC SYLLABLE DDE;Lo;0;L;;;;;N;;;;; 12FE;ETHIOPIC SYLLABLE DDO;Lo;0;L;;;;;N;;;;; 12FF;ETHIOPIC SYLLABLE DDWA;Lo;0;L;;;;;N;;;;; 1300;ETHIOPIC SYLLABLE JA;Lo;0;L;;;;;N;;;;; 1301;ETHIOPIC SYLLABLE JU;Lo;0;L;;;;;N;;;;; 1302;ETHIOPIC SYLLABLE JI;Lo;0;L;;;;;N;;;;; 1303;ETHIOPIC SYLLABLE JAA;Lo;0;L;;;;;N;;;;; 1304;ETHIOPIC SYLLABLE JEE;Lo;0;L;;;;;N;;;;; 1305;ETHIOPIC SYLLABLE JE;Lo;0;L;;;;;N;;;;; 1306;ETHIOPIC SYLLABLE JO;Lo;0;L;;;;;N;;;;; 1307;ETHIOPIC SYLLABLE JWA;Lo;0;L;;;;;N;;;;; 1308;ETHIOPIC SYLLABLE GA;Lo;0;L;;;;;N;;;;; 1309;ETHIOPIC SYLLABLE GU;Lo;0;L;;;;;N;;;;; 130A;ETHIOPIC SYLLABLE GI;Lo;0;L;;;;;N;;;;; 130B;ETHIOPIC SYLLABLE GAA;Lo;0;L;;;;;N;;;;; 130C;ETHIOPIC SYLLABLE GEE;Lo;0;L;;;;;N;;;;; 130D;ETHIOPIC SYLLABLE GE;Lo;0;L;;;;;N;;;;; 130E;ETHIOPIC SYLLABLE GO;Lo;0;L;;;;;N;;;;; 130F;ETHIOPIC SYLLABLE GOA;Lo;0;L;;;;;N;;;;; 1310;ETHIOPIC SYLLABLE GWA;Lo;0;L;;;;;N;;;;; 1312;ETHIOPIC SYLLABLE GWI;Lo;0;L;;;;;N;;;;; 1313;ETHIOPIC SYLLABLE GWAA;Lo;0;L;;;;;N;;;;; 1314;ETHIOPIC SYLLABLE GWEE;Lo;0;L;;;;;N;;;;; 1315;ETHIOPIC SYLLABLE GWE;Lo;0;L;;;;;N;;;;; 1318;ETHIOPIC SYLLABLE GGA;Lo;0;L;;;;;N;;;;; 1319;ETHIOPIC SYLLABLE GGU;Lo;0;L;;;;;N;;;;; 131A;ETHIOPIC SYLLABLE GGI;Lo;0;L;;;;;N;;;;; 131B;ETHIOPIC SYLLABLE GGAA;Lo;0;L;;;;;N;;;;; 131C;ETHIOPIC SYLLABLE GGEE;Lo;0;L;;;;;N;;;;; 131D;ETHIOPIC SYLLABLE GGE;Lo;0;L;;;;;N;;;;; 131E;ETHIOPIC SYLLABLE GGO;Lo;0;L;;;;;N;;;;; 131F;ETHIOPIC SYLLABLE GGWAA;Lo;0;L;;;;;N;;;;; 1320;ETHIOPIC SYLLABLE THA;Lo;0;L;;;;;N;;;;; 1321;ETHIOPIC SYLLABLE THU;Lo;0;L;;;;;N;;;;; 1322;ETHIOPIC SYLLABLE THI;Lo;0;L;;;;;N;;;;; 1323;ETHIOPIC SYLLABLE THAA;Lo;0;L;;;;;N;;;;; 1324;ETHIOPIC SYLLABLE THEE;Lo;0;L;;;;;N;;;;; 1325;ETHIOPIC SYLLABLE THE;Lo;0;L;;;;;N;;;;; 1326;ETHIOPIC SYLLABLE THO;Lo;0;L;;;;;N;;;;; 1327;ETHIOPIC SYLLABLE THWA;Lo;0;L;;;;;N;;;;; 1328;ETHIOPIC SYLLABLE CHA;Lo;0;L;;;;;N;;;;; 1329;ETHIOPIC SYLLABLE CHU;Lo;0;L;;;;;N;;;;; 132A;ETHIOPIC SYLLABLE CHI;Lo;0;L;;;;;N;;;;; 132B;ETHIOPIC SYLLABLE CHAA;Lo;0;L;;;;;N;;;;; 132C;ETHIOPIC SYLLABLE CHEE;Lo;0;L;;;;;N;;;;; 132D;ETHIOPIC SYLLABLE CHE;Lo;0;L;;;;;N;;;;; 132E;ETHIOPIC SYLLABLE CHO;Lo;0;L;;;;;N;;;;; 132F;ETHIOPIC SYLLABLE CHWA;Lo;0;L;;;;;N;;;;; 1330;ETHIOPIC SYLLABLE PHA;Lo;0;L;;;;;N;;;;; 1331;ETHIOPIC SYLLABLE PHU;Lo;0;L;;;;;N;;;;; 1332;ETHIOPIC SYLLABLE PHI;Lo;0;L;;;;;N;;;;; 1333;ETHIOPIC SYLLABLE PHAA;Lo;0;L;;;;;N;;;;; 1334;ETHIOPIC SYLLABLE PHEE;Lo;0;L;;;;;N;;;;; 1335;ETHIOPIC SYLLABLE PHE;Lo;0;L;;;;;N;;;;; 1336;ETHIOPIC SYLLABLE PHO;Lo;0;L;;;;;N;;;;; 1337;ETHIOPIC SYLLABLE PHWA;Lo;0;L;;;;;N;;;;; 1338;ETHIOPIC SYLLABLE TSA;Lo;0;L;;;;;N;;;;; 1339;ETHIOPIC SYLLABLE TSU;Lo;0;L;;;;;N;;;;; 133A;ETHIOPIC SYLLABLE TSI;Lo;0;L;;;;;N;;;;; 133B;ETHIOPIC SYLLABLE TSAA;Lo;0;L;;;;;N;;;;; 133C;ETHIOPIC SYLLABLE TSEE;Lo;0;L;;;;;N;;;;; 133D;ETHIOPIC SYLLABLE TSE;Lo;0;L;;;;;N;;;;; 133E;ETHIOPIC SYLLABLE TSO;Lo;0;L;;;;;N;;;;; 133F;ETHIOPIC SYLLABLE TSWA;Lo;0;L;;;;;N;;;;; 1340;ETHIOPIC SYLLABLE TZA;Lo;0;L;;;;;N;;;;; 1341;ETHIOPIC SYLLABLE TZU;Lo;0;L;;;;;N;;;;; 1342;ETHIOPIC SYLLABLE TZI;Lo;0;L;;;;;N;;;;; 1343;ETHIOPIC SYLLABLE TZAA;Lo;0;L;;;;;N;;;;; 1344;ETHIOPIC SYLLABLE TZEE;Lo;0;L;;;;;N;;;;; 1345;ETHIOPIC SYLLABLE TZE;Lo;0;L;;;;;N;;;;; 1346;ETHIOPIC SYLLABLE TZO;Lo;0;L;;;;;N;;;;; 1347;ETHIOPIC SYLLABLE TZOA;Lo;0;L;;;;;N;;;;; 1348;ETHIOPIC SYLLABLE FA;Lo;0;L;;;;;N;;;;; 1349;ETHIOPIC SYLLABLE FU;Lo;0;L;;;;;N;;;;; 134A;ETHIOPIC SYLLABLE FI;Lo;0;L;;;;;N;;;;; 134B;ETHIOPIC SYLLABLE FAA;Lo;0;L;;;;;N;;;;; 134C;ETHIOPIC SYLLABLE FEE;Lo;0;L;;;;;N;;;;; 134D;ETHIOPIC SYLLABLE FE;Lo;0;L;;;;;N;;;;; 134E;ETHIOPIC SYLLABLE FO;Lo;0;L;;;;;N;;;;; 134F;ETHIOPIC SYLLABLE FWA;Lo;0;L;;;;;N;;;;; 1350;ETHIOPIC SYLLABLE PA;Lo;0;L;;;;;N;;;;; 1351;ETHIOPIC SYLLABLE PU;Lo;0;L;;;;;N;;;;; 1352;ETHIOPIC SYLLABLE PI;Lo;0;L;;;;;N;;;;; 1353;ETHIOPIC SYLLABLE PAA;Lo;0;L;;;;;N;;;;; 1354;ETHIOPIC SYLLABLE PEE;Lo;0;L;;;;;N;;;;; 1355;ETHIOPIC SYLLABLE PE;Lo;0;L;;;;;N;;;;; 1356;ETHIOPIC SYLLABLE PO;Lo;0;L;;;;;N;;;;; 1357;ETHIOPIC SYLLABLE PWA;Lo;0;L;;;;;N;;;;; 1358;ETHIOPIC SYLLABLE RYA;Lo;0;L;;;;;N;;;;; 1359;ETHIOPIC SYLLABLE MYA;Lo;0;L;;;;;N;;;;; 135A;ETHIOPIC SYLLABLE FYA;Lo;0;L;;;;;N;;;;; 135D;ETHIOPIC COMBINING GEMINATION AND VOWEL LENGTH MARK;Mn;230;NSM;;;;;N;;;;; 135E;ETHIOPIC COMBINING VOWEL LENGTH MARK;Mn;230;NSM;;;;;N;;;;; 135F;ETHIOPIC COMBINING GEMINATION MARK;Mn;230;NSM;;;;;N;;;;; 1360;ETHIOPIC SECTION MARK;Po;0;L;;;;;N;;;;; 1361;ETHIOPIC WORDSPACE;Po;0;L;;;;;N;;;;; 1362;ETHIOPIC FULL STOP;Po;0;L;;;;;N;;;;; 1363;ETHIOPIC COMMA;Po;0;L;;;;;N;;;;; 1364;ETHIOPIC SEMICOLON;Po;0;L;;;;;N;;;;; 1365;ETHIOPIC COLON;Po;0;L;;;;;N;;;;; 1366;ETHIOPIC PREFACE COLON;Po;0;L;;;;;N;;;;; 1367;ETHIOPIC QUESTION MARK;Po;0;L;;;;;N;;;;; 1368;ETHIOPIC PARAGRAPH SEPARATOR;Po;0;L;;;;;N;;;;; 1369;ETHIOPIC DIGIT ONE;No;0;L;;;1;1;N;;;;; 136A;ETHIOPIC DIGIT TWO;No;0;L;;;2;2;N;;;;; 136B;ETHIOPIC DIGIT THREE;No;0;L;;;3;3;N;;;;; 136C;ETHIOPIC DIGIT FOUR;No;0;L;;;4;4;N;;;;; 136D;ETHIOPIC DIGIT FIVE;No;0;L;;;5;5;N;;;;; 136E;ETHIOPIC DIGIT SIX;No;0;L;;;6;6;N;;;;; 136F;ETHIOPIC DIGIT SEVEN;No;0;L;;;7;7;N;;;;; 1370;ETHIOPIC DIGIT EIGHT;No;0;L;;;8;8;N;;;;; 1371;ETHIOPIC DIGIT NINE;No;0;L;;;9;9;N;;;;; 1372;ETHIOPIC NUMBER TEN;No;0;L;;;;10;N;;;;; 1373;ETHIOPIC NUMBER TWENTY;No;0;L;;;;20;N;;;;; 1374;ETHIOPIC NUMBER THIRTY;No;0;L;;;;30;N;;;;; 1375;ETHIOPIC NUMBER FORTY;No;0;L;;;;40;N;;;;; 1376;ETHIOPIC NUMBER FIFTY;No;0;L;;;;50;N;;;;; 1377;ETHIOPIC NUMBER SIXTY;No;0;L;;;;60;N;;;;; 1378;ETHIOPIC NUMBER SEVENTY;No;0;L;;;;70;N;;;;; 1379;ETHIOPIC NUMBER EIGHTY;No;0;L;;;;80;N;;;;; 137A;ETHIOPIC NUMBER NINETY;No;0;L;;;;90;N;;;;; 137B;ETHIOPIC NUMBER HUNDRED;No;0;L;;;;100;N;;;;; 137C;ETHIOPIC NUMBER TEN THOUSAND;No;0;L;;;;10000;N;;;;; 1380;ETHIOPIC SYLLABLE SEBATBEIT MWA;Lo;0;L;;;;;N;;;;; 1381;ETHIOPIC SYLLABLE MWI;Lo;0;L;;;;;N;;;;; 1382;ETHIOPIC SYLLABLE MWEE;Lo;0;L;;;;;N;;;;; 1383;ETHIOPIC SYLLABLE MWE;Lo;0;L;;;;;N;;;;; 1384;ETHIOPIC SYLLABLE SEBATBEIT BWA;Lo;0;L;;;;;N;;;;; 1385;ETHIOPIC SYLLABLE BWI;Lo;0;L;;;;;N;;;;; 1386;ETHIOPIC SYLLABLE BWEE;Lo;0;L;;;;;N;;;;; 1387;ETHIOPIC SYLLABLE BWE;Lo;0;L;;;;;N;;;;; 1388;ETHIOPIC SYLLABLE SEBATBEIT FWA;Lo;0;L;;;;;N;;;;; 1389;ETHIOPIC SYLLABLE FWI;Lo;0;L;;;;;N;;;;; 138A;ETHIOPIC SYLLABLE FWEE;Lo;0;L;;;;;N;;;;; 138B;ETHIOPIC SYLLABLE FWE;Lo;0;L;;;;;N;;;;; 138C;ETHIOPIC SYLLABLE SEBATBEIT PWA;Lo;0;L;;;;;N;;;;; 138D;ETHIOPIC SYLLABLE PWI;Lo;0;L;;;;;N;;;;; 138E;ETHIOPIC SYLLABLE PWEE;Lo;0;L;;;;;N;;;;; 138F;ETHIOPIC SYLLABLE PWE;Lo;0;L;;;;;N;;;;; 1390;ETHIOPIC TONAL MARK YIZET;So;0;ON;;;;;N;;;;; 1391;ETHIOPIC TONAL MARK DERET;So;0;ON;;;;;N;;;;; 1392;ETHIOPIC TONAL MARK RIKRIK;So;0;ON;;;;;N;;;;; 1393;ETHIOPIC TONAL MARK SHORT RIKRIK;So;0;ON;;;;;N;;;;; 1394;ETHIOPIC TONAL MARK DIFAT;So;0;ON;;;;;N;;;;; 1395;ETHIOPIC TONAL MARK KENAT;So;0;ON;;;;;N;;;;; 1396;ETHIOPIC TONAL MARK CHIRET;So;0;ON;;;;;N;;;;; 1397;ETHIOPIC TONAL MARK HIDET;So;0;ON;;;;;N;;;;; 1398;ETHIOPIC TONAL MARK DERET-HIDET;So;0;ON;;;;;N;;;;; 1399;ETHIOPIC TONAL MARK KURT;So;0;ON;;;;;N;;;;; 13A0;CHEROKEE LETTER A;Lu;0;L;;;;;N;;;;AB70; 13A1;CHEROKEE LETTER E;Lu;0;L;;;;;N;;;;AB71; 13A2;CHEROKEE LETTER I;Lu;0;L;;;;;N;;;;AB72; 13A3;CHEROKEE LETTER O;Lu;0;L;;;;;N;;;;AB73; 13A4;CHEROKEE LETTER U;Lu;0;L;;;;;N;;;;AB74; 13A5;CHEROKEE LETTER V;Lu;0;L;;;;;N;;;;AB75; 13A6;CHEROKEE LETTER GA;Lu;0;L;;;;;N;;;;AB76; 13A7;CHEROKEE LETTER KA;Lu;0;L;;;;;N;;;;AB77; 13A8;CHEROKEE LETTER GE;Lu;0;L;;;;;N;;;;AB78; 13A9;CHEROKEE LETTER GI;Lu;0;L;;;;;N;;;;AB79; 13AA;CHEROKEE LETTER GO;Lu;0;L;;;;;N;;;;AB7A; 13AB;CHEROKEE LETTER GU;Lu;0;L;;;;;N;;;;AB7B; 13AC;CHEROKEE LETTER GV;Lu;0;L;;;;;N;;;;AB7C; 13AD;CHEROKEE LETTER HA;Lu;0;L;;;;;N;;;;AB7D; 13AE;CHEROKEE LETTER HE;Lu;0;L;;;;;N;;;;AB7E; 13AF;CHEROKEE LETTER HI;Lu;0;L;;;;;N;;;;AB7F; 13B0;CHEROKEE LETTER HO;Lu;0;L;;;;;N;;;;AB80; 13B1;CHEROKEE LETTER HU;Lu;0;L;;;;;N;;;;AB81; 13B2;CHEROKEE LETTER HV;Lu;0;L;;;;;N;;;;AB82; 13B3;CHEROKEE LETTER LA;Lu;0;L;;;;;N;;;;AB83; 13B4;CHEROKEE LETTER LE;Lu;0;L;;;;;N;;;;AB84; 13B5;CHEROKEE LETTER LI;Lu;0;L;;;;;N;;;;AB85; 13B6;CHEROKEE LETTER LO;Lu;0;L;;;;;N;;;;AB86; 13B7;CHEROKEE LETTER LU;Lu;0;L;;;;;N;;;;AB87; 13B8;CHEROKEE LETTER LV;Lu;0;L;;;;;N;;;;AB88; 13B9;CHEROKEE LETTER MA;Lu;0;L;;;;;N;;;;AB89; 13BA;CHEROKEE LETTER ME;Lu;0;L;;;;;N;;;;AB8A; 13BB;CHEROKEE LETTER MI;Lu;0;L;;;;;N;;;;AB8B; 13BC;CHEROKEE LETTER MO;Lu;0;L;;;;;N;;;;AB8C; 13BD;CHEROKEE LETTER MU;Lu;0;L;;;;;N;;;;AB8D; 13BE;CHEROKEE LETTER NA;Lu;0;L;;;;;N;;;;AB8E; 13BF;CHEROKEE LETTER HNA;Lu;0;L;;;;;N;;;;AB8F; 13C0;CHEROKEE LETTER NAH;Lu;0;L;;;;;N;;;;AB90; 13C1;CHEROKEE LETTER NE;Lu;0;L;;;;;N;;;;AB91; 13C2;CHEROKEE LETTER NI;Lu;0;L;;;;;N;;;;AB92; 13C3;CHEROKEE LETTER NO;Lu;0;L;;;;;N;;;;AB93; 13C4;CHEROKEE LETTER NU;Lu;0;L;;;;;N;;;;AB94; 13C5;CHEROKEE LETTER NV;Lu;0;L;;;;;N;;;;AB95; 13C6;CHEROKEE LETTER QUA;Lu;0;L;;;;;N;;;;AB96; 13C7;CHEROKEE LETTER QUE;Lu;0;L;;;;;N;;;;AB97; 13C8;CHEROKEE LETTER QUI;Lu;0;L;;;;;N;;;;AB98; 13C9;CHEROKEE LETTER QUO;Lu;0;L;;;;;N;;;;AB99; 13CA;CHEROKEE LETTER QUU;Lu;0;L;;;;;N;;;;AB9A; 13CB;CHEROKEE LETTER QUV;Lu;0;L;;;;;N;;;;AB9B; 13CC;CHEROKEE LETTER SA;Lu;0;L;;;;;N;;;;AB9C; 13CD;CHEROKEE LETTER S;Lu;0;L;;;;;N;;;;AB9D; 13CE;CHEROKEE LETTER SE;Lu;0;L;;;;;N;;;;AB9E; 13CF;CHEROKEE LETTER SI;Lu;0;L;;;;;N;;;;AB9F; 13D0;CHEROKEE LETTER SO;Lu;0;L;;;;;N;;;;ABA0; 13D1;CHEROKEE LETTER SU;Lu;0;L;;;;;N;;;;ABA1; 13D2;CHEROKEE LETTER SV;Lu;0;L;;;;;N;;;;ABA2; 13D3;CHEROKEE LETTER DA;Lu;0;L;;;;;N;;;;ABA3; 13D4;CHEROKEE LETTER TA;Lu;0;L;;;;;N;;;;ABA4; 13D5;CHEROKEE LETTER DE;Lu;0;L;;;;;N;;;;ABA5; 13D6;CHEROKEE LETTER TE;Lu;0;L;;;;;N;;;;ABA6; 13D7;CHEROKEE LETTER DI;Lu;0;L;;;;;N;;;;ABA7; 13D8;CHEROKEE LETTER TI;Lu;0;L;;;;;N;;;;ABA8; 13D9;CHEROKEE LETTER DO;Lu;0;L;;;;;N;;;;ABA9; 13DA;CHEROKEE LETTER DU;Lu;0;L;;;;;N;;;;ABAA; 13DB;CHEROKEE LETTER DV;Lu;0;L;;;;;N;;;;ABAB; 13DC;CHEROKEE LETTER DLA;Lu;0;L;;;;;N;;;;ABAC; 13DD;CHEROKEE LETTER TLA;Lu;0;L;;;;;N;;;;ABAD; 13DE;CHEROKEE LETTER TLE;Lu;0;L;;;;;N;;;;ABAE; 13DF;CHEROKEE LETTER TLI;Lu;0;L;;;;;N;;;;ABAF; 13E0;CHEROKEE LETTER TLO;Lu;0;L;;;;;N;;;;ABB0; 13E1;CHEROKEE LETTER TLU;Lu;0;L;;;;;N;;;;ABB1; 13E2;CHEROKEE LETTER TLV;Lu;0;L;;;;;N;;;;ABB2; 13E3;CHEROKEE LETTER TSA;Lu;0;L;;;;;N;;;;ABB3; 13E4;CHEROKEE LETTER TSE;Lu;0;L;;;;;N;;;;ABB4; 13E5;CHEROKEE LETTER TSI;Lu;0;L;;;;;N;;;;ABB5; 13E6;CHEROKEE LETTER TSO;Lu;0;L;;;;;N;;;;ABB6; 13E7;CHEROKEE LETTER TSU;Lu;0;L;;;;;N;;;;ABB7; 13E8;CHEROKEE LETTER TSV;Lu;0;L;;;;;N;;;;ABB8; 13E9;CHEROKEE LETTER WA;Lu;0;L;;;;;N;;;;ABB9; 13EA;CHEROKEE LETTER WE;Lu;0;L;;;;;N;;;;ABBA; 13EB;CHEROKEE LETTER WI;Lu;0;L;;;;;N;;;;ABBB; 13EC;CHEROKEE LETTER WO;Lu;0;L;;;;;N;;;;ABBC; 13ED;CHEROKEE LETTER WU;Lu;0;L;;;;;N;;;;ABBD; 13EE;CHEROKEE LETTER WV;Lu;0;L;;;;;N;;;;ABBE; 13EF;CHEROKEE LETTER YA;Lu;0;L;;;;;N;;;;ABBF; 13F0;CHEROKEE LETTER YE;Lu;0;L;;;;;N;;;;13F8; 13F1;CHEROKEE LETTER YI;Lu;0;L;;;;;N;;;;13F9; 13F2;CHEROKEE LETTER YO;Lu;0;L;;;;;N;;;;13FA; 13F3;CHEROKEE LETTER YU;Lu;0;L;;;;;N;;;;13FB; 13F4;CHEROKEE LETTER YV;Lu;0;L;;;;;N;;;;13FC; 13F5;CHEROKEE LETTER MV;Lu;0;L;;;;;N;;;;13FD; 13F8;CHEROKEE SMALL LETTER YE;Ll;0;L;;;;;N;;;13F0;;13F0 13F9;CHEROKEE SMALL LETTER YI;Ll;0;L;;;;;N;;;13F1;;13F1 13FA;CHEROKEE SMALL LETTER YO;Ll;0;L;;;;;N;;;13F2;;13F2 13FB;CHEROKEE SMALL LETTER YU;Ll;0;L;;;;;N;;;13F3;;13F3 13FC;CHEROKEE SMALL LETTER YV;Ll;0;L;;;;;N;;;13F4;;13F4 13FD;CHEROKEE SMALL LETTER MV;Ll;0;L;;;;;N;;;13F5;;13F5 1400;CANADIAN SYLLABICS HYPHEN;Pd;0;ON;;;;;N;;;;; 1401;CANADIAN SYLLABICS E;Lo;0;L;;;;;N;;;;; 1402;CANADIAN SYLLABICS AAI;Lo;0;L;;;;;N;;;;; 1403;CANADIAN SYLLABICS I;Lo;0;L;;;;;N;;;;; 1404;CANADIAN SYLLABICS II;Lo;0;L;;;;;N;;;;; 1405;CANADIAN SYLLABICS O;Lo;0;L;;;;;N;;;;; 1406;CANADIAN SYLLABICS OO;Lo;0;L;;;;;N;;;;; 1407;CANADIAN SYLLABICS Y-CREE OO;Lo;0;L;;;;;N;;;;; 1408;CANADIAN SYLLABICS CARRIER EE;Lo;0;L;;;;;N;;;;; 1409;CANADIAN SYLLABICS CARRIER I;Lo;0;L;;;;;N;;;;; 140A;CANADIAN SYLLABICS A;Lo;0;L;;;;;N;;;;; 140B;CANADIAN SYLLABICS AA;Lo;0;L;;;;;N;;;;; 140C;CANADIAN SYLLABICS WE;Lo;0;L;;;;;N;;;;; 140D;CANADIAN SYLLABICS WEST-CREE WE;Lo;0;L;;;;;N;;;;; 140E;CANADIAN SYLLABICS WI;Lo;0;L;;;;;N;;;;; 140F;CANADIAN SYLLABICS WEST-CREE WI;Lo;0;L;;;;;N;;;;; 1410;CANADIAN SYLLABICS WII;Lo;0;L;;;;;N;;;;; 1411;CANADIAN SYLLABICS WEST-CREE WII;Lo;0;L;;;;;N;;;;; 1412;CANADIAN SYLLABICS WO;Lo;0;L;;;;;N;;;;; 1413;CANADIAN SYLLABICS WEST-CREE WO;Lo;0;L;;;;;N;;;;; 1414;CANADIAN SYLLABICS WOO;Lo;0;L;;;;;N;;;;; 1415;CANADIAN SYLLABICS WEST-CREE WOO;Lo;0;L;;;;;N;;;;; 1416;CANADIAN SYLLABICS NASKAPI WOO;Lo;0;L;;;;;N;;;;; 1417;CANADIAN SYLLABICS WA;Lo;0;L;;;;;N;;;;; 1418;CANADIAN SYLLABICS WEST-CREE WA;Lo;0;L;;;;;N;;;;; 1419;CANADIAN SYLLABICS WAA;Lo;0;L;;;;;N;;;;; 141A;CANADIAN SYLLABICS WEST-CREE WAA;Lo;0;L;;;;;N;;;;; 141B;CANADIAN SYLLABICS NASKAPI WAA;Lo;0;L;;;;;N;;;;; 141C;CANADIAN SYLLABICS AI;Lo;0;L;;;;;N;;;;; 141D;CANADIAN SYLLABICS Y-CREE W;Lo;0;L;;;;;N;;;;; 141E;CANADIAN SYLLABICS GLOTTAL STOP;Lo;0;L;;;;;N;;;;; 141F;CANADIAN SYLLABICS FINAL ACUTE;Lo;0;L;;;;;N;;;;; 1420;CANADIAN SYLLABICS FINAL GRAVE;Lo;0;L;;;;;N;;;;; 1421;CANADIAN SYLLABICS FINAL BOTTOM HALF RING;Lo;0;L;;;;;N;;;;; 1422;CANADIAN SYLLABICS FINAL TOP HALF RING;Lo;0;L;;;;;N;;;;; 1423;CANADIAN SYLLABICS FINAL RIGHT HALF RING;Lo;0;L;;;;;N;;;;; 1424;CANADIAN SYLLABICS FINAL RING;Lo;0;L;;;;;N;;;;; 1425;CANADIAN SYLLABICS FINAL DOUBLE ACUTE;Lo;0;L;;;;;N;;;;; 1426;CANADIAN SYLLABICS FINAL DOUBLE SHORT VERTICAL STROKES;Lo;0;L;;;;;N;;;;; 1427;CANADIAN SYLLABICS FINAL MIDDLE DOT;Lo;0;L;;;;;N;;;;; 1428;CANADIAN SYLLABICS FINAL SHORT HORIZONTAL STROKE;Lo;0;L;;;;;N;;;;; 1429;CANADIAN SYLLABICS FINAL PLUS;Lo;0;L;;;;;N;;;;; 142A;CANADIAN SYLLABICS FINAL DOWN TACK;Lo;0;L;;;;;N;;;;; 142B;CANADIAN SYLLABICS EN;Lo;0;L;;;;;N;;;;; 142C;CANADIAN SYLLABICS IN;Lo;0;L;;;;;N;;;;; 142D;CANADIAN SYLLABICS ON;Lo;0;L;;;;;N;;;;; 142E;CANADIAN SYLLABICS AN;Lo;0;L;;;;;N;;;;; 142F;CANADIAN SYLLABICS PE;Lo;0;L;;;;;N;;;;; 1430;CANADIAN SYLLABICS PAAI;Lo;0;L;;;;;N;;;;; 1431;CANADIAN SYLLABICS PI;Lo;0;L;;;;;N;;;;; 1432;CANADIAN SYLLABICS PII;Lo;0;L;;;;;N;;;;; 1433;CANADIAN SYLLABICS PO;Lo;0;L;;;;;N;;;;; 1434;CANADIAN SYLLABICS POO;Lo;0;L;;;;;N;;;;; 1435;CANADIAN SYLLABICS Y-CREE POO;Lo;0;L;;;;;N;;;;; 1436;CANADIAN SYLLABICS CARRIER HEE;Lo;0;L;;;;;N;;;;; 1437;CANADIAN SYLLABICS CARRIER HI;Lo;0;L;;;;;N;;;;; 1438;CANADIAN SYLLABICS PA;Lo;0;L;;;;;N;;;;; 1439;CANADIAN SYLLABICS PAA;Lo;0;L;;;;;N;;;;; 143A;CANADIAN SYLLABICS PWE;Lo;0;L;;;;;N;;;;; 143B;CANADIAN SYLLABICS WEST-CREE PWE;Lo;0;L;;;;;N;;;;; 143C;CANADIAN SYLLABICS PWI;Lo;0;L;;;;;N;;;;; 143D;CANADIAN SYLLABICS WEST-CREE PWI;Lo;0;L;;;;;N;;;;; 143E;CANADIAN SYLLABICS PWII;Lo;0;L;;;;;N;;;;; 143F;CANADIAN SYLLABICS WEST-CREE PWII;Lo;0;L;;;;;N;;;;; 1440;CANADIAN SYLLABICS PWO;Lo;0;L;;;;;N;;;;; 1441;CANADIAN SYLLABICS WEST-CREE PWO;Lo;0;L;;;;;N;;;;; 1442;CANADIAN SYLLABICS PWOO;Lo;0;L;;;;;N;;;;; 1443;CANADIAN SYLLABICS WEST-CREE PWOO;Lo;0;L;;;;;N;;;;; 1444;CANADIAN SYLLABICS PWA;Lo;0;L;;;;;N;;;;; 1445;CANADIAN SYLLABICS WEST-CREE PWA;Lo;0;L;;;;;N;;;;; 1446;CANADIAN SYLLABICS PWAA;Lo;0;L;;;;;N;;;;; 1447;CANADIAN SYLLABICS WEST-CREE PWAA;Lo;0;L;;;;;N;;;;; 1448;CANADIAN SYLLABICS Y-CREE PWAA;Lo;0;L;;;;;N;;;;; 1449;CANADIAN SYLLABICS P;Lo;0;L;;;;;N;;;;; 144A;CANADIAN SYLLABICS WEST-CREE P;Lo;0;L;;;;;N;;;;; 144B;CANADIAN SYLLABICS CARRIER H;Lo;0;L;;;;;N;;;;; 144C;CANADIAN SYLLABICS TE;Lo;0;L;;;;;N;;;;; 144D;CANADIAN SYLLABICS TAAI;Lo;0;L;;;;;N;;;;; 144E;CANADIAN SYLLABICS TI;Lo;0;L;;;;;N;;;;; 144F;CANADIAN SYLLABICS TII;Lo;0;L;;;;;N;;;;; 1450;CANADIAN SYLLABICS TO;Lo;0;L;;;;;N;;;;; 1451;CANADIAN SYLLABICS TOO;Lo;0;L;;;;;N;;;;; 1452;CANADIAN SYLLABICS Y-CREE TOO;Lo;0;L;;;;;N;;;;; 1453;CANADIAN SYLLABICS CARRIER DEE;Lo;0;L;;;;;N;;;;; 1454;CANADIAN SYLLABICS CARRIER DI;Lo;0;L;;;;;N;;;;; 1455;CANADIAN SYLLABICS TA;Lo;0;L;;;;;N;;;;; 1456;CANADIAN SYLLABICS TAA;Lo;0;L;;;;;N;;;;; 1457;CANADIAN SYLLABICS TWE;Lo;0;L;;;;;N;;;;; 1458;CANADIAN SYLLABICS WEST-CREE TWE;Lo;0;L;;;;;N;;;;; 1459;CANADIAN SYLLABICS TWI;Lo;0;L;;;;;N;;;;; 145A;CANADIAN SYLLABICS WEST-CREE TWI;Lo;0;L;;;;;N;;;;; 145B;CANADIAN SYLLABICS TWII;Lo;0;L;;;;;N;;;;; 145C;CANADIAN SYLLABICS WEST-CREE TWII;Lo;0;L;;;;;N;;;;; 145D;CANADIAN SYLLABICS TWO;Lo;0;L;;;;;N;;;;; 145E;CANADIAN SYLLABICS WEST-CREE TWO;Lo;0;L;;;;;N;;;;; 145F;CANADIAN SYLLABICS TWOO;Lo;0;L;;;;;N;;;;; 1460;CANADIAN SYLLABICS WEST-CREE TWOO;Lo;0;L;;;;;N;;;;; 1461;CANADIAN SYLLABICS TWA;Lo;0;L;;;;;N;;;;; 1462;CANADIAN SYLLABICS WEST-CREE TWA;Lo;0;L;;;;;N;;;;; 1463;CANADIAN SYLLABICS TWAA;Lo;0;L;;;;;N;;;;; 1464;CANADIAN SYLLABICS WEST-CREE TWAA;Lo;0;L;;;;;N;;;;; 1465;CANADIAN SYLLABICS NASKAPI TWAA;Lo;0;L;;;;;N;;;;; 1466;CANADIAN SYLLABICS T;Lo;0;L;;;;;N;;;;; 1467;CANADIAN SYLLABICS TTE;Lo;0;L;;;;;N;;;;; 1468;CANADIAN SYLLABICS TTI;Lo;0;L;;;;;N;;;;; 1469;CANADIAN SYLLABICS TTO;Lo;0;L;;;;;N;;;;; 146A;CANADIAN SYLLABICS TTA;Lo;0;L;;;;;N;;;;; 146B;CANADIAN SYLLABICS KE;Lo;0;L;;;;;N;;;;; 146C;CANADIAN SYLLABICS KAAI;Lo;0;L;;;;;N;;;;; 146D;CANADIAN SYLLABICS KI;Lo;0;L;;;;;N;;;;; 146E;CANADIAN SYLLABICS KII;Lo;0;L;;;;;N;;;;; 146F;CANADIAN SYLLABICS KO;Lo;0;L;;;;;N;;;;; 1470;CANADIAN SYLLABICS KOO;Lo;0;L;;;;;N;;;;; 1471;CANADIAN SYLLABICS Y-CREE KOO;Lo;0;L;;;;;N;;;;; 1472;CANADIAN SYLLABICS KA;Lo;0;L;;;;;N;;;;; 1473;CANADIAN SYLLABICS KAA;Lo;0;L;;;;;N;;;;; 1474;CANADIAN SYLLABICS KWE;Lo;0;L;;;;;N;;;;; 1475;CANADIAN SYLLABICS WEST-CREE KWE;Lo;0;L;;;;;N;;;;; 1476;CANADIAN SYLLABICS KWI;Lo;0;L;;;;;N;;;;; 1477;CANADIAN SYLLABICS WEST-CREE KWI;Lo;0;L;;;;;N;;;;; 1478;CANADIAN SYLLABICS KWII;Lo;0;L;;;;;N;;;;; 1479;CANADIAN SYLLABICS WEST-CREE KWII;Lo;0;L;;;;;N;;;;; 147A;CANADIAN SYLLABICS KWO;Lo;0;L;;;;;N;;;;; 147B;CANADIAN SYLLABICS WEST-CREE KWO;Lo;0;L;;;;;N;;;;; 147C;CANADIAN SYLLABICS KWOO;Lo;0;L;;;;;N;;;;; 147D;CANADIAN SYLLABICS WEST-CREE KWOO;Lo;0;L;;;;;N;;;;; 147E;CANADIAN SYLLABICS KWA;Lo;0;L;;;;;N;;;;; 147F;CANADIAN SYLLABICS WEST-CREE KWA;Lo;0;L;;;;;N;;;;; 1480;CANADIAN SYLLABICS KWAA;Lo;0;L;;;;;N;;;;; 1481;CANADIAN SYLLABICS WEST-CREE KWAA;Lo;0;L;;;;;N;;;;; 1482;CANADIAN SYLLABICS NASKAPI KWAA;Lo;0;L;;;;;N;;;;; 1483;CANADIAN SYLLABICS K;Lo;0;L;;;;;N;;;;; 1484;CANADIAN SYLLABICS KW;Lo;0;L;;;;;N;;;;; 1485;CANADIAN SYLLABICS SOUTH-SLAVEY KEH;Lo;0;L;;;;;N;;;;; 1486;CANADIAN SYLLABICS SOUTH-SLAVEY KIH;Lo;0;L;;;;;N;;;;; 1487;CANADIAN SYLLABICS SOUTH-SLAVEY KOH;Lo;0;L;;;;;N;;;;; 1488;CANADIAN SYLLABICS SOUTH-SLAVEY KAH;Lo;0;L;;;;;N;;;;; 1489;CANADIAN SYLLABICS CE;Lo;0;L;;;;;N;;;;; 148A;CANADIAN SYLLABICS CAAI;Lo;0;L;;;;;N;;;;; 148B;CANADIAN SYLLABICS CI;Lo;0;L;;;;;N;;;;; 148C;CANADIAN SYLLABICS CII;Lo;0;L;;;;;N;;;;; 148D;CANADIAN SYLLABICS CO;Lo;0;L;;;;;N;;;;; 148E;CANADIAN SYLLABICS COO;Lo;0;L;;;;;N;;;;; 148F;CANADIAN SYLLABICS Y-CREE COO;Lo;0;L;;;;;N;;;;; 1490;CANADIAN SYLLABICS CA;Lo;0;L;;;;;N;;;;; 1491;CANADIAN SYLLABICS CAA;Lo;0;L;;;;;N;;;;; 1492;CANADIAN SYLLABICS CWE;Lo;0;L;;;;;N;;;;; 1493;CANADIAN SYLLABICS WEST-CREE CWE;Lo;0;L;;;;;N;;;;; 1494;CANADIAN SYLLABICS CWI;Lo;0;L;;;;;N;;;;; 1495;CANADIAN SYLLABICS WEST-CREE CWI;Lo;0;L;;;;;N;;;;; 1496;CANADIAN SYLLABICS CWII;Lo;0;L;;;;;N;;;;; 1497;CANADIAN SYLLABICS WEST-CREE CWII;Lo;0;L;;;;;N;;;;; 1498;CANADIAN SYLLABICS CWO;Lo;0;L;;;;;N;;;;; 1499;CANADIAN SYLLABICS WEST-CREE CWO;Lo;0;L;;;;;N;;;;; 149A;CANADIAN SYLLABICS CWOO;Lo;0;L;;;;;N;;;;; 149B;CANADIAN SYLLABICS WEST-CREE CWOO;Lo;0;L;;;;;N;;;;; 149C;CANADIAN SYLLABICS CWA;Lo;0;L;;;;;N;;;;; 149D;CANADIAN SYLLABICS WEST-CREE CWA;Lo;0;L;;;;;N;;;;; 149E;CANADIAN SYLLABICS CWAA;Lo;0;L;;;;;N;;;;; 149F;CANADIAN SYLLABICS WEST-CREE CWAA;Lo;0;L;;;;;N;;;;; 14A0;CANADIAN SYLLABICS NASKAPI CWAA;Lo;0;L;;;;;N;;;;; 14A1;CANADIAN SYLLABICS C;Lo;0;L;;;;;N;;;;; 14A2;CANADIAN SYLLABICS SAYISI TH;Lo;0;L;;;;;N;;;;; 14A3;CANADIAN SYLLABICS ME;Lo;0;L;;;;;N;;;;; 14A4;CANADIAN SYLLABICS MAAI;Lo;0;L;;;;;N;;;;; 14A5;CANADIAN SYLLABICS MI;Lo;0;L;;;;;N;;;;; 14A6;CANADIAN SYLLABICS MII;Lo;0;L;;;;;N;;;;; 14A7;CANADIAN SYLLABICS MO;Lo;0;L;;;;;N;;;;; 14A8;CANADIAN SYLLABICS MOO;Lo;0;L;;;;;N;;;;; 14A9;CANADIAN SYLLABICS Y-CREE MOO;Lo;0;L;;;;;N;;;;; 14AA;CANADIAN SYLLABICS MA;Lo;0;L;;;;;N;;;;; 14AB;CANADIAN SYLLABICS MAA;Lo;0;L;;;;;N;;;;; 14AC;CANADIAN SYLLABICS MWE;Lo;0;L;;;;;N;;;;; 14AD;CANADIAN SYLLABICS WEST-CREE MWE;Lo;0;L;;;;;N;;;;; 14AE;CANADIAN SYLLABICS MWI;Lo;0;L;;;;;N;;;;; 14AF;CANADIAN SYLLABICS WEST-CREE MWI;Lo;0;L;;;;;N;;;;; 14B0;CANADIAN SYLLABICS MWII;Lo;0;L;;;;;N;;;;; 14B1;CANADIAN SYLLABICS WEST-CREE MWII;Lo;0;L;;;;;N;;;;; 14B2;CANADIAN SYLLABICS MWO;Lo;0;L;;;;;N;;;;; 14B3;CANADIAN SYLLABICS WEST-CREE MWO;Lo;0;L;;;;;N;;;;; 14B4;CANADIAN SYLLABICS MWOO;Lo;0;L;;;;;N;;;;; 14B5;CANADIAN SYLLABICS WEST-CREE MWOO;Lo;0;L;;;;;N;;;;; 14B6;CANADIAN SYLLABICS MWA;Lo;0;L;;;;;N;;;;; 14B7;CANADIAN SYLLABICS WEST-CREE MWA;Lo;0;L;;;;;N;;;;; 14B8;CANADIAN SYLLABICS MWAA;Lo;0;L;;;;;N;;;;; 14B9;CANADIAN SYLLABICS WEST-CREE MWAA;Lo;0;L;;;;;N;;;;; 14BA;CANADIAN SYLLABICS NASKAPI MWAA;Lo;0;L;;;;;N;;;;; 14BB;CANADIAN SYLLABICS M;Lo;0;L;;;;;N;;;;; 14BC;CANADIAN SYLLABICS WEST-CREE M;Lo;0;L;;;;;N;;;;; 14BD;CANADIAN SYLLABICS MH;Lo;0;L;;;;;N;;;;; 14BE;CANADIAN SYLLABICS ATHAPASCAN M;Lo;0;L;;;;;N;;;;; 14BF;CANADIAN SYLLABICS SAYISI M;Lo;0;L;;;;;N;;;;; 14C0;CANADIAN SYLLABICS NE;Lo;0;L;;;;;N;;;;; 14C1;CANADIAN SYLLABICS NAAI;Lo;0;L;;;;;N;;;;; 14C2;CANADIAN SYLLABICS NI;Lo;0;L;;;;;N;;;;; 14C3;CANADIAN SYLLABICS NII;Lo;0;L;;;;;N;;;;; 14C4;CANADIAN SYLLABICS NO;Lo;0;L;;;;;N;;;;; 14C5;CANADIAN SYLLABICS NOO;Lo;0;L;;;;;N;;;;; 14C6;CANADIAN SYLLABICS Y-CREE NOO;Lo;0;L;;;;;N;;;;; 14C7;CANADIAN SYLLABICS NA;Lo;0;L;;;;;N;;;;; 14C8;CANADIAN SYLLABICS NAA;Lo;0;L;;;;;N;;;;; 14C9;CANADIAN SYLLABICS NWE;Lo;0;L;;;;;N;;;;; 14CA;CANADIAN SYLLABICS WEST-CREE NWE;Lo;0;L;;;;;N;;;;; 14CB;CANADIAN SYLLABICS NWA;Lo;0;L;;;;;N;;;;; 14CC;CANADIAN SYLLABICS WEST-CREE NWA;Lo;0;L;;;;;N;;;;; 14CD;CANADIAN SYLLABICS NWAA;Lo;0;L;;;;;N;;;;; 14CE;CANADIAN SYLLABICS WEST-CREE NWAA;Lo;0;L;;;;;N;;;;; 14CF;CANADIAN SYLLABICS NASKAPI NWAA;Lo;0;L;;;;;N;;;;; 14D0;CANADIAN SYLLABICS N;Lo;0;L;;;;;N;;;;; 14D1;CANADIAN SYLLABICS CARRIER NG;Lo;0;L;;;;;N;;;;; 14D2;CANADIAN SYLLABICS NH;Lo;0;L;;;;;N;;;;; 14D3;CANADIAN SYLLABICS LE;Lo;0;L;;;;;N;;;;; 14D4;CANADIAN SYLLABICS LAAI;Lo;0;L;;;;;N;;;;; 14D5;CANADIAN SYLLABICS LI;Lo;0;L;;;;;N;;;;; 14D6;CANADIAN SYLLABICS LII;Lo;0;L;;;;;N;;;;; 14D7;CANADIAN SYLLABICS LO;Lo;0;L;;;;;N;;;;; 14D8;CANADIAN SYLLABICS LOO;Lo;0;L;;;;;N;;;;; 14D9;CANADIAN SYLLABICS Y-CREE LOO;Lo;0;L;;;;;N;;;;; 14DA;CANADIAN SYLLABICS LA;Lo;0;L;;;;;N;;;;; 14DB;CANADIAN SYLLABICS LAA;Lo;0;L;;;;;N;;;;; 14DC;CANADIAN SYLLABICS LWE;Lo;0;L;;;;;N;;;;; 14DD;CANADIAN SYLLABICS WEST-CREE LWE;Lo;0;L;;;;;N;;;;; 14DE;CANADIAN SYLLABICS LWI;Lo;0;L;;;;;N;;;;; 14DF;CANADIAN SYLLABICS WEST-CREE LWI;Lo;0;L;;;;;N;;;;; 14E0;CANADIAN SYLLABICS LWII;Lo;0;L;;;;;N;;;;; 14E1;CANADIAN SYLLABICS WEST-CREE LWII;Lo;0;L;;;;;N;;;;; 14E2;CANADIAN SYLLABICS LWO;Lo;0;L;;;;;N;;;;; 14E3;CANADIAN SYLLABICS WEST-CREE LWO;Lo;0;L;;;;;N;;;;; 14E4;CANADIAN SYLLABICS LWOO;Lo;0;L;;;;;N;;;;; 14E5;CANADIAN SYLLABICS WEST-CREE LWOO;Lo;0;L;;;;;N;;;;; 14E6;CANADIAN SYLLABICS LWA;Lo;0;L;;;;;N;;;;; 14E7;CANADIAN SYLLABICS WEST-CREE LWA;Lo;0;L;;;;;N;;;;; 14E8;CANADIAN SYLLABICS LWAA;Lo;0;L;;;;;N;;;;; 14E9;CANADIAN SYLLABICS WEST-CREE LWAA;Lo;0;L;;;;;N;;;;; 14EA;CANADIAN SYLLABICS L;Lo;0;L;;;;;N;;;;; 14EB;CANADIAN SYLLABICS WEST-CREE L;Lo;0;L;;;;;N;;;;; 14EC;CANADIAN SYLLABICS MEDIAL L;Lo;0;L;;;;;N;;;;; 14ED;CANADIAN SYLLABICS SE;Lo;0;L;;;;;N;;;;; 14EE;CANADIAN SYLLABICS SAAI;Lo;0;L;;;;;N;;;;; 14EF;CANADIAN SYLLABICS SI;Lo;0;L;;;;;N;;;;; 14F0;CANADIAN SYLLABICS SII;Lo;0;L;;;;;N;;;;; 14F1;CANADIAN SYLLABICS SO;Lo;0;L;;;;;N;;;;; 14F2;CANADIAN SYLLABICS SOO;Lo;0;L;;;;;N;;;;; 14F3;CANADIAN SYLLABICS Y-CREE SOO;Lo;0;L;;;;;N;;;;; 14F4;CANADIAN SYLLABICS SA;Lo;0;L;;;;;N;;;;; 14F5;CANADIAN SYLLABICS SAA;Lo;0;L;;;;;N;;;;; 14F6;CANADIAN SYLLABICS SWE;Lo;0;L;;;;;N;;;;; 14F7;CANADIAN SYLLABICS WEST-CREE SWE;Lo;0;L;;;;;N;;;;; 14F8;CANADIAN SYLLABICS SWI;Lo;0;L;;;;;N;;;;; 14F9;CANADIAN SYLLABICS WEST-CREE SWI;Lo;0;L;;;;;N;;;;; 14FA;CANADIAN SYLLABICS SWII;Lo;0;L;;;;;N;;;;; 14FB;CANADIAN SYLLABICS WEST-CREE SWII;Lo;0;L;;;;;N;;;;; 14FC;CANADIAN SYLLABICS SWO;Lo;0;L;;;;;N;;;;; 14FD;CANADIAN SYLLABICS WEST-CREE SWO;Lo;0;L;;;;;N;;;;; 14FE;CANADIAN SYLLABICS SWOO;Lo;0;L;;;;;N;;;;; 14FF;CANADIAN SYLLABICS WEST-CREE SWOO;Lo;0;L;;;;;N;;;;; 1500;CANADIAN SYLLABICS SWA;Lo;0;L;;;;;N;;;;; 1501;CANADIAN SYLLABICS WEST-CREE SWA;Lo;0;L;;;;;N;;;;; 1502;CANADIAN SYLLABICS SWAA;Lo;0;L;;;;;N;;;;; 1503;CANADIAN SYLLABICS WEST-CREE SWAA;Lo;0;L;;;;;N;;;;; 1504;CANADIAN SYLLABICS NASKAPI SWAA;Lo;0;L;;;;;N;;;;; 1505;CANADIAN SYLLABICS S;Lo;0;L;;;;;N;;;;; 1506;CANADIAN SYLLABICS ATHAPASCAN S;Lo;0;L;;;;;N;;;;; 1507;CANADIAN SYLLABICS SW;Lo;0;L;;;;;N;;;;; 1508;CANADIAN SYLLABICS BLACKFOOT S;Lo;0;L;;;;;N;;;;; 1509;CANADIAN SYLLABICS MOOSE-CREE SK;Lo;0;L;;;;;N;;;;; 150A;CANADIAN SYLLABICS NASKAPI SKW;Lo;0;L;;;;;N;;;;; 150B;CANADIAN SYLLABICS NASKAPI S-W;Lo;0;L;;;;;N;;;;; 150C;CANADIAN SYLLABICS NASKAPI SPWA;Lo;0;L;;;;;N;;;;; 150D;CANADIAN SYLLABICS NASKAPI STWA;Lo;0;L;;;;;N;;;;; 150E;CANADIAN SYLLABICS NASKAPI SKWA;Lo;0;L;;;;;N;;;;; 150F;CANADIAN SYLLABICS NASKAPI SCWA;Lo;0;L;;;;;N;;;;; 1510;CANADIAN SYLLABICS SHE;Lo;0;L;;;;;N;;;;; 1511;CANADIAN SYLLABICS SHI;Lo;0;L;;;;;N;;;;; 1512;CANADIAN SYLLABICS SHII;Lo;0;L;;;;;N;;;;; 1513;CANADIAN SYLLABICS SHO;Lo;0;L;;;;;N;;;;; 1514;CANADIAN SYLLABICS SHOO;Lo;0;L;;;;;N;;;;; 1515;CANADIAN SYLLABICS SHA;Lo;0;L;;;;;N;;;;; 1516;CANADIAN SYLLABICS SHAA;Lo;0;L;;;;;N;;;;; 1517;CANADIAN SYLLABICS SHWE;Lo;0;L;;;;;N;;;;; 1518;CANADIAN SYLLABICS WEST-CREE SHWE;Lo;0;L;;;;;N;;;;; 1519;CANADIAN SYLLABICS SHWI;Lo;0;L;;;;;N;;;;; 151A;CANADIAN SYLLABICS WEST-CREE SHWI;Lo;0;L;;;;;N;;;;; 151B;CANADIAN SYLLABICS SHWII;Lo;0;L;;;;;N;;;;; 151C;CANADIAN SYLLABICS WEST-CREE SHWII;Lo;0;L;;;;;N;;;;; 151D;CANADIAN SYLLABICS SHWO;Lo;0;L;;;;;N;;;;; 151E;CANADIAN SYLLABICS WEST-CREE SHWO;Lo;0;L;;;;;N;;;;; 151F;CANADIAN SYLLABICS SHWOO;Lo;0;L;;;;;N;;;;; 1520;CANADIAN SYLLABICS WEST-CREE SHWOO;Lo;0;L;;;;;N;;;;; 1521;CANADIAN SYLLABICS SHWA;Lo;0;L;;;;;N;;;;; 1522;CANADIAN SYLLABICS WEST-CREE SHWA;Lo;0;L;;;;;N;;;;; 1523;CANADIAN SYLLABICS SHWAA;Lo;0;L;;;;;N;;;;; 1524;CANADIAN SYLLABICS WEST-CREE SHWAA;Lo;0;L;;;;;N;;;;; 1525;CANADIAN SYLLABICS SH;Lo;0;L;;;;;N;;;;; 1526;CANADIAN SYLLABICS YE;Lo;0;L;;;;;N;;;;; 1527;CANADIAN SYLLABICS YAAI;Lo;0;L;;;;;N;;;;; 1528;CANADIAN SYLLABICS YI;Lo;0;L;;;;;N;;;;; 1529;CANADIAN SYLLABICS YII;Lo;0;L;;;;;N;;;;; 152A;CANADIAN SYLLABICS YO;Lo;0;L;;;;;N;;;;; 152B;CANADIAN SYLLABICS YOO;Lo;0;L;;;;;N;;;;; 152C;CANADIAN SYLLABICS Y-CREE YOO;Lo;0;L;;;;;N;;;;; 152D;CANADIAN SYLLABICS YA;Lo;0;L;;;;;N;;;;; 152E;CANADIAN SYLLABICS YAA;Lo;0;L;;;;;N;;;;; 152F;CANADIAN SYLLABICS YWE;Lo;0;L;;;;;N;;;;; 1530;CANADIAN SYLLABICS WEST-CREE YWE;Lo;0;L;;;;;N;;;;; 1531;CANADIAN SYLLABICS YWI;Lo;0;L;;;;;N;;;;; 1532;CANADIAN SYLLABICS WEST-CREE YWI;Lo;0;L;;;;;N;;;;; 1533;CANADIAN SYLLABICS YWII;Lo;0;L;;;;;N;;;;; 1534;CANADIAN SYLLABICS WEST-CREE YWII;Lo;0;L;;;;;N;;;;; 1535;CANADIAN SYLLABICS YWO;Lo;0;L;;;;;N;;;;; 1536;CANADIAN SYLLABICS WEST-CREE YWO;Lo;0;L;;;;;N;;;;; 1537;CANADIAN SYLLABICS YWOO;Lo;0;L;;;;;N;;;;; 1538;CANADIAN SYLLABICS WEST-CREE YWOO;Lo;0;L;;;;;N;;;;; 1539;CANADIAN SYLLABICS YWA;Lo;0;L;;;;;N;;;;; 153A;CANADIAN SYLLABICS WEST-CREE YWA;Lo;0;L;;;;;N;;;;; 153B;CANADIAN SYLLABICS YWAA;Lo;0;L;;;;;N;;;;; 153C;CANADIAN SYLLABICS WEST-CREE YWAA;Lo;0;L;;;;;N;;;;; 153D;CANADIAN SYLLABICS NASKAPI YWAA;Lo;0;L;;;;;N;;;;; 153E;CANADIAN SYLLABICS Y;Lo;0;L;;;;;N;;;;; 153F;CANADIAN SYLLABICS BIBLE-CREE Y;Lo;0;L;;;;;N;;;;; 1540;CANADIAN SYLLABICS WEST-CREE Y;Lo;0;L;;;;;N;;;;; 1541;CANADIAN SYLLABICS SAYISI YI;Lo;0;L;;;;;N;;;;; 1542;CANADIAN SYLLABICS RE;Lo;0;L;;;;;N;;;;; 1543;CANADIAN SYLLABICS R-CREE RE;Lo;0;L;;;;;N;;;;; 1544;CANADIAN SYLLABICS WEST-CREE LE;Lo;0;L;;;;;N;;;;; 1545;CANADIAN SYLLABICS RAAI;Lo;0;L;;;;;N;;;;; 1546;CANADIAN SYLLABICS RI;Lo;0;L;;;;;N;;;;; 1547;CANADIAN SYLLABICS RII;Lo;0;L;;;;;N;;;;; 1548;CANADIAN SYLLABICS RO;Lo;0;L;;;;;N;;;;; 1549;CANADIAN SYLLABICS ROO;Lo;0;L;;;;;N;;;;; 154A;CANADIAN SYLLABICS WEST-CREE LO;Lo;0;L;;;;;N;;;;; 154B;CANADIAN SYLLABICS RA;Lo;0;L;;;;;N;;;;; 154C;CANADIAN SYLLABICS RAA;Lo;0;L;;;;;N;;;;; 154D;CANADIAN SYLLABICS WEST-CREE LA;Lo;0;L;;;;;N;;;;; 154E;CANADIAN SYLLABICS RWAA;Lo;0;L;;;;;N;;;;; 154F;CANADIAN SYLLABICS WEST-CREE RWAA;Lo;0;L;;;;;N;;;;; 1550;CANADIAN SYLLABICS R;Lo;0;L;;;;;N;;;;; 1551;CANADIAN SYLLABICS WEST-CREE R;Lo;0;L;;;;;N;;;;; 1552;CANADIAN SYLLABICS MEDIAL R;Lo;0;L;;;;;N;;;;; 1553;CANADIAN SYLLABICS FE;Lo;0;L;;;;;N;;;;; 1554;CANADIAN SYLLABICS FAAI;Lo;0;L;;;;;N;;;;; 1555;CANADIAN SYLLABICS FI;Lo;0;L;;;;;N;;;;; 1556;CANADIAN SYLLABICS FII;Lo;0;L;;;;;N;;;;; 1557;CANADIAN SYLLABICS FO;Lo;0;L;;;;;N;;;;; 1558;CANADIAN SYLLABICS FOO;Lo;0;L;;;;;N;;;;; 1559;CANADIAN SYLLABICS FA;Lo;0;L;;;;;N;;;;; 155A;CANADIAN SYLLABICS FAA;Lo;0;L;;;;;N;;;;; 155B;CANADIAN SYLLABICS FWAA;Lo;0;L;;;;;N;;;;; 155C;CANADIAN SYLLABICS WEST-CREE FWAA;Lo;0;L;;;;;N;;;;; 155D;CANADIAN SYLLABICS F;Lo;0;L;;;;;N;;;;; 155E;CANADIAN SYLLABICS THE;Lo;0;L;;;;;N;;;;; 155F;CANADIAN SYLLABICS N-CREE THE;Lo;0;L;;;;;N;;;;; 1560;CANADIAN SYLLABICS THI;Lo;0;L;;;;;N;;;;; 1561;CANADIAN SYLLABICS N-CREE THI;Lo;0;L;;;;;N;;;;; 1562;CANADIAN SYLLABICS THII;Lo;0;L;;;;;N;;;;; 1563;CANADIAN SYLLABICS N-CREE THII;Lo;0;L;;;;;N;;;;; 1564;CANADIAN SYLLABICS THO;Lo;0;L;;;;;N;;;;; 1565;CANADIAN SYLLABICS THOO;Lo;0;L;;;;;N;;;;; 1566;CANADIAN SYLLABICS THA;Lo;0;L;;;;;N;;;;; 1567;CANADIAN SYLLABICS THAA;Lo;0;L;;;;;N;;;;; 1568;CANADIAN SYLLABICS THWAA;Lo;0;L;;;;;N;;;;; 1569;CANADIAN SYLLABICS WEST-CREE THWAA;Lo;0;L;;;;;N;;;;; 156A;CANADIAN SYLLABICS TH;Lo;0;L;;;;;N;;;;; 156B;CANADIAN SYLLABICS TTHE;Lo;0;L;;;;;N;;;;; 156C;CANADIAN SYLLABICS TTHI;Lo;0;L;;;;;N;;;;; 156D;CANADIAN SYLLABICS TTHO;Lo;0;L;;;;;N;;;;; 156E;CANADIAN SYLLABICS TTHA;Lo;0;L;;;;;N;;;;; 156F;CANADIAN SYLLABICS TTH;Lo;0;L;;;;;N;;;;; 1570;CANADIAN SYLLABICS TYE;Lo;0;L;;;;;N;;;;; 1571;CANADIAN SYLLABICS TYI;Lo;0;L;;;;;N;;;;; 1572;CANADIAN SYLLABICS TYO;Lo;0;L;;;;;N;;;;; 1573;CANADIAN SYLLABICS TYA;Lo;0;L;;;;;N;;;;; 1574;CANADIAN SYLLABICS NUNAVIK HE;Lo;0;L;;;;;N;;;;; 1575;CANADIAN SYLLABICS NUNAVIK HI;Lo;0;L;;;;;N;;;;; 1576;CANADIAN SYLLABICS NUNAVIK HII;Lo;0;L;;;;;N;;;;; 1577;CANADIAN SYLLABICS NUNAVIK HO;Lo;0;L;;;;;N;;;;; 1578;CANADIAN SYLLABICS NUNAVIK HOO;Lo;0;L;;;;;N;;;;; 1579;CANADIAN SYLLABICS NUNAVIK HA;Lo;0;L;;;;;N;;;;; 157A;CANADIAN SYLLABICS NUNAVIK HAA;Lo;0;L;;;;;N;;;;; 157B;CANADIAN SYLLABICS NUNAVIK H;Lo;0;L;;;;;N;;;;; 157C;CANADIAN SYLLABICS NUNAVUT H;Lo;0;L;;;;;N;;;;; 157D;CANADIAN SYLLABICS HK;Lo;0;L;;;;;N;;;;; 157E;CANADIAN SYLLABICS QAAI;Lo;0;L;;;;;N;;;;; 157F;CANADIAN SYLLABICS QI;Lo;0;L;;;;;N;;;;; 1580;CANADIAN SYLLABICS QII;Lo;0;L;;;;;N;;;;; 1581;CANADIAN SYLLABICS QO;Lo;0;L;;;;;N;;;;; 1582;CANADIAN SYLLABICS QOO;Lo;0;L;;;;;N;;;;; 1583;CANADIAN SYLLABICS QA;Lo;0;L;;;;;N;;;;; 1584;CANADIAN SYLLABICS QAA;Lo;0;L;;;;;N;;;;; 1585;CANADIAN SYLLABICS Q;Lo;0;L;;;;;N;;;;; 1586;CANADIAN SYLLABICS TLHE;Lo;0;L;;;;;N;;;;; 1587;CANADIAN SYLLABICS TLHI;Lo;0;L;;;;;N;;;;; 1588;CANADIAN SYLLABICS TLHO;Lo;0;L;;;;;N;;;;; 1589;CANADIAN SYLLABICS TLHA;Lo;0;L;;;;;N;;;;; 158A;CANADIAN SYLLABICS WEST-CREE RE;Lo;0;L;;;;;N;;;;; 158B;CANADIAN SYLLABICS WEST-CREE RI;Lo;0;L;;;;;N;;;;; 158C;CANADIAN SYLLABICS WEST-CREE RO;Lo;0;L;;;;;N;;;;; 158D;CANADIAN SYLLABICS WEST-CREE RA;Lo;0;L;;;;;N;;;;; 158E;CANADIAN SYLLABICS NGAAI;Lo;0;L;;;;;N;;;;; 158F;CANADIAN SYLLABICS NGI;Lo;0;L;;;;;N;;;;; 1590;CANADIAN SYLLABICS NGII;Lo;0;L;;;;;N;;;;; 1591;CANADIAN SYLLABICS NGO;Lo;0;L;;;;;N;;;;; 1592;CANADIAN SYLLABICS NGOO;Lo;0;L;;;;;N;;;;; 1593;CANADIAN SYLLABICS NGA;Lo;0;L;;;;;N;;;;; 1594;CANADIAN SYLLABICS NGAA;Lo;0;L;;;;;N;;;;; 1595;CANADIAN SYLLABICS NG;Lo;0;L;;;;;N;;;;; 1596;CANADIAN SYLLABICS NNG;Lo;0;L;;;;;N;;;;; 1597;CANADIAN SYLLABICS SAYISI SHE;Lo;0;L;;;;;N;;;;; 1598;CANADIAN SYLLABICS SAYISI SHI;Lo;0;L;;;;;N;;;;; 1599;CANADIAN SYLLABICS SAYISI SHO;Lo;0;L;;;;;N;;;;; 159A;CANADIAN SYLLABICS SAYISI SHA;Lo;0;L;;;;;N;;;;; 159B;CANADIAN SYLLABICS WOODS-CREE THE;Lo;0;L;;;;;N;;;;; 159C;CANADIAN SYLLABICS WOODS-CREE THI;Lo;0;L;;;;;N;;;;; 159D;CANADIAN SYLLABICS WOODS-CREE THO;Lo;0;L;;;;;N;;;;; 159E;CANADIAN SYLLABICS WOODS-CREE THA;Lo;0;L;;;;;N;;;;; 159F;CANADIAN SYLLABICS WOODS-CREE TH;Lo;0;L;;;;;N;;;;; 15A0;CANADIAN SYLLABICS LHI;Lo;0;L;;;;;N;;;;; 15A1;CANADIAN SYLLABICS LHII;Lo;0;L;;;;;N;;;;; 15A2;CANADIAN SYLLABICS LHO;Lo;0;L;;;;;N;;;;; 15A3;CANADIAN SYLLABICS LHOO;Lo;0;L;;;;;N;;;;; 15A4;CANADIAN SYLLABICS LHA;Lo;0;L;;;;;N;;;;; 15A5;CANADIAN SYLLABICS LHAA;Lo;0;L;;;;;N;;;;; 15A6;CANADIAN SYLLABICS LH;Lo;0;L;;;;;N;;;;; 15A7;CANADIAN SYLLABICS TH-CREE THE;Lo;0;L;;;;;N;;;;; 15A8;CANADIAN SYLLABICS TH-CREE THI;Lo;0;L;;;;;N;;;;; 15A9;CANADIAN SYLLABICS TH-CREE THII;Lo;0;L;;;;;N;;;;; 15AA;CANADIAN SYLLABICS TH-CREE THO;Lo;0;L;;;;;N;;;;; 15AB;CANADIAN SYLLABICS TH-CREE THOO;Lo;0;L;;;;;N;;;;; 15AC;CANADIAN SYLLABICS TH-CREE THA;Lo;0;L;;;;;N;;;;; 15AD;CANADIAN SYLLABICS TH-CREE THAA;Lo;0;L;;;;;N;;;;; 15AE;CANADIAN SYLLABICS TH-CREE TH;Lo;0;L;;;;;N;;;;; 15AF;CANADIAN SYLLABICS AIVILIK B;Lo;0;L;;;;;N;;;;; 15B0;CANADIAN SYLLABICS BLACKFOOT E;Lo;0;L;;;;;N;;;;; 15B1;CANADIAN SYLLABICS BLACKFOOT I;Lo;0;L;;;;;N;;;;; 15B2;CANADIAN SYLLABICS BLACKFOOT O;Lo;0;L;;;;;N;;;;; 15B3;CANADIAN SYLLABICS BLACKFOOT A;Lo;0;L;;;;;N;;;;; 15B4;CANADIAN SYLLABICS BLACKFOOT WE;Lo;0;L;;;;;N;;;;; 15B5;CANADIAN SYLLABICS BLACKFOOT WI;Lo;0;L;;;;;N;;;;; 15B6;CANADIAN SYLLABICS BLACKFOOT WO;Lo;0;L;;;;;N;;;;; 15B7;CANADIAN SYLLABICS BLACKFOOT WA;Lo;0;L;;;;;N;;;;; 15B8;CANADIAN SYLLABICS BLACKFOOT NE;Lo;0;L;;;;;N;;;;; 15B9;CANADIAN SYLLABICS BLACKFOOT NI;Lo;0;L;;;;;N;;;;; 15BA;CANADIAN SYLLABICS BLACKFOOT NO;Lo;0;L;;;;;N;;;;; 15BB;CANADIAN SYLLABICS BLACKFOOT NA;Lo;0;L;;;;;N;;;;; 15BC;CANADIAN SYLLABICS BLACKFOOT KE;Lo;0;L;;;;;N;;;;; 15BD;CANADIAN SYLLABICS BLACKFOOT KI;Lo;0;L;;;;;N;;;;; 15BE;CANADIAN SYLLABICS BLACKFOOT KO;Lo;0;L;;;;;N;;;;; 15BF;CANADIAN SYLLABICS BLACKFOOT KA;Lo;0;L;;;;;N;;;;; 15C0;CANADIAN SYLLABICS SAYISI HE;Lo;0;L;;;;;N;;;;; 15C1;CANADIAN SYLLABICS SAYISI HI;Lo;0;L;;;;;N;;;;; 15C2;CANADIAN SYLLABICS SAYISI HO;Lo;0;L;;;;;N;;;;; 15C3;CANADIAN SYLLABICS SAYISI HA;Lo;0;L;;;;;N;;;;; 15C4;CANADIAN SYLLABICS CARRIER GHU;Lo;0;L;;;;;N;;;;; 15C5;CANADIAN SYLLABICS CARRIER GHO;Lo;0;L;;;;;N;;;;; 15C6;CANADIAN SYLLABICS CARRIER GHE;Lo;0;L;;;;;N;;;;; 15C7;CANADIAN SYLLABICS CARRIER GHEE;Lo;0;L;;;;;N;;;;; 15C8;CANADIAN SYLLABICS CARRIER GHI;Lo;0;L;;;;;N;;;;; 15C9;CANADIAN SYLLABICS CARRIER GHA;Lo;0;L;;;;;N;;;;; 15CA;CANADIAN SYLLABICS CARRIER RU;Lo;0;L;;;;;N;;;;; 15CB;CANADIAN SYLLABICS CARRIER RO;Lo;0;L;;;;;N;;;;; 15CC;CANADIAN SYLLABICS CARRIER RE;Lo;0;L;;;;;N;;;;; 15CD;CANADIAN SYLLABICS CARRIER REE;Lo;0;L;;;;;N;;;;; 15CE;CANADIAN SYLLABICS CARRIER RI;Lo;0;L;;;;;N;;;;; 15CF;CANADIAN SYLLABICS CARRIER RA;Lo;0;L;;;;;N;;;;; 15D0;CANADIAN SYLLABICS CARRIER WU;Lo;0;L;;;;;N;;;;; 15D1;CANADIAN SYLLABICS CARRIER WO;Lo;0;L;;;;;N;;;;; 15D2;CANADIAN SYLLABICS CARRIER WE;Lo;0;L;;;;;N;;;;; 15D3;CANADIAN SYLLABICS CARRIER WEE;Lo;0;L;;;;;N;;;;; 15D4;CANADIAN SYLLABICS CARRIER WI;Lo;0;L;;;;;N;;;;; 15D5;CANADIAN SYLLABICS CARRIER WA;Lo;0;L;;;;;N;;;;; 15D6;CANADIAN SYLLABICS CARRIER HWU;Lo;0;L;;;;;N;;;;; 15D7;CANADIAN SYLLABICS CARRIER HWO;Lo;0;L;;;;;N;;;;; 15D8;CANADIAN SYLLABICS CARRIER HWE;Lo;0;L;;;;;N;;;;; 15D9;CANADIAN SYLLABICS CARRIER HWEE;Lo;0;L;;;;;N;;;;; 15DA;CANADIAN SYLLABICS CARRIER HWI;Lo;0;L;;;;;N;;;;; 15DB;CANADIAN SYLLABICS CARRIER HWA;Lo;0;L;;;;;N;;;;; 15DC;CANADIAN SYLLABICS CARRIER THU;Lo;0;L;;;;;N;;;;; 15DD;CANADIAN SYLLABICS CARRIER THO;Lo;0;L;;;;;N;;;;; 15DE;CANADIAN SYLLABICS CARRIER THE;Lo;0;L;;;;;N;;;;; 15DF;CANADIAN SYLLABICS CARRIER THEE;Lo;0;L;;;;;N;;;;; 15E0;CANADIAN SYLLABICS CARRIER THI;Lo;0;L;;;;;N;;;;; 15E1;CANADIAN SYLLABICS CARRIER THA;Lo;0;L;;;;;N;;;;; 15E2;CANADIAN SYLLABICS CARRIER TTU;Lo;0;L;;;;;N;;;;; 15E3;CANADIAN SYLLABICS CARRIER TTO;Lo;0;L;;;;;N;;;;; 15E4;CANADIAN SYLLABICS CARRIER TTE;Lo;0;L;;;;;N;;;;; 15E5;CANADIAN SYLLABICS CARRIER TTEE;Lo;0;L;;;;;N;;;;; 15E6;CANADIAN SYLLABICS CARRIER TTI;Lo;0;L;;;;;N;;;;; 15E7;CANADIAN SYLLABICS CARRIER TTA;Lo;0;L;;;;;N;;;;; 15E8;CANADIAN SYLLABICS CARRIER PU;Lo;0;L;;;;;N;;;;; 15E9;CANADIAN SYLLABICS CARRIER PO;Lo;0;L;;;;;N;;;;; 15EA;CANADIAN SYLLABICS CARRIER PE;Lo;0;L;;;;;N;;;;; 15EB;CANADIAN SYLLABICS CARRIER PEE;Lo;0;L;;;;;N;;;;; 15EC;CANADIAN SYLLABICS CARRIER PI;Lo;0;L;;;;;N;;;;; 15ED;CANADIAN SYLLABICS CARRIER PA;Lo;0;L;;;;;N;;;;; 15EE;CANADIAN SYLLABICS CARRIER P;Lo;0;L;;;;;N;;;;; 15EF;CANADIAN SYLLABICS CARRIER GU;Lo;0;L;;;;;N;;;;; 15F0;CANADIAN SYLLABICS CARRIER GO;Lo;0;L;;;;;N;;;;; 15F1;CANADIAN SYLLABICS CARRIER GE;Lo;0;L;;;;;N;;;;; 15F2;CANADIAN SYLLABICS CARRIER GEE;Lo;0;L;;;;;N;;;;; 15F3;CANADIAN SYLLABICS CARRIER GI;Lo;0;L;;;;;N;;;;; 15F4;CANADIAN SYLLABICS CARRIER GA;Lo;0;L;;;;;N;;;;; 15F5;CANADIAN SYLLABICS CARRIER KHU;Lo;0;L;;;;;N;;;;; 15F6;CANADIAN SYLLABICS CARRIER KHO;Lo;0;L;;;;;N;;;;; 15F7;CANADIAN SYLLABICS CARRIER KHE;Lo;0;L;;;;;N;;;;; 15F8;CANADIAN SYLLABICS CARRIER KHEE;Lo;0;L;;;;;N;;;;; 15F9;CANADIAN SYLLABICS CARRIER KHI;Lo;0;L;;;;;N;;;;; 15FA;CANADIAN SYLLABICS CARRIER KHA;Lo;0;L;;;;;N;;;;; 15FB;CANADIAN SYLLABICS CARRIER KKU;Lo;0;L;;;;;N;;;;; 15FC;CANADIAN SYLLABICS CARRIER KKO;Lo;0;L;;;;;N;;;;; 15FD;CANADIAN SYLLABICS CARRIER KKE;Lo;0;L;;;;;N;;;;; 15FE;CANADIAN SYLLABICS CARRIER KKEE;Lo;0;L;;;;;N;;;;; 15FF;CANADIAN SYLLABICS CARRIER KKI;Lo;0;L;;;;;N;;;;; 1600;CANADIAN SYLLABICS CARRIER KKA;Lo;0;L;;;;;N;;;;; 1601;CANADIAN SYLLABICS CARRIER KK;Lo;0;L;;;;;N;;;;; 1602;CANADIAN SYLLABICS CARRIER NU;Lo;0;L;;;;;N;;;;; 1603;CANADIAN SYLLABICS CARRIER NO;Lo;0;L;;;;;N;;;;; 1604;CANADIAN SYLLABICS CARRIER NE;Lo;0;L;;;;;N;;;;; 1605;CANADIAN SYLLABICS CARRIER NEE;Lo;0;L;;;;;N;;;;; 1606;CANADIAN SYLLABICS CARRIER NI;Lo;0;L;;;;;N;;;;; 1607;CANADIAN SYLLABICS CARRIER NA;Lo;0;L;;;;;N;;;;; 1608;CANADIAN SYLLABICS CARRIER MU;Lo;0;L;;;;;N;;;;; 1609;CANADIAN SYLLABICS CARRIER MO;Lo;0;L;;;;;N;;;;; 160A;CANADIAN SYLLABICS CARRIER ME;Lo;0;L;;;;;N;;;;; 160B;CANADIAN SYLLABICS CARRIER MEE;Lo;0;L;;;;;N;;;;; 160C;CANADIAN SYLLABICS CARRIER MI;Lo;0;L;;;;;N;;;;; 160D;CANADIAN SYLLABICS CARRIER MA;Lo;0;L;;;;;N;;;;; 160E;CANADIAN SYLLABICS CARRIER YU;Lo;0;L;;;;;N;;;;; 160F;CANADIAN SYLLABICS CARRIER YO;Lo;0;L;;;;;N;;;;; 1610;CANADIAN SYLLABICS CARRIER YE;Lo;0;L;;;;;N;;;;; 1611;CANADIAN SYLLABICS CARRIER YEE;Lo;0;L;;;;;N;;;;; 1612;CANADIAN SYLLABICS CARRIER YI;Lo;0;L;;;;;N;;;;; 1613;CANADIAN SYLLABICS CARRIER YA;Lo;0;L;;;;;N;;;;; 1614;CANADIAN SYLLABICS CARRIER JU;Lo;0;L;;;;;N;;;;; 1615;CANADIAN SYLLABICS SAYISI JU;Lo;0;L;;;;;N;;;;; 1616;CANADIAN SYLLABICS CARRIER JO;Lo;0;L;;;;;N;;;;; 1617;CANADIAN SYLLABICS CARRIER JE;Lo;0;L;;;;;N;;;;; 1618;CANADIAN SYLLABICS CARRIER JEE;Lo;0;L;;;;;N;;;;; 1619;CANADIAN SYLLABICS CARRIER JI;Lo;0;L;;;;;N;;;;; 161A;CANADIAN SYLLABICS SAYISI JI;Lo;0;L;;;;;N;;;;; 161B;CANADIAN SYLLABICS CARRIER JA;Lo;0;L;;;;;N;;;;; 161C;CANADIAN SYLLABICS CARRIER JJU;Lo;0;L;;;;;N;;;;; 161D;CANADIAN SYLLABICS CARRIER JJO;Lo;0;L;;;;;N;;;;; 161E;CANADIAN SYLLABICS CARRIER JJE;Lo;0;L;;;;;N;;;;; 161F;CANADIAN SYLLABICS CARRIER JJEE;Lo;0;L;;;;;N;;;;; 1620;CANADIAN SYLLABICS CARRIER JJI;Lo;0;L;;;;;N;;;;; 1621;CANADIAN SYLLABICS CARRIER JJA;Lo;0;L;;;;;N;;;;; 1622;CANADIAN SYLLABICS CARRIER LU;Lo;0;L;;;;;N;;;;; 1623;CANADIAN SYLLABICS CARRIER LO;Lo;0;L;;;;;N;;;;; 1624;CANADIAN SYLLABICS CARRIER LE;Lo;0;L;;;;;N;;;;; 1625;CANADIAN SYLLABICS CARRIER LEE;Lo;0;L;;;;;N;;;;; 1626;CANADIAN SYLLABICS CARRIER LI;Lo;0;L;;;;;N;;;;; 1627;CANADIAN SYLLABICS CARRIER LA;Lo;0;L;;;;;N;;;;; 1628;CANADIAN SYLLABICS CARRIER DLU;Lo;0;L;;;;;N;;;;; 1629;CANADIAN SYLLABICS CARRIER DLO;Lo;0;L;;;;;N;;;;; 162A;CANADIAN SYLLABICS CARRIER DLE;Lo;0;L;;;;;N;;;;; 162B;CANADIAN SYLLABICS CARRIER DLEE;Lo;0;L;;;;;N;;;;; 162C;CANADIAN SYLLABICS CARRIER DLI;Lo;0;L;;;;;N;;;;; 162D;CANADIAN SYLLABICS CARRIER DLA;Lo;0;L;;;;;N;;;;; 162E;CANADIAN SYLLABICS CARRIER LHU;Lo;0;L;;;;;N;;;;; 162F;CANADIAN SYLLABICS CARRIER LHO;Lo;0;L;;;;;N;;;;; 1630;CANADIAN SYLLABICS CARRIER LHE;Lo;0;L;;;;;N;;;;; 1631;CANADIAN SYLLABICS CARRIER LHEE;Lo;0;L;;;;;N;;;;; 1632;CANADIAN SYLLABICS CARRIER LHI;Lo;0;L;;;;;N;;;;; 1633;CANADIAN SYLLABICS CARRIER LHA;Lo;0;L;;;;;N;;;;; 1634;CANADIAN SYLLABICS CARRIER TLHU;Lo;0;L;;;;;N;;;;; 1635;CANADIAN SYLLABICS CARRIER TLHO;Lo;0;L;;;;;N;;;;; 1636;CANADIAN SYLLABICS CARRIER TLHE;Lo;0;L;;;;;N;;;;; 1637;CANADIAN SYLLABICS CARRIER TLHEE;Lo;0;L;;;;;N;;;;; 1638;CANADIAN SYLLABICS CARRIER TLHI;Lo;0;L;;;;;N;;;;; 1639;CANADIAN SYLLABICS CARRIER TLHA;Lo;0;L;;;;;N;;;;; 163A;CANADIAN SYLLABICS CARRIER TLU;Lo;0;L;;;;;N;;;;; 163B;CANADIAN SYLLABICS CARRIER TLO;Lo;0;L;;;;;N;;;;; 163C;CANADIAN SYLLABICS CARRIER TLE;Lo;0;L;;;;;N;;;;; 163D;CANADIAN SYLLABICS CARRIER TLEE;Lo;0;L;;;;;N;;;;; 163E;CANADIAN SYLLABICS CARRIER TLI;Lo;0;L;;;;;N;;;;; 163F;CANADIAN SYLLABICS CARRIER TLA;Lo;0;L;;;;;N;;;;; 1640;CANADIAN SYLLABICS CARRIER ZU;Lo;0;L;;;;;N;;;;; 1641;CANADIAN SYLLABICS CARRIER ZO;Lo;0;L;;;;;N;;;;; 1642;CANADIAN SYLLABICS CARRIER ZE;Lo;0;L;;;;;N;;;;; 1643;CANADIAN SYLLABICS CARRIER ZEE;Lo;0;L;;;;;N;;;;; 1644;CANADIAN SYLLABICS CARRIER ZI;Lo;0;L;;;;;N;;;;; 1645;CANADIAN SYLLABICS CARRIER ZA;Lo;0;L;;;;;N;;;;; 1646;CANADIAN SYLLABICS CARRIER Z;Lo;0;L;;;;;N;;;;; 1647;CANADIAN SYLLABICS CARRIER INITIAL Z;Lo;0;L;;;;;N;;;;; 1648;CANADIAN SYLLABICS CARRIER DZU;Lo;0;L;;;;;N;;;;; 1649;CANADIAN SYLLABICS CARRIER DZO;Lo;0;L;;;;;N;;;;; 164A;CANADIAN SYLLABICS CARRIER DZE;Lo;0;L;;;;;N;;;;; 164B;CANADIAN SYLLABICS CARRIER DZEE;Lo;0;L;;;;;N;;;;; 164C;CANADIAN SYLLABICS CARRIER DZI;Lo;0;L;;;;;N;;;;; 164D;CANADIAN SYLLABICS CARRIER DZA;Lo;0;L;;;;;N;;;;; 164E;CANADIAN SYLLABICS CARRIER SU;Lo;0;L;;;;;N;;;;; 164F;CANADIAN SYLLABICS CARRIER SO;Lo;0;L;;;;;N;;;;; 1650;CANADIAN SYLLABICS CARRIER SE;Lo;0;L;;;;;N;;;;; 1651;CANADIAN SYLLABICS CARRIER SEE;Lo;0;L;;;;;N;;;;; 1652;CANADIAN SYLLABICS CARRIER SI;Lo;0;L;;;;;N;;;;; 1653;CANADIAN SYLLABICS CARRIER SA;Lo;0;L;;;;;N;;;;; 1654;CANADIAN SYLLABICS CARRIER SHU;Lo;0;L;;;;;N;;;;; 1655;CANADIAN SYLLABICS CARRIER SHO;Lo;0;L;;;;;N;;;;; 1656;CANADIAN SYLLABICS CARRIER SHE;Lo;0;L;;;;;N;;;;; 1657;CANADIAN SYLLABICS CARRIER SHEE;Lo;0;L;;;;;N;;;;; 1658;CANADIAN SYLLABICS CARRIER SHI;Lo;0;L;;;;;N;;;;; 1659;CANADIAN SYLLABICS CARRIER SHA;Lo;0;L;;;;;N;;;;; 165A;CANADIAN SYLLABICS CARRIER SH;Lo;0;L;;;;;N;;;;; 165B;CANADIAN SYLLABICS CARRIER TSU;Lo;0;L;;;;;N;;;;; 165C;CANADIAN SYLLABICS CARRIER TSO;Lo;0;L;;;;;N;;;;; 165D;CANADIAN SYLLABICS CARRIER TSE;Lo;0;L;;;;;N;;;;; 165E;CANADIAN SYLLABICS CARRIER TSEE;Lo;0;L;;;;;N;;;;; 165F;CANADIAN SYLLABICS CARRIER TSI;Lo;0;L;;;;;N;;;;; 1660;CANADIAN SYLLABICS CARRIER TSA;Lo;0;L;;;;;N;;;;; 1661;CANADIAN SYLLABICS CARRIER CHU;Lo;0;L;;;;;N;;;;; 1662;CANADIAN SYLLABICS CARRIER CHO;Lo;0;L;;;;;N;;;;; 1663;CANADIAN SYLLABICS CARRIER CHE;Lo;0;L;;;;;N;;;;; 1664;CANADIAN SYLLABICS CARRIER CHEE;Lo;0;L;;;;;N;;;;; 1665;CANADIAN SYLLABICS CARRIER CHI;Lo;0;L;;;;;N;;;;; 1666;CANADIAN SYLLABICS CARRIER CHA;Lo;0;L;;;;;N;;;;; 1667;CANADIAN SYLLABICS CARRIER TTSU;Lo;0;L;;;;;N;;;;; 1668;CANADIAN SYLLABICS CARRIER TTSO;Lo;0;L;;;;;N;;;;; 1669;CANADIAN SYLLABICS CARRIER TTSE;Lo;0;L;;;;;N;;;;; 166A;CANADIAN SYLLABICS CARRIER TTSEE;Lo;0;L;;;;;N;;;;; 166B;CANADIAN SYLLABICS CARRIER TTSI;Lo;0;L;;;;;N;;;;; 166C;CANADIAN SYLLABICS CARRIER TTSA;Lo;0;L;;;;;N;;;;; 166D;CANADIAN SYLLABICS CHI SIGN;Po;0;L;;;;;N;;;;; 166E;CANADIAN SYLLABICS FULL STOP;Po;0;L;;;;;N;;;;; 166F;CANADIAN SYLLABICS QAI;Lo;0;L;;;;;N;;;;; 1670;CANADIAN SYLLABICS NGAI;Lo;0;L;;;;;N;;;;; 1671;CANADIAN SYLLABICS NNGI;Lo;0;L;;;;;N;;;;; 1672;CANADIAN SYLLABICS NNGII;Lo;0;L;;;;;N;;;;; 1673;CANADIAN SYLLABICS NNGO;Lo;0;L;;;;;N;;;;; 1674;CANADIAN SYLLABICS NNGOO;Lo;0;L;;;;;N;;;;; 1675;CANADIAN SYLLABICS NNGA;Lo;0;L;;;;;N;;;;; 1676;CANADIAN SYLLABICS NNGAA;Lo;0;L;;;;;N;;;;; 1677;CANADIAN SYLLABICS WOODS-CREE THWEE;Lo;0;L;;;;;N;;;;; 1678;CANADIAN SYLLABICS WOODS-CREE THWI;Lo;0;L;;;;;N;;;;; 1679;CANADIAN SYLLABICS WOODS-CREE THWII;Lo;0;L;;;;;N;;;;; 167A;CANADIAN SYLLABICS WOODS-CREE THWO;Lo;0;L;;;;;N;;;;; 167B;CANADIAN SYLLABICS WOODS-CREE THWOO;Lo;0;L;;;;;N;;;;; 167C;CANADIAN SYLLABICS WOODS-CREE THWA;Lo;0;L;;;;;N;;;;; 167D;CANADIAN SYLLABICS WOODS-CREE THWAA;Lo;0;L;;;;;N;;;;; 167E;CANADIAN SYLLABICS WOODS-CREE FINAL TH;Lo;0;L;;;;;N;;;;; 167F;CANADIAN SYLLABICS BLACKFOOT W;Lo;0;L;;;;;N;;;;; 1680;OGHAM SPACE MARK;Zs;0;WS;;;;;N;;;;; 1681;OGHAM LETTER BEITH;Lo;0;L;;;;;N;;;;; 1682;OGHAM LETTER LUIS;Lo;0;L;;;;;N;;;;; 1683;OGHAM LETTER FEARN;Lo;0;L;;;;;N;;;;; 1684;OGHAM LETTER SAIL;Lo;0;L;;;;;N;;;;; 1685;OGHAM LETTER NION;Lo;0;L;;;;;N;;;;; 1686;OGHAM LETTER UATH;Lo;0;L;;;;;N;;;;; 1687;OGHAM LETTER DAIR;Lo;0;L;;;;;N;;;;; 1688;OGHAM LETTER TINNE;Lo;0;L;;;;;N;;;;; 1689;OGHAM LETTER COLL;Lo;0;L;;;;;N;;;;; 168A;OGHAM LETTER CEIRT;Lo;0;L;;;;;N;;;;; 168B;OGHAM LETTER MUIN;Lo;0;L;;;;;N;;;;; 168C;OGHAM LETTER GORT;Lo;0;L;;;;;N;;;;; 168D;OGHAM LETTER NGEADAL;Lo;0;L;;;;;N;;;;; 168E;OGHAM LETTER STRAIF;Lo;0;L;;;;;N;;;;; 168F;OGHAM LETTER RUIS;Lo;0;L;;;;;N;;;;; 1690;OGHAM LETTER AILM;Lo;0;L;;;;;N;;;;; 1691;OGHAM LETTER ONN;Lo;0;L;;;;;N;;;;; 1692;OGHAM LETTER UR;Lo;0;L;;;;;N;;;;; 1693;OGHAM LETTER EADHADH;Lo;0;L;;;;;N;;;;; 1694;OGHAM LETTER IODHADH;Lo;0;L;;;;;N;;;;; 1695;OGHAM LETTER EABHADH;Lo;0;L;;;;;N;;;;; 1696;OGHAM LETTER OR;Lo;0;L;;;;;N;;;;; 1697;OGHAM LETTER UILLEANN;Lo;0;L;;;;;N;;;;; 1698;OGHAM LETTER IFIN;Lo;0;L;;;;;N;;;;; 1699;OGHAM LETTER EAMHANCHOLL;Lo;0;L;;;;;N;;;;; 169A;OGHAM LETTER PEITH;Lo;0;L;;;;;N;;;;; 169B;OGHAM FEATHER MARK;Ps;0;ON;;;;;Y;;;;; 169C;OGHAM REVERSED FEATHER MARK;Pe;0;ON;;;;;Y;;;;; 16A0;RUNIC LETTER FEHU FEOH FE F;Lo;0;L;;;;;N;;;;; 16A1;RUNIC LETTER V;Lo;0;L;;;;;N;;;;; 16A2;RUNIC LETTER URUZ UR U;Lo;0;L;;;;;N;;;;; 16A3;RUNIC LETTER YR;Lo;0;L;;;;;N;;;;; 16A4;RUNIC LETTER Y;Lo;0;L;;;;;N;;;;; 16A5;RUNIC LETTER W;Lo;0;L;;;;;N;;;;; 16A6;RUNIC LETTER THURISAZ THURS THORN;Lo;0;L;;;;;N;;;;; 16A7;RUNIC LETTER ETH;Lo;0;L;;;;;N;;;;; 16A8;RUNIC LETTER ANSUZ A;Lo;0;L;;;;;N;;;;; 16A9;RUNIC LETTER OS O;Lo;0;L;;;;;N;;;;; 16AA;RUNIC LETTER AC A;Lo;0;L;;;;;N;;;;; 16AB;RUNIC LETTER AESC;Lo;0;L;;;;;N;;;;; 16AC;RUNIC LETTER LONG-BRANCH-OSS O;Lo;0;L;;;;;N;;;;; 16AD;RUNIC LETTER SHORT-TWIG-OSS O;Lo;0;L;;;;;N;;;;; 16AE;RUNIC LETTER O;Lo;0;L;;;;;N;;;;; 16AF;RUNIC LETTER OE;Lo;0;L;;;;;N;;;;; 16B0;RUNIC LETTER ON;Lo;0;L;;;;;N;;;;; 16B1;RUNIC LETTER RAIDO RAD REID R;Lo;0;L;;;;;N;;;;; 16B2;RUNIC LETTER KAUNA;Lo;0;L;;;;;N;;;;; 16B3;RUNIC LETTER CEN;Lo;0;L;;;;;N;;;;; 16B4;RUNIC LETTER KAUN K;Lo;0;L;;;;;N;;;;; 16B5;RUNIC LETTER G;Lo;0;L;;;;;N;;;;; 16B6;RUNIC LETTER ENG;Lo;0;L;;;;;N;;;;; 16B7;RUNIC LETTER GEBO GYFU G;Lo;0;L;;;;;N;;;;; 16B8;RUNIC LETTER GAR;Lo;0;L;;;;;N;;;;; 16B9;RUNIC LETTER WUNJO WYNN W;Lo;0;L;;;;;N;;;;; 16BA;RUNIC LETTER HAGLAZ H;Lo;0;L;;;;;N;;;;; 16BB;RUNIC LETTER HAEGL H;Lo;0;L;;;;;N;;;;; 16BC;RUNIC LETTER LONG-BRANCH-HAGALL H;Lo;0;L;;;;;N;;;;; 16BD;RUNIC LETTER SHORT-TWIG-HAGALL H;Lo;0;L;;;;;N;;;;; 16BE;RUNIC LETTER NAUDIZ NYD NAUD N;Lo;0;L;;;;;N;;;;; 16BF;RUNIC LETTER SHORT-TWIG-NAUD N;Lo;0;L;;;;;N;;;;; 16C0;RUNIC LETTER DOTTED-N;Lo;0;L;;;;;N;;;;; 16C1;RUNIC LETTER ISAZ IS ISS I;Lo;0;L;;;;;N;;;;; 16C2;RUNIC LETTER E;Lo;0;L;;;;;N;;;;; 16C3;RUNIC LETTER JERAN J;Lo;0;L;;;;;N;;;;; 16C4;RUNIC LETTER GER;Lo;0;L;;;;;N;;;;; 16C5;RUNIC LETTER LONG-BRANCH-AR AE;Lo;0;L;;;;;N;;;;; 16C6;RUNIC LETTER SHORT-TWIG-AR A;Lo;0;L;;;;;N;;;;; 16C7;RUNIC LETTER IWAZ EOH;Lo;0;L;;;;;N;;;;; 16C8;RUNIC LETTER PERTHO PEORTH P;Lo;0;L;;;;;N;;;;; 16C9;RUNIC LETTER ALGIZ EOLHX;Lo;0;L;;;;;N;;;;; 16CA;RUNIC LETTER SOWILO S;Lo;0;L;;;;;N;;;;; 16CB;RUNIC LETTER SIGEL LONG-BRANCH-SOL S;Lo;0;L;;;;;N;;;;; 16CC;RUNIC LETTER SHORT-TWIG-SOL S;Lo;0;L;;;;;N;;;;; 16CD;RUNIC LETTER C;Lo;0;L;;;;;N;;;;; 16CE;RUNIC LETTER Z;Lo;0;L;;;;;N;;;;; 16CF;RUNIC LETTER TIWAZ TIR TYR T;Lo;0;L;;;;;N;;;;; 16D0;RUNIC LETTER SHORT-TWIG-TYR T;Lo;0;L;;;;;N;;;;; 16D1;RUNIC LETTER D;Lo;0;L;;;;;N;;;;; 16D2;RUNIC LETTER BERKANAN BEORC BJARKAN B;Lo;0;L;;;;;N;;;;; 16D3;RUNIC LETTER SHORT-TWIG-BJARKAN B;Lo;0;L;;;;;N;;;;; 16D4;RUNIC LETTER DOTTED-P;Lo;0;L;;;;;N;;;;; 16D5;RUNIC LETTER OPEN-P;Lo;0;L;;;;;N;;;;; 16D6;RUNIC LETTER EHWAZ EH E;Lo;0;L;;;;;N;;;;; 16D7;RUNIC LETTER MANNAZ MAN M;Lo;0;L;;;;;N;;;;; 16D8;RUNIC LETTER LONG-BRANCH-MADR M;Lo;0;L;;;;;N;;;;; 16D9;RUNIC LETTER SHORT-TWIG-MADR M;Lo;0;L;;;;;N;;;;; 16DA;RUNIC LETTER LAUKAZ LAGU LOGR L;Lo;0;L;;;;;N;;;;; 16DB;RUNIC LETTER DOTTED-L;Lo;0;L;;;;;N;;;;; 16DC;RUNIC LETTER INGWAZ;Lo;0;L;;;;;N;;;;; 16DD;RUNIC LETTER ING;Lo;0;L;;;;;N;;;;; 16DE;RUNIC LETTER DAGAZ DAEG D;Lo;0;L;;;;;N;;;;; 16DF;RUNIC LETTER OTHALAN ETHEL O;Lo;0;L;;;;;N;;;;; 16E0;RUNIC LETTER EAR;Lo;0;L;;;;;N;;;;; 16E1;RUNIC LETTER IOR;Lo;0;L;;;;;N;;;;; 16E2;RUNIC LETTER CWEORTH;Lo;0;L;;;;;N;;;;; 16E3;RUNIC LETTER CALC;Lo;0;L;;;;;N;;;;; 16E4;RUNIC LETTER CEALC;Lo;0;L;;;;;N;;;;; 16E5;RUNIC LETTER STAN;Lo;0;L;;;;;N;;;;; 16E6;RUNIC LETTER LONG-BRANCH-YR;Lo;0;L;;;;;N;;;;; 16E7;RUNIC LETTER SHORT-TWIG-YR;Lo;0;L;;;;;N;;;;; 16E8;RUNIC LETTER ICELANDIC-YR;Lo;0;L;;;;;N;;;;; 16E9;RUNIC LETTER Q;Lo;0;L;;;;;N;;;;; 16EA;RUNIC LETTER X;Lo;0;L;;;;;N;;;;; 16EB;RUNIC SINGLE PUNCTUATION;Po;0;L;;;;;N;;;;; 16EC;RUNIC MULTIPLE PUNCTUATION;Po;0;L;;;;;N;;;;; 16ED;RUNIC CROSS PUNCTUATION;Po;0;L;;;;;N;;;;; 16EE;RUNIC ARLAUG SYMBOL;Nl;0;L;;;;17;N;;;;; 16EF;RUNIC TVIMADUR SYMBOL;Nl;0;L;;;;18;N;;;;; 16F0;RUNIC BELGTHOR SYMBOL;Nl;0;L;;;;19;N;;;;; 16F1;RUNIC LETTER K;Lo;0;L;;;;;N;;;;; 16F2;RUNIC LETTER SH;Lo;0;L;;;;;N;;;;; 16F3;RUNIC LETTER OO;Lo;0;L;;;;;N;;;;; 16F4;RUNIC LETTER FRANKS CASKET OS;Lo;0;L;;;;;N;;;;; 16F5;RUNIC LETTER FRANKS CASKET IS;Lo;0;L;;;;;N;;;;; 16F6;RUNIC LETTER FRANKS CASKET EH;Lo;0;L;;;;;N;;;;; 16F7;RUNIC LETTER FRANKS CASKET AC;Lo;0;L;;;;;N;;;;; 16F8;RUNIC LETTER FRANKS CASKET AESC;Lo;0;L;;;;;N;;;;; 1700;TAGALOG LETTER A;Lo;0;L;;;;;N;;;;; 1701;TAGALOG LETTER I;Lo;0;L;;;;;N;;;;; 1702;TAGALOG LETTER U;Lo;0;L;;;;;N;;;;; 1703;TAGALOG LETTER KA;Lo;0;L;;;;;N;;;;; 1704;TAGALOG LETTER GA;Lo;0;L;;;;;N;;;;; 1705;TAGALOG LETTER NGA;Lo;0;L;;;;;N;;;;; 1706;TAGALOG LETTER TA;Lo;0;L;;;;;N;;;;; 1707;TAGALOG LETTER DA;Lo;0;L;;;;;N;;;;; 1708;TAGALOG LETTER NA;Lo;0;L;;;;;N;;;;; 1709;TAGALOG LETTER PA;Lo;0;L;;;;;N;;;;; 170A;TAGALOG LETTER BA;Lo;0;L;;;;;N;;;;; 170B;TAGALOG LETTER MA;Lo;0;L;;;;;N;;;;; 170C;TAGALOG LETTER YA;Lo;0;L;;;;;N;;;;; 170E;TAGALOG LETTER LA;Lo;0;L;;;;;N;;;;; 170F;TAGALOG LETTER WA;Lo;0;L;;;;;N;;;;; 1710;TAGALOG LETTER SA;Lo;0;L;;;;;N;;;;; 1711;TAGALOG LETTER HA;Lo;0;L;;;;;N;;;;; 1712;TAGALOG VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; 1713;TAGALOG VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 1714;TAGALOG SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 1720;HANUNOO LETTER A;Lo;0;L;;;;;N;;;;; 1721;HANUNOO LETTER I;Lo;0;L;;;;;N;;;;; 1722;HANUNOO LETTER U;Lo;0;L;;;;;N;;;;; 1723;HANUNOO LETTER KA;Lo;0;L;;;;;N;;;;; 1724;HANUNOO LETTER GA;Lo;0;L;;;;;N;;;;; 1725;HANUNOO LETTER NGA;Lo;0;L;;;;;N;;;;; 1726;HANUNOO LETTER TA;Lo;0;L;;;;;N;;;;; 1727;HANUNOO LETTER DA;Lo;0;L;;;;;N;;;;; 1728;HANUNOO LETTER NA;Lo;0;L;;;;;N;;;;; 1729;HANUNOO LETTER PA;Lo;0;L;;;;;N;;;;; 172A;HANUNOO LETTER BA;Lo;0;L;;;;;N;;;;; 172B;HANUNOO LETTER MA;Lo;0;L;;;;;N;;;;; 172C;HANUNOO LETTER YA;Lo;0;L;;;;;N;;;;; 172D;HANUNOO LETTER RA;Lo;0;L;;;;;N;;;;; 172E;HANUNOO LETTER LA;Lo;0;L;;;;;N;;;;; 172F;HANUNOO LETTER WA;Lo;0;L;;;;;N;;;;; 1730;HANUNOO LETTER SA;Lo;0;L;;;;;N;;;;; 1731;HANUNOO LETTER HA;Lo;0;L;;;;;N;;;;; 1732;HANUNOO VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; 1733;HANUNOO VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 1734;HANUNOO SIGN PAMUDPOD;Mn;9;NSM;;;;;N;;;;; 1735;PHILIPPINE SINGLE PUNCTUATION;Po;0;L;;;;;N;;;;; 1736;PHILIPPINE DOUBLE PUNCTUATION;Po;0;L;;;;;N;;;;; 1740;BUHID LETTER A;Lo;0;L;;;;;N;;;;; 1741;BUHID LETTER I;Lo;0;L;;;;;N;;;;; 1742;BUHID LETTER U;Lo;0;L;;;;;N;;;;; 1743;BUHID LETTER KA;Lo;0;L;;;;;N;;;;; 1744;BUHID LETTER GA;Lo;0;L;;;;;N;;;;; 1745;BUHID LETTER NGA;Lo;0;L;;;;;N;;;;; 1746;BUHID LETTER TA;Lo;0;L;;;;;N;;;;; 1747;BUHID LETTER DA;Lo;0;L;;;;;N;;;;; 1748;BUHID LETTER NA;Lo;0;L;;;;;N;;;;; 1749;BUHID LETTER PA;Lo;0;L;;;;;N;;;;; 174A;BUHID LETTER BA;Lo;0;L;;;;;N;;;;; 174B;BUHID LETTER MA;Lo;0;L;;;;;N;;;;; 174C;BUHID LETTER YA;Lo;0;L;;;;;N;;;;; 174D;BUHID LETTER RA;Lo;0;L;;;;;N;;;;; 174E;BUHID LETTER LA;Lo;0;L;;;;;N;;;;; 174F;BUHID LETTER WA;Lo;0;L;;;;;N;;;;; 1750;BUHID LETTER SA;Lo;0;L;;;;;N;;;;; 1751;BUHID LETTER HA;Lo;0;L;;;;;N;;;;; 1752;BUHID VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; 1753;BUHID VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 1760;TAGBANWA LETTER A;Lo;0;L;;;;;N;;;;; 1761;TAGBANWA LETTER I;Lo;0;L;;;;;N;;;;; 1762;TAGBANWA LETTER U;Lo;0;L;;;;;N;;;;; 1763;TAGBANWA LETTER KA;Lo;0;L;;;;;N;;;;; 1764;TAGBANWA LETTER GA;Lo;0;L;;;;;N;;;;; 1765;TAGBANWA LETTER NGA;Lo;0;L;;;;;N;;;;; 1766;TAGBANWA LETTER TA;Lo;0;L;;;;;N;;;;; 1767;TAGBANWA LETTER DA;Lo;0;L;;;;;N;;;;; 1768;TAGBANWA LETTER NA;Lo;0;L;;;;;N;;;;; 1769;TAGBANWA LETTER PA;Lo;0;L;;;;;N;;;;; 176A;TAGBANWA LETTER BA;Lo;0;L;;;;;N;;;;; 176B;TAGBANWA LETTER MA;Lo;0;L;;;;;N;;;;; 176C;TAGBANWA LETTER YA;Lo;0;L;;;;;N;;;;; 176E;TAGBANWA LETTER LA;Lo;0;L;;;;;N;;;;; 176F;TAGBANWA LETTER WA;Lo;0;L;;;;;N;;;;; 1770;TAGBANWA LETTER SA;Lo;0;L;;;;;N;;;;; 1772;TAGBANWA VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; 1773;TAGBANWA VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 1780;KHMER LETTER KA;Lo;0;L;;;;;N;;;;; 1781;KHMER LETTER KHA;Lo;0;L;;;;;N;;;;; 1782;KHMER LETTER KO;Lo;0;L;;;;;N;;;;; 1783;KHMER LETTER KHO;Lo;0;L;;;;;N;;;;; 1784;KHMER LETTER NGO;Lo;0;L;;;;;N;;;;; 1785;KHMER LETTER CA;Lo;0;L;;;;;N;;;;; 1786;KHMER LETTER CHA;Lo;0;L;;;;;N;;;;; 1787;KHMER LETTER CO;Lo;0;L;;;;;N;;;;; 1788;KHMER LETTER CHO;Lo;0;L;;;;;N;;;;; 1789;KHMER LETTER NYO;Lo;0;L;;;;;N;;;;; 178A;KHMER LETTER DA;Lo;0;L;;;;;N;;;;; 178B;KHMER LETTER TTHA;Lo;0;L;;;;;N;;;;; 178C;KHMER LETTER DO;Lo;0;L;;;;;N;;;;; 178D;KHMER LETTER TTHO;Lo;0;L;;;;;N;;;;; 178E;KHMER LETTER NNO;Lo;0;L;;;;;N;;;;; 178F;KHMER LETTER TA;Lo;0;L;;;;;N;;;;; 1790;KHMER LETTER THA;Lo;0;L;;;;;N;;;;; 1791;KHMER LETTER TO;Lo;0;L;;;;;N;;;;; 1792;KHMER LETTER THO;Lo;0;L;;;;;N;;;;; 1793;KHMER LETTER NO;Lo;0;L;;;;;N;;;;; 1794;KHMER LETTER BA;Lo;0;L;;;;;N;;;;; 1795;KHMER LETTER PHA;Lo;0;L;;;;;N;;;;; 1796;KHMER LETTER PO;Lo;0;L;;;;;N;;;;; 1797;KHMER LETTER PHO;Lo;0;L;;;;;N;;;;; 1798;KHMER LETTER MO;Lo;0;L;;;;;N;;;;; 1799;KHMER LETTER YO;Lo;0;L;;;;;N;;;;; 179A;KHMER LETTER RO;Lo;0;L;;;;;N;;;;; 179B;KHMER LETTER LO;Lo;0;L;;;;;N;;;;; 179C;KHMER LETTER VO;Lo;0;L;;;;;N;;;;; 179D;KHMER LETTER SHA;Lo;0;L;;;;;N;;;;; 179E;KHMER LETTER SSO;Lo;0;L;;;;;N;;;;; 179F;KHMER LETTER SA;Lo;0;L;;;;;N;;;;; 17A0;KHMER LETTER HA;Lo;0;L;;;;;N;;;;; 17A1;KHMER LETTER LA;Lo;0;L;;;;;N;;;;; 17A2;KHMER LETTER QA;Lo;0;L;;;;;N;;;;; 17A3;KHMER INDEPENDENT VOWEL QAQ;Lo;0;L;;;;;N;;;;; 17A4;KHMER INDEPENDENT VOWEL QAA;Lo;0;L;;;;;N;;;;; 17A5;KHMER INDEPENDENT VOWEL QI;Lo;0;L;;;;;N;;;;; 17A6;KHMER INDEPENDENT VOWEL QII;Lo;0;L;;;;;N;;;;; 17A7;KHMER INDEPENDENT VOWEL QU;Lo;0;L;;;;;N;;;;; 17A8;KHMER INDEPENDENT VOWEL QUK;Lo;0;L;;;;;N;;;;; 17A9;KHMER INDEPENDENT VOWEL QUU;Lo;0;L;;;;;N;;;;; 17AA;KHMER INDEPENDENT VOWEL QUUV;Lo;0;L;;;;;N;;;;; 17AB;KHMER INDEPENDENT VOWEL RY;Lo;0;L;;;;;N;;;;; 17AC;KHMER INDEPENDENT VOWEL RYY;Lo;0;L;;;;;N;;;;; 17AD;KHMER INDEPENDENT VOWEL LY;Lo;0;L;;;;;N;;;;; 17AE;KHMER INDEPENDENT VOWEL LYY;Lo;0;L;;;;;N;;;;; 17AF;KHMER INDEPENDENT VOWEL QE;Lo;0;L;;;;;N;;;;; 17B0;KHMER INDEPENDENT VOWEL QAI;Lo;0;L;;;;;N;;;;; 17B1;KHMER INDEPENDENT VOWEL QOO TYPE ONE;Lo;0;L;;;;;N;;;;; 17B2;KHMER INDEPENDENT VOWEL QOO TYPE TWO;Lo;0;L;;;;;N;;;;; 17B3;KHMER INDEPENDENT VOWEL QAU;Lo;0;L;;;;;N;;;;; 17B4;KHMER VOWEL INHERENT AQ;Mn;0;NSM;;;;;N;;;;; 17B5;KHMER VOWEL INHERENT AA;Mn;0;NSM;;;;;N;;;;; 17B6;KHMER VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 17B7;KHMER VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; 17B8;KHMER VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; 17B9;KHMER VOWEL SIGN Y;Mn;0;NSM;;;;;N;;;;; 17BA;KHMER VOWEL SIGN YY;Mn;0;NSM;;;;;N;;;;; 17BB;KHMER VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 17BC;KHMER VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 17BD;KHMER VOWEL SIGN UA;Mn;0;NSM;;;;;N;;;;; 17BE;KHMER VOWEL SIGN OE;Mc;0;L;;;;;N;;;;; 17BF;KHMER VOWEL SIGN YA;Mc;0;L;;;;;N;;;;; 17C0;KHMER VOWEL SIGN IE;Mc;0;L;;;;;N;;;;; 17C1;KHMER VOWEL SIGN E;Mc;0;L;;;;;N;;;;; 17C2;KHMER VOWEL SIGN AE;Mc;0;L;;;;;N;;;;; 17C3;KHMER VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; 17C4;KHMER VOWEL SIGN OO;Mc;0;L;;;;;N;;;;; 17C5;KHMER VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; 17C6;KHMER SIGN NIKAHIT;Mn;0;NSM;;;;;N;;;;; 17C7;KHMER SIGN REAHMUK;Mc;0;L;;;;;N;;;;; 17C8;KHMER SIGN YUUKALEAPINTU;Mc;0;L;;;;;N;;;;; 17C9;KHMER SIGN MUUSIKATOAN;Mn;0;NSM;;;;;N;;;;; 17CA;KHMER SIGN TRIISAP;Mn;0;NSM;;;;;N;;;;; 17CB;KHMER SIGN BANTOC;Mn;0;NSM;;;;;N;;;;; 17CC;KHMER SIGN ROBAT;Mn;0;NSM;;;;;N;;;;; 17CD;KHMER SIGN TOANDAKHIAT;Mn;0;NSM;;;;;N;;;;; 17CE;KHMER SIGN KAKABAT;Mn;0;NSM;;;;;N;;;;; 17CF;KHMER SIGN AHSDA;Mn;0;NSM;;;;;N;;;;; 17D0;KHMER SIGN SAMYOK SANNYA;Mn;0;NSM;;;;;N;;;;; 17D1;KHMER SIGN VIRIAM;Mn;0;NSM;;;;;N;;;;; 17D2;KHMER SIGN COENG;Mn;9;NSM;;;;;N;;;;; 17D3;KHMER SIGN BATHAMASAT;Mn;0;NSM;;;;;N;;;;; 17D4;KHMER SIGN KHAN;Po;0;L;;;;;N;;;;; 17D5;KHMER SIGN BARIYOOSAN;Po;0;L;;;;;N;;;;; 17D6;KHMER SIGN CAMNUC PII KUUH;Po;0;L;;;;;N;;;;; 17D7;KHMER SIGN LEK TOO;Lm;0;L;;;;;N;;;;; 17D8;KHMER SIGN BEYYAL;Po;0;L;;;;;N;;;;; 17D9;KHMER SIGN PHNAEK MUAN;Po;0;L;;;;;N;;;;; 17DA;KHMER SIGN KOOMUUT;Po;0;L;;;;;N;;;;; 17DB;KHMER CURRENCY SYMBOL RIEL;Sc;0;ET;;;;;N;;;;; 17DC;KHMER SIGN AVAKRAHASANYA;Lo;0;L;;;;;N;;;;; 17DD;KHMER SIGN ATTHACAN;Mn;230;NSM;;;;;N;;;;; 17E0;KHMER DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 17E1;KHMER DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 17E2;KHMER DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 17E3;KHMER DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 17E4;KHMER DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 17E5;KHMER DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 17E6;KHMER DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 17E7;KHMER DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 17E8;KHMER DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 17E9;KHMER DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 17F0;KHMER SYMBOL LEK ATTAK SON;No;0;ON;;;;0;N;;;;; 17F1;KHMER SYMBOL LEK ATTAK MUOY;No;0;ON;;;;1;N;;;;; 17F2;KHMER SYMBOL LEK ATTAK PII;No;0;ON;;;;2;N;;;;; 17F3;KHMER SYMBOL LEK ATTAK BEI;No;0;ON;;;;3;N;;;;; 17F4;KHMER SYMBOL LEK ATTAK BUON;No;0;ON;;;;4;N;;;;; 17F5;KHMER SYMBOL LEK ATTAK PRAM;No;0;ON;;;;5;N;;;;; 17F6;KHMER SYMBOL LEK ATTAK PRAM-MUOY;No;0;ON;;;;6;N;;;;; 17F7;KHMER SYMBOL LEK ATTAK PRAM-PII;No;0;ON;;;;7;N;;;;; 17F8;KHMER SYMBOL LEK ATTAK PRAM-BEI;No;0;ON;;;;8;N;;;;; 17F9;KHMER SYMBOL LEK ATTAK PRAM-BUON;No;0;ON;;;;9;N;;;;; 1800;MONGOLIAN BIRGA;Po;0;ON;;;;;N;;;;; 1801;MONGOLIAN ELLIPSIS;Po;0;ON;;;;;N;;;;; 1802;MONGOLIAN COMMA;Po;0;ON;;;;;N;;;;; 1803;MONGOLIAN FULL STOP;Po;0;ON;;;;;N;;;;; 1804;MONGOLIAN COLON;Po;0;ON;;;;;N;;;;; 1805;MONGOLIAN FOUR DOTS;Po;0;ON;;;;;N;;;;; 1806;MONGOLIAN TODO SOFT HYPHEN;Pd;0;ON;;;;;N;;;;; 1807;MONGOLIAN SIBE SYLLABLE BOUNDARY MARKER;Po;0;ON;;;;;N;;;;; 1808;MONGOLIAN MANCHU COMMA;Po;0;ON;;;;;N;;;;; 1809;MONGOLIAN MANCHU FULL STOP;Po;0;ON;;;;;N;;;;; 180A;MONGOLIAN NIRUGU;Po;0;ON;;;;;N;;;;; 180B;MONGOLIAN FREE VARIATION SELECTOR ONE;Mn;0;NSM;;;;;N;;;;; 180C;MONGOLIAN FREE VARIATION SELECTOR TWO;Mn;0;NSM;;;;;N;;;;; 180D;MONGOLIAN FREE VARIATION SELECTOR THREE;Mn;0;NSM;;;;;N;;;;; 180E;MONGOLIAN VOWEL SEPARATOR;Cf;0;BN;;;;;N;;;;; 1810;MONGOLIAN DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 1811;MONGOLIAN DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 1812;MONGOLIAN DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 1813;MONGOLIAN DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 1814;MONGOLIAN DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 1815;MONGOLIAN DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 1816;MONGOLIAN DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 1817;MONGOLIAN DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 1818;MONGOLIAN DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 1819;MONGOLIAN DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 1820;MONGOLIAN LETTER A;Lo;0;L;;;;;N;;;;; 1821;MONGOLIAN LETTER E;Lo;0;L;;;;;N;;;;; 1822;MONGOLIAN LETTER I;Lo;0;L;;;;;N;;;;; 1823;MONGOLIAN LETTER O;Lo;0;L;;;;;N;;;;; 1824;MONGOLIAN LETTER U;Lo;0;L;;;;;N;;;;; 1825;MONGOLIAN LETTER OE;Lo;0;L;;;;;N;;;;; 1826;MONGOLIAN LETTER UE;Lo;0;L;;;;;N;;;;; 1827;MONGOLIAN LETTER EE;Lo;0;L;;;;;N;;;;; 1828;MONGOLIAN LETTER NA;Lo;0;L;;;;;N;;;;; 1829;MONGOLIAN LETTER ANG;Lo;0;L;;;;;N;;;;; 182A;MONGOLIAN LETTER BA;Lo;0;L;;;;;N;;;;; 182B;MONGOLIAN LETTER PA;Lo;0;L;;;;;N;;;;; 182C;MONGOLIAN LETTER QA;Lo;0;L;;;;;N;;;;; 182D;MONGOLIAN LETTER GA;Lo;0;L;;;;;N;;;;; 182E;MONGOLIAN LETTER MA;Lo;0;L;;;;;N;;;;; 182F;MONGOLIAN LETTER LA;Lo;0;L;;;;;N;;;;; 1830;MONGOLIAN LETTER SA;Lo;0;L;;;;;N;;;;; 1831;MONGOLIAN LETTER SHA;Lo;0;L;;;;;N;;;;; 1832;MONGOLIAN LETTER TA;Lo;0;L;;;;;N;;;;; 1833;MONGOLIAN LETTER DA;Lo;0;L;;;;;N;;;;; 1834;MONGOLIAN LETTER CHA;Lo;0;L;;;;;N;;;;; 1835;MONGOLIAN LETTER JA;Lo;0;L;;;;;N;;;;; 1836;MONGOLIAN LETTER YA;Lo;0;L;;;;;N;;;;; 1837;MONGOLIAN LETTER RA;Lo;0;L;;;;;N;;;;; 1838;MONGOLIAN LETTER WA;Lo;0;L;;;;;N;;;;; 1839;MONGOLIAN LETTER FA;Lo;0;L;;;;;N;;;;; 183A;MONGOLIAN LETTER KA;Lo;0;L;;;;;N;;;;; 183B;MONGOLIAN LETTER KHA;Lo;0;L;;;;;N;;;;; 183C;MONGOLIAN LETTER TSA;Lo;0;L;;;;;N;;;;; 183D;MONGOLIAN LETTER ZA;Lo;0;L;;;;;N;;;;; 183E;MONGOLIAN LETTER HAA;Lo;0;L;;;;;N;;;;; 183F;MONGOLIAN LETTER ZRA;Lo;0;L;;;;;N;;;;; 1840;MONGOLIAN LETTER LHA;Lo;0;L;;;;;N;;;;; 1841;MONGOLIAN LETTER ZHI;Lo;0;L;;;;;N;;;;; 1842;MONGOLIAN LETTER CHI;Lo;0;L;;;;;N;;;;; 1843;MONGOLIAN LETTER TODO LONG VOWEL SIGN;Lm;0;L;;;;;N;;;;; 1844;MONGOLIAN LETTER TODO E;Lo;0;L;;;;;N;;;;; 1845;MONGOLIAN LETTER TODO I;Lo;0;L;;;;;N;;;;; 1846;MONGOLIAN LETTER TODO O;Lo;0;L;;;;;N;;;;; 1847;MONGOLIAN LETTER TODO U;Lo;0;L;;;;;N;;;;; 1848;MONGOLIAN LETTER TODO OE;Lo;0;L;;;;;N;;;;; 1849;MONGOLIAN LETTER TODO UE;Lo;0;L;;;;;N;;;;; 184A;MONGOLIAN LETTER TODO ANG;Lo;0;L;;;;;N;;;;; 184B;MONGOLIAN LETTER TODO BA;Lo;0;L;;;;;N;;;;; 184C;MONGOLIAN LETTER TODO PA;Lo;0;L;;;;;N;;;;; 184D;MONGOLIAN LETTER TODO QA;Lo;0;L;;;;;N;;;;; 184E;MONGOLIAN LETTER TODO GA;Lo;0;L;;;;;N;;;;; 184F;MONGOLIAN LETTER TODO MA;Lo;0;L;;;;;N;;;;; 1850;MONGOLIAN LETTER TODO TA;Lo;0;L;;;;;N;;;;; 1851;MONGOLIAN LETTER TODO DA;Lo;0;L;;;;;N;;;;; 1852;MONGOLIAN LETTER TODO CHA;Lo;0;L;;;;;N;;;;; 1853;MONGOLIAN LETTER TODO JA;Lo;0;L;;;;;N;;;;; 1854;MONGOLIAN LETTER TODO TSA;Lo;0;L;;;;;N;;;;; 1855;MONGOLIAN LETTER TODO YA;Lo;0;L;;;;;N;;;;; 1856;MONGOLIAN LETTER TODO WA;Lo;0;L;;;;;N;;;;; 1857;MONGOLIAN LETTER TODO KA;Lo;0;L;;;;;N;;;;; 1858;MONGOLIAN LETTER TODO GAA;Lo;0;L;;;;;N;;;;; 1859;MONGOLIAN LETTER TODO HAA;Lo;0;L;;;;;N;;;;; 185A;MONGOLIAN LETTER TODO JIA;Lo;0;L;;;;;N;;;;; 185B;MONGOLIAN LETTER TODO NIA;Lo;0;L;;;;;N;;;;; 185C;MONGOLIAN LETTER TODO DZA;Lo;0;L;;;;;N;;;;; 185D;MONGOLIAN LETTER SIBE E;Lo;0;L;;;;;N;;;;; 185E;MONGOLIAN LETTER SIBE I;Lo;0;L;;;;;N;;;;; 185F;MONGOLIAN LETTER SIBE IY;Lo;0;L;;;;;N;;;;; 1860;MONGOLIAN LETTER SIBE UE;Lo;0;L;;;;;N;;;;; 1861;MONGOLIAN LETTER SIBE U;Lo;0;L;;;;;N;;;;; 1862;MONGOLIAN LETTER SIBE ANG;Lo;0;L;;;;;N;;;;; 1863;MONGOLIAN LETTER SIBE KA;Lo;0;L;;;;;N;;;;; 1864;MONGOLIAN LETTER SIBE GA;Lo;0;L;;;;;N;;;;; 1865;MONGOLIAN LETTER SIBE HA;Lo;0;L;;;;;N;;;;; 1866;MONGOLIAN LETTER SIBE PA;Lo;0;L;;;;;N;;;;; 1867;MONGOLIAN LETTER SIBE SHA;Lo;0;L;;;;;N;;;;; 1868;MONGOLIAN LETTER SIBE TA;Lo;0;L;;;;;N;;;;; 1869;MONGOLIAN LETTER SIBE DA;Lo;0;L;;;;;N;;;;; 186A;MONGOLIAN LETTER SIBE JA;Lo;0;L;;;;;N;;;;; 186B;MONGOLIAN LETTER SIBE FA;Lo;0;L;;;;;N;;;;; 186C;MONGOLIAN LETTER SIBE GAA;Lo;0;L;;;;;N;;;;; 186D;MONGOLIAN LETTER SIBE HAA;Lo;0;L;;;;;N;;;;; 186E;MONGOLIAN LETTER SIBE TSA;Lo;0;L;;;;;N;;;;; 186F;MONGOLIAN LETTER SIBE ZA;Lo;0;L;;;;;N;;;;; 1870;MONGOLIAN LETTER SIBE RAA;Lo;0;L;;;;;N;;;;; 1871;MONGOLIAN LETTER SIBE CHA;Lo;0;L;;;;;N;;;;; 1872;MONGOLIAN LETTER SIBE ZHA;Lo;0;L;;;;;N;;;;; 1873;MONGOLIAN LETTER MANCHU I;Lo;0;L;;;;;N;;;;; 1874;MONGOLIAN LETTER MANCHU KA;Lo;0;L;;;;;N;;;;; 1875;MONGOLIAN LETTER MANCHU RA;Lo;0;L;;;;;N;;;;; 1876;MONGOLIAN LETTER MANCHU FA;Lo;0;L;;;;;N;;;;; 1877;MONGOLIAN LETTER MANCHU ZHA;Lo;0;L;;;;;N;;;;; 1880;MONGOLIAN LETTER ALI GALI ANUSVARA ONE;Lo;0;L;;;;;N;;;;; 1881;MONGOLIAN LETTER ALI GALI VISARGA ONE;Lo;0;L;;;;;N;;;;; 1882;MONGOLIAN LETTER ALI GALI DAMARU;Lo;0;L;;;;;N;;;;; 1883;MONGOLIAN LETTER ALI GALI UBADAMA;Lo;0;L;;;;;N;;;;; 1884;MONGOLIAN LETTER ALI GALI INVERTED UBADAMA;Lo;0;L;;;;;N;;;;; 1885;MONGOLIAN LETTER ALI GALI BALUDA;Mn;0;NSM;;;;;N;;;;; 1886;MONGOLIAN LETTER ALI GALI THREE BALUDA;Mn;0;NSM;;;;;N;;;;; 1887;MONGOLIAN LETTER ALI GALI A;Lo;0;L;;;;;N;;;;; 1888;MONGOLIAN LETTER ALI GALI I;Lo;0;L;;;;;N;;;;; 1889;MONGOLIAN LETTER ALI GALI KA;Lo;0;L;;;;;N;;;;; 188A;MONGOLIAN LETTER ALI GALI NGA;Lo;0;L;;;;;N;;;;; 188B;MONGOLIAN LETTER ALI GALI CA;Lo;0;L;;;;;N;;;;; 188C;MONGOLIAN LETTER ALI GALI TTA;Lo;0;L;;;;;N;;;;; 188D;MONGOLIAN LETTER ALI GALI TTHA;Lo;0;L;;;;;N;;;;; 188E;MONGOLIAN LETTER ALI GALI DDA;Lo;0;L;;;;;N;;;;; 188F;MONGOLIAN LETTER ALI GALI NNA;Lo;0;L;;;;;N;;;;; 1890;MONGOLIAN LETTER ALI GALI TA;Lo;0;L;;;;;N;;;;; 1891;MONGOLIAN LETTER ALI GALI DA;Lo;0;L;;;;;N;;;;; 1892;MONGOLIAN LETTER ALI GALI PA;Lo;0;L;;;;;N;;;;; 1893;MONGOLIAN LETTER ALI GALI PHA;Lo;0;L;;;;;N;;;;; 1894;MONGOLIAN LETTER ALI GALI SSA;Lo;0;L;;;;;N;;;;; 1895;MONGOLIAN LETTER ALI GALI ZHA;Lo;0;L;;;;;N;;;;; 1896;MONGOLIAN LETTER ALI GALI ZA;Lo;0;L;;;;;N;;;;; 1897;MONGOLIAN LETTER ALI GALI AH;Lo;0;L;;;;;N;;;;; 1898;MONGOLIAN LETTER TODO ALI GALI TA;Lo;0;L;;;;;N;;;;; 1899;MONGOLIAN LETTER TODO ALI GALI ZHA;Lo;0;L;;;;;N;;;;; 189A;MONGOLIAN LETTER MANCHU ALI GALI GHA;Lo;0;L;;;;;N;;;;; 189B;MONGOLIAN LETTER MANCHU ALI GALI NGA;Lo;0;L;;;;;N;;;;; 189C;MONGOLIAN LETTER MANCHU ALI GALI CA;Lo;0;L;;;;;N;;;;; 189D;MONGOLIAN LETTER MANCHU ALI GALI JHA;Lo;0;L;;;;;N;;;;; 189E;MONGOLIAN LETTER MANCHU ALI GALI TTA;Lo;0;L;;;;;N;;;;; 189F;MONGOLIAN LETTER MANCHU ALI GALI DDHA;Lo;0;L;;;;;N;;;;; 18A0;MONGOLIAN LETTER MANCHU ALI GALI TA;Lo;0;L;;;;;N;;;;; 18A1;MONGOLIAN LETTER MANCHU ALI GALI DHA;Lo;0;L;;;;;N;;;;; 18A2;MONGOLIAN LETTER MANCHU ALI GALI SSA;Lo;0;L;;;;;N;;;;; 18A3;MONGOLIAN LETTER MANCHU ALI GALI CYA;Lo;0;L;;;;;N;;;;; 18A4;MONGOLIAN LETTER MANCHU ALI GALI ZHA;Lo;0;L;;;;;N;;;;; 18A5;MONGOLIAN LETTER MANCHU ALI GALI ZA;Lo;0;L;;;;;N;;;;; 18A6;MONGOLIAN LETTER ALI GALI HALF U;Lo;0;L;;;;;N;;;;; 18A7;MONGOLIAN LETTER ALI GALI HALF YA;Lo;0;L;;;;;N;;;;; 18A8;MONGOLIAN LETTER MANCHU ALI GALI BHA;Lo;0;L;;;;;N;;;;; 18A9;MONGOLIAN LETTER ALI GALI DAGALGA;Mn;228;NSM;;;;;N;;;;; 18AA;MONGOLIAN LETTER MANCHU ALI GALI LHA;Lo;0;L;;;;;N;;;;; 18B0;CANADIAN SYLLABICS OY;Lo;0;L;;;;;N;;;;; 18B1;CANADIAN SYLLABICS AY;Lo;0;L;;;;;N;;;;; 18B2;CANADIAN SYLLABICS AAY;Lo;0;L;;;;;N;;;;; 18B3;CANADIAN SYLLABICS WAY;Lo;0;L;;;;;N;;;;; 18B4;CANADIAN SYLLABICS POY;Lo;0;L;;;;;N;;;;; 18B5;CANADIAN SYLLABICS PAY;Lo;0;L;;;;;N;;;;; 18B6;CANADIAN SYLLABICS PWOY;Lo;0;L;;;;;N;;;;; 18B7;CANADIAN SYLLABICS TAY;Lo;0;L;;;;;N;;;;; 18B8;CANADIAN SYLLABICS KAY;Lo;0;L;;;;;N;;;;; 18B9;CANADIAN SYLLABICS KWAY;Lo;0;L;;;;;N;;;;; 18BA;CANADIAN SYLLABICS MAY;Lo;0;L;;;;;N;;;;; 18BB;CANADIAN SYLLABICS NOY;Lo;0;L;;;;;N;;;;; 18BC;CANADIAN SYLLABICS NAY;Lo;0;L;;;;;N;;;;; 18BD;CANADIAN SYLLABICS LAY;Lo;0;L;;;;;N;;;;; 18BE;CANADIAN SYLLABICS SOY;Lo;0;L;;;;;N;;;;; 18BF;CANADIAN SYLLABICS SAY;Lo;0;L;;;;;N;;;;; 18C0;CANADIAN SYLLABICS SHOY;Lo;0;L;;;;;N;;;;; 18C1;CANADIAN SYLLABICS SHAY;Lo;0;L;;;;;N;;;;; 18C2;CANADIAN SYLLABICS SHWOY;Lo;0;L;;;;;N;;;;; 18C3;CANADIAN SYLLABICS YOY;Lo;0;L;;;;;N;;;;; 18C4;CANADIAN SYLLABICS YAY;Lo;0;L;;;;;N;;;;; 18C5;CANADIAN SYLLABICS RAY;Lo;0;L;;;;;N;;;;; 18C6;CANADIAN SYLLABICS NWI;Lo;0;L;;;;;N;;;;; 18C7;CANADIAN SYLLABICS OJIBWAY NWI;Lo;0;L;;;;;N;;;;; 18C8;CANADIAN SYLLABICS NWII;Lo;0;L;;;;;N;;;;; 18C9;CANADIAN SYLLABICS OJIBWAY NWII;Lo;0;L;;;;;N;;;;; 18CA;CANADIAN SYLLABICS NWO;Lo;0;L;;;;;N;;;;; 18CB;CANADIAN SYLLABICS OJIBWAY NWO;Lo;0;L;;;;;N;;;;; 18CC;CANADIAN SYLLABICS NWOO;Lo;0;L;;;;;N;;;;; 18CD;CANADIAN SYLLABICS OJIBWAY NWOO;Lo;0;L;;;;;N;;;;; 18CE;CANADIAN SYLLABICS RWEE;Lo;0;L;;;;;N;;;;; 18CF;CANADIAN SYLLABICS RWI;Lo;0;L;;;;;N;;;;; 18D0;CANADIAN SYLLABICS RWII;Lo;0;L;;;;;N;;;;; 18D1;CANADIAN SYLLABICS RWO;Lo;0;L;;;;;N;;;;; 18D2;CANADIAN SYLLABICS RWOO;Lo;0;L;;;;;N;;;;; 18D3;CANADIAN SYLLABICS RWA;Lo;0;L;;;;;N;;;;; 18D4;CANADIAN SYLLABICS OJIBWAY P;Lo;0;L;;;;;N;;;;; 18D5;CANADIAN SYLLABICS OJIBWAY T;Lo;0;L;;;;;N;;;;; 18D6;CANADIAN SYLLABICS OJIBWAY K;Lo;0;L;;;;;N;;;;; 18D7;CANADIAN SYLLABICS OJIBWAY C;Lo;0;L;;;;;N;;;;; 18D8;CANADIAN SYLLABICS OJIBWAY M;Lo;0;L;;;;;N;;;;; 18D9;CANADIAN SYLLABICS OJIBWAY N;Lo;0;L;;;;;N;;;;; 18DA;CANADIAN SYLLABICS OJIBWAY S;Lo;0;L;;;;;N;;;;; 18DB;CANADIAN SYLLABICS OJIBWAY SH;Lo;0;L;;;;;N;;;;; 18DC;CANADIAN SYLLABICS EASTERN W;Lo;0;L;;;;;N;;;;; 18DD;CANADIAN SYLLABICS WESTERN W;Lo;0;L;;;;;N;;;;; 18DE;CANADIAN SYLLABICS FINAL SMALL RING;Lo;0;L;;;;;N;;;;; 18DF;CANADIAN SYLLABICS FINAL RAISED DOT;Lo;0;L;;;;;N;;;;; 18E0;CANADIAN SYLLABICS R-CREE RWE;Lo;0;L;;;;;N;;;;; 18E1;CANADIAN SYLLABICS WEST-CREE LOO;Lo;0;L;;;;;N;;;;; 18E2;CANADIAN SYLLABICS WEST-CREE LAA;Lo;0;L;;;;;N;;;;; 18E3;CANADIAN SYLLABICS THWE;Lo;0;L;;;;;N;;;;; 18E4;CANADIAN SYLLABICS THWA;Lo;0;L;;;;;N;;;;; 18E5;CANADIAN SYLLABICS TTHWE;Lo;0;L;;;;;N;;;;; 18E6;CANADIAN SYLLABICS TTHOO;Lo;0;L;;;;;N;;;;; 18E7;CANADIAN SYLLABICS TTHAA;Lo;0;L;;;;;N;;;;; 18E8;CANADIAN SYLLABICS TLHWE;Lo;0;L;;;;;N;;;;; 18E9;CANADIAN SYLLABICS TLHOO;Lo;0;L;;;;;N;;;;; 18EA;CANADIAN SYLLABICS SAYISI SHWE;Lo;0;L;;;;;N;;;;; 18EB;CANADIAN SYLLABICS SAYISI SHOO;Lo;0;L;;;;;N;;;;; 18EC;CANADIAN SYLLABICS SAYISI HOO;Lo;0;L;;;;;N;;;;; 18ED;CANADIAN SYLLABICS CARRIER GWU;Lo;0;L;;;;;N;;;;; 18EE;CANADIAN SYLLABICS CARRIER DENE GEE;Lo;0;L;;;;;N;;;;; 18EF;CANADIAN SYLLABICS CARRIER GAA;Lo;0;L;;;;;N;;;;; 18F0;CANADIAN SYLLABICS CARRIER GWA;Lo;0;L;;;;;N;;;;; 18F1;CANADIAN SYLLABICS SAYISI JUU;Lo;0;L;;;;;N;;;;; 18F2;CANADIAN SYLLABICS CARRIER JWA;Lo;0;L;;;;;N;;;;; 18F3;CANADIAN SYLLABICS BEAVER DENE L;Lo;0;L;;;;;N;;;;; 18F4;CANADIAN SYLLABICS BEAVER DENE R;Lo;0;L;;;;;N;;;;; 18F5;CANADIAN SYLLABICS CARRIER DENTAL S;Lo;0;L;;;;;N;;;;; 1900;LIMBU VOWEL-CARRIER LETTER;Lo;0;L;;;;;N;;;;; 1901;LIMBU LETTER KA;Lo;0;L;;;;;N;;;;; 1902;LIMBU LETTER KHA;Lo;0;L;;;;;N;;;;; 1903;LIMBU LETTER GA;Lo;0;L;;;;;N;;;;; 1904;LIMBU LETTER GHA;Lo;0;L;;;;;N;;;;; 1905;LIMBU LETTER NGA;Lo;0;L;;;;;N;;;;; 1906;LIMBU LETTER CA;Lo;0;L;;;;;N;;;;; 1907;LIMBU LETTER CHA;Lo;0;L;;;;;N;;;;; 1908;LIMBU LETTER JA;Lo;0;L;;;;;N;;;;; 1909;LIMBU LETTER JHA;Lo;0;L;;;;;N;;;;; 190A;LIMBU LETTER YAN;Lo;0;L;;;;;N;;;;; 190B;LIMBU LETTER TA;Lo;0;L;;;;;N;;;;; 190C;LIMBU LETTER THA;Lo;0;L;;;;;N;;;;; 190D;LIMBU LETTER DA;Lo;0;L;;;;;N;;;;; 190E;LIMBU LETTER DHA;Lo;0;L;;;;;N;;;;; 190F;LIMBU LETTER NA;Lo;0;L;;;;;N;;;;; 1910;LIMBU LETTER PA;Lo;0;L;;;;;N;;;;; 1911;LIMBU LETTER PHA;Lo;0;L;;;;;N;;;;; 1912;LIMBU LETTER BA;Lo;0;L;;;;;N;;;;; 1913;LIMBU LETTER BHA;Lo;0;L;;;;;N;;;;; 1914;LIMBU LETTER MA;Lo;0;L;;;;;N;;;;; 1915;LIMBU LETTER YA;Lo;0;L;;;;;N;;;;; 1916;LIMBU LETTER RA;Lo;0;L;;;;;N;;;;; 1917;LIMBU LETTER LA;Lo;0;L;;;;;N;;;;; 1918;LIMBU LETTER WA;Lo;0;L;;;;;N;;;;; 1919;LIMBU LETTER SHA;Lo;0;L;;;;;N;;;;; 191A;LIMBU LETTER SSA;Lo;0;L;;;;;N;;;;; 191B;LIMBU LETTER SA;Lo;0;L;;;;;N;;;;; 191C;LIMBU LETTER HA;Lo;0;L;;;;;N;;;;; 191D;LIMBU LETTER GYAN;Lo;0;L;;;;;N;;;;; 191E;LIMBU LETTER TRA;Lo;0;L;;;;;N;;;;; 1920;LIMBU VOWEL SIGN A;Mn;0;NSM;;;;;N;;;;; 1921;LIMBU VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; 1922;LIMBU VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 1923;LIMBU VOWEL SIGN EE;Mc;0;L;;;;;N;;;;; 1924;LIMBU VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; 1925;LIMBU VOWEL SIGN OO;Mc;0;L;;;;;N;;;;; 1926;LIMBU VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; 1927;LIMBU VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; 1928;LIMBU VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; 1929;LIMBU SUBJOINED LETTER YA;Mc;0;L;;;;;N;;;;; 192A;LIMBU SUBJOINED LETTER RA;Mc;0;L;;;;;N;;;;; 192B;LIMBU SUBJOINED LETTER WA;Mc;0;L;;;;;N;;;;; 1930;LIMBU SMALL LETTER KA;Mc;0;L;;;;;N;;;;; 1931;LIMBU SMALL LETTER NGA;Mc;0;L;;;;;N;;;;; 1932;LIMBU SMALL LETTER ANUSVARA;Mn;0;NSM;;;;;N;;;;; 1933;LIMBU SMALL LETTER TA;Mc;0;L;;;;;N;;;;; 1934;LIMBU SMALL LETTER NA;Mc;0;L;;;;;N;;;;; 1935;LIMBU SMALL LETTER PA;Mc;0;L;;;;;N;;;;; 1936;LIMBU SMALL LETTER MA;Mc;0;L;;;;;N;;;;; 1937;LIMBU SMALL LETTER RA;Mc;0;L;;;;;N;;;;; 1938;LIMBU SMALL LETTER LA;Mc;0;L;;;;;N;;;;; 1939;LIMBU SIGN MUKPHRENG;Mn;222;NSM;;;;;N;;;;; 193A;LIMBU SIGN KEMPHRENG;Mn;230;NSM;;;;;N;;;;; 193B;LIMBU SIGN SA-I;Mn;220;NSM;;;;;N;;;;; 1940;LIMBU SIGN LOO;So;0;ON;;;;;N;;;;; 1944;LIMBU EXCLAMATION MARK;Po;0;ON;;;;;N;;;;; 1945;LIMBU QUESTION MARK;Po;0;ON;;;;;N;;;;; 1946;LIMBU DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 1947;LIMBU DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 1948;LIMBU DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 1949;LIMBU DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 194A;LIMBU DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 194B;LIMBU DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 194C;LIMBU DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 194D;LIMBU DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 194E;LIMBU DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 194F;LIMBU DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 1950;TAI LE LETTER KA;Lo;0;L;;;;;N;;;;; 1951;TAI LE LETTER XA;Lo;0;L;;;;;N;;;;; 1952;TAI LE LETTER NGA;Lo;0;L;;;;;N;;;;; 1953;TAI LE LETTER TSA;Lo;0;L;;;;;N;;;;; 1954;TAI LE LETTER SA;Lo;0;L;;;;;N;;;;; 1955;TAI LE LETTER YA;Lo;0;L;;;;;N;;;;; 1956;TAI LE LETTER TA;Lo;0;L;;;;;N;;;;; 1957;TAI LE LETTER THA;Lo;0;L;;;;;N;;;;; 1958;TAI LE LETTER LA;Lo;0;L;;;;;N;;;;; 1959;TAI LE LETTER PA;Lo;0;L;;;;;N;;;;; 195A;TAI LE LETTER PHA;Lo;0;L;;;;;N;;;;; 195B;TAI LE LETTER MA;Lo;0;L;;;;;N;;;;; 195C;TAI LE LETTER FA;Lo;0;L;;;;;N;;;;; 195D;TAI LE LETTER VA;Lo;0;L;;;;;N;;;;; 195E;TAI LE LETTER HA;Lo;0;L;;;;;N;;;;; 195F;TAI LE LETTER QA;Lo;0;L;;;;;N;;;;; 1960;TAI LE LETTER KHA;Lo;0;L;;;;;N;;;;; 1961;TAI LE LETTER TSHA;Lo;0;L;;;;;N;;;;; 1962;TAI LE LETTER NA;Lo;0;L;;;;;N;;;;; 1963;TAI LE LETTER A;Lo;0;L;;;;;N;;;;; 1964;TAI LE LETTER I;Lo;0;L;;;;;N;;;;; 1965;TAI LE LETTER EE;Lo;0;L;;;;;N;;;;; 1966;TAI LE LETTER EH;Lo;0;L;;;;;N;;;;; 1967;TAI LE LETTER U;Lo;0;L;;;;;N;;;;; 1968;TAI LE LETTER OO;Lo;0;L;;;;;N;;;;; 1969;TAI LE LETTER O;Lo;0;L;;;;;N;;;;; 196A;TAI LE LETTER UE;Lo;0;L;;;;;N;;;;; 196B;TAI LE LETTER E;Lo;0;L;;;;;N;;;;; 196C;TAI LE LETTER AUE;Lo;0;L;;;;;N;;;;; 196D;TAI LE LETTER AI;Lo;0;L;;;;;N;;;;; 1970;TAI LE LETTER TONE-2;Lo;0;L;;;;;N;;;;; 1971;TAI LE LETTER TONE-3;Lo;0;L;;;;;N;;;;; 1972;TAI LE LETTER TONE-4;Lo;0;L;;;;;N;;;;; 1973;TAI LE LETTER TONE-5;Lo;0;L;;;;;N;;;;; 1974;TAI LE LETTER TONE-6;Lo;0;L;;;;;N;;;;; 1980;NEW TAI LUE LETTER HIGH QA;Lo;0;L;;;;;N;;;;; 1981;NEW TAI LUE LETTER LOW QA;Lo;0;L;;;;;N;;;;; 1982;NEW TAI LUE LETTER HIGH KA;Lo;0;L;;;;;N;;;;; 1983;NEW TAI LUE LETTER HIGH XA;Lo;0;L;;;;;N;;;;; 1984;NEW TAI LUE LETTER HIGH NGA;Lo;0;L;;;;;N;;;;; 1985;NEW TAI LUE LETTER LOW KA;Lo;0;L;;;;;N;;;;; 1986;NEW TAI LUE LETTER LOW XA;Lo;0;L;;;;;N;;;;; 1987;NEW TAI LUE LETTER LOW NGA;Lo;0;L;;;;;N;;;;; 1988;NEW TAI LUE LETTER HIGH TSA;Lo;0;L;;;;;N;;;;; 1989;NEW TAI LUE LETTER HIGH SA;Lo;0;L;;;;;N;;;;; 198A;NEW TAI LUE LETTER HIGH YA;Lo;0;L;;;;;N;;;;; 198B;NEW TAI LUE LETTER LOW TSA;Lo;0;L;;;;;N;;;;; 198C;NEW TAI LUE LETTER LOW SA;Lo;0;L;;;;;N;;;;; 198D;NEW TAI LUE LETTER LOW YA;Lo;0;L;;;;;N;;;;; 198E;NEW TAI LUE LETTER HIGH TA;Lo;0;L;;;;;N;;;;; 198F;NEW TAI LUE LETTER HIGH THA;Lo;0;L;;;;;N;;;;; 1990;NEW TAI LUE LETTER HIGH NA;Lo;0;L;;;;;N;;;;; 1991;NEW TAI LUE LETTER LOW TA;Lo;0;L;;;;;N;;;;; 1992;NEW TAI LUE LETTER LOW THA;Lo;0;L;;;;;N;;;;; 1993;NEW TAI LUE LETTER LOW NA;Lo;0;L;;;;;N;;;;; 1994;NEW TAI LUE LETTER HIGH PA;Lo;0;L;;;;;N;;;;; 1995;NEW TAI LUE LETTER HIGH PHA;Lo;0;L;;;;;N;;;;; 1996;NEW TAI LUE LETTER HIGH MA;Lo;0;L;;;;;N;;;;; 1997;NEW TAI LUE LETTER LOW PA;Lo;0;L;;;;;N;;;;; 1998;NEW TAI LUE LETTER LOW PHA;Lo;0;L;;;;;N;;;;; 1999;NEW TAI LUE LETTER LOW MA;Lo;0;L;;;;;N;;;;; 199A;NEW TAI LUE LETTER HIGH FA;Lo;0;L;;;;;N;;;;; 199B;NEW TAI LUE LETTER HIGH VA;Lo;0;L;;;;;N;;;;; 199C;NEW TAI LUE LETTER HIGH LA;Lo;0;L;;;;;N;;;;; 199D;NEW TAI LUE LETTER LOW FA;Lo;0;L;;;;;N;;;;; 199E;NEW TAI LUE LETTER LOW VA;Lo;0;L;;;;;N;;;;; 199F;NEW TAI LUE LETTER LOW LA;Lo;0;L;;;;;N;;;;; 19A0;NEW TAI LUE LETTER HIGH HA;Lo;0;L;;;;;N;;;;; 19A1;NEW TAI LUE LETTER HIGH DA;Lo;0;L;;;;;N;;;;; 19A2;NEW TAI LUE LETTER HIGH BA;Lo;0;L;;;;;N;;;;; 19A3;NEW TAI LUE LETTER LOW HA;Lo;0;L;;;;;N;;;;; 19A4;NEW TAI LUE LETTER LOW DA;Lo;0;L;;;;;N;;;;; 19A5;NEW TAI LUE LETTER LOW BA;Lo;0;L;;;;;N;;;;; 19A6;NEW TAI LUE LETTER HIGH KVA;Lo;0;L;;;;;N;;;;; 19A7;NEW TAI LUE LETTER HIGH XVA;Lo;0;L;;;;;N;;;;; 19A8;NEW TAI LUE LETTER LOW KVA;Lo;0;L;;;;;N;;;;; 19A9;NEW TAI LUE LETTER LOW XVA;Lo;0;L;;;;;N;;;;; 19AA;NEW TAI LUE LETTER HIGH SUA;Lo;0;L;;;;;N;;;;; 19AB;NEW TAI LUE LETTER LOW SUA;Lo;0;L;;;;;N;;;;; 19B0;NEW TAI LUE VOWEL SIGN VOWEL SHORTENER;Lo;0;L;;;;;N;;;;; 19B1;NEW TAI LUE VOWEL SIGN AA;Lo;0;L;;;;;N;;;;; 19B2;NEW TAI LUE VOWEL SIGN II;Lo;0;L;;;;;N;;;;; 19B3;NEW TAI LUE VOWEL SIGN U;Lo;0;L;;;;;N;;;;; 19B4;NEW TAI LUE VOWEL SIGN UU;Lo;0;L;;;;;N;;;;; 19B5;NEW TAI LUE VOWEL SIGN E;Lo;0;L;;;;;N;;;;; 19B6;NEW TAI LUE VOWEL SIGN AE;Lo;0;L;;;;;N;;;;; 19B7;NEW TAI LUE VOWEL SIGN O;Lo;0;L;;;;;N;;;;; 19B8;NEW TAI LUE VOWEL SIGN OA;Lo;0;L;;;;;N;;;;; 19B9;NEW TAI LUE VOWEL SIGN UE;Lo;0;L;;;;;N;;;;; 19BA;NEW TAI LUE VOWEL SIGN AY;Lo;0;L;;;;;N;;;;; 19BB;NEW TAI LUE VOWEL SIGN AAY;Lo;0;L;;;;;N;;;;; 19BC;NEW TAI LUE VOWEL SIGN UY;Lo;0;L;;;;;N;;;;; 19BD;NEW TAI LUE VOWEL SIGN OY;Lo;0;L;;;;;N;;;;; 19BE;NEW TAI LUE VOWEL SIGN OAY;Lo;0;L;;;;;N;;;;; 19BF;NEW TAI LUE VOWEL SIGN UEY;Lo;0;L;;;;;N;;;;; 19C0;NEW TAI LUE VOWEL SIGN IY;Lo;0;L;;;;;N;;;;; 19C1;NEW TAI LUE LETTER FINAL V;Lo;0;L;;;;;N;;;;; 19C2;NEW TAI LUE LETTER FINAL NG;Lo;0;L;;;;;N;;;;; 19C3;NEW TAI LUE LETTER FINAL N;Lo;0;L;;;;;N;;;;; 19C4;NEW TAI LUE LETTER FINAL M;Lo;0;L;;;;;N;;;;; 19C5;NEW TAI LUE LETTER FINAL K;Lo;0;L;;;;;N;;;;; 19C6;NEW TAI LUE LETTER FINAL D;Lo;0;L;;;;;N;;;;; 19C7;NEW TAI LUE LETTER FINAL B;Lo;0;L;;;;;N;;;;; 19C8;NEW TAI LUE TONE MARK-1;Lo;0;L;;;;;N;;;;; 19C9;NEW TAI LUE TONE MARK-2;Lo;0;L;;;;;N;;;;; 19D0;NEW TAI LUE DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 19D1;NEW TAI LUE DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 19D2;NEW TAI LUE DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 19D3;NEW TAI LUE DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 19D4;NEW TAI LUE DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 19D5;NEW TAI LUE DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 19D6;NEW TAI LUE DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 19D7;NEW TAI LUE DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 19D8;NEW TAI LUE DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 19D9;NEW TAI LUE DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 19DA;NEW TAI LUE THAM DIGIT ONE;No;0;L;;;1;1;N;;;;; 19DE;NEW TAI LUE SIGN LAE;So;0;ON;;;;;N;;;;; 19DF;NEW TAI LUE SIGN LAEV;So;0;ON;;;;;N;;;;; 19E0;KHMER SYMBOL PATHAMASAT;So;0;ON;;;;;N;;;;; 19E1;KHMER SYMBOL MUOY KOET;So;0;ON;;;;;N;;;;; 19E2;KHMER SYMBOL PII KOET;So;0;ON;;;;;N;;;;; 19E3;KHMER SYMBOL BEI KOET;So;0;ON;;;;;N;;;;; 19E4;KHMER SYMBOL BUON KOET;So;0;ON;;;;;N;;;;; 19E5;KHMER SYMBOL PRAM KOET;So;0;ON;;;;;N;;;;; 19E6;KHMER SYMBOL PRAM-MUOY KOET;So;0;ON;;;;;N;;;;; 19E7;KHMER SYMBOL PRAM-PII KOET;So;0;ON;;;;;N;;;;; 19E8;KHMER SYMBOL PRAM-BEI KOET;So;0;ON;;;;;N;;;;; 19E9;KHMER SYMBOL PRAM-BUON KOET;So;0;ON;;;;;N;;;;; 19EA;KHMER SYMBOL DAP KOET;So;0;ON;;;;;N;;;;; 19EB;KHMER SYMBOL DAP-MUOY KOET;So;0;ON;;;;;N;;;;; 19EC;KHMER SYMBOL DAP-PII KOET;So;0;ON;;;;;N;;;;; 19ED;KHMER SYMBOL DAP-BEI KOET;So;0;ON;;;;;N;;;;; 19EE;KHMER SYMBOL DAP-BUON KOET;So;0;ON;;;;;N;;;;; 19EF;KHMER SYMBOL DAP-PRAM KOET;So;0;ON;;;;;N;;;;; 19F0;KHMER SYMBOL TUTEYASAT;So;0;ON;;;;;N;;;;; 19F1;KHMER SYMBOL MUOY ROC;So;0;ON;;;;;N;;;;; 19F2;KHMER SYMBOL PII ROC;So;0;ON;;;;;N;;;;; 19F3;KHMER SYMBOL BEI ROC;So;0;ON;;;;;N;;;;; 19F4;KHMER SYMBOL BUON ROC;So;0;ON;;;;;N;;;;; 19F5;KHMER SYMBOL PRAM ROC;So;0;ON;;;;;N;;;;; 19F6;KHMER SYMBOL PRAM-MUOY ROC;So;0;ON;;;;;N;;;;; 19F7;KHMER SYMBOL PRAM-PII ROC;So;0;ON;;;;;N;;;;; 19F8;KHMER SYMBOL PRAM-BEI ROC;So;0;ON;;;;;N;;;;; 19F9;KHMER SYMBOL PRAM-BUON ROC;So;0;ON;;;;;N;;;;; 19FA;KHMER SYMBOL DAP ROC;So;0;ON;;;;;N;;;;; 19FB;KHMER SYMBOL DAP-MUOY ROC;So;0;ON;;;;;N;;;;; 19FC;KHMER SYMBOL DAP-PII ROC;So;0;ON;;;;;N;;;;; 19FD;KHMER SYMBOL DAP-BEI ROC;So;0;ON;;;;;N;;;;; 19FE;KHMER SYMBOL DAP-BUON ROC;So;0;ON;;;;;N;;;;; 19FF;KHMER SYMBOL DAP-PRAM ROC;So;0;ON;;;;;N;;;;; 1A00;BUGINESE LETTER KA;Lo;0;L;;;;;N;;;;; 1A01;BUGINESE LETTER GA;Lo;0;L;;;;;N;;;;; 1A02;BUGINESE LETTER NGA;Lo;0;L;;;;;N;;;;; 1A03;BUGINESE LETTER NGKA;Lo;0;L;;;;;N;;;;; 1A04;BUGINESE LETTER PA;Lo;0;L;;;;;N;;;;; 1A05;BUGINESE LETTER BA;Lo;0;L;;;;;N;;;;; 1A06;BUGINESE LETTER MA;Lo;0;L;;;;;N;;;;; 1A07;BUGINESE LETTER MPA;Lo;0;L;;;;;N;;;;; 1A08;BUGINESE LETTER TA;Lo;0;L;;;;;N;;;;; 1A09;BUGINESE LETTER DA;Lo;0;L;;;;;N;;;;; 1A0A;BUGINESE LETTER NA;Lo;0;L;;;;;N;;;;; 1A0B;BUGINESE LETTER NRA;Lo;0;L;;;;;N;;;;; 1A0C;BUGINESE LETTER CA;Lo;0;L;;;;;N;;;;; 1A0D;BUGINESE LETTER JA;Lo;0;L;;;;;N;;;;; 1A0E;BUGINESE LETTER NYA;Lo;0;L;;;;;N;;;;; 1A0F;BUGINESE LETTER NYCA;Lo;0;L;;;;;N;;;;; 1A10;BUGINESE LETTER YA;Lo;0;L;;;;;N;;;;; 1A11;BUGINESE LETTER RA;Lo;0;L;;;;;N;;;;; 1A12;BUGINESE LETTER LA;Lo;0;L;;;;;N;;;;; 1A13;BUGINESE LETTER VA;Lo;0;L;;;;;N;;;;; 1A14;BUGINESE LETTER SA;Lo;0;L;;;;;N;;;;; 1A15;BUGINESE LETTER A;Lo;0;L;;;;;N;;;;; 1A16;BUGINESE LETTER HA;Lo;0;L;;;;;N;;;;; 1A17;BUGINESE VOWEL SIGN I;Mn;230;NSM;;;;;N;;;;; 1A18;BUGINESE VOWEL SIGN U;Mn;220;NSM;;;;;N;;;;; 1A19;BUGINESE VOWEL SIGN E;Mc;0;L;;;;;N;;;;; 1A1A;BUGINESE VOWEL SIGN O;Mc;0;L;;;;;N;;;;; 1A1B;BUGINESE VOWEL SIGN AE;Mn;0;NSM;;;;;N;;;;; 1A1E;BUGINESE PALLAWA;Po;0;L;;;;;N;;;;; 1A1F;BUGINESE END OF SECTION;Po;0;L;;;;;N;;;;; 1A20;TAI THAM LETTER HIGH KA;Lo;0;L;;;;;N;;;;; 1A21;TAI THAM LETTER HIGH KHA;Lo;0;L;;;;;N;;;;; 1A22;TAI THAM LETTER HIGH KXA;Lo;0;L;;;;;N;;;;; 1A23;TAI THAM LETTER LOW KA;Lo;0;L;;;;;N;;;;; 1A24;TAI THAM LETTER LOW KXA;Lo;0;L;;;;;N;;;;; 1A25;TAI THAM LETTER LOW KHA;Lo;0;L;;;;;N;;;;; 1A26;TAI THAM LETTER NGA;Lo;0;L;;;;;N;;;;; 1A27;TAI THAM LETTER HIGH CA;Lo;0;L;;;;;N;;;;; 1A28;TAI THAM LETTER HIGH CHA;Lo;0;L;;;;;N;;;;; 1A29;TAI THAM LETTER LOW CA;Lo;0;L;;;;;N;;;;; 1A2A;TAI THAM LETTER LOW SA;Lo;0;L;;;;;N;;;;; 1A2B;TAI THAM LETTER LOW CHA;Lo;0;L;;;;;N;;;;; 1A2C;TAI THAM LETTER NYA;Lo;0;L;;;;;N;;;;; 1A2D;TAI THAM LETTER RATA;Lo;0;L;;;;;N;;;;; 1A2E;TAI THAM LETTER HIGH RATHA;Lo;0;L;;;;;N;;;;; 1A2F;TAI THAM LETTER DA;Lo;0;L;;;;;N;;;;; 1A30;TAI THAM LETTER LOW RATHA;Lo;0;L;;;;;N;;;;; 1A31;TAI THAM LETTER RANA;Lo;0;L;;;;;N;;;;; 1A32;TAI THAM LETTER HIGH TA;Lo;0;L;;;;;N;;;;; 1A33;TAI THAM LETTER HIGH THA;Lo;0;L;;;;;N;;;;; 1A34;TAI THAM LETTER LOW TA;Lo;0;L;;;;;N;;;;; 1A35;TAI THAM LETTER LOW THA;Lo;0;L;;;;;N;;;;; 1A36;TAI THAM LETTER NA;Lo;0;L;;;;;N;;;;; 1A37;TAI THAM LETTER BA;Lo;0;L;;;;;N;;;;; 1A38;TAI THAM LETTER HIGH PA;Lo;0;L;;;;;N;;;;; 1A39;TAI THAM LETTER HIGH PHA;Lo;0;L;;;;;N;;;;; 1A3A;TAI THAM LETTER HIGH FA;Lo;0;L;;;;;N;;;;; 1A3B;TAI THAM LETTER LOW PA;Lo;0;L;;;;;N;;;;; 1A3C;TAI THAM LETTER LOW FA;Lo;0;L;;;;;N;;;;; 1A3D;TAI THAM LETTER LOW PHA;Lo;0;L;;;;;N;;;;; 1A3E;TAI THAM LETTER MA;Lo;0;L;;;;;N;;;;; 1A3F;TAI THAM LETTER LOW YA;Lo;0;L;;;;;N;;;;; 1A40;TAI THAM LETTER HIGH YA;Lo;0;L;;;;;N;;;;; 1A41;TAI THAM LETTER RA;Lo;0;L;;;;;N;;;;; 1A42;TAI THAM LETTER RUE;Lo;0;L;;;;;N;;;;; 1A43;TAI THAM LETTER LA;Lo;0;L;;;;;N;;;;; 1A44;TAI THAM LETTER LUE;Lo;0;L;;;;;N;;;;; 1A45;TAI THAM LETTER WA;Lo;0;L;;;;;N;;;;; 1A46;TAI THAM LETTER HIGH SHA;Lo;0;L;;;;;N;;;;; 1A47;TAI THAM LETTER HIGH SSA;Lo;0;L;;;;;N;;;;; 1A48;TAI THAM LETTER HIGH SA;Lo;0;L;;;;;N;;;;; 1A49;TAI THAM LETTER HIGH HA;Lo;0;L;;;;;N;;;;; 1A4A;TAI THAM LETTER LLA;Lo;0;L;;;;;N;;;;; 1A4B;TAI THAM LETTER A;Lo;0;L;;;;;N;;;;; 1A4C;TAI THAM LETTER LOW HA;Lo;0;L;;;;;N;;;;; 1A4D;TAI THAM LETTER I;Lo;0;L;;;;;N;;;;; 1A4E;TAI THAM LETTER II;Lo;0;L;;;;;N;;;;; 1A4F;TAI THAM LETTER U;Lo;0;L;;;;;N;;;;; 1A50;TAI THAM LETTER UU;Lo;0;L;;;;;N;;;;; 1A51;TAI THAM LETTER EE;Lo;0;L;;;;;N;;;;; 1A52;TAI THAM LETTER OO;Lo;0;L;;;;;N;;;;; 1A53;TAI THAM LETTER LAE;Lo;0;L;;;;;N;;;;; 1A54;TAI THAM LETTER GREAT SA;Lo;0;L;;;;;N;;;;; 1A55;TAI THAM CONSONANT SIGN MEDIAL RA;Mc;0;L;;;;;N;;;;; 1A56;TAI THAM CONSONANT SIGN MEDIAL LA;Mn;0;NSM;;;;;N;;;;; 1A57;TAI THAM CONSONANT SIGN LA TANG LAI;Mc;0;L;;;;;N;;;;; 1A58;TAI THAM SIGN MAI KANG LAI;Mn;0;NSM;;;;;N;;;;; 1A59;TAI THAM CONSONANT SIGN FINAL NGA;Mn;0;NSM;;;;;N;;;;; 1A5A;TAI THAM CONSONANT SIGN LOW PA;Mn;0;NSM;;;;;N;;;;; 1A5B;TAI THAM CONSONANT SIGN HIGH RATHA OR LOW PA;Mn;0;NSM;;;;;N;;;;; 1A5C;TAI THAM CONSONANT SIGN MA;Mn;0;NSM;;;;;N;;;;; 1A5D;TAI THAM CONSONANT SIGN BA;Mn;0;NSM;;;;;N;;;;; 1A5E;TAI THAM CONSONANT SIGN SA;Mn;0;NSM;;;;;N;;;;; 1A60;TAI THAM SIGN SAKOT;Mn;9;NSM;;;;;N;;;;; 1A61;TAI THAM VOWEL SIGN A;Mc;0;L;;;;;N;;;;; 1A62;TAI THAM VOWEL SIGN MAI SAT;Mn;0;NSM;;;;;N;;;;; 1A63;TAI THAM VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 1A64;TAI THAM VOWEL SIGN TALL AA;Mc;0;L;;;;;N;;;;; 1A65;TAI THAM VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; 1A66;TAI THAM VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; 1A67;TAI THAM VOWEL SIGN UE;Mn;0;NSM;;;;;N;;;;; 1A68;TAI THAM VOWEL SIGN UUE;Mn;0;NSM;;;;;N;;;;; 1A69;TAI THAM VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 1A6A;TAI THAM VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 1A6B;TAI THAM VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; 1A6C;TAI THAM VOWEL SIGN OA BELOW;Mn;0;NSM;;;;;N;;;;; 1A6D;TAI THAM VOWEL SIGN OY;Mc;0;L;;;;;N;;;;; 1A6E;TAI THAM VOWEL SIGN E;Mc;0;L;;;;;N;;;;; 1A6F;TAI THAM VOWEL SIGN AE;Mc;0;L;;;;;N;;;;; 1A70;TAI THAM VOWEL SIGN OO;Mc;0;L;;;;;N;;;;; 1A71;TAI THAM VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; 1A72;TAI THAM VOWEL SIGN THAM AI;Mc;0;L;;;;;N;;;;; 1A73;TAI THAM VOWEL SIGN OA ABOVE;Mn;0;NSM;;;;;N;;;;; 1A74;TAI THAM SIGN MAI KANG;Mn;0;NSM;;;;;N;;;;; 1A75;TAI THAM SIGN TONE-1;Mn;230;NSM;;;;;N;;;;; 1A76;TAI THAM SIGN TONE-2;Mn;230;NSM;;;;;N;;;;; 1A77;TAI THAM SIGN KHUEN TONE-3;Mn;230;NSM;;;;;N;;;;; 1A78;TAI THAM SIGN KHUEN TONE-4;Mn;230;NSM;;;;;N;;;;; 1A79;TAI THAM SIGN KHUEN TONE-5;Mn;230;NSM;;;;;N;;;;; 1A7A;TAI THAM SIGN RA HAAM;Mn;230;NSM;;;;;N;;;;; 1A7B;TAI THAM SIGN MAI SAM;Mn;230;NSM;;;;;N;;;;; 1A7C;TAI THAM SIGN KHUEN-LUE KARAN;Mn;230;NSM;;;;;N;;;;; 1A7F;TAI THAM COMBINING CRYPTOGRAMMIC DOT;Mn;220;NSM;;;;;N;;;;; 1A80;TAI THAM HORA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 1A81;TAI THAM HORA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 1A82;TAI THAM HORA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 1A83;TAI THAM HORA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 1A84;TAI THAM HORA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 1A85;TAI THAM HORA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 1A86;TAI THAM HORA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 1A87;TAI THAM HORA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 1A88;TAI THAM HORA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 1A89;TAI THAM HORA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 1A90;TAI THAM THAM DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 1A91;TAI THAM THAM DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 1A92;TAI THAM THAM DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 1A93;TAI THAM THAM DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 1A94;TAI THAM THAM DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 1A95;TAI THAM THAM DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 1A96;TAI THAM THAM DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 1A97;TAI THAM THAM DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 1A98;TAI THAM THAM DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 1A99;TAI THAM THAM DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 1AA0;TAI THAM SIGN WIANG;Po;0;L;;;;;N;;;;; 1AA1;TAI THAM SIGN WIANGWAAK;Po;0;L;;;;;N;;;;; 1AA2;TAI THAM SIGN SAWAN;Po;0;L;;;;;N;;;;; 1AA3;TAI THAM SIGN KEOW;Po;0;L;;;;;N;;;;; 1AA4;TAI THAM SIGN HOY;Po;0;L;;;;;N;;;;; 1AA5;TAI THAM SIGN DOKMAI;Po;0;L;;;;;N;;;;; 1AA6;TAI THAM SIGN REVERSED ROTATED RANA;Po;0;L;;;;;N;;;;; 1AA7;TAI THAM SIGN MAI YAMOK;Lm;0;L;;;;;N;;;;; 1AA8;TAI THAM SIGN KAAN;Po;0;L;;;;;N;;;;; 1AA9;TAI THAM SIGN KAANKUU;Po;0;L;;;;;N;;;;; 1AAA;TAI THAM SIGN SATKAAN;Po;0;L;;;;;N;;;;; 1AAB;TAI THAM SIGN SATKAANKUU;Po;0;L;;;;;N;;;;; 1AAC;TAI THAM SIGN HANG;Po;0;L;;;;;N;;;;; 1AAD;TAI THAM SIGN CAANG;Po;0;L;;;;;N;;;;; 1AB0;COMBINING DOUBLED CIRCUMFLEX ACCENT;Mn;230;NSM;;;;;N;;;;; 1AB1;COMBINING DIAERESIS-RING;Mn;230;NSM;;;;;N;;;;; 1AB2;COMBINING INFINITY;Mn;230;NSM;;;;;N;;;;; 1AB3;COMBINING DOWNWARDS ARROW;Mn;230;NSM;;;;;N;;;;; 1AB4;COMBINING TRIPLE DOT;Mn;230;NSM;;;;;N;;;;; 1AB5;COMBINING X-X BELOW;Mn;220;NSM;;;;;N;;;;; 1AB6;COMBINING WIGGLY LINE BELOW;Mn;220;NSM;;;;;N;;;;; 1AB7;COMBINING OPEN MARK BELOW;Mn;220;NSM;;;;;N;;;;; 1AB8;COMBINING DOUBLE OPEN MARK BELOW;Mn;220;NSM;;;;;N;;;;; 1AB9;COMBINING LIGHT CENTRALIZATION STROKE BELOW;Mn;220;NSM;;;;;N;;;;; 1ABA;COMBINING STRONG CENTRALIZATION STROKE BELOW;Mn;220;NSM;;;;;N;;;;; 1ABB;COMBINING PARENTHESES ABOVE;Mn;230;NSM;;;;;N;;;;; 1ABC;COMBINING DOUBLE PARENTHESES ABOVE;Mn;230;NSM;;;;;N;;;;; 1ABD;COMBINING PARENTHESES BELOW;Mn;220;NSM;;;;;N;;;;; 1ABE;COMBINING PARENTHESES OVERLAY;Me;0;NSM;;;;;N;;;;; 1B00;BALINESE SIGN ULU RICEM;Mn;0;NSM;;;;;N;;;;; 1B01;BALINESE SIGN ULU CANDRA;Mn;0;NSM;;;;;N;;;;; 1B02;BALINESE SIGN CECEK;Mn;0;NSM;;;;;N;;;;; 1B03;BALINESE SIGN SURANG;Mn;0;NSM;;;;;N;;;;; 1B04;BALINESE SIGN BISAH;Mc;0;L;;;;;N;;;;; 1B05;BALINESE LETTER AKARA;Lo;0;L;;;;;N;;;;; 1B06;BALINESE LETTER AKARA TEDUNG;Lo;0;L;1B05 1B35;;;;N;;;;; 1B07;BALINESE LETTER IKARA;Lo;0;L;;;;;N;;;;; 1B08;BALINESE LETTER IKARA TEDUNG;Lo;0;L;1B07 1B35;;;;N;;;;; 1B09;BALINESE LETTER UKARA;Lo;0;L;;;;;N;;;;; 1B0A;BALINESE LETTER UKARA TEDUNG;Lo;0;L;1B09 1B35;;;;N;;;;; 1B0B;BALINESE LETTER RA REPA;Lo;0;L;;;;;N;;;;; 1B0C;BALINESE LETTER RA REPA TEDUNG;Lo;0;L;1B0B 1B35;;;;N;;;;; 1B0D;BALINESE LETTER LA LENGA;Lo;0;L;;;;;N;;;;; 1B0E;BALINESE LETTER LA LENGA TEDUNG;Lo;0;L;1B0D 1B35;;;;N;;;;; 1B0F;BALINESE LETTER EKARA;Lo;0;L;;;;;N;;;;; 1B10;BALINESE LETTER AIKARA;Lo;0;L;;;;;N;;;;; 1B11;BALINESE LETTER OKARA;Lo;0;L;;;;;N;;;;; 1B12;BALINESE LETTER OKARA TEDUNG;Lo;0;L;1B11 1B35;;;;N;;;;; 1B13;BALINESE LETTER KA;Lo;0;L;;;;;N;;;;; 1B14;BALINESE LETTER KA MAHAPRANA;Lo;0;L;;;;;N;;;;; 1B15;BALINESE LETTER GA;Lo;0;L;;;;;N;;;;; 1B16;BALINESE LETTER GA GORA;Lo;0;L;;;;;N;;;;; 1B17;BALINESE LETTER NGA;Lo;0;L;;;;;N;;;;; 1B18;BALINESE LETTER CA;Lo;0;L;;;;;N;;;;; 1B19;BALINESE LETTER CA LACA;Lo;0;L;;;;;N;;;;; 1B1A;BALINESE LETTER JA;Lo;0;L;;;;;N;;;;; 1B1B;BALINESE LETTER JA JERA;Lo;0;L;;;;;N;;;;; 1B1C;BALINESE LETTER NYA;Lo;0;L;;;;;N;;;;; 1B1D;BALINESE LETTER TA LATIK;Lo;0;L;;;;;N;;;;; 1B1E;BALINESE LETTER TA MURDA MAHAPRANA;Lo;0;L;;;;;N;;;;; 1B1F;BALINESE LETTER DA MURDA ALPAPRANA;Lo;0;L;;;;;N;;;;; 1B20;BALINESE LETTER DA MURDA MAHAPRANA;Lo;0;L;;;;;N;;;;; 1B21;BALINESE LETTER NA RAMBAT;Lo;0;L;;;;;N;;;;; 1B22;BALINESE LETTER TA;Lo;0;L;;;;;N;;;;; 1B23;BALINESE LETTER TA TAWA;Lo;0;L;;;;;N;;;;; 1B24;BALINESE LETTER DA;Lo;0;L;;;;;N;;;;; 1B25;BALINESE LETTER DA MADU;Lo;0;L;;;;;N;;;;; 1B26;BALINESE LETTER NA;Lo;0;L;;;;;N;;;;; 1B27;BALINESE LETTER PA;Lo;0;L;;;;;N;;;;; 1B28;BALINESE LETTER PA KAPAL;Lo;0;L;;;;;N;;;;; 1B29;BALINESE LETTER BA;Lo;0;L;;;;;N;;;;; 1B2A;BALINESE LETTER BA KEMBANG;Lo;0;L;;;;;N;;;;; 1B2B;BALINESE LETTER MA;Lo;0;L;;;;;N;;;;; 1B2C;BALINESE LETTER YA;Lo;0;L;;;;;N;;;;; 1B2D;BALINESE LETTER RA;Lo;0;L;;;;;N;;;;; 1B2E;BALINESE LETTER LA;Lo;0;L;;;;;N;;;;; 1B2F;BALINESE LETTER WA;Lo;0;L;;;;;N;;;;; 1B30;BALINESE LETTER SA SAGA;Lo;0;L;;;;;N;;;;; 1B31;BALINESE LETTER SA SAPA;Lo;0;L;;;;;N;;;;; 1B32;BALINESE LETTER SA;Lo;0;L;;;;;N;;;;; 1B33;BALINESE LETTER HA;Lo;0;L;;;;;N;;;;; 1B34;BALINESE SIGN REREKAN;Mn;7;NSM;;;;;N;;;;; 1B35;BALINESE VOWEL SIGN TEDUNG;Mc;0;L;;;;;N;;;;; 1B36;BALINESE VOWEL SIGN ULU;Mn;0;NSM;;;;;N;;;;; 1B37;BALINESE VOWEL SIGN ULU SARI;Mn;0;NSM;;;;;N;;;;; 1B38;BALINESE VOWEL SIGN SUKU;Mn;0;NSM;;;;;N;;;;; 1B39;BALINESE VOWEL SIGN SUKU ILUT;Mn;0;NSM;;;;;N;;;;; 1B3A;BALINESE VOWEL SIGN RA REPA;Mn;0;NSM;;;;;N;;;;; 1B3B;BALINESE VOWEL SIGN RA REPA TEDUNG;Mc;0;L;1B3A 1B35;;;;N;;;;; 1B3C;BALINESE VOWEL SIGN LA LENGA;Mn;0;NSM;;;;;N;;;;; 1B3D;BALINESE VOWEL SIGN LA LENGA TEDUNG;Mc;0;L;1B3C 1B35;;;;N;;;;; 1B3E;BALINESE VOWEL SIGN TALING;Mc;0;L;;;;;N;;;;; 1B3F;BALINESE VOWEL SIGN TALING REPA;Mc;0;L;;;;;N;;;;; 1B40;BALINESE VOWEL SIGN TALING TEDUNG;Mc;0;L;1B3E 1B35;;;;N;;;;; 1B41;BALINESE VOWEL SIGN TALING REPA TEDUNG;Mc;0;L;1B3F 1B35;;;;N;;;;; 1B42;BALINESE VOWEL SIGN PEPET;Mn;0;NSM;;;;;N;;;;; 1B43;BALINESE VOWEL SIGN PEPET TEDUNG;Mc;0;L;1B42 1B35;;;;N;;;;; 1B44;BALINESE ADEG ADEG;Mc;9;L;;;;;N;;;;; 1B45;BALINESE LETTER KAF SASAK;Lo;0;L;;;;;N;;;;; 1B46;BALINESE LETTER KHOT SASAK;Lo;0;L;;;;;N;;;;; 1B47;BALINESE LETTER TZIR SASAK;Lo;0;L;;;;;N;;;;; 1B48;BALINESE LETTER EF SASAK;Lo;0;L;;;;;N;;;;; 1B49;BALINESE LETTER VE SASAK;Lo;0;L;;;;;N;;;;; 1B4A;BALINESE LETTER ZAL SASAK;Lo;0;L;;;;;N;;;;; 1B4B;BALINESE LETTER ASYURA SASAK;Lo;0;L;;;;;N;;;;; 1B50;BALINESE DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 1B51;BALINESE DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 1B52;BALINESE DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 1B53;BALINESE DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 1B54;BALINESE DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 1B55;BALINESE DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 1B56;BALINESE DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 1B57;BALINESE DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 1B58;BALINESE DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 1B59;BALINESE DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 1B5A;BALINESE PANTI;Po;0;L;;;;;N;;;;; 1B5B;BALINESE PAMADA;Po;0;L;;;;;N;;;;; 1B5C;BALINESE WINDU;Po;0;L;;;;;N;;;;; 1B5D;BALINESE CARIK PAMUNGKAH;Po;0;L;;;;;N;;;;; 1B5E;BALINESE CARIK SIKI;Po;0;L;;;;;N;;;;; 1B5F;BALINESE CARIK PAREREN;Po;0;L;;;;;N;;;;; 1B60;BALINESE PAMENENG;Po;0;L;;;;;N;;;;; 1B61;BALINESE MUSICAL SYMBOL DONG;So;0;L;;;;;N;;;;; 1B62;BALINESE MUSICAL SYMBOL DENG;So;0;L;;;;;N;;;;; 1B63;BALINESE MUSICAL SYMBOL DUNG;So;0;L;;;;;N;;;;; 1B64;BALINESE MUSICAL SYMBOL DANG;So;0;L;;;;;N;;;;; 1B65;BALINESE MUSICAL SYMBOL DANG SURANG;So;0;L;;;;;N;;;;; 1B66;BALINESE MUSICAL SYMBOL DING;So;0;L;;;;;N;;;;; 1B67;BALINESE MUSICAL SYMBOL DAENG;So;0;L;;;;;N;;;;; 1B68;BALINESE MUSICAL SYMBOL DEUNG;So;0;L;;;;;N;;;;; 1B69;BALINESE MUSICAL SYMBOL DAING;So;0;L;;;;;N;;;;; 1B6A;BALINESE MUSICAL SYMBOL DANG GEDE;So;0;L;;;;;N;;;;; 1B6B;BALINESE MUSICAL SYMBOL COMBINING TEGEH;Mn;230;NSM;;;;;N;;;;; 1B6C;BALINESE MUSICAL SYMBOL COMBINING ENDEP;Mn;220;NSM;;;;;N;;;;; 1B6D;BALINESE MUSICAL SYMBOL COMBINING KEMPUL;Mn;230;NSM;;;;;N;;;;; 1B6E;BALINESE MUSICAL SYMBOL COMBINING KEMPLI;Mn;230;NSM;;;;;N;;;;; 1B6F;BALINESE MUSICAL SYMBOL COMBINING JEGOGAN;Mn;230;NSM;;;;;N;;;;; 1B70;BALINESE MUSICAL SYMBOL COMBINING KEMPUL WITH JEGOGAN;Mn;230;NSM;;;;;N;;;;; 1B71;BALINESE MUSICAL SYMBOL COMBINING KEMPLI WITH JEGOGAN;Mn;230;NSM;;;;;N;;;;; 1B72;BALINESE MUSICAL SYMBOL COMBINING BENDE;Mn;230;NSM;;;;;N;;;;; 1B73;BALINESE MUSICAL SYMBOL COMBINING GONG;Mn;230;NSM;;;;;N;;;;; 1B74;BALINESE MUSICAL SYMBOL RIGHT-HAND OPEN DUG;So;0;L;;;;;N;;;;; 1B75;BALINESE MUSICAL SYMBOL RIGHT-HAND OPEN DAG;So;0;L;;;;;N;;;;; 1B76;BALINESE MUSICAL SYMBOL RIGHT-HAND CLOSED TUK;So;0;L;;;;;N;;;;; 1B77;BALINESE MUSICAL SYMBOL RIGHT-HAND CLOSED TAK;So;0;L;;;;;N;;;;; 1B78;BALINESE MUSICAL SYMBOL LEFT-HAND OPEN PANG;So;0;L;;;;;N;;;;; 1B79;BALINESE MUSICAL SYMBOL LEFT-HAND OPEN PUNG;So;0;L;;;;;N;;;;; 1B7A;BALINESE MUSICAL SYMBOL LEFT-HAND CLOSED PLAK;So;0;L;;;;;N;;;;; 1B7B;BALINESE MUSICAL SYMBOL LEFT-HAND CLOSED PLUK;So;0;L;;;;;N;;;;; 1B7C;BALINESE MUSICAL SYMBOL LEFT-HAND OPEN PING;So;0;L;;;;;N;;;;; 1B80;SUNDANESE SIGN PANYECEK;Mn;0;NSM;;;;;N;;;;; 1B81;SUNDANESE SIGN PANGLAYAR;Mn;0;NSM;;;;;N;;;;; 1B82;SUNDANESE SIGN PANGWISAD;Mc;0;L;;;;;N;;;;; 1B83;SUNDANESE LETTER A;Lo;0;L;;;;;N;;;;; 1B84;SUNDANESE LETTER I;Lo;0;L;;;;;N;;;;; 1B85;SUNDANESE LETTER U;Lo;0;L;;;;;N;;;;; 1B86;SUNDANESE LETTER AE;Lo;0;L;;;;;N;;;;; 1B87;SUNDANESE LETTER O;Lo;0;L;;;;;N;;;;; 1B88;SUNDANESE LETTER E;Lo;0;L;;;;;N;;;;; 1B89;SUNDANESE LETTER EU;Lo;0;L;;;;;N;;;;; 1B8A;SUNDANESE LETTER KA;Lo;0;L;;;;;N;;;;; 1B8B;SUNDANESE LETTER QA;Lo;0;L;;;;;N;;;;; 1B8C;SUNDANESE LETTER GA;Lo;0;L;;;;;N;;;;; 1B8D;SUNDANESE LETTER NGA;Lo;0;L;;;;;N;;;;; 1B8E;SUNDANESE LETTER CA;Lo;0;L;;;;;N;;;;; 1B8F;SUNDANESE LETTER JA;Lo;0;L;;;;;N;;;;; 1B90;SUNDANESE LETTER ZA;Lo;0;L;;;;;N;;;;; 1B91;SUNDANESE LETTER NYA;Lo;0;L;;;;;N;;;;; 1B92;SUNDANESE LETTER TA;Lo;0;L;;;;;N;;;;; 1B93;SUNDANESE LETTER DA;Lo;0;L;;;;;N;;;;; 1B94;SUNDANESE LETTER NA;Lo;0;L;;;;;N;;;;; 1B95;SUNDANESE LETTER PA;Lo;0;L;;;;;N;;;;; 1B96;SUNDANESE LETTER FA;Lo;0;L;;;;;N;;;;; 1B97;SUNDANESE LETTER VA;Lo;0;L;;;;;N;;;;; 1B98;SUNDANESE LETTER BA;Lo;0;L;;;;;N;;;;; 1B99;SUNDANESE LETTER MA;Lo;0;L;;;;;N;;;;; 1B9A;SUNDANESE LETTER YA;Lo;0;L;;;;;N;;;;; 1B9B;SUNDANESE LETTER RA;Lo;0;L;;;;;N;;;;; 1B9C;SUNDANESE LETTER LA;Lo;0;L;;;;;N;;;;; 1B9D;SUNDANESE LETTER WA;Lo;0;L;;;;;N;;;;; 1B9E;SUNDANESE LETTER SA;Lo;0;L;;;;;N;;;;; 1B9F;SUNDANESE LETTER XA;Lo;0;L;;;;;N;;;;; 1BA0;SUNDANESE LETTER HA;Lo;0;L;;;;;N;;;;; 1BA1;SUNDANESE CONSONANT SIGN PAMINGKAL;Mc;0;L;;;;;N;;;;; 1BA2;SUNDANESE CONSONANT SIGN PANYAKRA;Mn;0;NSM;;;;;N;;;;; 1BA3;SUNDANESE CONSONANT SIGN PANYIKU;Mn;0;NSM;;;;;N;;;;; 1BA4;SUNDANESE VOWEL SIGN PANGHULU;Mn;0;NSM;;;;;N;;;;; 1BA5;SUNDANESE VOWEL SIGN PANYUKU;Mn;0;NSM;;;;;N;;;;; 1BA6;SUNDANESE VOWEL SIGN PANAELAENG;Mc;0;L;;;;;N;;;;; 1BA7;SUNDANESE VOWEL SIGN PANOLONG;Mc;0;L;;;;;N;;;;; 1BA8;SUNDANESE VOWEL SIGN PAMEPET;Mn;0;NSM;;;;;N;;;;; 1BA9;SUNDANESE VOWEL SIGN PANEULEUNG;Mn;0;NSM;;;;;N;;;;; 1BAA;SUNDANESE SIGN PAMAAEH;Mc;9;L;;;;;N;;;;; 1BAB;SUNDANESE SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 1BAC;SUNDANESE CONSONANT SIGN PASANGAN MA;Mn;0;NSM;;;;;N;;;;; 1BAD;SUNDANESE CONSONANT SIGN PASANGAN WA;Mn;0;NSM;;;;;N;;;;; 1BAE;SUNDANESE LETTER KHA;Lo;0;L;;;;;N;;;;; 1BAF;SUNDANESE LETTER SYA;Lo;0;L;;;;;N;;;;; 1BB0;SUNDANESE DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 1BB1;SUNDANESE DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 1BB2;SUNDANESE DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 1BB3;SUNDANESE DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 1BB4;SUNDANESE DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 1BB5;SUNDANESE DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 1BB6;SUNDANESE DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 1BB7;SUNDANESE DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 1BB8;SUNDANESE DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 1BB9;SUNDANESE DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 1BBA;SUNDANESE AVAGRAHA;Lo;0;L;;;;;N;;;;; 1BBB;SUNDANESE LETTER REU;Lo;0;L;;;;;N;;;;; 1BBC;SUNDANESE LETTER LEU;Lo;0;L;;;;;N;;;;; 1BBD;SUNDANESE LETTER BHA;Lo;0;L;;;;;N;;;;; 1BBE;SUNDANESE LETTER FINAL K;Lo;0;L;;;;;N;;;;; 1BBF;SUNDANESE LETTER FINAL M;Lo;0;L;;;;;N;;;;; 1BC0;BATAK LETTER A;Lo;0;L;;;;;N;;;;; 1BC1;BATAK LETTER SIMALUNGUN A;Lo;0;L;;;;;N;;;;; 1BC2;BATAK LETTER HA;Lo;0;L;;;;;N;;;;; 1BC3;BATAK LETTER SIMALUNGUN HA;Lo;0;L;;;;;N;;;;; 1BC4;BATAK LETTER MANDAILING HA;Lo;0;L;;;;;N;;;;; 1BC5;BATAK LETTER BA;Lo;0;L;;;;;N;;;;; 1BC6;BATAK LETTER KARO BA;Lo;0;L;;;;;N;;;;; 1BC7;BATAK LETTER PA;Lo;0;L;;;;;N;;;;; 1BC8;BATAK LETTER SIMALUNGUN PA;Lo;0;L;;;;;N;;;;; 1BC9;BATAK LETTER NA;Lo;0;L;;;;;N;;;;; 1BCA;BATAK LETTER MANDAILING NA;Lo;0;L;;;;;N;;;;; 1BCB;BATAK LETTER WA;Lo;0;L;;;;;N;;;;; 1BCC;BATAK LETTER SIMALUNGUN WA;Lo;0;L;;;;;N;;;;; 1BCD;BATAK LETTER PAKPAK WA;Lo;0;L;;;;;N;;;;; 1BCE;BATAK LETTER GA;Lo;0;L;;;;;N;;;;; 1BCF;BATAK LETTER SIMALUNGUN GA;Lo;0;L;;;;;N;;;;; 1BD0;BATAK LETTER JA;Lo;0;L;;;;;N;;;;; 1BD1;BATAK LETTER DA;Lo;0;L;;;;;N;;;;; 1BD2;BATAK LETTER RA;Lo;0;L;;;;;N;;;;; 1BD3;BATAK LETTER SIMALUNGUN RA;Lo;0;L;;;;;N;;;;; 1BD4;BATAK LETTER MA;Lo;0;L;;;;;N;;;;; 1BD5;BATAK LETTER SIMALUNGUN MA;Lo;0;L;;;;;N;;;;; 1BD6;BATAK LETTER SOUTHERN TA;Lo;0;L;;;;;N;;;;; 1BD7;BATAK LETTER NORTHERN TA;Lo;0;L;;;;;N;;;;; 1BD8;BATAK LETTER SA;Lo;0;L;;;;;N;;;;; 1BD9;BATAK LETTER SIMALUNGUN SA;Lo;0;L;;;;;N;;;;; 1BDA;BATAK LETTER MANDAILING SA;Lo;0;L;;;;;N;;;;; 1BDB;BATAK LETTER YA;Lo;0;L;;;;;N;;;;; 1BDC;BATAK LETTER SIMALUNGUN YA;Lo;0;L;;;;;N;;;;; 1BDD;BATAK LETTER NGA;Lo;0;L;;;;;N;;;;; 1BDE;BATAK LETTER LA;Lo;0;L;;;;;N;;;;; 1BDF;BATAK LETTER SIMALUNGUN LA;Lo;0;L;;;;;N;;;;; 1BE0;BATAK LETTER NYA;Lo;0;L;;;;;N;;;;; 1BE1;BATAK LETTER CA;Lo;0;L;;;;;N;;;;; 1BE2;BATAK LETTER NDA;Lo;0;L;;;;;N;;;;; 1BE3;BATAK LETTER MBA;Lo;0;L;;;;;N;;;;; 1BE4;BATAK LETTER I;Lo;0;L;;;;;N;;;;; 1BE5;BATAK LETTER U;Lo;0;L;;;;;N;;;;; 1BE6;BATAK SIGN TOMPI;Mn;7;NSM;;;;;N;;;;; 1BE7;BATAK VOWEL SIGN E;Mc;0;L;;;;;N;;;;; 1BE8;BATAK VOWEL SIGN PAKPAK E;Mn;0;NSM;;;;;N;;;;; 1BE9;BATAK VOWEL SIGN EE;Mn;0;NSM;;;;;N;;;;; 1BEA;BATAK VOWEL SIGN I;Mc;0;L;;;;;N;;;;; 1BEB;BATAK VOWEL SIGN KARO I;Mc;0;L;;;;;N;;;;; 1BEC;BATAK VOWEL SIGN O;Mc;0;L;;;;;N;;;;; 1BED;BATAK VOWEL SIGN KARO O;Mn;0;NSM;;;;;N;;;;; 1BEE;BATAK VOWEL SIGN U;Mc;0;L;;;;;N;;;;; 1BEF;BATAK VOWEL SIGN U FOR SIMALUNGUN SA;Mn;0;NSM;;;;;N;;;;; 1BF0;BATAK CONSONANT SIGN NG;Mn;0;NSM;;;;;N;;;;; 1BF1;BATAK CONSONANT SIGN H;Mn;0;NSM;;;;;N;;;;; 1BF2;BATAK PANGOLAT;Mc;9;L;;;;;N;;;;; 1BF3;BATAK PANONGONAN;Mc;9;L;;;;;N;;;;; 1BFC;BATAK SYMBOL BINDU NA METEK;Po;0;L;;;;;N;;;;; 1BFD;BATAK SYMBOL BINDU PINARBORAS;Po;0;L;;;;;N;;;;; 1BFE;BATAK SYMBOL BINDU JUDUL;Po;0;L;;;;;N;;;;; 1BFF;BATAK SYMBOL BINDU PANGOLAT;Po;0;L;;;;;N;;;;; 1C00;LEPCHA LETTER KA;Lo;0;L;;;;;N;;;;; 1C01;LEPCHA LETTER KLA;Lo;0;L;;;;;N;;;;; 1C02;LEPCHA LETTER KHA;Lo;0;L;;;;;N;;;;; 1C03;LEPCHA LETTER GA;Lo;0;L;;;;;N;;;;; 1C04;LEPCHA LETTER GLA;Lo;0;L;;;;;N;;;;; 1C05;LEPCHA LETTER NGA;Lo;0;L;;;;;N;;;;; 1C06;LEPCHA LETTER CA;Lo;0;L;;;;;N;;;;; 1C07;LEPCHA LETTER CHA;Lo;0;L;;;;;N;;;;; 1C08;LEPCHA LETTER JA;Lo;0;L;;;;;N;;;;; 1C09;LEPCHA LETTER NYA;Lo;0;L;;;;;N;;;;; 1C0A;LEPCHA LETTER TA;Lo;0;L;;;;;N;;;;; 1C0B;LEPCHA LETTER THA;Lo;0;L;;;;;N;;;;; 1C0C;LEPCHA LETTER DA;Lo;0;L;;;;;N;;;;; 1C0D;LEPCHA LETTER NA;Lo;0;L;;;;;N;;;;; 1C0E;LEPCHA LETTER PA;Lo;0;L;;;;;N;;;;; 1C0F;LEPCHA LETTER PLA;Lo;0;L;;;;;N;;;;; 1C10;LEPCHA LETTER PHA;Lo;0;L;;;;;N;;;;; 1C11;LEPCHA LETTER FA;Lo;0;L;;;;;N;;;;; 1C12;LEPCHA LETTER FLA;Lo;0;L;;;;;N;;;;; 1C13;LEPCHA LETTER BA;Lo;0;L;;;;;N;;;;; 1C14;LEPCHA LETTER BLA;Lo;0;L;;;;;N;;;;; 1C15;LEPCHA LETTER MA;Lo;0;L;;;;;N;;;;; 1C16;LEPCHA LETTER MLA;Lo;0;L;;;;;N;;;;; 1C17;LEPCHA LETTER TSA;Lo;0;L;;;;;N;;;;; 1C18;LEPCHA LETTER TSHA;Lo;0;L;;;;;N;;;;; 1C19;LEPCHA LETTER DZA;Lo;0;L;;;;;N;;;;; 1C1A;LEPCHA LETTER YA;Lo;0;L;;;;;N;;;;; 1C1B;LEPCHA LETTER RA;Lo;0;L;;;;;N;;;;; 1C1C;LEPCHA LETTER LA;Lo;0;L;;;;;N;;;;; 1C1D;LEPCHA LETTER HA;Lo;0;L;;;;;N;;;;; 1C1E;LEPCHA LETTER HLA;Lo;0;L;;;;;N;;;;; 1C1F;LEPCHA LETTER VA;Lo;0;L;;;;;N;;;;; 1C20;LEPCHA LETTER SA;Lo;0;L;;;;;N;;;;; 1C21;LEPCHA LETTER SHA;Lo;0;L;;;;;N;;;;; 1C22;LEPCHA LETTER WA;Lo;0;L;;;;;N;;;;; 1C23;LEPCHA LETTER A;Lo;0;L;;;;;N;;;;; 1C24;LEPCHA SUBJOINED LETTER YA;Mc;0;L;;;;;N;;;;; 1C25;LEPCHA SUBJOINED LETTER RA;Mc;0;L;;;;;N;;;;; 1C26;LEPCHA VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 1C27;LEPCHA VOWEL SIGN I;Mc;0;L;;;;;N;;;;; 1C28;LEPCHA VOWEL SIGN O;Mc;0;L;;;;;N;;;;; 1C29;LEPCHA VOWEL SIGN OO;Mc;0;L;;;;;N;;;;; 1C2A;LEPCHA VOWEL SIGN U;Mc;0;L;;;;;N;;;;; 1C2B;LEPCHA VOWEL SIGN UU;Mc;0;L;;;;;N;;;;; 1C2C;LEPCHA VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; 1C2D;LEPCHA CONSONANT SIGN K;Mn;0;NSM;;;;;N;;;;; 1C2E;LEPCHA CONSONANT SIGN M;Mn;0;NSM;;;;;N;;;;; 1C2F;LEPCHA CONSONANT SIGN L;Mn;0;NSM;;;;;N;;;;; 1C30;LEPCHA CONSONANT SIGN N;Mn;0;NSM;;;;;N;;;;; 1C31;LEPCHA CONSONANT SIGN P;Mn;0;NSM;;;;;N;;;;; 1C32;LEPCHA CONSONANT SIGN R;Mn;0;NSM;;;;;N;;;;; 1C33;LEPCHA CONSONANT SIGN T;Mn;0;NSM;;;;;N;;;;; 1C34;LEPCHA CONSONANT SIGN NYIN-DO;Mc;0;L;;;;;N;;;;; 1C35;LEPCHA CONSONANT SIGN KANG;Mc;0;L;;;;;N;;;;; 1C36;LEPCHA SIGN RAN;Mn;0;NSM;;;;;N;;;;; 1C37;LEPCHA SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; 1C3B;LEPCHA PUNCTUATION TA-ROL;Po;0;L;;;;;N;;;;; 1C3C;LEPCHA PUNCTUATION NYET THYOOM TA-ROL;Po;0;L;;;;;N;;;;; 1C3D;LEPCHA PUNCTUATION CER-WA;Po;0;L;;;;;N;;;;; 1C3E;LEPCHA PUNCTUATION TSHOOK CER-WA;Po;0;L;;;;;N;;;;; 1C3F;LEPCHA PUNCTUATION TSHOOK;Po;0;L;;;;;N;;;;; 1C40;LEPCHA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 1C41;LEPCHA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 1C42;LEPCHA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 1C43;LEPCHA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 1C44;LEPCHA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 1C45;LEPCHA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 1C46;LEPCHA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 1C47;LEPCHA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 1C48;LEPCHA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 1C49;LEPCHA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 1C4D;LEPCHA LETTER TTA;Lo;0;L;;;;;N;;;;; 1C4E;LEPCHA LETTER TTHA;Lo;0;L;;;;;N;;;;; 1C4F;LEPCHA LETTER DDA;Lo;0;L;;;;;N;;;;; 1C50;OL CHIKI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 1C51;OL CHIKI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 1C52;OL CHIKI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 1C53;OL CHIKI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 1C54;OL CHIKI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 1C55;OL CHIKI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 1C56;OL CHIKI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 1C57;OL CHIKI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 1C58;OL CHIKI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 1C59;OL CHIKI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 1C5A;OL CHIKI LETTER LA;Lo;0;L;;;;;N;;;;; 1C5B;OL CHIKI LETTER AT;Lo;0;L;;;;;N;;;;; 1C5C;OL CHIKI LETTER AG;Lo;0;L;;;;;N;;;;; 1C5D;OL CHIKI LETTER ANG;Lo;0;L;;;;;N;;;;; 1C5E;OL CHIKI LETTER AL;Lo;0;L;;;;;N;;;;; 1C5F;OL CHIKI LETTER LAA;Lo;0;L;;;;;N;;;;; 1C60;OL CHIKI LETTER AAK;Lo;0;L;;;;;N;;;;; 1C61;OL CHIKI LETTER AAJ;Lo;0;L;;;;;N;;;;; 1C62;OL CHIKI LETTER AAM;Lo;0;L;;;;;N;;;;; 1C63;OL CHIKI LETTER AAW;Lo;0;L;;;;;N;;;;; 1C64;OL CHIKI LETTER LI;Lo;0;L;;;;;N;;;;; 1C65;OL CHIKI LETTER IS;Lo;0;L;;;;;N;;;;; 1C66;OL CHIKI LETTER IH;Lo;0;L;;;;;N;;;;; 1C67;OL CHIKI LETTER INY;Lo;0;L;;;;;N;;;;; 1C68;OL CHIKI LETTER IR;Lo;0;L;;;;;N;;;;; 1C69;OL CHIKI LETTER LU;Lo;0;L;;;;;N;;;;; 1C6A;OL CHIKI LETTER UC;Lo;0;L;;;;;N;;;;; 1C6B;OL CHIKI LETTER UD;Lo;0;L;;;;;N;;;;; 1C6C;OL CHIKI LETTER UNN;Lo;0;L;;;;;N;;;;; 1C6D;OL CHIKI LETTER UY;Lo;0;L;;;;;N;;;;; 1C6E;OL CHIKI LETTER LE;Lo;0;L;;;;;N;;;;; 1C6F;OL CHIKI LETTER EP;Lo;0;L;;;;;N;;;;; 1C70;OL CHIKI LETTER EDD;Lo;0;L;;;;;N;;;;; 1C71;OL CHIKI LETTER EN;Lo;0;L;;;;;N;;;;; 1C72;OL CHIKI LETTER ERR;Lo;0;L;;;;;N;;;;; 1C73;OL CHIKI LETTER LO;Lo;0;L;;;;;N;;;;; 1C74;OL CHIKI LETTER OTT;Lo;0;L;;;;;N;;;;; 1C75;OL CHIKI LETTER OB;Lo;0;L;;;;;N;;;;; 1C76;OL CHIKI LETTER OV;Lo;0;L;;;;;N;;;;; 1C77;OL CHIKI LETTER OH;Lo;0;L;;;;;N;;;;; 1C78;OL CHIKI MU TTUDDAG;Lm;0;L;;;;;N;;;;; 1C79;OL CHIKI GAAHLAA TTUDDAAG;Lm;0;L;;;;;N;;;;; 1C7A;OL CHIKI MU-GAAHLAA TTUDDAAG;Lm;0;L;;;;;N;;;;; 1C7B;OL CHIKI RELAA;Lm;0;L;;;;;N;;;;; 1C7C;OL CHIKI PHAARKAA;Lm;0;L;;;;;N;;;;; 1C7D;OL CHIKI AHAD;Lm;0;L;;;;;N;;;;; 1C7E;OL CHIKI PUNCTUATION MUCAAD;Po;0;L;;;;;N;;;;; 1C7F;OL CHIKI PUNCTUATION DOUBLE MUCAAD;Po;0;L;;;;;N;;;;; 1C80;CYRILLIC SMALL LETTER ROUNDED VE;Ll;0;L;;;;;N;;;0412;;0412 1C81;CYRILLIC SMALL LETTER LONG-LEGGED DE;Ll;0;L;;;;;N;;;0414;;0414 1C82;CYRILLIC SMALL LETTER NARROW O;Ll;0;L;;;;;N;;;041E;;041E 1C83;CYRILLIC SMALL LETTER WIDE ES;Ll;0;L;;;;;N;;;0421;;0421 1C84;CYRILLIC SMALL LETTER TALL TE;Ll;0;L;;;;;N;;;0422;;0422 1C85;CYRILLIC SMALL LETTER THREE-LEGGED TE;Ll;0;L;;;;;N;;;0422;;0422 1C86;CYRILLIC SMALL LETTER TALL HARD SIGN;Ll;0;L;;;;;N;;;042A;;042A 1C87;CYRILLIC SMALL LETTER TALL YAT;Ll;0;L;;;;;N;;;0462;;0462 1C88;CYRILLIC SMALL LETTER UNBLENDED UK;Ll;0;L;;;;;N;;;A64A;;A64A 1CC0;SUNDANESE PUNCTUATION BINDU SURYA;Po;0;L;;;;;N;;;;; 1CC1;SUNDANESE PUNCTUATION BINDU PANGLONG;Po;0;L;;;;;N;;;;; 1CC2;SUNDANESE PUNCTUATION BINDU PURNAMA;Po;0;L;;;;;N;;;;; 1CC3;SUNDANESE PUNCTUATION BINDU CAKRA;Po;0;L;;;;;N;;;;; 1CC4;SUNDANESE PUNCTUATION BINDU LEU SATANGA;Po;0;L;;;;;N;;;;; 1CC5;SUNDANESE PUNCTUATION BINDU KA SATANGA;Po;0;L;;;;;N;;;;; 1CC6;SUNDANESE PUNCTUATION BINDU DA SATANGA;Po;0;L;;;;;N;;;;; 1CC7;SUNDANESE PUNCTUATION BINDU BA SATANGA;Po;0;L;;;;;N;;;;; 1CD0;VEDIC TONE KARSHANA;Mn;230;NSM;;;;;N;;;;; 1CD1;VEDIC TONE SHARA;Mn;230;NSM;;;;;N;;;;; 1CD2;VEDIC TONE PRENKHA;Mn;230;NSM;;;;;N;;;;; 1CD3;VEDIC SIGN NIHSHVASA;Po;0;L;;;;;N;;;;; 1CD4;VEDIC SIGN YAJURVEDIC MIDLINE SVARITA;Mn;1;NSM;;;;;N;;;;; 1CD5;VEDIC TONE YAJURVEDIC AGGRAVATED INDEPENDENT SVARITA;Mn;220;NSM;;;;;N;;;;; 1CD6;VEDIC TONE YAJURVEDIC INDEPENDENT SVARITA;Mn;220;NSM;;;;;N;;;;; 1CD7;VEDIC TONE YAJURVEDIC KATHAKA INDEPENDENT SVARITA;Mn;220;NSM;;;;;N;;;;; 1CD8;VEDIC TONE CANDRA BELOW;Mn;220;NSM;;;;;N;;;;; 1CD9;VEDIC TONE YAJURVEDIC KATHAKA INDEPENDENT SVARITA SCHROEDER;Mn;220;NSM;;;;;N;;;;; 1CDA;VEDIC TONE DOUBLE SVARITA;Mn;230;NSM;;;;;N;;;;; 1CDB;VEDIC TONE TRIPLE SVARITA;Mn;230;NSM;;;;;N;;;;; 1CDC;VEDIC TONE KATHAKA ANUDATTA;Mn;220;NSM;;;;;N;;;;; 1CDD;VEDIC TONE DOT BELOW;Mn;220;NSM;;;;;N;;;;; 1CDE;VEDIC TONE TWO DOTS BELOW;Mn;220;NSM;;;;;N;;;;; 1CDF;VEDIC TONE THREE DOTS BELOW;Mn;220;NSM;;;;;N;;;;; 1CE0;VEDIC TONE RIGVEDIC KASHMIRI INDEPENDENT SVARITA;Mn;230;NSM;;;;;N;;;;; 1CE1;VEDIC TONE ATHARVAVEDIC INDEPENDENT SVARITA;Mc;0;L;;;;;N;;;;; 1CE2;VEDIC SIGN VISARGA SVARITA;Mn;1;NSM;;;;;N;;;;; 1CE3;VEDIC SIGN VISARGA UDATTA;Mn;1;NSM;;;;;N;;;;; 1CE4;VEDIC SIGN REVERSED VISARGA UDATTA;Mn;1;NSM;;;;;N;;;;; 1CE5;VEDIC SIGN VISARGA ANUDATTA;Mn;1;NSM;;;;;N;;;;; 1CE6;VEDIC SIGN REVERSED VISARGA ANUDATTA;Mn;1;NSM;;;;;N;;;;; 1CE7;VEDIC SIGN VISARGA UDATTA WITH TAIL;Mn;1;NSM;;;;;N;;;;; 1CE8;VEDIC SIGN VISARGA ANUDATTA WITH TAIL;Mn;1;NSM;;;;;N;;;;; 1CE9;VEDIC SIGN ANUSVARA ANTARGOMUKHA;Lo;0;L;;;;;N;;;;; 1CEA;VEDIC SIGN ANUSVARA BAHIRGOMUKHA;Lo;0;L;;;;;N;;;;; 1CEB;VEDIC SIGN ANUSVARA VAMAGOMUKHA;Lo;0;L;;;;;N;;;;; 1CEC;VEDIC SIGN ANUSVARA VAMAGOMUKHA WITH TAIL;Lo;0;L;;;;;N;;;;; 1CED;VEDIC SIGN TIRYAK;Mn;220;NSM;;;;;N;;;;; 1CEE;VEDIC SIGN HEXIFORM LONG ANUSVARA;Lo;0;L;;;;;N;;;;; 1CEF;VEDIC SIGN LONG ANUSVARA;Lo;0;L;;;;;N;;;;; 1CF0;VEDIC SIGN RTHANG LONG ANUSVARA;Lo;0;L;;;;;N;;;;; 1CF1;VEDIC SIGN ANUSVARA UBHAYATO MUKHA;Lo;0;L;;;;;N;;;;; 1CF2;VEDIC SIGN ARDHAVISARGA;Mc;0;L;;;;;N;;;;; 1CF3;VEDIC SIGN ROTATED ARDHAVISARGA;Mc;0;L;;;;;N;;;;; 1CF4;VEDIC TONE CANDRA ABOVE;Mn;230;NSM;;;;;N;;;;; 1CF5;VEDIC SIGN JIHVAMULIYA;Lo;0;L;;;;;N;;;;; 1CF6;VEDIC SIGN UPADHMANIYA;Lo;0;L;;;;;N;;;;; 1CF8;VEDIC TONE RING ABOVE;Mn;230;NSM;;;;;N;;;;; 1CF9;VEDIC TONE DOUBLE RING ABOVE;Mn;230;NSM;;;;;N;;;;; 1D00;LATIN LETTER SMALL CAPITAL A;Ll;0;L;;;;;N;;;;; 1D01;LATIN LETTER SMALL CAPITAL AE;Ll;0;L;;;;;N;;;;; 1D02;LATIN SMALL LETTER TURNED AE;Ll;0;L;;;;;N;;;;; 1D03;LATIN LETTER SMALL CAPITAL BARRED B;Ll;0;L;;;;;N;;;;; 1D04;LATIN LETTER SMALL CAPITAL C;Ll;0;L;;;;;N;;;;; 1D05;LATIN LETTER SMALL CAPITAL D;Ll;0;L;;;;;N;;;;; 1D06;LATIN LETTER SMALL CAPITAL ETH;Ll;0;L;;;;;N;;;;; 1D07;LATIN LETTER SMALL CAPITAL E;Ll;0;L;;;;;N;;;;; 1D08;LATIN SMALL LETTER TURNED OPEN E;Ll;0;L;;;;;N;;;;; 1D09;LATIN SMALL LETTER TURNED I;Ll;0;L;;;;;N;;;;; 1D0A;LATIN LETTER SMALL CAPITAL J;Ll;0;L;;;;;N;;;;; 1D0B;LATIN LETTER SMALL CAPITAL K;Ll;0;L;;;;;N;;;;; 1D0C;LATIN LETTER SMALL CAPITAL L WITH STROKE;Ll;0;L;;;;;N;;;;; 1D0D;LATIN LETTER SMALL CAPITAL M;Ll;0;L;;;;;N;;;;; 1D0E;LATIN LETTER SMALL CAPITAL REVERSED N;Ll;0;L;;;;;N;;;;; 1D0F;LATIN LETTER SMALL CAPITAL O;Ll;0;L;;;;;N;;;;; 1D10;LATIN LETTER SMALL CAPITAL OPEN O;Ll;0;L;;;;;N;;;;; 1D11;LATIN SMALL LETTER SIDEWAYS O;Ll;0;L;;;;;N;;;;; 1D12;LATIN SMALL LETTER SIDEWAYS OPEN O;Ll;0;L;;;;;N;;;;; 1D13;LATIN SMALL LETTER SIDEWAYS O WITH STROKE;Ll;0;L;;;;;N;;;;; 1D14;LATIN SMALL LETTER TURNED OE;Ll;0;L;;;;;N;;;;; 1D15;LATIN LETTER SMALL CAPITAL OU;Ll;0;L;;;;;N;;;;; 1D16;LATIN SMALL LETTER TOP HALF O;Ll;0;L;;;;;N;;;;; 1D17;LATIN SMALL LETTER BOTTOM HALF O;Ll;0;L;;;;;N;;;;; 1D18;LATIN LETTER SMALL CAPITAL P;Ll;0;L;;;;;N;;;;; 1D19;LATIN LETTER SMALL CAPITAL REVERSED R;Ll;0;L;;;;;N;;;;; 1D1A;LATIN LETTER SMALL CAPITAL TURNED R;Ll;0;L;;;;;N;;;;; 1D1B;LATIN LETTER SMALL CAPITAL T;Ll;0;L;;;;;N;;;;; 1D1C;LATIN LETTER SMALL CAPITAL U;Ll;0;L;;;;;N;;;;; 1D1D;LATIN SMALL LETTER SIDEWAYS U;Ll;0;L;;;;;N;;;;; 1D1E;LATIN SMALL LETTER SIDEWAYS DIAERESIZED U;Ll;0;L;;;;;N;;;;; 1D1F;LATIN SMALL LETTER SIDEWAYS TURNED M;Ll;0;L;;;;;N;;;;; 1D20;LATIN LETTER SMALL CAPITAL V;Ll;0;L;;;;;N;;;;; 1D21;LATIN LETTER SMALL CAPITAL W;Ll;0;L;;;;;N;;;;; 1D22;LATIN LETTER SMALL CAPITAL Z;Ll;0;L;;;;;N;;;;; 1D23;LATIN LETTER SMALL CAPITAL EZH;Ll;0;L;;;;;N;;;;; 1D24;LATIN LETTER VOICED LARYNGEAL SPIRANT;Ll;0;L;;;;;N;;;;; 1D25;LATIN LETTER AIN;Ll;0;L;;;;;N;;;;; 1D26;GREEK LETTER SMALL CAPITAL GAMMA;Ll;0;L;;;;;N;;;;; 1D27;GREEK LETTER SMALL CAPITAL LAMDA;Ll;0;L;;;;;N;;;;; 1D28;GREEK LETTER SMALL CAPITAL PI;Ll;0;L;;;;;N;;;;; 1D29;GREEK LETTER SMALL CAPITAL RHO;Ll;0;L;;;;;N;;;;; 1D2A;GREEK LETTER SMALL CAPITAL PSI;Ll;0;L;;;;;N;;;;; 1D2B;CYRILLIC LETTER SMALL CAPITAL EL;Ll;0;L;;;;;N;;;;; 1D2C;MODIFIER LETTER CAPITAL A;Lm;0;L;<super> 0041;;;;N;;;;; 1D2D;MODIFIER LETTER CAPITAL AE;Lm;0;L;<super> 00C6;;;;N;;;;; 1D2E;MODIFIER LETTER CAPITAL B;Lm;0;L;<super> 0042;;;;N;;;;; 1D2F;MODIFIER LETTER CAPITAL BARRED B;Lm;0;L;;;;;N;;;;; 1D30;MODIFIER LETTER CAPITAL D;Lm;0;L;<super> 0044;;;;N;;;;; 1D31;MODIFIER LETTER CAPITAL E;Lm;0;L;<super> 0045;;;;N;;;;; 1D32;MODIFIER LETTER CAPITAL REVERSED E;Lm;0;L;<super> 018E;;;;N;;;;; 1D33;MODIFIER LETTER CAPITAL G;Lm;0;L;<super> 0047;;;;N;;;;; 1D34;MODIFIER LETTER CAPITAL H;Lm;0;L;<super> 0048;;;;N;;;;; 1D35;MODIFIER LETTER CAPITAL I;Lm;0;L;<super> 0049;;;;N;;;;; 1D36;MODIFIER LETTER CAPITAL J;Lm;0;L;<super> 004A;;;;N;;;;; 1D37;MODIFIER LETTER CAPITAL K;Lm;0;L;<super> 004B;;;;N;;;;; 1D38;MODIFIER LETTER CAPITAL L;Lm;0;L;<super> 004C;;;;N;;;;; 1D39;MODIFIER LETTER CAPITAL M;Lm;0;L;<super> 004D;;;;N;;;;; 1D3A;MODIFIER LETTER CAPITAL N;Lm;0;L;<super> 004E;;;;N;;;;; 1D3B;MODIFIER LETTER CAPITAL REVERSED N;Lm;0;L;;;;;N;;;;; 1D3C;MODIFIER LETTER CAPITAL O;Lm;0;L;<super> 004F;;;;N;;;;; 1D3D;MODIFIER LETTER CAPITAL OU;Lm;0;L;<super> 0222;;;;N;;;;; 1D3E;MODIFIER LETTER CAPITAL P;Lm;0;L;<super> 0050;;;;N;;;;; 1D3F;MODIFIER LETTER CAPITAL R;Lm;0;L;<super> 0052;;;;N;;;;; 1D40;MODIFIER LETTER CAPITAL T;Lm;0;L;<super> 0054;;;;N;;;;; 1D41;MODIFIER LETTER CAPITAL U;Lm;0;L;<super> 0055;;;;N;;;;; 1D42;MODIFIER LETTER CAPITAL W;Lm;0;L;<super> 0057;;;;N;;;;; 1D43;MODIFIER LETTER SMALL A;Lm;0;L;<super> 0061;;;;N;;;;; 1D44;MODIFIER LETTER SMALL TURNED A;Lm;0;L;<super> 0250;;;;N;;;;; 1D45;MODIFIER LETTER SMALL ALPHA;Lm;0;L;<super> 0251;;;;N;;;;; 1D46;MODIFIER LETTER SMALL TURNED AE;Lm;0;L;<super> 1D02;;;;N;;;;; 1D47;MODIFIER LETTER SMALL B;Lm;0;L;<super> 0062;;;;N;;;;; 1D48;MODIFIER LETTER SMALL D;Lm;0;L;<super> 0064;;;;N;;;;; 1D49;MODIFIER LETTER SMALL E;Lm;0;L;<super> 0065;;;;N;;;;; 1D4A;MODIFIER LETTER SMALL SCHWA;Lm;0;L;<super> 0259;;;;N;;;;; 1D4B;MODIFIER LETTER SMALL OPEN E;Lm;0;L;<super> 025B;;;;N;;;;; 1D4C;MODIFIER LETTER SMALL TURNED OPEN E;Lm;0;L;<super> 025C;;;;N;;;;; 1D4D;MODIFIER LETTER SMALL G;Lm;0;L;<super> 0067;;;;N;;;;; 1D4E;MODIFIER LETTER SMALL TURNED I;Lm;0;L;;;;;N;;;;; 1D4F;MODIFIER LETTER SMALL K;Lm;0;L;<super> 006B;;;;N;;;;; 1D50;MODIFIER LETTER SMALL M;Lm;0;L;<super> 006D;;;;N;;;;; 1D51;MODIFIER LETTER SMALL ENG;Lm;0;L;<super> 014B;;;;N;;;;; 1D52;MODIFIER LETTER SMALL O;Lm;0;L;<super> 006F;;;;N;;;;; 1D53;MODIFIER LETTER SMALL OPEN O;Lm;0;L;<super> 0254;;;;N;;;;; 1D54;MODIFIER LETTER SMALL TOP HALF O;Lm;0;L;<super> 1D16;;;;N;;;;; 1D55;MODIFIER LETTER SMALL BOTTOM HALF O;Lm;0;L;<super> 1D17;;;;N;;;;; 1D56;MODIFIER LETTER SMALL P;Lm;0;L;<super> 0070;;;;N;;;;; 1D57;MODIFIER LETTER SMALL T;Lm;0;L;<super> 0074;;;;N;;;;; 1D58;MODIFIER LETTER SMALL U;Lm;0;L;<super> 0075;;;;N;;;;; 1D59;MODIFIER LETTER SMALL SIDEWAYS U;Lm;0;L;<super> 1D1D;;;;N;;;;; 1D5A;MODIFIER LETTER SMALL TURNED M;Lm;0;L;<super> 026F;;;;N;;;;; 1D5B;MODIFIER LETTER SMALL V;Lm;0;L;<super> 0076;;;;N;;;;; 1D5C;MODIFIER LETTER SMALL AIN;Lm;0;L;<super> 1D25;;;;N;;;;; 1D5D;MODIFIER LETTER SMALL BETA;Lm;0;L;<super> 03B2;;;;N;;;;; 1D5E;MODIFIER LETTER SMALL GREEK GAMMA;Lm;0;L;<super> 03B3;;;;N;;;;; 1D5F;MODIFIER LETTER SMALL DELTA;Lm;0;L;<super> 03B4;;;;N;;;;; 1D60;MODIFIER LETTER SMALL GREEK PHI;Lm;0;L;<super> 03C6;;;;N;;;;; 1D61;MODIFIER LETTER SMALL CHI;Lm;0;L;<super> 03C7;;;;N;;;;; 1D62;LATIN SUBSCRIPT SMALL LETTER I;Lm;0;L;<sub> 0069;;;;N;;;;; 1D63;LATIN SUBSCRIPT SMALL LETTER R;Lm;0;L;<sub> 0072;;;;N;;;;; 1D64;LATIN SUBSCRIPT SMALL LETTER U;Lm;0;L;<sub> 0075;;;;N;;;;; 1D65;LATIN SUBSCRIPT SMALL LETTER V;Lm;0;L;<sub> 0076;;;;N;;;;; 1D66;GREEK SUBSCRIPT SMALL LETTER BETA;Lm;0;L;<sub> 03B2;;;;N;;;;; 1D67;GREEK SUBSCRIPT SMALL LETTER GAMMA;Lm;0;L;<sub> 03B3;;;;N;;;;; 1D68;GREEK SUBSCRIPT SMALL LETTER RHO;Lm;0;L;<sub> 03C1;;;;N;;;;; 1D69;GREEK SUBSCRIPT SMALL LETTER PHI;Lm;0;L;<sub> 03C6;;;;N;;;;; 1D6A;GREEK SUBSCRIPT SMALL LETTER CHI;Lm;0;L;<sub> 03C7;;;;N;;;;; 1D6B;LATIN SMALL LETTER UE;Ll;0;L;;;;;N;;;;; 1D6C;LATIN SMALL LETTER B WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;; 1D6D;LATIN SMALL LETTER D WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;; 1D6E;LATIN SMALL LETTER F WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;; 1D6F;LATIN SMALL LETTER M WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;; 1D70;LATIN SMALL LETTER N WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;; 1D71;LATIN SMALL LETTER P WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;; 1D72;LATIN SMALL LETTER R WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;; 1D73;LATIN SMALL LETTER R WITH FISHHOOK AND MIDDLE TILDE;Ll;0;L;;;;;N;;;;; 1D74;LATIN SMALL LETTER S WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;; 1D75;LATIN SMALL LETTER T WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;; 1D76;LATIN SMALL LETTER Z WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;; 1D77;LATIN SMALL LETTER TURNED G;Ll;0;L;;;;;N;;;;; 1D78;MODIFIER LETTER CYRILLIC EN;Lm;0;L;<super> 043D;;;;N;;;;; 1D79;LATIN SMALL LETTER INSULAR G;Ll;0;L;;;;;N;;;A77D;;A77D 1D7A;LATIN SMALL LETTER TH WITH STRIKETHROUGH;Ll;0;L;;;;;N;;;;; 1D7B;LATIN SMALL CAPITAL LETTER I WITH STROKE;Ll;0;L;;;;;N;;;;; 1D7C;LATIN SMALL LETTER IOTA WITH STROKE;Ll;0;L;;;;;N;;;;; 1D7D;LATIN SMALL LETTER P WITH STROKE;Ll;0;L;;;;;N;;;2C63;;2C63 1D7E;LATIN SMALL CAPITAL LETTER U WITH STROKE;Ll;0;L;;;;;N;;;;; 1D7F;LATIN SMALL LETTER UPSILON WITH STROKE;Ll;0;L;;;;;N;;;;; 1D80;LATIN SMALL LETTER B WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; 1D81;LATIN SMALL LETTER D WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; 1D82;LATIN SMALL LETTER F WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; 1D83;LATIN SMALL LETTER G WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; 1D84;LATIN SMALL LETTER K WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; 1D85;LATIN SMALL LETTER L WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; 1D86;LATIN SMALL LETTER M WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; 1D87;LATIN SMALL LETTER N WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; 1D88;LATIN SMALL LETTER P WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; 1D89;LATIN SMALL LETTER R WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; 1D8A;LATIN SMALL LETTER S WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; 1D8B;LATIN SMALL LETTER ESH WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; 1D8C;LATIN SMALL LETTER V WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; 1D8D;LATIN SMALL LETTER X WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; 1D8E;LATIN SMALL LETTER Z WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; 1D8F;LATIN SMALL LETTER A WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; 1D90;LATIN SMALL LETTER ALPHA WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; 1D91;LATIN SMALL LETTER D WITH HOOK AND TAIL;Ll;0;L;;;;;N;;;;; 1D92;LATIN SMALL LETTER E WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; 1D93;LATIN SMALL LETTER OPEN E WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; 1D94;LATIN SMALL LETTER REVERSED OPEN E WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; 1D95;LATIN SMALL LETTER SCHWA WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; 1D96;LATIN SMALL LETTER I WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; 1D97;LATIN SMALL LETTER OPEN O WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; 1D98;LATIN SMALL LETTER ESH WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; 1D99;LATIN SMALL LETTER U WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; 1D9A;LATIN SMALL LETTER EZH WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; 1D9B;MODIFIER LETTER SMALL TURNED ALPHA;Lm;0;L;<super> 0252;;;;N;;;;; 1D9C;MODIFIER LETTER SMALL C;Lm;0;L;<super> 0063;;;;N;;;;; 1D9D;MODIFIER LETTER SMALL C WITH CURL;Lm;0;L;<super> 0255;;;;N;;;;; 1D9E;MODIFIER LETTER SMALL ETH;Lm;0;L;<super> 00F0;;;;N;;;;; 1D9F;MODIFIER LETTER SMALL REVERSED OPEN E;Lm;0;L;<super> 025C;;;;N;;;;; 1DA0;MODIFIER LETTER SMALL F;Lm;0;L;<super> 0066;;;;N;;;;; 1DA1;MODIFIER LETTER SMALL DOTLESS J WITH STROKE;Lm;0;L;<super> 025F;;;;N;;;;; 1DA2;MODIFIER LETTER SMALL SCRIPT G;Lm;0;L;<super> 0261;;;;N;;;;; 1DA3;MODIFIER LETTER SMALL TURNED H;Lm;0;L;<super> 0265;;;;N;;;;; 1DA4;MODIFIER LETTER SMALL I WITH STROKE;Lm;0;L;<super> 0268;;;;N;;;;; 1DA5;MODIFIER LETTER SMALL IOTA;Lm;0;L;<super> 0269;;;;N;;;;; 1DA6;MODIFIER LETTER SMALL CAPITAL I;Lm;0;L;<super> 026A;;;;N;;;;; 1DA7;MODIFIER LETTER SMALL CAPITAL I WITH STROKE;Lm;0;L;<super> 1D7B;;;;N;;;;; 1DA8;MODIFIER LETTER SMALL J WITH CROSSED-TAIL;Lm;0;L;<super> 029D;;;;N;;;;; 1DA9;MODIFIER LETTER SMALL L WITH RETROFLEX HOOK;Lm;0;L;<super> 026D;;;;N;;;;; 1DAA;MODIFIER LETTER SMALL L WITH PALATAL HOOK;Lm;0;L;<super> 1D85;;;;N;;;;; 1DAB;MODIFIER LETTER SMALL CAPITAL L;Lm;0;L;<super> 029F;;;;N;;;;; 1DAC;MODIFIER LETTER SMALL M WITH HOOK;Lm;0;L;<super> 0271;;;;N;;;;; 1DAD;MODIFIER LETTER SMALL TURNED M WITH LONG LEG;Lm;0;L;<super> 0270;;;;N;;;;; 1DAE;MODIFIER LETTER SMALL N WITH LEFT HOOK;Lm;0;L;<super> 0272;;;;N;;;;; 1DAF;MODIFIER LETTER SMALL N WITH RETROFLEX HOOK;Lm;0;L;<super> 0273;;;;N;;;;; 1DB0;MODIFIER LETTER SMALL CAPITAL N;Lm;0;L;<super> 0274;;;;N;;;;; 1DB1;MODIFIER LETTER SMALL BARRED O;Lm;0;L;<super> 0275;;;;N;;;;; 1DB2;MODIFIER LETTER SMALL PHI;Lm;0;L;<super> 0278;;;;N;;;;; 1DB3;MODIFIER LETTER SMALL S WITH HOOK;Lm;0;L;<super> 0282;;;;N;;;;; 1DB4;MODIFIER LETTER SMALL ESH;Lm;0;L;<super> 0283;;;;N;;;;; 1DB5;MODIFIER LETTER SMALL T WITH PALATAL HOOK;Lm;0;L;<super> 01AB;;;;N;;;;; 1DB6;MODIFIER LETTER SMALL U BAR;Lm;0;L;<super> 0289;;;;N;;;;; 1DB7;MODIFIER LETTER SMALL UPSILON;Lm;0;L;<super> 028A;;;;N;;;;; 1DB8;MODIFIER LETTER SMALL CAPITAL U;Lm;0;L;<super> 1D1C;;;;N;;;;; 1DB9;MODIFIER LETTER SMALL V WITH HOOK;Lm;0;L;<super> 028B;;;;N;;;;; 1DBA;MODIFIER LETTER SMALL TURNED V;Lm;0;L;<super> 028C;;;;N;;;;; 1DBB;MODIFIER LETTER SMALL Z;Lm;0;L;<super> 007A;;;;N;;;;; 1DBC;MODIFIER LETTER SMALL Z WITH RETROFLEX HOOK;Lm;0;L;<super> 0290;;;;N;;;;; 1DBD;MODIFIER LETTER SMALL Z WITH CURL;Lm;0;L;<super> 0291;;;;N;;;;; 1DBE;MODIFIER LETTER SMALL EZH;Lm;0;L;<super> 0292;;;;N;;;;; 1DBF;MODIFIER LETTER SMALL THETA;Lm;0;L;<super> 03B8;;;;N;;;;; 1DC0;COMBINING DOTTED GRAVE ACCENT;Mn;230;NSM;;;;;N;;;;; 1DC1;COMBINING DOTTED ACUTE ACCENT;Mn;230;NSM;;;;;N;;;;; 1DC2;COMBINING SNAKE BELOW;Mn;220;NSM;;;;;N;;;;; 1DC3;COMBINING SUSPENSION MARK;Mn;230;NSM;;;;;N;;;;; 1DC4;COMBINING MACRON-ACUTE;Mn;230;NSM;;;;;N;;;;; 1DC5;COMBINING GRAVE-MACRON;Mn;230;NSM;;;;;N;;;;; 1DC6;COMBINING MACRON-GRAVE;Mn;230;NSM;;;;;N;;;;; 1DC7;COMBINING ACUTE-MACRON;Mn;230;NSM;;;;;N;;;;; 1DC8;COMBINING GRAVE-ACUTE-GRAVE;Mn;230;NSM;;;;;N;;;;; 1DC9;COMBINING ACUTE-GRAVE-ACUTE;Mn;230;NSM;;;;;N;;;;; 1DCA;COMBINING LATIN SMALL LETTER R BELOW;Mn;220;NSM;;;;;N;;;;; 1DCB;COMBINING BREVE-MACRON;Mn;230;NSM;;;;;N;;;;; 1DCC;COMBINING MACRON-BREVE;Mn;230;NSM;;;;;N;;;;; 1DCD;COMBINING DOUBLE CIRCUMFLEX ABOVE;Mn;234;NSM;;;;;N;;;;; 1DCE;COMBINING OGONEK ABOVE;Mn;214;NSM;;;;;N;;;;; 1DCF;COMBINING ZIGZAG BELOW;Mn;220;NSM;;;;;N;;;;; 1DD0;COMBINING IS BELOW;Mn;202;NSM;;;;;N;;;;; 1DD1;COMBINING UR ABOVE;Mn;230;NSM;;;;;N;;;;; 1DD2;COMBINING US ABOVE;Mn;230;NSM;;;;;N;;;;; 1DD3;COMBINING LATIN SMALL LETTER FLATTENED OPEN A ABOVE;Mn;230;NSM;;;;;N;;;;; 1DD4;COMBINING LATIN SMALL LETTER AE;Mn;230;NSM;;;;;N;;;;; 1DD5;COMBINING LATIN SMALL LETTER AO;Mn;230;NSM;;;;;N;;;;; 1DD6;COMBINING LATIN SMALL LETTER AV;Mn;230;NSM;;;;;N;;;;; 1DD7;COMBINING LATIN SMALL LETTER C CEDILLA;Mn;230;NSM;;;;;N;;;;; 1DD8;COMBINING LATIN SMALL LETTER INSULAR D;Mn;230;NSM;;;;;N;;;;; 1DD9;COMBINING LATIN SMALL LETTER ETH;Mn;230;NSM;;;;;N;;;;; 1DDA;COMBINING LATIN SMALL LETTER G;Mn;230;NSM;;;;;N;;;;; 1DDB;COMBINING LATIN LETTER SMALL CAPITAL G;Mn;230;NSM;;;;;N;;;;; 1DDC;COMBINING LATIN SMALL LETTER K;Mn;230;NSM;;;;;N;;;;; 1DDD;COMBINING LATIN SMALL LETTER L;Mn;230;NSM;;;;;N;;;;; 1DDE;COMBINING LATIN LETTER SMALL CAPITAL L;Mn;230;NSM;;;;;N;;;;; 1DDF;COMBINING LATIN LETTER SMALL CAPITAL M;Mn;230;NSM;;;;;N;;;;; 1DE0;COMBINING LATIN SMALL LETTER N;Mn;230;NSM;;;;;N;;;;; 1DE1;COMBINING LATIN LETTER SMALL CAPITAL N;Mn;230;NSM;;;;;N;;;;; 1DE2;COMBINING LATIN LETTER SMALL CAPITAL R;Mn;230;NSM;;;;;N;;;;; 1DE3;COMBINING LATIN SMALL LETTER R ROTUNDA;Mn;230;NSM;;;;;N;;;;; 1DE4;COMBINING LATIN SMALL LETTER S;Mn;230;NSM;;;;;N;;;;; 1DE5;COMBINING LATIN SMALL LETTER LONG S;Mn;230;NSM;;;;;N;;;;; 1DE6;COMBINING LATIN SMALL LETTER Z;Mn;230;NSM;;;;;N;;;;; 1DE7;COMBINING LATIN SMALL LETTER ALPHA;Mn;230;NSM;;;;;N;;;;; 1DE8;COMBINING LATIN SMALL LETTER B;Mn;230;NSM;;;;;N;;;;; 1DE9;COMBINING LATIN SMALL LETTER BETA;Mn;230;NSM;;;;;N;;;;; 1DEA;COMBINING LATIN SMALL LETTER SCHWA;Mn;230;NSM;;;;;N;;;;; 1DEB;COMBINING LATIN SMALL LETTER F;Mn;230;NSM;;;;;N;;;;; 1DEC;COMBINING LATIN SMALL LETTER L WITH DOUBLE MIDDLE TILDE;Mn;230;NSM;;;;;N;;;;; 1DED;COMBINING LATIN SMALL LETTER O WITH LIGHT CENTRALIZATION STROKE;Mn;230;NSM;;;;;N;;;;; 1DEE;COMBINING LATIN SMALL LETTER P;Mn;230;NSM;;;;;N;;;;; 1DEF;COMBINING LATIN SMALL LETTER ESH;Mn;230;NSM;;;;;N;;;;; 1DF0;COMBINING LATIN SMALL LETTER U WITH LIGHT CENTRALIZATION STROKE;Mn;230;NSM;;;;;N;;;;; 1DF1;COMBINING LATIN SMALL LETTER W;Mn;230;NSM;;;;;N;;;;; 1DF2;COMBINING LATIN SMALL LETTER A WITH DIAERESIS;Mn;230;NSM;;;;;N;;;;; 1DF3;COMBINING LATIN SMALL LETTER O WITH DIAERESIS;Mn;230;NSM;;;;;N;;;;; 1DF4;COMBINING LATIN SMALL LETTER U WITH DIAERESIS;Mn;230;NSM;;;;;N;;;;; 1DF5;COMBINING UP TACK ABOVE;Mn;230;NSM;;;;;N;;;;; 1DFB;COMBINING DELETION MARK;Mn;230;NSM;;;;;N;;;;; 1DFC;COMBINING DOUBLE INVERTED BREVE BELOW;Mn;233;NSM;;;;;N;;;;; 1DFD;COMBINING ALMOST EQUAL TO BELOW;Mn;220;NSM;;;;;N;;;;; 1DFE;COMBINING LEFT ARROWHEAD ABOVE;Mn;230;NSM;;;;;N;;;;; 1DFF;COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW;Mn;220;NSM;;;;;N;;;;; 1E00;LATIN CAPITAL LETTER A WITH RING BELOW;Lu;0;L;0041 0325;;;;N;;;;1E01; 1E01;LATIN SMALL LETTER A WITH RING BELOW;Ll;0;L;0061 0325;;;;N;;;1E00;;1E00 1E02;LATIN CAPITAL LETTER B WITH DOT ABOVE;Lu;0;L;0042 0307;;;;N;;;;1E03; 1E03;LATIN SMALL LETTER B WITH DOT ABOVE;Ll;0;L;0062 0307;;;;N;;;1E02;;1E02 1E04;LATIN CAPITAL LETTER B WITH DOT BELOW;Lu;0;L;0042 0323;;;;N;;;;1E05; 1E05;LATIN SMALL LETTER B WITH DOT BELOW;Ll;0;L;0062 0323;;;;N;;;1E04;;1E04 1E06;LATIN CAPITAL LETTER B WITH LINE BELOW;Lu;0;L;0042 0331;;;;N;;;;1E07; 1E07;LATIN SMALL LETTER B WITH LINE BELOW;Ll;0;L;0062 0331;;;;N;;;1E06;;1E06 1E08;LATIN CAPITAL LETTER C WITH CEDILLA AND ACUTE;Lu;0;L;00C7 0301;;;;N;;;;1E09; 1E09;LATIN SMALL LETTER C WITH CEDILLA AND ACUTE;Ll;0;L;00E7 0301;;;;N;;;1E08;;1E08 1E0A;LATIN CAPITAL LETTER D WITH DOT ABOVE;Lu;0;L;0044 0307;;;;N;;;;1E0B; 1E0B;LATIN SMALL LETTER D WITH DOT ABOVE;Ll;0;L;0064 0307;;;;N;;;1E0A;;1E0A 1E0C;LATIN CAPITAL LETTER D WITH DOT BELOW;Lu;0;L;0044 0323;;;;N;;;;1E0D; 1E0D;LATIN SMALL LETTER D WITH DOT BELOW;Ll;0;L;0064 0323;;;;N;;;1E0C;;1E0C 1E0E;LATIN CAPITAL LETTER D WITH LINE BELOW;Lu;0;L;0044 0331;;;;N;;;;1E0F; 1E0F;LATIN SMALL LETTER D WITH LINE BELOW;Ll;0;L;0064 0331;;;;N;;;1E0E;;1E0E 1E10;LATIN CAPITAL LETTER D WITH CEDILLA;Lu;0;L;0044 0327;;;;N;;;;1E11; 1E11;LATIN SMALL LETTER D WITH CEDILLA;Ll;0;L;0064 0327;;;;N;;;1E10;;1E10 1E12;LATIN CAPITAL LETTER D WITH CIRCUMFLEX BELOW;Lu;0;L;0044 032D;;;;N;;;;1E13; 1E13;LATIN SMALL LETTER D WITH CIRCUMFLEX BELOW;Ll;0;L;0064 032D;;;;N;;;1E12;;1E12 1E14;LATIN CAPITAL LETTER E WITH MACRON AND GRAVE;Lu;0;L;0112 0300;;;;N;;;;1E15; 1E15;LATIN SMALL LETTER E WITH MACRON AND GRAVE;Ll;0;L;0113 0300;;;;N;;;1E14;;1E14 1E16;LATIN CAPITAL LETTER E WITH MACRON AND ACUTE;Lu;0;L;0112 0301;;;;N;;;;1E17; 1E17;LATIN SMALL LETTER E WITH MACRON AND ACUTE;Ll;0;L;0113 0301;;;;N;;;1E16;;1E16 1E18;LATIN CAPITAL LETTER E WITH CIRCUMFLEX BELOW;Lu;0;L;0045 032D;;;;N;;;;1E19; 1E19;LATIN SMALL LETTER E WITH CIRCUMFLEX BELOW;Ll;0;L;0065 032D;;;;N;;;1E18;;1E18 1E1A;LATIN CAPITAL LETTER E WITH TILDE BELOW;Lu;0;L;0045 0330;;;;N;;;;1E1B; 1E1B;LATIN SMALL LETTER E WITH TILDE BELOW;Ll;0;L;0065 0330;;;;N;;;1E1A;;1E1A 1E1C;LATIN CAPITAL LETTER E WITH CEDILLA AND BREVE;Lu;0;L;0228 0306;;;;N;;;;1E1D; 1E1D;LATIN SMALL LETTER E WITH CEDILLA AND BREVE;Ll;0;L;0229 0306;;;;N;;;1E1C;;1E1C 1E1E;LATIN CAPITAL LETTER F WITH DOT ABOVE;Lu;0;L;0046 0307;;;;N;;;;1E1F; 1E1F;LATIN SMALL LETTER F WITH DOT ABOVE;Ll;0;L;0066 0307;;;;N;;;1E1E;;1E1E 1E20;LATIN CAPITAL LETTER G WITH MACRON;Lu;0;L;0047 0304;;;;N;;;;1E21; 1E21;LATIN SMALL LETTER G WITH MACRON;Ll;0;L;0067 0304;;;;N;;;1E20;;1E20 1E22;LATIN CAPITAL LETTER H WITH DOT ABOVE;Lu;0;L;0048 0307;;;;N;;;;1E23; 1E23;LATIN SMALL LETTER H WITH DOT ABOVE;Ll;0;L;0068 0307;;;;N;;;1E22;;1E22 1E24;LATIN CAPITAL LETTER H WITH DOT BELOW;Lu;0;L;0048 0323;;;;N;;;;1E25; 1E25;LATIN SMALL LETTER H WITH DOT BELOW;Ll;0;L;0068 0323;;;;N;;;1E24;;1E24 1E26;LATIN CAPITAL LETTER H WITH DIAERESIS;Lu;0;L;0048 0308;;;;N;;;;1E27; 1E27;LATIN SMALL LETTER H WITH DIAERESIS;Ll;0;L;0068 0308;;;;N;;;1E26;;1E26 1E28;LATIN CAPITAL LETTER H WITH CEDILLA;Lu;0;L;0048 0327;;;;N;;;;1E29; 1E29;LATIN SMALL LETTER H WITH CEDILLA;Ll;0;L;0068 0327;;;;N;;;1E28;;1E28 1E2A;LATIN CAPITAL LETTER H WITH BREVE BELOW;Lu;0;L;0048 032E;;;;N;;;;1E2B; 1E2B;LATIN SMALL LETTER H WITH BREVE BELOW;Ll;0;L;0068 032E;;;;N;;;1E2A;;1E2A 1E2C;LATIN CAPITAL LETTER I WITH TILDE BELOW;Lu;0;L;0049 0330;;;;N;;;;1E2D; 1E2D;LATIN SMALL LETTER I WITH TILDE BELOW;Ll;0;L;0069 0330;;;;N;;;1E2C;;1E2C 1E2E;LATIN CAPITAL LETTER I WITH DIAERESIS AND ACUTE;Lu;0;L;00CF 0301;;;;N;;;;1E2F; 1E2F;LATIN SMALL LETTER I WITH DIAERESIS AND ACUTE;Ll;0;L;00EF 0301;;;;N;;;1E2E;;1E2E 1E30;LATIN CAPITAL LETTER K WITH ACUTE;Lu;0;L;004B 0301;;;;N;;;;1E31; 1E31;LATIN SMALL LETTER K WITH ACUTE;Ll;0;L;006B 0301;;;;N;;;1E30;;1E30 1E32;LATIN CAPITAL LETTER K WITH DOT BELOW;Lu;0;L;004B 0323;;;;N;;;;1E33; 1E33;LATIN SMALL LETTER K WITH DOT BELOW;Ll;0;L;006B 0323;;;;N;;;1E32;;1E32 1E34;LATIN CAPITAL LETTER K WITH LINE BELOW;Lu;0;L;004B 0331;;;;N;;;;1E35; 1E35;LATIN SMALL LETTER K WITH LINE BELOW;Ll;0;L;006B 0331;;;;N;;;1E34;;1E34 1E36;LATIN CAPITAL LETTER L WITH DOT BELOW;Lu;0;L;004C 0323;;;;N;;;;1E37; 1E37;LATIN SMALL LETTER L WITH DOT BELOW;Ll;0;L;006C 0323;;;;N;;;1E36;;1E36 1E38;LATIN CAPITAL LETTER L WITH DOT BELOW AND MACRON;Lu;0;L;1E36 0304;;;;N;;;;1E39; 1E39;LATIN SMALL LETTER L WITH DOT BELOW AND MACRON;Ll;0;L;1E37 0304;;;;N;;;1E38;;1E38 1E3A;LATIN CAPITAL LETTER L WITH LINE BELOW;Lu;0;L;004C 0331;;;;N;;;;1E3B; 1E3B;LATIN SMALL LETTER L WITH LINE BELOW;Ll;0;L;006C 0331;;;;N;;;1E3A;;1E3A 1E3C;LATIN CAPITAL LETTER L WITH CIRCUMFLEX BELOW;Lu;0;L;004C 032D;;;;N;;;;1E3D; 1E3D;LATIN SMALL LETTER L WITH CIRCUMFLEX BELOW;Ll;0;L;006C 032D;;;;N;;;1E3C;;1E3C 1E3E;LATIN CAPITAL LETTER M WITH ACUTE;Lu;0;L;004D 0301;;;;N;;;;1E3F; 1E3F;LATIN SMALL LETTER M WITH ACUTE;Ll;0;L;006D 0301;;;;N;;;1E3E;;1E3E 1E40;LATIN CAPITAL LETTER M WITH DOT ABOVE;Lu;0;L;004D 0307;;;;N;;;;1E41; 1E41;LATIN SMALL LETTER M WITH DOT ABOVE;Ll;0;L;006D 0307;;;;N;;;1E40;;1E40 1E42;LATIN CAPITAL LETTER M WITH DOT BELOW;Lu;0;L;004D 0323;;;;N;;;;1E43; 1E43;LATIN SMALL LETTER M WITH DOT BELOW;Ll;0;L;006D 0323;;;;N;;;1E42;;1E42 1E44;LATIN CAPITAL LETTER N WITH DOT ABOVE;Lu;0;L;004E 0307;;;;N;;;;1E45; 1E45;LATIN SMALL LETTER N WITH DOT ABOVE;Ll;0;L;006E 0307;;;;N;;;1E44;;1E44 1E46;LATIN CAPITAL LETTER N WITH DOT BELOW;Lu;0;L;004E 0323;;;;N;;;;1E47; 1E47;LATIN SMALL LETTER N WITH DOT BELOW;Ll;0;L;006E 0323;;;;N;;;1E46;;1E46 1E48;LATIN CAPITAL LETTER N WITH LINE BELOW;Lu;0;L;004E 0331;;;;N;;;;1E49; 1E49;LATIN SMALL LETTER N WITH LINE BELOW;Ll;0;L;006E 0331;;;;N;;;1E48;;1E48 1E4A;LATIN CAPITAL LETTER N WITH CIRCUMFLEX BELOW;Lu;0;L;004E 032D;;;;N;;;;1E4B; 1E4B;LATIN SMALL LETTER N WITH CIRCUMFLEX BELOW;Ll;0;L;006E 032D;;;;N;;;1E4A;;1E4A 1E4C;LATIN CAPITAL LETTER O WITH TILDE AND ACUTE;Lu;0;L;00D5 0301;;;;N;;;;1E4D; 1E4D;LATIN SMALL LETTER O WITH TILDE AND ACUTE;Ll;0;L;00F5 0301;;;;N;;;1E4C;;1E4C 1E4E;LATIN CAPITAL LETTER O WITH TILDE AND DIAERESIS;Lu;0;L;00D5 0308;;;;N;;;;1E4F; 1E4F;LATIN SMALL LETTER O WITH TILDE AND DIAERESIS;Ll;0;L;00F5 0308;;;;N;;;1E4E;;1E4E 1E50;LATIN CAPITAL LETTER O WITH MACRON AND GRAVE;Lu;0;L;014C 0300;;;;N;;;;1E51; 1E51;LATIN SMALL LETTER O WITH MACRON AND GRAVE;Ll;0;L;014D 0300;;;;N;;;1E50;;1E50 1E52;LATIN CAPITAL LETTER O WITH MACRON AND ACUTE;Lu;0;L;014C 0301;;;;N;;;;1E53; 1E53;LATIN SMALL LETTER O WITH MACRON AND ACUTE;Ll;0;L;014D 0301;;;;N;;;1E52;;1E52 1E54;LATIN CAPITAL LETTER P WITH ACUTE;Lu;0;L;0050 0301;;;;N;;;;1E55; 1E55;LATIN SMALL LETTER P WITH ACUTE;Ll;0;L;0070 0301;;;;N;;;1E54;;1E54 1E56;LATIN CAPITAL LETTER P WITH DOT ABOVE;Lu;0;L;0050 0307;;;;N;;;;1E57; 1E57;LATIN SMALL LETTER P WITH DOT ABOVE;Ll;0;L;0070 0307;;;;N;;;1E56;;1E56 1E58;LATIN CAPITAL LETTER R WITH DOT ABOVE;Lu;0;L;0052 0307;;;;N;;;;1E59; 1E59;LATIN SMALL LETTER R WITH DOT ABOVE;Ll;0;L;0072 0307;;;;N;;;1E58;;1E58 1E5A;LATIN CAPITAL LETTER R WITH DOT BELOW;Lu;0;L;0052 0323;;;;N;;;;1E5B; 1E5B;LATIN SMALL LETTER R WITH DOT BELOW;Ll;0;L;0072 0323;;;;N;;;1E5A;;1E5A 1E5C;LATIN CAPITAL LETTER R WITH DOT BELOW AND MACRON;Lu;0;L;1E5A 0304;;;;N;;;;1E5D; 1E5D;LATIN SMALL LETTER R WITH DOT BELOW AND MACRON;Ll;0;L;1E5B 0304;;;;N;;;1E5C;;1E5C 1E5E;LATIN CAPITAL LETTER R WITH LINE BELOW;Lu;0;L;0052 0331;;;;N;;;;1E5F; 1E5F;LATIN SMALL LETTER R WITH LINE BELOW;Ll;0;L;0072 0331;;;;N;;;1E5E;;1E5E 1E60;LATIN CAPITAL LETTER S WITH DOT ABOVE;Lu;0;L;0053 0307;;;;N;;;;1E61; 1E61;LATIN SMALL LETTER S WITH DOT ABOVE;Ll;0;L;0073 0307;;;;N;;;1E60;;1E60 1E62;LATIN CAPITAL LETTER S WITH DOT BELOW;Lu;0;L;0053 0323;;;;N;;;;1E63; 1E63;LATIN SMALL LETTER S WITH DOT BELOW;Ll;0;L;0073 0323;;;;N;;;1E62;;1E62 1E64;LATIN CAPITAL LETTER S WITH ACUTE AND DOT ABOVE;Lu;0;L;015A 0307;;;;N;;;;1E65; 1E65;LATIN SMALL LETTER S WITH ACUTE AND DOT ABOVE;Ll;0;L;015B 0307;;;;N;;;1E64;;1E64 1E66;LATIN CAPITAL LETTER S WITH CARON AND DOT ABOVE;Lu;0;L;0160 0307;;;;N;;;;1E67; 1E67;LATIN SMALL LETTER S WITH CARON AND DOT ABOVE;Ll;0;L;0161 0307;;;;N;;;1E66;;1E66 1E68;LATIN CAPITAL LETTER S WITH DOT BELOW AND DOT ABOVE;Lu;0;L;1E62 0307;;;;N;;;;1E69; 1E69;LATIN SMALL LETTER S WITH DOT BELOW AND DOT ABOVE;Ll;0;L;1E63 0307;;;;N;;;1E68;;1E68 1E6A;LATIN CAPITAL LETTER T WITH DOT ABOVE;Lu;0;L;0054 0307;;;;N;;;;1E6B; 1E6B;LATIN SMALL LETTER T WITH DOT ABOVE;Ll;0;L;0074 0307;;;;N;;;1E6A;;1E6A 1E6C;LATIN CAPITAL LETTER T WITH DOT BELOW;Lu;0;L;0054 0323;;;;N;;;;1E6D; 1E6D;LATIN SMALL LETTER T WITH DOT BELOW;Ll;0;L;0074 0323;;;;N;;;1E6C;;1E6C 1E6E;LATIN CAPITAL LETTER T WITH LINE BELOW;Lu;0;L;0054 0331;;;;N;;;;1E6F; 1E6F;LATIN SMALL LETTER T WITH LINE BELOW;Ll;0;L;0074 0331;;;;N;;;1E6E;;1E6E 1E70;LATIN CAPITAL LETTER T WITH CIRCUMFLEX BELOW;Lu;0;L;0054 032D;;;;N;;;;1E71; 1E71;LATIN SMALL LETTER T WITH CIRCUMFLEX BELOW;Ll;0;L;0074 032D;;;;N;;;1E70;;1E70 1E72;LATIN CAPITAL LETTER U WITH DIAERESIS BELOW;Lu;0;L;0055 0324;;;;N;;;;1E73; 1E73;LATIN SMALL LETTER U WITH DIAERESIS BELOW;Ll;0;L;0075 0324;;;;N;;;1E72;;1E72 1E74;LATIN CAPITAL LETTER U WITH TILDE BELOW;Lu;0;L;0055 0330;;;;N;;;;1E75; 1E75;LATIN SMALL LETTER U WITH TILDE BELOW;Ll;0;L;0075 0330;;;;N;;;1E74;;1E74 1E76;LATIN CAPITAL LETTER U WITH CIRCUMFLEX BELOW;Lu;0;L;0055 032D;;;;N;;;;1E77; 1E77;LATIN SMALL LETTER U WITH CIRCUMFLEX BELOW;Ll;0;L;0075 032D;;;;N;;;1E76;;1E76 1E78;LATIN CAPITAL LETTER U WITH TILDE AND ACUTE;Lu;0;L;0168 0301;;;;N;;;;1E79; 1E79;LATIN SMALL LETTER U WITH TILDE AND ACUTE;Ll;0;L;0169 0301;;;;N;;;1E78;;1E78 1E7A;LATIN CAPITAL LETTER U WITH MACRON AND DIAERESIS;Lu;0;L;016A 0308;;;;N;;;;1E7B; 1E7B;LATIN SMALL LETTER U WITH MACRON AND DIAERESIS;Ll;0;L;016B 0308;;;;N;;;1E7A;;1E7A 1E7C;LATIN CAPITAL LETTER V WITH TILDE;Lu;0;L;0056 0303;;;;N;;;;1E7D; 1E7D;LATIN SMALL LETTER V WITH TILDE;Ll;0;L;0076 0303;;;;N;;;1E7C;;1E7C 1E7E;LATIN CAPITAL LETTER V WITH DOT BELOW;Lu;0;L;0056 0323;;;;N;;;;1E7F; 1E7F;LATIN SMALL LETTER V WITH DOT BELOW;Ll;0;L;0076 0323;;;;N;;;1E7E;;1E7E 1E80;LATIN CAPITAL LETTER W WITH GRAVE;Lu;0;L;0057 0300;;;;N;;;;1E81; 1E81;LATIN SMALL LETTER W WITH GRAVE;Ll;0;L;0077 0300;;;;N;;;1E80;;1E80 1E82;LATIN CAPITAL LETTER W WITH ACUTE;Lu;0;L;0057 0301;;;;N;;;;1E83; 1E83;LATIN SMALL LETTER W WITH ACUTE;Ll;0;L;0077 0301;;;;N;;;1E82;;1E82 1E84;LATIN CAPITAL LETTER W WITH DIAERESIS;Lu;0;L;0057 0308;;;;N;;;;1E85; 1E85;LATIN SMALL LETTER W WITH DIAERESIS;Ll;0;L;0077 0308;;;;N;;;1E84;;1E84 1E86;LATIN CAPITAL LETTER W WITH DOT ABOVE;Lu;0;L;0057 0307;;;;N;;;;1E87; 1E87;LATIN SMALL LETTER W WITH DOT ABOVE;Ll;0;L;0077 0307;;;;N;;;1E86;;1E86 1E88;LATIN CAPITAL LETTER W WITH DOT BELOW;Lu;0;L;0057 0323;;;;N;;;;1E89; 1E89;LATIN SMALL LETTER W WITH DOT BELOW;Ll;0;L;0077 0323;;;;N;;;1E88;;1E88 1E8A;LATIN CAPITAL LETTER X WITH DOT ABOVE;Lu;0;L;0058 0307;;;;N;;;;1E8B; 1E8B;LATIN SMALL LETTER X WITH DOT ABOVE;Ll;0;L;0078 0307;;;;N;;;1E8A;;1E8A 1E8C;LATIN CAPITAL LETTER X WITH DIAERESIS;Lu;0;L;0058 0308;;;;N;;;;1E8D; 1E8D;LATIN SMALL LETTER X WITH DIAERESIS;Ll;0;L;0078 0308;;;;N;;;1E8C;;1E8C 1E8E;LATIN CAPITAL LETTER Y WITH DOT ABOVE;Lu;0;L;0059 0307;;;;N;;;;1E8F; 1E8F;LATIN SMALL LETTER Y WITH DOT ABOVE;Ll;0;L;0079 0307;;;;N;;;1E8E;;1E8E 1E90;LATIN CAPITAL LETTER Z WITH CIRCUMFLEX;Lu;0;L;005A 0302;;;;N;;;;1E91; 1E91;LATIN SMALL LETTER Z WITH CIRCUMFLEX;Ll;0;L;007A 0302;;;;N;;;1E90;;1E90 1E92;LATIN CAPITAL LETTER Z WITH DOT BELOW;Lu;0;L;005A 0323;;;;N;;;;1E93; 1E93;LATIN SMALL LETTER Z WITH DOT BELOW;Ll;0;L;007A 0323;;;;N;;;1E92;;1E92 1E94;LATIN CAPITAL LETTER Z WITH LINE BELOW;Lu;0;L;005A 0331;;;;N;;;;1E95; 1E95;LATIN SMALL LETTER Z WITH LINE BELOW;Ll;0;L;007A 0331;;;;N;;;1E94;;1E94 1E96;LATIN SMALL LETTER H WITH LINE BELOW;Ll;0;L;0068 0331;;;;N;;;;; 1E97;LATIN SMALL LETTER T WITH DIAERESIS;Ll;0;L;0074 0308;;;;N;;;;; 1E98;LATIN SMALL LETTER W WITH RING ABOVE;Ll;0;L;0077 030A;;;;N;;;;; 1E99;LATIN SMALL LETTER Y WITH RING ABOVE;Ll;0;L;0079 030A;;;;N;;;;; 1E9A;LATIN SMALL LETTER A WITH RIGHT HALF RING;Ll;0;L;<compat> 0061 02BE;;;;N;;;;; 1E9B;LATIN SMALL LETTER LONG S WITH DOT ABOVE;Ll;0;L;017F 0307;;;;N;;;1E60;;1E60 1E9C;LATIN SMALL LETTER LONG S WITH DIAGONAL STROKE;Ll;0;L;;;;;N;;;;; 1E9D;LATIN SMALL LETTER LONG S WITH HIGH STROKE;Ll;0;L;;;;;N;;;;; 1E9E;LATIN CAPITAL LETTER SHARP S;Lu;0;L;;;;;N;;;;00DF; 1E9F;LATIN SMALL LETTER DELTA;Ll;0;L;;;;;N;;;;; 1EA0;LATIN CAPITAL LETTER A WITH DOT BELOW;Lu;0;L;0041 0323;;;;N;;;;1EA1; 1EA1;LATIN SMALL LETTER A WITH DOT BELOW;Ll;0;L;0061 0323;;;;N;;;1EA0;;1EA0 1EA2;LATIN CAPITAL LETTER A WITH HOOK ABOVE;Lu;0;L;0041 0309;;;;N;;;;1EA3; 1EA3;LATIN SMALL LETTER A WITH HOOK ABOVE;Ll;0;L;0061 0309;;;;N;;;1EA2;;1EA2 1EA4;LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE;Lu;0;L;00C2 0301;;;;N;;;;1EA5; 1EA5;LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE;Ll;0;L;00E2 0301;;;;N;;;1EA4;;1EA4 1EA6;LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE;Lu;0;L;00C2 0300;;;;N;;;;1EA7; 1EA7;LATIN SMALL LETTER A WITH CIRCUMFLEX AND GRAVE;Ll;0;L;00E2 0300;;;;N;;;1EA6;;1EA6 1EA8;LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE;Lu;0;L;00C2 0309;;;;N;;;;1EA9; 1EA9;LATIN SMALL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE;Ll;0;L;00E2 0309;;;;N;;;1EA8;;1EA8 1EAA;LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE;Lu;0;L;00C2 0303;;;;N;;;;1EAB; 1EAB;LATIN SMALL LETTER A WITH CIRCUMFLEX AND TILDE;Ll;0;L;00E2 0303;;;;N;;;1EAA;;1EAA 1EAC;LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW;Lu;0;L;1EA0 0302;;;;N;;;;1EAD; 1EAD;LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT BELOW;Ll;0;L;1EA1 0302;;;;N;;;1EAC;;1EAC 1EAE;LATIN CAPITAL LETTER A WITH BREVE AND ACUTE;Lu;0;L;0102 0301;;;;N;;;;1EAF; 1EAF;LATIN SMALL LETTER A WITH BREVE AND ACUTE;Ll;0;L;0103 0301;;;;N;;;1EAE;;1EAE 1EB0;LATIN CAPITAL LETTER A WITH BREVE AND GRAVE;Lu;0;L;0102 0300;;;;N;;;;1EB1; 1EB1;LATIN SMALL LETTER A WITH BREVE AND GRAVE;Ll;0;L;0103 0300;;;;N;;;1EB0;;1EB0 1EB2;LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE;Lu;0;L;0102 0309;;;;N;;;;1EB3; 1EB3;LATIN SMALL LETTER A WITH BREVE AND HOOK ABOVE;Ll;0;L;0103 0309;;;;N;;;1EB2;;1EB2 1EB4;LATIN CAPITAL LETTER A WITH BREVE AND TILDE;Lu;0;L;0102 0303;;;;N;;;;1EB5; 1EB5;LATIN SMALL LETTER A WITH BREVE AND TILDE;Ll;0;L;0103 0303;;;;N;;;1EB4;;1EB4 1EB6;LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW;Lu;0;L;1EA0 0306;;;;N;;;;1EB7; 1EB7;LATIN SMALL LETTER A WITH BREVE AND DOT BELOW;Ll;0;L;1EA1 0306;;;;N;;;1EB6;;1EB6 1EB8;LATIN CAPITAL LETTER E WITH DOT BELOW;Lu;0;L;0045 0323;;;;N;;;;1EB9; 1EB9;LATIN SMALL LETTER E WITH DOT BELOW;Ll;0;L;0065 0323;;;;N;;;1EB8;;1EB8 1EBA;LATIN CAPITAL LETTER E WITH HOOK ABOVE;Lu;0;L;0045 0309;;;;N;;;;1EBB; 1EBB;LATIN SMALL LETTER E WITH HOOK ABOVE;Ll;0;L;0065 0309;;;;N;;;1EBA;;1EBA 1EBC;LATIN CAPITAL LETTER E WITH TILDE;Lu;0;L;0045 0303;;;;N;;;;1EBD; 1EBD;LATIN SMALL LETTER E WITH TILDE;Ll;0;L;0065 0303;;;;N;;;1EBC;;1EBC 1EBE;LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE;Lu;0;L;00CA 0301;;;;N;;;;1EBF; 1EBF;LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE;Ll;0;L;00EA 0301;;;;N;;;1EBE;;1EBE 1EC0;LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE;Lu;0;L;00CA 0300;;;;N;;;;1EC1; 1EC1;LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRAVE;Ll;0;L;00EA 0300;;;;N;;;1EC0;;1EC0 1EC2;LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE;Lu;0;L;00CA 0309;;;;N;;;;1EC3; 1EC3;LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE;Ll;0;L;00EA 0309;;;;N;;;1EC2;;1EC2 1EC4;LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE;Lu;0;L;00CA 0303;;;;N;;;;1EC5; 1EC5;LATIN SMALL LETTER E WITH CIRCUMFLEX AND TILDE;Ll;0;L;00EA 0303;;;;N;;;1EC4;;1EC4 1EC6;LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW;Lu;0;L;1EB8 0302;;;;N;;;;1EC7; 1EC7;LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW;Ll;0;L;1EB9 0302;;;;N;;;1EC6;;1EC6 1EC8;LATIN CAPITAL LETTER I WITH HOOK ABOVE;Lu;0;L;0049 0309;;;;N;;;;1EC9; 1EC9;LATIN SMALL LETTER I WITH HOOK ABOVE;Ll;0;L;0069 0309;;;;N;;;1EC8;;1EC8 1ECA;LATIN CAPITAL LETTER I WITH DOT BELOW;Lu;0;L;0049 0323;;;;N;;;;1ECB; 1ECB;LATIN SMALL LETTER I WITH DOT BELOW;Ll;0;L;0069 0323;;;;N;;;1ECA;;1ECA 1ECC;LATIN CAPITAL LETTER O WITH DOT BELOW;Lu;0;L;004F 0323;;;;N;;;;1ECD; 1ECD;LATIN SMALL LETTER O WITH DOT BELOW;Ll;0;L;006F 0323;;;;N;;;1ECC;;1ECC 1ECE;LATIN CAPITAL LETTER O WITH HOOK ABOVE;Lu;0;L;004F 0309;;;;N;;;;1ECF; 1ECF;LATIN SMALL LETTER O WITH HOOK ABOVE;Ll;0;L;006F 0309;;;;N;;;1ECE;;1ECE 1ED0;LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE;Lu;0;L;00D4 0301;;;;N;;;;1ED1; 1ED1;LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE;Ll;0;L;00F4 0301;;;;N;;;1ED0;;1ED0 1ED2;LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE;Lu;0;L;00D4 0300;;;;N;;;;1ED3; 1ED3;LATIN SMALL LETTER O WITH CIRCUMFLEX AND GRAVE;Ll;0;L;00F4 0300;;;;N;;;1ED2;;1ED2 1ED4;LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE;Lu;0;L;00D4 0309;;;;N;;;;1ED5; 1ED5;LATIN SMALL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE;Ll;0;L;00F4 0309;;;;N;;;1ED4;;1ED4 1ED6;LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE;Lu;0;L;00D4 0303;;;;N;;;;1ED7; 1ED7;LATIN SMALL LETTER O WITH CIRCUMFLEX AND TILDE;Ll;0;L;00F4 0303;;;;N;;;1ED6;;1ED6 1ED8;LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW;Lu;0;L;1ECC 0302;;;;N;;;;1ED9; 1ED9;LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW;Ll;0;L;1ECD 0302;;;;N;;;1ED8;;1ED8 1EDA;LATIN CAPITAL LETTER O WITH HORN AND ACUTE;Lu;0;L;01A0 0301;;;;N;;;;1EDB; 1EDB;LATIN SMALL LETTER O WITH HORN AND ACUTE;Ll;0;L;01A1 0301;;;;N;;;1EDA;;1EDA 1EDC;LATIN CAPITAL LETTER O WITH HORN AND GRAVE;Lu;0;L;01A0 0300;;;;N;;;;1EDD; 1EDD;LATIN SMALL LETTER O WITH HORN AND GRAVE;Ll;0;L;01A1 0300;;;;N;;;1EDC;;1EDC 1EDE;LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE;Lu;0;L;01A0 0309;;;;N;;;;1EDF; 1EDF;LATIN SMALL LETTER O WITH HORN AND HOOK ABOVE;Ll;0;L;01A1 0309;;;;N;;;1EDE;;1EDE 1EE0;LATIN CAPITAL LETTER O WITH HORN AND TILDE;Lu;0;L;01A0 0303;;;;N;;;;1EE1; 1EE1;LATIN SMALL LETTER O WITH HORN AND TILDE;Ll;0;L;01A1 0303;;;;N;;;1EE0;;1EE0 1EE2;LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW;Lu;0;L;01A0 0323;;;;N;;;;1EE3; 1EE3;LATIN SMALL LETTER O WITH HORN AND DOT BELOW;Ll;0;L;01A1 0323;;;;N;;;1EE2;;1EE2 1EE4;LATIN CAPITAL LETTER U WITH DOT BELOW;Lu;0;L;0055 0323;;;;N;;;;1EE5; 1EE5;LATIN SMALL LETTER U WITH DOT BELOW;Ll;0;L;0075 0323;;;;N;;;1EE4;;1EE4 1EE6;LATIN CAPITAL LETTER U WITH HOOK ABOVE;Lu;0;L;0055 0309;;;;N;;;;1EE7; 1EE7;LATIN SMALL LETTER U WITH HOOK ABOVE;Ll;0;L;0075 0309;;;;N;;;1EE6;;1EE6 1EE8;LATIN CAPITAL LETTER U WITH HORN AND ACUTE;Lu;0;L;01AF 0301;;;;N;;;;1EE9; 1EE9;LATIN SMALL LETTER U WITH HORN AND ACUTE;Ll;0;L;01B0 0301;;;;N;;;1EE8;;1EE8 1EEA;LATIN CAPITAL LETTER U WITH HORN AND GRAVE;Lu;0;L;01AF 0300;;;;N;;;;1EEB; 1EEB;LATIN SMALL LETTER U WITH HORN AND GRAVE;Ll;0;L;01B0 0300;;;;N;;;1EEA;;1EEA 1EEC;LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE;Lu;0;L;01AF 0309;;;;N;;;;1EED; 1EED;LATIN SMALL LETTER U WITH HORN AND HOOK ABOVE;Ll;0;L;01B0 0309;;;;N;;;1EEC;;1EEC 1EEE;LATIN CAPITAL LETTER U WITH HORN AND TILDE;Lu;0;L;01AF 0303;;;;N;;;;1EEF; 1EEF;LATIN SMALL LETTER U WITH HORN AND TILDE;Ll;0;L;01B0 0303;;;;N;;;1EEE;;1EEE 1EF0;LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW;Lu;0;L;01AF 0323;;;;N;;;;1EF1; 1EF1;LATIN SMALL LETTER U WITH HORN AND DOT BELOW;Ll;0;L;01B0 0323;;;;N;;;1EF0;;1EF0 1EF2;LATIN CAPITAL LETTER Y WITH GRAVE;Lu;0;L;0059 0300;;;;N;;;;1EF3; 1EF3;LATIN SMALL LETTER Y WITH GRAVE;Ll;0;L;0079 0300;;;;N;;;1EF2;;1EF2 1EF4;LATIN CAPITAL LETTER Y WITH DOT BELOW;Lu;0;L;0059 0323;;;;N;;;;1EF5; 1EF5;LATIN SMALL LETTER Y WITH DOT BELOW;Ll;0;L;0079 0323;;;;N;;;1EF4;;1EF4 1EF6;LATIN CAPITAL LETTER Y WITH HOOK ABOVE;Lu;0;L;0059 0309;;;;N;;;;1EF7; 1EF7;LATIN SMALL LETTER Y WITH HOOK ABOVE;Ll;0;L;0079 0309;;;;N;;;1EF6;;1EF6 1EF8;LATIN CAPITAL LETTER Y WITH TILDE;Lu;0;L;0059 0303;;;;N;;;;1EF9; 1EF9;LATIN SMALL LETTER Y WITH TILDE;Ll;0;L;0079 0303;;;;N;;;1EF8;;1EF8 1EFA;LATIN CAPITAL LETTER MIDDLE-WELSH LL;Lu;0;L;;;;;N;;;;1EFB; 1EFB;LATIN SMALL LETTER MIDDLE-WELSH LL;Ll;0;L;;;;;N;;;1EFA;;1EFA 1EFC;LATIN CAPITAL LETTER MIDDLE-WELSH V;Lu;0;L;;;;;N;;;;1EFD; 1EFD;LATIN SMALL LETTER MIDDLE-WELSH V;Ll;0;L;;;;;N;;;1EFC;;1EFC 1EFE;LATIN CAPITAL LETTER Y WITH LOOP;Lu;0;L;;;;;N;;;;1EFF; 1EFF;LATIN SMALL LETTER Y WITH LOOP;Ll;0;L;;;;;N;;;1EFE;;1EFE 1F00;GREEK SMALL LETTER ALPHA WITH PSILI;Ll;0;L;03B1 0313;;;;N;;;1F08;;1F08 1F01;GREEK SMALL LETTER ALPHA WITH DASIA;Ll;0;L;03B1 0314;;;;N;;;1F09;;1F09 1F02;GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA;Ll;0;L;1F00 0300;;;;N;;;1F0A;;1F0A 1F03;GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA;Ll;0;L;1F01 0300;;;;N;;;1F0B;;1F0B 1F04;GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA;Ll;0;L;1F00 0301;;;;N;;;1F0C;;1F0C 1F05;GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA;Ll;0;L;1F01 0301;;;;N;;;1F0D;;1F0D 1F06;GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI;Ll;0;L;1F00 0342;;;;N;;;1F0E;;1F0E 1F07;GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI;Ll;0;L;1F01 0342;;;;N;;;1F0F;;1F0F 1F08;GREEK CAPITAL LETTER ALPHA WITH PSILI;Lu;0;L;0391 0313;;;;N;;;;1F00; 1F09;GREEK CAPITAL LETTER ALPHA WITH DASIA;Lu;0;L;0391 0314;;;;N;;;;1F01; 1F0A;GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA;Lu;0;L;1F08 0300;;;;N;;;;1F02; 1F0B;GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA;Lu;0;L;1F09 0300;;;;N;;;;1F03; 1F0C;GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA;Lu;0;L;1F08 0301;;;;N;;;;1F04; 1F0D;GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA;Lu;0;L;1F09 0301;;;;N;;;;1F05; 1F0E;GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI;Lu;0;L;1F08 0342;;;;N;;;;1F06; 1F0F;GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI;Lu;0;L;1F09 0342;;;;N;;;;1F07; 1F10;GREEK SMALL LETTER EPSILON WITH PSILI;Ll;0;L;03B5 0313;;;;N;;;1F18;;1F18 1F11;GREEK SMALL LETTER EPSILON WITH DASIA;Ll;0;L;03B5 0314;;;;N;;;1F19;;1F19 1F12;GREEK SMALL LETTER EPSILON WITH PSILI AND VARIA;Ll;0;L;1F10 0300;;;;N;;;1F1A;;1F1A 1F13;GREEK SMALL LETTER EPSILON WITH DASIA AND VARIA;Ll;0;L;1F11 0300;;;;N;;;1F1B;;1F1B 1F14;GREEK SMALL LETTER EPSILON WITH PSILI AND OXIA;Ll;0;L;1F10 0301;;;;N;;;1F1C;;1F1C 1F15;GREEK SMALL LETTER EPSILON WITH DASIA AND OXIA;Ll;0;L;1F11 0301;;;;N;;;1F1D;;1F1D 1F18;GREEK CAPITAL LETTER EPSILON WITH PSILI;Lu;0;L;0395 0313;;;;N;;;;1F10; 1F19;GREEK CAPITAL LETTER EPSILON WITH DASIA;Lu;0;L;0395 0314;;;;N;;;;1F11; 1F1A;GREEK CAPITAL LETTER EPSILON WITH PSILI AND VARIA;Lu;0;L;1F18 0300;;;;N;;;;1F12; 1F1B;GREEK CAPITAL LETTER EPSILON WITH DASIA AND VARIA;Lu;0;L;1F19 0300;;;;N;;;;1F13; 1F1C;GREEK CAPITAL LETTER EPSILON WITH PSILI AND OXIA;Lu;0;L;1F18 0301;;;;N;;;;1F14; 1F1D;GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA;Lu;0;L;1F19 0301;;;;N;;;;1F15; 1F20;GREEK SMALL LETTER ETA WITH PSILI;Ll;0;L;03B7 0313;;;;N;;;1F28;;1F28 1F21;GREEK SMALL LETTER ETA WITH DASIA;Ll;0;L;03B7 0314;;;;N;;;1F29;;1F29 1F22;GREEK SMALL LETTER ETA WITH PSILI AND VARIA;Ll;0;L;1F20 0300;;;;N;;;1F2A;;1F2A 1F23;GREEK SMALL LETTER ETA WITH DASIA AND VARIA;Ll;0;L;1F21 0300;;;;N;;;1F2B;;1F2B 1F24;GREEK SMALL LETTER ETA WITH PSILI AND OXIA;Ll;0;L;1F20 0301;;;;N;;;1F2C;;1F2C 1F25;GREEK SMALL LETTER ETA WITH DASIA AND OXIA;Ll;0;L;1F21 0301;;;;N;;;1F2D;;1F2D 1F26;GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI;Ll;0;L;1F20 0342;;;;N;;;1F2E;;1F2E 1F27;GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI;Ll;0;L;1F21 0342;;;;N;;;1F2F;;1F2F 1F28;GREEK CAPITAL LETTER ETA WITH PSILI;Lu;0;L;0397 0313;;;;N;;;;1F20; 1F29;GREEK CAPITAL LETTER ETA WITH DASIA;Lu;0;L;0397 0314;;;;N;;;;1F21; 1F2A;GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA;Lu;0;L;1F28 0300;;;;N;;;;1F22; 1F2B;GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA;Lu;0;L;1F29 0300;;;;N;;;;1F23; 1F2C;GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA;Lu;0;L;1F28 0301;;;;N;;;;1F24; 1F2D;GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA;Lu;0;L;1F29 0301;;;;N;;;;1F25; 1F2E;GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI;Lu;0;L;1F28 0342;;;;N;;;;1F26; 1F2F;GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI;Lu;0;L;1F29 0342;;;;N;;;;1F27; 1F30;GREEK SMALL LETTER IOTA WITH PSILI;Ll;0;L;03B9 0313;;;;N;;;1F38;;1F38 1F31;GREEK SMALL LETTER IOTA WITH DASIA;Ll;0;L;03B9 0314;;;;N;;;1F39;;1F39 1F32;GREEK SMALL LETTER IOTA WITH PSILI AND VARIA;Ll;0;L;1F30 0300;;;;N;;;1F3A;;1F3A 1F33;GREEK SMALL LETTER IOTA WITH DASIA AND VARIA;Ll;0;L;1F31 0300;;;;N;;;1F3B;;1F3B 1F34;GREEK SMALL LETTER IOTA WITH PSILI AND OXIA;Ll;0;L;1F30 0301;;;;N;;;1F3C;;1F3C 1F35;GREEK SMALL LETTER IOTA WITH DASIA AND OXIA;Ll;0;L;1F31 0301;;;;N;;;1F3D;;1F3D 1F36;GREEK SMALL LETTER IOTA WITH PSILI AND PERISPOMENI;Ll;0;L;1F30 0342;;;;N;;;1F3E;;1F3E 1F37;GREEK SMALL LETTER IOTA WITH DASIA AND PERISPOMENI;Ll;0;L;1F31 0342;;;;N;;;1F3F;;1F3F 1F38;GREEK CAPITAL LETTER IOTA WITH PSILI;Lu;0;L;0399 0313;;;;N;;;;1F30; 1F39;GREEK CAPITAL LETTER IOTA WITH DASIA;Lu;0;L;0399 0314;;;;N;;;;1F31; 1F3A;GREEK CAPITAL LETTER IOTA WITH PSILI AND VARIA;Lu;0;L;1F38 0300;;;;N;;;;1F32; 1F3B;GREEK CAPITAL LETTER IOTA WITH DASIA AND VARIA;Lu;0;L;1F39 0300;;;;N;;;;1F33; 1F3C;GREEK CAPITAL LETTER IOTA WITH PSILI AND OXIA;Lu;0;L;1F38 0301;;;;N;;;;1F34; 1F3D;GREEK CAPITAL LETTER IOTA WITH DASIA AND OXIA;Lu;0;L;1F39 0301;;;;N;;;;1F35; 1F3E;GREEK CAPITAL LETTER IOTA WITH PSILI AND PERISPOMENI;Lu;0;L;1F38 0342;;;;N;;;;1F36; 1F3F;GREEK CAPITAL LETTER IOTA WITH DASIA AND PERISPOMENI;Lu;0;L;1F39 0342;;;;N;;;;1F37; 1F40;GREEK SMALL LETTER OMICRON WITH PSILI;Ll;0;L;03BF 0313;;;;N;;;1F48;;1F48 1F41;GREEK SMALL LETTER OMICRON WITH DASIA;Ll;0;L;03BF 0314;;;;N;;;1F49;;1F49 1F42;GREEK SMALL LETTER OMICRON WITH PSILI AND VARIA;Ll;0;L;1F40 0300;;;;N;;;1F4A;;1F4A 1F43;GREEK SMALL LETTER OMICRON WITH DASIA AND VARIA;Ll;0;L;1F41 0300;;;;N;;;1F4B;;1F4B 1F44;GREEK SMALL LETTER OMICRON WITH PSILI AND OXIA;Ll;0;L;1F40 0301;;;;N;;;1F4C;;1F4C 1F45;GREEK SMALL LETTER OMICRON WITH DASIA AND OXIA;Ll;0;L;1F41 0301;;;;N;;;1F4D;;1F4D 1F48;GREEK CAPITAL LETTER OMICRON WITH PSILI;Lu;0;L;039F 0313;;;;N;;;;1F40; 1F49;GREEK CAPITAL LETTER OMICRON WITH DASIA;Lu;0;L;039F 0314;;;;N;;;;1F41; 1F4A;GREEK CAPITAL LETTER OMICRON WITH PSILI AND VARIA;Lu;0;L;1F48 0300;;;;N;;;;1F42; 1F4B;GREEK CAPITAL LETTER OMICRON WITH DASIA AND VARIA;Lu;0;L;1F49 0300;;;;N;;;;1F43; 1F4C;GREEK CAPITAL LETTER OMICRON WITH PSILI AND OXIA;Lu;0;L;1F48 0301;;;;N;;;;1F44; 1F4D;GREEK CAPITAL LETTER OMICRON WITH DASIA AND OXIA;Lu;0;L;1F49 0301;;;;N;;;;1F45; 1F50;GREEK SMALL LETTER UPSILON WITH PSILI;Ll;0;L;03C5 0313;;;;N;;;;; 1F51;GREEK SMALL LETTER UPSILON WITH DASIA;Ll;0;L;03C5 0314;;;;N;;;1F59;;1F59 1F52;GREEK SMALL LETTER UPSILON WITH PSILI AND VARIA;Ll;0;L;1F50 0300;;;;N;;;;; 1F53;GREEK SMALL LETTER UPSILON WITH DASIA AND VARIA;Ll;0;L;1F51 0300;;;;N;;;1F5B;;1F5B 1F54;GREEK SMALL LETTER UPSILON WITH PSILI AND OXIA;Ll;0;L;1F50 0301;;;;N;;;;; 1F55;GREEK SMALL LETTER UPSILON WITH DASIA AND OXIA;Ll;0;L;1F51 0301;;;;N;;;1F5D;;1F5D 1F56;GREEK SMALL LETTER UPSILON WITH PSILI AND PERISPOMENI;Ll;0;L;1F50 0342;;;;N;;;;; 1F57;GREEK SMALL LETTER UPSILON WITH DASIA AND PERISPOMENI;Ll;0;L;1F51 0342;;;;N;;;1F5F;;1F5F 1F59;GREEK CAPITAL LETTER UPSILON WITH DASIA;Lu;0;L;03A5 0314;;;;N;;;;1F51; 1F5B;GREEK CAPITAL LETTER UPSILON WITH DASIA AND VARIA;Lu;0;L;1F59 0300;;;;N;;;;1F53; 1F5D;GREEK CAPITAL LETTER UPSILON WITH DASIA AND OXIA;Lu;0;L;1F59 0301;;;;N;;;;1F55; 1F5F;GREEK CAPITAL LETTER UPSILON WITH DASIA AND PERISPOMENI;Lu;0;L;1F59 0342;;;;N;;;;1F57; 1F60;GREEK SMALL LETTER OMEGA WITH PSILI;Ll;0;L;03C9 0313;;;;N;;;1F68;;1F68 1F61;GREEK SMALL LETTER OMEGA WITH DASIA;Ll;0;L;03C9 0314;;;;N;;;1F69;;1F69 1F62;GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA;Ll;0;L;1F60 0300;;;;N;;;1F6A;;1F6A 1F63;GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA;Ll;0;L;1F61 0300;;;;N;;;1F6B;;1F6B 1F64;GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA;Ll;0;L;1F60 0301;;;;N;;;1F6C;;1F6C 1F65;GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA;Ll;0;L;1F61 0301;;;;N;;;1F6D;;1F6D 1F66;GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI;Ll;0;L;1F60 0342;;;;N;;;1F6E;;1F6E 1F67;GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI;Ll;0;L;1F61 0342;;;;N;;;1F6F;;1F6F 1F68;GREEK CAPITAL LETTER OMEGA WITH PSILI;Lu;0;L;03A9 0313;;;;N;;;;1F60; 1F69;GREEK CAPITAL LETTER OMEGA WITH DASIA;Lu;0;L;03A9 0314;;;;N;;;;1F61; 1F6A;GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA;Lu;0;L;1F68 0300;;;;N;;;;1F62; 1F6B;GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA;Lu;0;L;1F69 0300;;;;N;;;;1F63; 1F6C;GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA;Lu;0;L;1F68 0301;;;;N;;;;1F64; 1F6D;GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA;Lu;0;L;1F69 0301;;;;N;;;;1F65; 1F6E;GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI;Lu;0;L;1F68 0342;;;;N;;;;1F66; 1F6F;GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI;Lu;0;L;1F69 0342;;;;N;;;;1F67; 1F70;GREEK SMALL LETTER ALPHA WITH VARIA;Ll;0;L;03B1 0300;;;;N;;;1FBA;;1FBA 1F71;GREEK SMALL LETTER ALPHA WITH OXIA;Ll;0;L;03AC;;;;N;;;1FBB;;1FBB 1F72;GREEK SMALL LETTER EPSILON WITH VARIA;Ll;0;L;03B5 0300;;;;N;;;1FC8;;1FC8 1F73;GREEK SMALL LETTER EPSILON WITH OXIA;Ll;0;L;03AD;;;;N;;;1FC9;;1FC9 1F74;GREEK SMALL LETTER ETA WITH VARIA;Ll;0;L;03B7 0300;;;;N;;;1FCA;;1FCA 1F75;GREEK SMALL LETTER ETA WITH OXIA;Ll;0;L;03AE;;;;N;;;1FCB;;1FCB 1F76;GREEK SMALL LETTER IOTA WITH VARIA;Ll;0;L;03B9 0300;;;;N;;;1FDA;;1FDA 1F77;GREEK SMALL LETTER IOTA WITH OXIA;Ll;0;L;03AF;;;;N;;;1FDB;;1FDB 1F78;GREEK SMALL LETTER OMICRON WITH VARIA;Ll;0;L;03BF 0300;;;;N;;;1FF8;;1FF8 1F79;GREEK SMALL LETTER OMICRON WITH OXIA;Ll;0;L;03CC;;;;N;;;1FF9;;1FF9 1F7A;GREEK SMALL LETTER UPSILON WITH VARIA;Ll;0;L;03C5 0300;;;;N;;;1FEA;;1FEA 1F7B;GREEK SMALL LETTER UPSILON WITH OXIA;Ll;0;L;03CD;;;;N;;;1FEB;;1FEB 1F7C;GREEK SMALL LETTER OMEGA WITH VARIA;Ll;0;L;03C9 0300;;;;N;;;1FFA;;1FFA 1F7D;GREEK SMALL LETTER OMEGA WITH OXIA;Ll;0;L;03CE;;;;N;;;1FFB;;1FFB 1F80;GREEK SMALL LETTER ALPHA WITH PSILI AND YPOGEGRAMMENI;Ll;0;L;1F00 0345;;;;N;;;1F88;;1F88 1F81;GREEK SMALL LETTER ALPHA WITH DASIA AND YPOGEGRAMMENI;Ll;0;L;1F01 0345;;;;N;;;1F89;;1F89 1F82;GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA AND YPOGEGRAMMENI;Ll;0;L;1F02 0345;;;;N;;;1F8A;;1F8A 1F83;GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA AND YPOGEGRAMMENI;Ll;0;L;1F03 0345;;;;N;;;1F8B;;1F8B 1F84;GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA AND YPOGEGRAMMENI;Ll;0;L;1F04 0345;;;;N;;;1F8C;;1F8C 1F85;GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA AND YPOGEGRAMMENI;Ll;0;L;1F05 0345;;;;N;;;1F8D;;1F8D 1F86;GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1F06 0345;;;;N;;;1F8E;;1F8E 1F87;GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1F07 0345;;;;N;;;1F8F;;1F8F 1F88;GREEK CAPITAL LETTER ALPHA WITH PSILI AND PROSGEGRAMMENI;Lt;0;L;1F08 0345;;;;N;;;;1F80; 1F89;GREEK CAPITAL LETTER ALPHA WITH DASIA AND PROSGEGRAMMENI;Lt;0;L;1F09 0345;;;;N;;;;1F81; 1F8A;GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI;Lt;0;L;1F0A 0345;;;;N;;;;1F82; 1F8B;GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI;Lt;0;L;1F0B 0345;;;;N;;;;1F83; 1F8C;GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI;Lt;0;L;1F0C 0345;;;;N;;;;1F84; 1F8D;GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI;Lt;0;L;1F0D 0345;;;;N;;;;1F85; 1F8E;GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI;Lt;0;L;1F0E 0345;;;;N;;;;1F86; 1F8F;GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI;Lt;0;L;1F0F 0345;;;;N;;;;1F87; 1F90;GREEK SMALL LETTER ETA WITH PSILI AND YPOGEGRAMMENI;Ll;0;L;1F20 0345;;;;N;;;1F98;;1F98 1F91;GREEK SMALL LETTER ETA WITH DASIA AND YPOGEGRAMMENI;Ll;0;L;1F21 0345;;;;N;;;1F99;;1F99 1F92;GREEK SMALL LETTER ETA WITH PSILI AND VARIA AND YPOGEGRAMMENI;Ll;0;L;1F22 0345;;;;N;;;1F9A;;1F9A 1F93;GREEK SMALL LETTER ETA WITH DASIA AND VARIA AND YPOGEGRAMMENI;Ll;0;L;1F23 0345;;;;N;;;1F9B;;1F9B 1F94;GREEK SMALL LETTER ETA WITH PSILI AND OXIA AND YPOGEGRAMMENI;Ll;0;L;1F24 0345;;;;N;;;1F9C;;1F9C 1F95;GREEK SMALL LETTER ETA WITH DASIA AND OXIA AND YPOGEGRAMMENI;Ll;0;L;1F25 0345;;;;N;;;1F9D;;1F9D 1F96;GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1F26 0345;;;;N;;;1F9E;;1F9E 1F97;GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1F27 0345;;;;N;;;1F9F;;1F9F 1F98;GREEK CAPITAL LETTER ETA WITH PSILI AND PROSGEGRAMMENI;Lt;0;L;1F28 0345;;;;N;;;;1F90; 1F99;GREEK CAPITAL LETTER ETA WITH DASIA AND PROSGEGRAMMENI;Lt;0;L;1F29 0345;;;;N;;;;1F91; 1F9A;GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI;Lt;0;L;1F2A 0345;;;;N;;;;1F92; 1F9B;GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI;Lt;0;L;1F2B 0345;;;;N;;;;1F93; 1F9C;GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI;Lt;0;L;1F2C 0345;;;;N;;;;1F94; 1F9D;GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI;Lt;0;L;1F2D 0345;;;;N;;;;1F95; 1F9E;GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI;Lt;0;L;1F2E 0345;;;;N;;;;1F96; 1F9F;GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI;Lt;0;L;1F2F 0345;;;;N;;;;1F97; 1FA0;GREEK SMALL LETTER OMEGA WITH PSILI AND YPOGEGRAMMENI;Ll;0;L;1F60 0345;;;;N;;;1FA8;;1FA8 1FA1;GREEK SMALL LETTER OMEGA WITH DASIA AND YPOGEGRAMMENI;Ll;0;L;1F61 0345;;;;N;;;1FA9;;1FA9 1FA2;GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA AND YPOGEGRAMMENI;Ll;0;L;1F62 0345;;;;N;;;1FAA;;1FAA 1FA3;GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA AND YPOGEGRAMMENI;Ll;0;L;1F63 0345;;;;N;;;1FAB;;1FAB 1FA4;GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA AND YPOGEGRAMMENI;Ll;0;L;1F64 0345;;;;N;;;1FAC;;1FAC 1FA5;GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA AND YPOGEGRAMMENI;Ll;0;L;1F65 0345;;;;N;;;1FAD;;1FAD 1FA6;GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1F66 0345;;;;N;;;1FAE;;1FAE 1FA7;GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1F67 0345;;;;N;;;1FAF;;1FAF 1FA8;GREEK CAPITAL LETTER OMEGA WITH PSILI AND PROSGEGRAMMENI;Lt;0;L;1F68 0345;;;;N;;;;1FA0; 1FA9;GREEK CAPITAL LETTER OMEGA WITH DASIA AND PROSGEGRAMMENI;Lt;0;L;1F69 0345;;;;N;;;;1FA1; 1FAA;GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI;Lt;0;L;1F6A 0345;;;;N;;;;1FA2; 1FAB;GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI;Lt;0;L;1F6B 0345;;;;N;;;;1FA3; 1FAC;GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI;Lt;0;L;1F6C 0345;;;;N;;;;1FA4; 1FAD;GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI;Lt;0;L;1F6D 0345;;;;N;;;;1FA5; 1FAE;GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI;Lt;0;L;1F6E 0345;;;;N;;;;1FA6; 1FAF;GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI;Lt;0;L;1F6F 0345;;;;N;;;;1FA7; 1FB0;GREEK SMALL LETTER ALPHA WITH VRACHY;Ll;0;L;03B1 0306;;;;N;;;1FB8;;1FB8 1FB1;GREEK SMALL LETTER ALPHA WITH MACRON;Ll;0;L;03B1 0304;;;;N;;;1FB9;;1FB9 1FB2;GREEK SMALL LETTER ALPHA WITH VARIA AND YPOGEGRAMMENI;Ll;0;L;1F70 0345;;;;N;;;;; 1FB3;GREEK SMALL LETTER ALPHA WITH YPOGEGRAMMENI;Ll;0;L;03B1 0345;;;;N;;;1FBC;;1FBC 1FB4;GREEK SMALL LETTER ALPHA WITH OXIA AND YPOGEGRAMMENI;Ll;0;L;03AC 0345;;;;N;;;;; 1FB6;GREEK SMALL LETTER ALPHA WITH PERISPOMENI;Ll;0;L;03B1 0342;;;;N;;;;; 1FB7;GREEK SMALL LETTER ALPHA WITH PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1FB6 0345;;;;N;;;;; 1FB8;GREEK CAPITAL LETTER ALPHA WITH VRACHY;Lu;0;L;0391 0306;;;;N;;;;1FB0; 1FB9;GREEK CAPITAL LETTER ALPHA WITH MACRON;Lu;0;L;0391 0304;;;;N;;;;1FB1; 1FBA;GREEK CAPITAL LETTER ALPHA WITH VARIA;Lu;0;L;0391 0300;;;;N;;;;1F70; 1FBB;GREEK CAPITAL LETTER ALPHA WITH OXIA;Lu;0;L;0386;;;;N;;;;1F71; 1FBC;GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI;Lt;0;L;0391 0345;;;;N;;;;1FB3; 1FBD;GREEK KORONIS;Sk;0;ON;<compat> 0020 0313;;;;N;;;;; 1FBE;GREEK PROSGEGRAMMENI;Ll;0;L;03B9;;;;N;;;0399;;0399 1FBF;GREEK PSILI;Sk;0;ON;<compat> 0020 0313;;;;N;;;;; 1FC0;GREEK PERISPOMENI;Sk;0;ON;<compat> 0020 0342;;;;N;;;;; 1FC1;GREEK DIALYTIKA AND PERISPOMENI;Sk;0;ON;00A8 0342;;;;N;;;;; 1FC2;GREEK SMALL LETTER ETA WITH VARIA AND YPOGEGRAMMENI;Ll;0;L;1F74 0345;;;;N;;;;; 1FC3;GREEK SMALL LETTER ETA WITH YPOGEGRAMMENI;Ll;0;L;03B7 0345;;;;N;;;1FCC;;1FCC 1FC4;GREEK SMALL LETTER ETA WITH OXIA AND YPOGEGRAMMENI;Ll;0;L;03AE 0345;;;;N;;;;; 1FC6;GREEK SMALL LETTER ETA WITH PERISPOMENI;Ll;0;L;03B7 0342;;;;N;;;;; 1FC7;GREEK SMALL LETTER ETA WITH PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1FC6 0345;;;;N;;;;; 1FC8;GREEK CAPITAL LETTER EPSILON WITH VARIA;Lu;0;L;0395 0300;;;;N;;;;1F72; 1FC9;GREEK CAPITAL LETTER EPSILON WITH OXIA;Lu;0;L;0388;;;;N;;;;1F73; 1FCA;GREEK CAPITAL LETTER ETA WITH VARIA;Lu;0;L;0397 0300;;;;N;;;;1F74; 1FCB;GREEK CAPITAL LETTER ETA WITH OXIA;Lu;0;L;0389;;;;N;;;;1F75; 1FCC;GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI;Lt;0;L;0397 0345;;;;N;;;;1FC3; 1FCD;GREEK PSILI AND VARIA;Sk;0;ON;1FBF 0300;;;;N;;;;; 1FCE;GREEK PSILI AND OXIA;Sk;0;ON;1FBF 0301;;;;N;;;;; 1FCF;GREEK PSILI AND PERISPOMENI;Sk;0;ON;1FBF 0342;;;;N;;;;; 1FD0;GREEK SMALL LETTER IOTA WITH VRACHY;Ll;0;L;03B9 0306;;;;N;;;1FD8;;1FD8 1FD1;GREEK SMALL LETTER IOTA WITH MACRON;Ll;0;L;03B9 0304;;;;N;;;1FD9;;1FD9 1FD2;GREEK SMALL LETTER IOTA WITH DIALYTIKA AND VARIA;Ll;0;L;03CA 0300;;;;N;;;;; 1FD3;GREEK SMALL LETTER IOTA WITH DIALYTIKA AND OXIA;Ll;0;L;0390;;;;N;;;;; 1FD6;GREEK SMALL LETTER IOTA WITH PERISPOMENI;Ll;0;L;03B9 0342;;;;N;;;;; 1FD7;GREEK SMALL LETTER IOTA WITH DIALYTIKA AND PERISPOMENI;Ll;0;L;03CA 0342;;;;N;;;;; 1FD8;GREEK CAPITAL LETTER IOTA WITH VRACHY;Lu;0;L;0399 0306;;;;N;;;;1FD0; 1FD9;GREEK CAPITAL LETTER IOTA WITH MACRON;Lu;0;L;0399 0304;;;;N;;;;1FD1; 1FDA;GREEK CAPITAL LETTER IOTA WITH VARIA;Lu;0;L;0399 0300;;;;N;;;;1F76; 1FDB;GREEK CAPITAL LETTER IOTA WITH OXIA;Lu;0;L;038A;;;;N;;;;1F77; 1FDD;GREEK DASIA AND VARIA;Sk;0;ON;1FFE 0300;;;;N;;;;; 1FDE;GREEK DASIA AND OXIA;Sk;0;ON;1FFE 0301;;;;N;;;;; 1FDF;GREEK DASIA AND PERISPOMENI;Sk;0;ON;1FFE 0342;;;;N;;;;; 1FE0;GREEK SMALL LETTER UPSILON WITH VRACHY;Ll;0;L;03C5 0306;;;;N;;;1FE8;;1FE8 1FE1;GREEK SMALL LETTER UPSILON WITH MACRON;Ll;0;L;03C5 0304;;;;N;;;1FE9;;1FE9 1FE2;GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND VARIA;Ll;0;L;03CB 0300;;;;N;;;;; 1FE3;GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND OXIA;Ll;0;L;03B0;;;;N;;;;; 1FE4;GREEK SMALL LETTER RHO WITH PSILI;Ll;0;L;03C1 0313;;;;N;;;;; 1FE5;GREEK SMALL LETTER RHO WITH DASIA;Ll;0;L;03C1 0314;;;;N;;;1FEC;;1FEC 1FE6;GREEK SMALL LETTER UPSILON WITH PERISPOMENI;Ll;0;L;03C5 0342;;;;N;;;;; 1FE7;GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND PERISPOMENI;Ll;0;L;03CB 0342;;;;N;;;;; 1FE8;GREEK CAPITAL LETTER UPSILON WITH VRACHY;Lu;0;L;03A5 0306;;;;N;;;;1FE0; 1FE9;GREEK CAPITAL LETTER UPSILON WITH MACRON;Lu;0;L;03A5 0304;;;;N;;;;1FE1; 1FEA;GREEK CAPITAL LETTER UPSILON WITH VARIA;Lu;0;L;03A5 0300;;;;N;;;;1F7A; 1FEB;GREEK CAPITAL LETTER UPSILON WITH OXIA;Lu;0;L;038E;;;;N;;;;1F7B; 1FEC;GREEK CAPITAL LETTER RHO WITH DASIA;Lu;0;L;03A1 0314;;;;N;;;;1FE5; 1FED;GREEK DIALYTIKA AND VARIA;Sk;0;ON;00A8 0300;;;;N;;;;; 1FEE;GREEK DIALYTIKA AND OXIA;Sk;0;ON;0385;;;;N;;;;; 1FEF;GREEK VARIA;Sk;0;ON;0060;;;;N;;;;; 1FF2;GREEK SMALL LETTER OMEGA WITH VARIA AND YPOGEGRAMMENI;Ll;0;L;1F7C 0345;;;;N;;;;; 1FF3;GREEK SMALL LETTER OMEGA WITH YPOGEGRAMMENI;Ll;0;L;03C9 0345;;;;N;;;1FFC;;1FFC 1FF4;GREEK SMALL LETTER OMEGA WITH OXIA AND YPOGEGRAMMENI;Ll;0;L;03CE 0345;;;;N;;;;; 1FF6;GREEK SMALL LETTER OMEGA WITH PERISPOMENI;Ll;0;L;03C9 0342;;;;N;;;;; 1FF7;GREEK SMALL LETTER OMEGA WITH PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1FF6 0345;;;;N;;;;; 1FF8;GREEK CAPITAL LETTER OMICRON WITH VARIA;Lu;0;L;039F 0300;;;;N;;;;1F78; 1FF9;GREEK CAPITAL LETTER OMICRON WITH OXIA;Lu;0;L;038C;;;;N;;;;1F79; 1FFA;GREEK CAPITAL LETTER OMEGA WITH VARIA;Lu;0;L;03A9 0300;;;;N;;;;1F7C; 1FFB;GREEK CAPITAL LETTER OMEGA WITH OXIA;Lu;0;L;038F;;;;N;;;;1F7D; 1FFC;GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI;Lt;0;L;03A9 0345;;;;N;;;;1FF3; 1FFD;GREEK OXIA;Sk;0;ON;00B4;;;;N;;;;; 1FFE;GREEK DASIA;Sk;0;ON;<compat> 0020 0314;;;;N;;;;; 2000;EN QUAD;Zs;0;WS;2002;;;;N;;;;; 2001;EM QUAD;Zs;0;WS;2003;;;;N;;;;; 2002;EN SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;; 2003;EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;; 2004;THREE-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;; 2005;FOUR-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;; 2006;SIX-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;; 2007;FIGURE SPACE;Zs;0;WS;<noBreak> 0020;;;;N;;;;; 2008;PUNCTUATION SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;; 2009;THIN SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;; 200A;HAIR SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;; 200B;ZERO WIDTH SPACE;Cf;0;BN;;;;;N;;;;; 200C;ZERO WIDTH NON-JOINER;Cf;0;BN;;;;;N;;;;; 200D;ZERO WIDTH JOINER;Cf;0;BN;;;;;N;;;;; 200E;LEFT-TO-RIGHT MARK;Cf;0;L;;;;;N;;;;; 200F;RIGHT-TO-LEFT MARK;Cf;0;R;;;;;N;;;;; 2010;HYPHEN;Pd;0;ON;;;;;N;;;;; 2011;NON-BREAKING HYPHEN;Pd;0;ON;<noBreak> 2010;;;;N;;;;; 2012;FIGURE DASH;Pd;0;ON;;;;;N;;;;; 2013;EN DASH;Pd;0;ON;;;;;N;;;;; 2014;EM DASH;Pd;0;ON;;;;;N;;;;; 2015;HORIZONTAL BAR;Pd;0;ON;;;;;N;QUOTATION DASH;;;; 2016;DOUBLE VERTICAL LINE;Po;0;ON;;;;;N;DOUBLE VERTICAL BAR;;;; 2017;DOUBLE LOW LINE;Po;0;ON;<compat> 0020 0333;;;;N;SPACING DOUBLE UNDERSCORE;;;; 2018;LEFT SINGLE QUOTATION MARK;Pi;0;ON;;;;;N;SINGLE TURNED COMMA QUOTATION MARK;;;; 2019;RIGHT SINGLE QUOTATION MARK;Pf;0;ON;;;;;N;SINGLE COMMA QUOTATION MARK;;;; 201A;SINGLE LOW-9 QUOTATION MARK;Ps;0;ON;;;;;N;LOW SINGLE COMMA QUOTATION MARK;;;; 201B;SINGLE HIGH-REVERSED-9 QUOTATION MARK;Pi;0;ON;;;;;N;SINGLE REVERSED COMMA QUOTATION MARK;;;; 201C;LEFT DOUBLE QUOTATION MARK;Pi;0;ON;;;;;N;DOUBLE TURNED COMMA QUOTATION MARK;;;; 201D;RIGHT DOUBLE QUOTATION MARK;Pf;0;ON;;;;;N;DOUBLE COMMA QUOTATION MARK;;;; 201E;DOUBLE LOW-9 QUOTATION MARK;Ps;0;ON;;;;;N;LOW DOUBLE COMMA QUOTATION MARK;;;; 201F;DOUBLE HIGH-REVERSED-9 QUOTATION MARK;Pi;0;ON;;;;;N;DOUBLE REVERSED COMMA QUOTATION MARK;;;; 2020;DAGGER;Po;0;ON;;;;;N;;;;; 2021;DOUBLE DAGGER;Po;0;ON;;;;;N;;;;; 2022;BULLET;Po;0;ON;;;;;N;;;;; 2023;TRIANGULAR BULLET;Po;0;ON;;;;;N;;;;; 2024;ONE DOT LEADER;Po;0;ON;<compat> 002E;;;;N;;;;; 2025;TWO DOT LEADER;Po;0;ON;<compat> 002E 002E;;;;N;;;;; 2026;HORIZONTAL ELLIPSIS;Po;0;ON;<compat> 002E 002E 002E;;;;N;;;;; 2027;HYPHENATION POINT;Po;0;ON;;;;;N;;;;; 2028;LINE SEPARATOR;Zl;0;WS;;;;;N;;;;; 2029;PARAGRAPH SEPARATOR;Zp;0;B;;;;;N;;;;; 202A;LEFT-TO-RIGHT EMBEDDING;Cf;0;LRE;;;;;N;;;;; 202B;RIGHT-TO-LEFT EMBEDDING;Cf;0;RLE;;;;;N;;;;; 202C;POP DIRECTIONAL FORMATTING;Cf;0;PDF;;;;;N;;;;; 202D;LEFT-TO-RIGHT OVERRIDE;Cf;0;LRO;;;;;N;;;;; 202E;RIGHT-TO-LEFT OVERRIDE;Cf;0;RLO;;;;;N;;;;; 202F;NARROW NO-BREAK SPACE;Zs;0;CS;<noBreak> 0020;;;;N;;;;; 2030;PER MILLE SIGN;Po;0;ET;;;;;N;;;;; 2031;PER TEN THOUSAND SIGN;Po;0;ET;;;;;N;;;;; 2032;PRIME;Po;0;ET;;;;;N;;;;; 2033;DOUBLE PRIME;Po;0;ET;<compat> 2032 2032;;;;N;;;;; 2034;TRIPLE PRIME;Po;0;ET;<compat> 2032 2032 2032;;;;N;;;;; 2035;REVERSED PRIME;Po;0;ON;;;;;N;;;;; 2036;REVERSED DOUBLE PRIME;Po;0;ON;<compat> 2035 2035;;;;N;;;;; 2037;REVERSED TRIPLE PRIME;Po;0;ON;<compat> 2035 2035 2035;;;;N;;;;; 2038;CARET;Po;0;ON;;;;;N;;;;; 2039;SINGLE LEFT-POINTING ANGLE QUOTATION MARK;Pi;0;ON;;;;;Y;LEFT POINTING SINGLE GUILLEMET;;;; 203A;SINGLE RIGHT-POINTING ANGLE QUOTATION MARK;Pf;0;ON;;;;;Y;RIGHT POINTING SINGLE GUILLEMET;;;; 203B;REFERENCE MARK;Po;0;ON;;;;;N;;;;; 203C;DOUBLE EXCLAMATION MARK;Po;0;ON;<compat> 0021 0021;;;;N;;;;; 203D;INTERROBANG;Po;0;ON;;;;;N;;;;; 203E;OVERLINE;Po;0;ON;<compat> 0020 0305;;;;N;SPACING OVERSCORE;;;; 203F;UNDERTIE;Pc;0;ON;;;;;N;;;;; 2040;CHARACTER TIE;Pc;0;ON;;;;;N;;;;; 2041;CARET INSERTION POINT;Po;0;ON;;;;;N;;;;; 2042;ASTERISM;Po;0;ON;;;;;N;;;;; 2043;HYPHEN BULLET;Po;0;ON;;;;;N;;;;; 2044;FRACTION SLASH;Sm;0;CS;;;;;N;;;;; 2045;LEFT SQUARE BRACKET WITH QUILL;Ps;0;ON;;;;;Y;;;;; 2046;RIGHT SQUARE BRACKET WITH QUILL;Pe;0;ON;;;;;Y;;;;; 2047;DOUBLE QUESTION MARK;Po;0;ON;<compat> 003F 003F;;;;N;;;;; 2048;QUESTION EXCLAMATION MARK;Po;0;ON;<compat> 003F 0021;;;;N;;;;; 2049;EXCLAMATION QUESTION MARK;Po;0;ON;<compat> 0021 003F;;;;N;;;;; 204A;TIRONIAN SIGN ET;Po;0;ON;;;;;N;;;;; 204B;REVERSED PILCROW SIGN;Po;0;ON;;;;;N;;;;; 204C;BLACK LEFTWARDS BULLET;Po;0;ON;;;;;N;;;;; 204D;BLACK RIGHTWARDS BULLET;Po;0;ON;;;;;N;;;;; 204E;LOW ASTERISK;Po;0;ON;;;;;N;;;;; 204F;REVERSED SEMICOLON;Po;0;ON;;;;;N;;;;; 2050;CLOSE UP;Po;0;ON;;;;;N;;;;; 2051;TWO ASTERISKS ALIGNED VERTICALLY;Po;0;ON;;;;;N;;;;; 2052;COMMERCIAL MINUS SIGN;Sm;0;ON;;;;;N;;;;; 2053;SWUNG DASH;Po;0;ON;;;;;N;;;;; 2054;INVERTED UNDERTIE;Pc;0;ON;;;;;N;;;;; 2055;FLOWER PUNCTUATION MARK;Po;0;ON;;;;;N;;;;; 2056;THREE DOT PUNCTUATION;Po;0;ON;;;;;N;;;;; 2057;QUADRUPLE PRIME;Po;0;ON;<compat> 2032 2032 2032 2032;;;;N;;;;; 2058;FOUR DOT PUNCTUATION;Po;0;ON;;;;;N;;;;; 2059;FIVE DOT PUNCTUATION;Po;0;ON;;;;;N;;;;; 205A;TWO DOT PUNCTUATION;Po;0;ON;;;;;N;;;;; 205B;FOUR DOT MARK;Po;0;ON;;;;;N;;;;; 205C;DOTTED CROSS;Po;0;ON;;;;;N;;;;; 205D;TRICOLON;Po;0;ON;;;;;N;;;;; 205E;VERTICAL FOUR DOTS;Po;0;ON;;;;;N;;;;; 205F;MEDIUM MATHEMATICAL SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;; 2060;WORD JOINER;Cf;0;BN;;;;;N;;;;; 2061;FUNCTION APPLICATION;Cf;0;BN;;;;;N;;;;; 2062;INVISIBLE TIMES;Cf;0;BN;;;;;N;;;;; 2063;INVISIBLE SEPARATOR;Cf;0;BN;;;;;N;;;;; 2064;INVISIBLE PLUS;Cf;0;BN;;;;;N;;;;; 2066;LEFT-TO-RIGHT ISOLATE;Cf;0;LRI;;;;;N;;;;; 2067;RIGHT-TO-LEFT ISOLATE;Cf;0;RLI;;;;;N;;;;; 2068;FIRST STRONG ISOLATE;Cf;0;FSI;;;;;N;;;;; 2069;POP DIRECTIONAL ISOLATE;Cf;0;PDI;;;;;N;;;;; 206A;INHIBIT SYMMETRIC SWAPPING;Cf;0;BN;;;;;N;;;;; 206B;ACTIVATE SYMMETRIC SWAPPING;Cf;0;BN;;;;;N;;;;; 206C;INHIBIT ARABIC FORM SHAPING;Cf;0;BN;;;;;N;;;;; 206D;ACTIVATE ARABIC FORM SHAPING;Cf;0;BN;;;;;N;;;;; 206E;NATIONAL DIGIT SHAPES;Cf;0;BN;;;;;N;;;;; 206F;NOMINAL DIGIT SHAPES;Cf;0;BN;;;;;N;;;;; 2070;SUPERSCRIPT ZERO;No;0;EN;<super> 0030;;0;0;N;SUPERSCRIPT DIGIT ZERO;;;; 2071;SUPERSCRIPT LATIN SMALL LETTER I;Lm;0;L;<super> 0069;;;;N;;;;; 2074;SUPERSCRIPT FOUR;No;0;EN;<super> 0034;;4;4;N;SUPERSCRIPT DIGIT FOUR;;;; 2075;SUPERSCRIPT FIVE;No;0;EN;<super> 0035;;5;5;N;SUPERSCRIPT DIGIT FIVE;;;; 2076;SUPERSCRIPT SIX;No;0;EN;<super> 0036;;6;6;N;SUPERSCRIPT DIGIT SIX;;;; 2077;SUPERSCRIPT SEVEN;No;0;EN;<super> 0037;;7;7;N;SUPERSCRIPT DIGIT SEVEN;;;; 2078;SUPERSCRIPT EIGHT;No;0;EN;<super> 0038;;8;8;N;SUPERSCRIPT DIGIT EIGHT;;;; 2079;SUPERSCRIPT NINE;No;0;EN;<super> 0039;;9;9;N;SUPERSCRIPT DIGIT NINE;;;; 207A;SUPERSCRIPT PLUS SIGN;Sm;0;ES;<super> 002B;;;;N;;;;; 207B;SUPERSCRIPT MINUS;Sm;0;ES;<super> 2212;;;;N;SUPERSCRIPT HYPHEN-MINUS;;;; 207C;SUPERSCRIPT EQUALS SIGN;Sm;0;ON;<super> 003D;;;;N;;;;; 207D;SUPERSCRIPT LEFT PARENTHESIS;Ps;0;ON;<super> 0028;;;;Y;SUPERSCRIPT OPENING PARENTHESIS;;;; 207E;SUPERSCRIPT RIGHT PARENTHESIS;Pe;0;ON;<super> 0029;;;;Y;SUPERSCRIPT CLOSING PARENTHESIS;;;; 207F;SUPERSCRIPT LATIN SMALL LETTER N;Lm;0;L;<super> 006E;;;;N;;;;; 2080;SUBSCRIPT ZERO;No;0;EN;<sub> 0030;;0;0;N;SUBSCRIPT DIGIT ZERO;;;; 2081;SUBSCRIPT ONE;No;0;EN;<sub> 0031;;1;1;N;SUBSCRIPT DIGIT ONE;;;; 2082;SUBSCRIPT TWO;No;0;EN;<sub> 0032;;2;2;N;SUBSCRIPT DIGIT TWO;;;; 2083;SUBSCRIPT THREE;No;0;EN;<sub> 0033;;3;3;N;SUBSCRIPT DIGIT THREE;;;; 2084;SUBSCRIPT FOUR;No;0;EN;<sub> 0034;;4;4;N;SUBSCRIPT DIGIT FOUR;;;; 2085;SUBSCRIPT FIVE;No;0;EN;<sub> 0035;;5;5;N;SUBSCRIPT DIGIT FIVE;;;; 2086;SUBSCRIPT SIX;No;0;EN;<sub> 0036;;6;6;N;SUBSCRIPT DIGIT SIX;;;; 2087;SUBSCRIPT SEVEN;No;0;EN;<sub> 0037;;7;7;N;SUBSCRIPT DIGIT SEVEN;;;; 2088;SUBSCRIPT EIGHT;No;0;EN;<sub> 0038;;8;8;N;SUBSCRIPT DIGIT EIGHT;;;; 2089;SUBSCRIPT NINE;No;0;EN;<sub> 0039;;9;9;N;SUBSCRIPT DIGIT NINE;;;; 208A;SUBSCRIPT PLUS SIGN;Sm;0;ES;<sub> 002B;;;;N;;;;; 208B;SUBSCRIPT MINUS;Sm;0;ES;<sub> 2212;;;;N;SUBSCRIPT HYPHEN-MINUS;;;; 208C;SUBSCRIPT EQUALS SIGN;Sm;0;ON;<sub> 003D;;;;N;;;;; 208D;SUBSCRIPT LEFT PARENTHESIS;Ps;0;ON;<sub> 0028;;;;Y;SUBSCRIPT OPENING PARENTHESIS;;;; 208E;SUBSCRIPT RIGHT PARENTHESIS;Pe;0;ON;<sub> 0029;;;;Y;SUBSCRIPT CLOSING PARENTHESIS;;;; 2090;LATIN SUBSCRIPT SMALL LETTER A;Lm;0;L;<sub> 0061;;;;N;;;;; 2091;LATIN SUBSCRIPT SMALL LETTER E;Lm;0;L;<sub> 0065;;;;N;;;;; 2092;LATIN SUBSCRIPT SMALL LETTER O;Lm;0;L;<sub> 006F;;;;N;;;;; 2093;LATIN SUBSCRIPT SMALL LETTER X;Lm;0;L;<sub> 0078;;;;N;;;;; 2094;LATIN SUBSCRIPT SMALL LETTER SCHWA;Lm;0;L;<sub> 0259;;;;N;;;;; 2095;LATIN SUBSCRIPT SMALL LETTER H;Lm;0;L;<sub> 0068;;;;N;;;;; 2096;LATIN SUBSCRIPT SMALL LETTER K;Lm;0;L;<sub> 006B;;;;N;;;;; 2097;LATIN SUBSCRIPT SMALL LETTER L;Lm;0;L;<sub> 006C;;;;N;;;;; 2098;LATIN SUBSCRIPT SMALL LETTER M;Lm;0;L;<sub> 006D;;;;N;;;;; 2099;LATIN SUBSCRIPT SMALL LETTER N;Lm;0;L;<sub> 006E;;;;N;;;;; 209A;LATIN SUBSCRIPT SMALL LETTER P;Lm;0;L;<sub> 0070;;;;N;;;;; 209B;LATIN SUBSCRIPT SMALL LETTER S;Lm;0;L;<sub> 0073;;;;N;;;;; 209C;LATIN SUBSCRIPT SMALL LETTER T;Lm;0;L;<sub> 0074;;;;N;;;;; 20A0;EURO-CURRENCY SIGN;Sc;0;ET;;;;;N;;;;; 20A1;COLON SIGN;Sc;0;ET;;;;;N;;;;; 20A2;CRUZEIRO SIGN;Sc;0;ET;;;;;N;;;;; 20A3;FRENCH FRANC SIGN;Sc;0;ET;;;;;N;;;;; 20A4;LIRA SIGN;Sc;0;ET;;;;;N;;;;; 20A5;MILL SIGN;Sc;0;ET;;;;;N;;;;; 20A6;NAIRA SIGN;Sc;0;ET;;;;;N;;;;; 20A7;PESETA SIGN;Sc;0;ET;;;;;N;;;;; 20A8;RUPEE SIGN;Sc;0;ET;<compat> 0052 0073;;;;N;;;;; 20A9;WON SIGN;Sc;0;ET;;;;;N;;;;; 20AA;NEW SHEQEL SIGN;Sc;0;ET;;;;;N;;;;; 20AB;DONG SIGN;Sc;0;ET;;;;;N;;;;; 20AC;EURO SIGN;Sc;0;ET;;;;;N;;;;; 20AD;KIP SIGN;Sc;0;ET;;;;;N;;;;; 20AE;TUGRIK SIGN;Sc;0;ET;;;;;N;;;;; 20AF;DRACHMA SIGN;Sc;0;ET;;;;;N;;;;; 20B0;GERMAN PENNY SIGN;Sc;0;ET;;;;;N;;;;; 20B1;PESO SIGN;Sc;0;ET;;;;;N;;;;; 20B2;GUARANI SIGN;Sc;0;ET;;;;;N;;;;; 20B3;AUSTRAL SIGN;Sc;0;ET;;;;;N;;;;; 20B4;HRYVNIA SIGN;Sc;0;ET;;;;;N;;;;; 20B5;CEDI SIGN;Sc;0;ET;;;;;N;;;;; 20B6;LIVRE TOURNOIS SIGN;Sc;0;ET;;;;;N;;;;; 20B7;SPESMILO SIGN;Sc;0;ET;;;;;N;;;;; 20B8;TENGE SIGN;Sc;0;ET;;;;;N;;;;; 20B9;INDIAN RUPEE SIGN;Sc;0;ET;;;;;N;;;;; 20BA;TURKISH LIRA SIGN;Sc;0;ET;;;;;N;;;;; 20BB;NORDIC MARK SIGN;Sc;0;ET;;;;;N;;;;; 20BC;MANAT SIGN;Sc;0;ET;;;;;N;;;;; 20BD;RUBLE SIGN;Sc;0;ET;;;;;N;;;;; 20BE;LARI SIGN;Sc;0;ET;;;;;N;;;;; 20D0;COMBINING LEFT HARPOON ABOVE;Mn;230;NSM;;;;;N;NON-SPACING LEFT HARPOON ABOVE;;;; 20D1;COMBINING RIGHT HARPOON ABOVE;Mn;230;NSM;;;;;N;NON-SPACING RIGHT HARPOON ABOVE;;;; 20D2;COMBINING LONG VERTICAL LINE OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING LONG VERTICAL BAR OVERLAY;;;; 20D3;COMBINING SHORT VERTICAL LINE OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING SHORT VERTICAL BAR OVERLAY;;;; 20D4;COMBINING ANTICLOCKWISE ARROW ABOVE;Mn;230;NSM;;;;;N;NON-SPACING ANTICLOCKWISE ARROW ABOVE;;;; 20D5;COMBINING CLOCKWISE ARROW ABOVE;Mn;230;NSM;;;;;N;NON-SPACING CLOCKWISE ARROW ABOVE;;;; 20D6;COMBINING LEFT ARROW ABOVE;Mn;230;NSM;;;;;N;NON-SPACING LEFT ARROW ABOVE;;;; 20D7;COMBINING RIGHT ARROW ABOVE;Mn;230;NSM;;;;;N;NON-SPACING RIGHT ARROW ABOVE;;;; 20D8;COMBINING RING OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING RING OVERLAY;;;; 20D9;COMBINING CLOCKWISE RING OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING CLOCKWISE RING OVERLAY;;;; 20DA;COMBINING ANTICLOCKWISE RING OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING ANTICLOCKWISE RING OVERLAY;;;; 20DB;COMBINING THREE DOTS ABOVE;Mn;230;NSM;;;;;N;NON-SPACING THREE DOTS ABOVE;;;; 20DC;COMBINING FOUR DOTS ABOVE;Mn;230;NSM;;;;;N;NON-SPACING FOUR DOTS ABOVE;;;; 20DD;COMBINING ENCLOSING CIRCLE;Me;0;NSM;;;;;N;ENCLOSING CIRCLE;;;; 20DE;COMBINING ENCLOSING SQUARE;Me;0;NSM;;;;;N;ENCLOSING SQUARE;;;; 20DF;COMBINING ENCLOSING DIAMOND;Me;0;NSM;;;;;N;ENCLOSING DIAMOND;;;; 20E0;COMBINING ENCLOSING CIRCLE BACKSLASH;Me;0;NSM;;;;;N;ENCLOSING CIRCLE SLASH;;;; 20E1;COMBINING LEFT RIGHT ARROW ABOVE;Mn;230;NSM;;;;;N;NON-SPACING LEFT RIGHT ARROW ABOVE;;;; 20E2;COMBINING ENCLOSING SCREEN;Me;0;NSM;;;;;N;;;;; 20E3;COMBINING ENCLOSING KEYCAP;Me;0;NSM;;;;;N;;;;; 20E4;COMBINING ENCLOSING UPWARD POINTING TRIANGLE;Me;0;NSM;;;;;N;;;;; 20E5;COMBINING REVERSE SOLIDUS OVERLAY;Mn;1;NSM;;;;;N;;;;; 20E6;COMBINING DOUBLE VERTICAL STROKE OVERLAY;Mn;1;NSM;;;;;N;;;;; 20E7;COMBINING ANNUITY SYMBOL;Mn;230;NSM;;;;;N;;;;; 20E8;COMBINING TRIPLE UNDERDOT;Mn;220;NSM;;;;;N;;;;; 20E9;COMBINING WIDE BRIDGE ABOVE;Mn;230;NSM;;;;;N;;;;; 20EA;COMBINING LEFTWARDS ARROW OVERLAY;Mn;1;NSM;;;;;N;;;;; 20EB;COMBINING LONG DOUBLE SOLIDUS OVERLAY;Mn;1;NSM;;;;;N;;;;; 20EC;COMBINING RIGHTWARDS HARPOON WITH BARB DOWNWARDS;Mn;220;NSM;;;;;N;;;;; 20ED;COMBINING LEFTWARDS HARPOON WITH BARB DOWNWARDS;Mn;220;NSM;;;;;N;;;;; 20EE;COMBINING LEFT ARROW BELOW;Mn;220;NSM;;;;;N;;;;; 20EF;COMBINING RIGHT ARROW BELOW;Mn;220;NSM;;;;;N;;;;; 20F0;COMBINING ASTERISK ABOVE;Mn;230;NSM;;;;;N;;;;; 2100;ACCOUNT OF;So;0;ON;<compat> 0061 002F 0063;;;;N;;;;; 2101;ADDRESSED TO THE SUBJECT;So;0;ON;<compat> 0061 002F 0073;;;;N;;;;; 2102;DOUBLE-STRUCK CAPITAL C;Lu;0;L;<font> 0043;;;;N;DOUBLE-STRUCK C;;;; 2103;DEGREE CELSIUS;So;0;ON;<compat> 00B0 0043;;;;N;DEGREES CENTIGRADE;;;; 2104;CENTRE LINE SYMBOL;So;0;ON;;;;;N;C L SYMBOL;;;; 2105;CARE OF;So;0;ON;<compat> 0063 002F 006F;;;;N;;;;; 2106;CADA UNA;So;0;ON;<compat> 0063 002F 0075;;;;N;;;;; 2107;EULER CONSTANT;Lu;0;L;<compat> 0190;;;;N;EULERS;;;; 2108;SCRUPLE;So;0;ON;;;;;N;;;;; 2109;DEGREE FAHRENHEIT;So;0;ON;<compat> 00B0 0046;;;;N;DEGREES FAHRENHEIT;;;; 210A;SCRIPT SMALL G;Ll;0;L;<font> 0067;;;;N;;;;; 210B;SCRIPT CAPITAL H;Lu;0;L;<font> 0048;;;;N;SCRIPT H;;;; 210C;BLACK-LETTER CAPITAL H;Lu;0;L;<font> 0048;;;;N;BLACK-LETTER H;;;; 210D;DOUBLE-STRUCK CAPITAL H;Lu;0;L;<font> 0048;;;;N;DOUBLE-STRUCK H;;;; 210E;PLANCK CONSTANT;Ll;0;L;<font> 0068;;;;N;;;;; 210F;PLANCK CONSTANT OVER TWO PI;Ll;0;L;<font> 0127;;;;N;PLANCK CONSTANT OVER 2 PI;;;; 2110;SCRIPT CAPITAL I;Lu;0;L;<font> 0049;;;;N;SCRIPT I;;;; 2111;BLACK-LETTER CAPITAL I;Lu;0;L;<font> 0049;;;;N;BLACK-LETTER I;;;; 2112;SCRIPT CAPITAL L;Lu;0;L;<font> 004C;;;;N;SCRIPT L;;;; 2113;SCRIPT SMALL L;Ll;0;L;<font> 006C;;;;N;;;;; 2114;L B BAR SYMBOL;So;0;ON;;;;;N;;;;; 2115;DOUBLE-STRUCK CAPITAL N;Lu;0;L;<font> 004E;;;;N;DOUBLE-STRUCK N;;;; 2116;NUMERO SIGN;So;0;ON;<compat> 004E 006F;;;;N;NUMERO;;;; 2117;SOUND RECORDING COPYRIGHT;So;0;ON;;;;;N;;;;; 2118;SCRIPT CAPITAL P;Sm;0;ON;;;;;N;SCRIPT P;;;; 2119;DOUBLE-STRUCK CAPITAL P;Lu;0;L;<font> 0050;;;;N;DOUBLE-STRUCK P;;;; 211A;DOUBLE-STRUCK CAPITAL Q;Lu;0;L;<font> 0051;;;;N;DOUBLE-STRUCK Q;;;; 211B;SCRIPT CAPITAL R;Lu;0;L;<font> 0052;;;;N;SCRIPT R;;;; 211C;BLACK-LETTER CAPITAL R;Lu;0;L;<font> 0052;;;;N;BLACK-LETTER R;;;; 211D;DOUBLE-STRUCK CAPITAL R;Lu;0;L;<font> 0052;;;;N;DOUBLE-STRUCK R;;;; 211E;PRESCRIPTION TAKE;So;0;ON;;;;;N;;;;; 211F;RESPONSE;So;0;ON;;;;;N;;;;; 2120;SERVICE MARK;So;0;ON;<super> 0053 004D;;;;N;;;;; 2121;TELEPHONE SIGN;So;0;ON;<compat> 0054 0045 004C;;;;N;T E L SYMBOL;;;; 2122;TRADE MARK SIGN;So;0;ON;<super> 0054 004D;;;;N;TRADEMARK;;;; 2123;VERSICLE;So;0;ON;;;;;N;;;;; 2124;DOUBLE-STRUCK CAPITAL Z;Lu;0;L;<font> 005A;;;;N;DOUBLE-STRUCK Z;;;; 2125;OUNCE SIGN;So;0;ON;;;;;N;OUNCE;;;; 2126;OHM SIGN;Lu;0;L;03A9;;;;N;OHM;;;03C9; 2127;INVERTED OHM SIGN;So;0;ON;;;;;N;MHO;;;; 2128;BLACK-LETTER CAPITAL Z;Lu;0;L;<font> 005A;;;;N;BLACK-LETTER Z;;;; 2129;TURNED GREEK SMALL LETTER IOTA;So;0;ON;;;;;N;;;;; 212A;KELVIN SIGN;Lu;0;L;004B;;;;N;DEGREES KELVIN;;;006B; 212B;ANGSTROM SIGN;Lu;0;L;00C5;;;;N;ANGSTROM UNIT;;;00E5; 212C;SCRIPT CAPITAL B;Lu;0;L;<font> 0042;;;;N;SCRIPT B;;;; 212D;BLACK-LETTER CAPITAL C;Lu;0;L;<font> 0043;;;;N;BLACK-LETTER C;;;; 212E;ESTIMATED SYMBOL;So;0;ET;;;;;N;;;;; 212F;SCRIPT SMALL E;Ll;0;L;<font> 0065;;;;N;;;;; 2130;SCRIPT CAPITAL E;Lu;0;L;<font> 0045;;;;N;SCRIPT E;;;; 2131;SCRIPT CAPITAL F;Lu;0;L;<font> 0046;;;;N;SCRIPT F;;;; 2132;TURNED CAPITAL F;Lu;0;L;;;;;N;TURNED F;;;214E; 2133;SCRIPT CAPITAL M;Lu;0;L;<font> 004D;;;;N;SCRIPT M;;;; 2134;SCRIPT SMALL O;Ll;0;L;<font> 006F;;;;N;;;;; 2135;ALEF SYMBOL;Lo;0;L;<compat> 05D0;;;;N;FIRST TRANSFINITE CARDINAL;;;; 2136;BET SYMBOL;Lo;0;L;<compat> 05D1;;;;N;SECOND TRANSFINITE CARDINAL;;;; 2137;GIMEL SYMBOL;Lo;0;L;<compat> 05D2;;;;N;THIRD TRANSFINITE CARDINAL;;;; 2138;DALET SYMBOL;Lo;0;L;<compat> 05D3;;;;N;FOURTH TRANSFINITE CARDINAL;;;; 2139;INFORMATION SOURCE;Ll;0;L;<font> 0069;;;;N;;;;; 213A;ROTATED CAPITAL Q;So;0;ON;;;;;N;;;;; 213B;FACSIMILE SIGN;So;0;ON;<compat> 0046 0041 0058;;;;N;;;;; 213C;DOUBLE-STRUCK SMALL PI;Ll;0;L;<font> 03C0;;;;N;;;;; 213D;DOUBLE-STRUCK SMALL GAMMA;Ll;0;L;<font> 03B3;;;;N;;;;; 213E;DOUBLE-STRUCK CAPITAL GAMMA;Lu;0;L;<font> 0393;;;;N;;;;; 213F;DOUBLE-STRUCK CAPITAL PI;Lu;0;L;<font> 03A0;;;;N;;;;; 2140;DOUBLE-STRUCK N-ARY SUMMATION;Sm;0;ON;<font> 2211;;;;Y;;;;; 2141;TURNED SANS-SERIF CAPITAL G;Sm;0;ON;;;;;N;;;;; 2142;TURNED SANS-SERIF CAPITAL L;Sm;0;ON;;;;;N;;;;; 2143;REVERSED SANS-SERIF CAPITAL L;Sm;0;ON;;;;;N;;;;; 2144;TURNED SANS-SERIF CAPITAL Y;Sm;0;ON;;;;;N;;;;; 2145;DOUBLE-STRUCK ITALIC CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;; 2146;DOUBLE-STRUCK ITALIC SMALL D;Ll;0;L;<font> 0064;;;;N;;;;; 2147;DOUBLE-STRUCK ITALIC SMALL E;Ll;0;L;<font> 0065;;;;N;;;;; 2148;DOUBLE-STRUCK ITALIC SMALL I;Ll;0;L;<font> 0069;;;;N;;;;; 2149;DOUBLE-STRUCK ITALIC SMALL J;Ll;0;L;<font> 006A;;;;N;;;;; 214A;PROPERTY LINE;So;0;ON;;;;;N;;;;; 214B;TURNED AMPERSAND;Sm;0;ON;;;;;N;;;;; 214C;PER SIGN;So;0;ON;;;;;N;;;;; 214D;AKTIESELSKAB;So;0;ON;;;;;N;;;;; 214E;TURNED SMALL F;Ll;0;L;;;;;N;;;2132;;2132 214F;SYMBOL FOR SAMARITAN SOURCE;So;0;L;;;;;N;;;;; 2150;VULGAR FRACTION ONE SEVENTH;No;0;ON;<fraction> 0031 2044 0037;;;1/7;N;;;;; 2151;VULGAR FRACTION ONE NINTH;No;0;ON;<fraction> 0031 2044 0039;;;1/9;N;;;;; 2152;VULGAR FRACTION ONE TENTH;No;0;ON;<fraction> 0031 2044 0031 0030;;;1/10;N;;;;; 2153;VULGAR FRACTION ONE THIRD;No;0;ON;<fraction> 0031 2044 0033;;;1/3;N;FRACTION ONE THIRD;;;; 2154;VULGAR FRACTION TWO THIRDS;No;0;ON;<fraction> 0032 2044 0033;;;2/3;N;FRACTION TWO THIRDS;;;; 2155;VULGAR FRACTION ONE FIFTH;No;0;ON;<fraction> 0031 2044 0035;;;1/5;N;FRACTION ONE FIFTH;;;; 2156;VULGAR FRACTION TWO FIFTHS;No;0;ON;<fraction> 0032 2044 0035;;;2/5;N;FRACTION TWO FIFTHS;;;; 2157;VULGAR FRACTION THREE FIFTHS;No;0;ON;<fraction> 0033 2044 0035;;;3/5;N;FRACTION THREE FIFTHS;;;; 2158;VULGAR FRACTION FOUR FIFTHS;No;0;ON;<fraction> 0034 2044 0035;;;4/5;N;FRACTION FOUR FIFTHS;;;; 2159;VULGAR FRACTION ONE SIXTH;No;0;ON;<fraction> 0031 2044 0036;;;1/6;N;FRACTION ONE SIXTH;;;; 215A;VULGAR FRACTION FIVE SIXTHS;No;0;ON;<fraction> 0035 2044 0036;;;5/6;N;FRACTION FIVE SIXTHS;;;; 215B;VULGAR FRACTION ONE EIGHTH;No;0;ON;<fraction> 0031 2044 0038;;;1/8;N;FRACTION ONE EIGHTH;;;; 215C;VULGAR FRACTION THREE EIGHTHS;No;0;ON;<fraction> 0033 2044 0038;;;3/8;N;FRACTION THREE EIGHTHS;;;; 215D;VULGAR FRACTION FIVE EIGHTHS;No;0;ON;<fraction> 0035 2044 0038;;;5/8;N;FRACTION FIVE EIGHTHS;;;; 215E;VULGAR FRACTION SEVEN EIGHTHS;No;0;ON;<fraction> 0037 2044 0038;;;7/8;N;FRACTION SEVEN EIGHTHS;;;; 215F;FRACTION NUMERATOR ONE;No;0;ON;<fraction> 0031 2044;;;1;N;;;;; 2160;ROMAN NUMERAL ONE;Nl;0;L;<compat> 0049;;;1;N;;;;2170; 2161;ROMAN NUMERAL TWO;Nl;0;L;<compat> 0049 0049;;;2;N;;;;2171; 2162;ROMAN NUMERAL THREE;Nl;0;L;<compat> 0049 0049 0049;;;3;N;;;;2172; 2163;ROMAN NUMERAL FOUR;Nl;0;L;<compat> 0049 0056;;;4;N;;;;2173; 2164;ROMAN NUMERAL FIVE;Nl;0;L;<compat> 0056;;;5;N;;;;2174; 2165;ROMAN NUMERAL SIX;Nl;0;L;<compat> 0056 0049;;;6;N;;;;2175; 2166;ROMAN NUMERAL SEVEN;Nl;0;L;<compat> 0056 0049 0049;;;7;N;;;;2176; 2167;ROMAN NUMERAL EIGHT;Nl;0;L;<compat> 0056 0049 0049 0049;;;8;N;;;;2177; 2168;ROMAN NUMERAL NINE;Nl;0;L;<compat> 0049 0058;;;9;N;;;;2178; 2169;ROMAN NUMERAL TEN;Nl;0;L;<compat> 0058;;;10;N;;;;2179; 216A;ROMAN NUMERAL ELEVEN;Nl;0;L;<compat> 0058 0049;;;11;N;;;;217A; 216B;ROMAN NUMERAL TWELVE;Nl;0;L;<compat> 0058 0049 0049;;;12;N;;;;217B; 216C;ROMAN NUMERAL FIFTY;Nl;0;L;<compat> 004C;;;50;N;;;;217C; 216D;ROMAN NUMERAL ONE HUNDRED;Nl;0;L;<compat> 0043;;;100;N;;;;217D; 216E;ROMAN NUMERAL FIVE HUNDRED;Nl;0;L;<compat> 0044;;;500;N;;;;217E; 216F;ROMAN NUMERAL ONE THOUSAND;Nl;0;L;<compat> 004D;;;1000;N;;;;217F; 2170;SMALL ROMAN NUMERAL ONE;Nl;0;L;<compat> 0069;;;1;N;;;2160;;2160 2171;SMALL ROMAN NUMERAL TWO;Nl;0;L;<compat> 0069 0069;;;2;N;;;2161;;2161 2172;SMALL ROMAN NUMERAL THREE;Nl;0;L;<compat> 0069 0069 0069;;;3;N;;;2162;;2162 2173;SMALL ROMAN NUMERAL FOUR;Nl;0;L;<compat> 0069 0076;;;4;N;;;2163;;2163 2174;SMALL ROMAN NUMERAL FIVE;Nl;0;L;<compat> 0076;;;5;N;;;2164;;2164 2175;SMALL ROMAN NUMERAL SIX;Nl;0;L;<compat> 0076 0069;;;6;N;;;2165;;2165 2176;SMALL ROMAN NUMERAL SEVEN;Nl;0;L;<compat> 0076 0069 0069;;;7;N;;;2166;;2166 2177;SMALL ROMAN NUMERAL EIGHT;Nl;0;L;<compat> 0076 0069 0069 0069;;;8;N;;;2167;;2167 2178;SMALL ROMAN NUMERAL NINE;Nl;0;L;<compat> 0069 0078;;;9;N;;;2168;;2168 2179;SMALL ROMAN NUMERAL TEN;Nl;0;L;<compat> 0078;;;10;N;;;2169;;2169 217A;SMALL ROMAN NUMERAL ELEVEN;Nl;0;L;<compat> 0078 0069;;;11;N;;;216A;;216A 217B;SMALL ROMAN NUMERAL TWELVE;Nl;0;L;<compat> 0078 0069 0069;;;12;N;;;216B;;216B 217C;SMALL ROMAN NUMERAL FIFTY;Nl;0;L;<compat> 006C;;;50;N;;;216C;;216C 217D;SMALL ROMAN NUMERAL ONE HUNDRED;Nl;0;L;<compat> 0063;;;100;N;;;216D;;216D 217E;SMALL ROMAN NUMERAL FIVE HUNDRED;Nl;0;L;<compat> 0064;;;500;N;;;216E;;216E 217F;SMALL ROMAN NUMERAL ONE THOUSAND;Nl;0;L;<compat> 006D;;;1000;N;;;216F;;216F 2180;ROMAN NUMERAL ONE THOUSAND C D;Nl;0;L;;;;1000;N;;;;; 2181;ROMAN NUMERAL FIVE THOUSAND;Nl;0;L;;;;5000;N;;;;; 2182;ROMAN NUMERAL TEN THOUSAND;Nl;0;L;;;;10000;N;;;;; 2183;ROMAN NUMERAL REVERSED ONE HUNDRED;Lu;0;L;;;;;N;;;;2184; 2184;LATIN SMALL LETTER REVERSED C;Ll;0;L;;;;;N;;;2183;;2183 2185;ROMAN NUMERAL SIX LATE FORM;Nl;0;L;;;;6;N;;;;; 2186;ROMAN NUMERAL FIFTY EARLY FORM;Nl;0;L;;;;50;N;;;;; 2187;ROMAN NUMERAL FIFTY THOUSAND;Nl;0;L;;;;50000;N;;;;; 2188;ROMAN NUMERAL ONE HUNDRED THOUSAND;Nl;0;L;;;;100000;N;;;;; 2189;VULGAR FRACTION ZERO THIRDS;No;0;ON;<fraction> 0030 2044 0033;;;0;N;;;;; 218A;TURNED DIGIT TWO;So;0;ON;;;;;N;;;;; 218B;TURNED DIGIT THREE;So;0;ON;;;;;N;;;;; 2190;LEFTWARDS ARROW;Sm;0;ON;;;;;N;LEFT ARROW;;;; 2191;UPWARDS ARROW;Sm;0;ON;;;;;N;UP ARROW;;;; 2192;RIGHTWARDS ARROW;Sm;0;ON;;;;;N;RIGHT ARROW;;;; 2193;DOWNWARDS ARROW;Sm;0;ON;;;;;N;DOWN ARROW;;;; 2194;LEFT RIGHT ARROW;Sm;0;ON;;;;;N;;;;; 2195;UP DOWN ARROW;So;0;ON;;;;;N;;;;; 2196;NORTH WEST ARROW;So;0;ON;;;;;N;UPPER LEFT ARROW;;;; 2197;NORTH EAST ARROW;So;0;ON;;;;;N;UPPER RIGHT ARROW;;;; 2198;SOUTH EAST ARROW;So;0;ON;;;;;N;LOWER RIGHT ARROW;;;; 2199;SOUTH WEST ARROW;So;0;ON;;;;;N;LOWER LEFT ARROW;;;; 219A;LEFTWARDS ARROW WITH STROKE;Sm;0;ON;2190 0338;;;;N;LEFT ARROW WITH STROKE;;;; 219B;RIGHTWARDS ARROW WITH STROKE;Sm;0;ON;2192 0338;;;;N;RIGHT ARROW WITH STROKE;;;; 219C;LEFTWARDS WAVE ARROW;So;0;ON;;;;;N;LEFT WAVE ARROW;;;; 219D;RIGHTWARDS WAVE ARROW;So;0;ON;;;;;N;RIGHT WAVE ARROW;;;; 219E;LEFTWARDS TWO HEADED ARROW;So;0;ON;;;;;N;LEFT TWO HEADED ARROW;;;; 219F;UPWARDS TWO HEADED ARROW;So;0;ON;;;;;N;UP TWO HEADED ARROW;;;; 21A0;RIGHTWARDS TWO HEADED ARROW;Sm;0;ON;;;;;N;RIGHT TWO HEADED ARROW;;;; 21A1;DOWNWARDS TWO HEADED ARROW;So;0;ON;;;;;N;DOWN TWO HEADED ARROW;;;; 21A2;LEFTWARDS ARROW WITH TAIL;So;0;ON;;;;;N;LEFT ARROW WITH TAIL;;;; 21A3;RIGHTWARDS ARROW WITH TAIL;Sm;0;ON;;;;;N;RIGHT ARROW WITH TAIL;;;; 21A4;LEFTWARDS ARROW FROM BAR;So;0;ON;;;;;N;LEFT ARROW FROM BAR;;;; 21A5;UPWARDS ARROW FROM BAR;So;0;ON;;;;;N;UP ARROW FROM BAR;;;; 21A6;RIGHTWARDS ARROW FROM BAR;Sm;0;ON;;;;;N;RIGHT ARROW FROM BAR;;;; 21A7;DOWNWARDS ARROW FROM BAR;So;0;ON;;;;;N;DOWN ARROW FROM BAR;;;; 21A8;UP DOWN ARROW WITH BASE;So;0;ON;;;;;N;;;;; 21A9;LEFTWARDS ARROW WITH HOOK;So;0;ON;;;;;N;LEFT ARROW WITH HOOK;;;; 21AA;RIGHTWARDS ARROW WITH HOOK;So;0;ON;;;;;N;RIGHT ARROW WITH HOOK;;;; 21AB;LEFTWARDS ARROW WITH LOOP;So;0;ON;;;;;N;LEFT ARROW WITH LOOP;;;; 21AC;RIGHTWARDS ARROW WITH LOOP;So;0;ON;;;;;N;RIGHT ARROW WITH LOOP;;;; 21AD;LEFT RIGHT WAVE ARROW;So;0;ON;;;;;N;;;;; 21AE;LEFT RIGHT ARROW WITH STROKE;Sm;0;ON;2194 0338;;;;N;;;;; 21AF;DOWNWARDS ZIGZAG ARROW;So;0;ON;;;;;N;DOWN ZIGZAG ARROW;;;; 21B0;UPWARDS ARROW WITH TIP LEFTWARDS;So;0;ON;;;;;N;UP ARROW WITH TIP LEFT;;;; 21B1;UPWARDS ARROW WITH TIP RIGHTWARDS;So;0;ON;;;;;N;UP ARROW WITH TIP RIGHT;;;; 21B2;DOWNWARDS ARROW WITH TIP LEFTWARDS;So;0;ON;;;;;N;DOWN ARROW WITH TIP LEFT;;;; 21B3;DOWNWARDS ARROW WITH TIP RIGHTWARDS;So;0;ON;;;;;N;DOWN ARROW WITH TIP RIGHT;;;; 21B4;RIGHTWARDS ARROW WITH CORNER DOWNWARDS;So;0;ON;;;;;N;RIGHT ARROW WITH CORNER DOWN;;;; 21B5;DOWNWARDS ARROW WITH CORNER LEFTWARDS;So;0;ON;;;;;N;DOWN ARROW WITH CORNER LEFT;;;; 21B6;ANTICLOCKWISE TOP SEMICIRCLE ARROW;So;0;ON;;;;;N;;;;; 21B7;CLOCKWISE TOP SEMICIRCLE ARROW;So;0;ON;;;;;N;;;;; 21B8;NORTH WEST ARROW TO LONG BAR;So;0;ON;;;;;N;UPPER LEFT ARROW TO LONG BAR;;;; 21B9;LEFTWARDS ARROW TO BAR OVER RIGHTWARDS ARROW TO BAR;So;0;ON;;;;;N;LEFT ARROW TO BAR OVER RIGHT ARROW TO BAR;;;; 21BA;ANTICLOCKWISE OPEN CIRCLE ARROW;So;0;ON;;;;;N;;;;; 21BB;CLOCKWISE OPEN CIRCLE ARROW;So;0;ON;;;;;N;;;;; 21BC;LEFTWARDS HARPOON WITH BARB UPWARDS;So;0;ON;;;;;N;LEFT HARPOON WITH BARB UP;;;; 21BD;LEFTWARDS HARPOON WITH BARB DOWNWARDS;So;0;ON;;;;;N;LEFT HARPOON WITH BARB DOWN;;;; 21BE;UPWARDS HARPOON WITH BARB RIGHTWARDS;So;0;ON;;;;;N;UP HARPOON WITH BARB RIGHT;;;; 21BF;UPWARDS HARPOON WITH BARB LEFTWARDS;So;0;ON;;;;;N;UP HARPOON WITH BARB LEFT;;;; 21C0;RIGHTWARDS HARPOON WITH BARB UPWARDS;So;0;ON;;;;;N;RIGHT HARPOON WITH BARB UP;;;; 21C1;RIGHTWARDS HARPOON WITH BARB DOWNWARDS;So;0;ON;;;;;N;RIGHT HARPOON WITH BARB DOWN;;;; 21C2;DOWNWARDS HARPOON WITH BARB RIGHTWARDS;So;0;ON;;;;;N;DOWN HARPOON WITH BARB RIGHT;;;; 21C3;DOWNWARDS HARPOON WITH BARB LEFTWARDS;So;0;ON;;;;;N;DOWN HARPOON WITH BARB LEFT;;;; 21C4;RIGHTWARDS ARROW OVER LEFTWARDS ARROW;So;0;ON;;;;;N;RIGHT ARROW OVER LEFT ARROW;;;; 21C5;UPWARDS ARROW LEFTWARDS OF DOWNWARDS ARROW;So;0;ON;;;;;N;UP ARROW LEFT OF DOWN ARROW;;;; 21C6;LEFTWARDS ARROW OVER RIGHTWARDS ARROW;So;0;ON;;;;;N;LEFT ARROW OVER RIGHT ARROW;;;; 21C7;LEFTWARDS PAIRED ARROWS;So;0;ON;;;;;N;LEFT PAIRED ARROWS;;;; 21C8;UPWARDS PAIRED ARROWS;So;0;ON;;;;;N;UP PAIRED ARROWS;;;; 21C9;RIGHTWARDS PAIRED ARROWS;So;0;ON;;;;;N;RIGHT PAIRED ARROWS;;;; 21CA;DOWNWARDS PAIRED ARROWS;So;0;ON;;;;;N;DOWN PAIRED ARROWS;;;; 21CB;LEFTWARDS HARPOON OVER RIGHTWARDS HARPOON;So;0;ON;;;;;N;LEFT HARPOON OVER RIGHT HARPOON;;;; 21CC;RIGHTWARDS HARPOON OVER LEFTWARDS HARPOON;So;0;ON;;;;;N;RIGHT HARPOON OVER LEFT HARPOON;;;; 21CD;LEFTWARDS DOUBLE ARROW WITH STROKE;So;0;ON;21D0 0338;;;;N;LEFT DOUBLE ARROW WITH STROKE;;;; 21CE;LEFT RIGHT DOUBLE ARROW WITH STROKE;Sm;0;ON;21D4 0338;;;;N;;;;; 21CF;RIGHTWARDS DOUBLE ARROW WITH STROKE;Sm;0;ON;21D2 0338;;;;N;RIGHT DOUBLE ARROW WITH STROKE;;;; 21D0;LEFTWARDS DOUBLE ARROW;So;0;ON;;;;;N;LEFT DOUBLE ARROW;;;; 21D1;UPWARDS DOUBLE ARROW;So;0;ON;;;;;N;UP DOUBLE ARROW;;;; 21D2;RIGHTWARDS DOUBLE ARROW;Sm;0;ON;;;;;N;RIGHT DOUBLE ARROW;;;; 21D3;DOWNWARDS DOUBLE ARROW;So;0;ON;;;;;N;DOWN DOUBLE ARROW;;;; 21D4;LEFT RIGHT DOUBLE ARROW;Sm;0;ON;;;;;N;;;;; 21D5;UP DOWN DOUBLE ARROW;So;0;ON;;;;;N;;;;; 21D6;NORTH WEST DOUBLE ARROW;So;0;ON;;;;;N;UPPER LEFT DOUBLE ARROW;;;; 21D7;NORTH EAST DOUBLE ARROW;So;0;ON;;;;;N;UPPER RIGHT DOUBLE ARROW;;;; 21D8;SOUTH EAST DOUBLE ARROW;So;0;ON;;;;;N;LOWER RIGHT DOUBLE ARROW;;;; 21D9;SOUTH WEST DOUBLE ARROW;So;0;ON;;;;;N;LOWER LEFT DOUBLE ARROW;;;; 21DA;LEFTWARDS TRIPLE ARROW;So;0;ON;;;;;N;LEFT TRIPLE ARROW;;;; 21DB;RIGHTWARDS TRIPLE ARROW;So;0;ON;;;;;N;RIGHT TRIPLE ARROW;;;; 21DC;LEFTWARDS SQUIGGLE ARROW;So;0;ON;;;;;N;LEFT SQUIGGLE ARROW;;;; 21DD;RIGHTWARDS SQUIGGLE ARROW;So;0;ON;;;;;N;RIGHT SQUIGGLE ARROW;;;; 21DE;UPWARDS ARROW WITH DOUBLE STROKE;So;0;ON;;;;;N;UP ARROW WITH DOUBLE STROKE;;;; 21DF;DOWNWARDS ARROW WITH DOUBLE STROKE;So;0;ON;;;;;N;DOWN ARROW WITH DOUBLE STROKE;;;; 21E0;LEFTWARDS DASHED ARROW;So;0;ON;;;;;N;LEFT DASHED ARROW;;;; 21E1;UPWARDS DASHED ARROW;So;0;ON;;;;;N;UP DASHED ARROW;;;; 21E2;RIGHTWARDS DASHED ARROW;So;0;ON;;;;;N;RIGHT DASHED ARROW;;;; 21E3;DOWNWARDS DASHED ARROW;So;0;ON;;;;;N;DOWN DASHED ARROW;;;; 21E4;LEFTWARDS ARROW TO BAR;So;0;ON;;;;;N;LEFT ARROW TO BAR;;;; 21E5;RIGHTWARDS ARROW TO BAR;So;0;ON;;;;;N;RIGHT ARROW TO BAR;;;; 21E6;LEFTWARDS WHITE ARROW;So;0;ON;;;;;N;WHITE LEFT ARROW;;;; 21E7;UPWARDS WHITE ARROW;So;0;ON;;;;;N;WHITE UP ARROW;;;; 21E8;RIGHTWARDS WHITE ARROW;So;0;ON;;;;;N;WHITE RIGHT ARROW;;;; 21E9;DOWNWARDS WHITE ARROW;So;0;ON;;;;;N;WHITE DOWN ARROW;;;; 21EA;UPWARDS WHITE ARROW FROM BAR;So;0;ON;;;;;N;WHITE UP ARROW FROM BAR;;;; 21EB;UPWARDS WHITE ARROW ON PEDESTAL;So;0;ON;;;;;N;;;;; 21EC;UPWARDS WHITE ARROW ON PEDESTAL WITH HORIZONTAL BAR;So;0;ON;;;;;N;;;;; 21ED;UPWARDS WHITE ARROW ON PEDESTAL WITH VERTICAL BAR;So;0;ON;;;;;N;;;;; 21EE;UPWARDS WHITE DOUBLE ARROW;So;0;ON;;;;;N;;;;; 21EF;UPWARDS WHITE DOUBLE ARROW ON PEDESTAL;So;0;ON;;;;;N;;;;; 21F0;RIGHTWARDS WHITE ARROW FROM WALL;So;0;ON;;;;;N;;;;; 21F1;NORTH WEST ARROW TO CORNER;So;0;ON;;;;;N;;;;; 21F2;SOUTH EAST ARROW TO CORNER;So;0;ON;;;;;N;;;;; 21F3;UP DOWN WHITE ARROW;So;0;ON;;;;;N;;;;; 21F4;RIGHT ARROW WITH SMALL CIRCLE;Sm;0;ON;;;;;N;;;;; 21F5;DOWNWARDS ARROW LEFTWARDS OF UPWARDS ARROW;Sm;0;ON;;;;;N;;;;; 21F6;THREE RIGHTWARDS ARROWS;Sm;0;ON;;;;;N;;;;; 21F7;LEFTWARDS ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 21F8;RIGHTWARDS ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 21F9;LEFT RIGHT ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 21FA;LEFTWARDS ARROW WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 21FB;RIGHTWARDS ARROW WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 21FC;LEFT RIGHT ARROW WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 21FD;LEFTWARDS OPEN-HEADED ARROW;Sm;0;ON;;;;;N;;;;; 21FE;RIGHTWARDS OPEN-HEADED ARROW;Sm;0;ON;;;;;N;;;;; 21FF;LEFT RIGHT OPEN-HEADED ARROW;Sm;0;ON;;;;;N;;;;; 2200;FOR ALL;Sm;0;ON;;;;;N;;;;; 2201;COMPLEMENT;Sm;0;ON;;;;;Y;;;;; 2202;PARTIAL DIFFERENTIAL;Sm;0;ON;;;;;Y;;;;; 2203;THERE EXISTS;Sm;0;ON;;;;;Y;;;;; 2204;THERE DOES NOT EXIST;Sm;0;ON;2203 0338;;;;Y;;;;; 2205;EMPTY SET;Sm;0;ON;;;;;N;;;;; 2206;INCREMENT;Sm;0;ON;;;;;N;;;;; 2207;NABLA;Sm;0;ON;;;;;N;;;;; 2208;ELEMENT OF;Sm;0;ON;;;;;Y;;;;; 2209;NOT AN ELEMENT OF;Sm;0;ON;2208 0338;;;;Y;;;;; 220A;SMALL ELEMENT OF;Sm;0;ON;;;;;Y;;;;; 220B;CONTAINS AS MEMBER;Sm;0;ON;;;;;Y;;;;; 220C;DOES NOT CONTAIN AS MEMBER;Sm;0;ON;220B 0338;;;;Y;;;;; 220D;SMALL CONTAINS AS MEMBER;Sm;0;ON;;;;;Y;;;;; 220E;END OF PROOF;Sm;0;ON;;;;;N;;;;; 220F;N-ARY PRODUCT;Sm;0;ON;;;;;N;;;;; 2210;N-ARY COPRODUCT;Sm;0;ON;;;;;N;;;;; 2211;N-ARY SUMMATION;Sm;0;ON;;;;;Y;;;;; 2212;MINUS SIGN;Sm;0;ES;;;;;N;;;;; 2213;MINUS-OR-PLUS SIGN;Sm;0;ET;;;;;N;;;;; 2214;DOT PLUS;Sm;0;ON;;;;;N;;;;; 2215;DIVISION SLASH;Sm;0;ON;;;;;Y;;;;; 2216;SET MINUS;Sm;0;ON;;;;;Y;;;;; 2217;ASTERISK OPERATOR;Sm;0;ON;;;;;N;;;;; 2218;RING OPERATOR;Sm;0;ON;;;;;N;;;;; 2219;BULLET OPERATOR;Sm;0;ON;;;;;N;;;;; 221A;SQUARE ROOT;Sm;0;ON;;;;;Y;;;;; 221B;CUBE ROOT;Sm;0;ON;;;;;Y;;;;; 221C;FOURTH ROOT;Sm;0;ON;;;;;Y;;;;; 221D;PROPORTIONAL TO;Sm;0;ON;;;;;Y;;;;; 221E;INFINITY;Sm;0;ON;;;;;N;;;;; 221F;RIGHT ANGLE;Sm;0;ON;;;;;Y;;;;; 2220;ANGLE;Sm;0;ON;;;;;Y;;;;; 2221;MEASURED ANGLE;Sm;0;ON;;;;;Y;;;;; 2222;SPHERICAL ANGLE;Sm;0;ON;;;;;Y;;;;; 2223;DIVIDES;Sm;0;ON;;;;;N;;;;; 2224;DOES NOT DIVIDE;Sm;0;ON;2223 0338;;;;Y;;;;; 2225;PARALLEL TO;Sm;0;ON;;;;;N;;;;; 2226;NOT PARALLEL TO;Sm;0;ON;2225 0338;;;;Y;;;;; 2227;LOGICAL AND;Sm;0;ON;;;;;N;;;;; 2228;LOGICAL OR;Sm;0;ON;;;;;N;;;;; 2229;INTERSECTION;Sm;0;ON;;;;;N;;;;; 222A;UNION;Sm;0;ON;;;;;N;;;;; 222B;INTEGRAL;Sm;0;ON;;;;;Y;;;;; 222C;DOUBLE INTEGRAL;Sm;0;ON;<compat> 222B 222B;;;;Y;;;;; 222D;TRIPLE INTEGRAL;Sm;0;ON;<compat> 222B 222B 222B;;;;Y;;;;; 222E;CONTOUR INTEGRAL;Sm;0;ON;;;;;Y;;;;; 222F;SURFACE INTEGRAL;Sm;0;ON;<compat> 222E 222E;;;;Y;;;;; 2230;VOLUME INTEGRAL;Sm;0;ON;<compat> 222E 222E 222E;;;;Y;;;;; 2231;CLOCKWISE INTEGRAL;Sm;0;ON;;;;;Y;;;;; 2232;CLOCKWISE CONTOUR INTEGRAL;Sm;0;ON;;;;;Y;;;;; 2233;ANTICLOCKWISE CONTOUR INTEGRAL;Sm;0;ON;;;;;Y;;;;; 2234;THEREFORE;Sm;0;ON;;;;;N;;;;; 2235;BECAUSE;Sm;0;ON;;;;;N;;;;; 2236;RATIO;Sm;0;ON;;;;;N;;;;; 2237;PROPORTION;Sm;0;ON;;;;;N;;;;; 2238;DOT MINUS;Sm;0;ON;;;;;N;;;;; 2239;EXCESS;Sm;0;ON;;;;;Y;;;;; 223A;GEOMETRIC PROPORTION;Sm;0;ON;;;;;N;;;;; 223B;HOMOTHETIC;Sm;0;ON;;;;;Y;;;;; 223C;TILDE OPERATOR;Sm;0;ON;;;;;Y;;;;; 223D;REVERSED TILDE;Sm;0;ON;;;;;Y;;;;; 223E;INVERTED LAZY S;Sm;0;ON;;;;;Y;;;;; 223F;SINE WAVE;Sm;0;ON;;;;;Y;;;;; 2240;WREATH PRODUCT;Sm;0;ON;;;;;Y;;;;; 2241;NOT TILDE;Sm;0;ON;223C 0338;;;;Y;;;;; 2242;MINUS TILDE;Sm;0;ON;;;;;Y;;;;; 2243;ASYMPTOTICALLY EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2244;NOT ASYMPTOTICALLY EQUAL TO;Sm;0;ON;2243 0338;;;;Y;;;;; 2245;APPROXIMATELY EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2246;APPROXIMATELY BUT NOT ACTUALLY EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2247;NEITHER APPROXIMATELY NOR ACTUALLY EQUAL TO;Sm;0;ON;2245 0338;;;;Y;;;;; 2248;ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2249;NOT ALMOST EQUAL TO;Sm;0;ON;2248 0338;;;;Y;;;;; 224A;ALMOST EQUAL OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 224B;TRIPLE TILDE;Sm;0;ON;;;;;Y;;;;; 224C;ALL EQUAL TO;Sm;0;ON;;;;;Y;;;;; 224D;EQUIVALENT TO;Sm;0;ON;;;;;N;;;;; 224E;GEOMETRICALLY EQUIVALENT TO;Sm;0;ON;;;;;N;;;;; 224F;DIFFERENCE BETWEEN;Sm;0;ON;;;;;N;;;;; 2250;APPROACHES THE LIMIT;Sm;0;ON;;;;;N;;;;; 2251;GEOMETRICALLY EQUAL TO;Sm;0;ON;;;;;N;;;;; 2252;APPROXIMATELY EQUAL TO OR THE IMAGE OF;Sm;0;ON;;;;;Y;;;;; 2253;IMAGE OF OR APPROXIMATELY EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2254;COLON EQUALS;Sm;0;ON;;;;;Y;COLON EQUAL;;;; 2255;EQUALS COLON;Sm;0;ON;;;;;Y;EQUAL COLON;;;; 2256;RING IN EQUAL TO;Sm;0;ON;;;;;N;;;;; 2257;RING EQUAL TO;Sm;0;ON;;;;;N;;;;; 2258;CORRESPONDS TO;Sm;0;ON;;;;;N;;;;; 2259;ESTIMATES;Sm;0;ON;;;;;N;;;;; 225A;EQUIANGULAR TO;Sm;0;ON;;;;;N;;;;; 225B;STAR EQUALS;Sm;0;ON;;;;;N;;;;; 225C;DELTA EQUAL TO;Sm;0;ON;;;;;N;;;;; 225D;EQUAL TO BY DEFINITION;Sm;0;ON;;;;;N;;;;; 225E;MEASURED BY;Sm;0;ON;;;;;N;;;;; 225F;QUESTIONED EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2260;NOT EQUAL TO;Sm;0;ON;003D 0338;;;;Y;;;;; 2261;IDENTICAL TO;Sm;0;ON;;;;;N;;;;; 2262;NOT IDENTICAL TO;Sm;0;ON;2261 0338;;;;Y;;;;; 2263;STRICTLY EQUIVALENT TO;Sm;0;ON;;;;;N;;;;; 2264;LESS-THAN OR EQUAL TO;Sm;0;ON;;;;;Y;LESS THAN OR EQUAL TO;;;; 2265;GREATER-THAN OR EQUAL TO;Sm;0;ON;;;;;Y;GREATER THAN OR EQUAL TO;;;; 2266;LESS-THAN OVER EQUAL TO;Sm;0;ON;;;;;Y;LESS THAN OVER EQUAL TO;;;; 2267;GREATER-THAN OVER EQUAL TO;Sm;0;ON;;;;;Y;GREATER THAN OVER EQUAL TO;;;; 2268;LESS-THAN BUT NOT EQUAL TO;Sm;0;ON;;;;;Y;LESS THAN BUT NOT EQUAL TO;;;; 2269;GREATER-THAN BUT NOT EQUAL TO;Sm;0;ON;;;;;Y;GREATER THAN BUT NOT EQUAL TO;;;; 226A;MUCH LESS-THAN;Sm;0;ON;;;;;Y;MUCH LESS THAN;;;; 226B;MUCH GREATER-THAN;Sm;0;ON;;;;;Y;MUCH GREATER THAN;;;; 226C;BETWEEN;Sm;0;ON;;;;;N;;;;; 226D;NOT EQUIVALENT TO;Sm;0;ON;224D 0338;;;;N;;;;; 226E;NOT LESS-THAN;Sm;0;ON;003C 0338;;;;Y;NOT LESS THAN;;;; 226F;NOT GREATER-THAN;Sm;0;ON;003E 0338;;;;Y;NOT GREATER THAN;;;; 2270;NEITHER LESS-THAN NOR EQUAL TO;Sm;0;ON;2264 0338;;;;Y;NEITHER LESS THAN NOR EQUAL TO;;;; 2271;NEITHER GREATER-THAN NOR EQUAL TO;Sm;0;ON;2265 0338;;;;Y;NEITHER GREATER THAN NOR EQUAL TO;;;; 2272;LESS-THAN OR EQUIVALENT TO;Sm;0;ON;;;;;Y;LESS THAN OR EQUIVALENT TO;;;; 2273;GREATER-THAN OR EQUIVALENT TO;Sm;0;ON;;;;;Y;GREATER THAN OR EQUIVALENT TO;;;; 2274;NEITHER LESS-THAN NOR EQUIVALENT TO;Sm;0;ON;2272 0338;;;;Y;NEITHER LESS THAN NOR EQUIVALENT TO;;;; 2275;NEITHER GREATER-THAN NOR EQUIVALENT TO;Sm;0;ON;2273 0338;;;;Y;NEITHER GREATER THAN NOR EQUIVALENT TO;;;; 2276;LESS-THAN OR GREATER-THAN;Sm;0;ON;;;;;Y;LESS THAN OR GREATER THAN;;;; 2277;GREATER-THAN OR LESS-THAN;Sm;0;ON;;;;;Y;GREATER THAN OR LESS THAN;;;; 2278;NEITHER LESS-THAN NOR GREATER-THAN;Sm;0;ON;2276 0338;;;;Y;NEITHER LESS THAN NOR GREATER THAN;;;; 2279;NEITHER GREATER-THAN NOR LESS-THAN;Sm;0;ON;2277 0338;;;;Y;NEITHER GREATER THAN NOR LESS THAN;;;; 227A;PRECEDES;Sm;0;ON;;;;;Y;;;;; 227B;SUCCEEDS;Sm;0;ON;;;;;Y;;;;; 227C;PRECEDES OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 227D;SUCCEEDS OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 227E;PRECEDES OR EQUIVALENT TO;Sm;0;ON;;;;;Y;;;;; 227F;SUCCEEDS OR EQUIVALENT TO;Sm;0;ON;;;;;Y;;;;; 2280;DOES NOT PRECEDE;Sm;0;ON;227A 0338;;;;Y;;;;; 2281;DOES NOT SUCCEED;Sm;0;ON;227B 0338;;;;Y;;;;; 2282;SUBSET OF;Sm;0;ON;;;;;Y;;;;; 2283;SUPERSET OF;Sm;0;ON;;;;;Y;;;;; 2284;NOT A SUBSET OF;Sm;0;ON;2282 0338;;;;Y;;;;; 2285;NOT A SUPERSET OF;Sm;0;ON;2283 0338;;;;Y;;;;; 2286;SUBSET OF OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2287;SUPERSET OF OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2288;NEITHER A SUBSET OF NOR EQUAL TO;Sm;0;ON;2286 0338;;;;Y;;;;; 2289;NEITHER A SUPERSET OF NOR EQUAL TO;Sm;0;ON;2287 0338;;;;Y;;;;; 228A;SUBSET OF WITH NOT EQUAL TO;Sm;0;ON;;;;;Y;SUBSET OF OR NOT EQUAL TO;;;; 228B;SUPERSET OF WITH NOT EQUAL TO;Sm;0;ON;;;;;Y;SUPERSET OF OR NOT EQUAL TO;;;; 228C;MULTISET;Sm;0;ON;;;;;Y;;;;; 228D;MULTISET MULTIPLICATION;Sm;0;ON;;;;;N;;;;; 228E;MULTISET UNION;Sm;0;ON;;;;;N;;;;; 228F;SQUARE IMAGE OF;Sm;0;ON;;;;;Y;;;;; 2290;SQUARE ORIGINAL OF;Sm;0;ON;;;;;Y;;;;; 2291;SQUARE IMAGE OF OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2292;SQUARE ORIGINAL OF OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2293;SQUARE CAP;Sm;0;ON;;;;;N;;;;; 2294;SQUARE CUP;Sm;0;ON;;;;;N;;;;; 2295;CIRCLED PLUS;Sm;0;ON;;;;;N;;;;; 2296;CIRCLED MINUS;Sm;0;ON;;;;;N;;;;; 2297;CIRCLED TIMES;Sm;0;ON;;;;;N;;;;; 2298;CIRCLED DIVISION SLASH;Sm;0;ON;;;;;Y;;;;; 2299;CIRCLED DOT OPERATOR;Sm;0;ON;;;;;N;;;;; 229A;CIRCLED RING OPERATOR;Sm;0;ON;;;;;N;;;;; 229B;CIRCLED ASTERISK OPERATOR;Sm;0;ON;;;;;N;;;;; 229C;CIRCLED EQUALS;Sm;0;ON;;;;;N;;;;; 229D;CIRCLED DASH;Sm;0;ON;;;;;N;;;;; 229E;SQUARED PLUS;Sm;0;ON;;;;;N;;;;; 229F;SQUARED MINUS;Sm;0;ON;;;;;N;;;;; 22A0;SQUARED TIMES;Sm;0;ON;;;;;N;;;;; 22A1;SQUARED DOT OPERATOR;Sm;0;ON;;;;;N;;;;; 22A2;RIGHT TACK;Sm;0;ON;;;;;Y;;;;; 22A3;LEFT TACK;Sm;0;ON;;;;;Y;;;;; 22A4;DOWN TACK;Sm;0;ON;;;;;N;;;;; 22A5;UP TACK;Sm;0;ON;;;;;N;;;;; 22A6;ASSERTION;Sm;0;ON;;;;;Y;;;;; 22A7;MODELS;Sm;0;ON;;;;;Y;;;;; 22A8;TRUE;Sm;0;ON;;;;;Y;;;;; 22A9;FORCES;Sm;0;ON;;;;;Y;;;;; 22AA;TRIPLE VERTICAL BAR RIGHT TURNSTILE;Sm;0;ON;;;;;Y;;;;; 22AB;DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE;Sm;0;ON;;;;;Y;;;;; 22AC;DOES NOT PROVE;Sm;0;ON;22A2 0338;;;;Y;;;;; 22AD;NOT TRUE;Sm;0;ON;22A8 0338;;;;Y;;;;; 22AE;DOES NOT FORCE;Sm;0;ON;22A9 0338;;;;Y;;;;; 22AF;NEGATED DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE;Sm;0;ON;22AB 0338;;;;Y;;;;; 22B0;PRECEDES UNDER RELATION;Sm;0;ON;;;;;Y;;;;; 22B1;SUCCEEDS UNDER RELATION;Sm;0;ON;;;;;Y;;;;; 22B2;NORMAL SUBGROUP OF;Sm;0;ON;;;;;Y;;;;; 22B3;CONTAINS AS NORMAL SUBGROUP;Sm;0;ON;;;;;Y;;;;; 22B4;NORMAL SUBGROUP OF OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 22B5;CONTAINS AS NORMAL SUBGROUP OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 22B6;ORIGINAL OF;Sm;0;ON;;;;;Y;;;;; 22B7;IMAGE OF;Sm;0;ON;;;;;Y;;;;; 22B8;MULTIMAP;Sm;0;ON;;;;;Y;;;;; 22B9;HERMITIAN CONJUGATE MATRIX;Sm;0;ON;;;;;N;;;;; 22BA;INTERCALATE;Sm;0;ON;;;;;N;;;;; 22BB;XOR;Sm;0;ON;;;;;N;;;;; 22BC;NAND;Sm;0;ON;;;;;N;;;;; 22BD;NOR;Sm;0;ON;;;;;N;;;;; 22BE;RIGHT ANGLE WITH ARC;Sm;0;ON;;;;;Y;;;;; 22BF;RIGHT TRIANGLE;Sm;0;ON;;;;;Y;;;;; 22C0;N-ARY LOGICAL AND;Sm;0;ON;;;;;N;;;;; 22C1;N-ARY LOGICAL OR;Sm;0;ON;;;;;N;;;;; 22C2;N-ARY INTERSECTION;Sm;0;ON;;;;;N;;;;; 22C3;N-ARY UNION;Sm;0;ON;;;;;N;;;;; 22C4;DIAMOND OPERATOR;Sm;0;ON;;;;;N;;;;; 22C5;DOT OPERATOR;Sm;0;ON;;;;;N;;;;; 22C6;STAR OPERATOR;Sm;0;ON;;;;;N;;;;; 22C7;DIVISION TIMES;Sm;0;ON;;;;;N;;;;; 22C8;BOWTIE;Sm;0;ON;;;;;N;;;;; 22C9;LEFT NORMAL FACTOR SEMIDIRECT PRODUCT;Sm;0;ON;;;;;Y;;;;; 22CA;RIGHT NORMAL FACTOR SEMIDIRECT PRODUCT;Sm;0;ON;;;;;Y;;;;; 22CB;LEFT SEMIDIRECT PRODUCT;Sm;0;ON;;;;;Y;;;;; 22CC;RIGHT SEMIDIRECT PRODUCT;Sm;0;ON;;;;;Y;;;;; 22CD;REVERSED TILDE EQUALS;Sm;0;ON;;;;;Y;;;;; 22CE;CURLY LOGICAL OR;Sm;0;ON;;;;;N;;;;; 22CF;CURLY LOGICAL AND;Sm;0;ON;;;;;N;;;;; 22D0;DOUBLE SUBSET;Sm;0;ON;;;;;Y;;;;; 22D1;DOUBLE SUPERSET;Sm;0;ON;;;;;Y;;;;; 22D2;DOUBLE INTERSECTION;Sm;0;ON;;;;;N;;;;; 22D3;DOUBLE UNION;Sm;0;ON;;;;;N;;;;; 22D4;PITCHFORK;Sm;0;ON;;;;;N;;;;; 22D5;EQUAL AND PARALLEL TO;Sm;0;ON;;;;;N;;;;; 22D6;LESS-THAN WITH DOT;Sm;0;ON;;;;;Y;LESS THAN WITH DOT;;;; 22D7;GREATER-THAN WITH DOT;Sm;0;ON;;;;;Y;GREATER THAN WITH DOT;;;; 22D8;VERY MUCH LESS-THAN;Sm;0;ON;;;;;Y;VERY MUCH LESS THAN;;;; 22D9;VERY MUCH GREATER-THAN;Sm;0;ON;;;;;Y;VERY MUCH GREATER THAN;;;; 22DA;LESS-THAN EQUAL TO OR GREATER-THAN;Sm;0;ON;;;;;Y;LESS THAN EQUAL TO OR GREATER THAN;;;; 22DB;GREATER-THAN EQUAL TO OR LESS-THAN;Sm;0;ON;;;;;Y;GREATER THAN EQUAL TO OR LESS THAN;;;; 22DC;EQUAL TO OR LESS-THAN;Sm;0;ON;;;;;Y;EQUAL TO OR LESS THAN;;;; 22DD;EQUAL TO OR GREATER-THAN;Sm;0;ON;;;;;Y;EQUAL TO OR GREATER THAN;;;; 22DE;EQUAL TO OR PRECEDES;Sm;0;ON;;;;;Y;;;;; 22DF;EQUAL TO OR SUCCEEDS;Sm;0;ON;;;;;Y;;;;; 22E0;DOES NOT PRECEDE OR EQUAL;Sm;0;ON;227C 0338;;;;Y;;;;; 22E1;DOES NOT SUCCEED OR EQUAL;Sm;0;ON;227D 0338;;;;Y;;;;; 22E2;NOT SQUARE IMAGE OF OR EQUAL TO;Sm;0;ON;2291 0338;;;;Y;;;;; 22E3;NOT SQUARE ORIGINAL OF OR EQUAL TO;Sm;0;ON;2292 0338;;;;Y;;;;; 22E4;SQUARE IMAGE OF OR NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; 22E5;SQUARE ORIGINAL OF OR NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; 22E6;LESS-THAN BUT NOT EQUIVALENT TO;Sm;0;ON;;;;;Y;LESS THAN BUT NOT EQUIVALENT TO;;;; 22E7;GREATER-THAN BUT NOT EQUIVALENT TO;Sm;0;ON;;;;;Y;GREATER THAN BUT NOT EQUIVALENT TO;;;; 22E8;PRECEDES BUT NOT EQUIVALENT TO;Sm;0;ON;;;;;Y;;;;; 22E9;SUCCEEDS BUT NOT EQUIVALENT TO;Sm;0;ON;;;;;Y;;;;; 22EA;NOT NORMAL SUBGROUP OF;Sm;0;ON;22B2 0338;;;;Y;;;;; 22EB;DOES NOT CONTAIN AS NORMAL SUBGROUP;Sm;0;ON;22B3 0338;;;;Y;;;;; 22EC;NOT NORMAL SUBGROUP OF OR EQUAL TO;Sm;0;ON;22B4 0338;;;;Y;;;;; 22ED;DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL;Sm;0;ON;22B5 0338;;;;Y;;;;; 22EE;VERTICAL ELLIPSIS;Sm;0;ON;;;;;N;;;;; 22EF;MIDLINE HORIZONTAL ELLIPSIS;Sm;0;ON;;;;;N;;;;; 22F0;UP RIGHT DIAGONAL ELLIPSIS;Sm;0;ON;;;;;Y;;;;; 22F1;DOWN RIGHT DIAGONAL ELLIPSIS;Sm;0;ON;;;;;Y;;;;; 22F2;ELEMENT OF WITH LONG HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;; 22F3;ELEMENT OF WITH VERTICAL BAR AT END OF HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;; 22F4;SMALL ELEMENT OF WITH VERTICAL BAR AT END OF HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;; 22F5;ELEMENT OF WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;; 22F6;ELEMENT OF WITH OVERBAR;Sm;0;ON;;;;;Y;;;;; 22F7;SMALL ELEMENT OF WITH OVERBAR;Sm;0;ON;;;;;Y;;;;; 22F8;ELEMENT OF WITH UNDERBAR;Sm;0;ON;;;;;Y;;;;; 22F9;ELEMENT OF WITH TWO HORIZONTAL STROKES;Sm;0;ON;;;;;Y;;;;; 22FA;CONTAINS WITH LONG HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;; 22FB;CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;; 22FC;SMALL CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;; 22FD;CONTAINS WITH OVERBAR;Sm;0;ON;;;;;Y;;;;; 22FE;SMALL CONTAINS WITH OVERBAR;Sm;0;ON;;;;;Y;;;;; 22FF;Z NOTATION BAG MEMBERSHIP;Sm;0;ON;;;;;Y;;;;; 2300;DIAMETER SIGN;So;0;ON;;;;;N;;;;; 2301;ELECTRIC ARROW;So;0;ON;;;;;N;;;;; 2302;HOUSE;So;0;ON;;;;;N;;;;; 2303;UP ARROWHEAD;So;0;ON;;;;;N;;;;; 2304;DOWN ARROWHEAD;So;0;ON;;;;;N;;;;; 2305;PROJECTIVE;So;0;ON;;;;;N;;;;; 2306;PERSPECTIVE;So;0;ON;;;;;N;;;;; 2307;WAVY LINE;So;0;ON;;;;;N;;;;; 2308;LEFT CEILING;Ps;0;ON;;;;;Y;;;;; 2309;RIGHT CEILING;Pe;0;ON;;;;;Y;;;;; 230A;LEFT FLOOR;Ps;0;ON;;;;;Y;;;;; 230B;RIGHT FLOOR;Pe;0;ON;;;;;Y;;;;; 230C;BOTTOM RIGHT CROP;So;0;ON;;;;;N;;;;; 230D;BOTTOM LEFT CROP;So;0;ON;;;;;N;;;;; 230E;TOP RIGHT CROP;So;0;ON;;;;;N;;;;; 230F;TOP LEFT CROP;So;0;ON;;;;;N;;;;; 2310;REVERSED NOT SIGN;So;0;ON;;;;;N;;;;; 2311;SQUARE LOZENGE;So;0;ON;;;;;N;;;;; 2312;ARC;So;0;ON;;;;;N;;;;; 2313;SEGMENT;So;0;ON;;;;;N;;;;; 2314;SECTOR;So;0;ON;;;;;N;;;;; 2315;TELEPHONE RECORDER;So;0;ON;;;;;N;;;;; 2316;POSITION INDICATOR;So;0;ON;;;;;N;;;;; 2317;VIEWDATA SQUARE;So;0;ON;;;;;N;;;;; 2318;PLACE OF INTEREST SIGN;So;0;ON;;;;;N;COMMAND KEY;;;; 2319;TURNED NOT SIGN;So;0;ON;;;;;N;;;;; 231A;WATCH;So;0;ON;;;;;N;;;;; 231B;HOURGLASS;So;0;ON;;;;;N;;;;; 231C;TOP LEFT CORNER;So;0;ON;;;;;N;;;;; 231D;TOP RIGHT CORNER;So;0;ON;;;;;N;;;;; 231E;BOTTOM LEFT CORNER;So;0;ON;;;;;N;;;;; 231F;BOTTOM RIGHT CORNER;So;0;ON;;;;;N;;;;; 2320;TOP HALF INTEGRAL;Sm;0;ON;;;;;Y;;;;; 2321;BOTTOM HALF INTEGRAL;Sm;0;ON;;;;;Y;;;;; 2322;FROWN;So;0;ON;;;;;N;;;;; 2323;SMILE;So;0;ON;;;;;N;;;;; 2324;UP ARROWHEAD BETWEEN TWO HORIZONTAL BARS;So;0;ON;;;;;N;ENTER KEY;;;; 2325;OPTION KEY;So;0;ON;;;;;N;;;;; 2326;ERASE TO THE RIGHT;So;0;ON;;;;;N;DELETE TO THE RIGHT KEY;;;; 2327;X IN A RECTANGLE BOX;So;0;ON;;;;;N;CLEAR KEY;;;; 2328;KEYBOARD;So;0;ON;;;;;N;;;;; 2329;LEFT-POINTING ANGLE BRACKET;Ps;0;ON;3008;;;;Y;BRA;;;; 232A;RIGHT-POINTING ANGLE BRACKET;Pe;0;ON;3009;;;;Y;KET;;;; 232B;ERASE TO THE LEFT;So;0;ON;;;;;N;DELETE TO THE LEFT KEY;;;; 232C;BENZENE RING;So;0;ON;;;;;N;;;;; 232D;CYLINDRICITY;So;0;ON;;;;;N;;;;; 232E;ALL AROUND-PROFILE;So;0;ON;;;;;N;;;;; 232F;SYMMETRY;So;0;ON;;;;;N;;;;; 2330;TOTAL RUNOUT;So;0;ON;;;;;N;;;;; 2331;DIMENSION ORIGIN;So;0;ON;;;;;N;;;;; 2332;CONICAL TAPER;So;0;ON;;;;;N;;;;; 2333;SLOPE;So;0;ON;;;;;N;;;;; 2334;COUNTERBORE;So;0;ON;;;;;N;;;;; 2335;COUNTERSINK;So;0;ON;;;;;N;;;;; 2336;APL FUNCTIONAL SYMBOL I-BEAM;So;0;L;;;;;N;;;;; 2337;APL FUNCTIONAL SYMBOL SQUISH QUAD;So;0;L;;;;;N;;;;; 2338;APL FUNCTIONAL SYMBOL QUAD EQUAL;So;0;L;;;;;N;;;;; 2339;APL FUNCTIONAL SYMBOL QUAD DIVIDE;So;0;L;;;;;N;;;;; 233A;APL FUNCTIONAL SYMBOL QUAD DIAMOND;So;0;L;;;;;N;;;;; 233B;APL FUNCTIONAL SYMBOL QUAD JOT;So;0;L;;;;;N;;;;; 233C;APL FUNCTIONAL SYMBOL QUAD CIRCLE;So;0;L;;;;;N;;;;; 233D;APL FUNCTIONAL SYMBOL CIRCLE STILE;So;0;L;;;;;N;;;;; 233E;APL FUNCTIONAL SYMBOL CIRCLE JOT;So;0;L;;;;;N;;;;; 233F;APL FUNCTIONAL SYMBOL SLASH BAR;So;0;L;;;;;N;;;;; 2340;APL FUNCTIONAL SYMBOL BACKSLASH BAR;So;0;L;;;;;N;;;;; 2341;APL FUNCTIONAL SYMBOL QUAD SLASH;So;0;L;;;;;N;;;;; 2342;APL FUNCTIONAL SYMBOL QUAD BACKSLASH;So;0;L;;;;;N;;;;; 2343;APL FUNCTIONAL SYMBOL QUAD LESS-THAN;So;0;L;;;;;N;;;;; 2344;APL FUNCTIONAL SYMBOL QUAD GREATER-THAN;So;0;L;;;;;N;;;;; 2345;APL FUNCTIONAL SYMBOL LEFTWARDS VANE;So;0;L;;;;;N;;;;; 2346;APL FUNCTIONAL SYMBOL RIGHTWARDS VANE;So;0;L;;;;;N;;;;; 2347;APL FUNCTIONAL SYMBOL QUAD LEFTWARDS ARROW;So;0;L;;;;;N;;;;; 2348;APL FUNCTIONAL SYMBOL QUAD RIGHTWARDS ARROW;So;0;L;;;;;N;;;;; 2349;APL FUNCTIONAL SYMBOL CIRCLE BACKSLASH;So;0;L;;;;;N;;;;; 234A;APL FUNCTIONAL SYMBOL DOWN TACK UNDERBAR;So;0;L;;;;;N;;;;; 234B;APL FUNCTIONAL SYMBOL DELTA STILE;So;0;L;;;;;N;;;;; 234C;APL FUNCTIONAL SYMBOL QUAD DOWN CARET;So;0;L;;;;;N;;;;; 234D;APL FUNCTIONAL SYMBOL QUAD DELTA;So;0;L;;;;;N;;;;; 234E;APL FUNCTIONAL SYMBOL DOWN TACK JOT;So;0;L;;;;;N;;;;; 234F;APL FUNCTIONAL SYMBOL UPWARDS VANE;So;0;L;;;;;N;;;;; 2350;APL FUNCTIONAL SYMBOL QUAD UPWARDS ARROW;So;0;L;;;;;N;;;;; 2351;APL FUNCTIONAL SYMBOL UP TACK OVERBAR;So;0;L;;;;;N;;;;; 2352;APL FUNCTIONAL SYMBOL DEL STILE;So;0;L;;;;;N;;;;; 2353;APL FUNCTIONAL SYMBOL QUAD UP CARET;So;0;L;;;;;N;;;;; 2354;APL FUNCTIONAL SYMBOL QUAD DEL;So;0;L;;;;;N;;;;; 2355;APL FUNCTIONAL SYMBOL UP TACK JOT;So;0;L;;;;;N;;;;; 2356;APL FUNCTIONAL SYMBOL DOWNWARDS VANE;So;0;L;;;;;N;;;;; 2357;APL FUNCTIONAL SYMBOL QUAD DOWNWARDS ARROW;So;0;L;;;;;N;;;;; 2358;APL FUNCTIONAL SYMBOL QUOTE UNDERBAR;So;0;L;;;;;N;;;;; 2359;APL FUNCTIONAL SYMBOL DELTA UNDERBAR;So;0;L;;;;;N;;;;; 235A;APL FUNCTIONAL SYMBOL DIAMOND UNDERBAR;So;0;L;;;;;N;;;;; 235B;APL FUNCTIONAL SYMBOL JOT UNDERBAR;So;0;L;;;;;N;;;;; 235C;APL FUNCTIONAL SYMBOL CIRCLE UNDERBAR;So;0;L;;;;;N;;;;; 235D;APL FUNCTIONAL SYMBOL UP SHOE JOT;So;0;L;;;;;N;;;;; 235E;APL FUNCTIONAL SYMBOL QUOTE QUAD;So;0;L;;;;;N;;;;; 235F;APL FUNCTIONAL SYMBOL CIRCLE STAR;So;0;L;;;;;N;;;;; 2360;APL FUNCTIONAL SYMBOL QUAD COLON;So;0;L;;;;;N;;;;; 2361;APL FUNCTIONAL SYMBOL UP TACK DIAERESIS;So;0;L;;;;;N;;;;; 2362;APL FUNCTIONAL SYMBOL DEL DIAERESIS;So;0;L;;;;;N;;;;; 2363;APL FUNCTIONAL SYMBOL STAR DIAERESIS;So;0;L;;;;;N;;;;; 2364;APL FUNCTIONAL SYMBOL JOT DIAERESIS;So;0;L;;;;;N;;;;; 2365;APL FUNCTIONAL SYMBOL CIRCLE DIAERESIS;So;0;L;;;;;N;;;;; 2366;APL FUNCTIONAL SYMBOL DOWN SHOE STILE;So;0;L;;;;;N;;;;; 2367;APL FUNCTIONAL SYMBOL LEFT SHOE STILE;So;0;L;;;;;N;;;;; 2368;APL FUNCTIONAL SYMBOL TILDE DIAERESIS;So;0;L;;;;;N;;;;; 2369;APL FUNCTIONAL SYMBOL GREATER-THAN DIAERESIS;So;0;L;;;;;N;;;;; 236A;APL FUNCTIONAL SYMBOL COMMA BAR;So;0;L;;;;;N;;;;; 236B;APL FUNCTIONAL SYMBOL DEL TILDE;So;0;L;;;;;N;;;;; 236C;APL FUNCTIONAL SYMBOL ZILDE;So;0;L;;;;;N;;;;; 236D;APL FUNCTIONAL SYMBOL STILE TILDE;So;0;L;;;;;N;;;;; 236E;APL FUNCTIONAL SYMBOL SEMICOLON UNDERBAR;So;0;L;;;;;N;;;;; 236F;APL FUNCTIONAL SYMBOL QUAD NOT EQUAL;So;0;L;;;;;N;;;;; 2370;APL FUNCTIONAL SYMBOL QUAD QUESTION;So;0;L;;;;;N;;;;; 2371;APL FUNCTIONAL SYMBOL DOWN CARET TILDE;So;0;L;;;;;N;;;;; 2372;APL FUNCTIONAL SYMBOL UP CARET TILDE;So;0;L;;;;;N;;;;; 2373;APL FUNCTIONAL SYMBOL IOTA;So;0;L;;;;;N;;;;; 2374;APL FUNCTIONAL SYMBOL RHO;So;0;L;;;;;N;;;;; 2375;APL FUNCTIONAL SYMBOL OMEGA;So;0;L;;;;;N;;;;; 2376;APL FUNCTIONAL SYMBOL ALPHA UNDERBAR;So;0;L;;;;;N;;;;; 2377;APL FUNCTIONAL SYMBOL EPSILON UNDERBAR;So;0;L;;;;;N;;;;; 2378;APL FUNCTIONAL SYMBOL IOTA UNDERBAR;So;0;L;;;;;N;;;;; 2379;APL FUNCTIONAL SYMBOL OMEGA UNDERBAR;So;0;L;;;;;N;;;;; 237A;APL FUNCTIONAL SYMBOL ALPHA;So;0;L;;;;;N;;;;; 237B;NOT CHECK MARK;So;0;ON;;;;;N;;;;; 237C;RIGHT ANGLE WITH DOWNWARDS ZIGZAG ARROW;Sm;0;ON;;;;;N;;;;; 237D;SHOULDERED OPEN BOX;So;0;ON;;;;;N;;;;; 237E;BELL SYMBOL;So;0;ON;;;;;N;;;;; 237F;VERTICAL LINE WITH MIDDLE DOT;So;0;ON;;;;;N;;;;; 2380;INSERTION SYMBOL;So;0;ON;;;;;N;;;;; 2381;CONTINUOUS UNDERLINE SYMBOL;So;0;ON;;;;;N;;;;; 2382;DISCONTINUOUS UNDERLINE SYMBOL;So;0;ON;;;;;N;;;;; 2383;EMPHASIS SYMBOL;So;0;ON;;;;;N;;;;; 2384;COMPOSITION SYMBOL;So;0;ON;;;;;N;;;;; 2385;WHITE SQUARE WITH CENTRE VERTICAL LINE;So;0;ON;;;;;N;;;;; 2386;ENTER SYMBOL;So;0;ON;;;;;N;;;;; 2387;ALTERNATIVE KEY SYMBOL;So;0;ON;;;;;N;;;;; 2388;HELM SYMBOL;So;0;ON;;;;;N;;;;; 2389;CIRCLED HORIZONTAL BAR WITH NOTCH;So;0;ON;;;;;N;;;;; 238A;CIRCLED TRIANGLE DOWN;So;0;ON;;;;;N;;;;; 238B;BROKEN CIRCLE WITH NORTHWEST ARROW;So;0;ON;;;;;N;;;;; 238C;UNDO SYMBOL;So;0;ON;;;;;N;;;;; 238D;MONOSTABLE SYMBOL;So;0;ON;;;;;N;;;;; 238E;HYSTERESIS SYMBOL;So;0;ON;;;;;N;;;;; 238F;OPEN-CIRCUIT-OUTPUT H-TYPE SYMBOL;So;0;ON;;;;;N;;;;; 2390;OPEN-CIRCUIT-OUTPUT L-TYPE SYMBOL;So;0;ON;;;;;N;;;;; 2391;PASSIVE-PULL-DOWN-OUTPUT SYMBOL;So;0;ON;;;;;N;;;;; 2392;PASSIVE-PULL-UP-OUTPUT SYMBOL;So;0;ON;;;;;N;;;;; 2393;DIRECT CURRENT SYMBOL FORM TWO;So;0;ON;;;;;N;;;;; 2394;SOFTWARE-FUNCTION SYMBOL;So;0;ON;;;;;N;;;;; 2395;APL FUNCTIONAL SYMBOL QUAD;So;0;L;;;;;N;;;;; 2396;DECIMAL SEPARATOR KEY SYMBOL;So;0;ON;;;;;N;;;;; 2397;PREVIOUS PAGE;So;0;ON;;;;;N;;;;; 2398;NEXT PAGE;So;0;ON;;;;;N;;;;; 2399;PRINT SCREEN SYMBOL;So;0;ON;;;;;N;;;;; 239A;CLEAR SCREEN SYMBOL;So;0;ON;;;;;N;;;;; 239B;LEFT PARENTHESIS UPPER HOOK;Sm;0;ON;;;;;N;;;;; 239C;LEFT PARENTHESIS EXTENSION;Sm;0;ON;;;;;N;;;;; 239D;LEFT PARENTHESIS LOWER HOOK;Sm;0;ON;;;;;N;;;;; 239E;RIGHT PARENTHESIS UPPER HOOK;Sm;0;ON;;;;;N;;;;; 239F;RIGHT PARENTHESIS EXTENSION;Sm;0;ON;;;;;N;;;;; 23A0;RIGHT PARENTHESIS LOWER HOOK;Sm;0;ON;;;;;N;;;;; 23A1;LEFT SQUARE BRACKET UPPER CORNER;Sm;0;ON;;;;;N;;;;; 23A2;LEFT SQUARE BRACKET EXTENSION;Sm;0;ON;;;;;N;;;;; 23A3;LEFT SQUARE BRACKET LOWER CORNER;Sm;0;ON;;;;;N;;;;; 23A4;RIGHT SQUARE BRACKET UPPER CORNER;Sm;0;ON;;;;;N;;;;; 23A5;RIGHT SQUARE BRACKET EXTENSION;Sm;0;ON;;;;;N;;;;; 23A6;RIGHT SQUARE BRACKET LOWER CORNER;Sm;0;ON;;;;;N;;;;; 23A7;LEFT CURLY BRACKET UPPER HOOK;Sm;0;ON;;;;;N;;;;; 23A8;LEFT CURLY BRACKET MIDDLE PIECE;Sm;0;ON;;;;;N;;;;; 23A9;LEFT CURLY BRACKET LOWER HOOK;Sm;0;ON;;;;;N;;;;; 23AA;CURLY BRACKET EXTENSION;Sm;0;ON;;;;;N;;;;; 23AB;RIGHT CURLY BRACKET UPPER HOOK;Sm;0;ON;;;;;N;;;;; 23AC;RIGHT CURLY BRACKET MIDDLE PIECE;Sm;0;ON;;;;;N;;;;; 23AD;RIGHT CURLY BRACKET LOWER HOOK;Sm;0;ON;;;;;N;;;;; 23AE;INTEGRAL EXTENSION;Sm;0;ON;;;;;N;;;;; 23AF;HORIZONTAL LINE EXTENSION;Sm;0;ON;;;;;N;;;;; 23B0;UPPER LEFT OR LOWER RIGHT CURLY BRACKET SECTION;Sm;0;ON;;;;;N;;;;; 23B1;UPPER RIGHT OR LOWER LEFT CURLY BRACKET SECTION;Sm;0;ON;;;;;N;;;;; 23B2;SUMMATION TOP;Sm;0;ON;;;;;N;;;;; 23B3;SUMMATION BOTTOM;Sm;0;ON;;;;;N;;;;; 23B4;TOP SQUARE BRACKET;So;0;ON;;;;;N;;;;; 23B5;BOTTOM SQUARE BRACKET;So;0;ON;;;;;N;;;;; 23B6;BOTTOM SQUARE BRACKET OVER TOP SQUARE BRACKET;So;0;ON;;;;;N;;;;; 23B7;RADICAL SYMBOL BOTTOM;So;0;ON;;;;;N;;;;; 23B8;LEFT VERTICAL BOX LINE;So;0;ON;;;;;N;;;;; 23B9;RIGHT VERTICAL BOX LINE;So;0;ON;;;;;N;;;;; 23BA;HORIZONTAL SCAN LINE-1;So;0;ON;;;;;N;;;;; 23BB;HORIZONTAL SCAN LINE-3;So;0;ON;;;;;N;;;;; 23BC;HORIZONTAL SCAN LINE-7;So;0;ON;;;;;N;;;;; 23BD;HORIZONTAL SCAN LINE-9;So;0;ON;;;;;N;;;;; 23BE;DENTISTRY SYMBOL LIGHT VERTICAL AND TOP RIGHT;So;0;ON;;;;;N;;;;; 23BF;DENTISTRY SYMBOL LIGHT VERTICAL AND BOTTOM RIGHT;So;0;ON;;;;;N;;;;; 23C0;DENTISTRY SYMBOL LIGHT VERTICAL WITH CIRCLE;So;0;ON;;;;;N;;;;; 23C1;DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL WITH CIRCLE;So;0;ON;;;;;N;;;;; 23C2;DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL WITH CIRCLE;So;0;ON;;;;;N;;;;; 23C3;DENTISTRY SYMBOL LIGHT VERTICAL WITH TRIANGLE;So;0;ON;;;;;N;;;;; 23C4;DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL WITH TRIANGLE;So;0;ON;;;;;N;;;;; 23C5;DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL WITH TRIANGLE;So;0;ON;;;;;N;;;;; 23C6;DENTISTRY SYMBOL LIGHT VERTICAL AND WAVE;So;0;ON;;;;;N;;;;; 23C7;DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL WITH WAVE;So;0;ON;;;;;N;;;;; 23C8;DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL WITH WAVE;So;0;ON;;;;;N;;;;; 23C9;DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL;So;0;ON;;;;;N;;;;; 23CA;DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL;So;0;ON;;;;;N;;;;; 23CB;DENTISTRY SYMBOL LIGHT VERTICAL AND TOP LEFT;So;0;ON;;;;;N;;;;; 23CC;DENTISTRY SYMBOL LIGHT VERTICAL AND BOTTOM LEFT;So;0;ON;;;;;N;;;;; 23CD;SQUARE FOOT;So;0;ON;;;;;N;;;;; 23CE;RETURN SYMBOL;So;0;ON;;;;;N;;;;; 23CF;EJECT SYMBOL;So;0;ON;;;;;N;;;;; 23D0;VERTICAL LINE EXTENSION;So;0;ON;;;;;N;;;;; 23D1;METRICAL BREVE;So;0;ON;;;;;N;;;;; 23D2;METRICAL LONG OVER SHORT;So;0;ON;;;;;N;;;;; 23D3;METRICAL SHORT OVER LONG;So;0;ON;;;;;N;;;;; 23D4;METRICAL LONG OVER TWO SHORTS;So;0;ON;;;;;N;;;;; 23D5;METRICAL TWO SHORTS OVER LONG;So;0;ON;;;;;N;;;;; 23D6;METRICAL TWO SHORTS JOINED;So;0;ON;;;;;N;;;;; 23D7;METRICAL TRISEME;So;0;ON;;;;;N;;;;; 23D8;METRICAL TETRASEME;So;0;ON;;;;;N;;;;; 23D9;METRICAL PENTASEME;So;0;ON;;;;;N;;;;; 23DA;EARTH GROUND;So;0;ON;;;;;N;;;;; 23DB;FUSE;So;0;ON;;;;;N;;;;; 23DC;TOP PARENTHESIS;Sm;0;ON;;;;;N;;;;; 23DD;BOTTOM PARENTHESIS;Sm;0;ON;;;;;N;;;;; 23DE;TOP CURLY BRACKET;Sm;0;ON;;;;;N;;;;; 23DF;BOTTOM CURLY BRACKET;Sm;0;ON;;;;;N;;;;; 23E0;TOP TORTOISE SHELL BRACKET;Sm;0;ON;;;;;N;;;;; 23E1;BOTTOM TORTOISE SHELL BRACKET;Sm;0;ON;;;;;N;;;;; 23E2;WHITE TRAPEZIUM;So;0;ON;;;;;N;;;;; 23E3;BENZENE RING WITH CIRCLE;So;0;ON;;;;;N;;;;; 23E4;STRAIGHTNESS;So;0;ON;;;;;N;;;;; 23E5;FLATNESS;So;0;ON;;;;;N;;;;; 23E6;AC CURRENT;So;0;ON;;;;;N;;;;; 23E7;ELECTRICAL INTERSECTION;So;0;ON;;;;;N;;;;; 23E8;DECIMAL EXPONENT SYMBOL;So;0;ON;;;;;N;;;;; 23E9;BLACK RIGHT-POINTING DOUBLE TRIANGLE;So;0;ON;;;;;N;;;;; 23EA;BLACK LEFT-POINTING DOUBLE TRIANGLE;So;0;ON;;;;;N;;;;; 23EB;BLACK UP-POINTING DOUBLE TRIANGLE;So;0;ON;;;;;N;;;;; 23EC;BLACK DOWN-POINTING DOUBLE TRIANGLE;So;0;ON;;;;;N;;;;; 23ED;BLACK RIGHT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR;So;0;ON;;;;;N;;;;; 23EE;BLACK LEFT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR;So;0;ON;;;;;N;;;;; 23EF;BLACK RIGHT-POINTING TRIANGLE WITH DOUBLE VERTICAL BAR;So;0;ON;;;;;N;;;;; 23F0;ALARM CLOCK;So;0;ON;;;;;N;;;;; 23F1;STOPWATCH;So;0;ON;;;;;N;;;;; 23F2;TIMER CLOCK;So;0;ON;;;;;N;;;;; 23F3;HOURGLASS WITH FLOWING SAND;So;0;ON;;;;;N;;;;; 23F4;BLACK MEDIUM LEFT-POINTING TRIANGLE;So;0;ON;;;;;N;;;;; 23F5;BLACK MEDIUM RIGHT-POINTING TRIANGLE;So;0;ON;;;;;N;;;;; 23F6;BLACK MEDIUM UP-POINTING TRIANGLE;So;0;ON;;;;;N;;;;; 23F7;BLACK MEDIUM DOWN-POINTING TRIANGLE;So;0;ON;;;;;N;;;;; 23F8;DOUBLE VERTICAL BAR;So;0;ON;;;;;N;;;;; 23F9;BLACK SQUARE FOR STOP;So;0;ON;;;;;N;;;;; 23FA;BLACK CIRCLE FOR RECORD;So;0;ON;;;;;N;;;;; 23FB;POWER SYMBOL;So;0;ON;;;;;N;;;;; 23FC;POWER ON-OFF SYMBOL;So;0;ON;;;;;N;;;;; 23FD;POWER ON SYMBOL;So;0;ON;;;;;N;;;;; 23FE;POWER SLEEP SYMBOL;So;0;ON;;;;;N;;;;; 2400;SYMBOL FOR NULL;So;0;ON;;;;;N;GRAPHIC FOR NULL;;;; 2401;SYMBOL FOR START OF HEADING;So;0;ON;;;;;N;GRAPHIC FOR START OF HEADING;;;; 2402;SYMBOL FOR START OF TEXT;So;0;ON;;;;;N;GRAPHIC FOR START OF TEXT;;;; 2403;SYMBOL FOR END OF TEXT;So;0;ON;;;;;N;GRAPHIC FOR END OF TEXT;;;; 2404;SYMBOL FOR END OF TRANSMISSION;So;0;ON;;;;;N;GRAPHIC FOR END OF TRANSMISSION;;;; 2405;SYMBOL FOR ENQUIRY;So;0;ON;;;;;N;GRAPHIC FOR ENQUIRY;;;; 2406;SYMBOL FOR ACKNOWLEDGE;So;0;ON;;;;;N;GRAPHIC FOR ACKNOWLEDGE;;;; 2407;SYMBOL FOR BELL;So;0;ON;;;;;N;GRAPHIC FOR BELL;;;; 2408;SYMBOL FOR BACKSPACE;So;0;ON;;;;;N;GRAPHIC FOR BACKSPACE;;;; 2409;SYMBOL FOR HORIZONTAL TABULATION;So;0;ON;;;;;N;GRAPHIC FOR HORIZONTAL TABULATION;;;; 240A;SYMBOL FOR LINE FEED;So;0;ON;;;;;N;GRAPHIC FOR LINE FEED;;;; 240B;SYMBOL FOR VERTICAL TABULATION;So;0;ON;;;;;N;GRAPHIC FOR VERTICAL TABULATION;;;; 240C;SYMBOL FOR FORM FEED;So;0;ON;;;;;N;GRAPHIC FOR FORM FEED;;;; 240D;SYMBOL FOR CARRIAGE RETURN;So;0;ON;;;;;N;GRAPHIC FOR CARRIAGE RETURN;;;; 240E;SYMBOL FOR SHIFT OUT;So;0;ON;;;;;N;GRAPHIC FOR SHIFT OUT;;;; 240F;SYMBOL FOR SHIFT IN;So;0;ON;;;;;N;GRAPHIC FOR SHIFT IN;;;; 2410;SYMBOL FOR DATA LINK ESCAPE;So;0;ON;;;;;N;GRAPHIC FOR DATA LINK ESCAPE;;;; 2411;SYMBOL FOR DEVICE CONTROL ONE;So;0;ON;;;;;N;GRAPHIC FOR DEVICE CONTROL ONE;;;; 2412;SYMBOL FOR DEVICE CONTROL TWO;So;0;ON;;;;;N;GRAPHIC FOR DEVICE CONTROL TWO;;;; 2413;SYMBOL FOR DEVICE CONTROL THREE;So;0;ON;;;;;N;GRAPHIC FOR DEVICE CONTROL THREE;;;; 2414;SYMBOL FOR DEVICE CONTROL FOUR;So;0;ON;;;;;N;GRAPHIC FOR DEVICE CONTROL FOUR;;;; 2415;SYMBOL FOR NEGATIVE ACKNOWLEDGE;So;0;ON;;;;;N;GRAPHIC FOR NEGATIVE ACKNOWLEDGE;;;; 2416;SYMBOL FOR SYNCHRONOUS IDLE;So;0;ON;;;;;N;GRAPHIC FOR SYNCHRONOUS IDLE;;;; 2417;SYMBOL FOR END OF TRANSMISSION BLOCK;So;0;ON;;;;;N;GRAPHIC FOR END OF TRANSMISSION BLOCK;;;; 2418;SYMBOL FOR CANCEL;So;0;ON;;;;;N;GRAPHIC FOR CANCEL;;;; 2419;SYMBOL FOR END OF MEDIUM;So;0;ON;;;;;N;GRAPHIC FOR END OF MEDIUM;;;; 241A;SYMBOL FOR SUBSTITUTE;So;0;ON;;;;;N;GRAPHIC FOR SUBSTITUTE;;;; 241B;SYMBOL FOR ESCAPE;So;0;ON;;;;;N;GRAPHIC FOR ESCAPE;;;; 241C;SYMBOL FOR FILE SEPARATOR;So;0;ON;;;;;N;GRAPHIC FOR FILE SEPARATOR;;;; 241D;SYMBOL FOR GROUP SEPARATOR;So;0;ON;;;;;N;GRAPHIC FOR GROUP SEPARATOR;;;; 241E;SYMBOL FOR RECORD SEPARATOR;So;0;ON;;;;;N;GRAPHIC FOR RECORD SEPARATOR;;;; 241F;SYMBOL FOR UNIT SEPARATOR;So;0;ON;;;;;N;GRAPHIC FOR UNIT SEPARATOR;;;; 2420;SYMBOL FOR SPACE;So;0;ON;;;;;N;GRAPHIC FOR SPACE;;;; 2421;SYMBOL FOR DELETE;So;0;ON;;;;;N;GRAPHIC FOR DELETE;;;; 2422;BLANK SYMBOL;So;0;ON;;;;;N;BLANK;;;; 2423;OPEN BOX;So;0;ON;;;;;N;;;;; 2424;SYMBOL FOR NEWLINE;So;0;ON;;;;;N;GRAPHIC FOR NEWLINE;;;; 2425;SYMBOL FOR DELETE FORM TWO;So;0;ON;;;;;N;;;;; 2426;SYMBOL FOR SUBSTITUTE FORM TWO;So;0;ON;;;;;N;;;;; 2440;OCR HOOK;So;0;ON;;;;;N;;;;; 2441;OCR CHAIR;So;0;ON;;;;;N;;;;; 2442;OCR FORK;So;0;ON;;;;;N;;;;; 2443;OCR INVERTED FORK;So;0;ON;;;;;N;;;;; 2444;OCR BELT BUCKLE;So;0;ON;;;;;N;;;;; 2445;OCR BOW TIE;So;0;ON;;;;;N;;;;; 2446;OCR BRANCH BANK IDENTIFICATION;So;0;ON;;;;;N;;;;; 2447;OCR AMOUNT OF CHECK;So;0;ON;;;;;N;;;;; 2448;OCR DASH;So;0;ON;;;;;N;;;;; 2449;OCR CUSTOMER ACCOUNT NUMBER;So;0;ON;;;;;N;;;;; 244A;OCR DOUBLE BACKSLASH;So;0;ON;;;;;N;;;;; 2460;CIRCLED DIGIT ONE;No;0;ON;<circle> 0031;;1;1;N;;;;; 2461;CIRCLED DIGIT TWO;No;0;ON;<circle> 0032;;2;2;N;;;;; 2462;CIRCLED DIGIT THREE;No;0;ON;<circle> 0033;;3;3;N;;;;; 2463;CIRCLED DIGIT FOUR;No;0;ON;<circle> 0034;;4;4;N;;;;; 2464;CIRCLED DIGIT FIVE;No;0;ON;<circle> 0035;;5;5;N;;;;; 2465;CIRCLED DIGIT SIX;No;0;ON;<circle> 0036;;6;6;N;;;;; 2466;CIRCLED DIGIT SEVEN;No;0;ON;<circle> 0037;;7;7;N;;;;; 2467;CIRCLED DIGIT EIGHT;No;0;ON;<circle> 0038;;8;8;N;;;;; 2468;CIRCLED DIGIT NINE;No;0;ON;<circle> 0039;;9;9;N;;;;; 2469;CIRCLED NUMBER TEN;No;0;ON;<circle> 0031 0030;;;10;N;;;;; 246A;CIRCLED NUMBER ELEVEN;No;0;ON;<circle> 0031 0031;;;11;N;;;;; 246B;CIRCLED NUMBER TWELVE;No;0;ON;<circle> 0031 0032;;;12;N;;;;; 246C;CIRCLED NUMBER THIRTEEN;No;0;ON;<circle> 0031 0033;;;13;N;;;;; 246D;CIRCLED NUMBER FOURTEEN;No;0;ON;<circle> 0031 0034;;;14;N;;;;; 246E;CIRCLED NUMBER FIFTEEN;No;0;ON;<circle> 0031 0035;;;15;N;;;;; 246F;CIRCLED NUMBER SIXTEEN;No;0;ON;<circle> 0031 0036;;;16;N;;;;; 2470;CIRCLED NUMBER SEVENTEEN;No;0;ON;<circle> 0031 0037;;;17;N;;;;; 2471;CIRCLED NUMBER EIGHTEEN;No;0;ON;<circle> 0031 0038;;;18;N;;;;; 2472;CIRCLED NUMBER NINETEEN;No;0;ON;<circle> 0031 0039;;;19;N;;;;; 2473;CIRCLED NUMBER TWENTY;No;0;ON;<circle> 0032 0030;;;20;N;;;;; 2474;PARENTHESIZED DIGIT ONE;No;0;ON;<compat> 0028 0031 0029;;1;1;N;;;;; 2475;PARENTHESIZED DIGIT TWO;No;0;ON;<compat> 0028 0032 0029;;2;2;N;;;;; 2476;PARENTHESIZED DIGIT THREE;No;0;ON;<compat> 0028 0033 0029;;3;3;N;;;;; 2477;PARENTHESIZED DIGIT FOUR;No;0;ON;<compat> 0028 0034 0029;;4;4;N;;;;; 2478;PARENTHESIZED DIGIT FIVE;No;0;ON;<compat> 0028 0035 0029;;5;5;N;;;;; 2479;PARENTHESIZED DIGIT SIX;No;0;ON;<compat> 0028 0036 0029;;6;6;N;;;;; 247A;PARENTHESIZED DIGIT SEVEN;No;0;ON;<compat> 0028 0037 0029;;7;7;N;;;;; 247B;PARENTHESIZED DIGIT EIGHT;No;0;ON;<compat> 0028 0038 0029;;8;8;N;;;;; 247C;PARENTHESIZED DIGIT NINE;No;0;ON;<compat> 0028 0039 0029;;9;9;N;;;;; 247D;PARENTHESIZED NUMBER TEN;No;0;ON;<compat> 0028 0031 0030 0029;;;10;N;;;;; 247E;PARENTHESIZED NUMBER ELEVEN;No;0;ON;<compat> 0028 0031 0031 0029;;;11;N;;;;; 247F;PARENTHESIZED NUMBER TWELVE;No;0;ON;<compat> 0028 0031 0032 0029;;;12;N;;;;; 2480;PARENTHESIZED NUMBER THIRTEEN;No;0;ON;<compat> 0028 0031 0033 0029;;;13;N;;;;; 2481;PARENTHESIZED NUMBER FOURTEEN;No;0;ON;<compat> 0028 0031 0034 0029;;;14;N;;;;; 2482;PARENTHESIZED NUMBER FIFTEEN;No;0;ON;<compat> 0028 0031 0035 0029;;;15;N;;;;; 2483;PARENTHESIZED NUMBER SIXTEEN;No;0;ON;<compat> 0028 0031 0036 0029;;;16;N;;;;; 2484;PARENTHESIZED NUMBER SEVENTEEN;No;0;ON;<compat> 0028 0031 0037 0029;;;17;N;;;;; 2485;PARENTHESIZED NUMBER EIGHTEEN;No;0;ON;<compat> 0028 0031 0038 0029;;;18;N;;;;; 2486;PARENTHESIZED NUMBER NINETEEN;No;0;ON;<compat> 0028 0031 0039 0029;;;19;N;;;;; 2487;PARENTHESIZED NUMBER TWENTY;No;0;ON;<compat> 0028 0032 0030 0029;;;20;N;;;;; 2488;DIGIT ONE FULL STOP;No;0;EN;<compat> 0031 002E;;1;1;N;DIGIT ONE PERIOD;;;; 2489;DIGIT TWO FULL STOP;No;0;EN;<compat> 0032 002E;;2;2;N;DIGIT TWO PERIOD;;;; 248A;DIGIT THREE FULL STOP;No;0;EN;<compat> 0033 002E;;3;3;N;DIGIT THREE PERIOD;;;; 248B;DIGIT FOUR FULL STOP;No;0;EN;<compat> 0034 002E;;4;4;N;DIGIT FOUR PERIOD;;;; 248C;DIGIT FIVE FULL STOP;No;0;EN;<compat> 0035 002E;;5;5;N;DIGIT FIVE PERIOD;;;; 248D;DIGIT SIX FULL STOP;No;0;EN;<compat> 0036 002E;;6;6;N;DIGIT SIX PERIOD;;;; 248E;DIGIT SEVEN FULL STOP;No;0;EN;<compat> 0037 002E;;7;7;N;DIGIT SEVEN PERIOD;;;; 248F;DIGIT EIGHT FULL STOP;No;0;EN;<compat> 0038 002E;;8;8;N;DIGIT EIGHT PERIOD;;;; 2490;DIGIT NINE FULL STOP;No;0;EN;<compat> 0039 002E;;9;9;N;DIGIT NINE PERIOD;;;; 2491;NUMBER TEN FULL STOP;No;0;EN;<compat> 0031 0030 002E;;;10;N;NUMBER TEN PERIOD;;;; 2492;NUMBER ELEVEN FULL STOP;No;0;EN;<compat> 0031 0031 002E;;;11;N;NUMBER ELEVEN PERIOD;;;; 2493;NUMBER TWELVE FULL STOP;No;0;EN;<compat> 0031 0032 002E;;;12;N;NUMBER TWELVE PERIOD;;;; 2494;NUMBER THIRTEEN FULL STOP;No;0;EN;<compat> 0031 0033 002E;;;13;N;NUMBER THIRTEEN PERIOD;;;; 2495;NUMBER FOURTEEN FULL STOP;No;0;EN;<compat> 0031 0034 002E;;;14;N;NUMBER FOURTEEN PERIOD;;;; 2496;NUMBER FIFTEEN FULL STOP;No;0;EN;<compat> 0031 0035 002E;;;15;N;NUMBER FIFTEEN PERIOD;;;; 2497;NUMBER SIXTEEN FULL STOP;No;0;EN;<compat> 0031 0036 002E;;;16;N;NUMBER SIXTEEN PERIOD;;;; 2498;NUMBER SEVENTEEN FULL STOP;No;0;EN;<compat> 0031 0037 002E;;;17;N;NUMBER SEVENTEEN PERIOD;;;; 2499;NUMBER EIGHTEEN FULL STOP;No;0;EN;<compat> 0031 0038 002E;;;18;N;NUMBER EIGHTEEN PERIOD;;;; 249A;NUMBER NINETEEN FULL STOP;No;0;EN;<compat> 0031 0039 002E;;;19;N;NUMBER NINETEEN PERIOD;;;; 249B;NUMBER TWENTY FULL STOP;No;0;EN;<compat> 0032 0030 002E;;;20;N;NUMBER TWENTY PERIOD;;;; 249C;PARENTHESIZED LATIN SMALL LETTER A;So;0;L;<compat> 0028 0061 0029;;;;N;;;;; 249D;PARENTHESIZED LATIN SMALL LETTER B;So;0;L;<compat> 0028 0062 0029;;;;N;;;;; 249E;PARENTHESIZED LATIN SMALL LETTER C;So;0;L;<compat> 0028 0063 0029;;;;N;;;;; 249F;PARENTHESIZED LATIN SMALL LETTER D;So;0;L;<compat> 0028 0064 0029;;;;N;;;;; 24A0;PARENTHESIZED LATIN SMALL LETTER E;So;0;L;<compat> 0028 0065 0029;;;;N;;;;; 24A1;PARENTHESIZED LATIN SMALL LETTER F;So;0;L;<compat> 0028 0066 0029;;;;N;;;;; 24A2;PARENTHESIZED LATIN SMALL LETTER G;So;0;L;<compat> 0028 0067 0029;;;;N;;;;; 24A3;PARENTHESIZED LATIN SMALL LETTER H;So;0;L;<compat> 0028 0068 0029;;;;N;;;;; 24A4;PARENTHESIZED LATIN SMALL LETTER I;So;0;L;<compat> 0028 0069 0029;;;;N;;;;; 24A5;PARENTHESIZED LATIN SMALL LETTER J;So;0;L;<compat> 0028 006A 0029;;;;N;;;;; 24A6;PARENTHESIZED LATIN SMALL LETTER K;So;0;L;<compat> 0028 006B 0029;;;;N;;;;; 24A7;PARENTHESIZED LATIN SMALL LETTER L;So;0;L;<compat> 0028 006C 0029;;;;N;;;;; 24A8;PARENTHESIZED LATIN SMALL LETTER M;So;0;L;<compat> 0028 006D 0029;;;;N;;;;; 24A9;PARENTHESIZED LATIN SMALL LETTER N;So;0;L;<compat> 0028 006E 0029;;;;N;;;;; 24AA;PARENTHESIZED LATIN SMALL LETTER O;So;0;L;<compat> 0028 006F 0029;;;;N;;;;; 24AB;PARENTHESIZED LATIN SMALL LETTER P;So;0;L;<compat> 0028 0070 0029;;;;N;;;;; 24AC;PARENTHESIZED LATIN SMALL LETTER Q;So;0;L;<compat> 0028 0071 0029;;;;N;;;;; 24AD;PARENTHESIZED LATIN SMALL LETTER R;So;0;L;<compat> 0028 0072 0029;;;;N;;;;; 24AE;PARENTHESIZED LATIN SMALL LETTER S;So;0;L;<compat> 0028 0073 0029;;;;N;;;;; 24AF;PARENTHESIZED LATIN SMALL LETTER T;So;0;L;<compat> 0028 0074 0029;;;;N;;;;; 24B0;PARENTHESIZED LATIN SMALL LETTER U;So;0;L;<compat> 0028 0075 0029;;;;N;;;;; 24B1;PARENTHESIZED LATIN SMALL LETTER V;So;0;L;<compat> 0028 0076 0029;;;;N;;;;; 24B2;PARENTHESIZED LATIN SMALL LETTER W;So;0;L;<compat> 0028 0077 0029;;;;N;;;;; 24B3;PARENTHESIZED LATIN SMALL LETTER X;So;0;L;<compat> 0028 0078 0029;;;;N;;;;; 24B4;PARENTHESIZED LATIN SMALL LETTER Y;So;0;L;<compat> 0028 0079 0029;;;;N;;;;; 24B5;PARENTHESIZED LATIN SMALL LETTER Z;So;0;L;<compat> 0028 007A 0029;;;;N;;;;; 24B6;CIRCLED LATIN CAPITAL LETTER A;So;0;L;<circle> 0041;;;;N;;;;24D0; 24B7;CIRCLED LATIN CAPITAL LETTER B;So;0;L;<circle> 0042;;;;N;;;;24D1; 24B8;CIRCLED LATIN CAPITAL LETTER C;So;0;L;<circle> 0043;;;;N;;;;24D2; 24B9;CIRCLED LATIN CAPITAL LETTER D;So;0;L;<circle> 0044;;;;N;;;;24D3; 24BA;CIRCLED LATIN CAPITAL LETTER E;So;0;L;<circle> 0045;;;;N;;;;24D4; 24BB;CIRCLED LATIN CAPITAL LETTER F;So;0;L;<circle> 0046;;;;N;;;;24D5; 24BC;CIRCLED LATIN CAPITAL LETTER G;So;0;L;<circle> 0047;;;;N;;;;24D6; 24BD;CIRCLED LATIN CAPITAL LETTER H;So;0;L;<circle> 0048;;;;N;;;;24D7; 24BE;CIRCLED LATIN CAPITAL LETTER I;So;0;L;<circle> 0049;;;;N;;;;24D8; 24BF;CIRCLED LATIN CAPITAL LETTER J;So;0;L;<circle> 004A;;;;N;;;;24D9; 24C0;CIRCLED LATIN CAPITAL LETTER K;So;0;L;<circle> 004B;;;;N;;;;24DA; 24C1;CIRCLED LATIN CAPITAL LETTER L;So;0;L;<circle> 004C;;;;N;;;;24DB; 24C2;CIRCLED LATIN CAPITAL LETTER M;So;0;L;<circle> 004D;;;;N;;;;24DC; 24C3;CIRCLED LATIN CAPITAL LETTER N;So;0;L;<circle> 004E;;;;N;;;;24DD; 24C4;CIRCLED LATIN CAPITAL LETTER O;So;0;L;<circle> 004F;;;;N;;;;24DE; 24C5;CIRCLED LATIN CAPITAL LETTER P;So;0;L;<circle> 0050;;;;N;;;;24DF; 24C6;CIRCLED LATIN CAPITAL LETTER Q;So;0;L;<circle> 0051;;;;N;;;;24E0; 24C7;CIRCLED LATIN CAPITAL LETTER R;So;0;L;<circle> 0052;;;;N;;;;24E1; 24C8;CIRCLED LATIN CAPITAL LETTER S;So;0;L;<circle> 0053;;;;N;;;;24E2; 24C9;CIRCLED LATIN CAPITAL LETTER T;So;0;L;<circle> 0054;;;;N;;;;24E3; 24CA;CIRCLED LATIN CAPITAL LETTER U;So;0;L;<circle> 0055;;;;N;;;;24E4; 24CB;CIRCLED LATIN CAPITAL LETTER V;So;0;L;<circle> 0056;;;;N;;;;24E5; 24CC;CIRCLED LATIN CAPITAL LETTER W;So;0;L;<circle> 0057;;;;N;;;;24E6; 24CD;CIRCLED LATIN CAPITAL LETTER X;So;0;L;<circle> 0058;;;;N;;;;24E7; 24CE;CIRCLED LATIN CAPITAL LETTER Y;So;0;L;<circle> 0059;;;;N;;;;24E8; 24CF;CIRCLED LATIN CAPITAL LETTER Z;So;0;L;<circle> 005A;;;;N;;;;24E9; 24D0;CIRCLED LATIN SMALL LETTER A;So;0;L;<circle> 0061;;;;N;;;24B6;;24B6 24D1;CIRCLED LATIN SMALL LETTER B;So;0;L;<circle> 0062;;;;N;;;24B7;;24B7 24D2;CIRCLED LATIN SMALL LETTER C;So;0;L;<circle> 0063;;;;N;;;24B8;;24B8 24D3;CIRCLED LATIN SMALL LETTER D;So;0;L;<circle> 0064;;;;N;;;24B9;;24B9 24D4;CIRCLED LATIN SMALL LETTER E;So;0;L;<circle> 0065;;;;N;;;24BA;;24BA 24D5;CIRCLED LATIN SMALL LETTER F;So;0;L;<circle> 0066;;;;N;;;24BB;;24BB 24D6;CIRCLED LATIN SMALL LETTER G;So;0;L;<circle> 0067;;;;N;;;24BC;;24BC 24D7;CIRCLED LATIN SMALL LETTER H;So;0;L;<circle> 0068;;;;N;;;24BD;;24BD 24D8;CIRCLED LATIN SMALL LETTER I;So;0;L;<circle> 0069;;;;N;;;24BE;;24BE 24D9;CIRCLED LATIN SMALL LETTER J;So;0;L;<circle> 006A;;;;N;;;24BF;;24BF 24DA;CIRCLED LATIN SMALL LETTER K;So;0;L;<circle> 006B;;;;N;;;24C0;;24C0 24DB;CIRCLED LATIN SMALL LETTER L;So;0;L;<circle> 006C;;;;N;;;24C1;;24C1 24DC;CIRCLED LATIN SMALL LETTER M;So;0;L;<circle> 006D;;;;N;;;24C2;;24C2 24DD;CIRCLED LATIN SMALL LETTER N;So;0;L;<circle> 006E;;;;N;;;24C3;;24C3 24DE;CIRCLED LATIN SMALL LETTER O;So;0;L;<circle> 006F;;;;N;;;24C4;;24C4 24DF;CIRCLED LATIN SMALL LETTER P;So;0;L;<circle> 0070;;;;N;;;24C5;;24C5 24E0;CIRCLED LATIN SMALL LETTER Q;So;0;L;<circle> 0071;;;;N;;;24C6;;24C6 24E1;CIRCLED LATIN SMALL LETTER R;So;0;L;<circle> 0072;;;;N;;;24C7;;24C7 24E2;CIRCLED LATIN SMALL LETTER S;So;0;L;<circle> 0073;;;;N;;;24C8;;24C8 24E3;CIRCLED LATIN SMALL LETTER T;So;0;L;<circle> 0074;;;;N;;;24C9;;24C9 24E4;CIRCLED LATIN SMALL LETTER U;So;0;L;<circle> 0075;;;;N;;;24CA;;24CA 24E5;CIRCLED LATIN SMALL LETTER V;So;0;L;<circle> 0076;;;;N;;;24CB;;24CB 24E6;CIRCLED LATIN SMALL LETTER W;So;0;L;<circle> 0077;;;;N;;;24CC;;24CC 24E7;CIRCLED LATIN SMALL LETTER X;So;0;L;<circle> 0078;;;;N;;;24CD;;24CD 24E8;CIRCLED LATIN SMALL LETTER Y;So;0;L;<circle> 0079;;;;N;;;24CE;;24CE 24E9;CIRCLED LATIN SMALL LETTER Z;So;0;L;<circle> 007A;;;;N;;;24CF;;24CF 24EA;CIRCLED DIGIT ZERO;No;0;ON;<circle> 0030;;0;0;N;;;;; 24EB;NEGATIVE CIRCLED NUMBER ELEVEN;No;0;ON;;;;11;N;;;;; 24EC;NEGATIVE CIRCLED NUMBER TWELVE;No;0;ON;;;;12;N;;;;; 24ED;NEGATIVE CIRCLED NUMBER THIRTEEN;No;0;ON;;;;13;N;;;;; 24EE;NEGATIVE CIRCLED NUMBER FOURTEEN;No;0;ON;;;;14;N;;;;; 24EF;NEGATIVE CIRCLED NUMBER FIFTEEN;No;0;ON;;;;15;N;;;;; 24F0;NEGATIVE CIRCLED NUMBER SIXTEEN;No;0;ON;;;;16;N;;;;; 24F1;NEGATIVE CIRCLED NUMBER SEVENTEEN;No;0;ON;;;;17;N;;;;; 24F2;NEGATIVE CIRCLED NUMBER EIGHTEEN;No;0;ON;;;;18;N;;;;; 24F3;NEGATIVE CIRCLED NUMBER NINETEEN;No;0;ON;;;;19;N;;;;; 24F4;NEGATIVE CIRCLED NUMBER TWENTY;No;0;ON;;;;20;N;;;;; 24F5;DOUBLE CIRCLED DIGIT ONE;No;0;ON;;;1;1;N;;;;; 24F6;DOUBLE CIRCLED DIGIT TWO;No;0;ON;;;2;2;N;;;;; 24F7;DOUBLE CIRCLED DIGIT THREE;No;0;ON;;;3;3;N;;;;; 24F8;DOUBLE CIRCLED DIGIT FOUR;No;0;ON;;;4;4;N;;;;; 24F9;DOUBLE CIRCLED DIGIT FIVE;No;0;ON;;;5;5;N;;;;; 24FA;DOUBLE CIRCLED DIGIT SIX;No;0;ON;;;6;6;N;;;;; 24FB;DOUBLE CIRCLED DIGIT SEVEN;No;0;ON;;;7;7;N;;;;; 24FC;DOUBLE CIRCLED DIGIT EIGHT;No;0;ON;;;8;8;N;;;;; 24FD;DOUBLE CIRCLED DIGIT NINE;No;0;ON;;;9;9;N;;;;; 24FE;DOUBLE CIRCLED NUMBER TEN;No;0;ON;;;;10;N;;;;; 24FF;NEGATIVE CIRCLED DIGIT ZERO;No;0;ON;;;0;0;N;;;;; 2500;BOX DRAWINGS LIGHT HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT HORIZONTAL;;;; 2501;BOX DRAWINGS HEAVY HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY HORIZONTAL;;;; 2502;BOX DRAWINGS LIGHT VERTICAL;So;0;ON;;;;;N;FORMS LIGHT VERTICAL;;;; 2503;BOX DRAWINGS HEAVY VERTICAL;So;0;ON;;;;;N;FORMS HEAVY VERTICAL;;;; 2504;BOX DRAWINGS LIGHT TRIPLE DASH HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT TRIPLE DASH HORIZONTAL;;;; 2505;BOX DRAWINGS HEAVY TRIPLE DASH HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY TRIPLE DASH HORIZONTAL;;;; 2506;BOX DRAWINGS LIGHT TRIPLE DASH VERTICAL;So;0;ON;;;;;N;FORMS LIGHT TRIPLE DASH VERTICAL;;;; 2507;BOX DRAWINGS HEAVY TRIPLE DASH VERTICAL;So;0;ON;;;;;N;FORMS HEAVY TRIPLE DASH VERTICAL;;;; 2508;BOX DRAWINGS LIGHT QUADRUPLE DASH HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT QUADRUPLE DASH HORIZONTAL;;;; 2509;BOX DRAWINGS HEAVY QUADRUPLE DASH HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY QUADRUPLE DASH HORIZONTAL;;;; 250A;BOX DRAWINGS LIGHT QUADRUPLE DASH VERTICAL;So;0;ON;;;;;N;FORMS LIGHT QUADRUPLE DASH VERTICAL;;;; 250B;BOX DRAWINGS HEAVY QUADRUPLE DASH VERTICAL;So;0;ON;;;;;N;FORMS HEAVY QUADRUPLE DASH VERTICAL;;;; 250C;BOX DRAWINGS LIGHT DOWN AND RIGHT;So;0;ON;;;;;N;FORMS LIGHT DOWN AND RIGHT;;;; 250D;BOX DRAWINGS DOWN LIGHT AND RIGHT HEAVY;So;0;ON;;;;;N;FORMS DOWN LIGHT AND RIGHT HEAVY;;;; 250E;BOX DRAWINGS DOWN HEAVY AND RIGHT LIGHT;So;0;ON;;;;;N;FORMS DOWN HEAVY AND RIGHT LIGHT;;;; 250F;BOX DRAWINGS HEAVY DOWN AND RIGHT;So;0;ON;;;;;N;FORMS HEAVY DOWN AND RIGHT;;;; 2510;BOX DRAWINGS LIGHT DOWN AND LEFT;So;0;ON;;;;;N;FORMS LIGHT DOWN AND LEFT;;;; 2511;BOX DRAWINGS DOWN LIGHT AND LEFT HEAVY;So;0;ON;;;;;N;FORMS DOWN LIGHT AND LEFT HEAVY;;;; 2512;BOX DRAWINGS DOWN HEAVY AND LEFT LIGHT;So;0;ON;;;;;N;FORMS DOWN HEAVY AND LEFT LIGHT;;;; 2513;BOX DRAWINGS HEAVY DOWN AND LEFT;So;0;ON;;;;;N;FORMS HEAVY DOWN AND LEFT;;;; 2514;BOX DRAWINGS LIGHT UP AND RIGHT;So;0;ON;;;;;N;FORMS LIGHT UP AND RIGHT;;;; 2515;BOX DRAWINGS UP LIGHT AND RIGHT HEAVY;So;0;ON;;;;;N;FORMS UP LIGHT AND RIGHT HEAVY;;;; 2516;BOX DRAWINGS UP HEAVY AND RIGHT LIGHT;So;0;ON;;;;;N;FORMS UP HEAVY AND RIGHT LIGHT;;;; 2517;BOX DRAWINGS HEAVY UP AND RIGHT;So;0;ON;;;;;N;FORMS HEAVY UP AND RIGHT;;;; 2518;BOX DRAWINGS LIGHT UP AND LEFT;So;0;ON;;;;;N;FORMS LIGHT UP AND LEFT;;;; 2519;BOX DRAWINGS UP LIGHT AND LEFT HEAVY;So;0;ON;;;;;N;FORMS UP LIGHT AND LEFT HEAVY;;;; 251A;BOX DRAWINGS UP HEAVY AND LEFT LIGHT;So;0;ON;;;;;N;FORMS UP HEAVY AND LEFT LIGHT;;;; 251B;BOX DRAWINGS HEAVY UP AND LEFT;So;0;ON;;;;;N;FORMS HEAVY UP AND LEFT;;;; 251C;BOX DRAWINGS LIGHT VERTICAL AND RIGHT;So;0;ON;;;;;N;FORMS LIGHT VERTICAL AND RIGHT;;;; 251D;BOX DRAWINGS VERTICAL LIGHT AND RIGHT HEAVY;So;0;ON;;;;;N;FORMS VERTICAL LIGHT AND RIGHT HEAVY;;;; 251E;BOX DRAWINGS UP HEAVY AND RIGHT DOWN LIGHT;So;0;ON;;;;;N;FORMS UP HEAVY AND RIGHT DOWN LIGHT;;;; 251F;BOX DRAWINGS DOWN HEAVY AND RIGHT UP LIGHT;So;0;ON;;;;;N;FORMS DOWN HEAVY AND RIGHT UP LIGHT;;;; 2520;BOX DRAWINGS VERTICAL HEAVY AND RIGHT LIGHT;So;0;ON;;;;;N;FORMS VERTICAL HEAVY AND RIGHT LIGHT;;;; 2521;BOX DRAWINGS DOWN LIGHT AND RIGHT UP HEAVY;So;0;ON;;;;;N;FORMS DOWN LIGHT AND RIGHT UP HEAVY;;;; 2522;BOX DRAWINGS UP LIGHT AND RIGHT DOWN HEAVY;So;0;ON;;;;;N;FORMS UP LIGHT AND RIGHT DOWN HEAVY;;;; 2523;BOX DRAWINGS HEAVY VERTICAL AND RIGHT;So;0;ON;;;;;N;FORMS HEAVY VERTICAL AND RIGHT;;;; 2524;BOX DRAWINGS LIGHT VERTICAL AND LEFT;So;0;ON;;;;;N;FORMS LIGHT VERTICAL AND LEFT;;;; 2525;BOX DRAWINGS VERTICAL LIGHT AND LEFT HEAVY;So;0;ON;;;;;N;FORMS VERTICAL LIGHT AND LEFT HEAVY;;;; 2526;BOX DRAWINGS UP HEAVY AND LEFT DOWN LIGHT;So;0;ON;;;;;N;FORMS UP HEAVY AND LEFT DOWN LIGHT;;;; 2527;BOX DRAWINGS DOWN HEAVY AND LEFT UP LIGHT;So;0;ON;;;;;N;FORMS DOWN HEAVY AND LEFT UP LIGHT;;;; 2528;BOX DRAWINGS VERTICAL HEAVY AND LEFT LIGHT;So;0;ON;;;;;N;FORMS VERTICAL HEAVY AND LEFT LIGHT;;;; 2529;BOX DRAWINGS DOWN LIGHT AND LEFT UP HEAVY;So;0;ON;;;;;N;FORMS DOWN LIGHT AND LEFT UP HEAVY;;;; 252A;BOX DRAWINGS UP LIGHT AND LEFT DOWN HEAVY;So;0;ON;;;;;N;FORMS UP LIGHT AND LEFT DOWN HEAVY;;;; 252B;BOX DRAWINGS HEAVY VERTICAL AND LEFT;So;0;ON;;;;;N;FORMS HEAVY VERTICAL AND LEFT;;;; 252C;BOX DRAWINGS LIGHT DOWN AND HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT DOWN AND HORIZONTAL;;;; 252D;BOX DRAWINGS LEFT HEAVY AND RIGHT DOWN LIGHT;So;0;ON;;;;;N;FORMS LEFT HEAVY AND RIGHT DOWN LIGHT;;;; 252E;BOX DRAWINGS RIGHT HEAVY AND LEFT DOWN LIGHT;So;0;ON;;;;;N;FORMS RIGHT HEAVY AND LEFT DOWN LIGHT;;;; 252F;BOX DRAWINGS DOWN LIGHT AND HORIZONTAL HEAVY;So;0;ON;;;;;N;FORMS DOWN LIGHT AND HORIZONTAL HEAVY;;;; 2530;BOX DRAWINGS DOWN HEAVY AND HORIZONTAL LIGHT;So;0;ON;;;;;N;FORMS DOWN HEAVY AND HORIZONTAL LIGHT;;;; 2531;BOX DRAWINGS RIGHT LIGHT AND LEFT DOWN HEAVY;So;0;ON;;;;;N;FORMS RIGHT LIGHT AND LEFT DOWN HEAVY;;;; 2532;BOX DRAWINGS LEFT LIGHT AND RIGHT DOWN HEAVY;So;0;ON;;;;;N;FORMS LEFT LIGHT AND RIGHT DOWN HEAVY;;;; 2533;BOX DRAWINGS HEAVY DOWN AND HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY DOWN AND HORIZONTAL;;;; 2534;BOX DRAWINGS LIGHT UP AND HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT UP AND HORIZONTAL;;;; 2535;BOX DRAWINGS LEFT HEAVY AND RIGHT UP LIGHT;So;0;ON;;;;;N;FORMS LEFT HEAVY AND RIGHT UP LIGHT;;;; 2536;BOX DRAWINGS RIGHT HEAVY AND LEFT UP LIGHT;So;0;ON;;;;;N;FORMS RIGHT HEAVY AND LEFT UP LIGHT;;;; 2537;BOX DRAWINGS UP LIGHT AND HORIZONTAL HEAVY;So;0;ON;;;;;N;FORMS UP LIGHT AND HORIZONTAL HEAVY;;;; 2538;BOX DRAWINGS UP HEAVY AND HORIZONTAL LIGHT;So;0;ON;;;;;N;FORMS UP HEAVY AND HORIZONTAL LIGHT;;;; 2539;BOX DRAWINGS RIGHT LIGHT AND LEFT UP HEAVY;So;0;ON;;;;;N;FORMS RIGHT LIGHT AND LEFT UP HEAVY;;;; 253A;BOX DRAWINGS LEFT LIGHT AND RIGHT UP HEAVY;So;0;ON;;;;;N;FORMS LEFT LIGHT AND RIGHT UP HEAVY;;;; 253B;BOX DRAWINGS HEAVY UP AND HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY UP AND HORIZONTAL;;;; 253C;BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT VERTICAL AND HORIZONTAL;;;; 253D;BOX DRAWINGS LEFT HEAVY AND RIGHT VERTICAL LIGHT;So;0;ON;;;;;N;FORMS LEFT HEAVY AND RIGHT VERTICAL LIGHT;;;; 253E;BOX DRAWINGS RIGHT HEAVY AND LEFT VERTICAL LIGHT;So;0;ON;;;;;N;FORMS RIGHT HEAVY AND LEFT VERTICAL LIGHT;;;; 253F;BOX DRAWINGS VERTICAL LIGHT AND HORIZONTAL HEAVY;So;0;ON;;;;;N;FORMS VERTICAL LIGHT AND HORIZONTAL HEAVY;;;; 2540;BOX DRAWINGS UP HEAVY AND DOWN HORIZONTAL LIGHT;So;0;ON;;;;;N;FORMS UP HEAVY AND DOWN HORIZONTAL LIGHT;;;; 2541;BOX DRAWINGS DOWN HEAVY AND UP HORIZONTAL LIGHT;So;0;ON;;;;;N;FORMS DOWN HEAVY AND UP HORIZONTAL LIGHT;;;; 2542;BOX DRAWINGS VERTICAL HEAVY AND HORIZONTAL LIGHT;So;0;ON;;;;;N;FORMS VERTICAL HEAVY AND HORIZONTAL LIGHT;;;; 2543;BOX DRAWINGS LEFT UP HEAVY AND RIGHT DOWN LIGHT;So;0;ON;;;;;N;FORMS LEFT UP HEAVY AND RIGHT DOWN LIGHT;;;; 2544;BOX DRAWINGS RIGHT UP HEAVY AND LEFT DOWN LIGHT;So;0;ON;;;;;N;FORMS RIGHT UP HEAVY AND LEFT DOWN LIGHT;;;; 2545;BOX DRAWINGS LEFT DOWN HEAVY AND RIGHT UP LIGHT;So;0;ON;;;;;N;FORMS LEFT DOWN HEAVY AND RIGHT UP LIGHT;;;; 2546;BOX DRAWINGS RIGHT DOWN HEAVY AND LEFT UP LIGHT;So;0;ON;;;;;N;FORMS RIGHT DOWN HEAVY AND LEFT UP LIGHT;;;; 2547;BOX DRAWINGS DOWN LIGHT AND UP HORIZONTAL HEAVY;So;0;ON;;;;;N;FORMS DOWN LIGHT AND UP HORIZONTAL HEAVY;;;; 2548;BOX DRAWINGS UP LIGHT AND DOWN HORIZONTAL HEAVY;So;0;ON;;;;;N;FORMS UP LIGHT AND DOWN HORIZONTAL HEAVY;;;; 2549;BOX DRAWINGS RIGHT LIGHT AND LEFT VERTICAL HEAVY;So;0;ON;;;;;N;FORMS RIGHT LIGHT AND LEFT VERTICAL HEAVY;;;; 254A;BOX DRAWINGS LEFT LIGHT AND RIGHT VERTICAL HEAVY;So;0;ON;;;;;N;FORMS LEFT LIGHT AND RIGHT VERTICAL HEAVY;;;; 254B;BOX DRAWINGS HEAVY VERTICAL AND HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY VERTICAL AND HORIZONTAL;;;; 254C;BOX DRAWINGS LIGHT DOUBLE DASH HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT DOUBLE DASH HORIZONTAL;;;; 254D;BOX DRAWINGS HEAVY DOUBLE DASH HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY DOUBLE DASH HORIZONTAL;;;; 254E;BOX DRAWINGS LIGHT DOUBLE DASH VERTICAL;So;0;ON;;;;;N;FORMS LIGHT DOUBLE DASH VERTICAL;;;; 254F;BOX DRAWINGS HEAVY DOUBLE DASH VERTICAL;So;0;ON;;;;;N;FORMS HEAVY DOUBLE DASH VERTICAL;;;; 2550;BOX DRAWINGS DOUBLE HORIZONTAL;So;0;ON;;;;;N;FORMS DOUBLE HORIZONTAL;;;; 2551;BOX DRAWINGS DOUBLE VERTICAL;So;0;ON;;;;;N;FORMS DOUBLE VERTICAL;;;; 2552;BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE;So;0;ON;;;;;N;FORMS DOWN SINGLE AND RIGHT DOUBLE;;;; 2553;BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE;So;0;ON;;;;;N;FORMS DOWN DOUBLE AND RIGHT SINGLE;;;; 2554;BOX DRAWINGS DOUBLE DOWN AND RIGHT;So;0;ON;;;;;N;FORMS DOUBLE DOWN AND RIGHT;;;; 2555;BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE;So;0;ON;;;;;N;FORMS DOWN SINGLE AND LEFT DOUBLE;;;; 2556;BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE;So;0;ON;;;;;N;FORMS DOWN DOUBLE AND LEFT SINGLE;;;; 2557;BOX DRAWINGS DOUBLE DOWN AND LEFT;So;0;ON;;;;;N;FORMS DOUBLE DOWN AND LEFT;;;; 2558;BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE;So;0;ON;;;;;N;FORMS UP SINGLE AND RIGHT DOUBLE;;;; 2559;BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE;So;0;ON;;;;;N;FORMS UP DOUBLE AND RIGHT SINGLE;;;; 255A;BOX DRAWINGS DOUBLE UP AND RIGHT;So;0;ON;;;;;N;FORMS DOUBLE UP AND RIGHT;;;; 255B;BOX DRAWINGS UP SINGLE AND LEFT DOUBLE;So;0;ON;;;;;N;FORMS UP SINGLE AND LEFT DOUBLE;;;; 255C;BOX DRAWINGS UP DOUBLE AND LEFT SINGLE;So;0;ON;;;;;N;FORMS UP DOUBLE AND LEFT SINGLE;;;; 255D;BOX DRAWINGS DOUBLE UP AND LEFT;So;0;ON;;;;;N;FORMS DOUBLE UP AND LEFT;;;; 255E;BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE;So;0;ON;;;;;N;FORMS VERTICAL SINGLE AND RIGHT DOUBLE;;;; 255F;BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE;So;0;ON;;;;;N;FORMS VERTICAL DOUBLE AND RIGHT SINGLE;;;; 2560;BOX DRAWINGS DOUBLE VERTICAL AND RIGHT;So;0;ON;;;;;N;FORMS DOUBLE VERTICAL AND RIGHT;;;; 2561;BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE;So;0;ON;;;;;N;FORMS VERTICAL SINGLE AND LEFT DOUBLE;;;; 2562;BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE;So;0;ON;;;;;N;FORMS VERTICAL DOUBLE AND LEFT SINGLE;;;; 2563;BOX DRAWINGS DOUBLE VERTICAL AND LEFT;So;0;ON;;;;;N;FORMS DOUBLE VERTICAL AND LEFT;;;; 2564;BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE;So;0;ON;;;;;N;FORMS DOWN SINGLE AND HORIZONTAL DOUBLE;;;; 2565;BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE;So;0;ON;;;;;N;FORMS DOWN DOUBLE AND HORIZONTAL SINGLE;;;; 2566;BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL;So;0;ON;;;;;N;FORMS DOUBLE DOWN AND HORIZONTAL;;;; 2567;BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE;So;0;ON;;;;;N;FORMS UP SINGLE AND HORIZONTAL DOUBLE;;;; 2568;BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE;So;0;ON;;;;;N;FORMS UP DOUBLE AND HORIZONTAL SINGLE;;;; 2569;BOX DRAWINGS DOUBLE UP AND HORIZONTAL;So;0;ON;;;;;N;FORMS DOUBLE UP AND HORIZONTAL;;;; 256A;BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE;So;0;ON;;;;;N;FORMS VERTICAL SINGLE AND HORIZONTAL DOUBLE;;;; 256B;BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE;So;0;ON;;;;;N;FORMS VERTICAL DOUBLE AND HORIZONTAL SINGLE;;;; 256C;BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL;So;0;ON;;;;;N;FORMS DOUBLE VERTICAL AND HORIZONTAL;;;; 256D;BOX DRAWINGS LIGHT ARC DOWN AND RIGHT;So;0;ON;;;;;N;FORMS LIGHT ARC DOWN AND RIGHT;;;; 256E;BOX DRAWINGS LIGHT ARC DOWN AND LEFT;So;0;ON;;;;;N;FORMS LIGHT ARC DOWN AND LEFT;;;; 256F;BOX DRAWINGS LIGHT ARC UP AND LEFT;So;0;ON;;;;;N;FORMS LIGHT ARC UP AND LEFT;;;; 2570;BOX DRAWINGS LIGHT ARC UP AND RIGHT;So;0;ON;;;;;N;FORMS LIGHT ARC UP AND RIGHT;;;; 2571;BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT;So;0;ON;;;;;N;FORMS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT;;;; 2572;BOX DRAWINGS LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT;So;0;ON;;;;;N;FORMS LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT;;;; 2573;BOX DRAWINGS LIGHT DIAGONAL CROSS;So;0;ON;;;;;N;FORMS LIGHT DIAGONAL CROSS;;;; 2574;BOX DRAWINGS LIGHT LEFT;So;0;ON;;;;;N;FORMS LIGHT LEFT;;;; 2575;BOX DRAWINGS LIGHT UP;So;0;ON;;;;;N;FORMS LIGHT UP;;;; 2576;BOX DRAWINGS LIGHT RIGHT;So;0;ON;;;;;N;FORMS LIGHT RIGHT;;;; 2577;BOX DRAWINGS LIGHT DOWN;So;0;ON;;;;;N;FORMS LIGHT DOWN;;;; 2578;BOX DRAWINGS HEAVY LEFT;So;0;ON;;;;;N;FORMS HEAVY LEFT;;;; 2579;BOX DRAWINGS HEAVY UP;So;0;ON;;;;;N;FORMS HEAVY UP;;;; 257A;BOX DRAWINGS HEAVY RIGHT;So;0;ON;;;;;N;FORMS HEAVY RIGHT;;;; 257B;BOX DRAWINGS HEAVY DOWN;So;0;ON;;;;;N;FORMS HEAVY DOWN;;;; 257C;BOX DRAWINGS LIGHT LEFT AND HEAVY RIGHT;So;0;ON;;;;;N;FORMS LIGHT LEFT AND HEAVY RIGHT;;;; 257D;BOX DRAWINGS LIGHT UP AND HEAVY DOWN;So;0;ON;;;;;N;FORMS LIGHT UP AND HEAVY DOWN;;;; 257E;BOX DRAWINGS HEAVY LEFT AND LIGHT RIGHT;So;0;ON;;;;;N;FORMS HEAVY LEFT AND LIGHT RIGHT;;;; 257F;BOX DRAWINGS HEAVY UP AND LIGHT DOWN;So;0;ON;;;;;N;FORMS HEAVY UP AND LIGHT DOWN;;;; 2580;UPPER HALF BLOCK;So;0;ON;;;;;N;;;;; 2581;LOWER ONE EIGHTH BLOCK;So;0;ON;;;;;N;;;;; 2582;LOWER ONE QUARTER BLOCK;So;0;ON;;;;;N;;;;; 2583;LOWER THREE EIGHTHS BLOCK;So;0;ON;;;;;N;;;;; 2584;LOWER HALF BLOCK;So;0;ON;;;;;N;;;;; 2585;LOWER FIVE EIGHTHS BLOCK;So;0;ON;;;;;N;;;;; 2586;LOWER THREE QUARTERS BLOCK;So;0;ON;;;;;N;LOWER THREE QUARTER BLOCK;;;; 2587;LOWER SEVEN EIGHTHS BLOCK;So;0;ON;;;;;N;;;;; 2588;FULL BLOCK;So;0;ON;;;;;N;;;;; 2589;LEFT SEVEN EIGHTHS BLOCK;So;0;ON;;;;;N;;;;; 258A;LEFT THREE QUARTERS BLOCK;So;0;ON;;;;;N;LEFT THREE QUARTER BLOCK;;;; 258B;LEFT FIVE EIGHTHS BLOCK;So;0;ON;;;;;N;;;;; 258C;LEFT HALF BLOCK;So;0;ON;;;;;N;;;;; 258D;LEFT THREE EIGHTHS BLOCK;So;0;ON;;;;;N;;;;; 258E;LEFT ONE QUARTER BLOCK;So;0;ON;;;;;N;;;;; 258F;LEFT ONE EIGHTH BLOCK;So;0;ON;;;;;N;;;;; 2590;RIGHT HALF BLOCK;So;0;ON;;;;;N;;;;; 2591;LIGHT SHADE;So;0;ON;;;;;N;;;;; 2592;MEDIUM SHADE;So;0;ON;;;;;N;;;;; 2593;DARK SHADE;So;0;ON;;;;;N;;;;; 2594;UPPER ONE EIGHTH BLOCK;So;0;ON;;;;;N;;;;; 2595;RIGHT ONE EIGHTH BLOCK;So;0;ON;;;;;N;;;;; 2596;QUADRANT LOWER LEFT;So;0;ON;;;;;N;;;;; 2597;QUADRANT LOWER RIGHT;So;0;ON;;;;;N;;;;; 2598;QUADRANT UPPER LEFT;So;0;ON;;;;;N;;;;; 2599;QUADRANT UPPER LEFT AND LOWER LEFT AND LOWER RIGHT;So;0;ON;;;;;N;;;;; 259A;QUADRANT UPPER LEFT AND LOWER RIGHT;So;0;ON;;;;;N;;;;; 259B;QUADRANT UPPER LEFT AND UPPER RIGHT AND LOWER LEFT;So;0;ON;;;;;N;;;;; 259C;QUADRANT UPPER LEFT AND UPPER RIGHT AND LOWER RIGHT;So;0;ON;;;;;N;;;;; 259D;QUADRANT UPPER RIGHT;So;0;ON;;;;;N;;;;; 259E;QUADRANT UPPER RIGHT AND LOWER LEFT;So;0;ON;;;;;N;;;;; 259F;QUADRANT UPPER RIGHT AND LOWER LEFT AND LOWER RIGHT;So;0;ON;;;;;N;;;;; 25A0;BLACK SQUARE;So;0;ON;;;;;N;;;;; 25A1;WHITE SQUARE;So;0;ON;;;;;N;;;;; 25A2;WHITE SQUARE WITH ROUNDED CORNERS;So;0;ON;;;;;N;;;;; 25A3;WHITE SQUARE CONTAINING BLACK SMALL SQUARE;So;0;ON;;;;;N;;;;; 25A4;SQUARE WITH HORIZONTAL FILL;So;0;ON;;;;;N;;;;; 25A5;SQUARE WITH VERTICAL FILL;So;0;ON;;;;;N;;;;; 25A6;SQUARE WITH ORTHOGONAL CROSSHATCH FILL;So;0;ON;;;;;N;;;;; 25A7;SQUARE WITH UPPER LEFT TO LOWER RIGHT FILL;So;0;ON;;;;;N;;;;; 25A8;SQUARE WITH UPPER RIGHT TO LOWER LEFT FILL;So;0;ON;;;;;N;;;;; 25A9;SQUARE WITH DIAGONAL CROSSHATCH FILL;So;0;ON;;;;;N;;;;; 25AA;BLACK SMALL SQUARE;So;0;ON;;;;;N;;;;; 25AB;WHITE SMALL SQUARE;So;0;ON;;;;;N;;;;; 25AC;BLACK RECTANGLE;So;0;ON;;;;;N;;;;; 25AD;WHITE RECTANGLE;So;0;ON;;;;;N;;;;; 25AE;BLACK VERTICAL RECTANGLE;So;0;ON;;;;;N;;;;; 25AF;WHITE VERTICAL RECTANGLE;So;0;ON;;;;;N;;;;; 25B0;BLACK PARALLELOGRAM;So;0;ON;;;;;N;;;;; 25B1;WHITE PARALLELOGRAM;So;0;ON;;;;;N;;;;; 25B2;BLACK UP-POINTING TRIANGLE;So;0;ON;;;;;N;BLACK UP POINTING TRIANGLE;;;; 25B3;WHITE UP-POINTING TRIANGLE;So;0;ON;;;;;N;WHITE UP POINTING TRIANGLE;;;; 25B4;BLACK UP-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;BLACK UP POINTING SMALL TRIANGLE;;;; 25B5;WHITE UP-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;WHITE UP POINTING SMALL TRIANGLE;;;; 25B6;BLACK RIGHT-POINTING TRIANGLE;So;0;ON;;;;;N;BLACK RIGHT POINTING TRIANGLE;;;; 25B7;WHITE RIGHT-POINTING TRIANGLE;Sm;0;ON;;;;;N;WHITE RIGHT POINTING TRIANGLE;;;; 25B8;BLACK RIGHT-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;BLACK RIGHT POINTING SMALL TRIANGLE;;;; 25B9;WHITE RIGHT-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;WHITE RIGHT POINTING SMALL TRIANGLE;;;; 25BA;BLACK RIGHT-POINTING POINTER;So;0;ON;;;;;N;BLACK RIGHT POINTING POINTER;;;; 25BB;WHITE RIGHT-POINTING POINTER;So;0;ON;;;;;N;WHITE RIGHT POINTING POINTER;;;; 25BC;BLACK DOWN-POINTING TRIANGLE;So;0;ON;;;;;N;BLACK DOWN POINTING TRIANGLE;;;; 25BD;WHITE DOWN-POINTING TRIANGLE;So;0;ON;;;;;N;WHITE DOWN POINTING TRIANGLE;;;; 25BE;BLACK DOWN-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;BLACK DOWN POINTING SMALL TRIANGLE;;;; 25BF;WHITE DOWN-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;WHITE DOWN POINTING SMALL TRIANGLE;;;; 25C0;BLACK LEFT-POINTING TRIANGLE;So;0;ON;;;;;N;BLACK LEFT POINTING TRIANGLE;;;; 25C1;WHITE LEFT-POINTING TRIANGLE;Sm;0;ON;;;;;N;WHITE LEFT POINTING TRIANGLE;;;; 25C2;BLACK LEFT-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;BLACK LEFT POINTING SMALL TRIANGLE;;;; 25C3;WHITE LEFT-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;WHITE LEFT POINTING SMALL TRIANGLE;;;; 25C4;BLACK LEFT-POINTING POINTER;So;0;ON;;;;;N;BLACK LEFT POINTING POINTER;;;; 25C5;WHITE LEFT-POINTING POINTER;So;0;ON;;;;;N;WHITE LEFT POINTING POINTER;;;; 25C6;BLACK DIAMOND;So;0;ON;;;;;N;;;;; 25C7;WHITE DIAMOND;So;0;ON;;;;;N;;;;; 25C8;WHITE DIAMOND CONTAINING BLACK SMALL DIAMOND;So;0;ON;;;;;N;;;;; 25C9;FISHEYE;So;0;ON;;;;;N;;;;; 25CA;LOZENGE;So;0;ON;;;;;N;;;;; 25CB;WHITE CIRCLE;So;0;ON;;;;;N;;;;; 25CC;DOTTED CIRCLE;So;0;ON;;;;;N;;;;; 25CD;CIRCLE WITH VERTICAL FILL;So;0;ON;;;;;N;;;;; 25CE;BULLSEYE;So;0;ON;;;;;N;;;;; 25CF;BLACK CIRCLE;So;0;ON;;;;;N;;;;; 25D0;CIRCLE WITH LEFT HALF BLACK;So;0;ON;;;;;N;;;;; 25D1;CIRCLE WITH RIGHT HALF BLACK;So;0;ON;;;;;N;;;;; 25D2;CIRCLE WITH LOWER HALF BLACK;So;0;ON;;;;;N;;;;; 25D3;CIRCLE WITH UPPER HALF BLACK;So;0;ON;;;;;N;;;;; 25D4;CIRCLE WITH UPPER RIGHT QUADRANT BLACK;So;0;ON;;;;;N;;;;; 25D5;CIRCLE WITH ALL BUT UPPER LEFT QUADRANT BLACK;So;0;ON;;;;;N;;;;; 25D6;LEFT HALF BLACK CIRCLE;So;0;ON;;;;;N;;;;; 25D7;RIGHT HALF BLACK CIRCLE;So;0;ON;;;;;N;;;;; 25D8;INVERSE BULLET;So;0;ON;;;;;N;;;;; 25D9;INVERSE WHITE CIRCLE;So;0;ON;;;;;N;;;;; 25DA;UPPER HALF INVERSE WHITE CIRCLE;So;0;ON;;;;;N;;;;; 25DB;LOWER HALF INVERSE WHITE CIRCLE;So;0;ON;;;;;N;;;;; 25DC;UPPER LEFT QUADRANT CIRCULAR ARC;So;0;ON;;;;;N;;;;; 25DD;UPPER RIGHT QUADRANT CIRCULAR ARC;So;0;ON;;;;;N;;;;; 25DE;LOWER RIGHT QUADRANT CIRCULAR ARC;So;0;ON;;;;;N;;;;; 25DF;LOWER LEFT QUADRANT CIRCULAR ARC;So;0;ON;;;;;N;;;;; 25E0;UPPER HALF CIRCLE;So;0;ON;;;;;N;;;;; 25E1;LOWER HALF CIRCLE;So;0;ON;;;;;N;;;;; 25E2;BLACK LOWER RIGHT TRIANGLE;So;0;ON;;;;;N;;;;; 25E3;BLACK LOWER LEFT TRIANGLE;So;0;ON;;;;;N;;;;; 25E4;BLACK UPPER LEFT TRIANGLE;So;0;ON;;;;;N;;;;; 25E5;BLACK UPPER RIGHT TRIANGLE;So;0;ON;;;;;N;;;;; 25E6;WHITE BULLET;So;0;ON;;;;;N;;;;; 25E7;SQUARE WITH LEFT HALF BLACK;So;0;ON;;;;;N;;;;; 25E8;SQUARE WITH RIGHT HALF BLACK;So;0;ON;;;;;N;;;;; 25E9;SQUARE WITH UPPER LEFT DIAGONAL HALF BLACK;So;0;ON;;;;;N;;;;; 25EA;SQUARE WITH LOWER RIGHT DIAGONAL HALF BLACK;So;0;ON;;;;;N;;;;; 25EB;WHITE SQUARE WITH VERTICAL BISECTING LINE;So;0;ON;;;;;N;;;;; 25EC;WHITE UP-POINTING TRIANGLE WITH DOT;So;0;ON;;;;;N;WHITE UP POINTING TRIANGLE WITH DOT;;;; 25ED;UP-POINTING TRIANGLE WITH LEFT HALF BLACK;So;0;ON;;;;;N;UP POINTING TRIANGLE WITH LEFT HALF BLACK;;;; 25EE;UP-POINTING TRIANGLE WITH RIGHT HALF BLACK;So;0;ON;;;;;N;UP POINTING TRIANGLE WITH RIGHT HALF BLACK;;;; 25EF;LARGE CIRCLE;So;0;ON;;;;;N;;;;; 25F0;WHITE SQUARE WITH UPPER LEFT QUADRANT;So;0;ON;;;;;N;;;;; 25F1;WHITE SQUARE WITH LOWER LEFT QUADRANT;So;0;ON;;;;;N;;;;; 25F2;WHITE SQUARE WITH LOWER RIGHT QUADRANT;So;0;ON;;;;;N;;;;; 25F3;WHITE SQUARE WITH UPPER RIGHT QUADRANT;So;0;ON;;;;;N;;;;; 25F4;WHITE CIRCLE WITH UPPER LEFT QUADRANT;So;0;ON;;;;;N;;;;; 25F5;WHITE CIRCLE WITH LOWER LEFT QUADRANT;So;0;ON;;;;;N;;;;; 25F6;WHITE CIRCLE WITH LOWER RIGHT QUADRANT;So;0;ON;;;;;N;;;;; 25F7;WHITE CIRCLE WITH UPPER RIGHT QUADRANT;So;0;ON;;;;;N;;;;; 25F8;UPPER LEFT TRIANGLE;Sm;0;ON;;;;;N;;;;; 25F9;UPPER RIGHT TRIANGLE;Sm;0;ON;;;;;N;;;;; 25FA;LOWER LEFT TRIANGLE;Sm;0;ON;;;;;N;;;;; 25FB;WHITE MEDIUM SQUARE;Sm;0;ON;;;;;N;;;;; 25FC;BLACK MEDIUM SQUARE;Sm;0;ON;;;;;N;;;;; 25FD;WHITE MEDIUM SMALL SQUARE;Sm;0;ON;;;;;N;;;;; 25FE;BLACK MEDIUM SMALL SQUARE;Sm;0;ON;;;;;N;;;;; 25FF;LOWER RIGHT TRIANGLE;Sm;0;ON;;;;;N;;;;; 2600;BLACK SUN WITH RAYS;So;0;ON;;;;;N;;;;; 2601;CLOUD;So;0;ON;;;;;N;;;;; 2602;UMBRELLA;So;0;ON;;;;;N;;;;; 2603;SNOWMAN;So;0;ON;;;;;N;;;;; 2604;COMET;So;0;ON;;;;;N;;;;; 2605;BLACK STAR;So;0;ON;;;;;N;;;;; 2606;WHITE STAR;So;0;ON;;;;;N;;;;; 2607;LIGHTNING;So;0;ON;;;;;N;;;;; 2608;THUNDERSTORM;So;0;ON;;;;;N;;;;; 2609;SUN;So;0;ON;;;;;N;;;;; 260A;ASCENDING NODE;So;0;ON;;;;;N;;;;; 260B;DESCENDING NODE;So;0;ON;;;;;N;;;;; 260C;CONJUNCTION;So;0;ON;;;;;N;;;;; 260D;OPPOSITION;So;0;ON;;;;;N;;;;; 260E;BLACK TELEPHONE;So;0;ON;;;;;N;;;;; 260F;WHITE TELEPHONE;So;0;ON;;;;;N;;;;; 2610;BALLOT BOX;So;0;ON;;;;;N;;;;; 2611;BALLOT BOX WITH CHECK;So;0;ON;;;;;N;;;;; 2612;BALLOT BOX WITH X;So;0;ON;;;;;N;;;;; 2613;SALTIRE;So;0;ON;;;;;N;;;;; 2614;UMBRELLA WITH RAIN DROPS;So;0;ON;;;;;N;;;;; 2615;HOT BEVERAGE;So;0;ON;;;;;N;;;;; 2616;WHITE SHOGI PIECE;So;0;ON;;;;;N;;;;; 2617;BLACK SHOGI PIECE;So;0;ON;;;;;N;;;;; 2618;SHAMROCK;So;0;ON;;;;;N;;;;; 2619;REVERSED ROTATED FLORAL HEART BULLET;So;0;ON;;;;;N;;;;; 261A;BLACK LEFT POINTING INDEX;So;0;ON;;;;;N;;;;; 261B;BLACK RIGHT POINTING INDEX;So;0;ON;;;;;N;;;;; 261C;WHITE LEFT POINTING INDEX;So;0;ON;;;;;N;;;;; 261D;WHITE UP POINTING INDEX;So;0;ON;;;;;N;;;;; 261E;WHITE RIGHT POINTING INDEX;So;0;ON;;;;;N;;;;; 261F;WHITE DOWN POINTING INDEX;So;0;ON;;;;;N;;;;; 2620;SKULL AND CROSSBONES;So;0;ON;;;;;N;;;;; 2621;CAUTION SIGN;So;0;ON;;;;;N;;;;; 2622;RADIOACTIVE SIGN;So;0;ON;;;;;N;;;;; 2623;BIOHAZARD SIGN;So;0;ON;;;;;N;;;;; 2624;CADUCEUS;So;0;ON;;;;;N;;;;; 2625;ANKH;So;0;ON;;;;;N;;;;; 2626;ORTHODOX CROSS;So;0;ON;;;;;N;;;;; 2627;CHI RHO;So;0;ON;;;;;N;;;;; 2628;CROSS OF LORRAINE;So;0;ON;;;;;N;;;;; 2629;CROSS OF JERUSALEM;So;0;ON;;;;;N;;;;; 262A;STAR AND CRESCENT;So;0;ON;;;;;N;;;;; 262B;FARSI SYMBOL;So;0;ON;;;;;N;SYMBOL OF IRAN;;;; 262C;ADI SHAKTI;So;0;ON;;;;;N;;;;; 262D;HAMMER AND SICKLE;So;0;ON;;;;;N;;;;; 262E;PEACE SYMBOL;So;0;ON;;;;;N;;;;; 262F;YIN YANG;So;0;ON;;;;;N;;;;; 2630;TRIGRAM FOR HEAVEN;So;0;ON;;;;;N;;;;; 2631;TRIGRAM FOR LAKE;So;0;ON;;;;;N;;;;; 2632;TRIGRAM FOR FIRE;So;0;ON;;;;;N;;;;; 2633;TRIGRAM FOR THUNDER;So;0;ON;;;;;N;;;;; 2634;TRIGRAM FOR WIND;So;0;ON;;;;;N;;;;; 2635;TRIGRAM FOR WATER;So;0;ON;;;;;N;;;;; 2636;TRIGRAM FOR MOUNTAIN;So;0;ON;;;;;N;;;;; 2637;TRIGRAM FOR EARTH;So;0;ON;;;;;N;;;;; 2638;WHEEL OF DHARMA;So;0;ON;;;;;N;;;;; 2639;WHITE FROWNING FACE;So;0;ON;;;;;N;;;;; 263A;WHITE SMILING FACE;So;0;ON;;;;;N;;;;; 263B;BLACK SMILING FACE;So;0;ON;;;;;N;;;;; 263C;WHITE SUN WITH RAYS;So;0;ON;;;;;N;;;;; 263D;FIRST QUARTER MOON;So;0;ON;;;;;N;;;;; 263E;LAST QUARTER MOON;So;0;ON;;;;;N;;;;; 263F;MERCURY;So;0;ON;;;;;N;;;;; 2640;FEMALE SIGN;So;0;ON;;;;;N;;;;; 2641;EARTH;So;0;ON;;;;;N;;;;; 2642;MALE SIGN;So;0;ON;;;;;N;;;;; 2643;JUPITER;So;0;ON;;;;;N;;;;; 2644;SATURN;So;0;ON;;;;;N;;;;; 2645;URANUS;So;0;ON;;;;;N;;;;; 2646;NEPTUNE;So;0;ON;;;;;N;;;;; 2647;PLUTO;So;0;ON;;;;;N;;;;; 2648;ARIES;So;0;ON;;;;;N;;;;; 2649;TAURUS;So;0;ON;;;;;N;;;;; 264A;GEMINI;So;0;ON;;;;;N;;;;; 264B;CANCER;So;0;ON;;;;;N;;;;; 264C;LEO;So;0;ON;;;;;N;;;;; 264D;VIRGO;So;0;ON;;;;;N;;;;; 264E;LIBRA;So;0;ON;;;;;N;;;;; 264F;SCORPIUS;So;0;ON;;;;;N;;;;; 2650;SAGITTARIUS;So;0;ON;;;;;N;;;;; 2651;CAPRICORN;So;0;ON;;;;;N;;;;; 2652;AQUARIUS;So;0;ON;;;;;N;;;;; 2653;PISCES;So;0;ON;;;;;N;;;;; 2654;WHITE CHESS KING;So;0;ON;;;;;N;;;;; 2655;WHITE CHESS QUEEN;So;0;ON;;;;;N;;;;; 2656;WHITE CHESS ROOK;So;0;ON;;;;;N;;;;; 2657;WHITE CHESS BISHOP;So;0;ON;;;;;N;;;;; 2658;WHITE CHESS KNIGHT;So;0;ON;;;;;N;;;;; 2659;WHITE CHESS PAWN;So;0;ON;;;;;N;;;;; 265A;BLACK CHESS KING;So;0;ON;;;;;N;;;;; 265B;BLACK CHESS QUEEN;So;0;ON;;;;;N;;;;; 265C;BLACK CHESS ROOK;So;0;ON;;;;;N;;;;; 265D;BLACK CHESS BISHOP;So;0;ON;;;;;N;;;;; 265E;BLACK CHESS KNIGHT;So;0;ON;;;;;N;;;;; 265F;BLACK CHESS PAWN;So;0;ON;;;;;N;;;;; 2660;BLACK SPADE SUIT;So;0;ON;;;;;N;;;;; 2661;WHITE HEART SUIT;So;0;ON;;;;;N;;;;; 2662;WHITE DIAMOND SUIT;So;0;ON;;;;;N;;;;; 2663;BLACK CLUB SUIT;So;0;ON;;;;;N;;;;; 2664;WHITE SPADE SUIT;So;0;ON;;;;;N;;;;; 2665;BLACK HEART SUIT;So;0;ON;;;;;N;;;;; 2666;BLACK DIAMOND SUIT;So;0;ON;;;;;N;;;;; 2667;WHITE CLUB SUIT;So;0;ON;;;;;N;;;;; 2668;HOT SPRINGS;So;0;ON;;;;;N;;;;; 2669;QUARTER NOTE;So;0;ON;;;;;N;;;;; 266A;EIGHTH NOTE;So;0;ON;;;;;N;;;;; 266B;BEAMED EIGHTH NOTES;So;0;ON;;;;;N;BARRED EIGHTH NOTES;;;; 266C;BEAMED SIXTEENTH NOTES;So;0;ON;;;;;N;BARRED SIXTEENTH NOTES;;;; 266D;MUSIC FLAT SIGN;So;0;ON;;;;;N;FLAT;;;; 266E;MUSIC NATURAL SIGN;So;0;ON;;;;;N;NATURAL;;;; 266F;MUSIC SHARP SIGN;Sm;0;ON;;;;;N;SHARP;;;; 2670;WEST SYRIAC CROSS;So;0;ON;;;;;N;;;;; 2671;EAST SYRIAC CROSS;So;0;ON;;;;;N;;;;; 2672;UNIVERSAL RECYCLING SYMBOL;So;0;ON;;;;;N;;;;; 2673;RECYCLING SYMBOL FOR TYPE-1 PLASTICS;So;0;ON;;;;;N;;;;; 2674;RECYCLING SYMBOL FOR TYPE-2 PLASTICS;So;0;ON;;;;;N;;;;; 2675;RECYCLING SYMBOL FOR TYPE-3 PLASTICS;So;0;ON;;;;;N;;;;; 2676;RECYCLING SYMBOL FOR TYPE-4 PLASTICS;So;0;ON;;;;;N;;;;; 2677;RECYCLING SYMBOL FOR TYPE-5 PLASTICS;So;0;ON;;;;;N;;;;; 2678;RECYCLING SYMBOL FOR TYPE-6 PLASTICS;So;0;ON;;;;;N;;;;; 2679;RECYCLING SYMBOL FOR TYPE-7 PLASTICS;So;0;ON;;;;;N;;;;; 267A;RECYCLING SYMBOL FOR GENERIC MATERIALS;So;0;ON;;;;;N;;;;; 267B;BLACK UNIVERSAL RECYCLING SYMBOL;So;0;ON;;;;;N;;;;; 267C;RECYCLED PAPER SYMBOL;So;0;ON;;;;;N;;;;; 267D;PARTIALLY-RECYCLED PAPER SYMBOL;So;0;ON;;;;;N;;;;; 267E;PERMANENT PAPER SIGN;So;0;ON;;;;;N;;;;; 267F;WHEELCHAIR SYMBOL;So;0;ON;;;;;N;;;;; 2680;DIE FACE-1;So;0;ON;;;;;N;;;;; 2681;DIE FACE-2;So;0;ON;;;;;N;;;;; 2682;DIE FACE-3;So;0;ON;;;;;N;;;;; 2683;DIE FACE-4;So;0;ON;;;;;N;;;;; 2684;DIE FACE-5;So;0;ON;;;;;N;;;;; 2685;DIE FACE-6;So;0;ON;;;;;N;;;;; 2686;WHITE CIRCLE WITH DOT RIGHT;So;0;ON;;;;;N;;;;; 2687;WHITE CIRCLE WITH TWO DOTS;So;0;ON;;;;;N;;;;; 2688;BLACK CIRCLE WITH WHITE DOT RIGHT;So;0;ON;;;;;N;;;;; 2689;BLACK CIRCLE WITH TWO WHITE DOTS;So;0;ON;;;;;N;;;;; 268A;MONOGRAM FOR YANG;So;0;ON;;;;;N;;;;; 268B;MONOGRAM FOR YIN;So;0;ON;;;;;N;;;;; 268C;DIGRAM FOR GREATER YANG;So;0;ON;;;;;N;;;;; 268D;DIGRAM FOR LESSER YIN;So;0;ON;;;;;N;;;;; 268E;DIGRAM FOR LESSER YANG;So;0;ON;;;;;N;;;;; 268F;DIGRAM FOR GREATER YIN;So;0;ON;;;;;N;;;;; 2690;WHITE FLAG;So;0;ON;;;;;N;;;;; 2691;BLACK FLAG;So;0;ON;;;;;N;;;;; 2692;HAMMER AND PICK;So;0;ON;;;;;N;;;;; 2693;ANCHOR;So;0;ON;;;;;N;;;;; 2694;CROSSED SWORDS;So;0;ON;;;;;N;;;;; 2695;STAFF OF AESCULAPIUS;So;0;ON;;;;;N;;;;; 2696;SCALES;So;0;ON;;;;;N;;;;; 2697;ALEMBIC;So;0;ON;;;;;N;;;;; 2698;FLOWER;So;0;ON;;;;;N;;;;; 2699;GEAR;So;0;ON;;;;;N;;;;; 269A;STAFF OF HERMES;So;0;ON;;;;;N;;;;; 269B;ATOM SYMBOL;So;0;ON;;;;;N;;;;; 269C;FLEUR-DE-LIS;So;0;ON;;;;;N;;;;; 269D;OUTLINED WHITE STAR;So;0;ON;;;;;N;;;;; 269E;THREE LINES CONVERGING RIGHT;So;0;ON;;;;;N;;;;; 269F;THREE LINES CONVERGING LEFT;So;0;ON;;;;;N;;;;; 26A0;WARNING SIGN;So;0;ON;;;;;N;;;;; 26A1;HIGH VOLTAGE SIGN;So;0;ON;;;;;N;;;;; 26A2;DOUBLED FEMALE SIGN;So;0;ON;;;;;N;;;;; 26A3;DOUBLED MALE SIGN;So;0;ON;;;;;N;;;;; 26A4;INTERLOCKED FEMALE AND MALE SIGN;So;0;ON;;;;;N;;;;; 26A5;MALE AND FEMALE SIGN;So;0;ON;;;;;N;;;;; 26A6;MALE WITH STROKE SIGN;So;0;ON;;;;;N;;;;; 26A7;MALE WITH STROKE AND MALE AND FEMALE SIGN;So;0;ON;;;;;N;;;;; 26A8;VERTICAL MALE WITH STROKE SIGN;So;0;ON;;;;;N;;;;; 26A9;HORIZONTAL MALE WITH STROKE SIGN;So;0;ON;;;;;N;;;;; 26AA;MEDIUM WHITE CIRCLE;So;0;ON;;;;;N;;;;; 26AB;MEDIUM BLACK CIRCLE;So;0;ON;;;;;N;;;;; 26AC;MEDIUM SMALL WHITE CIRCLE;So;0;L;;;;;N;;;;; 26AD;MARRIAGE SYMBOL;So;0;ON;;;;;N;;;;; 26AE;DIVORCE SYMBOL;So;0;ON;;;;;N;;;;; 26AF;UNMARRIED PARTNERSHIP SYMBOL;So;0;ON;;;;;N;;;;; 26B0;COFFIN;So;0;ON;;;;;N;;;;; 26B1;FUNERAL URN;So;0;ON;;;;;N;;;;; 26B2;NEUTER;So;0;ON;;;;;N;;;;; 26B3;CERES;So;0;ON;;;;;N;;;;; 26B4;PALLAS;So;0;ON;;;;;N;;;;; 26B5;JUNO;So;0;ON;;;;;N;;;;; 26B6;VESTA;So;0;ON;;;;;N;;;;; 26B7;CHIRON;So;0;ON;;;;;N;;;;; 26B8;BLACK MOON LILITH;So;0;ON;;;;;N;;;;; 26B9;SEXTILE;So;0;ON;;;;;N;;;;; 26BA;SEMISEXTILE;So;0;ON;;;;;N;;;;; 26BB;QUINCUNX;So;0;ON;;;;;N;;;;; 26BC;SESQUIQUADRATE;So;0;ON;;;;;N;;;;; 26BD;SOCCER BALL;So;0;ON;;;;;N;;;;; 26BE;BASEBALL;So;0;ON;;;;;N;;;;; 26BF;SQUARED KEY;So;0;ON;;;;;N;;;;; 26C0;WHITE DRAUGHTS MAN;So;0;ON;;;;;N;;;;; 26C1;WHITE DRAUGHTS KING;So;0;ON;;;;;N;;;;; 26C2;BLACK DRAUGHTS MAN;So;0;ON;;;;;N;;;;; 26C3;BLACK DRAUGHTS KING;So;0;ON;;;;;N;;;;; 26C4;SNOWMAN WITHOUT SNOW;So;0;ON;;;;;N;;;;; 26C5;SUN BEHIND CLOUD;So;0;ON;;;;;N;;;;; 26C6;RAIN;So;0;ON;;;;;N;;;;; 26C7;BLACK SNOWMAN;So;0;ON;;;;;N;;;;; 26C8;THUNDER CLOUD AND RAIN;So;0;ON;;;;;N;;;;; 26C9;TURNED WHITE SHOGI PIECE;So;0;ON;;;;;N;;;;; 26CA;TURNED BLACK SHOGI PIECE;So;0;ON;;;;;N;;;;; 26CB;WHITE DIAMOND IN SQUARE;So;0;ON;;;;;N;;;;; 26CC;CROSSING LANES;So;0;ON;;;;;N;;;;; 26CD;DISABLED CAR;So;0;ON;;;;;N;;;;; 26CE;OPHIUCHUS;So;0;ON;;;;;N;;;;; 26CF;PICK;So;0;ON;;;;;N;;;;; 26D0;CAR SLIDING;So;0;ON;;;;;N;;;;; 26D1;HELMET WITH WHITE CROSS;So;0;ON;;;;;N;;;;; 26D2;CIRCLED CROSSING LANES;So;0;ON;;;;;N;;;;; 26D3;CHAINS;So;0;ON;;;;;N;;;;; 26D4;NO ENTRY;So;0;ON;;;;;N;;;;; 26D5;ALTERNATE ONE-WAY LEFT WAY TRAFFIC;So;0;ON;;;;;N;;;;; 26D6;BLACK TWO-WAY LEFT WAY TRAFFIC;So;0;ON;;;;;N;;;;; 26D7;WHITE TWO-WAY LEFT WAY TRAFFIC;So;0;ON;;;;;N;;;;; 26D8;BLACK LEFT LANE MERGE;So;0;ON;;;;;N;;;;; 26D9;WHITE LEFT LANE MERGE;So;0;ON;;;;;N;;;;; 26DA;DRIVE SLOW SIGN;So;0;ON;;;;;N;;;;; 26DB;HEAVY WHITE DOWN-POINTING TRIANGLE;So;0;ON;;;;;N;;;;; 26DC;LEFT CLOSED ENTRY;So;0;ON;;;;;N;;;;; 26DD;SQUARED SALTIRE;So;0;ON;;;;;N;;;;; 26DE;FALLING DIAGONAL IN WHITE CIRCLE IN BLACK SQUARE;So;0;ON;;;;;N;;;;; 26DF;BLACK TRUCK;So;0;ON;;;;;N;;;;; 26E0;RESTRICTED LEFT ENTRY-1;So;0;ON;;;;;N;;;;; 26E1;RESTRICTED LEFT ENTRY-2;So;0;ON;;;;;N;;;;; 26E2;ASTRONOMICAL SYMBOL FOR URANUS;So;0;ON;;;;;N;;;;; 26E3;HEAVY CIRCLE WITH STROKE AND TWO DOTS ABOVE;So;0;ON;;;;;N;;;;; 26E4;PENTAGRAM;So;0;ON;;;;;N;;;;; 26E5;RIGHT-HANDED INTERLACED PENTAGRAM;So;0;ON;;;;;N;;;;; 26E6;LEFT-HANDED INTERLACED PENTAGRAM;So;0;ON;;;;;N;;;;; 26E7;INVERTED PENTAGRAM;So;0;ON;;;;;N;;;;; 26E8;BLACK CROSS ON SHIELD;So;0;ON;;;;;N;;;;; 26E9;SHINTO SHRINE;So;0;ON;;;;;N;;;;; 26EA;CHURCH;So;0;ON;;;;;N;;;;; 26EB;CASTLE;So;0;ON;;;;;N;;;;; 26EC;HISTORIC SITE;So;0;ON;;;;;N;;;;; 26ED;GEAR WITHOUT HUB;So;0;ON;;;;;N;;;;; 26EE;GEAR WITH HANDLES;So;0;ON;;;;;N;;;;; 26EF;MAP SYMBOL FOR LIGHTHOUSE;So;0;ON;;;;;N;;;;; 26F0;MOUNTAIN;So;0;ON;;;;;N;;;;; 26F1;UMBRELLA ON GROUND;So;0;ON;;;;;N;;;;; 26F2;FOUNTAIN;So;0;ON;;;;;N;;;;; 26F3;FLAG IN HOLE;So;0;ON;;;;;N;;;;; 26F4;FERRY;So;0;ON;;;;;N;;;;; 26F5;SAILBOAT;So;0;ON;;;;;N;;;;; 26F6;SQUARE FOUR CORNERS;So;0;ON;;;;;N;;;;; 26F7;SKIER;So;0;ON;;;;;N;;;;; 26F8;ICE SKATE;So;0;ON;;;;;N;;;;; 26F9;PERSON WITH BALL;So;0;ON;;;;;N;;;;; 26FA;TENT;So;0;ON;;;;;N;;;;; 26FB;JAPANESE BANK SYMBOL;So;0;ON;;;;;N;;;;; 26FC;HEADSTONE GRAVEYARD SYMBOL;So;0;ON;;;;;N;;;;; 26FD;FUEL PUMP;So;0;ON;;;;;N;;;;; 26FE;CUP ON BLACK SQUARE;So;0;ON;;;;;N;;;;; 26FF;WHITE FLAG WITH HORIZONTAL MIDDLE BLACK STRIPE;So;0;ON;;;;;N;;;;; 2700;BLACK SAFETY SCISSORS;So;0;ON;;;;;N;;;;; 2701;UPPER BLADE SCISSORS;So;0;ON;;;;;N;;;;; 2702;BLACK SCISSORS;So;0;ON;;;;;N;;;;; 2703;LOWER BLADE SCISSORS;So;0;ON;;;;;N;;;;; 2704;WHITE SCISSORS;So;0;ON;;;;;N;;;;; 2705;WHITE HEAVY CHECK MARK;So;0;ON;;;;;N;;;;; 2706;TELEPHONE LOCATION SIGN;So;0;ON;;;;;N;;;;; 2707;TAPE DRIVE;So;0;ON;;;;;N;;;;; 2708;AIRPLANE;So;0;ON;;;;;N;;;;; 2709;ENVELOPE;So;0;ON;;;;;N;;;;; 270A;RAISED FIST;So;0;ON;;;;;N;;;;; 270B;RAISED HAND;So;0;ON;;;;;N;;;;; 270C;VICTORY HAND;So;0;ON;;;;;N;;;;; 270D;WRITING HAND;So;0;ON;;;;;N;;;;; 270E;LOWER RIGHT PENCIL;So;0;ON;;;;;N;;;;; 270F;PENCIL;So;0;ON;;;;;N;;;;; 2710;UPPER RIGHT PENCIL;So;0;ON;;;;;N;;;;; 2711;WHITE NIB;So;0;ON;;;;;N;;;;; 2712;BLACK NIB;So;0;ON;;;;;N;;;;; 2713;CHECK MARK;So;0;ON;;;;;N;;;;; 2714;HEAVY CHECK MARK;So;0;ON;;;;;N;;;;; 2715;MULTIPLICATION X;So;0;ON;;;;;N;;;;; 2716;HEAVY MULTIPLICATION X;So;0;ON;;;;;N;;;;; 2717;BALLOT X;So;0;ON;;;;;N;;;;; 2718;HEAVY BALLOT X;So;0;ON;;;;;N;;;;; 2719;OUTLINED GREEK CROSS;So;0;ON;;;;;N;;;;; 271A;HEAVY GREEK CROSS;So;0;ON;;;;;N;;;;; 271B;OPEN CENTRE CROSS;So;0;ON;;;;;N;OPEN CENTER CROSS;;;; 271C;HEAVY OPEN CENTRE CROSS;So;0;ON;;;;;N;HEAVY OPEN CENTER CROSS;;;; 271D;LATIN CROSS;So;0;ON;;;;;N;;;;; 271E;SHADOWED WHITE LATIN CROSS;So;0;ON;;;;;N;;;;; 271F;OUTLINED LATIN CROSS;So;0;ON;;;;;N;;;;; 2720;MALTESE CROSS;So;0;ON;;;;;N;;;;; 2721;STAR OF DAVID;So;0;ON;;;;;N;;;;; 2722;FOUR TEARDROP-SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 2723;FOUR BALLOON-SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 2724;HEAVY FOUR BALLOON-SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 2725;FOUR CLUB-SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 2726;BLACK FOUR POINTED STAR;So;0;ON;;;;;N;;;;; 2727;WHITE FOUR POINTED STAR;So;0;ON;;;;;N;;;;; 2728;SPARKLES;So;0;ON;;;;;N;;;;; 2729;STRESS OUTLINED WHITE STAR;So;0;ON;;;;;N;;;;; 272A;CIRCLED WHITE STAR;So;0;ON;;;;;N;;;;; 272B;OPEN CENTRE BLACK STAR;So;0;ON;;;;;N;OPEN CENTER BLACK STAR;;;; 272C;BLACK CENTRE WHITE STAR;So;0;ON;;;;;N;BLACK CENTER WHITE STAR;;;; 272D;OUTLINED BLACK STAR;So;0;ON;;;;;N;;;;; 272E;HEAVY OUTLINED BLACK STAR;So;0;ON;;;;;N;;;;; 272F;PINWHEEL STAR;So;0;ON;;;;;N;;;;; 2730;SHADOWED WHITE STAR;So;0;ON;;;;;N;;;;; 2731;HEAVY ASTERISK;So;0;ON;;;;;N;;;;; 2732;OPEN CENTRE ASTERISK;So;0;ON;;;;;N;OPEN CENTER ASTERISK;;;; 2733;EIGHT SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 2734;EIGHT POINTED BLACK STAR;So;0;ON;;;;;N;;;;; 2735;EIGHT POINTED PINWHEEL STAR;So;0;ON;;;;;N;;;;; 2736;SIX POINTED BLACK STAR;So;0;ON;;;;;N;;;;; 2737;EIGHT POINTED RECTILINEAR BLACK STAR;So;0;ON;;;;;N;;;;; 2738;HEAVY EIGHT POINTED RECTILINEAR BLACK STAR;So;0;ON;;;;;N;;;;; 2739;TWELVE POINTED BLACK STAR;So;0;ON;;;;;N;;;;; 273A;SIXTEEN POINTED ASTERISK;So;0;ON;;;;;N;;;;; 273B;TEARDROP-SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 273C;OPEN CENTRE TEARDROP-SPOKED ASTERISK;So;0;ON;;;;;N;OPEN CENTER TEARDROP-SPOKED ASTERISK;;;; 273D;HEAVY TEARDROP-SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 273E;SIX PETALLED BLACK AND WHITE FLORETTE;So;0;ON;;;;;N;;;;; 273F;BLACK FLORETTE;So;0;ON;;;;;N;;;;; 2740;WHITE FLORETTE;So;0;ON;;;;;N;;;;; 2741;EIGHT PETALLED OUTLINED BLACK FLORETTE;So;0;ON;;;;;N;;;;; 2742;CIRCLED OPEN CENTRE EIGHT POINTED STAR;So;0;ON;;;;;N;CIRCLED OPEN CENTER EIGHT POINTED STAR;;;; 2743;HEAVY TEARDROP-SPOKED PINWHEEL ASTERISK;So;0;ON;;;;;N;;;;; 2744;SNOWFLAKE;So;0;ON;;;;;N;;;;; 2745;TIGHT TRIFOLIATE SNOWFLAKE;So;0;ON;;;;;N;;;;; 2746;HEAVY CHEVRON SNOWFLAKE;So;0;ON;;;;;N;;;;; 2747;SPARKLE;So;0;ON;;;;;N;;;;; 2748;HEAVY SPARKLE;So;0;ON;;;;;N;;;;; 2749;BALLOON-SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 274A;EIGHT TEARDROP-SPOKED PROPELLER ASTERISK;So;0;ON;;;;;N;;;;; 274B;HEAVY EIGHT TEARDROP-SPOKED PROPELLER ASTERISK;So;0;ON;;;;;N;;;;; 274C;CROSS MARK;So;0;ON;;;;;N;;;;; 274D;SHADOWED WHITE CIRCLE;So;0;ON;;;;;N;;;;; 274E;NEGATIVE SQUARED CROSS MARK;So;0;ON;;;;;N;;;;; 274F;LOWER RIGHT DROP-SHADOWED WHITE SQUARE;So;0;ON;;;;;N;;;;; 2750;UPPER RIGHT DROP-SHADOWED WHITE SQUARE;So;0;ON;;;;;N;;;;; 2751;LOWER RIGHT SHADOWED WHITE SQUARE;So;0;ON;;;;;N;;;;; 2752;UPPER RIGHT SHADOWED WHITE SQUARE;So;0;ON;;;;;N;;;;; 2753;BLACK QUESTION MARK ORNAMENT;So;0;ON;;;;;N;;;;; 2754;WHITE QUESTION MARK ORNAMENT;So;0;ON;;;;;N;;;;; 2755;WHITE EXCLAMATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; 2756;BLACK DIAMOND MINUS WHITE X;So;0;ON;;;;;N;;;;; 2757;HEAVY EXCLAMATION MARK SYMBOL;So;0;ON;;;;;N;;;;; 2758;LIGHT VERTICAL BAR;So;0;ON;;;;;N;;;;; 2759;MEDIUM VERTICAL BAR;So;0;ON;;;;;N;;;;; 275A;HEAVY VERTICAL BAR;So;0;ON;;;;;N;;;;; 275B;HEAVY SINGLE TURNED COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; 275C;HEAVY SINGLE COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; 275D;HEAVY DOUBLE TURNED COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; 275E;HEAVY DOUBLE COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; 275F;HEAVY LOW SINGLE COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; 2760;HEAVY LOW DOUBLE COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; 2761;CURVED STEM PARAGRAPH SIGN ORNAMENT;So;0;ON;;;;;N;;;;; 2762;HEAVY EXCLAMATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; 2763;HEAVY HEART EXCLAMATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; 2764;HEAVY BLACK HEART;So;0;ON;;;;;N;;;;; 2765;ROTATED HEAVY BLACK HEART BULLET;So;0;ON;;;;;N;;;;; 2766;FLORAL HEART;So;0;ON;;;;;N;;;;; 2767;ROTATED FLORAL HEART BULLET;So;0;ON;;;;;N;;;;; 2768;MEDIUM LEFT PARENTHESIS ORNAMENT;Ps;0;ON;;;;;Y;;;;; 2769;MEDIUM RIGHT PARENTHESIS ORNAMENT;Pe;0;ON;;;;;Y;;;;; 276A;MEDIUM FLATTENED LEFT PARENTHESIS ORNAMENT;Ps;0;ON;;;;;Y;;;;; 276B;MEDIUM FLATTENED RIGHT PARENTHESIS ORNAMENT;Pe;0;ON;;;;;Y;;;;; 276C;MEDIUM LEFT-POINTING ANGLE BRACKET ORNAMENT;Ps;0;ON;;;;;Y;;;;; 276D;MEDIUM RIGHT-POINTING ANGLE BRACKET ORNAMENT;Pe;0;ON;;;;;Y;;;;; 276E;HEAVY LEFT-POINTING ANGLE QUOTATION MARK ORNAMENT;Ps;0;ON;;;;;Y;;;;; 276F;HEAVY RIGHT-POINTING ANGLE QUOTATION MARK ORNAMENT;Pe;0;ON;;;;;Y;;;;; 2770;HEAVY LEFT-POINTING ANGLE BRACKET ORNAMENT;Ps;0;ON;;;;;Y;;;;; 2771;HEAVY RIGHT-POINTING ANGLE BRACKET ORNAMENT;Pe;0;ON;;;;;Y;;;;; 2772;LIGHT LEFT TORTOISE SHELL BRACKET ORNAMENT;Ps;0;ON;;;;;Y;;;;; 2773;LIGHT RIGHT TORTOISE SHELL BRACKET ORNAMENT;Pe;0;ON;;;;;Y;;;;; 2774;MEDIUM LEFT CURLY BRACKET ORNAMENT;Ps;0;ON;;;;;Y;;;;; 2775;MEDIUM RIGHT CURLY BRACKET ORNAMENT;Pe;0;ON;;;;;Y;;;;; 2776;DINGBAT NEGATIVE CIRCLED DIGIT ONE;No;0;ON;;;1;1;N;INVERSE CIRCLED DIGIT ONE;;;; 2777;DINGBAT NEGATIVE CIRCLED DIGIT TWO;No;0;ON;;;2;2;N;INVERSE CIRCLED DIGIT TWO;;;; 2778;DINGBAT NEGATIVE CIRCLED DIGIT THREE;No;0;ON;;;3;3;N;INVERSE CIRCLED DIGIT THREE;;;; 2779;DINGBAT NEGATIVE CIRCLED DIGIT FOUR;No;0;ON;;;4;4;N;INVERSE CIRCLED DIGIT FOUR;;;; 277A;DINGBAT NEGATIVE CIRCLED DIGIT FIVE;No;0;ON;;;5;5;N;INVERSE CIRCLED DIGIT FIVE;;;; 277B;DINGBAT NEGATIVE CIRCLED DIGIT SIX;No;0;ON;;;6;6;N;INVERSE CIRCLED DIGIT SIX;;;; 277C;DINGBAT NEGATIVE CIRCLED DIGIT SEVEN;No;0;ON;;;7;7;N;INVERSE CIRCLED DIGIT SEVEN;;;; 277D;DINGBAT NEGATIVE CIRCLED DIGIT EIGHT;No;0;ON;;;8;8;N;INVERSE CIRCLED DIGIT EIGHT;;;; 277E;DINGBAT NEGATIVE CIRCLED DIGIT NINE;No;0;ON;;;9;9;N;INVERSE CIRCLED DIGIT NINE;;;; 277F;DINGBAT NEGATIVE CIRCLED NUMBER TEN;No;0;ON;;;;10;N;INVERSE CIRCLED NUMBER TEN;;;; 2780;DINGBAT CIRCLED SANS-SERIF DIGIT ONE;No;0;ON;;;1;1;N;CIRCLED SANS-SERIF DIGIT ONE;;;; 2781;DINGBAT CIRCLED SANS-SERIF DIGIT TWO;No;0;ON;;;2;2;N;CIRCLED SANS-SERIF DIGIT TWO;;;; 2782;DINGBAT CIRCLED SANS-SERIF DIGIT THREE;No;0;ON;;;3;3;N;CIRCLED SANS-SERIF DIGIT THREE;;;; 2783;DINGBAT CIRCLED SANS-SERIF DIGIT FOUR;No;0;ON;;;4;4;N;CIRCLED SANS-SERIF DIGIT FOUR;;;; 2784;DINGBAT CIRCLED SANS-SERIF DIGIT FIVE;No;0;ON;;;5;5;N;CIRCLED SANS-SERIF DIGIT FIVE;;;; 2785;DINGBAT CIRCLED SANS-SERIF DIGIT SIX;No;0;ON;;;6;6;N;CIRCLED SANS-SERIF DIGIT SIX;;;; 2786;DINGBAT CIRCLED SANS-SERIF DIGIT SEVEN;No;0;ON;;;7;7;N;CIRCLED SANS-SERIF DIGIT SEVEN;;;; 2787;DINGBAT CIRCLED SANS-SERIF DIGIT EIGHT;No;0;ON;;;8;8;N;CIRCLED SANS-SERIF DIGIT EIGHT;;;; 2788;DINGBAT CIRCLED SANS-SERIF DIGIT NINE;No;0;ON;;;9;9;N;CIRCLED SANS-SERIF DIGIT NINE;;;; 2789;DINGBAT CIRCLED SANS-SERIF NUMBER TEN;No;0;ON;;;;10;N;CIRCLED SANS-SERIF NUMBER TEN;;;; 278A;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT ONE;No;0;ON;;;1;1;N;INVERSE CIRCLED SANS-SERIF DIGIT ONE;;;; 278B;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT TWO;No;0;ON;;;2;2;N;INVERSE CIRCLED SANS-SERIF DIGIT TWO;;;; 278C;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT THREE;No;0;ON;;;3;3;N;INVERSE CIRCLED SANS-SERIF DIGIT THREE;;;; 278D;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT FOUR;No;0;ON;;;4;4;N;INVERSE CIRCLED SANS-SERIF DIGIT FOUR;;;; 278E;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT FIVE;No;0;ON;;;5;5;N;INVERSE CIRCLED SANS-SERIF DIGIT FIVE;;;; 278F;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT SIX;No;0;ON;;;6;6;N;INVERSE CIRCLED SANS-SERIF DIGIT SIX;;;; 2790;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT SEVEN;No;0;ON;;;7;7;N;INVERSE CIRCLED SANS-SERIF DIGIT SEVEN;;;; 2791;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT EIGHT;No;0;ON;;;8;8;N;INVERSE CIRCLED SANS-SERIF DIGIT EIGHT;;;; 2792;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT NINE;No;0;ON;;;9;9;N;INVERSE CIRCLED SANS-SERIF DIGIT NINE;;;; 2793;DINGBAT NEGATIVE CIRCLED SANS-SERIF NUMBER TEN;No;0;ON;;;;10;N;INVERSE CIRCLED SANS-SERIF NUMBER TEN;;;; 2794;HEAVY WIDE-HEADED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY WIDE-HEADED RIGHT ARROW;;;; 2795;HEAVY PLUS SIGN;So;0;ON;;;;;N;;;;; 2796;HEAVY MINUS SIGN;So;0;ON;;;;;N;;;;; 2797;HEAVY DIVISION SIGN;So;0;ON;;;;;N;;;;; 2798;HEAVY SOUTH EAST ARROW;So;0;ON;;;;;N;HEAVY LOWER RIGHT ARROW;;;; 2799;HEAVY RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY RIGHT ARROW;;;; 279A;HEAVY NORTH EAST ARROW;So;0;ON;;;;;N;HEAVY UPPER RIGHT ARROW;;;; 279B;DRAFTING POINT RIGHTWARDS ARROW;So;0;ON;;;;;N;DRAFTING POINT RIGHT ARROW;;;; 279C;HEAVY ROUND-TIPPED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY ROUND-TIPPED RIGHT ARROW;;;; 279D;TRIANGLE-HEADED RIGHTWARDS ARROW;So;0;ON;;;;;N;TRIANGLE-HEADED RIGHT ARROW;;;; 279E;HEAVY TRIANGLE-HEADED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY TRIANGLE-HEADED RIGHT ARROW;;;; 279F;DASHED TRIANGLE-HEADED RIGHTWARDS ARROW;So;0;ON;;;;;N;DASHED TRIANGLE-HEADED RIGHT ARROW;;;; 27A0;HEAVY DASHED TRIANGLE-HEADED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY DASHED TRIANGLE-HEADED RIGHT ARROW;;;; 27A1;BLACK RIGHTWARDS ARROW;So;0;ON;;;;;N;BLACK RIGHT ARROW;;;; 27A2;THREE-D TOP-LIGHTED RIGHTWARDS ARROWHEAD;So;0;ON;;;;;N;THREE-D TOP-LIGHTED RIGHT ARROWHEAD;;;; 27A3;THREE-D BOTTOM-LIGHTED RIGHTWARDS ARROWHEAD;So;0;ON;;;;;N;THREE-D BOTTOM-LIGHTED RIGHT ARROWHEAD;;;; 27A4;BLACK RIGHTWARDS ARROWHEAD;So;0;ON;;;;;N;BLACK RIGHT ARROWHEAD;;;; 27A5;HEAVY BLACK CURVED DOWNWARDS AND RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY BLACK CURVED DOWN AND RIGHT ARROW;;;; 27A6;HEAVY BLACK CURVED UPWARDS AND RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY BLACK CURVED UP AND RIGHT ARROW;;;; 27A7;SQUAT BLACK RIGHTWARDS ARROW;So;0;ON;;;;;N;SQUAT BLACK RIGHT ARROW;;;; 27A8;HEAVY CONCAVE-POINTED BLACK RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY CONCAVE-POINTED BLACK RIGHT ARROW;;;; 27A9;RIGHT-SHADED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;RIGHT-SHADED WHITE RIGHT ARROW;;;; 27AA;LEFT-SHADED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;LEFT-SHADED WHITE RIGHT ARROW;;;; 27AB;BACK-TILTED SHADOWED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;BACK-TILTED SHADOWED WHITE RIGHT ARROW;;;; 27AC;FRONT-TILTED SHADOWED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;FRONT-TILTED SHADOWED WHITE RIGHT ARROW;;;; 27AD;HEAVY LOWER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY LOWER RIGHT-SHADOWED WHITE RIGHT ARROW;;;; 27AE;HEAVY UPPER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY UPPER RIGHT-SHADOWED WHITE RIGHT ARROW;;;; 27AF;NOTCHED LOWER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;NOTCHED LOWER RIGHT-SHADOWED WHITE RIGHT ARROW;;;; 27B0;CURLY LOOP;So;0;ON;;;;;N;;;;; 27B1;NOTCHED UPPER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;NOTCHED UPPER RIGHT-SHADOWED WHITE RIGHT ARROW;;;; 27B2;CIRCLED HEAVY WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;CIRCLED HEAVY WHITE RIGHT ARROW;;;; 27B3;WHITE-FEATHERED RIGHTWARDS ARROW;So;0;ON;;;;;N;WHITE-FEATHERED RIGHT ARROW;;;; 27B4;BLACK-FEATHERED SOUTH EAST ARROW;So;0;ON;;;;;N;BLACK-FEATHERED LOWER RIGHT ARROW;;;; 27B5;BLACK-FEATHERED RIGHTWARDS ARROW;So;0;ON;;;;;N;BLACK-FEATHERED RIGHT ARROW;;;; 27B6;BLACK-FEATHERED NORTH EAST ARROW;So;0;ON;;;;;N;BLACK-FEATHERED UPPER RIGHT ARROW;;;; 27B7;HEAVY BLACK-FEATHERED SOUTH EAST ARROW;So;0;ON;;;;;N;HEAVY BLACK-FEATHERED LOWER RIGHT ARROW;;;; 27B8;HEAVY BLACK-FEATHERED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY BLACK-FEATHERED RIGHT ARROW;;;; 27B9;HEAVY BLACK-FEATHERED NORTH EAST ARROW;So;0;ON;;;;;N;HEAVY BLACK-FEATHERED UPPER RIGHT ARROW;;;; 27BA;TEARDROP-BARBED RIGHTWARDS ARROW;So;0;ON;;;;;N;TEARDROP-BARBED RIGHT ARROW;;;; 27BB;HEAVY TEARDROP-SHANKED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY TEARDROP-SHANKED RIGHT ARROW;;;; 27BC;WEDGE-TAILED RIGHTWARDS ARROW;So;0;ON;;;;;N;WEDGE-TAILED RIGHT ARROW;;;; 27BD;HEAVY WEDGE-TAILED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY WEDGE-TAILED RIGHT ARROW;;;; 27BE;OPEN-OUTLINED RIGHTWARDS ARROW;So;0;ON;;;;;N;OPEN-OUTLINED RIGHT ARROW;;;; 27BF;DOUBLE CURLY LOOP;So;0;ON;;;;;N;;;;; 27C0;THREE DIMENSIONAL ANGLE;Sm;0;ON;;;;;Y;;;;; 27C1;WHITE TRIANGLE CONTAINING SMALL WHITE TRIANGLE;Sm;0;ON;;;;;N;;;;; 27C2;PERPENDICULAR;Sm;0;ON;;;;;N;;;;; 27C3;OPEN SUBSET;Sm;0;ON;;;;;Y;;;;; 27C4;OPEN SUPERSET;Sm;0;ON;;;;;Y;;;;; 27C5;LEFT S-SHAPED BAG DELIMITER;Ps;0;ON;;;;;Y;;;;; 27C6;RIGHT S-SHAPED BAG DELIMITER;Pe;0;ON;;;;;Y;;;;; 27C7;OR WITH DOT INSIDE;Sm;0;ON;;;;;N;;;;; 27C8;REVERSE SOLIDUS PRECEDING SUBSET;Sm;0;ON;;;;;Y;;;;; 27C9;SUPERSET PRECEDING SOLIDUS;Sm;0;ON;;;;;Y;;;;; 27CA;VERTICAL BAR WITH HORIZONTAL STROKE;Sm;0;ON;;;;;N;;;;; 27CB;MATHEMATICAL RISING DIAGONAL;Sm;0;ON;;;;;Y;;;;; 27CC;LONG DIVISION;Sm;0;ON;;;;;Y;;;;; 27CD;MATHEMATICAL FALLING DIAGONAL;Sm;0;ON;;;;;Y;;;;; 27CE;SQUARED LOGICAL AND;Sm;0;ON;;;;;N;;;;; 27CF;SQUARED LOGICAL OR;Sm;0;ON;;;;;N;;;;; 27D0;WHITE DIAMOND WITH CENTRED DOT;Sm;0;ON;;;;;N;;;;; 27D1;AND WITH DOT;Sm;0;ON;;;;;N;;;;; 27D2;ELEMENT OF OPENING UPWARDS;Sm;0;ON;;;;;N;;;;; 27D3;LOWER RIGHT CORNER WITH DOT;Sm;0;ON;;;;;Y;;;;; 27D4;UPPER LEFT CORNER WITH DOT;Sm;0;ON;;;;;Y;;;;; 27D5;LEFT OUTER JOIN;Sm;0;ON;;;;;Y;;;;; 27D6;RIGHT OUTER JOIN;Sm;0;ON;;;;;Y;;;;; 27D7;FULL OUTER JOIN;Sm;0;ON;;;;;N;;;;; 27D8;LARGE UP TACK;Sm;0;ON;;;;;N;;;;; 27D9;LARGE DOWN TACK;Sm;0;ON;;;;;N;;;;; 27DA;LEFT AND RIGHT DOUBLE TURNSTILE;Sm;0;ON;;;;;N;;;;; 27DB;LEFT AND RIGHT TACK;Sm;0;ON;;;;;N;;;;; 27DC;LEFT MULTIMAP;Sm;0;ON;;;;;Y;;;;; 27DD;LONG RIGHT TACK;Sm;0;ON;;;;;Y;;;;; 27DE;LONG LEFT TACK;Sm;0;ON;;;;;Y;;;;; 27DF;UP TACK WITH CIRCLE ABOVE;Sm;0;ON;;;;;N;;;;; 27E0;LOZENGE DIVIDED BY HORIZONTAL RULE;Sm;0;ON;;;;;N;;;;; 27E1;WHITE CONCAVE-SIDED DIAMOND;Sm;0;ON;;;;;N;;;;; 27E2;WHITE CONCAVE-SIDED DIAMOND WITH LEFTWARDS TICK;Sm;0;ON;;;;;Y;;;;; 27E3;WHITE CONCAVE-SIDED DIAMOND WITH RIGHTWARDS TICK;Sm;0;ON;;;;;Y;;;;; 27E4;WHITE SQUARE WITH LEFTWARDS TICK;Sm;0;ON;;;;;Y;;;;; 27E5;WHITE SQUARE WITH RIGHTWARDS TICK;Sm;0;ON;;;;;Y;;;;; 27E6;MATHEMATICAL LEFT WHITE SQUARE BRACKET;Ps;0;ON;;;;;Y;;;;; 27E7;MATHEMATICAL RIGHT WHITE SQUARE BRACKET;Pe;0;ON;;;;;Y;;;;; 27E8;MATHEMATICAL LEFT ANGLE BRACKET;Ps;0;ON;;;;;Y;;;;; 27E9;MATHEMATICAL RIGHT ANGLE BRACKET;Pe;0;ON;;;;;Y;;;;; 27EA;MATHEMATICAL LEFT DOUBLE ANGLE BRACKET;Ps;0;ON;;;;;Y;;;;; 27EB;MATHEMATICAL RIGHT DOUBLE ANGLE BRACKET;Pe;0;ON;;;;;Y;;;;; 27EC;MATHEMATICAL LEFT WHITE TORTOISE SHELL BRACKET;Ps;0;ON;;;;;Y;;;;; 27ED;MATHEMATICAL RIGHT WHITE TORTOISE SHELL BRACKET;Pe;0;ON;;;;;Y;;;;; 27EE;MATHEMATICAL LEFT FLATTENED PARENTHESIS;Ps;0;ON;;;;;Y;;;;; 27EF;MATHEMATICAL RIGHT FLATTENED PARENTHESIS;Pe;0;ON;;;;;Y;;;;; 27F0;UPWARDS QUADRUPLE ARROW;Sm;0;ON;;;;;N;;;;; 27F1;DOWNWARDS QUADRUPLE ARROW;Sm;0;ON;;;;;N;;;;; 27F2;ANTICLOCKWISE GAPPED CIRCLE ARROW;Sm;0;ON;;;;;N;;;;; 27F3;CLOCKWISE GAPPED CIRCLE ARROW;Sm;0;ON;;;;;N;;;;; 27F4;RIGHT ARROW WITH CIRCLED PLUS;Sm;0;ON;;;;;N;;;;; 27F5;LONG LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 27F6;LONG RIGHTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 27F7;LONG LEFT RIGHT ARROW;Sm;0;ON;;;;;N;;;;; 27F8;LONG LEFTWARDS DOUBLE ARROW;Sm;0;ON;;;;;N;;;;; 27F9;LONG RIGHTWARDS DOUBLE ARROW;Sm;0;ON;;;;;N;;;;; 27FA;LONG LEFT RIGHT DOUBLE ARROW;Sm;0;ON;;;;;N;;;;; 27FB;LONG LEFTWARDS ARROW FROM BAR;Sm;0;ON;;;;;N;;;;; 27FC;LONG RIGHTWARDS ARROW FROM BAR;Sm;0;ON;;;;;N;;;;; 27FD;LONG LEFTWARDS DOUBLE ARROW FROM BAR;Sm;0;ON;;;;;N;;;;; 27FE;LONG RIGHTWARDS DOUBLE ARROW FROM BAR;Sm;0;ON;;;;;N;;;;; 27FF;LONG RIGHTWARDS SQUIGGLE ARROW;Sm;0;ON;;;;;N;;;;; 2800;BRAILLE PATTERN BLANK;So;0;L;;;;;N;;;;; 2801;BRAILLE PATTERN DOTS-1;So;0;L;;;;;N;;;;; 2802;BRAILLE PATTERN DOTS-2;So;0;L;;;;;N;;;;; 2803;BRAILLE PATTERN DOTS-12;So;0;L;;;;;N;;;;; 2804;BRAILLE PATTERN DOTS-3;So;0;L;;;;;N;;;;; 2805;BRAILLE PATTERN DOTS-13;So;0;L;;;;;N;;;;; 2806;BRAILLE PATTERN DOTS-23;So;0;L;;;;;N;;;;; 2807;BRAILLE PATTERN DOTS-123;So;0;L;;;;;N;;;;; 2808;BRAILLE PATTERN DOTS-4;So;0;L;;;;;N;;;;; 2809;BRAILLE PATTERN DOTS-14;So;0;L;;;;;N;;;;; 280A;BRAILLE PATTERN DOTS-24;So;0;L;;;;;N;;;;; 280B;BRAILLE PATTERN DOTS-124;So;0;L;;;;;N;;;;; 280C;BRAILLE PATTERN DOTS-34;So;0;L;;;;;N;;;;; 280D;BRAILLE PATTERN DOTS-134;So;0;L;;;;;N;;;;; 280E;BRAILLE PATTERN DOTS-234;So;0;L;;;;;N;;;;; 280F;BRAILLE PATTERN DOTS-1234;So;0;L;;;;;N;;;;; 2810;BRAILLE PATTERN DOTS-5;So;0;L;;;;;N;;;;; 2811;BRAILLE PATTERN DOTS-15;So;0;L;;;;;N;;;;; 2812;BRAILLE PATTERN DOTS-25;So;0;L;;;;;N;;;;; 2813;BRAILLE PATTERN DOTS-125;So;0;L;;;;;N;;;;; 2814;BRAILLE PATTERN DOTS-35;So;0;L;;;;;N;;;;; 2815;BRAILLE PATTERN DOTS-135;So;0;L;;;;;N;;;;; 2816;BRAILLE PATTERN DOTS-235;So;0;L;;;;;N;;;;; 2817;BRAILLE PATTERN DOTS-1235;So;0;L;;;;;N;;;;; 2818;BRAILLE PATTERN DOTS-45;So;0;L;;;;;N;;;;; 2819;BRAILLE PATTERN DOTS-145;So;0;L;;;;;N;;;;; 281A;BRAILLE PATTERN DOTS-245;So;0;L;;;;;N;;;;; 281B;BRAILLE PATTERN DOTS-1245;So;0;L;;;;;N;;;;; 281C;BRAILLE PATTERN DOTS-345;So;0;L;;;;;N;;;;; 281D;BRAILLE PATTERN DOTS-1345;So;0;L;;;;;N;;;;; 281E;BRAILLE PATTERN DOTS-2345;So;0;L;;;;;N;;;;; 281F;BRAILLE PATTERN DOTS-12345;So;0;L;;;;;N;;;;; 2820;BRAILLE PATTERN DOTS-6;So;0;L;;;;;N;;;;; 2821;BRAILLE PATTERN DOTS-16;So;0;L;;;;;N;;;;; 2822;BRAILLE PATTERN DOTS-26;So;0;L;;;;;N;;;;; 2823;BRAILLE PATTERN DOTS-126;So;0;L;;;;;N;;;;; 2824;BRAILLE PATTERN DOTS-36;So;0;L;;;;;N;;;;; 2825;BRAILLE PATTERN DOTS-136;So;0;L;;;;;N;;;;; 2826;BRAILLE PATTERN DOTS-236;So;0;L;;;;;N;;;;; 2827;BRAILLE PATTERN DOTS-1236;So;0;L;;;;;N;;;;; 2828;BRAILLE PATTERN DOTS-46;So;0;L;;;;;N;;;;; 2829;BRAILLE PATTERN DOTS-146;So;0;L;;;;;N;;;;; 282A;BRAILLE PATTERN DOTS-246;So;0;L;;;;;N;;;;; 282B;BRAILLE PATTERN DOTS-1246;So;0;L;;;;;N;;;;; 282C;BRAILLE PATTERN DOTS-346;So;0;L;;;;;N;;;;; 282D;BRAILLE PATTERN DOTS-1346;So;0;L;;;;;N;;;;; 282E;BRAILLE PATTERN DOTS-2346;So;0;L;;;;;N;;;;; 282F;BRAILLE PATTERN DOTS-12346;So;0;L;;;;;N;;;;; 2830;BRAILLE PATTERN DOTS-56;So;0;L;;;;;N;;;;; 2831;BRAILLE PATTERN DOTS-156;So;0;L;;;;;N;;;;; 2832;BRAILLE PATTERN DOTS-256;So;0;L;;;;;N;;;;; 2833;BRAILLE PATTERN DOTS-1256;So;0;L;;;;;N;;;;; 2834;BRAILLE PATTERN DOTS-356;So;0;L;;;;;N;;;;; 2835;BRAILLE PATTERN DOTS-1356;So;0;L;;;;;N;;;;; 2836;BRAILLE PATTERN DOTS-2356;So;0;L;;;;;N;;;;; 2837;BRAILLE PATTERN DOTS-12356;So;0;L;;;;;N;;;;; 2838;BRAILLE PATTERN DOTS-456;So;0;L;;;;;N;;;;; 2839;BRAILLE PATTERN DOTS-1456;So;0;L;;;;;N;;;;; 283A;BRAILLE PATTERN DOTS-2456;So;0;L;;;;;N;;;;; 283B;BRAILLE PATTERN DOTS-12456;So;0;L;;;;;N;;;;; 283C;BRAILLE PATTERN DOTS-3456;So;0;L;;;;;N;;;;; 283D;BRAILLE PATTERN DOTS-13456;So;0;L;;;;;N;;;;; 283E;BRAILLE PATTERN DOTS-23456;So;0;L;;;;;N;;;;; 283F;BRAILLE PATTERN DOTS-123456;So;0;L;;;;;N;;;;; 2840;BRAILLE PATTERN DOTS-7;So;0;L;;;;;N;;;;; 2841;BRAILLE PATTERN DOTS-17;So;0;L;;;;;N;;;;; 2842;BRAILLE PATTERN DOTS-27;So;0;L;;;;;N;;;;; 2843;BRAILLE PATTERN DOTS-127;So;0;L;;;;;N;;;;; 2844;BRAILLE PATTERN DOTS-37;So;0;L;;;;;N;;;;; 2845;BRAILLE PATTERN DOTS-137;So;0;L;;;;;N;;;;; 2846;BRAILLE PATTERN DOTS-237;So;0;L;;;;;N;;;;; 2847;BRAILLE PATTERN DOTS-1237;So;0;L;;;;;N;;;;; 2848;BRAILLE PATTERN DOTS-47;So;0;L;;;;;N;;;;; 2849;BRAILLE PATTERN DOTS-147;So;0;L;;;;;N;;;;; 284A;BRAILLE PATTERN DOTS-247;So;0;L;;;;;N;;;;; 284B;BRAILLE PATTERN DOTS-1247;So;0;L;;;;;N;;;;; 284C;BRAILLE PATTERN DOTS-347;So;0;L;;;;;N;;;;; 284D;BRAILLE PATTERN DOTS-1347;So;0;L;;;;;N;;;;; 284E;BRAILLE PATTERN DOTS-2347;So;0;L;;;;;N;;;;; 284F;BRAILLE PATTERN DOTS-12347;So;0;L;;;;;N;;;;; 2850;BRAILLE PATTERN DOTS-57;So;0;L;;;;;N;;;;; 2851;BRAILLE PATTERN DOTS-157;So;0;L;;;;;N;;;;; 2852;BRAILLE PATTERN DOTS-257;So;0;L;;;;;N;;;;; 2853;BRAILLE PATTERN DOTS-1257;So;0;L;;;;;N;;;;; 2854;BRAILLE PATTERN DOTS-357;So;0;L;;;;;N;;;;; 2855;BRAILLE PATTERN DOTS-1357;So;0;L;;;;;N;;;;; 2856;BRAILLE PATTERN DOTS-2357;So;0;L;;;;;N;;;;; 2857;BRAILLE PATTERN DOTS-12357;So;0;L;;;;;N;;;;; 2858;BRAILLE PATTERN DOTS-457;So;0;L;;;;;N;;;;; 2859;BRAILLE PATTERN DOTS-1457;So;0;L;;;;;N;;;;; 285A;BRAILLE PATTERN DOTS-2457;So;0;L;;;;;N;;;;; 285B;BRAILLE PATTERN DOTS-12457;So;0;L;;;;;N;;;;; 285C;BRAILLE PATTERN DOTS-3457;So;0;L;;;;;N;;;;; 285D;BRAILLE PATTERN DOTS-13457;So;0;L;;;;;N;;;;; 285E;BRAILLE PATTERN DOTS-23457;So;0;L;;;;;N;;;;; 285F;BRAILLE PATTERN DOTS-123457;So;0;L;;;;;N;;;;; 2860;BRAILLE PATTERN DOTS-67;So;0;L;;;;;N;;;;; 2861;BRAILLE PATTERN DOTS-167;So;0;L;;;;;N;;;;; 2862;BRAILLE PATTERN DOTS-267;So;0;L;;;;;N;;;;; 2863;BRAILLE PATTERN DOTS-1267;So;0;L;;;;;N;;;;; 2864;BRAILLE PATTERN DOTS-367;So;0;L;;;;;N;;;;; 2865;BRAILLE PATTERN DOTS-1367;So;0;L;;;;;N;;;;; 2866;BRAILLE PATTERN DOTS-2367;So;0;L;;;;;N;;;;; 2867;BRAILLE PATTERN DOTS-12367;So;0;L;;;;;N;;;;; 2868;BRAILLE PATTERN DOTS-467;So;0;L;;;;;N;;;;; 2869;BRAILLE PATTERN DOTS-1467;So;0;L;;;;;N;;;;; 286A;BRAILLE PATTERN DOTS-2467;So;0;L;;;;;N;;;;; 286B;BRAILLE PATTERN DOTS-12467;So;0;L;;;;;N;;;;; 286C;BRAILLE PATTERN DOTS-3467;So;0;L;;;;;N;;;;; 286D;BRAILLE PATTERN DOTS-13467;So;0;L;;;;;N;;;;; 286E;BRAILLE PATTERN DOTS-23467;So;0;L;;;;;N;;;;; 286F;BRAILLE PATTERN DOTS-123467;So;0;L;;;;;N;;;;; 2870;BRAILLE PATTERN DOTS-567;So;0;L;;;;;N;;;;; 2871;BRAILLE PATTERN DOTS-1567;So;0;L;;;;;N;;;;; 2872;BRAILLE PATTERN DOTS-2567;So;0;L;;;;;N;;;;; 2873;BRAILLE PATTERN DOTS-12567;So;0;L;;;;;N;;;;; 2874;BRAILLE PATTERN DOTS-3567;So;0;L;;;;;N;;;;; 2875;BRAILLE PATTERN DOTS-13567;So;0;L;;;;;N;;;;; 2876;BRAILLE PATTERN DOTS-23567;So;0;L;;;;;N;;;;; 2877;BRAILLE PATTERN DOTS-123567;So;0;L;;;;;N;;;;; 2878;BRAILLE PATTERN DOTS-4567;So;0;L;;;;;N;;;;; 2879;BRAILLE PATTERN DOTS-14567;So;0;L;;;;;N;;;;; 287A;BRAILLE PATTERN DOTS-24567;So;0;L;;;;;N;;;;; 287B;BRAILLE PATTERN DOTS-124567;So;0;L;;;;;N;;;;; 287C;BRAILLE PATTERN DOTS-34567;So;0;L;;;;;N;;;;; 287D;BRAILLE PATTERN DOTS-134567;So;0;L;;;;;N;;;;; 287E;BRAILLE PATTERN DOTS-234567;So;0;L;;;;;N;;;;; 287F;BRAILLE PATTERN DOTS-1234567;So;0;L;;;;;N;;;;; 2880;BRAILLE PATTERN DOTS-8;So;0;L;;;;;N;;;;; 2881;BRAILLE PATTERN DOTS-18;So;0;L;;;;;N;;;;; 2882;BRAILLE PATTERN DOTS-28;So;0;L;;;;;N;;;;; 2883;BRAILLE PATTERN DOTS-128;So;0;L;;;;;N;;;;; 2884;BRAILLE PATTERN DOTS-38;So;0;L;;;;;N;;;;; 2885;BRAILLE PATTERN DOTS-138;So;0;L;;;;;N;;;;; 2886;BRAILLE PATTERN DOTS-238;So;0;L;;;;;N;;;;; 2887;BRAILLE PATTERN DOTS-1238;So;0;L;;;;;N;;;;; 2888;BRAILLE PATTERN DOTS-48;So;0;L;;;;;N;;;;; 2889;BRAILLE PATTERN DOTS-148;So;0;L;;;;;N;;;;; 288A;BRAILLE PATTERN DOTS-248;So;0;L;;;;;N;;;;; 288B;BRAILLE PATTERN DOTS-1248;So;0;L;;;;;N;;;;; 288C;BRAILLE PATTERN DOTS-348;So;0;L;;;;;N;;;;; 288D;BRAILLE PATTERN DOTS-1348;So;0;L;;;;;N;;;;; 288E;BRAILLE PATTERN DOTS-2348;So;0;L;;;;;N;;;;; 288F;BRAILLE PATTERN DOTS-12348;So;0;L;;;;;N;;;;; 2890;BRAILLE PATTERN DOTS-58;So;0;L;;;;;N;;;;; 2891;BRAILLE PATTERN DOTS-158;So;0;L;;;;;N;;;;; 2892;BRAILLE PATTERN DOTS-258;So;0;L;;;;;N;;;;; 2893;BRAILLE PATTERN DOTS-1258;So;0;L;;;;;N;;;;; 2894;BRAILLE PATTERN DOTS-358;So;0;L;;;;;N;;;;; 2895;BRAILLE PATTERN DOTS-1358;So;0;L;;;;;N;;;;; 2896;BRAILLE PATTERN DOTS-2358;So;0;L;;;;;N;;;;; 2897;BRAILLE PATTERN DOTS-12358;So;0;L;;;;;N;;;;; 2898;BRAILLE PATTERN DOTS-458;So;0;L;;;;;N;;;;; 2899;BRAILLE PATTERN DOTS-1458;So;0;L;;;;;N;;;;; 289A;BRAILLE PATTERN DOTS-2458;So;0;L;;;;;N;;;;; 289B;BRAILLE PATTERN DOTS-12458;So;0;L;;;;;N;;;;; 289C;BRAILLE PATTERN DOTS-3458;So;0;L;;;;;N;;;;; 289D;BRAILLE PATTERN DOTS-13458;So;0;L;;;;;N;;;;; 289E;BRAILLE PATTERN DOTS-23458;So;0;L;;;;;N;;;;; 289F;BRAILLE PATTERN DOTS-123458;So;0;L;;;;;N;;;;; 28A0;BRAILLE PATTERN DOTS-68;So;0;L;;;;;N;;;;; 28A1;BRAILLE PATTERN DOTS-168;So;0;L;;;;;N;;;;; 28A2;BRAILLE PATTERN DOTS-268;So;0;L;;;;;N;;;;; 28A3;BRAILLE PATTERN DOTS-1268;So;0;L;;;;;N;;;;; 28A4;BRAILLE PATTERN DOTS-368;So;0;L;;;;;N;;;;; 28A5;BRAILLE PATTERN DOTS-1368;So;0;L;;;;;N;;;;; 28A6;BRAILLE PATTERN DOTS-2368;So;0;L;;;;;N;;;;; 28A7;BRAILLE PATTERN DOTS-12368;So;0;L;;;;;N;;;;; 28A8;BRAILLE PATTERN DOTS-468;So;0;L;;;;;N;;;;; 28A9;BRAILLE PATTERN DOTS-1468;So;0;L;;;;;N;;;;; 28AA;BRAILLE PATTERN DOTS-2468;So;0;L;;;;;N;;;;; 28AB;BRAILLE PATTERN DOTS-12468;So;0;L;;;;;N;;;;; 28AC;BRAILLE PATTERN DOTS-3468;So;0;L;;;;;N;;;;; 28AD;BRAILLE PATTERN DOTS-13468;So;0;L;;;;;N;;;;; 28AE;BRAILLE PATTERN DOTS-23468;So;0;L;;;;;N;;;;; 28AF;BRAILLE PATTERN DOTS-123468;So;0;L;;;;;N;;;;; 28B0;BRAILLE PATTERN DOTS-568;So;0;L;;;;;N;;;;; 28B1;BRAILLE PATTERN DOTS-1568;So;0;L;;;;;N;;;;; 28B2;BRAILLE PATTERN DOTS-2568;So;0;L;;;;;N;;;;; 28B3;BRAILLE PATTERN DOTS-12568;So;0;L;;;;;N;;;;; 28B4;BRAILLE PATTERN DOTS-3568;So;0;L;;;;;N;;;;; 28B5;BRAILLE PATTERN DOTS-13568;So;0;L;;;;;N;;;;; 28B6;BRAILLE PATTERN DOTS-23568;So;0;L;;;;;N;;;;; 28B7;BRAILLE PATTERN DOTS-123568;So;0;L;;;;;N;;;;; 28B8;BRAILLE PATTERN DOTS-4568;So;0;L;;;;;N;;;;; 28B9;BRAILLE PATTERN DOTS-14568;So;0;L;;;;;N;;;;; 28BA;BRAILLE PATTERN DOTS-24568;So;0;L;;;;;N;;;;; 28BB;BRAILLE PATTERN DOTS-124568;So;0;L;;;;;N;;;;; 28BC;BRAILLE PATTERN DOTS-34568;So;0;L;;;;;N;;;;; 28BD;BRAILLE PATTERN DOTS-134568;So;0;L;;;;;N;;;;; 28BE;BRAILLE PATTERN DOTS-234568;So;0;L;;;;;N;;;;; 28BF;BRAILLE PATTERN DOTS-1234568;So;0;L;;;;;N;;;;; 28C0;BRAILLE PATTERN DOTS-78;So;0;L;;;;;N;;;;; 28C1;BRAILLE PATTERN DOTS-178;So;0;L;;;;;N;;;;; 28C2;BRAILLE PATTERN DOTS-278;So;0;L;;;;;N;;;;; 28C3;BRAILLE PATTERN DOTS-1278;So;0;L;;;;;N;;;;; 28C4;BRAILLE PATTERN DOTS-378;So;0;L;;;;;N;;;;; 28C5;BRAILLE PATTERN DOTS-1378;So;0;L;;;;;N;;;;; 28C6;BRAILLE PATTERN DOTS-2378;So;0;L;;;;;N;;;;; 28C7;BRAILLE PATTERN DOTS-12378;So;0;L;;;;;N;;;;; 28C8;BRAILLE PATTERN DOTS-478;So;0;L;;;;;N;;;;; 28C9;BRAILLE PATTERN DOTS-1478;So;0;L;;;;;N;;;;; 28CA;BRAILLE PATTERN DOTS-2478;So;0;L;;;;;N;;;;; 28CB;BRAILLE PATTERN DOTS-12478;So;0;L;;;;;N;;;;; 28CC;BRAILLE PATTERN DOTS-3478;So;0;L;;;;;N;;;;; 28CD;BRAILLE PATTERN DOTS-13478;So;0;L;;;;;N;;;;; 28CE;BRAILLE PATTERN DOTS-23478;So;0;L;;;;;N;;;;; 28CF;BRAILLE PATTERN DOTS-123478;So;0;L;;;;;N;;;;; 28D0;BRAILLE PATTERN DOTS-578;So;0;L;;;;;N;;;;; 28D1;BRAILLE PATTERN DOTS-1578;So;0;L;;;;;N;;;;; 28D2;BRAILLE PATTERN DOTS-2578;So;0;L;;;;;N;;;;; 28D3;BRAILLE PATTERN DOTS-12578;So;0;L;;;;;N;;;;; 28D4;BRAILLE PATTERN DOTS-3578;So;0;L;;;;;N;;;;; 28D5;BRAILLE PATTERN DOTS-13578;So;0;L;;;;;N;;;;; 28D6;BRAILLE PATTERN DOTS-23578;So;0;L;;;;;N;;;;; 28D7;BRAILLE PATTERN DOTS-123578;So;0;L;;;;;N;;;;; 28D8;BRAILLE PATTERN DOTS-4578;So;0;L;;;;;N;;;;; 28D9;BRAILLE PATTERN DOTS-14578;So;0;L;;;;;N;;;;; 28DA;BRAILLE PATTERN DOTS-24578;So;0;L;;;;;N;;;;; 28DB;BRAILLE PATTERN DOTS-124578;So;0;L;;;;;N;;;;; 28DC;BRAILLE PATTERN DOTS-34578;So;0;L;;;;;N;;;;; 28DD;BRAILLE PATTERN DOTS-134578;So;0;L;;;;;N;;;;; 28DE;BRAILLE PATTERN DOTS-234578;So;0;L;;;;;N;;;;; 28DF;BRAILLE PATTERN DOTS-1234578;So;0;L;;;;;N;;;;; 28E0;BRAILLE PATTERN DOTS-678;So;0;L;;;;;N;;;;; 28E1;BRAILLE PATTERN DOTS-1678;So;0;L;;;;;N;;;;; 28E2;BRAILLE PATTERN DOTS-2678;So;0;L;;;;;N;;;;; 28E3;BRAILLE PATTERN DOTS-12678;So;0;L;;;;;N;;;;; 28E4;BRAILLE PATTERN DOTS-3678;So;0;L;;;;;N;;;;; 28E5;BRAILLE PATTERN DOTS-13678;So;0;L;;;;;N;;;;; 28E6;BRAILLE PATTERN DOTS-23678;So;0;L;;;;;N;;;;; 28E7;BRAILLE PATTERN DOTS-123678;So;0;L;;;;;N;;;;; 28E8;BRAILLE PATTERN DOTS-4678;So;0;L;;;;;N;;;;; 28E9;BRAILLE PATTERN DOTS-14678;So;0;L;;;;;N;;;;; 28EA;BRAILLE PATTERN DOTS-24678;So;0;L;;;;;N;;;;; 28EB;BRAILLE PATTERN DOTS-124678;So;0;L;;;;;N;;;;; 28EC;BRAILLE PATTERN DOTS-34678;So;0;L;;;;;N;;;;; 28ED;BRAILLE PATTERN DOTS-134678;So;0;L;;;;;N;;;;; 28EE;BRAILLE PATTERN DOTS-234678;So;0;L;;;;;N;;;;; 28EF;BRAILLE PATTERN DOTS-1234678;So;0;L;;;;;N;;;;; 28F0;BRAILLE PATTERN DOTS-5678;So;0;L;;;;;N;;;;; 28F1;BRAILLE PATTERN DOTS-15678;So;0;L;;;;;N;;;;; 28F2;BRAILLE PATTERN DOTS-25678;So;0;L;;;;;N;;;;; 28F3;BRAILLE PATTERN DOTS-125678;So;0;L;;;;;N;;;;; 28F4;BRAILLE PATTERN DOTS-35678;So;0;L;;;;;N;;;;; 28F5;BRAILLE PATTERN DOTS-135678;So;0;L;;;;;N;;;;; 28F6;BRAILLE PATTERN DOTS-235678;So;0;L;;;;;N;;;;; 28F7;BRAILLE PATTERN DOTS-1235678;So;0;L;;;;;N;;;;; 28F8;BRAILLE PATTERN DOTS-45678;So;0;L;;;;;N;;;;; 28F9;BRAILLE PATTERN DOTS-145678;So;0;L;;;;;N;;;;; 28FA;BRAILLE PATTERN DOTS-245678;So;0;L;;;;;N;;;;; 28FB;BRAILLE PATTERN DOTS-1245678;So;0;L;;;;;N;;;;; 28FC;BRAILLE PATTERN DOTS-345678;So;0;L;;;;;N;;;;; 28FD;BRAILLE PATTERN DOTS-1345678;So;0;L;;;;;N;;;;; 28FE;BRAILLE PATTERN DOTS-2345678;So;0;L;;;;;N;;;;; 28FF;BRAILLE PATTERN DOTS-12345678;So;0;L;;;;;N;;;;; 2900;RIGHTWARDS TWO-HEADED ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2901;RIGHTWARDS TWO-HEADED ARROW WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2902;LEFTWARDS DOUBLE ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2903;RIGHTWARDS DOUBLE ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2904;LEFT RIGHT DOUBLE ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2905;RIGHTWARDS TWO-HEADED ARROW FROM BAR;Sm;0;ON;;;;;N;;;;; 2906;LEFTWARDS DOUBLE ARROW FROM BAR;Sm;0;ON;;;;;N;;;;; 2907;RIGHTWARDS DOUBLE ARROW FROM BAR;Sm;0;ON;;;;;N;;;;; 2908;DOWNWARDS ARROW WITH HORIZONTAL STROKE;Sm;0;ON;;;;;N;;;;; 2909;UPWARDS ARROW WITH HORIZONTAL STROKE;Sm;0;ON;;;;;N;;;;; 290A;UPWARDS TRIPLE ARROW;Sm;0;ON;;;;;N;;;;; 290B;DOWNWARDS TRIPLE ARROW;Sm;0;ON;;;;;N;;;;; 290C;LEFTWARDS DOUBLE DASH ARROW;Sm;0;ON;;;;;N;;;;; 290D;RIGHTWARDS DOUBLE DASH ARROW;Sm;0;ON;;;;;N;;;;; 290E;LEFTWARDS TRIPLE DASH ARROW;Sm;0;ON;;;;;N;;;;; 290F;RIGHTWARDS TRIPLE DASH ARROW;Sm;0;ON;;;;;N;;;;; 2910;RIGHTWARDS TWO-HEADED TRIPLE DASH ARROW;Sm;0;ON;;;;;N;;;;; 2911;RIGHTWARDS ARROW WITH DOTTED STEM;Sm;0;ON;;;;;N;;;;; 2912;UPWARDS ARROW TO BAR;Sm;0;ON;;;;;N;;;;; 2913;DOWNWARDS ARROW TO BAR;Sm;0;ON;;;;;N;;;;; 2914;RIGHTWARDS ARROW WITH TAIL WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2915;RIGHTWARDS ARROW WITH TAIL WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2916;RIGHTWARDS TWO-HEADED ARROW WITH TAIL;Sm;0;ON;;;;;N;;;;; 2917;RIGHTWARDS TWO-HEADED ARROW WITH TAIL WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2918;RIGHTWARDS TWO-HEADED ARROW WITH TAIL WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2919;LEFTWARDS ARROW-TAIL;Sm;0;ON;;;;;N;;;;; 291A;RIGHTWARDS ARROW-TAIL;Sm;0;ON;;;;;N;;;;; 291B;LEFTWARDS DOUBLE ARROW-TAIL;Sm;0;ON;;;;;N;;;;; 291C;RIGHTWARDS DOUBLE ARROW-TAIL;Sm;0;ON;;;;;N;;;;; 291D;LEFTWARDS ARROW TO BLACK DIAMOND;Sm;0;ON;;;;;N;;;;; 291E;RIGHTWARDS ARROW TO BLACK DIAMOND;Sm;0;ON;;;;;N;;;;; 291F;LEFTWARDS ARROW FROM BAR TO BLACK DIAMOND;Sm;0;ON;;;;;N;;;;; 2920;RIGHTWARDS ARROW FROM BAR TO BLACK DIAMOND;Sm;0;ON;;;;;N;;;;; 2921;NORTH WEST AND SOUTH EAST ARROW;Sm;0;ON;;;;;N;;;;; 2922;NORTH EAST AND SOUTH WEST ARROW;Sm;0;ON;;;;;N;;;;; 2923;NORTH WEST ARROW WITH HOOK;Sm;0;ON;;;;;N;;;;; 2924;NORTH EAST ARROW WITH HOOK;Sm;0;ON;;;;;N;;;;; 2925;SOUTH EAST ARROW WITH HOOK;Sm;0;ON;;;;;N;;;;; 2926;SOUTH WEST ARROW WITH HOOK;Sm;0;ON;;;;;N;;;;; 2927;NORTH WEST ARROW AND NORTH EAST ARROW;Sm;0;ON;;;;;N;;;;; 2928;NORTH EAST ARROW AND SOUTH EAST ARROW;Sm;0;ON;;;;;N;;;;; 2929;SOUTH EAST ARROW AND SOUTH WEST ARROW;Sm;0;ON;;;;;N;;;;; 292A;SOUTH WEST ARROW AND NORTH WEST ARROW;Sm;0;ON;;;;;N;;;;; 292B;RISING DIAGONAL CROSSING FALLING DIAGONAL;Sm;0;ON;;;;;N;;;;; 292C;FALLING DIAGONAL CROSSING RISING DIAGONAL;Sm;0;ON;;;;;N;;;;; 292D;SOUTH EAST ARROW CROSSING NORTH EAST ARROW;Sm;0;ON;;;;;N;;;;; 292E;NORTH EAST ARROW CROSSING SOUTH EAST ARROW;Sm;0;ON;;;;;N;;;;; 292F;FALLING DIAGONAL CROSSING NORTH EAST ARROW;Sm;0;ON;;;;;N;;;;; 2930;RISING DIAGONAL CROSSING SOUTH EAST ARROW;Sm;0;ON;;;;;N;;;;; 2931;NORTH EAST ARROW CROSSING NORTH WEST ARROW;Sm;0;ON;;;;;N;;;;; 2932;NORTH WEST ARROW CROSSING NORTH EAST ARROW;Sm;0;ON;;;;;N;;;;; 2933;WAVE ARROW POINTING DIRECTLY RIGHT;Sm;0;ON;;;;;N;;;;; 2934;ARROW POINTING RIGHTWARDS THEN CURVING UPWARDS;Sm;0;ON;;;;;N;;;;; 2935;ARROW POINTING RIGHTWARDS THEN CURVING DOWNWARDS;Sm;0;ON;;;;;N;;;;; 2936;ARROW POINTING DOWNWARDS THEN CURVING LEFTWARDS;Sm;0;ON;;;;;N;;;;; 2937;ARROW POINTING DOWNWARDS THEN CURVING RIGHTWARDS;Sm;0;ON;;;;;N;;;;; 2938;RIGHT-SIDE ARC CLOCKWISE ARROW;Sm;0;ON;;;;;N;;;;; 2939;LEFT-SIDE ARC ANTICLOCKWISE ARROW;Sm;0;ON;;;;;N;;;;; 293A;TOP ARC ANTICLOCKWISE ARROW;Sm;0;ON;;;;;N;;;;; 293B;BOTTOM ARC ANTICLOCKWISE ARROW;Sm;0;ON;;;;;N;;;;; 293C;TOP ARC CLOCKWISE ARROW WITH MINUS;Sm;0;ON;;;;;N;;;;; 293D;TOP ARC ANTICLOCKWISE ARROW WITH PLUS;Sm;0;ON;;;;;N;;;;; 293E;LOWER RIGHT SEMICIRCULAR CLOCKWISE ARROW;Sm;0;ON;;;;;N;;;;; 293F;LOWER LEFT SEMICIRCULAR ANTICLOCKWISE ARROW;Sm;0;ON;;;;;N;;;;; 2940;ANTICLOCKWISE CLOSED CIRCLE ARROW;Sm;0;ON;;;;;N;;;;; 2941;CLOCKWISE CLOSED CIRCLE ARROW;Sm;0;ON;;;;;N;;;;; 2942;RIGHTWARDS ARROW ABOVE SHORT LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 2943;LEFTWARDS ARROW ABOVE SHORT RIGHTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 2944;SHORT RIGHTWARDS ARROW ABOVE LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 2945;RIGHTWARDS ARROW WITH PLUS BELOW;Sm;0;ON;;;;;N;;;;; 2946;LEFTWARDS ARROW WITH PLUS BELOW;Sm;0;ON;;;;;N;;;;; 2947;RIGHTWARDS ARROW THROUGH X;Sm;0;ON;;;;;N;;;;; 2948;LEFT RIGHT ARROW THROUGH SMALL CIRCLE;Sm;0;ON;;;;;N;;;;; 2949;UPWARDS TWO-HEADED ARROW FROM SMALL CIRCLE;Sm;0;ON;;;;;N;;;;; 294A;LEFT BARB UP RIGHT BARB DOWN HARPOON;Sm;0;ON;;;;;N;;;;; 294B;LEFT BARB DOWN RIGHT BARB UP HARPOON;Sm;0;ON;;;;;N;;;;; 294C;UP BARB RIGHT DOWN BARB LEFT HARPOON;Sm;0;ON;;;;;N;;;;; 294D;UP BARB LEFT DOWN BARB RIGHT HARPOON;Sm;0;ON;;;;;N;;;;; 294E;LEFT BARB UP RIGHT BARB UP HARPOON;Sm;0;ON;;;;;N;;;;; 294F;UP BARB RIGHT DOWN BARB RIGHT HARPOON;Sm;0;ON;;;;;N;;;;; 2950;LEFT BARB DOWN RIGHT BARB DOWN HARPOON;Sm;0;ON;;;;;N;;;;; 2951;UP BARB LEFT DOWN BARB LEFT HARPOON;Sm;0;ON;;;;;N;;;;; 2952;LEFTWARDS HARPOON WITH BARB UP TO BAR;Sm;0;ON;;;;;N;;;;; 2953;RIGHTWARDS HARPOON WITH BARB UP TO BAR;Sm;0;ON;;;;;N;;;;; 2954;UPWARDS HARPOON WITH BARB RIGHT TO BAR;Sm;0;ON;;;;;N;;;;; 2955;DOWNWARDS HARPOON WITH BARB RIGHT TO BAR;Sm;0;ON;;;;;N;;;;; 2956;LEFTWARDS HARPOON WITH BARB DOWN TO BAR;Sm;0;ON;;;;;N;;;;; 2957;RIGHTWARDS HARPOON WITH BARB DOWN TO BAR;Sm;0;ON;;;;;N;;;;; 2958;UPWARDS HARPOON WITH BARB LEFT TO BAR;Sm;0;ON;;;;;N;;;;; 2959;DOWNWARDS HARPOON WITH BARB LEFT TO BAR;Sm;0;ON;;;;;N;;;;; 295A;LEFTWARDS HARPOON WITH BARB UP FROM BAR;Sm;0;ON;;;;;N;;;;; 295B;RIGHTWARDS HARPOON WITH BARB UP FROM BAR;Sm;0;ON;;;;;N;;;;; 295C;UPWARDS HARPOON WITH BARB RIGHT FROM BAR;Sm;0;ON;;;;;N;;;;; 295D;DOWNWARDS HARPOON WITH BARB RIGHT FROM BAR;Sm;0;ON;;;;;N;;;;; 295E;LEFTWARDS HARPOON WITH BARB DOWN FROM BAR;Sm;0;ON;;;;;N;;;;; 295F;RIGHTWARDS HARPOON WITH BARB DOWN FROM BAR;Sm;0;ON;;;;;N;;;;; 2960;UPWARDS HARPOON WITH BARB LEFT FROM BAR;Sm;0;ON;;;;;N;;;;; 2961;DOWNWARDS HARPOON WITH BARB LEFT FROM BAR;Sm;0;ON;;;;;N;;;;; 2962;LEFTWARDS HARPOON WITH BARB UP ABOVE LEFTWARDS HARPOON WITH BARB DOWN;Sm;0;ON;;;;;N;;;;; 2963;UPWARDS HARPOON WITH BARB LEFT BESIDE UPWARDS HARPOON WITH BARB RIGHT;Sm;0;ON;;;;;N;;;;; 2964;RIGHTWARDS HARPOON WITH BARB UP ABOVE RIGHTWARDS HARPOON WITH BARB DOWN;Sm;0;ON;;;;;N;;;;; 2965;DOWNWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT;Sm;0;ON;;;;;N;;;;; 2966;LEFTWARDS HARPOON WITH BARB UP ABOVE RIGHTWARDS HARPOON WITH BARB UP;Sm;0;ON;;;;;N;;;;; 2967;LEFTWARDS HARPOON WITH BARB DOWN ABOVE RIGHTWARDS HARPOON WITH BARB DOWN;Sm;0;ON;;;;;N;;;;; 2968;RIGHTWARDS HARPOON WITH BARB UP ABOVE LEFTWARDS HARPOON WITH BARB UP;Sm;0;ON;;;;;N;;;;; 2969;RIGHTWARDS HARPOON WITH BARB DOWN ABOVE LEFTWARDS HARPOON WITH BARB DOWN;Sm;0;ON;;;;;N;;;;; 296A;LEFTWARDS HARPOON WITH BARB UP ABOVE LONG DASH;Sm;0;ON;;;;;N;;;;; 296B;LEFTWARDS HARPOON WITH BARB DOWN BELOW LONG DASH;Sm;0;ON;;;;;N;;;;; 296C;RIGHTWARDS HARPOON WITH BARB UP ABOVE LONG DASH;Sm;0;ON;;;;;N;;;;; 296D;RIGHTWARDS HARPOON WITH BARB DOWN BELOW LONG DASH;Sm;0;ON;;;;;N;;;;; 296E;UPWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT;Sm;0;ON;;;;;N;;;;; 296F;DOWNWARDS HARPOON WITH BARB LEFT BESIDE UPWARDS HARPOON WITH BARB RIGHT;Sm;0;ON;;;;;N;;;;; 2970;RIGHT DOUBLE ARROW WITH ROUNDED HEAD;Sm;0;ON;;;;;N;;;;; 2971;EQUALS SIGN ABOVE RIGHTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 2972;TILDE OPERATOR ABOVE RIGHTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 2973;LEFTWARDS ARROW ABOVE TILDE OPERATOR;Sm;0;ON;;;;;N;;;;; 2974;RIGHTWARDS ARROW ABOVE TILDE OPERATOR;Sm;0;ON;;;;;N;;;;; 2975;RIGHTWARDS ARROW ABOVE ALMOST EQUAL TO;Sm;0;ON;;;;;N;;;;; 2976;LESS-THAN ABOVE LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 2977;LEFTWARDS ARROW THROUGH LESS-THAN;Sm;0;ON;;;;;N;;;;; 2978;GREATER-THAN ABOVE RIGHTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 2979;SUBSET ABOVE RIGHTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 297A;LEFTWARDS ARROW THROUGH SUBSET;Sm;0;ON;;;;;N;;;;; 297B;SUPERSET ABOVE LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 297C;LEFT FISH TAIL;Sm;0;ON;;;;;N;;;;; 297D;RIGHT FISH TAIL;Sm;0;ON;;;;;N;;;;; 297E;UP FISH TAIL;Sm;0;ON;;;;;N;;;;; 297F;DOWN FISH TAIL;Sm;0;ON;;;;;N;;;;; 2980;TRIPLE VERTICAL BAR DELIMITER;Sm;0;ON;;;;;N;;;;; 2981;Z NOTATION SPOT;Sm;0;ON;;;;;N;;;;; 2982;Z NOTATION TYPE COLON;Sm;0;ON;;;;;N;;;;; 2983;LEFT WHITE CURLY BRACKET;Ps;0;ON;;;;;Y;;;;; 2984;RIGHT WHITE CURLY BRACKET;Pe;0;ON;;;;;Y;;;;; 2985;LEFT WHITE PARENTHESIS;Ps;0;ON;;;;;Y;;;;; 2986;RIGHT WHITE PARENTHESIS;Pe;0;ON;;;;;Y;;;;; 2987;Z NOTATION LEFT IMAGE BRACKET;Ps;0;ON;;;;;Y;;;;; 2988;Z NOTATION RIGHT IMAGE BRACKET;Pe;0;ON;;;;;Y;;;;; 2989;Z NOTATION LEFT BINDING BRACKET;Ps;0;ON;;;;;Y;;;;; 298A;Z NOTATION RIGHT BINDING BRACKET;Pe;0;ON;;;;;Y;;;;; 298B;LEFT SQUARE BRACKET WITH UNDERBAR;Ps;0;ON;;;;;Y;;;;; 298C;RIGHT SQUARE BRACKET WITH UNDERBAR;Pe;0;ON;;;;;Y;;;;; 298D;LEFT SQUARE BRACKET WITH TICK IN TOP CORNER;Ps;0;ON;;;;;Y;;;;; 298E;RIGHT SQUARE BRACKET WITH TICK IN BOTTOM CORNER;Pe;0;ON;;;;;Y;;;;; 298F;LEFT SQUARE BRACKET WITH TICK IN BOTTOM CORNER;Ps;0;ON;;;;;Y;;;;; 2990;RIGHT SQUARE BRACKET WITH TICK IN TOP CORNER;Pe;0;ON;;;;;Y;;;;; 2991;LEFT ANGLE BRACKET WITH DOT;Ps;0;ON;;;;;Y;;;;; 2992;RIGHT ANGLE BRACKET WITH DOT;Pe;0;ON;;;;;Y;;;;; 2993;LEFT ARC LESS-THAN BRACKET;Ps;0;ON;;;;;Y;;;;; 2994;RIGHT ARC GREATER-THAN BRACKET;Pe;0;ON;;;;;Y;;;;; 2995;DOUBLE LEFT ARC GREATER-THAN BRACKET;Ps;0;ON;;;;;Y;;;;; 2996;DOUBLE RIGHT ARC LESS-THAN BRACKET;Pe;0;ON;;;;;Y;;;;; 2997;LEFT BLACK TORTOISE SHELL BRACKET;Ps;0;ON;;;;;Y;;;;; 2998;RIGHT BLACK TORTOISE SHELL BRACKET;Pe;0;ON;;;;;Y;;;;; 2999;DOTTED FENCE;Sm;0;ON;;;;;N;;;;; 299A;VERTICAL ZIGZAG LINE;Sm;0;ON;;;;;N;;;;; 299B;MEASURED ANGLE OPENING LEFT;Sm;0;ON;;;;;Y;;;;; 299C;RIGHT ANGLE VARIANT WITH SQUARE;Sm;0;ON;;;;;Y;;;;; 299D;MEASURED RIGHT ANGLE WITH DOT;Sm;0;ON;;;;;Y;;;;; 299E;ANGLE WITH S INSIDE;Sm;0;ON;;;;;Y;;;;; 299F;ACUTE ANGLE;Sm;0;ON;;;;;Y;;;;; 29A0;SPHERICAL ANGLE OPENING LEFT;Sm;0;ON;;;;;Y;;;;; 29A1;SPHERICAL ANGLE OPENING UP;Sm;0;ON;;;;;Y;;;;; 29A2;TURNED ANGLE;Sm;0;ON;;;;;Y;;;;; 29A3;REVERSED ANGLE;Sm;0;ON;;;;;Y;;;;; 29A4;ANGLE WITH UNDERBAR;Sm;0;ON;;;;;Y;;;;; 29A5;REVERSED ANGLE WITH UNDERBAR;Sm;0;ON;;;;;Y;;;;; 29A6;OBLIQUE ANGLE OPENING UP;Sm;0;ON;;;;;Y;;;;; 29A7;OBLIQUE ANGLE OPENING DOWN;Sm;0;ON;;;;;Y;;;;; 29A8;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING UP AND RIGHT;Sm;0;ON;;;;;Y;;;;; 29A9;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING UP AND LEFT;Sm;0;ON;;;;;Y;;;;; 29AA;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING DOWN AND RIGHT;Sm;0;ON;;;;;Y;;;;; 29AB;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING DOWN AND LEFT;Sm;0;ON;;;;;Y;;;;; 29AC;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING RIGHT AND UP;Sm;0;ON;;;;;Y;;;;; 29AD;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING LEFT AND UP;Sm;0;ON;;;;;Y;;;;; 29AE;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING RIGHT AND DOWN;Sm;0;ON;;;;;Y;;;;; 29AF;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING LEFT AND DOWN;Sm;0;ON;;;;;Y;;;;; 29B0;REVERSED EMPTY SET;Sm;0;ON;;;;;N;;;;; 29B1;EMPTY SET WITH OVERBAR;Sm;0;ON;;;;;N;;;;; 29B2;EMPTY SET WITH SMALL CIRCLE ABOVE;Sm;0;ON;;;;;N;;;;; 29B3;EMPTY SET WITH RIGHT ARROW ABOVE;Sm;0;ON;;;;;N;;;;; 29B4;EMPTY SET WITH LEFT ARROW ABOVE;Sm;0;ON;;;;;N;;;;; 29B5;CIRCLE WITH HORIZONTAL BAR;Sm;0;ON;;;;;N;;;;; 29B6;CIRCLED VERTICAL BAR;Sm;0;ON;;;;;N;;;;; 29B7;CIRCLED PARALLEL;Sm;0;ON;;;;;N;;;;; 29B8;CIRCLED REVERSE SOLIDUS;Sm;0;ON;;;;;Y;;;;; 29B9;CIRCLED PERPENDICULAR;Sm;0;ON;;;;;N;;;;; 29BA;CIRCLE DIVIDED BY HORIZONTAL BAR AND TOP HALF DIVIDED BY VERTICAL BAR;Sm;0;ON;;;;;N;;;;; 29BB;CIRCLE WITH SUPERIMPOSED X;Sm;0;ON;;;;;N;;;;; 29BC;CIRCLED ANTICLOCKWISE-ROTATED DIVISION SIGN;Sm;0;ON;;;;;N;;;;; 29BD;UP ARROW THROUGH CIRCLE;Sm;0;ON;;;;;N;;;;; 29BE;CIRCLED WHITE BULLET;Sm;0;ON;;;;;N;;;;; 29BF;CIRCLED BULLET;Sm;0;ON;;;;;N;;;;; 29C0;CIRCLED LESS-THAN;Sm;0;ON;;;;;Y;;;;; 29C1;CIRCLED GREATER-THAN;Sm;0;ON;;;;;Y;;;;; 29C2;CIRCLE WITH SMALL CIRCLE TO THE RIGHT;Sm;0;ON;;;;;Y;;;;; 29C3;CIRCLE WITH TWO HORIZONTAL STROKES TO THE RIGHT;Sm;0;ON;;;;;Y;;;;; 29C4;SQUARED RISING DIAGONAL SLASH;Sm;0;ON;;;;;Y;;;;; 29C5;SQUARED FALLING DIAGONAL SLASH;Sm;0;ON;;;;;Y;;;;; 29C6;SQUARED ASTERISK;Sm;0;ON;;;;;N;;;;; 29C7;SQUARED SMALL CIRCLE;Sm;0;ON;;;;;N;;;;; 29C8;SQUARED SQUARE;Sm;0;ON;;;;;N;;;;; 29C9;TWO JOINED SQUARES;Sm;0;ON;;;;;Y;;;;; 29CA;TRIANGLE WITH DOT ABOVE;Sm;0;ON;;;;;N;;;;; 29CB;TRIANGLE WITH UNDERBAR;Sm;0;ON;;;;;N;;;;; 29CC;S IN TRIANGLE;Sm;0;ON;;;;;N;;;;; 29CD;TRIANGLE WITH SERIFS AT BOTTOM;Sm;0;ON;;;;;N;;;;; 29CE;RIGHT TRIANGLE ABOVE LEFT TRIANGLE;Sm;0;ON;;;;;Y;;;;; 29CF;LEFT TRIANGLE BESIDE VERTICAL BAR;Sm;0;ON;;;;;Y;;;;; 29D0;VERTICAL BAR BESIDE RIGHT TRIANGLE;Sm;0;ON;;;;;Y;;;;; 29D1;BOWTIE WITH LEFT HALF BLACK;Sm;0;ON;;;;;Y;;;;; 29D2;BOWTIE WITH RIGHT HALF BLACK;Sm;0;ON;;;;;Y;;;;; 29D3;BLACK BOWTIE;Sm;0;ON;;;;;N;;;;; 29D4;TIMES WITH LEFT HALF BLACK;Sm;0;ON;;;;;Y;;;;; 29D5;TIMES WITH RIGHT HALF BLACK;Sm;0;ON;;;;;Y;;;;; 29D6;WHITE HOURGLASS;Sm;0;ON;;;;;N;;;;; 29D7;BLACK HOURGLASS;Sm;0;ON;;;;;N;;;;; 29D8;LEFT WIGGLY FENCE;Ps;0;ON;;;;;Y;;;;; 29D9;RIGHT WIGGLY FENCE;Pe;0;ON;;;;;Y;;;;; 29DA;LEFT DOUBLE WIGGLY FENCE;Ps;0;ON;;;;;Y;;;;; 29DB;RIGHT DOUBLE WIGGLY FENCE;Pe;0;ON;;;;;Y;;;;; 29DC;INCOMPLETE INFINITY;Sm;0;ON;;;;;Y;;;;; 29DD;TIE OVER INFINITY;Sm;0;ON;;;;;N;;;;; 29DE;INFINITY NEGATED WITH VERTICAL BAR;Sm;0;ON;;;;;N;;;;; 29DF;DOUBLE-ENDED MULTIMAP;Sm;0;ON;;;;;N;;;;; 29E0;SQUARE WITH CONTOURED OUTLINE;Sm;0;ON;;;;;N;;;;; 29E1;INCREASES AS;Sm;0;ON;;;;;Y;;;;; 29E2;SHUFFLE PRODUCT;Sm;0;ON;;;;;N;;;;; 29E3;EQUALS SIGN AND SLANTED PARALLEL;Sm;0;ON;;;;;Y;;;;; 29E4;EQUALS SIGN AND SLANTED PARALLEL WITH TILDE ABOVE;Sm;0;ON;;;;;Y;;;;; 29E5;IDENTICAL TO AND SLANTED PARALLEL;Sm;0;ON;;;;;Y;;;;; 29E6;GLEICH STARK;Sm;0;ON;;;;;N;;;;; 29E7;THERMODYNAMIC;Sm;0;ON;;;;;N;;;;; 29E8;DOWN-POINTING TRIANGLE WITH LEFT HALF BLACK;Sm;0;ON;;;;;Y;;;;; 29E9;DOWN-POINTING TRIANGLE WITH RIGHT HALF BLACK;Sm;0;ON;;;;;Y;;;;; 29EA;BLACK DIAMOND WITH DOWN ARROW;Sm;0;ON;;;;;N;;;;; 29EB;BLACK LOZENGE;Sm;0;ON;;;;;N;;;;; 29EC;WHITE CIRCLE WITH DOWN ARROW;Sm;0;ON;;;;;N;;;;; 29ED;BLACK CIRCLE WITH DOWN ARROW;Sm;0;ON;;;;;N;;;;; 29EE;ERROR-BARRED WHITE SQUARE;Sm;0;ON;;;;;N;;;;; 29EF;ERROR-BARRED BLACK SQUARE;Sm;0;ON;;;;;N;;;;; 29F0;ERROR-BARRED WHITE DIAMOND;Sm;0;ON;;;;;N;;;;; 29F1;ERROR-BARRED BLACK DIAMOND;Sm;0;ON;;;;;N;;;;; 29F2;ERROR-BARRED WHITE CIRCLE;Sm;0;ON;;;;;N;;;;; 29F3;ERROR-BARRED BLACK CIRCLE;Sm;0;ON;;;;;N;;;;; 29F4;RULE-DELAYED;Sm;0;ON;;;;;Y;;;;; 29F5;REVERSE SOLIDUS OPERATOR;Sm;0;ON;;;;;Y;;;;; 29F6;SOLIDUS WITH OVERBAR;Sm;0;ON;;;;;Y;;;;; 29F7;REVERSE SOLIDUS WITH HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;; 29F8;BIG SOLIDUS;Sm;0;ON;;;;;Y;;;;; 29F9;BIG REVERSE SOLIDUS;Sm;0;ON;;;;;Y;;;;; 29FA;DOUBLE PLUS;Sm;0;ON;;;;;N;;;;; 29FB;TRIPLE PLUS;Sm;0;ON;;;;;N;;;;; 29FC;LEFT-POINTING CURVED ANGLE BRACKET;Ps;0;ON;;;;;Y;;;;; 29FD;RIGHT-POINTING CURVED ANGLE BRACKET;Pe;0;ON;;;;;Y;;;;; 29FE;TINY;Sm;0;ON;;;;;N;;;;; 29FF;MINY;Sm;0;ON;;;;;N;;;;; 2A00;N-ARY CIRCLED DOT OPERATOR;Sm;0;ON;;;;;N;;;;; 2A01;N-ARY CIRCLED PLUS OPERATOR;Sm;0;ON;;;;;N;;;;; 2A02;N-ARY CIRCLED TIMES OPERATOR;Sm;0;ON;;;;;N;;;;; 2A03;N-ARY UNION OPERATOR WITH DOT;Sm;0;ON;;;;;N;;;;; 2A04;N-ARY UNION OPERATOR WITH PLUS;Sm;0;ON;;;;;N;;;;; 2A05;N-ARY SQUARE INTERSECTION OPERATOR;Sm;0;ON;;;;;N;;;;; 2A06;N-ARY SQUARE UNION OPERATOR;Sm;0;ON;;;;;N;;;;; 2A07;TWO LOGICAL AND OPERATOR;Sm;0;ON;;;;;N;;;;; 2A08;TWO LOGICAL OR OPERATOR;Sm;0;ON;;;;;N;;;;; 2A09;N-ARY TIMES OPERATOR;Sm;0;ON;;;;;N;;;;; 2A0A;MODULO TWO SUM;Sm;0;ON;;;;;Y;;;;; 2A0B;SUMMATION WITH INTEGRAL;Sm;0;ON;;;;;Y;;;;; 2A0C;QUADRUPLE INTEGRAL OPERATOR;Sm;0;ON;<compat> 222B 222B 222B 222B;;;;Y;;;;; 2A0D;FINITE PART INTEGRAL;Sm;0;ON;;;;;Y;;;;; 2A0E;INTEGRAL WITH DOUBLE STROKE;Sm;0;ON;;;;;Y;;;;; 2A0F;INTEGRAL AVERAGE WITH SLASH;Sm;0;ON;;;;;Y;;;;; 2A10;CIRCULATION FUNCTION;Sm;0;ON;;;;;Y;;;;; 2A11;ANTICLOCKWISE INTEGRATION;Sm;0;ON;;;;;Y;;;;; 2A12;LINE INTEGRATION WITH RECTANGULAR PATH AROUND POLE;Sm;0;ON;;;;;Y;;;;; 2A13;LINE INTEGRATION WITH SEMICIRCULAR PATH AROUND POLE;Sm;0;ON;;;;;Y;;;;; 2A14;LINE INTEGRATION NOT INCLUDING THE POLE;Sm;0;ON;;;;;Y;;;;; 2A15;INTEGRAL AROUND A POINT OPERATOR;Sm;0;ON;;;;;Y;;;;; 2A16;QUATERNION INTEGRAL OPERATOR;Sm;0;ON;;;;;Y;;;;; 2A17;INTEGRAL WITH LEFTWARDS ARROW WITH HOOK;Sm;0;ON;;;;;Y;;;;; 2A18;INTEGRAL WITH TIMES SIGN;Sm;0;ON;;;;;Y;;;;; 2A19;INTEGRAL WITH INTERSECTION;Sm;0;ON;;;;;Y;;;;; 2A1A;INTEGRAL WITH UNION;Sm;0;ON;;;;;Y;;;;; 2A1B;INTEGRAL WITH OVERBAR;Sm;0;ON;;;;;Y;;;;; 2A1C;INTEGRAL WITH UNDERBAR;Sm;0;ON;;;;;Y;;;;; 2A1D;JOIN;Sm;0;ON;;;;;N;;;;; 2A1E;LARGE LEFT TRIANGLE OPERATOR;Sm;0;ON;;;;;Y;;;;; 2A1F;Z NOTATION SCHEMA COMPOSITION;Sm;0;ON;;;;;Y;;;;; 2A20;Z NOTATION SCHEMA PIPING;Sm;0;ON;;;;;Y;;;;; 2A21;Z NOTATION SCHEMA PROJECTION;Sm;0;ON;;;;;Y;;;;; 2A22;PLUS SIGN WITH SMALL CIRCLE ABOVE;Sm;0;ON;;;;;N;;;;; 2A23;PLUS SIGN WITH CIRCUMFLEX ACCENT ABOVE;Sm;0;ON;;;;;N;;;;; 2A24;PLUS SIGN WITH TILDE ABOVE;Sm;0;ON;;;;;Y;;;;; 2A25;PLUS SIGN WITH DOT BELOW;Sm;0;ON;;;;;N;;;;; 2A26;PLUS SIGN WITH TILDE BELOW;Sm;0;ON;;;;;Y;;;;; 2A27;PLUS SIGN WITH SUBSCRIPT TWO;Sm;0;ON;;;;;N;;;;; 2A28;PLUS SIGN WITH BLACK TRIANGLE;Sm;0;ON;;;;;N;;;;; 2A29;MINUS SIGN WITH COMMA ABOVE;Sm;0;ON;;;;;Y;;;;; 2A2A;MINUS SIGN WITH DOT BELOW;Sm;0;ON;;;;;N;;;;; 2A2B;MINUS SIGN WITH FALLING DOTS;Sm;0;ON;;;;;Y;;;;; 2A2C;MINUS SIGN WITH RISING DOTS;Sm;0;ON;;;;;Y;;;;; 2A2D;PLUS SIGN IN LEFT HALF CIRCLE;Sm;0;ON;;;;;Y;;;;; 2A2E;PLUS SIGN IN RIGHT HALF CIRCLE;Sm;0;ON;;;;;Y;;;;; 2A2F;VECTOR OR CROSS PRODUCT;Sm;0;ON;;;;;N;;;;; 2A30;MULTIPLICATION SIGN WITH DOT ABOVE;Sm;0;ON;;;;;N;;;;; 2A31;MULTIPLICATION SIGN WITH UNDERBAR;Sm;0;ON;;;;;N;;;;; 2A32;SEMIDIRECT PRODUCT WITH BOTTOM CLOSED;Sm;0;ON;;;;;N;;;;; 2A33;SMASH PRODUCT;Sm;0;ON;;;;;N;;;;; 2A34;MULTIPLICATION SIGN IN LEFT HALF CIRCLE;Sm;0;ON;;;;;Y;;;;; 2A35;MULTIPLICATION SIGN IN RIGHT HALF CIRCLE;Sm;0;ON;;;;;Y;;;;; 2A36;CIRCLED MULTIPLICATION SIGN WITH CIRCUMFLEX ACCENT;Sm;0;ON;;;;;N;;;;; 2A37;MULTIPLICATION SIGN IN DOUBLE CIRCLE;Sm;0;ON;;;;;N;;;;; 2A38;CIRCLED DIVISION SIGN;Sm;0;ON;;;;;N;;;;; 2A39;PLUS SIGN IN TRIANGLE;Sm;0;ON;;;;;N;;;;; 2A3A;MINUS SIGN IN TRIANGLE;Sm;0;ON;;;;;N;;;;; 2A3B;MULTIPLICATION SIGN IN TRIANGLE;Sm;0;ON;;;;;N;;;;; 2A3C;INTERIOR PRODUCT;Sm;0;ON;;;;;Y;;;;; 2A3D;RIGHTHAND INTERIOR PRODUCT;Sm;0;ON;;;;;Y;;;;; 2A3E;Z NOTATION RELATIONAL COMPOSITION;Sm;0;ON;;;;;Y;;;;; 2A3F;AMALGAMATION OR COPRODUCT;Sm;0;ON;;;;;N;;;;; 2A40;INTERSECTION WITH DOT;Sm;0;ON;;;;;N;;;;; 2A41;UNION WITH MINUS SIGN;Sm;0;ON;;;;;N;;;;; 2A42;UNION WITH OVERBAR;Sm;0;ON;;;;;N;;;;; 2A43;INTERSECTION WITH OVERBAR;Sm;0;ON;;;;;N;;;;; 2A44;INTERSECTION WITH LOGICAL AND;Sm;0;ON;;;;;N;;;;; 2A45;UNION WITH LOGICAL OR;Sm;0;ON;;;;;N;;;;; 2A46;UNION ABOVE INTERSECTION;Sm;0;ON;;;;;N;;;;; 2A47;INTERSECTION ABOVE UNION;Sm;0;ON;;;;;N;;;;; 2A48;UNION ABOVE BAR ABOVE INTERSECTION;Sm;0;ON;;;;;N;;;;; 2A49;INTERSECTION ABOVE BAR ABOVE UNION;Sm;0;ON;;;;;N;;;;; 2A4A;UNION BESIDE AND JOINED WITH UNION;Sm;0;ON;;;;;N;;;;; 2A4B;INTERSECTION BESIDE AND JOINED WITH INTERSECTION;Sm;0;ON;;;;;N;;;;; 2A4C;CLOSED UNION WITH SERIFS;Sm;0;ON;;;;;N;;;;; 2A4D;CLOSED INTERSECTION WITH SERIFS;Sm;0;ON;;;;;N;;;;; 2A4E;DOUBLE SQUARE INTERSECTION;Sm;0;ON;;;;;N;;;;; 2A4F;DOUBLE SQUARE UNION;Sm;0;ON;;;;;N;;;;; 2A50;CLOSED UNION WITH SERIFS AND SMASH PRODUCT;Sm;0;ON;;;;;N;;;;; 2A51;LOGICAL AND WITH DOT ABOVE;Sm;0;ON;;;;;N;;;;; 2A52;LOGICAL OR WITH DOT ABOVE;Sm;0;ON;;;;;N;;;;; 2A53;DOUBLE LOGICAL AND;Sm;0;ON;;;;;N;;;;; 2A54;DOUBLE LOGICAL OR;Sm;0;ON;;;;;N;;;;; 2A55;TWO INTERSECTING LOGICAL AND;Sm;0;ON;;;;;N;;;;; 2A56;TWO INTERSECTING LOGICAL OR;Sm;0;ON;;;;;N;;;;; 2A57;SLOPING LARGE OR;Sm;0;ON;;;;;Y;;;;; 2A58;SLOPING LARGE AND;Sm;0;ON;;;;;Y;;;;; 2A59;LOGICAL OR OVERLAPPING LOGICAL AND;Sm;0;ON;;;;;N;;;;; 2A5A;LOGICAL AND WITH MIDDLE STEM;Sm;0;ON;;;;;N;;;;; 2A5B;LOGICAL OR WITH MIDDLE STEM;Sm;0;ON;;;;;N;;;;; 2A5C;LOGICAL AND WITH HORIZONTAL DASH;Sm;0;ON;;;;;N;;;;; 2A5D;LOGICAL OR WITH HORIZONTAL DASH;Sm;0;ON;;;;;N;;;;; 2A5E;LOGICAL AND WITH DOUBLE OVERBAR;Sm;0;ON;;;;;N;;;;; 2A5F;LOGICAL AND WITH UNDERBAR;Sm;0;ON;;;;;N;;;;; 2A60;LOGICAL AND WITH DOUBLE UNDERBAR;Sm;0;ON;;;;;N;;;;; 2A61;SMALL VEE WITH UNDERBAR;Sm;0;ON;;;;;N;;;;; 2A62;LOGICAL OR WITH DOUBLE OVERBAR;Sm;0;ON;;;;;N;;;;; 2A63;LOGICAL OR WITH DOUBLE UNDERBAR;Sm;0;ON;;;;;N;;;;; 2A64;Z NOTATION DOMAIN ANTIRESTRICTION;Sm;0;ON;;;;;Y;;;;; 2A65;Z NOTATION RANGE ANTIRESTRICTION;Sm;0;ON;;;;;Y;;;;; 2A66;EQUALS SIGN WITH DOT BELOW;Sm;0;ON;;;;;N;;;;; 2A67;IDENTICAL WITH DOT ABOVE;Sm;0;ON;;;;;N;;;;; 2A68;TRIPLE HORIZONTAL BAR WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2A69;TRIPLE HORIZONTAL BAR WITH TRIPLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2A6A;TILDE OPERATOR WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;; 2A6B;TILDE OPERATOR WITH RISING DOTS;Sm;0;ON;;;;;Y;;;;; 2A6C;SIMILAR MINUS SIMILAR;Sm;0;ON;;;;;Y;;;;; 2A6D;CONGRUENT WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;; 2A6E;EQUALS WITH ASTERISK;Sm;0;ON;;;;;N;;;;; 2A6F;ALMOST EQUAL TO WITH CIRCUMFLEX ACCENT;Sm;0;ON;;;;;Y;;;;; 2A70;APPROXIMATELY EQUAL OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2A71;EQUALS SIGN ABOVE PLUS SIGN;Sm;0;ON;;;;;N;;;;; 2A72;PLUS SIGN ABOVE EQUALS SIGN;Sm;0;ON;;;;;N;;;;; 2A73;EQUALS SIGN ABOVE TILDE OPERATOR;Sm;0;ON;;;;;Y;;;;; 2A74;DOUBLE COLON EQUAL;Sm;0;ON;<compat> 003A 003A 003D;;;;Y;;;;; 2A75;TWO CONSECUTIVE EQUALS SIGNS;Sm;0;ON;<compat> 003D 003D;;;;N;;;;; 2A76;THREE CONSECUTIVE EQUALS SIGNS;Sm;0;ON;<compat> 003D 003D 003D;;;;N;;;;; 2A77;EQUALS SIGN WITH TWO DOTS ABOVE AND TWO DOTS BELOW;Sm;0;ON;;;;;N;;;;; 2A78;EQUIVALENT WITH FOUR DOTS ABOVE;Sm;0;ON;;;;;N;;;;; 2A79;LESS-THAN WITH CIRCLE INSIDE;Sm;0;ON;;;;;Y;;;;; 2A7A;GREATER-THAN WITH CIRCLE INSIDE;Sm;0;ON;;;;;Y;;;;; 2A7B;LESS-THAN WITH QUESTION MARK ABOVE;Sm;0;ON;;;;;Y;;;;; 2A7C;GREATER-THAN WITH QUESTION MARK ABOVE;Sm;0;ON;;;;;Y;;;;; 2A7D;LESS-THAN OR SLANTED EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2A7E;GREATER-THAN OR SLANTED EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2A7F;LESS-THAN OR SLANTED EQUAL TO WITH DOT INSIDE;Sm;0;ON;;;;;Y;;;;; 2A80;GREATER-THAN OR SLANTED EQUAL TO WITH DOT INSIDE;Sm;0;ON;;;;;Y;;;;; 2A81;LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;; 2A82;GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;; 2A83;LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE RIGHT;Sm;0;ON;;;;;Y;;;;; 2A84;GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE LEFT;Sm;0;ON;;;;;Y;;;;; 2A85;LESS-THAN OR APPROXIMATE;Sm;0;ON;;;;;Y;;;;; 2A86;GREATER-THAN OR APPROXIMATE;Sm;0;ON;;;;;Y;;;;; 2A87;LESS-THAN AND SINGLE-LINE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2A88;GREATER-THAN AND SINGLE-LINE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2A89;LESS-THAN AND NOT APPROXIMATE;Sm;0;ON;;;;;Y;;;;; 2A8A;GREATER-THAN AND NOT APPROXIMATE;Sm;0;ON;;;;;Y;;;;; 2A8B;LESS-THAN ABOVE DOUBLE-LINE EQUAL ABOVE GREATER-THAN;Sm;0;ON;;;;;Y;;;;; 2A8C;GREATER-THAN ABOVE DOUBLE-LINE EQUAL ABOVE LESS-THAN;Sm;0;ON;;;;;Y;;;;; 2A8D;LESS-THAN ABOVE SIMILAR OR EQUAL;Sm;0;ON;;;;;Y;;;;; 2A8E;GREATER-THAN ABOVE SIMILAR OR EQUAL;Sm;0;ON;;;;;Y;;;;; 2A8F;LESS-THAN ABOVE SIMILAR ABOVE GREATER-THAN;Sm;0;ON;;;;;Y;;;;; 2A90;GREATER-THAN ABOVE SIMILAR ABOVE LESS-THAN;Sm;0;ON;;;;;Y;;;;; 2A91;LESS-THAN ABOVE GREATER-THAN ABOVE DOUBLE-LINE EQUAL;Sm;0;ON;;;;;Y;;;;; 2A92;GREATER-THAN ABOVE LESS-THAN ABOVE DOUBLE-LINE EQUAL;Sm;0;ON;;;;;Y;;;;; 2A93;LESS-THAN ABOVE SLANTED EQUAL ABOVE GREATER-THAN ABOVE SLANTED EQUAL;Sm;0;ON;;;;;Y;;;;; 2A94;GREATER-THAN ABOVE SLANTED EQUAL ABOVE LESS-THAN ABOVE SLANTED EQUAL;Sm;0;ON;;;;;Y;;;;; 2A95;SLANTED EQUAL TO OR LESS-THAN;Sm;0;ON;;;;;Y;;;;; 2A96;SLANTED EQUAL TO OR GREATER-THAN;Sm;0;ON;;;;;Y;;;;; 2A97;SLANTED EQUAL TO OR LESS-THAN WITH DOT INSIDE;Sm;0;ON;;;;;Y;;;;; 2A98;SLANTED EQUAL TO OR GREATER-THAN WITH DOT INSIDE;Sm;0;ON;;;;;Y;;;;; 2A99;DOUBLE-LINE EQUAL TO OR LESS-THAN;Sm;0;ON;;;;;Y;;;;; 2A9A;DOUBLE-LINE EQUAL TO OR GREATER-THAN;Sm;0;ON;;;;;Y;;;;; 2A9B;DOUBLE-LINE SLANTED EQUAL TO OR LESS-THAN;Sm;0;ON;;;;;Y;;;;; 2A9C;DOUBLE-LINE SLANTED EQUAL TO OR GREATER-THAN;Sm;0;ON;;;;;Y;;;;; 2A9D;SIMILAR OR LESS-THAN;Sm;0;ON;;;;;Y;;;;; 2A9E;SIMILAR OR GREATER-THAN;Sm;0;ON;;;;;Y;;;;; 2A9F;SIMILAR ABOVE LESS-THAN ABOVE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;; 2AA0;SIMILAR ABOVE GREATER-THAN ABOVE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;; 2AA1;DOUBLE NESTED LESS-THAN;Sm;0;ON;;;;;Y;;;;; 2AA2;DOUBLE NESTED GREATER-THAN;Sm;0;ON;;;;;Y;;;;; 2AA3;DOUBLE NESTED LESS-THAN WITH UNDERBAR;Sm;0;ON;;;;;Y;;;;; 2AA4;GREATER-THAN OVERLAPPING LESS-THAN;Sm;0;ON;;;;;N;;;;; 2AA5;GREATER-THAN BESIDE LESS-THAN;Sm;0;ON;;;;;N;;;;; 2AA6;LESS-THAN CLOSED BY CURVE;Sm;0;ON;;;;;Y;;;;; 2AA7;GREATER-THAN CLOSED BY CURVE;Sm;0;ON;;;;;Y;;;;; 2AA8;LESS-THAN CLOSED BY CURVE ABOVE SLANTED EQUAL;Sm;0;ON;;;;;Y;;;;; 2AA9;GREATER-THAN CLOSED BY CURVE ABOVE SLANTED EQUAL;Sm;0;ON;;;;;Y;;;;; 2AAA;SMALLER THAN;Sm;0;ON;;;;;Y;;;;; 2AAB;LARGER THAN;Sm;0;ON;;;;;Y;;;;; 2AAC;SMALLER THAN OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2AAD;LARGER THAN OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2AAE;EQUALS SIGN WITH BUMPY ABOVE;Sm;0;ON;;;;;N;;;;; 2AAF;PRECEDES ABOVE SINGLE-LINE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;; 2AB0;SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;; 2AB1;PRECEDES ABOVE SINGLE-LINE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2AB2;SUCCEEDS ABOVE SINGLE-LINE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2AB3;PRECEDES ABOVE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;; 2AB4;SUCCEEDS ABOVE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;; 2AB5;PRECEDES ABOVE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2AB6;SUCCEEDS ABOVE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2AB7;PRECEDES ABOVE ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2AB8;SUCCEEDS ABOVE ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2AB9;PRECEDES ABOVE NOT ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2ABA;SUCCEEDS ABOVE NOT ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2ABB;DOUBLE PRECEDES;Sm;0;ON;;;;;Y;;;;; 2ABC;DOUBLE SUCCEEDS;Sm;0;ON;;;;;Y;;;;; 2ABD;SUBSET WITH DOT;Sm;0;ON;;;;;Y;;;;; 2ABE;SUPERSET WITH DOT;Sm;0;ON;;;;;Y;;;;; 2ABF;SUBSET WITH PLUS SIGN BELOW;Sm;0;ON;;;;;Y;;;;; 2AC0;SUPERSET WITH PLUS SIGN BELOW;Sm;0;ON;;;;;Y;;;;; 2AC1;SUBSET WITH MULTIPLICATION SIGN BELOW;Sm;0;ON;;;;;Y;;;;; 2AC2;SUPERSET WITH MULTIPLICATION SIGN BELOW;Sm;0;ON;;;;;Y;;;;; 2AC3;SUBSET OF OR EQUAL TO WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;; 2AC4;SUPERSET OF OR EQUAL TO WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;; 2AC5;SUBSET OF ABOVE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;; 2AC6;SUPERSET OF ABOVE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;; 2AC7;SUBSET OF ABOVE TILDE OPERATOR;Sm;0;ON;;;;;Y;;;;; 2AC8;SUPERSET OF ABOVE TILDE OPERATOR;Sm;0;ON;;;;;Y;;;;; 2AC9;SUBSET OF ABOVE ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2ACA;SUPERSET OF ABOVE ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2ACB;SUBSET OF ABOVE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2ACC;SUPERSET OF ABOVE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2ACD;SQUARE LEFT OPEN BOX OPERATOR;Sm;0;ON;;;;;Y;;;;; 2ACE;SQUARE RIGHT OPEN BOX OPERATOR;Sm;0;ON;;;;;Y;;;;; 2ACF;CLOSED SUBSET;Sm;0;ON;;;;;Y;;;;; 2AD0;CLOSED SUPERSET;Sm;0;ON;;;;;Y;;;;; 2AD1;CLOSED SUBSET OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2AD2;CLOSED SUPERSET OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2AD3;SUBSET ABOVE SUPERSET;Sm;0;ON;;;;;Y;;;;; 2AD4;SUPERSET ABOVE SUBSET;Sm;0;ON;;;;;Y;;;;; 2AD5;SUBSET ABOVE SUBSET;Sm;0;ON;;;;;Y;;;;; 2AD6;SUPERSET ABOVE SUPERSET;Sm;0;ON;;;;;Y;;;;; 2AD7;SUPERSET BESIDE SUBSET;Sm;0;ON;;;;;N;;;;; 2AD8;SUPERSET BESIDE AND JOINED BY DASH WITH SUBSET;Sm;0;ON;;;;;N;;;;; 2AD9;ELEMENT OF OPENING DOWNWARDS;Sm;0;ON;;;;;N;;;;; 2ADA;PITCHFORK WITH TEE TOP;Sm;0;ON;;;;;N;;;;; 2ADB;TRANSVERSAL INTERSECTION;Sm;0;ON;;;;;N;;;;; 2ADC;FORKING;Sm;0;ON;2ADD 0338;;;;Y;;;;; 2ADD;NONFORKING;Sm;0;ON;;;;;N;;;;; 2ADE;SHORT LEFT TACK;Sm;0;ON;;;;;Y;;;;; 2ADF;SHORT DOWN TACK;Sm;0;ON;;;;;N;;;;; 2AE0;SHORT UP TACK;Sm;0;ON;;;;;N;;;;; 2AE1;PERPENDICULAR WITH S;Sm;0;ON;;;;;N;;;;; 2AE2;VERTICAL BAR TRIPLE RIGHT TURNSTILE;Sm;0;ON;;;;;Y;;;;; 2AE3;DOUBLE VERTICAL BAR LEFT TURNSTILE;Sm;0;ON;;;;;Y;;;;; 2AE4;VERTICAL BAR DOUBLE LEFT TURNSTILE;Sm;0;ON;;;;;Y;;;;; 2AE5;DOUBLE VERTICAL BAR DOUBLE LEFT TURNSTILE;Sm;0;ON;;;;;Y;;;;; 2AE6;LONG DASH FROM LEFT MEMBER OF DOUBLE VERTICAL;Sm;0;ON;;;;;Y;;;;; 2AE7;SHORT DOWN TACK WITH OVERBAR;Sm;0;ON;;;;;N;;;;; 2AE8;SHORT UP TACK WITH UNDERBAR;Sm;0;ON;;;;;N;;;;; 2AE9;SHORT UP TACK ABOVE SHORT DOWN TACK;Sm;0;ON;;;;;N;;;;; 2AEA;DOUBLE DOWN TACK;Sm;0;ON;;;;;N;;;;; 2AEB;DOUBLE UP TACK;Sm;0;ON;;;;;N;;;;; 2AEC;DOUBLE STROKE NOT SIGN;Sm;0;ON;;;;;Y;;;;; 2AED;REVERSED DOUBLE STROKE NOT SIGN;Sm;0;ON;;;;;Y;;;;; 2AEE;DOES NOT DIVIDE WITH REVERSED NEGATION SLASH;Sm;0;ON;;;;;Y;;;;; 2AEF;VERTICAL LINE WITH CIRCLE ABOVE;Sm;0;ON;;;;;N;;;;; 2AF0;VERTICAL LINE WITH CIRCLE BELOW;Sm;0;ON;;;;;N;;;;; 2AF1;DOWN TACK WITH CIRCLE BELOW;Sm;0;ON;;;;;N;;;;; 2AF2;PARALLEL WITH HORIZONTAL STROKE;Sm;0;ON;;;;;N;;;;; 2AF3;PARALLEL WITH TILDE OPERATOR;Sm;0;ON;;;;;Y;;;;; 2AF4;TRIPLE VERTICAL BAR BINARY RELATION;Sm;0;ON;;;;;N;;;;; 2AF5;TRIPLE VERTICAL BAR WITH HORIZONTAL STROKE;Sm;0;ON;;;;;N;;;;; 2AF6;TRIPLE COLON OPERATOR;Sm;0;ON;;;;;N;;;;; 2AF7;TRIPLE NESTED LESS-THAN;Sm;0;ON;;;;;Y;;;;; 2AF8;TRIPLE NESTED GREATER-THAN;Sm;0;ON;;;;;Y;;;;; 2AF9;DOUBLE-LINE SLANTED LESS-THAN OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2AFA;DOUBLE-LINE SLANTED GREATER-THAN OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; 2AFB;TRIPLE SOLIDUS BINARY RELATION;Sm;0;ON;;;;;Y;;;;; 2AFC;LARGE TRIPLE VERTICAL BAR OPERATOR;Sm;0;ON;;;;;N;;;;; 2AFD;DOUBLE SOLIDUS OPERATOR;Sm;0;ON;;;;;Y;;;;; 2AFE;WHITE VERTICAL BAR;Sm;0;ON;;;;;N;;;;; 2AFF;N-ARY WHITE VERTICAL BAR;Sm;0;ON;;;;;N;;;;; 2B00;NORTH EAST WHITE ARROW;So;0;ON;;;;;N;;;;; 2B01;NORTH WEST WHITE ARROW;So;0;ON;;;;;N;;;;; 2B02;SOUTH EAST WHITE ARROW;So;0;ON;;;;;N;;;;; 2B03;SOUTH WEST WHITE ARROW;So;0;ON;;;;;N;;;;; 2B04;LEFT RIGHT WHITE ARROW;So;0;ON;;;;;N;;;;; 2B05;LEFTWARDS BLACK ARROW;So;0;ON;;;;;N;;;;; 2B06;UPWARDS BLACK ARROW;So;0;ON;;;;;N;;;;; 2B07;DOWNWARDS BLACK ARROW;So;0;ON;;;;;N;;;;; 2B08;NORTH EAST BLACK ARROW;So;0;ON;;;;;N;;;;; 2B09;NORTH WEST BLACK ARROW;So;0;ON;;;;;N;;;;; 2B0A;SOUTH EAST BLACK ARROW;So;0;ON;;;;;N;;;;; 2B0B;SOUTH WEST BLACK ARROW;So;0;ON;;;;;N;;;;; 2B0C;LEFT RIGHT BLACK ARROW;So;0;ON;;;;;N;;;;; 2B0D;UP DOWN BLACK ARROW;So;0;ON;;;;;N;;;;; 2B0E;RIGHTWARDS ARROW WITH TIP DOWNWARDS;So;0;ON;;;;;N;;;;; 2B0F;RIGHTWARDS ARROW WITH TIP UPWARDS;So;0;ON;;;;;N;;;;; 2B10;LEFTWARDS ARROW WITH TIP DOWNWARDS;So;0;ON;;;;;N;;;;; 2B11;LEFTWARDS ARROW WITH TIP UPWARDS;So;0;ON;;;;;N;;;;; 2B12;SQUARE WITH TOP HALF BLACK;So;0;ON;;;;;N;;;;; 2B13;SQUARE WITH BOTTOM HALF BLACK;So;0;ON;;;;;N;;;;; 2B14;SQUARE WITH UPPER RIGHT DIAGONAL HALF BLACK;So;0;ON;;;;;N;;;;; 2B15;SQUARE WITH LOWER LEFT DIAGONAL HALF BLACK;So;0;ON;;;;;N;;;;; 2B16;DIAMOND WITH LEFT HALF BLACK;So;0;ON;;;;;N;;;;; 2B17;DIAMOND WITH RIGHT HALF BLACK;So;0;ON;;;;;N;;;;; 2B18;DIAMOND WITH TOP HALF BLACK;So;0;ON;;;;;N;;;;; 2B19;DIAMOND WITH BOTTOM HALF BLACK;So;0;ON;;;;;N;;;;; 2B1A;DOTTED SQUARE;So;0;ON;;;;;N;;;;; 2B1B;BLACK LARGE SQUARE;So;0;ON;;;;;N;;;;; 2B1C;WHITE LARGE SQUARE;So;0;ON;;;;;N;;;;; 2B1D;BLACK VERY SMALL SQUARE;So;0;ON;;;;;N;;;;; 2B1E;WHITE VERY SMALL SQUARE;So;0;ON;;;;;N;;;;; 2B1F;BLACK PENTAGON;So;0;ON;;;;;N;;;;; 2B20;WHITE PENTAGON;So;0;ON;;;;;N;;;;; 2B21;WHITE HEXAGON;So;0;ON;;;;;N;;;;; 2B22;BLACK HEXAGON;So;0;ON;;;;;N;;;;; 2B23;HORIZONTAL BLACK HEXAGON;So;0;ON;;;;;N;;;;; 2B24;BLACK LARGE CIRCLE;So;0;ON;;;;;N;;;;; 2B25;BLACK MEDIUM DIAMOND;So;0;ON;;;;;N;;;;; 2B26;WHITE MEDIUM DIAMOND;So;0;ON;;;;;N;;;;; 2B27;BLACK MEDIUM LOZENGE;So;0;ON;;;;;N;;;;; 2B28;WHITE MEDIUM LOZENGE;So;0;ON;;;;;N;;;;; 2B29;BLACK SMALL DIAMOND;So;0;ON;;;;;N;;;;; 2B2A;BLACK SMALL LOZENGE;So;0;ON;;;;;N;;;;; 2B2B;WHITE SMALL LOZENGE;So;0;ON;;;;;N;;;;; 2B2C;BLACK HORIZONTAL ELLIPSE;So;0;ON;;;;;N;;;;; 2B2D;WHITE HORIZONTAL ELLIPSE;So;0;ON;;;;;N;;;;; 2B2E;BLACK VERTICAL ELLIPSE;So;0;ON;;;;;N;;;;; 2B2F;WHITE VERTICAL ELLIPSE;So;0;ON;;;;;N;;;;; 2B30;LEFT ARROW WITH SMALL CIRCLE;Sm;0;ON;;;;;N;;;;; 2B31;THREE LEFTWARDS ARROWS;Sm;0;ON;;;;;N;;;;; 2B32;LEFT ARROW WITH CIRCLED PLUS;Sm;0;ON;;;;;N;;;;; 2B33;LONG LEFTWARDS SQUIGGLE ARROW;Sm;0;ON;;;;;N;;;;; 2B34;LEFTWARDS TWO-HEADED ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2B35;LEFTWARDS TWO-HEADED ARROW WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2B36;LEFTWARDS TWO-HEADED ARROW FROM BAR;Sm;0;ON;;;;;N;;;;; 2B37;LEFTWARDS TWO-HEADED TRIPLE DASH ARROW;Sm;0;ON;;;;;N;;;;; 2B38;LEFTWARDS ARROW WITH DOTTED STEM;Sm;0;ON;;;;;N;;;;; 2B39;LEFTWARDS ARROW WITH TAIL WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2B3A;LEFTWARDS ARROW WITH TAIL WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2B3B;LEFTWARDS TWO-HEADED ARROW WITH TAIL;Sm;0;ON;;;;;N;;;;; 2B3C;LEFTWARDS TWO-HEADED ARROW WITH TAIL WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2B3D;LEFTWARDS TWO-HEADED ARROW WITH TAIL WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; 2B3E;LEFTWARDS ARROW THROUGH X;Sm;0;ON;;;;;N;;;;; 2B3F;WAVE ARROW POINTING DIRECTLY LEFT;Sm;0;ON;;;;;N;;;;; 2B40;EQUALS SIGN ABOVE LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 2B41;REVERSE TILDE OPERATOR ABOVE LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 2B42;LEFTWARDS ARROW ABOVE REVERSE ALMOST EQUAL TO;Sm;0;ON;;;;;N;;;;; 2B43;RIGHTWARDS ARROW THROUGH GREATER-THAN;Sm;0;ON;;;;;N;;;;; 2B44;RIGHTWARDS ARROW THROUGH SUPERSET;Sm;0;ON;;;;;N;;;;; 2B45;LEFTWARDS QUADRUPLE ARROW;So;0;ON;;;;;N;;;;; 2B46;RIGHTWARDS QUADRUPLE ARROW;So;0;ON;;;;;N;;;;; 2B47;REVERSE TILDE OPERATOR ABOVE RIGHTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 2B48;RIGHTWARDS ARROW ABOVE REVERSE ALMOST EQUAL TO;Sm;0;ON;;;;;N;;;;; 2B49;TILDE OPERATOR ABOVE LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;; 2B4A;LEFTWARDS ARROW ABOVE ALMOST EQUAL TO;Sm;0;ON;;;;;N;;;;; 2B4B;LEFTWARDS ARROW ABOVE REVERSE TILDE OPERATOR;Sm;0;ON;;;;;N;;;;; 2B4C;RIGHTWARDS ARROW ABOVE REVERSE TILDE OPERATOR;Sm;0;ON;;;;;N;;;;; 2B4D;DOWNWARDS TRIANGLE-HEADED ZIGZAG ARROW;So;0;ON;;;;;N;;;;; 2B4E;SHORT SLANTED NORTH ARROW;So;0;ON;;;;;N;;;;; 2B4F;SHORT BACKSLANTED SOUTH ARROW;So;0;ON;;;;;N;;;;; 2B50;WHITE MEDIUM STAR;So;0;ON;;;;;N;;;;; 2B51;BLACK SMALL STAR;So;0;ON;;;;;N;;;;; 2B52;WHITE SMALL STAR;So;0;ON;;;;;N;;;;; 2B53;BLACK RIGHT-POINTING PENTAGON;So;0;ON;;;;;N;;;;; 2B54;WHITE RIGHT-POINTING PENTAGON;So;0;ON;;;;;N;;;;; 2B55;HEAVY LARGE CIRCLE;So;0;ON;;;;;N;;;;; 2B56;HEAVY OVAL WITH OVAL INSIDE;So;0;ON;;;;;N;;;;; 2B57;HEAVY CIRCLE WITH CIRCLE INSIDE;So;0;ON;;;;;N;;;;; 2B58;HEAVY CIRCLE;So;0;ON;;;;;N;;;;; 2B59;HEAVY CIRCLED SALTIRE;So;0;ON;;;;;N;;;;; 2B5A;SLANTED NORTH ARROW WITH HOOKED HEAD;So;0;ON;;;;;N;;;;; 2B5B;BACKSLANTED SOUTH ARROW WITH HOOKED TAIL;So;0;ON;;;;;N;;;;; 2B5C;SLANTED NORTH ARROW WITH HORIZONTAL TAIL;So;0;ON;;;;;N;;;;; 2B5D;BACKSLANTED SOUTH ARROW WITH HORIZONTAL TAIL;So;0;ON;;;;;N;;;;; 2B5E;BENT ARROW POINTING DOWNWARDS THEN NORTH EAST;So;0;ON;;;;;N;;;;; 2B5F;SHORT BENT ARROW POINTING DOWNWARDS THEN NORTH EAST;So;0;ON;;;;;N;;;;; 2B60;LEFTWARDS TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; 2B61;UPWARDS TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; 2B62;RIGHTWARDS TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; 2B63;DOWNWARDS TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; 2B64;LEFT RIGHT TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; 2B65;UP DOWN TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; 2B66;NORTH WEST TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; 2B67;NORTH EAST TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; 2B68;SOUTH EAST TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; 2B69;SOUTH WEST TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; 2B6A;LEFTWARDS TRIANGLE-HEADED DASHED ARROW;So;0;ON;;;;;N;;;;; 2B6B;UPWARDS TRIANGLE-HEADED DASHED ARROW;So;0;ON;;;;;N;;;;; 2B6C;RIGHTWARDS TRIANGLE-HEADED DASHED ARROW;So;0;ON;;;;;N;;;;; 2B6D;DOWNWARDS TRIANGLE-HEADED DASHED ARROW;So;0;ON;;;;;N;;;;; 2B6E;CLOCKWISE TRIANGLE-HEADED OPEN CIRCLE ARROW;So;0;ON;;;;;N;;;;; 2B6F;ANTICLOCKWISE TRIANGLE-HEADED OPEN CIRCLE ARROW;So;0;ON;;;;;N;;;;; 2B70;LEFTWARDS TRIANGLE-HEADED ARROW TO BAR;So;0;ON;;;;;N;;;;; 2B71;UPWARDS TRIANGLE-HEADED ARROW TO BAR;So;0;ON;;;;;N;;;;; 2B72;RIGHTWARDS TRIANGLE-HEADED ARROW TO BAR;So;0;ON;;;;;N;;;;; 2B73;DOWNWARDS TRIANGLE-HEADED ARROW TO BAR;So;0;ON;;;;;N;;;;; 2B76;NORTH WEST TRIANGLE-HEADED ARROW TO BAR;So;0;ON;;;;;N;;;;; 2B77;NORTH EAST TRIANGLE-HEADED ARROW TO BAR;So;0;ON;;;;;N;;;;; 2B78;SOUTH EAST TRIANGLE-HEADED ARROW TO BAR;So;0;ON;;;;;N;;;;; 2B79;SOUTH WEST TRIANGLE-HEADED ARROW TO BAR;So;0;ON;;;;;N;;;;; 2B7A;LEFTWARDS TRIANGLE-HEADED ARROW WITH DOUBLE HORIZONTAL STROKE;So;0;ON;;;;;N;;;;; 2B7B;UPWARDS TRIANGLE-HEADED ARROW WITH DOUBLE HORIZONTAL STROKE;So;0;ON;;;;;N;;;;; 2B7C;RIGHTWARDS TRIANGLE-HEADED ARROW WITH DOUBLE HORIZONTAL STROKE;So;0;ON;;;;;N;;;;; 2B7D;DOWNWARDS TRIANGLE-HEADED ARROW WITH DOUBLE HORIZONTAL STROKE;So;0;ON;;;;;N;;;;; 2B7E;HORIZONTAL TAB KEY;So;0;ON;;;;;N;;;;; 2B7F;VERTICAL TAB KEY;So;0;ON;;;;;N;;;;; 2B80;LEFTWARDS TRIANGLE-HEADED ARROW OVER RIGHTWARDS TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; 2B81;UPWARDS TRIANGLE-HEADED ARROW LEFTWARDS OF DOWNWARDS TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; 2B82;RIGHTWARDS TRIANGLE-HEADED ARROW OVER LEFTWARDS TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; 2B83;DOWNWARDS TRIANGLE-HEADED ARROW LEFTWARDS OF UPWARDS TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; 2B84;LEFTWARDS TRIANGLE-HEADED PAIRED ARROWS;So;0;ON;;;;;N;;;;; 2B85;UPWARDS TRIANGLE-HEADED PAIRED ARROWS;So;0;ON;;;;;N;;;;; 2B86;RIGHTWARDS TRIANGLE-HEADED PAIRED ARROWS;So;0;ON;;;;;N;;;;; 2B87;DOWNWARDS TRIANGLE-HEADED PAIRED ARROWS;So;0;ON;;;;;N;;;;; 2B88;LEFTWARDS BLACK CIRCLED WHITE ARROW;So;0;ON;;;;;N;;;;; 2B89;UPWARDS BLACK CIRCLED WHITE ARROW;So;0;ON;;;;;N;;;;; 2B8A;RIGHTWARDS BLACK CIRCLED WHITE ARROW;So;0;ON;;;;;N;;;;; 2B8B;DOWNWARDS BLACK CIRCLED WHITE ARROW;So;0;ON;;;;;N;;;;; 2B8C;ANTICLOCKWISE TRIANGLE-HEADED RIGHT U-SHAPED ARROW;So;0;ON;;;;;N;;;;; 2B8D;ANTICLOCKWISE TRIANGLE-HEADED BOTTOM U-SHAPED ARROW;So;0;ON;;;;;N;;;;; 2B8E;ANTICLOCKWISE TRIANGLE-HEADED LEFT U-SHAPED ARROW;So;0;ON;;;;;N;;;;; 2B8F;ANTICLOCKWISE TRIANGLE-HEADED TOP U-SHAPED ARROW;So;0;ON;;;;;N;;;;; 2B90;RETURN LEFT;So;0;ON;;;;;N;;;;; 2B91;RETURN RIGHT;So;0;ON;;;;;N;;;;; 2B92;NEWLINE LEFT;So;0;ON;;;;;N;;;;; 2B93;NEWLINE RIGHT;So;0;ON;;;;;N;;;;; 2B94;FOUR CORNER ARROWS CIRCLING ANTICLOCKWISE;So;0;ON;;;;;N;;;;; 2B95;RIGHTWARDS BLACK ARROW;So;0;ON;;;;;N;;;;; 2B98;THREE-D TOP-LIGHTED LEFTWARDS EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; 2B99;THREE-D RIGHT-LIGHTED UPWARDS EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; 2B9A;THREE-D TOP-LIGHTED RIGHTWARDS EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; 2B9B;THREE-D LEFT-LIGHTED DOWNWARDS EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; 2B9C;BLACK LEFTWARDS EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; 2B9D;BLACK UPWARDS EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; 2B9E;BLACK RIGHTWARDS EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; 2B9F;BLACK DOWNWARDS EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; 2BA0;DOWNWARDS TRIANGLE-HEADED ARROW WITH LONG TIP LEFTWARDS;So;0;ON;;;;;N;;;;; 2BA1;DOWNWARDS TRIANGLE-HEADED ARROW WITH LONG TIP RIGHTWARDS;So;0;ON;;;;;N;;;;; 2BA2;UPWARDS TRIANGLE-HEADED ARROW WITH LONG TIP LEFTWARDS;So;0;ON;;;;;N;;;;; 2BA3;UPWARDS TRIANGLE-HEADED ARROW WITH LONG TIP RIGHTWARDS;So;0;ON;;;;;N;;;;; 2BA4;LEFTWARDS TRIANGLE-HEADED ARROW WITH LONG TIP UPWARDS;So;0;ON;;;;;N;;;;; 2BA5;RIGHTWARDS TRIANGLE-HEADED ARROW WITH LONG TIP UPWARDS;So;0;ON;;;;;N;;;;; 2BA6;LEFTWARDS TRIANGLE-HEADED ARROW WITH LONG TIP DOWNWARDS;So;0;ON;;;;;N;;;;; 2BA7;RIGHTWARDS TRIANGLE-HEADED ARROW WITH LONG TIP DOWNWARDS;So;0;ON;;;;;N;;;;; 2BA8;BLACK CURVED DOWNWARDS AND LEFTWARDS ARROW;So;0;ON;;;;;N;;;;; 2BA9;BLACK CURVED DOWNWARDS AND RIGHTWARDS ARROW;So;0;ON;;;;;N;;;;; 2BAA;BLACK CURVED UPWARDS AND LEFTWARDS ARROW;So;0;ON;;;;;N;;;;; 2BAB;BLACK CURVED UPWARDS AND RIGHTWARDS ARROW;So;0;ON;;;;;N;;;;; 2BAC;BLACK CURVED LEFTWARDS AND UPWARDS ARROW;So;0;ON;;;;;N;;;;; 2BAD;BLACK CURVED RIGHTWARDS AND UPWARDS ARROW;So;0;ON;;;;;N;;;;; 2BAE;BLACK CURVED LEFTWARDS AND DOWNWARDS ARROW;So;0;ON;;;;;N;;;;; 2BAF;BLACK CURVED RIGHTWARDS AND DOWNWARDS ARROW;So;0;ON;;;;;N;;;;; 2BB0;RIBBON ARROW DOWN LEFT;So;0;ON;;;;;N;;;;; 2BB1;RIBBON ARROW DOWN RIGHT;So;0;ON;;;;;N;;;;; 2BB2;RIBBON ARROW UP LEFT;So;0;ON;;;;;N;;;;; 2BB3;RIBBON ARROW UP RIGHT;So;0;ON;;;;;N;;;;; 2BB4;RIBBON ARROW LEFT UP;So;0;ON;;;;;N;;;;; 2BB5;RIBBON ARROW RIGHT UP;So;0;ON;;;;;N;;;;; 2BB6;RIBBON ARROW LEFT DOWN;So;0;ON;;;;;N;;;;; 2BB7;RIBBON ARROW RIGHT DOWN;So;0;ON;;;;;N;;;;; 2BB8;UPWARDS WHITE ARROW FROM BAR WITH HORIZONTAL BAR;So;0;ON;;;;;N;;;;; 2BB9;UP ARROWHEAD IN A RECTANGLE BOX;So;0;ON;;;;;N;;;;; 2BBD;BALLOT BOX WITH LIGHT X;So;0;ON;;;;;N;;;;; 2BBE;CIRCLED X;So;0;ON;;;;;N;;;;; 2BBF;CIRCLED BOLD X;So;0;ON;;;;;N;;;;; 2BC0;BLACK SQUARE CENTRED;So;0;ON;;;;;N;;;;; 2BC1;BLACK DIAMOND CENTRED;So;0;ON;;;;;N;;;;; 2BC2;TURNED BLACK PENTAGON;So;0;ON;;;;;N;;;;; 2BC3;HORIZONTAL BLACK OCTAGON;So;0;ON;;;;;N;;;;; 2BC4;BLACK OCTAGON;So;0;ON;;;;;N;;;;; 2BC5;BLACK MEDIUM UP-POINTING TRIANGLE CENTRED;So;0;ON;;;;;N;;;;; 2BC6;BLACK MEDIUM DOWN-POINTING TRIANGLE CENTRED;So;0;ON;;;;;N;;;;; 2BC7;BLACK MEDIUM LEFT-POINTING TRIANGLE CENTRED;So;0;ON;;;;;N;;;;; 2BC8;BLACK MEDIUM RIGHT-POINTING TRIANGLE CENTRED;So;0;ON;;;;;N;;;;; 2BCA;TOP HALF BLACK CIRCLE;So;0;ON;;;;;N;;;;; 2BCB;BOTTOM HALF BLACK CIRCLE;So;0;ON;;;;;N;;;;; 2BCC;LIGHT FOUR POINTED BLACK CUSP;So;0;ON;;;;;N;;;;; 2BCD;ROTATED LIGHT FOUR POINTED BLACK CUSP;So;0;ON;;;;;N;;;;; 2BCE;WHITE FOUR POINTED CUSP;So;0;ON;;;;;N;;;;; 2BCF;ROTATED WHITE FOUR POINTED CUSP;So;0;ON;;;;;N;;;;; 2BD0;SQUARE POSITION INDICATOR;So;0;ON;;;;;N;;;;; 2BD1;UNCERTAINTY SIGN;So;0;ON;;;;;N;;;;; 2BEC;LEFTWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS;So;0;ON;;;;;N;;;;; 2BED;UPWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS;So;0;ON;;;;;N;;;;; 2BEE;RIGHTWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS;So;0;ON;;;;;N;;;;; 2BEF;DOWNWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS;So;0;ON;;;;;N;;;;; 2C00;GLAGOLITIC CAPITAL LETTER AZU;Lu;0;L;;;;;N;;;;2C30; 2C01;GLAGOLITIC CAPITAL LETTER BUKY;Lu;0;L;;;;;N;;;;2C31; 2C02;GLAGOLITIC CAPITAL LETTER VEDE;Lu;0;L;;;;;N;;;;2C32; 2C03;GLAGOLITIC CAPITAL LETTER GLAGOLI;Lu;0;L;;;;;N;;;;2C33; 2C04;GLAGOLITIC CAPITAL LETTER DOBRO;Lu;0;L;;;;;N;;;;2C34; 2C05;GLAGOLITIC CAPITAL LETTER YESTU;Lu;0;L;;;;;N;;;;2C35; 2C06;GLAGOLITIC CAPITAL LETTER ZHIVETE;Lu;0;L;;;;;N;;;;2C36; 2C07;GLAGOLITIC CAPITAL LETTER DZELO;Lu;0;L;;;;;N;;;;2C37; 2C08;GLAGOLITIC CAPITAL LETTER ZEMLJA;Lu;0;L;;;;;N;;;;2C38; 2C09;GLAGOLITIC CAPITAL LETTER IZHE;Lu;0;L;;;;;N;;;;2C39; 2C0A;GLAGOLITIC CAPITAL LETTER INITIAL IZHE;Lu;0;L;;;;;N;;;;2C3A; 2C0B;GLAGOLITIC CAPITAL LETTER I;Lu;0;L;;;;;N;;;;2C3B; 2C0C;GLAGOLITIC CAPITAL LETTER DJERVI;Lu;0;L;;;;;N;;;;2C3C; 2C0D;GLAGOLITIC CAPITAL LETTER KAKO;Lu;0;L;;;;;N;;;;2C3D; 2C0E;GLAGOLITIC CAPITAL LETTER LJUDIJE;Lu;0;L;;;;;N;;;;2C3E; 2C0F;GLAGOLITIC CAPITAL LETTER MYSLITE;Lu;0;L;;;;;N;;;;2C3F; 2C10;GLAGOLITIC CAPITAL LETTER NASHI;Lu;0;L;;;;;N;;;;2C40; 2C11;GLAGOLITIC CAPITAL LETTER ONU;Lu;0;L;;;;;N;;;;2C41; 2C12;GLAGOLITIC CAPITAL LETTER POKOJI;Lu;0;L;;;;;N;;;;2C42; 2C13;GLAGOLITIC CAPITAL LETTER RITSI;Lu;0;L;;;;;N;;;;2C43; 2C14;GLAGOLITIC CAPITAL LETTER SLOVO;Lu;0;L;;;;;N;;;;2C44; 2C15;GLAGOLITIC CAPITAL LETTER TVRIDO;Lu;0;L;;;;;N;;;;2C45; 2C16;GLAGOLITIC CAPITAL LETTER UKU;Lu;0;L;;;;;N;;;;2C46; 2C17;GLAGOLITIC CAPITAL LETTER FRITU;Lu;0;L;;;;;N;;;;2C47; 2C18;GLAGOLITIC CAPITAL LETTER HERU;Lu;0;L;;;;;N;;;;2C48; 2C19;GLAGOLITIC CAPITAL LETTER OTU;Lu;0;L;;;;;N;;;;2C49; 2C1A;GLAGOLITIC CAPITAL LETTER PE;Lu;0;L;;;;;N;;;;2C4A; 2C1B;GLAGOLITIC CAPITAL LETTER SHTA;Lu;0;L;;;;;N;;;;2C4B; 2C1C;GLAGOLITIC CAPITAL LETTER TSI;Lu;0;L;;;;;N;;;;2C4C; 2C1D;GLAGOLITIC CAPITAL LETTER CHRIVI;Lu;0;L;;;;;N;;;;2C4D; 2C1E;GLAGOLITIC CAPITAL LETTER SHA;Lu;0;L;;;;;N;;;;2C4E; 2C1F;GLAGOLITIC CAPITAL LETTER YERU;Lu;0;L;;;;;N;;;;2C4F; 2C20;GLAGOLITIC CAPITAL LETTER YERI;Lu;0;L;;;;;N;;;;2C50; 2C21;GLAGOLITIC CAPITAL LETTER YATI;Lu;0;L;;;;;N;;;;2C51; 2C22;GLAGOLITIC CAPITAL LETTER SPIDERY HA;Lu;0;L;;;;;N;;;;2C52; 2C23;GLAGOLITIC CAPITAL LETTER YU;Lu;0;L;;;;;N;;;;2C53; 2C24;GLAGOLITIC CAPITAL LETTER SMALL YUS;Lu;0;L;;;;;N;;;;2C54; 2C25;GLAGOLITIC CAPITAL LETTER SMALL YUS WITH TAIL;Lu;0;L;;;;;N;;;;2C55; 2C26;GLAGOLITIC CAPITAL LETTER YO;Lu;0;L;;;;;N;;;;2C56; 2C27;GLAGOLITIC CAPITAL LETTER IOTATED SMALL YUS;Lu;0;L;;;;;N;;;;2C57; 2C28;GLAGOLITIC CAPITAL LETTER BIG YUS;Lu;0;L;;;;;N;;;;2C58; 2C29;GLAGOLITIC CAPITAL LETTER IOTATED BIG YUS;Lu;0;L;;;;;N;;;;2C59; 2C2A;GLAGOLITIC CAPITAL LETTER FITA;Lu;0;L;;;;;N;;;;2C5A; 2C2B;GLAGOLITIC CAPITAL LETTER IZHITSA;Lu;0;L;;;;;N;;;;2C5B; 2C2C;GLAGOLITIC CAPITAL LETTER SHTAPIC;Lu;0;L;;;;;N;;;;2C5C; 2C2D;GLAGOLITIC CAPITAL LETTER TROKUTASTI A;Lu;0;L;;;;;N;;;;2C5D; 2C2E;GLAGOLITIC CAPITAL LETTER LATINATE MYSLITE;Lu;0;L;;;;;N;;;;2C5E; 2C30;GLAGOLITIC SMALL LETTER AZU;Ll;0;L;;;;;N;;;2C00;;2C00 2C31;GLAGOLITIC SMALL LETTER BUKY;Ll;0;L;;;;;N;;;2C01;;2C01 2C32;GLAGOLITIC SMALL LETTER VEDE;Ll;0;L;;;;;N;;;2C02;;2C02 2C33;GLAGOLITIC SMALL LETTER GLAGOLI;Ll;0;L;;;;;N;;;2C03;;2C03 2C34;GLAGOLITIC SMALL LETTER DOBRO;Ll;0;L;;;;;N;;;2C04;;2C04 2C35;GLAGOLITIC SMALL LETTER YESTU;Ll;0;L;;;;;N;;;2C05;;2C05 2C36;GLAGOLITIC SMALL LETTER ZHIVETE;Ll;0;L;;;;;N;;;2C06;;2C06 2C37;GLAGOLITIC SMALL LETTER DZELO;Ll;0;L;;;;;N;;;2C07;;2C07 2C38;GLAGOLITIC SMALL LETTER ZEMLJA;Ll;0;L;;;;;N;;;2C08;;2C08 2C39;GLAGOLITIC SMALL LETTER IZHE;Ll;0;L;;;;;N;;;2C09;;2C09 2C3A;GLAGOLITIC SMALL LETTER INITIAL IZHE;Ll;0;L;;;;;N;;;2C0A;;2C0A 2C3B;GLAGOLITIC SMALL LETTER I;Ll;0;L;;;;;N;;;2C0B;;2C0B 2C3C;GLAGOLITIC SMALL LETTER DJERVI;Ll;0;L;;;;;N;;;2C0C;;2C0C 2C3D;GLAGOLITIC SMALL LETTER KAKO;Ll;0;L;;;;;N;;;2C0D;;2C0D 2C3E;GLAGOLITIC SMALL LETTER LJUDIJE;Ll;0;L;;;;;N;;;2C0E;;2C0E 2C3F;GLAGOLITIC SMALL LETTER MYSLITE;Ll;0;L;;;;;N;;;2C0F;;2C0F 2C40;GLAGOLITIC SMALL LETTER NASHI;Ll;0;L;;;;;N;;;2C10;;2C10 2C41;GLAGOLITIC SMALL LETTER ONU;Ll;0;L;;;;;N;;;2C11;;2C11 2C42;GLAGOLITIC SMALL LETTER POKOJI;Ll;0;L;;;;;N;;;2C12;;2C12 2C43;GLAGOLITIC SMALL LETTER RITSI;Ll;0;L;;;;;N;;;2C13;;2C13 2C44;GLAGOLITIC SMALL LETTER SLOVO;Ll;0;L;;;;;N;;;2C14;;2C14 2C45;GLAGOLITIC SMALL LETTER TVRIDO;Ll;0;L;;;;;N;;;2C15;;2C15 2C46;GLAGOLITIC SMALL LETTER UKU;Ll;0;L;;;;;N;;;2C16;;2C16 2C47;GLAGOLITIC SMALL LETTER FRITU;Ll;0;L;;;;;N;;;2C17;;2C17 2C48;GLAGOLITIC SMALL LETTER HERU;Ll;0;L;;;;;N;;;2C18;;2C18 2C49;GLAGOLITIC SMALL LETTER OTU;Ll;0;L;;;;;N;;;2C19;;2C19 2C4A;GLAGOLITIC SMALL LETTER PE;Ll;0;L;;;;;N;;;2C1A;;2C1A 2C4B;GLAGOLITIC SMALL LETTER SHTA;Ll;0;L;;;;;N;;;2C1B;;2C1B 2C4C;GLAGOLITIC SMALL LETTER TSI;Ll;0;L;;;;;N;;;2C1C;;2C1C 2C4D;GLAGOLITIC SMALL LETTER CHRIVI;Ll;0;L;;;;;N;;;2C1D;;2C1D 2C4E;GLAGOLITIC SMALL LETTER SHA;Ll;0;L;;;;;N;;;2C1E;;2C1E 2C4F;GLAGOLITIC SMALL LETTER YERU;Ll;0;L;;;;;N;;;2C1F;;2C1F 2C50;GLAGOLITIC SMALL LETTER YERI;Ll;0;L;;;;;N;;;2C20;;2C20 2C51;GLAGOLITIC SMALL LETTER YATI;Ll;0;L;;;;;N;;;2C21;;2C21 2C52;GLAGOLITIC SMALL LETTER SPIDERY HA;Ll;0;L;;;;;N;;;2C22;;2C22 2C53;GLAGOLITIC SMALL LETTER YU;Ll;0;L;;;;;N;;;2C23;;2C23 2C54;GLAGOLITIC SMALL LETTER SMALL YUS;Ll;0;L;;;;;N;;;2C24;;2C24 2C55;GLAGOLITIC SMALL LETTER SMALL YUS WITH TAIL;Ll;0;L;;;;;N;;;2C25;;2C25 2C56;GLAGOLITIC SMALL LETTER YO;Ll;0;L;;;;;N;;;2C26;;2C26 2C57;GLAGOLITIC SMALL LETTER IOTATED SMALL YUS;Ll;0;L;;;;;N;;;2C27;;2C27 2C58;GLAGOLITIC SMALL LETTER BIG YUS;Ll;0;L;;;;;N;;;2C28;;2C28 2C59;GLAGOLITIC SMALL LETTER IOTATED BIG YUS;Ll;0;L;;;;;N;;;2C29;;2C29 2C5A;GLAGOLITIC SMALL LETTER FITA;Ll;0;L;;;;;N;;;2C2A;;2C2A 2C5B;GLAGOLITIC SMALL LETTER IZHITSA;Ll;0;L;;;;;N;;;2C2B;;2C2B 2C5C;GLAGOLITIC SMALL LETTER SHTAPIC;Ll;0;L;;;;;N;;;2C2C;;2C2C 2C5D;GLAGOLITIC SMALL LETTER TROKUTASTI A;Ll;0;L;;;;;N;;;2C2D;;2C2D 2C5E;GLAGOLITIC SMALL LETTER LATINATE MYSLITE;Ll;0;L;;;;;N;;;2C2E;;2C2E 2C60;LATIN CAPITAL LETTER L WITH DOUBLE BAR;Lu;0;L;;;;;N;;;;2C61; 2C61;LATIN SMALL LETTER L WITH DOUBLE BAR;Ll;0;L;;;;;N;;;2C60;;2C60 2C62;LATIN CAPITAL LETTER L WITH MIDDLE TILDE;Lu;0;L;;;;;N;;;;026B; 2C63;LATIN CAPITAL LETTER P WITH STROKE;Lu;0;L;;;;;N;;;;1D7D; 2C64;LATIN CAPITAL LETTER R WITH TAIL;Lu;0;L;;;;;N;;;;027D; 2C65;LATIN SMALL LETTER A WITH STROKE;Ll;0;L;;;;;N;;;023A;;023A 2C66;LATIN SMALL LETTER T WITH DIAGONAL STROKE;Ll;0;L;;;;;N;;;023E;;023E 2C67;LATIN CAPITAL LETTER H WITH DESCENDER;Lu;0;L;;;;;N;;;;2C68; 2C68;LATIN SMALL LETTER H WITH DESCENDER;Ll;0;L;;;;;N;;;2C67;;2C67 2C69;LATIN CAPITAL LETTER K WITH DESCENDER;Lu;0;L;;;;;N;;;;2C6A; 2C6A;LATIN SMALL LETTER K WITH DESCENDER;Ll;0;L;;;;;N;;;2C69;;2C69 2C6B;LATIN CAPITAL LETTER Z WITH DESCENDER;Lu;0;L;;;;;N;;;;2C6C; 2C6C;LATIN SMALL LETTER Z WITH DESCENDER;Ll;0;L;;;;;N;;;2C6B;;2C6B 2C6D;LATIN CAPITAL LETTER ALPHA;Lu;0;L;;;;;N;;;;0251; 2C6E;LATIN CAPITAL LETTER M WITH HOOK;Lu;0;L;;;;;N;;;;0271; 2C6F;LATIN CAPITAL LETTER TURNED A;Lu;0;L;;;;;N;;;;0250; 2C70;LATIN CAPITAL LETTER TURNED ALPHA;Lu;0;L;;;;;N;;;;0252; 2C71;LATIN SMALL LETTER V WITH RIGHT HOOK;Ll;0;L;;;;;N;;;;; 2C72;LATIN CAPITAL LETTER W WITH HOOK;Lu;0;L;;;;;N;;;;2C73; 2C73;LATIN SMALL LETTER W WITH HOOK;Ll;0;L;;;;;N;;;2C72;;2C72 2C74;LATIN SMALL LETTER V WITH CURL;Ll;0;L;;;;;N;;;;; 2C75;LATIN CAPITAL LETTER HALF H;Lu;0;L;;;;;N;;;;2C76; 2C76;LATIN SMALL LETTER HALF H;Ll;0;L;;;;;N;;;2C75;;2C75 2C77;LATIN SMALL LETTER TAILLESS PHI;Ll;0;L;;;;;N;;;;; 2C78;LATIN SMALL LETTER E WITH NOTCH;Ll;0;L;;;;;N;;;;; 2C79;LATIN SMALL LETTER TURNED R WITH TAIL;Ll;0;L;;;;;N;;;;; 2C7A;LATIN SMALL LETTER O WITH LOW RING INSIDE;Ll;0;L;;;;;N;;;;; 2C7B;LATIN LETTER SMALL CAPITAL TURNED E;Ll;0;L;;;;;N;;;;; 2C7C;LATIN SUBSCRIPT SMALL LETTER J;Lm;0;L;<sub> 006A;;;;N;;;;; 2C7D;MODIFIER LETTER CAPITAL V;Lm;0;L;<super> 0056;;;;N;;;;; 2C7E;LATIN CAPITAL LETTER S WITH SWASH TAIL;Lu;0;L;;;;;N;;;;023F; 2C7F;LATIN CAPITAL LETTER Z WITH SWASH TAIL;Lu;0;L;;;;;N;;;;0240; 2C80;COPTIC CAPITAL LETTER ALFA;Lu;0;L;;;;;N;;;;2C81; 2C81;COPTIC SMALL LETTER ALFA;Ll;0;L;;;;;N;;;2C80;;2C80 2C82;COPTIC CAPITAL LETTER VIDA;Lu;0;L;;;;;N;;;;2C83; 2C83;COPTIC SMALL LETTER VIDA;Ll;0;L;;;;;N;;;2C82;;2C82 2C84;COPTIC CAPITAL LETTER GAMMA;Lu;0;L;;;;;N;;;;2C85; 2C85;COPTIC SMALL LETTER GAMMA;Ll;0;L;;;;;N;;;2C84;;2C84 2C86;COPTIC CAPITAL LETTER DALDA;Lu;0;L;;;;;N;;;;2C87; 2C87;COPTIC SMALL LETTER DALDA;Ll;0;L;;;;;N;;;2C86;;2C86 2C88;COPTIC CAPITAL LETTER EIE;Lu;0;L;;;;;N;;;;2C89; 2C89;COPTIC SMALL LETTER EIE;Ll;0;L;;;;;N;;;2C88;;2C88 2C8A;COPTIC CAPITAL LETTER SOU;Lu;0;L;;;;;N;;;;2C8B; 2C8B;COPTIC SMALL LETTER SOU;Ll;0;L;;;;;N;;;2C8A;;2C8A 2C8C;COPTIC CAPITAL LETTER ZATA;Lu;0;L;;;;;N;;;;2C8D; 2C8D;COPTIC SMALL LETTER ZATA;Ll;0;L;;;;;N;;;2C8C;;2C8C 2C8E;COPTIC CAPITAL LETTER HATE;Lu;0;L;;;;;N;;;;2C8F; 2C8F;COPTIC SMALL LETTER HATE;Ll;0;L;;;;;N;;;2C8E;;2C8E 2C90;COPTIC CAPITAL LETTER THETHE;Lu;0;L;;;;;N;;;;2C91; 2C91;COPTIC SMALL LETTER THETHE;Ll;0;L;;;;;N;;;2C90;;2C90 2C92;COPTIC CAPITAL LETTER IAUDA;Lu;0;L;;;;;N;;;;2C93; 2C93;COPTIC SMALL LETTER IAUDA;Ll;0;L;;;;;N;;;2C92;;2C92 2C94;COPTIC CAPITAL LETTER KAPA;Lu;0;L;;;;;N;;;;2C95; 2C95;COPTIC SMALL LETTER KAPA;Ll;0;L;;;;;N;;;2C94;;2C94 2C96;COPTIC CAPITAL LETTER LAULA;Lu;0;L;;;;;N;;;;2C97; 2C97;COPTIC SMALL LETTER LAULA;Ll;0;L;;;;;N;;;2C96;;2C96 2C98;COPTIC CAPITAL LETTER MI;Lu;0;L;;;;;N;;;;2C99; 2C99;COPTIC SMALL LETTER MI;Ll;0;L;;;;;N;;;2C98;;2C98 2C9A;COPTIC CAPITAL LETTER NI;Lu;0;L;;;;;N;;;;2C9B; 2C9B;COPTIC SMALL LETTER NI;Ll;0;L;;;;;N;;;2C9A;;2C9A 2C9C;COPTIC CAPITAL LETTER KSI;Lu;0;L;;;;;N;;;;2C9D; 2C9D;COPTIC SMALL LETTER KSI;Ll;0;L;;;;;N;;;2C9C;;2C9C 2C9E;COPTIC CAPITAL LETTER O;Lu;0;L;;;;;N;;;;2C9F; 2C9F;COPTIC SMALL LETTER O;Ll;0;L;;;;;N;;;2C9E;;2C9E 2CA0;COPTIC CAPITAL LETTER PI;Lu;0;L;;;;;N;;;;2CA1; 2CA1;COPTIC SMALL LETTER PI;Ll;0;L;;;;;N;;;2CA0;;2CA0 2CA2;COPTIC CAPITAL LETTER RO;Lu;0;L;;;;;N;;;;2CA3; 2CA3;COPTIC SMALL LETTER RO;Ll;0;L;;;;;N;;;2CA2;;2CA2 2CA4;COPTIC CAPITAL LETTER SIMA;Lu;0;L;;;;;N;;;;2CA5; 2CA5;COPTIC SMALL LETTER SIMA;Ll;0;L;;;;;N;;;2CA4;;2CA4 2CA6;COPTIC CAPITAL LETTER TAU;Lu;0;L;;;;;N;;;;2CA7; 2CA7;COPTIC SMALL LETTER TAU;Ll;0;L;;;;;N;;;2CA6;;2CA6 2CA8;COPTIC CAPITAL LETTER UA;Lu;0;L;;;;;N;;;;2CA9; 2CA9;COPTIC SMALL LETTER UA;Ll;0;L;;;;;N;;;2CA8;;2CA8 2CAA;COPTIC CAPITAL LETTER FI;Lu;0;L;;;;;N;;;;2CAB; 2CAB;COPTIC SMALL LETTER FI;Ll;0;L;;;;;N;;;2CAA;;2CAA 2CAC;COPTIC CAPITAL LETTER KHI;Lu;0;L;;;;;N;;;;2CAD; 2CAD;COPTIC SMALL LETTER KHI;Ll;0;L;;;;;N;;;2CAC;;2CAC 2CAE;COPTIC CAPITAL LETTER PSI;Lu;0;L;;;;;N;;;;2CAF; 2CAF;COPTIC SMALL LETTER PSI;Ll;0;L;;;;;N;;;2CAE;;2CAE 2CB0;COPTIC CAPITAL LETTER OOU;Lu;0;L;;;;;N;;;;2CB1; 2CB1;COPTIC SMALL LETTER OOU;Ll;0;L;;;;;N;;;2CB0;;2CB0 2CB2;COPTIC CAPITAL LETTER DIALECT-P ALEF;Lu;0;L;;;;;N;;;;2CB3; 2CB3;COPTIC SMALL LETTER DIALECT-P ALEF;Ll;0;L;;;;;N;;;2CB2;;2CB2 2CB4;COPTIC CAPITAL LETTER OLD COPTIC AIN;Lu;0;L;;;;;N;;;;2CB5; 2CB5;COPTIC SMALL LETTER OLD COPTIC AIN;Ll;0;L;;;;;N;;;2CB4;;2CB4 2CB6;COPTIC CAPITAL LETTER CRYPTOGRAMMIC EIE;Lu;0;L;;;;;N;;;;2CB7; 2CB7;COPTIC SMALL LETTER CRYPTOGRAMMIC EIE;Ll;0;L;;;;;N;;;2CB6;;2CB6 2CB8;COPTIC CAPITAL LETTER DIALECT-P KAPA;Lu;0;L;;;;;N;;;;2CB9; 2CB9;COPTIC SMALL LETTER DIALECT-P KAPA;Ll;0;L;;;;;N;;;2CB8;;2CB8 2CBA;COPTIC CAPITAL LETTER DIALECT-P NI;Lu;0;L;;;;;N;;;;2CBB; 2CBB;COPTIC SMALL LETTER DIALECT-P NI;Ll;0;L;;;;;N;;;2CBA;;2CBA 2CBC;COPTIC CAPITAL LETTER CRYPTOGRAMMIC NI;Lu;0;L;;;;;N;;;;2CBD; 2CBD;COPTIC SMALL LETTER CRYPTOGRAMMIC NI;Ll;0;L;;;;;N;;;2CBC;;2CBC 2CBE;COPTIC CAPITAL LETTER OLD COPTIC OOU;Lu;0;L;;;;;N;;;;2CBF; 2CBF;COPTIC SMALL LETTER OLD COPTIC OOU;Ll;0;L;;;;;N;;;2CBE;;2CBE 2CC0;COPTIC CAPITAL LETTER SAMPI;Lu;0;L;;;;;N;;;;2CC1; 2CC1;COPTIC SMALL LETTER SAMPI;Ll;0;L;;;;;N;;;2CC0;;2CC0 2CC2;COPTIC CAPITAL LETTER CROSSED SHEI;Lu;0;L;;;;;N;;;;2CC3; 2CC3;COPTIC SMALL LETTER CROSSED SHEI;Ll;0;L;;;;;N;;;2CC2;;2CC2 2CC4;COPTIC CAPITAL LETTER OLD COPTIC SHEI;Lu;0;L;;;;;N;;;;2CC5; 2CC5;COPTIC SMALL LETTER OLD COPTIC SHEI;Ll;0;L;;;;;N;;;2CC4;;2CC4 2CC6;COPTIC CAPITAL LETTER OLD COPTIC ESH;Lu;0;L;;;;;N;;;;2CC7; 2CC7;COPTIC SMALL LETTER OLD COPTIC ESH;Ll;0;L;;;;;N;;;2CC6;;2CC6 2CC8;COPTIC CAPITAL LETTER AKHMIMIC KHEI;Lu;0;L;;;;;N;;;;2CC9; 2CC9;COPTIC SMALL LETTER AKHMIMIC KHEI;Ll;0;L;;;;;N;;;2CC8;;2CC8 2CCA;COPTIC CAPITAL LETTER DIALECT-P HORI;Lu;0;L;;;;;N;;;;2CCB; 2CCB;COPTIC SMALL LETTER DIALECT-P HORI;Ll;0;L;;;;;N;;;2CCA;;2CCA 2CCC;COPTIC CAPITAL LETTER OLD COPTIC HORI;Lu;0;L;;;;;N;;;;2CCD; 2CCD;COPTIC SMALL LETTER OLD COPTIC HORI;Ll;0;L;;;;;N;;;2CCC;;2CCC 2CCE;COPTIC CAPITAL LETTER OLD COPTIC HA;Lu;0;L;;;;;N;;;;2CCF; 2CCF;COPTIC SMALL LETTER OLD COPTIC HA;Ll;0;L;;;;;N;;;2CCE;;2CCE 2CD0;COPTIC CAPITAL LETTER L-SHAPED HA;Lu;0;L;;;;;N;;;;2CD1; 2CD1;COPTIC SMALL LETTER L-SHAPED HA;Ll;0;L;;;;;N;;;2CD0;;2CD0 2CD2;COPTIC CAPITAL LETTER OLD COPTIC HEI;Lu;0;L;;;;;N;;;;2CD3; 2CD3;COPTIC SMALL LETTER OLD COPTIC HEI;Ll;0;L;;;;;N;;;2CD2;;2CD2 2CD4;COPTIC CAPITAL LETTER OLD COPTIC HAT;Lu;0;L;;;;;N;;;;2CD5; 2CD5;COPTIC SMALL LETTER OLD COPTIC HAT;Ll;0;L;;;;;N;;;2CD4;;2CD4 2CD6;COPTIC CAPITAL LETTER OLD COPTIC GANGIA;Lu;0;L;;;;;N;;;;2CD7; 2CD7;COPTIC SMALL LETTER OLD COPTIC GANGIA;Ll;0;L;;;;;N;;;2CD6;;2CD6 2CD8;COPTIC CAPITAL LETTER OLD COPTIC DJA;Lu;0;L;;;;;N;;;;2CD9; 2CD9;COPTIC SMALL LETTER OLD COPTIC DJA;Ll;0;L;;;;;N;;;2CD8;;2CD8 2CDA;COPTIC CAPITAL LETTER OLD COPTIC SHIMA;Lu;0;L;;;;;N;;;;2CDB; 2CDB;COPTIC SMALL LETTER OLD COPTIC SHIMA;Ll;0;L;;;;;N;;;2CDA;;2CDA 2CDC;COPTIC CAPITAL LETTER OLD NUBIAN SHIMA;Lu;0;L;;;;;N;;;;2CDD; 2CDD;COPTIC SMALL LETTER OLD NUBIAN SHIMA;Ll;0;L;;;;;N;;;2CDC;;2CDC 2CDE;COPTIC CAPITAL LETTER OLD NUBIAN NGI;Lu;0;L;;;;;N;;;;2CDF; 2CDF;COPTIC SMALL LETTER OLD NUBIAN NGI;Ll;0;L;;;;;N;;;2CDE;;2CDE 2CE0;COPTIC CAPITAL LETTER OLD NUBIAN NYI;Lu;0;L;;;;;N;;;;2CE1; 2CE1;COPTIC SMALL LETTER OLD NUBIAN NYI;Ll;0;L;;;;;N;;;2CE0;;2CE0 2CE2;COPTIC CAPITAL LETTER OLD NUBIAN WAU;Lu;0;L;;;;;N;;;;2CE3; 2CE3;COPTIC SMALL LETTER OLD NUBIAN WAU;Ll;0;L;;;;;N;;;2CE2;;2CE2 2CE4;COPTIC SYMBOL KAI;Ll;0;L;;;;;N;;;;; 2CE5;COPTIC SYMBOL MI RO;So;0;ON;;;;;N;;;;; 2CE6;COPTIC SYMBOL PI RO;So;0;ON;;;;;N;;;;; 2CE7;COPTIC SYMBOL STAUROS;So;0;ON;;;;;N;;;;; 2CE8;COPTIC SYMBOL TAU RO;So;0;ON;;;;;N;;;;; 2CE9;COPTIC SYMBOL KHI RO;So;0;ON;;;;;N;;;;; 2CEA;COPTIC SYMBOL SHIMA SIMA;So;0;ON;;;;;N;;;;; 2CEB;COPTIC CAPITAL LETTER CRYPTOGRAMMIC SHEI;Lu;0;L;;;;;N;;;;2CEC; 2CEC;COPTIC SMALL LETTER CRYPTOGRAMMIC SHEI;Ll;0;L;;;;;N;;;2CEB;;2CEB 2CED;COPTIC CAPITAL LETTER CRYPTOGRAMMIC GANGIA;Lu;0;L;;;;;N;;;;2CEE; 2CEE;COPTIC SMALL LETTER CRYPTOGRAMMIC GANGIA;Ll;0;L;;;;;N;;;2CED;;2CED 2CEF;COPTIC COMBINING NI ABOVE;Mn;230;NSM;;;;;N;;;;; 2CF0;COPTIC COMBINING SPIRITUS ASPER;Mn;230;NSM;;;;;N;;;;; 2CF1;COPTIC COMBINING SPIRITUS LENIS;Mn;230;NSM;;;;;N;;;;; 2CF2;COPTIC CAPITAL LETTER BOHAIRIC KHEI;Lu;0;L;;;;;N;;;;2CF3; 2CF3;COPTIC SMALL LETTER BOHAIRIC KHEI;Ll;0;L;;;;;N;;;2CF2;;2CF2 2CF9;COPTIC OLD NUBIAN FULL STOP;Po;0;ON;;;;;N;;;;; 2CFA;COPTIC OLD NUBIAN DIRECT QUESTION MARK;Po;0;ON;;;;;N;;;;; 2CFB;COPTIC OLD NUBIAN INDIRECT QUESTION MARK;Po;0;ON;;;;;N;;;;; 2CFC;COPTIC OLD NUBIAN VERSE DIVIDER;Po;0;ON;;;;;N;;;;; 2CFD;COPTIC FRACTION ONE HALF;No;0;ON;;;;1/2;N;;;;; 2CFE;COPTIC FULL STOP;Po;0;ON;;;;;N;;;;; 2CFF;COPTIC MORPHOLOGICAL DIVIDER;Po;0;ON;;;;;N;;;;; 2D00;GEORGIAN SMALL LETTER AN;Ll;0;L;;;;;N;;;10A0;;10A0 2D01;GEORGIAN SMALL LETTER BAN;Ll;0;L;;;;;N;;;10A1;;10A1 2D02;GEORGIAN SMALL LETTER GAN;Ll;0;L;;;;;N;;;10A2;;10A2 2D03;GEORGIAN SMALL LETTER DON;Ll;0;L;;;;;N;;;10A3;;10A3 2D04;GEORGIAN SMALL LETTER EN;Ll;0;L;;;;;N;;;10A4;;10A4 2D05;GEORGIAN SMALL LETTER VIN;Ll;0;L;;;;;N;;;10A5;;10A5 2D06;GEORGIAN SMALL LETTER ZEN;Ll;0;L;;;;;N;;;10A6;;10A6 2D07;GEORGIAN SMALL LETTER TAN;Ll;0;L;;;;;N;;;10A7;;10A7 2D08;GEORGIAN SMALL LETTER IN;Ll;0;L;;;;;N;;;10A8;;10A8 2D09;GEORGIAN SMALL LETTER KAN;Ll;0;L;;;;;N;;;10A9;;10A9 2D0A;GEORGIAN SMALL LETTER LAS;Ll;0;L;;;;;N;;;10AA;;10AA 2D0B;GEORGIAN SMALL LETTER MAN;Ll;0;L;;;;;N;;;10AB;;10AB 2D0C;GEORGIAN SMALL LETTER NAR;Ll;0;L;;;;;N;;;10AC;;10AC 2D0D;GEORGIAN SMALL LETTER ON;Ll;0;L;;;;;N;;;10AD;;10AD 2D0E;GEORGIAN SMALL LETTER PAR;Ll;0;L;;;;;N;;;10AE;;10AE 2D0F;GEORGIAN SMALL LETTER ZHAR;Ll;0;L;;;;;N;;;10AF;;10AF 2D10;GEORGIAN SMALL LETTER RAE;Ll;0;L;;;;;N;;;10B0;;10B0 2D11;GEORGIAN SMALL LETTER SAN;Ll;0;L;;;;;N;;;10B1;;10B1 2D12;GEORGIAN SMALL LETTER TAR;Ll;0;L;;;;;N;;;10B2;;10B2 2D13;GEORGIAN SMALL LETTER UN;Ll;0;L;;;;;N;;;10B3;;10B3 2D14;GEORGIAN SMALL LETTER PHAR;Ll;0;L;;;;;N;;;10B4;;10B4 2D15;GEORGIAN SMALL LETTER KHAR;Ll;0;L;;;;;N;;;10B5;;10B5 2D16;GEORGIAN SMALL LETTER GHAN;Ll;0;L;;;;;N;;;10B6;;10B6 2D17;GEORGIAN SMALL LETTER QAR;Ll;0;L;;;;;N;;;10B7;;10B7 2D18;GEORGIAN SMALL LETTER SHIN;Ll;0;L;;;;;N;;;10B8;;10B8 2D19;GEORGIAN SMALL LETTER CHIN;Ll;0;L;;;;;N;;;10B9;;10B9 2D1A;GEORGIAN SMALL LETTER CAN;Ll;0;L;;;;;N;;;10BA;;10BA 2D1B;GEORGIAN SMALL LETTER JIL;Ll;0;L;;;;;N;;;10BB;;10BB 2D1C;GEORGIAN SMALL LETTER CIL;Ll;0;L;;;;;N;;;10BC;;10BC 2D1D;GEORGIAN SMALL LETTER CHAR;Ll;0;L;;;;;N;;;10BD;;10BD 2D1E;GEORGIAN SMALL LETTER XAN;Ll;0;L;;;;;N;;;10BE;;10BE 2D1F;GEORGIAN SMALL LETTER JHAN;Ll;0;L;;;;;N;;;10BF;;10BF 2D20;GEORGIAN SMALL LETTER HAE;Ll;0;L;;;;;N;;;10C0;;10C0 2D21;GEORGIAN SMALL LETTER HE;Ll;0;L;;;;;N;;;10C1;;10C1 2D22;GEORGIAN SMALL LETTER HIE;Ll;0;L;;;;;N;;;10C2;;10C2 2D23;GEORGIAN SMALL LETTER WE;Ll;0;L;;;;;N;;;10C3;;10C3 2D24;GEORGIAN SMALL LETTER HAR;Ll;0;L;;;;;N;;;10C4;;10C4 2D25;GEORGIAN SMALL LETTER HOE;Ll;0;L;;;;;N;;;10C5;;10C5 2D27;GEORGIAN SMALL LETTER YN;Ll;0;L;;;;;N;;;10C7;;10C7 2D2D;GEORGIAN SMALL LETTER AEN;Ll;0;L;;;;;N;;;10CD;;10CD 2D30;TIFINAGH LETTER YA;Lo;0;L;;;;;N;;;;; 2D31;TIFINAGH LETTER YAB;Lo;0;L;;;;;N;;;;; 2D32;TIFINAGH LETTER YABH;Lo;0;L;;;;;N;;;;; 2D33;TIFINAGH LETTER YAG;Lo;0;L;;;;;N;;;;; 2D34;TIFINAGH LETTER YAGHH;Lo;0;L;;;;;N;;;;; 2D35;TIFINAGH LETTER BERBER ACADEMY YAJ;Lo;0;L;;;;;N;;;;; 2D36;TIFINAGH LETTER YAJ;Lo;0;L;;;;;N;;;;; 2D37;TIFINAGH LETTER YAD;Lo;0;L;;;;;N;;;;; 2D38;TIFINAGH LETTER YADH;Lo;0;L;;;;;N;;;;; 2D39;TIFINAGH LETTER YADD;Lo;0;L;;;;;N;;;;; 2D3A;TIFINAGH LETTER YADDH;Lo;0;L;;;;;N;;;;; 2D3B;TIFINAGH LETTER YEY;Lo;0;L;;;;;N;;;;; 2D3C;TIFINAGH LETTER YAF;Lo;0;L;;;;;N;;;;; 2D3D;TIFINAGH LETTER YAK;Lo;0;L;;;;;N;;;;; 2D3E;TIFINAGH LETTER TUAREG YAK;Lo;0;L;;;;;N;;;;; 2D3F;TIFINAGH LETTER YAKHH;Lo;0;L;;;;;N;;;;; 2D40;TIFINAGH LETTER YAH;Lo;0;L;;;;;N;;;;; 2D41;TIFINAGH LETTER BERBER ACADEMY YAH;Lo;0;L;;;;;N;;;;; 2D42;TIFINAGH LETTER TUAREG YAH;Lo;0;L;;;;;N;;;;; 2D43;TIFINAGH LETTER YAHH;Lo;0;L;;;;;N;;;;; 2D44;TIFINAGH LETTER YAA;Lo;0;L;;;;;N;;;;; 2D45;TIFINAGH LETTER YAKH;Lo;0;L;;;;;N;;;;; 2D46;TIFINAGH LETTER TUAREG YAKH;Lo;0;L;;;;;N;;;;; 2D47;TIFINAGH LETTER YAQ;Lo;0;L;;;;;N;;;;; 2D48;TIFINAGH LETTER TUAREG YAQ;Lo;0;L;;;;;N;;;;; 2D49;TIFINAGH LETTER YI;Lo;0;L;;;;;N;;;;; 2D4A;TIFINAGH LETTER YAZH;Lo;0;L;;;;;N;;;;; 2D4B;TIFINAGH LETTER AHAGGAR YAZH;Lo;0;L;;;;;N;;;;; 2D4C;TIFINAGH LETTER TUAREG YAZH;Lo;0;L;;;;;N;;;;; 2D4D;TIFINAGH LETTER YAL;Lo;0;L;;;;;N;;;;; 2D4E;TIFINAGH LETTER YAM;Lo;0;L;;;;;N;;;;; 2D4F;TIFINAGH LETTER YAN;Lo;0;L;;;;;N;;;;; 2D50;TIFINAGH LETTER TUAREG YAGN;Lo;0;L;;;;;N;;;;; 2D51;TIFINAGH LETTER TUAREG YANG;Lo;0;L;;;;;N;;;;; 2D52;TIFINAGH LETTER YAP;Lo;0;L;;;;;N;;;;; 2D53;TIFINAGH LETTER YU;Lo;0;L;;;;;N;;;;; 2D54;TIFINAGH LETTER YAR;Lo;0;L;;;;;N;;;;; 2D55;TIFINAGH LETTER YARR;Lo;0;L;;;;;N;;;;; 2D56;TIFINAGH LETTER YAGH;Lo;0;L;;;;;N;;;;; 2D57;TIFINAGH LETTER TUAREG YAGH;Lo;0;L;;;;;N;;;;; 2D58;TIFINAGH LETTER AYER YAGH;Lo;0;L;;;;;N;;;;; 2D59;TIFINAGH LETTER YAS;Lo;0;L;;;;;N;;;;; 2D5A;TIFINAGH LETTER YASS;Lo;0;L;;;;;N;;;;; 2D5B;TIFINAGH LETTER YASH;Lo;0;L;;;;;N;;;;; 2D5C;TIFINAGH LETTER YAT;Lo;0;L;;;;;N;;;;; 2D5D;TIFINAGH LETTER YATH;Lo;0;L;;;;;N;;;;; 2D5E;TIFINAGH LETTER YACH;Lo;0;L;;;;;N;;;;; 2D5F;TIFINAGH LETTER YATT;Lo;0;L;;;;;N;;;;; 2D60;TIFINAGH LETTER YAV;Lo;0;L;;;;;N;;;;; 2D61;TIFINAGH LETTER YAW;Lo;0;L;;;;;N;;;;; 2D62;TIFINAGH LETTER YAY;Lo;0;L;;;;;N;;;;; 2D63;TIFINAGH LETTER YAZ;Lo;0;L;;;;;N;;;;; 2D64;TIFINAGH LETTER TAWELLEMET YAZ;Lo;0;L;;;;;N;;;;; 2D65;TIFINAGH LETTER YAZZ;Lo;0;L;;;;;N;;;;; 2D66;TIFINAGH LETTER YE;Lo;0;L;;;;;N;;;;; 2D67;TIFINAGH LETTER YO;Lo;0;L;;;;;N;;;;; 2D6F;TIFINAGH MODIFIER LETTER LABIALIZATION MARK;Lm;0;L;<super> 2D61;;;;N;;;;; 2D70;TIFINAGH SEPARATOR MARK;Po;0;L;;;;;N;;;;; 2D7F;TIFINAGH CONSONANT JOINER;Mn;9;NSM;;;;;N;;;;; 2D80;ETHIOPIC SYLLABLE LOA;Lo;0;L;;;;;N;;;;; 2D81;ETHIOPIC SYLLABLE MOA;Lo;0;L;;;;;N;;;;; 2D82;ETHIOPIC SYLLABLE ROA;Lo;0;L;;;;;N;;;;; 2D83;ETHIOPIC SYLLABLE SOA;Lo;0;L;;;;;N;;;;; 2D84;ETHIOPIC SYLLABLE SHOA;Lo;0;L;;;;;N;;;;; 2D85;ETHIOPIC SYLLABLE BOA;Lo;0;L;;;;;N;;;;; 2D86;ETHIOPIC SYLLABLE TOA;Lo;0;L;;;;;N;;;;; 2D87;ETHIOPIC SYLLABLE COA;Lo;0;L;;;;;N;;;;; 2D88;ETHIOPIC SYLLABLE NOA;Lo;0;L;;;;;N;;;;; 2D89;ETHIOPIC SYLLABLE NYOA;Lo;0;L;;;;;N;;;;; 2D8A;ETHIOPIC SYLLABLE GLOTTAL OA;Lo;0;L;;;;;N;;;;; 2D8B;ETHIOPIC SYLLABLE ZOA;Lo;0;L;;;;;N;;;;; 2D8C;ETHIOPIC SYLLABLE DOA;Lo;0;L;;;;;N;;;;; 2D8D;ETHIOPIC SYLLABLE DDOA;Lo;0;L;;;;;N;;;;; 2D8E;ETHIOPIC SYLLABLE JOA;Lo;0;L;;;;;N;;;;; 2D8F;ETHIOPIC SYLLABLE THOA;Lo;0;L;;;;;N;;;;; 2D90;ETHIOPIC SYLLABLE CHOA;Lo;0;L;;;;;N;;;;; 2D91;ETHIOPIC SYLLABLE PHOA;Lo;0;L;;;;;N;;;;; 2D92;ETHIOPIC SYLLABLE POA;Lo;0;L;;;;;N;;;;; 2D93;ETHIOPIC SYLLABLE GGWA;Lo;0;L;;;;;N;;;;; 2D94;ETHIOPIC SYLLABLE GGWI;Lo;0;L;;;;;N;;;;; 2D95;ETHIOPIC SYLLABLE GGWEE;Lo;0;L;;;;;N;;;;; 2D96;ETHIOPIC SYLLABLE GGWE;Lo;0;L;;;;;N;;;;; 2DA0;ETHIOPIC SYLLABLE SSA;Lo;0;L;;;;;N;;;;; 2DA1;ETHIOPIC SYLLABLE SSU;Lo;0;L;;;;;N;;;;; 2DA2;ETHIOPIC SYLLABLE SSI;Lo;0;L;;;;;N;;;;; 2DA3;ETHIOPIC SYLLABLE SSAA;Lo;0;L;;;;;N;;;;; 2DA4;ETHIOPIC SYLLABLE SSEE;Lo;0;L;;;;;N;;;;; 2DA5;ETHIOPIC SYLLABLE SSE;Lo;0;L;;;;;N;;;;; 2DA6;ETHIOPIC SYLLABLE SSO;Lo;0;L;;;;;N;;;;; 2DA8;ETHIOPIC SYLLABLE CCA;Lo;0;L;;;;;N;;;;; 2DA9;ETHIOPIC SYLLABLE CCU;Lo;0;L;;;;;N;;;;; 2DAA;ETHIOPIC SYLLABLE CCI;Lo;0;L;;;;;N;;;;; 2DAB;ETHIOPIC SYLLABLE CCAA;Lo;0;L;;;;;N;;;;; 2DAC;ETHIOPIC SYLLABLE CCEE;Lo;0;L;;;;;N;;;;; 2DAD;ETHIOPIC SYLLABLE CCE;Lo;0;L;;;;;N;;;;; 2DAE;ETHIOPIC SYLLABLE CCO;Lo;0;L;;;;;N;;;;; 2DB0;ETHIOPIC SYLLABLE ZZA;Lo;0;L;;;;;N;;;;; 2DB1;ETHIOPIC SYLLABLE ZZU;Lo;0;L;;;;;N;;;;; 2DB2;ETHIOPIC SYLLABLE ZZI;Lo;0;L;;;;;N;;;;; 2DB3;ETHIOPIC SYLLABLE ZZAA;Lo;0;L;;;;;N;;;;; 2DB4;ETHIOPIC SYLLABLE ZZEE;Lo;0;L;;;;;N;;;;; 2DB5;ETHIOPIC SYLLABLE ZZE;Lo;0;L;;;;;N;;;;; 2DB6;ETHIOPIC SYLLABLE ZZO;Lo;0;L;;;;;N;;;;; 2DB8;ETHIOPIC SYLLABLE CCHA;Lo;0;L;;;;;N;;;;; 2DB9;ETHIOPIC SYLLABLE CCHU;Lo;0;L;;;;;N;;;;; 2DBA;ETHIOPIC SYLLABLE CCHI;Lo;0;L;;;;;N;;;;; 2DBB;ETHIOPIC SYLLABLE CCHAA;Lo;0;L;;;;;N;;;;; 2DBC;ETHIOPIC SYLLABLE CCHEE;Lo;0;L;;;;;N;;;;; 2DBD;ETHIOPIC SYLLABLE CCHE;Lo;0;L;;;;;N;;;;; 2DBE;ETHIOPIC SYLLABLE CCHO;Lo;0;L;;;;;N;;;;; 2DC0;ETHIOPIC SYLLABLE QYA;Lo;0;L;;;;;N;;;;; 2DC1;ETHIOPIC SYLLABLE QYU;Lo;0;L;;;;;N;;;;; 2DC2;ETHIOPIC SYLLABLE QYI;Lo;0;L;;;;;N;;;;; 2DC3;ETHIOPIC SYLLABLE QYAA;Lo;0;L;;;;;N;;;;; 2DC4;ETHIOPIC SYLLABLE QYEE;Lo;0;L;;;;;N;;;;; 2DC5;ETHIOPIC SYLLABLE QYE;Lo;0;L;;;;;N;;;;; 2DC6;ETHIOPIC SYLLABLE QYO;Lo;0;L;;;;;N;;;;; 2DC8;ETHIOPIC SYLLABLE KYA;Lo;0;L;;;;;N;;;;; 2DC9;ETHIOPIC SYLLABLE KYU;Lo;0;L;;;;;N;;;;; 2DCA;ETHIOPIC SYLLABLE KYI;Lo;0;L;;;;;N;;;;; 2DCB;ETHIOPIC SYLLABLE KYAA;Lo;0;L;;;;;N;;;;; 2DCC;ETHIOPIC SYLLABLE KYEE;Lo;0;L;;;;;N;;;;; 2DCD;ETHIOPIC SYLLABLE KYE;Lo;0;L;;;;;N;;;;; 2DCE;ETHIOPIC SYLLABLE KYO;Lo;0;L;;;;;N;;;;; 2DD0;ETHIOPIC SYLLABLE XYA;Lo;0;L;;;;;N;;;;; 2DD1;ETHIOPIC SYLLABLE XYU;Lo;0;L;;;;;N;;;;; 2DD2;ETHIOPIC SYLLABLE XYI;Lo;0;L;;;;;N;;;;; 2DD3;ETHIOPIC SYLLABLE XYAA;Lo;0;L;;;;;N;;;;; 2DD4;ETHIOPIC SYLLABLE XYEE;Lo;0;L;;;;;N;;;;; 2DD5;ETHIOPIC SYLLABLE XYE;Lo;0;L;;;;;N;;;;; 2DD6;ETHIOPIC SYLLABLE XYO;Lo;0;L;;;;;N;;;;; 2DD8;ETHIOPIC SYLLABLE GYA;Lo;0;L;;;;;N;;;;; 2DD9;ETHIOPIC SYLLABLE GYU;Lo;0;L;;;;;N;;;;; 2DDA;ETHIOPIC SYLLABLE GYI;Lo;0;L;;;;;N;;;;; 2DDB;ETHIOPIC SYLLABLE GYAA;Lo;0;L;;;;;N;;;;; 2DDC;ETHIOPIC SYLLABLE GYEE;Lo;0;L;;;;;N;;;;; 2DDD;ETHIOPIC SYLLABLE GYE;Lo;0;L;;;;;N;;;;; 2DDE;ETHIOPIC SYLLABLE GYO;Lo;0;L;;;;;N;;;;; 2DE0;COMBINING CYRILLIC LETTER BE;Mn;230;NSM;;;;;N;;;;; 2DE1;COMBINING CYRILLIC LETTER VE;Mn;230;NSM;;;;;N;;;;; 2DE2;COMBINING CYRILLIC LETTER GHE;Mn;230;NSM;;;;;N;;;;; 2DE3;COMBINING CYRILLIC LETTER DE;Mn;230;NSM;;;;;N;;;;; 2DE4;COMBINING CYRILLIC LETTER ZHE;Mn;230;NSM;;;;;N;;;;; 2DE5;COMBINING CYRILLIC LETTER ZE;Mn;230;NSM;;;;;N;;;;; 2DE6;COMBINING CYRILLIC LETTER KA;Mn;230;NSM;;;;;N;;;;; 2DE7;COMBINING CYRILLIC LETTER EL;Mn;230;NSM;;;;;N;;;;; 2DE8;COMBINING CYRILLIC LETTER EM;Mn;230;NSM;;;;;N;;;;; 2DE9;COMBINING CYRILLIC LETTER EN;Mn;230;NSM;;;;;N;;;;; 2DEA;COMBINING CYRILLIC LETTER O;Mn;230;NSM;;;;;N;;;;; 2DEB;COMBINING CYRILLIC LETTER PE;Mn;230;NSM;;;;;N;;;;; 2DEC;COMBINING CYRILLIC LETTER ER;Mn;230;NSM;;;;;N;;;;; 2DED;COMBINING CYRILLIC LETTER ES;Mn;230;NSM;;;;;N;;;;; 2DEE;COMBINING CYRILLIC LETTER TE;Mn;230;NSM;;;;;N;;;;; 2DEF;COMBINING CYRILLIC LETTER HA;Mn;230;NSM;;;;;N;;;;; 2DF0;COMBINING CYRILLIC LETTER TSE;Mn;230;NSM;;;;;N;;;;; 2DF1;COMBINING CYRILLIC LETTER CHE;Mn;230;NSM;;;;;N;;;;; 2DF2;COMBINING CYRILLIC LETTER SHA;Mn;230;NSM;;;;;N;;;;; 2DF3;COMBINING CYRILLIC LETTER SHCHA;Mn;230;NSM;;;;;N;;;;; 2DF4;COMBINING CYRILLIC LETTER FITA;Mn;230;NSM;;;;;N;;;;; 2DF5;COMBINING CYRILLIC LETTER ES-TE;Mn;230;NSM;;;;;N;;;;; 2DF6;COMBINING CYRILLIC LETTER A;Mn;230;NSM;;;;;N;;;;; 2DF7;COMBINING CYRILLIC LETTER IE;Mn;230;NSM;;;;;N;;;;; 2DF8;COMBINING CYRILLIC LETTER DJERV;Mn;230;NSM;;;;;N;;;;; 2DF9;COMBINING CYRILLIC LETTER MONOGRAPH UK;Mn;230;NSM;;;;;N;;;;; 2DFA;COMBINING CYRILLIC LETTER YAT;Mn;230;NSM;;;;;N;;;;; 2DFB;COMBINING CYRILLIC LETTER YU;Mn;230;NSM;;;;;N;;;;; 2DFC;COMBINING CYRILLIC LETTER IOTIFIED A;Mn;230;NSM;;;;;N;;;;; 2DFD;COMBINING CYRILLIC LETTER LITTLE YUS;Mn;230;NSM;;;;;N;;;;; 2DFE;COMBINING CYRILLIC LETTER BIG YUS;Mn;230;NSM;;;;;N;;;;; 2DFF;COMBINING CYRILLIC LETTER IOTIFIED BIG YUS;Mn;230;NSM;;;;;N;;;;; 2E00;RIGHT ANGLE SUBSTITUTION MARKER;Po;0;ON;;;;;N;;;;; 2E01;RIGHT ANGLE DOTTED SUBSTITUTION MARKER;Po;0;ON;;;;;N;;;;; 2E02;LEFT SUBSTITUTION BRACKET;Pi;0;ON;;;;;Y;;;;; 2E03;RIGHT SUBSTITUTION BRACKET;Pf;0;ON;;;;;Y;;;;; 2E04;LEFT DOTTED SUBSTITUTION BRACKET;Pi;0;ON;;;;;Y;;;;; 2E05;RIGHT DOTTED SUBSTITUTION BRACKET;Pf;0;ON;;;;;Y;;;;; 2E06;RAISED INTERPOLATION MARKER;Po;0;ON;;;;;N;;;;; 2E07;RAISED DOTTED INTERPOLATION MARKER;Po;0;ON;;;;;N;;;;; 2E08;DOTTED TRANSPOSITION MARKER;Po;0;ON;;;;;N;;;;; 2E09;LEFT TRANSPOSITION BRACKET;Pi;0;ON;;;;;Y;;;;; 2E0A;RIGHT TRANSPOSITION BRACKET;Pf;0;ON;;;;;Y;;;;; 2E0B;RAISED SQUARE;Po;0;ON;;;;;N;;;;; 2E0C;LEFT RAISED OMISSION BRACKET;Pi;0;ON;;;;;Y;;;;; 2E0D;RIGHT RAISED OMISSION BRACKET;Pf;0;ON;;;;;Y;;;;; 2E0E;EDITORIAL CORONIS;Po;0;ON;;;;;N;;;;; 2E0F;PARAGRAPHOS;Po;0;ON;;;;;N;;;;; 2E10;FORKED PARAGRAPHOS;Po;0;ON;;;;;N;;;;; 2E11;REVERSED FORKED PARAGRAPHOS;Po;0;ON;;;;;N;;;;; 2E12;HYPODIASTOLE;Po;0;ON;;;;;N;;;;; 2E13;DOTTED OBELOS;Po;0;ON;;;;;N;;;;; 2E14;DOWNWARDS ANCORA;Po;0;ON;;;;;N;;;;; 2E15;UPWARDS ANCORA;Po;0;ON;;;;;N;;;;; 2E16;DOTTED RIGHT-POINTING ANGLE;Po;0;ON;;;;;N;;;;; 2E17;DOUBLE OBLIQUE HYPHEN;Pd;0;ON;;;;;N;;;;; 2E18;INVERTED INTERROBANG;Po;0;ON;;;;;N;;;;; 2E19;PALM BRANCH;Po;0;ON;;;;;N;;;;; 2E1A;HYPHEN WITH DIAERESIS;Pd;0;ON;;;;;N;;;;; 2E1B;TILDE WITH RING ABOVE;Po;0;ON;;;;;N;;;;; 2E1C;LEFT LOW PARAPHRASE BRACKET;Pi;0;ON;;;;;Y;;;;; 2E1D;RIGHT LOW PARAPHRASE BRACKET;Pf;0;ON;;;;;Y;;;;; 2E1E;TILDE WITH DOT ABOVE;Po;0;ON;;;;;N;;;;; 2E1F;TILDE WITH DOT BELOW;Po;0;ON;;;;;N;;;;; 2E20;LEFT VERTICAL BAR WITH QUILL;Pi;0;ON;;;;;Y;;;;; 2E21;RIGHT VERTICAL BAR WITH QUILL;Pf;0;ON;;;;;Y;;;;; 2E22;TOP LEFT HALF BRACKET;Ps;0;ON;;;;;Y;;;;; 2E23;TOP RIGHT HALF BRACKET;Pe;0;ON;;;;;Y;;;;; 2E24;BOTTOM LEFT HALF BRACKET;Ps;0;ON;;;;;Y;;;;; 2E25;BOTTOM RIGHT HALF BRACKET;Pe;0;ON;;;;;Y;;;;; 2E26;LEFT SIDEWAYS U BRACKET;Ps;0;ON;;;;;Y;;;;; 2E27;RIGHT SIDEWAYS U BRACKET;Pe;0;ON;;;;;Y;;;;; 2E28;LEFT DOUBLE PARENTHESIS;Ps;0;ON;;;;;Y;;;;; 2E29;RIGHT DOUBLE PARENTHESIS;Pe;0;ON;;;;;Y;;;;; 2E2A;TWO DOTS OVER ONE DOT PUNCTUATION;Po;0;ON;;;;;N;;;;; 2E2B;ONE DOT OVER TWO DOTS PUNCTUATION;Po;0;ON;;;;;N;;;;; 2E2C;SQUARED FOUR DOT PUNCTUATION;Po;0;ON;;;;;N;;;;; 2E2D;FIVE DOT MARK;Po;0;ON;;;;;N;;;;; 2E2E;REVERSED QUESTION MARK;Po;0;ON;;;;;N;;;;; 2E2F;VERTICAL TILDE;Lm;0;ON;;;;;N;;;;; 2E30;RING POINT;Po;0;ON;;;;;N;;;;; 2E31;WORD SEPARATOR MIDDLE DOT;Po;0;ON;;;;;N;;;;; 2E32;TURNED COMMA;Po;0;ON;;;;;N;;;;; 2E33;RAISED DOT;Po;0;ON;;;;;N;;;;; 2E34;RAISED COMMA;Po;0;ON;;;;;N;;;;; 2E35;TURNED SEMICOLON;Po;0;ON;;;;;N;;;;; 2E36;DAGGER WITH LEFT GUARD;Po;0;ON;;;;;N;;;;; 2E37;DAGGER WITH RIGHT GUARD;Po;0;ON;;;;;N;;;;; 2E38;TURNED DAGGER;Po;0;ON;;;;;N;;;;; 2E39;TOP HALF SECTION SIGN;Po;0;ON;;;;;N;;;;; 2E3A;TWO-EM DASH;Pd;0;ON;;;;;N;;;;; 2E3B;THREE-EM DASH;Pd;0;ON;;;;;N;;;;; 2E3C;STENOGRAPHIC FULL STOP;Po;0;ON;;;;;N;;;;; 2E3D;VERTICAL SIX DOTS;Po;0;ON;;;;;N;;;;; 2E3E;WIGGLY VERTICAL LINE;Po;0;ON;;;;;N;;;;; 2E3F;CAPITULUM;Po;0;ON;;;;;N;;;;; 2E40;DOUBLE HYPHEN;Pd;0;ON;;;;;N;;;;; 2E41;REVERSED COMMA;Po;0;ON;;;;;N;;;;; 2E42;DOUBLE LOW-REVERSED-9 QUOTATION MARK;Ps;0;ON;;;;;N;;;;; 2E43;DASH WITH LEFT UPTURN;Po;0;ON;;;;;N;;;;; 2E44;DOUBLE SUSPENSION MARK;Po;0;ON;;;;;N;;;;; 2E80;CJK RADICAL REPEAT;So;0;ON;;;;;N;;;;; 2E81;CJK RADICAL CLIFF;So;0;ON;;;;;N;;;;; 2E82;CJK RADICAL SECOND ONE;So;0;ON;;;;;N;;;;; 2E83;CJK RADICAL SECOND TWO;So;0;ON;;;;;N;;;;; 2E84;CJK RADICAL SECOND THREE;So;0;ON;;;;;N;;;;; 2E85;CJK RADICAL PERSON;So;0;ON;;;;;N;;;;; 2E86;CJK RADICAL BOX;So;0;ON;;;;;N;;;;; 2E87;CJK RADICAL TABLE;So;0;ON;;;;;N;;;;; 2E88;CJK RADICAL KNIFE ONE;So;0;ON;;;;;N;;;;; 2E89;CJK RADICAL KNIFE TWO;So;0;ON;;;;;N;;;;; 2E8A;CJK RADICAL DIVINATION;So;0;ON;;;;;N;;;;; 2E8B;CJK RADICAL SEAL;So;0;ON;;;;;N;;;;; 2E8C;CJK RADICAL SMALL ONE;So;0;ON;;;;;N;;;;; 2E8D;CJK RADICAL SMALL TWO;So;0;ON;;;;;N;;;;; 2E8E;CJK RADICAL LAME ONE;So;0;ON;;;;;N;;;;; 2E8F;CJK RADICAL LAME TWO;So;0;ON;;;;;N;;;;; 2E90;CJK RADICAL LAME THREE;So;0;ON;;;;;N;;;;; 2E91;CJK RADICAL LAME FOUR;So;0;ON;;;;;N;;;;; 2E92;CJK RADICAL SNAKE;So;0;ON;;;;;N;;;;; 2E93;CJK RADICAL THREAD;So;0;ON;;;;;N;;;;; 2E94;CJK RADICAL SNOUT ONE;So;0;ON;;;;;N;;;;; 2E95;CJK RADICAL SNOUT TWO;So;0;ON;;;;;N;;;;; 2E96;CJK RADICAL HEART ONE;So;0;ON;;;;;N;;;;; 2E97;CJK RADICAL HEART TWO;So;0;ON;;;;;N;;;;; 2E98;CJK RADICAL HAND;So;0;ON;;;;;N;;;;; 2E99;CJK RADICAL RAP;So;0;ON;;;;;N;;;;; 2E9B;CJK RADICAL CHOKE;So;0;ON;;;;;N;;;;; 2E9C;CJK RADICAL SUN;So;0;ON;;;;;N;;;;; 2E9D;CJK RADICAL MOON;So;0;ON;;;;;N;;;;; 2E9E;CJK RADICAL DEATH;So;0;ON;;;;;N;;;;; 2E9F;CJK RADICAL MOTHER;So;0;ON;<compat> 6BCD;;;;N;;;;; 2EA0;CJK RADICAL CIVILIAN;So;0;ON;;;;;N;;;;; 2EA1;CJK RADICAL WATER ONE;So;0;ON;;;;;N;;;;; 2EA2;CJK RADICAL WATER TWO;So;0;ON;;;;;N;;;;; 2EA3;CJK RADICAL FIRE;So;0;ON;;;;;N;;;;; 2EA4;CJK RADICAL PAW ONE;So;0;ON;;;;;N;;;;; 2EA5;CJK RADICAL PAW TWO;So;0;ON;;;;;N;;;;; 2EA6;CJK RADICAL SIMPLIFIED HALF TREE TRUNK;So;0;ON;;;;;N;;;;; 2EA7;CJK RADICAL COW;So;0;ON;;;;;N;;;;; 2EA8;CJK RADICAL DOG;So;0;ON;;;;;N;;;;; 2EA9;CJK RADICAL JADE;So;0;ON;;;;;N;;;;; 2EAA;CJK RADICAL BOLT OF CLOTH;So;0;ON;;;;;N;;;;; 2EAB;CJK RADICAL EYE;So;0;ON;;;;;N;;;;; 2EAC;CJK RADICAL SPIRIT ONE;So;0;ON;;;;;N;;;;; 2EAD;CJK RADICAL SPIRIT TWO;So;0;ON;;;;;N;;;;; 2EAE;CJK RADICAL BAMBOO;So;0;ON;;;;;N;;;;; 2EAF;CJK RADICAL SILK;So;0;ON;;;;;N;;;;; 2EB0;CJK RADICAL C-SIMPLIFIED SILK;So;0;ON;;;;;N;;;;; 2EB1;CJK RADICAL NET ONE;So;0;ON;;;;;N;;;;; 2EB2;CJK RADICAL NET TWO;So;0;ON;;;;;N;;;;; 2EB3;CJK RADICAL NET THREE;So;0;ON;;;;;N;;;;; 2EB4;CJK RADICAL NET FOUR;So;0;ON;;;;;N;;;;; 2EB5;CJK RADICAL MESH;So;0;ON;;;;;N;;;;; 2EB6;CJK RADICAL SHEEP;So;0;ON;;;;;N;;;;; 2EB7;CJK RADICAL RAM;So;0;ON;;;;;N;;;;; 2EB8;CJK RADICAL EWE;So;0;ON;;;;;N;;;;; 2EB9;CJK RADICAL OLD;So;0;ON;;;;;N;;;;; 2EBA;CJK RADICAL BRUSH ONE;So;0;ON;;;;;N;;;;; 2EBB;CJK RADICAL BRUSH TWO;So;0;ON;;;;;N;;;;; 2EBC;CJK RADICAL MEAT;So;0;ON;;;;;N;;;;; 2EBD;CJK RADICAL MORTAR;So;0;ON;;;;;N;;;;; 2EBE;CJK RADICAL GRASS ONE;So;0;ON;;;;;N;;;;; 2EBF;CJK RADICAL GRASS TWO;So;0;ON;;;;;N;;;;; 2EC0;CJK RADICAL GRASS THREE;So;0;ON;;;;;N;;;;; 2EC1;CJK RADICAL TIGER;So;0;ON;;;;;N;;;;; 2EC2;CJK RADICAL CLOTHES;So;0;ON;;;;;N;;;;; 2EC3;CJK RADICAL WEST ONE;So;0;ON;;;;;N;;;;; 2EC4;CJK RADICAL WEST TWO;So;0;ON;;;;;N;;;;; 2EC5;CJK RADICAL C-SIMPLIFIED SEE;So;0;ON;;;;;N;;;;; 2EC6;CJK RADICAL SIMPLIFIED HORN;So;0;ON;;;;;N;;;;; 2EC7;CJK RADICAL HORN;So;0;ON;;;;;N;;;;; 2EC8;CJK RADICAL C-SIMPLIFIED SPEECH;So;0;ON;;;;;N;;;;; 2EC9;CJK RADICAL C-SIMPLIFIED SHELL;So;0;ON;;;;;N;;;;; 2ECA;CJK RADICAL FOOT;So;0;ON;;;;;N;;;;; 2ECB;CJK RADICAL C-SIMPLIFIED CART;So;0;ON;;;;;N;;;;; 2ECC;CJK RADICAL SIMPLIFIED WALK;So;0;ON;;;;;N;;;;; 2ECD;CJK RADICAL WALK ONE;So;0;ON;;;;;N;;;;; 2ECE;CJK RADICAL WALK TWO;So;0;ON;;;;;N;;;;; 2ECF;CJK RADICAL CITY;So;0;ON;;;;;N;;;;; 2ED0;CJK RADICAL C-SIMPLIFIED GOLD;So;0;ON;;;;;N;;;;; 2ED1;CJK RADICAL LONG ONE;So;0;ON;;;;;N;;;;; 2ED2;CJK RADICAL LONG TWO;So;0;ON;;;;;N;;;;; 2ED3;CJK RADICAL C-SIMPLIFIED LONG;So;0;ON;;;;;N;;;;; 2ED4;CJK RADICAL C-SIMPLIFIED GATE;So;0;ON;;;;;N;;;;; 2ED5;CJK RADICAL MOUND ONE;So;0;ON;;;;;N;;;;; 2ED6;CJK RADICAL MOUND TWO;So;0;ON;;;;;N;;;;; 2ED7;CJK RADICAL RAIN;So;0;ON;;;;;N;;;;; 2ED8;CJK RADICAL BLUE;So;0;ON;;;;;N;;;;; 2ED9;CJK RADICAL C-SIMPLIFIED TANNED LEATHER;So;0;ON;;;;;N;;;;; 2EDA;CJK RADICAL C-SIMPLIFIED LEAF;So;0;ON;;;;;N;;;;; 2EDB;CJK RADICAL C-SIMPLIFIED WIND;So;0;ON;;;;;N;;;;; 2EDC;CJK RADICAL C-SIMPLIFIED FLY;So;0;ON;;;;;N;;;;; 2EDD;CJK RADICAL EAT ONE;So;0;ON;;;;;N;;;;; 2EDE;CJK RADICAL EAT TWO;So;0;ON;;;;;N;;;;; 2EDF;CJK RADICAL EAT THREE;So;0;ON;;;;;N;;;;; 2EE0;CJK RADICAL C-SIMPLIFIED EAT;So;0;ON;;;;;N;;;;; 2EE1;CJK RADICAL HEAD;So;0;ON;;;;;N;;;;; 2EE2;CJK RADICAL C-SIMPLIFIED HORSE;So;0;ON;;;;;N;;;;; 2EE3;CJK RADICAL BONE;So;0;ON;;;;;N;;;;; 2EE4;CJK RADICAL GHOST;So;0;ON;;;;;N;;;;; 2EE5;CJK RADICAL C-SIMPLIFIED FISH;So;0;ON;;;;;N;;;;; 2EE6;CJK RADICAL C-SIMPLIFIED BIRD;So;0;ON;;;;;N;;;;; 2EE7;CJK RADICAL C-SIMPLIFIED SALT;So;0;ON;;;;;N;;;;; 2EE8;CJK RADICAL SIMPLIFIED WHEAT;So;0;ON;;;;;N;;;;; 2EE9;CJK RADICAL SIMPLIFIED YELLOW;So;0;ON;;;;;N;;;;; 2EEA;CJK RADICAL C-SIMPLIFIED FROG;So;0;ON;;;;;N;;;;; 2EEB;CJK RADICAL J-SIMPLIFIED EVEN;So;0;ON;;;;;N;;;;; 2EEC;CJK RADICAL C-SIMPLIFIED EVEN;So;0;ON;;;;;N;;;;; 2EED;CJK RADICAL J-SIMPLIFIED TOOTH;So;0;ON;;;;;N;;;;; 2EEE;CJK RADICAL C-SIMPLIFIED TOOTH;So;0;ON;;;;;N;;;;; 2EEF;CJK RADICAL J-SIMPLIFIED DRAGON;So;0;ON;;;;;N;;;;; 2EF0;CJK RADICAL C-SIMPLIFIED DRAGON;So;0;ON;;;;;N;;;;; 2EF1;CJK RADICAL TURTLE;So;0;ON;;;;;N;;;;; 2EF2;CJK RADICAL J-SIMPLIFIED TURTLE;So;0;ON;;;;;N;;;;; 2EF3;CJK RADICAL C-SIMPLIFIED TURTLE;So;0;ON;<compat> 9F9F;;;;N;;;;; 2F00;KANGXI RADICAL ONE;So;0;ON;<compat> 4E00;;;;N;;;;; 2F01;KANGXI RADICAL LINE;So;0;ON;<compat> 4E28;;;;N;;;;; 2F02;KANGXI RADICAL DOT;So;0;ON;<compat> 4E36;;;;N;;;;; 2F03;KANGXI RADICAL SLASH;So;0;ON;<compat> 4E3F;;;;N;;;;; 2F04;KANGXI RADICAL SECOND;So;0;ON;<compat> 4E59;;;;N;;;;; 2F05;KANGXI RADICAL HOOK;So;0;ON;<compat> 4E85;;;;N;;;;; 2F06;KANGXI RADICAL TWO;So;0;ON;<compat> 4E8C;;;;N;;;;; 2F07;KANGXI RADICAL LID;So;0;ON;<compat> 4EA0;;;;N;;;;; 2F08;KANGXI RADICAL MAN;So;0;ON;<compat> 4EBA;;;;N;;;;; 2F09;KANGXI RADICAL LEGS;So;0;ON;<compat> 513F;;;;N;;;;; 2F0A;KANGXI RADICAL ENTER;So;0;ON;<compat> 5165;;;;N;;;;; 2F0B;KANGXI RADICAL EIGHT;So;0;ON;<compat> 516B;;;;N;;;;; 2F0C;KANGXI RADICAL DOWN BOX;So;0;ON;<compat> 5182;;;;N;;;;; 2F0D;KANGXI RADICAL COVER;So;0;ON;<compat> 5196;;;;N;;;;; 2F0E;KANGXI RADICAL ICE;So;0;ON;<compat> 51AB;;;;N;;;;; 2F0F;KANGXI RADICAL TABLE;So;0;ON;<compat> 51E0;;;;N;;;;; 2F10;KANGXI RADICAL OPEN BOX;So;0;ON;<compat> 51F5;;;;N;;;;; 2F11;KANGXI RADICAL KNIFE;So;0;ON;<compat> 5200;;;;N;;;;; 2F12;KANGXI RADICAL POWER;So;0;ON;<compat> 529B;;;;N;;;;; 2F13;KANGXI RADICAL WRAP;So;0;ON;<compat> 52F9;;;;N;;;;; 2F14;KANGXI RADICAL SPOON;So;0;ON;<compat> 5315;;;;N;;;;; 2F15;KANGXI RADICAL RIGHT OPEN BOX;So;0;ON;<compat> 531A;;;;N;;;;; 2F16;KANGXI RADICAL HIDING ENCLOSURE;So;0;ON;<compat> 5338;;;;N;;;;; 2F17;KANGXI RADICAL TEN;So;0;ON;<compat> 5341;;;;N;;;;; 2F18;KANGXI RADICAL DIVINATION;So;0;ON;<compat> 535C;;;;N;;;;; 2F19;KANGXI RADICAL SEAL;So;0;ON;<compat> 5369;;;;N;;;;; 2F1A;KANGXI RADICAL CLIFF;So;0;ON;<compat> 5382;;;;N;;;;; 2F1B;KANGXI RADICAL PRIVATE;So;0;ON;<compat> 53B6;;;;N;;;;; 2F1C;KANGXI RADICAL AGAIN;So;0;ON;<compat> 53C8;;;;N;;;;; 2F1D;KANGXI RADICAL MOUTH;So;0;ON;<compat> 53E3;;;;N;;;;; 2F1E;KANGXI RADICAL ENCLOSURE;So;0;ON;<compat> 56D7;;;;N;;;;; 2F1F;KANGXI RADICAL EARTH;So;0;ON;<compat> 571F;;;;N;;;;; 2F20;KANGXI RADICAL SCHOLAR;So;0;ON;<compat> 58EB;;;;N;;;;; 2F21;KANGXI RADICAL GO;So;0;ON;<compat> 5902;;;;N;;;;; 2F22;KANGXI RADICAL GO SLOWLY;So;0;ON;<compat> 590A;;;;N;;;;; 2F23;KANGXI RADICAL EVENING;So;0;ON;<compat> 5915;;;;N;;;;; 2F24;KANGXI RADICAL BIG;So;0;ON;<compat> 5927;;;;N;;;;; 2F25;KANGXI RADICAL WOMAN;So;0;ON;<compat> 5973;;;;N;;;;; 2F26;KANGXI RADICAL CHILD;So;0;ON;<compat> 5B50;;;;N;;;;; 2F27;KANGXI RADICAL ROOF;So;0;ON;<compat> 5B80;;;;N;;;;; 2F28;KANGXI RADICAL INCH;So;0;ON;<compat> 5BF8;;;;N;;;;; 2F29;KANGXI RADICAL SMALL;So;0;ON;<compat> 5C0F;;;;N;;;;; 2F2A;KANGXI RADICAL LAME;So;0;ON;<compat> 5C22;;;;N;;;;; 2F2B;KANGXI RADICAL CORPSE;So;0;ON;<compat> 5C38;;;;N;;;;; 2F2C;KANGXI RADICAL SPROUT;So;0;ON;<compat> 5C6E;;;;N;;;;; 2F2D;KANGXI RADICAL MOUNTAIN;So;0;ON;<compat> 5C71;;;;N;;;;; 2F2E;KANGXI RADICAL RIVER;So;0;ON;<compat> 5DDB;;;;N;;;;; 2F2F;KANGXI RADICAL WORK;So;0;ON;<compat> 5DE5;;;;N;;;;; 2F30;KANGXI RADICAL ONESELF;So;0;ON;<compat> 5DF1;;;;N;;;;; 2F31;KANGXI RADICAL TURBAN;So;0;ON;<compat> 5DFE;;;;N;;;;; 2F32;KANGXI RADICAL DRY;So;0;ON;<compat> 5E72;;;;N;;;;; 2F33;KANGXI RADICAL SHORT THREAD;So;0;ON;<compat> 5E7A;;;;N;;;;; 2F34;KANGXI RADICAL DOTTED CLIFF;So;0;ON;<compat> 5E7F;;;;N;;;;; 2F35;KANGXI RADICAL LONG STRIDE;So;0;ON;<compat> 5EF4;;;;N;;;;; 2F36;KANGXI RADICAL TWO HANDS;So;0;ON;<compat> 5EFE;;;;N;;;;; 2F37;KANGXI RADICAL SHOOT;So;0;ON;<compat> 5F0B;;;;N;;;;; 2F38;KANGXI RADICAL BOW;So;0;ON;<compat> 5F13;;;;N;;;;; 2F39;KANGXI RADICAL SNOUT;So;0;ON;<compat> 5F50;;;;N;;;;; 2F3A;KANGXI RADICAL BRISTLE;So;0;ON;<compat> 5F61;;;;N;;;;; 2F3B;KANGXI RADICAL STEP;So;0;ON;<compat> 5F73;;;;N;;;;; 2F3C;KANGXI RADICAL HEART;So;0;ON;<compat> 5FC3;;;;N;;;;; 2F3D;KANGXI RADICAL HALBERD;So;0;ON;<compat> 6208;;;;N;;;;; 2F3E;KANGXI RADICAL DOOR;So;0;ON;<compat> 6236;;;;N;;;;; 2F3F;KANGXI RADICAL HAND;So;0;ON;<compat> 624B;;;;N;;;;; 2F40;KANGXI RADICAL BRANCH;So;0;ON;<compat> 652F;;;;N;;;;; 2F41;KANGXI RADICAL RAP;So;0;ON;<compat> 6534;;;;N;;;;; 2F42;KANGXI RADICAL SCRIPT;So;0;ON;<compat> 6587;;;;N;;;;; 2F43;KANGXI RADICAL DIPPER;So;0;ON;<compat> 6597;;;;N;;;;; 2F44;KANGXI RADICAL AXE;So;0;ON;<compat> 65A4;;;;N;;;;; 2F45;KANGXI RADICAL SQUARE;So;0;ON;<compat> 65B9;;;;N;;;;; 2F46;KANGXI RADICAL NOT;So;0;ON;<compat> 65E0;;;;N;;;;; 2F47;KANGXI RADICAL SUN;So;0;ON;<compat> 65E5;;;;N;;;;; 2F48;KANGXI RADICAL SAY;So;0;ON;<compat> 66F0;;;;N;;;;; 2F49;KANGXI RADICAL MOON;So;0;ON;<compat> 6708;;;;N;;;;; 2F4A;KANGXI RADICAL TREE;So;0;ON;<compat> 6728;;;;N;;;;; 2F4B;KANGXI RADICAL LACK;So;0;ON;<compat> 6B20;;;;N;;;;; 2F4C;KANGXI RADICAL STOP;So;0;ON;<compat> 6B62;;;;N;;;;; 2F4D;KANGXI RADICAL DEATH;So;0;ON;<compat> 6B79;;;;N;;;;; 2F4E;KANGXI RADICAL WEAPON;So;0;ON;<compat> 6BB3;;;;N;;;;; 2F4F;KANGXI RADICAL DO NOT;So;0;ON;<compat> 6BCB;;;;N;;;;; 2F50;KANGXI RADICAL COMPARE;So;0;ON;<compat> 6BD4;;;;N;;;;; 2F51;KANGXI RADICAL FUR;So;0;ON;<compat> 6BDB;;;;N;;;;; 2F52;KANGXI RADICAL CLAN;So;0;ON;<compat> 6C0F;;;;N;;;;; 2F53;KANGXI RADICAL STEAM;So;0;ON;<compat> 6C14;;;;N;;;;; 2F54;KANGXI RADICAL WATER;So;0;ON;<compat> 6C34;;;;N;;;;; 2F55;KANGXI RADICAL FIRE;So;0;ON;<compat> 706B;;;;N;;;;; 2F56;KANGXI RADICAL CLAW;So;0;ON;<compat> 722A;;;;N;;;;; 2F57;KANGXI RADICAL FATHER;So;0;ON;<compat> 7236;;;;N;;;;; 2F58;KANGXI RADICAL DOUBLE X;So;0;ON;<compat> 723B;;;;N;;;;; 2F59;KANGXI RADICAL HALF TREE TRUNK;So;0;ON;<compat> 723F;;;;N;;;;; 2F5A;KANGXI RADICAL SLICE;So;0;ON;<compat> 7247;;;;N;;;;; 2F5B;KANGXI RADICAL FANG;So;0;ON;<compat> 7259;;;;N;;;;; 2F5C;KANGXI RADICAL COW;So;0;ON;<compat> 725B;;;;N;;;;; 2F5D;KANGXI RADICAL DOG;So;0;ON;<compat> 72AC;;;;N;;;;; 2F5E;KANGXI RADICAL PROFOUND;So;0;ON;<compat> 7384;;;;N;;;;; 2F5F;KANGXI RADICAL JADE;So;0;ON;<compat> 7389;;;;N;;;;; 2F60;KANGXI RADICAL MELON;So;0;ON;<compat> 74DC;;;;N;;;;; 2F61;KANGXI RADICAL TILE;So;0;ON;<compat> 74E6;;;;N;;;;; 2F62;KANGXI RADICAL SWEET;So;0;ON;<compat> 7518;;;;N;;;;; 2F63;KANGXI RADICAL LIFE;So;0;ON;<compat> 751F;;;;N;;;;; 2F64;KANGXI RADICAL USE;So;0;ON;<compat> 7528;;;;N;;;;; 2F65;KANGXI RADICAL FIELD;So;0;ON;<compat> 7530;;;;N;;;;; 2F66;KANGXI RADICAL BOLT OF CLOTH;So;0;ON;<compat> 758B;;;;N;;;;; 2F67;KANGXI RADICAL SICKNESS;So;0;ON;<compat> 7592;;;;N;;;;; 2F68;KANGXI RADICAL DOTTED TENT;So;0;ON;<compat> 7676;;;;N;;;;; 2F69;KANGXI RADICAL WHITE;So;0;ON;<compat> 767D;;;;N;;;;; 2F6A;KANGXI RADICAL SKIN;So;0;ON;<compat> 76AE;;;;N;;;;; 2F6B;KANGXI RADICAL DISH;So;0;ON;<compat> 76BF;;;;N;;;;; 2F6C;KANGXI RADICAL EYE;So;0;ON;<compat> 76EE;;;;N;;;;; 2F6D;KANGXI RADICAL SPEAR;So;0;ON;<compat> 77DB;;;;N;;;;; 2F6E;KANGXI RADICAL ARROW;So;0;ON;<compat> 77E2;;;;N;;;;; 2F6F;KANGXI RADICAL STONE;So;0;ON;<compat> 77F3;;;;N;;;;; 2F70;KANGXI RADICAL SPIRIT;So;0;ON;<compat> 793A;;;;N;;;;; 2F71;KANGXI RADICAL TRACK;So;0;ON;<compat> 79B8;;;;N;;;;; 2F72;KANGXI RADICAL GRAIN;So;0;ON;<compat> 79BE;;;;N;;;;; 2F73;KANGXI RADICAL CAVE;So;0;ON;<compat> 7A74;;;;N;;;;; 2F74;KANGXI RADICAL STAND;So;0;ON;<compat> 7ACB;;;;N;;;;; 2F75;KANGXI RADICAL BAMBOO;So;0;ON;<compat> 7AF9;;;;N;;;;; 2F76;KANGXI RADICAL RICE;So;0;ON;<compat> 7C73;;;;N;;;;; 2F77;KANGXI RADICAL SILK;So;0;ON;<compat> 7CF8;;;;N;;;;; 2F78;KANGXI RADICAL JAR;So;0;ON;<compat> 7F36;;;;N;;;;; 2F79;KANGXI RADICAL NET;So;0;ON;<compat> 7F51;;;;N;;;;; 2F7A;KANGXI RADICAL SHEEP;So;0;ON;<compat> 7F8A;;;;N;;;;; 2F7B;KANGXI RADICAL FEATHER;So;0;ON;<compat> 7FBD;;;;N;;;;; 2F7C;KANGXI RADICAL OLD;So;0;ON;<compat> 8001;;;;N;;;;; 2F7D;KANGXI RADICAL AND;So;0;ON;<compat> 800C;;;;N;;;;; 2F7E;KANGXI RADICAL PLOW;So;0;ON;<compat> 8012;;;;N;;;;; 2F7F;KANGXI RADICAL EAR;So;0;ON;<compat> 8033;;;;N;;;;; 2F80;KANGXI RADICAL BRUSH;So;0;ON;<compat> 807F;;;;N;;;;; 2F81;KANGXI RADICAL MEAT;So;0;ON;<compat> 8089;;;;N;;;;; 2F82;KANGXI RADICAL MINISTER;So;0;ON;<compat> 81E3;;;;N;;;;; 2F83;KANGXI RADICAL SELF;So;0;ON;<compat> 81EA;;;;N;;;;; 2F84;KANGXI RADICAL ARRIVE;So;0;ON;<compat> 81F3;;;;N;;;;; 2F85;KANGXI RADICAL MORTAR;So;0;ON;<compat> 81FC;;;;N;;;;; 2F86;KANGXI RADICAL TONGUE;So;0;ON;<compat> 820C;;;;N;;;;; 2F87;KANGXI RADICAL OPPOSE;So;0;ON;<compat> 821B;;;;N;;;;; 2F88;KANGXI RADICAL BOAT;So;0;ON;<compat> 821F;;;;N;;;;; 2F89;KANGXI RADICAL STOPPING;So;0;ON;<compat> 826E;;;;N;;;;; 2F8A;KANGXI RADICAL COLOR;So;0;ON;<compat> 8272;;;;N;;;;; 2F8B;KANGXI RADICAL GRASS;So;0;ON;<compat> 8278;;;;N;;;;; 2F8C;KANGXI RADICAL TIGER;So;0;ON;<compat> 864D;;;;N;;;;; 2F8D;KANGXI RADICAL INSECT;So;0;ON;<compat> 866B;;;;N;;;;; 2F8E;KANGXI RADICAL BLOOD;So;0;ON;<compat> 8840;;;;N;;;;; 2F8F;KANGXI RADICAL WALK ENCLOSURE;So;0;ON;<compat> 884C;;;;N;;;;; 2F90;KANGXI RADICAL CLOTHES;So;0;ON;<compat> 8863;;;;N;;;;; 2F91;KANGXI RADICAL WEST;So;0;ON;<compat> 897E;;;;N;;;;; 2F92;KANGXI RADICAL SEE;So;0;ON;<compat> 898B;;;;N;;;;; 2F93;KANGXI RADICAL HORN;So;0;ON;<compat> 89D2;;;;N;;;;; 2F94;KANGXI RADICAL SPEECH;So;0;ON;<compat> 8A00;;;;N;;;;; 2F95;KANGXI RADICAL VALLEY;So;0;ON;<compat> 8C37;;;;N;;;;; 2F96;KANGXI RADICAL BEAN;So;0;ON;<compat> 8C46;;;;N;;;;; 2F97;KANGXI RADICAL PIG;So;0;ON;<compat> 8C55;;;;N;;;;; 2F98;KANGXI RADICAL BADGER;So;0;ON;<compat> 8C78;;;;N;;;;; 2F99;KANGXI RADICAL SHELL;So;0;ON;<compat> 8C9D;;;;N;;;;; 2F9A;KANGXI RADICAL RED;So;0;ON;<compat> 8D64;;;;N;;;;; 2F9B;KANGXI RADICAL RUN;So;0;ON;<compat> 8D70;;;;N;;;;; 2F9C;KANGXI RADICAL FOOT;So;0;ON;<compat> 8DB3;;;;N;;;;; 2F9D;KANGXI RADICAL BODY;So;0;ON;<compat> 8EAB;;;;N;;;;; 2F9E;KANGXI RADICAL CART;So;0;ON;<compat> 8ECA;;;;N;;;;; 2F9F;KANGXI RADICAL BITTER;So;0;ON;<compat> 8F9B;;;;N;;;;; 2FA0;KANGXI RADICAL MORNING;So;0;ON;<compat> 8FB0;;;;N;;;;; 2FA1;KANGXI RADICAL WALK;So;0;ON;<compat> 8FB5;;;;N;;;;; 2FA2;KANGXI RADICAL CITY;So;0;ON;<compat> 9091;;;;N;;;;; 2FA3;KANGXI RADICAL WINE;So;0;ON;<compat> 9149;;;;N;;;;; 2FA4;KANGXI RADICAL DISTINGUISH;So;0;ON;<compat> 91C6;;;;N;;;;; 2FA5;KANGXI RADICAL VILLAGE;So;0;ON;<compat> 91CC;;;;N;;;;; 2FA6;KANGXI RADICAL GOLD;So;0;ON;<compat> 91D1;;;;N;;;;; 2FA7;KANGXI RADICAL LONG;So;0;ON;<compat> 9577;;;;N;;;;; 2FA8;KANGXI RADICAL GATE;So;0;ON;<compat> 9580;;;;N;;;;; 2FA9;KANGXI RADICAL MOUND;So;0;ON;<compat> 961C;;;;N;;;;; 2FAA;KANGXI RADICAL SLAVE;So;0;ON;<compat> 96B6;;;;N;;;;; 2FAB;KANGXI RADICAL SHORT TAILED BIRD;So;0;ON;<compat> 96B9;;;;N;;;;; 2FAC;KANGXI RADICAL RAIN;So;0;ON;<compat> 96E8;;;;N;;;;; 2FAD;KANGXI RADICAL BLUE;So;0;ON;<compat> 9751;;;;N;;;;; 2FAE;KANGXI RADICAL WRONG;So;0;ON;<compat> 975E;;;;N;;;;; 2FAF;KANGXI RADICAL FACE;So;0;ON;<compat> 9762;;;;N;;;;; 2FB0;KANGXI RADICAL LEATHER;So;0;ON;<compat> 9769;;;;N;;;;; 2FB1;KANGXI RADICAL TANNED LEATHER;So;0;ON;<compat> 97CB;;;;N;;;;; 2FB2;KANGXI RADICAL LEEK;So;0;ON;<compat> 97ED;;;;N;;;;; 2FB3;KANGXI RADICAL SOUND;So;0;ON;<compat> 97F3;;;;N;;;;; 2FB4;KANGXI RADICAL LEAF;So;0;ON;<compat> 9801;;;;N;;;;; 2FB5;KANGXI RADICAL WIND;So;0;ON;<compat> 98A8;;;;N;;;;; 2FB6;KANGXI RADICAL FLY;So;0;ON;<compat> 98DB;;;;N;;;;; 2FB7;KANGXI RADICAL EAT;So;0;ON;<compat> 98DF;;;;N;;;;; 2FB8;KANGXI RADICAL HEAD;So;0;ON;<compat> 9996;;;;N;;;;; 2FB9;KANGXI RADICAL FRAGRANT;So;0;ON;<compat> 9999;;;;N;;;;; 2FBA;KANGXI RADICAL HORSE;So;0;ON;<compat> 99AC;;;;N;;;;; 2FBB;KANGXI RADICAL BONE;So;0;ON;<compat> 9AA8;;;;N;;;;; 2FBC;KANGXI RADICAL TALL;So;0;ON;<compat> 9AD8;;;;N;;;;; 2FBD;KANGXI RADICAL HAIR;So;0;ON;<compat> 9ADF;;;;N;;;;; 2FBE;KANGXI RADICAL FIGHT;So;0;ON;<compat> 9B25;;;;N;;;;; 2FBF;KANGXI RADICAL SACRIFICIAL WINE;So;0;ON;<compat> 9B2F;;;;N;;;;; 2FC0;KANGXI RADICAL CAULDRON;So;0;ON;<compat> 9B32;;;;N;;;;; 2FC1;KANGXI RADICAL GHOST;So;0;ON;<compat> 9B3C;;;;N;;;;; 2FC2;KANGXI RADICAL FISH;So;0;ON;<compat> 9B5A;;;;N;;;;; 2FC3;KANGXI RADICAL BIRD;So;0;ON;<compat> 9CE5;;;;N;;;;; 2FC4;KANGXI RADICAL SALT;So;0;ON;<compat> 9E75;;;;N;;;;; 2FC5;KANGXI RADICAL DEER;So;0;ON;<compat> 9E7F;;;;N;;;;; 2FC6;KANGXI RADICAL WHEAT;So;0;ON;<compat> 9EA5;;;;N;;;;; 2FC7;KANGXI RADICAL HEMP;So;0;ON;<compat> 9EBB;;;;N;;;;; 2FC8;KANGXI RADICAL YELLOW;So;0;ON;<compat> 9EC3;;;;N;;;;; 2FC9;KANGXI RADICAL MILLET;So;0;ON;<compat> 9ECD;;;;N;;;;; 2FCA;KANGXI RADICAL BLACK;So;0;ON;<compat> 9ED1;;;;N;;;;; 2FCB;KANGXI RADICAL EMBROIDERY;So;0;ON;<compat> 9EF9;;;;N;;;;; 2FCC;KANGXI RADICAL FROG;So;0;ON;<compat> 9EFD;;;;N;;;;; 2FCD;KANGXI RADICAL TRIPOD;So;0;ON;<compat> 9F0E;;;;N;;;;; 2FCE;KANGXI RADICAL DRUM;So;0;ON;<compat> 9F13;;;;N;;;;; 2FCF;KANGXI RADICAL RAT;So;0;ON;<compat> 9F20;;;;N;;;;; 2FD0;KANGXI RADICAL NOSE;So;0;ON;<compat> 9F3B;;;;N;;;;; 2FD1;KANGXI RADICAL EVEN;So;0;ON;<compat> 9F4A;;;;N;;;;; 2FD2;KANGXI RADICAL TOOTH;So;0;ON;<compat> 9F52;;;;N;;;;; 2FD3;KANGXI RADICAL DRAGON;So;0;ON;<compat> 9F8D;;;;N;;;;; 2FD4;KANGXI RADICAL TURTLE;So;0;ON;<compat> 9F9C;;;;N;;;;; 2FD5;KANGXI RADICAL FLUTE;So;0;ON;<compat> 9FA0;;;;N;;;;; 2FF0;IDEOGRAPHIC DESCRIPTION CHARACTER LEFT TO RIGHT;So;0;ON;;;;;N;;;;; 2FF1;IDEOGRAPHIC DESCRIPTION CHARACTER ABOVE TO BELOW;So;0;ON;;;;;N;;;;; 2FF2;IDEOGRAPHIC DESCRIPTION CHARACTER LEFT TO MIDDLE AND RIGHT;So;0;ON;;;;;N;;;;; 2FF3;IDEOGRAPHIC DESCRIPTION CHARACTER ABOVE TO MIDDLE AND BELOW;So;0;ON;;;;;N;;;;; 2FF4;IDEOGRAPHIC DESCRIPTION CHARACTER FULL SURROUND;So;0;ON;;;;;N;;;;; 2FF5;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM ABOVE;So;0;ON;;;;;N;;;;; 2FF6;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM BELOW;So;0;ON;;;;;N;;;;; 2FF7;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM LEFT;So;0;ON;;;;;N;;;;; 2FF8;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM UPPER LEFT;So;0;ON;;;;;N;;;;; 2FF9;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM UPPER RIGHT;So;0;ON;;;;;N;;;;; 2FFA;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM LOWER LEFT;So;0;ON;;;;;N;;;;; 2FFB;IDEOGRAPHIC DESCRIPTION CHARACTER OVERLAID;So;0;ON;;;;;N;;;;; 3000;IDEOGRAPHIC SPACE;Zs;0;WS;<wide> 0020;;;;N;;;;; 3001;IDEOGRAPHIC COMMA;Po;0;ON;;;;;N;;;;; 3002;IDEOGRAPHIC FULL STOP;Po;0;ON;;;;;N;IDEOGRAPHIC PERIOD;;;; 3003;DITTO MARK;Po;0;ON;;;;;N;;;;; 3004;JAPANESE INDUSTRIAL STANDARD SYMBOL;So;0;ON;;;;;N;;;;; 3005;IDEOGRAPHIC ITERATION MARK;Lm;0;L;;;;;N;;;;; 3006;IDEOGRAPHIC CLOSING MARK;Lo;0;L;;;;;N;;;;; 3007;IDEOGRAPHIC NUMBER ZERO;Nl;0;L;;;;0;N;;;;; 3008;LEFT ANGLE BRACKET;Ps;0;ON;;;;;Y;OPENING ANGLE BRACKET;;;; 3009;RIGHT ANGLE BRACKET;Pe;0;ON;;;;;Y;CLOSING ANGLE BRACKET;;;; 300A;LEFT DOUBLE ANGLE BRACKET;Ps;0;ON;;;;;Y;OPENING DOUBLE ANGLE BRACKET;;;; 300B;RIGHT DOUBLE ANGLE BRACKET;Pe;0;ON;;;;;Y;CLOSING DOUBLE ANGLE BRACKET;;;; 300C;LEFT CORNER BRACKET;Ps;0;ON;;;;;Y;OPENING CORNER BRACKET;;;; 300D;RIGHT CORNER BRACKET;Pe;0;ON;;;;;Y;CLOSING CORNER BRACKET;;;; 300E;LEFT WHITE CORNER BRACKET;Ps;0;ON;;;;;Y;OPENING WHITE CORNER BRACKET;;;; 300F;RIGHT WHITE CORNER BRACKET;Pe;0;ON;;;;;Y;CLOSING WHITE CORNER BRACKET;;;; 3010;LEFT BLACK LENTICULAR BRACKET;Ps;0;ON;;;;;Y;OPENING BLACK LENTICULAR BRACKET;;;; 3011;RIGHT BLACK LENTICULAR BRACKET;Pe;0;ON;;;;;Y;CLOSING BLACK LENTICULAR BRACKET;;;; 3012;POSTAL MARK;So;0;ON;;;;;N;;;;; 3013;GETA MARK;So;0;ON;;;;;N;;;;; 3014;LEFT TORTOISE SHELL BRACKET;Ps;0;ON;;;;;Y;OPENING TORTOISE SHELL BRACKET;;;; 3015;RIGHT TORTOISE SHELL BRACKET;Pe;0;ON;;;;;Y;CLOSING TORTOISE SHELL BRACKET;;;; 3016;LEFT WHITE LENTICULAR BRACKET;Ps;0;ON;;;;;Y;OPENING WHITE LENTICULAR BRACKET;;;; 3017;RIGHT WHITE LENTICULAR BRACKET;Pe;0;ON;;;;;Y;CLOSING WHITE LENTICULAR BRACKET;;;; 3018;LEFT WHITE TORTOISE SHELL BRACKET;Ps;0;ON;;;;;Y;OPENING WHITE TORTOISE SHELL BRACKET;;;; 3019;RIGHT WHITE TORTOISE SHELL BRACKET;Pe;0;ON;;;;;Y;CLOSING WHITE TORTOISE SHELL BRACKET;;;; 301A;LEFT WHITE SQUARE BRACKET;Ps;0;ON;;;;;Y;OPENING WHITE SQUARE BRACKET;;;; 301B;RIGHT WHITE SQUARE BRACKET;Pe;0;ON;;;;;Y;CLOSING WHITE SQUARE BRACKET;;;; 301C;WAVE DASH;Pd;0;ON;;;;;N;;;;; 301D;REVERSED DOUBLE PRIME QUOTATION MARK;Ps;0;ON;;;;;N;;;;; 301E;DOUBLE PRIME QUOTATION MARK;Pe;0;ON;;;;;N;;;;; 301F;LOW DOUBLE PRIME QUOTATION MARK;Pe;0;ON;;;;;N;;;;; 3020;POSTAL MARK FACE;So;0;ON;;;;;N;;;;; 3021;HANGZHOU NUMERAL ONE;Nl;0;L;;;;1;N;;;;; 3022;HANGZHOU NUMERAL TWO;Nl;0;L;;;;2;N;;;;; 3023;HANGZHOU NUMERAL THREE;Nl;0;L;;;;3;N;;;;; 3024;HANGZHOU NUMERAL FOUR;Nl;0;L;;;;4;N;;;;; 3025;HANGZHOU NUMERAL FIVE;Nl;0;L;;;;5;N;;;;; 3026;HANGZHOU NUMERAL SIX;Nl;0;L;;;;6;N;;;;; 3027;HANGZHOU NUMERAL SEVEN;Nl;0;L;;;;7;N;;;;; 3028;HANGZHOU NUMERAL EIGHT;Nl;0;L;;;;8;N;;;;; 3029;HANGZHOU NUMERAL NINE;Nl;0;L;;;;9;N;;;;; 302A;IDEOGRAPHIC LEVEL TONE MARK;Mn;218;NSM;;;;;N;;;;; 302B;IDEOGRAPHIC RISING TONE MARK;Mn;228;NSM;;;;;N;;;;; 302C;IDEOGRAPHIC DEPARTING TONE MARK;Mn;232;NSM;;;;;N;;;;; 302D;IDEOGRAPHIC ENTERING TONE MARK;Mn;222;NSM;;;;;N;;;;; 302E;HANGUL SINGLE DOT TONE MARK;Mc;224;L;;;;;N;;;;; 302F;HANGUL DOUBLE DOT TONE MARK;Mc;224;L;;;;;N;;;;; 3030;WAVY DASH;Pd;0;ON;;;;;N;;;;; 3031;VERTICAL KANA REPEAT MARK;Lm;0;L;;;;;N;;;;; 3032;VERTICAL KANA REPEAT WITH VOICED SOUND MARK;Lm;0;L;;;;;N;;;;; 3033;VERTICAL KANA REPEAT MARK UPPER HALF;Lm;0;L;;;;;N;;;;; 3034;VERTICAL KANA REPEAT WITH VOICED SOUND MARK UPPER HALF;Lm;0;L;;;;;N;;;;; 3035;VERTICAL KANA REPEAT MARK LOWER HALF;Lm;0;L;;;;;N;;;;; 3036;CIRCLED POSTAL MARK;So;0;ON;<compat> 3012;;;;N;;;;; 3037;IDEOGRAPHIC TELEGRAPH LINE FEED SEPARATOR SYMBOL;So;0;ON;;;;;N;;;;; 3038;HANGZHOU NUMERAL TEN;Nl;0;L;<compat> 5341;;;10;N;;;;; 3039;HANGZHOU NUMERAL TWENTY;Nl;0;L;<compat> 5344;;;20;N;;;;; 303A;HANGZHOU NUMERAL THIRTY;Nl;0;L;<compat> 5345;;;30;N;;;;; 303B;VERTICAL IDEOGRAPHIC ITERATION MARK;Lm;0;L;;;;;N;;;;; 303C;MASU MARK;Lo;0;L;;;;;N;;;;; 303D;PART ALTERNATION MARK;Po;0;ON;;;;;N;;;;; 303E;IDEOGRAPHIC VARIATION INDICATOR;So;0;ON;;;;;N;;;;; 303F;IDEOGRAPHIC HALF FILL SPACE;So;0;ON;;;;;N;;;;; 3041;HIRAGANA LETTER SMALL A;Lo;0;L;;;;;N;;;;; 3042;HIRAGANA LETTER A;Lo;0;L;;;;;N;;;;; 3043;HIRAGANA LETTER SMALL I;Lo;0;L;;;;;N;;;;; 3044;HIRAGANA LETTER I;Lo;0;L;;;;;N;;;;; 3045;HIRAGANA LETTER SMALL U;Lo;0;L;;;;;N;;;;; 3046;HIRAGANA LETTER U;Lo;0;L;;;;;N;;;;; 3047;HIRAGANA LETTER SMALL E;Lo;0;L;;;;;N;;;;; 3048;HIRAGANA LETTER E;Lo;0;L;;;;;N;;;;; 3049;HIRAGANA LETTER SMALL O;Lo;0;L;;;;;N;;;;; 304A;HIRAGANA LETTER O;Lo;0;L;;;;;N;;;;; 304B;HIRAGANA LETTER KA;Lo;0;L;;;;;N;;;;; 304C;HIRAGANA LETTER GA;Lo;0;L;304B 3099;;;;N;;;;; 304D;HIRAGANA LETTER KI;Lo;0;L;;;;;N;;;;; 304E;HIRAGANA LETTER GI;Lo;0;L;304D 3099;;;;N;;;;; 304F;HIRAGANA LETTER KU;Lo;0;L;;;;;N;;;;; 3050;HIRAGANA LETTER GU;Lo;0;L;304F 3099;;;;N;;;;; 3051;HIRAGANA LETTER KE;Lo;0;L;;;;;N;;;;; 3052;HIRAGANA LETTER GE;Lo;0;L;3051 3099;;;;N;;;;; 3053;HIRAGANA LETTER KO;Lo;0;L;;;;;N;;;;; 3054;HIRAGANA LETTER GO;Lo;0;L;3053 3099;;;;N;;;;; 3055;HIRAGANA LETTER SA;Lo;0;L;;;;;N;;;;; 3056;HIRAGANA LETTER ZA;Lo;0;L;3055 3099;;;;N;;;;; 3057;HIRAGANA LETTER SI;Lo;0;L;;;;;N;;;;; 3058;HIRAGANA LETTER ZI;Lo;0;L;3057 3099;;;;N;;;;; 3059;HIRAGANA LETTER SU;Lo;0;L;;;;;N;;;;; 305A;HIRAGANA LETTER ZU;Lo;0;L;3059 3099;;;;N;;;;; 305B;HIRAGANA LETTER SE;Lo;0;L;;;;;N;;;;; 305C;HIRAGANA LETTER ZE;Lo;0;L;305B 3099;;;;N;;;;; 305D;HIRAGANA LETTER SO;Lo;0;L;;;;;N;;;;; 305E;HIRAGANA LETTER ZO;Lo;0;L;305D 3099;;;;N;;;;; 305F;HIRAGANA LETTER TA;Lo;0;L;;;;;N;;;;; 3060;HIRAGANA LETTER DA;Lo;0;L;305F 3099;;;;N;;;;; 3061;HIRAGANA LETTER TI;Lo;0;L;;;;;N;;;;; 3062;HIRAGANA LETTER DI;Lo;0;L;3061 3099;;;;N;;;;; 3063;HIRAGANA LETTER SMALL TU;Lo;0;L;;;;;N;;;;; 3064;HIRAGANA LETTER TU;Lo;0;L;;;;;N;;;;; 3065;HIRAGANA LETTER DU;Lo;0;L;3064 3099;;;;N;;;;; 3066;HIRAGANA LETTER TE;Lo;0;L;;;;;N;;;;; 3067;HIRAGANA LETTER DE;Lo;0;L;3066 3099;;;;N;;;;; 3068;HIRAGANA LETTER TO;Lo;0;L;;;;;N;;;;; 3069;HIRAGANA LETTER DO;Lo;0;L;3068 3099;;;;N;;;;; 306A;HIRAGANA LETTER NA;Lo;0;L;;;;;N;;;;; 306B;HIRAGANA LETTER NI;Lo;0;L;;;;;N;;;;; 306C;HIRAGANA LETTER NU;Lo;0;L;;;;;N;;;;; 306D;HIRAGANA LETTER NE;Lo;0;L;;;;;N;;;;; 306E;HIRAGANA LETTER NO;Lo;0;L;;;;;N;;;;; 306F;HIRAGANA LETTER HA;Lo;0;L;;;;;N;;;;; 3070;HIRAGANA LETTER BA;Lo;0;L;306F 3099;;;;N;;;;; 3071;HIRAGANA LETTER PA;Lo;0;L;306F 309A;;;;N;;;;; 3072;HIRAGANA LETTER HI;Lo;0;L;;;;;N;;;;; 3073;HIRAGANA LETTER BI;Lo;0;L;3072 3099;;;;N;;;;; 3074;HIRAGANA LETTER PI;Lo;0;L;3072 309A;;;;N;;;;; 3075;HIRAGANA LETTER HU;Lo;0;L;;;;;N;;;;; 3076;HIRAGANA LETTER BU;Lo;0;L;3075 3099;;;;N;;;;; 3077;HIRAGANA LETTER PU;Lo;0;L;3075 309A;;;;N;;;;; 3078;HIRAGANA LETTER HE;Lo;0;L;;;;;N;;;;; 3079;HIRAGANA LETTER BE;Lo;0;L;3078 3099;;;;N;;;;; 307A;HIRAGANA LETTER PE;Lo;0;L;3078 309A;;;;N;;;;; 307B;HIRAGANA LETTER HO;Lo;0;L;;;;;N;;;;; 307C;HIRAGANA LETTER BO;Lo;0;L;307B 3099;;;;N;;;;; 307D;HIRAGANA LETTER PO;Lo;0;L;307B 309A;;;;N;;;;; 307E;HIRAGANA LETTER MA;Lo;0;L;;;;;N;;;;; 307F;HIRAGANA LETTER MI;Lo;0;L;;;;;N;;;;; 3080;HIRAGANA LETTER MU;Lo;0;L;;;;;N;;;;; 3081;HIRAGANA LETTER ME;Lo;0;L;;;;;N;;;;; 3082;HIRAGANA LETTER MO;Lo;0;L;;;;;N;;;;; 3083;HIRAGANA LETTER SMALL YA;Lo;0;L;;;;;N;;;;; 3084;HIRAGANA LETTER YA;Lo;0;L;;;;;N;;;;; 3085;HIRAGANA LETTER SMALL YU;Lo;0;L;;;;;N;;;;; 3086;HIRAGANA LETTER YU;Lo;0;L;;;;;N;;;;; 3087;HIRAGANA LETTER SMALL YO;Lo;0;L;;;;;N;;;;; 3088;HIRAGANA LETTER YO;Lo;0;L;;;;;N;;;;; 3089;HIRAGANA LETTER RA;Lo;0;L;;;;;N;;;;; 308A;HIRAGANA LETTER RI;Lo;0;L;;;;;N;;;;; 308B;HIRAGANA LETTER RU;Lo;0;L;;;;;N;;;;; 308C;HIRAGANA LETTER RE;Lo;0;L;;;;;N;;;;; 308D;HIRAGANA LETTER RO;Lo;0;L;;;;;N;;;;; 308E;HIRAGANA LETTER SMALL WA;Lo;0;L;;;;;N;;;;; 308F;HIRAGANA LETTER WA;Lo;0;L;;;;;N;;;;; 3090;HIRAGANA LETTER WI;Lo;0;L;;;;;N;;;;; 3091;HIRAGANA LETTER WE;Lo;0;L;;;;;N;;;;; 3092;HIRAGANA LETTER WO;Lo;0;L;;;;;N;;;;; 3093;HIRAGANA LETTER N;Lo;0;L;;;;;N;;;;; 3094;HIRAGANA LETTER VU;Lo;0;L;3046 3099;;;;N;;;;; 3095;HIRAGANA LETTER SMALL KA;Lo;0;L;;;;;N;;;;; 3096;HIRAGANA LETTER SMALL KE;Lo;0;L;;;;;N;;;;; 3099;COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK;Mn;8;NSM;;;;;N;NON-SPACING KATAKANA-HIRAGANA VOICED SOUND MARK;;;; 309A;COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK;Mn;8;NSM;;;;;N;NON-SPACING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK;;;; 309B;KATAKANA-HIRAGANA VOICED SOUND MARK;Sk;0;ON;<compat> 0020 3099;;;;N;;;;; 309C;KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK;Sk;0;ON;<compat> 0020 309A;;;;N;;;;; 309D;HIRAGANA ITERATION MARK;Lm;0;L;;;;;N;;;;; 309E;HIRAGANA VOICED ITERATION MARK;Lm;0;L;309D 3099;;;;N;;;;; 309F;HIRAGANA DIGRAPH YORI;Lo;0;L;<vertical> 3088 308A;;;;N;;;;; 30A0;KATAKANA-HIRAGANA DOUBLE HYPHEN;Pd;0;ON;;;;;N;;;;; 30A1;KATAKANA LETTER SMALL A;Lo;0;L;;;;;N;;;;; 30A2;KATAKANA LETTER A;Lo;0;L;;;;;N;;;;; 30A3;KATAKANA LETTER SMALL I;Lo;0;L;;;;;N;;;;; 30A4;KATAKANA LETTER I;Lo;0;L;;;;;N;;;;; 30A5;KATAKANA LETTER SMALL U;Lo;0;L;;;;;N;;;;; 30A6;KATAKANA LETTER U;Lo;0;L;;;;;N;;;;; 30A7;KATAKANA LETTER SMALL E;Lo;0;L;;;;;N;;;;; 30A8;KATAKANA LETTER E;Lo;0;L;;;;;N;;;;; 30A9;KATAKANA LETTER SMALL O;Lo;0;L;;;;;N;;;;; 30AA;KATAKANA LETTER O;Lo;0;L;;;;;N;;;;; 30AB;KATAKANA LETTER KA;Lo;0;L;;;;;N;;;;; 30AC;KATAKANA LETTER GA;Lo;0;L;30AB 3099;;;;N;;;;; 30AD;KATAKANA LETTER KI;Lo;0;L;;;;;N;;;;; 30AE;KATAKANA LETTER GI;Lo;0;L;30AD 3099;;;;N;;;;; 30AF;KATAKANA LETTER KU;Lo;0;L;;;;;N;;;;; 30B0;KATAKANA LETTER GU;Lo;0;L;30AF 3099;;;;N;;;;; 30B1;KATAKANA LETTER KE;Lo;0;L;;;;;N;;;;; 30B2;KATAKANA LETTER GE;Lo;0;L;30B1 3099;;;;N;;;;; 30B3;KATAKANA LETTER KO;Lo;0;L;;;;;N;;;;; 30B4;KATAKANA LETTER GO;Lo;0;L;30B3 3099;;;;N;;;;; 30B5;KATAKANA LETTER SA;Lo;0;L;;;;;N;;;;; 30B6;KATAKANA LETTER ZA;Lo;0;L;30B5 3099;;;;N;;;;; 30B7;KATAKANA LETTER SI;Lo;0;L;;;;;N;;;;; 30B8;KATAKANA LETTER ZI;Lo;0;L;30B7 3099;;;;N;;;;; 30B9;KATAKANA LETTER SU;Lo;0;L;;;;;N;;;;; 30BA;KATAKANA LETTER ZU;Lo;0;L;30B9 3099;;;;N;;;;; 30BB;KATAKANA LETTER SE;Lo;0;L;;;;;N;;;;; 30BC;KATAKANA LETTER ZE;Lo;0;L;30BB 3099;;;;N;;;;; 30BD;KATAKANA LETTER SO;Lo;0;L;;;;;N;;;;; 30BE;KATAKANA LETTER ZO;Lo;0;L;30BD 3099;;;;N;;;;; 30BF;KATAKANA LETTER TA;Lo;0;L;;;;;N;;;;; 30C0;KATAKANA LETTER DA;Lo;0;L;30BF 3099;;;;N;;;;; 30C1;KATAKANA LETTER TI;Lo;0;L;;;;;N;;;;; 30C2;KATAKANA LETTER DI;Lo;0;L;30C1 3099;;;;N;;;;; 30C3;KATAKANA LETTER SMALL TU;Lo;0;L;;;;;N;;;;; 30C4;KATAKANA LETTER TU;Lo;0;L;;;;;N;;;;; 30C5;KATAKANA LETTER DU;Lo;0;L;30C4 3099;;;;N;;;;; 30C6;KATAKANA LETTER TE;Lo;0;L;;;;;N;;;;; 30C7;KATAKANA LETTER DE;Lo;0;L;30C6 3099;;;;N;;;;; 30C8;KATAKANA LETTER TO;Lo;0;L;;;;;N;;;;; 30C9;KATAKANA LETTER DO;Lo;0;L;30C8 3099;;;;N;;;;; 30CA;KATAKANA LETTER NA;Lo;0;L;;;;;N;;;;; 30CB;KATAKANA LETTER NI;Lo;0;L;;;;;N;;;;; 30CC;KATAKANA LETTER NU;Lo;0;L;;;;;N;;;;; 30CD;KATAKANA LETTER NE;Lo;0;L;;;;;N;;;;; 30CE;KATAKANA LETTER NO;Lo;0;L;;;;;N;;;;; 30CF;KATAKANA LETTER HA;Lo;0;L;;;;;N;;;;; 30D0;KATAKANA LETTER BA;Lo;0;L;30CF 3099;;;;N;;;;; 30D1;KATAKANA LETTER PA;Lo;0;L;30CF 309A;;;;N;;;;; 30D2;KATAKANA LETTER HI;Lo;0;L;;;;;N;;;;; 30D3;KATAKANA LETTER BI;Lo;0;L;30D2 3099;;;;N;;;;; 30D4;KATAKANA LETTER PI;Lo;0;L;30D2 309A;;;;N;;;;; 30D5;KATAKANA LETTER HU;Lo;0;L;;;;;N;;;;; 30D6;KATAKANA LETTER BU;Lo;0;L;30D5 3099;;;;N;;;;; 30D7;KATAKANA LETTER PU;Lo;0;L;30D5 309A;;;;N;;;;; 30D8;KATAKANA LETTER HE;Lo;0;L;;;;;N;;;;; 30D9;KATAKANA LETTER BE;Lo;0;L;30D8 3099;;;;N;;;;; 30DA;KATAKANA LETTER PE;Lo;0;L;30D8 309A;;;;N;;;;; 30DB;KATAKANA LETTER HO;Lo;0;L;;;;;N;;;;; 30DC;KATAKANA LETTER BO;Lo;0;L;30DB 3099;;;;N;;;;; 30DD;KATAKANA LETTER PO;Lo;0;L;30DB 309A;;;;N;;;;; 30DE;KATAKANA LETTER MA;Lo;0;L;;;;;N;;;;; 30DF;KATAKANA LETTER MI;Lo;0;L;;;;;N;;;;; 30E0;KATAKANA LETTER MU;Lo;0;L;;;;;N;;;;; 30E1;KATAKANA LETTER ME;Lo;0;L;;;;;N;;;;; 30E2;KATAKANA LETTER MO;Lo;0;L;;;;;N;;;;; 30E3;KATAKANA LETTER SMALL YA;Lo;0;L;;;;;N;;;;; 30E4;KATAKANA LETTER YA;Lo;0;L;;;;;N;;;;; 30E5;KATAKANA LETTER SMALL YU;Lo;0;L;;;;;N;;;;; 30E6;KATAKANA LETTER YU;Lo;0;L;;;;;N;;;;; 30E7;KATAKANA LETTER SMALL YO;Lo;0;L;;;;;N;;;;; 30E8;KATAKANA LETTER YO;Lo;0;L;;;;;N;;;;; 30E9;KATAKANA LETTER RA;Lo;0;L;;;;;N;;;;; 30EA;KATAKANA LETTER RI;Lo;0;L;;;;;N;;;;; 30EB;KATAKANA LETTER RU;Lo;0;L;;;;;N;;;;; 30EC;KATAKANA LETTER RE;Lo;0;L;;;;;N;;;;; 30ED;KATAKANA LETTER RO;Lo;0;L;;;;;N;;;;; 30EE;KATAKANA LETTER SMALL WA;Lo;0;L;;;;;N;;;;; 30EF;KATAKANA LETTER WA;Lo;0;L;;;;;N;;;;; 30F0;KATAKANA LETTER WI;Lo;0;L;;;;;N;;;;; 30F1;KATAKANA LETTER WE;Lo;0;L;;;;;N;;;;; 30F2;KATAKANA LETTER WO;Lo;0;L;;;;;N;;;;; 30F3;KATAKANA LETTER N;Lo;0;L;;;;;N;;;;; 30F4;KATAKANA LETTER VU;Lo;0;L;30A6 3099;;;;N;;;;; 30F5;KATAKANA LETTER SMALL KA;Lo;0;L;;;;;N;;;;; 30F6;KATAKANA LETTER SMALL KE;Lo;0;L;;;;;N;;;;; 30F7;KATAKANA LETTER VA;Lo;0;L;30EF 3099;;;;N;;;;; 30F8;KATAKANA LETTER VI;Lo;0;L;30F0 3099;;;;N;;;;; 30F9;KATAKANA LETTER VE;Lo;0;L;30F1 3099;;;;N;;;;; 30FA;KATAKANA LETTER VO;Lo;0;L;30F2 3099;;;;N;;;;; 30FB;KATAKANA MIDDLE DOT;Po;0;ON;;;;;N;;;;; 30FC;KATAKANA-HIRAGANA PROLONGED SOUND MARK;Lm;0;L;;;;;N;;;;; 30FD;KATAKANA ITERATION MARK;Lm;0;L;;;;;N;;;;; 30FE;KATAKANA VOICED ITERATION MARK;Lm;0;L;30FD 3099;;;;N;;;;; 30FF;KATAKANA DIGRAPH KOTO;Lo;0;L;<vertical> 30B3 30C8;;;;N;;;;; 3105;BOPOMOFO LETTER B;Lo;0;L;;;;;N;;;;; 3106;BOPOMOFO LETTER P;Lo;0;L;;;;;N;;;;; 3107;BOPOMOFO LETTER M;Lo;0;L;;;;;N;;;;; 3108;BOPOMOFO LETTER F;Lo;0;L;;;;;N;;;;; 3109;BOPOMOFO LETTER D;Lo;0;L;;;;;N;;;;; 310A;BOPOMOFO LETTER T;Lo;0;L;;;;;N;;;;; 310B;BOPOMOFO LETTER N;Lo;0;L;;;;;N;;;;; 310C;BOPOMOFO LETTER L;Lo;0;L;;;;;N;;;;; 310D;BOPOMOFO LETTER G;Lo;0;L;;;;;N;;;;; 310E;BOPOMOFO LETTER K;Lo;0;L;;;;;N;;;;; 310F;BOPOMOFO LETTER H;Lo;0;L;;;;;N;;;;; 3110;BOPOMOFO LETTER J;Lo;0;L;;;;;N;;;;; 3111;BOPOMOFO LETTER Q;Lo;0;L;;;;;N;;;;; 3112;BOPOMOFO LETTER X;Lo;0;L;;;;;N;;;;; 3113;BOPOMOFO LETTER ZH;Lo;0;L;;;;;N;;;;; 3114;BOPOMOFO LETTER CH;Lo;0;L;;;;;N;;;;; 3115;BOPOMOFO LETTER SH;Lo;0;L;;;;;N;;;;; 3116;BOPOMOFO LETTER R;Lo;0;L;;;;;N;;;;; 3117;BOPOMOFO LETTER Z;Lo;0;L;;;;;N;;;;; 3118;BOPOMOFO LETTER C;Lo;0;L;;;;;N;;;;; 3119;BOPOMOFO LETTER S;Lo;0;L;;;;;N;;;;; 311A;BOPOMOFO LETTER A;Lo;0;L;;;;;N;;;;; 311B;BOPOMOFO LETTER O;Lo;0;L;;;;;N;;;;; 311C;BOPOMOFO LETTER E;Lo;0;L;;;;;N;;;;; 311D;BOPOMOFO LETTER EH;Lo;0;L;;;;;N;;;;; 311E;BOPOMOFO LETTER AI;Lo;0;L;;;;;N;;;;; 311F;BOPOMOFO LETTER EI;Lo;0;L;;;;;N;;;;; 3120;BOPOMOFO LETTER AU;Lo;0;L;;;;;N;;;;; 3121;BOPOMOFO LETTER OU;Lo;0;L;;;;;N;;;;; 3122;BOPOMOFO LETTER AN;Lo;0;L;;;;;N;;;;; 3123;BOPOMOFO LETTER EN;Lo;0;L;;;;;N;;;;; 3124;BOPOMOFO LETTER ANG;Lo;0;L;;;;;N;;;;; 3125;BOPOMOFO LETTER ENG;Lo;0;L;;;;;N;;;;; 3126;BOPOMOFO LETTER ER;Lo;0;L;;;;;N;;;;; 3127;BOPOMOFO LETTER I;Lo;0;L;;;;;N;;;;; 3128;BOPOMOFO LETTER U;Lo;0;L;;;;;N;;;;; 3129;BOPOMOFO LETTER IU;Lo;0;L;;;;;N;;;;; 312A;BOPOMOFO LETTER V;Lo;0;L;;;;;N;;;;; 312B;BOPOMOFO LETTER NG;Lo;0;L;;;;;N;;;;; 312C;BOPOMOFO LETTER GN;Lo;0;L;;;;;N;;;;; 312D;BOPOMOFO LETTER IH;Lo;0;L;;;;;N;;;;; 3131;HANGUL LETTER KIYEOK;Lo;0;L;<compat> 1100;;;;N;HANGUL LETTER GIYEOG;;;; 3132;HANGUL LETTER SSANGKIYEOK;Lo;0;L;<compat> 1101;;;;N;HANGUL LETTER SSANG GIYEOG;;;; 3133;HANGUL LETTER KIYEOK-SIOS;Lo;0;L;<compat> 11AA;;;;N;HANGUL LETTER GIYEOG SIOS;;;; 3134;HANGUL LETTER NIEUN;Lo;0;L;<compat> 1102;;;;N;;;;; 3135;HANGUL LETTER NIEUN-CIEUC;Lo;0;L;<compat> 11AC;;;;N;HANGUL LETTER NIEUN JIEUJ;;;; 3136;HANGUL LETTER NIEUN-HIEUH;Lo;0;L;<compat> 11AD;;;;N;HANGUL LETTER NIEUN HIEUH;;;; 3137;HANGUL LETTER TIKEUT;Lo;0;L;<compat> 1103;;;;N;HANGUL LETTER DIGEUD;;;; 3138;HANGUL LETTER SSANGTIKEUT;Lo;0;L;<compat> 1104;;;;N;HANGUL LETTER SSANG DIGEUD;;;; 3139;HANGUL LETTER RIEUL;Lo;0;L;<compat> 1105;;;;N;HANGUL LETTER LIEUL;;;; 313A;HANGUL LETTER RIEUL-KIYEOK;Lo;0;L;<compat> 11B0;;;;N;HANGUL LETTER LIEUL GIYEOG;;;; 313B;HANGUL LETTER RIEUL-MIEUM;Lo;0;L;<compat> 11B1;;;;N;HANGUL LETTER LIEUL MIEUM;;;; 313C;HANGUL LETTER RIEUL-PIEUP;Lo;0;L;<compat> 11B2;;;;N;HANGUL LETTER LIEUL BIEUB;;;; 313D;HANGUL LETTER RIEUL-SIOS;Lo;0;L;<compat> 11B3;;;;N;HANGUL LETTER LIEUL SIOS;;;; 313E;HANGUL LETTER RIEUL-THIEUTH;Lo;0;L;<compat> 11B4;;;;N;HANGUL LETTER LIEUL TIEUT;;;; 313F;HANGUL LETTER RIEUL-PHIEUPH;Lo;0;L;<compat> 11B5;;;;N;HANGUL LETTER LIEUL PIEUP;;;; 3140;HANGUL LETTER RIEUL-HIEUH;Lo;0;L;<compat> 111A;;;;N;HANGUL LETTER LIEUL HIEUH;;;; 3141;HANGUL LETTER MIEUM;Lo;0;L;<compat> 1106;;;;N;;;;; 3142;HANGUL LETTER PIEUP;Lo;0;L;<compat> 1107;;;;N;HANGUL LETTER BIEUB;;;; 3143;HANGUL LETTER SSANGPIEUP;Lo;0;L;<compat> 1108;;;;N;HANGUL LETTER SSANG BIEUB;;;; 3144;HANGUL LETTER PIEUP-SIOS;Lo;0;L;<compat> 1121;;;;N;HANGUL LETTER BIEUB SIOS;;;; 3145;HANGUL LETTER SIOS;Lo;0;L;<compat> 1109;;;;N;;;;; 3146;HANGUL LETTER SSANGSIOS;Lo;0;L;<compat> 110A;;;;N;HANGUL LETTER SSANG SIOS;;;; 3147;HANGUL LETTER IEUNG;Lo;0;L;<compat> 110B;;;;N;;;;; 3148;HANGUL LETTER CIEUC;Lo;0;L;<compat> 110C;;;;N;HANGUL LETTER JIEUJ;;;; 3149;HANGUL LETTER SSANGCIEUC;Lo;0;L;<compat> 110D;;;;N;HANGUL LETTER SSANG JIEUJ;;;; 314A;HANGUL LETTER CHIEUCH;Lo;0;L;<compat> 110E;;;;N;HANGUL LETTER CIEUC;;;; 314B;HANGUL LETTER KHIEUKH;Lo;0;L;<compat> 110F;;;;N;HANGUL LETTER KIYEOK;;;; 314C;HANGUL LETTER THIEUTH;Lo;0;L;<compat> 1110;;;;N;HANGUL LETTER TIEUT;;;; 314D;HANGUL LETTER PHIEUPH;Lo;0;L;<compat> 1111;;;;N;HANGUL LETTER PIEUP;;;; 314E;HANGUL LETTER HIEUH;Lo;0;L;<compat> 1112;;;;N;;;;; 314F;HANGUL LETTER A;Lo;0;L;<compat> 1161;;;;N;;;;; 3150;HANGUL LETTER AE;Lo;0;L;<compat> 1162;;;;N;;;;; 3151;HANGUL LETTER YA;Lo;0;L;<compat> 1163;;;;N;;;;; 3152;HANGUL LETTER YAE;Lo;0;L;<compat> 1164;;;;N;;;;; 3153;HANGUL LETTER EO;Lo;0;L;<compat> 1165;;;;N;;;;; 3154;HANGUL LETTER E;Lo;0;L;<compat> 1166;;;;N;;;;; 3155;HANGUL LETTER YEO;Lo;0;L;<compat> 1167;;;;N;;;;; 3156;HANGUL LETTER YE;Lo;0;L;<compat> 1168;;;;N;;;;; 3157;HANGUL LETTER O;Lo;0;L;<compat> 1169;;;;N;;;;; 3158;HANGUL LETTER WA;Lo;0;L;<compat> 116A;;;;N;;;;; 3159;HANGUL LETTER WAE;Lo;0;L;<compat> 116B;;;;N;;;;; 315A;HANGUL LETTER OE;Lo;0;L;<compat> 116C;;;;N;;;;; 315B;HANGUL LETTER YO;Lo;0;L;<compat> 116D;;;;N;;;;; 315C;HANGUL LETTER U;Lo;0;L;<compat> 116E;;;;N;;;;; 315D;HANGUL LETTER WEO;Lo;0;L;<compat> 116F;;;;N;;;;; 315E;HANGUL LETTER WE;Lo;0;L;<compat> 1170;;;;N;;;;; 315F;HANGUL LETTER WI;Lo;0;L;<compat> 1171;;;;N;;;;; 3160;HANGUL LETTER YU;Lo;0;L;<compat> 1172;;;;N;;;;; 3161;HANGUL LETTER EU;Lo;0;L;<compat> 1173;;;;N;;;;; 3162;HANGUL LETTER YI;Lo;0;L;<compat> 1174;;;;N;;;;; 3163;HANGUL LETTER I;Lo;0;L;<compat> 1175;;;;N;;;;; 3164;HANGUL FILLER;Lo;0;L;<compat> 1160;;;;N;HANGUL CAE OM;;;; 3165;HANGUL LETTER SSANGNIEUN;Lo;0;L;<compat> 1114;;;;N;HANGUL LETTER SSANG NIEUN;;;; 3166;HANGUL LETTER NIEUN-TIKEUT;Lo;0;L;<compat> 1115;;;;N;HANGUL LETTER NIEUN DIGEUD;;;; 3167;HANGUL LETTER NIEUN-SIOS;Lo;0;L;<compat> 11C7;;;;N;HANGUL LETTER NIEUN SIOS;;;; 3168;HANGUL LETTER NIEUN-PANSIOS;Lo;0;L;<compat> 11C8;;;;N;HANGUL LETTER NIEUN BAN CHI EUM;;;; 3169;HANGUL LETTER RIEUL-KIYEOK-SIOS;Lo;0;L;<compat> 11CC;;;;N;HANGUL LETTER LIEUL GIYEOG SIOS;;;; 316A;HANGUL LETTER RIEUL-TIKEUT;Lo;0;L;<compat> 11CE;;;;N;HANGUL LETTER LIEUL DIGEUD;;;; 316B;HANGUL LETTER RIEUL-PIEUP-SIOS;Lo;0;L;<compat> 11D3;;;;N;HANGUL LETTER LIEUL BIEUB SIOS;;;; 316C;HANGUL LETTER RIEUL-PANSIOS;Lo;0;L;<compat> 11D7;;;;N;HANGUL LETTER LIEUL BAN CHI EUM;;;; 316D;HANGUL LETTER RIEUL-YEORINHIEUH;Lo;0;L;<compat> 11D9;;;;N;HANGUL LETTER LIEUL YEOLIN HIEUH;;;; 316E;HANGUL LETTER MIEUM-PIEUP;Lo;0;L;<compat> 111C;;;;N;HANGUL LETTER MIEUM BIEUB;;;; 316F;HANGUL LETTER MIEUM-SIOS;Lo;0;L;<compat> 11DD;;;;N;HANGUL LETTER MIEUM SIOS;;;; 3170;HANGUL LETTER MIEUM-PANSIOS;Lo;0;L;<compat> 11DF;;;;N;HANGUL LETTER BIEUB BAN CHI EUM;;;; 3171;HANGUL LETTER KAPYEOUNMIEUM;Lo;0;L;<compat> 111D;;;;N;HANGUL LETTER MIEUM SUN GYEONG EUM;;;; 3172;HANGUL LETTER PIEUP-KIYEOK;Lo;0;L;<compat> 111E;;;;N;HANGUL LETTER BIEUB GIYEOG;;;; 3173;HANGUL LETTER PIEUP-TIKEUT;Lo;0;L;<compat> 1120;;;;N;HANGUL LETTER BIEUB DIGEUD;;;; 3174;HANGUL LETTER PIEUP-SIOS-KIYEOK;Lo;0;L;<compat> 1122;;;;N;HANGUL LETTER BIEUB SIOS GIYEOG;;;; 3175;HANGUL LETTER PIEUP-SIOS-TIKEUT;Lo;0;L;<compat> 1123;;;;N;HANGUL LETTER BIEUB SIOS DIGEUD;;;; 3176;HANGUL LETTER PIEUP-CIEUC;Lo;0;L;<compat> 1127;;;;N;HANGUL LETTER BIEUB JIEUJ;;;; 3177;HANGUL LETTER PIEUP-THIEUTH;Lo;0;L;<compat> 1129;;;;N;HANGUL LETTER BIEUB TIEUT;;;; 3178;HANGUL LETTER KAPYEOUNPIEUP;Lo;0;L;<compat> 112B;;;;N;HANGUL LETTER BIEUB SUN GYEONG EUM;;;; 3179;HANGUL LETTER KAPYEOUNSSANGPIEUP;Lo;0;L;<compat> 112C;;;;N;HANGUL LETTER SSANG BIEUB SUN GYEONG EUM;;;; 317A;HANGUL LETTER SIOS-KIYEOK;Lo;0;L;<compat> 112D;;;;N;HANGUL LETTER SIOS GIYEOG;;;; 317B;HANGUL LETTER SIOS-NIEUN;Lo;0;L;<compat> 112E;;;;N;HANGUL LETTER SIOS NIEUN;;;; 317C;HANGUL LETTER SIOS-TIKEUT;Lo;0;L;<compat> 112F;;;;N;HANGUL LETTER SIOS DIGEUD;;;; 317D;HANGUL LETTER SIOS-PIEUP;Lo;0;L;<compat> 1132;;;;N;HANGUL LETTER SIOS BIEUB;;;; 317E;HANGUL LETTER SIOS-CIEUC;Lo;0;L;<compat> 1136;;;;N;HANGUL LETTER SIOS JIEUJ;;;; 317F;HANGUL LETTER PANSIOS;Lo;0;L;<compat> 1140;;;;N;HANGUL LETTER BAN CHI EUM;;;; 3180;HANGUL LETTER SSANGIEUNG;Lo;0;L;<compat> 1147;;;;N;HANGUL LETTER SSANG IEUNG;;;; 3181;HANGUL LETTER YESIEUNG;Lo;0;L;<compat> 114C;;;;N;HANGUL LETTER NGIEUNG;;;; 3182;HANGUL LETTER YESIEUNG-SIOS;Lo;0;L;<compat> 11F1;;;;N;HANGUL LETTER NGIEUNG SIOS;;;; 3183;HANGUL LETTER YESIEUNG-PANSIOS;Lo;0;L;<compat> 11F2;;;;N;HANGUL LETTER NGIEUNG BAN CHI EUM;;;; 3184;HANGUL LETTER KAPYEOUNPHIEUPH;Lo;0;L;<compat> 1157;;;;N;HANGUL LETTER PIEUP SUN GYEONG EUM;;;; 3185;HANGUL LETTER SSANGHIEUH;Lo;0;L;<compat> 1158;;;;N;HANGUL LETTER SSANG HIEUH;;;; 3186;HANGUL LETTER YEORINHIEUH;Lo;0;L;<compat> 1159;;;;N;HANGUL LETTER YEOLIN HIEUH;;;; 3187;HANGUL LETTER YO-YA;Lo;0;L;<compat> 1184;;;;N;HANGUL LETTER YOYA;;;; 3188;HANGUL LETTER YO-YAE;Lo;0;L;<compat> 1185;;;;N;HANGUL LETTER YOYAE;;;; 3189;HANGUL LETTER YO-I;Lo;0;L;<compat> 1188;;;;N;HANGUL LETTER YOI;;;; 318A;HANGUL LETTER YU-YEO;Lo;0;L;<compat> 1191;;;;N;HANGUL LETTER YUYEO;;;; 318B;HANGUL LETTER YU-YE;Lo;0;L;<compat> 1192;;;;N;HANGUL LETTER YUYE;;;; 318C;HANGUL LETTER YU-I;Lo;0;L;<compat> 1194;;;;N;HANGUL LETTER YUI;;;; 318D;HANGUL LETTER ARAEA;Lo;0;L;<compat> 119E;;;;N;HANGUL LETTER ALAE A;;;; 318E;HANGUL LETTER ARAEAE;Lo;0;L;<compat> 11A1;;;;N;HANGUL LETTER ALAE AE;;;; 3190;IDEOGRAPHIC ANNOTATION LINKING MARK;So;0;L;;;;;N;KANBUN TATETEN;;;; 3191;IDEOGRAPHIC ANNOTATION REVERSE MARK;So;0;L;;;;;N;KAERITEN RE;;;; 3192;IDEOGRAPHIC ANNOTATION ONE MARK;No;0;L;<super> 4E00;;;1;N;KAERITEN ITI;;;; 3193;IDEOGRAPHIC ANNOTATION TWO MARK;No;0;L;<super> 4E8C;;;2;N;KAERITEN NI;;;; 3194;IDEOGRAPHIC ANNOTATION THREE MARK;No;0;L;<super> 4E09;;;3;N;KAERITEN SAN;;;; 3195;IDEOGRAPHIC ANNOTATION FOUR MARK;No;0;L;<super> 56DB;;;4;N;KAERITEN SI;;;; 3196;IDEOGRAPHIC ANNOTATION TOP MARK;So;0;L;<super> 4E0A;;;;N;KAERITEN ZYOU;;;; 3197;IDEOGRAPHIC ANNOTATION MIDDLE MARK;So;0;L;<super> 4E2D;;;;N;KAERITEN TYUU;;;; 3198;IDEOGRAPHIC ANNOTATION BOTTOM MARK;So;0;L;<super> 4E0B;;;;N;KAERITEN GE;;;; 3199;IDEOGRAPHIC ANNOTATION FIRST MARK;So;0;L;<super> 7532;;;;N;KAERITEN KOU;;;; 319A;IDEOGRAPHIC ANNOTATION SECOND MARK;So;0;L;<super> 4E59;;;;N;KAERITEN OTU;;;; 319B;IDEOGRAPHIC ANNOTATION THIRD MARK;So;0;L;<super> 4E19;;;;N;KAERITEN HEI;;;; 319C;IDEOGRAPHIC ANNOTATION FOURTH MARK;So;0;L;<super> 4E01;;;;N;KAERITEN TEI;;;; 319D;IDEOGRAPHIC ANNOTATION HEAVEN MARK;So;0;L;<super> 5929;;;;N;KAERITEN TEN;;;; 319E;IDEOGRAPHIC ANNOTATION EARTH MARK;So;0;L;<super> 5730;;;;N;KAERITEN TI;;;; 319F;IDEOGRAPHIC ANNOTATION MAN MARK;So;0;L;<super> 4EBA;;;;N;KAERITEN ZIN;;;; 31A0;BOPOMOFO LETTER BU;Lo;0;L;;;;;N;;;;; 31A1;BOPOMOFO LETTER ZI;Lo;0;L;;;;;N;;;;; 31A2;BOPOMOFO LETTER JI;Lo;0;L;;;;;N;;;;; 31A3;BOPOMOFO LETTER GU;Lo;0;L;;;;;N;;;;; 31A4;BOPOMOFO LETTER EE;Lo;0;L;;;;;N;;;;; 31A5;BOPOMOFO LETTER ENN;Lo;0;L;;;;;N;;;;; 31A6;BOPOMOFO LETTER OO;Lo;0;L;;;;;N;;;;; 31A7;BOPOMOFO LETTER ONN;Lo;0;L;;;;;N;;;;; 31A8;BOPOMOFO LETTER IR;Lo;0;L;;;;;N;;;;; 31A9;BOPOMOFO LETTER ANN;Lo;0;L;;;;;N;;;;; 31AA;BOPOMOFO LETTER INN;Lo;0;L;;;;;N;;;;; 31AB;BOPOMOFO LETTER UNN;Lo;0;L;;;;;N;;;;; 31AC;BOPOMOFO LETTER IM;Lo;0;L;;;;;N;;;;; 31AD;BOPOMOFO LETTER NGG;Lo;0;L;;;;;N;;;;; 31AE;BOPOMOFO LETTER AINN;Lo;0;L;;;;;N;;;;; 31AF;BOPOMOFO LETTER AUNN;Lo;0;L;;;;;N;;;;; 31B0;BOPOMOFO LETTER AM;Lo;0;L;;;;;N;;;;; 31B1;BOPOMOFO LETTER OM;Lo;0;L;;;;;N;;;;; 31B2;BOPOMOFO LETTER ONG;Lo;0;L;;;;;N;;;;; 31B3;BOPOMOFO LETTER INNN;Lo;0;L;;;;;N;;;;; 31B4;BOPOMOFO FINAL LETTER P;Lo;0;L;;;;;N;;;;; 31B5;BOPOMOFO FINAL LETTER T;Lo;0;L;;;;;N;;;;; 31B6;BOPOMOFO FINAL LETTER K;Lo;0;L;;;;;N;;;;; 31B7;BOPOMOFO FINAL LETTER H;Lo;0;L;;;;;N;;;;; 31B8;BOPOMOFO LETTER GH;Lo;0;L;;;;;N;;;;; 31B9;BOPOMOFO LETTER LH;Lo;0;L;;;;;N;;;;; 31BA;BOPOMOFO LETTER ZY;Lo;0;L;;;;;N;;;;; 31C0;CJK STROKE T;So;0;ON;;;;;N;;;;; 31C1;CJK STROKE WG;So;0;ON;;;;;N;;;;; 31C2;CJK STROKE XG;So;0;ON;;;;;N;;;;; 31C3;CJK STROKE BXG;So;0;ON;;;;;N;;;;; 31C4;CJK STROKE SW;So;0;ON;;;;;N;;;;; 31C5;CJK STROKE HZZ;So;0;ON;;;;;N;;;;; 31C6;CJK STROKE HZG;So;0;ON;;;;;N;;;;; 31C7;CJK STROKE HP;So;0;ON;;;;;N;;;;; 31C8;CJK STROKE HZWG;So;0;ON;;;;;N;;;;; 31C9;CJK STROKE SZWG;So;0;ON;;;;;N;;;;; 31CA;CJK STROKE HZT;So;0;ON;;;;;N;;;;; 31CB;CJK STROKE HZZP;So;0;ON;;;;;N;;;;; 31CC;CJK STROKE HPWG;So;0;ON;;;;;N;;;;; 31CD;CJK STROKE HZW;So;0;ON;;;;;N;;;;; 31CE;CJK STROKE HZZZ;So;0;ON;;;;;N;;;;; 31CF;CJK STROKE N;So;0;ON;;;;;N;;;;; 31D0;CJK STROKE H;So;0;ON;;;;;N;;;;; 31D1;CJK STROKE S;So;0;ON;;;;;N;;;;; 31D2;CJK STROKE P;So;0;ON;;;;;N;;;;; 31D3;CJK STROKE SP;So;0;ON;;;;;N;;;;; 31D4;CJK STROKE D;So;0;ON;;;;;N;;;;; 31D5;CJK STROKE HZ;So;0;ON;;;;;N;;;;; 31D6;CJK STROKE HG;So;0;ON;;;;;N;;;;; 31D7;CJK STROKE SZ;So;0;ON;;;;;N;;;;; 31D8;CJK STROKE SWZ;So;0;ON;;;;;N;;;;; 31D9;CJK STROKE ST;So;0;ON;;;;;N;;;;; 31DA;CJK STROKE SG;So;0;ON;;;;;N;;;;; 31DB;CJK STROKE PD;So;0;ON;;;;;N;;;;; 31DC;CJK STROKE PZ;So;0;ON;;;;;N;;;;; 31DD;CJK STROKE TN;So;0;ON;;;;;N;;;;; 31DE;CJK STROKE SZZ;So;0;ON;;;;;N;;;;; 31DF;CJK STROKE SWG;So;0;ON;;;;;N;;;;; 31E0;CJK STROKE HXWG;So;0;ON;;;;;N;;;;; 31E1;CJK STROKE HZZZG;So;0;ON;;;;;N;;;;; 31E2;CJK STROKE PG;So;0;ON;;;;;N;;;;; 31E3;CJK STROKE Q;So;0;ON;;;;;N;;;;; 31F0;KATAKANA LETTER SMALL KU;Lo;0;L;;;;;N;;;;; 31F1;KATAKANA LETTER SMALL SI;Lo;0;L;;;;;N;;;;; 31F2;KATAKANA LETTER SMALL SU;Lo;0;L;;;;;N;;;;; 31F3;KATAKANA LETTER SMALL TO;Lo;0;L;;;;;N;;;;; 31F4;KATAKANA LETTER SMALL NU;Lo;0;L;;;;;N;;;;; 31F5;KATAKANA LETTER SMALL HA;Lo;0;L;;;;;N;;;;; 31F6;KATAKANA LETTER SMALL HI;Lo;0;L;;;;;N;;;;; 31F7;KATAKANA LETTER SMALL HU;Lo;0;L;;;;;N;;;;; 31F8;KATAKANA LETTER SMALL HE;Lo;0;L;;;;;N;;;;; 31F9;KATAKANA LETTER SMALL HO;Lo;0;L;;;;;N;;;;; 31FA;KATAKANA LETTER SMALL MU;Lo;0;L;;;;;N;;;;; 31FB;KATAKANA LETTER SMALL RA;Lo;0;L;;;;;N;;;;; 31FC;KATAKANA LETTER SMALL RI;Lo;0;L;;;;;N;;;;; 31FD;KATAKANA LETTER SMALL RU;Lo;0;L;;;;;N;;;;; 31FE;KATAKANA LETTER SMALL RE;Lo;0;L;;;;;N;;;;; 31FF;KATAKANA LETTER SMALL RO;Lo;0;L;;;;;N;;;;; 3200;PARENTHESIZED HANGUL KIYEOK;So;0;L;<compat> 0028 1100 0029;;;;N;PARENTHESIZED HANGUL GIYEOG;;;; 3201;PARENTHESIZED HANGUL NIEUN;So;0;L;<compat> 0028 1102 0029;;;;N;;;;; 3202;PARENTHESIZED HANGUL TIKEUT;So;0;L;<compat> 0028 1103 0029;;;;N;PARENTHESIZED HANGUL DIGEUD;;;; 3203;PARENTHESIZED HANGUL RIEUL;So;0;L;<compat> 0028 1105 0029;;;;N;PARENTHESIZED HANGUL LIEUL;;;; 3204;PARENTHESIZED HANGUL MIEUM;So;0;L;<compat> 0028 1106 0029;;;;N;;;;; 3205;PARENTHESIZED HANGUL PIEUP;So;0;L;<compat> 0028 1107 0029;;;;N;PARENTHESIZED HANGUL BIEUB;;;; 3206;PARENTHESIZED HANGUL SIOS;So;0;L;<compat> 0028 1109 0029;;;;N;;;;; 3207;PARENTHESIZED HANGUL IEUNG;So;0;L;<compat> 0028 110B 0029;;;;N;;;;; 3208;PARENTHESIZED HANGUL CIEUC;So;0;L;<compat> 0028 110C 0029;;;;N;PARENTHESIZED HANGUL JIEUJ;;;; 3209;PARENTHESIZED HANGUL CHIEUCH;So;0;L;<compat> 0028 110E 0029;;;;N;PARENTHESIZED HANGUL CIEUC;;;; 320A;PARENTHESIZED HANGUL KHIEUKH;So;0;L;<compat> 0028 110F 0029;;;;N;PARENTHESIZED HANGUL KIYEOK;;;; 320B;PARENTHESIZED HANGUL THIEUTH;So;0;L;<compat> 0028 1110 0029;;;;N;PARENTHESIZED HANGUL TIEUT;;;; 320C;PARENTHESIZED HANGUL PHIEUPH;So;0;L;<compat> 0028 1111 0029;;;;N;PARENTHESIZED HANGUL PIEUP;;;; 320D;PARENTHESIZED HANGUL HIEUH;So;0;L;<compat> 0028 1112 0029;;;;N;;;;; 320E;PARENTHESIZED HANGUL KIYEOK A;So;0;L;<compat> 0028 1100 1161 0029;;;;N;PARENTHESIZED HANGUL GA;;;; 320F;PARENTHESIZED HANGUL NIEUN A;So;0;L;<compat> 0028 1102 1161 0029;;;;N;PARENTHESIZED HANGUL NA;;;; 3210;PARENTHESIZED HANGUL TIKEUT A;So;0;L;<compat> 0028 1103 1161 0029;;;;N;PARENTHESIZED HANGUL DA;;;; 3211;PARENTHESIZED HANGUL RIEUL A;So;0;L;<compat> 0028 1105 1161 0029;;;;N;PARENTHESIZED HANGUL LA;;;; 3212;PARENTHESIZED HANGUL MIEUM A;So;0;L;<compat> 0028 1106 1161 0029;;;;N;PARENTHESIZED HANGUL MA;;;; 3213;PARENTHESIZED HANGUL PIEUP A;So;0;L;<compat> 0028 1107 1161 0029;;;;N;PARENTHESIZED HANGUL BA;;;; 3214;PARENTHESIZED HANGUL SIOS A;So;0;L;<compat> 0028 1109 1161 0029;;;;N;PARENTHESIZED HANGUL SA;;;; 3215;PARENTHESIZED HANGUL IEUNG A;So;0;L;<compat> 0028 110B 1161 0029;;;;N;PARENTHESIZED HANGUL A;;;; 3216;PARENTHESIZED HANGUL CIEUC A;So;0;L;<compat> 0028 110C 1161 0029;;;;N;PARENTHESIZED HANGUL JA;;;; 3217;PARENTHESIZED HANGUL CHIEUCH A;So;0;L;<compat> 0028 110E 1161 0029;;;;N;PARENTHESIZED HANGUL CA;;;; 3218;PARENTHESIZED HANGUL KHIEUKH A;So;0;L;<compat> 0028 110F 1161 0029;;;;N;PARENTHESIZED HANGUL KA;;;; 3219;PARENTHESIZED HANGUL THIEUTH A;So;0;L;<compat> 0028 1110 1161 0029;;;;N;PARENTHESIZED HANGUL TA;;;; 321A;PARENTHESIZED HANGUL PHIEUPH A;So;0;L;<compat> 0028 1111 1161 0029;;;;N;PARENTHESIZED HANGUL PA;;;; 321B;PARENTHESIZED HANGUL HIEUH A;So;0;L;<compat> 0028 1112 1161 0029;;;;N;PARENTHESIZED HANGUL HA;;;; 321C;PARENTHESIZED HANGUL CIEUC U;So;0;L;<compat> 0028 110C 116E 0029;;;;N;PARENTHESIZED HANGUL JU;;;; 321D;PARENTHESIZED KOREAN CHARACTER OJEON;So;0;ON;<compat> 0028 110B 1169 110C 1165 11AB 0029;;;;N;;;;; 321E;PARENTHESIZED KOREAN CHARACTER O HU;So;0;ON;<compat> 0028 110B 1169 1112 116E 0029;;;;N;;;;; 3220;PARENTHESIZED IDEOGRAPH ONE;No;0;L;<compat> 0028 4E00 0029;;;1;N;;;;; 3221;PARENTHESIZED IDEOGRAPH TWO;No;0;L;<compat> 0028 4E8C 0029;;;2;N;;;;; 3222;PARENTHESIZED IDEOGRAPH THREE;No;0;L;<compat> 0028 4E09 0029;;;3;N;;;;; 3223;PARENTHESIZED IDEOGRAPH FOUR;No;0;L;<compat> 0028 56DB 0029;;;4;N;;;;; 3224;PARENTHESIZED IDEOGRAPH FIVE;No;0;L;<compat> 0028 4E94 0029;;;5;N;;;;; 3225;PARENTHESIZED IDEOGRAPH SIX;No;0;L;<compat> 0028 516D 0029;;;6;N;;;;; 3226;PARENTHESIZED IDEOGRAPH SEVEN;No;0;L;<compat> 0028 4E03 0029;;;7;N;;;;; 3227;PARENTHESIZED IDEOGRAPH EIGHT;No;0;L;<compat> 0028 516B 0029;;;8;N;;;;; 3228;PARENTHESIZED IDEOGRAPH NINE;No;0;L;<compat> 0028 4E5D 0029;;;9;N;;;;; 3229;PARENTHESIZED IDEOGRAPH TEN;No;0;L;<compat> 0028 5341 0029;;;10;N;;;;; 322A;PARENTHESIZED IDEOGRAPH MOON;So;0;L;<compat> 0028 6708 0029;;;;N;;;;; 322B;PARENTHESIZED IDEOGRAPH FIRE;So;0;L;<compat> 0028 706B 0029;;;;N;;;;; 322C;PARENTHESIZED IDEOGRAPH WATER;So;0;L;<compat> 0028 6C34 0029;;;;N;;;;; 322D;PARENTHESIZED IDEOGRAPH WOOD;So;0;L;<compat> 0028 6728 0029;;;;N;;;;; 322E;PARENTHESIZED IDEOGRAPH METAL;So;0;L;<compat> 0028 91D1 0029;;;;N;;;;; 322F;PARENTHESIZED IDEOGRAPH EARTH;So;0;L;<compat> 0028 571F 0029;;;;N;;;;; 3230;PARENTHESIZED IDEOGRAPH SUN;So;0;L;<compat> 0028 65E5 0029;;;;N;;;;; 3231;PARENTHESIZED IDEOGRAPH STOCK;So;0;L;<compat> 0028 682A 0029;;;;N;;;;; 3232;PARENTHESIZED IDEOGRAPH HAVE;So;0;L;<compat> 0028 6709 0029;;;;N;;;;; 3233;PARENTHESIZED IDEOGRAPH SOCIETY;So;0;L;<compat> 0028 793E 0029;;;;N;;;;; 3234;PARENTHESIZED IDEOGRAPH NAME;So;0;L;<compat> 0028 540D 0029;;;;N;;;;; 3235;PARENTHESIZED IDEOGRAPH SPECIAL;So;0;L;<compat> 0028 7279 0029;;;;N;;;;; 3236;PARENTHESIZED IDEOGRAPH FINANCIAL;So;0;L;<compat> 0028 8CA1 0029;;;;N;;;;; 3237;PARENTHESIZED IDEOGRAPH CONGRATULATION;So;0;L;<compat> 0028 795D 0029;;;;N;;;;; 3238;PARENTHESIZED IDEOGRAPH LABOR;So;0;L;<compat> 0028 52B4 0029;;;;N;;;;; 3239;PARENTHESIZED IDEOGRAPH REPRESENT;So;0;L;<compat> 0028 4EE3 0029;;;;N;;;;; 323A;PARENTHESIZED IDEOGRAPH CALL;So;0;L;<compat> 0028 547C 0029;;;;N;;;;; 323B;PARENTHESIZED IDEOGRAPH STUDY;So;0;L;<compat> 0028 5B66 0029;;;;N;;;;; 323C;PARENTHESIZED IDEOGRAPH SUPERVISE;So;0;L;<compat> 0028 76E3 0029;;;;N;;;;; 323D;PARENTHESIZED IDEOGRAPH ENTERPRISE;So;0;L;<compat> 0028 4F01 0029;;;;N;;;;; 323E;PARENTHESIZED IDEOGRAPH RESOURCE;So;0;L;<compat> 0028 8CC7 0029;;;;N;;;;; 323F;PARENTHESIZED IDEOGRAPH ALLIANCE;So;0;L;<compat> 0028 5354 0029;;;;N;;;;; 3240;PARENTHESIZED IDEOGRAPH FESTIVAL;So;0;L;<compat> 0028 796D 0029;;;;N;;;;; 3241;PARENTHESIZED IDEOGRAPH REST;So;0;L;<compat> 0028 4F11 0029;;;;N;;;;; 3242;PARENTHESIZED IDEOGRAPH SELF;So;0;L;<compat> 0028 81EA 0029;;;;N;;;;; 3243;PARENTHESIZED IDEOGRAPH REACH;So;0;L;<compat> 0028 81F3 0029;;;;N;;;;; 3244;CIRCLED IDEOGRAPH QUESTION;So;0;L;<circle> 554F;;;;N;;;;; 3245;CIRCLED IDEOGRAPH KINDERGARTEN;So;0;L;<circle> 5E7C;;;;N;;;;; 3246;CIRCLED IDEOGRAPH SCHOOL;So;0;L;<circle> 6587;;;;N;;;;; 3247;CIRCLED IDEOGRAPH KOTO;So;0;L;<circle> 7B8F;;;;N;;;;; 3248;CIRCLED NUMBER TEN ON BLACK SQUARE;No;0;L;;;;10;N;;;;; 3249;CIRCLED NUMBER TWENTY ON BLACK SQUARE;No;0;L;;;;20;N;;;;; 324A;CIRCLED NUMBER THIRTY ON BLACK SQUARE;No;0;L;;;;30;N;;;;; 324B;CIRCLED NUMBER FORTY ON BLACK SQUARE;No;0;L;;;;40;N;;;;; 324C;CIRCLED NUMBER FIFTY ON BLACK SQUARE;No;0;L;;;;50;N;;;;; 324D;CIRCLED NUMBER SIXTY ON BLACK SQUARE;No;0;L;;;;60;N;;;;; 324E;CIRCLED NUMBER SEVENTY ON BLACK SQUARE;No;0;L;;;;70;N;;;;; 324F;CIRCLED NUMBER EIGHTY ON BLACK SQUARE;No;0;L;;;;80;N;;;;; 3250;PARTNERSHIP SIGN;So;0;ON;<square> 0050 0054 0045;;;;N;;;;; 3251;CIRCLED NUMBER TWENTY ONE;No;0;ON;<circle> 0032 0031;;;21;N;;;;; 3252;CIRCLED NUMBER TWENTY TWO;No;0;ON;<circle> 0032 0032;;;22;N;;;;; 3253;CIRCLED NUMBER TWENTY THREE;No;0;ON;<circle> 0032 0033;;;23;N;;;;; 3254;CIRCLED NUMBER TWENTY FOUR;No;0;ON;<circle> 0032 0034;;;24;N;;;;; 3255;CIRCLED NUMBER TWENTY FIVE;No;0;ON;<circle> 0032 0035;;;25;N;;;;; 3256;CIRCLED NUMBER TWENTY SIX;No;0;ON;<circle> 0032 0036;;;26;N;;;;; 3257;CIRCLED NUMBER TWENTY SEVEN;No;0;ON;<circle> 0032 0037;;;27;N;;;;; 3258;CIRCLED NUMBER TWENTY EIGHT;No;0;ON;<circle> 0032 0038;;;28;N;;;;; 3259;CIRCLED NUMBER TWENTY NINE;No;0;ON;<circle> 0032 0039;;;29;N;;;;; 325A;CIRCLED NUMBER THIRTY;No;0;ON;<circle> 0033 0030;;;30;N;;;;; 325B;CIRCLED NUMBER THIRTY ONE;No;0;ON;<circle> 0033 0031;;;31;N;;;;; 325C;CIRCLED NUMBER THIRTY TWO;No;0;ON;<circle> 0033 0032;;;32;N;;;;; 325D;CIRCLED NUMBER THIRTY THREE;No;0;ON;<circle> 0033 0033;;;33;N;;;;; 325E;CIRCLED NUMBER THIRTY FOUR;No;0;ON;<circle> 0033 0034;;;34;N;;;;; 325F;CIRCLED NUMBER THIRTY FIVE;No;0;ON;<circle> 0033 0035;;;35;N;;;;; 3260;CIRCLED HANGUL KIYEOK;So;0;L;<circle> 1100;;;;N;CIRCLED HANGUL GIYEOG;;;; 3261;CIRCLED HANGUL NIEUN;So;0;L;<circle> 1102;;;;N;;;;; 3262;CIRCLED HANGUL TIKEUT;So;0;L;<circle> 1103;;;;N;CIRCLED HANGUL DIGEUD;;;; 3263;CIRCLED HANGUL RIEUL;So;0;L;<circle> 1105;;;;N;CIRCLED HANGUL LIEUL;;;; 3264;CIRCLED HANGUL MIEUM;So;0;L;<circle> 1106;;;;N;;;;; 3265;CIRCLED HANGUL PIEUP;So;0;L;<circle> 1107;;;;N;CIRCLED HANGUL BIEUB;;;; 3266;CIRCLED HANGUL SIOS;So;0;L;<circle> 1109;;;;N;;;;; 3267;CIRCLED HANGUL IEUNG;So;0;L;<circle> 110B;;;;N;;;;; 3268;CIRCLED HANGUL CIEUC;So;0;L;<circle> 110C;;;;N;CIRCLED HANGUL JIEUJ;;;; 3269;CIRCLED HANGUL CHIEUCH;So;0;L;<circle> 110E;;;;N;CIRCLED HANGUL CIEUC;;;; 326A;CIRCLED HANGUL KHIEUKH;So;0;L;<circle> 110F;;;;N;CIRCLED HANGUL KIYEOK;;;; 326B;CIRCLED HANGUL THIEUTH;So;0;L;<circle> 1110;;;;N;CIRCLED HANGUL TIEUT;;;; 326C;CIRCLED HANGUL PHIEUPH;So;0;L;<circle> 1111;;;;N;CIRCLED HANGUL PIEUP;;;; 326D;CIRCLED HANGUL HIEUH;So;0;L;<circle> 1112;;;;N;;;;; 326E;CIRCLED HANGUL KIYEOK A;So;0;L;<circle> 1100 1161;;;;N;CIRCLED HANGUL GA;;;; 326F;CIRCLED HANGUL NIEUN A;So;0;L;<circle> 1102 1161;;;;N;CIRCLED HANGUL NA;;;; 3270;CIRCLED HANGUL TIKEUT A;So;0;L;<circle> 1103 1161;;;;N;CIRCLED HANGUL DA;;;; 3271;CIRCLED HANGUL RIEUL A;So;0;L;<circle> 1105 1161;;;;N;CIRCLED HANGUL LA;;;; 3272;CIRCLED HANGUL MIEUM A;So;0;L;<circle> 1106 1161;;;;N;CIRCLED HANGUL MA;;;; 3273;CIRCLED HANGUL PIEUP A;So;0;L;<circle> 1107 1161;;;;N;CIRCLED HANGUL BA;;;; 3274;CIRCLED HANGUL SIOS A;So;0;L;<circle> 1109 1161;;;;N;CIRCLED HANGUL SA;;;; 3275;CIRCLED HANGUL IEUNG A;So;0;L;<circle> 110B 1161;;;;N;CIRCLED HANGUL A;;;; 3276;CIRCLED HANGUL CIEUC A;So;0;L;<circle> 110C 1161;;;;N;CIRCLED HANGUL JA;;;; 3277;CIRCLED HANGUL CHIEUCH A;So;0;L;<circle> 110E 1161;;;;N;CIRCLED HANGUL CA;;;; 3278;CIRCLED HANGUL KHIEUKH A;So;0;L;<circle> 110F 1161;;;;N;CIRCLED HANGUL KA;;;; 3279;CIRCLED HANGUL THIEUTH A;So;0;L;<circle> 1110 1161;;;;N;CIRCLED HANGUL TA;;;; 327A;CIRCLED HANGUL PHIEUPH A;So;0;L;<circle> 1111 1161;;;;N;CIRCLED HANGUL PA;;;; 327B;CIRCLED HANGUL HIEUH A;So;0;L;<circle> 1112 1161;;;;N;CIRCLED HANGUL HA;;;; 327C;CIRCLED KOREAN CHARACTER CHAMKO;So;0;ON;<circle> 110E 1161 11B7 1100 1169;;;;N;;;;; 327D;CIRCLED KOREAN CHARACTER JUEUI;So;0;ON;<circle> 110C 116E 110B 1174;;;;N;;;;; 327E;CIRCLED HANGUL IEUNG U;So;0;ON;<circle> 110B 116E;;;;N;;;;; 327F;KOREAN STANDARD SYMBOL;So;0;L;;;;;N;;;;; 3280;CIRCLED IDEOGRAPH ONE;No;0;L;<circle> 4E00;;;1;N;;;;; 3281;CIRCLED IDEOGRAPH TWO;No;0;L;<circle> 4E8C;;;2;N;;;;; 3282;CIRCLED IDEOGRAPH THREE;No;0;L;<circle> 4E09;;;3;N;;;;; 3283;CIRCLED IDEOGRAPH FOUR;No;0;L;<circle> 56DB;;;4;N;;;;; 3284;CIRCLED IDEOGRAPH FIVE;No;0;L;<circle> 4E94;;;5;N;;;;; 3285;CIRCLED IDEOGRAPH SIX;No;0;L;<circle> 516D;;;6;N;;;;; 3286;CIRCLED IDEOGRAPH SEVEN;No;0;L;<circle> 4E03;;;7;N;;;;; 3287;CIRCLED IDEOGRAPH EIGHT;No;0;L;<circle> 516B;;;8;N;;;;; 3288;CIRCLED IDEOGRAPH NINE;No;0;L;<circle> 4E5D;;;9;N;;;;; 3289;CIRCLED IDEOGRAPH TEN;No;0;L;<circle> 5341;;;10;N;;;;; 328A;CIRCLED IDEOGRAPH MOON;So;0;L;<circle> 6708;;;;N;;;;; 328B;CIRCLED IDEOGRAPH FIRE;So;0;L;<circle> 706B;;;;N;;;;; 328C;CIRCLED IDEOGRAPH WATER;So;0;L;<circle> 6C34;;;;N;;;;; 328D;CIRCLED IDEOGRAPH WOOD;So;0;L;<circle> 6728;;;;N;;;;; 328E;CIRCLED IDEOGRAPH METAL;So;0;L;<circle> 91D1;;;;N;;;;; 328F;CIRCLED IDEOGRAPH EARTH;So;0;L;<circle> 571F;;;;N;;;;; 3290;CIRCLED IDEOGRAPH SUN;So;0;L;<circle> 65E5;;;;N;;;;; 3291;CIRCLED IDEOGRAPH STOCK;So;0;L;<circle> 682A;;;;N;;;;; 3292;CIRCLED IDEOGRAPH HAVE;So;0;L;<circle> 6709;;;;N;;;;; 3293;CIRCLED IDEOGRAPH SOCIETY;So;0;L;<circle> 793E;;;;N;;;;; 3294;CIRCLED IDEOGRAPH NAME;So;0;L;<circle> 540D;;;;N;;;;; 3295;CIRCLED IDEOGRAPH SPECIAL;So;0;L;<circle> 7279;;;;N;;;;; 3296;CIRCLED IDEOGRAPH FINANCIAL;So;0;L;<circle> 8CA1;;;;N;;;;; 3297;CIRCLED IDEOGRAPH CONGRATULATION;So;0;L;<circle> 795D;;;;N;;;;; 3298;CIRCLED IDEOGRAPH LABOR;So;0;L;<circle> 52B4;;;;N;;;;; 3299;CIRCLED IDEOGRAPH SECRET;So;0;L;<circle> 79D8;;;;N;;;;; 329A;CIRCLED IDEOGRAPH MALE;So;0;L;<circle> 7537;;;;N;;;;; 329B;CIRCLED IDEOGRAPH FEMALE;So;0;L;<circle> 5973;;;;N;;;;; 329C;CIRCLED IDEOGRAPH SUITABLE;So;0;L;<circle> 9069;;;;N;;;;; 329D;CIRCLED IDEOGRAPH EXCELLENT;So;0;L;<circle> 512A;;;;N;;;;; 329E;CIRCLED IDEOGRAPH PRINT;So;0;L;<circle> 5370;;;;N;;;;; 329F;CIRCLED IDEOGRAPH ATTENTION;So;0;L;<circle> 6CE8;;;;N;;;;; 32A0;CIRCLED IDEOGRAPH ITEM;So;0;L;<circle> 9805;;;;N;;;;; 32A1;CIRCLED IDEOGRAPH REST;So;0;L;<circle> 4F11;;;;N;;;;; 32A2;CIRCLED IDEOGRAPH COPY;So;0;L;<circle> 5199;;;;N;;;;; 32A3;CIRCLED IDEOGRAPH CORRECT;So;0;L;<circle> 6B63;;;;N;;;;; 32A4;CIRCLED IDEOGRAPH HIGH;So;0;L;<circle> 4E0A;;;;N;;;;; 32A5;CIRCLED IDEOGRAPH CENTRE;So;0;L;<circle> 4E2D;;;;N;CIRCLED IDEOGRAPH CENTER;;;; 32A6;CIRCLED IDEOGRAPH LOW;So;0;L;<circle> 4E0B;;;;N;;;;; 32A7;CIRCLED IDEOGRAPH LEFT;So;0;L;<circle> 5DE6;;;;N;;;;; 32A8;CIRCLED IDEOGRAPH RIGHT;So;0;L;<circle> 53F3;;;;N;;;;; 32A9;CIRCLED IDEOGRAPH MEDICINE;So;0;L;<circle> 533B;;;;N;;;;; 32AA;CIRCLED IDEOGRAPH RELIGION;So;0;L;<circle> 5B97;;;;N;;;;; 32AB;CIRCLED IDEOGRAPH STUDY;So;0;L;<circle> 5B66;;;;N;;;;; 32AC;CIRCLED IDEOGRAPH SUPERVISE;So;0;L;<circle> 76E3;;;;N;;;;; 32AD;CIRCLED IDEOGRAPH ENTERPRISE;So;0;L;<circle> 4F01;;;;N;;;;; 32AE;CIRCLED IDEOGRAPH RESOURCE;So;0;L;<circle> 8CC7;;;;N;;;;; 32AF;CIRCLED IDEOGRAPH ALLIANCE;So;0;L;<circle> 5354;;;;N;;;;; 32B0;CIRCLED IDEOGRAPH NIGHT;So;0;L;<circle> 591C;;;;N;;;;; 32B1;CIRCLED NUMBER THIRTY SIX;No;0;ON;<circle> 0033 0036;;;36;N;;;;; 32B2;CIRCLED NUMBER THIRTY SEVEN;No;0;ON;<circle> 0033 0037;;;37;N;;;;; 32B3;CIRCLED NUMBER THIRTY EIGHT;No;0;ON;<circle> 0033 0038;;;38;N;;;;; 32B4;CIRCLED NUMBER THIRTY NINE;No;0;ON;<circle> 0033 0039;;;39;N;;;;; 32B5;CIRCLED NUMBER FORTY;No;0;ON;<circle> 0034 0030;;;40;N;;;;; 32B6;CIRCLED NUMBER FORTY ONE;No;0;ON;<circle> 0034 0031;;;41;N;;;;; 32B7;CIRCLED NUMBER FORTY TWO;No;0;ON;<circle> 0034 0032;;;42;N;;;;; 32B8;CIRCLED NUMBER FORTY THREE;No;0;ON;<circle> 0034 0033;;;43;N;;;;; 32B9;CIRCLED NUMBER FORTY FOUR;No;0;ON;<circle> 0034 0034;;;44;N;;;;; 32BA;CIRCLED NUMBER FORTY FIVE;No;0;ON;<circle> 0034 0035;;;45;N;;;;; 32BB;CIRCLED NUMBER FORTY SIX;No;0;ON;<circle> 0034 0036;;;46;N;;;;; 32BC;CIRCLED NUMBER FORTY SEVEN;No;0;ON;<circle> 0034 0037;;;47;N;;;;; 32BD;CIRCLED NUMBER FORTY EIGHT;No;0;ON;<circle> 0034 0038;;;48;N;;;;; 32BE;CIRCLED NUMBER FORTY NINE;No;0;ON;<circle> 0034 0039;;;49;N;;;;; 32BF;CIRCLED NUMBER FIFTY;No;0;ON;<circle> 0035 0030;;;50;N;;;;; 32C0;IDEOGRAPHIC TELEGRAPH SYMBOL FOR JANUARY;So;0;L;<compat> 0031 6708;;;;N;;;;; 32C1;IDEOGRAPHIC TELEGRAPH SYMBOL FOR FEBRUARY;So;0;L;<compat> 0032 6708;;;;N;;;;; 32C2;IDEOGRAPHIC TELEGRAPH SYMBOL FOR MARCH;So;0;L;<compat> 0033 6708;;;;N;;;;; 32C3;IDEOGRAPHIC TELEGRAPH SYMBOL FOR APRIL;So;0;L;<compat> 0034 6708;;;;N;;;;; 32C4;IDEOGRAPHIC TELEGRAPH SYMBOL FOR MAY;So;0;L;<compat> 0035 6708;;;;N;;;;; 32C5;IDEOGRAPHIC TELEGRAPH SYMBOL FOR JUNE;So;0;L;<compat> 0036 6708;;;;N;;;;; 32C6;IDEOGRAPHIC TELEGRAPH SYMBOL FOR JULY;So;0;L;<compat> 0037 6708;;;;N;;;;; 32C7;IDEOGRAPHIC TELEGRAPH SYMBOL FOR AUGUST;So;0;L;<compat> 0038 6708;;;;N;;;;; 32C8;IDEOGRAPHIC TELEGRAPH SYMBOL FOR SEPTEMBER;So;0;L;<compat> 0039 6708;;;;N;;;;; 32C9;IDEOGRAPHIC TELEGRAPH SYMBOL FOR OCTOBER;So;0;L;<compat> 0031 0030 6708;;;;N;;;;; 32CA;IDEOGRAPHIC TELEGRAPH SYMBOL FOR NOVEMBER;So;0;L;<compat> 0031 0031 6708;;;;N;;;;; 32CB;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DECEMBER;So;0;L;<compat> 0031 0032 6708;;;;N;;;;; 32CC;SQUARE HG;So;0;ON;<square> 0048 0067;;;;N;;;;; 32CD;SQUARE ERG;So;0;ON;<square> 0065 0072 0067;;;;N;;;;; 32CE;SQUARE EV;So;0;ON;<square> 0065 0056;;;;N;;;;; 32CF;LIMITED LIABILITY SIGN;So;0;ON;<square> 004C 0054 0044;;;;N;;;;; 32D0;CIRCLED KATAKANA A;So;0;L;<circle> 30A2;;;;N;;;;; 32D1;CIRCLED KATAKANA I;So;0;L;<circle> 30A4;;;;N;;;;; 32D2;CIRCLED KATAKANA U;So;0;L;<circle> 30A6;;;;N;;;;; 32D3;CIRCLED KATAKANA E;So;0;L;<circle> 30A8;;;;N;;;;; 32D4;CIRCLED KATAKANA O;So;0;L;<circle> 30AA;;;;N;;;;; 32D5;CIRCLED KATAKANA KA;So;0;L;<circle> 30AB;;;;N;;;;; 32D6;CIRCLED KATAKANA KI;So;0;L;<circle> 30AD;;;;N;;;;; 32D7;CIRCLED KATAKANA KU;So;0;L;<circle> 30AF;;;;N;;;;; 32D8;CIRCLED KATAKANA KE;So;0;L;<circle> 30B1;;;;N;;;;; 32D9;CIRCLED KATAKANA KO;So;0;L;<circle> 30B3;;;;N;;;;; 32DA;CIRCLED KATAKANA SA;So;0;L;<circle> 30B5;;;;N;;;;; 32DB;CIRCLED KATAKANA SI;So;0;L;<circle> 30B7;;;;N;;;;; 32DC;CIRCLED KATAKANA SU;So;0;L;<circle> 30B9;;;;N;;;;; 32DD;CIRCLED KATAKANA SE;So;0;L;<circle> 30BB;;;;N;;;;; 32DE;CIRCLED KATAKANA SO;So;0;L;<circle> 30BD;;;;N;;;;; 32DF;CIRCLED KATAKANA TA;So;0;L;<circle> 30BF;;;;N;;;;; 32E0;CIRCLED KATAKANA TI;So;0;L;<circle> 30C1;;;;N;;;;; 32E1;CIRCLED KATAKANA TU;So;0;L;<circle> 30C4;;;;N;;;;; 32E2;CIRCLED KATAKANA TE;So;0;L;<circle> 30C6;;;;N;;;;; 32E3;CIRCLED KATAKANA TO;So;0;L;<circle> 30C8;;;;N;;;;; 32E4;CIRCLED KATAKANA NA;So;0;L;<circle> 30CA;;;;N;;;;; 32E5;CIRCLED KATAKANA NI;So;0;L;<circle> 30CB;;;;N;;;;; 32E6;CIRCLED KATAKANA NU;So;0;L;<circle> 30CC;;;;N;;;;; 32E7;CIRCLED KATAKANA NE;So;0;L;<circle> 30CD;;;;N;;;;; 32E8;CIRCLED KATAKANA NO;So;0;L;<circle> 30CE;;;;N;;;;; 32E9;CIRCLED KATAKANA HA;So;0;L;<circle> 30CF;;;;N;;;;; 32EA;CIRCLED KATAKANA HI;So;0;L;<circle> 30D2;;;;N;;;;; 32EB;CIRCLED KATAKANA HU;So;0;L;<circle> 30D5;;;;N;;;;; 32EC;CIRCLED KATAKANA HE;So;0;L;<circle> 30D8;;;;N;;;;; 32ED;CIRCLED KATAKANA HO;So;0;L;<circle> 30DB;;;;N;;;;; 32EE;CIRCLED KATAKANA MA;So;0;L;<circle> 30DE;;;;N;;;;; 32EF;CIRCLED KATAKANA MI;So;0;L;<circle> 30DF;;;;N;;;;; 32F0;CIRCLED KATAKANA MU;So;0;L;<circle> 30E0;;;;N;;;;; 32F1;CIRCLED KATAKANA ME;So;0;L;<circle> 30E1;;;;N;;;;; 32F2;CIRCLED KATAKANA MO;So;0;L;<circle> 30E2;;;;N;;;;; 32F3;CIRCLED KATAKANA YA;So;0;L;<circle> 30E4;;;;N;;;;; 32F4;CIRCLED KATAKANA YU;So;0;L;<circle> 30E6;;;;N;;;;; 32F5;CIRCLED KATAKANA YO;So;0;L;<circle> 30E8;;;;N;;;;; 32F6;CIRCLED KATAKANA RA;So;0;L;<circle> 30E9;;;;N;;;;; 32F7;CIRCLED KATAKANA RI;So;0;L;<circle> 30EA;;;;N;;;;; 32F8;CIRCLED KATAKANA RU;So;0;L;<circle> 30EB;;;;N;;;;; 32F9;CIRCLED KATAKANA RE;So;0;L;<circle> 30EC;;;;N;;;;; 32FA;CIRCLED KATAKANA RO;So;0;L;<circle> 30ED;;;;N;;;;; 32FB;CIRCLED KATAKANA WA;So;0;L;<circle> 30EF;;;;N;;;;; 32FC;CIRCLED KATAKANA WI;So;0;L;<circle> 30F0;;;;N;;;;; 32FD;CIRCLED KATAKANA WE;So;0;L;<circle> 30F1;;;;N;;;;; 32FE;CIRCLED KATAKANA WO;So;0;L;<circle> 30F2;;;;N;;;;; 3300;SQUARE APAATO;So;0;L;<square> 30A2 30D1 30FC 30C8;;;;N;SQUARED APAATO;;;; 3301;SQUARE ARUHUA;So;0;L;<square> 30A2 30EB 30D5 30A1;;;;N;SQUARED ARUHUA;;;; 3302;SQUARE ANPEA;So;0;L;<square> 30A2 30F3 30DA 30A2;;;;N;SQUARED ANPEA;;;; 3303;SQUARE AARU;So;0;L;<square> 30A2 30FC 30EB;;;;N;SQUARED AARU;;;; 3304;SQUARE ININGU;So;0;L;<square> 30A4 30CB 30F3 30B0;;;;N;SQUARED ININGU;;;; 3305;SQUARE INTI;So;0;L;<square> 30A4 30F3 30C1;;;;N;SQUARED INTI;;;; 3306;SQUARE UON;So;0;L;<square> 30A6 30A9 30F3;;;;N;SQUARED UON;;;; 3307;SQUARE ESUKUUDO;So;0;L;<square> 30A8 30B9 30AF 30FC 30C9;;;;N;SQUARED ESUKUUDO;;;; 3308;SQUARE EEKAA;So;0;L;<square> 30A8 30FC 30AB 30FC;;;;N;SQUARED EEKAA;;;; 3309;SQUARE ONSU;So;0;L;<square> 30AA 30F3 30B9;;;;N;SQUARED ONSU;;;; 330A;SQUARE OOMU;So;0;L;<square> 30AA 30FC 30E0;;;;N;SQUARED OOMU;;;; 330B;SQUARE KAIRI;So;0;L;<square> 30AB 30A4 30EA;;;;N;SQUARED KAIRI;;;; 330C;SQUARE KARATTO;So;0;L;<square> 30AB 30E9 30C3 30C8;;;;N;SQUARED KARATTO;;;; 330D;SQUARE KARORII;So;0;L;<square> 30AB 30ED 30EA 30FC;;;;N;SQUARED KARORII;;;; 330E;SQUARE GARON;So;0;L;<square> 30AC 30ED 30F3;;;;N;SQUARED GARON;;;; 330F;SQUARE GANMA;So;0;L;<square> 30AC 30F3 30DE;;;;N;SQUARED GANMA;;;; 3310;SQUARE GIGA;So;0;L;<square> 30AE 30AC;;;;N;SQUARED GIGA;;;; 3311;SQUARE GINII;So;0;L;<square> 30AE 30CB 30FC;;;;N;SQUARED GINII;;;; 3312;SQUARE KYURII;So;0;L;<square> 30AD 30E5 30EA 30FC;;;;N;SQUARED KYURII;;;; 3313;SQUARE GIRUDAA;So;0;L;<square> 30AE 30EB 30C0 30FC;;;;N;SQUARED GIRUDAA;;;; 3314;SQUARE KIRO;So;0;L;<square> 30AD 30ED;;;;N;SQUARED KIRO;;;; 3315;SQUARE KIROGURAMU;So;0;L;<square> 30AD 30ED 30B0 30E9 30E0;;;;N;SQUARED KIROGURAMU;;;; 3316;SQUARE KIROMEETORU;So;0;L;<square> 30AD 30ED 30E1 30FC 30C8 30EB;;;;N;SQUARED KIROMEETORU;;;; 3317;SQUARE KIROWATTO;So;0;L;<square> 30AD 30ED 30EF 30C3 30C8;;;;N;SQUARED KIROWATTO;;;; 3318;SQUARE GURAMU;So;0;L;<square> 30B0 30E9 30E0;;;;N;SQUARED GURAMU;;;; 3319;SQUARE GURAMUTON;So;0;L;<square> 30B0 30E9 30E0 30C8 30F3;;;;N;SQUARED GURAMUTON;;;; 331A;SQUARE KURUZEIRO;So;0;L;<square> 30AF 30EB 30BC 30A4 30ED;;;;N;SQUARED KURUZEIRO;;;; 331B;SQUARE KUROONE;So;0;L;<square> 30AF 30ED 30FC 30CD;;;;N;SQUARED KUROONE;;;; 331C;SQUARE KEESU;So;0;L;<square> 30B1 30FC 30B9;;;;N;SQUARED KEESU;;;; 331D;SQUARE KORUNA;So;0;L;<square> 30B3 30EB 30CA;;;;N;SQUARED KORUNA;;;; 331E;SQUARE KOOPO;So;0;L;<square> 30B3 30FC 30DD;;;;N;SQUARED KOOPO;;;; 331F;SQUARE SAIKURU;So;0;L;<square> 30B5 30A4 30AF 30EB;;;;N;SQUARED SAIKURU;;;; 3320;SQUARE SANTIIMU;So;0;L;<square> 30B5 30F3 30C1 30FC 30E0;;;;N;SQUARED SANTIIMU;;;; 3321;SQUARE SIRINGU;So;0;L;<square> 30B7 30EA 30F3 30B0;;;;N;SQUARED SIRINGU;;;; 3322;SQUARE SENTI;So;0;L;<square> 30BB 30F3 30C1;;;;N;SQUARED SENTI;;;; 3323;SQUARE SENTO;So;0;L;<square> 30BB 30F3 30C8;;;;N;SQUARED SENTO;;;; 3324;SQUARE DAASU;So;0;L;<square> 30C0 30FC 30B9;;;;N;SQUARED DAASU;;;; 3325;SQUARE DESI;So;0;L;<square> 30C7 30B7;;;;N;SQUARED DESI;;;; 3326;SQUARE DORU;So;0;L;<square> 30C9 30EB;;;;N;SQUARED DORU;;;; 3327;SQUARE TON;So;0;L;<square> 30C8 30F3;;;;N;SQUARED TON;;;; 3328;SQUARE NANO;So;0;L;<square> 30CA 30CE;;;;N;SQUARED NANO;;;; 3329;SQUARE NOTTO;So;0;L;<square> 30CE 30C3 30C8;;;;N;SQUARED NOTTO;;;; 332A;SQUARE HAITU;So;0;L;<square> 30CF 30A4 30C4;;;;N;SQUARED HAITU;;;; 332B;SQUARE PAASENTO;So;0;L;<square> 30D1 30FC 30BB 30F3 30C8;;;;N;SQUARED PAASENTO;;;; 332C;SQUARE PAATU;So;0;L;<square> 30D1 30FC 30C4;;;;N;SQUARED PAATU;;;; 332D;SQUARE BAARERU;So;0;L;<square> 30D0 30FC 30EC 30EB;;;;N;SQUARED BAARERU;;;; 332E;SQUARE PIASUTORU;So;0;L;<square> 30D4 30A2 30B9 30C8 30EB;;;;N;SQUARED PIASUTORU;;;; 332F;SQUARE PIKURU;So;0;L;<square> 30D4 30AF 30EB;;;;N;SQUARED PIKURU;;;; 3330;SQUARE PIKO;So;0;L;<square> 30D4 30B3;;;;N;SQUARED PIKO;;;; 3331;SQUARE BIRU;So;0;L;<square> 30D3 30EB;;;;N;SQUARED BIRU;;;; 3332;SQUARE HUARADDO;So;0;L;<square> 30D5 30A1 30E9 30C3 30C9;;;;N;SQUARED HUARADDO;;;; 3333;SQUARE HUIITO;So;0;L;<square> 30D5 30A3 30FC 30C8;;;;N;SQUARED HUIITO;;;; 3334;SQUARE BUSSYERU;So;0;L;<square> 30D6 30C3 30B7 30A7 30EB;;;;N;SQUARED BUSSYERU;;;; 3335;SQUARE HURAN;So;0;L;<square> 30D5 30E9 30F3;;;;N;SQUARED HURAN;;;; 3336;SQUARE HEKUTAARU;So;0;L;<square> 30D8 30AF 30BF 30FC 30EB;;;;N;SQUARED HEKUTAARU;;;; 3337;SQUARE PESO;So;0;L;<square> 30DA 30BD;;;;N;SQUARED PESO;;;; 3338;SQUARE PENIHI;So;0;L;<square> 30DA 30CB 30D2;;;;N;SQUARED PENIHI;;;; 3339;SQUARE HERUTU;So;0;L;<square> 30D8 30EB 30C4;;;;N;SQUARED HERUTU;;;; 333A;SQUARE PENSU;So;0;L;<square> 30DA 30F3 30B9;;;;N;SQUARED PENSU;;;; 333B;SQUARE PEEZI;So;0;L;<square> 30DA 30FC 30B8;;;;N;SQUARED PEEZI;;;; 333C;SQUARE BEETA;So;0;L;<square> 30D9 30FC 30BF;;;;N;SQUARED BEETA;;;; 333D;SQUARE POINTO;So;0;L;<square> 30DD 30A4 30F3 30C8;;;;N;SQUARED POINTO;;;; 333E;SQUARE BORUTO;So;0;L;<square> 30DC 30EB 30C8;;;;N;SQUARED BORUTO;;;; 333F;SQUARE HON;So;0;L;<square> 30DB 30F3;;;;N;SQUARED HON;;;; 3340;SQUARE PONDO;So;0;L;<square> 30DD 30F3 30C9;;;;N;SQUARED PONDO;;;; 3341;SQUARE HOORU;So;0;L;<square> 30DB 30FC 30EB;;;;N;SQUARED HOORU;;;; 3342;SQUARE HOON;So;0;L;<square> 30DB 30FC 30F3;;;;N;SQUARED HOON;;;; 3343;SQUARE MAIKURO;So;0;L;<square> 30DE 30A4 30AF 30ED;;;;N;SQUARED MAIKURO;;;; 3344;SQUARE MAIRU;So;0;L;<square> 30DE 30A4 30EB;;;;N;SQUARED MAIRU;;;; 3345;SQUARE MAHHA;So;0;L;<square> 30DE 30C3 30CF;;;;N;SQUARED MAHHA;;;; 3346;SQUARE MARUKU;So;0;L;<square> 30DE 30EB 30AF;;;;N;SQUARED MARUKU;;;; 3347;SQUARE MANSYON;So;0;L;<square> 30DE 30F3 30B7 30E7 30F3;;;;N;SQUARED MANSYON;;;; 3348;SQUARE MIKURON;So;0;L;<square> 30DF 30AF 30ED 30F3;;;;N;SQUARED MIKURON;;;; 3349;SQUARE MIRI;So;0;L;<square> 30DF 30EA;;;;N;SQUARED MIRI;;;; 334A;SQUARE MIRIBAARU;So;0;L;<square> 30DF 30EA 30D0 30FC 30EB;;;;N;SQUARED MIRIBAARU;;;; 334B;SQUARE MEGA;So;0;L;<square> 30E1 30AC;;;;N;SQUARED MEGA;;;; 334C;SQUARE MEGATON;So;0;L;<square> 30E1 30AC 30C8 30F3;;;;N;SQUARED MEGATON;;;; 334D;SQUARE MEETORU;So;0;L;<square> 30E1 30FC 30C8 30EB;;;;N;SQUARED MEETORU;;;; 334E;SQUARE YAADO;So;0;L;<square> 30E4 30FC 30C9;;;;N;SQUARED YAADO;;;; 334F;SQUARE YAARU;So;0;L;<square> 30E4 30FC 30EB;;;;N;SQUARED YAARU;;;; 3350;SQUARE YUAN;So;0;L;<square> 30E6 30A2 30F3;;;;N;SQUARED YUAN;;;; 3351;SQUARE RITTORU;So;0;L;<square> 30EA 30C3 30C8 30EB;;;;N;SQUARED RITTORU;;;; 3352;SQUARE RIRA;So;0;L;<square> 30EA 30E9;;;;N;SQUARED RIRA;;;; 3353;SQUARE RUPII;So;0;L;<square> 30EB 30D4 30FC;;;;N;SQUARED RUPII;;;; 3354;SQUARE RUUBURU;So;0;L;<square> 30EB 30FC 30D6 30EB;;;;N;SQUARED RUUBURU;;;; 3355;SQUARE REMU;So;0;L;<square> 30EC 30E0;;;;N;SQUARED REMU;;;; 3356;SQUARE RENTOGEN;So;0;L;<square> 30EC 30F3 30C8 30B2 30F3;;;;N;SQUARED RENTOGEN;;;; 3357;SQUARE WATTO;So;0;L;<square> 30EF 30C3 30C8;;;;N;SQUARED WATTO;;;; 3358;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR ZERO;So;0;L;<compat> 0030 70B9;;;;N;;;;; 3359;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR ONE;So;0;L;<compat> 0031 70B9;;;;N;;;;; 335A;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWO;So;0;L;<compat> 0032 70B9;;;;N;;;;; 335B;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR THREE;So;0;L;<compat> 0033 70B9;;;;N;;;;; 335C;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FOUR;So;0;L;<compat> 0034 70B9;;;;N;;;;; 335D;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FIVE;So;0;L;<compat> 0035 70B9;;;;N;;;;; 335E;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SIX;So;0;L;<compat> 0036 70B9;;;;N;;;;; 335F;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SEVEN;So;0;L;<compat> 0037 70B9;;;;N;;;;; 3360;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR EIGHT;So;0;L;<compat> 0038 70B9;;;;N;;;;; 3361;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR NINE;So;0;L;<compat> 0039 70B9;;;;N;;;;; 3362;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TEN;So;0;L;<compat> 0031 0030 70B9;;;;N;;;;; 3363;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR ELEVEN;So;0;L;<compat> 0031 0031 70B9;;;;N;;;;; 3364;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWELVE;So;0;L;<compat> 0031 0032 70B9;;;;N;;;;; 3365;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR THIRTEEN;So;0;L;<compat> 0031 0033 70B9;;;;N;;;;; 3366;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FOURTEEN;So;0;L;<compat> 0031 0034 70B9;;;;N;;;;; 3367;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FIFTEEN;So;0;L;<compat> 0031 0035 70B9;;;;N;;;;; 3368;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SIXTEEN;So;0;L;<compat> 0031 0036 70B9;;;;N;;;;; 3369;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SEVENTEEN;So;0;L;<compat> 0031 0037 70B9;;;;N;;;;; 336A;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR EIGHTEEN;So;0;L;<compat> 0031 0038 70B9;;;;N;;;;; 336B;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR NINETEEN;So;0;L;<compat> 0031 0039 70B9;;;;N;;;;; 336C;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY;So;0;L;<compat> 0032 0030 70B9;;;;N;;;;; 336D;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-ONE;So;0;L;<compat> 0032 0031 70B9;;;;N;;;;; 336E;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-TWO;So;0;L;<compat> 0032 0032 70B9;;;;N;;;;; 336F;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-THREE;So;0;L;<compat> 0032 0033 70B9;;;;N;;;;; 3370;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-FOUR;So;0;L;<compat> 0032 0034 70B9;;;;N;;;;; 3371;SQUARE HPA;So;0;L;<square> 0068 0050 0061;;;;N;;;;; 3372;SQUARE DA;So;0;L;<square> 0064 0061;;;;N;;;;; 3373;SQUARE AU;So;0;L;<square> 0041 0055;;;;N;;;;; 3374;SQUARE BAR;So;0;L;<square> 0062 0061 0072;;;;N;;;;; 3375;SQUARE OV;So;0;L;<square> 006F 0056;;;;N;;;;; 3376;SQUARE PC;So;0;L;<square> 0070 0063;;;;N;;;;; 3377;SQUARE DM;So;0;ON;<square> 0064 006D;;;;N;;;;; 3378;SQUARE DM SQUARED;So;0;ON;<square> 0064 006D 00B2;;;;N;;;;; 3379;SQUARE DM CUBED;So;0;ON;<square> 0064 006D 00B3;;;;N;;;;; 337A;SQUARE IU;So;0;ON;<square> 0049 0055;;;;N;;;;; 337B;SQUARE ERA NAME HEISEI;So;0;L;<square> 5E73 6210;;;;N;SQUARED TWO IDEOGRAPHS ERA NAME HEISEI;;;; 337C;SQUARE ERA NAME SYOUWA;So;0;L;<square> 662D 548C;;;;N;SQUARED TWO IDEOGRAPHS ERA NAME SYOUWA;;;; 337D;SQUARE ERA NAME TAISYOU;So;0;L;<square> 5927 6B63;;;;N;SQUARED TWO IDEOGRAPHS ERA NAME TAISYOU;;;; 337E;SQUARE ERA NAME MEIZI;So;0;L;<square> 660E 6CBB;;;;N;SQUARED TWO IDEOGRAPHS ERA NAME MEIZI;;;; 337F;SQUARE CORPORATION;So;0;L;<square> 682A 5F0F 4F1A 793E;;;;N;SQUARED FOUR IDEOGRAPHS CORPORATION;;;; 3380;SQUARE PA AMPS;So;0;L;<square> 0070 0041;;;;N;SQUARED PA AMPS;;;; 3381;SQUARE NA;So;0;L;<square> 006E 0041;;;;N;SQUARED NA;;;; 3382;SQUARE MU A;So;0;L;<square> 03BC 0041;;;;N;SQUARED MU A;;;; 3383;SQUARE MA;So;0;L;<square> 006D 0041;;;;N;SQUARED MA;;;; 3384;SQUARE KA;So;0;L;<square> 006B 0041;;;;N;SQUARED KA;;;; 3385;SQUARE KB;So;0;L;<square> 004B 0042;;;;N;SQUARED KB;;;; 3386;SQUARE MB;So;0;L;<square> 004D 0042;;;;N;SQUARED MB;;;; 3387;SQUARE GB;So;0;L;<square> 0047 0042;;;;N;SQUARED GB;;;; 3388;SQUARE CAL;So;0;L;<square> 0063 0061 006C;;;;N;SQUARED CAL;;;; 3389;SQUARE KCAL;So;0;L;<square> 006B 0063 0061 006C;;;;N;SQUARED KCAL;;;; 338A;SQUARE PF;So;0;L;<square> 0070 0046;;;;N;SQUARED PF;;;; 338B;SQUARE NF;So;0;L;<square> 006E 0046;;;;N;SQUARED NF;;;; 338C;SQUARE MU F;So;0;L;<square> 03BC 0046;;;;N;SQUARED MU F;;;; 338D;SQUARE MU G;So;0;L;<square> 03BC 0067;;;;N;SQUARED MU G;;;; 338E;SQUARE MG;So;0;L;<square> 006D 0067;;;;N;SQUARED MG;;;; 338F;SQUARE KG;So;0;L;<square> 006B 0067;;;;N;SQUARED KG;;;; 3390;SQUARE HZ;So;0;L;<square> 0048 007A;;;;N;SQUARED HZ;;;; 3391;SQUARE KHZ;So;0;L;<square> 006B 0048 007A;;;;N;SQUARED KHZ;;;; 3392;SQUARE MHZ;So;0;L;<square> 004D 0048 007A;;;;N;SQUARED MHZ;;;; 3393;SQUARE GHZ;So;0;L;<square> 0047 0048 007A;;;;N;SQUARED GHZ;;;; 3394;SQUARE THZ;So;0;L;<square> 0054 0048 007A;;;;N;SQUARED THZ;;;; 3395;SQUARE MU L;So;0;L;<square> 03BC 2113;;;;N;SQUARED MU L;;;; 3396;SQUARE ML;So;0;L;<square> 006D 2113;;;;N;SQUARED ML;;;; 3397;SQUARE DL;So;0;L;<square> 0064 2113;;;;N;SQUARED DL;;;; 3398;SQUARE KL;So;0;L;<square> 006B 2113;;;;N;SQUARED KL;;;; 3399;SQUARE FM;So;0;L;<square> 0066 006D;;;;N;SQUARED FM;;;; 339A;SQUARE NM;So;0;L;<square> 006E 006D;;;;N;SQUARED NM;;;; 339B;SQUARE MU M;So;0;L;<square> 03BC 006D;;;;N;SQUARED MU M;;;; 339C;SQUARE MM;So;0;L;<square> 006D 006D;;;;N;SQUARED MM;;;; 339D;SQUARE CM;So;0;L;<square> 0063 006D;;;;N;SQUARED CM;;;; 339E;SQUARE KM;So;0;L;<square> 006B 006D;;;;N;SQUARED KM;;;; 339F;SQUARE MM SQUARED;So;0;L;<square> 006D 006D 00B2;;;;N;SQUARED MM SQUARED;;;; 33A0;SQUARE CM SQUARED;So;0;L;<square> 0063 006D 00B2;;;;N;SQUARED CM SQUARED;;;; 33A1;SQUARE M SQUARED;So;0;L;<square> 006D 00B2;;;;N;SQUARED M SQUARED;;;; 33A2;SQUARE KM SQUARED;So;0;L;<square> 006B 006D 00B2;;;;N;SQUARED KM SQUARED;;;; 33A3;SQUARE MM CUBED;So;0;L;<square> 006D 006D 00B3;;;;N;SQUARED MM CUBED;;;; 33A4;SQUARE CM CUBED;So;0;L;<square> 0063 006D 00B3;;;;N;SQUARED CM CUBED;;;; 33A5;SQUARE M CUBED;So;0;L;<square> 006D 00B3;;;;N;SQUARED M CUBED;;;; 33A6;SQUARE KM CUBED;So;0;L;<square> 006B 006D 00B3;;;;N;SQUARED KM CUBED;;;; 33A7;SQUARE M OVER S;So;0;L;<square> 006D 2215 0073;;;;N;SQUARED M OVER S;;;; 33A8;SQUARE M OVER S SQUARED;So;0;L;<square> 006D 2215 0073 00B2;;;;N;SQUARED M OVER S SQUARED;;;; 33A9;SQUARE PA;So;0;L;<square> 0050 0061;;;;N;SQUARED PA;;;; 33AA;SQUARE KPA;So;0;L;<square> 006B 0050 0061;;;;N;SQUARED KPA;;;; 33AB;SQUARE MPA;So;0;L;<square> 004D 0050 0061;;;;N;SQUARED MPA;;;; 33AC;SQUARE GPA;So;0;L;<square> 0047 0050 0061;;;;N;SQUARED GPA;;;; 33AD;SQUARE RAD;So;0;L;<square> 0072 0061 0064;;;;N;SQUARED RAD;;;; 33AE;SQUARE RAD OVER S;So;0;L;<square> 0072 0061 0064 2215 0073;;;;N;SQUARED RAD OVER S;;;; 33AF;SQUARE RAD OVER S SQUARED;So;0;L;<square> 0072 0061 0064 2215 0073 00B2;;;;N;SQUARED RAD OVER S SQUARED;;;; 33B0;SQUARE PS;So;0;L;<square> 0070 0073;;;;N;SQUARED PS;;;; 33B1;SQUARE NS;So;0;L;<square> 006E 0073;;;;N;SQUARED NS;;;; 33B2;SQUARE MU S;So;0;L;<square> 03BC 0073;;;;N;SQUARED MU S;;;; 33B3;SQUARE MS;So;0;L;<square> 006D 0073;;;;N;SQUARED MS;;;; 33B4;SQUARE PV;So;0;L;<square> 0070 0056;;;;N;SQUARED PV;;;; 33B5;SQUARE NV;So;0;L;<square> 006E 0056;;;;N;SQUARED NV;;;; 33B6;SQUARE MU V;So;0;L;<square> 03BC 0056;;;;N;SQUARED MU V;;;; 33B7;SQUARE MV;So;0;L;<square> 006D 0056;;;;N;SQUARED MV;;;; 33B8;SQUARE KV;So;0;L;<square> 006B 0056;;;;N;SQUARED KV;;;; 33B9;SQUARE MV MEGA;So;0;L;<square> 004D 0056;;;;N;SQUARED MV MEGA;;;; 33BA;SQUARE PW;So;0;L;<square> 0070 0057;;;;N;SQUARED PW;;;; 33BB;SQUARE NW;So;0;L;<square> 006E 0057;;;;N;SQUARED NW;;;; 33BC;SQUARE MU W;So;0;L;<square> 03BC 0057;;;;N;SQUARED MU W;;;; 33BD;SQUARE MW;So;0;L;<square> 006D 0057;;;;N;SQUARED MW;;;; 33BE;SQUARE KW;So;0;L;<square> 006B 0057;;;;N;SQUARED KW;;;; 33BF;SQUARE MW MEGA;So;0;L;<square> 004D 0057;;;;N;SQUARED MW MEGA;;;; 33C0;SQUARE K OHM;So;0;L;<square> 006B 03A9;;;;N;SQUARED K OHM;;;; 33C1;SQUARE M OHM;So;0;L;<square> 004D 03A9;;;;N;SQUARED M OHM;;;; 33C2;SQUARE AM;So;0;L;<square> 0061 002E 006D 002E;;;;N;SQUARED AM;;;; 33C3;SQUARE BQ;So;0;L;<square> 0042 0071;;;;N;SQUARED BQ;;;; 33C4;SQUARE CC;So;0;L;<square> 0063 0063;;;;N;SQUARED CC;;;; 33C5;SQUARE CD;So;0;L;<square> 0063 0064;;;;N;SQUARED CD;;;; 33C6;SQUARE C OVER KG;So;0;L;<square> 0043 2215 006B 0067;;;;N;SQUARED C OVER KG;;;; 33C7;SQUARE CO;So;0;L;<square> 0043 006F 002E;;;;N;SQUARED CO;;;; 33C8;SQUARE DB;So;0;L;<square> 0064 0042;;;;N;SQUARED DB;;;; 33C9;SQUARE GY;So;0;L;<square> 0047 0079;;;;N;SQUARED GY;;;; 33CA;SQUARE HA;So;0;L;<square> 0068 0061;;;;N;SQUARED HA;;;; 33CB;SQUARE HP;So;0;L;<square> 0048 0050;;;;N;SQUARED HP;;;; 33CC;SQUARE IN;So;0;L;<square> 0069 006E;;;;N;SQUARED IN;;;; 33CD;SQUARE KK;So;0;L;<square> 004B 004B;;;;N;SQUARED KK;;;; 33CE;SQUARE KM CAPITAL;So;0;L;<square> 004B 004D;;;;N;SQUARED KM CAPITAL;;;; 33CF;SQUARE KT;So;0;L;<square> 006B 0074;;;;N;SQUARED KT;;;; 33D0;SQUARE LM;So;0;L;<square> 006C 006D;;;;N;SQUARED LM;;;; 33D1;SQUARE LN;So;0;L;<square> 006C 006E;;;;N;SQUARED LN;;;; 33D2;SQUARE LOG;So;0;L;<square> 006C 006F 0067;;;;N;SQUARED LOG;;;; 33D3;SQUARE LX;So;0;L;<square> 006C 0078;;;;N;SQUARED LX;;;; 33D4;SQUARE MB SMALL;So;0;L;<square> 006D 0062;;;;N;SQUARED MB SMALL;;;; 33D5;SQUARE MIL;So;0;L;<square> 006D 0069 006C;;;;N;SQUARED MIL;;;; 33D6;SQUARE MOL;So;0;L;<square> 006D 006F 006C;;;;N;SQUARED MOL;;;; 33D7;SQUARE PH;So;0;L;<square> 0050 0048;;;;N;SQUARED PH;;;; 33D8;SQUARE PM;So;0;L;<square> 0070 002E 006D 002E;;;;N;SQUARED PM;;;; 33D9;SQUARE PPM;So;0;L;<square> 0050 0050 004D;;;;N;SQUARED PPM;;;; 33DA;SQUARE PR;So;0;L;<square> 0050 0052;;;;N;SQUARED PR;;;; 33DB;SQUARE SR;So;0;L;<square> 0073 0072;;;;N;SQUARED SR;;;; 33DC;SQUARE SV;So;0;L;<square> 0053 0076;;;;N;SQUARED SV;;;; 33DD;SQUARE WB;So;0;L;<square> 0057 0062;;;;N;SQUARED WB;;;; 33DE;SQUARE V OVER M;So;0;ON;<square> 0056 2215 006D;;;;N;;;;; 33DF;SQUARE A OVER M;So;0;ON;<square> 0041 2215 006D;;;;N;;;;; 33E0;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY ONE;So;0;L;<compat> 0031 65E5;;;;N;;;;; 33E1;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWO;So;0;L;<compat> 0032 65E5;;;;N;;;;; 33E2;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THREE;So;0;L;<compat> 0033 65E5;;;;N;;;;; 33E3;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FOUR;So;0;L;<compat> 0034 65E5;;;;N;;;;; 33E4;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FIVE;So;0;L;<compat> 0035 65E5;;;;N;;;;; 33E5;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SIX;So;0;L;<compat> 0036 65E5;;;;N;;;;; 33E6;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SEVEN;So;0;L;<compat> 0037 65E5;;;;N;;;;; 33E7;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY EIGHT;So;0;L;<compat> 0038 65E5;;;;N;;;;; 33E8;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY NINE;So;0;L;<compat> 0039 65E5;;;;N;;;;; 33E9;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TEN;So;0;L;<compat> 0031 0030 65E5;;;;N;;;;; 33EA;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY ELEVEN;So;0;L;<compat> 0031 0031 65E5;;;;N;;;;; 33EB;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWELVE;So;0;L;<compat> 0031 0032 65E5;;;;N;;;;; 33EC;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THIRTEEN;So;0;L;<compat> 0031 0033 65E5;;;;N;;;;; 33ED;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FOURTEEN;So;0;L;<compat> 0031 0034 65E5;;;;N;;;;; 33EE;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FIFTEEN;So;0;L;<compat> 0031 0035 65E5;;;;N;;;;; 33EF;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SIXTEEN;So;0;L;<compat> 0031 0036 65E5;;;;N;;;;; 33F0;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SEVENTEEN;So;0;L;<compat> 0031 0037 65E5;;;;N;;;;; 33F1;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY EIGHTEEN;So;0;L;<compat> 0031 0038 65E5;;;;N;;;;; 33F2;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY NINETEEN;So;0;L;<compat> 0031 0039 65E5;;;;N;;;;; 33F3;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY;So;0;L;<compat> 0032 0030 65E5;;;;N;;;;; 33F4;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-ONE;So;0;L;<compat> 0032 0031 65E5;;;;N;;;;; 33F5;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-TWO;So;0;L;<compat> 0032 0032 65E5;;;;N;;;;; 33F6;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-THREE;So;0;L;<compat> 0032 0033 65E5;;;;N;;;;; 33F7;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-FOUR;So;0;L;<compat> 0032 0034 65E5;;;;N;;;;; 33F8;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-FIVE;So;0;L;<compat> 0032 0035 65E5;;;;N;;;;; 33F9;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-SIX;So;0;L;<compat> 0032 0036 65E5;;;;N;;;;; 33FA;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-SEVEN;So;0;L;<compat> 0032 0037 65E5;;;;N;;;;; 33FB;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-EIGHT;So;0;L;<compat> 0032 0038 65E5;;;;N;;;;; 33FC;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-NINE;So;0;L;<compat> 0032 0039 65E5;;;;N;;;;; 33FD;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THIRTY;So;0;L;<compat> 0033 0030 65E5;;;;N;;;;; 33FE;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THIRTY-ONE;So;0;L;<compat> 0033 0031 65E5;;;;N;;;;; 33FF;SQUARE GAL;So;0;ON;<square> 0067 0061 006C;;;;N;;;;; 3400;<CJK Ideograph Extension A, First>;Lo;0;L;;;;;N;;;;; 4DB5;<CJK Ideograph Extension A, Last>;Lo;0;L;;;;;N;;;;; 4DC0;HEXAGRAM FOR THE CREATIVE HEAVEN;So;0;ON;;;;;N;;;;; 4DC1;HEXAGRAM FOR THE RECEPTIVE EARTH;So;0;ON;;;;;N;;;;; 4DC2;HEXAGRAM FOR DIFFICULTY AT THE BEGINNING;So;0;ON;;;;;N;;;;; 4DC3;HEXAGRAM FOR YOUTHFUL FOLLY;So;0;ON;;;;;N;;;;; 4DC4;HEXAGRAM FOR WAITING;So;0;ON;;;;;N;;;;; 4DC5;HEXAGRAM FOR CONFLICT;So;0;ON;;;;;N;;;;; 4DC6;HEXAGRAM FOR THE ARMY;So;0;ON;;;;;N;;;;; 4DC7;HEXAGRAM FOR HOLDING TOGETHER;So;0;ON;;;;;N;;;;; 4DC8;HEXAGRAM FOR SMALL TAMING;So;0;ON;;;;;N;;;;; 4DC9;HEXAGRAM FOR TREADING;So;0;ON;;;;;N;;;;; 4DCA;HEXAGRAM FOR PEACE;So;0;ON;;;;;N;;;;; 4DCB;HEXAGRAM FOR STANDSTILL;So;0;ON;;;;;N;;;;; 4DCC;HEXAGRAM FOR FELLOWSHIP;So;0;ON;;;;;N;;;;; 4DCD;HEXAGRAM FOR GREAT POSSESSION;So;0;ON;;;;;N;;;;; 4DCE;HEXAGRAM FOR MODESTY;So;0;ON;;;;;N;;;;; 4DCF;HEXAGRAM FOR ENTHUSIASM;So;0;ON;;;;;N;;;;; 4DD0;HEXAGRAM FOR FOLLOWING;So;0;ON;;;;;N;;;;; 4DD1;HEXAGRAM FOR WORK ON THE DECAYED;So;0;ON;;;;;N;;;;; 4DD2;HEXAGRAM FOR APPROACH;So;0;ON;;;;;N;;;;; 4DD3;HEXAGRAM FOR CONTEMPLATION;So;0;ON;;;;;N;;;;; 4DD4;HEXAGRAM FOR BITING THROUGH;So;0;ON;;;;;N;;;;; 4DD5;HEXAGRAM FOR GRACE;So;0;ON;;;;;N;;;;; 4DD6;HEXAGRAM FOR SPLITTING APART;So;0;ON;;;;;N;;;;; 4DD7;HEXAGRAM FOR RETURN;So;0;ON;;;;;N;;;;; 4DD8;HEXAGRAM FOR INNOCENCE;So;0;ON;;;;;N;;;;; 4DD9;HEXAGRAM FOR GREAT TAMING;So;0;ON;;;;;N;;;;; 4DDA;HEXAGRAM FOR MOUTH CORNERS;So;0;ON;;;;;N;;;;; 4DDB;HEXAGRAM FOR GREAT PREPONDERANCE;So;0;ON;;;;;N;;;;; 4DDC;HEXAGRAM FOR THE ABYSMAL WATER;So;0;ON;;;;;N;;;;; 4DDD;HEXAGRAM FOR THE CLINGING FIRE;So;0;ON;;;;;N;;;;; 4DDE;HEXAGRAM FOR INFLUENCE;So;0;ON;;;;;N;;;;; 4DDF;HEXAGRAM FOR DURATION;So;0;ON;;;;;N;;;;; 4DE0;HEXAGRAM FOR RETREAT;So;0;ON;;;;;N;;;;; 4DE1;HEXAGRAM FOR GREAT POWER;So;0;ON;;;;;N;;;;; 4DE2;HEXAGRAM FOR PROGRESS;So;0;ON;;;;;N;;;;; 4DE3;HEXAGRAM FOR DARKENING OF THE LIGHT;So;0;ON;;;;;N;;;;; 4DE4;HEXAGRAM FOR THE FAMILY;So;0;ON;;;;;N;;;;; 4DE5;HEXAGRAM FOR OPPOSITION;So;0;ON;;;;;N;;;;; 4DE6;HEXAGRAM FOR OBSTRUCTION;So;0;ON;;;;;N;;;;; 4DE7;HEXAGRAM FOR DELIVERANCE;So;0;ON;;;;;N;;;;; 4DE8;HEXAGRAM FOR DECREASE;So;0;ON;;;;;N;;;;; 4DE9;HEXAGRAM FOR INCREASE;So;0;ON;;;;;N;;;;; 4DEA;HEXAGRAM FOR BREAKTHROUGH;So;0;ON;;;;;N;;;;; 4DEB;HEXAGRAM FOR COMING TO MEET;So;0;ON;;;;;N;;;;; 4DEC;HEXAGRAM FOR GATHERING TOGETHER;So;0;ON;;;;;N;;;;; 4DED;HEXAGRAM FOR PUSHING UPWARD;So;0;ON;;;;;N;;;;; 4DEE;HEXAGRAM FOR OPPRESSION;So;0;ON;;;;;N;;;;; 4DEF;HEXAGRAM FOR THE WELL;So;0;ON;;;;;N;;;;; 4DF0;HEXAGRAM FOR REVOLUTION;So;0;ON;;;;;N;;;;; 4DF1;HEXAGRAM FOR THE CAULDRON;So;0;ON;;;;;N;;;;; 4DF2;HEXAGRAM FOR THE AROUSING THUNDER;So;0;ON;;;;;N;;;;; 4DF3;HEXAGRAM FOR THE KEEPING STILL MOUNTAIN;So;0;ON;;;;;N;;;;; 4DF4;HEXAGRAM FOR DEVELOPMENT;So;0;ON;;;;;N;;;;; 4DF5;HEXAGRAM FOR THE MARRYING MAIDEN;So;0;ON;;;;;N;;;;; 4DF6;HEXAGRAM FOR ABUNDANCE;So;0;ON;;;;;N;;;;; 4DF7;HEXAGRAM FOR THE WANDERER;So;0;ON;;;;;N;;;;; 4DF8;HEXAGRAM FOR THE GENTLE WIND;So;0;ON;;;;;N;;;;; 4DF9;HEXAGRAM FOR THE JOYOUS LAKE;So;0;ON;;;;;N;;;;; 4DFA;HEXAGRAM FOR DISPERSION;So;0;ON;;;;;N;;;;; 4DFB;HEXAGRAM FOR LIMITATION;So;0;ON;;;;;N;;;;; 4DFC;HEXAGRAM FOR INNER TRUTH;So;0;ON;;;;;N;;;;; 4DFD;HEXAGRAM FOR SMALL PREPONDERANCE;So;0;ON;;;;;N;;;;; 4DFE;HEXAGRAM FOR AFTER COMPLETION;So;0;ON;;;;;N;;;;; 4DFF;HEXAGRAM FOR BEFORE COMPLETION;So;0;ON;;;;;N;;;;; 4E00;<CJK Ideograph, First>;Lo;0;L;;;;;N;;;;; 9FD5;<CJK Ideograph, Last>;Lo;0;L;;;;;N;;;;; A000;YI SYLLABLE IT;Lo;0;L;;;;;N;;;;; A001;YI SYLLABLE IX;Lo;0;L;;;;;N;;;;; A002;YI SYLLABLE I;Lo;0;L;;;;;N;;;;; A003;YI SYLLABLE IP;Lo;0;L;;;;;N;;;;; A004;YI SYLLABLE IET;Lo;0;L;;;;;N;;;;; A005;YI SYLLABLE IEX;Lo;0;L;;;;;N;;;;; A006;YI SYLLABLE IE;Lo;0;L;;;;;N;;;;; A007;YI SYLLABLE IEP;Lo;0;L;;;;;N;;;;; A008;YI SYLLABLE AT;Lo;0;L;;;;;N;;;;; A009;YI SYLLABLE AX;Lo;0;L;;;;;N;;;;; A00A;YI SYLLABLE A;Lo;0;L;;;;;N;;;;; A00B;YI SYLLABLE AP;Lo;0;L;;;;;N;;;;; A00C;YI SYLLABLE UOX;Lo;0;L;;;;;N;;;;; A00D;YI SYLLABLE UO;Lo;0;L;;;;;N;;;;; A00E;YI SYLLABLE UOP;Lo;0;L;;;;;N;;;;; A00F;YI SYLLABLE OT;Lo;0;L;;;;;N;;;;; A010;YI SYLLABLE OX;Lo;0;L;;;;;N;;;;; A011;YI SYLLABLE O;Lo;0;L;;;;;N;;;;; A012;YI SYLLABLE OP;Lo;0;L;;;;;N;;;;; A013;YI SYLLABLE EX;Lo;0;L;;;;;N;;;;; A014;YI SYLLABLE E;Lo;0;L;;;;;N;;;;; A015;YI SYLLABLE WU;Lm;0;L;;;;;N;;;;; A016;YI SYLLABLE BIT;Lo;0;L;;;;;N;;;;; A017;YI SYLLABLE BIX;Lo;0;L;;;;;N;;;;; A018;YI SYLLABLE BI;Lo;0;L;;;;;N;;;;; A019;YI SYLLABLE BIP;Lo;0;L;;;;;N;;;;; A01A;YI SYLLABLE BIET;Lo;0;L;;;;;N;;;;; A01B;YI SYLLABLE BIEX;Lo;0;L;;;;;N;;;;; A01C;YI SYLLABLE BIE;Lo;0;L;;;;;N;;;;; A01D;YI SYLLABLE BIEP;Lo;0;L;;;;;N;;;;; A01E;YI SYLLABLE BAT;Lo;0;L;;;;;N;;;;; A01F;YI SYLLABLE BAX;Lo;0;L;;;;;N;;;;; A020;YI SYLLABLE BA;Lo;0;L;;;;;N;;;;; A021;YI SYLLABLE BAP;Lo;0;L;;;;;N;;;;; A022;YI SYLLABLE BUOX;Lo;0;L;;;;;N;;;;; A023;YI SYLLABLE BUO;Lo;0;L;;;;;N;;;;; A024;YI SYLLABLE BUOP;Lo;0;L;;;;;N;;;;; A025;YI SYLLABLE BOT;Lo;0;L;;;;;N;;;;; A026;YI SYLLABLE BOX;Lo;0;L;;;;;N;;;;; A027;YI SYLLABLE BO;Lo;0;L;;;;;N;;;;; A028;YI SYLLABLE BOP;Lo;0;L;;;;;N;;;;; A029;YI SYLLABLE BEX;Lo;0;L;;;;;N;;;;; A02A;YI SYLLABLE BE;Lo;0;L;;;;;N;;;;; A02B;YI SYLLABLE BEP;Lo;0;L;;;;;N;;;;; A02C;YI SYLLABLE BUT;Lo;0;L;;;;;N;;;;; A02D;YI SYLLABLE BUX;Lo;0;L;;;;;N;;;;; A02E;YI SYLLABLE BU;Lo;0;L;;;;;N;;;;; A02F;YI SYLLABLE BUP;Lo;0;L;;;;;N;;;;; A030;YI SYLLABLE BURX;Lo;0;L;;;;;N;;;;; A031;YI SYLLABLE BUR;Lo;0;L;;;;;N;;;;; A032;YI SYLLABLE BYT;Lo;0;L;;;;;N;;;;; A033;YI SYLLABLE BYX;Lo;0;L;;;;;N;;;;; A034;YI SYLLABLE BY;Lo;0;L;;;;;N;;;;; A035;YI SYLLABLE BYP;Lo;0;L;;;;;N;;;;; A036;YI SYLLABLE BYRX;Lo;0;L;;;;;N;;;;; A037;YI SYLLABLE BYR;Lo;0;L;;;;;N;;;;; A038;YI SYLLABLE PIT;Lo;0;L;;;;;N;;;;; A039;YI SYLLABLE PIX;Lo;0;L;;;;;N;;;;; A03A;YI SYLLABLE PI;Lo;0;L;;;;;N;;;;; A03B;YI SYLLABLE PIP;Lo;0;L;;;;;N;;;;; A03C;YI SYLLABLE PIEX;Lo;0;L;;;;;N;;;;; A03D;YI SYLLABLE PIE;Lo;0;L;;;;;N;;;;; A03E;YI SYLLABLE PIEP;Lo;0;L;;;;;N;;;;; A03F;YI SYLLABLE PAT;Lo;0;L;;;;;N;;;;; A040;YI SYLLABLE PAX;Lo;0;L;;;;;N;;;;; A041;YI SYLLABLE PA;Lo;0;L;;;;;N;;;;; A042;YI SYLLABLE PAP;Lo;0;L;;;;;N;;;;; A043;YI SYLLABLE PUOX;Lo;0;L;;;;;N;;;;; A044;YI SYLLABLE PUO;Lo;0;L;;;;;N;;;;; A045;YI SYLLABLE PUOP;Lo;0;L;;;;;N;;;;; A046;YI SYLLABLE POT;Lo;0;L;;;;;N;;;;; A047;YI SYLLABLE POX;Lo;0;L;;;;;N;;;;; A048;YI SYLLABLE PO;Lo;0;L;;;;;N;;;;; A049;YI SYLLABLE POP;Lo;0;L;;;;;N;;;;; A04A;YI SYLLABLE PUT;Lo;0;L;;;;;N;;;;; A04B;YI SYLLABLE PUX;Lo;0;L;;;;;N;;;;; A04C;YI SYLLABLE PU;Lo;0;L;;;;;N;;;;; A04D;YI SYLLABLE PUP;Lo;0;L;;;;;N;;;;; A04E;YI SYLLABLE PURX;Lo;0;L;;;;;N;;;;; A04F;YI SYLLABLE PUR;Lo;0;L;;;;;N;;;;; A050;YI SYLLABLE PYT;Lo;0;L;;;;;N;;;;; A051;YI SYLLABLE PYX;Lo;0;L;;;;;N;;;;; A052;YI SYLLABLE PY;Lo;0;L;;;;;N;;;;; A053;YI SYLLABLE PYP;Lo;0;L;;;;;N;;;;; A054;YI SYLLABLE PYRX;Lo;0;L;;;;;N;;;;; A055;YI SYLLABLE PYR;Lo;0;L;;;;;N;;;;; A056;YI SYLLABLE BBIT;Lo;0;L;;;;;N;;;;; A057;YI SYLLABLE BBIX;Lo;0;L;;;;;N;;;;; A058;YI SYLLABLE BBI;Lo;0;L;;;;;N;;;;; A059;YI SYLLABLE BBIP;Lo;0;L;;;;;N;;;;; A05A;YI SYLLABLE BBIET;Lo;0;L;;;;;N;;;;; A05B;YI SYLLABLE BBIEX;Lo;0;L;;;;;N;;;;; A05C;YI SYLLABLE BBIE;Lo;0;L;;;;;N;;;;; A05D;YI SYLLABLE BBIEP;Lo;0;L;;;;;N;;;;; A05E;YI SYLLABLE BBAT;Lo;0;L;;;;;N;;;;; A05F;YI SYLLABLE BBAX;Lo;0;L;;;;;N;;;;; A060;YI SYLLABLE BBA;Lo;0;L;;;;;N;;;;; A061;YI SYLLABLE BBAP;Lo;0;L;;;;;N;;;;; A062;YI SYLLABLE BBUOX;Lo;0;L;;;;;N;;;;; A063;YI SYLLABLE BBUO;Lo;0;L;;;;;N;;;;; A064;YI SYLLABLE BBUOP;Lo;0;L;;;;;N;;;;; A065;YI SYLLABLE BBOT;Lo;0;L;;;;;N;;;;; A066;YI SYLLABLE BBOX;Lo;0;L;;;;;N;;;;; A067;YI SYLLABLE BBO;Lo;0;L;;;;;N;;;;; A068;YI SYLLABLE BBOP;Lo;0;L;;;;;N;;;;; A069;YI SYLLABLE BBEX;Lo;0;L;;;;;N;;;;; A06A;YI SYLLABLE BBE;Lo;0;L;;;;;N;;;;; A06B;YI SYLLABLE BBEP;Lo;0;L;;;;;N;;;;; A06C;YI SYLLABLE BBUT;Lo;0;L;;;;;N;;;;; A06D;YI SYLLABLE BBUX;Lo;0;L;;;;;N;;;;; A06E;YI SYLLABLE BBU;Lo;0;L;;;;;N;;;;; A06F;YI SYLLABLE BBUP;Lo;0;L;;;;;N;;;;; A070;YI SYLLABLE BBURX;Lo;0;L;;;;;N;;;;; A071;YI SYLLABLE BBUR;Lo;0;L;;;;;N;;;;; A072;YI SYLLABLE BBYT;Lo;0;L;;;;;N;;;;; A073;YI SYLLABLE BBYX;Lo;0;L;;;;;N;;;;; A074;YI SYLLABLE BBY;Lo;0;L;;;;;N;;;;; A075;YI SYLLABLE BBYP;Lo;0;L;;;;;N;;;;; A076;YI SYLLABLE NBIT;Lo;0;L;;;;;N;;;;; A077;YI SYLLABLE NBIX;Lo;0;L;;;;;N;;;;; A078;YI SYLLABLE NBI;Lo;0;L;;;;;N;;;;; A079;YI SYLLABLE NBIP;Lo;0;L;;;;;N;;;;; A07A;YI SYLLABLE NBIEX;Lo;0;L;;;;;N;;;;; A07B;YI SYLLABLE NBIE;Lo;0;L;;;;;N;;;;; A07C;YI SYLLABLE NBIEP;Lo;0;L;;;;;N;;;;; A07D;YI SYLLABLE NBAT;Lo;0;L;;;;;N;;;;; A07E;YI SYLLABLE NBAX;Lo;0;L;;;;;N;;;;; A07F;YI SYLLABLE NBA;Lo;0;L;;;;;N;;;;; A080;YI SYLLABLE NBAP;Lo;0;L;;;;;N;;;;; A081;YI SYLLABLE NBOT;Lo;0;L;;;;;N;;;;; A082;YI SYLLABLE NBOX;Lo;0;L;;;;;N;;;;; A083;YI SYLLABLE NBO;Lo;0;L;;;;;N;;;;; A084;YI SYLLABLE NBOP;Lo;0;L;;;;;N;;;;; A085;YI SYLLABLE NBUT;Lo;0;L;;;;;N;;;;; A086;YI SYLLABLE NBUX;Lo;0;L;;;;;N;;;;; A087;YI SYLLABLE NBU;Lo;0;L;;;;;N;;;;; A088;YI SYLLABLE NBUP;Lo;0;L;;;;;N;;;;; A089;YI SYLLABLE NBURX;Lo;0;L;;;;;N;;;;; A08A;YI SYLLABLE NBUR;Lo;0;L;;;;;N;;;;; A08B;YI SYLLABLE NBYT;Lo;0;L;;;;;N;;;;; A08C;YI SYLLABLE NBYX;Lo;0;L;;;;;N;;;;; A08D;YI SYLLABLE NBY;Lo;0;L;;;;;N;;;;; A08E;YI SYLLABLE NBYP;Lo;0;L;;;;;N;;;;; A08F;YI SYLLABLE NBYRX;Lo;0;L;;;;;N;;;;; A090;YI SYLLABLE NBYR;Lo;0;L;;;;;N;;;;; A091;YI SYLLABLE HMIT;Lo;0;L;;;;;N;;;;; A092;YI SYLLABLE HMIX;Lo;0;L;;;;;N;;;;; A093;YI SYLLABLE HMI;Lo;0;L;;;;;N;;;;; A094;YI SYLLABLE HMIP;Lo;0;L;;;;;N;;;;; A095;YI SYLLABLE HMIEX;Lo;0;L;;;;;N;;;;; A096;YI SYLLABLE HMIE;Lo;0;L;;;;;N;;;;; A097;YI SYLLABLE HMIEP;Lo;0;L;;;;;N;;;;; A098;YI SYLLABLE HMAT;Lo;0;L;;;;;N;;;;; A099;YI SYLLABLE HMAX;Lo;0;L;;;;;N;;;;; A09A;YI SYLLABLE HMA;Lo;0;L;;;;;N;;;;; A09B;YI SYLLABLE HMAP;Lo;0;L;;;;;N;;;;; A09C;YI SYLLABLE HMUOX;Lo;0;L;;;;;N;;;;; A09D;YI SYLLABLE HMUO;Lo;0;L;;;;;N;;;;; A09E;YI SYLLABLE HMUOP;Lo;0;L;;;;;N;;;;; A09F;YI SYLLABLE HMOT;Lo;0;L;;;;;N;;;;; A0A0;YI SYLLABLE HMOX;Lo;0;L;;;;;N;;;;; A0A1;YI SYLLABLE HMO;Lo;0;L;;;;;N;;;;; A0A2;YI SYLLABLE HMOP;Lo;0;L;;;;;N;;;;; A0A3;YI SYLLABLE HMUT;Lo;0;L;;;;;N;;;;; A0A4;YI SYLLABLE HMUX;Lo;0;L;;;;;N;;;;; A0A5;YI SYLLABLE HMU;Lo;0;L;;;;;N;;;;; A0A6;YI SYLLABLE HMUP;Lo;0;L;;;;;N;;;;; A0A7;YI SYLLABLE HMURX;Lo;0;L;;;;;N;;;;; A0A8;YI SYLLABLE HMUR;Lo;0;L;;;;;N;;;;; A0A9;YI SYLLABLE HMYX;Lo;0;L;;;;;N;;;;; A0AA;YI SYLLABLE HMY;Lo;0;L;;;;;N;;;;; A0AB;YI SYLLABLE HMYP;Lo;0;L;;;;;N;;;;; A0AC;YI SYLLABLE HMYRX;Lo;0;L;;;;;N;;;;; A0AD;YI SYLLABLE HMYR;Lo;0;L;;;;;N;;;;; A0AE;YI SYLLABLE MIT;Lo;0;L;;;;;N;;;;; A0AF;YI SYLLABLE MIX;Lo;0;L;;;;;N;;;;; A0B0;YI SYLLABLE MI;Lo;0;L;;;;;N;;;;; A0B1;YI SYLLABLE MIP;Lo;0;L;;;;;N;;;;; A0B2;YI SYLLABLE MIEX;Lo;0;L;;;;;N;;;;; A0B3;YI SYLLABLE MIE;Lo;0;L;;;;;N;;;;; A0B4;YI SYLLABLE MIEP;Lo;0;L;;;;;N;;;;; A0B5;YI SYLLABLE MAT;Lo;0;L;;;;;N;;;;; A0B6;YI SYLLABLE MAX;Lo;0;L;;;;;N;;;;; A0B7;YI SYLLABLE MA;Lo;0;L;;;;;N;;;;; A0B8;YI SYLLABLE MAP;Lo;0;L;;;;;N;;;;; A0B9;YI SYLLABLE MUOT;Lo;0;L;;;;;N;;;;; A0BA;YI SYLLABLE MUOX;Lo;0;L;;;;;N;;;;; A0BB;YI SYLLABLE MUO;Lo;0;L;;;;;N;;;;; A0BC;YI SYLLABLE MUOP;Lo;0;L;;;;;N;;;;; A0BD;YI SYLLABLE MOT;Lo;0;L;;;;;N;;;;; A0BE;YI SYLLABLE MOX;Lo;0;L;;;;;N;;;;; A0BF;YI SYLLABLE MO;Lo;0;L;;;;;N;;;;; A0C0;YI SYLLABLE MOP;Lo;0;L;;;;;N;;;;; A0C1;YI SYLLABLE MEX;Lo;0;L;;;;;N;;;;; A0C2;YI SYLLABLE ME;Lo;0;L;;;;;N;;;;; A0C3;YI SYLLABLE MUT;Lo;0;L;;;;;N;;;;; A0C4;YI SYLLABLE MUX;Lo;0;L;;;;;N;;;;; A0C5;YI SYLLABLE MU;Lo;0;L;;;;;N;;;;; A0C6;YI SYLLABLE MUP;Lo;0;L;;;;;N;;;;; A0C7;YI SYLLABLE MURX;Lo;0;L;;;;;N;;;;; A0C8;YI SYLLABLE MUR;Lo;0;L;;;;;N;;;;; A0C9;YI SYLLABLE MYT;Lo;0;L;;;;;N;;;;; A0CA;YI SYLLABLE MYX;Lo;0;L;;;;;N;;;;; A0CB;YI SYLLABLE MY;Lo;0;L;;;;;N;;;;; A0CC;YI SYLLABLE MYP;Lo;0;L;;;;;N;;;;; A0CD;YI SYLLABLE FIT;Lo;0;L;;;;;N;;;;; A0CE;YI SYLLABLE FIX;Lo;0;L;;;;;N;;;;; A0CF;YI SYLLABLE FI;Lo;0;L;;;;;N;;;;; A0D0;YI SYLLABLE FIP;Lo;0;L;;;;;N;;;;; A0D1;YI SYLLABLE FAT;Lo;0;L;;;;;N;;;;; A0D2;YI SYLLABLE FAX;Lo;0;L;;;;;N;;;;; A0D3;YI SYLLABLE FA;Lo;0;L;;;;;N;;;;; A0D4;YI SYLLABLE FAP;Lo;0;L;;;;;N;;;;; A0D5;YI SYLLABLE FOX;Lo;0;L;;;;;N;;;;; A0D6;YI SYLLABLE FO;Lo;0;L;;;;;N;;;;; A0D7;YI SYLLABLE FOP;Lo;0;L;;;;;N;;;;; A0D8;YI SYLLABLE FUT;Lo;0;L;;;;;N;;;;; A0D9;YI SYLLABLE FUX;Lo;0;L;;;;;N;;;;; A0DA;YI SYLLABLE FU;Lo;0;L;;;;;N;;;;; A0DB;YI SYLLABLE FUP;Lo;0;L;;;;;N;;;;; A0DC;YI SYLLABLE FURX;Lo;0;L;;;;;N;;;;; A0DD;YI SYLLABLE FUR;Lo;0;L;;;;;N;;;;; A0DE;YI SYLLABLE FYT;Lo;0;L;;;;;N;;;;; A0DF;YI SYLLABLE FYX;Lo;0;L;;;;;N;;;;; A0E0;YI SYLLABLE FY;Lo;0;L;;;;;N;;;;; A0E1;YI SYLLABLE FYP;Lo;0;L;;;;;N;;;;; A0E2;YI SYLLABLE VIT;Lo;0;L;;;;;N;;;;; A0E3;YI SYLLABLE VIX;Lo;0;L;;;;;N;;;;; A0E4;YI SYLLABLE VI;Lo;0;L;;;;;N;;;;; A0E5;YI SYLLABLE VIP;Lo;0;L;;;;;N;;;;; A0E6;YI SYLLABLE VIET;Lo;0;L;;;;;N;;;;; A0E7;YI SYLLABLE VIEX;Lo;0;L;;;;;N;;;;; A0E8;YI SYLLABLE VIE;Lo;0;L;;;;;N;;;;; A0E9;YI SYLLABLE VIEP;Lo;0;L;;;;;N;;;;; A0EA;YI SYLLABLE VAT;Lo;0;L;;;;;N;;;;; A0EB;YI SYLLABLE VAX;Lo;0;L;;;;;N;;;;; A0EC;YI SYLLABLE VA;Lo;0;L;;;;;N;;;;; A0ED;YI SYLLABLE VAP;Lo;0;L;;;;;N;;;;; A0EE;YI SYLLABLE VOT;Lo;0;L;;;;;N;;;;; A0EF;YI SYLLABLE VOX;Lo;0;L;;;;;N;;;;; A0F0;YI SYLLABLE VO;Lo;0;L;;;;;N;;;;; A0F1;YI SYLLABLE VOP;Lo;0;L;;;;;N;;;;; A0F2;YI SYLLABLE VEX;Lo;0;L;;;;;N;;;;; A0F3;YI SYLLABLE VEP;Lo;0;L;;;;;N;;;;; A0F4;YI SYLLABLE VUT;Lo;0;L;;;;;N;;;;; A0F5;YI SYLLABLE VUX;Lo;0;L;;;;;N;;;;; A0F6;YI SYLLABLE VU;Lo;0;L;;;;;N;;;;; A0F7;YI SYLLABLE VUP;Lo;0;L;;;;;N;;;;; A0F8;YI SYLLABLE VURX;Lo;0;L;;;;;N;;;;; A0F9;YI SYLLABLE VUR;Lo;0;L;;;;;N;;;;; A0FA;YI SYLLABLE VYT;Lo;0;L;;;;;N;;;;; A0FB;YI SYLLABLE VYX;Lo;0;L;;;;;N;;;;; A0FC;YI SYLLABLE VY;Lo;0;L;;;;;N;;;;; A0FD;YI SYLLABLE VYP;Lo;0;L;;;;;N;;;;; A0FE;YI SYLLABLE VYRX;Lo;0;L;;;;;N;;;;; A0FF;YI SYLLABLE VYR;Lo;0;L;;;;;N;;;;; A100;YI SYLLABLE DIT;Lo;0;L;;;;;N;;;;; A101;YI SYLLABLE DIX;Lo;0;L;;;;;N;;;;; A102;YI SYLLABLE DI;Lo;0;L;;;;;N;;;;; A103;YI SYLLABLE DIP;Lo;0;L;;;;;N;;;;; A104;YI SYLLABLE DIEX;Lo;0;L;;;;;N;;;;; A105;YI SYLLABLE DIE;Lo;0;L;;;;;N;;;;; A106;YI SYLLABLE DIEP;Lo;0;L;;;;;N;;;;; A107;YI SYLLABLE DAT;Lo;0;L;;;;;N;;;;; A108;YI SYLLABLE DAX;Lo;0;L;;;;;N;;;;; A109;YI SYLLABLE DA;Lo;0;L;;;;;N;;;;; A10A;YI SYLLABLE DAP;Lo;0;L;;;;;N;;;;; A10B;YI SYLLABLE DUOX;Lo;0;L;;;;;N;;;;; A10C;YI SYLLABLE DUO;Lo;0;L;;;;;N;;;;; A10D;YI SYLLABLE DOT;Lo;0;L;;;;;N;;;;; A10E;YI SYLLABLE DOX;Lo;0;L;;;;;N;;;;; A10F;YI SYLLABLE DO;Lo;0;L;;;;;N;;;;; A110;YI SYLLABLE DOP;Lo;0;L;;;;;N;;;;; A111;YI SYLLABLE DEX;Lo;0;L;;;;;N;;;;; A112;YI SYLLABLE DE;Lo;0;L;;;;;N;;;;; A113;YI SYLLABLE DEP;Lo;0;L;;;;;N;;;;; A114;YI SYLLABLE DUT;Lo;0;L;;;;;N;;;;; A115;YI SYLLABLE DUX;Lo;0;L;;;;;N;;;;; A116;YI SYLLABLE DU;Lo;0;L;;;;;N;;;;; A117;YI SYLLABLE DUP;Lo;0;L;;;;;N;;;;; A118;YI SYLLABLE DURX;Lo;0;L;;;;;N;;;;; A119;YI SYLLABLE DUR;Lo;0;L;;;;;N;;;;; A11A;YI SYLLABLE TIT;Lo;0;L;;;;;N;;;;; A11B;YI SYLLABLE TIX;Lo;0;L;;;;;N;;;;; A11C;YI SYLLABLE TI;Lo;0;L;;;;;N;;;;; A11D;YI SYLLABLE TIP;Lo;0;L;;;;;N;;;;; A11E;YI SYLLABLE TIEX;Lo;0;L;;;;;N;;;;; A11F;YI SYLLABLE TIE;Lo;0;L;;;;;N;;;;; A120;YI SYLLABLE TIEP;Lo;0;L;;;;;N;;;;; A121;YI SYLLABLE TAT;Lo;0;L;;;;;N;;;;; A122;YI SYLLABLE TAX;Lo;0;L;;;;;N;;;;; A123;YI SYLLABLE TA;Lo;0;L;;;;;N;;;;; A124;YI SYLLABLE TAP;Lo;0;L;;;;;N;;;;; A125;YI SYLLABLE TUOT;Lo;0;L;;;;;N;;;;; A126;YI SYLLABLE TUOX;Lo;0;L;;;;;N;;;;; A127;YI SYLLABLE TUO;Lo;0;L;;;;;N;;;;; A128;YI SYLLABLE TUOP;Lo;0;L;;;;;N;;;;; A129;YI SYLLABLE TOT;Lo;0;L;;;;;N;;;;; A12A;YI SYLLABLE TOX;Lo;0;L;;;;;N;;;;; A12B;YI SYLLABLE TO;Lo;0;L;;;;;N;;;;; A12C;YI SYLLABLE TOP;Lo;0;L;;;;;N;;;;; A12D;YI SYLLABLE TEX;Lo;0;L;;;;;N;;;;; A12E;YI SYLLABLE TE;Lo;0;L;;;;;N;;;;; A12F;YI SYLLABLE TEP;Lo;0;L;;;;;N;;;;; A130;YI SYLLABLE TUT;Lo;0;L;;;;;N;;;;; A131;YI SYLLABLE TUX;Lo;0;L;;;;;N;;;;; A132;YI SYLLABLE TU;Lo;0;L;;;;;N;;;;; A133;YI SYLLABLE TUP;Lo;0;L;;;;;N;;;;; A134;YI SYLLABLE TURX;Lo;0;L;;;;;N;;;;; A135;YI SYLLABLE TUR;Lo;0;L;;;;;N;;;;; A136;YI SYLLABLE DDIT;Lo;0;L;;;;;N;;;;; A137;YI SYLLABLE DDIX;Lo;0;L;;;;;N;;;;; A138;YI SYLLABLE DDI;Lo;0;L;;;;;N;;;;; A139;YI SYLLABLE DDIP;Lo;0;L;;;;;N;;;;; A13A;YI SYLLABLE DDIEX;Lo;0;L;;;;;N;;;;; A13B;YI SYLLABLE DDIE;Lo;0;L;;;;;N;;;;; A13C;YI SYLLABLE DDIEP;Lo;0;L;;;;;N;;;;; A13D;YI SYLLABLE DDAT;Lo;0;L;;;;;N;;;;; A13E;YI SYLLABLE DDAX;Lo;0;L;;;;;N;;;;; A13F;YI SYLLABLE DDA;Lo;0;L;;;;;N;;;;; A140;YI SYLLABLE DDAP;Lo;0;L;;;;;N;;;;; A141;YI SYLLABLE DDUOX;Lo;0;L;;;;;N;;;;; A142;YI SYLLABLE DDUO;Lo;0;L;;;;;N;;;;; A143;YI SYLLABLE DDUOP;Lo;0;L;;;;;N;;;;; A144;YI SYLLABLE DDOT;Lo;0;L;;;;;N;;;;; A145;YI SYLLABLE DDOX;Lo;0;L;;;;;N;;;;; A146;YI SYLLABLE DDO;Lo;0;L;;;;;N;;;;; A147;YI SYLLABLE DDOP;Lo;0;L;;;;;N;;;;; A148;YI SYLLABLE DDEX;Lo;0;L;;;;;N;;;;; A149;YI SYLLABLE DDE;Lo;0;L;;;;;N;;;;; A14A;YI SYLLABLE DDEP;Lo;0;L;;;;;N;;;;; A14B;YI SYLLABLE DDUT;Lo;0;L;;;;;N;;;;; A14C;YI SYLLABLE DDUX;Lo;0;L;;;;;N;;;;; A14D;YI SYLLABLE DDU;Lo;0;L;;;;;N;;;;; A14E;YI SYLLABLE DDUP;Lo;0;L;;;;;N;;;;; A14F;YI SYLLABLE DDURX;Lo;0;L;;;;;N;;;;; A150;YI SYLLABLE DDUR;Lo;0;L;;;;;N;;;;; A151;YI SYLLABLE NDIT;Lo;0;L;;;;;N;;;;; A152;YI SYLLABLE NDIX;Lo;0;L;;;;;N;;;;; A153;YI SYLLABLE NDI;Lo;0;L;;;;;N;;;;; A154;YI SYLLABLE NDIP;Lo;0;L;;;;;N;;;;; A155;YI SYLLABLE NDIEX;Lo;0;L;;;;;N;;;;; A156;YI SYLLABLE NDIE;Lo;0;L;;;;;N;;;;; A157;YI SYLLABLE NDAT;Lo;0;L;;;;;N;;;;; A158;YI SYLLABLE NDAX;Lo;0;L;;;;;N;;;;; A159;YI SYLLABLE NDA;Lo;0;L;;;;;N;;;;; A15A;YI SYLLABLE NDAP;Lo;0;L;;;;;N;;;;; A15B;YI SYLLABLE NDOT;Lo;0;L;;;;;N;;;;; A15C;YI SYLLABLE NDOX;Lo;0;L;;;;;N;;;;; A15D;YI SYLLABLE NDO;Lo;0;L;;;;;N;;;;; A15E;YI SYLLABLE NDOP;Lo;0;L;;;;;N;;;;; A15F;YI SYLLABLE NDEX;Lo;0;L;;;;;N;;;;; A160;YI SYLLABLE NDE;Lo;0;L;;;;;N;;;;; A161;YI SYLLABLE NDEP;Lo;0;L;;;;;N;;;;; A162;YI SYLLABLE NDUT;Lo;0;L;;;;;N;;;;; A163;YI SYLLABLE NDUX;Lo;0;L;;;;;N;;;;; A164;YI SYLLABLE NDU;Lo;0;L;;;;;N;;;;; A165;YI SYLLABLE NDUP;Lo;0;L;;;;;N;;;;; A166;YI SYLLABLE NDURX;Lo;0;L;;;;;N;;;;; A167;YI SYLLABLE NDUR;Lo;0;L;;;;;N;;;;; A168;YI SYLLABLE HNIT;Lo;0;L;;;;;N;;;;; A169;YI SYLLABLE HNIX;Lo;0;L;;;;;N;;;;; A16A;YI SYLLABLE HNI;Lo;0;L;;;;;N;;;;; A16B;YI SYLLABLE HNIP;Lo;0;L;;;;;N;;;;; A16C;YI SYLLABLE HNIET;Lo;0;L;;;;;N;;;;; A16D;YI SYLLABLE HNIEX;Lo;0;L;;;;;N;;;;; A16E;YI SYLLABLE HNIE;Lo;0;L;;;;;N;;;;; A16F;YI SYLLABLE HNIEP;Lo;0;L;;;;;N;;;;; A170;YI SYLLABLE HNAT;Lo;0;L;;;;;N;;;;; A171;YI SYLLABLE HNAX;Lo;0;L;;;;;N;;;;; A172;YI SYLLABLE HNA;Lo;0;L;;;;;N;;;;; A173;YI SYLLABLE HNAP;Lo;0;L;;;;;N;;;;; A174;YI SYLLABLE HNUOX;Lo;0;L;;;;;N;;;;; A175;YI SYLLABLE HNUO;Lo;0;L;;;;;N;;;;; A176;YI SYLLABLE HNOT;Lo;0;L;;;;;N;;;;; A177;YI SYLLABLE HNOX;Lo;0;L;;;;;N;;;;; A178;YI SYLLABLE HNOP;Lo;0;L;;;;;N;;;;; A179;YI SYLLABLE HNEX;Lo;0;L;;;;;N;;;;; A17A;YI SYLLABLE HNE;Lo;0;L;;;;;N;;;;; A17B;YI SYLLABLE HNEP;Lo;0;L;;;;;N;;;;; A17C;YI SYLLABLE HNUT;Lo;0;L;;;;;N;;;;; A17D;YI SYLLABLE NIT;Lo;0;L;;;;;N;;;;; A17E;YI SYLLABLE NIX;Lo;0;L;;;;;N;;;;; A17F;YI SYLLABLE NI;Lo;0;L;;;;;N;;;;; A180;YI SYLLABLE NIP;Lo;0;L;;;;;N;;;;; A181;YI SYLLABLE NIEX;Lo;0;L;;;;;N;;;;; A182;YI SYLLABLE NIE;Lo;0;L;;;;;N;;;;; A183;YI SYLLABLE NIEP;Lo;0;L;;;;;N;;;;; A184;YI SYLLABLE NAX;Lo;0;L;;;;;N;;;;; A185;YI SYLLABLE NA;Lo;0;L;;;;;N;;;;; A186;YI SYLLABLE NAP;Lo;0;L;;;;;N;;;;; A187;YI SYLLABLE NUOX;Lo;0;L;;;;;N;;;;; A188;YI SYLLABLE NUO;Lo;0;L;;;;;N;;;;; A189;YI SYLLABLE NUOP;Lo;0;L;;;;;N;;;;; A18A;YI SYLLABLE NOT;Lo;0;L;;;;;N;;;;; A18B;YI SYLLABLE NOX;Lo;0;L;;;;;N;;;;; A18C;YI SYLLABLE NO;Lo;0;L;;;;;N;;;;; A18D;YI SYLLABLE NOP;Lo;0;L;;;;;N;;;;; A18E;YI SYLLABLE NEX;Lo;0;L;;;;;N;;;;; A18F;YI SYLLABLE NE;Lo;0;L;;;;;N;;;;; A190;YI SYLLABLE NEP;Lo;0;L;;;;;N;;;;; A191;YI SYLLABLE NUT;Lo;0;L;;;;;N;;;;; A192;YI SYLLABLE NUX;Lo;0;L;;;;;N;;;;; A193;YI SYLLABLE NU;Lo;0;L;;;;;N;;;;; A194;YI SYLLABLE NUP;Lo;0;L;;;;;N;;;;; A195;YI SYLLABLE NURX;Lo;0;L;;;;;N;;;;; A196;YI SYLLABLE NUR;Lo;0;L;;;;;N;;;;; A197;YI SYLLABLE HLIT;Lo;0;L;;;;;N;;;;; A198;YI SYLLABLE HLIX;Lo;0;L;;;;;N;;;;; A199;YI SYLLABLE HLI;Lo;0;L;;;;;N;;;;; A19A;YI SYLLABLE HLIP;Lo;0;L;;;;;N;;;;; A19B;YI SYLLABLE HLIEX;Lo;0;L;;;;;N;;;;; A19C;YI SYLLABLE HLIE;Lo;0;L;;;;;N;;;;; A19D;YI SYLLABLE HLIEP;Lo;0;L;;;;;N;;;;; A19E;YI SYLLABLE HLAT;Lo;0;L;;;;;N;;;;; A19F;YI SYLLABLE HLAX;Lo;0;L;;;;;N;;;;; A1A0;YI SYLLABLE HLA;Lo;0;L;;;;;N;;;;; A1A1;YI SYLLABLE HLAP;Lo;0;L;;;;;N;;;;; A1A2;YI SYLLABLE HLUOX;Lo;0;L;;;;;N;;;;; A1A3;YI SYLLABLE HLUO;Lo;0;L;;;;;N;;;;; A1A4;YI SYLLABLE HLUOP;Lo;0;L;;;;;N;;;;; A1A5;YI SYLLABLE HLOX;Lo;0;L;;;;;N;;;;; A1A6;YI SYLLABLE HLO;Lo;0;L;;;;;N;;;;; A1A7;YI SYLLABLE HLOP;Lo;0;L;;;;;N;;;;; A1A8;YI SYLLABLE HLEX;Lo;0;L;;;;;N;;;;; A1A9;YI SYLLABLE HLE;Lo;0;L;;;;;N;;;;; A1AA;YI SYLLABLE HLEP;Lo;0;L;;;;;N;;;;; A1AB;YI SYLLABLE HLUT;Lo;0;L;;;;;N;;;;; A1AC;YI SYLLABLE HLUX;Lo;0;L;;;;;N;;;;; A1AD;YI SYLLABLE HLU;Lo;0;L;;;;;N;;;;; A1AE;YI SYLLABLE HLUP;Lo;0;L;;;;;N;;;;; A1AF;YI SYLLABLE HLURX;Lo;0;L;;;;;N;;;;; A1B0;YI SYLLABLE HLUR;Lo;0;L;;;;;N;;;;; A1B1;YI SYLLABLE HLYT;Lo;0;L;;;;;N;;;;; A1B2;YI SYLLABLE HLYX;Lo;0;L;;;;;N;;;;; A1B3;YI SYLLABLE HLY;Lo;0;L;;;;;N;;;;; A1B4;YI SYLLABLE HLYP;Lo;0;L;;;;;N;;;;; A1B5;YI SYLLABLE HLYRX;Lo;0;L;;;;;N;;;;; A1B6;YI SYLLABLE HLYR;Lo;0;L;;;;;N;;;;; A1B7;YI SYLLABLE LIT;Lo;0;L;;;;;N;;;;; A1B8;YI SYLLABLE LIX;Lo;0;L;;;;;N;;;;; A1B9;YI SYLLABLE LI;Lo;0;L;;;;;N;;;;; A1BA;YI SYLLABLE LIP;Lo;0;L;;;;;N;;;;; A1BB;YI SYLLABLE LIET;Lo;0;L;;;;;N;;;;; A1BC;YI SYLLABLE LIEX;Lo;0;L;;;;;N;;;;; A1BD;YI SYLLABLE LIE;Lo;0;L;;;;;N;;;;; A1BE;YI SYLLABLE LIEP;Lo;0;L;;;;;N;;;;; A1BF;YI SYLLABLE LAT;Lo;0;L;;;;;N;;;;; A1C0;YI SYLLABLE LAX;Lo;0;L;;;;;N;;;;; A1C1;YI SYLLABLE LA;Lo;0;L;;;;;N;;;;; A1C2;YI SYLLABLE LAP;Lo;0;L;;;;;N;;;;; A1C3;YI SYLLABLE LUOT;Lo;0;L;;;;;N;;;;; A1C4;YI SYLLABLE LUOX;Lo;0;L;;;;;N;;;;; A1C5;YI SYLLABLE LUO;Lo;0;L;;;;;N;;;;; A1C6;YI SYLLABLE LUOP;Lo;0;L;;;;;N;;;;; A1C7;YI SYLLABLE LOT;Lo;0;L;;;;;N;;;;; A1C8;YI SYLLABLE LOX;Lo;0;L;;;;;N;;;;; A1C9;YI SYLLABLE LO;Lo;0;L;;;;;N;;;;; A1CA;YI SYLLABLE LOP;Lo;0;L;;;;;N;;;;; A1CB;YI SYLLABLE LEX;Lo;0;L;;;;;N;;;;; A1CC;YI SYLLABLE LE;Lo;0;L;;;;;N;;;;; A1CD;YI SYLLABLE LEP;Lo;0;L;;;;;N;;;;; A1CE;YI SYLLABLE LUT;Lo;0;L;;;;;N;;;;; A1CF;YI SYLLABLE LUX;Lo;0;L;;;;;N;;;;; A1D0;YI SYLLABLE LU;Lo;0;L;;;;;N;;;;; A1D1;YI SYLLABLE LUP;Lo;0;L;;;;;N;;;;; A1D2;YI SYLLABLE LURX;Lo;0;L;;;;;N;;;;; A1D3;YI SYLLABLE LUR;Lo;0;L;;;;;N;;;;; A1D4;YI SYLLABLE LYT;Lo;0;L;;;;;N;;;;; A1D5;YI SYLLABLE LYX;Lo;0;L;;;;;N;;;;; A1D6;YI SYLLABLE LY;Lo;0;L;;;;;N;;;;; A1D7;YI SYLLABLE LYP;Lo;0;L;;;;;N;;;;; A1D8;YI SYLLABLE LYRX;Lo;0;L;;;;;N;;;;; A1D9;YI SYLLABLE LYR;Lo;0;L;;;;;N;;;;; A1DA;YI SYLLABLE GIT;Lo;0;L;;;;;N;;;;; A1DB;YI SYLLABLE GIX;Lo;0;L;;;;;N;;;;; A1DC;YI SYLLABLE GI;Lo;0;L;;;;;N;;;;; A1DD;YI SYLLABLE GIP;Lo;0;L;;;;;N;;;;; A1DE;YI SYLLABLE GIET;Lo;0;L;;;;;N;;;;; A1DF;YI SYLLABLE GIEX;Lo;0;L;;;;;N;;;;; A1E0;YI SYLLABLE GIE;Lo;0;L;;;;;N;;;;; A1E1;YI SYLLABLE GIEP;Lo;0;L;;;;;N;;;;; A1E2;YI SYLLABLE GAT;Lo;0;L;;;;;N;;;;; A1E3;YI SYLLABLE GAX;Lo;0;L;;;;;N;;;;; A1E4;YI SYLLABLE GA;Lo;0;L;;;;;N;;;;; A1E5;YI SYLLABLE GAP;Lo;0;L;;;;;N;;;;; A1E6;YI SYLLABLE GUOT;Lo;0;L;;;;;N;;;;; A1E7;YI SYLLABLE GUOX;Lo;0;L;;;;;N;;;;; A1E8;YI SYLLABLE GUO;Lo;0;L;;;;;N;;;;; A1E9;YI SYLLABLE GUOP;Lo;0;L;;;;;N;;;;; A1EA;YI SYLLABLE GOT;Lo;0;L;;;;;N;;;;; A1EB;YI SYLLABLE GOX;Lo;0;L;;;;;N;;;;; A1EC;YI SYLLABLE GO;Lo;0;L;;;;;N;;;;; A1ED;YI SYLLABLE GOP;Lo;0;L;;;;;N;;;;; A1EE;YI SYLLABLE GET;Lo;0;L;;;;;N;;;;; A1EF;YI SYLLABLE GEX;Lo;0;L;;;;;N;;;;; A1F0;YI SYLLABLE GE;Lo;0;L;;;;;N;;;;; A1F1;YI SYLLABLE GEP;Lo;0;L;;;;;N;;;;; A1F2;YI SYLLABLE GUT;Lo;0;L;;;;;N;;;;; A1F3;YI SYLLABLE GUX;Lo;0;L;;;;;N;;;;; A1F4;YI SYLLABLE GU;Lo;0;L;;;;;N;;;;; A1F5;YI SYLLABLE GUP;Lo;0;L;;;;;N;;;;; A1F6;YI SYLLABLE GURX;Lo;0;L;;;;;N;;;;; A1F7;YI SYLLABLE GUR;Lo;0;L;;;;;N;;;;; A1F8;YI SYLLABLE KIT;Lo;0;L;;;;;N;;;;; A1F9;YI SYLLABLE KIX;Lo;0;L;;;;;N;;;;; A1FA;YI SYLLABLE KI;Lo;0;L;;;;;N;;;;; A1FB;YI SYLLABLE KIP;Lo;0;L;;;;;N;;;;; A1FC;YI SYLLABLE KIEX;Lo;0;L;;;;;N;;;;; A1FD;YI SYLLABLE KIE;Lo;0;L;;;;;N;;;;; A1FE;YI SYLLABLE KIEP;Lo;0;L;;;;;N;;;;; A1FF;YI SYLLABLE KAT;Lo;0;L;;;;;N;;;;; A200;YI SYLLABLE KAX;Lo;0;L;;;;;N;;;;; A201;YI SYLLABLE KA;Lo;0;L;;;;;N;;;;; A202;YI SYLLABLE KAP;Lo;0;L;;;;;N;;;;; A203;YI SYLLABLE KUOX;Lo;0;L;;;;;N;;;;; A204;YI SYLLABLE KUO;Lo;0;L;;;;;N;;;;; A205;YI SYLLABLE KUOP;Lo;0;L;;;;;N;;;;; A206;YI SYLLABLE KOT;Lo;0;L;;;;;N;;;;; A207;YI SYLLABLE KOX;Lo;0;L;;;;;N;;;;; A208;YI SYLLABLE KO;Lo;0;L;;;;;N;;;;; A209;YI SYLLABLE KOP;Lo;0;L;;;;;N;;;;; A20A;YI SYLLABLE KET;Lo;0;L;;;;;N;;;;; A20B;YI SYLLABLE KEX;Lo;0;L;;;;;N;;;;; A20C;YI SYLLABLE KE;Lo;0;L;;;;;N;;;;; A20D;YI SYLLABLE KEP;Lo;0;L;;;;;N;;;;; A20E;YI SYLLABLE KUT;Lo;0;L;;;;;N;;;;; A20F;YI SYLLABLE KUX;Lo;0;L;;;;;N;;;;; A210;YI SYLLABLE KU;Lo;0;L;;;;;N;;;;; A211;YI SYLLABLE KUP;Lo;0;L;;;;;N;;;;; A212;YI SYLLABLE KURX;Lo;0;L;;;;;N;;;;; A213;YI SYLLABLE KUR;Lo;0;L;;;;;N;;;;; A214;YI SYLLABLE GGIT;Lo;0;L;;;;;N;;;;; A215;YI SYLLABLE GGIX;Lo;0;L;;;;;N;;;;; A216;YI SYLLABLE GGI;Lo;0;L;;;;;N;;;;; A217;YI SYLLABLE GGIEX;Lo;0;L;;;;;N;;;;; A218;YI SYLLABLE GGIE;Lo;0;L;;;;;N;;;;; A219;YI SYLLABLE GGIEP;Lo;0;L;;;;;N;;;;; A21A;YI SYLLABLE GGAT;Lo;0;L;;;;;N;;;;; A21B;YI SYLLABLE GGAX;Lo;0;L;;;;;N;;;;; A21C;YI SYLLABLE GGA;Lo;0;L;;;;;N;;;;; A21D;YI SYLLABLE GGAP;Lo;0;L;;;;;N;;;;; A21E;YI SYLLABLE GGUOT;Lo;0;L;;;;;N;;;;; A21F;YI SYLLABLE GGUOX;Lo;0;L;;;;;N;;;;; A220;YI SYLLABLE GGUO;Lo;0;L;;;;;N;;;;; A221;YI SYLLABLE GGUOP;Lo;0;L;;;;;N;;;;; A222;YI SYLLABLE GGOT;Lo;0;L;;;;;N;;;;; A223;YI SYLLABLE GGOX;Lo;0;L;;;;;N;;;;; A224;YI SYLLABLE GGO;Lo;0;L;;;;;N;;;;; A225;YI SYLLABLE GGOP;Lo;0;L;;;;;N;;;;; A226;YI SYLLABLE GGET;Lo;0;L;;;;;N;;;;; A227;YI SYLLABLE GGEX;Lo;0;L;;;;;N;;;;; A228;YI SYLLABLE GGE;Lo;0;L;;;;;N;;;;; A229;YI SYLLABLE GGEP;Lo;0;L;;;;;N;;;;; A22A;YI SYLLABLE GGUT;Lo;0;L;;;;;N;;;;; A22B;YI SYLLABLE GGUX;Lo;0;L;;;;;N;;;;; A22C;YI SYLLABLE GGU;Lo;0;L;;;;;N;;;;; A22D;YI SYLLABLE GGUP;Lo;0;L;;;;;N;;;;; A22E;YI SYLLABLE GGURX;Lo;0;L;;;;;N;;;;; A22F;YI SYLLABLE GGUR;Lo;0;L;;;;;N;;;;; A230;YI SYLLABLE MGIEX;Lo;0;L;;;;;N;;;;; A231;YI SYLLABLE MGIE;Lo;0;L;;;;;N;;;;; A232;YI SYLLABLE MGAT;Lo;0;L;;;;;N;;;;; A233;YI SYLLABLE MGAX;Lo;0;L;;;;;N;;;;; A234;YI SYLLABLE MGA;Lo;0;L;;;;;N;;;;; A235;YI SYLLABLE MGAP;Lo;0;L;;;;;N;;;;; A236;YI SYLLABLE MGUOX;Lo;0;L;;;;;N;;;;; A237;YI SYLLABLE MGUO;Lo;0;L;;;;;N;;;;; A238;YI SYLLABLE MGUOP;Lo;0;L;;;;;N;;;;; A239;YI SYLLABLE MGOT;Lo;0;L;;;;;N;;;;; A23A;YI SYLLABLE MGOX;Lo;0;L;;;;;N;;;;; A23B;YI SYLLABLE MGO;Lo;0;L;;;;;N;;;;; A23C;YI SYLLABLE MGOP;Lo;0;L;;;;;N;;;;; A23D;YI SYLLABLE MGEX;Lo;0;L;;;;;N;;;;; A23E;YI SYLLABLE MGE;Lo;0;L;;;;;N;;;;; A23F;YI SYLLABLE MGEP;Lo;0;L;;;;;N;;;;; A240;YI SYLLABLE MGUT;Lo;0;L;;;;;N;;;;; A241;YI SYLLABLE MGUX;Lo;0;L;;;;;N;;;;; A242;YI SYLLABLE MGU;Lo;0;L;;;;;N;;;;; A243;YI SYLLABLE MGUP;Lo;0;L;;;;;N;;;;; A244;YI SYLLABLE MGURX;Lo;0;L;;;;;N;;;;; A245;YI SYLLABLE MGUR;Lo;0;L;;;;;N;;;;; A246;YI SYLLABLE HXIT;Lo;0;L;;;;;N;;;;; A247;YI SYLLABLE HXIX;Lo;0;L;;;;;N;;;;; A248;YI SYLLABLE HXI;Lo;0;L;;;;;N;;;;; A249;YI SYLLABLE HXIP;Lo;0;L;;;;;N;;;;; A24A;YI SYLLABLE HXIET;Lo;0;L;;;;;N;;;;; A24B;YI SYLLABLE HXIEX;Lo;0;L;;;;;N;;;;; A24C;YI SYLLABLE HXIE;Lo;0;L;;;;;N;;;;; A24D;YI SYLLABLE HXIEP;Lo;0;L;;;;;N;;;;; A24E;YI SYLLABLE HXAT;Lo;0;L;;;;;N;;;;; A24F;YI SYLLABLE HXAX;Lo;0;L;;;;;N;;;;; A250;YI SYLLABLE HXA;Lo;0;L;;;;;N;;;;; A251;YI SYLLABLE HXAP;Lo;0;L;;;;;N;;;;; A252;YI SYLLABLE HXUOT;Lo;0;L;;;;;N;;;;; A253;YI SYLLABLE HXUOX;Lo;0;L;;;;;N;;;;; A254;YI SYLLABLE HXUO;Lo;0;L;;;;;N;;;;; A255;YI SYLLABLE HXUOP;Lo;0;L;;;;;N;;;;; A256;YI SYLLABLE HXOT;Lo;0;L;;;;;N;;;;; A257;YI SYLLABLE HXOX;Lo;0;L;;;;;N;;;;; A258;YI SYLLABLE HXO;Lo;0;L;;;;;N;;;;; A259;YI SYLLABLE HXOP;Lo;0;L;;;;;N;;;;; A25A;YI SYLLABLE HXEX;Lo;0;L;;;;;N;;;;; A25B;YI SYLLABLE HXE;Lo;0;L;;;;;N;;;;; A25C;YI SYLLABLE HXEP;Lo;0;L;;;;;N;;;;; A25D;YI SYLLABLE NGIEX;Lo;0;L;;;;;N;;;;; A25E;YI SYLLABLE NGIE;Lo;0;L;;;;;N;;;;; A25F;YI SYLLABLE NGIEP;Lo;0;L;;;;;N;;;;; A260;YI SYLLABLE NGAT;Lo;0;L;;;;;N;;;;; A261;YI SYLLABLE NGAX;Lo;0;L;;;;;N;;;;; A262;YI SYLLABLE NGA;Lo;0;L;;;;;N;;;;; A263;YI SYLLABLE NGAP;Lo;0;L;;;;;N;;;;; A264;YI SYLLABLE NGUOT;Lo;0;L;;;;;N;;;;; A265;YI SYLLABLE NGUOX;Lo;0;L;;;;;N;;;;; A266;YI SYLLABLE NGUO;Lo;0;L;;;;;N;;;;; A267;YI SYLLABLE NGOT;Lo;0;L;;;;;N;;;;; A268;YI SYLLABLE NGOX;Lo;0;L;;;;;N;;;;; A269;YI SYLLABLE NGO;Lo;0;L;;;;;N;;;;; A26A;YI SYLLABLE NGOP;Lo;0;L;;;;;N;;;;; A26B;YI SYLLABLE NGEX;Lo;0;L;;;;;N;;;;; A26C;YI SYLLABLE NGE;Lo;0;L;;;;;N;;;;; A26D;YI SYLLABLE NGEP;Lo;0;L;;;;;N;;;;; A26E;YI SYLLABLE HIT;Lo;0;L;;;;;N;;;;; A26F;YI SYLLABLE HIEX;Lo;0;L;;;;;N;;;;; A270;YI SYLLABLE HIE;Lo;0;L;;;;;N;;;;; A271;YI SYLLABLE HAT;Lo;0;L;;;;;N;;;;; A272;YI SYLLABLE HAX;Lo;0;L;;;;;N;;;;; A273;YI SYLLABLE HA;Lo;0;L;;;;;N;;;;; A274;YI SYLLABLE HAP;Lo;0;L;;;;;N;;;;; A275;YI SYLLABLE HUOT;Lo;0;L;;;;;N;;;;; A276;YI SYLLABLE HUOX;Lo;0;L;;;;;N;;;;; A277;YI SYLLABLE HUO;Lo;0;L;;;;;N;;;;; A278;YI SYLLABLE HUOP;Lo;0;L;;;;;N;;;;; A279;YI SYLLABLE HOT;Lo;0;L;;;;;N;;;;; A27A;YI SYLLABLE HOX;Lo;0;L;;;;;N;;;;; A27B;YI SYLLABLE HO;Lo;0;L;;;;;N;;;;; A27C;YI SYLLABLE HOP;Lo;0;L;;;;;N;;;;; A27D;YI SYLLABLE HEX;Lo;0;L;;;;;N;;;;; A27E;YI SYLLABLE HE;Lo;0;L;;;;;N;;;;; A27F;YI SYLLABLE HEP;Lo;0;L;;;;;N;;;;; A280;YI SYLLABLE WAT;Lo;0;L;;;;;N;;;;; A281;YI SYLLABLE WAX;Lo;0;L;;;;;N;;;;; A282;YI SYLLABLE WA;Lo;0;L;;;;;N;;;;; A283;YI SYLLABLE WAP;Lo;0;L;;;;;N;;;;; A284;YI SYLLABLE WUOX;Lo;0;L;;;;;N;;;;; A285;YI SYLLABLE WUO;Lo;0;L;;;;;N;;;;; A286;YI SYLLABLE WUOP;Lo;0;L;;;;;N;;;;; A287;YI SYLLABLE WOX;Lo;0;L;;;;;N;;;;; A288;YI SYLLABLE WO;Lo;0;L;;;;;N;;;;; A289;YI SYLLABLE WOP;Lo;0;L;;;;;N;;;;; A28A;YI SYLLABLE WEX;Lo;0;L;;;;;N;;;;; A28B;YI SYLLABLE WE;Lo;0;L;;;;;N;;;;; A28C;YI SYLLABLE WEP;Lo;0;L;;;;;N;;;;; A28D;YI SYLLABLE ZIT;Lo;0;L;;;;;N;;;;; A28E;YI SYLLABLE ZIX;Lo;0;L;;;;;N;;;;; A28F;YI SYLLABLE ZI;Lo;0;L;;;;;N;;;;; A290;YI SYLLABLE ZIP;Lo;0;L;;;;;N;;;;; A291;YI SYLLABLE ZIEX;Lo;0;L;;;;;N;;;;; A292;YI SYLLABLE ZIE;Lo;0;L;;;;;N;;;;; A293;YI SYLLABLE ZIEP;Lo;0;L;;;;;N;;;;; A294;YI SYLLABLE ZAT;Lo;0;L;;;;;N;;;;; A295;YI SYLLABLE ZAX;Lo;0;L;;;;;N;;;;; A296;YI SYLLABLE ZA;Lo;0;L;;;;;N;;;;; A297;YI SYLLABLE ZAP;Lo;0;L;;;;;N;;;;; A298;YI SYLLABLE ZUOX;Lo;0;L;;;;;N;;;;; A299;YI SYLLABLE ZUO;Lo;0;L;;;;;N;;;;; A29A;YI SYLLABLE ZUOP;Lo;0;L;;;;;N;;;;; A29B;YI SYLLABLE ZOT;Lo;0;L;;;;;N;;;;; A29C;YI SYLLABLE ZOX;Lo;0;L;;;;;N;;;;; A29D;YI SYLLABLE ZO;Lo;0;L;;;;;N;;;;; A29E;YI SYLLABLE ZOP;Lo;0;L;;;;;N;;;;; A29F;YI SYLLABLE ZEX;Lo;0;L;;;;;N;;;;; A2A0;YI SYLLABLE ZE;Lo;0;L;;;;;N;;;;; A2A1;YI SYLLABLE ZEP;Lo;0;L;;;;;N;;;;; A2A2;YI SYLLABLE ZUT;Lo;0;L;;;;;N;;;;; A2A3;YI SYLLABLE ZUX;Lo;0;L;;;;;N;;;;; A2A4;YI SYLLABLE ZU;Lo;0;L;;;;;N;;;;; A2A5;YI SYLLABLE ZUP;Lo;0;L;;;;;N;;;;; A2A6;YI SYLLABLE ZURX;Lo;0;L;;;;;N;;;;; A2A7;YI SYLLABLE ZUR;Lo;0;L;;;;;N;;;;; A2A8;YI SYLLABLE ZYT;Lo;0;L;;;;;N;;;;; A2A9;YI SYLLABLE ZYX;Lo;0;L;;;;;N;;;;; A2AA;YI SYLLABLE ZY;Lo;0;L;;;;;N;;;;; A2AB;YI SYLLABLE ZYP;Lo;0;L;;;;;N;;;;; A2AC;YI SYLLABLE ZYRX;Lo;0;L;;;;;N;;;;; A2AD;YI SYLLABLE ZYR;Lo;0;L;;;;;N;;;;; A2AE;YI SYLLABLE CIT;Lo;0;L;;;;;N;;;;; A2AF;YI SYLLABLE CIX;Lo;0;L;;;;;N;;;;; A2B0;YI SYLLABLE CI;Lo;0;L;;;;;N;;;;; A2B1;YI SYLLABLE CIP;Lo;0;L;;;;;N;;;;; A2B2;YI SYLLABLE CIET;Lo;0;L;;;;;N;;;;; A2B3;YI SYLLABLE CIEX;Lo;0;L;;;;;N;;;;; A2B4;YI SYLLABLE CIE;Lo;0;L;;;;;N;;;;; A2B5;YI SYLLABLE CIEP;Lo;0;L;;;;;N;;;;; A2B6;YI SYLLABLE CAT;Lo;0;L;;;;;N;;;;; A2B7;YI SYLLABLE CAX;Lo;0;L;;;;;N;;;;; A2B8;YI SYLLABLE CA;Lo;0;L;;;;;N;;;;; A2B9;YI SYLLABLE CAP;Lo;0;L;;;;;N;;;;; A2BA;YI SYLLABLE CUOX;Lo;0;L;;;;;N;;;;; A2BB;YI SYLLABLE CUO;Lo;0;L;;;;;N;;;;; A2BC;YI SYLLABLE CUOP;Lo;0;L;;;;;N;;;;; A2BD;YI SYLLABLE COT;Lo;0;L;;;;;N;;;;; A2BE;YI SYLLABLE COX;Lo;0;L;;;;;N;;;;; A2BF;YI SYLLABLE CO;Lo;0;L;;;;;N;;;;; A2C0;YI SYLLABLE COP;Lo;0;L;;;;;N;;;;; A2C1;YI SYLLABLE CEX;Lo;0;L;;;;;N;;;;; A2C2;YI SYLLABLE CE;Lo;0;L;;;;;N;;;;; A2C3;YI SYLLABLE CEP;Lo;0;L;;;;;N;;;;; A2C4;YI SYLLABLE CUT;Lo;0;L;;;;;N;;;;; A2C5;YI SYLLABLE CUX;Lo;0;L;;;;;N;;;;; A2C6;YI SYLLABLE CU;Lo;0;L;;;;;N;;;;; A2C7;YI SYLLABLE CUP;Lo;0;L;;;;;N;;;;; A2C8;YI SYLLABLE CURX;Lo;0;L;;;;;N;;;;; A2C9;YI SYLLABLE CUR;Lo;0;L;;;;;N;;;;; A2CA;YI SYLLABLE CYT;Lo;0;L;;;;;N;;;;; A2CB;YI SYLLABLE CYX;Lo;0;L;;;;;N;;;;; A2CC;YI SYLLABLE CY;Lo;0;L;;;;;N;;;;; A2CD;YI SYLLABLE CYP;Lo;0;L;;;;;N;;;;; A2CE;YI SYLLABLE CYRX;Lo;0;L;;;;;N;;;;; A2CF;YI SYLLABLE CYR;Lo;0;L;;;;;N;;;;; A2D0;YI SYLLABLE ZZIT;Lo;0;L;;;;;N;;;;; A2D1;YI SYLLABLE ZZIX;Lo;0;L;;;;;N;;;;; A2D2;YI SYLLABLE ZZI;Lo;0;L;;;;;N;;;;; A2D3;YI SYLLABLE ZZIP;Lo;0;L;;;;;N;;;;; A2D4;YI SYLLABLE ZZIET;Lo;0;L;;;;;N;;;;; A2D5;YI SYLLABLE ZZIEX;Lo;0;L;;;;;N;;;;; A2D6;YI SYLLABLE ZZIE;Lo;0;L;;;;;N;;;;; A2D7;YI SYLLABLE ZZIEP;Lo;0;L;;;;;N;;;;; A2D8;YI SYLLABLE ZZAT;Lo;0;L;;;;;N;;;;; A2D9;YI SYLLABLE ZZAX;Lo;0;L;;;;;N;;;;; A2DA;YI SYLLABLE ZZA;Lo;0;L;;;;;N;;;;; A2DB;YI SYLLABLE ZZAP;Lo;0;L;;;;;N;;;;; A2DC;YI SYLLABLE ZZOX;Lo;0;L;;;;;N;;;;; A2DD;YI SYLLABLE ZZO;Lo;0;L;;;;;N;;;;; A2DE;YI SYLLABLE ZZOP;Lo;0;L;;;;;N;;;;; A2DF;YI SYLLABLE ZZEX;Lo;0;L;;;;;N;;;;; A2E0;YI SYLLABLE ZZE;Lo;0;L;;;;;N;;;;; A2E1;YI SYLLABLE ZZEP;Lo;0;L;;;;;N;;;;; A2E2;YI SYLLABLE ZZUX;Lo;0;L;;;;;N;;;;; A2E3;YI SYLLABLE ZZU;Lo;0;L;;;;;N;;;;; A2E4;YI SYLLABLE ZZUP;Lo;0;L;;;;;N;;;;; A2E5;YI SYLLABLE ZZURX;Lo;0;L;;;;;N;;;;; A2E6;YI SYLLABLE ZZUR;Lo;0;L;;;;;N;;;;; A2E7;YI SYLLABLE ZZYT;Lo;0;L;;;;;N;;;;; A2E8;YI SYLLABLE ZZYX;Lo;0;L;;;;;N;;;;; A2E9;YI SYLLABLE ZZY;Lo;0;L;;;;;N;;;;; A2EA;YI SYLLABLE ZZYP;Lo;0;L;;;;;N;;;;; A2EB;YI SYLLABLE ZZYRX;Lo;0;L;;;;;N;;;;; A2EC;YI SYLLABLE ZZYR;Lo;0;L;;;;;N;;;;; A2ED;YI SYLLABLE NZIT;Lo;0;L;;;;;N;;;;; A2EE;YI SYLLABLE NZIX;Lo;0;L;;;;;N;;;;; A2EF;YI SYLLABLE NZI;Lo;0;L;;;;;N;;;;; A2F0;YI SYLLABLE NZIP;Lo;0;L;;;;;N;;;;; A2F1;YI SYLLABLE NZIEX;Lo;0;L;;;;;N;;;;; A2F2;YI SYLLABLE NZIE;Lo;0;L;;;;;N;;;;; A2F3;YI SYLLABLE NZIEP;Lo;0;L;;;;;N;;;;; A2F4;YI SYLLABLE NZAT;Lo;0;L;;;;;N;;;;; A2F5;YI SYLLABLE NZAX;Lo;0;L;;;;;N;;;;; A2F6;YI SYLLABLE NZA;Lo;0;L;;;;;N;;;;; A2F7;YI SYLLABLE NZAP;Lo;0;L;;;;;N;;;;; A2F8;YI SYLLABLE NZUOX;Lo;0;L;;;;;N;;;;; A2F9;YI SYLLABLE NZUO;Lo;0;L;;;;;N;;;;; A2FA;YI SYLLABLE NZOX;Lo;0;L;;;;;N;;;;; A2FB;YI SYLLABLE NZOP;Lo;0;L;;;;;N;;;;; A2FC;YI SYLLABLE NZEX;Lo;0;L;;;;;N;;;;; A2FD;YI SYLLABLE NZE;Lo;0;L;;;;;N;;;;; A2FE;YI SYLLABLE NZUX;Lo;0;L;;;;;N;;;;; A2FF;YI SYLLABLE NZU;Lo;0;L;;;;;N;;;;; A300;YI SYLLABLE NZUP;Lo;0;L;;;;;N;;;;; A301;YI SYLLABLE NZURX;Lo;0;L;;;;;N;;;;; A302;YI SYLLABLE NZUR;Lo;0;L;;;;;N;;;;; A303;YI SYLLABLE NZYT;Lo;0;L;;;;;N;;;;; A304;YI SYLLABLE NZYX;Lo;0;L;;;;;N;;;;; A305;YI SYLLABLE NZY;Lo;0;L;;;;;N;;;;; A306;YI SYLLABLE NZYP;Lo;0;L;;;;;N;;;;; A307;YI SYLLABLE NZYRX;Lo;0;L;;;;;N;;;;; A308;YI SYLLABLE NZYR;Lo;0;L;;;;;N;;;;; A309;YI SYLLABLE SIT;Lo;0;L;;;;;N;;;;; A30A;YI SYLLABLE SIX;Lo;0;L;;;;;N;;;;; A30B;YI SYLLABLE SI;Lo;0;L;;;;;N;;;;; A30C;YI SYLLABLE SIP;Lo;0;L;;;;;N;;;;; A30D;YI SYLLABLE SIEX;Lo;0;L;;;;;N;;;;; A30E;YI SYLLABLE SIE;Lo;0;L;;;;;N;;;;; A30F;YI SYLLABLE SIEP;Lo;0;L;;;;;N;;;;; A310;YI SYLLABLE SAT;Lo;0;L;;;;;N;;;;; A311;YI SYLLABLE SAX;Lo;0;L;;;;;N;;;;; A312;YI SYLLABLE SA;Lo;0;L;;;;;N;;;;; A313;YI SYLLABLE SAP;Lo;0;L;;;;;N;;;;; A314;YI SYLLABLE SUOX;Lo;0;L;;;;;N;;;;; A315;YI SYLLABLE SUO;Lo;0;L;;;;;N;;;;; A316;YI SYLLABLE SUOP;Lo;0;L;;;;;N;;;;; A317;YI SYLLABLE SOT;Lo;0;L;;;;;N;;;;; A318;YI SYLLABLE SOX;Lo;0;L;;;;;N;;;;; A319;YI SYLLABLE SO;Lo;0;L;;;;;N;;;;; A31A;YI SYLLABLE SOP;Lo;0;L;;;;;N;;;;; A31B;YI SYLLABLE SEX;Lo;0;L;;;;;N;;;;; A31C;YI SYLLABLE SE;Lo;0;L;;;;;N;;;;; A31D;YI SYLLABLE SEP;Lo;0;L;;;;;N;;;;; A31E;YI SYLLABLE SUT;Lo;0;L;;;;;N;;;;; A31F;YI SYLLABLE SUX;Lo;0;L;;;;;N;;;;; A320;YI SYLLABLE SU;Lo;0;L;;;;;N;;;;; A321;YI SYLLABLE SUP;Lo;0;L;;;;;N;;;;; A322;YI SYLLABLE SURX;Lo;0;L;;;;;N;;;;; A323;YI SYLLABLE SUR;Lo;0;L;;;;;N;;;;; A324;YI SYLLABLE SYT;Lo;0;L;;;;;N;;;;; A325;YI SYLLABLE SYX;Lo;0;L;;;;;N;;;;; A326;YI SYLLABLE SY;Lo;0;L;;;;;N;;;;; A327;YI SYLLABLE SYP;Lo;0;L;;;;;N;;;;; A328;YI SYLLABLE SYRX;Lo;0;L;;;;;N;;;;; A329;YI SYLLABLE SYR;Lo;0;L;;;;;N;;;;; A32A;YI SYLLABLE SSIT;Lo;0;L;;;;;N;;;;; A32B;YI SYLLABLE SSIX;Lo;0;L;;;;;N;;;;; A32C;YI SYLLABLE SSI;Lo;0;L;;;;;N;;;;; A32D;YI SYLLABLE SSIP;Lo;0;L;;;;;N;;;;; A32E;YI SYLLABLE SSIEX;Lo;0;L;;;;;N;;;;; A32F;YI SYLLABLE SSIE;Lo;0;L;;;;;N;;;;; A330;YI SYLLABLE SSIEP;Lo;0;L;;;;;N;;;;; A331;YI SYLLABLE SSAT;Lo;0;L;;;;;N;;;;; A332;YI SYLLABLE SSAX;Lo;0;L;;;;;N;;;;; A333;YI SYLLABLE SSA;Lo;0;L;;;;;N;;;;; A334;YI SYLLABLE SSAP;Lo;0;L;;;;;N;;;;; A335;YI SYLLABLE SSOT;Lo;0;L;;;;;N;;;;; A336;YI SYLLABLE SSOX;Lo;0;L;;;;;N;;;;; A337;YI SYLLABLE SSO;Lo;0;L;;;;;N;;;;; A338;YI SYLLABLE SSOP;Lo;0;L;;;;;N;;;;; A339;YI SYLLABLE SSEX;Lo;0;L;;;;;N;;;;; A33A;YI SYLLABLE SSE;Lo;0;L;;;;;N;;;;; A33B;YI SYLLABLE SSEP;Lo;0;L;;;;;N;;;;; A33C;YI SYLLABLE SSUT;Lo;0;L;;;;;N;;;;; A33D;YI SYLLABLE SSUX;Lo;0;L;;;;;N;;;;; A33E;YI SYLLABLE SSU;Lo;0;L;;;;;N;;;;; A33F;YI SYLLABLE SSUP;Lo;0;L;;;;;N;;;;; A340;YI SYLLABLE SSYT;Lo;0;L;;;;;N;;;;; A341;YI SYLLABLE SSYX;Lo;0;L;;;;;N;;;;; A342;YI SYLLABLE SSY;Lo;0;L;;;;;N;;;;; A343;YI SYLLABLE SSYP;Lo;0;L;;;;;N;;;;; A344;YI SYLLABLE SSYRX;Lo;0;L;;;;;N;;;;; A345;YI SYLLABLE SSYR;Lo;0;L;;;;;N;;;;; A346;YI SYLLABLE ZHAT;Lo;0;L;;;;;N;;;;; A347;YI SYLLABLE ZHAX;Lo;0;L;;;;;N;;;;; A348;YI SYLLABLE ZHA;Lo;0;L;;;;;N;;;;; A349;YI SYLLABLE ZHAP;Lo;0;L;;;;;N;;;;; A34A;YI SYLLABLE ZHUOX;Lo;0;L;;;;;N;;;;; A34B;YI SYLLABLE ZHUO;Lo;0;L;;;;;N;;;;; A34C;YI SYLLABLE ZHUOP;Lo;0;L;;;;;N;;;;; A34D;YI SYLLABLE ZHOT;Lo;0;L;;;;;N;;;;; A34E;YI SYLLABLE ZHOX;Lo;0;L;;;;;N;;;;; A34F;YI SYLLABLE ZHO;Lo;0;L;;;;;N;;;;; A350;YI SYLLABLE ZHOP;Lo;0;L;;;;;N;;;;; A351;YI SYLLABLE ZHET;Lo;0;L;;;;;N;;;;; A352;YI SYLLABLE ZHEX;Lo;0;L;;;;;N;;;;; A353;YI SYLLABLE ZHE;Lo;0;L;;;;;N;;;;; A354;YI SYLLABLE ZHEP;Lo;0;L;;;;;N;;;;; A355;YI SYLLABLE ZHUT;Lo;0;L;;;;;N;;;;; A356;YI SYLLABLE ZHUX;Lo;0;L;;;;;N;;;;; A357;YI SYLLABLE ZHU;Lo;0;L;;;;;N;;;;; A358;YI SYLLABLE ZHUP;Lo;0;L;;;;;N;;;;; A359;YI SYLLABLE ZHURX;Lo;0;L;;;;;N;;;;; A35A;YI SYLLABLE ZHUR;Lo;0;L;;;;;N;;;;; A35B;YI SYLLABLE ZHYT;Lo;0;L;;;;;N;;;;; A35C;YI SYLLABLE ZHYX;Lo;0;L;;;;;N;;;;; A35D;YI SYLLABLE ZHY;Lo;0;L;;;;;N;;;;; A35E;YI SYLLABLE ZHYP;Lo;0;L;;;;;N;;;;; A35F;YI SYLLABLE ZHYRX;Lo;0;L;;;;;N;;;;; A360;YI SYLLABLE ZHYR;Lo;0;L;;;;;N;;;;; A361;YI SYLLABLE CHAT;Lo;0;L;;;;;N;;;;; A362;YI SYLLABLE CHAX;Lo;0;L;;;;;N;;;;; A363;YI SYLLABLE CHA;Lo;0;L;;;;;N;;;;; A364;YI SYLLABLE CHAP;Lo;0;L;;;;;N;;;;; A365;YI SYLLABLE CHUOT;Lo;0;L;;;;;N;;;;; A366;YI SYLLABLE CHUOX;Lo;0;L;;;;;N;;;;; A367;YI SYLLABLE CHUO;Lo;0;L;;;;;N;;;;; A368;YI SYLLABLE CHUOP;Lo;0;L;;;;;N;;;;; A369;YI SYLLABLE CHOT;Lo;0;L;;;;;N;;;;; A36A;YI SYLLABLE CHOX;Lo;0;L;;;;;N;;;;; A36B;YI SYLLABLE CHO;Lo;0;L;;;;;N;;;;; A36C;YI SYLLABLE CHOP;Lo;0;L;;;;;N;;;;; A36D;YI SYLLABLE CHET;Lo;0;L;;;;;N;;;;; A36E;YI SYLLABLE CHEX;Lo;0;L;;;;;N;;;;; A36F;YI SYLLABLE CHE;Lo;0;L;;;;;N;;;;; A370;YI SYLLABLE CHEP;Lo;0;L;;;;;N;;;;; A371;YI SYLLABLE CHUX;Lo;0;L;;;;;N;;;;; A372;YI SYLLABLE CHU;Lo;0;L;;;;;N;;;;; A373;YI SYLLABLE CHUP;Lo;0;L;;;;;N;;;;; A374;YI SYLLABLE CHURX;Lo;0;L;;;;;N;;;;; A375;YI SYLLABLE CHUR;Lo;0;L;;;;;N;;;;; A376;YI SYLLABLE CHYT;Lo;0;L;;;;;N;;;;; A377;YI SYLLABLE CHYX;Lo;0;L;;;;;N;;;;; A378;YI SYLLABLE CHY;Lo;0;L;;;;;N;;;;; A379;YI SYLLABLE CHYP;Lo;0;L;;;;;N;;;;; A37A;YI SYLLABLE CHYRX;Lo;0;L;;;;;N;;;;; A37B;YI SYLLABLE CHYR;Lo;0;L;;;;;N;;;;; A37C;YI SYLLABLE RRAX;Lo;0;L;;;;;N;;;;; A37D;YI SYLLABLE RRA;Lo;0;L;;;;;N;;;;; A37E;YI SYLLABLE RRUOX;Lo;0;L;;;;;N;;;;; A37F;YI SYLLABLE RRUO;Lo;0;L;;;;;N;;;;; A380;YI SYLLABLE RROT;Lo;0;L;;;;;N;;;;; A381;YI SYLLABLE RROX;Lo;0;L;;;;;N;;;;; A382;YI SYLLABLE RRO;Lo;0;L;;;;;N;;;;; A383;YI SYLLABLE RROP;Lo;0;L;;;;;N;;;;; A384;YI SYLLABLE RRET;Lo;0;L;;;;;N;;;;; A385;YI SYLLABLE RREX;Lo;0;L;;;;;N;;;;; A386;YI SYLLABLE RRE;Lo;0;L;;;;;N;;;;; A387;YI SYLLABLE RREP;Lo;0;L;;;;;N;;;;; A388;YI SYLLABLE RRUT;Lo;0;L;;;;;N;;;;; A389;YI SYLLABLE RRUX;Lo;0;L;;;;;N;;;;; A38A;YI SYLLABLE RRU;Lo;0;L;;;;;N;;;;; A38B;YI SYLLABLE RRUP;Lo;0;L;;;;;N;;;;; A38C;YI SYLLABLE RRURX;Lo;0;L;;;;;N;;;;; A38D;YI SYLLABLE RRUR;Lo;0;L;;;;;N;;;;; A38E;YI SYLLABLE RRYT;Lo;0;L;;;;;N;;;;; A38F;YI SYLLABLE RRYX;Lo;0;L;;;;;N;;;;; A390;YI SYLLABLE RRY;Lo;0;L;;;;;N;;;;; A391;YI SYLLABLE RRYP;Lo;0;L;;;;;N;;;;; A392;YI SYLLABLE RRYRX;Lo;0;L;;;;;N;;;;; A393;YI SYLLABLE RRYR;Lo;0;L;;;;;N;;;;; A394;YI SYLLABLE NRAT;Lo;0;L;;;;;N;;;;; A395;YI SYLLABLE NRAX;Lo;0;L;;;;;N;;;;; A396;YI SYLLABLE NRA;Lo;0;L;;;;;N;;;;; A397;YI SYLLABLE NRAP;Lo;0;L;;;;;N;;;;; A398;YI SYLLABLE NROX;Lo;0;L;;;;;N;;;;; A399;YI SYLLABLE NRO;Lo;0;L;;;;;N;;;;; A39A;YI SYLLABLE NROP;Lo;0;L;;;;;N;;;;; A39B;YI SYLLABLE NRET;Lo;0;L;;;;;N;;;;; A39C;YI SYLLABLE NREX;Lo;0;L;;;;;N;;;;; A39D;YI SYLLABLE NRE;Lo;0;L;;;;;N;;;;; A39E;YI SYLLABLE NREP;Lo;0;L;;;;;N;;;;; A39F;YI SYLLABLE NRUT;Lo;0;L;;;;;N;;;;; A3A0;YI SYLLABLE NRUX;Lo;0;L;;;;;N;;;;; A3A1;YI SYLLABLE NRU;Lo;0;L;;;;;N;;;;; A3A2;YI SYLLABLE NRUP;Lo;0;L;;;;;N;;;;; A3A3;YI SYLLABLE NRURX;Lo;0;L;;;;;N;;;;; A3A4;YI SYLLABLE NRUR;Lo;0;L;;;;;N;;;;; A3A5;YI SYLLABLE NRYT;Lo;0;L;;;;;N;;;;; A3A6;YI SYLLABLE NRYX;Lo;0;L;;;;;N;;;;; A3A7;YI SYLLABLE NRY;Lo;0;L;;;;;N;;;;; A3A8;YI SYLLABLE NRYP;Lo;0;L;;;;;N;;;;; A3A9;YI SYLLABLE NRYRX;Lo;0;L;;;;;N;;;;; A3AA;YI SYLLABLE NRYR;Lo;0;L;;;;;N;;;;; A3AB;YI SYLLABLE SHAT;Lo;0;L;;;;;N;;;;; A3AC;YI SYLLABLE SHAX;Lo;0;L;;;;;N;;;;; A3AD;YI SYLLABLE SHA;Lo;0;L;;;;;N;;;;; A3AE;YI SYLLABLE SHAP;Lo;0;L;;;;;N;;;;; A3AF;YI SYLLABLE SHUOX;Lo;0;L;;;;;N;;;;; A3B0;YI SYLLABLE SHUO;Lo;0;L;;;;;N;;;;; A3B1;YI SYLLABLE SHUOP;Lo;0;L;;;;;N;;;;; A3B2;YI SYLLABLE SHOT;Lo;0;L;;;;;N;;;;; A3B3;YI SYLLABLE SHOX;Lo;0;L;;;;;N;;;;; A3B4;YI SYLLABLE SHO;Lo;0;L;;;;;N;;;;; A3B5;YI SYLLABLE SHOP;Lo;0;L;;;;;N;;;;; A3B6;YI SYLLABLE SHET;Lo;0;L;;;;;N;;;;; A3B7;YI SYLLABLE SHEX;Lo;0;L;;;;;N;;;;; A3B8;YI SYLLABLE SHE;Lo;0;L;;;;;N;;;;; A3B9;YI SYLLABLE SHEP;Lo;0;L;;;;;N;;;;; A3BA;YI SYLLABLE SHUT;Lo;0;L;;;;;N;;;;; A3BB;YI SYLLABLE SHUX;Lo;0;L;;;;;N;;;;; A3BC;YI SYLLABLE SHU;Lo;0;L;;;;;N;;;;; A3BD;YI SYLLABLE SHUP;Lo;0;L;;;;;N;;;;; A3BE;YI SYLLABLE SHURX;Lo;0;L;;;;;N;;;;; A3BF;YI SYLLABLE SHUR;Lo;0;L;;;;;N;;;;; A3C0;YI SYLLABLE SHYT;Lo;0;L;;;;;N;;;;; A3C1;YI SYLLABLE SHYX;Lo;0;L;;;;;N;;;;; A3C2;YI SYLLABLE SHY;Lo;0;L;;;;;N;;;;; A3C3;YI SYLLABLE SHYP;Lo;0;L;;;;;N;;;;; A3C4;YI SYLLABLE SHYRX;Lo;0;L;;;;;N;;;;; A3C5;YI SYLLABLE SHYR;Lo;0;L;;;;;N;;;;; A3C6;YI SYLLABLE RAT;Lo;0;L;;;;;N;;;;; A3C7;YI SYLLABLE RAX;Lo;0;L;;;;;N;;;;; A3C8;YI SYLLABLE RA;Lo;0;L;;;;;N;;;;; A3C9;YI SYLLABLE RAP;Lo;0;L;;;;;N;;;;; A3CA;YI SYLLABLE RUOX;Lo;0;L;;;;;N;;;;; A3CB;YI SYLLABLE RUO;Lo;0;L;;;;;N;;;;; A3CC;YI SYLLABLE RUOP;Lo;0;L;;;;;N;;;;; A3CD;YI SYLLABLE ROT;Lo;0;L;;;;;N;;;;; A3CE;YI SYLLABLE ROX;Lo;0;L;;;;;N;;;;; A3CF;YI SYLLABLE RO;Lo;0;L;;;;;N;;;;; A3D0;YI SYLLABLE ROP;Lo;0;L;;;;;N;;;;; A3D1;YI SYLLABLE REX;Lo;0;L;;;;;N;;;;; A3D2;YI SYLLABLE RE;Lo;0;L;;;;;N;;;;; A3D3;YI SYLLABLE REP;Lo;0;L;;;;;N;;;;; A3D4;YI SYLLABLE RUT;Lo;0;L;;;;;N;;;;; A3D5;YI SYLLABLE RUX;Lo;0;L;;;;;N;;;;; A3D6;YI SYLLABLE RU;Lo;0;L;;;;;N;;;;; A3D7;YI SYLLABLE RUP;Lo;0;L;;;;;N;;;;; A3D8;YI SYLLABLE RURX;Lo;0;L;;;;;N;;;;; A3D9;YI SYLLABLE RUR;Lo;0;L;;;;;N;;;;; A3DA;YI SYLLABLE RYT;Lo;0;L;;;;;N;;;;; A3DB;YI SYLLABLE RYX;Lo;0;L;;;;;N;;;;; A3DC;YI SYLLABLE RY;Lo;0;L;;;;;N;;;;; A3DD;YI SYLLABLE RYP;Lo;0;L;;;;;N;;;;; A3DE;YI SYLLABLE RYRX;Lo;0;L;;;;;N;;;;; A3DF;YI SYLLABLE RYR;Lo;0;L;;;;;N;;;;; A3E0;YI SYLLABLE JIT;Lo;0;L;;;;;N;;;;; A3E1;YI SYLLABLE JIX;Lo;0;L;;;;;N;;;;; A3E2;YI SYLLABLE JI;Lo;0;L;;;;;N;;;;; A3E3;YI SYLLABLE JIP;Lo;0;L;;;;;N;;;;; A3E4;YI SYLLABLE JIET;Lo;0;L;;;;;N;;;;; A3E5;YI SYLLABLE JIEX;Lo;0;L;;;;;N;;;;; A3E6;YI SYLLABLE JIE;Lo;0;L;;;;;N;;;;; A3E7;YI SYLLABLE JIEP;Lo;0;L;;;;;N;;;;; A3E8;YI SYLLABLE JUOT;Lo;0;L;;;;;N;;;;; A3E9;YI SYLLABLE JUOX;Lo;0;L;;;;;N;;;;; A3EA;YI SYLLABLE JUO;Lo;0;L;;;;;N;;;;; A3EB;YI SYLLABLE JUOP;Lo;0;L;;;;;N;;;;; A3EC;YI SYLLABLE JOT;Lo;0;L;;;;;N;;;;; A3ED;YI SYLLABLE JOX;Lo;0;L;;;;;N;;;;; A3EE;YI SYLLABLE JO;Lo;0;L;;;;;N;;;;; A3EF;YI SYLLABLE JOP;Lo;0;L;;;;;N;;;;; A3F0;YI SYLLABLE JUT;Lo;0;L;;;;;N;;;;; A3F1;YI SYLLABLE JUX;Lo;0;L;;;;;N;;;;; A3F2;YI SYLLABLE JU;Lo;0;L;;;;;N;;;;; A3F3;YI SYLLABLE JUP;Lo;0;L;;;;;N;;;;; A3F4;YI SYLLABLE JURX;Lo;0;L;;;;;N;;;;; A3F5;YI SYLLABLE JUR;Lo;0;L;;;;;N;;;;; A3F6;YI SYLLABLE JYT;Lo;0;L;;;;;N;;;;; A3F7;YI SYLLABLE JYX;Lo;0;L;;;;;N;;;;; A3F8;YI SYLLABLE JY;Lo;0;L;;;;;N;;;;; A3F9;YI SYLLABLE JYP;Lo;0;L;;;;;N;;;;; A3FA;YI SYLLABLE JYRX;Lo;0;L;;;;;N;;;;; A3FB;YI SYLLABLE JYR;Lo;0;L;;;;;N;;;;; A3FC;YI SYLLABLE QIT;Lo;0;L;;;;;N;;;;; A3FD;YI SYLLABLE QIX;Lo;0;L;;;;;N;;;;; A3FE;YI SYLLABLE QI;Lo;0;L;;;;;N;;;;; A3FF;YI SYLLABLE QIP;Lo;0;L;;;;;N;;;;; A400;YI SYLLABLE QIET;Lo;0;L;;;;;N;;;;; A401;YI SYLLABLE QIEX;Lo;0;L;;;;;N;;;;; A402;YI SYLLABLE QIE;Lo;0;L;;;;;N;;;;; A403;YI SYLLABLE QIEP;Lo;0;L;;;;;N;;;;; A404;YI SYLLABLE QUOT;Lo;0;L;;;;;N;;;;; A405;YI SYLLABLE QUOX;Lo;0;L;;;;;N;;;;; A406;YI SYLLABLE QUO;Lo;0;L;;;;;N;;;;; A407;YI SYLLABLE QUOP;Lo;0;L;;;;;N;;;;; A408;YI SYLLABLE QOT;Lo;0;L;;;;;N;;;;; A409;YI SYLLABLE QOX;Lo;0;L;;;;;N;;;;; A40A;YI SYLLABLE QO;Lo;0;L;;;;;N;;;;; A40B;YI SYLLABLE QOP;Lo;0;L;;;;;N;;;;; A40C;YI SYLLABLE QUT;Lo;0;L;;;;;N;;;;; A40D;YI SYLLABLE QUX;Lo;0;L;;;;;N;;;;; A40E;YI SYLLABLE QU;Lo;0;L;;;;;N;;;;; A40F;YI SYLLABLE QUP;Lo;0;L;;;;;N;;;;; A410;YI SYLLABLE QURX;Lo;0;L;;;;;N;;;;; A411;YI SYLLABLE QUR;Lo;0;L;;;;;N;;;;; A412;YI SYLLABLE QYT;Lo;0;L;;;;;N;;;;; A413;YI SYLLABLE QYX;Lo;0;L;;;;;N;;;;; A414;YI SYLLABLE QY;Lo;0;L;;;;;N;;;;; A415;YI SYLLABLE QYP;Lo;0;L;;;;;N;;;;; A416;YI SYLLABLE QYRX;Lo;0;L;;;;;N;;;;; A417;YI SYLLABLE QYR;Lo;0;L;;;;;N;;;;; A418;YI SYLLABLE JJIT;Lo;0;L;;;;;N;;;;; A419;YI SYLLABLE JJIX;Lo;0;L;;;;;N;;;;; A41A;YI SYLLABLE JJI;Lo;0;L;;;;;N;;;;; A41B;YI SYLLABLE JJIP;Lo;0;L;;;;;N;;;;; A41C;YI SYLLABLE JJIET;Lo;0;L;;;;;N;;;;; A41D;YI SYLLABLE JJIEX;Lo;0;L;;;;;N;;;;; A41E;YI SYLLABLE JJIE;Lo;0;L;;;;;N;;;;; A41F;YI SYLLABLE JJIEP;Lo;0;L;;;;;N;;;;; A420;YI SYLLABLE JJUOX;Lo;0;L;;;;;N;;;;; A421;YI SYLLABLE JJUO;Lo;0;L;;;;;N;;;;; A422;YI SYLLABLE JJUOP;Lo;0;L;;;;;N;;;;; A423;YI SYLLABLE JJOT;Lo;0;L;;;;;N;;;;; A424;YI SYLLABLE JJOX;Lo;0;L;;;;;N;;;;; A425;YI SYLLABLE JJO;Lo;0;L;;;;;N;;;;; A426;YI SYLLABLE JJOP;Lo;0;L;;;;;N;;;;; A427;YI SYLLABLE JJUT;Lo;0;L;;;;;N;;;;; A428;YI SYLLABLE JJUX;Lo;0;L;;;;;N;;;;; A429;YI SYLLABLE JJU;Lo;0;L;;;;;N;;;;; A42A;YI SYLLABLE JJUP;Lo;0;L;;;;;N;;;;; A42B;YI SYLLABLE JJURX;Lo;0;L;;;;;N;;;;; A42C;YI SYLLABLE JJUR;Lo;0;L;;;;;N;;;;; A42D;YI SYLLABLE JJYT;Lo;0;L;;;;;N;;;;; A42E;YI SYLLABLE JJYX;Lo;0;L;;;;;N;;;;; A42F;YI SYLLABLE JJY;Lo;0;L;;;;;N;;;;; A430;YI SYLLABLE JJYP;Lo;0;L;;;;;N;;;;; A431;YI SYLLABLE NJIT;Lo;0;L;;;;;N;;;;; A432;YI SYLLABLE NJIX;Lo;0;L;;;;;N;;;;; A433;YI SYLLABLE NJI;Lo;0;L;;;;;N;;;;; A434;YI SYLLABLE NJIP;Lo;0;L;;;;;N;;;;; A435;YI SYLLABLE NJIET;Lo;0;L;;;;;N;;;;; A436;YI SYLLABLE NJIEX;Lo;0;L;;;;;N;;;;; A437;YI SYLLABLE NJIE;Lo;0;L;;;;;N;;;;; A438;YI SYLLABLE NJIEP;Lo;0;L;;;;;N;;;;; A439;YI SYLLABLE NJUOX;Lo;0;L;;;;;N;;;;; A43A;YI SYLLABLE NJUO;Lo;0;L;;;;;N;;;;; A43B;YI SYLLABLE NJOT;Lo;0;L;;;;;N;;;;; A43C;YI SYLLABLE NJOX;Lo;0;L;;;;;N;;;;; A43D;YI SYLLABLE NJO;Lo;0;L;;;;;N;;;;; A43E;YI SYLLABLE NJOP;Lo;0;L;;;;;N;;;;; A43F;YI SYLLABLE NJUX;Lo;0;L;;;;;N;;;;; A440;YI SYLLABLE NJU;Lo;0;L;;;;;N;;;;; A441;YI SYLLABLE NJUP;Lo;0;L;;;;;N;;;;; A442;YI SYLLABLE NJURX;Lo;0;L;;;;;N;;;;; A443;YI SYLLABLE NJUR;Lo;0;L;;;;;N;;;;; A444;YI SYLLABLE NJYT;Lo;0;L;;;;;N;;;;; A445;YI SYLLABLE NJYX;Lo;0;L;;;;;N;;;;; A446;YI SYLLABLE NJY;Lo;0;L;;;;;N;;;;; A447;YI SYLLABLE NJYP;Lo;0;L;;;;;N;;;;; A448;YI SYLLABLE NJYRX;Lo;0;L;;;;;N;;;;; A449;YI SYLLABLE NJYR;Lo;0;L;;;;;N;;;;; A44A;YI SYLLABLE NYIT;Lo;0;L;;;;;N;;;;; A44B;YI SYLLABLE NYIX;Lo;0;L;;;;;N;;;;; A44C;YI SYLLABLE NYI;Lo;0;L;;;;;N;;;;; A44D;YI SYLLABLE NYIP;Lo;0;L;;;;;N;;;;; A44E;YI SYLLABLE NYIET;Lo;0;L;;;;;N;;;;; A44F;YI SYLLABLE NYIEX;Lo;0;L;;;;;N;;;;; A450;YI SYLLABLE NYIE;Lo;0;L;;;;;N;;;;; A451;YI SYLLABLE NYIEP;Lo;0;L;;;;;N;;;;; A452;YI SYLLABLE NYUOX;Lo;0;L;;;;;N;;;;; A453;YI SYLLABLE NYUO;Lo;0;L;;;;;N;;;;; A454;YI SYLLABLE NYUOP;Lo;0;L;;;;;N;;;;; A455;YI SYLLABLE NYOT;Lo;0;L;;;;;N;;;;; A456;YI SYLLABLE NYOX;Lo;0;L;;;;;N;;;;; A457;YI SYLLABLE NYO;Lo;0;L;;;;;N;;;;; A458;YI SYLLABLE NYOP;Lo;0;L;;;;;N;;;;; A459;YI SYLLABLE NYUT;Lo;0;L;;;;;N;;;;; A45A;YI SYLLABLE NYUX;Lo;0;L;;;;;N;;;;; A45B;YI SYLLABLE NYU;Lo;0;L;;;;;N;;;;; A45C;YI SYLLABLE NYUP;Lo;0;L;;;;;N;;;;; A45D;YI SYLLABLE XIT;Lo;0;L;;;;;N;;;;; A45E;YI SYLLABLE XIX;Lo;0;L;;;;;N;;;;; A45F;YI SYLLABLE XI;Lo;0;L;;;;;N;;;;; A460;YI SYLLABLE XIP;Lo;0;L;;;;;N;;;;; A461;YI SYLLABLE XIET;Lo;0;L;;;;;N;;;;; A462;YI SYLLABLE XIEX;Lo;0;L;;;;;N;;;;; A463;YI SYLLABLE XIE;Lo;0;L;;;;;N;;;;; A464;YI SYLLABLE XIEP;Lo;0;L;;;;;N;;;;; A465;YI SYLLABLE XUOX;Lo;0;L;;;;;N;;;;; A466;YI SYLLABLE XUO;Lo;0;L;;;;;N;;;;; A467;YI SYLLABLE XOT;Lo;0;L;;;;;N;;;;; A468;YI SYLLABLE XOX;Lo;0;L;;;;;N;;;;; A469;YI SYLLABLE XO;Lo;0;L;;;;;N;;;;; A46A;YI SYLLABLE XOP;Lo;0;L;;;;;N;;;;; A46B;YI SYLLABLE XYT;Lo;0;L;;;;;N;;;;; A46C;YI SYLLABLE XYX;Lo;0;L;;;;;N;;;;; A46D;YI SYLLABLE XY;Lo;0;L;;;;;N;;;;; A46E;YI SYLLABLE XYP;Lo;0;L;;;;;N;;;;; A46F;YI SYLLABLE XYRX;Lo;0;L;;;;;N;;;;; A470;YI SYLLABLE XYR;Lo;0;L;;;;;N;;;;; A471;YI SYLLABLE YIT;Lo;0;L;;;;;N;;;;; A472;YI SYLLABLE YIX;Lo;0;L;;;;;N;;;;; A473;YI SYLLABLE YI;Lo;0;L;;;;;N;;;;; A474;YI SYLLABLE YIP;Lo;0;L;;;;;N;;;;; A475;YI SYLLABLE YIET;Lo;0;L;;;;;N;;;;; A476;YI SYLLABLE YIEX;Lo;0;L;;;;;N;;;;; A477;YI SYLLABLE YIE;Lo;0;L;;;;;N;;;;; A478;YI SYLLABLE YIEP;Lo;0;L;;;;;N;;;;; A479;YI SYLLABLE YUOT;Lo;0;L;;;;;N;;;;; A47A;YI SYLLABLE YUOX;Lo;0;L;;;;;N;;;;; A47B;YI SYLLABLE YUO;Lo;0;L;;;;;N;;;;; A47C;YI SYLLABLE YUOP;Lo;0;L;;;;;N;;;;; A47D;YI SYLLABLE YOT;Lo;0;L;;;;;N;;;;; A47E;YI SYLLABLE YOX;Lo;0;L;;;;;N;;;;; A47F;YI SYLLABLE YO;Lo;0;L;;;;;N;;;;; A480;YI SYLLABLE YOP;Lo;0;L;;;;;N;;;;; A481;YI SYLLABLE YUT;Lo;0;L;;;;;N;;;;; A482;YI SYLLABLE YUX;Lo;0;L;;;;;N;;;;; A483;YI SYLLABLE YU;Lo;0;L;;;;;N;;;;; A484;YI SYLLABLE YUP;Lo;0;L;;;;;N;;;;; A485;YI SYLLABLE YURX;Lo;0;L;;;;;N;;;;; A486;YI SYLLABLE YUR;Lo;0;L;;;;;N;;;;; A487;YI SYLLABLE YYT;Lo;0;L;;;;;N;;;;; A488;YI SYLLABLE YYX;Lo;0;L;;;;;N;;;;; A489;YI SYLLABLE YY;Lo;0;L;;;;;N;;;;; A48A;YI SYLLABLE YYP;Lo;0;L;;;;;N;;;;; A48B;YI SYLLABLE YYRX;Lo;0;L;;;;;N;;;;; A48C;YI SYLLABLE YYR;Lo;0;L;;;;;N;;;;; A490;YI RADICAL QOT;So;0;ON;;;;;N;;;;; A491;YI RADICAL LI;So;0;ON;;;;;N;;;;; A492;YI RADICAL KIT;So;0;ON;;;;;N;;;;; A493;YI RADICAL NYIP;So;0;ON;;;;;N;;;;; A494;YI RADICAL CYP;So;0;ON;;;;;N;;;;; A495;YI RADICAL SSI;So;0;ON;;;;;N;;;;; A496;YI RADICAL GGOP;So;0;ON;;;;;N;;;;; A497;YI RADICAL GEP;So;0;ON;;;;;N;;;;; A498;YI RADICAL MI;So;0;ON;;;;;N;;;;; A499;YI RADICAL HXIT;So;0;ON;;;;;N;;;;; A49A;YI RADICAL LYR;So;0;ON;;;;;N;;;;; A49B;YI RADICAL BBUT;So;0;ON;;;;;N;;;;; A49C;YI RADICAL MOP;So;0;ON;;;;;N;;;;; A49D;YI RADICAL YO;So;0;ON;;;;;N;;;;; A49E;YI RADICAL PUT;So;0;ON;;;;;N;;;;; A49F;YI RADICAL HXUO;So;0;ON;;;;;N;;;;; A4A0;YI RADICAL TAT;So;0;ON;;;;;N;;;;; A4A1;YI RADICAL GA;So;0;ON;;;;;N;;;;; A4A2;YI RADICAL ZUP;So;0;ON;;;;;N;;;;; A4A3;YI RADICAL CYT;So;0;ON;;;;;N;;;;; A4A4;YI RADICAL DDUR;So;0;ON;;;;;N;;;;; A4A5;YI RADICAL BUR;So;0;ON;;;;;N;;;;; A4A6;YI RADICAL GGUO;So;0;ON;;;;;N;;;;; A4A7;YI RADICAL NYOP;So;0;ON;;;;;N;;;;; A4A8;YI RADICAL TU;So;0;ON;;;;;N;;;;; A4A9;YI RADICAL OP;So;0;ON;;;;;N;;;;; A4AA;YI RADICAL JJUT;So;0;ON;;;;;N;;;;; A4AB;YI RADICAL ZOT;So;0;ON;;;;;N;;;;; A4AC;YI RADICAL PYT;So;0;ON;;;;;N;;;;; A4AD;YI RADICAL HMO;So;0;ON;;;;;N;;;;; A4AE;YI RADICAL YIT;So;0;ON;;;;;N;;;;; A4AF;YI RADICAL VUR;So;0;ON;;;;;N;;;;; A4B0;YI RADICAL SHY;So;0;ON;;;;;N;;;;; A4B1;YI RADICAL VEP;So;0;ON;;;;;N;;;;; A4B2;YI RADICAL ZA;So;0;ON;;;;;N;;;;; A4B3;YI RADICAL JO;So;0;ON;;;;;N;;;;; A4B4;YI RADICAL NZUP;So;0;ON;;;;;N;;;;; A4B5;YI RADICAL JJY;So;0;ON;;;;;N;;;;; A4B6;YI RADICAL GOT;So;0;ON;;;;;N;;;;; A4B7;YI RADICAL JJIE;So;0;ON;;;;;N;;;;; A4B8;YI RADICAL WO;So;0;ON;;;;;N;;;;; A4B9;YI RADICAL DU;So;0;ON;;;;;N;;;;; A4BA;YI RADICAL SHUR;So;0;ON;;;;;N;;;;; A4BB;YI RADICAL LIE;So;0;ON;;;;;N;;;;; A4BC;YI RADICAL CY;So;0;ON;;;;;N;;;;; A4BD;YI RADICAL CUOP;So;0;ON;;;;;N;;;;; A4BE;YI RADICAL CIP;So;0;ON;;;;;N;;;;; A4BF;YI RADICAL HXOP;So;0;ON;;;;;N;;;;; A4C0;YI RADICAL SHAT;So;0;ON;;;;;N;;;;; A4C1;YI RADICAL ZUR;So;0;ON;;;;;N;;;;; A4C2;YI RADICAL SHOP;So;0;ON;;;;;N;;;;; A4C3;YI RADICAL CHE;So;0;ON;;;;;N;;;;; A4C4;YI RADICAL ZZIET;So;0;ON;;;;;N;;;;; A4C5;YI RADICAL NBIE;So;0;ON;;;;;N;;;;; A4C6;YI RADICAL KE;So;0;ON;;;;;N;;;;; A4D0;LISU LETTER BA;Lo;0;L;;;;;N;;;;; A4D1;LISU LETTER PA;Lo;0;L;;;;;N;;;;; A4D2;LISU LETTER PHA;Lo;0;L;;;;;N;;;;; A4D3;LISU LETTER DA;Lo;0;L;;;;;N;;;;; A4D4;LISU LETTER TA;Lo;0;L;;;;;N;;;;; A4D5;LISU LETTER THA;Lo;0;L;;;;;N;;;;; A4D6;LISU LETTER GA;Lo;0;L;;;;;N;;;;; A4D7;LISU LETTER KA;Lo;0;L;;;;;N;;;;; A4D8;LISU LETTER KHA;Lo;0;L;;;;;N;;;;; A4D9;LISU LETTER JA;Lo;0;L;;;;;N;;;;; A4DA;LISU LETTER CA;Lo;0;L;;;;;N;;;;; A4DB;LISU LETTER CHA;Lo;0;L;;;;;N;;;;; A4DC;LISU LETTER DZA;Lo;0;L;;;;;N;;;;; A4DD;LISU LETTER TSA;Lo;0;L;;;;;N;;;;; A4DE;LISU LETTER TSHA;Lo;0;L;;;;;N;;;;; A4DF;LISU LETTER MA;Lo;0;L;;;;;N;;;;; A4E0;LISU LETTER NA;Lo;0;L;;;;;N;;;;; A4E1;LISU LETTER LA;Lo;0;L;;;;;N;;;;; A4E2;LISU LETTER SA;Lo;0;L;;;;;N;;;;; A4E3;LISU LETTER ZHA;Lo;0;L;;;;;N;;;;; A4E4;LISU LETTER ZA;Lo;0;L;;;;;N;;;;; A4E5;LISU LETTER NGA;Lo;0;L;;;;;N;;;;; A4E6;LISU LETTER HA;Lo;0;L;;;;;N;;;;; A4E7;LISU LETTER XA;Lo;0;L;;;;;N;;;;; A4E8;LISU LETTER HHA;Lo;0;L;;;;;N;;;;; A4E9;LISU LETTER FA;Lo;0;L;;;;;N;;;;; A4EA;LISU LETTER WA;Lo;0;L;;;;;N;;;;; A4EB;LISU LETTER SHA;Lo;0;L;;;;;N;;;;; A4EC;LISU LETTER YA;Lo;0;L;;;;;N;;;;; A4ED;LISU LETTER GHA;Lo;0;L;;;;;N;;;;; A4EE;LISU LETTER A;Lo;0;L;;;;;N;;;;; A4EF;LISU LETTER AE;Lo;0;L;;;;;N;;;;; A4F0;LISU LETTER E;Lo;0;L;;;;;N;;;;; A4F1;LISU LETTER EU;Lo;0;L;;;;;N;;;;; A4F2;LISU LETTER I;Lo;0;L;;;;;N;;;;; A4F3;LISU LETTER O;Lo;0;L;;;;;N;;;;; A4F4;LISU LETTER U;Lo;0;L;;;;;N;;;;; A4F5;LISU LETTER UE;Lo;0;L;;;;;N;;;;; A4F6;LISU LETTER UH;Lo;0;L;;;;;N;;;;; A4F7;LISU LETTER OE;Lo;0;L;;;;;N;;;;; A4F8;LISU LETTER TONE MYA TI;Lm;0;L;;;;;N;;;;; A4F9;LISU LETTER TONE NA PO;Lm;0;L;;;;;N;;;;; A4FA;LISU LETTER TONE MYA CYA;Lm;0;L;;;;;N;;;;; A4FB;LISU LETTER TONE MYA BO;Lm;0;L;;;;;N;;;;; A4FC;LISU LETTER TONE MYA NA;Lm;0;L;;;;;N;;;;; A4FD;LISU LETTER TONE MYA JEU;Lm;0;L;;;;;N;;;;; A4FE;LISU PUNCTUATION COMMA;Po;0;L;;;;;N;;;;; A4FF;LISU PUNCTUATION FULL STOP;Po;0;L;;;;;N;;;;; A500;VAI SYLLABLE EE;Lo;0;L;;;;;N;;;;; A501;VAI SYLLABLE EEN;Lo;0;L;;;;;N;;;;; A502;VAI SYLLABLE HEE;Lo;0;L;;;;;N;;;;; A503;VAI SYLLABLE WEE;Lo;0;L;;;;;N;;;;; A504;VAI SYLLABLE WEEN;Lo;0;L;;;;;N;;;;; A505;VAI SYLLABLE PEE;Lo;0;L;;;;;N;;;;; A506;VAI SYLLABLE BHEE;Lo;0;L;;;;;N;;;;; A507;VAI SYLLABLE BEE;Lo;0;L;;;;;N;;;;; A508;VAI SYLLABLE MBEE;Lo;0;L;;;;;N;;;;; A509;VAI SYLLABLE KPEE;Lo;0;L;;;;;N;;;;; A50A;VAI SYLLABLE MGBEE;Lo;0;L;;;;;N;;;;; A50B;VAI SYLLABLE GBEE;Lo;0;L;;;;;N;;;;; A50C;VAI SYLLABLE FEE;Lo;0;L;;;;;N;;;;; A50D;VAI SYLLABLE VEE;Lo;0;L;;;;;N;;;;; A50E;VAI SYLLABLE TEE;Lo;0;L;;;;;N;;;;; A50F;VAI SYLLABLE THEE;Lo;0;L;;;;;N;;;;; A510;VAI SYLLABLE DHEE;Lo;0;L;;;;;N;;;;; A511;VAI SYLLABLE DHHEE;Lo;0;L;;;;;N;;;;; A512;VAI SYLLABLE LEE;Lo;0;L;;;;;N;;;;; A513;VAI SYLLABLE REE;Lo;0;L;;;;;N;;;;; A514;VAI SYLLABLE DEE;Lo;0;L;;;;;N;;;;; A515;VAI SYLLABLE NDEE;Lo;0;L;;;;;N;;;;; A516;VAI SYLLABLE SEE;Lo;0;L;;;;;N;;;;; A517;VAI SYLLABLE SHEE;Lo;0;L;;;;;N;;;;; A518;VAI SYLLABLE ZEE;Lo;0;L;;;;;N;;;;; A519;VAI SYLLABLE ZHEE;Lo;0;L;;;;;N;;;;; A51A;VAI SYLLABLE CEE;Lo;0;L;;;;;N;;;;; A51B;VAI SYLLABLE JEE;Lo;0;L;;;;;N;;;;; A51C;VAI SYLLABLE NJEE;Lo;0;L;;;;;N;;;;; A51D;VAI SYLLABLE YEE;Lo;0;L;;;;;N;;;;; A51E;VAI SYLLABLE KEE;Lo;0;L;;;;;N;;;;; A51F;VAI SYLLABLE NGGEE;Lo;0;L;;;;;N;;;;; A520;VAI SYLLABLE GEE;Lo;0;L;;;;;N;;;;; A521;VAI SYLLABLE MEE;Lo;0;L;;;;;N;;;;; A522;VAI SYLLABLE NEE;Lo;0;L;;;;;N;;;;; A523;VAI SYLLABLE NYEE;Lo;0;L;;;;;N;;;;; A524;VAI SYLLABLE I;Lo;0;L;;;;;N;;;;; A525;VAI SYLLABLE IN;Lo;0;L;;;;;N;;;;; A526;VAI SYLLABLE HI;Lo;0;L;;;;;N;;;;; A527;VAI SYLLABLE HIN;Lo;0;L;;;;;N;;;;; A528;VAI SYLLABLE WI;Lo;0;L;;;;;N;;;;; A529;VAI SYLLABLE WIN;Lo;0;L;;;;;N;;;;; A52A;VAI SYLLABLE PI;Lo;0;L;;;;;N;;;;; A52B;VAI SYLLABLE BHI;Lo;0;L;;;;;N;;;;; A52C;VAI SYLLABLE BI;Lo;0;L;;;;;N;;;;; A52D;VAI SYLLABLE MBI;Lo;0;L;;;;;N;;;;; A52E;VAI SYLLABLE KPI;Lo;0;L;;;;;N;;;;; A52F;VAI SYLLABLE MGBI;Lo;0;L;;;;;N;;;;; A530;VAI SYLLABLE GBI;Lo;0;L;;;;;N;;;;; A531;VAI SYLLABLE FI;Lo;0;L;;;;;N;;;;; A532;VAI SYLLABLE VI;Lo;0;L;;;;;N;;;;; A533;VAI SYLLABLE TI;Lo;0;L;;;;;N;;;;; A534;VAI SYLLABLE THI;Lo;0;L;;;;;N;;;;; A535;VAI SYLLABLE DHI;Lo;0;L;;;;;N;;;;; A536;VAI SYLLABLE DHHI;Lo;0;L;;;;;N;;;;; A537;VAI SYLLABLE LI;Lo;0;L;;;;;N;;;;; A538;VAI SYLLABLE RI;Lo;0;L;;;;;N;;;;; A539;VAI SYLLABLE DI;Lo;0;L;;;;;N;;;;; A53A;VAI SYLLABLE NDI;Lo;0;L;;;;;N;;;;; A53B;VAI SYLLABLE SI;Lo;0;L;;;;;N;;;;; A53C;VAI SYLLABLE SHI;Lo;0;L;;;;;N;;;;; A53D;VAI SYLLABLE ZI;Lo;0;L;;;;;N;;;;; A53E;VAI SYLLABLE ZHI;Lo;0;L;;;;;N;;;;; A53F;VAI SYLLABLE CI;Lo;0;L;;;;;N;;;;; A540;VAI SYLLABLE JI;Lo;0;L;;;;;N;;;;; A541;VAI SYLLABLE NJI;Lo;0;L;;;;;N;;;;; A542;VAI SYLLABLE YI;Lo;0;L;;;;;N;;;;; A543;VAI SYLLABLE KI;Lo;0;L;;;;;N;;;;; A544;VAI SYLLABLE NGGI;Lo;0;L;;;;;N;;;;; A545;VAI SYLLABLE GI;Lo;0;L;;;;;N;;;;; A546;VAI SYLLABLE MI;Lo;0;L;;;;;N;;;;; A547;VAI SYLLABLE NI;Lo;0;L;;;;;N;;;;; A548;VAI SYLLABLE NYI;Lo;0;L;;;;;N;;;;; A549;VAI SYLLABLE A;Lo;0;L;;;;;N;;;;; A54A;VAI SYLLABLE AN;Lo;0;L;;;;;N;;;;; A54B;VAI SYLLABLE NGAN;Lo;0;L;;;;;N;;;;; A54C;VAI SYLLABLE HA;Lo;0;L;;;;;N;;;;; A54D;VAI SYLLABLE HAN;Lo;0;L;;;;;N;;;;; A54E;VAI SYLLABLE WA;Lo;0;L;;;;;N;;;;; A54F;VAI SYLLABLE WAN;Lo;0;L;;;;;N;;;;; A550;VAI SYLLABLE PA;Lo;0;L;;;;;N;;;;; A551;VAI SYLLABLE BHA;Lo;0;L;;;;;N;;;;; A552;VAI SYLLABLE BA;Lo;0;L;;;;;N;;;;; A553;VAI SYLLABLE MBA;Lo;0;L;;;;;N;;;;; A554;VAI SYLLABLE KPA;Lo;0;L;;;;;N;;;;; A555;VAI SYLLABLE KPAN;Lo;0;L;;;;;N;;;;; A556;VAI SYLLABLE MGBA;Lo;0;L;;;;;N;;;;; A557;VAI SYLLABLE GBA;Lo;0;L;;;;;N;;;;; A558;VAI SYLLABLE FA;Lo;0;L;;;;;N;;;;; A559;VAI SYLLABLE VA;Lo;0;L;;;;;N;;;;; A55A;VAI SYLLABLE TA;Lo;0;L;;;;;N;;;;; A55B;VAI SYLLABLE THA;Lo;0;L;;;;;N;;;;; A55C;VAI SYLLABLE DHA;Lo;0;L;;;;;N;;;;; A55D;VAI SYLLABLE DHHA;Lo;0;L;;;;;N;;;;; A55E;VAI SYLLABLE LA;Lo;0;L;;;;;N;;;;; A55F;VAI SYLLABLE RA;Lo;0;L;;;;;N;;;;; A560;VAI SYLLABLE DA;Lo;0;L;;;;;N;;;;; A561;VAI SYLLABLE NDA;Lo;0;L;;;;;N;;;;; A562;VAI SYLLABLE SA;Lo;0;L;;;;;N;;;;; A563;VAI SYLLABLE SHA;Lo;0;L;;;;;N;;;;; A564;VAI SYLLABLE ZA;Lo;0;L;;;;;N;;;;; A565;VAI SYLLABLE ZHA;Lo;0;L;;;;;N;;;;; A566;VAI SYLLABLE CA;Lo;0;L;;;;;N;;;;; A567;VAI SYLLABLE JA;Lo;0;L;;;;;N;;;;; A568;VAI SYLLABLE NJA;Lo;0;L;;;;;N;;;;; A569;VAI SYLLABLE YA;Lo;0;L;;;;;N;;;;; A56A;VAI SYLLABLE KA;Lo;0;L;;;;;N;;;;; A56B;VAI SYLLABLE KAN;Lo;0;L;;;;;N;;;;; A56C;VAI SYLLABLE NGGA;Lo;0;L;;;;;N;;;;; A56D;VAI SYLLABLE GA;Lo;0;L;;;;;N;;;;; A56E;VAI SYLLABLE MA;Lo;0;L;;;;;N;;;;; A56F;VAI SYLLABLE NA;Lo;0;L;;;;;N;;;;; A570;VAI SYLLABLE NYA;Lo;0;L;;;;;N;;;;; A571;VAI SYLLABLE OO;Lo;0;L;;;;;N;;;;; A572;VAI SYLLABLE OON;Lo;0;L;;;;;N;;;;; A573;VAI SYLLABLE HOO;Lo;0;L;;;;;N;;;;; A574;VAI SYLLABLE WOO;Lo;0;L;;;;;N;;;;; A575;VAI SYLLABLE WOON;Lo;0;L;;;;;N;;;;; A576;VAI SYLLABLE POO;Lo;0;L;;;;;N;;;;; A577;VAI SYLLABLE BHOO;Lo;0;L;;;;;N;;;;; A578;VAI SYLLABLE BOO;Lo;0;L;;;;;N;;;;; A579;VAI SYLLABLE MBOO;Lo;0;L;;;;;N;;;;; A57A;VAI SYLLABLE KPOO;Lo;0;L;;;;;N;;;;; A57B;VAI SYLLABLE MGBOO;Lo;0;L;;;;;N;;;;; A57C;VAI SYLLABLE GBOO;Lo;0;L;;;;;N;;;;; A57D;VAI SYLLABLE FOO;Lo;0;L;;;;;N;;;;; A57E;VAI SYLLABLE VOO;Lo;0;L;;;;;N;;;;; A57F;VAI SYLLABLE TOO;Lo;0;L;;;;;N;;;;; A580;VAI SYLLABLE THOO;Lo;0;L;;;;;N;;;;; A581;VAI SYLLABLE DHOO;Lo;0;L;;;;;N;;;;; A582;VAI SYLLABLE DHHOO;Lo;0;L;;;;;N;;;;; A583;VAI SYLLABLE LOO;Lo;0;L;;;;;N;;;;; A584;VAI SYLLABLE ROO;Lo;0;L;;;;;N;;;;; A585;VAI SYLLABLE DOO;Lo;0;L;;;;;N;;;;; A586;VAI SYLLABLE NDOO;Lo;0;L;;;;;N;;;;; A587;VAI SYLLABLE SOO;Lo;0;L;;;;;N;;;;; A588;VAI SYLLABLE SHOO;Lo;0;L;;;;;N;;;;; A589;VAI SYLLABLE ZOO;Lo;0;L;;;;;N;;;;; A58A;VAI SYLLABLE ZHOO;Lo;0;L;;;;;N;;;;; A58B;VAI SYLLABLE COO;Lo;0;L;;;;;N;;;;; A58C;VAI SYLLABLE JOO;Lo;0;L;;;;;N;;;;; A58D;VAI SYLLABLE NJOO;Lo;0;L;;;;;N;;;;; A58E;VAI SYLLABLE YOO;Lo;0;L;;;;;N;;;;; A58F;VAI SYLLABLE KOO;Lo;0;L;;;;;N;;;;; A590;VAI SYLLABLE NGGOO;Lo;0;L;;;;;N;;;;; A591;VAI SYLLABLE GOO;Lo;0;L;;;;;N;;;;; A592;VAI SYLLABLE MOO;Lo;0;L;;;;;N;;;;; A593;VAI SYLLABLE NOO;Lo;0;L;;;;;N;;;;; A594;VAI SYLLABLE NYOO;Lo;0;L;;;;;N;;;;; A595;VAI SYLLABLE U;Lo;0;L;;;;;N;;;;; A596;VAI SYLLABLE UN;Lo;0;L;;;;;N;;;;; A597;VAI SYLLABLE HU;Lo;0;L;;;;;N;;;;; A598;VAI SYLLABLE HUN;Lo;0;L;;;;;N;;;;; A599;VAI SYLLABLE WU;Lo;0;L;;;;;N;;;;; A59A;VAI SYLLABLE WUN;Lo;0;L;;;;;N;;;;; A59B;VAI SYLLABLE PU;Lo;0;L;;;;;N;;;;; A59C;VAI SYLLABLE BHU;Lo;0;L;;;;;N;;;;; A59D;VAI SYLLABLE BU;Lo;0;L;;;;;N;;;;; A59E;VAI SYLLABLE MBU;Lo;0;L;;;;;N;;;;; A59F;VAI SYLLABLE KPU;Lo;0;L;;;;;N;;;;; A5A0;VAI SYLLABLE MGBU;Lo;0;L;;;;;N;;;;; A5A1;VAI SYLLABLE GBU;Lo;0;L;;;;;N;;;;; A5A2;VAI SYLLABLE FU;Lo;0;L;;;;;N;;;;; A5A3;VAI SYLLABLE VU;Lo;0;L;;;;;N;;;;; A5A4;VAI SYLLABLE TU;Lo;0;L;;;;;N;;;;; A5A5;VAI SYLLABLE THU;Lo;0;L;;;;;N;;;;; A5A6;VAI SYLLABLE DHU;Lo;0;L;;;;;N;;;;; A5A7;VAI SYLLABLE DHHU;Lo;0;L;;;;;N;;;;; A5A8;VAI SYLLABLE LU;Lo;0;L;;;;;N;;;;; A5A9;VAI SYLLABLE RU;Lo;0;L;;;;;N;;;;; A5AA;VAI SYLLABLE DU;Lo;0;L;;;;;N;;;;; A5AB;VAI SYLLABLE NDU;Lo;0;L;;;;;N;;;;; A5AC;VAI SYLLABLE SU;Lo;0;L;;;;;N;;;;; A5AD;VAI SYLLABLE SHU;Lo;0;L;;;;;N;;;;; A5AE;VAI SYLLABLE ZU;Lo;0;L;;;;;N;;;;; A5AF;VAI SYLLABLE ZHU;Lo;0;L;;;;;N;;;;; A5B0;VAI SYLLABLE CU;Lo;0;L;;;;;N;;;;; A5B1;VAI SYLLABLE JU;Lo;0;L;;;;;N;;;;; A5B2;VAI SYLLABLE NJU;Lo;0;L;;;;;N;;;;; A5B3;VAI SYLLABLE YU;Lo;0;L;;;;;N;;;;; A5B4;VAI SYLLABLE KU;Lo;0;L;;;;;N;;;;; A5B5;VAI SYLLABLE NGGU;Lo;0;L;;;;;N;;;;; A5B6;VAI SYLLABLE GU;Lo;0;L;;;;;N;;;;; A5B7;VAI SYLLABLE MU;Lo;0;L;;;;;N;;;;; A5B8;VAI SYLLABLE NU;Lo;0;L;;;;;N;;;;; A5B9;VAI SYLLABLE NYU;Lo;0;L;;;;;N;;;;; A5BA;VAI SYLLABLE O;Lo;0;L;;;;;N;;;;; A5BB;VAI SYLLABLE ON;Lo;0;L;;;;;N;;;;; A5BC;VAI SYLLABLE NGON;Lo;0;L;;;;;N;;;;; A5BD;VAI SYLLABLE HO;Lo;0;L;;;;;N;;;;; A5BE;VAI SYLLABLE HON;Lo;0;L;;;;;N;;;;; A5BF;VAI SYLLABLE WO;Lo;0;L;;;;;N;;;;; A5C0;VAI SYLLABLE WON;Lo;0;L;;;;;N;;;;; A5C1;VAI SYLLABLE PO;Lo;0;L;;;;;N;;;;; A5C2;VAI SYLLABLE BHO;Lo;0;L;;;;;N;;;;; A5C3;VAI SYLLABLE BO;Lo;0;L;;;;;N;;;;; A5C4;VAI SYLLABLE MBO;Lo;0;L;;;;;N;;;;; A5C5;VAI SYLLABLE KPO;Lo;0;L;;;;;N;;;;; A5C6;VAI SYLLABLE MGBO;Lo;0;L;;;;;N;;;;; A5C7;VAI SYLLABLE GBO;Lo;0;L;;;;;N;;;;; A5C8;VAI SYLLABLE GBON;Lo;0;L;;;;;N;;;;; A5C9;VAI SYLLABLE FO;Lo;0;L;;;;;N;;;;; A5CA;VAI SYLLABLE VO;Lo;0;L;;;;;N;;;;; A5CB;VAI SYLLABLE TO;Lo;0;L;;;;;N;;;;; A5CC;VAI SYLLABLE THO;Lo;0;L;;;;;N;;;;; A5CD;VAI SYLLABLE DHO;Lo;0;L;;;;;N;;;;; A5CE;VAI SYLLABLE DHHO;Lo;0;L;;;;;N;;;;; A5CF;VAI SYLLABLE LO;Lo;0;L;;;;;N;;;;; A5D0;VAI SYLLABLE RO;Lo;0;L;;;;;N;;;;; A5D1;VAI SYLLABLE DO;Lo;0;L;;;;;N;;;;; A5D2;VAI SYLLABLE NDO;Lo;0;L;;;;;N;;;;; A5D3;VAI SYLLABLE SO;Lo;0;L;;;;;N;;;;; A5D4;VAI SYLLABLE SHO;Lo;0;L;;;;;N;;;;; A5D5;VAI SYLLABLE ZO;Lo;0;L;;;;;N;;;;; A5D6;VAI SYLLABLE ZHO;Lo;0;L;;;;;N;;;;; A5D7;VAI SYLLABLE CO;Lo;0;L;;;;;N;;;;; A5D8;VAI SYLLABLE JO;Lo;0;L;;;;;N;;;;; A5D9;VAI SYLLABLE NJO;Lo;0;L;;;;;N;;;;; A5DA;VAI SYLLABLE YO;Lo;0;L;;;;;N;;;;; A5DB;VAI SYLLABLE KO;Lo;0;L;;;;;N;;;;; A5DC;VAI SYLLABLE NGGO;Lo;0;L;;;;;N;;;;; A5DD;VAI SYLLABLE GO;Lo;0;L;;;;;N;;;;; A5DE;VAI SYLLABLE MO;Lo;0;L;;;;;N;;;;; A5DF;VAI SYLLABLE NO;Lo;0;L;;;;;N;;;;; A5E0;VAI SYLLABLE NYO;Lo;0;L;;;;;N;;;;; A5E1;VAI SYLLABLE E;Lo;0;L;;;;;N;;;;; A5E2;VAI SYLLABLE EN;Lo;0;L;;;;;N;;;;; A5E3;VAI SYLLABLE NGEN;Lo;0;L;;;;;N;;;;; A5E4;VAI SYLLABLE HE;Lo;0;L;;;;;N;;;;; A5E5;VAI SYLLABLE HEN;Lo;0;L;;;;;N;;;;; A5E6;VAI SYLLABLE WE;Lo;0;L;;;;;N;;;;; A5E7;VAI SYLLABLE WEN;Lo;0;L;;;;;N;;;;; A5E8;VAI SYLLABLE PE;Lo;0;L;;;;;N;;;;; A5E9;VAI SYLLABLE BHE;Lo;0;L;;;;;N;;;;; A5EA;VAI SYLLABLE BE;Lo;0;L;;;;;N;;;;; A5EB;VAI SYLLABLE MBE;Lo;0;L;;;;;N;;;;; A5EC;VAI SYLLABLE KPE;Lo;0;L;;;;;N;;;;; A5ED;VAI SYLLABLE KPEN;Lo;0;L;;;;;N;;;;; A5EE;VAI SYLLABLE MGBE;Lo;0;L;;;;;N;;;;; A5EF;VAI SYLLABLE GBE;Lo;0;L;;;;;N;;;;; A5F0;VAI SYLLABLE GBEN;Lo;0;L;;;;;N;;;;; A5F1;VAI SYLLABLE FE;Lo;0;L;;;;;N;;;;; A5F2;VAI SYLLABLE VE;Lo;0;L;;;;;N;;;;; A5F3;VAI SYLLABLE TE;Lo;0;L;;;;;N;;;;; A5F4;VAI SYLLABLE THE;Lo;0;L;;;;;N;;;;; A5F5;VAI SYLLABLE DHE;Lo;0;L;;;;;N;;;;; A5F6;VAI SYLLABLE DHHE;Lo;0;L;;;;;N;;;;; A5F7;VAI SYLLABLE LE;Lo;0;L;;;;;N;;;;; A5F8;VAI SYLLABLE RE;Lo;0;L;;;;;N;;;;; A5F9;VAI SYLLABLE DE;Lo;0;L;;;;;N;;;;; A5FA;VAI SYLLABLE NDE;Lo;0;L;;;;;N;;;;; A5FB;VAI SYLLABLE SE;Lo;0;L;;;;;N;;;;; A5FC;VAI SYLLABLE SHE;Lo;0;L;;;;;N;;;;; A5FD;VAI SYLLABLE ZE;Lo;0;L;;;;;N;;;;; A5FE;VAI SYLLABLE ZHE;Lo;0;L;;;;;N;;;;; A5FF;VAI SYLLABLE CE;Lo;0;L;;;;;N;;;;; A600;VAI SYLLABLE JE;Lo;0;L;;;;;N;;;;; A601;VAI SYLLABLE NJE;Lo;0;L;;;;;N;;;;; A602;VAI SYLLABLE YE;Lo;0;L;;;;;N;;;;; A603;VAI SYLLABLE KE;Lo;0;L;;;;;N;;;;; A604;VAI SYLLABLE NGGE;Lo;0;L;;;;;N;;;;; A605;VAI SYLLABLE NGGEN;Lo;0;L;;;;;N;;;;; A606;VAI SYLLABLE GE;Lo;0;L;;;;;N;;;;; A607;VAI SYLLABLE GEN;Lo;0;L;;;;;N;;;;; A608;VAI SYLLABLE ME;Lo;0;L;;;;;N;;;;; A609;VAI SYLLABLE NE;Lo;0;L;;;;;N;;;;; A60A;VAI SYLLABLE NYE;Lo;0;L;;;;;N;;;;; A60B;VAI SYLLABLE NG;Lo;0;L;;;;;N;;;;; A60C;VAI SYLLABLE LENGTHENER;Lm;0;L;;;;;N;;;;; A60D;VAI COMMA;Po;0;ON;;;;;N;;;;; A60E;VAI FULL STOP;Po;0;ON;;;;;N;;;;; A60F;VAI QUESTION MARK;Po;0;ON;;;;;N;;;;; A610;VAI SYLLABLE NDOLE FA;Lo;0;L;;;;;N;;;;; A611;VAI SYLLABLE NDOLE KA;Lo;0;L;;;;;N;;;;; A612;VAI SYLLABLE NDOLE SOO;Lo;0;L;;;;;N;;;;; A613;VAI SYMBOL FEENG;Lo;0;L;;;;;N;;;;; A614;VAI SYMBOL KEENG;Lo;0;L;;;;;N;;;;; A615;VAI SYMBOL TING;Lo;0;L;;;;;N;;;;; A616;VAI SYMBOL NII;Lo;0;L;;;;;N;;;;; A617;VAI SYMBOL BANG;Lo;0;L;;;;;N;;;;; A618;VAI SYMBOL FAA;Lo;0;L;;;;;N;;;;; A619;VAI SYMBOL TAA;Lo;0;L;;;;;N;;;;; A61A;VAI SYMBOL DANG;Lo;0;L;;;;;N;;;;; A61B;VAI SYMBOL DOONG;Lo;0;L;;;;;N;;;;; A61C;VAI SYMBOL KUNG;Lo;0;L;;;;;N;;;;; A61D;VAI SYMBOL TONG;Lo;0;L;;;;;N;;;;; A61E;VAI SYMBOL DO-O;Lo;0;L;;;;;N;;;;; A61F;VAI SYMBOL JONG;Lo;0;L;;;;;N;;;;; A620;VAI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; A621;VAI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; A622;VAI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; A623;VAI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; A624;VAI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; A625;VAI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; A626;VAI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; A627;VAI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; A628;VAI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; A629;VAI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; A62A;VAI SYLLABLE NDOLE MA;Lo;0;L;;;;;N;;;;; A62B;VAI SYLLABLE NDOLE DO;Lo;0;L;;;;;N;;;;; A640;CYRILLIC CAPITAL LETTER ZEMLYA;Lu;0;L;;;;;N;;;;A641; A641;CYRILLIC SMALL LETTER ZEMLYA;Ll;0;L;;;;;N;;;A640;;A640 A642;CYRILLIC CAPITAL LETTER DZELO;Lu;0;L;;;;;N;;;;A643; A643;CYRILLIC SMALL LETTER DZELO;Ll;0;L;;;;;N;;;A642;;A642 A644;CYRILLIC CAPITAL LETTER REVERSED DZE;Lu;0;L;;;;;N;;;;A645; A645;CYRILLIC SMALL LETTER REVERSED DZE;Ll;0;L;;;;;N;;;A644;;A644 A646;CYRILLIC CAPITAL LETTER IOTA;Lu;0;L;;;;;N;;;;A647; A647;CYRILLIC SMALL LETTER IOTA;Ll;0;L;;;;;N;;;A646;;A646 A648;CYRILLIC CAPITAL LETTER DJERV;Lu;0;L;;;;;N;;;;A649; A649;CYRILLIC SMALL LETTER DJERV;Ll;0;L;;;;;N;;;A648;;A648 A64A;CYRILLIC CAPITAL LETTER MONOGRAPH UK;Lu;0;L;;;;;N;;;;A64B; A64B;CYRILLIC SMALL LETTER MONOGRAPH UK;Ll;0;L;;;;;N;;;A64A;;A64A A64C;CYRILLIC CAPITAL LETTER BROAD OMEGA;Lu;0;L;;;;;N;;;;A64D; A64D;CYRILLIC SMALL LETTER BROAD OMEGA;Ll;0;L;;;;;N;;;A64C;;A64C A64E;CYRILLIC CAPITAL LETTER NEUTRAL YER;Lu;0;L;;;;;N;;;;A64F; A64F;CYRILLIC SMALL LETTER NEUTRAL YER;Ll;0;L;;;;;N;;;A64E;;A64E A650;CYRILLIC CAPITAL LETTER YERU WITH BACK YER;Lu;0;L;;;;;N;;;;A651; A651;CYRILLIC SMALL LETTER YERU WITH BACK YER;Ll;0;L;;;;;N;;;A650;;A650 A652;CYRILLIC CAPITAL LETTER IOTIFIED YAT;Lu;0;L;;;;;N;;;;A653; A653;CYRILLIC SMALL LETTER IOTIFIED YAT;Ll;0;L;;;;;N;;;A652;;A652 A654;CYRILLIC CAPITAL LETTER REVERSED YU;Lu;0;L;;;;;N;;;;A655; A655;CYRILLIC SMALL LETTER REVERSED YU;Ll;0;L;;;;;N;;;A654;;A654 A656;CYRILLIC CAPITAL LETTER IOTIFIED A;Lu;0;L;;;;;N;;;;A657; A657;CYRILLIC SMALL LETTER IOTIFIED A;Ll;0;L;;;;;N;;;A656;;A656 A658;CYRILLIC CAPITAL LETTER CLOSED LITTLE YUS;Lu;0;L;;;;;N;;;;A659; A659;CYRILLIC SMALL LETTER CLOSED LITTLE YUS;Ll;0;L;;;;;N;;;A658;;A658 A65A;CYRILLIC CAPITAL LETTER BLENDED YUS;Lu;0;L;;;;;N;;;;A65B; A65B;CYRILLIC SMALL LETTER BLENDED YUS;Ll;0;L;;;;;N;;;A65A;;A65A A65C;CYRILLIC CAPITAL LETTER IOTIFIED CLOSED LITTLE YUS;Lu;0;L;;;;;N;;;;A65D; A65D;CYRILLIC SMALL LETTER IOTIFIED CLOSED LITTLE YUS;Ll;0;L;;;;;N;;;A65C;;A65C A65E;CYRILLIC CAPITAL LETTER YN;Lu;0;L;;;;;N;;;;A65F; A65F;CYRILLIC SMALL LETTER YN;Ll;0;L;;;;;N;;;A65E;;A65E A660;CYRILLIC CAPITAL LETTER REVERSED TSE;Lu;0;L;;;;;N;;;;A661; A661;CYRILLIC SMALL LETTER REVERSED TSE;Ll;0;L;;;;;N;;;A660;;A660 A662;CYRILLIC CAPITAL LETTER SOFT DE;Lu;0;L;;;;;N;;;;A663; A663;CYRILLIC SMALL LETTER SOFT DE;Ll;0;L;;;;;N;;;A662;;A662 A664;CYRILLIC CAPITAL LETTER SOFT EL;Lu;0;L;;;;;N;;;;A665; A665;CYRILLIC SMALL LETTER SOFT EL;Ll;0;L;;;;;N;;;A664;;A664 A666;CYRILLIC CAPITAL LETTER SOFT EM;Lu;0;L;;;;;N;;;;A667; A667;CYRILLIC SMALL LETTER SOFT EM;Ll;0;L;;;;;N;;;A666;;A666 A668;CYRILLIC CAPITAL LETTER MONOCULAR O;Lu;0;L;;;;;N;;;;A669; A669;CYRILLIC SMALL LETTER MONOCULAR O;Ll;0;L;;;;;N;;;A668;;A668 A66A;CYRILLIC CAPITAL LETTER BINOCULAR O;Lu;0;L;;;;;N;;;;A66B; A66B;CYRILLIC SMALL LETTER BINOCULAR O;Ll;0;L;;;;;N;;;A66A;;A66A A66C;CYRILLIC CAPITAL LETTER DOUBLE MONOCULAR O;Lu;0;L;;;;;N;;;;A66D; A66D;CYRILLIC SMALL LETTER DOUBLE MONOCULAR O;Ll;0;L;;;;;N;;;A66C;;A66C A66E;CYRILLIC LETTER MULTIOCULAR O;Lo;0;L;;;;;N;;;;; A66F;COMBINING CYRILLIC VZMET;Mn;230;NSM;;;;;N;;;;; A670;COMBINING CYRILLIC TEN MILLIONS SIGN;Me;0;NSM;;;;;N;;;;; A671;COMBINING CYRILLIC HUNDRED MILLIONS SIGN;Me;0;NSM;;;;;N;;;;; A672;COMBINING CYRILLIC THOUSAND MILLIONS SIGN;Me;0;NSM;;;;;N;;;;; A673;SLAVONIC ASTERISK;Po;0;ON;;;;;N;;;;; A674;COMBINING CYRILLIC LETTER UKRAINIAN IE;Mn;230;NSM;;;;;N;;;;; A675;COMBINING CYRILLIC LETTER I;Mn;230;NSM;;;;;N;;;;; A676;COMBINING CYRILLIC LETTER YI;Mn;230;NSM;;;;;N;;;;; A677;COMBINING CYRILLIC LETTER U;Mn;230;NSM;;;;;N;;;;; A678;COMBINING CYRILLIC LETTER HARD SIGN;Mn;230;NSM;;;;;N;;;;; A679;COMBINING CYRILLIC LETTER YERU;Mn;230;NSM;;;;;N;;;;; A67A;COMBINING CYRILLIC LETTER SOFT SIGN;Mn;230;NSM;;;;;N;;;;; A67B;COMBINING CYRILLIC LETTER OMEGA;Mn;230;NSM;;;;;N;;;;; A67C;COMBINING CYRILLIC KAVYKA;Mn;230;NSM;;;;;N;;;;; A67D;COMBINING CYRILLIC PAYEROK;Mn;230;NSM;;;;;N;;;;; A67E;CYRILLIC KAVYKA;Po;0;ON;;;;;N;;;;; A67F;CYRILLIC PAYEROK;Lm;0;ON;;;;;N;;;;; A680;CYRILLIC CAPITAL LETTER DWE;Lu;0;L;;;;;N;;;;A681; A681;CYRILLIC SMALL LETTER DWE;Ll;0;L;;;;;N;;;A680;;A680 A682;CYRILLIC CAPITAL LETTER DZWE;Lu;0;L;;;;;N;;;;A683; A683;CYRILLIC SMALL LETTER DZWE;Ll;0;L;;;;;N;;;A682;;A682 A684;CYRILLIC CAPITAL LETTER ZHWE;Lu;0;L;;;;;N;;;;A685; A685;CYRILLIC SMALL LETTER ZHWE;Ll;0;L;;;;;N;;;A684;;A684 A686;CYRILLIC CAPITAL LETTER CCHE;Lu;0;L;;;;;N;;;;A687; A687;CYRILLIC SMALL LETTER CCHE;Ll;0;L;;;;;N;;;A686;;A686 A688;CYRILLIC CAPITAL LETTER DZZE;Lu;0;L;;;;;N;;;;A689; A689;CYRILLIC SMALL LETTER DZZE;Ll;0;L;;;;;N;;;A688;;A688 A68A;CYRILLIC CAPITAL LETTER TE WITH MIDDLE HOOK;Lu;0;L;;;;;N;;;;A68B; A68B;CYRILLIC SMALL LETTER TE WITH MIDDLE HOOK;Ll;0;L;;;;;N;;;A68A;;A68A A68C;CYRILLIC CAPITAL LETTER TWE;Lu;0;L;;;;;N;;;;A68D; A68D;CYRILLIC SMALL LETTER TWE;Ll;0;L;;;;;N;;;A68C;;A68C A68E;CYRILLIC CAPITAL LETTER TSWE;Lu;0;L;;;;;N;;;;A68F; A68F;CYRILLIC SMALL LETTER TSWE;Ll;0;L;;;;;N;;;A68E;;A68E A690;CYRILLIC CAPITAL LETTER TSSE;Lu;0;L;;;;;N;;;;A691; A691;CYRILLIC SMALL LETTER TSSE;Ll;0;L;;;;;N;;;A690;;A690 A692;CYRILLIC CAPITAL LETTER TCHE;Lu;0;L;;;;;N;;;;A693; A693;CYRILLIC SMALL LETTER TCHE;Ll;0;L;;;;;N;;;A692;;A692 A694;CYRILLIC CAPITAL LETTER HWE;Lu;0;L;;;;;N;;;;A695; A695;CYRILLIC SMALL LETTER HWE;Ll;0;L;;;;;N;;;A694;;A694 A696;CYRILLIC CAPITAL LETTER SHWE;Lu;0;L;;;;;N;;;;A697; A697;CYRILLIC SMALL LETTER SHWE;Ll;0;L;;;;;N;;;A696;;A696 A698;CYRILLIC CAPITAL LETTER DOUBLE O;Lu;0;L;;;;;N;;;;A699; A699;CYRILLIC SMALL LETTER DOUBLE O;Ll;0;L;;;;;N;;;A698;;A698 A69A;CYRILLIC CAPITAL LETTER CROSSED O;Lu;0;L;;;;;N;;;;A69B; A69B;CYRILLIC SMALL LETTER CROSSED O;Ll;0;L;;;;;N;;;A69A;;A69A A69C;MODIFIER LETTER CYRILLIC HARD SIGN;Lm;0;L;<super> 044A;;;;N;;;;; A69D;MODIFIER LETTER CYRILLIC SOFT SIGN;Lm;0;L;<super> 044C;;;;N;;;;; A69E;COMBINING CYRILLIC LETTER EF;Mn;230;NSM;;;;;N;;;;; A69F;COMBINING CYRILLIC LETTER IOTIFIED E;Mn;230;NSM;;;;;N;;;;; A6A0;BAMUM LETTER A;Lo;0;L;;;;;N;;;;; A6A1;BAMUM LETTER KA;Lo;0;L;;;;;N;;;;; A6A2;BAMUM LETTER U;Lo;0;L;;;;;N;;;;; A6A3;BAMUM LETTER KU;Lo;0;L;;;;;N;;;;; A6A4;BAMUM LETTER EE;Lo;0;L;;;;;N;;;;; A6A5;BAMUM LETTER REE;Lo;0;L;;;;;N;;;;; A6A6;BAMUM LETTER TAE;Lo;0;L;;;;;N;;;;; A6A7;BAMUM LETTER O;Lo;0;L;;;;;N;;;;; A6A8;BAMUM LETTER NYI;Lo;0;L;;;;;N;;;;; A6A9;BAMUM LETTER I;Lo;0;L;;;;;N;;;;; A6AA;BAMUM LETTER LA;Lo;0;L;;;;;N;;;;; A6AB;BAMUM LETTER PA;Lo;0;L;;;;;N;;;;; A6AC;BAMUM LETTER RII;Lo;0;L;;;;;N;;;;; A6AD;BAMUM LETTER RIEE;Lo;0;L;;;;;N;;;;; A6AE;BAMUM LETTER LEEEE;Lo;0;L;;;;;N;;;;; A6AF;BAMUM LETTER MEEEE;Lo;0;L;;;;;N;;;;; A6B0;BAMUM LETTER TAA;Lo;0;L;;;;;N;;;;; A6B1;BAMUM LETTER NDAA;Lo;0;L;;;;;N;;;;; A6B2;BAMUM LETTER NJAEM;Lo;0;L;;;;;N;;;;; A6B3;BAMUM LETTER M;Lo;0;L;;;;;N;;;;; A6B4;BAMUM LETTER SUU;Lo;0;L;;;;;N;;;;; A6B5;BAMUM LETTER MU;Lo;0;L;;;;;N;;;;; A6B6;BAMUM LETTER SHII;Lo;0;L;;;;;N;;;;; A6B7;BAMUM LETTER SI;Lo;0;L;;;;;N;;;;; A6B8;BAMUM LETTER SHEUX;Lo;0;L;;;;;N;;;;; A6B9;BAMUM LETTER SEUX;Lo;0;L;;;;;N;;;;; A6BA;BAMUM LETTER KYEE;Lo;0;L;;;;;N;;;;; A6BB;BAMUM LETTER KET;Lo;0;L;;;;;N;;;;; A6BC;BAMUM LETTER NUAE;Lo;0;L;;;;;N;;;;; A6BD;BAMUM LETTER NU;Lo;0;L;;;;;N;;;;; A6BE;BAMUM LETTER NJUAE;Lo;0;L;;;;;N;;;;; A6BF;BAMUM LETTER YOQ;Lo;0;L;;;;;N;;;;; A6C0;BAMUM LETTER SHU;Lo;0;L;;;;;N;;;;; A6C1;BAMUM LETTER YUQ;Lo;0;L;;;;;N;;;;; A6C2;BAMUM LETTER YA;Lo;0;L;;;;;N;;;;; A6C3;BAMUM LETTER NSHA;Lo;0;L;;;;;N;;;;; A6C4;BAMUM LETTER KEUX;Lo;0;L;;;;;N;;;;; A6C5;BAMUM LETTER PEUX;Lo;0;L;;;;;N;;;;; A6C6;BAMUM LETTER NJEE;Lo;0;L;;;;;N;;;;; A6C7;BAMUM LETTER NTEE;Lo;0;L;;;;;N;;;;; A6C8;BAMUM LETTER PUE;Lo;0;L;;;;;N;;;;; A6C9;BAMUM LETTER WUE;Lo;0;L;;;;;N;;;;; A6CA;BAMUM LETTER PEE;Lo;0;L;;;;;N;;;;; A6CB;BAMUM LETTER FEE;Lo;0;L;;;;;N;;;;; A6CC;BAMUM LETTER RU;Lo;0;L;;;;;N;;;;; A6CD;BAMUM LETTER LU;Lo;0;L;;;;;N;;;;; A6CE;BAMUM LETTER MI;Lo;0;L;;;;;N;;;;; A6CF;BAMUM LETTER NI;Lo;0;L;;;;;N;;;;; A6D0;BAMUM LETTER REUX;Lo;0;L;;;;;N;;;;; A6D1;BAMUM LETTER RAE;Lo;0;L;;;;;N;;;;; A6D2;BAMUM LETTER KEN;Lo;0;L;;;;;N;;;;; A6D3;BAMUM LETTER NGKWAEN;Lo;0;L;;;;;N;;;;; A6D4;BAMUM LETTER NGGA;Lo;0;L;;;;;N;;;;; A6D5;BAMUM LETTER NGA;Lo;0;L;;;;;N;;;;; A6D6;BAMUM LETTER SHO;Lo;0;L;;;;;N;;;;; A6D7;BAMUM LETTER PUAE;Lo;0;L;;;;;N;;;;; A6D8;BAMUM LETTER FU;Lo;0;L;;;;;N;;;;; A6D9;BAMUM LETTER FOM;Lo;0;L;;;;;N;;;;; A6DA;BAMUM LETTER WA;Lo;0;L;;;;;N;;;;; A6DB;BAMUM LETTER NA;Lo;0;L;;;;;N;;;;; A6DC;BAMUM LETTER LI;Lo;0;L;;;;;N;;;;; A6DD;BAMUM LETTER PI;Lo;0;L;;;;;N;;;;; A6DE;BAMUM LETTER LOQ;Lo;0;L;;;;;N;;;;; A6DF;BAMUM LETTER KO;Lo;0;L;;;;;N;;;;; A6E0;BAMUM LETTER MBEN;Lo;0;L;;;;;N;;;;; A6E1;BAMUM LETTER REN;Lo;0;L;;;;;N;;;;; A6E2;BAMUM LETTER MEN;Lo;0;L;;;;;N;;;;; A6E3;BAMUM LETTER MA;Lo;0;L;;;;;N;;;;; A6E4;BAMUM LETTER TI;Lo;0;L;;;;;N;;;;; A6E5;BAMUM LETTER KI;Lo;0;L;;;;;N;;;;; A6E6;BAMUM LETTER MO;Nl;0;L;;;;1;N;;;;; A6E7;BAMUM LETTER MBAA;Nl;0;L;;;;2;N;;;;; A6E8;BAMUM LETTER TET;Nl;0;L;;;;3;N;;;;; A6E9;BAMUM LETTER KPA;Nl;0;L;;;;4;N;;;;; A6EA;BAMUM LETTER TEN;Nl;0;L;;;;5;N;;;;; A6EB;BAMUM LETTER NTUU;Nl;0;L;;;;6;N;;;;; A6EC;BAMUM LETTER SAMBA;Nl;0;L;;;;7;N;;;;; A6ED;BAMUM LETTER FAAMAE;Nl;0;L;;;;8;N;;;;; A6EE;BAMUM LETTER KOVUU;Nl;0;L;;;;9;N;;;;; A6EF;BAMUM LETTER KOGHOM;Nl;0;L;;;;0;N;;;;; A6F0;BAMUM COMBINING MARK KOQNDON;Mn;230;NSM;;;;;N;;;;; A6F1;BAMUM COMBINING MARK TUKWENTIS;Mn;230;NSM;;;;;N;;;;; A6F2;BAMUM NJAEMLI;Po;0;L;;;;;N;;;;; A6F3;BAMUM FULL STOP;Po;0;L;;;;;N;;;;; A6F4;BAMUM COLON;Po;0;L;;;;;N;;;;; A6F5;BAMUM COMMA;Po;0;L;;;;;N;;;;; A6F6;BAMUM SEMICOLON;Po;0;L;;;;;N;;;;; A6F7;BAMUM QUESTION MARK;Po;0;L;;;;;N;;;;; A700;MODIFIER LETTER CHINESE TONE YIN PING;Sk;0;ON;;;;;N;;;;; A701;MODIFIER LETTER CHINESE TONE YANG PING;Sk;0;ON;;;;;N;;;;; A702;MODIFIER LETTER CHINESE TONE YIN SHANG;Sk;0;ON;;;;;N;;;;; A703;MODIFIER LETTER CHINESE TONE YANG SHANG;Sk;0;ON;;;;;N;;;;; A704;MODIFIER LETTER CHINESE TONE YIN QU;Sk;0;ON;;;;;N;;;;; A705;MODIFIER LETTER CHINESE TONE YANG QU;Sk;0;ON;;;;;N;;;;; A706;MODIFIER LETTER CHINESE TONE YIN RU;Sk;0;ON;;;;;N;;;;; A707;MODIFIER LETTER CHINESE TONE YANG RU;Sk;0;ON;;;;;N;;;;; A708;MODIFIER LETTER EXTRA-HIGH DOTTED TONE BAR;Sk;0;ON;;;;;N;;;;; A709;MODIFIER LETTER HIGH DOTTED TONE BAR;Sk;0;ON;;;;;N;;;;; A70A;MODIFIER LETTER MID DOTTED TONE BAR;Sk;0;ON;;;;;N;;;;; A70B;MODIFIER LETTER LOW DOTTED TONE BAR;Sk;0;ON;;;;;N;;;;; A70C;MODIFIER LETTER EXTRA-LOW DOTTED TONE BAR;Sk;0;ON;;;;;N;;;;; A70D;MODIFIER LETTER EXTRA-HIGH DOTTED LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;; A70E;MODIFIER LETTER HIGH DOTTED LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;; A70F;MODIFIER LETTER MID DOTTED LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;; A710;MODIFIER LETTER LOW DOTTED LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;; A711;MODIFIER LETTER EXTRA-LOW DOTTED LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;; A712;MODIFIER LETTER EXTRA-HIGH LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;; A713;MODIFIER LETTER HIGH LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;; A714;MODIFIER LETTER MID LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;; A715;MODIFIER LETTER LOW LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;; A716;MODIFIER LETTER EXTRA-LOW LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;; A717;MODIFIER LETTER DOT VERTICAL BAR;Lm;0;ON;;;;;N;;;;; A718;MODIFIER LETTER DOT SLASH;Lm;0;ON;;;;;N;;;;; A719;MODIFIER LETTER DOT HORIZONTAL BAR;Lm;0;ON;;;;;N;;;;; A71A;MODIFIER LETTER LOWER RIGHT CORNER ANGLE;Lm;0;ON;;;;;N;;;;; A71B;MODIFIER LETTER RAISED UP ARROW;Lm;0;ON;;;;;N;;;;; A71C;MODIFIER LETTER RAISED DOWN ARROW;Lm;0;ON;;;;;N;;;;; A71D;MODIFIER LETTER RAISED EXCLAMATION MARK;Lm;0;ON;;;;;N;;;;; A71E;MODIFIER LETTER RAISED INVERTED EXCLAMATION MARK;Lm;0;ON;;;;;N;;;;; A71F;MODIFIER LETTER LOW INVERTED EXCLAMATION MARK;Lm;0;ON;;;;;N;;;;; A720;MODIFIER LETTER STRESS AND HIGH TONE;Sk;0;ON;;;;;N;;;;; A721;MODIFIER LETTER STRESS AND LOW TONE;Sk;0;ON;;;;;N;;;;; A722;LATIN CAPITAL LETTER EGYPTOLOGICAL ALEF;Lu;0;L;;;;;N;;;;A723; A723;LATIN SMALL LETTER EGYPTOLOGICAL ALEF;Ll;0;L;;;;;N;;;A722;;A722 A724;LATIN CAPITAL LETTER EGYPTOLOGICAL AIN;Lu;0;L;;;;;N;;;;A725; A725;LATIN SMALL LETTER EGYPTOLOGICAL AIN;Ll;0;L;;;;;N;;;A724;;A724 A726;LATIN CAPITAL LETTER HENG;Lu;0;L;;;;;N;;;;A727; A727;LATIN SMALL LETTER HENG;Ll;0;L;;;;;N;;;A726;;A726 A728;LATIN CAPITAL LETTER TZ;Lu;0;L;;;;;N;;;;A729; A729;LATIN SMALL LETTER TZ;Ll;0;L;;;;;N;;;A728;;A728 A72A;LATIN CAPITAL LETTER TRESILLO;Lu;0;L;;;;;N;;;;A72B; A72B;LATIN SMALL LETTER TRESILLO;Ll;0;L;;;;;N;;;A72A;;A72A A72C;LATIN CAPITAL LETTER CUATRILLO;Lu;0;L;;;;;N;;;;A72D; A72D;LATIN SMALL LETTER CUATRILLO;Ll;0;L;;;;;N;;;A72C;;A72C A72E;LATIN CAPITAL LETTER CUATRILLO WITH COMMA;Lu;0;L;;;;;N;;;;A72F; A72F;LATIN SMALL LETTER CUATRILLO WITH COMMA;Ll;0;L;;;;;N;;;A72E;;A72E A730;LATIN LETTER SMALL CAPITAL F;Ll;0;L;;;;;N;;;;; A731;LATIN LETTER SMALL CAPITAL S;Ll;0;L;;;;;N;;;;; A732;LATIN CAPITAL LETTER AA;Lu;0;L;;;;;N;;;;A733; A733;LATIN SMALL LETTER AA;Ll;0;L;;;;;N;;;A732;;A732 A734;LATIN CAPITAL LETTER AO;Lu;0;L;;;;;N;;;;A735; A735;LATIN SMALL LETTER AO;Ll;0;L;;;;;N;;;A734;;A734 A736;LATIN CAPITAL LETTER AU;Lu;0;L;;;;;N;;;;A737; A737;LATIN SMALL LETTER AU;Ll;0;L;;;;;N;;;A736;;A736 A738;LATIN CAPITAL LETTER AV;Lu;0;L;;;;;N;;;;A739; A739;LATIN SMALL LETTER AV;Ll;0;L;;;;;N;;;A738;;A738 A73A;LATIN CAPITAL LETTER AV WITH HORIZONTAL BAR;Lu;0;L;;;;;N;;;;A73B; A73B;LATIN SMALL LETTER AV WITH HORIZONTAL BAR;Ll;0;L;;;;;N;;;A73A;;A73A A73C;LATIN CAPITAL LETTER AY;Lu;0;L;;;;;N;;;;A73D; A73D;LATIN SMALL LETTER AY;Ll;0;L;;;;;N;;;A73C;;A73C A73E;LATIN CAPITAL LETTER REVERSED C WITH DOT;Lu;0;L;;;;;N;;;;A73F; A73F;LATIN SMALL LETTER REVERSED C WITH DOT;Ll;0;L;;;;;N;;;A73E;;A73E A740;LATIN CAPITAL LETTER K WITH STROKE;Lu;0;L;;;;;N;;;;A741; A741;LATIN SMALL LETTER K WITH STROKE;Ll;0;L;;;;;N;;;A740;;A740 A742;LATIN CAPITAL LETTER K WITH DIAGONAL STROKE;Lu;0;L;;;;;N;;;;A743; A743;LATIN SMALL LETTER K WITH DIAGONAL STROKE;Ll;0;L;;;;;N;;;A742;;A742 A744;LATIN CAPITAL LETTER K WITH STROKE AND DIAGONAL STROKE;Lu;0;L;;;;;N;;;;A745; A745;LATIN SMALL LETTER K WITH STROKE AND DIAGONAL STROKE;Ll;0;L;;;;;N;;;A744;;A744 A746;LATIN CAPITAL LETTER BROKEN L;Lu;0;L;;;;;N;;;;A747; A747;LATIN SMALL LETTER BROKEN L;Ll;0;L;;;;;N;;;A746;;A746 A748;LATIN CAPITAL LETTER L WITH HIGH STROKE;Lu;0;L;;;;;N;;;;A749; A749;LATIN SMALL LETTER L WITH HIGH STROKE;Ll;0;L;;;;;N;;;A748;;A748 A74A;LATIN CAPITAL LETTER O WITH LONG STROKE OVERLAY;Lu;0;L;;;;;N;;;;A74B; A74B;LATIN SMALL LETTER O WITH LONG STROKE OVERLAY;Ll;0;L;;;;;N;;;A74A;;A74A A74C;LATIN CAPITAL LETTER O WITH LOOP;Lu;0;L;;;;;N;;;;A74D; A74D;LATIN SMALL LETTER O WITH LOOP;Ll;0;L;;;;;N;;;A74C;;A74C A74E;LATIN CAPITAL LETTER OO;Lu;0;L;;;;;N;;;;A74F; A74F;LATIN SMALL LETTER OO;Ll;0;L;;;;;N;;;A74E;;A74E A750;LATIN CAPITAL LETTER P WITH STROKE THROUGH DESCENDER;Lu;0;L;;;;;N;;;;A751; A751;LATIN SMALL LETTER P WITH STROKE THROUGH DESCENDER;Ll;0;L;;;;;N;;;A750;;A750 A752;LATIN CAPITAL LETTER P WITH FLOURISH;Lu;0;L;;;;;N;;;;A753; A753;LATIN SMALL LETTER P WITH FLOURISH;Ll;0;L;;;;;N;;;A752;;A752 A754;LATIN CAPITAL LETTER P WITH SQUIRREL TAIL;Lu;0;L;;;;;N;;;;A755; A755;LATIN SMALL LETTER P WITH SQUIRREL TAIL;Ll;0;L;;;;;N;;;A754;;A754 A756;LATIN CAPITAL LETTER Q WITH STROKE THROUGH DESCENDER;Lu;0;L;;;;;N;;;;A757; A757;LATIN SMALL LETTER Q WITH STROKE THROUGH DESCENDER;Ll;0;L;;;;;N;;;A756;;A756 A758;LATIN CAPITAL LETTER Q WITH DIAGONAL STROKE;Lu;0;L;;;;;N;;;;A759; A759;LATIN SMALL LETTER Q WITH DIAGONAL STROKE;Ll;0;L;;;;;N;;;A758;;A758 A75A;LATIN CAPITAL LETTER R ROTUNDA;Lu;0;L;;;;;N;;;;A75B; A75B;LATIN SMALL LETTER R ROTUNDA;Ll;0;L;;;;;N;;;A75A;;A75A A75C;LATIN CAPITAL LETTER RUM ROTUNDA;Lu;0;L;;;;;N;;;;A75D; A75D;LATIN SMALL LETTER RUM ROTUNDA;Ll;0;L;;;;;N;;;A75C;;A75C A75E;LATIN CAPITAL LETTER V WITH DIAGONAL STROKE;Lu;0;L;;;;;N;;;;A75F; A75F;LATIN SMALL LETTER V WITH DIAGONAL STROKE;Ll;0;L;;;;;N;;;A75E;;A75E A760;LATIN CAPITAL LETTER VY;Lu;0;L;;;;;N;;;;A761; A761;LATIN SMALL LETTER VY;Ll;0;L;;;;;N;;;A760;;A760 A762;LATIN CAPITAL LETTER VISIGOTHIC Z;Lu;0;L;;;;;N;;;;A763; A763;LATIN SMALL LETTER VISIGOTHIC Z;Ll;0;L;;;;;N;;;A762;;A762 A764;LATIN CAPITAL LETTER THORN WITH STROKE;Lu;0;L;;;;;N;;;;A765; A765;LATIN SMALL LETTER THORN WITH STROKE;Ll;0;L;;;;;N;;;A764;;A764 A766;LATIN CAPITAL LETTER THORN WITH STROKE THROUGH DESCENDER;Lu;0;L;;;;;N;;;;A767; A767;LATIN SMALL LETTER THORN WITH STROKE THROUGH DESCENDER;Ll;0;L;;;;;N;;;A766;;A766 A768;LATIN CAPITAL LETTER VEND;Lu;0;L;;;;;N;;;;A769; A769;LATIN SMALL LETTER VEND;Ll;0;L;;;;;N;;;A768;;A768 A76A;LATIN CAPITAL LETTER ET;Lu;0;L;;;;;N;;;;A76B; A76B;LATIN SMALL LETTER ET;Ll;0;L;;;;;N;;;A76A;;A76A A76C;LATIN CAPITAL LETTER IS;Lu;0;L;;;;;N;;;;A76D; A76D;LATIN SMALL LETTER IS;Ll;0;L;;;;;N;;;A76C;;A76C A76E;LATIN CAPITAL LETTER CON;Lu;0;L;;;;;N;;;;A76F; A76F;LATIN SMALL LETTER CON;Ll;0;L;;;;;N;;;A76E;;A76E A770;MODIFIER LETTER US;Lm;0;L;<super> A76F;;;;N;;;;; A771;LATIN SMALL LETTER DUM;Ll;0;L;;;;;N;;;;; A772;LATIN SMALL LETTER LUM;Ll;0;L;;;;;N;;;;; A773;LATIN SMALL LETTER MUM;Ll;0;L;;;;;N;;;;; A774;LATIN SMALL LETTER NUM;Ll;0;L;;;;;N;;;;; A775;LATIN SMALL LETTER RUM;Ll;0;L;;;;;N;;;;; A776;LATIN LETTER SMALL CAPITAL RUM;Ll;0;L;;;;;N;;;;; A777;LATIN SMALL LETTER TUM;Ll;0;L;;;;;N;;;;; A778;LATIN SMALL LETTER UM;Ll;0;L;;;;;N;;;;; A779;LATIN CAPITAL LETTER INSULAR D;Lu;0;L;;;;;N;;;;A77A; A77A;LATIN SMALL LETTER INSULAR D;Ll;0;L;;;;;N;;;A779;;A779 A77B;LATIN CAPITAL LETTER INSULAR F;Lu;0;L;;;;;N;;;;A77C; A77C;LATIN SMALL LETTER INSULAR F;Ll;0;L;;;;;N;;;A77B;;A77B A77D;LATIN CAPITAL LETTER INSULAR G;Lu;0;L;;;;;N;;;;1D79; A77E;LATIN CAPITAL LETTER TURNED INSULAR G;Lu;0;L;;;;;N;;;;A77F; A77F;LATIN SMALL LETTER TURNED INSULAR G;Ll;0;L;;;;;N;;;A77E;;A77E A780;LATIN CAPITAL LETTER TURNED L;Lu;0;L;;;;;N;;;;A781; A781;LATIN SMALL LETTER TURNED L;Ll;0;L;;;;;N;;;A780;;A780 A782;LATIN CAPITAL LETTER INSULAR R;Lu;0;L;;;;;N;;;;A783; A783;LATIN SMALL LETTER INSULAR R;Ll;0;L;;;;;N;;;A782;;A782 A784;LATIN CAPITAL LETTER INSULAR S;Lu;0;L;;;;;N;;;;A785; A785;LATIN SMALL LETTER INSULAR S;Ll;0;L;;;;;N;;;A784;;A784 A786;LATIN CAPITAL LETTER INSULAR T;Lu;0;L;;;;;N;;;;A787; A787;LATIN SMALL LETTER INSULAR T;Ll;0;L;;;;;N;;;A786;;A786 A788;MODIFIER LETTER LOW CIRCUMFLEX ACCENT;Lm;0;ON;;;;;N;;;;; A789;MODIFIER LETTER COLON;Sk;0;L;;;;;N;;;;; A78A;MODIFIER LETTER SHORT EQUALS SIGN;Sk;0;L;;;;;N;;;;; A78B;LATIN CAPITAL LETTER SALTILLO;Lu;0;L;;;;;N;;;;A78C; A78C;LATIN SMALL LETTER SALTILLO;Ll;0;L;;;;;N;;;A78B;;A78B A78D;LATIN CAPITAL LETTER TURNED H;Lu;0;L;;;;;N;;;;0265; A78E;LATIN SMALL LETTER L WITH RETROFLEX HOOK AND BELT;Ll;0;L;;;;;N;;;;; A78F;LATIN LETTER SINOLOGICAL DOT;Lo;0;L;;;;;N;;;;; A790;LATIN CAPITAL LETTER N WITH DESCENDER;Lu;0;L;;;;;N;;;;A791; A791;LATIN SMALL LETTER N WITH DESCENDER;Ll;0;L;;;;;N;;;A790;;A790 A792;LATIN CAPITAL LETTER C WITH BAR;Lu;0;L;;;;;N;;;;A793; A793;LATIN SMALL LETTER C WITH BAR;Ll;0;L;;;;;N;;;A792;;A792 A794;LATIN SMALL LETTER C WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; A795;LATIN SMALL LETTER H WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; A796;LATIN CAPITAL LETTER B WITH FLOURISH;Lu;0;L;;;;;N;;;;A797; A797;LATIN SMALL LETTER B WITH FLOURISH;Ll;0;L;;;;;N;;;A796;;A796 A798;LATIN CAPITAL LETTER F WITH STROKE;Lu;0;L;;;;;N;;;;A799; A799;LATIN SMALL LETTER F WITH STROKE;Ll;0;L;;;;;N;;;A798;;A798 A79A;LATIN CAPITAL LETTER VOLAPUK AE;Lu;0;L;;;;;N;;;;A79B; A79B;LATIN SMALL LETTER VOLAPUK AE;Ll;0;L;;;;;N;;;A79A;;A79A A79C;LATIN CAPITAL LETTER VOLAPUK OE;Lu;0;L;;;;;N;;;;A79D; A79D;LATIN SMALL LETTER VOLAPUK OE;Ll;0;L;;;;;N;;;A79C;;A79C A79E;LATIN CAPITAL LETTER VOLAPUK UE;Lu;0;L;;;;;N;;;;A79F; A79F;LATIN SMALL LETTER VOLAPUK UE;Ll;0;L;;;;;N;;;A79E;;A79E A7A0;LATIN CAPITAL LETTER G WITH OBLIQUE STROKE;Lu;0;L;;;;;N;;;;A7A1; A7A1;LATIN SMALL LETTER G WITH OBLIQUE STROKE;Ll;0;L;;;;;N;;;A7A0;;A7A0 A7A2;LATIN CAPITAL LETTER K WITH OBLIQUE STROKE;Lu;0;L;;;;;N;;;;A7A3; A7A3;LATIN SMALL LETTER K WITH OBLIQUE STROKE;Ll;0;L;;;;;N;;;A7A2;;A7A2 A7A4;LATIN CAPITAL LETTER N WITH OBLIQUE STROKE;Lu;0;L;;;;;N;;;;A7A5; A7A5;LATIN SMALL LETTER N WITH OBLIQUE STROKE;Ll;0;L;;;;;N;;;A7A4;;A7A4 A7A6;LATIN CAPITAL LETTER R WITH OBLIQUE STROKE;Lu;0;L;;;;;N;;;;A7A7; A7A7;LATIN SMALL LETTER R WITH OBLIQUE STROKE;Ll;0;L;;;;;N;;;A7A6;;A7A6 A7A8;LATIN CAPITAL LETTER S WITH OBLIQUE STROKE;Lu;0;L;;;;;N;;;;A7A9; A7A9;LATIN SMALL LETTER S WITH OBLIQUE STROKE;Ll;0;L;;;;;N;;;A7A8;;A7A8 A7AA;LATIN CAPITAL LETTER H WITH HOOK;Lu;0;L;;;;;N;;;;0266; A7AB;LATIN CAPITAL LETTER REVERSED OPEN E;Lu;0;L;;;;;N;;;;025C; A7AC;LATIN CAPITAL LETTER SCRIPT G;Lu;0;L;;;;;N;;;;0261; A7AD;LATIN CAPITAL LETTER L WITH BELT;Lu;0;L;;;;;N;;;;026C; A7AE;LATIN CAPITAL LETTER SMALL CAPITAL I;Lu;0;L;;;;;N;;;;026A; A7B0;LATIN CAPITAL LETTER TURNED K;Lu;0;L;;;;;N;;;;029E; A7B1;LATIN CAPITAL LETTER TURNED T;Lu;0;L;;;;;N;;;;0287; A7B2;LATIN CAPITAL LETTER J WITH CROSSED-TAIL;Lu;0;L;;;;;N;;;;029D; A7B3;LATIN CAPITAL LETTER CHI;Lu;0;L;;;;;N;;;;AB53; A7B4;LATIN CAPITAL LETTER BETA;Lu;0;L;;;;;N;;;;A7B5; A7B5;LATIN SMALL LETTER BETA;Ll;0;L;;;;;N;;;A7B4;;A7B4 A7B6;LATIN CAPITAL LETTER OMEGA;Lu;0;L;;;;;N;;;;A7B7; A7B7;LATIN SMALL LETTER OMEGA;Ll;0;L;;;;;N;;;A7B6;;A7B6 A7F7;LATIN EPIGRAPHIC LETTER SIDEWAYS I;Lo;0;L;;;;;N;;;;; A7F8;MODIFIER LETTER CAPITAL H WITH STROKE;Lm;0;L;<super> 0126;;;;N;;;;; A7F9;MODIFIER LETTER SMALL LIGATURE OE;Lm;0;L;<super> 0153;;;;N;;;;; A7FA;LATIN LETTER SMALL CAPITAL TURNED M;Ll;0;L;;;;;N;;;;; A7FB;LATIN EPIGRAPHIC LETTER REVERSED F;Lo;0;L;;;;;N;;;;; A7FC;LATIN EPIGRAPHIC LETTER REVERSED P;Lo;0;L;;;;;N;;;;; A7FD;LATIN EPIGRAPHIC LETTER INVERTED M;Lo;0;L;;;;;N;;;;; A7FE;LATIN EPIGRAPHIC LETTER I LONGA;Lo;0;L;;;;;N;;;;; A7FF;LATIN EPIGRAPHIC LETTER ARCHAIC M;Lo;0;L;;;;;N;;;;; A800;SYLOTI NAGRI LETTER A;Lo;0;L;;;;;N;;;;; A801;SYLOTI NAGRI LETTER I;Lo;0;L;;;;;N;;;;; A802;SYLOTI NAGRI SIGN DVISVARA;Mn;0;NSM;;;;;N;;;;; A803;SYLOTI NAGRI LETTER U;Lo;0;L;;;;;N;;;;; A804;SYLOTI NAGRI LETTER E;Lo;0;L;;;;;N;;;;; A805;SYLOTI NAGRI LETTER O;Lo;0;L;;;;;N;;;;; A806;SYLOTI NAGRI SIGN HASANTA;Mn;9;NSM;;;;;N;;;;; A807;SYLOTI NAGRI LETTER KO;Lo;0;L;;;;;N;;;;; A808;SYLOTI NAGRI LETTER KHO;Lo;0;L;;;;;N;;;;; A809;SYLOTI NAGRI LETTER GO;Lo;0;L;;;;;N;;;;; A80A;SYLOTI NAGRI LETTER GHO;Lo;0;L;;;;;N;;;;; A80B;SYLOTI NAGRI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; A80C;SYLOTI NAGRI LETTER CO;Lo;0;L;;;;;N;;;;; A80D;SYLOTI NAGRI LETTER CHO;Lo;0;L;;;;;N;;;;; A80E;SYLOTI NAGRI LETTER JO;Lo;0;L;;;;;N;;;;; A80F;SYLOTI NAGRI LETTER JHO;Lo;0;L;;;;;N;;;;; A810;SYLOTI NAGRI LETTER TTO;Lo;0;L;;;;;N;;;;; A811;SYLOTI NAGRI LETTER TTHO;Lo;0;L;;;;;N;;;;; A812;SYLOTI NAGRI LETTER DDO;Lo;0;L;;;;;N;;;;; A813;SYLOTI NAGRI LETTER DDHO;Lo;0;L;;;;;N;;;;; A814;SYLOTI NAGRI LETTER TO;Lo;0;L;;;;;N;;;;; A815;SYLOTI NAGRI LETTER THO;Lo;0;L;;;;;N;;;;; A816;SYLOTI NAGRI LETTER DO;Lo;0;L;;;;;N;;;;; A817;SYLOTI NAGRI LETTER DHO;Lo;0;L;;;;;N;;;;; A818;SYLOTI NAGRI LETTER NO;Lo;0;L;;;;;N;;;;; A819;SYLOTI NAGRI LETTER PO;Lo;0;L;;;;;N;;;;; A81A;SYLOTI NAGRI LETTER PHO;Lo;0;L;;;;;N;;;;; A81B;SYLOTI NAGRI LETTER BO;Lo;0;L;;;;;N;;;;; A81C;SYLOTI NAGRI LETTER BHO;Lo;0;L;;;;;N;;;;; A81D;SYLOTI NAGRI LETTER MO;Lo;0;L;;;;;N;;;;; A81E;SYLOTI NAGRI LETTER RO;Lo;0;L;;;;;N;;;;; A81F;SYLOTI NAGRI LETTER LO;Lo;0;L;;;;;N;;;;; A820;SYLOTI NAGRI LETTER RRO;Lo;0;L;;;;;N;;;;; A821;SYLOTI NAGRI LETTER SO;Lo;0;L;;;;;N;;;;; A822;SYLOTI NAGRI LETTER HO;Lo;0;L;;;;;N;;;;; A823;SYLOTI NAGRI VOWEL SIGN A;Mc;0;L;;;;;N;;;;; A824;SYLOTI NAGRI VOWEL SIGN I;Mc;0;L;;;;;N;;;;; A825;SYLOTI NAGRI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; A826;SYLOTI NAGRI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; A827;SYLOTI NAGRI VOWEL SIGN OO;Mc;0;L;;;;;N;;;;; A828;SYLOTI NAGRI POETRY MARK-1;So;0;ON;;;;;N;;;;; A829;SYLOTI NAGRI POETRY MARK-2;So;0;ON;;;;;N;;;;; A82A;SYLOTI NAGRI POETRY MARK-3;So;0;ON;;;;;N;;;;; A82B;SYLOTI NAGRI POETRY MARK-4;So;0;ON;;;;;N;;;;; A830;NORTH INDIC FRACTION ONE QUARTER;No;0;L;;;;1/4;N;;;;; A831;NORTH INDIC FRACTION ONE HALF;No;0;L;;;;1/2;N;;;;; A832;NORTH INDIC FRACTION THREE QUARTERS;No;0;L;;;;3/4;N;;;;; A833;NORTH INDIC FRACTION ONE SIXTEENTH;No;0;L;;;;1/16;N;;;;; A834;NORTH INDIC FRACTION ONE EIGHTH;No;0;L;;;;1/8;N;;;;; A835;NORTH INDIC FRACTION THREE SIXTEENTHS;No;0;L;;;;3/16;N;;;;; A836;NORTH INDIC QUARTER MARK;So;0;L;;;;;N;;;;; A837;NORTH INDIC PLACEHOLDER MARK;So;0;L;;;;;N;;;;; A838;NORTH INDIC RUPEE MARK;Sc;0;ET;;;;;N;;;;; A839;NORTH INDIC QUANTITY MARK;So;0;ET;;;;;N;;;;; A840;PHAGS-PA LETTER KA;Lo;0;L;;;;;N;;;;; A841;PHAGS-PA LETTER KHA;Lo;0;L;;;;;N;;;;; A842;PHAGS-PA LETTER GA;Lo;0;L;;;;;N;;;;; A843;PHAGS-PA LETTER NGA;Lo;0;L;;;;;N;;;;; A844;PHAGS-PA LETTER CA;Lo;0;L;;;;;N;;;;; A845;PHAGS-PA LETTER CHA;Lo;0;L;;;;;N;;;;; A846;PHAGS-PA LETTER JA;Lo;0;L;;;;;N;;;;; A847;PHAGS-PA LETTER NYA;Lo;0;L;;;;;N;;;;; A848;PHAGS-PA LETTER TA;Lo;0;L;;;;;N;;;;; A849;PHAGS-PA LETTER THA;Lo;0;L;;;;;N;;;;; A84A;PHAGS-PA LETTER DA;Lo;0;L;;;;;N;;;;; A84B;PHAGS-PA LETTER NA;Lo;0;L;;;;;N;;;;; A84C;PHAGS-PA LETTER PA;Lo;0;L;;;;;N;;;;; A84D;PHAGS-PA LETTER PHA;Lo;0;L;;;;;N;;;;; A84E;PHAGS-PA LETTER BA;Lo;0;L;;;;;N;;;;; A84F;PHAGS-PA LETTER MA;Lo;0;L;;;;;N;;;;; A850;PHAGS-PA LETTER TSA;Lo;0;L;;;;;N;;;;; A851;PHAGS-PA LETTER TSHA;Lo;0;L;;;;;N;;;;; A852;PHAGS-PA LETTER DZA;Lo;0;L;;;;;N;;;;; A853;PHAGS-PA LETTER WA;Lo;0;L;;;;;N;;;;; A854;PHAGS-PA LETTER ZHA;Lo;0;L;;;;;N;;;;; A855;PHAGS-PA LETTER ZA;Lo;0;L;;;;;N;;;;; A856;PHAGS-PA LETTER SMALL A;Lo;0;L;;;;;N;;;;; A857;PHAGS-PA LETTER YA;Lo;0;L;;;;;N;;;;; A858;PHAGS-PA LETTER RA;Lo;0;L;;;;;N;;;;; A859;PHAGS-PA LETTER LA;Lo;0;L;;;;;N;;;;; A85A;PHAGS-PA LETTER SHA;Lo;0;L;;;;;N;;;;; A85B;PHAGS-PA LETTER SA;Lo;0;L;;;;;N;;;;; A85C;PHAGS-PA LETTER HA;Lo;0;L;;;;;N;;;;; A85D;PHAGS-PA LETTER A;Lo;0;L;;;;;N;;;;; A85E;PHAGS-PA LETTER I;Lo;0;L;;;;;N;;;;; A85F;PHAGS-PA LETTER U;Lo;0;L;;;;;N;;;;; A860;PHAGS-PA LETTER E;Lo;0;L;;;;;N;;;;; A861;PHAGS-PA LETTER O;Lo;0;L;;;;;N;;;;; A862;PHAGS-PA LETTER QA;Lo;0;L;;;;;N;;;;; A863;PHAGS-PA LETTER XA;Lo;0;L;;;;;N;;;;; A864;PHAGS-PA LETTER FA;Lo;0;L;;;;;N;;;;; A865;PHAGS-PA LETTER GGA;Lo;0;L;;;;;N;;;;; A866;PHAGS-PA LETTER EE;Lo;0;L;;;;;N;;;;; A867;PHAGS-PA SUBJOINED LETTER WA;Lo;0;L;;;;;N;;;;; A868;PHAGS-PA SUBJOINED LETTER YA;Lo;0;L;;;;;N;;;;; A869;PHAGS-PA LETTER TTA;Lo;0;L;;;;;N;;;;; A86A;PHAGS-PA LETTER TTHA;Lo;0;L;;;;;N;;;;; A86B;PHAGS-PA LETTER DDA;Lo;0;L;;;;;N;;;;; A86C;PHAGS-PA LETTER NNA;Lo;0;L;;;;;N;;;;; A86D;PHAGS-PA LETTER ALTERNATE YA;Lo;0;L;;;;;N;;;;; A86E;PHAGS-PA LETTER VOICELESS SHA;Lo;0;L;;;;;N;;;;; A86F;PHAGS-PA LETTER VOICED HA;Lo;0;L;;;;;N;;;;; A870;PHAGS-PA LETTER ASPIRATED FA;Lo;0;L;;;;;N;;;;; A871;PHAGS-PA SUBJOINED LETTER RA;Lo;0;L;;;;;N;;;;; A872;PHAGS-PA SUPERFIXED LETTER RA;Lo;0;L;;;;;N;;;;; A873;PHAGS-PA LETTER CANDRABINDU;Lo;0;L;;;;;N;;;;; A874;PHAGS-PA SINGLE HEAD MARK;Po;0;ON;;;;;N;;;;; A875;PHAGS-PA DOUBLE HEAD MARK;Po;0;ON;;;;;N;;;;; A876;PHAGS-PA MARK SHAD;Po;0;ON;;;;;N;;;;; A877;PHAGS-PA MARK DOUBLE SHAD;Po;0;ON;;;;;N;;;;; A880;SAURASHTRA SIGN ANUSVARA;Mc;0;L;;;;;N;;;;; A881;SAURASHTRA SIGN VISARGA;Mc;0;L;;;;;N;;;;; A882;SAURASHTRA LETTER A;Lo;0;L;;;;;N;;;;; A883;SAURASHTRA LETTER AA;Lo;0;L;;;;;N;;;;; A884;SAURASHTRA LETTER I;Lo;0;L;;;;;N;;;;; A885;SAURASHTRA LETTER II;Lo;0;L;;;;;N;;;;; A886;SAURASHTRA LETTER U;Lo;0;L;;;;;N;;;;; A887;SAURASHTRA LETTER UU;Lo;0;L;;;;;N;;;;; A888;SAURASHTRA LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; A889;SAURASHTRA LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; A88A;SAURASHTRA LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; A88B;SAURASHTRA LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; A88C;SAURASHTRA LETTER E;Lo;0;L;;;;;N;;;;; A88D;SAURASHTRA LETTER EE;Lo;0;L;;;;;N;;;;; A88E;SAURASHTRA LETTER AI;Lo;0;L;;;;;N;;;;; A88F;SAURASHTRA LETTER O;Lo;0;L;;;;;N;;;;; A890;SAURASHTRA LETTER OO;Lo;0;L;;;;;N;;;;; A891;SAURASHTRA LETTER AU;Lo;0;L;;;;;N;;;;; A892;SAURASHTRA LETTER KA;Lo;0;L;;;;;N;;;;; A893;SAURASHTRA LETTER KHA;Lo;0;L;;;;;N;;;;; A894;SAURASHTRA LETTER GA;Lo;0;L;;;;;N;;;;; A895;SAURASHTRA LETTER GHA;Lo;0;L;;;;;N;;;;; A896;SAURASHTRA LETTER NGA;Lo;0;L;;;;;N;;;;; A897;SAURASHTRA LETTER CA;Lo;0;L;;;;;N;;;;; A898;SAURASHTRA LETTER CHA;Lo;0;L;;;;;N;;;;; A899;SAURASHTRA LETTER JA;Lo;0;L;;;;;N;;;;; A89A;SAURASHTRA LETTER JHA;Lo;0;L;;;;;N;;;;; A89B;SAURASHTRA LETTER NYA;Lo;0;L;;;;;N;;;;; A89C;SAURASHTRA LETTER TTA;Lo;0;L;;;;;N;;;;; A89D;SAURASHTRA LETTER TTHA;Lo;0;L;;;;;N;;;;; A89E;SAURASHTRA LETTER DDA;Lo;0;L;;;;;N;;;;; A89F;SAURASHTRA LETTER DDHA;Lo;0;L;;;;;N;;;;; A8A0;SAURASHTRA LETTER NNA;Lo;0;L;;;;;N;;;;; A8A1;SAURASHTRA LETTER TA;Lo;0;L;;;;;N;;;;; A8A2;SAURASHTRA LETTER THA;Lo;0;L;;;;;N;;;;; A8A3;SAURASHTRA LETTER DA;Lo;0;L;;;;;N;;;;; A8A4;SAURASHTRA LETTER DHA;Lo;0;L;;;;;N;;;;; A8A5;SAURASHTRA LETTER NA;Lo;0;L;;;;;N;;;;; A8A6;SAURASHTRA LETTER PA;Lo;0;L;;;;;N;;;;; A8A7;SAURASHTRA LETTER PHA;Lo;0;L;;;;;N;;;;; A8A8;SAURASHTRA LETTER BA;Lo;0;L;;;;;N;;;;; A8A9;SAURASHTRA LETTER BHA;Lo;0;L;;;;;N;;;;; A8AA;SAURASHTRA LETTER MA;Lo;0;L;;;;;N;;;;; A8AB;SAURASHTRA LETTER YA;Lo;0;L;;;;;N;;;;; A8AC;SAURASHTRA LETTER RA;Lo;0;L;;;;;N;;;;; A8AD;SAURASHTRA LETTER LA;Lo;0;L;;;;;N;;;;; A8AE;SAURASHTRA LETTER VA;Lo;0;L;;;;;N;;;;; A8AF;SAURASHTRA LETTER SHA;Lo;0;L;;;;;N;;;;; A8B0;SAURASHTRA LETTER SSA;Lo;0;L;;;;;N;;;;; A8B1;SAURASHTRA LETTER SA;Lo;0;L;;;;;N;;;;; A8B2;SAURASHTRA LETTER HA;Lo;0;L;;;;;N;;;;; A8B3;SAURASHTRA LETTER LLA;Lo;0;L;;;;;N;;;;; A8B4;SAURASHTRA CONSONANT SIGN HAARU;Mc;0;L;;;;;N;;;;; A8B5;SAURASHTRA VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; A8B6;SAURASHTRA VOWEL SIGN I;Mc;0;L;;;;;N;;;;; A8B7;SAURASHTRA VOWEL SIGN II;Mc;0;L;;;;;N;;;;; A8B8;SAURASHTRA VOWEL SIGN U;Mc;0;L;;;;;N;;;;; A8B9;SAURASHTRA VOWEL SIGN UU;Mc;0;L;;;;;N;;;;; A8BA;SAURASHTRA VOWEL SIGN VOCALIC R;Mc;0;L;;;;;N;;;;; A8BB;SAURASHTRA VOWEL SIGN VOCALIC RR;Mc;0;L;;;;;N;;;;; A8BC;SAURASHTRA VOWEL SIGN VOCALIC L;Mc;0;L;;;;;N;;;;; A8BD;SAURASHTRA VOWEL SIGN VOCALIC LL;Mc;0;L;;;;;N;;;;; A8BE;SAURASHTRA VOWEL SIGN E;Mc;0;L;;;;;N;;;;; A8BF;SAURASHTRA VOWEL SIGN EE;Mc;0;L;;;;;N;;;;; A8C0;SAURASHTRA VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; A8C1;SAURASHTRA VOWEL SIGN O;Mc;0;L;;;;;N;;;;; A8C2;SAURASHTRA VOWEL SIGN OO;Mc;0;L;;;;;N;;;;; A8C3;SAURASHTRA VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; A8C4;SAURASHTRA SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; A8C5;SAURASHTRA SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; A8CE;SAURASHTRA DANDA;Po;0;L;;;;;N;;;;; A8CF;SAURASHTRA DOUBLE DANDA;Po;0;L;;;;;N;;;;; A8D0;SAURASHTRA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; A8D1;SAURASHTRA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; A8D2;SAURASHTRA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; A8D3;SAURASHTRA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; A8D4;SAURASHTRA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; A8D5;SAURASHTRA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; A8D6;SAURASHTRA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; A8D7;SAURASHTRA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; A8D8;SAURASHTRA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; A8D9;SAURASHTRA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; A8E0;COMBINING DEVANAGARI DIGIT ZERO;Mn;230;NSM;;;;;N;;;;; A8E1;COMBINING DEVANAGARI DIGIT ONE;Mn;230;NSM;;;;;N;;;;; A8E2;COMBINING DEVANAGARI DIGIT TWO;Mn;230;NSM;;;;;N;;;;; A8E3;COMBINING DEVANAGARI DIGIT THREE;Mn;230;NSM;;;;;N;;;;; A8E4;COMBINING DEVANAGARI DIGIT FOUR;Mn;230;NSM;;;;;N;;;;; A8E5;COMBINING DEVANAGARI DIGIT FIVE;Mn;230;NSM;;;;;N;;;;; A8E6;COMBINING DEVANAGARI DIGIT SIX;Mn;230;NSM;;;;;N;;;;; A8E7;COMBINING DEVANAGARI DIGIT SEVEN;Mn;230;NSM;;;;;N;;;;; A8E8;COMBINING DEVANAGARI DIGIT EIGHT;Mn;230;NSM;;;;;N;;;;; A8E9;COMBINING DEVANAGARI DIGIT NINE;Mn;230;NSM;;;;;N;;;;; A8EA;COMBINING DEVANAGARI LETTER A;Mn;230;NSM;;;;;N;;;;; A8EB;COMBINING DEVANAGARI LETTER U;Mn;230;NSM;;;;;N;;;;; A8EC;COMBINING DEVANAGARI LETTER KA;Mn;230;NSM;;;;;N;;;;; A8ED;COMBINING DEVANAGARI LETTER NA;Mn;230;NSM;;;;;N;;;;; A8EE;COMBINING DEVANAGARI LETTER PA;Mn;230;NSM;;;;;N;;;;; A8EF;COMBINING DEVANAGARI LETTER RA;Mn;230;NSM;;;;;N;;;;; A8F0;COMBINING DEVANAGARI LETTER VI;Mn;230;NSM;;;;;N;;;;; A8F1;COMBINING DEVANAGARI SIGN AVAGRAHA;Mn;230;NSM;;;;;N;;;;; A8F2;DEVANAGARI SIGN SPACING CANDRABINDU;Lo;0;L;;;;;N;;;;; A8F3;DEVANAGARI SIGN CANDRABINDU VIRAMA;Lo;0;L;;;;;N;;;;; A8F4;DEVANAGARI SIGN DOUBLE CANDRABINDU VIRAMA;Lo;0;L;;;;;N;;;;; A8F5;DEVANAGARI SIGN CANDRABINDU TWO;Lo;0;L;;;;;N;;;;; A8F6;DEVANAGARI SIGN CANDRABINDU THREE;Lo;0;L;;;;;N;;;;; A8F7;DEVANAGARI SIGN CANDRABINDU AVAGRAHA;Lo;0;L;;;;;N;;;;; A8F8;DEVANAGARI SIGN PUSHPIKA;Po;0;L;;;;;N;;;;; A8F9;DEVANAGARI GAP FILLER;Po;0;L;;;;;N;;;;; A8FA;DEVANAGARI CARET;Po;0;L;;;;;N;;;;; A8FB;DEVANAGARI HEADSTROKE;Lo;0;L;;;;;N;;;;; A8FC;DEVANAGARI SIGN SIDDHAM;Po;0;L;;;;;N;;;;; A8FD;DEVANAGARI JAIN OM;Lo;0;L;;;;;N;;;;; A900;KAYAH LI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; A901;KAYAH LI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; A902;KAYAH LI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; A903;KAYAH LI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; A904;KAYAH LI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; A905;KAYAH LI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; A906;KAYAH LI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; A907;KAYAH LI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; A908;KAYAH LI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; A909;KAYAH LI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; A90A;KAYAH LI LETTER KA;Lo;0;L;;;;;N;;;;; A90B;KAYAH LI LETTER KHA;Lo;0;L;;;;;N;;;;; A90C;KAYAH LI LETTER GA;Lo;0;L;;;;;N;;;;; A90D;KAYAH LI LETTER NGA;Lo;0;L;;;;;N;;;;; A90E;KAYAH LI LETTER SA;Lo;0;L;;;;;N;;;;; A90F;KAYAH LI LETTER SHA;Lo;0;L;;;;;N;;;;; A910;KAYAH LI LETTER ZA;Lo;0;L;;;;;N;;;;; A911;KAYAH LI LETTER NYA;Lo;0;L;;;;;N;;;;; A912;KAYAH LI LETTER TA;Lo;0;L;;;;;N;;;;; A913;KAYAH LI LETTER HTA;Lo;0;L;;;;;N;;;;; A914;KAYAH LI LETTER NA;Lo;0;L;;;;;N;;;;; A915;KAYAH LI LETTER PA;Lo;0;L;;;;;N;;;;; A916;KAYAH LI LETTER PHA;Lo;0;L;;;;;N;;;;; A917;KAYAH LI LETTER MA;Lo;0;L;;;;;N;;;;; A918;KAYAH LI LETTER DA;Lo;0;L;;;;;N;;;;; A919;KAYAH LI LETTER BA;Lo;0;L;;;;;N;;;;; A91A;KAYAH LI LETTER RA;Lo;0;L;;;;;N;;;;; A91B;KAYAH LI LETTER YA;Lo;0;L;;;;;N;;;;; A91C;KAYAH LI LETTER LA;Lo;0;L;;;;;N;;;;; A91D;KAYAH LI LETTER WA;Lo;0;L;;;;;N;;;;; A91E;KAYAH LI LETTER THA;Lo;0;L;;;;;N;;;;; A91F;KAYAH LI LETTER HA;Lo;0;L;;;;;N;;;;; A920;KAYAH LI LETTER VA;Lo;0;L;;;;;N;;;;; A921;KAYAH LI LETTER CA;Lo;0;L;;;;;N;;;;; A922;KAYAH LI LETTER A;Lo;0;L;;;;;N;;;;; A923;KAYAH LI LETTER OE;Lo;0;L;;;;;N;;;;; A924;KAYAH LI LETTER I;Lo;0;L;;;;;N;;;;; A925;KAYAH LI LETTER OO;Lo;0;L;;;;;N;;;;; A926;KAYAH LI VOWEL UE;Mn;0;NSM;;;;;N;;;;; A927;KAYAH LI VOWEL E;Mn;0;NSM;;;;;N;;;;; A928;KAYAH LI VOWEL U;Mn;0;NSM;;;;;N;;;;; A929;KAYAH LI VOWEL EE;Mn;0;NSM;;;;;N;;;;; A92A;KAYAH LI VOWEL O;Mn;0;NSM;;;;;N;;;;; A92B;KAYAH LI TONE PLOPHU;Mn;220;NSM;;;;;N;;;;; A92C;KAYAH LI TONE CALYA;Mn;220;NSM;;;;;N;;;;; A92D;KAYAH LI TONE CALYA PLOPHU;Mn;220;NSM;;;;;N;;;;; A92E;KAYAH LI SIGN CWI;Po;0;L;;;;;N;;;;; A92F;KAYAH LI SIGN SHYA;Po;0;L;;;;;N;;;;; A930;REJANG LETTER KA;Lo;0;L;;;;;N;;;;; A931;REJANG LETTER GA;Lo;0;L;;;;;N;;;;; A932;REJANG LETTER NGA;Lo;0;L;;;;;N;;;;; A933;REJANG LETTER TA;Lo;0;L;;;;;N;;;;; A934;REJANG LETTER DA;Lo;0;L;;;;;N;;;;; A935;REJANG LETTER NA;Lo;0;L;;;;;N;;;;; A936;REJANG LETTER PA;Lo;0;L;;;;;N;;;;; A937;REJANG LETTER BA;Lo;0;L;;;;;N;;;;; A938;REJANG LETTER MA;Lo;0;L;;;;;N;;;;; A939;REJANG LETTER CA;Lo;0;L;;;;;N;;;;; A93A;REJANG LETTER JA;Lo;0;L;;;;;N;;;;; A93B;REJANG LETTER NYA;Lo;0;L;;;;;N;;;;; A93C;REJANG LETTER SA;Lo;0;L;;;;;N;;;;; A93D;REJANG LETTER RA;Lo;0;L;;;;;N;;;;; A93E;REJANG LETTER LA;Lo;0;L;;;;;N;;;;; A93F;REJANG LETTER YA;Lo;0;L;;;;;N;;;;; A940;REJANG LETTER WA;Lo;0;L;;;;;N;;;;; A941;REJANG LETTER HA;Lo;0;L;;;;;N;;;;; A942;REJANG LETTER MBA;Lo;0;L;;;;;N;;;;; A943;REJANG LETTER NGGA;Lo;0;L;;;;;N;;;;; A944;REJANG LETTER NDA;Lo;0;L;;;;;N;;;;; A945;REJANG LETTER NYJA;Lo;0;L;;;;;N;;;;; A946;REJANG LETTER A;Lo;0;L;;;;;N;;;;; A947;REJANG VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; A948;REJANG VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; A949;REJANG VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; A94A;REJANG VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; A94B;REJANG VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; A94C;REJANG VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;; A94D;REJANG VOWEL SIGN EU;Mn;0;NSM;;;;;N;;;;; A94E;REJANG VOWEL SIGN EA;Mn;0;NSM;;;;;N;;;;; A94F;REJANG CONSONANT SIGN NG;Mn;0;NSM;;;;;N;;;;; A950;REJANG CONSONANT SIGN N;Mn;0;NSM;;;;;N;;;;; A951;REJANG CONSONANT SIGN R;Mn;0;NSM;;;;;N;;;;; A952;REJANG CONSONANT SIGN H;Mc;0;L;;;;;N;;;;; A953;REJANG VIRAMA;Mc;9;L;;;;;N;;;;; A95F;REJANG SECTION MARK;Po;0;L;;;;;N;;;;; A960;HANGUL CHOSEONG TIKEUT-MIEUM;Lo;0;L;;;;;N;;;;; A961;HANGUL CHOSEONG TIKEUT-PIEUP;Lo;0;L;;;;;N;;;;; A962;HANGUL CHOSEONG TIKEUT-SIOS;Lo;0;L;;;;;N;;;;; A963;HANGUL CHOSEONG TIKEUT-CIEUC;Lo;0;L;;;;;N;;;;; A964;HANGUL CHOSEONG RIEUL-KIYEOK;Lo;0;L;;;;;N;;;;; A965;HANGUL CHOSEONG RIEUL-SSANGKIYEOK;Lo;0;L;;;;;N;;;;; A966;HANGUL CHOSEONG RIEUL-TIKEUT;Lo;0;L;;;;;N;;;;; A967;HANGUL CHOSEONG RIEUL-SSANGTIKEUT;Lo;0;L;;;;;N;;;;; A968;HANGUL CHOSEONG RIEUL-MIEUM;Lo;0;L;;;;;N;;;;; A969;HANGUL CHOSEONG RIEUL-PIEUP;Lo;0;L;;;;;N;;;;; A96A;HANGUL CHOSEONG RIEUL-SSANGPIEUP;Lo;0;L;;;;;N;;;;; A96B;HANGUL CHOSEONG RIEUL-KAPYEOUNPIEUP;Lo;0;L;;;;;N;;;;; A96C;HANGUL CHOSEONG RIEUL-SIOS;Lo;0;L;;;;;N;;;;; A96D;HANGUL CHOSEONG RIEUL-CIEUC;Lo;0;L;;;;;N;;;;; A96E;HANGUL CHOSEONG RIEUL-KHIEUKH;Lo;0;L;;;;;N;;;;; A96F;HANGUL CHOSEONG MIEUM-KIYEOK;Lo;0;L;;;;;N;;;;; A970;HANGUL CHOSEONG MIEUM-TIKEUT;Lo;0;L;;;;;N;;;;; A971;HANGUL CHOSEONG MIEUM-SIOS;Lo;0;L;;;;;N;;;;; A972;HANGUL CHOSEONG PIEUP-SIOS-THIEUTH;Lo;0;L;;;;;N;;;;; A973;HANGUL CHOSEONG PIEUP-KHIEUKH;Lo;0;L;;;;;N;;;;; A974;HANGUL CHOSEONG PIEUP-HIEUH;Lo;0;L;;;;;N;;;;; A975;HANGUL CHOSEONG SSANGSIOS-PIEUP;Lo;0;L;;;;;N;;;;; A976;HANGUL CHOSEONG IEUNG-RIEUL;Lo;0;L;;;;;N;;;;; A977;HANGUL CHOSEONG IEUNG-HIEUH;Lo;0;L;;;;;N;;;;; A978;HANGUL CHOSEONG SSANGCIEUC-HIEUH;Lo;0;L;;;;;N;;;;; A979;HANGUL CHOSEONG SSANGTHIEUTH;Lo;0;L;;;;;N;;;;; A97A;HANGUL CHOSEONG PHIEUPH-HIEUH;Lo;0;L;;;;;N;;;;; A97B;HANGUL CHOSEONG HIEUH-SIOS;Lo;0;L;;;;;N;;;;; A97C;HANGUL CHOSEONG SSANGYEORINHIEUH;Lo;0;L;;;;;N;;;;; A980;JAVANESE SIGN PANYANGGA;Mn;0;NSM;;;;;N;;;;; A981;JAVANESE SIGN CECAK;Mn;0;NSM;;;;;N;;;;; A982;JAVANESE SIGN LAYAR;Mn;0;NSM;;;;;N;;;;; A983;JAVANESE SIGN WIGNYAN;Mc;0;L;;;;;N;;;;; A984;JAVANESE LETTER A;Lo;0;L;;;;;N;;;;; A985;JAVANESE LETTER I KAWI;Lo;0;L;;;;;N;;;;; A986;JAVANESE LETTER I;Lo;0;L;;;;;N;;;;; A987;JAVANESE LETTER II;Lo;0;L;;;;;N;;;;; A988;JAVANESE LETTER U;Lo;0;L;;;;;N;;;;; A989;JAVANESE LETTER PA CEREK;Lo;0;L;;;;;N;;;;; A98A;JAVANESE LETTER NGA LELET;Lo;0;L;;;;;N;;;;; A98B;JAVANESE LETTER NGA LELET RASWADI;Lo;0;L;;;;;N;;;;; A98C;JAVANESE LETTER E;Lo;0;L;;;;;N;;;;; A98D;JAVANESE LETTER AI;Lo;0;L;;;;;N;;;;; A98E;JAVANESE LETTER O;Lo;0;L;;;;;N;;;;; A98F;JAVANESE LETTER KA;Lo;0;L;;;;;N;;;;; A990;JAVANESE LETTER KA SASAK;Lo;0;L;;;;;N;;;;; A991;JAVANESE LETTER KA MURDA;Lo;0;L;;;;;N;;;;; A992;JAVANESE LETTER GA;Lo;0;L;;;;;N;;;;; A993;JAVANESE LETTER GA MURDA;Lo;0;L;;;;;N;;;;; A994;JAVANESE LETTER NGA;Lo;0;L;;;;;N;;;;; A995;JAVANESE LETTER CA;Lo;0;L;;;;;N;;;;; A996;JAVANESE LETTER CA MURDA;Lo;0;L;;;;;N;;;;; A997;JAVANESE LETTER JA;Lo;0;L;;;;;N;;;;; A998;JAVANESE LETTER NYA MURDA;Lo;0;L;;;;;N;;;;; A999;JAVANESE LETTER JA MAHAPRANA;Lo;0;L;;;;;N;;;;; A99A;JAVANESE LETTER NYA;Lo;0;L;;;;;N;;;;; A99B;JAVANESE LETTER TTA;Lo;0;L;;;;;N;;;;; A99C;JAVANESE LETTER TTA MAHAPRANA;Lo;0;L;;;;;N;;;;; A99D;JAVANESE LETTER DDA;Lo;0;L;;;;;N;;;;; A99E;JAVANESE LETTER DDA MAHAPRANA;Lo;0;L;;;;;N;;;;; A99F;JAVANESE LETTER NA MURDA;Lo;0;L;;;;;N;;;;; A9A0;JAVANESE LETTER TA;Lo;0;L;;;;;N;;;;; A9A1;JAVANESE LETTER TA MURDA;Lo;0;L;;;;;N;;;;; A9A2;JAVANESE LETTER DA;Lo;0;L;;;;;N;;;;; A9A3;JAVANESE LETTER DA MAHAPRANA;Lo;0;L;;;;;N;;;;; A9A4;JAVANESE LETTER NA;Lo;0;L;;;;;N;;;;; A9A5;JAVANESE LETTER PA;Lo;0;L;;;;;N;;;;; A9A6;JAVANESE LETTER PA MURDA;Lo;0;L;;;;;N;;;;; A9A7;JAVANESE LETTER BA;Lo;0;L;;;;;N;;;;; A9A8;JAVANESE LETTER BA MURDA;Lo;0;L;;;;;N;;;;; A9A9;JAVANESE LETTER MA;Lo;0;L;;;;;N;;;;; A9AA;JAVANESE LETTER YA;Lo;0;L;;;;;N;;;;; A9AB;JAVANESE LETTER RA;Lo;0;L;;;;;N;;;;; A9AC;JAVANESE LETTER RA AGUNG;Lo;0;L;;;;;N;;;;; A9AD;JAVANESE LETTER LA;Lo;0;L;;;;;N;;;;; A9AE;JAVANESE LETTER WA;Lo;0;L;;;;;N;;;;; A9AF;JAVANESE LETTER SA MURDA;Lo;0;L;;;;;N;;;;; A9B0;JAVANESE LETTER SA MAHAPRANA;Lo;0;L;;;;;N;;;;; A9B1;JAVANESE LETTER SA;Lo;0;L;;;;;N;;;;; A9B2;JAVANESE LETTER HA;Lo;0;L;;;;;N;;;;; A9B3;JAVANESE SIGN CECAK TELU;Mn;7;NSM;;;;;N;;;;; A9B4;JAVANESE VOWEL SIGN TARUNG;Mc;0;L;;;;;N;;;;; A9B5;JAVANESE VOWEL SIGN TOLONG;Mc;0;L;;;;;N;;;;; A9B6;JAVANESE VOWEL SIGN WULU;Mn;0;NSM;;;;;N;;;;; A9B7;JAVANESE VOWEL SIGN WULU MELIK;Mn;0;NSM;;;;;N;;;;; A9B8;JAVANESE VOWEL SIGN SUKU;Mn;0;NSM;;;;;N;;;;; A9B9;JAVANESE VOWEL SIGN SUKU MENDUT;Mn;0;NSM;;;;;N;;;;; A9BA;JAVANESE VOWEL SIGN TALING;Mc;0;L;;;;;N;;;;; A9BB;JAVANESE VOWEL SIGN DIRGA MURE;Mc;0;L;;;;;N;;;;; A9BC;JAVANESE VOWEL SIGN PEPET;Mn;0;NSM;;;;;N;;;;; A9BD;JAVANESE CONSONANT SIGN KERET;Mc;0;L;;;;;N;;;;; A9BE;JAVANESE CONSONANT SIGN PENGKAL;Mc;0;L;;;;;N;;;;; A9BF;JAVANESE CONSONANT SIGN CAKRA;Mc;0;L;;;;;N;;;;; A9C0;JAVANESE PANGKON;Mc;9;L;;;;;N;;;;; A9C1;JAVANESE LEFT RERENGGAN;Po;0;L;;;;;N;;;;; A9C2;JAVANESE RIGHT RERENGGAN;Po;0;L;;;;;N;;;;; A9C3;JAVANESE PADA ANDAP;Po;0;L;;;;;N;;;;; A9C4;JAVANESE PADA MADYA;Po;0;L;;;;;N;;;;; A9C5;JAVANESE PADA LUHUR;Po;0;L;;;;;N;;;;; A9C6;JAVANESE PADA WINDU;Po;0;L;;;;;N;;;;; A9C7;JAVANESE PADA PANGKAT;Po;0;L;;;;;N;;;;; A9C8;JAVANESE PADA LINGSA;Po;0;L;;;;;N;;;;; A9C9;JAVANESE PADA LUNGSI;Po;0;L;;;;;N;;;;; A9CA;JAVANESE PADA ADEG;Po;0;L;;;;;N;;;;; A9CB;JAVANESE PADA ADEG ADEG;Po;0;L;;;;;N;;;;; A9CC;JAVANESE PADA PISELEH;Po;0;L;;;;;N;;;;; A9CD;JAVANESE TURNED PADA PISELEH;Po;0;L;;;;;N;;;;; A9CF;JAVANESE PANGRANGKEP;Lm;0;L;;;;;N;;;;; A9D0;JAVANESE DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; A9D1;JAVANESE DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; A9D2;JAVANESE DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; A9D3;JAVANESE DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; A9D4;JAVANESE DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; A9D5;JAVANESE DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; A9D6;JAVANESE DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; A9D7;JAVANESE DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; A9D8;JAVANESE DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; A9D9;JAVANESE DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; A9DE;JAVANESE PADA TIRTA TUMETES;Po;0;L;;;;;N;;;;; A9DF;JAVANESE PADA ISEN-ISEN;Po;0;L;;;;;N;;;;; A9E0;MYANMAR LETTER SHAN GHA;Lo;0;L;;;;;N;;;;; A9E1;MYANMAR LETTER SHAN CHA;Lo;0;L;;;;;N;;;;; A9E2;MYANMAR LETTER SHAN JHA;Lo;0;L;;;;;N;;;;; A9E3;MYANMAR LETTER SHAN NNA;Lo;0;L;;;;;N;;;;; A9E4;MYANMAR LETTER SHAN BHA;Lo;0;L;;;;;N;;;;; A9E5;MYANMAR SIGN SHAN SAW;Mn;0;NSM;;;;;N;;;;; A9E6;MYANMAR MODIFIER LETTER SHAN REDUPLICATION;Lm;0;L;;;;;N;;;;; A9E7;MYANMAR LETTER TAI LAING NYA;Lo;0;L;;;;;N;;;;; A9E8;MYANMAR LETTER TAI LAING FA;Lo;0;L;;;;;N;;;;; A9E9;MYANMAR LETTER TAI LAING GA;Lo;0;L;;;;;N;;;;; A9EA;MYANMAR LETTER TAI LAING GHA;Lo;0;L;;;;;N;;;;; A9EB;MYANMAR LETTER TAI LAING JA;Lo;0;L;;;;;N;;;;; A9EC;MYANMAR LETTER TAI LAING JHA;Lo;0;L;;;;;N;;;;; A9ED;MYANMAR LETTER TAI LAING DDA;Lo;0;L;;;;;N;;;;; A9EE;MYANMAR LETTER TAI LAING DDHA;Lo;0;L;;;;;N;;;;; A9EF;MYANMAR LETTER TAI LAING NNA;Lo;0;L;;;;;N;;;;; A9F0;MYANMAR TAI LAING DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; A9F1;MYANMAR TAI LAING DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; A9F2;MYANMAR TAI LAING DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; A9F3;MYANMAR TAI LAING DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; A9F4;MYANMAR TAI LAING DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; A9F5;MYANMAR TAI LAING DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; A9F6;MYANMAR TAI LAING DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; A9F7;MYANMAR TAI LAING DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; A9F8;MYANMAR TAI LAING DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; A9F9;MYANMAR TAI LAING DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; A9FA;MYANMAR LETTER TAI LAING LLA;Lo;0;L;;;;;N;;;;; A9FB;MYANMAR LETTER TAI LAING DA;Lo;0;L;;;;;N;;;;; A9FC;MYANMAR LETTER TAI LAING DHA;Lo;0;L;;;;;N;;;;; A9FD;MYANMAR LETTER TAI LAING BA;Lo;0;L;;;;;N;;;;; A9FE;MYANMAR LETTER TAI LAING BHA;Lo;0;L;;;;;N;;;;; AA00;CHAM LETTER A;Lo;0;L;;;;;N;;;;; AA01;CHAM LETTER I;Lo;0;L;;;;;N;;;;; AA02;CHAM LETTER U;Lo;0;L;;;;;N;;;;; AA03;CHAM LETTER E;Lo;0;L;;;;;N;;;;; AA04;CHAM LETTER AI;Lo;0;L;;;;;N;;;;; AA05;CHAM LETTER O;Lo;0;L;;;;;N;;;;; AA06;CHAM LETTER KA;Lo;0;L;;;;;N;;;;; AA07;CHAM LETTER KHA;Lo;0;L;;;;;N;;;;; AA08;CHAM LETTER GA;Lo;0;L;;;;;N;;;;; AA09;CHAM LETTER GHA;Lo;0;L;;;;;N;;;;; AA0A;CHAM LETTER NGUE;Lo;0;L;;;;;N;;;;; AA0B;CHAM LETTER NGA;Lo;0;L;;;;;N;;;;; AA0C;CHAM LETTER CHA;Lo;0;L;;;;;N;;;;; AA0D;CHAM LETTER CHHA;Lo;0;L;;;;;N;;;;; AA0E;CHAM LETTER JA;Lo;0;L;;;;;N;;;;; AA0F;CHAM LETTER JHA;Lo;0;L;;;;;N;;;;; AA10;CHAM LETTER NHUE;Lo;0;L;;;;;N;;;;; AA11;CHAM LETTER NHA;Lo;0;L;;;;;N;;;;; AA12;CHAM LETTER NHJA;Lo;0;L;;;;;N;;;;; AA13;CHAM LETTER TA;Lo;0;L;;;;;N;;;;; AA14;CHAM LETTER THA;Lo;0;L;;;;;N;;;;; AA15;CHAM LETTER DA;Lo;0;L;;;;;N;;;;; AA16;CHAM LETTER DHA;Lo;0;L;;;;;N;;;;; AA17;CHAM LETTER NUE;Lo;0;L;;;;;N;;;;; AA18;CHAM LETTER NA;Lo;0;L;;;;;N;;;;; AA19;CHAM LETTER DDA;Lo;0;L;;;;;N;;;;; AA1A;CHAM LETTER PA;Lo;0;L;;;;;N;;;;; AA1B;CHAM LETTER PPA;Lo;0;L;;;;;N;;;;; AA1C;CHAM LETTER PHA;Lo;0;L;;;;;N;;;;; AA1D;CHAM LETTER BA;Lo;0;L;;;;;N;;;;; AA1E;CHAM LETTER BHA;Lo;0;L;;;;;N;;;;; AA1F;CHAM LETTER MUE;Lo;0;L;;;;;N;;;;; AA20;CHAM LETTER MA;Lo;0;L;;;;;N;;;;; AA21;CHAM LETTER BBA;Lo;0;L;;;;;N;;;;; AA22;CHAM LETTER YA;Lo;0;L;;;;;N;;;;; AA23;CHAM LETTER RA;Lo;0;L;;;;;N;;;;; AA24;CHAM LETTER LA;Lo;0;L;;;;;N;;;;; AA25;CHAM LETTER VA;Lo;0;L;;;;;N;;;;; AA26;CHAM LETTER SSA;Lo;0;L;;;;;N;;;;; AA27;CHAM LETTER SA;Lo;0;L;;;;;N;;;;; AA28;CHAM LETTER HA;Lo;0;L;;;;;N;;;;; AA29;CHAM VOWEL SIGN AA;Mn;0;NSM;;;;;N;;;;; AA2A;CHAM VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; AA2B;CHAM VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; AA2C;CHAM VOWEL SIGN EI;Mn;0;NSM;;;;;N;;;;; AA2D;CHAM VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; AA2E;CHAM VOWEL SIGN OE;Mn;0;NSM;;;;;N;;;;; AA2F;CHAM VOWEL SIGN O;Mc;0;L;;;;;N;;;;; AA30;CHAM VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; AA31;CHAM VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;; AA32;CHAM VOWEL SIGN UE;Mn;0;NSM;;;;;N;;;;; AA33;CHAM CONSONANT SIGN YA;Mc;0;L;;;;;N;;;;; AA34;CHAM CONSONANT SIGN RA;Mc;0;L;;;;;N;;;;; AA35;CHAM CONSONANT SIGN LA;Mn;0;NSM;;;;;N;;;;; AA36;CHAM CONSONANT SIGN WA;Mn;0;NSM;;;;;N;;;;; AA40;CHAM LETTER FINAL K;Lo;0;L;;;;;N;;;;; AA41;CHAM LETTER FINAL G;Lo;0;L;;;;;N;;;;; AA42;CHAM LETTER FINAL NG;Lo;0;L;;;;;N;;;;; AA43;CHAM CONSONANT SIGN FINAL NG;Mn;0;NSM;;;;;N;;;;; AA44;CHAM LETTER FINAL CH;Lo;0;L;;;;;N;;;;; AA45;CHAM LETTER FINAL T;Lo;0;L;;;;;N;;;;; AA46;CHAM LETTER FINAL N;Lo;0;L;;;;;N;;;;; AA47;CHAM LETTER FINAL P;Lo;0;L;;;;;N;;;;; AA48;CHAM LETTER FINAL Y;Lo;0;L;;;;;N;;;;; AA49;CHAM LETTER FINAL R;Lo;0;L;;;;;N;;;;; AA4A;CHAM LETTER FINAL L;Lo;0;L;;;;;N;;;;; AA4B;CHAM LETTER FINAL SS;Lo;0;L;;;;;N;;;;; AA4C;CHAM CONSONANT SIGN FINAL M;Mn;0;NSM;;;;;N;;;;; AA4D;CHAM CONSONANT SIGN FINAL H;Mc;0;L;;;;;N;;;;; AA50;CHAM DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; AA51;CHAM DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; AA52;CHAM DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; AA53;CHAM DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; AA54;CHAM DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; AA55;CHAM DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; AA56;CHAM DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; AA57;CHAM DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; AA58;CHAM DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; AA59;CHAM DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; AA5C;CHAM PUNCTUATION SPIRAL;Po;0;L;;;;;N;;;;; AA5D;CHAM PUNCTUATION DANDA;Po;0;L;;;;;N;;;;; AA5E;CHAM PUNCTUATION DOUBLE DANDA;Po;0;L;;;;;N;;;;; AA5F;CHAM PUNCTUATION TRIPLE DANDA;Po;0;L;;;;;N;;;;; AA60;MYANMAR LETTER KHAMTI GA;Lo;0;L;;;;;N;;;;; AA61;MYANMAR LETTER KHAMTI CA;Lo;0;L;;;;;N;;;;; AA62;MYANMAR LETTER KHAMTI CHA;Lo;0;L;;;;;N;;;;; AA63;MYANMAR LETTER KHAMTI JA;Lo;0;L;;;;;N;;;;; AA64;MYANMAR LETTER KHAMTI JHA;Lo;0;L;;;;;N;;;;; AA65;MYANMAR LETTER KHAMTI NYA;Lo;0;L;;;;;N;;;;; AA66;MYANMAR LETTER KHAMTI TTA;Lo;0;L;;;;;N;;;;; AA67;MYANMAR LETTER KHAMTI TTHA;Lo;0;L;;;;;N;;;;; AA68;MYANMAR LETTER KHAMTI DDA;Lo;0;L;;;;;N;;;;; AA69;MYANMAR LETTER KHAMTI DDHA;Lo;0;L;;;;;N;;;;; AA6A;MYANMAR LETTER KHAMTI DHA;Lo;0;L;;;;;N;;;;; AA6B;MYANMAR LETTER KHAMTI NA;Lo;0;L;;;;;N;;;;; AA6C;MYANMAR LETTER KHAMTI SA;Lo;0;L;;;;;N;;;;; AA6D;MYANMAR LETTER KHAMTI HA;Lo;0;L;;;;;N;;;;; AA6E;MYANMAR LETTER KHAMTI HHA;Lo;0;L;;;;;N;;;;; AA6F;MYANMAR LETTER KHAMTI FA;Lo;0;L;;;;;N;;;;; AA70;MYANMAR MODIFIER LETTER KHAMTI REDUPLICATION;Lm;0;L;;;;;N;;;;; AA71;MYANMAR LETTER KHAMTI XA;Lo;0;L;;;;;N;;;;; AA72;MYANMAR LETTER KHAMTI ZA;Lo;0;L;;;;;N;;;;; AA73;MYANMAR LETTER KHAMTI RA;Lo;0;L;;;;;N;;;;; AA74;MYANMAR LOGOGRAM KHAMTI OAY;Lo;0;L;;;;;N;;;;; AA75;MYANMAR LOGOGRAM KHAMTI QN;Lo;0;L;;;;;N;;;;; AA76;MYANMAR LOGOGRAM KHAMTI HM;Lo;0;L;;;;;N;;;;; AA77;MYANMAR SYMBOL AITON EXCLAMATION;So;0;L;;;;;N;;;;; AA78;MYANMAR SYMBOL AITON ONE;So;0;L;;;;;N;;;;; AA79;MYANMAR SYMBOL AITON TWO;So;0;L;;;;;N;;;;; AA7A;MYANMAR LETTER AITON RA;Lo;0;L;;;;;N;;;;; AA7B;MYANMAR SIGN PAO KAREN TONE;Mc;0;L;;;;;N;;;;; AA7C;MYANMAR SIGN TAI LAING TONE-2;Mn;0;NSM;;;;;N;;;;; AA7D;MYANMAR SIGN TAI LAING TONE-5;Mc;0;L;;;;;N;;;;; AA7E;MYANMAR LETTER SHWE PALAUNG CHA;Lo;0;L;;;;;N;;;;; AA7F;MYANMAR LETTER SHWE PALAUNG SHA;Lo;0;L;;;;;N;;;;; AA80;TAI VIET LETTER LOW KO;Lo;0;L;;;;;N;;;;; AA81;TAI VIET LETTER HIGH KO;Lo;0;L;;;;;N;;;;; AA82;TAI VIET LETTER LOW KHO;Lo;0;L;;;;;N;;;;; AA83;TAI VIET LETTER HIGH KHO;Lo;0;L;;;;;N;;;;; AA84;TAI VIET LETTER LOW KHHO;Lo;0;L;;;;;N;;;;; AA85;TAI VIET LETTER HIGH KHHO;Lo;0;L;;;;;N;;;;; AA86;TAI VIET LETTER LOW GO;Lo;0;L;;;;;N;;;;; AA87;TAI VIET LETTER HIGH GO;Lo;0;L;;;;;N;;;;; AA88;TAI VIET LETTER LOW NGO;Lo;0;L;;;;;N;;;;; AA89;TAI VIET LETTER HIGH NGO;Lo;0;L;;;;;N;;;;; AA8A;TAI VIET LETTER LOW CO;Lo;0;L;;;;;N;;;;; AA8B;TAI VIET LETTER HIGH CO;Lo;0;L;;;;;N;;;;; AA8C;TAI VIET LETTER LOW CHO;Lo;0;L;;;;;N;;;;; AA8D;TAI VIET LETTER HIGH CHO;Lo;0;L;;;;;N;;;;; AA8E;TAI VIET LETTER LOW SO;Lo;0;L;;;;;N;;;;; AA8F;TAI VIET LETTER HIGH SO;Lo;0;L;;;;;N;;;;; AA90;TAI VIET LETTER LOW NYO;Lo;0;L;;;;;N;;;;; AA91;TAI VIET LETTER HIGH NYO;Lo;0;L;;;;;N;;;;; AA92;TAI VIET LETTER LOW DO;Lo;0;L;;;;;N;;;;; AA93;TAI VIET LETTER HIGH DO;Lo;0;L;;;;;N;;;;; AA94;TAI VIET LETTER LOW TO;Lo;0;L;;;;;N;;;;; AA95;TAI VIET LETTER HIGH TO;Lo;0;L;;;;;N;;;;; AA96;TAI VIET LETTER LOW THO;Lo;0;L;;;;;N;;;;; AA97;TAI VIET LETTER HIGH THO;Lo;0;L;;;;;N;;;;; AA98;TAI VIET LETTER LOW NO;Lo;0;L;;;;;N;;;;; AA99;TAI VIET LETTER HIGH NO;Lo;0;L;;;;;N;;;;; AA9A;TAI VIET LETTER LOW BO;Lo;0;L;;;;;N;;;;; AA9B;TAI VIET LETTER HIGH BO;Lo;0;L;;;;;N;;;;; AA9C;TAI VIET LETTER LOW PO;Lo;0;L;;;;;N;;;;; AA9D;TAI VIET LETTER HIGH PO;Lo;0;L;;;;;N;;;;; AA9E;TAI VIET LETTER LOW PHO;Lo;0;L;;;;;N;;;;; AA9F;TAI VIET LETTER HIGH PHO;Lo;0;L;;;;;N;;;;; AAA0;TAI VIET LETTER LOW FO;Lo;0;L;;;;;N;;;;; AAA1;TAI VIET LETTER HIGH FO;Lo;0;L;;;;;N;;;;; AAA2;TAI VIET LETTER LOW MO;Lo;0;L;;;;;N;;;;; AAA3;TAI VIET LETTER HIGH MO;Lo;0;L;;;;;N;;;;; AAA4;TAI VIET LETTER LOW YO;Lo;0;L;;;;;N;;;;; AAA5;TAI VIET LETTER HIGH YO;Lo;0;L;;;;;N;;;;; AAA6;TAI VIET LETTER LOW RO;Lo;0;L;;;;;N;;;;; AAA7;TAI VIET LETTER HIGH RO;Lo;0;L;;;;;N;;;;; AAA8;TAI VIET LETTER LOW LO;Lo;0;L;;;;;N;;;;; AAA9;TAI VIET LETTER HIGH LO;Lo;0;L;;;;;N;;;;; AAAA;TAI VIET LETTER LOW VO;Lo;0;L;;;;;N;;;;; AAAB;TAI VIET LETTER HIGH VO;Lo;0;L;;;;;N;;;;; AAAC;TAI VIET LETTER LOW HO;Lo;0;L;;;;;N;;;;; AAAD;TAI VIET LETTER HIGH HO;Lo;0;L;;;;;N;;;;; AAAE;TAI VIET LETTER LOW O;Lo;0;L;;;;;N;;;;; AAAF;TAI VIET LETTER HIGH O;Lo;0;L;;;;;N;;;;; AAB0;TAI VIET MAI KANG;Mn;230;NSM;;;;;N;;;;; AAB1;TAI VIET VOWEL AA;Lo;0;L;;;;;N;;;;; AAB2;TAI VIET VOWEL I;Mn;230;NSM;;;;;N;;;;; AAB3;TAI VIET VOWEL UE;Mn;230;NSM;;;;;N;;;;; AAB4;TAI VIET VOWEL U;Mn;220;NSM;;;;;N;;;;; AAB5;TAI VIET VOWEL E;Lo;0;L;;;;;N;;;;; AAB6;TAI VIET VOWEL O;Lo;0;L;;;;;N;;;;; AAB7;TAI VIET MAI KHIT;Mn;230;NSM;;;;;N;;;;; AAB8;TAI VIET VOWEL IA;Mn;230;NSM;;;;;N;;;;; AAB9;TAI VIET VOWEL UEA;Lo;0;L;;;;;N;;;;; AABA;TAI VIET VOWEL UA;Lo;0;L;;;;;N;;;;; AABB;TAI VIET VOWEL AUE;Lo;0;L;;;;;N;;;;; AABC;TAI VIET VOWEL AY;Lo;0;L;;;;;N;;;;; AABD;TAI VIET VOWEL AN;Lo;0;L;;;;;N;;;;; AABE;TAI VIET VOWEL AM;Mn;230;NSM;;;;;N;;;;; AABF;TAI VIET TONE MAI EK;Mn;230;NSM;;;;;N;;;;; AAC0;TAI VIET TONE MAI NUENG;Lo;0;L;;;;;N;;;;; AAC1;TAI VIET TONE MAI THO;Mn;230;NSM;;;;;N;;;;; AAC2;TAI VIET TONE MAI SONG;Lo;0;L;;;;;N;;;;; AADB;TAI VIET SYMBOL KON;Lo;0;L;;;;;N;;;;; AADC;TAI VIET SYMBOL NUENG;Lo;0;L;;;;;N;;;;; AADD;TAI VIET SYMBOL SAM;Lm;0;L;;;;;N;;;;; AADE;TAI VIET SYMBOL HO HOI;Po;0;L;;;;;N;;;;; AADF;TAI VIET SYMBOL KOI KOI;Po;0;L;;;;;N;;;;; AAE0;MEETEI MAYEK LETTER E;Lo;0;L;;;;;N;;;;; AAE1;MEETEI MAYEK LETTER O;Lo;0;L;;;;;N;;;;; AAE2;MEETEI MAYEK LETTER CHA;Lo;0;L;;;;;N;;;;; AAE3;MEETEI MAYEK LETTER NYA;Lo;0;L;;;;;N;;;;; AAE4;MEETEI MAYEK LETTER TTA;Lo;0;L;;;;;N;;;;; AAE5;MEETEI MAYEK LETTER TTHA;Lo;0;L;;;;;N;;;;; AAE6;MEETEI MAYEK LETTER DDA;Lo;0;L;;;;;N;;;;; AAE7;MEETEI MAYEK LETTER DDHA;Lo;0;L;;;;;N;;;;; AAE8;MEETEI MAYEK LETTER NNA;Lo;0;L;;;;;N;;;;; AAE9;MEETEI MAYEK LETTER SHA;Lo;0;L;;;;;N;;;;; AAEA;MEETEI MAYEK LETTER SSA;Lo;0;L;;;;;N;;;;; AAEB;MEETEI MAYEK VOWEL SIGN II;Mc;0;L;;;;;N;;;;; AAEC;MEETEI MAYEK VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; AAED;MEETEI MAYEK VOWEL SIGN AAI;Mn;0;NSM;;;;;N;;;;; AAEE;MEETEI MAYEK VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; AAEF;MEETEI MAYEK VOWEL SIGN AAU;Mc;0;L;;;;;N;;;;; AAF0;MEETEI MAYEK CHEIKHAN;Po;0;L;;;;;N;;;;; AAF1;MEETEI MAYEK AHANG KHUDAM;Po;0;L;;;;;N;;;;; AAF2;MEETEI MAYEK ANJI;Lo;0;L;;;;;N;;;;; AAF3;MEETEI MAYEK SYLLABLE REPETITION MARK;Lm;0;L;;;;;N;;;;; AAF4;MEETEI MAYEK WORD REPETITION MARK;Lm;0;L;;;;;N;;;;; AAF5;MEETEI MAYEK VOWEL SIGN VISARGA;Mc;0;L;;;;;N;;;;; AAF6;MEETEI MAYEK VIRAMA;Mn;9;NSM;;;;;N;;;;; AB01;ETHIOPIC SYLLABLE TTHU;Lo;0;L;;;;;N;;;;; AB02;ETHIOPIC SYLLABLE TTHI;Lo;0;L;;;;;N;;;;; AB03;ETHIOPIC SYLLABLE TTHAA;Lo;0;L;;;;;N;;;;; AB04;ETHIOPIC SYLLABLE TTHEE;Lo;0;L;;;;;N;;;;; AB05;ETHIOPIC SYLLABLE TTHE;Lo;0;L;;;;;N;;;;; AB06;ETHIOPIC SYLLABLE TTHO;Lo;0;L;;;;;N;;;;; AB09;ETHIOPIC SYLLABLE DDHU;Lo;0;L;;;;;N;;;;; AB0A;ETHIOPIC SYLLABLE DDHI;Lo;0;L;;;;;N;;;;; AB0B;ETHIOPIC SYLLABLE DDHAA;Lo;0;L;;;;;N;;;;; AB0C;ETHIOPIC SYLLABLE DDHEE;Lo;0;L;;;;;N;;;;; AB0D;ETHIOPIC SYLLABLE DDHE;Lo;0;L;;;;;N;;;;; AB0E;ETHIOPIC SYLLABLE DDHO;Lo;0;L;;;;;N;;;;; AB11;ETHIOPIC SYLLABLE DZU;Lo;0;L;;;;;N;;;;; AB12;ETHIOPIC SYLLABLE DZI;Lo;0;L;;;;;N;;;;; AB13;ETHIOPIC SYLLABLE DZAA;Lo;0;L;;;;;N;;;;; AB14;ETHIOPIC SYLLABLE DZEE;Lo;0;L;;;;;N;;;;; AB15;ETHIOPIC SYLLABLE DZE;Lo;0;L;;;;;N;;;;; AB16;ETHIOPIC SYLLABLE DZO;Lo;0;L;;;;;N;;;;; AB20;ETHIOPIC SYLLABLE CCHHA;Lo;0;L;;;;;N;;;;; AB21;ETHIOPIC SYLLABLE CCHHU;Lo;0;L;;;;;N;;;;; AB22;ETHIOPIC SYLLABLE CCHHI;Lo;0;L;;;;;N;;;;; AB23;ETHIOPIC SYLLABLE CCHHAA;Lo;0;L;;;;;N;;;;; AB24;ETHIOPIC SYLLABLE CCHHEE;Lo;0;L;;;;;N;;;;; AB25;ETHIOPIC SYLLABLE CCHHE;Lo;0;L;;;;;N;;;;; AB26;ETHIOPIC SYLLABLE CCHHO;Lo;0;L;;;;;N;;;;; AB28;ETHIOPIC SYLLABLE BBA;Lo;0;L;;;;;N;;;;; AB29;ETHIOPIC SYLLABLE BBU;Lo;0;L;;;;;N;;;;; AB2A;ETHIOPIC SYLLABLE BBI;Lo;0;L;;;;;N;;;;; AB2B;ETHIOPIC SYLLABLE BBAA;Lo;0;L;;;;;N;;;;; AB2C;ETHIOPIC SYLLABLE BBEE;Lo;0;L;;;;;N;;;;; AB2D;ETHIOPIC SYLLABLE BBE;Lo;0;L;;;;;N;;;;; AB2E;ETHIOPIC SYLLABLE BBO;Lo;0;L;;;;;N;;;;; AB30;LATIN SMALL LETTER BARRED ALPHA;Ll;0;L;;;;;N;;;;; AB31;LATIN SMALL LETTER A REVERSED-SCHWA;Ll;0;L;;;;;N;;;;; AB32;LATIN SMALL LETTER BLACKLETTER E;Ll;0;L;;;;;N;;;;; AB33;LATIN SMALL LETTER BARRED E;Ll;0;L;;;;;N;;;;; AB34;LATIN SMALL LETTER E WITH FLOURISH;Ll;0;L;;;;;N;;;;; AB35;LATIN SMALL LETTER LENIS F;Ll;0;L;;;;;N;;;;; AB36;LATIN SMALL LETTER SCRIPT G WITH CROSSED-TAIL;Ll;0;L;;;;;N;;;;; AB37;LATIN SMALL LETTER L WITH INVERTED LAZY S;Ll;0;L;;;;;N;;;;; AB38;LATIN SMALL LETTER L WITH DOUBLE MIDDLE TILDE;Ll;0;L;;;;;N;;;;; AB39;LATIN SMALL LETTER L WITH MIDDLE RING;Ll;0;L;;;;;N;;;;; AB3A;LATIN SMALL LETTER M WITH CROSSED-TAIL;Ll;0;L;;;;;N;;;;; AB3B;LATIN SMALL LETTER N WITH CROSSED-TAIL;Ll;0;L;;;;;N;;;;; AB3C;LATIN SMALL LETTER ENG WITH CROSSED-TAIL;Ll;0;L;;;;;N;;;;; AB3D;LATIN SMALL LETTER BLACKLETTER O;Ll;0;L;;;;;N;;;;; AB3E;LATIN SMALL LETTER BLACKLETTER O WITH STROKE;Ll;0;L;;;;;N;;;;; AB3F;LATIN SMALL LETTER OPEN O WITH STROKE;Ll;0;L;;;;;N;;;;; AB40;LATIN SMALL LETTER INVERTED OE;Ll;0;L;;;;;N;;;;; AB41;LATIN SMALL LETTER TURNED OE WITH STROKE;Ll;0;L;;;;;N;;;;; AB42;LATIN SMALL LETTER TURNED OE WITH HORIZONTAL STROKE;Ll;0;L;;;;;N;;;;; AB43;LATIN SMALL LETTER TURNED O OPEN-O;Ll;0;L;;;;;N;;;;; AB44;LATIN SMALL LETTER TURNED O OPEN-O WITH STROKE;Ll;0;L;;;;;N;;;;; AB45;LATIN SMALL LETTER STIRRUP R;Ll;0;L;;;;;N;;;;; AB46;LATIN LETTER SMALL CAPITAL R WITH RIGHT LEG;Ll;0;L;;;;;N;;;;; AB47;LATIN SMALL LETTER R WITHOUT HANDLE;Ll;0;L;;;;;N;;;;; AB48;LATIN SMALL LETTER DOUBLE R;Ll;0;L;;;;;N;;;;; AB49;LATIN SMALL LETTER R WITH CROSSED-TAIL;Ll;0;L;;;;;N;;;;; AB4A;LATIN SMALL LETTER DOUBLE R WITH CROSSED-TAIL;Ll;0;L;;;;;N;;;;; AB4B;LATIN SMALL LETTER SCRIPT R;Ll;0;L;;;;;N;;;;; AB4C;LATIN SMALL LETTER SCRIPT R WITH RING;Ll;0;L;;;;;N;;;;; AB4D;LATIN SMALL LETTER BASELINE ESH;Ll;0;L;;;;;N;;;;; AB4E;LATIN SMALL LETTER U WITH SHORT RIGHT LEG;Ll;0;L;;;;;N;;;;; AB4F;LATIN SMALL LETTER U BAR WITH SHORT RIGHT LEG;Ll;0;L;;;;;N;;;;; AB50;LATIN SMALL LETTER UI;Ll;0;L;;;;;N;;;;; AB51;LATIN SMALL LETTER TURNED UI;Ll;0;L;;;;;N;;;;; AB52;LATIN SMALL LETTER U WITH LEFT HOOK;Ll;0;L;;;;;N;;;;; AB53;LATIN SMALL LETTER CHI;Ll;0;L;;;;;N;;;A7B3;;A7B3 AB54;LATIN SMALL LETTER CHI WITH LOW RIGHT RING;Ll;0;L;;;;;N;;;;; AB55;LATIN SMALL LETTER CHI WITH LOW LEFT SERIF;Ll;0;L;;;;;N;;;;; AB56;LATIN SMALL LETTER X WITH LOW RIGHT RING;Ll;0;L;;;;;N;;;;; AB57;LATIN SMALL LETTER X WITH LONG LEFT LEG;Ll;0;L;;;;;N;;;;; AB58;LATIN SMALL LETTER X WITH LONG LEFT LEG AND LOW RIGHT RING;Ll;0;L;;;;;N;;;;; AB59;LATIN SMALL LETTER X WITH LONG LEFT LEG WITH SERIF;Ll;0;L;;;;;N;;;;; AB5A;LATIN SMALL LETTER Y WITH SHORT RIGHT LEG;Ll;0;L;;;;;N;;;;; AB5B;MODIFIER BREVE WITH INVERTED BREVE;Sk;0;L;;;;;N;;;;; AB5C;MODIFIER LETTER SMALL HENG;Lm;0;L;<super> A727;;;;N;;;;; AB5D;MODIFIER LETTER SMALL L WITH INVERTED LAZY S;Lm;0;L;<super> AB37;;;;N;;;;; AB5E;MODIFIER LETTER SMALL L WITH MIDDLE TILDE;Lm;0;L;<super> 026B;;;;N;;;;; AB5F;MODIFIER LETTER SMALL U WITH LEFT HOOK;Lm;0;L;<super> AB52;;;;N;;;;; AB60;LATIN SMALL LETTER SAKHA YAT;Ll;0;L;;;;;N;;;;; AB61;LATIN SMALL LETTER IOTIFIED E;Ll;0;L;;;;;N;;;;; AB62;LATIN SMALL LETTER OPEN OE;Ll;0;L;;;;;N;;;;; AB63;LATIN SMALL LETTER UO;Ll;0;L;;;;;N;;;;; AB64;LATIN SMALL LETTER INVERTED ALPHA;Ll;0;L;;;;;N;;;;; AB65;GREEK LETTER SMALL CAPITAL OMEGA;Ll;0;L;;;;;N;;;;; AB70;CHEROKEE SMALL LETTER A;Ll;0;L;;;;;N;;;13A0;;13A0 AB71;CHEROKEE SMALL LETTER E;Ll;0;L;;;;;N;;;13A1;;13A1 AB72;CHEROKEE SMALL LETTER I;Ll;0;L;;;;;N;;;13A2;;13A2 AB73;CHEROKEE SMALL LETTER O;Ll;0;L;;;;;N;;;13A3;;13A3 AB74;CHEROKEE SMALL LETTER U;Ll;0;L;;;;;N;;;13A4;;13A4 AB75;CHEROKEE SMALL LETTER V;Ll;0;L;;;;;N;;;13A5;;13A5 AB76;CHEROKEE SMALL LETTER GA;Ll;0;L;;;;;N;;;13A6;;13A6 AB77;CHEROKEE SMALL LETTER KA;Ll;0;L;;;;;N;;;13A7;;13A7 AB78;CHEROKEE SMALL LETTER GE;Ll;0;L;;;;;N;;;13A8;;13A8 AB79;CHEROKEE SMALL LETTER GI;Ll;0;L;;;;;N;;;13A9;;13A9 AB7A;CHEROKEE SMALL LETTER GO;Ll;0;L;;;;;N;;;13AA;;13AA AB7B;CHEROKEE SMALL LETTER GU;Ll;0;L;;;;;N;;;13AB;;13AB AB7C;CHEROKEE SMALL LETTER GV;Ll;0;L;;;;;N;;;13AC;;13AC AB7D;CHEROKEE SMALL LETTER HA;Ll;0;L;;;;;N;;;13AD;;13AD AB7E;CHEROKEE SMALL LETTER HE;Ll;0;L;;;;;N;;;13AE;;13AE AB7F;CHEROKEE SMALL LETTER HI;Ll;0;L;;;;;N;;;13AF;;13AF AB80;CHEROKEE SMALL LETTER HO;Ll;0;L;;;;;N;;;13B0;;13B0 AB81;CHEROKEE SMALL LETTER HU;Ll;0;L;;;;;N;;;13B1;;13B1 AB82;CHEROKEE SMALL LETTER HV;Ll;0;L;;;;;N;;;13B2;;13B2 AB83;CHEROKEE SMALL LETTER LA;Ll;0;L;;;;;N;;;13B3;;13B3 AB84;CHEROKEE SMALL LETTER LE;Ll;0;L;;;;;N;;;13B4;;13B4 AB85;CHEROKEE SMALL LETTER LI;Ll;0;L;;;;;N;;;13B5;;13B5 AB86;CHEROKEE SMALL LETTER LO;Ll;0;L;;;;;N;;;13B6;;13B6 AB87;CHEROKEE SMALL LETTER LU;Ll;0;L;;;;;N;;;13B7;;13B7 AB88;CHEROKEE SMALL LETTER LV;Ll;0;L;;;;;N;;;13B8;;13B8 AB89;CHEROKEE SMALL LETTER MA;Ll;0;L;;;;;N;;;13B9;;13B9 AB8A;CHEROKEE SMALL LETTER ME;Ll;0;L;;;;;N;;;13BA;;13BA AB8B;CHEROKEE SMALL LETTER MI;Ll;0;L;;;;;N;;;13BB;;13BB AB8C;CHEROKEE SMALL LETTER MO;Ll;0;L;;;;;N;;;13BC;;13BC AB8D;CHEROKEE SMALL LETTER MU;Ll;0;L;;;;;N;;;13BD;;13BD AB8E;CHEROKEE SMALL LETTER NA;Ll;0;L;;;;;N;;;13BE;;13BE AB8F;CHEROKEE SMALL LETTER HNA;Ll;0;L;;;;;N;;;13BF;;13BF AB90;CHEROKEE SMALL LETTER NAH;Ll;0;L;;;;;N;;;13C0;;13C0 AB91;CHEROKEE SMALL LETTER NE;Ll;0;L;;;;;N;;;13C1;;13C1 AB92;CHEROKEE SMALL LETTER NI;Ll;0;L;;;;;N;;;13C2;;13C2 AB93;CHEROKEE SMALL LETTER NO;Ll;0;L;;;;;N;;;13C3;;13C3 AB94;CHEROKEE SMALL LETTER NU;Ll;0;L;;;;;N;;;13C4;;13C4 AB95;CHEROKEE SMALL LETTER NV;Ll;0;L;;;;;N;;;13C5;;13C5 AB96;CHEROKEE SMALL LETTER QUA;Ll;0;L;;;;;N;;;13C6;;13C6 AB97;CHEROKEE SMALL LETTER QUE;Ll;0;L;;;;;N;;;13C7;;13C7 AB98;CHEROKEE SMALL LETTER QUI;Ll;0;L;;;;;N;;;13C8;;13C8 AB99;CHEROKEE SMALL LETTER QUO;Ll;0;L;;;;;N;;;13C9;;13C9 AB9A;CHEROKEE SMALL LETTER QUU;Ll;0;L;;;;;N;;;13CA;;13CA AB9B;CHEROKEE SMALL LETTER QUV;Ll;0;L;;;;;N;;;13CB;;13CB AB9C;CHEROKEE SMALL LETTER SA;Ll;0;L;;;;;N;;;13CC;;13CC AB9D;CHEROKEE SMALL LETTER S;Ll;0;L;;;;;N;;;13CD;;13CD AB9E;CHEROKEE SMALL LETTER SE;Ll;0;L;;;;;N;;;13CE;;13CE AB9F;CHEROKEE SMALL LETTER SI;Ll;0;L;;;;;N;;;13CF;;13CF ABA0;CHEROKEE SMALL LETTER SO;Ll;0;L;;;;;N;;;13D0;;13D0 ABA1;CHEROKEE SMALL LETTER SU;Ll;0;L;;;;;N;;;13D1;;13D1 ABA2;CHEROKEE SMALL LETTER SV;Ll;0;L;;;;;N;;;13D2;;13D2 ABA3;CHEROKEE SMALL LETTER DA;Ll;0;L;;;;;N;;;13D3;;13D3 ABA4;CHEROKEE SMALL LETTER TA;Ll;0;L;;;;;N;;;13D4;;13D4 ABA5;CHEROKEE SMALL LETTER DE;Ll;0;L;;;;;N;;;13D5;;13D5 ABA6;CHEROKEE SMALL LETTER TE;Ll;0;L;;;;;N;;;13D6;;13D6 ABA7;CHEROKEE SMALL LETTER DI;Ll;0;L;;;;;N;;;13D7;;13D7 ABA8;CHEROKEE SMALL LETTER TI;Ll;0;L;;;;;N;;;13D8;;13D8 ABA9;CHEROKEE SMALL LETTER DO;Ll;0;L;;;;;N;;;13D9;;13D9 ABAA;CHEROKEE SMALL LETTER DU;Ll;0;L;;;;;N;;;13DA;;13DA ABAB;CHEROKEE SMALL LETTER DV;Ll;0;L;;;;;N;;;13DB;;13DB ABAC;CHEROKEE SMALL LETTER DLA;Ll;0;L;;;;;N;;;13DC;;13DC ABAD;CHEROKEE SMALL LETTER TLA;Ll;0;L;;;;;N;;;13DD;;13DD ABAE;CHEROKEE SMALL LETTER TLE;Ll;0;L;;;;;N;;;13DE;;13DE ABAF;CHEROKEE SMALL LETTER TLI;Ll;0;L;;;;;N;;;13DF;;13DF ABB0;CHEROKEE SMALL LETTER TLO;Ll;0;L;;;;;N;;;13E0;;13E0 ABB1;CHEROKEE SMALL LETTER TLU;Ll;0;L;;;;;N;;;13E1;;13E1 ABB2;CHEROKEE SMALL LETTER TLV;Ll;0;L;;;;;N;;;13E2;;13E2 ABB3;CHEROKEE SMALL LETTER TSA;Ll;0;L;;;;;N;;;13E3;;13E3 ABB4;CHEROKEE SMALL LETTER TSE;Ll;0;L;;;;;N;;;13E4;;13E4 ABB5;CHEROKEE SMALL LETTER TSI;Ll;0;L;;;;;N;;;13E5;;13E5 ABB6;CHEROKEE SMALL LETTER TSO;Ll;0;L;;;;;N;;;13E6;;13E6 ABB7;CHEROKEE SMALL LETTER TSU;Ll;0;L;;;;;N;;;13E7;;13E7 ABB8;CHEROKEE SMALL LETTER TSV;Ll;0;L;;;;;N;;;13E8;;13E8 ABB9;CHEROKEE SMALL LETTER WA;Ll;0;L;;;;;N;;;13E9;;13E9 ABBA;CHEROKEE SMALL LETTER WE;Ll;0;L;;;;;N;;;13EA;;13EA ABBB;CHEROKEE SMALL LETTER WI;Ll;0;L;;;;;N;;;13EB;;13EB ABBC;CHEROKEE SMALL LETTER WO;Ll;0;L;;;;;N;;;13EC;;13EC ABBD;CHEROKEE SMALL LETTER WU;Ll;0;L;;;;;N;;;13ED;;13ED ABBE;CHEROKEE SMALL LETTER WV;Ll;0;L;;;;;N;;;13EE;;13EE ABBF;CHEROKEE SMALL LETTER YA;Ll;0;L;;;;;N;;;13EF;;13EF ABC0;MEETEI MAYEK LETTER KOK;Lo;0;L;;;;;N;;;;; ABC1;MEETEI MAYEK LETTER SAM;Lo;0;L;;;;;N;;;;; ABC2;MEETEI MAYEK LETTER LAI;Lo;0;L;;;;;N;;;;; ABC3;MEETEI MAYEK LETTER MIT;Lo;0;L;;;;;N;;;;; ABC4;MEETEI MAYEK LETTER PA;Lo;0;L;;;;;N;;;;; ABC5;MEETEI MAYEK LETTER NA;Lo;0;L;;;;;N;;;;; ABC6;MEETEI MAYEK LETTER CHIL;Lo;0;L;;;;;N;;;;; ABC7;MEETEI MAYEK LETTER TIL;Lo;0;L;;;;;N;;;;; ABC8;MEETEI MAYEK LETTER KHOU;Lo;0;L;;;;;N;;;;; ABC9;MEETEI MAYEK LETTER NGOU;Lo;0;L;;;;;N;;;;; ABCA;MEETEI MAYEK LETTER THOU;Lo;0;L;;;;;N;;;;; ABCB;MEETEI MAYEK LETTER WAI;Lo;0;L;;;;;N;;;;; ABCC;MEETEI MAYEK LETTER YANG;Lo;0;L;;;;;N;;;;; ABCD;MEETEI MAYEK LETTER HUK;Lo;0;L;;;;;N;;;;; ABCE;MEETEI MAYEK LETTER UN;Lo;0;L;;;;;N;;;;; ABCF;MEETEI MAYEK LETTER I;Lo;0;L;;;;;N;;;;; ABD0;MEETEI MAYEK LETTER PHAM;Lo;0;L;;;;;N;;;;; ABD1;MEETEI MAYEK LETTER ATIYA;Lo;0;L;;;;;N;;;;; ABD2;MEETEI MAYEK LETTER GOK;Lo;0;L;;;;;N;;;;; ABD3;MEETEI MAYEK LETTER JHAM;Lo;0;L;;;;;N;;;;; ABD4;MEETEI MAYEK LETTER RAI;Lo;0;L;;;;;N;;;;; ABD5;MEETEI MAYEK LETTER BA;Lo;0;L;;;;;N;;;;; ABD6;MEETEI MAYEK LETTER JIL;Lo;0;L;;;;;N;;;;; ABD7;MEETEI MAYEK LETTER DIL;Lo;0;L;;;;;N;;;;; ABD8;MEETEI MAYEK LETTER GHOU;Lo;0;L;;;;;N;;;;; ABD9;MEETEI MAYEK LETTER DHOU;Lo;0;L;;;;;N;;;;; ABDA;MEETEI MAYEK LETTER BHAM;Lo;0;L;;;;;N;;;;; ABDB;MEETEI MAYEK LETTER KOK LONSUM;Lo;0;L;;;;;N;;;;; ABDC;MEETEI MAYEK LETTER LAI LONSUM;Lo;0;L;;;;;N;;;;; ABDD;MEETEI MAYEK LETTER MIT LONSUM;Lo;0;L;;;;;N;;;;; ABDE;MEETEI MAYEK LETTER PA LONSUM;Lo;0;L;;;;;N;;;;; ABDF;MEETEI MAYEK LETTER NA LONSUM;Lo;0;L;;;;;N;;;;; ABE0;MEETEI MAYEK LETTER TIL LONSUM;Lo;0;L;;;;;N;;;;; ABE1;MEETEI MAYEK LETTER NGOU LONSUM;Lo;0;L;;;;;N;;;;; ABE2;MEETEI MAYEK LETTER I LONSUM;Lo;0;L;;;;;N;;;;; ABE3;MEETEI MAYEK VOWEL SIGN ONAP;Mc;0;L;;;;;N;;;;; ABE4;MEETEI MAYEK VOWEL SIGN INAP;Mc;0;L;;;;;N;;;;; ABE5;MEETEI MAYEK VOWEL SIGN ANAP;Mn;0;NSM;;;;;N;;;;; ABE6;MEETEI MAYEK VOWEL SIGN YENAP;Mc;0;L;;;;;N;;;;; ABE7;MEETEI MAYEK VOWEL SIGN SOUNAP;Mc;0;L;;;;;N;;;;; ABE8;MEETEI MAYEK VOWEL SIGN UNAP;Mn;0;NSM;;;;;N;;;;; ABE9;MEETEI MAYEK VOWEL SIGN CHEINAP;Mc;0;L;;;;;N;;;;; ABEA;MEETEI MAYEK VOWEL SIGN NUNG;Mc;0;L;;;;;N;;;;; ABEB;MEETEI MAYEK CHEIKHEI;Po;0;L;;;;;N;;;;; ABEC;MEETEI MAYEK LUM IYEK;Mc;0;L;;;;;N;;;;; ABED;MEETEI MAYEK APUN IYEK;Mn;9;NSM;;;;;N;;;;; ABF0;MEETEI MAYEK DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; ABF1;MEETEI MAYEK DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; ABF2;MEETEI MAYEK DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; ABF3;MEETEI MAYEK DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; ABF4;MEETEI MAYEK DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; ABF5;MEETEI MAYEK DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; ABF6;MEETEI MAYEK DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; ABF7;MEETEI MAYEK DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; ABF8;MEETEI MAYEK DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; ABF9;MEETEI MAYEK DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; AC00;<Hangul Syllable, First>;Lo;0;L;;;;;N;;;;; D7A3;<Hangul Syllable, Last>;Lo;0;L;;;;;N;;;;; D7B0;HANGUL JUNGSEONG O-YEO;Lo;0;L;;;;;N;;;;; D7B1;HANGUL JUNGSEONG O-O-I;Lo;0;L;;;;;N;;;;; D7B2;HANGUL JUNGSEONG YO-A;Lo;0;L;;;;;N;;;;; D7B3;HANGUL JUNGSEONG YO-AE;Lo;0;L;;;;;N;;;;; D7B4;HANGUL JUNGSEONG YO-EO;Lo;0;L;;;;;N;;;;; D7B5;HANGUL JUNGSEONG U-YEO;Lo;0;L;;;;;N;;;;; D7B6;HANGUL JUNGSEONG U-I-I;Lo;0;L;;;;;N;;;;; D7B7;HANGUL JUNGSEONG YU-AE;Lo;0;L;;;;;N;;;;; D7B8;HANGUL JUNGSEONG YU-O;Lo;0;L;;;;;N;;;;; D7B9;HANGUL JUNGSEONG EU-A;Lo;0;L;;;;;N;;;;; D7BA;HANGUL JUNGSEONG EU-EO;Lo;0;L;;;;;N;;;;; D7BB;HANGUL JUNGSEONG EU-E;Lo;0;L;;;;;N;;;;; D7BC;HANGUL JUNGSEONG EU-O;Lo;0;L;;;;;N;;;;; D7BD;HANGUL JUNGSEONG I-YA-O;Lo;0;L;;;;;N;;;;; D7BE;HANGUL JUNGSEONG I-YAE;Lo;0;L;;;;;N;;;;; D7BF;HANGUL JUNGSEONG I-YEO;Lo;0;L;;;;;N;;;;; D7C0;HANGUL JUNGSEONG I-YE;Lo;0;L;;;;;N;;;;; D7C1;HANGUL JUNGSEONG I-O-I;Lo;0;L;;;;;N;;;;; D7C2;HANGUL JUNGSEONG I-YO;Lo;0;L;;;;;N;;;;; D7C3;HANGUL JUNGSEONG I-YU;Lo;0;L;;;;;N;;;;; D7C4;HANGUL JUNGSEONG I-I;Lo;0;L;;;;;N;;;;; D7C5;HANGUL JUNGSEONG ARAEA-A;Lo;0;L;;;;;N;;;;; D7C6;HANGUL JUNGSEONG ARAEA-E;Lo;0;L;;;;;N;;;;; D7CB;HANGUL JONGSEONG NIEUN-RIEUL;Lo;0;L;;;;;N;;;;; D7CC;HANGUL JONGSEONG NIEUN-CHIEUCH;Lo;0;L;;;;;N;;;;; D7CD;HANGUL JONGSEONG SSANGTIKEUT;Lo;0;L;;;;;N;;;;; D7CE;HANGUL JONGSEONG SSANGTIKEUT-PIEUP;Lo;0;L;;;;;N;;;;; D7CF;HANGUL JONGSEONG TIKEUT-PIEUP;Lo;0;L;;;;;N;;;;; D7D0;HANGUL JONGSEONG TIKEUT-SIOS;Lo;0;L;;;;;N;;;;; D7D1;HANGUL JONGSEONG TIKEUT-SIOS-KIYEOK;Lo;0;L;;;;;N;;;;; D7D2;HANGUL JONGSEONG TIKEUT-CIEUC;Lo;0;L;;;;;N;;;;; D7D3;HANGUL JONGSEONG TIKEUT-CHIEUCH;Lo;0;L;;;;;N;;;;; D7D4;HANGUL JONGSEONG TIKEUT-THIEUTH;Lo;0;L;;;;;N;;;;; D7D5;HANGUL JONGSEONG RIEUL-SSANGKIYEOK;Lo;0;L;;;;;N;;;;; D7D6;HANGUL JONGSEONG RIEUL-KIYEOK-HIEUH;Lo;0;L;;;;;N;;;;; D7D7;HANGUL JONGSEONG SSANGRIEUL-KHIEUKH;Lo;0;L;;;;;N;;;;; D7D8;HANGUL JONGSEONG RIEUL-MIEUM-HIEUH;Lo;0;L;;;;;N;;;;; D7D9;HANGUL JONGSEONG RIEUL-PIEUP-TIKEUT;Lo;0;L;;;;;N;;;;; D7DA;HANGUL JONGSEONG RIEUL-PIEUP-PHIEUPH;Lo;0;L;;;;;N;;;;; D7DB;HANGUL JONGSEONG RIEUL-YESIEUNG;Lo;0;L;;;;;N;;;;; D7DC;HANGUL JONGSEONG RIEUL-YEORINHIEUH-HIEUH;Lo;0;L;;;;;N;;;;; D7DD;HANGUL JONGSEONG KAPYEOUNRIEUL;Lo;0;L;;;;;N;;;;; D7DE;HANGUL JONGSEONG MIEUM-NIEUN;Lo;0;L;;;;;N;;;;; D7DF;HANGUL JONGSEONG MIEUM-SSANGNIEUN;Lo;0;L;;;;;N;;;;; D7E0;HANGUL JONGSEONG SSANGMIEUM;Lo;0;L;;;;;N;;;;; D7E1;HANGUL JONGSEONG MIEUM-PIEUP-SIOS;Lo;0;L;;;;;N;;;;; D7E2;HANGUL JONGSEONG MIEUM-CIEUC;Lo;0;L;;;;;N;;;;; D7E3;HANGUL JONGSEONG PIEUP-TIKEUT;Lo;0;L;;;;;N;;;;; D7E4;HANGUL JONGSEONG PIEUP-RIEUL-PHIEUPH;Lo;0;L;;;;;N;;;;; D7E5;HANGUL JONGSEONG PIEUP-MIEUM;Lo;0;L;;;;;N;;;;; D7E6;HANGUL JONGSEONG SSANGPIEUP;Lo;0;L;;;;;N;;;;; D7E7;HANGUL JONGSEONG PIEUP-SIOS-TIKEUT;Lo;0;L;;;;;N;;;;; D7E8;HANGUL JONGSEONG PIEUP-CIEUC;Lo;0;L;;;;;N;;;;; D7E9;HANGUL JONGSEONG PIEUP-CHIEUCH;Lo;0;L;;;;;N;;;;; D7EA;HANGUL JONGSEONG SIOS-MIEUM;Lo;0;L;;;;;N;;;;; D7EB;HANGUL JONGSEONG SIOS-KAPYEOUNPIEUP;Lo;0;L;;;;;N;;;;; D7EC;HANGUL JONGSEONG SSANGSIOS-KIYEOK;Lo;0;L;;;;;N;;;;; D7ED;HANGUL JONGSEONG SSANGSIOS-TIKEUT;Lo;0;L;;;;;N;;;;; D7EE;HANGUL JONGSEONG SIOS-PANSIOS;Lo;0;L;;;;;N;;;;; D7EF;HANGUL JONGSEONG SIOS-CIEUC;Lo;0;L;;;;;N;;;;; D7F0;HANGUL JONGSEONG SIOS-CHIEUCH;Lo;0;L;;;;;N;;;;; D7F1;HANGUL JONGSEONG SIOS-THIEUTH;Lo;0;L;;;;;N;;;;; D7F2;HANGUL JONGSEONG SIOS-HIEUH;Lo;0;L;;;;;N;;;;; D7F3;HANGUL JONGSEONG PANSIOS-PIEUP;Lo;0;L;;;;;N;;;;; D7F4;HANGUL JONGSEONG PANSIOS-KAPYEOUNPIEUP;Lo;0;L;;;;;N;;;;; D7F5;HANGUL JONGSEONG YESIEUNG-MIEUM;Lo;0;L;;;;;N;;;;; D7F6;HANGUL JONGSEONG YESIEUNG-HIEUH;Lo;0;L;;;;;N;;;;; D7F7;HANGUL JONGSEONG CIEUC-PIEUP;Lo;0;L;;;;;N;;;;; D7F8;HANGUL JONGSEONG CIEUC-SSANGPIEUP;Lo;0;L;;;;;N;;;;; D7F9;HANGUL JONGSEONG SSANGCIEUC;Lo;0;L;;;;;N;;;;; D7FA;HANGUL JONGSEONG PHIEUPH-SIOS;Lo;0;L;;;;;N;;;;; D7FB;HANGUL JONGSEONG PHIEUPH-THIEUTH;Lo;0;L;;;;;N;;;;; D800;<Non Private Use High Surrogate, First>;Cs;0;L;;;;;N;;;;; DB7F;<Non Private Use High Surrogate, Last>;Cs;0;L;;;;;N;;;;; DB80;<Private Use High Surrogate, First>;Cs;0;L;;;;;N;;;;; DBFF;<Private Use High Surrogate, Last>;Cs;0;L;;;;;N;;;;; DC00;<Low Surrogate, First>;Cs;0;L;;;;;N;;;;; DFFF;<Low Surrogate, Last>;Cs;0;L;;;;;N;;;;; E000;<Private Use, First>;Co;0;L;;;;;N;;;;; F8FF;<Private Use, Last>;Co;0;L;;;;;N;;;;; F900;CJK COMPATIBILITY IDEOGRAPH-F900;Lo;0;L;8C48;;;;N;;;;; F901;CJK COMPATIBILITY IDEOGRAPH-F901;Lo;0;L;66F4;;;;N;;;;; F902;CJK COMPATIBILITY IDEOGRAPH-F902;Lo;0;L;8ECA;;;;N;;;;; F903;CJK COMPATIBILITY IDEOGRAPH-F903;Lo;0;L;8CC8;;;;N;;;;; F904;CJK COMPATIBILITY IDEOGRAPH-F904;Lo;0;L;6ED1;;;;N;;;;; F905;CJK COMPATIBILITY IDEOGRAPH-F905;Lo;0;L;4E32;;;;N;;;;; F906;CJK COMPATIBILITY IDEOGRAPH-F906;Lo;0;L;53E5;;;;N;;;;; F907;CJK COMPATIBILITY IDEOGRAPH-F907;Lo;0;L;9F9C;;;;N;;;;; F908;CJK COMPATIBILITY IDEOGRAPH-F908;Lo;0;L;9F9C;;;;N;;;;; F909;CJK COMPATIBILITY IDEOGRAPH-F909;Lo;0;L;5951;;;;N;;;;; F90A;CJK COMPATIBILITY IDEOGRAPH-F90A;Lo;0;L;91D1;;;;N;;;;; F90B;CJK COMPATIBILITY IDEOGRAPH-F90B;Lo;0;L;5587;;;;N;;;;; F90C;CJK COMPATIBILITY IDEOGRAPH-F90C;Lo;0;L;5948;;;;N;;;;; F90D;CJK COMPATIBILITY IDEOGRAPH-F90D;Lo;0;L;61F6;;;;N;;;;; F90E;CJK COMPATIBILITY IDEOGRAPH-F90E;Lo;0;L;7669;;;;N;;;;; F90F;CJK COMPATIBILITY IDEOGRAPH-F90F;Lo;0;L;7F85;;;;N;;;;; F910;CJK COMPATIBILITY IDEOGRAPH-F910;Lo;0;L;863F;;;;N;;;;; F911;CJK COMPATIBILITY IDEOGRAPH-F911;Lo;0;L;87BA;;;;N;;;;; F912;CJK COMPATIBILITY IDEOGRAPH-F912;Lo;0;L;88F8;;;;N;;;;; F913;CJK COMPATIBILITY IDEOGRAPH-F913;Lo;0;L;908F;;;;N;;;;; F914;CJK COMPATIBILITY IDEOGRAPH-F914;Lo;0;L;6A02;;;;N;;;;; F915;CJK COMPATIBILITY IDEOGRAPH-F915;Lo;0;L;6D1B;;;;N;;;;; F916;CJK COMPATIBILITY IDEOGRAPH-F916;Lo;0;L;70D9;;;;N;;;;; F917;CJK COMPATIBILITY IDEOGRAPH-F917;Lo;0;L;73DE;;;;N;;;;; F918;CJK COMPATIBILITY IDEOGRAPH-F918;Lo;0;L;843D;;;;N;;;;; F919;CJK COMPATIBILITY IDEOGRAPH-F919;Lo;0;L;916A;;;;N;;;;; F91A;CJK COMPATIBILITY IDEOGRAPH-F91A;Lo;0;L;99F1;;;;N;;;;; F91B;CJK COMPATIBILITY IDEOGRAPH-F91B;Lo;0;L;4E82;;;;N;;;;; F91C;CJK COMPATIBILITY IDEOGRAPH-F91C;Lo;0;L;5375;;;;N;;;;; F91D;CJK COMPATIBILITY IDEOGRAPH-F91D;Lo;0;L;6B04;;;;N;;;;; F91E;CJK COMPATIBILITY IDEOGRAPH-F91E;Lo;0;L;721B;;;;N;;;;; F91F;CJK COMPATIBILITY IDEOGRAPH-F91F;Lo;0;L;862D;;;;N;;;;; F920;CJK COMPATIBILITY IDEOGRAPH-F920;Lo;0;L;9E1E;;;;N;;;;; F921;CJK COMPATIBILITY IDEOGRAPH-F921;Lo;0;L;5D50;;;;N;;;;; F922;CJK COMPATIBILITY IDEOGRAPH-F922;Lo;0;L;6FEB;;;;N;;;;; F923;CJK COMPATIBILITY IDEOGRAPH-F923;Lo;0;L;85CD;;;;N;;;;; F924;CJK COMPATIBILITY IDEOGRAPH-F924;Lo;0;L;8964;;;;N;;;;; F925;CJK COMPATIBILITY IDEOGRAPH-F925;Lo;0;L;62C9;;;;N;;;;; F926;CJK COMPATIBILITY IDEOGRAPH-F926;Lo;0;L;81D8;;;;N;;;;; F927;CJK COMPATIBILITY IDEOGRAPH-F927;Lo;0;L;881F;;;;N;;;;; F928;CJK COMPATIBILITY IDEOGRAPH-F928;Lo;0;L;5ECA;;;;N;;;;; F929;CJK COMPATIBILITY IDEOGRAPH-F929;Lo;0;L;6717;;;;N;;;;; F92A;CJK COMPATIBILITY IDEOGRAPH-F92A;Lo;0;L;6D6A;;;;N;;;;; F92B;CJK COMPATIBILITY IDEOGRAPH-F92B;Lo;0;L;72FC;;;;N;;;;; F92C;CJK COMPATIBILITY IDEOGRAPH-F92C;Lo;0;L;90CE;;;;N;;;;; F92D;CJK COMPATIBILITY IDEOGRAPH-F92D;Lo;0;L;4F86;;;;N;;;;; F92E;CJK COMPATIBILITY IDEOGRAPH-F92E;Lo;0;L;51B7;;;;N;;;;; F92F;CJK COMPATIBILITY IDEOGRAPH-F92F;Lo;0;L;52DE;;;;N;;;;; F930;CJK COMPATIBILITY IDEOGRAPH-F930;Lo;0;L;64C4;;;;N;;;;; F931;CJK COMPATIBILITY IDEOGRAPH-F931;Lo;0;L;6AD3;;;;N;;;;; F932;CJK COMPATIBILITY IDEOGRAPH-F932;Lo;0;L;7210;;;;N;;;;; F933;CJK COMPATIBILITY IDEOGRAPH-F933;Lo;0;L;76E7;;;;N;;;;; F934;CJK COMPATIBILITY IDEOGRAPH-F934;Lo;0;L;8001;;;;N;;;;; F935;CJK COMPATIBILITY IDEOGRAPH-F935;Lo;0;L;8606;;;;N;;;;; F936;CJK COMPATIBILITY IDEOGRAPH-F936;Lo;0;L;865C;;;;N;;;;; F937;CJK COMPATIBILITY IDEOGRAPH-F937;Lo;0;L;8DEF;;;;N;;;;; F938;CJK COMPATIBILITY IDEOGRAPH-F938;Lo;0;L;9732;;;;N;;;;; F939;CJK COMPATIBILITY IDEOGRAPH-F939;Lo;0;L;9B6F;;;;N;;;;; F93A;CJK COMPATIBILITY IDEOGRAPH-F93A;Lo;0;L;9DFA;;;;N;;;;; F93B;CJK COMPATIBILITY IDEOGRAPH-F93B;Lo;0;L;788C;;;;N;;;;; F93C;CJK COMPATIBILITY IDEOGRAPH-F93C;Lo;0;L;797F;;;;N;;;;; F93D;CJK COMPATIBILITY IDEOGRAPH-F93D;Lo;0;L;7DA0;;;;N;;;;; F93E;CJK COMPATIBILITY IDEOGRAPH-F93E;Lo;0;L;83C9;;;;N;;;;; F93F;CJK COMPATIBILITY IDEOGRAPH-F93F;Lo;0;L;9304;;;;N;;;;; F940;CJK COMPATIBILITY IDEOGRAPH-F940;Lo;0;L;9E7F;;;;N;;;;; F941;CJK COMPATIBILITY IDEOGRAPH-F941;Lo;0;L;8AD6;;;;N;;;;; F942;CJK COMPATIBILITY IDEOGRAPH-F942;Lo;0;L;58DF;;;;N;;;;; F943;CJK COMPATIBILITY IDEOGRAPH-F943;Lo;0;L;5F04;;;;N;;;;; F944;CJK COMPATIBILITY IDEOGRAPH-F944;Lo;0;L;7C60;;;;N;;;;; F945;CJK COMPATIBILITY IDEOGRAPH-F945;Lo;0;L;807E;;;;N;;;;; F946;CJK COMPATIBILITY IDEOGRAPH-F946;Lo;0;L;7262;;;;N;;;;; F947;CJK COMPATIBILITY IDEOGRAPH-F947;Lo;0;L;78CA;;;;N;;;;; F948;CJK COMPATIBILITY IDEOGRAPH-F948;Lo;0;L;8CC2;;;;N;;;;; F949;CJK COMPATIBILITY IDEOGRAPH-F949;Lo;0;L;96F7;;;;N;;;;; F94A;CJK COMPATIBILITY IDEOGRAPH-F94A;Lo;0;L;58D8;;;;N;;;;; F94B;CJK COMPATIBILITY IDEOGRAPH-F94B;Lo;0;L;5C62;;;;N;;;;; F94C;CJK COMPATIBILITY IDEOGRAPH-F94C;Lo;0;L;6A13;;;;N;;;;; F94D;CJK COMPATIBILITY IDEOGRAPH-F94D;Lo;0;L;6DDA;;;;N;;;;; F94E;CJK COMPATIBILITY IDEOGRAPH-F94E;Lo;0;L;6F0F;;;;N;;;;; F94F;CJK COMPATIBILITY IDEOGRAPH-F94F;Lo;0;L;7D2F;;;;N;;;;; F950;CJK COMPATIBILITY IDEOGRAPH-F950;Lo;0;L;7E37;;;;N;;;;; F951;CJK COMPATIBILITY IDEOGRAPH-F951;Lo;0;L;964B;;;;N;;;;; F952;CJK COMPATIBILITY IDEOGRAPH-F952;Lo;0;L;52D2;;;;N;;;;; F953;CJK COMPATIBILITY IDEOGRAPH-F953;Lo;0;L;808B;;;;N;;;;; F954;CJK COMPATIBILITY IDEOGRAPH-F954;Lo;0;L;51DC;;;;N;;;;; F955;CJK COMPATIBILITY IDEOGRAPH-F955;Lo;0;L;51CC;;;;N;;;;; F956;CJK COMPATIBILITY IDEOGRAPH-F956;Lo;0;L;7A1C;;;;N;;;;; F957;CJK COMPATIBILITY IDEOGRAPH-F957;Lo;0;L;7DBE;;;;N;;;;; F958;CJK COMPATIBILITY IDEOGRAPH-F958;Lo;0;L;83F1;;;;N;;;;; F959;CJK COMPATIBILITY IDEOGRAPH-F959;Lo;0;L;9675;;;;N;;;;; F95A;CJK COMPATIBILITY IDEOGRAPH-F95A;Lo;0;L;8B80;;;;N;;;;; F95B;CJK COMPATIBILITY IDEOGRAPH-F95B;Lo;0;L;62CF;;;;N;;;;; F95C;CJK COMPATIBILITY IDEOGRAPH-F95C;Lo;0;L;6A02;;;;N;;;;; F95D;CJK COMPATIBILITY IDEOGRAPH-F95D;Lo;0;L;8AFE;;;;N;;;;; F95E;CJK COMPATIBILITY IDEOGRAPH-F95E;Lo;0;L;4E39;;;;N;;;;; F95F;CJK COMPATIBILITY IDEOGRAPH-F95F;Lo;0;L;5BE7;;;;N;;;;; F960;CJK COMPATIBILITY IDEOGRAPH-F960;Lo;0;L;6012;;;;N;;;;; F961;CJK COMPATIBILITY IDEOGRAPH-F961;Lo;0;L;7387;;;;N;;;;; F962;CJK COMPATIBILITY IDEOGRAPH-F962;Lo;0;L;7570;;;;N;;;;; F963;CJK COMPATIBILITY IDEOGRAPH-F963;Lo;0;L;5317;;;;N;;;;; F964;CJK COMPATIBILITY IDEOGRAPH-F964;Lo;0;L;78FB;;;;N;;;;; F965;CJK COMPATIBILITY IDEOGRAPH-F965;Lo;0;L;4FBF;;;;N;;;;; F966;CJK COMPATIBILITY IDEOGRAPH-F966;Lo;0;L;5FA9;;;;N;;;;; F967;CJK COMPATIBILITY IDEOGRAPH-F967;Lo;0;L;4E0D;;;;N;;;;; F968;CJK COMPATIBILITY IDEOGRAPH-F968;Lo;0;L;6CCC;;;;N;;;;; F969;CJK COMPATIBILITY IDEOGRAPH-F969;Lo;0;L;6578;;;;N;;;;; F96A;CJK COMPATIBILITY IDEOGRAPH-F96A;Lo;0;L;7D22;;;;N;;;;; F96B;CJK COMPATIBILITY IDEOGRAPH-F96B;Lo;0;L;53C3;;;3;N;;;;; F96C;CJK COMPATIBILITY IDEOGRAPH-F96C;Lo;0;L;585E;;;;N;;;;; F96D;CJK COMPATIBILITY IDEOGRAPH-F96D;Lo;0;L;7701;;;;N;;;;; F96E;CJK COMPATIBILITY IDEOGRAPH-F96E;Lo;0;L;8449;;;;N;;;;; F96F;CJK COMPATIBILITY IDEOGRAPH-F96F;Lo;0;L;8AAA;;;;N;;;;; F970;CJK COMPATIBILITY IDEOGRAPH-F970;Lo;0;L;6BBA;;;;N;;;;; F971;CJK COMPATIBILITY IDEOGRAPH-F971;Lo;0;L;8FB0;;;;N;;;;; F972;CJK COMPATIBILITY IDEOGRAPH-F972;Lo;0;L;6C88;;;;N;;;;; F973;CJK COMPATIBILITY IDEOGRAPH-F973;Lo;0;L;62FE;;;10;N;;;;; F974;CJK COMPATIBILITY IDEOGRAPH-F974;Lo;0;L;82E5;;;;N;;;;; F975;CJK COMPATIBILITY IDEOGRAPH-F975;Lo;0;L;63A0;;;;N;;;;; F976;CJK COMPATIBILITY IDEOGRAPH-F976;Lo;0;L;7565;;;;N;;;;; F977;CJK COMPATIBILITY IDEOGRAPH-F977;Lo;0;L;4EAE;;;;N;;;;; F978;CJK COMPATIBILITY IDEOGRAPH-F978;Lo;0;L;5169;;;2;N;;;;; F979;CJK COMPATIBILITY IDEOGRAPH-F979;Lo;0;L;51C9;;;;N;;;;; F97A;CJK COMPATIBILITY IDEOGRAPH-F97A;Lo;0;L;6881;;;;N;;;;; F97B;CJK COMPATIBILITY IDEOGRAPH-F97B;Lo;0;L;7CE7;;;;N;;;;; F97C;CJK COMPATIBILITY IDEOGRAPH-F97C;Lo;0;L;826F;;;;N;;;;; F97D;CJK COMPATIBILITY IDEOGRAPH-F97D;Lo;0;L;8AD2;;;;N;;;;; F97E;CJK COMPATIBILITY IDEOGRAPH-F97E;Lo;0;L;91CF;;;;N;;;;; F97F;CJK COMPATIBILITY IDEOGRAPH-F97F;Lo;0;L;52F5;;;;N;;;;; F980;CJK COMPATIBILITY IDEOGRAPH-F980;Lo;0;L;5442;;;;N;;;;; F981;CJK COMPATIBILITY IDEOGRAPH-F981;Lo;0;L;5973;;;;N;;;;; F982;CJK COMPATIBILITY IDEOGRAPH-F982;Lo;0;L;5EEC;;;;N;;;;; F983;CJK COMPATIBILITY IDEOGRAPH-F983;Lo;0;L;65C5;;;;N;;;;; F984;CJK COMPATIBILITY IDEOGRAPH-F984;Lo;0;L;6FFE;;;;N;;;;; F985;CJK COMPATIBILITY IDEOGRAPH-F985;Lo;0;L;792A;;;;N;;;;; F986;CJK COMPATIBILITY IDEOGRAPH-F986;Lo;0;L;95AD;;;;N;;;;; F987;CJK COMPATIBILITY IDEOGRAPH-F987;Lo;0;L;9A6A;;;;N;;;;; F988;CJK COMPATIBILITY IDEOGRAPH-F988;Lo;0;L;9E97;;;;N;;;;; F989;CJK COMPATIBILITY IDEOGRAPH-F989;Lo;0;L;9ECE;;;;N;;;;; F98A;CJK COMPATIBILITY IDEOGRAPH-F98A;Lo;0;L;529B;;;;N;;;;; F98B;CJK COMPATIBILITY IDEOGRAPH-F98B;Lo;0;L;66C6;;;;N;;;;; F98C;CJK COMPATIBILITY IDEOGRAPH-F98C;Lo;0;L;6B77;;;;N;;;;; F98D;CJK COMPATIBILITY IDEOGRAPH-F98D;Lo;0;L;8F62;;;;N;;;;; F98E;CJK COMPATIBILITY IDEOGRAPH-F98E;Lo;0;L;5E74;;;;N;;;;; F98F;CJK COMPATIBILITY IDEOGRAPH-F98F;Lo;0;L;6190;;;;N;;;;; F990;CJK COMPATIBILITY IDEOGRAPH-F990;Lo;0;L;6200;;;;N;;;;; F991;CJK COMPATIBILITY IDEOGRAPH-F991;Lo;0;L;649A;;;;N;;;;; F992;CJK COMPATIBILITY IDEOGRAPH-F992;Lo;0;L;6F23;;;;N;;;;; F993;CJK COMPATIBILITY IDEOGRAPH-F993;Lo;0;L;7149;;;;N;;;;; F994;CJK COMPATIBILITY IDEOGRAPH-F994;Lo;0;L;7489;;;;N;;;;; F995;CJK COMPATIBILITY IDEOGRAPH-F995;Lo;0;L;79CA;;;;N;;;;; F996;CJK COMPATIBILITY IDEOGRAPH-F996;Lo;0;L;7DF4;;;;N;;;;; F997;CJK COMPATIBILITY IDEOGRAPH-F997;Lo;0;L;806F;;;;N;;;;; F998;CJK COMPATIBILITY IDEOGRAPH-F998;Lo;0;L;8F26;;;;N;;;;; F999;CJK COMPATIBILITY IDEOGRAPH-F999;Lo;0;L;84EE;;;;N;;;;; F99A;CJK COMPATIBILITY IDEOGRAPH-F99A;Lo;0;L;9023;;;;N;;;;; F99B;CJK COMPATIBILITY IDEOGRAPH-F99B;Lo;0;L;934A;;;;N;;;;; F99C;CJK COMPATIBILITY IDEOGRAPH-F99C;Lo;0;L;5217;;;;N;;;;; F99D;CJK COMPATIBILITY IDEOGRAPH-F99D;Lo;0;L;52A3;;;;N;;;;; F99E;CJK COMPATIBILITY IDEOGRAPH-F99E;Lo;0;L;54BD;;;;N;;;;; F99F;CJK COMPATIBILITY IDEOGRAPH-F99F;Lo;0;L;70C8;;;;N;;;;; F9A0;CJK COMPATIBILITY IDEOGRAPH-F9A0;Lo;0;L;88C2;;;;N;;;;; F9A1;CJK COMPATIBILITY IDEOGRAPH-F9A1;Lo;0;L;8AAA;;;;N;;;;; F9A2;CJK COMPATIBILITY IDEOGRAPH-F9A2;Lo;0;L;5EC9;;;;N;;;;; F9A3;CJK COMPATIBILITY IDEOGRAPH-F9A3;Lo;0;L;5FF5;;;;N;;;;; F9A4;CJK COMPATIBILITY IDEOGRAPH-F9A4;Lo;0;L;637B;;;;N;;;;; F9A5;CJK COMPATIBILITY IDEOGRAPH-F9A5;Lo;0;L;6BAE;;;;N;;;;; F9A6;CJK COMPATIBILITY IDEOGRAPH-F9A6;Lo;0;L;7C3E;;;;N;;;;; F9A7;CJK COMPATIBILITY IDEOGRAPH-F9A7;Lo;0;L;7375;;;;N;;;;; F9A8;CJK COMPATIBILITY IDEOGRAPH-F9A8;Lo;0;L;4EE4;;;;N;;;;; F9A9;CJK COMPATIBILITY IDEOGRAPH-F9A9;Lo;0;L;56F9;;;;N;;;;; F9AA;CJK COMPATIBILITY IDEOGRAPH-F9AA;Lo;0;L;5BE7;;;;N;;;;; F9AB;CJK COMPATIBILITY IDEOGRAPH-F9AB;Lo;0;L;5DBA;;;;N;;;;; F9AC;CJK COMPATIBILITY IDEOGRAPH-F9AC;Lo;0;L;601C;;;;N;;;;; F9AD;CJK COMPATIBILITY IDEOGRAPH-F9AD;Lo;0;L;73B2;;;;N;;;;; F9AE;CJK COMPATIBILITY IDEOGRAPH-F9AE;Lo;0;L;7469;;;;N;;;;; F9AF;CJK COMPATIBILITY IDEOGRAPH-F9AF;Lo;0;L;7F9A;;;;N;;;;; F9B0;CJK COMPATIBILITY IDEOGRAPH-F9B0;Lo;0;L;8046;;;;N;;;;; F9B1;CJK COMPATIBILITY IDEOGRAPH-F9B1;Lo;0;L;9234;;;;N;;;;; F9B2;CJK COMPATIBILITY IDEOGRAPH-F9B2;Lo;0;L;96F6;;;0;N;;;;; F9B3;CJK COMPATIBILITY IDEOGRAPH-F9B3;Lo;0;L;9748;;;;N;;;;; F9B4;CJK COMPATIBILITY IDEOGRAPH-F9B4;Lo;0;L;9818;;;;N;;;;; F9B5;CJK COMPATIBILITY IDEOGRAPH-F9B5;Lo;0;L;4F8B;;;;N;;;;; F9B6;CJK COMPATIBILITY IDEOGRAPH-F9B6;Lo;0;L;79AE;;;;N;;;;; F9B7;CJK COMPATIBILITY IDEOGRAPH-F9B7;Lo;0;L;91B4;;;;N;;;;; F9B8;CJK COMPATIBILITY IDEOGRAPH-F9B8;Lo;0;L;96B8;;;;N;;;;; F9B9;CJK COMPATIBILITY IDEOGRAPH-F9B9;Lo;0;L;60E1;;;;N;;;;; F9BA;CJK COMPATIBILITY IDEOGRAPH-F9BA;Lo;0;L;4E86;;;;N;;;;; F9BB;CJK COMPATIBILITY IDEOGRAPH-F9BB;Lo;0;L;50DA;;;;N;;;;; F9BC;CJK COMPATIBILITY IDEOGRAPH-F9BC;Lo;0;L;5BEE;;;;N;;;;; F9BD;CJK COMPATIBILITY IDEOGRAPH-F9BD;Lo;0;L;5C3F;;;;N;;;;; F9BE;CJK COMPATIBILITY IDEOGRAPH-F9BE;Lo;0;L;6599;;;;N;;;;; F9BF;CJK COMPATIBILITY IDEOGRAPH-F9BF;Lo;0;L;6A02;;;;N;;;;; F9C0;CJK COMPATIBILITY IDEOGRAPH-F9C0;Lo;0;L;71CE;;;;N;;;;; F9C1;CJK COMPATIBILITY IDEOGRAPH-F9C1;Lo;0;L;7642;;;;N;;;;; F9C2;CJK COMPATIBILITY IDEOGRAPH-F9C2;Lo;0;L;84FC;;;;N;;;;; F9C3;CJK COMPATIBILITY IDEOGRAPH-F9C3;Lo;0;L;907C;;;;N;;;;; F9C4;CJK COMPATIBILITY IDEOGRAPH-F9C4;Lo;0;L;9F8D;;;;N;;;;; F9C5;CJK COMPATIBILITY IDEOGRAPH-F9C5;Lo;0;L;6688;;;;N;;;;; F9C6;CJK COMPATIBILITY IDEOGRAPH-F9C6;Lo;0;L;962E;;;;N;;;;; F9C7;CJK COMPATIBILITY IDEOGRAPH-F9C7;Lo;0;L;5289;;;;N;;;;; F9C8;CJK COMPATIBILITY IDEOGRAPH-F9C8;Lo;0;L;677B;;;;N;;;;; F9C9;CJK COMPATIBILITY IDEOGRAPH-F9C9;Lo;0;L;67F3;;;;N;;;;; F9CA;CJK COMPATIBILITY IDEOGRAPH-F9CA;Lo;0;L;6D41;;;;N;;;;; F9CB;CJK COMPATIBILITY IDEOGRAPH-F9CB;Lo;0;L;6E9C;;;;N;;;;; F9CC;CJK COMPATIBILITY IDEOGRAPH-F9CC;Lo;0;L;7409;;;;N;;;;; F9CD;CJK COMPATIBILITY IDEOGRAPH-F9CD;Lo;0;L;7559;;;;N;;;;; F9CE;CJK COMPATIBILITY IDEOGRAPH-F9CE;Lo;0;L;786B;;;;N;;;;; F9CF;CJK COMPATIBILITY IDEOGRAPH-F9CF;Lo;0;L;7D10;;;;N;;;;; F9D0;CJK COMPATIBILITY IDEOGRAPH-F9D0;Lo;0;L;985E;;;;N;;;;; F9D1;CJK COMPATIBILITY IDEOGRAPH-F9D1;Lo;0;L;516D;;;6;N;;;;; F9D2;CJK COMPATIBILITY IDEOGRAPH-F9D2;Lo;0;L;622E;;;;N;;;;; F9D3;CJK COMPATIBILITY IDEOGRAPH-F9D3;Lo;0;L;9678;;;6;N;;;;; F9D4;CJK COMPATIBILITY IDEOGRAPH-F9D4;Lo;0;L;502B;;;;N;;;;; F9D5;CJK COMPATIBILITY IDEOGRAPH-F9D5;Lo;0;L;5D19;;;;N;;;;; F9D6;CJK COMPATIBILITY IDEOGRAPH-F9D6;Lo;0;L;6DEA;;;;N;;;;; F9D7;CJK COMPATIBILITY IDEOGRAPH-F9D7;Lo;0;L;8F2A;;;;N;;;;; F9D8;CJK COMPATIBILITY IDEOGRAPH-F9D8;Lo;0;L;5F8B;;;;N;;;;; F9D9;CJK COMPATIBILITY IDEOGRAPH-F9D9;Lo;0;L;6144;;;;N;;;;; F9DA;CJK COMPATIBILITY IDEOGRAPH-F9DA;Lo;0;L;6817;;;;N;;;;; F9DB;CJK COMPATIBILITY IDEOGRAPH-F9DB;Lo;0;L;7387;;;;N;;;;; F9DC;CJK COMPATIBILITY IDEOGRAPH-F9DC;Lo;0;L;9686;;;;N;;;;; F9DD;CJK COMPATIBILITY IDEOGRAPH-F9DD;Lo;0;L;5229;;;;N;;;;; F9DE;CJK COMPATIBILITY IDEOGRAPH-F9DE;Lo;0;L;540F;;;;N;;;;; F9DF;CJK COMPATIBILITY IDEOGRAPH-F9DF;Lo;0;L;5C65;;;;N;;;;; F9E0;CJK COMPATIBILITY IDEOGRAPH-F9E0;Lo;0;L;6613;;;;N;;;;; F9E1;CJK COMPATIBILITY IDEOGRAPH-F9E1;Lo;0;L;674E;;;;N;;;;; F9E2;CJK COMPATIBILITY IDEOGRAPH-F9E2;Lo;0;L;68A8;;;;N;;;;; F9E3;CJK COMPATIBILITY IDEOGRAPH-F9E3;Lo;0;L;6CE5;;;;N;;;;; F9E4;CJK COMPATIBILITY IDEOGRAPH-F9E4;Lo;0;L;7406;;;;N;;;;; F9E5;CJK COMPATIBILITY IDEOGRAPH-F9E5;Lo;0;L;75E2;;;;N;;;;; F9E6;CJK COMPATIBILITY IDEOGRAPH-F9E6;Lo;0;L;7F79;;;;N;;;;; F9E7;CJK COMPATIBILITY IDEOGRAPH-F9E7;Lo;0;L;88CF;;;;N;;;;; F9E8;CJK COMPATIBILITY IDEOGRAPH-F9E8;Lo;0;L;88E1;;;;N;;;;; F9E9;CJK COMPATIBILITY IDEOGRAPH-F9E9;Lo;0;L;91CC;;;;N;;;;; F9EA;CJK COMPATIBILITY IDEOGRAPH-F9EA;Lo;0;L;96E2;;;;N;;;;; F9EB;CJK COMPATIBILITY IDEOGRAPH-F9EB;Lo;0;L;533F;;;;N;;;;; F9EC;CJK COMPATIBILITY IDEOGRAPH-F9EC;Lo;0;L;6EBA;;;;N;;;;; F9ED;CJK COMPATIBILITY IDEOGRAPH-F9ED;Lo;0;L;541D;;;;N;;;;; F9EE;CJK COMPATIBILITY IDEOGRAPH-F9EE;Lo;0;L;71D0;;;;N;;;;; F9EF;CJK COMPATIBILITY IDEOGRAPH-F9EF;Lo;0;L;7498;;;;N;;;;; F9F0;CJK COMPATIBILITY IDEOGRAPH-F9F0;Lo;0;L;85FA;;;;N;;;;; F9F1;CJK COMPATIBILITY IDEOGRAPH-F9F1;Lo;0;L;96A3;;;;N;;;;; F9F2;CJK COMPATIBILITY IDEOGRAPH-F9F2;Lo;0;L;9C57;;;;N;;;;; F9F3;CJK COMPATIBILITY IDEOGRAPH-F9F3;Lo;0;L;9E9F;;;;N;;;;; F9F4;CJK COMPATIBILITY IDEOGRAPH-F9F4;Lo;0;L;6797;;;;N;;;;; F9F5;CJK COMPATIBILITY IDEOGRAPH-F9F5;Lo;0;L;6DCB;;;;N;;;;; F9F6;CJK COMPATIBILITY IDEOGRAPH-F9F6;Lo;0;L;81E8;;;;N;;;;; F9F7;CJK COMPATIBILITY IDEOGRAPH-F9F7;Lo;0;L;7ACB;;;;N;;;;; F9F8;CJK COMPATIBILITY IDEOGRAPH-F9F8;Lo;0;L;7B20;;;;N;;;;; F9F9;CJK COMPATIBILITY IDEOGRAPH-F9F9;Lo;0;L;7C92;;;;N;;;;; F9FA;CJK COMPATIBILITY IDEOGRAPH-F9FA;Lo;0;L;72C0;;;;N;;;;; F9FB;CJK COMPATIBILITY IDEOGRAPH-F9FB;Lo;0;L;7099;;;;N;;;;; F9FC;CJK COMPATIBILITY IDEOGRAPH-F9FC;Lo;0;L;8B58;;;;N;;;;; F9FD;CJK COMPATIBILITY IDEOGRAPH-F9FD;Lo;0;L;4EC0;;;10;N;;;;; F9FE;CJK COMPATIBILITY IDEOGRAPH-F9FE;Lo;0;L;8336;;;;N;;;;; F9FF;CJK COMPATIBILITY IDEOGRAPH-F9FF;Lo;0;L;523A;;;;N;;;;; FA00;CJK COMPATIBILITY IDEOGRAPH-FA00;Lo;0;L;5207;;;;N;;;;; FA01;CJK COMPATIBILITY IDEOGRAPH-FA01;Lo;0;L;5EA6;;;;N;;;;; FA02;CJK COMPATIBILITY IDEOGRAPH-FA02;Lo;0;L;62D3;;;;N;;;;; FA03;CJK COMPATIBILITY IDEOGRAPH-FA03;Lo;0;L;7CD6;;;;N;;;;; FA04;CJK COMPATIBILITY IDEOGRAPH-FA04;Lo;0;L;5B85;;;;N;;;;; FA05;CJK COMPATIBILITY IDEOGRAPH-FA05;Lo;0;L;6D1E;;;;N;;;;; FA06;CJK COMPATIBILITY IDEOGRAPH-FA06;Lo;0;L;66B4;;;;N;;;;; FA07;CJK COMPATIBILITY IDEOGRAPH-FA07;Lo;0;L;8F3B;;;;N;;;;; FA08;CJK COMPATIBILITY IDEOGRAPH-FA08;Lo;0;L;884C;;;;N;;;;; FA09;CJK COMPATIBILITY IDEOGRAPH-FA09;Lo;0;L;964D;;;;N;;;;; FA0A;CJK COMPATIBILITY IDEOGRAPH-FA0A;Lo;0;L;898B;;;;N;;;;; FA0B;CJK COMPATIBILITY IDEOGRAPH-FA0B;Lo;0;L;5ED3;;;;N;;;;; FA0C;CJK COMPATIBILITY IDEOGRAPH-FA0C;Lo;0;L;5140;;;;N;;;;; FA0D;CJK COMPATIBILITY IDEOGRAPH-FA0D;Lo;0;L;55C0;;;;N;;;;; FA0E;CJK COMPATIBILITY IDEOGRAPH-FA0E;Lo;0;L;;;;;N;;;;; FA0F;CJK COMPATIBILITY IDEOGRAPH-FA0F;Lo;0;L;;;;;N;;;;; FA10;CJK COMPATIBILITY IDEOGRAPH-FA10;Lo;0;L;585A;;;;N;;;;; FA11;CJK COMPATIBILITY IDEOGRAPH-FA11;Lo;0;L;;;;;N;;;;; FA12;CJK COMPATIBILITY IDEOGRAPH-FA12;Lo;0;L;6674;;;;N;;;;; FA13;CJK COMPATIBILITY IDEOGRAPH-FA13;Lo;0;L;;;;;N;;;;; FA14;CJK COMPATIBILITY IDEOGRAPH-FA14;Lo;0;L;;;;;N;;;;; FA15;CJK COMPATIBILITY IDEOGRAPH-FA15;Lo;0;L;51DE;;;;N;;;;; FA16;CJK COMPATIBILITY IDEOGRAPH-FA16;Lo;0;L;732A;;;;N;;;;; FA17;CJK COMPATIBILITY IDEOGRAPH-FA17;Lo;0;L;76CA;;;;N;;;;; FA18;CJK COMPATIBILITY IDEOGRAPH-FA18;Lo;0;L;793C;;;;N;;;;; FA19;CJK COMPATIBILITY IDEOGRAPH-FA19;Lo;0;L;795E;;;;N;;;;; FA1A;CJK COMPATIBILITY IDEOGRAPH-FA1A;Lo;0;L;7965;;;;N;;;;; FA1B;CJK COMPATIBILITY IDEOGRAPH-FA1B;Lo;0;L;798F;;;;N;;;;; FA1C;CJK COMPATIBILITY IDEOGRAPH-FA1C;Lo;0;L;9756;;;;N;;;;; FA1D;CJK COMPATIBILITY IDEOGRAPH-FA1D;Lo;0;L;7CBE;;;;N;;;;; FA1E;CJK COMPATIBILITY IDEOGRAPH-FA1E;Lo;0;L;7FBD;;;;N;;;;; FA1F;CJK COMPATIBILITY IDEOGRAPH-FA1F;Lo;0;L;;;;;N;;;;; FA20;CJK COMPATIBILITY IDEOGRAPH-FA20;Lo;0;L;8612;;;;N;;;;; FA21;CJK COMPATIBILITY IDEOGRAPH-FA21;Lo;0;L;;;;;N;;;;; FA22;CJK COMPATIBILITY IDEOGRAPH-FA22;Lo;0;L;8AF8;;;;N;;;;; FA23;CJK COMPATIBILITY IDEOGRAPH-FA23;Lo;0;L;;;;;N;;;;; FA24;CJK COMPATIBILITY IDEOGRAPH-FA24;Lo;0;L;;;;;N;;;;; FA25;CJK COMPATIBILITY IDEOGRAPH-FA25;Lo;0;L;9038;;;;N;;;;; FA26;CJK COMPATIBILITY IDEOGRAPH-FA26;Lo;0;L;90FD;;;;N;;;;; FA27;CJK COMPATIBILITY IDEOGRAPH-FA27;Lo;0;L;;;;;N;;;;; FA28;CJK COMPATIBILITY IDEOGRAPH-FA28;Lo;0;L;;;;;N;;;;; FA29;CJK COMPATIBILITY IDEOGRAPH-FA29;Lo;0;L;;;;;N;;;;; FA2A;CJK COMPATIBILITY IDEOGRAPH-FA2A;Lo;0;L;98EF;;;;N;;;;; FA2B;CJK COMPATIBILITY IDEOGRAPH-FA2B;Lo;0;L;98FC;;;;N;;;;; FA2C;CJK COMPATIBILITY IDEOGRAPH-FA2C;Lo;0;L;9928;;;;N;;;;; FA2D;CJK COMPATIBILITY IDEOGRAPH-FA2D;Lo;0;L;9DB4;;;;N;;;;; FA2E;CJK COMPATIBILITY IDEOGRAPH-FA2E;Lo;0;L;90DE;;;;N;;;;; FA2F;CJK COMPATIBILITY IDEOGRAPH-FA2F;Lo;0;L;96B7;;;;N;;;;; FA30;CJK COMPATIBILITY IDEOGRAPH-FA30;Lo;0;L;4FAE;;;;N;;;;; FA31;CJK COMPATIBILITY IDEOGRAPH-FA31;Lo;0;L;50E7;;;;N;;;;; FA32;CJK COMPATIBILITY IDEOGRAPH-FA32;Lo;0;L;514D;;;;N;;;;; FA33;CJK COMPATIBILITY IDEOGRAPH-FA33;Lo;0;L;52C9;;;;N;;;;; FA34;CJK COMPATIBILITY IDEOGRAPH-FA34;Lo;0;L;52E4;;;;N;;;;; FA35;CJK COMPATIBILITY IDEOGRAPH-FA35;Lo;0;L;5351;;;;N;;;;; FA36;CJK COMPATIBILITY IDEOGRAPH-FA36;Lo;0;L;559D;;;;N;;;;; FA37;CJK COMPATIBILITY IDEOGRAPH-FA37;Lo;0;L;5606;;;;N;;;;; FA38;CJK COMPATIBILITY IDEOGRAPH-FA38;Lo;0;L;5668;;;;N;;;;; FA39;CJK COMPATIBILITY IDEOGRAPH-FA39;Lo;0;L;5840;;;;N;;;;; FA3A;CJK COMPATIBILITY IDEOGRAPH-FA3A;Lo;0;L;58A8;;;;N;;;;; FA3B;CJK COMPATIBILITY IDEOGRAPH-FA3B;Lo;0;L;5C64;;;;N;;;;; FA3C;CJK COMPATIBILITY IDEOGRAPH-FA3C;Lo;0;L;5C6E;;;;N;;;;; FA3D;CJK COMPATIBILITY IDEOGRAPH-FA3D;Lo;0;L;6094;;;;N;;;;; FA3E;CJK COMPATIBILITY IDEOGRAPH-FA3E;Lo;0;L;6168;;;;N;;;;; FA3F;CJK COMPATIBILITY IDEOGRAPH-FA3F;Lo;0;L;618E;;;;N;;;;; FA40;CJK COMPATIBILITY IDEOGRAPH-FA40;Lo;0;L;61F2;;;;N;;;;; FA41;CJK COMPATIBILITY IDEOGRAPH-FA41;Lo;0;L;654F;;;;N;;;;; FA42;CJK COMPATIBILITY IDEOGRAPH-FA42;Lo;0;L;65E2;;;;N;;;;; FA43;CJK COMPATIBILITY IDEOGRAPH-FA43;Lo;0;L;6691;;;;N;;;;; FA44;CJK COMPATIBILITY IDEOGRAPH-FA44;Lo;0;L;6885;;;;N;;;;; FA45;CJK COMPATIBILITY IDEOGRAPH-FA45;Lo;0;L;6D77;;;;N;;;;; FA46;CJK COMPATIBILITY IDEOGRAPH-FA46;Lo;0;L;6E1A;;;;N;;;;; FA47;CJK COMPATIBILITY IDEOGRAPH-FA47;Lo;0;L;6F22;;;;N;;;;; FA48;CJK COMPATIBILITY IDEOGRAPH-FA48;Lo;0;L;716E;;;;N;;;;; FA49;CJK COMPATIBILITY IDEOGRAPH-FA49;Lo;0;L;722B;;;;N;;;;; FA4A;CJK COMPATIBILITY IDEOGRAPH-FA4A;Lo;0;L;7422;;;;N;;;;; FA4B;CJK COMPATIBILITY IDEOGRAPH-FA4B;Lo;0;L;7891;;;;N;;;;; FA4C;CJK COMPATIBILITY IDEOGRAPH-FA4C;Lo;0;L;793E;;;;N;;;;; FA4D;CJK COMPATIBILITY IDEOGRAPH-FA4D;Lo;0;L;7949;;;;N;;;;; FA4E;CJK COMPATIBILITY IDEOGRAPH-FA4E;Lo;0;L;7948;;;;N;;;;; FA4F;CJK COMPATIBILITY IDEOGRAPH-FA4F;Lo;0;L;7950;;;;N;;;;; FA50;CJK COMPATIBILITY IDEOGRAPH-FA50;Lo;0;L;7956;;;;N;;;;; FA51;CJK COMPATIBILITY IDEOGRAPH-FA51;Lo;0;L;795D;;;;N;;;;; FA52;CJK COMPATIBILITY IDEOGRAPH-FA52;Lo;0;L;798D;;;;N;;;;; FA53;CJK COMPATIBILITY IDEOGRAPH-FA53;Lo;0;L;798E;;;;N;;;;; FA54;CJK COMPATIBILITY IDEOGRAPH-FA54;Lo;0;L;7A40;;;;N;;;;; FA55;CJK COMPATIBILITY IDEOGRAPH-FA55;Lo;0;L;7A81;;;;N;;;;; FA56;CJK COMPATIBILITY IDEOGRAPH-FA56;Lo;0;L;7BC0;;;;N;;;;; FA57;CJK COMPATIBILITY IDEOGRAPH-FA57;Lo;0;L;7DF4;;;;N;;;;; FA58;CJK COMPATIBILITY IDEOGRAPH-FA58;Lo;0;L;7E09;;;;N;;;;; FA59;CJK COMPATIBILITY IDEOGRAPH-FA59;Lo;0;L;7E41;;;;N;;;;; FA5A;CJK COMPATIBILITY IDEOGRAPH-FA5A;Lo;0;L;7F72;;;;N;;;;; FA5B;CJK COMPATIBILITY IDEOGRAPH-FA5B;Lo;0;L;8005;;;;N;;;;; FA5C;CJK COMPATIBILITY IDEOGRAPH-FA5C;Lo;0;L;81ED;;;;N;;;;; FA5D;CJK COMPATIBILITY IDEOGRAPH-FA5D;Lo;0;L;8279;;;;N;;;;; FA5E;CJK COMPATIBILITY IDEOGRAPH-FA5E;Lo;0;L;8279;;;;N;;;;; FA5F;CJK COMPATIBILITY IDEOGRAPH-FA5F;Lo;0;L;8457;;;;N;;;;; FA60;CJK COMPATIBILITY IDEOGRAPH-FA60;Lo;0;L;8910;;;;N;;;;; FA61;CJK COMPATIBILITY IDEOGRAPH-FA61;Lo;0;L;8996;;;;N;;;;; FA62;CJK COMPATIBILITY IDEOGRAPH-FA62;Lo;0;L;8B01;;;;N;;;;; FA63;CJK COMPATIBILITY IDEOGRAPH-FA63;Lo;0;L;8B39;;;;N;;;;; FA64;CJK COMPATIBILITY IDEOGRAPH-FA64;Lo;0;L;8CD3;;;;N;;;;; FA65;CJK COMPATIBILITY IDEOGRAPH-FA65;Lo;0;L;8D08;;;;N;;;;; FA66;CJK COMPATIBILITY IDEOGRAPH-FA66;Lo;0;L;8FB6;;;;N;;;;; FA67;CJK COMPATIBILITY IDEOGRAPH-FA67;Lo;0;L;9038;;;;N;;;;; FA68;CJK COMPATIBILITY IDEOGRAPH-FA68;Lo;0;L;96E3;;;;N;;;;; FA69;CJK COMPATIBILITY IDEOGRAPH-FA69;Lo;0;L;97FF;;;;N;;;;; FA6A;CJK COMPATIBILITY IDEOGRAPH-FA6A;Lo;0;L;983B;;;;N;;;;; FA6B;CJK COMPATIBILITY IDEOGRAPH-FA6B;Lo;0;L;6075;;;;N;;;;; FA6C;CJK COMPATIBILITY IDEOGRAPH-FA6C;Lo;0;L;242EE;;;;N;;;;; FA6D;CJK COMPATIBILITY IDEOGRAPH-FA6D;Lo;0;L;8218;;;;N;;;;; FA70;CJK COMPATIBILITY IDEOGRAPH-FA70;Lo;0;L;4E26;;;;N;;;;; FA71;CJK COMPATIBILITY IDEOGRAPH-FA71;Lo;0;L;51B5;;;;N;;;;; FA72;CJK COMPATIBILITY IDEOGRAPH-FA72;Lo;0;L;5168;;;;N;;;;; FA73;CJK COMPATIBILITY IDEOGRAPH-FA73;Lo;0;L;4F80;;;;N;;;;; FA74;CJK COMPATIBILITY IDEOGRAPH-FA74;Lo;0;L;5145;;;;N;;;;; FA75;CJK COMPATIBILITY IDEOGRAPH-FA75;Lo;0;L;5180;;;;N;;;;; FA76;CJK COMPATIBILITY IDEOGRAPH-FA76;Lo;0;L;52C7;;;;N;;;;; FA77;CJK COMPATIBILITY IDEOGRAPH-FA77;Lo;0;L;52FA;;;;N;;;;; FA78;CJK COMPATIBILITY IDEOGRAPH-FA78;Lo;0;L;559D;;;;N;;;;; FA79;CJK COMPATIBILITY IDEOGRAPH-FA79;Lo;0;L;5555;;;;N;;;;; FA7A;CJK COMPATIBILITY IDEOGRAPH-FA7A;Lo;0;L;5599;;;;N;;;;; FA7B;CJK COMPATIBILITY IDEOGRAPH-FA7B;Lo;0;L;55E2;;;;N;;;;; FA7C;CJK COMPATIBILITY IDEOGRAPH-FA7C;Lo;0;L;585A;;;;N;;;;; FA7D;CJK COMPATIBILITY IDEOGRAPH-FA7D;Lo;0;L;58B3;;;;N;;;;; FA7E;CJK COMPATIBILITY IDEOGRAPH-FA7E;Lo;0;L;5944;;;;N;;;;; FA7F;CJK COMPATIBILITY IDEOGRAPH-FA7F;Lo;0;L;5954;;;;N;;;;; FA80;CJK COMPATIBILITY IDEOGRAPH-FA80;Lo;0;L;5A62;;;;N;;;;; FA81;CJK COMPATIBILITY IDEOGRAPH-FA81;Lo;0;L;5B28;;;;N;;;;; FA82;CJK COMPATIBILITY IDEOGRAPH-FA82;Lo;0;L;5ED2;;;;N;;;;; FA83;CJK COMPATIBILITY IDEOGRAPH-FA83;Lo;0;L;5ED9;;;;N;;;;; FA84;CJK COMPATIBILITY IDEOGRAPH-FA84;Lo;0;L;5F69;;;;N;;;;; FA85;CJK COMPATIBILITY IDEOGRAPH-FA85;Lo;0;L;5FAD;;;;N;;;;; FA86;CJK COMPATIBILITY IDEOGRAPH-FA86;Lo;0;L;60D8;;;;N;;;;; FA87;CJK COMPATIBILITY IDEOGRAPH-FA87;Lo;0;L;614E;;;;N;;;;; FA88;CJK COMPATIBILITY IDEOGRAPH-FA88;Lo;0;L;6108;;;;N;;;;; FA89;CJK COMPATIBILITY IDEOGRAPH-FA89;Lo;0;L;618E;;;;N;;;;; FA8A;CJK COMPATIBILITY IDEOGRAPH-FA8A;Lo;0;L;6160;;;;N;;;;; FA8B;CJK COMPATIBILITY IDEOGRAPH-FA8B;Lo;0;L;61F2;;;;N;;;;; FA8C;CJK COMPATIBILITY IDEOGRAPH-FA8C;Lo;0;L;6234;;;;N;;;;; FA8D;CJK COMPATIBILITY IDEOGRAPH-FA8D;Lo;0;L;63C4;;;;N;;;;; FA8E;CJK COMPATIBILITY IDEOGRAPH-FA8E;Lo;0;L;641C;;;;N;;;;; FA8F;CJK COMPATIBILITY IDEOGRAPH-FA8F;Lo;0;L;6452;;;;N;;;;; FA90;CJK COMPATIBILITY IDEOGRAPH-FA90;Lo;0;L;6556;;;;N;;;;; FA91;CJK COMPATIBILITY IDEOGRAPH-FA91;Lo;0;L;6674;;;;N;;;;; FA92;CJK COMPATIBILITY IDEOGRAPH-FA92;Lo;0;L;6717;;;;N;;;;; FA93;CJK COMPATIBILITY IDEOGRAPH-FA93;Lo;0;L;671B;;;;N;;;;; FA94;CJK COMPATIBILITY IDEOGRAPH-FA94;Lo;0;L;6756;;;;N;;;;; FA95;CJK COMPATIBILITY IDEOGRAPH-FA95;Lo;0;L;6B79;;;;N;;;;; FA96;CJK COMPATIBILITY IDEOGRAPH-FA96;Lo;0;L;6BBA;;;;N;;;;; FA97;CJK COMPATIBILITY IDEOGRAPH-FA97;Lo;0;L;6D41;;;;N;;;;; FA98;CJK COMPATIBILITY IDEOGRAPH-FA98;Lo;0;L;6EDB;;;;N;;;;; FA99;CJK COMPATIBILITY IDEOGRAPH-FA99;Lo;0;L;6ECB;;;;N;;;;; FA9A;CJK COMPATIBILITY IDEOGRAPH-FA9A;Lo;0;L;6F22;;;;N;;;;; FA9B;CJK COMPATIBILITY IDEOGRAPH-FA9B;Lo;0;L;701E;;;;N;;;;; FA9C;CJK COMPATIBILITY IDEOGRAPH-FA9C;Lo;0;L;716E;;;;N;;;;; FA9D;CJK COMPATIBILITY IDEOGRAPH-FA9D;Lo;0;L;77A7;;;;N;;;;; FA9E;CJK COMPATIBILITY IDEOGRAPH-FA9E;Lo;0;L;7235;;;;N;;;;; FA9F;CJK COMPATIBILITY IDEOGRAPH-FA9F;Lo;0;L;72AF;;;;N;;;;; FAA0;CJK COMPATIBILITY IDEOGRAPH-FAA0;Lo;0;L;732A;;;;N;;;;; FAA1;CJK COMPATIBILITY IDEOGRAPH-FAA1;Lo;0;L;7471;;;;N;;;;; FAA2;CJK COMPATIBILITY IDEOGRAPH-FAA2;Lo;0;L;7506;;;;N;;;;; FAA3;CJK COMPATIBILITY IDEOGRAPH-FAA3;Lo;0;L;753B;;;;N;;;;; FAA4;CJK COMPATIBILITY IDEOGRAPH-FAA4;Lo;0;L;761D;;;;N;;;;; FAA5;CJK COMPATIBILITY IDEOGRAPH-FAA5;Lo;0;L;761F;;;;N;;;;; FAA6;CJK COMPATIBILITY IDEOGRAPH-FAA6;Lo;0;L;76CA;;;;N;;;;; FAA7;CJK COMPATIBILITY IDEOGRAPH-FAA7;Lo;0;L;76DB;;;;N;;;;; FAA8;CJK COMPATIBILITY IDEOGRAPH-FAA8;Lo;0;L;76F4;;;;N;;;;; FAA9;CJK COMPATIBILITY IDEOGRAPH-FAA9;Lo;0;L;774A;;;;N;;;;; FAAA;CJK COMPATIBILITY IDEOGRAPH-FAAA;Lo;0;L;7740;;;;N;;;;; FAAB;CJK COMPATIBILITY IDEOGRAPH-FAAB;Lo;0;L;78CC;;;;N;;;;; FAAC;CJK COMPATIBILITY IDEOGRAPH-FAAC;Lo;0;L;7AB1;;;;N;;;;; FAAD;CJK COMPATIBILITY IDEOGRAPH-FAAD;Lo;0;L;7BC0;;;;N;;;;; FAAE;CJK COMPATIBILITY IDEOGRAPH-FAAE;Lo;0;L;7C7B;;;;N;;;;; FAAF;CJK COMPATIBILITY IDEOGRAPH-FAAF;Lo;0;L;7D5B;;;;N;;;;; FAB0;CJK COMPATIBILITY IDEOGRAPH-FAB0;Lo;0;L;7DF4;;;;N;;;;; FAB1;CJK COMPATIBILITY IDEOGRAPH-FAB1;Lo;0;L;7F3E;;;;N;;;;; FAB2;CJK COMPATIBILITY IDEOGRAPH-FAB2;Lo;0;L;8005;;;;N;;;;; FAB3;CJK COMPATIBILITY IDEOGRAPH-FAB3;Lo;0;L;8352;;;;N;;;;; FAB4;CJK COMPATIBILITY IDEOGRAPH-FAB4;Lo;0;L;83EF;;;;N;;;;; FAB5;CJK COMPATIBILITY IDEOGRAPH-FAB5;Lo;0;L;8779;;;;N;;;;; FAB6;CJK COMPATIBILITY IDEOGRAPH-FAB6;Lo;0;L;8941;;;;N;;;;; FAB7;CJK COMPATIBILITY IDEOGRAPH-FAB7;Lo;0;L;8986;;;;N;;;;; FAB8;CJK COMPATIBILITY IDEOGRAPH-FAB8;Lo;0;L;8996;;;;N;;;;; FAB9;CJK COMPATIBILITY IDEOGRAPH-FAB9;Lo;0;L;8ABF;;;;N;;;;; FABA;CJK COMPATIBILITY IDEOGRAPH-FABA;Lo;0;L;8AF8;;;;N;;;;; FABB;CJK COMPATIBILITY IDEOGRAPH-FABB;Lo;0;L;8ACB;;;;N;;;;; FABC;CJK COMPATIBILITY IDEOGRAPH-FABC;Lo;0;L;8B01;;;;N;;;;; FABD;CJK COMPATIBILITY IDEOGRAPH-FABD;Lo;0;L;8AFE;;;;N;;;;; FABE;CJK COMPATIBILITY IDEOGRAPH-FABE;Lo;0;L;8AED;;;;N;;;;; FABF;CJK COMPATIBILITY IDEOGRAPH-FABF;Lo;0;L;8B39;;;;N;;;;; FAC0;CJK COMPATIBILITY IDEOGRAPH-FAC0;Lo;0;L;8B8A;;;;N;;;;; FAC1;CJK COMPATIBILITY IDEOGRAPH-FAC1;Lo;0;L;8D08;;;;N;;;;; FAC2;CJK COMPATIBILITY IDEOGRAPH-FAC2;Lo;0;L;8F38;;;;N;;;;; FAC3;CJK COMPATIBILITY IDEOGRAPH-FAC3;Lo;0;L;9072;;;;N;;;;; FAC4;CJK COMPATIBILITY IDEOGRAPH-FAC4;Lo;0;L;9199;;;;N;;;;; FAC5;CJK COMPATIBILITY IDEOGRAPH-FAC5;Lo;0;L;9276;;;;N;;;;; FAC6;CJK COMPATIBILITY IDEOGRAPH-FAC6;Lo;0;L;967C;;;;N;;;;; FAC7;CJK COMPATIBILITY IDEOGRAPH-FAC7;Lo;0;L;96E3;;;;N;;;;; FAC8;CJK COMPATIBILITY IDEOGRAPH-FAC8;Lo;0;L;9756;;;;N;;;;; FAC9;CJK COMPATIBILITY IDEOGRAPH-FAC9;Lo;0;L;97DB;;;;N;;;;; FACA;CJK COMPATIBILITY IDEOGRAPH-FACA;Lo;0;L;97FF;;;;N;;;;; FACB;CJK COMPATIBILITY IDEOGRAPH-FACB;Lo;0;L;980B;;;;N;;;;; FACC;CJK COMPATIBILITY IDEOGRAPH-FACC;Lo;0;L;983B;;;;N;;;;; FACD;CJK COMPATIBILITY IDEOGRAPH-FACD;Lo;0;L;9B12;;;;N;;;;; FACE;CJK COMPATIBILITY IDEOGRAPH-FACE;Lo;0;L;9F9C;;;;N;;;;; FACF;CJK COMPATIBILITY IDEOGRAPH-FACF;Lo;0;L;2284A;;;;N;;;;; FAD0;CJK COMPATIBILITY IDEOGRAPH-FAD0;Lo;0;L;22844;;;;N;;;;; FAD1;CJK COMPATIBILITY IDEOGRAPH-FAD1;Lo;0;L;233D5;;;;N;;;;; FAD2;CJK COMPATIBILITY IDEOGRAPH-FAD2;Lo;0;L;3B9D;;;;N;;;;; FAD3;CJK COMPATIBILITY IDEOGRAPH-FAD3;Lo;0;L;4018;;;;N;;;;; FAD4;CJK COMPATIBILITY IDEOGRAPH-FAD4;Lo;0;L;4039;;;;N;;;;; FAD5;CJK COMPATIBILITY IDEOGRAPH-FAD5;Lo;0;L;25249;;;;N;;;;; FAD6;CJK COMPATIBILITY IDEOGRAPH-FAD6;Lo;0;L;25CD0;;;;N;;;;; FAD7;CJK COMPATIBILITY IDEOGRAPH-FAD7;Lo;0;L;27ED3;;;;N;;;;; FAD8;CJK COMPATIBILITY IDEOGRAPH-FAD8;Lo;0;L;9F43;;;;N;;;;; FAD9;CJK COMPATIBILITY IDEOGRAPH-FAD9;Lo;0;L;9F8E;;;;N;;;;; FB00;LATIN SMALL LIGATURE FF;Ll;0;L;<compat> 0066 0066;;;;N;;;;; FB01;LATIN SMALL LIGATURE FI;Ll;0;L;<compat> 0066 0069;;;;N;;;;; FB02;LATIN SMALL LIGATURE FL;Ll;0;L;<compat> 0066 006C;;;;N;;;;; FB03;LATIN SMALL LIGATURE FFI;Ll;0;L;<compat> 0066 0066 0069;;;;N;;;;; FB04;LATIN SMALL LIGATURE FFL;Ll;0;L;<compat> 0066 0066 006C;;;;N;;;;; FB05;LATIN SMALL LIGATURE LONG S T;Ll;0;L;<compat> 017F 0074;;;;N;;;;; FB06;LATIN SMALL LIGATURE ST;Ll;0;L;<compat> 0073 0074;;;;N;;;;; FB13;ARMENIAN SMALL LIGATURE MEN NOW;Ll;0;L;<compat> 0574 0576;;;;N;;;;; FB14;ARMENIAN SMALL LIGATURE MEN ECH;Ll;0;L;<compat> 0574 0565;;;;N;;;;; FB15;ARMENIAN SMALL LIGATURE MEN INI;Ll;0;L;<compat> 0574 056B;;;;N;;;;; FB16;ARMENIAN SMALL LIGATURE VEW NOW;Ll;0;L;<compat> 057E 0576;;;;N;;;;; FB17;ARMENIAN SMALL LIGATURE MEN XEH;Ll;0;L;<compat> 0574 056D;;;;N;;;;; FB1D;HEBREW LETTER YOD WITH HIRIQ;Lo;0;R;05D9 05B4;;;;N;;;;; FB1E;HEBREW POINT JUDEO-SPANISH VARIKA;Mn;26;NSM;;;;;N;HEBREW POINT VARIKA;;;; FB1F;HEBREW LIGATURE YIDDISH YOD YOD PATAH;Lo;0;R;05F2 05B7;;;;N;;;;; FB20;HEBREW LETTER ALTERNATIVE AYIN;Lo;0;R;<font> 05E2;;;;N;;;;; FB21;HEBREW LETTER WIDE ALEF;Lo;0;R;<font> 05D0;;;;N;;;;; FB22;HEBREW LETTER WIDE DALET;Lo;0;R;<font> 05D3;;;;N;;;;; FB23;HEBREW LETTER WIDE HE;Lo;0;R;<font> 05D4;;;;N;;;;; FB24;HEBREW LETTER WIDE KAF;Lo;0;R;<font> 05DB;;;;N;;;;; FB25;HEBREW LETTER WIDE LAMED;Lo;0;R;<font> 05DC;;;;N;;;;; FB26;HEBREW LETTER WIDE FINAL MEM;Lo;0;R;<font> 05DD;;;;N;;;;; FB27;HEBREW LETTER WIDE RESH;Lo;0;R;<font> 05E8;;;;N;;;;; FB28;HEBREW LETTER WIDE TAV;Lo;0;R;<font> 05EA;;;;N;;;;; FB29;HEBREW LETTER ALTERNATIVE PLUS SIGN;Sm;0;ES;<font> 002B;;;;N;;;;; FB2A;HEBREW LETTER SHIN WITH SHIN DOT;Lo;0;R;05E9 05C1;;;;N;;;;; FB2B;HEBREW LETTER SHIN WITH SIN DOT;Lo;0;R;05E9 05C2;;;;N;;;;; FB2C;HEBREW LETTER SHIN WITH DAGESH AND SHIN DOT;Lo;0;R;FB49 05C1;;;;N;;;;; FB2D;HEBREW LETTER SHIN WITH DAGESH AND SIN DOT;Lo;0;R;FB49 05C2;;;;N;;;;; FB2E;HEBREW LETTER ALEF WITH PATAH;Lo;0;R;05D0 05B7;;;;N;;;;; FB2F;HEBREW LETTER ALEF WITH QAMATS;Lo;0;R;05D0 05B8;;;;N;;;;; FB30;HEBREW LETTER ALEF WITH MAPIQ;Lo;0;R;05D0 05BC;;;;N;;;;; FB31;HEBREW LETTER BET WITH DAGESH;Lo;0;R;05D1 05BC;;;;N;;;;; FB32;HEBREW LETTER GIMEL WITH DAGESH;Lo;0;R;05D2 05BC;;;;N;;;;; FB33;HEBREW LETTER DALET WITH DAGESH;Lo;0;R;05D3 05BC;;;;N;;;;; FB34;HEBREW LETTER HE WITH MAPIQ;Lo;0;R;05D4 05BC;;;;N;;;;; FB35;HEBREW LETTER VAV WITH DAGESH;Lo;0;R;05D5 05BC;;;;N;;;;; FB36;HEBREW LETTER ZAYIN WITH DAGESH;Lo;0;R;05D6 05BC;;;;N;;;;; FB38;HEBREW LETTER TET WITH DAGESH;Lo;0;R;05D8 05BC;;;;N;;;;; FB39;HEBREW LETTER YOD WITH DAGESH;Lo;0;R;05D9 05BC;;;;N;;;;; FB3A;HEBREW LETTER FINAL KAF WITH DAGESH;Lo;0;R;05DA 05BC;;;;N;;;;; FB3B;HEBREW LETTER KAF WITH DAGESH;Lo;0;R;05DB 05BC;;;;N;;;;; FB3C;HEBREW LETTER LAMED WITH DAGESH;Lo;0;R;05DC 05BC;;;;N;;;;; FB3E;HEBREW LETTER MEM WITH DAGESH;Lo;0;R;05DE 05BC;;;;N;;;;; FB40;HEBREW LETTER NUN WITH DAGESH;Lo;0;R;05E0 05BC;;;;N;;;;; FB41;HEBREW LETTER SAMEKH WITH DAGESH;Lo;0;R;05E1 05BC;;;;N;;;;; FB43;HEBREW LETTER FINAL PE WITH DAGESH;Lo;0;R;05E3 05BC;;;;N;;;;; FB44;HEBREW LETTER PE WITH DAGESH;Lo;0;R;05E4 05BC;;;;N;;;;; FB46;HEBREW LETTER TSADI WITH DAGESH;Lo;0;R;05E6 05BC;;;;N;;;;; FB47;HEBREW LETTER QOF WITH DAGESH;Lo;0;R;05E7 05BC;;;;N;;;;; FB48;HEBREW LETTER RESH WITH DAGESH;Lo;0;R;05E8 05BC;;;;N;;;;; FB49;HEBREW LETTER SHIN WITH DAGESH;Lo;0;R;05E9 05BC;;;;N;;;;; FB4A;HEBREW LETTER TAV WITH DAGESH;Lo;0;R;05EA 05BC;;;;N;;;;; FB4B;HEBREW LETTER VAV WITH HOLAM;Lo;0;R;05D5 05B9;;;;N;;;;; FB4C;HEBREW LETTER BET WITH RAFE;Lo;0;R;05D1 05BF;;;;N;;;;; FB4D;HEBREW LETTER KAF WITH RAFE;Lo;0;R;05DB 05BF;;;;N;;;;; FB4E;HEBREW LETTER PE WITH RAFE;Lo;0;R;05E4 05BF;;;;N;;;;; FB4F;HEBREW LIGATURE ALEF LAMED;Lo;0;R;<compat> 05D0 05DC;;;;N;;;;; FB50;ARABIC LETTER ALEF WASLA ISOLATED FORM;Lo;0;AL;<isolated> 0671;;;;N;;;;; FB51;ARABIC LETTER ALEF WASLA FINAL FORM;Lo;0;AL;<final> 0671;;;;N;;;;; FB52;ARABIC LETTER BEEH ISOLATED FORM;Lo;0;AL;<isolated> 067B;;;;N;;;;; FB53;ARABIC LETTER BEEH FINAL FORM;Lo;0;AL;<final> 067B;;;;N;;;;; FB54;ARABIC LETTER BEEH INITIAL FORM;Lo;0;AL;<initial> 067B;;;;N;;;;; FB55;ARABIC LETTER BEEH MEDIAL FORM;Lo;0;AL;<medial> 067B;;;;N;;;;; FB56;ARABIC LETTER PEH ISOLATED FORM;Lo;0;AL;<isolated> 067E;;;;N;;;;; FB57;ARABIC LETTER PEH FINAL FORM;Lo;0;AL;<final> 067E;;;;N;;;;; FB58;ARABIC LETTER PEH INITIAL FORM;Lo;0;AL;<initial> 067E;;;;N;;;;; FB59;ARABIC LETTER PEH MEDIAL FORM;Lo;0;AL;<medial> 067E;;;;N;;;;; FB5A;ARABIC LETTER BEHEH ISOLATED FORM;Lo;0;AL;<isolated> 0680;;;;N;;;;; FB5B;ARABIC LETTER BEHEH FINAL FORM;Lo;0;AL;<final> 0680;;;;N;;;;; FB5C;ARABIC LETTER BEHEH INITIAL FORM;Lo;0;AL;<initial> 0680;;;;N;;;;; FB5D;ARABIC LETTER BEHEH MEDIAL FORM;Lo;0;AL;<medial> 0680;;;;N;;;;; FB5E;ARABIC LETTER TTEHEH ISOLATED FORM;Lo;0;AL;<isolated> 067A;;;;N;;;;; FB5F;ARABIC LETTER TTEHEH FINAL FORM;Lo;0;AL;<final> 067A;;;;N;;;;; FB60;ARABIC LETTER TTEHEH INITIAL FORM;Lo;0;AL;<initial> 067A;;;;N;;;;; FB61;ARABIC LETTER TTEHEH MEDIAL FORM;Lo;0;AL;<medial> 067A;;;;N;;;;; FB62;ARABIC LETTER TEHEH ISOLATED FORM;Lo;0;AL;<isolated> 067F;;;;N;;;;; FB63;ARABIC LETTER TEHEH FINAL FORM;Lo;0;AL;<final> 067F;;;;N;;;;; FB64;ARABIC LETTER TEHEH INITIAL FORM;Lo;0;AL;<initial> 067F;;;;N;;;;; FB65;ARABIC LETTER TEHEH MEDIAL FORM;Lo;0;AL;<medial> 067F;;;;N;;;;; FB66;ARABIC LETTER TTEH ISOLATED FORM;Lo;0;AL;<isolated> 0679;;;;N;;;;; FB67;ARABIC LETTER TTEH FINAL FORM;Lo;0;AL;<final> 0679;;;;N;;;;; FB68;ARABIC LETTER TTEH INITIAL FORM;Lo;0;AL;<initial> 0679;;;;N;;;;; FB69;ARABIC LETTER TTEH MEDIAL FORM;Lo;0;AL;<medial> 0679;;;;N;;;;; FB6A;ARABIC LETTER VEH ISOLATED FORM;Lo;0;AL;<isolated> 06A4;;;;N;;;;; FB6B;ARABIC LETTER VEH FINAL FORM;Lo;0;AL;<final> 06A4;;;;N;;;;; FB6C;ARABIC LETTER VEH INITIAL FORM;Lo;0;AL;<initial> 06A4;;;;N;;;;; FB6D;ARABIC LETTER VEH MEDIAL FORM;Lo;0;AL;<medial> 06A4;;;;N;;;;; FB6E;ARABIC LETTER PEHEH ISOLATED FORM;Lo;0;AL;<isolated> 06A6;;;;N;;;;; FB6F;ARABIC LETTER PEHEH FINAL FORM;Lo;0;AL;<final> 06A6;;;;N;;;;; FB70;ARABIC LETTER PEHEH INITIAL FORM;Lo;0;AL;<initial> 06A6;;;;N;;;;; FB71;ARABIC LETTER PEHEH MEDIAL FORM;Lo;0;AL;<medial> 06A6;;;;N;;;;; FB72;ARABIC LETTER DYEH ISOLATED FORM;Lo;0;AL;<isolated> 0684;;;;N;;;;; FB73;ARABIC LETTER DYEH FINAL FORM;Lo;0;AL;<final> 0684;;;;N;;;;; FB74;ARABIC LETTER DYEH INITIAL FORM;Lo;0;AL;<initial> 0684;;;;N;;;;; FB75;ARABIC LETTER DYEH MEDIAL FORM;Lo;0;AL;<medial> 0684;;;;N;;;;; FB76;ARABIC LETTER NYEH ISOLATED FORM;Lo;0;AL;<isolated> 0683;;;;N;;;;; FB77;ARABIC LETTER NYEH FINAL FORM;Lo;0;AL;<final> 0683;;;;N;;;;; FB78;ARABIC LETTER NYEH INITIAL FORM;Lo;0;AL;<initial> 0683;;;;N;;;;; FB79;ARABIC LETTER NYEH MEDIAL FORM;Lo;0;AL;<medial> 0683;;;;N;;;;; FB7A;ARABIC LETTER TCHEH ISOLATED FORM;Lo;0;AL;<isolated> 0686;;;;N;;;;; FB7B;ARABIC LETTER TCHEH FINAL FORM;Lo;0;AL;<final> 0686;;;;N;;;;; FB7C;ARABIC LETTER TCHEH INITIAL FORM;Lo;0;AL;<initial> 0686;;;;N;;;;; FB7D;ARABIC LETTER TCHEH MEDIAL FORM;Lo;0;AL;<medial> 0686;;;;N;;;;; FB7E;ARABIC LETTER TCHEHEH ISOLATED FORM;Lo;0;AL;<isolated> 0687;;;;N;;;;; FB7F;ARABIC LETTER TCHEHEH FINAL FORM;Lo;0;AL;<final> 0687;;;;N;;;;; FB80;ARABIC LETTER TCHEHEH INITIAL FORM;Lo;0;AL;<initial> 0687;;;;N;;;;; FB81;ARABIC LETTER TCHEHEH MEDIAL FORM;Lo;0;AL;<medial> 0687;;;;N;;;;; FB82;ARABIC LETTER DDAHAL ISOLATED FORM;Lo;0;AL;<isolated> 068D;;;;N;;;;; FB83;ARABIC LETTER DDAHAL FINAL FORM;Lo;0;AL;<final> 068D;;;;N;;;;; FB84;ARABIC LETTER DAHAL ISOLATED FORM;Lo;0;AL;<isolated> 068C;;;;N;;;;; FB85;ARABIC LETTER DAHAL FINAL FORM;Lo;0;AL;<final> 068C;;;;N;;;;; FB86;ARABIC LETTER DUL ISOLATED FORM;Lo;0;AL;<isolated> 068E;;;;N;;;;; FB87;ARABIC LETTER DUL FINAL FORM;Lo;0;AL;<final> 068E;;;;N;;;;; FB88;ARABIC LETTER DDAL ISOLATED FORM;Lo;0;AL;<isolated> 0688;;;;N;;;;; FB89;ARABIC LETTER DDAL FINAL FORM;Lo;0;AL;<final> 0688;;;;N;;;;; FB8A;ARABIC LETTER JEH ISOLATED FORM;Lo;0;AL;<isolated> 0698;;;;N;;;;; FB8B;ARABIC LETTER JEH FINAL FORM;Lo;0;AL;<final> 0698;;;;N;;;;; FB8C;ARABIC LETTER RREH ISOLATED FORM;Lo;0;AL;<isolated> 0691;;;;N;;;;; FB8D;ARABIC LETTER RREH FINAL FORM;Lo;0;AL;<final> 0691;;;;N;;;;; FB8E;ARABIC LETTER KEHEH ISOLATED FORM;Lo;0;AL;<isolated> 06A9;;;;N;;;;; FB8F;ARABIC LETTER KEHEH FINAL FORM;Lo;0;AL;<final> 06A9;;;;N;;;;; FB90;ARABIC LETTER KEHEH INITIAL FORM;Lo;0;AL;<initial> 06A9;;;;N;;;;; FB91;ARABIC LETTER KEHEH MEDIAL FORM;Lo;0;AL;<medial> 06A9;;;;N;;;;; FB92;ARABIC LETTER GAF ISOLATED FORM;Lo;0;AL;<isolated> 06AF;;;;N;;;;; FB93;ARABIC LETTER GAF FINAL FORM;Lo;0;AL;<final> 06AF;;;;N;;;;; FB94;ARABIC LETTER GAF INITIAL FORM;Lo;0;AL;<initial> 06AF;;;;N;;;;; FB95;ARABIC LETTER GAF MEDIAL FORM;Lo;0;AL;<medial> 06AF;;;;N;;;;; FB96;ARABIC LETTER GUEH ISOLATED FORM;Lo;0;AL;<isolated> 06B3;;;;N;;;;; FB97;ARABIC LETTER GUEH FINAL FORM;Lo;0;AL;<final> 06B3;;;;N;;;;; FB98;ARABIC LETTER GUEH INITIAL FORM;Lo;0;AL;<initial> 06B3;;;;N;;;;; FB99;ARABIC LETTER GUEH MEDIAL FORM;Lo;0;AL;<medial> 06B3;;;;N;;;;; FB9A;ARABIC LETTER NGOEH ISOLATED FORM;Lo;0;AL;<isolated> 06B1;;;;N;;;;; FB9B;ARABIC LETTER NGOEH FINAL FORM;Lo;0;AL;<final> 06B1;;;;N;;;;; FB9C;ARABIC LETTER NGOEH INITIAL FORM;Lo;0;AL;<initial> 06B1;;;;N;;;;; FB9D;ARABIC LETTER NGOEH MEDIAL FORM;Lo;0;AL;<medial> 06B1;;;;N;;;;; FB9E;ARABIC LETTER NOON GHUNNA ISOLATED FORM;Lo;0;AL;<isolated> 06BA;;;;N;;;;; FB9F;ARABIC LETTER NOON GHUNNA FINAL FORM;Lo;0;AL;<final> 06BA;;;;N;;;;; FBA0;ARABIC LETTER RNOON ISOLATED FORM;Lo;0;AL;<isolated> 06BB;;;;N;;;;; FBA1;ARABIC LETTER RNOON FINAL FORM;Lo;0;AL;<final> 06BB;;;;N;;;;; FBA2;ARABIC LETTER RNOON INITIAL FORM;Lo;0;AL;<initial> 06BB;;;;N;;;;; FBA3;ARABIC LETTER RNOON MEDIAL FORM;Lo;0;AL;<medial> 06BB;;;;N;;;;; FBA4;ARABIC LETTER HEH WITH YEH ABOVE ISOLATED FORM;Lo;0;AL;<isolated> 06C0;;;;N;;;;; FBA5;ARABIC LETTER HEH WITH YEH ABOVE FINAL FORM;Lo;0;AL;<final> 06C0;;;;N;;;;; FBA6;ARABIC LETTER HEH GOAL ISOLATED FORM;Lo;0;AL;<isolated> 06C1;;;;N;;;;; FBA7;ARABIC LETTER HEH GOAL FINAL FORM;Lo;0;AL;<final> 06C1;;;;N;;;;; FBA8;ARABIC LETTER HEH GOAL INITIAL FORM;Lo;0;AL;<initial> 06C1;;;;N;;;;; FBA9;ARABIC LETTER HEH GOAL MEDIAL FORM;Lo;0;AL;<medial> 06C1;;;;N;;;;; FBAA;ARABIC LETTER HEH DOACHASHMEE ISOLATED FORM;Lo;0;AL;<isolated> 06BE;;;;N;;;;; FBAB;ARABIC LETTER HEH DOACHASHMEE FINAL FORM;Lo;0;AL;<final> 06BE;;;;N;;;;; FBAC;ARABIC LETTER HEH DOACHASHMEE INITIAL FORM;Lo;0;AL;<initial> 06BE;;;;N;;;;; FBAD;ARABIC LETTER HEH DOACHASHMEE MEDIAL FORM;Lo;0;AL;<medial> 06BE;;;;N;;;;; FBAE;ARABIC LETTER YEH BARREE ISOLATED FORM;Lo;0;AL;<isolated> 06D2;;;;N;;;;; FBAF;ARABIC LETTER YEH BARREE FINAL FORM;Lo;0;AL;<final> 06D2;;;;N;;;;; FBB0;ARABIC LETTER YEH BARREE WITH HAMZA ABOVE ISOLATED FORM;Lo;0;AL;<isolated> 06D3;;;;N;;;;; FBB1;ARABIC LETTER YEH BARREE WITH HAMZA ABOVE FINAL FORM;Lo;0;AL;<final> 06D3;;;;N;;;;; FBB2;ARABIC SYMBOL DOT ABOVE;Sk;0;AL;;;;;N;;;;; FBB3;ARABIC SYMBOL DOT BELOW;Sk;0;AL;;;;;N;;;;; FBB4;ARABIC SYMBOL TWO DOTS ABOVE;Sk;0;AL;;;;;N;;;;; FBB5;ARABIC SYMBOL TWO DOTS BELOW;Sk;0;AL;;;;;N;;;;; FBB6;ARABIC SYMBOL THREE DOTS ABOVE;Sk;0;AL;;;;;N;;;;; FBB7;ARABIC SYMBOL THREE DOTS BELOW;Sk;0;AL;;;;;N;;;;; FBB8;ARABIC SYMBOL THREE DOTS POINTING DOWNWARDS ABOVE;Sk;0;AL;;;;;N;;;;; FBB9;ARABIC SYMBOL THREE DOTS POINTING DOWNWARDS BELOW;Sk;0;AL;;;;;N;;;;; FBBA;ARABIC SYMBOL FOUR DOTS ABOVE;Sk;0;AL;;;;;N;;;;; FBBB;ARABIC SYMBOL FOUR DOTS BELOW;Sk;0;AL;;;;;N;;;;; FBBC;ARABIC SYMBOL DOUBLE VERTICAL BAR BELOW;Sk;0;AL;;;;;N;;;;; FBBD;ARABIC SYMBOL TWO DOTS VERTICALLY ABOVE;Sk;0;AL;;;;;N;;;;; FBBE;ARABIC SYMBOL TWO DOTS VERTICALLY BELOW;Sk;0;AL;;;;;N;;;;; FBBF;ARABIC SYMBOL RING;Sk;0;AL;;;;;N;;;;; FBC0;ARABIC SYMBOL SMALL TAH ABOVE;Sk;0;AL;;;;;N;;;;; FBC1;ARABIC SYMBOL SMALL TAH BELOW;Sk;0;AL;;;;;N;;;;; FBD3;ARABIC LETTER NG ISOLATED FORM;Lo;0;AL;<isolated> 06AD;;;;N;;;;; FBD4;ARABIC LETTER NG FINAL FORM;Lo;0;AL;<final> 06AD;;;;N;;;;; FBD5;ARABIC LETTER NG INITIAL FORM;Lo;0;AL;<initial> 06AD;;;;N;;;;; FBD6;ARABIC LETTER NG MEDIAL FORM;Lo;0;AL;<medial> 06AD;;;;N;;;;; FBD7;ARABIC LETTER U ISOLATED FORM;Lo;0;AL;<isolated> 06C7;;;;N;;;;; FBD8;ARABIC LETTER U FINAL FORM;Lo;0;AL;<final> 06C7;;;;N;;;;; FBD9;ARABIC LETTER OE ISOLATED FORM;Lo;0;AL;<isolated> 06C6;;;;N;;;;; FBDA;ARABIC LETTER OE FINAL FORM;Lo;0;AL;<final> 06C6;;;;N;;;;; FBDB;ARABIC LETTER YU ISOLATED FORM;Lo;0;AL;<isolated> 06C8;;;;N;;;;; FBDC;ARABIC LETTER YU FINAL FORM;Lo;0;AL;<final> 06C8;;;;N;;;;; FBDD;ARABIC LETTER U WITH HAMZA ABOVE ISOLATED FORM;Lo;0;AL;<isolated> 0677;;;;N;;;;; FBDE;ARABIC LETTER VE ISOLATED FORM;Lo;0;AL;<isolated> 06CB;;;;N;;;;; FBDF;ARABIC LETTER VE FINAL FORM;Lo;0;AL;<final> 06CB;;;;N;;;;; FBE0;ARABIC LETTER KIRGHIZ OE ISOLATED FORM;Lo;0;AL;<isolated> 06C5;;;;N;;;;; FBE1;ARABIC LETTER KIRGHIZ OE FINAL FORM;Lo;0;AL;<final> 06C5;;;;N;;;;; FBE2;ARABIC LETTER KIRGHIZ YU ISOLATED FORM;Lo;0;AL;<isolated> 06C9;;;;N;;;;; FBE3;ARABIC LETTER KIRGHIZ YU FINAL FORM;Lo;0;AL;<final> 06C9;;;;N;;;;; FBE4;ARABIC LETTER E ISOLATED FORM;Lo;0;AL;<isolated> 06D0;;;;N;;;;; FBE5;ARABIC LETTER E FINAL FORM;Lo;0;AL;<final> 06D0;;;;N;;;;; FBE6;ARABIC LETTER E INITIAL FORM;Lo;0;AL;<initial> 06D0;;;;N;;;;; FBE7;ARABIC LETTER E MEDIAL FORM;Lo;0;AL;<medial> 06D0;;;;N;;;;; FBE8;ARABIC LETTER UIGHUR KAZAKH KIRGHIZ ALEF MAKSURA INITIAL FORM;Lo;0;AL;<initial> 0649;;;;N;;;;; FBE9;ARABIC LETTER UIGHUR KAZAKH KIRGHIZ ALEF MAKSURA MEDIAL FORM;Lo;0;AL;<medial> 0649;;;;N;;;;; FBEA;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF ISOLATED FORM;Lo;0;AL;<isolated> 0626 0627;;;;N;;;;; FBEB;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF FINAL FORM;Lo;0;AL;<final> 0626 0627;;;;N;;;;; FBEC;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH AE ISOLATED FORM;Lo;0;AL;<isolated> 0626 06D5;;;;N;;;;; FBED;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH AE FINAL FORM;Lo;0;AL;<final> 0626 06D5;;;;N;;;;; FBEE;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH WAW ISOLATED FORM;Lo;0;AL;<isolated> 0626 0648;;;;N;;;;; FBEF;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH WAW FINAL FORM;Lo;0;AL;<final> 0626 0648;;;;N;;;;; FBF0;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH U ISOLATED FORM;Lo;0;AL;<isolated> 0626 06C7;;;;N;;;;; FBF1;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH U FINAL FORM;Lo;0;AL;<final> 0626 06C7;;;;N;;;;; FBF2;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH OE ISOLATED FORM;Lo;0;AL;<isolated> 0626 06C6;;;;N;;;;; FBF3;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH OE FINAL FORM;Lo;0;AL;<final> 0626 06C6;;;;N;;;;; FBF4;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YU ISOLATED FORM;Lo;0;AL;<isolated> 0626 06C8;;;;N;;;;; FBF5;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YU FINAL FORM;Lo;0;AL;<final> 0626 06C8;;;;N;;;;; FBF6;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH E ISOLATED FORM;Lo;0;AL;<isolated> 0626 06D0;;;;N;;;;; FBF7;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH E FINAL FORM;Lo;0;AL;<final> 0626 06D0;;;;N;;;;; FBF8;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH E INITIAL FORM;Lo;0;AL;<initial> 0626 06D0;;;;N;;;;; FBF9;ARABIC LIGATURE UIGHUR KIRGHIZ YEH WITH HAMZA ABOVE WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0626 0649;;;;N;;;;; FBFA;ARABIC LIGATURE UIGHUR KIRGHIZ YEH WITH HAMZA ABOVE WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0626 0649;;;;N;;;;; FBFB;ARABIC LIGATURE UIGHUR KIRGHIZ YEH WITH HAMZA ABOVE WITH ALEF MAKSURA INITIAL FORM;Lo;0;AL;<initial> 0626 0649;;;;N;;;;; FBFC;ARABIC LETTER FARSI YEH ISOLATED FORM;Lo;0;AL;<isolated> 06CC;;;;N;;;;; FBFD;ARABIC LETTER FARSI YEH FINAL FORM;Lo;0;AL;<final> 06CC;;;;N;;;;; FBFE;ARABIC LETTER FARSI YEH INITIAL FORM;Lo;0;AL;<initial> 06CC;;;;N;;;;; FBFF;ARABIC LETTER FARSI YEH MEDIAL FORM;Lo;0;AL;<medial> 06CC;;;;N;;;;; FC00;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 0626 062C;;;;N;;;;; FC01;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 0626 062D;;;;N;;;;; FC02;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0626 0645;;;;N;;;;; FC03;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0626 0649;;;;N;;;;; FC04;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0626 064A;;;;N;;;;; FC05;ARABIC LIGATURE BEH WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 0628 062C;;;;N;;;;; FC06;ARABIC LIGATURE BEH WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 0628 062D;;;;N;;;;; FC07;ARABIC LIGATURE BEH WITH KHAH ISOLATED FORM;Lo;0;AL;<isolated> 0628 062E;;;;N;;;;; FC08;ARABIC LIGATURE BEH WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0628 0645;;;;N;;;;; FC09;ARABIC LIGATURE BEH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0628 0649;;;;N;;;;; FC0A;ARABIC LIGATURE BEH WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0628 064A;;;;N;;;;; FC0B;ARABIC LIGATURE TEH WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 062A 062C;;;;N;;;;; FC0C;ARABIC LIGATURE TEH WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 062A 062D;;;;N;;;;; FC0D;ARABIC LIGATURE TEH WITH KHAH ISOLATED FORM;Lo;0;AL;<isolated> 062A 062E;;;;N;;;;; FC0E;ARABIC LIGATURE TEH WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 062A 0645;;;;N;;;;; FC0F;ARABIC LIGATURE TEH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 062A 0649;;;;N;;;;; FC10;ARABIC LIGATURE TEH WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 062A 064A;;;;N;;;;; FC11;ARABIC LIGATURE THEH WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 062B 062C;;;;N;;;;; FC12;ARABIC LIGATURE THEH WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 062B 0645;;;;N;;;;; FC13;ARABIC LIGATURE THEH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 062B 0649;;;;N;;;;; FC14;ARABIC LIGATURE THEH WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 062B 064A;;;;N;;;;; FC15;ARABIC LIGATURE JEEM WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 062C 062D;;;;N;;;;; FC16;ARABIC LIGATURE JEEM WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 062C 0645;;;;N;;;;; FC17;ARABIC LIGATURE HAH WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 062D 062C;;;;N;;;;; FC18;ARABIC LIGATURE HAH WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 062D 0645;;;;N;;;;; FC19;ARABIC LIGATURE KHAH WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 062E 062C;;;;N;;;;; FC1A;ARABIC LIGATURE KHAH WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 062E 062D;;;;N;;;;; FC1B;ARABIC LIGATURE KHAH WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 062E 0645;;;;N;;;;; FC1C;ARABIC LIGATURE SEEN WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 0633 062C;;;;N;;;;; FC1D;ARABIC LIGATURE SEEN WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 0633 062D;;;;N;;;;; FC1E;ARABIC LIGATURE SEEN WITH KHAH ISOLATED FORM;Lo;0;AL;<isolated> 0633 062E;;;;N;;;;; FC1F;ARABIC LIGATURE SEEN WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0633 0645;;;;N;;;;; FC20;ARABIC LIGATURE SAD WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 0635 062D;;;;N;;;;; FC21;ARABIC LIGATURE SAD WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0635 0645;;;;N;;;;; FC22;ARABIC LIGATURE DAD WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 0636 062C;;;;N;;;;; FC23;ARABIC LIGATURE DAD WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 0636 062D;;;;N;;;;; FC24;ARABIC LIGATURE DAD WITH KHAH ISOLATED FORM;Lo;0;AL;<isolated> 0636 062E;;;;N;;;;; FC25;ARABIC LIGATURE DAD WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0636 0645;;;;N;;;;; FC26;ARABIC LIGATURE TAH WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 0637 062D;;;;N;;;;; FC27;ARABIC LIGATURE TAH WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0637 0645;;;;N;;;;; FC28;ARABIC LIGATURE ZAH WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0638 0645;;;;N;;;;; FC29;ARABIC LIGATURE AIN WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 0639 062C;;;;N;;;;; FC2A;ARABIC LIGATURE AIN WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0639 0645;;;;N;;;;; FC2B;ARABIC LIGATURE GHAIN WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 063A 062C;;;;N;;;;; FC2C;ARABIC LIGATURE GHAIN WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 063A 0645;;;;N;;;;; FC2D;ARABIC LIGATURE FEH WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 0641 062C;;;;N;;;;; FC2E;ARABIC LIGATURE FEH WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 0641 062D;;;;N;;;;; FC2F;ARABIC LIGATURE FEH WITH KHAH ISOLATED FORM;Lo;0;AL;<isolated> 0641 062E;;;;N;;;;; FC30;ARABIC LIGATURE FEH WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0641 0645;;;;N;;;;; FC31;ARABIC LIGATURE FEH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0641 0649;;;;N;;;;; FC32;ARABIC LIGATURE FEH WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0641 064A;;;;N;;;;; FC33;ARABIC LIGATURE QAF WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 0642 062D;;;;N;;;;; FC34;ARABIC LIGATURE QAF WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0642 0645;;;;N;;;;; FC35;ARABIC LIGATURE QAF WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0642 0649;;;;N;;;;; FC36;ARABIC LIGATURE QAF WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0642 064A;;;;N;;;;; FC37;ARABIC LIGATURE KAF WITH ALEF ISOLATED FORM;Lo;0;AL;<isolated> 0643 0627;;;;N;;;;; FC38;ARABIC LIGATURE KAF WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 0643 062C;;;;N;;;;; FC39;ARABIC LIGATURE KAF WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 0643 062D;;;;N;;;;; FC3A;ARABIC LIGATURE KAF WITH KHAH ISOLATED FORM;Lo;0;AL;<isolated> 0643 062E;;;;N;;;;; FC3B;ARABIC LIGATURE KAF WITH LAM ISOLATED FORM;Lo;0;AL;<isolated> 0643 0644;;;;N;;;;; FC3C;ARABIC LIGATURE KAF WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0643 0645;;;;N;;;;; FC3D;ARABIC LIGATURE KAF WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0643 0649;;;;N;;;;; FC3E;ARABIC LIGATURE KAF WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0643 064A;;;;N;;;;; FC3F;ARABIC LIGATURE LAM WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 0644 062C;;;;N;;;;; FC40;ARABIC LIGATURE LAM WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 0644 062D;;;;N;;;;; FC41;ARABIC LIGATURE LAM WITH KHAH ISOLATED FORM;Lo;0;AL;<isolated> 0644 062E;;;;N;;;;; FC42;ARABIC LIGATURE LAM WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0644 0645;;;;N;;;;; FC43;ARABIC LIGATURE LAM WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0644 0649;;;;N;;;;; FC44;ARABIC LIGATURE LAM WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0644 064A;;;;N;;;;; FC45;ARABIC LIGATURE MEEM WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 0645 062C;;;;N;;;;; FC46;ARABIC LIGATURE MEEM WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 0645 062D;;;;N;;;;; FC47;ARABIC LIGATURE MEEM WITH KHAH ISOLATED FORM;Lo;0;AL;<isolated> 0645 062E;;;;N;;;;; FC48;ARABIC LIGATURE MEEM WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0645 0645;;;;N;;;;; FC49;ARABIC LIGATURE MEEM WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0645 0649;;;;N;;;;; FC4A;ARABIC LIGATURE MEEM WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0645 064A;;;;N;;;;; FC4B;ARABIC LIGATURE NOON WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 0646 062C;;;;N;;;;; FC4C;ARABIC LIGATURE NOON WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 0646 062D;;;;N;;;;; FC4D;ARABIC LIGATURE NOON WITH KHAH ISOLATED FORM;Lo;0;AL;<isolated> 0646 062E;;;;N;;;;; FC4E;ARABIC LIGATURE NOON WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0646 0645;;;;N;;;;; FC4F;ARABIC LIGATURE NOON WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0646 0649;;;;N;;;;; FC50;ARABIC LIGATURE NOON WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0646 064A;;;;N;;;;; FC51;ARABIC LIGATURE HEH WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 0647 062C;;;;N;;;;; FC52;ARABIC LIGATURE HEH WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0647 0645;;;;N;;;;; FC53;ARABIC LIGATURE HEH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0647 0649;;;;N;;;;; FC54;ARABIC LIGATURE HEH WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0647 064A;;;;N;;;;; FC55;ARABIC LIGATURE YEH WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 064A 062C;;;;N;;;;; FC56;ARABIC LIGATURE YEH WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 064A 062D;;;;N;;;;; FC57;ARABIC LIGATURE YEH WITH KHAH ISOLATED FORM;Lo;0;AL;<isolated> 064A 062E;;;;N;;;;; FC58;ARABIC LIGATURE YEH WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 064A 0645;;;;N;;;;; FC59;ARABIC LIGATURE YEH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 064A 0649;;;;N;;;;; FC5A;ARABIC LIGATURE YEH WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 064A 064A;;;;N;;;;; FC5B;ARABIC LIGATURE THAL WITH SUPERSCRIPT ALEF ISOLATED FORM;Lo;0;AL;<isolated> 0630 0670;;;;N;;;;; FC5C;ARABIC LIGATURE REH WITH SUPERSCRIPT ALEF ISOLATED FORM;Lo;0;AL;<isolated> 0631 0670;;;;N;;;;; FC5D;ARABIC LIGATURE ALEF MAKSURA WITH SUPERSCRIPT ALEF ISOLATED FORM;Lo;0;AL;<isolated> 0649 0670;;;;N;;;;; FC5E;ARABIC LIGATURE SHADDA WITH DAMMATAN ISOLATED FORM;Lo;0;AL;<isolated> 0020 064C 0651;;;;N;;;;; FC5F;ARABIC LIGATURE SHADDA WITH KASRATAN ISOLATED FORM;Lo;0;AL;<isolated> 0020 064D 0651;;;;N;;;;; FC60;ARABIC LIGATURE SHADDA WITH FATHA ISOLATED FORM;Lo;0;AL;<isolated> 0020 064E 0651;;;;N;;;;; FC61;ARABIC LIGATURE SHADDA WITH DAMMA ISOLATED FORM;Lo;0;AL;<isolated> 0020 064F 0651;;;;N;;;;; FC62;ARABIC LIGATURE SHADDA WITH KASRA ISOLATED FORM;Lo;0;AL;<isolated> 0020 0650 0651;;;;N;;;;; FC63;ARABIC LIGATURE SHADDA WITH SUPERSCRIPT ALEF ISOLATED FORM;Lo;0;AL;<isolated> 0020 0651 0670;;;;N;;;;; FC64;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH REH FINAL FORM;Lo;0;AL;<final> 0626 0631;;;;N;;;;; FC65;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ZAIN FINAL FORM;Lo;0;AL;<final> 0626 0632;;;;N;;;;; FC66;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM FINAL FORM;Lo;0;AL;<final> 0626 0645;;;;N;;;;; FC67;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH NOON FINAL FORM;Lo;0;AL;<final> 0626 0646;;;;N;;;;; FC68;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0626 0649;;;;N;;;;; FC69;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YEH FINAL FORM;Lo;0;AL;<final> 0626 064A;;;;N;;;;; FC6A;ARABIC LIGATURE BEH WITH REH FINAL FORM;Lo;0;AL;<final> 0628 0631;;;;N;;;;; FC6B;ARABIC LIGATURE BEH WITH ZAIN FINAL FORM;Lo;0;AL;<final> 0628 0632;;;;N;;;;; FC6C;ARABIC LIGATURE BEH WITH MEEM FINAL FORM;Lo;0;AL;<final> 0628 0645;;;;N;;;;; FC6D;ARABIC LIGATURE BEH WITH NOON FINAL FORM;Lo;0;AL;<final> 0628 0646;;;;N;;;;; FC6E;ARABIC LIGATURE BEH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0628 0649;;;;N;;;;; FC6F;ARABIC LIGATURE BEH WITH YEH FINAL FORM;Lo;0;AL;<final> 0628 064A;;;;N;;;;; FC70;ARABIC LIGATURE TEH WITH REH FINAL FORM;Lo;0;AL;<final> 062A 0631;;;;N;;;;; FC71;ARABIC LIGATURE TEH WITH ZAIN FINAL FORM;Lo;0;AL;<final> 062A 0632;;;;N;;;;; FC72;ARABIC LIGATURE TEH WITH MEEM FINAL FORM;Lo;0;AL;<final> 062A 0645;;;;N;;;;; FC73;ARABIC LIGATURE TEH WITH NOON FINAL FORM;Lo;0;AL;<final> 062A 0646;;;;N;;;;; FC74;ARABIC LIGATURE TEH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 062A 0649;;;;N;;;;; FC75;ARABIC LIGATURE TEH WITH YEH FINAL FORM;Lo;0;AL;<final> 062A 064A;;;;N;;;;; FC76;ARABIC LIGATURE THEH WITH REH FINAL FORM;Lo;0;AL;<final> 062B 0631;;;;N;;;;; FC77;ARABIC LIGATURE THEH WITH ZAIN FINAL FORM;Lo;0;AL;<final> 062B 0632;;;;N;;;;; FC78;ARABIC LIGATURE THEH WITH MEEM FINAL FORM;Lo;0;AL;<final> 062B 0645;;;;N;;;;; FC79;ARABIC LIGATURE THEH WITH NOON FINAL FORM;Lo;0;AL;<final> 062B 0646;;;;N;;;;; FC7A;ARABIC LIGATURE THEH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 062B 0649;;;;N;;;;; FC7B;ARABIC LIGATURE THEH WITH YEH FINAL FORM;Lo;0;AL;<final> 062B 064A;;;;N;;;;; FC7C;ARABIC LIGATURE FEH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0641 0649;;;;N;;;;; FC7D;ARABIC LIGATURE FEH WITH YEH FINAL FORM;Lo;0;AL;<final> 0641 064A;;;;N;;;;; FC7E;ARABIC LIGATURE QAF WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0642 0649;;;;N;;;;; FC7F;ARABIC LIGATURE QAF WITH YEH FINAL FORM;Lo;0;AL;<final> 0642 064A;;;;N;;;;; FC80;ARABIC LIGATURE KAF WITH ALEF FINAL FORM;Lo;0;AL;<final> 0643 0627;;;;N;;;;; FC81;ARABIC LIGATURE KAF WITH LAM FINAL FORM;Lo;0;AL;<final> 0643 0644;;;;N;;;;; FC82;ARABIC LIGATURE KAF WITH MEEM FINAL FORM;Lo;0;AL;<final> 0643 0645;;;;N;;;;; FC83;ARABIC LIGATURE KAF WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0643 0649;;;;N;;;;; FC84;ARABIC LIGATURE KAF WITH YEH FINAL FORM;Lo;0;AL;<final> 0643 064A;;;;N;;;;; FC85;ARABIC LIGATURE LAM WITH MEEM FINAL FORM;Lo;0;AL;<final> 0644 0645;;;;N;;;;; FC86;ARABIC LIGATURE LAM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0644 0649;;;;N;;;;; FC87;ARABIC LIGATURE LAM WITH YEH FINAL FORM;Lo;0;AL;<final> 0644 064A;;;;N;;;;; FC88;ARABIC LIGATURE MEEM WITH ALEF FINAL FORM;Lo;0;AL;<final> 0645 0627;;;;N;;;;; FC89;ARABIC LIGATURE MEEM WITH MEEM FINAL FORM;Lo;0;AL;<final> 0645 0645;;;;N;;;;; FC8A;ARABIC LIGATURE NOON WITH REH FINAL FORM;Lo;0;AL;<final> 0646 0631;;;;N;;;;; FC8B;ARABIC LIGATURE NOON WITH ZAIN FINAL FORM;Lo;0;AL;<final> 0646 0632;;;;N;;;;; FC8C;ARABIC LIGATURE NOON WITH MEEM FINAL FORM;Lo;0;AL;<final> 0646 0645;;;;N;;;;; FC8D;ARABIC LIGATURE NOON WITH NOON FINAL FORM;Lo;0;AL;<final> 0646 0646;;;;N;;;;; FC8E;ARABIC LIGATURE NOON WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0646 0649;;;;N;;;;; FC8F;ARABIC LIGATURE NOON WITH YEH FINAL FORM;Lo;0;AL;<final> 0646 064A;;;;N;;;;; FC90;ARABIC LIGATURE ALEF MAKSURA WITH SUPERSCRIPT ALEF FINAL FORM;Lo;0;AL;<final> 0649 0670;;;;N;;;;; FC91;ARABIC LIGATURE YEH WITH REH FINAL FORM;Lo;0;AL;<final> 064A 0631;;;;N;;;;; FC92;ARABIC LIGATURE YEH WITH ZAIN FINAL FORM;Lo;0;AL;<final> 064A 0632;;;;N;;;;; FC93;ARABIC LIGATURE YEH WITH MEEM FINAL FORM;Lo;0;AL;<final> 064A 0645;;;;N;;;;; FC94;ARABIC LIGATURE YEH WITH NOON FINAL FORM;Lo;0;AL;<final> 064A 0646;;;;N;;;;; FC95;ARABIC LIGATURE YEH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 064A 0649;;;;N;;;;; FC96;ARABIC LIGATURE YEH WITH YEH FINAL FORM;Lo;0;AL;<final> 064A 064A;;;;N;;;;; FC97;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0626 062C;;;;N;;;;; FC98;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0626 062D;;;;N;;;;; FC99;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 0626 062E;;;;N;;;;; FC9A;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0626 0645;;;;N;;;;; FC9B;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HEH INITIAL FORM;Lo;0;AL;<initial> 0626 0647;;;;N;;;;; FC9C;ARABIC LIGATURE BEH WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0628 062C;;;;N;;;;; FC9D;ARABIC LIGATURE BEH WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0628 062D;;;;N;;;;; FC9E;ARABIC LIGATURE BEH WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 0628 062E;;;;N;;;;; FC9F;ARABIC LIGATURE BEH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0628 0645;;;;N;;;;; FCA0;ARABIC LIGATURE BEH WITH HEH INITIAL FORM;Lo;0;AL;<initial> 0628 0647;;;;N;;;;; FCA1;ARABIC LIGATURE TEH WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 062A 062C;;;;N;;;;; FCA2;ARABIC LIGATURE TEH WITH HAH INITIAL FORM;Lo;0;AL;<initial> 062A 062D;;;;N;;;;; FCA3;ARABIC LIGATURE TEH WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 062A 062E;;;;N;;;;; FCA4;ARABIC LIGATURE TEH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 062A 0645;;;;N;;;;; FCA5;ARABIC LIGATURE TEH WITH HEH INITIAL FORM;Lo;0;AL;<initial> 062A 0647;;;;N;;;;; FCA6;ARABIC LIGATURE THEH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 062B 0645;;;;N;;;;; FCA7;ARABIC LIGATURE JEEM WITH HAH INITIAL FORM;Lo;0;AL;<initial> 062C 062D;;;;N;;;;; FCA8;ARABIC LIGATURE JEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 062C 0645;;;;N;;;;; FCA9;ARABIC LIGATURE HAH WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 062D 062C;;;;N;;;;; FCAA;ARABIC LIGATURE HAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 062D 0645;;;;N;;;;; FCAB;ARABIC LIGATURE KHAH WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 062E 062C;;;;N;;;;; FCAC;ARABIC LIGATURE KHAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 062E 0645;;;;N;;;;; FCAD;ARABIC LIGATURE SEEN WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0633 062C;;;;N;;;;; FCAE;ARABIC LIGATURE SEEN WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0633 062D;;;;N;;;;; FCAF;ARABIC LIGATURE SEEN WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 0633 062E;;;;N;;;;; FCB0;ARABIC LIGATURE SEEN WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0633 0645;;;;N;;;;; FCB1;ARABIC LIGATURE SAD WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0635 062D;;;;N;;;;; FCB2;ARABIC LIGATURE SAD WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 0635 062E;;;;N;;;;; FCB3;ARABIC LIGATURE SAD WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0635 0645;;;;N;;;;; FCB4;ARABIC LIGATURE DAD WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0636 062C;;;;N;;;;; FCB5;ARABIC LIGATURE DAD WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0636 062D;;;;N;;;;; FCB6;ARABIC LIGATURE DAD WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 0636 062E;;;;N;;;;; FCB7;ARABIC LIGATURE DAD WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0636 0645;;;;N;;;;; FCB8;ARABIC LIGATURE TAH WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0637 062D;;;;N;;;;; FCB9;ARABIC LIGATURE ZAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0638 0645;;;;N;;;;; FCBA;ARABIC LIGATURE AIN WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0639 062C;;;;N;;;;; FCBB;ARABIC LIGATURE AIN WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0639 0645;;;;N;;;;; FCBC;ARABIC LIGATURE GHAIN WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 063A 062C;;;;N;;;;; FCBD;ARABIC LIGATURE GHAIN WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 063A 0645;;;;N;;;;; FCBE;ARABIC LIGATURE FEH WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0641 062C;;;;N;;;;; FCBF;ARABIC LIGATURE FEH WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0641 062D;;;;N;;;;; FCC0;ARABIC LIGATURE FEH WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 0641 062E;;;;N;;;;; FCC1;ARABIC LIGATURE FEH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0641 0645;;;;N;;;;; FCC2;ARABIC LIGATURE QAF WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0642 062D;;;;N;;;;; FCC3;ARABIC LIGATURE QAF WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0642 0645;;;;N;;;;; FCC4;ARABIC LIGATURE KAF WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0643 062C;;;;N;;;;; FCC5;ARABIC LIGATURE KAF WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0643 062D;;;;N;;;;; FCC6;ARABIC LIGATURE KAF WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 0643 062E;;;;N;;;;; FCC7;ARABIC LIGATURE KAF WITH LAM INITIAL FORM;Lo;0;AL;<initial> 0643 0644;;;;N;;;;; FCC8;ARABIC LIGATURE KAF WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0643 0645;;;;N;;;;; FCC9;ARABIC LIGATURE LAM WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0644 062C;;;;N;;;;; FCCA;ARABIC LIGATURE LAM WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0644 062D;;;;N;;;;; FCCB;ARABIC LIGATURE LAM WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 0644 062E;;;;N;;;;; FCCC;ARABIC LIGATURE LAM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0644 0645;;;;N;;;;; FCCD;ARABIC LIGATURE LAM WITH HEH INITIAL FORM;Lo;0;AL;<initial> 0644 0647;;;;N;;;;; FCCE;ARABIC LIGATURE MEEM WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0645 062C;;;;N;;;;; FCCF;ARABIC LIGATURE MEEM WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0645 062D;;;;N;;;;; FCD0;ARABIC LIGATURE MEEM WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 0645 062E;;;;N;;;;; FCD1;ARABIC LIGATURE MEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0645 0645;;;;N;;;;; FCD2;ARABIC LIGATURE NOON WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0646 062C;;;;N;;;;; FCD3;ARABIC LIGATURE NOON WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0646 062D;;;;N;;;;; FCD4;ARABIC LIGATURE NOON WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 0646 062E;;;;N;;;;; FCD5;ARABIC LIGATURE NOON WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0646 0645;;;;N;;;;; FCD6;ARABIC LIGATURE NOON WITH HEH INITIAL FORM;Lo;0;AL;<initial> 0646 0647;;;;N;;;;; FCD7;ARABIC LIGATURE HEH WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0647 062C;;;;N;;;;; FCD8;ARABIC LIGATURE HEH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0647 0645;;;;N;;;;; FCD9;ARABIC LIGATURE HEH WITH SUPERSCRIPT ALEF INITIAL FORM;Lo;0;AL;<initial> 0647 0670;;;;N;;;;; FCDA;ARABIC LIGATURE YEH WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 064A 062C;;;;N;;;;; FCDB;ARABIC LIGATURE YEH WITH HAH INITIAL FORM;Lo;0;AL;<initial> 064A 062D;;;;N;;;;; FCDC;ARABIC LIGATURE YEH WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 064A 062E;;;;N;;;;; FCDD;ARABIC LIGATURE YEH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 064A 0645;;;;N;;;;; FCDE;ARABIC LIGATURE YEH WITH HEH INITIAL FORM;Lo;0;AL;<initial> 064A 0647;;;;N;;;;; FCDF;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM MEDIAL FORM;Lo;0;AL;<medial> 0626 0645;;;;N;;;;; FCE0;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HEH MEDIAL FORM;Lo;0;AL;<medial> 0626 0647;;;;N;;;;; FCE1;ARABIC LIGATURE BEH WITH MEEM MEDIAL FORM;Lo;0;AL;<medial> 0628 0645;;;;N;;;;; FCE2;ARABIC LIGATURE BEH WITH HEH MEDIAL FORM;Lo;0;AL;<medial> 0628 0647;;;;N;;;;; FCE3;ARABIC LIGATURE TEH WITH MEEM MEDIAL FORM;Lo;0;AL;<medial> 062A 0645;;;;N;;;;; FCE4;ARABIC LIGATURE TEH WITH HEH MEDIAL FORM;Lo;0;AL;<medial> 062A 0647;;;;N;;;;; FCE5;ARABIC LIGATURE THEH WITH MEEM MEDIAL FORM;Lo;0;AL;<medial> 062B 0645;;;;N;;;;; FCE6;ARABIC LIGATURE THEH WITH HEH MEDIAL FORM;Lo;0;AL;<medial> 062B 0647;;;;N;;;;; FCE7;ARABIC LIGATURE SEEN WITH MEEM MEDIAL FORM;Lo;0;AL;<medial> 0633 0645;;;;N;;;;; FCE8;ARABIC LIGATURE SEEN WITH HEH MEDIAL FORM;Lo;0;AL;<medial> 0633 0647;;;;N;;;;; FCE9;ARABIC LIGATURE SHEEN WITH MEEM MEDIAL FORM;Lo;0;AL;<medial> 0634 0645;;;;N;;;;; FCEA;ARABIC LIGATURE SHEEN WITH HEH MEDIAL FORM;Lo;0;AL;<medial> 0634 0647;;;;N;;;;; FCEB;ARABIC LIGATURE KAF WITH LAM MEDIAL FORM;Lo;0;AL;<medial> 0643 0644;;;;N;;;;; FCEC;ARABIC LIGATURE KAF WITH MEEM MEDIAL FORM;Lo;0;AL;<medial> 0643 0645;;;;N;;;;; FCED;ARABIC LIGATURE LAM WITH MEEM MEDIAL FORM;Lo;0;AL;<medial> 0644 0645;;;;N;;;;; FCEE;ARABIC LIGATURE NOON WITH MEEM MEDIAL FORM;Lo;0;AL;<medial> 0646 0645;;;;N;;;;; FCEF;ARABIC LIGATURE NOON WITH HEH MEDIAL FORM;Lo;0;AL;<medial> 0646 0647;;;;N;;;;; FCF0;ARABIC LIGATURE YEH WITH MEEM MEDIAL FORM;Lo;0;AL;<medial> 064A 0645;;;;N;;;;; FCF1;ARABIC LIGATURE YEH WITH HEH MEDIAL FORM;Lo;0;AL;<medial> 064A 0647;;;;N;;;;; FCF2;ARABIC LIGATURE SHADDA WITH FATHA MEDIAL FORM;Lo;0;AL;<medial> 0640 064E 0651;;;;N;;;;; FCF3;ARABIC LIGATURE SHADDA WITH DAMMA MEDIAL FORM;Lo;0;AL;<medial> 0640 064F 0651;;;;N;;;;; FCF4;ARABIC LIGATURE SHADDA WITH KASRA MEDIAL FORM;Lo;0;AL;<medial> 0640 0650 0651;;;;N;;;;; FCF5;ARABIC LIGATURE TAH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0637 0649;;;;N;;;;; FCF6;ARABIC LIGATURE TAH WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0637 064A;;;;N;;;;; FCF7;ARABIC LIGATURE AIN WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0639 0649;;;;N;;;;; FCF8;ARABIC LIGATURE AIN WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0639 064A;;;;N;;;;; FCF9;ARABIC LIGATURE GHAIN WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 063A 0649;;;;N;;;;; FCFA;ARABIC LIGATURE GHAIN WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 063A 064A;;;;N;;;;; FCFB;ARABIC LIGATURE SEEN WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0633 0649;;;;N;;;;; FCFC;ARABIC LIGATURE SEEN WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0633 064A;;;;N;;;;; FCFD;ARABIC LIGATURE SHEEN WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0634 0649;;;;N;;;;; FCFE;ARABIC LIGATURE SHEEN WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0634 064A;;;;N;;;;; FCFF;ARABIC LIGATURE HAH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 062D 0649;;;;N;;;;; FD00;ARABIC LIGATURE HAH WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 062D 064A;;;;N;;;;; FD01;ARABIC LIGATURE JEEM WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 062C 0649;;;;N;;;;; FD02;ARABIC LIGATURE JEEM WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 062C 064A;;;;N;;;;; FD03;ARABIC LIGATURE KHAH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 062E 0649;;;;N;;;;; FD04;ARABIC LIGATURE KHAH WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 062E 064A;;;;N;;;;; FD05;ARABIC LIGATURE SAD WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0635 0649;;;;N;;;;; FD06;ARABIC LIGATURE SAD WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0635 064A;;;;N;;;;; FD07;ARABIC LIGATURE DAD WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0636 0649;;;;N;;;;; FD08;ARABIC LIGATURE DAD WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0636 064A;;;;N;;;;; FD09;ARABIC LIGATURE SHEEN WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 0634 062C;;;;N;;;;; FD0A;ARABIC LIGATURE SHEEN WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 0634 062D;;;;N;;;;; FD0B;ARABIC LIGATURE SHEEN WITH KHAH ISOLATED FORM;Lo;0;AL;<isolated> 0634 062E;;;;N;;;;; FD0C;ARABIC LIGATURE SHEEN WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0634 0645;;;;N;;;;; FD0D;ARABIC LIGATURE SHEEN WITH REH ISOLATED FORM;Lo;0;AL;<isolated> 0634 0631;;;;N;;;;; FD0E;ARABIC LIGATURE SEEN WITH REH ISOLATED FORM;Lo;0;AL;<isolated> 0633 0631;;;;N;;;;; FD0F;ARABIC LIGATURE SAD WITH REH ISOLATED FORM;Lo;0;AL;<isolated> 0635 0631;;;;N;;;;; FD10;ARABIC LIGATURE DAD WITH REH ISOLATED FORM;Lo;0;AL;<isolated> 0636 0631;;;;N;;;;; FD11;ARABIC LIGATURE TAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0637 0649;;;;N;;;;; FD12;ARABIC LIGATURE TAH WITH YEH FINAL FORM;Lo;0;AL;<final> 0637 064A;;;;N;;;;; FD13;ARABIC LIGATURE AIN WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0639 0649;;;;N;;;;; FD14;ARABIC LIGATURE AIN WITH YEH FINAL FORM;Lo;0;AL;<final> 0639 064A;;;;N;;;;; FD15;ARABIC LIGATURE GHAIN WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 063A 0649;;;;N;;;;; FD16;ARABIC LIGATURE GHAIN WITH YEH FINAL FORM;Lo;0;AL;<final> 063A 064A;;;;N;;;;; FD17;ARABIC LIGATURE SEEN WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0633 0649;;;;N;;;;; FD18;ARABIC LIGATURE SEEN WITH YEH FINAL FORM;Lo;0;AL;<final> 0633 064A;;;;N;;;;; FD19;ARABIC LIGATURE SHEEN WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0634 0649;;;;N;;;;; FD1A;ARABIC LIGATURE SHEEN WITH YEH FINAL FORM;Lo;0;AL;<final> 0634 064A;;;;N;;;;; FD1B;ARABIC LIGATURE HAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 062D 0649;;;;N;;;;; FD1C;ARABIC LIGATURE HAH WITH YEH FINAL FORM;Lo;0;AL;<final> 062D 064A;;;;N;;;;; FD1D;ARABIC LIGATURE JEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 062C 0649;;;;N;;;;; FD1E;ARABIC LIGATURE JEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 062C 064A;;;;N;;;;; FD1F;ARABIC LIGATURE KHAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 062E 0649;;;;N;;;;; FD20;ARABIC LIGATURE KHAH WITH YEH FINAL FORM;Lo;0;AL;<final> 062E 064A;;;;N;;;;; FD21;ARABIC LIGATURE SAD WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0635 0649;;;;N;;;;; FD22;ARABIC LIGATURE SAD WITH YEH FINAL FORM;Lo;0;AL;<final> 0635 064A;;;;N;;;;; FD23;ARABIC LIGATURE DAD WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0636 0649;;;;N;;;;; FD24;ARABIC LIGATURE DAD WITH YEH FINAL FORM;Lo;0;AL;<final> 0636 064A;;;;N;;;;; FD25;ARABIC LIGATURE SHEEN WITH JEEM FINAL FORM;Lo;0;AL;<final> 0634 062C;;;;N;;;;; FD26;ARABIC LIGATURE SHEEN WITH HAH FINAL FORM;Lo;0;AL;<final> 0634 062D;;;;N;;;;; FD27;ARABIC LIGATURE SHEEN WITH KHAH FINAL FORM;Lo;0;AL;<final> 0634 062E;;;;N;;;;; FD28;ARABIC LIGATURE SHEEN WITH MEEM FINAL FORM;Lo;0;AL;<final> 0634 0645;;;;N;;;;; FD29;ARABIC LIGATURE SHEEN WITH REH FINAL FORM;Lo;0;AL;<final> 0634 0631;;;;N;;;;; FD2A;ARABIC LIGATURE SEEN WITH REH FINAL FORM;Lo;0;AL;<final> 0633 0631;;;;N;;;;; FD2B;ARABIC LIGATURE SAD WITH REH FINAL FORM;Lo;0;AL;<final> 0635 0631;;;;N;;;;; FD2C;ARABIC LIGATURE DAD WITH REH FINAL FORM;Lo;0;AL;<final> 0636 0631;;;;N;;;;; FD2D;ARABIC LIGATURE SHEEN WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0634 062C;;;;N;;;;; FD2E;ARABIC LIGATURE SHEEN WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0634 062D;;;;N;;;;; FD2F;ARABIC LIGATURE SHEEN WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 0634 062E;;;;N;;;;; FD30;ARABIC LIGATURE SHEEN WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0634 0645;;;;N;;;;; FD31;ARABIC LIGATURE SEEN WITH HEH INITIAL FORM;Lo;0;AL;<initial> 0633 0647;;;;N;;;;; FD32;ARABIC LIGATURE SHEEN WITH HEH INITIAL FORM;Lo;0;AL;<initial> 0634 0647;;;;N;;;;; FD33;ARABIC LIGATURE TAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0637 0645;;;;N;;;;; FD34;ARABIC LIGATURE SEEN WITH JEEM MEDIAL FORM;Lo;0;AL;<medial> 0633 062C;;;;N;;;;; FD35;ARABIC LIGATURE SEEN WITH HAH MEDIAL FORM;Lo;0;AL;<medial> 0633 062D;;;;N;;;;; FD36;ARABIC LIGATURE SEEN WITH KHAH MEDIAL FORM;Lo;0;AL;<medial> 0633 062E;;;;N;;;;; FD37;ARABIC LIGATURE SHEEN WITH JEEM MEDIAL FORM;Lo;0;AL;<medial> 0634 062C;;;;N;;;;; FD38;ARABIC LIGATURE SHEEN WITH HAH MEDIAL FORM;Lo;0;AL;<medial> 0634 062D;;;;N;;;;; FD39;ARABIC LIGATURE SHEEN WITH KHAH MEDIAL FORM;Lo;0;AL;<medial> 0634 062E;;;;N;;;;; FD3A;ARABIC LIGATURE TAH WITH MEEM MEDIAL FORM;Lo;0;AL;<medial> 0637 0645;;;;N;;;;; FD3B;ARABIC LIGATURE ZAH WITH MEEM MEDIAL FORM;Lo;0;AL;<medial> 0638 0645;;;;N;;;;; FD3C;ARABIC LIGATURE ALEF WITH FATHATAN FINAL FORM;Lo;0;AL;<final> 0627 064B;;;;N;;;;; FD3D;ARABIC LIGATURE ALEF WITH FATHATAN ISOLATED FORM;Lo;0;AL;<isolated> 0627 064B;;;;N;;;;; FD3E;ORNATE LEFT PARENTHESIS;Pe;0;ON;;;;;N;;;;; FD3F;ORNATE RIGHT PARENTHESIS;Ps;0;ON;;;;;N;;;;; FD50;ARABIC LIGATURE TEH WITH JEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 062A 062C 0645;;;;N;;;;; FD51;ARABIC LIGATURE TEH WITH HAH WITH JEEM FINAL FORM;Lo;0;AL;<final> 062A 062D 062C;;;;N;;;;; FD52;ARABIC LIGATURE TEH WITH HAH WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 062A 062D 062C;;;;N;;;;; FD53;ARABIC LIGATURE TEH WITH HAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 062A 062D 0645;;;;N;;;;; FD54;ARABIC LIGATURE TEH WITH KHAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 062A 062E 0645;;;;N;;;;; FD55;ARABIC LIGATURE TEH WITH MEEM WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 062A 0645 062C;;;;N;;;;; FD56;ARABIC LIGATURE TEH WITH MEEM WITH HAH INITIAL FORM;Lo;0;AL;<initial> 062A 0645 062D;;;;N;;;;; FD57;ARABIC LIGATURE TEH WITH MEEM WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 062A 0645 062E;;;;N;;;;; FD58;ARABIC LIGATURE JEEM WITH MEEM WITH HAH FINAL FORM;Lo;0;AL;<final> 062C 0645 062D;;;;N;;;;; FD59;ARABIC LIGATURE JEEM WITH MEEM WITH HAH INITIAL FORM;Lo;0;AL;<initial> 062C 0645 062D;;;;N;;;;; FD5A;ARABIC LIGATURE HAH WITH MEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 062D 0645 064A;;;;N;;;;; FD5B;ARABIC LIGATURE HAH WITH MEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 062D 0645 0649;;;;N;;;;; FD5C;ARABIC LIGATURE SEEN WITH HAH WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0633 062D 062C;;;;N;;;;; FD5D;ARABIC LIGATURE SEEN WITH JEEM WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0633 062C 062D;;;;N;;;;; FD5E;ARABIC LIGATURE SEEN WITH JEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0633 062C 0649;;;;N;;;;; FD5F;ARABIC LIGATURE SEEN WITH MEEM WITH HAH FINAL FORM;Lo;0;AL;<final> 0633 0645 062D;;;;N;;;;; FD60;ARABIC LIGATURE SEEN WITH MEEM WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0633 0645 062D;;;;N;;;;; FD61;ARABIC LIGATURE SEEN WITH MEEM WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0633 0645 062C;;;;N;;;;; FD62;ARABIC LIGATURE SEEN WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL;<final> 0633 0645 0645;;;;N;;;;; FD63;ARABIC LIGATURE SEEN WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0633 0645 0645;;;;N;;;;; FD64;ARABIC LIGATURE SAD WITH HAH WITH HAH FINAL FORM;Lo;0;AL;<final> 0635 062D 062D;;;;N;;;;; FD65;ARABIC LIGATURE SAD WITH HAH WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0635 062D 062D;;;;N;;;;; FD66;ARABIC LIGATURE SAD WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL;<final> 0635 0645 0645;;;;N;;;;; FD67;ARABIC LIGATURE SHEEN WITH HAH WITH MEEM FINAL FORM;Lo;0;AL;<final> 0634 062D 0645;;;;N;;;;; FD68;ARABIC LIGATURE SHEEN WITH HAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0634 062D 0645;;;;N;;;;; FD69;ARABIC LIGATURE SHEEN WITH JEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 0634 062C 064A;;;;N;;;;; FD6A;ARABIC LIGATURE SHEEN WITH MEEM WITH KHAH FINAL FORM;Lo;0;AL;<final> 0634 0645 062E;;;;N;;;;; FD6B;ARABIC LIGATURE SHEEN WITH MEEM WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 0634 0645 062E;;;;N;;;;; FD6C;ARABIC LIGATURE SHEEN WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL;<final> 0634 0645 0645;;;;N;;;;; FD6D;ARABIC LIGATURE SHEEN WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0634 0645 0645;;;;N;;;;; FD6E;ARABIC LIGATURE DAD WITH HAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0636 062D 0649;;;;N;;;;; FD6F;ARABIC LIGATURE DAD WITH KHAH WITH MEEM FINAL FORM;Lo;0;AL;<final> 0636 062E 0645;;;;N;;;;; FD70;ARABIC LIGATURE DAD WITH KHAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0636 062E 0645;;;;N;;;;; FD71;ARABIC LIGATURE TAH WITH MEEM WITH HAH FINAL FORM;Lo;0;AL;<final> 0637 0645 062D;;;;N;;;;; FD72;ARABIC LIGATURE TAH WITH MEEM WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0637 0645 062D;;;;N;;;;; FD73;ARABIC LIGATURE TAH WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0637 0645 0645;;;;N;;;;; FD74;ARABIC LIGATURE TAH WITH MEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 0637 0645 064A;;;;N;;;;; FD75;ARABIC LIGATURE AIN WITH JEEM WITH MEEM FINAL FORM;Lo;0;AL;<final> 0639 062C 0645;;;;N;;;;; FD76;ARABIC LIGATURE AIN WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL;<final> 0639 0645 0645;;;;N;;;;; FD77;ARABIC LIGATURE AIN WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0639 0645 0645;;;;N;;;;; FD78;ARABIC LIGATURE AIN WITH MEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0639 0645 0649;;;;N;;;;; FD79;ARABIC LIGATURE GHAIN WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL;<final> 063A 0645 0645;;;;N;;;;; FD7A;ARABIC LIGATURE GHAIN WITH MEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 063A 0645 064A;;;;N;;;;; FD7B;ARABIC LIGATURE GHAIN WITH MEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 063A 0645 0649;;;;N;;;;; FD7C;ARABIC LIGATURE FEH WITH KHAH WITH MEEM FINAL FORM;Lo;0;AL;<final> 0641 062E 0645;;;;N;;;;; FD7D;ARABIC LIGATURE FEH WITH KHAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0641 062E 0645;;;;N;;;;; FD7E;ARABIC LIGATURE QAF WITH MEEM WITH HAH FINAL FORM;Lo;0;AL;<final> 0642 0645 062D;;;;N;;;;; FD7F;ARABIC LIGATURE QAF WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL;<final> 0642 0645 0645;;;;N;;;;; FD80;ARABIC LIGATURE LAM WITH HAH WITH MEEM FINAL FORM;Lo;0;AL;<final> 0644 062D 0645;;;;N;;;;; FD81;ARABIC LIGATURE LAM WITH HAH WITH YEH FINAL FORM;Lo;0;AL;<final> 0644 062D 064A;;;;N;;;;; FD82;ARABIC LIGATURE LAM WITH HAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0644 062D 0649;;;;N;;;;; FD83;ARABIC LIGATURE LAM WITH JEEM WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0644 062C 062C;;;;N;;;;; FD84;ARABIC LIGATURE LAM WITH JEEM WITH JEEM FINAL FORM;Lo;0;AL;<final> 0644 062C 062C;;;;N;;;;; FD85;ARABIC LIGATURE LAM WITH KHAH WITH MEEM FINAL FORM;Lo;0;AL;<final> 0644 062E 0645;;;;N;;;;; FD86;ARABIC LIGATURE LAM WITH KHAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0644 062E 0645;;;;N;;;;; FD87;ARABIC LIGATURE LAM WITH MEEM WITH HAH FINAL FORM;Lo;0;AL;<final> 0644 0645 062D;;;;N;;;;; FD88;ARABIC LIGATURE LAM WITH MEEM WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0644 0645 062D;;;;N;;;;; FD89;ARABIC LIGATURE MEEM WITH HAH WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0645 062D 062C;;;;N;;;;; FD8A;ARABIC LIGATURE MEEM WITH HAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0645 062D 0645;;;;N;;;;; FD8B;ARABIC LIGATURE MEEM WITH HAH WITH YEH FINAL FORM;Lo;0;AL;<final> 0645 062D 064A;;;;N;;;;; FD8C;ARABIC LIGATURE MEEM WITH JEEM WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0645 062C 062D;;;;N;;;;; FD8D;ARABIC LIGATURE MEEM WITH JEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0645 062C 0645;;;;N;;;;; FD8E;ARABIC LIGATURE MEEM WITH KHAH WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0645 062E 062C;;;;N;;;;; FD8F;ARABIC LIGATURE MEEM WITH KHAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0645 062E 0645;;;;N;;;;; FD92;ARABIC LIGATURE MEEM WITH JEEM WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 0645 062C 062E;;;;N;;;;; FD93;ARABIC LIGATURE HEH WITH MEEM WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0647 0645 062C;;;;N;;;;; FD94;ARABIC LIGATURE HEH WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0647 0645 0645;;;;N;;;;; FD95;ARABIC LIGATURE NOON WITH HAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0646 062D 0645;;;;N;;;;; FD96;ARABIC LIGATURE NOON WITH HAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0646 062D 0649;;;;N;;;;; FD97;ARABIC LIGATURE NOON WITH JEEM WITH MEEM FINAL FORM;Lo;0;AL;<final> 0646 062C 0645;;;;N;;;;; FD98;ARABIC LIGATURE NOON WITH JEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0646 062C 0645;;;;N;;;;; FD99;ARABIC LIGATURE NOON WITH JEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0646 062C 0649;;;;N;;;;; FD9A;ARABIC LIGATURE NOON WITH MEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 0646 0645 064A;;;;N;;;;; FD9B;ARABIC LIGATURE NOON WITH MEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0646 0645 0649;;;;N;;;;; FD9C;ARABIC LIGATURE YEH WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL;<final> 064A 0645 0645;;;;N;;;;; FD9D;ARABIC LIGATURE YEH WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 064A 0645 0645;;;;N;;;;; FD9E;ARABIC LIGATURE BEH WITH KHAH WITH YEH FINAL FORM;Lo;0;AL;<final> 0628 062E 064A;;;;N;;;;; FD9F;ARABIC LIGATURE TEH WITH JEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 062A 062C 064A;;;;N;;;;; FDA0;ARABIC LIGATURE TEH WITH JEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 062A 062C 0649;;;;N;;;;; FDA1;ARABIC LIGATURE TEH WITH KHAH WITH YEH FINAL FORM;Lo;0;AL;<final> 062A 062E 064A;;;;N;;;;; FDA2;ARABIC LIGATURE TEH WITH KHAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 062A 062E 0649;;;;N;;;;; FDA3;ARABIC LIGATURE TEH WITH MEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 062A 0645 064A;;;;N;;;;; FDA4;ARABIC LIGATURE TEH WITH MEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 062A 0645 0649;;;;N;;;;; FDA5;ARABIC LIGATURE JEEM WITH MEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 062C 0645 064A;;;;N;;;;; FDA6;ARABIC LIGATURE JEEM WITH HAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 062C 062D 0649;;;;N;;;;; FDA7;ARABIC LIGATURE JEEM WITH MEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 062C 0645 0649;;;;N;;;;; FDA8;ARABIC LIGATURE SEEN WITH KHAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0633 062E 0649;;;;N;;;;; FDA9;ARABIC LIGATURE SAD WITH HAH WITH YEH FINAL FORM;Lo;0;AL;<final> 0635 062D 064A;;;;N;;;;; FDAA;ARABIC LIGATURE SHEEN WITH HAH WITH YEH FINAL FORM;Lo;0;AL;<final> 0634 062D 064A;;;;N;;;;; FDAB;ARABIC LIGATURE DAD WITH HAH WITH YEH FINAL FORM;Lo;0;AL;<final> 0636 062D 064A;;;;N;;;;; FDAC;ARABIC LIGATURE LAM WITH JEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 0644 062C 064A;;;;N;;;;; FDAD;ARABIC LIGATURE LAM WITH MEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 0644 0645 064A;;;;N;;;;; FDAE;ARABIC LIGATURE YEH WITH HAH WITH YEH FINAL FORM;Lo;0;AL;<final> 064A 062D 064A;;;;N;;;;; FDAF;ARABIC LIGATURE YEH WITH JEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 064A 062C 064A;;;;N;;;;; FDB0;ARABIC LIGATURE YEH WITH MEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 064A 0645 064A;;;;N;;;;; FDB1;ARABIC LIGATURE MEEM WITH MEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 0645 0645 064A;;;;N;;;;; FDB2;ARABIC LIGATURE QAF WITH MEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 0642 0645 064A;;;;N;;;;; FDB3;ARABIC LIGATURE NOON WITH HAH WITH YEH FINAL FORM;Lo;0;AL;<final> 0646 062D 064A;;;;N;;;;; FDB4;ARABIC LIGATURE QAF WITH MEEM WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0642 0645 062D;;;;N;;;;; FDB5;ARABIC LIGATURE LAM WITH HAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0644 062D 0645;;;;N;;;;; FDB6;ARABIC LIGATURE AIN WITH MEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 0639 0645 064A;;;;N;;;;; FDB7;ARABIC LIGATURE KAF WITH MEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 0643 0645 064A;;;;N;;;;; FDB8;ARABIC LIGATURE NOON WITH JEEM WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0646 062C 062D;;;;N;;;;; FDB9;ARABIC LIGATURE MEEM WITH KHAH WITH YEH FINAL FORM;Lo;0;AL;<final> 0645 062E 064A;;;;N;;;;; FDBA;ARABIC LIGATURE LAM WITH JEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0644 062C 0645;;;;N;;;;; FDBB;ARABIC LIGATURE KAF WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL;<final> 0643 0645 0645;;;;N;;;;; FDBC;ARABIC LIGATURE LAM WITH JEEM WITH MEEM FINAL FORM;Lo;0;AL;<final> 0644 062C 0645;;;;N;;;;; FDBD;ARABIC LIGATURE NOON WITH JEEM WITH HAH FINAL FORM;Lo;0;AL;<final> 0646 062C 062D;;;;N;;;;; FDBE;ARABIC LIGATURE JEEM WITH HAH WITH YEH FINAL FORM;Lo;0;AL;<final> 062C 062D 064A;;;;N;;;;; FDBF;ARABIC LIGATURE HAH WITH JEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 062D 062C 064A;;;;N;;;;; FDC0;ARABIC LIGATURE MEEM WITH JEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 0645 062C 064A;;;;N;;;;; FDC1;ARABIC LIGATURE FEH WITH MEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 0641 0645 064A;;;;N;;;;; FDC2;ARABIC LIGATURE BEH WITH HAH WITH YEH FINAL FORM;Lo;0;AL;<final> 0628 062D 064A;;;;N;;;;; FDC3;ARABIC LIGATURE KAF WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0643 0645 0645;;;;N;;;;; FDC4;ARABIC LIGATURE AIN WITH JEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0639 062C 0645;;;;N;;;;; FDC5;ARABIC LIGATURE SAD WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0635 0645 0645;;;;N;;;;; FDC6;ARABIC LIGATURE SEEN WITH KHAH WITH YEH FINAL FORM;Lo;0;AL;<final> 0633 062E 064A;;;;N;;;;; FDC7;ARABIC LIGATURE NOON WITH JEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 0646 062C 064A;;;;N;;;;; FDF0;ARABIC LIGATURE SALLA USED AS KORANIC STOP SIGN ISOLATED FORM;Lo;0;AL;<isolated> 0635 0644 06D2;;;;N;;;;; FDF1;ARABIC LIGATURE QALA USED AS KORANIC STOP SIGN ISOLATED FORM;Lo;0;AL;<isolated> 0642 0644 06D2;;;;N;;;;; FDF2;ARABIC LIGATURE ALLAH ISOLATED FORM;Lo;0;AL;<isolated> 0627 0644 0644 0647;;;;N;;;;; FDF3;ARABIC LIGATURE AKBAR ISOLATED FORM;Lo;0;AL;<isolated> 0627 0643 0628 0631;;;;N;;;;; FDF4;ARABIC LIGATURE MOHAMMAD ISOLATED FORM;Lo;0;AL;<isolated> 0645 062D 0645 062F;;;;N;;;;; FDF5;ARABIC LIGATURE SALAM ISOLATED FORM;Lo;0;AL;<isolated> 0635 0644 0639 0645;;;;N;;;;; FDF6;ARABIC LIGATURE RASOUL ISOLATED FORM;Lo;0;AL;<isolated> 0631 0633 0648 0644;;;;N;;;;; FDF7;ARABIC LIGATURE ALAYHE ISOLATED FORM;Lo;0;AL;<isolated> 0639 0644 064A 0647;;;;N;;;;; FDF8;ARABIC LIGATURE WASALLAM ISOLATED FORM;Lo;0;AL;<isolated> 0648 0633 0644 0645;;;;N;;;;; FDF9;ARABIC LIGATURE SALLA ISOLATED FORM;Lo;0;AL;<isolated> 0635 0644 0649;;;;N;;;;; FDFA;ARABIC LIGATURE SALLALLAHOU ALAYHE WASALLAM;Lo;0;AL;<isolated> 0635 0644 0649 0020 0627 0644 0644 0647 0020 0639 0644 064A 0647 0020 0648 0633 0644 0645;;;;N;ARABIC LETTER SALLALLAHOU ALAYHE WASALLAM;;;; FDFB;ARABIC LIGATURE JALLAJALALOUHOU;Lo;0;AL;<isolated> 062C 0644 0020 062C 0644 0627 0644 0647;;;;N;ARABIC LETTER JALLAJALALOUHOU;;;; FDFC;RIAL SIGN;Sc;0;AL;<isolated> 0631 06CC 0627 0644;;;;N;;;;; FDFD;ARABIC LIGATURE BISMILLAH AR-RAHMAN AR-RAHEEM;So;0;ON;;;;;N;;;;; FE00;VARIATION SELECTOR-1;Mn;0;NSM;;;;;N;;;;; FE01;VARIATION SELECTOR-2;Mn;0;NSM;;;;;N;;;;; FE02;VARIATION SELECTOR-3;Mn;0;NSM;;;;;N;;;;; FE03;VARIATION SELECTOR-4;Mn;0;NSM;;;;;N;;;;; FE04;VARIATION SELECTOR-5;Mn;0;NSM;;;;;N;;;;; FE05;VARIATION SELECTOR-6;Mn;0;NSM;;;;;N;;;;; FE06;VARIATION SELECTOR-7;Mn;0;NSM;;;;;N;;;;; FE07;VARIATION SELECTOR-8;Mn;0;NSM;;;;;N;;;;; FE08;VARIATION SELECTOR-9;Mn;0;NSM;;;;;N;;;;; FE09;VARIATION SELECTOR-10;Mn;0;NSM;;;;;N;;;;; FE0A;VARIATION SELECTOR-11;Mn;0;NSM;;;;;N;;;;; FE0B;VARIATION SELECTOR-12;Mn;0;NSM;;;;;N;;;;; FE0C;VARIATION SELECTOR-13;Mn;0;NSM;;;;;N;;;;; FE0D;VARIATION SELECTOR-14;Mn;0;NSM;;;;;N;;;;; FE0E;VARIATION SELECTOR-15;Mn;0;NSM;;;;;N;;;;; FE0F;VARIATION SELECTOR-16;Mn;0;NSM;;;;;N;;;;; FE10;PRESENTATION FORM FOR VERTICAL COMMA;Po;0;ON;<vertical> 002C;;;;N;;;;; FE11;PRESENTATION FORM FOR VERTICAL IDEOGRAPHIC COMMA;Po;0;ON;<vertical> 3001;;;;N;;;;; FE12;PRESENTATION FORM FOR VERTICAL IDEOGRAPHIC FULL STOP;Po;0;ON;<vertical> 3002;;;;N;;;;; FE13;PRESENTATION FORM FOR VERTICAL COLON;Po;0;ON;<vertical> 003A;;;;N;;;;; FE14;PRESENTATION FORM FOR VERTICAL SEMICOLON;Po;0;ON;<vertical> 003B;;;;N;;;;; FE15;PRESENTATION FORM FOR VERTICAL EXCLAMATION MARK;Po;0;ON;<vertical> 0021;;;;N;;;;; FE16;PRESENTATION FORM FOR VERTICAL QUESTION MARK;Po;0;ON;<vertical> 003F;;;;N;;;;; FE17;PRESENTATION FORM FOR VERTICAL LEFT WHITE LENTICULAR BRACKET;Ps;0;ON;<vertical> 3016;;;;N;;;;; FE18;PRESENTATION FORM FOR VERTICAL RIGHT WHITE LENTICULAR BRAKCET;Pe;0;ON;<vertical> 3017;;;;N;;;;; FE19;PRESENTATION FORM FOR VERTICAL HORIZONTAL ELLIPSIS;Po;0;ON;<vertical> 2026;;;;N;;;;; FE20;COMBINING LIGATURE LEFT HALF;Mn;230;NSM;;;;;N;;;;; FE21;COMBINING LIGATURE RIGHT HALF;Mn;230;NSM;;;;;N;;;;; FE22;COMBINING DOUBLE TILDE LEFT HALF;Mn;230;NSM;;;;;N;;;;; FE23;COMBINING DOUBLE TILDE RIGHT HALF;Mn;230;NSM;;;;;N;;;;; FE24;COMBINING MACRON LEFT HALF;Mn;230;NSM;;;;;N;;;;; FE25;COMBINING MACRON RIGHT HALF;Mn;230;NSM;;;;;N;;;;; FE26;COMBINING CONJOINING MACRON;Mn;230;NSM;;;;;N;;;;; FE27;COMBINING LIGATURE LEFT HALF BELOW;Mn;220;NSM;;;;;N;;;;; FE28;COMBINING LIGATURE RIGHT HALF BELOW;Mn;220;NSM;;;;;N;;;;; FE29;COMBINING TILDE LEFT HALF BELOW;Mn;220;NSM;;;;;N;;;;; FE2A;COMBINING TILDE RIGHT HALF BELOW;Mn;220;NSM;;;;;N;;;;; FE2B;COMBINING MACRON LEFT HALF BELOW;Mn;220;NSM;;;;;N;;;;; FE2C;COMBINING MACRON RIGHT HALF BELOW;Mn;220;NSM;;;;;N;;;;; FE2D;COMBINING CONJOINING MACRON BELOW;Mn;220;NSM;;;;;N;;;;; FE2E;COMBINING CYRILLIC TITLO LEFT HALF;Mn;230;NSM;;;;;N;;;;; FE2F;COMBINING CYRILLIC TITLO RIGHT HALF;Mn;230;NSM;;;;;N;;;;; FE30;PRESENTATION FORM FOR VERTICAL TWO DOT LEADER;Po;0;ON;<vertical> 2025;;;;N;GLYPH FOR VERTICAL TWO DOT LEADER;;;; FE31;PRESENTATION FORM FOR VERTICAL EM DASH;Pd;0;ON;<vertical> 2014;;;;N;GLYPH FOR VERTICAL EM DASH;;;; FE32;PRESENTATION FORM FOR VERTICAL EN DASH;Pd;0;ON;<vertical> 2013;;;;N;GLYPH FOR VERTICAL EN DASH;;;; FE33;PRESENTATION FORM FOR VERTICAL LOW LINE;Pc;0;ON;<vertical> 005F;;;;N;GLYPH FOR VERTICAL SPACING UNDERSCORE;;;; FE34;PRESENTATION FORM FOR VERTICAL WAVY LOW LINE;Pc;0;ON;<vertical> 005F;;;;N;GLYPH FOR VERTICAL SPACING WAVY UNDERSCORE;;;; FE35;PRESENTATION FORM FOR VERTICAL LEFT PARENTHESIS;Ps;0;ON;<vertical> 0028;;;;N;GLYPH FOR VERTICAL OPENING PARENTHESIS;;;; FE36;PRESENTATION FORM FOR VERTICAL RIGHT PARENTHESIS;Pe;0;ON;<vertical> 0029;;;;N;GLYPH FOR VERTICAL CLOSING PARENTHESIS;;;; FE37;PRESENTATION FORM FOR VERTICAL LEFT CURLY BRACKET;Ps;0;ON;<vertical> 007B;;;;N;GLYPH FOR VERTICAL OPENING CURLY BRACKET;;;; FE38;PRESENTATION FORM FOR VERTICAL RIGHT CURLY BRACKET;Pe;0;ON;<vertical> 007D;;;;N;GLYPH FOR VERTICAL CLOSING CURLY BRACKET;;;; FE39;PRESENTATION FORM FOR VERTICAL LEFT TORTOISE SHELL BRACKET;Ps;0;ON;<vertical> 3014;;;;N;GLYPH FOR VERTICAL OPENING TORTOISE SHELL BRACKET;;;; FE3A;PRESENTATION FORM FOR VERTICAL RIGHT TORTOISE SHELL BRACKET;Pe;0;ON;<vertical> 3015;;;;N;GLYPH FOR VERTICAL CLOSING TORTOISE SHELL BRACKET;;;; FE3B;PRESENTATION FORM FOR VERTICAL LEFT BLACK LENTICULAR BRACKET;Ps;0;ON;<vertical> 3010;;;;N;GLYPH FOR VERTICAL OPENING BLACK LENTICULAR BRACKET;;;; FE3C;PRESENTATION FORM FOR VERTICAL RIGHT BLACK LENTICULAR BRACKET;Pe;0;ON;<vertical> 3011;;;;N;GLYPH FOR VERTICAL CLOSING BLACK LENTICULAR BRACKET;;;; FE3D;PRESENTATION FORM FOR VERTICAL LEFT DOUBLE ANGLE BRACKET;Ps;0;ON;<vertical> 300A;;;;N;GLYPH FOR VERTICAL OPENING DOUBLE ANGLE BRACKET;;;; FE3E;PRESENTATION FORM FOR VERTICAL RIGHT DOUBLE ANGLE BRACKET;Pe;0;ON;<vertical> 300B;;;;N;GLYPH FOR VERTICAL CLOSING DOUBLE ANGLE BRACKET;;;; FE3F;PRESENTATION FORM FOR VERTICAL LEFT ANGLE BRACKET;Ps;0;ON;<vertical> 3008;;;;N;GLYPH FOR VERTICAL OPENING ANGLE BRACKET;;;; FE40;PRESENTATION FORM FOR VERTICAL RIGHT ANGLE BRACKET;Pe;0;ON;<vertical> 3009;;;;N;GLYPH FOR VERTICAL CLOSING ANGLE BRACKET;;;; FE41;PRESENTATION FORM FOR VERTICAL LEFT CORNER BRACKET;Ps;0;ON;<vertical> 300C;;;;N;GLYPH FOR VERTICAL OPENING CORNER BRACKET;;;; FE42;PRESENTATION FORM FOR VERTICAL RIGHT CORNER BRACKET;Pe;0;ON;<vertical> 300D;;;;N;GLYPH FOR VERTICAL CLOSING CORNER BRACKET;;;; FE43;PRESENTATION FORM FOR VERTICAL LEFT WHITE CORNER BRACKET;Ps;0;ON;<vertical> 300E;;;;N;GLYPH FOR VERTICAL OPENING WHITE CORNER BRACKET;;;; FE44;PRESENTATION FORM FOR VERTICAL RIGHT WHITE CORNER BRACKET;Pe;0;ON;<vertical> 300F;;;;N;GLYPH FOR VERTICAL CLOSING WHITE CORNER BRACKET;;;; FE45;SESAME DOT;Po;0;ON;;;;;N;;;;; FE46;WHITE SESAME DOT;Po;0;ON;;;;;N;;;;; FE47;PRESENTATION FORM FOR VERTICAL LEFT SQUARE BRACKET;Ps;0;ON;<vertical> 005B;;;;N;;;;; FE48;PRESENTATION FORM FOR VERTICAL RIGHT SQUARE BRACKET;Pe;0;ON;<vertical> 005D;;;;N;;;;; FE49;DASHED OVERLINE;Po;0;ON;<compat> 203E;;;;N;SPACING DASHED OVERSCORE;;;; FE4A;CENTRELINE OVERLINE;Po;0;ON;<compat> 203E;;;;N;SPACING CENTERLINE OVERSCORE;;;; FE4B;WAVY OVERLINE;Po;0;ON;<compat> 203E;;;;N;SPACING WAVY OVERSCORE;;;; FE4C;DOUBLE WAVY OVERLINE;Po;0;ON;<compat> 203E;;;;N;SPACING DOUBLE WAVY OVERSCORE;;;; FE4D;DASHED LOW LINE;Pc;0;ON;<compat> 005F;;;;N;SPACING DASHED UNDERSCORE;;;; FE4E;CENTRELINE LOW LINE;Pc;0;ON;<compat> 005F;;;;N;SPACING CENTERLINE UNDERSCORE;;;; FE4F;WAVY LOW LINE;Pc;0;ON;<compat> 005F;;;;N;SPACING WAVY UNDERSCORE;;;; FE50;SMALL COMMA;Po;0;CS;<small> 002C;;;;N;;;;; FE51;SMALL IDEOGRAPHIC COMMA;Po;0;ON;<small> 3001;;;;N;;;;; FE52;SMALL FULL STOP;Po;0;CS;<small> 002E;;;;N;SMALL PERIOD;;;; FE54;SMALL SEMICOLON;Po;0;ON;<small> 003B;;;;N;;;;; FE55;SMALL COLON;Po;0;CS;<small> 003A;;;;N;;;;; FE56;SMALL QUESTION MARK;Po;0;ON;<small> 003F;;;;N;;;;; FE57;SMALL EXCLAMATION MARK;Po;0;ON;<small> 0021;;;;N;;;;; FE58;SMALL EM DASH;Pd;0;ON;<small> 2014;;;;N;;;;; FE59;SMALL LEFT PARENTHESIS;Ps;0;ON;<small> 0028;;;;Y;SMALL OPENING PARENTHESIS;;;; FE5A;SMALL RIGHT PARENTHESIS;Pe;0;ON;<small> 0029;;;;Y;SMALL CLOSING PARENTHESIS;;;; FE5B;SMALL LEFT CURLY BRACKET;Ps;0;ON;<small> 007B;;;;Y;SMALL OPENING CURLY BRACKET;;;; FE5C;SMALL RIGHT CURLY BRACKET;Pe;0;ON;<small> 007D;;;;Y;SMALL CLOSING CURLY BRACKET;;;; FE5D;SMALL LEFT TORTOISE SHELL BRACKET;Ps;0;ON;<small> 3014;;;;Y;SMALL OPENING TORTOISE SHELL BRACKET;;;; FE5E;SMALL RIGHT TORTOISE SHELL BRACKET;Pe;0;ON;<small> 3015;;;;Y;SMALL CLOSING TORTOISE SHELL BRACKET;;;; FE5F;SMALL NUMBER SIGN;Po;0;ET;<small> 0023;;;;N;;;;; FE60;SMALL AMPERSAND;Po;0;ON;<small> 0026;;;;N;;;;; FE61;SMALL ASTERISK;Po;0;ON;<small> 002A;;;;N;;;;; FE62;SMALL PLUS SIGN;Sm;0;ES;<small> 002B;;;;N;;;;; FE63;SMALL HYPHEN-MINUS;Pd;0;ES;<small> 002D;;;;N;;;;; FE64;SMALL LESS-THAN SIGN;Sm;0;ON;<small> 003C;;;;Y;;;;; FE65;SMALL GREATER-THAN SIGN;Sm;0;ON;<small> 003E;;;;Y;;;;; FE66;SMALL EQUALS SIGN;Sm;0;ON;<small> 003D;;;;N;;;;; FE68;SMALL REVERSE SOLIDUS;Po;0;ON;<small> 005C;;;;N;SMALL BACKSLASH;;;; FE69;SMALL DOLLAR SIGN;Sc;0;ET;<small> 0024;;;;N;;;;; FE6A;SMALL PERCENT SIGN;Po;0;ET;<small> 0025;;;;N;;;;; FE6B;SMALL COMMERCIAL AT;Po;0;ON;<small> 0040;;;;N;;;;; FE70;ARABIC FATHATAN ISOLATED FORM;Lo;0;AL;<isolated> 0020 064B;;;;N;ARABIC SPACING FATHATAN;;;; FE71;ARABIC TATWEEL WITH FATHATAN ABOVE;Lo;0;AL;<medial> 0640 064B;;;;N;ARABIC FATHATAN ON TATWEEL;;;; FE72;ARABIC DAMMATAN ISOLATED FORM;Lo;0;AL;<isolated> 0020 064C;;;;N;ARABIC SPACING DAMMATAN;;;; FE73;ARABIC TAIL FRAGMENT;Lo;0;AL;;;;;N;;;;; FE74;ARABIC KASRATAN ISOLATED FORM;Lo;0;AL;<isolated> 0020 064D;;;;N;ARABIC SPACING KASRATAN;;;; FE76;ARABIC FATHA ISOLATED FORM;Lo;0;AL;<isolated> 0020 064E;;;;N;ARABIC SPACING FATHAH;;;; FE77;ARABIC FATHA MEDIAL FORM;Lo;0;AL;<medial> 0640 064E;;;;N;ARABIC FATHAH ON TATWEEL;;;; FE78;ARABIC DAMMA ISOLATED FORM;Lo;0;AL;<isolated> 0020 064F;;;;N;ARABIC SPACING DAMMAH;;;; FE79;ARABIC DAMMA MEDIAL FORM;Lo;0;AL;<medial> 0640 064F;;;;N;ARABIC DAMMAH ON TATWEEL;;;; FE7A;ARABIC KASRA ISOLATED FORM;Lo;0;AL;<isolated> 0020 0650;;;;N;ARABIC SPACING KASRAH;;;; FE7B;ARABIC KASRA MEDIAL FORM;Lo;0;AL;<medial> 0640 0650;;;;N;ARABIC KASRAH ON TATWEEL;;;; FE7C;ARABIC SHADDA ISOLATED FORM;Lo;0;AL;<isolated> 0020 0651;;;;N;ARABIC SPACING SHADDAH;;;; FE7D;ARABIC SHADDA MEDIAL FORM;Lo;0;AL;<medial> 0640 0651;;;;N;ARABIC SHADDAH ON TATWEEL;;;; FE7E;ARABIC SUKUN ISOLATED FORM;Lo;0;AL;<isolated> 0020 0652;;;;N;ARABIC SPACING SUKUN;;;; FE7F;ARABIC SUKUN MEDIAL FORM;Lo;0;AL;<medial> 0640 0652;;;;N;ARABIC SUKUN ON TATWEEL;;;; FE80;ARABIC LETTER HAMZA ISOLATED FORM;Lo;0;AL;<isolated> 0621;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH;;;; FE81;ARABIC LETTER ALEF WITH MADDA ABOVE ISOLATED FORM;Lo;0;AL;<isolated> 0622;;;;N;GLYPH FOR ISOLATE ARABIC MADDAH ON ALEF;;;; FE82;ARABIC LETTER ALEF WITH MADDA ABOVE FINAL FORM;Lo;0;AL;<final> 0622;;;;N;GLYPH FOR FINAL ARABIC MADDAH ON ALEF;;;; FE83;ARABIC LETTER ALEF WITH HAMZA ABOVE ISOLATED FORM;Lo;0;AL;<isolated> 0623;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH ON ALEF;;;; FE84;ARABIC LETTER ALEF WITH HAMZA ABOVE FINAL FORM;Lo;0;AL;<final> 0623;;;;N;GLYPH FOR FINAL ARABIC HAMZAH ON ALEF;;;; FE85;ARABIC LETTER WAW WITH HAMZA ABOVE ISOLATED FORM;Lo;0;AL;<isolated> 0624;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH ON WAW;;;; FE86;ARABIC LETTER WAW WITH HAMZA ABOVE FINAL FORM;Lo;0;AL;<final> 0624;;;;N;GLYPH FOR FINAL ARABIC HAMZAH ON WAW;;;; FE87;ARABIC LETTER ALEF WITH HAMZA BELOW ISOLATED FORM;Lo;0;AL;<isolated> 0625;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH UNDER ALEF;;;; FE88;ARABIC LETTER ALEF WITH HAMZA BELOW FINAL FORM;Lo;0;AL;<final> 0625;;;;N;GLYPH FOR FINAL ARABIC HAMZAH UNDER ALEF;;;; FE89;ARABIC LETTER YEH WITH HAMZA ABOVE ISOLATED FORM;Lo;0;AL;<isolated> 0626;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH ON YA;;;; FE8A;ARABIC LETTER YEH WITH HAMZA ABOVE FINAL FORM;Lo;0;AL;<final> 0626;;;;N;GLYPH FOR FINAL ARABIC HAMZAH ON YA;;;; FE8B;ARABIC LETTER YEH WITH HAMZA ABOVE INITIAL FORM;Lo;0;AL;<initial> 0626;;;;N;GLYPH FOR INITIAL ARABIC HAMZAH ON YA;;;; FE8C;ARABIC LETTER YEH WITH HAMZA ABOVE MEDIAL FORM;Lo;0;AL;<medial> 0626;;;;N;GLYPH FOR MEDIAL ARABIC HAMZAH ON YA;;;; FE8D;ARABIC LETTER ALEF ISOLATED FORM;Lo;0;AL;<isolated> 0627;;;;N;GLYPH FOR ISOLATE ARABIC ALEF;;;; FE8E;ARABIC LETTER ALEF FINAL FORM;Lo;0;AL;<final> 0627;;;;N;GLYPH FOR FINAL ARABIC ALEF;;;; FE8F;ARABIC LETTER BEH ISOLATED FORM;Lo;0;AL;<isolated> 0628;;;;N;GLYPH FOR ISOLATE ARABIC BAA;;;; FE90;ARABIC LETTER BEH FINAL FORM;Lo;0;AL;<final> 0628;;;;N;GLYPH FOR FINAL ARABIC BAA;;;; FE91;ARABIC LETTER BEH INITIAL FORM;Lo;0;AL;<initial> 0628;;;;N;GLYPH FOR INITIAL ARABIC BAA;;;; FE92;ARABIC LETTER BEH MEDIAL FORM;Lo;0;AL;<medial> 0628;;;;N;GLYPH FOR MEDIAL ARABIC BAA;;;; FE93;ARABIC LETTER TEH MARBUTA ISOLATED FORM;Lo;0;AL;<isolated> 0629;;;;N;GLYPH FOR ISOLATE ARABIC TAA MARBUTAH;;;; FE94;ARABIC LETTER TEH MARBUTA FINAL FORM;Lo;0;AL;<final> 0629;;;;N;GLYPH FOR FINAL ARABIC TAA MARBUTAH;;;; FE95;ARABIC LETTER TEH ISOLATED FORM;Lo;0;AL;<isolated> 062A;;;;N;GLYPH FOR ISOLATE ARABIC TAA;;;; FE96;ARABIC LETTER TEH FINAL FORM;Lo;0;AL;<final> 062A;;;;N;GLYPH FOR FINAL ARABIC TAA;;;; FE97;ARABIC LETTER TEH INITIAL FORM;Lo;0;AL;<initial> 062A;;;;N;GLYPH FOR INITIAL ARABIC TAA;;;; FE98;ARABIC LETTER TEH MEDIAL FORM;Lo;0;AL;<medial> 062A;;;;N;GLYPH FOR MEDIAL ARABIC TAA;;;; FE99;ARABIC LETTER THEH ISOLATED FORM;Lo;0;AL;<isolated> 062B;;;;N;GLYPH FOR ISOLATE ARABIC THAA;;;; FE9A;ARABIC LETTER THEH FINAL FORM;Lo;0;AL;<final> 062B;;;;N;GLYPH FOR FINAL ARABIC THAA;;;; FE9B;ARABIC LETTER THEH INITIAL FORM;Lo;0;AL;<initial> 062B;;;;N;GLYPH FOR INITIAL ARABIC THAA;;;; FE9C;ARABIC LETTER THEH MEDIAL FORM;Lo;0;AL;<medial> 062B;;;;N;GLYPH FOR MEDIAL ARABIC THAA;;;; FE9D;ARABIC LETTER JEEM ISOLATED FORM;Lo;0;AL;<isolated> 062C;;;;N;GLYPH FOR ISOLATE ARABIC JEEM;;;; FE9E;ARABIC LETTER JEEM FINAL FORM;Lo;0;AL;<final> 062C;;;;N;GLYPH FOR FINAL ARABIC JEEM;;;; FE9F;ARABIC LETTER JEEM INITIAL FORM;Lo;0;AL;<initial> 062C;;;;N;GLYPH FOR INITIAL ARABIC JEEM;;;; FEA0;ARABIC LETTER JEEM MEDIAL FORM;Lo;0;AL;<medial> 062C;;;;N;GLYPH FOR MEDIAL ARABIC JEEM;;;; FEA1;ARABIC LETTER HAH ISOLATED FORM;Lo;0;AL;<isolated> 062D;;;;N;GLYPH FOR ISOLATE ARABIC HAA;;;; FEA2;ARABIC LETTER HAH FINAL FORM;Lo;0;AL;<final> 062D;;;;N;GLYPH FOR FINAL ARABIC HAA;;;; FEA3;ARABIC LETTER HAH INITIAL FORM;Lo;0;AL;<initial> 062D;;;;N;GLYPH FOR INITIAL ARABIC HAA;;;; FEA4;ARABIC LETTER HAH MEDIAL FORM;Lo;0;AL;<medial> 062D;;;;N;GLYPH FOR MEDIAL ARABIC HAA;;;; FEA5;ARABIC LETTER KHAH ISOLATED FORM;Lo;0;AL;<isolated> 062E;;;;N;GLYPH FOR ISOLATE ARABIC KHAA;;;; FEA6;ARABIC LETTER KHAH FINAL FORM;Lo;0;AL;<final> 062E;;;;N;GLYPH FOR FINAL ARABIC KHAA;;;; FEA7;ARABIC LETTER KHAH INITIAL FORM;Lo;0;AL;<initial> 062E;;;;N;GLYPH FOR INITIAL ARABIC KHAA;;;; FEA8;ARABIC LETTER KHAH MEDIAL FORM;Lo;0;AL;<medial> 062E;;;;N;GLYPH FOR MEDIAL ARABIC KHAA;;;; FEA9;ARABIC LETTER DAL ISOLATED FORM;Lo;0;AL;<isolated> 062F;;;;N;GLYPH FOR ISOLATE ARABIC DAL;;;; FEAA;ARABIC LETTER DAL FINAL FORM;Lo;0;AL;<final> 062F;;;;N;GLYPH FOR FINAL ARABIC DAL;;;; FEAB;ARABIC LETTER THAL ISOLATED FORM;Lo;0;AL;<isolated> 0630;;;;N;GLYPH FOR ISOLATE ARABIC THAL;;;; FEAC;ARABIC LETTER THAL FINAL FORM;Lo;0;AL;<final> 0630;;;;N;GLYPH FOR FINAL ARABIC THAL;;;; FEAD;ARABIC LETTER REH ISOLATED FORM;Lo;0;AL;<isolated> 0631;;;;N;GLYPH FOR ISOLATE ARABIC RA;;;; FEAE;ARABIC LETTER REH FINAL FORM;Lo;0;AL;<final> 0631;;;;N;GLYPH FOR FINAL ARABIC RA;;;; FEAF;ARABIC LETTER ZAIN ISOLATED FORM;Lo;0;AL;<isolated> 0632;;;;N;GLYPH FOR ISOLATE ARABIC ZAIN;;;; FEB0;ARABIC LETTER ZAIN FINAL FORM;Lo;0;AL;<final> 0632;;;;N;GLYPH FOR FINAL ARABIC ZAIN;;;; FEB1;ARABIC LETTER SEEN ISOLATED FORM;Lo;0;AL;<isolated> 0633;;;;N;GLYPH FOR ISOLATE ARABIC SEEN;;;; FEB2;ARABIC LETTER SEEN FINAL FORM;Lo;0;AL;<final> 0633;;;;N;GLYPH FOR FINAL ARABIC SEEN;;;; FEB3;ARABIC LETTER SEEN INITIAL FORM;Lo;0;AL;<initial> 0633;;;;N;GLYPH FOR INITIAL ARABIC SEEN;;;; FEB4;ARABIC LETTER SEEN MEDIAL FORM;Lo;0;AL;<medial> 0633;;;;N;GLYPH FOR MEDIAL ARABIC SEEN;;;; FEB5;ARABIC LETTER SHEEN ISOLATED FORM;Lo;0;AL;<isolated> 0634;;;;N;GLYPH FOR ISOLATE ARABIC SHEEN;;;; FEB6;ARABIC LETTER SHEEN FINAL FORM;Lo;0;AL;<final> 0634;;;;N;GLYPH FOR FINAL ARABIC SHEEN;;;; FEB7;ARABIC LETTER SHEEN INITIAL FORM;Lo;0;AL;<initial> 0634;;;;N;GLYPH FOR INITIAL ARABIC SHEEN;;;; FEB8;ARABIC LETTER SHEEN MEDIAL FORM;Lo;0;AL;<medial> 0634;;;;N;GLYPH FOR MEDIAL ARABIC SHEEN;;;; FEB9;ARABIC LETTER SAD ISOLATED FORM;Lo;0;AL;<isolated> 0635;;;;N;GLYPH FOR ISOLATE ARABIC SAD;;;; FEBA;ARABIC LETTER SAD FINAL FORM;Lo;0;AL;<final> 0635;;;;N;GLYPH FOR FINAL ARABIC SAD;;;; FEBB;ARABIC LETTER SAD INITIAL FORM;Lo;0;AL;<initial> 0635;;;;N;GLYPH FOR INITIAL ARABIC SAD;;;; FEBC;ARABIC LETTER SAD MEDIAL FORM;Lo;0;AL;<medial> 0635;;;;N;GLYPH FOR MEDIAL ARABIC SAD;;;; FEBD;ARABIC LETTER DAD ISOLATED FORM;Lo;0;AL;<isolated> 0636;;;;N;GLYPH FOR ISOLATE ARABIC DAD;;;; FEBE;ARABIC LETTER DAD FINAL FORM;Lo;0;AL;<final> 0636;;;;N;GLYPH FOR FINAL ARABIC DAD;;;; FEBF;ARABIC LETTER DAD INITIAL FORM;Lo;0;AL;<initial> 0636;;;;N;GLYPH FOR INITIAL ARABIC DAD;;;; FEC0;ARABIC LETTER DAD MEDIAL FORM;Lo;0;AL;<medial> 0636;;;;N;GLYPH FOR MEDIAL ARABIC DAD;;;; FEC1;ARABIC LETTER TAH ISOLATED FORM;Lo;0;AL;<isolated> 0637;;;;N;GLYPH FOR ISOLATE ARABIC TAH;;;; FEC2;ARABIC LETTER TAH FINAL FORM;Lo;0;AL;<final> 0637;;;;N;GLYPH FOR FINAL ARABIC TAH;;;; FEC3;ARABIC LETTER TAH INITIAL FORM;Lo;0;AL;<initial> 0637;;;;N;GLYPH FOR INITIAL ARABIC TAH;;;; FEC4;ARABIC LETTER TAH MEDIAL FORM;Lo;0;AL;<medial> 0637;;;;N;GLYPH FOR MEDIAL ARABIC TAH;;;; FEC5;ARABIC LETTER ZAH ISOLATED FORM;Lo;0;AL;<isolated> 0638;;;;N;GLYPH FOR ISOLATE ARABIC DHAH;;;; FEC6;ARABIC LETTER ZAH FINAL FORM;Lo;0;AL;<final> 0638;;;;N;GLYPH FOR FINAL ARABIC DHAH;;;; FEC7;ARABIC LETTER ZAH INITIAL FORM;Lo;0;AL;<initial> 0638;;;;N;GLYPH FOR INITIAL ARABIC DHAH;;;; FEC8;ARABIC LETTER ZAH MEDIAL FORM;Lo;0;AL;<medial> 0638;;;;N;GLYPH FOR MEDIAL ARABIC DHAH;;;; FEC9;ARABIC LETTER AIN ISOLATED FORM;Lo;0;AL;<isolated> 0639;;;;N;GLYPH FOR ISOLATE ARABIC AIN;;;; FECA;ARABIC LETTER AIN FINAL FORM;Lo;0;AL;<final> 0639;;;;N;GLYPH FOR FINAL ARABIC AIN;;;; FECB;ARABIC LETTER AIN INITIAL FORM;Lo;0;AL;<initial> 0639;;;;N;GLYPH FOR INITIAL ARABIC AIN;;;; FECC;ARABIC LETTER AIN MEDIAL FORM;Lo;0;AL;<medial> 0639;;;;N;GLYPH FOR MEDIAL ARABIC AIN;;;; FECD;ARABIC LETTER GHAIN ISOLATED FORM;Lo;0;AL;<isolated> 063A;;;;N;GLYPH FOR ISOLATE ARABIC GHAIN;;;; FECE;ARABIC LETTER GHAIN FINAL FORM;Lo;0;AL;<final> 063A;;;;N;GLYPH FOR FINAL ARABIC GHAIN;;;; FECF;ARABIC LETTER GHAIN INITIAL FORM;Lo;0;AL;<initial> 063A;;;;N;GLYPH FOR INITIAL ARABIC GHAIN;;;; FED0;ARABIC LETTER GHAIN MEDIAL FORM;Lo;0;AL;<medial> 063A;;;;N;GLYPH FOR MEDIAL ARABIC GHAIN;;;; FED1;ARABIC LETTER FEH ISOLATED FORM;Lo;0;AL;<isolated> 0641;;;;N;GLYPH FOR ISOLATE ARABIC FA;;;; FED2;ARABIC LETTER FEH FINAL FORM;Lo;0;AL;<final> 0641;;;;N;GLYPH FOR FINAL ARABIC FA;;;; FED3;ARABIC LETTER FEH INITIAL FORM;Lo;0;AL;<initial> 0641;;;;N;GLYPH FOR INITIAL ARABIC FA;;;; FED4;ARABIC LETTER FEH MEDIAL FORM;Lo;0;AL;<medial> 0641;;;;N;GLYPH FOR MEDIAL ARABIC FA;;;; FED5;ARABIC LETTER QAF ISOLATED FORM;Lo;0;AL;<isolated> 0642;;;;N;GLYPH FOR ISOLATE ARABIC QAF;;;; FED6;ARABIC LETTER QAF FINAL FORM;Lo;0;AL;<final> 0642;;;;N;GLYPH FOR FINAL ARABIC QAF;;;; FED7;ARABIC LETTER QAF INITIAL FORM;Lo;0;AL;<initial> 0642;;;;N;GLYPH FOR INITIAL ARABIC QAF;;;; FED8;ARABIC LETTER QAF MEDIAL FORM;Lo;0;AL;<medial> 0642;;;;N;GLYPH FOR MEDIAL ARABIC QAF;;;; FED9;ARABIC LETTER KAF ISOLATED FORM;Lo;0;AL;<isolated> 0643;;;;N;GLYPH FOR ISOLATE ARABIC CAF;;;; FEDA;ARABIC LETTER KAF FINAL FORM;Lo;0;AL;<final> 0643;;;;N;GLYPH FOR FINAL ARABIC CAF;;;; FEDB;ARABIC LETTER KAF INITIAL FORM;Lo;0;AL;<initial> 0643;;;;N;GLYPH FOR INITIAL ARABIC CAF;;;; FEDC;ARABIC LETTER KAF MEDIAL FORM;Lo;0;AL;<medial> 0643;;;;N;GLYPH FOR MEDIAL ARABIC CAF;;;; FEDD;ARABIC LETTER LAM ISOLATED FORM;Lo;0;AL;<isolated> 0644;;;;N;GLYPH FOR ISOLATE ARABIC LAM;;;; FEDE;ARABIC LETTER LAM FINAL FORM;Lo;0;AL;<final> 0644;;;;N;GLYPH FOR FINAL ARABIC LAM;;;; FEDF;ARABIC LETTER LAM INITIAL FORM;Lo;0;AL;<initial> 0644;;;;N;GLYPH FOR INITIAL ARABIC LAM;;;; FEE0;ARABIC LETTER LAM MEDIAL FORM;Lo;0;AL;<medial> 0644;;;;N;GLYPH FOR MEDIAL ARABIC LAM;;;; FEE1;ARABIC LETTER MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0645;;;;N;GLYPH FOR ISOLATE ARABIC MEEM;;;; FEE2;ARABIC LETTER MEEM FINAL FORM;Lo;0;AL;<final> 0645;;;;N;GLYPH FOR FINAL ARABIC MEEM;;;; FEE3;ARABIC LETTER MEEM INITIAL FORM;Lo;0;AL;<initial> 0645;;;;N;GLYPH FOR INITIAL ARABIC MEEM;;;; FEE4;ARABIC LETTER MEEM MEDIAL FORM;Lo;0;AL;<medial> 0645;;;;N;GLYPH FOR MEDIAL ARABIC MEEM;;;; FEE5;ARABIC LETTER NOON ISOLATED FORM;Lo;0;AL;<isolated> 0646;;;;N;GLYPH FOR ISOLATE ARABIC NOON;;;; FEE6;ARABIC LETTER NOON FINAL FORM;Lo;0;AL;<final> 0646;;;;N;GLYPH FOR FINAL ARABIC NOON;;;; FEE7;ARABIC LETTER NOON INITIAL FORM;Lo;0;AL;<initial> 0646;;;;N;GLYPH FOR INITIAL ARABIC NOON;;;; FEE8;ARABIC LETTER NOON MEDIAL FORM;Lo;0;AL;<medial> 0646;;;;N;GLYPH FOR MEDIAL ARABIC NOON;;;; FEE9;ARABIC LETTER HEH ISOLATED FORM;Lo;0;AL;<isolated> 0647;;;;N;GLYPH FOR ISOLATE ARABIC HA;;;; FEEA;ARABIC LETTER HEH FINAL FORM;Lo;0;AL;<final> 0647;;;;N;GLYPH FOR FINAL ARABIC HA;;;; FEEB;ARABIC LETTER HEH INITIAL FORM;Lo;0;AL;<initial> 0647;;;;N;GLYPH FOR INITIAL ARABIC HA;;;; FEEC;ARABIC LETTER HEH MEDIAL FORM;Lo;0;AL;<medial> 0647;;;;N;GLYPH FOR MEDIAL ARABIC HA;;;; FEED;ARABIC LETTER WAW ISOLATED FORM;Lo;0;AL;<isolated> 0648;;;;N;GLYPH FOR ISOLATE ARABIC WAW;;;; FEEE;ARABIC LETTER WAW FINAL FORM;Lo;0;AL;<final> 0648;;;;N;GLYPH FOR FINAL ARABIC WAW;;;; FEEF;ARABIC LETTER ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0649;;;;N;GLYPH FOR ISOLATE ARABIC ALEF MAQSURAH;;;; FEF0;ARABIC LETTER ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0649;;;;N;GLYPH FOR FINAL ARABIC ALEF MAQSURAH;;;; FEF1;ARABIC LETTER YEH ISOLATED FORM;Lo;0;AL;<isolated> 064A;;;;N;GLYPH FOR ISOLATE ARABIC YA;;;; FEF2;ARABIC LETTER YEH FINAL FORM;Lo;0;AL;<final> 064A;;;;N;GLYPH FOR FINAL ARABIC YA;;;; FEF3;ARABIC LETTER YEH INITIAL FORM;Lo;0;AL;<initial> 064A;;;;N;GLYPH FOR INITIAL ARABIC YA;;;; FEF4;ARABIC LETTER YEH MEDIAL FORM;Lo;0;AL;<medial> 064A;;;;N;GLYPH FOR MEDIAL ARABIC YA;;;; FEF5;ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM;Lo;0;AL;<isolated> 0644 0622;;;;N;GLYPH FOR ISOLATE ARABIC MADDAH ON LIGATURE LAM ALEF;;;; FEF6;ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE FINAL FORM;Lo;0;AL;<final> 0644 0622;;;;N;GLYPH FOR FINAL ARABIC MADDAH ON LIGATURE LAM ALEF;;;; FEF7;ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM;Lo;0;AL;<isolated> 0644 0623;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH ON LIGATURE LAM ALEF;;;; FEF8;ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM;Lo;0;AL;<final> 0644 0623;;;;N;GLYPH FOR FINAL ARABIC HAMZAH ON LIGATURE LAM ALEF;;;; FEF9;ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW ISOLATED FORM;Lo;0;AL;<isolated> 0644 0625;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH UNDER LIGATURE LAM ALEF;;;; FEFA;ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW FINAL FORM;Lo;0;AL;<final> 0644 0625;;;;N;GLYPH FOR FINAL ARABIC HAMZAH UNDER LIGATURE LAM ALEF;;;; FEFB;ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM;Lo;0;AL;<isolated> 0644 0627;;;;N;GLYPH FOR ISOLATE ARABIC LIGATURE LAM ALEF;;;; FEFC;ARABIC LIGATURE LAM WITH ALEF FINAL FORM;Lo;0;AL;<final> 0644 0627;;;;N;GLYPH FOR FINAL ARABIC LIGATURE LAM ALEF;;;; FEFF;ZERO WIDTH NO-BREAK SPACE;Cf;0;BN;;;;;N;BYTE ORDER MARK;;;; FF01;FULLWIDTH EXCLAMATION MARK;Po;0;ON;<wide> 0021;;;;N;;;;; FF02;FULLWIDTH QUOTATION MARK;Po;0;ON;<wide> 0022;;;;N;;;;; FF03;FULLWIDTH NUMBER SIGN;Po;0;ET;<wide> 0023;;;;N;;;;; FF04;FULLWIDTH DOLLAR SIGN;Sc;0;ET;<wide> 0024;;;;N;;;;; FF05;FULLWIDTH PERCENT SIGN;Po;0;ET;<wide> 0025;;;;N;;;;; FF06;FULLWIDTH AMPERSAND;Po;0;ON;<wide> 0026;;;;N;;;;; FF07;FULLWIDTH APOSTROPHE;Po;0;ON;<wide> 0027;;;;N;;;;; FF08;FULLWIDTH LEFT PARENTHESIS;Ps;0;ON;<wide> 0028;;;;Y;FULLWIDTH OPENING PARENTHESIS;;;; FF09;FULLWIDTH RIGHT PARENTHESIS;Pe;0;ON;<wide> 0029;;;;Y;FULLWIDTH CLOSING PARENTHESIS;;;; FF0A;FULLWIDTH ASTERISK;Po;0;ON;<wide> 002A;;;;N;;;;; FF0B;FULLWIDTH PLUS SIGN;Sm;0;ES;<wide> 002B;;;;N;;;;; FF0C;FULLWIDTH COMMA;Po;0;CS;<wide> 002C;;;;N;;;;; FF0D;FULLWIDTH HYPHEN-MINUS;Pd;0;ES;<wide> 002D;;;;N;;;;; FF0E;FULLWIDTH FULL STOP;Po;0;CS;<wide> 002E;;;;N;FULLWIDTH PERIOD;;;; FF0F;FULLWIDTH SOLIDUS;Po;0;CS;<wide> 002F;;;;N;FULLWIDTH SLASH;;;; FF10;FULLWIDTH DIGIT ZERO;Nd;0;EN;<wide> 0030;0;0;0;N;;;;; FF11;FULLWIDTH DIGIT ONE;Nd;0;EN;<wide> 0031;1;1;1;N;;;;; FF12;FULLWIDTH DIGIT TWO;Nd;0;EN;<wide> 0032;2;2;2;N;;;;; FF13;FULLWIDTH DIGIT THREE;Nd;0;EN;<wide> 0033;3;3;3;N;;;;; FF14;FULLWIDTH DIGIT FOUR;Nd;0;EN;<wide> 0034;4;4;4;N;;;;; FF15;FULLWIDTH DIGIT FIVE;Nd;0;EN;<wide> 0035;5;5;5;N;;;;; FF16;FULLWIDTH DIGIT SIX;Nd;0;EN;<wide> 0036;6;6;6;N;;;;; FF17;FULLWIDTH DIGIT SEVEN;Nd;0;EN;<wide> 0037;7;7;7;N;;;;; FF18;FULLWIDTH DIGIT EIGHT;Nd;0;EN;<wide> 0038;8;8;8;N;;;;; FF19;FULLWIDTH DIGIT NINE;Nd;0;EN;<wide> 0039;9;9;9;N;;;;; FF1A;FULLWIDTH COLON;Po;0;CS;<wide> 003A;;;;N;;;;; FF1B;FULLWIDTH SEMICOLON;Po;0;ON;<wide> 003B;;;;N;;;;; FF1C;FULLWIDTH LESS-THAN SIGN;Sm;0;ON;<wide> 003C;;;;Y;;;;; FF1D;FULLWIDTH EQUALS SIGN;Sm;0;ON;<wide> 003D;;;;N;;;;; FF1E;FULLWIDTH GREATER-THAN SIGN;Sm;0;ON;<wide> 003E;;;;Y;;;;; FF1F;FULLWIDTH QUESTION MARK;Po;0;ON;<wide> 003F;;;;N;;;;; FF20;FULLWIDTH COMMERCIAL AT;Po;0;ON;<wide> 0040;;;;N;;;;; FF21;FULLWIDTH LATIN CAPITAL LETTER A;Lu;0;L;<wide> 0041;;;;N;;;;FF41; FF22;FULLWIDTH LATIN CAPITAL LETTER B;Lu;0;L;<wide> 0042;;;;N;;;;FF42; FF23;FULLWIDTH LATIN CAPITAL LETTER C;Lu;0;L;<wide> 0043;;;;N;;;;FF43; FF24;FULLWIDTH LATIN CAPITAL LETTER D;Lu;0;L;<wide> 0044;;;;N;;;;FF44; FF25;FULLWIDTH LATIN CAPITAL LETTER E;Lu;0;L;<wide> 0045;;;;N;;;;FF45; FF26;FULLWIDTH LATIN CAPITAL LETTER F;Lu;0;L;<wide> 0046;;;;N;;;;FF46; FF27;FULLWIDTH LATIN CAPITAL LETTER G;Lu;0;L;<wide> 0047;;;;N;;;;FF47; FF28;FULLWIDTH LATIN CAPITAL LETTER H;Lu;0;L;<wide> 0048;;;;N;;;;FF48; FF29;FULLWIDTH LATIN CAPITAL LETTER I;Lu;0;L;<wide> 0049;;;;N;;;;FF49; FF2A;FULLWIDTH LATIN CAPITAL LETTER J;Lu;0;L;<wide> 004A;;;;N;;;;FF4A; FF2B;FULLWIDTH LATIN CAPITAL LETTER K;Lu;0;L;<wide> 004B;;;;N;;;;FF4B; FF2C;FULLWIDTH LATIN CAPITAL LETTER L;Lu;0;L;<wide> 004C;;;;N;;;;FF4C; FF2D;FULLWIDTH LATIN CAPITAL LETTER M;Lu;0;L;<wide> 004D;;;;N;;;;FF4D; FF2E;FULLWIDTH LATIN CAPITAL LETTER N;Lu;0;L;<wide> 004E;;;;N;;;;FF4E; FF2F;FULLWIDTH LATIN CAPITAL LETTER O;Lu;0;L;<wide> 004F;;;;N;;;;FF4F; FF30;FULLWIDTH LATIN CAPITAL LETTER P;Lu;0;L;<wide> 0050;;;;N;;;;FF50; FF31;FULLWIDTH LATIN CAPITAL LETTER Q;Lu;0;L;<wide> 0051;;;;N;;;;FF51; FF32;FULLWIDTH LATIN CAPITAL LETTER R;Lu;0;L;<wide> 0052;;;;N;;;;FF52; FF33;FULLWIDTH LATIN CAPITAL LETTER S;Lu;0;L;<wide> 0053;;;;N;;;;FF53; FF34;FULLWIDTH LATIN CAPITAL LETTER T;Lu;0;L;<wide> 0054;;;;N;;;;FF54; FF35;FULLWIDTH LATIN CAPITAL LETTER U;Lu;0;L;<wide> 0055;;;;N;;;;FF55; FF36;FULLWIDTH LATIN CAPITAL LETTER V;Lu;0;L;<wide> 0056;;;;N;;;;FF56; FF37;FULLWIDTH LATIN CAPITAL LETTER W;Lu;0;L;<wide> 0057;;;;N;;;;FF57; FF38;FULLWIDTH LATIN CAPITAL LETTER X;Lu;0;L;<wide> 0058;;;;N;;;;FF58; FF39;FULLWIDTH LATIN CAPITAL LETTER Y;Lu;0;L;<wide> 0059;;;;N;;;;FF59; FF3A;FULLWIDTH LATIN CAPITAL LETTER Z;Lu;0;L;<wide> 005A;;;;N;;;;FF5A; FF3B;FULLWIDTH LEFT SQUARE BRACKET;Ps;0;ON;<wide> 005B;;;;Y;FULLWIDTH OPENING SQUARE BRACKET;;;; FF3C;FULLWIDTH REVERSE SOLIDUS;Po;0;ON;<wide> 005C;;;;N;FULLWIDTH BACKSLASH;;;; FF3D;FULLWIDTH RIGHT SQUARE BRACKET;Pe;0;ON;<wide> 005D;;;;Y;FULLWIDTH CLOSING SQUARE BRACKET;;;; FF3E;FULLWIDTH CIRCUMFLEX ACCENT;Sk;0;ON;<wide> 005E;;;;N;FULLWIDTH SPACING CIRCUMFLEX;;;; FF3F;FULLWIDTH LOW LINE;Pc;0;ON;<wide> 005F;;;;N;FULLWIDTH SPACING UNDERSCORE;;;; FF40;FULLWIDTH GRAVE ACCENT;Sk;0;ON;<wide> 0060;;;;N;FULLWIDTH SPACING GRAVE;;;; FF41;FULLWIDTH LATIN SMALL LETTER A;Ll;0;L;<wide> 0061;;;;N;;;FF21;;FF21 FF42;FULLWIDTH LATIN SMALL LETTER B;Ll;0;L;<wide> 0062;;;;N;;;FF22;;FF22 FF43;FULLWIDTH LATIN SMALL LETTER C;Ll;0;L;<wide> 0063;;;;N;;;FF23;;FF23 FF44;FULLWIDTH LATIN SMALL LETTER D;Ll;0;L;<wide> 0064;;;;N;;;FF24;;FF24 FF45;FULLWIDTH LATIN SMALL LETTER E;Ll;0;L;<wide> 0065;;;;N;;;FF25;;FF25 FF46;FULLWIDTH LATIN SMALL LETTER F;Ll;0;L;<wide> 0066;;;;N;;;FF26;;FF26 FF47;FULLWIDTH LATIN SMALL LETTER G;Ll;0;L;<wide> 0067;;;;N;;;FF27;;FF27 FF48;FULLWIDTH LATIN SMALL LETTER H;Ll;0;L;<wide> 0068;;;;N;;;FF28;;FF28 FF49;FULLWIDTH LATIN SMALL LETTER I;Ll;0;L;<wide> 0069;;;;N;;;FF29;;FF29 FF4A;FULLWIDTH LATIN SMALL LETTER J;Ll;0;L;<wide> 006A;;;;N;;;FF2A;;FF2A FF4B;FULLWIDTH LATIN SMALL LETTER K;Ll;0;L;<wide> 006B;;;;N;;;FF2B;;FF2B FF4C;FULLWIDTH LATIN SMALL LETTER L;Ll;0;L;<wide> 006C;;;;N;;;FF2C;;FF2C FF4D;FULLWIDTH LATIN SMALL LETTER M;Ll;0;L;<wide> 006D;;;;N;;;FF2D;;FF2D FF4E;FULLWIDTH LATIN SMALL LETTER N;Ll;0;L;<wide> 006E;;;;N;;;FF2E;;FF2E FF4F;FULLWIDTH LATIN SMALL LETTER O;Ll;0;L;<wide> 006F;;;;N;;;FF2F;;FF2F FF50;FULLWIDTH LATIN SMALL LETTER P;Ll;0;L;<wide> 0070;;;;N;;;FF30;;FF30 FF51;FULLWIDTH LATIN SMALL LETTER Q;Ll;0;L;<wide> 0071;;;;N;;;FF31;;FF31 FF52;FULLWIDTH LATIN SMALL LETTER R;Ll;0;L;<wide> 0072;;;;N;;;FF32;;FF32 FF53;FULLWIDTH LATIN SMALL LETTER S;Ll;0;L;<wide> 0073;;;;N;;;FF33;;FF33 FF54;FULLWIDTH LATIN SMALL LETTER T;Ll;0;L;<wide> 0074;;;;N;;;FF34;;FF34 FF55;FULLWIDTH LATIN SMALL LETTER U;Ll;0;L;<wide> 0075;;;;N;;;FF35;;FF35 FF56;FULLWIDTH LATIN SMALL LETTER V;Ll;0;L;<wide> 0076;;;;N;;;FF36;;FF36 FF57;FULLWIDTH LATIN SMALL LETTER W;Ll;0;L;<wide> 0077;;;;N;;;FF37;;FF37 FF58;FULLWIDTH LATIN SMALL LETTER X;Ll;0;L;<wide> 0078;;;;N;;;FF38;;FF38 FF59;FULLWIDTH LATIN SMALL LETTER Y;Ll;0;L;<wide> 0079;;;;N;;;FF39;;FF39 FF5A;FULLWIDTH LATIN SMALL LETTER Z;Ll;0;L;<wide> 007A;;;;N;;;FF3A;;FF3A FF5B;FULLWIDTH LEFT CURLY BRACKET;Ps;0;ON;<wide> 007B;;;;Y;FULLWIDTH OPENING CURLY BRACKET;;;; FF5C;FULLWIDTH VERTICAL LINE;Sm;0;ON;<wide> 007C;;;;N;FULLWIDTH VERTICAL BAR;;;; FF5D;FULLWIDTH RIGHT CURLY BRACKET;Pe;0;ON;<wide> 007D;;;;Y;FULLWIDTH CLOSING CURLY BRACKET;;;; FF5E;FULLWIDTH TILDE;Sm;0;ON;<wide> 007E;;;;N;FULLWIDTH SPACING TILDE;;;; FF5F;FULLWIDTH LEFT WHITE PARENTHESIS;Ps;0;ON;<wide> 2985;;;;Y;;;;; FF60;FULLWIDTH RIGHT WHITE PARENTHESIS;Pe;0;ON;<wide> 2986;;;;Y;;;;; FF61;HALFWIDTH IDEOGRAPHIC FULL STOP;Po;0;ON;<narrow> 3002;;;;N;HALFWIDTH IDEOGRAPHIC PERIOD;;;; FF62;HALFWIDTH LEFT CORNER BRACKET;Ps;0;ON;<narrow> 300C;;;;Y;HALFWIDTH OPENING CORNER BRACKET;;;; FF63;HALFWIDTH RIGHT CORNER BRACKET;Pe;0;ON;<narrow> 300D;;;;Y;HALFWIDTH CLOSING CORNER BRACKET;;;; FF64;HALFWIDTH IDEOGRAPHIC COMMA;Po;0;ON;<narrow> 3001;;;;N;;;;; FF65;HALFWIDTH KATAKANA MIDDLE DOT;Po;0;ON;<narrow> 30FB;;;;N;;;;; FF66;HALFWIDTH KATAKANA LETTER WO;Lo;0;L;<narrow> 30F2;;;;N;;;;; FF67;HALFWIDTH KATAKANA LETTER SMALL A;Lo;0;L;<narrow> 30A1;;;;N;;;;; FF68;HALFWIDTH KATAKANA LETTER SMALL I;Lo;0;L;<narrow> 30A3;;;;N;;;;; FF69;HALFWIDTH KATAKANA LETTER SMALL U;Lo;0;L;<narrow> 30A5;;;;N;;;;; FF6A;HALFWIDTH KATAKANA LETTER SMALL E;Lo;0;L;<narrow> 30A7;;;;N;;;;; FF6B;HALFWIDTH KATAKANA LETTER SMALL O;Lo;0;L;<narrow> 30A9;;;;N;;;;; FF6C;HALFWIDTH KATAKANA LETTER SMALL YA;Lo;0;L;<narrow> 30E3;;;;N;;;;; FF6D;HALFWIDTH KATAKANA LETTER SMALL YU;Lo;0;L;<narrow> 30E5;;;;N;;;;; FF6E;HALFWIDTH KATAKANA LETTER SMALL YO;Lo;0;L;<narrow> 30E7;;;;N;;;;; FF6F;HALFWIDTH KATAKANA LETTER SMALL TU;Lo;0;L;<narrow> 30C3;;;;N;;;;; FF70;HALFWIDTH KATAKANA-HIRAGANA PROLONGED SOUND MARK;Lm;0;L;<narrow> 30FC;;;;N;;;;; FF71;HALFWIDTH KATAKANA LETTER A;Lo;0;L;<narrow> 30A2;;;;N;;;;; FF72;HALFWIDTH KATAKANA LETTER I;Lo;0;L;<narrow> 30A4;;;;N;;;;; FF73;HALFWIDTH KATAKANA LETTER U;Lo;0;L;<narrow> 30A6;;;;N;;;;; FF74;HALFWIDTH KATAKANA LETTER E;Lo;0;L;<narrow> 30A8;;;;N;;;;; FF75;HALFWIDTH KATAKANA LETTER O;Lo;0;L;<narrow> 30AA;;;;N;;;;; FF76;HALFWIDTH KATAKANA LETTER KA;Lo;0;L;<narrow> 30AB;;;;N;;;;; FF77;HALFWIDTH KATAKANA LETTER KI;Lo;0;L;<narrow> 30AD;;;;N;;;;; FF78;HALFWIDTH KATAKANA LETTER KU;Lo;0;L;<narrow> 30AF;;;;N;;;;; FF79;HALFWIDTH KATAKANA LETTER KE;Lo;0;L;<narrow> 30B1;;;;N;;;;; FF7A;HALFWIDTH KATAKANA LETTER KO;Lo;0;L;<narrow> 30B3;;;;N;;;;; FF7B;HALFWIDTH KATAKANA LETTER SA;Lo;0;L;<narrow> 30B5;;;;N;;;;; FF7C;HALFWIDTH KATAKANA LETTER SI;Lo;0;L;<narrow> 30B7;;;;N;;;;; FF7D;HALFWIDTH KATAKANA LETTER SU;Lo;0;L;<narrow> 30B9;;;;N;;;;; FF7E;HALFWIDTH KATAKANA LETTER SE;Lo;0;L;<narrow> 30BB;;;;N;;;;; FF7F;HALFWIDTH KATAKANA LETTER SO;Lo;0;L;<narrow> 30BD;;;;N;;;;; FF80;HALFWIDTH KATAKANA LETTER TA;Lo;0;L;<narrow> 30BF;;;;N;;;;; FF81;HALFWIDTH KATAKANA LETTER TI;Lo;0;L;<narrow> 30C1;;;;N;;;;; FF82;HALFWIDTH KATAKANA LETTER TU;Lo;0;L;<narrow> 30C4;;;;N;;;;; FF83;HALFWIDTH KATAKANA LETTER TE;Lo;0;L;<narrow> 30C6;;;;N;;;;; FF84;HALFWIDTH KATAKANA LETTER TO;Lo;0;L;<narrow> 30C8;;;;N;;;;; FF85;HALFWIDTH KATAKANA LETTER NA;Lo;0;L;<narrow> 30CA;;;;N;;;;; FF86;HALFWIDTH KATAKANA LETTER NI;Lo;0;L;<narrow> 30CB;;;;N;;;;; FF87;HALFWIDTH KATAKANA LETTER NU;Lo;0;L;<narrow> 30CC;;;;N;;;;; FF88;HALFWIDTH KATAKANA LETTER NE;Lo;0;L;<narrow> 30CD;;;;N;;;;; FF89;HALFWIDTH KATAKANA LETTER NO;Lo;0;L;<narrow> 30CE;;;;N;;;;; FF8A;HALFWIDTH KATAKANA LETTER HA;Lo;0;L;<narrow> 30CF;;;;N;;;;; FF8B;HALFWIDTH KATAKANA LETTER HI;Lo;0;L;<narrow> 30D2;;;;N;;;;; FF8C;HALFWIDTH KATAKANA LETTER HU;Lo;0;L;<narrow> 30D5;;;;N;;;;; FF8D;HALFWIDTH KATAKANA LETTER HE;Lo;0;L;<narrow> 30D8;;;;N;;;;; FF8E;HALFWIDTH KATAKANA LETTER HO;Lo;0;L;<narrow> 30DB;;;;N;;;;; FF8F;HALFWIDTH KATAKANA LETTER MA;Lo;0;L;<narrow> 30DE;;;;N;;;;; FF90;HALFWIDTH KATAKANA LETTER MI;Lo;0;L;<narrow> 30DF;;;;N;;;;; FF91;HALFWIDTH KATAKANA LETTER MU;Lo;0;L;<narrow> 30E0;;;;N;;;;; FF92;HALFWIDTH KATAKANA LETTER ME;Lo;0;L;<narrow> 30E1;;;;N;;;;; FF93;HALFWIDTH KATAKANA LETTER MO;Lo;0;L;<narrow> 30E2;;;;N;;;;; FF94;HALFWIDTH KATAKANA LETTER YA;Lo;0;L;<narrow> 30E4;;;;N;;;;; FF95;HALFWIDTH KATAKANA LETTER YU;Lo;0;L;<narrow> 30E6;;;;N;;;;; FF96;HALFWIDTH KATAKANA LETTER YO;Lo;0;L;<narrow> 30E8;;;;N;;;;; FF97;HALFWIDTH KATAKANA LETTER RA;Lo;0;L;<narrow> 30E9;;;;N;;;;; FF98;HALFWIDTH KATAKANA LETTER RI;Lo;0;L;<narrow> 30EA;;;;N;;;;; FF99;HALFWIDTH KATAKANA LETTER RU;Lo;0;L;<narrow> 30EB;;;;N;;;;; FF9A;HALFWIDTH KATAKANA LETTER RE;Lo;0;L;<narrow> 30EC;;;;N;;;;; FF9B;HALFWIDTH KATAKANA LETTER RO;Lo;0;L;<narrow> 30ED;;;;N;;;;; FF9C;HALFWIDTH KATAKANA LETTER WA;Lo;0;L;<narrow> 30EF;;;;N;;;;; FF9D;HALFWIDTH KATAKANA LETTER N;Lo;0;L;<narrow> 30F3;;;;N;;;;; FF9E;HALFWIDTH KATAKANA VOICED SOUND MARK;Lm;0;L;<narrow> 3099;;;;N;;;;; FF9F;HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK;Lm;0;L;<narrow> 309A;;;;N;;;;; FFA0;HALFWIDTH HANGUL FILLER;Lo;0;L;<narrow> 3164;;;;N;HALFWIDTH HANGUL CAE OM;;;; FFA1;HALFWIDTH HANGUL LETTER KIYEOK;Lo;0;L;<narrow> 3131;;;;N;HALFWIDTH HANGUL LETTER GIYEOG;;;; FFA2;HALFWIDTH HANGUL LETTER SSANGKIYEOK;Lo;0;L;<narrow> 3132;;;;N;HALFWIDTH HANGUL LETTER SSANG GIYEOG;;;; FFA3;HALFWIDTH HANGUL LETTER KIYEOK-SIOS;Lo;0;L;<narrow> 3133;;;;N;HALFWIDTH HANGUL LETTER GIYEOG SIOS;;;; FFA4;HALFWIDTH HANGUL LETTER NIEUN;Lo;0;L;<narrow> 3134;;;;N;;;;; FFA5;HALFWIDTH HANGUL LETTER NIEUN-CIEUC;Lo;0;L;<narrow> 3135;;;;N;HALFWIDTH HANGUL LETTER NIEUN JIEUJ;;;; FFA6;HALFWIDTH HANGUL LETTER NIEUN-HIEUH;Lo;0;L;<narrow> 3136;;;;N;HALFWIDTH HANGUL LETTER NIEUN HIEUH;;;; FFA7;HALFWIDTH HANGUL LETTER TIKEUT;Lo;0;L;<narrow> 3137;;;;N;HALFWIDTH HANGUL LETTER DIGEUD;;;; FFA8;HALFWIDTH HANGUL LETTER SSANGTIKEUT;Lo;0;L;<narrow> 3138;;;;N;HALFWIDTH HANGUL LETTER SSANG DIGEUD;;;; FFA9;HALFWIDTH HANGUL LETTER RIEUL;Lo;0;L;<narrow> 3139;;;;N;HALFWIDTH HANGUL LETTER LIEUL;;;; FFAA;HALFWIDTH HANGUL LETTER RIEUL-KIYEOK;Lo;0;L;<narrow> 313A;;;;N;HALFWIDTH HANGUL LETTER LIEUL GIYEOG;;;; FFAB;HALFWIDTH HANGUL LETTER RIEUL-MIEUM;Lo;0;L;<narrow> 313B;;;;N;HALFWIDTH HANGUL LETTER LIEUL MIEUM;;;; FFAC;HALFWIDTH HANGUL LETTER RIEUL-PIEUP;Lo;0;L;<narrow> 313C;;;;N;HALFWIDTH HANGUL LETTER LIEUL BIEUB;;;; FFAD;HALFWIDTH HANGUL LETTER RIEUL-SIOS;Lo;0;L;<narrow> 313D;;;;N;HALFWIDTH HANGUL LETTER LIEUL SIOS;;;; FFAE;HALFWIDTH HANGUL LETTER RIEUL-THIEUTH;Lo;0;L;<narrow> 313E;;;;N;HALFWIDTH HANGUL LETTER LIEUL TIEUT;;;; FFAF;HALFWIDTH HANGUL LETTER RIEUL-PHIEUPH;Lo;0;L;<narrow> 313F;;;;N;HALFWIDTH HANGUL LETTER LIEUL PIEUP;;;; FFB0;HALFWIDTH HANGUL LETTER RIEUL-HIEUH;Lo;0;L;<narrow> 3140;;;;N;HALFWIDTH HANGUL LETTER LIEUL HIEUH;;;; FFB1;HALFWIDTH HANGUL LETTER MIEUM;Lo;0;L;<narrow> 3141;;;;N;;;;; FFB2;HALFWIDTH HANGUL LETTER PIEUP;Lo;0;L;<narrow> 3142;;;;N;HALFWIDTH HANGUL LETTER BIEUB;;;; FFB3;HALFWIDTH HANGUL LETTER SSANGPIEUP;Lo;0;L;<narrow> 3143;;;;N;HALFWIDTH HANGUL LETTER SSANG BIEUB;;;; FFB4;HALFWIDTH HANGUL LETTER PIEUP-SIOS;Lo;0;L;<narrow> 3144;;;;N;HALFWIDTH HANGUL LETTER BIEUB SIOS;;;; FFB5;HALFWIDTH HANGUL LETTER SIOS;Lo;0;L;<narrow> 3145;;;;N;;;;; FFB6;HALFWIDTH HANGUL LETTER SSANGSIOS;Lo;0;L;<narrow> 3146;;;;N;HALFWIDTH HANGUL LETTER SSANG SIOS;;;; FFB7;HALFWIDTH HANGUL LETTER IEUNG;Lo;0;L;<narrow> 3147;;;;N;;;;; FFB8;HALFWIDTH HANGUL LETTER CIEUC;Lo;0;L;<narrow> 3148;;;;N;HALFWIDTH HANGUL LETTER JIEUJ;;;; FFB9;HALFWIDTH HANGUL LETTER SSANGCIEUC;Lo;0;L;<narrow> 3149;;;;N;HALFWIDTH HANGUL LETTER SSANG JIEUJ;;;; FFBA;HALFWIDTH HANGUL LETTER CHIEUCH;Lo;0;L;<narrow> 314A;;;;N;HALFWIDTH HANGUL LETTER CIEUC;;;; FFBB;HALFWIDTH HANGUL LETTER KHIEUKH;Lo;0;L;<narrow> 314B;;;;N;HALFWIDTH HANGUL LETTER KIYEOK;;;; FFBC;HALFWIDTH HANGUL LETTER THIEUTH;Lo;0;L;<narrow> 314C;;;;N;HALFWIDTH HANGUL LETTER TIEUT;;;; FFBD;HALFWIDTH HANGUL LETTER PHIEUPH;Lo;0;L;<narrow> 314D;;;;N;HALFWIDTH HANGUL LETTER PIEUP;;;; FFBE;HALFWIDTH HANGUL LETTER HIEUH;Lo;0;L;<narrow> 314E;;;;N;;;;; FFC2;HALFWIDTH HANGUL LETTER A;Lo;0;L;<narrow> 314F;;;;N;;;;; FFC3;HALFWIDTH HANGUL LETTER AE;Lo;0;L;<narrow> 3150;;;;N;;;;; FFC4;HALFWIDTH HANGUL LETTER YA;Lo;0;L;<narrow> 3151;;;;N;;;;; FFC5;HALFWIDTH HANGUL LETTER YAE;Lo;0;L;<narrow> 3152;;;;N;;;;; FFC6;HALFWIDTH HANGUL LETTER EO;Lo;0;L;<narrow> 3153;;;;N;;;;; FFC7;HALFWIDTH HANGUL LETTER E;Lo;0;L;<narrow> 3154;;;;N;;;;; FFCA;HALFWIDTH HANGUL LETTER YEO;Lo;0;L;<narrow> 3155;;;;N;;;;; FFCB;HALFWIDTH HANGUL LETTER YE;Lo;0;L;<narrow> 3156;;;;N;;;;; FFCC;HALFWIDTH HANGUL LETTER O;Lo;0;L;<narrow> 3157;;;;N;;;;; FFCD;HALFWIDTH HANGUL LETTER WA;Lo;0;L;<narrow> 3158;;;;N;;;;; FFCE;HALFWIDTH HANGUL LETTER WAE;Lo;0;L;<narrow> 3159;;;;N;;;;; FFCF;HALFWIDTH HANGUL LETTER OE;Lo;0;L;<narrow> 315A;;;;N;;;;; FFD2;HALFWIDTH HANGUL LETTER YO;Lo;0;L;<narrow> 315B;;;;N;;;;; FFD3;HALFWIDTH HANGUL LETTER U;Lo;0;L;<narrow> 315C;;;;N;;;;; FFD4;HALFWIDTH HANGUL LETTER WEO;Lo;0;L;<narrow> 315D;;;;N;;;;; FFD5;HALFWIDTH HANGUL LETTER WE;Lo;0;L;<narrow> 315E;;;;N;;;;; FFD6;HALFWIDTH HANGUL LETTER WI;Lo;0;L;<narrow> 315F;;;;N;;;;; FFD7;HALFWIDTH HANGUL LETTER YU;Lo;0;L;<narrow> 3160;;;;N;;;;; FFDA;HALFWIDTH HANGUL LETTER EU;Lo;0;L;<narrow> 3161;;;;N;;;;; FFDB;HALFWIDTH HANGUL LETTER YI;Lo;0;L;<narrow> 3162;;;;N;;;;; FFDC;HALFWIDTH HANGUL LETTER I;Lo;0;L;<narrow> 3163;;;;N;;;;; FFE0;FULLWIDTH CENT SIGN;Sc;0;ET;<wide> 00A2;;;;N;;;;; FFE1;FULLWIDTH POUND SIGN;Sc;0;ET;<wide> 00A3;;;;N;;;;; FFE2;FULLWIDTH NOT SIGN;Sm;0;ON;<wide> 00AC;;;;N;;;;; FFE3;FULLWIDTH MACRON;Sk;0;ON;<wide> 00AF;;;;N;FULLWIDTH SPACING MACRON;;;; FFE4;FULLWIDTH BROKEN BAR;So;0;ON;<wide> 00A6;;;;N;FULLWIDTH BROKEN VERTICAL BAR;;;; FFE5;FULLWIDTH YEN SIGN;Sc;0;ET;<wide> 00A5;;;;N;;;;; FFE6;FULLWIDTH WON SIGN;Sc;0;ET;<wide> 20A9;;;;N;;;;; FFE8;HALFWIDTH FORMS LIGHT VERTICAL;So;0;ON;<narrow> 2502;;;;N;;;;; FFE9;HALFWIDTH LEFTWARDS ARROW;Sm;0;ON;<narrow> 2190;;;;N;;;;; FFEA;HALFWIDTH UPWARDS ARROW;Sm;0;ON;<narrow> 2191;;;;N;;;;; FFEB;HALFWIDTH RIGHTWARDS ARROW;Sm;0;ON;<narrow> 2192;;;;N;;;;; FFEC;HALFWIDTH DOWNWARDS ARROW;Sm;0;ON;<narrow> 2193;;;;N;;;;; FFED;HALFWIDTH BLACK SQUARE;So;0;ON;<narrow> 25A0;;;;N;;;;; FFEE;HALFWIDTH WHITE CIRCLE;So;0;ON;<narrow> 25CB;;;;N;;;;; FFF9;INTERLINEAR ANNOTATION ANCHOR;Cf;0;ON;;;;;N;;;;; FFFA;INTERLINEAR ANNOTATION SEPARATOR;Cf;0;ON;;;;;N;;;;; FFFB;INTERLINEAR ANNOTATION TERMINATOR;Cf;0;ON;;;;;N;;;;; FFFC;OBJECT REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 10000;LINEAR B SYLLABLE B008 A;Lo;0;L;;;;;N;;;;; 10001;LINEAR B SYLLABLE B038 E;Lo;0;L;;;;;N;;;;; 10002;LINEAR B SYLLABLE B028 I;Lo;0;L;;;;;N;;;;; 10003;LINEAR B SYLLABLE B061 O;Lo;0;L;;;;;N;;;;; 10004;LINEAR B SYLLABLE B010 U;Lo;0;L;;;;;N;;;;; 10005;LINEAR B SYLLABLE B001 DA;Lo;0;L;;;;;N;;;;; 10006;LINEAR B SYLLABLE B045 DE;Lo;0;L;;;;;N;;;;; 10007;LINEAR B SYLLABLE B007 DI;Lo;0;L;;;;;N;;;;; 10008;LINEAR B SYLLABLE B014 DO;Lo;0;L;;;;;N;;;;; 10009;LINEAR B SYLLABLE B051 DU;Lo;0;L;;;;;N;;;;; 1000A;LINEAR B SYLLABLE B057 JA;Lo;0;L;;;;;N;;;;; 1000B;LINEAR B SYLLABLE B046 JE;Lo;0;L;;;;;N;;;;; 1000D;LINEAR B SYLLABLE B036 JO;Lo;0;L;;;;;N;;;;; 1000E;LINEAR B SYLLABLE B065 JU;Lo;0;L;;;;;N;;;;; 1000F;LINEAR B SYLLABLE B077 KA;Lo;0;L;;;;;N;;;;; 10010;LINEAR B SYLLABLE B044 KE;Lo;0;L;;;;;N;;;;; 10011;LINEAR B SYLLABLE B067 KI;Lo;0;L;;;;;N;;;;; 10012;LINEAR B SYLLABLE B070 KO;Lo;0;L;;;;;N;;;;; 10013;LINEAR B SYLLABLE B081 KU;Lo;0;L;;;;;N;;;;; 10014;LINEAR B SYLLABLE B080 MA;Lo;0;L;;;;;N;;;;; 10015;LINEAR B SYLLABLE B013 ME;Lo;0;L;;;;;N;;;;; 10016;LINEAR B SYLLABLE B073 MI;Lo;0;L;;;;;N;;;;; 10017;LINEAR B SYLLABLE B015 MO;Lo;0;L;;;;;N;;;;; 10018;LINEAR B SYLLABLE B023 MU;Lo;0;L;;;;;N;;;;; 10019;LINEAR B SYLLABLE B006 NA;Lo;0;L;;;;;N;;;;; 1001A;LINEAR B SYLLABLE B024 NE;Lo;0;L;;;;;N;;;;; 1001B;LINEAR B SYLLABLE B030 NI;Lo;0;L;;;;;N;;;;; 1001C;LINEAR B SYLLABLE B052 NO;Lo;0;L;;;;;N;;;;; 1001D;LINEAR B SYLLABLE B055 NU;Lo;0;L;;;;;N;;;;; 1001E;LINEAR B SYLLABLE B003 PA;Lo;0;L;;;;;N;;;;; 1001F;LINEAR B SYLLABLE B072 PE;Lo;0;L;;;;;N;;;;; 10020;LINEAR B SYLLABLE B039 PI;Lo;0;L;;;;;N;;;;; 10021;LINEAR B SYLLABLE B011 PO;Lo;0;L;;;;;N;;;;; 10022;LINEAR B SYLLABLE B050 PU;Lo;0;L;;;;;N;;;;; 10023;LINEAR B SYLLABLE B016 QA;Lo;0;L;;;;;N;;;;; 10024;LINEAR B SYLLABLE B078 QE;Lo;0;L;;;;;N;;;;; 10025;LINEAR B SYLLABLE B021 QI;Lo;0;L;;;;;N;;;;; 10026;LINEAR B SYLLABLE B032 QO;Lo;0;L;;;;;N;;;;; 10028;LINEAR B SYLLABLE B060 RA;Lo;0;L;;;;;N;;;;; 10029;LINEAR B SYLLABLE B027 RE;Lo;0;L;;;;;N;;;;; 1002A;LINEAR B SYLLABLE B053 RI;Lo;0;L;;;;;N;;;;; 1002B;LINEAR B SYLLABLE B002 RO;Lo;0;L;;;;;N;;;;; 1002C;LINEAR B SYLLABLE B026 RU;Lo;0;L;;;;;N;;;;; 1002D;LINEAR B SYLLABLE B031 SA;Lo;0;L;;;;;N;;;;; 1002E;LINEAR B SYLLABLE B009 SE;Lo;0;L;;;;;N;;;;; 1002F;LINEAR B SYLLABLE B041 SI;Lo;0;L;;;;;N;;;;; 10030;LINEAR B SYLLABLE B012 SO;Lo;0;L;;;;;N;;;;; 10031;LINEAR B SYLLABLE B058 SU;Lo;0;L;;;;;N;;;;; 10032;LINEAR B SYLLABLE B059 TA;Lo;0;L;;;;;N;;;;; 10033;LINEAR B SYLLABLE B004 TE;Lo;0;L;;;;;N;;;;; 10034;LINEAR B SYLLABLE B037 TI;Lo;0;L;;;;;N;;;;; 10035;LINEAR B SYLLABLE B005 TO;Lo;0;L;;;;;N;;;;; 10036;LINEAR B SYLLABLE B069 TU;Lo;0;L;;;;;N;;;;; 10037;LINEAR B SYLLABLE B054 WA;Lo;0;L;;;;;N;;;;; 10038;LINEAR B SYLLABLE B075 WE;Lo;0;L;;;;;N;;;;; 10039;LINEAR B SYLLABLE B040 WI;Lo;0;L;;;;;N;;;;; 1003A;LINEAR B SYLLABLE B042 WO;Lo;0;L;;;;;N;;;;; 1003C;LINEAR B SYLLABLE B017 ZA;Lo;0;L;;;;;N;;;;; 1003D;LINEAR B SYLLABLE B074 ZE;Lo;0;L;;;;;N;;;;; 1003F;LINEAR B SYLLABLE B020 ZO;Lo;0;L;;;;;N;;;;; 10040;LINEAR B SYLLABLE B025 A2;Lo;0;L;;;;;N;;;;; 10041;LINEAR B SYLLABLE B043 A3;Lo;0;L;;;;;N;;;;; 10042;LINEAR B SYLLABLE B085 AU;Lo;0;L;;;;;N;;;;; 10043;LINEAR B SYLLABLE B071 DWE;Lo;0;L;;;;;N;;;;; 10044;LINEAR B SYLLABLE B090 DWO;Lo;0;L;;;;;N;;;;; 10045;LINEAR B SYLLABLE B048 NWA;Lo;0;L;;;;;N;;;;; 10046;LINEAR B SYLLABLE B029 PU2;Lo;0;L;;;;;N;;;;; 10047;LINEAR B SYLLABLE B062 PTE;Lo;0;L;;;;;N;;;;; 10048;LINEAR B SYLLABLE B076 RA2;Lo;0;L;;;;;N;;;;; 10049;LINEAR B SYLLABLE B033 RA3;Lo;0;L;;;;;N;;;;; 1004A;LINEAR B SYLLABLE B068 RO2;Lo;0;L;;;;;N;;;;; 1004B;LINEAR B SYLLABLE B066 TA2;Lo;0;L;;;;;N;;;;; 1004C;LINEAR B SYLLABLE B087 TWE;Lo;0;L;;;;;N;;;;; 1004D;LINEAR B SYLLABLE B091 TWO;Lo;0;L;;;;;N;;;;; 10050;LINEAR B SYMBOL B018;Lo;0;L;;;;;N;;;;; 10051;LINEAR B SYMBOL B019;Lo;0;L;;;;;N;;;;; 10052;LINEAR B SYMBOL B022;Lo;0;L;;;;;N;;;;; 10053;LINEAR B SYMBOL B034;Lo;0;L;;;;;N;;;;; 10054;LINEAR B SYMBOL B047;Lo;0;L;;;;;N;;;;; 10055;LINEAR B SYMBOL B049;Lo;0;L;;;;;N;;;;; 10056;LINEAR B SYMBOL B056;Lo;0;L;;;;;N;;;;; 10057;LINEAR B SYMBOL B063;Lo;0;L;;;;;N;;;;; 10058;LINEAR B SYMBOL B064;Lo;0;L;;;;;N;;;;; 10059;LINEAR B SYMBOL B079;Lo;0;L;;;;;N;;;;; 1005A;LINEAR B SYMBOL B082;Lo;0;L;;;;;N;;;;; 1005B;LINEAR B SYMBOL B083;Lo;0;L;;;;;N;;;;; 1005C;LINEAR B SYMBOL B086;Lo;0;L;;;;;N;;;;; 1005D;LINEAR B SYMBOL B089;Lo;0;L;;;;;N;;;;; 10080;LINEAR B IDEOGRAM B100 MAN;Lo;0;L;;;;;N;;;;; 10081;LINEAR B IDEOGRAM B102 WOMAN;Lo;0;L;;;;;N;;;;; 10082;LINEAR B IDEOGRAM B104 DEER;Lo;0;L;;;;;N;;;;; 10083;LINEAR B IDEOGRAM B105 EQUID;Lo;0;L;;;;;N;;;;; 10084;LINEAR B IDEOGRAM B105F MARE;Lo;0;L;;;;;N;;;;; 10085;LINEAR B IDEOGRAM B105M STALLION;Lo;0;L;;;;;N;;;;; 10086;LINEAR B IDEOGRAM B106F EWE;Lo;0;L;;;;;N;;;;; 10087;LINEAR B IDEOGRAM B106M RAM;Lo;0;L;;;;;N;;;;; 10088;LINEAR B IDEOGRAM B107F SHE-GOAT;Lo;0;L;;;;;N;;;;; 10089;LINEAR B IDEOGRAM B107M HE-GOAT;Lo;0;L;;;;;N;;;;; 1008A;LINEAR B IDEOGRAM B108F SOW;Lo;0;L;;;;;N;;;;; 1008B;LINEAR B IDEOGRAM B108M BOAR;Lo;0;L;;;;;N;;;;; 1008C;LINEAR B IDEOGRAM B109F COW;Lo;0;L;;;;;N;;;;; 1008D;LINEAR B IDEOGRAM B109M BULL;Lo;0;L;;;;;N;;;;; 1008E;LINEAR B IDEOGRAM B120 WHEAT;Lo;0;L;;;;;N;;;;; 1008F;LINEAR B IDEOGRAM B121 BARLEY;Lo;0;L;;;;;N;;;;; 10090;LINEAR B IDEOGRAM B122 OLIVE;Lo;0;L;;;;;N;;;;; 10091;LINEAR B IDEOGRAM B123 SPICE;Lo;0;L;;;;;N;;;;; 10092;LINEAR B IDEOGRAM B125 CYPERUS;Lo;0;L;;;;;N;;;;; 10093;LINEAR B MONOGRAM B127 KAPO;Lo;0;L;;;;;N;;;;; 10094;LINEAR B MONOGRAM B128 KANAKO;Lo;0;L;;;;;N;;;;; 10095;LINEAR B IDEOGRAM B130 OIL;Lo;0;L;;;;;N;;;;; 10096;LINEAR B IDEOGRAM B131 WINE;Lo;0;L;;;;;N;;;;; 10097;LINEAR B IDEOGRAM B132;Lo;0;L;;;;;N;;;;; 10098;LINEAR B MONOGRAM B133 AREPA;Lo;0;L;;;;;N;;;;; 10099;LINEAR B MONOGRAM B135 MERI;Lo;0;L;;;;;N;;;;; 1009A;LINEAR B IDEOGRAM B140 BRONZE;Lo;0;L;;;;;N;;;;; 1009B;LINEAR B IDEOGRAM B141 GOLD;Lo;0;L;;;;;N;;;;; 1009C;LINEAR B IDEOGRAM B142;Lo;0;L;;;;;N;;;;; 1009D;LINEAR B IDEOGRAM B145 WOOL;Lo;0;L;;;;;N;;;;; 1009E;LINEAR B IDEOGRAM B146;Lo;0;L;;;;;N;;;;; 1009F;LINEAR B IDEOGRAM B150;Lo;0;L;;;;;N;;;;; 100A0;LINEAR B IDEOGRAM B151 HORN;Lo;0;L;;;;;N;;;;; 100A1;LINEAR B IDEOGRAM B152;Lo;0;L;;;;;N;;;;; 100A2;LINEAR B IDEOGRAM B153;Lo;0;L;;;;;N;;;;; 100A3;LINEAR B IDEOGRAM B154;Lo;0;L;;;;;N;;;;; 100A4;LINEAR B MONOGRAM B156 TURO2;Lo;0;L;;;;;N;;;;; 100A5;LINEAR B IDEOGRAM B157;Lo;0;L;;;;;N;;;;; 100A6;LINEAR B IDEOGRAM B158;Lo;0;L;;;;;N;;;;; 100A7;LINEAR B IDEOGRAM B159 CLOTH;Lo;0;L;;;;;N;;;;; 100A8;LINEAR B IDEOGRAM B160;Lo;0;L;;;;;N;;;;; 100A9;LINEAR B IDEOGRAM B161;Lo;0;L;;;;;N;;;;; 100AA;LINEAR B IDEOGRAM B162 GARMENT;Lo;0;L;;;;;N;;;;; 100AB;LINEAR B IDEOGRAM B163 ARMOUR;Lo;0;L;;;;;N;;;;; 100AC;LINEAR B IDEOGRAM B164;Lo;0;L;;;;;N;;;;; 100AD;LINEAR B IDEOGRAM B165;Lo;0;L;;;;;N;;;;; 100AE;LINEAR B IDEOGRAM B166;Lo;0;L;;;;;N;;;;; 100AF;LINEAR B IDEOGRAM B167;Lo;0;L;;;;;N;;;;; 100B0;LINEAR B IDEOGRAM B168;Lo;0;L;;;;;N;;;;; 100B1;LINEAR B IDEOGRAM B169;Lo;0;L;;;;;N;;;;; 100B2;LINEAR B IDEOGRAM B170;Lo;0;L;;;;;N;;;;; 100B3;LINEAR B IDEOGRAM B171;Lo;0;L;;;;;N;;;;; 100B4;LINEAR B IDEOGRAM B172;Lo;0;L;;;;;N;;;;; 100B5;LINEAR B IDEOGRAM B173 MONTH;Lo;0;L;;;;;N;;;;; 100B6;LINEAR B IDEOGRAM B174;Lo;0;L;;;;;N;;;;; 100B7;LINEAR B IDEOGRAM B176 TREE;Lo;0;L;;;;;N;;;;; 100B8;LINEAR B IDEOGRAM B177;Lo;0;L;;;;;N;;;;; 100B9;LINEAR B IDEOGRAM B178;Lo;0;L;;;;;N;;;;; 100BA;LINEAR B IDEOGRAM B179;Lo;0;L;;;;;N;;;;; 100BB;LINEAR B IDEOGRAM B180;Lo;0;L;;;;;N;;;;; 100BC;LINEAR B IDEOGRAM B181;Lo;0;L;;;;;N;;;;; 100BD;LINEAR B IDEOGRAM B182;Lo;0;L;;;;;N;;;;; 100BE;LINEAR B IDEOGRAM B183;Lo;0;L;;;;;N;;;;; 100BF;LINEAR B IDEOGRAM B184;Lo;0;L;;;;;N;;;;; 100C0;LINEAR B IDEOGRAM B185;Lo;0;L;;;;;N;;;;; 100C1;LINEAR B IDEOGRAM B189;Lo;0;L;;;;;N;;;;; 100C2;LINEAR B IDEOGRAM B190;Lo;0;L;;;;;N;;;;; 100C3;LINEAR B IDEOGRAM B191 HELMET;Lo;0;L;;;;;N;;;;; 100C4;LINEAR B IDEOGRAM B220 FOOTSTOOL;Lo;0;L;;;;;N;;;;; 100C5;LINEAR B IDEOGRAM B225 BATHTUB;Lo;0;L;;;;;N;;;;; 100C6;LINEAR B IDEOGRAM B230 SPEAR;Lo;0;L;;;;;N;;;;; 100C7;LINEAR B IDEOGRAM B231 ARROW;Lo;0;L;;;;;N;;;;; 100C8;LINEAR B IDEOGRAM B232;Lo;0;L;;;;;N;;;;; 100C9;LINEAR B IDEOGRAM B233 SWORD;Lo;0;L;;;;;N;;;;; 100CA;LINEAR B IDEOGRAM B234;Lo;0;L;;;;;N;;;;; 100CB;LINEAR B IDEOGRAM B236;Lo;0;L;;;;;N;;;;; 100CC;LINEAR B IDEOGRAM B240 WHEELED CHARIOT;Lo;0;L;;;;;N;;;;; 100CD;LINEAR B IDEOGRAM B241 CHARIOT;Lo;0;L;;;;;N;;;;; 100CE;LINEAR B IDEOGRAM B242 CHARIOT FRAME;Lo;0;L;;;;;N;;;;; 100CF;LINEAR B IDEOGRAM B243 WHEEL;Lo;0;L;;;;;N;;;;; 100D0;LINEAR B IDEOGRAM B245;Lo;0;L;;;;;N;;;;; 100D1;LINEAR B IDEOGRAM B246;Lo;0;L;;;;;N;;;;; 100D2;LINEAR B MONOGRAM B247 DIPTE;Lo;0;L;;;;;N;;;;; 100D3;LINEAR B IDEOGRAM B248;Lo;0;L;;;;;N;;;;; 100D4;LINEAR B IDEOGRAM B249;Lo;0;L;;;;;N;;;;; 100D5;LINEAR B IDEOGRAM B251;Lo;0;L;;;;;N;;;;; 100D6;LINEAR B IDEOGRAM B252;Lo;0;L;;;;;N;;;;; 100D7;LINEAR B IDEOGRAM B253;Lo;0;L;;;;;N;;;;; 100D8;LINEAR B IDEOGRAM B254 DART;Lo;0;L;;;;;N;;;;; 100D9;LINEAR B IDEOGRAM B255;Lo;0;L;;;;;N;;;;; 100DA;LINEAR B IDEOGRAM B256;Lo;0;L;;;;;N;;;;; 100DB;LINEAR B IDEOGRAM B257;Lo;0;L;;;;;N;;;;; 100DC;LINEAR B IDEOGRAM B258;Lo;0;L;;;;;N;;;;; 100DD;LINEAR B IDEOGRAM B259;Lo;0;L;;;;;N;;;;; 100DE;LINEAR B IDEOGRAM VESSEL B155;Lo;0;L;;;;;N;;;;; 100DF;LINEAR B IDEOGRAM VESSEL B200;Lo;0;L;;;;;N;;;;; 100E0;LINEAR B IDEOGRAM VESSEL B201;Lo;0;L;;;;;N;;;;; 100E1;LINEAR B IDEOGRAM VESSEL B202;Lo;0;L;;;;;N;;;;; 100E2;LINEAR B IDEOGRAM VESSEL B203;Lo;0;L;;;;;N;;;;; 100E3;LINEAR B IDEOGRAM VESSEL B204;Lo;0;L;;;;;N;;;;; 100E4;LINEAR B IDEOGRAM VESSEL B205;Lo;0;L;;;;;N;;;;; 100E5;LINEAR B IDEOGRAM VESSEL B206;Lo;0;L;;;;;N;;;;; 100E6;LINEAR B IDEOGRAM VESSEL B207;Lo;0;L;;;;;N;;;;; 100E7;LINEAR B IDEOGRAM VESSEL B208;Lo;0;L;;;;;N;;;;; 100E8;LINEAR B IDEOGRAM VESSEL B209;Lo;0;L;;;;;N;;;;; 100E9;LINEAR B IDEOGRAM VESSEL B210;Lo;0;L;;;;;N;;;;; 100EA;LINEAR B IDEOGRAM VESSEL B211;Lo;0;L;;;;;N;;;;; 100EB;LINEAR B IDEOGRAM VESSEL B212;Lo;0;L;;;;;N;;;;; 100EC;LINEAR B IDEOGRAM VESSEL B213;Lo;0;L;;;;;N;;;;; 100ED;LINEAR B IDEOGRAM VESSEL B214;Lo;0;L;;;;;N;;;;; 100EE;LINEAR B IDEOGRAM VESSEL B215;Lo;0;L;;;;;N;;;;; 100EF;LINEAR B IDEOGRAM VESSEL B216;Lo;0;L;;;;;N;;;;; 100F0;LINEAR B IDEOGRAM VESSEL B217;Lo;0;L;;;;;N;;;;; 100F1;LINEAR B IDEOGRAM VESSEL B218;Lo;0;L;;;;;N;;;;; 100F2;LINEAR B IDEOGRAM VESSEL B219;Lo;0;L;;;;;N;;;;; 100F3;LINEAR B IDEOGRAM VESSEL B221;Lo;0;L;;;;;N;;;;; 100F4;LINEAR B IDEOGRAM VESSEL B222;Lo;0;L;;;;;N;;;;; 100F5;LINEAR B IDEOGRAM VESSEL B226;Lo;0;L;;;;;N;;;;; 100F6;LINEAR B IDEOGRAM VESSEL B227;Lo;0;L;;;;;N;;;;; 100F7;LINEAR B IDEOGRAM VESSEL B228;Lo;0;L;;;;;N;;;;; 100F8;LINEAR B IDEOGRAM VESSEL B229;Lo;0;L;;;;;N;;;;; 100F9;LINEAR B IDEOGRAM VESSEL B250;Lo;0;L;;;;;N;;;;; 100FA;LINEAR B IDEOGRAM VESSEL B305;Lo;0;L;;;;;N;;;;; 10100;AEGEAN WORD SEPARATOR LINE;Po;0;L;;;;;N;;;;; 10101;AEGEAN WORD SEPARATOR DOT;Po;0;ON;;;;;N;;;;; 10102;AEGEAN CHECK MARK;Po;0;L;;;;;N;;;;; 10107;AEGEAN NUMBER ONE;No;0;L;;;;1;N;;;;; 10108;AEGEAN NUMBER TWO;No;0;L;;;;2;N;;;;; 10109;AEGEAN NUMBER THREE;No;0;L;;;;3;N;;;;; 1010A;AEGEAN NUMBER FOUR;No;0;L;;;;4;N;;;;; 1010B;AEGEAN NUMBER FIVE;No;0;L;;;;5;N;;;;; 1010C;AEGEAN NUMBER SIX;No;0;L;;;;6;N;;;;; 1010D;AEGEAN NUMBER SEVEN;No;0;L;;;;7;N;;;;; 1010E;AEGEAN NUMBER EIGHT;No;0;L;;;;8;N;;;;; 1010F;AEGEAN NUMBER NINE;No;0;L;;;;9;N;;;;; 10110;AEGEAN NUMBER TEN;No;0;L;;;;10;N;;;;; 10111;AEGEAN NUMBER TWENTY;No;0;L;;;;20;N;;;;; 10112;AEGEAN NUMBER THIRTY;No;0;L;;;;30;N;;;;; 10113;AEGEAN NUMBER FORTY;No;0;L;;;;40;N;;;;; 10114;AEGEAN NUMBER FIFTY;No;0;L;;;;50;N;;;;; 10115;AEGEAN NUMBER SIXTY;No;0;L;;;;60;N;;;;; 10116;AEGEAN NUMBER SEVENTY;No;0;L;;;;70;N;;;;; 10117;AEGEAN NUMBER EIGHTY;No;0;L;;;;80;N;;;;; 10118;AEGEAN NUMBER NINETY;No;0;L;;;;90;N;;;;; 10119;AEGEAN NUMBER ONE HUNDRED;No;0;L;;;;100;N;;;;; 1011A;AEGEAN NUMBER TWO HUNDRED;No;0;L;;;;200;N;;;;; 1011B;AEGEAN NUMBER THREE HUNDRED;No;0;L;;;;300;N;;;;; 1011C;AEGEAN NUMBER FOUR HUNDRED;No;0;L;;;;400;N;;;;; 1011D;AEGEAN NUMBER FIVE HUNDRED;No;0;L;;;;500;N;;;;; 1011E;AEGEAN NUMBER SIX HUNDRED;No;0;L;;;;600;N;;;;; 1011F;AEGEAN NUMBER SEVEN HUNDRED;No;0;L;;;;700;N;;;;; 10120;AEGEAN NUMBER EIGHT HUNDRED;No;0;L;;;;800;N;;;;; 10121;AEGEAN NUMBER NINE HUNDRED;No;0;L;;;;900;N;;;;; 10122;AEGEAN NUMBER ONE THOUSAND;No;0;L;;;;1000;N;;;;; 10123;AEGEAN NUMBER TWO THOUSAND;No;0;L;;;;2000;N;;;;; 10124;AEGEAN NUMBER THREE THOUSAND;No;0;L;;;;3000;N;;;;; 10125;AEGEAN NUMBER FOUR THOUSAND;No;0;L;;;;4000;N;;;;; 10126;AEGEAN NUMBER FIVE THOUSAND;No;0;L;;;;5000;N;;;;; 10127;AEGEAN NUMBER SIX THOUSAND;No;0;L;;;;6000;N;;;;; 10128;AEGEAN NUMBER SEVEN THOUSAND;No;0;L;;;;7000;N;;;;; 10129;AEGEAN NUMBER EIGHT THOUSAND;No;0;L;;;;8000;N;;;;; 1012A;AEGEAN NUMBER NINE THOUSAND;No;0;L;;;;9000;N;;;;; 1012B;AEGEAN NUMBER TEN THOUSAND;No;0;L;;;;10000;N;;;;; 1012C;AEGEAN NUMBER TWENTY THOUSAND;No;0;L;;;;20000;N;;;;; 1012D;AEGEAN NUMBER THIRTY THOUSAND;No;0;L;;;;30000;N;;;;; 1012E;AEGEAN NUMBER FORTY THOUSAND;No;0;L;;;;40000;N;;;;; 1012F;AEGEAN NUMBER FIFTY THOUSAND;No;0;L;;;;50000;N;;;;; 10130;AEGEAN NUMBER SIXTY THOUSAND;No;0;L;;;;60000;N;;;;; 10131;AEGEAN NUMBER SEVENTY THOUSAND;No;0;L;;;;70000;N;;;;; 10132;AEGEAN NUMBER EIGHTY THOUSAND;No;0;L;;;;80000;N;;;;; 10133;AEGEAN NUMBER NINETY THOUSAND;No;0;L;;;;90000;N;;;;; 10137;AEGEAN WEIGHT BASE UNIT;So;0;L;;;;;N;;;;; 10138;AEGEAN WEIGHT FIRST SUBUNIT;So;0;L;;;;;N;;;;; 10139;AEGEAN WEIGHT SECOND SUBUNIT;So;0;L;;;;;N;;;;; 1013A;AEGEAN WEIGHT THIRD SUBUNIT;So;0;L;;;;;N;;;;; 1013B;AEGEAN WEIGHT FOURTH SUBUNIT;So;0;L;;;;;N;;;;; 1013C;AEGEAN DRY MEASURE FIRST SUBUNIT;So;0;L;;;;;N;;;;; 1013D;AEGEAN LIQUID MEASURE FIRST SUBUNIT;So;0;L;;;;;N;;;;; 1013E;AEGEAN MEASURE SECOND SUBUNIT;So;0;L;;;;;N;;;;; 1013F;AEGEAN MEASURE THIRD SUBUNIT;So;0;L;;;;;N;;;;; 10140;GREEK ACROPHONIC ATTIC ONE QUARTER;Nl;0;ON;;;;1/4;N;;;;; 10141;GREEK ACROPHONIC ATTIC ONE HALF;Nl;0;ON;;;;1/2;N;;;;; 10142;GREEK ACROPHONIC ATTIC ONE DRACHMA;Nl;0;ON;;;;1;N;;;;; 10143;GREEK ACROPHONIC ATTIC FIVE;Nl;0;ON;;;;5;N;;;;; 10144;GREEK ACROPHONIC ATTIC FIFTY;Nl;0;ON;;;;50;N;;;;; 10145;GREEK ACROPHONIC ATTIC FIVE HUNDRED;Nl;0;ON;;;;500;N;;;;; 10146;GREEK ACROPHONIC ATTIC FIVE THOUSAND;Nl;0;ON;;;;5000;N;;;;; 10147;GREEK ACROPHONIC ATTIC FIFTY THOUSAND;Nl;0;ON;;;;50000;N;;;;; 10148;GREEK ACROPHONIC ATTIC FIVE TALENTS;Nl;0;ON;;;;5;N;;;;; 10149;GREEK ACROPHONIC ATTIC TEN TALENTS;Nl;0;ON;;;;10;N;;;;; 1014A;GREEK ACROPHONIC ATTIC FIFTY TALENTS;Nl;0;ON;;;;50;N;;;;; 1014B;GREEK ACROPHONIC ATTIC ONE HUNDRED TALENTS;Nl;0;ON;;;;100;N;;;;; 1014C;GREEK ACROPHONIC ATTIC FIVE HUNDRED TALENTS;Nl;0;ON;;;;500;N;;;;; 1014D;GREEK ACROPHONIC ATTIC ONE THOUSAND TALENTS;Nl;0;ON;;;;1000;N;;;;; 1014E;GREEK ACROPHONIC ATTIC FIVE THOUSAND TALENTS;Nl;0;ON;;;;5000;N;;;;; 1014F;GREEK ACROPHONIC ATTIC FIVE STATERS;Nl;0;ON;;;;5;N;;;;; 10150;GREEK ACROPHONIC ATTIC TEN STATERS;Nl;0;ON;;;;10;N;;;;; 10151;GREEK ACROPHONIC ATTIC FIFTY STATERS;Nl;0;ON;;;;50;N;;;;; 10152;GREEK ACROPHONIC ATTIC ONE HUNDRED STATERS;Nl;0;ON;;;;100;N;;;;; 10153;GREEK ACROPHONIC ATTIC FIVE HUNDRED STATERS;Nl;0;ON;;;;500;N;;;;; 10154;GREEK ACROPHONIC ATTIC ONE THOUSAND STATERS;Nl;0;ON;;;;1000;N;;;;; 10155;GREEK ACROPHONIC ATTIC TEN THOUSAND STATERS;Nl;0;ON;;;;10000;N;;;;; 10156;GREEK ACROPHONIC ATTIC FIFTY THOUSAND STATERS;Nl;0;ON;;;;50000;N;;;;; 10157;GREEK ACROPHONIC ATTIC TEN MNAS;Nl;0;ON;;;;10;N;;;;; 10158;GREEK ACROPHONIC HERAEUM ONE PLETHRON;Nl;0;ON;;;;1;N;;;;; 10159;GREEK ACROPHONIC THESPIAN ONE;Nl;0;ON;;;;1;N;;;;; 1015A;GREEK ACROPHONIC HERMIONIAN ONE;Nl;0;ON;;;;1;N;;;;; 1015B;GREEK ACROPHONIC EPIDAUREAN TWO;Nl;0;ON;;;;2;N;;;;; 1015C;GREEK ACROPHONIC THESPIAN TWO;Nl;0;ON;;;;2;N;;;;; 1015D;GREEK ACROPHONIC CYRENAIC TWO DRACHMAS;Nl;0;ON;;;;2;N;;;;; 1015E;GREEK ACROPHONIC EPIDAUREAN TWO DRACHMAS;Nl;0;ON;;;;2;N;;;;; 1015F;GREEK ACROPHONIC TROEZENIAN FIVE;Nl;0;ON;;;;5;N;;;;; 10160;GREEK ACROPHONIC TROEZENIAN TEN;Nl;0;ON;;;;10;N;;;;; 10161;GREEK ACROPHONIC TROEZENIAN TEN ALTERNATE FORM;Nl;0;ON;;;;10;N;;;;; 10162;GREEK ACROPHONIC HERMIONIAN TEN;Nl;0;ON;;;;10;N;;;;; 10163;GREEK ACROPHONIC MESSENIAN TEN;Nl;0;ON;;;;10;N;;;;; 10164;GREEK ACROPHONIC THESPIAN TEN;Nl;0;ON;;;;10;N;;;;; 10165;GREEK ACROPHONIC THESPIAN THIRTY;Nl;0;ON;;;;30;N;;;;; 10166;GREEK ACROPHONIC TROEZENIAN FIFTY;Nl;0;ON;;;;50;N;;;;; 10167;GREEK ACROPHONIC TROEZENIAN FIFTY ALTERNATE FORM;Nl;0;ON;;;;50;N;;;;; 10168;GREEK ACROPHONIC HERMIONIAN FIFTY;Nl;0;ON;;;;50;N;;;;; 10169;GREEK ACROPHONIC THESPIAN FIFTY;Nl;0;ON;;;;50;N;;;;; 1016A;GREEK ACROPHONIC THESPIAN ONE HUNDRED;Nl;0;ON;;;;100;N;;;;; 1016B;GREEK ACROPHONIC THESPIAN THREE HUNDRED;Nl;0;ON;;;;300;N;;;;; 1016C;GREEK ACROPHONIC EPIDAUREAN FIVE HUNDRED;Nl;0;ON;;;;500;N;;;;; 1016D;GREEK ACROPHONIC TROEZENIAN FIVE HUNDRED;Nl;0;ON;;;;500;N;;;;; 1016E;GREEK ACROPHONIC THESPIAN FIVE HUNDRED;Nl;0;ON;;;;500;N;;;;; 1016F;GREEK ACROPHONIC CARYSTIAN FIVE HUNDRED;Nl;0;ON;;;;500;N;;;;; 10170;GREEK ACROPHONIC NAXIAN FIVE HUNDRED;Nl;0;ON;;;;500;N;;;;; 10171;GREEK ACROPHONIC THESPIAN ONE THOUSAND;Nl;0;ON;;;;1000;N;;;;; 10172;GREEK ACROPHONIC THESPIAN FIVE THOUSAND;Nl;0;ON;;;;5000;N;;;;; 10173;GREEK ACROPHONIC DELPHIC FIVE MNAS;Nl;0;ON;;;;5;N;;;;; 10174;GREEK ACROPHONIC STRATIAN FIFTY MNAS;Nl;0;ON;;;;50;N;;;;; 10175;GREEK ONE HALF SIGN;No;0;ON;;;;1/2;N;;;;; 10176;GREEK ONE HALF SIGN ALTERNATE FORM;No;0;ON;;;;1/2;N;;;;; 10177;GREEK TWO THIRDS SIGN;No;0;ON;;;;2/3;N;;;;; 10178;GREEK THREE QUARTERS SIGN;No;0;ON;;;;3/4;N;;;;; 10179;GREEK YEAR SIGN;So;0;ON;;;;;N;;;;; 1017A;GREEK TALENT SIGN;So;0;ON;;;;;N;;;;; 1017B;GREEK DRACHMA SIGN;So;0;ON;;;;;N;;;;; 1017C;GREEK OBOL SIGN;So;0;ON;;;;;N;;;;; 1017D;GREEK TWO OBOLS SIGN;So;0;ON;;;;;N;;;;; 1017E;GREEK THREE OBOLS SIGN;So;0;ON;;;;;N;;;;; 1017F;GREEK FOUR OBOLS SIGN;So;0;ON;;;;;N;;;;; 10180;GREEK FIVE OBOLS SIGN;So;0;ON;;;;;N;;;;; 10181;GREEK METRETES SIGN;So;0;ON;;;;;N;;;;; 10182;GREEK KYATHOS BASE SIGN;So;0;ON;;;;;N;;;;; 10183;GREEK LITRA SIGN;So;0;ON;;;;;N;;;;; 10184;GREEK OUNKIA SIGN;So;0;ON;;;;;N;;;;; 10185;GREEK XESTES SIGN;So;0;ON;;;;;N;;;;; 10186;GREEK ARTABE SIGN;So;0;ON;;;;;N;;;;; 10187;GREEK AROURA SIGN;So;0;ON;;;;;N;;;;; 10188;GREEK GRAMMA SIGN;So;0;ON;;;;;N;;;;; 10189;GREEK TRYBLION BASE SIGN;So;0;ON;;;;;N;;;;; 1018A;GREEK ZERO SIGN;No;0;ON;;;;0;N;;;;; 1018B;GREEK ONE QUARTER SIGN;No;0;ON;;;;1/4;N;;;;; 1018C;GREEK SINUSOID SIGN;So;0;ON;;;;;N;;;;; 1018D;GREEK INDICTION SIGN;So;0;L;;;;;N;;;;; 1018E;NOMISMA SIGN;So;0;L;;;;;N;;;;; 10190;ROMAN SEXTANS SIGN;So;0;ON;;;;;N;;;;; 10191;ROMAN UNCIA SIGN;So;0;ON;;;;;N;;;;; 10192;ROMAN SEMUNCIA SIGN;So;0;ON;;;;;N;;;;; 10193;ROMAN SEXTULA SIGN;So;0;ON;;;;;N;;;;; 10194;ROMAN DIMIDIA SEXTULA SIGN;So;0;ON;;;;;N;;;;; 10195;ROMAN SILIQUA SIGN;So;0;ON;;;;;N;;;;; 10196;ROMAN DENARIUS SIGN;So;0;ON;;;;;N;;;;; 10197;ROMAN QUINARIUS SIGN;So;0;ON;;;;;N;;;;; 10198;ROMAN SESTERTIUS SIGN;So;0;ON;;;;;N;;;;; 10199;ROMAN DUPONDIUS SIGN;So;0;ON;;;;;N;;;;; 1019A;ROMAN AS SIGN;So;0;ON;;;;;N;;;;; 1019B;ROMAN CENTURIAL SIGN;So;0;ON;;;;;N;;;;; 101A0;GREEK SYMBOL TAU RHO;So;0;ON;;;;;N;;;;; 101D0;PHAISTOS DISC SIGN PEDESTRIAN;So;0;L;;;;;N;;;;; 101D1;PHAISTOS DISC SIGN PLUMED HEAD;So;0;L;;;;;N;;;;; 101D2;PHAISTOS DISC SIGN TATTOOED HEAD;So;0;L;;;;;N;;;;; 101D3;PHAISTOS DISC SIGN CAPTIVE;So;0;L;;;;;N;;;;; 101D4;PHAISTOS DISC SIGN CHILD;So;0;L;;;;;N;;;;; 101D5;PHAISTOS DISC SIGN WOMAN;So;0;L;;;;;N;;;;; 101D6;PHAISTOS DISC SIGN HELMET;So;0;L;;;;;N;;;;; 101D7;PHAISTOS DISC SIGN GAUNTLET;So;0;L;;;;;N;;;;; 101D8;PHAISTOS DISC SIGN TIARA;So;0;L;;;;;N;;;;; 101D9;PHAISTOS DISC SIGN ARROW;So;0;L;;;;;N;;;;; 101DA;PHAISTOS DISC SIGN BOW;So;0;L;;;;;N;;;;; 101DB;PHAISTOS DISC SIGN SHIELD;So;0;L;;;;;N;;;;; 101DC;PHAISTOS DISC SIGN CLUB;So;0;L;;;;;N;;;;; 101DD;PHAISTOS DISC SIGN MANACLES;So;0;L;;;;;N;;;;; 101DE;PHAISTOS DISC SIGN MATTOCK;So;0;L;;;;;N;;;;; 101DF;PHAISTOS DISC SIGN SAW;So;0;L;;;;;N;;;;; 101E0;PHAISTOS DISC SIGN LID;So;0;L;;;;;N;;;;; 101E1;PHAISTOS DISC SIGN BOOMERANG;So;0;L;;;;;N;;;;; 101E2;PHAISTOS DISC SIGN CARPENTRY PLANE;So;0;L;;;;;N;;;;; 101E3;PHAISTOS DISC SIGN DOLIUM;So;0;L;;;;;N;;;;; 101E4;PHAISTOS DISC SIGN COMB;So;0;L;;;;;N;;;;; 101E5;PHAISTOS DISC SIGN SLING;So;0;L;;;;;N;;;;; 101E6;PHAISTOS DISC SIGN COLUMN;So;0;L;;;;;N;;;;; 101E7;PHAISTOS DISC SIGN BEEHIVE;So;0;L;;;;;N;;;;; 101E8;PHAISTOS DISC SIGN SHIP;So;0;L;;;;;N;;;;; 101E9;PHAISTOS DISC SIGN HORN;So;0;L;;;;;N;;;;; 101EA;PHAISTOS DISC SIGN HIDE;So;0;L;;;;;N;;;;; 101EB;PHAISTOS DISC SIGN BULLS LEG;So;0;L;;;;;N;;;;; 101EC;PHAISTOS DISC SIGN CAT;So;0;L;;;;;N;;;;; 101ED;PHAISTOS DISC SIGN RAM;So;0;L;;;;;N;;;;; 101EE;PHAISTOS DISC SIGN EAGLE;So;0;L;;;;;N;;;;; 101EF;PHAISTOS DISC SIGN DOVE;So;0;L;;;;;N;;;;; 101F0;PHAISTOS DISC SIGN TUNNY;So;0;L;;;;;N;;;;; 101F1;PHAISTOS DISC SIGN BEE;So;0;L;;;;;N;;;;; 101F2;PHAISTOS DISC SIGN PLANE TREE;So;0;L;;;;;N;;;;; 101F3;PHAISTOS DISC SIGN VINE;So;0;L;;;;;N;;;;; 101F4;PHAISTOS DISC SIGN PAPYRUS;So;0;L;;;;;N;;;;; 101F5;PHAISTOS DISC SIGN ROSETTE;So;0;L;;;;;N;;;;; 101F6;PHAISTOS DISC SIGN LILY;So;0;L;;;;;N;;;;; 101F7;PHAISTOS DISC SIGN OX BACK;So;0;L;;;;;N;;;;; 101F8;PHAISTOS DISC SIGN FLUTE;So;0;L;;;;;N;;;;; 101F9;PHAISTOS DISC SIGN GRATER;So;0;L;;;;;N;;;;; 101FA;PHAISTOS DISC SIGN STRAINER;So;0;L;;;;;N;;;;; 101FB;PHAISTOS DISC SIGN SMALL AXE;So;0;L;;;;;N;;;;; 101FC;PHAISTOS DISC SIGN WAVY BAND;So;0;L;;;;;N;;;;; 101FD;PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE;Mn;220;NSM;;;;;N;;;;; 10280;LYCIAN LETTER A;Lo;0;L;;;;;N;;;;; 10281;LYCIAN LETTER E;Lo;0;L;;;;;N;;;;; 10282;LYCIAN LETTER B;Lo;0;L;;;;;N;;;;; 10283;LYCIAN LETTER BH;Lo;0;L;;;;;N;;;;; 10284;LYCIAN LETTER G;Lo;0;L;;;;;N;;;;; 10285;LYCIAN LETTER D;Lo;0;L;;;;;N;;;;; 10286;LYCIAN LETTER I;Lo;0;L;;;;;N;;;;; 10287;LYCIAN LETTER W;Lo;0;L;;;;;N;;;;; 10288;LYCIAN LETTER Z;Lo;0;L;;;;;N;;;;; 10289;LYCIAN LETTER TH;Lo;0;L;;;;;N;;;;; 1028A;LYCIAN LETTER J;Lo;0;L;;;;;N;;;;; 1028B;LYCIAN LETTER K;Lo;0;L;;;;;N;;;;; 1028C;LYCIAN LETTER Q;Lo;0;L;;;;;N;;;;; 1028D;LYCIAN LETTER L;Lo;0;L;;;;;N;;;;; 1028E;LYCIAN LETTER M;Lo;0;L;;;;;N;;;;; 1028F;LYCIAN LETTER N;Lo;0;L;;;;;N;;;;; 10290;LYCIAN LETTER MM;Lo;0;L;;;;;N;;;;; 10291;LYCIAN LETTER NN;Lo;0;L;;;;;N;;;;; 10292;LYCIAN LETTER U;Lo;0;L;;;;;N;;;;; 10293;LYCIAN LETTER P;Lo;0;L;;;;;N;;;;; 10294;LYCIAN LETTER KK;Lo;0;L;;;;;N;;;;; 10295;LYCIAN LETTER R;Lo;0;L;;;;;N;;;;; 10296;LYCIAN LETTER S;Lo;0;L;;;;;N;;;;; 10297;LYCIAN LETTER T;Lo;0;L;;;;;N;;;;; 10298;LYCIAN LETTER TT;Lo;0;L;;;;;N;;;;; 10299;LYCIAN LETTER AN;Lo;0;L;;;;;N;;;;; 1029A;LYCIAN LETTER EN;Lo;0;L;;;;;N;;;;; 1029B;LYCIAN LETTER H;Lo;0;L;;;;;N;;;;; 1029C;LYCIAN LETTER X;Lo;0;L;;;;;N;;;;; 102A0;CARIAN LETTER A;Lo;0;L;;;;;N;;;;; 102A1;CARIAN LETTER P2;Lo;0;L;;;;;N;;;;; 102A2;CARIAN LETTER D;Lo;0;L;;;;;N;;;;; 102A3;CARIAN LETTER L;Lo;0;L;;;;;N;;;;; 102A4;CARIAN LETTER UUU;Lo;0;L;;;;;N;;;;; 102A5;CARIAN LETTER R;Lo;0;L;;;;;N;;;;; 102A6;CARIAN LETTER LD;Lo;0;L;;;;;N;;;;; 102A7;CARIAN LETTER A2;Lo;0;L;;;;;N;;;;; 102A8;CARIAN LETTER Q;Lo;0;L;;;;;N;;;;; 102A9;CARIAN LETTER B;Lo;0;L;;;;;N;;;;; 102AA;CARIAN LETTER M;Lo;0;L;;;;;N;;;;; 102AB;CARIAN LETTER O;Lo;0;L;;;;;N;;;;; 102AC;CARIAN LETTER D2;Lo;0;L;;;;;N;;;;; 102AD;CARIAN LETTER T;Lo;0;L;;;;;N;;;;; 102AE;CARIAN LETTER SH;Lo;0;L;;;;;N;;;;; 102AF;CARIAN LETTER SH2;Lo;0;L;;;;;N;;;;; 102B0;CARIAN LETTER S;Lo;0;L;;;;;N;;;;; 102B1;CARIAN LETTER C-18;Lo;0;L;;;;;N;;;;; 102B2;CARIAN LETTER U;Lo;0;L;;;;;N;;;;; 102B3;CARIAN LETTER NN;Lo;0;L;;;;;N;;;;; 102B4;CARIAN LETTER X;Lo;0;L;;;;;N;;;;; 102B5;CARIAN LETTER N;Lo;0;L;;;;;N;;;;; 102B6;CARIAN LETTER TT2;Lo;0;L;;;;;N;;;;; 102B7;CARIAN LETTER P;Lo;0;L;;;;;N;;;;; 102B8;CARIAN LETTER SS;Lo;0;L;;;;;N;;;;; 102B9;CARIAN LETTER I;Lo;0;L;;;;;N;;;;; 102BA;CARIAN LETTER E;Lo;0;L;;;;;N;;;;; 102BB;CARIAN LETTER UUUU;Lo;0;L;;;;;N;;;;; 102BC;CARIAN LETTER K;Lo;0;L;;;;;N;;;;; 102BD;CARIAN LETTER K2;Lo;0;L;;;;;N;;;;; 102BE;CARIAN LETTER ND;Lo;0;L;;;;;N;;;;; 102BF;CARIAN LETTER UU;Lo;0;L;;;;;N;;;;; 102C0;CARIAN LETTER G;Lo;0;L;;;;;N;;;;; 102C1;CARIAN LETTER G2;Lo;0;L;;;;;N;;;;; 102C2;CARIAN LETTER ST;Lo;0;L;;;;;N;;;;; 102C3;CARIAN LETTER ST2;Lo;0;L;;;;;N;;;;; 102C4;CARIAN LETTER NG;Lo;0;L;;;;;N;;;;; 102C5;CARIAN LETTER II;Lo;0;L;;;;;N;;;;; 102C6;CARIAN LETTER C-39;Lo;0;L;;;;;N;;;;; 102C7;CARIAN LETTER TT;Lo;0;L;;;;;N;;;;; 102C8;CARIAN LETTER UUU2;Lo;0;L;;;;;N;;;;; 102C9;CARIAN LETTER RR;Lo;0;L;;;;;N;;;;; 102CA;CARIAN LETTER MB;Lo;0;L;;;;;N;;;;; 102CB;CARIAN LETTER MB2;Lo;0;L;;;;;N;;;;; 102CC;CARIAN LETTER MB3;Lo;0;L;;;;;N;;;;; 102CD;CARIAN LETTER MB4;Lo;0;L;;;;;N;;;;; 102CE;CARIAN LETTER LD2;Lo;0;L;;;;;N;;;;; 102CF;CARIAN LETTER E2;Lo;0;L;;;;;N;;;;; 102D0;CARIAN LETTER UUU3;Lo;0;L;;;;;N;;;;; 102E0;COPTIC EPACT THOUSANDS MARK;Mn;220;NSM;;;;;N;;;;; 102E1;COPTIC EPACT DIGIT ONE;No;0;EN;;;;1;N;;;;; 102E2;COPTIC EPACT DIGIT TWO;No;0;EN;;;;2;N;;;;; 102E3;COPTIC EPACT DIGIT THREE;No;0;EN;;;;3;N;;;;; 102E4;COPTIC EPACT DIGIT FOUR;No;0;EN;;;;4;N;;;;; 102E5;COPTIC EPACT DIGIT FIVE;No;0;EN;;;;5;N;;;;; 102E6;COPTIC EPACT DIGIT SIX;No;0;EN;;;;6;N;;;;; 102E7;COPTIC EPACT DIGIT SEVEN;No;0;EN;;;;7;N;;;;; 102E8;COPTIC EPACT DIGIT EIGHT;No;0;EN;;;;8;N;;;;; 102E9;COPTIC EPACT DIGIT NINE;No;0;EN;;;;9;N;;;;; 102EA;COPTIC EPACT NUMBER TEN;No;0;EN;;;;10;N;;;;; 102EB;COPTIC EPACT NUMBER TWENTY;No;0;EN;;;;20;N;;;;; 102EC;COPTIC EPACT NUMBER THIRTY;No;0;EN;;;;30;N;;;;; 102ED;COPTIC EPACT NUMBER FORTY;No;0;EN;;;;40;N;;;;; 102EE;COPTIC EPACT NUMBER FIFTY;No;0;EN;;;;50;N;;;;; 102EF;COPTIC EPACT NUMBER SIXTY;No;0;EN;;;;60;N;;;;; 102F0;COPTIC EPACT NUMBER SEVENTY;No;0;EN;;;;70;N;;;;; 102F1;COPTIC EPACT NUMBER EIGHTY;No;0;EN;;;;80;N;;;;; 102F2;COPTIC EPACT NUMBER NINETY;No;0;EN;;;;90;N;;;;; 102F3;COPTIC EPACT NUMBER ONE HUNDRED;No;0;EN;;;;100;N;;;;; 102F4;COPTIC EPACT NUMBER TWO HUNDRED;No;0;EN;;;;200;N;;;;; 102F5;COPTIC EPACT NUMBER THREE HUNDRED;No;0;EN;;;;300;N;;;;; 102F6;COPTIC EPACT NUMBER FOUR HUNDRED;No;0;EN;;;;400;N;;;;; 102F7;COPTIC EPACT NUMBER FIVE HUNDRED;No;0;EN;;;;500;N;;;;; 102F8;COPTIC EPACT NUMBER SIX HUNDRED;No;0;EN;;;;600;N;;;;; 102F9;COPTIC EPACT NUMBER SEVEN HUNDRED;No;0;EN;;;;700;N;;;;; 102FA;COPTIC EPACT NUMBER EIGHT HUNDRED;No;0;EN;;;;800;N;;;;; 102FB;COPTIC EPACT NUMBER NINE HUNDRED;No;0;EN;;;;900;N;;;;; 10300;OLD ITALIC LETTER A;Lo;0;L;;;;;N;;;;; 10301;OLD ITALIC LETTER BE;Lo;0;L;;;;;N;;;;; 10302;OLD ITALIC LETTER KE;Lo;0;L;;;;;N;;;;; 10303;OLD ITALIC LETTER DE;Lo;0;L;;;;;N;;;;; 10304;OLD ITALIC LETTER E;Lo;0;L;;;;;N;;;;; 10305;OLD ITALIC LETTER VE;Lo;0;L;;;;;N;;;;; 10306;OLD ITALIC LETTER ZE;Lo;0;L;;;;;N;;;;; 10307;OLD ITALIC LETTER HE;Lo;0;L;;;;;N;;;;; 10308;OLD ITALIC LETTER THE;Lo;0;L;;;;;N;;;;; 10309;OLD ITALIC LETTER I;Lo;0;L;;;;;N;;;;; 1030A;OLD ITALIC LETTER KA;Lo;0;L;;;;;N;;;;; 1030B;OLD ITALIC LETTER EL;Lo;0;L;;;;;N;;;;; 1030C;OLD ITALIC LETTER EM;Lo;0;L;;;;;N;;;;; 1030D;OLD ITALIC LETTER EN;Lo;0;L;;;;;N;;;;; 1030E;OLD ITALIC LETTER ESH;Lo;0;L;;;;;N;;;;; 1030F;OLD ITALIC LETTER O;Lo;0;L;;;;;N;;;;; 10310;OLD ITALIC LETTER PE;Lo;0;L;;;;;N;;;;; 10311;OLD ITALIC LETTER SHE;Lo;0;L;;;;;N;;;;; 10312;OLD ITALIC LETTER KU;Lo;0;L;;;;;N;;;;; 10313;OLD ITALIC LETTER ER;Lo;0;L;;;;;N;;;;; 10314;OLD ITALIC LETTER ES;Lo;0;L;;;;;N;;;;; 10315;OLD ITALIC LETTER TE;Lo;0;L;;;;;N;;;;; 10316;OLD ITALIC LETTER U;Lo;0;L;;;;;N;;;;; 10317;OLD ITALIC LETTER EKS;Lo;0;L;;;;;N;;;;; 10318;OLD ITALIC LETTER PHE;Lo;0;L;;;;;N;;;;; 10319;OLD ITALIC LETTER KHE;Lo;0;L;;;;;N;;;;; 1031A;OLD ITALIC LETTER EF;Lo;0;L;;;;;N;;;;; 1031B;OLD ITALIC LETTER ERS;Lo;0;L;;;;;N;;;;; 1031C;OLD ITALIC LETTER CHE;Lo;0;L;;;;;N;;;;; 1031D;OLD ITALIC LETTER II;Lo;0;L;;;;;N;;;;; 1031E;OLD ITALIC LETTER UU;Lo;0;L;;;;;N;;;;; 1031F;OLD ITALIC LETTER ESS;Lo;0;L;;;;;N;;;;; 10320;OLD ITALIC NUMERAL ONE;No;0;L;;;;1;N;;;;; 10321;OLD ITALIC NUMERAL FIVE;No;0;L;;;;5;N;;;;; 10322;OLD ITALIC NUMERAL TEN;No;0;L;;;;10;N;;;;; 10323;OLD ITALIC NUMERAL FIFTY;No;0;L;;;;50;N;;;;; 10330;GOTHIC LETTER AHSA;Lo;0;L;;;;;N;;;;; 10331;GOTHIC LETTER BAIRKAN;Lo;0;L;;;;;N;;;;; 10332;GOTHIC LETTER GIBA;Lo;0;L;;;;;N;;;;; 10333;GOTHIC LETTER DAGS;Lo;0;L;;;;;N;;;;; 10334;GOTHIC LETTER AIHVUS;Lo;0;L;;;;;N;;;;; 10335;GOTHIC LETTER QAIRTHRA;Lo;0;L;;;;;N;;;;; 10336;GOTHIC LETTER IUJA;Lo;0;L;;;;;N;;;;; 10337;GOTHIC LETTER HAGL;Lo;0;L;;;;;N;;;;; 10338;GOTHIC LETTER THIUTH;Lo;0;L;;;;;N;;;;; 10339;GOTHIC LETTER EIS;Lo;0;L;;;;;N;;;;; 1033A;GOTHIC LETTER KUSMA;Lo;0;L;;;;;N;;;;; 1033B;GOTHIC LETTER LAGUS;Lo;0;L;;;;;N;;;;; 1033C;GOTHIC LETTER MANNA;Lo;0;L;;;;;N;;;;; 1033D;GOTHIC LETTER NAUTHS;Lo;0;L;;;;;N;;;;; 1033E;GOTHIC LETTER JER;Lo;0;L;;;;;N;;;;; 1033F;GOTHIC LETTER URUS;Lo;0;L;;;;;N;;;;; 10340;GOTHIC LETTER PAIRTHRA;Lo;0;L;;;;;N;;;;; 10341;GOTHIC LETTER NINETY;Nl;0;L;;;;90;N;;;;; 10342;GOTHIC LETTER RAIDA;Lo;0;L;;;;;N;;;;; 10343;GOTHIC LETTER SAUIL;Lo;0;L;;;;;N;;;;; 10344;GOTHIC LETTER TEIWS;Lo;0;L;;;;;N;;;;; 10345;GOTHIC LETTER WINJA;Lo;0;L;;;;;N;;;;; 10346;GOTHIC LETTER FAIHU;Lo;0;L;;;;;N;;;;; 10347;GOTHIC LETTER IGGWS;Lo;0;L;;;;;N;;;;; 10348;GOTHIC LETTER HWAIR;Lo;0;L;;;;;N;;;;; 10349;GOTHIC LETTER OTHAL;Lo;0;L;;;;;N;;;;; 1034A;GOTHIC LETTER NINE HUNDRED;Nl;0;L;;;;900;N;;;;; 10350;OLD PERMIC LETTER AN;Lo;0;L;;;;;N;;;;; 10351;OLD PERMIC LETTER BUR;Lo;0;L;;;;;N;;;;; 10352;OLD PERMIC LETTER GAI;Lo;0;L;;;;;N;;;;; 10353;OLD PERMIC LETTER DOI;Lo;0;L;;;;;N;;;;; 10354;OLD PERMIC LETTER E;Lo;0;L;;;;;N;;;;; 10355;OLD PERMIC LETTER ZHOI;Lo;0;L;;;;;N;;;;; 10356;OLD PERMIC LETTER DZHOI;Lo;0;L;;;;;N;;;;; 10357;OLD PERMIC LETTER ZATA;Lo;0;L;;;;;N;;;;; 10358;OLD PERMIC LETTER DZITA;Lo;0;L;;;;;N;;;;; 10359;OLD PERMIC LETTER I;Lo;0;L;;;;;N;;;;; 1035A;OLD PERMIC LETTER KOKE;Lo;0;L;;;;;N;;;;; 1035B;OLD PERMIC LETTER LEI;Lo;0;L;;;;;N;;;;; 1035C;OLD PERMIC LETTER MENOE;Lo;0;L;;;;;N;;;;; 1035D;OLD PERMIC LETTER NENOE;Lo;0;L;;;;;N;;;;; 1035E;OLD PERMIC LETTER VOOI;Lo;0;L;;;;;N;;;;; 1035F;OLD PERMIC LETTER PEEI;Lo;0;L;;;;;N;;;;; 10360;OLD PERMIC LETTER REI;Lo;0;L;;;;;N;;;;; 10361;OLD PERMIC LETTER SII;Lo;0;L;;;;;N;;;;; 10362;OLD PERMIC LETTER TAI;Lo;0;L;;;;;N;;;;; 10363;OLD PERMIC LETTER U;Lo;0;L;;;;;N;;;;; 10364;OLD PERMIC LETTER CHERY;Lo;0;L;;;;;N;;;;; 10365;OLD PERMIC LETTER SHOOI;Lo;0;L;;;;;N;;;;; 10366;OLD PERMIC LETTER SHCHOOI;Lo;0;L;;;;;N;;;;; 10367;OLD PERMIC LETTER YRY;Lo;0;L;;;;;N;;;;; 10368;OLD PERMIC LETTER YERU;Lo;0;L;;;;;N;;;;; 10369;OLD PERMIC LETTER O;Lo;0;L;;;;;N;;;;; 1036A;OLD PERMIC LETTER OO;Lo;0;L;;;;;N;;;;; 1036B;OLD PERMIC LETTER EF;Lo;0;L;;;;;N;;;;; 1036C;OLD PERMIC LETTER HA;Lo;0;L;;;;;N;;;;; 1036D;OLD PERMIC LETTER TSIU;Lo;0;L;;;;;N;;;;; 1036E;OLD PERMIC LETTER VER;Lo;0;L;;;;;N;;;;; 1036F;OLD PERMIC LETTER YER;Lo;0;L;;;;;N;;;;; 10370;OLD PERMIC LETTER YERI;Lo;0;L;;;;;N;;;;; 10371;OLD PERMIC LETTER YAT;Lo;0;L;;;;;N;;;;; 10372;OLD PERMIC LETTER IE;Lo;0;L;;;;;N;;;;; 10373;OLD PERMIC LETTER YU;Lo;0;L;;;;;N;;;;; 10374;OLD PERMIC LETTER YA;Lo;0;L;;;;;N;;;;; 10375;OLD PERMIC LETTER IA;Lo;0;L;;;;;N;;;;; 10376;COMBINING OLD PERMIC LETTER AN;Mn;230;NSM;;;;;N;;;;; 10377;COMBINING OLD PERMIC LETTER DOI;Mn;230;NSM;;;;;N;;;;; 10378;COMBINING OLD PERMIC LETTER ZATA;Mn;230;NSM;;;;;N;;;;; 10379;COMBINING OLD PERMIC LETTER NENOE;Mn;230;NSM;;;;;N;;;;; 1037A;COMBINING OLD PERMIC LETTER SII;Mn;230;NSM;;;;;N;;;;; 10380;UGARITIC LETTER ALPA;Lo;0;L;;;;;N;;;;; 10381;UGARITIC LETTER BETA;Lo;0;L;;;;;N;;;;; 10382;UGARITIC LETTER GAMLA;Lo;0;L;;;;;N;;;;; 10383;UGARITIC LETTER KHA;Lo;0;L;;;;;N;;;;; 10384;UGARITIC LETTER DELTA;Lo;0;L;;;;;N;;;;; 10385;UGARITIC LETTER HO;Lo;0;L;;;;;N;;;;; 10386;UGARITIC LETTER WO;Lo;0;L;;;;;N;;;;; 10387;UGARITIC LETTER ZETA;Lo;0;L;;;;;N;;;;; 10388;UGARITIC LETTER HOTA;Lo;0;L;;;;;N;;;;; 10389;UGARITIC LETTER TET;Lo;0;L;;;;;N;;;;; 1038A;UGARITIC LETTER YOD;Lo;0;L;;;;;N;;;;; 1038B;UGARITIC LETTER KAF;Lo;0;L;;;;;N;;;;; 1038C;UGARITIC LETTER SHIN;Lo;0;L;;;;;N;;;;; 1038D;UGARITIC LETTER LAMDA;Lo;0;L;;;;;N;;;;; 1038E;UGARITIC LETTER MEM;Lo;0;L;;;;;N;;;;; 1038F;UGARITIC LETTER DHAL;Lo;0;L;;;;;N;;;;; 10390;UGARITIC LETTER NUN;Lo;0;L;;;;;N;;;;; 10391;UGARITIC LETTER ZU;Lo;0;L;;;;;N;;;;; 10392;UGARITIC LETTER SAMKA;Lo;0;L;;;;;N;;;;; 10393;UGARITIC LETTER AIN;Lo;0;L;;;;;N;;;;; 10394;UGARITIC LETTER PU;Lo;0;L;;;;;N;;;;; 10395;UGARITIC LETTER SADE;Lo;0;L;;;;;N;;;;; 10396;UGARITIC LETTER QOPA;Lo;0;L;;;;;N;;;;; 10397;UGARITIC LETTER RASHA;Lo;0;L;;;;;N;;;;; 10398;UGARITIC LETTER THANNA;Lo;0;L;;;;;N;;;;; 10399;UGARITIC LETTER GHAIN;Lo;0;L;;;;;N;;;;; 1039A;UGARITIC LETTER TO;Lo;0;L;;;;;N;;;;; 1039B;UGARITIC LETTER I;Lo;0;L;;;;;N;;;;; 1039C;UGARITIC LETTER U;Lo;0;L;;;;;N;;;;; 1039D;UGARITIC LETTER SSU;Lo;0;L;;;;;N;;;;; 1039F;UGARITIC WORD DIVIDER;Po;0;L;;;;;N;;;;; 103A0;OLD PERSIAN SIGN A;Lo;0;L;;;;;N;;;;; 103A1;OLD PERSIAN SIGN I;Lo;0;L;;;;;N;;;;; 103A2;OLD PERSIAN SIGN U;Lo;0;L;;;;;N;;;;; 103A3;OLD PERSIAN SIGN KA;Lo;0;L;;;;;N;;;;; 103A4;OLD PERSIAN SIGN KU;Lo;0;L;;;;;N;;;;; 103A5;OLD PERSIAN SIGN GA;Lo;0;L;;;;;N;;;;; 103A6;OLD PERSIAN SIGN GU;Lo;0;L;;;;;N;;;;; 103A7;OLD PERSIAN SIGN XA;Lo;0;L;;;;;N;;;;; 103A8;OLD PERSIAN SIGN CA;Lo;0;L;;;;;N;;;;; 103A9;OLD PERSIAN SIGN JA;Lo;0;L;;;;;N;;;;; 103AA;OLD PERSIAN SIGN JI;Lo;0;L;;;;;N;;;;; 103AB;OLD PERSIAN SIGN TA;Lo;0;L;;;;;N;;;;; 103AC;OLD PERSIAN SIGN TU;Lo;0;L;;;;;N;;;;; 103AD;OLD PERSIAN SIGN DA;Lo;0;L;;;;;N;;;;; 103AE;OLD PERSIAN SIGN DI;Lo;0;L;;;;;N;;;;; 103AF;OLD PERSIAN SIGN DU;Lo;0;L;;;;;N;;;;; 103B0;OLD PERSIAN SIGN THA;Lo;0;L;;;;;N;;;;; 103B1;OLD PERSIAN SIGN PA;Lo;0;L;;;;;N;;;;; 103B2;OLD PERSIAN SIGN BA;Lo;0;L;;;;;N;;;;; 103B3;OLD PERSIAN SIGN FA;Lo;0;L;;;;;N;;;;; 103B4;OLD PERSIAN SIGN NA;Lo;0;L;;;;;N;;;;; 103B5;OLD PERSIAN SIGN NU;Lo;0;L;;;;;N;;;;; 103B6;OLD PERSIAN SIGN MA;Lo;0;L;;;;;N;;;;; 103B7;OLD PERSIAN SIGN MI;Lo;0;L;;;;;N;;;;; 103B8;OLD PERSIAN SIGN MU;Lo;0;L;;;;;N;;;;; 103B9;OLD PERSIAN SIGN YA;Lo;0;L;;;;;N;;;;; 103BA;OLD PERSIAN SIGN VA;Lo;0;L;;;;;N;;;;; 103BB;OLD PERSIAN SIGN VI;Lo;0;L;;;;;N;;;;; 103BC;OLD PERSIAN SIGN RA;Lo;0;L;;;;;N;;;;; 103BD;OLD PERSIAN SIGN RU;Lo;0;L;;;;;N;;;;; 103BE;OLD PERSIAN SIGN LA;Lo;0;L;;;;;N;;;;; 103BF;OLD PERSIAN SIGN SA;Lo;0;L;;;;;N;;;;; 103C0;OLD PERSIAN SIGN ZA;Lo;0;L;;;;;N;;;;; 103C1;OLD PERSIAN SIGN SHA;Lo;0;L;;;;;N;;;;; 103C2;OLD PERSIAN SIGN SSA;Lo;0;L;;;;;N;;;;; 103C3;OLD PERSIAN SIGN HA;Lo;0;L;;;;;N;;;;; 103C8;OLD PERSIAN SIGN AURAMAZDAA;Lo;0;L;;;;;N;;;;; 103C9;OLD PERSIAN SIGN AURAMAZDAA-2;Lo;0;L;;;;;N;;;;; 103CA;OLD PERSIAN SIGN AURAMAZDAAHA;Lo;0;L;;;;;N;;;;; 103CB;OLD PERSIAN SIGN XSHAAYATHIYA;Lo;0;L;;;;;N;;;;; 103CC;OLD PERSIAN SIGN DAHYAAUSH;Lo;0;L;;;;;N;;;;; 103CD;OLD PERSIAN SIGN DAHYAAUSH-2;Lo;0;L;;;;;N;;;;; 103CE;OLD PERSIAN SIGN BAGA;Lo;0;L;;;;;N;;;;; 103CF;OLD PERSIAN SIGN BUUMISH;Lo;0;L;;;;;N;;;;; 103D0;OLD PERSIAN WORD DIVIDER;Po;0;L;;;;;N;;;;; 103D1;OLD PERSIAN NUMBER ONE;Nl;0;L;;;;1;N;;;;; 103D2;OLD PERSIAN NUMBER TWO;Nl;0;L;;;;2;N;;;;; 103D3;OLD PERSIAN NUMBER TEN;Nl;0;L;;;;10;N;;;;; 103D4;OLD PERSIAN NUMBER TWENTY;Nl;0;L;;;;20;N;;;;; 103D5;OLD PERSIAN NUMBER HUNDRED;Nl;0;L;;;;100;N;;;;; 10400;DESERET CAPITAL LETTER LONG I;Lu;0;L;;;;;N;;;;10428; 10401;DESERET CAPITAL LETTER LONG E;Lu;0;L;;;;;N;;;;10429; 10402;DESERET CAPITAL LETTER LONG A;Lu;0;L;;;;;N;;;;1042A; 10403;DESERET CAPITAL LETTER LONG AH;Lu;0;L;;;;;N;;;;1042B; 10404;DESERET CAPITAL LETTER LONG O;Lu;0;L;;;;;N;;;;1042C; 10405;DESERET CAPITAL LETTER LONG OO;Lu;0;L;;;;;N;;;;1042D; 10406;DESERET CAPITAL LETTER SHORT I;Lu;0;L;;;;;N;;;;1042E; 10407;DESERET CAPITAL LETTER SHORT E;Lu;0;L;;;;;N;;;;1042F; 10408;DESERET CAPITAL LETTER SHORT A;Lu;0;L;;;;;N;;;;10430; 10409;DESERET CAPITAL LETTER SHORT AH;Lu;0;L;;;;;N;;;;10431; 1040A;DESERET CAPITAL LETTER SHORT O;Lu;0;L;;;;;N;;;;10432; 1040B;DESERET CAPITAL LETTER SHORT OO;Lu;0;L;;;;;N;;;;10433; 1040C;DESERET CAPITAL LETTER AY;Lu;0;L;;;;;N;;;;10434; 1040D;DESERET CAPITAL LETTER OW;Lu;0;L;;;;;N;;;;10435; 1040E;DESERET CAPITAL LETTER WU;Lu;0;L;;;;;N;;;;10436; 1040F;DESERET CAPITAL LETTER YEE;Lu;0;L;;;;;N;;;;10437; 10410;DESERET CAPITAL LETTER H;Lu;0;L;;;;;N;;;;10438; 10411;DESERET CAPITAL LETTER PEE;Lu;0;L;;;;;N;;;;10439; 10412;DESERET CAPITAL LETTER BEE;Lu;0;L;;;;;N;;;;1043A; 10413;DESERET CAPITAL LETTER TEE;Lu;0;L;;;;;N;;;;1043B; 10414;DESERET CAPITAL LETTER DEE;Lu;0;L;;;;;N;;;;1043C; 10415;DESERET CAPITAL LETTER CHEE;Lu;0;L;;;;;N;;;;1043D; 10416;DESERET CAPITAL LETTER JEE;Lu;0;L;;;;;N;;;;1043E; 10417;DESERET CAPITAL LETTER KAY;Lu;0;L;;;;;N;;;;1043F; 10418;DESERET CAPITAL LETTER GAY;Lu;0;L;;;;;N;;;;10440; 10419;DESERET CAPITAL LETTER EF;Lu;0;L;;;;;N;;;;10441; 1041A;DESERET CAPITAL LETTER VEE;Lu;0;L;;;;;N;;;;10442; 1041B;DESERET CAPITAL LETTER ETH;Lu;0;L;;;;;N;;;;10443; 1041C;DESERET CAPITAL LETTER THEE;Lu;0;L;;;;;N;;;;10444; 1041D;DESERET CAPITAL LETTER ES;Lu;0;L;;;;;N;;;;10445; 1041E;DESERET CAPITAL LETTER ZEE;Lu;0;L;;;;;N;;;;10446; 1041F;DESERET CAPITAL LETTER ESH;Lu;0;L;;;;;N;;;;10447; 10420;DESERET CAPITAL LETTER ZHEE;Lu;0;L;;;;;N;;;;10448; 10421;DESERET CAPITAL LETTER ER;Lu;0;L;;;;;N;;;;10449; 10422;DESERET CAPITAL LETTER EL;Lu;0;L;;;;;N;;;;1044A; 10423;DESERET CAPITAL LETTER EM;Lu;0;L;;;;;N;;;;1044B; 10424;DESERET CAPITAL LETTER EN;Lu;0;L;;;;;N;;;;1044C; 10425;DESERET CAPITAL LETTER ENG;Lu;0;L;;;;;N;;;;1044D; 10426;DESERET CAPITAL LETTER OI;Lu;0;L;;;;;N;;;;1044E; 10427;DESERET CAPITAL LETTER EW;Lu;0;L;;;;;N;;;;1044F; 10428;DESERET SMALL LETTER LONG I;Ll;0;L;;;;;N;;;10400;;10400 10429;DESERET SMALL LETTER LONG E;Ll;0;L;;;;;N;;;10401;;10401 1042A;DESERET SMALL LETTER LONG A;Ll;0;L;;;;;N;;;10402;;10402 1042B;DESERET SMALL LETTER LONG AH;Ll;0;L;;;;;N;;;10403;;10403 1042C;DESERET SMALL LETTER LONG O;Ll;0;L;;;;;N;;;10404;;10404 1042D;DESERET SMALL LETTER LONG OO;Ll;0;L;;;;;N;;;10405;;10405 1042E;DESERET SMALL LETTER SHORT I;Ll;0;L;;;;;N;;;10406;;10406 1042F;DESERET SMALL LETTER SHORT E;Ll;0;L;;;;;N;;;10407;;10407 10430;DESERET SMALL LETTER SHORT A;Ll;0;L;;;;;N;;;10408;;10408 10431;DESERET SMALL LETTER SHORT AH;Ll;0;L;;;;;N;;;10409;;10409 10432;DESERET SMALL LETTER SHORT O;Ll;0;L;;;;;N;;;1040A;;1040A 10433;DESERET SMALL LETTER SHORT OO;Ll;0;L;;;;;N;;;1040B;;1040B 10434;DESERET SMALL LETTER AY;Ll;0;L;;;;;N;;;1040C;;1040C 10435;DESERET SMALL LETTER OW;Ll;0;L;;;;;N;;;1040D;;1040D 10436;DESERET SMALL LETTER WU;Ll;0;L;;;;;N;;;1040E;;1040E 10437;DESERET SMALL LETTER YEE;Ll;0;L;;;;;N;;;1040F;;1040F 10438;DESERET SMALL LETTER H;Ll;0;L;;;;;N;;;10410;;10410 10439;DESERET SMALL LETTER PEE;Ll;0;L;;;;;N;;;10411;;10411 1043A;DESERET SMALL LETTER BEE;Ll;0;L;;;;;N;;;10412;;10412 1043B;DESERET SMALL LETTER TEE;Ll;0;L;;;;;N;;;10413;;10413 1043C;DESERET SMALL LETTER DEE;Ll;0;L;;;;;N;;;10414;;10414 1043D;DESERET SMALL LETTER CHEE;Ll;0;L;;;;;N;;;10415;;10415 1043E;DESERET SMALL LETTER JEE;Ll;0;L;;;;;N;;;10416;;10416 1043F;DESERET SMALL LETTER KAY;Ll;0;L;;;;;N;;;10417;;10417 10440;DESERET SMALL LETTER GAY;Ll;0;L;;;;;N;;;10418;;10418 10441;DESERET SMALL LETTER EF;Ll;0;L;;;;;N;;;10419;;10419 10442;DESERET SMALL LETTER VEE;Ll;0;L;;;;;N;;;1041A;;1041A 10443;DESERET SMALL LETTER ETH;Ll;0;L;;;;;N;;;1041B;;1041B 10444;DESERET SMALL LETTER THEE;Ll;0;L;;;;;N;;;1041C;;1041C 10445;DESERET SMALL LETTER ES;Ll;0;L;;;;;N;;;1041D;;1041D 10446;DESERET SMALL LETTER ZEE;Ll;0;L;;;;;N;;;1041E;;1041E 10447;DESERET SMALL LETTER ESH;Ll;0;L;;;;;N;;;1041F;;1041F 10448;DESERET SMALL LETTER ZHEE;Ll;0;L;;;;;N;;;10420;;10420 10449;DESERET SMALL LETTER ER;Ll;0;L;;;;;N;;;10421;;10421 1044A;DESERET SMALL LETTER EL;Ll;0;L;;;;;N;;;10422;;10422 1044B;DESERET SMALL LETTER EM;Ll;0;L;;;;;N;;;10423;;10423 1044C;DESERET SMALL LETTER EN;Ll;0;L;;;;;N;;;10424;;10424 1044D;DESERET SMALL LETTER ENG;Ll;0;L;;;;;N;;;10425;;10425 1044E;DESERET SMALL LETTER OI;Ll;0;L;;;;;N;;;10426;;10426 1044F;DESERET SMALL LETTER EW;Ll;0;L;;;;;N;;;10427;;10427 10450;SHAVIAN LETTER PEEP;Lo;0;L;;;;;N;;;;; 10451;SHAVIAN LETTER TOT;Lo;0;L;;;;;N;;;;; 10452;SHAVIAN LETTER KICK;Lo;0;L;;;;;N;;;;; 10453;SHAVIAN LETTER FEE;Lo;0;L;;;;;N;;;;; 10454;SHAVIAN LETTER THIGH;Lo;0;L;;;;;N;;;;; 10455;SHAVIAN LETTER SO;Lo;0;L;;;;;N;;;;; 10456;SHAVIAN LETTER SURE;Lo;0;L;;;;;N;;;;; 10457;SHAVIAN LETTER CHURCH;Lo;0;L;;;;;N;;;;; 10458;SHAVIAN LETTER YEA;Lo;0;L;;;;;N;;;;; 10459;SHAVIAN LETTER HUNG;Lo;0;L;;;;;N;;;;; 1045A;SHAVIAN LETTER BIB;Lo;0;L;;;;;N;;;;; 1045B;SHAVIAN LETTER DEAD;Lo;0;L;;;;;N;;;;; 1045C;SHAVIAN LETTER GAG;Lo;0;L;;;;;N;;;;; 1045D;SHAVIAN LETTER VOW;Lo;0;L;;;;;N;;;;; 1045E;SHAVIAN LETTER THEY;Lo;0;L;;;;;N;;;;; 1045F;SHAVIAN LETTER ZOO;Lo;0;L;;;;;N;;;;; 10460;SHAVIAN LETTER MEASURE;Lo;0;L;;;;;N;;;;; 10461;SHAVIAN LETTER JUDGE;Lo;0;L;;;;;N;;;;; 10462;SHAVIAN LETTER WOE;Lo;0;L;;;;;N;;;;; 10463;SHAVIAN LETTER HA-HA;Lo;0;L;;;;;N;;;;; 10464;SHAVIAN LETTER LOLL;Lo;0;L;;;;;N;;;;; 10465;SHAVIAN LETTER MIME;Lo;0;L;;;;;N;;;;; 10466;SHAVIAN LETTER IF;Lo;0;L;;;;;N;;;;; 10467;SHAVIAN LETTER EGG;Lo;0;L;;;;;N;;;;; 10468;SHAVIAN LETTER ASH;Lo;0;L;;;;;N;;;;; 10469;SHAVIAN LETTER ADO;Lo;0;L;;;;;N;;;;; 1046A;SHAVIAN LETTER ON;Lo;0;L;;;;;N;;;;; 1046B;SHAVIAN LETTER WOOL;Lo;0;L;;;;;N;;;;; 1046C;SHAVIAN LETTER OUT;Lo;0;L;;;;;N;;;;; 1046D;SHAVIAN LETTER AH;Lo;0;L;;;;;N;;;;; 1046E;SHAVIAN LETTER ROAR;Lo;0;L;;;;;N;;;;; 1046F;SHAVIAN LETTER NUN;Lo;0;L;;;;;N;;;;; 10470;SHAVIAN LETTER EAT;Lo;0;L;;;;;N;;;;; 10471;SHAVIAN LETTER AGE;Lo;0;L;;;;;N;;;;; 10472;SHAVIAN LETTER ICE;Lo;0;L;;;;;N;;;;; 10473;SHAVIAN LETTER UP;Lo;0;L;;;;;N;;;;; 10474;SHAVIAN LETTER OAK;Lo;0;L;;;;;N;;;;; 10475;SHAVIAN LETTER OOZE;Lo;0;L;;;;;N;;;;; 10476;SHAVIAN LETTER OIL;Lo;0;L;;;;;N;;;;; 10477;SHAVIAN LETTER AWE;Lo;0;L;;;;;N;;;;; 10478;SHAVIAN LETTER ARE;Lo;0;L;;;;;N;;;;; 10479;SHAVIAN LETTER OR;Lo;0;L;;;;;N;;;;; 1047A;SHAVIAN LETTER AIR;Lo;0;L;;;;;N;;;;; 1047B;SHAVIAN LETTER ERR;Lo;0;L;;;;;N;;;;; 1047C;SHAVIAN LETTER ARRAY;Lo;0;L;;;;;N;;;;; 1047D;SHAVIAN LETTER EAR;Lo;0;L;;;;;N;;;;; 1047E;SHAVIAN LETTER IAN;Lo;0;L;;;;;N;;;;; 1047F;SHAVIAN LETTER YEW;Lo;0;L;;;;;N;;;;; 10480;OSMANYA LETTER ALEF;Lo;0;L;;;;;N;;;;; 10481;OSMANYA LETTER BA;Lo;0;L;;;;;N;;;;; 10482;OSMANYA LETTER TA;Lo;0;L;;;;;N;;;;; 10483;OSMANYA LETTER JA;Lo;0;L;;;;;N;;;;; 10484;OSMANYA LETTER XA;Lo;0;L;;;;;N;;;;; 10485;OSMANYA LETTER KHA;Lo;0;L;;;;;N;;;;; 10486;OSMANYA LETTER DEEL;Lo;0;L;;;;;N;;;;; 10487;OSMANYA LETTER RA;Lo;0;L;;;;;N;;;;; 10488;OSMANYA LETTER SA;Lo;0;L;;;;;N;;;;; 10489;OSMANYA LETTER SHIIN;Lo;0;L;;;;;N;;;;; 1048A;OSMANYA LETTER DHA;Lo;0;L;;;;;N;;;;; 1048B;OSMANYA LETTER CAYN;Lo;0;L;;;;;N;;;;; 1048C;OSMANYA LETTER GA;Lo;0;L;;;;;N;;;;; 1048D;OSMANYA LETTER FA;Lo;0;L;;;;;N;;;;; 1048E;OSMANYA LETTER QAAF;Lo;0;L;;;;;N;;;;; 1048F;OSMANYA LETTER KAAF;Lo;0;L;;;;;N;;;;; 10490;OSMANYA LETTER LAAN;Lo;0;L;;;;;N;;;;; 10491;OSMANYA LETTER MIIN;Lo;0;L;;;;;N;;;;; 10492;OSMANYA LETTER NUUN;Lo;0;L;;;;;N;;;;; 10493;OSMANYA LETTER WAW;Lo;0;L;;;;;N;;;;; 10494;OSMANYA LETTER HA;Lo;0;L;;;;;N;;;;; 10495;OSMANYA LETTER YA;Lo;0;L;;;;;N;;;;; 10496;OSMANYA LETTER A;Lo;0;L;;;;;N;;;;; 10497;OSMANYA LETTER E;Lo;0;L;;;;;N;;;;; 10498;OSMANYA LETTER I;Lo;0;L;;;;;N;;;;; 10499;OSMANYA LETTER O;Lo;0;L;;;;;N;;;;; 1049A;OSMANYA LETTER U;Lo;0;L;;;;;N;;;;; 1049B;OSMANYA LETTER AA;Lo;0;L;;;;;N;;;;; 1049C;OSMANYA LETTER EE;Lo;0;L;;;;;N;;;;; 1049D;OSMANYA LETTER OO;Lo;0;L;;;;;N;;;;; 104A0;OSMANYA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 104A1;OSMANYA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 104A2;OSMANYA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 104A3;OSMANYA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 104A4;OSMANYA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 104A5;OSMANYA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 104A6;OSMANYA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 104A7;OSMANYA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 104A8;OSMANYA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 104A9;OSMANYA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 104B0;OSAGE CAPITAL LETTER A;Lu;0;L;;;;;N;;;;104D8; 104B1;OSAGE CAPITAL LETTER AI;Lu;0;L;;;;;N;;;;104D9; 104B2;OSAGE CAPITAL LETTER AIN;Lu;0;L;;;;;N;;;;104DA; 104B3;OSAGE CAPITAL LETTER AH;Lu;0;L;;;;;N;;;;104DB; 104B4;OSAGE CAPITAL LETTER BRA;Lu;0;L;;;;;N;;;;104DC; 104B5;OSAGE CAPITAL LETTER CHA;Lu;0;L;;;;;N;;;;104DD; 104B6;OSAGE CAPITAL LETTER EHCHA;Lu;0;L;;;;;N;;;;104DE; 104B7;OSAGE CAPITAL LETTER E;Lu;0;L;;;;;N;;;;104DF; 104B8;OSAGE CAPITAL LETTER EIN;Lu;0;L;;;;;N;;;;104E0; 104B9;OSAGE CAPITAL LETTER HA;Lu;0;L;;;;;N;;;;104E1; 104BA;OSAGE CAPITAL LETTER HYA;Lu;0;L;;;;;N;;;;104E2; 104BB;OSAGE CAPITAL LETTER I;Lu;0;L;;;;;N;;;;104E3; 104BC;OSAGE CAPITAL LETTER KA;Lu;0;L;;;;;N;;;;104E4; 104BD;OSAGE CAPITAL LETTER EHKA;Lu;0;L;;;;;N;;;;104E5; 104BE;OSAGE CAPITAL LETTER KYA;Lu;0;L;;;;;N;;;;104E6; 104BF;OSAGE CAPITAL LETTER LA;Lu;0;L;;;;;N;;;;104E7; 104C0;OSAGE CAPITAL LETTER MA;Lu;0;L;;;;;N;;;;104E8; 104C1;OSAGE CAPITAL LETTER NA;Lu;0;L;;;;;N;;;;104E9; 104C2;OSAGE CAPITAL LETTER O;Lu;0;L;;;;;N;;;;104EA; 104C3;OSAGE CAPITAL LETTER OIN;Lu;0;L;;;;;N;;;;104EB; 104C4;OSAGE CAPITAL LETTER PA;Lu;0;L;;;;;N;;;;104EC; 104C5;OSAGE CAPITAL LETTER EHPA;Lu;0;L;;;;;N;;;;104ED; 104C6;OSAGE CAPITAL LETTER SA;Lu;0;L;;;;;N;;;;104EE; 104C7;OSAGE CAPITAL LETTER SHA;Lu;0;L;;;;;N;;;;104EF; 104C8;OSAGE CAPITAL LETTER TA;Lu;0;L;;;;;N;;;;104F0; 104C9;OSAGE CAPITAL LETTER EHTA;Lu;0;L;;;;;N;;;;104F1; 104CA;OSAGE CAPITAL LETTER TSA;Lu;0;L;;;;;N;;;;104F2; 104CB;OSAGE CAPITAL LETTER EHTSA;Lu;0;L;;;;;N;;;;104F3; 104CC;OSAGE CAPITAL LETTER TSHA;Lu;0;L;;;;;N;;;;104F4; 104CD;OSAGE CAPITAL LETTER DHA;Lu;0;L;;;;;N;;;;104F5; 104CE;OSAGE CAPITAL LETTER U;Lu;0;L;;;;;N;;;;104F6; 104CF;OSAGE CAPITAL LETTER WA;Lu;0;L;;;;;N;;;;104F7; 104D0;OSAGE CAPITAL LETTER KHA;Lu;0;L;;;;;N;;;;104F8; 104D1;OSAGE CAPITAL LETTER GHA;Lu;0;L;;;;;N;;;;104F9; 104D2;OSAGE CAPITAL LETTER ZA;Lu;0;L;;;;;N;;;;104FA; 104D3;OSAGE CAPITAL LETTER ZHA;Lu;0;L;;;;;N;;;;104FB; 104D8;OSAGE SMALL LETTER A;Ll;0;L;;;;;N;;;104B0;;104B0 104D9;OSAGE SMALL LETTER AI;Ll;0;L;;;;;N;;;104B1;;104B1 104DA;OSAGE SMALL LETTER AIN;Ll;0;L;;;;;N;;;104B2;;104B2 104DB;OSAGE SMALL LETTER AH;Ll;0;L;;;;;N;;;104B3;;104B3 104DC;OSAGE SMALL LETTER BRA;Ll;0;L;;;;;N;;;104B4;;104B4 104DD;OSAGE SMALL LETTER CHA;Ll;0;L;;;;;N;;;104B5;;104B5 104DE;OSAGE SMALL LETTER EHCHA;Ll;0;L;;;;;N;;;104B6;;104B6 104DF;OSAGE SMALL LETTER E;Ll;0;L;;;;;N;;;104B7;;104B7 104E0;OSAGE SMALL LETTER EIN;Ll;0;L;;;;;N;;;104B8;;104B8 104E1;OSAGE SMALL LETTER HA;Ll;0;L;;;;;N;;;104B9;;104B9 104E2;OSAGE SMALL LETTER HYA;Ll;0;L;;;;;N;;;104BA;;104BA 104E3;OSAGE SMALL LETTER I;Ll;0;L;;;;;N;;;104BB;;104BB 104E4;OSAGE SMALL LETTER KA;Ll;0;L;;;;;N;;;104BC;;104BC 104E5;OSAGE SMALL LETTER EHKA;Ll;0;L;;;;;N;;;104BD;;104BD 104E6;OSAGE SMALL LETTER KYA;Ll;0;L;;;;;N;;;104BE;;104BE 104E7;OSAGE SMALL LETTER LA;Ll;0;L;;;;;N;;;104BF;;104BF 104E8;OSAGE SMALL LETTER MA;Ll;0;L;;;;;N;;;104C0;;104C0 104E9;OSAGE SMALL LETTER NA;Ll;0;L;;;;;N;;;104C1;;104C1 104EA;OSAGE SMALL LETTER O;Ll;0;L;;;;;N;;;104C2;;104C2 104EB;OSAGE SMALL LETTER OIN;Ll;0;L;;;;;N;;;104C3;;104C3 104EC;OSAGE SMALL LETTER PA;Ll;0;L;;;;;N;;;104C4;;104C4 104ED;OSAGE SMALL LETTER EHPA;Ll;0;L;;;;;N;;;104C5;;104C5 104EE;OSAGE SMALL LETTER SA;Ll;0;L;;;;;N;;;104C6;;104C6 104EF;OSAGE SMALL LETTER SHA;Ll;0;L;;;;;N;;;104C7;;104C7 104F0;OSAGE SMALL LETTER TA;Ll;0;L;;;;;N;;;104C8;;104C8 104F1;OSAGE SMALL LETTER EHTA;Ll;0;L;;;;;N;;;104C9;;104C9 104F2;OSAGE SMALL LETTER TSA;Ll;0;L;;;;;N;;;104CA;;104CA 104F3;OSAGE SMALL LETTER EHTSA;Ll;0;L;;;;;N;;;104CB;;104CB 104F4;OSAGE SMALL LETTER TSHA;Ll;0;L;;;;;N;;;104CC;;104CC 104F5;OSAGE SMALL LETTER DHA;Ll;0;L;;;;;N;;;104CD;;104CD 104F6;OSAGE SMALL LETTER U;Ll;0;L;;;;;N;;;104CE;;104CE 104F7;OSAGE SMALL LETTER WA;Ll;0;L;;;;;N;;;104CF;;104CF 104F8;OSAGE SMALL LETTER KHA;Ll;0;L;;;;;N;;;104D0;;104D0 104F9;OSAGE SMALL LETTER GHA;Ll;0;L;;;;;N;;;104D1;;104D1 104FA;OSAGE SMALL LETTER ZA;Ll;0;L;;;;;N;;;104D2;;104D2 104FB;OSAGE SMALL LETTER ZHA;Ll;0;L;;;;;N;;;104D3;;104D3 10500;ELBASAN LETTER A;Lo;0;L;;;;;N;;;;; 10501;ELBASAN LETTER BE;Lo;0;L;;;;;N;;;;; 10502;ELBASAN LETTER CE;Lo;0;L;;;;;N;;;;; 10503;ELBASAN LETTER CHE;Lo;0;L;;;;;N;;;;; 10504;ELBASAN LETTER DE;Lo;0;L;;;;;N;;;;; 10505;ELBASAN LETTER NDE;Lo;0;L;;;;;N;;;;; 10506;ELBASAN LETTER DHE;Lo;0;L;;;;;N;;;;; 10507;ELBASAN LETTER EI;Lo;0;L;;;;;N;;;;; 10508;ELBASAN LETTER E;Lo;0;L;;;;;N;;;;; 10509;ELBASAN LETTER FE;Lo;0;L;;;;;N;;;;; 1050A;ELBASAN LETTER GE;Lo;0;L;;;;;N;;;;; 1050B;ELBASAN LETTER GJE;Lo;0;L;;;;;N;;;;; 1050C;ELBASAN LETTER HE;Lo;0;L;;;;;N;;;;; 1050D;ELBASAN LETTER I;Lo;0;L;;;;;N;;;;; 1050E;ELBASAN LETTER JE;Lo;0;L;;;;;N;;;;; 1050F;ELBASAN LETTER KE;Lo;0;L;;;;;N;;;;; 10510;ELBASAN LETTER LE;Lo;0;L;;;;;N;;;;; 10511;ELBASAN LETTER LLE;Lo;0;L;;;;;N;;;;; 10512;ELBASAN LETTER ME;Lo;0;L;;;;;N;;;;; 10513;ELBASAN LETTER NE;Lo;0;L;;;;;N;;;;; 10514;ELBASAN LETTER NA;Lo;0;L;;;;;N;;;;; 10515;ELBASAN LETTER NJE;Lo;0;L;;;;;N;;;;; 10516;ELBASAN LETTER O;Lo;0;L;;;;;N;;;;; 10517;ELBASAN LETTER PE;Lo;0;L;;;;;N;;;;; 10518;ELBASAN LETTER QE;Lo;0;L;;;;;N;;;;; 10519;ELBASAN LETTER RE;Lo;0;L;;;;;N;;;;; 1051A;ELBASAN LETTER RRE;Lo;0;L;;;;;N;;;;; 1051B;ELBASAN LETTER SE;Lo;0;L;;;;;N;;;;; 1051C;ELBASAN LETTER SHE;Lo;0;L;;;;;N;;;;; 1051D;ELBASAN LETTER TE;Lo;0;L;;;;;N;;;;; 1051E;ELBASAN LETTER THE;Lo;0;L;;;;;N;;;;; 1051F;ELBASAN LETTER U;Lo;0;L;;;;;N;;;;; 10520;ELBASAN LETTER VE;Lo;0;L;;;;;N;;;;; 10521;ELBASAN LETTER XE;Lo;0;L;;;;;N;;;;; 10522;ELBASAN LETTER Y;Lo;0;L;;;;;N;;;;; 10523;ELBASAN LETTER ZE;Lo;0;L;;;;;N;;;;; 10524;ELBASAN LETTER ZHE;Lo;0;L;;;;;N;;;;; 10525;ELBASAN LETTER GHE;Lo;0;L;;;;;N;;;;; 10526;ELBASAN LETTER GHAMMA;Lo;0;L;;;;;N;;;;; 10527;ELBASAN LETTER KHE;Lo;0;L;;;;;N;;;;; 10530;CAUCASIAN ALBANIAN LETTER ALT;Lo;0;L;;;;;N;;;;; 10531;CAUCASIAN ALBANIAN LETTER BET;Lo;0;L;;;;;N;;;;; 10532;CAUCASIAN ALBANIAN LETTER GIM;Lo;0;L;;;;;N;;;;; 10533;CAUCASIAN ALBANIAN LETTER DAT;Lo;0;L;;;;;N;;;;; 10534;CAUCASIAN ALBANIAN LETTER EB;Lo;0;L;;;;;N;;;;; 10535;CAUCASIAN ALBANIAN LETTER ZARL;Lo;0;L;;;;;N;;;;; 10536;CAUCASIAN ALBANIAN LETTER EYN;Lo;0;L;;;;;N;;;;; 10537;CAUCASIAN ALBANIAN LETTER ZHIL;Lo;0;L;;;;;N;;;;; 10538;CAUCASIAN ALBANIAN LETTER TAS;Lo;0;L;;;;;N;;;;; 10539;CAUCASIAN ALBANIAN LETTER CHA;Lo;0;L;;;;;N;;;;; 1053A;CAUCASIAN ALBANIAN LETTER YOWD;Lo;0;L;;;;;N;;;;; 1053B;CAUCASIAN ALBANIAN LETTER ZHA;Lo;0;L;;;;;N;;;;; 1053C;CAUCASIAN ALBANIAN LETTER IRB;Lo;0;L;;;;;N;;;;; 1053D;CAUCASIAN ALBANIAN LETTER SHA;Lo;0;L;;;;;N;;;;; 1053E;CAUCASIAN ALBANIAN LETTER LAN;Lo;0;L;;;;;N;;;;; 1053F;CAUCASIAN ALBANIAN LETTER INYA;Lo;0;L;;;;;N;;;;; 10540;CAUCASIAN ALBANIAN LETTER XEYN;Lo;0;L;;;;;N;;;;; 10541;CAUCASIAN ALBANIAN LETTER DYAN;Lo;0;L;;;;;N;;;;; 10542;CAUCASIAN ALBANIAN LETTER CAR;Lo;0;L;;;;;N;;;;; 10543;CAUCASIAN ALBANIAN LETTER JHOX;Lo;0;L;;;;;N;;;;; 10544;CAUCASIAN ALBANIAN LETTER KAR;Lo;0;L;;;;;N;;;;; 10545;CAUCASIAN ALBANIAN LETTER LYIT;Lo;0;L;;;;;N;;;;; 10546;CAUCASIAN ALBANIAN LETTER HEYT;Lo;0;L;;;;;N;;;;; 10547;CAUCASIAN ALBANIAN LETTER QAY;Lo;0;L;;;;;N;;;;; 10548;CAUCASIAN ALBANIAN LETTER AOR;Lo;0;L;;;;;N;;;;; 10549;CAUCASIAN ALBANIAN LETTER CHOY;Lo;0;L;;;;;N;;;;; 1054A;CAUCASIAN ALBANIAN LETTER CHI;Lo;0;L;;;;;N;;;;; 1054B;CAUCASIAN ALBANIAN LETTER CYAY;Lo;0;L;;;;;N;;;;; 1054C;CAUCASIAN ALBANIAN LETTER MAQ;Lo;0;L;;;;;N;;;;; 1054D;CAUCASIAN ALBANIAN LETTER QAR;Lo;0;L;;;;;N;;;;; 1054E;CAUCASIAN ALBANIAN LETTER NOWC;Lo;0;L;;;;;N;;;;; 1054F;CAUCASIAN ALBANIAN LETTER DZYAY;Lo;0;L;;;;;N;;;;; 10550;CAUCASIAN ALBANIAN LETTER SHAK;Lo;0;L;;;;;N;;;;; 10551;CAUCASIAN ALBANIAN LETTER JAYN;Lo;0;L;;;;;N;;;;; 10552;CAUCASIAN ALBANIAN LETTER ON;Lo;0;L;;;;;N;;;;; 10553;CAUCASIAN ALBANIAN LETTER TYAY;Lo;0;L;;;;;N;;;;; 10554;CAUCASIAN ALBANIAN LETTER FAM;Lo;0;L;;;;;N;;;;; 10555;CAUCASIAN ALBANIAN LETTER DZAY;Lo;0;L;;;;;N;;;;; 10556;CAUCASIAN ALBANIAN LETTER CHAT;Lo;0;L;;;;;N;;;;; 10557;CAUCASIAN ALBANIAN LETTER PEN;Lo;0;L;;;;;N;;;;; 10558;CAUCASIAN ALBANIAN LETTER GHEYS;Lo;0;L;;;;;N;;;;; 10559;CAUCASIAN ALBANIAN LETTER RAT;Lo;0;L;;;;;N;;;;; 1055A;CAUCASIAN ALBANIAN LETTER SEYK;Lo;0;L;;;;;N;;;;; 1055B;CAUCASIAN ALBANIAN LETTER VEYZ;Lo;0;L;;;;;N;;;;; 1055C;CAUCASIAN ALBANIAN LETTER TIWR;Lo;0;L;;;;;N;;;;; 1055D;CAUCASIAN ALBANIAN LETTER SHOY;Lo;0;L;;;;;N;;;;; 1055E;CAUCASIAN ALBANIAN LETTER IWN;Lo;0;L;;;;;N;;;;; 1055F;CAUCASIAN ALBANIAN LETTER CYAW;Lo;0;L;;;;;N;;;;; 10560;CAUCASIAN ALBANIAN LETTER CAYN;Lo;0;L;;;;;N;;;;; 10561;CAUCASIAN ALBANIAN LETTER YAYD;Lo;0;L;;;;;N;;;;; 10562;CAUCASIAN ALBANIAN LETTER PIWR;Lo;0;L;;;;;N;;;;; 10563;CAUCASIAN ALBANIAN LETTER KIW;Lo;0;L;;;;;N;;;;; 1056F;CAUCASIAN ALBANIAN CITATION MARK;Po;0;L;;;;;N;;;;; 10600;LINEAR A SIGN AB001;Lo;0;L;;;;;N;;;;; 10601;LINEAR A SIGN AB002;Lo;0;L;;;;;N;;;;; 10602;LINEAR A SIGN AB003;Lo;0;L;;;;;N;;;;; 10603;LINEAR A SIGN AB004;Lo;0;L;;;;;N;;;;; 10604;LINEAR A SIGN AB005;Lo;0;L;;;;;N;;;;; 10605;LINEAR A SIGN AB006;Lo;0;L;;;;;N;;;;; 10606;LINEAR A SIGN AB007;Lo;0;L;;;;;N;;;;; 10607;LINEAR A SIGN AB008;Lo;0;L;;;;;N;;;;; 10608;LINEAR A SIGN AB009;Lo;0;L;;;;;N;;;;; 10609;LINEAR A SIGN AB010;Lo;0;L;;;;;N;;;;; 1060A;LINEAR A SIGN AB011;Lo;0;L;;;;;N;;;;; 1060B;LINEAR A SIGN AB013;Lo;0;L;;;;;N;;;;; 1060C;LINEAR A SIGN AB016;Lo;0;L;;;;;N;;;;; 1060D;LINEAR A SIGN AB017;Lo;0;L;;;;;N;;;;; 1060E;LINEAR A SIGN AB020;Lo;0;L;;;;;N;;;;; 1060F;LINEAR A SIGN AB021;Lo;0;L;;;;;N;;;;; 10610;LINEAR A SIGN AB021F;Lo;0;L;;;;;N;;;;; 10611;LINEAR A SIGN AB021M;Lo;0;L;;;;;N;;;;; 10612;LINEAR A SIGN AB022;Lo;0;L;;;;;N;;;;; 10613;LINEAR A SIGN AB022F;Lo;0;L;;;;;N;;;;; 10614;LINEAR A SIGN AB022M;Lo;0;L;;;;;N;;;;; 10615;LINEAR A SIGN AB023;Lo;0;L;;;;;N;;;;; 10616;LINEAR A SIGN AB023M;Lo;0;L;;;;;N;;;;; 10617;LINEAR A SIGN AB024;Lo;0;L;;;;;N;;;;; 10618;LINEAR A SIGN AB026;Lo;0;L;;;;;N;;;;; 10619;LINEAR A SIGN AB027;Lo;0;L;;;;;N;;;;; 1061A;LINEAR A SIGN AB028;Lo;0;L;;;;;N;;;;; 1061B;LINEAR A SIGN A028B;Lo;0;L;;;;;N;;;;; 1061C;LINEAR A SIGN AB029;Lo;0;L;;;;;N;;;;; 1061D;LINEAR A SIGN AB030;Lo;0;L;;;;;N;;;;; 1061E;LINEAR A SIGN AB031;Lo;0;L;;;;;N;;;;; 1061F;LINEAR A SIGN AB034;Lo;0;L;;;;;N;;;;; 10620;LINEAR A SIGN AB037;Lo;0;L;;;;;N;;;;; 10621;LINEAR A SIGN AB038;Lo;0;L;;;;;N;;;;; 10622;LINEAR A SIGN AB039;Lo;0;L;;;;;N;;;;; 10623;LINEAR A SIGN AB040;Lo;0;L;;;;;N;;;;; 10624;LINEAR A SIGN AB041;Lo;0;L;;;;;N;;;;; 10625;LINEAR A SIGN AB044;Lo;0;L;;;;;N;;;;; 10626;LINEAR A SIGN AB045;Lo;0;L;;;;;N;;;;; 10627;LINEAR A SIGN AB046;Lo;0;L;;;;;N;;;;; 10628;LINEAR A SIGN AB047;Lo;0;L;;;;;N;;;;; 10629;LINEAR A SIGN AB048;Lo;0;L;;;;;N;;;;; 1062A;LINEAR A SIGN AB049;Lo;0;L;;;;;N;;;;; 1062B;LINEAR A SIGN AB050;Lo;0;L;;;;;N;;;;; 1062C;LINEAR A SIGN AB051;Lo;0;L;;;;;N;;;;; 1062D;LINEAR A SIGN AB053;Lo;0;L;;;;;N;;;;; 1062E;LINEAR A SIGN AB054;Lo;0;L;;;;;N;;;;; 1062F;LINEAR A SIGN AB055;Lo;0;L;;;;;N;;;;; 10630;LINEAR A SIGN AB056;Lo;0;L;;;;;N;;;;; 10631;LINEAR A SIGN AB057;Lo;0;L;;;;;N;;;;; 10632;LINEAR A SIGN AB058;Lo;0;L;;;;;N;;;;; 10633;LINEAR A SIGN AB059;Lo;0;L;;;;;N;;;;; 10634;LINEAR A SIGN AB060;Lo;0;L;;;;;N;;;;; 10635;LINEAR A SIGN AB061;Lo;0;L;;;;;N;;;;; 10636;LINEAR A SIGN AB065;Lo;0;L;;;;;N;;;;; 10637;LINEAR A SIGN AB066;Lo;0;L;;;;;N;;;;; 10638;LINEAR A SIGN AB067;Lo;0;L;;;;;N;;;;; 10639;LINEAR A SIGN AB069;Lo;0;L;;;;;N;;;;; 1063A;LINEAR A SIGN AB070;Lo;0;L;;;;;N;;;;; 1063B;LINEAR A SIGN AB073;Lo;0;L;;;;;N;;;;; 1063C;LINEAR A SIGN AB074;Lo;0;L;;;;;N;;;;; 1063D;LINEAR A SIGN AB076;Lo;0;L;;;;;N;;;;; 1063E;LINEAR A SIGN AB077;Lo;0;L;;;;;N;;;;; 1063F;LINEAR A SIGN AB078;Lo;0;L;;;;;N;;;;; 10640;LINEAR A SIGN AB079;Lo;0;L;;;;;N;;;;; 10641;LINEAR A SIGN AB080;Lo;0;L;;;;;N;;;;; 10642;LINEAR A SIGN AB081;Lo;0;L;;;;;N;;;;; 10643;LINEAR A SIGN AB082;Lo;0;L;;;;;N;;;;; 10644;LINEAR A SIGN AB085;Lo;0;L;;;;;N;;;;; 10645;LINEAR A SIGN AB086;Lo;0;L;;;;;N;;;;; 10646;LINEAR A SIGN AB087;Lo;0;L;;;;;N;;;;; 10647;LINEAR A SIGN A100-102;Lo;0;L;;;;;N;;;;; 10648;LINEAR A SIGN AB118;Lo;0;L;;;;;N;;;;; 10649;LINEAR A SIGN AB120;Lo;0;L;;;;;N;;;;; 1064A;LINEAR A SIGN A120B;Lo;0;L;;;;;N;;;;; 1064B;LINEAR A SIGN AB122;Lo;0;L;;;;;N;;;;; 1064C;LINEAR A SIGN AB123;Lo;0;L;;;;;N;;;;; 1064D;LINEAR A SIGN AB131A;Lo;0;L;;;;;N;;;;; 1064E;LINEAR A SIGN AB131B;Lo;0;L;;;;;N;;;;; 1064F;LINEAR A SIGN A131C;Lo;0;L;;;;;N;;;;; 10650;LINEAR A SIGN AB164;Lo;0;L;;;;;N;;;;; 10651;LINEAR A SIGN AB171;Lo;0;L;;;;;N;;;;; 10652;LINEAR A SIGN AB180;Lo;0;L;;;;;N;;;;; 10653;LINEAR A SIGN AB188;Lo;0;L;;;;;N;;;;; 10654;LINEAR A SIGN AB191;Lo;0;L;;;;;N;;;;; 10655;LINEAR A SIGN A301;Lo;0;L;;;;;N;;;;; 10656;LINEAR A SIGN A302;Lo;0;L;;;;;N;;;;; 10657;LINEAR A SIGN A303;Lo;0;L;;;;;N;;;;; 10658;LINEAR A SIGN A304;Lo;0;L;;;;;N;;;;; 10659;LINEAR A SIGN A305;Lo;0;L;;;;;N;;;;; 1065A;LINEAR A SIGN A306;Lo;0;L;;;;;N;;;;; 1065B;LINEAR A SIGN A307;Lo;0;L;;;;;N;;;;; 1065C;LINEAR A SIGN A308;Lo;0;L;;;;;N;;;;; 1065D;LINEAR A SIGN A309A;Lo;0;L;;;;;N;;;;; 1065E;LINEAR A SIGN A309B;Lo;0;L;;;;;N;;;;; 1065F;LINEAR A SIGN A309C;Lo;0;L;;;;;N;;;;; 10660;LINEAR A SIGN A310;Lo;0;L;;;;;N;;;;; 10661;LINEAR A SIGN A311;Lo;0;L;;;;;N;;;;; 10662;LINEAR A SIGN A312;Lo;0;L;;;;;N;;;;; 10663;LINEAR A SIGN A313A;Lo;0;L;;;;;N;;;;; 10664;LINEAR A SIGN A313B;Lo;0;L;;;;;N;;;;; 10665;LINEAR A SIGN A313C;Lo;0;L;;;;;N;;;;; 10666;LINEAR A SIGN A314;Lo;0;L;;;;;N;;;;; 10667;LINEAR A SIGN A315;Lo;0;L;;;;;N;;;;; 10668;LINEAR A SIGN A316;Lo;0;L;;;;;N;;;;; 10669;LINEAR A SIGN A317;Lo;0;L;;;;;N;;;;; 1066A;LINEAR A SIGN A318;Lo;0;L;;;;;N;;;;; 1066B;LINEAR A SIGN A319;Lo;0;L;;;;;N;;;;; 1066C;LINEAR A SIGN A320;Lo;0;L;;;;;N;;;;; 1066D;LINEAR A SIGN A321;Lo;0;L;;;;;N;;;;; 1066E;LINEAR A SIGN A322;Lo;0;L;;;;;N;;;;; 1066F;LINEAR A SIGN A323;Lo;0;L;;;;;N;;;;; 10670;LINEAR A SIGN A324;Lo;0;L;;;;;N;;;;; 10671;LINEAR A SIGN A325;Lo;0;L;;;;;N;;;;; 10672;LINEAR A SIGN A326;Lo;0;L;;;;;N;;;;; 10673;LINEAR A SIGN A327;Lo;0;L;;;;;N;;;;; 10674;LINEAR A SIGN A328;Lo;0;L;;;;;N;;;;; 10675;LINEAR A SIGN A329;Lo;0;L;;;;;N;;;;; 10676;LINEAR A SIGN A330;Lo;0;L;;;;;N;;;;; 10677;LINEAR A SIGN A331;Lo;0;L;;;;;N;;;;; 10678;LINEAR A SIGN A332;Lo;0;L;;;;;N;;;;; 10679;LINEAR A SIGN A333;Lo;0;L;;;;;N;;;;; 1067A;LINEAR A SIGN A334;Lo;0;L;;;;;N;;;;; 1067B;LINEAR A SIGN A335;Lo;0;L;;;;;N;;;;; 1067C;LINEAR A SIGN A336;Lo;0;L;;;;;N;;;;; 1067D;LINEAR A SIGN A337;Lo;0;L;;;;;N;;;;; 1067E;LINEAR A SIGN A338;Lo;0;L;;;;;N;;;;; 1067F;LINEAR A SIGN A339;Lo;0;L;;;;;N;;;;; 10680;LINEAR A SIGN A340;Lo;0;L;;;;;N;;;;; 10681;LINEAR A SIGN A341;Lo;0;L;;;;;N;;;;; 10682;LINEAR A SIGN A342;Lo;0;L;;;;;N;;;;; 10683;LINEAR A SIGN A343;Lo;0;L;;;;;N;;;;; 10684;LINEAR A SIGN A344;Lo;0;L;;;;;N;;;;; 10685;LINEAR A SIGN A345;Lo;0;L;;;;;N;;;;; 10686;LINEAR A SIGN A346;Lo;0;L;;;;;N;;;;; 10687;LINEAR A SIGN A347;Lo;0;L;;;;;N;;;;; 10688;LINEAR A SIGN A348;Lo;0;L;;;;;N;;;;; 10689;LINEAR A SIGN A349;Lo;0;L;;;;;N;;;;; 1068A;LINEAR A SIGN A350;Lo;0;L;;;;;N;;;;; 1068B;LINEAR A SIGN A351;Lo;0;L;;;;;N;;;;; 1068C;LINEAR A SIGN A352;Lo;0;L;;;;;N;;;;; 1068D;LINEAR A SIGN A353;Lo;0;L;;;;;N;;;;; 1068E;LINEAR A SIGN A354;Lo;0;L;;;;;N;;;;; 1068F;LINEAR A SIGN A355;Lo;0;L;;;;;N;;;;; 10690;LINEAR A SIGN A356;Lo;0;L;;;;;N;;;;; 10691;LINEAR A SIGN A357;Lo;0;L;;;;;N;;;;; 10692;LINEAR A SIGN A358;Lo;0;L;;;;;N;;;;; 10693;LINEAR A SIGN A359;Lo;0;L;;;;;N;;;;; 10694;LINEAR A SIGN A360;Lo;0;L;;;;;N;;;;; 10695;LINEAR A SIGN A361;Lo;0;L;;;;;N;;;;; 10696;LINEAR A SIGN A362;Lo;0;L;;;;;N;;;;; 10697;LINEAR A SIGN A363;Lo;0;L;;;;;N;;;;; 10698;LINEAR A SIGN A364;Lo;0;L;;;;;N;;;;; 10699;LINEAR A SIGN A365;Lo;0;L;;;;;N;;;;; 1069A;LINEAR A SIGN A366;Lo;0;L;;;;;N;;;;; 1069B;LINEAR A SIGN A367;Lo;0;L;;;;;N;;;;; 1069C;LINEAR A SIGN A368;Lo;0;L;;;;;N;;;;; 1069D;LINEAR A SIGN A369;Lo;0;L;;;;;N;;;;; 1069E;LINEAR A SIGN A370;Lo;0;L;;;;;N;;;;; 1069F;LINEAR A SIGN A371;Lo;0;L;;;;;N;;;;; 106A0;LINEAR A SIGN A400-VAS;Lo;0;L;;;;;N;;;;; 106A1;LINEAR A SIGN A401-VAS;Lo;0;L;;;;;N;;;;; 106A2;LINEAR A SIGN A402-VAS;Lo;0;L;;;;;N;;;;; 106A3;LINEAR A SIGN A403-VAS;Lo;0;L;;;;;N;;;;; 106A4;LINEAR A SIGN A404-VAS;Lo;0;L;;;;;N;;;;; 106A5;LINEAR A SIGN A405-VAS;Lo;0;L;;;;;N;;;;; 106A6;LINEAR A SIGN A406-VAS;Lo;0;L;;;;;N;;;;; 106A7;LINEAR A SIGN A407-VAS;Lo;0;L;;;;;N;;;;; 106A8;LINEAR A SIGN A408-VAS;Lo;0;L;;;;;N;;;;; 106A9;LINEAR A SIGN A409-VAS;Lo;0;L;;;;;N;;;;; 106AA;LINEAR A SIGN A410-VAS;Lo;0;L;;;;;N;;;;; 106AB;LINEAR A SIGN A411-VAS;Lo;0;L;;;;;N;;;;; 106AC;LINEAR A SIGN A412-VAS;Lo;0;L;;;;;N;;;;; 106AD;LINEAR A SIGN A413-VAS;Lo;0;L;;;;;N;;;;; 106AE;LINEAR A SIGN A414-VAS;Lo;0;L;;;;;N;;;;; 106AF;LINEAR A SIGN A415-VAS;Lo;0;L;;;;;N;;;;; 106B0;LINEAR A SIGN A416-VAS;Lo;0;L;;;;;N;;;;; 106B1;LINEAR A SIGN A417-VAS;Lo;0;L;;;;;N;;;;; 106B2;LINEAR A SIGN A418-VAS;Lo;0;L;;;;;N;;;;; 106B3;LINEAR A SIGN A501;Lo;0;L;;;;;N;;;;; 106B4;LINEAR A SIGN A502;Lo;0;L;;;;;N;;;;; 106B5;LINEAR A SIGN A503;Lo;0;L;;;;;N;;;;; 106B6;LINEAR A SIGN A504;Lo;0;L;;;;;N;;;;; 106B7;LINEAR A SIGN A505;Lo;0;L;;;;;N;;;;; 106B8;LINEAR A SIGN A506;Lo;0;L;;;;;N;;;;; 106B9;LINEAR A SIGN A508;Lo;0;L;;;;;N;;;;; 106BA;LINEAR A SIGN A509;Lo;0;L;;;;;N;;;;; 106BB;LINEAR A SIGN A510;Lo;0;L;;;;;N;;;;; 106BC;LINEAR A SIGN A511;Lo;0;L;;;;;N;;;;; 106BD;LINEAR A SIGN A512;Lo;0;L;;;;;N;;;;; 106BE;LINEAR A SIGN A513;Lo;0;L;;;;;N;;;;; 106BF;LINEAR A SIGN A515;Lo;0;L;;;;;N;;;;; 106C0;LINEAR A SIGN A516;Lo;0;L;;;;;N;;;;; 106C1;LINEAR A SIGN A520;Lo;0;L;;;;;N;;;;; 106C2;LINEAR A SIGN A521;Lo;0;L;;;;;N;;;;; 106C3;LINEAR A SIGN A523;Lo;0;L;;;;;N;;;;; 106C4;LINEAR A SIGN A524;Lo;0;L;;;;;N;;;;; 106C5;LINEAR A SIGN A525;Lo;0;L;;;;;N;;;;; 106C6;LINEAR A SIGN A526;Lo;0;L;;;;;N;;;;; 106C7;LINEAR A SIGN A527;Lo;0;L;;;;;N;;;;; 106C8;LINEAR A SIGN A528;Lo;0;L;;;;;N;;;;; 106C9;LINEAR A SIGN A529;Lo;0;L;;;;;N;;;;; 106CA;LINEAR A SIGN A530;Lo;0;L;;;;;N;;;;; 106CB;LINEAR A SIGN A531;Lo;0;L;;;;;N;;;;; 106CC;LINEAR A SIGN A532;Lo;0;L;;;;;N;;;;; 106CD;LINEAR A SIGN A534;Lo;0;L;;;;;N;;;;; 106CE;LINEAR A SIGN A535;Lo;0;L;;;;;N;;;;; 106CF;LINEAR A SIGN A536;Lo;0;L;;;;;N;;;;; 106D0;LINEAR A SIGN A537;Lo;0;L;;;;;N;;;;; 106D1;LINEAR A SIGN A538;Lo;0;L;;;;;N;;;;; 106D2;LINEAR A SIGN A539;Lo;0;L;;;;;N;;;;; 106D3;LINEAR A SIGN A540;Lo;0;L;;;;;N;;;;; 106D4;LINEAR A SIGN A541;Lo;0;L;;;;;N;;;;; 106D5;LINEAR A SIGN A542;Lo;0;L;;;;;N;;;;; 106D6;LINEAR A SIGN A545;Lo;0;L;;;;;N;;;;; 106D7;LINEAR A SIGN A547;Lo;0;L;;;;;N;;;;; 106D8;LINEAR A SIGN A548;Lo;0;L;;;;;N;;;;; 106D9;LINEAR A SIGN A549;Lo;0;L;;;;;N;;;;; 106DA;LINEAR A SIGN A550;Lo;0;L;;;;;N;;;;; 106DB;LINEAR A SIGN A551;Lo;0;L;;;;;N;;;;; 106DC;LINEAR A SIGN A552;Lo;0;L;;;;;N;;;;; 106DD;LINEAR A SIGN A553;Lo;0;L;;;;;N;;;;; 106DE;LINEAR A SIGN A554;Lo;0;L;;;;;N;;;;; 106DF;LINEAR A SIGN A555;Lo;0;L;;;;;N;;;;; 106E0;LINEAR A SIGN A556;Lo;0;L;;;;;N;;;;; 106E1;LINEAR A SIGN A557;Lo;0;L;;;;;N;;;;; 106E2;LINEAR A SIGN A559;Lo;0;L;;;;;N;;;;; 106E3;LINEAR A SIGN A563;Lo;0;L;;;;;N;;;;; 106E4;LINEAR A SIGN A564;Lo;0;L;;;;;N;;;;; 106E5;LINEAR A SIGN A565;Lo;0;L;;;;;N;;;;; 106E6;LINEAR A SIGN A566;Lo;0;L;;;;;N;;;;; 106E7;LINEAR A SIGN A568;Lo;0;L;;;;;N;;;;; 106E8;LINEAR A SIGN A569;Lo;0;L;;;;;N;;;;; 106E9;LINEAR A SIGN A570;Lo;0;L;;;;;N;;;;; 106EA;LINEAR A SIGN A571;Lo;0;L;;;;;N;;;;; 106EB;LINEAR A SIGN A572;Lo;0;L;;;;;N;;;;; 106EC;LINEAR A SIGN A573;Lo;0;L;;;;;N;;;;; 106ED;LINEAR A SIGN A574;Lo;0;L;;;;;N;;;;; 106EE;LINEAR A SIGN A575;Lo;0;L;;;;;N;;;;; 106EF;LINEAR A SIGN A576;Lo;0;L;;;;;N;;;;; 106F0;LINEAR A SIGN A577;Lo;0;L;;;;;N;;;;; 106F1;LINEAR A SIGN A578;Lo;0;L;;;;;N;;;;; 106F2;LINEAR A SIGN A579;Lo;0;L;;;;;N;;;;; 106F3;LINEAR A SIGN A580;Lo;0;L;;;;;N;;;;; 106F4;LINEAR A SIGN A581;Lo;0;L;;;;;N;;;;; 106F5;LINEAR A SIGN A582;Lo;0;L;;;;;N;;;;; 106F6;LINEAR A SIGN A583;Lo;0;L;;;;;N;;;;; 106F7;LINEAR A SIGN A584;Lo;0;L;;;;;N;;;;; 106F8;LINEAR A SIGN A585;Lo;0;L;;;;;N;;;;; 106F9;LINEAR A SIGN A586;Lo;0;L;;;;;N;;;;; 106FA;LINEAR A SIGN A587;Lo;0;L;;;;;N;;;;; 106FB;LINEAR A SIGN A588;Lo;0;L;;;;;N;;;;; 106FC;LINEAR A SIGN A589;Lo;0;L;;;;;N;;;;; 106FD;LINEAR A SIGN A591;Lo;0;L;;;;;N;;;;; 106FE;LINEAR A SIGN A592;Lo;0;L;;;;;N;;;;; 106FF;LINEAR A SIGN A594;Lo;0;L;;;;;N;;;;; 10700;LINEAR A SIGN A595;Lo;0;L;;;;;N;;;;; 10701;LINEAR A SIGN A596;Lo;0;L;;;;;N;;;;; 10702;LINEAR A SIGN A598;Lo;0;L;;;;;N;;;;; 10703;LINEAR A SIGN A600;Lo;0;L;;;;;N;;;;; 10704;LINEAR A SIGN A601;Lo;0;L;;;;;N;;;;; 10705;LINEAR A SIGN A602;Lo;0;L;;;;;N;;;;; 10706;LINEAR A SIGN A603;Lo;0;L;;;;;N;;;;; 10707;LINEAR A SIGN A604;Lo;0;L;;;;;N;;;;; 10708;LINEAR A SIGN A606;Lo;0;L;;;;;N;;;;; 10709;LINEAR A SIGN A608;Lo;0;L;;;;;N;;;;; 1070A;LINEAR A SIGN A609;Lo;0;L;;;;;N;;;;; 1070B;LINEAR A SIGN A610;Lo;0;L;;;;;N;;;;; 1070C;LINEAR A SIGN A611;Lo;0;L;;;;;N;;;;; 1070D;LINEAR A SIGN A612;Lo;0;L;;;;;N;;;;; 1070E;LINEAR A SIGN A613;Lo;0;L;;;;;N;;;;; 1070F;LINEAR A SIGN A614;Lo;0;L;;;;;N;;;;; 10710;LINEAR A SIGN A615;Lo;0;L;;;;;N;;;;; 10711;LINEAR A SIGN A616;Lo;0;L;;;;;N;;;;; 10712;LINEAR A SIGN A617;Lo;0;L;;;;;N;;;;; 10713;LINEAR A SIGN A618;Lo;0;L;;;;;N;;;;; 10714;LINEAR A SIGN A619;Lo;0;L;;;;;N;;;;; 10715;LINEAR A SIGN A620;Lo;0;L;;;;;N;;;;; 10716;LINEAR A SIGN A621;Lo;0;L;;;;;N;;;;; 10717;LINEAR A SIGN A622;Lo;0;L;;;;;N;;;;; 10718;LINEAR A SIGN A623;Lo;0;L;;;;;N;;;;; 10719;LINEAR A SIGN A624;Lo;0;L;;;;;N;;;;; 1071A;LINEAR A SIGN A626;Lo;0;L;;;;;N;;;;; 1071B;LINEAR A SIGN A627;Lo;0;L;;;;;N;;;;; 1071C;LINEAR A SIGN A628;Lo;0;L;;;;;N;;;;; 1071D;LINEAR A SIGN A629;Lo;0;L;;;;;N;;;;; 1071E;LINEAR A SIGN A634;Lo;0;L;;;;;N;;;;; 1071F;LINEAR A SIGN A637;Lo;0;L;;;;;N;;;;; 10720;LINEAR A SIGN A638;Lo;0;L;;;;;N;;;;; 10721;LINEAR A SIGN A640;Lo;0;L;;;;;N;;;;; 10722;LINEAR A SIGN A642;Lo;0;L;;;;;N;;;;; 10723;LINEAR A SIGN A643;Lo;0;L;;;;;N;;;;; 10724;LINEAR A SIGN A644;Lo;0;L;;;;;N;;;;; 10725;LINEAR A SIGN A645;Lo;0;L;;;;;N;;;;; 10726;LINEAR A SIGN A646;Lo;0;L;;;;;N;;;;; 10727;LINEAR A SIGN A648;Lo;0;L;;;;;N;;;;; 10728;LINEAR A SIGN A649;Lo;0;L;;;;;N;;;;; 10729;LINEAR A SIGN A651;Lo;0;L;;;;;N;;;;; 1072A;LINEAR A SIGN A652;Lo;0;L;;;;;N;;;;; 1072B;LINEAR A SIGN A653;Lo;0;L;;;;;N;;;;; 1072C;LINEAR A SIGN A654;Lo;0;L;;;;;N;;;;; 1072D;LINEAR A SIGN A655;Lo;0;L;;;;;N;;;;; 1072E;LINEAR A SIGN A656;Lo;0;L;;;;;N;;;;; 1072F;LINEAR A SIGN A657;Lo;0;L;;;;;N;;;;; 10730;LINEAR A SIGN A658;Lo;0;L;;;;;N;;;;; 10731;LINEAR A SIGN A659;Lo;0;L;;;;;N;;;;; 10732;LINEAR A SIGN A660;Lo;0;L;;;;;N;;;;; 10733;LINEAR A SIGN A661;Lo;0;L;;;;;N;;;;; 10734;LINEAR A SIGN A662;Lo;0;L;;;;;N;;;;; 10735;LINEAR A SIGN A663;Lo;0;L;;;;;N;;;;; 10736;LINEAR A SIGN A664;Lo;0;L;;;;;N;;;;; 10740;LINEAR A SIGN A701 A;Lo;0;L;;;;;N;;;;; 10741;LINEAR A SIGN A702 B;Lo;0;L;;;;;N;;;;; 10742;LINEAR A SIGN A703 D;Lo;0;L;;;;;N;;;;; 10743;LINEAR A SIGN A704 E;Lo;0;L;;;;;N;;;;; 10744;LINEAR A SIGN A705 F;Lo;0;L;;;;;N;;;;; 10745;LINEAR A SIGN A706 H;Lo;0;L;;;;;N;;;;; 10746;LINEAR A SIGN A707 J;Lo;0;L;;;;;N;;;;; 10747;LINEAR A SIGN A708 K;Lo;0;L;;;;;N;;;;; 10748;LINEAR A SIGN A709 L;Lo;0;L;;;;;N;;;;; 10749;LINEAR A SIGN A709-2 L2;Lo;0;L;;;;;N;;;;; 1074A;LINEAR A SIGN A709-3 L3;Lo;0;L;;;;;N;;;;; 1074B;LINEAR A SIGN A709-4 L4;Lo;0;L;;;;;N;;;;; 1074C;LINEAR A SIGN A709-6 L6;Lo;0;L;;;;;N;;;;; 1074D;LINEAR A SIGN A710 W;Lo;0;L;;;;;N;;;;; 1074E;LINEAR A SIGN A711 X;Lo;0;L;;;;;N;;;;; 1074F;LINEAR A SIGN A712 Y;Lo;0;L;;;;;N;;;;; 10750;LINEAR A SIGN A713 OMEGA;Lo;0;L;;;;;N;;;;; 10751;LINEAR A SIGN A714 ABB;Lo;0;L;;;;;N;;;;; 10752;LINEAR A SIGN A715 BB;Lo;0;L;;;;;N;;;;; 10753;LINEAR A SIGN A717 DD;Lo;0;L;;;;;N;;;;; 10754;LINEAR A SIGN A726 EYYY;Lo;0;L;;;;;N;;;;; 10755;LINEAR A SIGN A732 JE;Lo;0;L;;;;;N;;;;; 10760;LINEAR A SIGN A800;Lo;0;L;;;;;N;;;;; 10761;LINEAR A SIGN A801;Lo;0;L;;;;;N;;;;; 10762;LINEAR A SIGN A802;Lo;0;L;;;;;N;;;;; 10763;LINEAR A SIGN A803;Lo;0;L;;;;;N;;;;; 10764;LINEAR A SIGN A804;Lo;0;L;;;;;N;;;;; 10765;LINEAR A SIGN A805;Lo;0;L;;;;;N;;;;; 10766;LINEAR A SIGN A806;Lo;0;L;;;;;N;;;;; 10767;LINEAR A SIGN A807;Lo;0;L;;;;;N;;;;; 10800;CYPRIOT SYLLABLE A;Lo;0;R;;;;;N;;;;; 10801;CYPRIOT SYLLABLE E;Lo;0;R;;;;;N;;;;; 10802;CYPRIOT SYLLABLE I;Lo;0;R;;;;;N;;;;; 10803;CYPRIOT SYLLABLE O;Lo;0;R;;;;;N;;;;; 10804;CYPRIOT SYLLABLE U;Lo;0;R;;;;;N;;;;; 10805;CYPRIOT SYLLABLE JA;Lo;0;R;;;;;N;;;;; 10808;CYPRIOT SYLLABLE JO;Lo;0;R;;;;;N;;;;; 1080A;CYPRIOT SYLLABLE KA;Lo;0;R;;;;;N;;;;; 1080B;CYPRIOT SYLLABLE KE;Lo;0;R;;;;;N;;;;; 1080C;CYPRIOT SYLLABLE KI;Lo;0;R;;;;;N;;;;; 1080D;CYPRIOT SYLLABLE KO;Lo;0;R;;;;;N;;;;; 1080E;CYPRIOT SYLLABLE KU;Lo;0;R;;;;;N;;;;; 1080F;CYPRIOT SYLLABLE LA;Lo;0;R;;;;;N;;;;; 10810;CYPRIOT SYLLABLE LE;Lo;0;R;;;;;N;;;;; 10811;CYPRIOT SYLLABLE LI;Lo;0;R;;;;;N;;;;; 10812;CYPRIOT SYLLABLE LO;Lo;0;R;;;;;N;;;;; 10813;CYPRIOT SYLLABLE LU;Lo;0;R;;;;;N;;;;; 10814;CYPRIOT SYLLABLE MA;Lo;0;R;;;;;N;;;;; 10815;CYPRIOT SYLLABLE ME;Lo;0;R;;;;;N;;;;; 10816;CYPRIOT SYLLABLE MI;Lo;0;R;;;;;N;;;;; 10817;CYPRIOT SYLLABLE MO;Lo;0;R;;;;;N;;;;; 10818;CYPRIOT SYLLABLE MU;Lo;0;R;;;;;N;;;;; 10819;CYPRIOT SYLLABLE NA;Lo;0;R;;;;;N;;;;; 1081A;CYPRIOT SYLLABLE NE;Lo;0;R;;;;;N;;;;; 1081B;CYPRIOT SYLLABLE NI;Lo;0;R;;;;;N;;;;; 1081C;CYPRIOT SYLLABLE NO;Lo;0;R;;;;;N;;;;; 1081D;CYPRIOT SYLLABLE NU;Lo;0;R;;;;;N;;;;; 1081E;CYPRIOT SYLLABLE PA;Lo;0;R;;;;;N;;;;; 1081F;CYPRIOT SYLLABLE PE;Lo;0;R;;;;;N;;;;; 10820;CYPRIOT SYLLABLE PI;Lo;0;R;;;;;N;;;;; 10821;CYPRIOT SYLLABLE PO;Lo;0;R;;;;;N;;;;; 10822;CYPRIOT SYLLABLE PU;Lo;0;R;;;;;N;;;;; 10823;CYPRIOT SYLLABLE RA;Lo;0;R;;;;;N;;;;; 10824;CYPRIOT SYLLABLE RE;Lo;0;R;;;;;N;;;;; 10825;CYPRIOT SYLLABLE RI;Lo;0;R;;;;;N;;;;; 10826;CYPRIOT SYLLABLE RO;Lo;0;R;;;;;N;;;;; 10827;CYPRIOT SYLLABLE RU;Lo;0;R;;;;;N;;;;; 10828;CYPRIOT SYLLABLE SA;Lo;0;R;;;;;N;;;;; 10829;CYPRIOT SYLLABLE SE;Lo;0;R;;;;;N;;;;; 1082A;CYPRIOT SYLLABLE SI;Lo;0;R;;;;;N;;;;; 1082B;CYPRIOT SYLLABLE SO;Lo;0;R;;;;;N;;;;; 1082C;CYPRIOT SYLLABLE SU;Lo;0;R;;;;;N;;;;; 1082D;CYPRIOT SYLLABLE TA;Lo;0;R;;;;;N;;;;; 1082E;CYPRIOT SYLLABLE TE;Lo;0;R;;;;;N;;;;; 1082F;CYPRIOT SYLLABLE TI;Lo;0;R;;;;;N;;;;; 10830;CYPRIOT SYLLABLE TO;Lo;0;R;;;;;N;;;;; 10831;CYPRIOT SYLLABLE TU;Lo;0;R;;;;;N;;;;; 10832;CYPRIOT SYLLABLE WA;Lo;0;R;;;;;N;;;;; 10833;CYPRIOT SYLLABLE WE;Lo;0;R;;;;;N;;;;; 10834;CYPRIOT SYLLABLE WI;Lo;0;R;;;;;N;;;;; 10835;CYPRIOT SYLLABLE WO;Lo;0;R;;;;;N;;;;; 10837;CYPRIOT SYLLABLE XA;Lo;0;R;;;;;N;;;;; 10838;CYPRIOT SYLLABLE XE;Lo;0;R;;;;;N;;;;; 1083C;CYPRIOT SYLLABLE ZA;Lo;0;R;;;;;N;;;;; 1083F;CYPRIOT SYLLABLE ZO;Lo;0;R;;;;;N;;;;; 10840;IMPERIAL ARAMAIC LETTER ALEPH;Lo;0;R;;;;;N;;;;; 10841;IMPERIAL ARAMAIC LETTER BETH;Lo;0;R;;;;;N;;;;; 10842;IMPERIAL ARAMAIC LETTER GIMEL;Lo;0;R;;;;;N;;;;; 10843;IMPERIAL ARAMAIC LETTER DALETH;Lo;0;R;;;;;N;;;;; 10844;IMPERIAL ARAMAIC LETTER HE;Lo;0;R;;;;;N;;;;; 10845;IMPERIAL ARAMAIC LETTER WAW;Lo;0;R;;;;;N;;;;; 10846;IMPERIAL ARAMAIC LETTER ZAYIN;Lo;0;R;;;;;N;;;;; 10847;IMPERIAL ARAMAIC LETTER HETH;Lo;0;R;;;;;N;;;;; 10848;IMPERIAL ARAMAIC LETTER TETH;Lo;0;R;;;;;N;;;;; 10849;IMPERIAL ARAMAIC LETTER YODH;Lo;0;R;;;;;N;;;;; 1084A;IMPERIAL ARAMAIC LETTER KAPH;Lo;0;R;;;;;N;;;;; 1084B;IMPERIAL ARAMAIC LETTER LAMEDH;Lo;0;R;;;;;N;;;;; 1084C;IMPERIAL ARAMAIC LETTER MEM;Lo;0;R;;;;;N;;;;; 1084D;IMPERIAL ARAMAIC LETTER NUN;Lo;0;R;;;;;N;;;;; 1084E;IMPERIAL ARAMAIC LETTER SAMEKH;Lo;0;R;;;;;N;;;;; 1084F;IMPERIAL ARAMAIC LETTER AYIN;Lo;0;R;;;;;N;;;;; 10850;IMPERIAL ARAMAIC LETTER PE;Lo;0;R;;;;;N;;;;; 10851;IMPERIAL ARAMAIC LETTER SADHE;Lo;0;R;;;;;N;;;;; 10852;IMPERIAL ARAMAIC LETTER QOPH;Lo;0;R;;;;;N;;;;; 10853;IMPERIAL ARAMAIC LETTER RESH;Lo;0;R;;;;;N;;;;; 10854;IMPERIAL ARAMAIC LETTER SHIN;Lo;0;R;;;;;N;;;;; 10855;IMPERIAL ARAMAIC LETTER TAW;Lo;0;R;;;;;N;;;;; 10857;IMPERIAL ARAMAIC SECTION SIGN;Po;0;R;;;;;N;;;;; 10858;IMPERIAL ARAMAIC NUMBER ONE;No;0;R;;;;1;N;;;;; 10859;IMPERIAL ARAMAIC NUMBER TWO;No;0;R;;;;2;N;;;;; 1085A;IMPERIAL ARAMAIC NUMBER THREE;No;0;R;;;;3;N;;;;; 1085B;IMPERIAL ARAMAIC NUMBER TEN;No;0;R;;;;10;N;;;;; 1085C;IMPERIAL ARAMAIC NUMBER TWENTY;No;0;R;;;;20;N;;;;; 1085D;IMPERIAL ARAMAIC NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;; 1085E;IMPERIAL ARAMAIC NUMBER ONE THOUSAND;No;0;R;;;;1000;N;;;;; 1085F;IMPERIAL ARAMAIC NUMBER TEN THOUSAND;No;0;R;;;;10000;N;;;;; 10860;PALMYRENE LETTER ALEPH;Lo;0;R;;;;;N;;;;; 10861;PALMYRENE LETTER BETH;Lo;0;R;;;;;N;;;;; 10862;PALMYRENE LETTER GIMEL;Lo;0;R;;;;;N;;;;; 10863;PALMYRENE LETTER DALETH;Lo;0;R;;;;;N;;;;; 10864;PALMYRENE LETTER HE;Lo;0;R;;;;;N;;;;; 10865;PALMYRENE LETTER WAW;Lo;0;R;;;;;N;;;;; 10866;PALMYRENE LETTER ZAYIN;Lo;0;R;;;;;N;;;;; 10867;PALMYRENE LETTER HETH;Lo;0;R;;;;;N;;;;; 10868;PALMYRENE LETTER TETH;Lo;0;R;;;;;N;;;;; 10869;PALMYRENE LETTER YODH;Lo;0;R;;;;;N;;;;; 1086A;PALMYRENE LETTER KAPH;Lo;0;R;;;;;N;;;;; 1086B;PALMYRENE LETTER LAMEDH;Lo;0;R;;;;;N;;;;; 1086C;PALMYRENE LETTER MEM;Lo;0;R;;;;;N;;;;; 1086D;PALMYRENE LETTER FINAL NUN;Lo;0;R;;;;;N;;;;; 1086E;PALMYRENE LETTER NUN;Lo;0;R;;;;;N;;;;; 1086F;PALMYRENE LETTER SAMEKH;Lo;0;R;;;;;N;;;;; 10870;PALMYRENE LETTER AYIN;Lo;0;R;;;;;N;;;;; 10871;PALMYRENE LETTER PE;Lo;0;R;;;;;N;;;;; 10872;PALMYRENE LETTER SADHE;Lo;0;R;;;;;N;;;;; 10873;PALMYRENE LETTER QOPH;Lo;0;R;;;;;N;;;;; 10874;PALMYRENE LETTER RESH;Lo;0;R;;;;;N;;;;; 10875;PALMYRENE LETTER SHIN;Lo;0;R;;;;;N;;;;; 10876;PALMYRENE LETTER TAW;Lo;0;R;;;;;N;;;;; 10877;PALMYRENE LEFT-POINTING FLEURON;So;0;R;;;;;N;;;;; 10878;PALMYRENE RIGHT-POINTING FLEURON;So;0;R;;;;;N;;;;; 10879;PALMYRENE NUMBER ONE;No;0;R;;;;1;N;;;;; 1087A;PALMYRENE NUMBER TWO;No;0;R;;;;2;N;;;;; 1087B;PALMYRENE NUMBER THREE;No;0;R;;;;3;N;;;;; 1087C;PALMYRENE NUMBER FOUR;No;0;R;;;;4;N;;;;; 1087D;PALMYRENE NUMBER FIVE;No;0;R;;;;5;N;;;;; 1087E;PALMYRENE NUMBER TEN;No;0;R;;;;10;N;;;;; 1087F;PALMYRENE NUMBER TWENTY;No;0;R;;;;20;N;;;;; 10880;NABATAEAN LETTER FINAL ALEPH;Lo;0;R;;;;;N;;;;; 10881;NABATAEAN LETTER ALEPH;Lo;0;R;;;;;N;;;;; 10882;NABATAEAN LETTER FINAL BETH;Lo;0;R;;;;;N;;;;; 10883;NABATAEAN LETTER BETH;Lo;0;R;;;;;N;;;;; 10884;NABATAEAN LETTER GIMEL;Lo;0;R;;;;;N;;;;; 10885;NABATAEAN LETTER DALETH;Lo;0;R;;;;;N;;;;; 10886;NABATAEAN LETTER FINAL HE;Lo;0;R;;;;;N;;;;; 10887;NABATAEAN LETTER HE;Lo;0;R;;;;;N;;;;; 10888;NABATAEAN LETTER WAW;Lo;0;R;;;;;N;;;;; 10889;NABATAEAN LETTER ZAYIN;Lo;0;R;;;;;N;;;;; 1088A;NABATAEAN LETTER HETH;Lo;0;R;;;;;N;;;;; 1088B;NABATAEAN LETTER TETH;Lo;0;R;;;;;N;;;;; 1088C;NABATAEAN LETTER FINAL YODH;Lo;0;R;;;;;N;;;;; 1088D;NABATAEAN LETTER YODH;Lo;0;R;;;;;N;;;;; 1088E;NABATAEAN LETTER FINAL KAPH;Lo;0;R;;;;;N;;;;; 1088F;NABATAEAN LETTER KAPH;Lo;0;R;;;;;N;;;;; 10890;NABATAEAN LETTER FINAL LAMEDH;Lo;0;R;;;;;N;;;;; 10891;NABATAEAN LETTER LAMEDH;Lo;0;R;;;;;N;;;;; 10892;NABATAEAN LETTER FINAL MEM;Lo;0;R;;;;;N;;;;; 10893;NABATAEAN LETTER MEM;Lo;0;R;;;;;N;;;;; 10894;NABATAEAN LETTER FINAL NUN;Lo;0;R;;;;;N;;;;; 10895;NABATAEAN LETTER NUN;Lo;0;R;;;;;N;;;;; 10896;NABATAEAN LETTER SAMEKH;Lo;0;R;;;;;N;;;;; 10897;NABATAEAN LETTER AYIN;Lo;0;R;;;;;N;;;;; 10898;NABATAEAN LETTER PE;Lo;0;R;;;;;N;;;;; 10899;NABATAEAN LETTER SADHE;Lo;0;R;;;;;N;;;;; 1089A;NABATAEAN LETTER QOPH;Lo;0;R;;;;;N;;;;; 1089B;NABATAEAN LETTER RESH;Lo;0;R;;;;;N;;;;; 1089C;NABATAEAN LETTER FINAL SHIN;Lo;0;R;;;;;N;;;;; 1089D;NABATAEAN LETTER SHIN;Lo;0;R;;;;;N;;;;; 1089E;NABATAEAN LETTER TAW;Lo;0;R;;;;;N;;;;; 108A7;NABATAEAN NUMBER ONE;No;0;R;;;;1;N;;;;; 108A8;NABATAEAN NUMBER TWO;No;0;R;;;;2;N;;;;; 108A9;NABATAEAN NUMBER THREE;No;0;R;;;;3;N;;;;; 108AA;NABATAEAN NUMBER FOUR;No;0;R;;;;4;N;;;;; 108AB;NABATAEAN CRUCIFORM NUMBER FOUR;No;0;R;;;;4;N;;;;; 108AC;NABATAEAN NUMBER FIVE;No;0;R;;;;5;N;;;;; 108AD;NABATAEAN NUMBER TEN;No;0;R;;;;10;N;;;;; 108AE;NABATAEAN NUMBER TWENTY;No;0;R;;;;20;N;;;;; 108AF;NABATAEAN NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;; 108E0;HATRAN LETTER ALEPH;Lo;0;R;;;;;N;;;;; 108E1;HATRAN LETTER BETH;Lo;0;R;;;;;N;;;;; 108E2;HATRAN LETTER GIMEL;Lo;0;R;;;;;N;;;;; 108E3;HATRAN LETTER DALETH-RESH;Lo;0;R;;;;;N;;;;; 108E4;HATRAN LETTER HE;Lo;0;R;;;;;N;;;;; 108E5;HATRAN LETTER WAW;Lo;0;R;;;;;N;;;;; 108E6;HATRAN LETTER ZAYN;Lo;0;R;;;;;N;;;;; 108E7;HATRAN LETTER HETH;Lo;0;R;;;;;N;;;;; 108E8;HATRAN LETTER TETH;Lo;0;R;;;;;N;;;;; 108E9;HATRAN LETTER YODH;Lo;0;R;;;;;N;;;;; 108EA;HATRAN LETTER KAPH;Lo;0;R;;;;;N;;;;; 108EB;HATRAN LETTER LAMEDH;Lo;0;R;;;;;N;;;;; 108EC;HATRAN LETTER MEM;Lo;0;R;;;;;N;;;;; 108ED;HATRAN LETTER NUN;Lo;0;R;;;;;N;;;;; 108EE;HATRAN LETTER SAMEKH;Lo;0;R;;;;;N;;;;; 108EF;HATRAN LETTER AYN;Lo;0;R;;;;;N;;;;; 108F0;HATRAN LETTER PE;Lo;0;R;;;;;N;;;;; 108F1;HATRAN LETTER SADHE;Lo;0;R;;;;;N;;;;; 108F2;HATRAN LETTER QOPH;Lo;0;R;;;;;N;;;;; 108F4;HATRAN LETTER SHIN;Lo;0;R;;;;;N;;;;; 108F5;HATRAN LETTER TAW;Lo;0;R;;;;;N;;;;; 108FB;HATRAN NUMBER ONE;No;0;R;;;;1;N;;;;; 108FC;HATRAN NUMBER FIVE;No;0;R;;;;5;N;;;;; 108FD;HATRAN NUMBER TEN;No;0;R;;;;10;N;;;;; 108FE;HATRAN NUMBER TWENTY;No;0;R;;;;20;N;;;;; 108FF;HATRAN NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;; 10900;PHOENICIAN LETTER ALF;Lo;0;R;;;;;N;;;;; 10901;PHOENICIAN LETTER BET;Lo;0;R;;;;;N;;;;; 10902;PHOENICIAN LETTER GAML;Lo;0;R;;;;;N;;;;; 10903;PHOENICIAN LETTER DELT;Lo;0;R;;;;;N;;;;; 10904;PHOENICIAN LETTER HE;Lo;0;R;;;;;N;;;;; 10905;PHOENICIAN LETTER WAU;Lo;0;R;;;;;N;;;;; 10906;PHOENICIAN LETTER ZAI;Lo;0;R;;;;;N;;;;; 10907;PHOENICIAN LETTER HET;Lo;0;R;;;;;N;;;;; 10908;PHOENICIAN LETTER TET;Lo;0;R;;;;;N;;;;; 10909;PHOENICIAN LETTER YOD;Lo;0;R;;;;;N;;;;; 1090A;PHOENICIAN LETTER KAF;Lo;0;R;;;;;N;;;;; 1090B;PHOENICIAN LETTER LAMD;Lo;0;R;;;;;N;;;;; 1090C;PHOENICIAN LETTER MEM;Lo;0;R;;;;;N;;;;; 1090D;PHOENICIAN LETTER NUN;Lo;0;R;;;;;N;;;;; 1090E;PHOENICIAN LETTER SEMK;Lo;0;R;;;;;N;;;;; 1090F;PHOENICIAN LETTER AIN;Lo;0;R;;;;;N;;;;; 10910;PHOENICIAN LETTER PE;Lo;0;R;;;;;N;;;;; 10911;PHOENICIAN LETTER SADE;Lo;0;R;;;;;N;;;;; 10912;PHOENICIAN LETTER QOF;Lo;0;R;;;;;N;;;;; 10913;PHOENICIAN LETTER ROSH;Lo;0;R;;;;;N;;;;; 10914;PHOENICIAN LETTER SHIN;Lo;0;R;;;;;N;;;;; 10915;PHOENICIAN LETTER TAU;Lo;0;R;;;;;N;;;;; 10916;PHOENICIAN NUMBER ONE;No;0;R;;;;1;N;;;;; 10917;PHOENICIAN NUMBER TEN;No;0;R;;;;10;N;;;;; 10918;PHOENICIAN NUMBER TWENTY;No;0;R;;;;20;N;;;;; 10919;PHOENICIAN NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;; 1091A;PHOENICIAN NUMBER TWO;No;0;R;;;;2;N;;;;; 1091B;PHOENICIAN NUMBER THREE;No;0;R;;;;3;N;;;;; 1091F;PHOENICIAN WORD SEPARATOR;Po;0;ON;;;;;N;;;;; 10920;LYDIAN LETTER A;Lo;0;R;;;;;N;;;;; 10921;LYDIAN LETTER B;Lo;0;R;;;;;N;;;;; 10922;LYDIAN LETTER G;Lo;0;R;;;;;N;;;;; 10923;LYDIAN LETTER D;Lo;0;R;;;;;N;;;;; 10924;LYDIAN LETTER E;Lo;0;R;;;;;N;;;;; 10925;LYDIAN LETTER V;Lo;0;R;;;;;N;;;;; 10926;LYDIAN LETTER I;Lo;0;R;;;;;N;;;;; 10927;LYDIAN LETTER Y;Lo;0;R;;;;;N;;;;; 10928;LYDIAN LETTER K;Lo;0;R;;;;;N;;;;; 10929;LYDIAN LETTER L;Lo;0;R;;;;;N;;;;; 1092A;LYDIAN LETTER M;Lo;0;R;;;;;N;;;;; 1092B;LYDIAN LETTER N;Lo;0;R;;;;;N;;;;; 1092C;LYDIAN LETTER O;Lo;0;R;;;;;N;;;;; 1092D;LYDIAN LETTER R;Lo;0;R;;;;;N;;;;; 1092E;LYDIAN LETTER SS;Lo;0;R;;;;;N;;;;; 1092F;LYDIAN LETTER T;Lo;0;R;;;;;N;;;;; 10930;LYDIAN LETTER U;Lo;0;R;;;;;N;;;;; 10931;LYDIAN LETTER F;Lo;0;R;;;;;N;;;;; 10932;LYDIAN LETTER Q;Lo;0;R;;;;;N;;;;; 10933;LYDIAN LETTER S;Lo;0;R;;;;;N;;;;; 10934;LYDIAN LETTER TT;Lo;0;R;;;;;N;;;;; 10935;LYDIAN LETTER AN;Lo;0;R;;;;;N;;;;; 10936;LYDIAN LETTER EN;Lo;0;R;;;;;N;;;;; 10937;LYDIAN LETTER LY;Lo;0;R;;;;;N;;;;; 10938;LYDIAN LETTER NN;Lo;0;R;;;;;N;;;;; 10939;LYDIAN LETTER C;Lo;0;R;;;;;N;;;;; 1093F;LYDIAN TRIANGULAR MARK;Po;0;R;;;;;N;;;;; 10980;MEROITIC HIEROGLYPHIC LETTER A;Lo;0;R;;;;;N;;;;; 10981;MEROITIC HIEROGLYPHIC LETTER E;Lo;0;R;;;;;N;;;;; 10982;MEROITIC HIEROGLYPHIC LETTER I;Lo;0;R;;;;;N;;;;; 10983;MEROITIC HIEROGLYPHIC LETTER O;Lo;0;R;;;;;N;;;;; 10984;MEROITIC HIEROGLYPHIC LETTER YA;Lo;0;R;;;;;N;;;;; 10985;MEROITIC HIEROGLYPHIC LETTER WA;Lo;0;R;;;;;N;;;;; 10986;MEROITIC HIEROGLYPHIC LETTER BA;Lo;0;R;;;;;N;;;;; 10987;MEROITIC HIEROGLYPHIC LETTER BA-2;Lo;0;R;;;;;N;;;;; 10988;MEROITIC HIEROGLYPHIC LETTER PA;Lo;0;R;;;;;N;;;;; 10989;MEROITIC HIEROGLYPHIC LETTER MA;Lo;0;R;;;;;N;;;;; 1098A;MEROITIC HIEROGLYPHIC LETTER NA;Lo;0;R;;;;;N;;;;; 1098B;MEROITIC HIEROGLYPHIC LETTER NA-2;Lo;0;R;;;;;N;;;;; 1098C;MEROITIC HIEROGLYPHIC LETTER NE;Lo;0;R;;;;;N;;;;; 1098D;MEROITIC HIEROGLYPHIC LETTER NE-2;Lo;0;R;;;;;N;;;;; 1098E;MEROITIC HIEROGLYPHIC LETTER RA;Lo;0;R;;;;;N;;;;; 1098F;MEROITIC HIEROGLYPHIC LETTER RA-2;Lo;0;R;;;;;N;;;;; 10990;MEROITIC HIEROGLYPHIC LETTER LA;Lo;0;R;;;;;N;;;;; 10991;MEROITIC HIEROGLYPHIC LETTER KHA;Lo;0;R;;;;;N;;;;; 10992;MEROITIC HIEROGLYPHIC LETTER HHA;Lo;0;R;;;;;N;;;;; 10993;MEROITIC HIEROGLYPHIC LETTER SA;Lo;0;R;;;;;N;;;;; 10994;MEROITIC HIEROGLYPHIC LETTER SA-2;Lo;0;R;;;;;N;;;;; 10995;MEROITIC HIEROGLYPHIC LETTER SE;Lo;0;R;;;;;N;;;;; 10996;MEROITIC HIEROGLYPHIC LETTER KA;Lo;0;R;;;;;N;;;;; 10997;MEROITIC HIEROGLYPHIC LETTER QA;Lo;0;R;;;;;N;;;;; 10998;MEROITIC HIEROGLYPHIC LETTER TA;Lo;0;R;;;;;N;;;;; 10999;MEROITIC HIEROGLYPHIC LETTER TA-2;Lo;0;R;;;;;N;;;;; 1099A;MEROITIC HIEROGLYPHIC LETTER TE;Lo;0;R;;;;;N;;;;; 1099B;MEROITIC HIEROGLYPHIC LETTER TE-2;Lo;0;R;;;;;N;;;;; 1099C;MEROITIC HIEROGLYPHIC LETTER TO;Lo;0;R;;;;;N;;;;; 1099D;MEROITIC HIEROGLYPHIC LETTER DA;Lo;0;R;;;;;N;;;;; 1099E;MEROITIC HIEROGLYPHIC SYMBOL VIDJ;Lo;0;R;;;;;N;;;;; 1099F;MEROITIC HIEROGLYPHIC SYMBOL VIDJ-2;Lo;0;R;;;;;N;;;;; 109A0;MEROITIC CURSIVE LETTER A;Lo;0;R;;;;;N;;;;; 109A1;MEROITIC CURSIVE LETTER E;Lo;0;R;;;;;N;;;;; 109A2;MEROITIC CURSIVE LETTER I;Lo;0;R;;;;;N;;;;; 109A3;MEROITIC CURSIVE LETTER O;Lo;0;R;;;;;N;;;;; 109A4;MEROITIC CURSIVE LETTER YA;Lo;0;R;;;;;N;;;;; 109A5;MEROITIC CURSIVE LETTER WA;Lo;0;R;;;;;N;;;;; 109A6;MEROITIC CURSIVE LETTER BA;Lo;0;R;;;;;N;;;;; 109A7;MEROITIC CURSIVE LETTER PA;Lo;0;R;;;;;N;;;;; 109A8;MEROITIC CURSIVE LETTER MA;Lo;0;R;;;;;N;;;;; 109A9;MEROITIC CURSIVE LETTER NA;Lo;0;R;;;;;N;;;;; 109AA;MEROITIC CURSIVE LETTER NE;Lo;0;R;;;;;N;;;;; 109AB;MEROITIC CURSIVE LETTER RA;Lo;0;R;;;;;N;;;;; 109AC;MEROITIC CURSIVE LETTER LA;Lo;0;R;;;;;N;;;;; 109AD;MEROITIC CURSIVE LETTER KHA;Lo;0;R;;;;;N;;;;; 109AE;MEROITIC CURSIVE LETTER HHA;Lo;0;R;;;;;N;;;;; 109AF;MEROITIC CURSIVE LETTER SA;Lo;0;R;;;;;N;;;;; 109B0;MEROITIC CURSIVE LETTER ARCHAIC SA;Lo;0;R;;;;;N;;;;; 109B1;MEROITIC CURSIVE LETTER SE;Lo;0;R;;;;;N;;;;; 109B2;MEROITIC CURSIVE LETTER KA;Lo;0;R;;;;;N;;;;; 109B3;MEROITIC CURSIVE LETTER QA;Lo;0;R;;;;;N;;;;; 109B4;MEROITIC CURSIVE LETTER TA;Lo;0;R;;;;;N;;;;; 109B5;MEROITIC CURSIVE LETTER TE;Lo;0;R;;;;;N;;;;; 109B6;MEROITIC CURSIVE LETTER TO;Lo;0;R;;;;;N;;;;; 109B7;MEROITIC CURSIVE LETTER DA;Lo;0;R;;;;;N;;;;; 109BC;MEROITIC CURSIVE FRACTION ELEVEN TWELFTHS;No;0;R;;;;11/12;N;;;;; 109BD;MEROITIC CURSIVE FRACTION ONE HALF;No;0;R;;;;1/2;N;;;;; 109BE;MEROITIC CURSIVE LOGOGRAM RMT;Lo;0;R;;;;;N;;;;; 109BF;MEROITIC CURSIVE LOGOGRAM IMN;Lo;0;R;;;;;N;;;;; 109C0;MEROITIC CURSIVE NUMBER ONE;No;0;R;;;;1;N;;;;; 109C1;MEROITIC CURSIVE NUMBER TWO;No;0;R;;;;2;N;;;;; 109C2;MEROITIC CURSIVE NUMBER THREE;No;0;R;;;;3;N;;;;; 109C3;MEROITIC CURSIVE NUMBER FOUR;No;0;R;;;;4;N;;;;; 109C4;MEROITIC CURSIVE NUMBER FIVE;No;0;R;;;;5;N;;;;; 109C5;MEROITIC CURSIVE NUMBER SIX;No;0;R;;;;6;N;;;;; 109C6;MEROITIC CURSIVE NUMBER SEVEN;No;0;R;;;;7;N;;;;; 109C7;MEROITIC CURSIVE NUMBER EIGHT;No;0;R;;;;8;N;;;;; 109C8;MEROITIC CURSIVE NUMBER NINE;No;0;R;;;;9;N;;;;; 109C9;MEROITIC CURSIVE NUMBER TEN;No;0;R;;;;10;N;;;;; 109CA;MEROITIC CURSIVE NUMBER TWENTY;No;0;R;;;;20;N;;;;; 109CB;MEROITIC CURSIVE NUMBER THIRTY;No;0;R;;;;30;N;;;;; 109CC;MEROITIC CURSIVE NUMBER FORTY;No;0;R;;;;40;N;;;;; 109CD;MEROITIC CURSIVE NUMBER FIFTY;No;0;R;;;;50;N;;;;; 109CE;MEROITIC CURSIVE NUMBER SIXTY;No;0;R;;;;60;N;;;;; 109CF;MEROITIC CURSIVE NUMBER SEVENTY;No;0;R;;;;70;N;;;;; 109D2;MEROITIC CURSIVE NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;; 109D3;MEROITIC CURSIVE NUMBER TWO HUNDRED;No;0;R;;;;200;N;;;;; 109D4;MEROITIC CURSIVE NUMBER THREE HUNDRED;No;0;R;;;;300;N;;;;; 109D5;MEROITIC CURSIVE NUMBER FOUR HUNDRED;No;0;R;;;;400;N;;;;; 109D6;MEROITIC CURSIVE NUMBER FIVE HUNDRED;No;0;R;;;;500;N;;;;; 109D7;MEROITIC CURSIVE NUMBER SIX HUNDRED;No;0;R;;;;600;N;;;;; 109D8;MEROITIC CURSIVE NUMBER SEVEN HUNDRED;No;0;R;;;;700;N;;;;; 109D9;MEROITIC CURSIVE NUMBER EIGHT HUNDRED;No;0;R;;;;800;N;;;;; 109DA;MEROITIC CURSIVE NUMBER NINE HUNDRED;No;0;R;;;;900;N;;;;; 109DB;MEROITIC CURSIVE NUMBER ONE THOUSAND;No;0;R;;;;1000;N;;;;; 109DC;MEROITIC CURSIVE NUMBER TWO THOUSAND;No;0;R;;;;2000;N;;;;; 109DD;MEROITIC CURSIVE NUMBER THREE THOUSAND;No;0;R;;;;3000;N;;;;; 109DE;MEROITIC CURSIVE NUMBER FOUR THOUSAND;No;0;R;;;;4000;N;;;;; 109DF;MEROITIC CURSIVE NUMBER FIVE THOUSAND;No;0;R;;;;5000;N;;;;; 109E0;MEROITIC CURSIVE NUMBER SIX THOUSAND;No;0;R;;;;6000;N;;;;; 109E1;MEROITIC CURSIVE NUMBER SEVEN THOUSAND;No;0;R;;;;7000;N;;;;; 109E2;MEROITIC CURSIVE NUMBER EIGHT THOUSAND;No;0;R;;;;8000;N;;;;; 109E3;MEROITIC CURSIVE NUMBER NINE THOUSAND;No;0;R;;;;9000;N;;;;; 109E4;MEROITIC CURSIVE NUMBER TEN THOUSAND;No;0;R;;;;10000;N;;;;; 109E5;MEROITIC CURSIVE NUMBER TWENTY THOUSAND;No;0;R;;;;20000;N;;;;; 109E6;MEROITIC CURSIVE NUMBER THIRTY THOUSAND;No;0;R;;;;30000;N;;;;; 109E7;MEROITIC CURSIVE NUMBER FORTY THOUSAND;No;0;R;;;;40000;N;;;;; 109E8;MEROITIC CURSIVE NUMBER FIFTY THOUSAND;No;0;R;;;;50000;N;;;;; 109E9;MEROITIC CURSIVE NUMBER SIXTY THOUSAND;No;0;R;;;;60000;N;;;;; 109EA;MEROITIC CURSIVE NUMBER SEVENTY THOUSAND;No;0;R;;;;70000;N;;;;; 109EB;MEROITIC CURSIVE NUMBER EIGHTY THOUSAND;No;0;R;;;;80000;N;;;;; 109EC;MEROITIC CURSIVE NUMBER NINETY THOUSAND;No;0;R;;;;90000;N;;;;; 109ED;MEROITIC CURSIVE NUMBER ONE HUNDRED THOUSAND;No;0;R;;;;100000;N;;;;; 109EE;MEROITIC CURSIVE NUMBER TWO HUNDRED THOUSAND;No;0;R;;;;200000;N;;;;; 109EF;MEROITIC CURSIVE NUMBER THREE HUNDRED THOUSAND;No;0;R;;;;300000;N;;;;; 109F0;MEROITIC CURSIVE NUMBER FOUR HUNDRED THOUSAND;No;0;R;;;;400000;N;;;;; 109F1;MEROITIC CURSIVE NUMBER FIVE HUNDRED THOUSAND;No;0;R;;;;500000;N;;;;; 109F2;MEROITIC CURSIVE NUMBER SIX HUNDRED THOUSAND;No;0;R;;;;600000;N;;;;; 109F3;MEROITIC CURSIVE NUMBER SEVEN HUNDRED THOUSAND;No;0;R;;;;700000;N;;;;; 109F4;MEROITIC CURSIVE NUMBER EIGHT HUNDRED THOUSAND;No;0;R;;;;800000;N;;;;; 109F5;MEROITIC CURSIVE NUMBER NINE HUNDRED THOUSAND;No;0;R;;;;900000;N;;;;; 109F6;MEROITIC CURSIVE FRACTION ONE TWELFTH;No;0;R;;;;1/12;N;;;;; 109F7;MEROITIC CURSIVE FRACTION TWO TWELFTHS;No;0;R;;;;2/12;N;;;;; 109F8;MEROITIC CURSIVE FRACTION THREE TWELFTHS;No;0;R;;;;3/12;N;;;;; 109F9;MEROITIC CURSIVE FRACTION FOUR TWELFTHS;No;0;R;;;;4/12;N;;;;; 109FA;MEROITIC CURSIVE FRACTION FIVE TWELFTHS;No;0;R;;;;5/12;N;;;;; 109FB;MEROITIC CURSIVE FRACTION SIX TWELFTHS;No;0;R;;;;6/12;N;;;;; 109FC;MEROITIC CURSIVE FRACTION SEVEN TWELFTHS;No;0;R;;;;7/12;N;;;;; 109FD;MEROITIC CURSIVE FRACTION EIGHT TWELFTHS;No;0;R;;;;8/12;N;;;;; 109FE;MEROITIC CURSIVE FRACTION NINE TWELFTHS;No;0;R;;;;9/12;N;;;;; 109FF;MEROITIC CURSIVE FRACTION TEN TWELFTHS;No;0;R;;;;10/12;N;;;;; 10A00;KHAROSHTHI LETTER A;Lo;0;R;;;;;N;;;;; 10A01;KHAROSHTHI VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; 10A02;KHAROSHTHI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 10A03;KHAROSHTHI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; 10A05;KHAROSHTHI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; 10A06;KHAROSHTHI VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; 10A0C;KHAROSHTHI VOWEL LENGTH MARK;Mn;0;NSM;;;;;N;;;;; 10A0D;KHAROSHTHI SIGN DOUBLE RING BELOW;Mn;220;NSM;;;;;N;;;;; 10A0E;KHAROSHTHI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; 10A0F;KHAROSHTHI SIGN VISARGA;Mn;230;NSM;;;;;N;;;;; 10A10;KHAROSHTHI LETTER KA;Lo;0;R;;;;;N;;;;; 10A11;KHAROSHTHI LETTER KHA;Lo;0;R;;;;;N;;;;; 10A12;KHAROSHTHI LETTER GA;Lo;0;R;;;;;N;;;;; 10A13;KHAROSHTHI LETTER GHA;Lo;0;R;;;;;N;;;;; 10A15;KHAROSHTHI LETTER CA;Lo;0;R;;;;;N;;;;; 10A16;KHAROSHTHI LETTER CHA;Lo;0;R;;;;;N;;;;; 10A17;KHAROSHTHI LETTER JA;Lo;0;R;;;;;N;;;;; 10A19;KHAROSHTHI LETTER NYA;Lo;0;R;;;;;N;;;;; 10A1A;KHAROSHTHI LETTER TTA;Lo;0;R;;;;;N;;;;; 10A1B;KHAROSHTHI LETTER TTHA;Lo;0;R;;;;;N;;;;; 10A1C;KHAROSHTHI LETTER DDA;Lo;0;R;;;;;N;;;;; 10A1D;KHAROSHTHI LETTER DDHA;Lo;0;R;;;;;N;;;;; 10A1E;KHAROSHTHI LETTER NNA;Lo;0;R;;;;;N;;;;; 10A1F;KHAROSHTHI LETTER TA;Lo;0;R;;;;;N;;;;; 10A20;KHAROSHTHI LETTER THA;Lo;0;R;;;;;N;;;;; 10A21;KHAROSHTHI LETTER DA;Lo;0;R;;;;;N;;;;; 10A22;KHAROSHTHI LETTER DHA;Lo;0;R;;;;;N;;;;; 10A23;KHAROSHTHI LETTER NA;Lo;0;R;;;;;N;;;;; 10A24;KHAROSHTHI LETTER PA;Lo;0;R;;;;;N;;;;; 10A25;KHAROSHTHI LETTER PHA;Lo;0;R;;;;;N;;;;; 10A26;KHAROSHTHI LETTER BA;Lo;0;R;;;;;N;;;;; 10A27;KHAROSHTHI LETTER BHA;Lo;0;R;;;;;N;;;;; 10A28;KHAROSHTHI LETTER MA;Lo;0;R;;;;;N;;;;; 10A29;KHAROSHTHI LETTER YA;Lo;0;R;;;;;N;;;;; 10A2A;KHAROSHTHI LETTER RA;Lo;0;R;;;;;N;;;;; 10A2B;KHAROSHTHI LETTER LA;Lo;0;R;;;;;N;;;;; 10A2C;KHAROSHTHI LETTER VA;Lo;0;R;;;;;N;;;;; 10A2D;KHAROSHTHI LETTER SHA;Lo;0;R;;;;;N;;;;; 10A2E;KHAROSHTHI LETTER SSA;Lo;0;R;;;;;N;;;;; 10A2F;KHAROSHTHI LETTER SA;Lo;0;R;;;;;N;;;;; 10A30;KHAROSHTHI LETTER ZA;Lo;0;R;;;;;N;;;;; 10A31;KHAROSHTHI LETTER HA;Lo;0;R;;;;;N;;;;; 10A32;KHAROSHTHI LETTER KKA;Lo;0;R;;;;;N;;;;; 10A33;KHAROSHTHI LETTER TTTHA;Lo;0;R;;;;;N;;;;; 10A38;KHAROSHTHI SIGN BAR ABOVE;Mn;230;NSM;;;;;N;;;;; 10A39;KHAROSHTHI SIGN CAUDA;Mn;1;NSM;;;;;N;;;;; 10A3A;KHAROSHTHI SIGN DOT BELOW;Mn;220;NSM;;;;;N;;;;; 10A3F;KHAROSHTHI VIRAMA;Mn;9;NSM;;;;;N;;;;; 10A40;KHAROSHTHI DIGIT ONE;No;0;R;;;1;1;N;;;;; 10A41;KHAROSHTHI DIGIT TWO;No;0;R;;;2;2;N;;;;; 10A42;KHAROSHTHI DIGIT THREE;No;0;R;;;3;3;N;;;;; 10A43;KHAROSHTHI DIGIT FOUR;No;0;R;;;4;4;N;;;;; 10A44;KHAROSHTHI NUMBER TEN;No;0;R;;;;10;N;;;;; 10A45;KHAROSHTHI NUMBER TWENTY;No;0;R;;;;20;N;;;;; 10A46;KHAROSHTHI NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;; 10A47;KHAROSHTHI NUMBER ONE THOUSAND;No;0;R;;;;1000;N;;;;; 10A50;KHAROSHTHI PUNCTUATION DOT;Po;0;R;;;;;N;;;;; 10A51;KHAROSHTHI PUNCTUATION SMALL CIRCLE;Po;0;R;;;;;N;;;;; 10A52;KHAROSHTHI PUNCTUATION CIRCLE;Po;0;R;;;;;N;;;;; 10A53;KHAROSHTHI PUNCTUATION CRESCENT BAR;Po;0;R;;;;;N;;;;; 10A54;KHAROSHTHI PUNCTUATION MANGALAM;Po;0;R;;;;;N;;;;; 10A55;KHAROSHTHI PUNCTUATION LOTUS;Po;0;R;;;;;N;;;;; 10A56;KHAROSHTHI PUNCTUATION DANDA;Po;0;R;;;;;N;;;;; 10A57;KHAROSHTHI PUNCTUATION DOUBLE DANDA;Po;0;R;;;;;N;;;;; 10A58;KHAROSHTHI PUNCTUATION LINES;Po;0;R;;;;;N;;;;; 10A60;OLD SOUTH ARABIAN LETTER HE;Lo;0;R;;;;;N;;;;; 10A61;OLD SOUTH ARABIAN LETTER LAMEDH;Lo;0;R;;;;;N;;;;; 10A62;OLD SOUTH ARABIAN LETTER HETH;Lo;0;R;;;;;N;;;;; 10A63;OLD SOUTH ARABIAN LETTER MEM;Lo;0;R;;;;;N;;;;; 10A64;OLD SOUTH ARABIAN LETTER QOPH;Lo;0;R;;;;;N;;;;; 10A65;OLD SOUTH ARABIAN LETTER WAW;Lo;0;R;;;;;N;;;;; 10A66;OLD SOUTH ARABIAN LETTER SHIN;Lo;0;R;;;;;N;;;;; 10A67;OLD SOUTH ARABIAN LETTER RESH;Lo;0;R;;;;;N;;;;; 10A68;OLD SOUTH ARABIAN LETTER BETH;Lo;0;R;;;;;N;;;;; 10A69;OLD SOUTH ARABIAN LETTER TAW;Lo;0;R;;;;;N;;;;; 10A6A;OLD SOUTH ARABIAN LETTER SAT;Lo;0;R;;;;;N;;;;; 10A6B;OLD SOUTH ARABIAN LETTER KAPH;Lo;0;R;;;;;N;;;;; 10A6C;OLD SOUTH ARABIAN LETTER NUN;Lo;0;R;;;;;N;;;;; 10A6D;OLD SOUTH ARABIAN LETTER KHETH;Lo;0;R;;;;;N;;;;; 10A6E;OLD SOUTH ARABIAN LETTER SADHE;Lo;0;R;;;;;N;;;;; 10A6F;OLD SOUTH ARABIAN LETTER SAMEKH;Lo;0;R;;;;;N;;;;; 10A70;OLD SOUTH ARABIAN LETTER FE;Lo;0;R;;;;;N;;;;; 10A71;OLD SOUTH ARABIAN LETTER ALEF;Lo;0;R;;;;;N;;;;; 10A72;OLD SOUTH ARABIAN LETTER AYN;Lo;0;R;;;;;N;;;;; 10A73;OLD SOUTH ARABIAN LETTER DHADHE;Lo;0;R;;;;;N;;;;; 10A74;OLD SOUTH ARABIAN LETTER GIMEL;Lo;0;R;;;;;N;;;;; 10A75;OLD SOUTH ARABIAN LETTER DALETH;Lo;0;R;;;;;N;;;;; 10A76;OLD SOUTH ARABIAN LETTER GHAYN;Lo;0;R;;;;;N;;;;; 10A77;OLD SOUTH ARABIAN LETTER TETH;Lo;0;R;;;;;N;;;;; 10A78;OLD SOUTH ARABIAN LETTER ZAYN;Lo;0;R;;;;;N;;;;; 10A79;OLD SOUTH ARABIAN LETTER DHALETH;Lo;0;R;;;;;N;;;;; 10A7A;OLD SOUTH ARABIAN LETTER YODH;Lo;0;R;;;;;N;;;;; 10A7B;OLD SOUTH ARABIAN LETTER THAW;Lo;0;R;;;;;N;;;;; 10A7C;OLD SOUTH ARABIAN LETTER THETH;Lo;0;R;;;;;N;;;;; 10A7D;OLD SOUTH ARABIAN NUMBER ONE;No;0;R;;;;1;N;;;;; 10A7E;OLD SOUTH ARABIAN NUMBER FIFTY;No;0;R;;;;50;N;;;;; 10A7F;OLD SOUTH ARABIAN NUMERIC INDICATOR;Po;0;R;;;;;N;;;;; 10A80;OLD NORTH ARABIAN LETTER HEH;Lo;0;R;;;;;N;;;;; 10A81;OLD NORTH ARABIAN LETTER LAM;Lo;0;R;;;;;N;;;;; 10A82;OLD NORTH ARABIAN LETTER HAH;Lo;0;R;;;;;N;;;;; 10A83;OLD NORTH ARABIAN LETTER MEEM;Lo;0;R;;;;;N;;;;; 10A84;OLD NORTH ARABIAN LETTER QAF;Lo;0;R;;;;;N;;;;; 10A85;OLD NORTH ARABIAN LETTER WAW;Lo;0;R;;;;;N;;;;; 10A86;OLD NORTH ARABIAN LETTER ES-2;Lo;0;R;;;;;N;;;;; 10A87;OLD NORTH ARABIAN LETTER REH;Lo;0;R;;;;;N;;;;; 10A88;OLD NORTH ARABIAN LETTER BEH;Lo;0;R;;;;;N;;;;; 10A89;OLD NORTH ARABIAN LETTER TEH;Lo;0;R;;;;;N;;;;; 10A8A;OLD NORTH ARABIAN LETTER ES-1;Lo;0;R;;;;;N;;;;; 10A8B;OLD NORTH ARABIAN LETTER KAF;Lo;0;R;;;;;N;;;;; 10A8C;OLD NORTH ARABIAN LETTER NOON;Lo;0;R;;;;;N;;;;; 10A8D;OLD NORTH ARABIAN LETTER KHAH;Lo;0;R;;;;;N;;;;; 10A8E;OLD NORTH ARABIAN LETTER SAD;Lo;0;R;;;;;N;;;;; 10A8F;OLD NORTH ARABIAN LETTER ES-3;Lo;0;R;;;;;N;;;;; 10A90;OLD NORTH ARABIAN LETTER FEH;Lo;0;R;;;;;N;;;;; 10A91;OLD NORTH ARABIAN LETTER ALEF;Lo;0;R;;;;;N;;;;; 10A92;OLD NORTH ARABIAN LETTER AIN;Lo;0;R;;;;;N;;;;; 10A93;OLD NORTH ARABIAN LETTER DAD;Lo;0;R;;;;;N;;;;; 10A94;OLD NORTH ARABIAN LETTER GEEM;Lo;0;R;;;;;N;;;;; 10A95;OLD NORTH ARABIAN LETTER DAL;Lo;0;R;;;;;N;;;;; 10A96;OLD NORTH ARABIAN LETTER GHAIN;Lo;0;R;;;;;N;;;;; 10A97;OLD NORTH ARABIAN LETTER TAH;Lo;0;R;;;;;N;;;;; 10A98;OLD NORTH ARABIAN LETTER ZAIN;Lo;0;R;;;;;N;;;;; 10A99;OLD NORTH ARABIAN LETTER THAL;Lo;0;R;;;;;N;;;;; 10A9A;OLD NORTH ARABIAN LETTER YEH;Lo;0;R;;;;;N;;;;; 10A9B;OLD NORTH ARABIAN LETTER THEH;Lo;0;R;;;;;N;;;;; 10A9C;OLD NORTH ARABIAN LETTER ZAH;Lo;0;R;;;;;N;;;;; 10A9D;OLD NORTH ARABIAN NUMBER ONE;No;0;R;;;;1;N;;;;; 10A9E;OLD NORTH ARABIAN NUMBER TEN;No;0;R;;;;10;N;;;;; 10A9F;OLD NORTH ARABIAN NUMBER TWENTY;No;0;R;;;;20;N;;;;; 10AC0;MANICHAEAN LETTER ALEPH;Lo;0;R;;;;;N;;;;; 10AC1;MANICHAEAN LETTER BETH;Lo;0;R;;;;;N;;;;; 10AC2;MANICHAEAN LETTER BHETH;Lo;0;R;;;;;N;;;;; 10AC3;MANICHAEAN LETTER GIMEL;Lo;0;R;;;;;N;;;;; 10AC4;MANICHAEAN LETTER GHIMEL;Lo;0;R;;;;;N;;;;; 10AC5;MANICHAEAN LETTER DALETH;Lo;0;R;;;;;N;;;;; 10AC6;MANICHAEAN LETTER HE;Lo;0;R;;;;;N;;;;; 10AC7;MANICHAEAN LETTER WAW;Lo;0;R;;;;;N;;;;; 10AC8;MANICHAEAN SIGN UD;So;0;R;;;;;N;;;;; 10AC9;MANICHAEAN LETTER ZAYIN;Lo;0;R;;;;;N;;;;; 10ACA;MANICHAEAN LETTER ZHAYIN;Lo;0;R;;;;;N;;;;; 10ACB;MANICHAEAN LETTER JAYIN;Lo;0;R;;;;;N;;;;; 10ACC;MANICHAEAN LETTER JHAYIN;Lo;0;R;;;;;N;;;;; 10ACD;MANICHAEAN LETTER HETH;Lo;0;R;;;;;N;;;;; 10ACE;MANICHAEAN LETTER TETH;Lo;0;R;;;;;N;;;;; 10ACF;MANICHAEAN LETTER YODH;Lo;0;R;;;;;N;;;;; 10AD0;MANICHAEAN LETTER KAPH;Lo;0;R;;;;;N;;;;; 10AD1;MANICHAEAN LETTER XAPH;Lo;0;R;;;;;N;;;;; 10AD2;MANICHAEAN LETTER KHAPH;Lo;0;R;;;;;N;;;;; 10AD3;MANICHAEAN LETTER LAMEDH;Lo;0;R;;;;;N;;;;; 10AD4;MANICHAEAN LETTER DHAMEDH;Lo;0;R;;;;;N;;;;; 10AD5;MANICHAEAN LETTER THAMEDH;Lo;0;R;;;;;N;;;;; 10AD6;MANICHAEAN LETTER MEM;Lo;0;R;;;;;N;;;;; 10AD7;MANICHAEAN LETTER NUN;Lo;0;R;;;;;N;;;;; 10AD8;MANICHAEAN LETTER SAMEKH;Lo;0;R;;;;;N;;;;; 10AD9;MANICHAEAN LETTER AYIN;Lo;0;R;;;;;N;;;;; 10ADA;MANICHAEAN LETTER AAYIN;Lo;0;R;;;;;N;;;;; 10ADB;MANICHAEAN LETTER PE;Lo;0;R;;;;;N;;;;; 10ADC;MANICHAEAN LETTER FE;Lo;0;R;;;;;N;;;;; 10ADD;MANICHAEAN LETTER SADHE;Lo;0;R;;;;;N;;;;; 10ADE;MANICHAEAN LETTER QOPH;Lo;0;R;;;;;N;;;;; 10ADF;MANICHAEAN LETTER XOPH;Lo;0;R;;;;;N;;;;; 10AE0;MANICHAEAN LETTER QHOPH;Lo;0;R;;;;;N;;;;; 10AE1;MANICHAEAN LETTER RESH;Lo;0;R;;;;;N;;;;; 10AE2;MANICHAEAN LETTER SHIN;Lo;0;R;;;;;N;;;;; 10AE3;MANICHAEAN LETTER SSHIN;Lo;0;R;;;;;N;;;;; 10AE4;MANICHAEAN LETTER TAW;Lo;0;R;;;;;N;;;;; 10AE5;MANICHAEAN ABBREVIATION MARK ABOVE;Mn;230;NSM;;;;;N;;;;; 10AE6;MANICHAEAN ABBREVIATION MARK BELOW;Mn;220;NSM;;;;;N;;;;; 10AEB;MANICHAEAN NUMBER ONE;No;0;R;;;;1;N;;;;; 10AEC;MANICHAEAN NUMBER FIVE;No;0;R;;;;5;N;;;;; 10AED;MANICHAEAN NUMBER TEN;No;0;R;;;;10;N;;;;; 10AEE;MANICHAEAN NUMBER TWENTY;No;0;R;;;;20;N;;;;; 10AEF;MANICHAEAN NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;; 10AF0;MANICHAEAN PUNCTUATION STAR;Po;0;R;;;;;N;;;;; 10AF1;MANICHAEAN PUNCTUATION FLEURON;Po;0;R;;;;;N;;;;; 10AF2;MANICHAEAN PUNCTUATION DOUBLE DOT WITHIN DOT;Po;0;R;;;;;N;;;;; 10AF3;MANICHAEAN PUNCTUATION DOT WITHIN DOT;Po;0;R;;;;;N;;;;; 10AF4;MANICHAEAN PUNCTUATION DOT;Po;0;R;;;;;N;;;;; 10AF5;MANICHAEAN PUNCTUATION TWO DOTS;Po;0;R;;;;;N;;;;; 10AF6;MANICHAEAN PUNCTUATION LINE FILLER;Po;0;R;;;;;N;;;;; 10B00;AVESTAN LETTER A;Lo;0;R;;;;;N;;;;; 10B01;AVESTAN LETTER AA;Lo;0;R;;;;;N;;;;; 10B02;AVESTAN LETTER AO;Lo;0;R;;;;;N;;;;; 10B03;AVESTAN LETTER AAO;Lo;0;R;;;;;N;;;;; 10B04;AVESTAN LETTER AN;Lo;0;R;;;;;N;;;;; 10B05;AVESTAN LETTER AAN;Lo;0;R;;;;;N;;;;; 10B06;AVESTAN LETTER AE;Lo;0;R;;;;;N;;;;; 10B07;AVESTAN LETTER AEE;Lo;0;R;;;;;N;;;;; 10B08;AVESTAN LETTER E;Lo;0;R;;;;;N;;;;; 10B09;AVESTAN LETTER EE;Lo;0;R;;;;;N;;;;; 10B0A;AVESTAN LETTER O;Lo;0;R;;;;;N;;;;; 10B0B;AVESTAN LETTER OO;Lo;0;R;;;;;N;;;;; 10B0C;AVESTAN LETTER I;Lo;0;R;;;;;N;;;;; 10B0D;AVESTAN LETTER II;Lo;0;R;;;;;N;;;;; 10B0E;AVESTAN LETTER U;Lo;0;R;;;;;N;;;;; 10B0F;AVESTAN LETTER UU;Lo;0;R;;;;;N;;;;; 10B10;AVESTAN LETTER KE;Lo;0;R;;;;;N;;;;; 10B11;AVESTAN LETTER XE;Lo;0;R;;;;;N;;;;; 10B12;AVESTAN LETTER XYE;Lo;0;R;;;;;N;;;;; 10B13;AVESTAN LETTER XVE;Lo;0;R;;;;;N;;;;; 10B14;AVESTAN LETTER GE;Lo;0;R;;;;;N;;;;; 10B15;AVESTAN LETTER GGE;Lo;0;R;;;;;N;;;;; 10B16;AVESTAN LETTER GHE;Lo;0;R;;;;;N;;;;; 10B17;AVESTAN LETTER CE;Lo;0;R;;;;;N;;;;; 10B18;AVESTAN LETTER JE;Lo;0;R;;;;;N;;;;; 10B19;AVESTAN LETTER TE;Lo;0;R;;;;;N;;;;; 10B1A;AVESTAN LETTER THE;Lo;0;R;;;;;N;;;;; 10B1B;AVESTAN LETTER DE;Lo;0;R;;;;;N;;;;; 10B1C;AVESTAN LETTER DHE;Lo;0;R;;;;;N;;;;; 10B1D;AVESTAN LETTER TTE;Lo;0;R;;;;;N;;;;; 10B1E;AVESTAN LETTER PE;Lo;0;R;;;;;N;;;;; 10B1F;AVESTAN LETTER FE;Lo;0;R;;;;;N;;;;; 10B20;AVESTAN LETTER BE;Lo;0;R;;;;;N;;;;; 10B21;AVESTAN LETTER BHE;Lo;0;R;;;;;N;;;;; 10B22;AVESTAN LETTER NGE;Lo;0;R;;;;;N;;;;; 10B23;AVESTAN LETTER NGYE;Lo;0;R;;;;;N;;;;; 10B24;AVESTAN LETTER NGVE;Lo;0;R;;;;;N;;;;; 10B25;AVESTAN LETTER NE;Lo;0;R;;;;;N;;;;; 10B26;AVESTAN LETTER NYE;Lo;0;R;;;;;N;;;;; 10B27;AVESTAN LETTER NNE;Lo;0;R;;;;;N;;;;; 10B28;AVESTAN LETTER ME;Lo;0;R;;;;;N;;;;; 10B29;AVESTAN LETTER HME;Lo;0;R;;;;;N;;;;; 10B2A;AVESTAN LETTER YYE;Lo;0;R;;;;;N;;;;; 10B2B;AVESTAN LETTER YE;Lo;0;R;;;;;N;;;;; 10B2C;AVESTAN LETTER VE;Lo;0;R;;;;;N;;;;; 10B2D;AVESTAN LETTER RE;Lo;0;R;;;;;N;;;;; 10B2E;AVESTAN LETTER LE;Lo;0;R;;;;;N;;;;; 10B2F;AVESTAN LETTER SE;Lo;0;R;;;;;N;;;;; 10B30;AVESTAN LETTER ZE;Lo;0;R;;;;;N;;;;; 10B31;AVESTAN LETTER SHE;Lo;0;R;;;;;N;;;;; 10B32;AVESTAN LETTER ZHE;Lo;0;R;;;;;N;;;;; 10B33;AVESTAN LETTER SHYE;Lo;0;R;;;;;N;;;;; 10B34;AVESTAN LETTER SSHE;Lo;0;R;;;;;N;;;;; 10B35;AVESTAN LETTER HE;Lo;0;R;;;;;N;;;;; 10B39;AVESTAN ABBREVIATION MARK;Po;0;ON;;;;;N;;;;; 10B3A;TINY TWO DOTS OVER ONE DOT PUNCTUATION;Po;0;ON;;;;;N;;;;; 10B3B;SMALL TWO DOTS OVER ONE DOT PUNCTUATION;Po;0;ON;;;;;N;;;;; 10B3C;LARGE TWO DOTS OVER ONE DOT PUNCTUATION;Po;0;ON;;;;;N;;;;; 10B3D;LARGE ONE DOT OVER TWO DOTS PUNCTUATION;Po;0;ON;;;;;N;;;;; 10B3E;LARGE TWO RINGS OVER ONE RING PUNCTUATION;Po;0;ON;;;;;N;;;;; 10B3F;LARGE ONE RING OVER TWO RINGS PUNCTUATION;Po;0;ON;;;;;N;;;;; 10B40;INSCRIPTIONAL PARTHIAN LETTER ALEPH;Lo;0;R;;;;;N;;;;; 10B41;INSCRIPTIONAL PARTHIAN LETTER BETH;Lo;0;R;;;;;N;;;;; 10B42;INSCRIPTIONAL PARTHIAN LETTER GIMEL;Lo;0;R;;;;;N;;;;; 10B43;INSCRIPTIONAL PARTHIAN LETTER DALETH;Lo;0;R;;;;;N;;;;; 10B44;INSCRIPTIONAL PARTHIAN LETTER HE;Lo;0;R;;;;;N;;;;; 10B45;INSCRIPTIONAL PARTHIAN LETTER WAW;Lo;0;R;;;;;N;;;;; 10B46;INSCRIPTIONAL PARTHIAN LETTER ZAYIN;Lo;0;R;;;;;N;;;;; 10B47;INSCRIPTIONAL PARTHIAN LETTER HETH;Lo;0;R;;;;;N;;;;; 10B48;INSCRIPTIONAL PARTHIAN LETTER TETH;Lo;0;R;;;;;N;;;;; 10B49;INSCRIPTIONAL PARTHIAN LETTER YODH;Lo;0;R;;;;;N;;;;; 10B4A;INSCRIPTIONAL PARTHIAN LETTER KAPH;Lo;0;R;;;;;N;;;;; 10B4B;INSCRIPTIONAL PARTHIAN LETTER LAMEDH;Lo;0;R;;;;;N;;;;; 10B4C;INSCRIPTIONAL PARTHIAN LETTER MEM;Lo;0;R;;;;;N;;;;; 10B4D;INSCRIPTIONAL PARTHIAN LETTER NUN;Lo;0;R;;;;;N;;;;; 10B4E;INSCRIPTIONAL PARTHIAN LETTER SAMEKH;Lo;0;R;;;;;N;;;;; 10B4F;INSCRIPTIONAL PARTHIAN LETTER AYIN;Lo;0;R;;;;;N;;;;; 10B50;INSCRIPTIONAL PARTHIAN LETTER PE;Lo;0;R;;;;;N;;;;; 10B51;INSCRIPTIONAL PARTHIAN LETTER SADHE;Lo;0;R;;;;;N;;;;; 10B52;INSCRIPTIONAL PARTHIAN LETTER QOPH;Lo;0;R;;;;;N;;;;; 10B53;INSCRIPTIONAL PARTHIAN LETTER RESH;Lo;0;R;;;;;N;;;;; 10B54;INSCRIPTIONAL PARTHIAN LETTER SHIN;Lo;0;R;;;;;N;;;;; 10B55;INSCRIPTIONAL PARTHIAN LETTER TAW;Lo;0;R;;;;;N;;;;; 10B58;INSCRIPTIONAL PARTHIAN NUMBER ONE;No;0;R;;;;1;N;;;;; 10B59;INSCRIPTIONAL PARTHIAN NUMBER TWO;No;0;R;;;;2;N;;;;; 10B5A;INSCRIPTIONAL PARTHIAN NUMBER THREE;No;0;R;;;;3;N;;;;; 10B5B;INSCRIPTIONAL PARTHIAN NUMBER FOUR;No;0;R;;;;4;N;;;;; 10B5C;INSCRIPTIONAL PARTHIAN NUMBER TEN;No;0;R;;;;10;N;;;;; 10B5D;INSCRIPTIONAL PARTHIAN NUMBER TWENTY;No;0;R;;;;20;N;;;;; 10B5E;INSCRIPTIONAL PARTHIAN NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;; 10B5F;INSCRIPTIONAL PARTHIAN NUMBER ONE THOUSAND;No;0;R;;;;1000;N;;;;; 10B60;INSCRIPTIONAL PAHLAVI LETTER ALEPH;Lo;0;R;;;;;N;;;;; 10B61;INSCRIPTIONAL PAHLAVI LETTER BETH;Lo;0;R;;;;;N;;;;; 10B62;INSCRIPTIONAL PAHLAVI LETTER GIMEL;Lo;0;R;;;;;N;;;;; 10B63;INSCRIPTIONAL PAHLAVI LETTER DALETH;Lo;0;R;;;;;N;;;;; 10B64;INSCRIPTIONAL PAHLAVI LETTER HE;Lo;0;R;;;;;N;;;;; 10B65;INSCRIPTIONAL PAHLAVI LETTER WAW-AYIN-RESH;Lo;0;R;;;;;N;;;;; 10B66;INSCRIPTIONAL PAHLAVI LETTER ZAYIN;Lo;0;R;;;;;N;;;;; 10B67;INSCRIPTIONAL PAHLAVI LETTER HETH;Lo;0;R;;;;;N;;;;; 10B68;INSCRIPTIONAL PAHLAVI LETTER TETH;Lo;0;R;;;;;N;;;;; 10B69;INSCRIPTIONAL PAHLAVI LETTER YODH;Lo;0;R;;;;;N;;;;; 10B6A;INSCRIPTIONAL PAHLAVI LETTER KAPH;Lo;0;R;;;;;N;;;;; 10B6B;INSCRIPTIONAL PAHLAVI LETTER LAMEDH;Lo;0;R;;;;;N;;;;; 10B6C;INSCRIPTIONAL PAHLAVI LETTER MEM-QOPH;Lo;0;R;;;;;N;;;;; 10B6D;INSCRIPTIONAL PAHLAVI LETTER NUN;Lo;0;R;;;;;N;;;;; 10B6E;INSCRIPTIONAL PAHLAVI LETTER SAMEKH;Lo;0;R;;;;;N;;;;; 10B6F;INSCRIPTIONAL PAHLAVI LETTER PE;Lo;0;R;;;;;N;;;;; 10B70;INSCRIPTIONAL PAHLAVI LETTER SADHE;Lo;0;R;;;;;N;;;;; 10B71;INSCRIPTIONAL PAHLAVI LETTER SHIN;Lo;0;R;;;;;N;;;;; 10B72;INSCRIPTIONAL PAHLAVI LETTER TAW;Lo;0;R;;;;;N;;;;; 10B78;INSCRIPTIONAL PAHLAVI NUMBER ONE;No;0;R;;;;1;N;;;;; 10B79;INSCRIPTIONAL PAHLAVI NUMBER TWO;No;0;R;;;;2;N;;;;; 10B7A;INSCRIPTIONAL PAHLAVI NUMBER THREE;No;0;R;;;;3;N;;;;; 10B7B;INSCRIPTIONAL PAHLAVI NUMBER FOUR;No;0;R;;;;4;N;;;;; 10B7C;INSCRIPTIONAL PAHLAVI NUMBER TEN;No;0;R;;;;10;N;;;;; 10B7D;INSCRIPTIONAL PAHLAVI NUMBER TWENTY;No;0;R;;;;20;N;;;;; 10B7E;INSCRIPTIONAL PAHLAVI NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;; 10B7F;INSCRIPTIONAL PAHLAVI NUMBER ONE THOUSAND;No;0;R;;;;1000;N;;;;; 10B80;PSALTER PAHLAVI LETTER ALEPH;Lo;0;R;;;;;N;;;;; 10B81;PSALTER PAHLAVI LETTER BETH;Lo;0;R;;;;;N;;;;; 10B82;PSALTER PAHLAVI LETTER GIMEL;Lo;0;R;;;;;N;;;;; 10B83;PSALTER PAHLAVI LETTER DALETH;Lo;0;R;;;;;N;;;;; 10B84;PSALTER PAHLAVI LETTER HE;Lo;0;R;;;;;N;;;;; 10B85;PSALTER PAHLAVI LETTER WAW-AYIN-RESH;Lo;0;R;;;;;N;;;;; 10B86;PSALTER PAHLAVI LETTER ZAYIN;Lo;0;R;;;;;N;;;;; 10B87;PSALTER PAHLAVI LETTER HETH;Lo;0;R;;;;;N;;;;; 10B88;PSALTER PAHLAVI LETTER YODH;Lo;0;R;;;;;N;;;;; 10B89;PSALTER PAHLAVI LETTER KAPH;Lo;0;R;;;;;N;;;;; 10B8A;PSALTER PAHLAVI LETTER LAMEDH;Lo;0;R;;;;;N;;;;; 10B8B;PSALTER PAHLAVI LETTER MEM-QOPH;Lo;0;R;;;;;N;;;;; 10B8C;PSALTER PAHLAVI LETTER NUN;Lo;0;R;;;;;N;;;;; 10B8D;PSALTER PAHLAVI LETTER SAMEKH;Lo;0;R;;;;;N;;;;; 10B8E;PSALTER PAHLAVI LETTER PE;Lo;0;R;;;;;N;;;;; 10B8F;PSALTER PAHLAVI LETTER SADHE;Lo;0;R;;;;;N;;;;; 10B90;PSALTER PAHLAVI LETTER SHIN;Lo;0;R;;;;;N;;;;; 10B91;PSALTER PAHLAVI LETTER TAW;Lo;0;R;;;;;N;;;;; 10B99;PSALTER PAHLAVI SECTION MARK;Po;0;R;;;;;N;;;;; 10B9A;PSALTER PAHLAVI TURNED SECTION MARK;Po;0;R;;;;;N;;;;; 10B9B;PSALTER PAHLAVI FOUR DOTS WITH CROSS;Po;0;R;;;;;N;;;;; 10B9C;PSALTER PAHLAVI FOUR DOTS WITH DOT;Po;0;R;;;;;N;;;;; 10BA9;PSALTER PAHLAVI NUMBER ONE;No;0;R;;;;1;N;;;;; 10BAA;PSALTER PAHLAVI NUMBER TWO;No;0;R;;;;2;N;;;;; 10BAB;PSALTER PAHLAVI NUMBER THREE;No;0;R;;;;3;N;;;;; 10BAC;PSALTER PAHLAVI NUMBER FOUR;No;0;R;;;;4;N;;;;; 10BAD;PSALTER PAHLAVI NUMBER TEN;No;0;R;;;;10;N;;;;; 10BAE;PSALTER PAHLAVI NUMBER TWENTY;No;0;R;;;;20;N;;;;; 10BAF;PSALTER PAHLAVI NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;; 10C00;OLD TURKIC LETTER ORKHON A;Lo;0;R;;;;;N;;;;; 10C01;OLD TURKIC LETTER YENISEI A;Lo;0;R;;;;;N;;;;; 10C02;OLD TURKIC LETTER YENISEI AE;Lo;0;R;;;;;N;;;;; 10C03;OLD TURKIC LETTER ORKHON I;Lo;0;R;;;;;N;;;;; 10C04;OLD TURKIC LETTER YENISEI I;Lo;0;R;;;;;N;;;;; 10C05;OLD TURKIC LETTER YENISEI E;Lo;0;R;;;;;N;;;;; 10C06;OLD TURKIC LETTER ORKHON O;Lo;0;R;;;;;N;;;;; 10C07;OLD TURKIC LETTER ORKHON OE;Lo;0;R;;;;;N;;;;; 10C08;OLD TURKIC LETTER YENISEI OE;Lo;0;R;;;;;N;;;;; 10C09;OLD TURKIC LETTER ORKHON AB;Lo;0;R;;;;;N;;;;; 10C0A;OLD TURKIC LETTER YENISEI AB;Lo;0;R;;;;;N;;;;; 10C0B;OLD TURKIC LETTER ORKHON AEB;Lo;0;R;;;;;N;;;;; 10C0C;OLD TURKIC LETTER YENISEI AEB;Lo;0;R;;;;;N;;;;; 10C0D;OLD TURKIC LETTER ORKHON AG;Lo;0;R;;;;;N;;;;; 10C0E;OLD TURKIC LETTER YENISEI AG;Lo;0;R;;;;;N;;;;; 10C0F;OLD TURKIC LETTER ORKHON AEG;Lo;0;R;;;;;N;;;;; 10C10;OLD TURKIC LETTER YENISEI AEG;Lo;0;R;;;;;N;;;;; 10C11;OLD TURKIC LETTER ORKHON AD;Lo;0;R;;;;;N;;;;; 10C12;OLD TURKIC LETTER YENISEI AD;Lo;0;R;;;;;N;;;;; 10C13;OLD TURKIC LETTER ORKHON AED;Lo;0;R;;;;;N;;;;; 10C14;OLD TURKIC LETTER ORKHON EZ;Lo;0;R;;;;;N;;;;; 10C15;OLD TURKIC LETTER YENISEI EZ;Lo;0;R;;;;;N;;;;; 10C16;OLD TURKIC LETTER ORKHON AY;Lo;0;R;;;;;N;;;;; 10C17;OLD TURKIC LETTER YENISEI AY;Lo;0;R;;;;;N;;;;; 10C18;OLD TURKIC LETTER ORKHON AEY;Lo;0;R;;;;;N;;;;; 10C19;OLD TURKIC LETTER YENISEI AEY;Lo;0;R;;;;;N;;;;; 10C1A;OLD TURKIC LETTER ORKHON AEK;Lo;0;R;;;;;N;;;;; 10C1B;OLD TURKIC LETTER YENISEI AEK;Lo;0;R;;;;;N;;;;; 10C1C;OLD TURKIC LETTER ORKHON OEK;Lo;0;R;;;;;N;;;;; 10C1D;OLD TURKIC LETTER YENISEI OEK;Lo;0;R;;;;;N;;;;; 10C1E;OLD TURKIC LETTER ORKHON AL;Lo;0;R;;;;;N;;;;; 10C1F;OLD TURKIC LETTER YENISEI AL;Lo;0;R;;;;;N;;;;; 10C20;OLD TURKIC LETTER ORKHON AEL;Lo;0;R;;;;;N;;;;; 10C21;OLD TURKIC LETTER ORKHON ELT;Lo;0;R;;;;;N;;;;; 10C22;OLD TURKIC LETTER ORKHON EM;Lo;0;R;;;;;N;;;;; 10C23;OLD TURKIC LETTER ORKHON AN;Lo;0;R;;;;;N;;;;; 10C24;OLD TURKIC LETTER ORKHON AEN;Lo;0;R;;;;;N;;;;; 10C25;OLD TURKIC LETTER YENISEI AEN;Lo;0;R;;;;;N;;;;; 10C26;OLD TURKIC LETTER ORKHON ENT;Lo;0;R;;;;;N;;;;; 10C27;OLD TURKIC LETTER YENISEI ENT;Lo;0;R;;;;;N;;;;; 10C28;OLD TURKIC LETTER ORKHON ENC;Lo;0;R;;;;;N;;;;; 10C29;OLD TURKIC LETTER YENISEI ENC;Lo;0;R;;;;;N;;;;; 10C2A;OLD TURKIC LETTER ORKHON ENY;Lo;0;R;;;;;N;;;;; 10C2B;OLD TURKIC LETTER YENISEI ENY;Lo;0;R;;;;;N;;;;; 10C2C;OLD TURKIC LETTER YENISEI ANG;Lo;0;R;;;;;N;;;;; 10C2D;OLD TURKIC LETTER ORKHON ENG;Lo;0;R;;;;;N;;;;; 10C2E;OLD TURKIC LETTER YENISEI AENG;Lo;0;R;;;;;N;;;;; 10C2F;OLD TURKIC LETTER ORKHON EP;Lo;0;R;;;;;N;;;;; 10C30;OLD TURKIC LETTER ORKHON OP;Lo;0;R;;;;;N;;;;; 10C31;OLD TURKIC LETTER ORKHON IC;Lo;0;R;;;;;N;;;;; 10C32;OLD TURKIC LETTER ORKHON EC;Lo;0;R;;;;;N;;;;; 10C33;OLD TURKIC LETTER YENISEI EC;Lo;0;R;;;;;N;;;;; 10C34;OLD TURKIC LETTER ORKHON AQ;Lo;0;R;;;;;N;;;;; 10C35;OLD TURKIC LETTER YENISEI AQ;Lo;0;R;;;;;N;;;;; 10C36;OLD TURKIC LETTER ORKHON IQ;Lo;0;R;;;;;N;;;;; 10C37;OLD TURKIC LETTER YENISEI IQ;Lo;0;R;;;;;N;;;;; 10C38;OLD TURKIC LETTER ORKHON OQ;Lo;0;R;;;;;N;;;;; 10C39;OLD TURKIC LETTER YENISEI OQ;Lo;0;R;;;;;N;;;;; 10C3A;OLD TURKIC LETTER ORKHON AR;Lo;0;R;;;;;N;;;;; 10C3B;OLD TURKIC LETTER YENISEI AR;Lo;0;R;;;;;N;;;;; 10C3C;OLD TURKIC LETTER ORKHON AER;Lo;0;R;;;;;N;;;;; 10C3D;OLD TURKIC LETTER ORKHON AS;Lo;0;R;;;;;N;;;;; 10C3E;OLD TURKIC LETTER ORKHON AES;Lo;0;R;;;;;N;;;;; 10C3F;OLD TURKIC LETTER ORKHON ASH;Lo;0;R;;;;;N;;;;; 10C40;OLD TURKIC LETTER YENISEI ASH;Lo;0;R;;;;;N;;;;; 10C41;OLD TURKIC LETTER ORKHON ESH;Lo;0;R;;;;;N;;;;; 10C42;OLD TURKIC LETTER YENISEI ESH;Lo;0;R;;;;;N;;;;; 10C43;OLD TURKIC LETTER ORKHON AT;Lo;0;R;;;;;N;;;;; 10C44;OLD TURKIC LETTER YENISEI AT;Lo;0;R;;;;;N;;;;; 10C45;OLD TURKIC LETTER ORKHON AET;Lo;0;R;;;;;N;;;;; 10C46;OLD TURKIC LETTER YENISEI AET;Lo;0;R;;;;;N;;;;; 10C47;OLD TURKIC LETTER ORKHON OT;Lo;0;R;;;;;N;;;;; 10C48;OLD TURKIC LETTER ORKHON BASH;Lo;0;R;;;;;N;;;;; 10C80;OLD HUNGARIAN CAPITAL LETTER A;Lu;0;R;;;;;N;;;;10CC0; 10C81;OLD HUNGARIAN CAPITAL LETTER AA;Lu;0;R;;;;;N;;;;10CC1; 10C82;OLD HUNGARIAN CAPITAL LETTER EB;Lu;0;R;;;;;N;;;;10CC2; 10C83;OLD HUNGARIAN CAPITAL LETTER AMB;Lu;0;R;;;;;N;;;;10CC3; 10C84;OLD HUNGARIAN CAPITAL LETTER EC;Lu;0;R;;;;;N;;;;10CC4; 10C85;OLD HUNGARIAN CAPITAL LETTER ENC;Lu;0;R;;;;;N;;;;10CC5; 10C86;OLD HUNGARIAN CAPITAL LETTER ECS;Lu;0;R;;;;;N;;;;10CC6; 10C87;OLD HUNGARIAN CAPITAL LETTER ED;Lu;0;R;;;;;N;;;;10CC7; 10C88;OLD HUNGARIAN CAPITAL LETTER AND;Lu;0;R;;;;;N;;;;10CC8; 10C89;OLD HUNGARIAN CAPITAL LETTER E;Lu;0;R;;;;;N;;;;10CC9; 10C8A;OLD HUNGARIAN CAPITAL LETTER CLOSE E;Lu;0;R;;;;;N;;;;10CCA; 10C8B;OLD HUNGARIAN CAPITAL LETTER EE;Lu;0;R;;;;;N;;;;10CCB; 10C8C;OLD HUNGARIAN CAPITAL LETTER EF;Lu;0;R;;;;;N;;;;10CCC; 10C8D;OLD HUNGARIAN CAPITAL LETTER EG;Lu;0;R;;;;;N;;;;10CCD; 10C8E;OLD HUNGARIAN CAPITAL LETTER EGY;Lu;0;R;;;;;N;;;;10CCE; 10C8F;OLD HUNGARIAN CAPITAL LETTER EH;Lu;0;R;;;;;N;;;;10CCF; 10C90;OLD HUNGARIAN CAPITAL LETTER I;Lu;0;R;;;;;N;;;;10CD0; 10C91;OLD HUNGARIAN CAPITAL LETTER II;Lu;0;R;;;;;N;;;;10CD1; 10C92;OLD HUNGARIAN CAPITAL LETTER EJ;Lu;0;R;;;;;N;;;;10CD2; 10C93;OLD HUNGARIAN CAPITAL LETTER EK;Lu;0;R;;;;;N;;;;10CD3; 10C94;OLD HUNGARIAN CAPITAL LETTER AK;Lu;0;R;;;;;N;;;;10CD4; 10C95;OLD HUNGARIAN CAPITAL LETTER UNK;Lu;0;R;;;;;N;;;;10CD5; 10C96;OLD HUNGARIAN CAPITAL LETTER EL;Lu;0;R;;;;;N;;;;10CD6; 10C97;OLD HUNGARIAN CAPITAL LETTER ELY;Lu;0;R;;;;;N;;;;10CD7; 10C98;OLD HUNGARIAN CAPITAL LETTER EM;Lu;0;R;;;;;N;;;;10CD8; 10C99;OLD HUNGARIAN CAPITAL LETTER EN;Lu;0;R;;;;;N;;;;10CD9; 10C9A;OLD HUNGARIAN CAPITAL LETTER ENY;Lu;0;R;;;;;N;;;;10CDA; 10C9B;OLD HUNGARIAN CAPITAL LETTER O;Lu;0;R;;;;;N;;;;10CDB; 10C9C;OLD HUNGARIAN CAPITAL LETTER OO;Lu;0;R;;;;;N;;;;10CDC; 10C9D;OLD HUNGARIAN CAPITAL LETTER NIKOLSBURG OE;Lu;0;R;;;;;N;;;;10CDD; 10C9E;OLD HUNGARIAN CAPITAL LETTER RUDIMENTA OE;Lu;0;R;;;;;N;;;;10CDE; 10C9F;OLD HUNGARIAN CAPITAL LETTER OEE;Lu;0;R;;;;;N;;;;10CDF; 10CA0;OLD HUNGARIAN CAPITAL LETTER EP;Lu;0;R;;;;;N;;;;10CE0; 10CA1;OLD HUNGARIAN CAPITAL LETTER EMP;Lu;0;R;;;;;N;;;;10CE1; 10CA2;OLD HUNGARIAN CAPITAL LETTER ER;Lu;0;R;;;;;N;;;;10CE2; 10CA3;OLD HUNGARIAN CAPITAL LETTER SHORT ER;Lu;0;R;;;;;N;;;;10CE3; 10CA4;OLD HUNGARIAN CAPITAL LETTER ES;Lu;0;R;;;;;N;;;;10CE4; 10CA5;OLD HUNGARIAN CAPITAL LETTER ESZ;Lu;0;R;;;;;N;;;;10CE5; 10CA6;OLD HUNGARIAN CAPITAL LETTER ET;Lu;0;R;;;;;N;;;;10CE6; 10CA7;OLD HUNGARIAN CAPITAL LETTER ENT;Lu;0;R;;;;;N;;;;10CE7; 10CA8;OLD HUNGARIAN CAPITAL LETTER ETY;Lu;0;R;;;;;N;;;;10CE8; 10CA9;OLD HUNGARIAN CAPITAL LETTER ECH;Lu;0;R;;;;;N;;;;10CE9; 10CAA;OLD HUNGARIAN CAPITAL LETTER U;Lu;0;R;;;;;N;;;;10CEA; 10CAB;OLD HUNGARIAN CAPITAL LETTER UU;Lu;0;R;;;;;N;;;;10CEB; 10CAC;OLD HUNGARIAN CAPITAL LETTER NIKOLSBURG UE;Lu;0;R;;;;;N;;;;10CEC; 10CAD;OLD HUNGARIAN CAPITAL LETTER RUDIMENTA UE;Lu;0;R;;;;;N;;;;10CED; 10CAE;OLD HUNGARIAN CAPITAL LETTER EV;Lu;0;R;;;;;N;;;;10CEE; 10CAF;OLD HUNGARIAN CAPITAL LETTER EZ;Lu;0;R;;;;;N;;;;10CEF; 10CB0;OLD HUNGARIAN CAPITAL LETTER EZS;Lu;0;R;;;;;N;;;;10CF0; 10CB1;OLD HUNGARIAN CAPITAL LETTER ENT-SHAPED SIGN;Lu;0;R;;;;;N;;;;10CF1; 10CB2;OLD HUNGARIAN CAPITAL LETTER US;Lu;0;R;;;;;N;;;;10CF2; 10CC0;OLD HUNGARIAN SMALL LETTER A;Ll;0;R;;;;;N;;;10C80;;10C80 10CC1;OLD HUNGARIAN SMALL LETTER AA;Ll;0;R;;;;;N;;;10C81;;10C81 10CC2;OLD HUNGARIAN SMALL LETTER EB;Ll;0;R;;;;;N;;;10C82;;10C82 10CC3;OLD HUNGARIAN SMALL LETTER AMB;Ll;0;R;;;;;N;;;10C83;;10C83 10CC4;OLD HUNGARIAN SMALL LETTER EC;Ll;0;R;;;;;N;;;10C84;;10C84 10CC5;OLD HUNGARIAN SMALL LETTER ENC;Ll;0;R;;;;;N;;;10C85;;10C85 10CC6;OLD HUNGARIAN SMALL LETTER ECS;Ll;0;R;;;;;N;;;10C86;;10C86 10CC7;OLD HUNGARIAN SMALL LETTER ED;Ll;0;R;;;;;N;;;10C87;;10C87 10CC8;OLD HUNGARIAN SMALL LETTER AND;Ll;0;R;;;;;N;;;10C88;;10C88 10CC9;OLD HUNGARIAN SMALL LETTER E;Ll;0;R;;;;;N;;;10C89;;10C89 10CCA;OLD HUNGARIAN SMALL LETTER CLOSE E;Ll;0;R;;;;;N;;;10C8A;;10C8A 10CCB;OLD HUNGARIAN SMALL LETTER EE;Ll;0;R;;;;;N;;;10C8B;;10C8B 10CCC;OLD HUNGARIAN SMALL LETTER EF;Ll;0;R;;;;;N;;;10C8C;;10C8C 10CCD;OLD HUNGARIAN SMALL LETTER EG;Ll;0;R;;;;;N;;;10C8D;;10C8D 10CCE;OLD HUNGARIAN SMALL LETTER EGY;Ll;0;R;;;;;N;;;10C8E;;10C8E 10CCF;OLD HUNGARIAN SMALL LETTER EH;Ll;0;R;;;;;N;;;10C8F;;10C8F 10CD0;OLD HUNGARIAN SMALL LETTER I;Ll;0;R;;;;;N;;;10C90;;10C90 10CD1;OLD HUNGARIAN SMALL LETTER II;Ll;0;R;;;;;N;;;10C91;;10C91 10CD2;OLD HUNGARIAN SMALL LETTER EJ;Ll;0;R;;;;;N;;;10C92;;10C92 10CD3;OLD HUNGARIAN SMALL LETTER EK;Ll;0;R;;;;;N;;;10C93;;10C93 10CD4;OLD HUNGARIAN SMALL LETTER AK;Ll;0;R;;;;;N;;;10C94;;10C94 10CD5;OLD HUNGARIAN SMALL LETTER UNK;Ll;0;R;;;;;N;;;10C95;;10C95 10CD6;OLD HUNGARIAN SMALL LETTER EL;Ll;0;R;;;;;N;;;10C96;;10C96 10CD7;OLD HUNGARIAN SMALL LETTER ELY;Ll;0;R;;;;;N;;;10C97;;10C97 10CD8;OLD HUNGARIAN SMALL LETTER EM;Ll;0;R;;;;;N;;;10C98;;10C98 10CD9;OLD HUNGARIAN SMALL LETTER EN;Ll;0;R;;;;;N;;;10C99;;10C99 10CDA;OLD HUNGARIAN SMALL LETTER ENY;Ll;0;R;;;;;N;;;10C9A;;10C9A 10CDB;OLD HUNGARIAN SMALL LETTER O;Ll;0;R;;;;;N;;;10C9B;;10C9B 10CDC;OLD HUNGARIAN SMALL LETTER OO;Ll;0;R;;;;;N;;;10C9C;;10C9C 10CDD;OLD HUNGARIAN SMALL LETTER NIKOLSBURG OE;Ll;0;R;;;;;N;;;10C9D;;10C9D 10CDE;OLD HUNGARIAN SMALL LETTER RUDIMENTA OE;Ll;0;R;;;;;N;;;10C9E;;10C9E 10CDF;OLD HUNGARIAN SMALL LETTER OEE;Ll;0;R;;;;;N;;;10C9F;;10C9F 10CE0;OLD HUNGARIAN SMALL LETTER EP;Ll;0;R;;;;;N;;;10CA0;;10CA0 10CE1;OLD HUNGARIAN SMALL LETTER EMP;Ll;0;R;;;;;N;;;10CA1;;10CA1 10CE2;OLD HUNGARIAN SMALL LETTER ER;Ll;0;R;;;;;N;;;10CA2;;10CA2 10CE3;OLD HUNGARIAN SMALL LETTER SHORT ER;Ll;0;R;;;;;N;;;10CA3;;10CA3 10CE4;OLD HUNGARIAN SMALL LETTER ES;Ll;0;R;;;;;N;;;10CA4;;10CA4 10CE5;OLD HUNGARIAN SMALL LETTER ESZ;Ll;0;R;;;;;N;;;10CA5;;10CA5 10CE6;OLD HUNGARIAN SMALL LETTER ET;Ll;0;R;;;;;N;;;10CA6;;10CA6 10CE7;OLD HUNGARIAN SMALL LETTER ENT;Ll;0;R;;;;;N;;;10CA7;;10CA7 10CE8;OLD HUNGARIAN SMALL LETTER ETY;Ll;0;R;;;;;N;;;10CA8;;10CA8 10CE9;OLD HUNGARIAN SMALL LETTER ECH;Ll;0;R;;;;;N;;;10CA9;;10CA9 10CEA;OLD HUNGARIAN SMALL LETTER U;Ll;0;R;;;;;N;;;10CAA;;10CAA 10CEB;OLD HUNGARIAN SMALL LETTER UU;Ll;0;R;;;;;N;;;10CAB;;10CAB 10CEC;OLD HUNGARIAN SMALL LETTER NIKOLSBURG UE;Ll;0;R;;;;;N;;;10CAC;;10CAC 10CED;OLD HUNGARIAN SMALL LETTER RUDIMENTA UE;Ll;0;R;;;;;N;;;10CAD;;10CAD 10CEE;OLD HUNGARIAN SMALL LETTER EV;Ll;0;R;;;;;N;;;10CAE;;10CAE 10CEF;OLD HUNGARIAN SMALL LETTER EZ;Ll;0;R;;;;;N;;;10CAF;;10CAF 10CF0;OLD HUNGARIAN SMALL LETTER EZS;Ll;0;R;;;;;N;;;10CB0;;10CB0 10CF1;OLD HUNGARIAN SMALL LETTER ENT-SHAPED SIGN;Ll;0;R;;;;;N;;;10CB1;;10CB1 10CF2;OLD HUNGARIAN SMALL LETTER US;Ll;0;R;;;;;N;;;10CB2;;10CB2 10CFA;OLD HUNGARIAN NUMBER ONE;No;0;R;;;;1;N;;;;; 10CFB;OLD HUNGARIAN NUMBER FIVE;No;0;R;;;;5;N;;;;; 10CFC;OLD HUNGARIAN NUMBER TEN;No;0;R;;;;10;N;;;;; 10CFD;OLD HUNGARIAN NUMBER FIFTY;No;0;R;;;;50;N;;;;; 10CFE;OLD HUNGARIAN NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;; 10CFF;OLD HUNGARIAN NUMBER ONE THOUSAND;No;0;R;;;;1000;N;;;;; 10E60;RUMI DIGIT ONE;No;0;AN;;;1;1;N;;;;; 10E61;RUMI DIGIT TWO;No;0;AN;;;2;2;N;;;;; 10E62;RUMI DIGIT THREE;No;0;AN;;;3;3;N;;;;; 10E63;RUMI DIGIT FOUR;No;0;AN;;;4;4;N;;;;; 10E64;RUMI DIGIT FIVE;No;0;AN;;;5;5;N;;;;; 10E65;RUMI DIGIT SIX;No;0;AN;;;6;6;N;;;;; 10E66;RUMI DIGIT SEVEN;No;0;AN;;;7;7;N;;;;; 10E67;RUMI DIGIT EIGHT;No;0;AN;;;8;8;N;;;;; 10E68;RUMI DIGIT NINE;No;0;AN;;;9;9;N;;;;; 10E69;RUMI NUMBER TEN;No;0;AN;;;;10;N;;;;; 10E6A;RUMI NUMBER TWENTY;No;0;AN;;;;20;N;;;;; 10E6B;RUMI NUMBER THIRTY;No;0;AN;;;;30;N;;;;; 10E6C;RUMI NUMBER FORTY;No;0;AN;;;;40;N;;;;; 10E6D;RUMI NUMBER FIFTY;No;0;AN;;;;50;N;;;;; 10E6E;RUMI NUMBER SIXTY;No;0;AN;;;;60;N;;;;; 10E6F;RUMI NUMBER SEVENTY;No;0;AN;;;;70;N;;;;; 10E70;RUMI NUMBER EIGHTY;No;0;AN;;;;80;N;;;;; 10E71;RUMI NUMBER NINETY;No;0;AN;;;;90;N;;;;; 10E72;RUMI NUMBER ONE HUNDRED;No;0;AN;;;;100;N;;;;; 10E73;RUMI NUMBER TWO HUNDRED;No;0;AN;;;;200;N;;;;; 10E74;RUMI NUMBER THREE HUNDRED;No;0;AN;;;;300;N;;;;; 10E75;RUMI NUMBER FOUR HUNDRED;No;0;AN;;;;400;N;;;;; 10E76;RUMI NUMBER FIVE HUNDRED;No;0;AN;;;;500;N;;;;; 10E77;RUMI NUMBER SIX HUNDRED;No;0;AN;;;;600;N;;;;; 10E78;RUMI NUMBER SEVEN HUNDRED;No;0;AN;;;;700;N;;;;; 10E79;RUMI NUMBER EIGHT HUNDRED;No;0;AN;;;;800;N;;;;; 10E7A;RUMI NUMBER NINE HUNDRED;No;0;AN;;;;900;N;;;;; 10E7B;RUMI FRACTION ONE HALF;No;0;AN;;;;1/2;N;;;;; 10E7C;RUMI FRACTION ONE QUARTER;No;0;AN;;;;1/4;N;;;;; 10E7D;RUMI FRACTION ONE THIRD;No;0;AN;;;;1/3;N;;;;; 10E7E;RUMI FRACTION TWO THIRDS;No;0;AN;;;;2/3;N;;;;; 11000;BRAHMI SIGN CANDRABINDU;Mc;0;L;;;;;N;;;;; 11001;BRAHMI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; 11002;BRAHMI SIGN VISARGA;Mc;0;L;;;;;N;;;;; 11003;BRAHMI SIGN JIHVAMULIYA;Lo;0;L;;;;;N;;;;; 11004;BRAHMI SIGN UPADHMANIYA;Lo;0;L;;;;;N;;;;; 11005;BRAHMI LETTER A;Lo;0;L;;;;;N;;;;; 11006;BRAHMI LETTER AA;Lo;0;L;;;;;N;;;;; 11007;BRAHMI LETTER I;Lo;0;L;;;;;N;;;;; 11008;BRAHMI LETTER II;Lo;0;L;;;;;N;;;;; 11009;BRAHMI LETTER U;Lo;0;L;;;;;N;;;;; 1100A;BRAHMI LETTER UU;Lo;0;L;;;;;N;;;;; 1100B;BRAHMI LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; 1100C;BRAHMI LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; 1100D;BRAHMI LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; 1100E;BRAHMI LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; 1100F;BRAHMI LETTER E;Lo;0;L;;;;;N;;;;; 11010;BRAHMI LETTER AI;Lo;0;L;;;;;N;;;;; 11011;BRAHMI LETTER O;Lo;0;L;;;;;N;;;;; 11012;BRAHMI LETTER AU;Lo;0;L;;;;;N;;;;; 11013;BRAHMI LETTER KA;Lo;0;L;;;;;N;;;;; 11014;BRAHMI LETTER KHA;Lo;0;L;;;;;N;;;;; 11015;BRAHMI LETTER GA;Lo;0;L;;;;;N;;;;; 11016;BRAHMI LETTER GHA;Lo;0;L;;;;;N;;;;; 11017;BRAHMI LETTER NGA;Lo;0;L;;;;;N;;;;; 11018;BRAHMI LETTER CA;Lo;0;L;;;;;N;;;;; 11019;BRAHMI LETTER CHA;Lo;0;L;;;;;N;;;;; 1101A;BRAHMI LETTER JA;Lo;0;L;;;;;N;;;;; 1101B;BRAHMI LETTER JHA;Lo;0;L;;;;;N;;;;; 1101C;BRAHMI LETTER NYA;Lo;0;L;;;;;N;;;;; 1101D;BRAHMI LETTER TTA;Lo;0;L;;;;;N;;;;; 1101E;BRAHMI LETTER TTHA;Lo;0;L;;;;;N;;;;; 1101F;BRAHMI LETTER DDA;Lo;0;L;;;;;N;;;;; 11020;BRAHMI LETTER DDHA;Lo;0;L;;;;;N;;;;; 11021;BRAHMI LETTER NNA;Lo;0;L;;;;;N;;;;; 11022;BRAHMI LETTER TA;Lo;0;L;;;;;N;;;;; 11023;BRAHMI LETTER THA;Lo;0;L;;;;;N;;;;; 11024;BRAHMI LETTER DA;Lo;0;L;;;;;N;;;;; 11025;BRAHMI LETTER DHA;Lo;0;L;;;;;N;;;;; 11026;BRAHMI LETTER NA;Lo;0;L;;;;;N;;;;; 11027;BRAHMI LETTER PA;Lo;0;L;;;;;N;;;;; 11028;BRAHMI LETTER PHA;Lo;0;L;;;;;N;;;;; 11029;BRAHMI LETTER BA;Lo;0;L;;;;;N;;;;; 1102A;BRAHMI LETTER BHA;Lo;0;L;;;;;N;;;;; 1102B;BRAHMI LETTER MA;Lo;0;L;;;;;N;;;;; 1102C;BRAHMI LETTER YA;Lo;0;L;;;;;N;;;;; 1102D;BRAHMI LETTER RA;Lo;0;L;;;;;N;;;;; 1102E;BRAHMI LETTER LA;Lo;0;L;;;;;N;;;;; 1102F;BRAHMI LETTER VA;Lo;0;L;;;;;N;;;;; 11030;BRAHMI LETTER SHA;Lo;0;L;;;;;N;;;;; 11031;BRAHMI LETTER SSA;Lo;0;L;;;;;N;;;;; 11032;BRAHMI LETTER SA;Lo;0;L;;;;;N;;;;; 11033;BRAHMI LETTER HA;Lo;0;L;;;;;N;;;;; 11034;BRAHMI LETTER LLA;Lo;0;L;;;;;N;;;;; 11035;BRAHMI LETTER OLD TAMIL LLLA;Lo;0;L;;;;;N;;;;; 11036;BRAHMI LETTER OLD TAMIL RRA;Lo;0;L;;;;;N;;;;; 11037;BRAHMI LETTER OLD TAMIL NNNA;Lo;0;L;;;;;N;;;;; 11038;BRAHMI VOWEL SIGN AA;Mn;0;NSM;;;;;N;;;;; 11039;BRAHMI VOWEL SIGN BHATTIPROLU AA;Mn;0;NSM;;;;;N;;;;; 1103A;BRAHMI VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; 1103B;BRAHMI VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; 1103C;BRAHMI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 1103D;BRAHMI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 1103E;BRAHMI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; 1103F;BRAHMI VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; 11040;BRAHMI VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; 11041;BRAHMI VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; 11042;BRAHMI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; 11043;BRAHMI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; 11044;BRAHMI VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; 11045;BRAHMI VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;; 11046;BRAHMI VIRAMA;Mn;9;NSM;;;;;N;;;;; 11047;BRAHMI DANDA;Po;0;L;;;;;N;;;;; 11048;BRAHMI DOUBLE DANDA;Po;0;L;;;;;N;;;;; 11049;BRAHMI PUNCTUATION DOT;Po;0;L;;;;;N;;;;; 1104A;BRAHMI PUNCTUATION DOUBLE DOT;Po;0;L;;;;;N;;;;; 1104B;BRAHMI PUNCTUATION LINE;Po;0;L;;;;;N;;;;; 1104C;BRAHMI PUNCTUATION CRESCENT BAR;Po;0;L;;;;;N;;;;; 1104D;BRAHMI PUNCTUATION LOTUS;Po;0;L;;;;;N;;;;; 11052;BRAHMI NUMBER ONE;No;0;ON;;;1;1;N;;;;; 11053;BRAHMI NUMBER TWO;No;0;ON;;;2;2;N;;;;; 11054;BRAHMI NUMBER THREE;No;0;ON;;;3;3;N;;;;; 11055;BRAHMI NUMBER FOUR;No;0;ON;;;4;4;N;;;;; 11056;BRAHMI NUMBER FIVE;No;0;ON;;;5;5;N;;;;; 11057;BRAHMI NUMBER SIX;No;0;ON;;;6;6;N;;;;; 11058;BRAHMI NUMBER SEVEN;No;0;ON;;;7;7;N;;;;; 11059;BRAHMI NUMBER EIGHT;No;0;ON;;;8;8;N;;;;; 1105A;BRAHMI NUMBER NINE;No;0;ON;;;9;9;N;;;;; 1105B;BRAHMI NUMBER TEN;No;0;ON;;;;10;N;;;;; 1105C;BRAHMI NUMBER TWENTY;No;0;ON;;;;20;N;;;;; 1105D;BRAHMI NUMBER THIRTY;No;0;ON;;;;30;N;;;;; 1105E;BRAHMI NUMBER FORTY;No;0;ON;;;;40;N;;;;; 1105F;BRAHMI NUMBER FIFTY;No;0;ON;;;;50;N;;;;; 11060;BRAHMI NUMBER SIXTY;No;0;ON;;;;60;N;;;;; 11061;BRAHMI NUMBER SEVENTY;No;0;ON;;;;70;N;;;;; 11062;BRAHMI NUMBER EIGHTY;No;0;ON;;;;80;N;;;;; 11063;BRAHMI NUMBER NINETY;No;0;ON;;;;90;N;;;;; 11064;BRAHMI NUMBER ONE HUNDRED;No;0;ON;;;;100;N;;;;; 11065;BRAHMI NUMBER ONE THOUSAND;No;0;ON;;;;1000;N;;;;; 11066;BRAHMI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 11067;BRAHMI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 11068;BRAHMI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 11069;BRAHMI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 1106A;BRAHMI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 1106B;BRAHMI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 1106C;BRAHMI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 1106D;BRAHMI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 1106E;BRAHMI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 1106F;BRAHMI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 1107F;BRAHMI NUMBER JOINER;Mn;9;NSM;;;;;N;;;;; 11080;KAITHI SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; 11081;KAITHI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; 11082;KAITHI SIGN VISARGA;Mc;0;L;;;;;N;;;;; 11083;KAITHI LETTER A;Lo;0;L;;;;;N;;;;; 11084;KAITHI LETTER AA;Lo;0;L;;;;;N;;;;; 11085;KAITHI LETTER I;Lo;0;L;;;;;N;;;;; 11086;KAITHI LETTER II;Lo;0;L;;;;;N;;;;; 11087;KAITHI LETTER U;Lo;0;L;;;;;N;;;;; 11088;KAITHI LETTER UU;Lo;0;L;;;;;N;;;;; 11089;KAITHI LETTER E;Lo;0;L;;;;;N;;;;; 1108A;KAITHI LETTER AI;Lo;0;L;;;;;N;;;;; 1108B;KAITHI LETTER O;Lo;0;L;;;;;N;;;;; 1108C;KAITHI LETTER AU;Lo;0;L;;;;;N;;;;; 1108D;KAITHI LETTER KA;Lo;0;L;;;;;N;;;;; 1108E;KAITHI LETTER KHA;Lo;0;L;;;;;N;;;;; 1108F;KAITHI LETTER GA;Lo;0;L;;;;;N;;;;; 11090;KAITHI LETTER GHA;Lo;0;L;;;;;N;;;;; 11091;KAITHI LETTER NGA;Lo;0;L;;;;;N;;;;; 11092;KAITHI LETTER CA;Lo;0;L;;;;;N;;;;; 11093;KAITHI LETTER CHA;Lo;0;L;;;;;N;;;;; 11094;KAITHI LETTER JA;Lo;0;L;;;;;N;;;;; 11095;KAITHI LETTER JHA;Lo;0;L;;;;;N;;;;; 11096;KAITHI LETTER NYA;Lo;0;L;;;;;N;;;;; 11097;KAITHI LETTER TTA;Lo;0;L;;;;;N;;;;; 11098;KAITHI LETTER TTHA;Lo;0;L;;;;;N;;;;; 11099;KAITHI LETTER DDA;Lo;0;L;;;;;N;;;;; 1109A;KAITHI LETTER DDDHA;Lo;0;L;11099 110BA;;;;N;;;;; 1109B;KAITHI LETTER DDHA;Lo;0;L;;;;;N;;;;; 1109C;KAITHI LETTER RHA;Lo;0;L;1109B 110BA;;;;N;;;;; 1109D;KAITHI LETTER NNA;Lo;0;L;;;;;N;;;;; 1109E;KAITHI LETTER TA;Lo;0;L;;;;;N;;;;; 1109F;KAITHI LETTER THA;Lo;0;L;;;;;N;;;;; 110A0;KAITHI LETTER DA;Lo;0;L;;;;;N;;;;; 110A1;KAITHI LETTER DHA;Lo;0;L;;;;;N;;;;; 110A2;KAITHI LETTER NA;Lo;0;L;;;;;N;;;;; 110A3;KAITHI LETTER PA;Lo;0;L;;;;;N;;;;; 110A4;KAITHI LETTER PHA;Lo;0;L;;;;;N;;;;; 110A5;KAITHI LETTER BA;Lo;0;L;;;;;N;;;;; 110A6;KAITHI LETTER BHA;Lo;0;L;;;;;N;;;;; 110A7;KAITHI LETTER MA;Lo;0;L;;;;;N;;;;; 110A8;KAITHI LETTER YA;Lo;0;L;;;;;N;;;;; 110A9;KAITHI LETTER RA;Lo;0;L;;;;;N;;;;; 110AA;KAITHI LETTER LA;Lo;0;L;;;;;N;;;;; 110AB;KAITHI LETTER VA;Lo;0;L;110A5 110BA;;;;N;;;;; 110AC;KAITHI LETTER SHA;Lo;0;L;;;;;N;;;;; 110AD;KAITHI LETTER SSA;Lo;0;L;;;;;N;;;;; 110AE;KAITHI LETTER SA;Lo;0;L;;;;;N;;;;; 110AF;KAITHI LETTER HA;Lo;0;L;;;;;N;;;;; 110B0;KAITHI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 110B1;KAITHI VOWEL SIGN I;Mc;0;L;;;;;N;;;;; 110B2;KAITHI VOWEL SIGN II;Mc;0;L;;;;;N;;;;; 110B3;KAITHI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 110B4;KAITHI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 110B5;KAITHI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; 110B6;KAITHI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; 110B7;KAITHI VOWEL SIGN O;Mc;0;L;;;;;N;;;;; 110B8;KAITHI VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; 110B9;KAITHI SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 110BA;KAITHI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; 110BB;KAITHI ABBREVIATION SIGN;Po;0;L;;;;;N;;;;; 110BC;KAITHI ENUMERATION SIGN;Po;0;L;;;;;N;;;;; 110BD;KAITHI NUMBER SIGN;Cf;0;L;;;;;N;;;;; 110BE;KAITHI SECTION MARK;Po;0;L;;;;;N;;;;; 110BF;KAITHI DOUBLE SECTION MARK;Po;0;L;;;;;N;;;;; 110C0;KAITHI DANDA;Po;0;L;;;;;N;;;;; 110C1;KAITHI DOUBLE DANDA;Po;0;L;;;;;N;;;;; 110D0;SORA SOMPENG LETTER SAH;Lo;0;L;;;;;N;;;;; 110D1;SORA SOMPENG LETTER TAH;Lo;0;L;;;;;N;;;;; 110D2;SORA SOMPENG LETTER BAH;Lo;0;L;;;;;N;;;;; 110D3;SORA SOMPENG LETTER CAH;Lo;0;L;;;;;N;;;;; 110D4;SORA SOMPENG LETTER DAH;Lo;0;L;;;;;N;;;;; 110D5;SORA SOMPENG LETTER GAH;Lo;0;L;;;;;N;;;;; 110D6;SORA SOMPENG LETTER MAH;Lo;0;L;;;;;N;;;;; 110D7;SORA SOMPENG LETTER NGAH;Lo;0;L;;;;;N;;;;; 110D8;SORA SOMPENG LETTER LAH;Lo;0;L;;;;;N;;;;; 110D9;SORA SOMPENG LETTER NAH;Lo;0;L;;;;;N;;;;; 110DA;SORA SOMPENG LETTER VAH;Lo;0;L;;;;;N;;;;; 110DB;SORA SOMPENG LETTER PAH;Lo;0;L;;;;;N;;;;; 110DC;SORA SOMPENG LETTER YAH;Lo;0;L;;;;;N;;;;; 110DD;SORA SOMPENG LETTER RAH;Lo;0;L;;;;;N;;;;; 110DE;SORA SOMPENG LETTER HAH;Lo;0;L;;;;;N;;;;; 110DF;SORA SOMPENG LETTER KAH;Lo;0;L;;;;;N;;;;; 110E0;SORA SOMPENG LETTER JAH;Lo;0;L;;;;;N;;;;; 110E1;SORA SOMPENG LETTER NYAH;Lo;0;L;;;;;N;;;;; 110E2;SORA SOMPENG LETTER AH;Lo;0;L;;;;;N;;;;; 110E3;SORA SOMPENG LETTER EEH;Lo;0;L;;;;;N;;;;; 110E4;SORA SOMPENG LETTER IH;Lo;0;L;;;;;N;;;;; 110E5;SORA SOMPENG LETTER UH;Lo;0;L;;;;;N;;;;; 110E6;SORA SOMPENG LETTER OH;Lo;0;L;;;;;N;;;;; 110E7;SORA SOMPENG LETTER EH;Lo;0;L;;;;;N;;;;; 110E8;SORA SOMPENG LETTER MAE;Lo;0;L;;;;;N;;;;; 110F0;SORA SOMPENG DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 110F1;SORA SOMPENG DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 110F2;SORA SOMPENG DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 110F3;SORA SOMPENG DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 110F4;SORA SOMPENG DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 110F5;SORA SOMPENG DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 110F6;SORA SOMPENG DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 110F7;SORA SOMPENG DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 110F8;SORA SOMPENG DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 110F9;SORA SOMPENG DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 11100;CHAKMA SIGN CANDRABINDU;Mn;230;NSM;;;;;N;;;;; 11101;CHAKMA SIGN ANUSVARA;Mn;230;NSM;;;;;N;;;;; 11102;CHAKMA SIGN VISARGA;Mn;230;NSM;;;;;N;;;;; 11103;CHAKMA LETTER AA;Lo;0;L;;;;;N;;;;; 11104;CHAKMA LETTER I;Lo;0;L;;;;;N;;;;; 11105;CHAKMA LETTER U;Lo;0;L;;;;;N;;;;; 11106;CHAKMA LETTER E;Lo;0;L;;;;;N;;;;; 11107;CHAKMA LETTER KAA;Lo;0;L;;;;;N;;;;; 11108;CHAKMA LETTER KHAA;Lo;0;L;;;;;N;;;;; 11109;CHAKMA LETTER GAA;Lo;0;L;;;;;N;;;;; 1110A;CHAKMA LETTER GHAA;Lo;0;L;;;;;N;;;;; 1110B;CHAKMA LETTER NGAA;Lo;0;L;;;;;N;;;;; 1110C;CHAKMA LETTER CAA;Lo;0;L;;;;;N;;;;; 1110D;CHAKMA LETTER CHAA;Lo;0;L;;;;;N;;;;; 1110E;CHAKMA LETTER JAA;Lo;0;L;;;;;N;;;;; 1110F;CHAKMA LETTER JHAA;Lo;0;L;;;;;N;;;;; 11110;CHAKMA LETTER NYAA;Lo;0;L;;;;;N;;;;; 11111;CHAKMA LETTER TTAA;Lo;0;L;;;;;N;;;;; 11112;CHAKMA LETTER TTHAA;Lo;0;L;;;;;N;;;;; 11113;CHAKMA LETTER DDAA;Lo;0;L;;;;;N;;;;; 11114;CHAKMA LETTER DDHAA;Lo;0;L;;;;;N;;;;; 11115;CHAKMA LETTER NNAA;Lo;0;L;;;;;N;;;;; 11116;CHAKMA LETTER TAA;Lo;0;L;;;;;N;;;;; 11117;CHAKMA LETTER THAA;Lo;0;L;;;;;N;;;;; 11118;CHAKMA LETTER DAA;Lo;0;L;;;;;N;;;;; 11119;CHAKMA LETTER DHAA;Lo;0;L;;;;;N;;;;; 1111A;CHAKMA LETTER NAA;Lo;0;L;;;;;N;;;;; 1111B;CHAKMA LETTER PAA;Lo;0;L;;;;;N;;;;; 1111C;CHAKMA LETTER PHAA;Lo;0;L;;;;;N;;;;; 1111D;CHAKMA LETTER BAA;Lo;0;L;;;;;N;;;;; 1111E;CHAKMA LETTER BHAA;Lo;0;L;;;;;N;;;;; 1111F;CHAKMA LETTER MAA;Lo;0;L;;;;;N;;;;; 11120;CHAKMA LETTER YYAA;Lo;0;L;;;;;N;;;;; 11121;CHAKMA LETTER YAA;Lo;0;L;;;;;N;;;;; 11122;CHAKMA LETTER RAA;Lo;0;L;;;;;N;;;;; 11123;CHAKMA LETTER LAA;Lo;0;L;;;;;N;;;;; 11124;CHAKMA LETTER WAA;Lo;0;L;;;;;N;;;;; 11125;CHAKMA LETTER SAA;Lo;0;L;;;;;N;;;;; 11126;CHAKMA LETTER HAA;Lo;0;L;;;;;N;;;;; 11127;CHAKMA VOWEL SIGN A;Mn;0;NSM;;;;;N;;;;; 11128;CHAKMA VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; 11129;CHAKMA VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; 1112A;CHAKMA VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 1112B;CHAKMA VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 1112C;CHAKMA VOWEL SIGN E;Mc;0;L;;;;;N;;;;; 1112D;CHAKMA VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; 1112E;CHAKMA VOWEL SIGN O;Mn;0;NSM;11131 11127;;;;N;;;;; 1112F;CHAKMA VOWEL SIGN AU;Mn;0;NSM;11132 11127;;;;N;;;;; 11130;CHAKMA VOWEL SIGN OI;Mn;0;NSM;;;;;N;;;;; 11131;CHAKMA O MARK;Mn;0;NSM;;;;;N;;;;; 11132;CHAKMA AU MARK;Mn;0;NSM;;;;;N;;;;; 11133;CHAKMA VIRAMA;Mn;9;NSM;;;;;N;;;;; 11134;CHAKMA MAAYYAA;Mn;9;NSM;;;;;N;;;;; 11136;CHAKMA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 11137;CHAKMA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 11138;CHAKMA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 11139;CHAKMA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 1113A;CHAKMA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 1113B;CHAKMA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 1113C;CHAKMA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 1113D;CHAKMA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 1113E;CHAKMA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 1113F;CHAKMA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 11140;CHAKMA SECTION MARK;Po;0;L;;;;;N;;;;; 11141;CHAKMA DANDA;Po;0;L;;;;;N;;;;; 11142;CHAKMA DOUBLE DANDA;Po;0;L;;;;;N;;;;; 11143;CHAKMA QUESTION MARK;Po;0;L;;;;;N;;;;; 11150;MAHAJANI LETTER A;Lo;0;L;;;;;N;;;;; 11151;MAHAJANI LETTER I;Lo;0;L;;;;;N;;;;; 11152;MAHAJANI LETTER U;Lo;0;L;;;;;N;;;;; 11153;MAHAJANI LETTER E;Lo;0;L;;;;;N;;;;; 11154;MAHAJANI LETTER O;Lo;0;L;;;;;N;;;;; 11155;MAHAJANI LETTER KA;Lo;0;L;;;;;N;;;;; 11156;MAHAJANI LETTER KHA;Lo;0;L;;;;;N;;;;; 11157;MAHAJANI LETTER GA;Lo;0;L;;;;;N;;;;; 11158;MAHAJANI LETTER GHA;Lo;0;L;;;;;N;;;;; 11159;MAHAJANI LETTER CA;Lo;0;L;;;;;N;;;;; 1115A;MAHAJANI LETTER CHA;Lo;0;L;;;;;N;;;;; 1115B;MAHAJANI LETTER JA;Lo;0;L;;;;;N;;;;; 1115C;MAHAJANI LETTER JHA;Lo;0;L;;;;;N;;;;; 1115D;MAHAJANI LETTER NYA;Lo;0;L;;;;;N;;;;; 1115E;MAHAJANI LETTER TTA;Lo;0;L;;;;;N;;;;; 1115F;MAHAJANI LETTER TTHA;Lo;0;L;;;;;N;;;;; 11160;MAHAJANI LETTER DDA;Lo;0;L;;;;;N;;;;; 11161;MAHAJANI LETTER DDHA;Lo;0;L;;;;;N;;;;; 11162;MAHAJANI LETTER NNA;Lo;0;L;;;;;N;;;;; 11163;MAHAJANI LETTER TA;Lo;0;L;;;;;N;;;;; 11164;MAHAJANI LETTER THA;Lo;0;L;;;;;N;;;;; 11165;MAHAJANI LETTER DA;Lo;0;L;;;;;N;;;;; 11166;MAHAJANI LETTER DHA;Lo;0;L;;;;;N;;;;; 11167;MAHAJANI LETTER NA;Lo;0;L;;;;;N;;;;; 11168;MAHAJANI LETTER PA;Lo;0;L;;;;;N;;;;; 11169;MAHAJANI LETTER PHA;Lo;0;L;;;;;N;;;;; 1116A;MAHAJANI LETTER BA;Lo;0;L;;;;;N;;;;; 1116B;MAHAJANI LETTER BHA;Lo;0;L;;;;;N;;;;; 1116C;MAHAJANI LETTER MA;Lo;0;L;;;;;N;;;;; 1116D;MAHAJANI LETTER RA;Lo;0;L;;;;;N;;;;; 1116E;MAHAJANI LETTER LA;Lo;0;L;;;;;N;;;;; 1116F;MAHAJANI LETTER VA;Lo;0;L;;;;;N;;;;; 11170;MAHAJANI LETTER SA;Lo;0;L;;;;;N;;;;; 11171;MAHAJANI LETTER HA;Lo;0;L;;;;;N;;;;; 11172;MAHAJANI LETTER RRA;Lo;0;L;;;;;N;;;;; 11173;MAHAJANI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; 11174;MAHAJANI ABBREVIATION SIGN;Po;0;L;;;;;N;;;;; 11175;MAHAJANI SECTION MARK;Po;0;L;;;;;N;;;;; 11176;MAHAJANI LIGATURE SHRI;Lo;0;L;;;;;N;;;;; 11180;SHARADA SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; 11181;SHARADA SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; 11182;SHARADA SIGN VISARGA;Mc;0;L;;;;;N;;;;; 11183;SHARADA LETTER A;Lo;0;L;;;;;N;;;;; 11184;SHARADA LETTER AA;Lo;0;L;;;;;N;;;;; 11185;SHARADA LETTER I;Lo;0;L;;;;;N;;;;; 11186;SHARADA LETTER II;Lo;0;L;;;;;N;;;;; 11187;SHARADA LETTER U;Lo;0;L;;;;;N;;;;; 11188;SHARADA LETTER UU;Lo;0;L;;;;;N;;;;; 11189;SHARADA LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; 1118A;SHARADA LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; 1118B;SHARADA LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; 1118C;SHARADA LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; 1118D;SHARADA LETTER E;Lo;0;L;;;;;N;;;;; 1118E;SHARADA LETTER AI;Lo;0;L;;;;;N;;;;; 1118F;SHARADA LETTER O;Lo;0;L;;;;;N;;;;; 11190;SHARADA LETTER AU;Lo;0;L;;;;;N;;;;; 11191;SHARADA LETTER KA;Lo;0;L;;;;;N;;;;; 11192;SHARADA LETTER KHA;Lo;0;L;;;;;N;;;;; 11193;SHARADA LETTER GA;Lo;0;L;;;;;N;;;;; 11194;SHARADA LETTER GHA;Lo;0;L;;;;;N;;;;; 11195;SHARADA LETTER NGA;Lo;0;L;;;;;N;;;;; 11196;SHARADA LETTER CA;Lo;0;L;;;;;N;;;;; 11197;SHARADA LETTER CHA;Lo;0;L;;;;;N;;;;; 11198;SHARADA LETTER JA;Lo;0;L;;;;;N;;;;; 11199;SHARADA LETTER JHA;Lo;0;L;;;;;N;;;;; 1119A;SHARADA LETTER NYA;Lo;0;L;;;;;N;;;;; 1119B;SHARADA LETTER TTA;Lo;0;L;;;;;N;;;;; 1119C;SHARADA LETTER TTHA;Lo;0;L;;;;;N;;;;; 1119D;SHARADA LETTER DDA;Lo;0;L;;;;;N;;;;; 1119E;SHARADA LETTER DDHA;Lo;0;L;;;;;N;;;;; 1119F;SHARADA LETTER NNA;Lo;0;L;;;;;N;;;;; 111A0;SHARADA LETTER TA;Lo;0;L;;;;;N;;;;; 111A1;SHARADA LETTER THA;Lo;0;L;;;;;N;;;;; 111A2;SHARADA LETTER DA;Lo;0;L;;;;;N;;;;; 111A3;SHARADA LETTER DHA;Lo;0;L;;;;;N;;;;; 111A4;SHARADA LETTER NA;Lo;0;L;;;;;N;;;;; 111A5;SHARADA LETTER PA;Lo;0;L;;;;;N;;;;; 111A6;SHARADA LETTER PHA;Lo;0;L;;;;;N;;;;; 111A7;SHARADA LETTER BA;Lo;0;L;;;;;N;;;;; 111A8;SHARADA LETTER BHA;Lo;0;L;;;;;N;;;;; 111A9;SHARADA LETTER MA;Lo;0;L;;;;;N;;;;; 111AA;SHARADA LETTER YA;Lo;0;L;;;;;N;;;;; 111AB;SHARADA LETTER RA;Lo;0;L;;;;;N;;;;; 111AC;SHARADA LETTER LA;Lo;0;L;;;;;N;;;;; 111AD;SHARADA LETTER LLA;Lo;0;L;;;;;N;;;;; 111AE;SHARADA LETTER VA;Lo;0;L;;;;;N;;;;; 111AF;SHARADA LETTER SHA;Lo;0;L;;;;;N;;;;; 111B0;SHARADA LETTER SSA;Lo;0;L;;;;;N;;;;; 111B1;SHARADA LETTER SA;Lo;0;L;;;;;N;;;;; 111B2;SHARADA LETTER HA;Lo;0;L;;;;;N;;;;; 111B3;SHARADA VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 111B4;SHARADA VOWEL SIGN I;Mc;0;L;;;;;N;;;;; 111B5;SHARADA VOWEL SIGN II;Mc;0;L;;;;;N;;;;; 111B6;SHARADA VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 111B7;SHARADA VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 111B8;SHARADA VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; 111B9;SHARADA VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; 111BA;SHARADA VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; 111BB;SHARADA VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; 111BC;SHARADA VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; 111BD;SHARADA VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; 111BE;SHARADA VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; 111BF;SHARADA VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; 111C0;SHARADA SIGN VIRAMA;Mc;9;L;;;;;N;;;;; 111C1;SHARADA SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; 111C2;SHARADA SIGN JIHVAMULIYA;Lo;0;L;;;;;N;;;;; 111C3;SHARADA SIGN UPADHMANIYA;Lo;0;L;;;;;N;;;;; 111C4;SHARADA OM;Lo;0;L;;;;;N;;;;; 111C5;SHARADA DANDA;Po;0;L;;;;;N;;;;; 111C6;SHARADA DOUBLE DANDA;Po;0;L;;;;;N;;;;; 111C7;SHARADA ABBREVIATION SIGN;Po;0;L;;;;;N;;;;; 111C8;SHARADA SEPARATOR;Po;0;L;;;;;N;;;;; 111C9;SHARADA SANDHI MARK;Po;0;L;;;;;N;;;;; 111CA;SHARADA SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; 111CB;SHARADA VOWEL MODIFIER MARK;Mn;0;NSM;;;;;N;;;;; 111CC;SHARADA EXTRA SHORT VOWEL MARK;Mn;0;NSM;;;;;N;;;;; 111CD;SHARADA SUTRA MARK;Po;0;L;;;;;N;;;;; 111D0;SHARADA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 111D1;SHARADA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 111D2;SHARADA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 111D3;SHARADA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 111D4;SHARADA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 111D5;SHARADA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 111D6;SHARADA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 111D7;SHARADA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 111D8;SHARADA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 111D9;SHARADA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 111DA;SHARADA EKAM;Lo;0;L;;;;;N;;;;; 111DB;SHARADA SIGN SIDDHAM;Po;0;L;;;;;N;;;;; 111DC;SHARADA HEADSTROKE;Lo;0;L;;;;;N;;;;; 111DD;SHARADA CONTINUATION SIGN;Po;0;L;;;;;N;;;;; 111DE;SHARADA SECTION MARK-1;Po;0;L;;;;;N;;;;; 111DF;SHARADA SECTION MARK-2;Po;0;L;;;;;N;;;;; 111E1;SINHALA ARCHAIC DIGIT ONE;No;0;L;;;;1;N;;;;; 111E2;SINHALA ARCHAIC DIGIT TWO;No;0;L;;;;2;N;;;;; 111E3;SINHALA ARCHAIC DIGIT THREE;No;0;L;;;;3;N;;;;; 111E4;SINHALA ARCHAIC DIGIT FOUR;No;0;L;;;;4;N;;;;; 111E5;SINHALA ARCHAIC DIGIT FIVE;No;0;L;;;;5;N;;;;; 111E6;SINHALA ARCHAIC DIGIT SIX;No;0;L;;;;6;N;;;;; 111E7;SINHALA ARCHAIC DIGIT SEVEN;No;0;L;;;;7;N;;;;; 111E8;SINHALA ARCHAIC DIGIT EIGHT;No;0;L;;;;8;N;;;;; 111E9;SINHALA ARCHAIC DIGIT NINE;No;0;L;;;;9;N;;;;; 111EA;SINHALA ARCHAIC NUMBER TEN;No;0;L;;;;10;N;;;;; 111EB;SINHALA ARCHAIC NUMBER TWENTY;No;0;L;;;;20;N;;;;; 111EC;SINHALA ARCHAIC NUMBER THIRTY;No;0;L;;;;30;N;;;;; 111ED;SINHALA ARCHAIC NUMBER FORTY;No;0;L;;;;40;N;;;;; 111EE;SINHALA ARCHAIC NUMBER FIFTY;No;0;L;;;;50;N;;;;; 111EF;SINHALA ARCHAIC NUMBER SIXTY;No;0;L;;;;60;N;;;;; 111F0;SINHALA ARCHAIC NUMBER SEVENTY;No;0;L;;;;70;N;;;;; 111F1;SINHALA ARCHAIC NUMBER EIGHTY;No;0;L;;;;80;N;;;;; 111F2;SINHALA ARCHAIC NUMBER NINETY;No;0;L;;;;90;N;;;;; 111F3;SINHALA ARCHAIC NUMBER ONE HUNDRED;No;0;L;;;;100;N;;;;; 111F4;SINHALA ARCHAIC NUMBER ONE THOUSAND;No;0;L;;;;1000;N;;;;; 11200;KHOJKI LETTER A;Lo;0;L;;;;;N;;;;; 11201;KHOJKI LETTER AA;Lo;0;L;;;;;N;;;;; 11202;KHOJKI LETTER I;Lo;0;L;;;;;N;;;;; 11203;KHOJKI LETTER U;Lo;0;L;;;;;N;;;;; 11204;KHOJKI LETTER E;Lo;0;L;;;;;N;;;;; 11205;KHOJKI LETTER AI;Lo;0;L;;;;;N;;;;; 11206;KHOJKI LETTER O;Lo;0;L;;;;;N;;;;; 11207;KHOJKI LETTER AU;Lo;0;L;;;;;N;;;;; 11208;KHOJKI LETTER KA;Lo;0;L;;;;;N;;;;; 11209;KHOJKI LETTER KHA;Lo;0;L;;;;;N;;;;; 1120A;KHOJKI LETTER GA;Lo;0;L;;;;;N;;;;; 1120B;KHOJKI LETTER GGA;Lo;0;L;;;;;N;;;;; 1120C;KHOJKI LETTER GHA;Lo;0;L;;;;;N;;;;; 1120D;KHOJKI LETTER NGA;Lo;0;L;;;;;N;;;;; 1120E;KHOJKI LETTER CA;Lo;0;L;;;;;N;;;;; 1120F;KHOJKI LETTER CHA;Lo;0;L;;;;;N;;;;; 11210;KHOJKI LETTER JA;Lo;0;L;;;;;N;;;;; 11211;KHOJKI LETTER JJA;Lo;0;L;;;;;N;;;;; 11213;KHOJKI LETTER NYA;Lo;0;L;;;;;N;;;;; 11214;KHOJKI LETTER TTA;Lo;0;L;;;;;N;;;;; 11215;KHOJKI LETTER TTHA;Lo;0;L;;;;;N;;;;; 11216;KHOJKI LETTER DDA;Lo;0;L;;;;;N;;;;; 11217;KHOJKI LETTER DDHA;Lo;0;L;;;;;N;;;;; 11218;KHOJKI LETTER NNA;Lo;0;L;;;;;N;;;;; 11219;KHOJKI LETTER TA;Lo;0;L;;;;;N;;;;; 1121A;KHOJKI LETTER THA;Lo;0;L;;;;;N;;;;; 1121B;KHOJKI LETTER DA;Lo;0;L;;;;;N;;;;; 1121C;KHOJKI LETTER DDDA;Lo;0;L;;;;;N;;;;; 1121D;KHOJKI LETTER DHA;Lo;0;L;;;;;N;;;;; 1121E;KHOJKI LETTER NA;Lo;0;L;;;;;N;;;;; 1121F;KHOJKI LETTER PA;Lo;0;L;;;;;N;;;;; 11220;KHOJKI LETTER PHA;Lo;0;L;;;;;N;;;;; 11221;KHOJKI LETTER BA;Lo;0;L;;;;;N;;;;; 11222;KHOJKI LETTER BBA;Lo;0;L;;;;;N;;;;; 11223;KHOJKI LETTER BHA;Lo;0;L;;;;;N;;;;; 11224;KHOJKI LETTER MA;Lo;0;L;;;;;N;;;;; 11225;KHOJKI LETTER YA;Lo;0;L;;;;;N;;;;; 11226;KHOJKI LETTER RA;Lo;0;L;;;;;N;;;;; 11227;KHOJKI LETTER LA;Lo;0;L;;;;;N;;;;; 11228;KHOJKI LETTER VA;Lo;0;L;;;;;N;;;;; 11229;KHOJKI LETTER SA;Lo;0;L;;;;;N;;;;; 1122A;KHOJKI LETTER HA;Lo;0;L;;;;;N;;;;; 1122B;KHOJKI LETTER LLA;Lo;0;L;;;;;N;;;;; 1122C;KHOJKI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 1122D;KHOJKI VOWEL SIGN I;Mc;0;L;;;;;N;;;;; 1122E;KHOJKI VOWEL SIGN II;Mc;0;L;;;;;N;;;;; 1122F;KHOJKI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 11230;KHOJKI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; 11231;KHOJKI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; 11232;KHOJKI VOWEL SIGN O;Mc;0;L;;;;;N;;;;; 11233;KHOJKI VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; 11234;KHOJKI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; 11235;KHOJKI SIGN VIRAMA;Mc;9;L;;;;;N;;;;; 11236;KHOJKI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; 11237;KHOJKI SIGN SHADDA;Mn;0;NSM;;;;;N;;;;; 11238;KHOJKI DANDA;Po;0;L;;;;;N;;;;; 11239;KHOJKI DOUBLE DANDA;Po;0;L;;;;;N;;;;; 1123A;KHOJKI WORD SEPARATOR;Po;0;L;;;;;N;;;;; 1123B;KHOJKI SECTION MARK;Po;0;L;;;;;N;;;;; 1123C;KHOJKI DOUBLE SECTION MARK;Po;0;L;;;;;N;;;;; 1123D;KHOJKI ABBREVIATION SIGN;Po;0;L;;;;;N;;;;; 1123E;KHOJKI SIGN SUKUN;Mn;0;NSM;;;;;N;;;;; 11280;MULTANI LETTER A;Lo;0;L;;;;;N;;;;; 11281;MULTANI LETTER I;Lo;0;L;;;;;N;;;;; 11282;MULTANI LETTER U;Lo;0;L;;;;;N;;;;; 11283;MULTANI LETTER E;Lo;0;L;;;;;N;;;;; 11284;MULTANI LETTER KA;Lo;0;L;;;;;N;;;;; 11285;MULTANI LETTER KHA;Lo;0;L;;;;;N;;;;; 11286;MULTANI LETTER GA;Lo;0;L;;;;;N;;;;; 11288;MULTANI LETTER GHA;Lo;0;L;;;;;N;;;;; 1128A;MULTANI LETTER CA;Lo;0;L;;;;;N;;;;; 1128B;MULTANI LETTER CHA;Lo;0;L;;;;;N;;;;; 1128C;MULTANI LETTER JA;Lo;0;L;;;;;N;;;;; 1128D;MULTANI LETTER JJA;Lo;0;L;;;;;N;;;;; 1128F;MULTANI LETTER NYA;Lo;0;L;;;;;N;;;;; 11290;MULTANI LETTER TTA;Lo;0;L;;;;;N;;;;; 11291;MULTANI LETTER TTHA;Lo;0;L;;;;;N;;;;; 11292;MULTANI LETTER DDA;Lo;0;L;;;;;N;;;;; 11293;MULTANI LETTER DDDA;Lo;0;L;;;;;N;;;;; 11294;MULTANI LETTER DDHA;Lo;0;L;;;;;N;;;;; 11295;MULTANI LETTER NNA;Lo;0;L;;;;;N;;;;; 11296;MULTANI LETTER TA;Lo;0;L;;;;;N;;;;; 11297;MULTANI LETTER THA;Lo;0;L;;;;;N;;;;; 11298;MULTANI LETTER DA;Lo;0;L;;;;;N;;;;; 11299;MULTANI LETTER DHA;Lo;0;L;;;;;N;;;;; 1129A;MULTANI LETTER NA;Lo;0;L;;;;;N;;;;; 1129B;MULTANI LETTER PA;Lo;0;L;;;;;N;;;;; 1129C;MULTANI LETTER PHA;Lo;0;L;;;;;N;;;;; 1129D;MULTANI LETTER BA;Lo;0;L;;;;;N;;;;; 1129F;MULTANI LETTER BHA;Lo;0;L;;;;;N;;;;; 112A0;MULTANI LETTER MA;Lo;0;L;;;;;N;;;;; 112A1;MULTANI LETTER YA;Lo;0;L;;;;;N;;;;; 112A2;MULTANI LETTER RA;Lo;0;L;;;;;N;;;;; 112A3;MULTANI LETTER LA;Lo;0;L;;;;;N;;;;; 112A4;MULTANI LETTER VA;Lo;0;L;;;;;N;;;;; 112A5;MULTANI LETTER SA;Lo;0;L;;;;;N;;;;; 112A6;MULTANI LETTER HA;Lo;0;L;;;;;N;;;;; 112A7;MULTANI LETTER RRA;Lo;0;L;;;;;N;;;;; 112A8;MULTANI LETTER RHA;Lo;0;L;;;;;N;;;;; 112A9;MULTANI SECTION MARK;Po;0;L;;;;;N;;;;; 112B0;KHUDAWADI LETTER A;Lo;0;L;;;;;N;;;;; 112B1;KHUDAWADI LETTER AA;Lo;0;L;;;;;N;;;;; 112B2;KHUDAWADI LETTER I;Lo;0;L;;;;;N;;;;; 112B3;KHUDAWADI LETTER II;Lo;0;L;;;;;N;;;;; 112B4;KHUDAWADI LETTER U;Lo;0;L;;;;;N;;;;; 112B5;KHUDAWADI LETTER UU;Lo;0;L;;;;;N;;;;; 112B6;KHUDAWADI LETTER E;Lo;0;L;;;;;N;;;;; 112B7;KHUDAWADI LETTER AI;Lo;0;L;;;;;N;;;;; 112B8;KHUDAWADI LETTER O;Lo;0;L;;;;;N;;;;; 112B9;KHUDAWADI LETTER AU;Lo;0;L;;;;;N;;;;; 112BA;KHUDAWADI LETTER KA;Lo;0;L;;;;;N;;;;; 112BB;KHUDAWADI LETTER KHA;Lo;0;L;;;;;N;;;;; 112BC;KHUDAWADI LETTER GA;Lo;0;L;;;;;N;;;;; 112BD;KHUDAWADI LETTER GGA;Lo;0;L;;;;;N;;;;; 112BE;KHUDAWADI LETTER GHA;Lo;0;L;;;;;N;;;;; 112BF;KHUDAWADI LETTER NGA;Lo;0;L;;;;;N;;;;; 112C0;KHUDAWADI LETTER CA;Lo;0;L;;;;;N;;;;; 112C1;KHUDAWADI LETTER CHA;Lo;0;L;;;;;N;;;;; 112C2;KHUDAWADI LETTER JA;Lo;0;L;;;;;N;;;;; 112C3;KHUDAWADI LETTER JJA;Lo;0;L;;;;;N;;;;; 112C4;KHUDAWADI LETTER JHA;Lo;0;L;;;;;N;;;;; 112C5;KHUDAWADI LETTER NYA;Lo;0;L;;;;;N;;;;; 112C6;KHUDAWADI LETTER TTA;Lo;0;L;;;;;N;;;;; 112C7;KHUDAWADI LETTER TTHA;Lo;0;L;;;;;N;;;;; 112C8;KHUDAWADI LETTER DDA;Lo;0;L;;;;;N;;;;; 112C9;KHUDAWADI LETTER DDDA;Lo;0;L;;;;;N;;;;; 112CA;KHUDAWADI LETTER RRA;Lo;0;L;;;;;N;;;;; 112CB;KHUDAWADI LETTER DDHA;Lo;0;L;;;;;N;;;;; 112CC;KHUDAWADI LETTER NNA;Lo;0;L;;;;;N;;;;; 112CD;KHUDAWADI LETTER TA;Lo;0;L;;;;;N;;;;; 112CE;KHUDAWADI LETTER THA;Lo;0;L;;;;;N;;;;; 112CF;KHUDAWADI LETTER DA;Lo;0;L;;;;;N;;;;; 112D0;KHUDAWADI LETTER DHA;Lo;0;L;;;;;N;;;;; 112D1;KHUDAWADI LETTER NA;Lo;0;L;;;;;N;;;;; 112D2;KHUDAWADI LETTER PA;Lo;0;L;;;;;N;;;;; 112D3;KHUDAWADI LETTER PHA;Lo;0;L;;;;;N;;;;; 112D4;KHUDAWADI LETTER BA;Lo;0;L;;;;;N;;;;; 112D5;KHUDAWADI LETTER BBA;Lo;0;L;;;;;N;;;;; 112D6;KHUDAWADI LETTER BHA;Lo;0;L;;;;;N;;;;; 112D7;KHUDAWADI LETTER MA;Lo;0;L;;;;;N;;;;; 112D8;KHUDAWADI LETTER YA;Lo;0;L;;;;;N;;;;; 112D9;KHUDAWADI LETTER RA;Lo;0;L;;;;;N;;;;; 112DA;KHUDAWADI LETTER LA;Lo;0;L;;;;;N;;;;; 112DB;KHUDAWADI LETTER VA;Lo;0;L;;;;;N;;;;; 112DC;KHUDAWADI LETTER SHA;Lo;0;L;;;;;N;;;;; 112DD;KHUDAWADI LETTER SA;Lo;0;L;;;;;N;;;;; 112DE;KHUDAWADI LETTER HA;Lo;0;L;;;;;N;;;;; 112DF;KHUDAWADI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; 112E0;KHUDAWADI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 112E1;KHUDAWADI VOWEL SIGN I;Mc;0;L;;;;;N;;;;; 112E2;KHUDAWADI VOWEL SIGN II;Mc;0;L;;;;;N;;;;; 112E3;KHUDAWADI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 112E4;KHUDAWADI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 112E5;KHUDAWADI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; 112E6;KHUDAWADI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; 112E7;KHUDAWADI VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; 112E8;KHUDAWADI VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;; 112E9;KHUDAWADI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; 112EA;KHUDAWADI SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 112F0;KHUDAWADI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 112F1;KHUDAWADI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 112F2;KHUDAWADI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 112F3;KHUDAWADI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 112F4;KHUDAWADI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 112F5;KHUDAWADI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 112F6;KHUDAWADI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 112F7;KHUDAWADI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 112F8;KHUDAWADI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 112F9;KHUDAWADI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 11300;GRANTHA SIGN COMBINING ANUSVARA ABOVE;Mn;0;NSM;;;;;N;;;;; 11301;GRANTHA SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; 11302;GRANTHA SIGN ANUSVARA;Mc;0;L;;;;;N;;;;; 11303;GRANTHA SIGN VISARGA;Mc;0;L;;;;;N;;;;; 11305;GRANTHA LETTER A;Lo;0;L;;;;;N;;;;; 11306;GRANTHA LETTER AA;Lo;0;L;;;;;N;;;;; 11307;GRANTHA LETTER I;Lo;0;L;;;;;N;;;;; 11308;GRANTHA LETTER II;Lo;0;L;;;;;N;;;;; 11309;GRANTHA LETTER U;Lo;0;L;;;;;N;;;;; 1130A;GRANTHA LETTER UU;Lo;0;L;;;;;N;;;;; 1130B;GRANTHA LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; 1130C;GRANTHA LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; 1130F;GRANTHA LETTER EE;Lo;0;L;;;;;N;;;;; 11310;GRANTHA LETTER AI;Lo;0;L;;;;;N;;;;; 11313;GRANTHA LETTER OO;Lo;0;L;;;;;N;;;;; 11314;GRANTHA LETTER AU;Lo;0;L;;;;;N;;;;; 11315;GRANTHA LETTER KA;Lo;0;L;;;;;N;;;;; 11316;GRANTHA LETTER KHA;Lo;0;L;;;;;N;;;;; 11317;GRANTHA LETTER GA;Lo;0;L;;;;;N;;;;; 11318;GRANTHA LETTER GHA;Lo;0;L;;;;;N;;;;; 11319;GRANTHA LETTER NGA;Lo;0;L;;;;;N;;;;; 1131A;GRANTHA LETTER CA;Lo;0;L;;;;;N;;;;; 1131B;GRANTHA LETTER CHA;Lo;0;L;;;;;N;;;;; 1131C;GRANTHA LETTER JA;Lo;0;L;;;;;N;;;;; 1131D;GRANTHA LETTER JHA;Lo;0;L;;;;;N;;;;; 1131E;GRANTHA LETTER NYA;Lo;0;L;;;;;N;;;;; 1131F;GRANTHA LETTER TTA;Lo;0;L;;;;;N;;;;; 11320;GRANTHA LETTER TTHA;Lo;0;L;;;;;N;;;;; 11321;GRANTHA LETTER DDA;Lo;0;L;;;;;N;;;;; 11322;GRANTHA LETTER DDHA;Lo;0;L;;;;;N;;;;; 11323;GRANTHA LETTER NNA;Lo;0;L;;;;;N;;;;; 11324;GRANTHA LETTER TA;Lo;0;L;;;;;N;;;;; 11325;GRANTHA LETTER THA;Lo;0;L;;;;;N;;;;; 11326;GRANTHA LETTER DA;Lo;0;L;;;;;N;;;;; 11327;GRANTHA LETTER DHA;Lo;0;L;;;;;N;;;;; 11328;GRANTHA LETTER NA;Lo;0;L;;;;;N;;;;; 1132A;GRANTHA LETTER PA;Lo;0;L;;;;;N;;;;; 1132B;GRANTHA LETTER PHA;Lo;0;L;;;;;N;;;;; 1132C;GRANTHA LETTER BA;Lo;0;L;;;;;N;;;;; 1132D;GRANTHA LETTER BHA;Lo;0;L;;;;;N;;;;; 1132E;GRANTHA LETTER MA;Lo;0;L;;;;;N;;;;; 1132F;GRANTHA LETTER YA;Lo;0;L;;;;;N;;;;; 11330;GRANTHA LETTER RA;Lo;0;L;;;;;N;;;;; 11332;GRANTHA LETTER LA;Lo;0;L;;;;;N;;;;; 11333;GRANTHA LETTER LLA;Lo;0;L;;;;;N;;;;; 11335;GRANTHA LETTER VA;Lo;0;L;;;;;N;;;;; 11336;GRANTHA LETTER SHA;Lo;0;L;;;;;N;;;;; 11337;GRANTHA LETTER SSA;Lo;0;L;;;;;N;;;;; 11338;GRANTHA LETTER SA;Lo;0;L;;;;;N;;;;; 11339;GRANTHA LETTER HA;Lo;0;L;;;;;N;;;;; 1133C;GRANTHA SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; 1133D;GRANTHA SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; 1133E;GRANTHA VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 1133F;GRANTHA VOWEL SIGN I;Mc;0;L;;;;;N;;;;; 11340;GRANTHA VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; 11341;GRANTHA VOWEL SIGN U;Mc;0;L;;;;;N;;;;; 11342;GRANTHA VOWEL SIGN UU;Mc;0;L;;;;;N;;;;; 11343;GRANTHA VOWEL SIGN VOCALIC R;Mc;0;L;;;;;N;;;;; 11344;GRANTHA VOWEL SIGN VOCALIC RR;Mc;0;L;;;;;N;;;;; 11347;GRANTHA VOWEL SIGN EE;Mc;0;L;;;;;N;;;;; 11348;GRANTHA VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; 1134B;GRANTHA VOWEL SIGN OO;Mc;0;L;11347 1133E;;;;N;;;;; 1134C;GRANTHA VOWEL SIGN AU;Mc;0;L;11347 11357;;;;N;;;;; 1134D;GRANTHA SIGN VIRAMA;Mc;9;L;;;;;N;;;;; 11350;GRANTHA OM;Lo;0;L;;;;;N;;;;; 11357;GRANTHA AU LENGTH MARK;Mc;0;L;;;;;N;;;;; 1135D;GRANTHA SIGN PLUTA;Lo;0;L;;;;;N;;;;; 1135E;GRANTHA LETTER VEDIC ANUSVARA;Lo;0;L;;;;;N;;;;; 1135F;GRANTHA LETTER VEDIC DOUBLE ANUSVARA;Lo;0;L;;;;;N;;;;; 11360;GRANTHA LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; 11361;GRANTHA LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; 11362;GRANTHA VOWEL SIGN VOCALIC L;Mc;0;L;;;;;N;;;;; 11363;GRANTHA VOWEL SIGN VOCALIC LL;Mc;0;L;;;;;N;;;;; 11366;COMBINING GRANTHA DIGIT ZERO;Mn;230;NSM;;;;;N;;;;; 11367;COMBINING GRANTHA DIGIT ONE;Mn;230;NSM;;;;;N;;;;; 11368;COMBINING GRANTHA DIGIT TWO;Mn;230;NSM;;;;;N;;;;; 11369;COMBINING GRANTHA DIGIT THREE;Mn;230;NSM;;;;;N;;;;; 1136A;COMBINING GRANTHA DIGIT FOUR;Mn;230;NSM;;;;;N;;;;; 1136B;COMBINING GRANTHA DIGIT FIVE;Mn;230;NSM;;;;;N;;;;; 1136C;COMBINING GRANTHA DIGIT SIX;Mn;230;NSM;;;;;N;;;;; 11370;COMBINING GRANTHA LETTER A;Mn;230;NSM;;;;;N;;;;; 11371;COMBINING GRANTHA LETTER KA;Mn;230;NSM;;;;;N;;;;; 11372;COMBINING GRANTHA LETTER NA;Mn;230;NSM;;;;;N;;;;; 11373;COMBINING GRANTHA LETTER VI;Mn;230;NSM;;;;;N;;;;; 11374;COMBINING GRANTHA LETTER PA;Mn;230;NSM;;;;;N;;;;; 11400;NEWA LETTER A;Lo;0;L;;;;;N;;;;; 11401;NEWA LETTER AA;Lo;0;L;;;;;N;;;;; 11402;NEWA LETTER I;Lo;0;L;;;;;N;;;;; 11403;NEWA LETTER II;Lo;0;L;;;;;N;;;;; 11404;NEWA LETTER U;Lo;0;L;;;;;N;;;;; 11405;NEWA LETTER UU;Lo;0;L;;;;;N;;;;; 11406;NEWA LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; 11407;NEWA LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; 11408;NEWA LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; 11409;NEWA LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; 1140A;NEWA LETTER E;Lo;0;L;;;;;N;;;;; 1140B;NEWA LETTER AI;Lo;0;L;;;;;N;;;;; 1140C;NEWA LETTER O;Lo;0;L;;;;;N;;;;; 1140D;NEWA LETTER AU;Lo;0;L;;;;;N;;;;; 1140E;NEWA LETTER KA;Lo;0;L;;;;;N;;;;; 1140F;NEWA LETTER KHA;Lo;0;L;;;;;N;;;;; 11410;NEWA LETTER GA;Lo;0;L;;;;;N;;;;; 11411;NEWA LETTER GHA;Lo;0;L;;;;;N;;;;; 11412;NEWA LETTER NGA;Lo;0;L;;;;;N;;;;; 11413;NEWA LETTER NGHA;Lo;0;L;;;;;N;;;;; 11414;NEWA LETTER CA;Lo;0;L;;;;;N;;;;; 11415;NEWA LETTER CHA;Lo;0;L;;;;;N;;;;; 11416;NEWA LETTER JA;Lo;0;L;;;;;N;;;;; 11417;NEWA LETTER JHA;Lo;0;L;;;;;N;;;;; 11418;NEWA LETTER NYA;Lo;0;L;;;;;N;;;;; 11419;NEWA LETTER NYHA;Lo;0;L;;;;;N;;;;; 1141A;NEWA LETTER TTA;Lo;0;L;;;;;N;;;;; 1141B;NEWA LETTER TTHA;Lo;0;L;;;;;N;;;;; 1141C;NEWA LETTER DDA;Lo;0;L;;;;;N;;;;; 1141D;NEWA LETTER DDHA;Lo;0;L;;;;;N;;;;; 1141E;NEWA LETTER NNA;Lo;0;L;;;;;N;;;;; 1141F;NEWA LETTER TA;Lo;0;L;;;;;N;;;;; 11420;NEWA LETTER THA;Lo;0;L;;;;;N;;;;; 11421;NEWA LETTER DA;Lo;0;L;;;;;N;;;;; 11422;NEWA LETTER DHA;Lo;0;L;;;;;N;;;;; 11423;NEWA LETTER NA;Lo;0;L;;;;;N;;;;; 11424;NEWA LETTER NHA;Lo;0;L;;;;;N;;;;; 11425;NEWA LETTER PA;Lo;0;L;;;;;N;;;;; 11426;NEWA LETTER PHA;Lo;0;L;;;;;N;;;;; 11427;NEWA LETTER BA;Lo;0;L;;;;;N;;;;; 11428;NEWA LETTER BHA;Lo;0;L;;;;;N;;;;; 11429;NEWA LETTER MA;Lo;0;L;;;;;N;;;;; 1142A;NEWA LETTER MHA;Lo;0;L;;;;;N;;;;; 1142B;NEWA LETTER YA;Lo;0;L;;;;;N;;;;; 1142C;NEWA LETTER RA;Lo;0;L;;;;;N;;;;; 1142D;NEWA LETTER RHA;Lo;0;L;;;;;N;;;;; 1142E;NEWA LETTER LA;Lo;0;L;;;;;N;;;;; 1142F;NEWA LETTER LHA;Lo;0;L;;;;;N;;;;; 11430;NEWA LETTER WA;Lo;0;L;;;;;N;;;;; 11431;NEWA LETTER SHA;Lo;0;L;;;;;N;;;;; 11432;NEWA LETTER SSA;Lo;0;L;;;;;N;;;;; 11433;NEWA LETTER SA;Lo;0;L;;;;;N;;;;; 11434;NEWA LETTER HA;Lo;0;L;;;;;N;;;;; 11435;NEWA VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 11436;NEWA VOWEL SIGN I;Mc;0;L;;;;;N;;;;; 11437;NEWA VOWEL SIGN II;Mc;0;L;;;;;N;;;;; 11438;NEWA VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 11439;NEWA VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 1143A;NEWA VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; 1143B;NEWA VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; 1143C;NEWA VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; 1143D;NEWA VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; 1143E;NEWA VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; 1143F;NEWA VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; 11440;NEWA VOWEL SIGN O;Mc;0;L;;;;;N;;;;; 11441;NEWA VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; 11442;NEWA SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 11443;NEWA SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; 11444;NEWA SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; 11445;NEWA SIGN VISARGA;Mc;0;L;;;;;N;;;;; 11446;NEWA SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; 11447;NEWA SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; 11448;NEWA SIGN FINAL ANUSVARA;Lo;0;L;;;;;N;;;;; 11449;NEWA OM;Lo;0;L;;;;;N;;;;; 1144A;NEWA SIDDHI;Lo;0;L;;;;;N;;;;; 1144B;NEWA DANDA;Po;0;L;;;;;N;;;;; 1144C;NEWA DOUBLE DANDA;Po;0;L;;;;;N;;;;; 1144D;NEWA COMMA;Po;0;L;;;;;N;;;;; 1144E;NEWA GAP FILLER;Po;0;L;;;;;N;;;;; 1144F;NEWA ABBREVIATION SIGN;Po;0;L;;;;;N;;;;; 11450;NEWA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 11451;NEWA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 11452;NEWA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 11453;NEWA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 11454;NEWA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 11455;NEWA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 11456;NEWA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 11457;NEWA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 11458;NEWA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 11459;NEWA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 1145B;NEWA PLACEHOLDER MARK;Po;0;L;;;;;N;;;;; 1145D;NEWA INSERTION SIGN;Po;0;L;;;;;N;;;;; 11480;TIRHUTA ANJI;Lo;0;L;;;;;N;;;;; 11481;TIRHUTA LETTER A;Lo;0;L;;;;;N;;;;; 11482;TIRHUTA LETTER AA;Lo;0;L;;;;;N;;;;; 11483;TIRHUTA LETTER I;Lo;0;L;;;;;N;;;;; 11484;TIRHUTA LETTER II;Lo;0;L;;;;;N;;;;; 11485;TIRHUTA LETTER U;Lo;0;L;;;;;N;;;;; 11486;TIRHUTA LETTER UU;Lo;0;L;;;;;N;;;;; 11487;TIRHUTA LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; 11488;TIRHUTA LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; 11489;TIRHUTA LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; 1148A;TIRHUTA LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; 1148B;TIRHUTA LETTER E;Lo;0;L;;;;;N;;;;; 1148C;TIRHUTA LETTER AI;Lo;0;L;;;;;N;;;;; 1148D;TIRHUTA LETTER O;Lo;0;L;;;;;N;;;;; 1148E;TIRHUTA LETTER AU;Lo;0;L;;;;;N;;;;; 1148F;TIRHUTA LETTER KA;Lo;0;L;;;;;N;;;;; 11490;TIRHUTA LETTER KHA;Lo;0;L;;;;;N;;;;; 11491;TIRHUTA LETTER GA;Lo;0;L;;;;;N;;;;; 11492;TIRHUTA LETTER GHA;Lo;0;L;;;;;N;;;;; 11493;TIRHUTA LETTER NGA;Lo;0;L;;;;;N;;;;; 11494;TIRHUTA LETTER CA;Lo;0;L;;;;;N;;;;; 11495;TIRHUTA LETTER CHA;Lo;0;L;;;;;N;;;;; 11496;TIRHUTA LETTER JA;Lo;0;L;;;;;N;;;;; 11497;TIRHUTA LETTER JHA;Lo;0;L;;;;;N;;;;; 11498;TIRHUTA LETTER NYA;Lo;0;L;;;;;N;;;;; 11499;TIRHUTA LETTER TTA;Lo;0;L;;;;;N;;;;; 1149A;TIRHUTA LETTER TTHA;Lo;0;L;;;;;N;;;;; 1149B;TIRHUTA LETTER DDA;Lo;0;L;;;;;N;;;;; 1149C;TIRHUTA LETTER DDHA;Lo;0;L;;;;;N;;;;; 1149D;TIRHUTA LETTER NNA;Lo;0;L;;;;;N;;;;; 1149E;TIRHUTA LETTER TA;Lo;0;L;;;;;N;;;;; 1149F;TIRHUTA LETTER THA;Lo;0;L;;;;;N;;;;; 114A0;TIRHUTA LETTER DA;Lo;0;L;;;;;N;;;;; 114A1;TIRHUTA LETTER DHA;Lo;0;L;;;;;N;;;;; 114A2;TIRHUTA LETTER NA;Lo;0;L;;;;;N;;;;; 114A3;TIRHUTA LETTER PA;Lo;0;L;;;;;N;;;;; 114A4;TIRHUTA LETTER PHA;Lo;0;L;;;;;N;;;;; 114A5;TIRHUTA LETTER BA;Lo;0;L;;;;;N;;;;; 114A6;TIRHUTA LETTER BHA;Lo;0;L;;;;;N;;;;; 114A7;TIRHUTA LETTER MA;Lo;0;L;;;;;N;;;;; 114A8;TIRHUTA LETTER YA;Lo;0;L;;;;;N;;;;; 114A9;TIRHUTA LETTER RA;Lo;0;L;;;;;N;;;;; 114AA;TIRHUTA LETTER LA;Lo;0;L;;;;;N;;;;; 114AB;TIRHUTA LETTER VA;Lo;0;L;;;;;N;;;;; 114AC;TIRHUTA LETTER SHA;Lo;0;L;;;;;N;;;;; 114AD;TIRHUTA LETTER SSA;Lo;0;L;;;;;N;;;;; 114AE;TIRHUTA LETTER SA;Lo;0;L;;;;;N;;;;; 114AF;TIRHUTA LETTER HA;Lo;0;L;;;;;N;;;;; 114B0;TIRHUTA VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 114B1;TIRHUTA VOWEL SIGN I;Mc;0;L;;;;;N;;;;; 114B2;TIRHUTA VOWEL SIGN II;Mc;0;L;;;;;N;;;;; 114B3;TIRHUTA VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 114B4;TIRHUTA VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 114B5;TIRHUTA VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; 114B6;TIRHUTA VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; 114B7;TIRHUTA VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; 114B8;TIRHUTA VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; 114B9;TIRHUTA VOWEL SIGN E;Mc;0;L;;;;;N;;;;; 114BA;TIRHUTA VOWEL SIGN SHORT E;Mn;0;NSM;;;;;N;;;;; 114BB;TIRHUTA VOWEL SIGN AI;Mc;0;L;114B9 114BA;;;;N;;;;; 114BC;TIRHUTA VOWEL SIGN O;Mc;0;L;114B9 114B0;;;;N;;;;; 114BD;TIRHUTA VOWEL SIGN SHORT O;Mc;0;L;;;;;N;;;;; 114BE;TIRHUTA VOWEL SIGN AU;Mc;0;L;114B9 114BD;;;;N;;;;; 114BF;TIRHUTA SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; 114C0;TIRHUTA SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; 114C1;TIRHUTA SIGN VISARGA;Mc;0;L;;;;;N;;;;; 114C2;TIRHUTA SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 114C3;TIRHUTA SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; 114C4;TIRHUTA SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; 114C5;TIRHUTA GVANG;Lo;0;L;;;;;N;;;;; 114C6;TIRHUTA ABBREVIATION SIGN;Po;0;L;;;;;N;;;;; 114C7;TIRHUTA OM;Lo;0;L;;;;;N;;;;; 114D0;TIRHUTA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 114D1;TIRHUTA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 114D2;TIRHUTA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 114D3;TIRHUTA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 114D4;TIRHUTA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 114D5;TIRHUTA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 114D6;TIRHUTA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 114D7;TIRHUTA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 114D8;TIRHUTA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 114D9;TIRHUTA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 11580;SIDDHAM LETTER A;Lo;0;L;;;;;N;;;;; 11581;SIDDHAM LETTER AA;Lo;0;L;;;;;N;;;;; 11582;SIDDHAM LETTER I;Lo;0;L;;;;;N;;;;; 11583;SIDDHAM LETTER II;Lo;0;L;;;;;N;;;;; 11584;SIDDHAM LETTER U;Lo;0;L;;;;;N;;;;; 11585;SIDDHAM LETTER UU;Lo;0;L;;;;;N;;;;; 11586;SIDDHAM LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; 11587;SIDDHAM LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; 11588;SIDDHAM LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; 11589;SIDDHAM LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; 1158A;SIDDHAM LETTER E;Lo;0;L;;;;;N;;;;; 1158B;SIDDHAM LETTER AI;Lo;0;L;;;;;N;;;;; 1158C;SIDDHAM LETTER O;Lo;0;L;;;;;N;;;;; 1158D;SIDDHAM LETTER AU;Lo;0;L;;;;;N;;;;; 1158E;SIDDHAM LETTER KA;Lo;0;L;;;;;N;;;;; 1158F;SIDDHAM LETTER KHA;Lo;0;L;;;;;N;;;;; 11590;SIDDHAM LETTER GA;Lo;0;L;;;;;N;;;;; 11591;SIDDHAM LETTER GHA;Lo;0;L;;;;;N;;;;; 11592;SIDDHAM LETTER NGA;Lo;0;L;;;;;N;;;;; 11593;SIDDHAM LETTER CA;Lo;0;L;;;;;N;;;;; 11594;SIDDHAM LETTER CHA;Lo;0;L;;;;;N;;;;; 11595;SIDDHAM LETTER JA;Lo;0;L;;;;;N;;;;; 11596;SIDDHAM LETTER JHA;Lo;0;L;;;;;N;;;;; 11597;SIDDHAM LETTER NYA;Lo;0;L;;;;;N;;;;; 11598;SIDDHAM LETTER TTA;Lo;0;L;;;;;N;;;;; 11599;SIDDHAM LETTER TTHA;Lo;0;L;;;;;N;;;;; 1159A;SIDDHAM LETTER DDA;Lo;0;L;;;;;N;;;;; 1159B;SIDDHAM LETTER DDHA;Lo;0;L;;;;;N;;;;; 1159C;SIDDHAM LETTER NNA;Lo;0;L;;;;;N;;;;; 1159D;SIDDHAM LETTER TA;Lo;0;L;;;;;N;;;;; 1159E;SIDDHAM LETTER THA;Lo;0;L;;;;;N;;;;; 1159F;SIDDHAM LETTER DA;Lo;0;L;;;;;N;;;;; 115A0;SIDDHAM LETTER DHA;Lo;0;L;;;;;N;;;;; 115A1;SIDDHAM LETTER NA;Lo;0;L;;;;;N;;;;; 115A2;SIDDHAM LETTER PA;Lo;0;L;;;;;N;;;;; 115A3;SIDDHAM LETTER PHA;Lo;0;L;;;;;N;;;;; 115A4;SIDDHAM LETTER BA;Lo;0;L;;;;;N;;;;; 115A5;SIDDHAM LETTER BHA;Lo;0;L;;;;;N;;;;; 115A6;SIDDHAM LETTER MA;Lo;0;L;;;;;N;;;;; 115A7;SIDDHAM LETTER YA;Lo;0;L;;;;;N;;;;; 115A8;SIDDHAM LETTER RA;Lo;0;L;;;;;N;;;;; 115A9;SIDDHAM LETTER LA;Lo;0;L;;;;;N;;;;; 115AA;SIDDHAM LETTER VA;Lo;0;L;;;;;N;;;;; 115AB;SIDDHAM LETTER SHA;Lo;0;L;;;;;N;;;;; 115AC;SIDDHAM LETTER SSA;Lo;0;L;;;;;N;;;;; 115AD;SIDDHAM LETTER SA;Lo;0;L;;;;;N;;;;; 115AE;SIDDHAM LETTER HA;Lo;0;L;;;;;N;;;;; 115AF;SIDDHAM VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 115B0;SIDDHAM VOWEL SIGN I;Mc;0;L;;;;;N;;;;; 115B1;SIDDHAM VOWEL SIGN II;Mc;0;L;;;;;N;;;;; 115B2;SIDDHAM VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 115B3;SIDDHAM VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 115B4;SIDDHAM VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; 115B5;SIDDHAM VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; 115B8;SIDDHAM VOWEL SIGN E;Mc;0;L;;;;;N;;;;; 115B9;SIDDHAM VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; 115BA;SIDDHAM VOWEL SIGN O;Mc;0;L;115B8 115AF;;;;N;;;;; 115BB;SIDDHAM VOWEL SIGN AU;Mc;0;L;115B9 115AF;;;;N;;;;; 115BC;SIDDHAM SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; 115BD;SIDDHAM SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; 115BE;SIDDHAM SIGN VISARGA;Mc;0;L;;;;;N;;;;; 115BF;SIDDHAM SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 115C0;SIDDHAM SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; 115C1;SIDDHAM SIGN SIDDHAM;Po;0;L;;;;;N;;;;; 115C2;SIDDHAM DANDA;Po;0;L;;;;;N;;;;; 115C3;SIDDHAM DOUBLE DANDA;Po;0;L;;;;;N;;;;; 115C4;SIDDHAM SEPARATOR DOT;Po;0;L;;;;;N;;;;; 115C5;SIDDHAM SEPARATOR BAR;Po;0;L;;;;;N;;;;; 115C6;SIDDHAM REPETITION MARK-1;Po;0;L;;;;;N;;;;; 115C7;SIDDHAM REPETITION MARK-2;Po;0;L;;;;;N;;;;; 115C8;SIDDHAM REPETITION MARK-3;Po;0;L;;;;;N;;;;; 115C9;SIDDHAM END OF TEXT MARK;Po;0;L;;;;;N;;;;; 115CA;SIDDHAM SECTION MARK WITH TRIDENT AND U-SHAPED ORNAMENTS;Po;0;L;;;;;N;;;;; 115CB;SIDDHAM SECTION MARK WITH TRIDENT AND DOTTED CRESCENTS;Po;0;L;;;;;N;;;;; 115CC;SIDDHAM SECTION MARK WITH RAYS AND DOTTED CRESCENTS;Po;0;L;;;;;N;;;;; 115CD;SIDDHAM SECTION MARK WITH RAYS AND DOTTED DOUBLE CRESCENTS;Po;0;L;;;;;N;;;;; 115CE;SIDDHAM SECTION MARK WITH RAYS AND DOTTED TRIPLE CRESCENTS;Po;0;L;;;;;N;;;;; 115CF;SIDDHAM SECTION MARK DOUBLE RING;Po;0;L;;;;;N;;;;; 115D0;SIDDHAM SECTION MARK DOUBLE RING WITH RAYS;Po;0;L;;;;;N;;;;; 115D1;SIDDHAM SECTION MARK WITH DOUBLE CRESCENTS;Po;0;L;;;;;N;;;;; 115D2;SIDDHAM SECTION MARK WITH TRIPLE CRESCENTS;Po;0;L;;;;;N;;;;; 115D3;SIDDHAM SECTION MARK WITH QUADRUPLE CRESCENTS;Po;0;L;;;;;N;;;;; 115D4;SIDDHAM SECTION MARK WITH SEPTUPLE CRESCENTS;Po;0;L;;;;;N;;;;; 115D5;SIDDHAM SECTION MARK WITH CIRCLES AND RAYS;Po;0;L;;;;;N;;;;; 115D6;SIDDHAM SECTION MARK WITH CIRCLES AND TWO ENCLOSURES;Po;0;L;;;;;N;;;;; 115D7;SIDDHAM SECTION MARK WITH CIRCLES AND FOUR ENCLOSURES;Po;0;L;;;;;N;;;;; 115D8;SIDDHAM LETTER THREE-CIRCLE ALTERNATE I;Lo;0;L;;;;;N;;;;; 115D9;SIDDHAM LETTER TWO-CIRCLE ALTERNATE I;Lo;0;L;;;;;N;;;;; 115DA;SIDDHAM LETTER TWO-CIRCLE ALTERNATE II;Lo;0;L;;;;;N;;;;; 115DB;SIDDHAM LETTER ALTERNATE U;Lo;0;L;;;;;N;;;;; 115DC;SIDDHAM VOWEL SIGN ALTERNATE U;Mn;0;NSM;;;;;N;;;;; 115DD;SIDDHAM VOWEL SIGN ALTERNATE UU;Mn;0;NSM;;;;;N;;;;; 11600;MODI LETTER A;Lo;0;L;;;;;N;;;;; 11601;MODI LETTER AA;Lo;0;L;;;;;N;;;;; 11602;MODI LETTER I;Lo;0;L;;;;;N;;;;; 11603;MODI LETTER II;Lo;0;L;;;;;N;;;;; 11604;MODI LETTER U;Lo;0;L;;;;;N;;;;; 11605;MODI LETTER UU;Lo;0;L;;;;;N;;;;; 11606;MODI LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; 11607;MODI LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; 11608;MODI LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; 11609;MODI LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; 1160A;MODI LETTER E;Lo;0;L;;;;;N;;;;; 1160B;MODI LETTER AI;Lo;0;L;;;;;N;;;;; 1160C;MODI LETTER O;Lo;0;L;;;;;N;;;;; 1160D;MODI LETTER AU;Lo;0;L;;;;;N;;;;; 1160E;MODI LETTER KA;Lo;0;L;;;;;N;;;;; 1160F;MODI LETTER KHA;Lo;0;L;;;;;N;;;;; 11610;MODI LETTER GA;Lo;0;L;;;;;N;;;;; 11611;MODI LETTER GHA;Lo;0;L;;;;;N;;;;; 11612;MODI LETTER NGA;Lo;0;L;;;;;N;;;;; 11613;MODI LETTER CA;Lo;0;L;;;;;N;;;;; 11614;MODI LETTER CHA;Lo;0;L;;;;;N;;;;; 11615;MODI LETTER JA;Lo;0;L;;;;;N;;;;; 11616;MODI LETTER JHA;Lo;0;L;;;;;N;;;;; 11617;MODI LETTER NYA;Lo;0;L;;;;;N;;;;; 11618;MODI LETTER TTA;Lo;0;L;;;;;N;;;;; 11619;MODI LETTER TTHA;Lo;0;L;;;;;N;;;;; 1161A;MODI LETTER DDA;Lo;0;L;;;;;N;;;;; 1161B;MODI LETTER DDHA;Lo;0;L;;;;;N;;;;; 1161C;MODI LETTER NNA;Lo;0;L;;;;;N;;;;; 1161D;MODI LETTER TA;Lo;0;L;;;;;N;;;;; 1161E;MODI LETTER THA;Lo;0;L;;;;;N;;;;; 1161F;MODI LETTER DA;Lo;0;L;;;;;N;;;;; 11620;MODI LETTER DHA;Lo;0;L;;;;;N;;;;; 11621;MODI LETTER NA;Lo;0;L;;;;;N;;;;; 11622;MODI LETTER PA;Lo;0;L;;;;;N;;;;; 11623;MODI LETTER PHA;Lo;0;L;;;;;N;;;;; 11624;MODI LETTER BA;Lo;0;L;;;;;N;;;;; 11625;MODI LETTER BHA;Lo;0;L;;;;;N;;;;; 11626;MODI LETTER MA;Lo;0;L;;;;;N;;;;; 11627;MODI LETTER YA;Lo;0;L;;;;;N;;;;; 11628;MODI LETTER RA;Lo;0;L;;;;;N;;;;; 11629;MODI LETTER LA;Lo;0;L;;;;;N;;;;; 1162A;MODI LETTER VA;Lo;0;L;;;;;N;;;;; 1162B;MODI LETTER SHA;Lo;0;L;;;;;N;;;;; 1162C;MODI LETTER SSA;Lo;0;L;;;;;N;;;;; 1162D;MODI LETTER SA;Lo;0;L;;;;;N;;;;; 1162E;MODI LETTER HA;Lo;0;L;;;;;N;;;;; 1162F;MODI LETTER LLA;Lo;0;L;;;;;N;;;;; 11630;MODI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 11631;MODI VOWEL SIGN I;Mc;0;L;;;;;N;;;;; 11632;MODI VOWEL SIGN II;Mc;0;L;;;;;N;;;;; 11633;MODI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 11634;MODI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 11635;MODI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; 11636;MODI VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; 11637;MODI VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; 11638;MODI VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; 11639;MODI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; 1163A;MODI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; 1163B;MODI VOWEL SIGN O;Mc;0;L;;;;;N;;;;; 1163C;MODI VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; 1163D;MODI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; 1163E;MODI SIGN VISARGA;Mc;0;L;;;;;N;;;;; 1163F;MODI SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 11640;MODI SIGN ARDHACANDRA;Mn;0;NSM;;;;;N;;;;; 11641;MODI DANDA;Po;0;L;;;;;N;;;;; 11642;MODI DOUBLE DANDA;Po;0;L;;;;;N;;;;; 11643;MODI ABBREVIATION SIGN;Po;0;L;;;;;N;;;;; 11644;MODI SIGN HUVA;Lo;0;L;;;;;N;;;;; 11650;MODI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 11651;MODI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 11652;MODI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 11653;MODI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 11654;MODI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 11655;MODI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 11656;MODI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 11657;MODI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 11658;MODI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 11659;MODI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 11660;MONGOLIAN BIRGA WITH ORNAMENT;Po;0;ON;;;;;N;;;;; 11661;MONGOLIAN ROTATED BIRGA;Po;0;ON;;;;;N;;;;; 11662;MONGOLIAN DOUBLE BIRGA WITH ORNAMENT;Po;0;ON;;;;;N;;;;; 11663;MONGOLIAN TRIPLE BIRGA WITH ORNAMENT;Po;0;ON;;;;;N;;;;; 11664;MONGOLIAN BIRGA WITH DOUBLE ORNAMENT;Po;0;ON;;;;;N;;;;; 11665;MONGOLIAN ROTATED BIRGA WITH ORNAMENT;Po;0;ON;;;;;N;;;;; 11666;MONGOLIAN ROTATED BIRGA WITH DOUBLE ORNAMENT;Po;0;ON;;;;;N;;;;; 11667;MONGOLIAN INVERTED BIRGA;Po;0;ON;;;;;N;;;;; 11668;MONGOLIAN INVERTED BIRGA WITH DOUBLE ORNAMENT;Po;0;ON;;;;;N;;;;; 11669;MONGOLIAN SWIRL BIRGA;Po;0;ON;;;;;N;;;;; 1166A;MONGOLIAN SWIRL BIRGA WITH ORNAMENT;Po;0;ON;;;;;N;;;;; 1166B;MONGOLIAN SWIRL BIRGA WITH DOUBLE ORNAMENT;Po;0;ON;;;;;N;;;;; 1166C;MONGOLIAN TURNED SWIRL BIRGA WITH DOUBLE ORNAMENT;Po;0;ON;;;;;N;;;;; 11680;TAKRI LETTER A;Lo;0;L;;;;;N;;;;; 11681;TAKRI LETTER AA;Lo;0;L;;;;;N;;;;; 11682;TAKRI LETTER I;Lo;0;L;;;;;N;;;;; 11683;TAKRI LETTER II;Lo;0;L;;;;;N;;;;; 11684;TAKRI LETTER U;Lo;0;L;;;;;N;;;;; 11685;TAKRI LETTER UU;Lo;0;L;;;;;N;;;;; 11686;TAKRI LETTER E;Lo;0;L;;;;;N;;;;; 11687;TAKRI LETTER AI;Lo;0;L;;;;;N;;;;; 11688;TAKRI LETTER O;Lo;0;L;;;;;N;;;;; 11689;TAKRI LETTER AU;Lo;0;L;;;;;N;;;;; 1168A;TAKRI LETTER KA;Lo;0;L;;;;;N;;;;; 1168B;TAKRI LETTER KHA;Lo;0;L;;;;;N;;;;; 1168C;TAKRI LETTER GA;Lo;0;L;;;;;N;;;;; 1168D;TAKRI LETTER GHA;Lo;0;L;;;;;N;;;;; 1168E;TAKRI LETTER NGA;Lo;0;L;;;;;N;;;;; 1168F;TAKRI LETTER CA;Lo;0;L;;;;;N;;;;; 11690;TAKRI LETTER CHA;Lo;0;L;;;;;N;;;;; 11691;TAKRI LETTER JA;Lo;0;L;;;;;N;;;;; 11692;TAKRI LETTER JHA;Lo;0;L;;;;;N;;;;; 11693;TAKRI LETTER NYA;Lo;0;L;;;;;N;;;;; 11694;TAKRI LETTER TTA;Lo;0;L;;;;;N;;;;; 11695;TAKRI LETTER TTHA;Lo;0;L;;;;;N;;;;; 11696;TAKRI LETTER DDA;Lo;0;L;;;;;N;;;;; 11697;TAKRI LETTER DDHA;Lo;0;L;;;;;N;;;;; 11698;TAKRI LETTER NNA;Lo;0;L;;;;;N;;;;; 11699;TAKRI LETTER TA;Lo;0;L;;;;;N;;;;; 1169A;TAKRI LETTER THA;Lo;0;L;;;;;N;;;;; 1169B;TAKRI LETTER DA;Lo;0;L;;;;;N;;;;; 1169C;TAKRI LETTER DHA;Lo;0;L;;;;;N;;;;; 1169D;TAKRI LETTER NA;Lo;0;L;;;;;N;;;;; 1169E;TAKRI LETTER PA;Lo;0;L;;;;;N;;;;; 1169F;TAKRI LETTER PHA;Lo;0;L;;;;;N;;;;; 116A0;TAKRI LETTER BA;Lo;0;L;;;;;N;;;;; 116A1;TAKRI LETTER BHA;Lo;0;L;;;;;N;;;;; 116A2;TAKRI LETTER MA;Lo;0;L;;;;;N;;;;; 116A3;TAKRI LETTER YA;Lo;0;L;;;;;N;;;;; 116A4;TAKRI LETTER RA;Lo;0;L;;;;;N;;;;; 116A5;TAKRI LETTER LA;Lo;0;L;;;;;N;;;;; 116A6;TAKRI LETTER VA;Lo;0;L;;;;;N;;;;; 116A7;TAKRI LETTER SHA;Lo;0;L;;;;;N;;;;; 116A8;TAKRI LETTER SA;Lo;0;L;;;;;N;;;;; 116A9;TAKRI LETTER HA;Lo;0;L;;;;;N;;;;; 116AA;TAKRI LETTER RRA;Lo;0;L;;;;;N;;;;; 116AB;TAKRI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; 116AC;TAKRI SIGN VISARGA;Mc;0;L;;;;;N;;;;; 116AD;TAKRI VOWEL SIGN AA;Mn;0;NSM;;;;;N;;;;; 116AE;TAKRI VOWEL SIGN I;Mc;0;L;;;;;N;;;;; 116AF;TAKRI VOWEL SIGN II;Mc;0;L;;;;;N;;;;; 116B0;TAKRI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 116B1;TAKRI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 116B2;TAKRI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; 116B3;TAKRI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; 116B4;TAKRI VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; 116B5;TAKRI VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;; 116B6;TAKRI SIGN VIRAMA;Mc;9;L;;;;;N;;;;; 116B7;TAKRI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; 116C0;TAKRI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 116C1;TAKRI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 116C2;TAKRI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 116C3;TAKRI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 116C4;TAKRI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 116C5;TAKRI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 116C6;TAKRI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 116C7;TAKRI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 116C8;TAKRI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 116C9;TAKRI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 11700;AHOM LETTER KA;Lo;0;L;;;;;N;;;;; 11701;AHOM LETTER KHA;Lo;0;L;;;;;N;;;;; 11702;AHOM LETTER NGA;Lo;0;L;;;;;N;;;;; 11703;AHOM LETTER NA;Lo;0;L;;;;;N;;;;; 11704;AHOM LETTER TA;Lo;0;L;;;;;N;;;;; 11705;AHOM LETTER ALTERNATE TA;Lo;0;L;;;;;N;;;;; 11706;AHOM LETTER PA;Lo;0;L;;;;;N;;;;; 11707;AHOM LETTER PHA;Lo;0;L;;;;;N;;;;; 11708;AHOM LETTER BA;Lo;0;L;;;;;N;;;;; 11709;AHOM LETTER MA;Lo;0;L;;;;;N;;;;; 1170A;AHOM LETTER JA;Lo;0;L;;;;;N;;;;; 1170B;AHOM LETTER CHA;Lo;0;L;;;;;N;;;;; 1170C;AHOM LETTER THA;Lo;0;L;;;;;N;;;;; 1170D;AHOM LETTER RA;Lo;0;L;;;;;N;;;;; 1170E;AHOM LETTER LA;Lo;0;L;;;;;N;;;;; 1170F;AHOM LETTER SA;Lo;0;L;;;;;N;;;;; 11710;AHOM LETTER NYA;Lo;0;L;;;;;N;;;;; 11711;AHOM LETTER HA;Lo;0;L;;;;;N;;;;; 11712;AHOM LETTER A;Lo;0;L;;;;;N;;;;; 11713;AHOM LETTER DA;Lo;0;L;;;;;N;;;;; 11714;AHOM LETTER DHA;Lo;0;L;;;;;N;;;;; 11715;AHOM LETTER GA;Lo;0;L;;;;;N;;;;; 11716;AHOM LETTER ALTERNATE GA;Lo;0;L;;;;;N;;;;; 11717;AHOM LETTER GHA;Lo;0;L;;;;;N;;;;; 11718;AHOM LETTER BHA;Lo;0;L;;;;;N;;;;; 11719;AHOM LETTER JHA;Lo;0;L;;;;;N;;;;; 1171D;AHOM CONSONANT SIGN MEDIAL LA;Mn;0;NSM;;;;;N;;;;; 1171E;AHOM CONSONANT SIGN MEDIAL RA;Mn;0;NSM;;;;;N;;;;; 1171F;AHOM CONSONANT SIGN MEDIAL LIGATING RA;Mn;0;NSM;;;;;N;;;;; 11720;AHOM VOWEL SIGN A;Mc;0;L;;;;;N;;;;; 11721;AHOM VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 11722;AHOM VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; 11723;AHOM VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; 11724;AHOM VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 11725;AHOM VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 11726;AHOM VOWEL SIGN E;Mc;0;L;;;;;N;;;;; 11727;AHOM VOWEL SIGN AW;Mn;0;NSM;;;;;N;;;;; 11728;AHOM VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; 11729;AHOM VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; 1172A;AHOM VOWEL SIGN AM;Mn;0;NSM;;;;;N;;;;; 1172B;AHOM SIGN KILLER;Mn;9;NSM;;;;;N;;;;; 11730;AHOM DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 11731;AHOM DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 11732;AHOM DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 11733;AHOM DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 11734;AHOM DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 11735;AHOM DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 11736;AHOM DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 11737;AHOM DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 11738;AHOM DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 11739;AHOM DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 1173A;AHOM NUMBER TEN;No;0;L;;;;10;N;;;;; 1173B;AHOM NUMBER TWENTY;No;0;L;;;;20;N;;;;; 1173C;AHOM SIGN SMALL SECTION;Po;0;L;;;;;N;;;;; 1173D;AHOM SIGN SECTION;Po;0;L;;;;;N;;;;; 1173E;AHOM SIGN RULAI;Po;0;L;;;;;N;;;;; 1173F;AHOM SYMBOL VI;So;0;L;;;;;N;;;;; 118A0;WARANG CITI CAPITAL LETTER NGAA;Lu;0;L;;;;;N;;;;118C0; 118A1;WARANG CITI CAPITAL LETTER A;Lu;0;L;;;;;N;;;;118C1; 118A2;WARANG CITI CAPITAL LETTER WI;Lu;0;L;;;;;N;;;;118C2; 118A3;WARANG CITI CAPITAL LETTER YU;Lu;0;L;;;;;N;;;;118C3; 118A4;WARANG CITI CAPITAL LETTER YA;Lu;0;L;;;;;N;;;;118C4; 118A5;WARANG CITI CAPITAL LETTER YO;Lu;0;L;;;;;N;;;;118C5; 118A6;WARANG CITI CAPITAL LETTER II;Lu;0;L;;;;;N;;;;118C6; 118A7;WARANG CITI CAPITAL LETTER UU;Lu;0;L;;;;;N;;;;118C7; 118A8;WARANG CITI CAPITAL LETTER E;Lu;0;L;;;;;N;;;;118C8; 118A9;WARANG CITI CAPITAL LETTER O;Lu;0;L;;;;;N;;;;118C9; 118AA;WARANG CITI CAPITAL LETTER ANG;Lu;0;L;;;;;N;;;;118CA; 118AB;WARANG CITI CAPITAL LETTER GA;Lu;0;L;;;;;N;;;;118CB; 118AC;WARANG CITI CAPITAL LETTER KO;Lu;0;L;;;;;N;;;;118CC; 118AD;WARANG CITI CAPITAL LETTER ENY;Lu;0;L;;;;;N;;;;118CD; 118AE;WARANG CITI CAPITAL LETTER YUJ;Lu;0;L;;;;;N;;;;118CE; 118AF;WARANG CITI CAPITAL LETTER UC;Lu;0;L;;;;;N;;;;118CF; 118B0;WARANG CITI CAPITAL LETTER ENN;Lu;0;L;;;;;N;;;;118D0; 118B1;WARANG CITI CAPITAL LETTER ODD;Lu;0;L;;;;;N;;;;118D1; 118B2;WARANG CITI CAPITAL LETTER TTE;Lu;0;L;;;;;N;;;;118D2; 118B3;WARANG CITI CAPITAL LETTER NUNG;Lu;0;L;;;;;N;;;;118D3; 118B4;WARANG CITI CAPITAL LETTER DA;Lu;0;L;;;;;N;;;;118D4; 118B5;WARANG CITI CAPITAL LETTER AT;Lu;0;L;;;;;N;;;;118D5; 118B6;WARANG CITI CAPITAL LETTER AM;Lu;0;L;;;;;N;;;;118D6; 118B7;WARANG CITI CAPITAL LETTER BU;Lu;0;L;;;;;N;;;;118D7; 118B8;WARANG CITI CAPITAL LETTER PU;Lu;0;L;;;;;N;;;;118D8; 118B9;WARANG CITI CAPITAL LETTER HIYO;Lu;0;L;;;;;N;;;;118D9; 118BA;WARANG CITI CAPITAL LETTER HOLO;Lu;0;L;;;;;N;;;;118DA; 118BB;WARANG CITI CAPITAL LETTER HORR;Lu;0;L;;;;;N;;;;118DB; 118BC;WARANG CITI CAPITAL LETTER HAR;Lu;0;L;;;;;N;;;;118DC; 118BD;WARANG CITI CAPITAL LETTER SSUU;Lu;0;L;;;;;N;;;;118DD; 118BE;WARANG CITI CAPITAL LETTER SII;Lu;0;L;;;;;N;;;;118DE; 118BF;WARANG CITI CAPITAL LETTER VIYO;Lu;0;L;;;;;N;;;;118DF; 118C0;WARANG CITI SMALL LETTER NGAA;Ll;0;L;;;;;N;;;118A0;;118A0 118C1;WARANG CITI SMALL LETTER A;Ll;0;L;;;;;N;;;118A1;;118A1 118C2;WARANG CITI SMALL LETTER WI;Ll;0;L;;;;;N;;;118A2;;118A2 118C3;WARANG CITI SMALL LETTER YU;Ll;0;L;;;;;N;;;118A3;;118A3 118C4;WARANG CITI SMALL LETTER YA;Ll;0;L;;;;;N;;;118A4;;118A4 118C5;WARANG CITI SMALL LETTER YO;Ll;0;L;;;;;N;;;118A5;;118A5 118C6;WARANG CITI SMALL LETTER II;Ll;0;L;;;;;N;;;118A6;;118A6 118C7;WARANG CITI SMALL LETTER UU;Ll;0;L;;;;;N;;;118A7;;118A7 118C8;WARANG CITI SMALL LETTER E;Ll;0;L;;;;;N;;;118A8;;118A8 118C9;WARANG CITI SMALL LETTER O;Ll;0;L;;;;;N;;;118A9;;118A9 118CA;WARANG CITI SMALL LETTER ANG;Ll;0;L;;;;;N;;;118AA;;118AA 118CB;WARANG CITI SMALL LETTER GA;Ll;0;L;;;;;N;;;118AB;;118AB 118CC;WARANG CITI SMALL LETTER KO;Ll;0;L;;;;;N;;;118AC;;118AC 118CD;WARANG CITI SMALL LETTER ENY;Ll;0;L;;;;;N;;;118AD;;118AD 118CE;WARANG CITI SMALL LETTER YUJ;Ll;0;L;;;;;N;;;118AE;;118AE 118CF;WARANG CITI SMALL LETTER UC;Ll;0;L;;;;;N;;;118AF;;118AF 118D0;WARANG CITI SMALL LETTER ENN;Ll;0;L;;;;;N;;;118B0;;118B0 118D1;WARANG CITI SMALL LETTER ODD;Ll;0;L;;;;;N;;;118B1;;118B1 118D2;WARANG CITI SMALL LETTER TTE;Ll;0;L;;;;;N;;;118B2;;118B2 118D3;WARANG CITI SMALL LETTER NUNG;Ll;0;L;;;;;N;;;118B3;;118B3 118D4;WARANG CITI SMALL LETTER DA;Ll;0;L;;;;;N;;;118B4;;118B4 118D5;WARANG CITI SMALL LETTER AT;Ll;0;L;;;;;N;;;118B5;;118B5 118D6;WARANG CITI SMALL LETTER AM;Ll;0;L;;;;;N;;;118B6;;118B6 118D7;WARANG CITI SMALL LETTER BU;Ll;0;L;;;;;N;;;118B7;;118B7 118D8;WARANG CITI SMALL LETTER PU;Ll;0;L;;;;;N;;;118B8;;118B8 118D9;WARANG CITI SMALL LETTER HIYO;Ll;0;L;;;;;N;;;118B9;;118B9 118DA;WARANG CITI SMALL LETTER HOLO;Ll;0;L;;;;;N;;;118BA;;118BA 118DB;WARANG CITI SMALL LETTER HORR;Ll;0;L;;;;;N;;;118BB;;118BB 118DC;WARANG CITI SMALL LETTER HAR;Ll;0;L;;;;;N;;;118BC;;118BC 118DD;WARANG CITI SMALL LETTER SSUU;Ll;0;L;;;;;N;;;118BD;;118BD 118DE;WARANG CITI SMALL LETTER SII;Ll;0;L;;;;;N;;;118BE;;118BE 118DF;WARANG CITI SMALL LETTER VIYO;Ll;0;L;;;;;N;;;118BF;;118BF 118E0;WARANG CITI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 118E1;WARANG CITI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 118E2;WARANG CITI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 118E3;WARANG CITI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 118E4;WARANG CITI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 118E5;WARANG CITI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 118E6;WARANG CITI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 118E7;WARANG CITI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 118E8;WARANG CITI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 118E9;WARANG CITI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 118EA;WARANG CITI NUMBER TEN;No;0;L;;;;10;N;;;;; 118EB;WARANG CITI NUMBER TWENTY;No;0;L;;;;20;N;;;;; 118EC;WARANG CITI NUMBER THIRTY;No;0;L;;;;30;N;;;;; 118ED;WARANG CITI NUMBER FORTY;No;0;L;;;;40;N;;;;; 118EE;WARANG CITI NUMBER FIFTY;No;0;L;;;;50;N;;;;; 118EF;WARANG CITI NUMBER SIXTY;No;0;L;;;;60;N;;;;; 118F0;WARANG CITI NUMBER SEVENTY;No;0;L;;;;70;N;;;;; 118F1;WARANG CITI NUMBER EIGHTY;No;0;L;;;;80;N;;;;; 118F2;WARANG CITI NUMBER NINETY;No;0;L;;;;90;N;;;;; 118FF;WARANG CITI OM;Lo;0;L;;;;;N;;;;; 11AC0;PAU CIN HAU LETTER PA;Lo;0;L;;;;;N;;;;; 11AC1;PAU CIN HAU LETTER KA;Lo;0;L;;;;;N;;;;; 11AC2;PAU CIN HAU LETTER LA;Lo;0;L;;;;;N;;;;; 11AC3;PAU CIN HAU LETTER MA;Lo;0;L;;;;;N;;;;; 11AC4;PAU CIN HAU LETTER DA;Lo;0;L;;;;;N;;;;; 11AC5;PAU CIN HAU LETTER ZA;Lo;0;L;;;;;N;;;;; 11AC6;PAU CIN HAU LETTER VA;Lo;0;L;;;;;N;;;;; 11AC7;PAU CIN HAU LETTER NGA;Lo;0;L;;;;;N;;;;; 11AC8;PAU CIN HAU LETTER HA;Lo;0;L;;;;;N;;;;; 11AC9;PAU CIN HAU LETTER GA;Lo;0;L;;;;;N;;;;; 11ACA;PAU CIN HAU LETTER KHA;Lo;0;L;;;;;N;;;;; 11ACB;PAU CIN HAU LETTER SA;Lo;0;L;;;;;N;;;;; 11ACC;PAU CIN HAU LETTER BA;Lo;0;L;;;;;N;;;;; 11ACD;PAU CIN HAU LETTER CA;Lo;0;L;;;;;N;;;;; 11ACE;PAU CIN HAU LETTER TA;Lo;0;L;;;;;N;;;;; 11ACF;PAU CIN HAU LETTER THA;Lo;0;L;;;;;N;;;;; 11AD0;PAU CIN HAU LETTER NA;Lo;0;L;;;;;N;;;;; 11AD1;PAU CIN HAU LETTER PHA;Lo;0;L;;;;;N;;;;; 11AD2;PAU CIN HAU LETTER RA;Lo;0;L;;;;;N;;;;; 11AD3;PAU CIN HAU LETTER FA;Lo;0;L;;;;;N;;;;; 11AD4;PAU CIN HAU LETTER CHA;Lo;0;L;;;;;N;;;;; 11AD5;PAU CIN HAU LETTER A;Lo;0;L;;;;;N;;;;; 11AD6;PAU CIN HAU LETTER E;Lo;0;L;;;;;N;;;;; 11AD7;PAU CIN HAU LETTER I;Lo;0;L;;;;;N;;;;; 11AD8;PAU CIN HAU LETTER O;Lo;0;L;;;;;N;;;;; 11AD9;PAU CIN HAU LETTER U;Lo;0;L;;;;;N;;;;; 11ADA;PAU CIN HAU LETTER UA;Lo;0;L;;;;;N;;;;; 11ADB;PAU CIN HAU LETTER IA;Lo;0;L;;;;;N;;;;; 11ADC;PAU CIN HAU LETTER FINAL P;Lo;0;L;;;;;N;;;;; 11ADD;PAU CIN HAU LETTER FINAL K;Lo;0;L;;;;;N;;;;; 11ADE;PAU CIN HAU LETTER FINAL T;Lo;0;L;;;;;N;;;;; 11ADF;PAU CIN HAU LETTER FINAL M;Lo;0;L;;;;;N;;;;; 11AE0;PAU CIN HAU LETTER FINAL N;Lo;0;L;;;;;N;;;;; 11AE1;PAU CIN HAU LETTER FINAL L;Lo;0;L;;;;;N;;;;; 11AE2;PAU CIN HAU LETTER FINAL W;Lo;0;L;;;;;N;;;;; 11AE3;PAU CIN HAU LETTER FINAL NG;Lo;0;L;;;;;N;;;;; 11AE4;PAU CIN HAU LETTER FINAL Y;Lo;0;L;;;;;N;;;;; 11AE5;PAU CIN HAU RISING TONE LONG;Lo;0;L;;;;;N;;;;; 11AE6;PAU CIN HAU RISING TONE;Lo;0;L;;;;;N;;;;; 11AE7;PAU CIN HAU SANDHI GLOTTAL STOP;Lo;0;L;;;;;N;;;;; 11AE8;PAU CIN HAU RISING TONE LONG FINAL;Lo;0;L;;;;;N;;;;; 11AE9;PAU CIN HAU RISING TONE FINAL;Lo;0;L;;;;;N;;;;; 11AEA;PAU CIN HAU SANDHI GLOTTAL STOP FINAL;Lo;0;L;;;;;N;;;;; 11AEB;PAU CIN HAU SANDHI TONE LONG;Lo;0;L;;;;;N;;;;; 11AEC;PAU CIN HAU SANDHI TONE;Lo;0;L;;;;;N;;;;; 11AED;PAU CIN HAU SANDHI TONE LONG FINAL;Lo;0;L;;;;;N;;;;; 11AEE;PAU CIN HAU SANDHI TONE FINAL;Lo;0;L;;;;;N;;;;; 11AEF;PAU CIN HAU MID-LEVEL TONE;Lo;0;L;;;;;N;;;;; 11AF0;PAU CIN HAU GLOTTAL STOP VARIANT;Lo;0;L;;;;;N;;;;; 11AF1;PAU CIN HAU MID-LEVEL TONE LONG FINAL;Lo;0;L;;;;;N;;;;; 11AF2;PAU CIN HAU MID-LEVEL TONE FINAL;Lo;0;L;;;;;N;;;;; 11AF3;PAU CIN HAU LOW-FALLING TONE LONG;Lo;0;L;;;;;N;;;;; 11AF4;PAU CIN HAU LOW-FALLING TONE;Lo;0;L;;;;;N;;;;; 11AF5;PAU CIN HAU GLOTTAL STOP;Lo;0;L;;;;;N;;;;; 11AF6;PAU CIN HAU LOW-FALLING TONE LONG FINAL;Lo;0;L;;;;;N;;;;; 11AF7;PAU CIN HAU LOW-FALLING TONE FINAL;Lo;0;L;;;;;N;;;;; 11AF8;PAU CIN HAU GLOTTAL STOP FINAL;Lo;0;L;;;;;N;;;;; 11C00;BHAIKSUKI LETTER A;Lo;0;L;;;;;N;;;;; 11C01;BHAIKSUKI LETTER AA;Lo;0;L;;;;;N;;;;; 11C02;BHAIKSUKI LETTER I;Lo;0;L;;;;;N;;;;; 11C03;BHAIKSUKI LETTER II;Lo;0;L;;;;;N;;;;; 11C04;BHAIKSUKI LETTER U;Lo;0;L;;;;;N;;;;; 11C05;BHAIKSUKI LETTER UU;Lo;0;L;;;;;N;;;;; 11C06;BHAIKSUKI LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; 11C07;BHAIKSUKI LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; 11C08;BHAIKSUKI LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; 11C0A;BHAIKSUKI LETTER E;Lo;0;L;;;;;N;;;;; 11C0B;BHAIKSUKI LETTER AI;Lo;0;L;;;;;N;;;;; 11C0C;BHAIKSUKI LETTER O;Lo;0;L;;;;;N;;;;; 11C0D;BHAIKSUKI LETTER AU;Lo;0;L;;;;;N;;;;; 11C0E;BHAIKSUKI LETTER KA;Lo;0;L;;;;;N;;;;; 11C0F;BHAIKSUKI LETTER KHA;Lo;0;L;;;;;N;;;;; 11C10;BHAIKSUKI LETTER GA;Lo;0;L;;;;;N;;;;; 11C11;BHAIKSUKI LETTER GHA;Lo;0;L;;;;;N;;;;; 11C12;BHAIKSUKI LETTER NGA;Lo;0;L;;;;;N;;;;; 11C13;BHAIKSUKI LETTER CA;Lo;0;L;;;;;N;;;;; 11C14;BHAIKSUKI LETTER CHA;Lo;0;L;;;;;N;;;;; 11C15;BHAIKSUKI LETTER JA;Lo;0;L;;;;;N;;;;; 11C16;BHAIKSUKI LETTER JHA;Lo;0;L;;;;;N;;;;; 11C17;BHAIKSUKI LETTER NYA;Lo;0;L;;;;;N;;;;; 11C18;BHAIKSUKI LETTER TTA;Lo;0;L;;;;;N;;;;; 11C19;BHAIKSUKI LETTER TTHA;Lo;0;L;;;;;N;;;;; 11C1A;BHAIKSUKI LETTER DDA;Lo;0;L;;;;;N;;;;; 11C1B;BHAIKSUKI LETTER DDHA;Lo;0;L;;;;;N;;;;; 11C1C;BHAIKSUKI LETTER NNA;Lo;0;L;;;;;N;;;;; 11C1D;BHAIKSUKI LETTER TA;Lo;0;L;;;;;N;;;;; 11C1E;BHAIKSUKI LETTER THA;Lo;0;L;;;;;N;;;;; 11C1F;BHAIKSUKI LETTER DA;Lo;0;L;;;;;N;;;;; 11C20;BHAIKSUKI LETTER DHA;Lo;0;L;;;;;N;;;;; 11C21;BHAIKSUKI LETTER NA;Lo;0;L;;;;;N;;;;; 11C22;BHAIKSUKI LETTER PA;Lo;0;L;;;;;N;;;;; 11C23;BHAIKSUKI LETTER PHA;Lo;0;L;;;;;N;;;;; 11C24;BHAIKSUKI LETTER BA;Lo;0;L;;;;;N;;;;; 11C25;BHAIKSUKI LETTER BHA;Lo;0;L;;;;;N;;;;; 11C26;BHAIKSUKI LETTER MA;Lo;0;L;;;;;N;;;;; 11C27;BHAIKSUKI LETTER YA;Lo;0;L;;;;;N;;;;; 11C28;BHAIKSUKI LETTER RA;Lo;0;L;;;;;N;;;;; 11C29;BHAIKSUKI LETTER LA;Lo;0;L;;;;;N;;;;; 11C2A;BHAIKSUKI LETTER VA;Lo;0;L;;;;;N;;;;; 11C2B;BHAIKSUKI LETTER SHA;Lo;0;L;;;;;N;;;;; 11C2C;BHAIKSUKI LETTER SSA;Lo;0;L;;;;;N;;;;; 11C2D;BHAIKSUKI LETTER SA;Lo;0;L;;;;;N;;;;; 11C2E;BHAIKSUKI LETTER HA;Lo;0;L;;;;;N;;;;; 11C2F;BHAIKSUKI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 11C30;BHAIKSUKI VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; 11C31;BHAIKSUKI VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; 11C32;BHAIKSUKI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 11C33;BHAIKSUKI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; 11C34;BHAIKSUKI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; 11C35;BHAIKSUKI VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; 11C36;BHAIKSUKI VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; 11C38;BHAIKSUKI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; 11C39;BHAIKSUKI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; 11C3A;BHAIKSUKI VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; 11C3B;BHAIKSUKI VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;; 11C3C;BHAIKSUKI SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; 11C3D;BHAIKSUKI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; 11C3E;BHAIKSUKI SIGN VISARGA;Mc;0;L;;;;;N;;;;; 11C3F;BHAIKSUKI SIGN VIRAMA;Mn;9;L;;;;;N;;;;; 11C40;BHAIKSUKI SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; 11C41;BHAIKSUKI DANDA;Po;0;L;;;;;N;;;;; 11C42;BHAIKSUKI DOUBLE DANDA;Po;0;L;;;;;N;;;;; 11C43;BHAIKSUKI WORD SEPARATOR;Po;0;L;;;;;N;;;;; 11C44;BHAIKSUKI GAP FILLER-1;Po;0;L;;;;;N;;;;; 11C45;BHAIKSUKI GAP FILLER-2;Po;0;L;;;;;N;;;;; 11C50;BHAIKSUKI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 11C51;BHAIKSUKI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 11C52;BHAIKSUKI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 11C53;BHAIKSUKI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 11C54;BHAIKSUKI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 11C55;BHAIKSUKI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 11C56;BHAIKSUKI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 11C57;BHAIKSUKI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 11C58;BHAIKSUKI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 11C59;BHAIKSUKI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 11C5A;BHAIKSUKI NUMBER ONE;No;0;L;;;;1;N;;;;; 11C5B;BHAIKSUKI NUMBER TWO;No;0;L;;;;2;N;;;;; 11C5C;BHAIKSUKI NUMBER THREE;No;0;L;;;;3;N;;;;; 11C5D;BHAIKSUKI NUMBER FOUR;No;0;L;;;;4;N;;;;; 11C5E;BHAIKSUKI NUMBER FIVE;No;0;L;;;;5;N;;;;; 11C5F;BHAIKSUKI NUMBER SIX;No;0;L;;;;6;N;;;;; 11C60;BHAIKSUKI NUMBER SEVEN;No;0;L;;;;7;N;;;;; 11C61;BHAIKSUKI NUMBER EIGHT;No;0;L;;;;8;N;;;;; 11C62;BHAIKSUKI NUMBER NINE;No;0;L;;;;9;N;;;;; 11C63;BHAIKSUKI NUMBER TEN;No;0;L;;;;10;N;;;;; 11C64;BHAIKSUKI NUMBER TWENTY;No;0;L;;;;20;N;;;;; 11C65;BHAIKSUKI NUMBER THIRTY;No;0;L;;;;30;N;;;;; 11C66;BHAIKSUKI NUMBER FORTY;No;0;L;;;;40;N;;;;; 11C67;BHAIKSUKI NUMBER FIFTY;No;0;L;;;;50;N;;;;; 11C68;BHAIKSUKI NUMBER SIXTY;No;0;L;;;;60;N;;;;; 11C69;BHAIKSUKI NUMBER SEVENTY;No;0;L;;;;70;N;;;;; 11C6A;BHAIKSUKI NUMBER EIGHTY;No;0;L;;;;80;N;;;;; 11C6B;BHAIKSUKI NUMBER NINETY;No;0;L;;;;90;N;;;;; 11C6C;BHAIKSUKI HUNDREDS UNIT MARK;No;0;L;;;;100;N;;;;; 11C70;MARCHEN HEAD MARK;Po;0;L;;;;;N;;;;; 11C71;MARCHEN MARK SHAD;Po;0;L;;;;;N;;;;; 11C72;MARCHEN LETTER KA;Lo;0;L;;;;;N;;;;; 11C73;MARCHEN LETTER KHA;Lo;0;L;;;;;N;;;;; 11C74;MARCHEN LETTER GA;Lo;0;L;;;;;N;;;;; 11C75;MARCHEN LETTER NGA;Lo;0;L;;;;;N;;;;; 11C76;MARCHEN LETTER CA;Lo;0;L;;;;;N;;;;; 11C77;MARCHEN LETTER CHA;Lo;0;L;;;;;N;;;;; 11C78;MARCHEN LETTER JA;Lo;0;L;;;;;N;;;;; 11C79;MARCHEN LETTER NYA;Lo;0;L;;;;;N;;;;; 11C7A;MARCHEN LETTER TA;Lo;0;L;;;;;N;;;;; 11C7B;MARCHEN LETTER THA;Lo;0;L;;;;;N;;;;; 11C7C;MARCHEN LETTER DA;Lo;0;L;;;;;N;;;;; 11C7D;MARCHEN LETTER NA;Lo;0;L;;;;;N;;;;; 11C7E;MARCHEN LETTER PA;Lo;0;L;;;;;N;;;;; 11C7F;MARCHEN LETTER PHA;Lo;0;L;;;;;N;;;;; 11C80;MARCHEN LETTER BA;Lo;0;L;;;;;N;;;;; 11C81;MARCHEN LETTER MA;Lo;0;L;;;;;N;;;;; 11C82;MARCHEN LETTER TSA;Lo;0;L;;;;;N;;;;; 11C83;MARCHEN LETTER TSHA;Lo;0;L;;;;;N;;;;; 11C84;MARCHEN LETTER DZA;Lo;0;L;;;;;N;;;;; 11C85;MARCHEN LETTER WA;Lo;0;L;;;;;N;;;;; 11C86;MARCHEN LETTER ZHA;Lo;0;L;;;;;N;;;;; 11C87;MARCHEN LETTER ZA;Lo;0;L;;;;;N;;;;; 11C88;MARCHEN LETTER -A;Lo;0;L;;;;;N;;;;; 11C89;MARCHEN LETTER YA;Lo;0;L;;;;;N;;;;; 11C8A;MARCHEN LETTER RA;Lo;0;L;;;;;N;;;;; 11C8B;MARCHEN LETTER LA;Lo;0;L;;;;;N;;;;; 11C8C;MARCHEN LETTER SHA;Lo;0;L;;;;;N;;;;; 11C8D;MARCHEN LETTER SA;Lo;0;L;;;;;N;;;;; 11C8E;MARCHEN LETTER HA;Lo;0;L;;;;;N;;;;; 11C8F;MARCHEN LETTER A;Lo;0;L;;;;;N;;;;; 11C92;MARCHEN SUBJOINED LETTER KA;Mn;0;NSM;;;;;N;;;;; 11C93;MARCHEN SUBJOINED LETTER KHA;Mn;0;NSM;;;;;N;;;;; 11C94;MARCHEN SUBJOINED LETTER GA;Mn;0;NSM;;;;;N;;;;; 11C95;MARCHEN SUBJOINED LETTER NGA;Mn;0;NSM;;;;;N;;;;; 11C96;MARCHEN SUBJOINED LETTER CA;Mn;0;NSM;;;;;N;;;;; 11C97;MARCHEN SUBJOINED LETTER CHA;Mn;0;NSM;;;;;N;;;;; 11C98;MARCHEN SUBJOINED LETTER JA;Mn;0;NSM;;;;;N;;;;; 11C99;MARCHEN SUBJOINED LETTER NYA;Mn;0;NSM;;;;;N;;;;; 11C9A;MARCHEN SUBJOINED LETTER TA;Mn;0;NSM;;;;;N;;;;; 11C9B;MARCHEN SUBJOINED LETTER THA;Mn;0;NSM;;;;;N;;;;; 11C9C;MARCHEN SUBJOINED LETTER DA;Mn;0;NSM;;;;;N;;;;; 11C9D;MARCHEN SUBJOINED LETTER NA;Mn;0;NSM;;;;;N;;;;; 11C9E;MARCHEN SUBJOINED LETTER PA;Mn;0;NSM;;;;;N;;;;; 11C9F;MARCHEN SUBJOINED LETTER PHA;Mn;0;NSM;;;;;N;;;;; 11CA0;MARCHEN SUBJOINED LETTER BA;Mn;0;NSM;;;;;N;;;;; 11CA1;MARCHEN SUBJOINED LETTER MA;Mn;0;NSM;;;;;N;;;;; 11CA2;MARCHEN SUBJOINED LETTER TSA;Mn;0;NSM;;;;;N;;;;; 11CA3;MARCHEN SUBJOINED LETTER TSHA;Mn;0;NSM;;;;;N;;;;; 11CA4;MARCHEN SUBJOINED LETTER DZA;Mn;0;NSM;;;;;N;;;;; 11CA5;MARCHEN SUBJOINED LETTER WA;Mn;0;NSM;;;;;N;;;;; 11CA6;MARCHEN SUBJOINED LETTER ZHA;Mn;0;NSM;;;;;N;;;;; 11CA7;MARCHEN SUBJOINED LETTER ZA;Mn;0;NSM;;;;;N;;;;; 11CA9;MARCHEN SUBJOINED LETTER YA;Mc;0;L;;;;;N;;;;; 11CAA;MARCHEN SUBJOINED LETTER RA;Mn;0;NSM;;;;;N;;;;; 11CAB;MARCHEN SUBJOINED LETTER LA;Mn;0;NSM;;;;;N;;;;; 11CAC;MARCHEN SUBJOINED LETTER SHA;Mn;0;NSM;;;;;N;;;;; 11CAD;MARCHEN SUBJOINED LETTER SA;Mn;0;NSM;;;;;N;;;;; 11CAE;MARCHEN SUBJOINED LETTER HA;Mn;0;NSM;;;;;N;;;;; 11CAF;MARCHEN SUBJOINED LETTER A;Mn;0;NSM;;;;;N;;;;; 11CB0;MARCHEN VOWEL SIGN AA;Mn;0;NSM;;;;;N;;;;; 11CB1;MARCHEN VOWEL SIGN I;Mc;0;L;;;;;N;;;;; 11CB2;MARCHEN VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; 11CB3;MARCHEN VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; 11CB4;MARCHEN VOWEL SIGN O;Mc;0;L;;;;;N;;;;; 11CB5;MARCHEN SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; 11CB6;MARCHEN SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; 12000;CUNEIFORM SIGN A;Lo;0;L;;;;;N;;;;; 12001;CUNEIFORM SIGN A TIMES A;Lo;0;L;;;;;N;;;;; 12002;CUNEIFORM SIGN A TIMES BAD;Lo;0;L;;;;;N;;;;; 12003;CUNEIFORM SIGN A TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; 12004;CUNEIFORM SIGN A TIMES HA;Lo;0;L;;;;;N;;;;; 12005;CUNEIFORM SIGN A TIMES IGI;Lo;0;L;;;;;N;;;;; 12006;CUNEIFORM SIGN A TIMES LAGAR GUNU;Lo;0;L;;;;;N;;;;; 12007;CUNEIFORM SIGN A TIMES MUSH;Lo;0;L;;;;;N;;;;; 12008;CUNEIFORM SIGN A TIMES SAG;Lo;0;L;;;;;N;;;;; 12009;CUNEIFORM SIGN A2;Lo;0;L;;;;;N;;;;; 1200A;CUNEIFORM SIGN AB;Lo;0;L;;;;;N;;;;; 1200B;CUNEIFORM SIGN AB TIMES ASH2;Lo;0;L;;;;;N;;;;; 1200C;CUNEIFORM SIGN AB TIMES DUN3 GUNU;Lo;0;L;;;;;N;;;;; 1200D;CUNEIFORM SIGN AB TIMES GAL;Lo;0;L;;;;;N;;;;; 1200E;CUNEIFORM SIGN AB TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; 1200F;CUNEIFORM SIGN AB TIMES HA;Lo;0;L;;;;;N;;;;; 12010;CUNEIFORM SIGN AB TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; 12011;CUNEIFORM SIGN AB TIMES IMIN;Lo;0;L;;;;;N;;;;; 12012;CUNEIFORM SIGN AB TIMES LAGAB;Lo;0;L;;;;;N;;;;; 12013;CUNEIFORM SIGN AB TIMES SHESH;Lo;0;L;;;;;N;;;;; 12014;CUNEIFORM SIGN AB TIMES U PLUS U PLUS U;Lo;0;L;;;;;N;;;;; 12015;CUNEIFORM SIGN AB GUNU;Lo;0;L;;;;;N;;;;; 12016;CUNEIFORM SIGN AB2;Lo;0;L;;;;;N;;;;; 12017;CUNEIFORM SIGN AB2 TIMES BALAG;Lo;0;L;;;;;N;;;;; 12018;CUNEIFORM SIGN AB2 TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; 12019;CUNEIFORM SIGN AB2 TIMES ME PLUS EN;Lo;0;L;;;;;N;;;;; 1201A;CUNEIFORM SIGN AB2 TIMES SHA3;Lo;0;L;;;;;N;;;;; 1201B;CUNEIFORM SIGN AB2 TIMES TAK4;Lo;0;L;;;;;N;;;;; 1201C;CUNEIFORM SIGN AD;Lo;0;L;;;;;N;;;;; 1201D;CUNEIFORM SIGN AK;Lo;0;L;;;;;N;;;;; 1201E;CUNEIFORM SIGN AK TIMES ERIN2;Lo;0;L;;;;;N;;;;; 1201F;CUNEIFORM SIGN AK TIMES SHITA PLUS GISH;Lo;0;L;;;;;N;;;;; 12020;CUNEIFORM SIGN AL;Lo;0;L;;;;;N;;;;; 12021;CUNEIFORM SIGN AL TIMES AL;Lo;0;L;;;;;N;;;;; 12022;CUNEIFORM SIGN AL TIMES DIM2;Lo;0;L;;;;;N;;;;; 12023;CUNEIFORM SIGN AL TIMES GISH;Lo;0;L;;;;;N;;;;; 12024;CUNEIFORM SIGN AL TIMES HA;Lo;0;L;;;;;N;;;;; 12025;CUNEIFORM SIGN AL TIMES KAD3;Lo;0;L;;;;;N;;;;; 12026;CUNEIFORM SIGN AL TIMES KI;Lo;0;L;;;;;N;;;;; 12027;CUNEIFORM SIGN AL TIMES SHE;Lo;0;L;;;;;N;;;;; 12028;CUNEIFORM SIGN AL TIMES USH;Lo;0;L;;;;;N;;;;; 12029;CUNEIFORM SIGN ALAN;Lo;0;L;;;;;N;;;;; 1202A;CUNEIFORM SIGN ALEPH;Lo;0;L;;;;;N;;;;; 1202B;CUNEIFORM SIGN AMAR;Lo;0;L;;;;;N;;;;; 1202C;CUNEIFORM SIGN AMAR TIMES SHE;Lo;0;L;;;;;N;;;;; 1202D;CUNEIFORM SIGN AN;Lo;0;L;;;;;N;;;;; 1202E;CUNEIFORM SIGN AN OVER AN;Lo;0;L;;;;;N;;;;; 1202F;CUNEIFORM SIGN AN THREE TIMES;Lo;0;L;;;;;N;;;;; 12030;CUNEIFORM SIGN AN PLUS NAGA OPPOSING AN PLUS NAGA;Lo;0;L;;;;;N;;;;; 12031;CUNEIFORM SIGN AN PLUS NAGA SQUARED;Lo;0;L;;;;;N;;;;; 12032;CUNEIFORM SIGN ANSHE;Lo;0;L;;;;;N;;;;; 12033;CUNEIFORM SIGN APIN;Lo;0;L;;;;;N;;;;; 12034;CUNEIFORM SIGN ARAD;Lo;0;L;;;;;N;;;;; 12035;CUNEIFORM SIGN ARAD TIMES KUR;Lo;0;L;;;;;N;;;;; 12036;CUNEIFORM SIGN ARKAB;Lo;0;L;;;;;N;;;;; 12037;CUNEIFORM SIGN ASAL2;Lo;0;L;;;;;N;;;;; 12038;CUNEIFORM SIGN ASH;Lo;0;L;;;;;N;;;;; 12039;CUNEIFORM SIGN ASH ZIDA TENU;Lo;0;L;;;;;N;;;;; 1203A;CUNEIFORM SIGN ASH KABA TENU;Lo;0;L;;;;;N;;;;; 1203B;CUNEIFORM SIGN ASH OVER ASH TUG2 OVER TUG2 TUG2 OVER TUG2 PAP;Lo;0;L;;;;;N;;;;; 1203C;CUNEIFORM SIGN ASH OVER ASH OVER ASH;Lo;0;L;;;;;N;;;;; 1203D;CUNEIFORM SIGN ASH OVER ASH OVER ASH CROSSING ASH OVER ASH OVER ASH;Lo;0;L;;;;;N;;;;; 1203E;CUNEIFORM SIGN ASH2;Lo;0;L;;;;;N;;;;; 1203F;CUNEIFORM SIGN ASHGAB;Lo;0;L;;;;;N;;;;; 12040;CUNEIFORM SIGN BA;Lo;0;L;;;;;N;;;;; 12041;CUNEIFORM SIGN BAD;Lo;0;L;;;;;N;;;;; 12042;CUNEIFORM SIGN BAG3;Lo;0;L;;;;;N;;;;; 12043;CUNEIFORM SIGN BAHAR2;Lo;0;L;;;;;N;;;;; 12044;CUNEIFORM SIGN BAL;Lo;0;L;;;;;N;;;;; 12045;CUNEIFORM SIGN BAL OVER BAL;Lo;0;L;;;;;N;;;;; 12046;CUNEIFORM SIGN BALAG;Lo;0;L;;;;;N;;;;; 12047;CUNEIFORM SIGN BAR;Lo;0;L;;;;;N;;;;; 12048;CUNEIFORM SIGN BARA2;Lo;0;L;;;;;N;;;;; 12049;CUNEIFORM SIGN BI;Lo;0;L;;;;;N;;;;; 1204A;CUNEIFORM SIGN BI TIMES A;Lo;0;L;;;;;N;;;;; 1204B;CUNEIFORM SIGN BI TIMES GAR;Lo;0;L;;;;;N;;;;; 1204C;CUNEIFORM SIGN BI TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; 1204D;CUNEIFORM SIGN BU;Lo;0;L;;;;;N;;;;; 1204E;CUNEIFORM SIGN BU OVER BU AB;Lo;0;L;;;;;N;;;;; 1204F;CUNEIFORM SIGN BU OVER BU UN;Lo;0;L;;;;;N;;;;; 12050;CUNEIFORM SIGN BU CROSSING BU;Lo;0;L;;;;;N;;;;; 12051;CUNEIFORM SIGN BULUG;Lo;0;L;;;;;N;;;;; 12052;CUNEIFORM SIGN BULUG OVER BULUG;Lo;0;L;;;;;N;;;;; 12053;CUNEIFORM SIGN BUR;Lo;0;L;;;;;N;;;;; 12054;CUNEIFORM SIGN BUR2;Lo;0;L;;;;;N;;;;; 12055;CUNEIFORM SIGN DA;Lo;0;L;;;;;N;;;;; 12056;CUNEIFORM SIGN DAG;Lo;0;L;;;;;N;;;;; 12057;CUNEIFORM SIGN DAG KISIM5 TIMES A PLUS MASH;Lo;0;L;;;;;N;;;;; 12058;CUNEIFORM SIGN DAG KISIM5 TIMES AMAR;Lo;0;L;;;;;N;;;;; 12059;CUNEIFORM SIGN DAG KISIM5 TIMES BALAG;Lo;0;L;;;;;N;;;;; 1205A;CUNEIFORM SIGN DAG KISIM5 TIMES BI;Lo;0;L;;;;;N;;;;; 1205B;CUNEIFORM SIGN DAG KISIM5 TIMES GA;Lo;0;L;;;;;N;;;;; 1205C;CUNEIFORM SIGN DAG KISIM5 TIMES GA PLUS MASH;Lo;0;L;;;;;N;;;;; 1205D;CUNEIFORM SIGN DAG KISIM5 TIMES GI;Lo;0;L;;;;;N;;;;; 1205E;CUNEIFORM SIGN DAG KISIM5 TIMES GIR2;Lo;0;L;;;;;N;;;;; 1205F;CUNEIFORM SIGN DAG KISIM5 TIMES GUD;Lo;0;L;;;;;N;;;;; 12060;CUNEIFORM SIGN DAG KISIM5 TIMES HA;Lo;0;L;;;;;N;;;;; 12061;CUNEIFORM SIGN DAG KISIM5 TIMES IR;Lo;0;L;;;;;N;;;;; 12062;CUNEIFORM SIGN DAG KISIM5 TIMES IR PLUS LU;Lo;0;L;;;;;N;;;;; 12063;CUNEIFORM SIGN DAG KISIM5 TIMES KAK;Lo;0;L;;;;;N;;;;; 12064;CUNEIFORM SIGN DAG KISIM5 TIMES LA;Lo;0;L;;;;;N;;;;; 12065;CUNEIFORM SIGN DAG KISIM5 TIMES LU;Lo;0;L;;;;;N;;;;; 12066;CUNEIFORM SIGN DAG KISIM5 TIMES LU PLUS MASH2;Lo;0;L;;;;;N;;;;; 12067;CUNEIFORM SIGN DAG KISIM5 TIMES LUM;Lo;0;L;;;;;N;;;;; 12068;CUNEIFORM SIGN DAG KISIM5 TIMES NE;Lo;0;L;;;;;N;;;;; 12069;CUNEIFORM SIGN DAG KISIM5 TIMES PAP PLUS PAP;Lo;0;L;;;;;N;;;;; 1206A;CUNEIFORM SIGN DAG KISIM5 TIMES SI;Lo;0;L;;;;;N;;;;; 1206B;CUNEIFORM SIGN DAG KISIM5 TIMES TAK4;Lo;0;L;;;;;N;;;;; 1206C;CUNEIFORM SIGN DAG KISIM5 TIMES U2 PLUS GIR2;Lo;0;L;;;;;N;;;;; 1206D;CUNEIFORM SIGN DAG KISIM5 TIMES USH;Lo;0;L;;;;;N;;;;; 1206E;CUNEIFORM SIGN DAM;Lo;0;L;;;;;N;;;;; 1206F;CUNEIFORM SIGN DAR;Lo;0;L;;;;;N;;;;; 12070;CUNEIFORM SIGN DARA3;Lo;0;L;;;;;N;;;;; 12071;CUNEIFORM SIGN DARA4;Lo;0;L;;;;;N;;;;; 12072;CUNEIFORM SIGN DI;Lo;0;L;;;;;N;;;;; 12073;CUNEIFORM SIGN DIB;Lo;0;L;;;;;N;;;;; 12074;CUNEIFORM SIGN DIM;Lo;0;L;;;;;N;;;;; 12075;CUNEIFORM SIGN DIM TIMES SHE;Lo;0;L;;;;;N;;;;; 12076;CUNEIFORM SIGN DIM2;Lo;0;L;;;;;N;;;;; 12077;CUNEIFORM SIGN DIN;Lo;0;L;;;;;N;;;;; 12078;CUNEIFORM SIGN DIN KASKAL U GUNU DISH;Lo;0;L;;;;;N;;;;; 12079;CUNEIFORM SIGN DISH;Lo;0;L;;;;;N;;;;; 1207A;CUNEIFORM SIGN DU;Lo;0;L;;;;;N;;;;; 1207B;CUNEIFORM SIGN DU OVER DU;Lo;0;L;;;;;N;;;;; 1207C;CUNEIFORM SIGN DU GUNU;Lo;0;L;;;;;N;;;;; 1207D;CUNEIFORM SIGN DU SHESHIG;Lo;0;L;;;;;N;;;;; 1207E;CUNEIFORM SIGN DUB;Lo;0;L;;;;;N;;;;; 1207F;CUNEIFORM SIGN DUB TIMES ESH2;Lo;0;L;;;;;N;;;;; 12080;CUNEIFORM SIGN DUB2;Lo;0;L;;;;;N;;;;; 12081;CUNEIFORM SIGN DUG;Lo;0;L;;;;;N;;;;; 12082;CUNEIFORM SIGN DUGUD;Lo;0;L;;;;;N;;;;; 12083;CUNEIFORM SIGN DUH;Lo;0;L;;;;;N;;;;; 12084;CUNEIFORM SIGN DUN;Lo;0;L;;;;;N;;;;; 12085;CUNEIFORM SIGN DUN3;Lo;0;L;;;;;N;;;;; 12086;CUNEIFORM SIGN DUN3 GUNU;Lo;0;L;;;;;N;;;;; 12087;CUNEIFORM SIGN DUN3 GUNU GUNU;Lo;0;L;;;;;N;;;;; 12088;CUNEIFORM SIGN DUN4;Lo;0;L;;;;;N;;;;; 12089;CUNEIFORM SIGN DUR2;Lo;0;L;;;;;N;;;;; 1208A;CUNEIFORM SIGN E;Lo;0;L;;;;;N;;;;; 1208B;CUNEIFORM SIGN E TIMES PAP;Lo;0;L;;;;;N;;;;; 1208C;CUNEIFORM SIGN E OVER E NUN OVER NUN;Lo;0;L;;;;;N;;;;; 1208D;CUNEIFORM SIGN E2;Lo;0;L;;;;;N;;;;; 1208E;CUNEIFORM SIGN E2 TIMES A PLUS HA PLUS DA;Lo;0;L;;;;;N;;;;; 1208F;CUNEIFORM SIGN E2 TIMES GAR;Lo;0;L;;;;;N;;;;; 12090;CUNEIFORM SIGN E2 TIMES MI;Lo;0;L;;;;;N;;;;; 12091;CUNEIFORM SIGN E2 TIMES SAL;Lo;0;L;;;;;N;;;;; 12092;CUNEIFORM SIGN E2 TIMES SHE;Lo;0;L;;;;;N;;;;; 12093;CUNEIFORM SIGN E2 TIMES U;Lo;0;L;;;;;N;;;;; 12094;CUNEIFORM SIGN EDIN;Lo;0;L;;;;;N;;;;; 12095;CUNEIFORM SIGN EGIR;Lo;0;L;;;;;N;;;;; 12096;CUNEIFORM SIGN EL;Lo;0;L;;;;;N;;;;; 12097;CUNEIFORM SIGN EN;Lo;0;L;;;;;N;;;;; 12098;CUNEIFORM SIGN EN TIMES GAN2;Lo;0;L;;;;;N;;;;; 12099;CUNEIFORM SIGN EN TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; 1209A;CUNEIFORM SIGN EN TIMES ME;Lo;0;L;;;;;N;;;;; 1209B;CUNEIFORM SIGN EN CROSSING EN;Lo;0;L;;;;;N;;;;; 1209C;CUNEIFORM SIGN EN OPPOSING EN;Lo;0;L;;;;;N;;;;; 1209D;CUNEIFORM SIGN EN SQUARED;Lo;0;L;;;;;N;;;;; 1209E;CUNEIFORM SIGN EREN;Lo;0;L;;;;;N;;;;; 1209F;CUNEIFORM SIGN ERIN2;Lo;0;L;;;;;N;;;;; 120A0;CUNEIFORM SIGN ESH2;Lo;0;L;;;;;N;;;;; 120A1;CUNEIFORM SIGN EZEN;Lo;0;L;;;;;N;;;;; 120A2;CUNEIFORM SIGN EZEN TIMES A;Lo;0;L;;;;;N;;;;; 120A3;CUNEIFORM SIGN EZEN TIMES A PLUS LAL;Lo;0;L;;;;;N;;;;; 120A4;CUNEIFORM SIGN EZEN TIMES A PLUS LAL TIMES LAL;Lo;0;L;;;;;N;;;;; 120A5;CUNEIFORM SIGN EZEN TIMES AN;Lo;0;L;;;;;N;;;;; 120A6;CUNEIFORM SIGN EZEN TIMES BAD;Lo;0;L;;;;;N;;;;; 120A7;CUNEIFORM SIGN EZEN TIMES DUN3 GUNU;Lo;0;L;;;;;N;;;;; 120A8;CUNEIFORM SIGN EZEN TIMES DUN3 GUNU GUNU;Lo;0;L;;;;;N;;;;; 120A9;CUNEIFORM SIGN EZEN TIMES HA;Lo;0;L;;;;;N;;;;; 120AA;CUNEIFORM SIGN EZEN TIMES HA GUNU;Lo;0;L;;;;;N;;;;; 120AB;CUNEIFORM SIGN EZEN TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; 120AC;CUNEIFORM SIGN EZEN TIMES KASKAL;Lo;0;L;;;;;N;;;;; 120AD;CUNEIFORM SIGN EZEN TIMES KASKAL SQUARED;Lo;0;L;;;;;N;;;;; 120AE;CUNEIFORM SIGN EZEN TIMES KU3;Lo;0;L;;;;;N;;;;; 120AF;CUNEIFORM SIGN EZEN TIMES LA;Lo;0;L;;;;;N;;;;; 120B0;CUNEIFORM SIGN EZEN TIMES LAL TIMES LAL;Lo;0;L;;;;;N;;;;; 120B1;CUNEIFORM SIGN EZEN TIMES LI;Lo;0;L;;;;;N;;;;; 120B2;CUNEIFORM SIGN EZEN TIMES LU;Lo;0;L;;;;;N;;;;; 120B3;CUNEIFORM SIGN EZEN TIMES U2;Lo;0;L;;;;;N;;;;; 120B4;CUNEIFORM SIGN EZEN TIMES UD;Lo;0;L;;;;;N;;;;; 120B5;CUNEIFORM SIGN GA;Lo;0;L;;;;;N;;;;; 120B6;CUNEIFORM SIGN GA GUNU;Lo;0;L;;;;;N;;;;; 120B7;CUNEIFORM SIGN GA2;Lo;0;L;;;;;N;;;;; 120B8;CUNEIFORM SIGN GA2 TIMES A PLUS DA PLUS HA;Lo;0;L;;;;;N;;;;; 120B9;CUNEIFORM SIGN GA2 TIMES A PLUS HA;Lo;0;L;;;;;N;;;;; 120BA;CUNEIFORM SIGN GA2 TIMES A PLUS IGI;Lo;0;L;;;;;N;;;;; 120BB;CUNEIFORM SIGN GA2 TIMES AB2 TENU PLUS TAB;Lo;0;L;;;;;N;;;;; 120BC;CUNEIFORM SIGN GA2 TIMES AN;Lo;0;L;;;;;N;;;;; 120BD;CUNEIFORM SIGN GA2 TIMES ASH;Lo;0;L;;;;;N;;;;; 120BE;CUNEIFORM SIGN GA2 TIMES ASH2 PLUS GAL;Lo;0;L;;;;;N;;;;; 120BF;CUNEIFORM SIGN GA2 TIMES BAD;Lo;0;L;;;;;N;;;;; 120C0;CUNEIFORM SIGN GA2 TIMES BAR PLUS RA;Lo;0;L;;;;;N;;;;; 120C1;CUNEIFORM SIGN GA2 TIMES BUR;Lo;0;L;;;;;N;;;;; 120C2;CUNEIFORM SIGN GA2 TIMES BUR PLUS RA;Lo;0;L;;;;;N;;;;; 120C3;CUNEIFORM SIGN GA2 TIMES DA;Lo;0;L;;;;;N;;;;; 120C4;CUNEIFORM SIGN GA2 TIMES DI;Lo;0;L;;;;;N;;;;; 120C5;CUNEIFORM SIGN GA2 TIMES DIM TIMES SHE;Lo;0;L;;;;;N;;;;; 120C6;CUNEIFORM SIGN GA2 TIMES DUB;Lo;0;L;;;;;N;;;;; 120C7;CUNEIFORM SIGN GA2 TIMES EL;Lo;0;L;;;;;N;;;;; 120C8;CUNEIFORM SIGN GA2 TIMES EL PLUS LA;Lo;0;L;;;;;N;;;;; 120C9;CUNEIFORM SIGN GA2 TIMES EN;Lo;0;L;;;;;N;;;;; 120CA;CUNEIFORM SIGN GA2 TIMES EN TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; 120CB;CUNEIFORM SIGN GA2 TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; 120CC;CUNEIFORM SIGN GA2 TIMES GAR;Lo;0;L;;;;;N;;;;; 120CD;CUNEIFORM SIGN GA2 TIMES GI;Lo;0;L;;;;;N;;;;; 120CE;CUNEIFORM SIGN GA2 TIMES GI4;Lo;0;L;;;;;N;;;;; 120CF;CUNEIFORM SIGN GA2 TIMES GI4 PLUS A;Lo;0;L;;;;;N;;;;; 120D0;CUNEIFORM SIGN GA2 TIMES GIR2 PLUS SU;Lo;0;L;;;;;N;;;;; 120D1;CUNEIFORM SIGN GA2 TIMES HA PLUS LU PLUS ESH2;Lo;0;L;;;;;N;;;;; 120D2;CUNEIFORM SIGN GA2 TIMES HAL;Lo;0;L;;;;;N;;;;; 120D3;CUNEIFORM SIGN GA2 TIMES HAL PLUS LA;Lo;0;L;;;;;N;;;;; 120D4;CUNEIFORM SIGN GA2 TIMES HI PLUS LI;Lo;0;L;;;;;N;;;;; 120D5;CUNEIFORM SIGN GA2 TIMES HUB2;Lo;0;L;;;;;N;;;;; 120D6;CUNEIFORM SIGN GA2 TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; 120D7;CUNEIFORM SIGN GA2 TIMES ISH PLUS HU PLUS ASH;Lo;0;L;;;;;N;;;;; 120D8;CUNEIFORM SIGN GA2 TIMES KAK;Lo;0;L;;;;;N;;;;; 120D9;CUNEIFORM SIGN GA2 TIMES KASKAL;Lo;0;L;;;;;N;;;;; 120DA;CUNEIFORM SIGN GA2 TIMES KID;Lo;0;L;;;;;N;;;;; 120DB;CUNEIFORM SIGN GA2 TIMES KID PLUS LAL;Lo;0;L;;;;;N;;;;; 120DC;CUNEIFORM SIGN GA2 TIMES KU3 PLUS AN;Lo;0;L;;;;;N;;;;; 120DD;CUNEIFORM SIGN GA2 TIMES LA;Lo;0;L;;;;;N;;;;; 120DE;CUNEIFORM SIGN GA2 TIMES ME PLUS EN;Lo;0;L;;;;;N;;;;; 120DF;CUNEIFORM SIGN GA2 TIMES MI;Lo;0;L;;;;;N;;;;; 120E0;CUNEIFORM SIGN GA2 TIMES NUN;Lo;0;L;;;;;N;;;;; 120E1;CUNEIFORM SIGN GA2 TIMES NUN OVER NUN;Lo;0;L;;;;;N;;;;; 120E2;CUNEIFORM SIGN GA2 TIMES PA;Lo;0;L;;;;;N;;;;; 120E3;CUNEIFORM SIGN GA2 TIMES SAL;Lo;0;L;;;;;N;;;;; 120E4;CUNEIFORM SIGN GA2 TIMES SAR;Lo;0;L;;;;;N;;;;; 120E5;CUNEIFORM SIGN GA2 TIMES SHE;Lo;0;L;;;;;N;;;;; 120E6;CUNEIFORM SIGN GA2 TIMES SHE PLUS TUR;Lo;0;L;;;;;N;;;;; 120E7;CUNEIFORM SIGN GA2 TIMES SHID;Lo;0;L;;;;;N;;;;; 120E8;CUNEIFORM SIGN GA2 TIMES SUM;Lo;0;L;;;;;N;;;;; 120E9;CUNEIFORM SIGN GA2 TIMES TAK4;Lo;0;L;;;;;N;;;;; 120EA;CUNEIFORM SIGN GA2 TIMES U;Lo;0;L;;;;;N;;;;; 120EB;CUNEIFORM SIGN GA2 TIMES UD;Lo;0;L;;;;;N;;;;; 120EC;CUNEIFORM SIGN GA2 TIMES UD PLUS DU;Lo;0;L;;;;;N;;;;; 120ED;CUNEIFORM SIGN GA2 OVER GA2;Lo;0;L;;;;;N;;;;; 120EE;CUNEIFORM SIGN GABA;Lo;0;L;;;;;N;;;;; 120EF;CUNEIFORM SIGN GABA CROSSING GABA;Lo;0;L;;;;;N;;;;; 120F0;CUNEIFORM SIGN GAD;Lo;0;L;;;;;N;;;;; 120F1;CUNEIFORM SIGN GAD OVER GAD GAR OVER GAR;Lo;0;L;;;;;N;;;;; 120F2;CUNEIFORM SIGN GAL;Lo;0;L;;;;;N;;;;; 120F3;CUNEIFORM SIGN GAL GAD OVER GAD GAR OVER GAR;Lo;0;L;;;;;N;;;;; 120F4;CUNEIFORM SIGN GALAM;Lo;0;L;;;;;N;;;;; 120F5;CUNEIFORM SIGN GAM;Lo;0;L;;;;;N;;;;; 120F6;CUNEIFORM SIGN GAN;Lo;0;L;;;;;N;;;;; 120F7;CUNEIFORM SIGN GAN2;Lo;0;L;;;;;N;;;;; 120F8;CUNEIFORM SIGN GAN2 TENU;Lo;0;L;;;;;N;;;;; 120F9;CUNEIFORM SIGN GAN2 OVER GAN2;Lo;0;L;;;;;N;;;;; 120FA;CUNEIFORM SIGN GAN2 CROSSING GAN2;Lo;0;L;;;;;N;;;;; 120FB;CUNEIFORM SIGN GAR;Lo;0;L;;;;;N;;;;; 120FC;CUNEIFORM SIGN GAR3;Lo;0;L;;;;;N;;;;; 120FD;CUNEIFORM SIGN GASHAN;Lo;0;L;;;;;N;;;;; 120FE;CUNEIFORM SIGN GESHTIN;Lo;0;L;;;;;N;;;;; 120FF;CUNEIFORM SIGN GESHTIN TIMES KUR;Lo;0;L;;;;;N;;;;; 12100;CUNEIFORM SIGN GI;Lo;0;L;;;;;N;;;;; 12101;CUNEIFORM SIGN GI TIMES E;Lo;0;L;;;;;N;;;;; 12102;CUNEIFORM SIGN GI TIMES U;Lo;0;L;;;;;N;;;;; 12103;CUNEIFORM SIGN GI CROSSING GI;Lo;0;L;;;;;N;;;;; 12104;CUNEIFORM SIGN GI4;Lo;0;L;;;;;N;;;;; 12105;CUNEIFORM SIGN GI4 OVER GI4;Lo;0;L;;;;;N;;;;; 12106;CUNEIFORM SIGN GI4 CROSSING GI4;Lo;0;L;;;;;N;;;;; 12107;CUNEIFORM SIGN GIDIM;Lo;0;L;;;;;N;;;;; 12108;CUNEIFORM SIGN GIR2;Lo;0;L;;;;;N;;;;; 12109;CUNEIFORM SIGN GIR2 GUNU;Lo;0;L;;;;;N;;;;; 1210A;CUNEIFORM SIGN GIR3;Lo;0;L;;;;;N;;;;; 1210B;CUNEIFORM SIGN GIR3 TIMES A PLUS IGI;Lo;0;L;;;;;N;;;;; 1210C;CUNEIFORM SIGN GIR3 TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; 1210D;CUNEIFORM SIGN GIR3 TIMES IGI;Lo;0;L;;;;;N;;;;; 1210E;CUNEIFORM SIGN GIR3 TIMES LU PLUS IGI;Lo;0;L;;;;;N;;;;; 1210F;CUNEIFORM SIGN GIR3 TIMES PA;Lo;0;L;;;;;N;;;;; 12110;CUNEIFORM SIGN GISAL;Lo;0;L;;;;;N;;;;; 12111;CUNEIFORM SIGN GISH;Lo;0;L;;;;;N;;;;; 12112;CUNEIFORM SIGN GISH CROSSING GISH;Lo;0;L;;;;;N;;;;; 12113;CUNEIFORM SIGN GISH TIMES BAD;Lo;0;L;;;;;N;;;;; 12114;CUNEIFORM SIGN GISH TIMES TAK4;Lo;0;L;;;;;N;;;;; 12115;CUNEIFORM SIGN GISH TENU;Lo;0;L;;;;;N;;;;; 12116;CUNEIFORM SIGN GU;Lo;0;L;;;;;N;;;;; 12117;CUNEIFORM SIGN GU CROSSING GU;Lo;0;L;;;;;N;;;;; 12118;CUNEIFORM SIGN GU2;Lo;0;L;;;;;N;;;;; 12119;CUNEIFORM SIGN GU2 TIMES KAK;Lo;0;L;;;;;N;;;;; 1211A;CUNEIFORM SIGN GU2 TIMES KAK TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; 1211B;CUNEIFORM SIGN GU2 TIMES NUN;Lo;0;L;;;;;N;;;;; 1211C;CUNEIFORM SIGN GU2 TIMES SAL PLUS TUG2;Lo;0;L;;;;;N;;;;; 1211D;CUNEIFORM SIGN GU2 GUNU;Lo;0;L;;;;;N;;;;; 1211E;CUNEIFORM SIGN GUD;Lo;0;L;;;;;N;;;;; 1211F;CUNEIFORM SIGN GUD TIMES A PLUS KUR;Lo;0;L;;;;;N;;;;; 12120;CUNEIFORM SIGN GUD TIMES KUR;Lo;0;L;;;;;N;;;;; 12121;CUNEIFORM SIGN GUD OVER GUD LUGAL;Lo;0;L;;;;;N;;;;; 12122;CUNEIFORM SIGN GUL;Lo;0;L;;;;;N;;;;; 12123;CUNEIFORM SIGN GUM;Lo;0;L;;;;;N;;;;; 12124;CUNEIFORM SIGN GUM TIMES SHE;Lo;0;L;;;;;N;;;;; 12125;CUNEIFORM SIGN GUR;Lo;0;L;;;;;N;;;;; 12126;CUNEIFORM SIGN GUR7;Lo;0;L;;;;;N;;;;; 12127;CUNEIFORM SIGN GURUN;Lo;0;L;;;;;N;;;;; 12128;CUNEIFORM SIGN GURUSH;Lo;0;L;;;;;N;;;;; 12129;CUNEIFORM SIGN HA;Lo;0;L;;;;;N;;;;; 1212A;CUNEIFORM SIGN HA TENU;Lo;0;L;;;;;N;;;;; 1212B;CUNEIFORM SIGN HA GUNU;Lo;0;L;;;;;N;;;;; 1212C;CUNEIFORM SIGN HAL;Lo;0;L;;;;;N;;;;; 1212D;CUNEIFORM SIGN HI;Lo;0;L;;;;;N;;;;; 1212E;CUNEIFORM SIGN HI TIMES ASH;Lo;0;L;;;;;N;;;;; 1212F;CUNEIFORM SIGN HI TIMES ASH2;Lo;0;L;;;;;N;;;;; 12130;CUNEIFORM SIGN HI TIMES BAD;Lo;0;L;;;;;N;;;;; 12131;CUNEIFORM SIGN HI TIMES DISH;Lo;0;L;;;;;N;;;;; 12132;CUNEIFORM SIGN HI TIMES GAD;Lo;0;L;;;;;N;;;;; 12133;CUNEIFORM SIGN HI TIMES KIN;Lo;0;L;;;;;N;;;;; 12134;CUNEIFORM SIGN HI TIMES NUN;Lo;0;L;;;;;N;;;;; 12135;CUNEIFORM SIGN HI TIMES SHE;Lo;0;L;;;;;N;;;;; 12136;CUNEIFORM SIGN HI TIMES U;Lo;0;L;;;;;N;;;;; 12137;CUNEIFORM SIGN HU;Lo;0;L;;;;;N;;;;; 12138;CUNEIFORM SIGN HUB2;Lo;0;L;;;;;N;;;;; 12139;CUNEIFORM SIGN HUB2 TIMES AN;Lo;0;L;;;;;N;;;;; 1213A;CUNEIFORM SIGN HUB2 TIMES HAL;Lo;0;L;;;;;N;;;;; 1213B;CUNEIFORM SIGN HUB2 TIMES KASKAL;Lo;0;L;;;;;N;;;;; 1213C;CUNEIFORM SIGN HUB2 TIMES LISH;Lo;0;L;;;;;N;;;;; 1213D;CUNEIFORM SIGN HUB2 TIMES UD;Lo;0;L;;;;;N;;;;; 1213E;CUNEIFORM SIGN HUL2;Lo;0;L;;;;;N;;;;; 1213F;CUNEIFORM SIGN I;Lo;0;L;;;;;N;;;;; 12140;CUNEIFORM SIGN I A;Lo;0;L;;;;;N;;;;; 12141;CUNEIFORM SIGN IB;Lo;0;L;;;;;N;;;;; 12142;CUNEIFORM SIGN IDIM;Lo;0;L;;;;;N;;;;; 12143;CUNEIFORM SIGN IDIM OVER IDIM BUR;Lo;0;L;;;;;N;;;;; 12144;CUNEIFORM SIGN IDIM OVER IDIM SQUARED;Lo;0;L;;;;;N;;;;; 12145;CUNEIFORM SIGN IG;Lo;0;L;;;;;N;;;;; 12146;CUNEIFORM SIGN IGI;Lo;0;L;;;;;N;;;;; 12147;CUNEIFORM SIGN IGI DIB;Lo;0;L;;;;;N;;;;; 12148;CUNEIFORM SIGN IGI RI;Lo;0;L;;;;;N;;;;; 12149;CUNEIFORM SIGN IGI OVER IGI SHIR OVER SHIR UD OVER UD;Lo;0;L;;;;;N;;;;; 1214A;CUNEIFORM SIGN IGI GUNU;Lo;0;L;;;;;N;;;;; 1214B;CUNEIFORM SIGN IL;Lo;0;L;;;;;N;;;;; 1214C;CUNEIFORM SIGN IL TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; 1214D;CUNEIFORM SIGN IL2;Lo;0;L;;;;;N;;;;; 1214E;CUNEIFORM SIGN IM;Lo;0;L;;;;;N;;;;; 1214F;CUNEIFORM SIGN IM TIMES TAK4;Lo;0;L;;;;;N;;;;; 12150;CUNEIFORM SIGN IM CROSSING IM;Lo;0;L;;;;;N;;;;; 12151;CUNEIFORM SIGN IM OPPOSING IM;Lo;0;L;;;;;N;;;;; 12152;CUNEIFORM SIGN IM SQUARED;Lo;0;L;;;;;N;;;;; 12153;CUNEIFORM SIGN IMIN;Lo;0;L;;;;;N;;;;; 12154;CUNEIFORM SIGN IN;Lo;0;L;;;;;N;;;;; 12155;CUNEIFORM SIGN IR;Lo;0;L;;;;;N;;;;; 12156;CUNEIFORM SIGN ISH;Lo;0;L;;;;;N;;;;; 12157;CUNEIFORM SIGN KA;Lo;0;L;;;;;N;;;;; 12158;CUNEIFORM SIGN KA TIMES A;Lo;0;L;;;;;N;;;;; 12159;CUNEIFORM SIGN KA TIMES AD;Lo;0;L;;;;;N;;;;; 1215A;CUNEIFORM SIGN KA TIMES AD PLUS KU3;Lo;0;L;;;;;N;;;;; 1215B;CUNEIFORM SIGN KA TIMES ASH2;Lo;0;L;;;;;N;;;;; 1215C;CUNEIFORM SIGN KA TIMES BAD;Lo;0;L;;;;;N;;;;; 1215D;CUNEIFORM SIGN KA TIMES BALAG;Lo;0;L;;;;;N;;;;; 1215E;CUNEIFORM SIGN KA TIMES BAR;Lo;0;L;;;;;N;;;;; 1215F;CUNEIFORM SIGN KA TIMES BI;Lo;0;L;;;;;N;;;;; 12160;CUNEIFORM SIGN KA TIMES ERIN2;Lo;0;L;;;;;N;;;;; 12161;CUNEIFORM SIGN KA TIMES ESH2;Lo;0;L;;;;;N;;;;; 12162;CUNEIFORM SIGN KA TIMES GA;Lo;0;L;;;;;N;;;;; 12163;CUNEIFORM SIGN KA TIMES GAL;Lo;0;L;;;;;N;;;;; 12164;CUNEIFORM SIGN KA TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; 12165;CUNEIFORM SIGN KA TIMES GAR;Lo;0;L;;;;;N;;;;; 12166;CUNEIFORM SIGN KA TIMES GAR PLUS SHA3 PLUS A;Lo;0;L;;;;;N;;;;; 12167;CUNEIFORM SIGN KA TIMES GI;Lo;0;L;;;;;N;;;;; 12168;CUNEIFORM SIGN KA TIMES GIR2;Lo;0;L;;;;;N;;;;; 12169;CUNEIFORM SIGN KA TIMES GISH PLUS SAR;Lo;0;L;;;;;N;;;;; 1216A;CUNEIFORM SIGN KA TIMES GISH CROSSING GISH;Lo;0;L;;;;;N;;;;; 1216B;CUNEIFORM SIGN KA TIMES GU;Lo;0;L;;;;;N;;;;; 1216C;CUNEIFORM SIGN KA TIMES GUR7;Lo;0;L;;;;;N;;;;; 1216D;CUNEIFORM SIGN KA TIMES IGI;Lo;0;L;;;;;N;;;;; 1216E;CUNEIFORM SIGN KA TIMES IM;Lo;0;L;;;;;N;;;;; 1216F;CUNEIFORM SIGN KA TIMES KAK;Lo;0;L;;;;;N;;;;; 12170;CUNEIFORM SIGN KA TIMES KI;Lo;0;L;;;;;N;;;;; 12171;CUNEIFORM SIGN KA TIMES KID;Lo;0;L;;;;;N;;;;; 12172;CUNEIFORM SIGN KA TIMES LI;Lo;0;L;;;;;N;;;;; 12173;CUNEIFORM SIGN KA TIMES LU;Lo;0;L;;;;;N;;;;; 12174;CUNEIFORM SIGN KA TIMES ME;Lo;0;L;;;;;N;;;;; 12175;CUNEIFORM SIGN KA TIMES ME PLUS DU;Lo;0;L;;;;;N;;;;; 12176;CUNEIFORM SIGN KA TIMES ME PLUS GI;Lo;0;L;;;;;N;;;;; 12177;CUNEIFORM SIGN KA TIMES ME PLUS TE;Lo;0;L;;;;;N;;;;; 12178;CUNEIFORM SIGN KA TIMES MI;Lo;0;L;;;;;N;;;;; 12179;CUNEIFORM SIGN KA TIMES MI PLUS NUNUZ;Lo;0;L;;;;;N;;;;; 1217A;CUNEIFORM SIGN KA TIMES NE;Lo;0;L;;;;;N;;;;; 1217B;CUNEIFORM SIGN KA TIMES NUN;Lo;0;L;;;;;N;;;;; 1217C;CUNEIFORM SIGN KA TIMES PI;Lo;0;L;;;;;N;;;;; 1217D;CUNEIFORM SIGN KA TIMES RU;Lo;0;L;;;;;N;;;;; 1217E;CUNEIFORM SIGN KA TIMES SA;Lo;0;L;;;;;N;;;;; 1217F;CUNEIFORM SIGN KA TIMES SAR;Lo;0;L;;;;;N;;;;; 12180;CUNEIFORM SIGN KA TIMES SHA;Lo;0;L;;;;;N;;;;; 12181;CUNEIFORM SIGN KA TIMES SHE;Lo;0;L;;;;;N;;;;; 12182;CUNEIFORM SIGN KA TIMES SHID;Lo;0;L;;;;;N;;;;; 12183;CUNEIFORM SIGN KA TIMES SHU;Lo;0;L;;;;;N;;;;; 12184;CUNEIFORM SIGN KA TIMES SIG;Lo;0;L;;;;;N;;;;; 12185;CUNEIFORM SIGN KA TIMES SUHUR;Lo;0;L;;;;;N;;;;; 12186;CUNEIFORM SIGN KA TIMES TAR;Lo;0;L;;;;;N;;;;; 12187;CUNEIFORM SIGN KA TIMES U;Lo;0;L;;;;;N;;;;; 12188;CUNEIFORM SIGN KA TIMES U2;Lo;0;L;;;;;N;;;;; 12189;CUNEIFORM SIGN KA TIMES UD;Lo;0;L;;;;;N;;;;; 1218A;CUNEIFORM SIGN KA TIMES UMUM TIMES PA;Lo;0;L;;;;;N;;;;; 1218B;CUNEIFORM SIGN KA TIMES USH;Lo;0;L;;;;;N;;;;; 1218C;CUNEIFORM SIGN KA TIMES ZI;Lo;0;L;;;;;N;;;;; 1218D;CUNEIFORM SIGN KA2;Lo;0;L;;;;;N;;;;; 1218E;CUNEIFORM SIGN KA2 CROSSING KA2;Lo;0;L;;;;;N;;;;; 1218F;CUNEIFORM SIGN KAB;Lo;0;L;;;;;N;;;;; 12190;CUNEIFORM SIGN KAD2;Lo;0;L;;;;;N;;;;; 12191;CUNEIFORM SIGN KAD3;Lo;0;L;;;;;N;;;;; 12192;CUNEIFORM SIGN KAD4;Lo;0;L;;;;;N;;;;; 12193;CUNEIFORM SIGN KAD5;Lo;0;L;;;;;N;;;;; 12194;CUNEIFORM SIGN KAD5 OVER KAD5;Lo;0;L;;;;;N;;;;; 12195;CUNEIFORM SIGN KAK;Lo;0;L;;;;;N;;;;; 12196;CUNEIFORM SIGN KAK TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; 12197;CUNEIFORM SIGN KAL;Lo;0;L;;;;;N;;;;; 12198;CUNEIFORM SIGN KAL TIMES BAD;Lo;0;L;;;;;N;;;;; 12199;CUNEIFORM SIGN KAL CROSSING KAL;Lo;0;L;;;;;N;;;;; 1219A;CUNEIFORM SIGN KAM2;Lo;0;L;;;;;N;;;;; 1219B;CUNEIFORM SIGN KAM4;Lo;0;L;;;;;N;;;;; 1219C;CUNEIFORM SIGN KASKAL;Lo;0;L;;;;;N;;;;; 1219D;CUNEIFORM SIGN KASKAL LAGAB TIMES U OVER LAGAB TIMES U;Lo;0;L;;;;;N;;;;; 1219E;CUNEIFORM SIGN KASKAL OVER KASKAL LAGAB TIMES U OVER LAGAB TIMES U;Lo;0;L;;;;;N;;;;; 1219F;CUNEIFORM SIGN KESH2;Lo;0;L;;;;;N;;;;; 121A0;CUNEIFORM SIGN KI;Lo;0;L;;;;;N;;;;; 121A1;CUNEIFORM SIGN KI TIMES BAD;Lo;0;L;;;;;N;;;;; 121A2;CUNEIFORM SIGN KI TIMES U;Lo;0;L;;;;;N;;;;; 121A3;CUNEIFORM SIGN KI TIMES UD;Lo;0;L;;;;;N;;;;; 121A4;CUNEIFORM SIGN KID;Lo;0;L;;;;;N;;;;; 121A5;CUNEIFORM SIGN KIN;Lo;0;L;;;;;N;;;;; 121A6;CUNEIFORM SIGN KISAL;Lo;0;L;;;;;N;;;;; 121A7;CUNEIFORM SIGN KISH;Lo;0;L;;;;;N;;;;; 121A8;CUNEIFORM SIGN KISIM5;Lo;0;L;;;;;N;;;;; 121A9;CUNEIFORM SIGN KISIM5 OVER KISIM5;Lo;0;L;;;;;N;;;;; 121AA;CUNEIFORM SIGN KU;Lo;0;L;;;;;N;;;;; 121AB;CUNEIFORM SIGN KU OVER HI TIMES ASH2 KU OVER HI TIMES ASH2;Lo;0;L;;;;;N;;;;; 121AC;CUNEIFORM SIGN KU3;Lo;0;L;;;;;N;;;;; 121AD;CUNEIFORM SIGN KU4;Lo;0;L;;;;;N;;;;; 121AE;CUNEIFORM SIGN KU4 VARIANT FORM;Lo;0;L;;;;;N;;;;; 121AF;CUNEIFORM SIGN KU7;Lo;0;L;;;;;N;;;;; 121B0;CUNEIFORM SIGN KUL;Lo;0;L;;;;;N;;;;; 121B1;CUNEIFORM SIGN KUL GUNU;Lo;0;L;;;;;N;;;;; 121B2;CUNEIFORM SIGN KUN;Lo;0;L;;;;;N;;;;; 121B3;CUNEIFORM SIGN KUR;Lo;0;L;;;;;N;;;;; 121B4;CUNEIFORM SIGN KUR OPPOSING KUR;Lo;0;L;;;;;N;;;;; 121B5;CUNEIFORM SIGN KUSHU2;Lo;0;L;;;;;N;;;;; 121B6;CUNEIFORM SIGN KWU318;Lo;0;L;;;;;N;;;;; 121B7;CUNEIFORM SIGN LA;Lo;0;L;;;;;N;;;;; 121B8;CUNEIFORM SIGN LAGAB;Lo;0;L;;;;;N;;;;; 121B9;CUNEIFORM SIGN LAGAB TIMES A;Lo;0;L;;;;;N;;;;; 121BA;CUNEIFORM SIGN LAGAB TIMES A PLUS DA PLUS HA;Lo;0;L;;;;;N;;;;; 121BB;CUNEIFORM SIGN LAGAB TIMES A PLUS GAR;Lo;0;L;;;;;N;;;;; 121BC;CUNEIFORM SIGN LAGAB TIMES A PLUS LAL;Lo;0;L;;;;;N;;;;; 121BD;CUNEIFORM SIGN LAGAB TIMES AL;Lo;0;L;;;;;N;;;;; 121BE;CUNEIFORM SIGN LAGAB TIMES AN;Lo;0;L;;;;;N;;;;; 121BF;CUNEIFORM SIGN LAGAB TIMES ASH ZIDA TENU;Lo;0;L;;;;;N;;;;; 121C0;CUNEIFORM SIGN LAGAB TIMES BAD;Lo;0;L;;;;;N;;;;; 121C1;CUNEIFORM SIGN LAGAB TIMES BI;Lo;0;L;;;;;N;;;;; 121C2;CUNEIFORM SIGN LAGAB TIMES DAR;Lo;0;L;;;;;N;;;;; 121C3;CUNEIFORM SIGN LAGAB TIMES EN;Lo;0;L;;;;;N;;;;; 121C4;CUNEIFORM SIGN LAGAB TIMES GA;Lo;0;L;;;;;N;;;;; 121C5;CUNEIFORM SIGN LAGAB TIMES GAR;Lo;0;L;;;;;N;;;;; 121C6;CUNEIFORM SIGN LAGAB TIMES GUD;Lo;0;L;;;;;N;;;;; 121C7;CUNEIFORM SIGN LAGAB TIMES GUD PLUS GUD;Lo;0;L;;;;;N;;;;; 121C8;CUNEIFORM SIGN LAGAB TIMES HA;Lo;0;L;;;;;N;;;;; 121C9;CUNEIFORM SIGN LAGAB TIMES HAL;Lo;0;L;;;;;N;;;;; 121CA;CUNEIFORM SIGN LAGAB TIMES HI TIMES NUN;Lo;0;L;;;;;N;;;;; 121CB;CUNEIFORM SIGN LAGAB TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; 121CC;CUNEIFORM SIGN LAGAB TIMES IM;Lo;0;L;;;;;N;;;;; 121CD;CUNEIFORM SIGN LAGAB TIMES IM PLUS HA;Lo;0;L;;;;;N;;;;; 121CE;CUNEIFORM SIGN LAGAB TIMES IM PLUS LU;Lo;0;L;;;;;N;;;;; 121CF;CUNEIFORM SIGN LAGAB TIMES KI;Lo;0;L;;;;;N;;;;; 121D0;CUNEIFORM SIGN LAGAB TIMES KIN;Lo;0;L;;;;;N;;;;; 121D1;CUNEIFORM SIGN LAGAB TIMES KU3;Lo;0;L;;;;;N;;;;; 121D2;CUNEIFORM SIGN LAGAB TIMES KUL;Lo;0;L;;;;;N;;;;; 121D3;CUNEIFORM SIGN LAGAB TIMES KUL PLUS HI PLUS A;Lo;0;L;;;;;N;;;;; 121D4;CUNEIFORM SIGN LAGAB TIMES LAGAB;Lo;0;L;;;;;N;;;;; 121D5;CUNEIFORM SIGN LAGAB TIMES LISH;Lo;0;L;;;;;N;;;;; 121D6;CUNEIFORM SIGN LAGAB TIMES LU;Lo;0;L;;;;;N;;;;; 121D7;CUNEIFORM SIGN LAGAB TIMES LUL;Lo;0;L;;;;;N;;;;; 121D8;CUNEIFORM SIGN LAGAB TIMES ME;Lo;0;L;;;;;N;;;;; 121D9;CUNEIFORM SIGN LAGAB TIMES ME PLUS EN;Lo;0;L;;;;;N;;;;; 121DA;CUNEIFORM SIGN LAGAB TIMES MUSH;Lo;0;L;;;;;N;;;;; 121DB;CUNEIFORM SIGN LAGAB TIMES NE;Lo;0;L;;;;;N;;;;; 121DC;CUNEIFORM SIGN LAGAB TIMES SHE PLUS SUM;Lo;0;L;;;;;N;;;;; 121DD;CUNEIFORM SIGN LAGAB TIMES SHITA PLUS GISH PLUS ERIN2;Lo;0;L;;;;;N;;;;; 121DE;CUNEIFORM SIGN LAGAB TIMES SHITA PLUS GISH TENU;Lo;0;L;;;;;N;;;;; 121DF;CUNEIFORM SIGN LAGAB TIMES SHU2;Lo;0;L;;;;;N;;;;; 121E0;CUNEIFORM SIGN LAGAB TIMES SHU2 PLUS SHU2;Lo;0;L;;;;;N;;;;; 121E1;CUNEIFORM SIGN LAGAB TIMES SUM;Lo;0;L;;;;;N;;;;; 121E2;CUNEIFORM SIGN LAGAB TIMES TAG;Lo;0;L;;;;;N;;;;; 121E3;CUNEIFORM SIGN LAGAB TIMES TAK4;Lo;0;L;;;;;N;;;;; 121E4;CUNEIFORM SIGN LAGAB TIMES TE PLUS A PLUS SU PLUS NA;Lo;0;L;;;;;N;;;;; 121E5;CUNEIFORM SIGN LAGAB TIMES U;Lo;0;L;;;;;N;;;;; 121E6;CUNEIFORM SIGN LAGAB TIMES U PLUS A;Lo;0;L;;;;;N;;;;; 121E7;CUNEIFORM SIGN LAGAB TIMES U PLUS U PLUS U;Lo;0;L;;;;;N;;;;; 121E8;CUNEIFORM SIGN LAGAB TIMES U2 PLUS ASH;Lo;0;L;;;;;N;;;;; 121E9;CUNEIFORM SIGN LAGAB TIMES UD;Lo;0;L;;;;;N;;;;; 121EA;CUNEIFORM SIGN LAGAB TIMES USH;Lo;0;L;;;;;N;;;;; 121EB;CUNEIFORM SIGN LAGAB SQUARED;Lo;0;L;;;;;N;;;;; 121EC;CUNEIFORM SIGN LAGAR;Lo;0;L;;;;;N;;;;; 121ED;CUNEIFORM SIGN LAGAR TIMES SHE;Lo;0;L;;;;;N;;;;; 121EE;CUNEIFORM SIGN LAGAR TIMES SHE PLUS SUM;Lo;0;L;;;;;N;;;;; 121EF;CUNEIFORM SIGN LAGAR GUNU;Lo;0;L;;;;;N;;;;; 121F0;CUNEIFORM SIGN LAGAR GUNU OVER LAGAR GUNU SHE;Lo;0;L;;;;;N;;;;; 121F1;CUNEIFORM SIGN LAHSHU;Lo;0;L;;;;;N;;;;; 121F2;CUNEIFORM SIGN LAL;Lo;0;L;;;;;N;;;;; 121F3;CUNEIFORM SIGN LAL TIMES LAL;Lo;0;L;;;;;N;;;;; 121F4;CUNEIFORM SIGN LAM;Lo;0;L;;;;;N;;;;; 121F5;CUNEIFORM SIGN LAM TIMES KUR;Lo;0;L;;;;;N;;;;; 121F6;CUNEIFORM SIGN LAM TIMES KUR PLUS RU;Lo;0;L;;;;;N;;;;; 121F7;CUNEIFORM SIGN LI;Lo;0;L;;;;;N;;;;; 121F8;CUNEIFORM SIGN LIL;Lo;0;L;;;;;N;;;;; 121F9;CUNEIFORM SIGN LIMMU2;Lo;0;L;;;;;N;;;;; 121FA;CUNEIFORM SIGN LISH;Lo;0;L;;;;;N;;;;; 121FB;CUNEIFORM SIGN LU;Lo;0;L;;;;;N;;;;; 121FC;CUNEIFORM SIGN LU TIMES BAD;Lo;0;L;;;;;N;;;;; 121FD;CUNEIFORM SIGN LU2;Lo;0;L;;;;;N;;;;; 121FE;CUNEIFORM SIGN LU2 TIMES AL;Lo;0;L;;;;;N;;;;; 121FF;CUNEIFORM SIGN LU2 TIMES BAD;Lo;0;L;;;;;N;;;;; 12200;CUNEIFORM SIGN LU2 TIMES ESH2;Lo;0;L;;;;;N;;;;; 12201;CUNEIFORM SIGN LU2 TIMES ESH2 TENU;Lo;0;L;;;;;N;;;;; 12202;CUNEIFORM SIGN LU2 TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; 12203;CUNEIFORM SIGN LU2 TIMES HI TIMES BAD;Lo;0;L;;;;;N;;;;; 12204;CUNEIFORM SIGN LU2 TIMES IM;Lo;0;L;;;;;N;;;;; 12205;CUNEIFORM SIGN LU2 TIMES KAD2;Lo;0;L;;;;;N;;;;; 12206;CUNEIFORM SIGN LU2 TIMES KAD3;Lo;0;L;;;;;N;;;;; 12207;CUNEIFORM SIGN LU2 TIMES KAD3 PLUS ASH;Lo;0;L;;;;;N;;;;; 12208;CUNEIFORM SIGN LU2 TIMES KI;Lo;0;L;;;;;N;;;;; 12209;CUNEIFORM SIGN LU2 TIMES LA PLUS ASH;Lo;0;L;;;;;N;;;;; 1220A;CUNEIFORM SIGN LU2 TIMES LAGAB;Lo;0;L;;;;;N;;;;; 1220B;CUNEIFORM SIGN LU2 TIMES ME PLUS EN;Lo;0;L;;;;;N;;;;; 1220C;CUNEIFORM SIGN LU2 TIMES NE;Lo;0;L;;;;;N;;;;; 1220D;CUNEIFORM SIGN LU2 TIMES NU;Lo;0;L;;;;;N;;;;; 1220E;CUNEIFORM SIGN LU2 TIMES SI PLUS ASH;Lo;0;L;;;;;N;;;;; 1220F;CUNEIFORM SIGN LU2 TIMES SIK2 PLUS BU;Lo;0;L;;;;;N;;;;; 12210;CUNEIFORM SIGN LU2 TIMES TUG2;Lo;0;L;;;;;N;;;;; 12211;CUNEIFORM SIGN LU2 TENU;Lo;0;L;;;;;N;;;;; 12212;CUNEIFORM SIGN LU2 CROSSING LU2;Lo;0;L;;;;;N;;;;; 12213;CUNEIFORM SIGN LU2 OPPOSING LU2;Lo;0;L;;;;;N;;;;; 12214;CUNEIFORM SIGN LU2 SQUARED;Lo;0;L;;;;;N;;;;; 12215;CUNEIFORM SIGN LU2 SHESHIG;Lo;0;L;;;;;N;;;;; 12216;CUNEIFORM SIGN LU3;Lo;0;L;;;;;N;;;;; 12217;CUNEIFORM SIGN LUGAL;Lo;0;L;;;;;N;;;;; 12218;CUNEIFORM SIGN LUGAL OVER LUGAL;Lo;0;L;;;;;N;;;;; 12219;CUNEIFORM SIGN LUGAL OPPOSING LUGAL;Lo;0;L;;;;;N;;;;; 1221A;CUNEIFORM SIGN LUGAL SHESHIG;Lo;0;L;;;;;N;;;;; 1221B;CUNEIFORM SIGN LUH;Lo;0;L;;;;;N;;;;; 1221C;CUNEIFORM SIGN LUL;Lo;0;L;;;;;N;;;;; 1221D;CUNEIFORM SIGN LUM;Lo;0;L;;;;;N;;;;; 1221E;CUNEIFORM SIGN LUM OVER LUM;Lo;0;L;;;;;N;;;;; 1221F;CUNEIFORM SIGN LUM OVER LUM GAR OVER GAR;Lo;0;L;;;;;N;;;;; 12220;CUNEIFORM SIGN MA;Lo;0;L;;;;;N;;;;; 12221;CUNEIFORM SIGN MA TIMES TAK4;Lo;0;L;;;;;N;;;;; 12222;CUNEIFORM SIGN MA GUNU;Lo;0;L;;;;;N;;;;; 12223;CUNEIFORM SIGN MA2;Lo;0;L;;;;;N;;;;; 12224;CUNEIFORM SIGN MAH;Lo;0;L;;;;;N;;;;; 12225;CUNEIFORM SIGN MAR;Lo;0;L;;;;;N;;;;; 12226;CUNEIFORM SIGN MASH;Lo;0;L;;;;;N;;;;; 12227;CUNEIFORM SIGN MASH2;Lo;0;L;;;;;N;;;;; 12228;CUNEIFORM SIGN ME;Lo;0;L;;;;;N;;;;; 12229;CUNEIFORM SIGN MES;Lo;0;L;;;;;N;;;;; 1222A;CUNEIFORM SIGN MI;Lo;0;L;;;;;N;;;;; 1222B;CUNEIFORM SIGN MIN;Lo;0;L;;;;;N;;;;; 1222C;CUNEIFORM SIGN MU;Lo;0;L;;;;;N;;;;; 1222D;CUNEIFORM SIGN MU OVER MU;Lo;0;L;;;;;N;;;;; 1222E;CUNEIFORM SIGN MUG;Lo;0;L;;;;;N;;;;; 1222F;CUNEIFORM SIGN MUG GUNU;Lo;0;L;;;;;N;;;;; 12230;CUNEIFORM SIGN MUNSUB;Lo;0;L;;;;;N;;;;; 12231;CUNEIFORM SIGN MURGU2;Lo;0;L;;;;;N;;;;; 12232;CUNEIFORM SIGN MUSH;Lo;0;L;;;;;N;;;;; 12233;CUNEIFORM SIGN MUSH TIMES A;Lo;0;L;;;;;N;;;;; 12234;CUNEIFORM SIGN MUSH TIMES KUR;Lo;0;L;;;;;N;;;;; 12235;CUNEIFORM SIGN MUSH TIMES ZA;Lo;0;L;;;;;N;;;;; 12236;CUNEIFORM SIGN MUSH OVER MUSH;Lo;0;L;;;;;N;;;;; 12237;CUNEIFORM SIGN MUSH OVER MUSH TIMES A PLUS NA;Lo;0;L;;;;;N;;;;; 12238;CUNEIFORM SIGN MUSH CROSSING MUSH;Lo;0;L;;;;;N;;;;; 12239;CUNEIFORM SIGN MUSH3;Lo;0;L;;;;;N;;;;; 1223A;CUNEIFORM SIGN MUSH3 TIMES A;Lo;0;L;;;;;N;;;;; 1223B;CUNEIFORM SIGN MUSH3 TIMES A PLUS DI;Lo;0;L;;;;;N;;;;; 1223C;CUNEIFORM SIGN MUSH3 TIMES DI;Lo;0;L;;;;;N;;;;; 1223D;CUNEIFORM SIGN MUSH3 GUNU;Lo;0;L;;;;;N;;;;; 1223E;CUNEIFORM SIGN NA;Lo;0;L;;;;;N;;;;; 1223F;CUNEIFORM SIGN NA2;Lo;0;L;;;;;N;;;;; 12240;CUNEIFORM SIGN NAGA;Lo;0;L;;;;;N;;;;; 12241;CUNEIFORM SIGN NAGA INVERTED;Lo;0;L;;;;;N;;;;; 12242;CUNEIFORM SIGN NAGA TIMES SHU TENU;Lo;0;L;;;;;N;;;;; 12243;CUNEIFORM SIGN NAGA OPPOSING NAGA;Lo;0;L;;;;;N;;;;; 12244;CUNEIFORM SIGN NAGAR;Lo;0;L;;;;;N;;;;; 12245;CUNEIFORM SIGN NAM NUTILLU;Lo;0;L;;;;;N;;;;; 12246;CUNEIFORM SIGN NAM;Lo;0;L;;;;;N;;;;; 12247;CUNEIFORM SIGN NAM2;Lo;0;L;;;;;N;;;;; 12248;CUNEIFORM SIGN NE;Lo;0;L;;;;;N;;;;; 12249;CUNEIFORM SIGN NE TIMES A;Lo;0;L;;;;;N;;;;; 1224A;CUNEIFORM SIGN NE TIMES UD;Lo;0;L;;;;;N;;;;; 1224B;CUNEIFORM SIGN NE SHESHIG;Lo;0;L;;;;;N;;;;; 1224C;CUNEIFORM SIGN NI;Lo;0;L;;;;;N;;;;; 1224D;CUNEIFORM SIGN NI TIMES E;Lo;0;L;;;;;N;;;;; 1224E;CUNEIFORM SIGN NI2;Lo;0;L;;;;;N;;;;; 1224F;CUNEIFORM SIGN NIM;Lo;0;L;;;;;N;;;;; 12250;CUNEIFORM SIGN NIM TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; 12251;CUNEIFORM SIGN NIM TIMES GAR PLUS GAN2 TENU;Lo;0;L;;;;;N;;;;; 12252;CUNEIFORM SIGN NINDA2;Lo;0;L;;;;;N;;;;; 12253;CUNEIFORM SIGN NINDA2 TIMES AN;Lo;0;L;;;;;N;;;;; 12254;CUNEIFORM SIGN NINDA2 TIMES ASH;Lo;0;L;;;;;N;;;;; 12255;CUNEIFORM SIGN NINDA2 TIMES ASH PLUS ASH;Lo;0;L;;;;;N;;;;; 12256;CUNEIFORM SIGN NINDA2 TIMES GUD;Lo;0;L;;;;;N;;;;; 12257;CUNEIFORM SIGN NINDA2 TIMES ME PLUS GAN2 TENU;Lo;0;L;;;;;N;;;;; 12258;CUNEIFORM SIGN NINDA2 TIMES NE;Lo;0;L;;;;;N;;;;; 12259;CUNEIFORM SIGN NINDA2 TIMES NUN;Lo;0;L;;;;;N;;;;; 1225A;CUNEIFORM SIGN NINDA2 TIMES SHE;Lo;0;L;;;;;N;;;;; 1225B;CUNEIFORM SIGN NINDA2 TIMES SHE PLUS A AN;Lo;0;L;;;;;N;;;;; 1225C;CUNEIFORM SIGN NINDA2 TIMES SHE PLUS ASH;Lo;0;L;;;;;N;;;;; 1225D;CUNEIFORM SIGN NINDA2 TIMES SHE PLUS ASH PLUS ASH;Lo;0;L;;;;;N;;;;; 1225E;CUNEIFORM SIGN NINDA2 TIMES U2 PLUS ASH;Lo;0;L;;;;;N;;;;; 1225F;CUNEIFORM SIGN NINDA2 TIMES USH;Lo;0;L;;;;;N;;;;; 12260;CUNEIFORM SIGN NISAG;Lo;0;L;;;;;N;;;;; 12261;CUNEIFORM SIGN NU;Lo;0;L;;;;;N;;;;; 12262;CUNEIFORM SIGN NU11;Lo;0;L;;;;;N;;;;; 12263;CUNEIFORM SIGN NUN;Lo;0;L;;;;;N;;;;; 12264;CUNEIFORM SIGN NUN LAGAR TIMES GAR;Lo;0;L;;;;;N;;;;; 12265;CUNEIFORM SIGN NUN LAGAR TIMES MASH;Lo;0;L;;;;;N;;;;; 12266;CUNEIFORM SIGN NUN LAGAR TIMES SAL;Lo;0;L;;;;;N;;;;; 12267;CUNEIFORM SIGN NUN LAGAR TIMES SAL OVER NUN LAGAR TIMES SAL;Lo;0;L;;;;;N;;;;; 12268;CUNEIFORM SIGN NUN LAGAR TIMES USH;Lo;0;L;;;;;N;;;;; 12269;CUNEIFORM SIGN NUN TENU;Lo;0;L;;;;;N;;;;; 1226A;CUNEIFORM SIGN NUN OVER NUN;Lo;0;L;;;;;N;;;;; 1226B;CUNEIFORM SIGN NUN CROSSING NUN;Lo;0;L;;;;;N;;;;; 1226C;CUNEIFORM SIGN NUN CROSSING NUN LAGAR OVER LAGAR;Lo;0;L;;;;;N;;;;; 1226D;CUNEIFORM SIGN NUNUZ;Lo;0;L;;;;;N;;;;; 1226E;CUNEIFORM SIGN NUNUZ AB2 TIMES ASHGAB;Lo;0;L;;;;;N;;;;; 1226F;CUNEIFORM SIGN NUNUZ AB2 TIMES BI;Lo;0;L;;;;;N;;;;; 12270;CUNEIFORM SIGN NUNUZ AB2 TIMES DUG;Lo;0;L;;;;;N;;;;; 12271;CUNEIFORM SIGN NUNUZ AB2 TIMES GUD;Lo;0;L;;;;;N;;;;; 12272;CUNEIFORM SIGN NUNUZ AB2 TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; 12273;CUNEIFORM SIGN NUNUZ AB2 TIMES KAD3;Lo;0;L;;;;;N;;;;; 12274;CUNEIFORM SIGN NUNUZ AB2 TIMES LA;Lo;0;L;;;;;N;;;;; 12275;CUNEIFORM SIGN NUNUZ AB2 TIMES NE;Lo;0;L;;;;;N;;;;; 12276;CUNEIFORM SIGN NUNUZ AB2 TIMES SILA3;Lo;0;L;;;;;N;;;;; 12277;CUNEIFORM SIGN NUNUZ AB2 TIMES U2;Lo;0;L;;;;;N;;;;; 12278;CUNEIFORM SIGN NUNUZ KISIM5 TIMES BI;Lo;0;L;;;;;N;;;;; 12279;CUNEIFORM SIGN NUNUZ KISIM5 TIMES BI U;Lo;0;L;;;;;N;;;;; 1227A;CUNEIFORM SIGN PA;Lo;0;L;;;;;N;;;;; 1227B;CUNEIFORM SIGN PAD;Lo;0;L;;;;;N;;;;; 1227C;CUNEIFORM SIGN PAN;Lo;0;L;;;;;N;;;;; 1227D;CUNEIFORM SIGN PAP;Lo;0;L;;;;;N;;;;; 1227E;CUNEIFORM SIGN PESH2;Lo;0;L;;;;;N;;;;; 1227F;CUNEIFORM SIGN PI;Lo;0;L;;;;;N;;;;; 12280;CUNEIFORM SIGN PI TIMES A;Lo;0;L;;;;;N;;;;; 12281;CUNEIFORM SIGN PI TIMES AB;Lo;0;L;;;;;N;;;;; 12282;CUNEIFORM SIGN PI TIMES BI;Lo;0;L;;;;;N;;;;; 12283;CUNEIFORM SIGN PI TIMES BU;Lo;0;L;;;;;N;;;;; 12284;CUNEIFORM SIGN PI TIMES E;Lo;0;L;;;;;N;;;;; 12285;CUNEIFORM SIGN PI TIMES I;Lo;0;L;;;;;N;;;;; 12286;CUNEIFORM SIGN PI TIMES IB;Lo;0;L;;;;;N;;;;; 12287;CUNEIFORM SIGN PI TIMES U;Lo;0;L;;;;;N;;;;; 12288;CUNEIFORM SIGN PI TIMES U2;Lo;0;L;;;;;N;;;;; 12289;CUNEIFORM SIGN PI CROSSING PI;Lo;0;L;;;;;N;;;;; 1228A;CUNEIFORM SIGN PIRIG;Lo;0;L;;;;;N;;;;; 1228B;CUNEIFORM SIGN PIRIG TIMES KAL;Lo;0;L;;;;;N;;;;; 1228C;CUNEIFORM SIGN PIRIG TIMES UD;Lo;0;L;;;;;N;;;;; 1228D;CUNEIFORM SIGN PIRIG TIMES ZA;Lo;0;L;;;;;N;;;;; 1228E;CUNEIFORM SIGN PIRIG OPPOSING PIRIG;Lo;0;L;;;;;N;;;;; 1228F;CUNEIFORM SIGN RA;Lo;0;L;;;;;N;;;;; 12290;CUNEIFORM SIGN RAB;Lo;0;L;;;;;N;;;;; 12291;CUNEIFORM SIGN RI;Lo;0;L;;;;;N;;;;; 12292;CUNEIFORM SIGN RU;Lo;0;L;;;;;N;;;;; 12293;CUNEIFORM SIGN SA;Lo;0;L;;;;;N;;;;; 12294;CUNEIFORM SIGN SAG NUTILLU;Lo;0;L;;;;;N;;;;; 12295;CUNEIFORM SIGN SAG;Lo;0;L;;;;;N;;;;; 12296;CUNEIFORM SIGN SAG TIMES A;Lo;0;L;;;;;N;;;;; 12297;CUNEIFORM SIGN SAG TIMES DU;Lo;0;L;;;;;N;;;;; 12298;CUNEIFORM SIGN SAG TIMES DUB;Lo;0;L;;;;;N;;;;; 12299;CUNEIFORM SIGN SAG TIMES HA;Lo;0;L;;;;;N;;;;; 1229A;CUNEIFORM SIGN SAG TIMES KAK;Lo;0;L;;;;;N;;;;; 1229B;CUNEIFORM SIGN SAG TIMES KUR;Lo;0;L;;;;;N;;;;; 1229C;CUNEIFORM SIGN SAG TIMES LUM;Lo;0;L;;;;;N;;;;; 1229D;CUNEIFORM SIGN SAG TIMES MI;Lo;0;L;;;;;N;;;;; 1229E;CUNEIFORM SIGN SAG TIMES NUN;Lo;0;L;;;;;N;;;;; 1229F;CUNEIFORM SIGN SAG TIMES SAL;Lo;0;L;;;;;N;;;;; 122A0;CUNEIFORM SIGN SAG TIMES SHID;Lo;0;L;;;;;N;;;;; 122A1;CUNEIFORM SIGN SAG TIMES TAB;Lo;0;L;;;;;N;;;;; 122A2;CUNEIFORM SIGN SAG TIMES U2;Lo;0;L;;;;;N;;;;; 122A3;CUNEIFORM SIGN SAG TIMES UB;Lo;0;L;;;;;N;;;;; 122A4;CUNEIFORM SIGN SAG TIMES UM;Lo;0;L;;;;;N;;;;; 122A5;CUNEIFORM SIGN SAG TIMES UR;Lo;0;L;;;;;N;;;;; 122A6;CUNEIFORM SIGN SAG TIMES USH;Lo;0;L;;;;;N;;;;; 122A7;CUNEIFORM SIGN SAG OVER SAG;Lo;0;L;;;;;N;;;;; 122A8;CUNEIFORM SIGN SAG GUNU;Lo;0;L;;;;;N;;;;; 122A9;CUNEIFORM SIGN SAL;Lo;0;L;;;;;N;;;;; 122AA;CUNEIFORM SIGN SAL LAGAB TIMES ASH2;Lo;0;L;;;;;N;;;;; 122AB;CUNEIFORM SIGN SANGA2;Lo;0;L;;;;;N;;;;; 122AC;CUNEIFORM SIGN SAR;Lo;0;L;;;;;N;;;;; 122AD;CUNEIFORM SIGN SHA;Lo;0;L;;;;;N;;;;; 122AE;CUNEIFORM SIGN SHA3;Lo;0;L;;;;;N;;;;; 122AF;CUNEIFORM SIGN SHA3 TIMES A;Lo;0;L;;;;;N;;;;; 122B0;CUNEIFORM SIGN SHA3 TIMES BAD;Lo;0;L;;;;;N;;;;; 122B1;CUNEIFORM SIGN SHA3 TIMES GISH;Lo;0;L;;;;;N;;;;; 122B2;CUNEIFORM SIGN SHA3 TIMES NE;Lo;0;L;;;;;N;;;;; 122B3;CUNEIFORM SIGN SHA3 TIMES SHU2;Lo;0;L;;;;;N;;;;; 122B4;CUNEIFORM SIGN SHA3 TIMES TUR;Lo;0;L;;;;;N;;;;; 122B5;CUNEIFORM SIGN SHA3 TIMES U;Lo;0;L;;;;;N;;;;; 122B6;CUNEIFORM SIGN SHA3 TIMES U PLUS A;Lo;0;L;;;;;N;;;;; 122B7;CUNEIFORM SIGN SHA6;Lo;0;L;;;;;N;;;;; 122B8;CUNEIFORM SIGN SHAB6;Lo;0;L;;;;;N;;;;; 122B9;CUNEIFORM SIGN SHAR2;Lo;0;L;;;;;N;;;;; 122BA;CUNEIFORM SIGN SHE;Lo;0;L;;;;;N;;;;; 122BB;CUNEIFORM SIGN SHE HU;Lo;0;L;;;;;N;;;;; 122BC;CUNEIFORM SIGN SHE OVER SHE GAD OVER GAD GAR OVER GAR;Lo;0;L;;;;;N;;;;; 122BD;CUNEIFORM SIGN SHE OVER SHE TAB OVER TAB GAR OVER GAR;Lo;0;L;;;;;N;;;;; 122BE;CUNEIFORM SIGN SHEG9;Lo;0;L;;;;;N;;;;; 122BF;CUNEIFORM SIGN SHEN;Lo;0;L;;;;;N;;;;; 122C0;CUNEIFORM SIGN SHESH;Lo;0;L;;;;;N;;;;; 122C1;CUNEIFORM SIGN SHESH2;Lo;0;L;;;;;N;;;;; 122C2;CUNEIFORM SIGN SHESHLAM;Lo;0;L;;;;;N;;;;; 122C3;CUNEIFORM SIGN SHID;Lo;0;L;;;;;N;;;;; 122C4;CUNEIFORM SIGN SHID TIMES A;Lo;0;L;;;;;N;;;;; 122C5;CUNEIFORM SIGN SHID TIMES IM;Lo;0;L;;;;;N;;;;; 122C6;CUNEIFORM SIGN SHIM;Lo;0;L;;;;;N;;;;; 122C7;CUNEIFORM SIGN SHIM TIMES A;Lo;0;L;;;;;N;;;;; 122C8;CUNEIFORM SIGN SHIM TIMES BAL;Lo;0;L;;;;;N;;;;; 122C9;CUNEIFORM SIGN SHIM TIMES BULUG;Lo;0;L;;;;;N;;;;; 122CA;CUNEIFORM SIGN SHIM TIMES DIN;Lo;0;L;;;;;N;;;;; 122CB;CUNEIFORM SIGN SHIM TIMES GAR;Lo;0;L;;;;;N;;;;; 122CC;CUNEIFORM SIGN SHIM TIMES IGI;Lo;0;L;;;;;N;;;;; 122CD;CUNEIFORM SIGN SHIM TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; 122CE;CUNEIFORM SIGN SHIM TIMES KUSHU2;Lo;0;L;;;;;N;;;;; 122CF;CUNEIFORM SIGN SHIM TIMES LUL;Lo;0;L;;;;;N;;;;; 122D0;CUNEIFORM SIGN SHIM TIMES MUG;Lo;0;L;;;;;N;;;;; 122D1;CUNEIFORM SIGN SHIM TIMES SAL;Lo;0;L;;;;;N;;;;; 122D2;CUNEIFORM SIGN SHINIG;Lo;0;L;;;;;N;;;;; 122D3;CUNEIFORM SIGN SHIR;Lo;0;L;;;;;N;;;;; 122D4;CUNEIFORM SIGN SHIR TENU;Lo;0;L;;;;;N;;;;; 122D5;CUNEIFORM SIGN SHIR OVER SHIR BUR OVER BUR;Lo;0;L;;;;;N;;;;; 122D6;CUNEIFORM SIGN SHITA;Lo;0;L;;;;;N;;;;; 122D7;CUNEIFORM SIGN SHU;Lo;0;L;;;;;N;;;;; 122D8;CUNEIFORM SIGN SHU OVER INVERTED SHU;Lo;0;L;;;;;N;;;;; 122D9;CUNEIFORM SIGN SHU2;Lo;0;L;;;;;N;;;;; 122DA;CUNEIFORM SIGN SHUBUR;Lo;0;L;;;;;N;;;;; 122DB;CUNEIFORM SIGN SI;Lo;0;L;;;;;N;;;;; 122DC;CUNEIFORM SIGN SI GUNU;Lo;0;L;;;;;N;;;;; 122DD;CUNEIFORM SIGN SIG;Lo;0;L;;;;;N;;;;; 122DE;CUNEIFORM SIGN SIG4;Lo;0;L;;;;;N;;;;; 122DF;CUNEIFORM SIGN SIG4 OVER SIG4 SHU2;Lo;0;L;;;;;N;;;;; 122E0;CUNEIFORM SIGN SIK2;Lo;0;L;;;;;N;;;;; 122E1;CUNEIFORM SIGN SILA3;Lo;0;L;;;;;N;;;;; 122E2;CUNEIFORM SIGN SU;Lo;0;L;;;;;N;;;;; 122E3;CUNEIFORM SIGN SU OVER SU;Lo;0;L;;;;;N;;;;; 122E4;CUNEIFORM SIGN SUD;Lo;0;L;;;;;N;;;;; 122E5;CUNEIFORM SIGN SUD2;Lo;0;L;;;;;N;;;;; 122E6;CUNEIFORM SIGN SUHUR;Lo;0;L;;;;;N;;;;; 122E7;CUNEIFORM SIGN SUM;Lo;0;L;;;;;N;;;;; 122E8;CUNEIFORM SIGN SUMASH;Lo;0;L;;;;;N;;;;; 122E9;CUNEIFORM SIGN SUR;Lo;0;L;;;;;N;;;;; 122EA;CUNEIFORM SIGN SUR9;Lo;0;L;;;;;N;;;;; 122EB;CUNEIFORM SIGN TA;Lo;0;L;;;;;N;;;;; 122EC;CUNEIFORM SIGN TA ASTERISK;Lo;0;L;;;;;N;;;;; 122ED;CUNEIFORM SIGN TA TIMES HI;Lo;0;L;;;;;N;;;;; 122EE;CUNEIFORM SIGN TA TIMES MI;Lo;0;L;;;;;N;;;;; 122EF;CUNEIFORM SIGN TA GUNU;Lo;0;L;;;;;N;;;;; 122F0;CUNEIFORM SIGN TAB;Lo;0;L;;;;;N;;;;; 122F1;CUNEIFORM SIGN TAB OVER TAB NI OVER NI DISH OVER DISH;Lo;0;L;;;;;N;;;;; 122F2;CUNEIFORM SIGN TAB SQUARED;Lo;0;L;;;;;N;;;;; 122F3;CUNEIFORM SIGN TAG;Lo;0;L;;;;;N;;;;; 122F4;CUNEIFORM SIGN TAG TIMES BI;Lo;0;L;;;;;N;;;;; 122F5;CUNEIFORM SIGN TAG TIMES GUD;Lo;0;L;;;;;N;;;;; 122F6;CUNEIFORM SIGN TAG TIMES SHE;Lo;0;L;;;;;N;;;;; 122F7;CUNEIFORM SIGN TAG TIMES SHU;Lo;0;L;;;;;N;;;;; 122F8;CUNEIFORM SIGN TAG TIMES TUG2;Lo;0;L;;;;;N;;;;; 122F9;CUNEIFORM SIGN TAG TIMES UD;Lo;0;L;;;;;N;;;;; 122FA;CUNEIFORM SIGN TAK4;Lo;0;L;;;;;N;;;;; 122FB;CUNEIFORM SIGN TAR;Lo;0;L;;;;;N;;;;; 122FC;CUNEIFORM SIGN TE;Lo;0;L;;;;;N;;;;; 122FD;CUNEIFORM SIGN TE GUNU;Lo;0;L;;;;;N;;;;; 122FE;CUNEIFORM SIGN TI;Lo;0;L;;;;;N;;;;; 122FF;CUNEIFORM SIGN TI TENU;Lo;0;L;;;;;N;;;;; 12300;CUNEIFORM SIGN TIL;Lo;0;L;;;;;N;;;;; 12301;CUNEIFORM SIGN TIR;Lo;0;L;;;;;N;;;;; 12302;CUNEIFORM SIGN TIR TIMES TAK4;Lo;0;L;;;;;N;;;;; 12303;CUNEIFORM SIGN TIR OVER TIR;Lo;0;L;;;;;N;;;;; 12304;CUNEIFORM SIGN TIR OVER TIR GAD OVER GAD GAR OVER GAR;Lo;0;L;;;;;N;;;;; 12305;CUNEIFORM SIGN TU;Lo;0;L;;;;;N;;;;; 12306;CUNEIFORM SIGN TUG2;Lo;0;L;;;;;N;;;;; 12307;CUNEIFORM SIGN TUK;Lo;0;L;;;;;N;;;;; 12308;CUNEIFORM SIGN TUM;Lo;0;L;;;;;N;;;;; 12309;CUNEIFORM SIGN TUR;Lo;0;L;;;;;N;;;;; 1230A;CUNEIFORM SIGN TUR OVER TUR ZA OVER ZA;Lo;0;L;;;;;N;;;;; 1230B;CUNEIFORM SIGN U;Lo;0;L;;;;;N;;;;; 1230C;CUNEIFORM SIGN U GUD;Lo;0;L;;;;;N;;;;; 1230D;CUNEIFORM SIGN U U U;Lo;0;L;;;;;N;;;;; 1230E;CUNEIFORM SIGN U OVER U PA OVER PA GAR OVER GAR;Lo;0;L;;;;;N;;;;; 1230F;CUNEIFORM SIGN U OVER U SUR OVER SUR;Lo;0;L;;;;;N;;;;; 12310;CUNEIFORM SIGN U OVER U U REVERSED OVER U REVERSED;Lo;0;L;;;;;N;;;;; 12311;CUNEIFORM SIGN U2;Lo;0;L;;;;;N;;;;; 12312;CUNEIFORM SIGN UB;Lo;0;L;;;;;N;;;;; 12313;CUNEIFORM SIGN UD;Lo;0;L;;;;;N;;;;; 12314;CUNEIFORM SIGN UD KUSHU2;Lo;0;L;;;;;N;;;;; 12315;CUNEIFORM SIGN UD TIMES BAD;Lo;0;L;;;;;N;;;;; 12316;CUNEIFORM SIGN UD TIMES MI;Lo;0;L;;;;;N;;;;; 12317;CUNEIFORM SIGN UD TIMES U PLUS U PLUS U;Lo;0;L;;;;;N;;;;; 12318;CUNEIFORM SIGN UD TIMES U PLUS U PLUS U GUNU;Lo;0;L;;;;;N;;;;; 12319;CUNEIFORM SIGN UD GUNU;Lo;0;L;;;;;N;;;;; 1231A;CUNEIFORM SIGN UD SHESHIG;Lo;0;L;;;;;N;;;;; 1231B;CUNEIFORM SIGN UD SHESHIG TIMES BAD;Lo;0;L;;;;;N;;;;; 1231C;CUNEIFORM SIGN UDUG;Lo;0;L;;;;;N;;;;; 1231D;CUNEIFORM SIGN UM;Lo;0;L;;;;;N;;;;; 1231E;CUNEIFORM SIGN UM TIMES LAGAB;Lo;0;L;;;;;N;;;;; 1231F;CUNEIFORM SIGN UM TIMES ME PLUS DA;Lo;0;L;;;;;N;;;;; 12320;CUNEIFORM SIGN UM TIMES SHA3;Lo;0;L;;;;;N;;;;; 12321;CUNEIFORM SIGN UM TIMES U;Lo;0;L;;;;;N;;;;; 12322;CUNEIFORM SIGN UMBIN;Lo;0;L;;;;;N;;;;; 12323;CUNEIFORM SIGN UMUM;Lo;0;L;;;;;N;;;;; 12324;CUNEIFORM SIGN UMUM TIMES KASKAL;Lo;0;L;;;;;N;;;;; 12325;CUNEIFORM SIGN UMUM TIMES PA;Lo;0;L;;;;;N;;;;; 12326;CUNEIFORM SIGN UN;Lo;0;L;;;;;N;;;;; 12327;CUNEIFORM SIGN UN GUNU;Lo;0;L;;;;;N;;;;; 12328;CUNEIFORM SIGN UR;Lo;0;L;;;;;N;;;;; 12329;CUNEIFORM SIGN UR CROSSING UR;Lo;0;L;;;;;N;;;;; 1232A;CUNEIFORM SIGN UR SHESHIG;Lo;0;L;;;;;N;;;;; 1232B;CUNEIFORM SIGN UR2;Lo;0;L;;;;;N;;;;; 1232C;CUNEIFORM SIGN UR2 TIMES A PLUS HA;Lo;0;L;;;;;N;;;;; 1232D;CUNEIFORM SIGN UR2 TIMES A PLUS NA;Lo;0;L;;;;;N;;;;; 1232E;CUNEIFORM SIGN UR2 TIMES AL;Lo;0;L;;;;;N;;;;; 1232F;CUNEIFORM SIGN UR2 TIMES HA;Lo;0;L;;;;;N;;;;; 12330;CUNEIFORM SIGN UR2 TIMES NUN;Lo;0;L;;;;;N;;;;; 12331;CUNEIFORM SIGN UR2 TIMES U2;Lo;0;L;;;;;N;;;;; 12332;CUNEIFORM SIGN UR2 TIMES U2 PLUS ASH;Lo;0;L;;;;;N;;;;; 12333;CUNEIFORM SIGN UR2 TIMES U2 PLUS BI;Lo;0;L;;;;;N;;;;; 12334;CUNEIFORM SIGN UR4;Lo;0;L;;;;;N;;;;; 12335;CUNEIFORM SIGN URI;Lo;0;L;;;;;N;;;;; 12336;CUNEIFORM SIGN URI3;Lo;0;L;;;;;N;;;;; 12337;CUNEIFORM SIGN URU;Lo;0;L;;;;;N;;;;; 12338;CUNEIFORM SIGN URU TIMES A;Lo;0;L;;;;;N;;;;; 12339;CUNEIFORM SIGN URU TIMES ASHGAB;Lo;0;L;;;;;N;;;;; 1233A;CUNEIFORM SIGN URU TIMES BAR;Lo;0;L;;;;;N;;;;; 1233B;CUNEIFORM SIGN URU TIMES DUN;Lo;0;L;;;;;N;;;;; 1233C;CUNEIFORM SIGN URU TIMES GA;Lo;0;L;;;;;N;;;;; 1233D;CUNEIFORM SIGN URU TIMES GAL;Lo;0;L;;;;;N;;;;; 1233E;CUNEIFORM SIGN URU TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; 1233F;CUNEIFORM SIGN URU TIMES GAR;Lo;0;L;;;;;N;;;;; 12340;CUNEIFORM SIGN URU TIMES GU;Lo;0;L;;;;;N;;;;; 12341;CUNEIFORM SIGN URU TIMES HA;Lo;0;L;;;;;N;;;;; 12342;CUNEIFORM SIGN URU TIMES IGI;Lo;0;L;;;;;N;;;;; 12343;CUNEIFORM SIGN URU TIMES IM;Lo;0;L;;;;;N;;;;; 12344;CUNEIFORM SIGN URU TIMES ISH;Lo;0;L;;;;;N;;;;; 12345;CUNEIFORM SIGN URU TIMES KI;Lo;0;L;;;;;N;;;;; 12346;CUNEIFORM SIGN URU TIMES LUM;Lo;0;L;;;;;N;;;;; 12347;CUNEIFORM SIGN URU TIMES MIN;Lo;0;L;;;;;N;;;;; 12348;CUNEIFORM SIGN URU TIMES PA;Lo;0;L;;;;;N;;;;; 12349;CUNEIFORM SIGN URU TIMES SHE;Lo;0;L;;;;;N;;;;; 1234A;CUNEIFORM SIGN URU TIMES SIG4;Lo;0;L;;;;;N;;;;; 1234B;CUNEIFORM SIGN URU TIMES TU;Lo;0;L;;;;;N;;;;; 1234C;CUNEIFORM SIGN URU TIMES U PLUS GUD;Lo;0;L;;;;;N;;;;; 1234D;CUNEIFORM SIGN URU TIMES UD;Lo;0;L;;;;;N;;;;; 1234E;CUNEIFORM SIGN URU TIMES URUDA;Lo;0;L;;;;;N;;;;; 1234F;CUNEIFORM SIGN URUDA;Lo;0;L;;;;;N;;;;; 12350;CUNEIFORM SIGN URUDA TIMES U;Lo;0;L;;;;;N;;;;; 12351;CUNEIFORM SIGN USH;Lo;0;L;;;;;N;;;;; 12352;CUNEIFORM SIGN USH TIMES A;Lo;0;L;;;;;N;;;;; 12353;CUNEIFORM SIGN USH TIMES KU;Lo;0;L;;;;;N;;;;; 12354;CUNEIFORM SIGN USH TIMES KUR;Lo;0;L;;;;;N;;;;; 12355;CUNEIFORM SIGN USH TIMES TAK4;Lo;0;L;;;;;N;;;;; 12356;CUNEIFORM SIGN USHX;Lo;0;L;;;;;N;;;;; 12357;CUNEIFORM SIGN USH2;Lo;0;L;;;;;N;;;;; 12358;CUNEIFORM SIGN USHUMX;Lo;0;L;;;;;N;;;;; 12359;CUNEIFORM SIGN UTUKI;Lo;0;L;;;;;N;;;;; 1235A;CUNEIFORM SIGN UZ3;Lo;0;L;;;;;N;;;;; 1235B;CUNEIFORM SIGN UZ3 TIMES KASKAL;Lo;0;L;;;;;N;;;;; 1235C;CUNEIFORM SIGN UZU;Lo;0;L;;;;;N;;;;; 1235D;CUNEIFORM SIGN ZA;Lo;0;L;;;;;N;;;;; 1235E;CUNEIFORM SIGN ZA TENU;Lo;0;L;;;;;N;;;;; 1235F;CUNEIFORM SIGN ZA SQUARED TIMES KUR;Lo;0;L;;;;;N;;;;; 12360;CUNEIFORM SIGN ZAG;Lo;0;L;;;;;N;;;;; 12361;CUNEIFORM SIGN ZAMX;Lo;0;L;;;;;N;;;;; 12362;CUNEIFORM SIGN ZE2;Lo;0;L;;;;;N;;;;; 12363;CUNEIFORM SIGN ZI;Lo;0;L;;;;;N;;;;; 12364;CUNEIFORM SIGN ZI OVER ZI;Lo;0;L;;;;;N;;;;; 12365;CUNEIFORM SIGN ZI3;Lo;0;L;;;;;N;;;;; 12366;CUNEIFORM SIGN ZIB;Lo;0;L;;;;;N;;;;; 12367;CUNEIFORM SIGN ZIB KABA TENU;Lo;0;L;;;;;N;;;;; 12368;CUNEIFORM SIGN ZIG;Lo;0;L;;;;;N;;;;; 12369;CUNEIFORM SIGN ZIZ2;Lo;0;L;;;;;N;;;;; 1236A;CUNEIFORM SIGN ZU;Lo;0;L;;;;;N;;;;; 1236B;CUNEIFORM SIGN ZU5;Lo;0;L;;;;;N;;;;; 1236C;CUNEIFORM SIGN ZU5 TIMES A;Lo;0;L;;;;;N;;;;; 1236D;CUNEIFORM SIGN ZUBUR;Lo;0;L;;;;;N;;;;; 1236E;CUNEIFORM SIGN ZUM;Lo;0;L;;;;;N;;;;; 1236F;CUNEIFORM SIGN KAP ELAMITE;Lo;0;L;;;;;N;;;;; 12370;CUNEIFORM SIGN AB TIMES NUN;Lo;0;L;;;;;N;;;;; 12371;CUNEIFORM SIGN AB2 TIMES A;Lo;0;L;;;;;N;;;;; 12372;CUNEIFORM SIGN AMAR TIMES KUG;Lo;0;L;;;;;N;;;;; 12373;CUNEIFORM SIGN DAG KISIM5 TIMES U2 PLUS MASH;Lo;0;L;;;;;N;;;;; 12374;CUNEIFORM SIGN DAG3;Lo;0;L;;;;;N;;;;; 12375;CUNEIFORM SIGN DISH PLUS SHU;Lo;0;L;;;;;N;;;;; 12376;CUNEIFORM SIGN DUB TIMES SHE;Lo;0;L;;;;;N;;;;; 12377;CUNEIFORM SIGN EZEN TIMES GUD;Lo;0;L;;;;;N;;;;; 12378;CUNEIFORM SIGN EZEN TIMES SHE;Lo;0;L;;;;;N;;;;; 12379;CUNEIFORM SIGN GA2 TIMES AN PLUS KAK PLUS A;Lo;0;L;;;;;N;;;;; 1237A;CUNEIFORM SIGN GA2 TIMES ASH2;Lo;0;L;;;;;N;;;;; 1237B;CUNEIFORM SIGN GE22;Lo;0;L;;;;;N;;;;; 1237C;CUNEIFORM SIGN GIG;Lo;0;L;;;;;N;;;;; 1237D;CUNEIFORM SIGN HUSH;Lo;0;L;;;;;N;;;;; 1237E;CUNEIFORM SIGN KA TIMES ANSHE;Lo;0;L;;;;;N;;;;; 1237F;CUNEIFORM SIGN KA TIMES ASH3;Lo;0;L;;;;;N;;;;; 12380;CUNEIFORM SIGN KA TIMES GISH;Lo;0;L;;;;;N;;;;; 12381;CUNEIFORM SIGN KA TIMES GUD;Lo;0;L;;;;;N;;;;; 12382;CUNEIFORM SIGN KA TIMES HI TIMES ASH2;Lo;0;L;;;;;N;;;;; 12383;CUNEIFORM SIGN KA TIMES LUM;Lo;0;L;;;;;N;;;;; 12384;CUNEIFORM SIGN KA TIMES PA;Lo;0;L;;;;;N;;;;; 12385;CUNEIFORM SIGN KA TIMES SHUL;Lo;0;L;;;;;N;;;;; 12386;CUNEIFORM SIGN KA TIMES TU;Lo;0;L;;;;;N;;;;; 12387;CUNEIFORM SIGN KA TIMES UR2;Lo;0;L;;;;;N;;;;; 12388;CUNEIFORM SIGN LAGAB TIMES GI;Lo;0;L;;;;;N;;;;; 12389;CUNEIFORM SIGN LU2 SHESHIG TIMES BAD;Lo;0;L;;;;;N;;;;; 1238A;CUNEIFORM SIGN LU2 TIMES ESH2 PLUS LAL;Lo;0;L;;;;;N;;;;; 1238B;CUNEIFORM SIGN LU2 TIMES SHU;Lo;0;L;;;;;N;;;;; 1238C;CUNEIFORM SIGN MESH;Lo;0;L;;;;;N;;;;; 1238D;CUNEIFORM SIGN MUSH3 TIMES ZA;Lo;0;L;;;;;N;;;;; 1238E;CUNEIFORM SIGN NA4;Lo;0;L;;;;;N;;;;; 1238F;CUNEIFORM SIGN NIN;Lo;0;L;;;;;N;;;;; 12390;CUNEIFORM SIGN NIN9;Lo;0;L;;;;;N;;;;; 12391;CUNEIFORM SIGN NINDA2 TIMES BAL;Lo;0;L;;;;;N;;;;; 12392;CUNEIFORM SIGN NINDA2 TIMES GI;Lo;0;L;;;;;N;;;;; 12393;CUNEIFORM SIGN NU11 ROTATED NINETY DEGREES;Lo;0;L;;;;;N;;;;; 12394;CUNEIFORM SIGN PESH2 ASTERISK;Lo;0;L;;;;;N;;;;; 12395;CUNEIFORM SIGN PIR2;Lo;0;L;;;;;N;;;;; 12396;CUNEIFORM SIGN SAG TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; 12397;CUNEIFORM SIGN TI2;Lo;0;L;;;;;N;;;;; 12398;CUNEIFORM SIGN UM TIMES ME;Lo;0;L;;;;;N;;;;; 12399;CUNEIFORM SIGN U U;Lo;0;L;;;;;N;;;;; 12400;CUNEIFORM NUMERIC SIGN TWO ASH;Nl;0;L;;;;2;N;;;;; 12401;CUNEIFORM NUMERIC SIGN THREE ASH;Nl;0;L;;;;3;N;;;;; 12402;CUNEIFORM NUMERIC SIGN FOUR ASH;Nl;0;L;;;;4;N;;;;; 12403;CUNEIFORM NUMERIC SIGN FIVE ASH;Nl;0;L;;;;5;N;;;;; 12404;CUNEIFORM NUMERIC SIGN SIX ASH;Nl;0;L;;;;6;N;;;;; 12405;CUNEIFORM NUMERIC SIGN SEVEN ASH;Nl;0;L;;;;7;N;;;;; 12406;CUNEIFORM NUMERIC SIGN EIGHT ASH;Nl;0;L;;;;8;N;;;;; 12407;CUNEIFORM NUMERIC SIGN NINE ASH;Nl;0;L;;;;9;N;;;;; 12408;CUNEIFORM NUMERIC SIGN THREE DISH;Nl;0;L;;;;3;N;;;;; 12409;CUNEIFORM NUMERIC SIGN FOUR DISH;Nl;0;L;;;;4;N;;;;; 1240A;CUNEIFORM NUMERIC SIGN FIVE DISH;Nl;0;L;;;;5;N;;;;; 1240B;CUNEIFORM NUMERIC SIGN SIX DISH;Nl;0;L;;;;6;N;;;;; 1240C;CUNEIFORM NUMERIC SIGN SEVEN DISH;Nl;0;L;;;;7;N;;;;; 1240D;CUNEIFORM NUMERIC SIGN EIGHT DISH;Nl;0;L;;;;8;N;;;;; 1240E;CUNEIFORM NUMERIC SIGN NINE DISH;Nl;0;L;;;;9;N;;;;; 1240F;CUNEIFORM NUMERIC SIGN FOUR U;Nl;0;L;;;;4;N;;;;; 12410;CUNEIFORM NUMERIC SIGN FIVE U;Nl;0;L;;;;5;N;;;;; 12411;CUNEIFORM NUMERIC SIGN SIX U;Nl;0;L;;;;6;N;;;;; 12412;CUNEIFORM NUMERIC SIGN SEVEN U;Nl;0;L;;;;7;N;;;;; 12413;CUNEIFORM NUMERIC SIGN EIGHT U;Nl;0;L;;;;8;N;;;;; 12414;CUNEIFORM NUMERIC SIGN NINE U;Nl;0;L;;;;9;N;;;;; 12415;CUNEIFORM NUMERIC SIGN ONE GESH2;Nl;0;L;;;;1;N;;;;; 12416;CUNEIFORM NUMERIC SIGN TWO GESH2;Nl;0;L;;;;2;N;;;;; 12417;CUNEIFORM NUMERIC SIGN THREE GESH2;Nl;0;L;;;;3;N;;;;; 12418;CUNEIFORM NUMERIC SIGN FOUR GESH2;Nl;0;L;;;;4;N;;;;; 12419;CUNEIFORM NUMERIC SIGN FIVE GESH2;Nl;0;L;;;;5;N;;;;; 1241A;CUNEIFORM NUMERIC SIGN SIX GESH2;Nl;0;L;;;;6;N;;;;; 1241B;CUNEIFORM NUMERIC SIGN SEVEN GESH2;Nl;0;L;;;;7;N;;;;; 1241C;CUNEIFORM NUMERIC SIGN EIGHT GESH2;Nl;0;L;;;;8;N;;;;; 1241D;CUNEIFORM NUMERIC SIGN NINE GESH2;Nl;0;L;;;;9;N;;;;; 1241E;CUNEIFORM NUMERIC SIGN ONE GESHU;Nl;0;L;;;;1;N;;;;; 1241F;CUNEIFORM NUMERIC SIGN TWO GESHU;Nl;0;L;;;;2;N;;;;; 12420;CUNEIFORM NUMERIC SIGN THREE GESHU;Nl;0;L;;;;3;N;;;;; 12421;CUNEIFORM NUMERIC SIGN FOUR GESHU;Nl;0;L;;;;4;N;;;;; 12422;CUNEIFORM NUMERIC SIGN FIVE GESHU;Nl;0;L;;;;5;N;;;;; 12423;CUNEIFORM NUMERIC SIGN TWO SHAR2;Nl;0;L;;;;2;N;;;;; 12424;CUNEIFORM NUMERIC SIGN THREE SHAR2;Nl;0;L;;;;3;N;;;;; 12425;CUNEIFORM NUMERIC SIGN THREE SHAR2 VARIANT FORM;Nl;0;L;;;;3;N;;;;; 12426;CUNEIFORM NUMERIC SIGN FOUR SHAR2;Nl;0;L;;;;4;N;;;;; 12427;CUNEIFORM NUMERIC SIGN FIVE SHAR2;Nl;0;L;;;;5;N;;;;; 12428;CUNEIFORM NUMERIC SIGN SIX SHAR2;Nl;0;L;;;;6;N;;;;; 12429;CUNEIFORM NUMERIC SIGN SEVEN SHAR2;Nl;0;L;;;;7;N;;;;; 1242A;CUNEIFORM NUMERIC SIGN EIGHT SHAR2;Nl;0;L;;;;8;N;;;;; 1242B;CUNEIFORM NUMERIC SIGN NINE SHAR2;Nl;0;L;;;;9;N;;;;; 1242C;CUNEIFORM NUMERIC SIGN ONE SHARU;Nl;0;L;;;;1;N;;;;; 1242D;CUNEIFORM NUMERIC SIGN TWO SHARU;Nl;0;L;;;;2;N;;;;; 1242E;CUNEIFORM NUMERIC SIGN THREE SHARU;Nl;0;L;;;;3;N;;;;; 1242F;CUNEIFORM NUMERIC SIGN THREE SHARU VARIANT FORM;Nl;0;L;;;;3;N;;;;; 12430;CUNEIFORM NUMERIC SIGN FOUR SHARU;Nl;0;L;;;;4;N;;;;; 12431;CUNEIFORM NUMERIC SIGN FIVE SHARU;Nl;0;L;;;;5;N;;;;; 12432;CUNEIFORM NUMERIC SIGN SHAR2 TIMES GAL PLUS DISH;Nl;0;L;;;;216000;N;;;;; 12433;CUNEIFORM NUMERIC SIGN SHAR2 TIMES GAL PLUS MIN;Nl;0;L;;;;432000;N;;;;; 12434;CUNEIFORM NUMERIC SIGN ONE BURU;Nl;0;L;;;;1;N;;;;; 12435;CUNEIFORM NUMERIC SIGN TWO BURU;Nl;0;L;;;;2;N;;;;; 12436;CUNEIFORM NUMERIC SIGN THREE BURU;Nl;0;L;;;;3;N;;;;; 12437;CUNEIFORM NUMERIC SIGN THREE BURU VARIANT FORM;Nl;0;L;;;;3;N;;;;; 12438;CUNEIFORM NUMERIC SIGN FOUR BURU;Nl;0;L;;;;4;N;;;;; 12439;CUNEIFORM NUMERIC SIGN FIVE BURU;Nl;0;L;;;;5;N;;;;; 1243A;CUNEIFORM NUMERIC SIGN THREE VARIANT FORM ESH16;Nl;0;L;;;;3;N;;;;; 1243B;CUNEIFORM NUMERIC SIGN THREE VARIANT FORM ESH21;Nl;0;L;;;;3;N;;;;; 1243C;CUNEIFORM NUMERIC SIGN FOUR VARIANT FORM LIMMU;Nl;0;L;;;;4;N;;;;; 1243D;CUNEIFORM NUMERIC SIGN FOUR VARIANT FORM LIMMU4;Nl;0;L;;;;4;N;;;;; 1243E;CUNEIFORM NUMERIC SIGN FOUR VARIANT FORM LIMMU A;Nl;0;L;;;;4;N;;;;; 1243F;CUNEIFORM NUMERIC SIGN FOUR VARIANT FORM LIMMU B;Nl;0;L;;;;4;N;;;;; 12440;CUNEIFORM NUMERIC SIGN SIX VARIANT FORM ASH9;Nl;0;L;;;;6;N;;;;; 12441;CUNEIFORM NUMERIC SIGN SEVEN VARIANT FORM IMIN3;Nl;0;L;;;;7;N;;;;; 12442;CUNEIFORM NUMERIC SIGN SEVEN VARIANT FORM IMIN A;Nl;0;L;;;;7;N;;;;; 12443;CUNEIFORM NUMERIC SIGN SEVEN VARIANT FORM IMIN B;Nl;0;L;;;;7;N;;;;; 12444;CUNEIFORM NUMERIC SIGN EIGHT VARIANT FORM USSU;Nl;0;L;;;;8;N;;;;; 12445;CUNEIFORM NUMERIC SIGN EIGHT VARIANT FORM USSU3;Nl;0;L;;;;8;N;;;;; 12446;CUNEIFORM NUMERIC SIGN NINE VARIANT FORM ILIMMU;Nl;0;L;;;;9;N;;;;; 12447;CUNEIFORM NUMERIC SIGN NINE VARIANT FORM ILIMMU3;Nl;0;L;;;;9;N;;;;; 12448;CUNEIFORM NUMERIC SIGN NINE VARIANT FORM ILIMMU4;Nl;0;L;;;;9;N;;;;; 12449;CUNEIFORM NUMERIC SIGN NINE VARIANT FORM ILIMMU A;Nl;0;L;;;;9;N;;;;; 1244A;CUNEIFORM NUMERIC SIGN TWO ASH TENU;Nl;0;L;;;;2;N;;;;; 1244B;CUNEIFORM NUMERIC SIGN THREE ASH TENU;Nl;0;L;;;;3;N;;;;; 1244C;CUNEIFORM NUMERIC SIGN FOUR ASH TENU;Nl;0;L;;;;4;N;;;;; 1244D;CUNEIFORM NUMERIC SIGN FIVE ASH TENU;Nl;0;L;;;;5;N;;;;; 1244E;CUNEIFORM NUMERIC SIGN SIX ASH TENU;Nl;0;L;;;;6;N;;;;; 1244F;CUNEIFORM NUMERIC SIGN ONE BAN2;Nl;0;L;;;;1;N;;;;; 12450;CUNEIFORM NUMERIC SIGN TWO BAN2;Nl;0;L;;;;2;N;;;;; 12451;CUNEIFORM NUMERIC SIGN THREE BAN2;Nl;0;L;;;;3;N;;;;; 12452;CUNEIFORM NUMERIC SIGN FOUR BAN2;Nl;0;L;;;;4;N;;;;; 12453;CUNEIFORM NUMERIC SIGN FOUR BAN2 VARIANT FORM;Nl;0;L;;;;4;N;;;;; 12454;CUNEIFORM NUMERIC SIGN FIVE BAN2;Nl;0;L;;;;5;N;;;;; 12455;CUNEIFORM NUMERIC SIGN FIVE BAN2 VARIANT FORM;Nl;0;L;;;;5;N;;;;; 12456;CUNEIFORM NUMERIC SIGN NIGIDAMIN;Nl;0;L;;;;2;N;;;;; 12457;CUNEIFORM NUMERIC SIGN NIGIDAESH;Nl;0;L;;;;3;N;;;;; 12458;CUNEIFORM NUMERIC SIGN ONE ESHE3;Nl;0;L;;;;1;N;;;;; 12459;CUNEIFORM NUMERIC SIGN TWO ESHE3;Nl;0;L;;;;2;N;;;;; 1245A;CUNEIFORM NUMERIC SIGN ONE THIRD DISH;Nl;0;L;;;;1/3;N;;;;; 1245B;CUNEIFORM NUMERIC SIGN TWO THIRDS DISH;Nl;0;L;;;;2/3;N;;;;; 1245C;CUNEIFORM NUMERIC SIGN FIVE SIXTHS DISH;Nl;0;L;;;;5/6;N;;;;; 1245D;CUNEIFORM NUMERIC SIGN ONE THIRD VARIANT FORM A;Nl;0;L;;;;1/3;N;;;;; 1245E;CUNEIFORM NUMERIC SIGN TWO THIRDS VARIANT FORM A;Nl;0;L;;;;2/3;N;;;;; 1245F;CUNEIFORM NUMERIC SIGN ONE EIGHTH ASH;Nl;0;L;;;;1/8;N;;;;; 12460;CUNEIFORM NUMERIC SIGN ONE QUARTER ASH;Nl;0;L;;;;1/4;N;;;;; 12461;CUNEIFORM NUMERIC SIGN OLD ASSYRIAN ONE SIXTH;Nl;0;L;;;;1/6;N;;;;; 12462;CUNEIFORM NUMERIC SIGN OLD ASSYRIAN ONE QUARTER;Nl;0;L;;;;1/4;N;;;;; 12463;CUNEIFORM NUMERIC SIGN ONE QUARTER GUR;Nl;0;L;;;;1/4;N;;;;; 12464;CUNEIFORM NUMERIC SIGN ONE HALF GUR;Nl;0;L;;;;1/2;N;;;;; 12465;CUNEIFORM NUMERIC SIGN ELAMITE ONE THIRD;Nl;0;L;;;;1/3;N;;;;; 12466;CUNEIFORM NUMERIC SIGN ELAMITE TWO THIRDS;Nl;0;L;;;;2/3;N;;;;; 12467;CUNEIFORM NUMERIC SIGN ELAMITE FORTY;Nl;0;L;;;;40;N;;;;; 12468;CUNEIFORM NUMERIC SIGN ELAMITE FIFTY;Nl;0;L;;;;50;N;;;;; 12469;CUNEIFORM NUMERIC SIGN FOUR U VARIANT FORM;Nl;0;L;;;;4;N;;;;; 1246A;CUNEIFORM NUMERIC SIGN FIVE U VARIANT FORM;Nl;0;L;;;;5;N;;;;; 1246B;CUNEIFORM NUMERIC SIGN SIX U VARIANT FORM;Nl;0;L;;;;6;N;;;;; 1246C;CUNEIFORM NUMERIC SIGN SEVEN U VARIANT FORM;Nl;0;L;;;;7;N;;;;; 1246D;CUNEIFORM NUMERIC SIGN EIGHT U VARIANT FORM;Nl;0;L;;;;8;N;;;;; 1246E;CUNEIFORM NUMERIC SIGN NINE U VARIANT FORM;Nl;0;L;;;;9;N;;;;; 12470;CUNEIFORM PUNCTUATION SIGN OLD ASSYRIAN WORD DIVIDER;Po;0;L;;;;;N;;;;; 12471;CUNEIFORM PUNCTUATION SIGN VERTICAL COLON;Po;0;L;;;;;N;;;;; 12472;CUNEIFORM PUNCTUATION SIGN DIAGONAL COLON;Po;0;L;;;;;N;;;;; 12473;CUNEIFORM PUNCTUATION SIGN DIAGONAL TRICOLON;Po;0;L;;;;;N;;;;; 12474;CUNEIFORM PUNCTUATION SIGN DIAGONAL QUADCOLON;Po;0;L;;;;;N;;;;; 12480;CUNEIFORM SIGN AB TIMES NUN TENU;Lo;0;L;;;;;N;;;;; 12481;CUNEIFORM SIGN AB TIMES SHU2;Lo;0;L;;;;;N;;;;; 12482;CUNEIFORM SIGN AD TIMES ESH2;Lo;0;L;;;;;N;;;;; 12483;CUNEIFORM SIGN BAD TIMES DISH TENU;Lo;0;L;;;;;N;;;;; 12484;CUNEIFORM SIGN BAHAR2 TIMES AB2;Lo;0;L;;;;;N;;;;; 12485;CUNEIFORM SIGN BAHAR2 TIMES NI;Lo;0;L;;;;;N;;;;; 12486;CUNEIFORM SIGN BAHAR2 TIMES ZA;Lo;0;L;;;;;N;;;;; 12487;CUNEIFORM SIGN BU OVER BU TIMES NA2;Lo;0;L;;;;;N;;;;; 12488;CUNEIFORM SIGN DA TIMES TAK4;Lo;0;L;;;;;N;;;;; 12489;CUNEIFORM SIGN DAG TIMES KUR;Lo;0;L;;;;;N;;;;; 1248A;CUNEIFORM SIGN DIM TIMES IGI;Lo;0;L;;;;;N;;;;; 1248B;CUNEIFORM SIGN DIM TIMES U U U;Lo;0;L;;;;;N;;;;; 1248C;CUNEIFORM SIGN DIM2 TIMES UD;Lo;0;L;;;;;N;;;;; 1248D;CUNEIFORM SIGN DUG TIMES ANSHE;Lo;0;L;;;;;N;;;;; 1248E;CUNEIFORM SIGN DUG TIMES ASH;Lo;0;L;;;;;N;;;;; 1248F;CUNEIFORM SIGN DUG TIMES ASH AT LEFT;Lo;0;L;;;;;N;;;;; 12490;CUNEIFORM SIGN DUG TIMES DIN;Lo;0;L;;;;;N;;;;; 12491;CUNEIFORM SIGN DUG TIMES DUN;Lo;0;L;;;;;N;;;;; 12492;CUNEIFORM SIGN DUG TIMES ERIN2;Lo;0;L;;;;;N;;;;; 12493;CUNEIFORM SIGN DUG TIMES GA;Lo;0;L;;;;;N;;;;; 12494;CUNEIFORM SIGN DUG TIMES GI;Lo;0;L;;;;;N;;;;; 12495;CUNEIFORM SIGN DUG TIMES GIR2 GUNU;Lo;0;L;;;;;N;;;;; 12496;CUNEIFORM SIGN DUG TIMES GISH;Lo;0;L;;;;;N;;;;; 12497;CUNEIFORM SIGN DUG TIMES HA;Lo;0;L;;;;;N;;;;; 12498;CUNEIFORM SIGN DUG TIMES HI;Lo;0;L;;;;;N;;;;; 12499;CUNEIFORM SIGN DUG TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; 1249A;CUNEIFORM SIGN DUG TIMES KASKAL;Lo;0;L;;;;;N;;;;; 1249B;CUNEIFORM SIGN DUG TIMES KUR;Lo;0;L;;;;;N;;;;; 1249C;CUNEIFORM SIGN DUG TIMES KUSHU2;Lo;0;L;;;;;N;;;;; 1249D;CUNEIFORM SIGN DUG TIMES KUSHU2 PLUS KASKAL;Lo;0;L;;;;;N;;;;; 1249E;CUNEIFORM SIGN DUG TIMES LAK-020;Lo;0;L;;;;;N;;;;; 1249F;CUNEIFORM SIGN DUG TIMES LAM;Lo;0;L;;;;;N;;;;; 124A0;CUNEIFORM SIGN DUG TIMES LAM TIMES KUR;Lo;0;L;;;;;N;;;;; 124A1;CUNEIFORM SIGN DUG TIMES LUH PLUS GISH;Lo;0;L;;;;;N;;;;; 124A2;CUNEIFORM SIGN DUG TIMES MASH;Lo;0;L;;;;;N;;;;; 124A3;CUNEIFORM SIGN DUG TIMES MES;Lo;0;L;;;;;N;;;;; 124A4;CUNEIFORM SIGN DUG TIMES MI;Lo;0;L;;;;;N;;;;; 124A5;CUNEIFORM SIGN DUG TIMES NI;Lo;0;L;;;;;N;;;;; 124A6;CUNEIFORM SIGN DUG TIMES PI;Lo;0;L;;;;;N;;;;; 124A7;CUNEIFORM SIGN DUG TIMES SHE;Lo;0;L;;;;;N;;;;; 124A8;CUNEIFORM SIGN DUG TIMES SI GUNU;Lo;0;L;;;;;N;;;;; 124A9;CUNEIFORM SIGN E2 TIMES KUR;Lo;0;L;;;;;N;;;;; 124AA;CUNEIFORM SIGN E2 TIMES PAP;Lo;0;L;;;;;N;;;;; 124AB;CUNEIFORM SIGN ERIN2 X;Lo;0;L;;;;;N;;;;; 124AC;CUNEIFORM SIGN ESH2 CROSSING ESH2;Lo;0;L;;;;;N;;;;; 124AD;CUNEIFORM SIGN EZEN SHESHIG TIMES ASH;Lo;0;L;;;;;N;;;;; 124AE;CUNEIFORM SIGN EZEN SHESHIG TIMES HI;Lo;0;L;;;;;N;;;;; 124AF;CUNEIFORM SIGN EZEN SHESHIG TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; 124B0;CUNEIFORM SIGN EZEN SHESHIG TIMES LA;Lo;0;L;;;;;N;;;;; 124B1;CUNEIFORM SIGN EZEN SHESHIG TIMES LAL;Lo;0;L;;;;;N;;;;; 124B2;CUNEIFORM SIGN EZEN SHESHIG TIMES ME;Lo;0;L;;;;;N;;;;; 124B3;CUNEIFORM SIGN EZEN SHESHIG TIMES MES;Lo;0;L;;;;;N;;;;; 124B4;CUNEIFORM SIGN EZEN SHESHIG TIMES SU;Lo;0;L;;;;;N;;;;; 124B5;CUNEIFORM SIGN EZEN TIMES SU;Lo;0;L;;;;;N;;;;; 124B6;CUNEIFORM SIGN GA2 TIMES BAHAR2;Lo;0;L;;;;;N;;;;; 124B7;CUNEIFORM SIGN GA2 TIMES DIM GUNU;Lo;0;L;;;;;N;;;;; 124B8;CUNEIFORM SIGN GA2 TIMES DUG TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; 124B9;CUNEIFORM SIGN GA2 TIMES DUG TIMES KASKAL;Lo;0;L;;;;;N;;;;; 124BA;CUNEIFORM SIGN GA2 TIMES EREN;Lo;0;L;;;;;N;;;;; 124BB;CUNEIFORM SIGN GA2 TIMES GA;Lo;0;L;;;;;N;;;;; 124BC;CUNEIFORM SIGN GA2 TIMES GAR PLUS DI;Lo;0;L;;;;;N;;;;; 124BD;CUNEIFORM SIGN GA2 TIMES GAR PLUS NE;Lo;0;L;;;;;N;;;;; 124BE;CUNEIFORM SIGN GA2 TIMES HA PLUS A;Lo;0;L;;;;;N;;;;; 124BF;CUNEIFORM SIGN GA2 TIMES KUSHU2 PLUS KASKAL;Lo;0;L;;;;;N;;;;; 124C0;CUNEIFORM SIGN GA2 TIMES LAM;Lo;0;L;;;;;N;;;;; 124C1;CUNEIFORM SIGN GA2 TIMES LAM TIMES KUR;Lo;0;L;;;;;N;;;;; 124C2;CUNEIFORM SIGN GA2 TIMES LUH;Lo;0;L;;;;;N;;;;; 124C3;CUNEIFORM SIGN GA2 TIMES MUSH;Lo;0;L;;;;;N;;;;; 124C4;CUNEIFORM SIGN GA2 TIMES NE;Lo;0;L;;;;;N;;;;; 124C5;CUNEIFORM SIGN GA2 TIMES NE PLUS E2;Lo;0;L;;;;;N;;;;; 124C6;CUNEIFORM SIGN GA2 TIMES NE PLUS GI;Lo;0;L;;;;;N;;;;; 124C7;CUNEIFORM SIGN GA2 TIMES SHIM;Lo;0;L;;;;;N;;;;; 124C8;CUNEIFORM SIGN GA2 TIMES ZIZ2;Lo;0;L;;;;;N;;;;; 124C9;CUNEIFORM SIGN GABA ROTATED NINETY DEGREES;Lo;0;L;;;;;N;;;;; 124CA;CUNEIFORM SIGN GESHTIN TIMES U;Lo;0;L;;;;;N;;;;; 124CB;CUNEIFORM SIGN GISH TIMES GISH CROSSING GISH;Lo;0;L;;;;;N;;;;; 124CC;CUNEIFORM SIGN GU2 TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; 124CD;CUNEIFORM SIGN GUD PLUS GISH TIMES TAK4;Lo;0;L;;;;;N;;;;; 124CE;CUNEIFORM SIGN HA TENU GUNU;Lo;0;L;;;;;N;;;;; 124CF;CUNEIFORM SIGN HI TIMES ASH OVER HI TIMES ASH;Lo;0;L;;;;;N;;;;; 124D0;CUNEIFORM SIGN KA TIMES BU;Lo;0;L;;;;;N;;;;; 124D1;CUNEIFORM SIGN KA TIMES KA;Lo;0;L;;;;;N;;;;; 124D2;CUNEIFORM SIGN KA TIMES U U U;Lo;0;L;;;;;N;;;;; 124D3;CUNEIFORM SIGN KA TIMES UR;Lo;0;L;;;;;N;;;;; 124D4;CUNEIFORM SIGN LAGAB TIMES ZU OVER ZU;Lo;0;L;;;;;N;;;;; 124D5;CUNEIFORM SIGN LAK-003;Lo;0;L;;;;;N;;;;; 124D6;CUNEIFORM SIGN LAK-021;Lo;0;L;;;;;N;;;;; 124D7;CUNEIFORM SIGN LAK-025;Lo;0;L;;;;;N;;;;; 124D8;CUNEIFORM SIGN LAK-030;Lo;0;L;;;;;N;;;;; 124D9;CUNEIFORM SIGN LAK-050;Lo;0;L;;;;;N;;;;; 124DA;CUNEIFORM SIGN LAK-051;Lo;0;L;;;;;N;;;;; 124DB;CUNEIFORM SIGN LAK-062;Lo;0;L;;;;;N;;;;; 124DC;CUNEIFORM SIGN LAK-079 OVER LAK-079 GUNU;Lo;0;L;;;;;N;;;;; 124DD;CUNEIFORM SIGN LAK-080;Lo;0;L;;;;;N;;;;; 124DE;CUNEIFORM SIGN LAK-081 OVER LAK-081;Lo;0;L;;;;;N;;;;; 124DF;CUNEIFORM SIGN LAK-092;Lo;0;L;;;;;N;;;;; 124E0;CUNEIFORM SIGN LAK-130;Lo;0;L;;;;;N;;;;; 124E1;CUNEIFORM SIGN LAK-142;Lo;0;L;;;;;N;;;;; 124E2;CUNEIFORM SIGN LAK-210;Lo;0;L;;;;;N;;;;; 124E3;CUNEIFORM SIGN LAK-219;Lo;0;L;;;;;N;;;;; 124E4;CUNEIFORM SIGN LAK-220;Lo;0;L;;;;;N;;;;; 124E5;CUNEIFORM SIGN LAK-225;Lo;0;L;;;;;N;;;;; 124E6;CUNEIFORM SIGN LAK-228;Lo;0;L;;;;;N;;;;; 124E7;CUNEIFORM SIGN LAK-238;Lo;0;L;;;;;N;;;;; 124E8;CUNEIFORM SIGN LAK-265;Lo;0;L;;;;;N;;;;; 124E9;CUNEIFORM SIGN LAK-266;Lo;0;L;;;;;N;;;;; 124EA;CUNEIFORM SIGN LAK-343;Lo;0;L;;;;;N;;;;; 124EB;CUNEIFORM SIGN LAK-347;Lo;0;L;;;;;N;;;;; 124EC;CUNEIFORM SIGN LAK-348;Lo;0;L;;;;;N;;;;; 124ED;CUNEIFORM SIGN LAK-383;Lo;0;L;;;;;N;;;;; 124EE;CUNEIFORM SIGN LAK-384;Lo;0;L;;;;;N;;;;; 124EF;CUNEIFORM SIGN LAK-390;Lo;0;L;;;;;N;;;;; 124F0;CUNEIFORM SIGN LAK-441;Lo;0;L;;;;;N;;;;; 124F1;CUNEIFORM SIGN LAK-449;Lo;0;L;;;;;N;;;;; 124F2;CUNEIFORM SIGN LAK-449 TIMES GU;Lo;0;L;;;;;N;;;;; 124F3;CUNEIFORM SIGN LAK-449 TIMES IGI;Lo;0;L;;;;;N;;;;; 124F4;CUNEIFORM SIGN LAK-449 TIMES PAP PLUS LU3;Lo;0;L;;;;;N;;;;; 124F5;CUNEIFORM SIGN LAK-449 TIMES PAP PLUS PAP PLUS LU3;Lo;0;L;;;;;N;;;;; 124F6;CUNEIFORM SIGN LAK-449 TIMES U2 PLUS BA;Lo;0;L;;;;;N;;;;; 124F7;CUNEIFORM SIGN LAK-450;Lo;0;L;;;;;N;;;;; 124F8;CUNEIFORM SIGN LAK-457;Lo;0;L;;;;;N;;;;; 124F9;CUNEIFORM SIGN LAK-470;Lo;0;L;;;;;N;;;;; 124FA;CUNEIFORM SIGN LAK-483;Lo;0;L;;;;;N;;;;; 124FB;CUNEIFORM SIGN LAK-490;Lo;0;L;;;;;N;;;;; 124FC;CUNEIFORM SIGN LAK-492;Lo;0;L;;;;;N;;;;; 124FD;CUNEIFORM SIGN LAK-493;Lo;0;L;;;;;N;;;;; 124FE;CUNEIFORM SIGN LAK-495;Lo;0;L;;;;;N;;;;; 124FF;CUNEIFORM SIGN LAK-550;Lo;0;L;;;;;N;;;;; 12500;CUNEIFORM SIGN LAK-608;Lo;0;L;;;;;N;;;;; 12501;CUNEIFORM SIGN LAK-617;Lo;0;L;;;;;N;;;;; 12502;CUNEIFORM SIGN LAK-617 TIMES ASH;Lo;0;L;;;;;N;;;;; 12503;CUNEIFORM SIGN LAK-617 TIMES BAD;Lo;0;L;;;;;N;;;;; 12504;CUNEIFORM SIGN LAK-617 TIMES DUN3 GUNU GUNU;Lo;0;L;;;;;N;;;;; 12505;CUNEIFORM SIGN LAK-617 TIMES KU3;Lo;0;L;;;;;N;;;;; 12506;CUNEIFORM SIGN LAK-617 TIMES LA;Lo;0;L;;;;;N;;;;; 12507;CUNEIFORM SIGN LAK-617 TIMES TAR;Lo;0;L;;;;;N;;;;; 12508;CUNEIFORM SIGN LAK-617 TIMES TE;Lo;0;L;;;;;N;;;;; 12509;CUNEIFORM SIGN LAK-617 TIMES U2;Lo;0;L;;;;;N;;;;; 1250A;CUNEIFORM SIGN LAK-617 TIMES UD;Lo;0;L;;;;;N;;;;; 1250B;CUNEIFORM SIGN LAK-617 TIMES URUDA;Lo;0;L;;;;;N;;;;; 1250C;CUNEIFORM SIGN LAK-636;Lo;0;L;;;;;N;;;;; 1250D;CUNEIFORM SIGN LAK-648;Lo;0;L;;;;;N;;;;; 1250E;CUNEIFORM SIGN LAK-648 TIMES DUB;Lo;0;L;;;;;N;;;;; 1250F;CUNEIFORM SIGN LAK-648 TIMES GA;Lo;0;L;;;;;N;;;;; 12510;CUNEIFORM SIGN LAK-648 TIMES IGI;Lo;0;L;;;;;N;;;;; 12511;CUNEIFORM SIGN LAK-648 TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; 12512;CUNEIFORM SIGN LAK-648 TIMES NI;Lo;0;L;;;;;N;;;;; 12513;CUNEIFORM SIGN LAK-648 TIMES PAP PLUS PAP PLUS LU3;Lo;0;L;;;;;N;;;;; 12514;CUNEIFORM SIGN LAK-648 TIMES SHESH PLUS KI;Lo;0;L;;;;;N;;;;; 12515;CUNEIFORM SIGN LAK-648 TIMES UD;Lo;0;L;;;;;N;;;;; 12516;CUNEIFORM SIGN LAK-648 TIMES URUDA;Lo;0;L;;;;;N;;;;; 12517;CUNEIFORM SIGN LAK-724;Lo;0;L;;;;;N;;;;; 12518;CUNEIFORM SIGN LAK-749;Lo;0;L;;;;;N;;;;; 12519;CUNEIFORM SIGN LU2 GUNU TIMES ASH;Lo;0;L;;;;;N;;;;; 1251A;CUNEIFORM SIGN LU2 TIMES DISH;Lo;0;L;;;;;N;;;;; 1251B;CUNEIFORM SIGN LU2 TIMES HAL;Lo;0;L;;;;;N;;;;; 1251C;CUNEIFORM SIGN LU2 TIMES PAP;Lo;0;L;;;;;N;;;;; 1251D;CUNEIFORM SIGN LU2 TIMES PAP PLUS PAP PLUS LU3;Lo;0;L;;;;;N;;;;; 1251E;CUNEIFORM SIGN LU2 TIMES TAK4;Lo;0;L;;;;;N;;;;; 1251F;CUNEIFORM SIGN MI PLUS ZA7;Lo;0;L;;;;;N;;;;; 12520;CUNEIFORM SIGN MUSH OVER MUSH TIMES GA;Lo;0;L;;;;;N;;;;; 12521;CUNEIFORM SIGN MUSH OVER MUSH TIMES KAK;Lo;0;L;;;;;N;;;;; 12522;CUNEIFORM SIGN NINDA2 TIMES DIM GUNU;Lo;0;L;;;;;N;;;;; 12523;CUNEIFORM SIGN NINDA2 TIMES GISH;Lo;0;L;;;;;N;;;;; 12524;CUNEIFORM SIGN NINDA2 TIMES GUL;Lo;0;L;;;;;N;;;;; 12525;CUNEIFORM SIGN NINDA2 TIMES HI;Lo;0;L;;;;;N;;;;; 12526;CUNEIFORM SIGN NINDA2 TIMES KESH2;Lo;0;L;;;;;N;;;;; 12527;CUNEIFORM SIGN NINDA2 TIMES LAK-050;Lo;0;L;;;;;N;;;;; 12528;CUNEIFORM SIGN NINDA2 TIMES MASH;Lo;0;L;;;;;N;;;;; 12529;CUNEIFORM SIGN NINDA2 TIMES PAP PLUS PAP;Lo;0;L;;;;;N;;;;; 1252A;CUNEIFORM SIGN NINDA2 TIMES U;Lo;0;L;;;;;N;;;;; 1252B;CUNEIFORM SIGN NINDA2 TIMES U PLUS U;Lo;0;L;;;;;N;;;;; 1252C;CUNEIFORM SIGN NINDA2 TIMES URUDA;Lo;0;L;;;;;N;;;;; 1252D;CUNEIFORM SIGN SAG GUNU TIMES HA;Lo;0;L;;;;;N;;;;; 1252E;CUNEIFORM SIGN SAG TIMES EN;Lo;0;L;;;;;N;;;;; 1252F;CUNEIFORM SIGN SAG TIMES SHE AT LEFT;Lo;0;L;;;;;N;;;;; 12530;CUNEIFORM SIGN SAG TIMES TAK4;Lo;0;L;;;;;N;;;;; 12531;CUNEIFORM SIGN SHA6 TENU;Lo;0;L;;;;;N;;;;; 12532;CUNEIFORM SIGN SHE OVER SHE;Lo;0;L;;;;;N;;;;; 12533;CUNEIFORM SIGN SHE PLUS HUB2;Lo;0;L;;;;;N;;;;; 12534;CUNEIFORM SIGN SHE PLUS NAM2;Lo;0;L;;;;;N;;;;; 12535;CUNEIFORM SIGN SHE PLUS SAR;Lo;0;L;;;;;N;;;;; 12536;CUNEIFORM SIGN SHU2 PLUS DUG TIMES NI;Lo;0;L;;;;;N;;;;; 12537;CUNEIFORM SIGN SHU2 PLUS E2 TIMES AN;Lo;0;L;;;;;N;;;;; 12538;CUNEIFORM SIGN SI TIMES TAK4;Lo;0;L;;;;;N;;;;; 12539;CUNEIFORM SIGN TAK4 PLUS SAG;Lo;0;L;;;;;N;;;;; 1253A;CUNEIFORM SIGN TUM TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; 1253B;CUNEIFORM SIGN TUM TIMES THREE DISH;Lo;0;L;;;;;N;;;;; 1253C;CUNEIFORM SIGN UR2 INVERTED;Lo;0;L;;;;;N;;;;; 1253D;CUNEIFORM SIGN UR2 TIMES UD;Lo;0;L;;;;;N;;;;; 1253E;CUNEIFORM SIGN URU TIMES DARA3;Lo;0;L;;;;;N;;;;; 1253F;CUNEIFORM SIGN URU TIMES LAK-668;Lo;0;L;;;;;N;;;;; 12540;CUNEIFORM SIGN URU TIMES LU3;Lo;0;L;;;;;N;;;;; 12541;CUNEIFORM SIGN ZA7;Lo;0;L;;;;;N;;;;; 12542;CUNEIFORM SIGN ZU OVER ZU PLUS SAR;Lo;0;L;;;;;N;;;;; 12543;CUNEIFORM SIGN ZU5 TIMES THREE DISH TENU;Lo;0;L;;;;;N;;;;; 13000;EGYPTIAN HIEROGLYPH A001;Lo;0;L;;;;;N;;;;; 13001;EGYPTIAN HIEROGLYPH A002;Lo;0;L;;;;;N;;;;; 13002;EGYPTIAN HIEROGLYPH A003;Lo;0;L;;;;;N;;;;; 13003;EGYPTIAN HIEROGLYPH A004;Lo;0;L;;;;;N;;;;; 13004;EGYPTIAN HIEROGLYPH A005;Lo;0;L;;;;;N;;;;; 13005;EGYPTIAN HIEROGLYPH A005A;Lo;0;L;;;;;N;;;;; 13006;EGYPTIAN HIEROGLYPH A006;Lo;0;L;;;;;N;;;;; 13007;EGYPTIAN HIEROGLYPH A006A;Lo;0;L;;;;;N;;;;; 13008;EGYPTIAN HIEROGLYPH A006B;Lo;0;L;;;;;N;;;;; 13009;EGYPTIAN HIEROGLYPH A007;Lo;0;L;;;;;N;;;;; 1300A;EGYPTIAN HIEROGLYPH A008;Lo;0;L;;;;;N;;;;; 1300B;EGYPTIAN HIEROGLYPH A009;Lo;0;L;;;;;N;;;;; 1300C;EGYPTIAN HIEROGLYPH A010;Lo;0;L;;;;;N;;;;; 1300D;EGYPTIAN HIEROGLYPH A011;Lo;0;L;;;;;N;;;;; 1300E;EGYPTIAN HIEROGLYPH A012;Lo;0;L;;;;;N;;;;; 1300F;EGYPTIAN HIEROGLYPH A013;Lo;0;L;;;;;N;;;;; 13010;EGYPTIAN HIEROGLYPH A014;Lo;0;L;;;;;N;;;;; 13011;EGYPTIAN HIEROGLYPH A014A;Lo;0;L;;;;;N;;;;; 13012;EGYPTIAN HIEROGLYPH A015;Lo;0;L;;;;;N;;;;; 13013;EGYPTIAN HIEROGLYPH A016;Lo;0;L;;;;;N;;;;; 13014;EGYPTIAN HIEROGLYPH A017;Lo;0;L;;;;;N;;;;; 13015;EGYPTIAN HIEROGLYPH A017A;Lo;0;L;;;;;N;;;;; 13016;EGYPTIAN HIEROGLYPH A018;Lo;0;L;;;;;N;;;;; 13017;EGYPTIAN HIEROGLYPH A019;Lo;0;L;;;;;N;;;;; 13018;EGYPTIAN HIEROGLYPH A020;Lo;0;L;;;;;N;;;;; 13019;EGYPTIAN HIEROGLYPH A021;Lo;0;L;;;;;N;;;;; 1301A;EGYPTIAN HIEROGLYPH A022;Lo;0;L;;;;;N;;;;; 1301B;EGYPTIAN HIEROGLYPH A023;Lo;0;L;;;;;N;;;;; 1301C;EGYPTIAN HIEROGLYPH A024;Lo;0;L;;;;;N;;;;; 1301D;EGYPTIAN HIEROGLYPH A025;Lo;0;L;;;;;N;;;;; 1301E;EGYPTIAN HIEROGLYPH A026;Lo;0;L;;;;;N;;;;; 1301F;EGYPTIAN HIEROGLYPH A027;Lo;0;L;;;;;N;;;;; 13020;EGYPTIAN HIEROGLYPH A028;Lo;0;L;;;;;N;;;;; 13021;EGYPTIAN HIEROGLYPH A029;Lo;0;L;;;;;N;;;;; 13022;EGYPTIAN HIEROGLYPH A030;Lo;0;L;;;;;N;;;;; 13023;EGYPTIAN HIEROGLYPH A031;Lo;0;L;;;;;N;;;;; 13024;EGYPTIAN HIEROGLYPH A032;Lo;0;L;;;;;N;;;;; 13025;EGYPTIAN HIEROGLYPH A032A;Lo;0;L;;;;;N;;;;; 13026;EGYPTIAN HIEROGLYPH A033;Lo;0;L;;;;;N;;;;; 13027;EGYPTIAN HIEROGLYPH A034;Lo;0;L;;;;;N;;;;; 13028;EGYPTIAN HIEROGLYPH A035;Lo;0;L;;;;;N;;;;; 13029;EGYPTIAN HIEROGLYPH A036;Lo;0;L;;;;;N;;;;; 1302A;EGYPTIAN HIEROGLYPH A037;Lo;0;L;;;;;N;;;;; 1302B;EGYPTIAN HIEROGLYPH A038;Lo;0;L;;;;;N;;;;; 1302C;EGYPTIAN HIEROGLYPH A039;Lo;0;L;;;;;N;;;;; 1302D;EGYPTIAN HIEROGLYPH A040;Lo;0;L;;;;;N;;;;; 1302E;EGYPTIAN HIEROGLYPH A040A;Lo;0;L;;;;;N;;;;; 1302F;EGYPTIAN HIEROGLYPH A041;Lo;0;L;;;;;N;;;;; 13030;EGYPTIAN HIEROGLYPH A042;Lo;0;L;;;;;N;;;;; 13031;EGYPTIAN HIEROGLYPH A042A;Lo;0;L;;;;;N;;;;; 13032;EGYPTIAN HIEROGLYPH A043;Lo;0;L;;;;;N;;;;; 13033;EGYPTIAN HIEROGLYPH A043A;Lo;0;L;;;;;N;;;;; 13034;EGYPTIAN HIEROGLYPH A044;Lo;0;L;;;;;N;;;;; 13035;EGYPTIAN HIEROGLYPH A045;Lo;0;L;;;;;N;;;;; 13036;EGYPTIAN HIEROGLYPH A045A;Lo;0;L;;;;;N;;;;; 13037;EGYPTIAN HIEROGLYPH A046;Lo;0;L;;;;;N;;;;; 13038;EGYPTIAN HIEROGLYPH A047;Lo;0;L;;;;;N;;;;; 13039;EGYPTIAN HIEROGLYPH A048;Lo;0;L;;;;;N;;;;; 1303A;EGYPTIAN HIEROGLYPH A049;Lo;0;L;;;;;N;;;;; 1303B;EGYPTIAN HIEROGLYPH A050;Lo;0;L;;;;;N;;;;; 1303C;EGYPTIAN HIEROGLYPH A051;Lo;0;L;;;;;N;;;;; 1303D;EGYPTIAN HIEROGLYPH A052;Lo;0;L;;;;;N;;;;; 1303E;EGYPTIAN HIEROGLYPH A053;Lo;0;L;;;;;N;;;;; 1303F;EGYPTIAN HIEROGLYPH A054;Lo;0;L;;;;;N;;;;; 13040;EGYPTIAN HIEROGLYPH A055;Lo;0;L;;;;;N;;;;; 13041;EGYPTIAN HIEROGLYPH A056;Lo;0;L;;;;;N;;;;; 13042;EGYPTIAN HIEROGLYPH A057;Lo;0;L;;;;;N;;;;; 13043;EGYPTIAN HIEROGLYPH A058;Lo;0;L;;;;;N;;;;; 13044;EGYPTIAN HIEROGLYPH A059;Lo;0;L;;;;;N;;;;; 13045;EGYPTIAN HIEROGLYPH A060;Lo;0;L;;;;;N;;;;; 13046;EGYPTIAN HIEROGLYPH A061;Lo;0;L;;;;;N;;;;; 13047;EGYPTIAN HIEROGLYPH A062;Lo;0;L;;;;;N;;;;; 13048;EGYPTIAN HIEROGLYPH A063;Lo;0;L;;;;;N;;;;; 13049;EGYPTIAN HIEROGLYPH A064;Lo;0;L;;;;;N;;;;; 1304A;EGYPTIAN HIEROGLYPH A065;Lo;0;L;;;;;N;;;;; 1304B;EGYPTIAN HIEROGLYPH A066;Lo;0;L;;;;;N;;;;; 1304C;EGYPTIAN HIEROGLYPH A067;Lo;0;L;;;;;N;;;;; 1304D;EGYPTIAN HIEROGLYPH A068;Lo;0;L;;;;;N;;;;; 1304E;EGYPTIAN HIEROGLYPH A069;Lo;0;L;;;;;N;;;;; 1304F;EGYPTIAN HIEROGLYPH A070;Lo;0;L;;;;;N;;;;; 13050;EGYPTIAN HIEROGLYPH B001;Lo;0;L;;;;;N;;;;; 13051;EGYPTIAN HIEROGLYPH B002;Lo;0;L;;;;;N;;;;; 13052;EGYPTIAN HIEROGLYPH B003;Lo;0;L;;;;;N;;;;; 13053;EGYPTIAN HIEROGLYPH B004;Lo;0;L;;;;;N;;;;; 13054;EGYPTIAN HIEROGLYPH B005;Lo;0;L;;;;;N;;;;; 13055;EGYPTIAN HIEROGLYPH B005A;Lo;0;L;;;;;N;;;;; 13056;EGYPTIAN HIEROGLYPH B006;Lo;0;L;;;;;N;;;;; 13057;EGYPTIAN HIEROGLYPH B007;Lo;0;L;;;;;N;;;;; 13058;EGYPTIAN HIEROGLYPH B008;Lo;0;L;;;;;N;;;;; 13059;EGYPTIAN HIEROGLYPH B009;Lo;0;L;;;;;N;;;;; 1305A;EGYPTIAN HIEROGLYPH C001;Lo;0;L;;;;;N;;;;; 1305B;EGYPTIAN HIEROGLYPH C002;Lo;0;L;;;;;N;;;;; 1305C;EGYPTIAN HIEROGLYPH C002A;Lo;0;L;;;;;N;;;;; 1305D;EGYPTIAN HIEROGLYPH C002B;Lo;0;L;;;;;N;;;;; 1305E;EGYPTIAN HIEROGLYPH C002C;Lo;0;L;;;;;N;;;;; 1305F;EGYPTIAN HIEROGLYPH C003;Lo;0;L;;;;;N;;;;; 13060;EGYPTIAN HIEROGLYPH C004;Lo;0;L;;;;;N;;;;; 13061;EGYPTIAN HIEROGLYPH C005;Lo;0;L;;;;;N;;;;; 13062;EGYPTIAN HIEROGLYPH C006;Lo;0;L;;;;;N;;;;; 13063;EGYPTIAN HIEROGLYPH C007;Lo;0;L;;;;;N;;;;; 13064;EGYPTIAN HIEROGLYPH C008;Lo;0;L;;;;;N;;;;; 13065;EGYPTIAN HIEROGLYPH C009;Lo;0;L;;;;;N;;;;; 13066;EGYPTIAN HIEROGLYPH C010;Lo;0;L;;;;;N;;;;; 13067;EGYPTIAN HIEROGLYPH C010A;Lo;0;L;;;;;N;;;;; 13068;EGYPTIAN HIEROGLYPH C011;Lo;0;L;;;;;N;;;;; 13069;EGYPTIAN HIEROGLYPH C012;Lo;0;L;;;;;N;;;;; 1306A;EGYPTIAN HIEROGLYPH C013;Lo;0;L;;;;;N;;;;; 1306B;EGYPTIAN HIEROGLYPH C014;Lo;0;L;;;;;N;;;;; 1306C;EGYPTIAN HIEROGLYPH C015;Lo;0;L;;;;;N;;;;; 1306D;EGYPTIAN HIEROGLYPH C016;Lo;0;L;;;;;N;;;;; 1306E;EGYPTIAN HIEROGLYPH C017;Lo;0;L;;;;;N;;;;; 1306F;EGYPTIAN HIEROGLYPH C018;Lo;0;L;;;;;N;;;;; 13070;EGYPTIAN HIEROGLYPH C019;Lo;0;L;;;;;N;;;;; 13071;EGYPTIAN HIEROGLYPH C020;Lo;0;L;;;;;N;;;;; 13072;EGYPTIAN HIEROGLYPH C021;Lo;0;L;;;;;N;;;;; 13073;EGYPTIAN HIEROGLYPH C022;Lo;0;L;;;;;N;;;;; 13074;EGYPTIAN HIEROGLYPH C023;Lo;0;L;;;;;N;;;;; 13075;EGYPTIAN HIEROGLYPH C024;Lo;0;L;;;;;N;;;;; 13076;EGYPTIAN HIEROGLYPH D001;Lo;0;L;;;;;N;;;;; 13077;EGYPTIAN HIEROGLYPH D002;Lo;0;L;;;;;N;;;;; 13078;EGYPTIAN HIEROGLYPH D003;Lo;0;L;;;;;N;;;;; 13079;EGYPTIAN HIEROGLYPH D004;Lo;0;L;;;;;N;;;;; 1307A;EGYPTIAN HIEROGLYPH D005;Lo;0;L;;;;;N;;;;; 1307B;EGYPTIAN HIEROGLYPH D006;Lo;0;L;;;;;N;;;;; 1307C;EGYPTIAN HIEROGLYPH D007;Lo;0;L;;;;;N;;;;; 1307D;EGYPTIAN HIEROGLYPH D008;Lo;0;L;;;;;N;;;;; 1307E;EGYPTIAN HIEROGLYPH D008A;Lo;0;L;;;;;N;;;;; 1307F;EGYPTIAN HIEROGLYPH D009;Lo;0;L;;;;;N;;;;; 13080;EGYPTIAN HIEROGLYPH D010;Lo;0;L;;;;;N;;;;; 13081;EGYPTIAN HIEROGLYPH D011;Lo;0;L;;;;;N;;;;; 13082;EGYPTIAN HIEROGLYPH D012;Lo;0;L;;;;;N;;;;; 13083;EGYPTIAN HIEROGLYPH D013;Lo;0;L;;;;;N;;;;; 13084;EGYPTIAN HIEROGLYPH D014;Lo;0;L;;;;;N;;;;; 13085;EGYPTIAN HIEROGLYPH D015;Lo;0;L;;;;;N;;;;; 13086;EGYPTIAN HIEROGLYPH D016;Lo;0;L;;;;;N;;;;; 13087;EGYPTIAN HIEROGLYPH D017;Lo;0;L;;;;;N;;;;; 13088;EGYPTIAN HIEROGLYPH D018;Lo;0;L;;;;;N;;;;; 13089;EGYPTIAN HIEROGLYPH D019;Lo;0;L;;;;;N;;;;; 1308A;EGYPTIAN HIEROGLYPH D020;Lo;0;L;;;;;N;;;;; 1308B;EGYPTIAN HIEROGLYPH D021;Lo;0;L;;;;;N;;;;; 1308C;EGYPTIAN HIEROGLYPH D022;Lo;0;L;;;;;N;;;;; 1308D;EGYPTIAN HIEROGLYPH D023;Lo;0;L;;;;;N;;;;; 1308E;EGYPTIAN HIEROGLYPH D024;Lo;0;L;;;;;N;;;;; 1308F;EGYPTIAN HIEROGLYPH D025;Lo;0;L;;;;;N;;;;; 13090;EGYPTIAN HIEROGLYPH D026;Lo;0;L;;;;;N;;;;; 13091;EGYPTIAN HIEROGLYPH D027;Lo;0;L;;;;;N;;;;; 13092;EGYPTIAN HIEROGLYPH D027A;Lo;0;L;;;;;N;;;;; 13093;EGYPTIAN HIEROGLYPH D028;Lo;0;L;;;;;N;;;;; 13094;EGYPTIAN HIEROGLYPH D029;Lo;0;L;;;;;N;;;;; 13095;EGYPTIAN HIEROGLYPH D030;Lo;0;L;;;;;N;;;;; 13096;EGYPTIAN HIEROGLYPH D031;Lo;0;L;;;;;N;;;;; 13097;EGYPTIAN HIEROGLYPH D031A;Lo;0;L;;;;;N;;;;; 13098;EGYPTIAN HIEROGLYPH D032;Lo;0;L;;;;;N;;;;; 13099;EGYPTIAN HIEROGLYPH D033;Lo;0;L;;;;;N;;;;; 1309A;EGYPTIAN HIEROGLYPH D034;Lo;0;L;;;;;N;;;;; 1309B;EGYPTIAN HIEROGLYPH D034A;Lo;0;L;;;;;N;;;;; 1309C;EGYPTIAN HIEROGLYPH D035;Lo;0;L;;;;;N;;;;; 1309D;EGYPTIAN HIEROGLYPH D036;Lo;0;L;;;;;N;;;;; 1309E;EGYPTIAN HIEROGLYPH D037;Lo;0;L;;;;;N;;;;; 1309F;EGYPTIAN HIEROGLYPH D038;Lo;0;L;;;;;N;;;;; 130A0;EGYPTIAN HIEROGLYPH D039;Lo;0;L;;;;;N;;;;; 130A1;EGYPTIAN HIEROGLYPH D040;Lo;0;L;;;;;N;;;;; 130A2;EGYPTIAN HIEROGLYPH D041;Lo;0;L;;;;;N;;;;; 130A3;EGYPTIAN HIEROGLYPH D042;Lo;0;L;;;;;N;;;;; 130A4;EGYPTIAN HIEROGLYPH D043;Lo;0;L;;;;;N;;;;; 130A5;EGYPTIAN HIEROGLYPH D044;Lo;0;L;;;;;N;;;;; 130A6;EGYPTIAN HIEROGLYPH D045;Lo;0;L;;;;;N;;;;; 130A7;EGYPTIAN HIEROGLYPH D046;Lo;0;L;;;;;N;;;;; 130A8;EGYPTIAN HIEROGLYPH D046A;Lo;0;L;;;;;N;;;;; 130A9;EGYPTIAN HIEROGLYPH D047;Lo;0;L;;;;;N;;;;; 130AA;EGYPTIAN HIEROGLYPH D048;Lo;0;L;;;;;N;;;;; 130AB;EGYPTIAN HIEROGLYPH D048A;Lo;0;L;;;;;N;;;;; 130AC;EGYPTIAN HIEROGLYPH D049;Lo;0;L;;;;;N;;;;; 130AD;EGYPTIAN HIEROGLYPH D050;Lo;0;L;;;;;N;;;;; 130AE;EGYPTIAN HIEROGLYPH D050A;Lo;0;L;;;;;N;;;;; 130AF;EGYPTIAN HIEROGLYPH D050B;Lo;0;L;;;;;N;;;;; 130B0;EGYPTIAN HIEROGLYPH D050C;Lo;0;L;;;;;N;;;;; 130B1;EGYPTIAN HIEROGLYPH D050D;Lo;0;L;;;;;N;;;;; 130B2;EGYPTIAN HIEROGLYPH D050E;Lo;0;L;;;;;N;;;;; 130B3;EGYPTIAN HIEROGLYPH D050F;Lo;0;L;;;;;N;;;;; 130B4;EGYPTIAN HIEROGLYPH D050G;Lo;0;L;;;;;N;;;;; 130B5;EGYPTIAN HIEROGLYPH D050H;Lo;0;L;;;;;N;;;;; 130B6;EGYPTIAN HIEROGLYPH D050I;Lo;0;L;;;;;N;;;;; 130B7;EGYPTIAN HIEROGLYPH D051;Lo;0;L;;;;;N;;;;; 130B8;EGYPTIAN HIEROGLYPH D052;Lo;0;L;;;;;N;;;;; 130B9;EGYPTIAN HIEROGLYPH D052A;Lo;0;L;;;;;N;;;;; 130BA;EGYPTIAN HIEROGLYPH D053;Lo;0;L;;;;;N;;;;; 130BB;EGYPTIAN HIEROGLYPH D054;Lo;0;L;;;;;N;;;;; 130BC;EGYPTIAN HIEROGLYPH D054A;Lo;0;L;;;;;N;;;;; 130BD;EGYPTIAN HIEROGLYPH D055;Lo;0;L;;;;;N;;;;; 130BE;EGYPTIAN HIEROGLYPH D056;Lo;0;L;;;;;N;;;;; 130BF;EGYPTIAN HIEROGLYPH D057;Lo;0;L;;;;;N;;;;; 130C0;EGYPTIAN HIEROGLYPH D058;Lo;0;L;;;;;N;;;;; 130C1;EGYPTIAN HIEROGLYPH D059;Lo;0;L;;;;;N;;;;; 130C2;EGYPTIAN HIEROGLYPH D060;Lo;0;L;;;;;N;;;;; 130C3;EGYPTIAN HIEROGLYPH D061;Lo;0;L;;;;;N;;;;; 130C4;EGYPTIAN HIEROGLYPH D062;Lo;0;L;;;;;N;;;;; 130C5;EGYPTIAN HIEROGLYPH D063;Lo;0;L;;;;;N;;;;; 130C6;EGYPTIAN HIEROGLYPH D064;Lo;0;L;;;;;N;;;;; 130C7;EGYPTIAN HIEROGLYPH D065;Lo;0;L;;;;;N;;;;; 130C8;EGYPTIAN HIEROGLYPH D066;Lo;0;L;;;;;N;;;;; 130C9;EGYPTIAN HIEROGLYPH D067;Lo;0;L;;;;;N;;;;; 130CA;EGYPTIAN HIEROGLYPH D067A;Lo;0;L;;;;;N;;;;; 130CB;EGYPTIAN HIEROGLYPH D067B;Lo;0;L;;;;;N;;;;; 130CC;EGYPTIAN HIEROGLYPH D067C;Lo;0;L;;;;;N;;;;; 130CD;EGYPTIAN HIEROGLYPH D067D;Lo;0;L;;;;;N;;;;; 130CE;EGYPTIAN HIEROGLYPH D067E;Lo;0;L;;;;;N;;;;; 130CF;EGYPTIAN HIEROGLYPH D067F;Lo;0;L;;;;;N;;;;; 130D0;EGYPTIAN HIEROGLYPH D067G;Lo;0;L;;;;;N;;;;; 130D1;EGYPTIAN HIEROGLYPH D067H;Lo;0;L;;;;;N;;;;; 130D2;EGYPTIAN HIEROGLYPH E001;Lo;0;L;;;;;N;;;;; 130D3;EGYPTIAN HIEROGLYPH E002;Lo;0;L;;;;;N;;;;; 130D4;EGYPTIAN HIEROGLYPH E003;Lo;0;L;;;;;N;;;;; 130D5;EGYPTIAN HIEROGLYPH E004;Lo;0;L;;;;;N;;;;; 130D6;EGYPTIAN HIEROGLYPH E005;Lo;0;L;;;;;N;;;;; 130D7;EGYPTIAN HIEROGLYPH E006;Lo;0;L;;;;;N;;;;; 130D8;EGYPTIAN HIEROGLYPH E007;Lo;0;L;;;;;N;;;;; 130D9;EGYPTIAN HIEROGLYPH E008;Lo;0;L;;;;;N;;;;; 130DA;EGYPTIAN HIEROGLYPH E008A;Lo;0;L;;;;;N;;;;; 130DB;EGYPTIAN HIEROGLYPH E009;Lo;0;L;;;;;N;;;;; 130DC;EGYPTIAN HIEROGLYPH E009A;Lo;0;L;;;;;N;;;;; 130DD;EGYPTIAN HIEROGLYPH E010;Lo;0;L;;;;;N;;;;; 130DE;EGYPTIAN HIEROGLYPH E011;Lo;0;L;;;;;N;;;;; 130DF;EGYPTIAN HIEROGLYPH E012;Lo;0;L;;;;;N;;;;; 130E0;EGYPTIAN HIEROGLYPH E013;Lo;0;L;;;;;N;;;;; 130E1;EGYPTIAN HIEROGLYPH E014;Lo;0;L;;;;;N;;;;; 130E2;EGYPTIAN HIEROGLYPH E015;Lo;0;L;;;;;N;;;;; 130E3;EGYPTIAN HIEROGLYPH E016;Lo;0;L;;;;;N;;;;; 130E4;EGYPTIAN HIEROGLYPH E016A;Lo;0;L;;;;;N;;;;; 130E5;EGYPTIAN HIEROGLYPH E017;Lo;0;L;;;;;N;;;;; 130E6;EGYPTIAN HIEROGLYPH E017A;Lo;0;L;;;;;N;;;;; 130E7;EGYPTIAN HIEROGLYPH E018;Lo;0;L;;;;;N;;;;; 130E8;EGYPTIAN HIEROGLYPH E019;Lo;0;L;;;;;N;;;;; 130E9;EGYPTIAN HIEROGLYPH E020;Lo;0;L;;;;;N;;;;; 130EA;EGYPTIAN HIEROGLYPH E020A;Lo;0;L;;;;;N;;;;; 130EB;EGYPTIAN HIEROGLYPH E021;Lo;0;L;;;;;N;;;;; 130EC;EGYPTIAN HIEROGLYPH E022;Lo;0;L;;;;;N;;;;; 130ED;EGYPTIAN HIEROGLYPH E023;Lo;0;L;;;;;N;;;;; 130EE;EGYPTIAN HIEROGLYPH E024;Lo;0;L;;;;;N;;;;; 130EF;EGYPTIAN HIEROGLYPH E025;Lo;0;L;;;;;N;;;;; 130F0;EGYPTIAN HIEROGLYPH E026;Lo;0;L;;;;;N;;;;; 130F1;EGYPTIAN HIEROGLYPH E027;Lo;0;L;;;;;N;;;;; 130F2;EGYPTIAN HIEROGLYPH E028;Lo;0;L;;;;;N;;;;; 130F3;EGYPTIAN HIEROGLYPH E028A;Lo;0;L;;;;;N;;;;; 130F4;EGYPTIAN HIEROGLYPH E029;Lo;0;L;;;;;N;;;;; 130F5;EGYPTIAN HIEROGLYPH E030;Lo;0;L;;;;;N;;;;; 130F6;EGYPTIAN HIEROGLYPH E031;Lo;0;L;;;;;N;;;;; 130F7;EGYPTIAN HIEROGLYPH E032;Lo;0;L;;;;;N;;;;; 130F8;EGYPTIAN HIEROGLYPH E033;Lo;0;L;;;;;N;;;;; 130F9;EGYPTIAN HIEROGLYPH E034;Lo;0;L;;;;;N;;;;; 130FA;EGYPTIAN HIEROGLYPH E034A;Lo;0;L;;;;;N;;;;; 130FB;EGYPTIAN HIEROGLYPH E036;Lo;0;L;;;;;N;;;;; 130FC;EGYPTIAN HIEROGLYPH E037;Lo;0;L;;;;;N;;;;; 130FD;EGYPTIAN HIEROGLYPH E038;Lo;0;L;;;;;N;;;;; 130FE;EGYPTIAN HIEROGLYPH F001;Lo;0;L;;;;;N;;;;; 130FF;EGYPTIAN HIEROGLYPH F001A;Lo;0;L;;;;;N;;;;; 13100;EGYPTIAN HIEROGLYPH F002;Lo;0;L;;;;;N;;;;; 13101;EGYPTIAN HIEROGLYPH F003;Lo;0;L;;;;;N;;;;; 13102;EGYPTIAN HIEROGLYPH F004;Lo;0;L;;;;;N;;;;; 13103;EGYPTIAN HIEROGLYPH F005;Lo;0;L;;;;;N;;;;; 13104;EGYPTIAN HIEROGLYPH F006;Lo;0;L;;;;;N;;;;; 13105;EGYPTIAN HIEROGLYPH F007;Lo;0;L;;;;;N;;;;; 13106;EGYPTIAN HIEROGLYPH F008;Lo;0;L;;;;;N;;;;; 13107;EGYPTIAN HIEROGLYPH F009;Lo;0;L;;;;;N;;;;; 13108;EGYPTIAN HIEROGLYPH F010;Lo;0;L;;;;;N;;;;; 13109;EGYPTIAN HIEROGLYPH F011;Lo;0;L;;;;;N;;;;; 1310A;EGYPTIAN HIEROGLYPH F012;Lo;0;L;;;;;N;;;;; 1310B;EGYPTIAN HIEROGLYPH F013;Lo;0;L;;;;;N;;;;; 1310C;EGYPTIAN HIEROGLYPH F013A;Lo;0;L;;;;;N;;;;; 1310D;EGYPTIAN HIEROGLYPH F014;Lo;0;L;;;;;N;;;;; 1310E;EGYPTIAN HIEROGLYPH F015;Lo;0;L;;;;;N;;;;; 1310F;EGYPTIAN HIEROGLYPH F016;Lo;0;L;;;;;N;;;;; 13110;EGYPTIAN HIEROGLYPH F017;Lo;0;L;;;;;N;;;;; 13111;EGYPTIAN HIEROGLYPH F018;Lo;0;L;;;;;N;;;;; 13112;EGYPTIAN HIEROGLYPH F019;Lo;0;L;;;;;N;;;;; 13113;EGYPTIAN HIEROGLYPH F020;Lo;0;L;;;;;N;;;;; 13114;EGYPTIAN HIEROGLYPH F021;Lo;0;L;;;;;N;;;;; 13115;EGYPTIAN HIEROGLYPH F021A;Lo;0;L;;;;;N;;;;; 13116;EGYPTIAN HIEROGLYPH F022;Lo;0;L;;;;;N;;;;; 13117;EGYPTIAN HIEROGLYPH F023;Lo;0;L;;;;;N;;;;; 13118;EGYPTIAN HIEROGLYPH F024;Lo;0;L;;;;;N;;;;; 13119;EGYPTIAN HIEROGLYPH F025;Lo;0;L;;;;;N;;;;; 1311A;EGYPTIAN HIEROGLYPH F026;Lo;0;L;;;;;N;;;;; 1311B;EGYPTIAN HIEROGLYPH F027;Lo;0;L;;;;;N;;;;; 1311C;EGYPTIAN HIEROGLYPH F028;Lo;0;L;;;;;N;;;;; 1311D;EGYPTIAN HIEROGLYPH F029;Lo;0;L;;;;;N;;;;; 1311E;EGYPTIAN HIEROGLYPH F030;Lo;0;L;;;;;N;;;;; 1311F;EGYPTIAN HIEROGLYPH F031;Lo;0;L;;;;;N;;;;; 13120;EGYPTIAN HIEROGLYPH F031A;Lo;0;L;;;;;N;;;;; 13121;EGYPTIAN HIEROGLYPH F032;Lo;0;L;;;;;N;;;;; 13122;EGYPTIAN HIEROGLYPH F033;Lo;0;L;;;;;N;;;;; 13123;EGYPTIAN HIEROGLYPH F034;Lo;0;L;;;;;N;;;;; 13124;EGYPTIAN HIEROGLYPH F035;Lo;0;L;;;;;N;;;;; 13125;EGYPTIAN HIEROGLYPH F036;Lo;0;L;;;;;N;;;;; 13126;EGYPTIAN HIEROGLYPH F037;Lo;0;L;;;;;N;;;;; 13127;EGYPTIAN HIEROGLYPH F037A;Lo;0;L;;;;;N;;;;; 13128;EGYPTIAN HIEROGLYPH F038;Lo;0;L;;;;;N;;;;; 13129;EGYPTIAN HIEROGLYPH F038A;Lo;0;L;;;;;N;;;;; 1312A;EGYPTIAN HIEROGLYPH F039;Lo;0;L;;;;;N;;;;; 1312B;EGYPTIAN HIEROGLYPH F040;Lo;0;L;;;;;N;;;;; 1312C;EGYPTIAN HIEROGLYPH F041;Lo;0;L;;;;;N;;;;; 1312D;EGYPTIAN HIEROGLYPH F042;Lo;0;L;;;;;N;;;;; 1312E;EGYPTIAN HIEROGLYPH F043;Lo;0;L;;;;;N;;;;; 1312F;EGYPTIAN HIEROGLYPH F044;Lo;0;L;;;;;N;;;;; 13130;EGYPTIAN HIEROGLYPH F045;Lo;0;L;;;;;N;;;;; 13131;EGYPTIAN HIEROGLYPH F045A;Lo;0;L;;;;;N;;;;; 13132;EGYPTIAN HIEROGLYPH F046;Lo;0;L;;;;;N;;;;; 13133;EGYPTIAN HIEROGLYPH F046A;Lo;0;L;;;;;N;;;;; 13134;EGYPTIAN HIEROGLYPH F047;Lo;0;L;;;;;N;;;;; 13135;EGYPTIAN HIEROGLYPH F047A;Lo;0;L;;;;;N;;;;; 13136;EGYPTIAN HIEROGLYPH F048;Lo;0;L;;;;;N;;;;; 13137;EGYPTIAN HIEROGLYPH F049;Lo;0;L;;;;;N;;;;; 13138;EGYPTIAN HIEROGLYPH F050;Lo;0;L;;;;;N;;;;; 13139;EGYPTIAN HIEROGLYPH F051;Lo;0;L;;;;;N;;;;; 1313A;EGYPTIAN HIEROGLYPH F051A;Lo;0;L;;;;;N;;;;; 1313B;EGYPTIAN HIEROGLYPH F051B;Lo;0;L;;;;;N;;;;; 1313C;EGYPTIAN HIEROGLYPH F051C;Lo;0;L;;;;;N;;;;; 1313D;EGYPTIAN HIEROGLYPH F052;Lo;0;L;;;;;N;;;;; 1313E;EGYPTIAN HIEROGLYPH F053;Lo;0;L;;;;;N;;;;; 1313F;EGYPTIAN HIEROGLYPH G001;Lo;0;L;;;;;N;;;;; 13140;EGYPTIAN HIEROGLYPH G002;Lo;0;L;;;;;N;;;;; 13141;EGYPTIAN HIEROGLYPH G003;Lo;0;L;;;;;N;;;;; 13142;EGYPTIAN HIEROGLYPH G004;Lo;0;L;;;;;N;;;;; 13143;EGYPTIAN HIEROGLYPH G005;Lo;0;L;;;;;N;;;;; 13144;EGYPTIAN HIEROGLYPH G006;Lo;0;L;;;;;N;;;;; 13145;EGYPTIAN HIEROGLYPH G006A;Lo;0;L;;;;;N;;;;; 13146;EGYPTIAN HIEROGLYPH G007;Lo;0;L;;;;;N;;;;; 13147;EGYPTIAN HIEROGLYPH G007A;Lo;0;L;;;;;N;;;;; 13148;EGYPTIAN HIEROGLYPH G007B;Lo;0;L;;;;;N;;;;; 13149;EGYPTIAN HIEROGLYPH G008;Lo;0;L;;;;;N;;;;; 1314A;EGYPTIAN HIEROGLYPH G009;Lo;0;L;;;;;N;;;;; 1314B;EGYPTIAN HIEROGLYPH G010;Lo;0;L;;;;;N;;;;; 1314C;EGYPTIAN HIEROGLYPH G011;Lo;0;L;;;;;N;;;;; 1314D;EGYPTIAN HIEROGLYPH G011A;Lo;0;L;;;;;N;;;;; 1314E;EGYPTIAN HIEROGLYPH G012;Lo;0;L;;;;;N;;;;; 1314F;EGYPTIAN HIEROGLYPH G013;Lo;0;L;;;;;N;;;;; 13150;EGYPTIAN HIEROGLYPH G014;Lo;0;L;;;;;N;;;;; 13151;EGYPTIAN HIEROGLYPH G015;Lo;0;L;;;;;N;;;;; 13152;EGYPTIAN HIEROGLYPH G016;Lo;0;L;;;;;N;;;;; 13153;EGYPTIAN HIEROGLYPH G017;Lo;0;L;;;;;N;;;;; 13154;EGYPTIAN HIEROGLYPH G018;Lo;0;L;;;;;N;;;;; 13155;EGYPTIAN HIEROGLYPH G019;Lo;0;L;;;;;N;;;;; 13156;EGYPTIAN HIEROGLYPH G020;Lo;0;L;;;;;N;;;;; 13157;EGYPTIAN HIEROGLYPH G020A;Lo;0;L;;;;;N;;;;; 13158;EGYPTIAN HIEROGLYPH G021;Lo;0;L;;;;;N;;;;; 13159;EGYPTIAN HIEROGLYPH G022;Lo;0;L;;;;;N;;;;; 1315A;EGYPTIAN HIEROGLYPH G023;Lo;0;L;;;;;N;;;;; 1315B;EGYPTIAN HIEROGLYPH G024;Lo;0;L;;;;;N;;;;; 1315C;EGYPTIAN HIEROGLYPH G025;Lo;0;L;;;;;N;;;;; 1315D;EGYPTIAN HIEROGLYPH G026;Lo;0;L;;;;;N;;;;; 1315E;EGYPTIAN HIEROGLYPH G026A;Lo;0;L;;;;;N;;;;; 1315F;EGYPTIAN HIEROGLYPH G027;Lo;0;L;;;;;N;;;;; 13160;EGYPTIAN HIEROGLYPH G028;Lo;0;L;;;;;N;;;;; 13161;EGYPTIAN HIEROGLYPH G029;Lo;0;L;;;;;N;;;;; 13162;EGYPTIAN HIEROGLYPH G030;Lo;0;L;;;;;N;;;;; 13163;EGYPTIAN HIEROGLYPH G031;Lo;0;L;;;;;N;;;;; 13164;EGYPTIAN HIEROGLYPH G032;Lo;0;L;;;;;N;;;;; 13165;EGYPTIAN HIEROGLYPH G033;Lo;0;L;;;;;N;;;;; 13166;EGYPTIAN HIEROGLYPH G034;Lo;0;L;;;;;N;;;;; 13167;EGYPTIAN HIEROGLYPH G035;Lo;0;L;;;;;N;;;;; 13168;EGYPTIAN HIEROGLYPH G036;Lo;0;L;;;;;N;;;;; 13169;EGYPTIAN HIEROGLYPH G036A;Lo;0;L;;;;;N;;;;; 1316A;EGYPTIAN HIEROGLYPH G037;Lo;0;L;;;;;N;;;;; 1316B;EGYPTIAN HIEROGLYPH G037A;Lo;0;L;;;;;N;;;;; 1316C;EGYPTIAN HIEROGLYPH G038;Lo;0;L;;;;;N;;;;; 1316D;EGYPTIAN HIEROGLYPH G039;Lo;0;L;;;;;N;;;;; 1316E;EGYPTIAN HIEROGLYPH G040;Lo;0;L;;;;;N;;;;; 1316F;EGYPTIAN HIEROGLYPH G041;Lo;0;L;;;;;N;;;;; 13170;EGYPTIAN HIEROGLYPH G042;Lo;0;L;;;;;N;;;;; 13171;EGYPTIAN HIEROGLYPH G043;Lo;0;L;;;;;N;;;;; 13172;EGYPTIAN HIEROGLYPH G043A;Lo;0;L;;;;;N;;;;; 13173;EGYPTIAN HIEROGLYPH G044;Lo;0;L;;;;;N;;;;; 13174;EGYPTIAN HIEROGLYPH G045;Lo;0;L;;;;;N;;;;; 13175;EGYPTIAN HIEROGLYPH G045A;Lo;0;L;;;;;N;;;;; 13176;EGYPTIAN HIEROGLYPH G046;Lo;0;L;;;;;N;;;;; 13177;EGYPTIAN HIEROGLYPH G047;Lo;0;L;;;;;N;;;;; 13178;EGYPTIAN HIEROGLYPH G048;Lo;0;L;;;;;N;;;;; 13179;EGYPTIAN HIEROGLYPH G049;Lo;0;L;;;;;N;;;;; 1317A;EGYPTIAN HIEROGLYPH G050;Lo;0;L;;;;;N;;;;; 1317B;EGYPTIAN HIEROGLYPH G051;Lo;0;L;;;;;N;;;;; 1317C;EGYPTIAN HIEROGLYPH G052;Lo;0;L;;;;;N;;;;; 1317D;EGYPTIAN HIEROGLYPH G053;Lo;0;L;;;;;N;;;;; 1317E;EGYPTIAN HIEROGLYPH G054;Lo;0;L;;;;;N;;;;; 1317F;EGYPTIAN HIEROGLYPH H001;Lo;0;L;;;;;N;;;;; 13180;EGYPTIAN HIEROGLYPH H002;Lo;0;L;;;;;N;;;;; 13181;EGYPTIAN HIEROGLYPH H003;Lo;0;L;;;;;N;;;;; 13182;EGYPTIAN HIEROGLYPH H004;Lo;0;L;;;;;N;;;;; 13183;EGYPTIAN HIEROGLYPH H005;Lo;0;L;;;;;N;;;;; 13184;EGYPTIAN HIEROGLYPH H006;Lo;0;L;;;;;N;;;;; 13185;EGYPTIAN HIEROGLYPH H006A;Lo;0;L;;;;;N;;;;; 13186;EGYPTIAN HIEROGLYPH H007;Lo;0;L;;;;;N;;;;; 13187;EGYPTIAN HIEROGLYPH H008;Lo;0;L;;;;;N;;;;; 13188;EGYPTIAN HIEROGLYPH I001;Lo;0;L;;;;;N;;;;; 13189;EGYPTIAN HIEROGLYPH I002;Lo;0;L;;;;;N;;;;; 1318A;EGYPTIAN HIEROGLYPH I003;Lo;0;L;;;;;N;;;;; 1318B;EGYPTIAN HIEROGLYPH I004;Lo;0;L;;;;;N;;;;; 1318C;EGYPTIAN HIEROGLYPH I005;Lo;0;L;;;;;N;;;;; 1318D;EGYPTIAN HIEROGLYPH I005A;Lo;0;L;;;;;N;;;;; 1318E;EGYPTIAN HIEROGLYPH I006;Lo;0;L;;;;;N;;;;; 1318F;EGYPTIAN HIEROGLYPH I007;Lo;0;L;;;;;N;;;;; 13190;EGYPTIAN HIEROGLYPH I008;Lo;0;L;;;;;N;;;;; 13191;EGYPTIAN HIEROGLYPH I009;Lo;0;L;;;;;N;;;;; 13192;EGYPTIAN HIEROGLYPH I009A;Lo;0;L;;;;;N;;;;; 13193;EGYPTIAN HIEROGLYPH I010;Lo;0;L;;;;;N;;;;; 13194;EGYPTIAN HIEROGLYPH I010A;Lo;0;L;;;;;N;;;;; 13195;EGYPTIAN HIEROGLYPH I011;Lo;0;L;;;;;N;;;;; 13196;EGYPTIAN HIEROGLYPH I011A;Lo;0;L;;;;;N;;;;; 13197;EGYPTIAN HIEROGLYPH I012;Lo;0;L;;;;;N;;;;; 13198;EGYPTIAN HIEROGLYPH I013;Lo;0;L;;;;;N;;;;; 13199;EGYPTIAN HIEROGLYPH I014;Lo;0;L;;;;;N;;;;; 1319A;EGYPTIAN HIEROGLYPH I015;Lo;0;L;;;;;N;;;;; 1319B;EGYPTIAN HIEROGLYPH K001;Lo;0;L;;;;;N;;;;; 1319C;EGYPTIAN HIEROGLYPH K002;Lo;0;L;;;;;N;;;;; 1319D;EGYPTIAN HIEROGLYPH K003;Lo;0;L;;;;;N;;;;; 1319E;EGYPTIAN HIEROGLYPH K004;Lo;0;L;;;;;N;;;;; 1319F;EGYPTIAN HIEROGLYPH K005;Lo;0;L;;;;;N;;;;; 131A0;EGYPTIAN HIEROGLYPH K006;Lo;0;L;;;;;N;;;;; 131A1;EGYPTIAN HIEROGLYPH K007;Lo;0;L;;;;;N;;;;; 131A2;EGYPTIAN HIEROGLYPH K008;Lo;0;L;;;;;N;;;;; 131A3;EGYPTIAN HIEROGLYPH L001;Lo;0;L;;;;;N;;;;; 131A4;EGYPTIAN HIEROGLYPH L002;Lo;0;L;;;;;N;;;;; 131A5;EGYPTIAN HIEROGLYPH L002A;Lo;0;L;;;;;N;;;;; 131A6;EGYPTIAN HIEROGLYPH L003;Lo;0;L;;;;;N;;;;; 131A7;EGYPTIAN HIEROGLYPH L004;Lo;0;L;;;;;N;;;;; 131A8;EGYPTIAN HIEROGLYPH L005;Lo;0;L;;;;;N;;;;; 131A9;EGYPTIAN HIEROGLYPH L006;Lo;0;L;;;;;N;;;;; 131AA;EGYPTIAN HIEROGLYPH L006A;Lo;0;L;;;;;N;;;;; 131AB;EGYPTIAN HIEROGLYPH L007;Lo;0;L;;;;;N;;;;; 131AC;EGYPTIAN HIEROGLYPH L008;Lo;0;L;;;;;N;;;;; 131AD;EGYPTIAN HIEROGLYPH M001;Lo;0;L;;;;;N;;;;; 131AE;EGYPTIAN HIEROGLYPH M001A;Lo;0;L;;;;;N;;;;; 131AF;EGYPTIAN HIEROGLYPH M001B;Lo;0;L;;;;;N;;;;; 131B0;EGYPTIAN HIEROGLYPH M002;Lo;0;L;;;;;N;;;;; 131B1;EGYPTIAN HIEROGLYPH M003;Lo;0;L;;;;;N;;;;; 131B2;EGYPTIAN HIEROGLYPH M003A;Lo;0;L;;;;;N;;;;; 131B3;EGYPTIAN HIEROGLYPH M004;Lo;0;L;;;;;N;;;;; 131B4;EGYPTIAN HIEROGLYPH M005;Lo;0;L;;;;;N;;;;; 131B5;EGYPTIAN HIEROGLYPH M006;Lo;0;L;;;;;N;;;;; 131B6;EGYPTIAN HIEROGLYPH M007;Lo;0;L;;;;;N;;;;; 131B7;EGYPTIAN HIEROGLYPH M008;Lo;0;L;;;;;N;;;;; 131B8;EGYPTIAN HIEROGLYPH M009;Lo;0;L;;;;;N;;;;; 131B9;EGYPTIAN HIEROGLYPH M010;Lo;0;L;;;;;N;;;;; 131BA;EGYPTIAN HIEROGLYPH M010A;Lo;0;L;;;;;N;;;;; 131BB;EGYPTIAN HIEROGLYPH M011;Lo;0;L;;;;;N;;;;; 131BC;EGYPTIAN HIEROGLYPH M012;Lo;0;L;;;;;N;;;;; 131BD;EGYPTIAN HIEROGLYPH M012A;Lo;0;L;;;;;N;;;;; 131BE;EGYPTIAN HIEROGLYPH M012B;Lo;0;L;;;;;N;;;;; 131BF;EGYPTIAN HIEROGLYPH M012C;Lo;0;L;;;;;N;;;;; 131C0;EGYPTIAN HIEROGLYPH M012D;Lo;0;L;;;;;N;;;;; 131C1;EGYPTIAN HIEROGLYPH M012E;Lo;0;L;;;;;N;;;;; 131C2;EGYPTIAN HIEROGLYPH M012F;Lo;0;L;;;;;N;;;;; 131C3;EGYPTIAN HIEROGLYPH M012G;Lo;0;L;;;;;N;;;;; 131C4;EGYPTIAN HIEROGLYPH M012H;Lo;0;L;;;;;N;;;;; 131C5;EGYPTIAN HIEROGLYPH M013;Lo;0;L;;;;;N;;;;; 131C6;EGYPTIAN HIEROGLYPH M014;Lo;0;L;;;;;N;;;;; 131C7;EGYPTIAN HIEROGLYPH M015;Lo;0;L;;;;;N;;;;; 131C8;EGYPTIAN HIEROGLYPH M015A;Lo;0;L;;;;;N;;;;; 131C9;EGYPTIAN HIEROGLYPH M016;Lo;0;L;;;;;N;;;;; 131CA;EGYPTIAN HIEROGLYPH M016A;Lo;0;L;;;;;N;;;;; 131CB;EGYPTIAN HIEROGLYPH M017;Lo;0;L;;;;;N;;;;; 131CC;EGYPTIAN HIEROGLYPH M017A;Lo;0;L;;;;;N;;;;; 131CD;EGYPTIAN HIEROGLYPH M018;Lo;0;L;;;;;N;;;;; 131CE;EGYPTIAN HIEROGLYPH M019;Lo;0;L;;;;;N;;;;; 131CF;EGYPTIAN HIEROGLYPH M020;Lo;0;L;;;;;N;;;;; 131D0;EGYPTIAN HIEROGLYPH M021;Lo;0;L;;;;;N;;;;; 131D1;EGYPTIAN HIEROGLYPH M022;Lo;0;L;;;;;N;;;;; 131D2;EGYPTIAN HIEROGLYPH M022A;Lo;0;L;;;;;N;;;;; 131D3;EGYPTIAN HIEROGLYPH M023;Lo;0;L;;;;;N;;;;; 131D4;EGYPTIAN HIEROGLYPH M024;Lo;0;L;;;;;N;;;;; 131D5;EGYPTIAN HIEROGLYPH M024A;Lo;0;L;;;;;N;;;;; 131D6;EGYPTIAN HIEROGLYPH M025;Lo;0;L;;;;;N;;;;; 131D7;EGYPTIAN HIEROGLYPH M026;Lo;0;L;;;;;N;;;;; 131D8;EGYPTIAN HIEROGLYPH M027;Lo;0;L;;;;;N;;;;; 131D9;EGYPTIAN HIEROGLYPH M028;Lo;0;L;;;;;N;;;;; 131DA;EGYPTIAN HIEROGLYPH M028A;Lo;0;L;;;;;N;;;;; 131DB;EGYPTIAN HIEROGLYPH M029;Lo;0;L;;;;;N;;;;; 131DC;EGYPTIAN HIEROGLYPH M030;Lo;0;L;;;;;N;;;;; 131DD;EGYPTIAN HIEROGLYPH M031;Lo;0;L;;;;;N;;;;; 131DE;EGYPTIAN HIEROGLYPH M031A;Lo;0;L;;;;;N;;;;; 131DF;EGYPTIAN HIEROGLYPH M032;Lo;0;L;;;;;N;;;;; 131E0;EGYPTIAN HIEROGLYPH M033;Lo;0;L;;;;;N;;;;; 131E1;EGYPTIAN HIEROGLYPH M033A;Lo;0;L;;;;;N;;;;; 131E2;EGYPTIAN HIEROGLYPH M033B;Lo;0;L;;;;;N;;;;; 131E3;EGYPTIAN HIEROGLYPH M034;Lo;0;L;;;;;N;;;;; 131E4;EGYPTIAN HIEROGLYPH M035;Lo;0;L;;;;;N;;;;; 131E5;EGYPTIAN HIEROGLYPH M036;Lo;0;L;;;;;N;;;;; 131E6;EGYPTIAN HIEROGLYPH M037;Lo;0;L;;;;;N;;;;; 131E7;EGYPTIAN HIEROGLYPH M038;Lo;0;L;;;;;N;;;;; 131E8;EGYPTIAN HIEROGLYPH M039;Lo;0;L;;;;;N;;;;; 131E9;EGYPTIAN HIEROGLYPH M040;Lo;0;L;;;;;N;;;;; 131EA;EGYPTIAN HIEROGLYPH M040A;Lo;0;L;;;;;N;;;;; 131EB;EGYPTIAN HIEROGLYPH M041;Lo;0;L;;;;;N;;;;; 131EC;EGYPTIAN HIEROGLYPH M042;Lo;0;L;;;;;N;;;;; 131ED;EGYPTIAN HIEROGLYPH M043;Lo;0;L;;;;;N;;;;; 131EE;EGYPTIAN HIEROGLYPH M044;Lo;0;L;;;;;N;;;;; 131EF;EGYPTIAN HIEROGLYPH N001;Lo;0;L;;;;;N;;;;; 131F0;EGYPTIAN HIEROGLYPH N002;Lo;0;L;;;;;N;;;;; 131F1;EGYPTIAN HIEROGLYPH N003;Lo;0;L;;;;;N;;;;; 131F2;EGYPTIAN HIEROGLYPH N004;Lo;0;L;;;;;N;;;;; 131F3;EGYPTIAN HIEROGLYPH N005;Lo;0;L;;;;;N;;;;; 131F4;EGYPTIAN HIEROGLYPH N006;Lo;0;L;;;;;N;;;;; 131F5;EGYPTIAN HIEROGLYPH N007;Lo;0;L;;;;;N;;;;; 131F6;EGYPTIAN HIEROGLYPH N008;Lo;0;L;;;;;N;;;;; 131F7;EGYPTIAN HIEROGLYPH N009;Lo;0;L;;;;;N;;;;; 131F8;EGYPTIAN HIEROGLYPH N010;Lo;0;L;;;;;N;;;;; 131F9;EGYPTIAN HIEROGLYPH N011;Lo;0;L;;;;;N;;;;; 131FA;EGYPTIAN HIEROGLYPH N012;Lo;0;L;;;;;N;;;;; 131FB;EGYPTIAN HIEROGLYPH N013;Lo;0;L;;;;;N;;;;; 131FC;EGYPTIAN HIEROGLYPH N014;Lo;0;L;;;;;N;;;;; 131FD;EGYPTIAN HIEROGLYPH N015;Lo;0;L;;;;;N;;;;; 131FE;EGYPTIAN HIEROGLYPH N016;Lo;0;L;;;;;N;;;;; 131FF;EGYPTIAN HIEROGLYPH N017;Lo;0;L;;;;;N;;;;; 13200;EGYPTIAN HIEROGLYPH N018;Lo;0;L;;;;;N;;;;; 13201;EGYPTIAN HIEROGLYPH N018A;Lo;0;L;;;;;N;;;;; 13202;EGYPTIAN HIEROGLYPH N018B;Lo;0;L;;;;;N;;;;; 13203;EGYPTIAN HIEROGLYPH N019;Lo;0;L;;;;;N;;;;; 13204;EGYPTIAN HIEROGLYPH N020;Lo;0;L;;;;;N;;;;; 13205;EGYPTIAN HIEROGLYPH N021;Lo;0;L;;;;;N;;;;; 13206;EGYPTIAN HIEROGLYPH N022;Lo;0;L;;;;;N;;;;; 13207;EGYPTIAN HIEROGLYPH N023;Lo;0;L;;;;;N;;;;; 13208;EGYPTIAN HIEROGLYPH N024;Lo;0;L;;;;;N;;;;; 13209;EGYPTIAN HIEROGLYPH N025;Lo;0;L;;;;;N;;;;; 1320A;EGYPTIAN HIEROGLYPH N025A;Lo;0;L;;;;;N;;;;; 1320B;EGYPTIAN HIEROGLYPH N026;Lo;0;L;;;;;N;;;;; 1320C;EGYPTIAN HIEROGLYPH N027;Lo;0;L;;;;;N;;;;; 1320D;EGYPTIAN HIEROGLYPH N028;Lo;0;L;;;;;N;;;;; 1320E;EGYPTIAN HIEROGLYPH N029;Lo;0;L;;;;;N;;;;; 1320F;EGYPTIAN HIEROGLYPH N030;Lo;0;L;;;;;N;;;;; 13210;EGYPTIAN HIEROGLYPH N031;Lo;0;L;;;;;N;;;;; 13211;EGYPTIAN HIEROGLYPH N032;Lo;0;L;;;;;N;;;;; 13212;EGYPTIAN HIEROGLYPH N033;Lo;0;L;;;;;N;;;;; 13213;EGYPTIAN HIEROGLYPH N033A;Lo;0;L;;;;;N;;;;; 13214;EGYPTIAN HIEROGLYPH N034;Lo;0;L;;;;;N;;;;; 13215;EGYPTIAN HIEROGLYPH N034A;Lo;0;L;;;;;N;;;;; 13216;EGYPTIAN HIEROGLYPH N035;Lo;0;L;;;;;N;;;;; 13217;EGYPTIAN HIEROGLYPH N035A;Lo;0;L;;;;;N;;;;; 13218;EGYPTIAN HIEROGLYPH N036;Lo;0;L;;;;;N;;;;; 13219;EGYPTIAN HIEROGLYPH N037;Lo;0;L;;;;;N;;;;; 1321A;EGYPTIAN HIEROGLYPH N037A;Lo;0;L;;;;;N;;;;; 1321B;EGYPTIAN HIEROGLYPH N038;Lo;0;L;;;;;N;;;;; 1321C;EGYPTIAN HIEROGLYPH N039;Lo;0;L;;;;;N;;;;; 1321D;EGYPTIAN HIEROGLYPH N040;Lo;0;L;;;;;N;;;;; 1321E;EGYPTIAN HIEROGLYPH N041;Lo;0;L;;;;;N;;;;; 1321F;EGYPTIAN HIEROGLYPH N042;Lo;0;L;;;;;N;;;;; 13220;EGYPTIAN HIEROGLYPH NL001;Lo;0;L;;;;;N;;;;; 13221;EGYPTIAN HIEROGLYPH NL002;Lo;0;L;;;;;N;;;;; 13222;EGYPTIAN HIEROGLYPH NL003;Lo;0;L;;;;;N;;;;; 13223;EGYPTIAN HIEROGLYPH NL004;Lo;0;L;;;;;N;;;;; 13224;EGYPTIAN HIEROGLYPH NL005;Lo;0;L;;;;;N;;;;; 13225;EGYPTIAN HIEROGLYPH NL005A;Lo;0;L;;;;;N;;;;; 13226;EGYPTIAN HIEROGLYPH NL006;Lo;0;L;;;;;N;;;;; 13227;EGYPTIAN HIEROGLYPH NL007;Lo;0;L;;;;;N;;;;; 13228;EGYPTIAN HIEROGLYPH NL008;Lo;0;L;;;;;N;;;;; 13229;EGYPTIAN HIEROGLYPH NL009;Lo;0;L;;;;;N;;;;; 1322A;EGYPTIAN HIEROGLYPH NL010;Lo;0;L;;;;;N;;;;; 1322B;EGYPTIAN HIEROGLYPH NL011;Lo;0;L;;;;;N;;;;; 1322C;EGYPTIAN HIEROGLYPH NL012;Lo;0;L;;;;;N;;;;; 1322D;EGYPTIAN HIEROGLYPH NL013;Lo;0;L;;;;;N;;;;; 1322E;EGYPTIAN HIEROGLYPH NL014;Lo;0;L;;;;;N;;;;; 1322F;EGYPTIAN HIEROGLYPH NL015;Lo;0;L;;;;;N;;;;; 13230;EGYPTIAN HIEROGLYPH NL016;Lo;0;L;;;;;N;;;;; 13231;EGYPTIAN HIEROGLYPH NL017;Lo;0;L;;;;;N;;;;; 13232;EGYPTIAN HIEROGLYPH NL017A;Lo;0;L;;;;;N;;;;; 13233;EGYPTIAN HIEROGLYPH NL018;Lo;0;L;;;;;N;;;;; 13234;EGYPTIAN HIEROGLYPH NL019;Lo;0;L;;;;;N;;;;; 13235;EGYPTIAN HIEROGLYPH NL020;Lo;0;L;;;;;N;;;;; 13236;EGYPTIAN HIEROGLYPH NU001;Lo;0;L;;;;;N;;;;; 13237;EGYPTIAN HIEROGLYPH NU002;Lo;0;L;;;;;N;;;;; 13238;EGYPTIAN HIEROGLYPH NU003;Lo;0;L;;;;;N;;;;; 13239;EGYPTIAN HIEROGLYPH NU004;Lo;0;L;;;;;N;;;;; 1323A;EGYPTIAN HIEROGLYPH NU005;Lo;0;L;;;;;N;;;;; 1323B;EGYPTIAN HIEROGLYPH NU006;Lo;0;L;;;;;N;;;;; 1323C;EGYPTIAN HIEROGLYPH NU007;Lo;0;L;;;;;N;;;;; 1323D;EGYPTIAN HIEROGLYPH NU008;Lo;0;L;;;;;N;;;;; 1323E;EGYPTIAN HIEROGLYPH NU009;Lo;0;L;;;;;N;;;;; 1323F;EGYPTIAN HIEROGLYPH NU010;Lo;0;L;;;;;N;;;;; 13240;EGYPTIAN HIEROGLYPH NU010A;Lo;0;L;;;;;N;;;;; 13241;EGYPTIAN HIEROGLYPH NU011;Lo;0;L;;;;;N;;;;; 13242;EGYPTIAN HIEROGLYPH NU011A;Lo;0;L;;;;;N;;;;; 13243;EGYPTIAN HIEROGLYPH NU012;Lo;0;L;;;;;N;;;;; 13244;EGYPTIAN HIEROGLYPH NU013;Lo;0;L;;;;;N;;;;; 13245;EGYPTIAN HIEROGLYPH NU014;Lo;0;L;;;;;N;;;;; 13246;EGYPTIAN HIEROGLYPH NU015;Lo;0;L;;;;;N;;;;; 13247;EGYPTIAN HIEROGLYPH NU016;Lo;0;L;;;;;N;;;;; 13248;EGYPTIAN HIEROGLYPH NU017;Lo;0;L;;;;;N;;;;; 13249;EGYPTIAN HIEROGLYPH NU018;Lo;0;L;;;;;N;;;;; 1324A;EGYPTIAN HIEROGLYPH NU018A;Lo;0;L;;;;;N;;;;; 1324B;EGYPTIAN HIEROGLYPH NU019;Lo;0;L;;;;;N;;;;; 1324C;EGYPTIAN HIEROGLYPH NU020;Lo;0;L;;;;;N;;;;; 1324D;EGYPTIAN HIEROGLYPH NU021;Lo;0;L;;;;;N;;;;; 1324E;EGYPTIAN HIEROGLYPH NU022;Lo;0;L;;;;;N;;;;; 1324F;EGYPTIAN HIEROGLYPH NU022A;Lo;0;L;;;;;N;;;;; 13250;EGYPTIAN HIEROGLYPH O001;Lo;0;L;;;;;N;;;;; 13251;EGYPTIAN HIEROGLYPH O001A;Lo;0;L;;;;;N;;;;; 13252;EGYPTIAN HIEROGLYPH O002;Lo;0;L;;;;;N;;;;; 13253;EGYPTIAN HIEROGLYPH O003;Lo;0;L;;;;;N;;;;; 13254;EGYPTIAN HIEROGLYPH O004;Lo;0;L;;;;;N;;;;; 13255;EGYPTIAN HIEROGLYPH O005;Lo;0;L;;;;;N;;;;; 13256;EGYPTIAN HIEROGLYPH O005A;Lo;0;L;;;;;N;;;;; 13257;EGYPTIAN HIEROGLYPH O006;Lo;0;L;;;;;N;;;;; 13258;EGYPTIAN HIEROGLYPH O006A;Lo;0;L;;;;;N;;;;; 13259;EGYPTIAN HIEROGLYPH O006B;Lo;0;L;;;;;N;;;;; 1325A;EGYPTIAN HIEROGLYPH O006C;Lo;0;L;;;;;N;;;;; 1325B;EGYPTIAN HIEROGLYPH O006D;Lo;0;L;;;;;N;;;;; 1325C;EGYPTIAN HIEROGLYPH O006E;Lo;0;L;;;;;N;;;;; 1325D;EGYPTIAN HIEROGLYPH O006F;Lo;0;L;;;;;N;;;;; 1325E;EGYPTIAN HIEROGLYPH O007;Lo;0;L;;;;;N;;;;; 1325F;EGYPTIAN HIEROGLYPH O008;Lo;0;L;;;;;N;;;;; 13260;EGYPTIAN HIEROGLYPH O009;Lo;0;L;;;;;N;;;;; 13261;EGYPTIAN HIEROGLYPH O010;Lo;0;L;;;;;N;;;;; 13262;EGYPTIAN HIEROGLYPH O010A;Lo;0;L;;;;;N;;;;; 13263;EGYPTIAN HIEROGLYPH O010B;Lo;0;L;;;;;N;;;;; 13264;EGYPTIAN HIEROGLYPH O010C;Lo;0;L;;;;;N;;;;; 13265;EGYPTIAN HIEROGLYPH O011;Lo;0;L;;;;;N;;;;; 13266;EGYPTIAN HIEROGLYPH O012;Lo;0;L;;;;;N;;;;; 13267;EGYPTIAN HIEROGLYPH O013;Lo;0;L;;;;;N;;;;; 13268;EGYPTIAN HIEROGLYPH O014;Lo;0;L;;;;;N;;;;; 13269;EGYPTIAN HIEROGLYPH O015;Lo;0;L;;;;;N;;;;; 1326A;EGYPTIAN HIEROGLYPH O016;Lo;0;L;;;;;N;;;;; 1326B;EGYPTIAN HIEROGLYPH O017;Lo;0;L;;;;;N;;;;; 1326C;EGYPTIAN HIEROGLYPH O018;Lo;0;L;;;;;N;;;;; 1326D;EGYPTIAN HIEROGLYPH O019;Lo;0;L;;;;;N;;;;; 1326E;EGYPTIAN HIEROGLYPH O019A;Lo;0;L;;;;;N;;;;; 1326F;EGYPTIAN HIEROGLYPH O020;Lo;0;L;;;;;N;;;;; 13270;EGYPTIAN HIEROGLYPH O020A;Lo;0;L;;;;;N;;;;; 13271;EGYPTIAN HIEROGLYPH O021;Lo;0;L;;;;;N;;;;; 13272;EGYPTIAN HIEROGLYPH O022;Lo;0;L;;;;;N;;;;; 13273;EGYPTIAN HIEROGLYPH O023;Lo;0;L;;;;;N;;;;; 13274;EGYPTIAN HIEROGLYPH O024;Lo;0;L;;;;;N;;;;; 13275;EGYPTIAN HIEROGLYPH O024A;Lo;0;L;;;;;N;;;;; 13276;EGYPTIAN HIEROGLYPH O025;Lo;0;L;;;;;N;;;;; 13277;EGYPTIAN HIEROGLYPH O025A;Lo;0;L;;;;;N;;;;; 13278;EGYPTIAN HIEROGLYPH O026;Lo;0;L;;;;;N;;;;; 13279;EGYPTIAN HIEROGLYPH O027;Lo;0;L;;;;;N;;;;; 1327A;EGYPTIAN HIEROGLYPH O028;Lo;0;L;;;;;N;;;;; 1327B;EGYPTIAN HIEROGLYPH O029;Lo;0;L;;;;;N;;;;; 1327C;EGYPTIAN HIEROGLYPH O029A;Lo;0;L;;;;;N;;;;; 1327D;EGYPTIAN HIEROGLYPH O030;Lo;0;L;;;;;N;;;;; 1327E;EGYPTIAN HIEROGLYPH O030A;Lo;0;L;;;;;N;;;;; 1327F;EGYPTIAN HIEROGLYPH O031;Lo;0;L;;;;;N;;;;; 13280;EGYPTIAN HIEROGLYPH O032;Lo;0;L;;;;;N;;;;; 13281;EGYPTIAN HIEROGLYPH O033;Lo;0;L;;;;;N;;;;; 13282;EGYPTIAN HIEROGLYPH O033A;Lo;0;L;;;;;N;;;;; 13283;EGYPTIAN HIEROGLYPH O034;Lo;0;L;;;;;N;;;;; 13284;EGYPTIAN HIEROGLYPH O035;Lo;0;L;;;;;N;;;;; 13285;EGYPTIAN HIEROGLYPH O036;Lo;0;L;;;;;N;;;;; 13286;EGYPTIAN HIEROGLYPH O036A;Lo;0;L;;;;;N;;;;; 13287;EGYPTIAN HIEROGLYPH O036B;Lo;0;L;;;;;N;;;;; 13288;EGYPTIAN HIEROGLYPH O036C;Lo;0;L;;;;;N;;;;; 13289;EGYPTIAN HIEROGLYPH O036D;Lo;0;L;;;;;N;;;;; 1328A;EGYPTIAN HIEROGLYPH O037;Lo;0;L;;;;;N;;;;; 1328B;EGYPTIAN HIEROGLYPH O038;Lo;0;L;;;;;N;;;;; 1328C;EGYPTIAN HIEROGLYPH O039;Lo;0;L;;;;;N;;;;; 1328D;EGYPTIAN HIEROGLYPH O040;Lo;0;L;;;;;N;;;;; 1328E;EGYPTIAN HIEROGLYPH O041;Lo;0;L;;;;;N;;;;; 1328F;EGYPTIAN HIEROGLYPH O042;Lo;0;L;;;;;N;;;;; 13290;EGYPTIAN HIEROGLYPH O043;Lo;0;L;;;;;N;;;;; 13291;EGYPTIAN HIEROGLYPH O044;Lo;0;L;;;;;N;;;;; 13292;EGYPTIAN HIEROGLYPH O045;Lo;0;L;;;;;N;;;;; 13293;EGYPTIAN HIEROGLYPH O046;Lo;0;L;;;;;N;;;;; 13294;EGYPTIAN HIEROGLYPH O047;Lo;0;L;;;;;N;;;;; 13295;EGYPTIAN HIEROGLYPH O048;Lo;0;L;;;;;N;;;;; 13296;EGYPTIAN HIEROGLYPH O049;Lo;0;L;;;;;N;;;;; 13297;EGYPTIAN HIEROGLYPH O050;Lo;0;L;;;;;N;;;;; 13298;EGYPTIAN HIEROGLYPH O050A;Lo;0;L;;;;;N;;;;; 13299;EGYPTIAN HIEROGLYPH O050B;Lo;0;L;;;;;N;;;;; 1329A;EGYPTIAN HIEROGLYPH O051;Lo;0;L;;;;;N;;;;; 1329B;EGYPTIAN HIEROGLYPH P001;Lo;0;L;;;;;N;;;;; 1329C;EGYPTIAN HIEROGLYPH P001A;Lo;0;L;;;;;N;;;;; 1329D;EGYPTIAN HIEROGLYPH P002;Lo;0;L;;;;;N;;;;; 1329E;EGYPTIAN HIEROGLYPH P003;Lo;0;L;;;;;N;;;;; 1329F;EGYPTIAN HIEROGLYPH P003A;Lo;0;L;;;;;N;;;;; 132A0;EGYPTIAN HIEROGLYPH P004;Lo;0;L;;;;;N;;;;; 132A1;EGYPTIAN HIEROGLYPH P005;Lo;0;L;;;;;N;;;;; 132A2;EGYPTIAN HIEROGLYPH P006;Lo;0;L;;;;;N;;;;; 132A3;EGYPTIAN HIEROGLYPH P007;Lo;0;L;;;;;N;;;;; 132A4;EGYPTIAN HIEROGLYPH P008;Lo;0;L;;;;;N;;;;; 132A5;EGYPTIAN HIEROGLYPH P009;Lo;0;L;;;;;N;;;;; 132A6;EGYPTIAN HIEROGLYPH P010;Lo;0;L;;;;;N;;;;; 132A7;EGYPTIAN HIEROGLYPH P011;Lo;0;L;;;;;N;;;;; 132A8;EGYPTIAN HIEROGLYPH Q001;Lo;0;L;;;;;N;;;;; 132A9;EGYPTIAN HIEROGLYPH Q002;Lo;0;L;;;;;N;;;;; 132AA;EGYPTIAN HIEROGLYPH Q003;Lo;0;L;;;;;N;;;;; 132AB;EGYPTIAN HIEROGLYPH Q004;Lo;0;L;;;;;N;;;;; 132AC;EGYPTIAN HIEROGLYPH Q005;Lo;0;L;;;;;N;;;;; 132AD;EGYPTIAN HIEROGLYPH Q006;Lo;0;L;;;;;N;;;;; 132AE;EGYPTIAN HIEROGLYPH Q007;Lo;0;L;;;;;N;;;;; 132AF;EGYPTIAN HIEROGLYPH R001;Lo;0;L;;;;;N;;;;; 132B0;EGYPTIAN HIEROGLYPH R002;Lo;0;L;;;;;N;;;;; 132B1;EGYPTIAN HIEROGLYPH R002A;Lo;0;L;;;;;N;;;;; 132B2;EGYPTIAN HIEROGLYPH R003;Lo;0;L;;;;;N;;;;; 132B3;EGYPTIAN HIEROGLYPH R003A;Lo;0;L;;;;;N;;;;; 132B4;EGYPTIAN HIEROGLYPH R003B;Lo;0;L;;;;;N;;;;; 132B5;EGYPTIAN HIEROGLYPH R004;Lo;0;L;;;;;N;;;;; 132B6;EGYPTIAN HIEROGLYPH R005;Lo;0;L;;;;;N;;;;; 132B7;EGYPTIAN HIEROGLYPH R006;Lo;0;L;;;;;N;;;;; 132B8;EGYPTIAN HIEROGLYPH R007;Lo;0;L;;;;;N;;;;; 132B9;EGYPTIAN HIEROGLYPH R008;Lo;0;L;;;;;N;;;;; 132BA;EGYPTIAN HIEROGLYPH R009;Lo;0;L;;;;;N;;;;; 132BB;EGYPTIAN HIEROGLYPH R010;Lo;0;L;;;;;N;;;;; 132BC;EGYPTIAN HIEROGLYPH R010A;Lo;0;L;;;;;N;;;;; 132BD;EGYPTIAN HIEROGLYPH R011;Lo;0;L;;;;;N;;;;; 132BE;EGYPTIAN HIEROGLYPH R012;Lo;0;L;;;;;N;;;;; 132BF;EGYPTIAN HIEROGLYPH R013;Lo;0;L;;;;;N;;;;; 132C0;EGYPTIAN HIEROGLYPH R014;Lo;0;L;;;;;N;;;;; 132C1;EGYPTIAN HIEROGLYPH R015;Lo;0;L;;;;;N;;;;; 132C2;EGYPTIAN HIEROGLYPH R016;Lo;0;L;;;;;N;;;;; 132C3;EGYPTIAN HIEROGLYPH R016A;Lo;0;L;;;;;N;;;;; 132C4;EGYPTIAN HIEROGLYPH R017;Lo;0;L;;;;;N;;;;; 132C5;EGYPTIAN HIEROGLYPH R018;Lo;0;L;;;;;N;;;;; 132C6;EGYPTIAN HIEROGLYPH R019;Lo;0;L;;;;;N;;;;; 132C7;EGYPTIAN HIEROGLYPH R020;Lo;0;L;;;;;N;;;;; 132C8;EGYPTIAN HIEROGLYPH R021;Lo;0;L;;;;;N;;;;; 132C9;EGYPTIAN HIEROGLYPH R022;Lo;0;L;;;;;N;;;;; 132CA;EGYPTIAN HIEROGLYPH R023;Lo;0;L;;;;;N;;;;; 132CB;EGYPTIAN HIEROGLYPH R024;Lo;0;L;;;;;N;;;;; 132CC;EGYPTIAN HIEROGLYPH R025;Lo;0;L;;;;;N;;;;; 132CD;EGYPTIAN HIEROGLYPH R026;Lo;0;L;;;;;N;;;;; 132CE;EGYPTIAN HIEROGLYPH R027;Lo;0;L;;;;;N;;;;; 132CF;EGYPTIAN HIEROGLYPH R028;Lo;0;L;;;;;N;;;;; 132D0;EGYPTIAN HIEROGLYPH R029;Lo;0;L;;;;;N;;;;; 132D1;EGYPTIAN HIEROGLYPH S001;Lo;0;L;;;;;N;;;;; 132D2;EGYPTIAN HIEROGLYPH S002;Lo;0;L;;;;;N;;;;; 132D3;EGYPTIAN HIEROGLYPH S002A;Lo;0;L;;;;;N;;;;; 132D4;EGYPTIAN HIEROGLYPH S003;Lo;0;L;;;;;N;;;;; 132D5;EGYPTIAN HIEROGLYPH S004;Lo;0;L;;;;;N;;;;; 132D6;EGYPTIAN HIEROGLYPH S005;Lo;0;L;;;;;N;;;;; 132D7;EGYPTIAN HIEROGLYPH S006;Lo;0;L;;;;;N;;;;; 132D8;EGYPTIAN HIEROGLYPH S006A;Lo;0;L;;;;;N;;;;; 132D9;EGYPTIAN HIEROGLYPH S007;Lo;0;L;;;;;N;;;;; 132DA;EGYPTIAN HIEROGLYPH S008;Lo;0;L;;;;;N;;;;; 132DB;EGYPTIAN HIEROGLYPH S009;Lo;0;L;;;;;N;;;;; 132DC;EGYPTIAN HIEROGLYPH S010;Lo;0;L;;;;;N;;;;; 132DD;EGYPTIAN HIEROGLYPH S011;Lo;0;L;;;;;N;;;;; 132DE;EGYPTIAN HIEROGLYPH S012;Lo;0;L;;;;;N;;;;; 132DF;EGYPTIAN HIEROGLYPH S013;Lo;0;L;;;;;N;;;;; 132E0;EGYPTIAN HIEROGLYPH S014;Lo;0;L;;;;;N;;;;; 132E1;EGYPTIAN HIEROGLYPH S014A;Lo;0;L;;;;;N;;;;; 132E2;EGYPTIAN HIEROGLYPH S014B;Lo;0;L;;;;;N;;;;; 132E3;EGYPTIAN HIEROGLYPH S015;Lo;0;L;;;;;N;;;;; 132E4;EGYPTIAN HIEROGLYPH S016;Lo;0;L;;;;;N;;;;; 132E5;EGYPTIAN HIEROGLYPH S017;Lo;0;L;;;;;N;;;;; 132E6;EGYPTIAN HIEROGLYPH S017A;Lo;0;L;;;;;N;;;;; 132E7;EGYPTIAN HIEROGLYPH S018;Lo;0;L;;;;;N;;;;; 132E8;EGYPTIAN HIEROGLYPH S019;Lo;0;L;;;;;N;;;;; 132E9;EGYPTIAN HIEROGLYPH S020;Lo;0;L;;;;;N;;;;; 132EA;EGYPTIAN HIEROGLYPH S021;Lo;0;L;;;;;N;;;;; 132EB;EGYPTIAN HIEROGLYPH S022;Lo;0;L;;;;;N;;;;; 132EC;EGYPTIAN HIEROGLYPH S023;Lo;0;L;;;;;N;;;;; 132ED;EGYPTIAN HIEROGLYPH S024;Lo;0;L;;;;;N;;;;; 132EE;EGYPTIAN HIEROGLYPH S025;Lo;0;L;;;;;N;;;;; 132EF;EGYPTIAN HIEROGLYPH S026;Lo;0;L;;;;;N;;;;; 132F0;EGYPTIAN HIEROGLYPH S026A;Lo;0;L;;;;;N;;;;; 132F1;EGYPTIAN HIEROGLYPH S026B;Lo;0;L;;;;;N;;;;; 132F2;EGYPTIAN HIEROGLYPH S027;Lo;0;L;;;;;N;;;;; 132F3;EGYPTIAN HIEROGLYPH S028;Lo;0;L;;;;;N;;;;; 132F4;EGYPTIAN HIEROGLYPH S029;Lo;0;L;;;;;N;;;;; 132F5;EGYPTIAN HIEROGLYPH S030;Lo;0;L;;;;;N;;;;; 132F6;EGYPTIAN HIEROGLYPH S031;Lo;0;L;;;;;N;;;;; 132F7;EGYPTIAN HIEROGLYPH S032;Lo;0;L;;;;;N;;;;; 132F8;EGYPTIAN HIEROGLYPH S033;Lo;0;L;;;;;N;;;;; 132F9;EGYPTIAN HIEROGLYPH S034;Lo;0;L;;;;;N;;;;; 132FA;EGYPTIAN HIEROGLYPH S035;Lo;0;L;;;;;N;;;;; 132FB;EGYPTIAN HIEROGLYPH S035A;Lo;0;L;;;;;N;;;;; 132FC;EGYPTIAN HIEROGLYPH S036;Lo;0;L;;;;;N;;;;; 132FD;EGYPTIAN HIEROGLYPH S037;Lo;0;L;;;;;N;;;;; 132FE;EGYPTIAN HIEROGLYPH S038;Lo;0;L;;;;;N;;;;; 132FF;EGYPTIAN HIEROGLYPH S039;Lo;0;L;;;;;N;;;;; 13300;EGYPTIAN HIEROGLYPH S040;Lo;0;L;;;;;N;;;;; 13301;EGYPTIAN HIEROGLYPH S041;Lo;0;L;;;;;N;;;;; 13302;EGYPTIAN HIEROGLYPH S042;Lo;0;L;;;;;N;;;;; 13303;EGYPTIAN HIEROGLYPH S043;Lo;0;L;;;;;N;;;;; 13304;EGYPTIAN HIEROGLYPH S044;Lo;0;L;;;;;N;;;;; 13305;EGYPTIAN HIEROGLYPH S045;Lo;0;L;;;;;N;;;;; 13306;EGYPTIAN HIEROGLYPH S046;Lo;0;L;;;;;N;;;;; 13307;EGYPTIAN HIEROGLYPH T001;Lo;0;L;;;;;N;;;;; 13308;EGYPTIAN HIEROGLYPH T002;Lo;0;L;;;;;N;;;;; 13309;EGYPTIAN HIEROGLYPH T003;Lo;0;L;;;;;N;;;;; 1330A;EGYPTIAN HIEROGLYPH T003A;Lo;0;L;;;;;N;;;;; 1330B;EGYPTIAN HIEROGLYPH T004;Lo;0;L;;;;;N;;;;; 1330C;EGYPTIAN HIEROGLYPH T005;Lo;0;L;;;;;N;;;;; 1330D;EGYPTIAN HIEROGLYPH T006;Lo;0;L;;;;;N;;;;; 1330E;EGYPTIAN HIEROGLYPH T007;Lo;0;L;;;;;N;;;;; 1330F;EGYPTIAN HIEROGLYPH T007A;Lo;0;L;;;;;N;;;;; 13310;EGYPTIAN HIEROGLYPH T008;Lo;0;L;;;;;N;;;;; 13311;EGYPTIAN HIEROGLYPH T008A;Lo;0;L;;;;;N;;;;; 13312;EGYPTIAN HIEROGLYPH T009;Lo;0;L;;;;;N;;;;; 13313;EGYPTIAN HIEROGLYPH T009A;Lo;0;L;;;;;N;;;;; 13314;EGYPTIAN HIEROGLYPH T010;Lo;0;L;;;;;N;;;;; 13315;EGYPTIAN HIEROGLYPH T011;Lo;0;L;;;;;N;;;;; 13316;EGYPTIAN HIEROGLYPH T011A;Lo;0;L;;;;;N;;;;; 13317;EGYPTIAN HIEROGLYPH T012;Lo;0;L;;;;;N;;;;; 13318;EGYPTIAN HIEROGLYPH T013;Lo;0;L;;;;;N;;;;; 13319;EGYPTIAN HIEROGLYPH T014;Lo;0;L;;;;;N;;;;; 1331A;EGYPTIAN HIEROGLYPH T015;Lo;0;L;;;;;N;;;;; 1331B;EGYPTIAN HIEROGLYPH T016;Lo;0;L;;;;;N;;;;; 1331C;EGYPTIAN HIEROGLYPH T016A;Lo;0;L;;;;;N;;;;; 1331D;EGYPTIAN HIEROGLYPH T017;Lo;0;L;;;;;N;;;;; 1331E;EGYPTIAN HIEROGLYPH T018;Lo;0;L;;;;;N;;;;; 1331F;EGYPTIAN HIEROGLYPH T019;Lo;0;L;;;;;N;;;;; 13320;EGYPTIAN HIEROGLYPH T020;Lo;0;L;;;;;N;;;;; 13321;EGYPTIAN HIEROGLYPH T021;Lo;0;L;;;;;N;;;;; 13322;EGYPTIAN HIEROGLYPH T022;Lo;0;L;;;;;N;;;;; 13323;EGYPTIAN HIEROGLYPH T023;Lo;0;L;;;;;N;;;;; 13324;EGYPTIAN HIEROGLYPH T024;Lo;0;L;;;;;N;;;;; 13325;EGYPTIAN HIEROGLYPH T025;Lo;0;L;;;;;N;;;;; 13326;EGYPTIAN HIEROGLYPH T026;Lo;0;L;;;;;N;;;;; 13327;EGYPTIAN HIEROGLYPH T027;Lo;0;L;;;;;N;;;;; 13328;EGYPTIAN HIEROGLYPH T028;Lo;0;L;;;;;N;;;;; 13329;EGYPTIAN HIEROGLYPH T029;Lo;0;L;;;;;N;;;;; 1332A;EGYPTIAN HIEROGLYPH T030;Lo;0;L;;;;;N;;;;; 1332B;EGYPTIAN HIEROGLYPH T031;Lo;0;L;;;;;N;;;;; 1332C;EGYPTIAN HIEROGLYPH T032;Lo;0;L;;;;;N;;;;; 1332D;EGYPTIAN HIEROGLYPH T032A;Lo;0;L;;;;;N;;;;; 1332E;EGYPTIAN HIEROGLYPH T033;Lo;0;L;;;;;N;;;;; 1332F;EGYPTIAN HIEROGLYPH T033A;Lo;0;L;;;;;N;;;;; 13330;EGYPTIAN HIEROGLYPH T034;Lo;0;L;;;;;N;;;;; 13331;EGYPTIAN HIEROGLYPH T035;Lo;0;L;;;;;N;;;;; 13332;EGYPTIAN HIEROGLYPH T036;Lo;0;L;;;;;N;;;;; 13333;EGYPTIAN HIEROGLYPH U001;Lo;0;L;;;;;N;;;;; 13334;EGYPTIAN HIEROGLYPH U002;Lo;0;L;;;;;N;;;;; 13335;EGYPTIAN HIEROGLYPH U003;Lo;0;L;;;;;N;;;;; 13336;EGYPTIAN HIEROGLYPH U004;Lo;0;L;;;;;N;;;;; 13337;EGYPTIAN HIEROGLYPH U005;Lo;0;L;;;;;N;;;;; 13338;EGYPTIAN HIEROGLYPH U006;Lo;0;L;;;;;N;;;;; 13339;EGYPTIAN HIEROGLYPH U006A;Lo;0;L;;;;;N;;;;; 1333A;EGYPTIAN HIEROGLYPH U006B;Lo;0;L;;;;;N;;;;; 1333B;EGYPTIAN HIEROGLYPH U007;Lo;0;L;;;;;N;;;;; 1333C;EGYPTIAN HIEROGLYPH U008;Lo;0;L;;;;;N;;;;; 1333D;EGYPTIAN HIEROGLYPH U009;Lo;0;L;;;;;N;;;;; 1333E;EGYPTIAN HIEROGLYPH U010;Lo;0;L;;;;;N;;;;; 1333F;EGYPTIAN HIEROGLYPH U011;Lo;0;L;;;;;N;;;;; 13340;EGYPTIAN HIEROGLYPH U012;Lo;0;L;;;;;N;;;;; 13341;EGYPTIAN HIEROGLYPH U013;Lo;0;L;;;;;N;;;;; 13342;EGYPTIAN HIEROGLYPH U014;Lo;0;L;;;;;N;;;;; 13343;EGYPTIAN HIEROGLYPH U015;Lo;0;L;;;;;N;;;;; 13344;EGYPTIAN HIEROGLYPH U016;Lo;0;L;;;;;N;;;;; 13345;EGYPTIAN HIEROGLYPH U017;Lo;0;L;;;;;N;;;;; 13346;EGYPTIAN HIEROGLYPH U018;Lo;0;L;;;;;N;;;;; 13347;EGYPTIAN HIEROGLYPH U019;Lo;0;L;;;;;N;;;;; 13348;EGYPTIAN HIEROGLYPH U020;Lo;0;L;;;;;N;;;;; 13349;EGYPTIAN HIEROGLYPH U021;Lo;0;L;;;;;N;;;;; 1334A;EGYPTIAN HIEROGLYPH U022;Lo;0;L;;;;;N;;;;; 1334B;EGYPTIAN HIEROGLYPH U023;Lo;0;L;;;;;N;;;;; 1334C;EGYPTIAN HIEROGLYPH U023A;Lo;0;L;;;;;N;;;;; 1334D;EGYPTIAN HIEROGLYPH U024;Lo;0;L;;;;;N;;;;; 1334E;EGYPTIAN HIEROGLYPH U025;Lo;0;L;;;;;N;;;;; 1334F;EGYPTIAN HIEROGLYPH U026;Lo;0;L;;;;;N;;;;; 13350;EGYPTIAN HIEROGLYPH U027;Lo;0;L;;;;;N;;;;; 13351;EGYPTIAN HIEROGLYPH U028;Lo;0;L;;;;;N;;;;; 13352;EGYPTIAN HIEROGLYPH U029;Lo;0;L;;;;;N;;;;; 13353;EGYPTIAN HIEROGLYPH U029A;Lo;0;L;;;;;N;;;;; 13354;EGYPTIAN HIEROGLYPH U030;Lo;0;L;;;;;N;;;;; 13355;EGYPTIAN HIEROGLYPH U031;Lo;0;L;;;;;N;;;;; 13356;EGYPTIAN HIEROGLYPH U032;Lo;0;L;;;;;N;;;;; 13357;EGYPTIAN HIEROGLYPH U032A;Lo;0;L;;;;;N;;;;; 13358;EGYPTIAN HIEROGLYPH U033;Lo;0;L;;;;;N;;;;; 13359;EGYPTIAN HIEROGLYPH U034;Lo;0;L;;;;;N;;;;; 1335A;EGYPTIAN HIEROGLYPH U035;Lo;0;L;;;;;N;;;;; 1335B;EGYPTIAN HIEROGLYPH U036;Lo;0;L;;;;;N;;;;; 1335C;EGYPTIAN HIEROGLYPH U037;Lo;0;L;;;;;N;;;;; 1335D;EGYPTIAN HIEROGLYPH U038;Lo;0;L;;;;;N;;;;; 1335E;EGYPTIAN HIEROGLYPH U039;Lo;0;L;;;;;N;;;;; 1335F;EGYPTIAN HIEROGLYPH U040;Lo;0;L;;;;;N;;;;; 13360;EGYPTIAN HIEROGLYPH U041;Lo;0;L;;;;;N;;;;; 13361;EGYPTIAN HIEROGLYPH U042;Lo;0;L;;;;;N;;;;; 13362;EGYPTIAN HIEROGLYPH V001;Lo;0;L;;;;;N;;;;; 13363;EGYPTIAN HIEROGLYPH V001A;Lo;0;L;;;;;N;;;;; 13364;EGYPTIAN HIEROGLYPH V001B;Lo;0;L;;;;;N;;;;; 13365;EGYPTIAN HIEROGLYPH V001C;Lo;0;L;;;;;N;;;;; 13366;EGYPTIAN HIEROGLYPH V001D;Lo;0;L;;;;;N;;;;; 13367;EGYPTIAN HIEROGLYPH V001E;Lo;0;L;;;;;N;;;;; 13368;EGYPTIAN HIEROGLYPH V001F;Lo;0;L;;;;;N;;;;; 13369;EGYPTIAN HIEROGLYPH V001G;Lo;0;L;;;;;N;;;;; 1336A;EGYPTIAN HIEROGLYPH V001H;Lo;0;L;;;;;N;;;;; 1336B;EGYPTIAN HIEROGLYPH V001I;Lo;0;L;;;;;N;;;;; 1336C;EGYPTIAN HIEROGLYPH V002;Lo;0;L;;;;;N;;;;; 1336D;EGYPTIAN HIEROGLYPH V002A;Lo;0;L;;;;;N;;;;; 1336E;EGYPTIAN HIEROGLYPH V003;Lo;0;L;;;;;N;;;;; 1336F;EGYPTIAN HIEROGLYPH V004;Lo;0;L;;;;;N;;;;; 13370;EGYPTIAN HIEROGLYPH V005;Lo;0;L;;;;;N;;;;; 13371;EGYPTIAN HIEROGLYPH V006;Lo;0;L;;;;;N;;;;; 13372;EGYPTIAN HIEROGLYPH V007;Lo;0;L;;;;;N;;;;; 13373;EGYPTIAN HIEROGLYPH V007A;Lo;0;L;;;;;N;;;;; 13374;EGYPTIAN HIEROGLYPH V007B;Lo;0;L;;;;;N;;;;; 13375;EGYPTIAN HIEROGLYPH V008;Lo;0;L;;;;;N;;;;; 13376;EGYPTIAN HIEROGLYPH V009;Lo;0;L;;;;;N;;;;; 13377;EGYPTIAN HIEROGLYPH V010;Lo;0;L;;;;;N;;;;; 13378;EGYPTIAN HIEROGLYPH V011;Lo;0;L;;;;;N;;;;; 13379;EGYPTIAN HIEROGLYPH V011A;Lo;0;L;;;;;N;;;;; 1337A;EGYPTIAN HIEROGLYPH V011B;Lo;0;L;;;;;N;;;;; 1337B;EGYPTIAN HIEROGLYPH V011C;Lo;0;L;;;;;N;;;;; 1337C;EGYPTIAN HIEROGLYPH V012;Lo;0;L;;;;;N;;;;; 1337D;EGYPTIAN HIEROGLYPH V012A;Lo;0;L;;;;;N;;;;; 1337E;EGYPTIAN HIEROGLYPH V012B;Lo;0;L;;;;;N;;;;; 1337F;EGYPTIAN HIEROGLYPH V013;Lo;0;L;;;;;N;;;;; 13380;EGYPTIAN HIEROGLYPH V014;Lo;0;L;;;;;N;;;;; 13381;EGYPTIAN HIEROGLYPH V015;Lo;0;L;;;;;N;;;;; 13382;EGYPTIAN HIEROGLYPH V016;Lo;0;L;;;;;N;;;;; 13383;EGYPTIAN HIEROGLYPH V017;Lo;0;L;;;;;N;;;;; 13384;EGYPTIAN HIEROGLYPH V018;Lo;0;L;;;;;N;;;;; 13385;EGYPTIAN HIEROGLYPH V019;Lo;0;L;;;;;N;;;;; 13386;EGYPTIAN HIEROGLYPH V020;Lo;0;L;;;;;N;;;;; 13387;EGYPTIAN HIEROGLYPH V020A;Lo;0;L;;;;;N;;;;; 13388;EGYPTIAN HIEROGLYPH V020B;Lo;0;L;;;;;N;;;;; 13389;EGYPTIAN HIEROGLYPH V020C;Lo;0;L;;;;;N;;;;; 1338A;EGYPTIAN HIEROGLYPH V020D;Lo;0;L;;;;;N;;;;; 1338B;EGYPTIAN HIEROGLYPH V020E;Lo;0;L;;;;;N;;;;; 1338C;EGYPTIAN HIEROGLYPH V020F;Lo;0;L;;;;;N;;;;; 1338D;EGYPTIAN HIEROGLYPH V020G;Lo;0;L;;;;;N;;;;; 1338E;EGYPTIAN HIEROGLYPH V020H;Lo;0;L;;;;;N;;;;; 1338F;EGYPTIAN HIEROGLYPH V020I;Lo;0;L;;;;;N;;;;; 13390;EGYPTIAN HIEROGLYPH V020J;Lo;0;L;;;;;N;;;;; 13391;EGYPTIAN HIEROGLYPH V020K;Lo;0;L;;;;;N;;;;; 13392;EGYPTIAN HIEROGLYPH V020L;Lo;0;L;;;;;N;;;;; 13393;EGYPTIAN HIEROGLYPH V021;Lo;0;L;;;;;N;;;;; 13394;EGYPTIAN HIEROGLYPH V022;Lo;0;L;;;;;N;;;;; 13395;EGYPTIAN HIEROGLYPH V023;Lo;0;L;;;;;N;;;;; 13396;EGYPTIAN HIEROGLYPH V023A;Lo;0;L;;;;;N;;;;; 13397;EGYPTIAN HIEROGLYPH V024;Lo;0;L;;;;;N;;;;; 13398;EGYPTIAN HIEROGLYPH V025;Lo;0;L;;;;;N;;;;; 13399;EGYPTIAN HIEROGLYPH V026;Lo;0;L;;;;;N;;;;; 1339A;EGYPTIAN HIEROGLYPH V027;Lo;0;L;;;;;N;;;;; 1339B;EGYPTIAN HIEROGLYPH V028;Lo;0;L;;;;;N;;;;; 1339C;EGYPTIAN HIEROGLYPH V028A;Lo;0;L;;;;;N;;;;; 1339D;EGYPTIAN HIEROGLYPH V029;Lo;0;L;;;;;N;;;;; 1339E;EGYPTIAN HIEROGLYPH V029A;Lo;0;L;;;;;N;;;;; 1339F;EGYPTIAN HIEROGLYPH V030;Lo;0;L;;;;;N;;;;; 133A0;EGYPTIAN HIEROGLYPH V030A;Lo;0;L;;;;;N;;;;; 133A1;EGYPTIAN HIEROGLYPH V031;Lo;0;L;;;;;N;;;;; 133A2;EGYPTIAN HIEROGLYPH V031A;Lo;0;L;;;;;N;;;;; 133A3;EGYPTIAN HIEROGLYPH V032;Lo;0;L;;;;;N;;;;; 133A4;EGYPTIAN HIEROGLYPH V033;Lo;0;L;;;;;N;;;;; 133A5;EGYPTIAN HIEROGLYPH V033A;Lo;0;L;;;;;N;;;;; 133A6;EGYPTIAN HIEROGLYPH V034;Lo;0;L;;;;;N;;;;; 133A7;EGYPTIAN HIEROGLYPH V035;Lo;0;L;;;;;N;;;;; 133A8;EGYPTIAN HIEROGLYPH V036;Lo;0;L;;;;;N;;;;; 133A9;EGYPTIAN HIEROGLYPH V037;Lo;0;L;;;;;N;;;;; 133AA;EGYPTIAN HIEROGLYPH V037A;Lo;0;L;;;;;N;;;;; 133AB;EGYPTIAN HIEROGLYPH V038;Lo;0;L;;;;;N;;;;; 133AC;EGYPTIAN HIEROGLYPH V039;Lo;0;L;;;;;N;;;;; 133AD;EGYPTIAN HIEROGLYPH V040;Lo;0;L;;;;;N;;;;; 133AE;EGYPTIAN HIEROGLYPH V040A;Lo;0;L;;;;;N;;;;; 133AF;EGYPTIAN HIEROGLYPH W001;Lo;0;L;;;;;N;;;;; 133B0;EGYPTIAN HIEROGLYPH W002;Lo;0;L;;;;;N;;;;; 133B1;EGYPTIAN HIEROGLYPH W003;Lo;0;L;;;;;N;;;;; 133B2;EGYPTIAN HIEROGLYPH W003A;Lo;0;L;;;;;N;;;;; 133B3;EGYPTIAN HIEROGLYPH W004;Lo;0;L;;;;;N;;;;; 133B4;EGYPTIAN HIEROGLYPH W005;Lo;0;L;;;;;N;;;;; 133B5;EGYPTIAN HIEROGLYPH W006;Lo;0;L;;;;;N;;;;; 133B6;EGYPTIAN HIEROGLYPH W007;Lo;0;L;;;;;N;;;;; 133B7;EGYPTIAN HIEROGLYPH W008;Lo;0;L;;;;;N;;;;; 133B8;EGYPTIAN HIEROGLYPH W009;Lo;0;L;;;;;N;;;;; 133B9;EGYPTIAN HIEROGLYPH W009A;Lo;0;L;;;;;N;;;;; 133BA;EGYPTIAN HIEROGLYPH W010;Lo;0;L;;;;;N;;;;; 133BB;EGYPTIAN HIEROGLYPH W010A;Lo;0;L;;;;;N;;;;; 133BC;EGYPTIAN HIEROGLYPH W011;Lo;0;L;;;;;N;;;;; 133BD;EGYPTIAN HIEROGLYPH W012;Lo;0;L;;;;;N;;;;; 133BE;EGYPTIAN HIEROGLYPH W013;Lo;0;L;;;;;N;;;;; 133BF;EGYPTIAN HIEROGLYPH W014;Lo;0;L;;;;;N;;;;; 133C0;EGYPTIAN HIEROGLYPH W014A;Lo;0;L;;;;;N;;;;; 133C1;EGYPTIAN HIEROGLYPH W015;Lo;0;L;;;;;N;;;;; 133C2;EGYPTIAN HIEROGLYPH W016;Lo;0;L;;;;;N;;;;; 133C3;EGYPTIAN HIEROGLYPH W017;Lo;0;L;;;;;N;;;;; 133C4;EGYPTIAN HIEROGLYPH W017A;Lo;0;L;;;;;N;;;;; 133C5;EGYPTIAN HIEROGLYPH W018;Lo;0;L;;;;;N;;;;; 133C6;EGYPTIAN HIEROGLYPH W018A;Lo;0;L;;;;;N;;;;; 133C7;EGYPTIAN HIEROGLYPH W019;Lo;0;L;;;;;N;;;;; 133C8;EGYPTIAN HIEROGLYPH W020;Lo;0;L;;;;;N;;;;; 133C9;EGYPTIAN HIEROGLYPH W021;Lo;0;L;;;;;N;;;;; 133CA;EGYPTIAN HIEROGLYPH W022;Lo;0;L;;;;;N;;;;; 133CB;EGYPTIAN HIEROGLYPH W023;Lo;0;L;;;;;N;;;;; 133CC;EGYPTIAN HIEROGLYPH W024;Lo;0;L;;;;;N;;;;; 133CD;EGYPTIAN HIEROGLYPH W024A;Lo;0;L;;;;;N;;;;; 133CE;EGYPTIAN HIEROGLYPH W025;Lo;0;L;;;;;N;;;;; 133CF;EGYPTIAN HIEROGLYPH X001;Lo;0;L;;;;;N;;;;; 133D0;EGYPTIAN HIEROGLYPH X002;Lo;0;L;;;;;N;;;;; 133D1;EGYPTIAN HIEROGLYPH X003;Lo;0;L;;;;;N;;;;; 133D2;EGYPTIAN HIEROGLYPH X004;Lo;0;L;;;;;N;;;;; 133D3;EGYPTIAN HIEROGLYPH X004A;Lo;0;L;;;;;N;;;;; 133D4;EGYPTIAN HIEROGLYPH X004B;Lo;0;L;;;;;N;;;;; 133D5;EGYPTIAN HIEROGLYPH X005;Lo;0;L;;;;;N;;;;; 133D6;EGYPTIAN HIEROGLYPH X006;Lo;0;L;;;;;N;;;;; 133D7;EGYPTIAN HIEROGLYPH X006A;Lo;0;L;;;;;N;;;;; 133D8;EGYPTIAN HIEROGLYPH X007;Lo;0;L;;;;;N;;;;; 133D9;EGYPTIAN HIEROGLYPH X008;Lo;0;L;;;;;N;;;;; 133DA;EGYPTIAN HIEROGLYPH X008A;Lo;0;L;;;;;N;;;;; 133DB;EGYPTIAN HIEROGLYPH Y001;Lo;0;L;;;;;N;;;;; 133DC;EGYPTIAN HIEROGLYPH Y001A;Lo;0;L;;;;;N;;;;; 133DD;EGYPTIAN HIEROGLYPH Y002;Lo;0;L;;;;;N;;;;; 133DE;EGYPTIAN HIEROGLYPH Y003;Lo;0;L;;;;;N;;;;; 133DF;EGYPTIAN HIEROGLYPH Y004;Lo;0;L;;;;;N;;;;; 133E0;EGYPTIAN HIEROGLYPH Y005;Lo;0;L;;;;;N;;;;; 133E1;EGYPTIAN HIEROGLYPH Y006;Lo;0;L;;;;;N;;;;; 133E2;EGYPTIAN HIEROGLYPH Y007;Lo;0;L;;;;;N;;;;; 133E3;EGYPTIAN HIEROGLYPH Y008;Lo;0;L;;;;;N;;;;; 133E4;EGYPTIAN HIEROGLYPH Z001;Lo;0;L;;;;;N;;;;; 133E5;EGYPTIAN HIEROGLYPH Z002;Lo;0;L;;;;;N;;;;; 133E6;EGYPTIAN HIEROGLYPH Z002A;Lo;0;L;;;;;N;;;;; 133E7;EGYPTIAN HIEROGLYPH Z002B;Lo;0;L;;;;;N;;;;; 133E8;EGYPTIAN HIEROGLYPH Z002C;Lo;0;L;;;;;N;;;;; 133E9;EGYPTIAN HIEROGLYPH Z002D;Lo;0;L;;;;;N;;;;; 133EA;EGYPTIAN HIEROGLYPH Z003;Lo;0;L;;;;;N;;;;; 133EB;EGYPTIAN HIEROGLYPH Z003A;Lo;0;L;;;;;N;;;;; 133EC;EGYPTIAN HIEROGLYPH Z003B;Lo;0;L;;;;;N;;;;; 133ED;EGYPTIAN HIEROGLYPH Z004;Lo;0;L;;;;;N;;;;; 133EE;EGYPTIAN HIEROGLYPH Z004A;Lo;0;L;;;;;N;;;;; 133EF;EGYPTIAN HIEROGLYPH Z005;Lo;0;L;;;;;N;;;;; 133F0;EGYPTIAN HIEROGLYPH Z005A;Lo;0;L;;;;;N;;;;; 133F1;EGYPTIAN HIEROGLYPH Z006;Lo;0;L;;;;;N;;;;; 133F2;EGYPTIAN HIEROGLYPH Z007;Lo;0;L;;;;;N;;;;; 133F3;EGYPTIAN HIEROGLYPH Z008;Lo;0;L;;;;;N;;;;; 133F4;EGYPTIAN HIEROGLYPH Z009;Lo;0;L;;;;;N;;;;; 133F5;EGYPTIAN HIEROGLYPH Z010;Lo;0;L;;;;;N;;;;; 133F6;EGYPTIAN HIEROGLYPH Z011;Lo;0;L;;;;;N;;;;; 133F7;EGYPTIAN HIEROGLYPH Z012;Lo;0;L;;;;;N;;;;; 133F8;EGYPTIAN HIEROGLYPH Z013;Lo;0;L;;;;;N;;;;; 133F9;EGYPTIAN HIEROGLYPH Z014;Lo;0;L;;;;;N;;;;; 133FA;EGYPTIAN HIEROGLYPH Z015;Lo;0;L;;;;;N;;;;; 133FB;EGYPTIAN HIEROGLYPH Z015A;Lo;0;L;;;;;N;;;;; 133FC;EGYPTIAN HIEROGLYPH Z015B;Lo;0;L;;;;;N;;;;; 133FD;EGYPTIAN HIEROGLYPH Z015C;Lo;0;L;;;;;N;;;;; 133FE;EGYPTIAN HIEROGLYPH Z015D;Lo;0;L;;;;;N;;;;; 133FF;EGYPTIAN HIEROGLYPH Z015E;Lo;0;L;;;;;N;;;;; 13400;EGYPTIAN HIEROGLYPH Z015F;Lo;0;L;;;;;N;;;;; 13401;EGYPTIAN HIEROGLYPH Z015G;Lo;0;L;;;;;N;;;;; 13402;EGYPTIAN HIEROGLYPH Z015H;Lo;0;L;;;;;N;;;;; 13403;EGYPTIAN HIEROGLYPH Z015I;Lo;0;L;;;;;N;;;;; 13404;EGYPTIAN HIEROGLYPH Z016;Lo;0;L;;;;;N;;;;; 13405;EGYPTIAN HIEROGLYPH Z016A;Lo;0;L;;;;;N;;;;; 13406;EGYPTIAN HIEROGLYPH Z016B;Lo;0;L;;;;;N;;;;; 13407;EGYPTIAN HIEROGLYPH Z016C;Lo;0;L;;;;;N;;;;; 13408;EGYPTIAN HIEROGLYPH Z016D;Lo;0;L;;;;;N;;;;; 13409;EGYPTIAN HIEROGLYPH Z016E;Lo;0;L;;;;;N;;;;; 1340A;EGYPTIAN HIEROGLYPH Z016F;Lo;0;L;;;;;N;;;;; 1340B;EGYPTIAN HIEROGLYPH Z016G;Lo;0;L;;;;;N;;;;; 1340C;EGYPTIAN HIEROGLYPH Z016H;Lo;0;L;;;;;N;;;;; 1340D;EGYPTIAN HIEROGLYPH AA001;Lo;0;L;;;;;N;;;;; 1340E;EGYPTIAN HIEROGLYPH AA002;Lo;0;L;;;;;N;;;;; 1340F;EGYPTIAN HIEROGLYPH AA003;Lo;0;L;;;;;N;;;;; 13410;EGYPTIAN HIEROGLYPH AA004;Lo;0;L;;;;;N;;;;; 13411;EGYPTIAN HIEROGLYPH AA005;Lo;0;L;;;;;N;;;;; 13412;EGYPTIAN HIEROGLYPH AA006;Lo;0;L;;;;;N;;;;; 13413;EGYPTIAN HIEROGLYPH AA007;Lo;0;L;;;;;N;;;;; 13414;EGYPTIAN HIEROGLYPH AA007A;Lo;0;L;;;;;N;;;;; 13415;EGYPTIAN HIEROGLYPH AA007B;Lo;0;L;;;;;N;;;;; 13416;EGYPTIAN HIEROGLYPH AA008;Lo;0;L;;;;;N;;;;; 13417;EGYPTIAN HIEROGLYPH AA009;Lo;0;L;;;;;N;;;;; 13418;EGYPTIAN HIEROGLYPH AA010;Lo;0;L;;;;;N;;;;; 13419;EGYPTIAN HIEROGLYPH AA011;Lo;0;L;;;;;N;;;;; 1341A;EGYPTIAN HIEROGLYPH AA012;Lo;0;L;;;;;N;;;;; 1341B;EGYPTIAN HIEROGLYPH AA013;Lo;0;L;;;;;N;;;;; 1341C;EGYPTIAN HIEROGLYPH AA014;Lo;0;L;;;;;N;;;;; 1341D;EGYPTIAN HIEROGLYPH AA015;Lo;0;L;;;;;N;;;;; 1341E;EGYPTIAN HIEROGLYPH AA016;Lo;0;L;;;;;N;;;;; 1341F;EGYPTIAN HIEROGLYPH AA017;Lo;0;L;;;;;N;;;;; 13420;EGYPTIAN HIEROGLYPH AA018;Lo;0;L;;;;;N;;;;; 13421;EGYPTIAN HIEROGLYPH AA019;Lo;0;L;;;;;N;;;;; 13422;EGYPTIAN HIEROGLYPH AA020;Lo;0;L;;;;;N;;;;; 13423;EGYPTIAN HIEROGLYPH AA021;Lo;0;L;;;;;N;;;;; 13424;EGYPTIAN HIEROGLYPH AA022;Lo;0;L;;;;;N;;;;; 13425;EGYPTIAN HIEROGLYPH AA023;Lo;0;L;;;;;N;;;;; 13426;EGYPTIAN HIEROGLYPH AA024;Lo;0;L;;;;;N;;;;; 13427;EGYPTIAN HIEROGLYPH AA025;Lo;0;L;;;;;N;;;;; 13428;EGYPTIAN HIEROGLYPH AA026;Lo;0;L;;;;;N;;;;; 13429;EGYPTIAN HIEROGLYPH AA027;Lo;0;L;;;;;N;;;;; 1342A;EGYPTIAN HIEROGLYPH AA028;Lo;0;L;;;;;N;;;;; 1342B;EGYPTIAN HIEROGLYPH AA029;Lo;0;L;;;;;N;;;;; 1342C;EGYPTIAN HIEROGLYPH AA030;Lo;0;L;;;;;N;;;;; 1342D;EGYPTIAN HIEROGLYPH AA031;Lo;0;L;;;;;N;;;;; 1342E;EGYPTIAN HIEROGLYPH AA032;Lo;0;L;;;;;N;;;;; 14400;ANATOLIAN HIEROGLYPH A001;Lo;0;L;;;;;N;;;;; 14401;ANATOLIAN HIEROGLYPH A002;Lo;0;L;;;;;N;;;;; 14402;ANATOLIAN HIEROGLYPH A003;Lo;0;L;;;;;N;;;;; 14403;ANATOLIAN HIEROGLYPH A004;Lo;0;L;;;;;N;;;;; 14404;ANATOLIAN HIEROGLYPH A005;Lo;0;L;;;;;N;;;;; 14405;ANATOLIAN HIEROGLYPH A006;Lo;0;L;;;;;N;;;;; 14406;ANATOLIAN HIEROGLYPH A007;Lo;0;L;;;;;N;;;;; 14407;ANATOLIAN HIEROGLYPH A008;Lo;0;L;;;;;N;;;;; 14408;ANATOLIAN HIEROGLYPH A009;Lo;0;L;;;;;N;;;;; 14409;ANATOLIAN HIEROGLYPH A010;Lo;0;L;;;;;N;;;;; 1440A;ANATOLIAN HIEROGLYPH A010A;Lo;0;L;;;;;N;;;;; 1440B;ANATOLIAN HIEROGLYPH A011;Lo;0;L;;;;;N;;;;; 1440C;ANATOLIAN HIEROGLYPH A012;Lo;0;L;;;;;N;;;;; 1440D;ANATOLIAN HIEROGLYPH A013;Lo;0;L;;;;;N;;;;; 1440E;ANATOLIAN HIEROGLYPH A014;Lo;0;L;;;;;N;;;;; 1440F;ANATOLIAN HIEROGLYPH A015;Lo;0;L;;;;;N;;;;; 14410;ANATOLIAN HIEROGLYPH A016;Lo;0;L;;;;;N;;;;; 14411;ANATOLIAN HIEROGLYPH A017;Lo;0;L;;;;;N;;;;; 14412;ANATOLIAN HIEROGLYPH A018;Lo;0;L;;;;;N;;;;; 14413;ANATOLIAN HIEROGLYPH A019;Lo;0;L;;;;;N;;;;; 14414;ANATOLIAN HIEROGLYPH A020;Lo;0;L;;;;;N;;;;; 14415;ANATOLIAN HIEROGLYPH A021;Lo;0;L;;;;;N;;;;; 14416;ANATOLIAN HIEROGLYPH A022;Lo;0;L;;;;;N;;;;; 14417;ANATOLIAN HIEROGLYPH A023;Lo;0;L;;;;;N;;;;; 14418;ANATOLIAN HIEROGLYPH A024;Lo;0;L;;;;;N;;;;; 14419;ANATOLIAN HIEROGLYPH A025;Lo;0;L;;;;;N;;;;; 1441A;ANATOLIAN HIEROGLYPH A026;Lo;0;L;;;;;N;;;;; 1441B;ANATOLIAN HIEROGLYPH A026A;Lo;0;L;;;;;N;;;;; 1441C;ANATOLIAN HIEROGLYPH A027;Lo;0;L;;;;;N;;;;; 1441D;ANATOLIAN HIEROGLYPH A028;Lo;0;L;;;;;N;;;;; 1441E;ANATOLIAN HIEROGLYPH A029;Lo;0;L;;;;;N;;;;; 1441F;ANATOLIAN HIEROGLYPH A030;Lo;0;L;;;;;N;;;;; 14420;ANATOLIAN HIEROGLYPH A031;Lo;0;L;;;;;N;;;;; 14421;ANATOLIAN HIEROGLYPH A032;Lo;0;L;;;;;N;;;;; 14422;ANATOLIAN HIEROGLYPH A033;Lo;0;L;;;;;N;;;;; 14423;ANATOLIAN HIEROGLYPH A034;Lo;0;L;;;;;N;;;;; 14424;ANATOLIAN HIEROGLYPH A035;Lo;0;L;;;;;N;;;;; 14425;ANATOLIAN HIEROGLYPH A036;Lo;0;L;;;;;N;;;;; 14426;ANATOLIAN HIEROGLYPH A037;Lo;0;L;;;;;N;;;;; 14427;ANATOLIAN HIEROGLYPH A038;Lo;0;L;;;;;N;;;;; 14428;ANATOLIAN HIEROGLYPH A039;Lo;0;L;;;;;N;;;;; 14429;ANATOLIAN HIEROGLYPH A039A;Lo;0;L;;;;;N;;;;; 1442A;ANATOLIAN HIEROGLYPH A040;Lo;0;L;;;;;N;;;;; 1442B;ANATOLIAN HIEROGLYPH A041;Lo;0;L;;;;;N;;;;; 1442C;ANATOLIAN HIEROGLYPH A041A;Lo;0;L;;;;;N;;;;; 1442D;ANATOLIAN HIEROGLYPH A042;Lo;0;L;;;;;N;;;;; 1442E;ANATOLIAN HIEROGLYPH A043;Lo;0;L;;;;;N;;;;; 1442F;ANATOLIAN HIEROGLYPH A044;Lo;0;L;;;;;N;;;;; 14430;ANATOLIAN HIEROGLYPH A045;Lo;0;L;;;;;N;;;;; 14431;ANATOLIAN HIEROGLYPH A045A;Lo;0;L;;;;;N;;;;; 14432;ANATOLIAN HIEROGLYPH A046;Lo;0;L;;;;;N;;;;; 14433;ANATOLIAN HIEROGLYPH A046A;Lo;0;L;;;;;N;;;;; 14434;ANATOLIAN HIEROGLYPH A046B;Lo;0;L;;;;;N;;;;; 14435;ANATOLIAN HIEROGLYPH A047;Lo;0;L;;;;;N;;;;; 14436;ANATOLIAN HIEROGLYPH A048;Lo;0;L;;;;;N;;;;; 14437;ANATOLIAN HIEROGLYPH A049;Lo;0;L;;;;;N;;;;; 14438;ANATOLIAN HIEROGLYPH A050;Lo;0;L;;;;;N;;;;; 14439;ANATOLIAN HIEROGLYPH A051;Lo;0;L;;;;;N;;;;; 1443A;ANATOLIAN HIEROGLYPH A052;Lo;0;L;;;;;N;;;;; 1443B;ANATOLIAN HIEROGLYPH A053;Lo;0;L;;;;;N;;;;; 1443C;ANATOLIAN HIEROGLYPH A054;Lo;0;L;;;;;N;;;;; 1443D;ANATOLIAN HIEROGLYPH A055;Lo;0;L;;;;;N;;;;; 1443E;ANATOLIAN HIEROGLYPH A056;Lo;0;L;;;;;N;;;;; 1443F;ANATOLIAN HIEROGLYPH A057;Lo;0;L;;;;;N;;;;; 14440;ANATOLIAN HIEROGLYPH A058;Lo;0;L;;;;;N;;;;; 14441;ANATOLIAN HIEROGLYPH A059;Lo;0;L;;;;;N;;;;; 14442;ANATOLIAN HIEROGLYPH A060;Lo;0;L;;;;;N;;;;; 14443;ANATOLIAN HIEROGLYPH A061;Lo;0;L;;;;;N;;;;; 14444;ANATOLIAN HIEROGLYPH A062;Lo;0;L;;;;;N;;;;; 14445;ANATOLIAN HIEROGLYPH A063;Lo;0;L;;;;;N;;;;; 14446;ANATOLIAN HIEROGLYPH A064;Lo;0;L;;;;;N;;;;; 14447;ANATOLIAN HIEROGLYPH A065;Lo;0;L;;;;;N;;;;; 14448;ANATOLIAN HIEROGLYPH A066;Lo;0;L;;;;;N;;;;; 14449;ANATOLIAN HIEROGLYPH A066A;Lo;0;L;;;;;N;;;;; 1444A;ANATOLIAN HIEROGLYPH A066B;Lo;0;L;;;;;N;;;;; 1444B;ANATOLIAN HIEROGLYPH A066C;Lo;0;L;;;;;N;;;;; 1444C;ANATOLIAN HIEROGLYPH A067;Lo;0;L;;;;;N;;;;; 1444D;ANATOLIAN HIEROGLYPH A068;Lo;0;L;;;;;N;;;;; 1444E;ANATOLIAN HIEROGLYPH A069;Lo;0;L;;;;;N;;;;; 1444F;ANATOLIAN HIEROGLYPH A070;Lo;0;L;;;;;N;;;;; 14450;ANATOLIAN HIEROGLYPH A071;Lo;0;L;;;;;N;;;;; 14451;ANATOLIAN HIEROGLYPH A072;Lo;0;L;;;;;N;;;;; 14452;ANATOLIAN HIEROGLYPH A073;Lo;0;L;;;;;N;;;;; 14453;ANATOLIAN HIEROGLYPH A074;Lo;0;L;;;;;N;;;;; 14454;ANATOLIAN HIEROGLYPH A075;Lo;0;L;;;;;N;;;;; 14455;ANATOLIAN HIEROGLYPH A076;Lo;0;L;;;;;N;;;;; 14456;ANATOLIAN HIEROGLYPH A077;Lo;0;L;;;;;N;;;;; 14457;ANATOLIAN HIEROGLYPH A078;Lo;0;L;;;;;N;;;;; 14458;ANATOLIAN HIEROGLYPH A079;Lo;0;L;;;;;N;;;;; 14459;ANATOLIAN HIEROGLYPH A080;Lo;0;L;;;;;N;;;;; 1445A;ANATOLIAN HIEROGLYPH A081;Lo;0;L;;;;;N;;;;; 1445B;ANATOLIAN HIEROGLYPH A082;Lo;0;L;;;;;N;;;;; 1445C;ANATOLIAN HIEROGLYPH A083;Lo;0;L;;;;;N;;;;; 1445D;ANATOLIAN HIEROGLYPH A084;Lo;0;L;;;;;N;;;;; 1445E;ANATOLIAN HIEROGLYPH A085;Lo;0;L;;;;;N;;;;; 1445F;ANATOLIAN HIEROGLYPH A086;Lo;0;L;;;;;N;;;;; 14460;ANATOLIAN HIEROGLYPH A087;Lo;0;L;;;;;N;;;;; 14461;ANATOLIAN HIEROGLYPH A088;Lo;0;L;;;;;N;;;;; 14462;ANATOLIAN HIEROGLYPH A089;Lo;0;L;;;;;N;;;;; 14463;ANATOLIAN HIEROGLYPH A090;Lo;0;L;;;;;N;;;;; 14464;ANATOLIAN HIEROGLYPH A091;Lo;0;L;;;;;N;;;;; 14465;ANATOLIAN HIEROGLYPH A092;Lo;0;L;;;;;N;;;;; 14466;ANATOLIAN HIEROGLYPH A093;Lo;0;L;;;;;N;;;;; 14467;ANATOLIAN HIEROGLYPH A094;Lo;0;L;;;;;N;;;;; 14468;ANATOLIAN HIEROGLYPH A095;Lo;0;L;;;;;N;;;;; 14469;ANATOLIAN HIEROGLYPH A096;Lo;0;L;;;;;N;;;;; 1446A;ANATOLIAN HIEROGLYPH A097;Lo;0;L;;;;;N;;;;; 1446B;ANATOLIAN HIEROGLYPH A097A;Lo;0;L;;;;;N;;;;; 1446C;ANATOLIAN HIEROGLYPH A098;Lo;0;L;;;;;N;;;;; 1446D;ANATOLIAN HIEROGLYPH A098A;Lo;0;L;;;;;N;;;;; 1446E;ANATOLIAN HIEROGLYPH A099;Lo;0;L;;;;;N;;;;; 1446F;ANATOLIAN HIEROGLYPH A100;Lo;0;L;;;;;N;;;;; 14470;ANATOLIAN HIEROGLYPH A100A;Lo;0;L;;;;;N;;;;; 14471;ANATOLIAN HIEROGLYPH A101;Lo;0;L;;;;;N;;;;; 14472;ANATOLIAN HIEROGLYPH A101A;Lo;0;L;;;;;N;;;;; 14473;ANATOLIAN HIEROGLYPH A102;Lo;0;L;;;;;N;;;;; 14474;ANATOLIAN HIEROGLYPH A102A;Lo;0;L;;;;;N;;;;; 14475;ANATOLIAN HIEROGLYPH A103;Lo;0;L;;;;;N;;;;; 14476;ANATOLIAN HIEROGLYPH A104;Lo;0;L;;;;;N;;;;; 14477;ANATOLIAN HIEROGLYPH A104A;Lo;0;L;;;;;N;;;;; 14478;ANATOLIAN HIEROGLYPH A104B;Lo;0;L;;;;;N;;;;; 14479;ANATOLIAN HIEROGLYPH A104C;Lo;0;L;;;;;N;;;;; 1447A;ANATOLIAN HIEROGLYPH A105;Lo;0;L;;;;;N;;;;; 1447B;ANATOLIAN HIEROGLYPH A105A;Lo;0;L;;;;;N;;;;; 1447C;ANATOLIAN HIEROGLYPH A105B;Lo;0;L;;;;;N;;;;; 1447D;ANATOLIAN HIEROGLYPH A106;Lo;0;L;;;;;N;;;;; 1447E;ANATOLIAN HIEROGLYPH A107;Lo;0;L;;;;;N;;;;; 1447F;ANATOLIAN HIEROGLYPH A107A;Lo;0;L;;;;;N;;;;; 14480;ANATOLIAN HIEROGLYPH A107B;Lo;0;L;;;;;N;;;;; 14481;ANATOLIAN HIEROGLYPH A107C;Lo;0;L;;;;;N;;;;; 14482;ANATOLIAN HIEROGLYPH A108;Lo;0;L;;;;;N;;;;; 14483;ANATOLIAN HIEROGLYPH A109;Lo;0;L;;;;;N;;;;; 14484;ANATOLIAN HIEROGLYPH A110;Lo;0;L;;;;;N;;;;; 14485;ANATOLIAN HIEROGLYPH A110A;Lo;0;L;;;;;N;;;;; 14486;ANATOLIAN HIEROGLYPH A110B;Lo;0;L;;;;;N;;;;; 14487;ANATOLIAN HIEROGLYPH A111;Lo;0;L;;;;;N;;;;; 14488;ANATOLIAN HIEROGLYPH A112;Lo;0;L;;;;;N;;;;; 14489;ANATOLIAN HIEROGLYPH A113;Lo;0;L;;;;;N;;;;; 1448A;ANATOLIAN HIEROGLYPH A114;Lo;0;L;;;;;N;;;;; 1448B;ANATOLIAN HIEROGLYPH A115;Lo;0;L;;;;;N;;;;; 1448C;ANATOLIAN HIEROGLYPH A115A;Lo;0;L;;;;;N;;;;; 1448D;ANATOLIAN HIEROGLYPH A116;Lo;0;L;;;;;N;;;;; 1448E;ANATOLIAN HIEROGLYPH A117;Lo;0;L;;;;;N;;;;; 1448F;ANATOLIAN HIEROGLYPH A118;Lo;0;L;;;;;N;;;;; 14490;ANATOLIAN HIEROGLYPH A119;Lo;0;L;;;;;N;;;;; 14491;ANATOLIAN HIEROGLYPH A120;Lo;0;L;;;;;N;;;;; 14492;ANATOLIAN HIEROGLYPH A121;Lo;0;L;;;;;N;;;;; 14493;ANATOLIAN HIEROGLYPH A122;Lo;0;L;;;;;N;;;;; 14494;ANATOLIAN HIEROGLYPH A123;Lo;0;L;;;;;N;;;;; 14495;ANATOLIAN HIEROGLYPH A124;Lo;0;L;;;;;N;;;;; 14496;ANATOLIAN HIEROGLYPH A125;Lo;0;L;;;;;N;;;;; 14497;ANATOLIAN HIEROGLYPH A125A;Lo;0;L;;;;;N;;;;; 14498;ANATOLIAN HIEROGLYPH A126;Lo;0;L;;;;;N;;;;; 14499;ANATOLIAN HIEROGLYPH A127;Lo;0;L;;;;;N;;;;; 1449A;ANATOLIAN HIEROGLYPH A128;Lo;0;L;;;;;N;;;;; 1449B;ANATOLIAN HIEROGLYPH A129;Lo;0;L;;;;;N;;;;; 1449C;ANATOLIAN HIEROGLYPH A130;Lo;0;L;;;;;N;;;;; 1449D;ANATOLIAN HIEROGLYPH A131;Lo;0;L;;;;;N;;;;; 1449E;ANATOLIAN HIEROGLYPH A132;Lo;0;L;;;;;N;;;;; 1449F;ANATOLIAN HIEROGLYPH A133;Lo;0;L;;;;;N;;;;; 144A0;ANATOLIAN HIEROGLYPH A134;Lo;0;L;;;;;N;;;;; 144A1;ANATOLIAN HIEROGLYPH A135;Lo;0;L;;;;;N;;;;; 144A2;ANATOLIAN HIEROGLYPH A135A;Lo;0;L;;;;;N;;;;; 144A3;ANATOLIAN HIEROGLYPH A136;Lo;0;L;;;;;N;;;;; 144A4;ANATOLIAN HIEROGLYPH A137;Lo;0;L;;;;;N;;;;; 144A5;ANATOLIAN HIEROGLYPH A138;Lo;0;L;;;;;N;;;;; 144A6;ANATOLIAN HIEROGLYPH A139;Lo;0;L;;;;;N;;;;; 144A7;ANATOLIAN HIEROGLYPH A140;Lo;0;L;;;;;N;;;;; 144A8;ANATOLIAN HIEROGLYPH A141;Lo;0;L;;;;;N;;;;; 144A9;ANATOLIAN HIEROGLYPH A142;Lo;0;L;;;;;N;;;;; 144AA;ANATOLIAN HIEROGLYPH A143;Lo;0;L;;;;;N;;;;; 144AB;ANATOLIAN HIEROGLYPH A144;Lo;0;L;;;;;N;;;;; 144AC;ANATOLIAN HIEROGLYPH A145;Lo;0;L;;;;;N;;;;; 144AD;ANATOLIAN HIEROGLYPH A146;Lo;0;L;;;;;N;;;;; 144AE;ANATOLIAN HIEROGLYPH A147;Lo;0;L;;;;;N;;;;; 144AF;ANATOLIAN HIEROGLYPH A148;Lo;0;L;;;;;N;;;;; 144B0;ANATOLIAN HIEROGLYPH A149;Lo;0;L;;;;;N;;;;; 144B1;ANATOLIAN HIEROGLYPH A150;Lo;0;L;;;;;N;;;;; 144B2;ANATOLIAN HIEROGLYPH A151;Lo;0;L;;;;;N;;;;; 144B3;ANATOLIAN HIEROGLYPH A152;Lo;0;L;;;;;N;;;;; 144B4;ANATOLIAN HIEROGLYPH A153;Lo;0;L;;;;;N;;;;; 144B5;ANATOLIAN HIEROGLYPH A154;Lo;0;L;;;;;N;;;;; 144B6;ANATOLIAN HIEROGLYPH A155;Lo;0;L;;;;;N;;;;; 144B7;ANATOLIAN HIEROGLYPH A156;Lo;0;L;;;;;N;;;;; 144B8;ANATOLIAN HIEROGLYPH A157;Lo;0;L;;;;;N;;;;; 144B9;ANATOLIAN HIEROGLYPH A158;Lo;0;L;;;;;N;;;;; 144BA;ANATOLIAN HIEROGLYPH A159;Lo;0;L;;;;;N;;;;; 144BB;ANATOLIAN HIEROGLYPH A160;Lo;0;L;;;;;N;;;;; 144BC;ANATOLIAN HIEROGLYPH A161;Lo;0;L;;;;;N;;;;; 144BD;ANATOLIAN HIEROGLYPH A162;Lo;0;L;;;;;N;;;;; 144BE;ANATOLIAN HIEROGLYPH A163;Lo;0;L;;;;;N;;;;; 144BF;ANATOLIAN HIEROGLYPH A164;Lo;0;L;;;;;N;;;;; 144C0;ANATOLIAN HIEROGLYPH A165;Lo;0;L;;;;;N;;;;; 144C1;ANATOLIAN HIEROGLYPH A166;Lo;0;L;;;;;N;;;;; 144C2;ANATOLIAN HIEROGLYPH A167;Lo;0;L;;;;;N;;;;; 144C3;ANATOLIAN HIEROGLYPH A168;Lo;0;L;;;;;N;;;;; 144C4;ANATOLIAN HIEROGLYPH A169;Lo;0;L;;;;;N;;;;; 144C5;ANATOLIAN HIEROGLYPH A170;Lo;0;L;;;;;N;;;;; 144C6;ANATOLIAN HIEROGLYPH A171;Lo;0;L;;;;;N;;;;; 144C7;ANATOLIAN HIEROGLYPH A172;Lo;0;L;;;;;N;;;;; 144C8;ANATOLIAN HIEROGLYPH A173;Lo;0;L;;;;;N;;;;; 144C9;ANATOLIAN HIEROGLYPH A174;Lo;0;L;;;;;N;;;;; 144CA;ANATOLIAN HIEROGLYPH A175;Lo;0;L;;;;;N;;;;; 144CB;ANATOLIAN HIEROGLYPH A176;Lo;0;L;;;;;N;;;;; 144CC;ANATOLIAN HIEROGLYPH A177;Lo;0;L;;;;;N;;;;; 144CD;ANATOLIAN HIEROGLYPH A178;Lo;0;L;;;;;N;;;;; 144CE;ANATOLIAN HIEROGLYPH A179;Lo;0;L;;;;;N;;;;; 144CF;ANATOLIAN HIEROGLYPH A180;Lo;0;L;;;;;N;;;;; 144D0;ANATOLIAN HIEROGLYPH A181;Lo;0;L;;;;;N;;;;; 144D1;ANATOLIAN HIEROGLYPH A182;Lo;0;L;;;;;N;;;;; 144D2;ANATOLIAN HIEROGLYPH A183;Lo;0;L;;;;;N;;;;; 144D3;ANATOLIAN HIEROGLYPH A184;Lo;0;L;;;;;N;;;;; 144D4;ANATOLIAN HIEROGLYPH A185;Lo;0;L;;;;;N;;;;; 144D5;ANATOLIAN HIEROGLYPH A186;Lo;0;L;;;;;N;;;;; 144D6;ANATOLIAN HIEROGLYPH A187;Lo;0;L;;;;;N;;;;; 144D7;ANATOLIAN HIEROGLYPH A188;Lo;0;L;;;;;N;;;;; 144D8;ANATOLIAN HIEROGLYPH A189;Lo;0;L;;;;;N;;;;; 144D9;ANATOLIAN HIEROGLYPH A190;Lo;0;L;;;;;N;;;;; 144DA;ANATOLIAN HIEROGLYPH A191;Lo;0;L;;;;;N;;;;; 144DB;ANATOLIAN HIEROGLYPH A192;Lo;0;L;;;;;N;;;;; 144DC;ANATOLIAN HIEROGLYPH A193;Lo;0;L;;;;;N;;;;; 144DD;ANATOLIAN HIEROGLYPH A194;Lo;0;L;;;;;N;;;;; 144DE;ANATOLIAN HIEROGLYPH A195;Lo;0;L;;;;;N;;;;; 144DF;ANATOLIAN HIEROGLYPH A196;Lo;0;L;;;;;N;;;;; 144E0;ANATOLIAN HIEROGLYPH A197;Lo;0;L;;;;;N;;;;; 144E1;ANATOLIAN HIEROGLYPH A198;Lo;0;L;;;;;N;;;;; 144E2;ANATOLIAN HIEROGLYPH A199;Lo;0;L;;;;;N;;;;; 144E3;ANATOLIAN HIEROGLYPH A200;Lo;0;L;;;;;N;;;;; 144E4;ANATOLIAN HIEROGLYPH A201;Lo;0;L;;;;;N;;;;; 144E5;ANATOLIAN HIEROGLYPH A202;Lo;0;L;;;;;N;;;;; 144E6;ANATOLIAN HIEROGLYPH A202A;Lo;0;L;;;;;N;;;;; 144E7;ANATOLIAN HIEROGLYPH A202B;Lo;0;L;;;;;N;;;;; 144E8;ANATOLIAN HIEROGLYPH A203;Lo;0;L;;;;;N;;;;; 144E9;ANATOLIAN HIEROGLYPH A204;Lo;0;L;;;;;N;;;;; 144EA;ANATOLIAN HIEROGLYPH A205;Lo;0;L;;;;;N;;;;; 144EB;ANATOLIAN HIEROGLYPH A206;Lo;0;L;;;;;N;;;;; 144EC;ANATOLIAN HIEROGLYPH A207;Lo;0;L;;;;;N;;;;; 144ED;ANATOLIAN HIEROGLYPH A207A;Lo;0;L;;;;;N;;;;; 144EE;ANATOLIAN HIEROGLYPH A208;Lo;0;L;;;;;N;;;;; 144EF;ANATOLIAN HIEROGLYPH A209;Lo;0;L;;;;;N;;;;; 144F0;ANATOLIAN HIEROGLYPH A209A;Lo;0;L;;;;;N;;;;; 144F1;ANATOLIAN HIEROGLYPH A210;Lo;0;L;;;;;N;;;;; 144F2;ANATOLIAN HIEROGLYPH A211;Lo;0;L;;;;;N;;;;; 144F3;ANATOLIAN HIEROGLYPH A212;Lo;0;L;;;;;N;;;;; 144F4;ANATOLIAN HIEROGLYPH A213;Lo;0;L;;;;;N;;;;; 144F5;ANATOLIAN HIEROGLYPH A214;Lo;0;L;;;;;N;;;;; 144F6;ANATOLIAN HIEROGLYPH A215;Lo;0;L;;;;;N;;;;; 144F7;ANATOLIAN HIEROGLYPH A215A;Lo;0;L;;;;;N;;;;; 144F8;ANATOLIAN HIEROGLYPH A216;Lo;0;L;;;;;N;;;;; 144F9;ANATOLIAN HIEROGLYPH A216A;Lo;0;L;;;;;N;;;;; 144FA;ANATOLIAN HIEROGLYPH A217;Lo;0;L;;;;;N;;;;; 144FB;ANATOLIAN HIEROGLYPH A218;Lo;0;L;;;;;N;;;;; 144FC;ANATOLIAN HIEROGLYPH A219;Lo;0;L;;;;;N;;;;; 144FD;ANATOLIAN HIEROGLYPH A220;Lo;0;L;;;;;N;;;;; 144FE;ANATOLIAN HIEROGLYPH A221;Lo;0;L;;;;;N;;;;; 144FF;ANATOLIAN HIEROGLYPH A222;Lo;0;L;;;;;N;;;;; 14500;ANATOLIAN HIEROGLYPH A223;Lo;0;L;;;;;N;;;;; 14501;ANATOLIAN HIEROGLYPH A224;Lo;0;L;;;;;N;;;;; 14502;ANATOLIAN HIEROGLYPH A225;Lo;0;L;;;;;N;;;;; 14503;ANATOLIAN HIEROGLYPH A226;Lo;0;L;;;;;N;;;;; 14504;ANATOLIAN HIEROGLYPH A227;Lo;0;L;;;;;N;;;;; 14505;ANATOLIAN HIEROGLYPH A227A;Lo;0;L;;;;;N;;;;; 14506;ANATOLIAN HIEROGLYPH A228;Lo;0;L;;;;;N;;;;; 14507;ANATOLIAN HIEROGLYPH A229;Lo;0;L;;;;;N;;;;; 14508;ANATOLIAN HIEROGLYPH A230;Lo;0;L;;;;;N;;;;; 14509;ANATOLIAN HIEROGLYPH A231;Lo;0;L;;;;;N;;;;; 1450A;ANATOLIAN HIEROGLYPH A232;Lo;0;L;;;;;N;;;;; 1450B;ANATOLIAN HIEROGLYPH A233;Lo;0;L;;;;;N;;;;; 1450C;ANATOLIAN HIEROGLYPH A234;Lo;0;L;;;;;N;;;;; 1450D;ANATOLIAN HIEROGLYPH A235;Lo;0;L;;;;;N;;;;; 1450E;ANATOLIAN HIEROGLYPH A236;Lo;0;L;;;;;N;;;;; 1450F;ANATOLIAN HIEROGLYPH A237;Lo;0;L;;;;;N;;;;; 14510;ANATOLIAN HIEROGLYPH A238;Lo;0;L;;;;;N;;;;; 14511;ANATOLIAN HIEROGLYPH A239;Lo;0;L;;;;;N;;;;; 14512;ANATOLIAN HIEROGLYPH A240;Lo;0;L;;;;;N;;;;; 14513;ANATOLIAN HIEROGLYPH A241;Lo;0;L;;;;;N;;;;; 14514;ANATOLIAN HIEROGLYPH A242;Lo;0;L;;;;;N;;;;; 14515;ANATOLIAN HIEROGLYPH A243;Lo;0;L;;;;;N;;;;; 14516;ANATOLIAN HIEROGLYPH A244;Lo;0;L;;;;;N;;;;; 14517;ANATOLIAN HIEROGLYPH A245;Lo;0;L;;;;;N;;;;; 14518;ANATOLIAN HIEROGLYPH A246;Lo;0;L;;;;;N;;;;; 14519;ANATOLIAN HIEROGLYPH A247;Lo;0;L;;;;;N;;;;; 1451A;ANATOLIAN HIEROGLYPH A248;Lo;0;L;;;;;N;;;;; 1451B;ANATOLIAN HIEROGLYPH A249;Lo;0;L;;;;;N;;;;; 1451C;ANATOLIAN HIEROGLYPH A250;Lo;0;L;;;;;N;;;;; 1451D;ANATOLIAN HIEROGLYPH A251;Lo;0;L;;;;;N;;;;; 1451E;ANATOLIAN HIEROGLYPH A252;Lo;0;L;;;;;N;;;;; 1451F;ANATOLIAN HIEROGLYPH A253;Lo;0;L;;;;;N;;;;; 14520;ANATOLIAN HIEROGLYPH A254;Lo;0;L;;;;;N;;;;; 14521;ANATOLIAN HIEROGLYPH A255;Lo;0;L;;;;;N;;;;; 14522;ANATOLIAN HIEROGLYPH A256;Lo;0;L;;;;;N;;;;; 14523;ANATOLIAN HIEROGLYPH A257;Lo;0;L;;;;;N;;;;; 14524;ANATOLIAN HIEROGLYPH A258;Lo;0;L;;;;;N;;;;; 14525;ANATOLIAN HIEROGLYPH A259;Lo;0;L;;;;;N;;;;; 14526;ANATOLIAN HIEROGLYPH A260;Lo;0;L;;;;;N;;;;; 14527;ANATOLIAN HIEROGLYPH A261;Lo;0;L;;;;;N;;;;; 14528;ANATOLIAN HIEROGLYPH A262;Lo;0;L;;;;;N;;;;; 14529;ANATOLIAN HIEROGLYPH A263;Lo;0;L;;;;;N;;;;; 1452A;ANATOLIAN HIEROGLYPH A264;Lo;0;L;;;;;N;;;;; 1452B;ANATOLIAN HIEROGLYPH A265;Lo;0;L;;;;;N;;;;; 1452C;ANATOLIAN HIEROGLYPH A266;Lo;0;L;;;;;N;;;;; 1452D;ANATOLIAN HIEROGLYPH A267;Lo;0;L;;;;;N;;;;; 1452E;ANATOLIAN HIEROGLYPH A267A;Lo;0;L;;;;;N;;;;; 1452F;ANATOLIAN HIEROGLYPH A268;Lo;0;L;;;;;N;;;;; 14530;ANATOLIAN HIEROGLYPH A269;Lo;0;L;;;;;N;;;;; 14531;ANATOLIAN HIEROGLYPH A270;Lo;0;L;;;;;N;;;;; 14532;ANATOLIAN HIEROGLYPH A271;Lo;0;L;;;;;N;;;;; 14533;ANATOLIAN HIEROGLYPH A272;Lo;0;L;;;;;N;;;;; 14534;ANATOLIAN HIEROGLYPH A273;Lo;0;L;;;;;N;;;;; 14535;ANATOLIAN HIEROGLYPH A274;Lo;0;L;;;;;N;;;;; 14536;ANATOLIAN HIEROGLYPH A275;Lo;0;L;;;;;N;;;;; 14537;ANATOLIAN HIEROGLYPH A276;Lo;0;L;;;;;N;;;;; 14538;ANATOLIAN HIEROGLYPH A277;Lo;0;L;;;;;N;;;;; 14539;ANATOLIAN HIEROGLYPH A278;Lo;0;L;;;;;N;;;;; 1453A;ANATOLIAN HIEROGLYPH A279;Lo;0;L;;;;;N;;;;; 1453B;ANATOLIAN HIEROGLYPH A280;Lo;0;L;;;;;N;;;;; 1453C;ANATOLIAN HIEROGLYPH A281;Lo;0;L;;;;;N;;;;; 1453D;ANATOLIAN HIEROGLYPH A282;Lo;0;L;;;;;N;;;;; 1453E;ANATOLIAN HIEROGLYPH A283;Lo;0;L;;;;;N;;;;; 1453F;ANATOLIAN HIEROGLYPH A284;Lo;0;L;;;;;N;;;;; 14540;ANATOLIAN HIEROGLYPH A285;Lo;0;L;;;;;N;;;;; 14541;ANATOLIAN HIEROGLYPH A286;Lo;0;L;;;;;N;;;;; 14542;ANATOLIAN HIEROGLYPH A287;Lo;0;L;;;;;N;;;;; 14543;ANATOLIAN HIEROGLYPH A288;Lo;0;L;;;;;N;;;;; 14544;ANATOLIAN HIEROGLYPH A289;Lo;0;L;;;;;N;;;;; 14545;ANATOLIAN HIEROGLYPH A289A;Lo;0;L;;;;;N;;;;; 14546;ANATOLIAN HIEROGLYPH A290;Lo;0;L;;;;;N;;;;; 14547;ANATOLIAN HIEROGLYPH A291;Lo;0;L;;;;;N;;;;; 14548;ANATOLIAN HIEROGLYPH A292;Lo;0;L;;;;;N;;;;; 14549;ANATOLIAN HIEROGLYPH A293;Lo;0;L;;;;;N;;;;; 1454A;ANATOLIAN HIEROGLYPH A294;Lo;0;L;;;;;N;;;;; 1454B;ANATOLIAN HIEROGLYPH A294A;Lo;0;L;;;;;N;;;;; 1454C;ANATOLIAN HIEROGLYPH A295;Lo;0;L;;;;;N;;;;; 1454D;ANATOLIAN HIEROGLYPH A296;Lo;0;L;;;;;N;;;;; 1454E;ANATOLIAN HIEROGLYPH A297;Lo;0;L;;;;;N;;;;; 1454F;ANATOLIAN HIEROGLYPH A298;Lo;0;L;;;;;N;;;;; 14550;ANATOLIAN HIEROGLYPH A299;Lo;0;L;;;;;N;;;;; 14551;ANATOLIAN HIEROGLYPH A299A;Lo;0;L;;;;;N;;;;; 14552;ANATOLIAN HIEROGLYPH A300;Lo;0;L;;;;;N;;;;; 14553;ANATOLIAN HIEROGLYPH A301;Lo;0;L;;;;;N;;;;; 14554;ANATOLIAN HIEROGLYPH A302;Lo;0;L;;;;;N;;;;; 14555;ANATOLIAN HIEROGLYPH A303;Lo;0;L;;;;;N;;;;; 14556;ANATOLIAN HIEROGLYPH A304;Lo;0;L;;;;;N;;;;; 14557;ANATOLIAN HIEROGLYPH A305;Lo;0;L;;;;;N;;;;; 14558;ANATOLIAN HIEROGLYPH A306;Lo;0;L;;;;;N;;;;; 14559;ANATOLIAN HIEROGLYPH A307;Lo;0;L;;;;;N;;;;; 1455A;ANATOLIAN HIEROGLYPH A308;Lo;0;L;;;;;N;;;;; 1455B;ANATOLIAN HIEROGLYPH A309;Lo;0;L;;;;;N;;;;; 1455C;ANATOLIAN HIEROGLYPH A309A;Lo;0;L;;;;;N;;;;; 1455D;ANATOLIAN HIEROGLYPH A310;Lo;0;L;;;;;N;;;;; 1455E;ANATOLIAN HIEROGLYPH A311;Lo;0;L;;;;;N;;;;; 1455F;ANATOLIAN HIEROGLYPH A312;Lo;0;L;;;;;N;;;;; 14560;ANATOLIAN HIEROGLYPH A313;Lo;0;L;;;;;N;;;;; 14561;ANATOLIAN HIEROGLYPH A314;Lo;0;L;;;;;N;;;;; 14562;ANATOLIAN HIEROGLYPH A315;Lo;0;L;;;;;N;;;;; 14563;ANATOLIAN HIEROGLYPH A316;Lo;0;L;;;;;N;;;;; 14564;ANATOLIAN HIEROGLYPH A317;Lo;0;L;;;;;N;;;;; 14565;ANATOLIAN HIEROGLYPH A318;Lo;0;L;;;;;N;;;;; 14566;ANATOLIAN HIEROGLYPH A319;Lo;0;L;;;;;N;;;;; 14567;ANATOLIAN HIEROGLYPH A320;Lo;0;L;;;;;N;;;;; 14568;ANATOLIAN HIEROGLYPH A321;Lo;0;L;;;;;N;;;;; 14569;ANATOLIAN HIEROGLYPH A322;Lo;0;L;;;;;N;;;;; 1456A;ANATOLIAN HIEROGLYPH A323;Lo;0;L;;;;;N;;;;; 1456B;ANATOLIAN HIEROGLYPH A324;Lo;0;L;;;;;N;;;;; 1456C;ANATOLIAN HIEROGLYPH A325;Lo;0;L;;;;;N;;;;; 1456D;ANATOLIAN HIEROGLYPH A326;Lo;0;L;;;;;N;;;;; 1456E;ANATOLIAN HIEROGLYPH A327;Lo;0;L;;;;;N;;;;; 1456F;ANATOLIAN HIEROGLYPH A328;Lo;0;L;;;;;N;;;;; 14570;ANATOLIAN HIEROGLYPH A329;Lo;0;L;;;;;N;;;;; 14571;ANATOLIAN HIEROGLYPH A329A;Lo;0;L;;;;;N;;;;; 14572;ANATOLIAN HIEROGLYPH A330;Lo;0;L;;;;;N;;;;; 14573;ANATOLIAN HIEROGLYPH A331;Lo;0;L;;;;;N;;;;; 14574;ANATOLIAN HIEROGLYPH A332A;Lo;0;L;;;;;N;;;;; 14575;ANATOLIAN HIEROGLYPH A332B;Lo;0;L;;;;;N;;;;; 14576;ANATOLIAN HIEROGLYPH A332C;Lo;0;L;;;;;N;;;;; 14577;ANATOLIAN HIEROGLYPH A333;Lo;0;L;;;;;N;;;;; 14578;ANATOLIAN HIEROGLYPH A334;Lo;0;L;;;;;N;;;;; 14579;ANATOLIAN HIEROGLYPH A335;Lo;0;L;;;;;N;;;;; 1457A;ANATOLIAN HIEROGLYPH A336;Lo;0;L;;;;;N;;;;; 1457B;ANATOLIAN HIEROGLYPH A336A;Lo;0;L;;;;;N;;;;; 1457C;ANATOLIAN HIEROGLYPH A336B;Lo;0;L;;;;;N;;;;; 1457D;ANATOLIAN HIEROGLYPH A336C;Lo;0;L;;;;;N;;;;; 1457E;ANATOLIAN HIEROGLYPH A337;Lo;0;L;;;;;N;;;;; 1457F;ANATOLIAN HIEROGLYPH A338;Lo;0;L;;;;;N;;;;; 14580;ANATOLIAN HIEROGLYPH A339;Lo;0;L;;;;;N;;;;; 14581;ANATOLIAN HIEROGLYPH A340;Lo;0;L;;;;;N;;;;; 14582;ANATOLIAN HIEROGLYPH A341;Lo;0;L;;;;;N;;;;; 14583;ANATOLIAN HIEROGLYPH A342;Lo;0;L;;;;;N;;;;; 14584;ANATOLIAN HIEROGLYPH A343;Lo;0;L;;;;;N;;;;; 14585;ANATOLIAN HIEROGLYPH A344;Lo;0;L;;;;;N;;;;; 14586;ANATOLIAN HIEROGLYPH A345;Lo;0;L;;;;;N;;;;; 14587;ANATOLIAN HIEROGLYPH A346;Lo;0;L;;;;;N;;;;; 14588;ANATOLIAN HIEROGLYPH A347;Lo;0;L;;;;;N;;;;; 14589;ANATOLIAN HIEROGLYPH A348;Lo;0;L;;;;;N;;;;; 1458A;ANATOLIAN HIEROGLYPH A349;Lo;0;L;;;;;N;;;;; 1458B;ANATOLIAN HIEROGLYPH A350;Lo;0;L;;;;;N;;;;; 1458C;ANATOLIAN HIEROGLYPH A351;Lo;0;L;;;;;N;;;;; 1458D;ANATOLIAN HIEROGLYPH A352;Lo;0;L;;;;;N;;;;; 1458E;ANATOLIAN HIEROGLYPH A353;Lo;0;L;;;;;N;;;;; 1458F;ANATOLIAN HIEROGLYPH A354;Lo;0;L;;;;;N;;;;; 14590;ANATOLIAN HIEROGLYPH A355;Lo;0;L;;;;;N;;;;; 14591;ANATOLIAN HIEROGLYPH A356;Lo;0;L;;;;;N;;;;; 14592;ANATOLIAN HIEROGLYPH A357;Lo;0;L;;;;;N;;;;; 14593;ANATOLIAN HIEROGLYPH A358;Lo;0;L;;;;;N;;;;; 14594;ANATOLIAN HIEROGLYPH A359;Lo;0;L;;;;;N;;;;; 14595;ANATOLIAN HIEROGLYPH A359A;Lo;0;L;;;;;N;;;;; 14596;ANATOLIAN HIEROGLYPH A360;Lo;0;L;;;;;N;;;;; 14597;ANATOLIAN HIEROGLYPH A361;Lo;0;L;;;;;N;;;;; 14598;ANATOLIAN HIEROGLYPH A362;Lo;0;L;;;;;N;;;;; 14599;ANATOLIAN HIEROGLYPH A363;Lo;0;L;;;;;N;;;;; 1459A;ANATOLIAN HIEROGLYPH A364;Lo;0;L;;;;;N;;;;; 1459B;ANATOLIAN HIEROGLYPH A364A;Lo;0;L;;;;;N;;;;; 1459C;ANATOLIAN HIEROGLYPH A365;Lo;0;L;;;;;N;;;;; 1459D;ANATOLIAN HIEROGLYPH A366;Lo;0;L;;;;;N;;;;; 1459E;ANATOLIAN HIEROGLYPH A367;Lo;0;L;;;;;N;;;;; 1459F;ANATOLIAN HIEROGLYPH A368;Lo;0;L;;;;;N;;;;; 145A0;ANATOLIAN HIEROGLYPH A368A;Lo;0;L;;;;;N;;;;; 145A1;ANATOLIAN HIEROGLYPH A369;Lo;0;L;;;;;N;;;;; 145A2;ANATOLIAN HIEROGLYPH A370;Lo;0;L;;;;;N;;;;; 145A3;ANATOLIAN HIEROGLYPH A371;Lo;0;L;;;;;N;;;;; 145A4;ANATOLIAN HIEROGLYPH A371A;Lo;0;L;;;;;N;;;;; 145A5;ANATOLIAN HIEROGLYPH A372;Lo;0;L;;;;;N;;;;; 145A6;ANATOLIAN HIEROGLYPH A373;Lo;0;L;;;;;N;;;;; 145A7;ANATOLIAN HIEROGLYPH A374;Lo;0;L;;;;;N;;;;; 145A8;ANATOLIAN HIEROGLYPH A375;Lo;0;L;;;;;N;;;;; 145A9;ANATOLIAN HIEROGLYPH A376;Lo;0;L;;;;;N;;;;; 145AA;ANATOLIAN HIEROGLYPH A377;Lo;0;L;;;;;N;;;;; 145AB;ANATOLIAN HIEROGLYPH A378;Lo;0;L;;;;;N;;;;; 145AC;ANATOLIAN HIEROGLYPH A379;Lo;0;L;;;;;N;;;;; 145AD;ANATOLIAN HIEROGLYPH A380;Lo;0;L;;;;;N;;;;; 145AE;ANATOLIAN HIEROGLYPH A381;Lo;0;L;;;;;N;;;;; 145AF;ANATOLIAN HIEROGLYPH A381A;Lo;0;L;;;;;N;;;;; 145B0;ANATOLIAN HIEROGLYPH A382;Lo;0;L;;;;;N;;;;; 145B1;ANATOLIAN HIEROGLYPH A383 RA OR RI;Lo;0;L;;;;;N;;;;; 145B2;ANATOLIAN HIEROGLYPH A383A;Lo;0;L;;;;;N;;;;; 145B3;ANATOLIAN HIEROGLYPH A384;Lo;0;L;;;;;N;;;;; 145B4;ANATOLIAN HIEROGLYPH A385;Lo;0;L;;;;;N;;;;; 145B5;ANATOLIAN HIEROGLYPH A386;Lo;0;L;;;;;N;;;;; 145B6;ANATOLIAN HIEROGLYPH A386A;Lo;0;L;;;;;N;;;;; 145B7;ANATOLIAN HIEROGLYPH A387;Lo;0;L;;;;;N;;;;; 145B8;ANATOLIAN HIEROGLYPH A388;Lo;0;L;;;;;N;;;;; 145B9;ANATOLIAN HIEROGLYPH A389;Lo;0;L;;;;;N;;;;; 145BA;ANATOLIAN HIEROGLYPH A390;Lo;0;L;;;;;N;;;;; 145BB;ANATOLIAN HIEROGLYPH A391;Lo;0;L;;;;;N;;;;; 145BC;ANATOLIAN HIEROGLYPH A392;Lo;0;L;;;;;N;;;;; 145BD;ANATOLIAN HIEROGLYPH A393 EIGHT;Lo;0;L;;;;;N;;;;; 145BE;ANATOLIAN HIEROGLYPH A394;Lo;0;L;;;;;N;;;;; 145BF;ANATOLIAN HIEROGLYPH A395;Lo;0;L;;;;;N;;;;; 145C0;ANATOLIAN HIEROGLYPH A396;Lo;0;L;;;;;N;;;;; 145C1;ANATOLIAN HIEROGLYPH A397;Lo;0;L;;;;;N;;;;; 145C2;ANATOLIAN HIEROGLYPH A398;Lo;0;L;;;;;N;;;;; 145C3;ANATOLIAN HIEROGLYPH A399;Lo;0;L;;;;;N;;;;; 145C4;ANATOLIAN HIEROGLYPH A400;Lo;0;L;;;;;N;;;;; 145C5;ANATOLIAN HIEROGLYPH A401;Lo;0;L;;;;;N;;;;; 145C6;ANATOLIAN HIEROGLYPH A402;Lo;0;L;;;;;N;;;;; 145C7;ANATOLIAN HIEROGLYPH A403;Lo;0;L;;;;;N;;;;; 145C8;ANATOLIAN HIEROGLYPH A404;Lo;0;L;;;;;N;;;;; 145C9;ANATOLIAN HIEROGLYPH A405;Lo;0;L;;;;;N;;;;; 145CA;ANATOLIAN HIEROGLYPH A406;Lo;0;L;;;;;N;;;;; 145CB;ANATOLIAN HIEROGLYPH A407;Lo;0;L;;;;;N;;;;; 145CC;ANATOLIAN HIEROGLYPH A408;Lo;0;L;;;;;N;;;;; 145CD;ANATOLIAN HIEROGLYPH A409;Lo;0;L;;;;;N;;;;; 145CE;ANATOLIAN HIEROGLYPH A410 BEGIN LOGOGRAM MARK;Lo;0;L;;;;;N;;;;; 145CF;ANATOLIAN HIEROGLYPH A410A END LOGOGRAM MARK;Lo;0;L;;;;;N;;;;; 145D0;ANATOLIAN HIEROGLYPH A411;Lo;0;L;;;;;N;;;;; 145D1;ANATOLIAN HIEROGLYPH A412;Lo;0;L;;;;;N;;;;; 145D2;ANATOLIAN HIEROGLYPH A413;Lo;0;L;;;;;N;;;;; 145D3;ANATOLIAN HIEROGLYPH A414;Lo;0;L;;;;;N;;;;; 145D4;ANATOLIAN HIEROGLYPH A415;Lo;0;L;;;;;N;;;;; 145D5;ANATOLIAN HIEROGLYPH A416;Lo;0;L;;;;;N;;;;; 145D6;ANATOLIAN HIEROGLYPH A417;Lo;0;L;;;;;N;;;;; 145D7;ANATOLIAN HIEROGLYPH A418;Lo;0;L;;;;;N;;;;; 145D8;ANATOLIAN HIEROGLYPH A419;Lo;0;L;;;;;N;;;;; 145D9;ANATOLIAN HIEROGLYPH A420;Lo;0;L;;;;;N;;;;; 145DA;ANATOLIAN HIEROGLYPH A421;Lo;0;L;;;;;N;;;;; 145DB;ANATOLIAN HIEROGLYPH A422;Lo;0;L;;;;;N;;;;; 145DC;ANATOLIAN HIEROGLYPH A423;Lo;0;L;;;;;N;;;;; 145DD;ANATOLIAN HIEROGLYPH A424;Lo;0;L;;;;;N;;;;; 145DE;ANATOLIAN HIEROGLYPH A425;Lo;0;L;;;;;N;;;;; 145DF;ANATOLIAN HIEROGLYPH A426;Lo;0;L;;;;;N;;;;; 145E0;ANATOLIAN HIEROGLYPH A427;Lo;0;L;;;;;N;;;;; 145E1;ANATOLIAN HIEROGLYPH A428;Lo;0;L;;;;;N;;;;; 145E2;ANATOLIAN HIEROGLYPH A429;Lo;0;L;;;;;N;;;;; 145E3;ANATOLIAN HIEROGLYPH A430;Lo;0;L;;;;;N;;;;; 145E4;ANATOLIAN HIEROGLYPH A431;Lo;0;L;;;;;N;;;;; 145E5;ANATOLIAN HIEROGLYPH A432;Lo;0;L;;;;;N;;;;; 145E6;ANATOLIAN HIEROGLYPH A433;Lo;0;L;;;;;N;;;;; 145E7;ANATOLIAN HIEROGLYPH A434;Lo;0;L;;;;;N;;;;; 145E8;ANATOLIAN HIEROGLYPH A435;Lo;0;L;;;;;N;;;;; 145E9;ANATOLIAN HIEROGLYPH A436;Lo;0;L;;;;;N;;;;; 145EA;ANATOLIAN HIEROGLYPH A437;Lo;0;L;;;;;N;;;;; 145EB;ANATOLIAN HIEROGLYPH A438;Lo;0;L;;;;;N;;;;; 145EC;ANATOLIAN HIEROGLYPH A439;Lo;0;L;;;;;N;;;;; 145ED;ANATOLIAN HIEROGLYPH A440;Lo;0;L;;;;;N;;;;; 145EE;ANATOLIAN HIEROGLYPH A441;Lo;0;L;;;;;N;;;;; 145EF;ANATOLIAN HIEROGLYPH A442;Lo;0;L;;;;;N;;;;; 145F0;ANATOLIAN HIEROGLYPH A443;Lo;0;L;;;;;N;;;;; 145F1;ANATOLIAN HIEROGLYPH A444;Lo;0;L;;;;;N;;;;; 145F2;ANATOLIAN HIEROGLYPH A445;Lo;0;L;;;;;N;;;;; 145F3;ANATOLIAN HIEROGLYPH A446;Lo;0;L;;;;;N;;;;; 145F4;ANATOLIAN HIEROGLYPH A447;Lo;0;L;;;;;N;;;;; 145F5;ANATOLIAN HIEROGLYPH A448;Lo;0;L;;;;;N;;;;; 145F6;ANATOLIAN HIEROGLYPH A449;Lo;0;L;;;;;N;;;;; 145F7;ANATOLIAN HIEROGLYPH A450;Lo;0;L;;;;;N;;;;; 145F8;ANATOLIAN HIEROGLYPH A450A;Lo;0;L;;;;;N;;;;; 145F9;ANATOLIAN HIEROGLYPH A451;Lo;0;L;;;;;N;;;;; 145FA;ANATOLIAN HIEROGLYPH A452;Lo;0;L;;;;;N;;;;; 145FB;ANATOLIAN HIEROGLYPH A453;Lo;0;L;;;;;N;;;;; 145FC;ANATOLIAN HIEROGLYPH A454;Lo;0;L;;;;;N;;;;; 145FD;ANATOLIAN HIEROGLYPH A455;Lo;0;L;;;;;N;;;;; 145FE;ANATOLIAN HIEROGLYPH A456;Lo;0;L;;;;;N;;;;; 145FF;ANATOLIAN HIEROGLYPH A457;Lo;0;L;;;;;N;;;;; 14600;ANATOLIAN HIEROGLYPH A457A;Lo;0;L;;;;;N;;;;; 14601;ANATOLIAN HIEROGLYPH A458;Lo;0;L;;;;;N;;;;; 14602;ANATOLIAN HIEROGLYPH A459;Lo;0;L;;;;;N;;;;; 14603;ANATOLIAN HIEROGLYPH A460;Lo;0;L;;;;;N;;;;; 14604;ANATOLIAN HIEROGLYPH A461;Lo;0;L;;;;;N;;;;; 14605;ANATOLIAN HIEROGLYPH A462;Lo;0;L;;;;;N;;;;; 14606;ANATOLIAN HIEROGLYPH A463;Lo;0;L;;;;;N;;;;; 14607;ANATOLIAN HIEROGLYPH A464;Lo;0;L;;;;;N;;;;; 14608;ANATOLIAN HIEROGLYPH A465;Lo;0;L;;;;;N;;;;; 14609;ANATOLIAN HIEROGLYPH A466;Lo;0;L;;;;;N;;;;; 1460A;ANATOLIAN HIEROGLYPH A467;Lo;0;L;;;;;N;;;;; 1460B;ANATOLIAN HIEROGLYPH A468;Lo;0;L;;;;;N;;;;; 1460C;ANATOLIAN HIEROGLYPH A469;Lo;0;L;;;;;N;;;;; 1460D;ANATOLIAN HIEROGLYPH A470;Lo;0;L;;;;;N;;;;; 1460E;ANATOLIAN HIEROGLYPH A471;Lo;0;L;;;;;N;;;;; 1460F;ANATOLIAN HIEROGLYPH A472;Lo;0;L;;;;;N;;;;; 14610;ANATOLIAN HIEROGLYPH A473;Lo;0;L;;;;;N;;;;; 14611;ANATOLIAN HIEROGLYPH A474;Lo;0;L;;;;;N;;;;; 14612;ANATOLIAN HIEROGLYPH A475;Lo;0;L;;;;;N;;;;; 14613;ANATOLIAN HIEROGLYPH A476;Lo;0;L;;;;;N;;;;; 14614;ANATOLIAN HIEROGLYPH A477;Lo;0;L;;;;;N;;;;; 14615;ANATOLIAN HIEROGLYPH A478;Lo;0;L;;;;;N;;;;; 14616;ANATOLIAN HIEROGLYPH A479;Lo;0;L;;;;;N;;;;; 14617;ANATOLIAN HIEROGLYPH A480;Lo;0;L;;;;;N;;;;; 14618;ANATOLIAN HIEROGLYPH A481;Lo;0;L;;;;;N;;;;; 14619;ANATOLIAN HIEROGLYPH A482;Lo;0;L;;;;;N;;;;; 1461A;ANATOLIAN HIEROGLYPH A483;Lo;0;L;;;;;N;;;;; 1461B;ANATOLIAN HIEROGLYPH A484;Lo;0;L;;;;;N;;;;; 1461C;ANATOLIAN HIEROGLYPH A485;Lo;0;L;;;;;N;;;;; 1461D;ANATOLIAN HIEROGLYPH A486;Lo;0;L;;;;;N;;;;; 1461E;ANATOLIAN HIEROGLYPH A487;Lo;0;L;;;;;N;;;;; 1461F;ANATOLIAN HIEROGLYPH A488;Lo;0;L;;;;;N;;;;; 14620;ANATOLIAN HIEROGLYPH A489;Lo;0;L;;;;;N;;;;; 14621;ANATOLIAN HIEROGLYPH A490;Lo;0;L;;;;;N;;;;; 14622;ANATOLIAN HIEROGLYPH A491;Lo;0;L;;;;;N;;;;; 14623;ANATOLIAN HIEROGLYPH A492;Lo;0;L;;;;;N;;;;; 14624;ANATOLIAN HIEROGLYPH A493;Lo;0;L;;;;;N;;;;; 14625;ANATOLIAN HIEROGLYPH A494;Lo;0;L;;;;;N;;;;; 14626;ANATOLIAN HIEROGLYPH A495;Lo;0;L;;;;;N;;;;; 14627;ANATOLIAN HIEROGLYPH A496;Lo;0;L;;;;;N;;;;; 14628;ANATOLIAN HIEROGLYPH A497;Lo;0;L;;;;;N;;;;; 14629;ANATOLIAN HIEROGLYPH A501;Lo;0;L;;;;;N;;;;; 1462A;ANATOLIAN HIEROGLYPH A502;Lo;0;L;;;;;N;;;;; 1462B;ANATOLIAN HIEROGLYPH A503;Lo;0;L;;;;;N;;;;; 1462C;ANATOLIAN HIEROGLYPH A504;Lo;0;L;;;;;N;;;;; 1462D;ANATOLIAN HIEROGLYPH A505;Lo;0;L;;;;;N;;;;; 1462E;ANATOLIAN HIEROGLYPH A506;Lo;0;L;;;;;N;;;;; 1462F;ANATOLIAN HIEROGLYPH A507;Lo;0;L;;;;;N;;;;; 14630;ANATOLIAN HIEROGLYPH A508;Lo;0;L;;;;;N;;;;; 14631;ANATOLIAN HIEROGLYPH A509;Lo;0;L;;;;;N;;;;; 14632;ANATOLIAN HIEROGLYPH A510;Lo;0;L;;;;;N;;;;; 14633;ANATOLIAN HIEROGLYPH A511;Lo;0;L;;;;;N;;;;; 14634;ANATOLIAN HIEROGLYPH A512;Lo;0;L;;;;;N;;;;; 14635;ANATOLIAN HIEROGLYPH A513;Lo;0;L;;;;;N;;;;; 14636;ANATOLIAN HIEROGLYPH A514;Lo;0;L;;;;;N;;;;; 14637;ANATOLIAN HIEROGLYPH A515;Lo;0;L;;;;;N;;;;; 14638;ANATOLIAN HIEROGLYPH A516;Lo;0;L;;;;;N;;;;; 14639;ANATOLIAN HIEROGLYPH A517;Lo;0;L;;;;;N;;;;; 1463A;ANATOLIAN HIEROGLYPH A518;Lo;0;L;;;;;N;;;;; 1463B;ANATOLIAN HIEROGLYPH A519;Lo;0;L;;;;;N;;;;; 1463C;ANATOLIAN HIEROGLYPH A520;Lo;0;L;;;;;N;;;;; 1463D;ANATOLIAN HIEROGLYPH A521;Lo;0;L;;;;;N;;;;; 1463E;ANATOLIAN HIEROGLYPH A522;Lo;0;L;;;;;N;;;;; 1463F;ANATOLIAN HIEROGLYPH A523;Lo;0;L;;;;;N;;;;; 14640;ANATOLIAN HIEROGLYPH A524;Lo;0;L;;;;;N;;;;; 14641;ANATOLIAN HIEROGLYPH A525;Lo;0;L;;;;;N;;;;; 14642;ANATOLIAN HIEROGLYPH A526;Lo;0;L;;;;;N;;;;; 14643;ANATOLIAN HIEROGLYPH A527;Lo;0;L;;;;;N;;;;; 14644;ANATOLIAN HIEROGLYPH A528;Lo;0;L;;;;;N;;;;; 14645;ANATOLIAN HIEROGLYPH A529;Lo;0;L;;;;;N;;;;; 14646;ANATOLIAN HIEROGLYPH A530;Lo;0;L;;;;;N;;;;; 16800;BAMUM LETTER PHASE-A NGKUE MFON;Lo;0;L;;;;;N;;;;; 16801;BAMUM LETTER PHASE-A GBIEE FON;Lo;0;L;;;;;N;;;;; 16802;BAMUM LETTER PHASE-A PON MFON PIPAEMGBIEE;Lo;0;L;;;;;N;;;;; 16803;BAMUM LETTER PHASE-A PON MFON PIPAEMBA;Lo;0;L;;;;;N;;;;; 16804;BAMUM LETTER PHASE-A NAA MFON;Lo;0;L;;;;;N;;;;; 16805;BAMUM LETTER PHASE-A SHUENSHUET;Lo;0;L;;;;;N;;;;; 16806;BAMUM LETTER PHASE-A TITA MFON;Lo;0;L;;;;;N;;;;; 16807;BAMUM LETTER PHASE-A NZA MFON;Lo;0;L;;;;;N;;;;; 16808;BAMUM LETTER PHASE-A SHINDA PA NJI;Lo;0;L;;;;;N;;;;; 16809;BAMUM LETTER PHASE-A PON PA NJI PIPAEMGBIEE;Lo;0;L;;;;;N;;;;; 1680A;BAMUM LETTER PHASE-A PON PA NJI PIPAEMBA;Lo;0;L;;;;;N;;;;; 1680B;BAMUM LETTER PHASE-A MAEMBGBIEE;Lo;0;L;;;;;N;;;;; 1680C;BAMUM LETTER PHASE-A TU MAEMBA;Lo;0;L;;;;;N;;;;; 1680D;BAMUM LETTER PHASE-A NGANGU;Lo;0;L;;;;;N;;;;; 1680E;BAMUM LETTER PHASE-A MAEMVEUX;Lo;0;L;;;;;N;;;;; 1680F;BAMUM LETTER PHASE-A MANSUAE;Lo;0;L;;;;;N;;;;; 16810;BAMUM LETTER PHASE-A MVEUAENGAM;Lo;0;L;;;;;N;;;;; 16811;BAMUM LETTER PHASE-A SEUNYAM;Lo;0;L;;;;;N;;;;; 16812;BAMUM LETTER PHASE-A NTOQPEN;Lo;0;L;;;;;N;;;;; 16813;BAMUM LETTER PHASE-A KEUKEUTNDA;Lo;0;L;;;;;N;;;;; 16814;BAMUM LETTER PHASE-A NKINDI;Lo;0;L;;;;;N;;;;; 16815;BAMUM LETTER PHASE-A SUU;Lo;0;L;;;;;N;;;;; 16816;BAMUM LETTER PHASE-A NGKUENZEUM;Lo;0;L;;;;;N;;;;; 16817;BAMUM LETTER PHASE-A LAPAQ;Lo;0;L;;;;;N;;;;; 16818;BAMUM LETTER PHASE-A LET KUT;Lo;0;L;;;;;N;;;;; 16819;BAMUM LETTER PHASE-A NTAP MFAA;Lo;0;L;;;;;N;;;;; 1681A;BAMUM LETTER PHASE-A MAEKEUP;Lo;0;L;;;;;N;;;;; 1681B;BAMUM LETTER PHASE-A PASHAE;Lo;0;L;;;;;N;;;;; 1681C;BAMUM LETTER PHASE-A GHEUAERAE;Lo;0;L;;;;;N;;;;; 1681D;BAMUM LETTER PHASE-A PAMSHAE;Lo;0;L;;;;;N;;;;; 1681E;BAMUM LETTER PHASE-A MON NGGEUAET;Lo;0;L;;;;;N;;;;; 1681F;BAMUM LETTER PHASE-A NZUN MEUT;Lo;0;L;;;;;N;;;;; 16820;BAMUM LETTER PHASE-A U YUQ NAE;Lo;0;L;;;;;N;;;;; 16821;BAMUM LETTER PHASE-A GHEUAEGHEUAE;Lo;0;L;;;;;N;;;;; 16822;BAMUM LETTER PHASE-A NTAP NTAA;Lo;0;L;;;;;N;;;;; 16823;BAMUM LETTER PHASE-A SISA;Lo;0;L;;;;;N;;;;; 16824;BAMUM LETTER PHASE-A MGBASA;Lo;0;L;;;;;N;;;;; 16825;BAMUM LETTER PHASE-A MEUNJOMNDEUQ;Lo;0;L;;;;;N;;;;; 16826;BAMUM LETTER PHASE-A MOOMPUQ;Lo;0;L;;;;;N;;;;; 16827;BAMUM LETTER PHASE-A KAFA;Lo;0;L;;;;;N;;;;; 16828;BAMUM LETTER PHASE-A PA LEERAEWA;Lo;0;L;;;;;N;;;;; 16829;BAMUM LETTER PHASE-A NDA LEERAEWA;Lo;0;L;;;;;N;;;;; 1682A;BAMUM LETTER PHASE-A PET;Lo;0;L;;;;;N;;;;; 1682B;BAMUM LETTER PHASE-A MAEMKPEN;Lo;0;L;;;;;N;;;;; 1682C;BAMUM LETTER PHASE-A NIKA;Lo;0;L;;;;;N;;;;; 1682D;BAMUM LETTER PHASE-A PUP;Lo;0;L;;;;;N;;;;; 1682E;BAMUM LETTER PHASE-A TUAEP;Lo;0;L;;;;;N;;;;; 1682F;BAMUM LETTER PHASE-A LUAEP;Lo;0;L;;;;;N;;;;; 16830;BAMUM LETTER PHASE-A SONJAM;Lo;0;L;;;;;N;;;;; 16831;BAMUM LETTER PHASE-A TEUTEUWEN;Lo;0;L;;;;;N;;;;; 16832;BAMUM LETTER PHASE-A MAENYI;Lo;0;L;;;;;N;;;;; 16833;BAMUM LETTER PHASE-A KET;Lo;0;L;;;;;N;;;;; 16834;BAMUM LETTER PHASE-A NDAANGGEUAET;Lo;0;L;;;;;N;;;;; 16835;BAMUM LETTER PHASE-A KUOQ;Lo;0;L;;;;;N;;;;; 16836;BAMUM LETTER PHASE-A MOOMEUT;Lo;0;L;;;;;N;;;;; 16837;BAMUM LETTER PHASE-A SHUM;Lo;0;L;;;;;N;;;;; 16838;BAMUM LETTER PHASE-A LOMMAE;Lo;0;L;;;;;N;;;;; 16839;BAMUM LETTER PHASE-A FIRI;Lo;0;L;;;;;N;;;;; 1683A;BAMUM LETTER PHASE-A ROM;Lo;0;L;;;;;N;;;;; 1683B;BAMUM LETTER PHASE-A KPOQ;Lo;0;L;;;;;N;;;;; 1683C;BAMUM LETTER PHASE-A SOQ;Lo;0;L;;;;;N;;;;; 1683D;BAMUM LETTER PHASE-A MAP PIEET;Lo;0;L;;;;;N;;;;; 1683E;BAMUM LETTER PHASE-A SHIRAE;Lo;0;L;;;;;N;;;;; 1683F;BAMUM LETTER PHASE-A NTAP;Lo;0;L;;;;;N;;;;; 16840;BAMUM LETTER PHASE-A SHOQ NSHUT YUM;Lo;0;L;;;;;N;;;;; 16841;BAMUM LETTER PHASE-A NYIT MONGKEUAEQ;Lo;0;L;;;;;N;;;;; 16842;BAMUM LETTER PHASE-A PAARAE;Lo;0;L;;;;;N;;;;; 16843;BAMUM LETTER PHASE-A NKAARAE;Lo;0;L;;;;;N;;;;; 16844;BAMUM LETTER PHASE-A UNKNOWN;Lo;0;L;;;;;N;;;;; 16845;BAMUM LETTER PHASE-A NGGEN;Lo;0;L;;;;;N;;;;; 16846;BAMUM LETTER PHASE-A MAESI;Lo;0;L;;;;;N;;;;; 16847;BAMUM LETTER PHASE-A NJAM;Lo;0;L;;;;;N;;;;; 16848;BAMUM LETTER PHASE-A MBANYI;Lo;0;L;;;;;N;;;;; 16849;BAMUM LETTER PHASE-A NYET;Lo;0;L;;;;;N;;;;; 1684A;BAMUM LETTER PHASE-A TEUAEN;Lo;0;L;;;;;N;;;;; 1684B;BAMUM LETTER PHASE-A SOT;Lo;0;L;;;;;N;;;;; 1684C;BAMUM LETTER PHASE-A PAAM;Lo;0;L;;;;;N;;;;; 1684D;BAMUM LETTER PHASE-A NSHIEE;Lo;0;L;;;;;N;;;;; 1684E;BAMUM LETTER PHASE-A MAEM;Lo;0;L;;;;;N;;;;; 1684F;BAMUM LETTER PHASE-A NYI;Lo;0;L;;;;;N;;;;; 16850;BAMUM LETTER PHASE-A KAQ;Lo;0;L;;;;;N;;;;; 16851;BAMUM LETTER PHASE-A NSHA;Lo;0;L;;;;;N;;;;; 16852;BAMUM LETTER PHASE-A VEE;Lo;0;L;;;;;N;;;;; 16853;BAMUM LETTER PHASE-A LU;Lo;0;L;;;;;N;;;;; 16854;BAMUM LETTER PHASE-A NEN;Lo;0;L;;;;;N;;;;; 16855;BAMUM LETTER PHASE-A NAQ;Lo;0;L;;;;;N;;;;; 16856;BAMUM LETTER PHASE-A MBAQ;Lo;0;L;;;;;N;;;;; 16857;BAMUM LETTER PHASE-B NSHUET;Lo;0;L;;;;;N;;;;; 16858;BAMUM LETTER PHASE-B TU MAEMGBIEE;Lo;0;L;;;;;N;;;;; 16859;BAMUM LETTER PHASE-B SIEE;Lo;0;L;;;;;N;;;;; 1685A;BAMUM LETTER PHASE-B SET TU;Lo;0;L;;;;;N;;;;; 1685B;BAMUM LETTER PHASE-B LOM NTEUM;Lo;0;L;;;;;N;;;;; 1685C;BAMUM LETTER PHASE-B MBA MAELEE;Lo;0;L;;;;;N;;;;; 1685D;BAMUM LETTER PHASE-B KIEEM;Lo;0;L;;;;;N;;;;; 1685E;BAMUM LETTER PHASE-B YEURAE;Lo;0;L;;;;;N;;;;; 1685F;BAMUM LETTER PHASE-B MBAARAE;Lo;0;L;;;;;N;;;;; 16860;BAMUM LETTER PHASE-B KAM;Lo;0;L;;;;;N;;;;; 16861;BAMUM LETTER PHASE-B PEESHI;Lo;0;L;;;;;N;;;;; 16862;BAMUM LETTER PHASE-B YAFU LEERAEWA;Lo;0;L;;;;;N;;;;; 16863;BAMUM LETTER PHASE-B LAM NSHUT NYAM;Lo;0;L;;;;;N;;;;; 16864;BAMUM LETTER PHASE-B NTIEE SHEUOQ;Lo;0;L;;;;;N;;;;; 16865;BAMUM LETTER PHASE-B NDU NJAA;Lo;0;L;;;;;N;;;;; 16866;BAMUM LETTER PHASE-B GHEUGHEUAEM;Lo;0;L;;;;;N;;;;; 16867;BAMUM LETTER PHASE-B PIT;Lo;0;L;;;;;N;;;;; 16868;BAMUM LETTER PHASE-B TU NSIEE;Lo;0;L;;;;;N;;;;; 16869;BAMUM LETTER PHASE-B SHET NJAQ;Lo;0;L;;;;;N;;;;; 1686A;BAMUM LETTER PHASE-B SHEUAEQTU;Lo;0;L;;;;;N;;;;; 1686B;BAMUM LETTER PHASE-B MFON TEUAEQ;Lo;0;L;;;;;N;;;;; 1686C;BAMUM LETTER PHASE-B MBIT MBAAKET;Lo;0;L;;;;;N;;;;; 1686D;BAMUM LETTER PHASE-B NYI NTEUM;Lo;0;L;;;;;N;;;;; 1686E;BAMUM LETTER PHASE-B KEUPUQ;Lo;0;L;;;;;N;;;;; 1686F;BAMUM LETTER PHASE-B GHEUGHEN;Lo;0;L;;;;;N;;;;; 16870;BAMUM LETTER PHASE-B KEUYEUX;Lo;0;L;;;;;N;;;;; 16871;BAMUM LETTER PHASE-B LAANAE;Lo;0;L;;;;;N;;;;; 16872;BAMUM LETTER PHASE-B PARUM;Lo;0;L;;;;;N;;;;; 16873;BAMUM LETTER PHASE-B VEUM;Lo;0;L;;;;;N;;;;; 16874;BAMUM LETTER PHASE-B NGKINDI MVOP;Lo;0;L;;;;;N;;;;; 16875;BAMUM LETTER PHASE-B NGGEU MBU;Lo;0;L;;;;;N;;;;; 16876;BAMUM LETTER PHASE-B WUAET;Lo;0;L;;;;;N;;;;; 16877;BAMUM LETTER PHASE-B SAKEUAE;Lo;0;L;;;;;N;;;;; 16878;BAMUM LETTER PHASE-B TAAM;Lo;0;L;;;;;N;;;;; 16879;BAMUM LETTER PHASE-B MEUQ;Lo;0;L;;;;;N;;;;; 1687A;BAMUM LETTER PHASE-B NGGUOQ;Lo;0;L;;;;;N;;;;; 1687B;BAMUM LETTER PHASE-B NGGUOQ LARGE;Lo;0;L;;;;;N;;;;; 1687C;BAMUM LETTER PHASE-B MFIYAQ;Lo;0;L;;;;;N;;;;; 1687D;BAMUM LETTER PHASE-B SUE;Lo;0;L;;;;;N;;;;; 1687E;BAMUM LETTER PHASE-B MBEURI;Lo;0;L;;;;;N;;;;; 1687F;BAMUM LETTER PHASE-B MONTIEEN;Lo;0;L;;;;;N;;;;; 16880;BAMUM LETTER PHASE-B NYAEMAE;Lo;0;L;;;;;N;;;;; 16881;BAMUM LETTER PHASE-B PUNGAAM;Lo;0;L;;;;;N;;;;; 16882;BAMUM LETTER PHASE-B MEUT NGGEET;Lo;0;L;;;;;N;;;;; 16883;BAMUM LETTER PHASE-B FEUX;Lo;0;L;;;;;N;;;;; 16884;BAMUM LETTER PHASE-B MBUOQ;Lo;0;L;;;;;N;;;;; 16885;BAMUM LETTER PHASE-B FEE;Lo;0;L;;;;;N;;;;; 16886;BAMUM LETTER PHASE-B KEUAEM;Lo;0;L;;;;;N;;;;; 16887;BAMUM LETTER PHASE-B MA NJEUAENA;Lo;0;L;;;;;N;;;;; 16888;BAMUM LETTER PHASE-B MA NJUQA;Lo;0;L;;;;;N;;;;; 16889;BAMUM LETTER PHASE-B LET;Lo;0;L;;;;;N;;;;; 1688A;BAMUM LETTER PHASE-B NGGAAM;Lo;0;L;;;;;N;;;;; 1688B;BAMUM LETTER PHASE-B NSEN;Lo;0;L;;;;;N;;;;; 1688C;BAMUM LETTER PHASE-B MA;Lo;0;L;;;;;N;;;;; 1688D;BAMUM LETTER PHASE-B KIQ;Lo;0;L;;;;;N;;;;; 1688E;BAMUM LETTER PHASE-B NGOM;Lo;0;L;;;;;N;;;;; 1688F;BAMUM LETTER PHASE-C NGKUE MAEMBA;Lo;0;L;;;;;N;;;;; 16890;BAMUM LETTER PHASE-C NZA;Lo;0;L;;;;;N;;;;; 16891;BAMUM LETTER PHASE-C YUM;Lo;0;L;;;;;N;;;;; 16892;BAMUM LETTER PHASE-C WANGKUOQ;Lo;0;L;;;;;N;;;;; 16893;BAMUM LETTER PHASE-C NGGEN;Lo;0;L;;;;;N;;;;; 16894;BAMUM LETTER PHASE-C NDEUAEREE;Lo;0;L;;;;;N;;;;; 16895;BAMUM LETTER PHASE-C NGKAQ;Lo;0;L;;;;;N;;;;; 16896;BAMUM LETTER PHASE-C GHARAE;Lo;0;L;;;;;N;;;;; 16897;BAMUM LETTER PHASE-C MBEEKEET;Lo;0;L;;;;;N;;;;; 16898;BAMUM LETTER PHASE-C GBAYI;Lo;0;L;;;;;N;;;;; 16899;BAMUM LETTER PHASE-C NYIR MKPARAQ MEUN;Lo;0;L;;;;;N;;;;; 1689A;BAMUM LETTER PHASE-C NTU MBIT;Lo;0;L;;;;;N;;;;; 1689B;BAMUM LETTER PHASE-C MBEUM;Lo;0;L;;;;;N;;;;; 1689C;BAMUM LETTER PHASE-C PIRIEEN;Lo;0;L;;;;;N;;;;; 1689D;BAMUM LETTER PHASE-C NDOMBU;Lo;0;L;;;;;N;;;;; 1689E;BAMUM LETTER PHASE-C MBAA CABBAGE-TREE;Lo;0;L;;;;;N;;;;; 1689F;BAMUM LETTER PHASE-C KEUSHEUAEP;Lo;0;L;;;;;N;;;;; 168A0;BAMUM LETTER PHASE-C GHAP;Lo;0;L;;;;;N;;;;; 168A1;BAMUM LETTER PHASE-C KEUKAQ;Lo;0;L;;;;;N;;;;; 168A2;BAMUM LETTER PHASE-C YU MUOMAE;Lo;0;L;;;;;N;;;;; 168A3;BAMUM LETTER PHASE-C NZEUM;Lo;0;L;;;;;N;;;;; 168A4;BAMUM LETTER PHASE-C MBUE;Lo;0;L;;;;;N;;;;; 168A5;BAMUM LETTER PHASE-C NSEUAEN;Lo;0;L;;;;;N;;;;; 168A6;BAMUM LETTER PHASE-C MBIT;Lo;0;L;;;;;N;;;;; 168A7;BAMUM LETTER PHASE-C YEUQ;Lo;0;L;;;;;N;;;;; 168A8;BAMUM LETTER PHASE-C KPARAQ;Lo;0;L;;;;;N;;;;; 168A9;BAMUM LETTER PHASE-C KAA;Lo;0;L;;;;;N;;;;; 168AA;BAMUM LETTER PHASE-C SEUX;Lo;0;L;;;;;N;;;;; 168AB;BAMUM LETTER PHASE-C NDIDA;Lo;0;L;;;;;N;;;;; 168AC;BAMUM LETTER PHASE-C TAASHAE;Lo;0;L;;;;;N;;;;; 168AD;BAMUM LETTER PHASE-C NJUEQ;Lo;0;L;;;;;N;;;;; 168AE;BAMUM LETTER PHASE-C TITA YUE;Lo;0;L;;;;;N;;;;; 168AF;BAMUM LETTER PHASE-C SUAET;Lo;0;L;;;;;N;;;;; 168B0;BAMUM LETTER PHASE-C NGGUAEN NYAM;Lo;0;L;;;;;N;;;;; 168B1;BAMUM LETTER PHASE-C VEUX;Lo;0;L;;;;;N;;;;; 168B2;BAMUM LETTER PHASE-C NANSANAQ;Lo;0;L;;;;;N;;;;; 168B3;BAMUM LETTER PHASE-C MA KEUAERI;Lo;0;L;;;;;N;;;;; 168B4;BAMUM LETTER PHASE-C NTAA;Lo;0;L;;;;;N;;;;; 168B5;BAMUM LETTER PHASE-C NGGUON;Lo;0;L;;;;;N;;;;; 168B6;BAMUM LETTER PHASE-C LAP;Lo;0;L;;;;;N;;;;; 168B7;BAMUM LETTER PHASE-C MBIRIEEN;Lo;0;L;;;;;N;;;;; 168B8;BAMUM LETTER PHASE-C MGBASAQ;Lo;0;L;;;;;N;;;;; 168B9;BAMUM LETTER PHASE-C NTEUNGBA;Lo;0;L;;;;;N;;;;; 168BA;BAMUM LETTER PHASE-C TEUTEUX;Lo;0;L;;;;;N;;;;; 168BB;BAMUM LETTER PHASE-C NGGUM;Lo;0;L;;;;;N;;;;; 168BC;BAMUM LETTER PHASE-C FUE;Lo;0;L;;;;;N;;;;; 168BD;BAMUM LETTER PHASE-C NDEUT;Lo;0;L;;;;;N;;;;; 168BE;BAMUM LETTER PHASE-C NSA;Lo;0;L;;;;;N;;;;; 168BF;BAMUM LETTER PHASE-C NSHAQ;Lo;0;L;;;;;N;;;;; 168C0;BAMUM LETTER PHASE-C BUNG;Lo;0;L;;;;;N;;;;; 168C1;BAMUM LETTER PHASE-C VEUAEPEN;Lo;0;L;;;;;N;;;;; 168C2;BAMUM LETTER PHASE-C MBERAE;Lo;0;L;;;;;N;;;;; 168C3;BAMUM LETTER PHASE-C RU;Lo;0;L;;;;;N;;;;; 168C4;BAMUM LETTER PHASE-C NJAEM;Lo;0;L;;;;;N;;;;; 168C5;BAMUM LETTER PHASE-C LAM;Lo;0;L;;;;;N;;;;; 168C6;BAMUM LETTER PHASE-C TITUAEP;Lo;0;L;;;;;N;;;;; 168C7;BAMUM LETTER PHASE-C NSUOT NGOM;Lo;0;L;;;;;N;;;;; 168C8;BAMUM LETTER PHASE-C NJEEEE;Lo;0;L;;;;;N;;;;; 168C9;BAMUM LETTER PHASE-C KET;Lo;0;L;;;;;N;;;;; 168CA;BAMUM LETTER PHASE-C NGGU;Lo;0;L;;;;;N;;;;; 168CB;BAMUM LETTER PHASE-C MAESI;Lo;0;L;;;;;N;;;;; 168CC;BAMUM LETTER PHASE-C MBUAEM;Lo;0;L;;;;;N;;;;; 168CD;BAMUM LETTER PHASE-C LU;Lo;0;L;;;;;N;;;;; 168CE;BAMUM LETTER PHASE-C KUT;Lo;0;L;;;;;N;;;;; 168CF;BAMUM LETTER PHASE-C NJAM;Lo;0;L;;;;;N;;;;; 168D0;BAMUM LETTER PHASE-C NGOM;Lo;0;L;;;;;N;;;;; 168D1;BAMUM LETTER PHASE-C WUP;Lo;0;L;;;;;N;;;;; 168D2;BAMUM LETTER PHASE-C NGGUEET;Lo;0;L;;;;;N;;;;; 168D3;BAMUM LETTER PHASE-C NSOM;Lo;0;L;;;;;N;;;;; 168D4;BAMUM LETTER PHASE-C NTEN;Lo;0;L;;;;;N;;;;; 168D5;BAMUM LETTER PHASE-C KUOP NKAARAE;Lo;0;L;;;;;N;;;;; 168D6;BAMUM LETTER PHASE-C NSUN;Lo;0;L;;;;;N;;;;; 168D7;BAMUM LETTER PHASE-C NDAM;Lo;0;L;;;;;N;;;;; 168D8;BAMUM LETTER PHASE-C MA NSIEE;Lo;0;L;;;;;N;;;;; 168D9;BAMUM LETTER PHASE-C YAA;Lo;0;L;;;;;N;;;;; 168DA;BAMUM LETTER PHASE-C NDAP;Lo;0;L;;;;;N;;;;; 168DB;BAMUM LETTER PHASE-C SHUEQ;Lo;0;L;;;;;N;;;;; 168DC;BAMUM LETTER PHASE-C SETFON;Lo;0;L;;;;;N;;;;; 168DD;BAMUM LETTER PHASE-C MBI;Lo;0;L;;;;;N;;;;; 168DE;BAMUM LETTER PHASE-C MAEMBA;Lo;0;L;;;;;N;;;;; 168DF;BAMUM LETTER PHASE-C MBANYI;Lo;0;L;;;;;N;;;;; 168E0;BAMUM LETTER PHASE-C KEUSEUX;Lo;0;L;;;;;N;;;;; 168E1;BAMUM LETTER PHASE-C MBEUX;Lo;0;L;;;;;N;;;;; 168E2;BAMUM LETTER PHASE-C KEUM;Lo;0;L;;;;;N;;;;; 168E3;BAMUM LETTER PHASE-C MBAA PICKET;Lo;0;L;;;;;N;;;;; 168E4;BAMUM LETTER PHASE-C YUWOQ;Lo;0;L;;;;;N;;;;; 168E5;BAMUM LETTER PHASE-C NJEUX;Lo;0;L;;;;;N;;;;; 168E6;BAMUM LETTER PHASE-C MIEE;Lo;0;L;;;;;N;;;;; 168E7;BAMUM LETTER PHASE-C MUAE;Lo;0;L;;;;;N;;;;; 168E8;BAMUM LETTER PHASE-C SHIQ;Lo;0;L;;;;;N;;;;; 168E9;BAMUM LETTER PHASE-C KEN LAW;Lo;0;L;;;;;N;;;;; 168EA;BAMUM LETTER PHASE-C KEN FATIGUE;Lo;0;L;;;;;N;;;;; 168EB;BAMUM LETTER PHASE-C NGAQ;Lo;0;L;;;;;N;;;;; 168EC;BAMUM LETTER PHASE-C NAQ;Lo;0;L;;;;;N;;;;; 168ED;BAMUM LETTER PHASE-C LIQ;Lo;0;L;;;;;N;;;;; 168EE;BAMUM LETTER PHASE-C PIN;Lo;0;L;;;;;N;;;;; 168EF;BAMUM LETTER PHASE-C PEN;Lo;0;L;;;;;N;;;;; 168F0;BAMUM LETTER PHASE-C TET;Lo;0;L;;;;;N;;;;; 168F1;BAMUM LETTER PHASE-D MBUO;Lo;0;L;;;;;N;;;;; 168F2;BAMUM LETTER PHASE-D WAP;Lo;0;L;;;;;N;;;;; 168F3;BAMUM LETTER PHASE-D NJI;Lo;0;L;;;;;N;;;;; 168F4;BAMUM LETTER PHASE-D MFON;Lo;0;L;;;;;N;;;;; 168F5;BAMUM LETTER PHASE-D NJIEE;Lo;0;L;;;;;N;;;;; 168F6;BAMUM LETTER PHASE-D LIEE;Lo;0;L;;;;;N;;;;; 168F7;BAMUM LETTER PHASE-D NJEUT;Lo;0;L;;;;;N;;;;; 168F8;BAMUM LETTER PHASE-D NSHEE;Lo;0;L;;;;;N;;;;; 168F9;BAMUM LETTER PHASE-D NGGAAMAE;Lo;0;L;;;;;N;;;;; 168FA;BAMUM LETTER PHASE-D NYAM;Lo;0;L;;;;;N;;;;; 168FB;BAMUM LETTER PHASE-D WUAEN;Lo;0;L;;;;;N;;;;; 168FC;BAMUM LETTER PHASE-D NGKUN;Lo;0;L;;;;;N;;;;; 168FD;BAMUM LETTER PHASE-D SHEE;Lo;0;L;;;;;N;;;;; 168FE;BAMUM LETTER PHASE-D NGKAP;Lo;0;L;;;;;N;;;;; 168FF;BAMUM LETTER PHASE-D KEUAETMEUN;Lo;0;L;;;;;N;;;;; 16900;BAMUM LETTER PHASE-D TEUT;Lo;0;L;;;;;N;;;;; 16901;BAMUM LETTER PHASE-D SHEUAE;Lo;0;L;;;;;N;;;;; 16902;BAMUM LETTER PHASE-D NJAP;Lo;0;L;;;;;N;;;;; 16903;BAMUM LETTER PHASE-D SUE;Lo;0;L;;;;;N;;;;; 16904;BAMUM LETTER PHASE-D KET;Lo;0;L;;;;;N;;;;; 16905;BAMUM LETTER PHASE-D YAEMMAE;Lo;0;L;;;;;N;;;;; 16906;BAMUM LETTER PHASE-D KUOM;Lo;0;L;;;;;N;;;;; 16907;BAMUM LETTER PHASE-D SAP;Lo;0;L;;;;;N;;;;; 16908;BAMUM LETTER PHASE-D MFEUT;Lo;0;L;;;;;N;;;;; 16909;BAMUM LETTER PHASE-D NDEUX;Lo;0;L;;;;;N;;;;; 1690A;BAMUM LETTER PHASE-D MALEERI;Lo;0;L;;;;;N;;;;; 1690B;BAMUM LETTER PHASE-D MEUT;Lo;0;L;;;;;N;;;;; 1690C;BAMUM LETTER PHASE-D SEUAEQ;Lo;0;L;;;;;N;;;;; 1690D;BAMUM LETTER PHASE-D YEN;Lo;0;L;;;;;N;;;;; 1690E;BAMUM LETTER PHASE-D NJEUAEM;Lo;0;L;;;;;N;;;;; 1690F;BAMUM LETTER PHASE-D KEUOT MBUAE;Lo;0;L;;;;;N;;;;; 16910;BAMUM LETTER PHASE-D NGKEURI;Lo;0;L;;;;;N;;;;; 16911;BAMUM LETTER PHASE-D TU;Lo;0;L;;;;;N;;;;; 16912;BAMUM LETTER PHASE-D GHAA;Lo;0;L;;;;;N;;;;; 16913;BAMUM LETTER PHASE-D NGKYEE;Lo;0;L;;;;;N;;;;; 16914;BAMUM LETTER PHASE-D FEUFEUAET;Lo;0;L;;;;;N;;;;; 16915;BAMUM LETTER PHASE-D NDEE;Lo;0;L;;;;;N;;;;; 16916;BAMUM LETTER PHASE-D MGBOFUM;Lo;0;L;;;;;N;;;;; 16917;BAMUM LETTER PHASE-D LEUAEP;Lo;0;L;;;;;N;;;;; 16918;BAMUM LETTER PHASE-D NDON;Lo;0;L;;;;;N;;;;; 16919;BAMUM LETTER PHASE-D MONI;Lo;0;L;;;;;N;;;;; 1691A;BAMUM LETTER PHASE-D MGBEUN;Lo;0;L;;;;;N;;;;; 1691B;BAMUM LETTER PHASE-D PUUT;Lo;0;L;;;;;N;;;;; 1691C;BAMUM LETTER PHASE-D MGBIEE;Lo;0;L;;;;;N;;;;; 1691D;BAMUM LETTER PHASE-D MFO;Lo;0;L;;;;;N;;;;; 1691E;BAMUM LETTER PHASE-D LUM;Lo;0;L;;;;;N;;;;; 1691F;BAMUM LETTER PHASE-D NSIEEP;Lo;0;L;;;;;N;;;;; 16920;BAMUM LETTER PHASE-D MBAA;Lo;0;L;;;;;N;;;;; 16921;BAMUM LETTER PHASE-D KWAET;Lo;0;L;;;;;N;;;;; 16922;BAMUM LETTER PHASE-D NYET;Lo;0;L;;;;;N;;;;; 16923;BAMUM LETTER PHASE-D TEUAEN;Lo;0;L;;;;;N;;;;; 16924;BAMUM LETTER PHASE-D SOT;Lo;0;L;;;;;N;;;;; 16925;BAMUM LETTER PHASE-D YUWOQ;Lo;0;L;;;;;N;;;;; 16926;BAMUM LETTER PHASE-D KEUM;Lo;0;L;;;;;N;;;;; 16927;BAMUM LETTER PHASE-D RAEM;Lo;0;L;;;;;N;;;;; 16928;BAMUM LETTER PHASE-D TEEEE;Lo;0;L;;;;;N;;;;; 16929;BAMUM LETTER PHASE-D NGKEUAEQ;Lo;0;L;;;;;N;;;;; 1692A;BAMUM LETTER PHASE-D MFEUAE;Lo;0;L;;;;;N;;;;; 1692B;BAMUM LETTER PHASE-D NSIEET;Lo;0;L;;;;;N;;;;; 1692C;BAMUM LETTER PHASE-D KEUP;Lo;0;L;;;;;N;;;;; 1692D;BAMUM LETTER PHASE-D PIP;Lo;0;L;;;;;N;;;;; 1692E;BAMUM LETTER PHASE-D PEUTAE;Lo;0;L;;;;;N;;;;; 1692F;BAMUM LETTER PHASE-D NYUE;Lo;0;L;;;;;N;;;;; 16930;BAMUM LETTER PHASE-D LET;Lo;0;L;;;;;N;;;;; 16931;BAMUM LETTER PHASE-D NGGAAM;Lo;0;L;;;;;N;;;;; 16932;BAMUM LETTER PHASE-D MFIEE;Lo;0;L;;;;;N;;;;; 16933;BAMUM LETTER PHASE-D NGGWAEN;Lo;0;L;;;;;N;;;;; 16934;BAMUM LETTER PHASE-D YUOM;Lo;0;L;;;;;N;;;;; 16935;BAMUM LETTER PHASE-D PAP;Lo;0;L;;;;;N;;;;; 16936;BAMUM LETTER PHASE-D YUOP;Lo;0;L;;;;;N;;;;; 16937;BAMUM LETTER PHASE-D NDAM;Lo;0;L;;;;;N;;;;; 16938;BAMUM LETTER PHASE-D NTEUM;Lo;0;L;;;;;N;;;;; 16939;BAMUM LETTER PHASE-D SUAE;Lo;0;L;;;;;N;;;;; 1693A;BAMUM LETTER PHASE-D KUN;Lo;0;L;;;;;N;;;;; 1693B;BAMUM LETTER PHASE-D NGGEUX;Lo;0;L;;;;;N;;;;; 1693C;BAMUM LETTER PHASE-D NGKIEE;Lo;0;L;;;;;N;;;;; 1693D;BAMUM LETTER PHASE-D TUOT;Lo;0;L;;;;;N;;;;; 1693E;BAMUM LETTER PHASE-D MEUN;Lo;0;L;;;;;N;;;;; 1693F;BAMUM LETTER PHASE-D KUQ;Lo;0;L;;;;;N;;;;; 16940;BAMUM LETTER PHASE-D NSUM;Lo;0;L;;;;;N;;;;; 16941;BAMUM LETTER PHASE-D TEUN;Lo;0;L;;;;;N;;;;; 16942;BAMUM LETTER PHASE-D MAENJET;Lo;0;L;;;;;N;;;;; 16943;BAMUM LETTER PHASE-D NGGAP;Lo;0;L;;;;;N;;;;; 16944;BAMUM LETTER PHASE-D LEUM;Lo;0;L;;;;;N;;;;; 16945;BAMUM LETTER PHASE-D NGGUOM;Lo;0;L;;;;;N;;;;; 16946;BAMUM LETTER PHASE-D NSHUT;Lo;0;L;;;;;N;;;;; 16947;BAMUM LETTER PHASE-D NJUEQ;Lo;0;L;;;;;N;;;;; 16948;BAMUM LETTER PHASE-D GHEUAE;Lo;0;L;;;;;N;;;;; 16949;BAMUM LETTER PHASE-D KU;Lo;0;L;;;;;N;;;;; 1694A;BAMUM LETTER PHASE-D REN OLD;Lo;0;L;;;;;N;;;;; 1694B;BAMUM LETTER PHASE-D TAE;Lo;0;L;;;;;N;;;;; 1694C;BAMUM LETTER PHASE-D TOQ;Lo;0;L;;;;;N;;;;; 1694D;BAMUM LETTER PHASE-D NYI;Lo;0;L;;;;;N;;;;; 1694E;BAMUM LETTER PHASE-D RII;Lo;0;L;;;;;N;;;;; 1694F;BAMUM LETTER PHASE-D LEEEE;Lo;0;L;;;;;N;;;;; 16950;BAMUM LETTER PHASE-D MEEEE;Lo;0;L;;;;;N;;;;; 16951;BAMUM LETTER PHASE-D M;Lo;0;L;;;;;N;;;;; 16952;BAMUM LETTER PHASE-D SUU;Lo;0;L;;;;;N;;;;; 16953;BAMUM LETTER PHASE-D MU;Lo;0;L;;;;;N;;;;; 16954;BAMUM LETTER PHASE-D SHII;Lo;0;L;;;;;N;;;;; 16955;BAMUM LETTER PHASE-D SHEUX;Lo;0;L;;;;;N;;;;; 16956;BAMUM LETTER PHASE-D KYEE;Lo;0;L;;;;;N;;;;; 16957;BAMUM LETTER PHASE-D NU;Lo;0;L;;;;;N;;;;; 16958;BAMUM LETTER PHASE-D SHU;Lo;0;L;;;;;N;;;;; 16959;BAMUM LETTER PHASE-D NTEE;Lo;0;L;;;;;N;;;;; 1695A;BAMUM LETTER PHASE-D PEE;Lo;0;L;;;;;N;;;;; 1695B;BAMUM LETTER PHASE-D NI;Lo;0;L;;;;;N;;;;; 1695C;BAMUM LETTER PHASE-D SHOQ;Lo;0;L;;;;;N;;;;; 1695D;BAMUM LETTER PHASE-D PUQ;Lo;0;L;;;;;N;;;;; 1695E;BAMUM LETTER PHASE-D MVOP;Lo;0;L;;;;;N;;;;; 1695F;BAMUM LETTER PHASE-D LOQ;Lo;0;L;;;;;N;;;;; 16960;BAMUM LETTER PHASE-D REN MUCH;Lo;0;L;;;;;N;;;;; 16961;BAMUM LETTER PHASE-D TI;Lo;0;L;;;;;N;;;;; 16962;BAMUM LETTER PHASE-D NTUU;Lo;0;L;;;;;N;;;;; 16963;BAMUM LETTER PHASE-D MBAA SEVEN;Lo;0;L;;;;;N;;;;; 16964;BAMUM LETTER PHASE-D SAQ;Lo;0;L;;;;;N;;;;; 16965;BAMUM LETTER PHASE-D FAA;Lo;0;L;;;;;N;;;;; 16966;BAMUM LETTER PHASE-E NDAP;Lo;0;L;;;;;N;;;;; 16967;BAMUM LETTER PHASE-E TOON;Lo;0;L;;;;;N;;;;; 16968;BAMUM LETTER PHASE-E MBEUM;Lo;0;L;;;;;N;;;;; 16969;BAMUM LETTER PHASE-E LAP;Lo;0;L;;;;;N;;;;; 1696A;BAMUM LETTER PHASE-E VOM;Lo;0;L;;;;;N;;;;; 1696B;BAMUM LETTER PHASE-E LOON;Lo;0;L;;;;;N;;;;; 1696C;BAMUM LETTER PHASE-E PAA;Lo;0;L;;;;;N;;;;; 1696D;BAMUM LETTER PHASE-E SOM;Lo;0;L;;;;;N;;;;; 1696E;BAMUM LETTER PHASE-E RAQ;Lo;0;L;;;;;N;;;;; 1696F;BAMUM LETTER PHASE-E NSHUOP;Lo;0;L;;;;;N;;;;; 16970;BAMUM LETTER PHASE-E NDUN;Lo;0;L;;;;;N;;;;; 16971;BAMUM LETTER PHASE-E PUAE;Lo;0;L;;;;;N;;;;; 16972;BAMUM LETTER PHASE-E TAM;Lo;0;L;;;;;N;;;;; 16973;BAMUM LETTER PHASE-E NGKA;Lo;0;L;;;;;N;;;;; 16974;BAMUM LETTER PHASE-E KPEUX;Lo;0;L;;;;;N;;;;; 16975;BAMUM LETTER PHASE-E WUO;Lo;0;L;;;;;N;;;;; 16976;BAMUM LETTER PHASE-E SEE;Lo;0;L;;;;;N;;;;; 16977;BAMUM LETTER PHASE-E NGGEUAET;Lo;0;L;;;;;N;;;;; 16978;BAMUM LETTER PHASE-E PAAM;Lo;0;L;;;;;N;;;;; 16979;BAMUM LETTER PHASE-E TOO;Lo;0;L;;;;;N;;;;; 1697A;BAMUM LETTER PHASE-E KUOP;Lo;0;L;;;;;N;;;;; 1697B;BAMUM LETTER PHASE-E LOM;Lo;0;L;;;;;N;;;;; 1697C;BAMUM LETTER PHASE-E NSHIEE;Lo;0;L;;;;;N;;;;; 1697D;BAMUM LETTER PHASE-E NGOP;Lo;0;L;;;;;N;;;;; 1697E;BAMUM LETTER PHASE-E MAEM;Lo;0;L;;;;;N;;;;; 1697F;BAMUM LETTER PHASE-E NGKEUX;Lo;0;L;;;;;N;;;;; 16980;BAMUM LETTER PHASE-E NGOQ;Lo;0;L;;;;;N;;;;; 16981;BAMUM LETTER PHASE-E NSHUE;Lo;0;L;;;;;N;;;;; 16982;BAMUM LETTER PHASE-E RIMGBA;Lo;0;L;;;;;N;;;;; 16983;BAMUM LETTER PHASE-E NJEUX;Lo;0;L;;;;;N;;;;; 16984;BAMUM LETTER PHASE-E PEEM;Lo;0;L;;;;;N;;;;; 16985;BAMUM LETTER PHASE-E SAA;Lo;0;L;;;;;N;;;;; 16986;BAMUM LETTER PHASE-E NGGURAE;Lo;0;L;;;;;N;;;;; 16987;BAMUM LETTER PHASE-E MGBA;Lo;0;L;;;;;N;;;;; 16988;BAMUM LETTER PHASE-E GHEUX;Lo;0;L;;;;;N;;;;; 16989;BAMUM LETTER PHASE-E NGKEUAEM;Lo;0;L;;;;;N;;;;; 1698A;BAMUM LETTER PHASE-E NJAEMLI;Lo;0;L;;;;;N;;;;; 1698B;BAMUM LETTER PHASE-E MAP;Lo;0;L;;;;;N;;;;; 1698C;BAMUM LETTER PHASE-E LOOT;Lo;0;L;;;;;N;;;;; 1698D;BAMUM LETTER PHASE-E NGGEEEE;Lo;0;L;;;;;N;;;;; 1698E;BAMUM LETTER PHASE-E NDIQ;Lo;0;L;;;;;N;;;;; 1698F;BAMUM LETTER PHASE-E TAEN NTEUM;Lo;0;L;;;;;N;;;;; 16990;BAMUM LETTER PHASE-E SET;Lo;0;L;;;;;N;;;;; 16991;BAMUM LETTER PHASE-E PUM;Lo;0;L;;;;;N;;;;; 16992;BAMUM LETTER PHASE-E NDAA SOFTNESS;Lo;0;L;;;;;N;;;;; 16993;BAMUM LETTER PHASE-E NGGUAESHAE NYAM;Lo;0;L;;;;;N;;;;; 16994;BAMUM LETTER PHASE-E YIEE;Lo;0;L;;;;;N;;;;; 16995;BAMUM LETTER PHASE-E GHEUN;Lo;0;L;;;;;N;;;;; 16996;BAMUM LETTER PHASE-E TUAE;Lo;0;L;;;;;N;;;;; 16997;BAMUM LETTER PHASE-E YEUAE;Lo;0;L;;;;;N;;;;; 16998;BAMUM LETTER PHASE-E PO;Lo;0;L;;;;;N;;;;; 16999;BAMUM LETTER PHASE-E TUMAE;Lo;0;L;;;;;N;;;;; 1699A;BAMUM LETTER PHASE-E KEUAE;Lo;0;L;;;;;N;;;;; 1699B;BAMUM LETTER PHASE-E SUAEN;Lo;0;L;;;;;N;;;;; 1699C;BAMUM LETTER PHASE-E TEUAEQ;Lo;0;L;;;;;N;;;;; 1699D;BAMUM LETTER PHASE-E VEUAE;Lo;0;L;;;;;N;;;;; 1699E;BAMUM LETTER PHASE-E WEUX;Lo;0;L;;;;;N;;;;; 1699F;BAMUM LETTER PHASE-E LAAM;Lo;0;L;;;;;N;;;;; 169A0;BAMUM LETTER PHASE-E PU;Lo;0;L;;;;;N;;;;; 169A1;BAMUM LETTER PHASE-E TAAQ;Lo;0;L;;;;;N;;;;; 169A2;BAMUM LETTER PHASE-E GHAAMAE;Lo;0;L;;;;;N;;;;; 169A3;BAMUM LETTER PHASE-E NGEUREUT;Lo;0;L;;;;;N;;;;; 169A4;BAMUM LETTER PHASE-E SHEUAEQ;Lo;0;L;;;;;N;;;;; 169A5;BAMUM LETTER PHASE-E MGBEN;Lo;0;L;;;;;N;;;;; 169A6;BAMUM LETTER PHASE-E MBEE;Lo;0;L;;;;;N;;;;; 169A7;BAMUM LETTER PHASE-E NZAQ;Lo;0;L;;;;;N;;;;; 169A8;BAMUM LETTER PHASE-E NKOM;Lo;0;L;;;;;N;;;;; 169A9;BAMUM LETTER PHASE-E GBET;Lo;0;L;;;;;N;;;;; 169AA;BAMUM LETTER PHASE-E TUM;Lo;0;L;;;;;N;;;;; 169AB;BAMUM LETTER PHASE-E KUET;Lo;0;L;;;;;N;;;;; 169AC;BAMUM LETTER PHASE-E YAP;Lo;0;L;;;;;N;;;;; 169AD;BAMUM LETTER PHASE-E NYI CLEAVER;Lo;0;L;;;;;N;;;;; 169AE;BAMUM LETTER PHASE-E YIT;Lo;0;L;;;;;N;;;;; 169AF;BAMUM LETTER PHASE-E MFEUQ;Lo;0;L;;;;;N;;;;; 169B0;BAMUM LETTER PHASE-E NDIAQ;Lo;0;L;;;;;N;;;;; 169B1;BAMUM LETTER PHASE-E PIEEQ;Lo;0;L;;;;;N;;;;; 169B2;BAMUM LETTER PHASE-E YUEQ;Lo;0;L;;;;;N;;;;; 169B3;BAMUM LETTER PHASE-E LEUAEM;Lo;0;L;;;;;N;;;;; 169B4;BAMUM LETTER PHASE-E FUE;Lo;0;L;;;;;N;;;;; 169B5;BAMUM LETTER PHASE-E GBEUX;Lo;0;L;;;;;N;;;;; 169B6;BAMUM LETTER PHASE-E NGKUP;Lo;0;L;;;;;N;;;;; 169B7;BAMUM LETTER PHASE-E KET;Lo;0;L;;;;;N;;;;; 169B8;BAMUM LETTER PHASE-E MAE;Lo;0;L;;;;;N;;;;; 169B9;BAMUM LETTER PHASE-E NGKAAMI;Lo;0;L;;;;;N;;;;; 169BA;BAMUM LETTER PHASE-E GHET;Lo;0;L;;;;;N;;;;; 169BB;BAMUM LETTER PHASE-E FA;Lo;0;L;;;;;N;;;;; 169BC;BAMUM LETTER PHASE-E NTUM;Lo;0;L;;;;;N;;;;; 169BD;BAMUM LETTER PHASE-E PEUT;Lo;0;L;;;;;N;;;;; 169BE;BAMUM LETTER PHASE-E YEUM;Lo;0;L;;;;;N;;;;; 169BF;BAMUM LETTER PHASE-E NGGEUAE;Lo;0;L;;;;;N;;;;; 169C0;BAMUM LETTER PHASE-E NYI BETWEEN;Lo;0;L;;;;;N;;;;; 169C1;BAMUM LETTER PHASE-E NZUQ;Lo;0;L;;;;;N;;;;; 169C2;BAMUM LETTER PHASE-E POON;Lo;0;L;;;;;N;;;;; 169C3;BAMUM LETTER PHASE-E MIEE;Lo;0;L;;;;;N;;;;; 169C4;BAMUM LETTER PHASE-E FUET;Lo;0;L;;;;;N;;;;; 169C5;BAMUM LETTER PHASE-E NAE;Lo;0;L;;;;;N;;;;; 169C6;BAMUM LETTER PHASE-E MUAE;Lo;0;L;;;;;N;;;;; 169C7;BAMUM LETTER PHASE-E GHEUAE;Lo;0;L;;;;;N;;;;; 169C8;BAMUM LETTER PHASE-E FU I;Lo;0;L;;;;;N;;;;; 169C9;BAMUM LETTER PHASE-E MVI;Lo;0;L;;;;;N;;;;; 169CA;BAMUM LETTER PHASE-E PUAQ;Lo;0;L;;;;;N;;;;; 169CB;BAMUM LETTER PHASE-E NGKUM;Lo;0;L;;;;;N;;;;; 169CC;BAMUM LETTER PHASE-E KUT;Lo;0;L;;;;;N;;;;; 169CD;BAMUM LETTER PHASE-E PIET;Lo;0;L;;;;;N;;;;; 169CE;BAMUM LETTER PHASE-E NTAP;Lo;0;L;;;;;N;;;;; 169CF;BAMUM LETTER PHASE-E YEUAET;Lo;0;L;;;;;N;;;;; 169D0;BAMUM LETTER PHASE-E NGGUP;Lo;0;L;;;;;N;;;;; 169D1;BAMUM LETTER PHASE-E PA PEOPLE;Lo;0;L;;;;;N;;;;; 169D2;BAMUM LETTER PHASE-E FU CALL;Lo;0;L;;;;;N;;;;; 169D3;BAMUM LETTER PHASE-E FOM;Lo;0;L;;;;;N;;;;; 169D4;BAMUM LETTER PHASE-E NJEE;Lo;0;L;;;;;N;;;;; 169D5;BAMUM LETTER PHASE-E A;Lo;0;L;;;;;N;;;;; 169D6;BAMUM LETTER PHASE-E TOQ;Lo;0;L;;;;;N;;;;; 169D7;BAMUM LETTER PHASE-E O;Lo;0;L;;;;;N;;;;; 169D8;BAMUM LETTER PHASE-E I;Lo;0;L;;;;;N;;;;; 169D9;BAMUM LETTER PHASE-E LAQ;Lo;0;L;;;;;N;;;;; 169DA;BAMUM LETTER PHASE-E PA PLURAL;Lo;0;L;;;;;N;;;;; 169DB;BAMUM LETTER PHASE-E TAA;Lo;0;L;;;;;N;;;;; 169DC;BAMUM LETTER PHASE-E TAQ;Lo;0;L;;;;;N;;;;; 169DD;BAMUM LETTER PHASE-E NDAA MY HOUSE;Lo;0;L;;;;;N;;;;; 169DE;BAMUM LETTER PHASE-E SHIQ;Lo;0;L;;;;;N;;;;; 169DF;BAMUM LETTER PHASE-E YEUX;Lo;0;L;;;;;N;;;;; 169E0;BAMUM LETTER PHASE-E NGUAE;Lo;0;L;;;;;N;;;;; 169E1;BAMUM LETTER PHASE-E YUAEN;Lo;0;L;;;;;N;;;;; 169E2;BAMUM LETTER PHASE-E YOQ SWIMMING;Lo;0;L;;;;;N;;;;; 169E3;BAMUM LETTER PHASE-E YOQ COVER;Lo;0;L;;;;;N;;;;; 169E4;BAMUM LETTER PHASE-E YUQ;Lo;0;L;;;;;N;;;;; 169E5;BAMUM LETTER PHASE-E YUN;Lo;0;L;;;;;N;;;;; 169E6;BAMUM LETTER PHASE-E KEUX;Lo;0;L;;;;;N;;;;; 169E7;BAMUM LETTER PHASE-E PEUX;Lo;0;L;;;;;N;;;;; 169E8;BAMUM LETTER PHASE-E NJEE EPOCH;Lo;0;L;;;;;N;;;;; 169E9;BAMUM LETTER PHASE-E PUE;Lo;0;L;;;;;N;;;;; 169EA;BAMUM LETTER PHASE-E WUE;Lo;0;L;;;;;N;;;;; 169EB;BAMUM LETTER PHASE-E FEE;Lo;0;L;;;;;N;;;;; 169EC;BAMUM LETTER PHASE-E VEE;Lo;0;L;;;;;N;;;;; 169ED;BAMUM LETTER PHASE-E LU;Lo;0;L;;;;;N;;;;; 169EE;BAMUM LETTER PHASE-E MI;Lo;0;L;;;;;N;;;;; 169EF;BAMUM LETTER PHASE-E REUX;Lo;0;L;;;;;N;;;;; 169F0;BAMUM LETTER PHASE-E RAE;Lo;0;L;;;;;N;;;;; 169F1;BAMUM LETTER PHASE-E NGUAET;Lo;0;L;;;;;N;;;;; 169F2;BAMUM LETTER PHASE-E NGA;Lo;0;L;;;;;N;;;;; 169F3;BAMUM LETTER PHASE-E SHO;Lo;0;L;;;;;N;;;;; 169F4;BAMUM LETTER PHASE-E SHOQ;Lo;0;L;;;;;N;;;;; 169F5;BAMUM LETTER PHASE-E FU REMEDY;Lo;0;L;;;;;N;;;;; 169F6;BAMUM LETTER PHASE-E NA;Lo;0;L;;;;;N;;;;; 169F7;BAMUM LETTER PHASE-E PI;Lo;0;L;;;;;N;;;;; 169F8;BAMUM LETTER PHASE-E LOQ;Lo;0;L;;;;;N;;;;; 169F9;BAMUM LETTER PHASE-E KO;Lo;0;L;;;;;N;;;;; 169FA;BAMUM LETTER PHASE-E MEN;Lo;0;L;;;;;N;;;;; 169FB;BAMUM LETTER PHASE-E MA;Lo;0;L;;;;;N;;;;; 169FC;BAMUM LETTER PHASE-E MAQ;Lo;0;L;;;;;N;;;;; 169FD;BAMUM LETTER PHASE-E TEU;Lo;0;L;;;;;N;;;;; 169FE;BAMUM LETTER PHASE-E KI;Lo;0;L;;;;;N;;;;; 169FF;BAMUM LETTER PHASE-E MON;Lo;0;L;;;;;N;;;;; 16A00;BAMUM LETTER PHASE-E TEN;Lo;0;L;;;;;N;;;;; 16A01;BAMUM LETTER PHASE-E FAQ;Lo;0;L;;;;;N;;;;; 16A02;BAMUM LETTER PHASE-E GHOM;Lo;0;L;;;;;N;;;;; 16A03;BAMUM LETTER PHASE-F KA;Lo;0;L;;;;;N;;;;; 16A04;BAMUM LETTER PHASE-F U;Lo;0;L;;;;;N;;;;; 16A05;BAMUM LETTER PHASE-F KU;Lo;0;L;;;;;N;;;;; 16A06;BAMUM LETTER PHASE-F EE;Lo;0;L;;;;;N;;;;; 16A07;BAMUM LETTER PHASE-F REE;Lo;0;L;;;;;N;;;;; 16A08;BAMUM LETTER PHASE-F TAE;Lo;0;L;;;;;N;;;;; 16A09;BAMUM LETTER PHASE-F NYI;Lo;0;L;;;;;N;;;;; 16A0A;BAMUM LETTER PHASE-F LA;Lo;0;L;;;;;N;;;;; 16A0B;BAMUM LETTER PHASE-F RII;Lo;0;L;;;;;N;;;;; 16A0C;BAMUM LETTER PHASE-F RIEE;Lo;0;L;;;;;N;;;;; 16A0D;BAMUM LETTER PHASE-F MEEEE;Lo;0;L;;;;;N;;;;; 16A0E;BAMUM LETTER PHASE-F TAA;Lo;0;L;;;;;N;;;;; 16A0F;BAMUM LETTER PHASE-F NDAA;Lo;0;L;;;;;N;;;;; 16A10;BAMUM LETTER PHASE-F NJAEM;Lo;0;L;;;;;N;;;;; 16A11;BAMUM LETTER PHASE-F M;Lo;0;L;;;;;N;;;;; 16A12;BAMUM LETTER PHASE-F SUU;Lo;0;L;;;;;N;;;;; 16A13;BAMUM LETTER PHASE-F SHII;Lo;0;L;;;;;N;;;;; 16A14;BAMUM LETTER PHASE-F SI;Lo;0;L;;;;;N;;;;; 16A15;BAMUM LETTER PHASE-F SEUX;Lo;0;L;;;;;N;;;;; 16A16;BAMUM LETTER PHASE-F KYEE;Lo;0;L;;;;;N;;;;; 16A17;BAMUM LETTER PHASE-F KET;Lo;0;L;;;;;N;;;;; 16A18;BAMUM LETTER PHASE-F NUAE;Lo;0;L;;;;;N;;;;; 16A19;BAMUM LETTER PHASE-F NU;Lo;0;L;;;;;N;;;;; 16A1A;BAMUM LETTER PHASE-F NJUAE;Lo;0;L;;;;;N;;;;; 16A1B;BAMUM LETTER PHASE-F YOQ;Lo;0;L;;;;;N;;;;; 16A1C;BAMUM LETTER PHASE-F SHU;Lo;0;L;;;;;N;;;;; 16A1D;BAMUM LETTER PHASE-F YA;Lo;0;L;;;;;N;;;;; 16A1E;BAMUM LETTER PHASE-F NSHA;Lo;0;L;;;;;N;;;;; 16A1F;BAMUM LETTER PHASE-F PEUX;Lo;0;L;;;;;N;;;;; 16A20;BAMUM LETTER PHASE-F NTEE;Lo;0;L;;;;;N;;;;; 16A21;BAMUM LETTER PHASE-F WUE;Lo;0;L;;;;;N;;;;; 16A22;BAMUM LETTER PHASE-F PEE;Lo;0;L;;;;;N;;;;; 16A23;BAMUM LETTER PHASE-F RU;Lo;0;L;;;;;N;;;;; 16A24;BAMUM LETTER PHASE-F NI;Lo;0;L;;;;;N;;;;; 16A25;BAMUM LETTER PHASE-F REUX;Lo;0;L;;;;;N;;;;; 16A26;BAMUM LETTER PHASE-F KEN;Lo;0;L;;;;;N;;;;; 16A27;BAMUM LETTER PHASE-F NGKWAEN;Lo;0;L;;;;;N;;;;; 16A28;BAMUM LETTER PHASE-F NGGA;Lo;0;L;;;;;N;;;;; 16A29;BAMUM LETTER PHASE-F SHO;Lo;0;L;;;;;N;;;;; 16A2A;BAMUM LETTER PHASE-F PUAE;Lo;0;L;;;;;N;;;;; 16A2B;BAMUM LETTER PHASE-F FOM;Lo;0;L;;;;;N;;;;; 16A2C;BAMUM LETTER PHASE-F WA;Lo;0;L;;;;;N;;;;; 16A2D;BAMUM LETTER PHASE-F LI;Lo;0;L;;;;;N;;;;; 16A2E;BAMUM LETTER PHASE-F LOQ;Lo;0;L;;;;;N;;;;; 16A2F;BAMUM LETTER PHASE-F KO;Lo;0;L;;;;;N;;;;; 16A30;BAMUM LETTER PHASE-F MBEN;Lo;0;L;;;;;N;;;;; 16A31;BAMUM LETTER PHASE-F REN;Lo;0;L;;;;;N;;;;; 16A32;BAMUM LETTER PHASE-F MA;Lo;0;L;;;;;N;;;;; 16A33;BAMUM LETTER PHASE-F MO;Lo;0;L;;;;;N;;;;; 16A34;BAMUM LETTER PHASE-F MBAA;Lo;0;L;;;;;N;;;;; 16A35;BAMUM LETTER PHASE-F TET;Lo;0;L;;;;;N;;;;; 16A36;BAMUM LETTER PHASE-F KPA;Lo;0;L;;;;;N;;;;; 16A37;BAMUM LETTER PHASE-F SAMBA;Lo;0;L;;;;;N;;;;; 16A38;BAMUM LETTER PHASE-F VUEQ;Lo;0;L;;;;;N;;;;; 16A40;MRO LETTER TA;Lo;0;L;;;;;N;;;;; 16A41;MRO LETTER NGI;Lo;0;L;;;;;N;;;;; 16A42;MRO LETTER YO;Lo;0;L;;;;;N;;;;; 16A43;MRO LETTER MIM;Lo;0;L;;;;;N;;;;; 16A44;MRO LETTER BA;Lo;0;L;;;;;N;;;;; 16A45;MRO LETTER DA;Lo;0;L;;;;;N;;;;; 16A46;MRO LETTER A;Lo;0;L;;;;;N;;;;; 16A47;MRO LETTER PHI;Lo;0;L;;;;;N;;;;; 16A48;MRO LETTER KHAI;Lo;0;L;;;;;N;;;;; 16A49;MRO LETTER HAO;Lo;0;L;;;;;N;;;;; 16A4A;MRO LETTER DAI;Lo;0;L;;;;;N;;;;; 16A4B;MRO LETTER CHU;Lo;0;L;;;;;N;;;;; 16A4C;MRO LETTER KEAAE;Lo;0;L;;;;;N;;;;; 16A4D;MRO LETTER OL;Lo;0;L;;;;;N;;;;; 16A4E;MRO LETTER MAEM;Lo;0;L;;;;;N;;;;; 16A4F;MRO LETTER NIN;Lo;0;L;;;;;N;;;;; 16A50;MRO LETTER PA;Lo;0;L;;;;;N;;;;; 16A51;MRO LETTER OO;Lo;0;L;;;;;N;;;;; 16A52;MRO LETTER O;Lo;0;L;;;;;N;;;;; 16A53;MRO LETTER RO;Lo;0;L;;;;;N;;;;; 16A54;MRO LETTER SHI;Lo;0;L;;;;;N;;;;; 16A55;MRO LETTER THEA;Lo;0;L;;;;;N;;;;; 16A56;MRO LETTER EA;Lo;0;L;;;;;N;;;;; 16A57;MRO LETTER WA;Lo;0;L;;;;;N;;;;; 16A58;MRO LETTER E;Lo;0;L;;;;;N;;;;; 16A59;MRO LETTER KO;Lo;0;L;;;;;N;;;;; 16A5A;MRO LETTER LAN;Lo;0;L;;;;;N;;;;; 16A5B;MRO LETTER LA;Lo;0;L;;;;;N;;;;; 16A5C;MRO LETTER HAI;Lo;0;L;;;;;N;;;;; 16A5D;MRO LETTER RI;Lo;0;L;;;;;N;;;;; 16A5E;MRO LETTER TEK;Lo;0;L;;;;;N;;;;; 16A60;MRO DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 16A61;MRO DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 16A62;MRO DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 16A63;MRO DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 16A64;MRO DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 16A65;MRO DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 16A66;MRO DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 16A67;MRO DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 16A68;MRO DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 16A69;MRO DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 16A6E;MRO DANDA;Po;0;L;;;;;N;;;;; 16A6F;MRO DOUBLE DANDA;Po;0;L;;;;;N;;;;; 16AD0;BASSA VAH LETTER ENNI;Lo;0;L;;;;;N;;;;; 16AD1;BASSA VAH LETTER KA;Lo;0;L;;;;;N;;;;; 16AD2;BASSA VAH LETTER SE;Lo;0;L;;;;;N;;;;; 16AD3;BASSA VAH LETTER FA;Lo;0;L;;;;;N;;;;; 16AD4;BASSA VAH LETTER MBE;Lo;0;L;;;;;N;;;;; 16AD5;BASSA VAH LETTER YIE;Lo;0;L;;;;;N;;;;; 16AD6;BASSA VAH LETTER GAH;Lo;0;L;;;;;N;;;;; 16AD7;BASSA VAH LETTER DHII;Lo;0;L;;;;;N;;;;; 16AD8;BASSA VAH LETTER KPAH;Lo;0;L;;;;;N;;;;; 16AD9;BASSA VAH LETTER JO;Lo;0;L;;;;;N;;;;; 16ADA;BASSA VAH LETTER HWAH;Lo;0;L;;;;;N;;;;; 16ADB;BASSA VAH LETTER WA;Lo;0;L;;;;;N;;;;; 16ADC;BASSA VAH LETTER ZO;Lo;0;L;;;;;N;;;;; 16ADD;BASSA VAH LETTER GBU;Lo;0;L;;;;;N;;;;; 16ADE;BASSA VAH LETTER DO;Lo;0;L;;;;;N;;;;; 16ADF;BASSA VAH LETTER CE;Lo;0;L;;;;;N;;;;; 16AE0;BASSA VAH LETTER UWU;Lo;0;L;;;;;N;;;;; 16AE1;BASSA VAH LETTER TO;Lo;0;L;;;;;N;;;;; 16AE2;BASSA VAH LETTER BA;Lo;0;L;;;;;N;;;;; 16AE3;BASSA VAH LETTER VU;Lo;0;L;;;;;N;;;;; 16AE4;BASSA VAH LETTER YEIN;Lo;0;L;;;;;N;;;;; 16AE5;BASSA VAH LETTER PA;Lo;0;L;;;;;N;;;;; 16AE6;BASSA VAH LETTER WADDA;Lo;0;L;;;;;N;;;;; 16AE7;BASSA VAH LETTER A;Lo;0;L;;;;;N;;;;; 16AE8;BASSA VAH LETTER O;Lo;0;L;;;;;N;;;;; 16AE9;BASSA VAH LETTER OO;Lo;0;L;;;;;N;;;;; 16AEA;BASSA VAH LETTER U;Lo;0;L;;;;;N;;;;; 16AEB;BASSA VAH LETTER EE;Lo;0;L;;;;;N;;;;; 16AEC;BASSA VAH LETTER E;Lo;0;L;;;;;N;;;;; 16AED;BASSA VAH LETTER I;Lo;0;L;;;;;N;;;;; 16AF0;BASSA VAH COMBINING HIGH TONE;Mn;1;NSM;;;;;N;;;;; 16AF1;BASSA VAH COMBINING LOW TONE;Mn;1;NSM;;;;;N;;;;; 16AF2;BASSA VAH COMBINING MID TONE;Mn;1;NSM;;;;;N;;;;; 16AF3;BASSA VAH COMBINING LOW-MID TONE;Mn;1;NSM;;;;;N;;;;; 16AF4;BASSA VAH COMBINING HIGH-LOW TONE;Mn;1;NSM;;;;;N;;;;; 16AF5;BASSA VAH FULL STOP;Po;0;L;;;;;N;;;;; 16B00;PAHAWH HMONG VOWEL KEEB;Lo;0;L;;;;;N;;;;; 16B01;PAHAWH HMONG VOWEL KEEV;Lo;0;L;;;;;N;;;;; 16B02;PAHAWH HMONG VOWEL KIB;Lo;0;L;;;;;N;;;;; 16B03;PAHAWH HMONG VOWEL KIV;Lo;0;L;;;;;N;;;;; 16B04;PAHAWH HMONG VOWEL KAUB;Lo;0;L;;;;;N;;;;; 16B05;PAHAWH HMONG VOWEL KAUV;Lo;0;L;;;;;N;;;;; 16B06;PAHAWH HMONG VOWEL KUB;Lo;0;L;;;;;N;;;;; 16B07;PAHAWH HMONG VOWEL KUV;Lo;0;L;;;;;N;;;;; 16B08;PAHAWH HMONG VOWEL KEB;Lo;0;L;;;;;N;;;;; 16B09;PAHAWH HMONG VOWEL KEV;Lo;0;L;;;;;N;;;;; 16B0A;PAHAWH HMONG VOWEL KAIB;Lo;0;L;;;;;N;;;;; 16B0B;PAHAWH HMONG VOWEL KAIV;Lo;0;L;;;;;N;;;;; 16B0C;PAHAWH HMONG VOWEL KOOB;Lo;0;L;;;;;N;;;;; 16B0D;PAHAWH HMONG VOWEL KOOV;Lo;0;L;;;;;N;;;;; 16B0E;PAHAWH HMONG VOWEL KAWB;Lo;0;L;;;;;N;;;;; 16B0F;PAHAWH HMONG VOWEL KAWV;Lo;0;L;;;;;N;;;;; 16B10;PAHAWH HMONG VOWEL KUAB;Lo;0;L;;;;;N;;;;; 16B11;PAHAWH HMONG VOWEL KUAV;Lo;0;L;;;;;N;;;;; 16B12;PAHAWH HMONG VOWEL KOB;Lo;0;L;;;;;N;;;;; 16B13;PAHAWH HMONG VOWEL KOV;Lo;0;L;;;;;N;;;;; 16B14;PAHAWH HMONG VOWEL KIAB;Lo;0;L;;;;;N;;;;; 16B15;PAHAWH HMONG VOWEL KIAV;Lo;0;L;;;;;N;;;;; 16B16;PAHAWH HMONG VOWEL KAB;Lo;0;L;;;;;N;;;;; 16B17;PAHAWH HMONG VOWEL KAV;Lo;0;L;;;;;N;;;;; 16B18;PAHAWH HMONG VOWEL KWB;Lo;0;L;;;;;N;;;;; 16B19;PAHAWH HMONG VOWEL KWV;Lo;0;L;;;;;N;;;;; 16B1A;PAHAWH HMONG VOWEL KAAB;Lo;0;L;;;;;N;;;;; 16B1B;PAHAWH HMONG VOWEL KAAV;Lo;0;L;;;;;N;;;;; 16B1C;PAHAWH HMONG CONSONANT VAU;Lo;0;L;;;;;N;;;;; 16B1D;PAHAWH HMONG CONSONANT NTSAU;Lo;0;L;;;;;N;;;;; 16B1E;PAHAWH HMONG CONSONANT LAU;Lo;0;L;;;;;N;;;;; 16B1F;PAHAWH HMONG CONSONANT HAU;Lo;0;L;;;;;N;;;;; 16B20;PAHAWH HMONG CONSONANT NLAU;Lo;0;L;;;;;N;;;;; 16B21;PAHAWH HMONG CONSONANT RAU;Lo;0;L;;;;;N;;;;; 16B22;PAHAWH HMONG CONSONANT NKAU;Lo;0;L;;;;;N;;;;; 16B23;PAHAWH HMONG CONSONANT QHAU;Lo;0;L;;;;;N;;;;; 16B24;PAHAWH HMONG CONSONANT YAU;Lo;0;L;;;;;N;;;;; 16B25;PAHAWH HMONG CONSONANT HLAU;Lo;0;L;;;;;N;;;;; 16B26;PAHAWH HMONG CONSONANT MAU;Lo;0;L;;;;;N;;;;; 16B27;PAHAWH HMONG CONSONANT CHAU;Lo;0;L;;;;;N;;;;; 16B28;PAHAWH HMONG CONSONANT NCHAU;Lo;0;L;;;;;N;;;;; 16B29;PAHAWH HMONG CONSONANT HNAU;Lo;0;L;;;;;N;;;;; 16B2A;PAHAWH HMONG CONSONANT PLHAU;Lo;0;L;;;;;N;;;;; 16B2B;PAHAWH HMONG CONSONANT NTHAU;Lo;0;L;;;;;N;;;;; 16B2C;PAHAWH HMONG CONSONANT NAU;Lo;0;L;;;;;N;;;;; 16B2D;PAHAWH HMONG CONSONANT AU;Lo;0;L;;;;;N;;;;; 16B2E;PAHAWH HMONG CONSONANT XAU;Lo;0;L;;;;;N;;;;; 16B2F;PAHAWH HMONG CONSONANT CAU;Lo;0;L;;;;;N;;;;; 16B30;PAHAWH HMONG MARK CIM TUB;Mn;230;NSM;;;;;N;;;;; 16B31;PAHAWH HMONG MARK CIM SO;Mn;230;NSM;;;;;N;;;;; 16B32;PAHAWH HMONG MARK CIM KES;Mn;230;NSM;;;;;N;;;;; 16B33;PAHAWH HMONG MARK CIM KHAV;Mn;230;NSM;;;;;N;;;;; 16B34;PAHAWH HMONG MARK CIM SUAM;Mn;230;NSM;;;;;N;;;;; 16B35;PAHAWH HMONG MARK CIM HOM;Mn;230;NSM;;;;;N;;;;; 16B36;PAHAWH HMONG MARK CIM TAUM;Mn;230;NSM;;;;;N;;;;; 16B37;PAHAWH HMONG SIGN VOS THOM;Po;0;L;;;;;N;;;;; 16B38;PAHAWH HMONG SIGN VOS TSHAB CEEB;Po;0;L;;;;;N;;;;; 16B39;PAHAWH HMONG SIGN CIM CHEEM;Po;0;L;;;;;N;;;;; 16B3A;PAHAWH HMONG SIGN VOS THIAB;Po;0;L;;;;;N;;;;; 16B3B;PAHAWH HMONG SIGN VOS FEEM;Po;0;L;;;;;N;;;;; 16B3C;PAHAWH HMONG SIGN XYEEM NTXIV;So;0;L;;;;;N;;;;; 16B3D;PAHAWH HMONG SIGN XYEEM RHO;So;0;L;;;;;N;;;;; 16B3E;PAHAWH HMONG SIGN XYEEM TOV;So;0;L;;;;;N;;;;; 16B3F;PAHAWH HMONG SIGN XYEEM FAIB;So;0;L;;;;;N;;;;; 16B40;PAHAWH HMONG SIGN VOS SEEV;Lm;0;L;;;;;N;;;;; 16B41;PAHAWH HMONG SIGN MEEJ SUAB;Lm;0;L;;;;;N;;;;; 16B42;PAHAWH HMONG SIGN VOS NRUA;Lm;0;L;;;;;N;;;;; 16B43;PAHAWH HMONG SIGN IB YAM;Lm;0;L;;;;;N;;;;; 16B44;PAHAWH HMONG SIGN XAUS;Po;0;L;;;;;N;;;;; 16B45;PAHAWH HMONG SIGN CIM TSOV ROG;So;0;L;;;;;N;;;;; 16B50;PAHAWH HMONG DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; 16B51;PAHAWH HMONG DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; 16B52;PAHAWH HMONG DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; 16B53;PAHAWH HMONG DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; 16B54;PAHAWH HMONG DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; 16B55;PAHAWH HMONG DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; 16B56;PAHAWH HMONG DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; 16B57;PAHAWH HMONG DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 16B58;PAHAWH HMONG DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 16B59;PAHAWH HMONG DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 16B5B;PAHAWH HMONG NUMBER TENS;No;0;L;;;;10;N;;;;; 16B5C;PAHAWH HMONG NUMBER HUNDREDS;No;0;L;;;;100;N;;;;; 16B5D;PAHAWH HMONG NUMBER TEN THOUSANDS;No;0;L;;;;10000;N;;;;; 16B5E;PAHAWH HMONG NUMBER MILLIONS;No;0;L;;;;1000000;N;;;;; 16B5F;PAHAWH HMONG NUMBER HUNDRED MILLIONS;No;0;L;;;;100000000;N;;;;; 16B60;PAHAWH HMONG NUMBER TEN BILLIONS;No;0;L;;;;10000000000;N;;;;; 16B61;PAHAWH HMONG NUMBER TRILLIONS;No;0;L;;;;1000000000000;N;;;;; 16B63;PAHAWH HMONG SIGN VOS LUB;Lo;0;L;;;;;N;;;;; 16B64;PAHAWH HMONG SIGN XYOO;Lo;0;L;;;;;N;;;;; 16B65;PAHAWH HMONG SIGN HLI;Lo;0;L;;;;;N;;;;; 16B66;PAHAWH HMONG SIGN THIRD-STAGE HLI;Lo;0;L;;;;;N;;;;; 16B67;PAHAWH HMONG SIGN ZWJ THAJ;Lo;0;L;;;;;N;;;;; 16B68;PAHAWH HMONG SIGN HNUB;Lo;0;L;;;;;N;;;;; 16B69;PAHAWH HMONG SIGN NQIG;Lo;0;L;;;;;N;;;;; 16B6A;PAHAWH HMONG SIGN XIAB;Lo;0;L;;;;;N;;;;; 16B6B;PAHAWH HMONG SIGN NTUJ;Lo;0;L;;;;;N;;;;; 16B6C;PAHAWH HMONG SIGN AV;Lo;0;L;;;;;N;;;;; 16B6D;PAHAWH HMONG SIGN TXHEEJ CEEV;Lo;0;L;;;;;N;;;;; 16B6E;PAHAWH HMONG SIGN MEEJ TSEEB;Lo;0;L;;;;;N;;;;; 16B6F;PAHAWH HMONG SIGN TAU;Lo;0;L;;;;;N;;;;; 16B70;PAHAWH HMONG SIGN LOS;Lo;0;L;;;;;N;;;;; 16B71;PAHAWH HMONG SIGN MUS;Lo;0;L;;;;;N;;;;; 16B72;PAHAWH HMONG SIGN CIM HAIS LUS NTOG NTOG;Lo;0;L;;;;;N;;;;; 16B73;PAHAWH HMONG SIGN CIM CUAM TSHOOJ;Lo;0;L;;;;;N;;;;; 16B74;PAHAWH HMONG SIGN CIM TXWV;Lo;0;L;;;;;N;;;;; 16B75;PAHAWH HMONG SIGN CIM TXWV CHWV;Lo;0;L;;;;;N;;;;; 16B76;PAHAWH HMONG SIGN CIM PUB DAWB;Lo;0;L;;;;;N;;;;; 16B77;PAHAWH HMONG SIGN CIM NRES TOS;Lo;0;L;;;;;N;;;;; 16B7D;PAHAWH HMONG CLAN SIGN TSHEEJ;Lo;0;L;;;;;N;;;;; 16B7E;PAHAWH HMONG CLAN SIGN YEEG;Lo;0;L;;;;;N;;;;; 16B7F;PAHAWH HMONG CLAN SIGN LIS;Lo;0;L;;;;;N;;;;; 16B80;PAHAWH HMONG CLAN SIGN LAUJ;Lo;0;L;;;;;N;;;;; 16B81;PAHAWH HMONG CLAN SIGN XYOOJ;Lo;0;L;;;;;N;;;;; 16B82;PAHAWH HMONG CLAN SIGN KOO;Lo;0;L;;;;;N;;;;; 16B83;PAHAWH HMONG CLAN SIGN HAWJ;Lo;0;L;;;;;N;;;;; 16B84;PAHAWH HMONG CLAN SIGN MUAS;Lo;0;L;;;;;N;;;;; 16B85;PAHAWH HMONG CLAN SIGN THOJ;Lo;0;L;;;;;N;;;;; 16B86;PAHAWH HMONG CLAN SIGN TSAB;Lo;0;L;;;;;N;;;;; 16B87;PAHAWH HMONG CLAN SIGN PHAB;Lo;0;L;;;;;N;;;;; 16B88;PAHAWH HMONG CLAN SIGN KHAB;Lo;0;L;;;;;N;;;;; 16B89;PAHAWH HMONG CLAN SIGN HAM;Lo;0;L;;;;;N;;;;; 16B8A;PAHAWH HMONG CLAN SIGN VAJ;Lo;0;L;;;;;N;;;;; 16B8B;PAHAWH HMONG CLAN SIGN FAJ;Lo;0;L;;;;;N;;;;; 16B8C;PAHAWH HMONG CLAN SIGN YAJ;Lo;0;L;;;;;N;;;;; 16B8D;PAHAWH HMONG CLAN SIGN TSWB;Lo;0;L;;;;;N;;;;; 16B8E;PAHAWH HMONG CLAN SIGN KWM;Lo;0;L;;;;;N;;;;; 16B8F;PAHAWH HMONG CLAN SIGN VWJ;Lo;0;L;;;;;N;;;;; 16F00;MIAO LETTER PA;Lo;0;L;;;;;N;;;;; 16F01;MIAO LETTER BA;Lo;0;L;;;;;N;;;;; 16F02;MIAO LETTER YI PA;Lo;0;L;;;;;N;;;;; 16F03;MIAO LETTER PLA;Lo;0;L;;;;;N;;;;; 16F04;MIAO LETTER MA;Lo;0;L;;;;;N;;;;; 16F05;MIAO LETTER MHA;Lo;0;L;;;;;N;;;;; 16F06;MIAO LETTER ARCHAIC MA;Lo;0;L;;;;;N;;;;; 16F07;MIAO LETTER FA;Lo;0;L;;;;;N;;;;; 16F08;MIAO LETTER VA;Lo;0;L;;;;;N;;;;; 16F09;MIAO LETTER VFA;Lo;0;L;;;;;N;;;;; 16F0A;MIAO LETTER TA;Lo;0;L;;;;;N;;;;; 16F0B;MIAO LETTER DA;Lo;0;L;;;;;N;;;;; 16F0C;MIAO LETTER YI TTA;Lo;0;L;;;;;N;;;;; 16F0D;MIAO LETTER YI TA;Lo;0;L;;;;;N;;;;; 16F0E;MIAO LETTER TTA;Lo;0;L;;;;;N;;;;; 16F0F;MIAO LETTER DDA;Lo;0;L;;;;;N;;;;; 16F10;MIAO LETTER NA;Lo;0;L;;;;;N;;;;; 16F11;MIAO LETTER NHA;Lo;0;L;;;;;N;;;;; 16F12;MIAO LETTER YI NNA;Lo;0;L;;;;;N;;;;; 16F13;MIAO LETTER ARCHAIC NA;Lo;0;L;;;;;N;;;;; 16F14;MIAO LETTER NNA;Lo;0;L;;;;;N;;;;; 16F15;MIAO LETTER NNHA;Lo;0;L;;;;;N;;;;; 16F16;MIAO LETTER LA;Lo;0;L;;;;;N;;;;; 16F17;MIAO LETTER LYA;Lo;0;L;;;;;N;;;;; 16F18;MIAO LETTER LHA;Lo;0;L;;;;;N;;;;; 16F19;MIAO LETTER LHYA;Lo;0;L;;;;;N;;;;; 16F1A;MIAO LETTER TLHA;Lo;0;L;;;;;N;;;;; 16F1B;MIAO LETTER DLHA;Lo;0;L;;;;;N;;;;; 16F1C;MIAO LETTER TLHYA;Lo;0;L;;;;;N;;;;; 16F1D;MIAO LETTER DLHYA;Lo;0;L;;;;;N;;;;; 16F1E;MIAO LETTER KA;Lo;0;L;;;;;N;;;;; 16F1F;MIAO LETTER GA;Lo;0;L;;;;;N;;;;; 16F20;MIAO LETTER YI KA;Lo;0;L;;;;;N;;;;; 16F21;MIAO LETTER QA;Lo;0;L;;;;;N;;;;; 16F22;MIAO LETTER QGA;Lo;0;L;;;;;N;;;;; 16F23;MIAO LETTER NGA;Lo;0;L;;;;;N;;;;; 16F24;MIAO LETTER NGHA;Lo;0;L;;;;;N;;;;; 16F25;MIAO LETTER ARCHAIC NGA;Lo;0;L;;;;;N;;;;; 16F26;MIAO LETTER HA;Lo;0;L;;;;;N;;;;; 16F27;MIAO LETTER XA;Lo;0;L;;;;;N;;;;; 16F28;MIAO LETTER GHA;Lo;0;L;;;;;N;;;;; 16F29;MIAO LETTER GHHA;Lo;0;L;;;;;N;;;;; 16F2A;MIAO LETTER TSSA;Lo;0;L;;;;;N;;;;; 16F2B;MIAO LETTER DZZA;Lo;0;L;;;;;N;;;;; 16F2C;MIAO LETTER NYA;Lo;0;L;;;;;N;;;;; 16F2D;MIAO LETTER NYHA;Lo;0;L;;;;;N;;;;; 16F2E;MIAO LETTER TSHA;Lo;0;L;;;;;N;;;;; 16F2F;MIAO LETTER DZHA;Lo;0;L;;;;;N;;;;; 16F30;MIAO LETTER YI TSHA;Lo;0;L;;;;;N;;;;; 16F31;MIAO LETTER YI DZHA;Lo;0;L;;;;;N;;;;; 16F32;MIAO LETTER REFORMED TSHA;Lo;0;L;;;;;N;;;;; 16F33;MIAO LETTER SHA;Lo;0;L;;;;;N;;;;; 16F34;MIAO LETTER SSA;Lo;0;L;;;;;N;;;;; 16F35;MIAO LETTER ZHA;Lo;0;L;;;;;N;;;;; 16F36;MIAO LETTER ZSHA;Lo;0;L;;;;;N;;;;; 16F37;MIAO LETTER TSA;Lo;0;L;;;;;N;;;;; 16F38;MIAO LETTER DZA;Lo;0;L;;;;;N;;;;; 16F39;MIAO LETTER YI TSA;Lo;0;L;;;;;N;;;;; 16F3A;MIAO LETTER SA;Lo;0;L;;;;;N;;;;; 16F3B;MIAO LETTER ZA;Lo;0;L;;;;;N;;;;; 16F3C;MIAO LETTER ZSA;Lo;0;L;;;;;N;;;;; 16F3D;MIAO LETTER ZZA;Lo;0;L;;;;;N;;;;; 16F3E;MIAO LETTER ZZSA;Lo;0;L;;;;;N;;;;; 16F3F;MIAO LETTER ARCHAIC ZZA;Lo;0;L;;;;;N;;;;; 16F40;MIAO LETTER ZZYA;Lo;0;L;;;;;N;;;;; 16F41;MIAO LETTER ZZSYA;Lo;0;L;;;;;N;;;;; 16F42;MIAO LETTER WA;Lo;0;L;;;;;N;;;;; 16F43;MIAO LETTER AH;Lo;0;L;;;;;N;;;;; 16F44;MIAO LETTER HHA;Lo;0;L;;;;;N;;;;; 16F50;MIAO LETTER NASALIZATION;Lo;0;L;;;;;N;;;;; 16F51;MIAO SIGN ASPIRATION;Mc;0;L;;;;;N;;;;; 16F52;MIAO SIGN REFORMED VOICING;Mc;0;L;;;;;N;;;;; 16F53;MIAO SIGN REFORMED ASPIRATION;Mc;0;L;;;;;N;;;;; 16F54;MIAO VOWEL SIGN A;Mc;0;L;;;;;N;;;;; 16F55;MIAO VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 16F56;MIAO VOWEL SIGN AHH;Mc;0;L;;;;;N;;;;; 16F57;MIAO VOWEL SIGN AN;Mc;0;L;;;;;N;;;;; 16F58;MIAO VOWEL SIGN ANG;Mc;0;L;;;;;N;;;;; 16F59;MIAO VOWEL SIGN O;Mc;0;L;;;;;N;;;;; 16F5A;MIAO VOWEL SIGN OO;Mc;0;L;;;;;N;;;;; 16F5B;MIAO VOWEL SIGN WO;Mc;0;L;;;;;N;;;;; 16F5C;MIAO VOWEL SIGN W;Mc;0;L;;;;;N;;;;; 16F5D;MIAO VOWEL SIGN E;Mc;0;L;;;;;N;;;;; 16F5E;MIAO VOWEL SIGN EN;Mc;0;L;;;;;N;;;;; 16F5F;MIAO VOWEL SIGN ENG;Mc;0;L;;;;;N;;;;; 16F60;MIAO VOWEL SIGN OEY;Mc;0;L;;;;;N;;;;; 16F61;MIAO VOWEL SIGN I;Mc;0;L;;;;;N;;;;; 16F62;MIAO VOWEL SIGN IA;Mc;0;L;;;;;N;;;;; 16F63;MIAO VOWEL SIGN IAN;Mc;0;L;;;;;N;;;;; 16F64;MIAO VOWEL SIGN IANG;Mc;0;L;;;;;N;;;;; 16F65;MIAO VOWEL SIGN IO;Mc;0;L;;;;;N;;;;; 16F66;MIAO VOWEL SIGN IE;Mc;0;L;;;;;N;;;;; 16F67;MIAO VOWEL SIGN II;Mc;0;L;;;;;N;;;;; 16F68;MIAO VOWEL SIGN IU;Mc;0;L;;;;;N;;;;; 16F69;MIAO VOWEL SIGN ING;Mc;0;L;;;;;N;;;;; 16F6A;MIAO VOWEL SIGN U;Mc;0;L;;;;;N;;;;; 16F6B;MIAO VOWEL SIGN UA;Mc;0;L;;;;;N;;;;; 16F6C;MIAO VOWEL SIGN UAN;Mc;0;L;;;;;N;;;;; 16F6D;MIAO VOWEL SIGN UANG;Mc;0;L;;;;;N;;;;; 16F6E;MIAO VOWEL SIGN UU;Mc;0;L;;;;;N;;;;; 16F6F;MIAO VOWEL SIGN UEI;Mc;0;L;;;;;N;;;;; 16F70;MIAO VOWEL SIGN UNG;Mc;0;L;;;;;N;;;;; 16F71;MIAO VOWEL SIGN Y;Mc;0;L;;;;;N;;;;; 16F72;MIAO VOWEL SIGN YI;Mc;0;L;;;;;N;;;;; 16F73;MIAO VOWEL SIGN AE;Mc;0;L;;;;;N;;;;; 16F74;MIAO VOWEL SIGN AEE;Mc;0;L;;;;;N;;;;; 16F75;MIAO VOWEL SIGN ERR;Mc;0;L;;;;;N;;;;; 16F76;MIAO VOWEL SIGN ROUNDED ERR;Mc;0;L;;;;;N;;;;; 16F77;MIAO VOWEL SIGN ER;Mc;0;L;;;;;N;;;;; 16F78;MIAO VOWEL SIGN ROUNDED ER;Mc;0;L;;;;;N;;;;; 16F79;MIAO VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; 16F7A;MIAO VOWEL SIGN EI;Mc;0;L;;;;;N;;;;; 16F7B;MIAO VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; 16F7C;MIAO VOWEL SIGN OU;Mc;0;L;;;;;N;;;;; 16F7D;MIAO VOWEL SIGN N;Mc;0;L;;;;;N;;;;; 16F7E;MIAO VOWEL SIGN NG;Mc;0;L;;;;;N;;;;; 16F8F;MIAO TONE RIGHT;Mn;0;NSM;;;;;N;;;;; 16F90;MIAO TONE TOP RIGHT;Mn;0;NSM;;;;;N;;;;; 16F91;MIAO TONE ABOVE;Mn;0;NSM;;;;;N;;;;; 16F92;MIAO TONE BELOW;Mn;0;NSM;;;;;N;;;;; 16F93;MIAO LETTER TONE-2;Lm;0;L;;;;;N;;;;; 16F94;MIAO LETTER TONE-3;Lm;0;L;;;;;N;;;;; 16F95;MIAO LETTER TONE-4;Lm;0;L;;;;;N;;;;; 16F96;MIAO LETTER TONE-5;Lm;0;L;;;;;N;;;;; 16F97;MIAO LETTER TONE-6;Lm;0;L;;;;;N;;;;; 16F98;MIAO LETTER TONE-7;Lm;0;L;;;;;N;;;;; 16F99;MIAO LETTER TONE-8;Lm;0;L;;;;;N;;;;; 16F9A;MIAO LETTER REFORMED TONE-1;Lm;0;L;;;;;N;;;;; 16F9B;MIAO LETTER REFORMED TONE-2;Lm;0;L;;;;;N;;;;; 16F9C;MIAO LETTER REFORMED TONE-4;Lm;0;L;;;;;N;;;;; 16F9D;MIAO LETTER REFORMED TONE-5;Lm;0;L;;;;;N;;;;; 16F9E;MIAO LETTER REFORMED TONE-6;Lm;0;L;;;;;N;;;;; 16F9F;MIAO LETTER REFORMED TONE-8;Lm;0;L;;;;;N;;;;; 16FE0;TANGUT ITERATION MARK;Lm;0;L;;;;;N;;;;; 17000;<Tangut Ideograph, First>;Lo;0;L;;;;;N;;;;; 187EC;<Tangut Ideograph, Last>;Lo;0;L;;;;;N;;;;; 18800;TANGUT COMPONENT-001;Lo;0;L;;;;;N;;;;; 18801;TANGUT COMPONENT-002;Lo;0;L;;;;;N;;;;; 18802;TANGUT COMPONENT-003;Lo;0;L;;;;;N;;;;; 18803;TANGUT COMPONENT-004;Lo;0;L;;;;;N;;;;; 18804;TANGUT COMPONENT-005;Lo;0;L;;;;;N;;;;; 18805;TANGUT COMPONENT-006;Lo;0;L;;;;;N;;;;; 18806;TANGUT COMPONENT-007;Lo;0;L;;;;;N;;;;; 18807;TANGUT COMPONENT-008;Lo;0;L;;;;;N;;;;; 18808;TANGUT COMPONENT-009;Lo;0;L;;;;;N;;;;; 18809;TANGUT COMPONENT-010;Lo;0;L;;;;;N;;;;; 1880A;TANGUT COMPONENT-011;Lo;0;L;;;;;N;;;;; 1880B;TANGUT COMPONENT-012;Lo;0;L;;;;;N;;;;; 1880C;TANGUT COMPONENT-013;Lo;0;L;;;;;N;;;;; 1880D;TANGUT COMPONENT-014;Lo;0;L;;;;;N;;;;; 1880E;TANGUT COMPONENT-015;Lo;0;L;;;;;N;;;;; 1880F;TANGUT COMPONENT-016;Lo;0;L;;;;;N;;;;; 18810;TANGUT COMPONENT-017;Lo;0;L;;;;;N;;;;; 18811;TANGUT COMPONENT-018;Lo;0;L;;;;;N;;;;; 18812;TANGUT COMPONENT-019;Lo;0;L;;;;;N;;;;; 18813;TANGUT COMPONENT-020;Lo;0;L;;;;;N;;;;; 18814;TANGUT COMPONENT-021;Lo;0;L;;;;;N;;;;; 18815;TANGUT COMPONENT-022;Lo;0;L;;;;;N;;;;; 18816;TANGUT COMPONENT-023;Lo;0;L;;;;;N;;;;; 18817;TANGUT COMPONENT-024;Lo;0;L;;;;;N;;;;; 18818;TANGUT COMPONENT-025;Lo;0;L;;;;;N;;;;; 18819;TANGUT COMPONENT-026;Lo;0;L;;;;;N;;;;; 1881A;TANGUT COMPONENT-027;Lo;0;L;;;;;N;;;;; 1881B;TANGUT COMPONENT-028;Lo;0;L;;;;;N;;;;; 1881C;TANGUT COMPONENT-029;Lo;0;L;;;;;N;;;;; 1881D;TANGUT COMPONENT-030;Lo;0;L;;;;;N;;;;; 1881E;TANGUT COMPONENT-031;Lo;0;L;;;;;N;;;;; 1881F;TANGUT COMPONENT-032;Lo;0;L;;;;;N;;;;; 18820;TANGUT COMPONENT-033;Lo;0;L;;;;;N;;;;; 18821;TANGUT COMPONENT-034;Lo;0;L;;;;;N;;;;; 18822;TANGUT COMPONENT-035;Lo;0;L;;;;;N;;;;; 18823;TANGUT COMPONENT-036;Lo;0;L;;;;;N;;;;; 18824;TANGUT COMPONENT-037;Lo;0;L;;;;;N;;;;; 18825;TANGUT COMPONENT-038;Lo;0;L;;;;;N;;;;; 18826;TANGUT COMPONENT-039;Lo;0;L;;;;;N;;;;; 18827;TANGUT COMPONENT-040;Lo;0;L;;;;;N;;;;; 18828;TANGUT COMPONENT-041;Lo;0;L;;;;;N;;;;; 18829;TANGUT COMPONENT-042;Lo;0;L;;;;;N;;;;; 1882A;TANGUT COMPONENT-043;Lo;0;L;;;;;N;;;;; 1882B;TANGUT COMPONENT-044;Lo;0;L;;;;;N;;;;; 1882C;TANGUT COMPONENT-045;Lo;0;L;;;;;N;;;;; 1882D;TANGUT COMPONENT-046;Lo;0;L;;;;;N;;;;; 1882E;TANGUT COMPONENT-047;Lo;0;L;;;;;N;;;;; 1882F;TANGUT COMPONENT-048;Lo;0;L;;;;;N;;;;; 18830;TANGUT COMPONENT-049;Lo;0;L;;;;;N;;;;; 18831;TANGUT COMPONENT-050;Lo;0;L;;;;;N;;;;; 18832;TANGUT COMPONENT-051;Lo;0;L;;;;;N;;;;; 18833;TANGUT COMPONENT-052;Lo;0;L;;;;;N;;;;; 18834;TANGUT COMPONENT-053;Lo;0;L;;;;;N;;;;; 18835;TANGUT COMPONENT-054;Lo;0;L;;;;;N;;;;; 18836;TANGUT COMPONENT-055;Lo;0;L;;;;;N;;;;; 18837;TANGUT COMPONENT-056;Lo;0;L;;;;;N;;;;; 18838;TANGUT COMPONENT-057;Lo;0;L;;;;;N;;;;; 18839;TANGUT COMPONENT-058;Lo;0;L;;;;;N;;;;; 1883A;TANGUT COMPONENT-059;Lo;0;L;;;;;N;;;;; 1883B;TANGUT COMPONENT-060;Lo;0;L;;;;;N;;;;; 1883C;TANGUT COMPONENT-061;Lo;0;L;;;;;N;;;;; 1883D;TANGUT COMPONENT-062;Lo;0;L;;;;;N;;;;; 1883E;TANGUT COMPONENT-063;Lo;0;L;;;;;N;;;;; 1883F;TANGUT COMPONENT-064;Lo;0;L;;;;;N;;;;; 18840;TANGUT COMPONENT-065;Lo;0;L;;;;;N;;;;; 18841;TANGUT COMPONENT-066;Lo;0;L;;;;;N;;;;; 18842;TANGUT COMPONENT-067;Lo;0;L;;;;;N;;;;; 18843;TANGUT COMPONENT-068;Lo;0;L;;;;;N;;;;; 18844;TANGUT COMPONENT-069;Lo;0;L;;;;;N;;;;; 18845;TANGUT COMPONENT-070;Lo;0;L;;;;;N;;;;; 18846;TANGUT COMPONENT-071;Lo;0;L;;;;;N;;;;; 18847;TANGUT COMPONENT-072;Lo;0;L;;;;;N;;;;; 18848;TANGUT COMPONENT-073;Lo;0;L;;;;;N;;;;; 18849;TANGUT COMPONENT-074;Lo;0;L;;;;;N;;;;; 1884A;TANGUT COMPONENT-075;Lo;0;L;;;;;N;;;;; 1884B;TANGUT COMPONENT-076;Lo;0;L;;;;;N;;;;; 1884C;TANGUT COMPONENT-077;Lo;0;L;;;;;N;;;;; 1884D;TANGUT COMPONENT-078;Lo;0;L;;;;;N;;;;; 1884E;TANGUT COMPONENT-079;Lo;0;L;;;;;N;;;;; 1884F;TANGUT COMPONENT-080;Lo;0;L;;;;;N;;;;; 18850;TANGUT COMPONENT-081;Lo;0;L;;;;;N;;;;; 18851;TANGUT COMPONENT-082;Lo;0;L;;;;;N;;;;; 18852;TANGUT COMPONENT-083;Lo;0;L;;;;;N;;;;; 18853;TANGUT COMPONENT-084;Lo;0;L;;;;;N;;;;; 18854;TANGUT COMPONENT-085;Lo;0;L;;;;;N;;;;; 18855;TANGUT COMPONENT-086;Lo;0;L;;;;;N;;;;; 18856;TANGUT COMPONENT-087;Lo;0;L;;;;;N;;;;; 18857;TANGUT COMPONENT-088;Lo;0;L;;;;;N;;;;; 18858;TANGUT COMPONENT-089;Lo;0;L;;;;;N;;;;; 18859;TANGUT COMPONENT-090;Lo;0;L;;;;;N;;;;; 1885A;TANGUT COMPONENT-091;Lo;0;L;;;;;N;;;;; 1885B;TANGUT COMPONENT-092;Lo;0;L;;;;;N;;;;; 1885C;TANGUT COMPONENT-093;Lo;0;L;;;;;N;;;;; 1885D;TANGUT COMPONENT-094;Lo;0;L;;;;;N;;;;; 1885E;TANGUT COMPONENT-095;Lo;0;L;;;;;N;;;;; 1885F;TANGUT COMPONENT-096;Lo;0;L;;;;;N;;;;; 18860;TANGUT COMPONENT-097;Lo;0;L;;;;;N;;;;; 18861;TANGUT COMPONENT-098;Lo;0;L;;;;;N;;;;; 18862;TANGUT COMPONENT-099;Lo;0;L;;;;;N;;;;; 18863;TANGUT COMPONENT-100;Lo;0;L;;;;;N;;;;; 18864;TANGUT COMPONENT-101;Lo;0;L;;;;;N;;;;; 18865;TANGUT COMPONENT-102;Lo;0;L;;;;;N;;;;; 18866;TANGUT COMPONENT-103;Lo;0;L;;;;;N;;;;; 18867;TANGUT COMPONENT-104;Lo;0;L;;;;;N;;;;; 18868;TANGUT COMPONENT-105;Lo;0;L;;;;;N;;;;; 18869;TANGUT COMPONENT-106;Lo;0;L;;;;;N;;;;; 1886A;TANGUT COMPONENT-107;Lo;0;L;;;;;N;;;;; 1886B;TANGUT COMPONENT-108;Lo;0;L;;;;;N;;;;; 1886C;TANGUT COMPONENT-109;Lo;0;L;;;;;N;;;;; 1886D;TANGUT COMPONENT-110;Lo;0;L;;;;;N;;;;; 1886E;TANGUT COMPONENT-111;Lo;0;L;;;;;N;;;;; 1886F;TANGUT COMPONENT-112;Lo;0;L;;;;;N;;;;; 18870;TANGUT COMPONENT-113;Lo;0;L;;;;;N;;;;; 18871;TANGUT COMPONENT-114;Lo;0;L;;;;;N;;;;; 18872;TANGUT COMPONENT-115;Lo;0;L;;;;;N;;;;; 18873;TANGUT COMPONENT-116;Lo;0;L;;;;;N;;;;; 18874;TANGUT COMPONENT-117;Lo;0;L;;;;;N;;;;; 18875;TANGUT COMPONENT-118;Lo;0;L;;;;;N;;;;; 18876;TANGUT COMPONENT-119;Lo;0;L;;;;;N;;;;; 18877;TANGUT COMPONENT-120;Lo;0;L;;;;;N;;;;; 18878;TANGUT COMPONENT-121;Lo;0;L;;;;;N;;;;; 18879;TANGUT COMPONENT-122;Lo;0;L;;;;;N;;;;; 1887A;TANGUT COMPONENT-123;Lo;0;L;;;;;N;;;;; 1887B;TANGUT COMPONENT-124;Lo;0;L;;;;;N;;;;; 1887C;TANGUT COMPONENT-125;Lo;0;L;;;;;N;;;;; 1887D;TANGUT COMPONENT-126;Lo;0;L;;;;;N;;;;; 1887E;TANGUT COMPONENT-127;Lo;0;L;;;;;N;;;;; 1887F;TANGUT COMPONENT-128;Lo;0;L;;;;;N;;;;; 18880;TANGUT COMPONENT-129;Lo;0;L;;;;;N;;;;; 18881;TANGUT COMPONENT-130;Lo;0;L;;;;;N;;;;; 18882;TANGUT COMPONENT-131;Lo;0;L;;;;;N;;;;; 18883;TANGUT COMPONENT-132;Lo;0;L;;;;;N;;;;; 18884;TANGUT COMPONENT-133;Lo;0;L;;;;;N;;;;; 18885;TANGUT COMPONENT-134;Lo;0;L;;;;;N;;;;; 18886;TANGUT COMPONENT-135;Lo;0;L;;;;;N;;;;; 18887;TANGUT COMPONENT-136;Lo;0;L;;;;;N;;;;; 18888;TANGUT COMPONENT-137;Lo;0;L;;;;;N;;;;; 18889;TANGUT COMPONENT-138;Lo;0;L;;;;;N;;;;; 1888A;TANGUT COMPONENT-139;Lo;0;L;;;;;N;;;;; 1888B;TANGUT COMPONENT-140;Lo;0;L;;;;;N;;;;; 1888C;TANGUT COMPONENT-141;Lo;0;L;;;;;N;;;;; 1888D;TANGUT COMPONENT-142;Lo;0;L;;;;;N;;;;; 1888E;TANGUT COMPONENT-143;Lo;0;L;;;;;N;;;;; 1888F;TANGUT COMPONENT-144;Lo;0;L;;;;;N;;;;; 18890;TANGUT COMPONENT-145;Lo;0;L;;;;;N;;;;; 18891;TANGUT COMPONENT-146;Lo;0;L;;;;;N;;;;; 18892;TANGUT COMPONENT-147;Lo;0;L;;;;;N;;;;; 18893;TANGUT COMPONENT-148;Lo;0;L;;;;;N;;;;; 18894;TANGUT COMPONENT-149;Lo;0;L;;;;;N;;;;; 18895;TANGUT COMPONENT-150;Lo;0;L;;;;;N;;;;; 18896;TANGUT COMPONENT-151;Lo;0;L;;;;;N;;;;; 18897;TANGUT COMPONENT-152;Lo;0;L;;;;;N;;;;; 18898;TANGUT COMPONENT-153;Lo;0;L;;;;;N;;;;; 18899;TANGUT COMPONENT-154;Lo;0;L;;;;;N;;;;; 1889A;TANGUT COMPONENT-155;Lo;0;L;;;;;N;;;;; 1889B;TANGUT COMPONENT-156;Lo;0;L;;;;;N;;;;; 1889C;TANGUT COMPONENT-157;Lo;0;L;;;;;N;;;;; 1889D;TANGUT COMPONENT-158;Lo;0;L;;;;;N;;;;; 1889E;TANGUT COMPONENT-159;Lo;0;L;;;;;N;;;;; 1889F;TANGUT COMPONENT-160;Lo;0;L;;;;;N;;;;; 188A0;TANGUT COMPONENT-161;Lo;0;L;;;;;N;;;;; 188A1;TANGUT COMPONENT-162;Lo;0;L;;;;;N;;;;; 188A2;TANGUT COMPONENT-163;Lo;0;L;;;;;N;;;;; 188A3;TANGUT COMPONENT-164;Lo;0;L;;;;;N;;;;; 188A4;TANGUT COMPONENT-165;Lo;0;L;;;;;N;;;;; 188A5;TANGUT COMPONENT-166;Lo;0;L;;;;;N;;;;; 188A6;TANGUT COMPONENT-167;Lo;0;L;;;;;N;;;;; 188A7;TANGUT COMPONENT-168;Lo;0;L;;;;;N;;;;; 188A8;TANGUT COMPONENT-169;Lo;0;L;;;;;N;;;;; 188A9;TANGUT COMPONENT-170;Lo;0;L;;;;;N;;;;; 188AA;TANGUT COMPONENT-171;Lo;0;L;;;;;N;;;;; 188AB;TANGUT COMPONENT-172;Lo;0;L;;;;;N;;;;; 188AC;TANGUT COMPONENT-173;Lo;0;L;;;;;N;;;;; 188AD;TANGUT COMPONENT-174;Lo;0;L;;;;;N;;;;; 188AE;TANGUT COMPONENT-175;Lo;0;L;;;;;N;;;;; 188AF;TANGUT COMPONENT-176;Lo;0;L;;;;;N;;;;; 188B0;TANGUT COMPONENT-177;Lo;0;L;;;;;N;;;;; 188B1;TANGUT COMPONENT-178;Lo;0;L;;;;;N;;;;; 188B2;TANGUT COMPONENT-179;Lo;0;L;;;;;N;;;;; 188B3;TANGUT COMPONENT-180;Lo;0;L;;;;;N;;;;; 188B4;TANGUT COMPONENT-181;Lo;0;L;;;;;N;;;;; 188B5;TANGUT COMPONENT-182;Lo;0;L;;;;;N;;;;; 188B6;TANGUT COMPONENT-183;Lo;0;L;;;;;N;;;;; 188B7;TANGUT COMPONENT-184;Lo;0;L;;;;;N;;;;; 188B8;TANGUT COMPONENT-185;Lo;0;L;;;;;N;;;;; 188B9;TANGUT COMPONENT-186;Lo;0;L;;;;;N;;;;; 188BA;TANGUT COMPONENT-187;Lo;0;L;;;;;N;;;;; 188BB;TANGUT COMPONENT-188;Lo;0;L;;;;;N;;;;; 188BC;TANGUT COMPONENT-189;Lo;0;L;;;;;N;;;;; 188BD;TANGUT COMPONENT-190;Lo;0;L;;;;;N;;;;; 188BE;TANGUT COMPONENT-191;Lo;0;L;;;;;N;;;;; 188BF;TANGUT COMPONENT-192;Lo;0;L;;;;;N;;;;; 188C0;TANGUT COMPONENT-193;Lo;0;L;;;;;N;;;;; 188C1;TANGUT COMPONENT-194;Lo;0;L;;;;;N;;;;; 188C2;TANGUT COMPONENT-195;Lo;0;L;;;;;N;;;;; 188C3;TANGUT COMPONENT-196;Lo;0;L;;;;;N;;;;; 188C4;TANGUT COMPONENT-197;Lo;0;L;;;;;N;;;;; 188C5;TANGUT COMPONENT-198;Lo;0;L;;;;;N;;;;; 188C6;TANGUT COMPONENT-199;Lo;0;L;;;;;N;;;;; 188C7;TANGUT COMPONENT-200;Lo;0;L;;;;;N;;;;; 188C8;TANGUT COMPONENT-201;Lo;0;L;;;;;N;;;;; 188C9;TANGUT COMPONENT-202;Lo;0;L;;;;;N;;;;; 188CA;TANGUT COMPONENT-203;Lo;0;L;;;;;N;;;;; 188CB;TANGUT COMPONENT-204;Lo;0;L;;;;;N;;;;; 188CC;TANGUT COMPONENT-205;Lo;0;L;;;;;N;;;;; 188CD;TANGUT COMPONENT-206;Lo;0;L;;;;;N;;;;; 188CE;TANGUT COMPONENT-207;Lo;0;L;;;;;N;;;;; 188CF;TANGUT COMPONENT-208;Lo;0;L;;;;;N;;;;; 188D0;TANGUT COMPONENT-209;Lo;0;L;;;;;N;;;;; 188D1;TANGUT COMPONENT-210;Lo;0;L;;;;;N;;;;; 188D2;TANGUT COMPONENT-211;Lo;0;L;;;;;N;;;;; 188D3;TANGUT COMPONENT-212;Lo;0;L;;;;;N;;;;; 188D4;TANGUT COMPONENT-213;Lo;0;L;;;;;N;;;;; 188D5;TANGUT COMPONENT-214;Lo;0;L;;;;;N;;;;; 188D6;TANGUT COMPONENT-215;Lo;0;L;;;;;N;;;;; 188D7;TANGUT COMPONENT-216;Lo;0;L;;;;;N;;;;; 188D8;TANGUT COMPONENT-217;Lo;0;L;;;;;N;;;;; 188D9;TANGUT COMPONENT-218;Lo;0;L;;;;;N;;;;; 188DA;TANGUT COMPONENT-219;Lo;0;L;;;;;N;;;;; 188DB;TANGUT COMPONENT-220;Lo;0;L;;;;;N;;;;; 188DC;TANGUT COMPONENT-221;Lo;0;L;;;;;N;;;;; 188DD;TANGUT COMPONENT-222;Lo;0;L;;;;;N;;;;; 188DE;TANGUT COMPONENT-223;Lo;0;L;;;;;N;;;;; 188DF;TANGUT COMPONENT-224;Lo;0;L;;;;;N;;;;; 188E0;TANGUT COMPONENT-225;Lo;0;L;;;;;N;;;;; 188E1;TANGUT COMPONENT-226;Lo;0;L;;;;;N;;;;; 188E2;TANGUT COMPONENT-227;Lo;0;L;;;;;N;;;;; 188E3;TANGUT COMPONENT-228;Lo;0;L;;;;;N;;;;; 188E4;TANGUT COMPONENT-229;Lo;0;L;;;;;N;;;;; 188E5;TANGUT COMPONENT-230;Lo;0;L;;;;;N;;;;; 188E6;TANGUT COMPONENT-231;Lo;0;L;;;;;N;;;;; 188E7;TANGUT COMPONENT-232;Lo;0;L;;;;;N;;;;; 188E8;TANGUT COMPONENT-233;Lo;0;L;;;;;N;;;;; 188E9;TANGUT COMPONENT-234;Lo;0;L;;;;;N;;;;; 188EA;TANGUT COMPONENT-235;Lo;0;L;;;;;N;;;;; 188EB;TANGUT COMPONENT-236;Lo;0;L;;;;;N;;;;; 188EC;TANGUT COMPONENT-237;Lo;0;L;;;;;N;;;;; 188ED;TANGUT COMPONENT-238;Lo;0;L;;;;;N;;;;; 188EE;TANGUT COMPONENT-239;Lo;0;L;;;;;N;;;;; 188EF;TANGUT COMPONENT-240;Lo;0;L;;;;;N;;;;; 188F0;TANGUT COMPONENT-241;Lo;0;L;;;;;N;;;;; 188F1;TANGUT COMPONENT-242;Lo;0;L;;;;;N;;;;; 188F2;TANGUT COMPONENT-243;Lo;0;L;;;;;N;;;;; 188F3;TANGUT COMPONENT-244;Lo;0;L;;;;;N;;;;; 188F4;TANGUT COMPONENT-245;Lo;0;L;;;;;N;;;;; 188F5;TANGUT COMPONENT-246;Lo;0;L;;;;;N;;;;; 188F6;TANGUT COMPONENT-247;Lo;0;L;;;;;N;;;;; 188F7;TANGUT COMPONENT-248;Lo;0;L;;;;;N;;;;; 188F8;TANGUT COMPONENT-249;Lo;0;L;;;;;N;;;;; 188F9;TANGUT COMPONENT-250;Lo;0;L;;;;;N;;;;; 188FA;TANGUT COMPONENT-251;Lo;0;L;;;;;N;;;;; 188FB;TANGUT COMPONENT-252;Lo;0;L;;;;;N;;;;; 188FC;TANGUT COMPONENT-253;Lo;0;L;;;;;N;;;;; 188FD;TANGUT COMPONENT-254;Lo;0;L;;;;;N;;;;; 188FE;TANGUT COMPONENT-255;Lo;0;L;;;;;N;;;;; 188FF;TANGUT COMPONENT-256;Lo;0;L;;;;;N;;;;; 18900;TANGUT COMPONENT-257;Lo;0;L;;;;;N;;;;; 18901;TANGUT COMPONENT-258;Lo;0;L;;;;;N;;;;; 18902;TANGUT COMPONENT-259;Lo;0;L;;;;;N;;;;; 18903;TANGUT COMPONENT-260;Lo;0;L;;;;;N;;;;; 18904;TANGUT COMPONENT-261;Lo;0;L;;;;;N;;;;; 18905;TANGUT COMPONENT-262;Lo;0;L;;;;;N;;;;; 18906;TANGUT COMPONENT-263;Lo;0;L;;;;;N;;;;; 18907;TANGUT COMPONENT-264;Lo;0;L;;;;;N;;;;; 18908;TANGUT COMPONENT-265;Lo;0;L;;;;;N;;;;; 18909;TANGUT COMPONENT-266;Lo;0;L;;;;;N;;;;; 1890A;TANGUT COMPONENT-267;Lo;0;L;;;;;N;;;;; 1890B;TANGUT COMPONENT-268;Lo;0;L;;;;;N;;;;; 1890C;TANGUT COMPONENT-269;Lo;0;L;;;;;N;;;;; 1890D;TANGUT COMPONENT-270;Lo;0;L;;;;;N;;;;; 1890E;TANGUT COMPONENT-271;Lo;0;L;;;;;N;;;;; 1890F;TANGUT COMPONENT-272;Lo;0;L;;;;;N;;;;; 18910;TANGUT COMPONENT-273;Lo;0;L;;;;;N;;;;; 18911;TANGUT COMPONENT-274;Lo;0;L;;;;;N;;;;; 18912;TANGUT COMPONENT-275;Lo;0;L;;;;;N;;;;; 18913;TANGUT COMPONENT-276;Lo;0;L;;;;;N;;;;; 18914;TANGUT COMPONENT-277;Lo;0;L;;;;;N;;;;; 18915;TANGUT COMPONENT-278;Lo;0;L;;;;;N;;;;; 18916;TANGUT COMPONENT-279;Lo;0;L;;;;;N;;;;; 18917;TANGUT COMPONENT-280;Lo;0;L;;;;;N;;;;; 18918;TANGUT COMPONENT-281;Lo;0;L;;;;;N;;;;; 18919;TANGUT COMPONENT-282;Lo;0;L;;;;;N;;;;; 1891A;TANGUT COMPONENT-283;Lo;0;L;;;;;N;;;;; 1891B;TANGUT COMPONENT-284;Lo;0;L;;;;;N;;;;; 1891C;TANGUT COMPONENT-285;Lo;0;L;;;;;N;;;;; 1891D;TANGUT COMPONENT-286;Lo;0;L;;;;;N;;;;; 1891E;TANGUT COMPONENT-287;Lo;0;L;;;;;N;;;;; 1891F;TANGUT COMPONENT-288;Lo;0;L;;;;;N;;;;; 18920;TANGUT COMPONENT-289;Lo;0;L;;;;;N;;;;; 18921;TANGUT COMPONENT-290;Lo;0;L;;;;;N;;;;; 18922;TANGUT COMPONENT-291;Lo;0;L;;;;;N;;;;; 18923;TANGUT COMPONENT-292;Lo;0;L;;;;;N;;;;; 18924;TANGUT COMPONENT-293;Lo;0;L;;;;;N;;;;; 18925;TANGUT COMPONENT-294;Lo;0;L;;;;;N;;;;; 18926;TANGUT COMPONENT-295;Lo;0;L;;;;;N;;;;; 18927;TANGUT COMPONENT-296;Lo;0;L;;;;;N;;;;; 18928;TANGUT COMPONENT-297;Lo;0;L;;;;;N;;;;; 18929;TANGUT COMPONENT-298;Lo;0;L;;;;;N;;;;; 1892A;TANGUT COMPONENT-299;Lo;0;L;;;;;N;;;;; 1892B;TANGUT COMPONENT-300;Lo;0;L;;;;;N;;;;; 1892C;TANGUT COMPONENT-301;Lo;0;L;;;;;N;;;;; 1892D;TANGUT COMPONENT-302;Lo;0;L;;;;;N;;;;; 1892E;TANGUT COMPONENT-303;Lo;0;L;;;;;N;;;;; 1892F;TANGUT COMPONENT-304;Lo;0;L;;;;;N;;;;; 18930;TANGUT COMPONENT-305;Lo;0;L;;;;;N;;;;; 18931;TANGUT COMPONENT-306;Lo;0;L;;;;;N;;;;; 18932;TANGUT COMPONENT-307;Lo;0;L;;;;;N;;;;; 18933;TANGUT COMPONENT-308;Lo;0;L;;;;;N;;;;; 18934;TANGUT COMPONENT-309;Lo;0;L;;;;;N;;;;; 18935;TANGUT COMPONENT-310;Lo;0;L;;;;;N;;;;; 18936;TANGUT COMPONENT-311;Lo;0;L;;;;;N;;;;; 18937;TANGUT COMPONENT-312;Lo;0;L;;;;;N;;;;; 18938;TANGUT COMPONENT-313;Lo;0;L;;;;;N;;;;; 18939;TANGUT COMPONENT-314;Lo;0;L;;;;;N;;;;; 1893A;TANGUT COMPONENT-315;Lo;0;L;;;;;N;;;;; 1893B;TANGUT COMPONENT-316;Lo;0;L;;;;;N;;;;; 1893C;TANGUT COMPONENT-317;Lo;0;L;;;;;N;;;;; 1893D;TANGUT COMPONENT-318;Lo;0;L;;;;;N;;;;; 1893E;TANGUT COMPONENT-319;Lo;0;L;;;;;N;;;;; 1893F;TANGUT COMPONENT-320;Lo;0;L;;;;;N;;;;; 18940;TANGUT COMPONENT-321;Lo;0;L;;;;;N;;;;; 18941;TANGUT COMPONENT-322;Lo;0;L;;;;;N;;;;; 18942;TANGUT COMPONENT-323;Lo;0;L;;;;;N;;;;; 18943;TANGUT COMPONENT-324;Lo;0;L;;;;;N;;;;; 18944;TANGUT COMPONENT-325;Lo;0;L;;;;;N;;;;; 18945;TANGUT COMPONENT-326;Lo;0;L;;;;;N;;;;; 18946;TANGUT COMPONENT-327;Lo;0;L;;;;;N;;;;; 18947;TANGUT COMPONENT-328;Lo;0;L;;;;;N;;;;; 18948;TANGUT COMPONENT-329;Lo;0;L;;;;;N;;;;; 18949;TANGUT COMPONENT-330;Lo;0;L;;;;;N;;;;; 1894A;TANGUT COMPONENT-331;Lo;0;L;;;;;N;;;;; 1894B;TANGUT COMPONENT-332;Lo;0;L;;;;;N;;;;; 1894C;TANGUT COMPONENT-333;Lo;0;L;;;;;N;;;;; 1894D;TANGUT COMPONENT-334;Lo;0;L;;;;;N;;;;; 1894E;TANGUT COMPONENT-335;Lo;0;L;;;;;N;;;;; 1894F;TANGUT COMPONENT-336;Lo;0;L;;;;;N;;;;; 18950;TANGUT COMPONENT-337;Lo;0;L;;;;;N;;;;; 18951;TANGUT COMPONENT-338;Lo;0;L;;;;;N;;;;; 18952;TANGUT COMPONENT-339;Lo;0;L;;;;;N;;;;; 18953;TANGUT COMPONENT-340;Lo;0;L;;;;;N;;;;; 18954;TANGUT COMPONENT-341;Lo;0;L;;;;;N;;;;; 18955;TANGUT COMPONENT-342;Lo;0;L;;;;;N;;;;; 18956;TANGUT COMPONENT-343;Lo;0;L;;;;;N;;;;; 18957;TANGUT COMPONENT-344;Lo;0;L;;;;;N;;;;; 18958;TANGUT COMPONENT-345;Lo;0;L;;;;;N;;;;; 18959;TANGUT COMPONENT-346;Lo;0;L;;;;;N;;;;; 1895A;TANGUT COMPONENT-347;Lo;0;L;;;;;N;;;;; 1895B;TANGUT COMPONENT-348;Lo;0;L;;;;;N;;;;; 1895C;TANGUT COMPONENT-349;Lo;0;L;;;;;N;;;;; 1895D;TANGUT COMPONENT-350;Lo;0;L;;;;;N;;;;; 1895E;TANGUT COMPONENT-351;Lo;0;L;;;;;N;;;;; 1895F;TANGUT COMPONENT-352;Lo;0;L;;;;;N;;;;; 18960;TANGUT COMPONENT-353;Lo;0;L;;;;;N;;;;; 18961;TANGUT COMPONENT-354;Lo;0;L;;;;;N;;;;; 18962;TANGUT COMPONENT-355;Lo;0;L;;;;;N;;;;; 18963;TANGUT COMPONENT-356;Lo;0;L;;;;;N;;;;; 18964;TANGUT COMPONENT-357;Lo;0;L;;;;;N;;;;; 18965;TANGUT COMPONENT-358;Lo;0;L;;;;;N;;;;; 18966;TANGUT COMPONENT-359;Lo;0;L;;;;;N;;;;; 18967;TANGUT COMPONENT-360;Lo;0;L;;;;;N;;;;; 18968;TANGUT COMPONENT-361;Lo;0;L;;;;;N;;;;; 18969;TANGUT COMPONENT-362;Lo;0;L;;;;;N;;;;; 1896A;TANGUT COMPONENT-363;Lo;0;L;;;;;N;;;;; 1896B;TANGUT COMPONENT-364;Lo;0;L;;;;;N;;;;; 1896C;TANGUT COMPONENT-365;Lo;0;L;;;;;N;;;;; 1896D;TANGUT COMPONENT-366;Lo;0;L;;;;;N;;;;; 1896E;TANGUT COMPONENT-367;Lo;0;L;;;;;N;;;;; 1896F;TANGUT COMPONENT-368;Lo;0;L;;;;;N;;;;; 18970;TANGUT COMPONENT-369;Lo;0;L;;;;;N;;;;; 18971;TANGUT COMPONENT-370;Lo;0;L;;;;;N;;;;; 18972;TANGUT COMPONENT-371;Lo;0;L;;;;;N;;;;; 18973;TANGUT COMPONENT-372;Lo;0;L;;;;;N;;;;; 18974;TANGUT COMPONENT-373;Lo;0;L;;;;;N;;;;; 18975;TANGUT COMPONENT-374;Lo;0;L;;;;;N;;;;; 18976;TANGUT COMPONENT-375;Lo;0;L;;;;;N;;;;; 18977;TANGUT COMPONENT-376;Lo;0;L;;;;;N;;;;; 18978;TANGUT COMPONENT-377;Lo;0;L;;;;;N;;;;; 18979;TANGUT COMPONENT-378;Lo;0;L;;;;;N;;;;; 1897A;TANGUT COMPONENT-379;Lo;0;L;;;;;N;;;;; 1897B;TANGUT COMPONENT-380;Lo;0;L;;;;;N;;;;; 1897C;TANGUT COMPONENT-381;Lo;0;L;;;;;N;;;;; 1897D;TANGUT COMPONENT-382;Lo;0;L;;;;;N;;;;; 1897E;TANGUT COMPONENT-383;Lo;0;L;;;;;N;;;;; 1897F;TANGUT COMPONENT-384;Lo;0;L;;;;;N;;;;; 18980;TANGUT COMPONENT-385;Lo;0;L;;;;;N;;;;; 18981;TANGUT COMPONENT-386;Lo;0;L;;;;;N;;;;; 18982;TANGUT COMPONENT-387;Lo;0;L;;;;;N;;;;; 18983;TANGUT COMPONENT-388;Lo;0;L;;;;;N;;;;; 18984;TANGUT COMPONENT-389;Lo;0;L;;;;;N;;;;; 18985;TANGUT COMPONENT-390;Lo;0;L;;;;;N;;;;; 18986;TANGUT COMPONENT-391;Lo;0;L;;;;;N;;;;; 18987;TANGUT COMPONENT-392;Lo;0;L;;;;;N;;;;; 18988;TANGUT COMPONENT-393;Lo;0;L;;;;;N;;;;; 18989;TANGUT COMPONENT-394;Lo;0;L;;;;;N;;;;; 1898A;TANGUT COMPONENT-395;Lo;0;L;;;;;N;;;;; 1898B;TANGUT COMPONENT-396;Lo;0;L;;;;;N;;;;; 1898C;TANGUT COMPONENT-397;Lo;0;L;;;;;N;;;;; 1898D;TANGUT COMPONENT-398;Lo;0;L;;;;;N;;;;; 1898E;TANGUT COMPONENT-399;Lo;0;L;;;;;N;;;;; 1898F;TANGUT COMPONENT-400;Lo;0;L;;;;;N;;;;; 18990;TANGUT COMPONENT-401;Lo;0;L;;;;;N;;;;; 18991;TANGUT COMPONENT-402;Lo;0;L;;;;;N;;;;; 18992;TANGUT COMPONENT-403;Lo;0;L;;;;;N;;;;; 18993;TANGUT COMPONENT-404;Lo;0;L;;;;;N;;;;; 18994;TANGUT COMPONENT-405;Lo;0;L;;;;;N;;;;; 18995;TANGUT COMPONENT-406;Lo;0;L;;;;;N;;;;; 18996;TANGUT COMPONENT-407;Lo;0;L;;;;;N;;;;; 18997;TANGUT COMPONENT-408;Lo;0;L;;;;;N;;;;; 18998;TANGUT COMPONENT-409;Lo;0;L;;;;;N;;;;; 18999;TANGUT COMPONENT-410;Lo;0;L;;;;;N;;;;; 1899A;TANGUT COMPONENT-411;Lo;0;L;;;;;N;;;;; 1899B;TANGUT COMPONENT-412;Lo;0;L;;;;;N;;;;; 1899C;TANGUT COMPONENT-413;Lo;0;L;;;;;N;;;;; 1899D;TANGUT COMPONENT-414;Lo;0;L;;;;;N;;;;; 1899E;TANGUT COMPONENT-415;Lo;0;L;;;;;N;;;;; 1899F;TANGUT COMPONENT-416;Lo;0;L;;;;;N;;;;; 189A0;TANGUT COMPONENT-417;Lo;0;L;;;;;N;;;;; 189A1;TANGUT COMPONENT-418;Lo;0;L;;;;;N;;;;; 189A2;TANGUT COMPONENT-419;Lo;0;L;;;;;N;;;;; 189A3;TANGUT COMPONENT-420;Lo;0;L;;;;;N;;;;; 189A4;TANGUT COMPONENT-421;Lo;0;L;;;;;N;;;;; 189A5;TANGUT COMPONENT-422;Lo;0;L;;;;;N;;;;; 189A6;TANGUT COMPONENT-423;Lo;0;L;;;;;N;;;;; 189A7;TANGUT COMPONENT-424;Lo;0;L;;;;;N;;;;; 189A8;TANGUT COMPONENT-425;Lo;0;L;;;;;N;;;;; 189A9;TANGUT COMPONENT-426;Lo;0;L;;;;;N;;;;; 189AA;TANGUT COMPONENT-427;Lo;0;L;;;;;N;;;;; 189AB;TANGUT COMPONENT-428;Lo;0;L;;;;;N;;;;; 189AC;TANGUT COMPONENT-429;Lo;0;L;;;;;N;;;;; 189AD;TANGUT COMPONENT-430;Lo;0;L;;;;;N;;;;; 189AE;TANGUT COMPONENT-431;Lo;0;L;;;;;N;;;;; 189AF;TANGUT COMPONENT-432;Lo;0;L;;;;;N;;;;; 189B0;TANGUT COMPONENT-433;Lo;0;L;;;;;N;;;;; 189B1;TANGUT COMPONENT-434;Lo;0;L;;;;;N;;;;; 189B2;TANGUT COMPONENT-435;Lo;0;L;;;;;N;;;;; 189B3;TANGUT COMPONENT-436;Lo;0;L;;;;;N;;;;; 189B4;TANGUT COMPONENT-437;Lo;0;L;;;;;N;;;;; 189B5;TANGUT COMPONENT-438;Lo;0;L;;;;;N;;;;; 189B6;TANGUT COMPONENT-439;Lo;0;L;;;;;N;;;;; 189B7;TANGUT COMPONENT-440;Lo;0;L;;;;;N;;;;; 189B8;TANGUT COMPONENT-441;Lo;0;L;;;;;N;;;;; 189B9;TANGUT COMPONENT-442;Lo;0;L;;;;;N;;;;; 189BA;TANGUT COMPONENT-443;Lo;0;L;;;;;N;;;;; 189BB;TANGUT COMPONENT-444;Lo;0;L;;;;;N;;;;; 189BC;TANGUT COMPONENT-445;Lo;0;L;;;;;N;;;;; 189BD;TANGUT COMPONENT-446;Lo;0;L;;;;;N;;;;; 189BE;TANGUT COMPONENT-447;Lo;0;L;;;;;N;;;;; 189BF;TANGUT COMPONENT-448;Lo;0;L;;;;;N;;;;; 189C0;TANGUT COMPONENT-449;Lo;0;L;;;;;N;;;;; 189C1;TANGUT COMPONENT-450;Lo;0;L;;;;;N;;;;; 189C2;TANGUT COMPONENT-451;Lo;0;L;;;;;N;;;;; 189C3;TANGUT COMPONENT-452;Lo;0;L;;;;;N;;;;; 189C4;TANGUT COMPONENT-453;Lo;0;L;;;;;N;;;;; 189C5;TANGUT COMPONENT-454;Lo;0;L;;;;;N;;;;; 189C6;TANGUT COMPONENT-455;Lo;0;L;;;;;N;;;;; 189C7;TANGUT COMPONENT-456;Lo;0;L;;;;;N;;;;; 189C8;TANGUT COMPONENT-457;Lo;0;L;;;;;N;;;;; 189C9;TANGUT COMPONENT-458;Lo;0;L;;;;;N;;;;; 189CA;TANGUT COMPONENT-459;Lo;0;L;;;;;N;;;;; 189CB;TANGUT COMPONENT-460;Lo;0;L;;;;;N;;;;; 189CC;TANGUT COMPONENT-461;Lo;0;L;;;;;N;;;;; 189CD;TANGUT COMPONENT-462;Lo;0;L;;;;;N;;;;; 189CE;TANGUT COMPONENT-463;Lo;0;L;;;;;N;;;;; 189CF;TANGUT COMPONENT-464;Lo;0;L;;;;;N;;;;; 189D0;TANGUT COMPONENT-465;Lo;0;L;;;;;N;;;;; 189D1;TANGUT COMPONENT-466;Lo;0;L;;;;;N;;;;; 189D2;TANGUT COMPONENT-467;Lo;0;L;;;;;N;;;;; 189D3;TANGUT COMPONENT-468;Lo;0;L;;;;;N;;;;; 189D4;TANGUT COMPONENT-469;Lo;0;L;;;;;N;;;;; 189D5;TANGUT COMPONENT-470;Lo;0;L;;;;;N;;;;; 189D6;TANGUT COMPONENT-471;Lo;0;L;;;;;N;;;;; 189D7;TANGUT COMPONENT-472;Lo;0;L;;;;;N;;;;; 189D8;TANGUT COMPONENT-473;Lo;0;L;;;;;N;;;;; 189D9;TANGUT COMPONENT-474;Lo;0;L;;;;;N;;;;; 189DA;TANGUT COMPONENT-475;Lo;0;L;;;;;N;;;;; 189DB;TANGUT COMPONENT-476;Lo;0;L;;;;;N;;;;; 189DC;TANGUT COMPONENT-477;Lo;0;L;;;;;N;;;;; 189DD;TANGUT COMPONENT-478;Lo;0;L;;;;;N;;;;; 189DE;TANGUT COMPONENT-479;Lo;0;L;;;;;N;;;;; 189DF;TANGUT COMPONENT-480;Lo;0;L;;;;;N;;;;; 189E0;TANGUT COMPONENT-481;Lo;0;L;;;;;N;;;;; 189E1;TANGUT COMPONENT-482;Lo;0;L;;;;;N;;;;; 189E2;TANGUT COMPONENT-483;Lo;0;L;;;;;N;;;;; 189E3;TANGUT COMPONENT-484;Lo;0;L;;;;;N;;;;; 189E4;TANGUT COMPONENT-485;Lo;0;L;;;;;N;;;;; 189E5;TANGUT COMPONENT-486;Lo;0;L;;;;;N;;;;; 189E6;TANGUT COMPONENT-487;Lo;0;L;;;;;N;;;;; 189E7;TANGUT COMPONENT-488;Lo;0;L;;;;;N;;;;; 189E8;TANGUT COMPONENT-489;Lo;0;L;;;;;N;;;;; 189E9;TANGUT COMPONENT-490;Lo;0;L;;;;;N;;;;; 189EA;TANGUT COMPONENT-491;Lo;0;L;;;;;N;;;;; 189EB;TANGUT COMPONENT-492;Lo;0;L;;;;;N;;;;; 189EC;TANGUT COMPONENT-493;Lo;0;L;;;;;N;;;;; 189ED;TANGUT COMPONENT-494;Lo;0;L;;;;;N;;;;; 189EE;TANGUT COMPONENT-495;Lo;0;L;;;;;N;;;;; 189EF;TANGUT COMPONENT-496;Lo;0;L;;;;;N;;;;; 189F0;TANGUT COMPONENT-497;Lo;0;L;;;;;N;;;;; 189F1;TANGUT COMPONENT-498;Lo;0;L;;;;;N;;;;; 189F2;TANGUT COMPONENT-499;Lo;0;L;;;;;N;;;;; 189F3;TANGUT COMPONENT-500;Lo;0;L;;;;;N;;;;; 189F4;TANGUT COMPONENT-501;Lo;0;L;;;;;N;;;;; 189F5;TANGUT COMPONENT-502;Lo;0;L;;;;;N;;;;; 189F6;TANGUT COMPONENT-503;Lo;0;L;;;;;N;;;;; 189F7;TANGUT COMPONENT-504;Lo;0;L;;;;;N;;;;; 189F8;TANGUT COMPONENT-505;Lo;0;L;;;;;N;;;;; 189F9;TANGUT COMPONENT-506;Lo;0;L;;;;;N;;;;; 189FA;TANGUT COMPONENT-507;Lo;0;L;;;;;N;;;;; 189FB;TANGUT COMPONENT-508;Lo;0;L;;;;;N;;;;; 189FC;TANGUT COMPONENT-509;Lo;0;L;;;;;N;;;;; 189FD;TANGUT COMPONENT-510;Lo;0;L;;;;;N;;;;; 189FE;TANGUT COMPONENT-511;Lo;0;L;;;;;N;;;;; 189FF;TANGUT COMPONENT-512;Lo;0;L;;;;;N;;;;; 18A00;TANGUT COMPONENT-513;Lo;0;L;;;;;N;;;;; 18A01;TANGUT COMPONENT-514;Lo;0;L;;;;;N;;;;; 18A02;TANGUT COMPONENT-515;Lo;0;L;;;;;N;;;;; 18A03;TANGUT COMPONENT-516;Lo;0;L;;;;;N;;;;; 18A04;TANGUT COMPONENT-517;Lo;0;L;;;;;N;;;;; 18A05;TANGUT COMPONENT-518;Lo;0;L;;;;;N;;;;; 18A06;TANGUT COMPONENT-519;Lo;0;L;;;;;N;;;;; 18A07;TANGUT COMPONENT-520;Lo;0;L;;;;;N;;;;; 18A08;TANGUT COMPONENT-521;Lo;0;L;;;;;N;;;;; 18A09;TANGUT COMPONENT-522;Lo;0;L;;;;;N;;;;; 18A0A;TANGUT COMPONENT-523;Lo;0;L;;;;;N;;;;; 18A0B;TANGUT COMPONENT-524;Lo;0;L;;;;;N;;;;; 18A0C;TANGUT COMPONENT-525;Lo;0;L;;;;;N;;;;; 18A0D;TANGUT COMPONENT-526;Lo;0;L;;;;;N;;;;; 18A0E;TANGUT COMPONENT-527;Lo;0;L;;;;;N;;;;; 18A0F;TANGUT COMPONENT-528;Lo;0;L;;;;;N;;;;; 18A10;TANGUT COMPONENT-529;Lo;0;L;;;;;N;;;;; 18A11;TANGUT COMPONENT-530;Lo;0;L;;;;;N;;;;; 18A12;TANGUT COMPONENT-531;Lo;0;L;;;;;N;;;;; 18A13;TANGUT COMPONENT-532;Lo;0;L;;;;;N;;;;; 18A14;TANGUT COMPONENT-533;Lo;0;L;;;;;N;;;;; 18A15;TANGUT COMPONENT-534;Lo;0;L;;;;;N;;;;; 18A16;TANGUT COMPONENT-535;Lo;0;L;;;;;N;;;;; 18A17;TANGUT COMPONENT-536;Lo;0;L;;;;;N;;;;; 18A18;TANGUT COMPONENT-537;Lo;0;L;;;;;N;;;;; 18A19;TANGUT COMPONENT-538;Lo;0;L;;;;;N;;;;; 18A1A;TANGUT COMPONENT-539;Lo;0;L;;;;;N;;;;; 18A1B;TANGUT COMPONENT-540;Lo;0;L;;;;;N;;;;; 18A1C;TANGUT COMPONENT-541;Lo;0;L;;;;;N;;;;; 18A1D;TANGUT COMPONENT-542;Lo;0;L;;;;;N;;;;; 18A1E;TANGUT COMPONENT-543;Lo;0;L;;;;;N;;;;; 18A1F;TANGUT COMPONENT-544;Lo;0;L;;;;;N;;;;; 18A20;TANGUT COMPONENT-545;Lo;0;L;;;;;N;;;;; 18A21;TANGUT COMPONENT-546;Lo;0;L;;;;;N;;;;; 18A22;TANGUT COMPONENT-547;Lo;0;L;;;;;N;;;;; 18A23;TANGUT COMPONENT-548;Lo;0;L;;;;;N;;;;; 18A24;TANGUT COMPONENT-549;Lo;0;L;;;;;N;;;;; 18A25;TANGUT COMPONENT-550;Lo;0;L;;;;;N;;;;; 18A26;TANGUT COMPONENT-551;Lo;0;L;;;;;N;;;;; 18A27;TANGUT COMPONENT-552;Lo;0;L;;;;;N;;;;; 18A28;TANGUT COMPONENT-553;Lo;0;L;;;;;N;;;;; 18A29;TANGUT COMPONENT-554;Lo;0;L;;;;;N;;;;; 18A2A;TANGUT COMPONENT-555;Lo;0;L;;;;;N;;;;; 18A2B;TANGUT COMPONENT-556;Lo;0;L;;;;;N;;;;; 18A2C;TANGUT COMPONENT-557;Lo;0;L;;;;;N;;;;; 18A2D;TANGUT COMPONENT-558;Lo;0;L;;;;;N;;;;; 18A2E;TANGUT COMPONENT-559;Lo;0;L;;;;;N;;;;; 18A2F;TANGUT COMPONENT-560;Lo;0;L;;;;;N;;;;; 18A30;TANGUT COMPONENT-561;Lo;0;L;;;;;N;;;;; 18A31;TANGUT COMPONENT-562;Lo;0;L;;;;;N;;;;; 18A32;TANGUT COMPONENT-563;Lo;0;L;;;;;N;;;;; 18A33;TANGUT COMPONENT-564;Lo;0;L;;;;;N;;;;; 18A34;TANGUT COMPONENT-565;Lo;0;L;;;;;N;;;;; 18A35;TANGUT COMPONENT-566;Lo;0;L;;;;;N;;;;; 18A36;TANGUT COMPONENT-567;Lo;0;L;;;;;N;;;;; 18A37;TANGUT COMPONENT-568;Lo;0;L;;;;;N;;;;; 18A38;TANGUT COMPONENT-569;Lo;0;L;;;;;N;;;;; 18A39;TANGUT COMPONENT-570;Lo;0;L;;;;;N;;;;; 18A3A;TANGUT COMPONENT-571;Lo;0;L;;;;;N;;;;; 18A3B;TANGUT COMPONENT-572;Lo;0;L;;;;;N;;;;; 18A3C;TANGUT COMPONENT-573;Lo;0;L;;;;;N;;;;; 18A3D;TANGUT COMPONENT-574;Lo;0;L;;;;;N;;;;; 18A3E;TANGUT COMPONENT-575;Lo;0;L;;;;;N;;;;; 18A3F;TANGUT COMPONENT-576;Lo;0;L;;;;;N;;;;; 18A40;TANGUT COMPONENT-577;Lo;0;L;;;;;N;;;;; 18A41;TANGUT COMPONENT-578;Lo;0;L;;;;;N;;;;; 18A42;TANGUT COMPONENT-579;Lo;0;L;;;;;N;;;;; 18A43;TANGUT COMPONENT-580;Lo;0;L;;;;;N;;;;; 18A44;TANGUT COMPONENT-581;Lo;0;L;;;;;N;;;;; 18A45;TANGUT COMPONENT-582;Lo;0;L;;;;;N;;;;; 18A46;TANGUT COMPONENT-583;Lo;0;L;;;;;N;;;;; 18A47;TANGUT COMPONENT-584;Lo;0;L;;;;;N;;;;; 18A48;TANGUT COMPONENT-585;Lo;0;L;;;;;N;;;;; 18A49;TANGUT COMPONENT-586;Lo;0;L;;;;;N;;;;; 18A4A;TANGUT COMPONENT-587;Lo;0;L;;;;;N;;;;; 18A4B;TANGUT COMPONENT-588;Lo;0;L;;;;;N;;;;; 18A4C;TANGUT COMPONENT-589;Lo;0;L;;;;;N;;;;; 18A4D;TANGUT COMPONENT-590;Lo;0;L;;;;;N;;;;; 18A4E;TANGUT COMPONENT-591;Lo;0;L;;;;;N;;;;; 18A4F;TANGUT COMPONENT-592;Lo;0;L;;;;;N;;;;; 18A50;TANGUT COMPONENT-593;Lo;0;L;;;;;N;;;;; 18A51;TANGUT COMPONENT-594;Lo;0;L;;;;;N;;;;; 18A52;TANGUT COMPONENT-595;Lo;0;L;;;;;N;;;;; 18A53;TANGUT COMPONENT-596;Lo;0;L;;;;;N;;;;; 18A54;TANGUT COMPONENT-597;Lo;0;L;;;;;N;;;;; 18A55;TANGUT COMPONENT-598;Lo;0;L;;;;;N;;;;; 18A56;TANGUT COMPONENT-599;Lo;0;L;;;;;N;;;;; 18A57;TANGUT COMPONENT-600;Lo;0;L;;;;;N;;;;; 18A58;TANGUT COMPONENT-601;Lo;0;L;;;;;N;;;;; 18A59;TANGUT COMPONENT-602;Lo;0;L;;;;;N;;;;; 18A5A;TANGUT COMPONENT-603;Lo;0;L;;;;;N;;;;; 18A5B;TANGUT COMPONENT-604;Lo;0;L;;;;;N;;;;; 18A5C;TANGUT COMPONENT-605;Lo;0;L;;;;;N;;;;; 18A5D;TANGUT COMPONENT-606;Lo;0;L;;;;;N;;;;; 18A5E;TANGUT COMPONENT-607;Lo;0;L;;;;;N;;;;; 18A5F;TANGUT COMPONENT-608;Lo;0;L;;;;;N;;;;; 18A60;TANGUT COMPONENT-609;Lo;0;L;;;;;N;;;;; 18A61;TANGUT COMPONENT-610;Lo;0;L;;;;;N;;;;; 18A62;TANGUT COMPONENT-611;Lo;0;L;;;;;N;;;;; 18A63;TANGUT COMPONENT-612;Lo;0;L;;;;;N;;;;; 18A64;TANGUT COMPONENT-613;Lo;0;L;;;;;N;;;;; 18A65;TANGUT COMPONENT-614;Lo;0;L;;;;;N;;;;; 18A66;TANGUT COMPONENT-615;Lo;0;L;;;;;N;;;;; 18A67;TANGUT COMPONENT-616;Lo;0;L;;;;;N;;;;; 18A68;TANGUT COMPONENT-617;Lo;0;L;;;;;N;;;;; 18A69;TANGUT COMPONENT-618;Lo;0;L;;;;;N;;;;; 18A6A;TANGUT COMPONENT-619;Lo;0;L;;;;;N;;;;; 18A6B;TANGUT COMPONENT-620;Lo;0;L;;;;;N;;;;; 18A6C;TANGUT COMPONENT-621;Lo;0;L;;;;;N;;;;; 18A6D;TANGUT COMPONENT-622;Lo;0;L;;;;;N;;;;; 18A6E;TANGUT COMPONENT-623;Lo;0;L;;;;;N;;;;; 18A6F;TANGUT COMPONENT-624;Lo;0;L;;;;;N;;;;; 18A70;TANGUT COMPONENT-625;Lo;0;L;;;;;N;;;;; 18A71;TANGUT COMPONENT-626;Lo;0;L;;;;;N;;;;; 18A72;TANGUT COMPONENT-627;Lo;0;L;;;;;N;;;;; 18A73;TANGUT COMPONENT-628;Lo;0;L;;;;;N;;;;; 18A74;TANGUT COMPONENT-629;Lo;0;L;;;;;N;;;;; 18A75;TANGUT COMPONENT-630;Lo;0;L;;;;;N;;;;; 18A76;TANGUT COMPONENT-631;Lo;0;L;;;;;N;;;;; 18A77;TANGUT COMPONENT-632;Lo;0;L;;;;;N;;;;; 18A78;TANGUT COMPONENT-633;Lo;0;L;;;;;N;;;;; 18A79;TANGUT COMPONENT-634;Lo;0;L;;;;;N;;;;; 18A7A;TANGUT COMPONENT-635;Lo;0;L;;;;;N;;;;; 18A7B;TANGUT COMPONENT-636;Lo;0;L;;;;;N;;;;; 18A7C;TANGUT COMPONENT-637;Lo;0;L;;;;;N;;;;; 18A7D;TANGUT COMPONENT-638;Lo;0;L;;;;;N;;;;; 18A7E;TANGUT COMPONENT-639;Lo;0;L;;;;;N;;;;; 18A7F;TANGUT COMPONENT-640;Lo;0;L;;;;;N;;;;; 18A80;TANGUT COMPONENT-641;Lo;0;L;;;;;N;;;;; 18A81;TANGUT COMPONENT-642;Lo;0;L;;;;;N;;;;; 18A82;TANGUT COMPONENT-643;Lo;0;L;;;;;N;;;;; 18A83;TANGUT COMPONENT-644;Lo;0;L;;;;;N;;;;; 18A84;TANGUT COMPONENT-645;Lo;0;L;;;;;N;;;;; 18A85;TANGUT COMPONENT-646;Lo;0;L;;;;;N;;;;; 18A86;TANGUT COMPONENT-647;Lo;0;L;;;;;N;;;;; 18A87;TANGUT COMPONENT-648;Lo;0;L;;;;;N;;;;; 18A88;TANGUT COMPONENT-649;Lo;0;L;;;;;N;;;;; 18A89;TANGUT COMPONENT-650;Lo;0;L;;;;;N;;;;; 18A8A;TANGUT COMPONENT-651;Lo;0;L;;;;;N;;;;; 18A8B;TANGUT COMPONENT-652;Lo;0;L;;;;;N;;;;; 18A8C;TANGUT COMPONENT-653;Lo;0;L;;;;;N;;;;; 18A8D;TANGUT COMPONENT-654;Lo;0;L;;;;;N;;;;; 18A8E;TANGUT COMPONENT-655;Lo;0;L;;;;;N;;;;; 18A8F;TANGUT COMPONENT-656;Lo;0;L;;;;;N;;;;; 18A90;TANGUT COMPONENT-657;Lo;0;L;;;;;N;;;;; 18A91;TANGUT COMPONENT-658;Lo;0;L;;;;;N;;;;; 18A92;TANGUT COMPONENT-659;Lo;0;L;;;;;N;;;;; 18A93;TANGUT COMPONENT-660;Lo;0;L;;;;;N;;;;; 18A94;TANGUT COMPONENT-661;Lo;0;L;;;;;N;;;;; 18A95;TANGUT COMPONENT-662;Lo;0;L;;;;;N;;;;; 18A96;TANGUT COMPONENT-663;Lo;0;L;;;;;N;;;;; 18A97;TANGUT COMPONENT-664;Lo;0;L;;;;;N;;;;; 18A98;TANGUT COMPONENT-665;Lo;0;L;;;;;N;;;;; 18A99;TANGUT COMPONENT-666;Lo;0;L;;;;;N;;;;; 18A9A;TANGUT COMPONENT-667;Lo;0;L;;;;;N;;;;; 18A9B;TANGUT COMPONENT-668;Lo;0;L;;;;;N;;;;; 18A9C;TANGUT COMPONENT-669;Lo;0;L;;;;;N;;;;; 18A9D;TANGUT COMPONENT-670;Lo;0;L;;;;;N;;;;; 18A9E;TANGUT COMPONENT-671;Lo;0;L;;;;;N;;;;; 18A9F;TANGUT COMPONENT-672;Lo;0;L;;;;;N;;;;; 18AA0;TANGUT COMPONENT-673;Lo;0;L;;;;;N;;;;; 18AA1;TANGUT COMPONENT-674;Lo;0;L;;;;;N;;;;; 18AA2;TANGUT COMPONENT-675;Lo;0;L;;;;;N;;;;; 18AA3;TANGUT COMPONENT-676;Lo;0;L;;;;;N;;;;; 18AA4;TANGUT COMPONENT-677;Lo;0;L;;;;;N;;;;; 18AA5;TANGUT COMPONENT-678;Lo;0;L;;;;;N;;;;; 18AA6;TANGUT COMPONENT-679;Lo;0;L;;;;;N;;;;; 18AA7;TANGUT COMPONENT-680;Lo;0;L;;;;;N;;;;; 18AA8;TANGUT COMPONENT-681;Lo;0;L;;;;;N;;;;; 18AA9;TANGUT COMPONENT-682;Lo;0;L;;;;;N;;;;; 18AAA;TANGUT COMPONENT-683;Lo;0;L;;;;;N;;;;; 18AAB;TANGUT COMPONENT-684;Lo;0;L;;;;;N;;;;; 18AAC;TANGUT COMPONENT-685;Lo;0;L;;;;;N;;;;; 18AAD;TANGUT COMPONENT-686;Lo;0;L;;;;;N;;;;; 18AAE;TANGUT COMPONENT-687;Lo;0;L;;;;;N;;;;; 18AAF;TANGUT COMPONENT-688;Lo;0;L;;;;;N;;;;; 18AB0;TANGUT COMPONENT-689;Lo;0;L;;;;;N;;;;; 18AB1;TANGUT COMPONENT-690;Lo;0;L;;;;;N;;;;; 18AB2;TANGUT COMPONENT-691;Lo;0;L;;;;;N;;;;; 18AB3;TANGUT COMPONENT-692;Lo;0;L;;;;;N;;;;; 18AB4;TANGUT COMPONENT-693;Lo;0;L;;;;;N;;;;; 18AB5;TANGUT COMPONENT-694;Lo;0;L;;;;;N;;;;; 18AB6;TANGUT COMPONENT-695;Lo;0;L;;;;;N;;;;; 18AB7;TANGUT COMPONENT-696;Lo;0;L;;;;;N;;;;; 18AB8;TANGUT COMPONENT-697;Lo;0;L;;;;;N;;;;; 18AB9;TANGUT COMPONENT-698;Lo;0;L;;;;;N;;;;; 18ABA;TANGUT COMPONENT-699;Lo;0;L;;;;;N;;;;; 18ABB;TANGUT COMPONENT-700;Lo;0;L;;;;;N;;;;; 18ABC;TANGUT COMPONENT-701;Lo;0;L;;;;;N;;;;; 18ABD;TANGUT COMPONENT-702;Lo;0;L;;;;;N;;;;; 18ABE;TANGUT COMPONENT-703;Lo;0;L;;;;;N;;;;; 18ABF;TANGUT COMPONENT-704;Lo;0;L;;;;;N;;;;; 18AC0;TANGUT COMPONENT-705;Lo;0;L;;;;;N;;;;; 18AC1;TANGUT COMPONENT-706;Lo;0;L;;;;;N;;;;; 18AC2;TANGUT COMPONENT-707;Lo;0;L;;;;;N;;;;; 18AC3;TANGUT COMPONENT-708;Lo;0;L;;;;;N;;;;; 18AC4;TANGUT COMPONENT-709;Lo;0;L;;;;;N;;;;; 18AC5;TANGUT COMPONENT-710;Lo;0;L;;;;;N;;;;; 18AC6;TANGUT COMPONENT-711;Lo;0;L;;;;;N;;;;; 18AC7;TANGUT COMPONENT-712;Lo;0;L;;;;;N;;;;; 18AC8;TANGUT COMPONENT-713;Lo;0;L;;;;;N;;;;; 18AC9;TANGUT COMPONENT-714;Lo;0;L;;;;;N;;;;; 18ACA;TANGUT COMPONENT-715;Lo;0;L;;;;;N;;;;; 18ACB;TANGUT COMPONENT-716;Lo;0;L;;;;;N;;;;; 18ACC;TANGUT COMPONENT-717;Lo;0;L;;;;;N;;;;; 18ACD;TANGUT COMPONENT-718;Lo;0;L;;;;;N;;;;; 18ACE;TANGUT COMPONENT-719;Lo;0;L;;;;;N;;;;; 18ACF;TANGUT COMPONENT-720;Lo;0;L;;;;;N;;;;; 18AD0;TANGUT COMPONENT-721;Lo;0;L;;;;;N;;;;; 18AD1;TANGUT COMPONENT-722;Lo;0;L;;;;;N;;;;; 18AD2;TANGUT COMPONENT-723;Lo;0;L;;;;;N;;;;; 18AD3;TANGUT COMPONENT-724;Lo;0;L;;;;;N;;;;; 18AD4;TANGUT COMPONENT-725;Lo;0;L;;;;;N;;;;; 18AD5;TANGUT COMPONENT-726;Lo;0;L;;;;;N;;;;; 18AD6;TANGUT COMPONENT-727;Lo;0;L;;;;;N;;;;; 18AD7;TANGUT COMPONENT-728;Lo;0;L;;;;;N;;;;; 18AD8;TANGUT COMPONENT-729;Lo;0;L;;;;;N;;;;; 18AD9;TANGUT COMPONENT-730;Lo;0;L;;;;;N;;;;; 18ADA;TANGUT COMPONENT-731;Lo;0;L;;;;;N;;;;; 18ADB;TANGUT COMPONENT-732;Lo;0;L;;;;;N;;;;; 18ADC;TANGUT COMPONENT-733;Lo;0;L;;;;;N;;;;; 18ADD;TANGUT COMPONENT-734;Lo;0;L;;;;;N;;;;; 18ADE;TANGUT COMPONENT-735;Lo;0;L;;;;;N;;;;; 18ADF;TANGUT COMPONENT-736;Lo;0;L;;;;;N;;;;; 18AE0;TANGUT COMPONENT-737;Lo;0;L;;;;;N;;;;; 18AE1;TANGUT COMPONENT-738;Lo;0;L;;;;;N;;;;; 18AE2;TANGUT COMPONENT-739;Lo;0;L;;;;;N;;;;; 18AE3;TANGUT COMPONENT-740;Lo;0;L;;;;;N;;;;; 18AE4;TANGUT COMPONENT-741;Lo;0;L;;;;;N;;;;; 18AE5;TANGUT COMPONENT-742;Lo;0;L;;;;;N;;;;; 18AE6;TANGUT COMPONENT-743;Lo;0;L;;;;;N;;;;; 18AE7;TANGUT COMPONENT-744;Lo;0;L;;;;;N;;;;; 18AE8;TANGUT COMPONENT-745;Lo;0;L;;;;;N;;;;; 18AE9;TANGUT COMPONENT-746;Lo;0;L;;;;;N;;;;; 18AEA;TANGUT COMPONENT-747;Lo;0;L;;;;;N;;;;; 18AEB;TANGUT COMPONENT-748;Lo;0;L;;;;;N;;;;; 18AEC;TANGUT COMPONENT-749;Lo;0;L;;;;;N;;;;; 18AED;TANGUT COMPONENT-750;Lo;0;L;;;;;N;;;;; 18AEE;TANGUT COMPONENT-751;Lo;0;L;;;;;N;;;;; 18AEF;TANGUT COMPONENT-752;Lo;0;L;;;;;N;;;;; 18AF0;TANGUT COMPONENT-753;Lo;0;L;;;;;N;;;;; 18AF1;TANGUT COMPONENT-754;Lo;0;L;;;;;N;;;;; 18AF2;TANGUT COMPONENT-755;Lo;0;L;;;;;N;;;;; 1B000;KATAKANA LETTER ARCHAIC E;Lo;0;L;;;;;N;;;;; 1B001;HIRAGANA LETTER ARCHAIC YE;Lo;0;L;;;;;N;;;;; 1BC00;DUPLOYAN LETTER H;Lo;0;L;;;;;N;;;;; 1BC01;DUPLOYAN LETTER X;Lo;0;L;;;;;N;;;;; 1BC02;DUPLOYAN LETTER P;Lo;0;L;;;;;N;;;;; 1BC03;DUPLOYAN LETTER T;Lo;0;L;;;;;N;;;;; 1BC04;DUPLOYAN LETTER F;Lo;0;L;;;;;N;;;;; 1BC05;DUPLOYAN LETTER K;Lo;0;L;;;;;N;;;;; 1BC06;DUPLOYAN LETTER L;Lo;0;L;;;;;N;;;;; 1BC07;DUPLOYAN LETTER B;Lo;0;L;;;;;N;;;;; 1BC08;DUPLOYAN LETTER D;Lo;0;L;;;;;N;;;;; 1BC09;DUPLOYAN LETTER V;Lo;0;L;;;;;N;;;;; 1BC0A;DUPLOYAN LETTER G;Lo;0;L;;;;;N;;;;; 1BC0B;DUPLOYAN LETTER R;Lo;0;L;;;;;N;;;;; 1BC0C;DUPLOYAN LETTER P N;Lo;0;L;;;;;N;;;;; 1BC0D;DUPLOYAN LETTER D S;Lo;0;L;;;;;N;;;;; 1BC0E;DUPLOYAN LETTER F N;Lo;0;L;;;;;N;;;;; 1BC0F;DUPLOYAN LETTER K M;Lo;0;L;;;;;N;;;;; 1BC10;DUPLOYAN LETTER R S;Lo;0;L;;;;;N;;;;; 1BC11;DUPLOYAN LETTER TH;Lo;0;L;;;;;N;;;;; 1BC12;DUPLOYAN LETTER SLOAN DH;Lo;0;L;;;;;N;;;;; 1BC13;DUPLOYAN LETTER DH;Lo;0;L;;;;;N;;;;; 1BC14;DUPLOYAN LETTER KK;Lo;0;L;;;;;N;;;;; 1BC15;DUPLOYAN LETTER SLOAN J;Lo;0;L;;;;;N;;;;; 1BC16;DUPLOYAN LETTER HL;Lo;0;L;;;;;N;;;;; 1BC17;DUPLOYAN LETTER LH;Lo;0;L;;;;;N;;;;; 1BC18;DUPLOYAN LETTER RH;Lo;0;L;;;;;N;;;;; 1BC19;DUPLOYAN LETTER M;Lo;0;L;;;;;N;;;;; 1BC1A;DUPLOYAN LETTER N;Lo;0;L;;;;;N;;;;; 1BC1B;DUPLOYAN LETTER J;Lo;0;L;;;;;N;;;;; 1BC1C;DUPLOYAN LETTER S;Lo;0;L;;;;;N;;;;; 1BC1D;DUPLOYAN LETTER M N;Lo;0;L;;;;;N;;;;; 1BC1E;DUPLOYAN LETTER N M;Lo;0;L;;;;;N;;;;; 1BC1F;DUPLOYAN LETTER J M;Lo;0;L;;;;;N;;;;; 1BC20;DUPLOYAN LETTER S J;Lo;0;L;;;;;N;;;;; 1BC21;DUPLOYAN LETTER M WITH DOT;Lo;0;L;;;;;N;;;;; 1BC22;DUPLOYAN LETTER N WITH DOT;Lo;0;L;;;;;N;;;;; 1BC23;DUPLOYAN LETTER J WITH DOT;Lo;0;L;;;;;N;;;;; 1BC24;DUPLOYAN LETTER J WITH DOTS INSIDE AND ABOVE;Lo;0;L;;;;;N;;;;; 1BC25;DUPLOYAN LETTER S WITH DOT;Lo;0;L;;;;;N;;;;; 1BC26;DUPLOYAN LETTER S WITH DOT BELOW;Lo;0;L;;;;;N;;;;; 1BC27;DUPLOYAN LETTER M S;Lo;0;L;;;;;N;;;;; 1BC28;DUPLOYAN LETTER N S;Lo;0;L;;;;;N;;;;; 1BC29;DUPLOYAN LETTER J S;Lo;0;L;;;;;N;;;;; 1BC2A;DUPLOYAN LETTER S S;Lo;0;L;;;;;N;;;;; 1BC2B;DUPLOYAN LETTER M N S;Lo;0;L;;;;;N;;;;; 1BC2C;DUPLOYAN LETTER N M S;Lo;0;L;;;;;N;;;;; 1BC2D;DUPLOYAN LETTER J M S;Lo;0;L;;;;;N;;;;; 1BC2E;DUPLOYAN LETTER S J S;Lo;0;L;;;;;N;;;;; 1BC2F;DUPLOYAN LETTER J S WITH DOT;Lo;0;L;;;;;N;;;;; 1BC30;DUPLOYAN LETTER J N;Lo;0;L;;;;;N;;;;; 1BC31;DUPLOYAN LETTER J N S;Lo;0;L;;;;;N;;;;; 1BC32;DUPLOYAN LETTER S T;Lo;0;L;;;;;N;;;;; 1BC33;DUPLOYAN LETTER S T R;Lo;0;L;;;;;N;;;;; 1BC34;DUPLOYAN LETTER S P;Lo;0;L;;;;;N;;;;; 1BC35;DUPLOYAN LETTER S P R;Lo;0;L;;;;;N;;;;; 1BC36;DUPLOYAN LETTER T S;Lo;0;L;;;;;N;;;;; 1BC37;DUPLOYAN LETTER T R S;Lo;0;L;;;;;N;;;;; 1BC38;DUPLOYAN LETTER W;Lo;0;L;;;;;N;;;;; 1BC39;DUPLOYAN LETTER WH;Lo;0;L;;;;;N;;;;; 1BC3A;DUPLOYAN LETTER W R;Lo;0;L;;;;;N;;;;; 1BC3B;DUPLOYAN LETTER S N;Lo;0;L;;;;;N;;;;; 1BC3C;DUPLOYAN LETTER S M;Lo;0;L;;;;;N;;;;; 1BC3D;DUPLOYAN LETTER K R S;Lo;0;L;;;;;N;;;;; 1BC3E;DUPLOYAN LETTER G R S;Lo;0;L;;;;;N;;;;; 1BC3F;DUPLOYAN LETTER S K;Lo;0;L;;;;;N;;;;; 1BC40;DUPLOYAN LETTER S K R;Lo;0;L;;;;;N;;;;; 1BC41;DUPLOYAN LETTER A;Lo;0;L;;;;;N;;;;; 1BC42;DUPLOYAN LETTER SLOAN OW;Lo;0;L;;;;;N;;;;; 1BC43;DUPLOYAN LETTER OA;Lo;0;L;;;;;N;;;;; 1BC44;DUPLOYAN LETTER O;Lo;0;L;;;;;N;;;;; 1BC45;DUPLOYAN LETTER AOU;Lo;0;L;;;;;N;;;;; 1BC46;DUPLOYAN LETTER I;Lo;0;L;;;;;N;;;;; 1BC47;DUPLOYAN LETTER E;Lo;0;L;;;;;N;;;;; 1BC48;DUPLOYAN LETTER IE;Lo;0;L;;;;;N;;;;; 1BC49;DUPLOYAN LETTER SHORT I;Lo;0;L;;;;;N;;;;; 1BC4A;DUPLOYAN LETTER UI;Lo;0;L;;;;;N;;;;; 1BC4B;DUPLOYAN LETTER EE;Lo;0;L;;;;;N;;;;; 1BC4C;DUPLOYAN LETTER SLOAN EH;Lo;0;L;;;;;N;;;;; 1BC4D;DUPLOYAN LETTER ROMANIAN I;Lo;0;L;;;;;N;;;;; 1BC4E;DUPLOYAN LETTER SLOAN EE;Lo;0;L;;;;;N;;;;; 1BC4F;DUPLOYAN LETTER LONG I;Lo;0;L;;;;;N;;;;; 1BC50;DUPLOYAN LETTER YE;Lo;0;L;;;;;N;;;;; 1BC51;DUPLOYAN LETTER U;Lo;0;L;;;;;N;;;;; 1BC52;DUPLOYAN LETTER EU;Lo;0;L;;;;;N;;;;; 1BC53;DUPLOYAN LETTER XW;Lo;0;L;;;;;N;;;;; 1BC54;DUPLOYAN LETTER U N;Lo;0;L;;;;;N;;;;; 1BC55;DUPLOYAN LETTER LONG U;Lo;0;L;;;;;N;;;;; 1BC56;DUPLOYAN LETTER ROMANIAN U;Lo;0;L;;;;;N;;;;; 1BC57;DUPLOYAN LETTER UH;Lo;0;L;;;;;N;;;;; 1BC58;DUPLOYAN LETTER SLOAN U;Lo;0;L;;;;;N;;;;; 1BC59;DUPLOYAN LETTER OOH;Lo;0;L;;;;;N;;;;; 1BC5A;DUPLOYAN LETTER OW;Lo;0;L;;;;;N;;;;; 1BC5B;DUPLOYAN LETTER OU;Lo;0;L;;;;;N;;;;; 1BC5C;DUPLOYAN LETTER WA;Lo;0;L;;;;;N;;;;; 1BC5D;DUPLOYAN LETTER WO;Lo;0;L;;;;;N;;;;; 1BC5E;DUPLOYAN LETTER WI;Lo;0;L;;;;;N;;;;; 1BC5F;DUPLOYAN LETTER WEI;Lo;0;L;;;;;N;;;;; 1BC60;DUPLOYAN LETTER WOW;Lo;0;L;;;;;N;;;;; 1BC61;DUPLOYAN LETTER NASAL U;Lo;0;L;;;;;N;;;;; 1BC62;DUPLOYAN LETTER NASAL O;Lo;0;L;;;;;N;;;;; 1BC63;DUPLOYAN LETTER NASAL I;Lo;0;L;;;;;N;;;;; 1BC64;DUPLOYAN LETTER NASAL A;Lo;0;L;;;;;N;;;;; 1BC65;DUPLOYAN LETTER PERNIN AN;Lo;0;L;;;;;N;;;;; 1BC66;DUPLOYAN LETTER PERNIN AM;Lo;0;L;;;;;N;;;;; 1BC67;DUPLOYAN LETTER SLOAN EN;Lo;0;L;;;;;N;;;;; 1BC68;DUPLOYAN LETTER SLOAN AN;Lo;0;L;;;;;N;;;;; 1BC69;DUPLOYAN LETTER SLOAN ON;Lo;0;L;;;;;N;;;;; 1BC6A;DUPLOYAN LETTER VOCALIC M;Lo;0;L;;;;;N;;;;; 1BC70;DUPLOYAN AFFIX LEFT HORIZONTAL SECANT;Lo;0;L;;;;;N;;;;; 1BC71;DUPLOYAN AFFIX MID HORIZONTAL SECANT;Lo;0;L;;;;;N;;;;; 1BC72;DUPLOYAN AFFIX RIGHT HORIZONTAL SECANT;Lo;0;L;;;;;N;;;;; 1BC73;DUPLOYAN AFFIX LOW VERTICAL SECANT;Lo;0;L;;;;;N;;;;; 1BC74;DUPLOYAN AFFIX MID VERTICAL SECANT;Lo;0;L;;;;;N;;;;; 1BC75;DUPLOYAN AFFIX HIGH VERTICAL SECANT;Lo;0;L;;;;;N;;;;; 1BC76;DUPLOYAN AFFIX ATTACHED SECANT;Lo;0;L;;;;;N;;;;; 1BC77;DUPLOYAN AFFIX ATTACHED LEFT-TO-RIGHT SECANT;Lo;0;L;;;;;N;;;;; 1BC78;DUPLOYAN AFFIX ATTACHED TANGENT;Lo;0;L;;;;;N;;;;; 1BC79;DUPLOYAN AFFIX ATTACHED TAIL;Lo;0;L;;;;;N;;;;; 1BC7A;DUPLOYAN AFFIX ATTACHED E HOOK;Lo;0;L;;;;;N;;;;; 1BC7B;DUPLOYAN AFFIX ATTACHED I HOOK;Lo;0;L;;;;;N;;;;; 1BC7C;DUPLOYAN AFFIX ATTACHED TANGENT HOOK;Lo;0;L;;;;;N;;;;; 1BC80;DUPLOYAN AFFIX HIGH ACUTE;Lo;0;L;;;;;N;;;;; 1BC81;DUPLOYAN AFFIX HIGH TIGHT ACUTE;Lo;0;L;;;;;N;;;;; 1BC82;DUPLOYAN AFFIX HIGH GRAVE;Lo;0;L;;;;;N;;;;; 1BC83;DUPLOYAN AFFIX HIGH LONG GRAVE;Lo;0;L;;;;;N;;;;; 1BC84;DUPLOYAN AFFIX HIGH DOT;Lo;0;L;;;;;N;;;;; 1BC85;DUPLOYAN AFFIX HIGH CIRCLE;Lo;0;L;;;;;N;;;;; 1BC86;DUPLOYAN AFFIX HIGH LINE;Lo;0;L;;;;;N;;;;; 1BC87;DUPLOYAN AFFIX HIGH WAVE;Lo;0;L;;;;;N;;;;; 1BC88;DUPLOYAN AFFIX HIGH VERTICAL;Lo;0;L;;;;;N;;;;; 1BC90;DUPLOYAN AFFIX LOW ACUTE;Lo;0;L;;;;;N;;;;; 1BC91;DUPLOYAN AFFIX LOW TIGHT ACUTE;Lo;0;L;;;;;N;;;;; 1BC92;DUPLOYAN AFFIX LOW GRAVE;Lo;0;L;;;;;N;;;;; 1BC93;DUPLOYAN AFFIX LOW LONG GRAVE;Lo;0;L;;;;;N;;;;; 1BC94;DUPLOYAN AFFIX LOW DOT;Lo;0;L;;;;;N;;;;; 1BC95;DUPLOYAN AFFIX LOW CIRCLE;Lo;0;L;;;;;N;;;;; 1BC96;DUPLOYAN AFFIX LOW LINE;Lo;0;L;;;;;N;;;;; 1BC97;DUPLOYAN AFFIX LOW WAVE;Lo;0;L;;;;;N;;;;; 1BC98;DUPLOYAN AFFIX LOW VERTICAL;Lo;0;L;;;;;N;;;;; 1BC99;DUPLOYAN AFFIX LOW ARROW;Lo;0;L;;;;;N;;;;; 1BC9C;DUPLOYAN SIGN O WITH CROSS;So;0;L;;;;;N;;;;; 1BC9D;DUPLOYAN THICK LETTER SELECTOR;Mn;0;NSM;;;;;N;;;;; 1BC9E;DUPLOYAN DOUBLE MARK;Mn;1;NSM;;;;;N;;;;; 1BC9F;DUPLOYAN PUNCTUATION CHINOOK FULL STOP;Po;0;L;;;;;N;;;;; 1BCA0;SHORTHAND FORMAT LETTER OVERLAP;Cf;0;BN;;;;;N;;;;; 1BCA1;SHORTHAND FORMAT CONTINUING OVERLAP;Cf;0;BN;;;;;N;;;;; 1BCA2;SHORTHAND FORMAT DOWN STEP;Cf;0;BN;;;;;N;;;;; 1BCA3;SHORTHAND FORMAT UP STEP;Cf;0;BN;;;;;N;;;;; 1D000;BYZANTINE MUSICAL SYMBOL PSILI;So;0;L;;;;;N;;;;; 1D001;BYZANTINE MUSICAL SYMBOL DASEIA;So;0;L;;;;;N;;;;; 1D002;BYZANTINE MUSICAL SYMBOL PERISPOMENI;So;0;L;;;;;N;;;;; 1D003;BYZANTINE MUSICAL SYMBOL OXEIA EKFONITIKON;So;0;L;;;;;N;;;;; 1D004;BYZANTINE MUSICAL SYMBOL OXEIA DIPLI;So;0;L;;;;;N;;;;; 1D005;BYZANTINE MUSICAL SYMBOL VAREIA EKFONITIKON;So;0;L;;;;;N;;;;; 1D006;BYZANTINE MUSICAL SYMBOL VAREIA DIPLI;So;0;L;;;;;N;;;;; 1D007;BYZANTINE MUSICAL SYMBOL KATHISTI;So;0;L;;;;;N;;;;; 1D008;BYZANTINE MUSICAL SYMBOL SYRMATIKI;So;0;L;;;;;N;;;;; 1D009;BYZANTINE MUSICAL SYMBOL PARAKLITIKI;So;0;L;;;;;N;;;;; 1D00A;BYZANTINE MUSICAL SYMBOL YPOKRISIS;So;0;L;;;;;N;;;;; 1D00B;BYZANTINE MUSICAL SYMBOL YPOKRISIS DIPLI;So;0;L;;;;;N;;;;; 1D00C;BYZANTINE MUSICAL SYMBOL KREMASTI;So;0;L;;;;;N;;;;; 1D00D;BYZANTINE MUSICAL SYMBOL APESO EKFONITIKON;So;0;L;;;;;N;;;;; 1D00E;BYZANTINE MUSICAL SYMBOL EXO EKFONITIKON;So;0;L;;;;;N;;;;; 1D00F;BYZANTINE MUSICAL SYMBOL TELEIA;So;0;L;;;;;N;;;;; 1D010;BYZANTINE MUSICAL SYMBOL KENTIMATA;So;0;L;;;;;N;;;;; 1D011;BYZANTINE MUSICAL SYMBOL APOSTROFOS;So;0;L;;;;;N;;;;; 1D012;BYZANTINE MUSICAL SYMBOL APOSTROFOS DIPLI;So;0;L;;;;;N;;;;; 1D013;BYZANTINE MUSICAL SYMBOL SYNEVMA;So;0;L;;;;;N;;;;; 1D014;BYZANTINE MUSICAL SYMBOL THITA;So;0;L;;;;;N;;;;; 1D015;BYZANTINE MUSICAL SYMBOL OLIGON ARCHAION;So;0;L;;;;;N;;;;; 1D016;BYZANTINE MUSICAL SYMBOL GORGON ARCHAION;So;0;L;;;;;N;;;;; 1D017;BYZANTINE MUSICAL SYMBOL PSILON;So;0;L;;;;;N;;;;; 1D018;BYZANTINE MUSICAL SYMBOL CHAMILON;So;0;L;;;;;N;;;;; 1D019;BYZANTINE MUSICAL SYMBOL VATHY;So;0;L;;;;;N;;;;; 1D01A;BYZANTINE MUSICAL SYMBOL ISON ARCHAION;So;0;L;;;;;N;;;;; 1D01B;BYZANTINE MUSICAL SYMBOL KENTIMA ARCHAION;So;0;L;;;;;N;;;;; 1D01C;BYZANTINE MUSICAL SYMBOL KENTIMATA ARCHAION;So;0;L;;;;;N;;;;; 1D01D;BYZANTINE MUSICAL SYMBOL SAXIMATA;So;0;L;;;;;N;;;;; 1D01E;BYZANTINE MUSICAL SYMBOL PARICHON;So;0;L;;;;;N;;;;; 1D01F;BYZANTINE MUSICAL SYMBOL STAVROS APODEXIA;So;0;L;;;;;N;;;;; 1D020;BYZANTINE MUSICAL SYMBOL OXEIAI ARCHAION;So;0;L;;;;;N;;;;; 1D021;BYZANTINE MUSICAL SYMBOL VAREIAI ARCHAION;So;0;L;;;;;N;;;;; 1D022;BYZANTINE MUSICAL SYMBOL APODERMA ARCHAION;So;0;L;;;;;N;;;;; 1D023;BYZANTINE MUSICAL SYMBOL APOTHEMA;So;0;L;;;;;N;;;;; 1D024;BYZANTINE MUSICAL SYMBOL KLASMA;So;0;L;;;;;N;;;;; 1D025;BYZANTINE MUSICAL SYMBOL REVMA;So;0;L;;;;;N;;;;; 1D026;BYZANTINE MUSICAL SYMBOL PIASMA ARCHAION;So;0;L;;;;;N;;;;; 1D027;BYZANTINE MUSICAL SYMBOL TINAGMA;So;0;L;;;;;N;;;;; 1D028;BYZANTINE MUSICAL SYMBOL ANATRICHISMA;So;0;L;;;;;N;;;;; 1D029;BYZANTINE MUSICAL SYMBOL SEISMA;So;0;L;;;;;N;;;;; 1D02A;BYZANTINE MUSICAL SYMBOL SYNAGMA ARCHAION;So;0;L;;;;;N;;;;; 1D02B;BYZANTINE MUSICAL SYMBOL SYNAGMA META STAVROU;So;0;L;;;;;N;;;;; 1D02C;BYZANTINE MUSICAL SYMBOL OYRANISMA ARCHAION;So;0;L;;;;;N;;;;; 1D02D;BYZANTINE MUSICAL SYMBOL THEMA;So;0;L;;;;;N;;;;; 1D02E;BYZANTINE MUSICAL SYMBOL LEMOI;So;0;L;;;;;N;;;;; 1D02F;BYZANTINE MUSICAL SYMBOL DYO;So;0;L;;;;;N;;;;; 1D030;BYZANTINE MUSICAL SYMBOL TRIA;So;0;L;;;;;N;;;;; 1D031;BYZANTINE MUSICAL SYMBOL TESSERA;So;0;L;;;;;N;;;;; 1D032;BYZANTINE MUSICAL SYMBOL KRATIMATA;So;0;L;;;;;N;;;;; 1D033;BYZANTINE MUSICAL SYMBOL APESO EXO NEO;So;0;L;;;;;N;;;;; 1D034;BYZANTINE MUSICAL SYMBOL FTHORA ARCHAION;So;0;L;;;;;N;;;;; 1D035;BYZANTINE MUSICAL SYMBOL IMIFTHORA;So;0;L;;;;;N;;;;; 1D036;BYZANTINE MUSICAL SYMBOL TROMIKON ARCHAION;So;0;L;;;;;N;;;;; 1D037;BYZANTINE MUSICAL SYMBOL KATAVA TROMIKON;So;0;L;;;;;N;;;;; 1D038;BYZANTINE MUSICAL SYMBOL PELASTON;So;0;L;;;;;N;;;;; 1D039;BYZANTINE MUSICAL SYMBOL PSIFISTON;So;0;L;;;;;N;;;;; 1D03A;BYZANTINE MUSICAL SYMBOL KONTEVMA;So;0;L;;;;;N;;;;; 1D03B;BYZANTINE MUSICAL SYMBOL CHOREVMA ARCHAION;So;0;L;;;;;N;;;;; 1D03C;BYZANTINE MUSICAL SYMBOL RAPISMA;So;0;L;;;;;N;;;;; 1D03D;BYZANTINE MUSICAL SYMBOL PARAKALESMA ARCHAION;So;0;L;;;;;N;;;;; 1D03E;BYZANTINE MUSICAL SYMBOL PARAKLITIKI ARCHAION;So;0;L;;;;;N;;;;; 1D03F;BYZANTINE MUSICAL SYMBOL ICHADIN;So;0;L;;;;;N;;;;; 1D040;BYZANTINE MUSICAL SYMBOL NANA;So;0;L;;;;;N;;;;; 1D041;BYZANTINE MUSICAL SYMBOL PETASMA;So;0;L;;;;;N;;;;; 1D042;BYZANTINE MUSICAL SYMBOL KONTEVMA ALLO;So;0;L;;;;;N;;;;; 1D043;BYZANTINE MUSICAL SYMBOL TROMIKON ALLO;So;0;L;;;;;N;;;;; 1D044;BYZANTINE MUSICAL SYMBOL STRAGGISMATA;So;0;L;;;;;N;;;;; 1D045;BYZANTINE MUSICAL SYMBOL GRONTHISMATA;So;0;L;;;;;N;;;;; 1D046;BYZANTINE MUSICAL SYMBOL ISON NEO;So;0;L;;;;;N;;;;; 1D047;BYZANTINE MUSICAL SYMBOL OLIGON NEO;So;0;L;;;;;N;;;;; 1D048;BYZANTINE MUSICAL SYMBOL OXEIA NEO;So;0;L;;;;;N;;;;; 1D049;BYZANTINE MUSICAL SYMBOL PETASTI;So;0;L;;;;;N;;;;; 1D04A;BYZANTINE MUSICAL SYMBOL KOUFISMA;So;0;L;;;;;N;;;;; 1D04B;BYZANTINE MUSICAL SYMBOL PETASTOKOUFISMA;So;0;L;;;;;N;;;;; 1D04C;BYZANTINE MUSICAL SYMBOL KRATIMOKOUFISMA;So;0;L;;;;;N;;;;; 1D04D;BYZANTINE MUSICAL SYMBOL PELASTON NEO;So;0;L;;;;;N;;;;; 1D04E;BYZANTINE MUSICAL SYMBOL KENTIMATA NEO ANO;So;0;L;;;;;N;;;;; 1D04F;BYZANTINE MUSICAL SYMBOL KENTIMA NEO ANO;So;0;L;;;;;N;;;;; 1D050;BYZANTINE MUSICAL SYMBOL YPSILI;So;0;L;;;;;N;;;;; 1D051;BYZANTINE MUSICAL SYMBOL APOSTROFOS NEO;So;0;L;;;;;N;;;;; 1D052;BYZANTINE MUSICAL SYMBOL APOSTROFOI SYNDESMOS NEO;So;0;L;;;;;N;;;;; 1D053;BYZANTINE MUSICAL SYMBOL YPORROI;So;0;L;;;;;N;;;;; 1D054;BYZANTINE MUSICAL SYMBOL KRATIMOYPORROON;So;0;L;;;;;N;;;;; 1D055;BYZANTINE MUSICAL SYMBOL ELAFRON;So;0;L;;;;;N;;;;; 1D056;BYZANTINE MUSICAL SYMBOL CHAMILI;So;0;L;;;;;N;;;;; 1D057;BYZANTINE MUSICAL SYMBOL MIKRON ISON;So;0;L;;;;;N;;;;; 1D058;BYZANTINE MUSICAL SYMBOL VAREIA NEO;So;0;L;;;;;N;;;;; 1D059;BYZANTINE MUSICAL SYMBOL PIASMA NEO;So;0;L;;;;;N;;;;; 1D05A;BYZANTINE MUSICAL SYMBOL PSIFISTON NEO;So;0;L;;;;;N;;;;; 1D05B;BYZANTINE MUSICAL SYMBOL OMALON;So;0;L;;;;;N;;;;; 1D05C;BYZANTINE MUSICAL SYMBOL ANTIKENOMA;So;0;L;;;;;N;;;;; 1D05D;BYZANTINE MUSICAL SYMBOL LYGISMA;So;0;L;;;;;N;;;;; 1D05E;BYZANTINE MUSICAL SYMBOL PARAKLITIKI NEO;So;0;L;;;;;N;;;;; 1D05F;BYZANTINE MUSICAL SYMBOL PARAKALESMA NEO;So;0;L;;;;;N;;;;; 1D060;BYZANTINE MUSICAL SYMBOL ETERON PARAKALESMA;So;0;L;;;;;N;;;;; 1D061;BYZANTINE MUSICAL SYMBOL KYLISMA;So;0;L;;;;;N;;;;; 1D062;BYZANTINE MUSICAL SYMBOL ANTIKENOKYLISMA;So;0;L;;;;;N;;;;; 1D063;BYZANTINE MUSICAL SYMBOL TROMIKON NEO;So;0;L;;;;;N;;;;; 1D064;BYZANTINE MUSICAL SYMBOL EKSTREPTON;So;0;L;;;;;N;;;;; 1D065;BYZANTINE MUSICAL SYMBOL SYNAGMA NEO;So;0;L;;;;;N;;;;; 1D066;BYZANTINE MUSICAL SYMBOL SYRMA;So;0;L;;;;;N;;;;; 1D067;BYZANTINE MUSICAL SYMBOL CHOREVMA NEO;So;0;L;;;;;N;;;;; 1D068;BYZANTINE MUSICAL SYMBOL EPEGERMA;So;0;L;;;;;N;;;;; 1D069;BYZANTINE MUSICAL SYMBOL SEISMA NEO;So;0;L;;;;;N;;;;; 1D06A;BYZANTINE MUSICAL SYMBOL XIRON KLASMA;So;0;L;;;;;N;;;;; 1D06B;BYZANTINE MUSICAL SYMBOL TROMIKOPSIFISTON;So;0;L;;;;;N;;;;; 1D06C;BYZANTINE MUSICAL SYMBOL PSIFISTOLYGISMA;So;0;L;;;;;N;;;;; 1D06D;BYZANTINE MUSICAL SYMBOL TROMIKOLYGISMA;So;0;L;;;;;N;;;;; 1D06E;BYZANTINE MUSICAL SYMBOL TROMIKOPARAKALESMA;So;0;L;;;;;N;;;;; 1D06F;BYZANTINE MUSICAL SYMBOL PSIFISTOPARAKALESMA;So;0;L;;;;;N;;;;; 1D070;BYZANTINE MUSICAL SYMBOL TROMIKOSYNAGMA;So;0;L;;;;;N;;;;; 1D071;BYZANTINE MUSICAL SYMBOL PSIFISTOSYNAGMA;So;0;L;;;;;N;;;;; 1D072;BYZANTINE MUSICAL SYMBOL GORGOSYNTHETON;So;0;L;;;;;N;;;;; 1D073;BYZANTINE MUSICAL SYMBOL ARGOSYNTHETON;So;0;L;;;;;N;;;;; 1D074;BYZANTINE MUSICAL SYMBOL ETERON ARGOSYNTHETON;So;0;L;;;;;N;;;;; 1D075;BYZANTINE MUSICAL SYMBOL OYRANISMA NEO;So;0;L;;;;;N;;;;; 1D076;BYZANTINE MUSICAL SYMBOL THEMATISMOS ESO;So;0;L;;;;;N;;;;; 1D077;BYZANTINE MUSICAL SYMBOL THEMATISMOS EXO;So;0;L;;;;;N;;;;; 1D078;BYZANTINE MUSICAL SYMBOL THEMA APLOUN;So;0;L;;;;;N;;;;; 1D079;BYZANTINE MUSICAL SYMBOL THES KAI APOTHES;So;0;L;;;;;N;;;;; 1D07A;BYZANTINE MUSICAL SYMBOL KATAVASMA;So;0;L;;;;;N;;;;; 1D07B;BYZANTINE MUSICAL SYMBOL ENDOFONON;So;0;L;;;;;N;;;;; 1D07C;BYZANTINE MUSICAL SYMBOL YFEN KATO;So;0;L;;;;;N;;;;; 1D07D;BYZANTINE MUSICAL SYMBOL YFEN ANO;So;0;L;;;;;N;;;;; 1D07E;BYZANTINE MUSICAL SYMBOL STAVROS;So;0;L;;;;;N;;;;; 1D07F;BYZANTINE MUSICAL SYMBOL KLASMA ANO;So;0;L;;;;;N;;;;; 1D080;BYZANTINE MUSICAL SYMBOL DIPLI ARCHAION;So;0;L;;;;;N;;;;; 1D081;BYZANTINE MUSICAL SYMBOL KRATIMA ARCHAION;So;0;L;;;;;N;;;;; 1D082;BYZANTINE MUSICAL SYMBOL KRATIMA ALLO;So;0;L;;;;;N;;;;; 1D083;BYZANTINE MUSICAL SYMBOL KRATIMA NEO;So;0;L;;;;;N;;;;; 1D084;BYZANTINE MUSICAL SYMBOL APODERMA NEO;So;0;L;;;;;N;;;;; 1D085;BYZANTINE MUSICAL SYMBOL APLI;So;0;L;;;;;N;;;;; 1D086;BYZANTINE MUSICAL SYMBOL DIPLI;So;0;L;;;;;N;;;;; 1D087;BYZANTINE MUSICAL SYMBOL TRIPLI;So;0;L;;;;;N;;;;; 1D088;BYZANTINE MUSICAL SYMBOL TETRAPLI;So;0;L;;;;;N;;;;; 1D089;BYZANTINE MUSICAL SYMBOL KORONIS;So;0;L;;;;;N;;;;; 1D08A;BYZANTINE MUSICAL SYMBOL LEIMMA ENOS CHRONOU;So;0;L;;;;;N;;;;; 1D08B;BYZANTINE MUSICAL SYMBOL LEIMMA DYO CHRONON;So;0;L;;;;;N;;;;; 1D08C;BYZANTINE MUSICAL SYMBOL LEIMMA TRION CHRONON;So;0;L;;;;;N;;;;; 1D08D;BYZANTINE MUSICAL SYMBOL LEIMMA TESSARON CHRONON;So;0;L;;;;;N;;;;; 1D08E;BYZANTINE MUSICAL SYMBOL LEIMMA IMISEOS CHRONOU;So;0;L;;;;;N;;;;; 1D08F;BYZANTINE MUSICAL SYMBOL GORGON NEO ANO;So;0;L;;;;;N;;;;; 1D090;BYZANTINE MUSICAL SYMBOL GORGON PARESTIGMENON ARISTERA;So;0;L;;;;;N;;;;; 1D091;BYZANTINE MUSICAL SYMBOL GORGON PARESTIGMENON DEXIA;So;0;L;;;;;N;;;;; 1D092;BYZANTINE MUSICAL SYMBOL DIGORGON;So;0;L;;;;;N;;;;; 1D093;BYZANTINE MUSICAL SYMBOL DIGORGON PARESTIGMENON ARISTERA KATO;So;0;L;;;;;N;;;;; 1D094;BYZANTINE MUSICAL SYMBOL DIGORGON PARESTIGMENON ARISTERA ANO;So;0;L;;;;;N;;;;; 1D095;BYZANTINE MUSICAL SYMBOL DIGORGON PARESTIGMENON DEXIA;So;0;L;;;;;N;;;;; 1D096;BYZANTINE MUSICAL SYMBOL TRIGORGON;So;0;L;;;;;N;;;;; 1D097;BYZANTINE MUSICAL SYMBOL ARGON;So;0;L;;;;;N;;;;; 1D098;BYZANTINE MUSICAL SYMBOL IMIDIARGON;So;0;L;;;;;N;;;;; 1D099;BYZANTINE MUSICAL SYMBOL DIARGON;So;0;L;;;;;N;;;;; 1D09A;BYZANTINE MUSICAL SYMBOL AGOGI POLI ARGI;So;0;L;;;;;N;;;;; 1D09B;BYZANTINE MUSICAL SYMBOL AGOGI ARGOTERI;So;0;L;;;;;N;;;;; 1D09C;BYZANTINE MUSICAL SYMBOL AGOGI ARGI;So;0;L;;;;;N;;;;; 1D09D;BYZANTINE MUSICAL SYMBOL AGOGI METRIA;So;0;L;;;;;N;;;;; 1D09E;BYZANTINE MUSICAL SYMBOL AGOGI MESI;So;0;L;;;;;N;;;;; 1D09F;BYZANTINE MUSICAL SYMBOL AGOGI GORGI;So;0;L;;;;;N;;;;; 1D0A0;BYZANTINE MUSICAL SYMBOL AGOGI GORGOTERI;So;0;L;;;;;N;;;;; 1D0A1;BYZANTINE MUSICAL SYMBOL AGOGI POLI GORGI;So;0;L;;;;;N;;;;; 1D0A2;BYZANTINE MUSICAL SYMBOL MARTYRIA PROTOS ICHOS;So;0;L;;;;;N;;;;; 1D0A3;BYZANTINE MUSICAL SYMBOL MARTYRIA ALLI PROTOS ICHOS;So;0;L;;;;;N;;;;; 1D0A4;BYZANTINE MUSICAL SYMBOL MARTYRIA DEYTEROS ICHOS;So;0;L;;;;;N;;;;; 1D0A5;BYZANTINE MUSICAL SYMBOL MARTYRIA ALLI DEYTEROS ICHOS;So;0;L;;;;;N;;;;; 1D0A6;BYZANTINE MUSICAL SYMBOL MARTYRIA TRITOS ICHOS;So;0;L;;;;;N;;;;; 1D0A7;BYZANTINE MUSICAL SYMBOL MARTYRIA TRIFONIAS;So;0;L;;;;;N;;;;; 1D0A8;BYZANTINE MUSICAL SYMBOL MARTYRIA TETARTOS ICHOS;So;0;L;;;;;N;;;;; 1D0A9;BYZANTINE MUSICAL SYMBOL MARTYRIA TETARTOS LEGETOS ICHOS;So;0;L;;;;;N;;;;; 1D0AA;BYZANTINE MUSICAL SYMBOL MARTYRIA LEGETOS ICHOS;So;0;L;;;;;N;;;;; 1D0AB;BYZANTINE MUSICAL SYMBOL MARTYRIA PLAGIOS ICHOS;So;0;L;;;;;N;;;;; 1D0AC;BYZANTINE MUSICAL SYMBOL ISAKIA TELOUS ICHIMATOS;So;0;L;;;;;N;;;;; 1D0AD;BYZANTINE MUSICAL SYMBOL APOSTROFOI TELOUS ICHIMATOS;So;0;L;;;;;N;;;;; 1D0AE;BYZANTINE MUSICAL SYMBOL FANEROSIS TETRAFONIAS;So;0;L;;;;;N;;;;; 1D0AF;BYZANTINE MUSICAL SYMBOL FANEROSIS MONOFONIAS;So;0;L;;;;;N;;;;; 1D0B0;BYZANTINE MUSICAL SYMBOL FANEROSIS DIFONIAS;So;0;L;;;;;N;;;;; 1D0B1;BYZANTINE MUSICAL SYMBOL MARTYRIA VARYS ICHOS;So;0;L;;;;;N;;;;; 1D0B2;BYZANTINE MUSICAL SYMBOL MARTYRIA PROTOVARYS ICHOS;So;0;L;;;;;N;;;;; 1D0B3;BYZANTINE MUSICAL SYMBOL MARTYRIA PLAGIOS TETARTOS ICHOS;So;0;L;;;;;N;;;;; 1D0B4;BYZANTINE MUSICAL SYMBOL GORTHMIKON N APLOUN;So;0;L;;;;;N;;;;; 1D0B5;BYZANTINE MUSICAL SYMBOL GORTHMIKON N DIPLOUN;So;0;L;;;;;N;;;;; 1D0B6;BYZANTINE MUSICAL SYMBOL ENARXIS KAI FTHORA VOU;So;0;L;;;;;N;;;;; 1D0B7;BYZANTINE MUSICAL SYMBOL IMIFONON;So;0;L;;;;;N;;;;; 1D0B8;BYZANTINE MUSICAL SYMBOL IMIFTHORON;So;0;L;;;;;N;;;;; 1D0B9;BYZANTINE MUSICAL SYMBOL FTHORA ARCHAION DEYTEROU ICHOU;So;0;L;;;;;N;;;;; 1D0BA;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI PA;So;0;L;;;;;N;;;;; 1D0BB;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI NANA;So;0;L;;;;;N;;;;; 1D0BC;BYZANTINE MUSICAL SYMBOL FTHORA NAOS ICHOS;So;0;L;;;;;N;;;;; 1D0BD;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI DI;So;0;L;;;;;N;;;;; 1D0BE;BYZANTINE MUSICAL SYMBOL FTHORA SKLIRON DIATONON DI;So;0;L;;;;;N;;;;; 1D0BF;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI KE;So;0;L;;;;;N;;;;; 1D0C0;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI ZO;So;0;L;;;;;N;;;;; 1D0C1;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI NI KATO;So;0;L;;;;;N;;;;; 1D0C2;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI NI ANO;So;0;L;;;;;N;;;;; 1D0C3;BYZANTINE MUSICAL SYMBOL FTHORA MALAKON CHROMA DIFONIAS;So;0;L;;;;;N;;;;; 1D0C4;BYZANTINE MUSICAL SYMBOL FTHORA MALAKON CHROMA MONOFONIAS;So;0;L;;;;;N;;;;; 1D0C5;BYZANTINE MUSICAL SYMBOL FHTORA SKLIRON CHROMA VASIS;So;0;L;;;;;N;;;;; 1D0C6;BYZANTINE MUSICAL SYMBOL FTHORA SKLIRON CHROMA SYNAFI;So;0;L;;;;;N;;;;; 1D0C7;BYZANTINE MUSICAL SYMBOL FTHORA NENANO;So;0;L;;;;;N;;;;; 1D0C8;BYZANTINE MUSICAL SYMBOL CHROA ZYGOS;So;0;L;;;;;N;;;;; 1D0C9;BYZANTINE MUSICAL SYMBOL CHROA KLITON;So;0;L;;;;;N;;;;; 1D0CA;BYZANTINE MUSICAL SYMBOL CHROA SPATHI;So;0;L;;;;;N;;;;; 1D0CB;BYZANTINE MUSICAL SYMBOL FTHORA I YFESIS TETARTIMORION;So;0;L;;;;;N;;;;; 1D0CC;BYZANTINE MUSICAL SYMBOL FTHORA ENARMONIOS ANTIFONIA;So;0;L;;;;;N;;;;; 1D0CD;BYZANTINE MUSICAL SYMBOL YFESIS TRITIMORION;So;0;L;;;;;N;;;;; 1D0CE;BYZANTINE MUSICAL SYMBOL DIESIS TRITIMORION;So;0;L;;;;;N;;;;; 1D0CF;BYZANTINE MUSICAL SYMBOL DIESIS TETARTIMORION;So;0;L;;;;;N;;;;; 1D0D0;BYZANTINE MUSICAL SYMBOL DIESIS APLI DYO DODEKATA;So;0;L;;;;;N;;;;; 1D0D1;BYZANTINE MUSICAL SYMBOL DIESIS MONOGRAMMOS TESSERA DODEKATA;So;0;L;;;;;N;;;;; 1D0D2;BYZANTINE MUSICAL SYMBOL DIESIS DIGRAMMOS EX DODEKATA;So;0;L;;;;;N;;;;; 1D0D3;BYZANTINE MUSICAL SYMBOL DIESIS TRIGRAMMOS OKTO DODEKATA;So;0;L;;;;;N;;;;; 1D0D4;BYZANTINE MUSICAL SYMBOL YFESIS APLI DYO DODEKATA;So;0;L;;;;;N;;;;; 1D0D5;BYZANTINE MUSICAL SYMBOL YFESIS MONOGRAMMOS TESSERA DODEKATA;So;0;L;;;;;N;;;;; 1D0D6;BYZANTINE MUSICAL SYMBOL YFESIS DIGRAMMOS EX DODEKATA;So;0;L;;;;;N;;;;; 1D0D7;BYZANTINE MUSICAL SYMBOL YFESIS TRIGRAMMOS OKTO DODEKATA;So;0;L;;;;;N;;;;; 1D0D8;BYZANTINE MUSICAL SYMBOL GENIKI DIESIS;So;0;L;;;;;N;;;;; 1D0D9;BYZANTINE MUSICAL SYMBOL GENIKI YFESIS;So;0;L;;;;;N;;;;; 1D0DA;BYZANTINE MUSICAL SYMBOL DIASTOLI APLI MIKRI;So;0;L;;;;;N;;;;; 1D0DB;BYZANTINE MUSICAL SYMBOL DIASTOLI APLI MEGALI;So;0;L;;;;;N;;;;; 1D0DC;BYZANTINE MUSICAL SYMBOL DIASTOLI DIPLI;So;0;L;;;;;N;;;;; 1D0DD;BYZANTINE MUSICAL SYMBOL DIASTOLI THESEOS;So;0;L;;;;;N;;;;; 1D0DE;BYZANTINE MUSICAL SYMBOL SIMANSIS THESEOS;So;0;L;;;;;N;;;;; 1D0DF;BYZANTINE MUSICAL SYMBOL SIMANSIS THESEOS DISIMOU;So;0;L;;;;;N;;;;; 1D0E0;BYZANTINE MUSICAL SYMBOL SIMANSIS THESEOS TRISIMOU;So;0;L;;;;;N;;;;; 1D0E1;BYZANTINE MUSICAL SYMBOL SIMANSIS THESEOS TETRASIMOU;So;0;L;;;;;N;;;;; 1D0E2;BYZANTINE MUSICAL SYMBOL SIMANSIS ARSEOS;So;0;L;;;;;N;;;;; 1D0E3;BYZANTINE MUSICAL SYMBOL SIMANSIS ARSEOS DISIMOU;So;0;L;;;;;N;;;;; 1D0E4;BYZANTINE MUSICAL SYMBOL SIMANSIS ARSEOS TRISIMOU;So;0;L;;;;;N;;;;; 1D0E5;BYZANTINE MUSICAL SYMBOL SIMANSIS ARSEOS TETRASIMOU;So;0;L;;;;;N;;;;; 1D0E6;BYZANTINE MUSICAL SYMBOL DIGRAMMA GG;So;0;L;;;;;N;;;;; 1D0E7;BYZANTINE MUSICAL SYMBOL DIFTOGGOS OU;So;0;L;;;;;N;;;;; 1D0E8;BYZANTINE MUSICAL SYMBOL STIGMA;So;0;L;;;;;N;;;;; 1D0E9;BYZANTINE MUSICAL SYMBOL ARKTIKO PA;So;0;L;;;;;N;;;;; 1D0EA;BYZANTINE MUSICAL SYMBOL ARKTIKO VOU;So;0;L;;;;;N;;;;; 1D0EB;BYZANTINE MUSICAL SYMBOL ARKTIKO GA;So;0;L;;;;;N;;;;; 1D0EC;BYZANTINE MUSICAL SYMBOL ARKTIKO DI;So;0;L;;;;;N;;;;; 1D0ED;BYZANTINE MUSICAL SYMBOL ARKTIKO KE;So;0;L;;;;;N;;;;; 1D0EE;BYZANTINE MUSICAL SYMBOL ARKTIKO ZO;So;0;L;;;;;N;;;;; 1D0EF;BYZANTINE MUSICAL SYMBOL ARKTIKO NI;So;0;L;;;;;N;;;;; 1D0F0;BYZANTINE MUSICAL SYMBOL KENTIMATA NEO MESO;So;0;L;;;;;N;;;;; 1D0F1;BYZANTINE MUSICAL SYMBOL KENTIMA NEO MESO;So;0;L;;;;;N;;;;; 1D0F2;BYZANTINE MUSICAL SYMBOL KENTIMATA NEO KATO;So;0;L;;;;;N;;;;; 1D0F3;BYZANTINE MUSICAL SYMBOL KENTIMA NEO KATO;So;0;L;;;;;N;;;;; 1D0F4;BYZANTINE MUSICAL SYMBOL KLASMA KATO;So;0;L;;;;;N;;;;; 1D0F5;BYZANTINE MUSICAL SYMBOL GORGON NEO KATO;So;0;L;;;;;N;;;;; 1D100;MUSICAL SYMBOL SINGLE BARLINE;So;0;L;;;;;N;;;;; 1D101;MUSICAL SYMBOL DOUBLE BARLINE;So;0;L;;;;;N;;;;; 1D102;MUSICAL SYMBOL FINAL BARLINE;So;0;L;;;;;N;;;;; 1D103;MUSICAL SYMBOL REVERSE FINAL BARLINE;So;0;L;;;;;N;;;;; 1D104;MUSICAL SYMBOL DASHED BARLINE;So;0;L;;;;;N;;;;; 1D105;MUSICAL SYMBOL SHORT BARLINE;So;0;L;;;;;N;;;;; 1D106;MUSICAL SYMBOL LEFT REPEAT SIGN;So;0;L;;;;;N;;;;; 1D107;MUSICAL SYMBOL RIGHT REPEAT SIGN;So;0;L;;;;;N;;;;; 1D108;MUSICAL SYMBOL REPEAT DOTS;So;0;L;;;;;N;;;;; 1D109;MUSICAL SYMBOL DAL SEGNO;So;0;L;;;;;N;;;;; 1D10A;MUSICAL SYMBOL DA CAPO;So;0;L;;;;;N;;;;; 1D10B;MUSICAL SYMBOL SEGNO;So;0;L;;;;;N;;;;; 1D10C;MUSICAL SYMBOL CODA;So;0;L;;;;;N;;;;; 1D10D;MUSICAL SYMBOL REPEATED FIGURE-1;So;0;L;;;;;N;;;;; 1D10E;MUSICAL SYMBOL REPEATED FIGURE-2;So;0;L;;;;;N;;;;; 1D10F;MUSICAL SYMBOL REPEATED FIGURE-3;So;0;L;;;;;N;;;;; 1D110;MUSICAL SYMBOL FERMATA;So;0;L;;;;;N;;;;; 1D111;MUSICAL SYMBOL FERMATA BELOW;So;0;L;;;;;N;;;;; 1D112;MUSICAL SYMBOL BREATH MARK;So;0;L;;;;;N;;;;; 1D113;MUSICAL SYMBOL CAESURA;So;0;L;;;;;N;;;;; 1D114;MUSICAL SYMBOL BRACE;So;0;L;;;;;N;;;;; 1D115;MUSICAL SYMBOL BRACKET;So;0;L;;;;;N;;;;; 1D116;MUSICAL SYMBOL ONE-LINE STAFF;So;0;L;;;;;N;;;;; 1D117;MUSICAL SYMBOL TWO-LINE STAFF;So;0;L;;;;;N;;;;; 1D118;MUSICAL SYMBOL THREE-LINE STAFF;So;0;L;;;;;N;;;;; 1D119;MUSICAL SYMBOL FOUR-LINE STAFF;So;0;L;;;;;N;;;;; 1D11A;MUSICAL SYMBOL FIVE-LINE STAFF;So;0;L;;;;;N;;;;; 1D11B;MUSICAL SYMBOL SIX-LINE STAFF;So;0;L;;;;;N;;;;; 1D11C;MUSICAL SYMBOL SIX-STRING FRETBOARD;So;0;L;;;;;N;;;;; 1D11D;MUSICAL SYMBOL FOUR-STRING FRETBOARD;So;0;L;;;;;N;;;;; 1D11E;MUSICAL SYMBOL G CLEF;So;0;L;;;;;N;;;;; 1D11F;MUSICAL SYMBOL G CLEF OTTAVA ALTA;So;0;L;;;;;N;;;;; 1D120;MUSICAL SYMBOL G CLEF OTTAVA BASSA;So;0;L;;;;;N;;;;; 1D121;MUSICAL SYMBOL C CLEF;So;0;L;;;;;N;;;;; 1D122;MUSICAL SYMBOL F CLEF;So;0;L;;;;;N;;;;; 1D123;MUSICAL SYMBOL F CLEF OTTAVA ALTA;So;0;L;;;;;N;;;;; 1D124;MUSICAL SYMBOL F CLEF OTTAVA BASSA;So;0;L;;;;;N;;;;; 1D125;MUSICAL SYMBOL DRUM CLEF-1;So;0;L;;;;;N;;;;; 1D126;MUSICAL SYMBOL DRUM CLEF-2;So;0;L;;;;;N;;;;; 1D129;MUSICAL SYMBOL MULTIPLE MEASURE REST;So;0;L;;;;;N;;;;; 1D12A;MUSICAL SYMBOL DOUBLE SHARP;So;0;L;;;;;N;;;;; 1D12B;MUSICAL SYMBOL DOUBLE FLAT;So;0;L;;;;;N;;;;; 1D12C;MUSICAL SYMBOL FLAT UP;So;0;L;;;;;N;;;;; 1D12D;MUSICAL SYMBOL FLAT DOWN;So;0;L;;;;;N;;;;; 1D12E;MUSICAL SYMBOL NATURAL UP;So;0;L;;;;;N;;;;; 1D12F;MUSICAL SYMBOL NATURAL DOWN;So;0;L;;;;;N;;;;; 1D130;MUSICAL SYMBOL SHARP UP;So;0;L;;;;;N;;;;; 1D131;MUSICAL SYMBOL SHARP DOWN;So;0;L;;;;;N;;;;; 1D132;MUSICAL SYMBOL QUARTER TONE SHARP;So;0;L;;;;;N;;;;; 1D133;MUSICAL SYMBOL QUARTER TONE FLAT;So;0;L;;;;;N;;;;; 1D134;MUSICAL SYMBOL COMMON TIME;So;0;L;;;;;N;;;;; 1D135;MUSICAL SYMBOL CUT TIME;So;0;L;;;;;N;;;;; 1D136;MUSICAL SYMBOL OTTAVA ALTA;So;0;L;;;;;N;;;;; 1D137;MUSICAL SYMBOL OTTAVA BASSA;So;0;L;;;;;N;;;;; 1D138;MUSICAL SYMBOL QUINDICESIMA ALTA;So;0;L;;;;;N;;;;; 1D139;MUSICAL SYMBOL QUINDICESIMA BASSA;So;0;L;;;;;N;;;;; 1D13A;MUSICAL SYMBOL MULTI REST;So;0;L;;;;;N;;;;; 1D13B;MUSICAL SYMBOL WHOLE REST;So;0;L;;;;;N;;;;; 1D13C;MUSICAL SYMBOL HALF REST;So;0;L;;;;;N;;;;; 1D13D;MUSICAL SYMBOL QUARTER REST;So;0;L;;;;;N;;;;; 1D13E;MUSICAL SYMBOL EIGHTH REST;So;0;L;;;;;N;;;;; 1D13F;MUSICAL SYMBOL SIXTEENTH REST;So;0;L;;;;;N;;;;; 1D140;MUSICAL SYMBOL THIRTY-SECOND REST;So;0;L;;;;;N;;;;; 1D141;MUSICAL SYMBOL SIXTY-FOURTH REST;So;0;L;;;;;N;;;;; 1D142;MUSICAL SYMBOL ONE HUNDRED TWENTY-EIGHTH REST;So;0;L;;;;;N;;;;; 1D143;MUSICAL SYMBOL X NOTEHEAD;So;0;L;;;;;N;;;;; 1D144;MUSICAL SYMBOL PLUS NOTEHEAD;So;0;L;;;;;N;;;;; 1D145;MUSICAL SYMBOL CIRCLE X NOTEHEAD;So;0;L;;;;;N;;;;; 1D146;MUSICAL SYMBOL SQUARE NOTEHEAD WHITE;So;0;L;;;;;N;;;;; 1D147;MUSICAL SYMBOL SQUARE NOTEHEAD BLACK;So;0;L;;;;;N;;;;; 1D148;MUSICAL SYMBOL TRIANGLE NOTEHEAD UP WHITE;So;0;L;;;;;N;;;;; 1D149;MUSICAL SYMBOL TRIANGLE NOTEHEAD UP BLACK;So;0;L;;;;;N;;;;; 1D14A;MUSICAL SYMBOL TRIANGLE NOTEHEAD LEFT WHITE;So;0;L;;;;;N;;;;; 1D14B;MUSICAL SYMBOL TRIANGLE NOTEHEAD LEFT BLACK;So;0;L;;;;;N;;;;; 1D14C;MUSICAL SYMBOL TRIANGLE NOTEHEAD RIGHT WHITE;So;0;L;;;;;N;;;;; 1D14D;MUSICAL SYMBOL TRIANGLE NOTEHEAD RIGHT BLACK;So;0;L;;;;;N;;;;; 1D14E;MUSICAL SYMBOL TRIANGLE NOTEHEAD DOWN WHITE;So;0;L;;;;;N;;;;; 1D14F;MUSICAL SYMBOL TRIANGLE NOTEHEAD DOWN BLACK;So;0;L;;;;;N;;;;; 1D150;MUSICAL SYMBOL TRIANGLE NOTEHEAD UP RIGHT WHITE;So;0;L;;;;;N;;;;; 1D151;MUSICAL SYMBOL TRIANGLE NOTEHEAD UP RIGHT BLACK;So;0;L;;;;;N;;;;; 1D152;MUSICAL SYMBOL MOON NOTEHEAD WHITE;So;0;L;;;;;N;;;;; 1D153;MUSICAL SYMBOL MOON NOTEHEAD BLACK;So;0;L;;;;;N;;;;; 1D154;MUSICAL SYMBOL TRIANGLE-ROUND NOTEHEAD DOWN WHITE;So;0;L;;;;;N;;;;; 1D155;MUSICAL SYMBOL TRIANGLE-ROUND NOTEHEAD DOWN BLACK;So;0;L;;;;;N;;;;; 1D156;MUSICAL SYMBOL PARENTHESIS NOTEHEAD;So;0;L;;;;;N;;;;; 1D157;MUSICAL SYMBOL VOID NOTEHEAD;So;0;L;;;;;N;;;;; 1D158;MUSICAL SYMBOL NOTEHEAD BLACK;So;0;L;;;;;N;;;;; 1D159;MUSICAL SYMBOL NULL NOTEHEAD;So;0;L;;;;;N;;;;; 1D15A;MUSICAL SYMBOL CLUSTER NOTEHEAD WHITE;So;0;L;;;;;N;;;;; 1D15B;MUSICAL SYMBOL CLUSTER NOTEHEAD BLACK;So;0;L;;;;;N;;;;; 1D15C;MUSICAL SYMBOL BREVE;So;0;L;;;;;N;;;;; 1D15D;MUSICAL SYMBOL WHOLE NOTE;So;0;L;;;;;N;;;;; 1D15E;MUSICAL SYMBOL HALF NOTE;So;0;L;1D157 1D165;;;;N;;;;; 1D15F;MUSICAL SYMBOL QUARTER NOTE;So;0;L;1D158 1D165;;;;N;;;;; 1D160;MUSICAL SYMBOL EIGHTH NOTE;So;0;L;1D15F 1D16E;;;;N;;;;; 1D161;MUSICAL SYMBOL SIXTEENTH NOTE;So;0;L;1D15F 1D16F;;;;N;;;;; 1D162;MUSICAL SYMBOL THIRTY-SECOND NOTE;So;0;L;1D15F 1D170;;;;N;;;;; 1D163;MUSICAL SYMBOL SIXTY-FOURTH NOTE;So;0;L;1D15F 1D171;;;;N;;;;; 1D164;MUSICAL SYMBOL ONE HUNDRED TWENTY-EIGHTH NOTE;So;0;L;1D15F 1D172;;;;N;;;;; 1D165;MUSICAL SYMBOL COMBINING STEM;Mc;216;L;;;;;N;;;;; 1D166;MUSICAL SYMBOL COMBINING SPRECHGESANG STEM;Mc;216;L;;;;;N;;;;; 1D167;MUSICAL SYMBOL COMBINING TREMOLO-1;Mn;1;NSM;;;;;N;;;;; 1D168;MUSICAL SYMBOL COMBINING TREMOLO-2;Mn;1;NSM;;;;;N;;;;; 1D169;MUSICAL SYMBOL COMBINING TREMOLO-3;Mn;1;NSM;;;;;N;;;;; 1D16A;MUSICAL SYMBOL FINGERED TREMOLO-1;So;0;L;;;;;N;;;;; 1D16B;MUSICAL SYMBOL FINGERED TREMOLO-2;So;0;L;;;;;N;;;;; 1D16C;MUSICAL SYMBOL FINGERED TREMOLO-3;So;0;L;;;;;N;;;;; 1D16D;MUSICAL SYMBOL COMBINING AUGMENTATION DOT;Mc;226;L;;;;;N;;;;; 1D16E;MUSICAL SYMBOL COMBINING FLAG-1;Mc;216;L;;;;;N;;;;; 1D16F;MUSICAL SYMBOL COMBINING FLAG-2;Mc;216;L;;;;;N;;;;; 1D170;MUSICAL SYMBOL COMBINING FLAG-3;Mc;216;L;;;;;N;;;;; 1D171;MUSICAL SYMBOL COMBINING FLAG-4;Mc;216;L;;;;;N;;;;; 1D172;MUSICAL SYMBOL COMBINING FLAG-5;Mc;216;L;;;;;N;;;;; 1D173;MUSICAL SYMBOL BEGIN BEAM;Cf;0;BN;;;;;N;;;;; 1D174;MUSICAL SYMBOL END BEAM;Cf;0;BN;;;;;N;;;;; 1D175;MUSICAL SYMBOL BEGIN TIE;Cf;0;BN;;;;;N;;;;; 1D176;MUSICAL SYMBOL END TIE;Cf;0;BN;;;;;N;;;;; 1D177;MUSICAL SYMBOL BEGIN SLUR;Cf;0;BN;;;;;N;;;;; 1D178;MUSICAL SYMBOL END SLUR;Cf;0;BN;;;;;N;;;;; 1D179;MUSICAL SYMBOL BEGIN PHRASE;Cf;0;BN;;;;;N;;;;; 1D17A;MUSICAL SYMBOL END PHRASE;Cf;0;BN;;;;;N;;;;; 1D17B;MUSICAL SYMBOL COMBINING ACCENT;Mn;220;NSM;;;;;N;;;;; 1D17C;MUSICAL SYMBOL COMBINING STACCATO;Mn;220;NSM;;;;;N;;;;; 1D17D;MUSICAL SYMBOL COMBINING TENUTO;Mn;220;NSM;;;;;N;;;;; 1D17E;MUSICAL SYMBOL COMBINING STACCATISSIMO;Mn;220;NSM;;;;;N;;;;; 1D17F;MUSICAL SYMBOL COMBINING MARCATO;Mn;220;NSM;;;;;N;;;;; 1D180;MUSICAL SYMBOL COMBINING MARCATO-STACCATO;Mn;220;NSM;;;;;N;;;;; 1D181;MUSICAL SYMBOL COMBINING ACCENT-STACCATO;Mn;220;NSM;;;;;N;;;;; 1D182;MUSICAL SYMBOL COMBINING LOURE;Mn;220;NSM;;;;;N;;;;; 1D183;MUSICAL SYMBOL ARPEGGIATO UP;So;0;L;;;;;N;;;;; 1D184;MUSICAL SYMBOL ARPEGGIATO DOWN;So;0;L;;;;;N;;;;; 1D185;MUSICAL SYMBOL COMBINING DOIT;Mn;230;NSM;;;;;N;;;;; 1D186;MUSICAL SYMBOL COMBINING RIP;Mn;230;NSM;;;;;N;;;;; 1D187;MUSICAL SYMBOL COMBINING FLIP;Mn;230;NSM;;;;;N;;;;; 1D188;MUSICAL SYMBOL COMBINING SMEAR;Mn;230;NSM;;;;;N;;;;; 1D189;MUSICAL SYMBOL COMBINING BEND;Mn;230;NSM;;;;;N;;;;; 1D18A;MUSICAL SYMBOL COMBINING DOUBLE TONGUE;Mn;220;NSM;;;;;N;;;;; 1D18B;MUSICAL SYMBOL COMBINING TRIPLE TONGUE;Mn;220;NSM;;;;;N;;;;; 1D18C;MUSICAL SYMBOL RINFORZANDO;So;0;L;;;;;N;;;;; 1D18D;MUSICAL SYMBOL SUBITO;So;0;L;;;;;N;;;;; 1D18E;MUSICAL SYMBOL Z;So;0;L;;;;;N;;;;; 1D18F;MUSICAL SYMBOL PIANO;So;0;L;;;;;N;;;;; 1D190;MUSICAL SYMBOL MEZZO;So;0;L;;;;;N;;;;; 1D191;MUSICAL SYMBOL FORTE;So;0;L;;;;;N;;;;; 1D192;MUSICAL SYMBOL CRESCENDO;So;0;L;;;;;N;;;;; 1D193;MUSICAL SYMBOL DECRESCENDO;So;0;L;;;;;N;;;;; 1D194;MUSICAL SYMBOL GRACE NOTE SLASH;So;0;L;;;;;N;;;;; 1D195;MUSICAL SYMBOL GRACE NOTE NO SLASH;So;0;L;;;;;N;;;;; 1D196;MUSICAL SYMBOL TR;So;0;L;;;;;N;;;;; 1D197;MUSICAL SYMBOL TURN;So;0;L;;;;;N;;;;; 1D198;MUSICAL SYMBOL INVERTED TURN;So;0;L;;;;;N;;;;; 1D199;MUSICAL SYMBOL TURN SLASH;So;0;L;;;;;N;;;;; 1D19A;MUSICAL SYMBOL TURN UP;So;0;L;;;;;N;;;;; 1D19B;MUSICAL SYMBOL ORNAMENT STROKE-1;So;0;L;;;;;N;;;;; 1D19C;MUSICAL SYMBOL ORNAMENT STROKE-2;So;0;L;;;;;N;;;;; 1D19D;MUSICAL SYMBOL ORNAMENT STROKE-3;So;0;L;;;;;N;;;;; 1D19E;MUSICAL SYMBOL ORNAMENT STROKE-4;So;0;L;;;;;N;;;;; 1D19F;MUSICAL SYMBOL ORNAMENT STROKE-5;So;0;L;;;;;N;;;;; 1D1A0;MUSICAL SYMBOL ORNAMENT STROKE-6;So;0;L;;;;;N;;;;; 1D1A1;MUSICAL SYMBOL ORNAMENT STROKE-7;So;0;L;;;;;N;;;;; 1D1A2;MUSICAL SYMBOL ORNAMENT STROKE-8;So;0;L;;;;;N;;;;; 1D1A3;MUSICAL SYMBOL ORNAMENT STROKE-9;So;0;L;;;;;N;;;;; 1D1A4;MUSICAL SYMBOL ORNAMENT STROKE-10;So;0;L;;;;;N;;;;; 1D1A5;MUSICAL SYMBOL ORNAMENT STROKE-11;So;0;L;;;;;N;;;;; 1D1A6;MUSICAL SYMBOL HAUPTSTIMME;So;0;L;;;;;N;;;;; 1D1A7;MUSICAL SYMBOL NEBENSTIMME;So;0;L;;;;;N;;;;; 1D1A8;MUSICAL SYMBOL END OF STIMME;So;0;L;;;;;N;;;;; 1D1A9;MUSICAL SYMBOL DEGREE SLASH;So;0;L;;;;;N;;;;; 1D1AA;MUSICAL SYMBOL COMBINING DOWN BOW;Mn;230;NSM;;;;;N;;;;; 1D1AB;MUSICAL SYMBOL COMBINING UP BOW;Mn;230;NSM;;;;;N;;;;; 1D1AC;MUSICAL SYMBOL COMBINING HARMONIC;Mn;230;NSM;;;;;N;;;;; 1D1AD;MUSICAL SYMBOL COMBINING SNAP PIZZICATO;Mn;230;NSM;;;;;N;;;;; 1D1AE;MUSICAL SYMBOL PEDAL MARK;So;0;L;;;;;N;;;;; 1D1AF;MUSICAL SYMBOL PEDAL UP MARK;So;0;L;;;;;N;;;;; 1D1B0;MUSICAL SYMBOL HALF PEDAL MARK;So;0;L;;;;;N;;;;; 1D1B1;MUSICAL SYMBOL GLISSANDO UP;So;0;L;;;;;N;;;;; 1D1B2;MUSICAL SYMBOL GLISSANDO DOWN;So;0;L;;;;;N;;;;; 1D1B3;MUSICAL SYMBOL WITH FINGERNAILS;So;0;L;;;;;N;;;;; 1D1B4;MUSICAL SYMBOL DAMP;So;0;L;;;;;N;;;;; 1D1B5;MUSICAL SYMBOL DAMP ALL;So;0;L;;;;;N;;;;; 1D1B6;MUSICAL SYMBOL MAXIMA;So;0;L;;;;;N;;;;; 1D1B7;MUSICAL SYMBOL LONGA;So;0;L;;;;;N;;;;; 1D1B8;MUSICAL SYMBOL BREVIS;So;0;L;;;;;N;;;;; 1D1B9;MUSICAL SYMBOL SEMIBREVIS WHITE;So;0;L;;;;;N;;;;; 1D1BA;MUSICAL SYMBOL SEMIBREVIS BLACK;So;0;L;;;;;N;;;;; 1D1BB;MUSICAL SYMBOL MINIMA;So;0;L;1D1B9 1D165;;;;N;;;;; 1D1BC;MUSICAL SYMBOL MINIMA BLACK;So;0;L;1D1BA 1D165;;;;N;;;;; 1D1BD;MUSICAL SYMBOL SEMIMINIMA WHITE;So;0;L;1D1BB 1D16E;;;;N;;;;; 1D1BE;MUSICAL SYMBOL SEMIMINIMA BLACK;So;0;L;1D1BC 1D16E;;;;N;;;;; 1D1BF;MUSICAL SYMBOL FUSA WHITE;So;0;L;1D1BB 1D16F;;;;N;;;;; 1D1C0;MUSICAL SYMBOL FUSA BLACK;So;0;L;1D1BC 1D16F;;;;N;;;;; 1D1C1;MUSICAL SYMBOL LONGA PERFECTA REST;So;0;L;;;;;N;;;;; 1D1C2;MUSICAL SYMBOL LONGA IMPERFECTA REST;So;0;L;;;;;N;;;;; 1D1C3;MUSICAL SYMBOL BREVIS REST;So;0;L;;;;;N;;;;; 1D1C4;MUSICAL SYMBOL SEMIBREVIS REST;So;0;L;;;;;N;;;;; 1D1C5;MUSICAL SYMBOL MINIMA REST;So;0;L;;;;;N;;;;; 1D1C6;MUSICAL SYMBOL SEMIMINIMA REST;So;0;L;;;;;N;;;;; 1D1C7;MUSICAL SYMBOL TEMPUS PERFECTUM CUM PROLATIONE PERFECTA;So;0;L;;;;;N;;;;; 1D1C8;MUSICAL SYMBOL TEMPUS PERFECTUM CUM PROLATIONE IMPERFECTA;So;0;L;;;;;N;;;;; 1D1C9;MUSICAL SYMBOL TEMPUS PERFECTUM CUM PROLATIONE PERFECTA DIMINUTION-1;So;0;L;;;;;N;;;;; 1D1CA;MUSICAL SYMBOL TEMPUS IMPERFECTUM CUM PROLATIONE PERFECTA;So;0;L;;;;;N;;;;; 1D1CB;MUSICAL SYMBOL TEMPUS IMPERFECTUM CUM PROLATIONE IMPERFECTA;So;0;L;;;;;N;;;;; 1D1CC;MUSICAL SYMBOL TEMPUS IMPERFECTUM CUM PROLATIONE IMPERFECTA DIMINUTION-1;So;0;L;;;;;N;;;;; 1D1CD;MUSICAL SYMBOL TEMPUS IMPERFECTUM CUM PROLATIONE IMPERFECTA DIMINUTION-2;So;0;L;;;;;N;;;;; 1D1CE;MUSICAL SYMBOL TEMPUS IMPERFECTUM CUM PROLATIONE IMPERFECTA DIMINUTION-3;So;0;L;;;;;N;;;;; 1D1CF;MUSICAL SYMBOL CROIX;So;0;L;;;;;N;;;;; 1D1D0;MUSICAL SYMBOL GREGORIAN C CLEF;So;0;L;;;;;N;;;;; 1D1D1;MUSICAL SYMBOL GREGORIAN F CLEF;So;0;L;;;;;N;;;;; 1D1D2;MUSICAL SYMBOL SQUARE B;So;0;L;;;;;N;;;;; 1D1D3;MUSICAL SYMBOL VIRGA;So;0;L;;;;;N;;;;; 1D1D4;MUSICAL SYMBOL PODATUS;So;0;L;;;;;N;;;;; 1D1D5;MUSICAL SYMBOL CLIVIS;So;0;L;;;;;N;;;;; 1D1D6;MUSICAL SYMBOL SCANDICUS;So;0;L;;;;;N;;;;; 1D1D7;MUSICAL SYMBOL CLIMACUS;So;0;L;;;;;N;;;;; 1D1D8;MUSICAL SYMBOL TORCULUS;So;0;L;;;;;N;;;;; 1D1D9;MUSICAL SYMBOL PORRECTUS;So;0;L;;;;;N;;;;; 1D1DA;MUSICAL SYMBOL PORRECTUS FLEXUS;So;0;L;;;;;N;;;;; 1D1DB;MUSICAL SYMBOL SCANDICUS FLEXUS;So;0;L;;;;;N;;;;; 1D1DC;MUSICAL SYMBOL TORCULUS RESUPINUS;So;0;L;;;;;N;;;;; 1D1DD;MUSICAL SYMBOL PES SUBPUNCTIS;So;0;L;;;;;N;;;;; 1D1DE;MUSICAL SYMBOL KIEVAN C CLEF;So;0;L;;;;;N;;;;; 1D1DF;MUSICAL SYMBOL KIEVAN END OF PIECE;So;0;L;;;;;N;;;;; 1D1E0;MUSICAL SYMBOL KIEVAN FINAL NOTE;So;0;L;;;;;N;;;;; 1D1E1;MUSICAL SYMBOL KIEVAN RECITATIVE MARK;So;0;L;;;;;N;;;;; 1D1E2;MUSICAL SYMBOL KIEVAN WHOLE NOTE;So;0;L;;;;;N;;;;; 1D1E3;MUSICAL SYMBOL KIEVAN HALF NOTE;So;0;L;;;;;N;;;;; 1D1E4;MUSICAL SYMBOL KIEVAN QUARTER NOTE STEM DOWN;So;0;L;;;;;N;;;;; 1D1E5;MUSICAL SYMBOL KIEVAN QUARTER NOTE STEM UP;So;0;L;;;;;N;;;;; 1D1E6;MUSICAL SYMBOL KIEVAN EIGHTH NOTE STEM DOWN;So;0;L;;;;;N;;;;; 1D1E7;MUSICAL SYMBOL KIEVAN EIGHTH NOTE STEM UP;So;0;L;;;;;N;;;;; 1D1E8;MUSICAL SYMBOL KIEVAN FLAT SIGN;So;0;L;;;;;N;;;;; 1D200;GREEK VOCAL NOTATION SYMBOL-1;So;0;ON;;;;;N;;;;; 1D201;GREEK VOCAL NOTATION SYMBOL-2;So;0;ON;;;;;N;;;;; 1D202;GREEK VOCAL NOTATION SYMBOL-3;So;0;ON;;;;;N;;;;; 1D203;GREEK VOCAL NOTATION SYMBOL-4;So;0;ON;;;;;N;;;;; 1D204;GREEK VOCAL NOTATION SYMBOL-5;So;0;ON;;;;;N;;;;; 1D205;GREEK VOCAL NOTATION SYMBOL-6;So;0;ON;;;;;N;;;;; 1D206;GREEK VOCAL NOTATION SYMBOL-7;So;0;ON;;;;;N;;;;; 1D207;GREEK VOCAL NOTATION SYMBOL-8;So;0;ON;;;;;N;;;;; 1D208;GREEK VOCAL NOTATION SYMBOL-9;So;0;ON;;;;;N;;;;; 1D209;GREEK VOCAL NOTATION SYMBOL-10;So;0;ON;;;;;N;;;;; 1D20A;GREEK VOCAL NOTATION SYMBOL-11;So;0;ON;;;;;N;;;;; 1D20B;GREEK VOCAL NOTATION SYMBOL-12;So;0;ON;;;;;N;;;;; 1D20C;GREEK VOCAL NOTATION SYMBOL-13;So;0;ON;;;;;N;;;;; 1D20D;GREEK VOCAL NOTATION SYMBOL-14;So;0;ON;;;;;N;;;;; 1D20E;GREEK VOCAL NOTATION SYMBOL-15;So;0;ON;;;;;N;;;;; 1D20F;GREEK VOCAL NOTATION SYMBOL-16;So;0;ON;;;;;N;;;;; 1D210;GREEK VOCAL NOTATION SYMBOL-17;So;0;ON;;;;;N;;;;; 1D211;GREEK VOCAL NOTATION SYMBOL-18;So;0;ON;;;;;N;;;;; 1D212;GREEK VOCAL NOTATION SYMBOL-19;So;0;ON;;;;;N;;;;; 1D213;GREEK VOCAL NOTATION SYMBOL-20;So;0;ON;;;;;N;;;;; 1D214;GREEK VOCAL NOTATION SYMBOL-21;So;0;ON;;;;;N;;;;; 1D215;GREEK VOCAL NOTATION SYMBOL-22;So;0;ON;;;;;N;;;;; 1D216;GREEK VOCAL NOTATION SYMBOL-23;So;0;ON;;;;;N;;;;; 1D217;GREEK VOCAL NOTATION SYMBOL-24;So;0;ON;;;;;N;;;;; 1D218;GREEK VOCAL NOTATION SYMBOL-50;So;0;ON;;;;;N;;;;; 1D219;GREEK VOCAL NOTATION SYMBOL-51;So;0;ON;;;;;N;;;;; 1D21A;GREEK VOCAL NOTATION SYMBOL-52;So;0;ON;;;;;N;;;;; 1D21B;GREEK VOCAL NOTATION SYMBOL-53;So;0;ON;;;;;N;;;;; 1D21C;GREEK VOCAL NOTATION SYMBOL-54;So;0;ON;;;;;N;;;;; 1D21D;GREEK INSTRUMENTAL NOTATION SYMBOL-1;So;0;ON;;;;;N;;;;; 1D21E;GREEK INSTRUMENTAL NOTATION SYMBOL-2;So;0;ON;;;;;N;;;;; 1D21F;GREEK INSTRUMENTAL NOTATION SYMBOL-4;So;0;ON;;;;;N;;;;; 1D220;GREEK INSTRUMENTAL NOTATION SYMBOL-5;So;0;ON;;;;;N;;;;; 1D221;GREEK INSTRUMENTAL NOTATION SYMBOL-7;So;0;ON;;;;;N;;;;; 1D222;GREEK INSTRUMENTAL NOTATION SYMBOL-8;So;0;ON;;;;;N;;;;; 1D223;GREEK INSTRUMENTAL NOTATION SYMBOL-11;So;0;ON;;;;;N;;;;; 1D224;GREEK INSTRUMENTAL NOTATION SYMBOL-12;So;0;ON;;;;;N;;;;; 1D225;GREEK INSTRUMENTAL NOTATION SYMBOL-13;So;0;ON;;;;;N;;;;; 1D226;GREEK INSTRUMENTAL NOTATION SYMBOL-14;So;0;ON;;;;;N;;;;; 1D227;GREEK INSTRUMENTAL NOTATION SYMBOL-17;So;0;ON;;;;;N;;;;; 1D228;GREEK INSTRUMENTAL NOTATION SYMBOL-18;So;0;ON;;;;;N;;;;; 1D229;GREEK INSTRUMENTAL NOTATION SYMBOL-19;So;0;ON;;;;;N;;;;; 1D22A;GREEK INSTRUMENTAL NOTATION SYMBOL-23;So;0;ON;;;;;N;;;;; 1D22B;GREEK INSTRUMENTAL NOTATION SYMBOL-24;So;0;ON;;;;;N;;;;; 1D22C;GREEK INSTRUMENTAL NOTATION SYMBOL-25;So;0;ON;;;;;N;;;;; 1D22D;GREEK INSTRUMENTAL NOTATION SYMBOL-26;So;0;ON;;;;;N;;;;; 1D22E;GREEK INSTRUMENTAL NOTATION SYMBOL-27;So;0;ON;;;;;N;;;;; 1D22F;GREEK INSTRUMENTAL NOTATION SYMBOL-29;So;0;ON;;;;;N;;;;; 1D230;GREEK INSTRUMENTAL NOTATION SYMBOL-30;So;0;ON;;;;;N;;;;; 1D231;GREEK INSTRUMENTAL NOTATION SYMBOL-32;So;0;ON;;;;;N;;;;; 1D232;GREEK INSTRUMENTAL NOTATION SYMBOL-36;So;0;ON;;;;;N;;;;; 1D233;GREEK INSTRUMENTAL NOTATION SYMBOL-37;So;0;ON;;;;;N;;;;; 1D234;GREEK INSTRUMENTAL NOTATION SYMBOL-38;So;0;ON;;;;;N;;;;; 1D235;GREEK INSTRUMENTAL NOTATION SYMBOL-39;So;0;ON;;;;;N;;;;; 1D236;GREEK INSTRUMENTAL NOTATION SYMBOL-40;So;0;ON;;;;;N;;;;; 1D237;GREEK INSTRUMENTAL NOTATION SYMBOL-42;So;0;ON;;;;;N;;;;; 1D238;GREEK INSTRUMENTAL NOTATION SYMBOL-43;So;0;ON;;;;;N;;;;; 1D239;GREEK INSTRUMENTAL NOTATION SYMBOL-45;So;0;ON;;;;;N;;;;; 1D23A;GREEK INSTRUMENTAL NOTATION SYMBOL-47;So;0;ON;;;;;N;;;;; 1D23B;GREEK INSTRUMENTAL NOTATION SYMBOL-48;So;0;ON;;;;;N;;;;; 1D23C;GREEK INSTRUMENTAL NOTATION SYMBOL-49;So;0;ON;;;;;N;;;;; 1D23D;GREEK INSTRUMENTAL NOTATION SYMBOL-50;So;0;ON;;;;;N;;;;; 1D23E;GREEK INSTRUMENTAL NOTATION SYMBOL-51;So;0;ON;;;;;N;;;;; 1D23F;GREEK INSTRUMENTAL NOTATION SYMBOL-52;So;0;ON;;;;;N;;;;; 1D240;GREEK INSTRUMENTAL NOTATION SYMBOL-53;So;0;ON;;;;;N;;;;; 1D241;GREEK INSTRUMENTAL NOTATION SYMBOL-54;So;0;ON;;;;;N;;;;; 1D242;COMBINING GREEK MUSICAL TRISEME;Mn;230;NSM;;;;;N;;;;; 1D243;COMBINING GREEK MUSICAL TETRASEME;Mn;230;NSM;;;;;N;;;;; 1D244;COMBINING GREEK MUSICAL PENTASEME;Mn;230;NSM;;;;;N;;;;; 1D245;GREEK MUSICAL LEIMMA;So;0;ON;;;;;N;;;;; 1D300;MONOGRAM FOR EARTH;So;0;ON;;;;;N;;;;; 1D301;DIGRAM FOR HEAVENLY EARTH;So;0;ON;;;;;N;;;;; 1D302;DIGRAM FOR HUMAN EARTH;So;0;ON;;;;;N;;;;; 1D303;DIGRAM FOR EARTHLY HEAVEN;So;0;ON;;;;;N;;;;; 1D304;DIGRAM FOR EARTHLY HUMAN;So;0;ON;;;;;N;;;;; 1D305;DIGRAM FOR EARTH;So;0;ON;;;;;N;;;;; 1D306;TETRAGRAM FOR CENTRE;So;0;ON;;;;;N;;;;; 1D307;TETRAGRAM FOR FULL CIRCLE;So;0;ON;;;;;N;;;;; 1D308;TETRAGRAM FOR MIRED;So;0;ON;;;;;N;;;;; 1D309;TETRAGRAM FOR BARRIER;So;0;ON;;;;;N;;;;; 1D30A;TETRAGRAM FOR KEEPING SMALL;So;0;ON;;;;;N;;;;; 1D30B;TETRAGRAM FOR CONTRARIETY;So;0;ON;;;;;N;;;;; 1D30C;TETRAGRAM FOR ASCENT;So;0;ON;;;;;N;;;;; 1D30D;TETRAGRAM FOR OPPOSITION;So;0;ON;;;;;N;;;;; 1D30E;TETRAGRAM FOR BRANCHING OUT;So;0;ON;;;;;N;;;;; 1D30F;TETRAGRAM FOR DEFECTIVENESS OR DISTORTION;So;0;ON;;;;;N;;;;; 1D310;TETRAGRAM FOR DIVERGENCE;So;0;ON;;;;;N;;;;; 1D311;TETRAGRAM FOR YOUTHFULNESS;So;0;ON;;;;;N;;;;; 1D312;TETRAGRAM FOR INCREASE;So;0;ON;;;;;N;;;;; 1D313;TETRAGRAM FOR PENETRATION;So;0;ON;;;;;N;;;;; 1D314;TETRAGRAM FOR REACH;So;0;ON;;;;;N;;;;; 1D315;TETRAGRAM FOR CONTACT;So;0;ON;;;;;N;;;;; 1D316;TETRAGRAM FOR HOLDING BACK;So;0;ON;;;;;N;;;;; 1D317;TETRAGRAM FOR WAITING;So;0;ON;;;;;N;;;;; 1D318;TETRAGRAM FOR FOLLOWING;So;0;ON;;;;;N;;;;; 1D319;TETRAGRAM FOR ADVANCE;So;0;ON;;;;;N;;;;; 1D31A;TETRAGRAM FOR RELEASE;So;0;ON;;;;;N;;;;; 1D31B;TETRAGRAM FOR RESISTANCE;So;0;ON;;;;;N;;;;; 1D31C;TETRAGRAM FOR EASE;So;0;ON;;;;;N;;;;; 1D31D;TETRAGRAM FOR JOY;So;0;ON;;;;;N;;;;; 1D31E;TETRAGRAM FOR CONTENTION;So;0;ON;;;;;N;;;;; 1D31F;TETRAGRAM FOR ENDEAVOUR;So;0;ON;;;;;N;;;;; 1D320;TETRAGRAM FOR DUTIES;So;0;ON;;;;;N;;;;; 1D321;TETRAGRAM FOR CHANGE;So;0;ON;;;;;N;;;;; 1D322;TETRAGRAM FOR DECISIVENESS;So;0;ON;;;;;N;;;;; 1D323;TETRAGRAM FOR BOLD RESOLUTION;So;0;ON;;;;;N;;;;; 1D324;TETRAGRAM FOR PACKING;So;0;ON;;;;;N;;;;; 1D325;TETRAGRAM FOR LEGION;So;0;ON;;;;;N;;;;; 1D326;TETRAGRAM FOR CLOSENESS;So;0;ON;;;;;N;;;;; 1D327;TETRAGRAM FOR KINSHIP;So;0;ON;;;;;N;;;;; 1D328;TETRAGRAM FOR GATHERING;So;0;ON;;;;;N;;;;; 1D329;TETRAGRAM FOR STRENGTH;So;0;ON;;;;;N;;;;; 1D32A;TETRAGRAM FOR PURITY;So;0;ON;;;;;N;;;;; 1D32B;TETRAGRAM FOR FULLNESS;So;0;ON;;;;;N;;;;; 1D32C;TETRAGRAM FOR RESIDENCE;So;0;ON;;;;;N;;;;; 1D32D;TETRAGRAM FOR LAW OR MODEL;So;0;ON;;;;;N;;;;; 1D32E;TETRAGRAM FOR RESPONSE;So;0;ON;;;;;N;;;;; 1D32F;TETRAGRAM FOR GOING TO MEET;So;0;ON;;;;;N;;;;; 1D330;TETRAGRAM FOR ENCOUNTERS;So;0;ON;;;;;N;;;;; 1D331;TETRAGRAM FOR STOVE;So;0;ON;;;;;N;;;;; 1D332;TETRAGRAM FOR GREATNESS;So;0;ON;;;;;N;;;;; 1D333;TETRAGRAM FOR ENLARGEMENT;So;0;ON;;;;;N;;;;; 1D334;TETRAGRAM FOR PATTERN;So;0;ON;;;;;N;;;;; 1D335;TETRAGRAM FOR RITUAL;So;0;ON;;;;;N;;;;; 1D336;TETRAGRAM FOR FLIGHT;So;0;ON;;;;;N;;;;; 1D337;TETRAGRAM FOR VASTNESS OR WASTING;So;0;ON;;;;;N;;;;; 1D338;TETRAGRAM FOR CONSTANCY;So;0;ON;;;;;N;;;;; 1D339;TETRAGRAM FOR MEASURE;So;0;ON;;;;;N;;;;; 1D33A;TETRAGRAM FOR ETERNITY;So;0;ON;;;;;N;;;;; 1D33B;TETRAGRAM FOR UNITY;So;0;ON;;;;;N;;;;; 1D33C;TETRAGRAM FOR DIMINISHMENT;So;0;ON;;;;;N;;;;; 1D33D;TETRAGRAM FOR CLOSED MOUTH;So;0;ON;;;;;N;;;;; 1D33E;TETRAGRAM FOR GUARDEDNESS;So;0;ON;;;;;N;;;;; 1D33F;TETRAGRAM FOR GATHERING IN;So;0;ON;;;;;N;;;;; 1D340;TETRAGRAM FOR MASSING;So;0;ON;;;;;N;;;;; 1D341;TETRAGRAM FOR ACCUMULATION;So;0;ON;;;;;N;;;;; 1D342;TETRAGRAM FOR EMBELLISHMENT;So;0;ON;;;;;N;;;;; 1D343;TETRAGRAM FOR DOUBT;So;0;ON;;;;;N;;;;; 1D344;TETRAGRAM FOR WATCH;So;0;ON;;;;;N;;;;; 1D345;TETRAGRAM FOR SINKING;So;0;ON;;;;;N;;;;; 1D346;TETRAGRAM FOR INNER;So;0;ON;;;;;N;;;;; 1D347;TETRAGRAM FOR DEPARTURE;So;0;ON;;;;;N;;;;; 1D348;TETRAGRAM FOR DARKENING;So;0;ON;;;;;N;;;;; 1D349;TETRAGRAM FOR DIMMING;So;0;ON;;;;;N;;;;; 1D34A;TETRAGRAM FOR EXHAUSTION;So;0;ON;;;;;N;;;;; 1D34B;TETRAGRAM FOR SEVERANCE;So;0;ON;;;;;N;;;;; 1D34C;TETRAGRAM FOR STOPPAGE;So;0;ON;;;;;N;;;;; 1D34D;TETRAGRAM FOR HARDNESS;So;0;ON;;;;;N;;;;; 1D34E;TETRAGRAM FOR COMPLETION;So;0;ON;;;;;N;;;;; 1D34F;TETRAGRAM FOR CLOSURE;So;0;ON;;;;;N;;;;; 1D350;TETRAGRAM FOR FAILURE;So;0;ON;;;;;N;;;;; 1D351;TETRAGRAM FOR AGGRAVATION;So;0;ON;;;;;N;;;;; 1D352;TETRAGRAM FOR COMPLIANCE;So;0;ON;;;;;N;;;;; 1D353;TETRAGRAM FOR ON THE VERGE;So;0;ON;;;;;N;;;;; 1D354;TETRAGRAM FOR DIFFICULTIES;So;0;ON;;;;;N;;;;; 1D355;TETRAGRAM FOR LABOURING;So;0;ON;;;;;N;;;;; 1D356;TETRAGRAM FOR FOSTERING;So;0;ON;;;;;N;;;;; 1D360;COUNTING ROD UNIT DIGIT ONE;No;0;L;;;;1;N;;;;; 1D361;COUNTING ROD UNIT DIGIT TWO;No;0;L;;;;2;N;;;;; 1D362;COUNTING ROD UNIT DIGIT THREE;No;0;L;;;;3;N;;;;; 1D363;COUNTING ROD UNIT DIGIT FOUR;No;0;L;;;;4;N;;;;; 1D364;COUNTING ROD UNIT DIGIT FIVE;No;0;L;;;;5;N;;;;; 1D365;COUNTING ROD UNIT DIGIT SIX;No;0;L;;;;6;N;;;;; 1D366;COUNTING ROD UNIT DIGIT SEVEN;No;0;L;;;;7;N;;;;; 1D367;COUNTING ROD UNIT DIGIT EIGHT;No;0;L;;;;8;N;;;;; 1D368;COUNTING ROD UNIT DIGIT NINE;No;0;L;;;;9;N;;;;; 1D369;COUNTING ROD TENS DIGIT ONE;No;0;L;;;;10;N;;;;; 1D36A;COUNTING ROD TENS DIGIT TWO;No;0;L;;;;20;N;;;;; 1D36B;COUNTING ROD TENS DIGIT THREE;No;0;L;;;;30;N;;;;; 1D36C;COUNTING ROD TENS DIGIT FOUR;No;0;L;;;;40;N;;;;; 1D36D;COUNTING ROD TENS DIGIT FIVE;No;0;L;;;;50;N;;;;; 1D36E;COUNTING ROD TENS DIGIT SIX;No;0;L;;;;60;N;;;;; 1D36F;COUNTING ROD TENS DIGIT SEVEN;No;0;L;;;;70;N;;;;; 1D370;COUNTING ROD TENS DIGIT EIGHT;No;0;L;;;;80;N;;;;; 1D371;COUNTING ROD TENS DIGIT NINE;No;0;L;;;;90;N;;;;; 1D400;MATHEMATICAL BOLD CAPITAL A;Lu;0;L;<font> 0041;;;;N;;;;; 1D401;MATHEMATICAL BOLD CAPITAL B;Lu;0;L;<font> 0042;;;;N;;;;; 1D402;MATHEMATICAL BOLD CAPITAL C;Lu;0;L;<font> 0043;;;;N;;;;; 1D403;MATHEMATICAL BOLD CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;; 1D404;MATHEMATICAL BOLD CAPITAL E;Lu;0;L;<font> 0045;;;;N;;;;; 1D405;MATHEMATICAL BOLD CAPITAL F;Lu;0;L;<font> 0046;;;;N;;;;; 1D406;MATHEMATICAL BOLD CAPITAL G;Lu;0;L;<font> 0047;;;;N;;;;; 1D407;MATHEMATICAL BOLD CAPITAL H;Lu;0;L;<font> 0048;;;;N;;;;; 1D408;MATHEMATICAL BOLD CAPITAL I;Lu;0;L;<font> 0049;;;;N;;;;; 1D409;MATHEMATICAL BOLD CAPITAL J;Lu;0;L;<font> 004A;;;;N;;;;; 1D40A;MATHEMATICAL BOLD CAPITAL K;Lu;0;L;<font> 004B;;;;N;;;;; 1D40B;MATHEMATICAL BOLD CAPITAL L;Lu;0;L;<font> 004C;;;;N;;;;; 1D40C;MATHEMATICAL BOLD CAPITAL M;Lu;0;L;<font> 004D;;;;N;;;;; 1D40D;MATHEMATICAL BOLD CAPITAL N;Lu;0;L;<font> 004E;;;;N;;;;; 1D40E;MATHEMATICAL BOLD CAPITAL O;Lu;0;L;<font> 004F;;;;N;;;;; 1D40F;MATHEMATICAL BOLD CAPITAL P;Lu;0;L;<font> 0050;;;;N;;;;; 1D410;MATHEMATICAL BOLD CAPITAL Q;Lu;0;L;<font> 0051;;;;N;;;;; 1D411;MATHEMATICAL BOLD CAPITAL R;Lu;0;L;<font> 0052;;;;N;;;;; 1D412;MATHEMATICAL BOLD CAPITAL S;Lu;0;L;<font> 0053;;;;N;;;;; 1D413;MATHEMATICAL BOLD CAPITAL T;Lu;0;L;<font> 0054;;;;N;;;;; 1D414;MATHEMATICAL BOLD CAPITAL U;Lu;0;L;<font> 0055;;;;N;;;;; 1D415;MATHEMATICAL BOLD CAPITAL V;Lu;0;L;<font> 0056;;;;N;;;;; 1D416;MATHEMATICAL BOLD CAPITAL W;Lu;0;L;<font> 0057;;;;N;;;;; 1D417;MATHEMATICAL BOLD CAPITAL X;Lu;0;L;<font> 0058;;;;N;;;;; 1D418;MATHEMATICAL BOLD CAPITAL Y;Lu;0;L;<font> 0059;;;;N;;;;; 1D419;MATHEMATICAL BOLD CAPITAL Z;Lu;0;L;<font> 005A;;;;N;;;;; 1D41A;MATHEMATICAL BOLD SMALL A;Ll;0;L;<font> 0061;;;;N;;;;; 1D41B;MATHEMATICAL BOLD SMALL B;Ll;0;L;<font> 0062;;;;N;;;;; 1D41C;MATHEMATICAL BOLD SMALL C;Ll;0;L;<font> 0063;;;;N;;;;; 1D41D;MATHEMATICAL BOLD SMALL D;Ll;0;L;<font> 0064;;;;N;;;;; 1D41E;MATHEMATICAL BOLD SMALL E;Ll;0;L;<font> 0065;;;;N;;;;; 1D41F;MATHEMATICAL BOLD SMALL F;Ll;0;L;<font> 0066;;;;N;;;;; 1D420;MATHEMATICAL BOLD SMALL G;Ll;0;L;<font> 0067;;;;N;;;;; 1D421;MATHEMATICAL BOLD SMALL H;Ll;0;L;<font> 0068;;;;N;;;;; 1D422;MATHEMATICAL BOLD SMALL I;Ll;0;L;<font> 0069;;;;N;;;;; 1D423;MATHEMATICAL BOLD SMALL J;Ll;0;L;<font> 006A;;;;N;;;;; 1D424;MATHEMATICAL BOLD SMALL K;Ll;0;L;<font> 006B;;;;N;;;;; 1D425;MATHEMATICAL BOLD SMALL L;Ll;0;L;<font> 006C;;;;N;;;;; 1D426;MATHEMATICAL BOLD SMALL M;Ll;0;L;<font> 006D;;;;N;;;;; 1D427;MATHEMATICAL BOLD SMALL N;Ll;0;L;<font> 006E;;;;N;;;;; 1D428;MATHEMATICAL BOLD SMALL O;Ll;0;L;<font> 006F;;;;N;;;;; 1D429;MATHEMATICAL BOLD SMALL P;Ll;0;L;<font> 0070;;;;N;;;;; 1D42A;MATHEMATICAL BOLD SMALL Q;Ll;0;L;<font> 0071;;;;N;;;;; 1D42B;MATHEMATICAL BOLD SMALL R;Ll;0;L;<font> 0072;;;;N;;;;; 1D42C;MATHEMATICAL BOLD SMALL S;Ll;0;L;<font> 0073;;;;N;;;;; 1D42D;MATHEMATICAL BOLD SMALL T;Ll;0;L;<font> 0074;;;;N;;;;; 1D42E;MATHEMATICAL BOLD SMALL U;Ll;0;L;<font> 0075;;;;N;;;;; 1D42F;MATHEMATICAL BOLD SMALL V;Ll;0;L;<font> 0076;;;;N;;;;; 1D430;MATHEMATICAL BOLD SMALL W;Ll;0;L;<font> 0077;;;;N;;;;; 1D431;MATHEMATICAL BOLD SMALL X;Ll;0;L;<font> 0078;;;;N;;;;; 1D432;MATHEMATICAL BOLD SMALL Y;Ll;0;L;<font> 0079;;;;N;;;;; 1D433;MATHEMATICAL BOLD SMALL Z;Ll;0;L;<font> 007A;;;;N;;;;; 1D434;MATHEMATICAL ITALIC CAPITAL A;Lu;0;L;<font> 0041;;;;N;;;;; 1D435;MATHEMATICAL ITALIC CAPITAL B;Lu;0;L;<font> 0042;;;;N;;;;; 1D436;MATHEMATICAL ITALIC CAPITAL C;Lu;0;L;<font> 0043;;;;N;;;;; 1D437;MATHEMATICAL ITALIC CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;; 1D438;MATHEMATICAL ITALIC CAPITAL E;Lu;0;L;<font> 0045;;;;N;;;;; 1D439;MATHEMATICAL ITALIC CAPITAL F;Lu;0;L;<font> 0046;;;;N;;;;; 1D43A;MATHEMATICAL ITALIC CAPITAL G;Lu;0;L;<font> 0047;;;;N;;;;; 1D43B;MATHEMATICAL ITALIC CAPITAL H;Lu;0;L;<font> 0048;;;;N;;;;; 1D43C;MATHEMATICAL ITALIC CAPITAL I;Lu;0;L;<font> 0049;;;;N;;;;; 1D43D;MATHEMATICAL ITALIC CAPITAL J;Lu;0;L;<font> 004A;;;;N;;;;; 1D43E;MATHEMATICAL ITALIC CAPITAL K;Lu;0;L;<font> 004B;;;;N;;;;; 1D43F;MATHEMATICAL ITALIC CAPITAL L;Lu;0;L;<font> 004C;;;;N;;;;; 1D440;MATHEMATICAL ITALIC CAPITAL M;Lu;0;L;<font> 004D;;;;N;;;;; 1D441;MATHEMATICAL ITALIC CAPITAL N;Lu;0;L;<font> 004E;;;;N;;;;; 1D442;MATHEMATICAL ITALIC CAPITAL O;Lu;0;L;<font> 004F;;;;N;;;;; 1D443;MATHEMATICAL ITALIC CAPITAL P;Lu;0;L;<font> 0050;;;;N;;;;; 1D444;MATHEMATICAL ITALIC CAPITAL Q;Lu;0;L;<font> 0051;;;;N;;;;; 1D445;MATHEMATICAL ITALIC CAPITAL R;Lu;0;L;<font> 0052;;;;N;;;;; 1D446;MATHEMATICAL ITALIC CAPITAL S;Lu;0;L;<font> 0053;;;;N;;;;; 1D447;MATHEMATICAL ITALIC CAPITAL T;Lu;0;L;<font> 0054;;;;N;;;;; 1D448;MATHEMATICAL ITALIC CAPITAL U;Lu;0;L;<font> 0055;;;;N;;;;; 1D449;MATHEMATICAL ITALIC CAPITAL V;Lu;0;L;<font> 0056;;;;N;;;;; 1D44A;MATHEMATICAL ITALIC CAPITAL W;Lu;0;L;<font> 0057;;;;N;;;;; 1D44B;MATHEMATICAL ITALIC CAPITAL X;Lu;0;L;<font> 0058;;;;N;;;;; 1D44C;MATHEMATICAL ITALIC CAPITAL Y;Lu;0;L;<font> 0059;;;;N;;;;; 1D44D;MATHEMATICAL ITALIC CAPITAL Z;Lu;0;L;<font> 005A;;;;N;;;;; 1D44E;MATHEMATICAL ITALIC SMALL A;Ll;0;L;<font> 0061;;;;N;;;;; 1D44F;MATHEMATICAL ITALIC SMALL B;Ll;0;L;<font> 0062;;;;N;;;;; 1D450;MATHEMATICAL ITALIC SMALL C;Ll;0;L;<font> 0063;;;;N;;;;; 1D451;MATHEMATICAL ITALIC SMALL D;Ll;0;L;<font> 0064;;;;N;;;;; 1D452;MATHEMATICAL ITALIC SMALL E;Ll;0;L;<font> 0065;;;;N;;;;; 1D453;MATHEMATICAL ITALIC SMALL F;Ll;0;L;<font> 0066;;;;N;;;;; 1D454;MATHEMATICAL ITALIC SMALL G;Ll;0;L;<font> 0067;;;;N;;;;; 1D456;MATHEMATICAL ITALIC SMALL I;Ll;0;L;<font> 0069;;;;N;;;;; 1D457;MATHEMATICAL ITALIC SMALL J;Ll;0;L;<font> 006A;;;;N;;;;; 1D458;MATHEMATICAL ITALIC SMALL K;Ll;0;L;<font> 006B;;;;N;;;;; 1D459;MATHEMATICAL ITALIC SMALL L;Ll;0;L;<font> 006C;;;;N;;;;; 1D45A;MATHEMATICAL ITALIC SMALL M;Ll;0;L;<font> 006D;;;;N;;;;; 1D45B;MATHEMATICAL ITALIC SMALL N;Ll;0;L;<font> 006E;;;;N;;;;; 1D45C;MATHEMATICAL ITALIC SMALL O;Ll;0;L;<font> 006F;;;;N;;;;; 1D45D;MATHEMATICAL ITALIC SMALL P;Ll;0;L;<font> 0070;;;;N;;;;; 1D45E;MATHEMATICAL ITALIC SMALL Q;Ll;0;L;<font> 0071;;;;N;;;;; 1D45F;MATHEMATICAL ITALIC SMALL R;Ll;0;L;<font> 0072;;;;N;;;;; 1D460;MATHEMATICAL ITALIC SMALL S;Ll;0;L;<font> 0073;;;;N;;;;; 1D461;MATHEMATICAL ITALIC SMALL T;Ll;0;L;<font> 0074;;;;N;;;;; 1D462;MATHEMATICAL ITALIC SMALL U;Ll;0;L;<font> 0075;;;;N;;;;; 1D463;MATHEMATICAL ITALIC SMALL V;Ll;0;L;<font> 0076;;;;N;;;;; 1D464;MATHEMATICAL ITALIC SMALL W;Ll;0;L;<font> 0077;;;;N;;;;; 1D465;MATHEMATICAL ITALIC SMALL X;Ll;0;L;<font> 0078;;;;N;;;;; 1D466;MATHEMATICAL ITALIC SMALL Y;Ll;0;L;<font> 0079;;;;N;;;;; 1D467;MATHEMATICAL ITALIC SMALL Z;Ll;0;L;<font> 007A;;;;N;;;;; 1D468;MATHEMATICAL BOLD ITALIC CAPITAL A;Lu;0;L;<font> 0041;;;;N;;;;; 1D469;MATHEMATICAL BOLD ITALIC CAPITAL B;Lu;0;L;<font> 0042;;;;N;;;;; 1D46A;MATHEMATICAL BOLD ITALIC CAPITAL C;Lu;0;L;<font> 0043;;;;N;;;;; 1D46B;MATHEMATICAL BOLD ITALIC CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;; 1D46C;MATHEMATICAL BOLD ITALIC CAPITAL E;Lu;0;L;<font> 0045;;;;N;;;;; 1D46D;MATHEMATICAL BOLD ITALIC CAPITAL F;Lu;0;L;<font> 0046;;;;N;;;;; 1D46E;MATHEMATICAL BOLD ITALIC CAPITAL G;Lu;0;L;<font> 0047;;;;N;;;;; 1D46F;MATHEMATICAL BOLD ITALIC CAPITAL H;Lu;0;L;<font> 0048;;;;N;;;;; 1D470;MATHEMATICAL BOLD ITALIC CAPITAL I;Lu;0;L;<font> 0049;;;;N;;;;; 1D471;MATHEMATICAL BOLD ITALIC CAPITAL J;Lu;0;L;<font> 004A;;;;N;;;;; 1D472;MATHEMATICAL BOLD ITALIC CAPITAL K;Lu;0;L;<font> 004B;;;;N;;;;; 1D473;MATHEMATICAL BOLD ITALIC CAPITAL L;Lu;0;L;<font> 004C;;;;N;;;;; 1D474;MATHEMATICAL BOLD ITALIC CAPITAL M;Lu;0;L;<font> 004D;;;;N;;;;; 1D475;MATHEMATICAL BOLD ITALIC CAPITAL N;Lu;0;L;<font> 004E;;;;N;;;;; 1D476;MATHEMATICAL BOLD ITALIC CAPITAL O;Lu;0;L;<font> 004F;;;;N;;;;; 1D477;MATHEMATICAL BOLD ITALIC CAPITAL P;Lu;0;L;<font> 0050;;;;N;;;;; 1D478;MATHEMATICAL BOLD ITALIC CAPITAL Q;Lu;0;L;<font> 0051;;;;N;;;;; 1D479;MATHEMATICAL BOLD ITALIC CAPITAL R;Lu;0;L;<font> 0052;;;;N;;;;; 1D47A;MATHEMATICAL BOLD ITALIC CAPITAL S;Lu;0;L;<font> 0053;;;;N;;;;; 1D47B;MATHEMATICAL BOLD ITALIC CAPITAL T;Lu;0;L;<font> 0054;;;;N;;;;; 1D47C;MATHEMATICAL BOLD ITALIC CAPITAL U;Lu;0;L;<font> 0055;;;;N;;;;; 1D47D;MATHEMATICAL BOLD ITALIC CAPITAL V;Lu;0;L;<font> 0056;;;;N;;;;; 1D47E;MATHEMATICAL BOLD ITALIC CAPITAL W;Lu;0;L;<font> 0057;;;;N;;;;; 1D47F;MATHEMATICAL BOLD ITALIC CAPITAL X;Lu;0;L;<font> 0058;;;;N;;;;; 1D480;MATHEMATICAL BOLD ITALIC CAPITAL Y;Lu;0;L;<font> 0059;;;;N;;;;; 1D481;MATHEMATICAL BOLD ITALIC CAPITAL Z;Lu;0;L;<font> 005A;;;;N;;;;; 1D482;MATHEMATICAL BOLD ITALIC SMALL A;Ll;0;L;<font> 0061;;;;N;;;;; 1D483;MATHEMATICAL BOLD ITALIC SMALL B;Ll;0;L;<font> 0062;;;;N;;;;; 1D484;MATHEMATICAL BOLD ITALIC SMALL C;Ll;0;L;<font> 0063;;;;N;;;;; 1D485;MATHEMATICAL BOLD ITALIC SMALL D;Ll;0;L;<font> 0064;;;;N;;;;; 1D486;MATHEMATICAL BOLD ITALIC SMALL E;Ll;0;L;<font> 0065;;;;N;;;;; 1D487;MATHEMATICAL BOLD ITALIC SMALL F;Ll;0;L;<font> 0066;;;;N;;;;; 1D488;MATHEMATICAL BOLD ITALIC SMALL G;Ll;0;L;<font> 0067;;;;N;;;;; 1D489;MATHEMATICAL BOLD ITALIC SMALL H;Ll;0;L;<font> 0068;;;;N;;;;; 1D48A;MATHEMATICAL BOLD ITALIC SMALL I;Ll;0;L;<font> 0069;;;;N;;;;; 1D48B;MATHEMATICAL BOLD ITALIC SMALL J;Ll;0;L;<font> 006A;;;;N;;;;; 1D48C;MATHEMATICAL BOLD ITALIC SMALL K;Ll;0;L;<font> 006B;;;;N;;;;; 1D48D;MATHEMATICAL BOLD ITALIC SMALL L;Ll;0;L;<font> 006C;;;;N;;;;; 1D48E;MATHEMATICAL BOLD ITALIC SMALL M;Ll;0;L;<font> 006D;;;;N;;;;; 1D48F;MATHEMATICAL BOLD ITALIC SMALL N;Ll;0;L;<font> 006E;;;;N;;;;; 1D490;MATHEMATICAL BOLD ITALIC SMALL O;Ll;0;L;<font> 006F;;;;N;;;;; 1D491;MATHEMATICAL BOLD ITALIC SMALL P;Ll;0;L;<font> 0070;;;;N;;;;; 1D492;MATHEMATICAL BOLD ITALIC SMALL Q;Ll;0;L;<font> 0071;;;;N;;;;; 1D493;MATHEMATICAL BOLD ITALIC SMALL R;Ll;0;L;<font> 0072;;;;N;;;;; 1D494;MATHEMATICAL BOLD ITALIC SMALL S;Ll;0;L;<font> 0073;;;;N;;;;; 1D495;MATHEMATICAL BOLD ITALIC SMALL T;Ll;0;L;<font> 0074;;;;N;;;;; 1D496;MATHEMATICAL BOLD ITALIC SMALL U;Ll;0;L;<font> 0075;;;;N;;;;; 1D497;MATHEMATICAL BOLD ITALIC SMALL V;Ll;0;L;<font> 0076;;;;N;;;;; 1D498;MATHEMATICAL BOLD ITALIC SMALL W;Ll;0;L;<font> 0077;;;;N;;;;; 1D499;MATHEMATICAL BOLD ITALIC SMALL X;Ll;0;L;<font> 0078;;;;N;;;;; 1D49A;MATHEMATICAL BOLD ITALIC SMALL Y;Ll;0;L;<font> 0079;;;;N;;;;; 1D49B;MATHEMATICAL BOLD ITALIC SMALL Z;Ll;0;L;<font> 007A;;;;N;;;;; 1D49C;MATHEMATICAL SCRIPT CAPITAL A;Lu;0;L;<font> 0041;;;;N;;;;; 1D49E;MATHEMATICAL SCRIPT CAPITAL C;Lu;0;L;<font> 0043;;;;N;;;;; 1D49F;MATHEMATICAL SCRIPT CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;; 1D4A2;MATHEMATICAL SCRIPT CAPITAL G;Lu;0;L;<font> 0047;;;;N;;;;; 1D4A5;MATHEMATICAL SCRIPT CAPITAL J;Lu;0;L;<font> 004A;;;;N;;;;; 1D4A6;MATHEMATICAL SCRIPT CAPITAL K;Lu;0;L;<font> 004B;;;;N;;;;; 1D4A9;MATHEMATICAL SCRIPT CAPITAL N;Lu;0;L;<font> 004E;;;;N;;;;; 1D4AA;MATHEMATICAL SCRIPT CAPITAL O;Lu;0;L;<font> 004F;;;;N;;;;; 1D4AB;MATHEMATICAL SCRIPT CAPITAL P;Lu;0;L;<font> 0050;;;;N;;;;; 1D4AC;MATHEMATICAL SCRIPT CAPITAL Q;Lu;0;L;<font> 0051;;;;N;;;;; 1D4AE;MATHEMATICAL SCRIPT CAPITAL S;Lu;0;L;<font> 0053;;;;N;;;;; 1D4AF;MATHEMATICAL SCRIPT CAPITAL T;Lu;0;L;<font> 0054;;;;N;;;;; 1D4B0;MATHEMATICAL SCRIPT CAPITAL U;Lu;0;L;<font> 0055;;;;N;;;;; 1D4B1;MATHEMATICAL SCRIPT CAPITAL V;Lu;0;L;<font> 0056;;;;N;;;;; 1D4B2;MATHEMATICAL SCRIPT CAPITAL W;Lu;0;L;<font> 0057;;;;N;;;;; 1D4B3;MATHEMATICAL SCRIPT CAPITAL X;Lu;0;L;<font> 0058;;;;N;;;;; 1D4B4;MATHEMATICAL SCRIPT CAPITAL Y;Lu;0;L;<font> 0059;;;;N;;;;; 1D4B5;MATHEMATICAL SCRIPT CAPITAL Z;Lu;0;L;<font> 005A;;;;N;;;;; 1D4B6;MATHEMATICAL SCRIPT SMALL A;Ll;0;L;<font> 0061;;;;N;;;;; 1D4B7;MATHEMATICAL SCRIPT SMALL B;Ll;0;L;<font> 0062;;;;N;;;;; 1D4B8;MATHEMATICAL SCRIPT SMALL C;Ll;0;L;<font> 0063;;;;N;;;;; 1D4B9;MATHEMATICAL SCRIPT SMALL D;Ll;0;L;<font> 0064;;;;N;;;;; 1D4BB;MATHEMATICAL SCRIPT SMALL F;Ll;0;L;<font> 0066;;;;N;;;;; 1D4BD;MATHEMATICAL SCRIPT SMALL H;Ll;0;L;<font> 0068;;;;N;;;;; 1D4BE;MATHEMATICAL SCRIPT SMALL I;Ll;0;L;<font> 0069;;;;N;;;;; 1D4BF;MATHEMATICAL SCRIPT SMALL J;Ll;0;L;<font> 006A;;;;N;;;;; 1D4C0;MATHEMATICAL SCRIPT SMALL K;Ll;0;L;<font> 006B;;;;N;;;;; 1D4C1;MATHEMATICAL SCRIPT SMALL L;Ll;0;L;<font> 006C;;;;N;;;;; 1D4C2;MATHEMATICAL SCRIPT SMALL M;Ll;0;L;<font> 006D;;;;N;;;;; 1D4C3;MATHEMATICAL SCRIPT SMALL N;Ll;0;L;<font> 006E;;;;N;;;;; 1D4C5;MATHEMATICAL SCRIPT SMALL P;Ll;0;L;<font> 0070;;;;N;;;;; 1D4C6;MATHEMATICAL SCRIPT SMALL Q;Ll;0;L;<font> 0071;;;;N;;;;; 1D4C7;MATHEMATICAL SCRIPT SMALL R;Ll;0;L;<font> 0072;;;;N;;;;; 1D4C8;MATHEMATICAL SCRIPT SMALL S;Ll;0;L;<font> 0073;;;;N;;;;; 1D4C9;MATHEMATICAL SCRIPT SMALL T;Ll;0;L;<font> 0074;;;;N;;;;; 1D4CA;MATHEMATICAL SCRIPT SMALL U;Ll;0;L;<font> 0075;;;;N;;;;; 1D4CB;MATHEMATICAL SCRIPT SMALL V;Ll;0;L;<font> 0076;;;;N;;;;; 1D4CC;MATHEMATICAL SCRIPT SMALL W;Ll;0;L;<font> 0077;;;;N;;;;; 1D4CD;MATHEMATICAL SCRIPT SMALL X;Ll;0;L;<font> 0078;;;;N;;;;; 1D4CE;MATHEMATICAL SCRIPT SMALL Y;Ll;0;L;<font> 0079;;;;N;;;;; 1D4CF;MATHEMATICAL SCRIPT SMALL Z;Ll;0;L;<font> 007A;;;;N;;;;; 1D4D0;MATHEMATICAL BOLD SCRIPT CAPITAL A;Lu;0;L;<font> 0041;;;;N;;;;; 1D4D1;MATHEMATICAL BOLD SCRIPT CAPITAL B;Lu;0;L;<font> 0042;;;;N;;;;; 1D4D2;MATHEMATICAL BOLD SCRIPT CAPITAL C;Lu;0;L;<font> 0043;;;;N;;;;; 1D4D3;MATHEMATICAL BOLD SCRIPT CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;; 1D4D4;MATHEMATICAL BOLD SCRIPT CAPITAL E;Lu;0;L;<font> 0045;;;;N;;;;; 1D4D5;MATHEMATICAL BOLD SCRIPT CAPITAL F;Lu;0;L;<font> 0046;;;;N;;;;; 1D4D6;MATHEMATICAL BOLD SCRIPT CAPITAL G;Lu;0;L;<font> 0047;;;;N;;;;; 1D4D7;MATHEMATICAL BOLD SCRIPT CAPITAL H;Lu;0;L;<font> 0048;;;;N;;;;; 1D4D8;MATHEMATICAL BOLD SCRIPT CAPITAL I;Lu;0;L;<font> 0049;;;;N;;;;; 1D4D9;MATHEMATICAL BOLD SCRIPT CAPITAL J;Lu;0;L;<font> 004A;;;;N;;;;; 1D4DA;MATHEMATICAL BOLD SCRIPT CAPITAL K;Lu;0;L;<font> 004B;;;;N;;;;; 1D4DB;MATHEMATICAL BOLD SCRIPT CAPITAL L;Lu;0;L;<font> 004C;;;;N;;;;; 1D4DC;MATHEMATICAL BOLD SCRIPT CAPITAL M;Lu;0;L;<font> 004D;;;;N;;;;; 1D4DD;MATHEMATICAL BOLD SCRIPT CAPITAL N;Lu;0;L;<font> 004E;;;;N;;;;; 1D4DE;MATHEMATICAL BOLD SCRIPT CAPITAL O;Lu;0;L;<font> 004F;;;;N;;;;; 1D4DF;MATHEMATICAL BOLD SCRIPT CAPITAL P;Lu;0;L;<font> 0050;;;;N;;;;; 1D4E0;MATHEMATICAL BOLD SCRIPT CAPITAL Q;Lu;0;L;<font> 0051;;;;N;;;;; 1D4E1;MATHEMATICAL BOLD SCRIPT CAPITAL R;Lu;0;L;<font> 0052;;;;N;;;;; 1D4E2;MATHEMATICAL BOLD SCRIPT CAPITAL S;Lu;0;L;<font> 0053;;;;N;;;;; 1D4E3;MATHEMATICAL BOLD SCRIPT CAPITAL T;Lu;0;L;<font> 0054;;;;N;;;;; 1D4E4;MATHEMATICAL BOLD SCRIPT CAPITAL U;Lu;0;L;<font> 0055;;;;N;;;;; 1D4E5;MATHEMATICAL BOLD SCRIPT CAPITAL V;Lu;0;L;<font> 0056;;;;N;;;;; 1D4E6;MATHEMATICAL BOLD SCRIPT CAPITAL W;Lu;0;L;<font> 0057;;;;N;;;;; 1D4E7;MATHEMATICAL BOLD SCRIPT CAPITAL X;Lu;0;L;<font> 0058;;;;N;;;;; 1D4E8;MATHEMATICAL BOLD SCRIPT CAPITAL Y;Lu;0;L;<font> 0059;;;;N;;;;; 1D4E9;MATHEMATICAL BOLD SCRIPT CAPITAL Z;Lu;0;L;<font> 005A;;;;N;;;;; 1D4EA;MATHEMATICAL BOLD SCRIPT SMALL A;Ll;0;L;<font> 0061;;;;N;;;;; 1D4EB;MATHEMATICAL BOLD SCRIPT SMALL B;Ll;0;L;<font> 0062;;;;N;;;;; 1D4EC;MATHEMATICAL BOLD SCRIPT SMALL C;Ll;0;L;<font> 0063;;;;N;;;;; 1D4ED;MATHEMATICAL BOLD SCRIPT SMALL D;Ll;0;L;<font> 0064;;;;N;;;;; 1D4EE;MATHEMATICAL BOLD SCRIPT SMALL E;Ll;0;L;<font> 0065;;;;N;;;;; 1D4EF;MATHEMATICAL BOLD SCRIPT SMALL F;Ll;0;L;<font> 0066;;;;N;;;;; 1D4F0;MATHEMATICAL BOLD SCRIPT SMALL G;Ll;0;L;<font> 0067;;;;N;;;;; 1D4F1;MATHEMATICAL BOLD SCRIPT SMALL H;Ll;0;L;<font> 0068;;;;N;;;;; 1D4F2;MATHEMATICAL BOLD SCRIPT SMALL I;Ll;0;L;<font> 0069;;;;N;;;;; 1D4F3;MATHEMATICAL BOLD SCRIPT SMALL J;Ll;0;L;<font> 006A;;;;N;;;;; 1D4F4;MATHEMATICAL BOLD SCRIPT SMALL K;Ll;0;L;<font> 006B;;;;N;;;;; 1D4F5;MATHEMATICAL BOLD SCRIPT SMALL L;Ll;0;L;<font> 006C;;;;N;;;;; 1D4F6;MATHEMATICAL BOLD SCRIPT SMALL M;Ll;0;L;<font> 006D;;;;N;;;;; 1D4F7;MATHEMATICAL BOLD SCRIPT SMALL N;Ll;0;L;<font> 006E;;;;N;;;;; 1D4F8;MATHEMATICAL BOLD SCRIPT SMALL O;Ll;0;L;<font> 006F;;;;N;;;;; 1D4F9;MATHEMATICAL BOLD SCRIPT SMALL P;Ll;0;L;<font> 0070;;;;N;;;;; 1D4FA;MATHEMATICAL BOLD SCRIPT SMALL Q;Ll;0;L;<font> 0071;;;;N;;;;; 1D4FB;MATHEMATICAL BOLD SCRIPT SMALL R;Ll;0;L;<font> 0072;;;;N;;;;; 1D4FC;MATHEMATICAL BOLD SCRIPT SMALL S;Ll;0;L;<font> 0073;;;;N;;;;; 1D4FD;MATHEMATICAL BOLD SCRIPT SMALL T;Ll;0;L;<font> 0074;;;;N;;;;; 1D4FE;MATHEMATICAL BOLD SCRIPT SMALL U;Ll;0;L;<font> 0075;;;;N;;;;; 1D4FF;MATHEMATICAL BOLD SCRIPT SMALL V;Ll;0;L;<font> 0076;;;;N;;;;; 1D500;MATHEMATICAL BOLD SCRIPT SMALL W;Ll;0;L;<font> 0077;;;;N;;;;; 1D501;MATHEMATICAL BOLD SCRIPT SMALL X;Ll;0;L;<font> 0078;;;;N;;;;; 1D502;MATHEMATICAL BOLD SCRIPT SMALL Y;Ll;0;L;<font> 0079;;;;N;;;;; 1D503;MATHEMATICAL BOLD SCRIPT SMALL Z;Ll;0;L;<font> 007A;;;;N;;;;; 1D504;MATHEMATICAL FRAKTUR CAPITAL A;Lu;0;L;<font> 0041;;;;N;;;;; 1D505;MATHEMATICAL FRAKTUR CAPITAL B;Lu;0;L;<font> 0042;;;;N;;;;; 1D507;MATHEMATICAL FRAKTUR CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;; 1D508;MATHEMATICAL FRAKTUR CAPITAL E;Lu;0;L;<font> 0045;;;;N;;;;; 1D509;MATHEMATICAL FRAKTUR CAPITAL F;Lu;0;L;<font> 0046;;;;N;;;;; 1D50A;MATHEMATICAL FRAKTUR CAPITAL G;Lu;0;L;<font> 0047;;;;N;;;;; 1D50D;MATHEMATICAL FRAKTUR CAPITAL J;Lu;0;L;<font> 004A;;;;N;;;;; 1D50E;MATHEMATICAL FRAKTUR CAPITAL K;Lu;0;L;<font> 004B;;;;N;;;;; 1D50F;MATHEMATICAL FRAKTUR CAPITAL L;Lu;0;L;<font> 004C;;;;N;;;;; 1D510;MATHEMATICAL FRAKTUR CAPITAL M;Lu;0;L;<font> 004D;;;;N;;;;; 1D511;MATHEMATICAL FRAKTUR CAPITAL N;Lu;0;L;<font> 004E;;;;N;;;;; 1D512;MATHEMATICAL FRAKTUR CAPITAL O;Lu;0;L;<font> 004F;;;;N;;;;; 1D513;MATHEMATICAL FRAKTUR CAPITAL P;Lu;0;L;<font> 0050;;;;N;;;;; 1D514;MATHEMATICAL FRAKTUR CAPITAL Q;Lu;0;L;<font> 0051;;;;N;;;;; 1D516;MATHEMATICAL FRAKTUR CAPITAL S;Lu;0;L;<font> 0053;;;;N;;;;; 1D517;MATHEMATICAL FRAKTUR CAPITAL T;Lu;0;L;<font> 0054;;;;N;;;;; 1D518;MATHEMATICAL FRAKTUR CAPITAL U;Lu;0;L;<font> 0055;;;;N;;;;; 1D519;MATHEMATICAL FRAKTUR CAPITAL V;Lu;0;L;<font> 0056;;;;N;;;;; 1D51A;MATHEMATICAL FRAKTUR CAPITAL W;Lu;0;L;<font> 0057;;;;N;;;;; 1D51B;MATHEMATICAL FRAKTUR CAPITAL X;Lu;0;L;<font> 0058;;;;N;;;;; 1D51C;MATHEMATICAL FRAKTUR CAPITAL Y;Lu;0;L;<font> 0059;;;;N;;;;; 1D51E;MATHEMATICAL FRAKTUR SMALL A;Ll;0;L;<font> 0061;;;;N;;;;; 1D51F;MATHEMATICAL FRAKTUR SMALL B;Ll;0;L;<font> 0062;;;;N;;;;; 1D520;MATHEMATICAL FRAKTUR SMALL C;Ll;0;L;<font> 0063;;;;N;;;;; 1D521;MATHEMATICAL FRAKTUR SMALL D;Ll;0;L;<font> 0064;;;;N;;;;; 1D522;MATHEMATICAL FRAKTUR SMALL E;Ll;0;L;<font> 0065;;;;N;;;;; 1D523;MATHEMATICAL FRAKTUR SMALL F;Ll;0;L;<font> 0066;;;;N;;;;; 1D524;MATHEMATICAL FRAKTUR SMALL G;Ll;0;L;<font> 0067;;;;N;;;;; 1D525;MATHEMATICAL FRAKTUR SMALL H;Ll;0;L;<font> 0068;;;;N;;;;; 1D526;MATHEMATICAL FRAKTUR SMALL I;Ll;0;L;<font> 0069;;;;N;;;;; 1D527;MATHEMATICAL FRAKTUR SMALL J;Ll;0;L;<font> 006A;;;;N;;;;; 1D528;MATHEMATICAL FRAKTUR SMALL K;Ll;0;L;<font> 006B;;;;N;;;;; 1D529;MATHEMATICAL FRAKTUR SMALL L;Ll;0;L;<font> 006C;;;;N;;;;; 1D52A;MATHEMATICAL FRAKTUR SMALL M;Ll;0;L;<font> 006D;;;;N;;;;; 1D52B;MATHEMATICAL FRAKTUR SMALL N;Ll;0;L;<font> 006E;;;;N;;;;; 1D52C;MATHEMATICAL FRAKTUR SMALL O;Ll;0;L;<font> 006F;;;;N;;;;; 1D52D;MATHEMATICAL FRAKTUR SMALL P;Ll;0;L;<font> 0070;;;;N;;;;; 1D52E;MATHEMATICAL FRAKTUR SMALL Q;Ll;0;L;<font> 0071;;;;N;;;;; 1D52F;MATHEMATICAL FRAKTUR SMALL R;Ll;0;L;<font> 0072;;;;N;;;;; 1D530;MATHEMATICAL FRAKTUR SMALL S;Ll;0;L;<font> 0073;;;;N;;;;; 1D531;MATHEMATICAL FRAKTUR SMALL T;Ll;0;L;<font> 0074;;;;N;;;;; 1D532;MATHEMATICAL FRAKTUR SMALL U;Ll;0;L;<font> 0075;;;;N;;;;; 1D533;MATHEMATICAL FRAKTUR SMALL V;Ll;0;L;<font> 0076;;;;N;;;;; 1D534;MATHEMATICAL FRAKTUR SMALL W;Ll;0;L;<font> 0077;;;;N;;;;; 1D535;MATHEMATICAL FRAKTUR SMALL X;Ll;0;L;<font> 0078;;;;N;;;;; 1D536;MATHEMATICAL FRAKTUR SMALL Y;Ll;0;L;<font> 0079;;;;N;;;;; 1D537;MATHEMATICAL FRAKTUR SMALL Z;Ll;0;L;<font> 007A;;;;N;;;;; 1D538;MATHEMATICAL DOUBLE-STRUCK CAPITAL A;Lu;0;L;<font> 0041;;;;N;;;;; 1D539;MATHEMATICAL DOUBLE-STRUCK CAPITAL B;Lu;0;L;<font> 0042;;;;N;;;;; 1D53B;MATHEMATICAL DOUBLE-STRUCK CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;; 1D53C;MATHEMATICAL DOUBLE-STRUCK CAPITAL E;Lu;0;L;<font> 0045;;;;N;;;;; 1D53D;MATHEMATICAL DOUBLE-STRUCK CAPITAL F;Lu;0;L;<font> 0046;;;;N;;;;; 1D53E;MATHEMATICAL DOUBLE-STRUCK CAPITAL G;Lu;0;L;<font> 0047;;;;N;;;;; 1D540;MATHEMATICAL DOUBLE-STRUCK CAPITAL I;Lu;0;L;<font> 0049;;;;N;;;;; 1D541;MATHEMATICAL DOUBLE-STRUCK CAPITAL J;Lu;0;L;<font> 004A;;;;N;;;;; 1D542;MATHEMATICAL DOUBLE-STRUCK CAPITAL K;Lu;0;L;<font> 004B;;;;N;;;;; 1D543;MATHEMATICAL DOUBLE-STRUCK CAPITAL L;Lu;0;L;<font> 004C;;;;N;;;;; 1D544;MATHEMATICAL DOUBLE-STRUCK CAPITAL M;Lu;0;L;<font> 004D;;;;N;;;;; 1D546;MATHEMATICAL DOUBLE-STRUCK CAPITAL O;Lu;0;L;<font> 004F;;;;N;;;;; 1D54A;MATHEMATICAL DOUBLE-STRUCK CAPITAL S;Lu;0;L;<font> 0053;;;;N;;;;; 1D54B;MATHEMATICAL DOUBLE-STRUCK CAPITAL T;Lu;0;L;<font> 0054;;;;N;;;;; 1D54C;MATHEMATICAL DOUBLE-STRUCK CAPITAL U;Lu;0;L;<font> 0055;;;;N;;;;; 1D54D;MATHEMATICAL DOUBLE-STRUCK CAPITAL V;Lu;0;L;<font> 0056;;;;N;;;;; 1D54E;MATHEMATICAL DOUBLE-STRUCK CAPITAL W;Lu;0;L;<font> 0057;;;;N;;;;; 1D54F;MATHEMATICAL DOUBLE-STRUCK CAPITAL X;Lu;0;L;<font> 0058;;;;N;;;;; 1D550;MATHEMATICAL DOUBLE-STRUCK CAPITAL Y;Lu;0;L;<font> 0059;;;;N;;;;; 1D552;MATHEMATICAL DOUBLE-STRUCK SMALL A;Ll;0;L;<font> 0061;;;;N;;;;; 1D553;MATHEMATICAL DOUBLE-STRUCK SMALL B;Ll;0;L;<font> 0062;;;;N;;;;; 1D554;MATHEMATICAL DOUBLE-STRUCK SMALL C;Ll;0;L;<font> 0063;;;;N;;;;; 1D555;MATHEMATICAL DOUBLE-STRUCK SMALL D;Ll;0;L;<font> 0064;;;;N;;;;; 1D556;MATHEMATICAL DOUBLE-STRUCK SMALL E;Ll;0;L;<font> 0065;;;;N;;;;; 1D557;MATHEMATICAL DOUBLE-STRUCK SMALL F;Ll;0;L;<font> 0066;;;;N;;;;; 1D558;MATHEMATICAL DOUBLE-STRUCK SMALL G;Ll;0;L;<font> 0067;;;;N;;;;; 1D559;MATHEMATICAL DOUBLE-STRUCK SMALL H;Ll;0;L;<font> 0068;;;;N;;;;; 1D55A;MATHEMATICAL DOUBLE-STRUCK SMALL I;Ll;0;L;<font> 0069;;;;N;;;;; 1D55B;MATHEMATICAL DOUBLE-STRUCK SMALL J;Ll;0;L;<font> 006A;;;;N;;;;; 1D55C;MATHEMATICAL DOUBLE-STRUCK SMALL K;Ll;0;L;<font> 006B;;;;N;;;;; 1D55D;MATHEMATICAL DOUBLE-STRUCK SMALL L;Ll;0;L;<font> 006C;;;;N;;;;; 1D55E;MATHEMATICAL DOUBLE-STRUCK SMALL M;Ll;0;L;<font> 006D;;;;N;;;;; 1D55F;MATHEMATICAL DOUBLE-STRUCK SMALL N;Ll;0;L;<font> 006E;;;;N;;;;; 1D560;MATHEMATICAL DOUBLE-STRUCK SMALL O;Ll;0;L;<font> 006F;;;;N;;;;; 1D561;MATHEMATICAL DOUBLE-STRUCK SMALL P;Ll;0;L;<font> 0070;;;;N;;;;; 1D562;MATHEMATICAL DOUBLE-STRUCK SMALL Q;Ll;0;L;<font> 0071;;;;N;;;;; 1D563;MATHEMATICAL DOUBLE-STRUCK SMALL R;Ll;0;L;<font> 0072;;;;N;;;;; 1D564;MATHEMATICAL DOUBLE-STRUCK SMALL S;Ll;0;L;<font> 0073;;;;N;;;;; 1D565;MATHEMATICAL DOUBLE-STRUCK SMALL T;Ll;0;L;<font> 0074;;;;N;;;;; 1D566;MATHEMATICAL DOUBLE-STRUCK SMALL U;Ll;0;L;<font> 0075;;;;N;;;;; 1D567;MATHEMATICAL DOUBLE-STRUCK SMALL V;Ll;0;L;<font> 0076;;;;N;;;;; 1D568;MATHEMATICAL DOUBLE-STRUCK SMALL W;Ll;0;L;<font> 0077;;;;N;;;;; 1D569;MATHEMATICAL DOUBLE-STRUCK SMALL X;Ll;0;L;<font> 0078;;;;N;;;;; 1D56A;MATHEMATICAL DOUBLE-STRUCK SMALL Y;Ll;0;L;<font> 0079;;;;N;;;;; 1D56B;MATHEMATICAL DOUBLE-STRUCK SMALL Z;Ll;0;L;<font> 007A;;;;N;;;;; 1D56C;MATHEMATICAL BOLD FRAKTUR CAPITAL A;Lu;0;L;<font> 0041;;;;N;;;;; 1D56D;MATHEMATICAL BOLD FRAKTUR CAPITAL B;Lu;0;L;<font> 0042;;;;N;;;;; 1D56E;MATHEMATICAL BOLD FRAKTUR CAPITAL C;Lu;0;L;<font> 0043;;;;N;;;;; 1D56F;MATHEMATICAL BOLD FRAKTUR CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;; 1D570;MATHEMATICAL BOLD FRAKTUR CAPITAL E;Lu;0;L;<font> 0045;;;;N;;;;; 1D571;MATHEMATICAL BOLD FRAKTUR CAPITAL F;Lu;0;L;<font> 0046;;;;N;;;;; 1D572;MATHEMATICAL BOLD FRAKTUR CAPITAL G;Lu;0;L;<font> 0047;;;;N;;;;; 1D573;MATHEMATICAL BOLD FRAKTUR CAPITAL H;Lu;0;L;<font> 0048;;;;N;;;;; 1D574;MATHEMATICAL BOLD FRAKTUR CAPITAL I;Lu;0;L;<font> 0049;;;;N;;;;; 1D575;MATHEMATICAL BOLD FRAKTUR CAPITAL J;Lu;0;L;<font> 004A;;;;N;;;;; 1D576;MATHEMATICAL BOLD FRAKTUR CAPITAL K;Lu;0;L;<font> 004B;;;;N;;;;; 1D577;MATHEMATICAL BOLD FRAKTUR CAPITAL L;Lu;0;L;<font> 004C;;;;N;;;;; 1D578;MATHEMATICAL BOLD FRAKTUR CAPITAL M;Lu;0;L;<font> 004D;;;;N;;;;; 1D579;MATHEMATICAL BOLD FRAKTUR CAPITAL N;Lu;0;L;<font> 004E;;;;N;;;;; 1D57A;MATHEMATICAL BOLD FRAKTUR CAPITAL O;Lu;0;L;<font> 004F;;;;N;;;;; 1D57B;MATHEMATICAL BOLD FRAKTUR CAPITAL P;Lu;0;L;<font> 0050;;;;N;;;;; 1D57C;MATHEMATICAL BOLD FRAKTUR CAPITAL Q;Lu;0;L;<font> 0051;;;;N;;;;; 1D57D;MATHEMATICAL BOLD FRAKTUR CAPITAL R;Lu;0;L;<font> 0052;;;;N;;;;; 1D57E;MATHEMATICAL BOLD FRAKTUR CAPITAL S;Lu;0;L;<font> 0053;;;;N;;;;; 1D57F;MATHEMATICAL BOLD FRAKTUR CAPITAL T;Lu;0;L;<font> 0054;;;;N;;;;; 1D580;MATHEMATICAL BOLD FRAKTUR CAPITAL U;Lu;0;L;<font> 0055;;;;N;;;;; 1D581;MATHEMATICAL BOLD FRAKTUR CAPITAL V;Lu;0;L;<font> 0056;;;;N;;;;; 1D582;MATHEMATICAL BOLD FRAKTUR CAPITAL W;Lu;0;L;<font> 0057;;;;N;;;;; 1D583;MATHEMATICAL BOLD FRAKTUR CAPITAL X;Lu;0;L;<font> 0058;;;;N;;;;; 1D584;MATHEMATICAL BOLD FRAKTUR CAPITAL Y;Lu;0;L;<font> 0059;;;;N;;;;; 1D585;MATHEMATICAL BOLD FRAKTUR CAPITAL Z;Lu;0;L;<font> 005A;;;;N;;;;; 1D586;MATHEMATICAL BOLD FRAKTUR SMALL A;Ll;0;L;<font> 0061;;;;N;;;;; 1D587;MATHEMATICAL BOLD FRAKTUR SMALL B;Ll;0;L;<font> 0062;;;;N;;;;; 1D588;MATHEMATICAL BOLD FRAKTUR SMALL C;Ll;0;L;<font> 0063;;;;N;;;;; 1D589;MATHEMATICAL BOLD FRAKTUR SMALL D;Ll;0;L;<font> 0064;;;;N;;;;; 1D58A;MATHEMATICAL BOLD FRAKTUR SMALL E;Ll;0;L;<font> 0065;;;;N;;;;; 1D58B;MATHEMATICAL BOLD FRAKTUR SMALL F;Ll;0;L;<font> 0066;;;;N;;;;; 1D58C;MATHEMATICAL BOLD FRAKTUR SMALL G;Ll;0;L;<font> 0067;;;;N;;;;; 1D58D;MATHEMATICAL BOLD FRAKTUR SMALL H;Ll;0;L;<font> 0068;;;;N;;;;; 1D58E;MATHEMATICAL BOLD FRAKTUR SMALL I;Ll;0;L;<font> 0069;;;;N;;;;; 1D58F;MATHEMATICAL BOLD FRAKTUR SMALL J;Ll;0;L;<font> 006A;;;;N;;;;; 1D590;MATHEMATICAL BOLD FRAKTUR SMALL K;Ll;0;L;<font> 006B;;;;N;;;;; 1D591;MATHEMATICAL BOLD FRAKTUR SMALL L;Ll;0;L;<font> 006C;;;;N;;;;; 1D592;MATHEMATICAL BOLD FRAKTUR SMALL M;Ll;0;L;<font> 006D;;;;N;;;;; 1D593;MATHEMATICAL BOLD FRAKTUR SMALL N;Ll;0;L;<font> 006E;;;;N;;;;; 1D594;MATHEMATICAL BOLD FRAKTUR SMALL O;Ll;0;L;<font> 006F;;;;N;;;;; 1D595;MATHEMATICAL BOLD FRAKTUR SMALL P;Ll;0;L;<font> 0070;;;;N;;;;; 1D596;MATHEMATICAL BOLD FRAKTUR SMALL Q;Ll;0;L;<font> 0071;;;;N;;;;; 1D597;MATHEMATICAL BOLD FRAKTUR SMALL R;Ll;0;L;<font> 0072;;;;N;;;;; 1D598;MATHEMATICAL BOLD FRAKTUR SMALL S;Ll;0;L;<font> 0073;;;;N;;;;; 1D599;MATHEMATICAL BOLD FRAKTUR SMALL T;Ll;0;L;<font> 0074;;;;N;;;;; 1D59A;MATHEMATICAL BOLD FRAKTUR SMALL U;Ll;0;L;<font> 0075;;;;N;;;;; 1D59B;MATHEMATICAL BOLD FRAKTUR SMALL V;Ll;0;L;<font> 0076;;;;N;;;;; 1D59C;MATHEMATICAL BOLD FRAKTUR SMALL W;Ll;0;L;<font> 0077;;;;N;;;;; 1D59D;MATHEMATICAL BOLD FRAKTUR SMALL X;Ll;0;L;<font> 0078;;;;N;;;;; 1D59E;MATHEMATICAL BOLD FRAKTUR SMALL Y;Ll;0;L;<font> 0079;;;;N;;;;; 1D59F;MATHEMATICAL BOLD FRAKTUR SMALL Z;Ll;0;L;<font> 007A;;;;N;;;;; 1D5A0;MATHEMATICAL SANS-SERIF CAPITAL A;Lu;0;L;<font> 0041;;;;N;;;;; 1D5A1;MATHEMATICAL SANS-SERIF CAPITAL B;Lu;0;L;<font> 0042;;;;N;;;;; 1D5A2;MATHEMATICAL SANS-SERIF CAPITAL C;Lu;0;L;<font> 0043;;;;N;;;;; 1D5A3;MATHEMATICAL SANS-SERIF CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;; 1D5A4;MATHEMATICAL SANS-SERIF CAPITAL E;Lu;0;L;<font> 0045;;;;N;;;;; 1D5A5;MATHEMATICAL SANS-SERIF CAPITAL F;Lu;0;L;<font> 0046;;;;N;;;;; 1D5A6;MATHEMATICAL SANS-SERIF CAPITAL G;Lu;0;L;<font> 0047;;;;N;;;;; 1D5A7;MATHEMATICAL SANS-SERIF CAPITAL H;Lu;0;L;<font> 0048;;;;N;;;;; 1D5A8;MATHEMATICAL SANS-SERIF CAPITAL I;Lu;0;L;<font> 0049;;;;N;;;;; 1D5A9;MATHEMATICAL SANS-SERIF CAPITAL J;Lu;0;L;<font> 004A;;;;N;;;;; 1D5AA;MATHEMATICAL SANS-SERIF CAPITAL K;Lu;0;L;<font> 004B;;;;N;;;;; 1D5AB;MATHEMATICAL SANS-SERIF CAPITAL L;Lu;0;L;<font> 004C;;;;N;;;;; 1D5AC;MATHEMATICAL SANS-SERIF CAPITAL M;Lu;0;L;<font> 004D;;;;N;;;;; 1D5AD;MATHEMATICAL SANS-SERIF CAPITAL N;Lu;0;L;<font> 004E;;;;N;;;;; 1D5AE;MATHEMATICAL SANS-SERIF CAPITAL O;Lu;0;L;<font> 004F;;;;N;;;;; 1D5AF;MATHEMATICAL SANS-SERIF CAPITAL P;Lu;0;L;<font> 0050;;;;N;;;;; 1D5B0;MATHEMATICAL SANS-SERIF CAPITAL Q;Lu;0;L;<font> 0051;;;;N;;;;; 1D5B1;MATHEMATICAL SANS-SERIF CAPITAL R;Lu;0;L;<font> 0052;;;;N;;;;; 1D5B2;MATHEMATICAL SANS-SERIF CAPITAL S;Lu;0;L;<font> 0053;;;;N;;;;; 1D5B3;MATHEMATICAL SANS-SERIF CAPITAL T;Lu;0;L;<font> 0054;;;;N;;;;; 1D5B4;MATHEMATICAL SANS-SERIF CAPITAL U;Lu;0;L;<font> 0055;;;;N;;;;; 1D5B5;MATHEMATICAL SANS-SERIF CAPITAL V;Lu;0;L;<font> 0056;;;;N;;;;; 1D5B6;MATHEMATICAL SANS-SERIF CAPITAL W;Lu;0;L;<font> 0057;;;;N;;;;; 1D5B7;MATHEMATICAL SANS-SERIF CAPITAL X;Lu;0;L;<font> 0058;;;;N;;;;; 1D5B8;MATHEMATICAL SANS-SERIF CAPITAL Y;Lu;0;L;<font> 0059;;;;N;;;;; 1D5B9;MATHEMATICAL SANS-SERIF CAPITAL Z;Lu;0;L;<font> 005A;;;;N;;;;; 1D5BA;MATHEMATICAL SANS-SERIF SMALL A;Ll;0;L;<font> 0061;;;;N;;;;; 1D5BB;MATHEMATICAL SANS-SERIF SMALL B;Ll;0;L;<font> 0062;;;;N;;;;; 1D5BC;MATHEMATICAL SANS-SERIF SMALL C;Ll;0;L;<font> 0063;;;;N;;;;; 1D5BD;MATHEMATICAL SANS-SERIF SMALL D;Ll;0;L;<font> 0064;;;;N;;;;; 1D5BE;MATHEMATICAL SANS-SERIF SMALL E;Ll;0;L;<font> 0065;;;;N;;;;; 1D5BF;MATHEMATICAL SANS-SERIF SMALL F;Ll;0;L;<font> 0066;;;;N;;;;; 1D5C0;MATHEMATICAL SANS-SERIF SMALL G;Ll;0;L;<font> 0067;;;;N;;;;; 1D5C1;MATHEMATICAL SANS-SERIF SMALL H;Ll;0;L;<font> 0068;;;;N;;;;; 1D5C2;MATHEMATICAL SANS-SERIF SMALL I;Ll;0;L;<font> 0069;;;;N;;;;; 1D5C3;MATHEMATICAL SANS-SERIF SMALL J;Ll;0;L;<font> 006A;;;;N;;;;; 1D5C4;MATHEMATICAL SANS-SERIF SMALL K;Ll;0;L;<font> 006B;;;;N;;;;; 1D5C5;MATHEMATICAL SANS-SERIF SMALL L;Ll;0;L;<font> 006C;;;;N;;;;; 1D5C6;MATHEMATICAL SANS-SERIF SMALL M;Ll;0;L;<font> 006D;;;;N;;;;; 1D5C7;MATHEMATICAL SANS-SERIF SMALL N;Ll;0;L;<font> 006E;;;;N;;;;; 1D5C8;MATHEMATICAL SANS-SERIF SMALL O;Ll;0;L;<font> 006F;;;;N;;;;; 1D5C9;MATHEMATICAL SANS-SERIF SMALL P;Ll;0;L;<font> 0070;;;;N;;;;; 1D5CA;MATHEMATICAL SANS-SERIF SMALL Q;Ll;0;L;<font> 0071;;;;N;;;;; 1D5CB;MATHEMATICAL SANS-SERIF SMALL R;Ll;0;L;<font> 0072;;;;N;;;;; 1D5CC;MATHEMATICAL SANS-SERIF SMALL S;Ll;0;L;<font> 0073;;;;N;;;;; 1D5CD;MATHEMATICAL SANS-SERIF SMALL T;Ll;0;L;<font> 0074;;;;N;;;;; 1D5CE;MATHEMATICAL SANS-SERIF SMALL U;Ll;0;L;<font> 0075;;;;N;;;;; 1D5CF;MATHEMATICAL SANS-SERIF SMALL V;Ll;0;L;<font> 0076;;;;N;;;;; 1D5D0;MATHEMATICAL SANS-SERIF SMALL W;Ll;0;L;<font> 0077;;;;N;;;;; 1D5D1;MATHEMATICAL SANS-SERIF SMALL X;Ll;0;L;<font> 0078;;;;N;;;;; 1D5D2;MATHEMATICAL SANS-SERIF SMALL Y;Ll;0;L;<font> 0079;;;;N;;;;; 1D5D3;MATHEMATICAL SANS-SERIF SMALL Z;Ll;0;L;<font> 007A;;;;N;;;;; 1D5D4;MATHEMATICAL SANS-SERIF BOLD CAPITAL A;Lu;0;L;<font> 0041;;;;N;;;;; 1D5D5;MATHEMATICAL SANS-SERIF BOLD CAPITAL B;Lu;0;L;<font> 0042;;;;N;;;;; 1D5D6;MATHEMATICAL SANS-SERIF BOLD CAPITAL C;Lu;0;L;<font> 0043;;;;N;;;;; 1D5D7;MATHEMATICAL SANS-SERIF BOLD CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;; 1D5D8;MATHEMATICAL SANS-SERIF BOLD CAPITAL E;Lu;0;L;<font> 0045;;;;N;;;;; 1D5D9;MATHEMATICAL SANS-SERIF BOLD CAPITAL F;Lu;0;L;<font> 0046;;;;N;;;;; 1D5DA;MATHEMATICAL SANS-SERIF BOLD CAPITAL G;Lu;0;L;<font> 0047;;;;N;;;;; 1D5DB;MATHEMATICAL SANS-SERIF BOLD CAPITAL H;Lu;0;L;<font> 0048;;;;N;;;;; 1D5DC;MATHEMATICAL SANS-SERIF BOLD CAPITAL I;Lu;0;L;<font> 0049;;;;N;;;;; 1D5DD;MATHEMATICAL SANS-SERIF BOLD CAPITAL J;Lu;0;L;<font> 004A;;;;N;;;;; 1D5DE;MATHEMATICAL SANS-SERIF BOLD CAPITAL K;Lu;0;L;<font> 004B;;;;N;;;;; 1D5DF;MATHEMATICAL SANS-SERIF BOLD CAPITAL L;Lu;0;L;<font> 004C;;;;N;;;;; 1D5E0;MATHEMATICAL SANS-SERIF BOLD CAPITAL M;Lu;0;L;<font> 004D;;;;N;;;;; 1D5E1;MATHEMATICAL SANS-SERIF BOLD CAPITAL N;Lu;0;L;<font> 004E;;;;N;;;;; 1D5E2;MATHEMATICAL SANS-SERIF BOLD CAPITAL O;Lu;0;L;<font> 004F;;;;N;;;;; 1D5E3;MATHEMATICAL SANS-SERIF BOLD CAPITAL P;Lu;0;L;<font> 0050;;;;N;;;;; 1D5E4;MATHEMATICAL SANS-SERIF BOLD CAPITAL Q;Lu;0;L;<font> 0051;;;;N;;;;; 1D5E5;MATHEMATICAL SANS-SERIF BOLD CAPITAL R;Lu;0;L;<font> 0052;;;;N;;;;; 1D5E6;MATHEMATICAL SANS-SERIF BOLD CAPITAL S;Lu;0;L;<font> 0053;;;;N;;;;; 1D5E7;MATHEMATICAL SANS-SERIF BOLD CAPITAL T;Lu;0;L;<font> 0054;;;;N;;;;; 1D5E8;MATHEMATICAL SANS-SERIF BOLD CAPITAL U;Lu;0;L;<font> 0055;;;;N;;;;; 1D5E9;MATHEMATICAL SANS-SERIF BOLD CAPITAL V;Lu;0;L;<font> 0056;;;;N;;;;; 1D5EA;MATHEMATICAL SANS-SERIF BOLD CAPITAL W;Lu;0;L;<font> 0057;;;;N;;;;; 1D5EB;MATHEMATICAL SANS-SERIF BOLD CAPITAL X;Lu;0;L;<font> 0058;;;;N;;;;; 1D5EC;MATHEMATICAL SANS-SERIF BOLD CAPITAL Y;Lu;0;L;<font> 0059;;;;N;;;;; 1D5ED;MATHEMATICAL SANS-SERIF BOLD CAPITAL Z;Lu;0;L;<font> 005A;;;;N;;;;; 1D5EE;MATHEMATICAL SANS-SERIF BOLD SMALL A;Ll;0;L;<font> 0061;;;;N;;;;; 1D5EF;MATHEMATICAL SANS-SERIF BOLD SMALL B;Ll;0;L;<font> 0062;;;;N;;;;; 1D5F0;MATHEMATICAL SANS-SERIF BOLD SMALL C;Ll;0;L;<font> 0063;;;;N;;;;; 1D5F1;MATHEMATICAL SANS-SERIF BOLD SMALL D;Ll;0;L;<font> 0064;;;;N;;;;; 1D5F2;MATHEMATICAL SANS-SERIF BOLD SMALL E;Ll;0;L;<font> 0065;;;;N;;;;; 1D5F3;MATHEMATICAL SANS-SERIF BOLD SMALL F;Ll;0;L;<font> 0066;;;;N;;;;; 1D5F4;MATHEMATICAL SANS-SERIF BOLD SMALL G;Ll;0;L;<font> 0067;;;;N;;;;; 1D5F5;MATHEMATICAL SANS-SERIF BOLD SMALL H;Ll;0;L;<font> 0068;;;;N;;;;; 1D5F6;MATHEMATICAL SANS-SERIF BOLD SMALL I;Ll;0;L;<font> 0069;;;;N;;;;; 1D5F7;MATHEMATICAL SANS-SERIF BOLD SMALL J;Ll;0;L;<font> 006A;;;;N;;;;; 1D5F8;MATHEMATICAL SANS-SERIF BOLD SMALL K;Ll;0;L;<font> 006B;;;;N;;;;; 1D5F9;MATHEMATICAL SANS-SERIF BOLD SMALL L;Ll;0;L;<font> 006C;;;;N;;;;; 1D5FA;MATHEMATICAL SANS-SERIF BOLD SMALL M;Ll;0;L;<font> 006D;;;;N;;;;; 1D5FB;MATHEMATICAL SANS-SERIF BOLD SMALL N;Ll;0;L;<font> 006E;;;;N;;;;; 1D5FC;MATHEMATICAL SANS-SERIF BOLD SMALL O;Ll;0;L;<font> 006F;;;;N;;;;; 1D5FD;MATHEMATICAL SANS-SERIF BOLD SMALL P;Ll;0;L;<font> 0070;;;;N;;;;; 1D5FE;MATHEMATICAL SANS-SERIF BOLD SMALL Q;Ll;0;L;<font> 0071;;;;N;;;;; 1D5FF;MATHEMATICAL SANS-SERIF BOLD SMALL R;Ll;0;L;<font> 0072;;;;N;;;;; 1D600;MATHEMATICAL SANS-SERIF BOLD SMALL S;Ll;0;L;<font> 0073;;;;N;;;;; 1D601;MATHEMATICAL SANS-SERIF BOLD SMALL T;Ll;0;L;<font> 0074;;;;N;;;;; 1D602;MATHEMATICAL SANS-SERIF BOLD SMALL U;Ll;0;L;<font> 0075;;;;N;;;;; 1D603;MATHEMATICAL SANS-SERIF BOLD SMALL V;Ll;0;L;<font> 0076;;;;N;;;;; 1D604;MATHEMATICAL SANS-SERIF BOLD SMALL W;Ll;0;L;<font> 0077;;;;N;;;;; 1D605;MATHEMATICAL SANS-SERIF BOLD SMALL X;Ll;0;L;<font> 0078;;;;N;;;;; 1D606;MATHEMATICAL SANS-SERIF BOLD SMALL Y;Ll;0;L;<font> 0079;;;;N;;;;; 1D607;MATHEMATICAL SANS-SERIF BOLD SMALL Z;Ll;0;L;<font> 007A;;;;N;;;;; 1D608;MATHEMATICAL SANS-SERIF ITALIC CAPITAL A;Lu;0;L;<font> 0041;;;;N;;;;; 1D609;MATHEMATICAL SANS-SERIF ITALIC CAPITAL B;Lu;0;L;<font> 0042;;;;N;;;;; 1D60A;MATHEMATICAL SANS-SERIF ITALIC CAPITAL C;Lu;0;L;<font> 0043;;;;N;;;;; 1D60B;MATHEMATICAL SANS-SERIF ITALIC CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;; 1D60C;MATHEMATICAL SANS-SERIF ITALIC CAPITAL E;Lu;0;L;<font> 0045;;;;N;;;;; 1D60D;MATHEMATICAL SANS-SERIF ITALIC CAPITAL F;Lu;0;L;<font> 0046;;;;N;;;;; 1D60E;MATHEMATICAL SANS-SERIF ITALIC CAPITAL G;Lu;0;L;<font> 0047;;;;N;;;;; 1D60F;MATHEMATICAL SANS-SERIF ITALIC CAPITAL H;Lu;0;L;<font> 0048;;;;N;;;;; 1D610;MATHEMATICAL SANS-SERIF ITALIC CAPITAL I;Lu;0;L;<font> 0049;;;;N;;;;; 1D611;MATHEMATICAL SANS-SERIF ITALIC CAPITAL J;Lu;0;L;<font> 004A;;;;N;;;;; 1D612;MATHEMATICAL SANS-SERIF ITALIC CAPITAL K;Lu;0;L;<font> 004B;;;;N;;;;; 1D613;MATHEMATICAL SANS-SERIF ITALIC CAPITAL L;Lu;0;L;<font> 004C;;;;N;;;;; 1D614;MATHEMATICAL SANS-SERIF ITALIC CAPITAL M;Lu;0;L;<font> 004D;;;;N;;;;; 1D615;MATHEMATICAL SANS-SERIF ITALIC CAPITAL N;Lu;0;L;<font> 004E;;;;N;;;;; 1D616;MATHEMATICAL SANS-SERIF ITALIC CAPITAL O;Lu;0;L;<font> 004F;;;;N;;;;; 1D617;MATHEMATICAL SANS-SERIF ITALIC CAPITAL P;Lu;0;L;<font> 0050;;;;N;;;;; 1D618;MATHEMATICAL SANS-SERIF ITALIC CAPITAL Q;Lu;0;L;<font> 0051;;;;N;;;;; 1D619;MATHEMATICAL SANS-SERIF ITALIC CAPITAL R;Lu;0;L;<font> 0052;;;;N;;;;; 1D61A;MATHEMATICAL SANS-SERIF ITALIC CAPITAL S;Lu;0;L;<font> 0053;;;;N;;;;; 1D61B;MATHEMATICAL SANS-SERIF ITALIC CAPITAL T;Lu;0;L;<font> 0054;;;;N;;;;; 1D61C;MATHEMATICAL SANS-SERIF ITALIC CAPITAL U;Lu;0;L;<font> 0055;;;;N;;;;; 1D61D;MATHEMATICAL SANS-SERIF ITALIC CAPITAL V;Lu;0;L;<font> 0056;;;;N;;;;; 1D61E;MATHEMATICAL SANS-SERIF ITALIC CAPITAL W;Lu;0;L;<font> 0057;;;;N;;;;; 1D61F;MATHEMATICAL SANS-SERIF ITALIC CAPITAL X;Lu;0;L;<font> 0058;;;;N;;;;; 1D620;MATHEMATICAL SANS-SERIF ITALIC CAPITAL Y;Lu;0;L;<font> 0059;;;;N;;;;; 1D621;MATHEMATICAL SANS-SERIF ITALIC CAPITAL Z;Lu;0;L;<font> 005A;;;;N;;;;; 1D622;MATHEMATICAL SANS-SERIF ITALIC SMALL A;Ll;0;L;<font> 0061;;;;N;;;;; 1D623;MATHEMATICAL SANS-SERIF ITALIC SMALL B;Ll;0;L;<font> 0062;;;;N;;;;; 1D624;MATHEMATICAL SANS-SERIF ITALIC SMALL C;Ll;0;L;<font> 0063;;;;N;;;;; 1D625;MATHEMATICAL SANS-SERIF ITALIC SMALL D;Ll;0;L;<font> 0064;;;;N;;;;; 1D626;MATHEMATICAL SANS-SERIF ITALIC SMALL E;Ll;0;L;<font> 0065;;;;N;;;;; 1D627;MATHEMATICAL SANS-SERIF ITALIC SMALL F;Ll;0;L;<font> 0066;;;;N;;;;; 1D628;MATHEMATICAL SANS-SERIF ITALIC SMALL G;Ll;0;L;<font> 0067;;;;N;;;;; 1D629;MATHEMATICAL SANS-SERIF ITALIC SMALL H;Ll;0;L;<font> 0068;;;;N;;;;; 1D62A;MATHEMATICAL SANS-SERIF ITALIC SMALL I;Ll;0;L;<font> 0069;;;;N;;;;; 1D62B;MATHEMATICAL SANS-SERIF ITALIC SMALL J;Ll;0;L;<font> 006A;;;;N;;;;; 1D62C;MATHEMATICAL SANS-SERIF ITALIC SMALL K;Ll;0;L;<font> 006B;;;;N;;;;; 1D62D;MATHEMATICAL SANS-SERIF ITALIC SMALL L;Ll;0;L;<font> 006C;;;;N;;;;; 1D62E;MATHEMATICAL SANS-SERIF ITALIC SMALL M;Ll;0;L;<font> 006D;;;;N;;;;; 1D62F;MATHEMATICAL SANS-SERIF ITALIC SMALL N;Ll;0;L;<font> 006E;;;;N;;;;; 1D630;MATHEMATICAL SANS-SERIF ITALIC SMALL O;Ll;0;L;<font> 006F;;;;N;;;;; 1D631;MATHEMATICAL SANS-SERIF ITALIC SMALL P;Ll;0;L;<font> 0070;;;;N;;;;; 1D632;MATHEMATICAL SANS-SERIF ITALIC SMALL Q;Ll;0;L;<font> 0071;;;;N;;;;; 1D633;MATHEMATICAL SANS-SERIF ITALIC SMALL R;Ll;0;L;<font> 0072;;;;N;;;;; 1D634;MATHEMATICAL SANS-SERIF ITALIC SMALL S;Ll;0;L;<font> 0073;;;;N;;;;; 1D635;MATHEMATICAL SANS-SERIF ITALIC SMALL T;Ll;0;L;<font> 0074;;;;N;;;;; 1D636;MATHEMATICAL SANS-SERIF ITALIC SMALL U;Ll;0;L;<font> 0075;;;;N;;;;; 1D637;MATHEMATICAL SANS-SERIF ITALIC SMALL V;Ll;0;L;<font> 0076;;;;N;;;;; 1D638;MATHEMATICAL SANS-SERIF ITALIC SMALL W;Ll;0;L;<font> 0077;;;;N;;;;; 1D639;MATHEMATICAL SANS-SERIF ITALIC SMALL X;Ll;0;L;<font> 0078;;;;N;;;;; 1D63A;MATHEMATICAL SANS-SERIF ITALIC SMALL Y;Ll;0;L;<font> 0079;;;;N;;;;; 1D63B;MATHEMATICAL SANS-SERIF ITALIC SMALL Z;Ll;0;L;<font> 007A;;;;N;;;;; 1D63C;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL A;Lu;0;L;<font> 0041;;;;N;;;;; 1D63D;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL B;Lu;0;L;<font> 0042;;;;N;;;;; 1D63E;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL C;Lu;0;L;<font> 0043;;;;N;;;;; 1D63F;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;; 1D640;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL E;Lu;0;L;<font> 0045;;;;N;;;;; 1D641;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL F;Lu;0;L;<font> 0046;;;;N;;;;; 1D642;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL G;Lu;0;L;<font> 0047;;;;N;;;;; 1D643;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL H;Lu;0;L;<font> 0048;;;;N;;;;; 1D644;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL I;Lu;0;L;<font> 0049;;;;N;;;;; 1D645;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL J;Lu;0;L;<font> 004A;;;;N;;;;; 1D646;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL K;Lu;0;L;<font> 004B;;;;N;;;;; 1D647;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL L;Lu;0;L;<font> 004C;;;;N;;;;; 1D648;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL M;Lu;0;L;<font> 004D;;;;N;;;;; 1D649;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL N;Lu;0;L;<font> 004E;;;;N;;;;; 1D64A;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL O;Lu;0;L;<font> 004F;;;;N;;;;; 1D64B;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL P;Lu;0;L;<font> 0050;;;;N;;;;; 1D64C;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL Q;Lu;0;L;<font> 0051;;;;N;;;;; 1D64D;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL R;Lu;0;L;<font> 0052;;;;N;;;;; 1D64E;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL S;Lu;0;L;<font> 0053;;;;N;;;;; 1D64F;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL T;Lu;0;L;<font> 0054;;;;N;;;;; 1D650;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL U;Lu;0;L;<font> 0055;;;;N;;;;; 1D651;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL V;Lu;0;L;<font> 0056;;;;N;;;;; 1D652;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL W;Lu;0;L;<font> 0057;;;;N;;;;; 1D653;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL X;Lu;0;L;<font> 0058;;;;N;;;;; 1D654;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL Y;Lu;0;L;<font> 0059;;;;N;;;;; 1D655;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL Z;Lu;0;L;<font> 005A;;;;N;;;;; 1D656;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL A;Ll;0;L;<font> 0061;;;;N;;;;; 1D657;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL B;Ll;0;L;<font> 0062;;;;N;;;;; 1D658;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL C;Ll;0;L;<font> 0063;;;;N;;;;; 1D659;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL D;Ll;0;L;<font> 0064;;;;N;;;;; 1D65A;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL E;Ll;0;L;<font> 0065;;;;N;;;;; 1D65B;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL F;Ll;0;L;<font> 0066;;;;N;;;;; 1D65C;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL G;Ll;0;L;<font> 0067;;;;N;;;;; 1D65D;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL H;Ll;0;L;<font> 0068;;;;N;;;;; 1D65E;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL I;Ll;0;L;<font> 0069;;;;N;;;;; 1D65F;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL J;Ll;0;L;<font> 006A;;;;N;;;;; 1D660;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL K;Ll;0;L;<font> 006B;;;;N;;;;; 1D661;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL L;Ll;0;L;<font> 006C;;;;N;;;;; 1D662;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL M;Ll;0;L;<font> 006D;;;;N;;;;; 1D663;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL N;Ll;0;L;<font> 006E;;;;N;;;;; 1D664;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL O;Ll;0;L;<font> 006F;;;;N;;;;; 1D665;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL P;Ll;0;L;<font> 0070;;;;N;;;;; 1D666;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL Q;Ll;0;L;<font> 0071;;;;N;;;;; 1D667;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL R;Ll;0;L;<font> 0072;;;;N;;;;; 1D668;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL S;Ll;0;L;<font> 0073;;;;N;;;;; 1D669;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL T;Ll;0;L;<font> 0074;;;;N;;;;; 1D66A;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL U;Ll;0;L;<font> 0075;;;;N;;;;; 1D66B;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL V;Ll;0;L;<font> 0076;;;;N;;;;; 1D66C;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL W;Ll;0;L;<font> 0077;;;;N;;;;; 1D66D;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL X;Ll;0;L;<font> 0078;;;;N;;;;; 1D66E;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL Y;Ll;0;L;<font> 0079;;;;N;;;;; 1D66F;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL Z;Ll;0;L;<font> 007A;;;;N;;;;; 1D670;MATHEMATICAL MONOSPACE CAPITAL A;Lu;0;L;<font> 0041;;;;N;;;;; 1D671;MATHEMATICAL MONOSPACE CAPITAL B;Lu;0;L;<font> 0042;;;;N;;;;; 1D672;MATHEMATICAL MONOSPACE CAPITAL C;Lu;0;L;<font> 0043;;;;N;;;;; 1D673;MATHEMATICAL MONOSPACE CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;; 1D674;MATHEMATICAL MONOSPACE CAPITAL E;Lu;0;L;<font> 0045;;;;N;;;;; 1D675;MATHEMATICAL MONOSPACE CAPITAL F;Lu;0;L;<font> 0046;;;;N;;;;; 1D676;MATHEMATICAL MONOSPACE CAPITAL G;Lu;0;L;<font> 0047;;;;N;;;;; 1D677;MATHEMATICAL MONOSPACE CAPITAL H;Lu;0;L;<font> 0048;;;;N;;;;; 1D678;MATHEMATICAL MONOSPACE CAPITAL I;Lu;0;L;<font> 0049;;;;N;;;;; 1D679;MATHEMATICAL MONOSPACE CAPITAL J;Lu;0;L;<font> 004A;;;;N;;;;; 1D67A;MATHEMATICAL MONOSPACE CAPITAL K;Lu;0;L;<font> 004B;;;;N;;;;; 1D67B;MATHEMATICAL MONOSPACE CAPITAL L;Lu;0;L;<font> 004C;;;;N;;;;; 1D67C;MATHEMATICAL MONOSPACE CAPITAL M;Lu;0;L;<font> 004D;;;;N;;;;; 1D67D;MATHEMATICAL MONOSPACE CAPITAL N;Lu;0;L;<font> 004E;;;;N;;;;; 1D67E;MATHEMATICAL MONOSPACE CAPITAL O;Lu;0;L;<font> 004F;;;;N;;;;; 1D67F;MATHEMATICAL MONOSPACE CAPITAL P;Lu;0;L;<font> 0050;;;;N;;;;; 1D680;MATHEMATICAL MONOSPACE CAPITAL Q;Lu;0;L;<font> 0051;;;;N;;;;; 1D681;MATHEMATICAL MONOSPACE CAPITAL R;Lu;0;L;<font> 0052;;;;N;;;;; 1D682;MATHEMATICAL MONOSPACE CAPITAL S;Lu;0;L;<font> 0053;;;;N;;;;; 1D683;MATHEMATICAL MONOSPACE CAPITAL T;Lu;0;L;<font> 0054;;;;N;;;;; 1D684;MATHEMATICAL MONOSPACE CAPITAL U;Lu;0;L;<font> 0055;;;;N;;;;; 1D685;MATHEMATICAL MONOSPACE CAPITAL V;Lu;0;L;<font> 0056;;;;N;;;;; 1D686;MATHEMATICAL MONOSPACE CAPITAL W;Lu;0;L;<font> 0057;;;;N;;;;; 1D687;MATHEMATICAL MONOSPACE CAPITAL X;Lu;0;L;<font> 0058;;;;N;;;;; 1D688;MATHEMATICAL MONOSPACE CAPITAL Y;Lu;0;L;<font> 0059;;;;N;;;;; 1D689;MATHEMATICAL MONOSPACE CAPITAL Z;Lu;0;L;<font> 005A;;;;N;;;;; 1D68A;MATHEMATICAL MONOSPACE SMALL A;Ll;0;L;<font> 0061;;;;N;;;;; 1D68B;MATHEMATICAL MONOSPACE SMALL B;Ll;0;L;<font> 0062;;;;N;;;;; 1D68C;MATHEMATICAL MONOSPACE SMALL C;Ll;0;L;<font> 0063;;;;N;;;;; 1D68D;MATHEMATICAL MONOSPACE SMALL D;Ll;0;L;<font> 0064;;;;N;;;;; 1D68E;MATHEMATICAL MONOSPACE SMALL E;Ll;0;L;<font> 0065;;;;N;;;;; 1D68F;MATHEMATICAL MONOSPACE SMALL F;Ll;0;L;<font> 0066;;;;N;;;;; 1D690;MATHEMATICAL MONOSPACE SMALL G;Ll;0;L;<font> 0067;;;;N;;;;; 1D691;MATHEMATICAL MONOSPACE SMALL H;Ll;0;L;<font> 0068;;;;N;;;;; 1D692;MATHEMATICAL MONOSPACE SMALL I;Ll;0;L;<font> 0069;;;;N;;;;; 1D693;MATHEMATICAL MONOSPACE SMALL J;Ll;0;L;<font> 006A;;;;N;;;;; 1D694;MATHEMATICAL MONOSPACE SMALL K;Ll;0;L;<font> 006B;;;;N;;;;; 1D695;MATHEMATICAL MONOSPACE SMALL L;Ll;0;L;<font> 006C;;;;N;;;;; 1D696;MATHEMATICAL MONOSPACE SMALL M;Ll;0;L;<font> 006D;;;;N;;;;; 1D697;MATHEMATICAL MONOSPACE SMALL N;Ll;0;L;<font> 006E;;;;N;;;;; 1D698;MATHEMATICAL MONOSPACE SMALL O;Ll;0;L;<font> 006F;;;;N;;;;; 1D699;MATHEMATICAL MONOSPACE SMALL P;Ll;0;L;<font> 0070;;;;N;;;;; 1D69A;MATHEMATICAL MONOSPACE SMALL Q;Ll;0;L;<font> 0071;;;;N;;;;; 1D69B;MATHEMATICAL MONOSPACE SMALL R;Ll;0;L;<font> 0072;;;;N;;;;; 1D69C;MATHEMATICAL MONOSPACE SMALL S;Ll;0;L;<font> 0073;;;;N;;;;; 1D69D;MATHEMATICAL MONOSPACE SMALL T;Ll;0;L;<font> 0074;;;;N;;;;; 1D69E;MATHEMATICAL MONOSPACE SMALL U;Ll;0;L;<font> 0075;;;;N;;;;; 1D69F;MATHEMATICAL MONOSPACE SMALL V;Ll;0;L;<font> 0076;;;;N;;;;; 1D6A0;MATHEMATICAL MONOSPACE SMALL W;Ll;0;L;<font> 0077;;;;N;;;;; 1D6A1;MATHEMATICAL MONOSPACE SMALL X;Ll;0;L;<font> 0078;;;;N;;;;; 1D6A2;MATHEMATICAL MONOSPACE SMALL Y;Ll;0;L;<font> 0079;;;;N;;;;; 1D6A3;MATHEMATICAL MONOSPACE SMALL Z;Ll;0;L;<font> 007A;;;;N;;;;; 1D6A4;MATHEMATICAL ITALIC SMALL DOTLESS I;Ll;0;L;<font> 0131;;;;N;;;;; 1D6A5;MATHEMATICAL ITALIC SMALL DOTLESS J;Ll;0;L;<font> 0237;;;;N;;;;; 1D6A8;MATHEMATICAL BOLD CAPITAL ALPHA;Lu;0;L;<font> 0391;;;;N;;;;; 1D6A9;MATHEMATICAL BOLD CAPITAL BETA;Lu;0;L;<font> 0392;;;;N;;;;; 1D6AA;MATHEMATICAL BOLD CAPITAL GAMMA;Lu;0;L;<font> 0393;;;;N;;;;; 1D6AB;MATHEMATICAL BOLD CAPITAL DELTA;Lu;0;L;<font> 0394;;;;N;;;;; 1D6AC;MATHEMATICAL BOLD CAPITAL EPSILON;Lu;0;L;<font> 0395;;;;N;;;;; 1D6AD;MATHEMATICAL BOLD CAPITAL ZETA;Lu;0;L;<font> 0396;;;;N;;;;; 1D6AE;MATHEMATICAL BOLD CAPITAL ETA;Lu;0;L;<font> 0397;;;;N;;;;; 1D6AF;MATHEMATICAL BOLD CAPITAL THETA;Lu;0;L;<font> 0398;;;;N;;;;; 1D6B0;MATHEMATICAL BOLD CAPITAL IOTA;Lu;0;L;<font> 0399;;;;N;;;;; 1D6B1;MATHEMATICAL BOLD CAPITAL KAPPA;Lu;0;L;<font> 039A;;;;N;;;;; 1D6B2;MATHEMATICAL BOLD CAPITAL LAMDA;Lu;0;L;<font> 039B;;;;N;;;;; 1D6B3;MATHEMATICAL BOLD CAPITAL MU;Lu;0;L;<font> 039C;;;;N;;;;; 1D6B4;MATHEMATICAL BOLD CAPITAL NU;Lu;0;L;<font> 039D;;;;N;;;;; 1D6B5;MATHEMATICAL BOLD CAPITAL XI;Lu;0;L;<font> 039E;;;;N;;;;; 1D6B6;MATHEMATICAL BOLD CAPITAL OMICRON;Lu;0;L;<font> 039F;;;;N;;;;; 1D6B7;MATHEMATICAL BOLD CAPITAL PI;Lu;0;L;<font> 03A0;;;;N;;;;; 1D6B8;MATHEMATICAL BOLD CAPITAL RHO;Lu;0;L;<font> 03A1;;;;N;;;;; 1D6B9;MATHEMATICAL BOLD CAPITAL THETA SYMBOL;Lu;0;L;<font> 03F4;;;;N;;;;; 1D6BA;MATHEMATICAL BOLD CAPITAL SIGMA;Lu;0;L;<font> 03A3;;;;N;;;;; 1D6BB;MATHEMATICAL BOLD CAPITAL TAU;Lu;0;L;<font> 03A4;;;;N;;;;; 1D6BC;MATHEMATICAL BOLD CAPITAL UPSILON;Lu;0;L;<font> 03A5;;;;N;;;;; 1D6BD;MATHEMATICAL BOLD CAPITAL PHI;Lu;0;L;<font> 03A6;;;;N;;;;; 1D6BE;MATHEMATICAL BOLD CAPITAL CHI;Lu;0;L;<font> 03A7;;;;N;;;;; 1D6BF;MATHEMATICAL BOLD CAPITAL PSI;Lu;0;L;<font> 03A8;;;;N;;;;; 1D6C0;MATHEMATICAL BOLD CAPITAL OMEGA;Lu;0;L;<font> 03A9;;;;N;;;;; 1D6C1;MATHEMATICAL BOLD NABLA;Sm;0;L;<font> 2207;;;;N;;;;; 1D6C2;MATHEMATICAL BOLD SMALL ALPHA;Ll;0;L;<font> 03B1;;;;N;;;;; 1D6C3;MATHEMATICAL BOLD SMALL BETA;Ll;0;L;<font> 03B2;;;;N;;;;; 1D6C4;MATHEMATICAL BOLD SMALL GAMMA;Ll;0;L;<font> 03B3;;;;N;;;;; 1D6C5;MATHEMATICAL BOLD SMALL DELTA;Ll;0;L;<font> 03B4;;;;N;;;;; 1D6C6;MATHEMATICAL BOLD SMALL EPSILON;Ll;0;L;<font> 03B5;;;;N;;;;; 1D6C7;MATHEMATICAL BOLD SMALL ZETA;Ll;0;L;<font> 03B6;;;;N;;;;; 1D6C8;MATHEMATICAL BOLD SMALL ETA;Ll;0;L;<font> 03B7;;;;N;;;;; 1D6C9;MATHEMATICAL BOLD SMALL THETA;Ll;0;L;<font> 03B8;;;;N;;;;; 1D6CA;MATHEMATICAL BOLD SMALL IOTA;Ll;0;L;<font> 03B9;;;;N;;;;; 1D6CB;MATHEMATICAL BOLD SMALL KAPPA;Ll;0;L;<font> 03BA;;;;N;;;;; 1D6CC;MATHEMATICAL BOLD SMALL LAMDA;Ll;0;L;<font> 03BB;;;;N;;;;; 1D6CD;MATHEMATICAL BOLD SMALL MU;Ll;0;L;<font> 03BC;;;;N;;;;; 1D6CE;MATHEMATICAL BOLD SMALL NU;Ll;0;L;<font> 03BD;;;;N;;;;; 1D6CF;MATHEMATICAL BOLD SMALL XI;Ll;0;L;<font> 03BE;;;;N;;;;; 1D6D0;MATHEMATICAL BOLD SMALL OMICRON;Ll;0;L;<font> 03BF;;;;N;;;;; 1D6D1;MATHEMATICAL BOLD SMALL PI;Ll;0;L;<font> 03C0;;;;N;;;;; 1D6D2;MATHEMATICAL BOLD SMALL RHO;Ll;0;L;<font> 03C1;;;;N;;;;; 1D6D3;MATHEMATICAL BOLD SMALL FINAL SIGMA;Ll;0;L;<font> 03C2;;;;N;;;;; 1D6D4;MATHEMATICAL BOLD SMALL SIGMA;Ll;0;L;<font> 03C3;;;;N;;;;; 1D6D5;MATHEMATICAL BOLD SMALL TAU;Ll;0;L;<font> 03C4;;;;N;;;;; 1D6D6;MATHEMATICAL BOLD SMALL UPSILON;Ll;0;L;<font> 03C5;;;;N;;;;; 1D6D7;MATHEMATICAL BOLD SMALL PHI;Ll;0;L;<font> 03C6;;;;N;;;;; 1D6D8;MATHEMATICAL BOLD SMALL CHI;Ll;0;L;<font> 03C7;;;;N;;;;; 1D6D9;MATHEMATICAL BOLD SMALL PSI;Ll;0;L;<font> 03C8;;;;N;;;;; 1D6DA;MATHEMATICAL BOLD SMALL OMEGA;Ll;0;L;<font> 03C9;;;;N;;;;; 1D6DB;MATHEMATICAL BOLD PARTIAL DIFFERENTIAL;Sm;0;ON;<font> 2202;;;;Y;;;;; 1D6DC;MATHEMATICAL BOLD EPSILON SYMBOL;Ll;0;L;<font> 03F5;;;;N;;;;; 1D6DD;MATHEMATICAL BOLD THETA SYMBOL;Ll;0;L;<font> 03D1;;;;N;;;;; 1D6DE;MATHEMATICAL BOLD KAPPA SYMBOL;Ll;0;L;<font> 03F0;;;;N;;;;; 1D6DF;MATHEMATICAL BOLD PHI SYMBOL;Ll;0;L;<font> 03D5;;;;N;;;;; 1D6E0;MATHEMATICAL BOLD RHO SYMBOL;Ll;0;L;<font> 03F1;;;;N;;;;; 1D6E1;MATHEMATICAL BOLD PI SYMBOL;Ll;0;L;<font> 03D6;;;;N;;;;; 1D6E2;MATHEMATICAL ITALIC CAPITAL ALPHA;Lu;0;L;<font> 0391;;;;N;;;;; 1D6E3;MATHEMATICAL ITALIC CAPITAL BETA;Lu;0;L;<font> 0392;;;;N;;;;; 1D6E4;MATHEMATICAL ITALIC CAPITAL GAMMA;Lu;0;L;<font> 0393;;;;N;;;;; 1D6E5;MATHEMATICAL ITALIC CAPITAL DELTA;Lu;0;L;<font> 0394;;;;N;;;;; 1D6E6;MATHEMATICAL ITALIC CAPITAL EPSILON;Lu;0;L;<font> 0395;;;;N;;;;; 1D6E7;MATHEMATICAL ITALIC CAPITAL ZETA;Lu;0;L;<font> 0396;;;;N;;;;; 1D6E8;MATHEMATICAL ITALIC CAPITAL ETA;Lu;0;L;<font> 0397;;;;N;;;;; 1D6E9;MATHEMATICAL ITALIC CAPITAL THETA;Lu;0;L;<font> 0398;;;;N;;;;; 1D6EA;MATHEMATICAL ITALIC CAPITAL IOTA;Lu;0;L;<font> 0399;;;;N;;;;; 1D6EB;MATHEMATICAL ITALIC CAPITAL KAPPA;Lu;0;L;<font> 039A;;;;N;;;;; 1D6EC;MATHEMATICAL ITALIC CAPITAL LAMDA;Lu;0;L;<font> 039B;;;;N;;;;; 1D6ED;MATHEMATICAL ITALIC CAPITAL MU;Lu;0;L;<font> 039C;;;;N;;;;; 1D6EE;MATHEMATICAL ITALIC CAPITAL NU;Lu;0;L;<font> 039D;;;;N;;;;; 1D6EF;MATHEMATICAL ITALIC CAPITAL XI;Lu;0;L;<font> 039E;;;;N;;;;; 1D6F0;MATHEMATICAL ITALIC CAPITAL OMICRON;Lu;0;L;<font> 039F;;;;N;;;;; 1D6F1;MATHEMATICAL ITALIC CAPITAL PI;Lu;0;L;<font> 03A0;;;;N;;;;; 1D6F2;MATHEMATICAL ITALIC CAPITAL RHO;Lu;0;L;<font> 03A1;;;;N;;;;; 1D6F3;MATHEMATICAL ITALIC CAPITAL THETA SYMBOL;Lu;0;L;<font> 03F4;;;;N;;;;; 1D6F4;MATHEMATICAL ITALIC CAPITAL SIGMA;Lu;0;L;<font> 03A3;;;;N;;;;; 1D6F5;MATHEMATICAL ITALIC CAPITAL TAU;Lu;0;L;<font> 03A4;;;;N;;;;; 1D6F6;MATHEMATICAL ITALIC CAPITAL UPSILON;Lu;0;L;<font> 03A5;;;;N;;;;; 1D6F7;MATHEMATICAL ITALIC CAPITAL PHI;Lu;0;L;<font> 03A6;;;;N;;;;; 1D6F8;MATHEMATICAL ITALIC CAPITAL CHI;Lu;0;L;<font> 03A7;;;;N;;;;; 1D6F9;MATHEMATICAL ITALIC CAPITAL PSI;Lu;0;L;<font> 03A8;;;;N;;;;; 1D6FA;MATHEMATICAL ITALIC CAPITAL OMEGA;Lu;0;L;<font> 03A9;;;;N;;;;; 1D6FB;MATHEMATICAL ITALIC NABLA;Sm;0;L;<font> 2207;;;;N;;;;; 1D6FC;MATHEMATICAL ITALIC SMALL ALPHA;Ll;0;L;<font> 03B1;;;;N;;;;; 1D6FD;MATHEMATICAL ITALIC SMALL BETA;Ll;0;L;<font> 03B2;;;;N;;;;; 1D6FE;MATHEMATICAL ITALIC SMALL GAMMA;Ll;0;L;<font> 03B3;;;;N;;;;; 1D6FF;MATHEMATICAL ITALIC SMALL DELTA;Ll;0;L;<font> 03B4;;;;N;;;;; 1D700;MATHEMATICAL ITALIC SMALL EPSILON;Ll;0;L;<font> 03B5;;;;N;;;;; 1D701;MATHEMATICAL ITALIC SMALL ZETA;Ll;0;L;<font> 03B6;;;;N;;;;; 1D702;MATHEMATICAL ITALIC SMALL ETA;Ll;0;L;<font> 03B7;;;;N;;;;; 1D703;MATHEMATICAL ITALIC SMALL THETA;Ll;0;L;<font> 03B8;;;;N;;;;; 1D704;MATHEMATICAL ITALIC SMALL IOTA;Ll;0;L;<font> 03B9;;;;N;;;;; 1D705;MATHEMATICAL ITALIC SMALL KAPPA;Ll;0;L;<font> 03BA;;;;N;;;;; 1D706;MATHEMATICAL ITALIC SMALL LAMDA;Ll;0;L;<font> 03BB;;;;N;;;;; 1D707;MATHEMATICAL ITALIC SMALL MU;Ll;0;L;<font> 03BC;;;;N;;;;; 1D708;MATHEMATICAL ITALIC SMALL NU;Ll;0;L;<font> 03BD;;;;N;;;;; 1D709;MATHEMATICAL ITALIC SMALL XI;Ll;0;L;<font> 03BE;;;;N;;;;; 1D70A;MATHEMATICAL ITALIC SMALL OMICRON;Ll;0;L;<font> 03BF;;;;N;;;;; 1D70B;MATHEMATICAL ITALIC SMALL PI;Ll;0;L;<font> 03C0;;;;N;;;;; 1D70C;MATHEMATICAL ITALIC SMALL RHO;Ll;0;L;<font> 03C1;;;;N;;;;; 1D70D;MATHEMATICAL ITALIC SMALL FINAL SIGMA;Ll;0;L;<font> 03C2;;;;N;;;;; 1D70E;MATHEMATICAL ITALIC SMALL SIGMA;Ll;0;L;<font> 03C3;;;;N;;;;; 1D70F;MATHEMATICAL ITALIC SMALL TAU;Ll;0;L;<font> 03C4;;;;N;;;;; 1D710;MATHEMATICAL ITALIC SMALL UPSILON;Ll;0;L;<font> 03C5;;;;N;;;;; 1D711;MATHEMATICAL ITALIC SMALL PHI;Ll;0;L;<font> 03C6;;;;N;;;;; 1D712;MATHEMATICAL ITALIC SMALL CHI;Ll;0;L;<font> 03C7;;;;N;;;;; 1D713;MATHEMATICAL ITALIC SMALL PSI;Ll;0;L;<font> 03C8;;;;N;;;;; 1D714;MATHEMATICAL ITALIC SMALL OMEGA;Ll;0;L;<font> 03C9;;;;N;;;;; 1D715;MATHEMATICAL ITALIC PARTIAL DIFFERENTIAL;Sm;0;ON;<font> 2202;;;;Y;;;;; 1D716;MATHEMATICAL ITALIC EPSILON SYMBOL;Ll;0;L;<font> 03F5;;;;N;;;;; 1D717;MATHEMATICAL ITALIC THETA SYMBOL;Ll;0;L;<font> 03D1;;;;N;;;;; 1D718;MATHEMATICAL ITALIC KAPPA SYMBOL;Ll;0;L;<font> 03F0;;;;N;;;;; 1D719;MATHEMATICAL ITALIC PHI SYMBOL;Ll;0;L;<font> 03D5;;;;N;;;;; 1D71A;MATHEMATICAL ITALIC RHO SYMBOL;Ll;0;L;<font> 03F1;;;;N;;;;; 1D71B;MATHEMATICAL ITALIC PI SYMBOL;Ll;0;L;<font> 03D6;;;;N;;;;; 1D71C;MATHEMATICAL BOLD ITALIC CAPITAL ALPHA;Lu;0;L;<font> 0391;;;;N;;;;; 1D71D;MATHEMATICAL BOLD ITALIC CAPITAL BETA;Lu;0;L;<font> 0392;;;;N;;;;; 1D71E;MATHEMATICAL BOLD ITALIC CAPITAL GAMMA;Lu;0;L;<font> 0393;;;;N;;;;; 1D71F;MATHEMATICAL BOLD ITALIC CAPITAL DELTA;Lu;0;L;<font> 0394;;;;N;;;;; 1D720;MATHEMATICAL BOLD ITALIC CAPITAL EPSILON;Lu;0;L;<font> 0395;;;;N;;;;; 1D721;MATHEMATICAL BOLD ITALIC CAPITAL ZETA;Lu;0;L;<font> 0396;;;;N;;;;; 1D722;MATHEMATICAL BOLD ITALIC CAPITAL ETA;Lu;0;L;<font> 0397;;;;N;;;;; 1D723;MATHEMATICAL BOLD ITALIC CAPITAL THETA;Lu;0;L;<font> 0398;;;;N;;;;; 1D724;MATHEMATICAL BOLD ITALIC CAPITAL IOTA;Lu;0;L;<font> 0399;;;;N;;;;; 1D725;MATHEMATICAL BOLD ITALIC CAPITAL KAPPA;Lu;0;L;<font> 039A;;;;N;;;;; 1D726;MATHEMATICAL BOLD ITALIC CAPITAL LAMDA;Lu;0;L;<font> 039B;;;;N;;;;; 1D727;MATHEMATICAL BOLD ITALIC CAPITAL MU;Lu;0;L;<font> 039C;;;;N;;;;; 1D728;MATHEMATICAL BOLD ITALIC CAPITAL NU;Lu;0;L;<font> 039D;;;;N;;;;; 1D729;MATHEMATICAL BOLD ITALIC CAPITAL XI;Lu;0;L;<font> 039E;;;;N;;;;; 1D72A;MATHEMATICAL BOLD ITALIC CAPITAL OMICRON;Lu;0;L;<font> 039F;;;;N;;;;; 1D72B;MATHEMATICAL BOLD ITALIC CAPITAL PI;Lu;0;L;<font> 03A0;;;;N;;;;; 1D72C;MATHEMATICAL BOLD ITALIC CAPITAL RHO;Lu;0;L;<font> 03A1;;;;N;;;;; 1D72D;MATHEMATICAL BOLD ITALIC CAPITAL THETA SYMBOL;Lu;0;L;<font> 03F4;;;;N;;;;; 1D72E;MATHEMATICAL BOLD ITALIC CAPITAL SIGMA;Lu;0;L;<font> 03A3;;;;N;;;;; 1D72F;MATHEMATICAL BOLD ITALIC CAPITAL TAU;Lu;0;L;<font> 03A4;;;;N;;;;; 1D730;MATHEMATICAL BOLD ITALIC CAPITAL UPSILON;Lu;0;L;<font> 03A5;;;;N;;;;; 1D731;MATHEMATICAL BOLD ITALIC CAPITAL PHI;Lu;0;L;<font> 03A6;;;;N;;;;; 1D732;MATHEMATICAL BOLD ITALIC CAPITAL CHI;Lu;0;L;<font> 03A7;;;;N;;;;; 1D733;MATHEMATICAL BOLD ITALIC CAPITAL PSI;Lu;0;L;<font> 03A8;;;;N;;;;; 1D734;MATHEMATICAL BOLD ITALIC CAPITAL OMEGA;Lu;0;L;<font> 03A9;;;;N;;;;; 1D735;MATHEMATICAL BOLD ITALIC NABLA;Sm;0;L;<font> 2207;;;;N;;;;; 1D736;MATHEMATICAL BOLD ITALIC SMALL ALPHA;Ll;0;L;<font> 03B1;;;;N;;;;; 1D737;MATHEMATICAL BOLD ITALIC SMALL BETA;Ll;0;L;<font> 03B2;;;;N;;;;; 1D738;MATHEMATICAL BOLD ITALIC SMALL GAMMA;Ll;0;L;<font> 03B3;;;;N;;;;; 1D739;MATHEMATICAL BOLD ITALIC SMALL DELTA;Ll;0;L;<font> 03B4;;;;N;;;;; 1D73A;MATHEMATICAL BOLD ITALIC SMALL EPSILON;Ll;0;L;<font> 03B5;;;;N;;;;; 1D73B;MATHEMATICAL BOLD ITALIC SMALL ZETA;Ll;0;L;<font> 03B6;;;;N;;;;; 1D73C;MATHEMATICAL BOLD ITALIC SMALL ETA;Ll;0;L;<font> 03B7;;;;N;;;;; 1D73D;MATHEMATICAL BOLD ITALIC SMALL THETA;Ll;0;L;<font> 03B8;;;;N;;;;; 1D73E;MATHEMATICAL BOLD ITALIC SMALL IOTA;Ll;0;L;<font> 03B9;;;;N;;;;; 1D73F;MATHEMATICAL BOLD ITALIC SMALL KAPPA;Ll;0;L;<font> 03BA;;;;N;;;;; 1D740;MATHEMATICAL BOLD ITALIC SMALL LAMDA;Ll;0;L;<font> 03BB;;;;N;;;;; 1D741;MATHEMATICAL BOLD ITALIC SMALL MU;Ll;0;L;<font> 03BC;;;;N;;;;; 1D742;MATHEMATICAL BOLD ITALIC SMALL NU;Ll;0;L;<font> 03BD;;;;N;;;;; 1D743;MATHEMATICAL BOLD ITALIC SMALL XI;Ll;0;L;<font> 03BE;;;;N;;;;; 1D744;MATHEMATICAL BOLD ITALIC SMALL OMICRON;Ll;0;L;<font> 03BF;;;;N;;;;; 1D745;MATHEMATICAL BOLD ITALIC SMALL PI;Ll;0;L;<font> 03C0;;;;N;;;;; 1D746;MATHEMATICAL BOLD ITALIC SMALL RHO;Ll;0;L;<font> 03C1;;;;N;;;;; 1D747;MATHEMATICAL BOLD ITALIC SMALL FINAL SIGMA;Ll;0;L;<font> 03C2;;;;N;;;;; 1D748;MATHEMATICAL BOLD ITALIC SMALL SIGMA;Ll;0;L;<font> 03C3;;;;N;;;;; 1D749;MATHEMATICAL BOLD ITALIC SMALL TAU;Ll;0;L;<font> 03C4;;;;N;;;;; 1D74A;MATHEMATICAL BOLD ITALIC SMALL UPSILON;Ll;0;L;<font> 03C5;;;;N;;;;; 1D74B;MATHEMATICAL BOLD ITALIC SMALL PHI;Ll;0;L;<font> 03C6;;;;N;;;;; 1D74C;MATHEMATICAL BOLD ITALIC SMALL CHI;Ll;0;L;<font> 03C7;;;;N;;;;; 1D74D;MATHEMATICAL BOLD ITALIC SMALL PSI;Ll;0;L;<font> 03C8;;;;N;;;;; 1D74E;MATHEMATICAL BOLD ITALIC SMALL OMEGA;Ll;0;L;<font> 03C9;;;;N;;;;; 1D74F;MATHEMATICAL BOLD ITALIC PARTIAL DIFFERENTIAL;Sm;0;ON;<font> 2202;;;;Y;;;;; 1D750;MATHEMATICAL BOLD ITALIC EPSILON SYMBOL;Ll;0;L;<font> 03F5;;;;N;;;;; 1D751;MATHEMATICAL BOLD ITALIC THETA SYMBOL;Ll;0;L;<font> 03D1;;;;N;;;;; 1D752;MATHEMATICAL BOLD ITALIC KAPPA SYMBOL;Ll;0;L;<font> 03F0;;;;N;;;;; 1D753;MATHEMATICAL BOLD ITALIC PHI SYMBOL;Ll;0;L;<font> 03D5;;;;N;;;;; 1D754;MATHEMATICAL BOLD ITALIC RHO SYMBOL;Ll;0;L;<font> 03F1;;;;N;;;;; 1D755;MATHEMATICAL BOLD ITALIC PI SYMBOL;Ll;0;L;<font> 03D6;;;;N;;;;; 1D756;MATHEMATICAL SANS-SERIF BOLD CAPITAL ALPHA;Lu;0;L;<font> 0391;;;;N;;;;; 1D757;MATHEMATICAL SANS-SERIF BOLD CAPITAL BETA;Lu;0;L;<font> 0392;;;;N;;;;; 1D758;MATHEMATICAL SANS-SERIF BOLD CAPITAL GAMMA;Lu;0;L;<font> 0393;;;;N;;;;; 1D759;MATHEMATICAL SANS-SERIF BOLD CAPITAL DELTA;Lu;0;L;<font> 0394;;;;N;;;;; 1D75A;MATHEMATICAL SANS-SERIF BOLD CAPITAL EPSILON;Lu;0;L;<font> 0395;;;;N;;;;; 1D75B;MATHEMATICAL SANS-SERIF BOLD CAPITAL ZETA;Lu;0;L;<font> 0396;;;;N;;;;; 1D75C;MATHEMATICAL SANS-SERIF BOLD CAPITAL ETA;Lu;0;L;<font> 0397;;;;N;;;;; 1D75D;MATHEMATICAL SANS-SERIF BOLD CAPITAL THETA;Lu;0;L;<font> 0398;;;;N;;;;; 1D75E;MATHEMATICAL SANS-SERIF BOLD CAPITAL IOTA;Lu;0;L;<font> 0399;;;;N;;;;; 1D75F;MATHEMATICAL SANS-SERIF BOLD CAPITAL KAPPA;Lu;0;L;<font> 039A;;;;N;;;;; 1D760;MATHEMATICAL SANS-SERIF BOLD CAPITAL LAMDA;Lu;0;L;<font> 039B;;;;N;;;;; 1D761;MATHEMATICAL SANS-SERIF BOLD CAPITAL MU;Lu;0;L;<font> 039C;;;;N;;;;; 1D762;MATHEMATICAL SANS-SERIF BOLD CAPITAL NU;Lu;0;L;<font> 039D;;;;N;;;;; 1D763;MATHEMATICAL SANS-SERIF BOLD CAPITAL XI;Lu;0;L;<font> 039E;;;;N;;;;; 1D764;MATHEMATICAL SANS-SERIF BOLD CAPITAL OMICRON;Lu;0;L;<font> 039F;;;;N;;;;; 1D765;MATHEMATICAL SANS-SERIF BOLD CAPITAL PI;Lu;0;L;<font> 03A0;;;;N;;;;; 1D766;MATHEMATICAL SANS-SERIF BOLD CAPITAL RHO;Lu;0;L;<font> 03A1;;;;N;;;;; 1D767;MATHEMATICAL SANS-SERIF BOLD CAPITAL THETA SYMBOL;Lu;0;L;<font> 03F4;;;;N;;;;; 1D768;MATHEMATICAL SANS-SERIF BOLD CAPITAL SIGMA;Lu;0;L;<font> 03A3;;;;N;;;;; 1D769;MATHEMATICAL SANS-SERIF BOLD CAPITAL TAU;Lu;0;L;<font> 03A4;;;;N;;;;; 1D76A;MATHEMATICAL SANS-SERIF BOLD CAPITAL UPSILON;Lu;0;L;<font> 03A5;;;;N;;;;; 1D76B;MATHEMATICAL SANS-SERIF BOLD CAPITAL PHI;Lu;0;L;<font> 03A6;;;;N;;;;; 1D76C;MATHEMATICAL SANS-SERIF BOLD CAPITAL CHI;Lu;0;L;<font> 03A7;;;;N;;;;; 1D76D;MATHEMATICAL SANS-SERIF BOLD CAPITAL PSI;Lu;0;L;<font> 03A8;;;;N;;;;; 1D76E;MATHEMATICAL SANS-SERIF BOLD CAPITAL OMEGA;Lu;0;L;<font> 03A9;;;;N;;;;; 1D76F;MATHEMATICAL SANS-SERIF BOLD NABLA;Sm;0;L;<font> 2207;;;;N;;;;; 1D770;MATHEMATICAL SANS-SERIF BOLD SMALL ALPHA;Ll;0;L;<font> 03B1;;;;N;;;;; 1D771;MATHEMATICAL SANS-SERIF BOLD SMALL BETA;Ll;0;L;<font> 03B2;;;;N;;;;; 1D772;MATHEMATICAL SANS-SERIF BOLD SMALL GAMMA;Ll;0;L;<font> 03B3;;;;N;;;;; 1D773;MATHEMATICAL SANS-SERIF BOLD SMALL DELTA;Ll;0;L;<font> 03B4;;;;N;;;;; 1D774;MATHEMATICAL SANS-SERIF BOLD SMALL EPSILON;Ll;0;L;<font> 03B5;;;;N;;;;; 1D775;MATHEMATICAL SANS-SERIF BOLD SMALL ZETA;Ll;0;L;<font> 03B6;;;;N;;;;; 1D776;MATHEMATICAL SANS-SERIF BOLD SMALL ETA;Ll;0;L;<font> 03B7;;;;N;;;;; 1D777;MATHEMATICAL SANS-SERIF BOLD SMALL THETA;Ll;0;L;<font> 03B8;;;;N;;;;; 1D778;MATHEMATICAL SANS-SERIF BOLD SMALL IOTA;Ll;0;L;<font> 03B9;;;;N;;;;; 1D779;MATHEMATICAL SANS-SERIF BOLD SMALL KAPPA;Ll;0;L;<font> 03BA;;;;N;;;;; 1D77A;MATHEMATICAL SANS-SERIF BOLD SMALL LAMDA;Ll;0;L;<font> 03BB;;;;N;;;;; 1D77B;MATHEMATICAL SANS-SERIF BOLD SMALL MU;Ll;0;L;<font> 03BC;;;;N;;;;; 1D77C;MATHEMATICAL SANS-SERIF BOLD SMALL NU;Ll;0;L;<font> 03BD;;;;N;;;;; 1D77D;MATHEMATICAL SANS-SERIF BOLD SMALL XI;Ll;0;L;<font> 03BE;;;;N;;;;; 1D77E;MATHEMATICAL SANS-SERIF BOLD SMALL OMICRON;Ll;0;L;<font> 03BF;;;;N;;;;; 1D77F;MATHEMATICAL SANS-SERIF BOLD SMALL PI;Ll;0;L;<font> 03C0;;;;N;;;;; 1D780;MATHEMATICAL SANS-SERIF BOLD SMALL RHO;Ll;0;L;<font> 03C1;;;;N;;;;; 1D781;MATHEMATICAL SANS-SERIF BOLD SMALL FINAL SIGMA;Ll;0;L;<font> 03C2;;;;N;;;;; 1D782;MATHEMATICAL SANS-SERIF BOLD SMALL SIGMA;Ll;0;L;<font> 03C3;;;;N;;;;; 1D783;MATHEMATICAL SANS-SERIF BOLD SMALL TAU;Ll;0;L;<font> 03C4;;;;N;;;;; 1D784;MATHEMATICAL SANS-SERIF BOLD SMALL UPSILON;Ll;0;L;<font> 03C5;;;;N;;;;; 1D785;MATHEMATICAL SANS-SERIF BOLD SMALL PHI;Ll;0;L;<font> 03C6;;;;N;;;;; 1D786;MATHEMATICAL SANS-SERIF BOLD SMALL CHI;Ll;0;L;<font> 03C7;;;;N;;;;; 1D787;MATHEMATICAL SANS-SERIF BOLD SMALL PSI;Ll;0;L;<font> 03C8;;;;N;;;;; 1D788;MATHEMATICAL SANS-SERIF BOLD SMALL OMEGA;Ll;0;L;<font> 03C9;;;;N;;;;; 1D789;MATHEMATICAL SANS-SERIF BOLD PARTIAL DIFFERENTIAL;Sm;0;ON;<font> 2202;;;;Y;;;;; 1D78A;MATHEMATICAL SANS-SERIF BOLD EPSILON SYMBOL;Ll;0;L;<font> 03F5;;;;N;;;;; 1D78B;MATHEMATICAL SANS-SERIF BOLD THETA SYMBOL;Ll;0;L;<font> 03D1;;;;N;;;;; 1D78C;MATHEMATICAL SANS-SERIF BOLD KAPPA SYMBOL;Ll;0;L;<font> 03F0;;;;N;;;;; 1D78D;MATHEMATICAL SANS-SERIF BOLD PHI SYMBOL;Ll;0;L;<font> 03D5;;;;N;;;;; 1D78E;MATHEMATICAL SANS-SERIF BOLD RHO SYMBOL;Ll;0;L;<font> 03F1;;;;N;;;;; 1D78F;MATHEMATICAL SANS-SERIF BOLD PI SYMBOL;Ll;0;L;<font> 03D6;;;;N;;;;; 1D790;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL ALPHA;Lu;0;L;<font> 0391;;;;N;;;;; 1D791;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL BETA;Lu;0;L;<font> 0392;;;;N;;;;; 1D792;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL GAMMA;Lu;0;L;<font> 0393;;;;N;;;;; 1D793;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL DELTA;Lu;0;L;<font> 0394;;;;N;;;;; 1D794;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL EPSILON;Lu;0;L;<font> 0395;;;;N;;;;; 1D795;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL ZETA;Lu;0;L;<font> 0396;;;;N;;;;; 1D796;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL ETA;Lu;0;L;<font> 0397;;;;N;;;;; 1D797;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL THETA;Lu;0;L;<font> 0398;;;;N;;;;; 1D798;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL IOTA;Lu;0;L;<font> 0399;;;;N;;;;; 1D799;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL KAPPA;Lu;0;L;<font> 039A;;;;N;;;;; 1D79A;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL LAMDA;Lu;0;L;<font> 039B;;;;N;;;;; 1D79B;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL MU;Lu;0;L;<font> 039C;;;;N;;;;; 1D79C;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL NU;Lu;0;L;<font> 039D;;;;N;;;;; 1D79D;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL XI;Lu;0;L;<font> 039E;;;;N;;;;; 1D79E;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL OMICRON;Lu;0;L;<font> 039F;;;;N;;;;; 1D79F;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL PI;Lu;0;L;<font> 03A0;;;;N;;;;; 1D7A0;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL RHO;Lu;0;L;<font> 03A1;;;;N;;;;; 1D7A1;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL THETA SYMBOL;Lu;0;L;<font> 03F4;;;;N;;;;; 1D7A2;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL SIGMA;Lu;0;L;<font> 03A3;;;;N;;;;; 1D7A3;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL TAU;Lu;0;L;<font> 03A4;;;;N;;;;; 1D7A4;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL UPSILON;Lu;0;L;<font> 03A5;;;;N;;;;; 1D7A5;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL PHI;Lu;0;L;<font> 03A6;;;;N;;;;; 1D7A6;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL CHI;Lu;0;L;<font> 03A7;;;;N;;;;; 1D7A7;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL PSI;Lu;0;L;<font> 03A8;;;;N;;;;; 1D7A8;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL OMEGA;Lu;0;L;<font> 03A9;;;;N;;;;; 1D7A9;MATHEMATICAL SANS-SERIF BOLD ITALIC NABLA;Sm;0;L;<font> 2207;;;;N;;;;; 1D7AA;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ALPHA;Ll;0;L;<font> 03B1;;;;N;;;;; 1D7AB;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL BETA;Ll;0;L;<font> 03B2;;;;N;;;;; 1D7AC;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL GAMMA;Ll;0;L;<font> 03B3;;;;N;;;;; 1D7AD;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL DELTA;Ll;0;L;<font> 03B4;;;;N;;;;; 1D7AE;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL EPSILON;Ll;0;L;<font> 03B5;;;;N;;;;; 1D7AF;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ZETA;Ll;0;L;<font> 03B6;;;;N;;;;; 1D7B0;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ETA;Ll;0;L;<font> 03B7;;;;N;;;;; 1D7B1;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL THETA;Ll;0;L;<font> 03B8;;;;N;;;;; 1D7B2;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL IOTA;Ll;0;L;<font> 03B9;;;;N;;;;; 1D7B3;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL KAPPA;Ll;0;L;<font> 03BA;;;;N;;;;; 1D7B4;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL LAMDA;Ll;0;L;<font> 03BB;;;;N;;;;; 1D7B5;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL MU;Ll;0;L;<font> 03BC;;;;N;;;;; 1D7B6;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL NU;Ll;0;L;<font> 03BD;;;;N;;;;; 1D7B7;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL XI;Ll;0;L;<font> 03BE;;;;N;;;;; 1D7B8;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL OMICRON;Ll;0;L;<font> 03BF;;;;N;;;;; 1D7B9;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL PI;Ll;0;L;<font> 03C0;;;;N;;;;; 1D7BA;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL RHO;Ll;0;L;<font> 03C1;;;;N;;;;; 1D7BB;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL FINAL SIGMA;Ll;0;L;<font> 03C2;;;;N;;;;; 1D7BC;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL SIGMA;Ll;0;L;<font> 03C3;;;;N;;;;; 1D7BD;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL TAU;Ll;0;L;<font> 03C4;;;;N;;;;; 1D7BE;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL UPSILON;Ll;0;L;<font> 03C5;;;;N;;;;; 1D7BF;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL PHI;Ll;0;L;<font> 03C6;;;;N;;;;; 1D7C0;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL CHI;Ll;0;L;<font> 03C7;;;;N;;;;; 1D7C1;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL PSI;Ll;0;L;<font> 03C8;;;;N;;;;; 1D7C2;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL OMEGA;Ll;0;L;<font> 03C9;;;;N;;;;; 1D7C3;MATHEMATICAL SANS-SERIF BOLD ITALIC PARTIAL DIFFERENTIAL;Sm;0;ON;<font> 2202;;;;Y;;;;; 1D7C4;MATHEMATICAL SANS-SERIF BOLD ITALIC EPSILON SYMBOL;Ll;0;L;<font> 03F5;;;;N;;;;; 1D7C5;MATHEMATICAL SANS-SERIF BOLD ITALIC THETA SYMBOL;Ll;0;L;<font> 03D1;;;;N;;;;; 1D7C6;MATHEMATICAL SANS-SERIF BOLD ITALIC KAPPA SYMBOL;Ll;0;L;<font> 03F0;;;;N;;;;; 1D7C7;MATHEMATICAL SANS-SERIF BOLD ITALIC PHI SYMBOL;Ll;0;L;<font> 03D5;;;;N;;;;; 1D7C8;MATHEMATICAL SANS-SERIF BOLD ITALIC RHO SYMBOL;Ll;0;L;<font> 03F1;;;;N;;;;; 1D7C9;MATHEMATICAL SANS-SERIF BOLD ITALIC PI SYMBOL;Ll;0;L;<font> 03D6;;;;N;;;;; 1D7CA;MATHEMATICAL BOLD CAPITAL DIGAMMA;Lu;0;L;<font> 03DC;;;;N;;;;; 1D7CB;MATHEMATICAL BOLD SMALL DIGAMMA;Ll;0;L;<font> 03DD;;;;N;;;;; 1D7CE;MATHEMATICAL BOLD DIGIT ZERO;Nd;0;EN;<font> 0030;0;0;0;N;;;;; 1D7CF;MATHEMATICAL BOLD DIGIT ONE;Nd;0;EN;<font> 0031;1;1;1;N;;;;; 1D7D0;MATHEMATICAL BOLD DIGIT TWO;Nd;0;EN;<font> 0032;2;2;2;N;;;;; 1D7D1;MATHEMATICAL BOLD DIGIT THREE;Nd;0;EN;<font> 0033;3;3;3;N;;;;; 1D7D2;MATHEMATICAL BOLD DIGIT FOUR;Nd;0;EN;<font> 0034;4;4;4;N;;;;; 1D7D3;MATHEMATICAL BOLD DIGIT FIVE;Nd;0;EN;<font> 0035;5;5;5;N;;;;; 1D7D4;MATHEMATICAL BOLD DIGIT SIX;Nd;0;EN;<font> 0036;6;6;6;N;;;;; 1D7D5;MATHEMATICAL BOLD DIGIT SEVEN;Nd;0;EN;<font> 0037;7;7;7;N;;;;; 1D7D6;MATHEMATICAL BOLD DIGIT EIGHT;Nd;0;EN;<font> 0038;8;8;8;N;;;;; 1D7D7;MATHEMATICAL BOLD DIGIT NINE;Nd;0;EN;<font> 0039;9;9;9;N;;;;; 1D7D8;MATHEMATICAL DOUBLE-STRUCK DIGIT ZERO;Nd;0;EN;<font> 0030;0;0;0;N;;;;; 1D7D9;MATHEMATICAL DOUBLE-STRUCK DIGIT ONE;Nd;0;EN;<font> 0031;1;1;1;N;;;;; 1D7DA;MATHEMATICAL DOUBLE-STRUCK DIGIT TWO;Nd;0;EN;<font> 0032;2;2;2;N;;;;; 1D7DB;MATHEMATICAL DOUBLE-STRUCK DIGIT THREE;Nd;0;EN;<font> 0033;3;3;3;N;;;;; 1D7DC;MATHEMATICAL DOUBLE-STRUCK DIGIT FOUR;Nd;0;EN;<font> 0034;4;4;4;N;;;;; 1D7DD;MATHEMATICAL DOUBLE-STRUCK DIGIT FIVE;Nd;0;EN;<font> 0035;5;5;5;N;;;;; 1D7DE;MATHEMATICAL DOUBLE-STRUCK DIGIT SIX;Nd;0;EN;<font> 0036;6;6;6;N;;;;; 1D7DF;MATHEMATICAL DOUBLE-STRUCK DIGIT SEVEN;Nd;0;EN;<font> 0037;7;7;7;N;;;;; 1D7E0;MATHEMATICAL DOUBLE-STRUCK DIGIT EIGHT;Nd;0;EN;<font> 0038;8;8;8;N;;;;; 1D7E1;MATHEMATICAL DOUBLE-STRUCK DIGIT NINE;Nd;0;EN;<font> 0039;9;9;9;N;;;;; 1D7E2;MATHEMATICAL SANS-SERIF DIGIT ZERO;Nd;0;EN;<font> 0030;0;0;0;N;;;;; 1D7E3;MATHEMATICAL SANS-SERIF DIGIT ONE;Nd;0;EN;<font> 0031;1;1;1;N;;;;; 1D7E4;MATHEMATICAL SANS-SERIF DIGIT TWO;Nd;0;EN;<font> 0032;2;2;2;N;;;;; 1D7E5;MATHEMATICAL SANS-SERIF DIGIT THREE;Nd;0;EN;<font> 0033;3;3;3;N;;;;; 1D7E6;MATHEMATICAL SANS-SERIF DIGIT FOUR;Nd;0;EN;<font> 0034;4;4;4;N;;;;; 1D7E7;MATHEMATICAL SANS-SERIF DIGIT FIVE;Nd;0;EN;<font> 0035;5;5;5;N;;;;; 1D7E8;MATHEMATICAL SANS-SERIF DIGIT SIX;Nd;0;EN;<font> 0036;6;6;6;N;;;;; 1D7E9;MATHEMATICAL SANS-SERIF DIGIT SEVEN;Nd;0;EN;<font> 0037;7;7;7;N;;;;; 1D7EA;MATHEMATICAL SANS-SERIF DIGIT EIGHT;Nd;0;EN;<font> 0038;8;8;8;N;;;;; 1D7EB;MATHEMATICAL SANS-SERIF DIGIT NINE;Nd;0;EN;<font> 0039;9;9;9;N;;;;; 1D7EC;MATHEMATICAL SANS-SERIF BOLD DIGIT ZERO;Nd;0;EN;<font> 0030;0;0;0;N;;;;; 1D7ED;MATHEMATICAL SANS-SERIF BOLD DIGIT ONE;Nd;0;EN;<font> 0031;1;1;1;N;;;;; 1D7EE;MATHEMATICAL SANS-SERIF BOLD DIGIT TWO;Nd;0;EN;<font> 0032;2;2;2;N;;;;; 1D7EF;MATHEMATICAL SANS-SERIF BOLD DIGIT THREE;Nd;0;EN;<font> 0033;3;3;3;N;;;;; 1D7F0;MATHEMATICAL SANS-SERIF BOLD DIGIT FOUR;Nd;0;EN;<font> 0034;4;4;4;N;;;;; 1D7F1;MATHEMATICAL SANS-SERIF BOLD DIGIT FIVE;Nd;0;EN;<font> 0035;5;5;5;N;;;;; 1D7F2;MATHEMATICAL SANS-SERIF BOLD DIGIT SIX;Nd;0;EN;<font> 0036;6;6;6;N;;;;; 1D7F3;MATHEMATICAL SANS-SERIF BOLD DIGIT SEVEN;Nd;0;EN;<font> 0037;7;7;7;N;;;;; 1D7F4;MATHEMATICAL SANS-SERIF BOLD DIGIT EIGHT;Nd;0;EN;<font> 0038;8;8;8;N;;;;; 1D7F5;MATHEMATICAL SANS-SERIF BOLD DIGIT NINE;Nd;0;EN;<font> 0039;9;9;9;N;;;;; 1D7F6;MATHEMATICAL MONOSPACE DIGIT ZERO;Nd;0;EN;<font> 0030;0;0;0;N;;;;; 1D7F7;MATHEMATICAL MONOSPACE DIGIT ONE;Nd;0;EN;<font> 0031;1;1;1;N;;;;; 1D7F8;MATHEMATICAL MONOSPACE DIGIT TWO;Nd;0;EN;<font> 0032;2;2;2;N;;;;; 1D7F9;MATHEMATICAL MONOSPACE DIGIT THREE;Nd;0;EN;<font> 0033;3;3;3;N;;;;; 1D7FA;MATHEMATICAL MONOSPACE DIGIT FOUR;Nd;0;EN;<font> 0034;4;4;4;N;;;;; 1D7FB;MATHEMATICAL MONOSPACE DIGIT FIVE;Nd;0;EN;<font> 0035;5;5;5;N;;;;; 1D7FC;MATHEMATICAL MONOSPACE DIGIT SIX;Nd;0;EN;<font> 0036;6;6;6;N;;;;; 1D7FD;MATHEMATICAL MONOSPACE DIGIT SEVEN;Nd;0;EN;<font> 0037;7;7;7;N;;;;; 1D7FE;MATHEMATICAL MONOSPACE DIGIT EIGHT;Nd;0;EN;<font> 0038;8;8;8;N;;;;; 1D7FF;MATHEMATICAL MONOSPACE DIGIT NINE;Nd;0;EN;<font> 0039;9;9;9;N;;;;; 1D800;SIGNWRITING HAND-FIST INDEX;So;0;L;;;;;N;;;;; 1D801;SIGNWRITING HAND-CIRCLE INDEX;So;0;L;;;;;N;;;;; 1D802;SIGNWRITING HAND-CUP INDEX;So;0;L;;;;;N;;;;; 1D803;SIGNWRITING HAND-OVAL INDEX;So;0;L;;;;;N;;;;; 1D804;SIGNWRITING HAND-HINGE INDEX;So;0;L;;;;;N;;;;; 1D805;SIGNWRITING HAND-ANGLE INDEX;So;0;L;;;;;N;;;;; 1D806;SIGNWRITING HAND-FIST INDEX BENT;So;0;L;;;;;N;;;;; 1D807;SIGNWRITING HAND-CIRCLE INDEX BENT;So;0;L;;;;;N;;;;; 1D808;SIGNWRITING HAND-FIST THUMB UNDER INDEX BENT;So;0;L;;;;;N;;;;; 1D809;SIGNWRITING HAND-FIST INDEX RAISED KNUCKLE;So;0;L;;;;;N;;;;; 1D80A;SIGNWRITING HAND-FIST INDEX CUPPED;So;0;L;;;;;N;;;;; 1D80B;SIGNWRITING HAND-FIST INDEX HINGED;So;0;L;;;;;N;;;;; 1D80C;SIGNWRITING HAND-FIST INDEX HINGED LOW;So;0;L;;;;;N;;;;; 1D80D;SIGNWRITING HAND-CIRCLE INDEX HINGE;So;0;L;;;;;N;;;;; 1D80E;SIGNWRITING HAND-FIST INDEX MIDDLE;So;0;L;;;;;N;;;;; 1D80F;SIGNWRITING HAND-CIRCLE INDEX MIDDLE;So;0;L;;;;;N;;;;; 1D810;SIGNWRITING HAND-FIST INDEX MIDDLE BENT;So;0;L;;;;;N;;;;; 1D811;SIGNWRITING HAND-FIST INDEX MIDDLE RAISED KNUCKLES;So;0;L;;;;;N;;;;; 1D812;SIGNWRITING HAND-FIST INDEX MIDDLE HINGED;So;0;L;;;;;N;;;;; 1D813;SIGNWRITING HAND-FIST INDEX UP MIDDLE HINGED;So;0;L;;;;;N;;;;; 1D814;SIGNWRITING HAND-FIST INDEX HINGED MIDDLE UP;So;0;L;;;;;N;;;;; 1D815;SIGNWRITING HAND-FIST INDEX MIDDLE CONJOINED;So;0;L;;;;;N;;;;; 1D816;SIGNWRITING HAND-FIST INDEX MIDDLE CONJOINED INDEX BENT;So;0;L;;;;;N;;;;; 1D817;SIGNWRITING HAND-FIST INDEX MIDDLE CONJOINED MIDDLE BENT;So;0;L;;;;;N;;;;; 1D818;SIGNWRITING HAND-FIST INDEX MIDDLE CONJOINED CUPPED;So;0;L;;;;;N;;;;; 1D819;SIGNWRITING HAND-FIST INDEX MIDDLE CONJOINED HINGED;So;0;L;;;;;N;;;;; 1D81A;SIGNWRITING HAND-FIST INDEX MIDDLE CROSSED;So;0;L;;;;;N;;;;; 1D81B;SIGNWRITING HAND-CIRCLE INDEX MIDDLE CROSSED;So;0;L;;;;;N;;;;; 1D81C;SIGNWRITING HAND-FIST MIDDLE BENT OVER INDEX;So;0;L;;;;;N;;;;; 1D81D;SIGNWRITING HAND-FIST INDEX BENT OVER MIDDLE;So;0;L;;;;;N;;;;; 1D81E;SIGNWRITING HAND-FIST INDEX MIDDLE THUMB;So;0;L;;;;;N;;;;; 1D81F;SIGNWRITING HAND-CIRCLE INDEX MIDDLE THUMB;So;0;L;;;;;N;;;;; 1D820;SIGNWRITING HAND-FIST INDEX MIDDLE STRAIGHT THUMB BENT;So;0;L;;;;;N;;;;; 1D821;SIGNWRITING HAND-FIST INDEX MIDDLE BENT THUMB STRAIGHT;So;0;L;;;;;N;;;;; 1D822;SIGNWRITING HAND-FIST INDEX MIDDLE THUMB BENT;So;0;L;;;;;N;;;;; 1D823;SIGNWRITING HAND-FIST INDEX MIDDLE HINGED SPREAD THUMB SIDE;So;0;L;;;;;N;;;;; 1D824;SIGNWRITING HAND-FIST INDEX UP MIDDLE HINGED THUMB SIDE;So;0;L;;;;;N;;;;; 1D825;SIGNWRITING HAND-FIST INDEX UP MIDDLE HINGED THUMB CONJOINED;So;0;L;;;;;N;;;;; 1D826;SIGNWRITING HAND-FIST INDEX HINGED MIDDLE UP THUMB SIDE;So;0;L;;;;;N;;;;; 1D827;SIGNWRITING HAND-FIST INDEX MIDDLE UP SPREAD THUMB FORWARD;So;0;L;;;;;N;;;;; 1D828;SIGNWRITING HAND-FIST INDEX MIDDLE THUMB CUPPED;So;0;L;;;;;N;;;;; 1D829;SIGNWRITING HAND-FIST INDEX MIDDLE THUMB CIRCLED;So;0;L;;;;;N;;;;; 1D82A;SIGNWRITING HAND-FIST INDEX MIDDLE THUMB HOOKED;So;0;L;;;;;N;;;;; 1D82B;SIGNWRITING HAND-FIST INDEX MIDDLE THUMB HINGED;So;0;L;;;;;N;;;;; 1D82C;SIGNWRITING HAND-FIST THUMB BETWEEN INDEX MIDDLE STRAIGHT;So;0;L;;;;;N;;;;; 1D82D;SIGNWRITING HAND-FIST INDEX MIDDLE CONJOINED THUMB SIDE;So;0;L;;;;;N;;;;; 1D82E;SIGNWRITING HAND-FIST INDEX MIDDLE CONJOINED THUMB SIDE CONJOINED;So;0;L;;;;;N;;;;; 1D82F;SIGNWRITING HAND-FIST INDEX MIDDLE CONJOINED THUMB SIDE BENT;So;0;L;;;;;N;;;;; 1D830;SIGNWRITING HAND-FIST MIDDLE THUMB HOOKED INDEX UP;So;0;L;;;;;N;;;;; 1D831;SIGNWRITING HAND-FIST INDEX THUMB HOOKED MIDDLE UP;So;0;L;;;;;N;;;;; 1D832;SIGNWRITING HAND-FIST INDEX MIDDLE CONJOINED HINGED THUMB SIDE;So;0;L;;;;;N;;;;; 1D833;SIGNWRITING HAND-FIST INDEX MIDDLE CROSSED THUMB SIDE;So;0;L;;;;;N;;;;; 1D834;SIGNWRITING HAND-FIST INDEX MIDDLE CONJOINED THUMB FORWARD;So;0;L;;;;;N;;;;; 1D835;SIGNWRITING HAND-FIST INDEX MIDDLE CONJOINED CUPPED THUMB FORWARD;So;0;L;;;;;N;;;;; 1D836;SIGNWRITING HAND-FIST MIDDLE THUMB CUPPED INDEX UP;So;0;L;;;;;N;;;;; 1D837;SIGNWRITING HAND-FIST INDEX THUMB CUPPED MIDDLE UP;So;0;L;;;;;N;;;;; 1D838;SIGNWRITING HAND-FIST MIDDLE THUMB CIRCLED INDEX UP;So;0;L;;;;;N;;;;; 1D839;SIGNWRITING HAND-FIST MIDDLE THUMB CIRCLED INDEX HINGED;So;0;L;;;;;N;;;;; 1D83A;SIGNWRITING HAND-FIST INDEX THUMB ANGLED OUT MIDDLE UP;So;0;L;;;;;N;;;;; 1D83B;SIGNWRITING HAND-FIST INDEX THUMB ANGLED IN MIDDLE UP;So;0;L;;;;;N;;;;; 1D83C;SIGNWRITING HAND-FIST INDEX THUMB CIRCLED MIDDLE UP;So;0;L;;;;;N;;;;; 1D83D;SIGNWRITING HAND-FIST INDEX MIDDLE THUMB CONJOINED HINGED;So;0;L;;;;;N;;;;; 1D83E;SIGNWRITING HAND-FIST INDEX MIDDLE THUMB ANGLED OUT;So;0;L;;;;;N;;;;; 1D83F;SIGNWRITING HAND-FIST INDEX MIDDLE THUMB ANGLED;So;0;L;;;;;N;;;;; 1D840;SIGNWRITING HAND-FIST MIDDLE THUMB ANGLED OUT INDEX UP;So;0;L;;;;;N;;;;; 1D841;SIGNWRITING HAND-FIST MIDDLE THUMB ANGLED OUT INDEX CROSSED;So;0;L;;;;;N;;;;; 1D842;SIGNWRITING HAND-FIST MIDDLE THUMB ANGLED INDEX UP;So;0;L;;;;;N;;;;; 1D843;SIGNWRITING HAND-FIST INDEX THUMB HOOKED MIDDLE HINGED;So;0;L;;;;;N;;;;; 1D844;SIGNWRITING HAND-FLAT FOUR FINGERS;So;0;L;;;;;N;;;;; 1D845;SIGNWRITING HAND-FLAT FOUR FINGERS BENT;So;0;L;;;;;N;;;;; 1D846;SIGNWRITING HAND-FLAT FOUR FINGERS HINGED;So;0;L;;;;;N;;;;; 1D847;SIGNWRITING HAND-FLAT FOUR FINGERS CONJOINED;So;0;L;;;;;N;;;;; 1D848;SIGNWRITING HAND-FLAT FOUR FINGERS CONJOINED SPLIT;So;0;L;;;;;N;;;;; 1D849;SIGNWRITING HAND-CLAW FOUR FINGERS CONJOINED;So;0;L;;;;;N;;;;; 1D84A;SIGNWRITING HAND-FIST FOUR FINGERS CONJOINED BENT;So;0;L;;;;;N;;;;; 1D84B;SIGNWRITING HAND-HINGE FOUR FINGERS CONJOINED;So;0;L;;;;;N;;;;; 1D84C;SIGNWRITING HAND-FLAT FIVE FINGERS SPREAD;So;0;L;;;;;N;;;;; 1D84D;SIGNWRITING HAND-FLAT HEEL FIVE FINGERS SPREAD;So;0;L;;;;;N;;;;; 1D84E;SIGNWRITING HAND-FLAT FIVE FINGERS SPREAD FOUR BENT;So;0;L;;;;;N;;;;; 1D84F;SIGNWRITING HAND-FLAT HEEL FIVE FINGERS SPREAD FOUR BENT;So;0;L;;;;;N;;;;; 1D850;SIGNWRITING HAND-FLAT FIVE FINGERS SPREAD BENT;So;0;L;;;;;N;;;;; 1D851;SIGNWRITING HAND-FLAT HEEL FIVE FINGERS SPREAD BENT;So;0;L;;;;;N;;;;; 1D852;SIGNWRITING HAND-FLAT FIVE FINGERS SPREAD THUMB FORWARD;So;0;L;;;;;N;;;;; 1D853;SIGNWRITING HAND-CUP FIVE FINGERS SPREAD;So;0;L;;;;;N;;;;; 1D854;SIGNWRITING HAND-CUP FIVE FINGERS SPREAD OPEN;So;0;L;;;;;N;;;;; 1D855;SIGNWRITING HAND-HINGE FIVE FINGERS SPREAD OPEN;So;0;L;;;;;N;;;;; 1D856;SIGNWRITING HAND-OVAL FIVE FINGERS SPREAD;So;0;L;;;;;N;;;;; 1D857;SIGNWRITING HAND-FLAT FIVE FINGERS SPREAD HINGED;So;0;L;;;;;N;;;;; 1D858;SIGNWRITING HAND-FLAT FIVE FINGERS SPREAD HINGED THUMB SIDE;So;0;L;;;;;N;;;;; 1D859;SIGNWRITING HAND-FLAT FIVE FINGERS SPREAD HINGED NO THUMB;So;0;L;;;;;N;;;;; 1D85A;SIGNWRITING HAND-FLAT;So;0;L;;;;;N;;;;; 1D85B;SIGNWRITING HAND-FLAT BETWEEN PALM FACINGS;So;0;L;;;;;N;;;;; 1D85C;SIGNWRITING HAND-FLAT HEEL;So;0;L;;;;;N;;;;; 1D85D;SIGNWRITING HAND-FLAT THUMB SIDE;So;0;L;;;;;N;;;;; 1D85E;SIGNWRITING HAND-FLAT HEEL THUMB SIDE;So;0;L;;;;;N;;;;; 1D85F;SIGNWRITING HAND-FLAT THUMB BENT;So;0;L;;;;;N;;;;; 1D860;SIGNWRITING HAND-FLAT THUMB FORWARD;So;0;L;;;;;N;;;;; 1D861;SIGNWRITING HAND-FLAT SPLIT INDEX THUMB SIDE;So;0;L;;;;;N;;;;; 1D862;SIGNWRITING HAND-FLAT SPLIT CENTRE;So;0;L;;;;;N;;;;; 1D863;SIGNWRITING HAND-FLAT SPLIT CENTRE THUMB SIDE;So;0;L;;;;;N;;;;; 1D864;SIGNWRITING HAND-FLAT SPLIT CENTRE THUMB SIDE BENT;So;0;L;;;;;N;;;;; 1D865;SIGNWRITING HAND-FLAT SPLIT LITTLE;So;0;L;;;;;N;;;;; 1D866;SIGNWRITING HAND-CLAW;So;0;L;;;;;N;;;;; 1D867;SIGNWRITING HAND-CLAW THUMB SIDE;So;0;L;;;;;N;;;;; 1D868;SIGNWRITING HAND-CLAW NO THUMB;So;0;L;;;;;N;;;;; 1D869;SIGNWRITING HAND-CLAW THUMB FORWARD;So;0;L;;;;;N;;;;; 1D86A;SIGNWRITING HAND-HOOK CURLICUE;So;0;L;;;;;N;;;;; 1D86B;SIGNWRITING HAND-HOOK;So;0;L;;;;;N;;;;; 1D86C;SIGNWRITING HAND-CUP OPEN;So;0;L;;;;;N;;;;; 1D86D;SIGNWRITING HAND-CUP;So;0;L;;;;;N;;;;; 1D86E;SIGNWRITING HAND-CUP OPEN THUMB SIDE;So;0;L;;;;;N;;;;; 1D86F;SIGNWRITING HAND-CUP THUMB SIDE;So;0;L;;;;;N;;;;; 1D870;SIGNWRITING HAND-CUP OPEN NO THUMB;So;0;L;;;;;N;;;;; 1D871;SIGNWRITING HAND-CUP NO THUMB;So;0;L;;;;;N;;;;; 1D872;SIGNWRITING HAND-CUP OPEN THUMB FORWARD;So;0;L;;;;;N;;;;; 1D873;SIGNWRITING HAND-CUP THUMB FORWARD;So;0;L;;;;;N;;;;; 1D874;SIGNWRITING HAND-CURLICUE OPEN;So;0;L;;;;;N;;;;; 1D875;SIGNWRITING HAND-CURLICUE;So;0;L;;;;;N;;;;; 1D876;SIGNWRITING HAND-CIRCLE;So;0;L;;;;;N;;;;; 1D877;SIGNWRITING HAND-OVAL;So;0;L;;;;;N;;;;; 1D878;SIGNWRITING HAND-OVAL THUMB SIDE;So;0;L;;;;;N;;;;; 1D879;SIGNWRITING HAND-OVAL NO THUMB;So;0;L;;;;;N;;;;; 1D87A;SIGNWRITING HAND-OVAL THUMB FORWARD;So;0;L;;;;;N;;;;; 1D87B;SIGNWRITING HAND-HINGE OPEN;So;0;L;;;;;N;;;;; 1D87C;SIGNWRITING HAND-HINGE OPEN THUMB FORWARD;So;0;L;;;;;N;;;;; 1D87D;SIGNWRITING HAND-HINGE;So;0;L;;;;;N;;;;; 1D87E;SIGNWRITING HAND-HINGE SMALL;So;0;L;;;;;N;;;;; 1D87F;SIGNWRITING HAND-HINGE OPEN THUMB SIDE;So;0;L;;;;;N;;;;; 1D880;SIGNWRITING HAND-HINGE THUMB SIDE;So;0;L;;;;;N;;;;; 1D881;SIGNWRITING HAND-HINGE OPEN NO THUMB;So;0;L;;;;;N;;;;; 1D882;SIGNWRITING HAND-HINGE NO THUMB;So;0;L;;;;;N;;;;; 1D883;SIGNWRITING HAND-HINGE THUMB SIDE TOUCHING INDEX;So;0;L;;;;;N;;;;; 1D884;SIGNWRITING HAND-HINGE THUMB BETWEEN MIDDLE RING;So;0;L;;;;;N;;;;; 1D885;SIGNWRITING HAND-ANGLE;So;0;L;;;;;N;;;;; 1D886;SIGNWRITING HAND-FIST INDEX MIDDLE RING;So;0;L;;;;;N;;;;; 1D887;SIGNWRITING HAND-CIRCLE INDEX MIDDLE RING;So;0;L;;;;;N;;;;; 1D888;SIGNWRITING HAND-HINGE INDEX MIDDLE RING;So;0;L;;;;;N;;;;; 1D889;SIGNWRITING HAND-ANGLE INDEX MIDDLE RING;So;0;L;;;;;N;;;;; 1D88A;SIGNWRITING HAND-HINGE LITTLE;So;0;L;;;;;N;;;;; 1D88B;SIGNWRITING HAND-FIST INDEX MIDDLE RING BENT;So;0;L;;;;;N;;;;; 1D88C;SIGNWRITING HAND-FIST INDEX MIDDLE RING CONJOINED;So;0;L;;;;;N;;;;; 1D88D;SIGNWRITING HAND-HINGE INDEX MIDDLE RING CONJOINED;So;0;L;;;;;N;;;;; 1D88E;SIGNWRITING HAND-FIST LITTLE DOWN;So;0;L;;;;;N;;;;; 1D88F;SIGNWRITING HAND-FIST LITTLE DOWN RIPPLE STRAIGHT;So;0;L;;;;;N;;;;; 1D890;SIGNWRITING HAND-FIST LITTLE DOWN RIPPLE CURVED;So;0;L;;;;;N;;;;; 1D891;SIGNWRITING HAND-FIST LITTLE DOWN OTHERS CIRCLED;So;0;L;;;;;N;;;;; 1D892;SIGNWRITING HAND-FIST LITTLE UP;So;0;L;;;;;N;;;;; 1D893;SIGNWRITING HAND-FIST THUMB UNDER LITTLE UP;So;0;L;;;;;N;;;;; 1D894;SIGNWRITING HAND-CIRCLE LITTLE UP;So;0;L;;;;;N;;;;; 1D895;SIGNWRITING HAND-OVAL LITTLE UP;So;0;L;;;;;N;;;;; 1D896;SIGNWRITING HAND-ANGLE LITTLE UP;So;0;L;;;;;N;;;;; 1D897;SIGNWRITING HAND-FIST LITTLE RAISED KNUCKLE;So;0;L;;;;;N;;;;; 1D898;SIGNWRITING HAND-FIST LITTLE BENT;So;0;L;;;;;N;;;;; 1D899;SIGNWRITING HAND-FIST LITTLE TOUCHES THUMB;So;0;L;;;;;N;;;;; 1D89A;SIGNWRITING HAND-FIST LITTLE THUMB;So;0;L;;;;;N;;;;; 1D89B;SIGNWRITING HAND-HINGE LITTLE THUMB;So;0;L;;;;;N;;;;; 1D89C;SIGNWRITING HAND-FIST LITTLE INDEX THUMB;So;0;L;;;;;N;;;;; 1D89D;SIGNWRITING HAND-HINGE LITTLE INDEX THUMB;So;0;L;;;;;N;;;;; 1D89E;SIGNWRITING HAND-ANGLE LITTLE INDEX THUMB INDEX THUMB OUT;So;0;L;;;;;N;;;;; 1D89F;SIGNWRITING HAND-ANGLE LITTLE INDEX THUMB INDEX THUMB;So;0;L;;;;;N;;;;; 1D8A0;SIGNWRITING HAND-FIST LITTLE INDEX;So;0;L;;;;;N;;;;; 1D8A1;SIGNWRITING HAND-CIRCLE LITTLE INDEX;So;0;L;;;;;N;;;;; 1D8A2;SIGNWRITING HAND-HINGE LITTLE INDEX;So;0;L;;;;;N;;;;; 1D8A3;SIGNWRITING HAND-ANGLE LITTLE INDEX;So;0;L;;;;;N;;;;; 1D8A4;SIGNWRITING HAND-FIST INDEX MIDDLE LITTLE;So;0;L;;;;;N;;;;; 1D8A5;SIGNWRITING HAND-CIRCLE INDEX MIDDLE LITTLE;So;0;L;;;;;N;;;;; 1D8A6;SIGNWRITING HAND-HINGE INDEX MIDDLE LITTLE;So;0;L;;;;;N;;;;; 1D8A7;SIGNWRITING HAND-HINGE RING;So;0;L;;;;;N;;;;; 1D8A8;SIGNWRITING HAND-ANGLE INDEX MIDDLE LITTLE;So;0;L;;;;;N;;;;; 1D8A9;SIGNWRITING HAND-FIST INDEX MIDDLE CROSS LITTLE;So;0;L;;;;;N;;;;; 1D8AA;SIGNWRITING HAND-CIRCLE INDEX MIDDLE CROSS LITTLE;So;0;L;;;;;N;;;;; 1D8AB;SIGNWRITING HAND-FIST RING DOWN;So;0;L;;;;;N;;;;; 1D8AC;SIGNWRITING HAND-HINGE RING DOWN INDEX THUMB HOOK MIDDLE;So;0;L;;;;;N;;;;; 1D8AD;SIGNWRITING HAND-ANGLE RING DOWN MIDDLE THUMB INDEX CROSS;So;0;L;;;;;N;;;;; 1D8AE;SIGNWRITING HAND-FIST RING UP;So;0;L;;;;;N;;;;; 1D8AF;SIGNWRITING HAND-FIST RING RAISED KNUCKLE;So;0;L;;;;;N;;;;; 1D8B0;SIGNWRITING HAND-FIST RING LITTLE;So;0;L;;;;;N;;;;; 1D8B1;SIGNWRITING HAND-CIRCLE RING LITTLE;So;0;L;;;;;N;;;;; 1D8B2;SIGNWRITING HAND-OVAL RING LITTLE;So;0;L;;;;;N;;;;; 1D8B3;SIGNWRITING HAND-ANGLE RING LITTLE;So;0;L;;;;;N;;;;; 1D8B4;SIGNWRITING HAND-FIST RING MIDDLE;So;0;L;;;;;N;;;;; 1D8B5;SIGNWRITING HAND-FIST RING MIDDLE CONJOINED;So;0;L;;;;;N;;;;; 1D8B6;SIGNWRITING HAND-FIST RING MIDDLE RAISED KNUCKLES;So;0;L;;;;;N;;;;; 1D8B7;SIGNWRITING HAND-FIST RING INDEX;So;0;L;;;;;N;;;;; 1D8B8;SIGNWRITING HAND-FIST RING THUMB;So;0;L;;;;;N;;;;; 1D8B9;SIGNWRITING HAND-HOOK RING THUMB;So;0;L;;;;;N;;;;; 1D8BA;SIGNWRITING HAND-FIST INDEX RING LITTLE;So;0;L;;;;;N;;;;; 1D8BB;SIGNWRITING HAND-CIRCLE INDEX RING LITTLE;So;0;L;;;;;N;;;;; 1D8BC;SIGNWRITING HAND-CURLICUE INDEX RING LITTLE ON;So;0;L;;;;;N;;;;; 1D8BD;SIGNWRITING HAND-HOOK INDEX RING LITTLE OUT;So;0;L;;;;;N;;;;; 1D8BE;SIGNWRITING HAND-HOOK INDEX RING LITTLE IN;So;0;L;;;;;N;;;;; 1D8BF;SIGNWRITING HAND-HOOK INDEX RING LITTLE UNDER;So;0;L;;;;;N;;;;; 1D8C0;SIGNWRITING HAND-CUP INDEX RING LITTLE;So;0;L;;;;;N;;;;; 1D8C1;SIGNWRITING HAND-HINGE INDEX RING LITTLE;So;0;L;;;;;N;;;;; 1D8C2;SIGNWRITING HAND-ANGLE INDEX RING LITTLE OUT;So;0;L;;;;;N;;;;; 1D8C3;SIGNWRITING HAND-ANGLE INDEX RING LITTLE;So;0;L;;;;;N;;;;; 1D8C4;SIGNWRITING HAND-FIST MIDDLE DOWN;So;0;L;;;;;N;;;;; 1D8C5;SIGNWRITING HAND-HINGE MIDDLE;So;0;L;;;;;N;;;;; 1D8C6;SIGNWRITING HAND-FIST MIDDLE UP;So;0;L;;;;;N;;;;; 1D8C7;SIGNWRITING HAND-CIRCLE MIDDLE UP;So;0;L;;;;;N;;;;; 1D8C8;SIGNWRITING HAND-FIST MIDDLE RAISED KNUCKLE;So;0;L;;;;;N;;;;; 1D8C9;SIGNWRITING HAND-FIST MIDDLE UP THUMB SIDE;So;0;L;;;;;N;;;;; 1D8CA;SIGNWRITING HAND-HOOK MIDDLE THUMB;So;0;L;;;;;N;;;;; 1D8CB;SIGNWRITING HAND-FIST MIDDLE THUMB LITTLE;So;0;L;;;;;N;;;;; 1D8CC;SIGNWRITING HAND-FIST MIDDLE LITTLE;So;0;L;;;;;N;;;;; 1D8CD;SIGNWRITING HAND-FIST MIDDLE RING LITTLE;So;0;L;;;;;N;;;;; 1D8CE;SIGNWRITING HAND-CIRCLE MIDDLE RING LITTLE;So;0;L;;;;;N;;;;; 1D8CF;SIGNWRITING HAND-CURLICUE MIDDLE RING LITTLE ON;So;0;L;;;;;N;;;;; 1D8D0;SIGNWRITING HAND-CUP MIDDLE RING LITTLE;So;0;L;;;;;N;;;;; 1D8D1;SIGNWRITING HAND-HINGE MIDDLE RING LITTLE;So;0;L;;;;;N;;;;; 1D8D2;SIGNWRITING HAND-ANGLE MIDDLE RING LITTLE OUT;So;0;L;;;;;N;;;;; 1D8D3;SIGNWRITING HAND-ANGLE MIDDLE RING LITTLE IN;So;0;L;;;;;N;;;;; 1D8D4;SIGNWRITING HAND-ANGLE MIDDLE RING LITTLE;So;0;L;;;;;N;;;;; 1D8D5;SIGNWRITING HAND-CIRCLE MIDDLE RING LITTLE BENT;So;0;L;;;;;N;;;;; 1D8D6;SIGNWRITING HAND-CLAW MIDDLE RING LITTLE CONJOINED;So;0;L;;;;;N;;;;; 1D8D7;SIGNWRITING HAND-CLAW MIDDLE RING LITTLE CONJOINED SIDE;So;0;L;;;;;N;;;;; 1D8D8;SIGNWRITING HAND-HOOK MIDDLE RING LITTLE CONJOINED OUT;So;0;L;;;;;N;;;;; 1D8D9;SIGNWRITING HAND-HOOK MIDDLE RING LITTLE CONJOINED IN;So;0;L;;;;;N;;;;; 1D8DA;SIGNWRITING HAND-HOOK MIDDLE RING LITTLE CONJOINED;So;0;L;;;;;N;;;;; 1D8DB;SIGNWRITING HAND-HINGE INDEX HINGED;So;0;L;;;;;N;;;;; 1D8DC;SIGNWRITING HAND-FIST INDEX THUMB SIDE;So;0;L;;;;;N;;;;; 1D8DD;SIGNWRITING HAND-HINGE INDEX THUMB SIDE;So;0;L;;;;;N;;;;; 1D8DE;SIGNWRITING HAND-FIST INDEX THUMB SIDE THUMB DIAGONAL;So;0;L;;;;;N;;;;; 1D8DF;SIGNWRITING HAND-FIST INDEX THUMB SIDE THUMB CONJOINED;So;0;L;;;;;N;;;;; 1D8E0;SIGNWRITING HAND-FIST INDEX THUMB SIDE THUMB BENT;So;0;L;;;;;N;;;;; 1D8E1;SIGNWRITING HAND-FIST INDEX THUMB SIDE INDEX BENT;So;0;L;;;;;N;;;;; 1D8E2;SIGNWRITING HAND-FIST INDEX THUMB SIDE BOTH BENT;So;0;L;;;;;N;;;;; 1D8E3;SIGNWRITING HAND-FIST INDEX THUMB SIDE INDEX HINGE;So;0;L;;;;;N;;;;; 1D8E4;SIGNWRITING HAND-FIST INDEX THUMB FORWARD INDEX STRAIGHT;So;0;L;;;;;N;;;;; 1D8E5;SIGNWRITING HAND-FIST INDEX THUMB FORWARD INDEX BENT;So;0;L;;;;;N;;;;; 1D8E6;SIGNWRITING HAND-FIST INDEX THUMB HOOK;So;0;L;;;;;N;;;;; 1D8E7;SIGNWRITING HAND-FIST INDEX THUMB CURLICUE;So;0;L;;;;;N;;;;; 1D8E8;SIGNWRITING HAND-FIST INDEX THUMB CURVE THUMB INSIDE;So;0;L;;;;;N;;;;; 1D8E9;SIGNWRITING HAND-CLAW INDEX THUMB CURVE THUMB INSIDE;So;0;L;;;;;N;;;;; 1D8EA;SIGNWRITING HAND-FIST INDEX THUMB CURVE THUMB UNDER;So;0;L;;;;;N;;;;; 1D8EB;SIGNWRITING HAND-FIST INDEX THUMB CIRCLE;So;0;L;;;;;N;;;;; 1D8EC;SIGNWRITING HAND-CUP INDEX THUMB;So;0;L;;;;;N;;;;; 1D8ED;SIGNWRITING HAND-CUP INDEX THUMB OPEN;So;0;L;;;;;N;;;;; 1D8EE;SIGNWRITING HAND-HINGE INDEX THUMB OPEN;So;0;L;;;;;N;;;;; 1D8EF;SIGNWRITING HAND-HINGE INDEX THUMB LARGE;So;0;L;;;;;N;;;;; 1D8F0;SIGNWRITING HAND-HINGE INDEX THUMB;So;0;L;;;;;N;;;;; 1D8F1;SIGNWRITING HAND-HINGE INDEX THUMB SMALL;So;0;L;;;;;N;;;;; 1D8F2;SIGNWRITING HAND-ANGLE INDEX THUMB OUT;So;0;L;;;;;N;;;;; 1D8F3;SIGNWRITING HAND-ANGLE INDEX THUMB IN;So;0;L;;;;;N;;;;; 1D8F4;SIGNWRITING HAND-ANGLE INDEX THUMB;So;0;L;;;;;N;;;;; 1D8F5;SIGNWRITING HAND-FIST THUMB;So;0;L;;;;;N;;;;; 1D8F6;SIGNWRITING HAND-FIST THUMB HEEL;So;0;L;;;;;N;;;;; 1D8F7;SIGNWRITING HAND-FIST THUMB SIDE DIAGONAL;So;0;L;;;;;N;;;;; 1D8F8;SIGNWRITING HAND-FIST THUMB SIDE CONJOINED;So;0;L;;;;;N;;;;; 1D8F9;SIGNWRITING HAND-FIST THUMB SIDE BENT;So;0;L;;;;;N;;;;; 1D8FA;SIGNWRITING HAND-FIST THUMB FORWARD;So;0;L;;;;;N;;;;; 1D8FB;SIGNWRITING HAND-FIST THUMB BETWEEN INDEX MIDDLE;So;0;L;;;;;N;;;;; 1D8FC;SIGNWRITING HAND-FIST THUMB BETWEEN MIDDLE RING;So;0;L;;;;;N;;;;; 1D8FD;SIGNWRITING HAND-FIST THUMB BETWEEN RING LITTLE;So;0;L;;;;;N;;;;; 1D8FE;SIGNWRITING HAND-FIST THUMB UNDER TWO FINGERS;So;0;L;;;;;N;;;;; 1D8FF;SIGNWRITING HAND-FIST THUMB OVER TWO FINGERS;So;0;L;;;;;N;;;;; 1D900;SIGNWRITING HAND-FIST THUMB UNDER THREE FINGERS;So;0;L;;;;;N;;;;; 1D901;SIGNWRITING HAND-FIST THUMB UNDER FOUR FINGERS;So;0;L;;;;;N;;;;; 1D902;SIGNWRITING HAND-FIST THUMB OVER FOUR RAISED KNUCKLES;So;0;L;;;;;N;;;;; 1D903;SIGNWRITING HAND-FIST;So;0;L;;;;;N;;;;; 1D904;SIGNWRITING HAND-FIST HEEL;So;0;L;;;;;N;;;;; 1D905;SIGNWRITING TOUCH SINGLE;So;0;L;;;;;N;;;;; 1D906;SIGNWRITING TOUCH MULTIPLE;So;0;L;;;;;N;;;;; 1D907;SIGNWRITING TOUCH BETWEEN;So;0;L;;;;;N;;;;; 1D908;SIGNWRITING GRASP SINGLE;So;0;L;;;;;N;;;;; 1D909;SIGNWRITING GRASP MULTIPLE;So;0;L;;;;;N;;;;; 1D90A;SIGNWRITING GRASP BETWEEN;So;0;L;;;;;N;;;;; 1D90B;SIGNWRITING STRIKE SINGLE;So;0;L;;;;;N;;;;; 1D90C;SIGNWRITING STRIKE MULTIPLE;So;0;L;;;;;N;;;;; 1D90D;SIGNWRITING STRIKE BETWEEN;So;0;L;;;;;N;;;;; 1D90E;SIGNWRITING BRUSH SINGLE;So;0;L;;;;;N;;;;; 1D90F;SIGNWRITING BRUSH MULTIPLE;So;0;L;;;;;N;;;;; 1D910;SIGNWRITING BRUSH BETWEEN;So;0;L;;;;;N;;;;; 1D911;SIGNWRITING RUB SINGLE;So;0;L;;;;;N;;;;; 1D912;SIGNWRITING RUB MULTIPLE;So;0;L;;;;;N;;;;; 1D913;SIGNWRITING RUB BETWEEN;So;0;L;;;;;N;;;;; 1D914;SIGNWRITING SURFACE SYMBOLS;So;0;L;;;;;N;;;;; 1D915;SIGNWRITING SURFACE BETWEEN;So;0;L;;;;;N;;;;; 1D916;SIGNWRITING SQUEEZE LARGE SINGLE;So;0;L;;;;;N;;;;; 1D917;SIGNWRITING SQUEEZE SMALL SINGLE;So;0;L;;;;;N;;;;; 1D918;SIGNWRITING SQUEEZE LARGE MULTIPLE;So;0;L;;;;;N;;;;; 1D919;SIGNWRITING SQUEEZE SMALL MULTIPLE;So;0;L;;;;;N;;;;; 1D91A;SIGNWRITING SQUEEZE SEQUENTIAL;So;0;L;;;;;N;;;;; 1D91B;SIGNWRITING FLICK LARGE SINGLE;So;0;L;;;;;N;;;;; 1D91C;SIGNWRITING FLICK SMALL SINGLE;So;0;L;;;;;N;;;;; 1D91D;SIGNWRITING FLICK LARGE MULTIPLE;So;0;L;;;;;N;;;;; 1D91E;SIGNWRITING FLICK SMALL MULTIPLE;So;0;L;;;;;N;;;;; 1D91F;SIGNWRITING FLICK SEQUENTIAL;So;0;L;;;;;N;;;;; 1D920;SIGNWRITING SQUEEZE FLICK ALTERNATING;So;0;L;;;;;N;;;;; 1D921;SIGNWRITING MOVEMENT-HINGE UP DOWN LARGE;So;0;L;;;;;N;;;;; 1D922;SIGNWRITING MOVEMENT-HINGE UP DOWN SMALL;So;0;L;;;;;N;;;;; 1D923;SIGNWRITING MOVEMENT-HINGE UP SEQUENTIAL;So;0;L;;;;;N;;;;; 1D924;SIGNWRITING MOVEMENT-HINGE DOWN SEQUENTIAL;So;0;L;;;;;N;;;;; 1D925;SIGNWRITING MOVEMENT-HINGE UP DOWN ALTERNATING LARGE;So;0;L;;;;;N;;;;; 1D926;SIGNWRITING MOVEMENT-HINGE UP DOWN ALTERNATING SMALL;So;0;L;;;;;N;;;;; 1D927;SIGNWRITING MOVEMENT-HINGE SIDE TO SIDE SCISSORS;So;0;L;;;;;N;;;;; 1D928;SIGNWRITING MOVEMENT-WALLPLANE FINGER CONTACT;So;0;L;;;;;N;;;;; 1D929;SIGNWRITING MOVEMENT-FLOORPLANE FINGER CONTACT;So;0;L;;;;;N;;;;; 1D92A;SIGNWRITING MOVEMENT-WALLPLANE SINGLE STRAIGHT SMALL;So;0;L;;;;;N;;;;; 1D92B;SIGNWRITING MOVEMENT-WALLPLANE SINGLE STRAIGHT MEDIUM;So;0;L;;;;;N;;;;; 1D92C;SIGNWRITING MOVEMENT-WALLPLANE SINGLE STRAIGHT LARGE;So;0;L;;;;;N;;;;; 1D92D;SIGNWRITING MOVEMENT-WALLPLANE SINGLE STRAIGHT LARGEST;So;0;L;;;;;N;;;;; 1D92E;SIGNWRITING MOVEMENT-WALLPLANE SINGLE WRIST FLEX;So;0;L;;;;;N;;;;; 1D92F;SIGNWRITING MOVEMENT-WALLPLANE DOUBLE STRAIGHT;So;0;L;;;;;N;;;;; 1D930;SIGNWRITING MOVEMENT-WALLPLANE DOUBLE WRIST FLEX;So;0;L;;;;;N;;;;; 1D931;SIGNWRITING MOVEMENT-WALLPLANE DOUBLE ALTERNATING;So;0;L;;;;;N;;;;; 1D932;SIGNWRITING MOVEMENT-WALLPLANE DOUBLE ALTERNATING WRIST FLEX;So;0;L;;;;;N;;;;; 1D933;SIGNWRITING MOVEMENT-WALLPLANE CROSS;So;0;L;;;;;N;;;;; 1D934;SIGNWRITING MOVEMENT-WALLPLANE TRIPLE STRAIGHT MOVEMENT;So;0;L;;;;;N;;;;; 1D935;SIGNWRITING MOVEMENT-WALLPLANE TRIPLE WRIST FLEX;So;0;L;;;;;N;;;;; 1D936;SIGNWRITING MOVEMENT-WALLPLANE TRIPLE ALTERNATING;So;0;L;;;;;N;;;;; 1D937;SIGNWRITING MOVEMENT-WALLPLANE TRIPLE ALTERNATING WRIST FLEX;So;0;L;;;;;N;;;;; 1D938;SIGNWRITING MOVEMENT-WALLPLANE BEND SMALL;So;0;L;;;;;N;;;;; 1D939;SIGNWRITING MOVEMENT-WALLPLANE BEND MEDIUM;So;0;L;;;;;N;;;;; 1D93A;SIGNWRITING MOVEMENT-WALLPLANE BEND LARGE;So;0;L;;;;;N;;;;; 1D93B;SIGNWRITING MOVEMENT-WALLPLANE CORNER SMALL;So;0;L;;;;;N;;;;; 1D93C;SIGNWRITING MOVEMENT-WALLPLANE CORNER MEDIUM;So;0;L;;;;;N;;;;; 1D93D;SIGNWRITING MOVEMENT-WALLPLANE CORNER LARGE;So;0;L;;;;;N;;;;; 1D93E;SIGNWRITING MOVEMENT-WALLPLANE CORNER ROTATION;So;0;L;;;;;N;;;;; 1D93F;SIGNWRITING MOVEMENT-WALLPLANE CHECK SMALL;So;0;L;;;;;N;;;;; 1D940;SIGNWRITING MOVEMENT-WALLPLANE CHECK MEDIUM;So;0;L;;;;;N;;;;; 1D941;SIGNWRITING MOVEMENT-WALLPLANE CHECK LARGE;So;0;L;;;;;N;;;;; 1D942;SIGNWRITING MOVEMENT-WALLPLANE BOX SMALL;So;0;L;;;;;N;;;;; 1D943;SIGNWRITING MOVEMENT-WALLPLANE BOX MEDIUM;So;0;L;;;;;N;;;;; 1D944;SIGNWRITING MOVEMENT-WALLPLANE BOX LARGE;So;0;L;;;;;N;;;;; 1D945;SIGNWRITING MOVEMENT-WALLPLANE ZIGZAG SMALL;So;0;L;;;;;N;;;;; 1D946;SIGNWRITING MOVEMENT-WALLPLANE ZIGZAG MEDIUM;So;0;L;;;;;N;;;;; 1D947;SIGNWRITING MOVEMENT-WALLPLANE ZIGZAG LARGE;So;0;L;;;;;N;;;;; 1D948;SIGNWRITING MOVEMENT-WALLPLANE PEAKS SMALL;So;0;L;;;;;N;;;;; 1D949;SIGNWRITING MOVEMENT-WALLPLANE PEAKS MEDIUM;So;0;L;;;;;N;;;;; 1D94A;SIGNWRITING MOVEMENT-WALLPLANE PEAKS LARGE;So;0;L;;;;;N;;;;; 1D94B;SIGNWRITING TRAVEL-WALLPLANE ROTATION-WALLPLANE SINGLE;So;0;L;;;;;N;;;;; 1D94C;SIGNWRITING TRAVEL-WALLPLANE ROTATION-WALLPLANE DOUBLE;So;0;L;;;;;N;;;;; 1D94D;SIGNWRITING TRAVEL-WALLPLANE ROTATION-WALLPLANE ALTERNATING;So;0;L;;;;;N;;;;; 1D94E;SIGNWRITING TRAVEL-WALLPLANE ROTATION-FLOORPLANE SINGLE;So;0;L;;;;;N;;;;; 1D94F;SIGNWRITING TRAVEL-WALLPLANE ROTATION-FLOORPLANE DOUBLE;So;0;L;;;;;N;;;;; 1D950;SIGNWRITING TRAVEL-WALLPLANE ROTATION-FLOORPLANE ALTERNATING;So;0;L;;;;;N;;;;; 1D951;SIGNWRITING TRAVEL-WALLPLANE SHAKING;So;0;L;;;;;N;;;;; 1D952;SIGNWRITING TRAVEL-WALLPLANE ARM SPIRAL SINGLE;So;0;L;;;;;N;;;;; 1D953;SIGNWRITING TRAVEL-WALLPLANE ARM SPIRAL DOUBLE;So;0;L;;;;;N;;;;; 1D954;SIGNWRITING TRAVEL-WALLPLANE ARM SPIRAL TRIPLE;So;0;L;;;;;N;;;;; 1D955;SIGNWRITING MOVEMENT-DIAGONAL AWAY SMALL;So;0;L;;;;;N;;;;; 1D956;SIGNWRITING MOVEMENT-DIAGONAL AWAY MEDIUM;So;0;L;;;;;N;;;;; 1D957;SIGNWRITING MOVEMENT-DIAGONAL AWAY LARGE;So;0;L;;;;;N;;;;; 1D958;SIGNWRITING MOVEMENT-DIAGONAL AWAY LARGEST;So;0;L;;;;;N;;;;; 1D959;SIGNWRITING MOVEMENT-DIAGONAL TOWARDS SMALL;So;0;L;;;;;N;;;;; 1D95A;SIGNWRITING MOVEMENT-DIAGONAL TOWARDS MEDIUM;So;0;L;;;;;N;;;;; 1D95B;SIGNWRITING MOVEMENT-DIAGONAL TOWARDS LARGE;So;0;L;;;;;N;;;;; 1D95C;SIGNWRITING MOVEMENT-DIAGONAL TOWARDS LARGEST;So;0;L;;;;;N;;;;; 1D95D;SIGNWRITING MOVEMENT-DIAGONAL BETWEEN AWAY SMALL;So;0;L;;;;;N;;;;; 1D95E;SIGNWRITING MOVEMENT-DIAGONAL BETWEEN AWAY MEDIUM;So;0;L;;;;;N;;;;; 1D95F;SIGNWRITING MOVEMENT-DIAGONAL BETWEEN AWAY LARGE;So;0;L;;;;;N;;;;; 1D960;SIGNWRITING MOVEMENT-DIAGONAL BETWEEN AWAY LARGEST;So;0;L;;;;;N;;;;; 1D961;SIGNWRITING MOVEMENT-DIAGONAL BETWEEN TOWARDS SMALL;So;0;L;;;;;N;;;;; 1D962;SIGNWRITING MOVEMENT-DIAGONAL BETWEEN TOWARDS MEDIUM;So;0;L;;;;;N;;;;; 1D963;SIGNWRITING MOVEMENT-DIAGONAL BETWEEN TOWARDS LARGE;So;0;L;;;;;N;;;;; 1D964;SIGNWRITING MOVEMENT-DIAGONAL BETWEEN TOWARDS LARGEST;So;0;L;;;;;N;;;;; 1D965;SIGNWRITING MOVEMENT-FLOORPLANE SINGLE STRAIGHT SMALL;So;0;L;;;;;N;;;;; 1D966;SIGNWRITING MOVEMENT-FLOORPLANE SINGLE STRAIGHT MEDIUM;So;0;L;;;;;N;;;;; 1D967;SIGNWRITING MOVEMENT-FLOORPLANE SINGLE STRAIGHT LARGE;So;0;L;;;;;N;;;;; 1D968;SIGNWRITING MOVEMENT-FLOORPLANE SINGLE STRAIGHT LARGEST;So;0;L;;;;;N;;;;; 1D969;SIGNWRITING MOVEMENT-FLOORPLANE SINGLE WRIST FLEX;So;0;L;;;;;N;;;;; 1D96A;SIGNWRITING MOVEMENT-FLOORPLANE DOUBLE STRAIGHT;So;0;L;;;;;N;;;;; 1D96B;SIGNWRITING MOVEMENT-FLOORPLANE DOUBLE WRIST FLEX;So;0;L;;;;;N;;;;; 1D96C;SIGNWRITING MOVEMENT-FLOORPLANE DOUBLE ALTERNATING;So;0;L;;;;;N;;;;; 1D96D;SIGNWRITING MOVEMENT-FLOORPLANE DOUBLE ALTERNATING WRIST FLEX;So;0;L;;;;;N;;;;; 1D96E;SIGNWRITING MOVEMENT-FLOORPLANE CROSS;So;0;L;;;;;N;;;;; 1D96F;SIGNWRITING MOVEMENT-FLOORPLANE TRIPLE STRAIGHT MOVEMENT;So;0;L;;;;;N;;;;; 1D970;SIGNWRITING MOVEMENT-FLOORPLANE TRIPLE WRIST FLEX;So;0;L;;;;;N;;;;; 1D971;SIGNWRITING MOVEMENT-FLOORPLANE TRIPLE ALTERNATING MOVEMENT;So;0;L;;;;;N;;;;; 1D972;SIGNWRITING MOVEMENT-FLOORPLANE TRIPLE ALTERNATING WRIST FLEX;So;0;L;;;;;N;;;;; 1D973;SIGNWRITING MOVEMENT-FLOORPLANE BEND;So;0;L;;;;;N;;;;; 1D974;SIGNWRITING MOVEMENT-FLOORPLANE CORNER SMALL;So;0;L;;;;;N;;;;; 1D975;SIGNWRITING MOVEMENT-FLOORPLANE CORNER MEDIUM;So;0;L;;;;;N;;;;; 1D976;SIGNWRITING MOVEMENT-FLOORPLANE CORNER LARGE;So;0;L;;;;;N;;;;; 1D977;SIGNWRITING MOVEMENT-FLOORPLANE CHECK;So;0;L;;;;;N;;;;; 1D978;SIGNWRITING MOVEMENT-FLOORPLANE BOX SMALL;So;0;L;;;;;N;;;;; 1D979;SIGNWRITING MOVEMENT-FLOORPLANE BOX MEDIUM;So;0;L;;;;;N;;;;; 1D97A;SIGNWRITING MOVEMENT-FLOORPLANE BOX LARGE;So;0;L;;;;;N;;;;; 1D97B;SIGNWRITING MOVEMENT-FLOORPLANE ZIGZAG SMALL;So;0;L;;;;;N;;;;; 1D97C;SIGNWRITING MOVEMENT-FLOORPLANE ZIGZAG MEDIUM;So;0;L;;;;;N;;;;; 1D97D;SIGNWRITING MOVEMENT-FLOORPLANE ZIGZAG LARGE;So;0;L;;;;;N;;;;; 1D97E;SIGNWRITING MOVEMENT-FLOORPLANE PEAKS SMALL;So;0;L;;;;;N;;;;; 1D97F;SIGNWRITING MOVEMENT-FLOORPLANE PEAKS MEDIUM;So;0;L;;;;;N;;;;; 1D980;SIGNWRITING MOVEMENT-FLOORPLANE PEAKS LARGE;So;0;L;;;;;N;;;;; 1D981;SIGNWRITING TRAVEL-FLOORPLANE ROTATION-FLOORPLANE SINGLE;So;0;L;;;;;N;;;;; 1D982;SIGNWRITING TRAVEL-FLOORPLANE ROTATION-FLOORPLANE DOUBLE;So;0;L;;;;;N;;;;; 1D983;SIGNWRITING TRAVEL-FLOORPLANE ROTATION-FLOORPLANE ALTERNATING;So;0;L;;;;;N;;;;; 1D984;SIGNWRITING TRAVEL-FLOORPLANE ROTATION-WALLPLANE SINGLE;So;0;L;;;;;N;;;;; 1D985;SIGNWRITING TRAVEL-FLOORPLANE ROTATION-WALLPLANE DOUBLE;So;0;L;;;;;N;;;;; 1D986;SIGNWRITING TRAVEL-FLOORPLANE ROTATION-WALLPLANE ALTERNATING;So;0;L;;;;;N;;;;; 1D987;SIGNWRITING TRAVEL-FLOORPLANE SHAKING;So;0;L;;;;;N;;;;; 1D988;SIGNWRITING MOVEMENT-WALLPLANE CURVE QUARTER SMALL;So;0;L;;;;;N;;;;; 1D989;SIGNWRITING MOVEMENT-WALLPLANE CURVE QUARTER MEDIUM;So;0;L;;;;;N;;;;; 1D98A;SIGNWRITING MOVEMENT-WALLPLANE CURVE QUARTER LARGE;So;0;L;;;;;N;;;;; 1D98B;SIGNWRITING MOVEMENT-WALLPLANE CURVE QUARTER LARGEST;So;0;L;;;;;N;;;;; 1D98C;SIGNWRITING MOVEMENT-WALLPLANE CURVE HALF-CIRCLE SMALL;So;0;L;;;;;N;;;;; 1D98D;SIGNWRITING MOVEMENT-WALLPLANE CURVE HALF-CIRCLE MEDIUM;So;0;L;;;;;N;;;;; 1D98E;SIGNWRITING MOVEMENT-WALLPLANE CURVE HALF-CIRCLE LARGE;So;0;L;;;;;N;;;;; 1D98F;SIGNWRITING MOVEMENT-WALLPLANE CURVE HALF-CIRCLE LARGEST;So;0;L;;;;;N;;;;; 1D990;SIGNWRITING MOVEMENT-WALLPLANE CURVE THREE-QUARTER CIRCLE SMALL;So;0;L;;;;;N;;;;; 1D991;SIGNWRITING MOVEMENT-WALLPLANE CURVE THREE-QUARTER CIRCLE MEDIUM;So;0;L;;;;;N;;;;; 1D992;SIGNWRITING MOVEMENT-WALLPLANE HUMP SMALL;So;0;L;;;;;N;;;;; 1D993;SIGNWRITING MOVEMENT-WALLPLANE HUMP MEDIUM;So;0;L;;;;;N;;;;; 1D994;SIGNWRITING MOVEMENT-WALLPLANE HUMP LARGE;So;0;L;;;;;N;;;;; 1D995;SIGNWRITING MOVEMENT-WALLPLANE LOOP SMALL;So;0;L;;;;;N;;;;; 1D996;SIGNWRITING MOVEMENT-WALLPLANE LOOP MEDIUM;So;0;L;;;;;N;;;;; 1D997;SIGNWRITING MOVEMENT-WALLPLANE LOOP LARGE;So;0;L;;;;;N;;;;; 1D998;SIGNWRITING MOVEMENT-WALLPLANE LOOP SMALL DOUBLE;So;0;L;;;;;N;;;;; 1D999;SIGNWRITING MOVEMENT-WALLPLANE WAVE CURVE DOUBLE SMALL;So;0;L;;;;;N;;;;; 1D99A;SIGNWRITING MOVEMENT-WALLPLANE WAVE CURVE DOUBLE MEDIUM;So;0;L;;;;;N;;;;; 1D99B;SIGNWRITING MOVEMENT-WALLPLANE WAVE CURVE DOUBLE LARGE;So;0;L;;;;;N;;;;; 1D99C;SIGNWRITING MOVEMENT-WALLPLANE WAVE CURVE TRIPLE SMALL;So;0;L;;;;;N;;;;; 1D99D;SIGNWRITING MOVEMENT-WALLPLANE WAVE CURVE TRIPLE MEDIUM;So;0;L;;;;;N;;;;; 1D99E;SIGNWRITING MOVEMENT-WALLPLANE WAVE CURVE TRIPLE LARGE;So;0;L;;;;;N;;;;; 1D99F;SIGNWRITING MOVEMENT-WALLPLANE CURVE THEN STRAIGHT;So;0;L;;;;;N;;;;; 1D9A0;SIGNWRITING MOVEMENT-WALLPLANE CURVED CROSS SMALL;So;0;L;;;;;N;;;;; 1D9A1;SIGNWRITING MOVEMENT-WALLPLANE CURVED CROSS MEDIUM;So;0;L;;;;;N;;;;; 1D9A2;SIGNWRITING ROTATION-WALLPLANE SINGLE;So;0;L;;;;;N;;;;; 1D9A3;SIGNWRITING ROTATION-WALLPLANE DOUBLE;So;0;L;;;;;N;;;;; 1D9A4;SIGNWRITING ROTATION-WALLPLANE ALTERNATE;So;0;L;;;;;N;;;;; 1D9A5;SIGNWRITING MOVEMENT-WALLPLANE SHAKING;So;0;L;;;;;N;;;;; 1D9A6;SIGNWRITING MOVEMENT-WALLPLANE CURVE HITTING FRONT WALL;So;0;L;;;;;N;;;;; 1D9A7;SIGNWRITING MOVEMENT-WALLPLANE HUMP HITTING FRONT WALL;So;0;L;;;;;N;;;;; 1D9A8;SIGNWRITING MOVEMENT-WALLPLANE LOOP HITTING FRONT WALL;So;0;L;;;;;N;;;;; 1D9A9;SIGNWRITING MOVEMENT-WALLPLANE WAVE HITTING FRONT WALL;So;0;L;;;;;N;;;;; 1D9AA;SIGNWRITING ROTATION-WALLPLANE SINGLE HITTING FRONT WALL;So;0;L;;;;;N;;;;; 1D9AB;SIGNWRITING ROTATION-WALLPLANE DOUBLE HITTING FRONT WALL;So;0;L;;;;;N;;;;; 1D9AC;SIGNWRITING ROTATION-WALLPLANE ALTERNATING HITTING FRONT WALL;So;0;L;;;;;N;;;;; 1D9AD;SIGNWRITING MOVEMENT-WALLPLANE CURVE HITTING CHEST;So;0;L;;;;;N;;;;; 1D9AE;SIGNWRITING MOVEMENT-WALLPLANE HUMP HITTING CHEST;So;0;L;;;;;N;;;;; 1D9AF;SIGNWRITING MOVEMENT-WALLPLANE LOOP HITTING CHEST;So;0;L;;;;;N;;;;; 1D9B0;SIGNWRITING MOVEMENT-WALLPLANE WAVE HITTING CHEST;So;0;L;;;;;N;;;;; 1D9B1;SIGNWRITING ROTATION-WALLPLANE SINGLE HITTING CHEST;So;0;L;;;;;N;;;;; 1D9B2;SIGNWRITING ROTATION-WALLPLANE DOUBLE HITTING CHEST;So;0;L;;;;;N;;;;; 1D9B3;SIGNWRITING ROTATION-WALLPLANE ALTERNATING HITTING CHEST;So;0;L;;;;;N;;;;; 1D9B4;SIGNWRITING MOVEMENT-WALLPLANE WAVE DIAGONAL PATH SMALL;So;0;L;;;;;N;;;;; 1D9B5;SIGNWRITING MOVEMENT-WALLPLANE WAVE DIAGONAL PATH MEDIUM;So;0;L;;;;;N;;;;; 1D9B6;SIGNWRITING MOVEMENT-WALLPLANE WAVE DIAGONAL PATH LARGE;So;0;L;;;;;N;;;;; 1D9B7;SIGNWRITING MOVEMENT-FLOORPLANE CURVE HITTING CEILING SMALL;So;0;L;;;;;N;;;;; 1D9B8;SIGNWRITING MOVEMENT-FLOORPLANE CURVE HITTING CEILING LARGE;So;0;L;;;;;N;;;;; 1D9B9;SIGNWRITING MOVEMENT-FLOORPLANE HUMP HITTING CEILING SMALL DOUBLE;So;0;L;;;;;N;;;;; 1D9BA;SIGNWRITING MOVEMENT-FLOORPLANE HUMP HITTING CEILING LARGE DOUBLE;So;0;L;;;;;N;;;;; 1D9BB;SIGNWRITING MOVEMENT-FLOORPLANE HUMP HITTING CEILING SMALL TRIPLE;So;0;L;;;;;N;;;;; 1D9BC;SIGNWRITING MOVEMENT-FLOORPLANE HUMP HITTING CEILING LARGE TRIPLE;So;0;L;;;;;N;;;;; 1D9BD;SIGNWRITING MOVEMENT-FLOORPLANE LOOP HITTING CEILING SMALL SINGLE;So;0;L;;;;;N;;;;; 1D9BE;SIGNWRITING MOVEMENT-FLOORPLANE LOOP HITTING CEILING LARGE SINGLE;So;0;L;;;;;N;;;;; 1D9BF;SIGNWRITING MOVEMENT-FLOORPLANE LOOP HITTING CEILING SMALL DOUBLE;So;0;L;;;;;N;;;;; 1D9C0;SIGNWRITING MOVEMENT-FLOORPLANE LOOP HITTING CEILING LARGE DOUBLE;So;0;L;;;;;N;;;;; 1D9C1;SIGNWRITING MOVEMENT-FLOORPLANE WAVE HITTING CEILING SMALL;So;0;L;;;;;N;;;;; 1D9C2;SIGNWRITING MOVEMENT-FLOORPLANE WAVE HITTING CEILING LARGE;So;0;L;;;;;N;;;;; 1D9C3;SIGNWRITING ROTATION-FLOORPLANE SINGLE HITTING CEILING;So;0;L;;;;;N;;;;; 1D9C4;SIGNWRITING ROTATION-FLOORPLANE DOUBLE HITTING CEILING;So;0;L;;;;;N;;;;; 1D9C5;SIGNWRITING ROTATION-FLOORPLANE ALTERNATING HITTING CEILING;So;0;L;;;;;N;;;;; 1D9C6;SIGNWRITING MOVEMENT-FLOORPLANE CURVE HITTING FLOOR SMALL;So;0;L;;;;;N;;;;; 1D9C7;SIGNWRITING MOVEMENT-FLOORPLANE CURVE HITTING FLOOR LARGE;So;0;L;;;;;N;;;;; 1D9C8;SIGNWRITING MOVEMENT-FLOORPLANE HUMP HITTING FLOOR SMALL DOUBLE;So;0;L;;;;;N;;;;; 1D9C9;SIGNWRITING MOVEMENT-FLOORPLANE HUMP HITTING FLOOR LARGE DOUBLE;So;0;L;;;;;N;;;;; 1D9CA;SIGNWRITING MOVEMENT-FLOORPLANE HUMP HITTING FLOOR TRIPLE SMALL TRIPLE;So;0;L;;;;;N;;;;; 1D9CB;SIGNWRITING MOVEMENT-FLOORPLANE HUMP HITTING FLOOR TRIPLE LARGE TRIPLE;So;0;L;;;;;N;;;;; 1D9CC;SIGNWRITING MOVEMENT-FLOORPLANE LOOP HITTING FLOOR SMALL SINGLE;So;0;L;;;;;N;;;;; 1D9CD;SIGNWRITING MOVEMENT-FLOORPLANE LOOP HITTING FLOOR LARGE SINGLE;So;0;L;;;;;N;;;;; 1D9CE;SIGNWRITING MOVEMENT-FLOORPLANE LOOP HITTING FLOOR SMALL DOUBLE;So;0;L;;;;;N;;;;; 1D9CF;SIGNWRITING MOVEMENT-FLOORPLANE LOOP HITTING FLOOR LARGE DOUBLE;So;0;L;;;;;N;;;;; 1D9D0;SIGNWRITING MOVEMENT-FLOORPLANE WAVE HITTING FLOOR SMALL;So;0;L;;;;;N;;;;; 1D9D1;SIGNWRITING MOVEMENT-FLOORPLANE WAVE HITTING FLOOR LARGE;So;0;L;;;;;N;;;;; 1D9D2;SIGNWRITING ROTATION-FLOORPLANE SINGLE HITTING FLOOR;So;0;L;;;;;N;;;;; 1D9D3;SIGNWRITING ROTATION-FLOORPLANE DOUBLE HITTING FLOOR;So;0;L;;;;;N;;;;; 1D9D4;SIGNWRITING ROTATION-FLOORPLANE ALTERNATING HITTING FLOOR;So;0;L;;;;;N;;;;; 1D9D5;SIGNWRITING MOVEMENT-FLOORPLANE CURVE SMALL;So;0;L;;;;;N;;;;; 1D9D6;SIGNWRITING MOVEMENT-FLOORPLANE CURVE MEDIUM;So;0;L;;;;;N;;;;; 1D9D7;SIGNWRITING MOVEMENT-FLOORPLANE CURVE LARGE;So;0;L;;;;;N;;;;; 1D9D8;SIGNWRITING MOVEMENT-FLOORPLANE CURVE LARGEST;So;0;L;;;;;N;;;;; 1D9D9;SIGNWRITING MOVEMENT-FLOORPLANE CURVE COMBINED;So;0;L;;;;;N;;;;; 1D9DA;SIGNWRITING MOVEMENT-FLOORPLANE HUMP SMALL;So;0;L;;;;;N;;;;; 1D9DB;SIGNWRITING MOVEMENT-FLOORPLANE LOOP SMALL;So;0;L;;;;;N;;;;; 1D9DC;SIGNWRITING MOVEMENT-FLOORPLANE WAVE SNAKE;So;0;L;;;;;N;;;;; 1D9DD;SIGNWRITING MOVEMENT-FLOORPLANE WAVE SMALL;So;0;L;;;;;N;;;;; 1D9DE;SIGNWRITING MOVEMENT-FLOORPLANE WAVE LARGE;So;0;L;;;;;N;;;;; 1D9DF;SIGNWRITING ROTATION-FLOORPLANE SINGLE;So;0;L;;;;;N;;;;; 1D9E0;SIGNWRITING ROTATION-FLOORPLANE DOUBLE;So;0;L;;;;;N;;;;; 1D9E1;SIGNWRITING ROTATION-FLOORPLANE ALTERNATING;So;0;L;;;;;N;;;;; 1D9E2;SIGNWRITING MOVEMENT-FLOORPLANE SHAKING PARALLEL;So;0;L;;;;;N;;;;; 1D9E3;SIGNWRITING MOVEMENT-WALLPLANE ARM CIRCLE SMALL SINGLE;So;0;L;;;;;N;;;;; 1D9E4;SIGNWRITING MOVEMENT-WALLPLANE ARM CIRCLE MEDIUM SINGLE;So;0;L;;;;;N;;;;; 1D9E5;SIGNWRITING MOVEMENT-WALLPLANE ARM CIRCLE SMALL DOUBLE;So;0;L;;;;;N;;;;; 1D9E6;SIGNWRITING MOVEMENT-WALLPLANE ARM CIRCLE MEDIUM DOUBLE;So;0;L;;;;;N;;;;; 1D9E7;SIGNWRITING MOVEMENT-FLOORPLANE ARM CIRCLE HITTING WALL SMALL SINGLE;So;0;L;;;;;N;;;;; 1D9E8;SIGNWRITING MOVEMENT-FLOORPLANE ARM CIRCLE HITTING WALL MEDIUM SINGLE;So;0;L;;;;;N;;;;; 1D9E9;SIGNWRITING MOVEMENT-FLOORPLANE ARM CIRCLE HITTING WALL LARGE SINGLE;So;0;L;;;;;N;;;;; 1D9EA;SIGNWRITING MOVEMENT-FLOORPLANE ARM CIRCLE HITTING WALL SMALL DOUBLE;So;0;L;;;;;N;;;;; 1D9EB;SIGNWRITING MOVEMENT-FLOORPLANE ARM CIRCLE HITTING WALL MEDIUM DOUBLE;So;0;L;;;;;N;;;;; 1D9EC;SIGNWRITING MOVEMENT-FLOORPLANE ARM CIRCLE HITTING WALL LARGE DOUBLE;So;0;L;;;;;N;;;;; 1D9ED;SIGNWRITING MOVEMENT-WALLPLANE WRIST CIRCLE FRONT SINGLE;So;0;L;;;;;N;;;;; 1D9EE;SIGNWRITING MOVEMENT-WALLPLANE WRIST CIRCLE FRONT DOUBLE;So;0;L;;;;;N;;;;; 1D9EF;SIGNWRITING MOVEMENT-FLOORPLANE WRIST CIRCLE HITTING WALL SINGLE;So;0;L;;;;;N;;;;; 1D9F0;SIGNWRITING MOVEMENT-FLOORPLANE WRIST CIRCLE HITTING WALL DOUBLE;So;0;L;;;;;N;;;;; 1D9F1;SIGNWRITING MOVEMENT-WALLPLANE FINGER CIRCLES SINGLE;So;0;L;;;;;N;;;;; 1D9F2;SIGNWRITING MOVEMENT-WALLPLANE FINGER CIRCLES DOUBLE;So;0;L;;;;;N;;;;; 1D9F3;SIGNWRITING MOVEMENT-FLOORPLANE FINGER CIRCLES HITTING WALL SINGLE;So;0;L;;;;;N;;;;; 1D9F4;SIGNWRITING MOVEMENT-FLOORPLANE FINGER CIRCLES HITTING WALL DOUBLE;So;0;L;;;;;N;;;;; 1D9F5;SIGNWRITING DYNAMIC ARROWHEAD SMALL;So;0;L;;;;;N;;;;; 1D9F6;SIGNWRITING DYNAMIC ARROWHEAD LARGE;So;0;L;;;;;N;;;;; 1D9F7;SIGNWRITING DYNAMIC FAST;So;0;L;;;;;N;;;;; 1D9F8;SIGNWRITING DYNAMIC SLOW;So;0;L;;;;;N;;;;; 1D9F9;SIGNWRITING DYNAMIC TENSE;So;0;L;;;;;N;;;;; 1D9FA;SIGNWRITING DYNAMIC RELAXED;So;0;L;;;;;N;;;;; 1D9FB;SIGNWRITING DYNAMIC SIMULTANEOUS;So;0;L;;;;;N;;;;; 1D9FC;SIGNWRITING DYNAMIC SIMULTANEOUS ALTERNATING;So;0;L;;;;;N;;;;; 1D9FD;SIGNWRITING DYNAMIC EVERY OTHER TIME;So;0;L;;;;;N;;;;; 1D9FE;SIGNWRITING DYNAMIC GRADUAL;So;0;L;;;;;N;;;;; 1D9FF;SIGNWRITING HEAD;So;0;L;;;;;N;;;;; 1DA00;SIGNWRITING HEAD RIM;Mn;0;NSM;;;;;N;;;;; 1DA01;SIGNWRITING HEAD MOVEMENT-WALLPLANE STRAIGHT;Mn;0;NSM;;;;;N;;;;; 1DA02;SIGNWRITING HEAD MOVEMENT-WALLPLANE TILT;Mn;0;NSM;;;;;N;;;;; 1DA03;SIGNWRITING HEAD MOVEMENT-FLOORPLANE STRAIGHT;Mn;0;NSM;;;;;N;;;;; 1DA04;SIGNWRITING HEAD MOVEMENT-WALLPLANE CURVE;Mn;0;NSM;;;;;N;;;;; 1DA05;SIGNWRITING HEAD MOVEMENT-FLOORPLANE CURVE;Mn;0;NSM;;;;;N;;;;; 1DA06;SIGNWRITING HEAD MOVEMENT CIRCLE;Mn;0;NSM;;;;;N;;;;; 1DA07;SIGNWRITING FACE DIRECTION POSITION NOSE FORWARD TILTING;Mn;0;NSM;;;;;N;;;;; 1DA08;SIGNWRITING FACE DIRECTION POSITION NOSE UP OR DOWN;Mn;0;NSM;;;;;N;;;;; 1DA09;SIGNWRITING FACE DIRECTION POSITION NOSE UP OR DOWN TILTING;Mn;0;NSM;;;;;N;;;;; 1DA0A;SIGNWRITING EYEBROWS STRAIGHT UP;Mn;0;NSM;;;;;N;;;;; 1DA0B;SIGNWRITING EYEBROWS STRAIGHT NEUTRAL;Mn;0;NSM;;;;;N;;;;; 1DA0C;SIGNWRITING EYEBROWS STRAIGHT DOWN;Mn;0;NSM;;;;;N;;;;; 1DA0D;SIGNWRITING DREAMY EYEBROWS NEUTRAL DOWN;Mn;0;NSM;;;;;N;;;;; 1DA0E;SIGNWRITING DREAMY EYEBROWS DOWN NEUTRAL;Mn;0;NSM;;;;;N;;;;; 1DA0F;SIGNWRITING DREAMY EYEBROWS UP NEUTRAL;Mn;0;NSM;;;;;N;;;;; 1DA10;SIGNWRITING DREAMY EYEBROWS NEUTRAL UP;Mn;0;NSM;;;;;N;;;;; 1DA11;SIGNWRITING FOREHEAD NEUTRAL;Mn;0;NSM;;;;;N;;;;; 1DA12;SIGNWRITING FOREHEAD CONTACT;Mn;0;NSM;;;;;N;;;;; 1DA13;SIGNWRITING FOREHEAD WRINKLED;Mn;0;NSM;;;;;N;;;;; 1DA14;SIGNWRITING EYES OPEN;Mn;0;NSM;;;;;N;;;;; 1DA15;SIGNWRITING EYES SQUEEZED;Mn;0;NSM;;;;;N;;;;; 1DA16;SIGNWRITING EYES CLOSED;Mn;0;NSM;;;;;N;;;;; 1DA17;SIGNWRITING EYE BLINK SINGLE;Mn;0;NSM;;;;;N;;;;; 1DA18;SIGNWRITING EYE BLINK MULTIPLE;Mn;0;NSM;;;;;N;;;;; 1DA19;SIGNWRITING EYES HALF OPEN;Mn;0;NSM;;;;;N;;;;; 1DA1A;SIGNWRITING EYES WIDE OPEN;Mn;0;NSM;;;;;N;;;;; 1DA1B;SIGNWRITING EYES HALF CLOSED;Mn;0;NSM;;;;;N;;;;; 1DA1C;SIGNWRITING EYES WIDENING MOVEMENT;Mn;0;NSM;;;;;N;;;;; 1DA1D;SIGNWRITING EYE WINK;Mn;0;NSM;;;;;N;;;;; 1DA1E;SIGNWRITING EYELASHES UP;Mn;0;NSM;;;;;N;;;;; 1DA1F;SIGNWRITING EYELASHES DOWN;Mn;0;NSM;;;;;N;;;;; 1DA20;SIGNWRITING EYELASHES FLUTTERING;Mn;0;NSM;;;;;N;;;;; 1DA21;SIGNWRITING EYEGAZE-WALLPLANE STRAIGHT;Mn;0;NSM;;;;;N;;;;; 1DA22;SIGNWRITING EYEGAZE-WALLPLANE STRAIGHT DOUBLE;Mn;0;NSM;;;;;N;;;;; 1DA23;SIGNWRITING EYEGAZE-WALLPLANE STRAIGHT ALTERNATING;Mn;0;NSM;;;;;N;;;;; 1DA24;SIGNWRITING EYEGAZE-FLOORPLANE STRAIGHT;Mn;0;NSM;;;;;N;;;;; 1DA25;SIGNWRITING EYEGAZE-FLOORPLANE STRAIGHT DOUBLE;Mn;0;NSM;;;;;N;;;;; 1DA26;SIGNWRITING EYEGAZE-FLOORPLANE STRAIGHT ALTERNATING;Mn;0;NSM;;;;;N;;;;; 1DA27;SIGNWRITING EYEGAZE-WALLPLANE CURVED;Mn;0;NSM;;;;;N;;;;; 1DA28;SIGNWRITING EYEGAZE-FLOORPLANE CURVED;Mn;0;NSM;;;;;N;;;;; 1DA29;SIGNWRITING EYEGAZE-WALLPLANE CIRCLING;Mn;0;NSM;;;;;N;;;;; 1DA2A;SIGNWRITING CHEEKS PUFFED;Mn;0;NSM;;;;;N;;;;; 1DA2B;SIGNWRITING CHEEKS NEUTRAL;Mn;0;NSM;;;;;N;;;;; 1DA2C;SIGNWRITING CHEEKS SUCKED;Mn;0;NSM;;;;;N;;;;; 1DA2D;SIGNWRITING TENSE CHEEKS HIGH;Mn;0;NSM;;;;;N;;;;; 1DA2E;SIGNWRITING TENSE CHEEKS MIDDLE;Mn;0;NSM;;;;;N;;;;; 1DA2F;SIGNWRITING TENSE CHEEKS LOW;Mn;0;NSM;;;;;N;;;;; 1DA30;SIGNWRITING EARS;Mn;0;NSM;;;;;N;;;;; 1DA31;SIGNWRITING NOSE NEUTRAL;Mn;0;NSM;;;;;N;;;;; 1DA32;SIGNWRITING NOSE CONTACT;Mn;0;NSM;;;;;N;;;;; 1DA33;SIGNWRITING NOSE WRINKLES;Mn;0;NSM;;;;;N;;;;; 1DA34;SIGNWRITING NOSE WIGGLES;Mn;0;NSM;;;;;N;;;;; 1DA35;SIGNWRITING AIR BLOWING OUT;Mn;0;NSM;;;;;N;;;;; 1DA36;SIGNWRITING AIR SUCKING IN;Mn;0;NSM;;;;;N;;;;; 1DA37;SIGNWRITING AIR BLOW SMALL ROTATIONS;So;0;L;;;;;N;;;;; 1DA38;SIGNWRITING AIR SUCK SMALL ROTATIONS;So;0;L;;;;;N;;;;; 1DA39;SIGNWRITING BREATH INHALE;So;0;L;;;;;N;;;;; 1DA3A;SIGNWRITING BREATH EXHALE;So;0;L;;;;;N;;;;; 1DA3B;SIGNWRITING MOUTH CLOSED NEUTRAL;Mn;0;NSM;;;;;N;;;;; 1DA3C;SIGNWRITING MOUTH CLOSED FORWARD;Mn;0;NSM;;;;;N;;;;; 1DA3D;SIGNWRITING MOUTH CLOSED CONTACT;Mn;0;NSM;;;;;N;;;;; 1DA3E;SIGNWRITING MOUTH SMILE;Mn;0;NSM;;;;;N;;;;; 1DA3F;SIGNWRITING MOUTH SMILE WRINKLED;Mn;0;NSM;;;;;N;;;;; 1DA40;SIGNWRITING MOUTH SMILE OPEN;Mn;0;NSM;;;;;N;;;;; 1DA41;SIGNWRITING MOUTH FROWN;Mn;0;NSM;;;;;N;;;;; 1DA42;SIGNWRITING MOUTH FROWN WRINKLED;Mn;0;NSM;;;;;N;;;;; 1DA43;SIGNWRITING MOUTH FROWN OPEN;Mn;0;NSM;;;;;N;;;;; 1DA44;SIGNWRITING MOUTH OPEN CIRCLE;Mn;0;NSM;;;;;N;;;;; 1DA45;SIGNWRITING MOUTH OPEN FORWARD;Mn;0;NSM;;;;;N;;;;; 1DA46;SIGNWRITING MOUTH OPEN WRINKLED;Mn;0;NSM;;;;;N;;;;; 1DA47;SIGNWRITING MOUTH OPEN OVAL;Mn;0;NSM;;;;;N;;;;; 1DA48;SIGNWRITING MOUTH OPEN OVAL WRINKLED;Mn;0;NSM;;;;;N;;;;; 1DA49;SIGNWRITING MOUTH OPEN OVAL YAWN;Mn;0;NSM;;;;;N;;;;; 1DA4A;SIGNWRITING MOUTH OPEN RECTANGLE;Mn;0;NSM;;;;;N;;;;; 1DA4B;SIGNWRITING MOUTH OPEN RECTANGLE WRINKLED;Mn;0;NSM;;;;;N;;;;; 1DA4C;SIGNWRITING MOUTH OPEN RECTANGLE YAWN;Mn;0;NSM;;;;;N;;;;; 1DA4D;SIGNWRITING MOUTH KISS;Mn;0;NSM;;;;;N;;;;; 1DA4E;SIGNWRITING MOUTH KISS FORWARD;Mn;0;NSM;;;;;N;;;;; 1DA4F;SIGNWRITING MOUTH KISS WRINKLED;Mn;0;NSM;;;;;N;;;;; 1DA50;SIGNWRITING MOUTH TENSE;Mn;0;NSM;;;;;N;;;;; 1DA51;SIGNWRITING MOUTH TENSE FORWARD;Mn;0;NSM;;;;;N;;;;; 1DA52;SIGNWRITING MOUTH TENSE SUCKED;Mn;0;NSM;;;;;N;;;;; 1DA53;SIGNWRITING LIPS PRESSED TOGETHER;Mn;0;NSM;;;;;N;;;;; 1DA54;SIGNWRITING LIP LOWER OVER UPPER;Mn;0;NSM;;;;;N;;;;; 1DA55;SIGNWRITING LIP UPPER OVER LOWER;Mn;0;NSM;;;;;N;;;;; 1DA56;SIGNWRITING MOUTH CORNERS;Mn;0;NSM;;;;;N;;;;; 1DA57;SIGNWRITING MOUTH WRINKLES SINGLE;Mn;0;NSM;;;;;N;;;;; 1DA58;SIGNWRITING MOUTH WRINKLES DOUBLE;Mn;0;NSM;;;;;N;;;;; 1DA59;SIGNWRITING TONGUE STICKING OUT FAR;Mn;0;NSM;;;;;N;;;;; 1DA5A;SIGNWRITING TONGUE LICKING LIPS;Mn;0;NSM;;;;;N;;;;; 1DA5B;SIGNWRITING TONGUE TIP BETWEEN LIPS;Mn;0;NSM;;;;;N;;;;; 1DA5C;SIGNWRITING TONGUE TIP TOUCHING INSIDE MOUTH;Mn;0;NSM;;;;;N;;;;; 1DA5D;SIGNWRITING TONGUE INSIDE MOUTH RELAXED;Mn;0;NSM;;;;;N;;;;; 1DA5E;SIGNWRITING TONGUE MOVES AGAINST CHEEK;Mn;0;NSM;;;;;N;;;;; 1DA5F;SIGNWRITING TONGUE CENTRE STICKING OUT;Mn;0;NSM;;;;;N;;;;; 1DA60;SIGNWRITING TONGUE CENTRE INSIDE MOUTH;Mn;0;NSM;;;;;N;;;;; 1DA61;SIGNWRITING TEETH;Mn;0;NSM;;;;;N;;;;; 1DA62;SIGNWRITING TEETH MOVEMENT;Mn;0;NSM;;;;;N;;;;; 1DA63;SIGNWRITING TEETH ON TONGUE;Mn;0;NSM;;;;;N;;;;; 1DA64;SIGNWRITING TEETH ON TONGUE MOVEMENT;Mn;0;NSM;;;;;N;;;;; 1DA65;SIGNWRITING TEETH ON LIPS;Mn;0;NSM;;;;;N;;;;; 1DA66;SIGNWRITING TEETH ON LIPS MOVEMENT;Mn;0;NSM;;;;;N;;;;; 1DA67;SIGNWRITING TEETH BITE LIPS;Mn;0;NSM;;;;;N;;;;; 1DA68;SIGNWRITING MOVEMENT-WALLPLANE JAW;Mn;0;NSM;;;;;N;;;;; 1DA69;SIGNWRITING MOVEMENT-FLOORPLANE JAW;Mn;0;NSM;;;;;N;;;;; 1DA6A;SIGNWRITING NECK;Mn;0;NSM;;;;;N;;;;; 1DA6B;SIGNWRITING HAIR;Mn;0;NSM;;;;;N;;;;; 1DA6C;SIGNWRITING EXCITEMENT;Mn;0;NSM;;;;;N;;;;; 1DA6D;SIGNWRITING SHOULDER HIP SPINE;So;0;L;;;;;N;;;;; 1DA6E;SIGNWRITING SHOULDER HIP POSITIONS;So;0;L;;;;;N;;;;; 1DA6F;SIGNWRITING WALLPLANE SHOULDER HIP MOVE;So;0;L;;;;;N;;;;; 1DA70;SIGNWRITING FLOORPLANE SHOULDER HIP MOVE;So;0;L;;;;;N;;;;; 1DA71;SIGNWRITING SHOULDER TILTING FROM WAIST;So;0;L;;;;;N;;;;; 1DA72;SIGNWRITING TORSO-WALLPLANE STRAIGHT STRETCH;So;0;L;;;;;N;;;;; 1DA73;SIGNWRITING TORSO-WALLPLANE CURVED BEND;So;0;L;;;;;N;;;;; 1DA74;SIGNWRITING TORSO-FLOORPLANE TWISTING;So;0;L;;;;;N;;;;; 1DA75;SIGNWRITING UPPER BODY TILTING FROM HIP JOINTS;Mn;0;NSM;;;;;N;;;;; 1DA76;SIGNWRITING LIMB COMBINATION;So;0;L;;;;;N;;;;; 1DA77;SIGNWRITING LIMB LENGTH-1;So;0;L;;;;;N;;;;; 1DA78;SIGNWRITING LIMB LENGTH-2;So;0;L;;;;;N;;;;; 1DA79;SIGNWRITING LIMB LENGTH-3;So;0;L;;;;;N;;;;; 1DA7A;SIGNWRITING LIMB LENGTH-4;So;0;L;;;;;N;;;;; 1DA7B;SIGNWRITING LIMB LENGTH-5;So;0;L;;;;;N;;;;; 1DA7C;SIGNWRITING LIMB LENGTH-6;So;0;L;;;;;N;;;;; 1DA7D;SIGNWRITING LIMB LENGTH-7;So;0;L;;;;;N;;;;; 1DA7E;SIGNWRITING FINGER;So;0;L;;;;;N;;;;; 1DA7F;SIGNWRITING LOCATION-WALLPLANE SPACE;So;0;L;;;;;N;;;;; 1DA80;SIGNWRITING LOCATION-FLOORPLANE SPACE;So;0;L;;;;;N;;;;; 1DA81;SIGNWRITING LOCATION HEIGHT;So;0;L;;;;;N;;;;; 1DA82;SIGNWRITING LOCATION WIDTH;So;0;L;;;;;N;;;;; 1DA83;SIGNWRITING LOCATION DEPTH;So;0;L;;;;;N;;;;; 1DA84;SIGNWRITING LOCATION HEAD NECK;Mn;0;NSM;;;;;N;;;;; 1DA85;SIGNWRITING LOCATION TORSO;So;0;L;;;;;N;;;;; 1DA86;SIGNWRITING LOCATION LIMBS DIGITS;So;0;L;;;;;N;;;;; 1DA87;SIGNWRITING COMMA;Po;0;L;;;;;N;;;;; 1DA88;SIGNWRITING FULL STOP;Po;0;L;;;;;N;;;;; 1DA89;SIGNWRITING SEMICOLON;Po;0;L;;;;;N;;;;; 1DA8A;SIGNWRITING COLON;Po;0;L;;;;;N;;;;; 1DA8B;SIGNWRITING PARENTHESIS;Po;0;L;;;;;N;;;;; 1DA9B;SIGNWRITING FILL MODIFIER-2;Mn;0;NSM;;;;;N;;;;; 1DA9C;SIGNWRITING FILL MODIFIER-3;Mn;0;NSM;;;;;N;;;;; 1DA9D;SIGNWRITING FILL MODIFIER-4;Mn;0;NSM;;;;;N;;;;; 1DA9E;SIGNWRITING FILL MODIFIER-5;Mn;0;NSM;;;;;N;;;;; 1DA9F;SIGNWRITING FILL MODIFIER-6;Mn;0;NSM;;;;;N;;;;; 1DAA1;SIGNWRITING ROTATION MODIFIER-2;Mn;0;NSM;;;;;N;;;;; 1DAA2;SIGNWRITING ROTATION MODIFIER-3;Mn;0;NSM;;;;;N;;;;; 1DAA3;SIGNWRITING ROTATION MODIFIER-4;Mn;0;NSM;;;;;N;;;;; 1DAA4;SIGNWRITING ROTATION MODIFIER-5;Mn;0;NSM;;;;;N;;;;; 1DAA5;SIGNWRITING ROTATION MODIFIER-6;Mn;0;NSM;;;;;N;;;;; 1DAA6;SIGNWRITING ROTATION MODIFIER-7;Mn;0;NSM;;;;;N;;;;; 1DAA7;SIGNWRITING ROTATION MODIFIER-8;Mn;0;NSM;;;;;N;;;;; 1DAA8;SIGNWRITING ROTATION MODIFIER-9;Mn;0;NSM;;;;;N;;;;; 1DAA9;SIGNWRITING ROTATION MODIFIER-10;Mn;0;NSM;;;;;N;;;;; 1DAAA;SIGNWRITING ROTATION MODIFIER-11;Mn;0;NSM;;;;;N;;;;; 1DAAB;SIGNWRITING ROTATION MODIFIER-12;Mn;0;NSM;;;;;N;;;;; 1DAAC;SIGNWRITING ROTATION MODIFIER-13;Mn;0;NSM;;;;;N;;;;; 1DAAD;SIGNWRITING ROTATION MODIFIER-14;Mn;0;NSM;;;;;N;;;;; 1DAAE;SIGNWRITING ROTATION MODIFIER-15;Mn;0;NSM;;;;;N;;;;; 1DAAF;SIGNWRITING ROTATION MODIFIER-16;Mn;0;NSM;;;;;N;;;;; 1E000;COMBINING GLAGOLITIC LETTER AZU;Mn;230;NSM;;;;;N;;;;; 1E001;COMBINING GLAGOLITIC LETTER BUKY;Mn;230;NSM;;;;;N;;;;; 1E002;COMBINING GLAGOLITIC LETTER VEDE;Mn;230;NSM;;;;;N;;;;; 1E003;COMBINING GLAGOLITIC LETTER GLAGOLI;Mn;230;NSM;;;;;N;;;;; 1E004;COMBINING GLAGOLITIC LETTER DOBRO;Mn;230;NSM;;;;;N;;;;; 1E005;COMBINING GLAGOLITIC LETTER YESTU;Mn;230;NSM;;;;;N;;;;; 1E006;COMBINING GLAGOLITIC LETTER ZHIVETE;Mn;230;NSM;;;;;N;;;;; 1E008;COMBINING GLAGOLITIC LETTER ZEMLJA;Mn;230;NSM;;;;;N;;;;; 1E009;COMBINING GLAGOLITIC LETTER IZHE;Mn;230;NSM;;;;;N;;;;; 1E00A;COMBINING GLAGOLITIC LETTER INITIAL IZHE;Mn;230;NSM;;;;;N;;;;; 1E00B;COMBINING GLAGOLITIC LETTER I;Mn;230;NSM;;;;;N;;;;; 1E00C;COMBINING GLAGOLITIC LETTER DJERVI;Mn;230;NSM;;;;;N;;;;; 1E00D;COMBINING GLAGOLITIC LETTER KAKO;Mn;230;NSM;;;;;N;;;;; 1E00E;COMBINING GLAGOLITIC LETTER LJUDIJE;Mn;230;NSM;;;;;N;;;;; 1E00F;COMBINING GLAGOLITIC LETTER MYSLITE;Mn;230;NSM;;;;;N;;;;; 1E010;COMBINING GLAGOLITIC LETTER NASHI;Mn;230;NSM;;;;;N;;;;; 1E011;COMBINING GLAGOLITIC LETTER ONU;Mn;230;NSM;;;;;N;;;;; 1E012;COMBINING GLAGOLITIC LETTER POKOJI;Mn;230;NSM;;;;;N;;;;; 1E013;COMBINING GLAGOLITIC LETTER RITSI;Mn;230;NSM;;;;;N;;;;; 1E014;COMBINING GLAGOLITIC LETTER SLOVO;Mn;230;NSM;;;;;N;;;;; 1E015;COMBINING GLAGOLITIC LETTER TVRIDO;Mn;230;NSM;;;;;N;;;;; 1E016;COMBINING GLAGOLITIC LETTER UKU;Mn;230;NSM;;;;;N;;;;; 1E017;COMBINING GLAGOLITIC LETTER FRITU;Mn;230;NSM;;;;;N;;;;; 1E018;COMBINING GLAGOLITIC LETTER HERU;Mn;230;NSM;;;;;N;;;;; 1E01B;COMBINING GLAGOLITIC LETTER SHTA;Mn;230;NSM;;;;;N;;;;; 1E01C;COMBINING GLAGOLITIC LETTER TSI;Mn;230;NSM;;;;;N;;;;; 1E01D;COMBINING GLAGOLITIC LETTER CHRIVI;Mn;230;NSM;;;;;N;;;;; 1E01E;COMBINING GLAGOLITIC LETTER SHA;Mn;230;NSM;;;;;N;;;;; 1E01F;COMBINING GLAGOLITIC LETTER YERU;Mn;230;NSM;;;;;N;;;;; 1E020;COMBINING GLAGOLITIC LETTER YERI;Mn;230;NSM;;;;;N;;;;; 1E021;COMBINING GLAGOLITIC LETTER YATI;Mn;230;NSM;;;;;N;;;;; 1E023;COMBINING GLAGOLITIC LETTER YU;Mn;230;NSM;;;;;N;;;;; 1E024;COMBINING GLAGOLITIC LETTER SMALL YUS;Mn;230;NSM;;;;;N;;;;; 1E026;COMBINING GLAGOLITIC LETTER YO;Mn;230;NSM;;;;;N;;;;; 1E027;COMBINING GLAGOLITIC LETTER IOTATED SMALL YUS;Mn;230;NSM;;;;;N;;;;; 1E028;COMBINING GLAGOLITIC LETTER BIG YUS;Mn;230;NSM;;;;;N;;;;; 1E029;COMBINING GLAGOLITIC LETTER IOTATED BIG YUS;Mn;230;NSM;;;;;N;;;;; 1E02A;COMBINING GLAGOLITIC LETTER FITA;Mn;230;NSM;;;;;N;;;;; 1E800;MENDE KIKAKUI SYLLABLE M001 KI;Lo;0;R;;;;;N;;;;; 1E801;MENDE KIKAKUI SYLLABLE M002 KA;Lo;0;R;;;;;N;;;;; 1E802;MENDE KIKAKUI SYLLABLE M003 KU;Lo;0;R;;;;;N;;;;; 1E803;MENDE KIKAKUI SYLLABLE M065 KEE;Lo;0;R;;;;;N;;;;; 1E804;MENDE KIKAKUI SYLLABLE M095 KE;Lo;0;R;;;;;N;;;;; 1E805;MENDE KIKAKUI SYLLABLE M076 KOO;Lo;0;R;;;;;N;;;;; 1E806;MENDE KIKAKUI SYLLABLE M048 KO;Lo;0;R;;;;;N;;;;; 1E807;MENDE KIKAKUI SYLLABLE M179 KUA;Lo;0;R;;;;;N;;;;; 1E808;MENDE KIKAKUI SYLLABLE M004 WI;Lo;0;R;;;;;N;;;;; 1E809;MENDE KIKAKUI SYLLABLE M005 WA;Lo;0;R;;;;;N;;;;; 1E80A;MENDE KIKAKUI SYLLABLE M006 WU;Lo;0;R;;;;;N;;;;; 1E80B;MENDE KIKAKUI SYLLABLE M126 WEE;Lo;0;R;;;;;N;;;;; 1E80C;MENDE KIKAKUI SYLLABLE M118 WE;Lo;0;R;;;;;N;;;;; 1E80D;MENDE KIKAKUI SYLLABLE M114 WOO;Lo;0;R;;;;;N;;;;; 1E80E;MENDE KIKAKUI SYLLABLE M045 WO;Lo;0;R;;;;;N;;;;; 1E80F;MENDE KIKAKUI SYLLABLE M194 WUI;Lo;0;R;;;;;N;;;;; 1E810;MENDE KIKAKUI SYLLABLE M143 WEI;Lo;0;R;;;;;N;;;;; 1E811;MENDE KIKAKUI SYLLABLE M061 WVI;Lo;0;R;;;;;N;;;;; 1E812;MENDE KIKAKUI SYLLABLE M049 WVA;Lo;0;R;;;;;N;;;;; 1E813;MENDE KIKAKUI SYLLABLE M139 WVE;Lo;0;R;;;;;N;;;;; 1E814;MENDE KIKAKUI SYLLABLE M007 MIN;Lo;0;R;;;;;N;;;;; 1E815;MENDE KIKAKUI SYLLABLE M008 MAN;Lo;0;R;;;;;N;;;;; 1E816;MENDE KIKAKUI SYLLABLE M009 MUN;Lo;0;R;;;;;N;;;;; 1E817;MENDE KIKAKUI SYLLABLE M059 MEN;Lo;0;R;;;;;N;;;;; 1E818;MENDE KIKAKUI SYLLABLE M094 MON;Lo;0;R;;;;;N;;;;; 1E819;MENDE KIKAKUI SYLLABLE M154 MUAN;Lo;0;R;;;;;N;;;;; 1E81A;MENDE KIKAKUI SYLLABLE M189 MUEN;Lo;0;R;;;;;N;;;;; 1E81B;MENDE KIKAKUI SYLLABLE M010 BI;Lo;0;R;;;;;N;;;;; 1E81C;MENDE KIKAKUI SYLLABLE M011 BA;Lo;0;R;;;;;N;;;;; 1E81D;MENDE KIKAKUI SYLLABLE M012 BU;Lo;0;R;;;;;N;;;;; 1E81E;MENDE KIKAKUI SYLLABLE M150 BEE;Lo;0;R;;;;;N;;;;; 1E81F;MENDE KIKAKUI SYLLABLE M097 BE;Lo;0;R;;;;;N;;;;; 1E820;MENDE KIKAKUI SYLLABLE M103 BOO;Lo;0;R;;;;;N;;;;; 1E821;MENDE KIKAKUI SYLLABLE M138 BO;Lo;0;R;;;;;N;;;;; 1E822;MENDE KIKAKUI SYLLABLE M013 I;Lo;0;R;;;;;N;;;;; 1E823;MENDE KIKAKUI SYLLABLE M014 A;Lo;0;R;;;;;N;;;;; 1E824;MENDE KIKAKUI SYLLABLE M015 U;Lo;0;R;;;;;N;;;;; 1E825;MENDE KIKAKUI SYLLABLE M163 EE;Lo;0;R;;;;;N;;;;; 1E826;MENDE KIKAKUI SYLLABLE M100 E;Lo;0;R;;;;;N;;;;; 1E827;MENDE KIKAKUI SYLLABLE M165 OO;Lo;0;R;;;;;N;;;;; 1E828;MENDE KIKAKUI SYLLABLE M147 O;Lo;0;R;;;;;N;;;;; 1E829;MENDE KIKAKUI SYLLABLE M137 EI;Lo;0;R;;;;;N;;;;; 1E82A;MENDE KIKAKUI SYLLABLE M131 IN;Lo;0;R;;;;;N;;;;; 1E82B;MENDE KIKAKUI SYLLABLE M135 IN;Lo;0;R;;;;;N;;;;; 1E82C;MENDE KIKAKUI SYLLABLE M195 AN;Lo;0;R;;;;;N;;;;; 1E82D;MENDE KIKAKUI SYLLABLE M178 EN;Lo;0;R;;;;;N;;;;; 1E82E;MENDE KIKAKUI SYLLABLE M019 SI;Lo;0;R;;;;;N;;;;; 1E82F;MENDE KIKAKUI SYLLABLE M020 SA;Lo;0;R;;;;;N;;;;; 1E830;MENDE KIKAKUI SYLLABLE M021 SU;Lo;0;R;;;;;N;;;;; 1E831;MENDE KIKAKUI SYLLABLE M162 SEE;Lo;0;R;;;;;N;;;;; 1E832;MENDE KIKAKUI SYLLABLE M116 SE;Lo;0;R;;;;;N;;;;; 1E833;MENDE KIKAKUI SYLLABLE M136 SOO;Lo;0;R;;;;;N;;;;; 1E834;MENDE KIKAKUI SYLLABLE M079 SO;Lo;0;R;;;;;N;;;;; 1E835;MENDE KIKAKUI SYLLABLE M196 SIA;Lo;0;R;;;;;N;;;;; 1E836;MENDE KIKAKUI SYLLABLE M025 LI;Lo;0;R;;;;;N;;;;; 1E837;MENDE KIKAKUI SYLLABLE M026 LA;Lo;0;R;;;;;N;;;;; 1E838;MENDE KIKAKUI SYLLABLE M027 LU;Lo;0;R;;;;;N;;;;; 1E839;MENDE KIKAKUI SYLLABLE M084 LEE;Lo;0;R;;;;;N;;;;; 1E83A;MENDE KIKAKUI SYLLABLE M073 LE;Lo;0;R;;;;;N;;;;; 1E83B;MENDE KIKAKUI SYLLABLE M054 LOO;Lo;0;R;;;;;N;;;;; 1E83C;MENDE KIKAKUI SYLLABLE M153 LO;Lo;0;R;;;;;N;;;;; 1E83D;MENDE KIKAKUI SYLLABLE M110 LONG LE;Lo;0;R;;;;;N;;;;; 1E83E;MENDE KIKAKUI SYLLABLE M016 DI;Lo;0;R;;;;;N;;;;; 1E83F;MENDE KIKAKUI SYLLABLE M017 DA;Lo;0;R;;;;;N;;;;; 1E840;MENDE KIKAKUI SYLLABLE M018 DU;Lo;0;R;;;;;N;;;;; 1E841;MENDE KIKAKUI SYLLABLE M089 DEE;Lo;0;R;;;;;N;;;;; 1E842;MENDE KIKAKUI SYLLABLE M180 DOO;Lo;0;R;;;;;N;;;;; 1E843;MENDE KIKAKUI SYLLABLE M181 DO;Lo;0;R;;;;;N;;;;; 1E844;MENDE KIKAKUI SYLLABLE M022 TI;Lo;0;R;;;;;N;;;;; 1E845;MENDE KIKAKUI SYLLABLE M023 TA;Lo;0;R;;;;;N;;;;; 1E846;MENDE KIKAKUI SYLLABLE M024 TU;Lo;0;R;;;;;N;;;;; 1E847;MENDE KIKAKUI SYLLABLE M091 TEE;Lo;0;R;;;;;N;;;;; 1E848;MENDE KIKAKUI SYLLABLE M055 TE;Lo;0;R;;;;;N;;;;; 1E849;MENDE KIKAKUI SYLLABLE M104 TOO;Lo;0;R;;;;;N;;;;; 1E84A;MENDE KIKAKUI SYLLABLE M069 TO;Lo;0;R;;;;;N;;;;; 1E84B;MENDE KIKAKUI SYLLABLE M028 JI;Lo;0;R;;;;;N;;;;; 1E84C;MENDE KIKAKUI SYLLABLE M029 JA;Lo;0;R;;;;;N;;;;; 1E84D;MENDE KIKAKUI SYLLABLE M030 JU;Lo;0;R;;;;;N;;;;; 1E84E;MENDE KIKAKUI SYLLABLE M157 JEE;Lo;0;R;;;;;N;;;;; 1E84F;MENDE KIKAKUI SYLLABLE M113 JE;Lo;0;R;;;;;N;;;;; 1E850;MENDE KIKAKUI SYLLABLE M160 JOO;Lo;0;R;;;;;N;;;;; 1E851;MENDE KIKAKUI SYLLABLE M063 JO;Lo;0;R;;;;;N;;;;; 1E852;MENDE KIKAKUI SYLLABLE M175 LONG JO;Lo;0;R;;;;;N;;;;; 1E853;MENDE KIKAKUI SYLLABLE M031 YI;Lo;0;R;;;;;N;;;;; 1E854;MENDE KIKAKUI SYLLABLE M032 YA;Lo;0;R;;;;;N;;;;; 1E855;MENDE KIKAKUI SYLLABLE M033 YU;Lo;0;R;;;;;N;;;;; 1E856;MENDE KIKAKUI SYLLABLE M109 YEE;Lo;0;R;;;;;N;;;;; 1E857;MENDE KIKAKUI SYLLABLE M080 YE;Lo;0;R;;;;;N;;;;; 1E858;MENDE KIKAKUI SYLLABLE M141 YOO;Lo;0;R;;;;;N;;;;; 1E859;MENDE KIKAKUI SYLLABLE M121 YO;Lo;0;R;;;;;N;;;;; 1E85A;MENDE KIKAKUI SYLLABLE M034 FI;Lo;0;R;;;;;N;;;;; 1E85B;MENDE KIKAKUI SYLLABLE M035 FA;Lo;0;R;;;;;N;;;;; 1E85C;MENDE KIKAKUI SYLLABLE M036 FU;Lo;0;R;;;;;N;;;;; 1E85D;MENDE KIKAKUI SYLLABLE M078 FEE;Lo;0;R;;;;;N;;;;; 1E85E;MENDE KIKAKUI SYLLABLE M075 FE;Lo;0;R;;;;;N;;;;; 1E85F;MENDE KIKAKUI SYLLABLE M133 FOO;Lo;0;R;;;;;N;;;;; 1E860;MENDE KIKAKUI SYLLABLE M088 FO;Lo;0;R;;;;;N;;;;; 1E861;MENDE KIKAKUI SYLLABLE M197 FUA;Lo;0;R;;;;;N;;;;; 1E862;MENDE KIKAKUI SYLLABLE M101 FAN;Lo;0;R;;;;;N;;;;; 1E863;MENDE KIKAKUI SYLLABLE M037 NIN;Lo;0;R;;;;;N;;;;; 1E864;MENDE KIKAKUI SYLLABLE M038 NAN;Lo;0;R;;;;;N;;;;; 1E865;MENDE KIKAKUI SYLLABLE M039 NUN;Lo;0;R;;;;;N;;;;; 1E866;MENDE KIKAKUI SYLLABLE M117 NEN;Lo;0;R;;;;;N;;;;; 1E867;MENDE KIKAKUI SYLLABLE M169 NON;Lo;0;R;;;;;N;;;;; 1E868;MENDE KIKAKUI SYLLABLE M176 HI;Lo;0;R;;;;;N;;;;; 1E869;MENDE KIKAKUI SYLLABLE M041 HA;Lo;0;R;;;;;N;;;;; 1E86A;MENDE KIKAKUI SYLLABLE M186 HU;Lo;0;R;;;;;N;;;;; 1E86B;MENDE KIKAKUI SYLLABLE M040 HEE;Lo;0;R;;;;;N;;;;; 1E86C;MENDE KIKAKUI SYLLABLE M096 HE;Lo;0;R;;;;;N;;;;; 1E86D;MENDE KIKAKUI SYLLABLE M042 HOO;Lo;0;R;;;;;N;;;;; 1E86E;MENDE KIKAKUI SYLLABLE M140 HO;Lo;0;R;;;;;N;;;;; 1E86F;MENDE KIKAKUI SYLLABLE M083 HEEI;Lo;0;R;;;;;N;;;;; 1E870;MENDE KIKAKUI SYLLABLE M128 HOOU;Lo;0;R;;;;;N;;;;; 1E871;MENDE KIKAKUI SYLLABLE M053 HIN;Lo;0;R;;;;;N;;;;; 1E872;MENDE KIKAKUI SYLLABLE M130 HAN;Lo;0;R;;;;;N;;;;; 1E873;MENDE KIKAKUI SYLLABLE M087 HUN;Lo;0;R;;;;;N;;;;; 1E874;MENDE KIKAKUI SYLLABLE M052 HEN;Lo;0;R;;;;;N;;;;; 1E875;MENDE KIKAKUI SYLLABLE M193 HON;Lo;0;R;;;;;N;;;;; 1E876;MENDE KIKAKUI SYLLABLE M046 HUAN;Lo;0;R;;;;;N;;;;; 1E877;MENDE KIKAKUI SYLLABLE M090 NGGI;Lo;0;R;;;;;N;;;;; 1E878;MENDE KIKAKUI SYLLABLE M043 NGGA;Lo;0;R;;;;;N;;;;; 1E879;MENDE KIKAKUI SYLLABLE M082 NGGU;Lo;0;R;;;;;N;;;;; 1E87A;MENDE KIKAKUI SYLLABLE M115 NGGEE;Lo;0;R;;;;;N;;;;; 1E87B;MENDE KIKAKUI SYLLABLE M146 NGGE;Lo;0;R;;;;;N;;;;; 1E87C;MENDE KIKAKUI SYLLABLE M156 NGGOO;Lo;0;R;;;;;N;;;;; 1E87D;MENDE KIKAKUI SYLLABLE M120 NGGO;Lo;0;R;;;;;N;;;;; 1E87E;MENDE KIKAKUI SYLLABLE M159 NGGAA;Lo;0;R;;;;;N;;;;; 1E87F;MENDE KIKAKUI SYLLABLE M127 NGGUA;Lo;0;R;;;;;N;;;;; 1E880;MENDE KIKAKUI SYLLABLE M086 LONG NGGE;Lo;0;R;;;;;N;;;;; 1E881;MENDE KIKAKUI SYLLABLE M106 LONG NGGOO;Lo;0;R;;;;;N;;;;; 1E882;MENDE KIKAKUI SYLLABLE M183 LONG NGGO;Lo;0;R;;;;;N;;;;; 1E883;MENDE KIKAKUI SYLLABLE M155 GI;Lo;0;R;;;;;N;;;;; 1E884;MENDE KIKAKUI SYLLABLE M111 GA;Lo;0;R;;;;;N;;;;; 1E885;MENDE KIKAKUI SYLLABLE M168 GU;Lo;0;R;;;;;N;;;;; 1E886;MENDE KIKAKUI SYLLABLE M190 GEE;Lo;0;R;;;;;N;;;;; 1E887;MENDE KIKAKUI SYLLABLE M166 GUEI;Lo;0;R;;;;;N;;;;; 1E888;MENDE KIKAKUI SYLLABLE M167 GUAN;Lo;0;R;;;;;N;;;;; 1E889;MENDE KIKAKUI SYLLABLE M184 NGEN;Lo;0;R;;;;;N;;;;; 1E88A;MENDE KIKAKUI SYLLABLE M057 NGON;Lo;0;R;;;;;N;;;;; 1E88B;MENDE KIKAKUI SYLLABLE M177 NGUAN;Lo;0;R;;;;;N;;;;; 1E88C;MENDE KIKAKUI SYLLABLE M068 PI;Lo;0;R;;;;;N;;;;; 1E88D;MENDE KIKAKUI SYLLABLE M099 PA;Lo;0;R;;;;;N;;;;; 1E88E;MENDE KIKAKUI SYLLABLE M050 PU;Lo;0;R;;;;;N;;;;; 1E88F;MENDE KIKAKUI SYLLABLE M081 PEE;Lo;0;R;;;;;N;;;;; 1E890;MENDE KIKAKUI SYLLABLE M051 PE;Lo;0;R;;;;;N;;;;; 1E891;MENDE KIKAKUI SYLLABLE M102 POO;Lo;0;R;;;;;N;;;;; 1E892;MENDE KIKAKUI SYLLABLE M066 PO;Lo;0;R;;;;;N;;;;; 1E893;MENDE KIKAKUI SYLLABLE M145 MBI;Lo;0;R;;;;;N;;;;; 1E894;MENDE KIKAKUI SYLLABLE M062 MBA;Lo;0;R;;;;;N;;;;; 1E895;MENDE KIKAKUI SYLLABLE M122 MBU;Lo;0;R;;;;;N;;;;; 1E896;MENDE KIKAKUI SYLLABLE M047 MBEE;Lo;0;R;;;;;N;;;;; 1E897;MENDE KIKAKUI SYLLABLE M188 MBEE;Lo;0;R;;;;;N;;;;; 1E898;MENDE KIKAKUI SYLLABLE M072 MBE;Lo;0;R;;;;;N;;;;; 1E899;MENDE KIKAKUI SYLLABLE M172 MBOO;Lo;0;R;;;;;N;;;;; 1E89A;MENDE KIKAKUI SYLLABLE M174 MBO;Lo;0;R;;;;;N;;;;; 1E89B;MENDE KIKAKUI SYLLABLE M187 MBUU;Lo;0;R;;;;;N;;;;; 1E89C;MENDE KIKAKUI SYLLABLE M161 LONG MBE;Lo;0;R;;;;;N;;;;; 1E89D;MENDE KIKAKUI SYLLABLE M105 LONG MBOO;Lo;0;R;;;;;N;;;;; 1E89E;MENDE KIKAKUI SYLLABLE M142 LONG MBO;Lo;0;R;;;;;N;;;;; 1E89F;MENDE KIKAKUI SYLLABLE M132 KPI;Lo;0;R;;;;;N;;;;; 1E8A0;MENDE KIKAKUI SYLLABLE M092 KPA;Lo;0;R;;;;;N;;;;; 1E8A1;MENDE KIKAKUI SYLLABLE M074 KPU;Lo;0;R;;;;;N;;;;; 1E8A2;MENDE KIKAKUI SYLLABLE M044 KPEE;Lo;0;R;;;;;N;;;;; 1E8A3;MENDE KIKAKUI SYLLABLE M108 KPE;Lo;0;R;;;;;N;;;;; 1E8A4;MENDE KIKAKUI SYLLABLE M112 KPOO;Lo;0;R;;;;;N;;;;; 1E8A5;MENDE KIKAKUI SYLLABLE M158 KPO;Lo;0;R;;;;;N;;;;; 1E8A6;MENDE KIKAKUI SYLLABLE M124 GBI;Lo;0;R;;;;;N;;;;; 1E8A7;MENDE KIKAKUI SYLLABLE M056 GBA;Lo;0;R;;;;;N;;;;; 1E8A8;MENDE KIKAKUI SYLLABLE M148 GBU;Lo;0;R;;;;;N;;;;; 1E8A9;MENDE KIKAKUI SYLLABLE M093 GBEE;Lo;0;R;;;;;N;;;;; 1E8AA;MENDE KIKAKUI SYLLABLE M107 GBE;Lo;0;R;;;;;N;;;;; 1E8AB;MENDE KIKAKUI SYLLABLE M071 GBOO;Lo;0;R;;;;;N;;;;; 1E8AC;MENDE KIKAKUI SYLLABLE M070 GBO;Lo;0;R;;;;;N;;;;; 1E8AD;MENDE KIKAKUI SYLLABLE M171 RA;Lo;0;R;;;;;N;;;;; 1E8AE;MENDE KIKAKUI SYLLABLE M123 NDI;Lo;0;R;;;;;N;;;;; 1E8AF;MENDE KIKAKUI SYLLABLE M129 NDA;Lo;0;R;;;;;N;;;;; 1E8B0;MENDE KIKAKUI SYLLABLE M125 NDU;Lo;0;R;;;;;N;;;;; 1E8B1;MENDE KIKAKUI SYLLABLE M191 NDEE;Lo;0;R;;;;;N;;;;; 1E8B2;MENDE KIKAKUI SYLLABLE M119 NDE;Lo;0;R;;;;;N;;;;; 1E8B3;MENDE KIKAKUI SYLLABLE M067 NDOO;Lo;0;R;;;;;N;;;;; 1E8B4;MENDE KIKAKUI SYLLABLE M064 NDO;Lo;0;R;;;;;N;;;;; 1E8B5;MENDE KIKAKUI SYLLABLE M152 NJA;Lo;0;R;;;;;N;;;;; 1E8B6;MENDE KIKAKUI SYLLABLE M192 NJU;Lo;0;R;;;;;N;;;;; 1E8B7;MENDE KIKAKUI SYLLABLE M149 NJEE;Lo;0;R;;;;;N;;;;; 1E8B8;MENDE KIKAKUI SYLLABLE M134 NJOO;Lo;0;R;;;;;N;;;;; 1E8B9;MENDE KIKAKUI SYLLABLE M182 VI;Lo;0;R;;;;;N;;;;; 1E8BA;MENDE KIKAKUI SYLLABLE M185 VA;Lo;0;R;;;;;N;;;;; 1E8BB;MENDE KIKAKUI SYLLABLE M151 VU;Lo;0;R;;;;;N;;;;; 1E8BC;MENDE KIKAKUI SYLLABLE M173 VEE;Lo;0;R;;;;;N;;;;; 1E8BD;MENDE KIKAKUI SYLLABLE M085 VE;Lo;0;R;;;;;N;;;;; 1E8BE;MENDE KIKAKUI SYLLABLE M144 VOO;Lo;0;R;;;;;N;;;;; 1E8BF;MENDE KIKAKUI SYLLABLE M077 VO;Lo;0;R;;;;;N;;;;; 1E8C0;MENDE KIKAKUI SYLLABLE M164 NYIN;Lo;0;R;;;;;N;;;;; 1E8C1;MENDE KIKAKUI SYLLABLE M058 NYAN;Lo;0;R;;;;;N;;;;; 1E8C2;MENDE KIKAKUI SYLLABLE M170 NYUN;Lo;0;R;;;;;N;;;;; 1E8C3;MENDE KIKAKUI SYLLABLE M098 NYEN;Lo;0;R;;;;;N;;;;; 1E8C4;MENDE KIKAKUI SYLLABLE M060 NYON;Lo;0;R;;;;;N;;;;; 1E8C7;MENDE KIKAKUI DIGIT ONE;No;0;R;;;;1;N;;;;; 1E8C8;MENDE KIKAKUI DIGIT TWO;No;0;R;;;;2;N;;;;; 1E8C9;MENDE KIKAKUI DIGIT THREE;No;0;R;;;;3;N;;;;; 1E8CA;MENDE KIKAKUI DIGIT FOUR;No;0;R;;;;4;N;;;;; 1E8CB;MENDE KIKAKUI DIGIT FIVE;No;0;R;;;;5;N;;;;; 1E8CC;MENDE KIKAKUI DIGIT SIX;No;0;R;;;;6;N;;;;; 1E8CD;MENDE KIKAKUI DIGIT SEVEN;No;0;R;;;;7;N;;;;; 1E8CE;MENDE KIKAKUI DIGIT EIGHT;No;0;R;;;;8;N;;;;; 1E8CF;MENDE KIKAKUI DIGIT NINE;No;0;R;;;;9;N;;;;; 1E8D0;MENDE KIKAKUI COMBINING NUMBER TEENS;Mn;220;NSM;;;;;N;;;;; 1E8D1;MENDE KIKAKUI COMBINING NUMBER TENS;Mn;220;NSM;;;;;N;;;;; 1E8D2;MENDE KIKAKUI COMBINING NUMBER HUNDREDS;Mn;220;NSM;;;;;N;;;;; 1E8D3;MENDE KIKAKUI COMBINING NUMBER THOUSANDS;Mn;220;NSM;;;;;N;;;;; 1E8D4;MENDE KIKAKUI COMBINING NUMBER TEN THOUSANDS;Mn;220;NSM;;;;;N;;;;; 1E8D5;MENDE KIKAKUI COMBINING NUMBER HUNDRED THOUSANDS;Mn;220;NSM;;;;;N;;;;; 1E8D6;MENDE KIKAKUI COMBINING NUMBER MILLIONS;Mn;220;NSM;;;;;N;;;;; 1E900;ADLAM CAPITAL LETTER ALIF;Lu;0;R;;;;;N;;;;1E922; 1E901;ADLAM CAPITAL LETTER DAALI;Lu;0;R;;;;;N;;;;1E923; 1E902;ADLAM CAPITAL LETTER LAAM;Lu;0;R;;;;;N;;;;1E924; 1E903;ADLAM CAPITAL LETTER MIIM;Lu;0;R;;;;;N;;;;1E925; 1E904;ADLAM CAPITAL LETTER BA;Lu;0;R;;;;;N;;;;1E926; 1E905;ADLAM CAPITAL LETTER SINNYIIYHE;Lu;0;R;;;;;N;;;;1E927; 1E906;ADLAM CAPITAL LETTER PE;Lu;0;R;;;;;N;;;;1E928; 1E907;ADLAM CAPITAL LETTER BHE;Lu;0;R;;;;;N;;;;1E929; 1E908;ADLAM CAPITAL LETTER RA;Lu;0;R;;;;;N;;;;1E92A; 1E909;ADLAM CAPITAL LETTER E;Lu;0;R;;;;;N;;;;1E92B; 1E90A;ADLAM CAPITAL LETTER FA;Lu;0;R;;;;;N;;;;1E92C; 1E90B;ADLAM CAPITAL LETTER I;Lu;0;R;;;;;N;;;;1E92D; 1E90C;ADLAM CAPITAL LETTER O;Lu;0;R;;;;;N;;;;1E92E; 1E90D;ADLAM CAPITAL LETTER DHA;Lu;0;R;;;;;N;;;;1E92F; 1E90E;ADLAM CAPITAL LETTER YHE;Lu;0;R;;;;;N;;;;1E930; 1E90F;ADLAM CAPITAL LETTER WAW;Lu;0;R;;;;;N;;;;1E931; 1E910;ADLAM CAPITAL LETTER NUN;Lu;0;R;;;;;N;;;;1E932; 1E911;ADLAM CAPITAL LETTER KAF;Lu;0;R;;;;;N;;;;1E933; 1E912;ADLAM CAPITAL LETTER YA;Lu;0;R;;;;;N;;;;1E934; 1E913;ADLAM CAPITAL LETTER U;Lu;0;R;;;;;N;;;;1E935; 1E914;ADLAM CAPITAL LETTER JIIM;Lu;0;R;;;;;N;;;;1E936; 1E915;ADLAM CAPITAL LETTER CHI;Lu;0;R;;;;;N;;;;1E937; 1E916;ADLAM CAPITAL LETTER HA;Lu;0;R;;;;;N;;;;1E938; 1E917;ADLAM CAPITAL LETTER QAAF;Lu;0;R;;;;;N;;;;1E939; 1E918;ADLAM CAPITAL LETTER GA;Lu;0;R;;;;;N;;;;1E93A; 1E919;ADLAM CAPITAL LETTER NYA;Lu;0;R;;;;;N;;;;1E93B; 1E91A;ADLAM CAPITAL LETTER TU;Lu;0;R;;;;;N;;;;1E93C; 1E91B;ADLAM CAPITAL LETTER NHA;Lu;0;R;;;;;N;;;;1E93D; 1E91C;ADLAM CAPITAL LETTER VA;Lu;0;R;;;;;N;;;;1E93E; 1E91D;ADLAM CAPITAL LETTER KHA;Lu;0;R;;;;;N;;;;1E93F; 1E91E;ADLAM CAPITAL LETTER GBE;Lu;0;R;;;;;N;;;;1E940; 1E91F;ADLAM CAPITAL LETTER ZAL;Lu;0;R;;;;;N;;;;1E941; 1E920;ADLAM CAPITAL LETTER KPO;Lu;0;R;;;;;N;;;;1E942; 1E921;ADLAM CAPITAL LETTER SHA;Lu;0;R;;;;;N;;;;1E943; 1E922;ADLAM SMALL LETTER ALIF;Ll;0;R;;;;;N;;;1E900;;1E900 1E923;ADLAM SMALL LETTER DAALI;Ll;0;R;;;;;N;;;1E901;;1E901 1E924;ADLAM SMALL LETTER LAAM;Ll;0;R;;;;;N;;;1E902;;1E902 1E925;ADLAM SMALL LETTER MIIM;Ll;0;R;;;;;N;;;1E903;;1E903 1E926;ADLAM SMALL LETTER BA;Ll;0;R;;;;;N;;;1E904;;1E904 1E927;ADLAM SMALL LETTER SINNYIIYHE;Ll;0;R;;;;;N;;;1E905;;1E905 1E928;ADLAM SMALL LETTER PE;Ll;0;R;;;;;N;;;1E906;;1E906 1E929;ADLAM SMALL LETTER BHE;Ll;0;R;;;;;N;;;1E907;;1E907 1E92A;ADLAM SMALL LETTER RA;Ll;0;R;;;;;N;;;1E908;;1E908 1E92B;ADLAM SMALL LETTER E;Ll;0;R;;;;;N;;;1E909;;1E909 1E92C;ADLAM SMALL LETTER FA;Ll;0;R;;;;;N;;;1E90A;;1E90A 1E92D;ADLAM SMALL LETTER I;Ll;0;R;;;;;N;;;1E90B;;1E90B 1E92E;ADLAM SMALL LETTER O;Ll;0;R;;;;;N;;;1E90C;;1E90C 1E92F;ADLAM SMALL LETTER DHA;Ll;0;R;;;;;N;;;1E90D;;1E90D 1E930;ADLAM SMALL LETTER YHE;Ll;0;R;;;;;N;;;1E90E;;1E90E 1E931;ADLAM SMALL LETTER WAW;Ll;0;R;;;;;N;;;1E90F;;1E90F 1E932;ADLAM SMALL LETTER NUN;Ll;0;R;;;;;N;;;1E910;;1E910 1E933;ADLAM SMALL LETTER KAF;Ll;0;R;;;;;N;;;1E911;;1E911 1E934;ADLAM SMALL LETTER YA;Ll;0;R;;;;;N;;;1E912;;1E912 1E935;ADLAM SMALL LETTER U;Ll;0;R;;;;;N;;;1E913;;1E913 1E936;ADLAM SMALL LETTER JIIM;Ll;0;R;;;;;N;;;1E914;;1E914 1E937;ADLAM SMALL LETTER CHI;Ll;0;R;;;;;N;;;1E915;;1E915 1E938;ADLAM SMALL LETTER HA;Ll;0;R;;;;;N;;;1E916;;1E916 1E939;ADLAM SMALL LETTER QAAF;Ll;0;R;;;;;N;;;1E917;;1E917 1E93A;ADLAM SMALL LETTER GA;Ll;0;R;;;;;N;;;1E918;;1E918 1E93B;ADLAM SMALL LETTER NYA;Ll;0;R;;;;;N;;;1E919;;1E919 1E93C;ADLAM SMALL LETTER TU;Ll;0;R;;;;;N;;;1E91A;;1E91A 1E93D;ADLAM SMALL LETTER NHA;Ll;0;R;;;;;N;;;1E91B;;1E91B 1E93E;ADLAM SMALL LETTER VA;Ll;0;R;;;;;N;;;1E91C;;1E91C 1E93F;ADLAM SMALL LETTER KHA;Ll;0;R;;;;;N;;;1E91D;;1E91D 1E940;ADLAM SMALL LETTER GBE;Ll;0;R;;;;;N;;;1E91E;;1E91E 1E941;ADLAM SMALL LETTER ZAL;Ll;0;R;;;;;N;;;1E91F;;1E91F 1E942;ADLAM SMALL LETTER KPO;Ll;0;R;;;;;N;;;1E920;;1E920 1E943;ADLAM SMALL LETTER SHA;Ll;0;R;;;;;N;;;1E921;;1E921 1E944;ADLAM ALIF LENGTHENER;Mn;230;NSM;;;;;N;;;;; 1E945;ADLAM VOWEL LENGTHENER;Mn;230;NSM;;;;;N;;;;; 1E946;ADLAM GEMINATION MARK;Mn;230;NSM;;;;;N;;;;; 1E947;ADLAM HAMZA;Mn;230;NSM;;;;;N;;;;; 1E948;ADLAM CONSONANT MODIFIER;Mn;230;NSM;;;;;N;;;;; 1E949;ADLAM GEMINATE CONSONANT MODIFIER;Mn;230;NSM;;;;;N;;;;; 1E94A;ADLAM NUKTA;Mn;7;NSM;;;;;N;;;;; 1E950;ADLAM DIGIT ZERO;Nd;0;R;;0;0;0;N;;;;; 1E951;ADLAM DIGIT ONE;Nd;0;R;;1;1;1;N;;;;; 1E952;ADLAM DIGIT TWO;Nd;0;R;;2;2;2;N;;;;; 1E953;ADLAM DIGIT THREE;Nd;0;R;;3;3;3;N;;;;; 1E954;ADLAM DIGIT FOUR;Nd;0;R;;4;4;4;N;;;;; 1E955;ADLAM DIGIT FIVE;Nd;0;R;;5;5;5;N;;;;; 1E956;ADLAM DIGIT SIX;Nd;0;R;;6;6;6;N;;;;; 1E957;ADLAM DIGIT SEVEN;Nd;0;R;;7;7;7;N;;;;; 1E958;ADLAM DIGIT EIGHT;Nd;0;R;;8;8;8;N;;;;; 1E959;ADLAM DIGIT NINE;Nd;0;R;;9;9;9;N;;;;; 1E95E;ADLAM INITIAL EXCLAMATION MARK;Po;0;R;;;;;N;;;;; 1E95F;ADLAM INITIAL QUESTION MARK;Po;0;R;;;;;N;;;;; 1EE00;ARABIC MATHEMATICAL ALEF;Lo;0;AL;<font> 0627;;;;N;;;;; 1EE01;ARABIC MATHEMATICAL BEH;Lo;0;AL;<font> 0628;;;;N;;;;; 1EE02;ARABIC MATHEMATICAL JEEM;Lo;0;AL;<font> 062C;;;;N;;;;; 1EE03;ARABIC MATHEMATICAL DAL;Lo;0;AL;<font> 062F;;;;N;;;;; 1EE05;ARABIC MATHEMATICAL WAW;Lo;0;AL;<font> 0648;;;;N;;;;; 1EE06;ARABIC MATHEMATICAL ZAIN;Lo;0;AL;<font> 0632;;;;N;;;;; 1EE07;ARABIC MATHEMATICAL HAH;Lo;0;AL;<font> 062D;;;;N;;;;; 1EE08;ARABIC MATHEMATICAL TAH;Lo;0;AL;<font> 0637;;;;N;;;;; 1EE09;ARABIC MATHEMATICAL YEH;Lo;0;AL;<font> 064A;;;;N;;;;; 1EE0A;ARABIC MATHEMATICAL KAF;Lo;0;AL;<font> 0643;;;;N;;;;; 1EE0B;ARABIC MATHEMATICAL LAM;Lo;0;AL;<font> 0644;;;;N;;;;; 1EE0C;ARABIC MATHEMATICAL MEEM;Lo;0;AL;<font> 0645;;;;N;;;;; 1EE0D;ARABIC MATHEMATICAL NOON;Lo;0;AL;<font> 0646;;;;N;;;;; 1EE0E;ARABIC MATHEMATICAL SEEN;Lo;0;AL;<font> 0633;;;;N;;;;; 1EE0F;ARABIC MATHEMATICAL AIN;Lo;0;AL;<font> 0639;;;;N;;;;; 1EE10;ARABIC MATHEMATICAL FEH;Lo;0;AL;<font> 0641;;;;N;;;;; 1EE11;ARABIC MATHEMATICAL SAD;Lo;0;AL;<font> 0635;;;;N;;;;; 1EE12;ARABIC MATHEMATICAL QAF;Lo;0;AL;<font> 0642;;;;N;;;;; 1EE13;ARABIC MATHEMATICAL REH;Lo;0;AL;<font> 0631;;;;N;;;;; 1EE14;ARABIC MATHEMATICAL SHEEN;Lo;0;AL;<font> 0634;;;;N;;;;; 1EE15;ARABIC MATHEMATICAL TEH;Lo;0;AL;<font> 062A;;;;N;;;;; 1EE16;ARABIC MATHEMATICAL THEH;Lo;0;AL;<font> 062B;;;;N;;;;; 1EE17;ARABIC MATHEMATICAL KHAH;Lo;0;AL;<font> 062E;;;;N;;;;; 1EE18;ARABIC MATHEMATICAL THAL;Lo;0;AL;<font> 0630;;;;N;;;;; 1EE19;ARABIC MATHEMATICAL DAD;Lo;0;AL;<font> 0636;;;;N;;;;; 1EE1A;ARABIC MATHEMATICAL ZAH;Lo;0;AL;<font> 0638;;;;N;;;;; 1EE1B;ARABIC MATHEMATICAL GHAIN;Lo;0;AL;<font> 063A;;;;N;;;;; 1EE1C;ARABIC MATHEMATICAL DOTLESS BEH;Lo;0;AL;<font> 066E;;;;N;;;;; 1EE1D;ARABIC MATHEMATICAL DOTLESS NOON;Lo;0;AL;<font> 06BA;;;;N;;;;; 1EE1E;ARABIC MATHEMATICAL DOTLESS FEH;Lo;0;AL;<font> 06A1;;;;N;;;;; 1EE1F;ARABIC MATHEMATICAL DOTLESS QAF;Lo;0;AL;<font> 066F;;;;N;;;;; 1EE21;ARABIC MATHEMATICAL INITIAL BEH;Lo;0;AL;<font> 0628;;;;N;;;;; 1EE22;ARABIC MATHEMATICAL INITIAL JEEM;Lo;0;AL;<font> 062C;;;;N;;;;; 1EE24;ARABIC MATHEMATICAL INITIAL HEH;Lo;0;AL;<font> 0647;;;;N;;;;; 1EE27;ARABIC MATHEMATICAL INITIAL HAH;Lo;0;AL;<font> 062D;;;;N;;;;; 1EE29;ARABIC MATHEMATICAL INITIAL YEH;Lo;0;AL;<font> 064A;;;;N;;;;; 1EE2A;ARABIC MATHEMATICAL INITIAL KAF;Lo;0;AL;<font> 0643;;;;N;;;;; 1EE2B;ARABIC MATHEMATICAL INITIAL LAM;Lo;0;AL;<font> 0644;;;;N;;;;; 1EE2C;ARABIC MATHEMATICAL INITIAL MEEM;Lo;0;AL;<font> 0645;;;;N;;;;; 1EE2D;ARABIC MATHEMATICAL INITIAL NOON;Lo;0;AL;<font> 0646;;;;N;;;;; 1EE2E;ARABIC MATHEMATICAL INITIAL SEEN;Lo;0;AL;<font> 0633;;;;N;;;;; 1EE2F;ARABIC MATHEMATICAL INITIAL AIN;Lo;0;AL;<font> 0639;;;;N;;;;; 1EE30;ARABIC MATHEMATICAL INITIAL FEH;Lo;0;AL;<font> 0641;;;;N;;;;; 1EE31;ARABIC MATHEMATICAL INITIAL SAD;Lo;0;AL;<font> 0635;;;;N;;;;; 1EE32;ARABIC MATHEMATICAL INITIAL QAF;Lo;0;AL;<font> 0642;;;;N;;;;; 1EE34;ARABIC MATHEMATICAL INITIAL SHEEN;Lo;0;AL;<font> 0634;;;;N;;;;; 1EE35;ARABIC MATHEMATICAL INITIAL TEH;Lo;0;AL;<font> 062A;;;;N;;;;; 1EE36;ARABIC MATHEMATICAL INITIAL THEH;Lo;0;AL;<font> 062B;;;;N;;;;; 1EE37;ARABIC MATHEMATICAL INITIAL KHAH;Lo;0;AL;<font> 062E;;;;N;;;;; 1EE39;ARABIC MATHEMATICAL INITIAL DAD;Lo;0;AL;<font> 0636;;;;N;;;;; 1EE3B;ARABIC MATHEMATICAL INITIAL GHAIN;Lo;0;AL;<font> 063A;;;;N;;;;; 1EE42;ARABIC MATHEMATICAL TAILED JEEM;Lo;0;AL;<font> 062C;;;;N;;;;; 1EE47;ARABIC MATHEMATICAL TAILED HAH;Lo;0;AL;<font> 062D;;;;N;;;;; 1EE49;ARABIC MATHEMATICAL TAILED YEH;Lo;0;AL;<font> 064A;;;;N;;;;; 1EE4B;ARABIC MATHEMATICAL TAILED LAM;Lo;0;AL;<font> 0644;;;;N;;;;; 1EE4D;ARABIC MATHEMATICAL TAILED NOON;Lo;0;AL;<font> 0646;;;;N;;;;; 1EE4E;ARABIC MATHEMATICAL TAILED SEEN;Lo;0;AL;<font> 0633;;;;N;;;;; 1EE4F;ARABIC MATHEMATICAL TAILED AIN;Lo;0;AL;<font> 0639;;;;N;;;;; 1EE51;ARABIC MATHEMATICAL TAILED SAD;Lo;0;AL;<font> 0635;;;;N;;;;; 1EE52;ARABIC MATHEMATICAL TAILED QAF;Lo;0;AL;<font> 0642;;;;N;;;;; 1EE54;ARABIC MATHEMATICAL TAILED SHEEN;Lo;0;AL;<font> 0634;;;;N;;;;; 1EE57;ARABIC MATHEMATICAL TAILED KHAH;Lo;0;AL;<font> 062E;;;;N;;;;; 1EE59;ARABIC MATHEMATICAL TAILED DAD;Lo;0;AL;<font> 0636;;;;N;;;;; 1EE5B;ARABIC MATHEMATICAL TAILED GHAIN;Lo;0;AL;<font> 063A;;;;N;;;;; 1EE5D;ARABIC MATHEMATICAL TAILED DOTLESS NOON;Lo;0;AL;<font> 06BA;;;;N;;;;; 1EE5F;ARABIC MATHEMATICAL TAILED DOTLESS QAF;Lo;0;AL;<font> 066F;;;;N;;;;; 1EE61;ARABIC MATHEMATICAL STRETCHED BEH;Lo;0;AL;<font> 0628;;;;N;;;;; 1EE62;ARABIC MATHEMATICAL STRETCHED JEEM;Lo;0;AL;<font> 062C;;;;N;;;;; 1EE64;ARABIC MATHEMATICAL STRETCHED HEH;Lo;0;AL;<font> 0647;;;;N;;;;; 1EE67;ARABIC MATHEMATICAL STRETCHED HAH;Lo;0;AL;<font> 062D;;;;N;;;;; 1EE68;ARABIC MATHEMATICAL STRETCHED TAH;Lo;0;AL;<font> 0637;;;;N;;;;; 1EE69;ARABIC MATHEMATICAL STRETCHED YEH;Lo;0;AL;<font> 064A;;;;N;;;;; 1EE6A;ARABIC MATHEMATICAL STRETCHED KAF;Lo;0;AL;<font> 0643;;;;N;;;;; 1EE6C;ARABIC MATHEMATICAL STRETCHED MEEM;Lo;0;AL;<font> 0645;;;;N;;;;; 1EE6D;ARABIC MATHEMATICAL STRETCHED NOON;Lo;0;AL;<font> 0646;;;;N;;;;; 1EE6E;ARABIC MATHEMATICAL STRETCHED SEEN;Lo;0;AL;<font> 0633;;;;N;;;;; 1EE6F;ARABIC MATHEMATICAL STRETCHED AIN;Lo;0;AL;<font> 0639;;;;N;;;;; 1EE70;ARABIC MATHEMATICAL STRETCHED FEH;Lo;0;AL;<font> 0641;;;;N;;;;; 1EE71;ARABIC MATHEMATICAL STRETCHED SAD;Lo;0;AL;<font> 0635;;;;N;;;;; 1EE72;ARABIC MATHEMATICAL STRETCHED QAF;Lo;0;AL;<font> 0642;;;;N;;;;; 1EE74;ARABIC MATHEMATICAL STRETCHED SHEEN;Lo;0;AL;<font> 0634;;;;N;;;;; 1EE75;ARABIC MATHEMATICAL STRETCHED TEH;Lo;0;AL;<font> 062A;;;;N;;;;; 1EE76;ARABIC MATHEMATICAL STRETCHED THEH;Lo;0;AL;<font> 062B;;;;N;;;;; 1EE77;ARABIC MATHEMATICAL STRETCHED KHAH;Lo;0;AL;<font> 062E;;;;N;;;;; 1EE79;ARABIC MATHEMATICAL STRETCHED DAD;Lo;0;AL;<font> 0636;;;;N;;;;; 1EE7A;ARABIC MATHEMATICAL STRETCHED ZAH;Lo;0;AL;<font> 0638;;;;N;;;;; 1EE7B;ARABIC MATHEMATICAL STRETCHED GHAIN;Lo;0;AL;<font> 063A;;;;N;;;;; 1EE7C;ARABIC MATHEMATICAL STRETCHED DOTLESS BEH;Lo;0;AL;<font> 066E;;;;N;;;;; 1EE7E;ARABIC MATHEMATICAL STRETCHED DOTLESS FEH;Lo;0;AL;<font> 06A1;;;;N;;;;; 1EE80;ARABIC MATHEMATICAL LOOPED ALEF;Lo;0;AL;<font> 0627;;;;N;;;;; 1EE81;ARABIC MATHEMATICAL LOOPED BEH;Lo;0;AL;<font> 0628;;;;N;;;;; 1EE82;ARABIC MATHEMATICAL LOOPED JEEM;Lo;0;AL;<font> 062C;;;;N;;;;; 1EE83;ARABIC MATHEMATICAL LOOPED DAL;Lo;0;AL;<font> 062F;;;;N;;;;; 1EE84;ARABIC MATHEMATICAL LOOPED HEH;Lo;0;AL;<font> 0647;;;;N;;;;; 1EE85;ARABIC MATHEMATICAL LOOPED WAW;Lo;0;AL;<font> 0648;;;;N;;;;; 1EE86;ARABIC MATHEMATICAL LOOPED ZAIN;Lo;0;AL;<font> 0632;;;;N;;;;; 1EE87;ARABIC MATHEMATICAL LOOPED HAH;Lo;0;AL;<font> 062D;;;;N;;;;; 1EE88;ARABIC MATHEMATICAL LOOPED TAH;Lo;0;AL;<font> 0637;;;;N;;;;; 1EE89;ARABIC MATHEMATICAL LOOPED YEH;Lo;0;AL;<font> 064A;;;;N;;;;; 1EE8B;ARABIC MATHEMATICAL LOOPED LAM;Lo;0;AL;<font> 0644;;;;N;;;;; 1EE8C;ARABIC MATHEMATICAL LOOPED MEEM;Lo;0;AL;<font> 0645;;;;N;;;;; 1EE8D;ARABIC MATHEMATICAL LOOPED NOON;Lo;0;AL;<font> 0646;;;;N;;;;; 1EE8E;ARABIC MATHEMATICAL LOOPED SEEN;Lo;0;AL;<font> 0633;;;;N;;;;; 1EE8F;ARABIC MATHEMATICAL LOOPED AIN;Lo;0;AL;<font> 0639;;;;N;;;;; 1EE90;ARABIC MATHEMATICAL LOOPED FEH;Lo;0;AL;<font> 0641;;;;N;;;;; 1EE91;ARABIC MATHEMATICAL LOOPED SAD;Lo;0;AL;<font> 0635;;;;N;;;;; 1EE92;ARABIC MATHEMATICAL LOOPED QAF;Lo;0;AL;<font> 0642;;;;N;;;;; 1EE93;ARABIC MATHEMATICAL LOOPED REH;Lo;0;AL;<font> 0631;;;;N;;;;; 1EE94;ARABIC MATHEMATICAL LOOPED SHEEN;Lo;0;AL;<font> 0634;;;;N;;;;; 1EE95;ARABIC MATHEMATICAL LOOPED TEH;Lo;0;AL;<font> 062A;;;;N;;;;; 1EE96;ARABIC MATHEMATICAL LOOPED THEH;Lo;0;AL;<font> 062B;;;;N;;;;; 1EE97;ARABIC MATHEMATICAL LOOPED KHAH;Lo;0;AL;<font> 062E;;;;N;;;;; 1EE98;ARABIC MATHEMATICAL LOOPED THAL;Lo;0;AL;<font> 0630;;;;N;;;;; 1EE99;ARABIC MATHEMATICAL LOOPED DAD;Lo;0;AL;<font> 0636;;;;N;;;;; 1EE9A;ARABIC MATHEMATICAL LOOPED ZAH;Lo;0;AL;<font> 0638;;;;N;;;;; 1EE9B;ARABIC MATHEMATICAL LOOPED GHAIN;Lo;0;AL;<font> 063A;;;;N;;;;; 1EEA1;ARABIC MATHEMATICAL DOUBLE-STRUCK BEH;Lo;0;AL;<font> 0628;;;;N;;;;; 1EEA2;ARABIC MATHEMATICAL DOUBLE-STRUCK JEEM;Lo;0;AL;<font> 062C;;;;N;;;;; 1EEA3;ARABIC MATHEMATICAL DOUBLE-STRUCK DAL;Lo;0;AL;<font> 062F;;;;N;;;;; 1EEA5;ARABIC MATHEMATICAL DOUBLE-STRUCK WAW;Lo;0;AL;<font> 0648;;;;N;;;;; 1EEA6;ARABIC MATHEMATICAL DOUBLE-STRUCK ZAIN;Lo;0;AL;<font> 0632;;;;N;;;;; 1EEA7;ARABIC MATHEMATICAL DOUBLE-STRUCK HAH;Lo;0;AL;<font> 062D;;;;N;;;;; 1EEA8;ARABIC MATHEMATICAL DOUBLE-STRUCK TAH;Lo;0;AL;<font> 0637;;;;N;;;;; 1EEA9;ARABIC MATHEMATICAL DOUBLE-STRUCK YEH;Lo;0;AL;<font> 064A;;;;N;;;;; 1EEAB;ARABIC MATHEMATICAL DOUBLE-STRUCK LAM;Lo;0;AL;<font> 0644;;;;N;;;;; 1EEAC;ARABIC MATHEMATICAL DOUBLE-STRUCK MEEM;Lo;0;AL;<font> 0645;;;;N;;;;; 1EEAD;ARABIC MATHEMATICAL DOUBLE-STRUCK NOON;Lo;0;AL;<font> 0646;;;;N;;;;; 1EEAE;ARABIC MATHEMATICAL DOUBLE-STRUCK SEEN;Lo;0;AL;<font> 0633;;;;N;;;;; 1EEAF;ARABIC MATHEMATICAL DOUBLE-STRUCK AIN;Lo;0;AL;<font> 0639;;;;N;;;;; 1EEB0;ARABIC MATHEMATICAL DOUBLE-STRUCK FEH;Lo;0;AL;<font> 0641;;;;N;;;;; 1EEB1;ARABIC MATHEMATICAL DOUBLE-STRUCK SAD;Lo;0;AL;<font> 0635;;;;N;;;;; 1EEB2;ARABIC MATHEMATICAL DOUBLE-STRUCK QAF;Lo;0;AL;<font> 0642;;;;N;;;;; 1EEB3;ARABIC MATHEMATICAL DOUBLE-STRUCK REH;Lo;0;AL;<font> 0631;;;;N;;;;; 1EEB4;ARABIC MATHEMATICAL DOUBLE-STRUCK SHEEN;Lo;0;AL;<font> 0634;;;;N;;;;; 1EEB5;ARABIC MATHEMATICAL DOUBLE-STRUCK TEH;Lo;0;AL;<font> 062A;;;;N;;;;; 1EEB6;ARABIC MATHEMATICAL DOUBLE-STRUCK THEH;Lo;0;AL;<font> 062B;;;;N;;;;; 1EEB7;ARABIC MATHEMATICAL DOUBLE-STRUCK KHAH;Lo;0;AL;<font> 062E;;;;N;;;;; 1EEB8;ARABIC MATHEMATICAL DOUBLE-STRUCK THAL;Lo;0;AL;<font> 0630;;;;N;;;;; 1EEB9;ARABIC MATHEMATICAL DOUBLE-STRUCK DAD;Lo;0;AL;<font> 0636;;;;N;;;;; 1EEBA;ARABIC MATHEMATICAL DOUBLE-STRUCK ZAH;Lo;0;AL;<font> 0638;;;;N;;;;; 1EEBB;ARABIC MATHEMATICAL DOUBLE-STRUCK GHAIN;Lo;0;AL;<font> 063A;;;;N;;;;; 1EEF0;ARABIC MATHEMATICAL OPERATOR MEEM WITH HAH WITH TATWEEL;Sm;0;ON;;;;;N;;;;; 1EEF1;ARABIC MATHEMATICAL OPERATOR HAH WITH DAL;Sm;0;ON;;;;;N;;;;; 1F000;MAHJONG TILE EAST WIND;So;0;ON;;;;;N;;;;; 1F001;MAHJONG TILE SOUTH WIND;So;0;ON;;;;;N;;;;; 1F002;MAHJONG TILE WEST WIND;So;0;ON;;;;;N;;;;; 1F003;MAHJONG TILE NORTH WIND;So;0;ON;;;;;N;;;;; 1F004;MAHJONG TILE RED DRAGON;So;0;ON;;;;;N;;;;; 1F005;MAHJONG TILE GREEN DRAGON;So;0;ON;;;;;N;;;;; 1F006;MAHJONG TILE WHITE DRAGON;So;0;ON;;;;;N;;;;; 1F007;MAHJONG TILE ONE OF CHARACTERS;So;0;ON;;;;;N;;;;; 1F008;MAHJONG TILE TWO OF CHARACTERS;So;0;ON;;;;;N;;;;; 1F009;MAHJONG TILE THREE OF CHARACTERS;So;0;ON;;;;;N;;;;; 1F00A;MAHJONG TILE FOUR OF CHARACTERS;So;0;ON;;;;;N;;;;; 1F00B;MAHJONG TILE FIVE OF CHARACTERS;So;0;ON;;;;;N;;;;; 1F00C;MAHJONG TILE SIX OF CHARACTERS;So;0;ON;;;;;N;;;;; 1F00D;MAHJONG TILE SEVEN OF CHARACTERS;So;0;ON;;;;;N;;;;; 1F00E;MAHJONG TILE EIGHT OF CHARACTERS;So;0;ON;;;;;N;;;;; 1F00F;MAHJONG TILE NINE OF CHARACTERS;So;0;ON;;;;;N;;;;; 1F010;MAHJONG TILE ONE OF BAMBOOS;So;0;ON;;;;;N;;;;; 1F011;MAHJONG TILE TWO OF BAMBOOS;So;0;ON;;;;;N;;;;; 1F012;MAHJONG TILE THREE OF BAMBOOS;So;0;ON;;;;;N;;;;; 1F013;MAHJONG TILE FOUR OF BAMBOOS;So;0;ON;;;;;N;;;;; 1F014;MAHJONG TILE FIVE OF BAMBOOS;So;0;ON;;;;;N;;;;; 1F015;MAHJONG TILE SIX OF BAMBOOS;So;0;ON;;;;;N;;;;; 1F016;MAHJONG TILE SEVEN OF BAMBOOS;So;0;ON;;;;;N;;;;; 1F017;MAHJONG TILE EIGHT OF BAMBOOS;So;0;ON;;;;;N;;;;; 1F018;MAHJONG TILE NINE OF BAMBOOS;So;0;ON;;;;;N;;;;; 1F019;MAHJONG TILE ONE OF CIRCLES;So;0;ON;;;;;N;;;;; 1F01A;MAHJONG TILE TWO OF CIRCLES;So;0;ON;;;;;N;;;;; 1F01B;MAHJONG TILE THREE OF CIRCLES;So;0;ON;;;;;N;;;;; 1F01C;MAHJONG TILE FOUR OF CIRCLES;So;0;ON;;;;;N;;;;; 1F01D;MAHJONG TILE FIVE OF CIRCLES;So;0;ON;;;;;N;;;;; 1F01E;MAHJONG TILE SIX OF CIRCLES;So;0;ON;;;;;N;;;;; 1F01F;MAHJONG TILE SEVEN OF CIRCLES;So;0;ON;;;;;N;;;;; 1F020;MAHJONG TILE EIGHT OF CIRCLES;So;0;ON;;;;;N;;;;; 1F021;MAHJONG TILE NINE OF CIRCLES;So;0;ON;;;;;N;;;;; 1F022;MAHJONG TILE PLUM;So;0;ON;;;;;N;;;;; 1F023;MAHJONG TILE ORCHID;So;0;ON;;;;;N;;;;; 1F024;MAHJONG TILE BAMBOO;So;0;ON;;;;;N;;;;; 1F025;MAHJONG TILE CHRYSANTHEMUM;So;0;ON;;;;;N;;;;; 1F026;MAHJONG TILE SPRING;So;0;ON;;;;;N;;;;; 1F027;MAHJONG TILE SUMMER;So;0;ON;;;;;N;;;;; 1F028;MAHJONG TILE AUTUMN;So;0;ON;;;;;N;;;;; 1F029;MAHJONG TILE WINTER;So;0;ON;;;;;N;;;;; 1F02A;MAHJONG TILE JOKER;So;0;ON;;;;;N;;;;; 1F02B;MAHJONG TILE BACK;So;0;ON;;;;;N;;;;; 1F030;DOMINO TILE HORIZONTAL BACK;So;0;ON;;;;;N;;;;; 1F031;DOMINO TILE HORIZONTAL-00-00;So;0;ON;;;;;N;;;;; 1F032;DOMINO TILE HORIZONTAL-00-01;So;0;ON;;;;;N;;;;; 1F033;DOMINO TILE HORIZONTAL-00-02;So;0;ON;;;;;N;;;;; 1F034;DOMINO TILE HORIZONTAL-00-03;So;0;ON;;;;;N;;;;; 1F035;DOMINO TILE HORIZONTAL-00-04;So;0;ON;;;;;N;;;;; 1F036;DOMINO TILE HORIZONTAL-00-05;So;0;ON;;;;;N;;;;; 1F037;DOMINO TILE HORIZONTAL-00-06;So;0;ON;;;;;N;;;;; 1F038;DOMINO TILE HORIZONTAL-01-00;So;0;ON;;;;;N;;;;; 1F039;DOMINO TILE HORIZONTAL-01-01;So;0;ON;;;;;N;;;;; 1F03A;DOMINO TILE HORIZONTAL-01-02;So;0;ON;;;;;N;;;;; 1F03B;DOMINO TILE HORIZONTAL-01-03;So;0;ON;;;;;N;;;;; 1F03C;DOMINO TILE HORIZONTAL-01-04;So;0;ON;;;;;N;;;;; 1F03D;DOMINO TILE HORIZONTAL-01-05;So;0;ON;;;;;N;;;;; 1F03E;DOMINO TILE HORIZONTAL-01-06;So;0;ON;;;;;N;;;;; 1F03F;DOMINO TILE HORIZONTAL-02-00;So;0;ON;;;;;N;;;;; 1F040;DOMINO TILE HORIZONTAL-02-01;So;0;ON;;;;;N;;;;; 1F041;DOMINO TILE HORIZONTAL-02-02;So;0;ON;;;;;N;;;;; 1F042;DOMINO TILE HORIZONTAL-02-03;So;0;ON;;;;;N;;;;; 1F043;DOMINO TILE HORIZONTAL-02-04;So;0;ON;;;;;N;;;;; 1F044;DOMINO TILE HORIZONTAL-02-05;So;0;ON;;;;;N;;;;; 1F045;DOMINO TILE HORIZONTAL-02-06;So;0;ON;;;;;N;;;;; 1F046;DOMINO TILE HORIZONTAL-03-00;So;0;ON;;;;;N;;;;; 1F047;DOMINO TILE HORIZONTAL-03-01;So;0;ON;;;;;N;;;;; 1F048;DOMINO TILE HORIZONTAL-03-02;So;0;ON;;;;;N;;;;; 1F049;DOMINO TILE HORIZONTAL-03-03;So;0;ON;;;;;N;;;;; 1F04A;DOMINO TILE HORIZONTAL-03-04;So;0;ON;;;;;N;;;;; 1F04B;DOMINO TILE HORIZONTAL-03-05;So;0;ON;;;;;N;;;;; 1F04C;DOMINO TILE HORIZONTAL-03-06;So;0;ON;;;;;N;;;;; 1F04D;DOMINO TILE HORIZONTAL-04-00;So;0;ON;;;;;N;;;;; 1F04E;DOMINO TILE HORIZONTAL-04-01;So;0;ON;;;;;N;;;;; 1F04F;DOMINO TILE HORIZONTAL-04-02;So;0;ON;;;;;N;;;;; 1F050;DOMINO TILE HORIZONTAL-04-03;So;0;ON;;;;;N;;;;; 1F051;DOMINO TILE HORIZONTAL-04-04;So;0;ON;;;;;N;;;;; 1F052;DOMINO TILE HORIZONTAL-04-05;So;0;ON;;;;;N;;;;; 1F053;DOMINO TILE HORIZONTAL-04-06;So;0;ON;;;;;N;;;;; 1F054;DOMINO TILE HORIZONTAL-05-00;So;0;ON;;;;;N;;;;; 1F055;DOMINO TILE HORIZONTAL-05-01;So;0;ON;;;;;N;;;;; 1F056;DOMINO TILE HORIZONTAL-05-02;So;0;ON;;;;;N;;;;; 1F057;DOMINO TILE HORIZONTAL-05-03;So;0;ON;;;;;N;;;;; 1F058;DOMINO TILE HORIZONTAL-05-04;So;0;ON;;;;;N;;;;; 1F059;DOMINO TILE HORIZONTAL-05-05;So;0;ON;;;;;N;;;;; 1F05A;DOMINO TILE HORIZONTAL-05-06;So;0;ON;;;;;N;;;;; 1F05B;DOMINO TILE HORIZONTAL-06-00;So;0;ON;;;;;N;;;;; 1F05C;DOMINO TILE HORIZONTAL-06-01;So;0;ON;;;;;N;;;;; 1F05D;DOMINO TILE HORIZONTAL-06-02;So;0;ON;;;;;N;;;;; 1F05E;DOMINO TILE HORIZONTAL-06-03;So;0;ON;;;;;N;;;;; 1F05F;DOMINO TILE HORIZONTAL-06-04;So;0;ON;;;;;N;;;;; 1F060;DOMINO TILE HORIZONTAL-06-05;So;0;ON;;;;;N;;;;; 1F061;DOMINO TILE HORIZONTAL-06-06;So;0;ON;;;;;N;;;;; 1F062;DOMINO TILE VERTICAL BACK;So;0;ON;;;;;N;;;;; 1F063;DOMINO TILE VERTICAL-00-00;So;0;ON;;;;;N;;;;; 1F064;DOMINO TILE VERTICAL-00-01;So;0;ON;;;;;N;;;;; 1F065;DOMINO TILE VERTICAL-00-02;So;0;ON;;;;;N;;;;; 1F066;DOMINO TILE VERTICAL-00-03;So;0;ON;;;;;N;;;;; 1F067;DOMINO TILE VERTICAL-00-04;So;0;ON;;;;;N;;;;; 1F068;DOMINO TILE VERTICAL-00-05;So;0;ON;;;;;N;;;;; 1F069;DOMINO TILE VERTICAL-00-06;So;0;ON;;;;;N;;;;; 1F06A;DOMINO TILE VERTICAL-01-00;So;0;ON;;;;;N;;;;; 1F06B;DOMINO TILE VERTICAL-01-01;So;0;ON;;;;;N;;;;; 1F06C;DOMINO TILE VERTICAL-01-02;So;0;ON;;;;;N;;;;; 1F06D;DOMINO TILE VERTICAL-01-03;So;0;ON;;;;;N;;;;; 1F06E;DOMINO TILE VERTICAL-01-04;So;0;ON;;;;;N;;;;; 1F06F;DOMINO TILE VERTICAL-01-05;So;0;ON;;;;;N;;;;; 1F070;DOMINO TILE VERTICAL-01-06;So;0;ON;;;;;N;;;;; 1F071;DOMINO TILE VERTICAL-02-00;So;0;ON;;;;;N;;;;; 1F072;DOMINO TILE VERTICAL-02-01;So;0;ON;;;;;N;;;;; 1F073;DOMINO TILE VERTICAL-02-02;So;0;ON;;;;;N;;;;; 1F074;DOMINO TILE VERTICAL-02-03;So;0;ON;;;;;N;;;;; 1F075;DOMINO TILE VERTICAL-02-04;So;0;ON;;;;;N;;;;; 1F076;DOMINO TILE VERTICAL-02-05;So;0;ON;;;;;N;;;;; 1F077;DOMINO TILE VERTICAL-02-06;So;0;ON;;;;;N;;;;; 1F078;DOMINO TILE VERTICAL-03-00;So;0;ON;;;;;N;;;;; 1F079;DOMINO TILE VERTICAL-03-01;So;0;ON;;;;;N;;;;; 1F07A;DOMINO TILE VERTICAL-03-02;So;0;ON;;;;;N;;;;; 1F07B;DOMINO TILE VERTICAL-03-03;So;0;ON;;;;;N;;;;; 1F07C;DOMINO TILE VERTICAL-03-04;So;0;ON;;;;;N;;;;; 1F07D;DOMINO TILE VERTICAL-03-05;So;0;ON;;;;;N;;;;; 1F07E;DOMINO TILE VERTICAL-03-06;So;0;ON;;;;;N;;;;; 1F07F;DOMINO TILE VERTICAL-04-00;So;0;ON;;;;;N;;;;; 1F080;DOMINO TILE VERTICAL-04-01;So;0;ON;;;;;N;;;;; 1F081;DOMINO TILE VERTICAL-04-02;So;0;ON;;;;;N;;;;; 1F082;DOMINO TILE VERTICAL-04-03;So;0;ON;;;;;N;;;;; 1F083;DOMINO TILE VERTICAL-04-04;So;0;ON;;;;;N;;;;; 1F084;DOMINO TILE VERTICAL-04-05;So;0;ON;;;;;N;;;;; 1F085;DOMINO TILE VERTICAL-04-06;So;0;ON;;;;;N;;;;; 1F086;DOMINO TILE VERTICAL-05-00;So;0;ON;;;;;N;;;;; 1F087;DOMINO TILE VERTICAL-05-01;So;0;ON;;;;;N;;;;; 1F088;DOMINO TILE VERTICAL-05-02;So;0;ON;;;;;N;;;;; 1F089;DOMINO TILE VERTICAL-05-03;So;0;ON;;;;;N;;;;; 1F08A;DOMINO TILE VERTICAL-05-04;So;0;ON;;;;;N;;;;; 1F08B;DOMINO TILE VERTICAL-05-05;So;0;ON;;;;;N;;;;; 1F08C;DOMINO TILE VERTICAL-05-06;So;0;ON;;;;;N;;;;; 1F08D;DOMINO TILE VERTICAL-06-00;So;0;ON;;;;;N;;;;; 1F08E;DOMINO TILE VERTICAL-06-01;So;0;ON;;;;;N;;;;; 1F08F;DOMINO TILE VERTICAL-06-02;So;0;ON;;;;;N;;;;; 1F090;DOMINO TILE VERTICAL-06-03;So;0;ON;;;;;N;;;;; 1F091;DOMINO TILE VERTICAL-06-04;So;0;ON;;;;;N;;;;; 1F092;DOMINO TILE VERTICAL-06-05;So;0;ON;;;;;N;;;;; 1F093;DOMINO TILE VERTICAL-06-06;So;0;ON;;;;;N;;;;; 1F0A0;PLAYING CARD BACK;So;0;ON;;;;;N;;;;; 1F0A1;PLAYING CARD ACE OF SPADES;So;0;ON;;;;;N;;;;; 1F0A2;PLAYING CARD TWO OF SPADES;So;0;ON;;;;;N;;;;; 1F0A3;PLAYING CARD THREE OF SPADES;So;0;ON;;;;;N;;;;; 1F0A4;PLAYING CARD FOUR OF SPADES;So;0;ON;;;;;N;;;;; 1F0A5;PLAYING CARD FIVE OF SPADES;So;0;ON;;;;;N;;;;; 1F0A6;PLAYING CARD SIX OF SPADES;So;0;ON;;;;;N;;;;; 1F0A7;PLAYING CARD SEVEN OF SPADES;So;0;ON;;;;;N;;;;; 1F0A8;PLAYING CARD EIGHT OF SPADES;So;0;ON;;;;;N;;;;; 1F0A9;PLAYING CARD NINE OF SPADES;So;0;ON;;;;;N;;;;; 1F0AA;PLAYING CARD TEN OF SPADES;So;0;ON;;;;;N;;;;; 1F0AB;PLAYING CARD JACK OF SPADES;So;0;ON;;;;;N;;;;; 1F0AC;PLAYING CARD KNIGHT OF SPADES;So;0;ON;;;;;N;;;;; 1F0AD;PLAYING CARD QUEEN OF SPADES;So;0;ON;;;;;N;;;;; 1F0AE;PLAYING CARD KING OF SPADES;So;0;ON;;;;;N;;;;; 1F0B1;PLAYING CARD ACE OF HEARTS;So;0;ON;;;;;N;;;;; 1F0B2;PLAYING CARD TWO OF HEARTS;So;0;ON;;;;;N;;;;; 1F0B3;PLAYING CARD THREE OF HEARTS;So;0;ON;;;;;N;;;;; 1F0B4;PLAYING CARD FOUR OF HEARTS;So;0;ON;;;;;N;;;;; 1F0B5;PLAYING CARD FIVE OF HEARTS;So;0;ON;;;;;N;;;;; 1F0B6;PLAYING CARD SIX OF HEARTS;So;0;ON;;;;;N;;;;; 1F0B7;PLAYING CARD SEVEN OF HEARTS;So;0;ON;;;;;N;;;;; 1F0B8;PLAYING CARD EIGHT OF HEARTS;So;0;ON;;;;;N;;;;; 1F0B9;PLAYING CARD NINE OF HEARTS;So;0;ON;;;;;N;;;;; 1F0BA;PLAYING CARD TEN OF HEARTS;So;0;ON;;;;;N;;;;; 1F0BB;PLAYING CARD JACK OF HEARTS;So;0;ON;;;;;N;;;;; 1F0BC;PLAYING CARD KNIGHT OF HEARTS;So;0;ON;;;;;N;;;;; 1F0BD;PLAYING CARD QUEEN OF HEARTS;So;0;ON;;;;;N;;;;; 1F0BE;PLAYING CARD KING OF HEARTS;So;0;ON;;;;;N;;;;; 1F0BF;PLAYING CARD RED JOKER;So;0;ON;;;;;N;;;;; 1F0C1;PLAYING CARD ACE OF DIAMONDS;So;0;ON;;;;;N;;;;; 1F0C2;PLAYING CARD TWO OF DIAMONDS;So;0;ON;;;;;N;;;;; 1F0C3;PLAYING CARD THREE OF DIAMONDS;So;0;ON;;;;;N;;;;; 1F0C4;PLAYING CARD FOUR OF DIAMONDS;So;0;ON;;;;;N;;;;; 1F0C5;PLAYING CARD FIVE OF DIAMONDS;So;0;ON;;;;;N;;;;; 1F0C6;PLAYING CARD SIX OF DIAMONDS;So;0;ON;;;;;N;;;;; 1F0C7;PLAYING CARD SEVEN OF DIAMONDS;So;0;ON;;;;;N;;;;; 1F0C8;PLAYING CARD EIGHT OF DIAMONDS;So;0;ON;;;;;N;;;;; 1F0C9;PLAYING CARD NINE OF DIAMONDS;So;0;ON;;;;;N;;;;; 1F0CA;PLAYING CARD TEN OF DIAMONDS;So;0;ON;;;;;N;;;;; 1F0CB;PLAYING CARD JACK OF DIAMONDS;So;0;ON;;;;;N;;;;; 1F0CC;PLAYING CARD KNIGHT OF DIAMONDS;So;0;ON;;;;;N;;;;; 1F0CD;PLAYING CARD QUEEN OF DIAMONDS;So;0;ON;;;;;N;;;;; 1F0CE;PLAYING CARD KING OF DIAMONDS;So;0;ON;;;;;N;;;;; 1F0CF;PLAYING CARD BLACK JOKER;So;0;ON;;;;;N;;;;; 1F0D1;PLAYING CARD ACE OF CLUBS;So;0;ON;;;;;N;;;;; 1F0D2;PLAYING CARD TWO OF CLUBS;So;0;ON;;;;;N;;;;; 1F0D3;PLAYING CARD THREE OF CLUBS;So;0;ON;;;;;N;;;;; 1F0D4;PLAYING CARD FOUR OF CLUBS;So;0;ON;;;;;N;;;;; 1F0D5;PLAYING CARD FIVE OF CLUBS;So;0;ON;;;;;N;;;;; 1F0D6;PLAYING CARD SIX OF CLUBS;So;0;ON;;;;;N;;;;; 1F0D7;PLAYING CARD SEVEN OF CLUBS;So;0;ON;;;;;N;;;;; 1F0D8;PLAYING CARD EIGHT OF CLUBS;So;0;ON;;;;;N;;;;; 1F0D9;PLAYING CARD NINE OF CLUBS;So;0;ON;;;;;N;;;;; 1F0DA;PLAYING CARD TEN OF CLUBS;So;0;ON;;;;;N;;;;; 1F0DB;PLAYING CARD JACK OF CLUBS;So;0;ON;;;;;N;;;;; 1F0DC;PLAYING CARD KNIGHT OF CLUBS;So;0;ON;;;;;N;;;;; 1F0DD;PLAYING CARD QUEEN OF CLUBS;So;0;ON;;;;;N;;;;; 1F0DE;PLAYING CARD KING OF CLUBS;So;0;ON;;;;;N;;;;; 1F0DF;PLAYING CARD WHITE JOKER;So;0;ON;;;;;N;;;;; 1F0E0;PLAYING CARD FOOL;So;0;ON;;;;;N;;;;; 1F0E1;PLAYING CARD TRUMP-1;So;0;ON;;;;;N;;;;; 1F0E2;PLAYING CARD TRUMP-2;So;0;ON;;;;;N;;;;; 1F0E3;PLAYING CARD TRUMP-3;So;0;ON;;;;;N;;;;; 1F0E4;PLAYING CARD TRUMP-4;So;0;ON;;;;;N;;;;; 1F0E5;PLAYING CARD TRUMP-5;So;0;ON;;;;;N;;;;; 1F0E6;PLAYING CARD TRUMP-6;So;0;ON;;;;;N;;;;; 1F0E7;PLAYING CARD TRUMP-7;So;0;ON;;;;;N;;;;; 1F0E8;PLAYING CARD TRUMP-8;So;0;ON;;;;;N;;;;; 1F0E9;PLAYING CARD TRUMP-9;So;0;ON;;;;;N;;;;; 1F0EA;PLAYING CARD TRUMP-10;So;0;ON;;;;;N;;;;; 1F0EB;PLAYING CARD TRUMP-11;So;0;ON;;;;;N;;;;; 1F0EC;PLAYING CARD TRUMP-12;So;0;ON;;;;;N;;;;; 1F0ED;PLAYING CARD TRUMP-13;So;0;ON;;;;;N;;;;; 1F0EE;PLAYING CARD TRUMP-14;So;0;ON;;;;;N;;;;; 1F0EF;PLAYING CARD TRUMP-15;So;0;ON;;;;;N;;;;; 1F0F0;PLAYING CARD TRUMP-16;So;0;ON;;;;;N;;;;; 1F0F1;PLAYING CARD TRUMP-17;So;0;ON;;;;;N;;;;; 1F0F2;PLAYING CARD TRUMP-18;So;0;ON;;;;;N;;;;; 1F0F3;PLAYING CARD TRUMP-19;So;0;ON;;;;;N;;;;; 1F0F4;PLAYING CARD TRUMP-20;So;0;ON;;;;;N;;;;; 1F0F5;PLAYING CARD TRUMP-21;So;0;ON;;;;;N;;;;; 1F100;DIGIT ZERO FULL STOP;No;0;EN;<compat> 0030 002E;;0;0;N;;;;; 1F101;DIGIT ZERO COMMA;No;0;EN;<compat> 0030 002C;;0;0;N;;;;; 1F102;DIGIT ONE COMMA;No;0;EN;<compat> 0031 002C;;1;1;N;;;;; 1F103;DIGIT TWO COMMA;No;0;EN;<compat> 0032 002C;;2;2;N;;;;; 1F104;DIGIT THREE COMMA;No;0;EN;<compat> 0033 002C;;3;3;N;;;;; 1F105;DIGIT FOUR COMMA;No;0;EN;<compat> 0034 002C;;4;4;N;;;;; 1F106;DIGIT FIVE COMMA;No;0;EN;<compat> 0035 002C;;5;5;N;;;;; 1F107;DIGIT SIX COMMA;No;0;EN;<compat> 0036 002C;;6;6;N;;;;; 1F108;DIGIT SEVEN COMMA;No;0;EN;<compat> 0037 002C;;7;7;N;;;;; 1F109;DIGIT EIGHT COMMA;No;0;EN;<compat> 0038 002C;;8;8;N;;;;; 1F10A;DIGIT NINE COMMA;No;0;EN;<compat> 0039 002C;;9;9;N;;;;; 1F10B;DINGBAT CIRCLED SANS-SERIF DIGIT ZERO;No;0;ON;;;;0;N;;;;; 1F10C;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT ZERO;No;0;ON;;;;0;N;;;;; 1F110;PARENTHESIZED LATIN CAPITAL LETTER A;So;0;L;<compat> 0028 0041 0029;;;;N;;;;; 1F111;PARENTHESIZED LATIN CAPITAL LETTER B;So;0;L;<compat> 0028 0042 0029;;;;N;;;;; 1F112;PARENTHESIZED LATIN CAPITAL LETTER C;So;0;L;<compat> 0028 0043 0029;;;;N;;;;; 1F113;PARENTHESIZED LATIN CAPITAL LETTER D;So;0;L;<compat> 0028 0044 0029;;;;N;;;;; 1F114;PARENTHESIZED LATIN CAPITAL LETTER E;So;0;L;<compat> 0028 0045 0029;;;;N;;;;; 1F115;PARENTHESIZED LATIN CAPITAL LETTER F;So;0;L;<compat> 0028 0046 0029;;;;N;;;;; 1F116;PARENTHESIZED LATIN CAPITAL LETTER G;So;0;L;<compat> 0028 0047 0029;;;;N;;;;; 1F117;PARENTHESIZED LATIN CAPITAL LETTER H;So;0;L;<compat> 0028 0048 0029;;;;N;;;;; 1F118;PARENTHESIZED LATIN CAPITAL LETTER I;So;0;L;<compat> 0028 0049 0029;;;;N;;;;; 1F119;PARENTHESIZED LATIN CAPITAL LETTER J;So;0;L;<compat> 0028 004A 0029;;;;N;;;;; 1F11A;PARENTHESIZED LATIN CAPITAL LETTER K;So;0;L;<compat> 0028 004B 0029;;;;N;;;;; 1F11B;PARENTHESIZED LATIN CAPITAL LETTER L;So;0;L;<compat> 0028 004C 0029;;;;N;;;;; 1F11C;PARENTHESIZED LATIN CAPITAL LETTER M;So;0;L;<compat> 0028 004D 0029;;;;N;;;;; 1F11D;PARENTHESIZED LATIN CAPITAL LETTER N;So;0;L;<compat> 0028 004E 0029;;;;N;;;;; 1F11E;PARENTHESIZED LATIN CAPITAL LETTER O;So;0;L;<compat> 0028 004F 0029;;;;N;;;;; 1F11F;PARENTHESIZED LATIN CAPITAL LETTER P;So;0;L;<compat> 0028 0050 0029;;;;N;;;;; 1F120;PARENTHESIZED LATIN CAPITAL LETTER Q;So;0;L;<compat> 0028 0051 0029;;;;N;;;;; 1F121;PARENTHESIZED LATIN CAPITAL LETTER R;So;0;L;<compat> 0028 0052 0029;;;;N;;;;; 1F122;PARENTHESIZED LATIN CAPITAL LETTER S;So;0;L;<compat> 0028 0053 0029;;;;N;;;;; 1F123;PARENTHESIZED LATIN CAPITAL LETTER T;So;0;L;<compat> 0028 0054 0029;;;;N;;;;; 1F124;PARENTHESIZED LATIN CAPITAL LETTER U;So;0;L;<compat> 0028 0055 0029;;;;N;;;;; 1F125;PARENTHESIZED LATIN CAPITAL LETTER V;So;0;L;<compat> 0028 0056 0029;;;;N;;;;; 1F126;PARENTHESIZED LATIN CAPITAL LETTER W;So;0;L;<compat> 0028 0057 0029;;;;N;;;;; 1F127;PARENTHESIZED LATIN CAPITAL LETTER X;So;0;L;<compat> 0028 0058 0029;;;;N;;;;; 1F128;PARENTHESIZED LATIN CAPITAL LETTER Y;So;0;L;<compat> 0028 0059 0029;;;;N;;;;; 1F129;PARENTHESIZED LATIN CAPITAL LETTER Z;So;0;L;<compat> 0028 005A 0029;;;;N;;;;; 1F12A;TORTOISE SHELL BRACKETED LATIN CAPITAL LETTER S;So;0;L;<compat> 3014 0053 3015;;;;N;;;;; 1F12B;CIRCLED ITALIC LATIN CAPITAL LETTER C;So;0;L;<circle> 0043;;;;N;;;;; 1F12C;CIRCLED ITALIC LATIN CAPITAL LETTER R;So;0;L;<circle> 0052;;;;N;;;;; 1F12D;CIRCLED CD;So;0;L;<circle> 0043 0044;;;;N;;;;; 1F12E;CIRCLED WZ;So;0;L;<circle> 0057 005A;;;;N;;;;; 1F130;SQUARED LATIN CAPITAL LETTER A;So;0;L;<square> 0041;;;;N;;;;; 1F131;SQUARED LATIN CAPITAL LETTER B;So;0;L;<square> 0042;;;;N;;;;; 1F132;SQUARED LATIN CAPITAL LETTER C;So;0;L;<square> 0043;;;;N;;;;; 1F133;SQUARED LATIN CAPITAL LETTER D;So;0;L;<square> 0044;;;;N;;;;; 1F134;SQUARED LATIN CAPITAL LETTER E;So;0;L;<square> 0045;;;;N;;;;; 1F135;SQUARED LATIN CAPITAL LETTER F;So;0;L;<square> 0046;;;;N;;;;; 1F136;SQUARED LATIN CAPITAL LETTER G;So;0;L;<square> 0047;;;;N;;;;; 1F137;SQUARED LATIN CAPITAL LETTER H;So;0;L;<square> 0048;;;;N;;;;; 1F138;SQUARED LATIN CAPITAL LETTER I;So;0;L;<square> 0049;;;;N;;;;; 1F139;SQUARED LATIN CAPITAL LETTER J;So;0;L;<square> 004A;;;;N;;;;; 1F13A;SQUARED LATIN CAPITAL LETTER K;So;0;L;<square> 004B;;;;N;;;;; 1F13B;SQUARED LATIN CAPITAL LETTER L;So;0;L;<square> 004C;;;;N;;;;; 1F13C;SQUARED LATIN CAPITAL LETTER M;So;0;L;<square> 004D;;;;N;;;;; 1F13D;SQUARED LATIN CAPITAL LETTER N;So;0;L;<square> 004E;;;;N;;;;; 1F13E;SQUARED LATIN CAPITAL LETTER O;So;0;L;<square> 004F;;;;N;;;;; 1F13F;SQUARED LATIN CAPITAL LETTER P;So;0;L;<square> 0050;;;;N;;;;; 1F140;SQUARED LATIN CAPITAL LETTER Q;So;0;L;<square> 0051;;;;N;;;;; 1F141;SQUARED LATIN CAPITAL LETTER R;So;0;L;<square> 0052;;;;N;;;;; 1F142;SQUARED LATIN CAPITAL LETTER S;So;0;L;<square> 0053;;;;N;;;;; 1F143;SQUARED LATIN CAPITAL LETTER T;So;0;L;<square> 0054;;;;N;;;;; 1F144;SQUARED LATIN CAPITAL LETTER U;So;0;L;<square> 0055;;;;N;;;;; 1F145;SQUARED LATIN CAPITAL LETTER V;So;0;L;<square> 0056;;;;N;;;;; 1F146;SQUARED LATIN CAPITAL LETTER W;So;0;L;<square> 0057;;;;N;;;;; 1F147;SQUARED LATIN CAPITAL LETTER X;So;0;L;<square> 0058;;;;N;;;;; 1F148;SQUARED LATIN CAPITAL LETTER Y;So;0;L;<square> 0059;;;;N;;;;; 1F149;SQUARED LATIN CAPITAL LETTER Z;So;0;L;<square> 005A;;;;N;;;;; 1F14A;SQUARED HV;So;0;L;<square> 0048 0056;;;;N;;;;; 1F14B;SQUARED MV;So;0;L;<square> 004D 0056;;;;N;;;;; 1F14C;SQUARED SD;So;0;L;<square> 0053 0044;;;;N;;;;; 1F14D;SQUARED SS;So;0;L;<square> 0053 0053;;;;N;;;;; 1F14E;SQUARED PPV;So;0;L;<square> 0050 0050 0056;;;;N;;;;; 1F14F;SQUARED WC;So;0;L;<square> 0057 0043;;;;N;;;;; 1F150;NEGATIVE CIRCLED LATIN CAPITAL LETTER A;So;0;L;;;;;N;;;;; 1F151;NEGATIVE CIRCLED LATIN CAPITAL LETTER B;So;0;L;;;;;N;;;;; 1F152;NEGATIVE CIRCLED LATIN CAPITAL LETTER C;So;0;L;;;;;N;;;;; 1F153;NEGATIVE CIRCLED LATIN CAPITAL LETTER D;So;0;L;;;;;N;;;;; 1F154;NEGATIVE CIRCLED LATIN CAPITAL LETTER E;So;0;L;;;;;N;;;;; 1F155;NEGATIVE CIRCLED LATIN CAPITAL LETTER F;So;0;L;;;;;N;;;;; 1F156;NEGATIVE CIRCLED LATIN CAPITAL LETTER G;So;0;L;;;;;N;;;;; 1F157;NEGATIVE CIRCLED LATIN CAPITAL LETTER H;So;0;L;;;;;N;;;;; 1F158;NEGATIVE CIRCLED LATIN CAPITAL LETTER I;So;0;L;;;;;N;;;;; 1F159;NEGATIVE CIRCLED LATIN CAPITAL LETTER J;So;0;L;;;;;N;;;;; 1F15A;NEGATIVE CIRCLED LATIN CAPITAL LETTER K;So;0;L;;;;;N;;;;; 1F15B;NEGATIVE CIRCLED LATIN CAPITAL LETTER L;So;0;L;;;;;N;;;;; 1F15C;NEGATIVE CIRCLED LATIN CAPITAL LETTER M;So;0;L;;;;;N;;;;; 1F15D;NEGATIVE CIRCLED LATIN CAPITAL LETTER N;So;0;L;;;;;N;;;;; 1F15E;NEGATIVE CIRCLED LATIN CAPITAL LETTER O;So;0;L;;;;;N;;;;; 1F15F;NEGATIVE CIRCLED LATIN CAPITAL LETTER P;So;0;L;;;;;N;;;;; 1F160;NEGATIVE CIRCLED LATIN CAPITAL LETTER Q;So;0;L;;;;;N;;;;; 1F161;NEGATIVE CIRCLED LATIN CAPITAL LETTER R;So;0;L;;;;;N;;;;; 1F162;NEGATIVE CIRCLED LATIN CAPITAL LETTER S;So;0;L;;;;;N;;;;; 1F163;NEGATIVE CIRCLED LATIN CAPITAL LETTER T;So;0;L;;;;;N;;;;; 1F164;NEGATIVE CIRCLED LATIN CAPITAL LETTER U;So;0;L;;;;;N;;;;; 1F165;NEGATIVE CIRCLED LATIN CAPITAL LETTER V;So;0;L;;;;;N;;;;; 1F166;NEGATIVE CIRCLED LATIN CAPITAL LETTER W;So;0;L;;;;;N;;;;; 1F167;NEGATIVE CIRCLED LATIN CAPITAL LETTER X;So;0;L;;;;;N;;;;; 1F168;NEGATIVE CIRCLED LATIN CAPITAL LETTER Y;So;0;L;;;;;N;;;;; 1F169;NEGATIVE CIRCLED LATIN CAPITAL LETTER Z;So;0;L;;;;;N;;;;; 1F16A;RAISED MC SIGN;So;0;ON;<super> 004D 0043;;;;N;;;;; 1F16B;RAISED MD SIGN;So;0;ON;<super> 004D 0044;;;;N;;;;; 1F170;NEGATIVE SQUARED LATIN CAPITAL LETTER A;So;0;L;;;;;N;;;;; 1F171;NEGATIVE SQUARED LATIN CAPITAL LETTER B;So;0;L;;;;;N;;;;; 1F172;NEGATIVE SQUARED LATIN CAPITAL LETTER C;So;0;L;;;;;N;;;;; 1F173;NEGATIVE SQUARED LATIN CAPITAL LETTER D;So;0;L;;;;;N;;;;; 1F174;NEGATIVE SQUARED LATIN CAPITAL LETTER E;So;0;L;;;;;N;;;;; 1F175;NEGATIVE SQUARED LATIN CAPITAL LETTER F;So;0;L;;;;;N;;;;; 1F176;NEGATIVE SQUARED LATIN CAPITAL LETTER G;So;0;L;;;;;N;;;;; 1F177;NEGATIVE SQUARED LATIN CAPITAL LETTER H;So;0;L;;;;;N;;;;; 1F178;NEGATIVE SQUARED LATIN CAPITAL LETTER I;So;0;L;;;;;N;;;;; 1F179;NEGATIVE SQUARED LATIN CAPITAL LETTER J;So;0;L;;;;;N;;;;; 1F17A;NEGATIVE SQUARED LATIN CAPITAL LETTER K;So;0;L;;;;;N;;;;; 1F17B;NEGATIVE SQUARED LATIN CAPITAL LETTER L;So;0;L;;;;;N;;;;; 1F17C;NEGATIVE SQUARED LATIN CAPITAL LETTER M;So;0;L;;;;;N;;;;; 1F17D;NEGATIVE SQUARED LATIN CAPITAL LETTER N;So;0;L;;;;;N;;;;; 1F17E;NEGATIVE SQUARED LATIN CAPITAL LETTER O;So;0;L;;;;;N;;;;; 1F17F;NEGATIVE SQUARED LATIN CAPITAL LETTER P;So;0;L;;;;;N;;;;; 1F180;NEGATIVE SQUARED LATIN CAPITAL LETTER Q;So;0;L;;;;;N;;;;; 1F181;NEGATIVE SQUARED LATIN CAPITAL LETTER R;So;0;L;;;;;N;;;;; 1F182;NEGATIVE SQUARED LATIN CAPITAL LETTER S;So;0;L;;;;;N;;;;; 1F183;NEGATIVE SQUARED LATIN CAPITAL LETTER T;So;0;L;;;;;N;;;;; 1F184;NEGATIVE SQUARED LATIN CAPITAL LETTER U;So;0;L;;;;;N;;;;; 1F185;NEGATIVE SQUARED LATIN CAPITAL LETTER V;So;0;L;;;;;N;;;;; 1F186;NEGATIVE SQUARED LATIN CAPITAL LETTER W;So;0;L;;;;;N;;;;; 1F187;NEGATIVE SQUARED LATIN CAPITAL LETTER X;So;0;L;;;;;N;;;;; 1F188;NEGATIVE SQUARED LATIN CAPITAL LETTER Y;So;0;L;;;;;N;;;;; 1F189;NEGATIVE SQUARED LATIN CAPITAL LETTER Z;So;0;L;;;;;N;;;;; 1F18A;CROSSED NEGATIVE SQUARED LATIN CAPITAL LETTER P;So;0;L;;;;;N;;;;; 1F18B;NEGATIVE SQUARED IC;So;0;L;;;;;N;;;;; 1F18C;NEGATIVE SQUARED PA;So;0;L;;;;;N;;;;; 1F18D;NEGATIVE SQUARED SA;So;0;L;;;;;N;;;;; 1F18E;NEGATIVE SQUARED AB;So;0;L;;;;;N;;;;; 1F18F;NEGATIVE SQUARED WC;So;0;L;;;;;N;;;;; 1F190;SQUARE DJ;So;0;L;<square> 0044 004A;;;;N;;;;; 1F191;SQUARED CL;So;0;L;;;;;N;;;;; 1F192;SQUARED COOL;So;0;L;;;;;N;;;;; 1F193;SQUARED FREE;So;0;L;;;;;N;;;;; 1F194;SQUARED ID;So;0;L;;;;;N;;;;; 1F195;SQUARED NEW;So;0;L;;;;;N;;;;; 1F196;SQUARED NG;So;0;L;;;;;N;;;;; 1F197;SQUARED OK;So;0;L;;;;;N;;;;; 1F198;SQUARED SOS;So;0;L;;;;;N;;;;; 1F199;SQUARED UP WITH EXCLAMATION MARK;So;0;L;;;;;N;;;;; 1F19A;SQUARED VS;So;0;L;;;;;N;;;;; 1F19B;SQUARED THREE D;So;0;L;;;;;N;;;;; 1F19C;SQUARED SECOND SCREEN;So;0;L;;;;;N;;;;; 1F19D;SQUARED TWO K;So;0;L;;;;;N;;;;; 1F19E;SQUARED FOUR K;So;0;L;;;;;N;;;;; 1F19F;SQUARED EIGHT K;So;0;L;;;;;N;;;;; 1F1A0;SQUARED FIVE POINT ONE;So;0;L;;;;;N;;;;; 1F1A1;SQUARED SEVEN POINT ONE;So;0;L;;;;;N;;;;; 1F1A2;SQUARED TWENTY-TWO POINT TWO;So;0;L;;;;;N;;;;; 1F1A3;SQUARED SIXTY P;So;0;L;;;;;N;;;;; 1F1A4;SQUARED ONE HUNDRED TWENTY P;So;0;L;;;;;N;;;;; 1F1A5;SQUARED LATIN SMALL LETTER D;So;0;L;;;;;N;;;;; 1F1A6;SQUARED HC;So;0;L;;;;;N;;;;; 1F1A7;SQUARED HDR;So;0;L;;;;;N;;;;; 1F1A8;SQUARED HI-RES;So;0;L;;;;;N;;;;; 1F1A9;SQUARED LOSSLESS;So;0;L;;;;;N;;;;; 1F1AA;SQUARED SHV;So;0;L;;;;;N;;;;; 1F1AB;SQUARED UHD;So;0;L;;;;;N;;;;; 1F1AC;SQUARED VOD;So;0;L;;;;;N;;;;; 1F1E6;REGIONAL INDICATOR SYMBOL LETTER A;So;0;L;;;;;N;;;;; 1F1E7;REGIONAL INDICATOR SYMBOL LETTER B;So;0;L;;;;;N;;;;; 1F1E8;REGIONAL INDICATOR SYMBOL LETTER C;So;0;L;;;;;N;;;;; 1F1E9;REGIONAL INDICATOR SYMBOL LETTER D;So;0;L;;;;;N;;;;; 1F1EA;REGIONAL INDICATOR SYMBOL LETTER E;So;0;L;;;;;N;;;;; 1F1EB;REGIONAL INDICATOR SYMBOL LETTER F;So;0;L;;;;;N;;;;; 1F1EC;REGIONAL INDICATOR SYMBOL LETTER G;So;0;L;;;;;N;;;;; 1F1ED;REGIONAL INDICATOR SYMBOL LETTER H;So;0;L;;;;;N;;;;; 1F1EE;REGIONAL INDICATOR SYMBOL LETTER I;So;0;L;;;;;N;;;;; 1F1EF;REGIONAL INDICATOR SYMBOL LETTER J;So;0;L;;;;;N;;;;; 1F1F0;REGIONAL INDICATOR SYMBOL LETTER K;So;0;L;;;;;N;;;;; 1F1F1;REGIONAL INDICATOR SYMBOL LETTER L;So;0;L;;;;;N;;;;; 1F1F2;REGIONAL INDICATOR SYMBOL LETTER M;So;0;L;;;;;N;;;;; 1F1F3;REGIONAL INDICATOR SYMBOL LETTER N;So;0;L;;;;;N;;;;; 1F1F4;REGIONAL INDICATOR SYMBOL LETTER O;So;0;L;;;;;N;;;;; 1F1F5;REGIONAL INDICATOR SYMBOL LETTER P;So;0;L;;;;;N;;;;; 1F1F6;REGIONAL INDICATOR SYMBOL LETTER Q;So;0;L;;;;;N;;;;; 1F1F7;REGIONAL INDICATOR SYMBOL LETTER R;So;0;L;;;;;N;;;;; 1F1F8;REGIONAL INDICATOR SYMBOL LETTER S;So;0;L;;;;;N;;;;; 1F1F9;REGIONAL INDICATOR SYMBOL LETTER T;So;0;L;;;;;N;;;;; 1F1FA;REGIONAL INDICATOR SYMBOL LETTER U;So;0;L;;;;;N;;;;; 1F1FB;REGIONAL INDICATOR SYMBOL LETTER V;So;0;L;;;;;N;;;;; 1F1FC;REGIONAL INDICATOR SYMBOL LETTER W;So;0;L;;;;;N;;;;; 1F1FD;REGIONAL INDICATOR SYMBOL LETTER X;So;0;L;;;;;N;;;;; 1F1FE;REGIONAL INDICATOR SYMBOL LETTER Y;So;0;L;;;;;N;;;;; 1F1FF;REGIONAL INDICATOR SYMBOL LETTER Z;So;0;L;;;;;N;;;;; 1F200;SQUARE HIRAGANA HOKA;So;0;L;<square> 307B 304B;;;;N;;;;; 1F201;SQUARED KATAKANA KOKO;So;0;L;<square> 30B3 30B3;;;;N;;;;; 1F202;SQUARED KATAKANA SA;So;0;L;<square> 30B5;;;;N;;;;; 1F210;SQUARED CJK UNIFIED IDEOGRAPH-624B;So;0;L;<square> 624B;;;;N;;;;; 1F211;SQUARED CJK UNIFIED IDEOGRAPH-5B57;So;0;L;<square> 5B57;;;;N;;;;; 1F212;SQUARED CJK UNIFIED IDEOGRAPH-53CC;So;0;L;<square> 53CC;;;;N;;;;; 1F213;SQUARED KATAKANA DE;So;0;L;<square> 30C7;;;;N;;;;; 1F214;SQUARED CJK UNIFIED IDEOGRAPH-4E8C;So;0;L;<square> 4E8C;;;;N;;;;; 1F215;SQUARED CJK UNIFIED IDEOGRAPH-591A;So;0;L;<square> 591A;;;;N;;;;; 1F216;SQUARED CJK UNIFIED IDEOGRAPH-89E3;So;0;L;<square> 89E3;;;;N;;;;; 1F217;SQUARED CJK UNIFIED IDEOGRAPH-5929;So;0;L;<square> 5929;;;;N;;;;; 1F218;SQUARED CJK UNIFIED IDEOGRAPH-4EA4;So;0;L;<square> 4EA4;;;;N;;;;; 1F219;SQUARED CJK UNIFIED IDEOGRAPH-6620;So;0;L;<square> 6620;;;;N;;;;; 1F21A;SQUARED CJK UNIFIED IDEOGRAPH-7121;So;0;L;<square> 7121;;;;N;;;;; 1F21B;SQUARED CJK UNIFIED IDEOGRAPH-6599;So;0;L;<square> 6599;;;;N;;;;; 1F21C;SQUARED CJK UNIFIED IDEOGRAPH-524D;So;0;L;<square> 524D;;;;N;;;;; 1F21D;SQUARED CJK UNIFIED IDEOGRAPH-5F8C;So;0;L;<square> 5F8C;;;;N;;;;; 1F21E;SQUARED CJK UNIFIED IDEOGRAPH-518D;So;0;L;<square> 518D;;;;N;;;;; 1F21F;SQUARED CJK UNIFIED IDEOGRAPH-65B0;So;0;L;<square> 65B0;;;;N;;;;; 1F220;SQUARED CJK UNIFIED IDEOGRAPH-521D;So;0;L;<square> 521D;;;;N;;;;; 1F221;SQUARED CJK UNIFIED IDEOGRAPH-7D42;So;0;L;<square> 7D42;;;;N;;;;; 1F222;SQUARED CJK UNIFIED IDEOGRAPH-751F;So;0;L;<square> 751F;;;;N;;;;; 1F223;SQUARED CJK UNIFIED IDEOGRAPH-8CA9;So;0;L;<square> 8CA9;;;;N;;;;; 1F224;SQUARED CJK UNIFIED IDEOGRAPH-58F0;So;0;L;<square> 58F0;;;;N;;;;; 1F225;SQUARED CJK UNIFIED IDEOGRAPH-5439;So;0;L;<square> 5439;;;;N;;;;; 1F226;SQUARED CJK UNIFIED IDEOGRAPH-6F14;So;0;L;<square> 6F14;;;;N;;;;; 1F227;SQUARED CJK UNIFIED IDEOGRAPH-6295;So;0;L;<square> 6295;;;;N;;;;; 1F228;SQUARED CJK UNIFIED IDEOGRAPH-6355;So;0;L;<square> 6355;;;;N;;;;; 1F229;SQUARED CJK UNIFIED IDEOGRAPH-4E00;So;0;L;<square> 4E00;;;;N;;;;; 1F22A;SQUARED CJK UNIFIED IDEOGRAPH-4E09;So;0;L;<square> 4E09;;;;N;;;;; 1F22B;SQUARED CJK UNIFIED IDEOGRAPH-904A;So;0;L;<square> 904A;;;;N;;;;; 1F22C;SQUARED CJK UNIFIED IDEOGRAPH-5DE6;So;0;L;<square> 5DE6;;;;N;;;;; 1F22D;SQUARED CJK UNIFIED IDEOGRAPH-4E2D;So;0;L;<square> 4E2D;;;;N;;;;; 1F22E;SQUARED CJK UNIFIED IDEOGRAPH-53F3;So;0;L;<square> 53F3;;;;N;;;;; 1F22F;SQUARED CJK UNIFIED IDEOGRAPH-6307;So;0;L;<square> 6307;;;;N;;;;; 1F230;SQUARED CJK UNIFIED IDEOGRAPH-8D70;So;0;L;<square> 8D70;;;;N;;;;; 1F231;SQUARED CJK UNIFIED IDEOGRAPH-6253;So;0;L;<square> 6253;;;;N;;;;; 1F232;SQUARED CJK UNIFIED IDEOGRAPH-7981;So;0;L;<square> 7981;;;;N;;;;; 1F233;SQUARED CJK UNIFIED IDEOGRAPH-7A7A;So;0;L;<square> 7A7A;;;;N;;;;; 1F234;SQUARED CJK UNIFIED IDEOGRAPH-5408;So;0;L;<square> 5408;;;;N;;;;; 1F235;SQUARED CJK UNIFIED IDEOGRAPH-6E80;So;0;L;<square> 6E80;;;;N;;;;; 1F236;SQUARED CJK UNIFIED IDEOGRAPH-6709;So;0;L;<square> 6709;;;;N;;;;; 1F237;SQUARED CJK UNIFIED IDEOGRAPH-6708;So;0;L;<square> 6708;;;;N;;;;; 1F238;SQUARED CJK UNIFIED IDEOGRAPH-7533;So;0;L;<square> 7533;;;;N;;;;; 1F239;SQUARED CJK UNIFIED IDEOGRAPH-5272;So;0;L;<square> 5272;;;;N;;;;; 1F23A;SQUARED CJK UNIFIED IDEOGRAPH-55B6;So;0;L;<square> 55B6;;;;N;;;;; 1F23B;SQUARED CJK UNIFIED IDEOGRAPH-914D;So;0;L;<square> 914D;;;;N;;;;; 1F240;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-672C;So;0;L;<compat> 3014 672C 3015;;;;N;;;;; 1F241;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-4E09;So;0;L;<compat> 3014 4E09 3015;;;;N;;;;; 1F242;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-4E8C;So;0;L;<compat> 3014 4E8C 3015;;;;N;;;;; 1F243;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-5B89;So;0;L;<compat> 3014 5B89 3015;;;;N;;;;; 1F244;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-70B9;So;0;L;<compat> 3014 70B9 3015;;;;N;;;;; 1F245;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-6253;So;0;L;<compat> 3014 6253 3015;;;;N;;;;; 1F246;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-76D7;So;0;L;<compat> 3014 76D7 3015;;;;N;;;;; 1F247;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-52DD;So;0;L;<compat> 3014 52DD 3015;;;;N;;;;; 1F248;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-6557;So;0;L;<compat> 3014 6557 3015;;;;N;;;;; 1F250;CIRCLED IDEOGRAPH ADVANTAGE;So;0;L;<circle> 5F97;;;;N;;;;; 1F251;CIRCLED IDEOGRAPH ACCEPT;So;0;L;<circle> 53EF;;;;N;;;;; 1F300;CYCLONE;So;0;ON;;;;;N;;;;; 1F301;FOGGY;So;0;ON;;;;;N;;;;; 1F302;CLOSED UMBRELLA;So;0;ON;;;;;N;;;;; 1F303;NIGHT WITH STARS;So;0;ON;;;;;N;;;;; 1F304;SUNRISE OVER MOUNTAINS;So;0;ON;;;;;N;;;;; 1F305;SUNRISE;So;0;ON;;;;;N;;;;; 1F306;CITYSCAPE AT DUSK;So;0;ON;;;;;N;;;;; 1F307;SUNSET OVER BUILDINGS;So;0;ON;;;;;N;;;;; 1F308;RAINBOW;So;0;ON;;;;;N;;;;; 1F309;BRIDGE AT NIGHT;So;0;ON;;;;;N;;;;; 1F30A;WATER WAVE;So;0;ON;;;;;N;;;;; 1F30B;VOLCANO;So;0;ON;;;;;N;;;;; 1F30C;MILKY WAY;So;0;ON;;;;;N;;;;; 1F30D;EARTH GLOBE EUROPE-AFRICA;So;0;ON;;;;;N;;;;; 1F30E;EARTH GLOBE AMERICAS;So;0;ON;;;;;N;;;;; 1F30F;EARTH GLOBE ASIA-AUSTRALIA;So;0;ON;;;;;N;;;;; 1F310;GLOBE WITH MERIDIANS;So;0;ON;;;;;N;;;;; 1F311;NEW MOON SYMBOL;So;0;ON;;;;;N;;;;; 1F312;WAXING CRESCENT MOON SYMBOL;So;0;ON;;;;;N;;;;; 1F313;FIRST QUARTER MOON SYMBOL;So;0;ON;;;;;N;;;;; 1F314;WAXING GIBBOUS MOON SYMBOL;So;0;ON;;;;;N;;;;; 1F315;FULL MOON SYMBOL;So;0;ON;;;;;N;;;;; 1F316;WANING GIBBOUS MOON SYMBOL;So;0;ON;;;;;N;;;;; 1F317;LAST QUARTER MOON SYMBOL;So;0;ON;;;;;N;;;;; 1F318;WANING CRESCENT MOON SYMBOL;So;0;ON;;;;;N;;;;; 1F319;CRESCENT MOON;So;0;ON;;;;;N;;;;; 1F31A;NEW MOON WITH FACE;So;0;ON;;;;;N;;;;; 1F31B;FIRST QUARTER MOON WITH FACE;So;0;ON;;;;;N;;;;; 1F31C;LAST QUARTER MOON WITH FACE;So;0;ON;;;;;N;;;;; 1F31D;FULL MOON WITH FACE;So;0;ON;;;;;N;;;;; 1F31E;SUN WITH FACE;So;0;ON;;;;;N;;;;; 1F31F;GLOWING STAR;So;0;ON;;;;;N;;;;; 1F320;SHOOTING STAR;So;0;ON;;;;;N;;;;; 1F321;THERMOMETER;So;0;ON;;;;;N;;;;; 1F322;BLACK DROPLET;So;0;ON;;;;;N;;;;; 1F323;WHITE SUN;So;0;ON;;;;;N;;;;; 1F324;WHITE SUN WITH SMALL CLOUD;So;0;ON;;;;;N;;;;; 1F325;WHITE SUN BEHIND CLOUD;So;0;ON;;;;;N;;;;; 1F326;WHITE SUN BEHIND CLOUD WITH RAIN;So;0;ON;;;;;N;;;;; 1F327;CLOUD WITH RAIN;So;0;ON;;;;;N;;;;; 1F328;CLOUD WITH SNOW;So;0;ON;;;;;N;;;;; 1F329;CLOUD WITH LIGHTNING;So;0;ON;;;;;N;;;;; 1F32A;CLOUD WITH TORNADO;So;0;ON;;;;;N;;;;; 1F32B;FOG;So;0;ON;;;;;N;;;;; 1F32C;WIND BLOWING FACE;So;0;ON;;;;;N;;;;; 1F32D;HOT DOG;So;0;ON;;;;;N;;;;; 1F32E;TACO;So;0;ON;;;;;N;;;;; 1F32F;BURRITO;So;0;ON;;;;;N;;;;; 1F330;CHESTNUT;So;0;ON;;;;;N;;;;; 1F331;SEEDLING;So;0;ON;;;;;N;;;;; 1F332;EVERGREEN TREE;So;0;ON;;;;;N;;;;; 1F333;DECIDUOUS TREE;So;0;ON;;;;;N;;;;; 1F334;PALM TREE;So;0;ON;;;;;N;;;;; 1F335;CACTUS;So;0;ON;;;;;N;;;;; 1F336;HOT PEPPER;So;0;ON;;;;;N;;;;; 1F337;TULIP;So;0;ON;;;;;N;;;;; 1F338;CHERRY BLOSSOM;So;0;ON;;;;;N;;;;; 1F339;ROSE;So;0;ON;;;;;N;;;;; 1F33A;HIBISCUS;So;0;ON;;;;;N;;;;; 1F33B;SUNFLOWER;So;0;ON;;;;;N;;;;; 1F33C;BLOSSOM;So;0;ON;;;;;N;;;;; 1F33D;EAR OF MAIZE;So;0;ON;;;;;N;;;;; 1F33E;EAR OF RICE;So;0;ON;;;;;N;;;;; 1F33F;HERB;So;0;ON;;;;;N;;;;; 1F340;FOUR LEAF CLOVER;So;0;ON;;;;;N;;;;; 1F341;MAPLE LEAF;So;0;ON;;;;;N;;;;; 1F342;FALLEN LEAF;So;0;ON;;;;;N;;;;; 1F343;LEAF FLUTTERING IN WIND;So;0;ON;;;;;N;;;;; 1F344;MUSHROOM;So;0;ON;;;;;N;;;;; 1F345;TOMATO;So;0;ON;;;;;N;;;;; 1F346;AUBERGINE;So;0;ON;;;;;N;;;;; 1F347;GRAPES;So;0;ON;;;;;N;;;;; 1F348;MELON;So;0;ON;;;;;N;;;;; 1F349;WATERMELON;So;0;ON;;;;;N;;;;; 1F34A;TANGERINE;So;0;ON;;;;;N;;;;; 1F34B;LEMON;So;0;ON;;;;;N;;;;; 1F34C;BANANA;So;0;ON;;;;;N;;;;; 1F34D;PINEAPPLE;So;0;ON;;;;;N;;;;; 1F34E;RED APPLE;So;0;ON;;;;;N;;;;; 1F34F;GREEN APPLE;So;0;ON;;;;;N;;;;; 1F350;PEAR;So;0;ON;;;;;N;;;;; 1F351;PEACH;So;0;ON;;;;;N;;;;; 1F352;CHERRIES;So;0;ON;;;;;N;;;;; 1F353;STRAWBERRY;So;0;ON;;;;;N;;;;; 1F354;HAMBURGER;So;0;ON;;;;;N;;;;; 1F355;SLICE OF PIZZA;So;0;ON;;;;;N;;;;; 1F356;MEAT ON BONE;So;0;ON;;;;;N;;;;; 1F357;POULTRY LEG;So;0;ON;;;;;N;;;;; 1F358;RICE CRACKER;So;0;ON;;;;;N;;;;; 1F359;RICE BALL;So;0;ON;;;;;N;;;;; 1F35A;COOKED RICE;So;0;ON;;;;;N;;;;; 1F35B;CURRY AND RICE;So;0;ON;;;;;N;;;;; 1F35C;STEAMING BOWL;So;0;ON;;;;;N;;;;; 1F35D;SPAGHETTI;So;0;ON;;;;;N;;;;; 1F35E;BREAD;So;0;ON;;;;;N;;;;; 1F35F;FRENCH FRIES;So;0;ON;;;;;N;;;;; 1F360;ROASTED SWEET POTATO;So;0;ON;;;;;N;;;;; 1F361;DANGO;So;0;ON;;;;;N;;;;; 1F362;ODEN;So;0;ON;;;;;N;;;;; 1F363;SUSHI;So;0;ON;;;;;N;;;;; 1F364;FRIED SHRIMP;So;0;ON;;;;;N;;;;; 1F365;FISH CAKE WITH SWIRL DESIGN;So;0;ON;;;;;N;;;;; 1F366;SOFT ICE CREAM;So;0;ON;;;;;N;;;;; 1F367;SHAVED ICE;So;0;ON;;;;;N;;;;; 1F368;ICE CREAM;So;0;ON;;;;;N;;;;; 1F369;DOUGHNUT;So;0;ON;;;;;N;;;;; 1F36A;COOKIE;So;0;ON;;;;;N;;;;; 1F36B;CHOCOLATE BAR;So;0;ON;;;;;N;;;;; 1F36C;CANDY;So;0;ON;;;;;N;;;;; 1F36D;LOLLIPOP;So;0;ON;;;;;N;;;;; 1F36E;CUSTARD;So;0;ON;;;;;N;;;;; 1F36F;HONEY POT;So;0;ON;;;;;N;;;;; 1F370;SHORTCAKE;So;0;ON;;;;;N;;;;; 1F371;BENTO BOX;So;0;ON;;;;;N;;;;; 1F372;POT OF FOOD;So;0;ON;;;;;N;;;;; 1F373;COOKING;So;0;ON;;;;;N;;;;; 1F374;FORK AND KNIFE;So;0;ON;;;;;N;;;;; 1F375;TEACUP WITHOUT HANDLE;So;0;ON;;;;;N;;;;; 1F376;SAKE BOTTLE AND CUP;So;0;ON;;;;;N;;;;; 1F377;WINE GLASS;So;0;ON;;;;;N;;;;; 1F378;COCKTAIL GLASS;So;0;ON;;;;;N;;;;; 1F379;TROPICAL DRINK;So;0;ON;;;;;N;;;;; 1F37A;BEER MUG;So;0;ON;;;;;N;;;;; 1F37B;CLINKING BEER MUGS;So;0;ON;;;;;N;;;;; 1F37C;BABY BOTTLE;So;0;ON;;;;;N;;;;; 1F37D;FORK AND KNIFE WITH PLATE;So;0;ON;;;;;N;;;;; 1F37E;BOTTLE WITH POPPING CORK;So;0;ON;;;;;N;;;;; 1F37F;POPCORN;So;0;ON;;;;;N;;;;; 1F380;RIBBON;So;0;ON;;;;;N;;;;; 1F381;WRAPPED PRESENT;So;0;ON;;;;;N;;;;; 1F382;BIRTHDAY CAKE;So;0;ON;;;;;N;;;;; 1F383;JACK-O-LANTERN;So;0;ON;;;;;N;;;;; 1F384;CHRISTMAS TREE;So;0;ON;;;;;N;;;;; 1F385;FATHER CHRISTMAS;So;0;ON;;;;;N;;;;; 1F386;FIREWORKS;So;0;ON;;;;;N;;;;; 1F387;FIREWORK SPARKLER;So;0;ON;;;;;N;;;;; 1F388;BALLOON;So;0;ON;;;;;N;;;;; 1F389;PARTY POPPER;So;0;ON;;;;;N;;;;; 1F38A;CONFETTI BALL;So;0;ON;;;;;N;;;;; 1F38B;TANABATA TREE;So;0;ON;;;;;N;;;;; 1F38C;CROSSED FLAGS;So;0;ON;;;;;N;;;;; 1F38D;PINE DECORATION;So;0;ON;;;;;N;;;;; 1F38E;JAPANESE DOLLS;So;0;ON;;;;;N;;;;; 1F38F;CARP STREAMER;So;0;ON;;;;;N;;;;; 1F390;WIND CHIME;So;0;ON;;;;;N;;;;; 1F391;MOON VIEWING CEREMONY;So;0;ON;;;;;N;;;;; 1F392;SCHOOL SATCHEL;So;0;ON;;;;;N;;;;; 1F393;GRADUATION CAP;So;0;ON;;;;;N;;;;; 1F394;HEART WITH TIP ON THE LEFT;So;0;ON;;;;;N;;;;; 1F395;BOUQUET OF FLOWERS;So;0;ON;;;;;N;;;;; 1F396;MILITARY MEDAL;So;0;ON;;;;;N;;;;; 1F397;REMINDER RIBBON;So;0;ON;;;;;N;;;;; 1F398;MUSICAL KEYBOARD WITH JACKS;So;0;ON;;;;;N;;;;; 1F399;STUDIO MICROPHONE;So;0;ON;;;;;N;;;;; 1F39A;LEVEL SLIDER;So;0;ON;;;;;N;;;;; 1F39B;CONTROL KNOBS;So;0;ON;;;;;N;;;;; 1F39C;BEAMED ASCENDING MUSICAL NOTES;So;0;ON;;;;;N;;;;; 1F39D;BEAMED DESCENDING MUSICAL NOTES;So;0;ON;;;;;N;;;;; 1F39E;FILM FRAMES;So;0;ON;;;;;N;;;;; 1F39F;ADMISSION TICKETS;So;0;ON;;;;;N;;;;; 1F3A0;CAROUSEL HORSE;So;0;ON;;;;;N;;;;; 1F3A1;FERRIS WHEEL;So;0;ON;;;;;N;;;;; 1F3A2;ROLLER COASTER;So;0;ON;;;;;N;;;;; 1F3A3;FISHING POLE AND FISH;So;0;ON;;;;;N;;;;; 1F3A4;MICROPHONE;So;0;ON;;;;;N;;;;; 1F3A5;MOVIE CAMERA;So;0;ON;;;;;N;;;;; 1F3A6;CINEMA;So;0;ON;;;;;N;;;;; 1F3A7;HEADPHONE;So;0;ON;;;;;N;;;;; 1F3A8;ARTIST PALETTE;So;0;ON;;;;;N;;;;; 1F3A9;TOP HAT;So;0;ON;;;;;N;;;;; 1F3AA;CIRCUS TENT;So;0;ON;;;;;N;;;;; 1F3AB;TICKET;So;0;ON;;;;;N;;;;; 1F3AC;CLAPPER BOARD;So;0;ON;;;;;N;;;;; 1F3AD;PERFORMING ARTS;So;0;ON;;;;;N;;;;; 1F3AE;VIDEO GAME;So;0;ON;;;;;N;;;;; 1F3AF;DIRECT HIT;So;0;ON;;;;;N;;;;; 1F3B0;SLOT MACHINE;So;0;ON;;;;;N;;;;; 1F3B1;BILLIARDS;So;0;ON;;;;;N;;;;; 1F3B2;GAME DIE;So;0;ON;;;;;N;;;;; 1F3B3;BOWLING;So;0;ON;;;;;N;;;;; 1F3B4;FLOWER PLAYING CARDS;So;0;ON;;;;;N;;;;; 1F3B5;MUSICAL NOTE;So;0;ON;;;;;N;;;;; 1F3B6;MULTIPLE MUSICAL NOTES;So;0;ON;;;;;N;;;;; 1F3B7;SAXOPHONE;So;0;ON;;;;;N;;;;; 1F3B8;GUITAR;So;0;ON;;;;;N;;;;; 1F3B9;MUSICAL KEYBOARD;So;0;ON;;;;;N;;;;; 1F3BA;TRUMPET;So;0;ON;;;;;N;;;;; 1F3BB;VIOLIN;So;0;ON;;;;;N;;;;; 1F3BC;MUSICAL SCORE;So;0;ON;;;;;N;;;;; 1F3BD;RUNNING SHIRT WITH SASH;So;0;ON;;;;;N;;;;; 1F3BE;TENNIS RACQUET AND BALL;So;0;ON;;;;;N;;;;; 1F3BF;SKI AND SKI BOOT;So;0;ON;;;;;N;;;;; 1F3C0;BASKETBALL AND HOOP;So;0;ON;;;;;N;;;;; 1F3C1;CHEQUERED FLAG;So;0;ON;;;;;N;;;;; 1F3C2;SNOWBOARDER;So;0;ON;;;;;N;;;;; 1F3C3;RUNNER;So;0;ON;;;;;N;;;;; 1F3C4;SURFER;So;0;ON;;;;;N;;;;; 1F3C5;SPORTS MEDAL;So;0;ON;;;;;N;;;;; 1F3C6;TROPHY;So;0;ON;;;;;N;;;;; 1F3C7;HORSE RACING;So;0;ON;;;;;N;;;;; 1F3C8;AMERICAN FOOTBALL;So;0;ON;;;;;N;;;;; 1F3C9;RUGBY FOOTBALL;So;0;ON;;;;;N;;;;; 1F3CA;SWIMMER;So;0;ON;;;;;N;;;;; 1F3CB;WEIGHT LIFTER;So;0;ON;;;;;N;;;;; 1F3CC;GOLFER;So;0;ON;;;;;N;;;;; 1F3CD;RACING MOTORCYCLE;So;0;ON;;;;;N;;;;; 1F3CE;RACING CAR;So;0;ON;;;;;N;;;;; 1F3CF;CRICKET BAT AND BALL;So;0;ON;;;;;N;;;;; 1F3D0;VOLLEYBALL;So;0;ON;;;;;N;;;;; 1F3D1;FIELD HOCKEY STICK AND BALL;So;0;ON;;;;;N;;;;; 1F3D2;ICE HOCKEY STICK AND PUCK;So;0;ON;;;;;N;;;;; 1F3D3;TABLE TENNIS PADDLE AND BALL;So;0;ON;;;;;N;;;;; 1F3D4;SNOW CAPPED MOUNTAIN;So;0;ON;;;;;N;;;;; 1F3D5;CAMPING;So;0;ON;;;;;N;;;;; 1F3D6;BEACH WITH UMBRELLA;So;0;ON;;;;;N;;;;; 1F3D7;BUILDING CONSTRUCTION;So;0;ON;;;;;N;;;;; 1F3D8;HOUSE BUILDINGS;So;0;ON;;;;;N;;;;; 1F3D9;CITYSCAPE;So;0;ON;;;;;N;;;;; 1F3DA;DERELICT HOUSE BUILDING;So;0;ON;;;;;N;;;;; 1F3DB;CLASSICAL BUILDING;So;0;ON;;;;;N;;;;; 1F3DC;DESERT;So;0;ON;;;;;N;;;;; 1F3DD;DESERT ISLAND;So;0;ON;;;;;N;;;;; 1F3DE;NATIONAL PARK;So;0;ON;;;;;N;;;;; 1F3DF;STADIUM;So;0;ON;;;;;N;;;;; 1F3E0;HOUSE BUILDING;So;0;ON;;;;;N;;;;; 1F3E1;HOUSE WITH GARDEN;So;0;ON;;;;;N;;;;; 1F3E2;OFFICE BUILDING;So;0;ON;;;;;N;;;;; 1F3E3;JAPANESE POST OFFICE;So;0;ON;;;;;N;;;;; 1F3E4;EUROPEAN POST OFFICE;So;0;ON;;;;;N;;;;; 1F3E5;HOSPITAL;So;0;ON;;;;;N;;;;; 1F3E6;BANK;So;0;ON;;;;;N;;;;; 1F3E7;AUTOMATED TELLER MACHINE;So;0;ON;;;;;N;;;;; 1F3E8;HOTEL;So;0;ON;;;;;N;;;;; 1F3E9;LOVE HOTEL;So;0;ON;;;;;N;;;;; 1F3EA;CONVENIENCE STORE;So;0;ON;;;;;N;;;;; 1F3EB;SCHOOL;So;0;ON;;;;;N;;;;; 1F3EC;DEPARTMENT STORE;So;0;ON;;;;;N;;;;; 1F3ED;FACTORY;So;0;ON;;;;;N;;;;; 1F3EE;IZAKAYA LANTERN;So;0;ON;;;;;N;;;;; 1F3EF;JAPANESE CASTLE;So;0;ON;;;;;N;;;;; 1F3F0;EUROPEAN CASTLE;So;0;ON;;;;;N;;;;; 1F3F1;WHITE PENNANT;So;0;ON;;;;;N;;;;; 1F3F2;BLACK PENNANT;So;0;ON;;;;;N;;;;; 1F3F3;WAVING WHITE FLAG;So;0;ON;;;;;N;;;;; 1F3F4;WAVING BLACK FLAG;So;0;ON;;;;;N;;;;; 1F3F5;ROSETTE;So;0;ON;;;;;N;;;;; 1F3F6;BLACK ROSETTE;So;0;ON;;;;;N;;;;; 1F3F7;LABEL;So;0;ON;;;;;N;;;;; 1F3F8;BADMINTON RACQUET AND SHUTTLECOCK;So;0;ON;;;;;N;;;;; 1F3F9;BOW AND ARROW;So;0;ON;;;;;N;;;;; 1F3FA;AMPHORA;So;0;ON;;;;;N;;;;; 1F3FB;EMOJI MODIFIER FITZPATRICK TYPE-1-2;Sk;0;ON;;;;;N;;;;; 1F3FC;EMOJI MODIFIER FITZPATRICK TYPE-3;Sk;0;ON;;;;;N;;;;; 1F3FD;EMOJI MODIFIER FITZPATRICK TYPE-4;Sk;0;ON;;;;;N;;;;; 1F3FE;EMOJI MODIFIER FITZPATRICK TYPE-5;Sk;0;ON;;;;;N;;;;; 1F3FF;EMOJI MODIFIER FITZPATRICK TYPE-6;Sk;0;ON;;;;;N;;;;; 1F400;RAT;So;0;ON;;;;;N;;;;; 1F401;MOUSE;So;0;ON;;;;;N;;;;; 1F402;OX;So;0;ON;;;;;N;;;;; 1F403;WATER BUFFALO;So;0;ON;;;;;N;;;;; 1F404;COW;So;0;ON;;;;;N;;;;; 1F405;TIGER;So;0;ON;;;;;N;;;;; 1F406;LEOPARD;So;0;ON;;;;;N;;;;; 1F407;RABBIT;So;0;ON;;;;;N;;;;; 1F408;CAT;So;0;ON;;;;;N;;;;; 1F409;DRAGON;So;0;ON;;;;;N;;;;; 1F40A;CROCODILE;So;0;ON;;;;;N;;;;; 1F40B;WHALE;So;0;ON;;;;;N;;;;; 1F40C;SNAIL;So;0;ON;;;;;N;;;;; 1F40D;SNAKE;So;0;ON;;;;;N;;;;; 1F40E;HORSE;So;0;ON;;;;;N;;;;; 1F40F;RAM;So;0;ON;;;;;N;;;;; 1F410;GOAT;So;0;ON;;;;;N;;;;; 1F411;SHEEP;So;0;ON;;;;;N;;;;; 1F412;MONKEY;So;0;ON;;;;;N;;;;; 1F413;ROOSTER;So;0;ON;;;;;N;;;;; 1F414;CHICKEN;So;0;ON;;;;;N;;;;; 1F415;DOG;So;0;ON;;;;;N;;;;; 1F416;PIG;So;0;ON;;;;;N;;;;; 1F417;BOAR;So;0;ON;;;;;N;;;;; 1F418;ELEPHANT;So;0;ON;;;;;N;;;;; 1F419;OCTOPUS;So;0;ON;;;;;N;;;;; 1F41A;SPIRAL SHELL;So;0;ON;;;;;N;;;;; 1F41B;BUG;So;0;ON;;;;;N;;;;; 1F41C;ANT;So;0;ON;;;;;N;;;;; 1F41D;HONEYBEE;So;0;ON;;;;;N;;;;; 1F41E;LADY BEETLE;So;0;ON;;;;;N;;;;; 1F41F;FISH;So;0;ON;;;;;N;;;;; 1F420;TROPICAL FISH;So;0;ON;;;;;N;;;;; 1F421;BLOWFISH;So;0;ON;;;;;N;;;;; 1F422;TURTLE;So;0;ON;;;;;N;;;;; 1F423;HATCHING CHICK;So;0;ON;;;;;N;;;;; 1F424;BABY CHICK;So;0;ON;;;;;N;;;;; 1F425;FRONT-FACING BABY CHICK;So;0;ON;;;;;N;;;;; 1F426;BIRD;So;0;ON;;;;;N;;;;; 1F427;PENGUIN;So;0;ON;;;;;N;;;;; 1F428;KOALA;So;0;ON;;;;;N;;;;; 1F429;POODLE;So;0;ON;;;;;N;;;;; 1F42A;DROMEDARY CAMEL;So;0;ON;;;;;N;;;;; 1F42B;BACTRIAN CAMEL;So;0;ON;;;;;N;;;;; 1F42C;DOLPHIN;So;0;ON;;;;;N;;;;; 1F42D;MOUSE FACE;So;0;ON;;;;;N;;;;; 1F42E;COW FACE;So;0;ON;;;;;N;;;;; 1F42F;TIGER FACE;So;0;ON;;;;;N;;;;; 1F430;RABBIT FACE;So;0;ON;;;;;N;;;;; 1F431;CAT FACE;So;0;ON;;;;;N;;;;; 1F432;DRAGON FACE;So;0;ON;;;;;N;;;;; 1F433;SPOUTING WHALE;So;0;ON;;;;;N;;;;; 1F434;HORSE FACE;So;0;ON;;;;;N;;;;; 1F435;MONKEY FACE;So;0;ON;;;;;N;;;;; 1F436;DOG FACE;So;0;ON;;;;;N;;;;; 1F437;PIG FACE;So;0;ON;;;;;N;;;;; 1F438;FROG FACE;So;0;ON;;;;;N;;;;; 1F439;HAMSTER FACE;So;0;ON;;;;;N;;;;; 1F43A;WOLF FACE;So;0;ON;;;;;N;;;;; 1F43B;BEAR FACE;So;0;ON;;;;;N;;;;; 1F43C;PANDA FACE;So;0;ON;;;;;N;;;;; 1F43D;PIG NOSE;So;0;ON;;;;;N;;;;; 1F43E;PAW PRINTS;So;0;ON;;;;;N;;;;; 1F43F;CHIPMUNK;So;0;ON;;;;;N;;;;; 1F440;EYES;So;0;ON;;;;;N;;;;; 1F441;EYE;So;0;ON;;;;;N;;;;; 1F442;EAR;So;0;ON;;;;;N;;;;; 1F443;NOSE;So;0;ON;;;;;N;;;;; 1F444;MOUTH;So;0;ON;;;;;N;;;;; 1F445;TONGUE;So;0;ON;;;;;N;;;;; 1F446;WHITE UP POINTING BACKHAND INDEX;So;0;ON;;;;;N;;;;; 1F447;WHITE DOWN POINTING BACKHAND INDEX;So;0;ON;;;;;N;;;;; 1F448;WHITE LEFT POINTING BACKHAND INDEX;So;0;ON;;;;;N;;;;; 1F449;WHITE RIGHT POINTING BACKHAND INDEX;So;0;ON;;;;;N;;;;; 1F44A;FISTED HAND SIGN;So;0;ON;;;;;N;;;;; 1F44B;WAVING HAND SIGN;So;0;ON;;;;;N;;;;; 1F44C;OK HAND SIGN;So;0;ON;;;;;N;;;;; 1F44D;THUMBS UP SIGN;So;0;ON;;;;;N;;;;; 1F44E;THUMBS DOWN SIGN;So;0;ON;;;;;N;;;;; 1F44F;CLAPPING HANDS SIGN;So;0;ON;;;;;N;;;;; 1F450;OPEN HANDS SIGN;So;0;ON;;;;;N;;;;; 1F451;CROWN;So;0;ON;;;;;N;;;;; 1F452;WOMANS HAT;So;0;ON;;;;;N;;;;; 1F453;EYEGLASSES;So;0;ON;;;;;N;;;;; 1F454;NECKTIE;So;0;ON;;;;;N;;;;; 1F455;T-SHIRT;So;0;ON;;;;;N;;;;; 1F456;JEANS;So;0;ON;;;;;N;;;;; 1F457;DRESS;So;0;ON;;;;;N;;;;; 1F458;KIMONO;So;0;ON;;;;;N;;;;; 1F459;BIKINI;So;0;ON;;;;;N;;;;; 1F45A;WOMANS CLOTHES;So;0;ON;;;;;N;;;;; 1F45B;PURSE;So;0;ON;;;;;N;;;;; 1F45C;HANDBAG;So;0;ON;;;;;N;;;;; 1F45D;POUCH;So;0;ON;;;;;N;;;;; 1F45E;MANS SHOE;So;0;ON;;;;;N;;;;; 1F45F;ATHLETIC SHOE;So;0;ON;;;;;N;;;;; 1F460;HIGH-HEELED SHOE;So;0;ON;;;;;N;;;;; 1F461;WOMANS SANDAL;So;0;ON;;;;;N;;;;; 1F462;WOMANS BOOTS;So;0;ON;;;;;N;;;;; 1F463;FOOTPRINTS;So;0;ON;;;;;N;;;;; 1F464;BUST IN SILHOUETTE;So;0;ON;;;;;N;;;;; 1F465;BUSTS IN SILHOUETTE;So;0;ON;;;;;N;;;;; 1F466;BOY;So;0;ON;;;;;N;;;;; 1F467;GIRL;So;0;ON;;;;;N;;;;; 1F468;MAN;So;0;ON;;;;;N;;;;; 1F469;WOMAN;So;0;ON;;;;;N;;;;; 1F46A;FAMILY;So;0;ON;;;;;N;;;;; 1F46B;MAN AND WOMAN HOLDING HANDS;So;0;ON;;;;;N;;;;; 1F46C;TWO MEN HOLDING HANDS;So;0;ON;;;;;N;;;;; 1F46D;TWO WOMEN HOLDING HANDS;So;0;ON;;;;;N;;;;; 1F46E;POLICE OFFICER;So;0;ON;;;;;N;;;;; 1F46F;WOMAN WITH BUNNY EARS;So;0;ON;;;;;N;;;;; 1F470;BRIDE WITH VEIL;So;0;ON;;;;;N;;;;; 1F471;PERSON WITH BLOND HAIR;So;0;ON;;;;;N;;;;; 1F472;MAN WITH GUA PI MAO;So;0;ON;;;;;N;;;;; 1F473;MAN WITH TURBAN;So;0;ON;;;;;N;;;;; 1F474;OLDER MAN;So;0;ON;;;;;N;;;;; 1F475;OLDER WOMAN;So;0;ON;;;;;N;;;;; 1F476;BABY;So;0;ON;;;;;N;;;;; 1F477;CONSTRUCTION WORKER;So;0;ON;;;;;N;;;;; 1F478;PRINCESS;So;0;ON;;;;;N;;;;; 1F479;JAPANESE OGRE;So;0;ON;;;;;N;;;;; 1F47A;JAPANESE GOBLIN;So;0;ON;;;;;N;;;;; 1F47B;GHOST;So;0;ON;;;;;N;;;;; 1F47C;BABY ANGEL;So;0;ON;;;;;N;;;;; 1F47D;EXTRATERRESTRIAL ALIEN;So;0;ON;;;;;N;;;;; 1F47E;ALIEN MONSTER;So;0;ON;;;;;N;;;;; 1F47F;IMP;So;0;ON;;;;;N;;;;; 1F480;SKULL;So;0;ON;;;;;N;;;;; 1F481;INFORMATION DESK PERSON;So;0;ON;;;;;N;;;;; 1F482;GUARDSMAN;So;0;ON;;;;;N;;;;; 1F483;DANCER;So;0;ON;;;;;N;;;;; 1F484;LIPSTICK;So;0;ON;;;;;N;;;;; 1F485;NAIL POLISH;So;0;ON;;;;;N;;;;; 1F486;FACE MASSAGE;So;0;ON;;;;;N;;;;; 1F487;HAIRCUT;So;0;ON;;;;;N;;;;; 1F488;BARBER POLE;So;0;ON;;;;;N;;;;; 1F489;SYRINGE;So;0;ON;;;;;N;;;;; 1F48A;PILL;So;0;ON;;;;;N;;;;; 1F48B;KISS MARK;So;0;ON;;;;;N;;;;; 1F48C;LOVE LETTER;So;0;ON;;;;;N;;;;; 1F48D;RING;So;0;ON;;;;;N;;;;; 1F48E;GEM STONE;So;0;ON;;;;;N;;;;; 1F48F;KISS;So;0;ON;;;;;N;;;;; 1F490;BOUQUET;So;0;ON;;;;;N;;;;; 1F491;COUPLE WITH HEART;So;0;ON;;;;;N;;;;; 1F492;WEDDING;So;0;ON;;;;;N;;;;; 1F493;BEATING HEART;So;0;ON;;;;;N;;;;; 1F494;BROKEN HEART;So;0;ON;;;;;N;;;;; 1F495;TWO HEARTS;So;0;ON;;;;;N;;;;; 1F496;SPARKLING HEART;So;0;ON;;;;;N;;;;; 1F497;GROWING HEART;So;0;ON;;;;;N;;;;; 1F498;HEART WITH ARROW;So;0;ON;;;;;N;;;;; 1F499;BLUE HEART;So;0;ON;;;;;N;;;;; 1F49A;GREEN HEART;So;0;ON;;;;;N;;;;; 1F49B;YELLOW HEART;So;0;ON;;;;;N;;;;; 1F49C;PURPLE HEART;So;0;ON;;;;;N;;;;; 1F49D;HEART WITH RIBBON;So;0;ON;;;;;N;;;;; 1F49E;REVOLVING HEARTS;So;0;ON;;;;;N;;;;; 1F49F;HEART DECORATION;So;0;ON;;;;;N;;;;; 1F4A0;DIAMOND SHAPE WITH A DOT INSIDE;So;0;ON;;;;;N;;;;; 1F4A1;ELECTRIC LIGHT BULB;So;0;ON;;;;;N;;;;; 1F4A2;ANGER SYMBOL;So;0;ON;;;;;N;;;;; 1F4A3;BOMB;So;0;ON;;;;;N;;;;; 1F4A4;SLEEPING SYMBOL;So;0;ON;;;;;N;;;;; 1F4A5;COLLISION SYMBOL;So;0;ON;;;;;N;;;;; 1F4A6;SPLASHING SWEAT SYMBOL;So;0;ON;;;;;N;;;;; 1F4A7;DROPLET;So;0;ON;;;;;N;;;;; 1F4A8;DASH SYMBOL;So;0;ON;;;;;N;;;;; 1F4A9;PILE OF POO;So;0;ON;;;;;N;;;;; 1F4AA;FLEXED BICEPS;So;0;ON;;;;;N;;;;; 1F4AB;DIZZY SYMBOL;So;0;ON;;;;;N;;;;; 1F4AC;SPEECH BALLOON;So;0;ON;;;;;N;;;;; 1F4AD;THOUGHT BALLOON;So;0;ON;;;;;N;;;;; 1F4AE;WHITE FLOWER;So;0;ON;;;;;N;;;;; 1F4AF;HUNDRED POINTS SYMBOL;So;0;ON;;;;;N;;;;; 1F4B0;MONEY BAG;So;0;ON;;;;;N;;;;; 1F4B1;CURRENCY EXCHANGE;So;0;ON;;;;;N;;;;; 1F4B2;HEAVY DOLLAR SIGN;So;0;ON;;;;;N;;;;; 1F4B3;CREDIT CARD;So;0;ON;;;;;N;;;;; 1F4B4;BANKNOTE WITH YEN SIGN;So;0;ON;;;;;N;;;;; 1F4B5;BANKNOTE WITH DOLLAR SIGN;So;0;ON;;;;;N;;;;; 1F4B6;BANKNOTE WITH EURO SIGN;So;0;ON;;;;;N;;;;; 1F4B7;BANKNOTE WITH POUND SIGN;So;0;ON;;;;;N;;;;; 1F4B8;MONEY WITH WINGS;So;0;ON;;;;;N;;;;; 1F4B9;CHART WITH UPWARDS TREND AND YEN SIGN;So;0;ON;;;;;N;;;;; 1F4BA;SEAT;So;0;ON;;;;;N;;;;; 1F4BB;PERSONAL COMPUTER;So;0;ON;;;;;N;;;;; 1F4BC;BRIEFCASE;So;0;ON;;;;;N;;;;; 1F4BD;MINIDISC;So;0;ON;;;;;N;;;;; 1F4BE;FLOPPY DISK;So;0;ON;;;;;N;;;;; 1F4BF;OPTICAL DISC;So;0;ON;;;;;N;;;;; 1F4C0;DVD;So;0;ON;;;;;N;;;;; 1F4C1;FILE FOLDER;So;0;ON;;;;;N;;;;; 1F4C2;OPEN FILE FOLDER;So;0;ON;;;;;N;;;;; 1F4C3;PAGE WITH CURL;So;0;ON;;;;;N;;;;; 1F4C4;PAGE FACING UP;So;0;ON;;;;;N;;;;; 1F4C5;CALENDAR;So;0;ON;;;;;N;;;;; 1F4C6;TEAR-OFF CALENDAR;So;0;ON;;;;;N;;;;; 1F4C7;CARD INDEX;So;0;ON;;;;;N;;;;; 1F4C8;CHART WITH UPWARDS TREND;So;0;ON;;;;;N;;;;; 1F4C9;CHART WITH DOWNWARDS TREND;So;0;ON;;;;;N;;;;; 1F4CA;BAR CHART;So;0;ON;;;;;N;;;;; 1F4CB;CLIPBOARD;So;0;ON;;;;;N;;;;; 1F4CC;PUSHPIN;So;0;ON;;;;;N;;;;; 1F4CD;ROUND PUSHPIN;So;0;ON;;;;;N;;;;; 1F4CE;PAPERCLIP;So;0;ON;;;;;N;;;;; 1F4CF;STRAIGHT RULER;So;0;ON;;;;;N;;;;; 1F4D0;TRIANGULAR RULER;So;0;ON;;;;;N;;;;; 1F4D1;BOOKMARK TABS;So;0;ON;;;;;N;;;;; 1F4D2;LEDGER;So;0;ON;;;;;N;;;;; 1F4D3;NOTEBOOK;So;0;ON;;;;;N;;;;; 1F4D4;NOTEBOOK WITH DECORATIVE COVER;So;0;ON;;;;;N;;;;; 1F4D5;CLOSED BOOK;So;0;ON;;;;;N;;;;; 1F4D6;OPEN BOOK;So;0;ON;;;;;N;;;;; 1F4D7;GREEN BOOK;So;0;ON;;;;;N;;;;; 1F4D8;BLUE BOOK;So;0;ON;;;;;N;;;;; 1F4D9;ORANGE BOOK;So;0;ON;;;;;N;;;;; 1F4DA;BOOKS;So;0;ON;;;;;N;;;;; 1F4DB;NAME BADGE;So;0;ON;;;;;N;;;;; 1F4DC;SCROLL;So;0;ON;;;;;N;;;;; 1F4DD;MEMO;So;0;ON;;;;;N;;;;; 1F4DE;TELEPHONE RECEIVER;So;0;ON;;;;;N;;;;; 1F4DF;PAGER;So;0;ON;;;;;N;;;;; 1F4E0;FAX MACHINE;So;0;ON;;;;;N;;;;; 1F4E1;SATELLITE ANTENNA;So;0;ON;;;;;N;;;;; 1F4E2;PUBLIC ADDRESS LOUDSPEAKER;So;0;ON;;;;;N;;;;; 1F4E3;CHEERING MEGAPHONE;So;0;ON;;;;;N;;;;; 1F4E4;OUTBOX TRAY;So;0;ON;;;;;N;;;;; 1F4E5;INBOX TRAY;So;0;ON;;;;;N;;;;; 1F4E6;PACKAGE;So;0;ON;;;;;N;;;;; 1F4E7;E-MAIL SYMBOL;So;0;ON;;;;;N;;;;; 1F4E8;INCOMING ENVELOPE;So;0;ON;;;;;N;;;;; 1F4E9;ENVELOPE WITH DOWNWARDS ARROW ABOVE;So;0;ON;;;;;N;;;;; 1F4EA;CLOSED MAILBOX WITH LOWERED FLAG;So;0;ON;;;;;N;;;;; 1F4EB;CLOSED MAILBOX WITH RAISED FLAG;So;0;ON;;;;;N;;;;; 1F4EC;OPEN MAILBOX WITH RAISED FLAG;So;0;ON;;;;;N;;;;; 1F4ED;OPEN MAILBOX WITH LOWERED FLAG;So;0;ON;;;;;N;;;;; 1F4EE;POSTBOX;So;0;ON;;;;;N;;;;; 1F4EF;POSTAL HORN;So;0;ON;;;;;N;;;;; 1F4F0;NEWSPAPER;So;0;ON;;;;;N;;;;; 1F4F1;MOBILE PHONE;So;0;ON;;;;;N;;;;; 1F4F2;MOBILE PHONE WITH RIGHTWARDS ARROW AT LEFT;So;0;ON;;;;;N;;;;; 1F4F3;VIBRATION MODE;So;0;ON;;;;;N;;;;; 1F4F4;MOBILE PHONE OFF;So;0;ON;;;;;N;;;;; 1F4F5;NO MOBILE PHONES;So;0;ON;;;;;N;;;;; 1F4F6;ANTENNA WITH BARS;So;0;ON;;;;;N;;;;; 1F4F7;CAMERA;So;0;ON;;;;;N;;;;; 1F4F8;CAMERA WITH FLASH;So;0;ON;;;;;N;;;;; 1F4F9;VIDEO CAMERA;So;0;ON;;;;;N;;;;; 1F4FA;TELEVISION;So;0;ON;;;;;N;;;;; 1F4FB;RADIO;So;0;ON;;;;;N;;;;; 1F4FC;VIDEOCASSETTE;So;0;ON;;;;;N;;;;; 1F4FD;FILM PROJECTOR;So;0;ON;;;;;N;;;;; 1F4FE;PORTABLE STEREO;So;0;ON;;;;;N;;;;; 1F4FF;PRAYER BEADS;So;0;ON;;;;;N;;;;; 1F500;TWISTED RIGHTWARDS ARROWS;So;0;ON;;;;;N;;;;; 1F501;CLOCKWISE RIGHTWARDS AND LEFTWARDS OPEN CIRCLE ARROWS;So;0;ON;;;;;N;;;;; 1F502;CLOCKWISE RIGHTWARDS AND LEFTWARDS OPEN CIRCLE ARROWS WITH CIRCLED ONE OVERLAY;So;0;ON;;;;;N;;;;; 1F503;CLOCKWISE DOWNWARDS AND UPWARDS OPEN CIRCLE ARROWS;So;0;ON;;;;;N;;;;; 1F504;ANTICLOCKWISE DOWNWARDS AND UPWARDS OPEN CIRCLE ARROWS;So;0;ON;;;;;N;;;;; 1F505;LOW BRIGHTNESS SYMBOL;So;0;ON;;;;;N;;;;; 1F506;HIGH BRIGHTNESS SYMBOL;So;0;ON;;;;;N;;;;; 1F507;SPEAKER WITH CANCELLATION STROKE;So;0;ON;;;;;N;;;;; 1F508;SPEAKER;So;0;ON;;;;;N;;;;; 1F509;SPEAKER WITH ONE SOUND WAVE;So;0;ON;;;;;N;;;;; 1F50A;SPEAKER WITH THREE SOUND WAVES;So;0;ON;;;;;N;;;;; 1F50B;BATTERY;So;0;ON;;;;;N;;;;; 1F50C;ELECTRIC PLUG;So;0;ON;;;;;N;;;;; 1F50D;LEFT-POINTING MAGNIFYING GLASS;So;0;ON;;;;;N;;;;; 1F50E;RIGHT-POINTING MAGNIFYING GLASS;So;0;ON;;;;;N;;;;; 1F50F;LOCK WITH INK PEN;So;0;ON;;;;;N;;;;; 1F510;CLOSED LOCK WITH KEY;So;0;ON;;;;;N;;;;; 1F511;KEY;So;0;ON;;;;;N;;;;; 1F512;LOCK;So;0;ON;;;;;N;;;;; 1F513;OPEN LOCK;So;0;ON;;;;;N;;;;; 1F514;BELL;So;0;ON;;;;;N;;;;; 1F515;BELL WITH CANCELLATION STROKE;So;0;ON;;;;;N;;;;; 1F516;BOOKMARK;So;0;ON;;;;;N;;;;; 1F517;LINK SYMBOL;So;0;ON;;;;;N;;;;; 1F518;RADIO BUTTON;So;0;ON;;;;;N;;;;; 1F519;BACK WITH LEFTWARDS ARROW ABOVE;So;0;ON;;;;;N;;;;; 1F51A;END WITH LEFTWARDS ARROW ABOVE;So;0;ON;;;;;N;;;;; 1F51B;ON WITH EXCLAMATION MARK WITH LEFT RIGHT ARROW ABOVE;So;0;ON;;;;;N;;;;; 1F51C;SOON WITH RIGHTWARDS ARROW ABOVE;So;0;ON;;;;;N;;;;; 1F51D;TOP WITH UPWARDS ARROW ABOVE;So;0;ON;;;;;N;;;;; 1F51E;NO ONE UNDER EIGHTEEN SYMBOL;So;0;ON;;;;;N;;;;; 1F51F;KEYCAP TEN;So;0;ON;;;;;N;;;;; 1F520;INPUT SYMBOL FOR LATIN CAPITAL LETTERS;So;0;ON;;;;;N;;;;; 1F521;INPUT SYMBOL FOR LATIN SMALL LETTERS;So;0;ON;;;;;N;;;;; 1F522;INPUT SYMBOL FOR NUMBERS;So;0;ON;;;;;N;;;;; 1F523;INPUT SYMBOL FOR SYMBOLS;So;0;ON;;;;;N;;;;; 1F524;INPUT SYMBOL FOR LATIN LETTERS;So;0;ON;;;;;N;;;;; 1F525;FIRE;So;0;ON;;;;;N;;;;; 1F526;ELECTRIC TORCH;So;0;ON;;;;;N;;;;; 1F527;WRENCH;So;0;ON;;;;;N;;;;; 1F528;HAMMER;So;0;ON;;;;;N;;;;; 1F529;NUT AND BOLT;So;0;ON;;;;;N;;;;; 1F52A;HOCHO;So;0;ON;;;;;N;;;;; 1F52B;PISTOL;So;0;ON;;;;;N;;;;; 1F52C;MICROSCOPE;So;0;ON;;;;;N;;;;; 1F52D;TELESCOPE;So;0;ON;;;;;N;;;;; 1F52E;CRYSTAL BALL;So;0;ON;;;;;N;;;;; 1F52F;SIX POINTED STAR WITH MIDDLE DOT;So;0;ON;;;;;N;;;;; 1F530;JAPANESE SYMBOL FOR BEGINNER;So;0;ON;;;;;N;;;;; 1F531;TRIDENT EMBLEM;So;0;ON;;;;;N;;;;; 1F532;BLACK SQUARE BUTTON;So;0;ON;;;;;N;;;;; 1F533;WHITE SQUARE BUTTON;So;0;ON;;;;;N;;;;; 1F534;LARGE RED CIRCLE;So;0;ON;;;;;N;;;;; 1F535;LARGE BLUE CIRCLE;So;0;ON;;;;;N;;;;; 1F536;LARGE ORANGE DIAMOND;So;0;ON;;;;;N;;;;; 1F537;LARGE BLUE DIAMOND;So;0;ON;;;;;N;;;;; 1F538;SMALL ORANGE DIAMOND;So;0;ON;;;;;N;;;;; 1F539;SMALL BLUE DIAMOND;So;0;ON;;;;;N;;;;; 1F53A;UP-POINTING RED TRIANGLE;So;0;ON;;;;;N;;;;; 1F53B;DOWN-POINTING RED TRIANGLE;So;0;ON;;;;;N;;;;; 1F53C;UP-POINTING SMALL RED TRIANGLE;So;0;ON;;;;;N;;;;; 1F53D;DOWN-POINTING SMALL RED TRIANGLE;So;0;ON;;;;;N;;;;; 1F53E;LOWER RIGHT SHADOWED WHITE CIRCLE;So;0;ON;;;;;N;;;;; 1F53F;UPPER RIGHT SHADOWED WHITE CIRCLE;So;0;ON;;;;;N;;;;; 1F540;CIRCLED CROSS POMMEE;So;0;ON;;;;;N;;;;; 1F541;CROSS POMMEE WITH HALF-CIRCLE BELOW;So;0;ON;;;;;N;;;;; 1F542;CROSS POMMEE;So;0;ON;;;;;N;;;;; 1F543;NOTCHED LEFT SEMICIRCLE WITH THREE DOTS;So;0;ON;;;;;N;;;;; 1F544;NOTCHED RIGHT SEMICIRCLE WITH THREE DOTS;So;0;ON;;;;;N;;;;; 1F545;SYMBOL FOR MARKS CHAPTER;So;0;ON;;;;;N;;;;; 1F546;WHITE LATIN CROSS;So;0;ON;;;;;N;;;;; 1F547;HEAVY LATIN CROSS;So;0;ON;;;;;N;;;;; 1F548;CELTIC CROSS;So;0;ON;;;;;N;;;;; 1F549;OM SYMBOL;So;0;ON;;;;;N;;;;; 1F54A;DOVE OF PEACE;So;0;ON;;;;;N;;;;; 1F54B;KAABA;So;0;ON;;;;;N;;;;; 1F54C;MOSQUE;So;0;ON;;;;;N;;;;; 1F54D;SYNAGOGUE;So;0;ON;;;;;N;;;;; 1F54E;MENORAH WITH NINE BRANCHES;So;0;ON;;;;;N;;;;; 1F54F;BOWL OF HYGIEIA;So;0;ON;;;;;N;;;;; 1F550;CLOCK FACE ONE OCLOCK;So;0;ON;;;;;N;;;;; 1F551;CLOCK FACE TWO OCLOCK;So;0;ON;;;;;N;;;;; 1F552;CLOCK FACE THREE OCLOCK;So;0;ON;;;;;N;;;;; 1F553;CLOCK FACE FOUR OCLOCK;So;0;ON;;;;;N;;;;; 1F554;CLOCK FACE FIVE OCLOCK;So;0;ON;;;;;N;;;;; 1F555;CLOCK FACE SIX OCLOCK;So;0;ON;;;;;N;;;;; 1F556;CLOCK FACE SEVEN OCLOCK;So;0;ON;;;;;N;;;;; 1F557;CLOCK FACE EIGHT OCLOCK;So;0;ON;;;;;N;;;;; 1F558;CLOCK FACE NINE OCLOCK;So;0;ON;;;;;N;;;;; 1F559;CLOCK FACE TEN OCLOCK;So;0;ON;;;;;N;;;;; 1F55A;CLOCK FACE ELEVEN OCLOCK;So;0;ON;;;;;N;;;;; 1F55B;CLOCK FACE TWELVE OCLOCK;So;0;ON;;;;;N;;;;; 1F55C;CLOCK FACE ONE-THIRTY;So;0;ON;;;;;N;;;;; 1F55D;CLOCK FACE TWO-THIRTY;So;0;ON;;;;;N;;;;; 1F55E;CLOCK FACE THREE-THIRTY;So;0;ON;;;;;N;;;;; 1F55F;CLOCK FACE FOUR-THIRTY;So;0;ON;;;;;N;;;;; 1F560;CLOCK FACE FIVE-THIRTY;So;0;ON;;;;;N;;;;; 1F561;CLOCK FACE SIX-THIRTY;So;0;ON;;;;;N;;;;; 1F562;CLOCK FACE SEVEN-THIRTY;So;0;ON;;;;;N;;;;; 1F563;CLOCK FACE EIGHT-THIRTY;So;0;ON;;;;;N;;;;; 1F564;CLOCK FACE NINE-THIRTY;So;0;ON;;;;;N;;;;; 1F565;CLOCK FACE TEN-THIRTY;So;0;ON;;;;;N;;;;; 1F566;CLOCK FACE ELEVEN-THIRTY;So;0;ON;;;;;N;;;;; 1F567;CLOCK FACE TWELVE-THIRTY;So;0;ON;;;;;N;;;;; 1F568;RIGHT SPEAKER;So;0;ON;;;;;N;;;;; 1F569;RIGHT SPEAKER WITH ONE SOUND WAVE;So;0;ON;;;;;N;;;;; 1F56A;RIGHT SPEAKER WITH THREE SOUND WAVES;So;0;ON;;;;;N;;;;; 1F56B;BULLHORN;So;0;ON;;;;;N;;;;; 1F56C;BULLHORN WITH SOUND WAVES;So;0;ON;;;;;N;;;;; 1F56D;RINGING BELL;So;0;ON;;;;;N;;;;; 1F56E;BOOK;So;0;ON;;;;;N;;;;; 1F56F;CANDLE;So;0;ON;;;;;N;;;;; 1F570;MANTELPIECE CLOCK;So;0;ON;;;;;N;;;;; 1F571;BLACK SKULL AND CROSSBONES;So;0;ON;;;;;N;;;;; 1F572;NO PIRACY;So;0;ON;;;;;N;;;;; 1F573;HOLE;So;0;ON;;;;;N;;;;; 1F574;MAN IN BUSINESS SUIT LEVITATING;So;0;ON;;;;;N;;;;; 1F575;SLEUTH OR SPY;So;0;ON;;;;;N;;;;; 1F576;DARK SUNGLASSES;So;0;ON;;;;;N;;;;; 1F577;SPIDER;So;0;ON;;;;;N;;;;; 1F578;SPIDER WEB;So;0;ON;;;;;N;;;;; 1F579;JOYSTICK;So;0;ON;;;;;N;;;;; 1F57A;MAN DANCING;So;0;ON;;;;;N;;;;; 1F57B;LEFT HAND TELEPHONE RECEIVER;So;0;ON;;;;;N;;;;; 1F57C;TELEPHONE RECEIVER WITH PAGE;So;0;ON;;;;;N;;;;; 1F57D;RIGHT HAND TELEPHONE RECEIVER;So;0;ON;;;;;N;;;;; 1F57E;WHITE TOUCHTONE TELEPHONE;So;0;ON;;;;;N;;;;; 1F57F;BLACK TOUCHTONE TELEPHONE;So;0;ON;;;;;N;;;;; 1F580;TELEPHONE ON TOP OF MODEM;So;0;ON;;;;;N;;;;; 1F581;CLAMSHELL MOBILE PHONE;So;0;ON;;;;;N;;;;; 1F582;BACK OF ENVELOPE;So;0;ON;;;;;N;;;;; 1F583;STAMPED ENVELOPE;So;0;ON;;;;;N;;;;; 1F584;ENVELOPE WITH LIGHTNING;So;0;ON;;;;;N;;;;; 1F585;FLYING ENVELOPE;So;0;ON;;;;;N;;;;; 1F586;PEN OVER STAMPED ENVELOPE;So;0;ON;;;;;N;;;;; 1F587;LINKED PAPERCLIPS;So;0;ON;;;;;N;;;;; 1F588;BLACK PUSHPIN;So;0;ON;;;;;N;;;;; 1F589;LOWER LEFT PENCIL;So;0;ON;;;;;N;;;;; 1F58A;LOWER LEFT BALLPOINT PEN;So;0;ON;;;;;N;;;;; 1F58B;LOWER LEFT FOUNTAIN PEN;So;0;ON;;;;;N;;;;; 1F58C;LOWER LEFT PAINTBRUSH;So;0;ON;;;;;N;;;;; 1F58D;LOWER LEFT CRAYON;So;0;ON;;;;;N;;;;; 1F58E;LEFT WRITING HAND;So;0;ON;;;;;N;;;;; 1F58F;TURNED OK HAND SIGN;So;0;ON;;;;;N;;;;; 1F590;RAISED HAND WITH FINGERS SPLAYED;So;0;ON;;;;;N;;;;; 1F591;REVERSED RAISED HAND WITH FINGERS SPLAYED;So;0;ON;;;;;N;;;;; 1F592;REVERSED THUMBS UP SIGN;So;0;ON;;;;;N;;;;; 1F593;REVERSED THUMBS DOWN SIGN;So;0;ON;;;;;N;;;;; 1F594;REVERSED VICTORY HAND;So;0;ON;;;;;N;;;;; 1F595;REVERSED HAND WITH MIDDLE FINGER EXTENDED;So;0;ON;;;;;N;;;;; 1F596;RAISED HAND WITH PART BETWEEN MIDDLE AND RING FINGERS;So;0;ON;;;;;N;;;;; 1F597;WHITE DOWN POINTING LEFT HAND INDEX;So;0;ON;;;;;N;;;;; 1F598;SIDEWAYS WHITE LEFT POINTING INDEX;So;0;ON;;;;;N;;;;; 1F599;SIDEWAYS WHITE RIGHT POINTING INDEX;So;0;ON;;;;;N;;;;; 1F59A;SIDEWAYS BLACK LEFT POINTING INDEX;So;0;ON;;;;;N;;;;; 1F59B;SIDEWAYS BLACK RIGHT POINTING INDEX;So;0;ON;;;;;N;;;;; 1F59C;BLACK LEFT POINTING BACKHAND INDEX;So;0;ON;;;;;N;;;;; 1F59D;BLACK RIGHT POINTING BACKHAND INDEX;So;0;ON;;;;;N;;;;; 1F59E;SIDEWAYS WHITE UP POINTING INDEX;So;0;ON;;;;;N;;;;; 1F59F;SIDEWAYS WHITE DOWN POINTING INDEX;So;0;ON;;;;;N;;;;; 1F5A0;SIDEWAYS BLACK UP POINTING INDEX;So;0;ON;;;;;N;;;;; 1F5A1;SIDEWAYS BLACK DOWN POINTING INDEX;So;0;ON;;;;;N;;;;; 1F5A2;BLACK UP POINTING BACKHAND INDEX;So;0;ON;;;;;N;;;;; 1F5A3;BLACK DOWN POINTING BACKHAND INDEX;So;0;ON;;;;;N;;;;; 1F5A4;BLACK HEART;So;0;ON;;;;;N;;;;; 1F5A5;DESKTOP COMPUTER;So;0;ON;;;;;N;;;;; 1F5A6;KEYBOARD AND MOUSE;So;0;ON;;;;;N;;;;; 1F5A7;THREE NETWORKED COMPUTERS;So;0;ON;;;;;N;;;;; 1F5A8;PRINTER;So;0;ON;;;;;N;;;;; 1F5A9;POCKET CALCULATOR;So;0;ON;;;;;N;;;;; 1F5AA;BLACK HARD SHELL FLOPPY DISK;So;0;ON;;;;;N;;;;; 1F5AB;WHITE HARD SHELL FLOPPY DISK;So;0;ON;;;;;N;;;;; 1F5AC;SOFT SHELL FLOPPY DISK;So;0;ON;;;;;N;;;;; 1F5AD;TAPE CARTRIDGE;So;0;ON;;;;;N;;;;; 1F5AE;WIRED KEYBOARD;So;0;ON;;;;;N;;;;; 1F5AF;ONE BUTTON MOUSE;So;0;ON;;;;;N;;;;; 1F5B0;TWO BUTTON MOUSE;So;0;ON;;;;;N;;;;; 1F5B1;THREE BUTTON MOUSE;So;0;ON;;;;;N;;;;; 1F5B2;TRACKBALL;So;0;ON;;;;;N;;;;; 1F5B3;OLD PERSONAL COMPUTER;So;0;ON;;;;;N;;;;; 1F5B4;HARD DISK;So;0;ON;;;;;N;;;;; 1F5B5;SCREEN;So;0;ON;;;;;N;;;;; 1F5B6;PRINTER ICON;So;0;ON;;;;;N;;;;; 1F5B7;FAX ICON;So;0;ON;;;;;N;;;;; 1F5B8;OPTICAL DISC ICON;So;0;ON;;;;;N;;;;; 1F5B9;DOCUMENT WITH TEXT;So;0;ON;;;;;N;;;;; 1F5BA;DOCUMENT WITH TEXT AND PICTURE;So;0;ON;;;;;N;;;;; 1F5BB;DOCUMENT WITH PICTURE;So;0;ON;;;;;N;;;;; 1F5BC;FRAME WITH PICTURE;So;0;ON;;;;;N;;;;; 1F5BD;FRAME WITH TILES;So;0;ON;;;;;N;;;;; 1F5BE;FRAME WITH AN X;So;0;ON;;;;;N;;;;; 1F5BF;BLACK FOLDER;So;0;ON;;;;;N;;;;; 1F5C0;FOLDER;So;0;ON;;;;;N;;;;; 1F5C1;OPEN FOLDER;So;0;ON;;;;;N;;;;; 1F5C2;CARD INDEX DIVIDERS;So;0;ON;;;;;N;;;;; 1F5C3;CARD FILE BOX;So;0;ON;;;;;N;;;;; 1F5C4;FILE CABINET;So;0;ON;;;;;N;;;;; 1F5C5;EMPTY NOTE;So;0;ON;;;;;N;;;;; 1F5C6;EMPTY NOTE PAGE;So;0;ON;;;;;N;;;;; 1F5C7;EMPTY NOTE PAD;So;0;ON;;;;;N;;;;; 1F5C8;NOTE;So;0;ON;;;;;N;;;;; 1F5C9;NOTE PAGE;So;0;ON;;;;;N;;;;; 1F5CA;NOTE PAD;So;0;ON;;;;;N;;;;; 1F5CB;EMPTY DOCUMENT;So;0;ON;;;;;N;;;;; 1F5CC;EMPTY PAGE;So;0;ON;;;;;N;;;;; 1F5CD;EMPTY PAGES;So;0;ON;;;;;N;;;;; 1F5CE;DOCUMENT;So;0;ON;;;;;N;;;;; 1F5CF;PAGE;So;0;ON;;;;;N;;;;; 1F5D0;PAGES;So;0;ON;;;;;N;;;;; 1F5D1;WASTEBASKET;So;0;ON;;;;;N;;;;; 1F5D2;SPIRAL NOTE PAD;So;0;ON;;;;;N;;;;; 1F5D3;SPIRAL CALENDAR PAD;So;0;ON;;;;;N;;;;; 1F5D4;DESKTOP WINDOW;So;0;ON;;;;;N;;;;; 1F5D5;MINIMIZE;So;0;ON;;;;;N;;;;; 1F5D6;MAXIMIZE;So;0;ON;;;;;N;;;;; 1F5D7;OVERLAP;So;0;ON;;;;;N;;;;; 1F5D8;CLOCKWISE RIGHT AND LEFT SEMICIRCLE ARROWS;So;0;ON;;;;;N;;;;; 1F5D9;CANCELLATION X;So;0;ON;;;;;N;;;;; 1F5DA;INCREASE FONT SIZE SYMBOL;So;0;ON;;;;;N;;;;; 1F5DB;DECREASE FONT SIZE SYMBOL;So;0;ON;;;;;N;;;;; 1F5DC;COMPRESSION;So;0;ON;;;;;N;;;;; 1F5DD;OLD KEY;So;0;ON;;;;;N;;;;; 1F5DE;ROLLED-UP NEWSPAPER;So;0;ON;;;;;N;;;;; 1F5DF;PAGE WITH CIRCLED TEXT;So;0;ON;;;;;N;;;;; 1F5E0;STOCK CHART;So;0;ON;;;;;N;;;;; 1F5E1;DAGGER KNIFE;So;0;ON;;;;;N;;;;; 1F5E2;LIPS;So;0;ON;;;;;N;;;;; 1F5E3;SPEAKING HEAD IN SILHOUETTE;So;0;ON;;;;;N;;;;; 1F5E4;THREE RAYS ABOVE;So;0;ON;;;;;N;;;;; 1F5E5;THREE RAYS BELOW;So;0;ON;;;;;N;;;;; 1F5E6;THREE RAYS LEFT;So;0;ON;;;;;N;;;;; 1F5E7;THREE RAYS RIGHT;So;0;ON;;;;;N;;;;; 1F5E8;LEFT SPEECH BUBBLE;So;0;ON;;;;;N;;;;; 1F5E9;RIGHT SPEECH BUBBLE;So;0;ON;;;;;N;;;;; 1F5EA;TWO SPEECH BUBBLES;So;0;ON;;;;;N;;;;; 1F5EB;THREE SPEECH BUBBLES;So;0;ON;;;;;N;;;;; 1F5EC;LEFT THOUGHT BUBBLE;So;0;ON;;;;;N;;;;; 1F5ED;RIGHT THOUGHT BUBBLE;So;0;ON;;;;;N;;;;; 1F5EE;LEFT ANGER BUBBLE;So;0;ON;;;;;N;;;;; 1F5EF;RIGHT ANGER BUBBLE;So;0;ON;;;;;N;;;;; 1F5F0;MOOD BUBBLE;So;0;ON;;;;;N;;;;; 1F5F1;LIGHTNING MOOD BUBBLE;So;0;ON;;;;;N;;;;; 1F5F2;LIGHTNING MOOD;So;0;ON;;;;;N;;;;; 1F5F3;BALLOT BOX WITH BALLOT;So;0;ON;;;;;N;;;;; 1F5F4;BALLOT SCRIPT X;So;0;ON;;;;;N;;;;; 1F5F5;BALLOT BOX WITH SCRIPT X;So;0;ON;;;;;N;;;;; 1F5F6;BALLOT BOLD SCRIPT X;So;0;ON;;;;;N;;;;; 1F5F7;BALLOT BOX WITH BOLD SCRIPT X;So;0;ON;;;;;N;;;;; 1F5F8;LIGHT CHECK MARK;So;0;ON;;;;;N;;;;; 1F5F9;BALLOT BOX WITH BOLD CHECK;So;0;ON;;;;;N;;;;; 1F5FA;WORLD MAP;So;0;ON;;;;;N;;;;; 1F5FB;MOUNT FUJI;So;0;ON;;;;;N;;;;; 1F5FC;TOKYO TOWER;So;0;ON;;;;;N;;;;; 1F5FD;STATUE OF LIBERTY;So;0;ON;;;;;N;;;;; 1F5FE;SILHOUETTE OF JAPAN;So;0;ON;;;;;N;;;;; 1F5FF;MOYAI;So;0;ON;;;;;N;;;;; 1F600;GRINNING FACE;So;0;ON;;;;;N;;;;; 1F601;GRINNING FACE WITH SMILING EYES;So;0;ON;;;;;N;;;;; 1F602;FACE WITH TEARS OF JOY;So;0;ON;;;;;N;;;;; 1F603;SMILING FACE WITH OPEN MOUTH;So;0;ON;;;;;N;;;;; 1F604;SMILING FACE WITH OPEN MOUTH AND SMILING EYES;So;0;ON;;;;;N;;;;; 1F605;SMILING FACE WITH OPEN MOUTH AND COLD SWEAT;So;0;ON;;;;;N;;;;; 1F606;SMILING FACE WITH OPEN MOUTH AND TIGHTLY-CLOSED EYES;So;0;ON;;;;;N;;;;; 1F607;SMILING FACE WITH HALO;So;0;ON;;;;;N;;;;; 1F608;SMILING FACE WITH HORNS;So;0;ON;;;;;N;;;;; 1F609;WINKING FACE;So;0;ON;;;;;N;;;;; 1F60A;SMILING FACE WITH SMILING EYES;So;0;ON;;;;;N;;;;; 1F60B;FACE SAVOURING DELICIOUS FOOD;So;0;ON;;;;;N;;;;; 1F60C;RELIEVED FACE;So;0;ON;;;;;N;;;;; 1F60D;SMILING FACE WITH HEART-SHAPED EYES;So;0;ON;;;;;N;;;;; 1F60E;SMILING FACE WITH SUNGLASSES;So;0;ON;;;;;N;;;;; 1F60F;SMIRKING FACE;So;0;ON;;;;;N;;;;; 1F610;NEUTRAL FACE;So;0;ON;;;;;N;;;;; 1F611;EXPRESSIONLESS FACE;So;0;ON;;;;;N;;;;; 1F612;UNAMUSED FACE;So;0;ON;;;;;N;;;;; 1F613;FACE WITH COLD SWEAT;So;0;ON;;;;;N;;;;; 1F614;PENSIVE FACE;So;0;ON;;;;;N;;;;; 1F615;CONFUSED FACE;So;0;ON;;;;;N;;;;; 1F616;CONFOUNDED FACE;So;0;ON;;;;;N;;;;; 1F617;KISSING FACE;So;0;ON;;;;;N;;;;; 1F618;FACE THROWING A KISS;So;0;ON;;;;;N;;;;; 1F619;KISSING FACE WITH SMILING EYES;So;0;ON;;;;;N;;;;; 1F61A;KISSING FACE WITH CLOSED EYES;So;0;ON;;;;;N;;;;; 1F61B;FACE WITH STUCK-OUT TONGUE;So;0;ON;;;;;N;;;;; 1F61C;FACE WITH STUCK-OUT TONGUE AND WINKING EYE;So;0;ON;;;;;N;;;;; 1F61D;FACE WITH STUCK-OUT TONGUE AND TIGHTLY-CLOSED EYES;So;0;ON;;;;;N;;;;; 1F61E;DISAPPOINTED FACE;So;0;ON;;;;;N;;;;; 1F61F;WORRIED FACE;So;0;ON;;;;;N;;;;; 1F620;ANGRY FACE;So;0;ON;;;;;N;;;;; 1F621;POUTING FACE;So;0;ON;;;;;N;;;;; 1F622;CRYING FACE;So;0;ON;;;;;N;;;;; 1F623;PERSEVERING FACE;So;0;ON;;;;;N;;;;; 1F624;FACE WITH LOOK OF TRIUMPH;So;0;ON;;;;;N;;;;; 1F625;DISAPPOINTED BUT RELIEVED FACE;So;0;ON;;;;;N;;;;; 1F626;FROWNING FACE WITH OPEN MOUTH;So;0;ON;;;;;N;;;;; 1F627;ANGUISHED FACE;So;0;ON;;;;;N;;;;; 1F628;FEARFUL FACE;So;0;ON;;;;;N;;;;; 1F629;WEARY FACE;So;0;ON;;;;;N;;;;; 1F62A;SLEEPY FACE;So;0;ON;;;;;N;;;;; 1F62B;TIRED FACE;So;0;ON;;;;;N;;;;; 1F62C;GRIMACING FACE;So;0;ON;;;;;N;;;;; 1F62D;LOUDLY CRYING FACE;So;0;ON;;;;;N;;;;; 1F62E;FACE WITH OPEN MOUTH;So;0;ON;;;;;N;;;;; 1F62F;HUSHED FACE;So;0;ON;;;;;N;;;;; 1F630;FACE WITH OPEN MOUTH AND COLD SWEAT;So;0;ON;;;;;N;;;;; 1F631;FACE SCREAMING IN FEAR;So;0;ON;;;;;N;;;;; 1F632;ASTONISHED FACE;So;0;ON;;;;;N;;;;; 1F633;FLUSHED FACE;So;0;ON;;;;;N;;;;; 1F634;SLEEPING FACE;So;0;ON;;;;;N;;;;; 1F635;DIZZY FACE;So;0;ON;;;;;N;;;;; 1F636;FACE WITHOUT MOUTH;So;0;ON;;;;;N;;;;; 1F637;FACE WITH MEDICAL MASK;So;0;ON;;;;;N;;;;; 1F638;GRINNING CAT FACE WITH SMILING EYES;So;0;ON;;;;;N;;;;; 1F639;CAT FACE WITH TEARS OF JOY;So;0;ON;;;;;N;;;;; 1F63A;SMILING CAT FACE WITH OPEN MOUTH;So;0;ON;;;;;N;;;;; 1F63B;SMILING CAT FACE WITH HEART-SHAPED EYES;So;0;ON;;;;;N;;;;; 1F63C;CAT FACE WITH WRY SMILE;So;0;ON;;;;;N;;;;; 1F63D;KISSING CAT FACE WITH CLOSED EYES;So;0;ON;;;;;N;;;;; 1F63E;POUTING CAT FACE;So;0;ON;;;;;N;;;;; 1F63F;CRYING CAT FACE;So;0;ON;;;;;N;;;;; 1F640;WEARY CAT FACE;So;0;ON;;;;;N;;;;; 1F641;SLIGHTLY FROWNING FACE;So;0;ON;;;;;N;;;;; 1F642;SLIGHTLY SMILING FACE;So;0;ON;;;;;N;;;;; 1F643;UPSIDE-DOWN FACE;So;0;ON;;;;;N;;;;; 1F644;FACE WITH ROLLING EYES;So;0;ON;;;;;N;;;;; 1F645;FACE WITH NO GOOD GESTURE;So;0;ON;;;;;N;;;;; 1F646;FACE WITH OK GESTURE;So;0;ON;;;;;N;;;;; 1F647;PERSON BOWING DEEPLY;So;0;ON;;;;;N;;;;; 1F648;SEE-NO-EVIL MONKEY;So;0;ON;;;;;N;;;;; 1F649;HEAR-NO-EVIL MONKEY;So;0;ON;;;;;N;;;;; 1F64A;SPEAK-NO-EVIL MONKEY;So;0;ON;;;;;N;;;;; 1F64B;HAPPY PERSON RAISING ONE HAND;So;0;ON;;;;;N;;;;; 1F64C;PERSON RAISING BOTH HANDS IN CELEBRATION;So;0;ON;;;;;N;;;;; 1F64D;PERSON FROWNING;So;0;ON;;;;;N;;;;; 1F64E;PERSON WITH POUTING FACE;So;0;ON;;;;;N;;;;; 1F64F;PERSON WITH FOLDED HANDS;So;0;ON;;;;;N;;;;; 1F650;NORTH WEST POINTING LEAF;So;0;ON;;;;;N;;;;; 1F651;SOUTH WEST POINTING LEAF;So;0;ON;;;;;N;;;;; 1F652;NORTH EAST POINTING LEAF;So;0;ON;;;;;N;;;;; 1F653;SOUTH EAST POINTING LEAF;So;0;ON;;;;;N;;;;; 1F654;TURNED NORTH WEST POINTING LEAF;So;0;ON;;;;;N;;;;; 1F655;TURNED SOUTH WEST POINTING LEAF;So;0;ON;;;;;N;;;;; 1F656;TURNED NORTH EAST POINTING LEAF;So;0;ON;;;;;N;;;;; 1F657;TURNED SOUTH EAST POINTING LEAF;So;0;ON;;;;;N;;;;; 1F658;NORTH WEST POINTING VINE LEAF;So;0;ON;;;;;N;;;;; 1F659;SOUTH WEST POINTING VINE LEAF;So;0;ON;;;;;N;;;;; 1F65A;NORTH EAST POINTING VINE LEAF;So;0;ON;;;;;N;;;;; 1F65B;SOUTH EAST POINTING VINE LEAF;So;0;ON;;;;;N;;;;; 1F65C;HEAVY NORTH WEST POINTING VINE LEAF;So;0;ON;;;;;N;;;;; 1F65D;HEAVY SOUTH WEST POINTING VINE LEAF;So;0;ON;;;;;N;;;;; 1F65E;HEAVY NORTH EAST POINTING VINE LEAF;So;0;ON;;;;;N;;;;; 1F65F;HEAVY SOUTH EAST POINTING VINE LEAF;So;0;ON;;;;;N;;;;; 1F660;NORTH WEST POINTING BUD;So;0;ON;;;;;N;;;;; 1F661;SOUTH WEST POINTING BUD;So;0;ON;;;;;N;;;;; 1F662;NORTH EAST POINTING BUD;So;0;ON;;;;;N;;;;; 1F663;SOUTH EAST POINTING BUD;So;0;ON;;;;;N;;;;; 1F664;HEAVY NORTH WEST POINTING BUD;So;0;ON;;;;;N;;;;; 1F665;HEAVY SOUTH WEST POINTING BUD;So;0;ON;;;;;N;;;;; 1F666;HEAVY NORTH EAST POINTING BUD;So;0;ON;;;;;N;;;;; 1F667;HEAVY SOUTH EAST POINTING BUD;So;0;ON;;;;;N;;;;; 1F668;HOLLOW QUILT SQUARE ORNAMENT;So;0;ON;;;;;N;;;;; 1F669;HOLLOW QUILT SQUARE ORNAMENT IN BLACK SQUARE;So;0;ON;;;;;N;;;;; 1F66A;SOLID QUILT SQUARE ORNAMENT;So;0;ON;;;;;N;;;;; 1F66B;SOLID QUILT SQUARE ORNAMENT IN BLACK SQUARE;So;0;ON;;;;;N;;;;; 1F66C;LEFTWARDS ROCKET;So;0;ON;;;;;N;;;;; 1F66D;UPWARDS ROCKET;So;0;ON;;;;;N;;;;; 1F66E;RIGHTWARDS ROCKET;So;0;ON;;;;;N;;;;; 1F66F;DOWNWARDS ROCKET;So;0;ON;;;;;N;;;;; 1F670;SCRIPT LIGATURE ET ORNAMENT;So;0;ON;;;;;N;;;;; 1F671;HEAVY SCRIPT LIGATURE ET ORNAMENT;So;0;ON;;;;;N;;;;; 1F672;LIGATURE OPEN ET ORNAMENT;So;0;ON;;;;;N;;;;; 1F673;HEAVY LIGATURE OPEN ET ORNAMENT;So;0;ON;;;;;N;;;;; 1F674;HEAVY AMPERSAND ORNAMENT;So;0;ON;;;;;N;;;;; 1F675;SWASH AMPERSAND ORNAMENT;So;0;ON;;;;;N;;;;; 1F676;SANS-SERIF HEAVY DOUBLE TURNED COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; 1F677;SANS-SERIF HEAVY DOUBLE COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; 1F678;SANS-SERIF HEAVY LOW DOUBLE COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; 1F679;HEAVY INTERROBANG ORNAMENT;So;0;ON;;;;;N;;;;; 1F67A;SANS-SERIF INTERROBANG ORNAMENT;So;0;ON;;;;;N;;;;; 1F67B;HEAVY SANS-SERIF INTERROBANG ORNAMENT;So;0;ON;;;;;N;;;;; 1F67C;VERY HEAVY SOLIDUS;So;0;ON;;;;;N;;;;; 1F67D;VERY HEAVY REVERSE SOLIDUS;So;0;ON;;;;;N;;;;; 1F67E;CHECKER BOARD;So;0;ON;;;;;N;;;;; 1F67F;REVERSE CHECKER BOARD;So;0;ON;;;;;N;;;;; 1F680;ROCKET;So;0;ON;;;;;N;;;;; 1F681;HELICOPTER;So;0;ON;;;;;N;;;;; 1F682;STEAM LOCOMOTIVE;So;0;ON;;;;;N;;;;; 1F683;RAILWAY CAR;So;0;ON;;;;;N;;;;; 1F684;HIGH-SPEED TRAIN;So;0;ON;;;;;N;;;;; 1F685;HIGH-SPEED TRAIN WITH BULLET NOSE;So;0;ON;;;;;N;;;;; 1F686;TRAIN;So;0;ON;;;;;N;;;;; 1F687;METRO;So;0;ON;;;;;N;;;;; 1F688;LIGHT RAIL;So;0;ON;;;;;N;;;;; 1F689;STATION;So;0;ON;;;;;N;;;;; 1F68A;TRAM;So;0;ON;;;;;N;;;;; 1F68B;TRAM CAR;So;0;ON;;;;;N;;;;; 1F68C;BUS;So;0;ON;;;;;N;;;;; 1F68D;ONCOMING BUS;So;0;ON;;;;;N;;;;; 1F68E;TROLLEYBUS;So;0;ON;;;;;N;;;;; 1F68F;BUS STOP;So;0;ON;;;;;N;;;;; 1F690;MINIBUS;So;0;ON;;;;;N;;;;; 1F691;AMBULANCE;So;0;ON;;;;;N;;;;; 1F692;FIRE ENGINE;So;0;ON;;;;;N;;;;; 1F693;POLICE CAR;So;0;ON;;;;;N;;;;; 1F694;ONCOMING POLICE CAR;So;0;ON;;;;;N;;;;; 1F695;TAXI;So;0;ON;;;;;N;;;;; 1F696;ONCOMING TAXI;So;0;ON;;;;;N;;;;; 1F697;AUTOMOBILE;So;0;ON;;;;;N;;;;; 1F698;ONCOMING AUTOMOBILE;So;0;ON;;;;;N;;;;; 1F699;RECREATIONAL VEHICLE;So;0;ON;;;;;N;;;;; 1F69A;DELIVERY TRUCK;So;0;ON;;;;;N;;;;; 1F69B;ARTICULATED LORRY;So;0;ON;;;;;N;;;;; 1F69C;TRACTOR;So;0;ON;;;;;N;;;;; 1F69D;MONORAIL;So;0;ON;;;;;N;;;;; 1F69E;MOUNTAIN RAILWAY;So;0;ON;;;;;N;;;;; 1F69F;SUSPENSION RAILWAY;So;0;ON;;;;;N;;;;; 1F6A0;MOUNTAIN CABLEWAY;So;0;ON;;;;;N;;;;; 1F6A1;AERIAL TRAMWAY;So;0;ON;;;;;N;;;;; 1F6A2;SHIP;So;0;ON;;;;;N;;;;; 1F6A3;ROWBOAT;So;0;ON;;;;;N;;;;; 1F6A4;SPEEDBOAT;So;0;ON;;;;;N;;;;; 1F6A5;HORIZONTAL TRAFFIC LIGHT;So;0;ON;;;;;N;;;;; 1F6A6;VERTICAL TRAFFIC LIGHT;So;0;ON;;;;;N;;;;; 1F6A7;CONSTRUCTION SIGN;So;0;ON;;;;;N;;;;; 1F6A8;POLICE CARS REVOLVING LIGHT;So;0;ON;;;;;N;;;;; 1F6A9;TRIANGULAR FLAG ON POST;So;0;ON;;;;;N;;;;; 1F6AA;DOOR;So;0;ON;;;;;N;;;;; 1F6AB;NO ENTRY SIGN;So;0;ON;;;;;N;;;;; 1F6AC;SMOKING SYMBOL;So;0;ON;;;;;N;;;;; 1F6AD;NO SMOKING SYMBOL;So;0;ON;;;;;N;;;;; 1F6AE;PUT LITTER IN ITS PLACE SYMBOL;So;0;ON;;;;;N;;;;; 1F6AF;DO NOT LITTER SYMBOL;So;0;ON;;;;;N;;;;; 1F6B0;POTABLE WATER SYMBOL;So;0;ON;;;;;N;;;;; 1F6B1;NON-POTABLE WATER SYMBOL;So;0;ON;;;;;N;;;;; 1F6B2;BICYCLE;So;0;ON;;;;;N;;;;; 1F6B3;NO BICYCLES;So;0;ON;;;;;N;;;;; 1F6B4;BICYCLIST;So;0;ON;;;;;N;;;;; 1F6B5;MOUNTAIN BICYCLIST;So;0;ON;;;;;N;;;;; 1F6B6;PEDESTRIAN;So;0;ON;;;;;N;;;;; 1F6B7;NO PEDESTRIANS;So;0;ON;;;;;N;;;;; 1F6B8;CHILDREN CROSSING;So;0;ON;;;;;N;;;;; 1F6B9;MENS SYMBOL;So;0;ON;;;;;N;;;;; 1F6BA;WOMENS SYMBOL;So;0;ON;;;;;N;;;;; 1F6BB;RESTROOM;So;0;ON;;;;;N;;;;; 1F6BC;BABY SYMBOL;So;0;ON;;;;;N;;;;; 1F6BD;TOILET;So;0;ON;;;;;N;;;;; 1F6BE;WATER CLOSET;So;0;ON;;;;;N;;;;; 1F6BF;SHOWER;So;0;ON;;;;;N;;;;; 1F6C0;BATH;So;0;ON;;;;;N;;;;; 1F6C1;BATHTUB;So;0;ON;;;;;N;;;;; 1F6C2;PASSPORT CONTROL;So;0;ON;;;;;N;;;;; 1F6C3;CUSTOMS;So;0;ON;;;;;N;;;;; 1F6C4;BAGGAGE CLAIM;So;0;ON;;;;;N;;;;; 1F6C5;LEFT LUGGAGE;So;0;ON;;;;;N;;;;; 1F6C6;TRIANGLE WITH ROUNDED CORNERS;So;0;ON;;;;;N;;;;; 1F6C7;PROHIBITED SIGN;So;0;ON;;;;;N;;;;; 1F6C8;CIRCLED INFORMATION SOURCE;So;0;ON;;;;;N;;;;; 1F6C9;BOYS SYMBOL;So;0;ON;;;;;N;;;;; 1F6CA;GIRLS SYMBOL;So;0;ON;;;;;N;;;;; 1F6CB;COUCH AND LAMP;So;0;ON;;;;;N;;;;; 1F6CC;SLEEPING ACCOMMODATION;So;0;ON;;;;;N;;;;; 1F6CD;SHOPPING BAGS;So;0;ON;;;;;N;;;;; 1F6CE;BELLHOP BELL;So;0;ON;;;;;N;;;;; 1F6CF;BED;So;0;ON;;;;;N;;;;; 1F6D0;PLACE OF WORSHIP;So;0;ON;;;;;N;;;;; 1F6D1;OCTAGONAL SIGN;So;0;ON;;;;;N;;;;; 1F6D2;SHOPPING TROLLEY;So;0;ON;;;;;N;;;;; 1F6E0;HAMMER AND WRENCH;So;0;ON;;;;;N;;;;; 1F6E1;SHIELD;So;0;ON;;;;;N;;;;; 1F6E2;OIL DRUM;So;0;ON;;;;;N;;;;; 1F6E3;MOTORWAY;So;0;ON;;;;;N;;;;; 1F6E4;RAILWAY TRACK;So;0;ON;;;;;N;;;;; 1F6E5;MOTOR BOAT;So;0;ON;;;;;N;;;;; 1F6E6;UP-POINTING MILITARY AIRPLANE;So;0;ON;;;;;N;;;;; 1F6E7;UP-POINTING AIRPLANE;So;0;ON;;;;;N;;;;; 1F6E8;UP-POINTING SMALL AIRPLANE;So;0;ON;;;;;N;;;;; 1F6E9;SMALL AIRPLANE;So;0;ON;;;;;N;;;;; 1F6EA;NORTHEAST-POINTING AIRPLANE;So;0;ON;;;;;N;;;;; 1F6EB;AIRPLANE DEPARTURE;So;0;ON;;;;;N;;;;; 1F6EC;AIRPLANE ARRIVING;So;0;ON;;;;;N;;;;; 1F6F0;SATELLITE;So;0;ON;;;;;N;;;;; 1F6F1;ONCOMING FIRE ENGINE;So;0;ON;;;;;N;;;;; 1F6F2;DIESEL LOCOMOTIVE;So;0;ON;;;;;N;;;;; 1F6F3;PASSENGER SHIP;So;0;ON;;;;;N;;;;; 1F6F4;SCOOTER;So;0;ON;;;;;N;;;;; 1F6F5;MOTOR SCOOTER;So;0;ON;;;;;N;;;;; 1F6F6;CANOE;So;0;ON;;;;;N;;;;; 1F700;ALCHEMICAL SYMBOL FOR QUINTESSENCE;So;0;ON;;;;;N;;;;; 1F701;ALCHEMICAL SYMBOL FOR AIR;So;0;ON;;;;;N;;;;; 1F702;ALCHEMICAL SYMBOL FOR FIRE;So;0;ON;;;;;N;;;;; 1F703;ALCHEMICAL SYMBOL FOR EARTH;So;0;ON;;;;;N;;;;; 1F704;ALCHEMICAL SYMBOL FOR WATER;So;0;ON;;;;;N;;;;; 1F705;ALCHEMICAL SYMBOL FOR AQUAFORTIS;So;0;ON;;;;;N;;;;; 1F706;ALCHEMICAL SYMBOL FOR AQUA REGIA;So;0;ON;;;;;N;;;;; 1F707;ALCHEMICAL SYMBOL FOR AQUA REGIA-2;So;0;ON;;;;;N;;;;; 1F708;ALCHEMICAL SYMBOL FOR AQUA VITAE;So;0;ON;;;;;N;;;;; 1F709;ALCHEMICAL SYMBOL FOR AQUA VITAE-2;So;0;ON;;;;;N;;;;; 1F70A;ALCHEMICAL SYMBOL FOR VINEGAR;So;0;ON;;;;;N;;;;; 1F70B;ALCHEMICAL SYMBOL FOR VINEGAR-2;So;0;ON;;;;;N;;;;; 1F70C;ALCHEMICAL SYMBOL FOR VINEGAR-3;So;0;ON;;;;;N;;;;; 1F70D;ALCHEMICAL SYMBOL FOR SULFUR;So;0;ON;;;;;N;;;;; 1F70E;ALCHEMICAL SYMBOL FOR PHILOSOPHERS SULFUR;So;0;ON;;;;;N;;;;; 1F70F;ALCHEMICAL SYMBOL FOR BLACK SULFUR;So;0;ON;;;;;N;;;;; 1F710;ALCHEMICAL SYMBOL FOR MERCURY SUBLIMATE;So;0;ON;;;;;N;;;;; 1F711;ALCHEMICAL SYMBOL FOR MERCURY SUBLIMATE-2;So;0;ON;;;;;N;;;;; 1F712;ALCHEMICAL SYMBOL FOR MERCURY SUBLIMATE-3;So;0;ON;;;;;N;;;;; 1F713;ALCHEMICAL SYMBOL FOR CINNABAR;So;0;ON;;;;;N;;;;; 1F714;ALCHEMICAL SYMBOL FOR SALT;So;0;ON;;;;;N;;;;; 1F715;ALCHEMICAL SYMBOL FOR NITRE;So;0;ON;;;;;N;;;;; 1F716;ALCHEMICAL SYMBOL FOR VITRIOL;So;0;ON;;;;;N;;;;; 1F717;ALCHEMICAL SYMBOL FOR VITRIOL-2;So;0;ON;;;;;N;;;;; 1F718;ALCHEMICAL SYMBOL FOR ROCK SALT;So;0;ON;;;;;N;;;;; 1F719;ALCHEMICAL SYMBOL FOR ROCK SALT-2;So;0;ON;;;;;N;;;;; 1F71A;ALCHEMICAL SYMBOL FOR GOLD;So;0;ON;;;;;N;;;;; 1F71B;ALCHEMICAL SYMBOL FOR SILVER;So;0;ON;;;;;N;;;;; 1F71C;ALCHEMICAL SYMBOL FOR IRON ORE;So;0;ON;;;;;N;;;;; 1F71D;ALCHEMICAL SYMBOL FOR IRON ORE-2;So;0;ON;;;;;N;;;;; 1F71E;ALCHEMICAL SYMBOL FOR CROCUS OF IRON;So;0;ON;;;;;N;;;;; 1F71F;ALCHEMICAL SYMBOL FOR REGULUS OF IRON;So;0;ON;;;;;N;;;;; 1F720;ALCHEMICAL SYMBOL FOR COPPER ORE;So;0;ON;;;;;N;;;;; 1F721;ALCHEMICAL SYMBOL FOR IRON-COPPER ORE;So;0;ON;;;;;N;;;;; 1F722;ALCHEMICAL SYMBOL FOR SUBLIMATE OF COPPER;So;0;ON;;;;;N;;;;; 1F723;ALCHEMICAL SYMBOL FOR CROCUS OF COPPER;So;0;ON;;;;;N;;;;; 1F724;ALCHEMICAL SYMBOL FOR CROCUS OF COPPER-2;So;0;ON;;;;;N;;;;; 1F725;ALCHEMICAL SYMBOL FOR COPPER ANTIMONIATE;So;0;ON;;;;;N;;;;; 1F726;ALCHEMICAL SYMBOL FOR SALT OF COPPER ANTIMONIATE;So;0;ON;;;;;N;;;;; 1F727;ALCHEMICAL SYMBOL FOR SUBLIMATE OF SALT OF COPPER;So;0;ON;;;;;N;;;;; 1F728;ALCHEMICAL SYMBOL FOR VERDIGRIS;So;0;ON;;;;;N;;;;; 1F729;ALCHEMICAL SYMBOL FOR TIN ORE;So;0;ON;;;;;N;;;;; 1F72A;ALCHEMICAL SYMBOL FOR LEAD ORE;So;0;ON;;;;;N;;;;; 1F72B;ALCHEMICAL SYMBOL FOR ANTIMONY ORE;So;0;ON;;;;;N;;;;; 1F72C;ALCHEMICAL SYMBOL FOR SUBLIMATE OF ANTIMONY;So;0;ON;;;;;N;;;;; 1F72D;ALCHEMICAL SYMBOL FOR SALT OF ANTIMONY;So;0;ON;;;;;N;;;;; 1F72E;ALCHEMICAL SYMBOL FOR SUBLIMATE OF SALT OF ANTIMONY;So;0;ON;;;;;N;;;;; 1F72F;ALCHEMICAL SYMBOL FOR VINEGAR OF ANTIMONY;So;0;ON;;;;;N;;;;; 1F730;ALCHEMICAL SYMBOL FOR REGULUS OF ANTIMONY;So;0;ON;;;;;N;;;;; 1F731;ALCHEMICAL SYMBOL FOR REGULUS OF ANTIMONY-2;So;0;ON;;;;;N;;;;; 1F732;ALCHEMICAL SYMBOL FOR REGULUS;So;0;ON;;;;;N;;;;; 1F733;ALCHEMICAL SYMBOL FOR REGULUS-2;So;0;ON;;;;;N;;;;; 1F734;ALCHEMICAL SYMBOL FOR REGULUS-3;So;0;ON;;;;;N;;;;; 1F735;ALCHEMICAL SYMBOL FOR REGULUS-4;So;0;ON;;;;;N;;;;; 1F736;ALCHEMICAL SYMBOL FOR ALKALI;So;0;ON;;;;;N;;;;; 1F737;ALCHEMICAL SYMBOL FOR ALKALI-2;So;0;ON;;;;;N;;;;; 1F738;ALCHEMICAL SYMBOL FOR MARCASITE;So;0;ON;;;;;N;;;;; 1F739;ALCHEMICAL SYMBOL FOR SAL-AMMONIAC;So;0;ON;;;;;N;;;;; 1F73A;ALCHEMICAL SYMBOL FOR ARSENIC;So;0;ON;;;;;N;;;;; 1F73B;ALCHEMICAL SYMBOL FOR REALGAR;So;0;ON;;;;;N;;;;; 1F73C;ALCHEMICAL SYMBOL FOR REALGAR-2;So;0;ON;;;;;N;;;;; 1F73D;ALCHEMICAL SYMBOL FOR AURIPIGMENT;So;0;ON;;;;;N;;;;; 1F73E;ALCHEMICAL SYMBOL FOR BISMUTH ORE;So;0;ON;;;;;N;;;;; 1F73F;ALCHEMICAL SYMBOL FOR TARTAR;So;0;ON;;;;;N;;;;; 1F740;ALCHEMICAL SYMBOL FOR TARTAR-2;So;0;ON;;;;;N;;;;; 1F741;ALCHEMICAL SYMBOL FOR QUICK LIME;So;0;ON;;;;;N;;;;; 1F742;ALCHEMICAL SYMBOL FOR BORAX;So;0;ON;;;;;N;;;;; 1F743;ALCHEMICAL SYMBOL FOR BORAX-2;So;0;ON;;;;;N;;;;; 1F744;ALCHEMICAL SYMBOL FOR BORAX-3;So;0;ON;;;;;N;;;;; 1F745;ALCHEMICAL SYMBOL FOR ALUM;So;0;ON;;;;;N;;;;; 1F746;ALCHEMICAL SYMBOL FOR OIL;So;0;ON;;;;;N;;;;; 1F747;ALCHEMICAL SYMBOL FOR SPIRIT;So;0;ON;;;;;N;;;;; 1F748;ALCHEMICAL SYMBOL FOR TINCTURE;So;0;ON;;;;;N;;;;; 1F749;ALCHEMICAL SYMBOL FOR GUM;So;0;ON;;;;;N;;;;; 1F74A;ALCHEMICAL SYMBOL FOR WAX;So;0;ON;;;;;N;;;;; 1F74B;ALCHEMICAL SYMBOL FOR POWDER;So;0;ON;;;;;N;;;;; 1F74C;ALCHEMICAL SYMBOL FOR CALX;So;0;ON;;;;;N;;;;; 1F74D;ALCHEMICAL SYMBOL FOR TUTTY;So;0;ON;;;;;N;;;;; 1F74E;ALCHEMICAL SYMBOL FOR CAPUT MORTUUM;So;0;ON;;;;;N;;;;; 1F74F;ALCHEMICAL SYMBOL FOR SCEPTER OF JOVE;So;0;ON;;;;;N;;;;; 1F750;ALCHEMICAL SYMBOL FOR CADUCEUS;So;0;ON;;;;;N;;;;; 1F751;ALCHEMICAL SYMBOL FOR TRIDENT;So;0;ON;;;;;N;;;;; 1F752;ALCHEMICAL SYMBOL FOR STARRED TRIDENT;So;0;ON;;;;;N;;;;; 1F753;ALCHEMICAL SYMBOL FOR LODESTONE;So;0;ON;;;;;N;;;;; 1F754;ALCHEMICAL SYMBOL FOR SOAP;So;0;ON;;;;;N;;;;; 1F755;ALCHEMICAL SYMBOL FOR URINE;So;0;ON;;;;;N;;;;; 1F756;ALCHEMICAL SYMBOL FOR HORSE DUNG;So;0;ON;;;;;N;;;;; 1F757;ALCHEMICAL SYMBOL FOR ASHES;So;0;ON;;;;;N;;;;; 1F758;ALCHEMICAL SYMBOL FOR POT ASHES;So;0;ON;;;;;N;;;;; 1F759;ALCHEMICAL SYMBOL FOR BRICK;So;0;ON;;;;;N;;;;; 1F75A;ALCHEMICAL SYMBOL FOR POWDERED BRICK;So;0;ON;;;;;N;;;;; 1F75B;ALCHEMICAL SYMBOL FOR AMALGAM;So;0;ON;;;;;N;;;;; 1F75C;ALCHEMICAL SYMBOL FOR STRATUM SUPER STRATUM;So;0;ON;;;;;N;;;;; 1F75D;ALCHEMICAL SYMBOL FOR STRATUM SUPER STRATUM-2;So;0;ON;;;;;N;;;;; 1F75E;ALCHEMICAL SYMBOL FOR SUBLIMATION;So;0;ON;;;;;N;;;;; 1F75F;ALCHEMICAL SYMBOL FOR PRECIPITATE;So;0;ON;;;;;N;;;;; 1F760;ALCHEMICAL SYMBOL FOR DISTILL;So;0;ON;;;;;N;;;;; 1F761;ALCHEMICAL SYMBOL FOR DISSOLVE;So;0;ON;;;;;N;;;;; 1F762;ALCHEMICAL SYMBOL FOR DISSOLVE-2;So;0;ON;;;;;N;;;;; 1F763;ALCHEMICAL SYMBOL FOR PURIFY;So;0;ON;;;;;N;;;;; 1F764;ALCHEMICAL SYMBOL FOR PUTREFACTION;So;0;ON;;;;;N;;;;; 1F765;ALCHEMICAL SYMBOL FOR CRUCIBLE;So;0;ON;;;;;N;;;;; 1F766;ALCHEMICAL SYMBOL FOR CRUCIBLE-2;So;0;ON;;;;;N;;;;; 1F767;ALCHEMICAL SYMBOL FOR CRUCIBLE-3;So;0;ON;;;;;N;;;;; 1F768;ALCHEMICAL SYMBOL FOR CRUCIBLE-4;So;0;ON;;;;;N;;;;; 1F769;ALCHEMICAL SYMBOL FOR CRUCIBLE-5;So;0;ON;;;;;N;;;;; 1F76A;ALCHEMICAL SYMBOL FOR ALEMBIC;So;0;ON;;;;;N;;;;; 1F76B;ALCHEMICAL SYMBOL FOR BATH OF MARY;So;0;ON;;;;;N;;;;; 1F76C;ALCHEMICAL SYMBOL FOR BATH OF VAPOURS;So;0;ON;;;;;N;;;;; 1F76D;ALCHEMICAL SYMBOL FOR RETORT;So;0;ON;;;;;N;;;;; 1F76E;ALCHEMICAL SYMBOL FOR HOUR;So;0;ON;;;;;N;;;;; 1F76F;ALCHEMICAL SYMBOL FOR NIGHT;So;0;ON;;;;;N;;;;; 1F770;ALCHEMICAL SYMBOL FOR DAY-NIGHT;So;0;ON;;;;;N;;;;; 1F771;ALCHEMICAL SYMBOL FOR MONTH;So;0;ON;;;;;N;;;;; 1F772;ALCHEMICAL SYMBOL FOR HALF DRAM;So;0;ON;;;;;N;;;;; 1F773;ALCHEMICAL SYMBOL FOR HALF OUNCE;So;0;ON;;;;;N;;;;; 1F780;BLACK LEFT-POINTING ISOSCELES RIGHT TRIANGLE;So;0;ON;;;;;N;;;;; 1F781;BLACK UP-POINTING ISOSCELES RIGHT TRIANGLE;So;0;ON;;;;;N;;;;; 1F782;BLACK RIGHT-POINTING ISOSCELES RIGHT TRIANGLE;So;0;ON;;;;;N;;;;; 1F783;BLACK DOWN-POINTING ISOSCELES RIGHT TRIANGLE;So;0;ON;;;;;N;;;;; 1F784;BLACK SLIGHTLY SMALL CIRCLE;So;0;ON;;;;;N;;;;; 1F785;MEDIUM BOLD WHITE CIRCLE;So;0;ON;;;;;N;;;;; 1F786;BOLD WHITE CIRCLE;So;0;ON;;;;;N;;;;; 1F787;HEAVY WHITE CIRCLE;So;0;ON;;;;;N;;;;; 1F788;VERY HEAVY WHITE CIRCLE;So;0;ON;;;;;N;;;;; 1F789;EXTREMELY HEAVY WHITE CIRCLE;So;0;ON;;;;;N;;;;; 1F78A;WHITE CIRCLE CONTAINING BLACK SMALL CIRCLE;So;0;ON;;;;;N;;;;; 1F78B;ROUND TARGET;So;0;ON;;;;;N;;;;; 1F78C;BLACK TINY SQUARE;So;0;ON;;;;;N;;;;; 1F78D;BLACK SLIGHTLY SMALL SQUARE;So;0;ON;;;;;N;;;;; 1F78E;LIGHT WHITE SQUARE;So;0;ON;;;;;N;;;;; 1F78F;MEDIUM WHITE SQUARE;So;0;ON;;;;;N;;;;; 1F790;BOLD WHITE SQUARE;So;0;ON;;;;;N;;;;; 1F791;HEAVY WHITE SQUARE;So;0;ON;;;;;N;;;;; 1F792;VERY HEAVY WHITE SQUARE;So;0;ON;;;;;N;;;;; 1F793;EXTREMELY HEAVY WHITE SQUARE;So;0;ON;;;;;N;;;;; 1F794;WHITE SQUARE CONTAINING BLACK VERY SMALL SQUARE;So;0;ON;;;;;N;;;;; 1F795;WHITE SQUARE CONTAINING BLACK MEDIUM SQUARE;So;0;ON;;;;;N;;;;; 1F796;SQUARE TARGET;So;0;ON;;;;;N;;;;; 1F797;BLACK TINY DIAMOND;So;0;ON;;;;;N;;;;; 1F798;BLACK VERY SMALL DIAMOND;So;0;ON;;;;;N;;;;; 1F799;BLACK MEDIUM SMALL DIAMOND;So;0;ON;;;;;N;;;;; 1F79A;WHITE DIAMOND CONTAINING BLACK VERY SMALL DIAMOND;So;0;ON;;;;;N;;;;; 1F79B;WHITE DIAMOND CONTAINING BLACK MEDIUM DIAMOND;So;0;ON;;;;;N;;;;; 1F79C;DIAMOND TARGET;So;0;ON;;;;;N;;;;; 1F79D;BLACK TINY LOZENGE;So;0;ON;;;;;N;;;;; 1F79E;BLACK VERY SMALL LOZENGE;So;0;ON;;;;;N;;;;; 1F79F;BLACK MEDIUM SMALL LOZENGE;So;0;ON;;;;;N;;;;; 1F7A0;WHITE LOZENGE CONTAINING BLACK SMALL LOZENGE;So;0;ON;;;;;N;;;;; 1F7A1;THIN GREEK CROSS;So;0;ON;;;;;N;;;;; 1F7A2;LIGHT GREEK CROSS;So;0;ON;;;;;N;;;;; 1F7A3;MEDIUM GREEK CROSS;So;0;ON;;;;;N;;;;; 1F7A4;BOLD GREEK CROSS;So;0;ON;;;;;N;;;;; 1F7A5;VERY BOLD GREEK CROSS;So;0;ON;;;;;N;;;;; 1F7A6;VERY HEAVY GREEK CROSS;So;0;ON;;;;;N;;;;; 1F7A7;EXTREMELY HEAVY GREEK CROSS;So;0;ON;;;;;N;;;;; 1F7A8;THIN SALTIRE;So;0;ON;;;;;N;;;;; 1F7A9;LIGHT SALTIRE;So;0;ON;;;;;N;;;;; 1F7AA;MEDIUM SALTIRE;So;0;ON;;;;;N;;;;; 1F7AB;BOLD SALTIRE;So;0;ON;;;;;N;;;;; 1F7AC;HEAVY SALTIRE;So;0;ON;;;;;N;;;;; 1F7AD;VERY HEAVY SALTIRE;So;0;ON;;;;;N;;;;; 1F7AE;EXTREMELY HEAVY SALTIRE;So;0;ON;;;;;N;;;;; 1F7AF;LIGHT FIVE SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 1F7B0;MEDIUM FIVE SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 1F7B1;BOLD FIVE SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 1F7B2;HEAVY FIVE SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 1F7B3;VERY HEAVY FIVE SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 1F7B4;EXTREMELY HEAVY FIVE SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 1F7B5;LIGHT SIX SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 1F7B6;MEDIUM SIX SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 1F7B7;BOLD SIX SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 1F7B8;HEAVY SIX SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 1F7B9;VERY HEAVY SIX SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 1F7BA;EXTREMELY HEAVY SIX SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 1F7BB;LIGHT EIGHT SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 1F7BC;MEDIUM EIGHT SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 1F7BD;BOLD EIGHT SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 1F7BE;HEAVY EIGHT SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 1F7BF;VERY HEAVY EIGHT SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 1F7C0;LIGHT THREE POINTED BLACK STAR;So;0;ON;;;;;N;;;;; 1F7C1;MEDIUM THREE POINTED BLACK STAR;So;0;ON;;;;;N;;;;; 1F7C2;THREE POINTED BLACK STAR;So;0;ON;;;;;N;;;;; 1F7C3;MEDIUM THREE POINTED PINWHEEL STAR;So;0;ON;;;;;N;;;;; 1F7C4;LIGHT FOUR POINTED BLACK STAR;So;0;ON;;;;;N;;;;; 1F7C5;MEDIUM FOUR POINTED BLACK STAR;So;0;ON;;;;;N;;;;; 1F7C6;FOUR POINTED BLACK STAR;So;0;ON;;;;;N;;;;; 1F7C7;MEDIUM FOUR POINTED PINWHEEL STAR;So;0;ON;;;;;N;;;;; 1F7C8;REVERSE LIGHT FOUR POINTED PINWHEEL STAR;So;0;ON;;;;;N;;;;; 1F7C9;LIGHT FIVE POINTED BLACK STAR;So;0;ON;;;;;N;;;;; 1F7CA;HEAVY FIVE POINTED BLACK STAR;So;0;ON;;;;;N;;;;; 1F7CB;MEDIUM SIX POINTED BLACK STAR;So;0;ON;;;;;N;;;;; 1F7CC;HEAVY SIX POINTED BLACK STAR;So;0;ON;;;;;N;;;;; 1F7CD;SIX POINTED PINWHEEL STAR;So;0;ON;;;;;N;;;;; 1F7CE;MEDIUM EIGHT POINTED BLACK STAR;So;0;ON;;;;;N;;;;; 1F7CF;HEAVY EIGHT POINTED BLACK STAR;So;0;ON;;;;;N;;;;; 1F7D0;VERY HEAVY EIGHT POINTED BLACK STAR;So;0;ON;;;;;N;;;;; 1F7D1;HEAVY EIGHT POINTED PINWHEEL STAR;So;0;ON;;;;;N;;;;; 1F7D2;LIGHT TWELVE POINTED BLACK STAR;So;0;ON;;;;;N;;;;; 1F7D3;HEAVY TWELVE POINTED BLACK STAR;So;0;ON;;;;;N;;;;; 1F7D4;HEAVY TWELVE POINTED PINWHEEL STAR;So;0;ON;;;;;N;;;;; 1F800;LEFTWARDS ARROW WITH SMALL TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; 1F801;UPWARDS ARROW WITH SMALL TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; 1F802;RIGHTWARDS ARROW WITH SMALL TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; 1F803;DOWNWARDS ARROW WITH SMALL TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; 1F804;LEFTWARDS ARROW WITH MEDIUM TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; 1F805;UPWARDS ARROW WITH MEDIUM TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; 1F806;RIGHTWARDS ARROW WITH MEDIUM TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; 1F807;DOWNWARDS ARROW WITH MEDIUM TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; 1F808;LEFTWARDS ARROW WITH LARGE TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; 1F809;UPWARDS ARROW WITH LARGE TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; 1F80A;RIGHTWARDS ARROW WITH LARGE TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; 1F80B;DOWNWARDS ARROW WITH LARGE TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; 1F810;LEFTWARDS ARROW WITH SMALL EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; 1F811;UPWARDS ARROW WITH SMALL EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; 1F812;RIGHTWARDS ARROW WITH SMALL EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; 1F813;DOWNWARDS ARROW WITH SMALL EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; 1F814;LEFTWARDS ARROW WITH EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; 1F815;UPWARDS ARROW WITH EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; 1F816;RIGHTWARDS ARROW WITH EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; 1F817;DOWNWARDS ARROW WITH EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; 1F818;HEAVY LEFTWARDS ARROW WITH EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; 1F819;HEAVY UPWARDS ARROW WITH EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; 1F81A;HEAVY RIGHTWARDS ARROW WITH EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; 1F81B;HEAVY DOWNWARDS ARROW WITH EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; 1F81C;HEAVY LEFTWARDS ARROW WITH LARGE EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; 1F81D;HEAVY UPWARDS ARROW WITH LARGE EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; 1F81E;HEAVY RIGHTWARDS ARROW WITH LARGE EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; 1F81F;HEAVY DOWNWARDS ARROW WITH LARGE EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; 1F820;LEFTWARDS TRIANGLE-HEADED ARROW WITH NARROW SHAFT;So;0;ON;;;;;N;;;;; 1F821;UPWARDS TRIANGLE-HEADED ARROW WITH NARROW SHAFT;So;0;ON;;;;;N;;;;; 1F822;RIGHTWARDS TRIANGLE-HEADED ARROW WITH NARROW SHAFT;So;0;ON;;;;;N;;;;; 1F823;DOWNWARDS TRIANGLE-HEADED ARROW WITH NARROW SHAFT;So;0;ON;;;;;N;;;;; 1F824;LEFTWARDS TRIANGLE-HEADED ARROW WITH MEDIUM SHAFT;So;0;ON;;;;;N;;;;; 1F825;UPWARDS TRIANGLE-HEADED ARROW WITH MEDIUM SHAFT;So;0;ON;;;;;N;;;;; 1F826;RIGHTWARDS TRIANGLE-HEADED ARROW WITH MEDIUM SHAFT;So;0;ON;;;;;N;;;;; 1F827;DOWNWARDS TRIANGLE-HEADED ARROW WITH MEDIUM SHAFT;So;0;ON;;;;;N;;;;; 1F828;LEFTWARDS TRIANGLE-HEADED ARROW WITH BOLD SHAFT;So;0;ON;;;;;N;;;;; 1F829;UPWARDS TRIANGLE-HEADED ARROW WITH BOLD SHAFT;So;0;ON;;;;;N;;;;; 1F82A;RIGHTWARDS TRIANGLE-HEADED ARROW WITH BOLD SHAFT;So;0;ON;;;;;N;;;;; 1F82B;DOWNWARDS TRIANGLE-HEADED ARROW WITH BOLD SHAFT;So;0;ON;;;;;N;;;;; 1F82C;LEFTWARDS TRIANGLE-HEADED ARROW WITH HEAVY SHAFT;So;0;ON;;;;;N;;;;; 1F82D;UPWARDS TRIANGLE-HEADED ARROW WITH HEAVY SHAFT;So;0;ON;;;;;N;;;;; 1F82E;RIGHTWARDS TRIANGLE-HEADED ARROW WITH HEAVY SHAFT;So;0;ON;;;;;N;;;;; 1F82F;DOWNWARDS TRIANGLE-HEADED ARROW WITH HEAVY SHAFT;So;0;ON;;;;;N;;;;; 1F830;LEFTWARDS TRIANGLE-HEADED ARROW WITH VERY HEAVY SHAFT;So;0;ON;;;;;N;;;;; 1F831;UPWARDS TRIANGLE-HEADED ARROW WITH VERY HEAVY SHAFT;So;0;ON;;;;;N;;;;; 1F832;RIGHTWARDS TRIANGLE-HEADED ARROW WITH VERY HEAVY SHAFT;So;0;ON;;;;;N;;;;; 1F833;DOWNWARDS TRIANGLE-HEADED ARROW WITH VERY HEAVY SHAFT;So;0;ON;;;;;N;;;;; 1F834;LEFTWARDS FINGER-POST ARROW;So;0;ON;;;;;N;;;;; 1F835;UPWARDS FINGER-POST ARROW;So;0;ON;;;;;N;;;;; 1F836;RIGHTWARDS FINGER-POST ARROW;So;0;ON;;;;;N;;;;; 1F837;DOWNWARDS FINGER-POST ARROW;So;0;ON;;;;;N;;;;; 1F838;LEFTWARDS SQUARED ARROW;So;0;ON;;;;;N;;;;; 1F839;UPWARDS SQUARED ARROW;So;0;ON;;;;;N;;;;; 1F83A;RIGHTWARDS SQUARED ARROW;So;0;ON;;;;;N;;;;; 1F83B;DOWNWARDS SQUARED ARROW;So;0;ON;;;;;N;;;;; 1F83C;LEFTWARDS COMPRESSED ARROW;So;0;ON;;;;;N;;;;; 1F83D;UPWARDS COMPRESSED ARROW;So;0;ON;;;;;N;;;;; 1F83E;RIGHTWARDS COMPRESSED ARROW;So;0;ON;;;;;N;;;;; 1F83F;DOWNWARDS COMPRESSED ARROW;So;0;ON;;;;;N;;;;; 1F840;LEFTWARDS HEAVY COMPRESSED ARROW;So;0;ON;;;;;N;;;;; 1F841;UPWARDS HEAVY COMPRESSED ARROW;So;0;ON;;;;;N;;;;; 1F842;RIGHTWARDS HEAVY COMPRESSED ARROW;So;0;ON;;;;;N;;;;; 1F843;DOWNWARDS HEAVY COMPRESSED ARROW;So;0;ON;;;;;N;;;;; 1F844;LEFTWARDS HEAVY ARROW;So;0;ON;;;;;N;;;;; 1F845;UPWARDS HEAVY ARROW;So;0;ON;;;;;N;;;;; 1F846;RIGHTWARDS HEAVY ARROW;So;0;ON;;;;;N;;;;; 1F847;DOWNWARDS HEAVY ARROW;So;0;ON;;;;;N;;;;; 1F850;LEFTWARDS SANS-SERIF ARROW;So;0;ON;;;;;N;;;;; 1F851;UPWARDS SANS-SERIF ARROW;So;0;ON;;;;;N;;;;; 1F852;RIGHTWARDS SANS-SERIF ARROW;So;0;ON;;;;;N;;;;; 1F853;DOWNWARDS SANS-SERIF ARROW;So;0;ON;;;;;N;;;;; 1F854;NORTH WEST SANS-SERIF ARROW;So;0;ON;;;;;N;;;;; 1F855;NORTH EAST SANS-SERIF ARROW;So;0;ON;;;;;N;;;;; 1F856;SOUTH EAST SANS-SERIF ARROW;So;0;ON;;;;;N;;;;; 1F857;SOUTH WEST SANS-SERIF ARROW;So;0;ON;;;;;N;;;;; 1F858;LEFT RIGHT SANS-SERIF ARROW;So;0;ON;;;;;N;;;;; 1F859;UP DOWN SANS-SERIF ARROW;So;0;ON;;;;;N;;;;; 1F860;WIDE-HEADED LEFTWARDS LIGHT BARB ARROW;So;0;ON;;;;;N;;;;; 1F861;WIDE-HEADED UPWARDS LIGHT BARB ARROW;So;0;ON;;;;;N;;;;; 1F862;WIDE-HEADED RIGHTWARDS LIGHT BARB ARROW;So;0;ON;;;;;N;;;;; 1F863;WIDE-HEADED DOWNWARDS LIGHT BARB ARROW;So;0;ON;;;;;N;;;;; 1F864;WIDE-HEADED NORTH WEST LIGHT BARB ARROW;So;0;ON;;;;;N;;;;; 1F865;WIDE-HEADED NORTH EAST LIGHT BARB ARROW;So;0;ON;;;;;N;;;;; 1F866;WIDE-HEADED SOUTH EAST LIGHT BARB ARROW;So;0;ON;;;;;N;;;;; 1F867;WIDE-HEADED SOUTH WEST LIGHT BARB ARROW;So;0;ON;;;;;N;;;;; 1F868;WIDE-HEADED LEFTWARDS BARB ARROW;So;0;ON;;;;;N;;;;; 1F869;WIDE-HEADED UPWARDS BARB ARROW;So;0;ON;;;;;N;;;;; 1F86A;WIDE-HEADED RIGHTWARDS BARB ARROW;So;0;ON;;;;;N;;;;; 1F86B;WIDE-HEADED DOWNWARDS BARB ARROW;So;0;ON;;;;;N;;;;; 1F86C;WIDE-HEADED NORTH WEST BARB ARROW;So;0;ON;;;;;N;;;;; 1F86D;WIDE-HEADED NORTH EAST BARB ARROW;So;0;ON;;;;;N;;;;; 1F86E;WIDE-HEADED SOUTH EAST BARB ARROW;So;0;ON;;;;;N;;;;; 1F86F;WIDE-HEADED SOUTH WEST BARB ARROW;So;0;ON;;;;;N;;;;; 1F870;WIDE-HEADED LEFTWARDS MEDIUM BARB ARROW;So;0;ON;;;;;N;;;;; 1F871;WIDE-HEADED UPWARDS MEDIUM BARB ARROW;So;0;ON;;;;;N;;;;; 1F872;WIDE-HEADED RIGHTWARDS MEDIUM BARB ARROW;So;0;ON;;;;;N;;;;; 1F873;WIDE-HEADED DOWNWARDS MEDIUM BARB ARROW;So;0;ON;;;;;N;;;;; 1F874;WIDE-HEADED NORTH WEST MEDIUM BARB ARROW;So;0;ON;;;;;N;;;;; 1F875;WIDE-HEADED NORTH EAST MEDIUM BARB ARROW;So;0;ON;;;;;N;;;;; 1F876;WIDE-HEADED SOUTH EAST MEDIUM BARB ARROW;So;0;ON;;;;;N;;;;; 1F877;WIDE-HEADED SOUTH WEST MEDIUM BARB ARROW;So;0;ON;;;;;N;;;;; 1F878;WIDE-HEADED LEFTWARDS HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; 1F879;WIDE-HEADED UPWARDS HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; 1F87A;WIDE-HEADED RIGHTWARDS HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; 1F87B;WIDE-HEADED DOWNWARDS HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; 1F87C;WIDE-HEADED NORTH WEST HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; 1F87D;WIDE-HEADED NORTH EAST HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; 1F87E;WIDE-HEADED SOUTH EAST HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; 1F87F;WIDE-HEADED SOUTH WEST HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; 1F880;WIDE-HEADED LEFTWARDS VERY HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; 1F881;WIDE-HEADED UPWARDS VERY HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; 1F882;WIDE-HEADED RIGHTWARDS VERY HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; 1F883;WIDE-HEADED DOWNWARDS VERY HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; 1F884;WIDE-HEADED NORTH WEST VERY HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; 1F885;WIDE-HEADED NORTH EAST VERY HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; 1F886;WIDE-HEADED SOUTH EAST VERY HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; 1F887;WIDE-HEADED SOUTH WEST VERY HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; 1F890;LEFTWARDS TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; 1F891;UPWARDS TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; 1F892;RIGHTWARDS TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; 1F893;DOWNWARDS TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; 1F894;LEFTWARDS WHITE ARROW WITHIN TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; 1F895;UPWARDS WHITE ARROW WITHIN TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; 1F896;RIGHTWARDS WHITE ARROW WITHIN TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; 1F897;DOWNWARDS WHITE ARROW WITHIN TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; 1F898;LEFTWARDS ARROW WITH NOTCHED TAIL;So;0;ON;;;;;N;;;;; 1F899;UPWARDS ARROW WITH NOTCHED TAIL;So;0;ON;;;;;N;;;;; 1F89A;RIGHTWARDS ARROW WITH NOTCHED TAIL;So;0;ON;;;;;N;;;;; 1F89B;DOWNWARDS ARROW WITH NOTCHED TAIL;So;0;ON;;;;;N;;;;; 1F89C;HEAVY ARROW SHAFT WIDTH ONE;So;0;ON;;;;;N;;;;; 1F89D;HEAVY ARROW SHAFT WIDTH TWO THIRDS;So;0;ON;;;;;N;;;;; 1F89E;HEAVY ARROW SHAFT WIDTH ONE HALF;So;0;ON;;;;;N;;;;; 1F89F;HEAVY ARROW SHAFT WIDTH ONE THIRD;So;0;ON;;;;;N;;;;; 1F8A0;LEFTWARDS BOTTOM-SHADED WHITE ARROW;So;0;ON;;;;;N;;;;; 1F8A1;RIGHTWARDS BOTTOM SHADED WHITE ARROW;So;0;ON;;;;;N;;;;; 1F8A2;LEFTWARDS TOP SHADED WHITE ARROW;So;0;ON;;;;;N;;;;; 1F8A3;RIGHTWARDS TOP SHADED WHITE ARROW;So;0;ON;;;;;N;;;;; 1F8A4;LEFTWARDS LEFT-SHADED WHITE ARROW;So;0;ON;;;;;N;;;;; 1F8A5;RIGHTWARDS RIGHT-SHADED WHITE ARROW;So;0;ON;;;;;N;;;;; 1F8A6;LEFTWARDS RIGHT-SHADED WHITE ARROW;So;0;ON;;;;;N;;;;; 1F8A7;RIGHTWARDS LEFT-SHADED WHITE ARROW;So;0;ON;;;;;N;;;;; 1F8A8;LEFTWARDS BACK-TILTED SHADOWED WHITE ARROW;So;0;ON;;;;;N;;;;; 1F8A9;RIGHTWARDS BACK-TILTED SHADOWED WHITE ARROW;So;0;ON;;;;;N;;;;; 1F8AA;LEFTWARDS FRONT-TILTED SHADOWED WHITE ARROW;So;0;ON;;;;;N;;;;; 1F8AB;RIGHTWARDS FRONT-TILTED SHADOWED WHITE ARROW;So;0;ON;;;;;N;;;;; 1F8AC;WHITE ARROW SHAFT WIDTH ONE;So;0;ON;;;;;N;;;;; 1F8AD;WHITE ARROW SHAFT WIDTH TWO THIRDS;So;0;ON;;;;;N;;;;; 1F910;ZIPPER-MOUTH FACE;So;0;ON;;;;;N;;;;; 1F911;MONEY-MOUTH FACE;So;0;ON;;;;;N;;;;; 1F912;FACE WITH THERMOMETER;So;0;ON;;;;;N;;;;; 1F913;NERD FACE;So;0;ON;;;;;N;;;;; 1F914;THINKING FACE;So;0;ON;;;;;N;;;;; 1F915;FACE WITH HEAD-BANDAGE;So;0;ON;;;;;N;;;;; 1F916;ROBOT FACE;So;0;ON;;;;;N;;;;; 1F917;HUGGING FACE;So;0;ON;;;;;N;;;;; 1F918;SIGN OF THE HORNS;So;0;ON;;;;;N;;;;; 1F919;CALL ME HAND;So;0;ON;;;;;N;;;;; 1F91A;RAISED BACK OF HAND;So;0;ON;;;;;N;;;;; 1F91B;LEFT-FACING FIST;So;0;ON;;;;;N;;;;; 1F91C;RIGHT-FACING FIST;So;0;ON;;;;;N;;;;; 1F91D;HANDSHAKE;So;0;ON;;;;;N;;;;; 1F91E;HAND WITH INDEX AND MIDDLE FINGERS CROSSED;So;0;ON;;;;;N;;;;; 1F920;FACE WITH COWBOY HAT;So;0;ON;;;;;N;;;;; 1F921;CLOWN FACE;So;0;ON;;;;;N;;;;; 1F922;NAUSEATED FACE;So;0;ON;;;;;N;;;;; 1F923;ROLLING ON THE FLOOR LAUGHING;So;0;ON;;;;;N;;;;; 1F924;DROOLING FACE;So;0;ON;;;;;N;;;;; 1F925;LYING FACE;So;0;ON;;;;;N;;;;; 1F926;FACE PALM;So;0;ON;;;;;N;;;;; 1F927;SNEEZING FACE;So;0;ON;;;;;N;;;;; 1F930;PREGNANT WOMAN;So;0;ON;;;;;N;;;;; 1F933;SELFIE;So;0;ON;;;;;N;;;;; 1F934;PRINCE;So;0;ON;;;;;N;;;;; 1F935;MAN IN TUXEDO;So;0;ON;;;;;N;;;;; 1F936;MOTHER CHRISTMAS;So;0;ON;;;;;N;;;;; 1F937;SHRUG;So;0;ON;;;;;N;;;;; 1F938;PERSON DOING CARTWHEEL;So;0;ON;;;;;N;;;;; 1F939;JUGGLING;So;0;ON;;;;;N;;;;; 1F93A;FENCER;So;0;ON;;;;;N;;;;; 1F93B;MODERN PENTATHLON;So;0;ON;;;;;N;;;;; 1F93C;WRESTLERS;So;0;ON;;;;;N;;;;; 1F93D;WATER POLO;So;0;ON;;;;;N;;;;; 1F93E;HANDBALL;So;0;ON;;;;;N;;;;; 1F940;WILTED FLOWER;So;0;ON;;;;;N;;;;; 1F941;DRUM WITH DRUMSTICKS;So;0;ON;;;;;N;;;;; 1F942;CLINKING GLASSES;So;0;ON;;;;;N;;;;; 1F943;TUMBLER GLASS;So;0;ON;;;;;N;;;;; 1F944;SPOON;So;0;ON;;;;;N;;;;; 1F945;GOAL NET;So;0;ON;;;;;N;;;;; 1F946;RIFLE;So;0;ON;;;;;N;;;;; 1F947;FIRST PLACE MEDAL;So;0;ON;;;;;N;;;;; 1F948;SECOND PLACE MEDAL;So;0;ON;;;;;N;;;;; 1F949;THIRD PLACE MEDAL;So;0;ON;;;;;N;;;;; 1F94A;BOXING GLOVE;So;0;ON;;;;;N;;;;; 1F94B;MARTIAL ARTS UNIFORM;So;0;ON;;;;;N;;;;; 1F950;CROISSANT;So;0;ON;;;;;N;;;;; 1F951;AVOCADO;So;0;ON;;;;;N;;;;; 1F952;CUCUMBER;So;0;ON;;;;;N;;;;; 1F953;BACON;So;0;ON;;;;;N;;;;; 1F954;POTATO;So;0;ON;;;;;N;;;;; 1F955;CARROT;So;0;ON;;;;;N;;;;; 1F956;BAGUETTE BREAD;So;0;ON;;;;;N;;;;; 1F957;GREEN SALAD;So;0;ON;;;;;N;;;;; 1F958;SHALLOW PAN OF FOOD;So;0;ON;;;;;N;;;;; 1F959;STUFFED FLATBREAD;So;0;ON;;;;;N;;;;; 1F95A;EGG;So;0;ON;;;;;N;;;;; 1F95B;GLASS OF MILK;So;0;ON;;;;;N;;;;; 1F95C;PEANUTS;So;0;ON;;;;;N;;;;; 1F95D;KIWIFRUIT;So;0;ON;;;;;N;;;;; 1F95E;PANCAKES;So;0;ON;;;;;N;;;;; 1F980;CRAB;So;0;ON;;;;;N;;;;; 1F981;LION FACE;So;0;ON;;;;;N;;;;; 1F982;SCORPION;So;0;ON;;;;;N;;;;; 1F983;TURKEY;So;0;ON;;;;;N;;;;; 1F984;UNICORN FACE;So;0;ON;;;;;N;;;;; 1F985;EAGLE;So;0;ON;;;;;N;;;;; 1F986;DUCK;So;0;ON;;;;;N;;;;; 1F987;BAT;So;0;ON;;;;;N;;;;; 1F988;SHARK;So;0;ON;;;;;N;;;;; 1F989;OWL;So;0;ON;;;;;N;;;;; 1F98A;FOX FACE;So;0;ON;;;;;N;;;;; 1F98B;BUTTERFLY;So;0;ON;;;;;N;;;;; 1F98C;DEER;So;0;ON;;;;;N;;;;; 1F98D;GORILLA;So;0;ON;;;;;N;;;;; 1F98E;LIZARD;So;0;ON;;;;;N;;;;; 1F98F;RHINOCEROS;So;0;ON;;;;;N;;;;; 1F990;SHRIMP;So;0;ON;;;;;N;;;;; 1F991;SQUID;So;0;ON;;;;;N;;;;; 1F9C0;CHEESE WEDGE;So;0;ON;;;;;N;;;;; 20000;<CJK Ideograph Extension B, First>;Lo;0;L;;;;;N;;;;; 2A6D6;<CJK Ideograph Extension B, Last>;Lo;0;L;;;;;N;;;;; 2A700;<CJK Ideograph Extension C, First>;Lo;0;L;;;;;N;;;;; 2B734;<CJK Ideograph Extension C, Last>;Lo;0;L;;;;;N;;;;; 2B740;<CJK Ideograph Extension D, First>;Lo;0;L;;;;;N;;;;; 2B81D;<CJK Ideograph Extension D, Last>;Lo;0;L;;;;;N;;;;; 2B820;<CJK Ideograph Extension E, First>;Lo;0;L;;;;;N;;;;; 2CEA1;<CJK Ideograph Extension E, Last>;Lo;0;L;;;;;N;;;;; 2F800;CJK COMPATIBILITY IDEOGRAPH-2F800;Lo;0;L;4E3D;;;;N;;;;; 2F801;CJK COMPATIBILITY IDEOGRAPH-2F801;Lo;0;L;4E38;;;;N;;;;; 2F802;CJK COMPATIBILITY IDEOGRAPH-2F802;Lo;0;L;4E41;;;;N;;;;; 2F803;CJK COMPATIBILITY IDEOGRAPH-2F803;Lo;0;L;20122;;;;N;;;;; 2F804;CJK COMPATIBILITY IDEOGRAPH-2F804;Lo;0;L;4F60;;;;N;;;;; 2F805;CJK COMPATIBILITY IDEOGRAPH-2F805;Lo;0;L;4FAE;;;;N;;;;; 2F806;CJK COMPATIBILITY IDEOGRAPH-2F806;Lo;0;L;4FBB;;;;N;;;;; 2F807;CJK COMPATIBILITY IDEOGRAPH-2F807;Lo;0;L;5002;;;;N;;;;; 2F808;CJK COMPATIBILITY IDEOGRAPH-2F808;Lo;0;L;507A;;;;N;;;;; 2F809;CJK COMPATIBILITY IDEOGRAPH-2F809;Lo;0;L;5099;;;;N;;;;; 2F80A;CJK COMPATIBILITY IDEOGRAPH-2F80A;Lo;0;L;50E7;;;;N;;;;; 2F80B;CJK COMPATIBILITY IDEOGRAPH-2F80B;Lo;0;L;50CF;;;;N;;;;; 2F80C;CJK COMPATIBILITY IDEOGRAPH-2F80C;Lo;0;L;349E;;;;N;;;;; 2F80D;CJK COMPATIBILITY IDEOGRAPH-2F80D;Lo;0;L;2063A;;;;N;;;;; 2F80E;CJK COMPATIBILITY IDEOGRAPH-2F80E;Lo;0;L;514D;;;;N;;;;; 2F80F;CJK COMPATIBILITY IDEOGRAPH-2F80F;Lo;0;L;5154;;;;N;;;;; 2F810;CJK COMPATIBILITY IDEOGRAPH-2F810;Lo;0;L;5164;;;;N;;;;; 2F811;CJK COMPATIBILITY IDEOGRAPH-2F811;Lo;0;L;5177;;;;N;;;;; 2F812;CJK COMPATIBILITY IDEOGRAPH-2F812;Lo;0;L;2051C;;;;N;;;;; 2F813;CJK COMPATIBILITY IDEOGRAPH-2F813;Lo;0;L;34B9;;;;N;;;;; 2F814;CJK COMPATIBILITY IDEOGRAPH-2F814;Lo;0;L;5167;;;;N;;;;; 2F815;CJK COMPATIBILITY IDEOGRAPH-2F815;Lo;0;L;518D;;;;N;;;;; 2F816;CJK COMPATIBILITY IDEOGRAPH-2F816;Lo;0;L;2054B;;;;N;;;;; 2F817;CJK COMPATIBILITY IDEOGRAPH-2F817;Lo;0;L;5197;;;;N;;;;; 2F818;CJK COMPATIBILITY IDEOGRAPH-2F818;Lo;0;L;51A4;;;;N;;;;; 2F819;CJK COMPATIBILITY IDEOGRAPH-2F819;Lo;0;L;4ECC;;;;N;;;;; 2F81A;CJK COMPATIBILITY IDEOGRAPH-2F81A;Lo;0;L;51AC;;;;N;;;;; 2F81B;CJK COMPATIBILITY IDEOGRAPH-2F81B;Lo;0;L;51B5;;;;N;;;;; 2F81C;CJK COMPATIBILITY IDEOGRAPH-2F81C;Lo;0;L;291DF;;;;N;;;;; 2F81D;CJK COMPATIBILITY IDEOGRAPH-2F81D;Lo;0;L;51F5;;;;N;;;;; 2F81E;CJK COMPATIBILITY IDEOGRAPH-2F81E;Lo;0;L;5203;;;;N;;;;; 2F81F;CJK COMPATIBILITY IDEOGRAPH-2F81F;Lo;0;L;34DF;;;;N;;;;; 2F820;CJK COMPATIBILITY IDEOGRAPH-2F820;Lo;0;L;523B;;;;N;;;;; 2F821;CJK COMPATIBILITY IDEOGRAPH-2F821;Lo;0;L;5246;;;;N;;;;; 2F822;CJK COMPATIBILITY IDEOGRAPH-2F822;Lo;0;L;5272;;;;N;;;;; 2F823;CJK COMPATIBILITY IDEOGRAPH-2F823;Lo;0;L;5277;;;;N;;;;; 2F824;CJK COMPATIBILITY IDEOGRAPH-2F824;Lo;0;L;3515;;;;N;;;;; 2F825;CJK COMPATIBILITY IDEOGRAPH-2F825;Lo;0;L;52C7;;;;N;;;;; 2F826;CJK COMPATIBILITY IDEOGRAPH-2F826;Lo;0;L;52C9;;;;N;;;;; 2F827;CJK COMPATIBILITY IDEOGRAPH-2F827;Lo;0;L;52E4;;;;N;;;;; 2F828;CJK COMPATIBILITY IDEOGRAPH-2F828;Lo;0;L;52FA;;;;N;;;;; 2F829;CJK COMPATIBILITY IDEOGRAPH-2F829;Lo;0;L;5305;;;;N;;;;; 2F82A;CJK COMPATIBILITY IDEOGRAPH-2F82A;Lo;0;L;5306;;;;N;;;;; 2F82B;CJK COMPATIBILITY IDEOGRAPH-2F82B;Lo;0;L;5317;;;;N;;;;; 2F82C;CJK COMPATIBILITY IDEOGRAPH-2F82C;Lo;0;L;5349;;;;N;;;;; 2F82D;CJK COMPATIBILITY IDEOGRAPH-2F82D;Lo;0;L;5351;;;;N;;;;; 2F82E;CJK COMPATIBILITY IDEOGRAPH-2F82E;Lo;0;L;535A;;;;N;;;;; 2F82F;CJK COMPATIBILITY IDEOGRAPH-2F82F;Lo;0;L;5373;;;;N;;;;; 2F830;CJK COMPATIBILITY IDEOGRAPH-2F830;Lo;0;L;537D;;;;N;;;;; 2F831;CJK COMPATIBILITY IDEOGRAPH-2F831;Lo;0;L;537F;;;;N;;;;; 2F832;CJK COMPATIBILITY IDEOGRAPH-2F832;Lo;0;L;537F;;;;N;;;;; 2F833;CJK COMPATIBILITY IDEOGRAPH-2F833;Lo;0;L;537F;;;;N;;;;; 2F834;CJK COMPATIBILITY IDEOGRAPH-2F834;Lo;0;L;20A2C;;;;N;;;;; 2F835;CJK COMPATIBILITY IDEOGRAPH-2F835;Lo;0;L;7070;;;;N;;;;; 2F836;CJK COMPATIBILITY IDEOGRAPH-2F836;Lo;0;L;53CA;;;;N;;;;; 2F837;CJK COMPATIBILITY IDEOGRAPH-2F837;Lo;0;L;53DF;;;;N;;;;; 2F838;CJK COMPATIBILITY IDEOGRAPH-2F838;Lo;0;L;20B63;;;;N;;;;; 2F839;CJK COMPATIBILITY IDEOGRAPH-2F839;Lo;0;L;53EB;;;;N;;;;; 2F83A;CJK COMPATIBILITY IDEOGRAPH-2F83A;Lo;0;L;53F1;;;;N;;;;; 2F83B;CJK COMPATIBILITY IDEOGRAPH-2F83B;Lo;0;L;5406;;;;N;;;;; 2F83C;CJK COMPATIBILITY IDEOGRAPH-2F83C;Lo;0;L;549E;;;;N;;;;; 2F83D;CJK COMPATIBILITY IDEOGRAPH-2F83D;Lo;0;L;5438;;;;N;;;;; 2F83E;CJK COMPATIBILITY IDEOGRAPH-2F83E;Lo;0;L;5448;;;;N;;;;; 2F83F;CJK COMPATIBILITY IDEOGRAPH-2F83F;Lo;0;L;5468;;;;N;;;;; 2F840;CJK COMPATIBILITY IDEOGRAPH-2F840;Lo;0;L;54A2;;;;N;;;;; 2F841;CJK COMPATIBILITY IDEOGRAPH-2F841;Lo;0;L;54F6;;;;N;;;;; 2F842;CJK COMPATIBILITY IDEOGRAPH-2F842;Lo;0;L;5510;;;;N;;;;; 2F843;CJK COMPATIBILITY IDEOGRAPH-2F843;Lo;0;L;5553;;;;N;;;;; 2F844;CJK COMPATIBILITY IDEOGRAPH-2F844;Lo;0;L;5563;;;;N;;;;; 2F845;CJK COMPATIBILITY IDEOGRAPH-2F845;Lo;0;L;5584;;;;N;;;;; 2F846;CJK COMPATIBILITY IDEOGRAPH-2F846;Lo;0;L;5584;;;;N;;;;; 2F847;CJK COMPATIBILITY IDEOGRAPH-2F847;Lo;0;L;5599;;;;N;;;;; 2F848;CJK COMPATIBILITY IDEOGRAPH-2F848;Lo;0;L;55AB;;;;N;;;;; 2F849;CJK COMPATIBILITY IDEOGRAPH-2F849;Lo;0;L;55B3;;;;N;;;;; 2F84A;CJK COMPATIBILITY IDEOGRAPH-2F84A;Lo;0;L;55C2;;;;N;;;;; 2F84B;CJK COMPATIBILITY IDEOGRAPH-2F84B;Lo;0;L;5716;;;;N;;;;; 2F84C;CJK COMPATIBILITY IDEOGRAPH-2F84C;Lo;0;L;5606;;;;N;;;;; 2F84D;CJK COMPATIBILITY IDEOGRAPH-2F84D;Lo;0;L;5717;;;;N;;;;; 2F84E;CJK COMPATIBILITY IDEOGRAPH-2F84E;Lo;0;L;5651;;;;N;;;;; 2F84F;CJK COMPATIBILITY IDEOGRAPH-2F84F;Lo;0;L;5674;;;;N;;;;; 2F850;CJK COMPATIBILITY IDEOGRAPH-2F850;Lo;0;L;5207;;;;N;;;;; 2F851;CJK COMPATIBILITY IDEOGRAPH-2F851;Lo;0;L;58EE;;;;N;;;;; 2F852;CJK COMPATIBILITY IDEOGRAPH-2F852;Lo;0;L;57CE;;;;N;;;;; 2F853;CJK COMPATIBILITY IDEOGRAPH-2F853;Lo;0;L;57F4;;;;N;;;;; 2F854;CJK COMPATIBILITY IDEOGRAPH-2F854;Lo;0;L;580D;;;;N;;;;; 2F855;CJK COMPATIBILITY IDEOGRAPH-2F855;Lo;0;L;578B;;;;N;;;;; 2F856;CJK COMPATIBILITY IDEOGRAPH-2F856;Lo;0;L;5832;;;;N;;;;; 2F857;CJK COMPATIBILITY IDEOGRAPH-2F857;Lo;0;L;5831;;;;N;;;;; 2F858;CJK COMPATIBILITY IDEOGRAPH-2F858;Lo;0;L;58AC;;;;N;;;;; 2F859;CJK COMPATIBILITY IDEOGRAPH-2F859;Lo;0;L;214E4;;;;N;;;;; 2F85A;CJK COMPATIBILITY IDEOGRAPH-2F85A;Lo;0;L;58F2;;;;N;;;;; 2F85B;CJK COMPATIBILITY IDEOGRAPH-2F85B;Lo;0;L;58F7;;;;N;;;;; 2F85C;CJK COMPATIBILITY IDEOGRAPH-2F85C;Lo;0;L;5906;;;;N;;;;; 2F85D;CJK COMPATIBILITY IDEOGRAPH-2F85D;Lo;0;L;591A;;;;N;;;;; 2F85E;CJK COMPATIBILITY IDEOGRAPH-2F85E;Lo;0;L;5922;;;;N;;;;; 2F85F;CJK COMPATIBILITY IDEOGRAPH-2F85F;Lo;0;L;5962;;;;N;;;;; 2F860;CJK COMPATIBILITY IDEOGRAPH-2F860;Lo;0;L;216A8;;;;N;;;;; 2F861;CJK COMPATIBILITY IDEOGRAPH-2F861;Lo;0;L;216EA;;;;N;;;;; 2F862;CJK COMPATIBILITY IDEOGRAPH-2F862;Lo;0;L;59EC;;;;N;;;;; 2F863;CJK COMPATIBILITY IDEOGRAPH-2F863;Lo;0;L;5A1B;;;;N;;;;; 2F864;CJK COMPATIBILITY IDEOGRAPH-2F864;Lo;0;L;5A27;;;;N;;;;; 2F865;CJK COMPATIBILITY IDEOGRAPH-2F865;Lo;0;L;59D8;;;;N;;;;; 2F866;CJK COMPATIBILITY IDEOGRAPH-2F866;Lo;0;L;5A66;;;;N;;;;; 2F867;CJK COMPATIBILITY IDEOGRAPH-2F867;Lo;0;L;36EE;;;;N;;;;; 2F868;CJK COMPATIBILITY IDEOGRAPH-2F868;Lo;0;L;36FC;;;;N;;;;; 2F869;CJK COMPATIBILITY IDEOGRAPH-2F869;Lo;0;L;5B08;;;;N;;;;; 2F86A;CJK COMPATIBILITY IDEOGRAPH-2F86A;Lo;0;L;5B3E;;;;N;;;;; 2F86B;CJK COMPATIBILITY IDEOGRAPH-2F86B;Lo;0;L;5B3E;;;;N;;;;; 2F86C;CJK COMPATIBILITY IDEOGRAPH-2F86C;Lo;0;L;219C8;;;;N;;;;; 2F86D;CJK COMPATIBILITY IDEOGRAPH-2F86D;Lo;0;L;5BC3;;;;N;;;;; 2F86E;CJK COMPATIBILITY IDEOGRAPH-2F86E;Lo;0;L;5BD8;;;;N;;;;; 2F86F;CJK COMPATIBILITY IDEOGRAPH-2F86F;Lo;0;L;5BE7;;;;N;;;;; 2F870;CJK COMPATIBILITY IDEOGRAPH-2F870;Lo;0;L;5BF3;;;;N;;;;; 2F871;CJK COMPATIBILITY IDEOGRAPH-2F871;Lo;0;L;21B18;;;;N;;;;; 2F872;CJK COMPATIBILITY IDEOGRAPH-2F872;Lo;0;L;5BFF;;;;N;;;;; 2F873;CJK COMPATIBILITY IDEOGRAPH-2F873;Lo;0;L;5C06;;;;N;;;;; 2F874;CJK COMPATIBILITY IDEOGRAPH-2F874;Lo;0;L;5F53;;;;N;;;;; 2F875;CJK COMPATIBILITY IDEOGRAPH-2F875;Lo;0;L;5C22;;;;N;;;;; 2F876;CJK COMPATIBILITY IDEOGRAPH-2F876;Lo;0;L;3781;;;;N;;;;; 2F877;CJK COMPATIBILITY IDEOGRAPH-2F877;Lo;0;L;5C60;;;;N;;;;; 2F878;CJK COMPATIBILITY IDEOGRAPH-2F878;Lo;0;L;5C6E;;;;N;;;;; 2F879;CJK COMPATIBILITY IDEOGRAPH-2F879;Lo;0;L;5CC0;;;;N;;;;; 2F87A;CJK COMPATIBILITY IDEOGRAPH-2F87A;Lo;0;L;5C8D;;;;N;;;;; 2F87B;CJK COMPATIBILITY IDEOGRAPH-2F87B;Lo;0;L;21DE4;;;;N;;;;; 2F87C;CJK COMPATIBILITY IDEOGRAPH-2F87C;Lo;0;L;5D43;;;;N;;;;; 2F87D;CJK COMPATIBILITY IDEOGRAPH-2F87D;Lo;0;L;21DE6;;;;N;;;;; 2F87E;CJK COMPATIBILITY IDEOGRAPH-2F87E;Lo;0;L;5D6E;;;;N;;;;; 2F87F;CJK COMPATIBILITY IDEOGRAPH-2F87F;Lo;0;L;5D6B;;;;N;;;;; 2F880;CJK COMPATIBILITY IDEOGRAPH-2F880;Lo;0;L;5D7C;;;;N;;;;; 2F881;CJK COMPATIBILITY IDEOGRAPH-2F881;Lo;0;L;5DE1;;;;N;;;;; 2F882;CJK COMPATIBILITY IDEOGRAPH-2F882;Lo;0;L;5DE2;;;;N;;;;; 2F883;CJK COMPATIBILITY IDEOGRAPH-2F883;Lo;0;L;382F;;;;N;;;;; 2F884;CJK COMPATIBILITY IDEOGRAPH-2F884;Lo;0;L;5DFD;;;;N;;;;; 2F885;CJK COMPATIBILITY IDEOGRAPH-2F885;Lo;0;L;5E28;;;;N;;;;; 2F886;CJK COMPATIBILITY IDEOGRAPH-2F886;Lo;0;L;5E3D;;;;N;;;;; 2F887;CJK COMPATIBILITY IDEOGRAPH-2F887;Lo;0;L;5E69;;;;N;;;;; 2F888;CJK COMPATIBILITY IDEOGRAPH-2F888;Lo;0;L;3862;;;;N;;;;; 2F889;CJK COMPATIBILITY IDEOGRAPH-2F889;Lo;0;L;22183;;;;N;;;;; 2F88A;CJK COMPATIBILITY IDEOGRAPH-2F88A;Lo;0;L;387C;;;;N;;;;; 2F88B;CJK COMPATIBILITY IDEOGRAPH-2F88B;Lo;0;L;5EB0;;;;N;;;;; 2F88C;CJK COMPATIBILITY IDEOGRAPH-2F88C;Lo;0;L;5EB3;;;;N;;;;; 2F88D;CJK COMPATIBILITY IDEOGRAPH-2F88D;Lo;0;L;5EB6;;;;N;;;;; 2F88E;CJK COMPATIBILITY IDEOGRAPH-2F88E;Lo;0;L;5ECA;;;;N;;;;; 2F88F;CJK COMPATIBILITY IDEOGRAPH-2F88F;Lo;0;L;2A392;;;;N;;;;; 2F890;CJK COMPATIBILITY IDEOGRAPH-2F890;Lo;0;L;5EFE;;;9;N;;;;; 2F891;CJK COMPATIBILITY IDEOGRAPH-2F891;Lo;0;L;22331;;;;N;;;;; 2F892;CJK COMPATIBILITY IDEOGRAPH-2F892;Lo;0;L;22331;;;;N;;;;; 2F893;CJK COMPATIBILITY IDEOGRAPH-2F893;Lo;0;L;8201;;;;N;;;;; 2F894;CJK COMPATIBILITY IDEOGRAPH-2F894;Lo;0;L;5F22;;;;N;;;;; 2F895;CJK COMPATIBILITY IDEOGRAPH-2F895;Lo;0;L;5F22;;;;N;;;;; 2F896;CJK COMPATIBILITY IDEOGRAPH-2F896;Lo;0;L;38C7;;;;N;;;;; 2F897;CJK COMPATIBILITY IDEOGRAPH-2F897;Lo;0;L;232B8;;;;N;;;;; 2F898;CJK COMPATIBILITY IDEOGRAPH-2F898;Lo;0;L;261DA;;;;N;;;;; 2F899;CJK COMPATIBILITY IDEOGRAPH-2F899;Lo;0;L;5F62;;;;N;;;;; 2F89A;CJK COMPATIBILITY IDEOGRAPH-2F89A;Lo;0;L;5F6B;;;;N;;;;; 2F89B;CJK COMPATIBILITY IDEOGRAPH-2F89B;Lo;0;L;38E3;;;;N;;;;; 2F89C;CJK COMPATIBILITY IDEOGRAPH-2F89C;Lo;0;L;5F9A;;;;N;;;;; 2F89D;CJK COMPATIBILITY IDEOGRAPH-2F89D;Lo;0;L;5FCD;;;;N;;;;; 2F89E;CJK COMPATIBILITY IDEOGRAPH-2F89E;Lo;0;L;5FD7;;;;N;;;;; 2F89F;CJK COMPATIBILITY IDEOGRAPH-2F89F;Lo;0;L;5FF9;;;;N;;;;; 2F8A0;CJK COMPATIBILITY IDEOGRAPH-2F8A0;Lo;0;L;6081;;;;N;;;;; 2F8A1;CJK COMPATIBILITY IDEOGRAPH-2F8A1;Lo;0;L;393A;;;;N;;;;; 2F8A2;CJK COMPATIBILITY IDEOGRAPH-2F8A2;Lo;0;L;391C;;;;N;;;;; 2F8A3;CJK COMPATIBILITY IDEOGRAPH-2F8A3;Lo;0;L;6094;;;;N;;;;; 2F8A4;CJK COMPATIBILITY IDEOGRAPH-2F8A4;Lo;0;L;226D4;;;;N;;;;; 2F8A5;CJK COMPATIBILITY IDEOGRAPH-2F8A5;Lo;0;L;60C7;;;;N;;;;; 2F8A6;CJK COMPATIBILITY IDEOGRAPH-2F8A6;Lo;0;L;6148;;;;N;;;;; 2F8A7;CJK COMPATIBILITY IDEOGRAPH-2F8A7;Lo;0;L;614C;;;;N;;;;; 2F8A8;CJK COMPATIBILITY IDEOGRAPH-2F8A8;Lo;0;L;614E;;;;N;;;;; 2F8A9;CJK COMPATIBILITY IDEOGRAPH-2F8A9;Lo;0;L;614C;;;;N;;;;; 2F8AA;CJK COMPATIBILITY IDEOGRAPH-2F8AA;Lo;0;L;617A;;;;N;;;;; 2F8AB;CJK COMPATIBILITY IDEOGRAPH-2F8AB;Lo;0;L;618E;;;;N;;;;; 2F8AC;CJK COMPATIBILITY IDEOGRAPH-2F8AC;Lo;0;L;61B2;;;;N;;;;; 2F8AD;CJK COMPATIBILITY IDEOGRAPH-2F8AD;Lo;0;L;61A4;;;;N;;;;; 2F8AE;CJK COMPATIBILITY IDEOGRAPH-2F8AE;Lo;0;L;61AF;;;;N;;;;; 2F8AF;CJK COMPATIBILITY IDEOGRAPH-2F8AF;Lo;0;L;61DE;;;;N;;;;; 2F8B0;CJK COMPATIBILITY IDEOGRAPH-2F8B0;Lo;0;L;61F2;;;;N;;;;; 2F8B1;CJK COMPATIBILITY IDEOGRAPH-2F8B1;Lo;0;L;61F6;;;;N;;;;; 2F8B2;CJK COMPATIBILITY IDEOGRAPH-2F8B2;Lo;0;L;6210;;;;N;;;;; 2F8B3;CJK COMPATIBILITY IDEOGRAPH-2F8B3;Lo;0;L;621B;;;;N;;;;; 2F8B4;CJK COMPATIBILITY IDEOGRAPH-2F8B4;Lo;0;L;625D;;;;N;;;;; 2F8B5;CJK COMPATIBILITY IDEOGRAPH-2F8B5;Lo;0;L;62B1;;;;N;;;;; 2F8B6;CJK COMPATIBILITY IDEOGRAPH-2F8B6;Lo;0;L;62D4;;;;N;;;;; 2F8B7;CJK COMPATIBILITY IDEOGRAPH-2F8B7;Lo;0;L;6350;;;;N;;;;; 2F8B8;CJK COMPATIBILITY IDEOGRAPH-2F8B8;Lo;0;L;22B0C;;;;N;;;;; 2F8B9;CJK COMPATIBILITY IDEOGRAPH-2F8B9;Lo;0;L;633D;;;;N;;;;; 2F8BA;CJK COMPATIBILITY IDEOGRAPH-2F8BA;Lo;0;L;62FC;;;;N;;;;; 2F8BB;CJK COMPATIBILITY IDEOGRAPH-2F8BB;Lo;0;L;6368;;;;N;;;;; 2F8BC;CJK COMPATIBILITY IDEOGRAPH-2F8BC;Lo;0;L;6383;;;;N;;;;; 2F8BD;CJK COMPATIBILITY IDEOGRAPH-2F8BD;Lo;0;L;63E4;;;;N;;;;; 2F8BE;CJK COMPATIBILITY IDEOGRAPH-2F8BE;Lo;0;L;22BF1;;;;N;;;;; 2F8BF;CJK COMPATIBILITY IDEOGRAPH-2F8BF;Lo;0;L;6422;;;;N;;;;; 2F8C0;CJK COMPATIBILITY IDEOGRAPH-2F8C0;Lo;0;L;63C5;;;;N;;;;; 2F8C1;CJK COMPATIBILITY IDEOGRAPH-2F8C1;Lo;0;L;63A9;;;;N;;;;; 2F8C2;CJK COMPATIBILITY IDEOGRAPH-2F8C2;Lo;0;L;3A2E;;;;N;;;;; 2F8C3;CJK COMPATIBILITY IDEOGRAPH-2F8C3;Lo;0;L;6469;;;;N;;;;; 2F8C4;CJK COMPATIBILITY IDEOGRAPH-2F8C4;Lo;0;L;647E;;;;N;;;;; 2F8C5;CJK COMPATIBILITY IDEOGRAPH-2F8C5;Lo;0;L;649D;;;;N;;;;; 2F8C6;CJK COMPATIBILITY IDEOGRAPH-2F8C6;Lo;0;L;6477;;;;N;;;;; 2F8C7;CJK COMPATIBILITY IDEOGRAPH-2F8C7;Lo;0;L;3A6C;;;;N;;;;; 2F8C8;CJK COMPATIBILITY IDEOGRAPH-2F8C8;Lo;0;L;654F;;;;N;;;;; 2F8C9;CJK COMPATIBILITY IDEOGRAPH-2F8C9;Lo;0;L;656C;;;;N;;;;; 2F8CA;CJK COMPATIBILITY IDEOGRAPH-2F8CA;Lo;0;L;2300A;;;;N;;;;; 2F8CB;CJK COMPATIBILITY IDEOGRAPH-2F8CB;Lo;0;L;65E3;;;;N;;;;; 2F8CC;CJK COMPATIBILITY IDEOGRAPH-2F8CC;Lo;0;L;66F8;;;;N;;;;; 2F8CD;CJK COMPATIBILITY IDEOGRAPH-2F8CD;Lo;0;L;6649;;;;N;;;;; 2F8CE;CJK COMPATIBILITY IDEOGRAPH-2F8CE;Lo;0;L;3B19;;;;N;;;;; 2F8CF;CJK COMPATIBILITY IDEOGRAPH-2F8CF;Lo;0;L;6691;;;;N;;;;; 2F8D0;CJK COMPATIBILITY IDEOGRAPH-2F8D0;Lo;0;L;3B08;;;;N;;;;; 2F8D1;CJK COMPATIBILITY IDEOGRAPH-2F8D1;Lo;0;L;3AE4;;;;N;;;;; 2F8D2;CJK COMPATIBILITY IDEOGRAPH-2F8D2;Lo;0;L;5192;;;;N;;;;; 2F8D3;CJK COMPATIBILITY IDEOGRAPH-2F8D3;Lo;0;L;5195;;;;N;;;;; 2F8D4;CJK COMPATIBILITY IDEOGRAPH-2F8D4;Lo;0;L;6700;;;;N;;;;; 2F8D5;CJK COMPATIBILITY IDEOGRAPH-2F8D5;Lo;0;L;669C;;;;N;;;;; 2F8D6;CJK COMPATIBILITY IDEOGRAPH-2F8D6;Lo;0;L;80AD;;;;N;;;;; 2F8D7;CJK COMPATIBILITY IDEOGRAPH-2F8D7;Lo;0;L;43D9;;;;N;;;;; 2F8D8;CJK COMPATIBILITY IDEOGRAPH-2F8D8;Lo;0;L;6717;;;;N;;;;; 2F8D9;CJK COMPATIBILITY IDEOGRAPH-2F8D9;Lo;0;L;671B;;;;N;;;;; 2F8DA;CJK COMPATIBILITY IDEOGRAPH-2F8DA;Lo;0;L;6721;;;;N;;;;; 2F8DB;CJK COMPATIBILITY IDEOGRAPH-2F8DB;Lo;0;L;675E;;;;N;;;;; 2F8DC;CJK COMPATIBILITY IDEOGRAPH-2F8DC;Lo;0;L;6753;;;;N;;;;; 2F8DD;CJK COMPATIBILITY IDEOGRAPH-2F8DD;Lo;0;L;233C3;;;;N;;;;; 2F8DE;CJK COMPATIBILITY IDEOGRAPH-2F8DE;Lo;0;L;3B49;;;;N;;;;; 2F8DF;CJK COMPATIBILITY IDEOGRAPH-2F8DF;Lo;0;L;67FA;;;;N;;;;; 2F8E0;CJK COMPATIBILITY IDEOGRAPH-2F8E0;Lo;0;L;6785;;;;N;;;;; 2F8E1;CJK COMPATIBILITY IDEOGRAPH-2F8E1;Lo;0;L;6852;;;;N;;;;; 2F8E2;CJK COMPATIBILITY IDEOGRAPH-2F8E2;Lo;0;L;6885;;;;N;;;;; 2F8E3;CJK COMPATIBILITY IDEOGRAPH-2F8E3;Lo;0;L;2346D;;;;N;;;;; 2F8E4;CJK COMPATIBILITY IDEOGRAPH-2F8E4;Lo;0;L;688E;;;;N;;;;; 2F8E5;CJK COMPATIBILITY IDEOGRAPH-2F8E5;Lo;0;L;681F;;;;N;;;;; 2F8E6;CJK COMPATIBILITY IDEOGRAPH-2F8E6;Lo;0;L;6914;;;;N;;;;; 2F8E7;CJK COMPATIBILITY IDEOGRAPH-2F8E7;Lo;0;L;3B9D;;;;N;;;;; 2F8E8;CJK COMPATIBILITY IDEOGRAPH-2F8E8;Lo;0;L;6942;;;;N;;;;; 2F8E9;CJK COMPATIBILITY IDEOGRAPH-2F8E9;Lo;0;L;69A3;;;;N;;;;; 2F8EA;CJK COMPATIBILITY IDEOGRAPH-2F8EA;Lo;0;L;69EA;;;;N;;;;; 2F8EB;CJK COMPATIBILITY IDEOGRAPH-2F8EB;Lo;0;L;6AA8;;;;N;;;;; 2F8EC;CJK COMPATIBILITY IDEOGRAPH-2F8EC;Lo;0;L;236A3;;;;N;;;;; 2F8ED;CJK COMPATIBILITY IDEOGRAPH-2F8ED;Lo;0;L;6ADB;;;;N;;;;; 2F8EE;CJK COMPATIBILITY IDEOGRAPH-2F8EE;Lo;0;L;3C18;;;;N;;;;; 2F8EF;CJK COMPATIBILITY IDEOGRAPH-2F8EF;Lo;0;L;6B21;;;;N;;;;; 2F8F0;CJK COMPATIBILITY IDEOGRAPH-2F8F0;Lo;0;L;238A7;;;;N;;;;; 2F8F1;CJK COMPATIBILITY IDEOGRAPH-2F8F1;Lo;0;L;6B54;;;;N;;;;; 2F8F2;CJK COMPATIBILITY IDEOGRAPH-2F8F2;Lo;0;L;3C4E;;;;N;;;;; 2F8F3;CJK COMPATIBILITY IDEOGRAPH-2F8F3;Lo;0;L;6B72;;;;N;;;;; 2F8F4;CJK COMPATIBILITY IDEOGRAPH-2F8F4;Lo;0;L;6B9F;;;;N;;;;; 2F8F5;CJK COMPATIBILITY IDEOGRAPH-2F8F5;Lo;0;L;6BBA;;;;N;;;;; 2F8F6;CJK COMPATIBILITY IDEOGRAPH-2F8F6;Lo;0;L;6BBB;;;;N;;;;; 2F8F7;CJK COMPATIBILITY IDEOGRAPH-2F8F7;Lo;0;L;23A8D;;;;N;;;;; 2F8F8;CJK COMPATIBILITY IDEOGRAPH-2F8F8;Lo;0;L;21D0B;;;;N;;;;; 2F8F9;CJK COMPATIBILITY IDEOGRAPH-2F8F9;Lo;0;L;23AFA;;;;N;;;;; 2F8FA;CJK COMPATIBILITY IDEOGRAPH-2F8FA;Lo;0;L;6C4E;;;;N;;;;; 2F8FB;CJK COMPATIBILITY IDEOGRAPH-2F8FB;Lo;0;L;23CBC;;;;N;;;;; 2F8FC;CJK COMPATIBILITY IDEOGRAPH-2F8FC;Lo;0;L;6CBF;;;;N;;;;; 2F8FD;CJK COMPATIBILITY IDEOGRAPH-2F8FD;Lo;0;L;6CCD;;;;N;;;;; 2F8FE;CJK COMPATIBILITY IDEOGRAPH-2F8FE;Lo;0;L;6C67;;;;N;;;;; 2F8FF;CJK COMPATIBILITY IDEOGRAPH-2F8FF;Lo;0;L;6D16;;;;N;;;;; 2F900;CJK COMPATIBILITY IDEOGRAPH-2F900;Lo;0;L;6D3E;;;;N;;;;; 2F901;CJK COMPATIBILITY IDEOGRAPH-2F901;Lo;0;L;6D77;;;;N;;;;; 2F902;CJK COMPATIBILITY IDEOGRAPH-2F902;Lo;0;L;6D41;;;;N;;;;; 2F903;CJK COMPATIBILITY IDEOGRAPH-2F903;Lo;0;L;6D69;;;;N;;;;; 2F904;CJK COMPATIBILITY IDEOGRAPH-2F904;Lo;0;L;6D78;;;;N;;;;; 2F905;CJK COMPATIBILITY IDEOGRAPH-2F905;Lo;0;L;6D85;;;;N;;;;; 2F906;CJK COMPATIBILITY IDEOGRAPH-2F906;Lo;0;L;23D1E;;;;N;;;;; 2F907;CJK COMPATIBILITY IDEOGRAPH-2F907;Lo;0;L;6D34;;;;N;;;;; 2F908;CJK COMPATIBILITY IDEOGRAPH-2F908;Lo;0;L;6E2F;;;;N;;;;; 2F909;CJK COMPATIBILITY IDEOGRAPH-2F909;Lo;0;L;6E6E;;;;N;;;;; 2F90A;CJK COMPATIBILITY IDEOGRAPH-2F90A;Lo;0;L;3D33;;;;N;;;;; 2F90B;CJK COMPATIBILITY IDEOGRAPH-2F90B;Lo;0;L;6ECB;;;;N;;;;; 2F90C;CJK COMPATIBILITY IDEOGRAPH-2F90C;Lo;0;L;6EC7;;;;N;;;;; 2F90D;CJK COMPATIBILITY IDEOGRAPH-2F90D;Lo;0;L;23ED1;;;;N;;;;; 2F90E;CJK COMPATIBILITY IDEOGRAPH-2F90E;Lo;0;L;6DF9;;;;N;;;;; 2F90F;CJK COMPATIBILITY IDEOGRAPH-2F90F;Lo;0;L;6F6E;;;;N;;;;; 2F910;CJK COMPATIBILITY IDEOGRAPH-2F910;Lo;0;L;23F5E;;;;N;;;;; 2F911;CJK COMPATIBILITY IDEOGRAPH-2F911;Lo;0;L;23F8E;;;;N;;;;; 2F912;CJK COMPATIBILITY IDEOGRAPH-2F912;Lo;0;L;6FC6;;;;N;;;;; 2F913;CJK COMPATIBILITY IDEOGRAPH-2F913;Lo;0;L;7039;;;;N;;;;; 2F914;CJK COMPATIBILITY IDEOGRAPH-2F914;Lo;0;L;701E;;;;N;;;;; 2F915;CJK COMPATIBILITY IDEOGRAPH-2F915;Lo;0;L;701B;;;;N;;;;; 2F916;CJK COMPATIBILITY IDEOGRAPH-2F916;Lo;0;L;3D96;;;;N;;;;; 2F917;CJK COMPATIBILITY IDEOGRAPH-2F917;Lo;0;L;704A;;;;N;;;;; 2F918;CJK COMPATIBILITY IDEOGRAPH-2F918;Lo;0;L;707D;;;;N;;;;; 2F919;CJK COMPATIBILITY IDEOGRAPH-2F919;Lo;0;L;7077;;;;N;;;;; 2F91A;CJK COMPATIBILITY IDEOGRAPH-2F91A;Lo;0;L;70AD;;;;N;;;;; 2F91B;CJK COMPATIBILITY IDEOGRAPH-2F91B;Lo;0;L;20525;;;;N;;;;; 2F91C;CJK COMPATIBILITY IDEOGRAPH-2F91C;Lo;0;L;7145;;;;N;;;;; 2F91D;CJK COMPATIBILITY IDEOGRAPH-2F91D;Lo;0;L;24263;;;;N;;;;; 2F91E;CJK COMPATIBILITY IDEOGRAPH-2F91E;Lo;0;L;719C;;;;N;;;;; 2F91F;CJK COMPATIBILITY IDEOGRAPH-2F91F;Lo;0;L;243AB;;;;N;;;;; 2F920;CJK COMPATIBILITY IDEOGRAPH-2F920;Lo;0;L;7228;;;;N;;;;; 2F921;CJK COMPATIBILITY IDEOGRAPH-2F921;Lo;0;L;7235;;;;N;;;;; 2F922;CJK COMPATIBILITY IDEOGRAPH-2F922;Lo;0;L;7250;;;;N;;;;; +2F923;CJK COMPATIBILITY IDEOGRAPH-2F923;Lo;0;L;24608;;;;N;;;;; +2F924;CJK COMPATIBILITY IDEOGRAPH-2F924;Lo;0;L;7280;;;;N;;;;; +2F925;CJK COMPATIBILITY IDEOGRAPH-2F925;Lo;0;L;7295;;;;N;;;;; +2F926;CJK COMPATIBILITY IDEOGRAPH-2F926;Lo;0;L;24735;;;;N;;;;; +2F927;CJK COMPATIBILITY IDEOGRAPH-2F927;Lo;0;L;24814;;;;N;;;;; +2F928;CJK COMPATIBILITY IDEOGRAPH-2F928;Lo;0;L;737A;;;;N;;;;; +2F929;CJK COMPATIBILITY IDEOGRAPH-2F929;Lo;0;L;738B;;;;N;;;;; +2F92A;CJK COMPATIBILITY IDEOGRAPH-2F92A;Lo;0;L;3EAC;;;;N;;;;; +2F92B;CJK COMPATIBILITY IDEOGRAPH-2F92B;Lo;0;L;73A5;;;;N;;;;; +2F92C;CJK COMPATIBILITY IDEOGRAPH-2F92C;Lo;0;L;3EB8;;;;N;;;;; +2F92D;CJK COMPATIBILITY IDEOGRAPH-2F92D;Lo;0;L;3EB8;;;;N;;;;; +2F92E;CJK COMPATIBILITY IDEOGRAPH-2F92E;Lo;0;L;7447;;;;N;;;;; +2F92F;CJK COMPATIBILITY IDEOGRAPH-2F92F;Lo;0;L;745C;;;;N;;;;; +2F930;CJK COMPATIBILITY IDEOGRAPH-2F930;Lo;0;L;7471;;;;N;;;;; +2F931;CJK COMPATIBILITY IDEOGRAPH-2F931;Lo;0;L;7485;;;;N;;;;; +2F932;CJK COMPATIBILITY IDEOGRAPH-2F932;Lo;0;L;74CA;;;;N;;;;; +2F933;CJK COMPATIBILITY IDEOGRAPH-2F933;Lo;0;L;3F1B;;;;N;;;;; +2F934;CJK COMPATIBILITY IDEOGRAPH-2F934;Lo;0;L;7524;;;;N;;;;; +2F935;CJK COMPATIBILITY IDEOGRAPH-2F935;Lo;0;L;24C36;;;;N;;;;; +2F936;CJK COMPATIBILITY IDEOGRAPH-2F936;Lo;0;L;753E;;;;N;;;;; +2F937;CJK COMPATIBILITY IDEOGRAPH-2F937;Lo;0;L;24C92;;;;N;;;;; +2F938;CJK COMPATIBILITY IDEOGRAPH-2F938;Lo;0;L;7570;;;;N;;;;; +2F939;CJK COMPATIBILITY IDEOGRAPH-2F939;Lo;0;L;2219F;;;;N;;;;; +2F93A;CJK COMPATIBILITY IDEOGRAPH-2F93A;Lo;0;L;7610;;;;N;;;;; +2F93B;CJK COMPATIBILITY IDEOGRAPH-2F93B;Lo;0;L;24FA1;;;;N;;;;; +2F93C;CJK COMPATIBILITY IDEOGRAPH-2F93C;Lo;0;L;24FB8;;;;N;;;;; +2F93D;CJK COMPATIBILITY IDEOGRAPH-2F93D;Lo;0;L;25044;;;;N;;;;; +2F93E;CJK COMPATIBILITY IDEOGRAPH-2F93E;Lo;0;L;3FFC;;;;N;;;;; +2F93F;CJK COMPATIBILITY IDEOGRAPH-2F93F;Lo;0;L;4008;;;;N;;;;; +2F940;CJK COMPATIBILITY IDEOGRAPH-2F940;Lo;0;L;76F4;;;;N;;;;; +2F941;CJK COMPATIBILITY IDEOGRAPH-2F941;Lo;0;L;250F3;;;;N;;;;; +2F942;CJK COMPATIBILITY IDEOGRAPH-2F942;Lo;0;L;250F2;;;;N;;;;; +2F943;CJK COMPATIBILITY IDEOGRAPH-2F943;Lo;0;L;25119;;;;N;;;;; +2F944;CJK COMPATIBILITY IDEOGRAPH-2F944;Lo;0;L;25133;;;;N;;;;; +2F945;CJK COMPATIBILITY IDEOGRAPH-2F945;Lo;0;L;771E;;;;N;;;;; +2F946;CJK COMPATIBILITY IDEOGRAPH-2F946;Lo;0;L;771F;;;;N;;;;; +2F947;CJK COMPATIBILITY IDEOGRAPH-2F947;Lo;0;L;771F;;;;N;;;;; +2F948;CJK COMPATIBILITY IDEOGRAPH-2F948;Lo;0;L;774A;;;;N;;;;; +2F949;CJK COMPATIBILITY IDEOGRAPH-2F949;Lo;0;L;4039;;;;N;;;;; +2F94A;CJK COMPATIBILITY IDEOGRAPH-2F94A;Lo;0;L;778B;;;;N;;;;; +2F94B;CJK COMPATIBILITY IDEOGRAPH-2F94B;Lo;0;L;4046;;;;N;;;;; +2F94C;CJK COMPATIBILITY IDEOGRAPH-2F94C;Lo;0;L;4096;;;;N;;;;; +2F94D;CJK COMPATIBILITY IDEOGRAPH-2F94D;Lo;0;L;2541D;;;;N;;;;; +2F94E;CJK COMPATIBILITY IDEOGRAPH-2F94E;Lo;0;L;784E;;;;N;;;;; +2F94F;CJK COMPATIBILITY IDEOGRAPH-2F94F;Lo;0;L;788C;;;;N;;;;; +2F950;CJK COMPATIBILITY IDEOGRAPH-2F950;Lo;0;L;78CC;;;;N;;;;; +2F951;CJK COMPATIBILITY IDEOGRAPH-2F951;Lo;0;L;40E3;;;;N;;;;; +2F952;CJK COMPATIBILITY IDEOGRAPH-2F952;Lo;0;L;25626;;;;N;;;;; +2F953;CJK COMPATIBILITY IDEOGRAPH-2F953;Lo;0;L;7956;;;;N;;;;; +2F954;CJK COMPATIBILITY IDEOGRAPH-2F954;Lo;0;L;2569A;;;;N;;;;; +2F955;CJK COMPATIBILITY IDEOGRAPH-2F955;Lo;0;L;256C5;;;;N;;;;; +2F956;CJK COMPATIBILITY IDEOGRAPH-2F956;Lo;0;L;798F;;;;N;;;;; +2F957;CJK COMPATIBILITY IDEOGRAPH-2F957;Lo;0;L;79EB;;;;N;;;;; +2F958;CJK COMPATIBILITY IDEOGRAPH-2F958;Lo;0;L;412F;;;;N;;;;; +2F959;CJK COMPATIBILITY IDEOGRAPH-2F959;Lo;0;L;7A40;;;;N;;;;; +2F95A;CJK COMPATIBILITY IDEOGRAPH-2F95A;Lo;0;L;7A4A;;;;N;;;;; +2F95B;CJK COMPATIBILITY IDEOGRAPH-2F95B;Lo;0;L;7A4F;;;;N;;;;; +2F95C;CJK COMPATIBILITY IDEOGRAPH-2F95C;Lo;0;L;2597C;;;;N;;;;; +2F95D;CJK COMPATIBILITY IDEOGRAPH-2F95D;Lo;0;L;25AA7;;;;N;;;;; +2F95E;CJK COMPATIBILITY IDEOGRAPH-2F95E;Lo;0;L;25AA7;;;;N;;;;; +2F95F;CJK COMPATIBILITY IDEOGRAPH-2F95F;Lo;0;L;7AEE;;;;N;;;;; +2F960;CJK COMPATIBILITY IDEOGRAPH-2F960;Lo;0;L;4202;;;;N;;;;; +2F961;CJK COMPATIBILITY IDEOGRAPH-2F961;Lo;0;L;25BAB;;;;N;;;;; +2F962;CJK COMPATIBILITY IDEOGRAPH-2F962;Lo;0;L;7BC6;;;;N;;;;; +2F963;CJK COMPATIBILITY IDEOGRAPH-2F963;Lo;0;L;7BC9;;;;N;;;;; +2F964;CJK COMPATIBILITY IDEOGRAPH-2F964;Lo;0;L;4227;;;;N;;;;; +2F965;CJK COMPATIBILITY IDEOGRAPH-2F965;Lo;0;L;25C80;;;;N;;;;; +2F966;CJK COMPATIBILITY IDEOGRAPH-2F966;Lo;0;L;7CD2;;;;N;;;;; +2F967;CJK COMPATIBILITY IDEOGRAPH-2F967;Lo;0;L;42A0;;;;N;;;;; +2F968;CJK COMPATIBILITY IDEOGRAPH-2F968;Lo;0;L;7CE8;;;;N;;;;; +2F969;CJK COMPATIBILITY IDEOGRAPH-2F969;Lo;0;L;7CE3;;;;N;;;;; +2F96A;CJK COMPATIBILITY IDEOGRAPH-2F96A;Lo;0;L;7D00;;;;N;;;;; +2F96B;CJK COMPATIBILITY IDEOGRAPH-2F96B;Lo;0;L;25F86;;;;N;;;;; +2F96C;CJK COMPATIBILITY IDEOGRAPH-2F96C;Lo;0;L;7D63;;;;N;;;;; +2F96D;CJK COMPATIBILITY IDEOGRAPH-2F96D;Lo;0;L;4301;;;;N;;;;; +2F96E;CJK COMPATIBILITY IDEOGRAPH-2F96E;Lo;0;L;7DC7;;;;N;;;;; +2F96F;CJK COMPATIBILITY IDEOGRAPH-2F96F;Lo;0;L;7E02;;;;N;;;;; +2F970;CJK COMPATIBILITY IDEOGRAPH-2F970;Lo;0;L;7E45;;;;N;;;;; +2F971;CJK COMPATIBILITY IDEOGRAPH-2F971;Lo;0;L;4334;;;;N;;;;; +2F972;CJK COMPATIBILITY IDEOGRAPH-2F972;Lo;0;L;26228;;;;N;;;;; +2F973;CJK COMPATIBILITY IDEOGRAPH-2F973;Lo;0;L;26247;;;;N;;;;; +2F974;CJK COMPATIBILITY IDEOGRAPH-2F974;Lo;0;L;4359;;;;N;;;;; +2F975;CJK COMPATIBILITY IDEOGRAPH-2F975;Lo;0;L;262D9;;;;N;;;;; +2F976;CJK COMPATIBILITY IDEOGRAPH-2F976;Lo;0;L;7F7A;;;;N;;;;; +2F977;CJK COMPATIBILITY IDEOGRAPH-2F977;Lo;0;L;2633E;;;;N;;;;; +2F978;CJK COMPATIBILITY IDEOGRAPH-2F978;Lo;0;L;7F95;;;;N;;;;; +2F979;CJK COMPATIBILITY IDEOGRAPH-2F979;Lo;0;L;7FFA;;;;N;;;;; +2F97A;CJK COMPATIBILITY IDEOGRAPH-2F97A;Lo;0;L;8005;;;;N;;;;; +2F97B;CJK COMPATIBILITY IDEOGRAPH-2F97B;Lo;0;L;264DA;;;;N;;;;; +2F97C;CJK COMPATIBILITY IDEOGRAPH-2F97C;Lo;0;L;26523;;;;N;;;;; +2F97D;CJK COMPATIBILITY IDEOGRAPH-2F97D;Lo;0;L;8060;;;;N;;;;; +2F97E;CJK COMPATIBILITY IDEOGRAPH-2F97E;Lo;0;L;265A8;;;;N;;;;; +2F97F;CJK COMPATIBILITY IDEOGRAPH-2F97F;Lo;0;L;8070;;;;N;;;;; +2F980;CJK COMPATIBILITY IDEOGRAPH-2F980;Lo;0;L;2335F;;;;N;;;;; +2F981;CJK COMPATIBILITY IDEOGRAPH-2F981;Lo;0;L;43D5;;;;N;;;;; +2F982;CJK COMPATIBILITY IDEOGRAPH-2F982;Lo;0;L;80B2;;;;N;;;;; +2F983;CJK COMPATIBILITY IDEOGRAPH-2F983;Lo;0;L;8103;;;;N;;;;; +2F984;CJK COMPATIBILITY IDEOGRAPH-2F984;Lo;0;L;440B;;;;N;;;;; +2F985;CJK COMPATIBILITY IDEOGRAPH-2F985;Lo;0;L;813E;;;;N;;;;; +2F986;CJK COMPATIBILITY IDEOGRAPH-2F986;Lo;0;L;5AB5;;;;N;;;;; +2F987;CJK COMPATIBILITY IDEOGRAPH-2F987;Lo;0;L;267A7;;;;N;;;;; +2F988;CJK COMPATIBILITY IDEOGRAPH-2F988;Lo;0;L;267B5;;;;N;;;;; +2F989;CJK COMPATIBILITY IDEOGRAPH-2F989;Lo;0;L;23393;;;;N;;;;; +2F98A;CJK COMPATIBILITY IDEOGRAPH-2F98A;Lo;0;L;2339C;;;;N;;;;; +2F98B;CJK COMPATIBILITY IDEOGRAPH-2F98B;Lo;0;L;8201;;;;N;;;;; +2F98C;CJK COMPATIBILITY IDEOGRAPH-2F98C;Lo;0;L;8204;;;;N;;;;; +2F98D;CJK COMPATIBILITY IDEOGRAPH-2F98D;Lo;0;L;8F9E;;;;N;;;;; +2F98E;CJK COMPATIBILITY IDEOGRAPH-2F98E;Lo;0;L;446B;;;;N;;;;; +2F98F;CJK COMPATIBILITY IDEOGRAPH-2F98F;Lo;0;L;8291;;;;N;;;;; +2F990;CJK COMPATIBILITY IDEOGRAPH-2F990;Lo;0;L;828B;;;;N;;;;; +2F991;CJK COMPATIBILITY IDEOGRAPH-2F991;Lo;0;L;829D;;;;N;;;;; +2F992;CJK COMPATIBILITY IDEOGRAPH-2F992;Lo;0;L;52B3;;;;N;;;;; +2F993;CJK COMPATIBILITY IDEOGRAPH-2F993;Lo;0;L;82B1;;;;N;;;;; +2F994;CJK COMPATIBILITY IDEOGRAPH-2F994;Lo;0;L;82B3;;;;N;;;;; +2F995;CJK COMPATIBILITY IDEOGRAPH-2F995;Lo;0;L;82BD;;;;N;;;;; +2F996;CJK COMPATIBILITY IDEOGRAPH-2F996;Lo;0;L;82E6;;;;N;;;;; +2F997;CJK COMPATIBILITY IDEOGRAPH-2F997;Lo;0;L;26B3C;;;;N;;;;; +2F998;CJK COMPATIBILITY IDEOGRAPH-2F998;Lo;0;L;82E5;;;;N;;;;; +2F999;CJK COMPATIBILITY IDEOGRAPH-2F999;Lo;0;L;831D;;;;N;;;;; +2F99A;CJK COMPATIBILITY IDEOGRAPH-2F99A;Lo;0;L;8363;;;;N;;;;; +2F99B;CJK COMPATIBILITY IDEOGRAPH-2F99B;Lo;0;L;83AD;;;;N;;;;; +2F99C;CJK COMPATIBILITY IDEOGRAPH-2F99C;Lo;0;L;8323;;;;N;;;;; +2F99D;CJK COMPATIBILITY IDEOGRAPH-2F99D;Lo;0;L;83BD;;;;N;;;;; +2F99E;CJK COMPATIBILITY IDEOGRAPH-2F99E;Lo;0;L;83E7;;;;N;;;;; +2F99F;CJK COMPATIBILITY IDEOGRAPH-2F99F;Lo;0;L;8457;;;;N;;;;; +2F9A0;CJK COMPATIBILITY IDEOGRAPH-2F9A0;Lo;0;L;8353;;;;N;;;;; +2F9A1;CJK COMPATIBILITY IDEOGRAPH-2F9A1;Lo;0;L;83CA;;;;N;;;;; +2F9A2;CJK COMPATIBILITY IDEOGRAPH-2F9A2;Lo;0;L;83CC;;;;N;;;;; +2F9A3;CJK COMPATIBILITY IDEOGRAPH-2F9A3;Lo;0;L;83DC;;;;N;;;;; +2F9A4;CJK COMPATIBILITY IDEOGRAPH-2F9A4;Lo;0;L;26C36;;;;N;;;;; +2F9A5;CJK COMPATIBILITY IDEOGRAPH-2F9A5;Lo;0;L;26D6B;;;;N;;;;; +2F9A6;CJK COMPATIBILITY IDEOGRAPH-2F9A6;Lo;0;L;26CD5;;;;N;;;;; +2F9A7;CJK COMPATIBILITY IDEOGRAPH-2F9A7;Lo;0;L;452B;;;;N;;;;; +2F9A8;CJK COMPATIBILITY IDEOGRAPH-2F9A8;Lo;0;L;84F1;;;;N;;;;; +2F9A9;CJK COMPATIBILITY IDEOGRAPH-2F9A9;Lo;0;L;84F3;;;;N;;;;; +2F9AA;CJK COMPATIBILITY IDEOGRAPH-2F9AA;Lo;0;L;8516;;;;N;;;;; +2F9AB;CJK COMPATIBILITY IDEOGRAPH-2F9AB;Lo;0;L;273CA;;;;N;;;;; +2F9AC;CJK COMPATIBILITY IDEOGRAPH-2F9AC;Lo;0;L;8564;;;;N;;;;; +2F9AD;CJK COMPATIBILITY IDEOGRAPH-2F9AD;Lo;0;L;26F2C;;;;N;;;;; +2F9AE;CJK COMPATIBILITY IDEOGRAPH-2F9AE;Lo;0;L;455D;;;;N;;;;; +2F9AF;CJK COMPATIBILITY IDEOGRAPH-2F9AF;Lo;0;L;4561;;;;N;;;;; +2F9B0;CJK COMPATIBILITY IDEOGRAPH-2F9B0;Lo;0;L;26FB1;;;;N;;;;; +2F9B1;CJK COMPATIBILITY IDEOGRAPH-2F9B1;Lo;0;L;270D2;;;;N;;;;; +2F9B2;CJK COMPATIBILITY IDEOGRAPH-2F9B2;Lo;0;L;456B;;;;N;;;;; +2F9B3;CJK COMPATIBILITY IDEOGRAPH-2F9B3;Lo;0;L;8650;;;;N;;;;; +2F9B4;CJK COMPATIBILITY IDEOGRAPH-2F9B4;Lo;0;L;865C;;;;N;;;;; +2F9B5;CJK COMPATIBILITY IDEOGRAPH-2F9B5;Lo;0;L;8667;;;;N;;;;; +2F9B6;CJK COMPATIBILITY IDEOGRAPH-2F9B6;Lo;0;L;8669;;;;N;;;;; +2F9B7;CJK COMPATIBILITY IDEOGRAPH-2F9B7;Lo;0;L;86A9;;;;N;;;;; +2F9B8;CJK COMPATIBILITY IDEOGRAPH-2F9B8;Lo;0;L;8688;;;;N;;;;; +2F9B9;CJK COMPATIBILITY IDEOGRAPH-2F9B9;Lo;0;L;870E;;;;N;;;;; +2F9BA;CJK COMPATIBILITY IDEOGRAPH-2F9BA;Lo;0;L;86E2;;;;N;;;;; +2F9BB;CJK COMPATIBILITY IDEOGRAPH-2F9BB;Lo;0;L;8779;;;;N;;;;; +2F9BC;CJK COMPATIBILITY IDEOGRAPH-2F9BC;Lo;0;L;8728;;;;N;;;;; +2F9BD;CJK COMPATIBILITY IDEOGRAPH-2F9BD;Lo;0;L;876B;;;;N;;;;; +2F9BE;CJK COMPATIBILITY IDEOGRAPH-2F9BE;Lo;0;L;8786;;;;N;;;;; +2F9BF;CJK COMPATIBILITY IDEOGRAPH-2F9BF;Lo;0;L;45D7;;;;N;;;;; +2F9C0;CJK COMPATIBILITY IDEOGRAPH-2F9C0;Lo;0;L;87E1;;;;N;;;;; +2F9C1;CJK COMPATIBILITY IDEOGRAPH-2F9C1;Lo;0;L;8801;;;;N;;;;; +2F9C2;CJK COMPATIBILITY IDEOGRAPH-2F9C2;Lo;0;L;45F9;;;;N;;;;; +2F9C3;CJK COMPATIBILITY IDEOGRAPH-2F9C3;Lo;0;L;8860;;;;N;;;;; +2F9C4;CJK COMPATIBILITY IDEOGRAPH-2F9C4;Lo;0;L;8863;;;;N;;;;; +2F9C5;CJK COMPATIBILITY IDEOGRAPH-2F9C5;Lo;0;L;27667;;;;N;;;;; +2F9C6;CJK COMPATIBILITY IDEOGRAPH-2F9C6;Lo;0;L;88D7;;;;N;;;;; +2F9C7;CJK COMPATIBILITY IDEOGRAPH-2F9C7;Lo;0;L;88DE;;;;N;;;;; +2F9C8;CJK COMPATIBILITY IDEOGRAPH-2F9C8;Lo;0;L;4635;;;;N;;;;; +2F9C9;CJK COMPATIBILITY IDEOGRAPH-2F9C9;Lo;0;L;88FA;;;;N;;;;; +2F9CA;CJK COMPATIBILITY IDEOGRAPH-2F9CA;Lo;0;L;34BB;;;;N;;;;; +2F9CB;CJK COMPATIBILITY IDEOGRAPH-2F9CB;Lo;0;L;278AE;;;;N;;;;; +2F9CC;CJK COMPATIBILITY IDEOGRAPH-2F9CC;Lo;0;L;27966;;;;N;;;;; +2F9CD;CJK COMPATIBILITY IDEOGRAPH-2F9CD;Lo;0;L;46BE;;;;N;;;;; +2F9CE;CJK COMPATIBILITY IDEOGRAPH-2F9CE;Lo;0;L;46C7;;;;N;;;;; +2F9CF;CJK COMPATIBILITY IDEOGRAPH-2F9CF;Lo;0;L;8AA0;;;;N;;;;; +2F9D0;CJK COMPATIBILITY IDEOGRAPH-2F9D0;Lo;0;L;8AED;;;;N;;;;; +2F9D1;CJK COMPATIBILITY IDEOGRAPH-2F9D1;Lo;0;L;8B8A;;;;N;;;;; +2F9D2;CJK COMPATIBILITY IDEOGRAPH-2F9D2;Lo;0;L;8C55;;;;N;;;;; +2F9D3;CJK COMPATIBILITY IDEOGRAPH-2F9D3;Lo;0;L;27CA8;;;;N;;;;; +2F9D4;CJK COMPATIBILITY IDEOGRAPH-2F9D4;Lo;0;L;8CAB;;;;N;;;;; +2F9D5;CJK COMPATIBILITY IDEOGRAPH-2F9D5;Lo;0;L;8CC1;;;;N;;;;; +2F9D6;CJK COMPATIBILITY IDEOGRAPH-2F9D6;Lo;0;L;8D1B;;;;N;;;;; +2F9D7;CJK COMPATIBILITY IDEOGRAPH-2F9D7;Lo;0;L;8D77;;;;N;;;;; +2F9D8;CJK COMPATIBILITY IDEOGRAPH-2F9D8;Lo;0;L;27F2F;;;;N;;;;; +2F9D9;CJK COMPATIBILITY IDEOGRAPH-2F9D9;Lo;0;L;20804;;;;N;;;;; +2F9DA;CJK COMPATIBILITY IDEOGRAPH-2F9DA;Lo;0;L;8DCB;;;;N;;;;; +2F9DB;CJK COMPATIBILITY IDEOGRAPH-2F9DB;Lo;0;L;8DBC;;;;N;;;;; +2F9DC;CJK COMPATIBILITY IDEOGRAPH-2F9DC;Lo;0;L;8DF0;;;;N;;;;; +2F9DD;CJK COMPATIBILITY IDEOGRAPH-2F9DD;Lo;0;L;208DE;;;;N;;;;; +2F9DE;CJK COMPATIBILITY IDEOGRAPH-2F9DE;Lo;0;L;8ED4;;;;N;;;;; +2F9DF;CJK COMPATIBILITY IDEOGRAPH-2F9DF;Lo;0;L;8F38;;;;N;;;;; +2F9E0;CJK COMPATIBILITY IDEOGRAPH-2F9E0;Lo;0;L;285D2;;;;N;;;;; +2F9E1;CJK COMPATIBILITY IDEOGRAPH-2F9E1;Lo;0;L;285ED;;;;N;;;;; +2F9E2;CJK COMPATIBILITY IDEOGRAPH-2F9E2;Lo;0;L;9094;;;;N;;;;; +2F9E3;CJK COMPATIBILITY IDEOGRAPH-2F9E3;Lo;0;L;90F1;;;;N;;;;; +2F9E4;CJK COMPATIBILITY IDEOGRAPH-2F9E4;Lo;0;L;9111;;;;N;;;;; +2F9E5;CJK COMPATIBILITY IDEOGRAPH-2F9E5;Lo;0;L;2872E;;;;N;;;;; +2F9E6;CJK COMPATIBILITY IDEOGRAPH-2F9E6;Lo;0;L;911B;;;;N;;;;; +2F9E7;CJK COMPATIBILITY IDEOGRAPH-2F9E7;Lo;0;L;9238;;;;N;;;;; +2F9E8;CJK COMPATIBILITY IDEOGRAPH-2F9E8;Lo;0;L;92D7;;;;N;;;;; +2F9E9;CJK COMPATIBILITY IDEOGRAPH-2F9E9;Lo;0;L;92D8;;;;N;;;;; +2F9EA;CJK COMPATIBILITY IDEOGRAPH-2F9EA;Lo;0;L;927C;;;;N;;;;; +2F9EB;CJK COMPATIBILITY IDEOGRAPH-2F9EB;Lo;0;L;93F9;;;;N;;;;; +2F9EC;CJK COMPATIBILITY IDEOGRAPH-2F9EC;Lo;0;L;9415;;;;N;;;;; +2F9ED;CJK COMPATIBILITY IDEOGRAPH-2F9ED;Lo;0;L;28BFA;;;;N;;;;; +2F9EE;CJK COMPATIBILITY IDEOGRAPH-2F9EE;Lo;0;L;958B;;;;N;;;;; +2F9EF;CJK COMPATIBILITY IDEOGRAPH-2F9EF;Lo;0;L;4995;;;;N;;;;; +2F9F0;CJK COMPATIBILITY IDEOGRAPH-2F9F0;Lo;0;L;95B7;;;;N;;;;; +2F9F1;CJK COMPATIBILITY IDEOGRAPH-2F9F1;Lo;0;L;28D77;;;;N;;;;; +2F9F2;CJK COMPATIBILITY IDEOGRAPH-2F9F2;Lo;0;L;49E6;;;;N;;;;; +2F9F3;CJK COMPATIBILITY IDEOGRAPH-2F9F3;Lo;0;L;96C3;;;;N;;;;; +2F9F4;CJK COMPATIBILITY IDEOGRAPH-2F9F4;Lo;0;L;5DB2;;;;N;;;;; +2F9F5;CJK COMPATIBILITY IDEOGRAPH-2F9F5;Lo;0;L;9723;;;;N;;;;; +2F9F6;CJK COMPATIBILITY IDEOGRAPH-2F9F6;Lo;0;L;29145;;;;N;;;;; +2F9F7;CJK COMPATIBILITY IDEOGRAPH-2F9F7;Lo;0;L;2921A;;;;N;;;;; +2F9F8;CJK COMPATIBILITY IDEOGRAPH-2F9F8;Lo;0;L;4A6E;;;;N;;;;; +2F9F9;CJK COMPATIBILITY IDEOGRAPH-2F9F9;Lo;0;L;4A76;;;;N;;;;; +2F9FA;CJK COMPATIBILITY IDEOGRAPH-2F9FA;Lo;0;L;97E0;;;;N;;;;; +2F9FB;CJK COMPATIBILITY IDEOGRAPH-2F9FB;Lo;0;L;2940A;;;;N;;;;; +2F9FC;CJK COMPATIBILITY IDEOGRAPH-2F9FC;Lo;0;L;4AB2;;;;N;;;;; +2F9FD;CJK COMPATIBILITY IDEOGRAPH-2F9FD;Lo;0;L;29496;;;;N;;;;; +2F9FE;CJK COMPATIBILITY IDEOGRAPH-2F9FE;Lo;0;L;980B;;;;N;;;;; +2F9FF;CJK COMPATIBILITY IDEOGRAPH-2F9FF;Lo;0;L;980B;;;;N;;;;; +2FA00;CJK COMPATIBILITY IDEOGRAPH-2FA00;Lo;0;L;9829;;;;N;;;;; +2FA01;CJK COMPATIBILITY IDEOGRAPH-2FA01;Lo;0;L;295B6;;;;N;;;;; +2FA02;CJK COMPATIBILITY IDEOGRAPH-2FA02;Lo;0;L;98E2;;;;N;;;;; +2FA03;CJK COMPATIBILITY IDEOGRAPH-2FA03;Lo;0;L;4B33;;;;N;;;;; +2FA04;CJK COMPATIBILITY IDEOGRAPH-2FA04;Lo;0;L;9929;;;;N;;;;; +2FA05;CJK COMPATIBILITY IDEOGRAPH-2FA05;Lo;0;L;99A7;;;;N;;;;; +2FA06;CJK COMPATIBILITY IDEOGRAPH-2FA06;Lo;0;L;99C2;;;;N;;;;; +2FA07;CJK COMPATIBILITY IDEOGRAPH-2FA07;Lo;0;L;99FE;;;;N;;;;; +2FA08;CJK COMPATIBILITY IDEOGRAPH-2FA08;Lo;0;L;4BCE;;;;N;;;;; +2FA09;CJK COMPATIBILITY IDEOGRAPH-2FA09;Lo;0;L;29B30;;;;N;;;;; +2FA0A;CJK COMPATIBILITY IDEOGRAPH-2FA0A;Lo;0;L;9B12;;;;N;;;;; +2FA0B;CJK COMPATIBILITY IDEOGRAPH-2FA0B;Lo;0;L;9C40;;;;N;;;;; +2FA0C;CJK COMPATIBILITY IDEOGRAPH-2FA0C;Lo;0;L;9CFD;;;;N;;;;; +2FA0D;CJK COMPATIBILITY IDEOGRAPH-2FA0D;Lo;0;L;4CCE;;;;N;;;;; +2FA0E;CJK COMPATIBILITY IDEOGRAPH-2FA0E;Lo;0;L;4CED;;;;N;;;;; +2FA0F;CJK COMPATIBILITY IDEOGRAPH-2FA0F;Lo;0;L;9D67;;;;N;;;;; +2FA10;CJK COMPATIBILITY IDEOGRAPH-2FA10;Lo;0;L;2A0CE;;;;N;;;;; +2FA11;CJK COMPATIBILITY IDEOGRAPH-2FA11;Lo;0;L;4CF8;;;;N;;;;; +2FA12;CJK COMPATIBILITY IDEOGRAPH-2FA12;Lo;0;L;2A105;;;;N;;;;; +2FA13;CJK COMPATIBILITY IDEOGRAPH-2FA13;Lo;0;L;2A20E;;;;N;;;;; +2FA14;CJK COMPATIBILITY IDEOGRAPH-2FA14;Lo;0;L;2A291;;;;N;;;;; +2FA15;CJK COMPATIBILITY IDEOGRAPH-2FA15;Lo;0;L;9EBB;;;;N;;;;; +2FA16;CJK COMPATIBILITY IDEOGRAPH-2FA16;Lo;0;L;4D56;;;;N;;;;; +2FA17;CJK COMPATIBILITY IDEOGRAPH-2FA17;Lo;0;L;9EF9;;;;N;;;;; +2FA18;CJK COMPATIBILITY IDEOGRAPH-2FA18;Lo;0;L;9EFE;;;;N;;;;; +2FA19;CJK COMPATIBILITY IDEOGRAPH-2FA19;Lo;0;L;9F05;;;;N;;;;; +2FA1A;CJK COMPATIBILITY IDEOGRAPH-2FA1A;Lo;0;L;9F0F;;;;N;;;;; +2FA1B;CJK COMPATIBILITY IDEOGRAPH-2FA1B;Lo;0;L;9F16;;;;N;;;;; +2FA1C;CJK COMPATIBILITY IDEOGRAPH-2FA1C;Lo;0;L;9F3B;;;;N;;;;; +2FA1D;CJK COMPATIBILITY IDEOGRAPH-2FA1D;Lo;0;L;2A600;;;;N;;;;; +E0001;LANGUAGE TAG;Cf;0;BN;;;;;N;;;;; +E0020;TAG SPACE;Cf;0;BN;;;;;N;;;;; +E0021;TAG EXCLAMATION MARK;Cf;0;BN;;;;;N;;;;; +E0022;TAG QUOTATION MARK;Cf;0;BN;;;;;N;;;;; +E0023;TAG NUMBER SIGN;Cf;0;BN;;;;;N;;;;; +E0024;TAG DOLLAR SIGN;Cf;0;BN;;;;;N;;;;; +E0025;TAG PERCENT SIGN;Cf;0;BN;;;;;N;;;;; +E0026;TAG AMPERSAND;Cf;0;BN;;;;;N;;;;; +E0027;TAG APOSTROPHE;Cf;0;BN;;;;;N;;;;; +E0028;TAG LEFT PARENTHESIS;Cf;0;BN;;;;;N;;;;; +E0029;TAG RIGHT PARENTHESIS;Cf;0;BN;;;;;N;;;;; +E002A;TAG ASTERISK;Cf;0;BN;;;;;N;;;;; +E002B;TAG PLUS SIGN;Cf;0;BN;;;;;N;;;;; +E002C;TAG COMMA;Cf;0;BN;;;;;N;;;;; +E002D;TAG HYPHEN-MINUS;Cf;0;BN;;;;;N;;;;; +E002E;TAG FULL STOP;Cf;0;BN;;;;;N;;;;; +E002F;TAG SOLIDUS;Cf;0;BN;;;;;N;;;;; +E0030;TAG DIGIT ZERO;Cf;0;BN;;;;;N;;;;; +E0031;TAG DIGIT ONE;Cf;0;BN;;;;;N;;;;; +E0032;TAG DIGIT TWO;Cf;0;BN;;;;;N;;;;; +E0033;TAG DIGIT THREE;Cf;0;BN;;;;;N;;;;; +E0034;TAG DIGIT FOUR;Cf;0;BN;;;;;N;;;;; +E0035;TAG DIGIT FIVE;Cf;0;BN;;;;;N;;;;; +E0036;TAG DIGIT SIX;Cf;0;BN;;;;;N;;;;; +E0037;TAG DIGIT SEVEN;Cf;0;BN;;;;;N;;;;; +E0038;TAG DIGIT EIGHT;Cf;0;BN;;;;;N;;;;; +E0039;TAG DIGIT NINE;Cf;0;BN;;;;;N;;;;; +E003A;TAG COLON;Cf;0;BN;;;;;N;;;;; +E003B;TAG SEMICOLON;Cf;0;BN;;;;;N;;;;; +E003C;TAG LESS-THAN SIGN;Cf;0;BN;;;;;N;;;;; +E003D;TAG EQUALS SIGN;Cf;0;BN;;;;;N;;;;; +E003E;TAG GREATER-THAN SIGN;Cf;0;BN;;;;;N;;;;; +E003F;TAG QUESTION MARK;Cf;0;BN;;;;;N;;;;; +E0040;TAG COMMERCIAL AT;Cf;0;BN;;;;;N;;;;; +E0041;TAG LATIN CAPITAL LETTER A;Cf;0;BN;;;;;N;;;;; +E0042;TAG LATIN CAPITAL LETTER B;Cf;0;BN;;;;;N;;;;; +E0043;TAG LATIN CAPITAL LETTER C;Cf;0;BN;;;;;N;;;;; +E0044;TAG LATIN CAPITAL LETTER D;Cf;0;BN;;;;;N;;;;; +E0045;TAG LATIN CAPITAL LETTER E;Cf;0;BN;;;;;N;;;;; +E0046;TAG LATIN CAPITAL LETTER F;Cf;0;BN;;;;;N;;;;; +E0047;TAG LATIN CAPITAL LETTER G;Cf;0;BN;;;;;N;;;;; +E0048;TAG LATIN CAPITAL LETTER H;Cf;0;BN;;;;;N;;;;; +E0049;TAG LATIN CAPITAL LETTER I;Cf;0;BN;;;;;N;;;;; +E004A;TAG LATIN CAPITAL LETTER J;Cf;0;BN;;;;;N;;;;; +E004B;TAG LATIN CAPITAL LETTER K;Cf;0;BN;;;;;N;;;;; +E004C;TAG LATIN CAPITAL LETTER L;Cf;0;BN;;;;;N;;;;; +E004D;TAG LATIN CAPITAL LETTER M;Cf;0;BN;;;;;N;;;;; +E004E;TAG LATIN CAPITAL LETTER N;Cf;0;BN;;;;;N;;;;; +E004F;TAG LATIN CAPITAL LETTER O;Cf;0;BN;;;;;N;;;;; +E0050;TAG LATIN CAPITAL LETTER P;Cf;0;BN;;;;;N;;;;; +E0051;TAG LATIN CAPITAL LETTER Q;Cf;0;BN;;;;;N;;;;; +E0052;TAG LATIN CAPITAL LETTER R;Cf;0;BN;;;;;N;;;;; +E0053;TAG LATIN CAPITAL LETTER S;Cf;0;BN;;;;;N;;;;; +E0054;TAG LATIN CAPITAL LETTER T;Cf;0;BN;;;;;N;;;;; +E0055;TAG LATIN CAPITAL LETTER U;Cf;0;BN;;;;;N;;;;; +E0056;TAG LATIN CAPITAL LETTER V;Cf;0;BN;;;;;N;;;;; +E0057;TAG LATIN CAPITAL LETTER W;Cf;0;BN;;;;;N;;;;; +E0058;TAG LATIN CAPITAL LETTER X;Cf;0;BN;;;;;N;;;;; +E0059;TAG LATIN CAPITAL LETTER Y;Cf;0;BN;;;;;N;;;;; +E005A;TAG LATIN CAPITAL LETTER Z;Cf;0;BN;;;;;N;;;;; +E005B;TAG LEFT SQUARE BRACKET;Cf;0;BN;;;;;N;;;;; +E005C;TAG REVERSE SOLIDUS;Cf;0;BN;;;;;N;;;;; +E005D;TAG RIGHT SQUARE BRACKET;Cf;0;BN;;;;;N;;;;; +E005E;TAG CIRCUMFLEX ACCENT;Cf;0;BN;;;;;N;;;;; +E005F;TAG LOW LINE;Cf;0;BN;;;;;N;;;;; +E0060;TAG GRAVE ACCENT;Cf;0;BN;;;;;N;;;;; +E0061;TAG LATIN SMALL LETTER A;Cf;0;BN;;;;;N;;;;; +E0062;TAG LATIN SMALL LETTER B;Cf;0;BN;;;;;N;;;;; +E0063;TAG LATIN SMALL LETTER C;Cf;0;BN;;;;;N;;;;; +E0064;TAG LATIN SMALL LETTER D;Cf;0;BN;;;;;N;;;;; +E0065;TAG LATIN SMALL LETTER E;Cf;0;BN;;;;;N;;;;; +E0066;TAG LATIN SMALL LETTER F;Cf;0;BN;;;;;N;;;;; +E0067;TAG LATIN SMALL LETTER G;Cf;0;BN;;;;;N;;;;; +E0068;TAG LATIN SMALL LETTER H;Cf;0;BN;;;;;N;;;;; +E0069;TAG LATIN SMALL LETTER I;Cf;0;BN;;;;;N;;;;; +E006A;TAG LATIN SMALL LETTER J;Cf;0;BN;;;;;N;;;;; +E006B;TAG LATIN SMALL LETTER K;Cf;0;BN;;;;;N;;;;; +E006C;TAG LATIN SMALL LETTER L;Cf;0;BN;;;;;N;;;;; +E006D;TAG LATIN SMALL LETTER M;Cf;0;BN;;;;;N;;;;; +E006E;TAG LATIN SMALL LETTER N;Cf;0;BN;;;;;N;;;;; +E006F;TAG LATIN SMALL LETTER O;Cf;0;BN;;;;;N;;;;; +E0070;TAG LATIN SMALL LETTER P;Cf;0;BN;;;;;N;;;;; +E0071;TAG LATIN SMALL LETTER Q;Cf;0;BN;;;;;N;;;;; +E0072;TAG LATIN SMALL LETTER R;Cf;0;BN;;;;;N;;;;; +E0073;TAG LATIN SMALL LETTER S;Cf;0;BN;;;;;N;;;;; +E0074;TAG LATIN SMALL LETTER T;Cf;0;BN;;;;;N;;;;; +E0075;TAG LATIN SMALL LETTER U;Cf;0;BN;;;;;N;;;;; +E0076;TAG LATIN SMALL LETTER V;Cf;0;BN;;;;;N;;;;; +E0077;TAG LATIN SMALL LETTER W;Cf;0;BN;;;;;N;;;;; +E0078;TAG LATIN SMALL LETTER X;Cf;0;BN;;;;;N;;;;; +E0079;TAG LATIN SMALL LETTER Y;Cf;0;BN;;;;;N;;;;; +E007A;TAG LATIN SMALL LETTER Z;Cf;0;BN;;;;;N;;;;; +E007B;TAG LEFT CURLY BRACKET;Cf;0;BN;;;;;N;;;;; +E007C;TAG VERTICAL LINE;Cf;0;BN;;;;;N;;;;; +E007D;TAG RIGHT CURLY BRACKET;Cf;0;BN;;;;;N;;;;; +E007E;TAG TILDE;Cf;0;BN;;;;;N;;;;; +E007F;CANCEL TAG;Cf;0;BN;;;;;N;;;;; +E0100;VARIATION SELECTOR-17;Mn;0;NSM;;;;;N;;;;; +E0101;VARIATION SELECTOR-18;Mn;0;NSM;;;;;N;;;;; +E0102;VARIATION SELECTOR-19;Mn;0;NSM;;;;;N;;;;; +E0103;VARIATION SELECTOR-20;Mn;0;NSM;;;;;N;;;;; +E0104;VARIATION SELECTOR-21;Mn;0;NSM;;;;;N;;;;; +E0105;VARIATION SELECTOR-22;Mn;0;NSM;;;;;N;;;;; +E0106;VARIATION SELECTOR-23;Mn;0;NSM;;;;;N;;;;; +E0107;VARIATION SELECTOR-24;Mn;0;NSM;;;;;N;;;;; +E0108;VARIATION SELECTOR-25;Mn;0;NSM;;;;;N;;;;; +E0109;VARIATION SELECTOR-26;Mn;0;NSM;;;;;N;;;;; +E010A;VARIATION SELECTOR-27;Mn;0;NSM;;;;;N;;;;; +E010B;VARIATION SELECTOR-28;Mn;0;NSM;;;;;N;;;;; +E010C;VARIATION SELECTOR-29;Mn;0;NSM;;;;;N;;;;; +E010D;VARIATION SELECTOR-30;Mn;0;NSM;;;;;N;;;;; +E010E;VARIATION SELECTOR-31;Mn;0;NSM;;;;;N;;;;; +E010F;VARIATION SELECTOR-32;Mn;0;NSM;;;;;N;;;;; +E0110;VARIATION SELECTOR-33;Mn;0;NSM;;;;;N;;;;; +E0111;VARIATION SELECTOR-34;Mn;0;NSM;;;;;N;;;;; +E0112;VARIATION SELECTOR-35;Mn;0;NSM;;;;;N;;;;; +E0113;VARIATION SELECTOR-36;Mn;0;NSM;;;;;N;;;;; +E0114;VARIATION SELECTOR-37;Mn;0;NSM;;;;;N;;;;; +E0115;VARIATION SELECTOR-38;Mn;0;NSM;;;;;N;;;;; +E0116;VARIATION SELECTOR-39;Mn;0;NSM;;;;;N;;;;; +E0117;VARIATION SELECTOR-40;Mn;0;NSM;;;;;N;;;;; +E0118;VARIATION SELECTOR-41;Mn;0;NSM;;;;;N;;;;; +E0119;VARIATION SELECTOR-42;Mn;0;NSM;;;;;N;;;;; +E011A;VARIATION SELECTOR-43;Mn;0;NSM;;;;;N;;;;; +E011B;VARIATION SELECTOR-44;Mn;0;NSM;;;;;N;;;;; +E011C;VARIATION SELECTOR-45;Mn;0;NSM;;;;;N;;;;; +E011D;VARIATION SELECTOR-46;Mn;0;NSM;;;;;N;;;;; +E011E;VARIATION SELECTOR-47;Mn;0;NSM;;;;;N;;;;; +E011F;VARIATION SELECTOR-48;Mn;0;NSM;;;;;N;;;;; +E0120;VARIATION SELECTOR-49;Mn;0;NSM;;;;;N;;;;; +E0121;VARIATION SELECTOR-50;Mn;0;NSM;;;;;N;;;;; +E0122;VARIATION SELECTOR-51;Mn;0;NSM;;;;;N;;;;; +E0123;VARIATION SELECTOR-52;Mn;0;NSM;;;;;N;;;;; +E0124;VARIATION SELECTOR-53;Mn;0;NSM;;;;;N;;;;; +E0125;VARIATION SELECTOR-54;Mn;0;NSM;;;;;N;;;;; +E0126;VARIATION SELECTOR-55;Mn;0;NSM;;;;;N;;;;; +E0127;VARIATION SELECTOR-56;Mn;0;NSM;;;;;N;;;;; +E0128;VARIATION SELECTOR-57;Mn;0;NSM;;;;;N;;;;; +E0129;VARIATION SELECTOR-58;Mn;0;NSM;;;;;N;;;;; +E012A;VARIATION SELECTOR-59;Mn;0;NSM;;;;;N;;;;; +E012B;VARIATION SELECTOR-60;Mn;0;NSM;;;;;N;;;;; +E012C;VARIATION SELECTOR-61;Mn;0;NSM;;;;;N;;;;; +E012D;VARIATION SELECTOR-62;Mn;0;NSM;;;;;N;;;;; +E012E;VARIATION SELECTOR-63;Mn;0;NSM;;;;;N;;;;; +E012F;VARIATION SELECTOR-64;Mn;0;NSM;;;;;N;;;;; +E0130;VARIATION SELECTOR-65;Mn;0;NSM;;;;;N;;;;; +E0131;VARIATION SELECTOR-66;Mn;0;NSM;;;;;N;;;;; +E0132;VARIATION SELECTOR-67;Mn;0;NSM;;;;;N;;;;; +E0133;VARIATION SELECTOR-68;Mn;0;NSM;;;;;N;;;;; +E0134;VARIATION SELECTOR-69;Mn;0;NSM;;;;;N;;;;; +E0135;VARIATION SELECTOR-70;Mn;0;NSM;;;;;N;;;;; +E0136;VARIATION SELECTOR-71;Mn;0;NSM;;;;;N;;;;; +E0137;VARIATION SELECTOR-72;Mn;0;NSM;;;;;N;;;;; +E0138;VARIATION SELECTOR-73;Mn;0;NSM;;;;;N;;;;; +E0139;VARIATION SELECTOR-74;Mn;0;NSM;;;;;N;;;;; +E013A;VARIATION SELECTOR-75;Mn;0;NSM;;;;;N;;;;; +E013B;VARIATION SELECTOR-76;Mn;0;NSM;;;;;N;;;;; +E013C;VARIATION SELECTOR-77;Mn;0;NSM;;;;;N;;;;; +E013D;VARIATION SELECTOR-78;Mn;0;NSM;;;;;N;;;;; +E013E;VARIATION SELECTOR-79;Mn;0;NSM;;;;;N;;;;; +E013F;VARIATION SELECTOR-80;Mn;0;NSM;;;;;N;;;;; +E0140;VARIATION SELECTOR-81;Mn;0;NSM;;;;;N;;;;; +E0141;VARIATION SELECTOR-82;Mn;0;NSM;;;;;N;;;;; +E0142;VARIATION SELECTOR-83;Mn;0;NSM;;;;;N;;;;; +E0143;VARIATION SELECTOR-84;Mn;0;NSM;;;;;N;;;;; +E0144;VARIATION SELECTOR-85;Mn;0;NSM;;;;;N;;;;; +E0145;VARIATION SELECTOR-86;Mn;0;NSM;;;;;N;;;;; +E0146;VARIATION SELECTOR-87;Mn;0;NSM;;;;;N;;;;; +E0147;VARIATION SELECTOR-88;Mn;0;NSM;;;;;N;;;;; +E0148;VARIATION SELECTOR-89;Mn;0;NSM;;;;;N;;;;; +E0149;VARIATION SELECTOR-90;Mn;0;NSM;;;;;N;;;;; +E014A;VARIATION SELECTOR-91;Mn;0;NSM;;;;;N;;;;; +E014B;VARIATION SELECTOR-92;Mn;0;NSM;;;;;N;;;;; +E014C;VARIATION SELECTOR-93;Mn;0;NSM;;;;;N;;;;; +E014D;VARIATION SELECTOR-94;Mn;0;NSM;;;;;N;;;;; +E014E;VARIATION SELECTOR-95;Mn;0;NSM;;;;;N;;;;; +E014F;VARIATION SELECTOR-96;Mn;0;NSM;;;;;N;;;;; +E0150;VARIATION SELECTOR-97;Mn;0;NSM;;;;;N;;;;; +E0151;VARIATION SELECTOR-98;Mn;0;NSM;;;;;N;;;;; +E0152;VARIATION SELECTOR-99;Mn;0;NSM;;;;;N;;;;; +E0153;VARIATION SELECTOR-100;Mn;0;NSM;;;;;N;;;;; +E0154;VARIATION SELECTOR-101;Mn;0;NSM;;;;;N;;;;; +E0155;VARIATION SELECTOR-102;Mn;0;NSM;;;;;N;;;;; +E0156;VARIATION SELECTOR-103;Mn;0;NSM;;;;;N;;;;; +E0157;VARIATION SELECTOR-104;Mn;0;NSM;;;;;N;;;;; +E0158;VARIATION SELECTOR-105;Mn;0;NSM;;;;;N;;;;; +E0159;VARIATION SELECTOR-106;Mn;0;NSM;;;;;N;;;;; +E015A;VARIATION SELECTOR-107;Mn;0;NSM;;;;;N;;;;; +E015B;VARIATION SELECTOR-108;Mn;0;NSM;;;;;N;;;;; +E015C;VARIATION SELECTOR-109;Mn;0;NSM;;;;;N;;;;; +E015D;VARIATION SELECTOR-110;Mn;0;NSM;;;;;N;;;;; +E015E;VARIATION SELECTOR-111;Mn;0;NSM;;;;;N;;;;; +E015F;VARIATION SELECTOR-112;Mn;0;NSM;;;;;N;;;;; +E0160;VARIATION SELECTOR-113;Mn;0;NSM;;;;;N;;;;; +E0161;VARIATION SELECTOR-114;Mn;0;NSM;;;;;N;;;;; +E0162;VARIATION SELECTOR-115;Mn;0;NSM;;;;;N;;;;; +E0163;VARIATION SELECTOR-116;Mn;0;NSM;;;;;N;;;;; +E0164;VARIATION SELECTOR-117;Mn;0;NSM;;;;;N;;;;; +E0165;VARIATION SELECTOR-118;Mn;0;NSM;;;;;N;;;;; +E0166;VARIATION SELECTOR-119;Mn;0;NSM;;;;;N;;;;; +E0167;VARIATION SELECTOR-120;Mn;0;NSM;;;;;N;;;;; +E0168;VARIATION SELECTOR-121;Mn;0;NSM;;;;;N;;;;; +E0169;VARIATION SELECTOR-122;Mn;0;NSM;;;;;N;;;;; +E016A;VARIATION SELECTOR-123;Mn;0;NSM;;;;;N;;;;; +E016B;VARIATION SELECTOR-124;Mn;0;NSM;;;;;N;;;;; +E016C;VARIATION SELECTOR-125;Mn;0;NSM;;;;;N;;;;; +E016D;VARIATION SELECTOR-126;Mn;0;NSM;;;;;N;;;;; +E016E;VARIATION SELECTOR-127;Mn;0;NSM;;;;;N;;;;; +E016F;VARIATION SELECTOR-128;Mn;0;NSM;;;;;N;;;;; +E0170;VARIATION SELECTOR-129;Mn;0;NSM;;;;;N;;;;; +E0171;VARIATION SELECTOR-130;Mn;0;NSM;;;;;N;;;;; +E0172;VARIATION SELECTOR-131;Mn;0;NSM;;;;;N;;;;; +E0173;VARIATION SELECTOR-132;Mn;0;NSM;;;;;N;;;;; +E0174;VARIATION SELECTOR-133;Mn;0;NSM;;;;;N;;;;; +E0175;VARIATION SELECTOR-134;Mn;0;NSM;;;;;N;;;;; +E0176;VARIATION SELECTOR-135;Mn;0;NSM;;;;;N;;;;; +E0177;VARIATION SELECTOR-136;Mn;0;NSM;;;;;N;;;;; +E0178;VARIATION SELECTOR-137;Mn;0;NSM;;;;;N;;;;; +E0179;VARIATION SELECTOR-138;Mn;0;NSM;;;;;N;;;;; +E017A;VARIATION SELECTOR-139;Mn;0;NSM;;;;;N;;;;; +E017B;VARIATION SELECTOR-140;Mn;0;NSM;;;;;N;;;;; +E017C;VARIATION SELECTOR-141;Mn;0;NSM;;;;;N;;;;; +E017D;VARIATION SELECTOR-142;Mn;0;NSM;;;;;N;;;;; +E017E;VARIATION SELECTOR-143;Mn;0;NSM;;;;;N;;;;; +E017F;VARIATION SELECTOR-144;Mn;0;NSM;;;;;N;;;;; +E0180;VARIATION SELECTOR-145;Mn;0;NSM;;;;;N;;;;; +E0181;VARIATION SELECTOR-146;Mn;0;NSM;;;;;N;;;;; +E0182;VARIATION SELECTOR-147;Mn;0;NSM;;;;;N;;;;; +E0183;VARIATION SELECTOR-148;Mn;0;NSM;;;;;N;;;;; +E0184;VARIATION SELECTOR-149;Mn;0;NSM;;;;;N;;;;; +E0185;VARIATION SELECTOR-150;Mn;0;NSM;;;;;N;;;;; +E0186;VARIATION SELECTOR-151;Mn;0;NSM;;;;;N;;;;; +E0187;VARIATION SELECTOR-152;Mn;0;NSM;;;;;N;;;;; +E0188;VARIATION SELECTOR-153;Mn;0;NSM;;;;;N;;;;; +E0189;VARIATION SELECTOR-154;Mn;0;NSM;;;;;N;;;;; +E018A;VARIATION SELECTOR-155;Mn;0;NSM;;;;;N;;;;; +E018B;VARIATION SELECTOR-156;Mn;0;NSM;;;;;N;;;;; +E018C;VARIATION SELECTOR-157;Mn;0;NSM;;;;;N;;;;; +E018D;VARIATION SELECTOR-158;Mn;0;NSM;;;;;N;;;;; +E018E;VARIATION SELECTOR-159;Mn;0;NSM;;;;;N;;;;; +E018F;VARIATION SELECTOR-160;Mn;0;NSM;;;;;N;;;;; +E0190;VARIATION SELECTOR-161;Mn;0;NSM;;;;;N;;;;; +E0191;VARIATION SELECTOR-162;Mn;0;NSM;;;;;N;;;;; +E0192;VARIATION SELECTOR-163;Mn;0;NSM;;;;;N;;;;; +E0193;VARIATION SELECTOR-164;Mn;0;NSM;;;;;N;;;;; +E0194;VARIATION SELECTOR-165;Mn;0;NSM;;;;;N;;;;; +E0195;VARIATION SELECTOR-166;Mn;0;NSM;;;;;N;;;;; +E0196;VARIATION SELECTOR-167;Mn;0;NSM;;;;;N;;;;; +E0197;VARIATION SELECTOR-168;Mn;0;NSM;;;;;N;;;;; +E0198;VARIATION SELECTOR-169;Mn;0;NSM;;;;;N;;;;; +E0199;VARIATION SELECTOR-170;Mn;0;NSM;;;;;N;;;;; +E019A;VARIATION SELECTOR-171;Mn;0;NSM;;;;;N;;;;; +E019B;VARIATION SELECTOR-172;Mn;0;NSM;;;;;N;;;;; +E019C;VARIATION SELECTOR-173;Mn;0;NSM;;;;;N;;;;; +E019D;VARIATION SELECTOR-174;Mn;0;NSM;;;;;N;;;;; +E019E;VARIATION SELECTOR-175;Mn;0;NSM;;;;;N;;;;; +E019F;VARIATION SELECTOR-176;Mn;0;NSM;;;;;N;;;;; +E01A0;VARIATION SELECTOR-177;Mn;0;NSM;;;;;N;;;;; +E01A1;VARIATION SELECTOR-178;Mn;0;NSM;;;;;N;;;;; +E01A2;VARIATION SELECTOR-179;Mn;0;NSM;;;;;N;;;;; +E01A3;VARIATION SELECTOR-180;Mn;0;NSM;;;;;N;;;;; +E01A4;VARIATION SELECTOR-181;Mn;0;NSM;;;;;N;;;;; +E01A5;VARIATION SELECTOR-182;Mn;0;NSM;;;;;N;;;;; +E01A6;VARIATION SELECTOR-183;Mn;0;NSM;;;;;N;;;;; +E01A7;VARIATION SELECTOR-184;Mn;0;NSM;;;;;N;;;;; +E01A8;VARIATION SELECTOR-185;Mn;0;NSM;;;;;N;;;;; +E01A9;VARIATION SELECTOR-186;Mn;0;NSM;;;;;N;;;;; +E01AA;VARIATION SELECTOR-187;Mn;0;NSM;;;;;N;;;;; +E01AB;VARIATION SELECTOR-188;Mn;0;NSM;;;;;N;;;;; +E01AC;VARIATION SELECTOR-189;Mn;0;NSM;;;;;N;;;;; +E01AD;VARIATION SELECTOR-190;Mn;0;NSM;;;;;N;;;;; +E01AE;VARIATION SELECTOR-191;Mn;0;NSM;;;;;N;;;;; +E01AF;VARIATION SELECTOR-192;Mn;0;NSM;;;;;N;;;;; +E01B0;VARIATION SELECTOR-193;Mn;0;NSM;;;;;N;;;;; +E01B1;VARIATION SELECTOR-194;Mn;0;NSM;;;;;N;;;;; +E01B2;VARIATION SELECTOR-195;Mn;0;NSM;;;;;N;;;;; +E01B3;VARIATION SELECTOR-196;Mn;0;NSM;;;;;N;;;;; +E01B4;VARIATION SELECTOR-197;Mn;0;NSM;;;;;N;;;;; +E01B5;VARIATION SELECTOR-198;Mn;0;NSM;;;;;N;;;;; +E01B6;VARIATION SELECTOR-199;Mn;0;NSM;;;;;N;;;;; +E01B7;VARIATION SELECTOR-200;Mn;0;NSM;;;;;N;;;;; +E01B8;VARIATION SELECTOR-201;Mn;0;NSM;;;;;N;;;;; +E01B9;VARIATION SELECTOR-202;Mn;0;NSM;;;;;N;;;;; +E01BA;VARIATION SELECTOR-203;Mn;0;NSM;;;;;N;;;;; +E01BB;VARIATION SELECTOR-204;Mn;0;NSM;;;;;N;;;;; +E01BC;VARIATION SELECTOR-205;Mn;0;NSM;;;;;N;;;;; +E01BD;VARIATION SELECTOR-206;Mn;0;NSM;;;;;N;;;;; +E01BE;VARIATION SELECTOR-207;Mn;0;NSM;;;;;N;;;;; +E01BF;VARIATION SELECTOR-208;Mn;0;NSM;;;;;N;;;;; +E01C0;VARIATION SELECTOR-209;Mn;0;NSM;;;;;N;;;;; +E01C1;VARIATION SELECTOR-210;Mn;0;NSM;;;;;N;;;;; +E01C2;VARIATION SELECTOR-211;Mn;0;NSM;;;;;N;;;;; +E01C3;VARIATION SELECTOR-212;Mn;0;NSM;;;;;N;;;;; +E01C4;VARIATION SELECTOR-213;Mn;0;NSM;;;;;N;;;;; +E01C5;VARIATION SELECTOR-214;Mn;0;NSM;;;;;N;;;;; +E01C6;VARIATION SELECTOR-215;Mn;0;NSM;;;;;N;;;;; +E01C7;VARIATION SELECTOR-216;Mn;0;NSM;;;;;N;;;;; +E01C8;VARIATION SELECTOR-217;Mn;0;NSM;;;;;N;;;;; +E01C9;VARIATION SELECTOR-218;Mn;0;NSM;;;;;N;;;;; +E01CA;VARIATION SELECTOR-219;Mn;0;NSM;;;;;N;;;;; +E01CB;VARIATION SELECTOR-220;Mn;0;NSM;;;;;N;;;;; +E01CC;VARIATION SELECTOR-221;Mn;0;NSM;;;;;N;;;;; +E01CD;VARIATION SELECTOR-222;Mn;0;NSM;;;;;N;;;;; +E01CE;VARIATION SELECTOR-223;Mn;0;NSM;;;;;N;;;;; +E01CF;VARIATION SELECTOR-224;Mn;0;NSM;;;;;N;;;;; +E01D0;VARIATION SELECTOR-225;Mn;0;NSM;;;;;N;;;;; +E01D1;VARIATION SELECTOR-226;Mn;0;NSM;;;;;N;;;;; +E01D2;VARIATION SELECTOR-227;Mn;0;NSM;;;;;N;;;;; +E01D3;VARIATION SELECTOR-228;Mn;0;NSM;;;;;N;;;;; +E01D4;VARIATION SELECTOR-229;Mn;0;NSM;;;;;N;;;;; +E01D5;VARIATION SELECTOR-230;Mn;0;NSM;;;;;N;;;;; +E01D6;VARIATION SELECTOR-231;Mn;0;NSM;;;;;N;;;;; +E01D7;VARIATION SELECTOR-232;Mn;0;NSM;;;;;N;;;;; +E01D8;VARIATION SELECTOR-233;Mn;0;NSM;;;;;N;;;;; +E01D9;VARIATION SELECTOR-234;Mn;0;NSM;;;;;N;;;;; +E01DA;VARIATION SELECTOR-235;Mn;0;NSM;;;;;N;;;;; +E01DB;VARIATION SELECTOR-236;Mn;0;NSM;;;;;N;;;;; +E01DC;VARIATION SELECTOR-237;Mn;0;NSM;;;;;N;;;;; +E01DD;VARIATION SELECTOR-238;Mn;0;NSM;;;;;N;;;;; +E01DE;VARIATION SELECTOR-239;Mn;0;NSM;;;;;N;;;;; +E01DF;VARIATION SELECTOR-240;Mn;0;NSM;;;;;N;;;;; +E01E0;VARIATION SELECTOR-241;Mn;0;NSM;;;;;N;;;;; +E01E1;VARIATION SELECTOR-242;Mn;0;NSM;;;;;N;;;;; +E01E2;VARIATION SELECTOR-243;Mn;0;NSM;;;;;N;;;;; +E01E3;VARIATION SELECTOR-244;Mn;0;NSM;;;;;N;;;;; +E01E4;VARIATION SELECTOR-245;Mn;0;NSM;;;;;N;;;;; +E01E5;VARIATION SELECTOR-246;Mn;0;NSM;;;;;N;;;;; +E01E6;VARIATION SELECTOR-247;Mn;0;NSM;;;;;N;;;;; +E01E7;VARIATION SELECTOR-248;Mn;0;NSM;;;;;N;;;;; +E01E8;VARIATION SELECTOR-249;Mn;0;NSM;;;;;N;;;;; +E01E9;VARIATION SELECTOR-250;Mn;0;NSM;;;;;N;;;;; +E01EA;VARIATION SELECTOR-251;Mn;0;NSM;;;;;N;;;;; +E01EB;VARIATION SELECTOR-252;Mn;0;NSM;;;;;N;;;;; +E01EC;VARIATION SELECTOR-253;Mn;0;NSM;;;;;N;;;;; +E01ED;VARIATION SELECTOR-254;Mn;0;NSM;;;;;N;;;;; +E01EE;VARIATION SELECTOR-255;Mn;0;NSM;;;;;N;;;;; +E01EF;VARIATION SELECTOR-256;Mn;0;NSM;;;;;N;;;;; +F0000;<Plane 15 Private Use, First>;Co;0;L;;;;;N;;;;; +FFFFD;<Plane 15 Private Use, Last>;Co;0;L;;;;;N;;;;; +100000;<Plane 16 Private Use, First>;Co;0;L;;;;;N;;;;; +10FFFD;<Plane 16 Private Use, Last>;Co;0;L;;;;;N;;;;; diff --git a/test/functional/fixtures/printargs-test.c b/test/functional/fixtures/printargs-test.c new file mode 100644 index 0000000000..be54605817 --- /dev/null +++ b/test/functional/fixtures/printargs-test.c @@ -0,0 +1,12 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + +#include <stdio.h> + +int main(int argc, char **argv) +{ + for (int i=1; i<argc; i++) { + printf("arg%d=%s;", i, argv[i]); + } + return 0; +} diff --git a/test/functional/fixtures/shell-test.c b/test/functional/fixtures/shell-test.c index d9ec254aff..8dbec2aaee 100644 --- a/test/functional/fixtures/shell-test.c +++ b/test/functional/fixtures/shell-test.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #include <stdio.h> #include <string.h> #include <stdint.h> @@ -12,8 +15,12 @@ static void help(void) puts(" shell-test"); puts(" shell-test EXE"); puts(" Prints \"ready $ \" to stderr."); + puts(" shell-test -t {prompt text}"); + puts(" Prints \"{prompt text} $ \" to stderr."); puts(" shell-test EXE \"prog args...\""); puts(" Prints \"ready $ prog args...\\n\" to stderr."); + puts(" shell-test -t {prompt text} EXE \"prog args...\""); + puts(" Prints \"{prompt text} $ progs args...\" to stderr."); puts(" shell-test REP {byte} \"line line line\""); puts(" Prints \"{lnr}: line line line\\n\" to stdout {byte} times."); puts(" I.e. for `shell-test REP ab \"test\"'"); @@ -30,7 +37,17 @@ int main(int argc, char **argv) } if (argc >= 2) { - if (strcmp(argv[1], "EXE") == 0) { + if (strcmp(argv[1], "-t") == 0) { + if (argc < 3) { + fprintf(stderr,"Missing prompt text for -t option\n"); + return 5; + } else { + fprintf(stderr, "%s $ ", argv[2]); + if (argc >= 5 && (strcmp(argv[3], "EXE") == 0)) { + fprintf(stderr, "%s\n", argv[4]); + } + } + } else if (strcmp(argv[1], "EXE") == 0) { fprintf(stderr, "ready $ "); if (argc >= 3) { fprintf(stderr, "%s\n", argv[2]); diff --git a/test/functional/fixtures/tty-test.c b/test/functional/fixtures/tty-test.c index 778e7f3cd3..edcbe23f86 100644 --- a/test/functional/fixtures/tty-test.c +++ b/test/functional/fixtures/tty-test.c @@ -1,40 +1,49 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <uv.h> +#ifdef _WIN32 +# include <windows.h> +#else +# include <unistd.h> +#endif + +// -V:STRUCT_CAST:641 +#define STRUCT_CAST(Type, obj) ((Type *)(obj)) +#define is_terminal(stream) (uv_guess_handle(fileno(stream)) == UV_TTY) +#define BUF_SIZE 0xfff +#define CTRL_C 0x03 uv_tty_t tty; +uv_tty_t tty_out; -#ifdef _WIN32 -#include <windows.h> bool owns_tty(void) { - HWND consoleWnd = GetConsoleWindow(); - DWORD dwProcessId; - GetWindowThreadProcessId(consoleWnd, &dwProcessId); - return GetCurrentProcessId() == dwProcessId; -} +#ifdef _WIN32 + // XXX: We need to make proper detect owns tty + // HWND consoleWnd = GetConsoleWindow(); + // DWORD dwProcessId; + // GetWindowThreadProcessId(consoleWnd, &dwProcessId); + // return GetCurrentProcessId() == dwProcessId; + return true; #else -#include <unistd.h> -bool owns_tty(void) -{ return getsid(0) == getpid(); -} #endif +} -#define is_terminal(stream) (uv_guess_handle(fileno(stream)) == UV_TTY) -#define BUF_SIZE 0xfff - -static void walk_cb(uv_handle_t *handle, void *arg) { +static void walk_cb(uv_handle_t *handle, void *arg) +{ if (!uv_is_closing(handle)) { uv_close(handle, NULL); } } -#ifndef WIN32 static void sig_handler(int signum) { - switch(signum) { + switch (signum) { case SIGWINCH: { int width, height; uv_tty_get_winsize(&tty, &width, &height); @@ -48,15 +57,15 @@ static void sig_handler(int signum) return; } } -#endif -// static void sigwinch_cb(uv_signal_t *handle, int signum) -// { -// int width, height; -// uv_tty_t *tty = handle->data; -// uv_tty_get_winsize(tty, &width, &height); -// fprintf(stderr, "rows: %d, cols: %d\n", height, width); -// } +#ifdef WIN32 +static void sigwinch_cb(uv_signal_t *handle, int signum) +{ + int width, height; + uv_tty_get_winsize(&tty_out, &width, &height); + fprintf(stderr, "rows: %d, cols: %d\n", height, width); +} +#endif static void alloc_cb(uv_handle_t *handle, size_t suggested, uv_buf_t *buf) { @@ -74,7 +83,7 @@ static void read_cb(uv_stream_t *stream, ssize_t cnt, const uv_buf_t *buf) int *interrupted = stream->data; for (int i = 0; i < cnt; i++) { - if (buf->base[i] == 3) { + if (buf->base[i] == CTRL_C) { (*interrupted)++; } } @@ -82,12 +91,14 @@ static void read_cb(uv_stream_t *stream, ssize_t cnt, const uv_buf_t *buf) uv_loop_t write_loop; uv_loop_init(&write_loop); uv_tty_t out; - uv_tty_init(&write_loop, &out, 1, 0); + uv_tty_init(&write_loop, &out, fileno(stdout), 0); + uv_write_t req; uv_buf_t b = {.base = buf->base, .len = (size_t)cnt}; - uv_write(&req, (uv_stream_t *)&out, &b, 1, NULL); + uv_write(&req, STRUCT_CAST(uv_stream_t, &out), &b, 1, NULL); uv_run(&write_loop, UV_RUN_DEFAULT); - uv_close((uv_handle_t *)&out, NULL); + + uv_close(STRUCT_CAST(uv_handle_t, &out), NULL); uv_run(&write_loop, UV_RUN_DEFAULT); if (uv_loop_close(&write_loop)) { abort(); @@ -131,7 +142,7 @@ int main(int argc, char **argv) if (argc > 1) { int count = atoi(argv[1]); - for (int i = 0; i < count; ++i) { + for (int i = 0; i < count; i++) { printf("line%d\n", i); } fflush(stdout); @@ -142,11 +153,17 @@ int main(int argc, char **argv) uv_prepare_t prepare; uv_prepare_init(uv_default_loop(), &prepare); uv_prepare_start(&prepare, prepare_cb); - // uv_tty_t tty; +#ifndef WIN32 uv_tty_init(uv_default_loop(), &tty, fileno(stderr), 1); +#else + uv_tty_init(uv_default_loop(), &tty, fileno(stdin), 1); + uv_tty_init(uv_default_loop(), &tty_out, fileno(stdout), 0); + int width, height; + uv_tty_get_winsize(&tty_out, &width, &height); +#endif uv_tty_set_mode(&tty, UV_TTY_MODE_RAW); tty.data = &interrupted; - uv_read_start((uv_stream_t *)&tty, alloc_cb, read_cb); + uv_read_start(STRUCT_CAST(uv_stream_t, &tty), alloc_cb, read_cb); #ifndef WIN32 struct sigaction sa; sigemptyset(&sa.sa_mask); @@ -154,15 +171,17 @@ int main(int argc, char **argv) sa.sa_handler = sig_handler; sigaction(SIGHUP, &sa, NULL); sigaction(SIGWINCH, &sa, NULL); - // uv_signal_t sigwinch_watcher; - // uv_signal_init(uv_default_loop(), &sigwinch_watcher); - // sigwinch_watcher.data = &tty; - // uv_signal_start(&sigwinch_watcher, sigwinch_cb, SIGWINCH); +#else + uv_signal_t sigwinch_watcher; + uv_signal_init(uv_default_loop(), &sigwinch_watcher); + uv_signal_start(&sigwinch_watcher, sigwinch_cb, SIGWINCH); #endif uv_run(uv_default_loop(), UV_RUN_DEFAULT); +#ifndef WIN32 // XXX: Without this the SIGHUP handler is skipped on some systems. sleep(100); +#endif return 0; } diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua index 5eec3afe65..848f1ef477 100644 --- a/test/functional/helpers.lua +++ b/test/functional/helpers.lua @@ -8,35 +8,39 @@ local Session = require('nvim.session') local TcpStream = require('nvim.tcp_stream') local SocketStream = require('nvim.socket_stream') local ChildProcessStream = require('nvim.child_process_stream') +local Paths = require('test.config.paths') +local check_cores = global_helpers.check_cores local check_logs = global_helpers.check_logs local neq = global_helpers.neq local eq = global_helpers.eq local ok = global_helpers.ok +local map = global_helpers.map +local filter = global_helpers.filter +local dedent = global_helpers.dedent local start_dir = lfs.currentdir() -local nvim_prog = os.getenv('NVIM_PROG') or 'build/bin/nvim' +-- XXX: NVIM_PROG takes precedence, QuickBuild sets it. +local nvim_prog = ( + os.getenv('NVIM_PROG') + or os.getenv('NVIM_PRG') + or Paths.test_build_dir .. '/bin/nvim' +) +-- Default settings for the test session. +local nvim_set = 'set shortmess+=I background=light noswapfile noautoindent' + ..' laststatus=1 undodir=. directory=. viewdir=. backupdir=.' + ..' belloff= noshowcmd noruler nomore' local nvim_argv = {nvim_prog, '-u', 'NONE', '-i', 'NONE', '-N', - '--cmd', 'set shortmess+=I background=light noswapfile noautoindent laststatus=1 undodir=. directory=. viewdir=. backupdir=.', - '--embed'} - -local mpack = require('mpack') - -local tmpname = global_helpers.tmpname -local uname = global_helpers.uname - --- Formulate a path to the directory containing nvim. We use this to --- help run test executables. It helps to keep the tests working, even --- when the build is not in the default location. + '--cmd', nvim_set, '--embed'} +-- Directory containing nvim. local nvim_dir = nvim_prog:gsub("[/\\][^/\\]+$", "") if nvim_dir == nvim_prog then - nvim_dir = "." + nvim_dir = "." end --- Nvim "Unit Under Test" http://en.wikipedia.org/wiki/Device_under_test -local NvimUUT = {} -NvimUUT.__index = NvimUUT - +local mpack = require('mpack') +local tmpname = global_helpers.tmpname +local uname = global_helpers.uname local prepend_argv if os.getenv('VALGRIND') then @@ -72,8 +76,8 @@ end local session, loop_running, last_error -local function set_session(s) - if session then +local function set_session(s, keep) + if session and not keep then session:close() end session = s @@ -169,6 +173,10 @@ local os_name = (function() end) end)() +local function iswin() + return package.config:sub(1,1) == '\\' +end + -- Executes a VimL function. -- Fails on VimL error, but does not update v:errmsg. local function nvim_call(name, ...) @@ -184,28 +192,6 @@ local function nvim_feed(input) end end -local function dedent(str) - -- find minimum common indent across lines - local indent = nil - for line in str:gmatch('[^\n]+') do - local line_indent = line:match('^%s+') or '' - if indent == nil or #line_indent < #indent then - indent = line_indent - end - end - if #indent == 0 then - -- no minimum common indent - return str - end - -- create a pattern for the indent - indent = indent:gsub('%s', '[ \t]') - -- strip it from the first line - str = str:gsub('^'..indent, '') - -- strip it from the remaining lines - str = str:gsub('[\n]'..indent, '\n') - return str -end - local function feed(...) for _, v in ipairs({...}) do nvim_feed(dedent(v)) @@ -260,12 +246,13 @@ local function retry(max, max_ms, fn) return result end if (max and tries >= max) or (luv.now() - start_time > timeout) then - break + if type(result) == "string" then + result = "\nretry() attempts: "..tostring(tries).."\n"..result + end + error(result) end tries = tries + 1 end - -- Do not use pcall() for the final attempt, let the failure bubble up. - return fn() end local function clear(...) @@ -288,7 +275,9 @@ local function clear(...) 'NVIM_LOG_FILE', 'NVIM_RPLUGIN_MANIFEST', }) do - env_tbl[k] = os.getenv(k) + if not env_tbl[k] then + env_tbl[k] = os.getenv(k) + end end env = {} for k, v in pairs(env_tbl) do @@ -316,7 +305,7 @@ end -- Executes an ex-command by user input. Because nvim_input() is used, VimL -- errors will not manifest as client (lua) errors. Use command() for that. -local function execute(...) +local function feed_command(...) for _, v in ipairs({...}) do if v:sub(1, 1) ~= '/' then -- not a search command, prefix with colon @@ -330,7 +319,14 @@ end -- Dedent the given text and write it to the file name. local function write_file(name, text, dont_dedent) local file = io.open(name, 'w') - if not dont_dedent then + if type(text) == 'table' then + -- Byte blob + local bytes = text + text = '' + for _, char in ipairs(bytes) do + text = ('%s%c'):format(text, char) + end + elseif not dont_dedent then text = dedent(text) end file:write(text) @@ -338,14 +334,44 @@ local function write_file(name, text, dont_dedent) file:close() end +local function read_file(name) + local file = io.open(name, 'r') + if not file then + return nil + end + local ret = file:read('*a') + file:close() + return ret +end + +local sourced_fnames = {} local function source(code) local fname = tmpname() write_file(fname, code) nvim_command('source '..fname) - os.remove(fname) + -- DO NOT REMOVE FILE HERE. + -- do_source() has a habit of checking whether files are โsameโ by using inode + -- and device IDs. If you run two source() calls in quick succession there is + -- a good chance that underlying filesystem will reuse the inode, making files + -- appear as โsymlinksโ to do_source when it checks FileIDs. With current + -- setup linux machines (both QB, travis and mine(ZyX-I) with XFS) do reuse + -- inodes, Mac OS machines (again, both QB and travis) do not. + -- + -- Files appearing as โsymlinksโ mean that both the first and the second + -- source() calls will use same SID, which may fail some tests which check for + -- exact numbers after `<SNR>` in e.g. function names. + sourced_fnames[#sourced_fnames + 1] = fname return fname end +local function set_shell_powershell() + source([[ + set shell=powershell shellquote=\" shellpipe=\| shellredir=> + set shellcmdflag=\ -NoLogo\ -NoProfile\ -ExecutionPolicy\ RemoteSigned\ -Command + let &shellxquote=' ' + ]]) +end + local function nvim(method, ...) return request('nvim_'..method, ...) end @@ -378,14 +404,21 @@ local function curbuf(method, ...) end local function wait() - -- Execute 'vim_eval' (a deferred function) to block + -- Execute 'nvim_eval' (a deferred function) to block -- until all pending input is processed. - session:request('vim_eval', '1') + session:request('nvim_eval', '1') end -- sleeps the test runner (_not_ the nvim instance) local function sleep(ms) - run(nil, nil, nil, ms) + local function notification_cb(method, _) + if method == "redraw" then + error("Screen is attached; use screen:sleep() instead.") + end + return true + end + + run(nil, notification_cb, nil, ms) end local function curbuf_contents() @@ -411,23 +444,34 @@ local function expect(contents) return eq(dedent(contents), curbuf_contents()) end +local function expect_any(contents) + contents = dedent(contents) + return ok(nil ~= string.find(curbuf_contents(), contents, 1, true)) +end + local function do_rmdir(path) if lfs.attributes(path, 'mode') ~= 'directory' then - return nil + return -- Don't complain. end for file in lfs.dir(path) do if file ~= '.' and file ~= '..' then local abspath = path..'/'..file if lfs.attributes(abspath, 'mode') == 'directory' then - local ret = do_rmdir(abspath) -- recurse - if not ret then - return nil - end + do_rmdir(abspath) -- recurse else local ret, err = os.remove(abspath) if not ret then - error('os.remove: '..err) - return nil + if not session then + error('os.remove: '..err) + else + -- Try Nvim delete(): it handles `readonly` attribute on Windows, + -- and avoids Lua cross-version/platform incompatibilities. + if -1 == nvim_call('delete', abspath) then + local hint = (os_name() == 'windows' + and ' (hint: try :%bwipeout! before rmdir())' or '') + error('delete() failed'..hint..': '..abspath) + end + end end end end @@ -436,7 +480,6 @@ local function do_rmdir(path) if not ret then error('lfs.rmdir('..path..'): '..err) end - return ret end local function rmdir(path) @@ -468,17 +511,6 @@ local exc_exec = function(cmd) return ret end -local function redir_exec(cmd) - nvim_command(([[ - redir => g:__output - silent! execute "%s" - redir END - ]]):format(cmd:gsub('\n', '\\n'):gsub('[\\"]', '\\%0'))) - local ret = nvim_eval('get(g:, "__output", 0)') - nvim_command('unlet! g:__output') - return ret -end - local function create_callindex(func) local table = {} setmetatable(table, { @@ -494,7 +526,6 @@ end -- Helper to skip tests. Returns true in Windows systems. -- pending_fn is pending() from busted local function pending_win32(pending_fn) - clear() if uname() == 'Windows' then if pending_fn ~= nil then pending_fn('FIXME: Windows', function() end) @@ -521,6 +552,14 @@ local function skip_fragile(pending_fn, cond) return false end +local function meth_pcall(...) + local ret = {pcall(...)} + if type(ret[2]) == 'string' then + ret[2] = ret[2]:gsub('^[^:]+:%d+: ', '') + end + return ret +end + local funcs = create_callindex(nvim_call) local meths = create_callindex(nvim) local uimeths = create_callindex(ui) @@ -531,66 +570,134 @@ local curbufmeths = create_callindex(curbuf) local curwinmeths = create_callindex(curwin) local curtabmeths = create_callindex(curtab) +local function redir_exec(cmd) + meths.set_var('__redir_exec_cmd', cmd) + nvim_command([[ + redir => g:__redir_exec_output + silent! execute g:__redir_exec_cmd + redir END + ]]) + local ret = meths.get_var('__redir_exec_output') + meths.del_var('__redir_exec_output') + meths.del_var('__redir_exec_cmd') + return ret +end + +local function get_pathsep() + return funcs.fnamemodify('.', ':p'):sub(-1) +end + +local function missing_provider(provider) + if provider == 'ruby' then + local prog = funcs['provider#' .. provider .. '#Detect']() + return prog == '' and (provider .. ' not detected') or false + elseif provider == 'python' or provider == 'python3' then + local py_major_version = (provider == 'python3' and 3 or 2) + local errors = funcs['provider#pythonx#Detect'](py_major_version)[2] + return errors ~= '' and errors or false + else + assert(false, 'Unknown provider: ' .. provider) + end +end + +local function alter_slashes(obj) + if not iswin() then + return obj + end + if type(obj) == 'string' then + local ret = obj:gsub('/', '\\') + return ret + elseif type(obj) == 'table' then + local ret = {} + for k, v in pairs(obj) do + ret[k] = alter_slashes(v) + end + return ret + else + assert(false, 'Could only alter slashes for tables of strings and strings') + end +end + +local module = { + prepend_argv = prepend_argv, + clear = clear, + connect = connect, + retry = retry, + spawn = spawn, + dedent = dedent, + source = source, + rawfeed = rawfeed, + insert = insert, + iswin = iswin, + feed = feed, + feed_command = feed_command, + eval = nvim_eval, + call = nvim_call, + command = nvim_command, + request = request, + next_message = next_message, + run = run, + stop = stop, + eq = eq, + neq = neq, + expect = expect, + expect_any = expect_any, + ok = ok, + map = map, + filter = filter, + nvim = nvim, + nvim_async = nvim_async, + nvim_prog = nvim_prog, + nvim_argv = nvim_argv, + nvim_set = nvim_set, + nvim_dir = nvim_dir, + buffer = buffer, + window = window, + tabpage = tabpage, + curbuf = curbuf, + curwin = curwin, + curtab = curtab, + curbuf_contents = curbuf_contents, + wait = wait, + sleep = sleep, + set_session = set_session, + write_file = write_file, + read_file = read_file, + os_name = os_name, + rmdir = rmdir, + mkdir = lfs.mkdir, + exc_exec = exc_exec, + redir_exec = redir_exec, + merge_args = merge_args, + funcs = funcs, + meths = meths, + bufmeths = bufmeths, + winmeths = winmeths, + tabmeths = tabmeths, + uimeths = uimeths, + curbufmeths = curbufmeths, + curwinmeths = curwinmeths, + curtabmeths = curtabmeths, + pending_win32 = pending_win32, + skip_fragile = skip_fragile, + set_shell_powershell = set_shell_powershell, + tmpname = tmpname, + meth_pcall = meth_pcall, + NIL = mpack.NIL, + get_pathsep = get_pathsep, + missing_provider = missing_provider, + alter_slashes = alter_slashes, +} + return function(after_each) if after_each then - after_each(check_logs) - end - return { - prepend_argv = prepend_argv, - clear = clear, - connect = connect, - retry = retry, - spawn = spawn, - dedent = dedent, - source = source, - rawfeed = rawfeed, - insert = insert, - feed = feed, - execute = execute, - eval = nvim_eval, - call = nvim_call, - command = nvim_command, - request = request, - next_message = next_message, - run = run, - stop = stop, - eq = eq, - neq = neq, - expect = expect, - ok = ok, - nvim = nvim, - nvim_async = nvim_async, - nvim_prog = nvim_prog, - nvim_dir = nvim_dir, - buffer = buffer, - window = window, - tabpage = tabpage, - curbuf = curbuf, - curwin = curwin, - curtab = curtab, - curbuf_contents = curbuf_contents, - wait = wait, - sleep = sleep, - set_session = set_session, - write_file = write_file, - os_name = os_name, - rmdir = rmdir, - mkdir = lfs.mkdir, - exc_exec = exc_exec, - redir_exec = redir_exec, - merge_args = merge_args, - funcs = funcs, - meths = meths, - bufmeths = bufmeths, - winmeths = winmeths, - tabmeths = tabmeths, - uimeths = uimeths, - curbufmeths = curbufmeths, - curwinmeths = curwinmeths, - curtabmeths = curtabmeths, - pending_win32 = pending_win32, - skip_fragile = skip_fragile, - tmpname = tmpname, - NIL = mpack.NIL, - } + after_each(function() + for _, fname in ipairs(sourced_fnames) do + os.remove(fname) + end + check_logs() + check_cores('build/bin/nvim') + end) + end + return module end diff --git a/test/functional/insert/ctrl_o_spec.lua b/test/functional/insert/ctrl_o_spec.lua new file mode 100644 index 0000000000..fbdff8a3a0 --- /dev/null +++ b/test/functional/insert/ctrl_o_spec.lua @@ -0,0 +1,43 @@ +local helpers = require('test.functional.helpers')(after_each) +local clear = helpers.clear +local eq = helpers.eq +local eval = helpers.eval +local expect = helpers.expect +local feed = helpers.feed +local insert = helpers.insert + +describe('insert-mode Ctrl-O', function() + before_each(clear) + + it('enters command mode for one command', function() + feed('ihello world<C-o>') + feed(':let ctrlo = "test"<CR>') + feed('iii') + expect('hello worldiii') + eq(1, eval('ctrlo ==# "test"')) + end) + + it('re-enters insert mode at the end of the line when running startinsert', function() + -- #6962 + feed('ihello world<C-o>') + feed(':startinsert<CR>') + feed('iii') + expect('hello worldiii') + end) + + it('re-enters insert mode at the beginning of the line when running startinsert', function() + insert('hello world') + feed('0<C-o>') + feed(':startinsert<CR>') + feed('aaa') + expect('aaahello world') + end) + + it('re-enters insert mode in the middle of the line when running startinsert', function() + insert('hello world') + feed('bi<C-o>') + feed(':startinsert<CR>') + feed('ooo') + expect('hello oooworld') + end) +end) diff --git a/test/functional/insert/ctrl_r_spec.lua b/test/functional/insert/ctrl_r_spec.lua new file mode 100644 index 0000000000..adc3c4b406 --- /dev/null +++ b/test/functional/insert/ctrl_r_spec.lua @@ -0,0 +1,19 @@ +local helpers = require('test.functional.helpers')(after_each) +local clear, feed = helpers.clear, helpers.feed +local expect, command = helpers.expect, helpers.command + +describe('insert-mode Ctrl-R', function() + before_each(clear) + + it('works', function() + command("let @@ = 'test'") + feed('i<C-r>"') + expect('test') + end) + + it('works with multi-byte text', function() + command("let @@ = 'pรฅskรคgg'") + feed('i<C-r>"') + expect('pรฅskรคgg') + end) +end) diff --git a/test/functional/insert/last_inserted_spec.lua b/test/functional/insert/last_inserted_spec.lua new file mode 100644 index 0000000000..dce23a3790 --- /dev/null +++ b/test/functional/insert/last_inserted_spec.lua @@ -0,0 +1,22 @@ +local helpers = require('test.functional.helpers')(after_each) +local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert +local expect = helpers.expect + +clear() + +describe('insert-mode', function() + it('CTRL-@ inserts last-inserted text, leaves insert-mode', function() + insert('hello') + feed('i<C-@>x') + expect('hellhello') + end) + -- C-Space is the same as C-@ + it('CTRL-SPC inserts last-inserted text, leaves insert-mode', function() + feed('i<C-Space>x') + expect('hellhellhello') + end) + it('CTRL-A inserts last inserted text', function() + feed('i<C-A>x') + expect('hellhellhellhelloxo') + end) +end) diff --git a/test/functional/legacy/002_filename_recognition_spec.lua b/test/functional/legacy/002_filename_recognition_spec.lua index 5a833281e7..26a62d92fe 100644 --- a/test/functional/legacy/002_filename_recognition_spec.lua +++ b/test/functional/legacy/002_filename_recognition_spec.lua @@ -3,7 +3,7 @@ local helpers = require('test.functional.helpers')(after_each) local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local execute, expect = helpers.execute, helpers.expect +local feed_command, expect = helpers.feed_command, helpers.expect describe('filename recognition', function() setup(clear) @@ -17,17 +17,17 @@ describe('filename recognition', function() fourth test for URL:\\machine.name\tmp\vimtest2d, and other text]]) -- Go to the first URL and append it to the beginning - execute('/^first', '/tmp', 'call append(0, expand("<cfile>"))') + feed_command('/^first', '/tmp', 'call append(0, expand("<cfile>"))') -- Repeat for the second URL -- this time, navigate to the word "URL" instead of "tmp" - execute('/^second', '/URL', 'call append(1, expand("<cfile>"))') + feed_command('/^second', '/URL', 'call append(1, expand("<cfile>"))') -- Repeat for the remaining URLs. This time, the 'isfname' option must be -- set to allow '\' in filenames - execute('set isf=@,48-57,/,.,-,_,+,,,$,:,~,\\') - execute('/^third', '/name', 'call append(2, expand("<cfile>"))') - execute('/^fourth', '/URL', 'call append(3, expand("<cfile>"))') + feed_command('set isf=@,48-57,/,.,-,_,+,,,$,:,~,\\') + feed_command('/^third', '/name', 'call append(2, expand("<cfile>"))') + feed_command('/^fourth', '/URL', 'call append(3, expand("<cfile>"))') -- Delete the initial text, which now starts at line 5 feed('5GdG') diff --git a/test/functional/legacy/003_cindent_spec.lua b/test/functional/legacy/003_cindent_spec.lua index 83388bd1eb..0cc4d298b7 100644 --- a/test/functional/legacy/003_cindent_spec.lua +++ b/test/functional/legacy/003_cindent_spec.lua @@ -5,14 +5,14 @@ local helpers = require('test.functional.helpers')(after_each) local feed, insert = helpers.feed, helpers.insert -local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect +local clear, feed_command, expect = helpers.clear, helpers.feed_command, helpers.expect -- Inserts text as usual, and additionally positions the cursor on line 1 and -- sets 'cindent' and tab settings. (In the original "test3.in" the modeline at -- the top of the file takes care of this.) local function insert_(content) insert(content) - execute('1', 'set cin ts=4 sw=4') + feed_command('1', 'set cin ts=4 sw=4') end describe('cindent', function() @@ -20,21 +20,21 @@ describe('cindent', function() it('1 is working', function() insert_([=[ - + /* start of AUTO matically checked vim: set ts=4 : */ { if (test) cmd1; cmd2; } - + { if (test) cmd1; else cmd2; } - + { if (test) { @@ -42,7 +42,7 @@ describe('cindent', function() cmd2; } } - + { if (test) { @@ -50,14 +50,14 @@ describe('cindent', function() else } } - + { while (this) if (test) cmd1; cmd2; } - + { while (this) if (test) @@ -65,25 +65,25 @@ describe('cindent', function() else cmd2; } - + { if (test) { cmd; } - + if (test) cmd; } - + { if (test) { cmd; } - + if (test) cmd; } - + { cmd1; for (blah) @@ -92,7 +92,7 @@ describe('cindent', function() cmd2; cmd3; } - + { cmd1; for (blah) @@ -100,7 +100,7 @@ describe('cindent', function() if (test) cmd2; cmd3; - + if (test) { cmd1; @@ -108,23 +108,23 @@ describe('cindent', function() cmd3; } } - - + + /* Test for 'cindent' do/while mixed with if/else: */ - + { do if (asdf) asdfasd; while (cond); - + do if (asdf) while (asdf) asdf; while (asdf); } - + /* Test for 'cindent' with two ) on a continuation line */ { if (asdfasdf;asldkfj asdlkfj as;ldkfj sal;d @@ -132,14 +132,14 @@ describe('cindent', function() al;sdjfka ;slkdf ) sa;ldkjfsa dlk;) line up here; } - - + + /* C++ tests: */ - + // foo() these three lines should remain in column 0 // { // } - + /* Test for continuation and unterminated lines: */ { i = 99 + 14325 + @@ -151,12 +151,12 @@ describe('cindent', function() 1234; c = 1; } - + /* testje for indent with empty line - + here */ - + { if (testing && not a joke || @@ -171,8 +171,8 @@ describe('cindent', function() line up here)) hay; } - - + + { switch (c) { @@ -191,7 +191,7 @@ describe('cindent', function() testing; } } - + { if (cond) { foo; @@ -201,7 +201,7 @@ describe('cindent', function() bar; } } - + { if (alskdfj ;alsdkfjal;skdjf (;sadlkfsa ;dlkf j;alksdfj ;alskdjf alsdkfj (asldk;fj @@ -210,7 +210,7 @@ describe('cindent', function() asdfasdf;))) asdfasdf; } - + int func(a, b) int a; @@ -223,7 +223,7 @@ describe('cindent', function() (c2 || c3) ) } - + { while (asd) { @@ -245,13 +245,13 @@ describe('cindent', function() asdf; } } - + { s = "/*"; b = ';' s = "/*"; b = ';'; a = b; } - + { switch (a) { @@ -285,7 +285,7 @@ describe('cindent', function() break; } } - + { if (!(vim_strchr(p_cpo, CPO_BUFOPTGLOB) != NULL && entering) && (bp_to->b_p_initialized || @@ -297,57 +297,57 @@ describe('cindent', function() asdf = asdf ? asdf: asdf; } - + /* Special Comments : This function has the added complexity (compared */ /* : to addtolist) of having to check for a detail */ /* : texture and add that to the list first. */ - + char *(array[100]) = { "testje", "foo", "bar", } - + enum soppie { yes = 0, no, maybe }; - + typedef enum soppie { yes = 0, no, maybe }; - + static enum { yes = 0, no, maybe } soppie; - + public static enum { yes = 0, no, maybe } soppie; - + static private enum { yes = 0, no, maybe } soppie; - + { int a, b; } - + { struct Type { @@ -360,7 +360,7 @@ describe('cindent', function() 2, "two", 3, "three" }; - + float matrix[3][3] = { { @@ -380,14 +380,14 @@ describe('cindent', function() } }; } - + { /* blah ( blah */ /* where does this go? */ - + /* blah ( blah */ cmd; - + func(arg1, /* comment */ arg2); @@ -398,7 +398,7 @@ describe('cindent', function() c; /* Hey, NOW it indents?! */ } } - + { func(arg1, arg2, @@ -406,7 +406,7 @@ describe('cindent', function() /* Hey, what am I doing here? Is this coz of the ","? */ } } - + main () { if (cond) @@ -420,7 +420,7 @@ describe('cindent', function() a = d; return; } - + { case 2: if (asdf && asdfasdf) @@ -431,42 +431,42 @@ describe('cindent', function() a = 9; case 4: x = 1; y = 2; - + label: if (asdf) here; - + label: if (asdf && asdfasdf) { } - + label: if (asdf && asdfasdf) { there; } - + label: if (asdf && asdfasdf) there; } - + { /* hello with ":set comments= cino=c5" */ - + /* hello with ":set comments= cino=" */ } - - + + { if (a < b) { a = a + 1; } else a = a + 2; - + if (a) do { testing; @@ -474,7 +474,7 @@ describe('cindent', function() a = b + 1; asdfasdf } - + { for ( int i = 0; i < 10; i++ ) @@ -482,13 +482,13 @@ describe('cindent', function() } i = 0; } - + class bob { int foo() {return 1;} int bar; } - + main() { while(1) @@ -501,32 +501,32 @@ describe('cindent', function() } misplacedline; } - + { if (clipboard.state == SELECT_DONE && ((row == clipboard.start.lnum && col >= clipboard.start.col) || row > clipboard.start.lnum)) } - + { if (1) {i += 4;} where_am_i; return 0; } - + { { } // sdf(asdf if (asdf) asd; } - + { label1: label2: } - + { int fooRet = foo(pBar1, false /*fKB*/, true /*fPTB*/, 3 /*nT*/, false /*fDF*/); @@ -538,12 +538,12 @@ describe('cindent', function() } } } - + { f1(/*comment*/); f2(); } - + { do { if (foo) { @@ -552,25 +552,25 @@ describe('cindent', function() } while (foo); foo(); // was wrong } - + int x; // no extra indent because of the ; void func() { } - + char *tab[] = {"aaa", "};", /* }; */ NULL} int indented; {} - + char *a[] = {"aaa", "bbb", "ccc", NULL}; // here - + char *tab[] = {"aaa", "xx", /* xx */}; /* asdf */ int not_indented; - + { do { switch (bla) @@ -581,23 +581,23 @@ describe('cindent', function() } while (boo); wrong; } - + int foo, bar; int foo; - + #if defined(foo) \ && defined(bar) char * xx = "asdf\ foo\ bor"; int x; - + char *foo = "asdf\ asdf\ asdf", *bar; - + void f() { #if defined(foo) \ @@ -616,19 +616,19 @@ describe('cindent', function() #endif } #endif - + int y; // comment // comment - + // comment - + { Constructor(int a, int b ) : BaseClass(a) { } } - + void foo() { char one, @@ -645,13 +645,13 @@ describe('cindent', function() kees, jan; } - + { t(int f, int d); // ) d(); } - + Constructor::Constructor(int a, int b ) : @@ -661,33 +661,33 @@ describe('cindent', function() mMember(b), { } - + Constructor::Constructor(int a, int b ) : BaseClass(a) { } - + Constructor::Constructor(int a, int b ) /*x*/ : /*x*/ BaseClass(a), member(b) { } - + A::A(int a, int b) : aa(a), bb(b), cc(c) { } - + class CAbc : public BaseClass1, protected BaseClass2 { int Test() { return FALSE; } int Test1() { return TRUE; } - + CAbc(int a, int b ) : BaseClass(a) { @@ -696,24 +696,24 @@ describe('cindent', function() case abc: asdf(); break; - + case 999: baer(); break; } } - + public: // <-- this was incoreectly indented before!! void testfall(); protected: void testfall(); }; - + class CAbc : public BaseClass1, protected BaseClass2 { }; - + static struct { int a; @@ -729,7 +729,7 @@ describe('cindent', function() 456 } }; - + static struct { int a; @@ -739,7 +739,7 @@ describe('cindent', function() { 123, 456 }, { 123, 456 } }; - + void asdf() /* ind_maxparen may cause trouble here */ { if ((0 @@ -769,17 +769,17 @@ describe('cindent', function() && 1 && 1)) break; } - + foo() { a = cond ? foo() : asdf + asdf; - + a = cond ? foo() : asdf + asdf; } - + int main(void) { if (a) @@ -788,7 +788,7 @@ describe('cindent', function() else 3; next_line_of_code(); } - + barry() { Foo::Foo (int one, @@ -796,14 +796,14 @@ describe('cindent', function() : something(4) {} } - + barry() { Foo::Foo (int one, int two) : something(4) {} } - + Constructor::Constructor(int a, int b ) : @@ -822,7 +822,7 @@ describe('cindent', function() && lele); lulu; } - + int main () { switch (c) @@ -832,13 +832,13 @@ describe('cindent', function() } } } - + main() { (void) MyFancyFuasdfadsfnction( argument); } - + main() { char foo[] = "/*"; @@ -846,7 +846,7 @@ describe('cindent', function() df */ hello } - + /* valid namespaces with normal indent */ namespace { @@ -885,7 +885,7 @@ describe('cindent', function() 22222222222222222; } } - + /* invalid namespaces use block indent */ namespace test test2 { 111111111111111111111; @@ -925,7 +925,7 @@ describe('cindent', function() } )foo"; } - + { int a[4] = { [0] = 0, @@ -934,12 +934,12 @@ describe('cindent', function() [3] = 3, }; } - + { a = b[2] + 3; } - + { if (1) /* aaaaa @@ -947,7 +947,7 @@ describe('cindent', function() */ a = 1; } - + void func() { switch (foo) @@ -974,29 +974,29 @@ describe('cindent', function() break; } } - + /* end of AUTO */ ]=]) - execute('/start of AUTO') + feed_command('/start of AUTO') feed('=/end of AUTO<cr>') expect([=[ - + /* start of AUTO matically checked vim: set ts=4 : */ { if (test) cmd1; cmd2; } - + { if (test) cmd1; else cmd2; } - + { if (test) { @@ -1004,7 +1004,7 @@ describe('cindent', function() cmd2; } } - + { if (test) { @@ -1012,14 +1012,14 @@ describe('cindent', function() else } } - + { while (this) if (test) cmd1; cmd2; } - + { while (this) if (test) @@ -1027,25 +1027,25 @@ describe('cindent', function() else cmd2; } - + { if (test) { cmd; } - + if (test) cmd; } - + { if (test) { cmd; } - + if (test) cmd; } - + { cmd1; for (blah) @@ -1054,7 +1054,7 @@ describe('cindent', function() cmd2; cmd3; } - + { cmd1; for (blah) @@ -1062,7 +1062,7 @@ describe('cindent', function() if (test) cmd2; cmd3; - + if (test) { cmd1; @@ -1070,23 +1070,23 @@ describe('cindent', function() cmd3; } } - - + + /* Test for 'cindent' do/while mixed with if/else: */ - + { do if (asdf) asdfasd; while (cond); - + do if (asdf) while (asdf) asdf; while (asdf); } - + /* Test for 'cindent' with two ) on a continuation line */ { if (asdfasdf;asldkfj asdlkfj as;ldkfj sal;d @@ -1094,14 +1094,14 @@ describe('cindent', function() al;sdjfka ;slkdf ) sa;ldkjfsa dlk;) line up here; } - - + + /* C++ tests: */ - + // foo() these three lines should remain in column 0 // { // } - + /* Test for continuation and unterminated lines: */ { i = 99 + 14325 + @@ -1113,12 +1113,12 @@ describe('cindent', function() 1234; c = 1; } - + /* testje for indent with empty line - + here */ - + { if (testing && not a joke || @@ -1133,8 +1133,8 @@ describe('cindent', function() line up here)) hay; } - - + + { switch (c) { @@ -1153,7 +1153,7 @@ describe('cindent', function() testing; } } - + { if (cond) { foo; @@ -1163,7 +1163,7 @@ describe('cindent', function() bar; } } - + { if (alskdfj ;alsdkfjal;skdjf (;sadlkfsa ;dlkf j;alksdfj ;alskdjf alsdkfj (asldk;fj @@ -1172,7 +1172,7 @@ describe('cindent', function() asdfasdf;))) asdfasdf; } - + int func(a, b) int a; @@ -1185,7 +1185,7 @@ describe('cindent', function() (c2 || c3) ) } - + { while (asd) { @@ -1207,13 +1207,13 @@ describe('cindent', function() asdf; } } - + { s = "/*"; b = ';' s = "/*"; b = ';'; a = b; } - + { switch (a) { @@ -1247,7 +1247,7 @@ describe('cindent', function() break; } } - + { if (!(vim_strchr(p_cpo, CPO_BUFOPTGLOB) != NULL && entering) && (bp_to->b_p_initialized || @@ -1259,57 +1259,57 @@ describe('cindent', function() asdf = asdf ? asdf: asdf; } - + /* Special Comments : This function has the added complexity (compared */ /* : to addtolist) of having to check for a detail */ /* : texture and add that to the list first. */ - + char *(array[100]) = { "testje", "foo", "bar", } - + enum soppie { yes = 0, no, maybe }; - + typedef enum soppie { yes = 0, no, maybe }; - + static enum { yes = 0, no, maybe } soppie; - + public static enum { yes = 0, no, maybe } soppie; - + static private enum { yes = 0, no, maybe } soppie; - + { int a, b; } - + { struct Type { @@ -1322,7 +1322,7 @@ describe('cindent', function() 2, "two", 3, "three" }; - + float matrix[3][3] = { { @@ -1342,14 +1342,14 @@ describe('cindent', function() } }; } - + { /* blah ( blah */ /* where does this go? */ - + /* blah ( blah */ cmd; - + func(arg1, /* comment */ arg2); @@ -1360,7 +1360,7 @@ describe('cindent', function() c; /* Hey, NOW it indents?! */ } } - + { func(arg1, arg2, @@ -1368,7 +1368,7 @@ describe('cindent', function() /* Hey, what am I doing here? Is this coz of the ","? */ } } - + main () { if (cond) @@ -1382,7 +1382,7 @@ describe('cindent', function() a = d; return; } - + { case 2: if (asdf && asdfasdf) @@ -1393,42 +1393,42 @@ describe('cindent', function() a = 9; case 4: x = 1; y = 2; - + label: if (asdf) here; - + label: if (asdf && asdfasdf) { } - + label: if (asdf && asdfasdf) { there; } - + label: if (asdf && asdfasdf) there; } - + { /* hello with ":set comments= cino=c5" */ - + /* hello with ":set comments= cino=" */ } - - + + { if (a < b) { a = a + 1; } else a = a + 2; - + if (a) do { testing; @@ -1436,7 +1436,7 @@ describe('cindent', function() a = b + 1; asdfasdf } - + { for ( int i = 0; i < 10; i++ ) @@ -1444,13 +1444,13 @@ describe('cindent', function() } i = 0; } - + class bob { int foo() {return 1;} int bar; } - + main() { while(1) @@ -1463,32 +1463,32 @@ describe('cindent', function() } misplacedline; } - + { if (clipboard.state == SELECT_DONE && ((row == clipboard.start.lnum && col >= clipboard.start.col) || row > clipboard.start.lnum)) } - + { if (1) {i += 4;} where_am_i; return 0; } - + { { } // sdf(asdf if (asdf) asd; } - + { label1: label2: } - + { int fooRet = foo(pBar1, false /*fKB*/, true /*fPTB*/, 3 /*nT*/, false /*fDF*/); @@ -1500,12 +1500,12 @@ describe('cindent', function() } } } - + { f1(/*comment*/); f2(); } - + { do { if (foo) { @@ -1514,25 +1514,25 @@ describe('cindent', function() } while (foo); foo(); // was wrong } - + int x; // no extra indent because of the ; void func() { } - + char *tab[] = {"aaa", "};", /* }; */ NULL} int indented; {} - + char *a[] = {"aaa", "bbb", "ccc", NULL}; // here - + char *tab[] = {"aaa", "xx", /* xx */}; /* asdf */ int not_indented; - + { do { switch (bla) @@ -1543,23 +1543,23 @@ describe('cindent', function() } while (boo); wrong; } - + int foo, bar; int foo; - + #if defined(foo) \ && defined(bar) char * xx = "asdf\ foo\ bor"; int x; - + char *foo = "asdf\ asdf\ asdf", *bar; - + void f() { #if defined(foo) \ @@ -1578,19 +1578,19 @@ describe('cindent', function() #endif } #endif - + int y; // comment // comment - + // comment - + { Constructor(int a, int b ) : BaseClass(a) { } } - + void foo() { char one, @@ -1607,13 +1607,13 @@ describe('cindent', function() kees, jan; } - + { t(int f, int d); // ) d(); } - + Constructor::Constructor(int a, int b ) : @@ -1623,33 +1623,33 @@ describe('cindent', function() mMember(b), { } - + Constructor::Constructor(int a, int b ) : BaseClass(a) { } - + Constructor::Constructor(int a, int b ) /*x*/ : /*x*/ BaseClass(a), member(b) { } - + A::A(int a, int b) : aa(a), bb(b), cc(c) { } - + class CAbc : public BaseClass1, protected BaseClass2 { int Test() { return FALSE; } int Test1() { return TRUE; } - + CAbc(int a, int b ) : BaseClass(a) { @@ -1658,24 +1658,24 @@ describe('cindent', function() case abc: asdf(); break; - + case 999: baer(); break; } } - + public: // <-- this was incoreectly indented before!! void testfall(); protected: void testfall(); }; - + class CAbc : public BaseClass1, protected BaseClass2 { }; - + static struct { int a; @@ -1691,7 +1691,7 @@ describe('cindent', function() 456 } }; - + static struct { int a; @@ -1701,7 +1701,7 @@ describe('cindent', function() { 123, 456 }, { 123, 456 } }; - + void asdf() /* ind_maxparen may cause trouble here */ { if ((0 @@ -1731,17 +1731,17 @@ describe('cindent', function() && 1 && 1)) break; } - + foo() { a = cond ? foo() : asdf + asdf; - + a = cond ? foo() : asdf + asdf; } - + int main(void) { if (a) @@ -1750,7 +1750,7 @@ describe('cindent', function() else 3; next_line_of_code(); } - + barry() { Foo::Foo (int one, @@ -1758,14 +1758,14 @@ describe('cindent', function() : something(4) {} } - + barry() { Foo::Foo (int one, int two) : something(4) {} } - + Constructor::Constructor(int a, int b ) : @@ -1784,7 +1784,7 @@ describe('cindent', function() && lele); lulu; } - + int main () { switch (c) @@ -1794,13 +1794,13 @@ describe('cindent', function() } } } - + main() { (void) MyFancyFuasdfadsfnction( argument); } - + main() { char foo[] = "/*"; @@ -1808,7 +1808,7 @@ describe('cindent', function() df */ hello } - + /* valid namespaces with normal indent */ namespace { @@ -1847,7 +1847,7 @@ describe('cindent', function() 22222222222222222; } } - + /* invalid namespaces use block indent */ namespace test test2 { 111111111111111111111; @@ -1887,7 +1887,7 @@ describe('cindent', function() } )foo"; } - + { int a[4] = { [0] = 0, @@ -1896,12 +1896,12 @@ describe('cindent', function() [3] = 3, }; } - + { a = b[2] + 3; } - + { if (1) /* aaaaa @@ -1909,7 +1909,7 @@ describe('cindent', function() */ a = 1; } - + void func() { switch (foo) @@ -1936,16 +1936,16 @@ describe('cindent', function() break; } } - + /* end of AUTO */ ]=]) end) it('2 is working', function() insert_([=[ - + { - + /* this is * a real serious important big * comment @@ -1954,14 +1954,14 @@ describe('cindent', function() } ]=]) - execute('set tw=0 wm=60 columns=80 noai fo=croq') - execute('/serious/e') + feed_command('set tw=0 wm=60 columns=80 noai fo=croq') + feed_command('/serious/e') feed('a about life, the universe, and the rest<esc>') expect([=[ - + { - + /* this is * a real serious * about life, the @@ -1976,48 +1976,48 @@ describe('cindent', function() it('3 is working', function() insert_([=[ - + { /* * Testing for comments, without 'cin' set */ - + /* * what happens here? */ - + /* the end of the comment, try inserting a line below */ - + /* how about this one */ } ]=]) - execute('set nocin') - execute('/comments') + feed_command('set nocin') + feed_command('/comments') feed('joabout life<esc>/happens<cr>') feed('jothere<esc>/below<cr>') feed('oline<esc>/this<cr>') feed('Ohello<esc>') expect([=[ - + { /* * Testing for comments, without 'cin' set */ about life - + /* * what happens here? */ there - + /* the end of the comment, try inserting a line below */ line - + /* how about hello this one */ @@ -2027,19 +2027,19 @@ describe('cindent', function() it('4 is working', function() insert_([=[ - + { var = this + that + vec[0] * vec[0] + vec[1] * vec[1] + vec2[2] * vec[2]; } ]=]) - execute('set cin') - execute('/vec2') + feed_command('set cin') + feed_command('/vec2') feed('==<cr>') expect([=[ - + { var = this + that + vec[0] * vec[0] + vec[1] * vec[1] @@ -2050,7 +2050,7 @@ describe('cindent', function() it('5 is working', function() insert_([=[ - + { asdf asdflkajds f; if (tes & ting) { @@ -2067,14 +2067,14 @@ describe('cindent', function() } ]=]) - execute('set cin') - execute('set cino=}4') - execute('/testing1') + feed_command('set cin') + feed_command('set cino=}4') + feed_command('/testing1') feed('k2==/testing2<cr>') feed('k2==<cr>') expect([=[ - + { asdf asdflkajds f; if (tes & ting) { @@ -2094,7 +2094,7 @@ describe('cindent', function() it('6 is working', function() insert_([=[ - + main ( int first_par, /* * Comment for * first par @@ -2114,17 +2114,17 @@ describe('cindent', function() * second par */ ); - + } ]=]) - execute('set cin') - execute('set cino=(0,)20') - execute('/main') + feed_command('set cin') + feed_command('set cino=(0,)20') + feed_command('/main') feed('=][<cr>') expect([=[ - + main ( int first_par, /* * Comment for * first par @@ -2144,14 +2144,14 @@ describe('cindent', function() * second par */ ); - + } ]=]) end) it('7 is working', function() insert_([=[ - + main(void) { /* Make sure that cino=X0s is not parsed like cino=Xs. */ @@ -2164,13 +2164,13 @@ describe('cindent', function() } ]=]) - execute('set cin') - execute('set cino=es,n0s') - execute('/main') + feed_command('set cin') + feed_command('set cino=es,n0s') + feed_command('/main') feed('=][<cr>') expect([=[ - + main(void) { /* Make sure that cino=X0s is not parsed like cino=Xs. */ @@ -2186,7 +2186,7 @@ describe('cindent', function() it('8 is working', function() insert_([=[ - + { do { @@ -2202,12 +2202,12 @@ describe('cindent', function() } ]=]) - execute('set cin') - execute('set cino=') + feed_command('set cin') + feed_command('set cino=') feed(']]=][<cr>') expect([=[ - + { do { @@ -2226,16 +2226,16 @@ describe('cindent', function() it('9 is working', function() insert_([=[ - + void f() { if ( k() ) { l(); - + } else { /* Start (two words) end */ m(); } - + n(); } ]=]) @@ -2243,16 +2243,16 @@ describe('cindent', function() feed(']]=][<cr>') expect([=[ - + void f() { if ( k() ) { l(); - + } else { /* Start (two words) end */ m(); } - + n(); } ]=]) @@ -2267,7 +2267,7 @@ describe('cindent', function() -- indented properly. And that's why we've had to add one explicitly. insert_([=[ { <= THIS IS THE CURLY BRACKET EXPLAINED IN THE COMMENT. - + void f() { if ( k() ) @@ -2280,12 +2280,12 @@ describe('cindent', function() } ]=]) - execute('set cino={s,e-s') + feed_command('set cino={s,e-s') feed(']]=][<cr>') expect([=[ { <= THIS IS THE CURLY BRACKET EXPLAINED IN THE COMMENT. - + void f() { if ( k() ) @@ -2301,7 +2301,7 @@ describe('cindent', function() it('11 is working', function() insert_([=[ - + void bar(void) { static array[2][2] = @@ -2309,12 +2309,12 @@ describe('cindent', function() { 1, 2 }, { 3, 4 }, } - + while (a) { foo(&a); } - + { int a; { @@ -2323,7 +2323,7 @@ describe('cindent', function() } b = a; } - + void func(void) { a = 1; @@ -2336,11 +2336,11 @@ describe('cindent', function() /* foo */ ]=]) - execute('set cino={s,fs') + feed_command('set cino={s,fs') feed(']]=/ foo<cr>') expect([=[ - + void bar(void) { static array[2][2] = @@ -2348,12 +2348,12 @@ describe('cindent', function() { 1, 2 }, { 3, 4 }, } - + while (a) { foo(&a); } - + { int a; { @@ -2362,7 +2362,7 @@ describe('cindent', function() } b = a; } - + void func(void) { a = 1; @@ -2378,7 +2378,7 @@ describe('cindent', function() it('12 is working', function() insert_([=[ - + a() { do { @@ -2390,12 +2390,12 @@ describe('cindent', function() } ]=]) - execute('set cino=') - execute('/while') + feed_command('set cino=') + feed_command('/while') feed('ohere<esc>') expect([=[ - + a() { do { @@ -2411,7 +2411,7 @@ describe('cindent', function() it('13 is working', function() insert_([=[ - + a() { label1: @@ -2420,12 +2420,12 @@ describe('cindent', function() } ]=]) - execute('set cino= com=') - execute('/comment') + feed_command('set cino= com=') + feed_command('/comment') feed('olabel2: b();<cr>label3 /* post */:<cr>/* pre */ label4:<cr>f(/*com*/);<cr>if (/*com*/)<cr>cmd();<esc>') expect([=[ - + a() { label1: @@ -2443,26 +2443,26 @@ describe('cindent', function() it('14 is working', function() insert_([=[ - + /* * A simple comment */ - + /* ** A different comment */ ]=]) - execute('set comments& comments^=s:/*,m:**,ex:*/') - execute('/simple') + feed_command('set comments& comments^=s:/*,m:**,ex:*/') + feed_command('/simple') feed('=5j<cr>') expect([=[ - + /* * A simple comment */ - + /* ** A different comment */ @@ -2471,26 +2471,26 @@ describe('cindent', function() it('15 is working', function() insert_([=[ - - + + void f() { - + /********* A comment. *********/ } ]=]) - execute('set cino=c0') - execute('set comments& comments-=s1:/* comments^=s0:/*') + feed_command('set cino=c0') + feed_command('set comments& comments-=s1:/* comments^=s0:/*') feed('2kdd]]=][<cr>') expect([=[ - + void f() { - + /********* A comment. *********/ @@ -2500,26 +2500,26 @@ describe('cindent', function() it('16 is working', function() insert_([=[ - - + + void f() { - + /********* A comment. *********/ } ]=]) - execute('set cino=c0,C1') - execute('set comments& comments-=s1:/* comments^=s0:/*') + feed_command('set cino=c0,C1') + feed_command('set comments& comments-=s1:/* comments^=s0:/*') feed('2kdd]]=][<cr>') expect([=[ - + void f() { - + /********* A comment. *********/ @@ -2529,7 +2529,7 @@ describe('cindent', function() it('17 is working', function() insert_([=[ - + void f() { c = c1 && @@ -2540,11 +2540,11 @@ describe('cindent', function() } ]=]) - execute('set cino=') + feed_command('set cino=') feed(']]=][<cr>') expect([=[ - + void f() { c = c1 && @@ -2558,8 +2558,8 @@ describe('cindent', function() it('18 is working', function() insert_([=[ - - + + void f() { c = c1 && @@ -2570,11 +2570,11 @@ describe('cindent', function() } ]=]) - execute('set cino=(s') + feed_command('set cino=(s') feed('2kdd]]=][<cr>') expect([=[ - + void f() { c = c1 && @@ -2588,8 +2588,8 @@ describe('cindent', function() it('19 is working', function() insert_([=[ - - + + void f() { c = c1 && @@ -2600,11 +2600,11 @@ describe('cindent', function() } ]=]) - execute('set cino=(s,U1 ') + feed_command('set cino=(s,U1 ') feed('2kdd]]=][<cr>') expect([=[ - + void f() { c = c1 && @@ -2618,8 +2618,8 @@ describe('cindent', function() it('20 is working', function() insert_([=[ - - + + void f() { if ( c1 @@ -2629,11 +2629,11 @@ describe('cindent', function() } ]=]) - execute('set cino=(0') + feed_command('set cino=(0') feed('2kdd]]=][<cr>') expect([=[ - + void f() { if ( c1 @@ -2646,8 +2646,8 @@ describe('cindent', function() it('21 is working', function() insert_([=[ - - + + void f() { if ( c1 @@ -2657,11 +2657,11 @@ describe('cindent', function() } ]=]) - execute('set cino=(0,w1 ') + feed_command('set cino=(0,w1 ') feed('2kdd]]=][<cr>') expect([=[ - + void f() { if ( c1 @@ -2674,8 +2674,8 @@ describe('cindent', function() it('22 is working', function() insert_([=[ - - + + void f() { c = c1 && ( @@ -2689,11 +2689,11 @@ describe('cindent', function() } ]=]) - execute('set cino=(s') + feed_command('set cino=(s') feed('2kdd]]=][<cr>') expect([=[ - + void f() { c = c1 && ( @@ -2710,8 +2710,8 @@ describe('cindent', function() it('23 is working', function() insert_([=[ - - + + void f() { c = c1 && ( @@ -2725,11 +2725,11 @@ describe('cindent', function() } ]=]) - execute('set cino=(s,m1 ') + feed_command('set cino=(s,m1 ') feed('2kdd]]=][<cr>') expect([=[ - + void f() { c = c1 && ( @@ -2746,8 +2746,8 @@ describe('cindent', function() it('24 is working', function() insert_([=[ - - + + void f() { switch (x) @@ -2762,11 +2762,11 @@ describe('cindent', function() } ]=]) - execute('set cino=b1') + feed_command('set cino=b1') feed('2kdd]]=][<cr>') expect([=[ - + void f() { switch (x) @@ -2784,8 +2784,8 @@ describe('cindent', function() it('25 is working', function() insert_([=[ - - + + void f() { invokeme( @@ -2801,11 +2801,11 @@ describe('cindent', function() } ]=]) - execute('set cino=(0,W5') + feed_command('set cino=(0,W5') feed('2kdd]]=][<cr>') expect([=[ - + void f() { invokeme( @@ -2824,8 +2824,8 @@ describe('cindent', function() it('26 is working', function() insert_([=[ - - + + void f() { statement; @@ -2834,11 +2834,11 @@ describe('cindent', function() } ]=]) - execute('set cino=/6') + feed_command('set cino=/6') feed('2kdd]]=][<cr>') expect([=[ - + void f() { statement; @@ -2850,8 +2850,8 @@ describe('cindent', function() it('27 is working', function() insert_([=[ - - + + void f() { statement; @@ -2860,12 +2860,12 @@ describe('cindent', function() } ]=]) - execute('set cino=') + feed_command('set cino=') feed('2kdd]]/comment 1/+1<cr>') feed('==<cr>') expect([=[ - + void f() { statement; @@ -2877,12 +2877,12 @@ describe('cindent', function() it('28 is working', function() insert_([=[ - - + + class CAbc { int Test() { return FALSE; } - + public: // comment void testfall(); protected: @@ -2890,15 +2890,15 @@ describe('cindent', function() }; ]=]) - execute('set cino=g0') + feed_command('set cino=g0') feed('2kdd]]=][<cr>') expect([=[ - + class CAbc { int Test() { return FALSE; } - + public: // comment void testfall(); protected: @@ -2909,8 +2909,8 @@ describe('cindent', function() it('29 is working', function() insert_([=[ - - + + class Foo : public Bar { public: @@ -2921,11 +2921,11 @@ describe('cindent', function() }; ]=]) - execute('set cino=(0,gs,hs') + feed_command('set cino=(0,gs,hs') feed('2kdd]]=][<cr>') expect([=[ - + class Foo : public Bar { public: @@ -2939,8 +2939,8 @@ describe('cindent', function() it('30 is working', function() insert_([=[ - - + + void foo() { @@ -2951,11 +2951,11 @@ describe('cindent', function() } ]=]) - execute('set cino=+20') + feed_command('set cino=+20') feed('2kdd]]=][<cr>') expect([=[ - + void foo() { @@ -2969,8 +2969,8 @@ describe('cindent', function() it('31 is working', function() insert_([=[ - - + + { averylongfunctionnamelongfunctionnameaverylongfunctionname()->asd( asdasdf, @@ -2978,9 +2978,9 @@ describe('cindent', function() asdfadsf), asdfasdf ); - + /* those are ugly, but consequent */ - + func()->asd(asdasdf, averylongfunctionname( abc, @@ -2994,7 +2994,7 @@ describe('cindent', function() ), asdasdf ); - + averylongfunctionnameaverylongfunctionnameavery()->asd(fasdf( abc, dec)->asdfasdfasdf( @@ -3009,11 +3009,11 @@ describe('cindent', function() } ]=]) - execute('set cino=(0,W2s') + feed_command('set cino=(0,W2s') feed('2kdd]]=][<cr>') expect([=[ - + { averylongfunctionnamelongfunctionnameaverylongfunctionname()->asd( asdasdf, @@ -3021,9 +3021,9 @@ describe('cindent', function() asdfadsf), asdfasdf ); - + /* those are ugly, but consequent */ - + func()->asd(asdasdf, averylongfunctionname( abc, @@ -3037,7 +3037,7 @@ describe('cindent', function() ), asdasdf ); - + averylongfunctionnameaverylongfunctionnameavery()->asd(fasdf( abc, dec)->asdfasdfasdf( @@ -3055,8 +3055,8 @@ describe('cindent', function() it('32 is working', function() insert_([=[ - - + + int main () { if (cond1 && @@ -3066,11 +3066,11 @@ describe('cindent', function() } ]=]) - execute('set cino=M1') + feed_command('set cino=M1') feed('2kdd]]=][<cr>') expect([=[ - + int main () { if (cond1 && @@ -3083,8 +3083,8 @@ describe('cindent', function() it('33 is working', function() insert_([=[ - - + + void func(int a #if defined(FOO) , int b @@ -3095,11 +3095,11 @@ describe('cindent', function() } ]=]) - execute('set cino=(0,ts') + feed_command('set cino=(0,ts') feed('2kdd2j=][<cr>') expect([=[ - + void func(int a #if defined(FOO) , int b @@ -3113,9 +3113,9 @@ describe('cindent', function() it('34 is working', function() insert_([=[ - - - + + + void func(int a #if defined(FOO) @@ -3127,12 +3127,12 @@ describe('cindent', function() } ]=]) - execute('set cino=(0') + feed_command('set cino=(0') feed('2kdd2j=][<cr>') expect([=[ - - + + void func(int a #if defined(FOO) @@ -3147,8 +3147,8 @@ describe('cindent', function() it('35 is working', function() insert_([=[ - - + + void func(void) { if(x==y) @@ -3159,7 +3159,7 @@ describe('cindent', function() } printf("Foo!\n"); } - + void func1(void) { char* tab[] = {"foo", "bar", @@ -3167,37 +3167,37 @@ describe('cindent', function() "this line used", "to be indented incorrectly"}; foo(); } - + void func2(void) { int tab[] = {1, 2, 3, 4, 5, 6}; - + printf("This line used to be indented incorrectly.\n"); } - + int foo[] #ifdef BAR - + = { 1, 2, 3, 4, 5, 6 } - + #endif ; int baz; - + void func3(void) { int tab[] = { 1, 2, 3, 4, 5, 6}; - + printf("Don't you dare indent this line incorrectly!\n"); } - + void func4(a, b, c) @@ -3206,14 +3206,14 @@ describe('cindent', function() int c; { } - + void func5( int a, int b) { } - + void func6( int a) @@ -3221,11 +3221,11 @@ describe('cindent', function() } ]=]) - execute('set cino&') + feed_command('set cino&') feed('2kdd2j=7][<cr>') expect([=[ - + void func(void) { if(x==y) @@ -3236,7 +3236,7 @@ describe('cindent', function() } printf("Foo!\n"); } - + void func1(void) { char* tab[] = {"foo", "bar", @@ -3244,37 +3244,37 @@ describe('cindent', function() "this line used", "to be indented incorrectly"}; foo(); } - + void func2(void) { int tab[] = {1, 2, 3, 4, 5, 6}; - + printf("This line used to be indented incorrectly.\n"); } - + int foo[] #ifdef BAR - + = { 1, 2, 3, 4, 5, 6 } - + #endif ; int baz; - + void func3(void) { int tab[] = { 1, 2, 3, 4, 5, 6}; - + printf("Don't you dare indent this line incorrectly!\n"); } - + void func4(a, b, c) @@ -3283,14 +3283,14 @@ describe('cindent', function() int c; { } - + void func5( int a, int b) { } - + void func6( int a) @@ -3301,17 +3301,17 @@ describe('cindent', function() it('36 is working', function() insert_([=[ - - + + void func(void) { int tab[] = { 1, 2, 3, 4, 5, 6}; - + printf("Indent this line correctly!\n"); - + switch (foo) { case bar: @@ -3328,21 +3328,21 @@ describe('cindent', function() } ]=]) - execute('set cino&') - execute('set cino+=l1') + feed_command('set cino&') + feed_command('set cino+=l1') feed('2kdd2j=][<cr>') expect([=[ - + void func(void) { int tab[] = { 1, 2, 3, 4, 5, 6}; - + printf("Indent this line correctly!\n"); - + switch (foo) { case bar: @@ -3362,8 +3362,8 @@ describe('cindent', function() it('37 is working', function() insert_([=[ - - + + void func(void) { cout << "a" @@ -3373,11 +3373,11 @@ describe('cindent', function() } ]=]) - execute('set cino&') + feed_command('set cino&') feed('2kdd2j=][<cr>') expect([=[ - + void func(void) { cout << "a" @@ -3390,7 +3390,7 @@ describe('cindent', function() it('38 is working', function() insert_([=[ - + void func(void) { /* @@ -3399,11 +3399,11 @@ describe('cindent', function() } ]=]) - execute('set com=s1:/*,m:*,ex:*/') + feed_command('set com=s1:/*,m:*,ex:*/') feed(']]3jofoo();<esc>') expect([=[ - + void func(void) { /* @@ -3416,8 +3416,8 @@ describe('cindent', function() it('39 is working', function() insert_([=[ - - + + void func(void) { for (int i = 0; i < 10; ++i) @@ -3429,11 +3429,11 @@ describe('cindent', function() } ]=]) - execute('set cino&') + feed_command('set cino&') feed('2kdd2j=][<cr>') expect([=[ - + void func(void) { for (int i = 0; i < 10; ++i) @@ -3448,8 +3448,8 @@ describe('cindent', function() it('40 is working', function() insert_([=[ - - + + void func(void) { if (condition1 @@ -3457,7 +3457,7 @@ describe('cindent', function() action(); function(argument1 && argument2); - + if (c1 && (c2 || c3)) foo; @@ -3465,7 +3465,7 @@ describe('cindent', function() (c2 || c3)) { } - + if ( c1 && ( c2 || c3)) @@ -3477,11 +3477,11 @@ describe('cindent', function() } ]=]) - execute('set cino=k2s,(0') + feed_command('set cino=k2s,(0') feed('2kdd3j=][<cr>') expect([=[ - + void func(void) { if (condition1 @@ -3489,7 +3489,7 @@ describe('cindent', function() action(); function(argument1 && argument2); - + if (c1 && (c2 || c3)) foo; @@ -3497,7 +3497,7 @@ describe('cindent', function() (c2 || c3)) { } - + if ( c1 && ( c2 || c3)) @@ -3512,8 +3512,8 @@ describe('cindent', function() it('41 is working', function() insert_([=[ - - + + void func(void) { if (condition1 @@ -3521,7 +3521,7 @@ describe('cindent', function() action(); function(argument1 && argument2); - + if (c1 && (c2 || c3)) foo; @@ -3529,7 +3529,7 @@ describe('cindent', function() (c2 || c3)) { } - + if ( c1 && ( c2 || c3)) @@ -3541,11 +3541,11 @@ describe('cindent', function() } ]=]) - execute('set cino=k2s,(s') + feed_command('set cino=k2s,(s') feed('2kdd3j=][<cr>') expect([=[ - + void func(void) { if (condition1 @@ -3553,7 +3553,7 @@ describe('cindent', function() action(); function(argument1 && argument2); - + if (c1 && (c2 || c3)) foo; @@ -3561,7 +3561,7 @@ describe('cindent', function() (c2 || c3)) { } - + if ( c1 && ( c2 || c3)) @@ -3576,8 +3576,8 @@ describe('cindent', function() it('42 is working', function() insert_([=[ - - + + void func(void) { if (condition1 @@ -3585,7 +3585,7 @@ describe('cindent', function() action(); function(argument1 && argument2); - + if (c1 && (c2 || c3)) foo; @@ -3597,7 +3597,7 @@ describe('cindent', function() && (c22345 || c3)) printf("foo\n"); - + c = c1 && ( c2 || @@ -3606,11 +3606,11 @@ describe('cindent', function() } ]=]) - execute('set cino=k2s,(s,U1') + feed_command('set cino=k2s,(s,U1') feed('2kdd3j=][<cr>') expect([=[ - + void func(void) { if (condition1 @@ -3618,7 +3618,7 @@ describe('cindent', function() action(); function(argument1 && argument2); - + if (c1 && (c2 || c3)) foo; @@ -3630,7 +3630,7 @@ describe('cindent', function() && (c22345 || c3)) printf("foo\n"); - + c = c1 && ( c2 || @@ -3642,8 +3642,8 @@ describe('cindent', function() it('43 is working', function() insert_([=[ - - + + void func(void) { if (condition1 @@ -3651,7 +3651,7 @@ describe('cindent', function() action(); function(argument1 && argument2); - + if (c1 && (c2 || c3)) foo; @@ -3663,12 +3663,12 @@ describe('cindent', function() && (c22345 || c3)) printf("foo\n"); - + if ( c1 && ( c2 || c3)) foo; - + a_long_line( argument, argument); @@ -3677,11 +3677,11 @@ describe('cindent', function() } ]=]) - execute('set cino=k2s,(0,W4') + feed_command('set cino=k2s,(0,W4') feed('2kdd3j=][<cr>') expect([=[ - + void func(void) { if (condition1 @@ -3689,7 +3689,7 @@ describe('cindent', function() action(); function(argument1 && argument2); - + if (c1 && (c2 || c3)) foo; @@ -3701,12 +3701,12 @@ describe('cindent', function() && (c22345 || c3)) printf("foo\n"); - + if ( c1 && ( c2 || c3)) foo; - + a_long_line( argument, argument); @@ -3718,8 +3718,8 @@ describe('cindent', function() it('44 is working', function() insert_([=[ - - + + void func(void) { if (condition1 @@ -3727,7 +3727,7 @@ describe('cindent', function() action(); function(argument1 && argument2); - + if (c1 && (c2 || c3)) foo; @@ -3742,11 +3742,11 @@ describe('cindent', function() } ]=]) - execute('set cino=k2s,u2') + feed_command('set cino=k2s,u2') feed('2kdd3j=][<cr>') expect([=[ - + void func(void) { if (condition1 @@ -3754,7 +3754,7 @@ describe('cindent', function() action(); function(argument1 && argument2); - + if (c1 && (c2 || c3)) foo; @@ -3772,8 +3772,8 @@ describe('cindent', function() it('45 is working', function() insert_([=[ - - + + void func(void) { if (condition1 @@ -3781,7 +3781,7 @@ describe('cindent', function() action(); function(argument1 && argument2); - + if (c1 && (c2 || c3)) foo; @@ -3793,7 +3793,7 @@ describe('cindent', function() && (c22345 || c3)) printf("foo\n"); - + if ( c1 && ( c2 || c3)) @@ -3805,11 +3805,11 @@ describe('cindent', function() } ]=]) - execute('set cino=k2s,(0,w1') + feed_command('set cino=k2s,(0,w1') feed('2kdd3j=][<cr>') expect([=[ - + void func(void) { if (condition1 @@ -3817,7 +3817,7 @@ describe('cindent', function() action(); function(argument1 && argument2); - + if (c1 && (c2 || c3)) foo; @@ -3829,7 +3829,7 @@ describe('cindent', function() && (c22345 || c3)) printf("foo\n"); - + if ( c1 && ( c2 || c3)) @@ -3844,8 +3844,8 @@ describe('cindent', function() it('46 is working', function() insert_([=[ - - + + void func(void) { if (condition1 @@ -3853,7 +3853,7 @@ describe('cindent', function() action(); function(argument1 && argument2); - + if (c1 && (c2 || c3)) foo; @@ -3864,11 +3864,11 @@ describe('cindent', function() } ]=]) - execute('set cino=k2,(s') + feed_command('set cino=k2,(s') feed('2kdd3j=][<cr>') expect([=[ - + void func(void) { if (condition1 @@ -3876,7 +3876,7 @@ describe('cindent', function() action(); function(argument1 && argument2); - + if (c1 && (c2 || c3)) foo; @@ -3890,7 +3890,7 @@ describe('cindent', function() it('47 is working', function() insert_([=[ - + NAMESPACESTART /* valid namespaces with normal indent */ namespace @@ -3915,6 +3915,26 @@ describe('cindent', function() { 111111111111111111; } + namespace test::cpp17 + { + 111111111111111111; + } + namespace ::incorrectcpp17 + { + 111111111111111111; + } + namespace test::incorrectcpp17:: + { + 111111111111111111; + } + namespace test:incorrectcpp17 + { + 111111111111111111; + } + namespace test:::incorrectcpp17 + { + 111111111111111111; + } namespace{ 111111111111111111; } @@ -3930,7 +3950,7 @@ describe('cindent', function() 22222222222222222; } } - + /* invalid namespaces use block indent */ namespace test test2 { 111111111111111111111; @@ -3956,12 +3976,12 @@ describe('cindent', function() NAMESPACEEND ]=]) - execute('set cino=N-s') - execute('/^NAMESPACESTART') + feed_command('set cino=N-s') + feed_command('/^NAMESPACESTART') feed('=/^NAMESPACEEND<cr>') expect([=[ - + NAMESPACESTART /* valid namespaces with normal indent */ namespace @@ -3986,6 +4006,26 @@ describe('cindent', function() { 111111111111111111; } + namespace test::cpp17 + { + 111111111111111111; + } + namespace ::incorrectcpp17 + { + 111111111111111111; + } + namespace test::incorrectcpp17:: + { + 111111111111111111; + } + namespace test:incorrectcpp17 + { + 111111111111111111; + } + namespace test:::incorrectcpp17 + { + 111111111111111111; + } namespace{ 111111111111111111; } @@ -4001,7 +4041,7 @@ describe('cindent', function() 22222222222222222; } } - + /* invalid namespaces use block indent */ namespace test test2 { 111111111111111111111; @@ -4030,7 +4070,7 @@ describe('cindent', function() it('48 is working', function() insert_([=[ - + JSSTART var bar = { foo: { @@ -4047,12 +4087,12 @@ describe('cindent', function() JSEND ]=]) - execute('set cino=j1,J1') - execute('/^JSSTART') + feed_command('set cino=j1,J1') + feed_command('/^JSSTART') feed('=/^JSEND<cr>') expect([=[ - + JSSTART var bar = { foo: { @@ -4072,7 +4112,7 @@ describe('cindent', function() it('49 is working', function() insert_([=[ - + JSSTART var foo = [ 1, @@ -4082,12 +4122,12 @@ describe('cindent', function() JSEND ]=]) - execute('set cino=j1,J1') - execute('/^JSSTART') + feed_command('set cino=j1,J1') + feed_command('/^JSSTART') feed('=/^JSEND<cr>') expect([=[ - + JSSTART var foo = [ 1, @@ -4100,7 +4140,7 @@ describe('cindent', function() it('50 is working', function() insert_([=[ - + JSSTART function bar() { var foo = [ @@ -4112,12 +4152,12 @@ describe('cindent', function() JSEND ]=]) - execute('set cino=j1,J1') - execute('/^JSSTART') + feed_command('set cino=j1,J1') + feed_command('/^JSSTART') feed('=/^JSEND<cr>') expect([=[ - + JSSTART function bar() { var foo = [ @@ -4132,10 +4172,10 @@ describe('cindent', function() it('51 is working', function() insert_([=[ - + JSSTART (function($){ - + if (cond && cond) { stmt; @@ -4143,18 +4183,18 @@ describe('cindent', function() window.something.left = (width - 50 + offset) + "px"; var class_name='myclass'; - + function private_method() { } - + var public_method={ method: function(options,args){ private_method(); } } - + function init(options) { - + $(this).data(class_name+'_public',$.extend({},{ foo: 'bar', bar: 2, @@ -4168,19 +4208,19 @@ describe('cindent', function() } }, options||{})); } - + $.fn[class_name]=function() { - + var _arguments=arguments; return this.each(function(){ - + var options=$(this).data(class_name+'_public'); if (!options) { init.apply(this,_arguments); - + } else { var method=public_method[_arguments[0]]; - + if (typeof(method)!='function') { console.log(class_name+' has no method "'+_arguments[0]+'"'); return false; @@ -4190,20 +4230,20 @@ describe('cindent', function() } }); } - + })(jQuery); JSEND ]=]) - execute('set cino=j1,J1') - execute('/^JSSTART') + feed_command('set cino=j1,J1') + feed_command('/^JSSTART') feed('=/^JSEND<cr>') expect([=[ - + JSSTART (function($){ - + if (cond && cond) { stmt; @@ -4211,18 +4251,18 @@ describe('cindent', function() window.something.left = (width - 50 + offset) + "px"; var class_name='myclass'; - + function private_method() { } - + var public_method={ method: function(options,args){ private_method(); } } - + function init(options) { - + $(this).data(class_name+'_public',$.extend({},{ foo: 'bar', bar: 2, @@ -4236,19 +4276,19 @@ describe('cindent', function() } }, options||{})); } - + $.fn[class_name]=function() { - + var _arguments=arguments; return this.each(function(){ - + var options=$(this).data(class_name+'_public'); if (!options) { init.apply(this,_arguments); - + } else { var method=public_method[_arguments[0]]; - + if (typeof(method)!='function') { console.log(class_name+' has no method "'+_arguments[0]+'"'); return false; @@ -4258,7 +4298,7 @@ describe('cindent', function() } }); } - + })(jQuery); JSEND ]=]) @@ -4266,7 +4306,7 @@ describe('cindent', function() it('52 is working', function() insert_([=[ - + JSSTART function init(options) { $(this).data(class_name+'_public',$.extend({},{ @@ -4285,12 +4325,12 @@ describe('cindent', function() JSEND ]=]) - execute('set cino=j1,J1') - execute('/^JSSTART') + feed_command('set cino=j1,J1') + feed_command('/^JSSTART') feed('=/^JSEND<cr>') expect([=[ - + JSSTART function init(options) { $(this).data(class_name+'_public',$.extend({},{ @@ -4312,7 +4352,7 @@ describe('cindent', function() it('53 is working', function() insert_([=[ - + JSSTART (function($){ function init(options) { @@ -4333,12 +4373,12 @@ describe('cindent', function() JSEND ]=]) - execute('set cino=j1,J1') - execute('/^JSSTART') + feed_command('set cino=j1,J1') + feed_command('/^JSSTART') feed('=/^JSEND<cr>') expect([=[ - + JSSTART (function($){ function init(options) { @@ -4362,7 +4402,7 @@ describe('cindent', function() it('javascript indent / vim-patch 7.4.670', function() insert_([=[ - + JSSTART // Results of JavaScript indent // 1 @@ -4379,7 +4419,7 @@ describe('cindent', function() 'i' ]; }()) - + // 2 (function(){ var a = [ @@ -4400,7 +4440,7 @@ describe('cindent', function() 'i' ]; }()) - + // 3 (function(){ var a = [ @@ -4423,7 +4463,7 @@ describe('cindent', function() 'i' ]; }()) - + // 4 { var a = [ @@ -4433,7 +4473,7 @@ describe('cindent', function() var b; var c; } - + // 5 { var a = [ @@ -4444,7 +4484,7 @@ describe('cindent', function() 3 ]; } - + // 6 { var a = [ @@ -4456,7 +4496,7 @@ describe('cindent', function() 3 ]; } - + // 7 { var a = [ @@ -4468,7 +4508,7 @@ describe('cindent', function() 3 ]; } - + // 8 var x = [ (function(){ @@ -4483,7 +4523,7 @@ describe('cindent', function() i; }) ]; - + // 9 var a = [ 0 + @@ -4502,7 +4542,7 @@ describe('cindent', function() 'h', 'i' ]; - + // 10 var a, b, @@ -4517,12 +4557,12 @@ describe('cindent', function() ]=]) -- :set cino=j1,J1,+2 - execute('set cino=j1,J1,+2') - execute('/^JSSTART') + feed_command('set cino=j1,J1,+2') + feed_command('/^JSSTART') feed('=/^JSEND<cr>') expect([=[ - + JSSTART // Results of JavaScript indent // 1 @@ -4539,7 +4579,7 @@ describe('cindent', function() 'i' ]; }()) - + // 2 (function(){ var a = [ @@ -4560,7 +4600,7 @@ describe('cindent', function() 'i' ]; }()) - + // 3 (function(){ var a = [ @@ -4583,7 +4623,7 @@ describe('cindent', function() 'i' ]; }()) - + // 4 { var a = [ @@ -4593,7 +4633,7 @@ describe('cindent', function() var b; var c; } - + // 5 { var a = [ @@ -4604,7 +4644,7 @@ describe('cindent', function() 3 ]; } - + // 6 { var a = [ @@ -4616,7 +4656,7 @@ describe('cindent', function() 3 ]; } - + // 7 { var a = [ @@ -4628,7 +4668,7 @@ describe('cindent', function() 3 ]; } - + // 8 var x = [ (function(){ @@ -4643,7 +4683,7 @@ describe('cindent', function() i; }) ]; - + // 9 var a = [ 0 + @@ -4662,7 +4702,7 @@ describe('cindent', function() 'h', 'i' ]; - + // 10 var a, b, diff --git a/test/functional/legacy/004_bufenter_with_modelines_spec.lua b/test/functional/legacy/004_bufenter_with_modelines_spec.lua index 3e5cdd2ff2..9b0df024c8 100644 --- a/test/functional/legacy/004_bufenter_with_modelines_spec.lua +++ b/test/functional/legacy/004_bufenter_with_modelines_spec.lua @@ -1,10 +1,9 @@ --- vim: set foldmethod=marker foldmarker=[[,]] : -- Test for autocommand that changes current buffer on BufEnter event. -- Check if modelines are interpreted for the correct buffer. local helpers = require('test.functional.helpers')(after_each) local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local execute, expect = helpers.execute, helpers.expect +local feed_command, expect = helpers.feed_command, helpers.expect describe('BufEnter with modelines', function() setup(clear) @@ -20,34 +19,34 @@ describe('BufEnter with modelines', function() this is a test end of test file Xxx]]) - execute('au BufEnter Xxx brew') + feed_command('au BufEnter Xxx brew') -- Write test file Xxx - execute('/start of') - execute('.,/end of/w! Xxx') - execute('set ai modeline modelines=3') + feed_command('/start of') + feed_command('.,/end of/w! Xxx') + feed_command('set ai modeline modelines=3') -- Split to Xxx, autocmd will do :brew - execute('sp Xxx') + feed_command('sp Xxx') -- Append text with autoindent to this file feed('G?this is a<CR>') feed('othis should be auto-indented<Esc>') -- Go to Xxx, no autocmd anymore - execute('au! BufEnter Xxx') - execute('buf Xxx') + feed_command('au! BufEnter Xxx') + feed_command('buf Xxx') -- Append text without autoindent to Xxx feed('G?this is a<CR>') feed('othis should be in column 1<Esc>') - execute('wq') + feed_command('wq') -- Include Xxx in the current file feed('G:r Xxx<CR>') -- Vim issue #57 do not move cursor on <c-o> when autoindent is set - execute('set fo+=r') + feed_command('set fo+=r') feed('G') feed('o# abcdef<Esc>2hi<CR><c-o>d0<Esc>') feed('o# abcdef<Esc>2hi<c-o>d0<Esc>') diff --git a/test/functional/legacy/005_bufleave_delete_buffer_spec.lua b/test/functional/legacy/005_bufleave_delete_buffer_spec.lua index 895f4ad181..417842c52d 100644 --- a/test/functional/legacy/005_bufleave_delete_buffer_spec.lua +++ b/test/functional/legacy/005_bufleave_delete_buffer_spec.lua @@ -3,7 +3,8 @@ local helpers = require('test.functional.helpers')(after_each) local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local execute, expect = helpers.execute, helpers.expect +local command, expect = helpers.command, helpers.expect +local wait = helpers.wait describe('test5', function() setup(clear) @@ -18,35 +19,37 @@ describe('test5', function() this is a test end of test file Xxx]]) - execute('w! Xxx0') - execute('au BufLeave Xxx bwipe') - execute('/start of') + command('w! Xxx0') + command('au BufLeave Xxx bwipe') + command('/start of') -- Write test file Xxx. - execute('.,/end of/w! Xxx') + command('.,/end of/w! Xxx') -- Split to Xxx. - execute('sp Xxx') + command('sp Xxx') -- Delete buffer Xxx, now we're back here. - execute('bwipe') + command('bwipe') feed('G?this is a<cr>') feed('othis is some more text<esc>') + wait() -- Append some text to this file. -- Write current file contents. - execute('?start?,$yank A') + command('?start?,$yank A') -- Delete current buffer, get an empty one. - execute('bwipe!') + command('bwipe!') -- Append an extra line to the output register. feed('ithis is another test line<esc>:yank A<cr>') + wait() -- Output results - execute('%d') - execute('0put a') - execute('$d') + command('%d') + command('0put a') + command('$d') -- Assert buffer contents. expect([[ diff --git a/test/functional/legacy/006_argument_list_spec.lua b/test/functional/legacy/006_argument_list_spec.lua index 764854314f..dac58df8a5 100644 --- a/test/functional/legacy/006_argument_list_spec.lua +++ b/test/functional/legacy/006_argument_list_spec.lua @@ -2,8 +2,9 @@ local helpers = require('test.functional.helpers')(after_each) local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local execute, dedent, eq = helpers.execute, helpers.dedent, helpers.eq +local command, dedent, eq = helpers.command, helpers.dedent, helpers.eq local curbuf_contents = helpers.curbuf_contents +local wait = helpers.wait describe('argument list', function() setup(clear) @@ -16,10 +17,11 @@ describe('argument list', function() this is a test this is a test end of test file Xxx]]) + wait() + + command('au BufReadPost Xxx2 next Xxx2 Xxx1') + command('/^start of') - execute('au BufReadPost Xxx2 next Xxx2 Xxx1') - execute('/^start of') - -- Write test file Xxx1 feed('A1<Esc>:.,/end of/w! Xxx1<cr>') @@ -28,29 +30,31 @@ describe('argument list', function() -- Write test file Xxx3 feed('$r3:.,/end of/w! Xxx3<cr>') + wait() -- Redefine arglist; go to Xxx1 - execute('next! Xxx1 Xxx2 Xxx3') - + command('next! Xxx1 Xxx2 Xxx3') + -- Open window for all args - execute('all') - + command('all') + -- Write contents of Xxx1 - execute('%yank A') + command('%yank A') -- Append contents of last window (Xxx1) feed('') - execute('%yank A') - + wait() + command('%yank A') + -- should now be in Xxx2 - execute('rew') - + command('rew') + -- Append contents of Xxx2 - execute('%yank A') + command('%yank A') - execute('%d') - execute('0put=@a') - execute('$d') + command('%d') + command('0put=@a') + command('$d') eq(dedent([[ start of test file Xxx1 diff --git a/test/functional/legacy/007_ball_buffer_list_spec.lua b/test/functional/legacy/007_ball_buffer_list_spec.lua index 07e3fe6e7a..8501faabec 100644 --- a/test/functional/legacy/007_ball_buffer_list_spec.lua +++ b/test/functional/legacy/007_ball_buffer_list_spec.lua @@ -2,7 +2,7 @@ local helpers = require('test.functional.helpers')(after_each) local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local execute, expect = helpers.execute, helpers.expect +local feed_command, expect = helpers.feed_command, helpers.expect describe(':ball', function() setup(clear) @@ -14,44 +14,44 @@ describe(':ball', function() this is a test end of test file Xxx]]) - execute('w! Xxx0') + feed_command('w! Xxx0') feed('gg') -- Write test file Xxx1 feed('A1:.,/end of/w! Xxx1<cr>') - execute('sp Xxx1') - execute('close') + feed_command('sp Xxx1') + feed_command('close') -- Write test file Xxx2 feed('$r2:.,/end of/w! Xxx2<cr>') - execute('sp Xxx2') - execute('close') + feed_command('sp Xxx2') + feed_command('close') -- Write test file Xxx3 feed('$r3:.,/end of/w! Xxx3<cr>') - execute('sp Xxx3') - execute('close') + feed_command('sp Xxx3') + feed_command('close') - execute('au BufReadPost Xxx2 bwipe') + feed_command('au BufReadPost Xxx2 bwipe') -- Open window for all args, close Xxx2 feed('$r4:ball<cr>') -- Write contents of this file - execute('%yank A') + feed_command('%yank A') - -- Append contents of second window (Xxx1) + -- Append contents of second window (Xxx1) feed('') - execute('%yank A') + feed_command('%yank A') -- Append contents of last window (this file) feed('') - execute('%yank A') + feed_command('%yank A') - execute('bf') - execute('%d') - execute('0put=@a') - execute('$d') + feed_command('bf') + feed_command('%d') + feed_command('0put=@a') + feed_command('$d') expect([[ start of test file Xxx4 diff --git a/test/functional/legacy/008_autocommands_spec.lua b/test/functional/legacy/008_autocommands_spec.lua new file mode 100644 index 0000000000..7474f1e068 --- /dev/null +++ b/test/functional/legacy/008_autocommands_spec.lua @@ -0,0 +1,91 @@ +-- Test for BufWritePre autocommand that deletes or unloads the buffer. +-- Test for BufUnload autocommand that unloads all other buffers. + +local helpers = require('test.functional.helpers')(after_each) +local feed, source = helpers.feed, helpers.source +local clear, feed_command, expect, eq, eval = helpers.clear, helpers.feed_command, helpers.expect, helpers.eq, helpers.eval +local write_file, wait, dedent = helpers.write_file, helpers.wait, helpers.dedent +local io = require('io') + +describe('autocommands that delete and unload buffers:', function() + local text1 = dedent([[ + start of Xxx1 + test + end of Xxx]]) + local text2 = text1:gsub('1', '2') + setup(function() + write_file('Xxx1', text1..'\n') + write_file('Xxx2', text2..'\n') + end) + teardown(function() + os.remove('test.out') + os.remove('Xxx1') + os.remove('Xxx2') + end) + before_each(clear) + + it('BufWritePre, BufUnload', function() + feed_command('au BufWritePre Xxx1 bunload') + feed_command('au BufWritePre Xxx2 bwipe') + feed_command('e Xxx2') + eq('Xxx2', eval('bufname("%")')) + feed_command('e Xxx1') + eq('Xxx1', eval('bufname("%")')) + -- The legacy test file did not check the error message. + feed_command('let v:errmsg = "no error"') + feed_command('write') + -- Discard all "hit enter" prompts and messages. + feed('<C-L>') + eq('E203: Autocommands deleted or unloaded buffer to be written', + eval('v:errmsg')) + eq('Xxx2', eval('bufname("%")')) + expect(text2) + -- Start editing Xxx2. + feed_command('e! Xxx2') + -- The legacy test file did not check the error message. + feed_command('let v:errmsg = "no error"') + -- Write Xxx2, will delete the buffer and give an error msg. + feed_command('w') + -- Discard all "hit enter" prompts and messages. + feed('<C-L>') + eq('E203: Autocommands deleted or unloaded buffer to be written', + eval('v:errmsg')) + eq('Xxx1', eval('bufname("%")')) + expect(text1) + end) + it('BufUnload, VimLeave', function() + source([[ + func CloseAll() + let i = 0 + while i <= bufnr('$') + if i != bufnr('%') && bufloaded(i) + exe i . "bunload" + endif + let i += 1 + endwhile + endfunc + func WriteToOut() + edit! test.out + $put ='VimLeave done' + write + endfunc + set shada='100 + au BufUnload * call CloseAll() + au VimLeave * call WriteToOut() + ]]) + feed_command('e Xxx2') + -- Discard all "hit enter" prompts and messages. + feed('<C-L>') + feed_command('e Xxx1') + -- Discard all "hit enter" prompts and messages. + feed('<C-L>') + feed_command('e Makefile') -- an existing file + feed('<C-L>') + feed_command('sp new2') + feed('<C-L>') + feed_command('q') + wait() + eq('VimLeave done', + string.match(io.open('test.out', 'r'):read('*all'), "^%s*(.-)%s*$")) + end) +end) diff --git a/test/functional/legacy/009_bufleave_autocommand_spec.lua b/test/functional/legacy/009_bufleave_autocommand_spec.lua deleted file mode 100644 index 7481c639cf..0000000000 --- a/test/functional/legacy/009_bufleave_autocommand_spec.lua +++ /dev/null @@ -1,22 +0,0 @@ --- Test for Bufleave autocommand that deletes the buffer we are about to edit. - -local helpers = require('test.functional.helpers')(after_each) -local clear, insert = helpers.clear, helpers.insert -local execute, expect = helpers.execute, helpers.expect - -describe('BufLeave autocommand', function() - setup(clear) - - it('is working', function() - insert([[ - start of test file xx - end of test file xx]]) - - execute('au BufLeave * bwipe yy') - execute('e yy') - - expect([[ - start of test file xx - end of test file xx]]) - end) -end) diff --git a/test/functional/legacy/011_autocommands_spec.lua b/test/functional/legacy/011_autocommands_spec.lua index ba899f8119..e01af4583b 100644 --- a/test/functional/legacy/011_autocommands_spec.lua +++ b/test/functional/legacy/011_autocommands_spec.lua @@ -14,8 +14,8 @@ local helpers= require('test.functional.helpers')(after_each) local lfs = require('lfs') -local clear, execute, expect, eq, neq, dedent, write_file, feed = - helpers.clear, helpers.execute, helpers.expect, helpers.eq, helpers.neq, +local clear, feed_command, expect, eq, neq, dedent, write_file, feed = + helpers.clear, helpers.feed_command, helpers.expect, helpers.eq, helpers.neq, helpers.dedent, helpers.write_file, helpers.feed if helpers.pending_win32(pending) then return end @@ -66,26 +66,26 @@ describe('file reading, writing and bufnew and filter autocommands', function() it('FileReadPost (using gzip)', function() prepare_gz_file('Xtestfile', text1) - execute('let $GZIP = ""') + feed_command('let $GZIP = ""') --execute('au FileChangedShell * echo "caught FileChangedShell"') - execute('set bin') - execute("au FileReadPost *.gz '[,']!gzip -d") + feed_command('set bin') + feed_command("au FileReadPost *.gz '[,']!gzip -d") -- Read and decompress the testfile. - execute('$r Xtestfile.gz') + feed_command('$r Xtestfile.gz') expect('\n'..text1) end) it('BufReadPre, BufReadPost (using gzip)', function() prepare_gz_file('Xtestfile', text1) local gzip_data = io.open('Xtestfile.gz'):read('*all') - execute('let $GZIP = ""') + feed_command('let $GZIP = ""') -- Setup autocommands to decompress before reading and re-compress afterwards. - execute("au BufReadPre *.gz exe '!gzip -d ' . shellescape(expand('<afile>'))") - execute("au BufReadPre *.gz call rename(expand('<afile>:r'), expand('<afile>'))") - execute("au BufReadPost *.gz call rename(expand('<afile>'), expand('<afile>:r'))") - execute("au BufReadPost *.gz exe '!gzip ' . shellescape(expand('<afile>:r'))") + feed_command("au BufReadPre *.gz exe '!gzip -d ' . shellescape(expand('<afile>'))") + feed_command("au BufReadPre *.gz call rename(expand('<afile>:r'), expand('<afile>'))") + feed_command("au BufReadPost *.gz call rename(expand('<afile>'), expand('<afile>:r'))") + feed_command("au BufReadPost *.gz exe '!gzip ' . shellescape(expand('<afile>:r'))") -- Edit compressed file. - execute('e! Xtestfile.gz') + feed_command('e! Xtestfile.gz') -- Discard all prompts and messages. feed('<C-L>') -- Expect the decompressed file in the buffer. @@ -96,11 +96,11 @@ describe('file reading, writing and bufnew and filter autocommands', function() it('FileReadPre, FileReadPost', function() prepare_gz_file('Xtestfile', text1) - execute('au! FileReadPre *.gz exe "silent !gzip -d " . shellescape(expand("<afile>"))') - execute('au FileReadPre *.gz call rename(expand("<afile>:r"), expand("<afile>"))') - execute("au! FileReadPost *.gz '[,']s/l/L/") + feed_command('au! FileReadPre *.gz exe "silent !gzip -d " . shellescape(expand("<afile>"))') + feed_command('au FileReadPre *.gz call rename(expand("<afile>:r"), expand("<afile>"))') + feed_command("au! FileReadPost *.gz '[,']s/l/L/") -- Read compressed file. - execute('$r Xtestfile.gz') + feed_command('$r Xtestfile.gz') -- Discard all prompts and messages. feed('<C-L>') expect([[ @@ -121,17 +121,17 @@ describe('file reading, writing and bufnew and filter autocommands', function() end it('FileAppendPre, FileAppendPost', function() - execute('au BufNewFile *.c read Xtest.c') + feed_command('au BufNewFile *.c read Xtest.c') -- Will load Xtest.c. - execute('e! foo.c') - execute("au FileAppendPre *.out '[,']s/new/NEW/") - execute('au FileAppendPost *.out !cat Xtest.c >>test.out') + feed_command('e! foo.c') + feed_command("au FileAppendPre *.out '[,']s/new/NEW/") + feed_command('au FileAppendPost *.out !cat Xtest.c >>test.out') -- Append it to the output file. - execute('w>>test.out') + feed_command('w>>test.out') -- Discard all prompts and messages. feed('<C-L>') -- Expect the decompressed file in the buffer. - execute('e test.out') + feed_command('e test.out') expect([[ /* @@ -166,18 +166,18 @@ describe('file reading, writing and bufnew and filter autocommands', function() * Here is a new .c file */]])) -- Need temp files here. - execute('set shelltemp') - execute('au FilterReadPre *.out call rename(expand("<afile>"), expand("<afile>") . ".t")') - execute('au FilterReadPre *.out exe "silent !sed s/e/E/ " . shellescape(expand("<afile>")) . ".t >" . shellescape(expand("<afile>"))') - execute('au FilterReadPre *.out exe "silent !rm " . shellescape(expand("<afile>")) . ".t"') - execute("au FilterReadPost *.out '[,']s/x/X/g") + feed_command('set shelltemp') + feed_command('au FilterReadPre *.out call rename(expand("<afile>"), expand("<afile>") . ".t")') + feed_command('au FilterReadPre *.out exe "silent !sed s/e/E/ " . shellescape(expand("<afile>")) . ".t >" . shellescape(expand("<afile>"))') + feed_command('au FilterReadPre *.out exe "silent !rm " . shellescape(expand("<afile>")) . ".t"') + feed_command("au FilterReadPost *.out '[,']s/x/X/g") -- Edit the output file. - execute('e! test.out') - execute('23,$!cat') + feed_command('e! test.out') + feed_command('23,$!cat') -- Discard all prompts and messages. feed('<C-L>') -- Remove CR for when sed adds them. - execute([[23,$s/\r$//]]) + feed_command([[23,$s/\r$//]]) expect([[ startstart start of testfile diff --git a/test/functional/legacy/012_directory_spec.lua b/test/functional/legacy/012_directory_spec.lua index cef31ae405..cec4f93737 100644 --- a/test/functional/legacy/012_directory_spec.lua +++ b/test/functional/legacy/012_directory_spec.lua @@ -3,12 +3,19 @@ -- - "./dir", in directory relative to file -- - "dir", in directory relative to current dir -local helpers = require('test.functional.helpers')(after_each) -local lfs = require('lfs') -local insert, eq = helpers.insert, helpers.eq -local neq, eval = helpers.neq, helpers.eval -local clear, execute = helpers.clear, helpers.execute -local wait, write_file = helpers.wait, helpers.write_file +local helpers = require('test.functional.helpers')(after_each) +local lfs = require('lfs') + +local eq = helpers.eq +local neq = helpers.neq +local wait = helpers.wait +local funcs = helpers.funcs +local meths = helpers.meths +local clear = helpers.clear +local insert = helpers.insert +local command = helpers.command +local write_file = helpers.write_file +local curbufmeths = helpers.curbufmeths local function ls_dir_sorted(dirname) local files = {} @@ -36,7 +43,7 @@ describe("'directory' option", function() clear() end) teardown(function() - execute('qall!') + command('qall!') helpers.rmdir('Xtest.je') helpers.rmdir('Xtest2') os.remove('Xtest1') @@ -49,21 +56,22 @@ describe("'directory' option", function() line 3 Abcdefghij end of testfile]]) - execute('set swapfile') - execute('set dir=.,~') + meths.set_option('swapfile', true) + curbufmeths.set_option('swapfile', true) + meths.set_option('directory', '.') -- sanity check: files should not exist yet. eq(nil, lfs.attributes('.Xtest1.swp')) - execute('e! Xtest1') + command('edit! Xtest1') wait() - eq('Xtest1', eval('buffer_name("%")')) + eq('Xtest1', funcs.buffer_name('%')) -- Verify that the swapfile exists. In the legacy test this was done by -- reading the output from :!ls. neq(nil, lfs.attributes('.Xtest1.swp')) - execute('set dir=./Xtest2,.,~') - execute('e Xtest1') + meths.set_option('directory', './Xtest2,.') + command('edit Xtest1') wait() -- swapfile should no longer exist in CWD. @@ -71,9 +79,9 @@ describe("'directory' option", function() eq({ "Xtest1.swp", "Xtest3" }, ls_dir_sorted("Xtest2")) - execute('set dir=Xtest.je,~') - execute('e Xtest2/Xtest3') - eq(1, eval('&swapfile')) + meths.set_option('directory', 'Xtest.je') + command('edit Xtest2/Xtest3') + eq(true, curbufmeths.get_option('swapfile')) wait() eq({ "Xtest3" }, ls_dir_sorted("Xtest2")) diff --git a/test/functional/legacy/015_alignment_spec.lua b/test/functional/legacy/015_alignment_spec.lua index 48d4042ff2..8423aa3d11 100644 --- a/test/functional/legacy/015_alignment_spec.lua +++ b/test/functional/legacy/015_alignment_spec.lua @@ -4,7 +4,7 @@ local helpers = require('test.functional.helpers')(after_each) local feed, insert = helpers.feed, helpers.insert -local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect +local clear, feed_command, expect = helpers.clear, helpers.feed_command, helpers.expect describe('alignment', function() setup(clear) @@ -19,7 +19,7 @@ describe('alignment', function() asdfa a xasdfa a asxxdfa a - + test for :center a a fa afd asdf @@ -28,7 +28,7 @@ describe('alignment', function() asdfa a xasdfa asdfasdfasdfasdfasdf asxxdfa a - + test for :right a a fa a @@ -111,34 +111,34 @@ describe('alignment', function() asxxdfa axxxoikey asxa;ofa axxxoikey asdfaqwer axxxoikey - + xxxxx xx xxxxxx xxxxxxx xxxxxxxxx xxx xxxx xxxxx xxxxx xxx xx xxxxxxxxxxxxxxxxxx xxxxx xxxx, xxxx xxxx xxxx xxxx xxx xx xx xx xxxxxxx. xxxx xxxx. - + > xx xx, xxxx xxxx xxx xxxx xxx xxxxx xxx xxx xxxxxxx xxx xxxxx > xxxxxx xxxxxxx: xxxx xxxxxxx, xx xxxxxx xxxx xxxxxxxxxx - + aa aa aa aa bb bb bb bb cc cc cc cc]]) - execute('set tw=65') + feed_command('set tw=65') feed([[:/^\s*test for :left/,/^\s*test for :center/ left<cr>]]) feed([[:/^\s*test for :center/,/^\s*test for :right/ center<cr>]]) feed([[:/^\s*test for :right/,/^xxx/-1 right<cr>]]) - execute('set fo+=tcroql tw=72') + feed_command('set fo+=tcroql tw=72') feed('/xxxxxxxx$<cr>') feed('0gq6kk<cr>') -- Undo/redo here to make the next undo only work on the following changes. feed('u<cr>') - execute('map gg :.,.+2s/^/x/<CR>kk:set tw=3<CR>gqq') - execute('/^aa') + feed_command('map gg :.,.+2s/^/x/<CR>kk:set tw=3<CR>gqq') + feed_command('/^aa') feed('ggu<cr>') -- Assert buffer contents. @@ -151,7 +151,7 @@ describe('alignment', function() asdfa a xasdfa a asxxdfa a - + test for :center a a fa afd asdf @@ -160,7 +160,7 @@ describe('alignment', function() asdfa a xasdfa asdfasdfasdfasdfasdf asxxdfa a - + test for :right a a fa a @@ -243,14 +243,14 @@ describe('alignment', function() asxxdfa axxxoikey asxa;ofa axxxoikey asdfaqwer axxxoikey - + xxxxx xx xxxxxx xxxxxxx xxxxxxxxx xxx xxxx xxxxx xxxxx xxx xx xxxxxxxxxxxxxxxxxx xxxxx xxxx, xxxx xxxx xxxx xxxx xxx xx xx xx xxxxxxx. xxxx xxxx. - + > xx xx, xxxx xxxx xxx xxxx xxx xxxxx xxx xxx xxxxxxx xxx xxxxx xxxxxx > xxxxxxx: xxxx xxxxxxx, xx xxxxxx xxxx xxxxxxxxxx - + aa aa aa aa bb bb bb bb cc cc cc cc]]) diff --git a/test/functional/legacy/018_unset_smart_indenting_spec.lua b/test/functional/legacy/018_unset_smart_indenting_spec.lua index ba1eac02cb..94fbb283f4 100644 --- a/test/functional/legacy/018_unset_smart_indenting_spec.lua +++ b/test/functional/legacy/018_unset_smart_indenting_spec.lua @@ -1,11 +1,15 @@ -- Tests for not doing smart indenting when it isn't set. local helpers = require('test.functional.helpers')(after_each) -local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local execute, expect = helpers.execute, helpers.expect + +local feed = helpers.feed +local clear = helpers.clear +local insert = helpers.insert +local expect = helpers.expect +local feed_command = helpers.feed_command describe('unset smart indenting', function() - setup(clear) + before_each(clear) it('is working', function() insert([[ @@ -15,8 +19,8 @@ describe('unset smart indenting', function() test text test text]]) - execute('set nocin nosi ai') - execute('/some') + feed_command('set nocin nosi ai') + feed_command('/some') feed('2cc#test<Esc>') expect([[ diff --git a/test/functional/legacy/019_smarttab_expandtab_spec.lua b/test/functional/legacy/019_smarttab_expandtab_spec.lua index 2287a9f786..ecb24885bb 100644 --- a/test/functional/legacy/019_smarttab_expandtab_spec.lua +++ b/test/functional/legacy/019_smarttab_expandtab_spec.lua @@ -3,7 +3,7 @@ local helpers = require('test.functional.helpers')(after_each) local feed, insert = helpers.feed, helpers.insert -local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect +local clear, feed_command, expect = helpers.clear, helpers.feed_command, helpers.expect describe([[performing "r<Tab>" with 'smarttab' and 'expandtab' set/not set, and "dv_"]], function() setup(clear) @@ -19,24 +19,24 @@ describe([[performing "r<Tab>" with 'smarttab' and 'expandtab' set/not set, and test text Second line beginning with whitespace]]) - execute('set smarttab expandtab ts=8 sw=4') + feed_command('set smarttab expandtab ts=8 sw=4') -- Make sure that backspace works, no matter what termcap is used. - execute('set t_kD=x7f t_kb=x08') + feed_command('set t_kD=x7f t_kb=x08') - execute('/some') + feed_command('/some') feed('r ') - execute('set noexpandtab') - execute('/other') + feed_command('set noexpandtab') + feed_command('/other') feed('r <cr>') -- Test replacing with Tabs and then backspacing to undo it. feed('0wR <bs><bs><bs><esc><cr>') -- Test replacing with Tabs. feed('0wR <esc><cr>') -- Test that copyindent works with expandtab set. - execute('set expandtab smartindent copyindent ts=8 sw=8 sts=8') + feed_command('set expandtab smartindent copyindent ts=8 sw=8 sts=8') feed('o{<cr>x<esc>') - execute('set nosol') - execute('/Second line/') + feed_command('set nosol') + feed_command('/Second line/') -- Test "dv_" feed('fwdv_') diff --git a/test/functional/legacy/020_blockwise_visual_spec.lua b/test/functional/legacy/020_blockwise_visual_spec.lua index 660348a792..8d90b1c77d 100644 --- a/test/functional/legacy/020_blockwise_visual_spec.lua +++ b/test/functional/legacy/020_blockwise_visual_spec.lua @@ -1,11 +1,10 @@ --- vim: set foldmethod=marker foldmarker=[[,]] : -- Tests Blockwise Visual when there are TABs before the text. -- First test for undo working properly when executing commands from a register. -- Also test this in an empty buffer. local helpers = require('test.functional.helpers')(after_each) local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local execute, expect = helpers.execute, helpers.expect +local feed_command, expect = helpers.feed_command, helpers.expect describe('blockwise visual', function() setup(clear) @@ -26,15 +25,15 @@ Ox jAy kdd]]) feed(":let @a = 'Ox<C-v><Esc>jAy<C-v><Esc>kdd'<cr>") feed('G0k@au') - execute('new') + feed_command('new') feed('@auY') - execute('quit') + feed_command('quit') feed('GP') - execute('/start here') + feed_command('/start here') feed('"by$<C-v>jjlld') - execute('/456') + feed_command('/456') feed('<C-v>jj"bP') - execute('$-3,$d') + feed_command('$-3,$d') expect([[ 123start here56 diff --git a/test/functional/legacy/021_control_wi_spec.lua b/test/functional/legacy/021_control_wi_spec.lua index 787a384fca..87d9deed7a 100644 --- a/test/functional/legacy/021_control_wi_spec.lua +++ b/test/functional/legacy/021_control_wi_spec.lua @@ -1,9 +1,8 @@ --- vim: set foldmethod=marker foldmarker=[[,]] : -- Tests for [ CTRL-I with a count and CTRL-W CTRL-I with a count local helpers = require('test.functional.helpers')(after_each) local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local execute, expect = helpers.execute, helpers.expect +local feed_command, expect = helpers.feed_command, helpers.expect describe('CTRL-W CTRL-I', function() setup(clear) @@ -20,18 +19,18 @@ describe('CTRL-W CTRL-I', function() test text]]) -- Search for the second occurence of start and append to register - execute('/start') + feed_command('/start') feed('2[<C-i>') - execute('yank A') + feed_command('yank A') -- Same as above but using different keystrokes. feed('?start<cr>') feed('2<C-w><Tab>') - execute('yank A') + feed_command('yank A') -- Clean buffer and put register feed('ggdG"ap') - execute('1d') + feed_command('1d') -- The buffer should now contain: expect([[ diff --git a/test/functional/legacy/022_line_ending_spec.lua b/test/functional/legacy/022_line_ending_spec.lua index 092440bb16..fb4b782011 100644 --- a/test/functional/legacy/022_line_ending_spec.lua +++ b/test/functional/legacy/022_line_ending_spec.lua @@ -2,7 +2,7 @@ local helpers = require('test.functional.helpers')(after_each) local clear, feed = helpers.clear, helpers.feed -local execute, expect = helpers.execute, helpers.expect +local feed_command, expect = helpers.feed_command, helpers.expect describe('line ending', function() setup(clear) @@ -14,8 +14,8 @@ describe('line ending', function() this one does<C-V><C-M> and the last one doesn't]], '<ESC>') - execute('set ta tx') - execute('e!') + feed_command('set ta tx') + feed_command('e!') expect("this lines ends in a\r\n".. "this one doesn't\n".. diff --git a/test/functional/legacy/023_edit_arguments_spec.lua b/test/functional/legacy/023_edit_arguments_spec.lua index 95ab983d24..e705397a2b 100644 --- a/test/functional/legacy/023_edit_arguments_spec.lua +++ b/test/functional/legacy/023_edit_arguments_spec.lua @@ -2,7 +2,8 @@ local helpers = require('test.functional.helpers')(after_each) local clear, insert = helpers.clear, helpers.insert -local execute, expect = helpers.execute, helpers.expect +local command, expect = helpers.command, helpers.expect +local wait = helpers.wait describe(':edit', function() setup(clear) @@ -12,31 +13,32 @@ describe(':edit', function() The result should be in Xfile1: "fooPIPEbar", in Xfile2: "fooSLASHbar" foo|bar foo/bar]]) + wait() -- Prepare some test files - execute('$-1w! Xfile1') - execute('$w! Xfile2') - execute('w! Xfile0') + command('$-1w! Xfile1') + command('$w! Xfile2') + command('w! Xfile0') -- Open Xfile using '+' range - execute('edit +1 Xfile1') - execute('s/|/PIPE/') - execute('yank A') - execute('w! Xfile1') + command('edit +1 Xfile1') + command('s/|/PIPE/') + command('yank A') + command('w! Xfile1') -- Open Xfile2 using '|' range - execute('edit Xfile2|1') - execute("s/\\//SLASH/") - execute('yank A') - execute('w! Xfile2') + command('edit Xfile2|1') + command("s/\\//SLASH/") + command('yank A') + command('w! Xfile2') -- Clean first buffer and put @a - execute('bf') - execute('%d') - execute('0put a') + command('bf') + command('%d') + command('0put a') -- Remove empty line - execute('$d') + command('$d') -- The buffer should now contain expect([[ diff --git a/test/functional/legacy/025_jump_tag_hidden_spec.lua b/test/functional/legacy/025_jump_tag_hidden_spec.lua index 99224f9e08..0d51b4da26 100644 --- a/test/functional/legacy/025_jump_tag_hidden_spec.lua +++ b/test/functional/legacy/025_jump_tag_hidden_spec.lua @@ -3,7 +3,7 @@ local helpers = require('test.functional.helpers')(after_each) local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local execute, expect = helpers.execute, helpers.expect +local feed_command, expect = helpers.feed_command, helpers.expect if helpers.pending_win32(pending) then return end @@ -21,30 +21,30 @@ describe('jump to a tag with hidden set', function() SECTION_OFF]]) - execute('w! Xxx') - execute('set hidden') + feed_command('w! Xxx') + feed_command('set hidden') -- Create a link from test25.dir to the current directory. - execute('!rm -f test25.dir') - execute('!ln -s . test25.dir') + feed_command('!rm -f test25.dir') + feed_command('!ln -s . test25.dir') -- Create tags.text, with the current directory name inserted. - execute('/tags line') - execute('r !pwd') + feed_command('/tags line') + feed_command('r !pwd') feed('d$/test<cr>') feed('hP:.w! tags.test<cr>') -- Try jumping to a tag in the current file, but with a path that contains a -- symbolic link. When wrong, this will give the ATTENTION message. The next -- space will then be eaten by hit-return, instead of moving the cursor to 'd'. - execute('set tags=tags.test') + feed_command('set tags=tags.test') feed('G<C-]> x:yank a<cr>') - execute('!rm -f Xxx test25.dir tags.test') + feed_command('!rm -f Xxx test25.dir tags.test') -- Put @a and remove empty line - execute('%d') - execute('0put a') - execute('$d') + feed_command('%d') + feed_command('0put a') + feed_command('$d') -- Assert buffer contents. expect("#efine SECTION_OFF 3") diff --git a/test/functional/legacy/026_execute_while_if_spec.lua b/test/functional/legacy/026_execute_while_if_spec.lua index 74ef34bb20..ea8abed7ae 100644 --- a/test/functional/legacy/026_execute_while_if_spec.lua +++ b/test/functional/legacy/026_execute_while_if_spec.lua @@ -1,9 +1,11 @@ -- Test for :execute, :while and :if local helpers = require('test.functional.helpers')(after_each) + local clear = helpers.clear -local execute, expect = helpers.execute, helpers.expect +local expect = helpers.expect local source = helpers.source +local command = helpers.command describe(':execute, :while and :if', function() setup(clear) @@ -37,7 +39,7 @@ describe(':execute, :while and :if', function() ]]) -- Remove empty line - execute('1d') + command('1d') -- Assert buffer contents. expect([[ diff --git a/test/functional/legacy/028_source_ctrl_v_spec.lua b/test/functional/legacy/028_source_ctrl_v_spec.lua index a8c43260be..fabf831341 100644 --- a/test/functional/legacy/028_source_ctrl_v_spec.lua +++ b/test/functional/legacy/028_source_ctrl_v_spec.lua @@ -2,7 +2,7 @@ local helpers = require('test.functional.helpers')(after_each) local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local execute, expect = helpers.execute, helpers.expect +local feed_command, expect = helpers.feed_command, helpers.expect describe('CTRL-V at the end of the line', function() setup(clear) @@ -24,8 +24,8 @@ describe('CTRL-V at the end of the line', function() feed(':%s/X/<C-v><C-v>/g<cr>') feed(':/firstline/+1,/lastline/-1w! Xtestfile<cr>') - execute('so Xtestfile') - execute('%d') + feed_command('so Xtestfile') + feed_command('%d') feed('Gmm__1<Esc><Esc>__2<Esc>__3<Esc><Esc>__4<Esc>__5<Esc>') feed(":'m,$s/<C-v><C-@>/0/g<cr>") diff --git a/test/functional/legacy/029_join_spec.lua b/test/functional/legacy/029_join_spec.lua index 7a183fcbec..460b9291bf 100644 --- a/test/functional/legacy/029_join_spec.lua +++ b/test/functional/legacy/029_join_spec.lua @@ -1,8 +1,12 @@ -- Test for joining lines with marks in them (and with 'joinspaces' set/reset) local helpers = require('test.functional.helpers')(after_each) -local feed, insert = helpers.feed, helpers.insert -local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect + +local feed = helpers.feed +local clear = helpers.clear +local insert = helpers.insert +local expect = helpers.expect +local feed_command = helpers.feed_command describe('joining lines', function() before_each(clear) @@ -46,19 +50,19 @@ describe('joining lines', function() -- Switch off 'joinspaces', then join some lines in the buffer using "J". -- Also set a few marks and record their movement when joining lines. - execute('set nojoinspaces') - execute('/firstline/') + feed_command('set nojoinspaces') + feed_command('/firstline/') feed('j"td/^$/<cr>') feed('PJjJjJjJjJjJjJjJjJjJjJjJjJjJ') feed('j05lmx2j06lmy2k4Jy3l$p`xyl$p`yy2l$p') -- Do the same with 'joinspaces' on. - execute('set joinspaces') + feed_command('set joinspaces') feed('j"tp') feed('JjJjJjJjJjJjJjJjJjJjJjJjJjJ') feed('j05lmx2j06lmy2k4Jy3l$p`xyl$p`yy2l$po<esc>') - execute('1d') + feed_command('1d') expect([[ asdfasdf. asdf @@ -129,20 +133,20 @@ describe('joining lines', function() } ]]) - execute('/^{/+1') - execute('set comments=s1:/*,mb:*,ex:*/,://') - execute('set nojoinspaces') - execute('set backspace=eol,start') + feed_command('/^{/+1') + feed_command('set comments=s1:/*,mb:*,ex:*/,://') + feed_command('set nojoinspaces') + feed_command('set backspace=eol,start') -- With 'joinspaces' switched off, join lines using both "J" and :join and -- verify that comment leaders are stripped or kept as appropriate. - execute('.,+3join') + feed_command('.,+3join') feed('j4J<cr>') - execute('.,+2join') + feed_command('.,+2join') feed('j3J<cr>') - execute('.,+2join') + feed_command('.,+2join') feed('j3J<cr>') - execute('.,+2join') + feed_command('.,+2join') feed('jj3J<cr>') expect([[ @@ -180,22 +184,22 @@ describe('joining lines', function() -- As mentioned above, we mimic the wrong initial cursor position in the old -- test by advancing one line further. - execute([[/^\d\+ this]], '+1') + feed_command([[/^\d\+ this]], '+1') -- Test with the default 'backspace' setting. feed('Avim1<c-u><esc><cr>') feed('Avim2<c-g>u<c-u><esc><cr>') - execute('set cpo-=<') - execute('inoremap <c-u> <left><c-u>') + feed_command('set cpo-=<') + feed_command('inoremap <c-u> <left><c-u>') feed('Avim3<c-u><esc><cr>') - execute('iunmap <c-u>') + feed_command('iunmap <c-u>') feed('Avim4<c-u><c-u><esc><cr>') -- Test with 'backspace' set to the compatible setting. - execute('set backspace=') + feed_command('set backspace=') feed('A vim5<esc>A<c-u><c-u><esc><cr>') feed('A vim6<esc>Azwei<c-g>u<c-u><esc><cr>') - execute('inoremap <c-u> <left><c-u>') + feed_command('inoremap <c-u> <left><c-u>') feed('A vim7<c-u><c-u><esc><cr>') expect([[ @@ -283,29 +287,29 @@ describe('joining lines', function() } ]]) - execute('/^{/+1') - execute([[set comments=sO:*\ -,mO:*\ \ ,exO:*/]]) - execute('set comments+=s1:/*,mb:*,ex:*/,://') - execute('set comments+=s1:>#,mb:#,ex:#<,:<') - execute('set backspace=eol,start') + feed_command('/^{/+1') + feed_command([[set comments=sO:*\ -,mO:*\ \ ,exO:*/]]) + feed_command('set comments+=s1:/*,mb:*,ex:*/,://') + feed_command('set comments+=s1:>#,mb:#,ex:#<,:<') + feed_command('set backspace=eol,start') -- With 'joinspaces' on (the default setting), again join lines and verify -- that comment leaders are stripped or kept as appropriate. - execute('.,+3join') + feed_command('.,+3join') feed('j4J<cr>') - execute('.,+8join') + feed_command('.,+8join') feed('j9J<cr>') - execute('.,+2join') + feed_command('.,+2join') feed('j3J<cr>') - execute('.,+2join') + feed_command('.,+2join') feed('j3J<cr>') - execute('.,+2join') + feed_command('.,+2join') feed('jj3J<cr>') feed('j') - execute('.,+2join') + feed_command('.,+2join') feed('jj3J<cr>') feed('j') - execute('.,+5join') + feed_command('.,+5join') feed('j6J<cr>') feed('oSome code!<cr>// Make sure backspacing does not remove this comment leader.<esc>0i<bs><esc>') diff --git a/test/functional/legacy/030_fileformats_spec.lua b/test/functional/legacy/030_fileformats_spec.lua index 5fd78b2c59..7384fdf847 100644 --- a/test/functional/legacy/030_fileformats_spec.lua +++ b/test/functional/legacy/030_fileformats_spec.lua @@ -1,8 +1,9 @@ -- Test for a lot of variations of the 'fileformats' option local helpers = require('test.functional.helpers')(after_each) -local feed, clear, execute = helpers.feed, helpers.clear, helpers.execute +local feed, clear, command = helpers.feed, helpers.clear, helpers.command local eq, write_file = helpers.eq, helpers.write_file +local wait = helpers.wait if helpers.pending_win32(pending) then return end @@ -45,198 +46,214 @@ describe('fileformats option', function() it('is working', function() -- Try reading and writing with 'fileformats' empty. - execute('set fileformats=') - execute('set fileformat=unix') - execute('e! XXUnix') - execute('w! test.out') - execute('e! XXDos') - execute('w! XXtt01') - execute('e! XXMac') - execute('w! XXtt02') - execute('bwipe XXUnix XXDos XXMac') - execute('set fileformat=dos') - execute('e! XXUnix') - execute('w! XXtt11') - execute('e! XXDos') - execute('w! XXtt12') - execute('e! XXMac') - execute('w! XXtt13') - execute('bwipe XXUnix XXDos XXMac') - execute('set fileformat=mac') - execute('e! XXUnix') - execute('w! XXtt21') - execute('e! XXDos') - execute('w! XXtt22') - execute('e! XXMac') - execute('w! XXtt23') - execute('bwipe XXUnix XXDos XXMac') + command('set fileformats=') + command('set fileformat=unix') + command('e! XXUnix') + command('w! test.out') + command('e! XXDos') + command('w! XXtt01') + command('e! XXMac') + command('w! XXtt02') + command('bwipe XXUnix XXDos XXMac') + command('set fileformat=dos') + command('e! XXUnix') + command('w! XXtt11') + command('e! XXDos') + command('w! XXtt12') + command('e! XXMac') + command('w! XXtt13') + command('bwipe XXUnix XXDos XXMac') + command('set fileformat=mac') + command('e! XXUnix') + command('w! XXtt21') + command('e! XXDos') + command('w! XXtt22') + command('e! XXMac') + command('w! XXtt23') + command('bwipe XXUnix XXDos XXMac') -- Try reading and writing with 'fileformats' set to one format. - execute('set fileformats=unix') - execute('e! XXUxDsMc') - execute('w! XXtt31') - execute('bwipe XXUxDsMc') - execute('set fileformats=dos') - execute('e! XXUxDsMc') - execute('w! XXtt32') - execute('bwipe XXUxDsMc') - execute('set fileformats=mac') - execute('e! XXUxDsMc') - execute('w! XXtt33') - execute('bwipe XXUxDsMc') + command('set fileformats=unix') + command('e! XXUxDsMc') + command('w! XXtt31') + command('bwipe XXUxDsMc') + command('set fileformats=dos') + command('e! XXUxDsMc') + command('w! XXtt32') + command('bwipe XXUxDsMc') + command('set fileformats=mac') + command('e! XXUxDsMc') + command('w! XXtt33') + command('bwipe XXUxDsMc') -- Try reading and writing with 'fileformats' set to two formats. - execute('set fileformats=unix,dos') - execute('e! XXUxDsMc') - execute('w! XXtt41') - execute('bwipe XXUxDsMc') - execute('e! XXUxMac') - execute('w! XXtt42') - execute('bwipe XXUxMac') - execute('e! XXDosMac') - execute('w! XXtt43') - execute('bwipe XXDosMac') - execute('set fileformats=unix,mac') - execute('e! XXUxDs') - execute('w! XXtt51') - execute('bwipe XXUxDs') - execute('e! XXUxDsMc') - execute('w! XXtt52') - execute('bwipe XXUxDsMc') - execute('e! XXDosMac') - execute('w! XXtt53') - execute('bwipe XXDosMac') - execute('e! XXEol') + command('set fileformats=unix,dos') + command('e! XXUxDsMc') + command('w! XXtt41') + command('bwipe XXUxDsMc') + command('e! XXUxMac') + command('w! XXtt42') + command('bwipe XXUxMac') + command('e! XXDosMac') + command('w! XXtt43') + command('bwipe XXDosMac') + command('set fileformats=unix,mac') + command('e! XXUxDs') + command('w! XXtt51') + command('bwipe XXUxDs') + command('e! XXUxDsMc') + command('w! XXtt52') + command('bwipe XXUxDsMc') + command('e! XXDosMac') + command('w! XXtt53') + command('bwipe XXDosMac') + command('e! XXEol') feed('ggO<C-R>=&ffs<CR>:<C-R>=&ff<CR><ESC>') - execute('w! XXtt54') - execute('bwipe XXEol') - execute('set fileformats=dos,mac') - execute('e! XXUxDs') - execute('w! XXtt61') - execute('bwipe XXUxDs') - execute('e! XXUxMac') + wait() + command('w! XXtt54') + command('bwipeout! XXEol') + command('set fileformats=dos,mac') + command('e! XXUxDs') + command('w! XXtt61') + command('bwipe XXUxDs') + command('e! XXUxMac') feed('ggO<C-R>=&ffs<CR>:<C-R>=&ff<CR><ESC>') - execute('w! XXtt62') - execute('bwipe XXUxMac') - execute('e! XXUxDsMc') - execute('w! XXtt63') - execute('bwipe XXUxDsMc') - execute('e! XXMacEol') + wait() + command('w! XXtt62') + command('bwipeout! XXUxMac') + command('e! XXUxDsMc') + command('w! XXtt63') + command('bwipe XXUxDsMc') + command('e! XXMacEol') feed('ggO<C-R>=&ffs<CR>:<C-R>=&ff<CR><ESC>') - execute('w! XXtt64') - execute('bwipe XXMacEol') + wait() + command('w! XXtt64') + command('bwipeout! XXMacEol') -- Try reading and writing with 'fileformats' set to three formats. - execute('set fileformats=unix,dos,mac') - execute('e! XXUxDsMc') - execute('w! XXtt71') - execute('bwipe XXUxDsMc') - execute('e! XXEol') + command('set fileformats=unix,dos,mac') + command('e! XXUxDsMc') + command('w! XXtt71') + command('bwipe XXUxDsMc') + command('e! XXEol') feed('ggO<C-R>=&ffs<CR>:<C-R>=&ff<CR><ESC>') - execute('w! XXtt72') - execute('bwipe XXEol') - execute('set fileformats=mac,dos,unix') - execute('e! XXUxDsMc') - execute('w! XXtt81') - execute('bwipe XXUxDsMc') - execute('e! XXEol') + wait() + command('w! XXtt72') + command('bwipeout! XXEol') + command('set fileformats=mac,dos,unix') + command('e! XXUxDsMc') + command('w! XXtt81') + command('bwipe XXUxDsMc') + command('e! XXEol') feed('ggO<C-R>=&ffs<CR>:<C-R>=&ff<CR><ESC>') - execute('w! XXtt82') - execute('bwipe XXEol') + wait() + command('w! XXtt82') + command('bwipeout! XXEol') -- Try with 'binary' set. - execute('set fileformats=mac,unix,dos') - execute('set binary') - execute('e! XXUxDsMc') - execute('w! XXtt91') - execute('bwipe XXUxDsMc') - execute('set fileformats=mac') - execute('e! XXUxDsMc') - execute('w! XXtt92') - execute('bwipe XXUxDsMc') - execute('set fileformats=dos') - execute('e! XXUxDsMc') - execute('w! XXtt93') + command('set fileformats=mac,unix,dos') + command('set binary') + command('e! XXUxDsMc') + command('w! XXtt91') + command('bwipe XXUxDsMc') + command('set fileformats=mac') + command('e! XXUxDsMc') + command('w! XXtt92') + command('bwipe XXUxDsMc') + command('set fileformats=dos') + command('e! XXUxDsMc') + command('w! XXtt93') -- Append "END" to each file so that we can see what the last written -- char was. - execute('set fileformat=unix nobin') + command('set fileformat=unix nobin') feed('ggdGaEND<esc>') - execute('w >>XXtt01') - execute('w >>XXtt02') - execute('w >>XXtt11') - execute('w >>XXtt12') - execute('w >>XXtt13') - execute('w >>XXtt21') - execute('w >>XXtt22') - execute('w >>XXtt23') - execute('w >>XXtt31') - execute('w >>XXtt32') - execute('w >>XXtt33') - execute('w >>XXtt41') - execute('w >>XXtt42') - execute('w >>XXtt43') - execute('w >>XXtt51') - execute('w >>XXtt52') - execute('w >>XXtt53') - execute('w >>XXtt54') - execute('w >>XXtt61') - execute('w >>XXtt62') - execute('w >>XXtt63') - execute('w >>XXtt64') - execute('w >>XXtt71') - execute('w >>XXtt72') - execute('w >>XXtt81') - execute('w >>XXtt82') - execute('w >>XXtt91') - execute('w >>XXtt92') - execute('w >>XXtt93') + wait() + command('w >>XXtt01') + command('w >>XXtt02') + command('w >>XXtt11') + command('w >>XXtt12') + command('w >>XXtt13') + command('w >>XXtt21') + command('w >>XXtt22') + command('w >>XXtt23') + command('w >>XXtt31') + command('w >>XXtt32') + command('w >>XXtt33') + command('w >>XXtt41') + command('w >>XXtt42') + command('w >>XXtt43') + command('w >>XXtt51') + command('w >>XXtt52') + command('w >>XXtt53') + command('w >>XXtt54') + command('w >>XXtt61') + command('w >>XXtt62') + command('w >>XXtt63') + command('w >>XXtt64') + command('w >>XXtt71') + command('w >>XXtt72') + command('w >>XXtt81') + command('w >>XXtt82') + command('w >>XXtt91') + command('w >>XXtt92') + command('w >>XXtt93') -- Concatenate the results. -- Make fileformat of test.out the native fileformat. -- Add a newline at the end. - execute('set binary') - execute('e! test.out') - execute('$r XXtt01') - execute('$r XXtt02') + command('set binary') + command('e! test.out') + command('$r XXtt01') + command('$r XXtt02') feed('Go1<esc>') - execute('$r XXtt11') - execute('$r XXtt12') - execute('$r XXtt13') + wait() + command('$r XXtt11') + command('$r XXtt12') + command('$r XXtt13') feed('Go2<esc>') - execute('$r XXtt21') - execute('$r XXtt22') - execute('$r XXtt23') + wait() + command('$r XXtt21') + command('$r XXtt22') + command('$r XXtt23') feed('Go3<esc>') - execute('$r XXtt31') - execute('$r XXtt32') - execute('$r XXtt33') + wait() + command('$r XXtt31') + command('$r XXtt32') + command('$r XXtt33') feed('Go4<esc>') - execute('$r XXtt41') - execute('$r XXtt42') - execute('$r XXtt43') + wait() + command('$r XXtt41') + command('$r XXtt42') + command('$r XXtt43') feed('Go5<esc>') - execute('$r XXtt51') - execute('$r XXtt52') - execute('$r XXtt53') - execute('$r XXtt54') + wait() + command('$r XXtt51') + command('$r XXtt52') + command('$r XXtt53') + command('$r XXtt54') feed('Go6<esc>') - execute('$r XXtt61') - execute('$r XXtt62') - execute('$r XXtt63') - execute('$r XXtt64') + wait() + command('$r XXtt61') + command('$r XXtt62') + command('$r XXtt63') + command('$r XXtt64') feed('Go7<esc>') - execute('$r XXtt71') - execute('$r XXtt72') + wait() + command('$r XXtt71') + command('$r XXtt72') feed('Go8<esc>') - execute('$r XXtt81') - execute('$r XXtt82') + wait() + command('$r XXtt81') + command('$r XXtt82') feed('Go9<esc>') - execute('$r XXtt91') - execute('$r XXtt92') - execute('$r XXtt93') + wait() + command('$r XXtt91') + command('$r XXtt92') + command('$r XXtt93') feed('Go10<esc>') - execute('$r XXUnix') - execute('set nobinary ff&') + wait() + command('$r XXUnix') + command('set nobinary ff&') -- Assert buffer contents. This has to be done manually as -- helpers.expect() calls helpers.dedent() which messes up the white space diff --git a/test/functional/legacy/031_close_commands_spec.lua b/test/functional/legacy/031_close_commands_spec.lua index d41eadaa00..64c67c9882 100644 --- a/test/functional/legacy/031_close_commands_spec.lua +++ b/test/functional/legacy/031_close_commands_spec.lua @@ -16,7 +16,7 @@ local clear = helpers.clear local source = helpers.source local insert = helpers.insert local expect = helpers.expect -local execute = helpers.execute +local feed_command = helpers.feed_command describe('Commands that close windows and/or buffers', function() local function cleanup() @@ -38,40 +38,40 @@ describe('Commands that close windows and/or buffers', function() feed('GA 1<Esc>:$w! Xtest1<CR>') feed('$r2:$w! Xtest2<CR>') feed('$r3:$w! Xtest3<CR>') - execute('n! Xtest1 Xtest2') + feed_command('n! Xtest1 Xtest2') feed('A 1<Esc>:set hidden<CR>') -- Test for working :n when hidden set - execute('n') + feed_command('n') expect('testtext 2') -- Test for failing :rew when hidden not set - execute('set nohidden') + feed_command('set nohidden') feed('A 2<Esc>:rew<CR>') expect('testtext 2 2') -- Test for working :rew when hidden set - execute('set hidden') - execute('rew') + feed_command('set hidden') + feed_command('rew') expect('testtext 1 1') -- Test for :all keeping a buffer when it's modified - execute('set nohidden') + feed_command('set nohidden') feed('A 1<Esc>:sp<CR>') - execute('n Xtest2 Xtest3') - execute('all') - execute('1wincmd w') + feed_command('n Xtest2 Xtest3') + feed_command('all') + feed_command('1wincmd w') expect('testtext 1 1 1') -- Test abandoning changed buffer, should be unloaded even when 'hidden' set - execute('set hidden') + feed_command('set hidden') feed('A 1<Esc>:q!<CR>') expect('testtext 2 2') - execute('unhide') + feed_command('unhide') expect('testtext 2 2') -- Test ":hide" hides anyway when 'hidden' not set - execute('set nohidden') + feed_command('set nohidden') feed('A 2<Esc>:hide<CR>') expect('testtext 3') @@ -80,42 +80,42 @@ describe('Commands that close windows and/or buffers', function() expect('testtext 3 3') -- Test ":edit" working in modified buffer when 'hidden' set - execute('set hidden') - execute('e Xtest1') + feed_command('set hidden') + feed_command('e Xtest1') expect('testtext 1') -- Test ":close" not hiding when 'hidden' not set in modified buffer - execute('sp Xtest3') - execute('set nohidden') + feed_command('sp Xtest3') + feed_command('set nohidden') feed('A 3<Esc>:close<CR>') expect('testtext 3 3 3') -- Test ":close!" does hide when 'hidden' not set in modified buffer feed('A 3<Esc>:close!<CR>') - execute('set nohidden') + feed_command('set nohidden') expect('testtext 1') -- Test ":all!" hides changed buffer - execute('sp Xtest4') + feed_command('sp Xtest4') feed('GA 4<Esc>:all!<CR>') - execute('1wincmd w') + feed_command('1wincmd w') expect('testtext 2 2 2') -- Test ":q!" and hidden buffer. - execute('bw! Xtest1 Xtest2 Xtest3 Xtest4') - execute('sp Xtest1') - execute('wincmd w') - execute('bw!') - execute('set modified') - execute('bot sp Xtest2') - execute('set modified') - execute('bot sp Xtest3') - execute('set modified') - execute('wincmd t') - execute('hide') - execute('q!') + feed_command('bw! Xtest1 Xtest2 Xtest3 Xtest4') + feed_command('sp Xtest1') + feed_command('wincmd w') + feed_command('bw!') + feed_command('set modified') + feed_command('bot sp Xtest2') + feed_command('set modified') + feed_command('bot sp Xtest3') + feed_command('set modified') + feed_command('wincmd t') + feed_command('hide') + feed_command('q!') expect('testtext 3') - execute('q!') + feed_command('q!') feed('<CR>') expect('testtext 1') source([[ diff --git a/test/functional/legacy/033_lisp_indent_spec.lua b/test/functional/legacy/033_lisp_indent_spec.lua index b4abb02ac2..2b79ee024b 100644 --- a/test/functional/legacy/033_lisp_indent_spec.lua +++ b/test/functional/legacy/033_lisp_indent_spec.lua @@ -1,10 +1,10 @@ --- vim: set foldmethod=marker foldmarker=[[,]] : -- Test for 'lisp' -- If the lisp feature is not enabled, this will fail! local helpers = require('test.functional.helpers')(after_each) local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local execute, expect = helpers.execute, helpers.expect +local command, expect = helpers.command, helpers.expect +local wait = helpers.wait describe('lisp indent', function() setup(clear) @@ -13,7 +13,7 @@ describe('lisp indent', function() insert([[ (defun html-file (base) (format nil "~(~A~).html" base)) - + (defmacro page (name title &rest body) (let ((ti (gensym))) `(with-open-file (*standard-output* @@ -26,29 +26,30 @@ describe('lisp indent', function() (as h2 (string-upcase ,ti))) (brs 3) ,@body)))) - + ;;; Utilities for generating links - + (defmacro with-link (dest &rest body) `(progn (format t "<a href=\"~A\">" (html-file ,dest)) ,@body (princ "</a>")))]]) - execute('set lisp') - execute('/^(defun') + command('set lisp') + command('/^(defun') feed('=G:/^(defun/,$yank A<cr>') + wait() -- Put @a and clean empty line - execute('%d') - execute('0put a') - execute('$d') + command('%d') + command('0put a') + command('$d') -- Assert buffer contents. expect([[ (defun html-file (base) (format nil "~(~A~).html" base)) - + (defmacro page (name title &rest body) (let ((ti (gensym))) `(with-open-file (*standard-output* @@ -61,9 +62,9 @@ describe('lisp indent', function() (as h2 (string-upcase ,ti))) (brs 3) ,@body)))) - + ;;; Utilities for generating links - + (defmacro with-link (dest &rest body) `(progn (format t "<a href=\"~A\">" (html-file ,dest)) diff --git a/test/functional/legacy/034_user_function_spec.lua b/test/functional/legacy/034_user_function_spec.lua index 38989cd982..0b7dfc4f0e 100644 --- a/test/functional/legacy/034_user_function_spec.lua +++ b/test/functional/legacy/034_user_function_spec.lua @@ -5,7 +5,7 @@ local helpers = require('test.functional.helpers')(after_each) local feed, insert, source = helpers.feed, helpers.insert, helpers.source -local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect +local clear, feed_command, expect = helpers.clear, helpers.feed_command, helpers.expect describe('user functions, expr-mappings, overwrite protected builtin functions and regression on calling expressions', function() setup(clear) @@ -72,19 +72,19 @@ describe('user functions, expr-mappings, overwrite protected builtin functions a feed('(one<cr>') feed('(two<cr>') feed('[(one again<esc>') - execute('call append(line("$"), max([1, 2, 3]))') - execute('call extend(g:, {"max": function("min")})') - execute('call append(line("$"), max([1, 2, 3]))') - execute('try') + feed_command('call append(line("$"), max([1, 2, 3]))') + feed_command('call extend(g:, {"max": function("min")})') + feed_command('call append(line("$"), max([1, 2, 3]))') + feed_command('try') -- Regression: the first line below used to throw "E110: Missing ')'" -- Second is here just to prove that this line is correct when not -- skipping rhs of &&. - execute([[ $put =(0&&(function('tr'))(1, 2, 3))]]) - execute([[ $put =(1&&(function('tr'))(1, 2, 3))]]) - execute('catch') - execute([[ $put ='!!! Unexpected exception:']]) - execute(' $put =v:exception') - execute('endtry') + feed_command([[ $put =(0&&(function('tr'))(1, 2, 3))]]) + feed_command([[ $put =(1&&(function('tr'))(1, 2, 3))]]) + feed_command('catch') + feed_command([[ $put ='!!! Unexpected exception:']]) + feed_command(' $put =v:exception') + feed_command('endtry') -- Assert buffer contents. expect([[ diff --git a/test/functional/legacy/035_increment_and_decrement_spec.lua b/test/functional/legacy/035_increment_and_decrement_spec.lua index 3b9f7a9d85..84eb9c0eee 100644 --- a/test/functional/legacy/035_increment_and_decrement_spec.lua +++ b/test/functional/legacy/035_increment_and_decrement_spec.lua @@ -3,7 +3,7 @@ local helpers = require('test.functional.helpers')(after_each) local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local execute, expect = helpers.execute, helpers.expect +local feed_command, expect = helpers.feed_command, helpers.expect describe('increment and decrement commands', function() setup(clear) @@ -19,25 +19,25 @@ describe('increment and decrement commands', function() -- Increment and decrement numbers in the first row, interpreting the -- numbers as decimal, octal or hexadecimal. - execute('set nrformats=bin,octal,hex', '1') + feed_command('set nrformats=bin,octal,hex', '1') feed('63l102ll64128$') -- For the second row, treat the numbers as decimal or octal. -- 0x100 should be interpreted as decimal 0, the character x, and decimal 100. - execute('set nrformats=octal', '2') + feed_command('set nrformats=octal', '2') feed('0w102l2w65129blx6lD') -- For the third row, treat the numbers as decimal or hexadecimal. -- 077 should be interpreted as decimal 77. - execute('set nrformats=hex', '3') + feed_command('set nrformats=hex', '3') feed('0101l257Txldt ') -- For the fourth row, interpret all numbers as decimal. - execute('set nrformats=', '4') + feed_command('set nrformats=', '4') feed('0200l100w78') -- For the last row, interpret as binary and hexadecimal. - execute('set nrformats=bin,hex', '5') + feed_command('set nrformats=bin,hex', '5') feed('010065l6432') expect([[ diff --git a/test/functional/legacy/036_regexp_character_classes_spec.lua b/test/functional/legacy/036_regexp_character_classes_spec.lua index 15287b9901..38e8145d1c 100644 --- a/test/functional/legacy/036_regexp_character_classes_spec.lua +++ b/test/functional/legacy/036_regexp_character_classes_spec.lua @@ -1,7 +1,7 @@ -- Test character classes in regexp using regexpengine 0, 1, 2. local helpers = require('test.functional.helpers')(after_each) -local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect +local clear, command, expect = helpers.clear, helpers.command, helpers.expect local source, write_file = helpers.source, helpers.write_file local function sixlines(text) @@ -14,7 +14,7 @@ end local function diff(text, nodedent) local fname = helpers.tmpname() - execute('w! '..fname) + command('w! '..fname) helpers.wait() local data = io.open(fname):read('*all') if nodedent then @@ -45,7 +45,7 @@ describe('character classes in regexp', function() end) before_each(function() clear() - execute('e test36.in') + command('e test36.in') end) teardown(function() os.remove('test36.in') @@ -275,4 +275,16 @@ describe('character classes in regexp', function() diff(sixlines(string.sub(punct1, 1)..digits..punct2..upper..punct3.. lower..punct4..ctrl2..iso_text)) end) + it('does not convert character class ranges to an incorrect class', function() + source([[ + 1 s/\%#=0[0-z]//g + 2 s/\%#=1[0-z]//g + 3 s/\%#=2[0-z]//g + 4 s/\%#=0[^0-z]//g + 5 s/\%#=1[^0-z]//g + 6 s/\%#=2[^0-z]//g + ]]) + diff(string.rep(ctrl1..punct1..punct4..ctrl2..iso_text..'\n', 3) + ..string.rep(digits..punct2..upper..punct3..lower..'\n', 3)) + end) end) diff --git a/test/functional/legacy/038_virtual_replace_spec.lua b/test/functional/legacy/038_virtual_replace_spec.lua index dcbc9c39f7..2dfc959a8c 100644 --- a/test/functional/legacy/038_virtual_replace_spec.lua +++ b/test/functional/legacy/038_virtual_replace_spec.lua @@ -2,31 +2,31 @@ local helpers = require('test.functional.helpers')(after_each) local feed = helpers.feed -local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect +local clear, feed_command, expect = helpers.clear, helpers.feed_command, helpers.expect describe('Virtual replace mode', function() setup(clear) it('is working', function() -- Make sure that backspace works, no matter what termcap is used. - execute('set t_kD=x7f t_kb=x08') + feed_command('set t_kD=x7f t_kb=x08') -- Use vi default for 'smarttab' - execute('set nosmarttab') + feed_command('set nosmarttab') feed('ggdGa<cr>') feed('abcdefghi<cr>') feed('jk<tab>lmn<cr>') feed('<Space><Space><Space><Space>opq<tab>rst<cr>') feed('<C-d>uvwxyz<cr>') feed('<esc>gg') - execute('set ai') - execute('set bs=2') + feed_command('set ai') + feed_command('set bs=2') feed('gR0<C-d> 1<cr>') feed('A<cr>') feed('BCDEFGHIJ<cr>') feed('<tab>KL<cr>') feed('MNO<cr>') feed('PQR<esc>G') - execute('ka') + feed_command('ka') feed('o0<C-d><cr>') feed('abcdefghi<cr>') feed('jk<tab>lmn<cr>') diff --git a/test/functional/legacy/039_visual_block_mode_commands_spec.lua b/test/functional/legacy/039_visual_block_mode_commands_spec.lua index 63335985cc..dffef50950 100644 --- a/test/functional/legacy/039_visual_block_mode_commands_spec.lua +++ b/test/functional/legacy/039_visual_block_mode_commands_spec.lua @@ -5,14 +5,14 @@ local helpers = require('test.functional.helpers')(after_each) local nvim, eq = helpers.meths, helpers.eq local insert, feed = helpers.insert, helpers.feed local clear, expect = helpers.clear, helpers.expect -local execute = helpers.execute +local feed_command = helpers.feed_command describe('Visual block mode', function() before_each(function() clear() - execute('set ts&vi sw&vi sts&vi noet') -- Vim compatible + feed_command('set ts&vi sw&vi sts&vi noet') -- Vim compatible end) it('should shift, insert, replace and change a block', function() @@ -55,9 +55,9 @@ describe('Visual block mode', function() cccc dddd]]) - execute('/^aa') + feed_command('/^aa') feed('l<C-v>jjjlllI<Right><Right> <ESC>') - execute('/xaaa$') + feed_command('/xaaa$') feed('<C-v>jjjI<lt>><Left>p<ESC>') expect([[ @@ -84,13 +84,13 @@ describe('Visual block mode', function() 4567]]) -- Test for Visual block was created with the last <C-v>$. - execute('/^A23$/') + feed_command('/^A23$/') feed('l<C-v>j$Aab<ESC>') -- Test for Visual block was created with the middle <C-v>$ (1). - execute('/^B23$/') + feed_command('/^B23$/') feed('l<C-v>j$hAab<ESC>') -- Test for Visual block was created with the middle <C-v>$ (2). - execute('/^C23$/') + feed_command('/^C23$/') feed('l<C-v>j$hhAab<ESC>') expect([[ @@ -112,8 +112,8 @@ describe('Visual block mode', function() ]]) -- Test for Visual block insert when virtualedit=all and utf-8 encoding. - execute('set ve=all') - execute('/\t\tline') + feed_command('set ve=all') + feed_command('/\t\tline') feed('07l<C-v>jjIx<ESC>') expect([[ @@ -199,10 +199,10 @@ describe('Visual block mode', function() 98765]]) -- Test cursor position. When virtualedit=block and Visual block mode and $gj. - execute('set ve=block') + feed_command('set ve=block') feed('G2l') feed('2k<C-v>$gj<ESC>') - execute([[let cpos=getpos("'>")]]) + feed_command([[let cpos=getpos("'>")]]) local cpos = nvim.get_var('cpos') local expected = { col = 4, @@ -223,7 +223,7 @@ describe('Visual block mode', function() #define BO_CRSR 0x0004]]) -- Block_insert when replacing spaces in front of the block with tabs. - execute('set ts=8 sts=4 sw=4') + feed_command('set ts=8 sts=4 sw=4') feed('ggf0<C-v>2jI<TAB><ESC>') expect([[ diff --git a/test/functional/legacy/041_writing_and_reading_hundred_kbyte_spec.lua b/test/functional/legacy/041_writing_and_reading_hundred_kbyte_spec.lua index b6451eb720..b526d82519 100644 --- a/test/functional/legacy/041_writing_and_reading_hundred_kbyte_spec.lua +++ b/test/functional/legacy/041_writing_and_reading_hundred_kbyte_spec.lua @@ -1,8 +1,10 @@ -- Test for writing and reading a file of over 100 Kbyte local helpers = require('test.functional.helpers')(after_each) + local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local execute, expect = helpers.execute, helpers.expect +local command, expect = helpers.command, helpers.expect +local wait = helpers.wait describe('writing and reading a file of over 100 Kbyte', function() setup(clear) @@ -16,17 +18,18 @@ describe('writing and reading a file of over 100 Kbyte', function() This is the end]]) feed('kY3000p2GY3000p') + wait() - execute('w! test.out') - execute('%d') - execute('e! test.out') - execute('yank A') - execute('3003yank A') - execute('6005yank A') - execute('%d') - execute('0put a') - execute('$d') - execute('w!') + command('w! test.out') + command('%d') + command('e! test.out') + command('yank A') + command('3003yank A') + command('6005yank A') + command('%d') + command('0put a') + command('$d') + command('w!') expect([[ This is the start diff --git a/test/functional/legacy/043_magic_settings_spec.lua b/test/functional/legacy/043_magic_settings_spec.lua index f174751de2..a88ccc2b42 100644 --- a/test/functional/legacy/043_magic_settings_spec.lua +++ b/test/functional/legacy/043_magic_settings_spec.lua @@ -1,9 +1,8 @@ --- vim: set foldmethod=marker foldmarker=[[,]] : -- Tests for regexp with various magic settings. local helpers = require('test.functional.helpers')(after_each) local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local execute, expect = helpers.execute, helpers.expect +local feed_command, expect = helpers.feed_command, helpers.expect describe('regexp with magic settings', function() setup(clear) @@ -21,27 +20,27 @@ describe('regexp with magic settings', function() 9 foobar ]]) - execute('/^1') - execute([[/a*b\{2}c\+/e]]) + feed_command('/^1') + feed_command([[/a*b\{2}c\+/e]]) feed([[x/\Md\*e\{2}f\+/e<cr>]]) feed('x:set nomagic<cr>') - execute([[/g\*h\{2}i\+/e]]) + feed_command([[/g\*h\{2}i\+/e]]) feed([[x/\mj*k\{2}l\+/e<cr>]]) feed([[x/\vm*n{2}o+/e<cr>]]) feed([[x/\V^aa$<cr>]]) feed('x:set magic<cr>') - execute([[/\v(a)(b)\2\1\1/e]]) + feed_command([[/\v(a)(b)\2\1\1/e]]) feed([[x/\V[ab]\(\[xy]\)\1<cr>]]) feed('x:$<cr>') - execute('set undolevels=100') + feed_command('set undolevels=100') feed('dv?bar?<cr>') feed('Yup:<cr>') - execute('?^1?,$yank A') + feed_command('?^1?,$yank A') -- Put @a and clean empty line - execute('%d') - execute('0put a') - execute('$d') + feed_command('%d') + feed_command('0put a') + feed_command('$d') -- Assert buffer contents. expect([[ diff --git a/test/functional/legacy/044_099_regexp_multibyte_magic_spec.lua b/test/functional/legacy/044_099_regexp_multibyte_magic_spec.lua index c6883e4902..074ee094b4 100644 --- a/test/functional/legacy/044_099_regexp_multibyte_magic_spec.lua +++ b/test/functional/legacy/044_099_regexp_multibyte_magic_spec.lua @@ -5,7 +5,7 @@ local helpers = require('test.functional.helpers')(after_each) local feed, insert = helpers.feed, helpers.insert -local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect +local clear, feed_command, expect = helpers.clear, helpers.feed_command, helpers.expect -- Runs the test protocol with the given 'regexpengine' setting. In the old test -- suite the test protocol was duplicated in test44 and test99, the only @@ -32,19 +32,19 @@ local function run_test_with_regexpengine(regexpengine) k combinations l รค รถ รผ ฮฑฬฬฬ]]) - execute('set re=' .. regexpengine) + feed_command('set re=' .. regexpengine) -- Lines 1-8. Exercise regexp search with various magic settings. On each -- line the character on which the cursor is expected to land is deleted. feed('/^1<cr>') feed([[/a*b\{2}c\+/e<cr>x]]) feed([[/\Md\*e\{2}f\+/e<cr>x]]) - execute('set nomagic') + feed_command('set nomagic') feed([[/g\*h\{2}i\+/e<cr>x]]) feed([[/\mj*k\{2}l\+/e<cr>x]]) feed([[/\vm*n{2}o+/e<cr>x]]) feed([[/\V^aa$<cr>x]]) - execute('set magic') + feed_command('set magic') feed([[/\v(a)(b)\2\1\1/e<cr>x]]) feed([[/\V[ab]\(\[xy]\)\1<cr>x]]) @@ -57,7 +57,7 @@ local function run_test_with_regexpengine(regexpengine) -- Line b. Find word by change of word class. -- (The "<" character in this test step seemed to confuse our "feed" test -- helper, which is why we've resorted to "execute" here.) - execute([[/ใก\<ใซใจ\>ใฏ]]) + feed_command([[/ใก\<ใซใจ\>ใฏ]]) feed('x') -- Lines c-i. Test \%u, [\u], and friends. @@ -73,28 +73,28 @@ local function run_test_with_regexpengine(regexpengine) -- Line k. Test substitution with combining characters by executing register -- contents. - execute([[let @w=':%s#comb[i]nations#ลฬแนฃฬmฬฅฬฮฑฬฬฬ#g']]) - execute('@w') + feed_command([[let @w=':%s#comb[i]nations#ลฬแนฃฬmฬฅฬฮฑฬฬฬ#g']]) + feed_command('@w') -- Line l. Ex command ":s/ \?/ /g" should NOT split multi-byte characters -- into bytes (fixed by vim-7.3.192). - execute([[/^l]]) - execute([[s/ \?/ /g]]) + feed_command([[/^l]]) + feed_command([[s/ \?/ /g]]) -- Additional tests. Test matchstr() with multi-byte characters. feed('G') - execute([[put =matchstr(\"ืืืื\", \".\", 0, 2)]]) -- ื - execute([[put =matchstr(\"ืืืื\", \"..\", 0, 2)]]) -- ืื - execute([[put =matchstr(\"ืืืื\", \".\", 0, 0)]]) -- ื - execute([[put =matchstr(\"ืืืื\", \".\", 4, -1)]]) -- ื + feed_command([[put =matchstr(\"ืืืื\", \".\", 0, 2)]]) -- ื + feed_command([[put =matchstr(\"ืืืื\", \"..\", 0, 2)]]) -- ืื + feed_command([[put =matchstr(\"ืืืื\", \".\", 0, 0)]]) -- ื + feed_command([[put =matchstr(\"ืืืื\", \".\", 4, -1)]]) -- ื -- Test that a search with "/e" offset wraps around at the end of the buffer. - execute('new') - execute([[$put =['dog(a', 'cat('] ]]) + feed_command('new') + feed_command([[$put =['dog(a', 'cat('] ]]) feed('/(/e+<cr>') feed('"ayn') - execute('bd!') - execute([[$put ='']]) + feed_command('bd!') + feed_command([[$put ='']]) feed('G"ap') -- Assert buffer contents. diff --git a/test/functional/legacy/045_folding_spec.lua b/test/functional/legacy/045_folding_spec.lua index cefd7c0d42..6ca1176aea 100644 --- a/test/functional/legacy/045_folding_spec.lua +++ b/test/functional/legacy/045_folding_spec.lua @@ -1,135 +1,212 @@ -- Tests for folding. +local Screen = require('test.functional.ui.screen') local helpers = require('test.functional.helpers')(after_each) -local feed, insert, clear, execute, expect = - helpers.feed, helpers.insert, helpers.clear, helpers.execute, helpers.expect +local feed, insert, feed_command, expect_any = + helpers.feed, helpers.insert, helpers.feed_command, helpers.expect_any describe('folding', function() - before_each(clear) + local screen - it('is working', function() + before_each(function() + helpers.clear() + + screen = Screen.new(20, 8) + screen:attach() + end) + after_each(function() + screen:detach() + end) + + it('creation, opening, moving (to the end) and closing', function() insert([[ 1 aa 2 bb 3 cc - 4 dd {{{ - 5 ee {{{ }}} - 6 ff }}} - 7 gg - 8 hh - 9 ii - a jj - b kk - last]]) + last + ]]) -- Basic test if a fold can be created, opened, moving to the end and -- closed. - execute('/^1') + feed_command('1') feed('zf2j') - execute('call append("$", "manual " . getline(foldclosed(".")))') + feed_command('call append("$", "manual " . getline(foldclosed(".")))') feed('zo') - execute('call append("$", foldclosed("."))') + feed_command('call append("$", foldclosed("."))') feed(']z') - execute('call append("$", getline("."))') + feed_command('call append("$", getline("."))') feed('zc') - execute('call append("$", getline(foldclosed(".")))') - -- Test folding with markers. - execute('set fdm=marker fdl=1 fdc=3') - execute('/^5') - execute('call append("$", "marker " . foldlevel("."))') + feed_command('call append("$", getline(foldclosed(".")))') + + expect_any([[ + manual 1 aa + -1 + 3 cc + 1 aa]]) + end) + + it("foldmethod=marker", function() + screen:try_resize(20, 10) + insert([[ + dd {{{ + ee {{{ }}} + ff }}} + ]]) + feed_command('set fdm=marker fdl=1') + feed_command('2') + feed_command('call append("$", "line 2 foldlevel=" . foldlevel("."))') feed('[z') - execute('call append("$", foldlevel("."))') - feed('jo{{ <esc>r{jj') - execute('call append("$", foldlevel("."))') + feed_command('call append("$", foldlevel("."))') + feed('jo{{ <esc>r{jj') -- writes '{{{' and moves 2 lines bot + feed_command('call append("$", foldlevel("."))') feed('kYpj') - execute('call append("$", foldlevel("."))') - -- Test folding with indent. - execute('set fdm=indent sw=2') - execute('/^2 b') - feed('i <esc>jI <esc>') - execute('call append("$", "indent " . foldlevel("."))') - feed('k') - execute('call append("$", foldlevel("."))') - -- Test syntax folding. - execute('set fdm=syntax fdl=0') - execute('syn region Hup start="dd" end="ii" fold contains=Fd1,Fd2,Fd3') - execute('syn region Fd1 start="ee" end="ff" fold contained') - execute('syn region Fd2 start="gg" end="hh" fold contained') - execute('syn region Fd3 start="commentstart" end="commentend" fold contained') + feed_command('call append("$", foldlevel("."))') + + helpers.wait() + screen:expect([[ + dd {{{ | + ee {{{ }}} | + {{{ | + ff }}} | + ff }}} | + ^ | + line 2 foldlevel=2 | + 1 | + 1 | + | + ]]) + + end) + + it("foldmethod=indent", function() + screen:try_resize(20, 8) + feed_command('set fdm=indent sw=2') + insert([[ + aa + bb + cc + last + ]]) + feed_command('call append("$", "foldlevel line3=" . foldlevel(3))') + feed_command('call append("$", foldlevel(2))') + feed('zR') + + helpers.wait() + screen:expect([[ + aa | + bb | + cc | + last | + ^ | + foldlevel line3=2 | + 1 | + | + ]]) + end) + + it("foldmethod=syntax", function() + screen:try_resize(35, 15) + insert([[ + 1 aa + 2 bb + 3 cc + 4 dd {{{ + 5 ee {{{ }}} + 6 ff }}} + 7 gg + 8 hh + 9 ii + a jj + b kk + last]]) + feed_command('set fdm=syntax fdl=0') + feed_command('syn region Hup start="dd" end="ii" fold contains=Fd1,Fd2,Fd3') + feed_command('syn region Fd1 start="ee" end="ff" fold contained') + feed_command('syn region Fd2 start="gg" end="hh" fold contained') + feed_command('syn region Fd3 start="commentstart" end="commentend" fold contained') feed('Gzk') - execute('call append("$", "folding " . getline("."))') + feed_command('call append("$", "folding " . getline("."))') feed('k') - execute('call append("$", getline("."))') + feed_command('call append("$", getline("."))') feed('jAcommentstart <esc>Acommentend<esc>') - execute('set fdl=1') + feed_command('set fdl=1') feed('3j') - execute('call append("$", getline("."))') - execute('set fdl=0') - feed('zO<C-L>j') - execute('call append("$", getline("."))') - -- Test expression folding. - execute('fun Flvl()') - execute(' let l = getline(v:lnum)') - execute(' if l =~ "bb$"') - execute(' return 2') - execute(' elseif l =~ "gg$"') - execute(' return "s1"') - execute(' elseif l =~ "ii$"') - execute(' return ">2"') - execute(' elseif l =~ "kk$"') - execute(' return "0"') - execute(' endif') - execute(' return "="') - execute('endfun') - execute('set fdm=expr fde=Flvl()') - execute('/bb$') - execute('call append("$", "expr " . foldlevel("."))') - execute('/hh$') - execute('call append("$", foldlevel("."))') - execute('/ii$') - execute('call append("$", foldlevel("."))') - execute('/kk$') - execute('call append("$", foldlevel("."))') - execute('0,/^last/delete') - execute('delfun Flvl') - - -- Assert buffer contents. - expect([[ - manual 1 aa - -1 + feed_command('call append("$", getline("."))') + feed_command('set fdl=0') + feed('zO<C-L>j') -- <C-L> redraws screen + feed_command('call append("$", getline("."))') + feed_command('set fdl=0') + expect_any([[ + folding 9 ii 3 cc + 9 ii + a jj]]) + end) + + it("foldmethod=expression", function() + insert([[ 1 aa - marker 2 - 1 - 1 - 0 - indent 2 - 1 - folding 9 ii - 3 cc + 2 bb + 3 cc + 4 dd {{{ + 5 ee {{{ }}} + 6 ff }}} 7 gg 8 hh + 9 ii + a jj + b kk + last ]]) + + feed_command([[ + fun Flvl() + let l = getline(v:lnum) + if l =~ "bb$" + return 2 + elseif l =~ "gg$" + return "s1" + elseif l =~ "ii$" + return ">2" + elseif l =~ "kk$" + return "0" + endif + return "=" + endfun + ]]) + feed_command('set fdm=expr fde=Flvl()') + feed_command('/bb$') + feed_command('call append("$", "expr " . foldlevel("."))') + feed_command('/hh$') + feed_command('call append("$", foldlevel("."))') + feed_command('/ii$') + feed_command('call append("$", foldlevel("."))') + feed_command('/kk$') + feed_command('call append("$", foldlevel("."))') + + expect_any([[ expr 2 1 2 0]]) end) - it('can open after :move', function() + it('can be opened after :move', function() + -- luacheck: ignore + screen:try_resize(35, 8) insert([[ Test fdm=indent and :move bug END line2 Test fdm=indent START line3 line4]]) - - execute('set noai nosta') - execute('set fdm=indent') - execute('1m1') + feed_command('set noai nosta ') + feed_command('set fdm=indent') + feed_command('1m1') feed('2jzc') - execute('m0') + feed_command('m0') + feed('zR') - expect([[ + expect_any([[ Test fdm=indent START line3 line4 @@ -137,3 +214,4 @@ describe('folding', function() line2]]) end) end) + diff --git a/test/functional/legacy/051_highlight_spec.lua b/test/functional/legacy/051_highlight_spec.lua index ef392d8c67..2ef74196ee 100644 --- a/test/functional/legacy/051_highlight_spec.lua +++ b/test/functional/legacy/051_highlight_spec.lua @@ -1,11 +1,12 @@ --- vim: set foldmethod=marker foldmarker=[[,]] : -- Tests for ":highlight". local Screen = require('test.functional.ui.screen') local helpers = require('test.functional.helpers')(after_each) local clear, feed = helpers.clear, helpers.feed -local execute, expect = helpers.execute, helpers.expect +local command, expect = helpers.command, helpers.expect +local eq = helpers.eq local wait = helpers.wait +local exc_exec = helpers.exc_exec if helpers.pending_win32(pending) then return end @@ -16,7 +17,8 @@ describe(':highlight', function() local screen = Screen.new(35, 10) screen:attach() -- Basic test if ":highlight" doesn't crash - execute('highlight') + command('set more') + feed(':highlight<CR>') -- FIXME(tarruda): We need to be sure the prompt is displayed before -- continuing, or risk a race condition where some of the following input -- is discarded resulting in test failure @@ -34,65 +36,52 @@ describe(':highlight', function() ]]) feed('q') wait() -- wait until we're back to normal - execute('hi Search') + command('hi Search') + command('hi Normal') -- Test setting colors. -- Test clearing one color and all doesn't generate error or warning - execute('hi NewGroup cterm=italic ctermfg=DarkBlue ctermbg=Grey gui=NONE guifg=#00ff00 guibg=Cyan') - execute('hi Group2 cterm=NONE') - execute('hi Group3 cterm=bold') - execute('redir! @a') - execute('hi NewGroup') - execute('hi Group2') - execute('hi Group3') - execute('hi clear NewGroup') - execute('hi NewGroup') - execute('hi Group2') - execute('hi Group2 NONE') - execute('hi Group2') - execute('hi clear') - execute('hi Group3') - execute([[hi Crash cterm='asdf]]) - execute('redir END') + command('hi NewGroup cterm=italic ctermfg=DarkBlue ctermbg=Grey gui=NONE guifg=#00ff00 guibg=Cyan') + command('hi Group2 cterm=NONE') + command('hi Group3 cterm=bold') + command('redir! @a') + command('hi NewGroup') + command('hi Group2') + command('hi Group3') + command('hi clear NewGroup') + command('hi NewGroup') + command('hi Group2') + command('hi Group2 NONE') + command('hi Group2') + command('hi clear') + command('hi Group3') + eq('Vim(highlight):E475: Invalid argument: cterm=\'asdf', + exc_exec([[hi Crash cterm='asdf]])) + command('redir END') -- Filter ctermfg and ctermbg, the numbers depend on the terminal - execute('0put a') - execute([[%s/ctermfg=\d*/ctermfg=2/]]) - execute([[%s/ctermbg=\d*/ctermbg=3/]]) - - -- Filter out possibly translated error message - execute('%s/E475: [^:]*:/E475:/') + command('0put a') + command([[%s/ctermfg=\d*/ctermfg=2/]]) + command([[%s/ctermbg=\d*/ctermbg=3/]]) -- Fix the fileformat - execute('set ff&') - execute('$d') + command('set ff&') + command('$d') -- Assert buffer contents. expect([[ - - + NewGroup xxx cterm=italic ctermfg=2 ctermbg=3 guifg=#00ff00 guibg=Cyan - Group2 xxx cleared - Group3 xxx cterm=bold - - NewGroup xxx cleared - Group2 xxx cleared - - Group2 xxx cleared - - - Group3 xxx cleared - - E475: cterm='asdf]]) + Group3 xxx cleared]]) screen:detach() end) end) diff --git a/test/functional/legacy/054_buffer_local_autocommands_spec.lua b/test/functional/legacy/054_buffer_local_autocommands_spec.lua index 494ea8f927..c8b9dfa98f 100644 --- a/test/functional/legacy/054_buffer_local_autocommands_spec.lua +++ b/test/functional/legacy/054_buffer_local_autocommands_spec.lua @@ -1,33 +1,37 @@ -- Some tests for buffer-local autocommands local helpers = require('test.functional.helpers')(after_each) -local clear, execute, eq = helpers.clear, helpers.execute, helpers.eq -local curbuf_contents = helpers.curbuf_contents + +local clear = helpers.clear +local expect = helpers.expect +local command = helpers.command + +local fname = 'Xtest-functional-legacy-054' describe('BufLeave <buffer>', function() setup(clear) it('is working', function() - execute('w! xx') - execute('au BufLeave <buffer> norm Ibuffer-local autocommand') - execute('au BufLeave <buffer> update') - + command('write! ' .. fname) + command('autocmd BufLeave <buffer> normal! Ibuffer-local autocommand') + command('autocmd BufLeave <buffer> update') + -- Here, autocommand for xx shall append a line - -- But autocommand shall not apply to buffer named <buffer> - execute('e somefile') + -- But autocommand shall not apply to buffer named <buffer> + command('edit somefile') -- Here, autocommand shall be auto-deleted - execute('bwipe xx') - + command('bwipeout ' .. fname) + -- Nothing shall be written - execute('e xx') - execute('e somefile') - execute('e xx') + command('edit ' .. fname) + command('edit somefile') + command('edit ' .. fname) - eq('buffer-local autocommand', curbuf_contents()) + expect('buffer-local autocommand') end) teardown(function() - os.remove('xx') + os.remove(fname) end) end) diff --git a/test/functional/legacy/055_list_and_dict_types_spec.lua b/test/functional/legacy/055_list_and_dict_types_spec.lua index dbe9e1bc7f..e84c415eb0 100644 --- a/test/functional/legacy/055_list_and_dict_types_spec.lua +++ b/test/functional/legacy/055_list_and_dict_types_spec.lua @@ -2,7 +2,7 @@ local helpers = require('test.functional.helpers')(after_each) local feed, source = helpers.feed, helpers.source -local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect +local clear, feed_command, expect = helpers.clear, helpers.feed_command, helpers.expect describe('list and dictionary types', function() before_each(clear) @@ -20,7 +20,7 @@ describe('list and dictionary types', function() $put =v:exception[:14] endtry]]) expect([[ - + [1, 'as''d', [1, 2, function('strlen')], {'a': 1}] {'a': 1} 1 @@ -38,7 +38,7 @@ describe('list and dictionary types', function() $put =string(l[0:8]) $put =string(l[8:-1])]]) expect([=[ - + [1, 'as''d', [1, 2, function('strlen')], {'a': 1}] ['as''d', [1, 2, function('strlen')], {'a': 1}] [1, 'as''d', [1, 2, function('strlen')]] @@ -84,7 +84,7 @@ describe('list and dictionary types', function() call filter(d, 'v:key =~ ''[ac391]''') $put =string(d)]]) expect([[ - + {'1': 'asd', 'b': [1, 2, function('strlen')], '-1': {'a': 1}}asd ['-1', '1', 'b'] ['asd', [1, 2, function('strlen')], {'a': 1}] @@ -134,7 +134,7 @@ describe('list and dictionary types', function() unlet d[-1] $put =string(d)]]) expect([[ - + [1, 'as''d', {'a': 1}] [4] {'1': 99, '3': 33}]]) @@ -142,42 +142,42 @@ describe('list and dictionary types', function() it("removing items out of range: silently skip items that don't exist", function() -- We can not use source() here as we want to ignore all errors. - execute('lang C') - execute('let l = [0, 1, 2, 3]') - execute('unlet l[2:1]') - execute('$put =string(l)') - execute('let l = [0, 1, 2, 3]') - execute('unlet l[2:2]') - execute('$put =string(l)') - execute('let l = [0, 1, 2, 3]') - execute('unlet l[2:3]') - execute('$put =string(l)') - execute('let l = [0, 1, 2, 3]') - execute('unlet l[2:4]') - execute('$put =string(l)') - execute('let l = [0, 1, 2, 3]') - execute('unlet l[2:5]') - execute('$put =string(l)') - execute('let l = [0, 1, 2, 3]') - execute('unlet l[-1:2]') - execute('$put =string(l)') - execute('let l = [0, 1, 2, 3]') - execute('unlet l[-2:2]') - execute('$put =string(l)') - execute('let l = [0, 1, 2, 3]') - execute('unlet l[-3:2]') - execute('$put =string(l)') - execute('let l = [0, 1, 2, 3]') - execute('unlet l[-4:2]') - execute('$put =string(l)') - execute('let l = [0, 1, 2, 3]') - execute('unlet l[-5:2]') - execute('$put =string(l)') - execute('let l = [0, 1, 2, 3]') - execute('unlet l[-6:2]') - execute('$put =string(l)') + feed_command('lang C') + feed_command('let l = [0, 1, 2, 3]') + feed_command('unlet l[2:1]') + feed_command('$put =string(l)') + feed_command('let l = [0, 1, 2, 3]') + feed_command('unlet l[2:2]') + feed_command('$put =string(l)') + feed_command('let l = [0, 1, 2, 3]') + feed_command('unlet l[2:3]') + feed_command('$put =string(l)') + feed_command('let l = [0, 1, 2, 3]') + feed_command('unlet l[2:4]') + feed_command('$put =string(l)') + feed_command('let l = [0, 1, 2, 3]') + feed_command('unlet l[2:5]') + feed_command('$put =string(l)') + feed_command('let l = [0, 1, 2, 3]') + feed_command('unlet l[-1:2]') + feed_command('$put =string(l)') + feed_command('let l = [0, 1, 2, 3]') + feed_command('unlet l[-2:2]') + feed_command('$put =string(l)') + feed_command('let l = [0, 1, 2, 3]') + feed_command('unlet l[-3:2]') + feed_command('$put =string(l)') + feed_command('let l = [0, 1, 2, 3]') + feed_command('unlet l[-4:2]') + feed_command('$put =string(l)') + feed_command('let l = [0, 1, 2, 3]') + feed_command('unlet l[-5:2]') + feed_command('$put =string(l)') + feed_command('let l = [0, 1, 2, 3]') + feed_command('unlet l[-6:2]') + feed_command('$put =string(l)') expect([=[ - + [0, 1, 2, 3] [0, 1, 3] [0, 1] @@ -208,7 +208,7 @@ describe('list and dictionary types', function() $put =v:exception[:14] endtry]]) expect([[ - + 2 3 Vim(let):E687: @@ -257,7 +257,7 @@ describe('list and dictionary types', function() " Must be almost empty now. $put =string(d)]]) expect([[ - + 3000 2900 2001 1600 1501 Vim(let):E716: 1500 NONE 2999 @@ -277,7 +277,7 @@ describe('list and dictionary types', function() let Fn = dict.func call Fn('xxx')]]) expect([[ - + len: 3 again: 3 xxx3]]) @@ -324,7 +324,7 @@ describe('list and dictionary types', function() let l3 = deepcopy(l2) $put ='same list: ' . (l3[1] is l3[2])]]) expect([[ - + Vim(let):E698: same list: 1]]) end) @@ -394,7 +394,7 @@ describe('list and dictionary types', function() endfor endfor]=]) expect([[ - + depth is 0 0000-000 ppppppp @@ -499,7 +499,7 @@ describe('list and dictionary types', function() endfor endfor]=]) expect([[ - + depth is 0 0000-000 ppppppp @@ -647,7 +647,7 @@ describe('list and dictionary types', function() $put =string(l)]]) expect([=[ - + Locks and commands or functions: No :unlet after lock on dict: Vim(unlet):E741: @@ -676,7 +676,7 @@ describe('list and dictionary types', function() end) it('locked variables (part 2)', function() - execute( + feed_command( 'let l = [1, 2, 3, 4]', 'lockvar! l', '$put =string(l)', @@ -691,7 +691,7 @@ describe('list and dictionary types', function() 'let l[1:2] = [0, 1]', '$put =string(l)') expect([=[ - + [1, 2, 3, 4] [1, 2, 3, 4] [1, 2, 3, 4] @@ -708,7 +708,7 @@ describe('list and dictionary types', function() $put ='exists g:footest#x:'.exists('g:footest#x') $put ='g:footest#x: '.g:footest#x]]) expect([[ - + locked g:footest#x:-1 exists g:footest#x:0 g:footest#x: 1]]) @@ -749,9 +749,9 @@ describe('list and dictionary types', function() $put ='caught ' . v:exception endtry endfunction]]) - execute('call Test(1, 2, [3, 4], {5: 6})') + feed_command('call Test(1, 2, [3, 4], {5: 6})') expect([=[ - + caught a:000 caught a:000[0] caught a:000[2] @@ -779,7 +779,7 @@ describe('list and dictionary types', function() $put =string(sort(copy(l), 'i')) $put =string(sort(copy(l)))]=]) expect([=[ - + ['-0', 'A11', 2, 'xaaa', 4, 'foo', 'foo6', 'foo', [0, 1, 2], 'x8', [0, 1, 2], 1.5] [1.5, [0, 1, 2], 'x8', [0, 1, 2], 'foo', 'foo6', 'foo', 4, 'xaaa', 2, 2, 'A11', '-0'] [1.5, [0, 1, 2], 'x8', [0, 1, 2], 'foo', 'foo6', 'foo', 4, 'xaaa', 2, 2, 'A11', '-0'] @@ -805,7 +805,7 @@ describe('list and dictionary types', function() $put =string(split('abc', '\zs')) $put =string(split('abc', '\zs', 1))]]) expect([=[ - + ['aa', 'bb'] ['aa', 'bb'] ['', 'aa', 'bb', ''] @@ -827,7 +827,7 @@ describe('list and dictionary types', function() $put =(l != deepcopy(l)) $put =(d != deepcopy(d))]]) expect([[ - + 1 1 0 @@ -845,7 +845,7 @@ describe('list and dictionary types', function() $put =(l == lcopy) $put =(dict4 == dict4copy)]]) expect([[ - + 1 1]]) end) @@ -856,7 +856,7 @@ describe('list and dictionary types', function() call extend(l, l) $put =string(l)]]) expect([=[ - + [1, 2, 3, 4, 5, 1, 2, 3, 4, 5]]=]) end) @@ -866,7 +866,7 @@ describe('list and dictionary types', function() call extend(d, d) $put =string(d)]]) expect([[ - + {'a': {'b': 'B'}}]]) end) @@ -881,7 +881,7 @@ describe('list and dictionary types', function() endtry $put =string(d)]]) expect([[ - + Vim(call):E737: a {'a': {'b': 'B'}}]]) end) @@ -892,29 +892,29 @@ describe('list and dictionary types', function() let l[:] = [1, 2] $put =string(l)]]) expect([=[ - + [1, 2]]=]) end) it('vim patch 7.3.637', function() - execute('let a = "No error caught"') - execute('try') - execute(' foldopen') - execute('catch') - execute(" let a = matchstr(v:exception,'^[^ ]*')") - execute('endtry') + feed_command('let a = "No error caught"') + feed_command('try') + feed_command(' foldopen') + feed_command('catch') + feed_command(" let a = matchstr(v:exception,'^[^ ]*')") + feed_command('endtry') feed('o<C-R>=a<CR><esc>') - execute('lang C') - execute('redir => a') + feed_command('lang C') + feed_command('redir => a') -- The test failes if this is not in one line. - execute("try|foobar|catch|let a = matchstr(v:exception,'^[^ ]*')|endtry") - execute('redir END') + feed_command("try|foobar|catch|let a = matchstr(v:exception,'^[^ ]*')|endtry") + feed_command('redir END') feed('o<C-R>=a<CR><esc>') expect([[ - + Vim(foldopen):E490: - - + + Error detected while processing : E492: Not an editor command: foobar|catch|let a = matchstr(v:exception,'^[^ ]*')|endtry ]]) diff --git a/test/functional/legacy/057_sort_spec.lua b/test/functional/legacy/057_sort_spec.lua index 6984ad0de2..bdc2c9779c 100644 --- a/test/functional/legacy/057_sort_spec.lua +++ b/test/functional/legacy/057_sort_spec.lua @@ -1,9 +1,10 @@ -- Tests for :sort command. local helpers = require('test.functional.helpers')(after_each) -local insert, execute, clear, expect, eq, eval, source = helpers.insert, - helpers.execute, helpers.clear, helpers.expect, helpers.eq, helpers.eval, - helpers.source + +local insert, command, clear, expect, eq, wait = helpers.insert, + helpers.command, helpers.clear, helpers.expect, helpers.eq, helpers.wait +local exc_exec = helpers.exc_exec describe(':sort', function() local text = [[ @@ -26,9 +27,10 @@ describe(':sort', function() it('alphabetical', function() insert(text) - execute('sort') + wait() + command('sort') expect([[ - + 123b a a122 @@ -65,12 +67,13 @@ describe(':sort', function() b321 b321b ]]) - execute('sort n') + wait() + command('sort n') expect([[ abc ab a - + -24 x-22 0 @@ -89,9 +92,10 @@ describe(':sort', function() it('hexadecimal', function() insert(text) - execute('sort x') + wait() + command('sort x') expect([[ - + a ab abc @@ -110,9 +114,10 @@ describe(':sort', function() it('alphabetical, unique', function() insert(text) - execute('sort u') + wait() + command('sort u') expect([[ - + 123b a a122 @@ -130,7 +135,8 @@ describe(':sort', function() it('alphabetical, reverse', function() insert(text) - execute('sort!') + wait() + command('sort!') expect([[ c321d c123d @@ -151,7 +157,8 @@ describe(':sort', function() it('numerical, reverse', function() insert(text) - execute('sort! n') + wait() + command('sort! n') expect([[ b322b b321b @@ -164,7 +171,7 @@ describe(':sort', function() b123 a123 a122 - + a ab abc]]) @@ -172,7 +179,8 @@ describe(':sort', function() it('unique, reverse', function() insert(text) - execute('sort! u') + wait() + command('sort! u') expect([[ c321d c123d @@ -192,12 +200,13 @@ describe(':sort', function() it('octal', function() insert(text) - execute('sort o') + wait() + command('sort o') expect([[ abc ab a - + a122 a123 b123 @@ -213,7 +222,8 @@ describe(':sort', function() it('reverse, hexadecimal', function() insert(text) - execute('sort! x') + wait() + command('sort! x') expect([[ c321d c123d @@ -234,10 +244,11 @@ describe(':sort', function() it('alphabetical, skip first character', function() insert(text) - execute('sort/./') + wait() + command('sort/./') expect([[ a - + a122 a123 b123 @@ -255,11 +266,12 @@ describe(':sort', function() it('alphabetical, skip first 2 characters', function() insert(text) - execute('sort/../') + wait() + command('sort/../') expect([[ ab a - + a321 b321 b321 @@ -276,11 +288,12 @@ describe(':sort', function() it('alphabetical, unique, skip first 2 characters', function() insert(text) - execute('sort/../u') + wait() + command('sort/../u') expect([[ ab a - + a321 b321 b321b @@ -296,12 +309,13 @@ describe(':sort', function() it('numerical, skip first character', function() insert(text) - execute('sort/./n') + wait() + command('sort/./n') expect([[ abc ab a - + a122 a123 b123 @@ -317,9 +331,10 @@ describe(':sort', function() it('alphabetical, sort on first character', function() insert(text) - execute('sort/./r') + wait() + command('sort/./r') expect([[ - + 123b abc ab @@ -338,10 +353,11 @@ describe(':sort', function() it('alphabetical, sort on first 2 characters', function() insert(text) - execute('sort/../r') + wait() + command('sort/../r') expect([[ a - + 123b a123 a122 @@ -359,7 +375,8 @@ describe(':sort', function() it('numerical, sort on first character', function() insert(text) - execute('sort/./rn') + wait() + command('sort/./rn') expect([[ abc ab @@ -380,12 +397,13 @@ describe(':sort', function() it('alphabetical, skip past first digit', function() insert(text) - execute([[sort/\d/]]) + wait() + command([[sort/\d/]]) expect([[ abc ab a - + a321 b321 b321 @@ -401,12 +419,13 @@ describe(':sort', function() it('alphabetical, sort on first digit', function() insert(text) - execute([[sort/\d/r]]) + wait() + command([[sort/\d/r]]) expect([[ abc ab a - + a123 a122 b123 @@ -422,12 +441,13 @@ describe(':sort', function() it('numerical, skip past first digit', function() insert(text) - execute([[sort/\d/n]]) + wait() + command([[sort/\d/n]]) expect([[ abc ab a - + a321 b321 c321d @@ -443,12 +463,13 @@ describe(':sort', function() it('numerical, sort on first digit', function() insert(text) - execute([[sort/\d/rn]]) + wait() + command([[sort/\d/rn]]) expect([[ abc ab a - + a123 a122 b123 @@ -464,12 +485,13 @@ describe(':sort', function() it('alphabetical, skip past first 2 digits', function() insert(text) - execute([[sort/\d\d/]]) + wait() + command([[sort/\d\d/]]) expect([[ abc ab a - + a321 b321 b321 @@ -485,12 +507,13 @@ describe(':sort', function() it('numerical, skip past first 2 digits', function() insert(text) - execute([[sort/\d\d/n]]) + wait() + command([[sort/\d\d/n]]) expect([[ abc ab a - + a321 b321 c321d @@ -506,12 +529,13 @@ describe(':sort', function() it('hexadecimal, skip past first 2 digits', function() insert(text) - execute([[sort/\d\d/x]]) + wait() + command([[sort/\d\d/x]]) expect([[ abc ab a - + a321 b321 b321 @@ -527,12 +551,13 @@ describe(':sort', function() it('alpha, on first 2 digits', function() insert(text) - execute([[sort/\d\d/r]]) + wait() + command([[sort/\d\d/r]]) expect([[ abc ab a - + a123 a122 b123 @@ -548,12 +573,13 @@ describe(':sort', function() it('numeric, on first 2 digits', function() insert(text) - execute([[sort/\d\d/rn]]) + wait() + command([[sort/\d\d/rn]]) expect([[ abc ab a - + a123 a122 b123 @@ -569,12 +595,13 @@ describe(':sort', function() it('hexadecimal, on first 2 digits', function() insert(text) - execute([[sort/\d\d/rx]]) + wait() + command([[sort/\d\d/rx]]) expect([[ abc ab a - + a123 a122 b123 @@ -591,13 +618,7 @@ describe(':sort', function() it('fails with wrong arguments', function() insert(text) -- This should fail with "E474: Invalid argument". - source([[ - try - sort no - catch - let tmpvar = v:exception - endtry]]) - eq('Vim(sort):E474: Invalid argument', eval('tmpvar')) + eq('Vim(sort):E474: Invalid argument', exc_exec('sort no')) expect(text) end) @@ -617,7 +638,8 @@ describe(':sort', function() 0b100010 0b100100 0b100010]]) - execute([[sort b]]) + wait() + command([[sort b]]) expect([[ 0b000000 0b001000 @@ -651,7 +673,8 @@ describe(':sort', function() 0b101010 0b000000 b0b111000]]) - execute([[sort b]]) + wait() + command([[sort b]]) expect([[ 0b000000 a0b001000 @@ -677,7 +700,8 @@ describe(':sort', function() 1.15e-6 -1.1e3 -1.01e3]]) - execute([[sort f]]) + wait() + command([[sort f]]) expect([[ -1.1e3 -1.01e3 diff --git a/test/functional/legacy/059_utf8_spell_checking_spec.lua b/test/functional/legacy/059_utf8_spell_checking_spec.lua index 2fb8f3557d..120e469ab2 100644 --- a/test/functional/legacy/059_utf8_spell_checking_spec.lua +++ b/test/functional/legacy/059_utf8_spell_checking_spec.lua @@ -2,7 +2,7 @@ local helpers = require('test.functional.helpers')(after_each) local feed, insert, source = helpers.feed, helpers.insert, helpers.source -local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect +local clear, feed_command, expect = helpers.clear, helpers.feed_command, helpers.expect local write_file, call = helpers.write_file, helpers.call if helpers.pending_win32(pending) then return end @@ -15,44 +15,44 @@ end describe("spell checking with 'encoding' set to utf-8", function() setup(function() clear() - execute("syntax off") + feed_command("syntax off") write_latin1('Xtest1.aff',[[ SET ISO8859-1 TRY esianrtolcdugmphbyfvkwjkqxz-รซรฉรจรชรฏรฎรคร รขรถรผรป'ESIANRTOLCDUGMPHBYFVKWJKQXZ - + FOL ร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรธรนรบรปรผรฝรพรรฟ LOW ร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรธรนรบรปรผรฝรพรรฟ UPP รรรรรร
รรรรรรรรรรรรรรรรรรรรรรรรรรฟ - + SOFOFROM abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรธรนรบรปรผรฝรพรรฟรรรรรร
รรรรรรรรรรรรรรรรรรรรรรรรยฟ SOFOTO ebctefghejklnnepkrstevvkesebctefghejklnnepkrstevvkeseeeeeeeceeeeeeeedneeeeeeeeeeepseeeeeeeeceeeeeeeedneeeeeeeeeeep? - + MIDWORD '- - + KEP = RAR ? BAD ! - + PFX I N 1 PFX I 0 in . - + PFX O Y 1 PFX O 0 out . - + SFX S Y 2 SFX S 0 s [^s] SFX S 0 es s - + SFX N N 3 SFX N 0 en [^n] SFX N 0 nen n SFX N 0 n . - + REP 3 REP g ch REP ch g REP svp s.v.p. - + MAP 9 MAP aร รกรขรฃรครฅ MAP eรจรฉรชรซ @@ -79,39 +79,39 @@ describe("spell checking with 'encoding' set to utf-8", function() ]]) write_latin1('Xtest2.aff', [[ SET ISO8859-1 - + FOL ร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรธรนรบรปรผรฝรพรรฟ LOW ร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรธรนรบรปรผรฝรพรรฟ UPP รรรรรร
รรรรรรรรรรรรรรรรรรรรรรรรรรฟ - + PFXPOSTPONE - + MIDWORD '- - + KEP = RAR ? BAD ! - + PFX I N 1 PFX I 0 in . - + PFX O Y 1 PFX O 0 out [a-z] - + SFX S Y 2 SFX S 0 s [^s] SFX S 0 es s - + SFX N N 3 SFX N 0 en [^n] SFX N 0 nen n SFX N 0 n . - + REP 3 REP g ch REP ch g REP svp s.v.p. - + MAP 9 MAP aร รกรขรฃรครฅ MAP eรจรฉรชรซ @@ -125,7 +125,7 @@ describe("spell checking with 'encoding' set to utf-8", function() ]]) write_latin1('Xtest3.aff', [[ SET ISO8859-1 - + COMPOUNDMIN 3 COMPOUNDRULE m* NEEDCOMPOUND x @@ -139,21 +139,21 @@ describe("spell checking with 'encoding' set to utf-8", function() ]]) write_latin1('Xtest4.aff', [[ SET ISO8859-1 - + FOL ร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรธรนรบรปรผรฝรพรรฟ LOW ร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรธรนรบรปรผรฝรพรรฟ UPP รรรรรร
รรรรรรรรรรรรรรรรรรรรรรรรรรฟ - + COMPOUNDRULE m+ COMPOUNDRULE sm*e COMPOUNDRULE sm+ COMPOUNDMIN 3 COMPOUNDWORDMAX 3 COMPOUNDFORBIDFLAG t - + COMPOUNDSYLMAX 5 SYLLABLE aรกeรฉiรญoรณรถรตuรบรผรปy/aa/au/ea/ee/ei/ie/oa/oe/oo/ou/uu/ui - + MAP 9 MAP aร รกรขรฃรครฅ MAP eรจรฉรชรซ @@ -164,23 +164,23 @@ describe("spell checking with 'encoding' set to utf-8", function() MAP cรง MAP yรฟรฝ MAP sร - + NEEDAFFIX x - + PFXPOSTPONE - + MIDWORD '- - + SFX q N 1 SFX q 0 -ok . - + SFX a Y 2 SFX a 0 s . SFX a 0 ize/t . - + PFX p N 1 PFX p 0 pre . - + PFX P N 1 PFX P 0 nou . ]]) @@ -196,28 +196,28 @@ describe("spell checking with 'encoding' set to utf-8", function() ]]) write_latin1('Xtest5.aff', [[ SET ISO8859-1 - + FLAG long - + NEEDAFFIX !! - + COMPOUNDRULE ssmm*ee - + NEEDCOMPOUND xx COMPOUNDPERMITFLAG pp - + SFX 13 Y 1 SFX 13 0 bork . - + SFX a1 Y 1 SFX a1 0 a1 . - + SFX aรฉ Y 1 SFX aรฉ 0 aรฉ . - + PFX zz Y 1 PFX zz 0 pre/pp . - + PFX yy Y 1 PFX yy 0 nou . ]]) @@ -231,26 +231,26 @@ describe("spell checking with 'encoding' set to utf-8", function() ]]) write_latin1('Xtest6.aff', [[ SET ISO8859-1 - + FLAG caplong - + NEEDAFFIX A! - + COMPOUNDRULE sMm*Ee - + NEEDCOMPOUND Xx - + COMPOUNDPERMITFLAG p - + SFX N3 Y 1 SFX N3 0 bork . - + SFX A1 Y 1 SFX A1 0 a1 . - + SFX Aรฉ Y 1 SFX Aรฉ 0 aรฉ . - + PFX Zz Y 1 PFX Zz 0 pre/p . ]]) @@ -264,29 +264,29 @@ describe("spell checking with 'encoding' set to utf-8", function() ]]) write_latin1('Xtest7.aff', [[ SET ISO8859-1 - + FOL ร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรธรนรบรปรผรฝรพรรฟ LOW ร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรธรนรบรปรผรฝรพรรฟ UPP รรรรรร
รรรรรรรรรรรรรรรรรรรรรรรรรรฟ - + FLAG num - + NEEDAFFIX 9999 - + COMPOUNDRULE 2,77*123 - + NEEDCOMPOUND 1 COMPOUNDPERMITFLAG 432 - + SFX 61003 Y 1 SFX 61003 0 meat . - + SFX 391 Y 1 SFX 391 0 a1 . - + SFX 111 Y 1 SFX 111 0 aรฉ . - + PFX 17 Y 1 PFX 17 0 pre/432 . ]]) @@ -300,7 +300,7 @@ describe("spell checking with 'encoding' set to utf-8", function() ]]) write_latin1('Xtest8.aff', [[ SET ISO8859-1 - + NOSPLITSUGS ]]) write_latin1('Xtest8.dic', [[ @@ -319,37 +319,37 @@ describe("spell checking with 'encoding' set to utf-8", function() write_latin1('Xtest-sal.aff', [[ SET ISO8859-1 TRY esianrtolcdugmphbyfvkwjkqxz-รซรฉรจรชรฏรฎรคร รขรถรผรป'ESIANRTOLCDUGMPHBYFVKWJKQXZ - + FOL ร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรธรนรบรปรผรฝรพรรฟ LOW ร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรธรนรบรปรผรฝรพรรฟ UPP รรรรรร
รรรรรรรรรรรรรรรรรรรรรรรรรรฟ - + MIDWORD '- - + KEP = RAR ? BAD ! - + PFX I N 1 PFX I 0 in . - + PFX O Y 1 PFX O 0 out . - + SFX S Y 2 SFX S 0 s [^s] SFX S 0 es s - + SFX N N 3 SFX N 0 en [^n] SFX N 0 nen n SFX N 0 n . - + REP 3 REP g ch REP ch g REP svp s.v.p. - + MAP 9 MAP aร รกรขรฃรครฅ MAP eรจรฉรชรซ @@ -360,7 +360,7 @@ describe("spell checking with 'encoding' set to utf-8", function() MAP cรง MAP yรฟรฝ MAP sร - + SAL AH(AEIOUY)-^ *H SAL AR(AEIOUY)-^ *R SAL A(HR)^ * @@ -550,60 +550,60 @@ describe("spell checking with 'encoding' set to utf-8", function() 1good: wrong OK puts. Test the end bad: inputs comment ok Ok. test dรฉรดl end the badend - + test2: elequint test elekwint test elekwent asdf ]]) test_one(1, 1) - execute([[$put =soundfold('goobledygoook')]]) - execute([[$put =soundfold('kรณopรซrรฟnรดven')]]) - execute([[$put =soundfold('oeverloos gezwets edale')]]) + feed_command([[$put =soundfold('goobledygoook')]]) + feed_command([[$put =soundfold('kรณopรซrรฟnรดven')]]) + feed_command([[$put =soundfold('oeverloos gezwets edale')]]) -- And now with SAL instead of SOFO items; test automatic reloading. os.execute('cp -f Xtest-sal.aff Xtest.aff') - execute('mkspell! Xtest Xtest') - execute([[$put =soundfold('goobledygoook')]]) - execute([[$put =soundfold('kรณopรซrรฟnรดven')]]) - execute([[$put =soundfold('oeverloos gezwets edale')]]) + feed_command('mkspell! Xtest Xtest') + feed_command([[$put =soundfold('goobledygoook')]]) + feed_command([[$put =soundfold('kรณopรซrรฟnรดven')]]) + feed_command([[$put =soundfold('oeverloos gezwets edale')]]) -- Also use an addition file. - execute('mkspell! Xtest.utf-8.add.spl Xtest.utf-8.add') - execute('set spellfile=Xtest.utf-8.add') - execute('/^test2:') + feed_command('mkspell! Xtest.utf-8.add.spl Xtest.utf-8.add') + feed_command('set spellfile=Xtest.utf-8.add') + feed_command('/^test2:') feed(']s') - execute('let [str, a] = spellbadword()') - execute('$put =str') - execute('set spl=Xtest_us.utf-8.spl') - execute('/^test2:') + feed_command('let [str, a] = spellbadword()') + feed_command('$put =str') + feed_command('set spl=Xtest_us.utf-8.spl') + feed_command('/^test2:') feed(']smm') - execute('let [str, a] = spellbadword()') - execute('$put =str') + feed_command('let [str, a] = spellbadword()') + feed_command('$put =str') feed('`m]s') - execute('let [str, a] = spellbadword()') - execute('$put =str') - execute('set spl=Xtest_gb.utf-8.spl') - execute('/^test2:') + feed_command('let [str, a] = spellbadword()') + feed_command('$put =str') + feed_command('set spl=Xtest_gb.utf-8.spl') + feed_command('/^test2:') feed(']smm') - execute('let [str, a] = spellbadword()') - execute('$put =str') + feed_command('let [str, a] = spellbadword()') + feed_command('$put =str') feed('`m]s') - execute('let [str, a] = spellbadword()') - execute('$put =str') - execute('set spl=Xtest_nz.utf-8.spl') - execute('/^test2:') + feed_command('let [str, a] = spellbadword()') + feed_command('$put =str') + feed_command('set spl=Xtest_nz.utf-8.spl') + feed_command('/^test2:') feed(']smm') - execute('let [str, a] = spellbadword()') - execute('$put =str') + feed_command('let [str, a] = spellbadword()') + feed_command('$put =str') feed('`m]s') - execute('let [str, a] = spellbadword()') - execute('$put =str') - execute('set spl=Xtest_ca.utf-8.spl') - execute('/^test2:') + feed_command('let [str, a] = spellbadword()') + feed_command('$put =str') + feed_command('set spl=Xtest_ca.utf-8.spl') + feed_command('/^test2:') feed(']smm') - execute('let [str, a] = spellbadword()') - execute('$put =str') + feed_command('let [str, a] = spellbadword()') + feed_command('$put =str') feed('`m]s') - execute('let [str, a] = spellbadword()') - execute('$put =str') - execute('1,/^test 1-1/-1d') + feed_command('let [str, a] = spellbadword()') + feed_command('$put =str') + feed_command('1,/^test 1-1/-1d') expect([[ test 1-1 # file: Xtest.utf-8.spl @@ -667,7 +667,7 @@ describe("spell checking with 'encoding' set to utf-8", function() ]]) -- Postponed prefixes. test_one(2, 1) - execute('1,/^test 2-1/-1d') + feed_command('1,/^test 2-1/-1d') expect([=[ test 2-1 # file: Xtest.utf-8.spl @@ -711,13 +711,13 @@ describe("spell checking with 'encoding' set to utf-8", function() it('part 3-3', function() insert([[ Test rules for compounding. - + 3good: foo mรฏ foobar foofoobar barfoo barbarfoo bad: bar la foomรฏ barmรฏ mรฏfoo mรฏbar mรฏmรฏ lala mรฏla lamรฏ foola labar badend ]]) test_one(3, 3) - execute('1,/^test 3-3/-1d') + feed_command('1,/^test 3-3/-1d') expect([=[ test 3-3 # file: Xtest.utf-8.spl @@ -755,7 +755,7 @@ describe("spell checking with 'encoding' set to utf-8", function() it('part 4-4', function() insert([[ Tests for compounding. - + 4good: word util bork prebork start end wordutil wordutils pro-ok bork borkbork borkborkbork borkborkborkbork borkborkborkborkbork tomato tomatotomato startend startword startwordword startwordend @@ -770,7 +770,7 @@ describe("spell checking with 'encoding' set to utf-8", function() badend ]]) test_one(4, 4) - execute('1,/^test 4-4/-1d') + feed_command('1,/^test 4-4/-1d') expect([=[ test 4-4 # file: Xtest.utf-8.spl @@ -823,7 +823,7 @@ describe("spell checking with 'encoding' set to utf-8", function() it('part 5-5', function() insert([[ Test affix flags with two characters - + 5good: fooa1 fooaรฉ bar prebar barbork prebarbork startprebar start end startend startmiddleend nouend bad: foo fooa2 prabar probarbirk middle startmiddle middleend endstart @@ -831,7 +831,7 @@ describe("spell checking with 'encoding' set to utf-8", function() badend ]]) test_one(5, 5) - execute('1,/^test 5-5/-1d') + feed_command('1,/^test 5-5/-1d') expect([=[ test 5-5 # file: Xtest.utf-8.spl @@ -878,7 +878,7 @@ describe("spell checking with 'encoding' set to utf-8", function() badend ]]) test_one(6, 6) - execute('1,/^test 6-6/-1d') + feed_command('1,/^test 6-6/-1d') expect([=[ test 6-6 # file: Xtest.utf-8.spl @@ -924,7 +924,7 @@ describe("spell checking with 'encoding' set to utf-8", function() -- Compound words. test_one(7, 7) -- Assert buffer contents. - execute('1,/^test 7-7/-1d') + feed_command('1,/^test 7-7/-1d') expect([=[ test 7-7 # file: Xtest.utf-8.spl @@ -968,7 +968,7 @@ describe("spell checking with 'encoding' set to utf-8", function() -- NOSPLITSUGS test_one(8, 8) -- Assert buffer contents. - execute('1,/^test 8-8/-1d') + feed_command('1,/^test 8-8/-1d') expect([=[ test 8-8 # file: Xtest.utf-8.spl @@ -992,7 +992,7 @@ describe("spell checking with 'encoding' set to utf-8", function() -- NOSPLITSUGS test_one(9, 9) -- Assert buffer contents. - execute('1,/^test 9-9/-1d') + feed_command('1,/^test 9-9/-1d') expect([=[ test 9-9 # file: Xtest.utf-8.spl diff --git a/test/functional/legacy/061_undo_tree_spec.lua b/test/functional/legacy/061_undo_tree_spec.lua index aeb2001d11..1a8ef067d0 100644 --- a/test/functional/legacy/061_undo_tree_spec.lua +++ b/test/functional/legacy/061_undo_tree_spec.lua @@ -1,8 +1,8 @@ -- Tests for undo tree and :earlier and :later. local helpers = require('test.functional.helpers')(after_each) +local feed_command = helpers.feed_command local write_file = helpers.write_file -local execute = helpers.execute local command = helpers.command local source = helpers.source local expect = helpers.expect @@ -44,7 +44,7 @@ describe('undo tree:', function() -- function to allow multiple attempts. local function test_earlier_later() clear() - execute('e Xtest') + feed_command('e Xtest') -- Assert that no undo history is present. eq({}, eval('undotree().entries')) -- Delete three characters and undo. @@ -88,13 +88,13 @@ describe('undo tree:', function() feed('Ab<esc>') feed('Ac<esc>') expect_line('123456abc') - execute('earlier 1s') + feed_command('earlier 1s') expect_line('123456') - execute('earlier 3s') + feed_command('earlier 3s') expect_line('123456789') - execute('later 1s') + feed_command('later 1s') expect_line('123456') - execute('later 1h') + feed_command('later 1h') expect_line('123456abc') end @@ -103,28 +103,28 @@ describe('undo tree:', function() it('file-write specifications', function() feed('ione one one<esc>') - execute('w Xtest') + feed_command('w Xtest') feed('otwo<esc>') feed('otwo<esc>') - execute('w') + feed_command('w') feed('othree<esc>') - execute('earlier 1f') + feed_command('earlier 1f') expect([[ one one one two two]]) - execute('earlier 1f') + feed_command('earlier 1f') expect('one one one') - execute('earlier 1f') + feed_command('earlier 1f') expect_empty_buffer() - execute('later 1f') + feed_command('later 1f') expect('one one one') - execute('later 1f') + feed_command('later 1f') expect([[ one one one two two]]) - execute('later 1f') + feed_command('later 1f') expect([[ one one one two @@ -193,20 +193,20 @@ describe('undo tree:', function() feed('ob<esc>') feed([[o1<esc>a2<C-R>=setline('.','1234')<cr><esc>]]) expect([[ - + a b 12034]]) feed('uu') expect([[ - + a b 1]]) feed('oc<esc>') feed([[o1<esc>a2<C-R>=setline('.','1234')<cr><esc>]]) expect([[ - + a b 1 @@ -214,16 +214,16 @@ describe('undo tree:', function() 12034]]) feed('u') expect([[ - + a b 1 c 12]]) feed('od<esc>') - execute('so! Xtest.source') + feed_command('so! Xtest.source') expect([[ - + a b 1 @@ -233,7 +233,7 @@ describe('undo tree:', function() 12123]]) feed('u') expect([[ - + a b 1 @@ -246,7 +246,7 @@ describe('undo tree:', function() -- interactive use (even in Vim; see ":help :undojoin"): feed(normal_commands) expect([[ - + a b 1 @@ -256,7 +256,7 @@ describe('undo tree:', function() 12123]]) feed('u') expect([[ - + a b 1 diff --git a/test/functional/legacy/062_tab_pages_spec.lua b/test/functional/legacy/062_tab_pages_spec.lua index d5b10b160e..eae0a8d51a 100644 --- a/test/functional/legacy/062_tab_pages_spec.lua +++ b/test/functional/legacy/062_tab_pages_spec.lua @@ -1,17 +1,18 @@ -- Tests for tab pages local helpers = require('test.functional.helpers')(after_each) -local feed, insert, source, clear, execute, expect, eval, eq = +local feed, insert, source, clear, command, expect, eval, eq = helpers.feed, helpers.insert, helpers.source, helpers.clear, - helpers.execute, helpers.expect, helpers.eval, helpers.eq + helpers.command, helpers.expect, helpers.eval, helpers.eq +local exc_exec = helpers.exc_exec describe('tab pages', function() before_each(clear) it('can be opened and closed', function() - execute('tabnew') + command('tabnew') eq(2, eval('tabpagenr()')) - execute('quit') + command('quit') eq(1, eval('tabpagenr()')) end) @@ -25,7 +26,7 @@ describe('tab pages', function() tabrewind ]]) eq('this is tab page 1', eval("getline('$')")) - execute('tablast') + command('tablast') eq('this is tab page 4', eval("getline('$')")) end) @@ -44,7 +45,7 @@ describe('tab pages', function() eq(100, eval('gettabvar(2, "val_num")')) eq('SetTabVar test', eval('gettabvar(2, "val_str")')) eq({'red', 'blue', 'green'}, eval('gettabvar(2, "val_list")')) - execute('tabnext 2') + command('tabnext 2') eq(100, eval('t:val_num')) eq('SetTabVar test', eval('t:val_str')) eq({'red', 'blue', 'green'}, eval('t:val_list')) @@ -52,8 +53,8 @@ describe('tab pages', function() it('work together with the drop feature and loaded buffers', function() -- Test for ":tab drop exist-file" to keep current window. - execute('sp test1') - execute('tab drop test1') + command('sp test1') + command('tab drop test1') eq(1, eval('tabpagenr("$")')) eq(2, eval('winnr("$")')) eq(1, eval('winnr()')) @@ -61,8 +62,8 @@ describe('tab pages', function() it('work together with the drop feature and new files', function() -- Test for ":tab drop new-file" to keep current window of tabpage 1. - execute('split') - execute('tab drop newfile') + command('split') + command('tab drop newfile') eq(2, eval('tabpagenr("$")')) eq(2, eval('tabpagewinnr(1, "$")')) eq(1, eval('tabpagewinnr(1)')) @@ -71,57 +72,49 @@ describe('tab pages', function() it('work together with the drop feature and multi loaded buffers', function() -- Test for ":tab drop multi-opend-file" to keep current tabpage and -- window. - execute('new test1') - execute('tabnew') - execute('new test1') - execute('tab drop test1') + command('new test1') + command('tabnew') + command('new test1') + command('tab drop test1') eq(2, eval('tabpagenr()')) eq(2, eval('tabpagewinnr(2, "$")')) eq(1, eval('tabpagewinnr(2)')) end) it('can be navigated with :tabmove', function() - execute('lang C') - execute('for i in range(9) | tabnew | endfor') + command('lang C') + command('for i in range(9) | tabnew | endfor') feed('1gt') eq(1, eval('tabpagenr()')) - execute('tabmove 5') + command('tabmove 5') eq(5, eval('tabpagenr()')) - execute('.tabmove') + command('.tabmove') eq(5, eval('tabpagenr()')) - execute('tabmove -') + command('tabmove -') eq(4, eval('tabpagenr()')) - execute('tabmove +') + command('tabmove +') eq(5, eval('tabpagenr()')) - execute('tabmove -2') + command('tabmove -2') eq(3, eval('tabpagenr()')) - execute('tabmove +4') + command('tabmove +4') eq(7, eval('tabpagenr()')) - execute('tabmove') + command('tabmove') eq(10, eval('tabpagenr()')) - execute('tabmove -20') + command('0tabmove') eq(1, eval('tabpagenr()')) - execute('tabmove +20') + command('$tabmove') eq(10, eval('tabpagenr()')) - execute('0tabmove') + command('tabmove 0') eq(1, eval('tabpagenr()')) - execute('$tabmove') + command('tabmove $') eq(10, eval('tabpagenr()')) - execute('tabmove 0') - eq(1, eval('tabpagenr()')) - execute('tabmove $') - eq(10, eval('tabpagenr()')) - execute('3tabmove') + command('3tabmove') eq(4, eval('tabpagenr()')) - execute('7tabmove 5') + command('7tabmove 5') eq(5, eval('tabpagenr()')) - execute('let a="No error caught."') - execute('try') - execute('tabmove foo') - execute('catch E474') - execute('let a="E474 caught."') - execute('endtry') - eq('E474 caught.', eval('a')) + command('let a="No error caught."') + eq('Vim(tabmove):E474: Invalid argument: tabmove foo', + exc_exec('tabmove foo')) end) it('can trigger certain autocommands', function() @@ -172,7 +165,7 @@ describe('tab pages', function() C tabnext 1 autocmd TabDestructive TabEnter * nested \ :C tabnext 2 | C tabclose 3 - C tabnext 3 + C tabnext 2 let g:r+=[tabpagenr().'/'.tabpagenr('$')] endfunction call Test() @@ -233,22 +226,14 @@ describe('tab pages', function() WinEnter TabEnter BufEnter - === tabnext 3 === - BufLeave - WinLeave - TabLeave - WinEnter - TabEnter === tabnext 2 === - BufLeave WinLeave TabLeave WinEnter TabEnter === tabnext 2 === === tabclose 3 === - BufEnter - === tabclose 3 === 2/2]]) + eq(2, eval("tabpagenr('$')")) end) end) diff --git a/test/functional/legacy/063_match_and_matchadd_spec.lua b/test/functional/legacy/063_match_and_matchadd_spec.lua index 298e0a31ea..a505a2db30 100644 --- a/test/functional/legacy/063_match_and_matchadd_spec.lua +++ b/test/functional/legacy/063_match_and_matchadd_spec.lua @@ -2,9 +2,11 @@ local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') -local feed, insert = helpers.feed, helpers.insert -local eval, clear, execute = helpers.eval, helpers.clear, helpers.execute + +local eval, clear, command = helpers.eval, helpers.clear, helpers.command local eq, neq = helpers.eq, helpers.neq +local insert = helpers.insert +local redir_exec = helpers.redir_exec describe('063: Test for ":match", "matchadd()" and related functions', function() setup(clear) @@ -15,12 +17,12 @@ describe('063: Test for ":match", "matchadd()" and related functions', function( -- Check that "matcharg()" returns the correct group and pattern if a match -- is defined. - execute("highlight MyGroup1 term=bold ctermbg=red guibg=red") - execute("highlight MyGroup2 term=italic ctermbg=green guibg=green") - execute("highlight MyGroup3 term=underline ctermbg=blue guibg=blue") - execute("match MyGroup1 /TODO/") - execute("2match MyGroup2 /FIXME/") - execute("3match MyGroup3 /XXX/") + command("highlight MyGroup1 term=bold ctermbg=red guibg=red") + command("highlight MyGroup2 term=italic ctermbg=green guibg=green") + command("highlight MyGroup3 term=underline ctermbg=blue guibg=blue") + command("match MyGroup1 /TODO/") + command("2match MyGroup2 /FIXME/") + command("3match MyGroup3 /XXX/") eq({'MyGroup1', 'TODO'}, eval('matcharg(1)')) eq({'MyGroup2', 'FIXME'}, eval('matcharg(2)')) eq({'MyGroup3', 'XXX'}, eval('matcharg(3)')) @@ -31,18 +33,18 @@ describe('063: Test for ":match", "matchadd()" and related functions', function( eq({}, eval('matcharg(4)')) -- Check that "matcharg()" returns ['', ''] if a match is not defined. - execute("match") - execute("2match") - execute("3match") + command("match") + command("2match") + command("3match") eq({'', ''}, eval('matcharg(1)')) eq({'', ''}, eval('matcharg(2)')) eq({'', ''}, eval('matcharg(3)')) -- Check that "matchadd()" and "getmatches()" agree on added matches and -- that default values apply. - execute("let m1 = matchadd('MyGroup1', 'TODO')") - execute("let m2 = matchadd('MyGroup2', 'FIXME', 42)") - execute("let m3 = matchadd('MyGroup3', 'XXX', 60, 17)") + command("let m1 = matchadd('MyGroup1', 'TODO')") + command("let m2 = matchadd('MyGroup2', 'FIXME', 42)") + command("let m3 = matchadd('MyGroup3', 'XXX', 60, 17)") eq({{group = 'MyGroup1', pattern = 'TODO', priority = 10, id = 4}, {group = 'MyGroup2', pattern = 'FIXME', priority = 42, id = 5}, {group = 'MyGroup3', pattern = 'XXX', priority = 60, id = 17}}, @@ -50,58 +52,58 @@ describe('063: Test for ":match", "matchadd()" and related functions', function( -- Check that "matchdelete()" deletes the matches defined in the previous -- test correctly. - execute("call matchdelete(m1)") - execute("call matchdelete(m2)") - execute("call matchdelete(m3)") + command("call matchdelete(m1)") + command("call matchdelete(m2)") + command("call matchdelete(m3)") eq({}, eval('getmatches()')) --- Check that "matchdelete()" returns 0 if successful and otherwise -1. - execute("let m = matchadd('MyGroup1', 'TODO')") + command("let m = matchadd('MyGroup1', 'TODO')") eq(0, eval('matchdelete(m)')) -- matchdelete throws error and returns -1 on failure neq(true, pcall(function() eval('matchdelete(42)') end)) - execute("let r2 = matchdelete(42)") + eq('\nE803: ID not found: 42', + redir_exec("let r2 = matchdelete(42)")) eq(-1, eval('r2')) -- Check that "clearmatches()" clears all matches defined by ":match" and -- "matchadd()". - execute("let m1 = matchadd('MyGroup1', 'TODO')") - execute("let m2 = matchadd('MyGroup2', 'FIXME', 42)") - execute("let m3 = matchadd('MyGroup3', 'XXX', 60, 17)") - execute("match MyGroup1 /COFFEE/") - execute("2match MyGroup2 /HUMPPA/") - execute("3match MyGroup3 /VIM/") - execute("call clearmatches()") + command("let m1 = matchadd('MyGroup1', 'TODO')") + command("let m2 = matchadd('MyGroup2', 'FIXME', 42)") + command("let m3 = matchadd('MyGroup3', 'XXX', 60, 17)") + command("match MyGroup1 /COFFEE/") + command("2match MyGroup2 /HUMPPA/") + command("3match MyGroup3 /VIM/") + command("call clearmatches()") eq({}, eval('getmatches()')) -- Check that "setmatches()" restores a list of matches saved by -- "getmatches()" without changes. (Matches with equal priority must also -- remain in the same order.) - execute("let m1 = matchadd('MyGroup1', 'TODO')") - execute("let m2 = matchadd('MyGroup2', 'FIXME', 42)") - execute("let m3 = matchadd('MyGroup3', 'XXX', 60, 17)") - execute("match MyGroup1 /COFFEE/") - execute("2match MyGroup2 /HUMPPA/") - execute("3match MyGroup3 /VIM/") - execute("let ml = getmatches()") + command("let m1 = matchadd('MyGroup1', 'TODO')") + command("let m2 = matchadd('MyGroup2', 'FIXME', 42)") + command("let m3 = matchadd('MyGroup3', 'XXX', 60, 17)") + command("match MyGroup1 /COFFEE/") + command("2match MyGroup2 /HUMPPA/") + command("3match MyGroup3 /VIM/") + command("let ml = getmatches()") local ml = eval("ml") - execute("call clearmatches()") - execute("call setmatches(ml)") + command("call clearmatches()") + command("call setmatches(ml)") eq(ml, eval('getmatches()')) -- Check that "setmatches()" can correctly restore the matches from matchaddpos() - execute("call clearmatches()") - execute("call setmatches(ml)") + command("call clearmatches()") + command("call setmatches(ml)") eq(ml, eval('getmatches()')) -- Check that "setmatches()" will not add two matches with the same ID. The -- expected behaviour (for now) is to add the first match but not the - -- second and to return 0 (even though it is a matter of debate whether - -- this can be considered successful behaviour). - execute("let r1 = setmatches([{'group': 'MyGroup1', 'pattern': 'TODO', 'priority': 10, 'id': 1}, {'group': 'MyGroup2', 'pattern': 'FIXME', 'priority': 10, 'id': 1}])") - feed("<cr>") - eq(0, eval("r1")) + -- second and to return -1. + eq('\nE801: ID already taken: 1', + redir_exec("let r1 = setmatches([{'group': 'MyGroup1', 'pattern': 'TODO', 'priority': 10, 'id': 1}, {'group': 'MyGroup2', 'pattern': 'FIXME', 'priority': 10, 'id': 1}])")) + eq(-1, eval("r1")) eq({{group = 'MyGroup1', pattern = 'TODO', priority = 10, id = 1}}, eval('getmatches()')) -- Check that "setmatches()" returns 0 if successful and otherwise -1. @@ -109,18 +111,17 @@ describe('063: Test for ":match", "matchadd()" and related functions', function( -- return values.) eq(0,eval("setmatches([])")) eq(0,eval("setmatches([{'group': 'MyGroup1', 'pattern': 'TODO', 'priority': 10, 'id': 1}])")) - execute("call clearmatches()") - execute("let rf1 = setmatches(0)") + command("call clearmatches()") + eq('\nE714: List required', redir_exec("let rf1 = setmatches(0)")) eq(-1, eval('rf1')) - execute("let rf2 = setmatches([0])") + eq('\nE474: Invalid argument', redir_exec("let rf2 = setmatches([0])")) eq(-1, eval('rf2')) - execute("let rf3 = setmatches([{'wrong key': 'wrong value'}])") - feed("<cr>") + eq('\nE474: Invalid argument', redir_exec("let rf3 = setmatches([{'wrong key': 'wrong value'}])")) eq(-1, eval('rf3')) -- Check that "matchaddpos()" positions matches correctly insert('abcdefghijklmnopq') - execute("call matchaddpos('MyGroup1', [[1, 5], [1, 8, 3]], 10, 3)") + command("call matchaddpos('MyGroup1', [[1, 5], [1, 8, 3]], 10, 3)") screen:expect([[ abcd{1:e}fg{1:hij}klmnop^q | ~ | @@ -129,9 +130,9 @@ describe('063: Test for ":match", "matchadd()" and related functions', function( | ]], {[1] = {background = Screen.colors.Red}}, {{bold = true, foreground = Screen.colors.Blue}}) - execute("call clearmatches()") - execute("call setline(1, 'abcdฮฃabcdef')") - execute("call matchaddpos('MyGroup1', [[1, 4, 2], [1, 9, 2]])") + command("call clearmatches()") + command("call setline(1, 'abcdฮฃabcdef')") + command("call matchaddpos('MyGroup1', [[1, 4, 2], [1, 9, 2]])") screen:expect([[ abc{1:dฮฃ}ab{1:cd}e^f | ~ | diff --git a/test/functional/legacy/065_float_and_logic_operators_spec.lua b/test/functional/legacy/065_float_and_logic_operators_spec.lua index d12ea502f3..ad1b004085 100644 --- a/test/functional/legacy/065_float_and_logic_operators_spec.lua +++ b/test/functional/legacy/065_float_and_logic_operators_spec.lua @@ -2,7 +2,7 @@ local helpers = require('test.functional.helpers')(after_each) local insert, source = helpers.insert, helpers.source -local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect +local clear, expect = helpers.clear, helpers.expect describe('floating point and logical operators', function() setup(clear) @@ -44,14 +44,7 @@ describe('floating point and logical operators', function() $put ='abs' $put =printf('%d', abs(1456)) $put =printf('%d', abs(-4)) - ]]) - - -- The test will throw an error if this line is included in a source() - -- call. The vim expression throws a exception "E745: Using a List as a - -- Number" which is fatal in a source() call but not in a execute() call. - execute([[$put =printf('%d', abs([1, 2, 3]))]]) - - source([[ + silent! $put =printf('%d', abs([1, 2, 3])) $put =printf('%g', abs(14.56)) $put =printf('%g', abs(-54.32)) $put ='ceil' @@ -100,12 +93,9 @@ describe('floating point and logical operators', function() $put =and(invert(127), 65535) $put =and(invert(16), 65535) $put =and(invert(128), 65535) + silent! $put =invert(1.0) ]]) - -- This line can not be included in a source() call. It throws a "E805: - -- Using a Float as a Number". Also compare comment above. - execute('$put =invert(1.0)') - -- Assert buffer contents. expect([=[ Results of test65: diff --git a/test/functional/legacy/066_visual_block_tab_spec.lua b/test/functional/legacy/066_visual_block_tab_spec.lua index 72fa7d881b..7c4984362f 100644 --- a/test/functional/legacy/066_visual_block_tab_spec.lua +++ b/test/functional/legacy/066_visual_block_tab_spec.lua @@ -3,7 +3,7 @@ local helpers = require('test.functional.helpers')(after_each) local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local execute, expect = helpers.execute, helpers.expect +local feed_command, expect = helpers.feed_command, helpers.expect describe('visual block shift and tab characters', function() setup(clear) @@ -24,23 +24,23 @@ describe('visual block shift and tab characters', function() feed('gg') feed([[fe<C-v>4jR<esc>ugvr1:'<lt>,'>yank A<cr>]]) - execute('/^abcdefgh') + feed_command('/^abcdefgh') feed('<C-v>4jI <esc>j<lt><lt>11|D') feed('j7|a <esc>') feed('j7|a <esc>') feed('j7|a <esc>4k13|<C-v>4j<lt>') - execute('$-5,$yank A') - execute([[$-4,$s/\s\+//g]]) + feed_command('$-5,$yank A') + feed_command([[$-4,$s/\s\+//g]]) feed('<C-v>4kI <esc>j<lt><lt>') feed('j7|a <esc>') feed('j7|a <esc>') feed('j7|a <esc>4k13|<C-v>4j3<lt>') - execute('$-4,$yank A') + feed_command('$-4,$yank A') -- Put @a and clean empty lines - execute('%d') - execute('0put a') - execute('$d') + feed_command('%d') + feed_command('0put a') + feed_command('$d') -- Assert buffer contents. expect([[ diff --git a/test/functional/legacy/067_augroup_exists_spec.lua b/test/functional/legacy/067_augroup_exists_spec.lua index 8f6b881ed8..4a77bf838a 100644 --- a/test/functional/legacy/067_augroup_exists_spec.lua +++ b/test/functional/legacy/067_augroup_exists_spec.lua @@ -3,32 +3,34 @@ local helpers = require('test.functional.helpers')(after_each) local clear = helpers.clear -local execute, expect = helpers.execute, helpers.expect +local command, expect = helpers.command, helpers.expect describe('augroup when calling exists()', function() setup(clear) it('is working', function() - execute('let results=[]') - execute('call add(results, "##BufEnter: " . exists("##BufEnter"))') - execute('call add(results, "#BufEnter: " . exists("#BufEnter"))') - execute('au BufEnter * let g:entered=1') - execute('call add(results, "#BufEnter: " . exists("#BufEnter"))') - execute('call add(results, "#auexists#BufEnter: " . exists("#auexists#BufEnter"))') - execute('augroup auexists', 'au BufEnter * let g:entered=1', 'augroup END') - execute('call add(results, "#auexists#BufEnter: " . exists("#auexists#BufEnter"))') - execute('call add(results, "#BufEnter#*.test: " . exists("#BufEnter#*.test"))') - execute('au BufEnter *.test let g:entered=1') - execute('call add(results, "#BufEnter#*.test: " . exists("#BufEnter#*.test"))') - execute('edit testfile.test') - execute('call add(results, "#BufEnter#<buffer>: " . exists("#BufEnter#<buffer>"))') - execute('au BufEnter <buffer> let g:entered=1') - execute('call add(results, "#BufEnter#<buffer>: " . exists("#BufEnter#<buffer>"))') - execute('edit testfile2.test') - execute('call add(results, "#BufEnter#<buffer>: " . exists("#BufEnter#<buffer>"))') - execute('bf') - execute('call append(0, results)') - execute('$d') + command('let results=[]') + command('call add(results, "##BufEnter: " . exists("##BufEnter"))') + command('call add(results, "#BufEnter: " . exists("#BufEnter"))') + command('au BufEnter * let g:entered=1') + command('call add(results, "#BufEnter: " . exists("#BufEnter"))') + command('call add(results, "#auexists#BufEnter: " . exists("#auexists#BufEnter"))') + command('augroup auexists') + command('au BufEnter * let g:entered=1') + command('augroup END') + command('call add(results, "#auexists#BufEnter: " . exists("#auexists#BufEnter"))') + command('call add(results, "#BufEnter#*.test: " . exists("#BufEnter#*.test"))') + command('au BufEnter *.test let g:entered=1') + command('call add(results, "#BufEnter#*.test: " . exists("#BufEnter#*.test"))') + command('edit testfile.test') + command('call add(results, "#BufEnter#<buffer>: " . exists("#BufEnter#<buffer>"))') + command('au BufEnter <buffer> let g:entered=1') + command('call add(results, "#BufEnter#<buffer>: " . exists("#BufEnter#<buffer>"))') + command('edit testfile2.test') + command('call add(results, "#BufEnter#<buffer>: " . exists("#BufEnter#<buffer>"))') + command('bf') + command('call append(0, results)') + command('$d') -- Assert buffer contents. expect([[ diff --git a/test/functional/legacy/068_text_formatting_spec.lua b/test/functional/legacy/068_text_formatting_spec.lua index e232e5073d..772dbc14cf 100644 --- a/test/functional/legacy/068_text_formatting_spec.lua +++ b/test/functional/legacy/068_text_formatting_spec.lua @@ -3,7 +3,7 @@ local helpers = require('test.functional.helpers')(after_each) local feed = helpers.feed local clear = helpers.clear local insert = helpers.insert -local execute = helpers.execute +local feed_command = helpers.feed_command local expect = helpers.expect describe('text formatting', function() @@ -15,195 +15,195 @@ describe('text formatting', function() -- mode so it has to be escaped with <C-V>. insert([[ Results of test68: - - + + { - - + + } - - + + { a b - + a } - - + + { a } - - + + { a b #a b } - - + + { 1 a # 1 a } - - + + { - + x a b c - + } - - + + { # 1 a b } - - + + { # x # a b } - - + + { 1aa 2bb } - - + + /* abc def ghi jkl * mno pqr stu */ - - + + # 1 xxxxx ]]) - execute('/^{/+1') - execute('set noai tw=2 fo=t') + feed_command('/^{/+1') + feed_command('set noai tw=2 fo=t') feed('gRa b<esc>') - execute('/^{/+1') - execute('set ai tw=2 fo=tw') + feed_command('/^{/+1') + feed_command('set ai tw=2 fo=tw') feed('gqgqjjllab<esc>') - execute('/^{/+1') - execute('set tw=3 fo=t') + feed_command('/^{/+1') + feed_command('set tw=3 fo=t') feed('gqgqo<cr>') feed('a <C-V><C-A><esc><esc>') - execute('/^{/+1') - execute('set tw=2 fo=tcq1 comments=:#') + feed_command('/^{/+1') + feed_command('set tw=2 fo=tcq1 comments=:#') feed('gqgqjgqgqo<cr>') feed('a b<cr>') feed('#a b<esc>') - execute('/^{/+1') - execute('set tw=5 fo=tcn comments=:#') + feed_command('/^{/+1') + feed_command('set tw=5 fo=tcn comments=:#') feed('A b<esc>jA b<esc>') - execute('/^{/+3') - execute('set tw=5 fo=t2a si') + feed_command('/^{/+3') + feed_command('set tw=5 fo=t2a si') feed('i <esc>A_<esc>') - execute('/^{/+1') - execute('set tw=5 fo=qn comments=:#') + feed_command('/^{/+1') + feed_command('set tw=5 fo=qn comments=:#') feed('gwap<cr>') - execute('/^{/+1') - execute('set tw=5 fo=q2 comments=:#') + feed_command('/^{/+1') + feed_command('set tw=5 fo=q2 comments=:#') feed('gwap<cr>') - execute('/^{/+2') - execute('set tw& fo=a') + feed_command('/^{/+2') + feed_command('set tw& fo=a') feed('I^^<esc><esc>') - execute('/mno pqr/') - execute('setl tw=20 fo=an12wcq comments=s1:/*,mb:*,ex:*/') + feed_command('/mno pqr/') + feed_command('setl tw=20 fo=an12wcq comments=s1:/*,mb:*,ex:*/') feed('A vwx yz<esc>') - execute('/^#/') - execute('setl tw=12 fo=tqnc comments=:#') + feed_command('/^#/') + feed_command('setl tw=12 fo=tqnc comments=:#') feed('A foobar<esc>') -- Assert buffer contents. expect([[ Results of test68: - - + + { a b } - - + + { a b - + a b } - - + + { a - + a } - - + + { a b #a b - + a b #a b } - - + + { 1 a b # 1 a # b } - - + + { - + x a b_ c - + } - - + + { # 1 a # b } - - + + { # x a # b } - - + + { 1aa ^^2bb } - - + + /* abc def ghi jkl * mno pqr stu * vwx yz */ - - + + # 1 xxxxx # foobar ]]) diff --git a/test/functional/legacy/069_multibyte_formatting_spec.lua b/test/functional/legacy/069_multibyte_formatting_spec.lua new file mode 100644 index 0000000000..38ca25d57a --- /dev/null +++ b/test/functional/legacy/069_multibyte_formatting_spec.lua @@ -0,0 +1,340 @@ +-- Test for multibyte text formatting. +-- Also test, that 'mps' with multibyte chars works. +-- And test "ra" on multibyte characters. +-- Also test byteidx() and byteidxcomp() + +local helpers = require('test.functional.helpers')(after_each) +local feed, insert, eq, eval, clear, feed_command, expect = helpers.feed, + helpers.insert, helpers.eq, helpers.eval, helpers.clear, helpers.feed_command, + helpers.expect + +describe('multibyte text', function() + before_each(clear) + + it('formatting with "set fo=t"', function() + insert([[ + { + ๏ผธ๏ผน๏ผบ + abc ๏ผธ๏ผน๏ผบ + }]]) + feed_command('/^{/+1') + feed_command('set tw=2 fo=t') + feed('gqgqjgqgqo<cr>') + feed('๏ผธ๏ผน๏ผบ<cr>') + feed('abc ๏ผธ๏ผน๏ผบ<esc><esc>') + expect([[ + { + ๏ผธ๏ผน๏ผบ + abc + ๏ผธ๏ผน๏ผบ + + ๏ผธ๏ผน๏ผบ + abc + ๏ผธ๏ผน๏ผบ + }]]) + end) + + it('formatting with "set fo=tm"', function() + insert([[ + { + ๏ผธ + ๏ผธa + ๏ผธ a + ๏ผธ๏ผน + ๏ผธ ๏ผน + }]]) + feed_command('/^{/+1') + feed_command('set tw=1 fo=tm') + feed('gqgqjgqgqjgqgqjgqgqjgqgqo<cr>') + feed('๏ผธ<cr>') + feed('๏ผธa<cr>') + feed('๏ผธ a<cr>') + feed('๏ผธ๏ผน<cr>') + feed('๏ผธ ๏ผน<esc><esc>') + expect([[ + { + ๏ผธ + ๏ผธ + a + ๏ผธ + a + ๏ผธ + ๏ผน + ๏ผธ + ๏ผน + + ๏ผธ + ๏ผธ + a + ๏ผธ + a + ๏ผธ + ๏ผน + ๏ผธ + ๏ผน + }]]) + end) + + it('formatting with "set fo=tm" (part 2)', function() + insert([[ + { + ๏ผธ + ๏ผธa + ๏ผธ a + ๏ผธ๏ผน + ๏ผธ ๏ผน + a๏ผธ + ab๏ผธ + abc๏ผธ + ab๏ผธ c + ab๏ผธ๏ผน + }]]) + feed_command('/^{/+1') + feed_command('set tw=2 fo=tm') + feed('gqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqo<cr>') + feed('๏ผธ<cr>') + feed('๏ผธa<cr>') + feed('๏ผธ a<cr>') + feed('๏ผธ๏ผน<cr>') + feed('๏ผธ ๏ผน<cr>') + feed('a๏ผธ<cr>') + feed('ab๏ผธ<cr>') + feed('abc๏ผธ<cr>') + feed('ab๏ผธ c<cr>') + feed('ab๏ผธ๏ผน<esc><esc>') + expect([[ + { + ๏ผธ + ๏ผธ + a + ๏ผธ + a + ๏ผธ + ๏ผน + ๏ผธ + ๏ผน + a + ๏ผธ + ab + ๏ผธ + abc + ๏ผธ + ab + ๏ผธ + c + ab + ๏ผธ + ๏ผน + + ๏ผธ + ๏ผธ + a + ๏ผธ + a + ๏ผธ + ๏ผน + ๏ผธ + ๏ผน + a + ๏ผธ + ab + ๏ผธ + abc + ๏ผธ + ab + ๏ผธ + c + ab + ๏ผธ + ๏ผน + }]]) + end) + + it('formatting with "set ai fo=tm"', function() + insert([[ + { + ๏ผธ + ๏ผธa + }]]) + feed_command('/^{/+1') + feed_command('set ai tw=2 fo=tm') + feed('gqgqjgqgqo<cr>') + feed('๏ผธ<cr>') + feed('๏ผธa<esc>') + expect([[ + { + ๏ผธ + ๏ผธ + a + + ๏ผธ + ๏ผธ + a + }]]) + end) + + it('formatting with "set ai fo=tm" (part 2)', function() + insert([[ + { + ๏ผธ + ๏ผธa + }]]) + feed_command('/^{/+1') + feed_command('set noai tw=2 fo=tm') + feed('gqgqjgqgqo<cr>') + -- Literal spaces will be trimmed from the by feed(). + feed('<space><space>๏ผธ<cr>') + feed('<space><space>๏ผธa<esc>') + expect([[ + { + ๏ผธ + ๏ผธ + a + + ๏ผธ + ๏ผธ + a + }]]) + end) + + it('formatting with "set fo=cqm" and multibyte comments', function() + insert([[ + { + ๏ผธ + ๏ผธa + ๏ผธa๏ผน + ๏ผธ๏ผน + ๏ผธ๏ผน๏ผบ + ๏ผธ ๏ผน + ๏ผธ ๏ผน๏ผบ + ๏ผธ๏ผธ + ๏ผธ๏ผธa + ๏ผธ๏ผธ๏ผน + }]]) + feed_command('/^{/+1') + feed_command('set tw=2 fo=cqm comments=n:๏ผธ') + feed('gqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqo<cr>') + feed('๏ผธ<cr>') + feed('๏ผธa<cr>') + feed('๏ผธa๏ผน<cr>') + feed('๏ผธ๏ผน<cr>') + feed('๏ผธ๏ผน๏ผบ<cr>') + feed('๏ผธ ๏ผน<cr>') + feed('๏ผธ ๏ผน๏ผบ<cr>') + feed('๏ผธ๏ผธ<cr>') + feed('๏ผธ๏ผธa<cr>') + feed('๏ผธ๏ผธ๏ผน<esc><esc>') + expect([[ + { + ๏ผธ + ๏ผธa + ๏ผธa + ๏ผธ๏ผน + ๏ผธ๏ผน + ๏ผธ๏ผน + ๏ผธ๏ผบ + ๏ผธ ๏ผน + ๏ผธ ๏ผน + ๏ผธ ๏ผบ + ๏ผธ๏ผธ + ๏ผธ๏ผธa + ๏ผธ๏ผธ๏ผน + + ๏ผธ + ๏ผธa + ๏ผธa + ๏ผธ๏ผน + ๏ผธ๏ผน + ๏ผธ๏ผน + ๏ผธ๏ผบ + ๏ผธ ๏ผน + ๏ผธ ๏ผน + ๏ผธ ๏ผบ + ๏ผธ๏ผธ + ๏ผธ๏ผธa + ๏ผธ๏ผธ๏ผน + }]]) + end) + + it('formatting in replace mode', function() + insert([[ + { + + }]]) + feed_command('/^{/+1') + feed_command('set tw=2 fo=tm') + feed('R๏ผธa<esc>') + expect([[ + { + ๏ผธ + a + }]]) + end) + + it("as values of 'mps'", function() + insert([[ + { + โ two three โ four + }]]) + feed_command('/^{/+1') + feed_command('set mps+=โ:โ') + feed('d%<cr>') + expect([[ + { + four + }]]) + end) + + it('can be replaced with r', function() + insert([[ + ๏ฝbb๏ฝ + ๏ฝ๏ฝb]]) + feed('gg0Vjra<cr>') + expect([[ + aaaa + aaa]]) + end) + + it("doesn't interfere with 'whichwrap'", function() + insert([[ + รก + x]]) + feed_command('set whichwrap+=h') + feed_command('/^x') + feed('dh') + expect([[ + รกx]]) + end) + + it('can be queried with byteidx() and byteidxcomp()', function() + -- One char of two bytes. + feed_command("let a = '.รฉ.'") + -- Normal e with composing char. + feed_command("let b = '.eฬ.'") + eq(0, eval('byteidx(a, 0)')) + eq(1, eval('byteidx(a, 1)')) + eq(3, eval('byteidx(a, 2)')) + eq(4, eval('byteidx(a, 3)')) + eq(-1, eval('byteidx(a, 4)')) + eq(0, eval('byteidx(b, 0)')) + eq(1, eval('byteidx(b, 1)')) + eq(4, eval('byteidx(b, 2)')) + eq(5, eval('byteidx(b, 3)')) + eq(-1, eval('byteidx(b, 4)')) + eq(0, eval('byteidxcomp(a, 0)')) + eq(1, eval('byteidxcomp(a, 1)')) + eq(3, eval('byteidxcomp(a, 2)')) + eq(4, eval('byteidxcomp(a, 3)')) + eq(-1, eval('byteidxcomp(a, 4)')) + eq(0, eval('byteidxcomp(b, 0)')) + eq(1, eval('byteidxcomp(b, 1)')) + eq(2, eval('byteidxcomp(b, 2)')) + eq(4, eval('byteidxcomp(b, 3)')) + eq(5, eval('byteidxcomp(b, 4)')) + eq(-1, eval('byteidxcomp(b, 5)')) + end) + + it('correctly interact with the \zs pattern', function() + eq('a๏ผa๏ผa๏ผa', eval([[substitute('๏ผ๏ผ๏ผ', '\zs', 'a', 'g')]])) + end) +end) diff --git a/test/functional/legacy/072_undo_file_spec.lua b/test/functional/legacy/072_undo_file_spec.lua index 4682a82008..b4927e779e 100644 --- a/test/functional/legacy/072_undo_file_spec.lua +++ b/test/functional/legacy/072_undo_file_spec.lua @@ -4,7 +4,7 @@ local helpers = require('test.functional.helpers')(after_each) local feed, insert = helpers.feed, helpers.insert -local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect +local clear, feed_command, expect = helpers.clear, helpers.feed_command, helpers.expect describe('72', function() setup(clear) @@ -13,34 +13,34 @@ describe('72', function() insert([[ 1111 ----- 2222 ----- - + 123456789]]) -- Test 'undofile': first a simple one-line change. - execute('set visualbell') - execute('set ul=100 undofile undodir=. nomore') - execute('e! Xtestfile') + feed_command('set visualbell') + feed_command('set ul=100 undofile undodir=. nomore') + feed_command('e! Xtestfile') feed('ggdGithis is one line<esc>:set ul=100<cr>') - execute('s/one/ONE/') - execute('set ul=100') - execute('w') - execute('bwipe!') - execute('e Xtestfile') + feed_command('s/one/ONE/') + feed_command('set ul=100') + feed_command('w') + feed_command('bwipe!') + feed_command('e Xtestfile') feed('u:.w! test.out<cr>') -- Test 'undofile', change in original file fails check. - execute('set noundofile') - execute('e! Xtestfile') - execute('s/line/Line/') - execute('w') - execute('set undofile') - execute('bwipe!') - execute('e Xtestfile') + feed_command('set noundofile') + feed_command('e! Xtestfile') + feed_command('s/line/Line/') + feed_command('w') + feed_command('set undofile') + feed_command('bwipe!') + feed_command('e Xtestfile') ---- TODO: this beeps. feed('u:.w >>test.out<cr>') -- Test 'undofile', add 10 lines, delete 6 lines, undo 3. - execute('set undofile') + feed_command('set undofile') feed('ggdGione<cr>') feed('two<cr>') feed('three<cr>') @@ -57,20 +57,20 @@ describe('72', function() feed('dd:set ul=100<cr>') feed('dd:set ul=100<cr>') feed('dd:set ul=100<cr>') - execute('w') - execute('bwipe!') - execute('e Xtestfile') + feed_command('w') + feed_command('bwipe!') + feed_command('e Xtestfile') feed('uuu:w >>test.out<cr>') -- Test that reading the undofiles when setting undofile works. - execute('set noundofile ul=0') + feed_command('set noundofile ul=0') feed('i<cr>') feed('<esc>u:e! Xtestfile<cr>') - execute('set undofile ul=100') + feed_command('set undofile ul=100') feed('uuuuuu:w >>test.out<cr>') ---- Open the output to see if it meets the expections - execute('e! test.out') + feed_command('e! test.out') -- Assert buffer contents. expect([[ diff --git a/test/functional/legacy/074_global_var_in_viminfo_spec.lua b/test/functional/legacy/074_global_var_in_viminfo_spec.lua index 2fc30c9d83..e17b463e30 100644 --- a/test/functional/legacy/074_global_var_in_viminfo_spec.lua +++ b/test/functional/legacy/074_global_var_in_viminfo_spec.lua @@ -2,8 +2,8 @@ local helpers = require('test.functional.helpers')(after_each) local lfs = require('lfs') -local clear, execute, eq, neq, eval, wait, spawn = - helpers.clear, helpers.execute, helpers.eq, helpers.neq, helpers.eval, +local clear, command, eq, neq, eval, wait, spawn = + helpers.clear, helpers.command, helpers.eq, helpers.neq, helpers.eval, helpers.wait, helpers.spawn describe('storing global variables in ShaDa files', function() @@ -26,31 +26,29 @@ describe('storing global variables in ShaDa files', function() 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100} - execute( - -- This will cause a few errors, do it silently. - 'set visualbell', - 'set shada+=!', - "let MY_GLOBAL_DICT={'foo': 1, 'bar': 0, 'longvarible': 1000}", - -- Store a really long list. Initially this was testing line wrapping in - -- viminfo, but shada files has no line wrapping, no matter how long the - -- list is. - 'let MY_GLOBAL_LIST=range(1,100)' - ) + command('set visualbell') + command('set shada+=!') + command('let MY_GLOBAL_DICT={\'foo\': 1, \'bar\': 0, \'longvarible\': 1000}') + -- Store a really long list. Initially this was testing line wrapping in + -- viminfo, but shada files has no line wrapping, no matter how long the + -- list is. + command('let MY_GLOBAL_LIST=range(1, 100)') + eq(test_dict, eval('MY_GLOBAL_DICT')) eq(test_list, eval('MY_GLOBAL_LIST')) - execute('wsh! ' .. tempname) + command('wsh! ' .. tempname) wait() -- Assert that the shada file exists. neq(nil, lfs.attributes(tempname)) - execute('unlet MY_GLOBAL_DICT', - 'unlet MY_GLOBAL_LIST') + command('unlet MY_GLOBAL_DICT') + command('unlet MY_GLOBAL_LIST') -- Assert that the variables where deleted. eq(0, eval('exists("MY_GLOBAL_DICT")')) eq(0, eval('exists("MY_GLOBAL_LIST")')) - execute('rsh! ' .. tempname) + command('rsh! ' .. tempname) eq(test_list, eval('MY_GLOBAL_LIST')) eq(test_dict, eval('MY_GLOBAL_DICT')) diff --git a/test/functional/legacy/075_maparg_spec.lua b/test/functional/legacy/075_maparg_spec.lua index e9d2acdaf5..fcfd33ec46 100644 --- a/test/functional/legacy/075_maparg_spec.lua +++ b/test/functional/legacy/075_maparg_spec.lua @@ -3,46 +3,48 @@ local helpers = require('test.functional.helpers')(after_each) local clear, feed = helpers.clear, helpers.feed -local execute, expect = helpers.execute, helpers.expect +local command, expect = helpers.command, helpers.expect +local wait = helpers.wait describe('maparg()', function() setup(clear) it('is working', function() - execute('set cpo-=<') + command('set cpo-=<') -- Test maparg() with a string result - execute('map foo<C-V> is<F4>foo') - execute('vnoremap <script> <buffer> <expr> <silent> bar isbar') - execute([[call append('$', maparg('foo<C-V>'))]]) - execute([[call append('$', string(maparg('foo<C-V>', '', 0, 1)))]]) - execute([[call append('$', string(maparg('bar', '', 0, 1)))]]) - execute('map <buffer> <nowait> foo bar') - execute([[call append('$', string(maparg('foo', '', 0, 1)))]]) - execute('map abc x<char-114>x') - execute([[call append('$', maparg('abc'))]]) - execute('map abc y<S-char-114>y') - execute([[call append('$', maparg('abc'))]]) + command('map foo<C-V> is<F4>foo') + command('vnoremap <script> <buffer> <expr> <silent> bar isbar') + command([[call append('$', maparg('foo<C-V>'))]]) + command([[call append('$', string(maparg('foo<C-V>', '', 0, 1)))]]) + command([[call append('$', string(maparg('bar', '', 0, 1)))]]) + command('map <buffer> <nowait> foo bar') + command([[call append('$', string(maparg('foo', '', 0, 1)))]]) + command('map abc x<char-114>x') + command([[call append('$', maparg('abc'))]]) + command('map abc y<S-char-114>y') + command([[call append('$', maparg('abc'))]]) feed('Go<esc>:<cr>') + wait() -- Outside of the range, minimum - execute('inoremap <Char-0x1040> a') - execute([[execute "normal a\u1040\<Esc>"]]) + command('inoremap <Char-0x1040> a') + command([[execute "normal a\u1040\<Esc>"]]) -- Inside of the range, minimum - execute('inoremap <Char-0x103f> b') - execute([[execute "normal a\u103f\<Esc>"]]) + command('inoremap <Char-0x103f> b') + command([[execute "normal a\u103f\<Esc>"]]) -- Inside of the range, maximum - execute('inoremap <Char-0xf03f> c') - execute([[execute "normal a\uf03f\<Esc>"]]) + command('inoremap <Char-0xf03f> c') + command([[execute "normal a\uf03f\<Esc>"]]) -- Outside of the range, maximum - execute('inoremap <Char-0xf040> d') - execute([[execute "normal a\uf040\<Esc>"]]) + command('inoremap <Char-0xf040> d') + command([[execute "normal a\uf040\<Esc>"]]) -- Remove empty line - execute('1d') + command('1d') -- Assert buffer contents. expect([[ diff --git a/test/functional/legacy/077_mf_hash_grow_spec.lua b/test/functional/legacy/077_mf_hash_grow_spec.lua index b43263300d..c692127213 100644 --- a/test/functional/legacy/077_mf_hash_grow_spec.lua +++ b/test/functional/legacy/077_mf_hash_grow_spec.lua @@ -7,8 +7,12 @@ -- If it isn't available then the test will be skipped. local helpers = require('test.functional.helpers')(after_each) + local feed = helpers.feed -local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect +local wait = helpers.wait +local clear = helpers.clear +local expect = helpers.expect +local command = helpers.command describe('mf_hash_grow()', function() setup(clear) @@ -18,19 +22,21 @@ describe('mf_hash_grow()', function() pending('was not tested because cksum was not found', function() end) else it('is working', function() - execute('set fileformat=unix undolevels=-1') + command('set fileformat=unix undolevels=-1') -- Fill the buffer with numbers 1 - 2000000 - execute('let i = 1') - execute('while i <= 2000000 | call append(i, range(i, i + 99)) | let i += 100 | endwhile') + command('let i = 1') + command('while i <= 2000000 | call append(i, range(i, i + 99)) | let i += 100 | endwhile') -- Delete empty first line, save to Xtest, and clear buffer feed('ggdd<cr>') - execute('w! Xtest') + wait() + command('w! Xtest') feed('ggdG<cr>') + wait() -- Calculate the cksum of Xtest and delete first line - execute('r !cksum Xtest') + command('r !cksum Xtest') feed('ggdd<cr>') -- Assert correct output of cksum. diff --git a/test/functional/legacy/080_substitute_spec.lua b/test/functional/legacy/080_substitute_spec.lua index 1bdae9be59..faeb61e3af 100644 --- a/test/functional/legacy/080_substitute_spec.lua +++ b/test/functional/legacy/080_substitute_spec.lua @@ -1,10 +1,10 @@ --- Test for *sub-replace-special* and *sub-replace-expression* on substitue(). --- Test for submatch() on substitue(). +-- Test for *sub-replace-special* and *sub-replace-expression* on substitute(). +-- Test for submatch() on substitute(). -- Test for *:s%* on :substitute. local helpers = require('test.functional.helpers')(after_each) local feed, insert = helpers.feed, helpers.insert -local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect +local clear, feed_command, expect = helpers.clear, helpers.feed_command, helpers.expect local eq, eval = helpers.eq, helpers.eval describe('substitue()', function() @@ -46,17 +46,17 @@ describe('substitue()', function() end it('with "set magic" (TEST_1)', function() - execute('set magic') + feed_command('set magic') test_1_and_2() end) it('with "set nomagic" (TEST_2)', function() - execute('set nomagic') + feed_command('set nomagic') test_1_and_2() end) it('with sub-replace-expression (TEST_3)', function() - execute('set magic&') + feed_command('set magic&') eq('a\\a', eval([[substitute('aAa', 'A', '\="\\"', '')]])) eq('b\\\\b', eval([[substitute('bBb', 'B', '\="\\\\"', '')]])) eq('c\rc', eval([[substitute('cCc', 'C', '\="]]..'\r'..[["', '')]])) @@ -70,7 +70,7 @@ describe('substitue()', function() end) it('with submatch() (TEST_4)', function() - execute('set magic&') + feed_command('set magic&') eq('a\\a', eval([[substitute('aAa', 'A', ]] .. [['\=substitute(submatch(0), ".", "\\", "")', '')]])) eq('b\\b', eval([[substitute('bBb', 'B', ]] .. @@ -92,7 +92,7 @@ describe('substitue()', function() end) it('with submatch() (TEST_5)', function() - execute('set magic&') + feed_command('set magic&') eq('A123456789987654321', eval([[substitute('A123456789', ]] .. [['A\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)', ]] .. [['\=submatch(0) . submatch(9) . submatch(8) . submatch(7) . ]] .. @@ -110,7 +110,7 @@ describe('substitue()', function() -- #2943. it('with submatch or \\ze (TEST_7)', function() - execute('set magic&') + feed_command('set magic&') eq('A\rA', eval("substitute('A\rA', 'A.', '\\=submatch(0)', '')")) eq('B\nB', eval([[substitute("B\nB", 'B.', '\=submatch(0)', '')]])) eq("['B\n']B", @@ -120,7 +120,7 @@ describe('substitue()', function() end) it('with \\zs and \\ze (TEST_10)', function() - execute('set magic&') + feed_command('set magic&') eq('a1a2a3a', eval([[substitute('123', '\zs', 'a', 'g')]])) eq('aaa', eval([[substitute('123', '\zs.', 'a', 'g')]])) eq('1a2a3a', eval([[substitute('123', '.\zs', 'a', 'g')]])) @@ -140,11 +140,11 @@ describe(':substitue', function() ,,X ,,Y ,,Z]]) - execute('set magic&') - execute([[1s/\(^\|,\)\ze\(,\|X\)/\1N/g]]) - execute([[2s/\(^\|,\)\ze\(,\|Y\)/\1N/gc]]) + feed_command('set magic&') + feed_command([[1s/\(^\|,\)\ze\(,\|X\)/\1N/g]]) + feed_command([[2s/\(^\|,\)\ze\(,\|Y\)/\1N/gc]]) feed('a') -- For the dialog of the previous :s command. - execute([[3s/\(^\|,\)\ze\(,\|Z\)/\1N/gc]]) + feed_command([[3s/\(^\|,\)\ze\(,\|Z\)/\1N/gc]]) feed('yy') -- For the dialog of the previous :s command. expect([[ N,,NX @@ -154,8 +154,8 @@ describe(':substitue', function() it('with confirmation dialog (TEST_9)', function() insert('xxx') - execute('set magic&') - execute('s/x/X/gc') + feed_command('set magic&') + feed_command('s/x/X/gc') feed('yyq') -- For the dialog of the previous :s command. expect('XXx') end) diff --git a/test/functional/legacy/081_coptions_movement_spec.lua b/test/functional/legacy/081_coptions_movement_spec.lua index 2ac1332687..993aff2ba2 100644 --- a/test/functional/legacy/081_coptions_movement_spec.lua +++ b/test/functional/legacy/081_coptions_movement_spec.lua @@ -2,7 +2,7 @@ local helpers = require('test.functional.helpers')(after_each) local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local execute, expect = helpers.execute, helpers.expect +local feed_command, expect = helpers.feed_command, helpers.expect describe('coptions', function() setup(clear) @@ -16,18 +16,18 @@ describe('coptions', function() ccc two three four ddd yee yoo four]]) - execute('set cpo-=;') + feed_command('set cpo-=;') feed('gg0tt;D') feed('j0fz;D') feed('j$Fy;D') feed('j$Ty;D') - execute('set cpo+=;') + feed_command('set cpo+=;') feed('j0tt;;D') feed('j$Ty;;D') - + expect([[ aaa two z diff --git a/test/functional/legacy/082_string_comparison_spec.lua b/test/functional/legacy/082_string_comparison_spec.lua index d6f3c45e1f..cfc0b96bce 100644 --- a/test/functional/legacy/082_string_comparison_spec.lua +++ b/test/functional/legacy/082_string_comparison_spec.lua @@ -3,7 +3,7 @@ local helpers = require('test.functional.helpers')(after_each) local feed, source = helpers.feed, helpers.source -local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect +local clear, feed_command, expect = helpers.clear, helpers.feed_command, helpers.expect describe('case-insensitive string comparison in UTF-8', function() setup(clear) @@ -106,11 +106,11 @@ describe('case-insensitive string comparison in UTF-8', function() ]]) -- Test that g~ap changes one paragraph only. - execute('new') + feed_command('new') feed('iabcd<cr><cr>defg<esc>gg0g~ap') - execute('let lns = getline(1,3)') - execute('q!') - execute([[call append(line('$'), lns)]]) + feed_command('let lns = getline(1,3)') + feed_command('q!') + feed_command([[call append(line('$'), lns)]]) -- Assert buffer contents. expect([=[ diff --git a/test/functional/legacy/084_curswant_spec.lua b/test/functional/legacy/084_curswant_spec.lua index 818914eeb9..9809ce5b88 100644 --- a/test/functional/legacy/084_curswant_spec.lua +++ b/test/functional/legacy/084_curswant_spec.lua @@ -25,7 +25,7 @@ describe('curswant', function() let curswant_after = winsaveview().curswant return [a:option_name, curswant_before, curswant_after] endfunction - + new put =['1234567890', '12345'] 1 delete _ @@ -33,7 +33,7 @@ describe('curswant', function() for option_name in target_option_names call add(result, TestCurswant(option_name)) endfor - + new put =map(copy(result), 'join(v:val, '' '')') 1 delete _ diff --git a/test/functional/legacy/088_conceal_tabs_spec.lua b/test/functional/legacy/088_conceal_tabs_spec.lua index 00e7312bf8..c9414679ab 100644 --- a/test/functional/legacy/088_conceal_tabs_spec.lua +++ b/test/functional/legacy/088_conceal_tabs_spec.lua @@ -2,8 +2,8 @@ -- tabulators. local helpers = require('test.functional.helpers')(after_each) -local feed, insert, clear, execute = - helpers.feed, helpers.insert, helpers.clear, helpers.execute +local feed, insert, clear, feed_command = + helpers.feed, helpers.insert, helpers.clear, helpers.feed_command local expect_pos = function(row, col) return helpers.eq({row, col}, helpers.eval('[screenrow(), screencol()]')) @@ -17,19 +17,19 @@ describe('cursor and column position with conceal and tabulators', function() start: .concealed. text |concealed| text - + .concealed. text |concealed| text - + .a. .b. .c. .d. |a| |b| |c| |d|]]) -- Conceal settings. - execute('set conceallevel=2') - execute('set concealcursor=nc') - execute('syntax match test /|/ conceal') + feed_command('set conceallevel=2') + feed_command('set concealcursor=nc') + feed_command('syntax match test /|/ conceal') -- Start test. - execute('/^start:') + feed_command('/^start:') feed('ztj') expect_pos(2, 1) -- We should end up in the same column when running these commands on the @@ -78,10 +78,10 @@ describe('cursor and column position with conceal and tabulators', function() expect_pos(9, 25) feed('$') expect_pos(9, 26) - execute('set lbr') + feed_command('set lbr') feed('$') expect_pos(9, 26) - execute('set list listchars=tab:>-') + feed_command('set list listchars=tab:>-') feed('0') expect_pos(9, 1) feed('W') diff --git a/test/functional/legacy/091_context_variables_spec.lua b/test/functional/legacy/091_context_variables_spec.lua index edf497d397..c08a58e14b 100644 --- a/test/functional/legacy/091_context_variables_spec.lua +++ b/test/functional/legacy/091_context_variables_spec.lua @@ -13,6 +13,14 @@ describe('context variables', function() -- Test for getbufvar(). -- Use strings to test for memory leaks. source([[ + function Getbufscope(buf, ...) + let ret = call('getbufvar', [a:buf, ''] + a:000) + if type(ret) == type({}) + return filter(copy(ret), 'v:key isnot# "changedtick"') + else + return ret + endif + endfunction let t:testvar='abcd' $put =string(gettabvar(1, 'testvar')) $put =string(gettabvar(1, 'testvar')) @@ -20,14 +28,14 @@ describe('context variables', function() let def_num = '5678' $put =string(getbufvar(1, 'var_num')) $put =string(getbufvar(1, 'var_num', def_num)) - $put =string(getbufvar(1, '')) - $put =string(getbufvar(1, '', def_num)) + $put =string(Getbufscope(1)) + $put =string(Getbufscope(1, def_num)) unlet b:var_num $put =string(getbufvar(1, 'var_num', def_num)) - $put =string(getbufvar(1, '')) - $put =string(getbufvar(1, '', def_num)) - $put =string(getbufvar(9, '')) - $put =string(getbufvar(9, '', def_num)) + $put =string(Getbufscope(1)) + $put =string(Getbufscope(1, def_num)) + $put =string(Getbufscope(9)) + $put =string(Getbufscope(9, def_num)) unlet def_num $put =string(getbufvar(1, '&autoindent')) $put =string(getbufvar(1, '&autoindent', 1)) diff --git a/test/functional/legacy/092_mksession_cursor_cols_utf8_spec.lua b/test/functional/legacy/092_mksession_cursor_cols_utf8_spec.lua index f8564384e9..44f1664abe 100644 --- a/test/functional/legacy/092_mksession_cursor_cols_utf8_spec.lua +++ b/test/functional/legacy/092_mksession_cursor_cols_utf8_spec.lua @@ -5,7 +5,7 @@ local helpers = require('test.functional.helpers')(after_each) local feed, insert = helpers.feed, helpers.insert -local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect +local clear, feed_command, expect = helpers.clear, helpers.feed_command, helpers.expect describe('store cursor position in session file in UTF-8', function() setup(clear) @@ -29,15 +29,15 @@ describe('store cursor position in session file in UTF-8', function() -- This test requires the buffer to correspond to a file on disk, here named -- "test.in", because otherwise :mksession won't write out the cursor column -- info needed for verification. - execute('write! test.in') + feed_command('write! test.in') - execute('set sessionoptions=buffers splitbelow fileencoding=utf-8') + feed_command('set sessionoptions=buffers splitbelow fileencoding=utf-8') -- Move the cursor through the buffer lines and position it with "|". Using -- :split after every normal mode command is a trick to have multiple -- cursors on the screen that can all be stored in the session file. - execute('/^start:') - execute('vsplit') + feed_command('/^start:') + feed_command('vsplit') feed('j16|:split<cr>') feed('j16|:split<cr>') feed('j16|:split<cr>') @@ -49,9 +49,9 @@ describe('store cursor position in session file in UTF-8', function() -- Again move the cursor through the buffer and position it with "|". This -- time also perform a horizontal scroll at every step. - execute('wincmd l') - execute('/^start:') - execute('set nowrap') + feed_command('wincmd l') + feed_command('/^start:') + feed_command('set nowrap') feed('j16|3zl:split<cr>') feed('j016|3zl:split<cr>') feed('j016|3zl:split<cr>') @@ -62,9 +62,9 @@ describe('store cursor position in session file in UTF-8', function() feed('j016|3zl:split<cr>') -- Create the session file, read it back in, and prepare for verification. - execute('mksession! test.out') - execute('new test.out') - execute([[v/\(^ *normal! 0\|^ *exe 'normal!\)/d]]) + feed_command('mksession! test.out') + feed_command('new test.out') + feed_command([[v/\(^ *normal! 0\|^ *exe 'normal!\)/d]]) -- Assert buffer contents. expect([[ diff --git a/test/functional/legacy/093_mksession_cursor_cols_latin1_spec.lua b/test/functional/legacy/093_mksession_cursor_cols_latin1_spec.lua index 40be7dcca4..49bc43f76f 100644 --- a/test/functional/legacy/093_mksession_cursor_cols_latin1_spec.lua +++ b/test/functional/legacy/093_mksession_cursor_cols_latin1_spec.lua @@ -5,7 +5,7 @@ local helpers = require('test.functional.helpers')(after_each) local feed, insert = helpers.feed, helpers.insert -local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect +local clear, feed_command, expect = helpers.clear, helpers.feed_command, helpers.expect if helpers.pending_win32(pending) then return end @@ -30,13 +30,13 @@ describe('store cursor position in session file in Latin-1', function() Aไ๖ three mulTibyte characters]]) -- Must write buffer to disk for :mksession. See the comments in -- "092_mksession_cursor_cols_utf8_spec.lua". - execute('write! test.in') + feed_command('write! test.in') - execute('set sessionoptions=buffers splitbelow fileencoding=latin1') + feed_command('set sessionoptions=buffers splitbelow fileencoding=latin1') -- Move the cursor through the buffer lines and position it with "|". - execute('/^start:') - execute('vsplit') + feed_command('/^start:') + feed_command('vsplit') feed('j16|:split<cr>') feed('j16|:split<cr>') feed('j16|:split<cr>') @@ -48,9 +48,9 @@ describe('store cursor position in session file in Latin-1', function() -- Again move the cursor through the buffer and position it with "|". This -- time also perform a horizontal scroll at every step. - execute('wincmd l') - execute('/^start:') - execute('set nowrap') + feed_command('wincmd l') + feed_command('/^start:') + feed_command('set nowrap') feed('j16|3zl:split<cr>') feed('j016|3zl:split<cr>') feed('j016|3zl:split<cr>') @@ -61,9 +61,9 @@ describe('store cursor position in session file in Latin-1', function() feed('j016|3zl:split<cr>') -- Create the session file, read it back in, and prepare for verification. - execute('mksession! test.out') - execute('new test.out') - execute([[v/\(^ *normal! 0\|^ *exe 'normal!\)/d]]) + feed_command('mksession! test.out') + feed_command('new test.out') + feed_command([[v/\(^ *normal! 0\|^ *exe 'normal!\)/d]]) -- Assert buffer contents. expect([[ diff --git a/test/functional/legacy/094_visual_mode_operators_spec.lua b/test/functional/legacy/094_visual_mode_operators_spec.lua index a52fa00672..84e384050a 100644 --- a/test/functional/legacy/094_visual_mode_operators_spec.lua +++ b/test/functional/legacy/094_visual_mode_operators_spec.lua @@ -6,7 +6,7 @@ local helpers = require('test.functional.helpers')(after_each) local feed, insert, source = helpers.feed, helpers.insert, helpers.source -local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect +local clear, feed_command, expect = helpers.clear, helpers.feed_command, helpers.expect -- Vim script user functions needed for some of the test cases. local function source_user_functions() @@ -54,38 +54,38 @@ describe('Visual mode and operator', function() it('simple change in Visual mode', function() insert([[ apple banana cherry - + line 1 line 1 line 2 line 2 line 3 line 3 line 4 line 4 line 5 line 5 line 6 line 6 - + xxxxxxxxxxxxx xxxxxxxxxxxxx xxxxxxxxxxxxx xxxxxxxxxxxxx]]) -- Exercise characterwise Visual mode plus operator, with count and repeat. - execute('/^apple') + feed_command('/^apple') feed('lvld.l3vd.') -- Same in linewise Visual mode. - execute('/^line 1') + feed_command('/^line 1') feed('Vcnewline<esc>j.j2Vd.') -- Same in blockwise Visual mode. - execute('/^xxxx') + feed_command('/^xxxx') feed('<c-v>jlc <esc>l.l2<c-v>c----<esc>l.') -- Assert buffer contents. expect([[ a y - + newline newline - + --------x --------x xxxx--------x @@ -98,15 +98,15 @@ describe('Visual mode and operator', function() JambuRambutanBananaTangerineMango]]) -- Set up Visual mode mappings. - execute('vnoremap W /\\u/s-1<CR>') - execute('vnoremap iW :<C-U>call SelectInCaps()<CR>') + feed_command('vnoremap W /\\u/s-1<CR>') + feed_command('vnoremap iW :<C-U>call SelectInCaps()<CR>') -- Do a simple change using the simple vmap, also with count and repeat. - execute('/^Kiwi') + feed_command('/^Kiwi') feed('vWcNo<esc>l.fD2vd.') -- Same, using the vmap that maps to an Ex command. - execute('/^Jambu') + feed_command('/^Jambu') feed('llviWc-<esc>l.l2vdl.') -- Assert buffer contents. @@ -122,20 +122,20 @@ describe('Visual mode and operator', function() LemonNectarineZ]]) -- Set up Operator-pending mode mappings. - execute('onoremap W /\\u/<CR>') - execute('onoremap <Leader>W :<C-U>call MoveToCap()<CR>') - execute('onoremap iW :<C-U>call SelectInCaps()<CR>') + feed_command('onoremap W /\\u/<CR>') + feed_command('onoremap <Leader>W :<C-U>call MoveToCap()<CR>') + feed_command('onoremap iW :<C-U>call SelectInCaps()<CR>') -- Do a simple change using the simple omap, also with count and repeat. - execute('/^Pineapple') + feed_command('/^Pineapple') feed('cW-<esc>l.l2.l.') -- Same, using the omap that maps to an Ex command to move the cursor. - execute('/^Juniper') + feed_command('/^Juniper') feed('g?\\WfD.') -- Same, using the omap that uses Ex and Visual mode (custom text object). - execute('/^Lemon') + feed_command('/^Lemon') feed('yiWPlciWNew<esc>fr.') -- Assert buffer contents. @@ -159,7 +159,7 @@ describe('Visual mode and operator', function() -- changed, taking into account the v/V/<c-v> modifier given; or -- - abort the operation by pressing Escape: no change to the buffer is -- carried out. - execute('/^zzzz') + feed_command('/^zzzz') feed([[dV:<cr>dv:<cr>:set noma | let v:errmsg = ''<cr>]]) feed([[d:<cr>:set ma | put = v:errmsg =~# '^E21' ? 'ok' : 'failed'<cr>]]) feed([[dv:<esc>dV:<esc>:set noma | let v:errmsg = ''<cr>]]) @@ -180,7 +180,7 @@ describe('Visual mode and operator', function() feed('v$p') expect([[ - + x]]) end) @@ -189,7 +189,7 @@ describe('Visual mode and operator', function() feed('kkv$d') expect([[ - + b c]]) end) @@ -199,7 +199,7 @@ describe('Visual mode and operator', function() feed('kkvj$d') expect([[ - + c]]) end) @@ -208,7 +208,7 @@ describe('Visual mode and operator', function() feed('v$d') expect([[ - + a b ]]) @@ -219,7 +219,7 @@ describe('Visual mode and operator', function() feed('kvj$d') expect([[ - + a ]]) end) @@ -235,7 +235,7 @@ describe('Visual mode and operator', function() feed('kkgh<End><Del>') expect([[ - + b c]]) end) @@ -245,7 +245,7 @@ describe('Visual mode and operator', function() feed('kkgh<Down><End><Del>') expect([[ - + c]]) end) @@ -254,7 +254,7 @@ describe('Visual mode and operator', function() feed('gh<End><Del>') expect([[ - + a b ]]) @@ -265,7 +265,7 @@ describe('Visual mode and operator', function() feed('kgh<Down><End><Del>') expect([[ - + a ]]) end) @@ -281,7 +281,7 @@ describe('Visual mode and operator', function() feed(' kkgH<Del> ') expect([[ - + b c]]) end) @@ -291,7 +291,7 @@ describe('Visual mode and operator', function() feed('kkgH<Down><Del>') expect([[ - + c]]) end) @@ -300,7 +300,7 @@ describe('Visual mode and operator', function() feed('gH<Del>') expect([[ - + a b]]) end) @@ -310,7 +310,7 @@ describe('Visual mode and operator', function() feed('kgH<Down><Del>') expect([[ - + a]]) end) end) @@ -318,25 +318,25 @@ describe('Visual mode and operator', function() describe('v_p:', function() it('replace last character with line register at middle line', function() put_aaabbbccc() - execute('-2yank') + feed_command('-2yank') feed('k$vp') expect([[ - + aaa bb aaa - + ccc]]) end) it('replace last character with line register at middle line selecting newline', function() put_aaabbbccc() - execute('-2yank') + feed_command('-2yank') feed('k$v$p') expect([[ - + aaa bb aaa @@ -345,11 +345,11 @@ describe('Visual mode and operator', function() it('replace last character with line register at last line', function() put_aaabbbccc() - execute('-2yank') + feed_command('-2yank') feed('$vp') expect([[ - + aaa bbb cc @@ -359,11 +359,11 @@ describe('Visual mode and operator', function() it('replace last character with line register at last line selecting newline', function() put_aaabbbccc() - execute('-2yank') + feed_command('-2yank') feed('$v$p') expect([[ - + aaa bbb cc @@ -380,7 +380,7 @@ describe('Visual mode and operator', function() feed('kv3lyjv3lpgvcxxx<Esc>') expect([[ - + zzz xxx ]]) end) @@ -392,7 +392,7 @@ describe('Visual mode and operator', function() feed('0v3l<Esc>gvcxxx<Esc>') expect([[ - + xxx ]]) end) end) diff --git a/test/functional/legacy/096_location_list_spec.lua b/test/functional/legacy/096_location_list_spec.lua index eac8d6356d..85c4fe0ec4 100644 --- a/test/functional/legacy/096_location_list_spec.lua +++ b/test/functional/legacy/096_location_list_spec.lua @@ -8,7 +8,7 @@ local helpers = require('test.functional.helpers')(after_each) local source = helpers.source -local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect +local clear, command, expect = helpers.clear, helpers.command, helpers.expect describe('location list', function() setup(clear) @@ -28,7 +28,7 @@ describe('location list', function() function! ReadTestProtocol(name) let base = substitute(a:name, '\v^test://(.*)%(\.[^.]+)?', '\1', '') let word = substitute(base, '\v(.*)\..*', '\1', '') - + setl modifiable setl noreadonly setl noswapfile @@ -37,9 +37,9 @@ describe('location list', function() " For problem 2: " 'buftype' has to be set to reproduce the constant opening of new windows. setl buftype=nofile - + call setline(1, word) - + setl nomodified setl nomodifiable setl readonly @@ -71,74 +71,77 @@ describe('location list', function() ]]) -- Set up the result buffer "test.out". - execute('enew') - execute('w! test.out') - execute('b 1') + command('enew') + command('w! test.out') + command('b 1') -- Test A. -- Open a new buffer as the sole window, rewind and open the prepopulated -- location list and navigate through the entries. - execute('lrewind') - execute('enew') - execute('lopen') - execute('lnext', 'lnext', 'lnext', 'lnext') + command('lrewind') + command('enew') + command('lopen') + command(('lnext|'):rep(4)) -- Split the window, copying the location list, then open the copied -- location list and again navigate forward. - execute('vert split') - execute('wincmd L') - execute('lopen') - execute('wincmd p') - execute('lnext') + command('vert split') + command('wincmd L') + command('lopen') + command('wincmd p') + command('lnext') -- Record the current file name and the file name of the corresponding -- location list entry, then open the result buffer. - execute('let fileName = expand("%")') - execute('wincmd p') - execute([[let locationListFileName = substitute(getline(line('.')), '\([^|]*\)|.*', '\1', '')]]) - execute('wincmd n') - execute('wincmd K') - execute('b test.out') + command('let fileName = expand("%")') + command('wincmd p') + command([[let locationListFileName = substitute(getline(line('.')), '\([^|]*\)|.*', '\1', '')]]) + command('wincmd n') + command('wincmd K') + command('b test.out') -- Prepare test output and write it to the result buffer. - execute([[let fileName = substitute(fileName, '\\', '/', 'g')]]) - execute([[let locationListFileName = substitute(locationListFileName, '\\', '/', 'g')]]) - execute([[call append(line('$'), "Test A:")]]) - execute([[call append(line('$'), " - file name displayed: " . fileName)]]) - execute([[call append(line('$'), " - quickfix claims that the file name displayed is: " . locationListFileName)]]) - execute('w') + command([[let fileName = substitute(fileName, '\\', '/', 'g')]]) + command([[let locationListFileName = substitute(locationListFileName, '\\', '/', 'g')]]) + command([[call append(line('$'), "Test A:")]]) + command([[call append(line('$'), " - file name displayed: " . fileName)]]) + command([[call append(line('$'), " - quickfix claims that the file name displayed is: " . locationListFileName)]]) + command('w') -- Clean slate for the next test. - execute('wincmd o') - execute('b 1') + command('wincmd o') + command('b 1') -- Test B. -- Rewind the location list, then open it and browse through it by running -- ":{number}" followed by Enter repeatedly in the location list window. - execute('lrewind') - execute('lopen') - execute('2', [[exe "normal \\<CR>"]]) - execute('wincmd p') - execute('3', [[exe "normal \<CR>"]]) - execute('wincmd p') - execute('4', [[exe "normal \<CR>"]]) + command('lrewind') + command('lopen') + command('2') + command([[exe "normal \\<CR>"]]) + command('wincmd p') + command('3') + command([[exe "normal \<CR>"]]) + command('wincmd p') + command('4') + command([[exe "normal \<CR>"]]) -- Record the number of windows open, then go back to the result buffer. - execute('let numberOfWindowsOpen = winnr("$")') - execute('wincmd n') - execute('wincmd K') - execute('b test.out') + command('let numberOfWindowsOpen = winnr("$")') + command('wincmd n') + command('wincmd K') + command('b test.out') -- Prepare test output and write it to the result buffer. - execute('call append(line("$"), "Test B:")') - execute('call append(line("$"), " - number of window open: " . numberOfWindowsOpen)') - execute('w') + command('call append(line("$"), "Test B:")') + command('call append(line("$"), " - number of window open: " . numberOfWindowsOpen)') + command('w') -- Clean slate. - execute('wincmd o') - execute('b 1') + command('wincmd o') + command('b 1') -- Test C. @@ -146,38 +149,41 @@ describe('location list', function() -- Enter browsing. But this time, move the location list window to the top -- to check whether it (the first window found) will be reused when we try -- to open new windows. - execute('lrewind') - execute('lopen') - execute('wincmd K') - execute('2', [[exe "normal \<CR>"]]) - execute('wincmd p') - execute('3', [[exe "normal \<CR>"]]) - execute('wincmd p') - execute('4', [[exe "normal \<CR>"]]) + command('lrewind') + command('lopen') + command('wincmd K') + command('2') + command([[exe "normal \<CR>"]]) + command('wincmd p') + command('3') + command([[exe "normal \<CR>"]]) + command('wincmd p') + command('4') + command([[exe "normal \<CR>"]]) -- Record the 'buftype' of window 1 (the location list) and the buffer name -- of window 2 (the current "test protocol" buffer), then go back to the -- result buffer. - execute('1wincmd w') - execute('let locationListWindowBufType = &buftype') - execute('2wincmd w') - execute('let bufferName = expand("%")') - execute('wincmd n') - execute('wincmd K') - execute('b test.out') + command('1wincmd w') + command('let locationListWindowBufType = &buftype') + command('2wincmd w') + command('let bufferName = expand("%")') + command('wincmd n') + command('wincmd K') + command('b test.out') -- Prepare test output and write it to the result buffer. - execute([[let bufferName = substitute(bufferName, '\\', '/', 'g')]]) - execute([[call append(line("$"), "Test C:")]]) - execute([[call append(line('$'), " - 'buftype' of the location list window: " . locationListWindowBufType)]]) - execute([[call append(line('$'), " - buffer displayed in the 2nd window: " . bufferName)]]) - execute('w') - execute('wincmd o') - execute('b 1') + command([[let bufferName = substitute(bufferName, '\\', '/', 'g')]]) + command([[call append(line("$"), "Test C:")]]) + command([[call append(line('$'), " - 'buftype' of the location list window: " . locationListWindowBufType)]]) + command([[call append(line('$'), " - buffer displayed in the 2nd window: " . bufferName)]]) + command('w') + command('wincmd o') + command('b 1') -- Assert buffer contents. expect([[ - + Test A: - file name displayed: test://bar.txt - quickfix claims that the file name displayed is: test://bar.txt diff --git a/test/functional/legacy/097_glob_path_spec.lua b/test/functional/legacy/097_glob_path_spec.lua index 23f1427cb5..6b63a317f1 100644 --- a/test/functional/legacy/097_glob_path_spec.lua +++ b/test/functional/legacy/097_glob_path_spec.lua @@ -4,7 +4,7 @@ local helpers = require('test.functional.helpers')(after_each) local clear = helpers.clear -local execute, expect = helpers.execute, helpers.expect +local command, expect = helpers.command, helpers.expect if helpers.pending_win32(pending) then return end @@ -19,26 +19,26 @@ describe('glob() and globpath()', function() it('is working', function() -- Make sure glob() doesn't use the shell - execute('set shell=doesnotexist') + command('set shell=doesnotexist') -- Consistent sorting of file names - execute('set nofileignorecase') + command('set nofileignorecase') - execute([[$put =glob('Xxx\{')]]) - execute([[$put =glob('Xxx\$')]]) + command([[$put =glob('Xxx\{')]]) + command([[$put =glob('Xxx\$')]]) - execute('w! Xxx{') - execute([[w! Xxx\$]]) - execute([[$put =glob('Xxx\{')]]) - execute([[$put =glob('Xxx\$')]]) + command('silent w! Xxx{') + command([[w! Xxx\$]]) + command([[$put =glob('Xxx\{')]]) + command([[$put =glob('Xxx\$')]]) - execute("$put =string(globpath('sautest/autoload', '*.vim'))") - execute("$put =string(globpath('sautest/autoload', '*.vim', 0, 1))") + command("$put =string(globpath('sautest/autoload', '*.vim'))") + command("$put =string(globpath('sautest/autoload', '*.vim', 0, 1))") expect([=[ - - - + + + Xxx{ Xxx$ 'sautest/autoload/Test104.vim diff --git a/test/functional/legacy/101_hlsearch_spec.lua b/test/functional/legacy/101_hlsearch_spec.lua index fa29e5fbe8..eff755221c 100644 --- a/test/functional/legacy/101_hlsearch_spec.lua +++ b/test/functional/legacy/101_hlsearch_spec.lua @@ -2,52 +2,52 @@ local helpers = require('test.functional.helpers')(after_each) local clear, feed = helpers.clear, helpers.feed -local execute, expect = helpers.execute, helpers.expect +local feed_command, expect = helpers.feed_command, helpers.expect describe('v:hlsearch', function() setup(clear) it('is working', function() -- Last abc: Q - execute('new') - execute([[call setline(1, repeat(['aaa'], 10))]]) - execute('set hlsearch nolazyredraw') - execute('let r=[]') - execute('command -nargs=0 -bar AddR :call add(r, [screenattr(1, 1), v:hlsearch])') - execute('/aaa') - execute('AddR') - execute('nohlsearch') - execute('AddR') - execute('let v:hlsearch=1') - execute('AddR') - execute('let v:hlsearch=0') - execute('AddR') - execute('set hlsearch') - execute('AddR') - execute('let v:hlsearch=0') - execute('AddR') + feed_command('new') + feed_command([[call setline(1, repeat(['aaa'], 10))]]) + feed_command('set hlsearch nolazyredraw') + feed_command('let r=[]') + feed_command('command -nargs=0 -bar AddR :call add(r, [screenattr(1, 1), v:hlsearch])') + feed_command('/aaa') + feed_command('AddR') + feed_command('nohlsearch') + feed_command('AddR') + feed_command('let v:hlsearch=1') + feed_command('AddR') + feed_command('let v:hlsearch=0') + feed_command('AddR') + feed_command('set hlsearch') + feed_command('AddR') + feed_command('let v:hlsearch=0') + feed_command('AddR') feed('n:AddR<cr>') - execute('let v:hlsearch=0') - execute('AddR') - execute('/') - execute('AddR') - execute('set nohls') - execute('/') - execute('AddR') - execute('let r1=r[0][0]') + feed_command('let v:hlsearch=0') + feed_command('AddR') + feed_command('/') + feed_command('AddR') + feed_command('set nohls') + feed_command('/') + feed_command('AddR') + feed_command('let r1=r[0][0]') -- I guess it is not guaranteed that screenattr outputs always the same character - execute([[call map(r, 'v:val[1].":".(v:val[0]==r1?"highlighted":"not highlighted")')]]) - execute('try') - execute(' let v:hlsearch=[]') - execute('catch') - execute([[ call add(r, matchstr(v:exception,'^Vim(let):E\d\+:'))]]) - execute('endtry') - execute('bwipeout!') - execute('$put=r') - execute('call garbagecollect(1)') - execute('call getchar()') - execute('1d', '1d') + feed_command([[call map(r, 'v:val[1].":".(v:val[0]==r1?"highlighted":"not highlighted")')]]) + feed_command('try') + feed_command(' let v:hlsearch=[]') + feed_command('catch') + feed_command([[ call add(r, matchstr(v:exception,'^Vim(let):E\d\+:'))]]) + feed_command('endtry') + feed_command('bwipeout!') + feed_command('$put=r') + feed_command('call garbagecollect(1)') + feed_command('call getchar()') + feed_command('1d', '1d') -- Assert buffer contents. expect([[ diff --git a/test/functional/legacy/102_fnameescape_spec.lua b/test/functional/legacy/102_fnameescape_spec.lua index c1a6c57956..c8ee423ff3 100644 --- a/test/functional/legacy/102_fnameescape_spec.lua +++ b/test/functional/legacy/102_fnameescape_spec.lua @@ -2,19 +2,19 @@ local helpers = require('test.functional.helpers')(after_each) local clear = helpers.clear -local execute, expect = helpers.execute, helpers.expect +local command, expect = helpers.command, helpers.expect describe('fnameescape', function() setup(clear) it('is working', function() - execute('let fname = "Xspa ce"') - execute('try', 'exe "w! " . fnameescape(fname)', "put='Space'", 'endtry') - execute('let fname = "Xemark!"') - execute('try', 'exe "w! " . fnameescape(fname)', "put='ExclamationMark'", 'endtry') + command('let fname = "Xspa ce"') + command('try | exe "w! " . fnameescape(fname) | put=\'Space\' | endtry') + command('let fname = "Xemark!"') + command('try | exe "w! " . fnameescape(fname) | put=\'ExclamationMark\' | endtry') expect([[ - + Space ExclamationMark]]) end) diff --git a/test/functional/legacy/104_let_assignment_spec.lua b/test/functional/legacy/104_let_assignment_spec.lua index 27c3715231..a03bb026f6 100644 --- a/test/functional/legacy/104_let_assignment_spec.lua +++ b/test/functional/legacy/104_let_assignment_spec.lua @@ -2,13 +2,13 @@ local helpers = require('test.functional.helpers')(after_each) local clear, source = helpers.clear, helpers.source -local execute, expect = helpers.execute, helpers.expect +local command, expect = helpers.command, helpers.expect describe(':let', function() setup(clear) it('is working', function() - execute('set runtimepath+=test/functional/fixtures') + command('set runtimepath+=test/functional/fixtures') -- Test to not autoload when assigning. It causes internal error. source([[ @@ -34,7 +34,7 @@ describe(':let', function() endfor]]) -- Remove empty line - execute('1d') + command('1d') -- Assert buffer contents. expect([[ diff --git a/test/functional/legacy/106_errorformat_spec.lua b/test/functional/legacy/106_errorformat_spec.lua index 2b17d63378..5d76adc786 100644 --- a/test/functional/legacy/106_errorformat_spec.lua +++ b/test/functional/legacy/106_errorformat_spec.lua @@ -2,19 +2,19 @@ local helpers = require('test.functional.helpers')(after_each) local clear = helpers.clear -local execute, expect = helpers.execute, helpers.expect +local command, expect = helpers.command, helpers.expect describe('errorformat', function() setup(clear) it('is working', function() - execute("set efm=%EEEE%m,%WWWW%m,%+CCCC%.%#,%-GGGG%.%#") - execute("cgetexpr ['WWWW', 'EEEE', 'CCCC']") - execute("$put =strtrans(string(map(getqflist(), '[v:val.text, v:val.valid]')))") - execute("cgetexpr ['WWWW', 'GGGG', 'EEEE', 'CCCC']") - execute("$put =strtrans(string(map(getqflist(), '[v:val.text, v:val.valid]')))") - execute("cgetexpr ['WWWW', 'GGGG', 'ZZZZ', 'EEEE', 'CCCC', 'YYYY']") - execute("$put =strtrans(string(map(getqflist(), '[v:val.text, v:val.valid]')))") + command("set efm=%EEEE%m,%WWWW%m,%+CCCC%.%#,%-GGGG%.%#") + command("cgetexpr ['WWWW', 'EEEE', 'CCCC']") + command("$put =strtrans(string(map(getqflist(), '[v:val.text, v:val.valid]')))") + command("cgetexpr ['WWWW', 'GGGG', 'EEEE', 'CCCC']") + command("$put =strtrans(string(map(getqflist(), '[v:val.text, v:val.valid]')))") + command("cgetexpr ['WWWW', 'GGGG', 'ZZZZ', 'EEEE', 'CCCC', 'YYYY']") + command("$put =strtrans(string(map(getqflist(), '[v:val.text, v:val.valid]')))") expect([=[ diff --git a/test/functional/legacy/107_adjust_window_and_contents_spec.lua b/test/functional/legacy/107_adjust_window_and_contents_spec.lua index 610bac7f21..836a0f8f24 100644 --- a/test/functional/legacy/107_adjust_window_and_contents_spec.lua +++ b/test/functional/legacy/107_adjust_window_and_contents_spec.lua @@ -2,8 +2,11 @@ local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') + +local wait = helpers.wait +local clear = helpers.clear local insert = helpers.insert -local clear, execute = helpers.clear, helpers.execute +local command = helpers.command if helpers.pending_win32(pending) then return end @@ -15,31 +18,34 @@ describe('107', function() screen:attach() insert('start:') - execute('new') - execute('call setline(1, range(1,256))') - execute('let r=[]') - execute('func! GetScreenStr(row)') - execute(' let str = ""') - execute(' for c in range(1,3)') - execute(' let str .= nr2char(screenchar(a:row, c))') - execute(' endfor') - execute(' return str') - execute('endfunc') - execute([[exe ":norm! \<C-W>t\<C-W>=1Gzt\<C-W>w\<C-W>+"]]) - execute('let s3=GetScreenStr(1)') - execute('wincmd p') - execute('call add(r, [line("w0"), s3])') - execute([[exe ":norm! \<C-W>t\<C-W>=50Gzt\<C-W>w\<C-W>+"]]) - execute('let s3=GetScreenStr(1)') - execute('wincmd p') - execute('call add(r, [line("w0"), s3])') - execute([[exe ":norm! \<C-W>t\<C-W>=59Gzt\<C-W>w\<C-W>+"]]) - execute('let s3=GetScreenStr(1)') - execute(':wincmd p') - execute('call add(r, [line("w0"), s3])') - execute('bwipeout!') - execute('$put=r') - execute('call garbagecollect(1)') + wait() + command('new') + command('call setline(1, range(1,256))') + command('let r=[]') + command([[ + func! GetScreenStr(row) + let str = "" + for c in range(1,3) + let str .= nr2char(screenchar(a:row, c)) + endfor + return str + endfunc + ]]) + command([[exe ":norm! \<C-W>t\<C-W>=1Gzt\<C-W>w\<C-W>+"]]) + command('let s3=GetScreenStr(1)') + command('wincmd p') + command('call add(r, [line("w0"), s3])') + command([[exe ":norm! \<C-W>t\<C-W>=50Gzt\<C-W>w\<C-W>+"]]) + command('let s3=GetScreenStr(1)') + command('wincmd p') + command('call add(r, [line("w0"), s3])') + command([[exe ":norm! \<C-W>t\<C-W>=59Gzt\<C-W>w\<C-W>+"]]) + command('let s3=GetScreenStr(1)') + command(':wincmd p') + command('call add(r, [line("w0"), s3])') + command('bwipeout!') + command('$put=r') + command('call garbagecollect(1)') screen:expect([[ start: | @@ -55,7 +61,7 @@ describe('107', function() ~ | ~ | ~ | - :call garbagecollect(1) | + 3 more lines | ]]) end) end) diff --git a/test/functional/legacy/108_backtrace_debug_commands_spec.lua b/test/functional/legacy/108_backtrace_debug_commands_spec.lua index a03092e446..b2e2fa4ed3 100644 --- a/test/functional/legacy/108_backtrace_debug_commands_spec.lua +++ b/test/functional/legacy/108_backtrace_debug_commands_spec.lua @@ -2,32 +2,32 @@ local helpers = require('test.functional.helpers')(after_each) local feed, clear = helpers.feed, helpers.clear -local execute, expect = helpers.execute, helpers.expect +local feed_command, expect = helpers.feed_command, helpers.expect describe('108', function() before_each(clear) it('is working', function() - execute('lang mess C') - execute('function! Foo()') - execute(' let var1 = 1') - execute(' let var2 = Bar(var1) + 9') - execute(' return var2') - execute('endfunction') - execute('function! Bar(var)') - execute(' let var1 = 2 + a:var') - execute(' let var2 = Bazz(var1) + 4') - execute(' return var2') - execute('endfunction') - execute('function! Bazz(var)') - execute(' let var1 = 3 + a:var') - execute(' let var3 = "another var"') - execute(' return var1') - execute('endfunction') - execute('new') - execute('debuggreedy') - execute('redir => out') - execute('debug echo Foo()') + feed_command('lang mess C') + feed_command('function! Foo()') + feed_command(' let var1 = 1') + feed_command(' let var2 = Bar(var1) + 9') + feed_command(' return var2') + feed_command('endfunction') + feed_command('function! Bar(var)') + feed_command(' let var1 = 2 + a:var') + feed_command(' let var2 = Bazz(var1) + 4') + feed_command(' return var2') + feed_command('endfunction') + feed_command('function! Bazz(var)') + feed_command(' let var1 = 3 + a:var') + feed_command(' let var3 = "another var"') + feed_command(' return var1') + feed_command('endfunction') + feed_command('new') + feed_command('debuggreedy') + feed_command('redir => out') + feed_command('debug echo Foo()') feed('step<cr>') feed('step<cr>') feed('step<cr>') @@ -83,9 +83,9 @@ describe('108', function() feed('fram<cr>') feed([[echo "\n- final result 19:"<cr>]]) feed('cont<cr>') - execute('0debuggreedy') - execute('redir END') - execute('$put =out') + feed_command('0debuggreedy') + feed_command('redir END') + feed_command('$put =out') -- Assert buffer contents. expect([=[ diff --git a/test/functional/legacy/arglist_spec.lua b/test/functional/legacy/arglist_spec.lua index b86d3f0aea..191f145095 100644 --- a/test/functional/legacy/arglist_spec.lua +++ b/test/functional/legacy/arglist_spec.lua @@ -1,7 +1,7 @@ -- Test argument list commands local helpers = require('test.functional.helpers')(after_each) -local clear, execute, eq = helpers.clear, helpers.execute, helpers.eq +local clear, command, eq = helpers.clear, helpers.command, helpers.eq local eval, exc_exec, neq = helpers.eval, helpers.exc_exec, helpers.neq if helpers.pending_win32(pending) then return end @@ -10,12 +10,12 @@ describe('argument list commands', function() before_each(clear) local function init_abc() - execute('args a b c') - execute('next') + command('args a b c') + command('next') end local function reset_arglist() - execute('arga a | %argd') + command('arga a | %argd') end local function assert_fails(cmd, err) @@ -23,183 +23,185 @@ describe('argument list commands', function() end it('test that argidx() works', function() - execute('args a b c') - execute('last') + command('args a b c') + command('last') eq(2, eval('argidx()')) - execute('%argdelete') + command('%argdelete') eq(0, eval('argidx()')) - execute('args a b c') + command('args a b c') eq(0, eval('argidx()')) - execute('next') + command('next') eq(1, eval('argidx()')) - execute('next') + command('next') eq(2, eval('argidx()')) - execute('1argdelete') + command('1argdelete') eq(1, eval('argidx()')) - execute('1argdelete') + command('1argdelete') eq(0, eval('argidx()')) - execute('1argdelete') + command('1argdelete') eq(0, eval('argidx()')) end) it('test that argadd() works', function() - execute('%argdelete') - execute('argadd a b c') + -- Fails with โE474: Invalid argumentโ. Not sure whether it is how it is + -- supposed to behave. + -- command('%argdelete') + command('argadd a b c') eq(0, eval('argidx()')) - execute('%argdelete') - execute('argadd a') + command('%argdelete') + command('argadd a') eq(0, eval('argidx()')) - execute('argadd b c d') + command('argadd b c d') eq(0, eval('argidx()')) init_abc() - execute('argadd x') + command('argadd x') eq({'a', 'b', 'x', 'c'}, eval('argv()')) eq(1, eval('argidx()')) init_abc() - execute('0argadd x') + command('0argadd x') eq({'x', 'a', 'b', 'c'}, eval('argv()')) eq(2, eval('argidx()')) init_abc() - execute('1argadd x') + command('1argadd x') eq({'a', 'x', 'b', 'c'}, eval('argv()')) eq(2, eval('argidx()')) init_abc() - execute('$argadd x') + command('$argadd x') eq({'a', 'b', 'c', 'x'}, eval('argv()')) eq(1, eval('argidx()')) init_abc() - execute('$argadd x') - execute('+2argadd y') + command('$argadd x') + command('+2argadd y') eq({'a', 'b', 'c', 'x', 'y'}, eval('argv()')) eq(1, eval('argidx()')) - execute('%argd') - execute('edit d') - execute('arga') + command('%argd') + command('edit d') + command('arga') eq(1, eval('len(argv())')) eq('d', eval('get(argv(), 0, "")')) - execute('%argd') - execute('new') - execute('arga') + command('%argd') + command('new') + command('arga') eq(0, eval('len(argv())')) end) it('test for [count]argument and [count]argdelete commands', function() reset_arglist() - execute('let save_hidden = &hidden') - execute('set hidden') - execute('let g:buffers = []') - execute('augroup TEST') - execute([[au BufEnter * call add(buffers, expand('%:t'))]]) - execute('augroup END') - - execute('argadd a b c d') - execute('$argu') - execute('$-argu') - execute('-argu') - execute('1argu') - execute('+2argu') - - execute('augroup TEST') - execute('au!') - execute('augroup END') + command('let save_hidden = &hidden') + command('set hidden') + command('let g:buffers = []') + command('augroup TEST') + command([[au BufEnter * call add(buffers, expand('%:t'))]]) + command('augroup END') + + command('argadd a b c d') + command('$argu') + command('$-argu') + command('-argu') + command('1argu') + command('+2argu') + + command('augroup TEST') + command('au!') + command('augroup END') eq({'d', 'c', 'b', 'a', 'c'}, eval('g:buffers')) - execute('redir => result') - execute('ar') - execute('redir END') + command('redir => result') + command('ar') + command('redir END') eq(1, eval([[result =~# 'a b \[c] d']])) - execute('.argd') + command('.argd') eq({'a', 'b', 'd'}, eval('argv()')) - execute('-argd') + command('-argd') eq({'a', 'd'}, eval('argv()')) - execute('$argd') + command('$argd') eq({'a'}, eval('argv()')) - execute('1arga c') - execute('1arga b') - execute('$argu') - execute('$arga x') + command('1arga c') + command('1arga b') + command('$argu') + command('$arga x') eq({'a', 'b', 'c', 'x'}, eval('argv()')) - execute('0arga Y') + command('0arga Y') eq({'Y', 'a', 'b', 'c', 'x'}, eval('argv()')) - execute('%argd') + command('%argd') eq({}, eval('argv()')) - execute('arga a b c d e f') - execute('2,$-argd') + command('arga a b c d e f') + command('2,$-argd') eq({'a', 'f'}, eval('argv()')) - execute('let &hidden = save_hidden') + command('let &hidden = save_hidden') -- Setting the argument list should fail when the current buffer has -- unsaved changes - execute('%argd') - execute('enew!') - execute('set modified') + command('%argd') + command('enew!') + command('set modified') assert_fails('args x y z', 'E37:') - execute('args! x y z') + command('args! x y z') eq({'x', 'y', 'z'}, eval('argv()')) eq('x', eval('expand("%:t")')) - execute('%argdelete') + command('%argdelete') assert_fails('argument', 'E163:') end) it('test for 0argadd and 0argedit', function() reset_arglist() - execute('arga a b c d') - execute('2argu') - execute('0arga added') + command('arga a b c d') + command('2argu') + command('0arga added') eq({'added', 'a', 'b', 'c', 'd'}, eval('argv()')) - execute('%argd') - execute('arga a b c d') - execute('2argu') - execute('0arge edited') + command('%argd') + command('arga a b c d') + command('2argu') + command('0arge edited') eq({'edited', 'a', 'b', 'c', 'd'}, eval('argv()')) - execute('2argu') - execute('arga third') + command('2argu') + command('arga third') eq({'edited', 'a', 'third', 'b', 'c', 'd'}, eval('argv()')) end) it('test for argc()', function() reset_arglist() eq(0, eval('argc()')) - execute('argadd a b') + command('argadd a b') eq(2, eval('argc()')) end) it('test for arglistid()', function() reset_arglist() - execute('arga a b') + command('arga a b') eq(0, eval('arglistid()')) - execute('split') - execute('arglocal') + command('split') + command('arglocal') eq(1, eval('arglistid()')) - execute('tabnew | tabfirst') + command('tabnew | tabfirst') eq(0, eval('arglistid(2)')) eq(1, eval('arglistid(1, 1)')) eq(0, eval('arglistid(2, 1)')) eq(1, eval('arglistid(1, 2)')) - execute('tabonly | only | enew!') - execute('argglobal') + command('tabonly | only | enew!') + command('argglobal') eq(0, eval('arglistid()')) end) @@ -207,64 +209,95 @@ describe('argument list commands', function() reset_arglist() eq({}, eval('argv()')) eq('', eval('argv(2)')) - execute('argadd a b c d') + command('argadd a b c d') eq('c', eval('argv(2)')) end) it('test for :argedit command', function() reset_arglist() - execute('argedit a') + command('argedit a') eq({'a'}, eval('argv()')) eq('a', eval('expand("%:t")')) - execute('argedit b') + command('argedit b') eq({'a', 'b'}, eval('argv()')) eq('b', eval('expand("%:t")')) - execute('argedit a') + command('argedit a') eq({'a', 'b'}, eval('argv()')) eq('a', eval('expand("%:t")')) - assert_fails('argedit a b', 'E172:') - execute('argedit c') + command('argedit c') eq({'a', 'c', 'b'}, eval('argv()')) - execute('0argedit x') + command('0argedit x') eq({'x', 'a', 'c', 'b'}, eval('argv()')) - execute('enew! | set modified') + command('enew! | set modified') assert_fails('argedit y', 'E37:') - execute('argedit! y') + command('argedit! y') eq({'x', 'y', 'a', 'c', 'b'}, eval('argv()')) - execute('%argd') + command('%argd') + -- Nvim allows unescaped spaces in filename on all platforms. #6010 + command('argedit a b') + eq({'a b'}, eval('argv()')) end) it('test for :argdelete command', function() reset_arglist() - execute('args aa a aaa b bb') - execute('argdelete a*') + command('args aa a aaa b bb') + command('argdelete a*') eq({'b', 'bb'}, eval('argv()')) eq('aa', eval('expand("%:t")')) - execute('last') - execute('argdelete %') + command('last') + command('argdelete %') eq({'b'}, eval('argv()')) assert_fails('argdelete', 'E471:') assert_fails('1,100argdelete', 'E16:') - execute('%argd') + command('%argd') end) it('test for the :next, :prev, :first, :last, :rewind commands', function() reset_arglist() - execute('args a b c d') - execute('last') + command('args a b c d') + command('last') eq(3, eval('argidx()')) assert_fails('next', 'E165:') - execute('prev') + command('prev') eq(2, eval('argidx()')) - execute('Next') + command('Next') eq(1, eval('argidx()')) - execute('first') + command('first') eq(0, eval('argidx()')) assert_fails('prev', 'E164:') - execute('3next') + command('3next') eq(3, eval('argidx()')) - execute('rewind') + command('rewind') eq(0, eval('argidx()')) - execute('%argd') + command('%argd') + end) + + + it('test for autocommand that redefines the argument list, when doing ":all"', function() + command('autocmd BufReadPost Xxx2 next Xxx2 Xxx1') + command("call writefile(['test file Xxx1'], 'Xxx1')") + command("call writefile(['test file Xxx2'], 'Xxx2')") + command("call writefile(['test file Xxx3'], 'Xxx3')") + + command('new') + -- redefine arglist; go to Xxx1 + command('next! Xxx1 Xxx2 Xxx3') + -- open window for all args + command('all') + eq('test file Xxx1', eval('getline(1)')) + command('wincmd w') + command('wincmd w') + eq('test file Xxx1', eval('getline(1)')) + -- should now be in Xxx2 + command('rewind') + eq('test file Xxx2', eval('getline(1)')) + + command('autocmd! BufReadPost Xxx2') + command('enew! | only') + command("call delete('Xxx1')") + command("call delete('Xxx2')") + command("call delete('Xxx3')") + command('argdelete Xxx*') + command('bwipe! Xxx1 Xxx2 Xxx3') end) end) diff --git a/test/functional/legacy/assert_spec.lua b/test/functional/legacy/assert_spec.lua index 8a042be7f7..d646e8dbf4 100644 --- a/test/functional/legacy/assert_spec.lua +++ b/test/functional/legacy/assert_spec.lua @@ -1,7 +1,7 @@ local helpers = require('test.functional.helpers')(after_each) local nvim, call = helpers.meths, helpers.call local clear, eq = helpers.clear, helpers.eq -local source, execute = helpers.source, helpers.execute +local source, command = helpers.source, helpers.command local exc_exec = helpers.exc_exec local function expected_errors(errors) @@ -55,7 +55,7 @@ describe('assert function:', function() it('should change v:errors when expected is not equal to actual', function() -- Lua does not tell integer from float. - execute('call assert_equal(1, 1.0)') + command('call assert_equal(1, 1.0)') expected_errors({'Expected 1 but got 1.0'}) end) @@ -219,8 +219,8 @@ describe('assert function:', function() -- assert_fails({cmd}, [, {error}]) describe('assert_fails', function() it('should change v:errors when error does not match v:errmsg', function() - execute([[call assert_fails('xxx', {})]]) - execute([[call assert_match("Expected {} but got 'E731:", v:errors[0])]]) + command([[call assert_fails('xxx', {})]]) + command([[call assert_match("Expected {} but got 'E731:", v:errors[0])]]) expected_errors({"Expected {} but got 'E731: using Dictionary as a String'"}) end) @@ -235,6 +235,41 @@ describe('assert function:', function() end) end) + -- assert_inrange({lower}, {upper}, {actual}[, {msg}]) + describe('assert_inrange()', function() + it('should not change v:errors when actual is in range', function() + call('assert_inrange', 7, 7, 7) + call('assert_inrange', 5, 7, 5) + call('assert_inrange', 5, 7, 6) + call('assert_inrange', 5, 7, 7) + expected_empty() + end) + + it('should change v:errors when actual is not in range', function() + call('assert_inrange', 5, 7, 4) + call('assert_inrange', 5, 7, 8) + expected_errors({ + "Expected range 5 - 7, but got 4", + "Expected range 5 - 7, but got 8", + }) + end) + + it('assert_inrange(1, 1) returns E119', function() + eq('Vim(call):E119: Not enough arguments for function: assert_inrange', + exc_exec("call assert_inrange(1, 1)")) + end) + end) + + -- assert_report({msg}) + describe('assert_report()', function() + it('should add a message to v:errors', function() + command("call assert_report('something is wrong')") + command("call assert_match('something is wrong', v:errors[0])") + command('call remove(v:errors, 0)') + expected_empty() + end) + end) + -- assert_exception({cmd}, [, {error}]) describe('assert_exception()', function() it('should assert thrown exceptions properly', function() diff --git a/test/functional/legacy/autochdir_spec.lua b/test/functional/legacy/autochdir_spec.lua index 06f7c1dd11..466e3ed830 100644 --- a/test/functional/legacy/autochdir_spec.lua +++ b/test/functional/legacy/autochdir_spec.lua @@ -1,7 +1,7 @@ local lfs = require('lfs') local helpers = require('test.functional.helpers')(after_each) local clear, eq = helpers.clear, helpers.eq -local eval, execute = helpers.eval, helpers.execute +local eval, command = helpers.eval, helpers.command describe('autochdir behavior', function() local dir = 'Xtest-functional-legacy-autochdir' @@ -17,9 +17,9 @@ describe('autochdir behavior', function() -- Tests vim/vim/777 without test_autochdir(). it('sets filename', function() - execute('set acd') - execute('new') - execute('w '..dir..'/Xtest') + command('set acd') + command('new') + command('w '..dir..'/Xtest') eq('Xtest', eval("expand('%')")) eq(dir, eval([[substitute(getcwd(), '.*[/\\]\(\k*\)', '\1', '')]])) end) diff --git a/test/functional/legacy/autocmd_option_spec.lua b/test/functional/legacy/autocmd_option_spec.lua index 28037e17c5..0c7e43bf31 100644 --- a/test/functional/legacy/autocmd_option_spec.lua +++ b/test/functional/legacy/autocmd_option_spec.lua @@ -4,7 +4,7 @@ local clear, eq, neq = helpers.clear, helpers.eq, helpers.neq local curbuf, buf = helpers.curbuf, helpers.bufmeths local curwin = helpers.curwin local redir_exec = helpers.redir_exec -local source, execute = helpers.source, helpers.execute +local source, command = helpers.source, helpers.command local function declare_hook_function() source([[ @@ -23,9 +23,9 @@ local function declare_hook_function() endfu ]]) end - + local function set_hook(pattern) - execute( + command( 'au OptionSet ' .. pattern .. ' :call AutoCommand(expand("<amatch>"), bufnr("%"), winnr())' @@ -33,7 +33,7 @@ local function set_hook(pattern) end local function init_var() - execute('let g:ret = []') + command('let g:ret = []') end local function get_result() @@ -88,9 +88,9 @@ end local function make_buffer() local old_buf = curbuf() - execute('botright new') + command('botright new') local new_buf = curbuf() - execute('wincmd p') -- move previous window + command('wincmd p') -- move previous window neq(old_buf, new_buf) eq(old_buf, curbuf()) @@ -100,10 +100,10 @@ end local function get_new_window_number() local old_win = curwin() - execute('botright new') + command('botright new') local new_win = curwin() local new_winnr = redir_exec('echo winnr()') - execute('wincmd p') -- move previous window + command('wincmd p') -- move previous window neq(old_win, new_win) eq(old_win, curwin()) @@ -122,42 +122,42 @@ describe('au OptionSet', function() end) it('should be called in setting number option', function() - execute('set nu') + command('set nu') expected_combination({'number', 0, 1, 'global'}) - execute('setlocal nonu') + command('setlocal nonu') expected_combination({'number', 1, 0, 'local'}) - execute('setglobal nonu') + command('setglobal nonu') expected_combination({'number', 1, 0, 'global'}) end) it('should be called in setting autoindent option',function() - execute('setlocal ai') + command('setlocal ai') expected_combination({'autoindent', 0, 1, 'local'}) - execute('setglobal ai') + command('setglobal ai') expected_combination({'autoindent', 0, 1, 'global'}) - execute('set noai') + command('set noai') expected_combination({'autoindent', 1, 0, 'global'}) end) it('should be called in inverting global autoindent option',function() - execute('set ai!') + command('set ai!') expected_combination({'autoindent', 0, 1, 'global'}) end) it('should be called in being unset local autoindent option',function() - execute('setlocal ai') + command('setlocal ai') expected_combination({'autoindent', 0, 1, 'local'}) - execute('setlocal ai<') + command('setlocal ai<') expected_combination({'autoindent', 1, 0, 'local'}) end) it('should be called in setting global list and number option at the same time',function() - execute('set list nu') + command('set list nu') expected_combination( {'list', 0, 1, 'global'}, {'number', 0, 1, 'global'} @@ -165,41 +165,41 @@ describe('au OptionSet', function() end) it('should not print anything, use :noa', function() - execute('noa set nolist nonu') + command('noa set nolist nonu') expected_empty() end) it('should be called in setting local acd', function() - execute('setlocal acd') + command('setlocal acd') expected_combination({'autochdir', 0, 1, 'local'}) end) it('should be called in setting autoread', function() - execute('set noar') + command('set noar') expected_combination({'autoread', 1, 0, 'global'}) - execute('setlocal ar') + command('setlocal ar') expected_combination({'autoread', 0, 1, 'local'}) end) it('should be called in inverting global autoread', function() - execute('setglobal invar') + command('setglobal invar') expected_combination({'autoread', 1, 0, 'global'}) end) it('should be called in setting backspace option through :let', function() - execute('let &bs=""') + command('let &bs=""') expected_combination({'backspace', 'indent,eol,start', '', 'global'}) end) describe('being set by setbufvar()', function() it('should not trigger because option name is invalid', function() - execute('call setbufvar(1, "&l:bk", 1)') + command('silent! call setbufvar(1, "&l:bk", 1)') expected_empty() end) it('should trigger using correct option name', function() - execute('call setbufvar(1, "&backup", 1)') + command('call setbufvar(1, "&backup", 1)') expected_combination({'backup', 0, 1, 'local'}) end) @@ -207,7 +207,7 @@ describe('au OptionSet', function() local new_buffer = make_buffer() local new_bufnr = buf.get_number(new_buffer) - execute('call setbufvar(' .. new_bufnr .. ', "&buftype", "nofile")') + command('call setbufvar(' .. new_bufnr .. ', "&buftype", "nofile")') expected_combination({'buftype', '', 'nofile', 'local', {bufnr = new_bufnr}}) end) end) @@ -224,16 +224,16 @@ describe('au OptionSet', function() it('should be called iff setting readonly', function() set_hook('readonly') - execute('set nu') + command('set nu') expected_empty() - execute('setlocal ro') + command('setlocal ro') expected_combination({'readonly', 0, 1, 'local'}) - execute('setglobal ro') + command('setglobal ro') expected_combination({'readonly', 0, 1, 'global'}) - execute('set noro') + command('set noro') expected_combination({'readonly', 1, 0, 'global'}) end) @@ -241,14 +241,14 @@ describe('au OptionSet', function() it('should not trigger because option name does not match with backup', function() set_hook('backup') - execute('call setbufvar(1, "&l:bk", 1)') + command('silent! call setbufvar(1, "&l:bk", 1)') expected_empty() end) it('should trigger, use correct option name backup', function() set_hook('backup') - execute('call setbufvar(1, "&backup", 1)') + command('call setbufvar(1, "&backup", 1)') expected_combination({'backup', 0, 1, 'local'}) end) @@ -258,7 +258,7 @@ describe('au OptionSet', function() local new_buffer = make_buffer() local new_bufnr = buf.get_number(new_buffer) - execute('call setbufvar(' .. new_bufnr .. ', "&buftype", "nofile")') + command('call setbufvar(' .. new_bufnr .. ', "&buftype", "nofile")') expected_combination({'buftype', '', 'nofile', 'local', {bufnr = new_bufnr}}) end) end) @@ -267,14 +267,14 @@ describe('au OptionSet', function() it('should not trigger because option name does not match with backup', function() set_hook('backup') - execute('call setwinvar(1, "&l:bk", 1)') + command('silent! call setwinvar(1, "&l:bk", 1)') expected_empty() end) it('should trigger, use correct option name backup', function() set_hook('backup') - execute('call setwinvar(1, "&backup", 1)') + command('call setwinvar(1, "&backup", 1)') expected_combination({'backup', 0, 1, 'local'}) end) @@ -283,7 +283,7 @@ describe('au OptionSet', function() local new_winnr = get_new_window_number() - execute('call setwinvar(' .. new_winnr .. ', "&cursorcolumn", 1)') + command('call setwinvar(' .. new_winnr .. ', "&cursorcolumn", 1)') -- expected_combination({'cursorcolumn', 0, 1, 'local', {winnr = new_winnr}}) expected_empty() end) diff --git a/test/functional/legacy/autoformat_join_spec.lua b/test/functional/legacy/autoformat_join_spec.lua index 4110d66f5b..84d661c190 100644 --- a/test/functional/legacy/autoformat_join_spec.lua +++ b/test/functional/legacy/autoformat_join_spec.lua @@ -1,9 +1,9 @@ --- vim: set foldmethod=marker foldmarker=[[,]] : -- Tests for setting the '[,'] marks when joining lines. local helpers = require('test.functional.helpers')(after_each) local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local execute, expect = helpers.execute, helpers.expect +local command, expect = helpers.command, helpers.expect +local wait = helpers.wait describe('autoformat join', function() setup(clear) @@ -21,12 +21,13 @@ Results:]]) feed('gg') feed('0gqj<cr>') + wait() - execute([[let a=string(getpos("'[")).'/'.string(getpos("']"))]]) - execute("g/^This line/;'}-join") - execute([[let b=string(getpos("'[")).'/'.string(getpos("']"))]]) - execute("$put ='First test: Start/End '.string(a)") - execute("$put ='Second test: Start/End '.string(b)") + command([[let a=string(getpos("'[")).'/'.string(getpos("']"))]]) + command("g/^This line/;'}-join") + command([[let b=string(getpos("'[")).'/'.string(getpos("']"))]]) + command("$put ='First test: Start/End '.string(a)") + command("$put ='Second test: Start/End '.string(b)") expect([[ O sodales, ludite, vos qui attamen consulite per voster honur. diff --git a/test/functional/legacy/breakindent_spec.lua b/test/functional/legacy/breakindent_spec.lua index 2504fe8e51..7594dba16c 100644 --- a/test/functional/legacy/breakindent_spec.lua +++ b/test/functional/legacy/breakindent_spec.lua @@ -2,7 +2,7 @@ local helpers = require('test.functional.helpers')(after_each) local feed, insert = helpers.feed, helpers.insert -local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect +local clear, feed_command, expect = helpers.clear, helpers.feed_command, helpers.expect describe('breakindent', function() setup(clear) @@ -10,186 +10,186 @@ describe('breakindent', function() it('is working', function() insert('dummy text') - execute('set wildchar=^E') - execute('10new') - execute('vsp') - execute('vert resize 20') - execute([[put =\"\tabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP\"]]) - execute('set ts=4 sw=4 sts=4 breakindent') - execute('fu! ScreenChar(line, width)') - execute(' let c=""') - execute(' for i in range(1,a:width)') - execute(' let c.=nr2char(screenchar(a:line, i))') - execute(' endfor') - execute([[ let c.="\n"]]) - execute(' for i in range(1,a:width)') - execute(' let c.=nr2char(screenchar(a:line+1, i))') - execute(' endfor') - execute([[ let c.="\n"]]) - execute(' for i in range(1,a:width)') - execute(' let c.=nr2char(screenchar(a:line+2, i))') - execute(' endfor') - execute(' return c') - execute('endfu') - execute('fu DoRecordScreen()') - execute(' wincmd l') - execute([[ $put =printf(\"\n%s\", g:test)]]) - execute(' $put =g:line1') - execute(' wincmd p') - execute('endfu') - execute('set briopt=min:0') - execute('let g:test="Test 1: Simple breakindent"') - execute('let line1=ScreenChar(line("."),8)') - execute('call DoRecordScreen()') - execute('let g:test="Test 2: Simple breakindent + sbr=>>"') - execute('set sbr=>>') - execute('let line1=ScreenChar(line("."),8)') - execute('call DoRecordScreen()') - execute('let g:test ="Test 3: Simple breakindent + briopt:sbr"') - execute('set briopt=sbr,min:0 sbr=++') - execute('let line1=ScreenChar(line("."),8)') - execute('call DoRecordScreen()') - execute('let g:test ="Test 4: Simple breakindent + min width: 18"') - execute('set sbr= briopt=min:18') - execute('let line1=ScreenChar(line("."),8)') - execute('call DoRecordScreen()') - execute('let g:test =" Test 5: Simple breakindent + shift by 2"') - execute('set briopt=shift:2,min:0') - execute('let line1=ScreenChar(line("."),8)') - execute('call DoRecordScreen()') - execute('let g:test=" Test 6: Simple breakindent + shift by -1"') - execute('set briopt=shift:-1,min:0') - execute('let line1=ScreenChar(line("."),8)') - execute('call DoRecordScreen()') - execute('let g:test=" Test 7: breakindent + shift by +1 + nu + sbr=? briopt:sbr"') - execute('set briopt=shift:1,sbr,min:0 nu sbr=? nuw=4') - execute('let line1=ScreenChar(line("."),10)') - execute('call DoRecordScreen()') - execute('let g:test=" Test 8: breakindent + shift:1 + nu + sbr=# list briopt:sbr"') - execute('set briopt=shift:1,sbr,min:0 nu sbr=# list lcs&vi') - execute('let line1=ScreenChar(line("."),10)') - execute('call DoRecordScreen()') - execute([[let g:test=" Test 9: breakindent + shift by +1 + 'nu' + sbr=# list"]]) - execute('set briopt-=sbr') - execute('let line1=ScreenChar(line("."),10)') - execute('call DoRecordScreen()') - execute([[let g:test=" Test 10: breakindent + shift by +1 + 'nu' + sbr=~ cpo+=n"]]) - execute('set cpo+=n sbr=~ nu nuw=4 nolist briopt=sbr,min:0') - execute('let line1=ScreenChar(line("."),10)') - execute('call DoRecordScreen()') - execute('wincmd p') - execute([[let g:test="\n Test 11: strdisplaywidth when breakindent is on"]]) - execute('set cpo-=n sbr=>> nu nuw=4 nolist briopt= ts=4') + feed_command('set wildchar=^E') + feed_command('10new') + feed_command('vsp') + feed_command('vert resize 20') + feed_command([[put =\"\tabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP\"]]) + feed_command('set ts=4 sw=4 sts=4 breakindent') + feed_command('fu! ScreenChar(line, width)') + feed_command(' let c=""') + feed_command(' for i in range(1,a:width)') + feed_command(' let c.=nr2char(screenchar(a:line, i))') + feed_command(' endfor') + feed_command([[ let c.="\n"]]) + feed_command(' for i in range(1,a:width)') + feed_command(' let c.=nr2char(screenchar(a:line+1, i))') + feed_command(' endfor') + feed_command([[ let c.="\n"]]) + feed_command(' for i in range(1,a:width)') + feed_command(' let c.=nr2char(screenchar(a:line+2, i))') + feed_command(' endfor') + feed_command(' return c') + feed_command('endfu') + feed_command('fu DoRecordScreen()') + feed_command(' wincmd l') + feed_command([[ $put =printf(\"\n%s\", g:test)]]) + feed_command(' $put =g:line1') + feed_command(' wincmd p') + feed_command('endfu') + feed_command('set briopt=min:0') + feed_command('let g:test="Test 1: Simple breakindent"') + feed_command('let line1=ScreenChar(line("."),8)') + feed_command('call DoRecordScreen()') + feed_command('let g:test="Test 2: Simple breakindent + sbr=>>"') + feed_command('set sbr=>>') + feed_command('let line1=ScreenChar(line("."),8)') + feed_command('call DoRecordScreen()') + feed_command('let g:test ="Test 3: Simple breakindent + briopt:sbr"') + feed_command('set briopt=sbr,min:0 sbr=++') + feed_command('let line1=ScreenChar(line("."),8)') + feed_command('call DoRecordScreen()') + feed_command('let g:test ="Test 4: Simple breakindent + min width: 18"') + feed_command('set sbr= briopt=min:18') + feed_command('let line1=ScreenChar(line("."),8)') + feed_command('call DoRecordScreen()') + feed_command('let g:test =" Test 5: Simple breakindent + shift by 2"') + feed_command('set briopt=shift:2,min:0') + feed_command('let line1=ScreenChar(line("."),8)') + feed_command('call DoRecordScreen()') + feed_command('let g:test=" Test 6: Simple breakindent + shift by -1"') + feed_command('set briopt=shift:-1,min:0') + feed_command('let line1=ScreenChar(line("."),8)') + feed_command('call DoRecordScreen()') + feed_command('let g:test=" Test 7: breakindent + shift by +1 + nu + sbr=? briopt:sbr"') + feed_command('set briopt=shift:1,sbr,min:0 nu sbr=? nuw=4') + feed_command('let line1=ScreenChar(line("."),10)') + feed_command('call DoRecordScreen()') + feed_command('let g:test=" Test 8: breakindent + shift:1 + nu + sbr=# list briopt:sbr"') + feed_command('set briopt=shift:1,sbr,min:0 nu sbr=# list lcs&vi') + feed_command('let line1=ScreenChar(line("."),10)') + feed_command('call DoRecordScreen()') + feed_command([[let g:test=" Test 9: breakindent + shift by +1 + 'nu' + sbr=# list"]]) + feed_command('set briopt-=sbr') + feed_command('let line1=ScreenChar(line("."),10)') + feed_command('call DoRecordScreen()') + feed_command([[let g:test=" Test 10: breakindent + shift by +1 + 'nu' + sbr=~ cpo+=n"]]) + feed_command('set cpo+=n sbr=~ nu nuw=4 nolist briopt=sbr,min:0') + feed_command('let line1=ScreenChar(line("."),10)') + feed_command('call DoRecordScreen()') + feed_command('wincmd p') + feed_command([[let g:test="\n Test 11: strdisplaywidth when breakindent is on"]]) + feed_command('set cpo-=n sbr=>> nu nuw=4 nolist briopt= ts=4') -- Skip leading tab when calculating text width. - execute('let text=getline(2)') + feed_command('let text=getline(2)') -- Text wraps 3 times. - execute('let width = strlen(text[1:])+indent(2)*4+strlen(&sbr)*3') - execute('$put =g:test') - execute([[$put =printf(\"strdisplaywidth: %d == calculated: %d\", strdisplaywidth(text), width)]]) - execute([[let g:str="\t\t\t\t\t{"]]) - execute('let g:test=" Test 12: breakindent + long indent"') - execute('wincmd p') - execute('set all& breakindent linebreak briopt=min:10 nu numberwidth=3 ts=4') - execute('$put =g:str') + feed_command('let width = strlen(text[1:])+indent(2)*4+strlen(&sbr)*3') + feed_command('$put =g:test') + feed_command([[$put =printf(\"strdisplaywidth: %d == calculated: %d\", strdisplaywidth(text), width)]]) + feed_command([[let g:str="\t\t\t\t\t{"]]) + feed_command('let g:test=" Test 12: breakindent + long indent"') + feed_command('wincmd p') + feed_command('set all& breakindent linebreak briopt=min:10 nu numberwidth=3 ts=4') + feed_command('$put =g:str') feed('zt') - execute('let line1=ScreenChar(1,10)') - execute('wincmd p') - execute('call DoRecordScreen()') + feed_command('let line1=ScreenChar(1,10)') + feed_command('wincmd p') + feed_command('call DoRecordScreen()') -- Test, that the string " a\tb\tc\td\te" is correctly displayed in a -- 20 column wide window (see bug report -- https://groups.google.com/d/msg/vim_dev/ZOdg2mc9c9Y/TT8EhFjEy0IJ ). - execute('only') - execute('vert 20new') - execute('set all& breakindent briopt=min:10') - execute([[call setline(1, [" a\tb\tc\td\te", " z y x w v"])]]) - execute([[/^\s*a]]) + feed_command('only') + feed_command('vert 20new') + feed_command('set all& breakindent briopt=min:10') + feed_command([[call setline(1, [" a\tb\tc\td\te", " z y x w v"])]]) + feed_command([[/^\s*a]]) feed('fbgjyl') - execute('let line1 = @0') - execute([[?^\s*z]]) + feed_command('let line1 = @0') + feed_command([[?^\s*z]]) feed('fygjyl') - execute('let line2 = @0') - execute('quit!') - execute([[$put ='Test 13: breakindent with wrapping Tab']]) - execute('$put =line1') - execute('$put =line2') - - execute('let g:test="Test 14: breakindent + visual blockwise delete #1"') - execute('set all& breakindent shada+=nX-test-breakindent.shada') - execute('30vnew') - execute('normal! 3a1234567890') - execute('normal! a abcde') - execute([[exec "normal! 0\<C-V>tex"]]) - execute('let line1=ScreenChar(line("."),8)') - execute('call DoRecordScreen()') - - execute('let g:test="Test 15: breakindent + visual blockwise delete #2"') - execute('%d') - execute('normal! 4a1234567890') - execute([[exec "normal! >>\<C-V>3f0x"]]) - execute('let line1=ScreenChar(line("."),20)') - execute('call DoRecordScreen()') - execute('quit!') + feed_command('let line2 = @0') + feed_command('quit!') + feed_command([[$put ='Test 13: breakindent with wrapping Tab']]) + feed_command('$put =line1') + feed_command('$put =line2') + + feed_command('let g:test="Test 14: breakindent + visual blockwise delete #1"') + feed_command('set all& breakindent shada+=nX-test-breakindent.shada') + feed_command('30vnew') + feed_command('normal! 3a1234567890') + feed_command('normal! a abcde') + feed_command([[exec "normal! 0\<C-V>tex"]]) + feed_command('let line1=ScreenChar(line("."),8)') + feed_command('call DoRecordScreen()') + + feed_command('let g:test="Test 15: breakindent + visual blockwise delete #2"') + feed_command('%d') + feed_command('normal! 4a1234567890') + feed_command([[exec "normal! >>\<C-V>3f0x"]]) + feed_command('let line1=ScreenChar(line("."),20)') + feed_command('call DoRecordScreen()') + feed_command('quit!') -- Assert buffer contents. expect([[ - + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP - + Test 1: Simple breakindent abcd qrst GHIJ - + Test 2: Simple breakindent + sbr=>> abcd >>qr >>EF - + Test 3: Simple breakindent + briopt:sbr abcd ++ qrst ++ GHIJ - + Test 4: Simple breakindent + min width: 18 abcd qrstuv IJKLMN - + Test 5: Simple breakindent + shift by 2 abcd qr EF - + Test 6: Simple breakindent + shift by -1 abcd qrstu HIJKL - + Test 7: breakindent + shift by +1 + nu + sbr=? briopt:sbr 2 ab ? m ? x - + Test 8: breakindent + shift:1 + nu + sbr=# list briopt:sbr 2 ^Iabcd # opq # BCD - + Test 9: breakindent + shift by +1 + 'nu' + sbr=# list 2 ^Iabcd #op #AB - + Test 10: breakindent + shift by +1 + 'nu' + sbr=~ cpo+=n 2 ab ~ mn ~ yz - + Test 11: strdisplaywidth when breakindent is on strdisplaywidth: 46 == calculated: 64 { - + Test 12: breakindent + long indent 56 @@ -197,12 +197,12 @@ describe('breakindent', function() Test 13: breakindent with wrapping Tab d w - + Test 14: breakindent + visual blockwise delete #1 e ~ ~ - + Test 15: breakindent + visual blockwise delete #2 1234567890 ~ diff --git a/test/functional/legacy/changelist_spec.lua b/test/functional/legacy/changelist_spec.lua index c718da3736..72c9872163 100644 --- a/test/functional/legacy/changelist_spec.lua +++ b/test/functional/legacy/changelist_spec.lua @@ -3,7 +3,7 @@ local helpers = require('test.functional.helpers')(after_each) local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local execute, expect = helpers.execute, helpers.expect +local feed_command, expect = helpers.feed_command, helpers.expect describe('changelist', function() setup(clear) @@ -12,14 +12,14 @@ describe('changelist', function() insert("1\n2") feed('Gkylp') - execute('set ul=100') + feed_command('set ul=100') feed('Gylp') - execute('set ul=100') + feed_command('set ul=100') feed('gg') - execute('vsplit') - execute('try', 'normal g;', 'normal ggVGcpass', 'catch', 'normal ggVGcfail', 'endtry') + feed_command('vsplit') + feed_command('try', 'normal g;', 'normal ggVGcpass', 'catch', 'normal ggVGcfail', 'endtry') expect('pass') end) diff --git a/test/functional/legacy/charsearch_spec.lua b/test/functional/legacy/charsearch_spec.lua index ef3369728d..c1a59c9ee1 100644 --- a/test/functional/legacy/charsearch_spec.lua +++ b/test/functional/legacy/charsearch_spec.lua @@ -2,7 +2,7 @@ local helpers = require('test.functional.helpers')(after_each) local feed, insert = helpers.feed, helpers.insert -local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect +local clear, feed_command, expect = helpers.clear, helpers.feed_command, helpers.expect describe('charsearch', function() setup(clear) @@ -14,23 +14,23 @@ describe('charsearch', function() Zabcdefghijkemnokqretkvwxyz]]) -- Check that "fe" and ";" work. - execute('/^X') + feed_command('/^X') feed('ylfep;;p,,p') -- Check that save/restore works. - execute('/^Y') + feed_command('/^Y') feed('ylfep') - execute('let csave = getcharsearch()') + feed_command('let csave = getcharsearch()') feed('fip') - execute('call setcharsearch(csave)') + feed_command('call setcharsearch(csave)') feed(';p;p') -- Check that setcharsearch() changes the settings. - execute('/^Z') + feed_command('/^Z') feed('ylfep') - execute("call setcharsearch({'char': 'k'})") + feed_command("call setcharsearch({'char': 'k'})") feed(';p') - execute("call setcharsearch({'forward': 0})") + feed_command("call setcharsearch({'forward': 0})") feed('$;p') - execute("call setcharsearch({'until': 1})") + feed_command("call setcharsearch({'until': 1})") feed(';;p') -- Assert buffer contents. diff --git a/test/functional/legacy/close_count_spec.lua b/test/functional/legacy/close_count_spec.lua index ad1812f22e..9b932e2ef0 100644 --- a/test/functional/legacy/close_count_spec.lua +++ b/test/functional/legacy/close_count_spec.lua @@ -1,133 +1,134 @@ -- Tests for :[count]close! and :[count]hide local helpers = require('test.functional.helpers')(after_each) -local feed, eval, eq, clear, execute = - helpers.feed, helpers.eval, helpers.eq, helpers.clear, helpers.execute + +local eq = helpers.eq +local wait = helpers.wait +local eval = helpers.eval +local feed = helpers.feed +local clear = helpers.clear +local command = helpers.command describe('close_count', function() setup(clear) it('is working', function() - execute('let tests = []') - execute('for i in range(5)') - execute('new') - execute('endfor') - execute('4wincmd w') - execute('close!') - execute('let buffers = []') - execute('windo call add(buffers, bufnr("%"))') + command('let tests = []') + command('for i in range(5)|new|endfor') + command('4wincmd w') + command('close!') + command('let buffers = []') + command('windo call add(buffers, bufnr("%"))') eq({6, 5, 4, 2, 1}, eval('buffers')) - execute('1close!') - execute('let buffers = []') - execute('windo call add(buffers, bufnr("%"))') + command('1close!') + command('let buffers = []') + command('windo call add(buffers, bufnr("%"))') eq({5, 4, 2, 1}, eval('buffers')) - execute('$close!') - execute('let buffers = []') - execute('windo call add(buffers, bufnr("%"))') + command('$close!') + command('let buffers = []') + command('windo call add(buffers, bufnr("%"))') eq({5, 4, 2}, eval('buffers')) - execute('1wincmd w') - execute('2close!') - execute('let buffers = []') - execute('windo call add(buffers, bufnr("%"))') + command('1wincmd w') + command('2close!') + command('let buffers = []') + command('windo call add(buffers, bufnr("%"))') eq({5, 2}, eval('buffers')) - execute('1wincmd w') - execute('new') - execute('new') - execute('2wincmd w') - execute('-1close!') - execute('let buffers = []') - execute('windo call add(buffers, bufnr("%"))') + command('1wincmd w') + command('new') + command('new') + command('2wincmd w') + command('-1close!') + command('let buffers = []') + command('windo call add(buffers, bufnr("%"))') eq({7, 5, 2}, eval('buffers')) - execute('2wincmd w') - execute('+1close!') - execute('let buffers = []') - execute('windo call add(buffers, bufnr("%"))') + command('2wincmd w') + command('+1close!') + command('let buffers = []') + command('windo call add(buffers, bufnr("%"))') eq({7, 5}, eval('buffers')) - execute('only!') - execute('b1') - execute('let tests = []') - execute('for i in range(5)') - execute('new') - execute('endfor') - execute('let buffers = []') - execute('windo call add(buffers, bufnr("%"))') + command('only!') + command('b1') + command('let tests = []') + command('for i in range(5)|new|endfor') + command('let buffers = []') + command('windo call add(buffers, bufnr("%"))') eq({13, 12, 11, 10, 9, 1}, eval('buffers')) - execute('4wincmd w') - execute('.hide') - execute('let buffers = []') - execute('windo call add(buffers, bufnr("%"))') + command('4wincmd w') + command('.hide') + command('let buffers = []') + command('windo call add(buffers, bufnr("%"))') eq({13, 12, 11, 9, 1}, eval('buffers')) - execute('1hide') - execute('let buffers = []') - execute('windo call add(buffers, bufnr("%"))') + command('1hide') + command('let buffers = []') + command('windo call add(buffers, bufnr("%"))') eq({12, 11, 9, 1}, eval('buffers')) - execute('$hide') - execute('let buffers = []') - execute('windo call add(buffers, bufnr("%"))') + command('$hide') + command('let buffers = []') + command('windo call add(buffers, bufnr("%"))') eq({12, 11, 9}, eval('buffers')) - execute('1wincmd w') - execute('2hide') - execute('let buffers = []') - execute('windo call add(buffers, bufnr("%"))') + command('1wincmd w') + command('2hide') + command('let buffers = []') + command('windo call add(buffers, bufnr("%"))') eq({12, 9}, eval('buffers')) - execute('1wincmd w') - execute('new') - execute('new') - execute('3wincmd w') - execute('-hide') - execute('let buffers = []') - execute('windo call add(buffers, bufnr("%"))') + command('1wincmd w') + command('new') + command('new') + command('3wincmd w') + command('-hide') + command('let buffers = []') + command('windo call add(buffers, bufnr("%"))') eq({15, 12, 9}, eval('buffers')) - execute('2wincmd w') - execute('+hide') - execute('let buffers = []') - execute('windo call add(buffers, bufnr("%"))') + command('2wincmd w') + command('+hide') + command('let buffers = []') + command('windo call add(buffers, bufnr("%"))') eq({15, 12}, eval('buffers')) - execute('only!') - execute('b1') - execute('let tests = []') - execute('set hidden') - execute('for i in range(5)') - execute('new') - execute('endfor') - execute('1wincmd w') - execute('$ hide') - execute('let buffers = []') - execute('windo call add(buffers, bufnr("%"))') + command('only!') + command('b1') + command('let tests = []') + command('set hidden') + command('for i in range(5)|new|endfor') + command('1wincmd w') + command('$ hide') + command('let buffers = []') + command('windo call add(buffers, bufnr("%"))') eq({20, 19, 18, 17, 16}, eval('buffers')) - execute('$-1 close!') - execute('let buffers = []') - execute('windo call add(buffers, bufnr("%"))') + command('$-1 close!') + command('let buffers = []') + command('windo call add(buffers, bufnr("%"))') eq({20, 19, 18, 16}, eval('buffers')) - execute('1wincmd w') - execute('.+close!') - execute('let buffers = []') - execute('windo call add(buffers, bufnr("%"))') + command('1wincmd w') + command('.+close!') + command('let buffers = []') + command('windo call add(buffers, bufnr("%"))') eq({20, 18, 16}, eval('buffers')) - execute('only!') - execute('b1') - execute('let tests = []') - execute('set hidden') - execute('for i in range(5)') - execute('new') - execute('endfor') - execute('4wincmd w') + command('only!') + command('b1') + command('let tests = []') + command('set hidden') + command('for i in range(5)|new|endfor') + command('4wincmd w') feed('<C-W>c<cr>') - execute('let buffers = []') - execute('windo call add(buffers, bufnr("%"))') + wait() + command('let buffers = []') + command('windo call add(buffers, bufnr("%"))') eq({25, 24, 23, 21, 1}, eval('buffers')) feed('1<C-W>c<cr>') - execute('let buffers = []') - execute('windo call add(buffers, bufnr("%"))') + wait() + command('let buffers = []') + command('windo call add(buffers, bufnr("%"))') eq({24, 23, 21, 1}, eval('buffers')) feed('9<C-W>c<cr>') - execute('let buffers = []') - execute('windo call add(buffers, bufnr("%"))') + wait() + command('let buffers = []') + command('windo call add(buffers, bufnr("%"))') eq({24, 23, 21}, eval('buffers')) - execute('1wincmd w') + command('1wincmd w') feed('2<C-W>c<cr>') - execute('let buffers = []') - execute('windo call add(buffers, bufnr("%"))') + wait() + command('let buffers = []') + command('windo call add(buffers, bufnr("%"))') eq({24, 21}, eval('buffers')) end) end) diff --git a/test/functional/legacy/command_count_spec.lua b/test/functional/legacy/command_count_spec.lua index c463ada968..ad5368430a 100644 --- a/test/functional/legacy/command_count_spec.lua +++ b/test/functional/legacy/command_count_spec.lua @@ -2,7 +2,7 @@ local helpers = require('test.functional.helpers')(after_each) local clear, source, expect = helpers.clear, helpers.source, helpers.expect -local execute = helpers.execute +local feed_command = helpers.feed_command describe('command_count', function() it('is working', function() @@ -87,35 +87,35 @@ describe('command_count', function() arga a b c d ]]) -- This can not be in the source() call as it will produce errors. - execute([[let v:errmsg = '']]) - execute('5argu') - execute([[call add(g:lines, '5argu ' . v:errmsg)]]) - execute('$argu') - execute([[call add(g:lines, '4argu ' . expand('%:t'))]]) - execute([[let v:errmsg = '']]) - execute('1argu') - execute([[call add(g:lines, '1argu ' . expand('%:t'))]]) - execute([[let v:errmsg = '']]) - execute('100b') - execute([[call add(g:lines, '100b ' . v:errmsg)]]) - execute('split') - execute('split') - execute('split') - execute('split') - execute([[let v:errmsg = '']]) - execute('0close') - execute([[call add(g:lines, '0close ' . v:errmsg)]]) - execute('$wincmd w') - execute('$close') - execute([[call add(g:lines, '$close ' . winnr())]]) - execute([[let v:errmsg = '']]) - execute('$+close') - execute([[call add(g:lines, '$+close ' . v:errmsg)]]) - execute('$tabe') - execute([[call add(g:lines, '$tabe ' . tabpagenr())]]) - execute([[let v:errmsg = '']]) - execute('$+tabe') - execute([[call add(g:lines, '$+tabe ' . v:errmsg)]]) + feed_command([[let v:errmsg = '']]) + feed_command('5argu') + feed_command([[call add(g:lines, '5argu ' . v:errmsg)]]) + feed_command('$argu') + feed_command([[call add(g:lines, '4argu ' . expand('%:t'))]]) + feed_command([[let v:errmsg = '']]) + feed_command('1argu') + feed_command([[call add(g:lines, '1argu ' . expand('%:t'))]]) + feed_command([[let v:errmsg = '']]) + feed_command('100b') + feed_command([[call add(g:lines, '100b ' . v:errmsg)]]) + feed_command('split') + feed_command('split') + feed_command('split') + feed_command('split') + feed_command([[let v:errmsg = '']]) + feed_command('0close') + feed_command([[call add(g:lines, '0close ' . v:errmsg)]]) + feed_command('$wincmd w') + feed_command('$close') + feed_command([[call add(g:lines, '$close ' . winnr())]]) + feed_command([[let v:errmsg = '']]) + feed_command('$+close') + feed_command([[call add(g:lines, '$+close ' . v:errmsg)]]) + feed_command('$tabe') + feed_command([[call add(g:lines, '$tabe ' . tabpagenr())]]) + feed_command([[let v:errmsg = '']]) + feed_command('$+tabe') + feed_command([[call add(g:lines, '$+tabe ' . v:errmsg)]]) source([[ only! e x diff --git a/test/functional/legacy/comparators_spec.lua b/test/functional/legacy/comparators_spec.lua index 27879b0f65..32e830a0af 100644 --- a/test/functional/legacy/comparators_spec.lua +++ b/test/functional/legacy/comparators_spec.lua @@ -2,13 +2,13 @@ local helpers = require('test.functional.helpers')(after_each) local clear, eq = helpers.clear, helpers.eq -local eval, execute = helpers.eval, helpers.execute +local eval, command = helpers.eval, helpers.command describe('comparators', function() before_each(clear) it('is working', function() - execute('set isident+=#') + command('set isident+=#') eq(1, eval('1 is#1')) end) end) diff --git a/test/functional/legacy/delete_spec.lua b/test/functional/legacy/delete_spec.lua index cd19e31a79..aeaab335e8 100644 --- a/test/functional/legacy/delete_spec.lua +++ b/test/functional/legacy/delete_spec.lua @@ -1,6 +1,6 @@ local helpers = require('test.functional.helpers')(after_each) local clear, source = helpers.clear, helpers.source -local eq, eval, execute = helpers.eq, helpers.eval, helpers.execute +local eq, eval, command = helpers.eq, helpers.eval, helpers.command if helpers.pending_win32(pending) then return end @@ -8,30 +8,30 @@ describe('Test for delete()', function() before_each(clear) it('file delete', function() - execute('split Xfile') - execute("call setline(1, ['a', 'b'])") - execute('wq') + command('split Xfile') + command("call setline(1, ['a', 'b'])") + command('wq') eq(eval("['a', 'b']"), eval("readfile('Xfile')")) eq(0, eval("delete('Xfile')")) eq(-1, eval("delete('Xfile')")) end) it('directory delete', function() - execute("call mkdir('Xdir1')") + command("call mkdir('Xdir1')") eq(1, eval("isdirectory('Xdir1')")) eq(0, eval("delete('Xdir1', 'd')")) eq(0, eval("isdirectory('Xdir1')")) eq(-1, eval("delete('Xdir1', 'd')")) end) it('recursive delete', function() - execute("call mkdir('Xdir1')") - execute("call mkdir('Xdir1/subdir')") - execute("call mkdir('Xdir1/empty')") - execute('split Xdir1/Xfile') - execute("call setline(1, ['a', 'b'])") - execute('w') - execute('w Xdir1/subdir/Xfile') - execute('close') + command("call mkdir('Xdir1')") + command("call mkdir('Xdir1/subdir')") + command("call mkdir('Xdir1/empty')") + command('split Xdir1/Xfile') + command("call setline(1, ['a', 'b'])") + command('w') + command('w Xdir1/subdir/Xfile') + command('close') eq(1, eval("isdirectory('Xdir1')")) eq(eval("['a', 'b']"), eval("readfile('Xdir1/Xfile')")) @@ -57,8 +57,8 @@ describe('Test for delete()', function() end) it('symlink directory delete', function() - execute("call mkdir('Xdir1')") - execute("silent !ln -s Xdir1 Xlink") + command("call mkdir('Xdir1')") + command("silent !ln -s Xdir1 Xlink") eq(1, eval("isdirectory('Xdir1')")) eq(1, eval("isdirectory('Xlink')")) -- Delete the link, not the directory diff --git a/test/functional/legacy/eval_spec.lua b/test/functional/legacy/eval_spec.lua index 3684fe714d..c5d38d6d05 100644 --- a/test/functional/legacy/eval_spec.lua +++ b/test/functional/legacy/eval_spec.lua @@ -2,8 +2,11 @@ local helpers = require('test.functional.helpers')(after_each) local feed, insert, source = helpers.feed, helpers.insert, helpers.source -local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect +local clear, command, expect = helpers.clear, helpers.command, helpers.expect local eq, eval, write_file = helpers.eq, helpers.eval, helpers.write_file +local wait = helpers.wait +local exc_exec = helpers.exc_exec +local dedent = helpers.dedent describe('eval', function() setup(function() @@ -37,17 +40,17 @@ describe('eval', function() end) it(':let', function() - execute('so test_eval_setup.vim') - execute([[let @" = 'abc']]) - execute('AR "') - execute([[let @" = "abc\n"]]) + command('so test_eval_setup.vim') + command([[let @" = 'abc']]) + command('AR "') + command([[let @" = "abc\n"]]) source('AR "') - execute([[let @" = "abc\<C-m>"]]) - execute('AR "') - execute([[let @= = '"abc"']]) - execute('AR =') + command([[let @" = "abc\<C-m>"]]) + command('AR "') + command([[let @= = '"abc"']]) + command('AR =') expect([[ - + ": type v; value: abc (['abc']), expr: abc (['abc']) ": type V; value: abc]].."\000 (['abc']), expr: abc\000"..[[ (['abc']) ": type V; value: abc]].."\r\000 (['abc\r']), expr: abc\r\000 (['abc\r"..[[']) @@ -55,32 +58,33 @@ describe('eval', function() end) it('basic setreg() tests', function() - execute('so test_eval_setup.vim') + command('so test_eval_setup.vim') insert('{{{1 Basic setreg tests') - execute([[call SetReg('a', 'abcA', 'c')]]) - execute([[call SetReg('b', 'abcB', 'v')]]) - execute([[call SetReg('c', 'abcC', 'l')]]) - execute([[call SetReg('d', 'abcD', 'V')]]) - execute([[call SetReg('e', 'abcE', 'b')]]) - execute([[call SetReg('f', 'abcF', "\<C-v>")]]) - execute([[call SetReg('g', 'abcG', 'b10')]]) - execute([[call SetReg('h', 'abcH', "\<C-v>10")]]) - execute([[call SetReg('I', 'abcI')]]) + command([[call SetReg('a', 'abcA', 'c')]]) + command([[call SetReg('b', 'abcB', 'v')]]) + command([[call SetReg('c', 'abcC', 'l')]]) + command([[call SetReg('d', 'abcD', 'V')]]) + command([[call SetReg('e', 'abcE', 'b')]]) + command([[call SetReg('f', 'abcF', "\<C-v>")]]) + command([[call SetReg('g', 'abcG', 'b10')]]) + command([[call SetReg('h', 'abcH', "\<C-v>10")]]) + command([[call SetReg('I', 'abcI')]]) feed('Go{{{1 Appending single lines with setreg()<esc>') - execute([[call SetReg('A', 'abcAc', 'c')]]) - execute([[call SetReg('A', 'abcAl', 'l')]]) - execute([[call SetReg('A', 'abcAc2','c')]]) - execute([[call SetReg('b', 'abcBc', 'ca')]]) - execute([[call SetReg('b', 'abcBb', 'ba')]]) - execute([[call SetReg('b', 'abcBc2','ca')]]) - execute([[call SetReg('b', 'abcBb2','b50a')]]) - execute([[call SetReg('C', 'abcCl', 'l')]]) - execute([[call SetReg('C', 'abcCc', 'c')]]) - execute([[call SetReg('D', 'abcDb', 'b')]]) - execute([[call SetReg('E', 'abcEb', 'b')]]) - execute([[call SetReg('E', 'abcEl', 'l')]]) - execute([[call SetReg('F', 'abcFc', 'c')]]) + wait() + command([[call SetReg('A', 'abcAc', 'c')]]) + command([[call SetReg('A', 'abcAl', 'l')]]) + command([[call SetReg('A', 'abcAc2','c')]]) + command([[call SetReg('b', 'abcBc', 'ca')]]) + command([[call SetReg('b', 'abcBb', 'ba')]]) + command([[call SetReg('b', 'abcBc2','ca')]]) + command([[call SetReg('b', 'abcBb2','b50a')]]) + command([[call SetReg('C', 'abcCl', 'l')]]) + command([[call SetReg('C', 'abcCc', 'c')]]) + command([[call SetReg('D', 'abcDb', 'b')]]) + command([[call SetReg('E', 'abcEb', 'b')]]) + command([[call SetReg('E', 'abcEl', 'l')]]) + command([[call SetReg('F', 'abcFc', 'c')]]) expect([[ {{{1 Basic setreg tests {{{2 setreg('a', 'abcA', 'c') @@ -191,14 +195,14 @@ describe('eval', function() end) it('appending NL with setreg()', function() - execute('so test_eval_setup.vim') - - execute([[call setreg('a', 'abcA2', 'c')]]) - execute([[call setreg('b', 'abcB2', 'v')]]) - execute([[call setreg('c', 'abcC2', 'l')]]) - execute([[call setreg('d', 'abcD2', 'V')]]) - execute([[call setreg('e', 'abcE2', 'b')]]) - execute([[call setreg('f', 'abcF2', "\<C-v>")]]) + command('so test_eval_setup.vim') + + command([[call setreg('a', 'abcA2', 'c')]]) + command([[call setreg('b', 'abcB2', 'v')]]) + command([[call setreg('c', 'abcC2', 'l')]]) + command([[call setreg('d', 'abcD2', 'V')]]) + command([[call setreg('e', 'abcE2', 'b')]]) + command([[call setreg('f', 'abcF2', "\<C-v>")]]) -- These registers where set like this in the old test_eval.in but never -- copied to the output buffer with SetReg(). They do not appear in -- test_eval.ok. Therefore they are commented out. @@ -206,14 +210,14 @@ describe('eval', function() --execute([[call setreg('h', 'abcH2', "\<C-v>10")]]) --execute([[call setreg('I', 'abcI2')]]) - execute([[call SetReg('A', "\n")]]) - execute([[call SetReg('B', "\n", 'c')]]) - execute([[call SetReg('C', "\n")]]) - execute([[call SetReg('D', "\n", 'l')]]) - execute([[call SetReg('E', "\n")]]) - execute([[call SetReg('F', "\n", 'b')]]) + command([[call SetReg('A', "\n")]]) + command([[call SetReg('B', "\n", 'c')]]) + command([[call SetReg('C', "\n")]]) + command([[call SetReg('D', "\n", 'l')]]) + command([[call SetReg('E', "\n")]]) + command([[call SetReg('F', "\n", 'b')]]) expect([[ - + {{{2 setreg('A', ']]..'\000'..[[') A: type V; value: abcA2]].."\000 (['abcA2']), expr: abcA2\000"..[[ (['abcA2']) == @@ -228,19 +232,19 @@ describe('eval', function() C: type V; value: abcC2]].."\000\000 (['abcC2', '']), expr: abcC2\000\000"..[[ (['abcC2', '']) == abcC2 - + == {{{2 setreg('D', ']]..'\000'..[[', 'l') D: type V; value: abcD2]].."\000\000 (['abcD2', '']), expr: abcD2\000\000"..[[ (['abcD2', '']) == abcD2 - + == {{{2 setreg('E', ']]..'\000'..[[') E: type V; value: abcE2]].."\000\000 (['abcE2', '']), expr: abcE2\000\000"..[[ (['abcE2', '']) == abcE2 - + == {{{2 setreg('F', ']]..'\000'..[[', 'b') F: type ]].."\0220; value: abcF2\000 (['abcF2', '']), expr: abcF2\000"..[[ (['abcF2', '']) @@ -250,27 +254,27 @@ describe('eval', function() end) it('setting and appending list with setreg()', function() - execute('so test_eval_setup.vim') - - execute([[$put ='{{{1 Setting lists with setreg()']]) - execute([=[call SetReg('a', ['abcA3'], 'c')]=]) - execute([=[call SetReg('b', ['abcB3'], 'l')]=]) - execute([=[call SetReg('c', ['abcC3'], 'b')]=]) - execute([=[call SetReg('d', ['abcD3'])]=]) - execute([=[call SetReg('e', [1, 2, 'abc', 3])]=]) - execute([=[call SetReg('f', [1, 2, 3])]=]) - - execute([[$put ='{{{1 Appending lists with setreg()']]) - execute([=[call SetReg('A', ['abcA3c'], 'c')]=]) - execute([=[call SetReg('b', ['abcB3l'], 'la')]=]) - execute([=[call SetReg('C', ['abcC3b'], 'lb')]=]) - execute([=[call SetReg('D', ['abcD32'])]=]) - execute([=[call SetReg('A', ['abcA32'])]=]) - execute([=[call SetReg('B', ['abcB3c'], 'c')]=]) - execute([=[call SetReg('C', ['abcC3l'], 'l')]=]) - execute([=[call SetReg('D', ['abcD3b'], 'b')]=]) + command('so test_eval_setup.vim') + + command([[$put ='{{{1 Setting lists with setreg()']]) + command([=[call SetReg('a', ['abcA3'], 'c')]=]) + command([=[call SetReg('b', ['abcB3'], 'l')]=]) + command([=[call SetReg('c', ['abcC3'], 'b')]=]) + command([=[call SetReg('d', ['abcD3'])]=]) + command([=[call SetReg('e', [1, 2, 'abc', 3])]=]) + command([=[call SetReg('f', [1, 2, 3])]=]) + + command([[$put ='{{{1 Appending lists with setreg()']]) + command([=[call SetReg('A', ['abcA3c'], 'c')]=]) + command([=[call SetReg('b', ['abcB3l'], 'la')]=]) + command([=[call SetReg('C', ['abcC3b'], 'lb')]=]) + command([=[call SetReg('D', ['abcD32'])]=]) + command([=[call SetReg('A', ['abcA32'])]=]) + command([=[call SetReg('B', ['abcB3c'], 'c')]=]) + command([=[call SetReg('C', ['abcC3l'], 'l')]=]) + command([=[call SetReg('D', ['abcD3b'], 'b')]=]) expect([[ - + {{{1 Setting lists with setreg() {{{2 setreg('a', ['abcA3'], 'c') a: type v; value: abcA3 (['abcA3']), expr: abcA3 (['abcA3']) @@ -359,9 +363,9 @@ describe('eval', function() -- the next expect() easier to write. This is neccessary because null -- bytes on a line by itself don't play well together with the dedent -- function used in expect(). - execute('%delete') - execute([[$put ='{{{1 Appending lists with NL with setreg()']]) - execute([=[call SetReg('A', ["\n", 'abcA3l2'], 'l')]=]) + command('%delete') + command([[$put ='{{{1 Appending lists with NL with setreg()']]) + command([=[call SetReg('A', ["\n", 'abcA3l2'], 'l')]=]) expect( '\n'.. '{{{1 Appending lists with NL with setreg()\n'.. @@ -374,8 +378,8 @@ describe('eval', function() '\000\n'.. 'abcA3l2\n'.. '==') - execute('%delete') - execute([=[call SetReg('B', ["\n", 'abcB3c2'], 'c')]=]) + command('%delete') + command([=[call SetReg('B', ["\n", 'abcB3c2'], 'c')]=]) expect( '\n'.. "{{{2 setreg('B', ['\000', 'abcB3c2'], 'c')\n".. @@ -386,8 +390,8 @@ describe('eval', function() 'abcB3c\n'.. '\000\n'.. 'abcB3c2=') - execute('%delete') - execute([=[call SetReg('C', ["\n", 'abcC3b2'], 'b')]=]) + command('%delete') + command([=[call SetReg('C', ["\n", 'abcC3b2'], 'b')]=]) expect( '\n'.. "{{{2 setreg('C', ['\000', 'abcC3b2'], 'b')\n".. @@ -398,8 +402,8 @@ describe('eval', function() ' abcC3l\n'.. ' \000\n'.. ' abcC3b2') - execute('%delete') - execute([=[call SetReg('D', ["\n", 'abcD3b50'],'b50')]=]) + command('%delete') + command([=[call SetReg('D', ["\n", 'abcD3b50'],'b50')]=]) expect( '\n'.. "{{{2 setreg('D', ['\000', 'abcD3b50'], 'b50')\n".. @@ -416,8 +420,8 @@ describe('eval', function() -- to make the expect() calls easier to write. Otherwise the null byte can -- make trouble on a line on its own. it('setting lists with NLs with setreg(), part 1', function() - execute('so test_eval_setup.vim') - execute([=[call SetReg('a', ['abcA4-0', "\n", "abcA4-2\n", "\nabcA4-3", "abcA4-4\nabcA4-4-2"])]=]) + command('so test_eval_setup.vim') + command([=[call SetReg('a', ['abcA4-0', "\n", "abcA4-2\n", "\nabcA4-3", "abcA4-4\nabcA4-4-2"])]=]) expect( '\n'.. "{{{2 setreg('a', ['abcA4-0', '\000', 'abcA4-2\000', '\000abcA4-3', 'abcA4-4\000abcA4-4-2'])\n".. @@ -432,8 +436,8 @@ describe('eval', function() end) it('setting lists with NLs with setreg(), part 2', function() - execute('so test_eval_setup.vim') - execute([=[call SetReg('b', ['abcB4c-0', "\n", "abcB4c-2\n", "\nabcB4c-3", "abcB4c-4\nabcB4c-4-2"], 'c')]=]) + command('so test_eval_setup.vim') + command([=[call SetReg('b', ['abcB4c-0', "\n", "abcB4c-2\n", "\nabcB4c-3", "abcB4c-4\nabcB4c-4-2"], 'c')]=]) expect( '\n'.. "{{{2 setreg('b', ['abcB4c-0', '\000', 'abcB4c-2\000', '\000abcB4c-3', 'abcB4c-4\000abcB4c-4-2'], 'c')\n".. @@ -447,8 +451,8 @@ describe('eval', function() end) it('setting lists with NLs with setreg(), part 3', function() - execute('so test_eval_setup.vim') - execute([=[call SetReg('c', ['abcC4l-0', "\n", "abcC4l-2\n", "\nabcC4l-3", "abcC4l-4\nabcC4l-4-2"], 'l')]=]) + command('so test_eval_setup.vim') + command([=[call SetReg('c', ['abcC4l-0', "\n", "abcC4l-2\n", "\nabcC4l-3", "abcC4l-4\nabcC4l-4-2"], 'l')]=]) expect( '\n'.. "{{{2 setreg('c', ['abcC4l-0', '\000', 'abcC4l-2\000', '\000abcC4l-3', 'abcC4l-4\000abcC4l-4-2'], 'l')\n".. @@ -462,8 +466,8 @@ describe('eval', function() '==') end) it('setting lists with NLs with setreg(), part 4', function() - execute('so test_eval_setup.vim') - execute([=[call SetReg('d', ['abcD4b-0', "\n", "abcD4b-2\n", "\nabcD4b-3", "abcD4b-4\nabcD4b-4-2"], 'b')]=]) + command('so test_eval_setup.vim') + command([=[call SetReg('d', ['abcD4b-0', "\n", "abcD4b-2\n", "\nabcD4b-3", "abcD4b-4\nabcD4b-4-2"], 'b')]=]) expect( '\n'.. "{{{2 setreg('d', ['abcD4b-0', '\000', 'abcD4b-2\000', '\000abcD4b-3', 'abcD4b-4\000abcD4b-4-2'], 'b')\n".. @@ -476,8 +480,8 @@ describe('eval', function() ' abcD4b-4\000abcD4b-4-2') end) it('setting lists with NLs with setreg(), part 5', function() - execute('so test_eval_setup.vim') - execute([=[call SetReg('e', ['abcE4b10-0', "\n", "abcE4b10-2\n", "\nabcE4b10-3", "abcE4b10-4\nabcE4b10-4-2"], 'b10')]=]) + command('so test_eval_setup.vim') + command([=[call SetReg('e', ['abcE4b10-0', "\n", "abcE4b10-2\n", "\nabcE4b10-3", "abcE4b10-4\nabcE4b10-4-2"], 'b10')]=]) expect( '\n'.. "{{{2 setreg('e', ['abcE4b10-0', '\000', 'abcE4b10-2\000', '\000abcE4b10-3', 'abcE4b10-4\000abcE4b10-4-2'], 'b10')\n".. @@ -494,32 +498,41 @@ describe('eval', function() -- Precondition: "a is actually unset and "0 is nonempty eq('', eval("getregtype('a')")) eq('', eval("getreg('a')")) - execute("call setreg('0','text')") + command("call setreg('0','text')") -- This used to return a NULL list -- which setreg didn't handle - execute("let x = getreg('a',1,1)") - execute("call setreg('0',x)") + command("let x = getreg('a',1,1)") + command("call setreg('0',x)") -- nvim didn't crash and "0 was emptied eq(2, eval("1+1")) eq({}, eval("getreg('0',1,1)")) -- x is a mutable list - execute("let y = x") + command("let y = x") eq({}, eval("y")) - execute("call add(x, 'item')") + command("call add(x, 'item')") eq({'item'}, eval("y")) end) + it('sets the unnamed register when the "u" option is passed to setreg', function() + command("call setreg('a','a reg', 'cu')") + eq("a reg", eval('@"')) + command("call setreg('b','b reg', 'cu')") + eq("b reg", eval('@"')) + command("call setreg('c','c reg', 'c')") + eq("b reg", eval('@"')) + end) + it('search and expressions', function() - execute('so test_eval_setup.vim') - execute([=[call SetReg('/', ['abc/'])]=]) - execute([=[call SetReg('/', ["abc/\n"])]=]) - execute([=[call SetReg('=', ['"abc/"'])]=]) - execute([=[call SetReg('=', ["\"abc/\n\""])]=]) + command('so test_eval_setup.vim') + command([=[call SetReg('/', ['abc/'])]=]) + command([=[call SetReg('/', ["abc/\n"])]=]) + command([=[call SetReg('=', ['"abc/"'])]=]) + command([=[call SetReg('=', ["\"abc/\n\""])]=]) expect([[ - + {{{2 setreg('/', ['abc/']) /: type v; value: abc/ (['abc/']), expr: abc/ (['abc/']) == @@ -536,35 +549,35 @@ describe('eval', function() describe('system clipboard', function() before_each(function() - execute('let &runtimepath = "test/functional/fixtures,".&runtimepath') - execute('call getreg("*")') -- force load of provider + command('let &runtimepath = "test/functional/fixtures,".&runtimepath') + command('call getreg("*")') -- force load of provider end) it('works', function() insert([[ Some first line (this text was at the top of the old test_eval.in). - + Note: system clipboard is saved, changed and restored. - + clipboard contents something else]]) - execute('so test_eval_setup.vim') + command('so test_eval_setup.vim') -- Save and restore system clipboard. - execute("let _clipreg = ['*', getreg('*'), getregtype('*')]") - execute('let _clipopt = &cb') - execute("let &cb='unnamed'") - execute('5y') - execute('AR *') - execute('tabdo :windo :echo "hi"') - execute('6y') - execute('AR *') - execute('let &cb=_clipopt') - execute("call call('setreg', _clipreg)") + command("let _clipreg = ['*', getreg('*'), getregtype('*')]") + command('let _clipopt = &cb') + command("let &cb='unnamed'") + command('5y') + command('AR *') + command('tabdo :windo :echo "hi"') + command('6y') + command('AR *') + command('let &cb=_clipopt') + command("call call('setreg', _clipreg)") expect([[ Some first line (this text was at the top of the old test_eval.in). - + Note: system clipboard is saved, changed and restored. - + clipboard contents something else *: type V; value: clipboard contents]]..'\00'..[[ (['clipboard contents']), expr: clipboard contents]]..'\00'..[[ (['clipboard contents']) @@ -582,17 +595,17 @@ describe('eval', function() $put =v:exception endtry endfun]]) - execute([[call ErrExe('call setreg()')]]) - execute([[call ErrExe('call setreg(1)')]]) - execute([[call ErrExe('call setreg(1, 2, 3, 4)')]]) - execute([=[call ErrExe('call setreg([], 2)')]=]) - execute([[call ErrExe('call setreg(1, {})')]]) - execute([=[call ErrExe('call setreg(1, 2, [])')]=]) - execute([=[call ErrExe('call setreg("/", ["1", "2"])')]=]) - execute([=[call ErrExe('call setreg("=", ["1", "2"])')]=]) - execute([=[call ErrExe('call setreg(1, ["", "", [], ""])')]=]) + command([[call ErrExe('call setreg()')]]) + command([[call ErrExe('call setreg(1)')]]) + command([[call ErrExe('call setreg(1, 2, 3, 4)')]]) + command([=[call ErrExe('call setreg([], 2)')]=]) + command([[call ErrExe('call setreg(1, {})')]]) + command([=[call ErrExe('call setreg(1, 2, [])')]=]) + command([=[call ErrExe('call setreg("/", ["1", "2"])')]=]) + command([=[call ErrExe('call setreg("=", ["1", "2"])')]=]) + command([=[call ErrExe('call setreg(1, ["", "", [], ""])')]=]) expect([[ - + Executing call setreg() Vim(call):E119: Not enough arguments for function: setreg Executing call setreg(1) @@ -614,48 +627,38 @@ describe('eval', function() end) it('function name not starting with a capital', function() - execute('try') - execute(' func! g:test()') - execute(' echo "test"') - execute(' endfunc') - execute('catch') - execute(' let tmp = v:exception') - execute('endtry') - eq('Vim(function):E128: Function name must start with a capital or "s:": g:test()', eval('tmp')) + eq('Vim(function):E128: Function name must start with a capital or "s:": g:test()\\nendfunction', + exc_exec(dedent([[ + function! g:test() + endfunction]]))) end) it('Function name followed by #', function() - execute('try') - execute(' func! test2() "#') - execute(' echo "test2"') - execute(' endfunc') - execute('catch') - execute(' let tmp = v:exception') - execute('endtry') - eq('Vim(function):E128: Function name must start with a capital or "s:": test2() "#', eval('tmp')) + eq('Vim(function):E128: Function name must start with a capital or "s:": test2() "#\\nendfunction', + exc_exec(dedent([[ + function! test2() "# + endfunction]]))) end) it('function name includes a colon', function() - execute('try') - execute(' func! b:test()') - execute(' echo "test"') - execute(' endfunc') - execute('catch') - execute(' let tmp = v:exception') - execute('endtry') - eq('Vim(function):E128: Function name must start with a capital or "s:": b:test()', eval('tmp')) + eq('Vim(function):E128: Function name must start with a capital or "s:": b:test()\\nendfunction', + exc_exec(dedent([[ + function! b:test() + endfunction]]))) end) it('function name starting with/without "g:", buffer-local funcref', function() - execute('function! g:Foo(n)') - execute(" $put ='called Foo(' . a:n . ')'") - execute('endfunction') - execute("let b:my_func = function('Foo')") - execute('call b:my_func(1)') - execute('echo g:Foo(2)') - execute('echo Foo(3)') + command([[ + function! g:Foo(n) + $put ='called Foo(' . a:n . ')' + endfunction + ]]) + command("let b:my_func = function('Foo')") + command('call b:my_func(1)') + command('echo g:Foo(2)') + command('echo Foo(3)') expect([[ - + called Foo(1) called Foo(2) called Foo(3)]]) @@ -664,20 +667,20 @@ describe('eval', function() it('script-local function used in Funcref must exist', function() source([[ " Vim script used in test_eval.in. Needed for script-local function. - + func! s:Testje() return "foo" endfunc - + let Bar = function('s:Testje') - + $put ='s:Testje exists: ' . exists('s:Testje') $put ='func s:Testje exists: ' . exists('*s:Testje') $put ='Bar exists: ' . exists('Bar') $put ='func Bar exists: ' . exists('*Bar') ]]) expect([[ - + s:Testje exists: 0 func s:Testje exists: 1 Bar exists: 1 @@ -685,12 +688,8 @@ describe('eval', function() end) it("using $ instead of '$' must give an error", function() - execute('try') - execute(" call append($, 'foobar')") - execute('catch') - execute(' let tmp = v:exception') - execute('endtry') - eq('Vim(call):E116: Invalid arguments for function append', eval('tmp')) + eq('Vim(call):E116: Invalid arguments for function append', + exc_exec('call append($, "foobar")')) end) it('getcurpos/setpos', function() @@ -699,13 +698,16 @@ describe('eval', function() 012345678 start:]]) - execute('/^012345678') + command('/^012345678') feed('6l') - execute('let sp = getcurpos()') + wait() + command('let sp = getcurpos()') feed('0') - execute("call setpos('.', sp)") + wait() + command("call setpos('.', sp)") feed('jyl') - execute('$put') + wait() + command('$put') expect([[ 012345678 012345678 @@ -715,18 +717,18 @@ describe('eval', function() end) it('substring and variable name', function() - execute("let str = 'abcdef'") - execute('let n = 3') + command("let str = 'abcdef'") + command('let n = 3') eq('def', eval('str[n:]')) eq('abcd', eval('str[:n]')) eq('d', eval('str[n:n]')) - execute('unlet n') - execute('let nn = 3') + command('unlet n') + command('let nn = 3') eq('def', eval('str[nn:]')) eq('abcd', eval('str[:nn]')) eq('d', eval('str[nn:nn]')) - execute('unlet nn') - execute('let b:nn = 4') + command('unlet nn') + command('let b:nn = 4') eq('ef', eval('str[b:nn:]')) eq('abcde', eval('str[:b:nn]')) eq('e', eval('str[b:nn:b:nn]')) diff --git a/test/functional/legacy/fixeol_spec.lua b/test/functional/legacy/fixeol_spec.lua index 1e9e832536..801451b300 100644 --- a/test/functional/legacy/fixeol_spec.lua +++ b/test/functional/legacy/fixeol_spec.lua @@ -2,7 +2,7 @@ local helpers = require('test.functional.helpers')(after_each) local feed = helpers.feed -local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect +local clear, feed_command, expect = helpers.clear, helpers.feed_command, helpers.expect if helpers.pending_win32(pending) then return end @@ -25,38 +25,38 @@ describe('fixeol', function() it('is working', function() -- First write two test files โ with and without trailing EOL. -- Use Unix fileformat for consistency. - execute('set ff=unix') - execute('enew!') + feed_command('set ff=unix') + feed_command('enew!') feed('awith eol<esc>:w! XXEol<cr>') - execute('enew!') - execute('set noeol nofixeol') + feed_command('enew!') + feed_command('set noeol nofixeol') feed('awithout eol<esc>:w! XXNoEol<cr>') - execute('set eol fixeol') - execute('bwipe XXEol XXNoEol') + feed_command('set eol fixeol') + feed_command('bwipe XXEol XXNoEol') -- Try editing files with 'fixeol' disabled. - execute('e! XXEol') + feed_command('e! XXEol') feed('ostays eol<esc>:set nofixeol<cr>') - execute('w! XXTestEol') - execute('e! XXNoEol') + feed_command('w! XXTestEol') + feed_command('e! XXNoEol') feed('ostays without<esc>:set nofixeol<cr>') - execute('w! XXTestNoEol') - execute('bwipe XXEol XXNoEol XXTestEol XXTestNoEol') - execute('set fixeol') + feed_command('w! XXTestNoEol') + feed_command('bwipe XXEol XXNoEol XXTestEol XXTestNoEol') + feed_command('set fixeol') -- Append "END" to each file so that we can see what the last written char was. feed('ggdGaEND<esc>:w >>XXEol<cr>') - execute('w >>XXNoEol') - execute('w >>XXTestEol') - execute('w >>XXTestNoEol') + feed_command('w >>XXNoEol') + feed_command('w >>XXTestEol') + feed_command('w >>XXTestNoEol') -- Concatenate the results. - execute('e! test.out') + feed_command('e! test.out') feed('a0<esc>:$r XXEol<cr>') - execute('$r XXNoEol') + feed_command('$r XXNoEol') feed('Go1<esc>:$r XXTestEol<cr>') - execute('$r XXTestNoEol') - execute('w') + feed_command('$r XXTestNoEol') + feed_command('w') -- Assert buffer contents. expect([=[ diff --git a/test/functional/legacy/function_sort_spec.lua b/test/functional/legacy/function_sort_spec.lua index 1b65f1ce95..12875460e0 100644 --- a/test/functional/legacy/function_sort_spec.lua +++ b/test/functional/legacy/function_sort_spec.lua @@ -1,10 +1,11 @@ local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear + local eq = helpers.eq +local neq = helpers.neq local eval = helpers.eval -local execute = helpers.execute +local clear = helpers.clear +local source = helpers.source local exc_exec = helpers.exc_exec -local neq = helpers.neq describe('sort', function() before_each(clear) @@ -31,14 +32,17 @@ describe('sort', function() end) it('ability to call sort() from a compare function', function() - execute('func Compare1(a, b) abort') - execute([[call sort(range(3), 'Compare2')]]) - execute('return a:a - a:b') - execute('endfunc') - - execute('func Compare2(a, b) abort') - execute('return a:a - a:b') - execute('endfunc') + source([[ + function Compare1(a, b) abort + call sort(range(3), 'Compare2') + return a:a - a:b + endfunc + + function Compare2(a, b) abort + return a:a - a:b + endfunc + ]]) + eq({1, 3, 5}, eval("sort([3, 1, 5], 'Compare1')")) end) diff --git a/test/functional/legacy/getcwd_spec.lua b/test/functional/legacy/getcwd_spec.lua index dcb56eb242..8fb31ccd22 100644 --- a/test/functional/legacy/getcwd_spec.lua +++ b/test/functional/legacy/getcwd_spec.lua @@ -2,7 +2,7 @@ local helpers = require('test.functional.helpers')(after_each) local eq, eval, source = helpers.eq, helpers.eval, helpers.source -local call, clear, execute = helpers.call, helpers.clear, helpers.execute +local call, clear, command = helpers.call, helpers.clear, helpers.command if helpers.pending_win32(pending) then return end @@ -39,48 +39,48 @@ describe('getcwd', function() return bufname . ' ' . dirname . ' ' . lflag endfunction ]]) - execute('new') - execute('let cwd=getcwd()') + command('new') + command('let cwd=getcwd()') call('mkdir', 'Xtopdir') - execute('silent cd Xtopdir') + command('silent cd Xtopdir') call('mkdir', 'Xdir1') call('mkdir', 'Xdir2') call('mkdir', 'Xdir3') - execute('new a') - execute('new b') - execute('new c') - execute('3wincmd w') - execute('silent lcd Xdir1') + command('new a') + command('new b') + command('new c') + command('3wincmd w') + command('silent lcd Xdir1') eq('a Xdir1 1', eval('GetCwdInfo(0, 0)')) - execute('wincmd W') + command('wincmd W') eq('b Xtopdir 0', eval('GetCwdInfo(0, 0)')) - execute('wincmd W') - execute('silent lcd Xdir3') + command('wincmd W') + command('silent lcd Xdir3') eq('c Xdir3 1', eval('GetCwdInfo(0, 0)')) eq('a Xdir1 1', eval('GetCwdInfo(bufwinnr("a"), 0)')) eq('b Xtopdir 0', eval('GetCwdInfo(bufwinnr("b"), 0)')) eq('c Xdir3 1', eval('GetCwdInfo(bufwinnr("c"), 0)')) - execute('wincmd W') + command('wincmd W') eq('a Xdir1 1', eval('GetCwdInfo(bufwinnr("a"), tabpagenr())')) eq('b Xtopdir 0', eval('GetCwdInfo(bufwinnr("b"), tabpagenr())')) eq('c Xdir3 1', eval('GetCwdInfo(bufwinnr("c"), tabpagenr())')) - execute('tabnew x') - execute('new y') - execute('new z') - execute('3wincmd w') + command('tabnew x') + command('new y') + command('new z') + command('3wincmd w') eq('x Xtopdir 0', eval('GetCwdInfo(0, 0)')) - execute('wincmd W') - execute('silent lcd Xdir2') + command('wincmd W') + command('silent lcd Xdir2') eq('y Xdir2 1', eval('GetCwdInfo(0, 0)')) - execute('wincmd W') - execute('silent lcd Xdir3') + command('wincmd W') + command('silent lcd Xdir3') eq('z Xdir3 1', eval('GetCwdInfo(0, 0)')) eq('x Xtopdir 0', eval('GetCwdInfo(bufwinnr("x"), 0)')) eq('y Xdir2 1', eval('GetCwdInfo(bufwinnr("y"), 0)')) eq('z Xdir3 1', eval('GetCwdInfo(bufwinnr("z"), 0)')) - execute('let tp_nr = tabpagenr()') - execute('tabrewind') + command('let tp_nr = tabpagenr()') + command('tabrewind') eq('x Xtopdir 0', eval('GetCwdInfo(3, tp_nr)')) eq('y Xdir2 1', eval('GetCwdInfo(2, tp_nr)')) eq('z Xdir3 1', eval('GetCwdInfo(1, tp_nr)')) diff --git a/test/functional/legacy/glob2regpat_spec.lua b/test/functional/legacy/glob2regpat_spec.lua index 82e7e3010f..029d95206e 100644 --- a/test/functional/legacy/glob2regpat_spec.lua +++ b/test/functional/legacy/glob2regpat_spec.lua @@ -1,16 +1,15 @@ -- Tests for signs local helpers = require('test.functional.helpers')(after_each) -local clear, execute = helpers.clear, helpers.execute -local eq, neq, eval = helpers.eq, helpers.neq, helpers.eval +local clear, exc_exec = helpers.clear, helpers.exc_exec +local eq, eval = helpers.eq, helpers.eval describe('glob2regpat()', function() before_each(clear) it('handles invalid input', function() - execute('call glob2regpat(1.33)') - helpers.feed('<cr>') - neq(nil, string.find(eval('v:errmsg'), '^E806:')) + eq('Vim(call):E806: using Float as a String', + exc_exec('call glob2regpat(1.33)')) end) it('returns ^$ for empty input', function() eq('^$', eval("glob2regpat('')")) diff --git a/test/functional/legacy/increment_spec.lua b/test/functional/legacy/increment_spec.lua index a76718ed8e..15273a4ad5 100644 --- a/test/functional/legacy/increment_spec.lua +++ b/test/functional/legacy/increment_spec.lua @@ -1,7 +1,7 @@ -- Tests for using Ctrl-A/Ctrl-X on visual selections local helpers = require('test.functional.helpers')(after_each) -local source, execute = helpers.source, helpers.execute +local source, command = helpers.source, helpers.command local call, clear = helpers.call, helpers.clear local eq, nvim = helpers.eq, helpers.meths @@ -742,14 +742,14 @@ describe('Ctrl-A/Ctrl-X on visual selections', function() local id = string.format('%02d', i) it('works on Test ' .. id, function() - execute('set nrformats&vi') -- &vi makes Vim compatible + command('set nrformats&vi') -- &vi makes Vim compatible call('Test_visual_increment_' .. id) eq({}, nvim.get_vvar('errors')) end) end it('does not drop leading zeroes', function() - execute('set nrformats&vi') -- &vi makes Vim compatible + command('set nrformats&vi') -- &vi makes Vim compatible call('Test_normal_increment_01') eq({}, nvim.get_vvar('errors')) end) diff --git a/test/functional/legacy/insertcount_spec.lua b/test/functional/legacy/insertcount_spec.lua index 3142f040b3..e53c9dc6ce 100644 --- a/test/functional/legacy/insertcount_spec.lua +++ b/test/functional/legacy/insertcount_spec.lua @@ -2,7 +2,7 @@ local helpers = require('test.functional.helpers')(after_each) local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local execute, expect = helpers.execute, helpers.expect +local feed_command, expect = helpers.feed_command, helpers.expect describe('insertcount', function() setup(clear) @@ -13,7 +13,7 @@ describe('insertcount', function() Second line Last line]]) - execute('/Second') + feed_command('/Second') feed('4gro') expect([[ diff --git a/test/functional/legacy/join_spec.lua b/test/functional/legacy/join_spec.lua index 3c4da8119c..d683d25eb0 100644 --- a/test/functional/legacy/join_spec.lua +++ b/test/functional/legacy/join_spec.lua @@ -2,19 +2,19 @@ local helpers = require('test.functional.helpers')(after_each) local clear, eq = helpers.clear, helpers.eq -local eval, execute = helpers.eval, helpers.execute +local eval, command = helpers.eval, helpers.command describe('joining lines', function() before_each(clear) it('is working', function() - execute('new') - execute([[call setline(1, ['one', 'two', 'three', 'four'])]]) - execute('normal J') + command('new') + command([[call setline(1, ['one', 'two', 'three', 'four'])]]) + command('normal J') eq('one two', eval('getline(1)')) - execute('%del') - execute([[call setline(1, ['one', 'two', 'three', 'four'])]]) - execute('normal 10J') + command('%del') + command([[call setline(1, ['one', 'two', 'three', 'four'])]]) + command('normal 10J') eq('one two three four', eval('getline(1)')) end) end) diff --git a/test/functional/legacy/lispwords_spec.lua b/test/functional/legacy/lispwords_spec.lua index 2ec51dca1b..57d8d51377 100644 --- a/test/functional/legacy/lispwords_spec.lua +++ b/test/functional/legacy/lispwords_spec.lua @@ -2,7 +2,7 @@ local helpers = require('test.functional.helpers')(after_each) local clear = helpers.clear local eq = helpers.eq local eval = helpers.eval -local execute = helpers.execute +local command = helpers.command local source = helpers.source describe('lispwords', function() @@ -17,7 +17,7 @@ describe('lispwords', function() eq('bar,baz,quux', eval('&l:lispwords')) eq('bar,baz,quux', eval('&lispwords')) - execute('setlocal lispwords<') + command('setlocal lispwords<') eq('foo,bar,baz', eval('&g:lispwords')) eq('foo,bar,baz', eval('&l:lispwords')) eq('foo,bar,baz', eval('&lispwords')) diff --git a/test/functional/legacy/listchars_spec.lua b/test/functional/legacy/listchars_spec.lua index d2838cddb6..3c0fa48e76 100644 --- a/test/functional/legacy/listchars_spec.lua +++ b/test/functional/legacy/listchars_spec.lua @@ -2,12 +2,12 @@ local helpers = require('test.functional.helpers')(after_each) local feed, insert, source = helpers.feed, helpers.insert, helpers.source -local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect +local clear, feed_command, expect = helpers.clear, helpers.feed_command, helpers.expect describe("'listchars'", function() before_each(function() clear() - execute('set listchars&vi') + feed_command('set listchars&vi') end) it("works with 'list'", function() @@ -26,14 +26,14 @@ describe("'listchars'", function() dd ee ]]) - execute('let g:lines = []') + feed_command('let g:lines = []') -- Set up 'listchars', switch on 'list', and use the "GG" mapping to record -- what the buffer lines look like. - execute('set listchars+=tab:>-,space:.,trail:<') - execute('set list') - execute('/^start:/') - execute('normal! jzt') + feed_command('set listchars+=tab:>-,space:.,trail:<') + feed_command('set list') + feed_command('/^start:/') + feed_command('normal! jzt') feed('GG<cr>') feed('GG<cr>') feed('GG<cr>') @@ -41,7 +41,7 @@ describe("'listchars'", function() feed('GGH') -- Repeat without displaying "trail" spaces. - execute('set listchars-=trail:<') + feed_command('set listchars-=trail:<') feed('GG<cr>') feed('GG<cr>') feed('GG<cr>') @@ -49,8 +49,8 @@ describe("'listchars'", function() feed('GG') -- Delete the buffer contents and :put the collected lines. - execute('%d') - execute('put =g:lines', '1d') + feed_command('%d') + feed_command('put =g:lines', '1d') -- Assert buffer contents. expect([[ @@ -76,21 +76,21 @@ describe("'listchars'", function() -- Set up 'listchars', switch 'list' *off* (:list must show the 'listchars' -- even when 'list' is off), then run :list and collect the output. - execute('set listchars+=tab:>-,space:.,trail:<') - execute('set nolist') - execute('/^start:/') - execute('redir! => g:lines') - execute('+1,$list') - execute('redir END') + feed_command('set listchars+=tab:>-,space:.,trail:<') + feed_command('set nolist') + feed_command('/^start:/') + feed_command('redir! => g:lines') + feed_command('+1,$list') + feed_command('redir END') -- Delete the buffer contents and :put the collected lines. - execute('%d') - execute('put =g:lines', '1d') + feed_command('%d') + feed_command('put =g:lines', '1d') -- Assert buffer contents. expect([[ - - + + ..fff>--<<$ >-------gg>-----$ .....h>-$ diff --git a/test/functional/legacy/listlbr_spec.lua b/test/functional/legacy/listlbr_spec.lua index eb979edc69..d39125c9e6 100644 --- a/test/functional/legacy/listlbr_spec.lua +++ b/test/functional/legacy/listlbr_spec.lua @@ -2,7 +2,7 @@ local helpers = require('test.functional.helpers')(after_each) local feed, insert, source = helpers.feed, helpers.insert, helpers.source -local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect +local clear, feed_command, expect = helpers.clear, helpers.feed_command, helpers.expect describe('listlbr', function() setup(clear) @@ -11,13 +11,13 @@ describe('listlbr', function() insert([[ dummy text]]) - execute('set wildchar=^E') - execute('10new') - execute('vsp') - execute('vert resize 20') - execute([[put =\"\tabcdef hijklmn\tpqrstuvwxyz_1060ABCDEFGHIJKLMNOP \"]]) - execute('norm! zt') - execute('set ts=4 sw=4 sts=4 linebreak sbr=+ wrap') + feed_command('set wildchar=^E') + feed_command('10new') + feed_command('vsp') + feed_command('vert resize 20') + feed_command([[put =\"\tabcdef hijklmn\tpqrstuvwxyz_1060ABCDEFGHIJKLMNOP \"]]) + feed_command('norm! zt') + feed_command('set ts=4 sw=4 sts=4 linebreak sbr=+ wrap') source([[ fu! ScreenChar(width) let c='' @@ -36,128 +36,128 @@ describe('listlbr', function() wincmd p endfu ]]) - execute('let g:test="Test 1: set linebreak"') - execute('redraw!') - execute('let line=ScreenChar(winwidth(0))') - execute('call DoRecordScreen()') - - execute('let g:test="Test 2: set linebreak + set list"') - execute('set linebreak list listchars=') - execute('redraw!') - execute('let line=ScreenChar(winwidth(0))') - execute('call DoRecordScreen()') - - execute('let g:test ="Test 3: set linebreak nolist"') - execute('set nolist linebreak') - execute('redraw!') - execute('let line=ScreenChar(winwidth(0))') - execute('call DoRecordScreen()') - - execute('let g:test ="Test 4: set linebreak with tab and 1 line as long as screen: should break!"') - execute('set nolist linebreak ts=8') - execute([[let line="1\t".repeat('a', winwidth(0)-2)]]) - execute('$put =line') - execute('$') - execute('norm! zt') - execute('redraw!') - execute('let line=ScreenChar(winwidth(0))') - execute('call DoRecordScreen()') - execute([[let line="_S_\t bla"]]) - execute('$put =line') - execute('$') - execute('norm! zt') - - execute('let g:test ="Test 5: set linebreak with conceal and set list and tab displayed by different char (line may not be truncated)"') - execute('set cpo&vim list linebreak conceallevel=2 concealcursor=nv listchars=tab:ab') - execute('syn match ConcealVar contained /_/ conceal') - execute('syn match All /.*/ contains=ConcealVar') - execute('let line=ScreenChar(winwidth(0))') - execute('call DoRecordScreen()') - execute('set cpo&vim linebreak') - - execute('let g:test ="Test 6: set linebreak with visual block mode"') - execute('let line="REMOVE: this not"') - execute('$put =g:test') - execute('$put =line') - execute('let line="REMOVE: aaaaaaaaaaaaa"') - execute('$put =line') - execute('1/^REMOVE:') + feed_command('let g:test="Test 1: set linebreak"') + feed_command('redraw!') + feed_command('let line=ScreenChar(winwidth(0))') + feed_command('call DoRecordScreen()') + + feed_command('let g:test="Test 2: set linebreak + set list"') + feed_command('set linebreak list listchars=') + feed_command('redraw!') + feed_command('let line=ScreenChar(winwidth(0))') + feed_command('call DoRecordScreen()') + + feed_command('let g:test ="Test 3: set linebreak nolist"') + feed_command('set nolist linebreak') + feed_command('redraw!') + feed_command('let line=ScreenChar(winwidth(0))') + feed_command('call DoRecordScreen()') + + feed_command('let g:test ="Test 4: set linebreak with tab and 1 line as long as screen: should break!"') + feed_command('set nolist linebreak ts=8') + feed_command([[let line="1\t".repeat('a', winwidth(0)-2)]]) + feed_command('$put =line') + feed_command('$') + feed_command('norm! zt') + feed_command('redraw!') + feed_command('let line=ScreenChar(winwidth(0))') + feed_command('call DoRecordScreen()') + feed_command([[let line="_S_\t bla"]]) + feed_command('$put =line') + feed_command('$') + feed_command('norm! zt') + + feed_command('let g:test ="Test 5: set linebreak with conceal and set list and tab displayed by different char (line may not be truncated)"') + feed_command('set cpo&vim list linebreak conceallevel=2 concealcursor=nv listchars=tab:ab') + feed_command('syn match ConcealVar contained /_/ conceal') + feed_command('syn match All /.*/ contains=ConcealVar') + feed_command('let line=ScreenChar(winwidth(0))') + feed_command('call DoRecordScreen()') + feed_command('set cpo&vim linebreak') + + feed_command('let g:test ="Test 6: set linebreak with visual block mode"') + feed_command('let line="REMOVE: this not"') + feed_command('$put =g:test') + feed_command('$put =line') + feed_command('let line="REMOVE: aaaaaaaaaaaaa"') + feed_command('$put =line') + feed_command('1/^REMOVE:') feed('0<C-V>jf x') - execute('$put') - execute('set cpo&vim linebreak') + feed_command('$put') + feed_command('set cpo&vim linebreak') - execute('let g:test ="Test 7: set linebreak with visual block mode and v_b_A"') - execute('$put =g:test') + feed_command('let g:test ="Test 7: set linebreak with visual block mode and v_b_A"') + feed_command('$put =g:test') feed('Golong line: <esc>40afoobar <esc>aTARGET at end<esc>') - execute([[exe "norm! $3B\<C-v>eAx\<Esc>"]]) - execute('set cpo&vim linebreak sbr=') + feed_command([[exe "norm! $3B\<C-v>eAx\<Esc>"]]) + feed_command('set cpo&vim linebreak sbr=') - execute('let g:test ="Test 8: set linebreak with visual char mode and changing block"') - execute('$put =g:test') + feed_command('let g:test ="Test 8: set linebreak with visual char mode and changing block"') + feed_command('$put =g:test') feed('Go1111-1111-1111-11-1111-1111-1111<esc>0f-lv3lc2222<esc>bgj.') - execute('let g:test ="Test 9: using redo after block visual mode"') - execute('$put =g:test') + feed_command('let g:test ="Test 9: using redo after block visual mode"') + feed_command('$put =g:test') feed('Go<CR>') feed('aaa<CR>') feed('aaa<CR>') feed('a<ESC>2k<C-V>2j~e.<CR>') - execute('let g:test ="Test 10: using normal commands after block-visual"') - execute('$put =g:test') - execute('set linebreak') + feed_command('let g:test ="Test 10: using normal commands after block-visual"') + feed_command('$put =g:test') + feed_command('set linebreak') feed('Go<cr>') feed('abcd{ef<cr>') feed('ghijklm<cr>') feed('no}pqrs<esc>2k0f{<C-V><C-V>c%<esc>') - execute('let g:test ="Test 11: using block replace mode after wrapping"') - execute('$put =g:test') - execute('set linebreak wrap') + feed_command('let g:test ="Test 11: using block replace mode after wrapping"') + feed_command('$put =g:test') + feed_command('set linebreak wrap') feed('Go<esc>150aa<esc>yypk147|<C-V>jr0<cr>') - execute('let g:test ="Test 12: set linebreak list listchars=space:_,tab:>-,tail:-,eol:$"') - execute('set list listchars=space:_,trail:-,tab:>-,eol:$') - execute('$put =g:test') - execute([[let line="a aaaaaaaaaaaaaaaaaaaaaa\ta "]]) - execute('$put =line') - execute('$') - execute('norm! zt') - execute('redraw!') - execute('let line=ScreenChar(winwidth(0))') - execute('call DoRecordScreen()') + feed_command('let g:test ="Test 12: set linebreak list listchars=space:_,tab:>-,tail:-,eol:$"') + feed_command('set list listchars=space:_,trail:-,tab:>-,eol:$') + feed_command('$put =g:test') + feed_command([[let line="a aaaaaaaaaaaaaaaaaaaaaa\ta "]]) + feed_command('$put =line') + feed_command('$') + feed_command('norm! zt') + feed_command('redraw!') + feed_command('let line=ScreenChar(winwidth(0))') + feed_command('call DoRecordScreen()') -- Assert buffer contents. expect([[ - + abcdef hijklmn pqrstuvwxyz_1060ABCDEFGHIJKLMNOP - + Test 1: set linebreak abcdef +hijklmn +pqrstuvwxyz_1060ABC +DEFGHIJKLMNOP - + Test 2: set linebreak + set list ^Iabcdef hijklmn^I +pqrstuvwxyz_1060ABC +DEFGHIJKLMNOP - + Test 3: set linebreak nolist abcdef +hijklmn +pqrstuvwxyz_1060ABC +DEFGHIJKLMNOP 1 aaaaaaaaaaaaaaaaaa - + Test 4: set linebreak with tab and 1 line as long as screen: should break! 1 +aaaaaaaaaaaaaaaaaa ~ ~ _S_ bla - + Test 5: set linebreak with conceal and set list and tab displayed by different char (line may not be truncated) Sabbbbbb bla ~ @@ -173,19 +173,19 @@ describe('listlbr', function() Test 8: set linebreak with visual char mode and changing block 1111-2222-1111-11-1111-2222-1111 Test 9: using redo after block visual mode - + AaA AaA A Test 10: using normal commands after block-visual - + abcdpqrs Test 11: using block replace mode after wrapping aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0aaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0aaa Test 12: set linebreak list listchars=space:_,tab:>-,tail:-,eol:$ a aaaaaaaaaaaaaaaaaaaaaa a - + Test 12: set linebreak list listchars=space:_,tab:>-,tail:-,eol:$ a_ aaaaaaaaaaaaaaaaaaaa diff --git a/test/functional/legacy/mapping_spec.lua b/test/functional/legacy/mapping_spec.lua index 1712219d04..56a5652184 100644 --- a/test/functional/legacy/mapping_spec.lua +++ b/test/functional/legacy/mapping_spec.lua @@ -2,7 +2,7 @@ local helpers = require('test.functional.helpers')(after_each) local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local execute, expect, wait = helpers.execute, helpers.expect, helpers.wait +local feed_command, expect, wait = helpers.feed_command, helpers.expect, helpers.wait describe('mapping', function() before_each(clear) @@ -13,7 +13,7 @@ describe('mapping', function() ]]) -- Abbreviations with ั (0x80) should work. - execute('inoreab ัะบะฟั vim') + feed_command('inoreab ัะบะฟั vim') feed('GAัะบะฟั <esc>') expect([[ @@ -23,61 +23,61 @@ describe('mapping', function() it('Ctrl-c works in Insert mode', function() -- Mapping of ctrl-c in insert mode - execute('set cpo-=< cpo-=k') - execute('inoremap <c-c> <ctrl-c>') - execute('cnoremap <c-c> dummy') - execute('cunmap <c-c>') + feed_command('set cpo-=< cpo-=k') + feed_command('inoremap <c-c> <ctrl-c>') + feed_command('cnoremap <c-c> dummy') + feed_command('cunmap <c-c>') feed('GA<cr>') feed('TEST2: CTRL-C |') wait() feed('<c-c>A|<cr><esc>') wait() - execute('unmap <c-c>') - execute('unmap! <c-c>') + feed_command('unmap <c-c>') + feed_command('unmap! <c-c>') expect([[ - + TEST2: CTRL-C |<ctrl-c>A| ]]) end) it('Ctrl-c works in Visual mode', function() - execute([[vnoremap <c-c> :<C-u>$put ='vmap works'<cr>]]) + feed_command([[vnoremap <c-c> :<C-u>$put ='vmap works'<cr>]]) feed('GV') -- XXX: For some reason the mapping is only triggered -- when <C-c> is in a separate feed command. wait() feed('<c-c>') - execute('vunmap <c-c>') + feed_command('vunmap <c-c>') expect([[ - + vmap works]]) end) it('langmap', function() -- langmap should not get remapped in insert mode. - execute('inoremap { FAIL_ilangmap') - execute('set langmap=+{ langnoremap') + feed_command('inoremap { FAIL_ilangmap') + feed_command('set langmap=+{ langnoremap') feed('o+<esc>') -- Insert mode expr mapping with langmap. - execute('inoremap <expr> { "FAIL_iexplangmap"') + feed_command('inoremap <expr> { "FAIL_iexplangmap"') feed('o+<esc>') -- langmap should not get remapped in cmdline mode. - execute('cnoremap { FAIL_clangmap') + feed_command('cnoremap { FAIL_clangmap') feed('o+<esc>') - execute('cunmap {') + feed_command('cunmap {') -- cmdline mode expr mapping with langmap. - execute('cnoremap <expr> { "FAIL_cexplangmap"') + feed_command('cnoremap <expr> { "FAIL_cexplangmap"') feed('o+<esc>') - execute('cunmap {') + feed_command('cunmap {') -- Assert buffer contents. expect([[ - + + + + @@ -91,10 +91,10 @@ describe('mapping', function() ]]) -- Vim's issue #212 (feedkeys insert mapping at current position) - execute('nnoremap . :call feedkeys(".", "in")<cr>') + feed_command('nnoremap . :call feedkeys(".", "in")<cr>') feed('/^a b<cr>') feed('0qqdw.ifoo<esc>qj0@q<esc>') - execute('unmap .') + feed_command('unmap .') expect([[ fooc d fooc d @@ -103,23 +103,23 @@ describe('mapping', function() it('i_CTRL-G_U', function() -- <c-g>U<cursor> works only within a single line - execute('imapclear') - execute('imap ( ()<c-g>U<left>') + feed_command('imapclear') + feed_command('imap ( ()<c-g>U<left>') feed('G2o<esc>ki<cr>Test1: text with a (here some more text<esc>k.') -- test undo feed('G2o<esc>ki<cr>Test2: text wit a (here some more text [und undo]<c-g>u<esc>k.u') - execute('imapclear') - execute('set whichwrap=<,>,[,]') + feed_command('imapclear') + feed_command('set whichwrap=<,>,[,]') feed('G3o<esc>2k') - execute([[:exe ":norm! iTest3: text with a (parenthesis here\<C-G>U\<Right>new line here\<esc>\<up>\<up>."]]) + feed_command([[:exe ":norm! iTest3: text with a (parenthesis here\<C-G>U\<Right>new line here\<esc>\<up>\<up>."]]) expect([[ - - + + Test1: text with a (here some more text) Test1: text with a (here some more text) - - + + Test2: text wit a (here some more text [und undo]) new line here Test3: text with a (parenthesis here diff --git a/test/functional/legacy/marks_spec.lua b/test/functional/legacy/marks_spec.lua index 6ecba70f08..bcec179ca2 100644 --- a/test/functional/legacy/marks_spec.lua +++ b/test/functional/legacy/marks_spec.lua @@ -1,6 +1,6 @@ local helpers = require('test.functional.helpers')(after_each) local feed, insert, source = helpers.feed, helpers.insert, helpers.source -local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect +local clear, feed_command, expect = helpers.clear, helpers.feed_command, helpers.expect describe('marks', function() before_each(function() @@ -9,14 +9,14 @@ describe('marks', function() it('restores a deleted mark after delete-undo-redo-undo', function() insert([[ - + textline A textline B textline C - + Results:]]) - execute([[:/^\t/+1]]) + feed_command([[:/^\t/+1]]) feed([[maddu<C-R>u]]) source([[ let g:a = string(getpos("'a")) @@ -24,11 +24,11 @@ describe('marks', function() ]]) expect([=[ - + textline A textline B textline C - + Results: Mark after delete-undo-redo-undo: [0, 3, 2, 0]]=]) end) diff --git a/test/functional/legacy/nested_function_spec.lua b/test/functional/legacy/nested_function_spec.lua index be9b66ee38..7a2ba1ecf2 100644 --- a/test/functional/legacy/nested_function_spec.lua +++ b/test/functional/legacy/nested_function_spec.lua @@ -2,7 +2,7 @@ local helpers = require('test.functional.helpers')(after_each) local clear, insert = helpers.clear, helpers.insert -local execute, expect, source = helpers.execute, helpers.expect, helpers.source +local command, expect, source = helpers.command, helpers.expect, helpers.source describe('test_nested_function', function() setup(clear) @@ -36,7 +36,7 @@ describe('test_nested_function', function() : endfunction : call s:{fn}() :endfunction]]) - execute('call NestedFunc()') + command('call NestedFunc()') -- Assert buffer contents. expect([[ diff --git a/test/functional/legacy/packadd_spec.lua b/test/functional/legacy/packadd_spec.lua index 2d851819e3..7c44353aec 100644 --- a/test/functional/legacy/packadd_spec.lua +++ b/test/functional/legacy/packadd_spec.lua @@ -1,7 +1,7 @@ -- Tests for 'packpath' and :packadd local helpers = require('test.functional.helpers')(after_each) -local clear, source, execute = helpers.clear, helpers.source, helpers.execute +local clear, source, command = helpers.clear, helpers.source, helpers.command local call, eq, nvim = helpers.call, helpers.eq, helpers.meths local feed = helpers.feed @@ -83,6 +83,41 @@ describe('packadd', function() call assert_equal(new_rtp, &rtp) endfunc + func Test_packadd_symlink_dir() + if !has('unix') + return + endif + let top2_dir = s:topdir . '/Xdir2' + let real_dir = s:topdir . '/Xsym' + call mkdir(real_dir, 'p') + exec "silent! !ln -s Xsym" top2_dir + let &rtp = top2_dir . ',' . top2_dir . '/after' + let &packpath = &rtp + + let s:plugdir = top2_dir . '/pack/mine/opt/mytest' + call mkdir(s:plugdir . '/plugin', 'p') + + exe 'split ' . s:plugdir . '/plugin/test.vim' + call setline(1, 'let g:plugin_works = 44') + wq + let g:plugin_works = 0 + + packadd mytest + + " Must have been inserted in the middle, not at the end + call assert_true(&rtp =~ '/pack/mine/opt/mytest,') + call assert_equal(44, g:plugin_works) + + " No change when doing it again. + let rtp_before = &rtp + packadd mytest + call assert_equal(rtp_before, &rtp) + + set rtp& + let rtp = &rtp + exec "silent !rm" top2_dir + endfunc + func Test_packloadall() " plugin foo with an autoload directory let fooplugindir = &packpath . '/pack/mine/start/foo/plugin' @@ -227,6 +262,11 @@ describe('packadd', function() expected_empty() end) + it('works with symlinks', function() + call('Test_packadd_symlink_dir') + expected_empty() + end) + it('works with :packloadall', function() call('Test_packloadall') expected_empty() @@ -263,12 +303,12 @@ describe('packadd', function() [2] = {bold = true, reverse = true} }) - execute([[let optdir1 = &packpath . '/pack/mine/opt']]) - execute([[let optdir2 = &packpath . '/pack/candidate/opt']]) - execute([[call mkdir(optdir1 . '/pluginA', 'p')]]) - execute([[call mkdir(optdir1 . '/pluginC', 'p')]]) - execute([[call mkdir(optdir2 . '/pluginB', 'p')]]) - execute([[call mkdir(optdir2 . '/pluginC', 'p')]]) + command([[let optdir1 = &packpath . '/pack/mine/opt']]) + command([[let optdir2 = &packpath . '/pack/candidate/opt']]) + command([[call mkdir(optdir1 . '/pluginA', 'p')]]) + command([[call mkdir(optdir1 . '/pluginC', 'p')]]) + command([[call mkdir(optdir2 . '/pluginB', 'p')]]) + command([[call mkdir(optdir2 . '/pluginC', 'p')]]) end) it('works', function() diff --git a/test/functional/legacy/search_mbyte_spec.lua b/test/functional/legacy/search_mbyte_spec.lua index a5a5822a45..a365f79cdf 100644 --- a/test/functional/legacy/search_mbyte_spec.lua +++ b/test/functional/legacy/search_mbyte_spec.lua @@ -1,6 +1,10 @@ local helpers = require('test.functional.helpers')(after_each) + +local wait = helpers.wait +local clear = helpers.clear local insert = helpers.insert -local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect +local expect = helpers.expect +local command = helpers.command describe('search_mbyte', function() before_each(clear) @@ -8,17 +12,18 @@ describe('search_mbyte', function() it("search('multi-byte char', 'bce')", function() insert([=[ Results: - + Test bce: ๏ผก]=]) + wait() - execute('/^Test bce:/+1') - execute([[$put =search('๏ผก', 'bce', line('.'))]]) + command('/^Test bce:/+1') + command([[$put =search('๏ผก', 'bce', line('.'))]]) -- Assert buffer contents. expect([=[ Results: - + Test bce: ๏ผก 4]=]) diff --git a/test/functional/legacy/search_spec.lua b/test/functional/legacy/search_spec.lua new file mode 100644 index 0000000000..5f71861821 --- /dev/null +++ b/test/functional/legacy/search_spec.lua @@ -0,0 +1,474 @@ +local helpers = require('test.functional.helpers')(after_each) +local Screen = require('test.functional.ui.screen') +local clear = helpers.clear +local command = helpers.command +local eq = helpers.eq +local eval = helpers.eval +local feed = helpers.feed +local funcs = helpers.funcs + +describe('search cmdline', function() + local screen + + before_each(function() + clear() + command('set nohlsearch') + screen = Screen.new(20, 3) + screen:attach() + screen:set_default_attr_ids({ + inc = {reverse = true} + }) + end) + + local function tenlines() + funcs.setline(1, { + ' 1', ' 2 these', ' 3 the', ' 4 their', ' 5 there', + ' 6 their', ' 7 the', ' 8 them', ' 9 these', ' 10 foobar' + }) + command('1') + end + + it('history can be navigated with <C-N>/<C-P>', function() + tenlines() + command('set noincsearch') + feed('/foobar<CR>') + feed('/the<CR>') + eq('the', eval('@/')) + feed('/thes<C-P><C-P><CR>') + eq('foobar', eval('@/')) + end) + + describe('can traverse matches', function() + before_each(tenlines) + local function forwarditer(wrapscan) + command('set incsearch '..wrapscan) + feed('/the') + screen:expect([[ + 1 | + 2 {inc:the}se | + /the^ | + ]]) + feed('<C-G>') + screen:expect([[ + 2 these | + 3 {inc:the} | + /the^ | + ]]) + eq({0, 0, 0, 0}, funcs.getpos('"')) + feed('<C-G>') + screen:expect([[ + 3 the | + 4 {inc:the}ir | + /the^ | + ]]) + feed('<C-G>') + screen:expect([[ + 4 their | + 5 {inc:the}re | + /the^ | + ]]) + feed('<C-G>') + screen:expect([[ + 5 there | + 6 {inc:the}ir | + /the^ | + ]]) + feed('<C-G>') + screen:expect([[ + 6 their | + 7 {inc:the} | + /the^ | + ]]) + feed('<C-G>') + screen:expect([[ + 7 the | + 8 {inc:the}m | + /the^ | + ]]) + feed('<C-G>') + screen:expect([[ + 8 them | + 9 {inc:the}se | + /the^ | + ]]) + feed('<C-G>') + if wrapscan == 'wrapscan' then + screen:expect([[ + 2 {inc:the}se | + 3 the | + /the^ | + ]]) + else + screen:expect([[ + 8 them | + 9 {inc:the}se | + /the^ | + ]]) + feed('<CR>') + eq({0, 0, 0, 0}, funcs.getpos('"')) + end + end + + local function backiter(wrapscan) + command('set incsearch '..wrapscan) + command('$') + + feed('?the') + screen:expect([[ + 9 {inc:the}se | + 10 foobar | + ?the^ | + ]]) + if wrapscan == 'wrapscan' then + feed('<C-G>') + screen:expect([[ + 2 {inc:the}se | + 3 the | + ?the^ | + ]]) + feed('<CR>') + screen:expect([[ + 2 ^these | + 3 the | + ?the | + ]]) + else + feed('<C-G>') + screen:expect([[ + 9 {inc:the}se | + 10 foobar | + ?the^ | + ]]) + feed('<CR>') + screen:expect([[ + 9 ^these | + 10 foobar | + ?the | + ]]) + end + command('$') + feed('?the') + screen:expect([[ + 9 {inc:the}se | + 10 foobar | + ?the^ | + ]]) + feed('<C-T>') + screen:expect([[ + 8 {inc:the}m | + 9 these | + ?the^ | + ]]) + for i = 1, 6 do + feed('<C-T>') + -- Avoid sleep just before expect, otherwise expect will take the full + -- timeout + if i ~= 6 then + screen:sleep(1) + end + end + screen:expect([[ + 2 {inc:the}se | + 3 the | + ?the^ | + ]]) + feed('<C-T>') + if wrapscan == 'wrapscan' then + screen:expect([[ + 9 {inc:the}se | + 10 foobar | + ?the^ | + ]]) + else + screen:expect([[ + 2 {inc:the}se | + 3 the | + ?the^ | + ]]) + end + end + + it("using <C-G> and 'nowrapscan'", function() + forwarditer('nowrapscan') + end) + + it("using <C-G> and 'wrapscan'", function() + forwarditer('wrapscan') + end) + + it("using <C-T> and 'nowrapscan'", function() + backiter('nowrapscan') + end) + + it("using <C-T> and 'wrapscan'", function() + backiter('wrapscan') + end) + end) + + it('expands pattern with <C-L>', function() + tenlines() + command('set incsearch wrapscan') + + feed('/the') + screen:expect([[ + 1 | + 2 {inc:the}se | + /the^ | + ]]) + feed('<C-L>') + screen:expect([[ + 1 | + 2 {inc:thes}e | + /thes^ | + ]]) + feed('<C-G>') + screen:expect([[ + 9 {inc:thes}e | + 10 foobar | + /thes^ | + ]]) + feed('<C-G>') + screen:expect([[ + 2 {inc:thes}e | + 3 the | + /thes^ | + ]]) + feed('<CR>') + screen:expect([[ + 2 ^these | + 3 the | + /thes | + ]]) + + command('1') + command('set nowrapscan') + feed('/the') + screen:expect([[ + 1 | + 2 {inc:the}se | + /the^ | + ]]) + feed('<C-L>') + screen:expect([[ + 1 | + 2 {inc:thes}e | + /thes^ | + ]]) + feed('<C-G>') + screen:expect([[ + 9 {inc:thes}e | + 10 foobar | + /thes^ | + ]]) + feed('<C-G><CR>') + screen:expect([[ + 9 ^these | + 10 foobar | + /thes | + ]]) + end) + + it('reduces pattern with <BS> and keeps cursor position', function() + tenlines() + command('set incsearch wrapscan') + + -- First match + feed('/thei') + screen:expect([[ + 4 {inc:thei}r | + 5 there | + /thei^ | + ]]) + -- Match from initial cursor position when modifying search + feed('<BS>') + screen:expect([[ + 1 | + 2 {inc:the}se | + /the^ | + ]]) + -- New text advances to next match + feed('s') + screen:expect([[ + 1 | + 2 {inc:thes}e | + /thes^ | + ]]) + -- Stay on this match when deleting a character + feed('<BS>') + screen:expect([[ + 1 | + 2 {inc:the}se | + /the^ | + ]]) + -- Advance to previous match + feed('<C-T>') + screen:expect([[ + 9 {inc:the}se | + 10 foobar | + /the^ | + ]]) + -- Extend search to include next character + feed('<C-L>') + screen:expect([[ + 9 {inc:thes}e | + 10 foobar | + /thes^ | + ]]) + -- Deleting all characters resets the cursor position + feed('<BS><BS><BS><BS>') + screen:expect([[ + 1 | + 2 these | + /^ | + ]]) + feed('the') + screen:expect([[ + 1 | + 2 {inc:the}se | + /the^ | + ]]) + feed('\\>') + screen:expect([[ + 2 these | + 3 {inc:the} | + /the\>^ | + ]]) + end) + + it('can traverse matches in the same line with <C-G>/<C-T>', function() + funcs.setline(1, { ' 1', ' 2 these', ' 3 the theother' }) + command('1') + command('set incsearch') + + -- First match + feed('/the') + screen:expect([[ + 1 | + 2 {inc:the}se | + /the^ | + ]]) + + -- Next match, different line + feed('<C-G>') + screen:expect([[ + 2 these | + 3 {inc:the} theother | + /the^ | + ]]) + + -- Next match, same line + feed('<C-G>') + screen:expect([[ + 2 these | + 3 the {inc:the}other | + /the^ | + ]]) + feed('<C-G>') + screen:expect([[ + 2 these | + 3 the theo{inc:the}r | + /the^ | + ]]) + + -- Previous match, same line + feed('<C-T>') + screen:expect([[ + 2 these | + 3 the {inc:the}other | + /the^ | + ]]) + feed('<C-T>') + screen:expect([[ + 2 these | + 3 {inc:the} theother | + /the^ | + ]]) + + -- Previous match, different line + feed('<C-T>') + screen:expect([[ + 2 {inc:the}se | + 3 the theother | + /the^ | + ]]) + end) + + it('keeps the view after deleting a char from the search', function() + screen:detach() + screen = Screen.new(20, 6) + screen:attach() + screen:set_default_attr_ids({ + inc = {reverse = true} + }) + screen:set_default_attr_ignore({ + {bold=true, reverse=true}, {bold=true, foreground=Screen.colors.Blue1} + }) + tenlines() + + feed('/foo') + screen:expect([[ + 6 their | + 7 the | + 8 them | + 9 these | + 10 {inc:foo}bar | + /foo^ | + ]]) + feed('<BS>') + screen:expect([[ + 6 their | + 7 the | + 8 them | + 9 these | + 10 {inc:fo}obar | + /fo^ | + ]]) + feed('<CR>') + screen:expect([[ + 6 their | + 7 the | + 8 them | + 9 these | + 10 ^foobar | + /fo | + ]]) + eq({lnum = 10, leftcol = 0, col = 4, topfill = 0, topline = 6, + coladd = 0, skipcol = 0, curswant = 4}, + funcs.winsaveview()) + end) + + it('restores original view after failed search', function() + screen:detach() + screen = Screen.new(40, 3) + screen:attach() + screen:set_default_attr_ids({ + inc = {reverse = true}, + err = { foreground = Screen.colors.Grey100, background = Screen.colors.Red }, + more = { bold = true, foreground = Screen.colors.SeaGreen4 }, + }) + tenlines() + feed('0') + feed('/foo') + screen:expect([[ + 9 these | + 10 {inc:foo}bar | + /foo^ | + ]]) + feed('<C-W>') + screen:expect([[ + 1 | + 2 these | + /^ | + ]]) + feed('<CR>') + screen:expect([[ + / | + {err:E35: No previous regular expression} | + {more:Press ENTER or type command to continue}^ | + ]]) + feed('<CR>') + eq({lnum = 1, leftcol = 0, col = 0, topfill = 0, topline = 1, + coladd = 0, skipcol = 0, curswant = 0}, + funcs.winsaveview()) + end) +end) diff --git a/test/functional/legacy/searchpos_spec.lua b/test/functional/legacy/searchpos_spec.lua index 7d4b7a3734..60f1edcd3f 100644 --- a/test/functional/legacy/searchpos_spec.lua +++ b/test/functional/legacy/searchpos_spec.lua @@ -1,7 +1,7 @@ local helpers = require('test.functional.helpers')(after_each) local call = helpers.call local clear = helpers.clear -local execute = helpers.execute +local command = helpers.command local eq = helpers.eq local eval = helpers.eval local insert = helpers.insert @@ -19,7 +19,7 @@ describe('searchpos', function() call('cursor', 1, 2) eq({2, 1, 1}, eval([[searchpos('\%(\([a-z]\)\|\_.\)\{-}xyz', 'pcW')]])) - execute('set cpo-=c') + command('set cpo-=c') call('cursor', 1, 2) eq({1, 2, 2}, eval([[searchpos('\%(\([a-z]\)\|\_.\)\{-}xyz', 'pcW')]])) call('cursor', 1, 3) diff --git a/test/functional/legacy/set_spec.lua b/test/functional/legacy/set_spec.lua index 11f371569d..deb268b1e8 100644 --- a/test/functional/legacy/set_spec.lua +++ b/test/functional/legacy/set_spec.lua @@ -1,30 +1,30 @@ -- Tests for :set local helpers = require('test.functional.helpers')(after_each) -local clear, execute, eval, eq = - helpers.clear, helpers.execute, helpers.eval, helpers.eq +local clear, command, eval, eq = + helpers.clear, helpers.command, helpers.eval, helpers.eq describe(':set', function() before_each(clear) it('handles backslash properly', function() - execute('set iskeyword=a,b,c') - execute('set iskeyword+=d') + command('set iskeyword=a,b,c') + command('set iskeyword+=d') eq('a,b,c,d', eval('&iskeyword')) - execute([[set iskeyword+=\\,e]]) + command([[set iskeyword+=\\,e]]) eq([[a,b,c,d,\,e]], eval('&iskeyword')) - execute('set iskeyword-=e') + command('set iskeyword-=e') eq([[a,b,c,d,\]], eval('&iskeyword')) - execute([[set iskeyword-=\]]) + command([[set iskeyword-=\]]) eq('a,b,c,d', eval('&iskeyword')) end) it('recognizes a trailing comma with +=', function() - execute('set wildignore=*.png,') - execute('set wildignore+=*.jpg') + command('set wildignore=*.png,') + command('set wildignore+=*.jpg') eq('*.png,*.jpg', eval('&wildignore')) end) end) diff --git a/test/functional/legacy/signs_spec.lua b/test/functional/legacy/signs_spec.lua index e80a32455a..0e65edbcf8 100644 --- a/test/functional/legacy/signs_spec.lua +++ b/test/functional/legacy/signs_spec.lua @@ -1,23 +1,23 @@ -- Tests for signs local helpers = require('test.functional.helpers')(after_each) -local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect +local clear, command, expect = helpers.clear, helpers.command, helpers.expect describe('signs', function() setup(clear) it('is working', function() - execute('sign define JumpSign text=x') - execute([[exe 'sign place 42 line=2 name=JumpSign buffer=' . bufnr('')]]) + command('sign define JumpSign text=x') + command([[exe 'sign place 42 line=2 name=JumpSign buffer=' . bufnr('')]]) -- Split the window to the bottom to verify :sign-jump will stay in the current -- window if the buffer is displayed there. - execute('bot split') - execute([[exe 'sign jump 42 buffer=' . bufnr('')]]) - execute([[call append(line('$'), winnr())]]) + command('bot split') + command([[exe 'sign jump 42 buffer=' . bufnr('')]]) + command([[call append(line('$'), winnr())]]) -- Assert buffer contents. expect([[ - + 2]]) end) end) diff --git a/test/functional/legacy/textobjects_spec.lua b/test/functional/legacy/textobjects_spec.lua index 15a93e3819..96f655cc41 100644 --- a/test/functional/legacy/textobjects_spec.lua +++ b/test/functional/legacy/textobjects_spec.lua @@ -1,14 +1,14 @@ local helpers = require('test.functional.helpers')(after_each) local call = helpers.call local clear = helpers.clear -local execute = helpers.execute +local command = helpers.command local expect = helpers.expect local source = helpers.source describe('Text object', function() before_each(function() clear() - execute('set shada=') + command('set shada=') source([[ function SelectionOut(data) new @@ -27,7 +27,7 @@ describe('Text object', function() end) it('Test for vi) without cpo-M', function() - execute('set cpo-=M') + command('set cpo-=M') call('SelectionOut', '(red \\(blue) green)') expect([[ @@ -38,7 +38,7 @@ describe('Text object', function() end) it('Test for vi) with cpo-M #1', function() - execute('set cpo+=M') + command('set cpo+=M') call('SelectionOut', '(red \\(blue) green)') expect([[ @@ -49,7 +49,7 @@ describe('Text object', function() end) it('Test for vi) with cpo-M #2', function() - execute('set cpo+=M') + command('set cpo+=M') call('SelectionOut', '(red (blue\\) green)') expect([[ diff --git a/test/functional/legacy/utf8_spec.lua b/test/functional/legacy/utf8_spec.lua index 4d4f55b9eb..02de6ab735 100644 --- a/test/functional/legacy/utf8_spec.lua +++ b/test/functional/legacy/utf8_spec.lua @@ -2,9 +2,10 @@ local helpers = require('test.functional.helpers')(after_each) local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local execute, expect = helpers.execute, helpers.expect +local command, expect = helpers.command, helpers.expect local eq, eval = helpers.eq, helpers.eval local source = helpers.source +local wait = helpers.wait describe('utf8', function() before_each(clear) @@ -12,16 +13,17 @@ describe('utf8', function() it('is working', function() insert('start:') - execute('new') - execute('call setline(1, ["aaa", "ใใใ", "bbb"])') + command('new') + command('call setline(1, ["aaa", "ใใใ", "bbb"])') -- Visual block Insert adjusts for multi-byte char feed('gg0l<C-V>jjIx<Esc>') + wait() - execute('let r = getline(1, "$")') - execute('bwipeout!') - execute('$put=r') - execute('call garbagecollect(1)') + command('let r = getline(1, "$")') + command('bwipeout!') + command('$put=r') + command('call garbagecollect(1)') expect([[ start: @@ -75,7 +77,7 @@ describe('utf8', function() feed(":Test3 <C-L>'<C-B>$put='<CR>") expect([[ - + Test1 Test2 ใใ Test3 N]]) diff --git a/test/functional/legacy/wordcount_spec.lua b/test/functional/legacy/wordcount_spec.lua index 171ec3de92..5412903866 100644 --- a/test/functional/legacy/wordcount_spec.lua +++ b/test/functional/legacy/wordcount_spec.lua @@ -2,8 +2,9 @@ local helpers = require('test.functional.helpers')(after_each) local feed, insert, source = helpers.feed, helpers.insert, helpers.source -local clear, execute = helpers.clear, helpers.execute +local clear, command = helpers.clear, helpers.command local eq, eval = helpers.eq, helpers.eval +local wait = helpers.wait if helpers.pending_win32(pending) then return end @@ -11,14 +12,13 @@ describe('wordcount', function() before_each(clear) it('is working', function() - execute('set selection=inclusive') - execute('fileformat=unix') - execute('fileformats=unix') + command('set selection=inclusive fileformat=unix fileformats=unix') insert([=[ RESULT test:]=]) + wait() - execute('new') + command('new') source([=[ function DoRecordWin(...) wincmd k @@ -59,7 +59,7 @@ describe('wordcount', function() ) -- Test 2: some words, cursor at start - execute([[call PutInWindow('one two three')]]) + command([[call PutInWindow('one two three')]]) eq(eval('DoRecordWin([1, 1, 0])'), eval([=[ [['', 'one two three'], {'chars': 15, 'cursor_chars': 1, 'words': 3, 'cursor_words': 0, 'bytes': 15, 'cursor_bytes': 1}] @@ -67,7 +67,7 @@ describe('wordcount', function() ) -- Test 3: some words, cursor at end - execute([[call PutInWindow('one two three')]]) + command([[call PutInWindow('one two three')]]) eq(eval('DoRecordWin([2, 99, 0])'), eval([=[ [['', 'one two three'], {'chars': 15, 'cursor_chars': 14, 'words': 3, 'cursor_words': 3, 'bytes': 15, 'cursor_bytes': 14}] @@ -75,17 +75,17 @@ describe('wordcount', function() ) -- Test 4: some words, cursor at end, ve=all - execute('set ve=all') - execute([[call PutInWindow('one two three')]]) + command('set ve=all') + command([[call PutInWindow('one two three')]]) eq(eval('DoRecordWin([2,99,0])'), eval([=[ [['', 'one two three'], {'chars': 15, 'cursor_chars': 15, 'words': 3, 'cursor_words': 3, 'bytes': 15, 'cursor_bytes': 15}] ]=]) ) - execute('set ve=') + command('set ve=') -- Test 5: several lines with words - execute([=[call PutInWindow(['one two three', 'one two three', 'one two three'])]=]) + command([=[call PutInWindow(['one two three', 'one two three', 'one two three'])]=]) eq(eval('DoRecordWin([4,99,0])'), eval([=[ [['', 'one two three', 'one two three', 'one two three'], {'chars': 43, 'cursor_chars': 42, 'words': 9, 'cursor_words': 9, 'bytes': 43, 'cursor_bytes': 42}] @@ -93,21 +93,21 @@ describe('wordcount', function() ) -- Test 6: one line with BOM set - execute([[call PutInWindow('one two three')]]) - execute('wincmd k') - execute('set bomb') - execute('wincmd j') + command([[call PutInWindow('one two three')]]) + command('wincmd k') + command('set bomb') + command('wincmd j') eq(eval('DoRecordWin([2,99,0])'), eval([=[ [['', 'one two three'], {'chars': 15, 'cursor_chars': 14, 'words': 3, 'cursor_words': 3, 'bytes': 18, 'cursor_bytes': 14}] ]=]) ) - execute('wincmd k') - execute('set nobomb') - execute('wincmd j') + command('wincmd k') + command('set nobomb') + command('wincmd j') -- Test 7: one line with multibyte words - execute([=[call PutInWindow(['รne Mยคne Mรผh'])]=]) + command([=[call PutInWindow(['รne Mยคne Mรผh'])]=]) eq(eval('DoRecordWin([2,99,0])'), eval([=[ [['', 'รne Mยคne Mรผh'], {'chars': 14, 'cursor_chars': 13, 'words': 3, 'cursor_words': 3, 'bytes': 17, 'cursor_bytes': 16}] @@ -115,7 +115,7 @@ describe('wordcount', function() ) -- Test 8: several lines with multibyte words - execute([=[call PutInWindow(['รne Mยคne Mรผh', 'und raus bist dรผ!'])]=]) + command([=[call PutInWindow(['รne Mยคne Mรผh', 'und raus bist dรผ!'])]=]) eq(eval('DoRecordWin([3,99,0])'), eval([=[ [['', 'รne Mยคne Mรผh', 'und raus bist dรผ!'], {'chars': 32, 'cursor_chars': 31, 'words': 7, 'cursor_words': 7, 'bytes': 36, 'cursor_bytes': 35}] @@ -123,15 +123,16 @@ describe('wordcount', function() ) -- Test 9: visual mode, complete buffer - execute([=[call PutInWindow(['รne Mยคne Mรผh', 'und raus bist dรผ!'])]=]) - execute('wincmd k') - execute('set ls=2 stl=%{STL()}') + command([=[call PutInWindow(['รne Mยคne Mรผh', 'und raus bist dรผ!'])]=]) + command('wincmd k') + command('set ls=2 stl=%{STL()}') -- -- Start visual mode quickly and select complete buffer. - execute('0') + command('0') feed('V2jy<cr>') - execute('set stl= ls=1') - execute('let log=DoRecordWin([3,99,0])') - execute('let log[1]=g:visual_stat') + wait() + command('set stl= ls=1') + command('let log=DoRecordWin([3,99,0])') + command('let log[1]=g:visual_stat') eq(eval('log'), eval([=[ [['', 'รne Mยคne Mรผh', 'und raus bist dรผ!'], {'chars': 32, 'words': 7, 'bytes': 36, 'visual_chars': 32, 'visual_words': 7, 'visual_bytes': 36}] @@ -139,15 +140,16 @@ describe('wordcount', function() ) -- Test 10: visual mode (empty) - execute([=[call PutInWindow(['รne Mยคne Mรผh', 'und raus bist dรผ!'])]=]) - execute('wincmd k') - execute('set ls=2 stl=%{STL()}') + command([=[call PutInWindow(['รne Mยคne Mรผh', 'und raus bist dรผ!'])]=]) + command('wincmd k') + command('set ls=2 stl=%{STL()}') -- Start visual mode quickly and select complete buffer. - execute('0') + command('0') feed('v$y<cr>') - execute('set stl= ls=1') - execute('let log=DoRecordWin([3,99,0])') - execute('let log[1]=g:visual_stat') + wait() + command('set stl= ls=1') + command('let log=DoRecordWin([3,99,0])') + command('let log[1]=g:visual_stat') eq(eval('log'), eval([=[ [['', 'รne Mยคne Mรผh', 'und raus bist dรผ!'], {'chars': 32, 'words': 7, 'bytes': 36, 'visual_chars': 1, 'visual_words': 0, 'visual_bytes': 1}] @@ -155,15 +157,16 @@ describe('wordcount', function() ) -- Test 11: visual mode, single line - execute([=[call PutInWindow(['รne Mยคne Mรผh', 'und raus bist dรผ!'])]=]) - execute('wincmd k') - execute('set ls=2 stl=%{STL()}') + command([=[call PutInWindow(['รne Mยคne Mรผh', 'und raus bist dรผ!'])]=]) + command('wincmd k') + command('set ls=2 stl=%{STL()}') -- Start visual mode quickly and select complete buffer. - execute('2') + command('2') feed('0v$y<cr>') - execute('set stl= ls=1') - execute('let log=DoRecordWin([3,99,0])') - execute('let log[1]=g:visual_stat') + wait() + command('set stl= ls=1') + command('let log=DoRecordWin([3,99,0])') + command('let log[1]=g:visual_stat') eq(eval('log'), eval([=[ [['', 'รne Mยคne Mรผh', 'und raus bist dรผ!'], {'chars': 32, 'words': 7, 'bytes': 36, 'visual_chars': 13, 'visual_words': 3, 'visual_bytes': 16}] diff --git a/test/functional/legacy/writefile_spec.lua b/test/functional/legacy/writefile_spec.lua index 765d373b82..4d54e07d6a 100644 --- a/test/functional/legacy/writefile_spec.lua +++ b/test/functional/legacy/writefile_spec.lua @@ -1,23 +1,23 @@ -- Tests for writefile() local helpers = require('test.functional.helpers')(after_each) -local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect +local clear, command, expect = helpers.clear, helpers.command, helpers.expect describe('writefile', function() setup(clear) it('is working', function() - execute('%delete _') - execute('let f = tempname()') - execute('call writefile(["over","written"], f, "b")') - execute('call writefile(["hello","world"], f, "b")') - execute('call writefile(["!", "good"], f, "a")') - execute('call writefile(["morning"], f, "ab")') - execute('call writefile(["", "vimmers"], f, "ab")') - execute('bwipeout!') - execute('$put =readfile(f)') - execute('1 delete _') - execute('call delete(f)') + command('%delete _') + command('let f = tempname()') + command('call writefile(["over","written"], f, "b")') + command('call writefile(["hello","world"], f, "b")') + command('call writefile(["!", "good"], f, "a")') + command('call writefile(["morning"], f, "ab")') + command('call writefile(["", "vimmers"], f, "ab")') + command('bwipeout!') + command('$put =readfile(f)') + command('1 delete _') + command('call delete(f)') -- Assert buffer contents. expect([[ diff --git a/test/functional/lua/api_spec.lua b/test/functional/lua/api_spec.lua new file mode 100644 index 0000000000..b1dc5c07fd --- /dev/null +++ b/test/functional/lua/api_spec.lua @@ -0,0 +1,204 @@ +-- Test suite for testing interactions with API bindings +local helpers = require('test.functional.helpers')(after_each) + +local exc_exec = helpers.exc_exec +local funcs = helpers.funcs +local clear = helpers.clear +local eval = helpers.eval +local NIL = helpers.NIL +local eq = helpers.eq + +before_each(clear) + +describe('luaeval(vim.api.โฆ)', function() + describe('with channel_id and buffer handle', function() + describe('nvim_buf_get_lines', function() + it('works', function() + funcs.setline(1, {"abc", "def", "a\nb", "ttt"}) + eq({{_TYPE={}, _VAL={'a\nb'}}}, + funcs.luaeval('vim.api.nvim_buf_get_lines(1, 2, 3, false)')) + end) + end) + describe('nvim_buf_set_lines', function() + it('works', function() + funcs.setline(1, {"abc", "def", "a\nb", "ttt"}) + eq(NIL, funcs.luaeval('vim.api.nvim_buf_set_lines(1, 1, 2, false, {"b\\0a"})')) + eq({'abc', {_TYPE={}, _VAL={'b\na'}}, {_TYPE={}, _VAL={'a\nb'}}, 'ttt'}, + funcs.luaeval('vim.api.nvim_buf_get_lines(1, 0, 4, false)')) + end) + end) + end) + describe('with errors', function() + it('transforms API error from nvim_buf_set_lines into lua error', function() + funcs.setline(1, {"abc", "def", "a\nb", "ttt"}) + eq({false, 'String cannot contain newlines'}, + funcs.luaeval('{pcall(vim.api.nvim_buf_set_lines, 1, 1, 2, false, {"b\\na"})}')) + end) + + it('transforms API error from nvim_win_set_cursor into lua error', function() + eq({false, 'Argument "pos" must be a [row, col] array'}, + funcs.luaeval('{pcall(vim.api.nvim_win_set_cursor, 0, {1, 2, 3})}')) + -- Used to produce a memory leak due to a bug in nvim_win_set_cursor + eq({false, 'Invalid window id'}, + funcs.luaeval('{pcall(vim.api.nvim_win_set_cursor, -1, {1, 2, 3})}')) + end) + + it('transforms API error from nvim_win_set_cursor + same array as in first test into lua error', + function() + eq({false, 'Argument "pos" must be a [row, col] array'}, + funcs.luaeval('{pcall(vim.api.nvim_win_set_cursor, 0, {"b\\na"})}')) + end) + end) + + it('correctly evaluates API code which calls luaeval', function() + local str = (([===[vim.api.nvim_eval([==[ + luaeval('vim.api.nvim_eval([=[ + luaeval("vim.api.nvim_eval([[ + luaeval(1) + ]])") + ]=])') + ]==])]===]):gsub('\n', ' ')) + eq(1, funcs.luaeval(str)) + end) + + it('correctly converts from API objects', function() + eq(1, funcs.luaeval('vim.api.nvim_eval("1")')) + eq('1', funcs.luaeval([[vim.api.nvim_eval('"1"')]])) + eq({}, funcs.luaeval('vim.api.nvim_eval("[]")')) + eq({}, funcs.luaeval('vim.api.nvim_eval("{}")')) + eq(1, funcs.luaeval('vim.api.nvim_eval("1.0")')) + eq(true, funcs.luaeval('vim.api.nvim_eval("v:true")')) + eq(false, funcs.luaeval('vim.api.nvim_eval("v:false")')) + eq(NIL, funcs.luaeval('vim.api.nvim_eval("v:null")')) + + eq(0, eval([[type(luaeval('vim.api.nvim_eval("1")'))]])) + eq(1, eval([[type(luaeval('vim.api.nvim_eval("''1''")'))]])) + eq(3, eval([[type(luaeval('vim.api.nvim_eval("[]")'))]])) + eq(4, eval([[type(luaeval('vim.api.nvim_eval("{}")'))]])) + eq(5, eval([[type(luaeval('vim.api.nvim_eval("1.0")'))]])) + eq(6, eval([[type(luaeval('vim.api.nvim_eval("v:true")'))]])) + eq(6, eval([[type(luaeval('vim.api.nvim_eval("v:false")'))]])) + eq(7, eval([[type(luaeval('vim.api.nvim_eval("v:null")'))]])) + + eq({foo=42}, funcs.luaeval([[vim.api.nvim_eval('{"foo": 42}')]])) + eq({42}, funcs.luaeval([[vim.api.nvim_eval('[42]')]])) + + eq({foo={bar=42}, baz=50}, funcs.luaeval([[vim.api.nvim_eval('{"foo": {"bar": 42}, "baz": 50}')]])) + eq({{42}, {}}, funcs.luaeval([=[vim.api.nvim_eval('[[42], []]')]=])) + end) + + it('correctly converts to API objects', function() + eq(1, funcs.luaeval('vim.api.nvim__id(1)')) + eq('1', funcs.luaeval('vim.api.nvim__id("1")')) + eq({1}, funcs.luaeval('vim.api.nvim__id({1})')) + eq({foo=1}, funcs.luaeval('vim.api.nvim__id({foo=1})')) + eq(1.5, funcs.luaeval('vim.api.nvim__id(1.5)')) + eq(true, funcs.luaeval('vim.api.nvim__id(true)')) + eq(false, funcs.luaeval('vim.api.nvim__id(false)')) + eq(NIL, funcs.luaeval('vim.api.nvim__id(nil)')) + + eq(0, eval([[type(luaeval('vim.api.nvim__id(1)'))]])) + eq(1, eval([[type(luaeval('vim.api.nvim__id("1")'))]])) + eq(3, eval([[type(luaeval('vim.api.nvim__id({1})'))]])) + eq(4, eval([[type(luaeval('vim.api.nvim__id({foo=1})'))]])) + eq(5, eval([[type(luaeval('vim.api.nvim__id(1.5)'))]])) + eq(6, eval([[type(luaeval('vim.api.nvim__id(true)'))]])) + eq(6, eval([[type(luaeval('vim.api.nvim__id(false)'))]])) + eq(7, eval([[type(luaeval('vim.api.nvim__id(nil)'))]])) + + eq({foo=1, bar={42, {{baz=true}, 5}}}, funcs.luaeval('vim.api.nvim__id({foo=1, bar={42, {{baz=true}, 5}}})')) + end) + + it('correctly converts container objects with type_idx to API objects', function() + eq(5, eval('type(luaeval("vim.api.nvim__id({[vim.type_idx]=vim.types.float, [vim.val_idx]=0})"))')) + eq(4, eval([[type(luaeval('vim.api.nvim__id({[vim.type_idx]=vim.types.dictionary})'))]])) + eq(3, eval([[type(luaeval('vim.api.nvim__id({[vim.type_idx]=vim.types.array})'))]])) + + eq({}, funcs.luaeval('vim.api.nvim__id({[vim.type_idx]=vim.types.array})')) + + -- Presence of type_idx makes Vim ignore some keys + eq({42}, funcs.luaeval('vim.api.nvim__id({[vim.type_idx]=vim.types.array, [vim.val_idx]=10, [5]=1, foo=2, [1]=42})')) + eq({foo=2}, funcs.luaeval('vim.api.nvim__id({[vim.type_idx]=vim.types.dictionary, [vim.val_idx]=10, [5]=1, foo=2, [1]=42})')) + eq(10, funcs.luaeval('vim.api.nvim__id({[vim.type_idx]=vim.types.float, [vim.val_idx]=10, [5]=1, foo=2, [1]=42})')) + eq({}, funcs.luaeval('vim.api.nvim__id({[vim.type_idx]=vim.types.array, [vim.val_idx]=10, [5]=1, foo=2})')) + end) + + it('correctly converts arrays with type_idx to API objects', function() + eq(3, eval([[type(luaeval('vim.api.nvim__id_array({[vim.type_idx]=vim.types.array})'))]])) + + eq({}, funcs.luaeval('vim.api.nvim__id_array({[vim.type_idx]=vim.types.array})')) + + eq({42}, funcs.luaeval('vim.api.nvim__id_array({[vim.type_idx]=vim.types.array, [vim.val_idx]=10, [5]=1, foo=2, [1]=42})')) + eq({{foo=2}}, funcs.luaeval('vim.api.nvim__id_array({{[vim.type_idx]=vim.types.dictionary, [vim.val_idx]=10, [5]=1, foo=2, [1]=42}})')) + eq({10}, funcs.luaeval('vim.api.nvim__id_array({{[vim.type_idx]=vim.types.float, [vim.val_idx]=10, [5]=1, foo=2, [1]=42}})')) + eq({}, funcs.luaeval('vim.api.nvim__id_array({[vim.type_idx]=vim.types.array, [vim.val_idx]=10, [5]=1, foo=2})')) + + eq({}, funcs.luaeval('vim.api.nvim__id_array({})')) + eq(3, eval([[type(luaeval('vim.api.nvim__id_array({})'))]])) + end) + + it('correctly converts dictionaries with type_idx to API objects', function() + eq(4, eval([[type(luaeval('vim.api.nvim__id_dictionary({[vim.type_idx]=vim.types.dictionary})'))]])) + + eq({}, funcs.luaeval('vim.api.nvim__id_dictionary({[vim.type_idx]=vim.types.dictionary})')) + + eq({v={42}}, funcs.luaeval('vim.api.nvim__id_dictionary({v={[vim.type_idx]=vim.types.array, [vim.val_idx]=10, [5]=1, foo=2, [1]=42}})')) + eq({foo=2}, funcs.luaeval('vim.api.nvim__id_dictionary({[vim.type_idx]=vim.types.dictionary, [vim.val_idx]=10, [5]=1, foo=2, [1]=42})')) + eq({v=10}, funcs.luaeval('vim.api.nvim__id_dictionary({v={[vim.type_idx]=vim.types.float, [vim.val_idx]=10, [5]=1, foo=2, [1]=42}})')) + eq({v={}}, funcs.luaeval('vim.api.nvim__id_dictionary({v={[vim.type_idx]=vim.types.array, [vim.val_idx]=10, [5]=1, foo=2}})')) + + -- If API requests dictionary, then empty table will be the one. This is not + -- the case normally because empty table is an empty arrray. + eq({}, funcs.luaeval('vim.api.nvim__id_dictionary({})')) + eq(4, eval([[type(luaeval('vim.api.nvim__id_dictionary({})'))]])) + end) + + it('errors out correctly when working with API', function() + -- Conversion errors + eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): [string "<VimL compiled string>"]:1: Cannot convert given lua type', + exc_exec([[call luaeval("vim.api.nvim__id(vim.api.nvim__id)")]])) + eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): [string "<VimL compiled string>"]:1: Cannot convert given lua table', + exc_exec([[call luaeval("vim.api.nvim__id({1, foo=42})")]])) + eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): [string "<VimL compiled string>"]:1: Cannot convert given lua type', + exc_exec([[call luaeval("vim.api.nvim__id({42, vim.api.nvim__id})")]])) + -- Errors in number of arguments + eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): [string "<VimL compiled string>"]:1: Expected 1 argument', + exc_exec([[call luaeval("vim.api.nvim__id()")]])) + eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): [string "<VimL compiled string>"]:1: Expected 1 argument', + exc_exec([[call luaeval("vim.api.nvim__id(1, 2)")]])) + eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): [string "<VimL compiled string>"]:1: Expected 2 arguments', + exc_exec([[call luaeval("vim.api.nvim_set_var(1, 2, 3)")]])) + -- Error in argument types + eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): [string "<VimL compiled string>"]:1: Expected lua string', + exc_exec([[call luaeval("vim.api.nvim_set_var(1, 2)")]])) + + eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): [string "<VimL compiled string>"]:1: Expected lua number', + exc_exec([[call luaeval("vim.api.nvim_buf_get_lines(0, 'test', 1, false)")]])) + eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): [string "<VimL compiled string>"]:1: Number is not integral', + exc_exec([[call luaeval("vim.api.nvim_buf_get_lines(0, 1.5, 1, false)")]])) + + eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): [string "<VimL compiled string>"]:1: Expected lua table', + exc_exec([[call luaeval("vim.api.nvim__id_float('test')")]])) + eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): [string "<VimL compiled string>"]:1: Unexpected type', + exc_exec([[call luaeval("vim.api.nvim__id_float({[vim.type_idx]=vim.types.dictionary})")]])) + + eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): [string "<VimL compiled string>"]:1: Expected lua table', + exc_exec([[call luaeval("vim.api.nvim__id_array(1)")]])) + eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): [string "<VimL compiled string>"]:1: Unexpected type', + exc_exec([[call luaeval("vim.api.nvim__id_array({[vim.type_idx]=vim.types.dictionary})")]])) + + eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): [string "<VimL compiled string>"]:1: Expected lua table', + exc_exec([[call luaeval("vim.api.nvim__id_dictionary(1)")]])) + eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): [string "<VimL compiled string>"]:1: Unexpected type', + exc_exec([[call luaeval("vim.api.nvim__id_dictionary({[vim.type_idx]=vim.types.array})")]])) + -- TODO: check for errors with Tabpage argument + -- TODO: check for errors with Window argument + -- TODO: check for errors with Buffer argument + end) + + it('accepts any value as API Boolean', function() + eq('', funcs.luaeval('vim.api.nvim_replace_termcodes("", vim, false, nil)')) + eq('', funcs.luaeval('vim.api.nvim_replace_termcodes("", 0, 1.5, "test")')) + eq('', funcs.luaeval('vim.api.nvim_replace_termcodes("", true, {}, {[vim.type_idx]=vim.types.array})')) + end) +end) diff --git a/test/functional/lua/commands_spec.lua b/test/functional/lua/commands_spec.lua new file mode 100644 index 0000000000..017ee55729 --- /dev/null +++ b/test/functional/lua/commands_spec.lua @@ -0,0 +1,164 @@ +-- Test suite for checking :lua* commands +local helpers = require('test.functional.helpers')(after_each) + +local eq = helpers.eq +local NIL = helpers.NIL +local clear = helpers.clear +local meths = helpers.meths +local funcs = helpers.funcs +local source = helpers.source +local dedent = helpers.dedent +local exc_exec = helpers.exc_exec +local write_file = helpers.write_file +local redir_exec = helpers.redir_exec +local curbufmeths = helpers.curbufmeths + +before_each(clear) + +describe(':lua command', function() + it('works', function() + eq('', redir_exec( + 'lua vim.api.nvim_buf_set_lines(1, 1, 2, false, {"TEST"})')) + eq({'', 'TEST'}, curbufmeths.get_lines(0, 100, false)) + source(dedent([[ + lua << EOF + vim.api.nvim_buf_set_lines(1, 1, 2, false, {"TSET"}) + EOF]])) + eq({'', 'TSET'}, curbufmeths.get_lines(0, 100, false)) + source(dedent([[ + lua << EOF + vim.api.nvim_buf_set_lines(1, 1, 2, false, {"SETT"})]])) + eq({'', 'SETT'}, curbufmeths.get_lines(0, 100, false)) + source(dedent([[ + lua << EOF + vim.api.nvim_buf_set_lines(1, 1, 2, false, {"ETTS"}) + vim.api.nvim_buf_set_lines(1, 2, 3, false, {"TTSE"}) + vim.api.nvim_buf_set_lines(1, 3, 4, false, {"STTE"}) + EOF]])) + eq({'', 'ETTS', 'TTSE', 'STTE'}, curbufmeths.get_lines(0, 100, false)) + end) + it('throws catchable errors', function() + eq([[Vim(lua):E5104: Error while creating lua chunk: [string "<VimL compiled string>"]:1: unexpected symbol near ')']], + exc_exec('lua ()')) + eq([[Vim(lua):E5105: Error while calling lua chunk: [string "<VimL compiled string>"]:1: TEST]], + exc_exec('lua error("TEST")')) + eq([[Vim(lua):E5105: Error while calling lua chunk: [string "<VimL compiled string>"]:1: Invalid buffer id]], + exc_exec('lua vim.api.nvim_buf_set_lines(-10, 1, 1, false, {"TEST"})')) + eq({''}, curbufmeths.get_lines(0, 100, false)) + end) + it('works with NULL errors', function() + eq([=[Vim(lua):E5105: Error while calling lua chunk: [NULL]]=], + exc_exec('lua error(nil)')) + end) + it('accepts embedded NLs without heredoc', function() + -- Such code is usually used for `:execute 'lua' {generated_string}`: + -- heredocs do not work in this case. + meths.command([[ + lua + vim.api.nvim_buf_set_lines(1, 1, 2, false, {"ETTS"}) + vim.api.nvim_buf_set_lines(1, 2, 3, false, {"TTSE"}) + vim.api.nvim_buf_set_lines(1, 3, 4, false, {"STTE"}) + ]]) + eq({'', 'ETTS', 'TTSE', 'STTE'}, curbufmeths.get_lines(0, 100, false)) + end) + it('preserves global and not preserves local variables', function() + eq('', redir_exec('lua gvar = 42')) + eq('', redir_exec('lua local lvar = 100500')) + eq(NIL, funcs.luaeval('lvar')) + eq(42, funcs.luaeval('gvar')) + end) + it('works with long strings', function() + local s = ('x'):rep(100500) + + eq('\nE5104: Error while creating lua chunk: [string "<VimL compiled string>"]:1: unfinished string near \'<eof>\'', redir_exec(('lua vim.api.nvim_buf_set_lines(1, 1, 2, false, {"%s})'):format(s))) + eq({''}, curbufmeths.get_lines(0, -1, false)) + + eq('', redir_exec(('lua vim.api.nvim_buf_set_lines(1, 1, 2, false, {"%s"})'):format(s))) + eq({'', s}, curbufmeths.get_lines(0, -1, false)) + end) +end) + +describe(':luado command', function() + it('works', function() + curbufmeths.set_lines(0, 1, false, {"ABC", "def", "gHi"}) + eq('', redir_exec('luado lines = (lines or {}) lines[#lines + 1] = {linenr, line}')) + eq({'ABC', 'def', 'gHi'}, curbufmeths.get_lines(0, -1, false)) + eq({{1, 'ABC'}, {2, 'def'}, {3, 'gHi'}}, funcs.luaeval('lines')) + + -- Automatic transformation of numbers + eq('', redir_exec('luado return linenr')) + eq({'1', '2', '3'}, curbufmeths.get_lines(0, -1, false)) + + eq('', redir_exec('luado return ("<%02x>"):format(line:byte())')) + eq({'<31>', '<32>', '<33>'}, curbufmeths.get_lines(0, -1, false)) + end) + it('stops processing lines when suddenly out of lines', function() + curbufmeths.set_lines(0, 1, false, {"ABC", "def", "gHi"}) + eq('', redir_exec('2,$luado runs = ((runs or 0) + 1) vim.api.nvim_command("%d")')) + eq({''}, curbufmeths.get_lines(0, -1, false)) + eq(1, funcs.luaeval('runs')) + end) + it('works correctly when changing lines out of range', function() + curbufmeths.set_lines(0, 1, false, {"ABC", "def", "gHi"}) + eq('\nE322: line number out of range: 1 past the end\nE320: Cannot find line 2', + redir_exec('2,$luado vim.api.nvim_command("%d") return linenr')) + eq({''}, curbufmeths.get_lines(0, -1, false)) + end) + it('fails on errors', function() + eq([[Vim(luado):E5109: Error while creating lua chunk: [string "<VimL compiled string>"]:1: unexpected symbol near ')']], + exc_exec('luado ()')) + eq([[Vim(luado):E5111: Error while calling lua function: [string "<VimL compiled string>"]:1: attempt to perform arithmetic on global 'liness' (a nil value)]], + exc_exec('luado return liness + 1')) + end) + it('works with NULL errors', function() + eq([=[Vim(luado):E5111: Error while calling lua function: [NULL]]=], + exc_exec('luado error(nil)')) + end) + it('fails in sandbox when needed', function() + curbufmeths.set_lines(0, 1, false, {"ABC", "def", "gHi"}) + eq('\nE48: Not allowed in sandbox: sandbox luado runs = (runs or 0) + 1', + redir_exec('sandbox luado runs = (runs or 0) + 1')) + eq(NIL, funcs.luaeval('runs')) + end) + it('works with long strings', function() + local s = ('x'):rep(100500) + + eq('\nE5109: Error while creating lua chunk: [string "<VimL compiled string>"]:1: unfinished string near \'<eof>\'', redir_exec(('luado return "%s'):format(s))) + eq({''}, curbufmeths.get_lines(0, -1, false)) + + eq('', redir_exec(('luado return "%s"'):format(s))) + eq({s}, curbufmeths.get_lines(0, -1, false)) + end) +end) + +describe(':luafile', function() + local fname = 'Xtest-functional-lua-commands-luafile' + + after_each(function() + os.remove(fname) + end) + + it('works', function() + write_file(fname, [[ + vim.api.nvim_buf_set_lines(1, 1, 2, false, {"ETTS"}) + vim.api.nvim_buf_set_lines(1, 2, 3, false, {"TTSE"}) + vim.api.nvim_buf_set_lines(1, 3, 4, false, {"STTE"}) + ]]) + eq('', redir_exec('luafile ' .. fname)) + eq({'', 'ETTS', 'TTSE', 'STTE'}, curbufmeths.get_lines(0, 100, false)) + end) + + it('correctly errors out', function() + write_file(fname, '()') + eq(("Vim(luafile):E5112: Error while creating lua chunk: %s:1: unexpected symbol near ')'"):format(fname), + exc_exec('luafile ' .. fname)) + write_file(fname, 'vimm.api.nvim_buf_set_lines(1, 1, 2, false, {"ETTS"})') + eq(("Vim(luafile):E5113: Error while calling lua chunk: %s:1: attempt to index global 'vimm' (a nil value)"):format(fname), + exc_exec('luafile ' .. fname)) + end) + it('works with NULL errors', function() + write_file(fname, 'error(nil)') + eq([=[Vim(luafile):E5113: Error while calling lua chunk: [NULL]]=], + exc_exec('luafile ' .. fname)) + end) +end) diff --git a/test/functional/lua/luaeval_spec.lua b/test/functional/lua/luaeval_spec.lua new file mode 100644 index 0000000000..6da0001cea --- /dev/null +++ b/test/functional/lua/luaeval_spec.lua @@ -0,0 +1,255 @@ +-- Test suite for testing luaeval() function +local helpers = require('test.functional.helpers')(after_each) + +local redir_exec = helpers.redir_exec +local exc_exec = helpers.exc_exec +local command = helpers.command +local meths = helpers.meths +local funcs = helpers.funcs +local clear = helpers.clear +local eval = helpers.eval +local NIL = helpers.NIL +local eq = helpers.eq + +before_each(clear) + +local function startswith(expected, actual) + eq(expected, actual:sub(1, #expected)) +end + +describe('luaeval()', function() + local nested_by_level = {} + local nested = {} + local nested_s = '{}' + for i=1,100 do + if i % 2 == 0 then + nested = {nested} + nested_s = '{' .. nested_s .. '}' + else + nested = {nested=nested} + nested_s = '{nested=' .. nested_s .. '}' + end + nested_by_level[i] = {o=nested, s=nested_s} + end + + describe('second argument', function() + it('is successfully received', function() + local t = {t=true, f=false, --[[n=NIL,]] d={l={'string', 42, 0.42}}} + eq(t, funcs.luaeval("_A", t)) + -- Not tested: nil, funcrefs, returned object identity: behaviour will + -- most likely change. + end) + end) + describe('lua values', function() + it('are successfully transformed', function() + eq({n=1, f=1.5, s='string', l={4, 2}}, + funcs.luaeval('{n=1, f=1.5, s="string", l={4, 2}}')) + -- Not tested: nil inside containers: behaviour will most likely change. + eq(NIL, funcs.luaeval('nil')) + eq({['']=1}, funcs.luaeval('{[""]=1}')) + end) + end) + describe('recursive lua values', function() + it('are successfully transformed', function() + funcs.luaeval('rawset(_G, "d", {})') + funcs.luaeval('rawset(d, "d", d)') + eq('\n{\'d\': {...@0}}', funcs.execute('echo luaeval("d")')) + + funcs.luaeval('rawset(_G, "l", {})') + funcs.luaeval('table.insert(l, l)') + eq('\n[[...@0]]', funcs.execute('echo luaeval("l")')) + end) + end) + describe('strings', function() + it('are successfully converted to special dictionaries', function() + command([[let s = luaeval('"\0"')]]) + eq({_TYPE={}, _VAL={'\n'}}, meths.get_var('s')) + eq(1, funcs.eval('s._TYPE is v:msgpack_types.binary')) + end) + it('are successfully converted to special dictionaries in table keys', + function() + command([[let d = luaeval('{["\0"]=1}')]]) + eq({_TYPE={}, _VAL={{{_TYPE={}, _VAL={'\n'}}, 1}}}, meths.get_var('d')) + eq(1, funcs.eval('d._TYPE is v:msgpack_types.map')) + eq(1, funcs.eval('d._VAL[0][0]._TYPE is v:msgpack_types.string')) + end) + it('are successfully converted to special dictionaries from a list', + function() + command([[let l = luaeval('{"abc", "a\0b", "c\0d", "def"}')]]) + eq({'abc', {_TYPE={}, _VAL={'a\nb'}}, {_TYPE={}, _VAL={'c\nd'}}, 'def'}, + meths.get_var('l')) + eq(1, funcs.eval('l[1]._TYPE is v:msgpack_types.binary')) + eq(1, funcs.eval('l[2]._TYPE is v:msgpack_types.binary')) + end) + end) + + -- Not checked: funcrefs converted to NIL. To be altered to something more + -- meaningful later. + + it('correctly evaluates scalars', function() + eq(1, funcs.luaeval('1')) + eq(0, eval('type(luaeval("1"))')) + + eq(1.5, funcs.luaeval('1.5')) + eq(5, eval('type(luaeval("1.5"))')) + + eq("test", funcs.luaeval('"test"')) + eq(1, eval('type(luaeval("\'test\'"))')) + + eq('', funcs.luaeval('""')) + eq({_TYPE={}, _VAL={'\n'}}, funcs.luaeval([['\0']])) + eq({_TYPE={}, _VAL={'\n', '\n'}}, funcs.luaeval([['\0\n\0']])) + eq(1, eval([[luaeval('"\0\n\0"')._TYPE is v:msgpack_types.binary]])) + + eq(true, funcs.luaeval('true')) + eq(false, funcs.luaeval('false')) + eq(NIL, funcs.luaeval('nil')) + end) + + it('correctly evaluates containers', function() + eq({}, funcs.luaeval('{}')) + eq(3, eval('type(luaeval("{}"))')) + + eq({test=1, foo=2}, funcs.luaeval('{test=1, foo=2}')) + eq(4, eval('type(luaeval("{test=1, foo=2}"))')) + + eq({4, 2}, funcs.luaeval('{4, 2}')) + eq(3, eval('type(luaeval("{4, 2}"))')) + + local level = 30 + eq(nested_by_level[level].o, funcs.luaeval(nested_by_level[level].s)) + + eq({_TYPE={}, _VAL={{{_TYPE={}, _VAL={'\n', '\n'}}, {_TYPE={}, _VAL={'\n', '\n\n'}}}}}, + funcs.luaeval([[{['\0\n\0']='\0\n\0\0'}]])) + eq(1, eval([[luaeval('{["\0\n\0"]="\0\n\0\0"}')._TYPE is v:msgpack_types.map]])) + eq(1, eval([[luaeval('{["\0\n\0"]="\0\n\0\0"}')._VAL[0][0]._TYPE is v:msgpack_types.string]])) + eq(1, eval([[luaeval('{["\0\n\0"]="\0\n\0\0"}')._VAL[0][1]._TYPE is v:msgpack_types.binary]])) + eq({nested={{_TYPE={}, _VAL={{{_TYPE={}, _VAL={'\n', '\n'}}, {_TYPE={}, _VAL={'\n', '\n\n'}}}}}}}, + funcs.luaeval([[{nested={{['\0\n\0']='\0\n\0\0'}}}]])) + end) + + it('correctly passes scalars as argument', function() + eq(1, funcs.luaeval('_A', 1)) + eq(1.5, funcs.luaeval('_A', 1.5)) + eq('', funcs.luaeval('_A', '')) + eq('test', funcs.luaeval('_A', 'test')) + eq(NIL, funcs.luaeval('_A', NIL)) + eq(true, funcs.luaeval('_A', true)) + eq(false, funcs.luaeval('_A', false)) + end) + + it('correctly passes containers as argument', function() + eq({}, funcs.luaeval('_A', {})) + eq({test=1}, funcs.luaeval('_A', {test=1})) + eq({4, 2}, funcs.luaeval('_A', {4, 2})) + local level = 28 + eq(nested_by_level[level].o, funcs.luaeval('_A', nested_by_level[level].o)) + end) + + local function sp(typ, val) + return ('{"_TYPE": v:msgpack_types.%s, "_VAL": %s}'):format(typ, val) + end + local function mapsp(...) + local val = '' + for i=1,(select('#', ...)/2) do + val = ('%s[%s,%s],'):format(val, select(i * 2 - 1, ...), + select(i * 2, ...)) + end + return sp('map', '[' .. val .. ']') + end + local function luaevalarg(argexpr, expr) + return eval(([=[ + [ + extend(g:, {'_ret': luaeval(%s, %s)})._ret, + type(g:_ret)==type({})&&has_key(g:_ret, '_TYPE') + ? [ + get(keys(filter(copy(v:msgpack_types), 'v:val is g:_ret._TYPE')), 0, + g:_ret._TYPE), + get(g:_ret, '_VAL', g:_ret) + ] + : [0, g:_ret]][1] + ]=]):format(expr or '"_A"', argexpr):gsub('\n', '')) + end + + it('correctly passes special dictionaries', function() + eq({'binary', {'\n', '\n'}}, luaevalarg(sp('binary', '["\\n", "\\n"]'))) + eq({'binary', {'\n', '\n'}}, luaevalarg(sp('string', '["\\n", "\\n"]'))) + eq({0, true}, luaevalarg(sp('boolean', 1))) + eq({0, false}, luaevalarg(sp('boolean', 0))) + eq({0, NIL}, luaevalarg(sp('nil', 0))) + eq({0, {[""]=""}}, luaevalarg(mapsp(sp('binary', '[""]'), '""'))) + eq({0, {[""]=""}}, luaevalarg(mapsp(sp('string', '[""]'), '""'))) + end) + + it('issues an error in some cases', function() + eq("Vim(call):E5100: Cannot convert given lua table: table should either have a sequence of positive integer keys or contain only string keys", + exc_exec('call luaeval("{1, foo=2}")')) + eq("Vim(call):E5101: Cannot convert given lua type", + exc_exec('call luaeval("vim.api.nvim_buf_get_lines")')) + startswith("Vim(call):E5107: Error while creating lua chunk for luaeval(): ", + exc_exec('call luaeval("1, 2, 3")')) + startswith("Vim(call):E5108: Error while calling lua chunk for luaeval(): ", + exc_exec('call luaeval("(nil)()")')) + eq("Vim(call):E5101: Cannot convert given lua type", + exc_exec('call luaeval("{42, vim.api}")')) + eq("Vim(call):E5101: Cannot convert given lua type", + exc_exec('call luaeval("{foo=42, baz=vim.api}")')) + + -- The following should not crash: conversion error happens inside + eq("Vim(call):E5101: Cannot convert given lua type", + exc_exec('call luaeval("vim.api")')) + -- The following should not show internal error + eq("\nE5101: Cannot convert given lua type\n0", + redir_exec('echo luaeval("vim.api")')) + end) + + it('correctly converts containers with type_idx', function() + eq(5, eval('type(luaeval("{[vim.type_idx]=vim.types.float, [vim.val_idx]=0}"))')) + eq(4, eval([[type(luaeval('{[vim.type_idx]=vim.types.dictionary}'))]])) + eq(3, eval([[type(luaeval('{[vim.type_idx]=vim.types.array}'))]])) + + eq({}, funcs.luaeval('{[vim.type_idx]=vim.types.array}')) + + -- Presence of type_idx makes Vim ignore some keys + eq({42}, funcs.luaeval('{[vim.type_idx]=vim.types.array, [vim.val_idx]=10, [5]=1, foo=2, [1]=42}')) + eq({foo=2}, funcs.luaeval('{[vim.type_idx]=vim.types.dictionary, [vim.val_idx]=10, [5]=1, foo=2, [1]=42}')) + eq(10, funcs.luaeval('{[vim.type_idx]=vim.types.float, [vim.val_idx]=10, [5]=1, foo=2, [1]=42}')) + + -- The following should not crash + eq({}, funcs.luaeval('{[vim.type_idx]=vim.types.dictionary}')) + end) + + it('correctly converts self-containing containers', function() + meths.set_var('l', {}) + eval('add(l, l)') + eq(true, eval('luaeval("_A == _A[1]", l)')) + eq(true, eval('luaeval("_A[1] == _A[1][1]", [l])')) + eq(true, eval('luaeval("_A.d == _A.d[1]", {"d": l})')) + eq(true, eval('luaeval("_A ~= _A[1]", [l])')) + + meths.set_var('d', {foo=42}) + eval('extend(d, {"d": d})') + eq(true, eval('luaeval("_A == _A.d", d)')) + eq(true, eval('luaeval("_A[1] == _A[1].d", [d])')) + eq(true, eval('luaeval("_A.d == _A.d.d", {"d": d})')) + eq(true, eval('luaeval("_A ~= _A.d", {"d": d})')) + end) + + it('errors out correctly when doing incorrect things in lua', function() + -- Conversion errors + eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): [string "<VimL compiled string>"]:1: attempt to call field \'xxx_nonexistent_key_xxx\' (a nil value)', + exc_exec([[call luaeval("vim.xxx_nonexistent_key_xxx()")]])) + eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): [string "<VimL compiled string>"]:1: ERROR', + exc_exec([[call luaeval("error('ERROR')")]])) + eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): [NULL]', + exc_exec([[call luaeval("error(nil)")]])) + end) + + it('does not leak memory when called with too long line', + function() + local s = ('x'):rep(65536) + eq('Vim(call):E5107: Error while creating lua chunk for luaeval(): [string "<VimL compiled string>"]:1: unexpected symbol near \')\'', + exc_exec([[call luaeval("(']] .. s ..[[' + )")]])) + eq(s, funcs.luaeval('"' .. s .. '"')) + end) +end) diff --git a/test/functional/lua/overrides_spec.lua b/test/functional/lua/overrides_spec.lua new file mode 100644 index 0000000000..8ca5fe57ba --- /dev/null +++ b/test/functional/lua/overrides_spec.lua @@ -0,0 +1,301 @@ +-- Test for Vim overrides of lua built-ins +local helpers = require('test.functional.helpers')(after_each) +local Screen = require('test.functional.ui.screen') + +local eq = helpers.eq +local neq = helpers.neq +local NIL = helpers.NIL +local feed = helpers.feed +local clear = helpers.clear +local funcs = helpers.funcs +local meths = helpers.meths +local iswin = helpers.iswin +local command = helpers.command +local write_file = helpers.write_file +local redir_exec = helpers.redir_exec +local alter_slashes = helpers.alter_slashes + +local screen + +local fname = 'Xtest-functional-lua-overrides-luafile' + +before_each(clear) + +after_each(function() + os.remove(fname) +end) + +describe('print', function() + it('returns nothing', function() + eq(NIL, funcs.luaeval('print("abc")')) + eq(0, funcs.luaeval('select("#", print("abc"))')) + end) + it('allows catching printed text with :execute', function() + eq('\nabc', funcs.execute('lua print("abc")')) + eq('\nabc', funcs.execute('luado print("abc")')) + eq('\nabc', funcs.execute('call luaeval("print(\'abc\')")')) + write_file(fname, 'print("abc")') + eq('\nabc', funcs.execute('luafile ' .. fname)) + + eq('\nabc', redir_exec('lua print("abc")')) + eq('\nabc', redir_exec('luado print("abc")')) + eq('\nabc', redir_exec('call luaeval("print(\'abc\')")')) + write_file(fname, 'print("abc")') + eq('\nabc', redir_exec('luafile ' .. fname)) + end) + it('handles errors in __tostring', function() + write_file(fname, [[ + local meta_nilerr = { __tostring = function() error(nil) end } + local meta_abcerr = { __tostring = function() error("abc") end } + local meta_tblout = { __tostring = function() return {"TEST"} end } + v_nilerr = setmetatable({}, meta_nilerr) + v_abcerr = setmetatable({}, meta_abcerr) + v_tblout = setmetatable({}, meta_tblout) + ]]) + eq('', redir_exec('luafile ' .. fname)) + eq('\nE5114: Error while converting print argument #2: [NULL]', + redir_exec('lua print("foo", v_nilerr, "bar")')) + eq('\nE5114: Error while converting print argument #2: Xtest-functional-lua-overrides-luafile:2: abc', + redir_exec('lua print("foo", v_abcerr, "bar")')) + eq('\nE5114: Error while converting print argument #2: <Unknown error: lua_tolstring returned NULL for tostring result>', + redir_exec('lua print("foo", v_tblout, "bar")')) + end) + it('prints strings with NULs and NLs correctly', function() + meths.set_option('more', true) + eq('\nabc ^@ def\nghi^@^@^@jkl\nTEST\n\n\nT\n', + redir_exec([[lua print("abc \0 def\nghi\0\0\0jkl\nTEST\n\n\nT\n")]])) + eq('\nabc ^@ def\nghi^@^@^@jkl\nTEST\n\n\nT^@', + redir_exec([[lua print("abc \0 def\nghi\0\0\0jkl\nTEST\n\n\nT\0")]])) + eq('\nT^@', redir_exec([[lua print("T\0")]])) + eq('\nT\n', redir_exec([[lua print("T\n")]])) + end) + it('prints empty strings correctly', function() + -- Regression: first test used to crash + eq('', redir_exec('lua print("")')) + eq('\n def', redir_exec('lua print("", "def")')) + eq('\nabc ', redir_exec('lua print("abc", "")')) + eq('\nabc def', redir_exec('lua print("abc", "", "def")')) + end) +end) + +describe('debug.debug', function() + before_each(function() + screen = Screen.new() + screen:attach() + screen:set_default_attr_ids({ + [0] = {bold=true, foreground=255}, + E = {foreground = Screen.colors.Grey100, background = Screen.colors.Red}, + cr = {bold = true, foreground = Screen.colors.SeaGreen4}, + }) + end) + it('works', function() + command([[lua + function Test(a) + print(a) + debug.debug() + print(a * 100) + end + ]]) + feed(':lua Test()\n') + screen:expect([[ + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + nil | + lua_debug> ^ | + ]]) + feed('print("TEST")\n') + screen:expect([[ + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + nil | + lua_debug> print("TEST") | + TEST | + lua_debug> ^ | + ]]) + feed('<C-c>') + screen:expect([[ + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + nil | + lua_debug> print("TEST") | + TEST | + | + {E:E5105: Error while calling lua chunk: [string "<VimL }| + {E:compiled string>"]:5: attempt to perform arithmetic o}| + {E:n local 'a' (a nil value)} | + Interrupt: {cr:Press ENTER or type command to continue}^ | + ]]) + feed('<C-l>:lua Test()\n') + screen:expect([[ + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + nil | + lua_debug> ^ | + ]]) + feed('\n') + screen:expect([[ + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + nil | + lua_debug> | + {E:E5105: Error while calling lua chunk: [string "<VimL }| + {E:compiled string>"]:5: attempt to perform arithmetic o}| + {E:n local 'a' (a nil value)} | + {cr:Press ENTER or type command to continue}^ | + ]]) + end) +end) + +describe('package.path/package.cpath', function() + local sl = alter_slashes + + local function get_new_paths(sufs, runtimepaths) + runtimepaths = runtimepaths or meths.list_runtime_paths() + local new_paths = {} + local sep = package.config:sub(1, 1) + for _, v in ipairs(runtimepaths) do + for _, suf in ipairs(sufs) do + new_paths[#new_paths + 1] = v .. sep .. 'lua' .. suf + end + end + return new_paths + end + local function execute_lua(cmd, ...) + return meths.execute_lua(cmd, {...}) + end + local function eval_lua(expr, ...) + return meths.execute_lua('return ' .. expr, {...}) + end + local function set_path(which, value) + return execute_lua('package[select(1, ...)] = select(2, ...)', which, value) + end + + it('contains directories from &runtimepath on first invocation', function() + local new_paths = get_new_paths(sl{'/?.lua', '/?/init.lua'}) + local new_paths_str = table.concat(new_paths, ';') + eq(new_paths_str, eval_lua('package.path'):sub(1, #new_paths_str)) + + local new_cpaths = get_new_paths(iswin() and {'\\?.dll'} or {'/?.so'}) + local new_cpaths_str = table.concat(new_cpaths, ';') + eq(new_cpaths_str, eval_lua('package.cpath'):sub(1, #new_cpaths_str)) + end) + it('puts directories from &runtimepath always at the start', function() + meths.set_option('runtimepath', 'a,b') + local new_paths = get_new_paths(sl{'/?.lua', '/?/init.lua'}, {'a', 'b'}) + local new_paths_str = table.concat(new_paths, ';') + eq(new_paths_str, eval_lua('package.path'):sub(1, #new_paths_str)) + + set_path('path', sl'foo/?.lua;foo/?/init.lua;' .. new_paths_str) + + neq(new_paths_str, eval_lua('package.path'):sub(1, #new_paths_str)) + + command('set runtimepath+=c') + new_paths = get_new_paths(sl{'/?.lua', '/?/init.lua'}, {'a', 'b', 'c'}) + new_paths_str = table.concat(new_paths, ';') + eq(new_paths_str, eval_lua('package.path'):sub(1, #new_paths_str)) + end) + it('understands uncommon suffixes', function() + set_path('cpath', './?/foo/bar/baz/x.nlua') + meths.set_option('runtimepath', 'a') + local new_paths = get_new_paths({'/?/foo/bar/baz/x.nlua'}, {'a'}) + local new_paths_str = table.concat(new_paths, ';') + eq(new_paths_str, eval_lua('package.cpath'):sub(1, #new_paths_str)) + + set_path('cpath', './yyy?zzz/x') + meths.set_option('runtimepath', 'b') + new_paths = get_new_paths({'/yyy?zzz/x'}, {'b'}) + new_paths_str = table.concat(new_paths, ';') + eq(new_paths_str, eval_lua('package.cpath'):sub(1, #new_paths_str)) + + set_path('cpath', './yyy?zzz/123?ghi/x') + meths.set_option('runtimepath', 'b') + new_paths = get_new_paths({'/yyy?zzz/123?ghi/x'}, {'b'}) + new_paths_str = table.concat(new_paths, ';') + eq(new_paths_str, eval_lua('package.cpath'):sub(1, #new_paths_str)) + end) + it('preserves empty items', function() + local many_empty_path = ';;;;;;' + local many_empty_cpath = ';;;;;;./?.luaso' + set_path('path', many_empty_path) + set_path('cpath', many_empty_cpath) + meths.set_option('runtimepath', 'a') + local new_paths = get_new_paths(sl{'/?.lua', '/?/init.lua'}, {'a'}) + local new_paths_str = table.concat(new_paths, ';') + eq(new_paths_str .. ';' .. many_empty_path, eval_lua('package.path')) + local new_cpaths = get_new_paths({'/?.luaso'}, {'a'}) + local new_cpaths_str = table.concat(new_cpaths, ';') + eq(new_cpaths_str .. ';' .. many_empty_cpath, eval_lua('package.cpath')) + end) + it('preserves empty value', function() + set_path('path', '') + meths.set_option('runtimepath', 'a') + local new_paths = get_new_paths(sl{'/?.lua', '/?/init.lua'}, {'a'}) + local new_paths_str = table.concat(new_paths, ';') + eq(new_paths_str .. ';', eval_lua('package.path')) + end) + it('purges out all additions if runtimepath is set to empty', function() + local new_paths = get_new_paths(sl{'/?.lua', '/?/init.lua'}) + local new_paths_str = table.concat(new_paths, ';') + local path = eval_lua('package.path') + eq(new_paths_str, path:sub(1, #new_paths_str)) + + local new_cpaths = get_new_paths(iswin() and {'\\?.dll'} or {'/?.so'}) + local new_cpaths_str = table.concat(new_cpaths, ';') + local cpath = eval_lua('package.cpath') + eq(new_cpaths_str, cpath:sub(1, #new_cpaths_str)) + + meths.set_option('runtimepath', '') + eq(path:sub(#new_paths_str + 2, -1), eval_lua('package.path')) + eq(cpath:sub(#new_cpaths_str + 2, -1), eval_lua('package.cpath')) + end) + it('works with paths with escaped commas', function() + meths.set_option('runtimepath', '\\,') + local new_paths = get_new_paths(sl{'/?.lua', '/?/init.lua'}, {','}) + local new_paths_str = table.concat(new_paths, ';') + eq(new_paths_str, eval_lua('package.path'):sub(1, #new_paths_str)) + end) + it('ignores paths with semicolons', function() + meths.set_option('runtimepath', 'foo;bar,\\,') + local new_paths = get_new_paths(sl{'/?.lua', '/?/init.lua'}, {','}) + local new_paths_str = table.concat(new_paths, ';') + eq(new_paths_str, eval_lua('package.path'):sub(1, #new_paths_str)) + end) +end) diff --git a/test/functional/normal/count_spec.lua b/test/functional/normal/count_spec.lua index 700e1f3e81..94f741250a 100644 --- a/test/functional/normal/count_spec.lua +++ b/test/functional/normal/count_spec.lua @@ -4,13 +4,13 @@ local eq = helpers.eq local eval = helpers.eval local feed = helpers.feed local clear = helpers.clear -local execute = helpers.execute +local command = helpers.command describe('v:count/v:count1', function() before_each(function() clear() - execute('map <silent> _x :<C-u>let g:count = "v:count=". v:count .", v:count1=". v:count1<CR>') + command('map <silent> _x :<C-u>let g:count = "v:count=". v:count .", v:count1=". v:count1<CR>') end) describe('in cmdwin', function() diff --git a/test/functional/normal/fold_spec.lua b/test/functional/normal/fold_spec.lua new file mode 100644 index 0000000000..00e83bedc8 --- /dev/null +++ b/test/functional/normal/fold_spec.lua @@ -0,0 +1,362 @@ +local helpers = require('test.functional.helpers')(after_each) + +local clear = helpers.clear +local insert = helpers.insert +local feed = helpers.feed +local expect = helpers.expect +local feed_command = helpers.feed_command +local funcs = helpers.funcs +local foldlevel = funcs.foldlevel +local foldclosedend = funcs.foldclosedend +local eq = helpers.eq + +describe('Folds', function() + local tempfname = 'Xtest-fold.txt' + clear() + before_each(function() feed_command('enew!') end) + after_each(function() os.remove(tempfname) end) + it('manual folding adjusts with filter', function() + insert([[ + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20]]) + feed_command('4,$fold', '%foldopen', '10,$fold', '%foldopen') + feed_command('1,8! cat') + feed('5ggzdzMGdd') + expect([[ + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9]]) + end) + describe('adjusting folds after :move', function() + local function manually_fold_indent() + -- setting foldmethod twice is a trick to get vim to set the folds for me + feed_command('set foldmethod=indent', 'set foldmethod=manual') + -- Ensure that all folds will get closed (makes it easier to test the + -- length of folds). + feed_command('set foldminlines=0') + -- Start with all folds open (so :move ranges aren't affected by closed + -- folds). + feed_command('%foldopen!') + end + + local function get_folds() + local rettab = {} + for i = 1, funcs.line('$') do + table.insert(rettab, foldlevel(i)) + end + return rettab + end + + local function test_move_indent(insert_string, move_command) + -- This test is easy because we just need to ensure that the resulting + -- fold is the same as calculated when creating folds from scratch. + insert(insert_string) + feed_command(move_command) + local after_move_folds = get_folds() + -- Doesn't change anything, but does call foldUpdateAll() + feed_command('set foldminlines=0') + eq(after_move_folds, get_folds()) + -- Set up the buffer with insert_string for the manual fold testing. + feed_command('enew!') + insert(insert_string) + manually_fold_indent() + feed_command(move_command) + end + + it('neither closes nor corrupts folds', function() + test_move_indent([[ +a + a + a + a + a + a +a + a + a + a + a + a +a + a + a + a + a + a]], '7,12m0') + expect([[ +a + a + a + a + a + a +a + a + a + a + a + a +a + a + a + a + a + a]]) + -- lines are not closed, folds are correct + for i = 1,funcs.line('$') do + eq(-1, funcs.foldclosed(i)) + if i == 1 or i == 7 or i == 13 then + eq(0, foldlevel(i)) + elseif i == 4 then + eq(2, foldlevel(i)) + else + eq(1, foldlevel(i)) + end + end + -- folds are not corrupted + feed('zM') + eq(6, foldclosedend(2)) + eq(12, foldclosedend(8)) + eq(18, foldclosedend(14)) + end) + it("doesn't split a fold when the move is within it", function() + test_move_indent([[ +a + a + a + a + a + a + a + a + a +a]], '5m6') + eq({0, 1, 1, 2, 2, 2, 2, 1, 1, 0}, get_folds()) + end) + it('truncates folds that end in the moved range', function() + test_move_indent([[ +a + a + a + a + a +a +a]], '4,5m6') + eq({0, 1, 2, 0, 0, 0, 0}, get_folds()) + end) + it('moves folds that start between moved range and destination', function() + test_move_indent([[ +a + a + a + a + a +a +a + a + a + a +a +a + a]], '3,4m$') + eq({0, 1, 1, 0, 0, 1, 2, 1, 0, 0, 1, 0, 0}, get_folds()) + end) + it('does not affect folds outside changed lines', function() + test_move_indent([[ + a + a + a +a +a +a + a + a + a]], '4m5') + eq({1, 1, 1, 0, 0, 0, 1, 1, 1}, get_folds()) + end) + it('moves and truncates folds that start in moved range', function() + test_move_indent([[ +a + a + a + a + a +a +a +a +a +a]], '1,3m7') + eq({0, 0, 0, 0, 0, 1, 2, 0, 0, 0}, get_folds()) + end) + it('breaks a fold when moving text into it', function() + test_move_indent([[ +a + a + a + a + a +a +a]], '$m4') + eq({0, 1, 2, 2, 0, 0, 0}, get_folds()) + end) + it('adjusts correctly when moving a range backwards', function() + test_move_indent([[ +a + a + a + a +a]], '2,3m0') + eq({1, 2, 0, 0, 0}, get_folds()) + end) + it('handles shifting all remaining folds', function() + test_move_indent([[ + a + a + a + a + a + a + a + a + a + a + a + a + a + a +a]], '13m7') + eq({1, 2, 2, 2, 1, 2, 2, 1, 1, 1, 2, 2, 2, 1, 0}, get_folds()) + end) + end) + it('updates correctly on :read', function() + -- luacheck: ignore 621 + helpers.write_file(tempfname, [[ + a + + + a]]) + insert([[ + a + a + a + a + ]]) + feed_command('set foldmethod=indent', '2', '%foldopen') + feed_command('read ' .. tempfname) + -- Just to check we have the correct file text. + expect([[ + a + a + a + + + a + a + a + ]]) + for i = 1,2 do + eq(1, funcs.foldlevel(i)) + end + for i = 3,5 do + eq(0, funcs.foldlevel(i)) + end + for i = 6,8 do + eq(1, funcs.foldlevel(i)) + end + end) + it('combines folds when removing separating space', function() + -- luacheck: ignore 621 + insert([[ + a + a + a + a + a + a + a + a + ]]) + feed_command('set foldmethod=indent', '3,5d') + eq(5, funcs.foldclosedend(1)) + end) + it("doesn't combine folds that have a specified end", function() + insert([[ + {{{ + }}} + + + + {{{ + + }}} + ]]) + feed_command('set foldmethod=marker', '3,5d', '%foldclose') + eq(2, funcs.foldclosedend(1)) + end) + it('splits folds according to >N and <N with foldexpr', function() + helpers.source([[ + function TestFoldExpr(lnum) + let thisline = getline(a:lnum) + if thisline == 'a' + return 1 + elseif thisline == 'b' + return 0 + elseif thisline == 'c' + return '<1' + elseif thisline == 'd' + return '>1' + endif + return 0 + endfunction + ]]) + helpers.write_file(tempfname, [[ + b + b + a + a + d + a + a + c]]) + insert([[ + a + a + a + a + a + a + ]]) + feed_command('set foldmethod=expr', 'set foldexpr=TestFoldExpr(v:lnum)', '2', 'foldopen') + feed_command('read ' .. tempfname, '%foldclose') + eq(2, funcs.foldclosedend(1)) + eq(0, funcs.foldlevel(3)) + eq(0, funcs.foldlevel(4)) + eq(6, funcs.foldclosedend(5)) + eq(10, funcs.foldclosedend(7)) + eq(14, funcs.foldclosedend(11)) + end) +end) diff --git a/test/functional/normal/lang_spec.lua b/test/functional/normal/lang_spec.lua new file mode 100644 index 0000000000..24d1262f5f --- /dev/null +++ b/test/functional/normal/lang_spec.lua @@ -0,0 +1,63 @@ +local helpers = require('test.functional.helpers')(after_each) +local clear, insert, eq = helpers.clear, helpers.insert, helpers.eq +local command, expect = helpers.command, helpers.expect +local feed, eval = helpers.feed, helpers.eval +local exc_exec = helpers.exc_exec + +describe('gu and gU', function() + before_each(clear) + + it('works in any locale with default casemap', function() + eq('internal,keepascii', eval('&casemap')) + insert("iI") + feed("VgU") + expect("II") + feed("Vgu") + expect("ii") + end) + + describe('works in Turkish locale', function() + clear() + + local err = exc_exec('lang ctype tr_TR.UTF-8') + if err ~= 0 then + pending("Locale tr_TR.UTF-8 not supported", function() end) + return + end + + before_each(function() + command('lang ctype tr_TR.UTF-8') + end) + + it('with default casemap', function() + eq('internal,keepascii', eval('&casemap')) + -- expect ASCII behavior + insert("iI") + feed("VgU") + expect("II") + feed("Vgu") + expect("ii") + end) + + it('with casemap=""', function() + command('set casemap=') + -- expect either Turkish locale behavior or ASCII behavior + local iupper = eval("toupper('i')") + if iupper == "ฤฐ" then + insert("iI") + feed("VgU") + expect("ฤฐI") + feed("Vgu") + expect("iฤฑ") + elseif iupper == "I" then + insert("iI") + feed("VgU") + expect("II") + feed("Vgu") + expect("ii") + else + error("expected toupper('i') to be either 'I' or 'ฤฐ'") + end + end) + end) +end) diff --git a/test/functional/normal/put_spec.lua b/test/functional/normal/put_spec.lua new file mode 100644 index 0000000000..148a35ec6b --- /dev/null +++ b/test/functional/normal/put_spec.lua @@ -0,0 +1,934 @@ +local Screen = require('test.functional.ui.screen') +local helpers = require('test.functional.helpers')(after_each) + +local clear = helpers.clear +local insert = helpers.insert +local feed = helpers.feed +local expect = helpers.expect +local eq = helpers.eq +local map = helpers.map +local filter = helpers.filter +local feed_command = helpers.feed_command +local curbuf_contents = helpers.curbuf_contents +local funcs = helpers.funcs +local dedent = helpers.dedent +local getreg = funcs.getreg + +local function reset() + feed_command('enew!') + insert([[ + Line of words 1 + Line of words 2]]) + feed_command('goto 1') + feed('itest_string.<esc>u') + funcs.setreg('a', 'test_stringa', 'V') + funcs.setreg('b', 'test_stringb\ntest_stringb\ntest_stringb', 'b') + funcs.setreg('"', 'test_string"', 'v') + feed_command('set virtualedit=') +end + +-- We check the last inserted register ". in each of these tests because it is +-- implemented completely differently in do_put(). +-- It is implemented differently so that control characters and imap'ped +-- characters work in the same manner when pasted as when inserted. +describe('put command', function() + clear() + before_each(reset) + + local function visual_marks_zero() + for _,v in pairs(funcs.getpos("'<")) do + if v ~= 0 then + return false + end + end + for _,v in pairs(funcs.getpos("'>")) do + if v ~= 0 then + return false + end + end + return true + end + + -- {{{ Where test definitions are run + local function run_test_variations(test_variations, extra_setup) + reset() + if extra_setup then extra_setup() end + local init_contents = curbuf_contents() + local init_cursorpos = funcs.getcurpos() + local assert_no_change = function (exception_table, after_undo) + expect(init_contents) + -- When putting the ". register forwards, undo doesn't move + -- the cursor back to where it was before. + -- This is because it uses the command character 'a' to + -- start the insert, and undo after that leaves the cursor + -- one place to the right (unless we were at the end of the + -- line when we pasted). + if not (exception_table.undo_position and after_undo) then + eq(funcs.getcurpos(), init_cursorpos) + end + end + + for _, test in pairs(test_variations) do + it(test.description, function() + if extra_setup then extra_setup() end + local orig_dotstr = funcs.getreg('.') + helpers.ok(visual_marks_zero()) + -- Make sure every test starts from the same conditions + assert_no_change(test.exception_table, false) + local was_cli = test.test_action() + test.test_assertions(test.exception_table, false) + -- Check that undo twice puts us back to the original conditions + -- (i.e. puts the cursor and text back to before) + feed('u') + assert_no_change(test.exception_table, true) + + -- Should not have changed the ". register + -- If we paste the ". register with a count we can't avoid + -- changing this register, hence avoid this check. + if not test.exception_table.dot_reg_changed then + eq(funcs.getreg('.'), orig_dotstr) + end + + -- Doing something, undoing it, and then redoing it should + -- leave us in the same state as just doing it once. + -- For :ex actions we want '@:', for normal actions we want '.' + + -- The '.' redo doesn't work for visual put so just exit if + -- it was tested. + -- We check that visual put was used by checking if the '< and + -- '> marks were changed. + if not visual_marks_zero() then + return + end + + if test.exception_table.undo_position then + funcs.setpos('.', init_cursorpos) + end + if was_cli then + feed('@:') + else + feed('.') + end + + test.test_assertions(test.exception_table, true) + end) + end + end -- run_test_variations() + -- }}} + + local function create_test_defs(test_defs, command_base, command_creator, -- {{{ + expect_base, expect_creator) + local rettab = {} + local exceptions + for _, v in pairs(test_defs) do + if v[4] then + exceptions = v[4] + else + exceptions = {} + end + table.insert(rettab, + { + test_action = command_creator(command_base, v[1]), + test_assertions = expect_creator(expect_base, v[2]), + description = v[3], + exception_table = exceptions, + }) + end + return rettab + end -- create_test_defs() }}} + + local function find_cursor_position(expect_string) -- {{{ + -- There must only be one occurance of the character 'x' in + -- expect_string. + -- This function removes that occurance, and returns the position that + -- it was in. + -- This returns the cursor position that would leave the 'x' in that + -- place if we feed 'ix<esc>' and the string existed before it. + for linenum, line in pairs(funcs.split(expect_string, '\n', 1)) do + local column = line:find('x') + if column then + return {linenum, column}, expect_string:gsub('x', '') + end + end + end -- find_cursor_position() }}} + + -- Action function creators {{{ + local function create_p_action(test_map, substitution) + local temp_val = test_map:gsub('p', substitution) + return function() + feed(temp_val) + return false + end + end + + local function create_put_action(command_base, substitution) + local temp_val = command_base:gsub('put', substitution) + return function() + feed_command(temp_val) + return true + end + end + -- }}} + + -- Expect function creator {{{ + local function expect_creator(conversion_function, expect_base, conversion_table) + local temp_expect_string = conversion_function(expect_base, conversion_table) + local cursor_position, expect_string = find_cursor_position(temp_expect_string) + return function(exception_table, after_redo) + expect(expect_string) + + -- Have to use getcurpos() instead of curwinmeths.get_cursor() in + -- order to account for virtualedit. + -- We always want the curswant element in getcurpos(), which is + -- sometimes different to the column element in + -- curwinmeths.get_cursor(). + -- NOTE: The ".gp command leaves the cursor after the pasted text + -- when running, but does not when the command is redone with the + -- '.' command. + if not (exception_table.redo_position and after_redo) then + local actual_position = funcs.getcurpos() + eq(cursor_position, {actual_position[2], actual_position[5]}) + end + end + end -- expect_creator() }}} + + -- Test definitions {{{ + local function copy_def(def) + local rettab = { '', {}, '', nil } + rettab[1] = def[1] + for k,v in pairs(def[2]) do + rettab[2][k] = v + end + rettab[3] = def[3] + if def[4] then + rettab[4] = {} + for k,v in pairs(def[4]) do + rettab[4][k] = v + end + end + return rettab + end + + local normal_command_defs = { + { + 'p', + {cursor_after = false, put_backwards = false, dot_register = false}, + 'pastes after cursor with p', + }, + { + 'gp', + {cursor_after = true, put_backwards = false, dot_register = false}, + 'leaves cursor after text with gp', + }, + { + '".p', + {cursor_after = false, put_backwards = false, dot_register = true}, + 'works with the ". register', + }, + { + '".gp', + {cursor_after = true, put_backwards = false, dot_register = true}, + 'gp works with the ". register', + {redo_position = true}, + }, + { + 'P', + {cursor_after = false, put_backwards = true, dot_register = false}, + 'pastes before cursor with P', + }, + { + 'gP', + {cursor_after = true, put_backwards = true, dot_register = false}, + 'gP pastes before cursor and leaves cursor after text', + }, + { + '".P', + {cursor_after = false, put_backwards = true, dot_register = true}, + 'P works with ". register', + }, + { + '".gP', + {cursor_after = true, put_backwards = true, dot_register = true}, + 'gP works with ". register', + {redo_position = true}, + }, + } + + -- Add a definition applying a count for each definition above. + -- Could do this for each transformation (p -> P, p -> gp etc), but I think + -- it's neater this way (balance between being explicit and too verbose). + for i = 1,#normal_command_defs do + local cur = normal_command_defs[i] + + -- Make modified copy of current definition that includes a count. + local newdef = copy_def(cur) + newdef[2].count = 2 + cur[2].count = 1 + newdef[1] = '2' .. newdef[1] + newdef[3] = 'double ' .. newdef[3] + + if cur[2].dot_register then + if not cur[4] then + newdef[4] = {} + end + newdef[4].dot_reg_changed = true + end + + normal_command_defs[#normal_command_defs + 1] = newdef + end + + local ex_command_defs = { + { + 'put', + {put_backwards = false, dot_register = false}, + 'pastes linewise forwards with :put', + }, + { + 'put!', + {put_backwards = true, dot_register = false}, + 'pastes linewise backwards with :put!', + }, + { + 'put .', + {put_backwards = false, dot_register = true}, + 'pastes linewise with the dot register', + }, + { + 'put! .', + {put_backwards = true, dot_register = true}, + 'pastes linewise backwards with the dot register', + }, + } + + local function non_dotdefs(def_table) + return filter(function(d) return not d[2].dot_register end, def_table) + end + + -- }}} + + -- Conversion functions {{{ + local function convert_characterwise(expect_base, conversion_table, + virtualedit_end, visual_put) + expect_base = dedent(expect_base) + -- There is no difference between 'P' and 'p' when VIsual_active + if not visual_put then + if conversion_table.put_backwards then + -- Special case for virtualedit at the end of a line. + local replace_string + if not virtualedit_end then + replace_string = 'test_stringx"%1' + else + replace_string = 'test_stringx"' + end + expect_base = expect_base:gsub('(.)test_stringx"', replace_string) + end + end + if conversion_table.count > 1 then + local rep_string = 'test_string"' + local extra_puts = rep_string:rep(conversion_table.count - 1) + expect_base = expect_base:gsub('test_stringx"', extra_puts .. 'test_stringx"') + end + if conversion_table.cursor_after then + expect_base = expect_base:gsub('test_stringx"', 'test_string"x') + end + if conversion_table.dot_register then + expect_base = expect_base:gsub('(test_stringx?)"', '%1.') + end + return expect_base + end -- convert_characterwise() + + local function make_back(string) + local prev_line + local rettab = {} + local string_found = false + for _, line in pairs(funcs.split(string, '\n', 1)) do + if line:find('test_string') then + string_found = true + table.insert(rettab, line) + else + if string_found then + if prev_line then + table.insert(rettab, prev_line) + prev_line = nil + end + table.insert(rettab, line) + else + table.insert(rettab, prev_line) + prev_line = line + end + end + end + -- In case there are no lines after the text that was put. + if prev_line and string_found then + table.insert(rettab, prev_line) + end + return table.concat(rettab, '\n') + end -- make_back() + + local function convert_linewise(expect_base, conversion_table, _, use_a, indent) + expect_base = dedent(expect_base) + if conversion_table.put_backwards then + expect_base = make_back(expect_base) + end + local p_str = 'test_string"' + if use_a then + p_str = 'test_stringa' + end + + if conversion_table.dot_register then + expect_base = expect_base:gsub('x' .. p_str, 'xtest_string.') + p_str = 'test_string.' + end + + if conversion_table.cursor_after then + expect_base = expect_base:gsub('x' .. p_str .. '\n', p_str .. '\nx') + end + + -- The 'indent' argument is only used here because a single put with an + -- indent doesn't require special handling. It doesn't require special + -- handling because the cursor is never put before the indent, hence + -- the modification of 'test_stringx"' gives the same overall answer as + -- modifying ' test_stringx"'. + + -- Only happens when using normal mode command actions. + if conversion_table.count and conversion_table.count > 1 then + if not indent then + indent = '' + end + local rep_string = indent .. p_str .. '\n' + local extra_puts = rep_string:rep(conversion_table.count - 1) + local orig_string, new_string + if conversion_table.cursor_after then + orig_string = indent .. p_str .. '\nx' + new_string = extra_puts .. orig_string + else + orig_string = indent .. 'x' .. p_str .. '\n' + new_string = orig_string .. extra_puts + end + expect_base = expect_base:gsub(orig_string, new_string) + end + return expect_base + end + + local function put_x_last(orig_line, p_str) + local prev_end, cur_end, cur_start = 0, 0, 0 + while cur_start do + prev_end = cur_end + cur_start, cur_end = orig_line:find(p_str, prev_end) + end + -- Assume (because that is the only way I call it) that p_str matches + -- the pattern 'test_string.' + return orig_line:sub(1, prev_end - 1) .. 'x' .. orig_line:sub(prev_end) + end + + local function convert_blockwise(expect_base, conversion_table, visual, + use_b, trailing_whitespace) + expect_base = dedent(expect_base) + local p_str = 'test_string"' + if use_b then + p_str = 'test_stringb' + end + + if conversion_table.dot_register then + expect_base = expect_base:gsub('(x?)' .. p_str, '%1test_string.') + -- Looks strange, but the dot is a special character in the pattern + -- and a literal character in the replacement. + expect_base = expect_base:gsub('test_stringx.', 'test_stringx.') + p_str = 'test_string.' + end + + -- No difference between 'p' and 'P' in visual mode. + if not visual then + if conversion_table.put_backwards then + -- One for the line where the cursor is left, one for all other + -- lines. + expect_base = expect_base:gsub('([^x])' .. p_str, p_str .. '%1') + expect_base = expect_base:gsub('([^x])x' .. p_str, 'x' .. p_str .. '%1') + if not trailing_whitespace then + expect_base = expect_base:gsub(' \n', '\n') + expect_base = expect_base:gsub(' $', '') + end + end + end + + if conversion_table.count and conversion_table.count > 1 then + local p_pattern = p_str:gsub('%.', '%%.') + expect_base = expect_base:gsub(p_pattern, + p_str:rep(conversion_table.count)) + expect_base = expect_base:gsub('test_stringx([b".])', + p_str:rep(conversion_table.count - 1) + .. '%0') + end + + if conversion_table.cursor_after then + if not visual then + local prev_line + local rettab = {} + local prev_in_block = false + for _, line in pairs(funcs.split(expect_base, '\n', 1)) do + if line:find('test_string') then + if prev_line then + prev_line = prev_line:gsub('x', '') + table.insert(rettab, prev_line) + end + prev_line = line + prev_in_block = true + else + if prev_in_block then + prev_line = put_x_last(prev_line, p_str) + table.insert(rettab, prev_line) + prev_in_block = false + end + table.insert(rettab, line) + end + end + if prev_line and prev_in_block then + table.insert(rettab, put_x_last(prev_line, p_str)) + end + + expect_base = table.concat(rettab, '\n') + else + expect_base = expect_base:gsub('x(.)', '%1x') + end + end + + return expect_base + end + -- }}} + + -- Convenience functions {{{ + local function run_normal_mode_tests(test_string, base_map, extra_setup, + virtualedit_end, selection_string) + local function convert_closure(e, c) + return convert_characterwise(e, c, virtualedit_end, selection_string) + end + local function expect_normal_creator(expect_base, conversion_table) + local test_expect = expect_creator(convert_closure, expect_base, conversion_table) + return function(exception_table, after_redo) + test_expect(exception_table, after_redo) + if selection_string then + eq(getreg('"'), selection_string) + else + eq(getreg('"'), 'test_string"') + end + end + end + run_test_variations( + create_test_defs( + normal_command_defs, + base_map, + create_p_action, + test_string, + expect_normal_creator + ), + extra_setup + ) + end -- run_normal_mode_tests() + + local function convert_linewiseer(expect_base, conversion_table) + return expect_creator(convert_linewise, expect_base, conversion_table) + end + + local function run_linewise_tests(expect_base, base_command, extra_setup) + local linewise_test_defs = create_test_defs( + ex_command_defs, base_command, + create_put_action, expect_base, convert_linewiseer) + run_test_variations(linewise_test_defs, extra_setup) + end -- run_linewise_tests() + -- }}} + + -- Actual tests + describe('default pasting', function() + local expect_string = [[ + Ltest_stringx"ine of words 1 + Line of words 2]] + run_normal_mode_tests(expect_string, 'p') + + run_linewise_tests([[ + Line of words 1 + xtest_string" + Line of words 2]], + 'put' + ) + end) + + describe('linewise register', function() + -- put with 'p' + local local_ex_command_defs = non_dotdefs(normal_command_defs) + local base_expect_string = [[ + Line of words 1 + xtest_stringa + Line of words 2]] + local function local_convert_linewise(expect_base, conversion_table) + return convert_linewise(expect_base, conversion_table, nil, true) + end + local function expect_lineput(expect_base, conversion_table) + return expect_creator(local_convert_linewise, expect_base, conversion_table) + end + run_test_variations( + create_test_defs( + local_ex_command_defs, + '"ap', + create_p_action, + base_expect_string, + expect_lineput + ) + ) + + -- put with :put + local linewise_put_defs = non_dotdefs(ex_command_defs) + base_expect_string = [[ + Line of words 1 + xtest_stringa + Line of words 2]] + run_test_variations( + create_test_defs( + linewise_put_defs, + 'put a', create_put_action, + base_expect_string, convert_linewiseer + ) + ) + + end) + + describe('blockwise register', function() + local blockwise_put_defs = non_dotdefs(normal_command_defs) + local test_base = [[ + Lxtest_stringbine of words 1 + Ltest_stringbine of words 2 + test_stringb]] + + local function expect_block_creator(expect_base, conversion_table) + return expect_creator(function(e,c) return convert_blockwise(e,c,nil,true) end, + expect_base, conversion_table) + end + + run_test_variations( + create_test_defs( + blockwise_put_defs, + '"bp', + create_p_action, + test_base, + expect_block_creator + ) + ) + end) + + it('adds correct indentation when put with [p and ]p', function() + feed('G>>"a]pix<esc>') + -- luacheck: ignore + expect([[ + Line of words 1 + Line of words 2 + xtest_stringa]]) + feed('uu"a[pix<esc>') + -- luacheck: ignore + expect([[ + Line of words 1 + xtest_stringa + Line of words 2]]) + end) + + describe('linewise paste with autoindent', function() + -- luacheck: ignore + run_linewise_tests([[ + Line of words 1 + Line of words 2 + xtest_string"]], + 'put' + , + function() + funcs.setline('$', ' Line of words 2') + -- Set curswant to '8' to be at the end of the tab character + -- This is where the cursor is put back after the 'u' command. + funcs.setpos('.', {0, 2, 1, 0, 8}) + feed_command('set autoindent') + end + ) + end) + + describe('put inside tabs with virtualedit', function() + local test_string = [[ + Line of words 1 + test_stringx" Line of words 2]] + run_normal_mode_tests(test_string, 'p', function() + funcs.setline('$', ' Line of words 2') + feed_command('set virtualedit=all') + funcs.setpos('.', {0, 2, 1, 2, 3}) + end) + end) + + describe('put after the line with virtualedit', function() + local test_string = [[ + Line of words 1 test_stringx" + Line of words 2]] + run_normal_mode_tests(test_string, 'p', function() + funcs.setline('$', ' Line of words 2') + feed_command('set virtualedit=all') + funcs.setpos('.', {0, 1, 16, 1, 17}) + end, true) + end) + + describe('Visual put', function() + describe('basic put', function() + local test_string = [[ + test_stringx" words 1 + Line of words 2]] + run_normal_mode_tests(test_string, 'v2ep', nil, nil, 'Line of') + end) + describe('over trailing newline', function() + local test_string = 'Line of test_stringx"Line of words 2' + run_normal_mode_tests(test_string, 'v$p', function() + funcs.setpos('.', {0, 1, 9, 0, 9}) + end, + nil, + 'words 1\n') + end) + describe('linewise mode', function() + local test_string = [[ + xtest_string" + Line of words 2]] + local function expect_vis_linewise(expect_base, conversion_table) + return expect_creator(function(e, c) + return convert_linewise(e, c, nil, nil) + end, + expect_base, conversion_table) + end + run_test_variations( + create_test_defs( + normal_command_defs, + 'Vp', + create_p_action, + test_string, + expect_vis_linewise + ), + function() funcs.setpos('.', {0, 1, 1, 0, 1}) end + ) + + describe('with whitespace at bol', function() + local function expect_vis_lineindented(expect_base, conversion_table) + local test_expect = expect_creator(function(e, c) + return convert_linewise(e, c, nil, nil, ' ') + end, + expect_base, conversion_table) + return function(exception_table, after_redo) + test_expect(exception_table, after_redo) + eq(getreg('"'), 'Line of words 1\n') + end + end + local base_expect_string = [[ + xtest_string" + Line of words 2]] + run_test_variations( + create_test_defs( + normal_command_defs, + 'Vp', + create_p_action, + base_expect_string, + expect_vis_lineindented + ), + function() + feed('i test_string.<esc>u') + funcs.setreg('"', ' test_string"', 'v') + end + ) + end) + + end) + + describe('blockwise visual mode', function() + local test_base = [[ + test_stringx"e of words 1 + test_string"e of words 2]] + + local function expect_block_creator(expect_base, conversion_table) + local test_expect = expect_creator(function(e, c) + return convert_blockwise(e, c, true) + end, expect_base, conversion_table) + return function(e,c) + test_expect(e,c) + eq(getreg('"'), 'Lin\nLin') + end + end + + local select_down_test_defs = create_test_defs( + normal_command_defs, + '<C-v>jllp', + create_p_action, + test_base, + expect_block_creator + ) + run_test_variations(select_down_test_defs) + + + -- Undo and redo of a visual block put leave the cursor in the top + -- left of the visual block area no matter where the cursor was + -- when it started. + local undo_redo_no = map(function(table) + local rettab = copy_def(table) + if not rettab[4] then + rettab[4] = {} + end + rettab[4].undo_position = true + rettab[4].redo_position = true + return rettab + end, + normal_command_defs) + + -- Selection direction doesn't matter + run_test_variations( + create_test_defs( + undo_redo_no, + '<C-v>kllp', + create_p_action, + test_base, + expect_block_creator + ), + function() funcs.setpos('.', {0, 2, 1, 0, 1}) end + ) + + describe('blockwise cursor after undo', function() + -- A bit of a hack of the reset above. + -- In the tests that selection direction doesn't matter, we + -- don't check the undo/redo position because it doesn't fit + -- the same pattern as everything else. + -- Here we fix this by directly checking the undo/redo position + -- in the test_assertions of our test definitions. + local function assertion_creator(_,_) + return function(_,_) + feed('u') + -- Have to use feed('u') here to set curswant, because + -- ex_undo() doesn't do that. + eq(funcs.getcurpos(), {0, 1, 1, 0, 1}) + feed('<C-r>') + eq(funcs.getcurpos(), {0, 1, 1, 0, 1}) + end + end + + run_test_variations( + create_test_defs( + undo_redo_no, + '<C-v>kllp', + create_p_action, + test_base, + assertion_creator + ), + function() funcs.setpos('.', {0, 2, 1, 0, 1}) end + ) + end) + end) + + + describe("with 'virtualedit'", function() + describe('splitting a tab character', function() + local base_expect_string = [[ + Line of words 1 + test_stringx" Line of words 2]] + run_normal_mode_tests( + base_expect_string, + 'vp', + function() + funcs.setline('$', ' Line of words 2') + feed_command('set virtualedit=all') + funcs.setpos('.', {0, 2, 1, 2, 3}) + end, + nil, + ' ' + ) + end) + describe('after end of line', function() + local base_expect_string = [[ + Line of words 1 test_stringx" + Line of words 2]] + run_normal_mode_tests( + base_expect_string, + 'vp', + function() + feed_command('set virtualedit=all') + funcs.setpos('.', {0, 1, 16, 2, 18}) + end, + true, + ' ' + ) + end) + end) + end) + + describe('. register special tests', function() + before_each(reset) + it('applies control character actions', function() + feed('i<C-t><esc>u') + expect([[ + Line of words 1 + Line of words 2]]) + feed('".p') + expect([[ + Line of words 1 + Line of words 2]]) + feed('u1go<C-v>j".p') + eq([[ + ine of words 1 + ine of words 2]], curbuf_contents()) + end) + + local function bell_test(actions, should_ring) + local screen = Screen.new() + screen:attach() + helpers.ok(not screen.bell and not screen.visualbell) + actions() + helpers.wait() + screen:wait(function() + if should_ring then + if not screen.bell and not screen.visualbell then + return 'Bell was not rung after action' + end + else + if screen.bell or screen.visualbell then + return 'Bell was rung after action' + end + end + end) + screen:detach() + end + + it('should not ring the bell with gp at end of line', function() + bell_test(function() feed('$".gp') end) + + -- Even if the last character is a multibyte character. + reset() + funcs.setline(1, 'helloเธก') + bell_test(function() feed('$".gp') end) + end) + + it('should not ring the bell with gp and end of file', function() + funcs.setpos('.', {0, 2, 1, 0}) + bell_test(function() feed('$vl".gp') end) + end) + + it('should ring the bell when deleting if not appropriate', function() + feed_command('goto 2') + feed('i<bs><esc>') + expect([[ + ine of words 1 + Line of words 2]]) + bell_test(function() feed('".P') end, true) + end) + + it('should restore cursor position after undo of ".p', function() + local origpos = funcs.getcurpos() + feed('".pu') + eq(origpos, funcs.getcurpos()) + end) + + it("should be unaffected by 'autoindent' with V\".2p", function() + feed_command('set autoindent') + feed('i test_string.<esc>u') + feed('V".2p') + expect([[ + test_string. + test_string. + Line of words 2]]) + end) + end) +end) + diff --git a/test/functional/normal/undo_spec.lua b/test/functional/normal/undo_spec.lua new file mode 100644 index 0000000000..a023ca3d90 --- /dev/null +++ b/test/functional/normal/undo_spec.lua @@ -0,0 +1,61 @@ +local helpers = require('test.functional.helpers')(after_each) + +local clear = helpers.clear +local command = helpers.command +local expect = helpers.expect +local feed = helpers.feed +local insert = helpers.insert + +describe('u CTRL-R g- g+', function() + before_each(clear) + + local function create_history(num_steps) + if num_steps == 0 then return end + insert('1') + if num_steps == 1 then return end + feed('o2<esc>') + feed('o3<esc>') + feed('u') + if num_steps == 2 then return end + feed('o4<esc>') + if num_steps == 3 then return end + feed('u') + end + + local function undo_and_redo(hist_pos, undo, redo, expect_str) + command('enew!') + create_history(hist_pos) + local cur_contents = helpers.curbuf_contents() + feed(undo) + expect(expect_str) + feed(redo) + expect(cur_contents) + end + + -- TODO Look for message saying 'Already at oldest change' + it('does nothing when no changes have happened', function() + undo_and_redo(0, 'u', '<C-r>', '') + undo_and_redo(0, 'g-', 'g+', '') + end) + it('undoes a change when at a leaf', function() + undo_and_redo(1, 'u', '<C-r>', '') + undo_and_redo(1, 'g-', 'g+', '') + end) + it('undoes a change when in a non-leaf', function() + undo_and_redo(2, 'u', '<C-r>', '1') + undo_and_redo(2, 'g-', 'g+', '1') + end) + it('undoes properly around a branch point', function() + undo_and_redo(3, 'u', '<C-r>', [[ + 1 + 2]]) + undo_and_redo(3, 'g-', 'g+', [[ + 1 + 2 + 3]]) + end) + it('can find the previous sequence after undoing to a branch', function() + undo_and_redo(4, 'u', '<C-r>', '1') + undo_and_redo(4, 'g-', 'g+', '1') + end) +end) diff --git a/test/functional/options/defaults_spec.lua b/test/functional/options/defaults_spec.lua index caeca5e4e2..b83b7b8eee 100644 --- a/test/functional/options/defaults_spec.lua +++ b/test/functional/options/defaults_spec.lua @@ -3,17 +3,17 @@ local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') local meths = helpers.meths -local execute = helpers.execute +local command = helpers.command local clear = helpers.clear local eval = helpers.eval local eq = helpers.eq local neq = helpers.neq +local mkdir = helpers.mkdir +local rmdir = helpers.rmdir local function init_session(...) local args = { helpers.nvim_prog, '-i', 'NONE', '--embed', - '--cmd', 'set shortmess+=I background=light noswapfile noautoindent', - '--cmd', 'set laststatus=1 undodir=. directory=. viewdir=. backupdir=.' - } + '--cmd', helpers.nvim_set } for _, v in ipairs({...}) do table.insert(args, v) end @@ -25,13 +25,13 @@ describe('startup defaults', function() if helpers.pending_win32(pending) then return end local function expect_filetype(expected) - local screen = Screen.new(48, 4) + local screen = Screen.new(50, 4) screen:attach() - execute('filetype') + command('filetype') screen:expect([[ - ^ | - ~ | - ~ | + ^ | + ~ | + ~ | ]]..expected ) end @@ -39,31 +39,49 @@ describe('startup defaults', function() it('enabled by `-u NORC`', function() init_session('-u', 'NORC') expect_filetype( - 'filetype detection:ON plugin:ON indent:ON |') + 'filetype detection:ON plugin:ON indent:ON |') end) it('disabled by `-u NONE`', function() init_session('-u', 'NONE') expect_filetype( - 'filetype detection:OFF plugin:OFF indent:OFF |') + 'filetype detection:OFF plugin:OFF indent:OFF |') end) it('overridden by early `filetype on`', function() init_session('-u', 'NORC', '--cmd', 'filetype on') expect_filetype( - 'filetype detection:ON plugin:OFF indent:OFF |') + 'filetype detection:ON plugin:OFF indent:OFF |') end) it('overridden by early `filetype plugin on`', function() init_session('-u', 'NORC', '--cmd', 'filetype plugin on') expect_filetype( - 'filetype detection:ON plugin:ON indent:OFF |') + 'filetype detection:ON plugin:ON indent:OFF |') end) it('overridden by early `filetype indent on`', function() init_session('-u', 'NORC', '--cmd', 'filetype indent on') expect_filetype( - 'filetype detection:ON plugin:OFF indent:ON |') + 'filetype detection:ON plugin:OFF indent:ON |') + end) + + it('adjusted by late `filetype off`', function() + init_session('-u', 'NORC', '-c', 'filetype off') + expect_filetype( + 'filetype detection:OFF plugin:(on) indent:(on) |') + end) + + it('adjusted by late `filetype plugin off`', function() + init_session('-u', 'NORC', '-c', 'filetype plugin off') + expect_filetype( + 'filetype detection:ON plugin:OFF indent:ON |') + end) + + it('adjusted by late `filetype indent off`', function() + init_session('-u', 'NORC', '-c', 'filetype indent off') + expect_filetype( + 'filetype detection:ON plugin:ON indent:OFF |') end) end) @@ -82,6 +100,11 @@ describe('startup defaults', function() init_session('-u', 'NORC', '--cmd', 'syntax off') eq(0, eval('exists("g:syntax_on")')) end) + + it('adjusted by late `syntax off`', function() + init_session('-u', 'NORC', '-c', 'syntax off') + eq(0, eval('exists("g:syntax_on")')) + end) end) describe('packpath', function() @@ -96,6 +119,60 @@ describe('startup defaults', function() eq(meths.get_option('runtimepath'), meths.get_option('packpath')) end) end) + + it('v:progpath is set to the absolute path', function() + eq(eval("fnamemodify(v:progpath, ':p')"), eval('v:progpath')) + end) + + describe('$NVIM_LOG_FILE', function() + -- TODO(jkeyes): use stdpath('data') instead. + local datasubdir = helpers.iswin() and 'nvim-data' or 'nvim' + local xdgdir = 'Xtest-startup-xdg-logpath' + local xdgdatadir = xdgdir..'/'..datasubdir + after_each(function() + os.remove('Xtest-logpath') + rmdir(xdgdir) + end) + + it('is used if expansion succeeds', function() + clear({env={ + NVIM_LOG_FILE='Xtest-logpath', + }}) + eq('Xtest-logpath', eval('$NVIM_LOG_FILE')) + end) + it('defaults to stdpath("data")/log if empty', function() + eq(true, mkdir(xdgdir) and mkdir(xdgdatadir)) + clear({env={ + XDG_DATA_HOME=xdgdir, + NVIM_LOG_FILE='', -- Empty is invalid. + }}) + -- server_start() calls ELOG, which tickles log_path_init(). + pcall(command, 'call serverstart(serverlist()[0])') + + eq(xdgdir..'/'..datasubdir..'/log', string.gsub(eval('$NVIM_LOG_FILE'), '\\', '/')) + end) + it('defaults to stdpath("data")/log if invalid', function() + eq(true, mkdir(xdgdir) and mkdir(xdgdatadir)) + clear({env={ + XDG_DATA_HOME=xdgdir, + NVIM_LOG_FILE='.', -- Any directory is invalid. + }}) + -- server_start() calls ELOG, which tickles log_path_init(). + pcall(command, 'call serverstart(serverlist()[0])') + + eq(xdgdir..'/'..datasubdir..'/log', string.gsub(eval('$NVIM_LOG_FILE'), '\\', '/')) + end) + it('defaults to .nvimlog if stdpath("data") is invalid', function() + clear({env={ + XDG_DATA_HOME='Xtest-missing-xdg-dir', + NVIM_LOG_FILE='.', -- Any directory is invalid. + }}) + -- server_start() calls ELOG, which tickles log_path_init(). + pcall(command, 'call serverstart(serverlist()[0])') + + eq('.nvimlog', eval('$NVIM_LOG_FILE')) + end) + end) end) describe('XDG-based defaults', function() diff --git a/test/functional/options/pastetoggle_spec.lua b/test/functional/options/pastetoggle_spec.lua new file mode 100644 index 0000000000..a1f86f73ff --- /dev/null +++ b/test/functional/options/pastetoggle_spec.lua @@ -0,0 +1,40 @@ +local helpers = require('test.functional.helpers')(after_each) + +local clear = helpers.clear +local feed = helpers.feed +local command = helpers.command +local eq = helpers.eq +local eval = helpers.eval +local sleep = helpers.sleep +local expect = helpers.expect + +describe("'pastetoggle' option", function() + before_each(function() + clear() + command('set nopaste') + end) + + it("toggles 'paste'", function() + command('set pastetoggle=a') + eq(0, eval('&paste')) + feed('a') + -- Need another key so that the vgetorpeek() function returns. + feed('j') + eq(1, eval('&paste')) + end) + + + it('does not wait for timeout', function() + command('set pastetoggle=abc') + command('set ttimeoutlen=9999999') + eq(0, eval('&paste')) + -- n.b. need <esc> to return from vgetorpeek() + feed('abc<esc>') + eq(1, eval('&paste')) + feed('ab') + sleep(10) + feed('c<esc>') + expect('bc') + eq(1, eval('&paste')) + end) +end) diff --git a/test/functional/options/shortmess_spec.lua b/test/functional/options/shortmess_spec.lua index 22e8a39b79..99a574ec46 100644 --- a/test/functional/options/shortmess_spec.lua +++ b/test/functional/options/shortmess_spec.lua @@ -1,6 +1,6 @@ local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') -local clear, execute = helpers.clear, helpers.execute +local clear, feed_command = helpers.clear, helpers.feed_command if helpers.pending_win32(pending) then return end @@ -19,7 +19,7 @@ describe("'shortmess'", function() describe('"F" flag', function() it('hides messages about the files read', function() - execute('e test') + feed_command('e test') screen:expect([[ ^ | ~ | @@ -27,8 +27,8 @@ describe("'shortmess'", function() ~ | "test" is a directory | ]]) - execute('set shortmess=F') - execute('e test') + feed_command('set shortmess=F') + feed_command('e test') screen:expect([[ ^ | ~ | diff --git a/test/functional/plugin/health_spec.lua b/test/functional/plugin/health_spec.lua index 52dc008707..3739540b09 100644 --- a/test/functional/plugin/health_spec.lua +++ b/test/functional/plugin/health_spec.lua @@ -1,6 +1,8 @@ local helpers = require('test.functional.helpers')(after_each) local plugin_helpers = require('test.functional.plugin.helpers') +local command = helpers.command + describe('health.vim', function() before_each(function() plugin_helpers.reset() @@ -8,7 +10,7 @@ describe('health.vim', function() -- health#broken#check() -- health#success1#check() -- health#success2#check() - helpers.execute("set runtimepath+=test/functional/fixtures") + command("set runtimepath+=test/functional/fixtures") end) it("reports", function() @@ -43,7 +45,7 @@ describe('health.vim', function() describe(":CheckHealth", function() it("concatenates multiple reports", function() - helpers.execute("CheckHealth success1 success2") + command("CheckHealth success1 success2") helpers.expect([[ health#success1#check @@ -62,19 +64,19 @@ describe('health.vim', function() end) it("gracefully handles broken healthcheck", function() - helpers.execute("CheckHealth broken") + command("CheckHealth broken") helpers.expect([[ health#broken#check ======================================================================== - ERROR: Failed to run healthcheck for "broken" plugin. Exception: - function health#check[20]..health#broken#check, line 1 + function health#check[21]..health#broken#check, line 1 caused an error ]]) end) it("gracefully handles invalid healthcheck", function() - helpers.execute("CheckHealth non_existent_healthcheck") + command("CheckHealth non_existent_healthcheck") helpers.expect([[ health#non_existent_healthcheck#check diff --git a/test/functional/plugin/helpers.lua b/test/functional/plugin/helpers.lua index 7580670149..2024e6ebbf 100644 --- a/test/functional/plugin/helpers.lua +++ b/test/functional/plugin/helpers.lua @@ -10,7 +10,7 @@ local function nvim_argv(shada_file) local rtp_value = ('\'%s/runtime\''):format( paths.test_source_path:gsub('\'', '\'\'')) local nvim_args = {nvim_prog, '-u', 'NORC', '-i', shada_file or 'NONE', '-N', - '--cmd', 'set shortmess+=I background=light noswapfile', + '--cmd', 'set shortmess+=I background=light noswapfile belloff= noshowcmd noruler', '--cmd', 'let &runtimepath=' .. rtp_value, '--cmd', additional_cmd, '--embed'} @@ -23,7 +23,7 @@ end local session = nil -local reset = function(...) +local function reset(...) if session then session:close() end @@ -31,7 +31,7 @@ local reset = function(...) set_session(session) end -local set_additional_cmd = function(s) +local function set_additional_cmd(s) additional_cmd = s end diff --git a/test/functional/plugin/matchparen_spec.lua b/test/functional/plugin/matchparen_spec.lua index 3e1ab70daf..51ec7e4870 100644 --- a/test/functional/plugin/matchparen_spec.lua +++ b/test/functional/plugin/matchparen_spec.lua @@ -2,7 +2,7 @@ local helpers = require('test.functional.helpers')(after_each) local plugin_helpers = require('test.functional.plugin.helpers') local Screen = require('test.functional.ui.screen') -local execute = helpers.execute +local command = helpers.command local meths = helpers.meths local feed = helpers.feed local eq = helpers.eq @@ -23,7 +23,7 @@ describe('matchparen', function() end) it('uses correct column after i_<Up>. Vim patch 7.4.1296', function() - execute('set noautoindent nosmartindent nocindent laststatus=0') + command('set noautoindent nosmartindent nocindent laststatus=0') eq(1, meths.get_var('loaded_matchparen')) feed('ivoid f_test()<cr>') feed('{<cr>') diff --git a/test/functional/plugin/shada_spec.lua b/test/functional/plugin/shada_spec.lua index b543037ae2..dbc78e63f0 100644 --- a/test/functional/plugin/shada_spec.lua +++ b/test/functional/plugin/shada_spec.lua @@ -179,6 +179,7 @@ describe('In autoload/shada.vim', function() ' + n name \'@\'', ' + rc contents ["abc", "def"]', ' + rt type CHARACTERWISE', + ' + ru is_unnamed FALSE', ' + rw block width 10', ' + sb search backward TRUE', ' + sc smartcase value FALSE', @@ -204,6 +205,7 @@ describe('In autoload/shada.vim', function() 'rt': 0, 'rw': 10, 'rc': ['abc', 'def'], + 'ru': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0}, 'n': 0x40, 'l': 10, 'c': 0, @@ -226,6 +228,8 @@ describe('In autoload/shada.vim', function() .. '0 (CHARACTERWISE), 1 (LINEWISE), 2 (BLOCKWISE)', ' + rt type 10', ' # Expected boolean', + ' + ru is_unnamed 10', + ' # Expected boolean', ' + sc smartcase value NIL', ' # Expected boolean', ' + sm magic value "TRUE"', @@ -240,6 +244,7 @@ describe('In autoload/shada.vim', function() 'sp': {'_TYPE': v:msgpack_types.string, '_VAL': ["abc"]}, 'rt': 10, 'rc': '10', + 'ru': 10, 'n': -0x40, 'l': -10, 'c': 'abc', @@ -636,6 +641,7 @@ describe('In autoload/shada.vim', function() ' # Required key missing: rc', ' + rw block width 0', ' + rt type CHARACTERWISE', + ' + ru is_unnamed FALSE', }, ([[ [{'type': 5, 'timestamp': 0, 'data': { }}] ]]):gsub('\n', '')) sd2strings_eq({ @@ -645,6 +651,7 @@ describe('In autoload/shada.vim', function() ' # Required key missing: rc', ' + rw block width 0', ' + rt type CHARACTERWISE', + ' + ru is_unnamed FALSE', }, ([[ [{'type': 5, 'timestamp': 0, 'data': { 'n': 0x20, }}] ]]):gsub('\n', '')) @@ -655,9 +662,11 @@ describe('In autoload/shada.vim', function() ' + rc contents ["abc", "def"]', ' + rw block width 0', ' + rt type CHARACTERWISE', + ' + ru is_unnamed FALSE', }, ([[ [{'type': 5, 'timestamp': 0, 'data': { 'n': 0x20, 'rc': ["abc", "def"], + 'ru': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0}, }}] ]]):gsub('\n', '')) sd2strings_eq({ 'Register with timestamp ' .. epoch .. ':', @@ -668,9 +677,11 @@ describe('In autoload/shada.vim', function() ' | - "abcdefghijklmnopqrstuvwxyz"', ' + rw block width 0', ' + rt type CHARACTERWISE', + ' + ru is_unnamed TRUE', }, ([[ [{'type': 5, 'timestamp': 0, 'data': { 'n': 0x20, 'rc': ['abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz'], + 'ru': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1}, }}] ]]):gsub('\n', '')) sd2strings_eq({ 'Register with timestamp ' .. epoch .. ':', @@ -681,6 +692,7 @@ describe('In autoload/shada.vim', function() ' | - "abcdefghijklmnopqrstuvwxyz"', ' + rw block width 0', ' + rt type CHARACTERWISE', + ' + ru is_unnamed FALSE', }, ([[ [{'type': 5, 'timestamp': 0, 'data': { 'n': 0x20, 'rc': ['abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz'], @@ -696,6 +708,7 @@ describe('In autoload/shada.vim', function() ' | - "abcdefghijklmnopqrstuvwxyz"', ' + rw block width 5', ' + rt type LINEWISE', + ' + ru is_unnamed FALSE', }, ([[ [{'type': 5, 'timestamp': 0, 'data': { 'n': 0x20, 'rc': ['abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz'], @@ -712,11 +725,14 @@ describe('In autoload/shada.vim', function() ' # Expected integer', ' + rw block width ""', ' + rt type BLOCKWISE', + ' # Expected boolean', + ' + ru is_unnamed ""', }, ([[ [{'type': 5, 'timestamp': 0, 'data': { 'n': 0x20, 'rc': ['abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz'], 'rw': "", 'rt': 2, + 'ru': "" }}] ]]):gsub('\n', '')) sd2strings_eq({ 'Register with timestamp ' .. epoch .. ':', @@ -729,11 +745,32 @@ describe('In autoload/shada.vim', function() ' # Unexpected enum value: expected one of 0 (CHARACTERWISE), ' .. '1 (LINEWISE), 2 (BLOCKWISE)', ' + rt type 10', + ' # Expected boolean', + ' + ru is_unnamed ["abc", "def"]', }, ([[ [{'type': 5, 'timestamp': 0, 'data': { 'n': 0x20, 'rc': 0, 'rw': -1, 'rt': 10, + 'ru': ['abc', 'def'], + }}] ]]):gsub('\n', '')) + sd2strings_eq({ + 'Register with timestamp ' .. epoch .. ':', + ' % Key Description Value', + ' + n name \' \'', + ' + rc contents @', + ' | - "abcdefghijklmnopqrstuvwxyz"', + ' | - "abcdefghijklmnopqrstuvwxyz"', + ' + rw block width 5', + ' + rt type LINEWISE', + ' # Expected boolean', + ' + ru is_unnamed 0', + }, ([[ [{'type': 5, 'timestamp': 0, 'data': { + 'n': 0x20, + 'rc': ['abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz'], + 'rw': 5, + 'rt': 1, + 'ru': 0, }}] ]]):gsub('\n', '')) end) @@ -2039,13 +2076,14 @@ describe('In autoload/shada.vim', function() end it('works', function() + local version = nvim('get_vvar', 'version') getbstrings_eq({{timestamp='current', type=1, value={ generator='shada.vim', - version=704, + version=version, }}}, {}) getbstrings_eq({ {timestamp='current', type=1, value={ - generator='shada.vim', version=704 + generator='shada.vim', version=version }}, {timestamp=0, type=1, value={generator='test'}} }, { @@ -2056,11 +2094,11 @@ describe('In autoload/shada.vim', function() nvim('set_var', 'shada#add_own_header', 1) getbstrings_eq({{timestamp='current', type=1, value={ generator='shada.vim', - version=704, + version=version, }}}, {}) getbstrings_eq({ {timestamp='current', type=1, value={ - generator='shada.vim', version=704 + generator='shada.vim', version=version }}, {timestamp=0, type=1, value={generator='test'}} }, { diff --git a/test/functional/provider/define_spec.lua b/test/functional/provider/define_spec.lua index b0363eb435..51a8831274 100644 --- a/test/functional/provider/define_spec.lua +++ b/test/functional/provider/define_spec.lua @@ -3,7 +3,6 @@ local eval, command, nvim = helpers.eval, helpers.command, helpers.nvim local eq, run, stop = helpers.eq, helpers.run, helpers.stop local clear = helpers.clear - local function get_prefix(sync) if sync then return 'sync' @@ -11,12 +10,10 @@ local function get_prefix(sync) return 'async' end - local function call(fn, arguments) command('call '..fn..'('..arguments..')') end - local function clear_and_init(init) return function() clear() @@ -26,7 +23,6 @@ local function clear_and_init(init) end end - local function runx(sync, handler, on_setup) local function setup_cb(...) on_setup(...) diff --git a/test/functional/provider/python3_spec.lua b/test/functional/provider/python3_spec.lua index a4e9a49c8a..aa50f53451 100644 --- a/test/functional/provider/python3_spec.lua +++ b/test/functional/provider/python3_spec.lua @@ -2,14 +2,15 @@ local helpers = require('test.functional.helpers')(after_each) local eval, command, feed = helpers.eval, helpers.command, helpers.feed local eq, clear, insert = helpers.eq, helpers.clear, helpers.insert local expect, write_file = helpers.expect, helpers.write_file +local feed_command = helpers.feed_command +local missing_provider = helpers.missing_provider do clear() - command('let [g:interp, g:errors] = provider#pythonx#Detect(3)') - local errors = eval('g:errors') - if errors ~= '' then + local err = missing_provider('python3') + if err then pending( - 'Python 3 (or the Python 3 neovim module) is broken or missing:\n' .. errors, + 'Python 3 (or the Python 3 neovim module) is broken or missing:\n' .. err, function() end) return end @@ -30,6 +31,15 @@ describe('python3 commands and functions', function() eq({100, 0}, eval('g:set_by_python3')) end) + it('does not truncate error message <1 MB', function() + -- XXX: Python limits the error name to 200 chars, so this test is + -- mostly bogus. + local very_long_symbol = string.rep('a', 1200) + feed_command(':silent! py3 print('..very_long_symbol..' b)') + -- Truncated error message would not contain this (last) line. + eq('SyntaxError: invalid syntax', eval('v:errmsg')) + end) + it('python3_execute with nested commands', function() command([[python3 vim.command('python3 vim.command("python3 vim.command(\'let set_by_nested_python3 = 555\')")')]]) eq(555, eval('g:set_by_nested_python3')) diff --git a/test/functional/provider/python_spec.lua b/test/functional/provider/python_spec.lua index 94dfa90ea8..25f5e0a6d0 100644 --- a/test/functional/provider/python_spec.lua +++ b/test/functional/provider/python_spec.lua @@ -12,14 +12,14 @@ local command = helpers.command local exc_exec = helpers.exc_exec local write_file = helpers.write_file local curbufmeths = helpers.curbufmeths +local missing_provider = helpers.missing_provider do clear() - command('let [g:interp, g:errors] = provider#pythonx#Detect(2)') - local errors = meths.get_var('errors') - if errors ~= '' then + local err = missing_provider('python') + if err then pending( - 'Python 2 (or the Python 2 neovim module) is broken or missing:\n' .. errors, + 'Python 2 (or the Python 2 neovim module) is broken or missing:\n' .. err, function() end) return end diff --git a/test/functional/provider/ruby_spec.lua b/test/functional/provider/ruby_spec.lua index 7b0e17688d..9f5ef3b3fc 100644 --- a/test/functional/provider/ruby_spec.lua +++ b/test/functional/provider/ruby_spec.lua @@ -10,13 +10,11 @@ local expect = helpers.expect local command = helpers.command local write_file = helpers.write_file local curbufmeths = helpers.curbufmeths +local missing_provider = helpers.missing_provider do clear() - command('let g:prog = provider#ruby#Detect()') - local prog = meths.get_var('prog') - - if prog == '' then + if missing_provider('ruby') then pending( "Cannot find the neovim RubyGem. Try :CheckHealth", function() end) diff --git a/test/functional/shada/errors_spec.lua b/test/functional/shada/errors_spec.lua index 2b6b26b433..66c8c4ad2f 100644 --- a/test/functional/shada/errors_spec.lua +++ b/test/functional/shada/errors_spec.lua @@ -510,4 +510,22 @@ $ .. '\nE574: Failed to write variable L', redir_exec('wshada')) end) + + it('errors with too large items', function() + wshada({ + 1, 206, 70, 90, 31, 179, 86, 133, 169, 103, 101, 110, 101, 114, 97, + 116, 111, 114, 196, 4, 145, 145, 145, 145, 145, 145, 96, 96, 96, 96, + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, + 96, 96, 145, 145, 145, 145, 111, 110, 196, 25, 78, 86, 73, 77, 32, + 118, 1, 46, 50, 46, 48, 45, 51, 48, 51, 45, 103, 98, 54, 55, + 52, 102, 100, 50, 99, 169, 109, 97, 120, 95, 107, 98, 121, 116, 101, + 10, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, + 207, 207, 207, 207, 207, 207, 207, 207, 16, 8, 206, 89, 90, 30, 253, + 35, 129, 161, 102, 196, 30, 47, 100, 101, 118, 47, 115, 104, 109, 47, + 102, 117, 122, 122, 105, 110, 103, 45, 110, 118, 105, 109, 45, 115, 104, + 97, 100, 97, 47, 108, 115, 2, 206, 89, 90, 30, 251, 13, 130, 162, + 115, 112, 196, 3, 102, 111, 111, 162, 115, 99, 195, 3, 146, 10, 0, + }) + eq('Vim(rshada):E576: Error while reading ShaDa file: there is an item at position 93 that is stated to be too long', exc_exec(sdrcmd())) + end) end) diff --git a/test/functional/shada/registers_spec.lua b/test/functional/shada/registers_spec.lua index fc812f799c..71af14aba8 100644 --- a/test/functional/shada/registers_spec.lua +++ b/test/functional/shada/registers_spec.lua @@ -148,4 +148,40 @@ describe('ShaDa support code', function() eq({{'\171ยซ'}, 'v'}, getreg('e')) end) + it('has a blank unnamed register if it wasn\'t set and register 0 is empty', + function() + setreg('1', {'one'}, 'c') + setreg('2', {'two'}, 'c') + setreg('a', {'a'}, 'c') + nvim_command('qall') + reset() + eq({{}, ''}, getreg('0')) + eq({{'one'}, 'v'}, getreg('1')) + eq({{}, ''}, getreg('"')) + eq({{'a'}, 'v'}, getreg('a')) + end) + + it('defaults the unnamed register to register 0 if it wasn\'t set', + function() + setreg('0', {'zero'}, 'c') + setreg('1', {'one'}, 'c') + setreg('2', {'two'}, 'c') + nvim_command('qall') + reset() + eq({{'zero'}, 'v'}, getreg('0')) + eq({{'one'}, 'v'}, getreg('1')) + eq({{'zero'}, 'v'}, getreg('"')) + end) + + it('remembers which register was the unnamed register when loading', + function() + setreg('0', {'zero'}, 'c') + setreg('1', {'one'}, 'cu') + setreg('2', {'two'}, 'c') + nvim_command('qall') + reset() + eq({{'zero'}, 'v'}, getreg('0')) + eq({{'one'}, 'v'}, getreg('1')) + eq({{'one'}, 'v'}, getreg('"')) + end) end) diff --git a/test/functional/shada/shada_spec.lua b/test/functional/shada/shada_spec.lua index 32598fc399..ca44026852 100644 --- a/test/functional/shada/shada_spec.lua +++ b/test/functional/shada/shada_spec.lua @@ -180,8 +180,7 @@ describe('ShaDa support code', function() nvim_command('undo') nvim_command('set shada+=%') nvim_command('wshada! ' .. shada_fname) - local readme_fname = paths.test_source_path .. '/README.md' - readme_fname = helpers.eval( 'resolve("' .. readme_fname .. '")' ) + local readme_fname = funcs.resolve(paths.test_source_path) .. '/README.md' eq({[7]=1, [8]=2, [9]=1, [10]=4, [11]=1}, find_file(readme_fname)) nvim_command('set shada+=r~') nvim_command('wshada! ' .. shada_fname) @@ -189,7 +188,8 @@ describe('ShaDa support code', function() nvim_command('set shada-=r~') nvim_command('wshada! ' .. shada_fname) eq({[7]=1, [8]=2, [9]=1, [10]=4, [11]=1}, find_file(readme_fname)) - nvim_command('set shada+=r' .. paths.test_source_path) + nvim_command('set shada+=r' .. funcs.escape( + funcs.escape(paths.test_source_path, '$~'), ' "\\,')) nvim_command('wshada! ' .. shada_fname) eq({}, find_file(readme_fname)) end) diff --git a/test/functional/spell/spellfile_spec.lua b/test/functional/spell/spellfile_spec.lua new file mode 100644 index 0000000000..afd2c1bce4 --- /dev/null +++ b/test/functional/spell/spellfile_spec.lua @@ -0,0 +1,110 @@ +local helpers = require('test.functional.helpers')(after_each) +local lfs = require('lfs') + +local eq = helpers.eq +local clear = helpers.clear +local meths = helpers.meths +local exc_exec = helpers.exc_exec +local rmdir = helpers.rmdir +local write_file = helpers.write_file + +local testdir = 'Xtest-functional-spell-spellfile.d' + +describe('spellfile', function() + before_each(function() + clear() + rmdir(testdir) + lfs.mkdir(testdir) + lfs.mkdir(testdir .. '/spell') + end) + after_each(function() + rmdir(testdir) + end) + -- โ Magic string (#VIMSPELLMAGIC) + -- โ โ Spell file version (#VIMSPELLVERSION) + local spellheader = 'VIMspell\050' + it('errors out when prefcond section is truncated', function() + meths.set_option('runtimepath', testdir) + write_file(testdir .. '/spell/en.ascii.spl', + -- โ Section identifier (#SN_PREFCOND) + -- โ โ Section flags (#SNF_REQUIRED or zero) + -- โ โ โ Section length (4 bytes, MSB first) + spellheader .. '\003\001\000\000\000\003' + -- โ Number of regexes in section (2 bytes, MSB first) + -- โ โ Condition length (1 byte) + -- โ โ โ Condition regex (missing!) + .. '\000\001\001') + meths.set_option('spelllang', 'en') + eq('Vim(set):E758: Truncated spell file', + exc_exec('set spell')) + end) + it('errors out when prefcond regexp contains NUL byte', function() + meths.set_option('runtimepath', testdir) + write_file(testdir .. '/spell/en.ascii.spl', + -- โ Section identifier (#SN_PREFCOND) + -- โ โ Section flags (#SNF_REQUIRED or zero) + -- โ โ โ Section length (4 bytes, MSB first) + spellheader .. '\003\001\000\000\000\008' + -- โ Number of regexes in section (2 bytes, MSB first) + -- โ โ Condition length (1 byte) + -- โ โ โ Condition regex + -- โ โ โ โ End of sections marker + .. '\000\001\005ab\000cd\255' + -- โ LWORDTREE tree length (4 bytes) + -- โ โ KWORDTREE tree length (4 bytes) + -- โ โ โ PREFIXTREE tree length + .. '\000\000\000\000\000\000\000\000\000\000\000\000') + meths.set_option('spelllang', 'en') + eq('Vim(set):E759: Format error in spell file', + exc_exec('set spell')) + end) + it('errors out when region contains NUL byte', function() + meths.set_option('runtimepath', testdir) + write_file(testdir .. '/spell/en.ascii.spl', + -- โ Section identifier (#SN_REGION) + -- โ โ Section flags (#SNF_REQUIRED or zero) + -- โ โ โ Section length (4 bytes, MSB first) + spellheader .. '\000\001\000\000\000\008' + -- โ Regions โ End of sections marker + .. '01234\00067\255' + -- โ LWORDTREE tree length (4 bytes) + -- โ โ KWORDTREE tree length (4 bytes) + -- โ โ โ PREFIXTREE tree length + .. '\000\000\000\000\000\000\000\000\000\000\000\000') + meths.set_option('spelllang', 'en') + eq('Vim(set):E759: Format error in spell file', + exc_exec('set spell')) + end) + it('errors out when SAL section contains NUL byte', function() + meths.set_option('runtimepath', testdir) + write_file(testdir .. '/spell/en.ascii.spl', + -- โ Section identifier (#SN_SAL) + -- โ โ Section flags (#SNF_REQUIRED or zero) + -- โ โ โ Section length (4 bytes, MSB first) + spellheader .. '\005\001\000\000\000\008' + -- โ salflags + -- โ โ salcount (2 bytes, MSB first) + -- โ โ โ salfromlen (1 byte) + -- โ โ โ โ Special character + -- โ โ โ โโ salfrom (should not contain NUL) + -- โ โ โ โโ โ saltolen + -- โ โ โ โโ โ โ salto + -- โ โ โ โโ โ โโ End of sections marker + .. '\000\000\001\0024\000\0017\255' + -- โ LWORDTREE tree length (4 bytes) + -- โ โ KWORDTREE tree length (4 bytes) + -- โ โ โ PREFIXTREE tree length + .. '\000\000\000\000\000\000\000\000\000\000\000\000') + meths.set_option('spelllang', 'en') + eq('Vim(set):E759: Format error in spell file', + exc_exec('set spell')) + end) + it('errors out when spell header contains NUL bytes', function() + meths.set_option('runtimepath', testdir) + write_file(testdir .. '/spell/en.ascii.spl', + spellheader:sub(1, -3) .. '\000\000') + meths.set_option('spelllang', 'en') + eq('Vim(set):E757: This does not look like a spell file', + exc_exec('set spell')) + end) +end) diff --git a/test/functional/terminal/api_spec.lua b/test/functional/terminal/api_spec.lua index 045bdb0749..e28cc03597 100644 --- a/test/functional/terminal/api_spec.lua +++ b/test/functional/terminal/api_spec.lua @@ -12,7 +12,7 @@ describe('api', function() helpers.clear() os.remove(socket_name) screen = child_session.screen_setup(0, '["'..helpers.nvim_prog - ..'", "-u", "NONE", "-i", "NONE", "--cmd", "set noswapfile"]') + ..'", "-u", "NONE", "-i", "NONE", "--cmd", "'..helpers.nvim_set..'"]') end) after_each(function() os.remove(socket_name) @@ -28,7 +28,7 @@ describe('api', function() {4:~ }| {4:~ }| {4:~ }| - {5:[No Name] }| + {4:~ }| ]]..socket_name..[[ | {3:-- TERMINAL --} | ]]) @@ -43,7 +43,7 @@ describe('api', function() {4:~ }| {4:~ }| {4:~ }| - {5:[No Name] [+] }| + {4:~ }| {3:-- INSERT --} | {3:-- TERMINAL --} | ]]) @@ -59,7 +59,7 @@ describe('api', function() [socket 1] this is more t{4: }| han 25 columns {4: }| [socket 2] input{1: } {4: }| - {5:[No Name] [+] }| + {4:~ }| {3:-- INSERT --} | {3:-- TERMINAL --} | ]]) diff --git a/test/functional/terminal/buffer_spec.lua b/test/functional/terminal/buffer_spec.lua index cecd67d7fa..4ce33fef7b 100644 --- a/test/functional/terminal/buffer_spec.lua +++ b/test/functional/terminal/buffer_spec.lua @@ -2,17 +2,16 @@ local helpers = require('test.functional.helpers')(after_each) local thelpers = require('test.functional.terminal.helpers') local feed, clear, nvim = helpers.feed, helpers.clear, helpers.nvim local wait = helpers.wait -local eval, execute, source = helpers.eval, helpers.execute, helpers.source +local eval, feed_command, source = helpers.eval, helpers.feed_command, helpers.source local eq, neq = helpers.eq, helpers.neq - -if helpers.pending_win32(pending) then return end +local write_file = helpers.write_file describe('terminal buffer', function() local screen before_each(function() clear() - execute('set modifiable swapfile undolevels=20') + feed_command('set modifiable swapfile undolevels=20') wait() screen = thelpers.screen_setup() end) @@ -50,11 +49,11 @@ describe('terminal buffer', function() feed('<c-\\><c-n>') screen:expect([[ tty ready | - {2: } | + {2:^ } | + | | | | - ^ | | ]]) end) @@ -74,18 +73,18 @@ describe('terminal buffer', function() feed('<c-\\><c-n>dd') screen:expect([[ tty ready | - {2: } | + {2:^ } | + | | | | - ^ | {8:E21: Cannot make changes, 'modifiable' is off} | ]]) end) it('sends data to the terminal when the "put" operator is used', function() feed('<c-\\><c-n>gg"ayj') - execute('let @a = "appended " . @a') + feed_command('let @a = "appended " . @a') feed('"ap"ap') screen:expect([[ ^tty ready | @@ -111,8 +110,8 @@ describe('terminal buffer', function() it('sends data to the terminal when the ":put" command is used', function() feed('<c-\\><c-n>gg"ayj') - execute('let @a = "appended " . @a') - execute('put a') + feed_command('let @a = "appended " . @a') + feed_command('put a') screen:expect([[ ^tty ready | appended tty ready | @@ -123,7 +122,7 @@ describe('terminal buffer', function() :put a | ]]) -- line argument is only used to move the cursor - execute('6put a') + feed_command('6put a') screen:expect([[ tty ready | appended tty ready | @@ -146,7 +145,7 @@ describe('terminal buffer', function() {4:~ }| :bd! | ]]) - execute('bnext') + feed_command('bnext') screen:expect([[ ^ | {4:~ }| @@ -159,9 +158,10 @@ describe('terminal buffer', function() end) it('handles loss of focus gracefully', function() + if helpers.pending_win32(pending) then return end -- Change the statusline to avoid printing the file name, which varies. nvim('set_option', 'statusline', '==========') - execute('set laststatus=0') + feed_command('set laststatus=0') -- Save the buffer number of the terminal for later testing. local tbuf = eval('bufnr("%")') @@ -190,20 +190,37 @@ describe('terminal buffer', function() ]]) neq(tbuf, eval('bufnr("%")')) - execute('quit!') -- Should exit the new window, not the terminal. + feed_command('quit!') -- Should exit the new window, not the terminal. eq(tbuf, eval('bufnr("%")')) - execute('set laststatus=1') -- Restore laststatus to the default. + feed_command('set laststatus=1') -- Restore laststatus to the default. end) it('term_close() use-after-free #4393', function() - if eval("executable('yes')") == 0 then - pending('missing "yes" command') - return - end - execute('terminal yes') + feed_command('terminal yes') feed([[<C-\><C-n>]]) - execute('bdelete!') + feed_command('bdelete!') end) end) +describe('No heap-buffer-overflow when using', function() + local testfilename = 'Xtestfile-functional-terminal-buffers_spec' + + before_each(function() + write_file(testfilename, "aaaaaaaaaaaaaaaaaaaaaaaaaaaa") + end) + + after_each(function() + os.remove(testfilename) + end) + + it('termopen(echo) #3161', function() + feed_command('edit ' .. testfilename) + -- Move cursor away from the beginning of the line + feed('$') + -- Let termopen() modify the buffer + feed_command('call termopen("echo")') + wait() + feed_command('bdelete!') + end) +end) diff --git a/test/functional/terminal/cursor_spec.lua b/test/functional/terminal/cursor_spec.lua index 1953022a7a..d49f1bfc23 100644 --- a/test/functional/terminal/cursor_spec.lua +++ b/test/functional/terminal/cursor_spec.lua @@ -2,12 +2,11 @@ local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') local thelpers = require('test.functional.terminal.helpers') local feed, clear, nvim = helpers.feed, helpers.clear, helpers.nvim -local nvim_dir, execute = helpers.nvim_dir, helpers.execute +local nvim_dir, command = helpers.nvim_dir, helpers.command +local feed_command = helpers.feed_command local hide_cursor = thelpers.hide_cursor local show_cursor = thelpers.show_cursor -if helpers.pending_win32(pending) then return end - describe('terminal cursor', function() local screen @@ -34,11 +33,11 @@ describe('terminal cursor', function() feed('<c-\\><c-n>') screen:expect([[ tty ready | - {2: } | + {2:^ } | + | | | | - ^ | | ]]) end) @@ -51,25 +50,26 @@ describe('terminal cursor', function() it('is positioned correctly when unfocused', function() screen:expect([[ {7: 1 }tty ready | - {7: 2 }{2: } | + {7: 2 }{2:^ } | {7: 3 } | {7: 4 } | {7: 5 } | - {7: 6 }^ | + {7: 6 } | :set number | ]]) end) - pending('is positioned correctly when focused', function() + it('is positioned correctly when focused', function() feed('i') + helpers.wait() screen:expect([[ - 1 tty ready | - 2 {1: } | - 3 | - 4 | - 5 | - 6 | - -- TERMINAL -- | + {7: 1 }tty ready | + {7: 2 }{1: } | + {7: 3 } | + {7: 4 } | + {7: 5 } | + {7: 6 } | + {3:-- TERMINAL --} | ]]) end) end) @@ -101,21 +101,21 @@ describe('terminal cursor', function() hide_cursor() screen:expect([[ tty ready | + ^ | | | | | - ^ | | ]]) show_cursor() screen:expect([[ tty ready | - {2: } | + {2:^ } | + | | | | - ^ | | ]]) end) @@ -137,7 +137,8 @@ describe('cursor with customized highlighting', function() [3] = {bold = true}, }) screen:attach({rgb=false}) - execute('call termopen(["'..nvim_dir..'/tty-test"]) | startinsert') + command('call termopen(["'..nvim_dir..'/tty-test"])') + feed_command('startinsert') end) it('overrides the default highlighting', function() @@ -153,11 +154,11 @@ describe('cursor with customized highlighting', function() feed('<c-\\><c-n>') screen:expect([[ tty ready | - {2: } | + {2:^ } | + | | | | - ^ | | ]]) end) diff --git a/test/functional/terminal/edit_spec.lua b/test/functional/terminal/edit_spec.lua index 8edcfa56b7..d2b2d8a60c 100644 --- a/test/functional/terminal/edit_spec.lua +++ b/test/functional/terminal/edit_spec.lua @@ -31,45 +31,38 @@ describe(':edit term://*', function() eq(termopen_runs[1], termopen_runs[1]:match('^term://.//%d+:$')) end) - it('runs TermOpen early enough to respect terminal_scrollback_buffer_size', function() + it("runs TermOpen early enough to set buffer-local 'scrollback'", function() local columns, lines = 20, 4 local scr = get_screen(columns, lines) local rep = 'a' meths.set_option('shellcmdflag', 'REP ' .. rep) - local rep_size = rep:byte() + local rep_size = rep:byte() -- 'a' => 97 local sb = 10 - local gsb = 20 - meths.set_var('terminal_scrollback_buffer_size', gsb) - command('autocmd TermOpen * :let b:terminal_scrollback_buffer_size = ' - .. tostring(sb)) + command('autocmd TermOpen * :setlocal scrollback='..tostring(sb) + ..'|call feedkeys("G", "n")') command('edit term://foobar') + local bufcontents = {} local winheight = curwinmeths.get_height() - -- I have no idea why there is + 4 needed. But otherwise it works fine with - -- different scrollbacks. - local shift = -4 - local buf_cont_start = rep_size - 1 - sb - winheight - shift - local bufline = function(i) return ('%d: foobar'):format(i) end + local buf_cont_start = rep_size - sb - winheight + 2 for i = buf_cont_start,(rep_size - 1) do - bufcontents[#bufcontents + 1] = bufline(i) + bufcontents[#bufcontents + 1] = ('%d: foobar'):format(i) end bufcontents[#bufcontents + 1] = '' bufcontents[#bufcontents + 1] = '[Process exited 0]' - -- Do not ask me why displayed screen is one line *before* buffer - -- contents: buffer starts with 87:, screen with 86:. + local exp_screen = '\n' - local did_cursor = false - for i = 0,(winheight - 1) do - local line = bufline(buf_cont_start + i - 1) + for i = 1,(winheight - 1) do + local line = bufcontents[#bufcontents - winheight + i] exp_screen = (exp_screen - .. (did_cursor and '' or '^') .. line .. (' '):rep(columns - #line) .. '|\n') - did_cursor = true end - exp_screen = exp_screen .. (' '):rep(columns) .. '|\n' + exp_screen = exp_screen..'^[Process exited 0] |\n' + + exp_screen = exp_screen..(' '):rep(columns)..'|\n' scr:expect(exp_screen) - eq(bufcontents, curbufmeths.get_lines(1, -1, true)) + eq(bufcontents, curbufmeths.get_lines(0, -1, true)) end) end) diff --git a/test/functional/terminal/ex_terminal_spec.lua b/test/functional/terminal/ex_terminal_spec.lua index 4247be0417..7522f073c4 100644 --- a/test/functional/terminal/ex_terminal_spec.lua +++ b/test/functional/terminal/ex_terminal_spec.lua @@ -2,11 +2,11 @@ local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') local clear, wait, nvim = helpers.clear, helpers.wait, helpers.nvim local nvim_dir, source, eq = helpers.nvim_dir, helpers.source, helpers.eq -local execute, eval = helpers.execute, helpers.eval - -if helpers.pending_win32(pending) then return end +local feed_command, eval = helpers.feed_command, helpers.eval +local iswin = helpers.iswin describe(':terminal', function() + if helpers.pending_win32(pending) then return end local screen before_each(function() @@ -20,26 +20,34 @@ describe(':terminal', function() source([[ echomsg "msg1" echomsg "msg2" + echomsg "msg3" ]]) -- Invoke a command that emits frequent terminal activity. - execute([[terminal while true; do echo X; done]]) + feed_command([[terminal while true; do echo X; done]]) helpers.feed([[<C-\><C-N>]]) + wait() + screen:sleep(10) -- Let some terminal activity happen. + feed_command("messages") screen:expect([[ - X | - X | - ^X | - | - ]]) - helpers.sleep(10) -- Let some terminal activity happen. - execute("messages") - screen:expect([[ - X | msg1 | msg2 | + msg3 | Press ENTER or type command to continue^ | ]]) end) + it("in normal-mode :split does not move cursor", function() + feed_command([[terminal while true; do echo foo; sleep .1; done]]) + helpers.feed([[<C-\><C-N>M]]) -- move cursor away from last line + wait() + eq(3, eval("line('$')")) -- window height + eq(2, eval("line('.')")) -- cursor is in the middle + feed_command('vsplit') + eq(2, eval("line('.')")) -- cursor stays where we put it + feed_command('split') + eq(2, eval("line('.')")) -- cursor stays where we put it + end) + end) describe(':terminal (with fake shell)', function() @@ -57,17 +65,41 @@ describe(':terminal (with fake shell)', function() -- Invokes `:terminal {cmd}` using a fake shell (shell-test.c) which prints -- the {cmd} and exits immediately . local function terminal_with_fake_shell(cmd) - execute("terminal "..(cmd and cmd or "")) + feed_command("terminal "..(cmd and cmd or "")) end it('with no argument, acts like termopen()', function() terminal_with_fake_shell() wait() screen:expect([[ - ready $ | + ^ready $ | + [Process exited 0] | + | + :terminal | + ]]) + end) + + it("with no argument, and 'shell' is set to empty string", function() + nvim('set_option', 'shell', '') + terminal_with_fake_shell() + wait() + screen:expect([[ + ^ | + ~ | + ~ | + E91: 'shell' option is empty | + ]]) + end) + + it("with no argument, but 'shell' has arguments, acts like termopen()", function() + nvim('set_option', 'shell', nvim_dir..'/shell-test -t jeff') + terminal_with_fake_shell() + wait() + screen:expect([[ + ^jeff $ | [Process exited 0] | | - -- TERMINAL -- | + :terminal | ]]) end) @@ -75,10 +107,22 @@ describe(':terminal (with fake shell)', function() terminal_with_fake_shell('echo hi') wait() screen:expect([[ - ready $ echo hi | + ^ready $ echo hi | + | + [Process exited 0] | + :terminal echo hi | + ]]) + end) + + it("executes a given command through the shell, when 'shell' has arguments", function() + nvim('set_option', 'shell', nvim_dir..'/shell-test -t jeff') + terminal_with_fake_shell('echo hi') + wait() + screen:expect([[ + ^jeff $ echo hi | | [Process exited 0] | - -- TERMINAL -- | + :terminal echo hi | ]]) end) @@ -86,10 +130,10 @@ describe(':terminal (with fake shell)', function() terminal_with_fake_shell([[echo 'hello' \ "world"]]) wait() screen:expect([[ - ready $ echo 'hello' \ "world" | + ^ready $ echo 'hello' \ "world" | | [Process exited 0] | - -- TERMINAL -- | + :terminal echo 'hello' \ "world" | ]]) end) @@ -112,4 +156,43 @@ describe(':terminal (with fake shell)', function() eq(2, eval("1+1")) -- Still alive? end) + it('works with findfile()', function() + feed_command('terminal') + eq('term://', string.match(eval('bufname("%")'), "^term://")) + eq('scripts/shadacat.py', eval('findfile("scripts/shadacat.py", ".")')) + end) + + it('works with :find', function() + terminal_with_fake_shell() + wait() + screen:expect([[ + ^ready $ | + [Process exited 0] | + | + :terminal | + ]]) + eq('term://', string.match(eval('bufname("%")'), "^term://")) + helpers.feed([[<C-\><C-N>]]) + feed_command([[find */shadacat.py]]) + if iswin() then + eq('scripts\\shadacat.py', eval('bufname("%")')) + else + eq('scripts/shadacat.py', eval('bufname("%")')) + end + end) + + it('works with gf', function() + terminal_with_fake_shell([[echo "scripts/shadacat.py"]]) + screen:expect([[ + ^ready $ echo "scripts/shadacat.py" | + | + [Process exited 0] | + :terminal echo "scripts/shadacat.py" | + ]]) + helpers.feed([[<C-\><C-N>]]) + eq('term://', string.match(eval('bufname("%")'), "^term://")) + helpers.feed([[ggf"lgf]]) + eq('scripts/shadacat.py', eval('bufname("%")')) + end) + end) diff --git a/test/functional/terminal/helpers.lua b/test/functional/terminal/helpers.lua index ae5e6d4b1f..bd24b9785d 100644 --- a/test/functional/terminal/helpers.lua +++ b/test/functional/terminal/helpers.lua @@ -1,7 +1,7 @@ local helpers = require('test.functional.helpers')(nil) local Screen = require('test.functional.ui.screen') local nvim_dir = helpers.nvim_dir -local execute, nvim, wait = helpers.execute, helpers.nvim, helpers.wait +local feed_command, nvim = helpers.feed_command, helpers.nvim local function feed_data(data) nvim('set_var', 'term_data', data) @@ -33,14 +33,15 @@ local function disable_mouse() feed_termcode('[?1002l') end local default_command = '["'..nvim_dir..'/tty-test'..'"]' +local function screen_setup(extra_rows, command, cols) + extra_rows = extra_rows and extra_rows or 0 + command = command and command or default_command + cols = cols and cols or 50 -local function screen_setup(extra_height, command) nvim('command', 'highlight TermCursor cterm=reverse') nvim('command', 'highlight TermCursorNC ctermbg=11') - nvim('set_var', 'terminal_scrollback_buffer_size', 10) - if not extra_height then extra_height = 0 end - if not command then command = default_command end - local screen = Screen.new(50, 7 + extra_height) + + local screen = Screen.new(cols, 7 + extra_rows) screen:set_default_attr_ids({ [1] = {reverse = true}, -- focused cursor [2] = {background = 11}, -- unfocused cursor @@ -55,31 +56,42 @@ local function screen_setup(extra_height, command) }) screen:attach({rgb=false}) - -- tty-test puts the terminal into raw mode and echoes all input. tests are - -- done by feeding it with terminfo codes to control the display and - -- verifying output with screen:expect. - execute('enew | call termopen('..command..') | startinsert') + + feed_command('enew | call termopen('..command..')') + nvim('input', '<CR>') + local vim_errmsg = nvim('eval', 'v:errmsg') + if vim_errmsg and "" ~= vim_errmsg then + error(vim_errmsg) + end + + feed_command('setlocal scrollback=10') + feed_command('startinsert') + + -- tty-test puts the terminal into raw mode and echoes input. Tests work by + -- feeding termcodes to control the display and asserting by screen:expect. if command == default_command then - -- wait for "tty ready" to be printed before each test or the terminal may - -- still be in canonical mode(will echo characters for example) - -- - local empty_line = ' ' + -- Wait for "tty ready" to be printed before each test or the terminal may + -- still be in canonical mode (will echo characters for example). + local empty_line = (' '):rep(cols + 1) local expected = { - 'tty ready ', - '{1: } ', + 'tty ready'..(' '):rep(cols - 8), + '{1: }' ..(' '):rep(cols), empty_line, empty_line, empty_line, empty_line, } - for _ = 1, extra_height do + for _ = 1, extra_rows do table.insert(expected, empty_line) end - table.insert(expected, '{3:-- TERMINAL --} ') + table.insert(expected, '{3:-- TERMINAL --}' .. ((' '):rep(cols - 13))) screen:expect(table.concat(expected, '\n')) else - wait() + -- This eval also acts as a wait(). + if 0 == nvim('eval', "exists('b:terminal_job_id')") then + error("terminal job failed to start") + end end return screen end diff --git a/test/functional/terminal/highlight_spec.lua b/test/functional/terminal/highlight_spec.lua index 0fe463401e..fddc0bbb71 100644 --- a/test/functional/terminal/highlight_spec.lua +++ b/test/functional/terminal/highlight_spec.lua @@ -2,11 +2,9 @@ local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') local thelpers = require('test.functional.terminal.helpers') local feed, clear, nvim = helpers.feed, helpers.clear, helpers.nvim -local nvim_dir, execute = helpers.nvim_dir, helpers.execute +local nvim_dir, command = helpers.nvim_dir, helpers.command local eq, eval = helpers.eq, helpers.eval -if helpers.pending_win32(pending) then return end - describe('terminal window highlighting', function() local screen @@ -27,7 +25,8 @@ describe('terminal window highlighting', function() [11] = {background = 11}, }) screen:attach({rgb=false}) - execute('enew | call termopen(["'..nvim_dir..'/tty-test"]) | startinsert') + command('enew | call termopen(["'..nvim_dir..'/tty-test"])') + feed('i') screen:expect([[ tty ready | {10: } | @@ -54,6 +53,7 @@ describe('terminal window highlighting', function() end) local function pass_attrs() + if helpers.pending_win32(pending) then return end screen:expect(sub([[ tty ready | {NUM:text}text{10: } | @@ -68,6 +68,7 @@ describe('terminal window highlighting', function() it('will pass the corresponding attributes', pass_attrs) it('will pass the corresponding attributes on scrollback', function() + if helpers.pending_win32(pending) then return end pass_attrs() local lines = {} for i = 1, 8 do @@ -130,7 +131,8 @@ describe('terminal window highlighting with custom palette', function() }) screen:attach({rgb=true}) nvim('set_var', 'terminal_color_3', '#123456') - execute('enew | call termopen(["'..nvim_dir..'/tty-test"]) | startinsert') + command('enew | call termopen(["'..nvim_dir..'/tty-test"])') + feed('i') screen:expect([[ tty ready | {7: } | @@ -143,6 +145,7 @@ describe('terminal window highlighting with custom palette', function() end) it('will use the custom color', function() + if helpers.pending_win32(pending) then return end thelpers.set_fg(3) thelpers.feed_data('text') thelpers.clear_attrs() @@ -164,9 +167,9 @@ describe('synIDattr()', function() before_each(function() clear() screen = Screen.new(50, 7) - execute('highlight Normal ctermfg=252 guifg=#ff0000 guibg=Black') + command('highlight Normal ctermfg=252 guifg=#ff0000 guibg=Black') -- Salmon #fa8072 Maroon #800000 - execute('highlight Keyword ctermfg=79 guifg=Salmon guisp=Maroon') + command('highlight Keyword ctermfg=79 guifg=Salmon guisp=Maroon') end) it('returns cterm-color if RGB-capable UI is _not_ attached', function() @@ -213,8 +216,8 @@ describe('fg/bg special colors', function() before_each(function() clear() screen = Screen.new(50, 7) - execute('highlight Normal ctermfg=145 ctermbg=16 guifg=#ff0000 guibg=Black') - execute('highlight Visual ctermfg=bg ctermbg=fg guifg=bg guibg=fg guisp=bg') + command('highlight Normal ctermfg=145 ctermbg=16 guifg=#ff0000 guibg=Black') + command('highlight Visual ctermfg=bg ctermbg=fg guifg=bg guibg=fg guisp=bg') end) it('resolve to "Normal" values', function() @@ -251,7 +254,7 @@ describe('fg/bg special colors', function() screen:attach({rgb=true}) local new_guibg = '#282c34' local new_guifg = '#abb2bf' - execute('highlight Normal guifg='..new_guifg..' guibg='..new_guibg) + command('highlight Normal guifg='..new_guifg..' guibg='..new_guibg) eq(new_guibg, eval('synIDattr(hlID("Visual"), "fg#")')) eq(new_guifg, eval('synIDattr(hlID("Visual"), "bg#")')) eq(new_guibg, eval('synIDattr(hlID("Visual"), "sp#")')) diff --git a/test/functional/terminal/mouse_spec.lua b/test/functional/terminal/mouse_spec.lua index ecb0b2beb0..29c62d7be7 100644 --- a/test/functional/terminal/mouse_spec.lua +++ b/test/functional/terminal/mouse_spec.lua @@ -1,11 +1,9 @@ local helpers = require('test.functional.helpers')(after_each) local thelpers = require('test.functional.terminal.helpers') -local clear = helpers.clear +local clear, eq, eval = helpers.clear, helpers.eq, helpers.eval local feed, nvim = helpers.feed, helpers.nvim local feed_data = thelpers.feed_data -if helpers.pending_win32(pending) then return end - describe('terminal mouse', function() local screen @@ -38,31 +36,17 @@ describe('terminal mouse', function() end) describe('when the terminal has focus', function() - it('will exit focus when scrolled', function() - feed('<MouseDown><0,0>') - screen:expect([[ - line23 | - line24 | - line25 | - line26 | - line27 | - ^line28 | - | - ]]) + it('will exit focus on mouse-scroll', function() + eq('t', eval('mode()')) + feed('<ScrollWheelUp><0,0>') + eq('n', eval('mode()')) end) - it('will exit focus after <C-\\>, then scrolled', function() + it('will exit focus on <C-\\> + mouse-scroll', function() + eq('t', eval('mode()')) feed('<C-\\>') - feed('<MouseDown><0,0>') - screen:expect([[ - line23 | - line24 | - line25 | - line26 | - line27 | - ^line28 | - | - ]]) + feed('<ScrollWheelUp><0,0>') + eq('n', eval('mode()')) end) describe('with mouse events enabled by the program', function() @@ -81,6 +65,7 @@ describe('terminal mouse', function() end) it('will forward mouse clicks to the program', function() + if helpers.pending_win32(pending) then return end feed('<LeftMouse><1,2>') screen:expect([[ line27 | @@ -94,7 +79,8 @@ describe('terminal mouse', function() end) it('will forward mouse scroll to the program', function() - feed('<MouseDown><0,0>') + if helpers.pending_win32(pending) then return end + feed('<ScrollWheelUp><0,0>') screen:expect([[ line27 | line28 | @@ -108,6 +94,7 @@ describe('terminal mouse', function() end) describe('with a split window and other buffer', function() + if helpers.pending_win32(pending) then return end before_each(function() feed('<c-\\><c-n>:vsp<cr>') screen:expect([[ @@ -117,7 +104,7 @@ describe('terminal mouse', function() rows: 5, cols: 25 |rows: 5, cols: 25 | {2:^ } |{2: } | ========== ========== | - | + :vsp | ]]) feed(':enew | set number<cr>') screen:expect([[ @@ -164,7 +151,7 @@ describe('terminal mouse', function() end) it('wont lose focus if another window is scrolled', function() - feed('<MouseDown><0,0><MouseDown><0,0>') + feed('<ScrollWheelUp><0,0><ScrollWheelUp><0,0>') screen:expect([[ {7: 21 }line |line30 | {7: 22 }line |rows: 5, cols: 25 | @@ -174,7 +161,7 @@ describe('terminal mouse', function() ========== ========== | {3:-- TERMINAL --} | ]]) - feed('<S-MouseUp><0,0>') + feed('<S-ScrollWheelDown><0,0>') screen:expect([[ {7: 26 }line |line30 | {7: 27 }line |rows: 5, cols: 25 | diff --git a/test/functional/terminal/scrollback_spec.lua b/test/functional/terminal/scrollback_spec.lua index d60819af65..af9b414311 100644 --- a/test/functional/terminal/scrollback_spec.lua +++ b/test/functional/terminal/scrollback_spec.lua @@ -2,25 +2,29 @@ local Screen = require('test.functional.ui.screen') local helpers = require('test.functional.helpers')(after_each) local thelpers = require('test.functional.terminal.helpers') local clear, eq, curbuf = helpers.clear, helpers.eq, helpers.curbuf -local feed, nvim_dir, execute = helpers.feed, helpers.nvim_dir, helpers.execute +local feed, nvim_dir, feed_command = helpers.feed, helpers.nvim_dir, helpers.feed_command +local iswin = helpers.iswin +local eval = helpers.eval +local command = helpers.command local wait = helpers.wait +local retry = helpers.retry +local curbufmeths = helpers.curbufmeths +local nvim = helpers.nvim local feed_data = thelpers.feed_data -if helpers.pending_win32(pending) then return end - describe('terminal scrollback', function() local screen before_each(function() clear() - screen = thelpers.screen_setup() + screen = thelpers.screen_setup(nil, nil, 30) end) after_each(function() screen:detach() end) - describe('when the limit is crossed', function() + describe('when the limit is exceeded', function() before_each(function() local lines = {} for i = 1, 30 do @@ -29,41 +33,41 @@ describe('terminal scrollback', function() table.insert(lines, '') feed_data(lines) screen:expect([[ - line26 | - line27 | - line28 | - line29 | - line30 | - {1: } | - {3:-- TERMINAL --} | + line26 | + line27 | + line28 | + line29 | + line30 | + {1: } | + {3:-- TERMINAL --} | ]]) end) it('will delete extra lines at the top', function() feed('<c-\\><c-n>gg') screen:expect([[ - ^line16 | - line17 | - line18 | - line19 | - line20 | - line21 | - | + ^line16 | + line17 | + line18 | + line19 | + line20 | + line21 | + | ]]) end) end) - describe('with the cursor at the last row', function() + describe('with cursor at last row', function() before_each(function() feed_data({'line1', 'line2', 'line3', 'line4', ''}) screen:expect([[ - tty ready | - line1 | - line2 | - line3 | - line4 | - {1: } | - {3:-- TERMINAL --} | + tty ready | + line1 | + line2 | + line3 | + line4 | + {1: } | + {3:-- TERMINAL --} | ]]) end) @@ -72,13 +76,13 @@ describe('terminal scrollback', function() it('will hide the top line', function() screen:expect([[ - line1 | - line2 | - line3 | - line4 | - line5 | - {1: } | - {3:-- TERMINAL --} | + line1 | + line2 | + line3 | + line4 | + line5 | + {1: } | + {3:-- TERMINAL --} | ]]) eq(7, curbuf('line_count')) end) @@ -88,62 +92,64 @@ describe('terminal scrollback', function() it('will hide the top 4 lines', function() screen:expect([[ - line3 | - line4 | - line5 | - line6 | - line7 | - line8{1: } | - {3:-- TERMINAL --} | + line3 | + line4 | + line5 | + line6 | + line7 | + line8{1: } | + {3:-- TERMINAL --} | ]]) feed('<c-\\><c-n>6k') screen:expect([[ - ^line2 | - line3 | - line4 | - line5 | - line6 | - line7 | - | + ^line2 | + line3 | + line4 | + line5 | + line6 | + line7 | + | ]]) feed('gg') screen:expect([[ - ^tty ready | - line1 | - line2 | - line3 | - line4 | - line5 | - | + ^tty ready | + line1 | + line2 | + line3 | + line4 | + line5 | + | ]]) feed('G') screen:expect([[ - line3 | - line4 | - line5 | - line6 | - line7 | - ^line8{2: } | - | + line3 | + line4 | + line5 | + line6 | + line7 | + ^line8{2: } | + | ]]) end) end) end) - describe('and the height is decreased by 1', function() + describe('and height decreased by 1', function() + if helpers.pending_win32(pending) then return end local function will_hide_top_line() - screen:try_resize(screen._width, screen._height - 1) + feed([[<C-\><C-N>:]]) -- Go to cmdline-mode, so cursor is at bottom. + screen:try_resize(screen._width - 2, screen._height - 1) screen:expect([[ - line2 | - line3 | - line4 | - rows: 5, cols: 50 | - {1: } | - {3:-- TERMINAL --} | + line2 | + line3 | + line4 | + rows: 5, cols: 28 | + {2: } | + :^ | ]]) end @@ -152,23 +158,23 @@ describe('terminal scrollback', function() describe('and then decreased by 2', function() before_each(function() will_hide_top_line() - screen:try_resize(screen._width, screen._height - 2) + screen:try_resize(screen._width - 2, screen._height - 2) end) it('will hide the top 3 lines', function() screen:expect([[ - rows: 5, cols: 50 | - rows: 3, cols: 50 | - {1: } | - {3:-- TERMINAL --} | + rows: 5, cols: 28 | + rows: 3, cols: 26 | + {2: } | + :^ | ]]) eq(8, curbuf('line_count')) - feed('<c-\\><c-n>3k') + feed([[<C-\><C-N>3k]]) screen:expect([[ - ^line4 | - rows: 5, cols: 50 | - rows: 3, cols: 50 | - | + ^line4 | + rows: 5, cols: 28 | + rows: 3, cols: 26 | + | ]]) end) end) @@ -176,6 +182,11 @@ describe('terminal scrollback', function() end) describe('with empty lines after the cursor', function() + -- XXX: Can't test this reliably on Windows unless the cursor is _moved_ + -- by the resize. http://docs.libuv.org/en/v1.x/signal.html + -- See also: https://github.com/rprichard/winpty/issues/110 + if helpers.pending_win32(pending) then return end + describe('and the height is decreased by 2', function() before_each(function() screen:try_resize(screen._width, screen._height - 2) @@ -183,11 +194,11 @@ describe('terminal scrollback', function() local function will_delete_last_two_lines() screen:expect([[ - tty ready | - rows: 4, cols: 50 | - {1: } | - | - {3:-- TERMINAL --} | + tty ready | + rows: 4, cols: 30 | + {1: } | + | + {3:-- TERMINAL --} | ]]) eq(4, curbuf('line_count')) end @@ -202,25 +213,25 @@ describe('terminal scrollback', function() it('will delete the last line and hide the first', function() screen:expect([[ - rows: 4, cols: 50 | - rows: 3, cols: 50 | - {1: } | - {3:-- TERMINAL --} | + rows: 4, cols: 30 | + rows: 3, cols: 30 | + {1: } | + {3:-- TERMINAL --} | ]]) eq(4, curbuf('line_count')) feed('<c-\\><c-n>gg') screen:expect([[ - ^tty ready | - rows: 4, cols: 50 | - rows: 3, cols: 50 | - | + ^tty ready | + rows: 4, cols: 30 | + rows: 3, cols: 30 | + | ]]) feed('a') screen:expect([[ - rows: 4, cols: 50 | - rows: 3, cols: 50 | - {1: } | - {3:-- TERMINAL --} | + rows: 4, cols: 30 | + rows: 3, cols: 30 | + {1: } | + {3:-- TERMINAL --} | ]]) end) end) @@ -231,33 +242,37 @@ describe('terminal scrollback', function() before_each(function() feed_data({'line1', 'line2', 'line3', 'line4', ''}) screen:expect([[ - tty ready | - line1 | - line2 | - line3 | - line4 | - {1: } | - {3:-- TERMINAL --} | + tty ready | + line1 | + line2 | + line3 | + line4 | + {1: } | + {3:-- TERMINAL --} | ]]) screen:try_resize(screen._width, screen._height - 3) screen:expect([[ - line4 | - rows: 3, cols: 50 | - {1: } | - {3:-- TERMINAL --} | + line4 | + rows: 3, cols: 30 | + {1: } | + {3:-- TERMINAL --} | ]]) eq(7, curbuf('line_count')) end) describe('and the height is increased by 1', function() + -- XXX: Can't test this reliably on Windows unless the cursor is _moved_ + -- by the resize. http://docs.libuv.org/en/v1.x/signal.html + -- See also: https://github.com/rprichard/winpty/issues/110 + if helpers.pending_win32(pending) then return end local function pop_then_push() screen:try_resize(screen._width, screen._height + 1) screen:expect([[ - line4 | - rows: 3, cols: 50 | - rows: 4, cols: 50 | - {1: } | - {3:-- TERMINAL --} | + line4 | + rows: 3, cols: 30 | + rows: 4, cols: 30 | + {1: } | + {3:-- TERMINAL --} | ]]) end @@ -272,26 +287,26 @@ describe('terminal scrollback', function() local function pop3_then_push1() screen:expect([[ - line2 | - line3 | - line4 | - rows: 3, cols: 50 | - rows: 4, cols: 50 | - rows: 7, cols: 50 | - {1: } | - {3:-- TERMINAL --} | + line2 | + line3 | + line4 | + rows: 3, cols: 30 | + rows: 4, cols: 30 | + rows: 7, cols: 30 | + {1: } | + {3:-- TERMINAL --} | ]]) eq(9, curbuf('line_count')) feed('<c-\\><c-n>gg') screen:expect([[ - ^tty ready | - line1 | - line2 | - line3 | - line4 | - rows: 3, cols: 50 | - rows: 4, cols: 50 | - | + ^tty ready | + line1 | + line2 | + line3 | + line4 | + rows: 3, cols: 30 | + rows: 4, cols: 30 | + | ]]) end @@ -306,18 +321,18 @@ describe('terminal scrollback', function() it('will show all lines and leave a blank one at the end', function() screen:expect([[ - tty ready | - line1 | - line2 | - line3 | - line4 | - rows: 3, cols: 50 | - rows: 4, cols: 50 | - rows: 7, cols: 50 | - rows: 11, cols: 50 | - {1: } | - | - {3:-- TERMINAL --} | + tty ready | + line1 | + line2 | + line3 | + line4 | + rows: 3, cols: 30 | + rows: 4, cols: 30 | + rows: 7, cols: 30 | + rows: 11, cols: 30 | + {1: } | + | + {3:-- TERMINAL --} | ]]) -- since there's an empty line after the cursor, the buffer line -- count equals the terminal screen height @@ -332,30 +347,171 @@ end) describe('terminal prints more lines than the screen height and exits', function() it('will push extra lines to scrollback', function() clear() - local screen = Screen.new(50, 7) + local screen = Screen.new(30, 7) screen:attach({rgb=false}) - execute('call termopen(["'..nvim_dir..'/tty-test", "10"]) | startinsert') + feed_command('call termopen(["'..nvim_dir..'/tty-test", "10"]) | startinsert') wait() screen:expect([[ - line6 | - line7 | - line8 | - line9 | - | - [Process exited 0] | - -- TERMINAL -- | + line6 | + line7 | + line8 | + line9 | + | + [Process exited 0] | + -- TERMINAL -- | ]]) feed('<cr>') -- closes the buffer correctly after pressing a key screen:expect([[ - ^ | - ~ | - ~ | - ~ | - ~ | - ~ | - | + ^ | + ~ | + ~ | + ~ | + ~ | + ~ | + | ]]) end) end) +describe("'scrollback' option", function() + before_each(function() + clear() + end) + + local function set_fake_shell() + -- shell-test.c is a fake shell that prints its arguments and exits. + nvim('set_option', 'shell', nvim_dir..'/shell-test') + nvim('set_option', 'shellcmdflag', 'EXE') + end + + local function expect_lines(expected, epsilon) + local ep = epsilon and epsilon or 0 + local actual = eval("line('$')") + if expected > actual + ep and expected < actual - ep then + error('expected (+/- '..ep..'): '..expected..', actual: '..tostring(actual)) + end + end + + it('set to 0 behaves as 1', function() + local screen + if iswin() then + screen = thelpers.screen_setup(nil, + "['powershell.exe', '-NoLogo', '-NoProfile', '-NoExit', '-Command', 'function global:prompt {return "..'"$"'.."}']", 30) + else + screen = thelpers.screen_setup(nil, "['sh']", 30) + end + + curbufmeths.set_option('scrollback', 0) + if iswin() then + feed_data('for($i=1;$i -le 30;$i++){Write-Host \"line$i\"}\r') + else + feed_data('for i in $(seq 1 30); do echo "line$i"; done\n') + end + screen:expect('line30 ', nil, nil, nil, true) + retry(nil, nil, function() expect_lines(7) end) + + screen:detach() + end) + + it('deletes lines (only) if necessary', function() + local screen + if iswin() then + screen = thelpers.screen_setup(nil, + "['powershell.exe', '-NoLogo', '-NoProfile', '-NoExit', '-Command', 'function global:prompt {return "..'"$"'.."}']", 30) + else + screen = thelpers.screen_setup(nil, "['sh']", 30) + end + + curbufmeths.set_option('scrollback', 200) + + -- Wait for prompt. + screen:expect('$', nil, nil, nil, true) + + wait() + if iswin() then + feed_data('for($i=1;$i -le 30;$i++){Write-Host \"line$i\"}\r') + else + feed_data('for i in $(seq 1 30); do echo "line$i"; done\n') + end + + screen:expect('line30 ', nil, nil, nil, true) + + retry(nil, nil, function() expect_lines(33, 2) end) + curbufmeths.set_option('scrollback', 10) + wait() + retry(nil, nil, function() expect_lines(16) end) + curbufmeths.set_option('scrollback', 10000) + retry(nil, nil, function() expect_lines(16) end) + -- Terminal job data is received asynchronously, may happen before the + -- 'scrollback' option is synchronized with the internal sb_buffer. + command('sleep 100m') + if iswin() then + feed_data('for($i=1;$i -le 40;$i++){Write-Host \"line$i\"}\r') + else + feed_data('for i in $(seq 1 40); do echo "line$i"; done\n') + end + + screen:expect('line40 ', nil, nil, nil, true) + + retry(nil, nil, function() expect_lines(58) end) + -- Verify off-screen state + eq('line35', eval("getline(line('w0') - 1)")) + eq('line26', eval("getline(line('w0') - 10)")) + + screen:detach() + end) + + it('defaults to 1000 in terminal buffers', function() + set_fake_shell() + command('terminal') + eq(1000, curbufmeths.get_option('scrollback')) + end) + + it('error if set to invalid value', function() + local status, rv = pcall(command, 'set scrollback=-2') + eq(false, status) -- assert failure + eq('E474:', string.match(rv, "E%d*:")) + + status, rv = pcall(command, 'set scrollback=100001') + eq(false, status) -- assert failure + eq('E474:', string.match(rv, "E%d*:")) + end) + + it('defaults to -1 on normal buffers', function() + command('new') + eq(-1, curbufmeths.get_option('scrollback')) + end) + + it(':setlocal in a normal buffer is an error', function() + command('new') + + -- :setlocal to -1 is NOT an error. + feed_command('setlocal scrollback=-1') + eq(nil, string.match(eval("v:errmsg"), "E%d*:")) + feed('<CR>') + + -- :setlocal to anything except -1 is an error. + feed_command('setlocal scrollback=42') + feed('<CR>') + eq('E474:', string.match(eval("v:errmsg"), "E%d*:")) + eq(-1, curbufmeths.get_option('scrollback')) + end) + + it(':set updates local value and global default', function() + set_fake_shell() + command('set scrollback=42') -- set global and (attempt) local + eq(-1, curbufmeths.get_option('scrollback')) -- normal buffer: -1 + command('terminal') + eq(42, curbufmeths.get_option('scrollback')) -- inherits global default + command('setlocal scrollback=99') + eq(99, curbufmeths.get_option('scrollback')) + command('set scrollback<') -- reset to global default + eq(42, curbufmeths.get_option('scrollback')) + command('setglobal scrollback=734') -- new global default + eq(42, curbufmeths.get_option('scrollback')) -- local value did not change + command('terminal') + eq(734, curbufmeths.get_option('scrollback')) + end) + +end) diff --git a/test/functional/terminal/tui_spec.lua b/test/functional/terminal/tui_spec.lua index 60f989d701..34a5ac0a49 100644 --- a/test/functional/terminal/tui_spec.lua +++ b/test/functional/terminal/tui_spec.lua @@ -2,9 +2,10 @@ -- as a simple way to send keys and assert screen state. local helpers = require('test.functional.helpers')(after_each) local thelpers = require('test.functional.terminal.helpers') -local feed = thelpers.feed_data -local execute = helpers.execute +local feed_data = thelpers.feed_data +local feed_command = helpers.feed_command local nvim_dir = helpers.nvim_dir +local retry = helpers.retry if helpers.pending_win32(pending) then return end @@ -13,7 +14,8 @@ describe('tui', function() before_each(function() helpers.clear() - screen = thelpers.screen_setup(0, '["'..helpers.nvim_prog..'", "-u", "NONE", "-i", "NONE", "--cmd", "set noswapfile"]') + screen = thelpers.screen_setup(0, '["'..helpers.nvim_prog + ..'", "-u", "NONE", "-i", "NONE", "--cmd", "set noswapfile noshowcmd noruler"]') -- right now pasting can be really slow in the TUI, especially in ASAN. -- this will be fixed later but for now we require a high timeout. screen.timeout = 60000 @@ -33,7 +35,7 @@ describe('tui', function() end) it('accepts basic utf-8 input', function() - feed('iabc\ntest1\ntest2') + feed_data('iabc\ntest1\ntest2') screen:expect([[ abc | test1 | @@ -43,7 +45,7 @@ describe('tui', function() {3:-- INSERT --} | {3:-- TERMINAL --} | ]]) - feed('\027') + feed_data('\027') screen:expect([[ abc | test1 | @@ -58,8 +60,8 @@ describe('tui', function() it('interprets leading <Esc> byte as ALT modifier in normal-mode', function() local keys = 'dfghjkl' for c in keys:gmatch('.') do - execute('nnoremap <a-'..c..'> ialt-'..c..'<cr><esc>') - feed('\027'..c) + feed_command('nnoremap <a-'..c..'> ialt-'..c..'<cr><esc>') + feed_data('\027'..c) end screen:expect([[ alt-j | @@ -70,7 +72,7 @@ describe('tui', function() | {3:-- TERMINAL --} | ]]) - feed('gg') + feed_data('gg') screen:expect([[ {1:a}lt-d | alt-f | @@ -89,7 +91,7 @@ describe('tui', function() -- Example: for input ALT+j: -- * Vim (Nvim prior to #3982) sets high-bit, inserts "รช". -- * Nvim (after #3982) inserts "j". - feed('i\027j') + feed_data('i\027j') screen:expect([[ j{1: } | {4:~ }| @@ -102,10 +104,10 @@ describe('tui', function() end) it('accepts ascii control sequences', function() - feed('i') - feed('\022\007') -- ctrl+g - feed('\022\022') -- ctrl+v - feed('\022\013') -- ctrl+m + feed_data('i') + feed_data('\022\007') -- ctrl+g + feed_data('\022\022') -- ctrl+v + feed_data('\022\013') -- ctrl+m screen:expect([[ {9:^G^V^M}{1: } | {4:~ }| @@ -118,7 +120,7 @@ describe('tui', function() end) it('automatically sends <Paste> for bracketed paste sequences', function() - feed('i\027[200~') + feed_data('i\027[200~') screen:expect([[ {1: } | {4:~ }| @@ -128,7 +130,7 @@ describe('tui', function() {3:-- INSERT (paste) --} | {3:-- TERMINAL --} | ]]) - feed('pasted from terminal') + feed_data('pasted from terminal') screen:expect([[ pasted from terminal{1: } | {4:~ }| @@ -138,7 +140,7 @@ describe('tui', function() {3:-- INSERT (paste) --} | {3:-- TERMINAL --} | ]]) - feed('\027[201~') + feed_data('\027[201~') screen:expect([[ pasted from terminal{1: } | {4:~ }| @@ -151,12 +153,12 @@ describe('tui', function() end) it('can handle arbitrarily long bursts of input', function() - execute('set ruler') + feed_command('set ruler') local t = {} for i = 1, 3000 do t[i] = 'item ' .. tostring(i) end - feed('i\027[200~'..table.concat(t, '\n')..'\027[201~') + feed_data('i\027[200~'..table.concat(t, '\n')..'\027[201~') screen:expect([[ item 2997 | item 2998 | @@ -177,8 +179,9 @@ describe('tui with non-tty file descriptors', function() end) it('can handle pipes as stdout and stderr', function() - local screen = thelpers.screen_setup(0, '"'..helpers.nvim_prog..' -u NONE -i NONE --cmd \'set noswapfile\' --cmd \'normal iabc\' > /dev/null 2>&1 && cat testF && rm testF"') - feed(':w testF\n:q\n') + local screen = thelpers.screen_setup(0, '"'..helpers.nvim_prog + ..' -u NONE -i NONE --cmd \'set noswapfile noshowcmd noruler\' --cmd \'normal iabc\' > /dev/null 2>&1 && cat testF && rm testF"') + feed_data(':w testF\n:q\n') screen:expect([[ :w testF | :q | @@ -196,13 +199,15 @@ describe('tui focus event handling', function() before_each(function() helpers.clear() - screen = thelpers.screen_setup(0, '["'..helpers.nvim_prog..'", "-u", "NONE", "-i", "NONE", "--cmd", "set noswapfile"]') - execute('autocmd FocusGained * echo "gained"') - execute('autocmd FocusLost * echo "lost"') + screen = thelpers.screen_setup(0, '["'..helpers.nvim_prog + ..'", "-u", "NONE", "-i", "NONE", "--cmd", "set noswapfile noshowcmd noruler"]') + feed_data(":autocmd FocusGained * echo 'gained'\n") + feed_data(":autocmd FocusLost * echo 'lost'\n") + feed_data("\034\016") -- CTRL-\ CTRL-N end) it('can handle focus events in normal mode', function() - feed('\027[I') + feed_data('\027[I') screen:expect([[ {1: } | {4:~ }| @@ -213,7 +218,7 @@ describe('tui focus event handling', function() {3:-- TERMINAL --} | ]]) - feed('\027[O') + feed_data('\027[O') screen:expect([[ {1: } | {4:~ }| @@ -226,9 +231,9 @@ describe('tui focus event handling', function() end) it('can handle focus events in insert mode', function() - execute('set noshowmode') - feed('i') - feed('\027[I') + feed_command('set noshowmode') + feed_data('i') + feed_data('\027[I') screen:expect([[ {1: } | {4:~ }| @@ -238,7 +243,7 @@ describe('tui focus event handling', function() gained | {3:-- TERMINAL --} | ]]) - feed('\027[O') + feed_data('\027[O') screen:expect([[ {1: } | {4:~ }| @@ -251,8 +256,8 @@ describe('tui focus event handling', function() end) it('can handle focus events in cmdline mode', function() - feed(':') - feed('\027[I') + feed_data(':') + feed_data('\027[I') screen:expect([[ | {4:~ }| @@ -262,7 +267,7 @@ describe('tui focus event handling', function() g{1:a}ined | {3:-- TERMINAL --} | ]]) - feed('\027[O') + feed_data('\027[O') screen:expect([[ | {4:~ }| @@ -275,30 +280,36 @@ describe('tui focus event handling', function() end) it('can handle focus events in terminal mode', function() - execute('set shell='..nvim_dir..'/shell-test') - execute('set laststatus=0') - execute('set noshowmode') - execute('terminal') - feed('\027[I') - screen:expect([[ - ready $ | - [Process exited 0]{1: } | - | - | - | - gained | - {3:-- TERMINAL --} | - ]]) - feed('\027[O') - screen:expect([[ - ready $ | - [Process exited 0]{1: } | - | - | - | - lost | - {3:-- TERMINAL --} | - ]]) + feed_data(':set shell='..nvim_dir..'/shell-test\n') + feed_data(':set noshowmode laststatus=0\n') + + retry(2, 3 * screen.timeout, function() + feed_data(':terminal\n') + feed_data('\027[I') + screen:expect([[ + {1:r}eady $ | + [Process exited 0] | + | + | + | + gained | + {3:-- TERMINAL --} | + ]]) + feed_data('\027[O') + screen:expect([[ + {1:r}eady $ | + [Process exited 0] | + | + | + | + lost | + {3:-- TERMINAL --} | + ]]) + + -- If retry is needed... + feed_data("\034\016") -- CTRL-\ CTRL-N + feed_data(':bwipeout!\n') + end) end) end) @@ -306,21 +317,22 @@ end) -- does not initialize the TUI. describe("tui 't_Co' (terminal colors)", function() local screen - local is_linux = (helpers.eval("system('uname') =~? 'linux'") == 1) + local is_freebsd = (helpers.eval("system('uname') =~? 'FreeBSD'") == 1) local function assert_term_colors(term, colorterm, maxcolors) helpers.clear({env={TERM=term}, args={}}) -- This is ugly because :term/termopen() forces TERM=xterm-256color. -- TODO: Revisit this after jobstart/termopen accept `env` dict. screen = thelpers.screen_setup(0, string.format( - [=[['sh', '-c', 'LANG=C TERM=%s %s %s -u NONE -i NONE --cmd "silent set noswapfile"']]=], + [=[['sh', '-c', 'LANG=C TERM=%s %s %s -u NONE -i NONE --cmd "silent set noswapfile noshowcmd noruler"']]=], term, (colorterm ~= nil and "COLORTERM="..colorterm or ""), helpers.nvim_prog)) thelpers.feed_data(":echo &t_Co\n") + helpers.wait() local tline - if maxcolors == 8 then + if maxcolors == 8 or maxcolors == 16 then tline = "~ " else tline = "{4:~ }" @@ -336,27 +348,79 @@ describe("tui 't_Co' (terminal colors)", function() ]], tline, tline, tline, tostring(maxcolors and maxcolors or ""))) end - it("unknown TERM sets empty 't_Co'", function() - assert_term_colors("yet-another-term", nil, nil) + -- ansi and no terminal type at all: + + it("no TERM uses 8 colors", function() + assert_term_colors(nil, nil, 8) + end) + + it("TERM=ansi no COLORTERM uses 8 colors", function() + assert_term_colors("ansi", nil, 8) end) - it("unknown TERM with COLORTERM=screen-256color uses 256 colors", function() - assert_term_colors("yet-another-term", "screen-256color", 256) + it("TERM=ansi with COLORTERM=anything-no-number uses 16 colors", function() + assert_term_colors("ansi", "yet-another-term", 16) end) - it("TERM=linux uses 8 colors", function() - if is_linux then - assert_term_colors("linux", nil, 8) + it("unknown TERM COLORTERM with 256 in name uses 256 colors", function() + assert_term_colors("ansi", "yet-another-term-256color", 256) + end) + + it("TERM=ansi-256color sets 256 colours", function() + assert_term_colors("ansi-256color", nil, 256) + end) + + -- Unknown terminal types: + + it("unknown TERM no COLORTERM sets 8 colours", function() + assert_term_colors("yet-another-term", nil, 8) + end) + + it("unknown TERM with COLORTERM=anything-no-number uses 16 colors", function() + assert_term_colors("yet-another-term", "yet-another-term", 16) + end) + + it("unknown TERM with 256 in name sets 256 colours", function() + assert_term_colors("yet-another-term-256color", nil, 256) + end) + + it("unknown TERM COLORTERM with 256 in name uses 256 colors", function() + assert_term_colors("yet-another-term", "yet-another-term-256color", 256) + end) + + -- Linux kernel terminal emulator: + + it("TERM=linux uses 256 colors", function() + assert_term_colors("linux", nil, 256) + end) + + it("TERM=linux-16color uses 256 colors", function() + assert_term_colors("linux-16color", nil, 256) + end) + + it("TERM=linux-256color uses 256 colors", function() + assert_term_colors("linux-256color", nil, 256) + end) + + -- screen: + -- + -- FreeBSD falls back to the built-in screen-256colour entry. + -- Linux and MacOS have a screen entry in external terminfo with 8 colours, + -- which is raised to 16 by COLORTERM. + + it("TERM=screen no COLORTERM uses 8/256 colors", function() + if is_freebsd then + assert_term_colors("screen", nil, 256) else - pending() + assert_term_colors("screen", nil, 8) end end) - it("TERM=screen uses 8 colors", function() - if is_linux then - assert_term_colors("screen", nil, 8) + it("TERM=screen COLORTERM=screen uses 16/256 colors", function() + if is_freebsd then + assert_term_colors("screen", "screen", 256) else - pending() + assert_term_colors("screen", "screen", 16) end end) @@ -364,15 +428,148 @@ describe("tui 't_Co' (terminal colors)", function() assert_term_colors("screen", "screen-256color", 256) end) - it("TERM=yet-another-term COLORTERM=screen-256color uses 256 colors", function() - assert_term_colors("screen", "screen-256color", 256) + it("TERM=screen-256color no COLORTERM uses 256 colors", function() + assert_term_colors("screen-256color", nil, 256) end) + -- tmux: + -- + -- FreeBSD and MacOS fall back to the built-in tmux-256colour entry. + -- Linux has a tmux entry in external terminfo with 8 colours, + -- which is raised to 256. + + it("TERM=tmux no COLORTERM uses 256 colors", function() + assert_term_colors("tmux", nil, 256) + end) + + it("TERM=tmux COLORTERM=tmux uses 256 colors", function() + assert_term_colors("tmux", "tmux", 256) + end) + + it("TERM=tmux COLORTERM=tmux-256color uses 256 colors", function() + assert_term_colors("tmux", "tmux-256color", 256) + end) + + it("TERM=tmux-256color no COLORTERM uses 256 colors", function() + assert_term_colors("tmux-256color", nil, 256) + end) + + -- xterm and imitators: + it("TERM=xterm uses 256 colors", function() assert_term_colors("xterm", nil, 256) end) + it("TERM=xterm COLORTERM=gnome-terminal uses 256 colors", function() + assert_term_colors("xterm", "gnome-terminal", 256) + end) + + it("TERM=xterm COLORTERM=mate-terminal uses 256 colors", function() + assert_term_colors("xterm", "mate-terminal", 256) + end) + it("TERM=xterm-256color uses 256 colors", function() assert_term_colors("xterm-256color", nil, 256) end) + + -- rxvt and stterm: + -- + -- FreeBSD and MacOS fall back to the built-in rxvt-256color and + -- st-256colour entries. + -- Linux has an rxvt, an st, and an st-16color entry in external terminfo + -- with 8, 8, and 16 colours respectively, which are raised to 256. + + it("TERM=rxvt no COLORTERM uses 256 colors", function() + assert_term_colors("rxvt", nil, 256) + end) + + it("TERM=rxvt COLORTERM=rxvt uses 256 colors", function() + assert_term_colors("rxvt", "rxvt", 256) + end) + + it("TERM=rxvt-256color uses 256 colors", function() + assert_term_colors("rxvt-256color", nil, 256) + end) + + it("TERM=st no COLORTERM uses 256 colors", function() + assert_term_colors("st", nil, 256) + end) + + it("TERM=st COLORTERM=st uses 256 colors", function() + assert_term_colors("st", "st", 256) + end) + + it("TERM=st COLORTERM=st-256color uses 256 colors", function() + assert_term_colors("st", "st-256color", 256) + end) + + it("TERM=st-16color no COLORTERM uses 8/256 colors", function() + assert_term_colors("st", nil, 256) + end) + + it("TERM=st-16color COLORTERM=st uses 16/256 colors", function() + assert_term_colors("st", "st", 256) + end) + + it("TERM=st-16color COLORTERM=st-256color uses 256 colors", function() + assert_term_colors("st", "st-256color", 256) + end) + + it("TERM=st-256color uses 256 colors", function() + assert_term_colors("st-256color", nil, 256) + end) + + -- gnome and vte: + -- + -- FreeBSD and MacOS fall back to the built-in vte-256color entry. + -- Linux has a gnome, a vte, a gnome-256color, and a vte-256color entry in + -- external terminfo with 8, 8, 256, and 256 colours respectively, which are + -- raised to 256. + + it("TERM=gnome no COLORTERM uses 256 colors", function() + assert_term_colors("gnome", nil, 256) + end) + + it("TERM=gnome COLORTERM=gnome uses 256 colors", function() + assert_term_colors("gnome", "gnome", 256) + end) + + it("TERM=gnome COLORTERM=gnome-256color uses 256 colors", function() + assert_term_colors("gnome", "gnome-256color", 256) + end) + + it("TERM=gnome-256color uses 256 colors", function() + assert_term_colors("gnome-256color", nil, 256) + end) + + it("TERM=vte no COLORTERM uses 256 colors", function() + assert_term_colors("vte", nil, 256) + end) + + it("TERM=vte COLORTERM=vte uses 256 colors", function() + assert_term_colors("vte", "vte", 256) + end) + + it("TERM=vte COLORTERM=vte-256color uses 256 colors", function() + assert_term_colors("vte", "vte-256color", 256) + end) + + it("TERM=vte-256color uses 256 colors", function() + assert_term_colors("vte-256color", nil, 256) + end) + + -- others: + + it("TERM=interix uses 8 colors", function() + assert_term_colors("interix", nil, 8) + end) + + it("TERM=iTerm.app uses 256 colors", function() + assert_term_colors("iTerm.app", nil, 256) + end) + + it("TERM=iterm uses 256 colors", function() + assert_term_colors("iterm", nil, 256) + end) + end) diff --git a/test/functional/terminal/window_spec.lua b/test/functional/terminal/window_spec.lua index eb7a67a1a6..0f705cfe40 100644 --- a/test/functional/terminal/window_spec.lua +++ b/test/functional/terminal/window_spec.lua @@ -3,8 +3,6 @@ local thelpers = require('test.functional.terminal.helpers') local feed, clear = helpers.feed, helpers.clear local wait = helpers.wait -if helpers.pending_win32(pending) then return end - describe('terminal window', function() local screen @@ -18,11 +16,11 @@ describe('terminal window', function() feed('<c-\\><c-n>') screen:expect([[ tty ready | - {2: } | + {2:^ } | + | | | | - ^ | | ]]) feed(':set colorcolumn=20<cr>i') diff --git a/test/functional/terminal/window_split_tab_spec.lua b/test/functional/terminal/window_split_tab_spec.lua index 6951b84a69..c5199f620e 100644 --- a/test/functional/terminal/window_split_tab_spec.lua +++ b/test/functional/terminal/window_split_tab_spec.lua @@ -2,9 +2,7 @@ local helpers = require('test.functional.helpers')(after_each) local thelpers = require('test.functional.terminal.helpers') local clear = helpers.clear local feed, nvim = helpers.feed, helpers.nvim -local execute = helpers.execute - -if helpers.pending_win32(pending) then return end +local feed_command = helpers.feed_command describe('terminal', function() local screen @@ -25,21 +23,22 @@ describe('terminal', function() end) it('resets its size when entering terminal window', function() + if helpers.pending_win32(pending) then return end feed('<c-\\><c-n>') - execute('2split') + feed_command('2split') screen:expect([[ - tty ready | - ^rows: 2, cols: 50 | + rows: 2, cols: 50 | + {2:^ } | ========== | - tty ready | rows: 2, cols: 50 | {2: } | {4:~ }| {4:~ }| + {4:~ }| ========== | - | + :2split | ]]) - execute('wincmd p') + feed_command('wincmd p') screen:expect([[ tty ready | rows: 2, cols: 50 | @@ -52,16 +51,16 @@ describe('terminal', function() ========== | :wincmd p | ]]) - execute('wincmd p') + feed_command('wincmd p') screen:expect([[ - rows: 5, cols: 50 | - ^rows: 2, cols: 50 | + rows: 2, cols: 50 | + {2:^ } | ========== | - rows: 5, cols: 50 | rows: 2, cols: 50 | {2: } | {4:~ }| {4:~ }| + {4:~ }| ========== | :wincmd p | ]]) @@ -69,31 +68,25 @@ describe('terminal', function() describe('when the screen is resized', function() it('will forward a resize request to the program', function() - screen:try_resize(screen._width + 3, screen._height + 5) + feed([[<C-\><C-N>:]]) -- Go to cmdline-mode, so cursor is at bottom. + screen:try_resize(screen._width - 3, screen._height - 2) screen:expect([[ - tty ready | - rows: 14, cols: 53 | - {1: } | - | - | - | - | - | - | - | - | - | - | - | - {3:-- TERMINAL --} | + tty ready | + rows: 7, cols: 47 | + {2: } | + | + | + | + | + :^ | ]]) - screen:try_resize(screen._width - 6, screen._height - 10) + screen:try_resize(screen._width - 6, screen._height - 3) screen:expect([[ - tty ready | - rows: 14, cols: 53 | - rows: 4, cols: 47 | - {1: } | - {3:-- TERMINAL --} | + tty ready | + rows: 7, cols: 47 | + rows: 4, cols: 41 | + {2: } | + :^ | ]]) end) end) diff --git a/test/functional/ui/bufhl_spec.lua b/test/functional/ui/bufhl_spec.lua index 53fe303762..e1e11203e0 100644 --- a/test/functional/ui/bufhl_spec.lua +++ b/test/functional/ui/bufhl_spec.lua @@ -1,7 +1,8 @@ local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') + local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local execute, request, neq = helpers.execute, helpers.request, helpers.neq +local command, request, neq = helpers.command, helpers.request, helpers.neq if helpers.pending_win32(pending) then return end @@ -11,7 +12,7 @@ describe('Buffer highlighting', function() before_each(function() clear() - execute("syntax on") + command('syntax on') screen = Screen.new(40, 8) screen:attach() screen:set_default_attr_ids({ @@ -106,7 +107,7 @@ describe('Buffer highlighting', function() combining highlights from different sources]]) - execute("hi ImportantWord gui=bold cterm=bold") + command("hi ImportantWord gui=bold cterm=bold") id1 = add_hl(0, "ImportantWord", 0, 2, 8) add_hl(id1, "ImportantWord", 1, 12, -1) add_hl(id1, "ImportantWord", 2, 0, 9) @@ -131,7 +132,7 @@ describe('Buffer highlighting', function() {1:~ }| {1:~ }| {1:~ }| - :hi ImportantWord gui=bold cterm=bold | + | ]]) end) @@ -145,7 +146,7 @@ describe('Buffer highlighting', function() {1:~ }| {1:~ }| {1:~ }| - :hi ImportantWord gui=bold cterm=bold | + | ]]) end) @@ -159,7 +160,7 @@ describe('Buffer highlighting', function() {1:~ }| {1:~ }| {1:~ }| - :hi ImportantWord gui=bold cterm=bold | + | ]]) end) @@ -175,7 +176,7 @@ describe('Buffer highlighting', function() {1:~ }| {1:~ }| {1:~ }| - :hi ImportantWord gui=bold cterm=bold | + | ]]) end) @@ -192,7 +193,7 @@ describe('Buffer highlighting', function() | ]]) - execute(':3move 4') + command(':3move 4') screen:expect([[ a {5:longer} example | | @@ -201,7 +202,7 @@ describe('Buffer highlighting', function() {1:~ }| {1:~ }| {1:~ }| - ::3move 4 | + | ]]) end) end) diff --git a/test/functional/ui/cmdline_highlight_spec.lua b/test/functional/ui/cmdline_highlight_spec.lua new file mode 100644 index 0000000000..d87ce72599 --- /dev/null +++ b/test/functional/ui/cmdline_highlight_spec.lua @@ -0,0 +1,893 @@ +local helpers = require('test.functional.helpers')(after_each) +local Screen = require('test.functional.ui.screen') + +local eq = helpers.eq +local feed = helpers.feed +local clear = helpers.clear +local meths = helpers.meths +local funcs = helpers.funcs +local source = helpers.source +local dedent = helpers.dedent +local command = helpers.command +local curbufmeths = helpers.curbufmeths + +local screen + +-- Bug in input() handling: :redraw! will erase the whole prompt up until +-- user types something. It exists in Vim as well, so using `h<BS>` as +-- a workaround. +local function redraw_input() + feed('{REDRAW}h<BS>') +end + +before_each(function() + clear() + screen = Screen.new(40, 8) + screen:attach() + source([[ + highlight RBP1 guibg=Red + highlight RBP2 guibg=Yellow + highlight RBP3 guibg=Green + highlight RBP4 guibg=Blue + let g:NUM_LVLS = 4 + function Redraw() + redraw! + return '' + endfunction + let g:id = '' + cnoremap <expr> {REDRAW} Redraw() + function DoPrompt(do_return) abort + let id = g:id + let Cb = g:Nvim_color_input{g:id} + let out = input({'prompt': ':', 'highlight': Cb}) + let g:out{id} = out + return (a:do_return ? out : '') + endfunction + nnoremap <expr> {PROMPT} DoPrompt(0) + cnoremap <expr> {PROMPT} DoPrompt(1) + function RainBowParens(cmdline) + let ret = [] + let i = 0 + let lvl = 0 + while i < len(a:cmdline) + if a:cmdline[i] is# '(' + call add(ret, [i, i + 1, 'RBP' . ((lvl % g:NUM_LVLS) + 1)]) + let lvl += 1 + elseif a:cmdline[i] is# ')' + let lvl -= 1 + call add(ret, [i, i + 1, 'RBP' . ((lvl % g:NUM_LVLS) + 1)]) + endif + let i += 1 + endwhile + return ret + endfunction + function SplittedMultibyteStart(cmdline) + let ret = [] + let i = 0 + while i < len(a:cmdline) + let char = nr2char(char2nr(a:cmdline[i:])) + if a:cmdline[i:i + len(char) - 1] is# char + if len(char) > 1 + call add(ret, [i + 1, i + len(char), 'RBP2']) + endif + let i += len(char) + else + let i += 1 + endif + endwhile + return ret + endfunction + function SplittedMultibyteEnd(cmdline) + let ret = [] + let i = 0 + while i < len(a:cmdline) + let char = nr2char(char2nr(a:cmdline[i:])) + if a:cmdline[i:i + len(char) - 1] is# char + if len(char) > 1 + call add(ret, [i, i + 1, 'RBP1']) + endif + let i += len(char) + else + let i += 1 + endif + endwhile + return ret + endfunction + function Echoing(cmdline) + echo 'HERE' + return v:_null_list + endfunction + function Echoning(cmdline) + echon 'HERE' + return v:_null_list + endfunction + function Echomsging(cmdline) + echomsg 'HERE' + return v:_null_list + endfunction + function Echoerring(cmdline) + echoerr 'HERE' + return v:_null_list + endfunction + function Redrawing(cmdline) + redraw! + return v:_null_list + endfunction + function Throwing(cmdline) + throw "ABC" + return v:_null_list + endfunction + function Halting(cmdline) + while 1 + endwhile + endfunction + function ReturningGlobal(cmdline) + return g:callback_return + endfunction + function ReturningGlobal2(cmdline) + return g:callback_return[:len(a:cmdline)-1] + endfunction + function ReturningGlobalN(n, cmdline) + return g:callback_return{a:n} + endfunction + let g:recording_calls = [] + function Recording(cmdline) + call add(g:recording_calls, a:cmdline) + return [] + endfunction + ]]) + screen:set_default_attr_ids({ + RBP1={background = Screen.colors.Red}, + RBP2={background = Screen.colors.Yellow}, + RBP3={background = Screen.colors.Green}, + RBP4={background = Screen.colors.Blue}, + EOB={bold = true, foreground = Screen.colors.Blue1}, + ERR={foreground = Screen.colors.Grey100, background = Screen.colors.Red}, + SK={foreground = Screen.colors.Blue}, + PE={bold = true, foreground = Screen.colors.SeaGreen4} + }) +end) + +local function set_color_cb(funcname, callback_return, id) + meths.set_var('id', id or '') + if id and id ~= '' and funcs.exists('*' .. funcname .. 'N') then + command(('let g:Nvim_color_input%s = {cmdline -> %sN(%s, cmdline)}'):format( + id, funcname, id)) + if callback_return then + meths.set_var('callback_return' .. id, callback_return) + end + else + meths.set_var('Nvim_color_input', funcname) + if callback_return then + meths.set_var('callback_return', callback_return) + end + end +end +local function start_prompt(text) + feed('{PROMPT}' .. (text or '')) +end + +describe('Command-line coloring', function() + it('works', function() + set_color_cb('RainBowParens') + meths.set_option('more', false) + start_prompt() + screen:expect([[ + | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + :^ | + ]]) + feed('e') + screen:expect([[ + | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + :e^ | + ]]) + feed('cho ') + screen:expect([[ + | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + :echo ^ | + ]]) + feed('(') + screen:expect([[ + | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + :echo {RBP1:(}^ | + ]]) + feed('(') + screen:expect([[ + | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + :echo {RBP1:(}{RBP2:(}^ | + ]]) + feed('42') + screen:expect([[ + | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + :echo {RBP1:(}{RBP2:(}42^ | + ]]) + feed('))') + screen:expect([[ + | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + :echo {RBP1:(}{RBP2:(}42{RBP2:)}{RBP1:)}^ | + ]]) + feed('<BS>') + screen:expect([[ + | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + :echo {RBP1:(}{RBP2:(}42{RBP2:)}^ | + ]]) + redraw_input() + screen:expect([[ + | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + :echo {RBP1:(}{RBP2:(}42{RBP2:)}^ | + ]]) + end) + for _, func_part in ipairs({'', 'n', 'msg'}) do + it('disables :echo' .. func_part .. ' messages', function() + set_color_cb('Echo' .. func_part .. 'ing') + start_prompt('echo') + screen:expect([[ + | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + :echo^ | + ]]) + end) + end + it('does the right thing when hl start appears to split multibyte char', + function() + set_color_cb('SplittedMultibyteStart') + start_prompt('echo "ยซ') + screen:expect([[ + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + :echo " | + {ERR:E5405: Chunk 0 start 7 splits multibyte }| + {ERR:character} | + :echo "ยซ^ | + ]]) + feed('ยป') + screen:expect([[ + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + :echo " | + {ERR:E5405: Chunk 0 start 7 splits multibyte }| + {ERR:character} | + :echo "ยซยป^ | + ]]) + end) + it('does the right thing when hl end appears to split multibyte char', + function() + set_color_cb('SplittedMultibyteEnd') + start_prompt('echo "ยซ') + screen:expect([[ + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + :echo " | + {ERR:E5406: Chunk 0 end 7 splits multibyte ch}| + {ERR:aracter} | + :echo "ยซ^ | + ]]) + end) + it('does the right thing when errorring', function() + set_color_cb('Echoerring') + start_prompt('e') + screen:expect([[ + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + : | + {ERR:E5407: Callback has thrown an exception:}| + {ERR: Vim(echoerr):HERE} | + :e^ | + ]]) + end) + it('silences :echo', function() + set_color_cb('Echoing') + start_prompt('e') + screen:expect([[ + | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + :e^ | + ]]) + eq('', meths.command_output('messages')) + end) + it('silences :echon', function() + set_color_cb('Echoning') + start_prompt('e') + screen:expect([[ + | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + :e^ | + ]]) + eq('', meths.command_output('messages')) + end) + it('silences :echomsg', function() + set_color_cb('Echomsging') + start_prompt('e') + screen:expect([[ + | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + :e^ | + ]]) + eq('', meths.command_output('messages')) + end) + it('does the right thing when throwing', function() + set_color_cb('Throwing') + start_prompt('e') + screen:expect([[ + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + : | + {ERR:E5407: Callback has thrown an exception:}| + {ERR: ABC} | + :e^ | + ]]) + end) + it('stops executing callback after a number of errors', function() + set_color_cb('SplittedMultibyteStart') + start_prompt('let x = "ยซยปยซยปยซยปยซยปยซยป"\n') + screen:expect([[ + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + :let x = " | + {ERR:E5405: Chunk 0 start 10 splits multibyte}| + {ERR: character} | + ^:let x = "ยซยปยซยปยซยปยซยปยซยป" | + ]]) + feed('\n') + screen:expect([[ + ^ | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + | + ]]) + eq('let x = "ยซยปยซยปยซยปยซยปยซยป"', meths.get_var('out')) + local msg = '\nE5405: Chunk 0 start 10 splits multibyte character' + eq(msg:rep(1), funcs.execute('messages')) + end) + it('allows interrupting callback with <C-c>', function() + set_color_cb('Halting') + start_prompt('echo 42') + screen:expect([[ + ^ | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + | + ]]) + screen:sleep(500) + feed('<C-c>') + screen:expect([[ + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + : | + {ERR:E5407: Callback has thrown an exception:}| + {ERR: Keyboard interrupt} | + :echo 42^ | + ]]) + redraw_input() + screen:expect([[ + | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + :echo 42^ | + ]]) + feed('\n') + screen:expect([[ + | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + ^:echo 42 | + ]]) + feed('\n') + eq('echo 42', meths.get_var('out')) + feed('<C-c>') + screen:expect([[ + ^ | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + Type :quit<Enter> to exit Nvim | + ]]) + end) + it('works fine with NUL, NL, CR', function() + set_color_cb('RainBowParens') + start_prompt('echo ("<C-v><CR><C-v><Nul><C-v><NL>")') + screen:expect([[ + | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + :echo {RBP1:(}"{SK:^M^@^@}"{RBP1:)}^ | + ]]) + end) + it('errors out when callback returns something wrong', function() + command('cnoremap + ++') + set_color_cb('ReturningGlobal', '') + start_prompt('#') + screen:expect([[ + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + : | + {ERR:E5400: Callback should return list} | + :#^ | + ]]) + + feed('<CR><CR><CR>') + set_color_cb('ReturningGlobal', {{0, 1, 'Normal'}, 42}) + start_prompt('#') + screen:expect([[ + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + : | + {ERR:E5401: List item 1 is not a List} | + :#^ | + ]]) + + feed('<CR><CR><CR>') + set_color_cb('ReturningGlobal2', {{0, 1, 'Normal'}, {1}}) + start_prompt('+') + screen:expect([[ + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + :+ | + {ERR:E5402: List item 1 has incorrect length:}| + {ERR: 1 /= 3} | + :++^ | + ]]) + + feed('<CR><CR><CR>') + set_color_cb('ReturningGlobal2', {{0, 1, 'Normal'}, {2, 3, 'Normal'}}) + start_prompt('+') + screen:expect([[ + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + :+ | + {ERR:E5403: Chunk 1 start 2 not in range [1, }| + {ERR:2)} | + :++^ | + ]]) + + feed('<CR><CR><CR>') + set_color_cb('ReturningGlobal2', {{0, 1, 'Normal'}, {1, 3, 'Normal'}}) + start_prompt('+') + screen:expect([[ + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + :+ | + {ERR:E5404: Chunk 1 end 3 not in range (1, 2]}| + | + :++^ | + ]]) + end) + it('does not error out when called from a errorred out cycle', function() + set_color_cb('ReturningGlobal', {{0, 1, 'Normal'}}) + feed(dedent([[ + :set regexpengine=2 + :for pat in [' \ze*', ' \zs*'] + : try + : let l = matchlist('x x', pat) + : $put =input({'prompt':'>','highlight':'ReturningGlobal'}) + : + : $put ='E888 NOT detected for ' . pat + : catch + : $put =input({'prompt':'>','highlight':'ReturningGlobal'}) + : + : $put ='E888 detected for ' . pat + : endtry + :endfor + : + : + : + : + : + : + ]])) + eq({'', ':', 'E888 detected for \\ze*', ':', 'E888 detected for \\zs*'}, + curbufmeths.get_lines(0, -1, false)) + eq('', funcs.execute('messages')) + end) + it('allows nesting input()s', function() + set_color_cb('ReturningGlobal', {{0, 1, 'RBP1'}}, '') + start_prompt('1') + screen:expect([[ + | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + :{RBP1:1}^ | + ]]) + + set_color_cb('ReturningGlobal', {{0, 1, 'RBP2'}}, '1') + start_prompt('2') + screen:expect([[ + | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + :{RBP2:2}^ | + ]]) + + set_color_cb('ReturningGlobal', {{0, 1, 'RBP3'}}, '2') + start_prompt('3') + screen:expect([[ + | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + :{RBP3:3}^ | + ]]) + + set_color_cb('ReturningGlobal', {{0, 1, 'RBP4'}}, '3') + start_prompt('4') + screen:expect([[ + | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + :{RBP4:4}^ | + ]]) + + feed('<CR>') + screen:expect([[ + | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + :{RBP3:3}4^ | + ]]) + feed('<CR>') + screen:expect([[ + | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + :{RBP2:2}34^ | + ]]) + feed('<CR>') + screen:expect([[ + | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + :{RBP1:1}234^ | + ]]) + feed('<CR><CR><C-l>') + screen:expect([[ + ^ | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + | + ]]) + eq('1234', meths.get_var('out')) + eq('234', meths.get_var('out1')) + eq('34', meths.get_var('out2')) + eq('4', meths.get_var('out3')) + eq(0, funcs.exists('g:out4')) + end) + it('runs callback with the same data only once', function() + local function new_recording_calls(...) + eq({...}, meths.get_var('recording_calls')) + meths.set_var('recording_calls', {}) + end + set_color_cb('Recording') + start_prompt('') + -- Regression test. Disambiguation: + -- + -- new_recording_calls(expected_result) -- (actual_before_fix) + -- + feed('a') + new_recording_calls('a') -- ('a', 'a') + feed('b') + new_recording_calls('ab') -- ('a', 'ab', 'ab') + feed('c') + new_recording_calls('abc') -- ('ab', 'abc', 'abc') + feed('<BS>') + new_recording_calls('ab') -- ('abc', 'ab', 'ab') + feed('<BS>') + new_recording_calls('a') -- ('ab', 'a', 'a') + feed('<BS>') + new_recording_calls() -- ('a') + feed('<CR><CR>') + eq('', meths.get_var('out')) + end) +end) +describe('Ex commands coloring support', function() + it('works', function() + meths.set_var('Nvim_color_cmdline', 'RainBowParens') + feed(':echo (((1)))') + screen:expect([[ + | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + :echo {RBP1:(}{RBP2:(}{RBP3:(}1{RBP3:)}{RBP2:)}{RBP1:)}^ | + ]]) + end) + it('still executes command-line even if errored out', function() + meths.set_var('Nvim_color_cmdline', 'SplittedMultibyteStart') + feed(':let x = "ยซ"\n') + eq('ยซ', meths.get_var('x')) + local msg = 'E5405: Chunk 0 start 10 splits multibyte character' + eq('\n'..msg, funcs.execute('messages')) + end) + it('does not error out when called from a errorred out cycle', function() + -- Apparently when there is a cycle in which one of the commands errors out + -- this error may be caught by color_cmdline before it is presented to the + -- user. + feed(dedent([[ + :set regexpengine=2 + :for pat in [' \ze*', ' \zs*'] + : try + : let l = matchlist('x x', pat) + : $put ='E888 NOT detected for ' . pat + : catch + : $put ='E888 detected for ' . pat + : endtry + :endfor + ]])) + eq({'', 'E888 detected for \\ze*', 'E888 detected for \\zs*'}, + curbufmeths.get_lines(0, -1, false)) + eq('', funcs.execute('messages')) + end) + it('does not crash when using `n` in debug mode', function() + feed(':debug execute "echo 1"\n') + screen:expect([[ + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + Entering Debug mode. Type "cont" to con| + tinue. | + cmd: execute "echo 1" | + >^ | + ]]) + feed('n\n') + screen:expect([[ + {EOB:~ }| + {EOB:~ }| + Entering Debug mode. Type "cont" to con| + tinue. | + cmd: execute "echo 1" | + >n | + 1 | + {PE:Press ENTER or type command to continue}^ | + ]]) + feed('\n') + screen:expect([[ + ^ | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + | + ]]) + end) + it('does not prevent mapping error from cancelling prompt', function() + command("cnoremap <expr> x execute('throw 42')[-1]") + feed(':#x') + screen:expect([[ + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + :# | + {ERR:Error detected while processing :} | + {ERR:E605: Exception not caught: 42} | + :#^ | + ]]) + feed('<CR>') + screen:expect([[ + ^ | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + | + ]]) + feed('<CR>') + screen:expect([[ + ^ | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + | + ]]) + eq('\nError detected while processing :\nE605: Exception not caught: 42', + meths.command_output('messages')) + end) + it('errors out when failing to get callback', function() + meths.set_var('Nvim_color_cmdline', 42) + feed(':#') + screen:expect([[ + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + : | + {ERR:E5408: Unable to get g:Nvim_color_cmdlin}| + {ERR:e callback: Vim:E6000: Argument is not a}| + {ERR: function or function name} | + :#^ | + ]]) + end) +end) +describe('Expressions coloring support', function() + it('works', function() + meths.set_var('Nvim_color_expr', 'RainBowParens') + feed(':echo <C-r>=(((1)))') + screen:expect([[ + | + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + ={RBP1:(}{RBP2:(}{RBP3:(}1{RBP3:)}{RBP2:)}{RBP1:)}^ | + ]]) + end) + it('errors out when failing to get callback', function() + meths.set_var('Nvim_color_expr', 42) + feed(':<C-r>=1') + screen:expect([[ + {EOB:~ }| + {EOB:~ }| + {EOB:~ }| + = | + {ERR:E5409: Unable to get g:Nvim_color_expr c}| + {ERR:allback: Vim:E6000: Argument is not a fu}| + {ERR:nction or function name} | + =1^ | + ]]) + end) +end) diff --git a/test/functional/ui/cursor_spec.lua b/test/functional/ui/cursor_spec.lua new file mode 100644 index 0000000000..b47210a777 --- /dev/null +++ b/test/functional/ui/cursor_spec.lua @@ -0,0 +1,246 @@ +local helpers = require('test.functional.helpers')(after_each) +local Screen = require('test.functional.ui.screen') +local clear, meths = helpers.clear, helpers.meths +local eq = helpers.eq +local command = helpers.command + +describe('ui/cursor', function() + local screen + + before_each(function() + clear() + screen = Screen.new(25, 5) + screen:attach() + end) + + after_each(function() + screen:detach() + end) + + it("'guicursor' is published as a UI event", function() + local expected_mode_info = { + [1] = { + blinkoff = 0, + blinkon = 0, + blinkwait = 0, + cell_percentage = 0, + cursor_shape = 'block', + name = 'normal', + hl_id = 0, + id_lm = 0, + mouse_shape = 0, + short_name = 'n' }, + [2] = { + blinkoff = 0, + blinkon = 0, + blinkwait = 0, + cell_percentage = 0, + cursor_shape = 'block', + name = 'visual', + hl_id = 0, + id_lm = 0, + mouse_shape = 0, + short_name = 'v' }, + [3] = { + blinkoff = 0, + blinkon = 0, + blinkwait = 0, + cell_percentage = 25, + cursor_shape = 'vertical', + name = 'insert', + hl_id = 0, + id_lm = 0, + mouse_shape = 0, + short_name = 'i' }, + [4] = { + blinkoff = 0, + blinkon = 0, + blinkwait = 0, + cell_percentage = 20, + cursor_shape = 'horizontal', + name = 'replace', + hl_id = 0, + id_lm = 0, + mouse_shape = 0, + short_name = 'r' }, + [5] = { + blinkoff = 0, + blinkon = 0, + blinkwait = 0, + cell_percentage = 0, + cursor_shape = 'block', + name = 'cmdline_normal', + hl_id = 0, + id_lm = 0, + mouse_shape = 0, + short_name = 'c' }, + [6] = { + blinkoff = 0, + blinkon = 0, + blinkwait = 0, + cell_percentage = 25, + cursor_shape = 'vertical', + name = 'cmdline_insert', + hl_id = 0, + id_lm = 0, + mouse_shape = 0, + short_name = 'ci' }, + [7] = { + blinkoff = 0, + blinkon = 0, + blinkwait = 0, + cell_percentage = 20, + cursor_shape = 'horizontal', + name = 'cmdline_replace', + hl_id = 0, + id_lm = 0, + mouse_shape = 0, + short_name = 'cr' }, + [8] = { + blinkoff = 0, + blinkon = 0, + blinkwait = 0, + cell_percentage = 20, + cursor_shape = 'horizontal', + name = 'operator', + hl_id = 0, + id_lm = 0, + mouse_shape = 0, + short_name = 'o' }, + [9] = { + blinkoff = 0, + blinkon = 0, + blinkwait = 0, + cell_percentage = 25, + cursor_shape = 'vertical', + name = 'visual_select', + hl_id = 0, + id_lm = 0, + mouse_shape = 0, + short_name = 've' }, + [10] = { + name = 'cmdline_hover', + mouse_shape = 0, + short_name = 'e' }, + [11] = { + name = 'statusline_hover', + mouse_shape = 0, + short_name = 's' }, + [12] = { + name = 'statusline_drag', + mouse_shape = 0, + short_name = 'sd' }, + [13] = { + name = 'vsep_hover', + mouse_shape = 0, + short_name = 'vs' }, + [14] = { + name = 'vsep_drag', + mouse_shape = 0, + short_name = 'vd' }, + [15] = { + name = 'more', + mouse_shape = 0, + short_name = 'm' }, + [16] = { + name = 'more_lastline', + mouse_shape = 0, + short_name = 'ml' }, + [17] = { + blinkoff = 0, + blinkon = 0, + blinkwait = 0, + cell_percentage = 0, + cursor_shape = 'block', + name = 'showmatch', + hl_id = 0, + id_lm = 0, + short_name = 'sm' }, + } + + screen:expect(function() + -- Default 'guicursor', published on startup. + eq(expected_mode_info, screen._mode_info) + eq(true, screen._cursor_style_enabled) + eq('normal', screen.mode) + end) + + -- Event is published ONLY if the cursor style changed. + screen._mode_info = nil + command("echo 'test'") + screen:expect([[ + ^ | + ~ | + ~ | + ~ | + test | + ]], nil, nil, function() + eq(nil, screen._mode_info) + end) + + -- Change the cursor style. + helpers.command('set guicursor=n-v-c:block,i-ci-ve:ver25,r-cr-o:hor20' + ..',a:blinkwait700-blinkoff400-blinkon250-Cursor/lCursor' + ..',sm:block-blinkwait175-blinkoff150-blinkon175') + + -- Update the expected values. + for _, m in ipairs(expected_mode_info) do + if m.name == 'showmatch' then + if m.blinkon then m.blinkon = 175 end + if m.blinkoff then m.blinkoff = 150 end + if m.blinkwait then m.blinkwait = 175 end + else + if m.blinkon then m.blinkon = 250 end + if m.blinkoff then m.blinkoff = 400 end + if m.blinkwait then m.blinkwait = 700 end + end + if m.hl_id then m.hl_id = 48 end + if m.id_lm then m.id_lm = 49 end + end + + -- Assert the new expectation. + screen:expect(function() + eq(expected_mode_info, screen._mode_info) + eq(true, screen._cursor_style_enabled) + eq('normal', screen.mode) + end) + + -- Another cursor style. + meths.set_option('guicursor', 'n-v-c:ver35-blinkwait171-blinkoff172-blinkon173' + ..',ve:hor35,o:ver50,i-ci:block,r-cr:hor90,sm:ver42') + screen:expect(function() + local named = {} + for _, m in ipairs(screen._mode_info) do + named[m.name] = m + end + eq('vertical', named.normal.cursor_shape) + eq(35, named.normal.cell_percentage) + eq('horizontal', named.visual_select.cursor_shape) + eq(35, named.visual_select.cell_percentage) + eq('vertical', named.operator.cursor_shape) + eq(50, named.operator.cell_percentage) + eq('block', named.insert.cursor_shape) + eq('vertical', named.showmatch.cursor_shape) + eq(90, named.cmdline_replace.cell_percentage) + eq(171, named.normal.blinkwait) + eq(172, named.normal.blinkoff) + eq(173, named.normal.blinkon) + eq(42, named.showmatch.cell_percentage) + end) + end) + + it("empty 'guicursor' sets cursor_shape=block in all modes", function() + meths.set_option('guicursor', '') + screen:expect(function() + -- Empty 'guicursor' sets enabled=false. + eq(false, screen._cursor_style_enabled) + for _, m in ipairs(screen._mode_info) do + if m['cursor_shape'] ~= nil then + eq('block', m.cursor_shape) + eq(0, m.blinkon) + end + end + end) + end) + +end) diff --git a/test/functional/ui/highlight_spec.lua b/test/functional/ui/highlight_spec.lua index 945b16ef92..d1357ea525 100644 --- a/test/functional/ui/highlight_spec.lua +++ b/test/functional/ui/highlight_spec.lua @@ -2,23 +2,24 @@ local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') local os = require('os') local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local execute, request, eq = helpers.execute, helpers.request, helpers.eq +local command = helpers.command +local eval, exc_exec = helpers.eval, helpers.exc_exec +local feed_command, request, eq = helpers.feed_command, helpers.request, helpers.eq +local curbufmeths = helpers.curbufmeths -if helpers.pending_win32(pending) then return end - -describe('color scheme compatibility', function() +describe('colorscheme compatibility', function() before_each(function() clear() end) it('t_Co is set to 256 by default', function() - eq('256', request('vim_eval', '&t_Co')) + eq('256', eval('&t_Co')) request('nvim_set_option', 't_Co', '88') - eq('88', request('vim_eval', '&t_Co')) + eq('88', eval('&t_Co')) end) end) -describe('manual syntax highlight', function() +describe('highlight: `:syntax manual`', function() -- When using manual syntax highlighting, it should be preserved even when -- switching buffers... bug did only occur without :set hidden -- Ref: vim patch 7.4.1236 @@ -41,18 +42,18 @@ describe('manual syntax highlight', function() end) it("works with buffer switch and 'hidden'", function() - execute('e tmp1.vim') - execute('e Xtest-functional-ui-highlight.tmp.vim') - execute('filetype on') - execute('syntax manual') - execute('set ft=vim') - execute('set syntax=ON') + feed_command('e tmp1.vim') + feed_command('e Xtest-functional-ui-highlight.tmp.vim') + feed_command('filetype on') + feed_command('syntax manual') + feed_command('set ft=vim') + feed_command('set syntax=ON') feed('iecho 1<esc>0') - execute('set hidden') - execute('w') - execute('bn') - execute('bp') + feed_command('set hidden') + feed_command('w') + feed_command('bn') + feed_command('bp') screen:expect([[ {1:^echo} 1 | {0:~ }| @@ -63,32 +64,32 @@ describe('manual syntax highlight', function() end) it("works with buffer switch and 'nohidden'", function() - execute('e tmp1.vim') - execute('e Xtest-functional-ui-highlight.tmp.vim') - execute('filetype on') - execute('syntax manual') - execute('set ft=vim') - execute('set syntax=ON') + command('e tmp1.vim') + command('e Xtest-functional-ui-highlight.tmp.vim') + command('filetype on') + command('syntax manual') + command('set filetype=vim fileformat=unix') + command('set syntax=ON') feed('iecho 1<esc>0') - execute('set nohidden') - execute('w') - execute('bn') - execute('bp') + command('set nohidden') + command('w') + command('silent bn') + eq("tmp1.vim", eval("fnamemodify(bufname('%'), ':t')")) + feed_command('silent bp') + eq("Xtest-functional-ui-highlight.tmp.vim", eval("fnamemodify(bufname('%'), ':t')")) screen:expect([[ {1:^echo} 1 | {0:~ }| {0:~ }| {0:~ }| - <ht.tmp.vim" 1L, 7C | + :silent bp | ]]) end) end) -describe('Default highlight groups', function() - -- Test the default attributes for highlight groups shown by the :highlight - -- command +describe('highlight defaults', function() local screen before_each(function() @@ -107,7 +108,7 @@ describe('Default highlight groups', function() [1] = {reverse = true, bold = true}, -- StatusLine [2] = {reverse = true} -- StatusLineNC }) - execute('sp', 'vsp', 'vsp') + feed_command('sp', 'vsp', 'vsp') screen:expect([[ ^ {2:|} {2:|} | {0:~ }{2:|}{0:~ }{2:|}{0:~ }| @@ -200,58 +201,31 @@ describe('Default highlight groups', function() it('insert mode text', function() feed('i') + screen:try_resize(53, 4) screen:expect([[ ^ | {0:~ }| {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| {1:-- INSERT --} | ]], {[0] = {bold=true, foreground=Screen.colors.Blue}, [1] = {bold = true}}) end) it('end of file markers', function() + screen:try_resize(53, 4) screen:expect([[ ^ | {1:~ }| {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| | ]], {[1] = {bold = true, foreground = Screen.colors.Blue}}) end) it('"wait return" text', function() + screen:try_resize(53, 4) feed(':ls<cr>') screen:expect([[ {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| :ls | 1 %a "[No Name]" line 1 | {1:Press ENTER or type command to continue}^ | @@ -259,89 +233,84 @@ describe('Default highlight groups', function() [1] = {bold = true, foreground = Screen.colors.SeaGreen}}) feed('<cr>') -- skip the "Press ENTER..." state or tests will hang end) + it('can be cleared and linked to other highlight groups', function() - execute('highlight clear ModeMsg') + screen:try_resize(53, 4) + feed_command('highlight clear ModeMsg') feed('i') screen:expect([[ ^ | {0:~ }| {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| -- INSERT -- | ]], {[0] = {bold=true, foreground=Screen.colors.Blue}, [1] = {bold=true}}) feed('<esc>') - execute('highlight CustomHLGroup guifg=red guibg=green') - execute('highlight link ModeMsg CustomHLGroup') + feed_command('highlight CustomHLGroup guifg=red guibg=green') + feed_command('highlight link ModeMsg CustomHLGroup') feed('i') screen:expect([[ ^ | {0:~ }| {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| {1:-- INSERT --} | ]], {[0] = {bold=true, foreground=Screen.colors.Blue}, [1] = {foreground = Screen.colors.Red, background = Screen.colors.Green}}) end) + it('can be cleared by assigning NONE', function() - execute('syn keyword TmpKeyword neovim') - execute('hi link TmpKeyword ErrorMsg') + screen:try_resize(53, 4) + feed_command('syn keyword TmpKeyword neovim') + feed_command('hi link TmpKeyword ErrorMsg') insert('neovim') screen:expect([[ {1:neovi^m} | {0:~ }| {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| | ]], { [0] = {bold=true, foreground=Screen.colors.Blue}, [1] = {foreground = Screen.colors.White, background = Screen.colors.Red} }) - execute("hi ErrorMsg term=NONE cterm=NONE ctermfg=NONE ctermbg=NONE" + feed_command("hi ErrorMsg term=NONE cterm=NONE ctermfg=NONE ctermbg=NONE" .. " gui=NONE guifg=NONE guibg=NONE guisp=NONE") screen:expect([[ neovi^m | {0:~ }| {0:~ }| + | + ]], {[0] = {bold=true, foreground=Screen.colors.Blue}}) + end) + + it('Cursor after `:hi clear|syntax reset` #6508', function() + command('highlight clear|syntax reset') + eq('guifg=bg guibg=fg', eval([[matchstr(execute('hi Cursor'), '\v(gui|cterm).*$')]])) + end) + + it('Whitespace highlight', function() + screen:try_resize(53, 4) + feed_command('highlight NonText gui=NONE guifg=#FF0000') + feed_command('set listchars=space:.,tab:>-,trail:*,eol:ยฌ list') + insert(' ne \t o\tv im ') + screen:expect([[ + ne{0:.>----.}o{0:>-----}v{0:..}im{0:*^*ยฌ} | {0:~ }| {0:~ }| + | + ]], { + [0] = {foreground=Screen.colors.Red}, + [1] = {foreground=Screen.colors.Blue}, + }) + feed_command('highlight Whitespace gui=NONE guifg=#0000FF') + screen:expect([[ + ne{1:.>----.}o{1:>-----}v{1:..}im{1:*^*}{0:ยฌ} | {0:~ }| {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - | - ]], {[0] = {bold=true, foreground=Screen.colors.Blue}}) + :highlight Whitespace gui=NONE guifg=#0000FF | + ]], { + [0] = {foreground=Screen.colors.Red}, + [1] = {foreground=Screen.colors.Blue}, + }) end) end) @@ -355,19 +324,19 @@ describe('guisp (special/undercurl)', function() end) it('can be set and is applied like foreground or background', function() - execute('syntax on') - execute('syn keyword TmpKeyword neovim') - execute('syn keyword TmpKeyword1 special') - execute('syn keyword TmpKeyword2 specialwithbg') - execute('syn keyword TmpKeyword3 specialwithfg') - execute('hi! Awesome guifg=red guibg=yellow guisp=red') - execute('hi! Awesome1 guisp=red') - execute('hi! Awesome2 guibg=yellow guisp=red') - execute('hi! Awesome3 guifg=red guisp=red') - execute('hi link TmpKeyword Awesome') - execute('hi link TmpKeyword1 Awesome1') - execute('hi link TmpKeyword2 Awesome2') - execute('hi link TmpKeyword3 Awesome3') + feed_command('syntax on') + feed_command('syn keyword TmpKeyword neovim') + feed_command('syn keyword TmpKeyword1 special') + feed_command('syn keyword TmpKeyword2 specialwithbg') + feed_command('syn keyword TmpKeyword3 specialwithfg') + feed_command('hi! Awesome guifg=red guibg=yellow guisp=red') + feed_command('hi! Awesome1 guisp=red') + feed_command('hi! Awesome2 guibg=yellow guisp=red') + feed_command('hi! Awesome3 guifg=red guisp=red') + feed_command('hi link TmpKeyword Awesome') + feed_command('hi link TmpKeyword1 Awesome1') + feed_command('hi link TmpKeyword2 Awesome2') + feed_command('hi link TmpKeyword3 Awesome3') insert([[ neovim awesome neovim @@ -401,7 +370,7 @@ describe('guisp (special/undercurl)', function() end) end) -describe("'cursorline' with 'listchars'", function() +describe("'listchars' highlight", function() local screen before_each(function() @@ -419,8 +388,8 @@ describe("'cursorline' with 'listchars'", function() [0] = {bold=true, foreground=Screen.colors.Blue}, [1] = {background=Screen.colors.Grey90} }) - execute('highlight clear ModeMsg') - execute('set cursorline') + feed_command('highlight clear ModeMsg') + feed_command('set cursorline') feed('i') screen:expect([[ {1:^ }| @@ -445,7 +414,7 @@ describe("'cursorline' with 'listchars'", function() {0:~ }| | ]]) - execute('set nocursorline') + feed_command('set nocursorline') screen:expect([[ abcdefg | kkasd^f | @@ -469,8 +438,8 @@ describe("'cursorline' with 'listchars'", function() ^f | | ]]) - execute('set cursorline') - execute('set cursorcolumn') + feed_command('set cursorline') + feed_command('set cursorcolumn') feed('kkiabcdefghijk<esc>hh') screen:expect([[ kkasd {1: } | @@ -509,11 +478,11 @@ describe("'cursorline' with 'listchars'", function() foreground=Screen.colors.Red, }, }) - execute('highlight clear ModeMsg') - execute('highlight SpecialKey guifg=#FF0000') - execute('set cursorline') - execute('set tabstop=8') - execute('set listchars=space:.,eol:ยฌ,tab:>-,extends:>,precedes:<,trail:* list') + feed_command('highlight clear ModeMsg') + feed_command('highlight Whitespace guifg=#FF0000') + feed_command('set cursorline') + feed_command('set tabstop=8') + feed_command('set listchars=space:.,eol:ยฌ,tab:>-,extends:>,precedes:<,trail:* list') feed('i\t abcd <cr>\t abcd <cr><esc>k') screen:expect([[ {5:>-------.}abcd{5:*}{4:ยฌ} | @@ -530,7 +499,7 @@ describe("'cursorline' with 'listchars'", function() {4:~ }| | ]]) - execute('set nocursorline') + feed_command('set nocursorline') screen:expect([[ {5:^>-------.}abcd{5:*}{4:ยฌ} | {5:>-------.}abcd{5:*}{4:ยฌ} | @@ -538,7 +507,7 @@ describe("'cursorline' with 'listchars'", function() {4:~ }| :set nocursorline | ]]) - execute('set nowrap') + feed_command('set nowrap') feed('ALorem ipsum dolor sit amet<ESC>0') screen:expect([[ {5:^>-------.}abcd{5:.}Lorem{4:>}| @@ -547,7 +516,7 @@ describe("'cursorline' with 'listchars'", function() {4:~ }| | ]]) - execute('set cursorline') + feed_command('set cursorline') screen:expect([[ {2:^>-------.}{1:abcd}{2:.}{1:Lorem}{4:>}| {5:>-------.}abcd{5:*}{4:ยฌ} | @@ -605,12 +574,12 @@ describe("'cursorline' with 'listchars'", function() bold=true, }, }) - execute('highlight clear ModeMsg') - execute('highlight SpecialKey guifg=#FF0000') - execute('set cursorline') - execute('set tabstop=8') - execute('set nowrap') - execute('set listchars=space:.,eol:ยฌ,tab:>-,extends:>,precedes:<,trail:* list') + feed_command('highlight clear ModeMsg') + feed_command('highlight Whitespace guifg=#FF0000') + feed_command('set cursorline') + feed_command('set tabstop=8') + feed_command('set nowrap') + feed_command('set listchars=space:.,eol:ยฌ,tab:>-,extends:>,precedes:<,trail:* list') feed('i\t abcd <cr>\t abcd Lorem ipsum dolor sit amet<cr><esc>kkk0') screen:expect([[ {2:^>-------.}{1:abcd}{2:*}{3:ยฌ}{1: }| @@ -644,4 +613,453 @@ describe("'cursorline' with 'listchars'", function() | ]]) end) + + it("'cursorline' with :match", function() + screen:set_default_attr_ids({ + [0] = {bold=true, foreground=Screen.colors.Blue}, + [1] = {background=Screen.colors.Grey90}, + [2] = {foreground=Screen.colors.Red}, + [3] = {foreground=Screen.colors.Green1}, + }) + feed_command('highlight clear ModeMsg') + feed_command('highlight Whitespace guifg=#FF0000') + feed_command('highlight Error guifg=#00FF00') + feed_command('set nowrap') + feed('ia \t bc \t <esc>') + screen:expect([[ + a bc ^ | + {0:~ }| + {0:~ }| + {0:~ }| + | + ]]) + feed_command('set listchars=space:.,eol:ยฌ,tab:>-,extends:>,precedes:<,trail:* list') + screen:expect([[ + a{2:.>-----.}bc{2:*>---*^*}{0:ยฌ} | + {0:~ }| + {0:~ }| + {0:~ }| + | + ]]) + feed_command('match Error /\\s\\+$/') + screen:expect([[ + a{2:.>-----.}bc{3:*>---*^*}{0:ยฌ} | + {0:~ }| + {0:~ }| + {0:~ }| + | + ]]) + end) +end) + +describe("'winhighlight' highlight", function() + local screen + + before_each(function() + clear() + screen = Screen.new(20,8) + screen:attach() + screen:set_default_attr_ids({ + [0] = {bold=true, foreground=Screen.colors.Blue}, + [1] = {background = Screen.colors.DarkBlue}, + [2] = {background = Screen.colors.DarkBlue, bold = true, foreground = Screen.colors.Blue1}, + [3] = {bold = true, reverse = true}, + [4] = {reverse = true}, + [5] = {background = Screen.colors.DarkGreen}, + [6] = {background = Screen.colors.DarkGreen, bold = true, foreground = Screen.colors.Blue1}, + [7] = {background = Screen.colors.DarkMagenta}, + [8] = {background = Screen.colors.DarkMagenta, bold = true, foreground = Screen.colors.Blue1}, + [9] = {foreground = Screen.colors.Brown}, + [10] = {foreground = Screen.colors.Brown, background = Screen.colors.DarkBlue}, + [11] = {background = Screen.colors.DarkBlue, bold = true, reverse = true}, + [12] = {background = Screen.colors.DarkGreen, reverse = true}, + [13] = {background = Screen.colors.Magenta4, reverse = true}, + [14] = {background = Screen.colors.DarkBlue, reverse = true}, + [15] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red}, + [16] = {foreground = Screen.colors.Blue1}, + [17] = {background = Screen.colors.LightRed}, + [18] = {background = Screen.colors.Gray90}, + [19] = {foreground = Screen.colors.LightGrey, background = Screen.colors.DarkGray}, + [20] = {background = Screen.colors.LightGrey, underline = true}, + [21] = {bold = true}, + [22] = {bold = true, foreground = Screen.colors.SeaGreen4}, + [23] = {background = Screen.colors.LightMagenta}, + [24] = {background = Screen.colors.WebGray}, + }) + command("hi Background1 guibg=DarkBlue") + command("hi Background2 guibg=DarkGreen") + end) + + it('works for background color', function() + insert("aa") + command("split") + command("set winhl=Normal:Background1") + screen:expect([[ + {1:a^a }| + {2:~ }| + {2:~ }| + {11:[No Name] [+] }| + aa | + {0:~ }| + {4:[No Name] [+] }| + | + ]]) + + command("enew") + screen:expect([[ + {1:^ }| + {2:~ }| + {2:~ }| + {11:[No Name] }| + aa | + {0:~ }| + {4:[No Name] [+] }| + | + ]]) + end) + + it('handles invalid values', function() + command("set winhl=Normal:Background1") + screen:expect([[ + {1:^ }| + {2:~ }| + {2:~ }| + {2:~ }| + {2:~ }| + {2:~ }| + {2:~ }| + | + ]]) + + eq('Vim(set):E474: Invalid argument: winhl=xxx:yyy', + exc_exec("set winhl=xxx:yyy")) + eq('Normal:Background1', eval('&winhl')) + screen:expect([[ + {1:^ }| + {2:~ }| + {2:~ }| + {2:~ }| + {2:~ }| + {2:~ }| + {2:~ }| + | + ]]) + end) + + + it('works local to the buffer', function() + insert("aa") + command("split") + command("setlocal winhl=Normal:Background1") + screen:expect([[ + {1:a^a }| + {2:~ }| + {2:~ }| + {11:[No Name] [+] }| + aa | + {0:~ }| + {4:[No Name] [+] }| + | + ]]) + + command("enew") + screen:expect([[ + ^ | + {0:~ }| + {0:~ }| + {3:[No Name] }| + aa | + {0:~ }| + {4:[No Name] [+] }| + | + ]]) + + command("bnext") + screen:expect([[ + {1:^aa }| + {2:~ }| + {2:~ }| + {11:[No Name] [+] }| + aa | + {0:~ }| + {4:[No Name] [+] }| + <f 1 --100%-- col 1 | + ]]) + end) + + it('for inactive window background works', function() + command("set winhl=Normal:Background1,NormalNC:Background2") + -- tests global value is copied across split + command("split") + screen:expect([[ + {1:^ }| + {2:~ }| + {2:~ }| + {11:[No Name] }| + {5: }| + {6:~ }| + {12:[No Name] }| + | + ]]) + + feed("<c-w><c-w>") + screen:expect([[ + {5: }| + {6:~ }| + {6:~ }| + {12:[No Name] }| + {1:^ }| + {2:~ }| + {11:[No Name] }| + | + ]]) + + feed("<c-w><c-w>") + screen:expect([[ + {1:^ }| + {2:~ }| + {2:~ }| + {11:[No Name] }| + {5: }| + {6:~ }| + {12:[No Name] }| + | + ]]) + end) + + it('works with NormalNC', function() + command("hi NormalNC guibg=DarkMagenta") + -- tests global value is copied across split + command("split") + screen:expect([[ + ^ | + {0:~ }| + {0:~ }| + {3:[No Name] }| + {7: }| + {8:~ }| + {13:[No Name] }| + | + ]]) + + command("wincmd w") + screen:expect([[ + {7: }| + {8:~ }| + {8:~ }| + {13:[No Name] }| + ^ | + {0:~ }| + {3:[No Name] }| + | + ]]) + + + -- winbg=Normal:... overrides global NormalNC + command("set winhl=Normal:Background1") + screen:expect([[ + {7: }| + {8:~ }| + {8:~ }| + {13:[No Name] }| + {1:^ }| + {2:~ }| + {11:[No Name] }| + | + ]]) + + command("wincmd w") + screen:expect([[ + ^ | + {0:~ }| + {0:~ }| + {3:[No Name] }| + {1: }| + {2:~ }| + {14:[No Name] }| + | + ]]) + + command("wincmd w") + command("set winhl=Normal:Background1,NormalNC:Background2") + screen:expect([[ + {7: }| + {8:~ }| + {8:~ }| + {13:[No Name] }| + {1:^ }| + {2:~ }| + {11:[No Name] }| + | + ]]) + + command("wincmd w") + screen:expect([[ + ^ | + {0:~ }| + {0:~ }| + {3:[No Name] }| + {5: }| + {6:~ }| + {12:[No Name] }| + | + ]]) + end) + + it('background applies also to non-text', function() + insert('Lorem ipsum dolor sit amet ') + command('set shiftwidth=2') + feed('>>') + command('set number') + command('set breakindent') + command('set briopt=shift:5,min:0') + command('set list') + command('set showbreak=โช') + screen:expect([[ + {9: 1 } ^Lorem ipsum do| + {9: } {0:โช}lor sit | + {9: } {0:โช}amet{0:-} | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + | + ]]) + + command('set winhl=Normal:Background1') + screen:expect([[ + {10: 1 }{1: ^Lorem ipsum do}| + {10: }{1: }{2:โช}{1:lor sit }| + {10: }{1: }{2:โช}{1:amet}{2:-}{1: }| + {2:~ }| + {2:~ }| + {2:~ }| + {2:~ }| + | + ]]) + + command('set nowrap') + command('set listchars+=extends:โฏ,precedes:โฎ') + feed('3w') + screen:expect([[ + {10: 1 }{2:โฎ}{1: dolor ^sit ame}{2:โฏ}| + {2:~ }| + {2:~ }| + {2:~ }| + {2:~ }| + {2:~ }| + {2:~ }| + | + ]]) + end) + + it('can override NonText, Conceal and EndOfBuffer', function() + curbufmeths.set_lines(0,-1,true, {"raa\000"}) + command('call matchaddpos("Conceal", [[1,2]], 0, -1, {"conceal": "#"})') + command('set cole=2 cocu=nvic') + command('split') + command('call matchaddpos("Conceal", [[1,2]], 0, -1, {"conceal": "#"})') + command('set winhl=SpecialKey:ErrorMsg,EndOfBuffer:Background1,' + ..'Conceal:Background2') + + screen:expect([[ + ^r{5:#}a{15:^@} | + {1:~ }| + {1:~ }| + {3:[No Name] [+] }| + r{19:#}a{16:^@} | + {0:~ }| + {4:[No Name] [+] }| + | + ]]) + end) + + it('can override LineNr, CursorColumn and ColorColumn', function() + insert('very text\nmore text') + command('set number') + command('set colorcolumn=2') + command('set cursorcolumn') + + command('split') + command('set winhl=LineNr:Background1,CursorColumn:Background2,' + ..'ColorColumn:ErrorMsg') + screen:expect([[ + {1: 1 }v{15:e}ry tex{5:t} | + {1: 2 }m{15:o}re tex^t | + {0:~ }| + {3:[No Name] [+] }| + {9: 1 }v{17:e}ry tex{18:t} | + {9: 2 }m{17:o}re text | + {4:[No Name] [+] }| + | + ]]) + end) + + it('can override Tabline', function() + command('tabnew') + command('set winhl=TabLine:Background1,TabLineSel:ErrorMsg') + + screen:expect([[ + {20: No Name] }{15: No Name]}{20:X}| + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + | + ]]) + command("tabnext") + screen:expect([[ + {21: No Name] }{1: No Name]}{20:X}| + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + | + ]]) + end) + + it('can override popupmenu', function() + insert('word wording wordy') + command('split') + command('set winhl=Pmenu:Background1,PmenuSel:Background2,' + ..'PmenuSbar:ErrorMsg,PmenuThumb:Normal') + screen:expect([[ + word wording word^y | + {0:~ }| + {0:~ }| + {3:[No Name] [+] }| + word wording wordy | + {0:~ }| + {4:[No Name] [+] }| + | + ]]) + + feed('oword<c-x><c-p>') + screen:expect([[ + word wording wordy | + wordy^ | + {1:word }{0: }| + {1:wording }{3: }| + {5:wordy }rdy | + wordy | + {4:[No Name] [+] }| + {21:-- }{22:match 1 of 3} | + ]]) + + feed('<esc>u<c-w><c-w>oword<c-x><c-p>') + screen:expect([[ + word wording wordy | + wordy | + {23:word }{0: }| + {23:wording }{4: }| + {24:wordy }rdy | + wordy^ | + {3:[No Name] [+] }| + {21:-- }{22:match 1 of 3} | + ]]) + end) end) diff --git a/test/functional/ui/inccommand_spec.lua b/test/functional/ui/inccommand_spec.lua index 35aeb6e67c..64965ccb94 100644 --- a/test/functional/ui/inccommand_spec.lua +++ b/test/functional/ui/inccommand_spec.lua @@ -1,10 +1,11 @@ local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') local clear = helpers.clear +local command = helpers.command local curbufmeths = helpers.curbufmeths local eq = helpers.eq local eval = helpers.eval -local execute = helpers.execute +local feed_command = helpers.feed_command local expect = helpers.expect local feed = helpers.feed local insert = helpers.insert @@ -21,9 +22,9 @@ local default_text = [[ local function common_setup(screen, inccommand, text) if screen then - execute("syntax on") - execute("set nohlsearch") - execute("hi Substitute guifg=red guibg=yellow") + command("syntax on") + command("set nohlsearch") + command("hi Substitute guifg=red guibg=yellow") screen:attach() screen:set_default_attr_ids({ [1] = {foreground = Screen.colors.Fuchsia}, @@ -42,10 +43,11 @@ local function common_setup(screen, inccommand, text) [14] = {foreground = Screen.colors.White, background = Screen.colors.Red}, [15] = {bold=true, foreground=Screen.colors.Blue}, [16] = {background=Screen.colors.Grey90}, -- cursorline + vis = {background=Screen.colors.LightGrey} }) end - execute("set inccommand=" .. (inccommand and inccommand or "")) + command("set inccommand=" .. (inccommand and inccommand or "")) if text then insert(text) @@ -90,8 +92,8 @@ describe(":substitute, 'inccommand' preserves", function() local screen = Screen.new(30,10) common_setup(screen, "split", "ABC") - execute("%s/AB/BA/") - execute("ls") + feed_command("%s/AB/BA/") + feed_command("ls") screen:expect([[ {15:~ }| @@ -110,25 +112,25 @@ describe(":substitute, 'inccommand' preserves", function() for _, case in pairs{"", "split", "nosplit"} do it("various delimiters (inccommand="..case..")", function() insert(default_text) - execute("set inccommand=" .. case) + feed_command("set inccommand=" .. case) local delims = { '/', '#', ';', '%', ',', '@', '!', ''} for _,delim in pairs(delims) do - execute("%s"..delim.."lines"..delim.."LINES"..delim.."g") + feed_command("%s"..delim.."lines"..delim.."LINES"..delim.."g") expect([[ Inc substitution on two LINES ]]) - execute("undo") + feed_command("undo") end end) end for _, case in pairs{"", "split", "nosplit"} do it("'undolevels' (inccommand="..case..")", function() - execute("set undolevels=139") - execute("setlocal undolevels=34") - execute("set inccommand=" .. case) + feed_command("set undolevels=139") + feed_command("setlocal undolevels=34") + feed_command("set inccommand=" .. case) insert("as") feed(":%s/as/glork/<enter>") eq(meths.get_option('undolevels'), 139) @@ -138,8 +140,8 @@ describe(":substitute, 'inccommand' preserves", function() for _, case in ipairs({"", "split", "nosplit"}) do it("empty undotree() (inccommand="..case..")", function() - execute("set undolevels=1000") - execute("set inccommand=" .. case) + feed_command("set undolevels=1000") + feed_command("set inccommand=" .. case) local expected_undotree = eval("undotree()") -- Start typing an incomplete :substitute command. @@ -156,8 +158,8 @@ describe(":substitute, 'inccommand' preserves", function() for _, case in ipairs({"", "split", "nosplit"}) do it("undotree() with branches (inccommand="..case..")", function() - execute("set undolevels=1000") - execute("set inccommand=" .. case) + feed_command("set undolevels=1000") + feed_command("set inccommand=" .. case) -- Make some changes. feed([[isome text 1<C-\><C-N>]]) feed([[osome text 2<C-\><C-N>]]) @@ -191,7 +193,7 @@ describe(":substitute, 'inccommand' preserves", function() for _, case in pairs{"", "split", "nosplit"} do it("b:changedtick (inccommand="..case..")", function() - execute("set inccommand=" .. case) + feed_command("set inccommand=" .. case) feed([[isome text 1<C-\><C-N>]]) feed([[osome text 2<C-\><C-N>]]) local expected_tick = eval("b:changedtick") @@ -207,6 +209,42 @@ describe(":substitute, 'inccommand' preserves", function() end) end + for _, case in pairs{"", "split", "nosplit"} do + it("visual selection for non-previewable command (inccommand="..case..") #5888", function() + local screen = Screen.new(30,10) + common_setup(screen, case, default_text) + feed('1G2V') + + feed(':s') + screen:expect([[ + {vis:Inc substitution on} | + t{vis:wo lines} | + | + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + :'<,'>s^ | + ]]) + + feed('o') + screen:expect([[ + {vis:Inc substitution on} | + t{vis:wo lines} | + | + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + :'<,'>so^ | + ]]) + end) + end + end) describe(":substitute, 'inccommand' preserves undo", function() @@ -234,18 +272,18 @@ describe(":substitute, 'inccommand' preserves undo", function() local function test_sub(substring, split, redoable) clear() - execute("set inccommand=" .. split) + feed_command("set inccommand=" .. split) insert("1") feed("o2<esc>") - execute("undo") + feed_command("undo") feed("o3<esc>") if redoable then feed("o4<esc>") - execute("undo") + feed_command("undo") end feed(substring.. "<enter>") - execute("undo") + feed_command("undo") feed("g-") expect([[ @@ -260,15 +298,15 @@ describe(":substitute, 'inccommand' preserves undo", function() local function test_notsub(substring, split, redoable) clear() - execute("set inccommand=" .. split) + feed_command("set inccommand=" .. split) insert("1") feed("o2<esc>") - execute("undo") + feed_command("undo") feed("o3<esc>") if redoable then feed("o4<esc>") - execute("undo") + feed_command("undo") end feed(substring .. "<esc>") @@ -294,7 +332,7 @@ describe(":substitute, 'inccommand' preserves undo", function() local function test_threetree(substring, split) clear() - execute("set inccommand=" .. split) + feed_command("set inccommand=" .. split) insert("1") feed("o2<esc>") @@ -315,6 +353,14 @@ describe(":substitute, 'inccommand' preserves undo", function() feed("2u") feed(substring .. "<esc>") + expect([[ + 1]]) + feed("g-") + expect([[ + ]]) + feed("g+") + expect([[ + 1]]) feed("<c-r>") expect([[ 1 @@ -337,9 +383,7 @@ describe(":substitute, 'inccommand' preserves undo", function() 2]]) end - -- TODO(vim): This does not work, even in Vim. - -- Waiting for fix (perhaps from upstream). - pending("at a non-leaf of the undo tree", function() + it("at a non-leaf of the undo tree", function() for _, case in pairs(cases) do for _, str in pairs(substrings) do for _, redoable in pairs({true}) do @@ -381,22 +425,22 @@ describe(":substitute, 'inccommand' preserves undo", function() for _, case in pairs(cases) do clear() common_setup(nil, case, default_text) - execute("set undolevels=0") + feed_command("set undolevels=0") feed("1G0") insert("X") feed(":%s/tw/MO/<esc>") - execute("undo") + feed_command("undo") expect(default_text) - execute("undo") + feed_command("undo") expect(default_text:gsub("Inc", "XInc")) - execute("undo") + feed_command("undo") - execute("%s/tw/MO/g") + feed_command("%s/tw/MO/g") expect(default_text:gsub("tw", "MO")) - execute("undo") + feed_command("undo") expect(default_text) - execute("undo") + feed_command("undo") expect(default_text:gsub("tw", "MO")) end end) @@ -407,13 +451,13 @@ describe(":substitute, 'inccommand' preserves undo", function() for _, case in pairs(cases) do clear() common_setup(screen, case, default_text) - execute("set undolevels=1") + feed_command("set undolevels=1") feed("1G0") insert("X") feed("IY<esc>") feed(":%s/tw/MO/<esc>") - -- execute("undo") here would cause "Press ENTER". + -- feed_command("undo") here would cause "Press ENTER". feed("u") expect(default_text:gsub("Inc", "XInc")) feed("u") @@ -439,7 +483,7 @@ describe(":substitute, 'inccommand' preserves undo", function() {15:~ }| {15:~ }| {15:~ }| - Already...st change | + Already ...t change | ]]) else screen:expect([[ @@ -452,7 +496,7 @@ describe(":substitute, 'inccommand' preserves undo", function() {15:~ }| {15:~ }| {15:~ }| - Already...st change | + Already ...t change | ]]) end end @@ -465,13 +509,13 @@ describe(":substitute, 'inccommand' preserves undo", function() for _, case in pairs(cases) do clear() common_setup(screen, case, default_text) - execute("set undolevels=2") + feed_command("set undolevels=2") feed("2GAx<esc>") feed("Ay<esc>") feed("Az<esc>") feed(":%s/tw/AR<esc>") - -- using execute("undo") here will result in a "Press ENTER" prompt + -- feed_command("undo") here would cause "Press ENTER". feed("u") expect(default_text:gsub("lines", "linesxy")) feed("u") @@ -491,7 +535,7 @@ describe(":substitute, 'inccommand' preserves undo", function() {15:~ }| {15:~ }| {15:~ }| - Already...st change | + Already ...t change | ]]) else screen:expect([[ @@ -504,7 +548,7 @@ describe(":substitute, 'inccommand' preserves undo", function() {15:~ }| {15:~ }| {15:~ }| - Already...st change | + Already ...t change | ]]) end @@ -531,7 +575,7 @@ describe(":substitute, 'inccommand' preserves undo", function() {15:~ }| {15:~ }| {15:~ }| - Already...st change | + Already ...t change | ]]) else screen:expect([[ @@ -544,7 +588,7 @@ describe(":substitute, 'inccommand' preserves undo", function() {15:~ }| {15:~ }| {15:~ }| - Already...st change | + Already ...t change | ]]) end screen:detach() @@ -558,9 +602,9 @@ describe(":substitute, 'inccommand' preserves undo", function() clear() common_setup(screen, case, default_text) - execute("set undolevels=-1") + feed_command("set undolevels=-1") feed(":%s/tw/MO/g<enter>") - -- using execute("undo") here will result in a "Press ENTER" prompt + -- feed_command("undo") here will result in a "Press ENTER" prompt feed("u") if case == "split" then screen:expect([[ @@ -573,7 +617,7 @@ describe(":substitute, 'inccommand' preserves undo", function() {15:~ }| {15:~ }| {15:~ }| - Already...st change | + Already ...t change | ]]) else screen:expect([[ @@ -586,7 +630,7 @@ describe(":substitute, 'inccommand' preserves undo", function() {15:~ }| {15:~ }| {15:~ }| - Already...st change | + Already ...t change | ]]) end @@ -594,7 +638,7 @@ describe(":substitute, 'inccommand' preserves undo", function() clear() common_setup(screen, case, default_text) - execute("set undolevels=-1") + feed_command("set undolevels=-1") feed("1G") feed("IL<esc>") feed(":%s/tw/MO/g<esc>") @@ -610,7 +654,7 @@ describe(":substitute, 'inccommand' preserves undo", function() {15:~ }| {15:~ }| {15:~ }| - Already...st change | + Already ...t change | ]]) end screen:detach() @@ -633,7 +677,7 @@ describe(":substitute, inccommand=split", function() end) it("preserves 'modified' buffer flag", function() - execute("set nomodified") + feed_command("set nomodified") feed(":%s/tw") screen:expect([[ Inc substitution on | @@ -761,7 +805,7 @@ describe(":substitute, inccommand=split", function() it('does not show split window for :s/', function() feed("2gg") feed(":s/tw") - wait() + screen:sleep(1) screen:expect([[ Inc substitution on | two lines | @@ -782,7 +826,7 @@ describe(":substitute, inccommand=split", function() end) it("'hlsearch' is active, 'cursorline' is not", function() - execute("set hlsearch cursorline") + feed_command("set hlsearch cursorline") feed("gg") -- Assert that 'cursorline' is active. @@ -874,7 +918,7 @@ describe(":substitute, inccommand=split", function() feed("gg") feed("2yy") feed("2000p") - execute("1,1000s/tw/BB/g") + feed_command("1,1000s/tw/BB/g") feed(":%s/tw/X") screen:expect([[ @@ -940,9 +984,9 @@ describe(":substitute, inccommand=split", function() -- Assert that 'inccommand' is ENABLED initially. eq("split", eval("&inccommand")) -- Set 'redrawtime' to minimal value, to ensure timeout is triggered. - execute("set redrawtime=1 nowrap") + feed_command("set redrawtime=1 nowrap") -- Load a big file. - execute("silent edit! test/functional/fixtures/bigfile.txt") + feed_command("silent edit! test/functional/fixtures/bigfile_oneline.txt") -- Start :substitute with a slow pattern. feed([[:%s/B.*N/x]]) wait() @@ -952,19 +996,19 @@ describe(":substitute, inccommand=split", function() -- Assert that preview cleared (or never manifested). screen:expect([[ 0000;<control>;Cc;0;BN;;;;;N;N| - 0001;<control>;Cc;0;BN;;;;;N;S| - 0002;<control>;Cc;0;BN;;;;;N;S| - 0003;<control>;Cc;0;BN;;;;;N;E| - 0004;<control>;Cc;0;BN;;;;;N;E| - 0005;<control>;Cc;0;BN;;;;;N;E| - 0006;<control>;Cc;0;BN;;;;;N;A| - 0007;<control>;Cc;0;BN;;;;;N;B| - 0008;<control>;Cc;0;BN;;;;;N;B| - 0009;<control>;Cc;0;S;;;;;N;CH| - 000A;<control>;Cc;0;B;;;;;N;LI| - 000B;<control>;Cc;0;S;;;;;N;LI| - 000C;<control>;Cc;0;WS;;;;;N;F| - 000D;<control>;Cc;0;B;;;;;N;CA| + 2F923;CJK COMPATIBILITY IDEOGR| + 2F924;CJK COMPATIBILITY IDEOGR| + 2F925;CJK COMPATIBILITY IDEOGR| + 2F926;CJK COMPATIBILITY IDEOGR| + 2F927;CJK COMPATIBILITY IDEOGR| + 2F928;CJK COMPATIBILITY IDEOGR| + 2F929;CJK COMPATIBILITY IDEOGR| + 2F92A;CJK COMPATIBILITY IDEOGR| + 2F92B;CJK COMPATIBILITY IDEOGR| + 2F92C;CJK COMPATIBILITY IDEOGR| + 2F92D;CJK COMPATIBILITY IDEOGR| + 2F92E;CJK COMPATIBILITY IDEOGR| + 2F92F;CJK COMPATIBILITY IDEOGR| :%s/B.*N/x^ | ]]) @@ -975,7 +1019,7 @@ describe(":substitute, inccommand=split", function() it("clears preview if non-previewable command is edited #5585", function() -- Put a non-previewable command in history. - execute("echo 'foo'") + feed_command("echo 'foo'") -- Start an incomplete :substitute command. feed(":1,2s/t/X") @@ -1036,7 +1080,7 @@ describe("inccommand=nosplit", function() end) it("works with :smagic, :snomagic", function() - execute("set hlsearch") + feed_command("set hlsearch") insert("Line *.3.* here") feed(":%smagic/3.*/X") -- start :smagic command @@ -1071,7 +1115,7 @@ describe("inccommand=nosplit", function() end) it('never shows preview buffer', function() - execute("set hlsearch") + feed_command("set hlsearch") feed(":%s/tw") screen:expect([[ @@ -1132,7 +1176,7 @@ describe("inccommand=nosplit", function() it("clears preview if non-previewable command is edited", function() -- Put a non-previewable command in history. - execute("echo 'foo'") + feed_command("echo 'foo'") -- Start an incomplete :substitute command. feed(":1,2s/t/X") @@ -1181,7 +1225,7 @@ describe(":substitute, 'inccommand' with a failing expression", function() it('in the pattern does nothing', function() for _, case in pairs(cases) do refresh(case) - execute("set inccommand=" .. case) + feed_command("set inccommand=" .. case) feed(":silent! %s/tw\\(/LARD/<enter>") expect(default_text) end @@ -1193,14 +1237,48 @@ describe(":substitute, 'inccommand' with a failing expression", function() local replacements = { "\\='LARD", "\\=xx_novar__xx" } for _, repl in pairs(replacements) do - execute("set inccommand=" .. case) + feed_command("set inccommand=" .. case) feed(":silent! %s/tw/" .. repl .. "/<enter>") expect(default_text:gsub("tw", "")) - execute("undo") + feed_command("undo") end end end) + it('in the range does not error #5912', function() + for _, case in pairs(cases) do + refresh(case) + feed(':100s/') + + screen:expect([[ + Inc substitution on | + two lines | + | + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + :100s/^ | + ]]) + + feed('<enter>') + screen:expect([[ + Inc substitution on | + two lines | + ^ | + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {14:E16: Invalid range} | + ]]) + end + end) + end) describe("'inccommand' and :cnoremap", function() @@ -1214,14 +1292,14 @@ describe("'inccommand' and :cnoremap", function() it('work with remapped characters', function() for _, case in pairs(cases) do refresh(case) - local command = "%s/lines/LINES/g" + local cmd = "%s/lines/LINES/g" - for i = 1, string.len(command) do - local c = string.sub(command, i, i) - execute("cnoremap ".. c .. " " .. c) + for i = 1, string.len(cmd) do + local c = string.sub(cmd, i, i) + feed_command("cnoremap ".. c .. " " .. c) end - execute(command) + feed_command(cmd) expect([[ Inc substitution on two LINES @@ -1232,7 +1310,7 @@ describe("'inccommand' and :cnoremap", function() it('work when mappings move the cursor', function() for _, case in pairs(cases) do refresh(case) - execute("cnoremap ,S LINES/<left><left><left><left><left><left>") + feed_command("cnoremap ,S LINES/<left><left><left><left><left><left>") feed(":%s/lines/,Sor three <enter>") expect([[ @@ -1240,21 +1318,21 @@ describe("'inccommand' and :cnoremap", function() two or three LINES ]]) - execute("cnoremap ;S /X/<left><left><left>") + feed_command("cnoremap ;S /X/<left><left><left>") feed(":%s/;SI<enter>") expect([[ Xnc substitution on two or three LXNES ]]) - execute("cnoremap ,T //Y/<left><left><left>") + feed_command("cnoremap ,T //Y/<left><left><left>") feed(":%s,TX<enter>") expect([[ Ync substitution on two or three LYNES ]]) - execute("cnoremap ;T s//Z/<left><left><left>") + feed_command("cnoremap ;T s//Z/<left><left><left>") feed(":%;TY<enter>") expect([[ Znc substitution on @@ -1266,7 +1344,7 @@ describe("'inccommand' and :cnoremap", function() it('does not work with a failing mapping', function() for _, case in pairs(cases) do refresh(case) - execute("cnoremap <expr> x execute('bwipeout!')[-1].'x'") + feed_command("cnoremap <expr> x execute('bwipeout!')[-1].'x'") feed(":%s/tw/tox<enter>") @@ -1279,7 +1357,7 @@ describe("'inccommand' and :cnoremap", function() it('work when temporarily moving the cursor', function() for _, case in pairs(cases) do refresh(case) - execute("cnoremap <expr> x cursor(1, 1)[-1].'x'") + feed_command("cnoremap <expr> x cursor(1, 1)[-1].'x'") feed(":%s/tw/tox/g<enter>") expect(default_text:gsub("tw", "tox")) @@ -1289,7 +1367,7 @@ describe("'inccommand' and :cnoremap", function() it("work when a mapping disables 'inccommand'", function() for _, case in pairs(cases) do refresh(case) - execute("cnoremap <expr> x execute('set inccommand=')[-1]") + feed_command("cnoremap <expr> x execute('set inccommand=')[-1]") feed(":%s/tw/toxa/g<enter>") expect(default_text:gsub("tw", "toa")) @@ -1363,7 +1441,7 @@ describe("'inccommand' autocommands", function() local function register_autocmd(event) meths.set_var(event .. "_fired", {}) - execute("autocmd " .. event .. " * call add(g:" .. event .. "_fired, expand('<abuf>'))") + feed_command("autocmd " .. event .. " * call add(g:" .. event .. "_fired, expand('<abuf>'))") end it('are not fired when splitting', function() @@ -1416,8 +1494,8 @@ describe("'inccommand' split windows", function() refresh() feed("gg") - execute("vsplit") - execute("split") + feed_command("vsplit") + feed_command("split") feed(":%s/tw") screen:expect([[ Inc substitution on {10:|}Inc substitution on| @@ -1453,9 +1531,9 @@ describe("'inccommand' split windows", function() ]]) feed("<esc>") - execute("only") - execute("split") - execute("vsplit") + feed_command("only") + feed_command("split") + feed_command("vsplit") feed(":%s/tw") screen:expect([[ @@ -1504,7 +1582,7 @@ describe("'inccommand' split windows", function() it("are not affected by various settings", function() for _, setting in pairs(settings) do refresh() - execute("set " .. setting) + feed_command("set " .. setting) feed(":%s/tw") diff --git a/test/functional/ui/input_spec.lua b/test/functional/ui/input_spec.lua index cec19250d2..29d974b709 100644 --- a/test/functional/ui/input_spec.lua +++ b/test/functional/ui/input_spec.lua @@ -1,5 +1,5 @@ local helpers = require('test.functional.helpers')(after_each) -local clear, execute, nvim = helpers.clear, helpers.execute, helpers.nvim +local clear, feed_command, nvim = helpers.clear, helpers.feed_command, helpers.nvim local feed, next_message, eq = helpers.feed, helpers.next_message, helpers.eq local expect = helpers.expect local Screen = require('test.functional.ui.screen') @@ -12,7 +12,7 @@ describe('mappings', function() local add_mapping = function(mapping, send) local cmd = "nnoremap "..mapping.." :call rpcnotify("..cid..", 'mapped', '" ..send:gsub('<', '<lt>').."')<cr>" - execute(cmd) + feed_command(cmd) end local check_mapping = function(mapping, expected) @@ -57,7 +57,7 @@ describe('feeding large chunks of input with <Paste>', function() clear() screen = Screen.new() screen:attach() - execute('set ruler') + feed_command('set ruler') end) it('ok', function() diff --git a/test/functional/ui/mode_spec.lua b/test/functional/ui/mode_spec.lua new file mode 100644 index 0000000000..f0cedfeeb5 --- /dev/null +++ b/test/functional/ui/mode_spec.lua @@ -0,0 +1,227 @@ +local helpers = require('test.functional.helpers')(after_each) +local Screen = require('test.functional.ui.screen') + +local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert +local command, eval = helpers.command, helpers.eval +local eq = helpers.eq + +describe('ui mode_change event', function() + local screen + + before_each(function() + clear() + screen = Screen.new(25, 4) + screen:attach({rgb= true}) + screen:set_default_attr_ids( { + [0] = {bold=true, foreground=255}, + [1] = {bold=true, reverse=true}, + [2] = {bold=true}, + [3] = {reverse=true}, + }) + end) + + it('works in normal mode', function() + screen:expect([[ + ^ | + {0:~ }| + {0:~ }| + | + ]],nil,nil,function () + eq("normal", screen.mode) + end) + + feed('d') + screen:expect([[ + ^ | + {0:~ }| + {0:~ }| + | + ]],nil,nil,function () + eq("operator", screen.mode) + end) + + feed('<esc>') + screen:expect([[ + ^ | + {0:~ }| + {0:~ }| + | + ]],nil,nil,function () + eq("normal", screen.mode) + end) + end) + + it('works in insert mode', function() + feed('i') + screen:expect([[ + ^ | + {0:~ }| + {0:~ }| + {2:-- INSERT --} | + ]],nil,nil,function () + eq("insert", screen.mode) + end) + + feed('word<esc>') + screen:expect([[ + wor^d | + {0:~ }| + {0:~ }| + | + ]], nil, nil, function () + eq("normal", screen.mode) + end) + + command("set showmatch") + eq(eval('&matchtime'), 5) -- tenths of seconds + feed('a(stuff') + screen:expect([[ + word(stuff^ | + {0:~ }| + {0:~ }| + {2:-- INSERT --} | + ]], nil, nil, function () + eq("insert", screen.mode) + end) + + feed(')') + screen:expect([[ + word^(stuff) | + {0:~ }| + {0:~ }| + {2:-- INSERT --} | + ]], nil, nil, function () + eq("showmatch", screen.mode) + end) + + screen:sleep(400) + screen:expect([[ + word(stuff)^ | + {0:~ }| + {0:~ }| + {2:-- INSERT --} | + ]], nil, nil, function () + eq("insert", screen.mode) + end) + end) + + it('works in replace mode', function() + feed('R') + screen:expect([[ + ^ | + {0:~ }| + {0:~ }| + {2:-- REPLACE --} | + ]], nil, nil, function () + eq("replace", screen.mode) + end) + + feed('word<esc>') + screen:expect([[ + wor^d | + {0:~ }| + {0:~ }| + | + ]], nil, nil, function () + eq("normal", screen.mode) + end) + end) + + it('works in cmdline mode', function() + feed(':') + screen:expect([[ + | + {0:~ }| + {0:~ }| + :^ | + ]],nil,nil,function () + eq("cmdline_normal", screen.mode) + end) + + feed('x<left>') + screen:expect([[ + | + {0:~ }| + {0:~ }| + :^x | + ]],nil,nil,function () + eq("cmdline_insert", screen.mode) + end) + + feed('<insert>') + screen:expect([[ + | + {0:~ }| + {0:~ }| + :^x | + ]],nil,nil,function () + eq("cmdline_replace", screen.mode) + end) + + + feed('<right>') + screen:expect([[ + | + {0:~ }| + {0:~ }| + :x^ | + ]],nil,nil,function () + eq("cmdline_normal", screen.mode) + end) + + feed('<esc>') + screen:expect([[ + ^ | + {0:~ }| + {0:~ }| + | + ]],nil,nil,function () + eq("normal", screen.mode) + end) + end) + + it('works in visal mode', function() + insert("text") + feed('v') + screen:expect([[ + tex^t | + {0:~ }| + {0:~ }| + {2:-- VISUAL --} | + ]],nil,nil,function () + eq("visual", screen.mode) + end) + + feed('<esc>') + screen:expect([[ + tex^t | + {0:~ }| + {0:~ }| + | + ]],nil,nil,function () + eq("normal", screen.mode) + end) + + command('set selection=exclusive') + feed('v') + screen:expect([[ + tex^t | + {0:~ }| + {0:~ }| + {2:-- VISUAL --} | + ]],nil,nil,function () + eq("visual_select", screen.mode) + end) + + feed('<esc>') + screen:expect([[ + tex^t | + {0:~ }| + {0:~ }| + | + ]],nil,nil,function () + eq("normal", screen.mode) + end) + end) +end) + diff --git a/test/functional/ui/mouse_spec.lua b/test/functional/ui/mouse_spec.lua index 17d949825a..3daf92eea0 100644 --- a/test/functional/ui/mouse_spec.lua +++ b/test/functional/ui/mouse_spec.lua @@ -1,21 +1,18 @@ local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') local clear, feed, meths = helpers.clear, helpers.feed, helpers.meths -local insert, execute = helpers.insert, helpers.execute +local insert, feed_command = helpers.insert, helpers.feed_command local eq, funcs = helpers.eq, helpers.funcs if helpers.pending_win32(pending) then return end -describe('Mouse input', function() +describe('ui/mouse/input', function() local screen before_each(function() clear() meths.set_option('mouse', 'a') meths.set_option('listchars', 'eol:$') - -- set mousetime to very high value to ensure that even in valgrind/travis, - -- nvim will still pick multiple clicks - meths.set_option('mousetime', 5000) screen = Screen.new(25, 5) screen:attach() screen:set_default_attr_ids({ @@ -119,13 +116,12 @@ describe('Mouse input', function() sel = { bold=true }, fill = { reverse=true } }) - screen.timeout = 15000 end) it('in tabline on filler space moves tab to the end', function() - execute('%delete') + feed_command('%delete') insert('this is foo') - execute('silent file foo | tabnew | file bar') + feed_command('silent file foo | tabnew | file bar') insert('this is bar') screen:expect([[ {tab: + foo }{sel: + bar }{fill: }{tab:X}| @@ -160,9 +156,9 @@ describe('Mouse input', function() return end - execute('%delete') + feed_command('%delete') insert('this is foo') - execute('silent file foo | tabnew | file bar') + feed_command('silent file foo | tabnew | file bar') insert('this is bar') screen:expect([[ {tab: + foo }{sel: + bar }{fill: }{tab:X}| @@ -190,9 +186,9 @@ describe('Mouse input', function() end) it('in tabline to the right moves tab right', function() - execute('%delete') + feed_command('%delete') insert('this is foo') - execute('silent file foo | tabnew | file bar') + feed_command('silent file foo | tabnew | file bar') insert('this is bar') screen:expect([[ {tab: + foo }{sel: + bar }{fill: }{tab:X}| @@ -220,9 +216,9 @@ describe('Mouse input', function() end) it('out of tabline under filler space moves tab to the end', function() - execute('%delete') + feed_command('%delete') insert('this is foo') - execute('silent file foo | tabnew | file bar') + feed_command('silent file foo | tabnew | file bar') insert('this is bar') screen:expect([[ {tab: + foo }{sel: + bar }{fill: }{tab:X}| @@ -265,9 +261,9 @@ describe('Mouse input', function() return end - execute('%delete') + feed_command('%delete') insert('this is foo') - execute('silent file foo | tabnew | file bar') + feed_command('silent file foo | tabnew | file bar') insert('this is bar') screen:expect([[ {tab: + foo }{sel: + bar }{fill: }{tab:X}| @@ -303,9 +299,9 @@ describe('Mouse input', function() end) it('out of tabline to the right moves tab right', function() - execute('%delete') + feed_command('%delete') insert('this is foo') - execute('silent file foo | tabnew | file bar') + feed_command('silent file foo | tabnew | file bar') insert('this is bar') screen:expect([[ {tab: + foo }{sel: + bar }{fill: }{tab:X}| @@ -352,9 +348,9 @@ describe('Mouse input', function() end) it('left click in default tabline (position 4) switches to tab', function() - execute('%delete') + feed_command('%delete') insert('this is foo') - execute('silent file foo | tabnew | file bar') + feed_command('silent file foo | tabnew | file bar') insert('this is bar') screen:expect([[ {tab: + foo }{sel: + bar }{fill: }{tab:X}| @@ -375,9 +371,9 @@ describe('Mouse input', function() it('left click in default tabline (position 24) closes tab', function() meths.set_option('hidden', true) - execute('%delete') + feed_command('%delete') insert('this is foo') - execute('silent file foo | tabnew | file bar') + feed_command('silent file foo | tabnew | file bar') insert('this is bar') screen:expect([[ {tab: + foo }{sel: + bar }{fill: }{tab:X}| @@ -398,9 +394,9 @@ describe('Mouse input', function() it('double click in default tabline (position 4) opens new tab', function() meths.set_option('hidden', true) - execute('%delete') + feed_command('%delete') insert('this is foo') - execute('silent file foo | tabnew | file bar') + feed_command('silent file foo | tabnew | file bar') insert('this is bar') screen:expect([[ {tab: + foo }{sel: + bar }{fill: }{tab:X}| @@ -421,13 +417,13 @@ describe('Mouse input', function() describe('%@ label', function() before_each(function() - execute([[ + feed_command([[ function Test(...) let g:reply = a:000 return copy(a:000) " Check for memory leaks: return should be freed endfunction ]]) - execute([[ + feed_command([[ function Test2(...) return call('Test', a:000 + [2]) endfunction @@ -533,9 +529,9 @@ describe('Mouse input', function() fill = { reverse=true }, vis = { background=Screen.colors.LightGrey } }) - execute('silent file foo | tabnew | file bar') + feed_command('silent file foo | tabnew | file bar') insert('this is bar') - execute('tabprevious') -- go to first tab + feed_command('tabprevious') -- go to first tab screen:expect([[ {sel: + foo }{tab: + bar }{fill: }{tab:X}| mouse | @@ -641,7 +637,7 @@ describe('Mouse input', function() mouse scrolling ]]) screen:try_resize(53, 14) - execute('sp', 'vsp') + feed_command('sp', 'vsp') screen:expect([[ lines {4:|}lines | to {4:|}to | @@ -658,7 +654,7 @@ describe('Mouse input', function() {4:[No Name] [+] }| :vsp | ]]) - feed('<MouseUp><0,0>') + feed('<ScrollWheelDown><0,0>') screen:expect([[ mouse scrolling {4:|}lines | ^ {4:|}to | @@ -675,7 +671,7 @@ describe('Mouse input', function() {4:[No Name] [+] }| | ]]) - feed('<MouseDown><27,0>') + feed('<ScrollWheelUp><27,0>') screen:expect([[ mouse scrolling {4:|}text | ^ {4:|}with | @@ -692,7 +688,7 @@ describe('Mouse input', function() {4:[No Name] [+] }| | ]]) - feed('<MouseDown><27,7><MouseDown>') + feed('<ScrollWheelUp><27,7><ScrollWheelUp>') screen:expect([[ mouse scrolling {4:|}text | ^ {4:|}with | @@ -754,12 +750,12 @@ describe('Mouse input', function() }) feed('ggdG') - execute('set concealcursor=n') - execute('set nowrap') - execute('syntax match NonText "\\<amet\\>" conceal') - execute('syntax match NonText "\\cs\\|g." conceal cchar=X') - execute('syntax match NonText "\\%(lo\\|cl\\)." conceal') - execute('syntax match NonText "Lo" conceal cchar=Y') + feed_command('set concealcursor=n') + feed_command('set nowrap') + feed_command('syntax match NonText "\\<amet\\>" conceal') + feed_command('syntax match NonText "\\cs\\|g." conceal cchar=X') + feed_command('syntax match NonText "\\%(lo\\|cl\\)." conceal') + feed_command('syntax match NonText "Lo" conceal cchar=Y') insert([[ Lorem ipsum dolor sit amet, consetetur sadipscing elitr. @@ -770,7 +766,7 @@ describe('Mouse input', function() end) it('(level 1) click on non-wrapped lines', function() - execute('let &conceallevel=1', 'echo') + feed_command('let &conceallevel=1', 'echo') feed('<esc><LeftMouse><0,0>') screen:expect([[ @@ -818,7 +814,7 @@ describe('Mouse input', function() end) -- level 1 - non wrapped it('(level 1) click on wrapped lines', function() - execute('let &conceallevel=1', 'let &wrap=1', 'echo') + feed_command('let &conceallevel=1', 'let &wrap=1', 'echo') feed('<esc><LeftMouse><0,0>') screen:expect([[ @@ -867,7 +863,7 @@ describe('Mouse input', function() it('(level 2) click on non-wrapped lines', function() - execute('let &conceallevel=2', 'echo') + feed_command('let &conceallevel=2', 'echo') feed('<esc><LeftMouse><0,0>') screen:expect([[ @@ -915,7 +911,7 @@ describe('Mouse input', function() end) -- level 2 - non wrapped it('(level 2) click on wrapped lines', function() - execute('let &conceallevel=2', 'let &wrap=1', 'echo') + feed_command('let &conceallevel=2', 'let &wrap=1', 'echo') feed('<esc><LeftMouse><0,0>') screen:expect([[ @@ -964,7 +960,7 @@ describe('Mouse input', function() it('(level 3) click on non-wrapped lines', function() - execute('let &conceallevel=3', 'echo') + feed_command('let &conceallevel=3', 'echo') feed('<esc><LeftMouse><0,0>') screen:expect([[ @@ -1012,7 +1008,7 @@ describe('Mouse input', function() end) -- level 3 - non wrapped it('(level 3) click on wrapped lines', function() - execute('let &conceallevel=3', 'let &wrap=1', 'echo') + feed_command('let &conceallevel=3', 'let &wrap=1', 'echo') feed('<esc><LeftMouse><0,0>') screen:expect([[ diff --git a/test/functional/ui/output_spec.lua b/test/functional/ui/output_spec.lua index d6d8f1c4e5..c6d564e8dc 100644 --- a/test/functional/ui/output_spec.lua +++ b/test/functional/ui/output_spec.lua @@ -8,13 +8,13 @@ describe("shell command :!", function() before_each(function() session.clear() screen = child_session.screen_setup(0, '["'..session.nvim_prog.. - '", "-u", "NONE", "-i", "NONE", "--cmd", "set noswapfile"]') + '", "-u", "NONE", "-i", "NONE", "--cmd", "'..session.nvim_set..'"]') screen:expect([[ {1: } | {4:~ }| {4:~ }| {4:~ }| - {5:[No Name] }| + {4:~ }| | {3:-- TERMINAL --} | ]]) @@ -25,14 +25,14 @@ describe("shell command :!", function() screen:detach() end) - it("displays output even without LF/EOF. #4646 #4569 #3772", function() + it("displays output without LF/EOF. #4646 #4569 #3772", function() -- NOTE: We use a child nvim (within a :term buffer) -- to avoid triggering a UI flush. child_session.feed_data(":!printf foo; sleep 200\n") screen:expect([[ {4:~ }| {4:~ }| - {5:[No Name] }| + {4:~ }| :!printf foo; sleep 200 | | foo | @@ -41,6 +41,11 @@ describe("shell command :!", function() end) it("throttles shell-command output greater than ~10KB", function() + if os.getenv("TRAVIS") and session.os_name() == "osx" then + pending("[Unreliable on Travis macOS.]", function() end) + return + end + screen.timeout = 20000 -- Avoid false failure on slow systems. child_session.feed_data( ":!for i in $(seq 2 3000); do echo XXXXXXXXXX $i; done\n") diff --git a/test/functional/ui/quickfix_spec.lua b/test/functional/ui/quickfix_spec.lua index 29b28fe9f0..b0d89ee3b6 100644 --- a/test/functional/ui/quickfix_spec.lua +++ b/test/functional/ui/quickfix_spec.lua @@ -1,7 +1,7 @@ local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') local clear, feed, meths = helpers.clear, helpers.feed, helpers.meths -local insert, execute = helpers.insert, helpers.execute +local insert, command = helpers.insert, helpers.command describe('quickfix selection highlight', function() @@ -28,8 +28,8 @@ describe('quickfix selection highlight', function() }) meths.set_option('errorformat', '%m %l') - execute('syntax on') - execute('highlight Search guibg=Green') + command('syntax on') + command('highlight Search guibg=Green') insert([[ Line 1 @@ -39,7 +39,7 @@ describe('quickfix selection highlight', function() Line 5 ]]) - execute('cad') + command('cad') feed('gg') screen:expect([[ @@ -52,12 +52,12 @@ describe('quickfix selection highlight', function() {1:~ }| {1:~ }| {1:~ }| - :cad | + | ]]) end) it('using default Search highlight group', function() - execute('copen') + command('copen') screen:expect([[ Line 1 | @@ -69,10 +69,10 @@ describe('quickfix selection highlight', function() |{3:5}| Line | || | {4:[Quickfix List] }| - :copen | + | ]]) - execute('cnext') + command('cnext') screen:expect([[ Line 1 | @@ -84,14 +84,14 @@ describe('quickfix selection highlight', function() |{3:5}| Line | || | {4:[Quickfix List] }| - :cnext | + | ]]) end) it('using QuickFixLine highlight group', function() - execute('highlight QuickFixLine guibg=Red') + command('highlight QuickFixLine guibg=Red') - execute('copen') + command('copen') screen:expect([[ Line 1 | @@ -103,10 +103,10 @@ describe('quickfix selection highlight', function() |{3:5}| Line | || | {4:[Quickfix List] }| - :copen | + | ]]) - execute('cnext') + command('cnext') screen:expect([[ Line 1 | @@ -118,16 +118,16 @@ describe('quickfix selection highlight', function() |{3:5}| Line | || | {4:[Quickfix List] }| - :cnext | + | ]]) end) it('combines with CursorLine', function() - execute('set cursorline') - execute('highlight QuickFixLine guifg=Red') - execute('highlight CursorLine guibg=Fuchsia') + command('set cursorline') + command('highlight QuickFixLine guifg=Red') + command('highlight CursorLine guibg=Fuchsia') - execute('copen') + command('copen') screen:expect([[ {9:Line 1 }| @@ -139,7 +139,7 @@ describe('quickfix selection highlight', function() |{3:5}| Line | || | {4:[Quickfix List] }| - :copen | + | ]]) feed('j') @@ -154,16 +154,16 @@ describe('quickfix selection highlight', function() |{3:5}| Line | || | {4:[Quickfix List] }| - :copen | + | ]]) end) it('QuickFixLine background takes precedence over CursorLine', function() - execute('set cursorline') - execute('highlight QuickFixLine guibg=Red') - execute('highlight CursorLine guibg=Fuchsia') + command('set cursorline') + command('highlight QuickFixLine guibg=Red') + command('highlight CursorLine guibg=Fuchsia') - execute('copen') + command('copen') screen:expect([[ {9:Line 1 }| @@ -175,7 +175,7 @@ describe('quickfix selection highlight', function() |{3:5}| Line | || | {4:[Quickfix List] }| - :copen | + | ]]) feed('j') @@ -190,7 +190,7 @@ describe('quickfix selection highlight', function() |{3:5}| Line | || | {4:[Quickfix List] }| - :copen | + | ]]) end) end) diff --git a/test/functional/ui/screen.lua b/test/functional/ui/screen.lua index 2581b36711..a6b7fb2997 100644 --- a/test/functional/ui/screen.lua +++ b/test/functional/ui/screen.lua @@ -1,31 +1,17 @@ --- This module contains the Screen class, a complete Nvim screen implementation --- designed for functional testing. The goal is to provide a simple and --- intuitive API for verifying screen state after a set of actions. +-- This module contains the Screen class, a complete Nvim UI implementation +-- designed for functional testing (verifying screen state, in particular). -- --- The screen class exposes a single assertion method, "Screen:expect". This --- method takes a string representing the expected screen state and an optional --- set of attribute identifiers for checking highlighted characters(more on --- this later). --- --- The string passed to "expect" will be processed according to these rules: --- --- - Each line of the string represents and is matched individually against --- a screen row. --- - The entire string is stripped of common indentation --- - Expected screen rows are stripped of the last character. The last --- character should be used to write pipes(|) that make clear where the --- screen ends --- - The last line is stripped, so the string must have (row count + 1) --- lines. +-- Screen:expect() takes a string representing the expected screen state and an +-- optional set of attribute identifiers for checking highlighted characters. -- -- Example usage: -- -- local screen = Screen.new(25, 10) --- -- attach the screen to the current Nvim instance +-- -- Attach the screen to the current Nvim instance. -- screen:attach() --- --enter insert mode and type some text +-- -- Enter insert-mode and type some text. -- feed('ihello screen') --- -- declare an expectation for the eventual screen state +-- -- Assert the expected screen state. -- screen:expect([[ -- hello screen | -- ~ | @@ -39,31 +25,19 @@ -- -- INSERT -- | -- ]]) -- <- Last line is stripped -- --- Since screen updates are received asynchronously, "expect" is actually --- specifying the eventual screen state. This is how "expect" works: It will --- start the event loop with a timeout of 5 seconds. Each time it receives an --- update the expected state will be checked against the updated state. --- --- If the expected state matches the current state, the event loop will be --- stopped and "expect" will return. If the timeout expires, the last match --- error will be reported and the test will fail. +-- Since screen updates are received asynchronously, expect() actually specifies +-- the _eventual_ screen state. -- --- If the second argument is passed to "expect", the screen rows will be --- transformed before being matched against the string lines. The --- transformation rule is simple: Each substring "S" composed with characters --- having the exact same set of attributes will be substituted by "{K:S}", --- where K is a key associated the attribute set via the second argument of --- "expect". --- If a transformation table is present, unexpected attribute sets in the final --- state is considered an error. To make testing simpler, a list of attribute --- sets that should be ignored can be passed as a third argument. Alternatively, --- this third argument can be "true" to indicate that all unexpected attribute --- sets should be ignored. +-- This is how expect() works: +-- * It starts the event loop with a timeout. +-- * Each time it receives an update it checks that against the expected state. +-- * If the expected state matches the current state, the event loop will be +-- stopped and expect() will return. +-- * If the timeout expires, the last match error will be reported and the +-- test will fail. -- --- To illustrate how this works, let's say that in the above example we wanted --- to assert that the "-- INSERT --" string is highlighted with the bold --- attribute(which normally is), here's how the call to "expect" should look --- like: +-- Continuing the above example, say we want to assert that "-- INSERT --" is +-- highlighted with the bold attribute. The expect() call should look like this: -- -- NonText = Screen.colors.Blue -- screen:expect([[ @@ -81,29 +55,21 @@ -- -- In this case "b" is a string associated with the set composed of one -- attribute: bold. Note that since the {b:} markup is not a real part of the --- screen, the delimiter(|) had to be moved right. Also, the highlighting of the --- NonText markers (~) is ignored in this test. +-- screen, the delimiter "|" moved to the right. Also, the highlighting of the +-- NonText markers "~" is ignored in this test. +-- +-- Tests will often share a group of attribute sets to expect(). Those can be +-- defined at the beginning of a test: -- --- Multiple expect:s will likely share a group of attribute sets to test. --- Therefore these could be specified at the beginning of a test like this: -- NonText = Screen.colors.Blue -- screen:set_default_attr_ids( { -- [1] = {reverse = true, bold = true}, -- [2] = {reverse = true} -- }) -- screen:set_default_attr_ignore( {{}, {bold=true, foreground=NonText}} ) --- These can be overridden for a specific expect expression, by passing --- different sets as parameters. -- --- To help writing screen tests, there is a utility function --- "screen:snapshot_util()", that can be placed in a test file at any point an --- "expect(...)" should be. It will wait a short amount of time and then dump --- the current state of the screen, in the form of an "expect(..)" expression --- that would match it exactly. "snapshot_util" optionally also take the --- transformation and ignore set as parameters, like expect, or uses the default --- set. It will generate a larger attribute transformation set, if needed. --- To generate a text-only test without highlight checks, --- use `screen:snapshot_util({},true)` +-- To help write screen tests, see Screen:snapshot_util(). +-- To debug screen tests, see Screen:redraw_debug(). local helpers = require('test.functional.helpers')(nil) local request, run, uimeths = helpers.request, helpers.run, helpers.uimeths @@ -205,24 +171,45 @@ end function Screen:try_resize(columns, rows) uimeths.try_resize(columns, rows) + -- Give ourselves a chance to _handle_resize, which requires using + -- self.sleep() (for the resize notification) rather than run() + self:sleep(0.1) end -- Asserts that `expected` eventually matches the screen state. -- --- expected: Expected screen state (string). --- attr_ids: Text attribute definitions. --- attr_ignore: Ignored text attributes. +-- expected: Expected screen state (string). Each line represents a screen +-- row. Last character of each row (typically "|") is stripped. +-- Common indentation is stripped. +-- Used as `condition` if NOT a string; must be the ONLY arg then. +-- attr_ids: Expected text attributes. Screen rows are transformed according +-- to this table, as follows: each substring S composed of +-- characters having the same attributes will be substituted by +-- "{K:S}", where K is a key in `attr_ids`. Any unexpected +-- attributes in the final state are an error. +-- attr_ignore: Ignored text attributes, or `true` to ignore all. -- condition: Function asserting some arbitrary condition. -- any: true: Succeed if `expected` matches ANY screen line(s). -- false (default): `expected` must match screen exactly. function Screen:expect(expected, attr_ids, attr_ignore, condition, any) - -- remove the last line and dedent - expected = dedent(expected:gsub('\n[ ]+$', '')) local expected_rows = {} - for row in expected:gmatch('[^\n]+') do - -- the last character should be the screen delimiter - row = row:sub(1, #row - 1) - table.insert(expected_rows, row) + if type(expected) ~= "string" then + assert(not (attr_ids or attr_ignore or condition or any)) + condition = expected + expected = nil + else + -- Remove the last line and dedent. Note that gsub returns more then one + -- value. + expected = dedent(expected:gsub('\n[ ]+$', ''), 0) + for row in expected:gmatch('[^\n]+') do + row = row:sub(1, #row - 1) -- Last char must be the screen delimiter. + table.insert(expected_rows, row) + end + if not any then + assert(self._height == #expected_rows, + "Expected screen state's row count(" .. #expected_rows + .. ') differs from configured height(' .. self._height .. ') of Screen.') + end end local ids = attr_ids or self._default_attr_ids local ignore = attr_ignore or self._default_attr_ignore @@ -238,7 +225,9 @@ function Screen:expect(expected, attr_ids, attr_ignore, condition, any) actual_rows[i] = self:_row_repr(self._rows[i], ids, ignore) end - if any then + if expected == nil then + return + elseif any then -- Search for `expected` anywhere in the screen lines. local actual_screen_str = table.concat(actual_rows, '\n') if nil == string.find(actual_screen_str, expected) then @@ -262,7 +251,7 @@ function Screen:expect(expected, attr_ids, attr_ignore, condition, any) ..'Expected:\n |'..table.concat(msg_expected_rows, '|\n |')..'|\n' ..'Actual:\n |'..table.concat(actual_rows, '|\n |')..'|\n\n'..[[ To print the expect() call that would assert the current screen state, use -screen:snaphot_util(). In case of non-deterministic failures, use +screen:snapshot_util(). In case of non-deterministic failures, use screen:redraw_debug() to show all intermediate screen states. ]]) end end @@ -296,18 +285,13 @@ function Screen:wait(check, timeout) if failure_after_success then print([[ -Warning: Screen changes have been received after the expected state was seen. -This is probably due to an indeterminism in the test. Try adding -`wait()` (or even a separate `screen:expect(...)`) at a point of possible -indeterminism, typically in between a `feed()` or `execute()` which is non- -synchronous, and a synchronous api call. - -Note that sometimes a `wait` can trigger redraws and consequently generate more -indeterminism. If adding `wait` calls seems to increase the frequency of these -messages, try removing every `wait` call in the test. - -If everything else fails, use Screen:redraw_debug to help investigate what is - causing the problem. + +Warning: Screen changes were received after the expected state. This indicates +indeterminism in the test. Try adding wait() (or screen:expect(...)) between +asynchronous (feed(), nvim_input()) and synchronous API calls. + - Use Screen:redraw_debug() to investigate the problem. + - wait() can trigger redraws and consequently generate more indeterminism. + In that case try removing every wait(). ]]) local tb = debug.traceback() local index = string.find(tb, '\n%s*%[C]') @@ -329,10 +313,13 @@ function Screen:_redraw(updates) -- print(require('inspect')(update)) local method = update[1] for i = 2, #update do - local handler = self['_handle_'..method] + local handler_name = '_handle_'..method + local handler = self[handler_name] if handler ~= nil then handler(self, unpack(update[i])) else + assert(self._on_event, + "Add Screen:"..handler_name.." or call Screen:set_on_event_handler") self._on_event(method, update[i]) end end @@ -363,6 +350,11 @@ function Screen:_handle_resize(width, height) } end +function Screen:_handle_mode_info_set(cursor_style_enabled, mode_info) + self._cursor_style_enabled = cursor_style_enabled + self._mode_info = mode_info +end + function Screen:_handle_clear() self:_clear_block(self._scroll_region.top, self._scroll_region.bot, self._scroll_region.left, self._scroll_region.right) @@ -394,9 +386,8 @@ function Screen:_handle_mouse_off() self._mouse_enabled = false end -function Screen:_handle_mode_change(mode) - assert(mode == 'insert' or mode == 'replace' - or mode == 'normal' or mode == 'cmdline') +function Screen:_handle_mode_change(mode, idx) + assert(mode == self._mode_info[idx+1].name) self.mode = mode end @@ -541,8 +532,12 @@ function Screen:_current_screen() return table.concat(rv, '\n') end +-- Generates tests. Call it where Screen:expect() would be. Waits briefly, then +-- dumps the current screen state in the form of Screen:expect(). +-- Use snapshot_util({},true) to generate a text-only (no attributes) test. +-- +-- @see Screen:redraw_debug() function Screen:snapshot_util(attrs, ignore) - -- util to generate screen test self:sleep(250) self:print_snapshot(attrs, ignore) end @@ -629,7 +624,7 @@ function Screen:_pprint_attrs(attrs) return table.concat(items, ", ") end -function backward_find_meaningful(tbl, from) -- luacheck: ignore +local function backward_find_meaningful(tbl, from) -- luacheck: no unused for i = from or #tbl, 1, -1 do if tbl[i] ~= ' ' then return i + 1 diff --git a/test/functional/ui/screen_basic_spec.lua b/test/functional/ui/screen_basic_spec.lua index d03f98c26f..bfcdc7f652 100644 --- a/test/functional/ui/screen_basic_spec.lua +++ b/test/functional/ui/screen_basic_spec.lua @@ -1,16 +1,15 @@ local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') local spawn, set_session, clear = helpers.spawn, helpers.set_session, helpers.clear -local feed, execute = helpers.feed, helpers.execute +local feed, command = helpers.feed, helpers.command local insert = helpers.insert local eq = helpers.eq +local eval = helpers.eval -if helpers.pending_win32(pending) then return end - -describe('Initial screen', function() +describe('screen', function() local screen local nvim_argv = {helpers.nvim_prog, '-u', 'NONE', '-i', 'NONE', '-N', - '--cmd', 'set shortmess+=I background=light noswapfile', + '--cmd', 'set shortmess+=I background=light noswapfile belloff= noshowcmd noruler', '--embed'} before_each(function() @@ -28,7 +27,7 @@ describe('Initial screen', function() screen:detach() end) - it('is the default initial screen', function() + it('default initial screen', function() screen:expect([[ ^ | {0:~ }| @@ -74,33 +73,29 @@ describe('Screen', function() describe(':suspend', function() it('is forwarded to the UI', function() local function check() - if not screen.suspended then - return 'Screen was not suspended' - end + eq(true, screen.suspended) end - execute('suspend') - screen:wait(check) + command('suspend') + screen:expect(check) screen.suspended = false feed('<c-z>') - screen:wait(check) + screen:expect(check) end) end) describe('bell/visual bell', function() it('is forwarded to the UI', function() feed('<left>') - screen:wait(function() - if not screen.bell or screen.visual_bell then - return 'Bell was not sent' - end + screen:expect(function() + eq(true, screen.bell) + eq(false, screen.visual_bell) end) screen.bell = false - execute('set visualbell') + command('set visualbell') feed('<left>') - screen:wait(function() - if not screen.visual_bell or screen.bell then - return 'Visual bell was not sent' - end + screen:expect(function() + eq(true, screen.visual_bell) + eq(false, screen.bell) end) end) end) @@ -108,36 +103,27 @@ describe('Screen', function() describe(':set title', function() it('is forwarded to the UI', function() local expected = 'test-title' - execute('set titlestring='..expected) - execute('set title') - screen:wait(function() - local actual = screen.title - if actual ~= expected then - return 'Expected title to be "'..expected..'" but was "'..actual..'"' - end + command('set titlestring='..expected) + command('set title') + screen:expect(function() + eq(expected, screen.title) end) end) it('has correct default title with unnamed file', function() local expected = '[No Name] - NVIM' - execute('set title') - screen:wait(function() - local actual = screen.title - if actual ~= expected then - return 'Expected title to be "'..expected..'" but was "'..actual..'"' - end + command('set title') + screen:expect(function() + eq(expected, screen.title) end) end) it('has correct default title with named file', function() local expected = 'myfile (/mydir) - NVIM' - execute('set title') - execute('file /mydir/myfile') - screen:wait(function() - local actual = screen.title - if actual ~= expected then - return 'Expected title to be "'..expected..'" but was "'..actual..'"' - end + command('set title') + command('file /mydir/myfile') + screen:expect(function() + eq(expected, screen.title) end) end) end) @@ -145,13 +131,10 @@ describe('Screen', function() describe(':set icon', function() it('is forwarded to the UI', function() local expected = 'test-icon' - execute('set iconstring='..expected) - execute('set icon') - screen:wait(function() - local actual = screen.icon - if actual ~= expected then - return 'Expected title to be "'..expected..'" but was "'..actual..'"' - end + command('set iconstring='..expected) + command('set icon') + screen:expect(function() + eq(expected, screen.icon) end) end) end) @@ -159,7 +142,7 @@ describe('Screen', function() describe('window', function() describe('split', function() it('horizontal', function() - execute('sp') + command('sp') screen:expect([[ ^ | {0:~ }| @@ -174,13 +157,13 @@ describe('Screen', function() {0:~ }| {0:~ }| {3:[No Name] }| - :sp | + | ]]) end) it('horizontal and resize', function() - execute('sp') - execute('resize 8') + command('sp') + command('resize 8') screen:expect([[ ^ | {0:~ }| @@ -195,12 +178,14 @@ describe('Screen', function() {0:~ }| {0:~ }| {3:[No Name] }| - :resize 8 | + | ]]) end) it('horizontal and vertical', function() - execute('sp', 'vsp', 'vsp') + command('sp') + command('vsp') + command('vsp') screen:expect([[ ^ {3:|} {3:|} | {0:~ }{3:|}{0:~ }{3:|}{0:~ }| @@ -240,7 +225,9 @@ describe('Screen', function() describe('tabnew', function() it('creates a new buffer', function() - execute('sp', 'vsp', 'vsp') + command('sp') + command('vsp') + command('vsp') insert('hello') screen:expect([[ hell^o {3:|}hello {3:|}hello | @@ -258,7 +245,7 @@ describe('Screen', function() {3:[No Name] [+] }| | ]]) - execute('tabnew') + command('tabnew') insert('hello2') feed('h') screen:expect([[ @@ -277,7 +264,7 @@ describe('Screen', function() {0:~ }| | ]]) - execute('tabprevious') + command('tabprevious') screen:expect([[ {2: }{6:4}{2:+ [No Name] }{4: + [No Name] }{3: }{4:X}| hell^o {3:|}hello {3:|}hello | @@ -322,9 +309,9 @@ describe('Screen', function() describe('normal mode', function() -- https://code.google.com/p/vim/issues/detail?id=339 it("setting 'ruler' doesn't reset the preferred column", function() - execute('set virtualedit=') + command('set virtualedit=') feed('i0123456<cr>789<esc>kllj') - execute('set ruler') + command('set ruler') feed('k') screen:expect([[ 0123^456 | @@ -340,7 +327,7 @@ describe('Screen', function() {0:~ }| {0:~ }| {0:~ }| - :set ruler 1,5 All | + 1,5 All | ]]) end) end) @@ -405,7 +392,9 @@ describe('Screen', function() split windows ]]) - execute('sp', 'vsp', 'vsp') + command('sp') + command('vsp') + command('vsp') screen:expect([[ and {3:|}and {3:|}and | clearing {3:|}clearing {3:|}clearing | @@ -563,11 +552,10 @@ describe('Screen', function() ]]) end) - -- FIXME this has some race conditions that cause it to fail periodically - pending('has minimum width/height values', function() + it('has minimum width/height values', function() screen:try_resize(1, 1) screen:expect([[ - -- INS^ERT --| + {2:-- INS^ERT --}| | ]]) feed('<esc>:ls') @@ -578,116 +566,61 @@ describe('Screen', function() end) end) - describe('mode change', function() - before_each(function() - screen:try_resize(25, 5) - end) - - it('works in normal mode', function() + describe('press enter', function() + it('does not crash on <F1> at โPress ENTERโ', function() + command('nnoremap <F1> :echo "TEST"<CR>') + feed(':ls<CR>') screen:expect([[ - ^ | - {0:~ }| - {0:~ }| - {0:~ }| - | - ]],nil,nil,function () - eq("normal", screen.mode) - end) - end) - - it('works in insert mode', function() - feed('i') - screen:expect([[ - ^ | - {0:~ }| - {0:~ }| - {0:~ }| - {2:-- INSERT --} | - ]],nil,nil,function () - eq("insert", screen.mode) - end) - - feed('word<esc>') - screen:expect([[ - wor^d | - {0:~ }| - {0:~ }| - {0:~ }| - | - ]], nil, nil, function () - eq("normal", screen.mode) - end) - end) - - it('works in replace mode', function() - feed('R') - screen:expect([[ - ^ | - {0:~ }| - {0:~ }| - {0:~ }| - {2:-- REPLACE --} | - ]], nil, nil, function () - eq("replace", screen.mode) - end) - - feed('word<esc>') + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + :ls | + 1 %a "[No Name]" line 1 | + {7:Press ENTER or type command to continue}^ | + ]]) + feed('<F1>') screen:expect([[ - wor^d | - {0:~ }| - {0:~ }| - {0:~ }| - | - ]], nil, nil, function () - eq("normal", screen.mode) - end) + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + TEST | + ]]) end) + end) +end) - it('works in cmdline mode', function() - feed(':') - screen:expect([[ - | - {0:~ }| - {0:~ }| - {0:~ }| - :^ | - ]],nil,nil,function () - eq("cmdline", screen.mode) - end) - - feed('<esc>/') - screen:expect([[ - | - {0:~ }| - {0:~ }| - {0:~ }| - /^ | - ]],nil,nil,function () - eq("cmdline", screen.mode) - end) - - - feed('<esc>?') - screen:expect([[ - | - {0:~ }| - {0:~ }| - {0:~ }| - ?^ | - ]],nil,nil,function () - eq("cmdline", screen.mode) - end) - - feed('<esc>') - screen:expect([[ - ^ | - {0:~ }| - {0:~ }| - {0:~ }| - | - ]],nil,nil,function () - eq("normal", screen.mode) - end) - end) +describe('nvim_ui_attach()', function() + before_each(function() + clear() + end) + it('handles very large width/height #2180', function() + local screen = Screen.new(999, 999) + screen:attach() + eq(999, eval('&lines')) + eq(999, eval('&columns')) + end) + it('invalid option returns error', function() + local screen = Screen.new() + local status, rv = pcall(function() screen:attach({foo={'foo'}}) end) + eq(false, status) + eq('No such ui option', rv:match("No such .*")) end) end) diff --git a/test/functional/ui/searchhl_spec.lua b/test/functional/ui/searchhl_spec.lua index 3914648e8f..11b18d015f 100644 --- a/test/functional/ui/searchhl_spec.lua +++ b/test/functional/ui/searchhl_spec.lua @@ -1,7 +1,7 @@ local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local execute = helpers.execute +local feed_command = helpers.feed_command if helpers.pending_win32(pending) then return end @@ -22,7 +22,7 @@ describe('search highlighting', function() end) it('is disabled by ":set nohlsearch"', function() - execute('set nohlsearch') + feed_command('set nohlsearch') insert("some text\nmore text") feed("gg/text<cr>") screen:expect([[ @@ -79,7 +79,7 @@ describe('search highlighting', function() /\<text\> | ]]) - execute("nohlsearch") + feed_command("nohlsearch") screen:expect([[ some text | more textstuff | @@ -92,8 +92,8 @@ describe('search highlighting', function() end) it('works with incsearch', function() - execute('set hlsearch') - execute('set incsearch') + feed_command('set hlsearch') + feed_command('set incsearch') insert([[ the first line in a little file @@ -156,8 +156,8 @@ describe('search highlighting', function() end) it('works with incsearch and offset', function() - execute('set hlsearch') - execute('set incsearch') + feed_command('set hlsearch') + feed_command('set incsearch') insert([[ not the match you're looking for the match is here]]) @@ -198,7 +198,7 @@ describe('search highlighting', function() end) it('works with multiline regexps', function() - execute('set hlsearch') + feed_command('set hlsearch') feed('4oa repeated line<esc>') feed('/line\\na<cr>') screen:expect([[ @@ -234,19 +234,19 @@ describe('search highlighting', function() [6] = {italic = true, background = colors.Magenta}, [7] = {bold = true, background = colors.Yellow}, } ) - execute('set hlsearch') + feed_command('set hlsearch') insert([[ very special text ]]) - execute("syntax on") - execute("highlight MyGroup guibg=Green gui=bold") - execute("highlight MyGroup2 guibg=Magenta gui=italic") - execute("call matchadd('MyGroup', 'special')") - execute("call matchadd('MyGroup2', 'text', 0)") + feed_command("syntax on") + feed_command("highlight MyGroup guibg=Green gui=bold") + feed_command("highlight MyGroup2 guibg=Magenta gui=italic") + feed_command("call matchadd('MyGroup', 'special')") + feed_command("call matchadd('MyGroup2', 'text', 0)") -- searchhl and matchadd matches are exclusive, only the higest priority -- is used (and matches with lower priorities are not combined) - execute("/ial te") + feed_command("/ial te") screen:expect([[ very {5:spec^ial}{2: te}{6:xt} | | @@ -257,7 +257,7 @@ describe('search highlighting', function() {4:search hit BOTTOM, continuing at TOP} | ]]) - execute("call clearmatches()") + feed_command("call clearmatches()") screen:expect([[ very spec{2:^ial te}xt | | @@ -270,7 +270,7 @@ describe('search highlighting', function() -- searchhl has priority over syntax, but in this case -- nonconflicting attributes are combined - execute("syntax keyword MyGroup special") + feed_command("syntax keyword MyGroup special") screen:expect([[ very {5:spec}{7:^ial}{2: te}xt | | diff --git a/test/functional/ui/sign_spec.lua b/test/functional/ui/sign_spec.lua index d02fc83809..e5c96f2ec0 100644 --- a/test/functional/ui/sign_spec.lua +++ b/test/functional/ui/sign_spec.lua @@ -1,6 +1,6 @@ local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') -local clear, feed, execute = helpers.clear, helpers.feed, helpers.execute +local clear, feed, command = helpers.clear, helpers.feed, helpers.command if helpers.pending_win32(pending) then return end @@ -25,11 +25,11 @@ describe('Signs', function() describe(':sign place', function() it('shadows previously placed signs', function() feed('ia<cr>b<cr>c<cr><esc>') - execute('sign define piet text=>> texthl=Search') - execute('sign define pietx text=>! texthl=Search') - execute('sign place 1 line=1 name=piet buffer=1') - execute('sign place 2 line=3 name=piet buffer=1') - execute('sign place 3 line=1 name=pietx buffer=1') + command('sign define piet text=>> texthl=Search') + command('sign define pietx text=>! texthl=Search') + command('sign place 1 line=1 name=piet buffer=1') + command('sign place 2 line=3 name=piet buffer=1') + command('sign place 3 line=1 name=pietx buffer=1') screen:expect([[ {1:>!}a | {2: }b | @@ -44,7 +44,7 @@ describe('Signs', function() {2: }{0:~ }| {2: }{0:~ }| {2: }{0:~ }| - :sign place 3 line=1 name=pietx buffer=1 | + | ]]) end) end) diff --git a/test/functional/ui/syntax_conceal_spec.lua b/test/functional/ui/syntax_conceal_spec.lua index ee3e4fa32a..28a104360d 100644 --- a/test/functional/ui/syntax_conceal_spec.lua +++ b/test/functional/ui/syntax_conceal_spec.lua @@ -1,6 +1,6 @@ local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') -local clear, feed, execute = helpers.clear, helpers.feed, helpers.execute +local clear, feed, command = helpers.clear, helpers.feed, helpers.command local insert = helpers.insert if helpers.pending_win32(pending) then return end @@ -25,7 +25,7 @@ describe('Screen', function() describe("match and conceal", function() before_each(function() - execute("let &conceallevel=1") + command("let &conceallevel=1") end) describe("multiple", function() @@ -38,7 +38,7 @@ describe('Screen', function() && && ]]) - execute("syn match dAmpersand '[&][&]' conceal cchar=โง") + command("syn match dAmpersand '[&][&]' conceal cchar=โง") end) it("double characters.", function() @@ -52,7 +52,7 @@ describe('Screen', function() ^ | {0:~ }| {0:~ }| - :syn match dAmpersand '[&][&]' conceal cchar=โง | + | ]]) end) @@ -68,7 +68,7 @@ describe('Screen', function() | {0:~ }| {0:~ }| - :syn match dAmpersand '[&][&]' conceal cchar=โง | + | ]]) end) @@ -84,7 +84,7 @@ describe('Screen', function() | {0:~ }| {0:~ }| - :syn match dAmpersand '[&][&]' conceal cchar=โง | + | ]]) end) @@ -100,7 +100,7 @@ describe('Screen', function() | {0:~ }| {0:~ }| - :syn match dAmpersand '[&][&]' conceal cchar=โง | + | ]]) end) @@ -116,15 +116,15 @@ describe('Screen', function() ^ | {0:~ }| {0:~ }| - :syn match dAmpersand '[&][&]' conceal cchar=โง | + | ]]) end) end) -- multiple it("keyword instances in initially in the document.", function() feed("2ilambda<cr><ESC>") - execute("let &conceallevel=1") - execute("syn keyword kLambda lambda conceal cchar=ฮป") + command("let &conceallevel=1") + command("syn keyword kLambda lambda conceal cchar=ฮป") screen:expect([[ {1:ฮป} | {1:ฮป} | @@ -135,7 +135,7 @@ describe('Screen', function() {0:~ }| {0:~ }| {0:~ }| - :syn keyword kLambda lambda conceal cchar=ฮป | + | ]]) end) -- Keyword @@ -144,11 +144,11 @@ describe('Screen', function() before_each(function() feed("2") insert("<r> a region of text </r>\n") - execute("let &conceallevel=1") + command("let &conceallevel=1") end) it('initially and conceal it.', function() - execute("syn region rText start='<r>' end='</r>' conceal cchar=R") + command("syn region rText start='<r>' end='</r>' conceal cchar=R") screen:expect([[ {1:R} | {1:R} | @@ -166,7 +166,7 @@ describe('Screen', function() it('initially and conceal its start tag and end tag.', function() -- concealends has a known bug (todo.txt) where the first match won't -- be replaced with cchar. - execute("syn region rText matchgroup=rMatch start='<r>' end='</r>' concealends cchar=-") + command("syn region rText matchgroup=rMatch start='<r>' end='</r>' concealends cchar=-") screen:expect([[ {1: } a region of text {1:-} | {1: } a region of text {1:-} | @@ -182,7 +182,7 @@ describe('Screen', function() end) it('that are nested and conceal the nested region\'s start and end tags.', function() - execute("syn region rText contains=rText matchgroup=rMatch start='<r>' end='</r>' concealends cchar=-") + command("syn region rText contains=rText matchgroup=rMatch start='<r>' end='</r>' concealends cchar=-") insert("<r> A region with <r> a nested <r> nested region.</r> </r> </r>\n") screen:expect([[ {1: } a region of text {1:-} | @@ -201,10 +201,10 @@ describe('Screen', function() describe("a region of text", function() before_each(function() - execute("syntax conceal on") + command("syntax conceal on") feed("2") insert("<r> a region of text </r>\n") - execute("syn region rText start='<r>' end='</r>' cchar=-") + command("syn region rText start='<r>' end='</r>' cchar=-") end) it("and turn on implicit concealing", function() @@ -218,15 +218,15 @@ describe('Screen', function() {0:~ }| {0:~ }| {0:~ }| - :syn region rText start='<r>' end='</r>' cchar=- | + | ]]) end) it("and then turn on, then off, and then back on implicit concealing.", function() - execute("syntax conceal off") + command("syntax conceal off") feed("2") insert("<i> italian text </i>\n") - execute("syn region iText start='<i>' end='</i>' cchar=*") + command("syn region iText start='<i>' end='</i>' cchar=*") screen:expect([[ {1:-} | {1:-} | @@ -237,10 +237,10 @@ describe('Screen', function() {0:~ }| {0:~ }| {0:~ }| - :syn region iText start='<i>' end='</i>' cchar=* | + | ]]) - execute("syntax conceal on") - execute("syn region iText start='<i>' end='</i>' cchar=*") + command("syntax conceal on") + command("syn region iText start='<i>' end='</i>' cchar=*") screen:expect([[ {1:-} | {1:-} | @@ -251,7 +251,7 @@ describe('Screen', function() {0:~ }| {0:~ }| {0:~ }| - :syn region iText start='<i>' end='</i>' cchar=* | + | ]]) end) end) -- a region of text (implicit concealing) @@ -262,13 +262,13 @@ describe('Screen', function() insert("// No Conceal\n") insert('"Conceal without a cchar"\n') insert("+ With cchar\n\n") - execute("syn match noConceal '^//.*$'") - execute("syn match concealNoCchar '\".\\{-}\"$' conceal") - execute("syn match concealWCchar '^+.\\{-}$' conceal cchar=C") + command("syn match noConceal '^//.*$'") + command("syn match concealNoCchar '\".\\{-}\"$' conceal") + command("syn match concealWCchar '^+.\\{-}$' conceal cchar=C") end) it("0. No concealing.", function() - execute("let &conceallevel=0") + command("let &conceallevel=0") screen:expect([[ // No Conceal | "Conceal without a cchar" | @@ -279,12 +279,12 @@ describe('Screen', function() {0:~ }| {0:~ }| {0:~ }| - :let &conceallevel=0 | + | ]]) end) it("1. Conceal using cchar or reference listchars.", function() - execute("let &conceallevel=1") + command("let &conceallevel=1") screen:expect([[ // No Conceal | {1: } | @@ -295,12 +295,12 @@ describe('Screen', function() {0:~ }| {0:~ }| {0:~ }| - :let &conceallevel=1 | + | ]]) end) it("2. Hidden unless cchar is set.", function() - execute("let &conceallevel=2") + command("let &conceallevel=2") screen:expect([[ // No Conceal | | @@ -311,12 +311,12 @@ describe('Screen', function() {0:~ }| {0:~ }| {0:~ }| - :let &conceallevel=2 | + | ]]) end) it("3. Hide all concealed text.", function() - execute("let &conceallevel=3") + command("let &conceallevel=3") screen:expect([[ // No Conceal | | @@ -327,7 +327,7 @@ describe('Screen', function() {0:~ }| {0:~ }| {0:~ }| - :let &conceallevel=3 | + | ]]) end) end) -- conceallevel diff --git a/test/functional/ui/tabline_spec.lua b/test/functional/ui/tabline_spec.lua new file mode 100644 index 0000000000..56331a33b5 --- /dev/null +++ b/test/functional/ui/tabline_spec.lua @@ -0,0 +1,57 @@ +local helpers = require('test.functional.helpers')(after_each) +local Screen = require('test.functional.ui.screen') +local clear, command, eq = helpers.clear, helpers.command, helpers.eq + +describe('ui/tabline', function() + local screen + local event_tabs, event_curtab + + before_each(function() + clear() + screen = Screen.new(25, 5) + screen:attach({rgb=true, ext_tabline=true}) + screen:set_on_event_handler(function(name, data) + if name == "tabline_update" then + event_curtab, event_tabs = unpack(data) + end + end) + end) + + after_each(function() + screen:detach() + end) + + describe('externalized', function() + it('publishes UI events', function() + command("tabedit another-tab") + + local expected_tabs = { + {tab = { id = 1 }, name = '[No Name]'}, + {tab = { id = 2 }, name = 'another-tab'}, + } + screen:expect([[ + ^ | + ~ | + ~ | + ~ | + | + ]], nil, nil, function() + eq({ id = 2 }, event_curtab) + eq(expected_tabs, event_tabs) + end) + + command("tabNext") + screen:expect([[ + ^ | + ~ | + ~ | + ~ | + | + ]], nil, nil, function() + eq({ id = 1 }, event_curtab) + eq(expected_tabs, event_tabs) + end) + + end) + end) +end) diff --git a/test/functional/ui/wildmode_spec.lua b/test/functional/ui/wildmode_spec.lua index 6a6dc99c3d..41a751c284 100644 --- a/test/functional/ui/wildmode_spec.lua +++ b/test/functional/ui/wildmode_spec.lua @@ -1,36 +1,151 @@ local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') -local clear, feed, execute = helpers.clear, helpers.feed, helpers.execute +local clear, feed, command = helpers.clear, helpers.feed, helpers.command +local iswin = helpers.iswin local funcs = helpers.funcs +local eq = helpers.eq +local eval = helpers.eval +local retry = helpers.retry -if helpers.pending_win32(pending) then return end - -describe("'wildmode'", function() +describe("'wildmenu'", function() local screen - before_each(function() clear() screen = Screen.new(25, 5) screen:attach() end) - after_each(function() screen:detach() end) - describe("'wildmenu'", function() - it(':sign <tab> shows wildmenu completions', function() - execute('set wildmode=full') - execute('set wildmenu') - feed(':sign <tab>') - screen:expect([[ - | - ~ | - ~ | - define jump list > | - :sign define^ | - ]]) + it(':sign <tab> shows wildmenu completions', function() + command('set wildmode=full') + command('set wildmenu') + feed(':sign <tab>') + screen:expect([[ + | + ~ | + ~ | + define jump list > | + :sign define^ | + ]]) + end) + + it('does not crash after cycling back to original text', function() + command('set wildmode=full') + feed(':j<Tab><Tab><Tab>') + screen:expect([[ + | + ~ | + ~ | + join jumps | + :j^ | + ]]) + -- This would cause nvim to crash before #6650 + feed('<BS><Tab>') + screen:expect([[ + | + ~ | + ~ | + ! # & < = > @ > | + :!^ | + ]]) + end) + + it('is preserved during :terminal activity', function() + -- Because this test verifies a _lack_ of activity after screen:sleep(), we + -- must wait the full timeout. So make it reasonable. + screen.timeout = 1000 + + command('set wildmenu wildmode=full') + command('set scrollback=4') + if iswin() then + if helpers.pending_win32(pending) then return end + -- feed([[:terminal 1,2,3,4,5 | foreach-object -process {echo $_; sleep 0.1}]]) + else + feed([[:terminal for i in $(seq 1 5000); do printf 'foo\nfoo\nfoo\n'; sleep 0.1; done<cr>]]) + end + + feed([[<C-\><C-N>gg]]) + feed([[:sign <Tab>]]) -- Invoke wildmenu. + screen:sleep(50) -- Allow some terminal output. + screen:expect([[ + foo | + foo | + foo | + define jump list > | + :sign define^ | + ]]) + + -- cmdline CTRL-D display should also be preserved. + feed([[<C-\><C-N>]]) + feed([[:sign <C-D>]]) -- Invoke cmdline CTRL-D. + screen:sleep(50) -- Allow some terminal output. + screen:expect([[ + :sign | + define place | + jump undefine | + list unplace | + :sign ^ | + ]]) + + -- Exiting cmdline should show the buffer. + feed([[<C-\><C-N>]]) + screen:expect([[ + ^foo | + foo | + foo | + foo | + | + ]]) + end) + + it('ignores :redrawstatus called from a timer #7108', function() + -- Because this test verifies a _lack_ of activity after screen:sleep(), we + -- must wait the full timeout. So make it reasonable. + screen.timeout = 1000 + + command('set wildmenu wildmode=full') + command([[call timer_start(10, {->execute('redrawstatus')}, {'repeat':-1})]]) + feed([[<C-\><C-N>]]) + feed([[:sign <Tab>]]) -- Invoke wildmenu. + screen:sleep(30) -- Allow some timer activity. + screen:expect([[ + | + ~ | + ~ | + define jump list > | + :sign define^ | + ]]) + end) + + it('with laststatus=0, :vsplit, :term #2255', function() + -- Because this test verifies a _lack_ of activity after screen:sleep(), we + -- must wait the full timeout. So make it reasonable. + screen.timeout = 1000 + + if not iswin() then + command('set shell=sh') -- Need a predictable "$" prompt. + end + command('set laststatus=0') + command('vsplit') + command('term') + + -- Check for a shell prompt to verify that the terminal loaded. + retry(nil, nil, function() + if iswin() then + eq('Microsoft', eval("matchstr(join(getline(1, '$')), 'Microsoft')")) + else + eq('$', eval([[matchstr(getline(1), '\$')]])) + end end) + + feed([[<C-\><C-N>]]) + feed([[:<Tab>]]) -- Invoke wildmenu. + screen:sleep(10) -- Flush + -- Check only the last 2 lines, because the shell output is + -- system-dependent. + screen:expect('! # & < = > @ > \n:!^', nil, nil, nil, true) end) end) @@ -50,10 +165,10 @@ describe('command line completion', function() it('lists directories with empty PATH', function() local tmp = funcs.tempname() - execute('e '.. tmp) - execute('cd %:h') - execute("call mkdir('Xtest-functional-viml-compl-dir')") - execute('let $PATH=""') + command('e '.. tmp) + command('cd %:h') + command("call mkdir('Xtest-functional-viml-compl-dir')") + command('let $PATH=""') feed(':!<tab><bs>') screen:expect([[ | diff --git a/test/functional/viml/completion_spec.lua b/test/functional/viml/completion_spec.lua index cd5f4260e0..0e5278345c 100644 --- a/test/functional/viml/completion_spec.lua +++ b/test/functional/viml/completion_spec.lua @@ -2,7 +2,8 @@ local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') local clear, feed = helpers.clear, helpers.feed local eval, eq, neq = helpers.eval, helpers.eq, helpers.neq -local execute, source, expect = helpers.execute, helpers.source, helpers.expect +local feed_command, source, expect = helpers.feed_command, helpers.source, helpers.expect +local meths = helpers.meths if helpers.pending_win32(pending) then return end @@ -66,25 +67,25 @@ describe('completion', function() it('is readonly', function() screen:try_resize(80, 8) feed('ifoo<ESC>o<C-x><C-n><ESC>') - execute('let v:completed_item.word = "bar"') + feed_command('let v:completed_item.word = "bar"') neq(nil, string.find(eval('v:errmsg'), '^E46: ')) - execute('let v:errmsg = ""') + feed_command('let v:errmsg = ""') - execute('let v:completed_item.abbr = "bar"') + feed_command('let v:completed_item.abbr = "bar"') neq(nil, string.find(eval('v:errmsg'), '^E46: ')) - execute('let v:errmsg = ""') + feed_command('let v:errmsg = ""') - execute('let v:completed_item.menu = "bar"') + feed_command('let v:completed_item.menu = "bar"') neq(nil, string.find(eval('v:errmsg'), '^E46: ')) - execute('let v:errmsg = ""') + feed_command('let v:errmsg = ""') - execute('let v:completed_item.info = "bar"') + feed_command('let v:completed_item.info = "bar"') neq(nil, string.find(eval('v:errmsg'), '^E46: ')) - execute('let v:errmsg = ""') + feed_command('let v:errmsg = ""') - execute('let v:completed_item.kind = "bar"') + feed_command('let v:completed_item.kind = "bar"') neq(nil, string.find(eval('v:errmsg'), '^E46: ')) - execute('let v:errmsg = ""') + feed_command('let v:errmsg = ""') end) it('returns expected dict in omni completion', function() source([[ @@ -124,7 +125,7 @@ describe('completion', function() end) it('inserts the first candidate if default', function() - execute('set completeopt+=menuone') + feed_command('set completeopt+=menuone') feed('ifoo<ESC>o') screen:expect([[ foo | @@ -175,7 +176,7 @@ describe('completion', function() eq('foo', eval('getline(3)')) end) it('selects the first candidate if noinsert', function() - execute('set completeopt+=menuone,noinsert') + feed_command('set completeopt+=menuone,noinsert') feed('ifoo<ESC>o<C-x><C-n>') screen:expect([[ foo | @@ -215,7 +216,7 @@ describe('completion', function() eq('foo', eval('getline(3)')) end) it('does not insert the first candidate if noselect', function() - execute('set completeopt+=menuone,noselect') + feed_command('set completeopt+=menuone,noselect') feed('ifoo<ESC>o<C-x><C-n>') screen:expect([[ foo | @@ -255,7 +256,7 @@ describe('completion', function() eq('bar', eval('getline(3)')) end) it('does not select/insert the first candidate if noselect and noinsert', function() - execute('set completeopt+=menuone,noselect,noinsert') + feed_command('set completeopt+=menuone,noselect,noinsert') feed('ifoo<ESC>o<C-x><C-n>') screen:expect([[ foo | @@ -304,14 +305,14 @@ describe('completion', function() eq('', eval('getline(3)')) end) it('does not change modified state if noinsert', function() - execute('set completeopt+=menuone,noinsert') - execute('setlocal nomodified') + feed_command('set completeopt+=menuone,noinsert') + feed_command('setlocal nomodified') feed('i<C-r>=TestComplete()<CR><ESC>') eq(0, eval('&l:modified')) end) it('does not change modified state if noselect', function() - execute('set completeopt+=menuone,noselect') - execute('setlocal nomodified') + feed_command('set completeopt+=menuone,noselect') + feed_command('setlocal nomodified') feed('i<C-r>=TestComplete()<CR><ESC>') eq(0, eval('&l:modified')) end) @@ -325,8 +326,8 @@ describe('completion', function() return '' endfunction ]]) - execute('set completeopt+=noselect,noinsert') - execute('inoremap <right> <c-r>=TestComplete()<cr>') + feed_command('set completeopt+=noselect,noinsert') + feed_command('inoremap <right> <c-r>=TestComplete()<cr>') end) local tests = { @@ -540,7 +541,7 @@ describe('completion', function() return '' endfunction ]]) - execute("set completeopt=menuone,noselect") + feed_command("set completeopt=menuone,noselect") end) it("works", function() @@ -706,7 +707,7 @@ describe('completion', function() it('disables folding during completion', function () - execute("set foldmethod=indent") + feed_command("set foldmethod=indent") feed('i<Tab>foo<CR><Tab>bar<Esc>gg') screen:expect([[ ^foo | @@ -733,7 +734,7 @@ describe('completion', function() end) it('popupmenu is not interrupted by events', function () - execute("set complete=.") + feed_command("set complete=.") feed('ifoobar fooegg<cr>f<c-p>') screen:expect([[ @@ -814,15 +815,66 @@ describe('completion', function() end) end) + describe('with numeric items', function() + before_each(function() + source([[ + function! TestComplete() abort + call complete(1, g:_complist) + return '' + endfunction + ]]) + meths.set_option('completeopt', 'menuone,noselect') + meths.set_var('_complist', {{ + word=0, + abbr=1, + menu=2, + kind=3, + info=4, + icase=5, + dup=6, + empty=7, + }}) + end) + + it('shows correct variant as word', function() + feed('i<C-r>=TestComplete()<CR>') + screen:expect([[ + ^ | + {1:1 3 2 }{0: }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {3:-- INSERT --} | + ]]) + end) + end) + + it("'ignorecase' 'infercase' CTRL-X CTRL-N #6451", function() + feed_command('set ignorecase infercase') + feed_command('edit BACKERS.md') + feed('oX<C-X><C-N>') + screen:expect([[ + # Bountysource Backers | + Xnull^ | + {2:Xnull }{6: } | + {1:Xoxomoon }{6: }ryone who backed our [Bountysource fundraise| + {1:Xu }{6: }ountysource.com/teams/neovim/fundraiser)! | + {1:Xpayn }{2: } | + {1:Xinity }{2: }d URL in BACKERS.md. | + {3:-- Keyword Local completion (^N^P) }{4:match 1 of 7} | + ]]) + end) end) -describe('External completion popupmenu', function() +describe('ui/externalized/popupmenu', function() local screen local items, selected, anchor before_each(function() clear() screen = Screen.new(60, 8) - screen:attach({rgb=true, popupmenu_external=true}) + screen:attach({rgb=true, ext_popupmenu=true}) screen:set_default_attr_ids({ [1] = {bold=true, foreground=Screen.colors.Blue}, [2] = {bold = true}, diff --git a/test/functional/viml/errorlist_spec.lua b/test/functional/viml/errorlist_spec.lua index f889ca9adc..6c5a63e6b1 100644 --- a/test/functional/viml/errorlist_spec.lua +++ b/test/functional/viml/errorlist_spec.lua @@ -27,20 +27,18 @@ describe('setqflist()', function() setqflist({''}, 'r', 'foo') command('copen') eq(':foo', get_cur_win_var('quickfix_title')) + setqflist({''}, 'r', {['title'] = 'qf_title'}) + eq('qf_title', get_cur_win_var('quickfix_title')) end) - it('requires string or number for {title}', function() - command('copen') + it('allows string {what} for backwards compatibility', function() setqflist({}, 'r', '5') + command('copen') eq(':5', get_cur_win_var('quickfix_title')) - setqflist({}, 'r', 6) - eq(':6', get_cur_win_var('quickfix_title')) - local exc = exc_exec('call setqflist([], "r", function("function"))') - eq('Vim(call):E729: using Funcref as a String', exc) - exc = exc_exec('call setqflist([], "r", [])') - eq('Vim(call):E730: using List as a String', exc) - exc = exc_exec('call setqflist([], "r", {})') - eq('Vim(call):E731: using Dictionary as a String', exc) + end) + + it('requires a dict for {what}', function() + eq('Vim(call):E715: Dictionary required', exc_exec('call setqflist([], "r", function("function"))')) end) end) diff --git a/test/functional/viml/function_spec.lua b/test/functional/viml/function_spec.lua index 776e760aaf..0cf92f7d40 100644 --- a/test/functional/viml/function_spec.lua +++ b/test/functional/viml/function_spec.lua @@ -1,29 +1,221 @@ local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear local eq = helpers.eq -local exc_exec = helpers.exc_exec +local clear = helpers.clear +local funcs = helpers.funcs +local dedent = helpers.dedent +local redir_exec = helpers.redir_exec -describe('Up to MAX_FUNC_ARGS arguments are handled by', function() - local max_func_args = 20 -- from eval.h - local range = helpers.funcs.range +before_each(clear) - before_each(clear) +local function check_nofunc(fname) + eq(0, funcs.exists('*' .. fname)) +end - it('printf()', function() - local printf = helpers.funcs.printf - local rep = helpers.funcs['repeat'] - local expected = '2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,' - eq(expected, printf(rep('%d,', max_func_args-1), unpack(range(2, max_func_args)))) - local ret = exc_exec('call printf("", 2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21)') - eq('Vim(call):E740: Too many arguments for function printf', ret) - end) +local function check_func(fname, body, indent) + if type(body) == 'number' then + body = ('return %i'):format(body) + end + eq(dedent(([[ - it('rpcnotify()', function() - local rpcnotify = helpers.funcs.rpcnotify - local ret = rpcnotify(0, 'foo', unpack(range(3, max_func_args))) - eq(1, ret) - ret = exc_exec('call rpcnotify(0, "foo", 3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21)') - eq('Vim(call):E740: Too many arguments for function rpcnotify', ret) + function %s()%s + endfunction]] + ), 3):format( + fname, + body and ('\n1' .. (' '):rep(2 + (indent or 8)) .. body) or ''), + redir_exec('function ' .. fname)) +end + +describe(':endfunction', function() + it('accepts bang', function() + eq('', redir_exec([[ + function F() + endfunction! + ]])) + check_func('F') + eq('', redir_exec([[ + function! F() + return 1 + endfunction! + ]])) + check_func('F', 1) + end) + it('accepts comments', function() + eq('', redir_exec([[ + function F1() + endfunction " Comment + ]])) + check_func('F1') + eq('', redir_exec([[ + function F2() + endfunction " }}} + ]])) + check_func('F2') + eq('', redir_exec([[ + function F3() + endfunction " F3 + ]])) + check_func('F3') + eq('', redir_exec([[ + function F4() + endfunction! " F4 + ]])) + check_func('F4') + eq('', redir_exec([[ + function! F4() + return 2 + endfunction! " F4 + ]])) + check_func('F4', 2) + end) + it('accepts function name', function() + eq('', redir_exec([[ + function F0() + endfunction F0 + ]])) + check_func('F0') + eq('', redir_exec([[ + function F1() + endfunction! F1 + ]])) + check_func('F1') + eq('', redir_exec([[ + function! F2() + endfunction! F2 + ]])) + check_func('F2') + eq('', redir_exec([[ + function! F2() + return 3 + endfunction! F2 + ]])) + check_func('F2', 3) + end) + it('accepts weird characters', function() + eq('', redir_exec([[ + function F1() + endfunction: }}} + ]])) + check_func('F1') + -- From accurev + eq('', redir_exec([[ + function F2() + endfunction :}}} + ]])) + check_func('F2') + -- From cream-vimabbrev + eq('', redir_exec([[ + function F3() + endfunction 1}}} + ]])) + check_func('F3') + -- From pyunit + eq('', redir_exec([[ + function F4() + endfunction # }}} + ]])) + check_func('F4') + -- From vim-lldb + eq('', redir_exec([[ + function F5() + endfunction() + ]])) + check_func('F5') + -- From vim-mail + eq('', redir_exec([[ + function F6() + endfunction; + ]])) + check_func('F6') + end) + it('accepts commented bar', function() + eq('', redir_exec([[ + function F1() + endfunction " F1 | echo 42 + ]])) + check_func('F1') + eq('', redir_exec([[ + function! F1() + return 42 + endfunction! " F1 | echo 42 + ]])) + check_func('F1', 42) + end) + it('errors out on an uncommented bar', function() + eq('\nE488: Trailing characters: | echo 42', redir_exec([[ + function F1() + endfunction | echo 42 + ]])) + check_nofunc('F1') + end) + it('allows running multiple commands', function() + eq('\n2', redir_exec([[ + function F1() + echo 2 + endfunction + call F1() + ]])) + check_func('F1', 'echo 2') + eq('\n2\n3\n4', redir_exec([[ + function F2() + echo 2 + endfunction F2 + function F3() + echo 3 + endfunction " F3 + function! F4() + echo 4 + endfunction! + call F2() + call F3() + call F4() + ]])) + check_func('F2', 'echo 2') + check_func('F3', 'echo 3') + check_func('F4', 'echo 4') + end) + it('allows running multiple commands with only one character in between', + function() + eq('\n3', redir_exec(dedent([[ + function! F1() + echo 3 + endfunction! + call F1()]]))) + check_func('F1', 'echo 3', 2) + eq('\n4', redir_exec(dedent([[ + function F5() + echo 4 + endfunction + call F5()]]))) + check_func('F5', 'echo 4', 2) + eq('\n5', redir_exec(dedent([[ + function F6() + echo 5 + endfunction " TEST + call F6()]]))) + check_func('F6', 'echo 5', 2) + eq('\n6', redir_exec(dedent([[ + function F7() + echo 6 + endfunction F7 + call F7()]]))) + check_func('F7', 'echo 6', 2) + eq('\n2\n3\n4', redir_exec(dedent([[ + function F2() + echo 2 + endfunction F2 + function F3() + echo 3 + endfunction " F3 + function! F4() + echo 4 + endfunction! + call F2() + call F3() + call F4()]]))) + check_func('F2', 'echo 2', 2) + check_func('F3', 'echo 3', 2) + check_func('F4', 'echo 4', 2) end) end) +-- vim: foldmarker=โถ,โฒ diff --git a/test/functional/viml/lang_spec.lua b/test/functional/viml/lang_spec.lua index a27e18f695..3ba9221aef 100644 --- a/test/functional/viml/lang_spec.lua +++ b/test/functional/viml/lang_spec.lua @@ -1,13 +1,12 @@ local helpers = require('test.functional.helpers')(after_each) local clear, eval, eq = helpers.clear, helpers.eval, helpers.eq -local execute, source = helpers.execute, helpers.source +local exc_exec, source = helpers.exc_exec, helpers.source describe('viml', function() before_each(clear) it('parses `<SID>` with turkish locale', function() - execute('lang ctype tr_TR.UTF-8') - if string.find(eval('v:errmsg'), '^E197: ') then + if exc_exec('lang ctype tr_TR.UTF-8') ~= 0 then pending("Locale tr_TR.UTF-8 not supported") return end diff --git a/test/helpers.lua b/test/helpers.lua index 0bc62da5d7..260f10002e 100644 --- a/test/helpers.lua +++ b/test/helpers.lua @@ -17,6 +17,49 @@ local ok = function(res) return assert.is_true(res) end +-- initial_path: directory to recurse into +-- re: include pattern (string) +-- exc_re: exclude pattern(s) (string or table) +local function glob(initial_path, re, exc_re) + exc_re = type(exc_re) == 'table' and exc_re or { exc_re } + local paths_to_check = {initial_path} + local ret = {} + local checked_files = {} + local function is_excluded(path) + for _, pat in pairs(exc_re) do + if path:match(pat) then return true end + end + return false + end + + if is_excluded(initial_path) then + return ret + end + while #paths_to_check > 0 do + local cur_path = paths_to_check[#paths_to_check] + paths_to_check[#paths_to_check] = nil + for e in lfs.dir(cur_path) do + local full_path = cur_path .. '/' .. e + local checked_path = full_path:sub(#initial_path + 1) + if (not is_excluded(checked_path)) and e:sub(1, 1) ~= '.' then + local attrs = lfs.attributes(full_path) + if attrs then + local check_key = attrs.dev .. ':' .. tostring(attrs.ino) + if not checked_files[check_key] then + checked_files[check_key] = true + if attrs.mode == 'directory' then + paths_to_check[#paths_to_check + 1] = full_path + elseif not re or checked_path:match(re) then + ret[#ret + 1] = full_path + end + end + end + end + end + end + return ret +end + local function check_logs() local log_dir = os.getenv('LOG_DIR') local runtime_errors = 0 @@ -68,6 +111,7 @@ local uname = (function() local status, f = pcall(io.popen, "uname -s") if status then platform = f:read("*l") + f:close() else platform = 'Windows' end @@ -75,19 +119,192 @@ local uname = (function() end) end)() -local function tmpname() - local fname = os.tmpname() - if uname() == 'Windows' and fname:sub(1, 2) == '\\s' then - -- In Windows tmpname() returns a filename starting with - -- special sequence \s, prepend $TEMP path - local tmpdir = os.getenv('TEMP') - return tmpdir..fname - elseif fname:match('^/tmp') and uname() == 'Darwin' then - -- In OS X /tmp links to /private/tmp - return '/private'..fname +local function tmpdir_get() + return os.getenv('TMPDIR') and os.getenv('TMPDIR') or os.getenv('TEMP') +end + +-- Is temp directory `dir` defined local to the project workspace? +local function tmpdir_is_local(dir) + return not not (dir and string.find(dir, 'Xtest')) +end + +local tmpname = (function() + local seq = 0 + local tmpdir = tmpdir_get() + return (function() + if tmpdir_is_local(tmpdir) then + -- Cannot control os.tmpname() dir, so hack our own tmpname() impl. + seq = seq + 1 + local fname = tmpdir..'/nvim-test-lua-'..seq + io.open(fname, 'w'):close() + return fname + else + local fname = os.tmpname() + if uname() == 'Windows' and fname:sub(1, 2) == '\\s' then + -- In Windows tmpname() returns a filename starting with + -- special sequence \s, prepend $TEMP path + return tmpdir..fname + elseif fname:match('^/tmp') and uname() == 'Darwin' then + -- In OS X /tmp links to /private/tmp + return '/private'..fname + else + return fname + end + end + end) +end)() + +local function map(func, tab) + local rettab = {} + for k, v in pairs(tab) do + rettab[k] = func(v) + end + return rettab +end + +local function filter(filter_func, tab) + local rettab = {} + for _, entry in pairs(tab) do + if filter_func(entry) then + table.insert(rettab, entry) + end + end + return rettab +end + +local function hasenv(name) + local env = os.getenv(name) + if env and env ~= '' then + return env + end + return nil +end + +local tests_skipped = 0 + +local function check_cores(app, force) + app = app or 'build/bin/nvim' + local initial_path, re, exc_re + local gdb_db_cmd = 'gdb -n -batch -ex "thread apply all bt full" "$_NVIM_TEST_APP" -c "$_NVIM_TEST_CORE"' + local lldb_db_cmd = 'lldb -Q -o "bt all" -f "$_NVIM_TEST_APP" -c "$_NVIM_TEST_CORE"' + local random_skip = false + -- Workspace-local $TMPDIR, scrubbed and pattern-escaped. + -- "./Xtest-tmpdir/" => "Xtest%-tmpdir" + local local_tmpdir = (tmpdir_is_local(tmpdir_get()) + and tmpdir_get():gsub('^[ ./]+',''):gsub('%/+$',''):gsub('([^%w])', '%%%1') + or nil) + local db_cmd + if hasenv('NVIM_TEST_CORE_GLOB_DIRECTORY') then + initial_path = os.getenv('NVIM_TEST_CORE_GLOB_DIRECTORY') + re = os.getenv('NVIM_TEST_CORE_GLOB_RE') + exc_re = { os.getenv('NVIM_TEST_CORE_EXC_RE'), local_tmpdir } + db_cmd = os.getenv('NVIM_TEST_CORE_DB_CMD') or gdb_db_cmd + random_skip = os.getenv('NVIM_TEST_CORE_RANDOM_SKIP') + elseif os.getenv('TRAVIS_OS_NAME') == 'osx' then + initial_path = '/cores' + re = nil + exc_re = { local_tmpdir } + db_cmd = lldb_db_cmd + else + initial_path = '.' + re = '/core[^/]*$' + exc_re = { '^/%.deps$', local_tmpdir } + db_cmd = gdb_db_cmd + random_skip = true + end + -- Finding cores takes too much time on linux + if not force and random_skip and math.random() < 0.9 then + tests_skipped = tests_skipped + 1 + return + end + local cores = glob(initial_path, re, exc_re) + local found_cores = 0 + local out = io.stdout + for _, core in ipairs(cores) do + local len = 80 - #core - #('Core file ') - 2 + local esigns = ('='):rep(len / 2) + out:write(('\n%s Core file %s %s\n'):format(esigns, core, esigns)) + out:flush() + local pipe = io.popen( + db_cmd:gsub('%$_NVIM_TEST_APP', app):gsub('%$_NVIM_TEST_CORE', core) + .. ' 2>&1', 'r') + if pipe then + local bt = pipe:read('*a') + if bt then + out:write(bt) + out:write('\n') + else + out:write('Failed to read from the pipe\n') + end + else + out:write('Failed to create pipe\n') + end + out:flush() + found_cores = found_cores + 1 + os.remove(core) + end + if found_cores ~= 0 then + out:write(('\nTests covered by this check: %u\n'):format(tests_skipped + 1)) + end + tests_skipped = 0 + if found_cores > 0 then + error("crash detected (see above)") + end +end + +local function which(exe) + local pipe = io.popen('which ' .. exe, 'r') + local ret = pipe:read('*a') + pipe:close() + if ret == '' then + return nil else - return fname + return ret:sub(1, -2) + end +end + +local function shallowcopy(orig) + local copy = {} + for orig_key, orig_value in pairs(orig) do + copy[orig_key] = orig_value + end + return copy +end + +local function concat_tables(...) + local ret = {} + for i = 1, select('#', ...) do + local tbl = select(i, ...) + if tbl then + for _, v in ipairs(tbl) do + ret[#ret + 1] = v + end + end + end + return ret +end + +local function dedent(str, leave_indent) + -- find minimum common indent across lines + local indent = nil + for line in str:gmatch('[^\n]+') do + local line_indent = line:match('^%s+') or '' + if indent == nil or #line_indent < #indent then + indent = line_indent + end + end + if indent == nil or #indent == 0 then + -- no minimum common indent + return str end + local left_indent = (' '):rep(leave_indent or 0) + -- create a pattern for the indent + indent = indent:gsub('%s', '[ \t]') + -- strip it from the first line + str = str:gsub('^'..indent, left_indent) + -- strip it from the remaining lines + str = str:gsub('[\n]'..indent, '\n' .. left_indent) + return str end return { @@ -97,4 +314,13 @@ return { check_logs = check_logs, uname = uname, tmpname = tmpname, + map = map, + filter = filter, + glob = glob, + check_cores = check_cores, + hasenv = hasenv, + which = which, + shallowcopy = shallowcopy, + concat_tables = concat_tables, + dedent = dedent, } diff --git a/test/includes/CMakeLists.txt b/test/includes/CMakeLists.txt index 3d85197f19..305d3369b7 100644 --- a/test/includes/CMakeLists.txt +++ b/test/includes/CMakeLists.txt @@ -1,5 +1,12 @@ file(GLOB_RECURSE PRE_HEADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} pre/*.h) +# We need to add the SDK directories on OS X, and perhaps other operating +# systems. +set(gen_cflags) +foreach(gen_include ${CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES}) + list(APPEND gen_cflags ${CMAKE_INCLUDE_FLAG_C}${gen_include}) +endforeach() + foreach(hfile ${PRE_HEADERS}) string(REGEX REPLACE ^pre/ post/ post_hfile ${hfile}) get_filename_component(hdir ${CMAKE_CURRENT_BINARY_DIR}/${post_hfile} PATH) @@ -8,6 +15,7 @@ foreach(hfile ${PRE_HEADERS}) OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${post_hfile} COMMAND ${CMAKE_C_COMPILER} -std=c99 -E -P ${CMAKE_CURRENT_SOURCE_DIR}/${hfile} + ${gen_cflags} -I${LIBUV_INCLUDE_DIRS} -o ${CMAKE_CURRENT_BINARY_DIR}/${post_hfile}) list(APPEND POST_HEADERS ${post_hfile}) diff --git a/test/unit/api/helpers.lua b/test/unit/api/helpers.lua index 883e1c6c19..4fb1cee4b3 100644 --- a/test/unit/api/helpers.lua +++ b/test/unit/api/helpers.lua @@ -1,4 +1,4 @@ -local helpers = require('test.unit.helpers') +local helpers = require('test.unit.helpers')(nil) local eval_helpers = require('test.unit.eval.helpers') local cimport = helpers.cimport @@ -19,47 +19,55 @@ local api = cimport('./src/nvim/api/private/defs.h', local obj2lua -local obj2lua_tab = { - [tonumber(api.kObjectTypeArray)] = function(obj) - local ret = {[type_key]=list_type} - for i = 1,tonumber(obj.data.array.size) do - ret[i] = obj2lua(obj.data.array.items[i - 1]) - end - if ret[1] then - ret[type_key] = nil - end - return ret - end, - [tonumber(api.kObjectTypeDictionary)] = function(obj) - local ret = {} - for i = 1,tonumber(obj.data.dictionary.size) do - local kv_pair = obj.data.dictionary.items[i - 1] - ret[ffi.string(kv_pair.key.data, kv_pair.key.size)] = obj2lua(kv_pair.value) - end - return ret - end, - [tonumber(api.kObjectTypeBoolean)] = function(obj) - if obj.data.boolean == false then - return false - else - return true - end - end, - [tonumber(api.kObjectTypeNil)] = function(_) - return nil_value - end, - [tonumber(api.kObjectTypeFloat)] = function(obj) - return tonumber(obj.data.floating) - end, - [tonumber(api.kObjectTypeInteger)] = function(obj) - return {[type_key]=int_type, value=tonumber(obj.data.integer)} - end, - [tonumber(api.kObjectTypeString)] = function(obj) - return ffi.string(obj.data.string.data, obj.data.string.size) - end, -} +local obj2lua_tab = nil + +local function init_obj2lua_tab() + if obj2lua_tab then + return + end + obj2lua_tab = { + [tonumber(api.kObjectTypeArray)] = function(obj) + local ret = {[type_key]=list_type} + for i = 1,tonumber(obj.data.array.size) do + ret[i] = obj2lua(obj.data.array.items[i - 1]) + end + if ret[1] then + ret[type_key] = nil + end + return ret + end, + [tonumber(api.kObjectTypeDictionary)] = function(obj) + local ret = {} + for i = 1,tonumber(obj.data.dictionary.size) do + local kv_pair = obj.data.dictionary.items[i - 1] + ret[ffi.string(kv_pair.key.data, kv_pair.key.size)] = obj2lua(kv_pair.value) + end + return ret + end, + [tonumber(api.kObjectTypeBoolean)] = function(obj) + if obj.data.boolean == false then + return false + else + return true + end + end, + [tonumber(api.kObjectTypeNil)] = function(_) + return nil_value + end, + [tonumber(api.kObjectTypeFloat)] = function(obj) + return tonumber(obj.data.floating) + end, + [tonumber(api.kObjectTypeInteger)] = function(obj) + return {[type_key]=int_type, value=tonumber(obj.data.integer)} + end, + [tonumber(api.kObjectTypeString)] = function(obj) + return ffi.string(obj.data.string.data, obj.data.string.size) + end, + } +end obj2lua = function(obj) + init_obj2lua_tab() return ((obj2lua_tab[tonumber(obj['type'])] or function(obj_inner) assert(false, 'Converting ' .. tostring(tonumber(obj_inner['type'])) .. ' is not implementing yet') end)(obj)) @@ -106,7 +114,8 @@ local lua2obj_type_tab = { api.xmalloc(len * ffi.sizeof('KeyValuePair'))), }}) for i = 1, len do - local key, val = table.unpack(kvs[i]) + local table_unpack = table.unpack or unpack -- luacheck: compat + local key, val = table_unpack(kvs[i]) dct.data.dictionary.items[i - 1] = ffi.new( 'KeyValuePair', {key=ffi.gc(lua2obj(key), nil).data.string, value=ffi.gc(lua2obj(val), nil)}) diff --git a/test/unit/api/private_helpers_spec.lua b/test/unit/api/private_helpers_spec.lua index 8c54ea6a2a..a534d83165 100644 --- a/test/unit/api/private_helpers_spec.lua +++ b/test/unit/api/private_helpers_spec.lua @@ -1,4 +1,5 @@ -local helpers = require('test.unit.helpers') +local helpers = require('test.unit.helpers')(after_each) +local itp = helpers.gen_itp(it) local eval_helpers = require('test.unit.eval.helpers') local api_helpers = require('test.unit.api.helpers') @@ -25,7 +26,7 @@ describe('vim_to_object', function() end local different_output_test = function(name, input, output) - it(name, function() + itp(name, function() eq(output, vim_to_object(input)) end) end @@ -76,19 +77,19 @@ describe('vim_to_object', function() different_output_test('outputs nil for nested lists (2 level, in dict)', lst3, {{lst=nil_value}, true, false, 'ttest'}) - it('outputs empty list for NULL list', function() + itp('outputs empty list for NULL list', function() local tt = typvalt('VAR_LIST', {v_list=NULL}) eq(nil, tt.vval.v_list) eq({[type_key]=list_type}, obj2lua(api.vim_to_object(tt))) end) - it('outputs empty dict for NULL dict', function() + itp('outputs empty dict for NULL dict', function() local tt = typvalt('VAR_DICT', {v_dict=NULL}) eq(nil, tt.vval.v_dict) eq({}, obj2lua(api.vim_to_object(tt))) end) - it('regression: partials in a list', function() + itp('regression: partials in a list', function() local llist = { { [type_key]=func_type, diff --git a/test/unit/buffer_spec.lua b/test/unit/buffer_spec.lua index 49a4d84279..f7124b2782 100644 --- a/test/unit/buffer_spec.lua +++ b/test/unit/buffer_spec.lua @@ -1,5 +1,6 @@ -local helpers = require("test.unit.helpers") +local helpers = require("test.unit.helpers")(after_each) +local itp = helpers.gen_itp(it) local to_cstr = helpers.to_cstr local get_str = helpers.ffi.string @@ -39,17 +40,17 @@ describe('buffer functions', function() describe('buf_valid', function() - it('should view NULL as an invalid buffer', function() + itp('should view NULL as an invalid buffer', function() eq(false, buffer.buf_valid(NULL)) end) - it('should view an open buffer as valid', function() + itp('should view an open buffer as valid', function() local buf = buflist_new(path1, buffer.BLN_LISTED) eq(true, buffer.buf_valid(buf)) end) - it('should view a closed and hidden buffer as valid', function() + itp('should view a closed and hidden buffer as valid', function() local buf = buflist_new(path1, buffer.BLN_LISTED) close_buffer(NULL, buf, 0, 0) @@ -57,7 +58,7 @@ describe('buffer functions', function() eq(true, buffer.buf_valid(buf)) end) - it('should view a closed and unloaded buffer as valid', function() + itp('should view a closed and unloaded buffer as valid', function() local buf = buflist_new(path1, buffer.BLN_LISTED) close_buffer(NULL, buf, buffer.DOBUF_UNLOAD, 0) @@ -65,7 +66,7 @@ describe('buffer functions', function() eq(true, buffer.buf_valid(buf)) end) - it('should view a closed and wiped buffer as invalid', function() + itp('should view a closed and wiped buffer as invalid', function() local buf = buflist_new(path1, buffer.BLN_LISTED) close_buffer(NULL, buf, buffer.DOBUF_WIPE, 0) @@ -84,7 +85,7 @@ describe('buffer functions', function() return buffer.buflist_findpat(to_cstr(pat), NULL, allow_unlisted, 0, 0) end - it('should find exact matches', function() + itp('should find exact matches', function() local buf = buflist_new(path1, buffer.BLN_LISTED) eq(buf.handle, buflist_findpat(path1, ONLY_LISTED)) @@ -92,7 +93,7 @@ describe('buffer functions', function() close_buffer(NULL, buf, buffer.DOBUF_WIPE, 0) end) - it('should prefer to match the start of a file path', function() + itp('should prefer to match the start of a file path', function() local buf1 = buflist_new(path1, buffer.BLN_LISTED) local buf2 = buflist_new(path2, buffer.BLN_LISTED) local buf3 = buflist_new(path3, buffer.BLN_LISTED) @@ -106,7 +107,7 @@ describe('buffer functions', function() close_buffer(NULL, buf3, buffer.DOBUF_WIPE, 0) end) - it('should prefer to match the end of a file over the middle', function() + itp('should prefer to match the end of a file over the middle', function() --{ Given: Two buffers, where 'test' appears in both -- And: 'test' appears at the end of buf3 but in the middle of buf2 local buf2 = buflist_new(path2, buffer.BLN_LISTED) @@ -130,7 +131,7 @@ describe('buffer functions', function() close_buffer(NULL, buf3, buffer.DOBUF_WIPE, 0) end) - it('should match a unique fragment of a file path', function() + itp('should match a unique fragment of a file path', function() local buf1 = buflist_new(path1, buffer.BLN_LISTED) local buf2 = buflist_new(path2, buffer.BLN_LISTED) local buf3 = buflist_new(path3, buffer.BLN_LISTED) @@ -142,7 +143,7 @@ describe('buffer functions', function() close_buffer(NULL, buf3, buffer.DOBUF_WIPE, 0) end) - it('should include / ignore unlisted buffers based on the flag.', function() + itp('should include / ignore unlisted buffers based on the flag.', function() --{ Given: A buffer local buf3 = buflist_new(path3, buffer.BLN_LISTED) @@ -169,7 +170,7 @@ describe('buffer functions', function() --} end) - it('should prefer listed buffers to unlisted buffers.', function() + itp('should prefer listed buffers to unlisted buffers.', function() --{ Given: Two buffers that match a pattern local buf1 = buflist_new(path1, buffer.BLN_LISTED) local buf2 = buflist_new(path2, buffer.BLN_LISTED) @@ -265,7 +266,7 @@ describe('buffer functions', function() local expected_cell_count = option.expected_cell_count or statusline_cell_count local expected_byte_length = option.expected_byte_length or expected_cell_count - it(description, function() + itp(description, function() if option.file_name then buffer.setfname(globals.curbuf, to_cstr(option.file_name), NULL, 1) else diff --git a/test/unit/eval/decode_spec.lua b/test/unit/eval/decode_spec.lua index 742b754d8a..0c444b33f2 100644 --- a/test/unit/eval/decode_spec.lua +++ b/test/unit/eval/decode_spec.lua @@ -1,35 +1,21 @@ -local helpers = require('test.unit.helpers') +local helpers = require('test.unit.helpers')(after_each) +local itp = helpers.gen_itp(it) local cimport = helpers.cimport -local to_cstr = helpers.to_cstr local eq = helpers.eq local neq = helpers.neq local ffi = helpers.ffi -local decode = cimport('./src/nvim/eval/decode.h', './src/nvim/eval_defs.h', +local decode = cimport('./src/nvim/eval/decode.h', './src/nvim/eval/typval.h', './src/nvim/globals.h', './src/nvim/memory.h', './src/nvim/message.h') describe('json_decode_string()', function() - local saved_p_enc = nil - - before_each(function() - saved_p_enc = decode.p_enc - end) - - after_each(function() - decode.emsg_silent = 0 - decode.p_enc = saved_p_enc - while decode.delete_first_msg() == 1 do - -- Delete all messages - end - end) - local char = function(c) return ffi.gc(decode.xmemdup(c, 1), decode.xfree) end - it('does not overflow when running with `nโฆ`, `tโฆ`, `fโฆ`', function() + itp('does not overflow when running with `nโฆ`, `tโฆ`, `fโฆ`', function() local rettv = ffi.new('typval_T', {v_type=decode.VAR_UNKNOWN}) decode.emsg_silent = 1 -- This will not crash, but if `len` argument will be ignored it will parse @@ -56,7 +42,7 @@ describe('json_decode_string()', function() eq(decode.VAR_UNKNOWN, rettv.v_type) end) - it('does not overflow and crash when running with `n`, `t`, `f`', function() + itp('does not overflow and crash when running with `n`, `t`, `f`', function() local rettv = ffi.new('typval_T', {v_type=decode.VAR_UNKNOWN}) decode.emsg_silent = 1 eq(0, decode.json_decode_string(char('n'), 1, rettv)) @@ -67,7 +53,7 @@ describe('json_decode_string()', function() eq(decode.VAR_UNKNOWN, rettv.v_type) end) - it('does not overflow when running with `"โฆ`', function() + itp('does not overflow when running with `"โฆ`', function() local rettv = ffi.new('typval_T', {v_type=decode.VAR_UNKNOWN}) decode.emsg_silent = 1 eq(0, decode.json_decode_string('"t"', 2, rettv)) @@ -84,7 +70,8 @@ describe('json_decode_string()', function() eq(msg, ffi.string(decode.last_msg_hist.msg)) end - it('does not overflow in error messages', function() + itp('does not overflow in error messages', function() + collectgarbage('restart') check_failure(']test', 1, 'E474: No container to close: ]') check_failure('[}test', 2, 'E474: Closing list with curly bracket: }') check_failure('{]test', 2, @@ -117,10 +104,6 @@ describe('json_decode_string()', function() check_failure('"\194"test', 3, 'E474: Only UTF-8 strings allowed: \194"') check_failure('"\252\144\128\128\128\128"test', 8, 'E474: Only UTF-8 code points up to U+10FFFF are allowed to appear unescaped: \252\144\128\128\128\128"') check_failure('"test', 1, 'E474: Expected string end: "') - decode.p_enc = to_cstr('latin1') - check_failure('"\\uABCD"test', 8, - 'E474: Failed to convert string "๊ฏ" from UTF-8') - decode.p_enc = saved_p_enc check_failure('-test', 1, 'E474: Missing number after minus sign: -') check_failure('-1.test', 3, 'E474: Missing number after decimal dot: -1.') check_failure('-1.0etest', 5, 'E474: Missing exponent: -1.0e') @@ -129,11 +112,11 @@ describe('json_decode_string()', function() check_failure('[1test', 2, 'E474: Unexpected end of input: [1') end) - it('does not overflow with `-`', function() + itp('does not overflow with `-`', function() check_failure('-0', 1, 'E474: Missing number after minus sign: -') end) - it('does not overflow and crash when running with `"`', function() + itp('does not overflow and crash when running with `"`', function() local rettv = ffi.new('typval_T', {v_type=decode.VAR_UNKNOWN}) decode.emsg_silent = 1 eq(0, decode.json_decode_string(char('"'), 1, rettv)) diff --git a/test/unit/eval/encode_spec.lua b/test/unit/eval/encode_spec.lua index 98fc8305e0..058c55093e 100644 --- a/test/unit/eval/encode_spec.lua +++ b/test/unit/eval/encode_spec.lua @@ -1,4 +1,5 @@ -local helpers = require('test.unit.helpers') +local helpers = require('test.unit.helpers')(after_each) +local itp = helpers.gen_itp(it) local eval_helpers = require('test.unit.eval.helpers') local cimport = helpers.cimport @@ -18,25 +19,25 @@ describe('encode_list_write()', function() return encode.encode_list_write(l, to_cstr(s), #s) end - it('writes empty string', function() + itp('writes empty string', function() local l = list() eq(0, encode_list_write(l, '')) eq({[type_key]=list_type}, lst2tbl(l)) end) - it('writes ASCII string literal with printable characters', function() + itp('writes ASCII string literal with printable characters', function() local l = list() eq(0, encode_list_write(l, 'abc')) eq({'abc'}, lst2tbl(l)) end) - it('writes string starting with NL', function() + itp('writes string starting with NL', function() local l = list() eq(0, encode_list_write(l, '\nabc')) eq({null_string, 'abc'}, lst2tbl(l)) end) - it('writes string starting with NL twice', function() + itp('writes string starting with NL twice', function() local l = list() eq(0, encode_list_write(l, '\nabc')) eq({null_string, 'abc'}, lst2tbl(l)) @@ -44,13 +45,13 @@ describe('encode_list_write()', function() eq({null_string, 'abc', 'abc'}, lst2tbl(l)) end) - it('writes string ending with NL', function() + itp('writes string ending with NL', function() local l = list() eq(0, encode_list_write(l, 'abc\n')) eq({'abc', null_string}, lst2tbl(l)) end) - it('writes string ending with NL twice', function() + itp('writes string ending with NL twice', function() local l = list() eq(0, encode_list_write(l, 'abc\n')) eq({'abc', null_string}, lst2tbl(l)) @@ -58,7 +59,7 @@ describe('encode_list_write()', function() eq({'abc', 'abc', null_string}, lst2tbl(l)) end) - it('writes string starting, ending and containing NL twice', function() + itp('writes string starting, ending and containing NL twice', function() local l = list() eq(0, encode_list_write(l, '\na\nb\n')) eq({null_string, 'a', 'b', null_string}, lst2tbl(l)) @@ -66,7 +67,7 @@ describe('encode_list_write()', function() eq({null_string, 'a', 'b', null_string, 'a', 'b', null_string}, lst2tbl(l)) end) - it('writes string starting, ending and containing NUL with NL between twice', function() + itp('writes string starting, ending and containing NUL with NL between twice', function() local l = list() eq(0, encode_list_write(l, '\0\n\0\n\0')) eq({'\n', '\n', '\n'}, lst2tbl(l)) @@ -74,7 +75,7 @@ describe('encode_list_write()', function() eq({'\n', '\n', '\n\n', '\n', '\n'}, lst2tbl(l)) end) - it('writes string starting, ending and containing NL with NUL between twice', function() + itp('writes string starting, ending and containing NL with NUL between twice', function() local l = list() eq(0, encode_list_write(l, '\n\0\n\0\n')) eq({null_string, '\n', '\n', null_string}, lst2tbl(l)) @@ -82,7 +83,7 @@ describe('encode_list_write()', function() eq({null_string, '\n', '\n', null_string, '\n', '\n', null_string}, lst2tbl(l)) end) - it('writes string containing a single NL twice', function() + itp('writes string containing a single NL twice', function() local l = list() eq(0, encode_list_write(l, '\n')) eq({null_string, null_string}, lst2tbl(l)) @@ -90,7 +91,7 @@ describe('encode_list_write()', function() eq({null_string, null_string, null_string}, lst2tbl(l)) end) - it('writes string containing a few NLs twice', function() + itp('writes string containing a few NLs twice', function() local l = list() eq(0, encode_list_write(l, '\n\n\n')) eq({null_string, null_string, null_string, null_string}, lst2tbl(l)) diff --git a/test/unit/eval/helpers.lua b/test/unit/eval/helpers.lua index c3c27e4fed..5bc482216e 100644 --- a/test/unit/eval/helpers.lua +++ b/test/unit/eval/helpers.lua @@ -1,17 +1,18 @@ -local helpers = require('test.unit.helpers') +local helpers = require('test.unit.helpers')(nil) local cimport = helpers.cimport local to_cstr = helpers.to_cstr local ffi = helpers.ffi local eq = helpers.eq -local eval = cimport('./src/nvim/eval.h', './src/nvim/eval_defs.h', +local eval = cimport('./src/nvim/eval.h', './src/nvim/eval/typval.h', './src/nvim/hashtab.h') local null_string = {[true]='NULL string'} local null_list = {[true]='NULL list'} local null_dict = {[true]='NULL dict'} local type_key = {[true]='type key'} +local locks_key = {[true]='locks key'} local list_type = {[true]='list type'} local dict_type = {[true]='dict type'} local func_type = {[true]='func type'} @@ -23,34 +24,72 @@ local nil_value = {[true]='nil'} local lua2typvalt local function li_alloc(nogc) - local gcfunc = eval.listitem_free + local gcfunc = eval.tv_list_item_free if nogc then gcfunc = nil end - local li = ffi.gc(eval.listitem_alloc(), gcfunc) + local li = ffi.gc(eval.tv_list_item_alloc(), gcfunc) li.li_next = nil li.li_prev = nil li.li_tv = {v_type=eval.VAR_UNKNOWN, v_lock=eval.VAR_UNLOCKED} return li end -local function list(...) - local ret = ffi.gc(eval.list_alloc(), eval.list_unref) - eq(0, ret.lv_refcount) - ret.lv_refcount = 1 - for i = 1, select('#', ...) do - local val = select(i, ...) - local li_tv = ffi.gc(lua2typvalt(val), nil) - local li = li_alloc(true) - li.li_tv = li_tv - eval.tv_list_append(ret, li) +local function populate_list(l, lua_l, processed) + processed = processed or {} + eq(0, l.lv_refcount) + l.lv_refcount = 1 + processed[lua_l] = l + for i = 1, #lua_l do + local item_tv = ffi.gc(lua2typvalt(lua_l[i], processed), nil) + local item_li = eval.tv_list_item_alloc() + item_li.li_tv = item_tv + eval.tv_list_append(l, item_li) end - return ret + return l end -local special_tab = { - [eval.kSpecialVarFalse] = false, - [eval.kSpecialVarNull] = nil_value, - [eval.kSpecialVarTrue] = true, -} +local function populate_dict(d, lua_d, processed) + processed = processed or {} + eq(0, d.dv_refcount) + d.dv_refcount = 1 + processed[lua_d] = d + for k, v in pairs(lua_d) do + if type(k) == 'string' then + local di = eval.tv_dict_item_alloc(to_cstr(k)) + local val_tv = ffi.gc(lua2typvalt(v, processed), nil) + eval.tv_copy(val_tv, di.di_tv) + eval.tv_clear(val_tv) + eval.tv_dict_add(d, di) + end + end + return d +end + +local function populate_partial(pt, lua_pt, processed) + processed = processed or {} + eq(0, pt.pt_refcount) + processed[lua_pt] = pt + local argv = nil + if lua_pt.args and #lua_pt.args > 0 then + argv = ffi.gc(ffi.cast('typval_T*', eval.xmalloc(ffi.sizeof('typval_T') * #lua_pt.args)), nil) + for i, arg in ipairs(lua_pt.args) do + local arg_tv = ffi.gc(lua2typvalt(arg, processed), nil) + argv[i - 1] = arg_tv + end + end + local dict = nil + if lua_pt.dict then + local dict_tv = ffi.gc(lua2typvalt(lua_pt.dict, processed), nil) + assert(dict_tv.v_type == eval.VAR_DICT) + dict = dict_tv.vval.v_dict + end + pt.pt_refcount = 1 + pt.pt_name = eval.xmemdupz(to_cstr(lua_pt.value), #lua_pt.value) + pt.pt_auto = not not lua_pt.auto + pt.pt_argc = lua_pt.args and #lua_pt.args or 0 + pt.pt_argv = argv + pt.pt_dict = dict + return pt +end local ptr2key = function(ptr) return tostring(ptr) @@ -60,64 +99,79 @@ local lst2tbl local dct2tbl local typvalt2lua -local typvalt2lua_tab -typvalt2lua_tab = { - [tonumber(eval.VAR_SPECIAL)] = function(t) - return special_tab[t.vval.v_special] - end, - [tonumber(eval.VAR_NUMBER)] = function(t) - return {[type_key]=int_type, value=tonumber(t.vval.v_number)} - end, - [tonumber(eval.VAR_FLOAT)] = function(t) - return tonumber(t.vval.v_float) - end, - [tonumber(eval.VAR_STRING)] = function(t) - local str = t.vval.v_string - if str == nil then - return null_string - else - return ffi.string(str) +local function partial2lua(pt, processed) + processed = processed or {} + local value, auto, dict, argv = nil, nil, nil, nil + if pt ~= nil then + value = ffi.string(pt.pt_name) + auto = pt.pt_auto and true or nil + argv = {} + for i = 1, pt.pt_argc do + argv[i] = typvalt2lua(pt.pt_argv[i - 1], processed) end - end, - [tonumber(eval.VAR_LIST)] = function(t, processed) - return lst2tbl(t.vval.v_list, processed) - end, - [tonumber(eval.VAR_DICT)] = function(t, processed) - return dct2tbl(t.vval.v_dict, processed) - end, - [tonumber(eval.VAR_FUNC)] = function(t, processed) - return {[type_key]=func_type, value=typvalt2lua_tab[eval.VAR_STRING](t, processed or {})} - end, - [tonumber(eval.VAR_PARTIAL)] = function(t, processed) - local p_key = ptr2key(t) - if processed[p_key] then - return processed[p_key] + if pt.pt_dict ~= nil then + dict = dct2tbl(pt.pt_dict) end - local pt = t.vval.v_partial - local value, auto, dict, argv = nil, nil, nil, nil - if pt ~= nil then - value = ffi.string(pt.pt_name) - auto = pt.pt_auto and true or nil - argv = {} - for i = 1, pt.pt_argc do - argv[i] = typvalt2lua(pt.pt_argv[i - 1], processed) + end + return { + [type_key]=func_type, + value=value, + auto=auto, + args=argv, + dict=dict, + } +end + +local typvalt2lua_tab = nil + +local function typvalt2lua_tab_init() + if typvalt2lua_tab then + return + end + typvalt2lua_tab = { + [tonumber(eval.VAR_SPECIAL)] = function(t) + return ({ + [tonumber(eval.kSpecialVarFalse)] = false, + [tonumber(eval.kSpecialVarNull)] = nil_value, + [tonumber(eval.kSpecialVarTrue)] = true, + })[tonumber(t.vval.v_special)] + end, + [tonumber(eval.VAR_NUMBER)] = function(t) + return {[type_key]=int_type, value=tonumber(t.vval.v_number)} + end, + [tonumber(eval.VAR_FLOAT)] = function(t) + return tonumber(t.vval.v_float) + end, + [tonumber(eval.VAR_STRING)] = function(t) + local str = t.vval.v_string + if str == nil then + return null_string + else + return ffi.string(str) end - if pt.pt_dict ~= nil then - dict = dct2tbl(pt.pt_dict) + end, + [tonumber(eval.VAR_LIST)] = function(t, processed) + return lst2tbl(t.vval.v_list, processed) + end, + [tonumber(eval.VAR_DICT)] = function(t, processed) + return dct2tbl(t.vval.v_dict, processed) + end, + [tonumber(eval.VAR_FUNC)] = function(t, processed) + return {[type_key]=func_type, value=typvalt2lua_tab[eval.VAR_STRING](t, processed or {})} + end, + [tonumber(eval.VAR_PARTIAL)] = function(t, processed) + local p_key = ptr2key(t) + if processed[p_key] then + return processed[p_key] end - end - return { - [type_key]=func_type, - value=value, - auto=auto, - args=argv, - dict=dict, - } - end, -} + return partial2lua(t.vval.v_partial, processed) + end, + } +end typvalt2lua = function(t, processed) + typvalt2lua_tab_init() return ((typvalt2lua_tab[tonumber(t.v_type)] or function(t_inner) assert(false, 'Converting ' .. tonumber(t_inner.v_type) .. ' was not implemented yet') end)(t, processed or {})) @@ -169,9 +223,10 @@ lst2tbl = function(l, processed) return ret end -local hi_key_removed = eval._hash_key_removed() +local hi_key_removed = nil local function dict_iter(d, return_hi) + hi_key_removed = hi_key_removed or eval._hash_key_removed() local init_s = { todo=d.dv_hashtab.ht_used, hi=d.dv_hashtab.ht_array, @@ -236,7 +291,7 @@ local typvalt = function(typ, vval) elseif type(typ) == 'string' then typ = eval[typ] end - return ffi.gc(ffi.new('typval_T', {v_type=typ, vval=vval}), eval.clear_tv) + return ffi.gc(ffi.new('typval_T', {v_type=typ, vval=vval}), eval.tv_clear) end local lua2typvalt_type_tab = { @@ -251,36 +306,16 @@ local lua2typvalt_type_tab = { processed[l].lv_refcount = processed[l].lv_refcount + 1 return typvalt(eval.VAR_LIST, {v_list=processed[l]}) end - local lst = eval.list_alloc() - lst.lv_refcount = 1 - processed[l] = lst - local ret = typvalt(eval.VAR_LIST, {v_list=lst}) - for i = 1, #l do - local item_tv = ffi.gc(lua2typvalt(l[i], processed), nil) - eval.list_append_tv(lst, item_tv) - eval.clear_tv(item_tv) - end - return ret + local lst = populate_list(eval.tv_list_alloc(), l, processed) + return typvalt(eval.VAR_LIST, {v_list=lst}) end, [dict_type] = function(l, processed) if processed[l] then processed[l].dv_refcount = processed[l].dv_refcount + 1 return typvalt(eval.VAR_DICT, {v_dict=processed[l]}) end - local dct = eval.dict_alloc() - dct.dv_refcount = 1 - processed[l] = dct - local ret = typvalt(eval.VAR_DICT, {v_dict=dct}) - for k, v in pairs(l) do - if type(k) == 'string' then - local di = eval.dictitem_alloc(to_cstr(k)) - local val_tv = ffi.gc(lua2typvalt(v, processed), nil) - eval.copy_tv(val_tv, di.di_tv) - eval.clear_tv(val_tv) - eval.dict_add(dct, di) - end - end - return ret + local dct = populate_dict(eval.tv_dict_alloc(), l, processed) + return typvalt(eval.VAR_DICT, {v_dict=dct}) end, [func_type] = function(l, processed) if processed[l] then @@ -288,29 +323,8 @@ local lua2typvalt_type_tab = { return typvalt(eval.VAR_PARTIAL, {v_partial=processed[l]}) end if l.args or l.dict then - local pt = ffi.gc(ffi.cast('partial_T*', eval.xmalloc(ffi.sizeof('partial_T'))), nil) - processed[l] = pt - local argv = nil - if l.args and #l.args > 0 then - argv = ffi.gc(ffi.cast('typval_T*', eval.xmalloc(ffi.sizeof('typval_T') * #l.args)), nil) - for i, arg in ipairs(l.args) do - local arg_tv = ffi.gc(lua2typvalt(arg, processed), nil) - eval.copy_tv(arg_tv, argv[i - 1]) - eval.clear_tv(arg_tv) - end - end - local dict = nil - if l.dict then - local dict_tv = ffi.gc(lua2typvalt(l.dict, processed), nil) - assert(dict_tv.v_type == eval.VAR_DICT) - dict = dict_tv.vval.v_dict - end - pt.pt_refcount = 1 - pt.pt_name = eval.xmemdupz(to_cstr(l.value), #l.value) - pt.pt_auto = not not l.auto - pt.pt_argc = l.args and #l.args or 0 - pt.pt_argv = argv - pt.pt_dict = dict + local pt = populate_partial(ffi.gc(ffi.cast('partial_T*', + eval.xcalloc(1, ffi.sizeof('partial_T'))), nil), l, processed) return typvalt(eval.VAR_PARTIAL, {v_partial=pt}) else return typvalt(eval.VAR_FUNC, { @@ -320,25 +334,28 @@ local lua2typvalt_type_tab = { end, } -local special_vals = { - [null_string] = {eval.VAR_STRING, {v_string=ffi.cast('char_u*', nil)}}, - [null_list] = {eval.VAR_LIST, {v_list=ffi.cast('list_T*', nil)}}, - [null_dict] = {eval.VAR_DICT, {v_dict=ffi.cast('dict_T*', nil)}}, - [nil_value] = {eval.VAR_SPECIAL, {v_special=eval.kSpecialVarNull}}, - [true] = {eval.VAR_SPECIAL, {v_special=eval.kSpecialVarTrue}}, - [false] = {eval.VAR_SPECIAL, {v_special=eval.kSpecialVarFalse}}, -} +local special_vals = nil -for k, v in pairs(special_vals) do - local tmp = function(typ, vval) - special_vals[k] = function() - return typvalt(typ, vval) +lua2typvalt = function(l, processed) + if not special_vals then + special_vals = { + [null_string] = {'VAR_STRING', {v_string=ffi.cast('char_u*', nil)}}, + [null_list] = {'VAR_LIST', {v_list=ffi.cast('list_T*', nil)}}, + [null_dict] = {'VAR_DICT', {v_dict=ffi.cast('dict_T*', nil)}}, + [nil_value] = {'VAR_SPECIAL', {v_special=eval.kSpecialVarNull}}, + [true] = {'VAR_SPECIAL', {v_special=eval.kSpecialVarTrue}}, + [false] = {'VAR_SPECIAL', {v_special=eval.kSpecialVarFalse}}, + } + + for k, v in pairs(special_vals) do + local tmp = function(typ, vval) + special_vals[k] = function() + return typvalt(eval[typ], vval) + end + end + tmp(v[1], v[2]) end end - tmp(v[1], v[2]) -end - -lua2typvalt = function(l, processed) processed = processed or {} if l == nil or l == nil_value then return special_vals[nil_value]() @@ -365,8 +382,19 @@ lua2typvalt = function(l, processed) end end +local void_ptr = ffi.typeof('void *') local function void(ptr) - return ffi.cast('void*', ptr) + return ffi.cast(void_ptr, ptr) +end + +local function alloc_len(len, get_ptr) + if type(len) == 'string' or type(len) == 'table' then + return #len + elseif len == nil then + return eval.strlen(get_ptr()) + else + return len + end end local alloc_logging_helpers = { @@ -374,14 +402,115 @@ local alloc_logging_helpers = { li = function(li) return {func='malloc', args={ffi.sizeof('listitem_T')}, ret=void(li)} end, dict = function(d) return {func='malloc', args={ffi.sizeof('dict_T')}, ret=void(d)} end, di = function(di, size) + size = alloc_len(size, function() return di.di_key end) return {func='malloc', args={ffi.offsetof('dictitem_T', 'di_key') + size + 1}, ret=void(di)} end, - str = function(s, size) return {func='malloc', args={size + 1}, ret=void(s)} end, + str = function(s, size) + size = alloc_len(size, function() return s end) + return {func='malloc', args={size + 1}, ret=void(s)} + end, + + dwatcher = function(w) return {func='malloc', args={ffi.sizeof('DictWatcher')}, ret=void(w)} end, - freed = function(p) return {func='free', args={p and void(p)}} end, + freed = function(p) return {func='free', args={type(p) == 'table' and p or void(p)}} end, + + -- lua_โฆ: allocated by this file, not by some Neovim function + lua_pt = function(pt) return {func='calloc', args={1, ffi.sizeof('partial_T')}, ret=void(pt)} end, + lua_tvs = function(argv, argc) + argc = alloc_len(argc) + return {func='malloc', args={ffi.sizeof('typval_T')*argc}, ret=void(argv)} + end, } +local function int(n) + return {[type_key]=int_type, value=n} +end + +local function list(...) + return populate_list(ffi.gc(eval.tv_list_alloc(), eval.tv_list_unref), + {...}, {}) +end + +local function dict(d) + return populate_dict(ffi.gc(eval.tv_dict_alloc(), eval.tv_dict_free), + d or {}, {}) +end + +local callback2tbl_type_tab = nil + +local function init_callback2tbl_type_tab() + if callback2tbl_type_tab then + return + end + callback2tbl_type_tab = { + [tonumber(eval.kCallbackNone)] = function(_) return {type='none'} end, + [tonumber(eval.kCallbackFuncref)] = function(cb) + return {type='fref', fref=ffi.string(cb.data.funcref)} + end, + [tonumber(eval.kCallbackPartial)] = function(cb) + local lua_pt = partial2lua(cb.data.partial) + return {type='pt', fref=ffi.string(lua_pt.value), pt=lua_pt} + end + } +end + +local function callback2tbl(cb) + init_callback2tbl_type_tab() + return callback2tbl_type_tab[tonumber(cb.type)](cb) +end + +local function tbl2callback(tbl) + local ret = nil + if tbl.type == 'none' then + ret = ffi.new('Callback[1]', {{type=eval.kCallbackNone}}) + elseif tbl.type == 'fref' then + ret = ffi.new('Callback[1]', {{type=eval.kCallbackFuncref, + data={funcref=eval.xstrdup(tbl.fref)}}}) + elseif tbl.type == 'pt' then + local pt = ffi.gc(ffi.cast('partial_T*', + eval.xcalloc(1, ffi.sizeof('partial_T'))), nil) + ret = ffi.new('Callback[1]', {{type=eval.kCallbackPartial, + data={partial=populate_partial(pt, tbl.pt, {})}}}) + else + assert(false) + end + return ffi.gc(ffi.cast('Callback*', ret), helpers.callback_free) +end + +local function dict_watchers(d) + local ret = {} + local h = d.watchers + local q = h.next + local qs = {} + local key_patterns = {} + while q ~= h do + local qitem = ffi.cast('DictWatcher *', + ffi.cast('char *', q) - ffi.offsetof('DictWatcher', 'node')) + ret[#ret + 1] = { + cb=callback2tbl(qitem.callback), + pat=ffi.string(qitem.key_pattern, qitem.key_pattern_len), + busy=qitem.busy, + } + qs[#qs + 1] = qitem + key_patterns[#key_patterns + 1] = {qitem.key_pattern, qitem.key_pattern_len} + q = q.next + end + return ret, qs, key_patterns +end + +local function eval0(expr) + local tv = ffi.gc(ffi.new('typval_T', {v_type=eval.VAR_UNKNOWN}), + eval.tv_clear) + if eval.eval0(to_cstr(expr), tv, nil, true) == 0 then + return nil + else + return tv + end +end + return { + int=int, + null_string=null_string, null_list=null_list, null_dict=null_dict, @@ -394,8 +523,10 @@ return { nil_value=nil_value, type_key=type_key, + locks_key=locks_key, list=list, + dict=dict, lst2tbl=lst2tbl, dct2tbl=dct2tbl, @@ -414,4 +545,12 @@ return { list_items=list_items, dict_items=dict_items, + + dict_watchers=dict_watchers, + tbl2callback=tbl2callback, + callback2tbl=callback2tbl, + + eval0=eval0, + + empty_list = {[type_key]=list_type}, } diff --git a/test/unit/eval/tricks_spec.lua b/test/unit/eval/tricks_spec.lua index 4c5184995c..7aa0f0f6e6 100644 --- a/test/unit/eval/tricks_spec.lua +++ b/test/unit/eval/tricks_spec.lua @@ -1,21 +1,18 @@ -local helpers = require('test.unit.helpers') +local helpers = require('test.unit.helpers')(after_each) +local eval_helpers = require('test.unit.eval.helpers') + +local itp = helpers.gen_itp(it) local cimport = helpers.cimport -local to_cstr = helpers.to_cstr -local ffi = helpers.ffi local eq = helpers.eq -local eval = cimport('./src/nvim/eval.h', './src/nvim/memory.h') +local eval0 = eval_helpers.eval0 -local eval_expr = function(expr) - return ffi.gc(eval.eval_expr(to_cstr(expr), nil), function(tv) - eval.clear_tv(tv) - eval.xfree(tv) - end) -end +local eval = cimport('./src/nvim/eval.h', './src/nvim/eval/typval.h', + './src/nvim/memory.h') describe('NULL typval_T', function() - it('is produced by $XXX_UNEXISTENT_VAR_XXX', function() + itp('is produced by $XXX_UNEXISTENT_VAR_XXX', function() -- Required for various tests which need to check whether typval_T with NULL -- string works correctly. This test checks that unexistent environment -- variable produces NULL string, not that some specific environment @@ -24,19 +21,19 @@ describe('NULL typval_T', function() while os.getenv(unexistent_env) ~= nil do unexistent_env = unexistent_env .. '_XXX' end - local rettv = eval_expr('$' .. unexistent_env) + local rettv = eval0('$' .. unexistent_env) eq(eval.VAR_STRING, rettv.v_type) eq(nil, rettv.vval.v_string) end) - it('is produced by v:_null_list', function() - local rettv = eval_expr('v:_null_list') + itp('is produced by v:_null_list', function() + local rettv = eval0('v:_null_list') eq(eval.VAR_LIST, rettv.v_type) eq(nil, rettv.vval.v_list) end) - it('is produced by v:_null_dict', function() - local rettv = eval_expr('v:_null_dict') + itp('is produced by v:_null_dict', function() + local rettv = eval0('v:_null_dict') eq(eval.VAR_DICT, rettv.v_type) eq(nil, rettv.vval.v_dict) end) diff --git a/test/unit/eval/tv_clear_spec.lua b/test/unit/eval/tv_clear_spec.lua index 96eccdbd71..ca37301b32 100644 --- a/test/unit/eval/tv_clear_spec.lua +++ b/test/unit/eval/tv_clear_spec.lua @@ -1,4 +1,5 @@ -local helpers = require('test.unit.helpers') +local helpers = require('test.unit.helpers')(after_each) +local itp = helpers.gen_itp(it) local eval_helpers = require('test.unit.eval.helpers') local alloc_log_new = helpers.alloc_log_new @@ -13,7 +14,7 @@ local list_items = eval_helpers.list_items local dict_items = eval_helpers.dict_items local lua2typvalt = eval_helpers.lua2typvalt -local lib = cimport('./src/nvim/eval_defs.h', './src/nvim/eval.h') +local lib = cimport('./src/nvim/eval/typval.h', './src/nvim/eval.h') local alloc_log = alloc_log_new() @@ -25,8 +26,8 @@ after_each(function() alloc_log:after_each() end) -describe('clear_tv()', function() - it('successfully frees all lists in [&l [1], *l, *l]', function() +describe('tv_clear()', function() + itp('successfully frees all lists in [&l [1], *l, *l]', function() local l_inner = {1} local list = {l_inner, l_inner, l_inner} local list_tv = ffi.gc(lua2typvalt(list), nil) @@ -43,7 +44,7 @@ describe('clear_tv()', function() a.li(lis[3]), }) eq(3, list_inner_p.lv_refcount) - lib.clear_tv(list_tv) + lib.tv_clear(list_tv) alloc_log:check({ a.freed(lis_inner[1]), a.freed(list_inner_p), @@ -53,7 +54,7 @@ describe('clear_tv()', function() a.freed(list_p), }) end) - it('successfully frees all lists in [&l [], *l, *l]', function() + itp('successfully frees all lists in [&l [], *l, *l]', function() local l_inner = {[type_key]=list_type} local list = {l_inner, l_inner, l_inner} local list_tv = ffi.gc(lua2typvalt(list), nil) @@ -68,7 +69,7 @@ describe('clear_tv()', function() a.li(lis[3]), }) eq(3, list_inner_p.lv_refcount) - lib.clear_tv(list_tv) + lib.tv_clear(list_tv) alloc_log:check({ a.freed(list_inner_p), a.freed(lis[1]), @@ -77,7 +78,7 @@ describe('clear_tv()', function() a.freed(list_p), }) end) - it('successfully frees all dictionaries in [&d {}, *d]', function() + itp('successfully frees all dictionaries in [&d {}, *d]', function() local d_inner = {} local list = {d_inner, d_inner} local list_tv = ffi.gc(lua2typvalt(list), nil) @@ -91,7 +92,7 @@ describe('clear_tv()', function() a.li(lis[2]), }) eq(2, dict_inner_p.dv_refcount) - lib.clear_tv(list_tv) + lib.tv_clear(list_tv) alloc_log:check({ a.freed(dict_inner_p), a.freed(lis[1]), @@ -99,7 +100,7 @@ describe('clear_tv()', function() a.freed(list_p), }) end) - it('successfully frees all dictionaries in [&d {a: 1}, *d]', function() + itp('successfully frees all dictionaries in [&d {a: 1}, *d]', function() local d_inner = {a=1} local list = {d_inner, d_inner} local list_tv = ffi.gc(lua2typvalt(list), nil) @@ -115,7 +116,7 @@ describe('clear_tv()', function() a.li(lis[2]), }) eq(2, dict_inner_p.dv_refcount) - lib.clear_tv(list_tv) + lib.tv_clear(list_tv) alloc_log:check({ a.freed(dis.a), a.freed(dict_inner_p), diff --git a/test/unit/eval/typval_spec.lua b/test/unit/eval/typval_spec.lua new file mode 100644 index 0000000000..bec74f05fc --- /dev/null +++ b/test/unit/eval/typval_spec.lua @@ -0,0 +1,3049 @@ +local bit = require('bit') +local helpers = require('test.unit.helpers')(after_each) +local eval_helpers = require('test.unit.eval.helpers') +local global_helpers = require('test.helpers') + +local itp = helpers.gen_itp(it) + +local OK = helpers.OK +local eq = helpers.eq +local neq = helpers.neq +local ffi = helpers.ffi +local FAIL = helpers.FAIL +local NULL = helpers.NULL +local cimport = helpers.cimport +local to_cstr = helpers.to_cstr +local alloc_log_new = helpers.alloc_log_new + +local a = eval_helpers.alloc_logging_helpers +local int = eval_helpers.int +local list = eval_helpers.list +local dict = eval_helpers.dict +local eval0 = eval_helpers.eval0 +local lst2tbl = eval_helpers.lst2tbl +local dct2tbl = eval_helpers.dct2tbl +local typvalt = eval_helpers.typvalt +local type_key = eval_helpers.type_key +local li_alloc = eval_helpers.li_alloc +local first_di = eval_helpers.first_di +local nil_value = eval_helpers.nil_value +local func_type = eval_helpers.func_type +local null_list = eval_helpers.null_list +local null_dict = eval_helpers.null_dict +local dict_items = eval_helpers.dict_items +local list_items = eval_helpers.list_items +local empty_list = eval_helpers.empty_list +local lua2typvalt = eval_helpers.lua2typvalt +local typvalt2lua = eval_helpers.typvalt2lua +local null_string = eval_helpers.null_string +local callback2tbl = eval_helpers.callback2tbl +local tbl2callback = eval_helpers.tbl2callback +local dict_watchers = eval_helpers.dict_watchers + +local concat_tables = global_helpers.concat_tables + +local lib = cimport('./src/nvim/eval/typval.h', './src/nvim/memory.h', + './src/nvim/mbyte.h', './src/nvim/garray.h', + './src/nvim/eval.h', './src/nvim/vim.h', + './src/nvim/globals.h') + +local function vimconv_alloc() + return ffi.gc( + ffi.cast('vimconv_T*', lib.xcalloc(1, ffi.sizeof('vimconv_T'))), + function(vc) + lib.convert_setup(vc, nil, nil) + lib.xfree(vc) + end) +end + +local function list_watch_alloc(li) + return ffi.cast('listwatch_T*', ffi.new('listwatch_T[1]', {{lw_item=li}})) +end + +local function list_watch(l, li) + local lw = list_watch_alloc(li or l.lv_first) + lib.tv_list_watch_add(l, lw) + return lw +end + +local function get_alloc_rets(exp_log, res) + setmetatable(res, { + __index={ + freed=function(r, n) return {func='free', args={r[n]}} end + } + }) + for i = 1,#exp_log do + if ({malloc=true, calloc=true})[exp_log[i].func] then + res[#res + 1] = exp_log[i].ret + end + end + return exp_log +end + +local to_cstr_nofree = function(v) return lib.xstrdup(v) end + +local alloc_log = alloc_log_new() + +before_each(function() + alloc_log:before_each() +end) + +after_each(function() + alloc_log:after_each() +end) + +local function ga_alloc(itemsize, growsize) + local ga = ffi.gc(ffi.cast('garray_T*', ffi.new('garray_T[1]', {})), + lib.ga_clear) + lib.ga_init(ga, itemsize or 1, growsize or 80) + return ga +end + +local function check_emsg(f, msg) + local saved_last_msg_hist = lib.last_msg_hist + if saved_last_msg_hist == nil then + saved_last_msg_hist = nil + end + local ret = {f()} + if msg ~= nil then + eq(msg, ffi.string(lib.last_msg_hist.msg)) + neq(saved_last_msg_hist, lib.last_msg_hist) + else + if saved_last_msg_hist ~= lib.last_msg_hist then + eq(nil, ffi.string(lib.last_msg_hist.msg)) + else + eq(saved_last_msg_hist, lib.last_msg_hist) + end + end + return unpack(ret) +end + +describe('typval.c', function() + describe('list', function() + describe('item', function() + describe('alloc()/free()', function() + itp('works', function() + local li = li_alloc(true) + neq(nil, li) + lib.tv_list_item_free(li) + alloc_log:check({ + a.li(li), + a.freed(li), + }) + end) + itp('also frees the value', function() + local li + local s + local l + local tv + li = li_alloc(true) + li.li_tv.v_type = lib.VAR_NUMBER + li.li_tv.vval.v_number = 10 + lib.tv_list_item_free(li) + alloc_log:check({ + a.li(li), + a.freed(li), + }) + + li = li_alloc(true) + li.li_tv.v_type = lib.VAR_FLOAT + li.li_tv.vval.v_float = 10.5 + lib.tv_list_item_free(li) + alloc_log:check({ + a.li(li), + a.freed(li), + }) + + li = li_alloc(true) + li.li_tv.v_type = lib.VAR_STRING + li.li_tv.vval.v_string = nil + lib.tv_list_item_free(li) + alloc_log:check({ + a.li(li), + a.freed(alloc_log.null), + a.freed(li), + }) + + li = li_alloc(true) + li.li_tv.v_type = lib.VAR_STRING + s = to_cstr_nofree('test') + li.li_tv.vval.v_string = s + lib.tv_list_item_free(li) + alloc_log:check({ + a.li(li), + a.str(s, #('test')), + a.freed(s), + a.freed(li), + }) + + li = li_alloc(true) + li.li_tv.v_type = lib.VAR_LIST + l = ffi.gc(list(), nil) + l.lv_refcount = 2 + li.li_tv.vval.v_list = l + lib.tv_list_item_free(li) + alloc_log:check({ + a.li(li), + a.list(l), + a.freed(li), + }) + eq(1, l.lv_refcount) + + li = li_alloc(true) + tv = lua2typvalt({}) + tv.vval.v_dict.dv_refcount = 2 + li.li_tv = tv + lib.tv_list_item_free(li) + alloc_log:check({ + a.li(li), + a.dict(tv.vval.v_dict), + a.freed(li), + }) + eq(1, tv.vval.v_dict.dv_refcount) + end) + end) + describe('remove()', function() + itp('works', function() + local l = list(1, 2, 3, 4, 5, 6, 7) + neq(nil, l) + local lis = list_items(l) + alloc_log:check({ + a.list(l), + a.li(lis[1]), + a.li(lis[2]), + a.li(lis[3]), + a.li(lis[4]), + a.li(lis[5]), + a.li(lis[6]), + a.li(lis[7]), + }) + + lib.tv_list_item_remove(l, lis[1]) + alloc_log:check({ + a.freed(table.remove(lis, 1)), + }) + eq(lis, list_items(l)) + + lib.tv_list_item_remove(l, lis[6]) + alloc_log:check({ + a.freed(table.remove(lis)), + }) + eq(lis, list_items(l)) + + lib.tv_list_item_remove(l, lis[3]) + alloc_log:check({ + a.freed(table.remove(lis, 3)), + }) + eq(lis, list_items(l)) + end) + itp('works and adjusts watchers correctly', function() + local l = ffi.gc(list(1, 2, 3, 4, 5, 6, 7), nil) + neq(nil, l) + local lis = list_items(l) + -- Three watchers: pointing to first, middle and last elements. + local lws = { + list_watch(l, lis[1]), + list_watch(l, lis[4]), + list_watch(l, lis[7]), + } + alloc_log:check({ + a.list(l), + a.li(lis[1]), + a.li(lis[2]), + a.li(lis[3]), + a.li(lis[4]), + a.li(lis[5]), + a.li(lis[6]), + a.li(lis[7]), + }) + + lib.tv_list_item_remove(l, lis[4]) + alloc_log:check({a.freed(lis[4])}) + eq({lis[1], lis[5], lis[7]}, {lws[1].lw_item, lws[2].lw_item, lws[3].lw_item}) + + lib.tv_list_item_remove(l, lis[2]) + alloc_log:check({a.freed(lis[2])}) + eq({lis[1], lis[5], lis[7]}, {lws[1].lw_item, lws[2].lw_item, lws[3].lw_item}) + + lib.tv_list_item_remove(l, lis[7]) + alloc_log:check({a.freed(lis[7])}) + eq({lis[1], lis[5], nil}, {lws[1].lw_item, lws[2].lw_item, lws[3].lw_item == nil and nil}) + + lib.tv_list_item_remove(l, lis[1]) + alloc_log:check({a.freed(lis[1])}) + eq({lis[3], lis[5], nil}, {lws[1].lw_item, lws[2].lw_item, lws[3].lw_item == nil and nil}) + + lib.tv_list_watch_remove(l, lws[2]) + lib.tv_list_watch_remove(l, lws[3]) + lib.tv_list_watch_remove(l, lws[1]) + lib.tv_list_free(l) + alloc_log:check({ + a.freed(lis[3]), + a.freed(lis[5]), + a.freed(lis[6]), + a.freed(l), + }) + end) + end) + end) + describe('watch', function() + describe('remove()', function() + itp('works', function() + local l = ffi.gc(list(1, 2, 3, 4, 5, 6, 7), nil) + eq(nil, l.lv_watch) + local lw = list_watch(l) + neq(nil, l.lv_watch) + alloc_log:clear() + lib.tv_list_watch_remove(l, lw) + eq(nil, l.lv_watch) + alloc_log:check({ + -- Does not free anything. + }) + local lws = { list_watch(l), list_watch(l), list_watch(l) } + alloc_log:clear() + lib.tv_list_watch_remove(l, lws[2]) + eq(lws[3], l.lv_watch) + eq(lws[1], l.lv_watch.lw_next) + lib.tv_list_watch_remove(l, lws[1]) + eq(lws[3], l.lv_watch) + eq(nil, l.lv_watch.lw_next) + lib.tv_list_watch_remove(l, lws[3]) + eq(nil, l.lv_watch) + alloc_log:check({ + -- Does not free anything. + }) + end) + itp('ignores not found watchers', function() + local l = list(1, 2, 3, 4, 5, 6, 7) + local lw = list_watch_alloc() + lib.tv_list_watch_remove(l, lw) + end) + end) + end) + -- add() and fix() were tested when testing tv_list_item_remove() + describe('free()', function() + itp('recursively frees list', function() + local l1 = ffi.gc(list(1, 'abc'), nil) + local l2 = ffi.gc(list({}), nil) + local l3 = ffi.gc(list(empty_list), nil) + local alloc_rets = {} + alloc_log:check(get_alloc_rets({ + a.list(l1), + a.li(l1.lv_first), + a.str(l1.lv_last.li_tv.vval.v_string, #('abc')), + a.li(l1.lv_last), + a.list(l2), + a.dict(l2.lv_first.li_tv.vval.v_dict), + a.li(l2.lv_first), + a.list(l3), + a.list(l3.lv_first.li_tv.vval.v_list), + a.li(l3.lv_first), + }, alloc_rets)) + lib.tv_list_free(l1) + alloc_log:check({ + alloc_rets:freed(2), + alloc_rets:freed(3), + alloc_rets:freed(4), + alloc_rets:freed(1), + }) + lib.tv_list_free(l2) + alloc_log:check({ + alloc_rets:freed(6), + alloc_rets:freed(7), + alloc_rets:freed(5), + }) + lib.tv_list_free(l3) + alloc_log:check({ + alloc_rets:freed(9), + alloc_rets:freed(10), + alloc_rets:freed(8), + }) + end) + end) + describe('free_list()', function() + itp('does not free list contents', function() + local l1 = ffi.gc(list(1, 'abc'), nil) + local l2 = ffi.gc(list({}), nil) + local l3 = ffi.gc(list(empty_list), nil) + local alloc_rets = {} + alloc_log:check(get_alloc_rets({ + a.list(l1), + a.li(l1.lv_first), + a.str(l1.lv_last.li_tv.vval.v_string, #('abc')), + a.li(l1.lv_last), + a.list(l2), + a.dict(l2.lv_first.li_tv.vval.v_dict), + a.li(l2.lv_first), + a.list(l3), + a.list(l3.lv_first.li_tv.vval.v_list), + a.li(l3.lv_first), + }, alloc_rets)) + lib.tv_list_free_list(l1) + alloc_log:check({ + alloc_rets:freed(1), + }) + lib.tv_list_free_list(l2) + alloc_log:check({ + alloc_rets:freed(5), + }) + lib.tv_list_free_list(l3) + alloc_log:check({ + alloc_rets:freed(8), + }) + end) + end) + describe('free_contents()', function() + itp('recursively frees list, except for the list structure itself', + function() + local l1 = ffi.gc(list(1, 'abc'), nil) + local l2 = ffi.gc(list({}), nil) + local l3 = ffi.gc(list(empty_list), nil) + local alloc_rets = {} + alloc_log:check(get_alloc_rets({ + a.list(l1), + a.li(l1.lv_first), + a.str(l1.lv_last.li_tv.vval.v_string, #('abc')), + a.li(l1.lv_last), + a.list(l2), + a.dict(l2.lv_first.li_tv.vval.v_dict), + a.li(l2.lv_first), + a.list(l3), + a.list(l3.lv_first.li_tv.vval.v_list), + a.li(l3.lv_first), + }, alloc_rets)) + lib.tv_list_free_contents(l1) + alloc_log:check({ + alloc_rets:freed(2), + alloc_rets:freed(3), + alloc_rets:freed(4), + }) + lib.tv_list_free_contents(l2) + alloc_log:check({ + alloc_rets:freed(6), + alloc_rets:freed(7), + }) + lib.tv_list_free_contents(l3) + alloc_log:check({ + alloc_rets:freed(9), + alloc_rets:freed(10), + }) + end) + end) + describe('unref()', function() + itp('recursively frees list when reference count goes to 0', function() + local l = ffi.gc(list(empty_list), nil) + local alloc_rets = {} + alloc_log:check(get_alloc_rets({ + a.list(l), + a.list(l.lv_first.li_tv.vval.v_list), + a.li(l.lv_first), + }, alloc_rets)) + l.lv_refcount = 2 + lib.tv_list_unref(l) + alloc_log:check({}) + lib.tv_list_unref(l) + alloc_log:check({ + alloc_rets:freed(2), + alloc_rets:freed(3), + alloc_rets:freed(1), + }) + end) + end) + describe('remove_items()', function() + itp('works', function() + local l_tv = lua2typvalt({1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}) + local l = l_tv.vval.v_list + local lis = list_items(l) + -- Three watchers: pointing to first, middle and last elements. + local lws = { + list_watch(l, lis[1]), + list_watch(l, lis[7]), + list_watch(l, lis[13]), + } + alloc_log:clear() + + lib.tv_list_remove_items(l, lis[1], lis[3]) + eq({4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, typvalt2lua(l_tv)) + eq({lis[4], lis[7], lis[13]}, {lws[1].lw_item, lws[2].lw_item, lws[3].lw_item}) + + lib.tv_list_remove_items(l, lis[11], lis[13]) + eq({4, 5, 6, 7, 8, 9, 10}, typvalt2lua(l_tv)) + eq({lis[4], lis[7], nil}, {lws[1].lw_item, lws[2].lw_item, lws[3].lw_item == nil and nil}) + + lib.tv_list_remove_items(l, lis[6], lis[8]) + eq({4, 5, 9, 10}, typvalt2lua(l_tv)) + eq({lis[4], lis[9], nil}, {lws[1].lw_item, lws[2].lw_item, lws[3].lw_item == nil and nil}) + + lib.tv_list_remove_items(l, lis[4], lis[10]) + eq(empty_list, typvalt2lua(l_tv)) + eq({true, true, true}, {lws[1].lw_item == nil, lws[2].lw_item == nil, lws[3].lw_item == nil}) + + lib.tv_list_watch_remove(l, lws[1]) + lib.tv_list_watch_remove(l, lws[2]) + lib.tv_list_watch_remove(l, lws[3]) + + alloc_log:check({}) + end) + end) + describe('insert', function() + describe('()', function() + itp('works', function() + local l_tv = lua2typvalt({1, 2, 3, 4, 5, 6, 7}) + local l = l_tv.vval.v_list + local lis = list_items(l) + local li + + li = li_alloc(true) + li.li_tv = {v_type=lib.VAR_FLOAT, vval={v_float=100500}} + lib.tv_list_insert(l, li, nil) + eq(l.lv_last, li) + eq({1, 2, 3, 4, 5, 6, 7, 100500}, typvalt2lua(l_tv)) + + li = li_alloc(true) + li.li_tv = {v_type=lib.VAR_FLOAT, vval={v_float=0}} + lib.tv_list_insert(l, li, lis[1]) + eq(l.lv_first, li) + eq({0, 1, 2, 3, 4, 5, 6, 7, 100500}, typvalt2lua(l_tv)) + + li = li_alloc(true) + li.li_tv = {v_type=lib.VAR_FLOAT, vval={v_float=4.5}} + lib.tv_list_insert(l, li, lis[5]) + eq(list_items(l)[6], li) + eq({0, 1, 2, 3, 4, 4.5, 5, 6, 7, 100500}, typvalt2lua(l_tv)) + end) + itp('works with an empty list', function() + local l_tv = lua2typvalt(empty_list) + local l = l_tv.vval.v_list + + eq(nil, l.lv_first) + eq(nil, l.lv_last) + + local li = li_alloc(true) + li.li_tv = {v_type=lib.VAR_FLOAT, vval={v_float=100500}} + lib.tv_list_insert(l, li, nil) + eq(l.lv_last, li) + eq({100500}, typvalt2lua(l_tv)) + end) + end) + describe('tv()', function() + itp('works', function() + local l_tv = lua2typvalt(empty_list) + local l = l_tv.vval.v_list + + local l_l_tv = lua2typvalt(empty_list) + alloc_log:clear() + local l_l = l_l_tv.vval.v_list + eq(1, l_l.lv_refcount) + lib.tv_list_insert_tv(l, l_l_tv, nil) + eq(2, l_l.lv_refcount) + eq(l_l, l.lv_first.li_tv.vval.v_list) + alloc_log:check({ + a.li(l.lv_first), + }) + + local l_s_tv = lua2typvalt('test') + alloc_log:check({ + a.str(l_s_tv.vval.v_string, 'test'), + }) + lib.tv_list_insert_tv(l, l_s_tv, l.lv_first) + alloc_log:check({ + a.li(l.lv_first), + a.str(l.lv_first.li_tv.vval.v_string, 'test'), + }) + + eq({'test', empty_list}, typvalt2lua(l_tv)) + end) + end) + end) + describe('append', function() + describe('list()', function() + itp('works', function() + local l_tv = lua2typvalt(empty_list) + local l = l_tv.vval.v_list + + local l_l = list(1) + alloc_log:clear() + eq(1, l_l.lv_refcount) + lib.tv_list_append_list(l, l_l) + eq(2, l_l.lv_refcount) + eq(l_l, l.lv_first.li_tv.vval.v_list) + alloc_log:check({ + a.li(l.lv_last), + }) + + lib.tv_list_append_list(l, nil) + alloc_log:check({ + a.li(l.lv_last), + }) + + eq({{1}, null_list}, typvalt2lua(l_tv)) + end) + end) + describe('dict()', function() + itp('works', function() + local l_tv = lua2typvalt(empty_list) + local l = l_tv.vval.v_list + + local l_d_tv = lua2typvalt({test=1}) + local l_d = l_d_tv.vval.v_dict + alloc_log:clear() + eq(1, l_d.dv_refcount) + lib.tv_list_append_dict(l, l_d) + eq(2, l_d.dv_refcount) + eq(l_d, l.lv_first.li_tv.vval.v_list) + alloc_log:check({ + a.li(l.lv_last), + }) + + lib.tv_list_append_dict(l, nil) + alloc_log:check({ + a.li(l.lv_last), + }) + + eq({{test=1}, null_dict}, typvalt2lua(l_tv)) + end) + end) + describe('string()', function() + itp('works', function() + local l_tv = lua2typvalt(empty_list) + local l = l_tv.vval.v_list + + alloc_log:clear() + lib.tv_list_append_string(l, 'test', 3) + alloc_log:check({ + a.str(l.lv_last.li_tv.vval.v_string, 'tes'), + a.li(l.lv_last), + }) + + lib.tv_list_append_string(l, nil, 0) + alloc_log:check({ + a.li(l.lv_last), + }) + + lib.tv_list_append_string(l, nil, -1) + alloc_log:check({ + a.li(l.lv_last), + }) + + lib.tv_list_append_string(l, 'test', -1) + alloc_log:check({ + a.str(l.lv_last.li_tv.vval.v_string, 'test'), + a.li(l.lv_last), + }) + + eq({'tes', null_string, null_string, 'test'}, typvalt2lua(l_tv)) + end) + end) + describe('allocated string()', function() + itp('works', function() + local l_tv = lua2typvalt(empty_list) + local l = l_tv.vval.v_list + + local s = lib.xstrdup('test') + alloc_log:clear() + lib.tv_list_append_allocated_string(l, s) + alloc_log:check({ + a.li(l.lv_last), + }) + + lib.tv_list_append_allocated_string(l, nil) + alloc_log:check({ + a.li(l.lv_last), + }) + + lib.tv_list_append_allocated_string(l, nil) + alloc_log:check({ + a.li(l.lv_last), + }) + + eq({'test', null_string, null_string}, typvalt2lua(l_tv)) + end) + end) + describe('number()', function() + itp('works', function() + local l_tv = lua2typvalt(empty_list) + local l = l_tv.vval.v_list + + alloc_log:clear() + lib.tv_list_append_number(l, -100500) + alloc_log:check({ + a.li(l.lv_last), + }) + + lib.tv_list_append_number(l, 100500) + alloc_log:check({ + a.li(l.lv_last), + }) + + eq({int(-100500), int(100500)}, typvalt2lua(l_tv)) + end) + end) + end) + describe('copy()', function() + local function tv_list_copy(...) + return ffi.gc(lib.tv_list_copy(...), lib.tv_list_unref) + end + itp('copies NULL correctly', function() + eq(nil, lib.tv_list_copy(nil, nil, true, 0)) + eq(nil, lib.tv_list_copy(nil, nil, false, 0)) + eq(nil, lib.tv_list_copy(nil, nil, true, 1)) + eq(nil, lib.tv_list_copy(nil, nil, false, 1)) + end) + itp('copies list correctly without converting items', function() + do + local v = {{['ยซ']='ยป'}, {'โ'}, 1, 'โ', null_string, null_list, null_dict} + local l_tv = lua2typvalt(v) + local l = l_tv.vval.v_list + local lis = list_items(l) + alloc_log:clear() + + eq(1, lis[1].li_tv.vval.v_dict.dv_refcount) + eq(1, lis[2].li_tv.vval.v_list.lv_refcount) + local l_copy1 = tv_list_copy(nil, l, false, 0) + eq(2, lis[1].li_tv.vval.v_dict.dv_refcount) + eq(2, lis[2].li_tv.vval.v_list.lv_refcount) + local lis_copy1 = list_items(l_copy1) + eq(lis[1].li_tv.vval.v_dict, lis_copy1[1].li_tv.vval.v_dict) + eq(lis[2].li_tv.vval.v_list, lis_copy1[2].li_tv.vval.v_list) + eq(v, lst2tbl(l_copy1)) + alloc_log:check({ + a.list(l_copy1), + a.li(lis_copy1[1]), + a.li(lis_copy1[2]), + a.li(lis_copy1[3]), + a.li(lis_copy1[4]), + a.str(lis_copy1[4].li_tv.vval.v_string, #v[4]), + a.li(lis_copy1[5]), + a.li(lis_copy1[6]), + a.li(lis_copy1[7]), + }) + lib.tv_list_free(ffi.gc(l_copy1, nil)) + alloc_log:clear() + + eq(1, lis[1].li_tv.vval.v_dict.dv_refcount) + eq(1, lis[2].li_tv.vval.v_list.lv_refcount) + local l_deepcopy1 = tv_list_copy(nil, l, true, 0) + neq(nil, l_deepcopy1) + eq(1, lis[1].li_tv.vval.v_dict.dv_refcount) + eq(1, lis[2].li_tv.vval.v_list.lv_refcount) + local lis_deepcopy1 = list_items(l_deepcopy1) + neq(lis[1].li_tv.vval.v_dict, lis_deepcopy1[1].li_tv.vval.v_dict) + neq(lis[2].li_tv.vval.v_list, lis_deepcopy1[2].li_tv.vval.v_list) + eq(v, lst2tbl(l_deepcopy1)) + local di_deepcopy1 = first_di(lis_deepcopy1[1].li_tv.vval.v_dict) + alloc_log:check({ + a.list(l_deepcopy1), + a.li(lis_deepcopy1[1]), + a.dict(lis_deepcopy1[1].li_tv.vval.v_dict), + a.di(di_deepcopy1, #('ยซ')), + a.str(di_deepcopy1.di_tv.vval.v_string, #v[1]['ยซ']), + a.li(lis_deepcopy1[2]), + a.list(lis_deepcopy1[2].li_tv.vval.v_list), + a.li(lis_deepcopy1[2].li_tv.vval.v_list.lv_first), + a.str(lis_deepcopy1[2].li_tv.vval.v_list.lv_first.li_tv.vval.v_string, #v[2][1]), + a.li(lis_deepcopy1[3]), + a.li(lis_deepcopy1[4]), + a.str(lis_deepcopy1[4].li_tv.vval.v_string, #v[4]), + a.li(lis_deepcopy1[5]), + a.li(lis_deepcopy1[6]), + a.li(lis_deepcopy1[7]), + }) + end + collectgarbage() + end) + itp('copies list correctly and converts items', function() + local vc = vimconv_alloc() + -- UTF-8 โ latin1 conversions needs no iconv + eq(OK, lib.convert_setup(vc, to_cstr('utf-8'), to_cstr('latin1'))) + + local v = {{['ยซ']='ยป'}, {'โ'}, 1, 'โ', null_string, null_list, null_dict} + local l_tv = lua2typvalt(v) + local l = l_tv.vval.v_list + local lis = list_items(l) + alloc_log:clear() + + eq(1, lis[1].li_tv.vval.v_dict.dv_refcount) + eq(1, lis[2].li_tv.vval.v_list.lv_refcount) + local l_deepcopy1 = tv_list_copy(vc, l, true, 0) + neq(nil, l_deepcopy1) + eq(1, lis[1].li_tv.vval.v_dict.dv_refcount) + eq(1, lis[2].li_tv.vval.v_list.lv_refcount) + local lis_deepcopy1 = list_items(l_deepcopy1) + neq(lis[1].li_tv.vval.v_dict, lis_deepcopy1[1].li_tv.vval.v_dict) + neq(lis[2].li_tv.vval.v_list, lis_deepcopy1[2].li_tv.vval.v_list) + eq({{['\171']='\187'}, {'\191'}, 1, '\191', null_string, null_list, null_dict}, + lst2tbl(l_deepcopy1)) + local di_deepcopy1 = first_di(lis_deepcopy1[1].li_tv.vval.v_dict) + alloc_log:clear_tmp_allocs() + alloc_log:check({ + a.list(l_deepcopy1), + a.li(lis_deepcopy1[1]), + a.dict(lis_deepcopy1[1].li_tv.vval.v_dict), + a.di(di_deepcopy1, 1), + a.str(di_deepcopy1.di_tv.vval.v_string, 2), + a.li(lis_deepcopy1[2]), + a.list(lis_deepcopy1[2].li_tv.vval.v_list), + a.li(lis_deepcopy1[2].li_tv.vval.v_list.lv_first), + a.str(lis_deepcopy1[2].li_tv.vval.v_list.lv_first.li_tv.vval.v_string, #v[2][1]), + a.li(lis_deepcopy1[3]), + a.li(lis_deepcopy1[4]), + a.str(lis_deepcopy1[4].li_tv.vval.v_string, #v[4]), + a.li(lis_deepcopy1[5]), + a.li(lis_deepcopy1[6]), + a.li(lis_deepcopy1[7]), + }) + end) + itp('returns different/same containers with(out) copyID', function() + local l_inner_tv = lua2typvalt(empty_list) + local l_tv = lua2typvalt({l_inner_tv, l_inner_tv}) + eq(3, l_inner_tv.vval.v_list.lv_refcount) + local l = l_tv.vval.v_list + eq(l.lv_first.li_tv.vval.v_list, l.lv_last.li_tv.vval.v_list) + + local l_copy1 = tv_list_copy(nil, l, true, 0) + neq(l_copy1.lv_first.li_tv.vval.v_list, l_copy1.lv_last.li_tv.vval.v_list) + eq({empty_list, empty_list}, lst2tbl(l_copy1)) + + local l_copy2 = tv_list_copy(nil, l, true, 2) + eq(l_copy2.lv_first.li_tv.vval.v_list, l_copy2.lv_last.li_tv.vval.v_list) + eq({empty_list, empty_list}, lst2tbl(l_copy2)) + + eq(3, l_inner_tv.vval.v_list.lv_refcount) + end) + itp('works with self-referencing list with copyID', function() + local l_tv = lua2typvalt(empty_list) + local l = l_tv.vval.v_list + eq(1, l.lv_refcount) + lib.tv_list_append_list(l, l) + eq(2, l.lv_refcount) + + local l_copy1 = tv_list_copy(nil, l, true, 2) + eq(2, l_copy1.lv_refcount) + local v = {} + v[1] = v + eq(v, lst2tbl(l_copy1)) + + local lis = list_items(l) + lib.tv_list_item_remove(l, lis[1]) + eq(1, l.lv_refcount) + + local lis_copy1 = list_items(l_copy1) + lib.tv_list_item_remove(l_copy1, lis_copy1[1]) + eq(1, l_copy1.lv_refcount) + end) + end) + describe('extend()', function() + itp('can extend list with itself', function() + local l + + l = list(1, {}) + alloc_log:clear() + eq(1, l.lv_refcount) + eq(1, l.lv_last.li_tv.vval.v_dict.dv_refcount) + + lib.tv_list_extend(l, l, nil) + alloc_log:check({ + a.li(l.lv_last.li_prev), + a.li(l.lv_last), + }) + eq(1, l.lv_refcount) + eq(2, l.lv_last.li_tv.vval.v_dict.dv_refcount) + eq({1, {}, 1, {}}, lst2tbl(l)) + + l = list(1, {}) + alloc_log:clear() + eq(1, l.lv_refcount) + eq(1, l.lv_last.li_tv.vval.v_dict.dv_refcount) + + lib.tv_list_extend(l, l, l.lv_last) + alloc_log:check({ + a.li(l.lv_last.li_prev.li_prev), + a.li(l.lv_last.li_prev), + }) + eq({1, 1, {}, {}}, lst2tbl(l)) + eq(1, l.lv_refcount) + eq(2, l.lv_last.li_tv.vval.v_dict.dv_refcount) + + l = list(1, {}) + alloc_log:clear() + eq(1, l.lv_refcount) + eq(1, l.lv_last.li_tv.vval.v_dict.dv_refcount) + + lib.tv_list_extend(l, l, l.lv_first) + alloc_log:check({ + a.li(l.lv_first), + a.li(l.lv_first.li_next), + }) + eq({1, {}, 1, {}}, lst2tbl(l)) + eq(1, l.lv_refcount) + eq(2, l.lv_last.li_tv.vval.v_dict.dv_refcount) + end) + itp('can extend list with an empty list', function() + local l = list(1, {}) + local el = list() + alloc_log:clear() + eq(1, l.lv_refcount) + eq(1, l.lv_last.li_tv.vval.v_dict.dv_refcount) + eq(1, el.lv_refcount) + + lib.tv_list_extend(l, el, nil) + alloc_log:check({ + }) + eq(1, l.lv_refcount) + eq(1, l.lv_last.li_tv.vval.v_dict.dv_refcount) + eq(1, el.lv_refcount) + eq({1, {}}, lst2tbl(l)) + + lib.tv_list_extend(l, el, l.lv_first) + alloc_log:check({ + }) + eq(1, l.lv_refcount) + eq(1, l.lv_last.li_tv.vval.v_dict.dv_refcount) + eq(1, el.lv_refcount) + eq({1, {}}, lst2tbl(l)) + + lib.tv_list_extend(l, el, l.lv_last) + alloc_log:check({ + }) + eq(1, l.lv_refcount) + eq(1, l.lv_last.li_tv.vval.v_dict.dv_refcount) + eq(1, el.lv_refcount) + eq({1, {}}, lst2tbl(l)) + end) + itp('can extend list with another non-empty list', function() + local l + local l2 = list(42, empty_list) + eq(1, l2.lv_refcount) + eq(1, l2.lv_last.li_tv.vval.v_list.lv_refcount) + + l = ffi.gc(list(1, {}), nil) + alloc_log:clear() + eq(1, l.lv_refcount) + eq(1, l.lv_last.li_tv.vval.v_dict.dv_refcount) + + lib.tv_list_extend(l, l2, nil) + alloc_log:check({ + a.li(l.lv_last.li_prev), + a.li(l.lv_last), + }) + eq(1, l2.lv_refcount) + eq(2, l2.lv_last.li_tv.vval.v_list.lv_refcount) + eq({1, {}, 42, empty_list}, lst2tbl(l)) + lib.tv_list_free(l) + eq(1, l2.lv_last.li_tv.vval.v_list.lv_refcount) + + l = ffi.gc(list(1, {}), nil) + alloc_log:clear() + eq(1, l.lv_refcount) + eq(1, l.lv_last.li_tv.vval.v_dict.dv_refcount) + + lib.tv_list_extend(l, l2, l.lv_first) + alloc_log:check({ + a.li(l.lv_first), + a.li(l.lv_first.li_next), + }) + eq(1, l2.lv_refcount) + eq(2, l2.lv_last.li_tv.vval.v_list.lv_refcount) + eq({42, empty_list, 1, {}}, lst2tbl(l)) + lib.tv_list_free(l) + eq(1, l2.lv_last.li_tv.vval.v_list.lv_refcount) + + l = ffi.gc(list(1, {}), nil) + alloc_log:clear() + eq(1, l.lv_refcount) + eq(1, l.lv_last.li_tv.vval.v_dict.dv_refcount) + + lib.tv_list_extend(l, l2, l.lv_last) + alloc_log:check({ + a.li(l.lv_first.li_next), + a.li(l.lv_first.li_next.li_next), + }) + eq(1, l2.lv_refcount) + eq(2, l2.lv_last.li_tv.vval.v_list.lv_refcount) + eq({1, 42, empty_list, {}}, lst2tbl(l)) + lib.tv_list_free(l) + eq(1, l2.lv_last.li_tv.vval.v_list.lv_refcount) + end) + end) + describe('concat()', function() + itp('works with NULL lists', function() + local l = list(1, {}) + alloc_log:clear() + eq(1, l.lv_refcount) + eq(1, l.lv_last.li_tv.vval.v_dict.dv_refcount) + + local rettv1 = typvalt() + eq(OK, lib.tv_list_concat(nil, l, rettv1)) + eq(1, l.lv_refcount) + eq(tonumber(lib.VAR_LIST), tonumber(rettv1.v_type)) + eq({1, {}}, typvalt2lua(rettv1)) + eq(1, rettv1.vval.v_list.lv_refcount) + alloc_log:check({ + a.list(rettv1.vval.v_list), + a.li(rettv1.vval.v_list.lv_first), + a.li(rettv1.vval.v_list.lv_last), + }) + eq(2, l.lv_last.li_tv.vval.v_dict.dv_refcount) + + local rettv2 = typvalt() + eq(OK, lib.tv_list_concat(l, nil, rettv2)) + eq(1, l.lv_refcount) + eq(tonumber(lib.VAR_LIST), tonumber(rettv2.v_type)) + eq({1, {}}, typvalt2lua(rettv2)) + eq(1, rettv2.vval.v_list.lv_refcount) + alloc_log:check({ + a.list(rettv2.vval.v_list), + a.li(rettv2.vval.v_list.lv_first), + a.li(rettv2.vval.v_list.lv_last), + }) + eq(3, l.lv_last.li_tv.vval.v_dict.dv_refcount) + + local rettv3 = typvalt() + eq(OK, lib.tv_list_concat(nil, nil, rettv3)) + eq(tonumber(lib.VAR_LIST), tonumber(rettv3.v_type)) + eq(null_list, typvalt2lua(rettv3)) + alloc_log:check({}) + end) + itp('works with two different lists', function() + local l1 = list(1, {}) + local l2 = list(3, empty_list) + eq(1, l1.lv_refcount) + eq(1, l1.lv_last.li_tv.vval.v_dict.dv_refcount) + eq(1, l2.lv_refcount) + eq(1, l2.lv_last.li_tv.vval.v_list.lv_refcount) + alloc_log:clear() + + local rettv = typvalt() + eq(OK, lib.tv_list_concat(l1, l2, rettv)) + eq(1, l1.lv_refcount) + eq(2, l1.lv_last.li_tv.vval.v_dict.dv_refcount) + eq(1, l2.lv_refcount) + eq(2, l2.lv_last.li_tv.vval.v_list.lv_refcount) + alloc_log:check({ + a.list(rettv.vval.v_list), + a.li(rettv.vval.v_list.lv_first), + a.li(rettv.vval.v_list.lv_first.li_next), + a.li(rettv.vval.v_list.lv_last.li_prev), + a.li(rettv.vval.v_list.lv_last), + }) + eq({1, {}, 3, empty_list}, typvalt2lua(rettv)) + end) + itp('can concatenate list with itself', function() + local l = list(1, {}) + eq(1, l.lv_refcount) + eq(1, l.lv_last.li_tv.vval.v_dict.dv_refcount) + alloc_log:clear() + + local rettv = typvalt() + eq(OK, lib.tv_list_concat(l, l, rettv)) + eq(1, l.lv_refcount) + eq(3, l.lv_last.li_tv.vval.v_dict.dv_refcount) + alloc_log:check({ + a.list(rettv.vval.v_list), + a.li(rettv.vval.v_list.lv_first), + a.li(rettv.vval.v_list.lv_first.li_next), + a.li(rettv.vval.v_list.lv_last.li_prev), + a.li(rettv.vval.v_list.lv_last), + }) + eq({1, {}, 1, {}}, typvalt2lua(rettv)) + end) + itp('can concatenate empty non-NULL lists', function() + local l = list(1, {}) + local le = list() + local le2 = list() + eq(1, l.lv_refcount) + eq(1, l.lv_last.li_tv.vval.v_dict.dv_refcount) + eq(1, le.lv_refcount) + eq(1, le2.lv_refcount) + alloc_log:clear() + + local rettv1 = typvalt() + eq(OK, lib.tv_list_concat(l, le, rettv1)) + eq(1, l.lv_refcount) + eq(2, l.lv_last.li_tv.vval.v_dict.dv_refcount) + eq(1, le.lv_refcount) + eq(1, le2.lv_refcount) + alloc_log:check({ + a.list(rettv1.vval.v_list), + a.li(rettv1.vval.v_list.lv_first), + a.li(rettv1.vval.v_list.lv_last), + }) + eq({1, {}}, typvalt2lua(rettv1)) + + local rettv2 = typvalt() + eq(OK, lib.tv_list_concat(le, l, rettv2)) + eq(1, l.lv_refcount) + eq(3, l.lv_last.li_tv.vval.v_dict.dv_refcount) + eq(1, le.lv_refcount) + eq(1, le2.lv_refcount) + alloc_log:check({ + a.list(rettv2.vval.v_list), + a.li(rettv2.vval.v_list.lv_first), + a.li(rettv2.vval.v_list.lv_last), + }) + eq({1, {}}, typvalt2lua(rettv2)) + + local rettv3 = typvalt() + eq(OK, lib.tv_list_concat(le, le, rettv3)) + eq(1, l.lv_refcount) + eq(3, l.lv_last.li_tv.vval.v_dict.dv_refcount) + eq(1, le.lv_refcount) + eq(1, le2.lv_refcount) + alloc_log:check({ + a.list(rettv3.vval.v_list), + }) + eq(empty_list, typvalt2lua(rettv3)) + + local rettv4 = typvalt() + eq(OK, lib.tv_list_concat(le, le2, rettv4)) + eq(1, l.lv_refcount) + eq(3, l.lv_last.li_tv.vval.v_dict.dv_refcount) + eq(1, le.lv_refcount) + eq(1, le2.lv_refcount) + alloc_log:check({ + a.list(rettv4.vval.v_list), + }) + eq(empty_list, typvalt2lua(rettv4)) + end) + end) + describe('join()', function() + local function list_join(l, sep, join_ret) + local ga = ga_alloc() + eq(join_ret or OK, lib.tv_list_join(ga, l, sep)) + local ret = '' + if ga.ga_data ~= nil then + ret = ffi.string(ga.ga_data) + end + -- For some reason this is not working well in GC + lib.ga_clear(ffi.gc(ga, nil)) + return ret + end + itp('works', function() + local l + l = list('boo', 'far') + eq('boo far', list_join(l, ' ')) + eq('boofar', list_join(l, '')) + + l = list('boo') + eq('boo', list_join(l, ' ')) + + l = list() + eq('', list_join(l, ' ')) + + l = list({}, 'far') + eq('{} far', list_join(l, ' ')) + + local recursive_list = {} + recursive_list[1] = recursive_list + l = ffi.gc(list(recursive_list, 'far'), nil) + eq('[[...@0]] far', list_join(l, ' ')) + + local recursive_l = l.lv_first.li_tv.vval.v_list + local recursive_li = recursive_l.lv_first + lib.tv_list_item_remove(recursive_l, recursive_li) + lib.tv_list_free(l) + end) + end) + describe('equal()', function() + itp('compares empty and NULL lists correctly', function() + local l = list() + local l2 = list() + + -- NULL lists are not equal to empty lists + eq(false, lib.tv_list_equal(l, nil, true, false)) + eq(false, lib.tv_list_equal(nil, l, false, false)) + eq(false, lib.tv_list_equal(nil, l, false, true)) + eq(false, lib.tv_list_equal(l, nil, true, true)) + + -- Yet NULL lists are equal themselves + eq(true, lib.tv_list_equal(nil, nil, true, false)) + eq(true, lib.tv_list_equal(nil, nil, false, false)) + eq(true, lib.tv_list_equal(nil, nil, false, true)) + eq(true, lib.tv_list_equal(nil, nil, true, true)) + + -- As well as empty lists + eq(true, lib.tv_list_equal(l, l, true, false)) + eq(true, lib.tv_list_equal(l, l2, false, false)) + eq(true, lib.tv_list_equal(l2, l, false, true)) + eq(true, lib.tv_list_equal(l2, l2, true, true)) + end) + -- Must not use recursive=true argument in the following tests because it + -- indicates that tv_equal_recurse_limit and recursive_cnt were set which + -- is essential. This argument will be set when comparing inner lists. + itp('compares lists correctly when case is not ignored', function() + local l1 = list('abc', {1, 2, 'Abc'}, 'def') + local l2 = list('abc', {1, 2, 'Abc'}) + local l3 = list('abc', {1, 2, 'Abc'}, 'Def') + local l4 = list('abc', {1, 2, 'Abc', 4}, 'def') + local l5 = list('Abc', {1, 2, 'Abc'}, 'def') + local l6 = list('abc', {1, 2, 'Abc'}, 'def') + local l7 = list('abc', {1, 2, 'abc'}, 'def') + local l8 = list('abc', nil, 'def') + local l9 = list('abc', {1, 2, nil}, 'def') + + eq(true, lib.tv_list_equal(l1, l1, false, false)) + eq(false, lib.tv_list_equal(l1, l2, false, false)) + eq(false, lib.tv_list_equal(l1, l3, false, false)) + eq(false, lib.tv_list_equal(l1, l4, false, false)) + eq(false, lib.tv_list_equal(l1, l5, false, false)) + eq(true, lib.tv_list_equal(l1, l6, false, false)) + eq(false, lib.tv_list_equal(l1, l7, false, false)) + eq(false, lib.tv_list_equal(l1, l8, false, false)) + eq(false, lib.tv_list_equal(l1, l9, false, false)) + end) + itp('compares lists correctly when case is ignored', function() + local l1 = list('abc', {1, 2, 'Abc'}, 'def') + local l2 = list('abc', {1, 2, 'Abc'}) + local l3 = list('abc', {1, 2, 'Abc'}, 'Def') + local l4 = list('abc', {1, 2, 'Abc', 4}, 'def') + local l5 = list('Abc', {1, 2, 'Abc'}, 'def') + local l6 = list('abc', {1, 2, 'Abc'}, 'def') + local l7 = list('abc', {1, 2, 'abc'}, 'def') + local l8 = list('abc', nil, 'def') + local l9 = list('abc', {1, 2, nil}, 'def') + + eq(true, lib.tv_list_equal(l1, l1, true, false)) + eq(false, lib.tv_list_equal(l1, l2, true, false)) + eq(true, lib.tv_list_equal(l1, l3, true, false)) + eq(false, lib.tv_list_equal(l1, l4, true, false)) + eq(true, lib.tv_list_equal(l1, l5, true, false)) + eq(true, lib.tv_list_equal(l1, l6, true, false)) + eq(true, lib.tv_list_equal(l1, l7, true, false)) + eq(false, lib.tv_list_equal(l1, l8, true, false)) + eq(false, lib.tv_list_equal(l1, l9, true, false)) + end) + end) + describe('find', function() + describe('()', function() + itp('correctly indexes list', function() + local l = list(1, 2, 3, 4, 5) + local lis = list_items(l) + alloc_log:clear() + + eq(nil, lib.tv_list_find(nil, -1)) + eq(nil, lib.tv_list_find(nil, 0)) + eq(nil, lib.tv_list_find(nil, 1)) + + eq(nil, lib.tv_list_find(l, 5)) + eq(nil, lib.tv_list_find(l, -6)) + eq(lis[1], lib.tv_list_find(l, -5)) + eq(lis[5], lib.tv_list_find(l, 4)) + eq(lis[3], lib.tv_list_find(l, 2)) + eq(lis[3], lib.tv_list_find(l, -3)) + eq(lis[3], lib.tv_list_find(l, 2)) + eq(lis[3], lib.tv_list_find(l, 2)) + eq(lis[3], lib.tv_list_find(l, -3)) + + l.lv_idx_item = nil + eq(lis[1], lib.tv_list_find(l, -5)) + l.lv_idx_item = nil + eq(lis[5], lib.tv_list_find(l, 4)) + l.lv_idx_item = nil + eq(lis[3], lib.tv_list_find(l, 2)) + l.lv_idx_item = nil + eq(lis[3], lib.tv_list_find(l, -3)) + l.lv_idx_item = nil + eq(lis[3], lib.tv_list_find(l, 2)) + l.lv_idx_item = nil + eq(lis[3], lib.tv_list_find(l, 2)) + l.lv_idx_item = nil + eq(lis[3], lib.tv_list_find(l, -3)) + + l.lv_idx_item = nil + eq(lis[3], lib.tv_list_find(l, 2)) + eq(lis[1], lib.tv_list_find(l, -5)) + eq(lis[3], lib.tv_list_find(l, 2)) + eq(lis[5], lib.tv_list_find(l, 4)) + eq(lis[3], lib.tv_list_find(l, 2)) + eq(lis[3], lib.tv_list_find(l, 2)) + eq(lis[3], lib.tv_list_find(l, 2)) + eq(lis[3], lib.tv_list_find(l, -3)) + eq(lis[3], lib.tv_list_find(l, 2)) + eq(lis[3], lib.tv_list_find(l, 2)) + eq(lis[3], lib.tv_list_find(l, 2)) + eq(lis[3], lib.tv_list_find(l, -3)) + + alloc_log:check({}) + end) + end) + describe('nr()', function() + local function tv_list_find_nr(l, n, msg) + return check_emsg(function() + local err = ffi.new('bool[1]', {false}) + local ret = lib.tv_list_find_nr(l, n, err) + return (err[0] == true), ret + end, msg) + end + itp('returns correct number', function() + local l = list(int(1), int(2), int(3), int(4), int(5)) + alloc_log:clear() + + eq({false, 1}, {tv_list_find_nr(l, -5)}) + eq({false, 5}, {tv_list_find_nr(l, 4)}) + eq({false, 3}, {tv_list_find_nr(l, 2)}) + eq({false, 3}, {tv_list_find_nr(l, -3)}) + + alloc_log:check({}) + end) + itp('returns correct number when given a string', function() + local l = list('1', '2', '3', '4', '5') + alloc_log:clear() + + eq({false, 1}, {tv_list_find_nr(l, -5)}) + eq({false, 5}, {tv_list_find_nr(l, 4)}) + eq({false, 3}, {tv_list_find_nr(l, 2)}) + eq({false, 3}, {tv_list_find_nr(l, -3)}) + + alloc_log:check({}) + end) + itp('returns zero when given a NULL string', function() + local l = list(null_string) + alloc_log:clear() + + eq({false, 0}, {tv_list_find_nr(l, 0)}) + + alloc_log:check({}) + end) + itp('errors out on NULL lists', function() + eq({true, -1}, {tv_list_find_nr(nil, -5)}) + eq({true, -1}, {tv_list_find_nr(nil, 4)}) + eq({true, -1}, {tv_list_find_nr(nil, 2)}) + eq({true, -1}, {tv_list_find_nr(nil, -3)}) + + alloc_log:check({}) + end) + itp('errors out on out-of-range indexes', function() + local l = list(int(1), int(2), int(3), int(4), int(5)) + alloc_log:clear() + + eq({true, -1}, {tv_list_find_nr(l, -6)}) + eq({true, -1}, {tv_list_find_nr(l, 5)}) + + alloc_log:check({}) + end) + itp('errors out on invalid types', function() + local l = list(1, empty_list, {}) + + eq({true, 0}, {tv_list_find_nr(l, 0, 'E805: Using a Float as a Number')}) + eq({true, 0}, {tv_list_find_nr(l, 1, 'E745: Using a List as a Number')}) + eq({true, 0}, {tv_list_find_nr(l, 2, 'E728: Using a Dictionary as a Number')}) + eq({true, 0}, {tv_list_find_nr(l, -1, 'E728: Using a Dictionary as a Number')}) + eq({true, 0}, {tv_list_find_nr(l, -2, 'E745: Using a List as a Number')}) + eq({true, 0}, {tv_list_find_nr(l, -3, 'E805: Using a Float as a Number')}) + end) + end) + local function tv_list_find_str(l, n, msg) + return check_emsg(function() + local ret = lib.tv_list_find_str(l, n) + local s = nil + if ret ~= nil then + s = ffi.string(ret) + end + return s + end, msg) + end + describe('str()', function() + itp('returns correct string', function() + local l = list(int(1), int(2), int(3), int(4), int(5)) + alloc_log:clear() + + eq('1', tv_list_find_str(l, -5)) + eq('5', tv_list_find_str(l, 4)) + eq('3', tv_list_find_str(l, 2)) + eq('3', tv_list_find_str(l, -3)) + + alloc_log:check({}) + end) + itp('returns string when used with VAR_STRING items', function() + local l = list('1', '2', '3', '4', '5') + alloc_log:clear() + + eq('1', tv_list_find_str(l, -5)) + eq('5', tv_list_find_str(l, 4)) + eq('3', tv_list_find_str(l, 2)) + eq('3', tv_list_find_str(l, -3)) + + alloc_log:check({}) + end) + itp('returns empty when used with NULL string', function() + local l = list(null_string) + alloc_log:clear() + + eq('', tv_list_find_str(l, 0)) + + alloc_log:check({}) + end) + itp('fails with error message when index is out of range', function() + local l = list(int(1), int(2), int(3), int(4), int(5)) + + eq(nil, tv_list_find_str(l, -6, 'E684: list index out of range: -6')) + eq(nil, tv_list_find_str(l, 5, 'E684: list index out of range: 5')) + end) + itp('fails with error message on invalid types', function() + local l = list(1, empty_list, {}) + + eq('', tv_list_find_str(l, 0, 'E806: using Float as a String')) + eq('', tv_list_find_str(l, 1, 'E730: using List as a String')) + eq('', tv_list_find_str(l, 2, 'E731: using Dictionary as a String')) + eq('', tv_list_find_str(l, -1, 'E731: using Dictionary as a String')) + eq('', tv_list_find_str(l, -2, 'E730: using List as a String')) + eq('', tv_list_find_str(l, -3, 'E806: using Float as a String')) + end) + end) + end) + describe('idx_of_item()', function() + itp('works', function() + local l = list(1, 2, 3, 4, 5) + local l2 = list(42, empty_list) + local lis = list_items(l) + local lis2 = list_items(l2) + + for i, li in ipairs(lis) do + eq(i - 1, lib.tv_list_idx_of_item(l, li)) + end + eq(-1, lib.tv_list_idx_of_item(l, lis2[1])) + eq(-1, lib.tv_list_idx_of_item(l, nil)) + eq(-1, lib.tv_list_idx_of_item(nil, nil)) + eq(-1, lib.tv_list_idx_of_item(nil, lis[1])) + end) + end) + end) + describe('dict', function() + describe('watcher', function() + describe('add()/remove()', function() + itp('works with an empty key', function() + local d = dict({}) + eq({}, dict_watchers(d)) + local cb = ffi.gc(tbl2callback({type='none'}), nil) + alloc_log:clear() + lib.tv_dict_watcher_add(d, '*', 0, cb[0]) + local ws, qs = dict_watchers(d) + local key_p = qs[1].key_pattern + alloc_log:check({ + a.dwatcher(qs[1]), + a.str(key_p, 0), + }) + eq({{busy=false, cb={type='none'}, pat=''}}, ws) + eq(true, lib.tv_dict_watcher_remove(d, 'x', 0, cb[0])) + alloc_log:check({ + a.freed(key_p), + a.freed(qs[1]), + }) + eq({}, dict_watchers(d)) + end) + itp('works with multiple callbacks', function() + local d = dict({}) + eq({}, dict_watchers(d)) + alloc_log:check({a.dict(d)}) + local cbs = {} + cbs[1] = {'te', ffi.gc(tbl2callback({type='none'}), nil)} + alloc_log:check({}) + cbs[2] = {'foo', ffi.gc(tbl2callback({type='fref', fref='tr'}), nil)} + alloc_log:check({ + a.str(cbs[2][2].data.funcref, #('tr')), + }) + cbs[3] = {'te', ffi.gc(tbl2callback({type='pt', fref='tr', pt={ + value='tr', + args={'test'}, + dict={}, + }}), nil)} + local pt3 = cbs[3][2].data.partial + local pt3_argv = pt3.pt_argv + local pt3_dict = pt3.pt_dict + local pt3_name = pt3.pt_name + local pt3_str_arg = pt3.pt_argv[0].vval.v_string + alloc_log:check({ + a.lua_pt(pt3), + a.lua_tvs(pt3_argv, pt3.pt_argc), + a.str(pt3_str_arg, #('test')), + a.dict(pt3_dict), + a.str(pt3_name, #('tr')), + }) + for _, v in ipairs(cbs) do + lib.tv_dict_watcher_add(d, v[1], #(v[1]), v[2][0]) + end + local ws, qs, kps = dict_watchers(d) + eq({{busy=false, pat=cbs[1][1], cb={type='none'}}, + {busy=false, pat=cbs[2][1], cb={type='fref', fref='tr'}}, + {busy=false, pat=cbs[3][1], cb={type='pt', fref='tr', pt={ + [type_key]=func_type, + value='tr', + args={'test'}, + dict={}, + }}}}, ws) + alloc_log:check({ + a.dwatcher(qs[1]), + a.str(kps[1][1], kps[1][2]), + a.dwatcher(qs[2]), + a.str(kps[2][1], kps[2][2]), + a.dwatcher(qs[3]), + a.str(kps[3][1], kps[3][2]), + }) + eq(true, lib.tv_dict_watcher_remove(d, cbs[2][1], #cbs[2][1], cbs[2][2][0])) + alloc_log:check({ + a.freed(cbs[2][2].data.funcref), + a.freed(kps[2][1]), + a.freed(qs[2]), + }) + eq(false, lib.tv_dict_watcher_remove(d, cbs[2][1], #cbs[2][1], cbs[2][2][0])) + eq({{busy=false, pat=cbs[1][1], cb={type='none'}}, + {busy=false, pat=cbs[3][1], cb={type='pt', fref='tr', pt={ + [type_key]=func_type, + value='tr', + args={'test'}, + dict={}, + }}}}, dict_watchers(d)) + eq(true, lib.tv_dict_watcher_remove(d, cbs[3][1], #cbs[3][1], cbs[3][2][0])) + alloc_log:check({ + a.freed(pt3_str_arg), + a.freed(pt3_argv), + a.freed(pt3_dict), + a.freed(pt3_name), + a.freed(pt3), + a.freed(kps[3][1]), + a.freed(qs[3]), + }) + eq(false, lib.tv_dict_watcher_remove(d, cbs[3][1], #cbs[3][1], cbs[3][2][0])) + eq({{busy=false, pat=cbs[1][1], cb={type='none'}}}, dict_watchers(d)) + eq(true, lib.tv_dict_watcher_remove(d, cbs[1][1], #cbs[1][1], cbs[1][2][0])) + alloc_log:check({ + a.freed(kps[1][1]), + a.freed(qs[1]), + }) + eq(false, lib.tv_dict_watcher_remove(d, cbs[1][1], #cbs[1][1], cbs[1][2][0])) + eq({}, dict_watchers(d)) + end) + end) + describe('notify', function() + -- Way too hard to test it here, functional tests in + -- dict_notifications_spec.lua. + end) + end) + describe('item', function() + describe('alloc()/free()', function() + local function check_tv_dict_item_alloc_len(s, len, tv, more_frees) + local di + if len == nil then + di = ffi.gc(lib.tv_dict_item_alloc(s), nil) + len = #s + else + di = ffi.gc(lib.tv_dict_item_alloc_len(s, len or #s), nil) + end + eq(s:sub(1, len), ffi.string(di.di_key)) + alloc_log:check({a.di(di, len)}) + if tv then + di.di_tv = ffi.gc(tv, nil) + else + di.di_tv.v_type = lib.VAR_UNKNOWN + end + lib.tv_dict_item_free(di) + alloc_log:check(concat_tables(more_frees, {a.freed(di)})) + end + local function check_tv_dict_item_alloc(s, tv, more_frees) + return check_tv_dict_item_alloc_len(s, nil, tv, more_frees) + end + itp('works', function() + check_tv_dict_item_alloc('') + check_tv_dict_item_alloc('t') + check_tv_dict_item_alloc('TEST') + check_tv_dict_item_alloc_len('', 0) + check_tv_dict_item_alloc_len('TEST', 2) + local tv = lua2typvalt('test') + alloc_log:check({a.str(tv.vval.v_string, #('test'))}) + check_tv_dict_item_alloc('', tv, {a.freed(tv.vval.v_string)}) + tv = lua2typvalt('test') + alloc_log:check({a.str(tv.vval.v_string, #('test'))}) + check_tv_dict_item_alloc_len('', 0, tv, {a.freed(tv.vval.v_string)}) + end) + end) + describe('add()/remove()', function() + itp('works', function() + local d = dict() + eq({}, dct2tbl(d)) + alloc_log:check({a.dict(d)}) + local di = ffi.gc(lib.tv_dict_item_alloc(''), nil) + local tv = lua2typvalt('test') + di.di_tv = ffi.gc(tv, nil) + alloc_log:check({a.di(di, ''), a.str(tv.vval.v_string, 'test')}) + eq(OK, lib.tv_dict_add(d, di)) + alloc_log:check({}) + eq(FAIL, check_emsg(function() return lib.tv_dict_add(d, di) end, + 'E685: Internal error: hash_add()')) + alloc_log:clear() + lib.tv_dict_item_remove(d, di) + alloc_log:check({ + a.freed(tv.vval.v_string), + a.freed(di), + }) + end) + end) + end) + describe('indexing', function() + describe('find()', function() + local function tv_dict_find(d, key, key_len) + local di = lib.tv_dict_find(d, key, key_len or #key) + if di == nil then + return nil, nil, nil + end + return typvalt2lua(di.di_tv), ffi.string(di.di_key), di + end + itp('works with NULL dict', function() + eq(nil, lib.tv_dict_find(nil, '', 0)) + eq(nil, lib.tv_dict_find(nil, 'test', -1)) + eq(nil, lib.tv_dict_find(nil, nil, 0)) + end) + itp('works with NULL key', function() + local lua_d = { + ['']=0, + t=1, + te=2, + tes=3, + test=4, + testt=5, + } + local d = dict(lua_d) + alloc_log:clear() + eq(lua_d, dct2tbl(d)) + alloc_log:check({}) + local dis = dict_items(d) + eq({0, '', dis['']}, {tv_dict_find(d, '', 0)}) + eq({0, '', dis['']}, {tv_dict_find(d, nil, 0)}) + end) + itp('works with len properly', function() + local lua_d = { + ['']=0, + t=1, + te=2, + tes=3, + test=4, + testt=5, + } + local d = dict(lua_d) + alloc_log:clear() + eq(lua_d, dct2tbl(d)) + alloc_log:check({}) + for i = 0, 5 do + local v, k = tv_dict_find(d, 'testt', i) + eq({i, ('testt'):sub(1, i)}, {v, k}) + end + eq(nil, tv_dict_find(d, 'testt', 6)) -- Should take NUL byte + eq(5, tv_dict_find(d, 'testt', -1)) + alloc_log:check({}) + end) + end) + describe('get_number()', function() + itp('works with NULL dict', function() + eq(0, check_emsg(function() return lib.tv_dict_get_number(nil, 'test') end, + nil)) + end) + itp('works', function() + local d = ffi.gc(dict({test={}}), nil) + eq(0, check_emsg(function() return lib.tv_dict_get_number(d, 'test') end, + 'E728: Using a Dictionary as a Number')) + d = ffi.gc(dict({tes=int(42), t=44, te='43'}), nil) + alloc_log:clear() + eq(0, check_emsg(function() return lib.tv_dict_get_number(d, 'test') end, + nil)) + eq(42, check_emsg(function() return lib.tv_dict_get_number(d, 'tes') end, + nil)) + eq(43, check_emsg(function() return lib.tv_dict_get_number(d, 'te') end, + nil)) + alloc_log:check({}) + eq(0, check_emsg(function() return lib.tv_dict_get_number(d, 't') end, + 'E805: Using a Float as a Number')) + end) + end) + describe('get_string()', function() + itp('works with NULL dict', function() + eq(nil, check_emsg(function() return lib.tv_dict_get_string(nil, 'test', false) end, + nil)) + end) + itp('works', function() + local d = ffi.gc(dict({test={}}), nil) + eq('', ffi.string(check_emsg(function() return lib.tv_dict_get_string(d, 'test', false) end, + 'E731: using Dictionary as a String'))) + d = ffi.gc(dict({tes=int(42), t=44, te='43', xx=int(45)}), nil) + alloc_log:clear() + local dis = dict_items(d) + eq(nil, check_emsg(function() return lib.tv_dict_get_string(d, 'test', false) end, + nil)) + local s42 = check_emsg(function() return lib.tv_dict_get_string(d, 'tes', false) end, + nil) + eq('42', ffi.string(s42)) + local s45 = check_emsg(function() return lib.tv_dict_get_string(d, 'xx', false) end, + nil) + eq(s42, s45) + eq('45', ffi.string(s45)) + eq('45', ffi.string(s42)) + local s43 = check_emsg(function() return lib.tv_dict_get_string(d, 'te', false) end, + nil) + eq('43', ffi.string(s43)) + neq(s42, s43) + eq(s43, dis.te.di_tv.vval.v_string) + alloc_log:check({}) + eq('', ffi.string(check_emsg(function() return lib.tv_dict_get_string(d, 't', false) end, + 'E806: using Float as a String'))) + end) + itp('allocates a string copy when requested', function() + local function tv_dict_get_string_alloc(d, key, emsg) + alloc_log:clear() + local ret = check_emsg(function() return lib.tv_dict_get_string(d, key, true) end, + emsg) + local s_ret = (ret ~= nil) and ffi.string(ret) or nil + if not emsg then + if s_ret then + alloc_log:check({a.str(ret, s_ret)}) + else + alloc_log:check({}) + end + end + lib.xfree(ret) + return s_ret + end + local d = ffi.gc(dict({test={}}), nil) + eq('', tv_dict_get_string_alloc(d, 'test', 'E731: using Dictionary as a String')) + d = ffi.gc(dict({tes=int(42), t=44, te='43', xx=int(45)}), nil) + alloc_log:clear() + eq(nil, tv_dict_get_string_alloc(d, 'test')) + eq('42', tv_dict_get_string_alloc(d, 'tes')) + eq('45', tv_dict_get_string_alloc(d, 'xx')) + eq('43', tv_dict_get_string_alloc(d, 'te')) + eq('', tv_dict_get_string_alloc(d, 't', 'E806: using Float as a String')) + end) + end) + describe('get_string_buf()', function() + local function tv_dict_get_string_buf(d, key, buf, emsg) + buf = buf or ffi.gc(lib.xmalloc(lib.NUMBUFLEN), lib.xfree) + alloc_log:clear() + local ret = check_emsg(function() return lib.tv_dict_get_string_buf(d, key, buf) end, + emsg) + local s_ret = (ret ~= nil) and ffi.string(ret) or nil + if not emsg then + alloc_log:check({}) + end + return s_ret, ret, buf + end + itp('works with NULL dict', function() + eq(nil, tv_dict_get_string_buf(nil, 'test')) + end) + itp('works', function() + local lua_d = { + ['']={}, + t=1, + te=int(2), + tes=empty_list, + test='tset', + testt=5, + } + local d = dict(lua_d) + alloc_log:clear() + eq(lua_d, dct2tbl(d)) + alloc_log:check({}) + local s, r, b + s, r, b = tv_dict_get_string_buf(d, 'test') + neq(r, b) + eq('tset', s) + s, r, b = tv_dict_get_string_buf(d, 't', nil, 'E806: using Float as a String') + neq(r, b) + eq('', s) + s, r, b = tv_dict_get_string_buf(d, 'te') + eq(r, b) + eq('2', s) + end) + end) + describe('get_string_buf_chk()', function() + local function tv_dict_get_string_buf_chk(d, key, len, buf, def, emsg) + buf = buf or ffi.gc(lib.xmalloc(lib.NUMBUFLEN), lib.xfree) + def = def or ffi.gc(lib.xstrdup('DEFAULT'), lib.xfree) + len = len or #key + alloc_log:clear() + local ret = check_emsg(function() return lib.tv_dict_get_string_buf_chk(d, key, len, buf, def) end, + emsg) + local s_ret = (ret ~= nil) and ffi.string(ret) or nil + if not emsg then + alloc_log:check({}) + end + return s_ret, ret, buf, def + end + itp('works with NULL dict', function() + eq('DEFAULT', tv_dict_get_string_buf_chk(nil, 'test')) + end) + itp('works', function() + local lua_d = { + ['']={}, + t=1, + te=int(2), + tes=empty_list, + test='tset', + testt=5, + } + local d = dict(lua_d) + alloc_log:clear() + eq(lua_d, dct2tbl(d)) + alloc_log:check({}) + local s, r, b, def + s, r, b, def = tv_dict_get_string_buf_chk(d, 'test') + neq(r, b) + neq(r, def) + eq('tset', s) + s, r, b, def = tv_dict_get_string_buf_chk(d, 'test', 1, nil, nil, 'E806: using Float as a String') + neq(r, b) + neq(r, def) + eq(nil, s) + s, r, b, def = tv_dict_get_string_buf_chk(d, 'te') + eq(r, b) + neq(r, def) + eq('2', s) + s, r, b, def = tv_dict_get_string_buf_chk(d, 'TEST') + eq(r, def) + neq(r, b) + eq('DEFAULT', s) + end) + end) + describe('get_callback()', function() + local function tv_dict_get_callback(d, key, key_len, emsg) + key_len = key_len or #key + local cb = ffi.gc(ffi.cast('Callback*', lib.xmalloc(ffi.sizeof('Callback'))), lib.callback_free) + alloc_log:clear() + local ret = check_emsg(function() + return lib.tv_dict_get_callback(d, key, key_len, cb) + end, emsg) + local cb_lua = callback2tbl(cb[0]) + return cb_lua, ret + end + itp('works with NULL dict', function() + eq({{type='none'}, true}, {tv_dict_get_callback(nil, '')}) + end) + itp('works', function() + local lua_d = { + ['']='tr', + t=int(1), + te={[type_key]=func_type, value='tr'}, + tes={[type_key]=func_type, value='tr', args={'a', 'b'}}, + test={[type_key]=func_type, value='Test', dict={test=1}, args={}}, + testt={[type_key]=func_type, value='Test', dict={test=1}, args={1}}, + } + local d = dict(lua_d) + eq(lua_d, dct2tbl(d)) + eq({{type='fref', fref='tr'}, true}, + {tv_dict_get_callback(d, nil, 0)}) + eq({{type='fref', fref='tr'}, true}, + {tv_dict_get_callback(d, '', -1)}) + eq({{type='none'}, true}, + {tv_dict_get_callback(d, 'x', -1)}) + eq({{type='fref', fref='tr'}, true}, + {tv_dict_get_callback(d, 'testt', 0)}) + eq({{type='none'}, false}, + {tv_dict_get_callback(d, 'test', 1, 'E6000: Argument is not a function or function name')}) + eq({{type='fref', fref='tr'}, true}, + {tv_dict_get_callback(d, 'testt', 2)}) + eq({{ type='pt', fref='tr', pt={ [type_key]=func_type, value='tr', args={ 'a', 'b' } } }, true}, + {tv_dict_get_callback(d, 'testt', 3)}) + eq({{ type='pt', fref='Test', pt={ [type_key]=func_type, value='Test', dict={ test=1 }, args={} } }, true}, + {tv_dict_get_callback(d, 'testt', 4)}) + eq({{ type='pt', fref='Test', pt={ [type_key]=func_type, value='Test', dict={ test=1 }, args={1} } }, true}, + {tv_dict_get_callback(d, 'testt', 5)}) + end) + end) + end) + describe('add', function() + describe('()', function() + itp('works', function() + local di = lib.tv_dict_item_alloc_len('t-est', 5) + alloc_log:check({a.di(di, 't-est')}) + di.di_tv.v_type = lib.VAR_NUMBER + di.di_tv.vval.v_number = 42 + local d = dict({test=10}) + local dis = dict_items(d) + alloc_log:check({ + a.dict(d), + a.di(dis.test, 'test') + }) + eq({test=10}, dct2tbl(d)) + alloc_log:clear() + eq(OK, lib.tv_dict_add(d, di)) + alloc_log:check({}) + eq({test=10, ['t-est']=int(42)}, dct2tbl(d)) + eq(FAIL, check_emsg(function() return lib.tv_dict_add(d, di) end, + 'E685: Internal error: hash_add()')) + end) + end) + describe('list()', function() + itp('works', function() + local l = list(1, 2, 3) + alloc_log:clear() + eq(1, l.lv_refcount) + local d = dict({test=10}) + alloc_log:clear() + eq({test=10}, dct2tbl(d)) + eq(OK, lib.tv_dict_add_list(d, 'testt', 3, l)) + local dis = dict_items(d) + alloc_log:check({a.di(dis.tes, 'tes')}) + eq({test=10, tes={1, 2, 3}}, dct2tbl(d)) + eq(2, l.lv_refcount) + eq(FAIL, check_emsg(function() return lib.tv_dict_add_list(d, 'testt', 3, l) end, + 'E685: Internal error: hash_add()')) + eq(2, l.lv_refcount) + alloc_log:clear() + lib.emsg_skip = lib.emsg_skip + 1 + eq(FAIL, check_emsg(function() return lib.tv_dict_add_list(d, 'testt', 3, l) end, + nil)) + eq(2, l.lv_refcount) + lib.emsg_skip = lib.emsg_skip - 1 + alloc_log:clear_tmp_allocs() + alloc_log:check({}) + end) + end) + describe('dict()', function() + itp('works', function() + local d2 = dict({foo=42}) + alloc_log:clear() + eq(1, d2.dv_refcount) + local d = dict({test=10}) + alloc_log:clear() + eq({test=10}, dct2tbl(d)) + eq(OK, lib.tv_dict_add_dict(d, 'testt', 3, d2)) + local dis = dict_items(d) + alloc_log:check({a.di(dis.tes, 'tes')}) + eq({test=10, tes={foo=42}}, dct2tbl(d)) + eq(2, d2.dv_refcount) + eq(FAIL, check_emsg(function() return lib.tv_dict_add_dict(d, 'testt', 3, d2) end, + 'E685: Internal error: hash_add()')) + eq(2, d2.dv_refcount) + alloc_log:clear() + lib.emsg_skip = lib.emsg_skip + 1 + eq(FAIL, check_emsg(function() return lib.tv_dict_add_dict(d, 'testt', 3, d2) end, + nil)) + eq(2, d2.dv_refcount) + lib.emsg_skip = lib.emsg_skip - 1 + alloc_log:clear_tmp_allocs() + alloc_log:check({}) + end) + end) + describe('nr()', function() + itp('works', function() + local d = dict({test=10}) + alloc_log:clear() + eq({test=10}, dct2tbl(d)) + eq(OK, lib.tv_dict_add_nr(d, 'testt', 3, 2)) + local dis = dict_items(d) + alloc_log:check({a.di(dis.tes, 'tes')}) + eq({test=10, tes=int(2)}, dct2tbl(d)) + eq(FAIL, check_emsg(function() return lib.tv_dict_add_nr(d, 'testt', 3, 2) end, + 'E685: Internal error: hash_add()')) + alloc_log:clear() + lib.emsg_skip = lib.emsg_skip + 1 + eq(FAIL, check_emsg(function() return lib.tv_dict_add_nr(d, 'testt', 3, 2) end, + nil)) + lib.emsg_skip = lib.emsg_skip - 1 + alloc_log:clear_tmp_allocs() + alloc_log:check({}) + end) + end) + describe('str()', function() + itp('works', function() + local d = dict({test=10}) + alloc_log:clear() + eq({test=10}, dct2tbl(d)) + eq(OK, lib.tv_dict_add_str(d, 'testt', 3, 'TEST')) + local dis = dict_items(d) + alloc_log:check({ + a.str(dis.tes.di_tv.vval.v_string, 'TEST'), + a.di(dis.tes, 'tes'), + }) + eq({test=10, tes='TEST'}, dct2tbl(d)) + eq(FAIL, check_emsg(function() return lib.tv_dict_add_str(d, 'testt', 3, 'TEST') end, + 'E685: Internal error: hash_add()')) + alloc_log:clear() + lib.emsg_skip = lib.emsg_skip + 1 + eq(FAIL, check_emsg(function() return lib.tv_dict_add_str(d, 'testt', 3, 'TEST') end, + nil)) + lib.emsg_skip = lib.emsg_skip - 1 + alloc_log:clear_tmp_allocs() + alloc_log:check({}) + end) + end) + describe('allocated_str()', function() + itp('works', function() + local d = dict({test=10}) + eq({test=10}, dct2tbl(d)) + alloc_log:clear() + local s1 = lib.xstrdup('TEST') + local s2 = lib.xstrdup('TEST') + local s3 = lib.xstrdup('TEST') + alloc_log:check({ + a.str(s1, 'TEST'), + a.str(s2, 'TEST'), + a.str(s3, 'TEST'), + }) + eq(OK, lib.tv_dict_add_allocated_str(d, 'testt', 3, s1)) + local dis = dict_items(d) + alloc_log:check({ + a.di(dis.tes, 'tes'), + }) + eq({test=10, tes='TEST'}, dct2tbl(d)) + eq(FAIL, check_emsg(function() return lib.tv_dict_add_allocated_str(d, 'testt', 3, s2) end, + 'E685: Internal error: hash_add()')) + alloc_log:clear() + lib.emsg_skip = lib.emsg_skip + 1 + eq(FAIL, check_emsg(function() return lib.tv_dict_add_allocated_str(d, 'testt', 3, s3) end, + nil)) + lib.emsg_skip = lib.emsg_skip - 1 + alloc_log:clear_tmp_allocs() + alloc_log:check({ + a.freed(s3), + }) + end) + end) + end) + describe('clear()', function() + itp('works', function() + local d = dict() + alloc_log:check({a.dict(d)}) + eq({}, dct2tbl(d)) + lib.tv_dict_clear(d) + eq({}, dct2tbl(d)) + lib.tv_dict_add_str(d, 'TEST', 3, 'tEsT') + local dis = dict_items(d) + local di = dis.TES + local di_s = di.di_tv.vval.v_string + alloc_log:check({a.str(di_s), a.di(di)}) + eq({TES='tEsT'}, dct2tbl(d)) + lib.tv_dict_clear(d) + alloc_log:check({a.freed(di_s), a.freed(di)}) + eq({}, dct2tbl(d)) + end) + end) + describe('extend()', function() + local function tv_dict_extend(d1, d2, action, emsg) + action = action or "force" + check_emsg(function() return lib.tv_dict_extend(d1, d2, action) end, emsg) + end + itp('works', function() + local d1 = dict() + alloc_log:check({a.dict(d1)}) + eq({}, dct2tbl(d1)) + local d2 = dict() + alloc_log:check({a.dict(d2)}) + eq({}, dct2tbl(d2)) + tv_dict_extend(d1, d2, 'error') + tv_dict_extend(d1, d2, 'keep') + tv_dict_extend(d1, d2, 'force') + alloc_log:check({}) + + d1 = dict({a='TEST'}) + eq({a='TEST'}, dct2tbl(d1)) + local dis1 = dict_items(d1) + local a1_s = dis1.a.di_tv.vval.v_string + alloc_log:clear_tmp_allocs() + alloc_log:check({ + a.dict(d1), + a.di(dis1.a), + a.str(a1_s), + }) + d2 = dict({a='TSET'}) + eq({a='TSET'}, dct2tbl(d2)) + local dis2 = dict_items(d2) + local a2_s = dis2.a.di_tv.vval.v_string + alloc_log:clear_tmp_allocs() + alloc_log:check({ + a.dict(d2), + a.di(dis2.a), + a.str(a2_s), + }) + + tv_dict_extend(d1, d2, 'error', 'E737: Key already exists: a') + eq({a='TEST'}, dct2tbl(d1)) + eq({a='TSET'}, dct2tbl(d2)) + alloc_log:clear() + + tv_dict_extend(d1, d2, 'keep') + alloc_log:check({}) + eq({a='TEST'}, dct2tbl(d1)) + eq({a='TSET'}, dct2tbl(d2)) + + tv_dict_extend(d1, d2, 'force') + alloc_log:check({ + a.freed(a1_s), + a.str(dis1.a.di_tv.vval.v_string), + }) + eq({a='TSET'}, dct2tbl(d1)) + eq({a='TSET'}, dct2tbl(d2)) + end) + itp('disallows overriding builtin or user functions', function() + local d = dict() + d.dv_scope = lib.VAR_DEF_SCOPE + local f_lua = { + [type_key]=func_type, + value='tr', + } + local f_tv = lua2typvalt(f_lua) + local p_lua = { + [type_key]=func_type, + value='tr', + args={1}, + } + local p_tv = lua2typvalt(p_lua) + eq(lib.VAR_PARTIAL, p_tv.v_type) + local d2 = dict({tr=f_tv}) + local d3 = dict({tr=p_tv}) + local d4 = dict({['TEST:THIS']=p_tv}) + local d5 = dict({Test=f_tv}) + local d6 = dict({Test=p_tv}) + eval0([[execute("function Test()\nendfunction")]]) + tv_dict_extend(d, d2, 'force', + 'E704: Funcref variable name must start with a capital: tr') + tv_dict_extend(d, d3, 'force', + 'E704: Funcref variable name must start with a capital: tr') + tv_dict_extend(d, d4, 'force', + 'E461: Illegal variable name: TEST:THIS') + tv_dict_extend(d, d5, 'force', + 'E705: Variable name conflicts with existing function: Test') + tv_dict_extend(d, d6, 'force', + 'E705: Variable name conflicts with existing function: Test') + eq({}, dct2tbl(d)) + d.dv_scope = lib.VAR_SCOPE + tv_dict_extend(d, d4, 'force', + 'E461: Illegal variable name: TEST:THIS') + eq({}, dct2tbl(d)) + tv_dict_extend(d, d2, 'force') + eq({tr=f_lua}, dct2tbl(d)) + tv_dict_extend(d, d3, 'force') + eq({tr=p_lua}, dct2tbl(d)) + tv_dict_extend(d, d5, 'force') + eq({tr=p_lua, Test=f_lua}, dct2tbl(d)) + tv_dict_extend(d, d6, 'force') + eq({tr=p_lua, Test=p_lua}, dct2tbl(d)) + end) + itp('cares about locks and read-only items', function() + local d_lua = {tv_locked=1, tv_fixed=2, di_ro=3, di_ro_sbx=4} + local d = dict(d_lua) + local dis = dict_items(d) + dis.tv_locked.di_tv.v_lock = lib.VAR_LOCKED + dis.tv_fixed.di_tv.v_lock = lib.VAR_FIXED + dis.di_ro.di_flags = bit.bor(dis.di_ro.di_flags, lib.DI_FLAGS_RO) + dis.di_ro_sbx.di_flags = bit.bor(dis.di_ro_sbx.di_flags, lib.DI_FLAGS_RO_SBX) + lib.sandbox = true + local d1 = dict({tv_locked=41}) + local d2 = dict({tv_fixed=42}) + local d3 = dict({di_ro=43}) + local d4 = dict({di_ro_sbx=44}) + tv_dict_extend(d, d1, 'force', 'E741: Value is locked: extend() argument') + tv_dict_extend(d, d2, 'force', 'E742: Cannot change value of extend() argument') + tv_dict_extend(d, d3, 'force', 'E46: Cannot change read-only variable "extend() argument"') + tv_dict_extend(d, d4, 'force', 'E794: Cannot set variable in the sandbox: "extend() argument"') + eq(d_lua, dct2tbl(d)) + lib.sandbox = false + tv_dict_extend(d, d4, 'force') + d_lua.di_ro_sbx = 44 + eq(d_lua, dct2tbl(d)) + end) + end) + describe('equal()', function() + local function tv_dict_equal(d1, d2, ic, recursive) + return lib.tv_dict_equal(d1, d2, ic or false, recursive or false) + end + itp('works', function() + eq(true, tv_dict_equal(nil, nil)) + local d1 = dict() + alloc_log:check({a.dict(d1)}) + eq(1, d1.dv_refcount) + eq(false, tv_dict_equal(nil, d1)) + eq(false, tv_dict_equal(d1, nil)) + eq(true, tv_dict_equal(d1, d1)) + eq(1, d1.dv_refcount) + alloc_log:check({}) + local d_upper = dict({a='TEST'}) + local dis_upper = dict_items(d_upper) + local d_lower = dict({a='test'}) + local dis_lower = dict_items(d_lower) + local d_kupper_upper = dict({A='TEST'}) + local dis_kupper_upper = dict_items(d_kupper_upper) + local d_kupper_lower = dict({A='test'}) + local dis_kupper_lower = dict_items(d_kupper_lower) + alloc_log:clear_tmp_allocs() + alloc_log:check({ + a.dict(d_upper), + a.di(dis_upper.a), + a.str(dis_upper.a.di_tv.vval.v_string), + + a.dict(d_lower), + a.di(dis_lower.a), + a.str(dis_lower.a.di_tv.vval.v_string), + + a.dict(d_kupper_upper), + a.di(dis_kupper_upper.A), + a.str(dis_kupper_upper.A.di_tv.vval.v_string), + + a.dict(d_kupper_lower), + a.di(dis_kupper_lower.A), + a.str(dis_kupper_lower.A.di_tv.vval.v_string), + }) + eq(true, tv_dict_equal(d_upper, d_upper)) + eq(true, tv_dict_equal(d_upper, d_upper, true)) + eq(false, tv_dict_equal(d_upper, d_lower, false)) + eq(true, tv_dict_equal(d_upper, d_lower, true)) + eq(true, tv_dict_equal(d_kupper_upper, d_kupper_lower, true)) + eq(false, tv_dict_equal(d_kupper_upper, d_lower, true)) + eq(false, tv_dict_equal(d_kupper_upper, d_upper, true)) + eq(true, tv_dict_equal(d_upper, d_upper, true, true)) + alloc_log:check({}) + end) + end) + describe('copy()', function() + local function tv_dict_copy(...) + return ffi.gc(lib.tv_dict_copy(...), lib.tv_dict_unref) + end + itp('copies NULL correctly', function() + eq(nil, lib.tv_dict_copy(nil, nil, true, 0)) + eq(nil, lib.tv_dict_copy(nil, nil, false, 0)) + eq(nil, lib.tv_dict_copy(nil, nil, true, 1)) + eq(nil, lib.tv_dict_copy(nil, nil, false, 1)) + end) + itp('copies dict correctly without converting items', function() + do + local v = {a={['ยซ']='ยป'}, b={'โ'}, ['1']=1, ['ยซยป']='โ', ns=null_string, nl=null_list, nd=null_dict} + local d_tv = lua2typvalt(v) + local d = d_tv.vval.v_dict + local dis = dict_items(d) + alloc_log:clear() + + eq(1, dis.a.di_tv.vval.v_dict.dv_refcount) + eq(1, dis.b.di_tv.vval.v_list.lv_refcount) + local d_copy1 = tv_dict_copy(nil, d, false, 0) + eq(2, dis.a.di_tv.vval.v_dict.dv_refcount) + eq(2, dis.b.di_tv.vval.v_list.lv_refcount) + local dis_copy1 = dict_items(d_copy1) + eq(dis.a.di_tv.vval.v_dict, dis_copy1.a.di_tv.vval.v_dict) + eq(dis.b.di_tv.vval.v_list, dis_copy1.b.di_tv.vval.v_list) + eq(v, dct2tbl(d_copy1)) + alloc_log:clear() + lib.tv_dict_free(ffi.gc(d_copy1, nil)) + alloc_log:clear() + + eq(1, dis.a.di_tv.vval.v_dict.dv_refcount) + eq(1, dis.b.di_tv.vval.v_list.lv_refcount) + local d_deepcopy1 = tv_dict_copy(nil, d, true, 0) + neq(nil, d_deepcopy1) + eq(1, dis.a.di_tv.vval.v_dict.dv_refcount) + eq(1, dis.b.di_tv.vval.v_list.lv_refcount) + local dis_deepcopy1 = dict_items(d_deepcopy1) + neq(dis.a.di_tv.vval.v_dict, dis_deepcopy1.a.di_tv.vval.v_dict) + neq(dis.b.di_tv.vval.v_list, dis_deepcopy1.b.di_tv.vval.v_list) + eq(v, dct2tbl(d_deepcopy1)) + alloc_log:clear() + end + collectgarbage() + end) + itp('copies dict correctly and converts items', function() + local vc = vimconv_alloc() + -- UTF-8 โ latin1 conversions need no iconv + eq(OK, lib.convert_setup(vc, to_cstr('utf-8'), to_cstr('latin1'))) + + local v = {a={['ยซ']='ยป'}, b={'โ'}, ['1']=1, ['ยซยป']='โ', ns=null_string, nl=null_list, nd=null_dict} + local d_tv = lua2typvalt(v) + local d = d_tv.vval.v_dict + local dis = dict_items(d) + alloc_log:clear() + + eq(1, dis.a.di_tv.vval.v_dict.dv_refcount) + eq(1, dis.b.di_tv.vval.v_list.lv_refcount) + local d_deepcopy1 = tv_dict_copy(vc, d, true, 0) + neq(nil, d_deepcopy1) + eq(1, dis.a.di_tv.vval.v_dict.dv_refcount) + eq(1, dis.b.di_tv.vval.v_list.lv_refcount) + local dis_deepcopy1 = dict_items(d_deepcopy1) + neq(dis.a.di_tv.vval.v_dict, dis_deepcopy1.a.di_tv.vval.v_dict) + neq(dis.b.di_tv.vval.v_list, dis_deepcopy1.b.di_tv.vval.v_list) + eq({a={['\171']='\187'}, b={'\191'}, ['1']=1, ['\171\187']='\191', ns=null_string, nl=null_list, nd=null_dict}, + dct2tbl(d_deepcopy1)) + alloc_log:clear_tmp_allocs() + alloc_log:clear() + end) + itp('returns different/same containers with(out) copyID', function() + local d_inner_tv = lua2typvalt({}) + local d_tv = lua2typvalt({a=d_inner_tv, b=d_inner_tv}) + eq(3, d_inner_tv.vval.v_dict.dv_refcount) + local d = d_tv.vval.v_dict + local dis = dict_items(d) + eq(dis.a.di_tv.vval.v_dict, dis.b.di_tv.vval.v_dict) + + local d_copy1 = tv_dict_copy(nil, d, true, 0) + local dis_copy1 = dict_items(d_copy1) + neq(dis_copy1.a.di_tv.vval.v_dict, dis_copy1.b.di_tv.vval.v_dict) + eq({a={}, b={}}, dct2tbl(d_copy1)) + + local d_copy2 = tv_dict_copy(nil, d, true, 2) + local dis_copy2 = dict_items(d_copy2) + eq(dis_copy2.a.di_tv.vval.v_dict, dis_copy2.b.di_tv.vval.v_dict) + eq({a={}, b={}}, dct2tbl(d_copy2)) + + eq(3, d_inner_tv.vval.v_dict.dv_refcount) + end) + itp('works with self-referencing dict with copyID', function() + local d_tv = lua2typvalt({}) + local d = d_tv.vval.v_dict + eq(1, d.dv_refcount) + lib.tv_dict_add_dict(d, 'test', 4, d) + eq(2, d.dv_refcount) + + local d_copy1 = tv_dict_copy(nil, d, true, 2) + eq(2, d_copy1.dv_refcount) + local v = {} + v.test = v + eq(v, dct2tbl(d_copy1)) + + lib.tv_dict_clear(d) + eq(1, d.dv_refcount) + + lib.tv_dict_clear(d_copy1) + eq(1, d_copy1.dv_refcount) + end) + end) + describe('set_keys_readonly()', function() + itp('works', function() + local d = dict({a=true}) + local dis = dict_items(d) + alloc_log:check({a.dict(d), a.di(dis.a)}) + eq(0, bit.band(dis.a.di_flags, lib.DI_FLAGS_RO)) + eq(0, bit.band(dis.a.di_flags, lib.DI_FLAGS_FIX)) + lib.tv_dict_set_keys_readonly(d) + alloc_log:check({}) + eq(lib.DI_FLAGS_RO, bit.band(dis.a.di_flags, lib.DI_FLAGS_RO)) + eq(lib.DI_FLAGS_FIX, bit.band(dis.a.di_flags, lib.DI_FLAGS_FIX)) + end) + end) + end) + describe('tv', function() + describe('alloc', function() + describe('list ret()', function() + itp('works', function() + local rettv = typvalt(lib.VAR_UNKNOWN) + local l = lib.tv_list_alloc_ret(rettv) + eq(empty_list, typvalt2lua(rettv)) + eq(rettv.vval.v_list, l) + end) + end) + describe('dict ret()', function() + itp('works', function() + local rettv = typvalt(lib.VAR_UNKNOWN) + lib.tv_dict_alloc_ret(rettv) + eq({}, typvalt2lua(rettv)) + end) + end) + end) + local function defalloc() + return {} + end + describe('clear()', function() + itp('works', function() + local function deffrees(alloc_rets) + local ret = {} + for i = #alloc_rets, 1, -1 do + ret[#alloc_rets - i + 1] = alloc_rets:freed(i) + end + return ret + end + alloc_log:check({}) + lib.tv_clear(nil) + alloc_log:check({}) + local ll = {} + local ll_l = nil + ll[1] = ll + local dd = {} + local dd_d = nil + dd.dd = dd + for _, v in ipairs({ + {nil_value}, + {null_string, nil, function() return {a.freed(alloc_log.null)} end}, + {0}, + {int(0)}, + {true}, + {false}, + {'true', function(tv) return {a.str(tv.vval.v_string)} end}, + {{}, function(tv) return {a.dict(tv.vval.v_dict)} end}, + {empty_list, function(tv) return {a.list(tv.vval.v_list)} end}, + {ll, function(tv) + ll_l = tv.vval.v_list + return {a.list(tv.vval.v_list), a.li(tv.vval.v_list.lv_first)} + end, defalloc}, + {dd, function(tv) + dd_d = tv.vval.v_dict + return {a.dict(tv.vval.v_dict), a.di(first_di(tv.vval.v_dict))} + end, defalloc}, + }) do + local tv = lua2typvalt(v[1]) + local alloc_rets = {} + alloc_log:check(get_alloc_rets((v[2] or defalloc)(tv), alloc_rets)) + lib.tv_clear(tv) + alloc_log:check((v[3] or deffrees)(alloc_rets)) + end + eq(1, ll_l.lv_refcount) + eq(1, dd_d.dv_refcount) + end) + end) + describe('copy()', function() + itp('works', function() + local function strallocs(tv) + return {a.str(tv.vval.v_string)} + end + for _, v in ipairs({ + {nil_value}, + {null_string}, + {0}, + {int(0)}, + {true}, + {false}, + {{}, function(tv) return {a.dict(tv.vval.v_dict)} end, nil, function(from, to) + eq(2, to.vval.v_dict.dv_refcount) + eq(to.vval.v_dict, from.vval.v_dict) + end}, + {empty_list, function(tv) return {a.list(tv.vval.v_list)} end, nil, function(from, to) + eq(2, to.vval.v_list.lv_refcount) + eq(to.vval.v_list, from.vval.v_list) + end}, + {'test', strallocs, strallocs, function(from, to) + neq(to.vval.v_string, from.vval.v_string) + end}, + }) do + local from = lua2typvalt(v[1]) + alloc_log:check((v[2] or defalloc)(from)) + local to = typvalt(lib.VAR_UNKNOWN) + lib.tv_copy(from, to) + local res = v[1] + eq(res, typvalt2lua(to)) + alloc_log:check((v[3] or defalloc)(to)) + if v[4] then + v[4](from, to) + end + end + end) + end) + describe('item_lock()', function() + itp('does not alter VAR_PARTIAL', function() + local p_tv = lua2typvalt({ + [type_key]=func_type, + value='tr', + dict={}, + }) + lib.tv_item_lock(p_tv, -1, true) + eq(lib.VAR_UNLOCKED, p_tv.vval.v_partial.pt_dict.dv_lock) + end) + itp('does not change VAR_FIXED values', function() + local d_tv = lua2typvalt({}) + local l_tv = lua2typvalt(empty_list) + alloc_log:clear() + d_tv.v_lock = lib.VAR_FIXED + d_tv.vval.v_dict.dv_lock = lib.VAR_FIXED + l_tv.v_lock = lib.VAR_FIXED + l_tv.vval.v_list.lv_lock = lib.VAR_FIXED + lib.tv_item_lock(d_tv, 1, true) + lib.tv_item_lock(l_tv, 1, true) + eq(lib.VAR_FIXED, d_tv.v_lock) + eq(lib.VAR_FIXED, l_tv.v_lock) + eq(lib.VAR_FIXED, d_tv.vval.v_dict.dv_lock) + eq(lib.VAR_FIXED, l_tv.vval.v_list.lv_lock) + lib.tv_item_lock(d_tv, 1, false) + lib.tv_item_lock(l_tv, 1, false) + eq(lib.VAR_FIXED, d_tv.v_lock) + eq(lib.VAR_FIXED, l_tv.v_lock) + eq(lib.VAR_FIXED, d_tv.vval.v_dict.dv_lock) + eq(lib.VAR_FIXED, l_tv.vval.v_list.lv_lock) + alloc_log:check({}) + end) + itp('works with NULL values', function() + local l_tv = lua2typvalt(null_list) + local d_tv = lua2typvalt(null_dict) + local s_tv = lua2typvalt(null_string) + alloc_log:clear() + lib.tv_item_lock(l_tv, 1, true) + lib.tv_item_lock(d_tv, 1, true) + lib.tv_item_lock(s_tv, 1, true) + eq(null_list, typvalt2lua(l_tv)) + eq(null_dict, typvalt2lua(d_tv)) + eq(null_string, typvalt2lua(s_tv)) + eq(lib.VAR_LOCKED, d_tv.v_lock) + eq(lib.VAR_LOCKED, l_tv.v_lock) + eq(lib.VAR_LOCKED, s_tv.v_lock) + alloc_log:check({}) + end) + end) + describe('islocked()', function() + itp('works with NULL values', function() + local l_tv = lua2typvalt(null_list) + local d_tv = lua2typvalt(null_dict) + eq(false, lib.tv_islocked(l_tv)) + eq(false, lib.tv_islocked(d_tv)) + end) + itp('works', function() + local tv = lua2typvalt() + local d_tv = lua2typvalt({}) + local l_tv = lua2typvalt(empty_list) + alloc_log:clear() + eq(false, lib.tv_islocked(tv)) + eq(false, lib.tv_islocked(l_tv)) + eq(false, lib.tv_islocked(d_tv)) + d_tv.vval.v_dict.dv_lock = lib.VAR_LOCKED + l_tv.vval.v_list.lv_lock = lib.VAR_LOCKED + eq(true, lib.tv_islocked(l_tv)) + eq(true, lib.tv_islocked(d_tv)) + tv.v_lock = lib.VAR_LOCKED + d_tv.v_lock = lib.VAR_LOCKED + l_tv.v_lock = lib.VAR_LOCKED + eq(true, lib.tv_islocked(tv)) + eq(true, lib.tv_islocked(l_tv)) + eq(true, lib.tv_islocked(d_tv)) + d_tv.vval.v_dict.dv_lock = lib.VAR_UNLOCKED + l_tv.vval.v_list.lv_lock = lib.VAR_UNLOCKED + eq(true, lib.tv_islocked(tv)) + eq(true, lib.tv_islocked(l_tv)) + eq(true, lib.tv_islocked(d_tv)) + tv.v_lock = lib.VAR_FIXED + d_tv.v_lock = lib.VAR_FIXED + l_tv.v_lock = lib.VAR_FIXED + eq(false, lib.tv_islocked(tv)) + eq(false, lib.tv_islocked(l_tv)) + eq(false, lib.tv_islocked(d_tv)) + d_tv.vval.v_dict.dv_lock = lib.VAR_LOCKED + l_tv.vval.v_list.lv_lock = lib.VAR_LOCKED + eq(true, lib.tv_islocked(l_tv)) + eq(true, lib.tv_islocked(d_tv)) + d_tv.vval.v_dict.dv_lock = lib.VAR_FIXED + l_tv.vval.v_list.lv_lock = lib.VAR_FIXED + eq(false, lib.tv_islocked(l_tv)) + eq(false, lib.tv_islocked(d_tv)) + alloc_log:check({}) + end) + end) + describe('check_lock()', function() + local function tv_check_lock(lock, name, name_len, emsg) + return check_emsg(function() + return lib.tv_check_lock(lock, name, name_len) + end, emsg) + end + itp('works', function() + eq(false, tv_check_lock(lib.VAR_UNLOCKED, 'test', 3)) + eq(true, tv_check_lock(lib.VAR_LOCKED, 'test', 3, + 'E741: Value is locked: tes')) + eq(true, tv_check_lock(lib.VAR_FIXED, 'test', 3, + 'E742: Cannot change value of tes')) + eq(true, tv_check_lock(lib.VAR_LOCKED, nil, 0, + 'E741: Value is locked: Unknown')) + eq(true, tv_check_lock(lib.VAR_FIXED, nil, 0, + 'E742: Cannot change value of Unknown')) + eq(true, tv_check_lock(lib.VAR_LOCKED, nil, lib.kTVCstring, + 'E741: Value is locked: Unknown')) + eq(true, tv_check_lock(lib.VAR_FIXED, 'test', lib.kTVCstring, + 'E742: Cannot change value of test')) + end) + end) + describe('equal()', function() + itp('compares empty and NULL lists correctly', function() + local l = lua2typvalt(empty_list) + local l2 = lua2typvalt(empty_list) + local nl = lua2typvalt(null_list) + + -- NULL lists are not equal to empty lists + eq(false, lib.tv_equal(l, nl, true, false)) + eq(false, lib.tv_equal(nl, l, false, false)) + eq(false, lib.tv_equal(nl, l, false, true)) + eq(false, lib.tv_equal(l, nl, true, true)) + + -- Yet NULL lists are equal themselves + eq(true, lib.tv_equal(nl, nl, true, false)) + eq(true, lib.tv_equal(nl, nl, false, false)) + eq(true, lib.tv_equal(nl, nl, false, true)) + eq(true, lib.tv_equal(nl, nl, true, true)) + + -- As well as empty lists + eq(true, lib.tv_equal(l, l, true, false)) + eq(true, lib.tv_equal(l, l2, false, false)) + eq(true, lib.tv_equal(l2, l, false, true)) + eq(true, lib.tv_equal(l2, l2, true, true)) + end) + -- Must not use recursive=true argument in the following tests because it + -- indicates that tv_equal_recurse_limit and recursive_cnt were set which + -- is essential. This argument will be set when comparing inner lists. + itp('compares lists correctly when case is not ignored', function() + local l1 = lua2typvalt({'abc', {1, 2, 'Abc'}, 'def'}) + local l2 = lua2typvalt({'abc', {1, 2, 'Abc'}}) + local l3 = lua2typvalt({'abc', {1, 2, 'Abc'}, 'Def'}) + local l4 = lua2typvalt({'abc', {1, 2, 'Abc', 4}, 'def'}) + local l5 = lua2typvalt({'Abc', {1, 2, 'Abc'}, 'def'}) + local l6 = lua2typvalt({'abc', {1, 2, 'Abc'}, 'def'}) + local l7 = lua2typvalt({'abc', {1, 2, 'abc'}, 'def'}) + local l8 = lua2typvalt({'abc', nil, 'def'}) + local l9 = lua2typvalt({'abc', {1, 2, nil}, 'def'}) + + eq(true, lib.tv_equal(l1, l1, false, false)) + eq(false, lib.tv_equal(l1, l2, false, false)) + eq(false, lib.tv_equal(l1, l3, false, false)) + eq(false, lib.tv_equal(l1, l4, false, false)) + eq(false, lib.tv_equal(l1, l5, false, false)) + eq(true, lib.tv_equal(l1, l6, false, false)) + eq(false, lib.tv_equal(l1, l7, false, false)) + eq(false, lib.tv_equal(l1, l8, false, false)) + eq(false, lib.tv_equal(l1, l9, false, false)) + end) + itp('compares lists correctly when case is ignored', function() + local l1 = lua2typvalt({'abc', {1, 2, 'Abc'}, 'def'}) + local l2 = lua2typvalt({'abc', {1, 2, 'Abc'}}) + local l3 = lua2typvalt({'abc', {1, 2, 'Abc'}, 'Def'}) + local l4 = lua2typvalt({'abc', {1, 2, 'Abc', 4}, 'def'}) + local l5 = lua2typvalt({'Abc', {1, 2, 'Abc'}, 'def'}) + local l6 = lua2typvalt({'abc', {1, 2, 'Abc'}, 'def'}) + local l7 = lua2typvalt({'abc', {1, 2, 'abc'}, 'def'}) + local l8 = lua2typvalt({'abc', nil, 'def'}) + local l9 = lua2typvalt({'abc', {1, 2, nil}, 'def'}) + + eq(true, lib.tv_equal(l1, l1, true, false)) + eq(false, lib.tv_equal(l1, l2, true, false)) + eq(true, lib.tv_equal(l1, l3, true, false)) + eq(false, lib.tv_equal(l1, l4, true, false)) + eq(true, lib.tv_equal(l1, l5, true, false)) + eq(true, lib.tv_equal(l1, l6, true, false)) + eq(true, lib.tv_equal(l1, l7, true, false)) + eq(false, lib.tv_equal(l1, l8, true, false)) + eq(false, lib.tv_equal(l1, l9, true, false)) + end) + local function tv_equal(d1, d2, ic, recursive) + return lib.tv_equal(d1, d2, ic or false, recursive or false) + end + itp('works with dictionaries', function() + local nd = lua2typvalt(null_dict) + eq(true, tv_equal(nd, nd)) + alloc_log:check({}) + local d1 = lua2typvalt({}) + alloc_log:check({a.dict(d1.vval.v_dict)}) + eq(1, d1.vval.v_dict.dv_refcount) + eq(false, tv_equal(nd, d1)) + eq(false, tv_equal(d1, nd)) + eq(true, tv_equal(d1, d1)) + eq(1, d1.vval.v_dict.dv_refcount) + alloc_log:check({}) + local d_upper = lua2typvalt({a='TEST'}) + local dis_upper = dict_items(d_upper.vval.v_dict) + local d_lower = lua2typvalt({a='test'}) + local dis_lower = dict_items(d_lower.vval.v_dict) + local d_kupper_upper = lua2typvalt({A='TEST'}) + local dis_kupper_upper = dict_items(d_kupper_upper.vval.v_dict) + local d_kupper_lower = lua2typvalt({A='test'}) + local dis_kupper_lower = dict_items(d_kupper_lower.vval.v_dict) + alloc_log:clear_tmp_allocs() + alloc_log:check({ + a.dict(d_upper.vval.v_dict), + a.di(dis_upper.a), + a.str(dis_upper.a.di_tv.vval.v_string), + + a.dict(d_lower.vval.v_dict), + a.di(dis_lower.a), + a.str(dis_lower.a.di_tv.vval.v_string), + + a.dict(d_kupper_upper.vval.v_dict), + a.di(dis_kupper_upper.A), + a.str(dis_kupper_upper.A.di_tv.vval.v_string), + + a.dict(d_kupper_lower.vval.v_dict), + a.di(dis_kupper_lower.A), + a.str(dis_kupper_lower.A.di_tv.vval.v_string), + }) + eq(true, tv_equal(d_upper, d_upper)) + eq(true, tv_equal(d_upper, d_upper, true)) + eq(false, tv_equal(d_upper, d_lower, false)) + eq(true, tv_equal(d_upper, d_lower, true)) + eq(true, tv_equal(d_kupper_upper, d_kupper_lower, true)) + eq(false, tv_equal(d_kupper_upper, d_lower, true)) + eq(false, tv_equal(d_kupper_upper, d_upper, true)) + eq(true, tv_equal(d_upper, d_upper, true, true)) + alloc_log:check({}) + end) + end) + describe('check', function() + describe('str_or_nr()', function() + itp('works', function() + local tv = typvalt() + local mem = lib.xmalloc(1) + tv.vval.v_list = mem -- Should crash when actually accessed + alloc_log:clear() + for _, v in ipairs({ + {lib.VAR_NUMBER, nil}, + {lib.VAR_FLOAT, 'E805: Expected a Number or a String, Float found'}, + {lib.VAR_PARTIAL, 'E703: Expected a Number or a String, Funcref found'}, + {lib.VAR_FUNC, 'E703: Expected a Number or a String, Funcref found'}, + {lib.VAR_LIST, 'E745: Expected a Number or a String, List found'}, + {lib.VAR_DICT, 'E728: Expected a Number or a String, Dictionary found'}, + {lib.VAR_SPECIAL, 'E5300: Expected a Number or a String'}, + {lib.VAR_UNKNOWN, 'E685: Internal error: tv_check_str_or_nr(UNKNOWN)'}, + }) do + local typ = v[1] + local emsg = v[2] + local ret = true + if emsg then ret = false end + tv.v_type = typ + eq(ret, check_emsg(function() return lib.tv_check_str_or_nr(tv) end, emsg)) + if emsg then + alloc_log:clear() + else + alloc_log:check({}) + end + end + end) + end) + describe('num()', function() + itp('works', function() + local tv = typvalt() + local mem = lib.xmalloc(1) + tv.vval.v_list = mem -- Should crash when actually accessed + alloc_log:clear() + for _, v in ipairs({ + {lib.VAR_NUMBER, nil}, + {lib.VAR_FLOAT, 'E805: Using a Float as a Number'}, + {lib.VAR_PARTIAL, 'E703: Using a Funcref as a Number'}, + {lib.VAR_FUNC, 'E703: Using a Funcref as a Number'}, + {lib.VAR_LIST, 'E745: Using a List as a Number'}, + {lib.VAR_DICT, 'E728: Using a Dictionary as a Number'}, + {lib.VAR_SPECIAL, nil}, + {lib.VAR_UNKNOWN, 'E685: using an invalid value as a Number'}, + }) do + local typ = v[1] + local emsg = v[2] + local ret = true + if emsg then ret = false end + tv.v_type = typ + eq(ret, check_emsg(function() return lib.tv_check_num(tv) end, emsg)) + if emsg then + alloc_log:clear() + else + alloc_log:check({}) + end + end + end) + end) + describe('str()', function() + itp('works', function() + local tv = typvalt() + local mem = lib.xmalloc(1) + tv.vval.v_list = mem -- Should crash when actually accessed + alloc_log:clear() + for _, v in ipairs({ + {lib.VAR_NUMBER, nil}, + {lib.VAR_FLOAT, 'E806: using Float as a String'}, + {lib.VAR_PARTIAL, 'E729: using Funcref as a String'}, + {lib.VAR_FUNC, 'E729: using Funcref as a String'}, + {lib.VAR_LIST, 'E730: using List as a String'}, + {lib.VAR_DICT, 'E731: using Dictionary as a String'}, + {lib.VAR_SPECIAL, nil}, + {lib.VAR_UNKNOWN, 'E908: using an invalid value as a String'}, + }) do + local typ = v[1] + local emsg = v[2] + local ret = true + if emsg then ret = false end + tv.v_type = typ + eq(ret, check_emsg(function() return lib.tv_check_str(tv) end, emsg)) + if emsg then + alloc_log:clear() + else + alloc_log:check({}) + end + end + end) + end) + end) + describe('get', function() + describe('number()', function() + itp('works', function() + for _, v in ipairs({ + {lib.VAR_NUMBER, {v_number=42}, nil, 42}, + {lib.VAR_STRING, {v_string=to_cstr('100500')}, nil, 100500}, + {lib.VAR_FLOAT, {v_float=42.53}, 'E805: Using a Float as a Number', 0}, + {lib.VAR_PARTIAL, {v_partial=NULL}, 'E703: Using a Funcref as a Number', 0}, + {lib.VAR_FUNC, {v_string=NULL}, 'E703: Using a Funcref as a Number', 0}, + {lib.VAR_LIST, {v_list=NULL}, 'E745: Using a List as a Number', 0}, + {lib.VAR_DICT, {v_dict=NULL}, 'E728: Using a Dictionary as a Number', 0}, + {lib.VAR_SPECIAL, {v_special=lib.kSpecialVarNull}, nil, 0}, + {lib.VAR_SPECIAL, {v_special=lib.kSpecialVarTrue}, nil, 1}, + {lib.VAR_SPECIAL, {v_special=lib.kSpecialVarFalse}, nil, 0}, + {lib.VAR_UNKNOWN, nil, 'E685: Internal error: tv_get_number(UNKNOWN)', 0}, + }) do + -- Using to_cstr, cannot free with tv_clear + local tv = ffi.gc(typvalt(v[1], v[2]), nil) + alloc_log:check({}) + local emsg = v[3] + local ret = v[4] + eq(ret, check_emsg(function() return lib.tv_get_number(tv) end, emsg)) + if emsg then + alloc_log:clear() + else + alloc_log:check({}) + end + end + end) + end) + describe('number_chk()', function() + itp('works', function() + for _, v in ipairs({ + {lib.VAR_NUMBER, {v_number=42}, nil, 42}, + {lib.VAR_STRING, {v_string=to_cstr('100500')}, nil, 100500}, + {lib.VAR_FLOAT, {v_float=42.53}, 'E805: Using a Float as a Number', 0}, + {lib.VAR_PARTIAL, {v_partial=NULL}, 'E703: Using a Funcref as a Number', 0}, + {lib.VAR_FUNC, {v_string=NULL}, 'E703: Using a Funcref as a Number', 0}, + {lib.VAR_LIST, {v_list=NULL}, 'E745: Using a List as a Number', 0}, + {lib.VAR_DICT, {v_dict=NULL}, 'E728: Using a Dictionary as a Number', 0}, + {lib.VAR_SPECIAL, {v_special=lib.kSpecialVarNull}, nil, 0}, + {lib.VAR_SPECIAL, {v_special=lib.kSpecialVarTrue}, nil, 1}, + {lib.VAR_SPECIAL, {v_special=lib.kSpecialVarFalse}, nil, 0}, + {lib.VAR_UNKNOWN, nil, 'E685: Internal error: tv_get_number(UNKNOWN)', 0}, + }) do + -- Using to_cstr, cannot free with tv_clear + local tv = ffi.gc(typvalt(v[1], v[2]), nil) + alloc_log:check({}) + local emsg = v[3] + local ret = {v[4], not not emsg} + eq(ret, check_emsg(function() + local err = ffi.new('bool[1]', {false}) + local res = lib.tv_get_number_chk(tv, err) + return {res, err[0]} + end, emsg)) + if emsg then + alloc_log:clear() + else + alloc_log:check({}) + end + end + end) + end) + describe('lnum()', function() + itp('works', function() + for _, v in ipairs({ + {lib.VAR_NUMBER, {v_number=42}, nil, 42}, + {lib.VAR_STRING, {v_string=to_cstr('100500')}, nil, 100500}, + {lib.VAR_STRING, {v_string=to_cstr('.')}, nil, 46}, + {lib.VAR_FLOAT, {v_float=42.53}, 'E805: Using a Float as a Number', -1}, + {lib.VAR_PARTIAL, {v_partial=NULL}, 'E703: Using a Funcref as a Number', -1}, + {lib.VAR_FUNC, {v_string=NULL}, 'E703: Using a Funcref as a Number', -1}, + {lib.VAR_LIST, {v_list=NULL}, 'E745: Using a List as a Number', -1}, + {lib.VAR_DICT, {v_dict=NULL}, 'E728: Using a Dictionary as a Number', -1}, + {lib.VAR_SPECIAL, {v_special=lib.kSpecialVarNull}, nil, 0}, + {lib.VAR_SPECIAL, {v_special=lib.kSpecialVarTrue}, nil, 1}, + {lib.VAR_SPECIAL, {v_special=lib.kSpecialVarFalse}, nil, 0}, + {lib.VAR_UNKNOWN, nil, 'E685: Internal error: tv_get_number(UNKNOWN)', -1}, + }) do + lib.curwin.w_cursor.lnum = 46 + -- Using to_cstr, cannot free with tv_clear + local tv = ffi.gc(typvalt(v[1], v[2]), nil) + alloc_log:check({}) + local emsg = v[3] + local ret = v[4] + eq(ret, check_emsg(function() return lib.tv_get_lnum(tv) end, emsg)) + if emsg then + alloc_log:clear() + else + alloc_log:check({}) + end + end + end) + end) + describe('float()', function() + itp('works', function() + for _, v in ipairs({ + {lib.VAR_NUMBER, {v_number=42}, nil, 42}, + {lib.VAR_STRING, {v_string=to_cstr('100500')}, 'E892: Using a String as a Float', 0}, + {lib.VAR_FLOAT, {v_float=42.53}, nil, 42.53}, + {lib.VAR_PARTIAL, {v_partial=NULL}, 'E891: Using a Funcref as a Float', 0}, + {lib.VAR_FUNC, {v_string=NULL}, 'E891: Using a Funcref as a Float', 0}, + {lib.VAR_LIST, {v_list=NULL}, 'E893: Using a List as a Float', 0}, + {lib.VAR_DICT, {v_dict=NULL}, 'E894: Using a Dictionary as a Float', 0}, + {lib.VAR_SPECIAL, {v_special=lib.kSpecialVarNull}, 'E907: Using a special value as a Float', 0}, + {lib.VAR_SPECIAL, {v_special=lib.kSpecialVarTrue}, 'E907: Using a special value as a Float', 0}, + {lib.VAR_SPECIAL, {v_special=lib.kSpecialVarFalse}, 'E907: Using a special value as a Float', 0}, + {lib.VAR_UNKNOWN, nil, 'E685: Internal error: tv_get_float(UNKNOWN)', 0}, + }) do + -- Using to_cstr, cannot free with tv_clear + local tv = ffi.gc(typvalt(v[1], v[2]), nil) + alloc_log:check({}) + local emsg = v[3] + local ret = v[4] + eq(ret, check_emsg(function() return lib.tv_get_float(tv) end, emsg)) + if emsg then + alloc_log:clear() + else + alloc_log:check({}) + end + end + end) + end) + describe('string()', function() + itp('works', function() + local buf = lib.tv_get_string(lua2typvalt(int(1))) + local buf_chk = lib.tv_get_string_chk(lua2typvalt(int(1))) + neq(buf, buf_chk) + for _, v in ipairs({ + {lib.VAR_NUMBER, {v_number=42}, nil, '42'}, + {lib.VAR_STRING, {v_string=to_cstr('100500')}, nil, '100500'}, + {lib.VAR_FLOAT, {v_float=42.53}, 'E806: using Float as a String', ''}, + {lib.VAR_PARTIAL, {v_partial=NULL}, 'E729: using Funcref as a String', ''}, + {lib.VAR_FUNC, {v_string=NULL}, 'E729: using Funcref as a String', ''}, + {lib.VAR_LIST, {v_list=NULL}, 'E730: using List as a String', ''}, + {lib.VAR_DICT, {v_dict=NULL}, 'E731: using Dictionary as a String', ''}, + {lib.VAR_SPECIAL, {v_special=lib.kSpecialVarNull}, nil, 'null'}, + {lib.VAR_SPECIAL, {v_special=lib.kSpecialVarTrue}, nil, 'true'}, + {lib.VAR_SPECIAL, {v_special=lib.kSpecialVarFalse}, nil, 'false'}, + {lib.VAR_UNKNOWN, nil, 'E908: using an invalid value as a String', ''}, + }) do + -- Using to_cstr in place of Neovim allocated string, cannot + -- tv_clear() that. + local tv = ffi.gc(typvalt(v[1], v[2]), nil) + alloc_log:check({}) + local emsg = v[3] + local ret = v[4] + eq(ret, check_emsg(function() + local res = lib.tv_get_string(tv) + if tv.v_type == lib.VAR_NUMBER or tv.v_type == lib.VAR_SPECIAL then + eq(buf, res) + else + neq(buf, res) + end + if res ~= nil then + return ffi.string(res) + else + return nil + end + end, emsg)) + if emsg then + alloc_log:clear() + else + alloc_log:check({}) + end + end + end) + end) + describe('string_chk()', function() + itp('works', function() + local buf = lib.tv_get_string_chk(lua2typvalt(int(1))) + for _, v in ipairs({ + {lib.VAR_NUMBER, {v_number=42}, nil, '42'}, + {lib.VAR_STRING, {v_string=to_cstr('100500')}, nil, '100500'}, + {lib.VAR_FLOAT, {v_float=42.53}, 'E806: using Float as a String', nil}, + {lib.VAR_PARTIAL, {v_partial=NULL}, 'E729: using Funcref as a String', nil}, + {lib.VAR_FUNC, {v_string=NULL}, 'E729: using Funcref as a String', nil}, + {lib.VAR_LIST, {v_list=NULL}, 'E730: using List as a String', nil}, + {lib.VAR_DICT, {v_dict=NULL}, 'E731: using Dictionary as a String', nil}, + {lib.VAR_SPECIAL, {v_special=lib.kSpecialVarNull}, nil, 'null'}, + {lib.VAR_SPECIAL, {v_special=lib.kSpecialVarTrue}, nil, 'true'}, + {lib.VAR_SPECIAL, {v_special=lib.kSpecialVarFalse}, nil, 'false'}, + {lib.VAR_UNKNOWN, nil, 'E908: using an invalid value as a String', nil}, + }) do + -- Using to_cstr, cannot free with tv_clear + local tv = ffi.gc(typvalt(v[1], v[2]), nil) + alloc_log:check({}) + local emsg = v[3] + local ret = v[4] + eq(ret, check_emsg(function() + local res = lib.tv_get_string_chk(tv) + if tv.v_type == lib.VAR_NUMBER or tv.v_type == lib.VAR_SPECIAL then + eq(buf, res) + else + neq(buf, res) + end + if res ~= nil then + return ffi.string(res) + else + return nil + end + end, emsg)) + if emsg then + alloc_log:clear() + else + alloc_log:check({}) + end + end + end) + end) + describe('string_buf()', function() + itp('works', function() + for _, v in ipairs({ + {lib.VAR_NUMBER, {v_number=42}, nil, '42'}, + {lib.VAR_STRING, {v_string=to_cstr('100500')}, nil, '100500'}, + {lib.VAR_FLOAT, {v_float=42.53}, 'E806: using Float as a String', ''}, + {lib.VAR_PARTIAL, {v_partial=NULL}, 'E729: using Funcref as a String', ''}, + {lib.VAR_FUNC, {v_string=NULL}, 'E729: using Funcref as a String', ''}, + {lib.VAR_LIST, {v_list=NULL}, 'E730: using List as a String', ''}, + {lib.VAR_DICT, {v_dict=NULL}, 'E731: using Dictionary as a String', ''}, + {lib.VAR_SPECIAL, {v_special=lib.kSpecialVarNull}, nil, 'null'}, + {lib.VAR_SPECIAL, {v_special=lib.kSpecialVarTrue}, nil, 'true'}, + {lib.VAR_SPECIAL, {v_special=lib.kSpecialVarFalse}, nil, 'false'}, + {lib.VAR_UNKNOWN, nil, 'E908: using an invalid value as a String', ''}, + }) do + -- Using to_cstr, cannot free with tv_clear + local tv = ffi.gc(typvalt(v[1], v[2]), nil) + alloc_log:check({}) + local emsg = v[3] + local ret = v[4] + eq(ret, check_emsg(function() + local buf = ffi.new('char[?]', lib.NUMBUFLEN, {0}) + local res = lib.tv_get_string_buf(tv, buf) + if tv.v_type == lib.VAR_NUMBER or tv.v_type == lib.VAR_SPECIAL then + eq(buf, res) + else + neq(buf, res) + end + if res ~= nil then + return ffi.string(res) + else + return nil + end + end, emsg)) + if emsg then + alloc_log:clear() + else + alloc_log:check({}) + end + end + end) + end) + describe('string_buf_chk()', function() + itp('works', function() + for _, v in ipairs({ + {lib.VAR_NUMBER, {v_number=42}, nil, '42'}, + {lib.VAR_STRING, {v_string=to_cstr('100500')}, nil, '100500'}, + {lib.VAR_FLOAT, {v_float=42.53}, 'E806: using Float as a String', nil}, + {lib.VAR_PARTIAL, {v_partial=NULL}, 'E729: using Funcref as a String', nil}, + {lib.VAR_FUNC, {v_string=NULL}, 'E729: using Funcref as a String', nil}, + {lib.VAR_LIST, {v_list=NULL}, 'E730: using List as a String', nil}, + {lib.VAR_DICT, {v_dict=NULL}, 'E731: using Dictionary as a String', nil}, + {lib.VAR_SPECIAL, {v_special=lib.kSpecialVarNull}, nil, 'null'}, + {lib.VAR_SPECIAL, {v_special=lib.kSpecialVarTrue}, nil, 'true'}, + {lib.VAR_SPECIAL, {v_special=lib.kSpecialVarFalse}, nil, 'false'}, + {lib.VAR_UNKNOWN, nil, 'E908: using an invalid value as a String', nil}, + }) do + -- Using to_cstr, cannot free with tv_clear + local tv = ffi.gc(typvalt(v[1], v[2]), nil) + alloc_log:check({}) + local emsg = v[3] + local ret = v[4] + eq(ret, check_emsg(function() + local buf = ffi.new('char[?]', lib.NUMBUFLEN, {0}) + local res = lib.tv_get_string_buf_chk(tv, buf) + if tv.v_type == lib.VAR_NUMBER or tv.v_type == lib.VAR_SPECIAL then + eq(buf, res) + else + neq(buf, res) + end + if res ~= nil then + return ffi.string(res) + else + return nil + end + end, emsg)) + if emsg then + alloc_log:clear() + else + alloc_log:check({}) + end + end + end) + end) + end) + end) +end) diff --git a/test/unit/fileio_spec.lua b/test/unit/fileio_spec.lua index 3e3c36617d..066d013b19 100644 --- a/test/unit/fileio_spec.lua +++ b/test/unit/fileio_spec.lua @@ -1,4 +1,5 @@ -local helpers = require("test.unit.helpers") +local helpers = require("test.unit.helpers")(after_each) +local itp = helpers.gen_itp(it) --{:cimport, :internalize, :eq, :neq, :ffi, :lib, :cstr, :to_cstr} = require 'test.unit.helpers' local eq = helpers.eq @@ -16,67 +17,67 @@ describe('file_pat functions', function() return ffi.string(res) end - it('returns ^path$ regex for literal path input', function() + itp('returns ^path$ regex for literal path input', function() eq( '^path$', file_pat_to_reg_pat('path')) end) - it('does not prepend ^ when there is a starting glob (*)', function() + itp('does not prepend ^ when there is a starting glob (*)', function() eq('path$', file_pat_to_reg_pat('*path')) end) - it('does not append $ when there is an ending glob (*)', function() + itp('does not append $ when there is an ending glob (*)', function() eq('^path', file_pat_to_reg_pat('path*')) end) - it('does not include ^ or $ when surrounded by globs (*)', function() + itp('does not include ^ or $ when surrounded by globs (*)', function() eq('path', file_pat_to_reg_pat('*path*')) end) - it('replaces the bash any character (?) with the regex any character (.)', function() + itp('replaces the bash any character (?) with the regex any character (.)', function() eq('^foo.bar$', file_pat_to_reg_pat('foo?bar')) end) - it('replaces a glob (*) in the middle of a path with regex multiple any character (.*)', + itp('replaces a glob (*) in the middle of a path with regex multiple any character (.*)', function() eq('^foo.*bar$', file_pat_to_reg_pat('foo*bar')) end) - it([[unescapes \? to ?]], function() + itp([[unescapes \? to ?]], function() eq('^foo?bar$', file_pat_to_reg_pat([[foo\?bar]])) end) - it([[unescapes \% to %]], function() + itp([[unescapes \% to %]], function() eq('^foo%bar$', file_pat_to_reg_pat([[foo\%bar]])) end) - it([[unescapes \, to ,]], function() + itp([[unescapes \, to ,]], function() eq('^foo,bar$', file_pat_to_reg_pat([[foo\,bar]])) end) - it([[unescapes '\ ' to ' ']], function() + itp([[unescapes '\ ' to ' ']], function() eq('^foo bar$', file_pat_to_reg_pat([[foo\ bar]])) end) - it([[escapes . to \.]], function() + itp([[escapes . to \.]], function() eq([[^foo\.bar$]], file_pat_to_reg_pat('foo.bar')) end) - it('Converts bash brace expansion {a,b} to regex options (a|b)', function() + itp('Converts bash brace expansion {a,b} to regex options (a|b)', function() eq([[^foo\(bar\|baz\)$]], file_pat_to_reg_pat('foo{bar,baz}')) end) - it('Collapses multiple consecutive * into a single character', function() + itp('Collapses multiple consecutive * into a single character', function() eq([[^foo.*bar$]], file_pat_to_reg_pat('foo*******bar')) eq([[foobar$]], file_pat_to_reg_pat('********foobar')) eq([[^foobar]], file_pat_to_reg_pat('foobar********')) end) - it('Does not escape ^', function() + itp('Does not escape ^', function() eq([[^^blah$]], file_pat_to_reg_pat('^blah')) eq([[^foo^bar$]], file_pat_to_reg_pat('foo^bar')) end) - it('Does not escape $', function() + itp('Does not escape $', function() eq([[^blah$$]], file_pat_to_reg_pat('blah$')) eq([[^foo$bar$]], file_pat_to_reg_pat('foo$bar')) end) diff --git a/test/unit/fixtures/multiqueue.c b/test/unit/fixtures/multiqueue.c index da63e55919..a8dca0a844 100644 --- a/test/unit/fixtures/multiqueue.c +++ b/test/unit/fixtures/multiqueue.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #include <string.h> #include <stdlib.h> #include "nvim/event/multiqueue.h" diff --git a/test/unit/fixtures/posix.h b/test/unit/fixtures/posix.h new file mode 100644 index 0000000000..f6f24cd9dc --- /dev/null +++ b/test/unit/fixtures/posix.h @@ -0,0 +1,11 @@ +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <sys/wait.h> +#include <stdlib.h> + +enum { + kPOSIXErrnoEINTR = EINTR, + kPOSIXErrnoECHILD = ECHILD, + kPOSIXWaitWUNTRACED = WUNTRACED, +}; diff --git a/test/unit/fixtures/rbuffer.c b/test/unit/fixtures/rbuffer.c index d587d6b054..3f4062fa18 100644 --- a/test/unit/fixtures/rbuffer.c +++ b/test/unit/fixtures/rbuffer.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #include "nvim/rbuffer.h" #include "rbuffer.h" diff --git a/test/unit/garray_spec.lua b/test/unit/garray_spec.lua index 422ef7b36a..28df8a6e3f 100644 --- a/test/unit/garray_spec.lua +++ b/test/unit/garray_spec.lua @@ -1,4 +1,5 @@ -local helpers = require("test.unit.helpers") +local helpers = require("test.unit.helpers")(after_each) +local itp = helpers.gen_itp(it) local cimport = helpers.cimport local internalize = helpers.internalize @@ -8,7 +9,7 @@ local ffi = helpers.ffi local to_cstr = helpers.to_cstr local NULL = helpers.NULL -local garray = cimport('stdlib.h', './src/nvim/garray.h') +local garray = cimport('./src/nvim/garray.h') local itemsize = 14 local growsize = 95 @@ -156,7 +157,7 @@ local ga_append_ints = function(garr, ...) end -- enhanced constructors -local garray_ctype = ffi.typeof('garray_T[1]') +local garray_ctype = function(...) return ffi.typeof('garray_T[1]')(...) end local new_garray = function() local garr = garray_ctype() return ffi.gc(garr, ga_clear) @@ -183,7 +184,7 @@ end describe('garray', function() describe('ga_init', function() - it('initializes the values of the garray', function() + itp('initializes the values of the garray', function() local garr = new_garray() ga_init(garr, itemsize, growsize) eq(0, ga_len(garr)) @@ -204,7 +205,7 @@ describe('garray', function() return garr end - it('grows by growsize items if num < growsize', function() + itp('grows by growsize items if num < growsize', function() itemsize = 16 growsize = 4 local grow_by = growsize - 1 @@ -213,7 +214,7 @@ describe('garray', function() eq(growsize, ga_maxlen(garr)) -- we requested LESS than growsize, so... end) - it('grows by num items if num > growsize', function() + itp('grows by num items if num > growsize', function() itemsize = 16 growsize = 4 local grow_by = growsize + 1 @@ -222,7 +223,7 @@ describe('garray', function() eq(grow_by, ga_maxlen(garr)) -- we requested MORE than growsize, so... end) - it('does not grow when nothing is requested', function() + itp('does not grow when nothing is requested', function() local garr = new_and_grow(16, 4, 0) eq(NULL, ga_data(garr)) eq(0, ga_maxlen(garr)) @@ -230,7 +231,7 @@ describe('garray', function() end) describe('ga_clear', function() - it('clears an already allocated array', function() + itp('clears an already allocated array', function() -- allocate and scramble an array local garr = garray_ctype() ga_init(garr, itemsize, growsize) @@ -247,7 +248,7 @@ describe('garray', function() end) describe('ga_append', function() - it('can append bytes', function() + itp('can append bytes', function() -- this is the actual ga_append, the others are just emulated lua -- versions local garr = new_garray() @@ -262,7 +263,7 @@ describe('garray', function() eq('hello', ffi.string(bytes)) end) - it('can append integers', function() + itp('can append integers', function() local garr = new_garray() ga_init(garr, ffi.sizeof("int"), 1) local input = { @@ -279,7 +280,7 @@ describe('garray', function() end end) - it('can append strings to a growing array of strings', function() + itp('can append strings to a growing array of strings', function() local garr = new_string_garray() local input = { "some", @@ -298,7 +299,7 @@ describe('garray', function() end) describe('ga_concat', function() - it('concatenates the parameter to the growing byte array', function() + itp('concatenates the parameter to the growing byte array', function() local garr = new_garray() ga_init(garr, ffi.sizeof("char"), 1) local str = "ohwellโโ" @@ -329,11 +330,11 @@ describe('garray', function() end describe('ga_concat_strings', function() - it('returns an empty string when concatenating an empty array', function() + itp('returns an empty string when concatenating an empty array', function() test_concat_fn({ }, ga_concat_strings) end) - it('can concatenate a non-empty array', function() + itp('can concatenate a non-empty array', function() test_concat_fn({ 'oh', 'my', @@ -343,11 +344,11 @@ describe('garray', function() end) describe('ga_concat_strings_sep', function() - it('returns an empty string when concatenating an empty array', function() + itp('returns an empty string when concatenating an empty array', function() test_concat_fn({ }, ga_concat_strings_sep, '---') end) - it('can concatenate a non-empty array', function() + itp('can concatenate a non-empty array', function() local sep = '-โโ-' test_concat_fn({ 'oh', @@ -358,7 +359,7 @@ describe('garray', function() end) describe('ga_remove_duplicate_strings', function() - it('sorts and removes duplicate strings', function() + itp('sorts and removes duplicate strings', function() local garr = new_string_garray() local input = { 'ccc', diff --git a/test/unit/helpers.lua b/test/unit/helpers.lua index 1bfdd32739..4b9f185156 100644 --- a/test/unit/helpers.lua +++ b/test/unit/helpers.lua @@ -4,8 +4,16 @@ local Set = require('test.unit.set') local Preprocess = require('test.unit.preprocess') local Paths = require('test.config.paths') local global_helpers = require('test.helpers') +local assert = require('luassert') +local say = require('say') +local posix = nil +local syscall = nil + +local check_cores = global_helpers.check_cores +local dedent = global_helpers.dedent local neq = global_helpers.neq +local map = global_helpers.map local eq = global_helpers.eq local ok = global_helpers.ok @@ -15,20 +23,110 @@ local NULL = ffi.cast('void*', 0) local OK = 1 local FAIL = 0 +local cimport + -- add some standard header locations for _, p in ipairs(Paths.include_paths) do Preprocess.add_to_include_path(p) end --- load neovim shared library -local libnvim = ffi.load(Paths.test_libnvim_path) +local child_pid = nil +local function only_separate(func) + return function(...) + if child_pid ~= 0 then + error('This function must be run in a separate process only') + end + return func(...) + end +end +local child_calls_init = {} +local child_calls_mod = nil +local child_calls_mod_once = nil +local function child_call(func, ret) + return function(...) + local child_calls = child_calls_mod or child_calls_init + if child_pid ~= 0 then + child_calls[#child_calls + 1] = {func=func, args={...}} + return ret + else + return func(...) + end + end +end + +-- Run some code at the start of the child process, before running the test +-- itself. Is supposed to be run in `before_each`. +local function child_call_once(func, ...) + if child_pid ~= 0 then + child_calls_mod_once[#child_calls_mod_once + 1] = { + func=func, args={...}} + else + func(...) + end +end + +local child_cleanups_mod_once = nil + +-- Run some code at the end of the child process, before exiting. Is supposed to +-- be run in `before_each` because `after_each` is run after child has exited. +local function child_cleanup_once(func, ...) + local child_cleanups = child_cleanups_mod_once + if child_pid ~= 0 then + child_cleanups[#child_cleanups + 1] = {func=func, args={...}} + else + func(...) + end +end + +local libnvim = nil + +local lib = setmetatable({}, { + __index = only_separate(function(_, idx) + return libnvim[idx] + end), + __newindex = child_call(function(_, idx, val) + libnvim[idx] = val + end), +}) + +local init = only_separate(function() + -- load neovim shared library + libnvim = ffi.load(Paths.test_libnvim_path) + for _, c in ipairs(child_calls_init) do + c.func(unpack(c.args)) + end + libnvim.time_init() + libnvim.early_init() + libnvim.event_init() + if child_calls_mod then + for _, c in ipairs(child_calls_mod) do + c.func(unpack(c.args)) + end + end + if child_calls_mod_once then + for _, c in ipairs(child_calls_mod_once) do + c.func(unpack(c.args)) + end + child_calls_mod_once = nil + end +end) + +local deinit = only_separate(function() + if child_cleanups_mod_once then + for _, c in ipairs(child_cleanups_mod_once) do + c.func(unpack(c.args)) + end + child_cleanups_mod_once = nil + end +end) local function trim(s) return s:match('^%s*(.*%S)') or '' end -- a Set that keeps around the lines we've already seen -local cdefs = Set:new() +local cdefs_init = Set:new() +local cdefs_mod = nil local imported = Set:new() local pragma_pack_id = 1 @@ -51,77 +149,120 @@ local function filter_complex_blocks(body) return table.concat(result, "\n") end -local previous_defines = '' --- use this helper to import C files, you can pass multiple paths at once, --- this helper will return the C namespace of the nvim library. -local function cimport(...) - local paths = {} - local args = {...} +local cdef = ffi.cdef - -- filter out paths we've already imported - for _,path in pairs(args) do - if path ~= nil and not imported:contains(path) then - paths[#paths + 1] = path - end - end +local cimportstr - for _,path in pairs(paths) do - imported:add(path) - end +local previous_defines_init = '' +local preprocess_cache_init = {} +local previous_defines_mod = '' +local preprocess_cache_mod = nil - if #paths == 0 then - return libnvim - end +local function is_child_cdefs() + return (os.getenv('NVIM_TEST_MAIN_CDEFS') ~= '1') +end - local body - body, previous_defines = Preprocess.preprocess(previous_defines, unpack(paths)) +-- use this helper to import C files, you can pass multiple paths at once, +-- this helper will return the C namespace of the nvim library. +cimport = function(...) + local previous_defines, preprocess_cache, cdefs + if is_child_cdefs() and preprocess_cache_mod then + preprocess_cache = preprocess_cache_mod + previous_defines = previous_defines_mod + cdefs = cdefs_mod + else + preprocess_cache = preprocess_cache_init + previous_defines = previous_defines_init + cdefs = cdefs_init + end + for _, path in ipairs({...}) do + if not (path:sub(1, 1) == '/' or path:sub(1, 1) == '.' + or path:sub(2, 2) == ':') then + path = './' .. path + end + if not preprocess_cache[path] then + local body + body, previous_defines = Preprocess.preprocess(previous_defines, path) + -- format it (so that the lines are "unique" statements), also filter out + -- Objective-C blocks + if os.getenv('NVIM_TEST_PRINT_I') == '1' then + local lnum = 0 + for line in body:gmatch('[^\n]+') do + lnum = lnum + 1 + print(lnum, line) + end + end + body = formatc(body) + body = filter_complex_blocks(body) + -- add the formatted lines to a set + local new_cdefs = Set:new() + for line in body:gmatch("[^\r\n]+") do + line = trim(line) + -- give each #pragma pack an unique id, so that they don't get removed + -- if they are inserted into the set + -- (they are needed in the right order with the struct definitions, + -- otherwise luajit has wrong memory layouts for the sturcts) + if line:match("#pragma%s+pack") then + line = line .. " // " .. pragma_pack_id + pragma_pack_id = pragma_pack_id + 1 + end + new_cdefs:add(line) + end - -- format it (so that the lines are "unique" statements), also filter out - -- Objective-C blocks - body = formatc(body) - body = filter_complex_blocks(body) + -- subtract the lines we've already imported from the new lines, then add + -- the new unique lines to the old lines (so they won't be imported again) + new_cdefs:diff(cdefs) + cdefs:union(new_cdefs) + -- request a sorted version of the new lines (same relative order as the + -- original preprocessed file) and feed that to the LuaJIT ffi + local new_lines = new_cdefs:to_table() + if os.getenv('NVIM_TEST_PRINT_CDEF') == '1' then + for lnum, line in ipairs(new_lines) do + print(lnum, line) + end + end + body = table.concat(new_lines, '\n') - -- add the formatted lines to a set - local new_cdefs = Set:new() - for line in body:gmatch("[^\r\n]+") do - line = trim(line) - -- give each #pragma pack an unique id, so that they don't get removed - -- if they are inserted into the set - -- (they are needed in the right order with the struct definitions, - -- otherwise luajit has wrong memory layouts for the sturcts) - if line:match("#pragma%s+pack") then - line = line .. " // " .. pragma_pack_id - pragma_pack_id = pragma_pack_id + 1 + preprocess_cache[path] = body end - new_cdefs:add(line) + cimportstr(preprocess_cache, path) end + return lib +end - -- subtract the lines we've already imported from the new lines, then add - -- the new unique lines to the old lines (so they won't be imported again) - new_cdefs:diff(cdefs) - cdefs:union(new_cdefs) - - if new_cdefs:size() == 0 then - -- if there's no new lines, just return - return libnvim +local cimport_immediate = function(...) + local saved_pid = child_pid + child_pid = 0 + local err, emsg = pcall(cimport, ...) + child_pid = saved_pid + if not err then + emsg = tostring(emsg) + io.stderr:write(emsg .. '\n') + assert(false) + else + return lib end +end - -- request a sorted version of the new lines (same relative order as the - -- original preprocessed file) and feed that to the LuaJIT ffi - local new_lines = new_cdefs:to_table() - if os.getenv('NVIM_TEST_PRINT_CDEF') == '1' then - for lnum, line in ipairs(new_lines) do - print(lnum, line) - end +local function _cimportstr(preprocess_cache, path) + if imported:contains(path) then + return lib end - ffi.cdef(table.concat(new_lines, "\n")) + local body = preprocess_cache[path] + if body == '' then + return lib + end + cdef(body) + imported:add(path) - return libnvim + return lib end -local function cppimport(path) - return cimport(Paths.test_include_path .. '/' .. path) +if is_child_cdefs() then + cimportstr = child_call(_cimportstr, lib) +else + cimportstr = _cimportstr end local function alloc_log_new() @@ -134,9 +275,12 @@ local function alloc_log_new() local allocator_functions = {'malloc', 'free', 'calloc', 'realloc'} function log:save_original_functions() for _, funcname in ipairs(allocator_functions) do - self.original_functions[funcname] = self.lib['mem_' .. funcname] + if not self.original_functions[funcname] then + self.original_functions[funcname] = self.lib['mem_' .. funcname] + end end end + log.save_original_functions = child_call(log.save_original_functions) function log:set_mocks() for _, k in ipairs(allocator_functions) do do @@ -163,6 +307,7 @@ local function alloc_log_new() end end end + log.set_mocks = child_call(log.set_mocks) function log:clear() self.log = {} end @@ -170,23 +315,52 @@ local function alloc_log_new() eq(exp, self.log) self:clear() end - function log:restore_original_functions() - for k, v in pairs(self.original_functions) do - self.lib['mem_' .. k] = v + function log:clear_tmp_allocs() + local toremove = {} + local allocs = {} + for i, v in ipairs(self.log) do + if v.func == 'malloc' or v.func == 'calloc' then + allocs[tostring(v.ret)] = i + elseif v.func == 'realloc' or v.func == 'free' then + if allocs[tostring(v.args[1])] then + toremove[#toremove + 1] = allocs[tostring(v.args[1])] + if v.func == 'free' then + toremove[#toremove + 1] = i + end + end + if v.func == 'realloc' then + allocs[tostring(v.ret)] = i + end + end + end + table.sort(toremove) + for i = #toremove,1,-1 do + table.remove(self.log, toremove[i]) end end - function log:before_each() + function log:restore_original_functions() + -- Do nothing: set mocks live in a separate process + return + --[[ + [ for k, v in pairs(self.original_functions) do + [ self.lib['mem_' .. k] = v + [ end + ]] + end + function log:setup() log:save_original_functions() log:set_mocks() end + function log:before_each() + return + end function log:after_each() log:restore_original_functions() end + log:setup() return log end -cimport('./src/nvim/types.h') - -- take a pointer to a C-allocated string and return an interned -- version while also freeing the memory local function internalize(cdata, len) @@ -199,17 +373,387 @@ local function to_cstr(string) return cstr(#string + 1, string) end --- initialize some global variables, this is still necessary to unit test --- functions that rely on global state. -do - local main = cimport('./src/nvim/main.h') - local time = cimport('./src/nvim/os/time.h') - time.time_init() - main.early_init() - main.event_init() +local sc + +if posix ~= nil then + sc = { + fork = posix.fork, + pipe = posix.pipe, + read = posix.read, + write = posix.write, + close = posix.close, + wait = posix.wait, + exit = posix._exit, + } +elseif syscall ~= nil then + sc = { + fork = syscall.fork, + pipe = function() + local ret = {syscall.pipe()} + return ret[3], ret[4] + end, + read = function(rd, len) + return rd:read(nil, len) + end, + write = function(wr, s) + return wr:write(s) + end, + close = function(p) + return p:close() + end, + wait = syscall.wait, + exit = syscall.exit, + } +else + cimport_immediate('./test/unit/fixtures/posix.h') + sc = { + fork = function() + return tonumber(ffi.C.fork()) + end, + pipe = function() + local ret = ffi.new('int[2]', {-1, -1}) + ffi.errno(0) + local res = ffi.C.pipe(ret) + if (res ~= 0) then + local err = ffi.errno(0) + assert(res == 0, ("pipe() error: %u: %s"):format( + err, ffi.string(ffi.C.strerror(err)))) + end + assert(ret[0] ~= -1 and ret[1] ~= -1) + return ret[0], ret[1] + end, + read = function(rd, len) + local ret = ffi.new('char[?]', len, {0}) + local total_bytes_read = 0 + ffi.errno(0) + while total_bytes_read < len do + local bytes_read = tonumber(ffi.C.read( + rd, + ffi.cast('void*', ret + total_bytes_read), + len - total_bytes_read)) + if bytes_read == -1 then + local err = ffi.errno(0) + if err ~= ffi.C.kPOSIXErrnoEINTR then + assert(false, ("read() error: %u: %s"):format( + err, ffi.string(ffi.C.strerror(err)))) + end + elseif bytes_read == 0 then + break + else + total_bytes_read = total_bytes_read + bytes_read + end + end + return ffi.string(ret, total_bytes_read) + end, + write = function(wr, s) + local wbuf = to_cstr(s) + local total_bytes_written = 0 + ffi.errno(0) + while total_bytes_written < #s do + local bytes_written = tonumber(ffi.C.write( + wr, + ffi.cast('void*', wbuf + total_bytes_written), + #s - total_bytes_written)) + if bytes_written == -1 then + local err = ffi.errno(0) + if err ~= ffi.C.kPOSIXErrnoEINTR then + assert(false, ("write() error: %u: %s"):format( + err, ffi.string(ffi.C.strerror(err)))) + end + elseif bytes_written == 0 then + break + else + total_bytes_written = total_bytes_written + bytes_written + end + end + return total_bytes_written + end, + close = ffi.C.close, + wait = function(pid) + ffi.errno(0) + while true do + local r = ffi.C.waitpid(pid, nil, ffi.C.kPOSIXWaitWUNTRACED) + if r == -1 then + local err = ffi.errno(0) + if err == ffi.C.kPOSIXErrnoECHILD then + break + elseif err ~= ffi.C.kPOSIXErrnoEINTR then + assert(false, ("waitpid() error: %u: %s"):format( + err, ffi.string(ffi.C.strerror(err)))) + end + else + assert(r == pid) + end + end + end, + exit = ffi.C._exit, + } +end + +local function format_list(lst) + local ret = '' + for _, v in ipairs(lst) do + if ret ~= '' then ret = ret .. ', ' end + ret = ret .. assert:format({v, n=1})[1] + end + return ret +end + +if os.getenv('NVIM_TEST_PRINT_SYSCALLS') == '1' then + for k_, v_ in pairs(sc) do + (function(k, v) + sc[k] = function(...) + local rets = {v(...)} + io.stderr:write(('%s(%s) = %s\n'):format(k, format_list({...}), + format_list(rets))) + return unpack(rets) + end + end)(k_, v_) + end +end + +local function just_fail(_) + return false +end +say:set('assertion.just_fail.positive', '%s') +say:set('assertion.just_fail.negative', '%s') +assert:register('assertion', 'just_fail', just_fail, + 'assertion.just_fail.positive', + 'assertion.just_fail.negative') + +local hook_fnamelen = 30 +local hook_sfnamelen = 30 +local hook_numlen = 5 +local hook_msglen = 1 + 1 + 1 + (1 + hook_fnamelen) + (1 + hook_sfnamelen) + (1 + hook_numlen) + 1 + +local tracehelp = dedent([[ + โ Trace type: _r_eturn from function , function _c_all, _l_ine executed, + โ _t_ail return, _C_ount (should not actually appear), + โ _s_aved from previous run for reference. + โโ Function type: _L_ua function, _C_ function, _m_ain part of chunk, + โโ function that did _t_ail call. + โโโ Function name type: _g_lobal, _l_ocal, _m_ethod, _f_ield, _u_pvalue, + โโโ space for unknown. + โโโ โ Source file name โ Function name โ Line + โโโ โ (trunc to 30 bytes, no .lua) โ (truncated to last 30 bytes) โ number + CWN SSSSSSSSSSSSSSSSSSSSSSSSSSSSSS:FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF:LLLLL\n +]]) + +local function child_sethook(wr) + local trace_level = os.getenv('NVIM_TEST_TRACE_LEVEL') + if not trace_level or trace_level == '' then + trace_level = 1 + else + trace_level = tonumber(trace_level) + end + if trace_level <= 0 then + return + end + local trace_only_c = trace_level <= 1 + local prev_info, prev_reason, prev_lnum + local function hook(reason, lnum, use_prev) + local info = nil + if use_prev then + info = prev_info + elseif reason ~= 'tail return' then -- tail return + info = debug.getinfo(2, 'nSl') + end + + if trace_only_c and (not info or info.what ~= 'C') and not use_prev then + if info.source:sub(-9) == '_spec.lua' then + prev_info = info + prev_reason = 'saved' + prev_lnum = lnum + end + return + end + if trace_only_c and not use_prev and prev_reason then + hook(prev_reason, prev_lnum, true) + prev_reason = nil + end + + local whatchar = ' ' + local namewhatchar = ' ' + local funcname = '' + local source = '' + local msgchar = reason:sub(1, 1) + + if reason == 'count' then + msgchar = 'C' + end + + if info then + funcname = (info.name or ''):sub(1, hook_fnamelen) + whatchar = info.what:sub(1, 1) + namewhatchar = info.namewhat:sub(1, 1) + if namewhatchar == '' then + namewhatchar = ' ' + end + source = info.source + if source:sub(1, 1) == '@' then + if source:sub(-4, -1) == '.lua' then + source = source:sub(1, -5) + end + source = source:sub(-hook_sfnamelen, -1) + end + lnum = lnum or info.currentline + end + + -- assert(-1 <= lnum and lnum <= 99999) + local lnum_s + if lnum == -1 then + lnum_s = 'nknwn' + else + lnum_s = ('%u'):format(lnum) + end + local msg = ( -- lua does not support %* + '' + .. msgchar + .. whatchar + .. namewhatchar + .. ' ' + .. source .. (' '):rep(hook_sfnamelen - #source) + .. ':' + .. funcname .. (' '):rep(hook_fnamelen - #funcname) + .. ':' + .. ('0'):rep(hook_numlen - #lnum_s) .. lnum_s + .. '\n' + ) + -- eq(hook_msglen, #msg) + sc.write(wr, msg) + end + debug.sethook(hook, 'crl') end -return { +local trace_end_msg = ('E%s\n'):format((' '):rep(hook_msglen - 2)) + +local function itp_child(wr, func) + init() + collectgarbage('stop') + child_sethook(wr) + local err, emsg = pcall(func) + collectgarbage('restart') + collectgarbage() + debug.sethook() + emsg = tostring(emsg) + sc.write(wr, trace_end_msg) + if not err then + if #emsg > 99999 then + emsg = emsg:sub(1, 99999) + end + sc.write(wr, ('-\n%05u\n%s'):format(#emsg, emsg)) + deinit() + sc.close(wr) + sc.exit(1) + else + sc.write(wr, '+\n') + deinit() + sc.close(wr) + sc.exit(0) + end +end + +local function check_child_err(rd) + local trace = {} + local did_traceline = false + while true do + local traceline = sc.read(rd, hook_msglen) + if #traceline ~= hook_msglen then + if #traceline == 0 then + break + else + trace[#trace + 1] = 'Partial read: <' .. trace .. '>\n' + end + end + if traceline == trace_end_msg then + did_traceline = true + break + end + trace[#trace + 1] = traceline + end + local res = sc.read(rd, 2) + if #res ~= 2 then + local error + if #trace == 0 then + error = '\nTest crashed, no trace available\n' + else + error = '\nTest crashed, trace:\n' .. tracehelp + for i = 1, #trace do + error = error .. trace[i] + end + end + if not did_traceline then + error = error .. '\nNo end of trace occurred' + end + local cc_err, cc_emsg = pcall(check_cores, Paths.test_luajit_prg, true) + if not cc_err then + error = error .. '\ncheck_cores failed: ' .. cc_emsg + end + assert.just_fail(error) + end + if res == '+\n' then + return + end + eq('-\n', res) + local len_s = sc.read(rd, 5) + local len = tonumber(len_s) + neq(0, len) + local err = sc.read(rd, len + 1) + assert.just_fail(err) +end + +local function itp_parent(rd, pid, allow_failure) + local err, emsg = pcall(check_child_err, rd) + sc.wait(pid) + sc.close(rd) + if not err then + if allow_failure then + io.stderr:write('Errorred out:\n' .. tostring(emsg) .. '\n') + os.execute([[ + sh -c "source ci/common/test.sh + check_core_dumps --delete \"]] .. Paths.test_luajit_prg .. [[\""]]) + else + error(emsg) + end + end +end + +local function gen_itp(it) + child_calls_mod = {} + child_calls_mod_once = {} + child_cleanups_mod_once = {} + preprocess_cache_mod = map(function(v) return v end, preprocess_cache_init) + previous_defines_mod = previous_defines_init + cdefs_mod = cdefs_init:copy() + local function itp(name, func, allow_failure) + if allow_failure and os.getenv('NVIM_TEST_RUN_FAILING_TESTS') ~= '1' then + -- FIXME Fix tests with this true + return + end + it(name, function() + local rd, wr = sc.pipe() + child_pid = sc.fork() + if child_pid == 0 then + sc.close(rd) + itp_child(wr, func) + else + sc.close(wr) + local saved_child_pid = child_pid + child_pid = nil + itp_parent(rd, saved_child_pid, allow_failure) + end + end) + end + return itp +end + +local function cppimport(path) + return cimport(Paths.test_include_path .. '/' .. path) +end + +cimport('./src/nvim/types.h', './src/nvim/main.h', './src/nvim/os/time.h') + +local module = { cimport = cimport, cppimport = cppimport, internalize = internalize, @@ -217,11 +761,19 @@ return { eq = eq, neq = neq, ffi = ffi, - lib = libnvim, + lib = lib, cstr = cstr, to_cstr = to_cstr, NULL = NULL, OK = OK, FAIL = FAIL, alloc_log_new = alloc_log_new, + gen_itp = gen_itp, + only_separate = only_separate, + child_call_once = child_call_once, + child_cleanup_once = child_cleanup_once, + sc = sc, } +return function() + return module +end diff --git a/test/unit/mbyte_spec.lua b/test/unit/mbyte_spec.lua index 9b2415a93f..6feef4e601 100644 --- a/test/unit/mbyte_spec.lua +++ b/test/unit/mbyte_spec.lua @@ -1,4 +1,5 @@ -local helpers = require("test.unit.helpers") +local helpers = require("test.unit.helpers")(after_each) +local itp = helpers.gen_itp(it) local ffi = helpers.ffi local eq = helpers.eq @@ -26,7 +27,7 @@ describe('mbyte', function() before_each(function() end) - it('utf_ptr2char', function() + itp('utf_ptr2char', function() -- For strings with length 1 the first byte is returned. for c = 0, 255 do eq(c, mbyte.utf_ptr2char(to_string({c, 0}))) @@ -44,7 +45,7 @@ describe('mbyte', function() describe('utfc_ptr2char_len', function() - it('1-byte sequences', function() + itp('1-byte sequences', function() local pcc = to_intp() for c = 0, 255 do eq(c, mbyte.utfc_ptr2char_len(to_string({c}), pcc, 1)) @@ -52,7 +53,7 @@ describe('mbyte', function() end end) - it('2-byte sequences', function() + itp('2-byte sequences', function() local pcc = to_intp() -- No combining characters eq(0x007f, mbyte.utfc_ptr2char_len(to_string({0x7f, 0x7f}), pcc, 2)) @@ -76,7 +77,7 @@ describe('mbyte', function() eq(0, pcc[0]) end) - it('3-byte sequences', function() + itp('3-byte sequences', function() local pcc = to_intp() -- No second UTF-8 character @@ -108,7 +109,7 @@ describe('mbyte', function() eq(0, pcc[0]) end) - it('4-byte sequences', function() + itp('4-byte sequences', function() local pcc = to_intp() -- No following combining character @@ -145,7 +146,7 @@ describe('mbyte', function() eq(0, pcc[0]) end) - it('5+-byte sequences', function() + itp('5+-byte sequences', function() local pcc = to_intp() -- No following combining character diff --git a/test/unit/memory_spec.lua b/test/unit/memory_spec.lua new file mode 100644 index 0000000000..bd72c8bf47 --- /dev/null +++ b/test/unit/memory_spec.lua @@ -0,0 +1,52 @@ +local helpers = require("test.unit.helpers")(after_each) +local itp = helpers.gen_itp(it) + +local cimport = helpers.cimport +local cstr = helpers.cstr +local eq = helpers.eq +local ffi = helpers.ffi +local to_cstr = helpers.to_cstr + +local cimp = cimport('stdlib.h', './src/nvim/memory.h') + +describe('xstrlcat()', function() + local function test_xstrlcat(dst, src, dsize) + assert.is_true(dsize >= 1 + string.len(dst)) -- sanity check for tests + local dst_cstr = cstr(dsize, dst) + local src_cstr = to_cstr(src) + eq(string.len(dst .. src), cimp.xstrlcat(dst_cstr, src_cstr, dsize)) + return ffi.string(dst_cstr) + end + + local function test_xstrlcat_overlap(dst, src_idx, dsize) + assert.is_true(dsize >= 1 + string.len(dst)) -- sanity check for tests + local dst_cstr = cstr(dsize, dst) + local src_cstr = dst_cstr + src_idx -- pointer into `dst` (overlaps) + eq(string.len(dst) + string.len(dst) - src_idx, + cimp.xstrlcat(dst_cstr, src_cstr, dsize)) + return ffi.string(dst_cstr) + end + + itp('concatenates strings', function() + eq('ab', test_xstrlcat('a', 'b', 3)) + eq('ab', test_xstrlcat('a', 'b', 4096)) + eq('ABCืืZdefgiืืZ', test_xstrlcat('ABCืืZ', 'defgiืืZ', 4096)) + eq('b', test_xstrlcat('', 'b', 4096)) + eq('a', test_xstrlcat('a', '', 4096)) + end) + + itp('concatenates overlapping strings', function() + eq('abcabc', test_xstrlcat_overlap('abc', 0, 7)) + eq('abca', test_xstrlcat_overlap('abc', 0, 5)) + eq('abcb', test_xstrlcat_overlap('abc', 1, 5)) + eq('abcc', test_xstrlcat_overlap('abc', 2, 10)) + eq('abcabc', test_xstrlcat_overlap('abc', 0, 2343)) + end) + + itp('truncates if `dsize` is too small', function() + eq('a', test_xstrlcat('a', 'b', 2)) + eq('', test_xstrlcat('', 'b', 1)) + eq('ABCืืZd', test_xstrlcat('ABCืืZ', 'defgiืืZ', 10)) + end) + +end) diff --git a/test/unit/message_spec.lua b/test/unit/message_spec.lua new file mode 100644 index 0000000000..7e92b5c857 --- /dev/null +++ b/test/unit/message_spec.lua @@ -0,0 +1,60 @@ +local helpers = require("test.unit.helpers")(after_each) +local itp = helpers.gen_itp(it) + +local ffi = helpers.ffi +local eq = helpers.eq +local to_cstr = helpers.to_cstr + +local cimp = helpers.cimport('./src/nvim/message.h', './src/nvim/memory.h', + './src/nvim/strings.h') + +describe('trunc_string', function() + local buflen = 40 + local function test_inplace(s, expected, room) + room = room and room or 20 + local buf = cimp.xmalloc(ffi.sizeof('char_u') * buflen) + ffi.C.strcpy(buf, s) + cimp.trunc_string(buf, buf, room, buflen) + eq(expected, ffi.string(buf)) + cimp.xfree(buf) + end + + local function test_copy(s, expected, room) + room = room and room or 20 + local buf = cimp.xmalloc(ffi.sizeof('char_u') * buflen) + local str = cimp.vim_strsave(to_cstr(s)) + cimp.trunc_string(str, buf, room, buflen) + eq(expected, ffi.string(buf)) + cimp.xfree(buf) + cimp.xfree(str) + end + + local permutations = { + { ['desc'] = 'in-place', ['func'] = test_inplace }, + { ['desc'] = 'by copy', ['func'] = test_copy }, + } + + for _,t in ipairs(permutations) do + describe('populates buf '..t.desc, function() + itp('with a small string', function() + t.func('text', 'text') + end) + + itp('with a medium string', function() + t.func('a short text', 'a short text') + end) + + itp('with a string of length == 1/2 room', function() + t.func('a text that fits', 'a text that fits', 34) + end) + + itp('with a string exactly the truncate size', function() + t.func('a text tha just fits', 'a text tha just fits') + end) + + itp('with a string that must be truncated', function() + t.func('a text that nott fits', 'a text t...nott fits') + end) + end) + end +end) diff --git a/test/unit/multiqueue_spec.lua b/test/unit/multiqueue_spec.lua index c7f8dd8328..bb08a8386f 100644 --- a/test/unit/multiqueue_spec.lua +++ b/test/unit/multiqueue_spec.lua @@ -1,9 +1,12 @@ -local helpers = require("test.unit.helpers") +local helpers = require("test.unit.helpers")(after_each) +local itp = helpers.gen_itp(it) -local ffi = helpers.ffi -local eq = helpers.eq +local child_call_once = helpers.child_call_once +local cimport = helpers.cimport +local ffi = helpers.ffi +local eq = helpers.eq -local multiqueue = helpers.cimport("./test/unit/fixtures/multiqueue.h") +local multiqueue = cimport("./test/unit/fixtures/multiqueue.h") describe("multiqueue (multi-level event-queue)", function() local parent, child1, child2, child3 @@ -21,28 +24,30 @@ describe("multiqueue (multi-level event-queue)", function() end before_each(function() - parent = multiqueue.multiqueue_new_parent(ffi.NULL, ffi.NULL) - child1 = multiqueue.multiqueue_new_child(parent) - child2 = multiqueue.multiqueue_new_child(parent) - child3 = multiqueue.multiqueue_new_child(parent) - put(child1, 'c1i1') - put(child1, 'c1i2') - put(child2, 'c2i1') - put(child1, 'c1i3') - put(child2, 'c2i2') - put(child2, 'c2i3') - put(child2, 'c2i4') - put(child3, 'c3i1') - put(child3, 'c3i2') + child_call_once(function() + parent = multiqueue.multiqueue_new_parent(ffi.NULL, ffi.NULL) + child1 = multiqueue.multiqueue_new_child(parent) + child2 = multiqueue.multiqueue_new_child(parent) + child3 = multiqueue.multiqueue_new_child(parent) + put(child1, 'c1i1') + put(child1, 'c1i2') + put(child2, 'c2i1') + put(child1, 'c1i3') + put(child2, 'c2i2') + put(child2, 'c2i3') + put(child2, 'c2i4') + put(child3, 'c3i1') + put(child3, 'c3i2') + end) end) - it('keeps count of added events', function() + itp('keeps count of added events', function() eq(3, multiqueue.multiqueue_size(child1)) eq(4, multiqueue.multiqueue_size(child2)) eq(2, multiqueue.multiqueue_size(child3)) end) - it('keeps count of removed events', function() + itp('keeps count of removed events', function() multiqueue.multiqueue_get(child1) eq(2, multiqueue.multiqueue_size(child1)) multiqueue.multiqueue_get(child1) @@ -57,7 +62,7 @@ describe("multiqueue (multi-level event-queue)", function() eq(0, multiqueue.multiqueue_size(child1)) end) - it('removing from parent removes from child', function() + itp('removing from parent removes from child', function() eq('c1i1', get(parent)) eq('c1i2', get(parent)) eq('c2i1', get(parent)) @@ -67,7 +72,7 @@ describe("multiqueue (multi-level event-queue)", function() eq('c2i4', get(parent)) end) - it('removing from child removes from parent', function() + itp('removing from child removes from parent', function() eq('c2i1', get(child2)) eq('c2i2', get(child2)) eq('c1i1', get(child1)) @@ -77,13 +82,13 @@ describe("multiqueue (multi-level event-queue)", function() eq('c2i4', get(parent)) end) - it('removing from child at the beginning of parent', function() + itp('removing from child at the beginning of parent', function() eq('c1i1', get(child1)) eq('c1i2', get(child1)) eq('c2i1', get(parent)) end) - it('removing from parent after get from parent and put to child', function() + itp('removing from parent after get from parent and put to child', function() eq('c1i1', get(parent)) eq('c1i2', get(parent)) eq('c2i1', get(parent)) @@ -99,7 +104,7 @@ describe("multiqueue (multi-level event-queue)", function() eq('c1i22', get(parent)) end) - it('removing from parent after get and put to child', function() + itp('removing from parent after get and put to child', function() eq('c1i1', get(child1)) eq('c1i2', get(child1)) eq('c2i1', get(child2)) @@ -117,7 +122,7 @@ describe("multiqueue (multi-level event-queue)", function() eq('c1i12', get(parent)) end) - it('put after removing from child at the end of parent', function() + itp('put after removing from child at the end of parent', function() eq('c3i1', get(child3)) eq('c3i2', get(child3)) put(child1, 'c1i11') @@ -133,7 +138,7 @@ describe("multiqueue (multi-level event-queue)", function() eq('c2i11', get(parent)) end) - it('removes from parent queue when child is freed', function() + itp('removes from parent queue when child is freed', function() free(child2) eq('c1i1', get(parent)) eq('c1i2', get(parent)) diff --git a/test/unit/option_spec.lua b/test/unit/option_spec.lua index 8bab0194a2..b8b8a435bc 100644 --- a/test/unit/option_spec.lua +++ b/test/unit/option_spec.lua @@ -1,4 +1,5 @@ -local helpers = require("test.unit.helpers") +local helpers = require("test.unit.helpers")(after_each) +local itp = helpers.gen_itp(it) local to_cstr = helpers.to_cstr local eq = helpers.eq @@ -12,23 +13,23 @@ end describe('check_ff_value', function() - it('views empty string as valid', function() + itp('views empty string as valid', function() eq(1, check_ff_value("")) end) - it('views "unix", "dos" and "mac" as valid', function() + itp('views "unix", "dos" and "mac" as valid', function() eq(1, check_ff_value("unix")) eq(1, check_ff_value("dos")) eq(1, check_ff_value("mac")) end) - it('views "foo" as invalid', function() + itp('views "foo" as invalid', function() eq(0, check_ff_value("foo")) end) end) describe('get_sts_value', function() - it([[returns 'softtabstop' when it is non-negative]], function() + itp([[returns 'softtabstop' when it is non-negative]], function() globals.curbuf.b_p_sts = 5 eq(5, option.get_sts_value()) @@ -36,7 +37,7 @@ describe('get_sts_value', function() eq(0, option.get_sts_value()) end) - it([[returns "effective shiftwidth" when 'softtabstop' is negative]], function() + itp([[returns "effective shiftwidth" when 'softtabstop' is negative]], function() local shiftwidth = 2 globals.curbuf.b_p_sw = shiftwidth local tabstop = 5 diff --git a/test/unit/os/env_spec.lua b/test/unit/os/env_spec.lua index 9e00a3e8f8..c54d5a9b77 100644 --- a/test/unit/os/env_spec.lua +++ b/test/unit/os/env_spec.lua @@ -1,4 +1,5 @@ -local helpers = require('test.unit.helpers') +local helpers = require('test.unit.helpers')(after_each) +local itp = helpers.gen_itp(it) local cimport = helpers.cimport local eq = helpers.eq @@ -10,19 +11,19 @@ local NULL = helpers.NULL require('lfs') -local env = cimport('./src/nvim/os/os.h') +local cimp = cimport('./src/nvim/os/os.h') -describe('env function', function() +describe('env.c', function() local function os_setenv(name, value, override) - return env.os_setenv((to_cstr(name)), (to_cstr(value)), override) + return cimp.os_setenv(to_cstr(name), to_cstr(value), override) end local function os_unsetenv(name, _, _) - return env.os_unsetenv((to_cstr(name))) + return cimp.os_unsetenv(to_cstr(name)) end local function os_getenv(name) - local rval = env.os_getenv((to_cstr(name))) + local rval = cimp.os_getenv(to_cstr(name)) if rval ~= NULL then return ffi.string(rval) else @@ -33,18 +34,18 @@ describe('env function', function() describe('os_setenv', function() local OK = 0 - it('sets an env variable and returns OK', function() - local name = 'NEOVIM_UNIT_TEST_SETENV_1N' - local value = 'NEOVIM_UNIT_TEST_SETENV_1V' + itp('sets an env variable and returns OK', function() + local name = 'NVIM_UNIT_TEST_SETENV_1N' + local value = 'NVIM_UNIT_TEST_SETENV_1V' eq(nil, os.getenv(name)) eq(OK, (os_setenv(name, value, 1))) eq(value, os.getenv(name)) end) - it("dosn't overwrite an env variable if overwrite is 0", function() - local name = 'NEOVIM_UNIT_TEST_SETENV_2N' - local value = 'NEOVIM_UNIT_TEST_SETENV_2V' - local value_updated = 'NEOVIM_UNIT_TEST_SETENV_2V_UPDATED' + itp("dosn't overwrite an env variable if overwrite is 0", function() + local name = 'NVIM_UNIT_TEST_SETENV_2N' + local value = 'NVIM_UNIT_TEST_SETENV_2V' + local value_updated = 'NVIM_UNIT_TEST_SETENV_2V_UPDATED' eq(OK, (os_setenv(name, value, 0))) eq(value, os.getenv(name)) eq(OK, (os_setenv(name, value_updated, 0))) @@ -52,24 +53,63 @@ describe('env function', function() end) end) + describe('os_setenv_append_path', function() + itp('appends /foo/bar to $PATH', function() + local original_path = os.getenv('PATH') + eq(true, cimp.os_setenv_append_path(to_cstr('/foo/bar/baz'))) + eq(original_path..':/foo/bar', os.getenv('PATH')) + end) + + itp('returns false if `fname` is not absolute', function() + local original_path = os.getenv('PATH') + eq(false, cimp.os_setenv_append_path(to_cstr('foo/bar/baz'))) + eq(original_path, os.getenv('PATH')) + end) + end) + + describe('os_shell_is_cmdexe', function() + itp('returns true for expected names', function() + eq(true, cimp.os_shell_is_cmdexe(to_cstr('cmd.exe'))) + eq(true, cimp.os_shell_is_cmdexe(to_cstr('cmd'))) + eq(true, cimp.os_shell_is_cmdexe(to_cstr('CMD.EXE'))) + eq(true, cimp.os_shell_is_cmdexe(to_cstr('CMD'))) + + os_setenv('COMSPEC', '/foo/bar/cmd.exe', 0) + eq(true, cimp.os_shell_is_cmdexe(to_cstr('$COMSPEC'))) + os_setenv('COMSPEC', [[C:\system32\cmd.exe]], 0) + eq(true, cimp.os_shell_is_cmdexe(to_cstr('$COMSPEC'))) + end) + itp('returns false for unexpected names', function() + eq(false, cimp.os_shell_is_cmdexe(to_cstr(''))) + eq(false, cimp.os_shell_is_cmdexe(to_cstr('powershell'))) + eq(false, cimp.os_shell_is_cmdexe(to_cstr(' cmd.exe '))) + eq(false, cimp.os_shell_is_cmdexe(to_cstr('cm'))) + eq(false, cimp.os_shell_is_cmdexe(to_cstr('md'))) + eq(false, cimp.os_shell_is_cmdexe(to_cstr('cmd.ex'))) + + os_setenv('COMSPEC', '/foo/bar/cmd', 0) + eq(false, cimp.os_shell_is_cmdexe(to_cstr('$COMSPEC'))) + end) + end) + describe('os_getenv', function() - it('reads an env variable', function() - local name = 'NEOVIM_UNIT_TEST_GETENV_1N' - local value = 'NEOVIM_UNIT_TEST_GETENV_1V' + itp('reads an env variable', function() + local name = 'NVIM_UNIT_TEST_GETENV_1N' + local value = 'NVIM_UNIT_TEST_GETENV_1V' eq(NULL, os_getenv(name)) - -- need to use os_setenv, because lua dosn't have a setenv function + -- Use os_setenv because Lua dosen't have setenv. os_setenv(name, value, 1) eq(value, os_getenv(name)) end) - it('returns NULL if the env variable is not found', function() - local name = 'NEOVIM_UNIT_TEST_GETENV_NOTFOUND' + itp('returns NULL if the env variable is not found', function() + local name = 'NVIM_UNIT_TEST_GETENV_NOTFOUND' return eq(NULL, os_getenv(name)) end) end) describe('os_unsetenv', function() - it('unsets environment variable', function() + itp('unsets environment variable', function() local name = 'TEST_UNSETENV' local value = 'TESTVALUE' os_setenv(name, value, 1) @@ -81,113 +121,126 @@ describe('env function', function() end) describe('os_getenvname_at_index', function() - it('returns names of environment variables', function() - local test_name = 'NEOVIM_UNIT_TEST_GETENVNAME_AT_INDEX_1N' - local test_value = 'NEOVIM_UNIT_TEST_GETENVNAME_AT_INDEX_1V' + itp('returns names of environment variables', function() + local test_name = 'NVIM_UNIT_TEST_GETENVNAME_AT_INDEX_1N' + local test_value = 'NVIM_UNIT_TEST_GETENVNAME_AT_INDEX_1V' os_setenv(test_name, test_value, 1) local i = 0 local names = { } local found_name = false - local name = env.os_getenvname_at_index(i) + local name = cimp.os_getenvname_at_index(i) while name ~= NULL do table.insert(names, ffi.string(name)) if (ffi.string(name)) == test_name then found_name = true end i = i + 1 - name = env.os_getenvname_at_index(i) + name = cimp.os_getenvname_at_index(i) end eq(true, (table.getn(names)) > 0) eq(true, found_name) end) - it('returns NULL if the index is out of bounds', function() + itp('returns NULL if the index is out of bounds', function() local huge = ffi.new('size_t', 10000) local maxuint32 = ffi.new('size_t', 4294967295) - eq(NULL, env.os_getenvname_at_index(huge)) - eq(NULL, env.os_getenvname_at_index(maxuint32)) + eq(NULL, cimp.os_getenvname_at_index(huge)) + eq(NULL, cimp.os_getenvname_at_index(maxuint32)) if ffi.abi('64bit') then -- couldn't use a bigger number because it gets converted to -- double somewere, should be big enough anyway -- maxuint64 = ffi.new 'size_t', 18446744073709551615 local maxuint64 = ffi.new('size_t', 18446744073709000000) - eq(NULL, env.os_getenvname_at_index(maxuint64)) + eq(NULL, cimp.os_getenvname_at_index(maxuint64)) end end) end) describe('os_get_pid', function() - it('returns the process ID', function() + itp('returns the process ID', function() local stat_file = io.open('/proc/self/stat') if stat_file then local stat_str = stat_file:read('*l') stat_file:close() local pid = tonumber((stat_str:match('%d+'))) - eq(pid, tonumber(env.os_get_pid())) + eq(pid, tonumber(cimp.os_get_pid())) else -- /proc is not available on all systems, test if pid is nonzero. - eq(true, (env.os_get_pid() > 0)) + eq(true, (cimp.os_get_pid() > 0)) end end) end) describe('os_get_hostname', function() - it('returns the hostname', function() + itp('returns the hostname', function() local handle = io.popen('hostname') local hostname = handle:read('*l') handle:close() local hostname_buf = cstr(255, '') - env.os_get_hostname(hostname_buf, 255) + cimp.os_get_hostname(hostname_buf, 255) eq(hostname, (ffi.string(hostname_buf))) end) end) describe('expand_env_esc', function() - it('expands environment variables', function() - local name = 'NEOVIM_UNIT_TEST_EXPAND_ENV_ESCN' - local value = 'NEOVIM_UNIT_TEST_EXPAND_ENV_ESCV' + itp('expands environment variables', function() + local name = 'NVIM_UNIT_TEST_EXPAND_ENV_ESCN' + local value = 'NVIM_UNIT_TEST_EXPAND_ENV_ESCV' os_setenv(name, value, 1) -- TODO(bobtwinkles) This only tests Unix expansions. There should be a -- test for Windows as well - local input1 = to_cstr('$NEOVIM_UNIT_TEST_EXPAND_ENV_ESCN/test') - local input2 = to_cstr('${NEOVIM_UNIT_TEST_EXPAND_ENV_ESCN}/test') + local input1 = to_cstr('$NVIM_UNIT_TEST_EXPAND_ENV_ESCN/test') + local input2 = to_cstr('${NVIM_UNIT_TEST_EXPAND_ENV_ESCN}/test') local output_buff1 = cstr(255, '') local output_buff2 = cstr(255, '') - local output_expected = 'NEOVIM_UNIT_TEST_EXPAND_ENV_ESCV/test' - env.expand_env_esc(input1, output_buff1, 255, false, true, NULL) - env.expand_env_esc(input2, output_buff2, 255, false, true, NULL) + local output_expected = 'NVIM_UNIT_TEST_EXPAND_ENV_ESCV/test' + cimp.expand_env_esc(input1, output_buff1, 255, false, true, NULL) + cimp.expand_env_esc(input2, output_buff2, 255, false, true, NULL) eq(output_expected, ffi.string(output_buff1)) eq(output_expected, ffi.string(output_buff2)) end) - it('expands ~ once when one is true', function() + itp('expands ~ once when `one` is true', function() local input = '~/foo ~ foo' local homedir = cstr(255, '') - env.expand_env_esc(to_cstr('~'), homedir, 255, false, true, NULL) + cimp.expand_env_esc(to_cstr('~'), homedir, 255, false, true, NULL) local output_expected = ffi.string(homedir) .. "/foo ~ foo" local output = cstr(255, '') - env.expand_env_esc(to_cstr(input), output, 255, false, true, NULL) + cimp.expand_env_esc(to_cstr(input), output, 255, false, true, NULL) eq(ffi.string(output), ffi.string(output_expected)) end) - it('expands ~ every time when one is false', function() + itp('expands ~ every time when `one` is false', function() local input = to_cstr('~/foo ~ foo') - local homedir = cstr(255, '') - env.expand_env_esc(to_cstr('~'), homedir, 255, false, true, NULL) - homedir = ffi.string(homedir) + local dst = cstr(255, '') + cimp.expand_env_esc(to_cstr('~'), dst, 255, false, true, NULL) + local homedir = ffi.string(dst) local output_expected = homedir .. "/foo " .. homedir .. " foo" local output = cstr(255, '') - env.expand_env_esc(input, output, 255, false, false, NULL) + cimp.expand_env_esc(input, output, 255, false, false, NULL) eq(output_expected, ffi.string(output)) end) - it('respects the dstlen parameter without expansion', function() + itp('does not crash #3725', function() + local name_out = ffi.new('char[100]') + cimp.os_get_user_name(name_out, 100) + local curuser = ffi.string(name_out) + + local src = to_cstr("~"..curuser.."/Vcs/django-rest-framework/rest_framework/renderers.py") + local dst = cstr(256, "~"..curuser) + cimp.expand_env_esc(src, dst, 256, false, false, NULL) + local len = string.len(ffi.string(dst)) + assert.True(len > 56) + assert.True(len < 256) + end) + + itp('respects `dstlen` without expansion', function() local input = to_cstr('this is a very long thing that will not fit') -- The buffer is long enough to actually contain the full input in case the -- test fails, but we don't tell expand_env_esc that local output = cstr(255, '') - env.expand_env_esc(input, output, 5, false, true, NULL) + cimp.expand_env_esc(input, output, 5, false, true, NULL) -- Make sure the first few characters are copied properly and that there is a -- terminating null character for i=0,3 do @@ -196,17 +249,17 @@ describe('env function', function() eq(0, output[4]) end) - it('respects the dstlen parameter with expansion', function() + itp('respects `dstlen` with expansion', function() local varname = to_cstr('NVIM_UNIT_TEST_EXPAND_ENV_ESC_DSTLENN') local varval = to_cstr('NVIM_UNIT_TEST_EXPAND_ENV_ESC_DSTLENV') - env.os_setenv(varname, varval, 1) + cimp.os_setenv(varname, varval, 1) -- TODO(bobtwinkles) This test uses unix-specific environment variable accessing, -- should have some alternative for windows local input = to_cstr('$NVIM_UNIT_TEST_EXPAND_ENV_ESC_DSTLENN/even more stuff') -- The buffer is long enough to actually contain the full input in case the -- test fails, but we don't tell expand_env_esc that local output = cstr(255, '') - env.expand_env_esc(input, output, 5, false, true, NULL) + cimp.expand_env_esc(input, output, 5, false, true, NULL) -- Make sure the first few characters are copied properly and that there is a -- terminating null character -- expand_env_esc SHOULD NOT expand the variable if there is not enough space to diff --git a/test/unit/os/fileio_spec.lua b/test/unit/os/fileio_spec.lua index 5358022422..d9c98e8afa 100644 --- a/test/unit/os/fileio_spec.lua +++ b/test/unit/os/fileio_spec.lua @@ -1,12 +1,15 @@ local lfs = require('lfs') -local helpers = require('test.unit.helpers') +local helpers = require('test.unit.helpers')(after_each) +local itp = helpers.gen_itp(it) local eq = helpers.eq local ffi = helpers.ffi local cimport = helpers.cimport +local cppimport = helpers.cppimport -local m = cimport('./src/nvim/os/fileio.h') +local m = cimport('./src/nvim/os/os.h', './src/nvim/os/fileio.h') +cppimport('fcntl.h') local fcontents = '' for i = 0, 255 do @@ -57,10 +60,26 @@ local function file_open_new(fname, flags, mode) return ret1[0], ret2 end +local function file_open_fd(fd, flags) + local ret2 = ffi.new('FileDescriptor') + local ret1 = m.file_open_fd(ret2, fd, flags) + return ret1, ret2 +end + +local function file_open_fd_new(fd, flags) + local ret1 = ffi.new('int[?]', 1, {0}) + local ret2 = ffi.gc(m.file_open_fd_new(ret1, fd, flags), nil) + return ret1[0], ret2 +end + local function file_write(fp, buf) return m.file_write(fp, buf, #buf) end +local function msgpack_file_write(fp, buf) + return m.msgpack_file_write(fp, buf, #buf) +end + local function file_read(fp, size) local buf = nil if size == nil then @@ -79,6 +98,10 @@ local function file_read(fp, size) return ret1, ret2 end +local function file_flush(fp) + return m.file_flush(fp) +end + local function file_fsync(fp) return m.file_fsync(fp) end @@ -87,149 +110,211 @@ local function file_skip(fp, size) return m.file_skip(fp, size) end +describe('file_open_fd', function() + itp('can use file descriptor returned by os_open for reading', function() + local fd = m.os_open(file1, m.kO_RDONLY, 0) + local err, fp = file_open_fd(fd, false) + eq(0, err) + eq({#fcontents, fcontents}, {file_read(fp, #fcontents)}) + eq(0, m.file_close(fp, false)) + end) + itp('can use file descriptor returned by os_open for writing', function() + eq(nil, lfs.attributes(filec)) + local fd = m.os_open(filec, m.kO_WRONLY + m.kO_CREAT, 384) + local err, fp = file_open_fd(fd, true) + eq(0, err) + eq(4, file_write(fp, 'test')) + eq(0, m.file_close(fp, false)) + eq(4, lfs.attributes(filec).size) + eq('test', io.open(filec):read('*a')) + end) +end) + +describe('file_open_fd_new', function() + itp('can use file descriptor returned by os_open for reading', function() + local fd = m.os_open(file1, m.kO_RDONLY, 0) + local err, fp = file_open_fd_new(fd, false) + eq(0, err) + eq({#fcontents, fcontents}, {file_read(fp, #fcontents)}) + eq(0, m.file_free(fp, false)) + end) + itp('can use file descriptor returned by os_open for writing', function() + eq(nil, lfs.attributes(filec)) + local fd = m.os_open(filec, m.kO_WRONLY + m.kO_CREAT, 384) + local err, fp = file_open_fd_new(fd, true) + eq(0, err) + eq(4, file_write(fp, 'test')) + eq(0, m.file_free(fp, false)) + eq(4, lfs.attributes(filec).size) + eq('test', io.open(filec):read('*a')) + end) +end) + describe('file_open', function() - it('can create a rwx------ file with kFileCreate', function() + itp('can create a rwx------ file with kFileCreate', function() local err, fp = file_open(filec, m.kFileCreate, 448) eq(0, err) local attrs = lfs.attributes(filec) eq('rwx------', attrs.permissions) - eq(0, m.file_close(fp)) + eq(0, m.file_close(fp, false)) end) - it('can create a rw------- file with kFileCreate', function() + itp('can create a rw------- file with kFileCreate', function() local err, fp = file_open(filec, m.kFileCreate, 384) eq(0, err) local attrs = lfs.attributes(filec) eq('rw-------', attrs.permissions) - eq(0, m.file_close(fp)) + eq(0, m.file_close(fp, false)) end) - it('can create a rwx------ file with kFileCreateOnly', function() + itp('can create a rwx------ file with kFileCreateOnly', function() local err, fp = file_open(filec, m.kFileCreateOnly, 448) eq(0, err) local attrs = lfs.attributes(filec) eq('rwx------', attrs.permissions) - eq(0, m.file_close(fp)) + eq(0, m.file_close(fp, false)) end) - it('can create a rw------- file with kFileCreateOnly', function() + itp('can create a rw------- file with kFileCreateOnly', function() local err, fp = file_open(filec, m.kFileCreateOnly, 384) eq(0, err) local attrs = lfs.attributes(filec) eq('rw-------', attrs.permissions) - eq(0, m.file_close(fp)) + eq(0, m.file_close(fp, false)) end) - it('fails to open an existing file with kFileCreateOnly', function() + itp('fails to open an existing file with kFileCreateOnly', function() local err, _ = file_open(file1, m.kFileCreateOnly, 384) eq(m.UV_EEXIST, err) end) - it('fails to open an symlink with kFileNoSymlink', function() + itp('fails to open an symlink with kFileNoSymlink', function() local err, _ = file_open(linkf, m.kFileNoSymlink, 384) -- err is UV_EMLINK in FreeBSD, but if I use `ok(err == m.UV_ELOOP or err == -- m.UV_EMLINK)`, then I loose the ability to see actual `err` value. if err ~= m.UV_ELOOP then eq(m.UV_EMLINK, err) end end) - it('can open an existing file write-only with kFileCreate', function() + itp('can open an existing file write-only with kFileCreate', function() local err, fp = file_open(file1, m.kFileCreate, 384) eq(0, err) eq(true, fp.wr) - eq(0, m.file_close(fp)) + eq(0, m.file_close(fp, false)) end) - it('can open an existing file read-only with zero', function() + itp('can open an existing file read-only with zero', function() local err, fp = file_open(file1, 0, 384) eq(0, err) eq(false, fp.wr) - eq(0, m.file_close(fp)) + eq(0, m.file_close(fp, false)) end) - it('can open an existing file read-only with kFileReadOnly', function() + itp('can open an existing file read-only with kFileReadOnly', function() local err, fp = file_open(file1, m.kFileReadOnly, 384) eq(0, err) eq(false, fp.wr) - eq(0, m.file_close(fp)) + eq(0, m.file_close(fp, false)) end) - it('can open an existing file read-only with kFileNoSymlink', function() + itp('can open an existing file read-only with kFileNoSymlink', function() local err, fp = file_open(file1, m.kFileNoSymlink, 384) eq(0, err) eq(false, fp.wr) - eq(0, m.file_close(fp)) + eq(0, m.file_close(fp, false)) end) - it('can truncate an existing file with kFileTruncate', function() + itp('can truncate an existing file with kFileTruncate', function() local err, fp = file_open(file1, m.kFileTruncate, 384) eq(0, err) eq(true, fp.wr) - eq(0, m.file_close(fp)) + eq(0, m.file_close(fp, false)) local attrs = lfs.attributes(file1) eq(0, attrs.size) end) - it('can open an existing file write-only with kFileWriteOnly', function() + itp('can open an existing file write-only with kFileWriteOnly', function() local err, fp = file_open(file1, m.kFileWriteOnly, 384) eq(0, err) eq(true, fp.wr) - eq(0, m.file_close(fp)) + eq(0, m.file_close(fp, false)) local attrs = lfs.attributes(file1) eq(4096, attrs.size) end) - it('fails to create a file with just kFileWriteOnly', function() + itp('fails to create a file with just kFileWriteOnly', function() local err, _ = file_open(filec, m.kFileWriteOnly, 384) eq(m.UV_ENOENT, err) local attrs = lfs.attributes(filec) eq(nil, attrs) end) - it('can truncate an existing file with kFileTruncate when opening a symlink', + itp('can truncate an existing file with kFileTruncate when opening a symlink', function() local err, fp = file_open(linkf, m.kFileTruncate, 384) eq(0, err) eq(true, fp.wr) - eq(0, m.file_close(fp)) + eq(0, m.file_close(fp, false)) local attrs = lfs.attributes(file1) eq(0, attrs.size) end) - it('fails to open a directory write-only', function() + itp('fails to open a directory write-only', function() local err, _ = file_open(dir, m.kFileWriteOnly, 384) eq(m.UV_EISDIR, err) end) - it('fails to open a broken symbolic link write-only', function() + itp('fails to open a broken symbolic link write-only', function() local err, _ = file_open(linkb, m.kFileWriteOnly, 384) eq(m.UV_ENOENT, err) end) - it('fails to open a broken symbolic link read-only', function() + itp('fails to open a broken symbolic link read-only', function() local err, _ = file_open(linkb, m.kFileReadOnly, 384) eq(m.UV_ENOENT, err) end) end) describe('file_open_new', function() - it('can open a file read-only', function() + itp('can open a file read-only', function() local err, fp = file_open_new(file1, 0, 384) eq(0, err) eq(false, fp.wr) - eq(0, m.file_free(fp)) + eq(0, m.file_free(fp, false)) end) - it('fails to open an existing file with kFileCreateOnly', function() + itp('fails to open an existing file with kFileCreateOnly', function() local err, fp = file_open_new(file1, m.kFileCreateOnly, 384) eq(m.UV_EEXIST, err) eq(nil, fp) end) end) --- file_close is called above, so it is not tested directly +describe('file_close', function() + itp('can flush writes to disk also with true argument', function() + local err, fp = file_open(filec, m.kFileCreateOnly, 384) + eq(0, err) + local wsize = file_write(fp, 'test') + eq(4, wsize) + eq(0, lfs.attributes(filec).size) + eq(0, m.file_close(fp, true)) + eq(wsize, lfs.attributes(filec).size) + end) +end) + +describe('file_free', function() + itp('can flush writes to disk also with true argument', function() + local err, fp = file_open_new(filec, m.kFileCreateOnly, 384) + eq(0, err) + local wsize = file_write(fp, 'test') + eq(4, wsize) + eq(0, lfs.attributes(filec).size) + eq(0, m.file_free(fp, true)) + eq(wsize, lfs.attributes(filec).size) + end) +end) describe('file_fsync', function() - it('can flush writes to disk', function() + itp('can flush writes to disk', function() local err, fp = file_open(filec, m.kFileCreateOnly, 384) eq(0, file_fsync(fp)) eq(0, err) @@ -239,12 +324,27 @@ describe('file_fsync', function() eq(0, lfs.attributes(filec).size) eq(0, file_fsync(fp)) eq(wsize, lfs.attributes(filec).size) - eq(0, m.file_close(fp)) + eq(0, m.file_close(fp, false)) + end) +end) + +describe('file_flush', function() + itp('can flush writes to disk', function() + local err, fp = file_open(filec, m.kFileCreateOnly, 384) + eq(0, file_flush(fp)) + eq(0, err) + eq(0, lfs.attributes(filec).size) + local wsize = file_write(fp, 'test') + eq(4, wsize) + eq(0, lfs.attributes(filec).size) + eq(0, file_flush(fp)) + eq(wsize, lfs.attributes(filec).size) + eq(0, m.file_close(fp, false)) end) end) describe('file_read', function() - it('can read small chunks of input until eof', function() + itp('can read small chunks of input until eof', function() local err, fp = file_open(file1, 0, 384) eq(0, err) eq(false, fp.wr) @@ -261,29 +361,29 @@ describe('file_read', function() eq({exp_err, exp_s}, {file_read(fp, size)}) shift = shift + size end - eq(0, m.file_close(fp)) + eq(0, m.file_close(fp, false)) end) - it('can read the whole file at once', function() + itp('can read the whole file at once', function() local err, fp = file_open(file1, 0, 384) eq(0, err) eq(false, fp.wr) eq({#fcontents, fcontents}, {file_read(fp, #fcontents)}) eq({0, ('\0'):rep(#fcontents)}, {file_read(fp, #fcontents)}) - eq(0, m.file_close(fp)) + eq(0, m.file_close(fp, false)) end) - it('can read more then 1024 bytes after reading a small chunk', function() + itp('can read more then 1024 bytes after reading a small chunk', function() local err, fp = file_open(file1, 0, 384) eq(0, err) eq(false, fp.wr) eq({5, fcontents:sub(1, 5)}, {file_read(fp, 5)}) eq({#fcontents - 5, fcontents:sub(6) .. (('\0'):rep(5))}, {file_read(fp, #fcontents)}) - eq(0, m.file_close(fp)) + eq(0, m.file_close(fp, false)) end) - it('can read file by 768-byte-chunks', function() + itp('can read file by 768-byte-chunks', function() local err, fp = file_open(file1, 0, 384) eq(0, err) eq(false, fp.wr) @@ -300,23 +400,23 @@ describe('file_read', function() eq({exp_err, exp_s}, {file_read(fp, size)}) shift = shift + size end - eq(0, m.file_close(fp)) + eq(0, m.file_close(fp, false)) end) end) describe('file_write', function() - it('can write the whole file at once', function() + itp('can write the whole file at once', function() local err, fp = file_open(filec, m.kFileCreateOnly, 384) eq(0, err) eq(true, fp.wr) local wr = file_write(fp, fcontents) eq(#fcontents, wr) - eq(0, m.file_close(fp)) + eq(0, m.file_close(fp, false)) eq(wr, lfs.attributes(filec).size) eq(fcontents, io.open(filec):read('*a')) end) - it('can write the whole file by small chunks', function() + itp('can write the whole file by small chunks', function() local err, fp = file_open(filec, m.kFileCreateOnly, 384) eq(0, err) eq(true, fp.wr) @@ -328,12 +428,12 @@ describe('file_write', function() eq(wr, #s) shift = shift + size end - eq(0, m.file_close(fp)) + eq(0, m.file_close(fp, false)) eq(#fcontents, lfs.attributes(filec).size) eq(fcontents, io.open(filec):read('*a')) end) - it('can write the whole file by 768-byte-chunks', function() + itp('can write the whole file by 768-byte-chunks', function() local err, fp = file_open(filec, m.kFileCreateOnly, 384) eq(0, err) eq(true, fp.wr) @@ -345,14 +445,26 @@ describe('file_write', function() eq(wr, #s) shift = shift + size end - eq(0, m.file_close(fp)) + eq(0, m.file_close(fp, false)) eq(#fcontents, lfs.attributes(filec).size) eq(fcontents, io.open(filec):read('*a')) end) end) +describe('msgpack_file_write', function() + itp('can write the whole file at once', function() + local err, fp = file_open(filec, m.kFileCreateOnly, 384) + eq(0, err) + eq(true, fp.wr) + local wr = msgpack_file_write(fp, fcontents) + eq(0, wr) + eq(0, m.file_close(fp, false)) + eq(fcontents, io.open(filec):read('*a')) + end) +end) + describe('file_skip', function() - it('can skip 3 bytes', function() + itp('can skip 3 bytes', function() local err, fp = file_open(file1, 0, 384) eq(0, err) eq(false, fp.wr) @@ -360,6 +472,6 @@ describe('file_skip', function() local rd, s = file_read(fp, 3) eq(3, rd) eq(fcontents:sub(4, 6), s) - eq(0, m.file_close(fp)) + eq(0, m.file_close(fp, false)) end) end) diff --git a/test/unit/os/fs_spec.lua b/test/unit/os/fs_spec.lua index 5d889d6e33..bc39507c08 100644 --- a/test/unit/os/fs_spec.lua +++ b/test/unit/os/fs_spec.lua @@ -1,7 +1,8 @@ local lfs = require('lfs') local bit = require('bit') -local helpers = require('test.unit.helpers') +local helpers = require('test.unit.helpers')(after_each) +local itp = helpers.gen_itp(it) local cimport = helpers.cimport local cppimport = helpers.cppimport @@ -15,15 +16,15 @@ local to_cstr = helpers.to_cstr local OK = helpers.OK local FAIL = helpers.FAIL local NULL = helpers.NULL + local NODE_NORMAL = 0 local NODE_WRITABLE = 1 -cimport('unistd.h') cimport('./src/nvim/os/shell.h') cimport('./src/nvim/option_defs.h') cimport('./src/nvim/main.h') cimport('./src/nvim/fileio.h') -local fs = cimport('./src/nvim/os/os.h') +local fs = cimport('./src/nvim/os/os.h', './src/nvim/path.h') cppimport('sys/stat.h') cppimport('fcntl.h') cppimport('uv-errno.h') @@ -34,7 +35,6 @@ for i = 0, 255 do end local fcontents = s:rep(16) -local buffer = "" local directory = nil local absolute_executable = nil local executable_name = nil @@ -64,28 +64,27 @@ local function os_getperm(filename) return tonumber(perm) end -describe('fs function', function() - local orig_test_file_perm +describe('fs.c', function() + local function os_isdir(name) + return fs.os_isdir(to_cstr(name)) + end - setup(function() + before_each(function() lfs.mkdir('unit-test-directory'); io.open('unit-test-directory/test.file', 'w').close() - orig_test_file_perm = os_getperm('unit-test-directory/test.file') io.open('unit-test-directory/test_2.file', 'w').close() lfs.link('test.file', 'unit-test-directory/test_link.file', true) lfs.link('non_existing_file.file', 'unit-test-directory/test_broken_link.file', true) - -- Since the tests are executed, they are called by an executable. We use - -- that executable for several asserts. + -- The tests are invoked with an absolute path to `busted` executable. absolute_executable = arg[0] - -- Split absolute_executable into a directory and the actual file name for - -- later usage. + -- Split the absolute_executable path into a directory and filename. directory, executable_name = string.match(absolute_executable, '^(.*)/(.*)$') end) - teardown(function() + after_each(function() os.remove('unit-test-directory/test.file') os.remove('unit-test-directory/test_2.file') os.remove('unit-test-directory/test_link.file') @@ -95,63 +94,68 @@ describe('fs function', function() end) describe('os_dirname', function() - local length - - local function os_dirname(buf, len) - return fs.os_dirname(buf, len) - end - - before_each(function() - length = (string.len(lfs.currentdir())) + 1 - buffer = cstr(length, '') + itp('returns OK and writes current directory to the buffer', function() + local length = string.len(lfs.currentdir()) + 1 + local buf = cstr(length, '') + eq(OK, fs.os_dirname(buf, length)) + eq(lfs.currentdir(), ffi.string(buf)) end) - it('returns OK and writes current directory into the buffer if it is large\n enough', function() - eq(OK, (os_dirname(buffer, length))) - eq(lfs.currentdir(), (ffi.string(buffer))) + itp('returns FAIL if the buffer is too small', function() + local length = string.len(lfs.currentdir()) + 1 + local buf = cstr(length - 1, '') + eq(FAIL, fs.os_dirname(buf, length - 1)) end) + end) - -- What kind of other failing cases are possible? - it('returns FAIL if the buffer is too small', function() - local buf = cstr((length - 1), '') - eq(FAIL, (os_dirname(buf, (length - 1)))) + describe('os_chdir', function() + itp('fails with path="~"', function() + eq(false, os_isdir('~')) -- sanity check: no literal "~" directory. + local length = 4096 + local expected_cwd = cstr(length, '') + local cwd = cstr(length, '') + eq(OK, fs.os_dirname(expected_cwd, length)) + + -- os_chdir returns 0 for success, not OK (1). + neq(0, fs.os_chdir('~')) -- fail + neq(0, fs.os_chdir('~/')) -- fail + + eq(OK, fs.os_dirname(cwd, length)) + -- CWD did not change. + eq(ffi.string(expected_cwd), ffi.string(cwd)) end) end) - local function os_isdir(name) - return fs.os_isdir((to_cstr(name))) - end - describe('os_isdir', function() - it('returns false if an empty string is given', function() + itp('returns false if an empty string is given', function() eq(false, (os_isdir(''))) end) - it('returns false if a nonexisting directory is given', function() + itp('returns false if a nonexisting directory is given', function() eq(false, (os_isdir('non-existing-directory'))) end) - it('returns false if a nonexisting absolute directory is given', function() + itp('returns false if a nonexisting absolute directory is given', function() eq(false, (os_isdir('/non-existing-directory'))) end) - it('returns false if an existing file is given', function() + itp('returns false if an existing file is given', function() eq(false, (os_isdir('unit-test-directory/test.file'))) end) - it('returns true if the current directory is given', function() + itp('returns true if the current directory is given', function() eq(true, (os_isdir('.'))) end) - it('returns true if the parent directory is given', function() + itp('returns true if the parent directory is given', function() eq(true, (os_isdir('..'))) end) - it('returns true if an arbitrary directory is given', function() + itp('returns true if an arbitrary directory is given', function() eq(true, (os_isdir('unit-test-directory'))) end) - it('returns true if an absolute directory is given', function() + itp('returns true if an absolute directory is given', function() eq(true, (os_isdir(directory))) end) end) @@ -181,27 +185,24 @@ describe('fs function', function() return os_can_exe(name) end - it('returns false when given a directory', function() + itp('returns false when given a directory', function() cant_exe('./unit-test-directory') end) - it('returns false when given a regular file without executable bit set', function() + itp('returns false when given a regular file without executable bit set', function() cant_exe('unit-test-directory/test.file') end) - it('returns false when the given file does not exists', function() + itp('returns false when the given file does not exists', function() cant_exe('does-not-exist.file') end) - it('returns the absolute path when given an executable inside $PATH', function() - -- Since executable_name does not start with "./", the path will be - -- selected from $PATH. Make sure the ends match, ignore the directories. - local _, busted = string.match(absolute_executable, '^(.*)/(.*)$') - local _, name = string.match(exe(executable_name), '^(.*)/(.*)$') - eq(busted, name) + itp('returns the absolute path when given an executable inside $PATH', function() + local fullpath = exe('ls') + eq(1, fs.path_is_absolute_path(to_cstr(fullpath))) end) - it('returns the absolute path when given an executable relative to the current dir', function() + itp('returns the absolute path when given an executable relative to the current dir', function() local old_dir = lfs.currentdir() lfs.chdir(directory) @@ -221,10 +222,6 @@ describe('fs function', function() end) describe('file permissions', function() - before_each(function() - os_setperm('unit-test-directory/test.file', orig_test_file_perm) - end) - local function os_fchown(filename, user_id, group_id) local fd = ffi.C.open(filename, 0) local res = fs.os_fchown(fd, user_id, group_id) @@ -245,22 +242,22 @@ describe('fs function', function() end describe('os_getperm', function() - it('returns UV_ENOENT when the given file does not exist', function() + itp('returns UV_ENOENT when the given file does not exist', function() eq(ffi.C.UV_ENOENT, (os_getperm('non-existing-file'))) end) - it('returns a perm > 0 when given an existing file', function() + itp('returns a perm > 0 when given an existing file', function() assert.is_true((os_getperm('unit-test-directory')) > 0) end) - it('returns S_IRUSR when the file is readable', function() + itp('returns S_IRUSR when the file is readable', function() local perm = os_getperm('unit-test-directory') assert.is_true((bit_set(perm, ffi.C.kS_IRUSR))) end) end) describe('os_setperm', function() - it('can set and unset the executable bit of a file', function() + itp('can set and unset the executable bit of a file', function() local perm = os_getperm('unit-test-directory/test.file') perm = unset_bit(perm, ffi.C.kS_IXUSR) eq(OK, (os_setperm('unit-test-directory/test.file', perm))) @@ -272,7 +269,7 @@ describe('fs function', function() assert.is_true((bit_set(perm, ffi.C.kS_IXUSR))) end) - it('fails if given file does not exist', function() + itp('fails if given file does not exist', function() local perm = ffi.C.kS_IXUSR eq(FAIL, (os_setperm('non-existing-file', perm))) end) @@ -280,7 +277,7 @@ describe('fs function', function() describe('os_fchown', function() local filename = 'unit-test-directory/test.file' - it('does not change owner and group if respective IDs are equal to -1', function() + itp('does not change owner and group if respective IDs are equal to -1', function() local uid = lfs.attributes(filename, 'uid') local gid = lfs.attributes(filename, 'gid') eq(0, os_fchown(filename, -1, -1)) @@ -292,7 +289,7 @@ describe('fs function', function() if (os.execute('id -G > /dev/null 2>&1') ~= 0) then pending('skipped (missing `id` utility)', function() end) else - it('owner of a file may change the group of the file to any group of which that owner is a member', function() + itp('owner of a file may change the group of the file to any group of which that owner is a member', function() local file_gid = lfs.attributes(filename, 'gid') -- Gets ID of any group of which current user is a member except the @@ -316,7 +313,7 @@ describe('fs function', function() if (ffi.os == 'Windows' or ffi.C.geteuid() == 0) then pending('skipped (uv_fs_chown is no-op on Windows)', function() end) else - it('returns nonzero if process has not enough permissions', function() + itp('returns nonzero if process has not enough permissions', function() -- chown to root neq(0, os_fchown(filename, 0, 0)) end) @@ -325,7 +322,7 @@ describe('fs function', function() describe('os_file_is_readable', function() - it('returns false if the file is not readable', function() + itp('returns false if the file is not readable', function() local perm = os_getperm('unit-test-directory/test.file') perm = unset_bit(perm, ffi.C.kS_IRUSR) perm = unset_bit(perm, ffi.C.kS_IRGRP) @@ -334,19 +331,19 @@ describe('fs function', function() eq(false, os_file_is_readable('unit-test-directory/test.file')) end) - it('returns false if the file does not exist', function() + itp('returns false if the file does not exist', function() eq(false, os_file_is_readable( 'unit-test-directory/what_are_you_smoking.gif')) end) - it('returns true if the file is readable', function() + itp('returns true if the file is readable', function() eq(true, os_file_is_readable( 'unit-test-directory/test.file')) end) end) describe('os_file_is_writable', function() - it('returns 0 if the file is readonly', function() + itp('returns 0 if the file is readonly', function() local perm = os_getperm('unit-test-directory/test.file') perm = unset_bit(perm, ffi.C.kS_IWUSR) perm = unset_bit(perm, ffi.C.kS_IWGRP) @@ -355,11 +352,11 @@ describe('fs function', function() eq(0, os_file_is_writable('unit-test-directory/test.file')) end) - it('returns 1 if the file is writable', function() + itp('returns 1 if the file is writable', function() eq(1, os_file_is_writable('unit-test-directory/test.file')) end) - it('returns 2 when given a folder with rights to write into', function() + itp('returns 2 when given a folder with rights to write into', function() eq(2, os_file_is_writable('unit-test-directory')) end) end) @@ -425,19 +422,19 @@ describe('fs function', function() end describe('os_path_exists', function() - it('returns false when given a non-existing file', function() + itp('returns false when given a non-existing file', function() eq(false, (os_path_exists('non-existing-file'))) end) - it('returns true when given an existing file', function() + itp('returns true when given an existing file', function() eq(true, (os_path_exists('unit-test-directory/test.file'))) end) - it('returns false when given a broken symlink', function() + itp('returns false when given a broken symlink', function() eq(false, (os_path_exists('unit-test-directory/test_broken_link.file'))) end) - it('returns true when given a directory', function() + itp('returns true when given a directory', function() eq(true, (os_path_exists('unit-test-directory'))) end) end) @@ -446,18 +443,18 @@ describe('fs function', function() local test = 'unit-test-directory/test.file' local not_exist = 'unit-test-directory/not_exist.file' - it('can rename file if destination file does not exist', function() + itp('can rename file if destination file does not exist', function() eq(OK, (os_rename(test, not_exist))) eq(false, (os_path_exists(test))) eq(true, (os_path_exists(not_exist))) eq(OK, (os_rename(not_exist, test))) -- restore test file end) - it('fail if source file does not exist', function() + itp('fail if source file does not exist', function() eq(FAIL, (os_rename(not_exist, test))) end) - it('can overwrite destination file if it exists', function() + itp('can overwrite destination file if it exists', function() local other = 'unit-test-directory/other.file' local file = io.open(other, 'w') file:write('other') @@ -482,11 +479,11 @@ describe('fs function', function() os.remove('unit-test-directory/test_remove.file') end) - it('returns non-zero when given a non-existing file', function() + itp('returns non-zero when given a non-existing file', function() neq(0, (os_remove('non-existing-file'))) end) - it('removes the given file and returns 0', function() + itp('removes the given file and returns 0', function() local f = 'unit-test-directory/test_remove.file' assert_file_exists(f) eq(0, (os_remove(f))) @@ -507,30 +504,30 @@ describe('fs function', function() os.remove(new_file) end) - it('returns UV_ENOENT for O_RDWR on a non-existing file', function() + itp('returns UV_ENOENT for O_RDWR on a non-existing file', function() eq(ffi.C.UV_ENOENT, (os_open('non-existing-file', ffi.C.kO_RDWR, 0))) end) - it('returns non-negative for O_CREAT on a non-existing file which then can be closed', function() + itp('returns non-negative for O_CREAT on a non-existing file which then can be closed', function() assert_file_does_not_exist(new_file) local fd = os_open(new_file, ffi.C.kO_CREAT, 0) assert.is_true(0 <= fd) eq(0, os_close(fd)) end) - it('returns non-negative for O_CREAT on a existing file which then can be closed', function() + itp('returns non-negative for O_CREAT on a existing file which then can be closed', function() assert_file_exists(existing_file) local fd = os_open(existing_file, ffi.C.kO_CREAT, 0) assert.is_true(0 <= fd) eq(0, os_close(fd)) end) - it('returns UV_EEXIST for O_CREAT|O_EXCL on a existing file', function() + itp('returns UV_EEXIST for O_CREAT|O_EXCL on a existing file', function() assert_file_exists(existing_file) eq(ffi.C.kUV_EEXIST, (os_open(existing_file, (bit.bor(ffi.C.kO_CREAT, ffi.C.kO_EXCL)), 0))) end) - it('sets `rwx` permissions for O_CREAT 700 which then can be closed', function() + itp('sets `rwx` permissions for O_CREAT 700 which then can be closed', function() assert_file_does_not_exist(new_file) --create the file local fd = os_open(new_file, ffi.C.kO_CREAT, tonumber("700", 8)) @@ -539,7 +536,7 @@ describe('fs function', function() eq(0, os_close(fd)) end) - it('sets `rw` permissions for O_CREAT 600 which then can be closed', function() + itp('sets `rw` permissions for O_CREAT 600 which then can be closed', function() assert_file_does_not_exist(new_file) --create the file local fd = os_open(new_file, ffi.C.kO_CREAT, tonumber("600", 8)) @@ -548,7 +545,7 @@ describe('fs function', function() eq(0, os_close(fd)) end) - it('returns a non-negative file descriptor for an existing file which then can be closed', function() + itp('returns a non-negative file descriptor for an existing file which then can be closed', function() local fd = os_open(existing_file, ffi.C.kO_RDWR, 0) assert.is_true(0 <= fd) eq(0, os_close(fd)) @@ -556,7 +553,7 @@ describe('fs function', function() end) describe('os_close', function() - it('returns EBADF for negative file descriptors', function() + itp('returns EBADF for negative file descriptors', function() eq(ffi.C.UV_EBADF, os_close(-1)) eq(ffi.C.UV_EBADF, os_close(-1000)) end) @@ -575,7 +572,7 @@ describe('fs function', function() os.remove(file) end) - it('can read zero bytes from a file', function() + itp('can read zero bytes from a file', function() local fd = os_open(file, ffi.C.kO_RDONLY, 0) ok(fd >= 0) eq({false, 0, ''}, {os_read(fd, nil)}) @@ -583,7 +580,7 @@ describe('fs function', function() eq(0, os_close(fd)) end) - it('can read from a file multiple times', function() + itp('can read from a file multiple times', function() local fd = os_open(file, ffi.C.kO_RDONLY, 0) ok(fd >= 0) eq({false, 2, '\000\001'}, {os_read(fd, 2)}) @@ -591,7 +588,7 @@ describe('fs function', function() eq(0, os_close(fd)) end) - it('can read the whole file at once and then report eof', function() + itp('can read the whole file at once and then report eof', function() local fd = os_open(file, ffi.C.kO_RDONLY, 0) ok(fd >= 0) eq({false, #fcontents, fcontents}, {os_read(fd, #fcontents)}) @@ -599,7 +596,7 @@ describe('fs function', function() eq(0, os_close(fd)) end) - it('can read the whole file in two calls, one partially', function() + itp('can read the whole file in two calls, one partially', function() local fd = os_open(file, ffi.C.kO_RDONLY, 0) ok(fd >= 0) eq({false, #fcontents * 3/4, fcontents:sub(1, #fcontents * 3/4)}, @@ -629,7 +626,7 @@ describe('fs function', function() os.remove(file) end) - it('can read zero bytes from a file', function() + itp('can read zero bytes from a file', function() local fd = os_open(file, ffi.C.kO_RDONLY, 0) ok(fd >= 0) eq({false, 0, {}}, {os_readv(fd, {})}) @@ -637,7 +634,7 @@ describe('fs function', function() eq(0, os_close(fd)) end) - it('can read from a file multiple times to a differently-sized buffers', function() + itp('can read from a file multiple times to a differently-sized buffers', function() local fd = os_open(file, ffi.C.kO_RDONLY, 0) ok(fd >= 0) eq({false, 2, {'\000\001'}}, {os_readv(fd, {2})}) @@ -645,7 +642,7 @@ describe('fs function', function() eq(0, os_close(fd)) end) - it('can read the whole file at once and then report eof', function() + itp('can read the whole file at once and then report eof', function() local fd = os_open(file, ffi.C.kO_RDONLY, 0) ok(fd >= 0) eq({false, @@ -662,7 +659,7 @@ describe('fs function', function() eq(0, os_close(fd)) end) - it('can read the whole file in two calls, one partially', function() + itp('can read the whole file in two calls, one partially', function() local fd = os_open(file, ffi.C.kO_RDONLY, 0) ok(fd >= 0) eq({false, #fcontents * 3/4, {fcontents:sub(1, #fcontents * 3/4)}}, @@ -689,7 +686,7 @@ describe('fs function', function() os.remove(file) end) - it('can write zero bytes to a file', function() + itp('can write zero bytes to a file', function() local fd = os_open(file, ffi.C.kO_WRONLY, 0) ok(fd >= 0) eq(0, os_write(fd, '')) @@ -698,7 +695,7 @@ describe('fs function', function() eq(0, os_close(fd)) end) - it('can write some data to a file', function() + itp('can write some data to a file', function() local fd = os_open(file, ffi.C.kO_WRONLY, 0) ok(fd >= 0) eq(3, os_write(fd, 'abc')) @@ -713,11 +710,11 @@ describe('fs function', function() os.remove('non-existing-file') end) - it('returns NODE_NORMAL for non-existing file', function() + itp('returns NODE_NORMAL for non-existing file', function() eq(NODE_NORMAL, fs.os_nodetype(to_cstr('non-existing-file'))) end) - it('returns NODE_WRITABLE for /dev/stderr', function() + itp('returns NODE_WRITABLE for /dev/stderr', function() eq(NODE_WRITABLE, fs.os_nodetype(to_cstr('/dev/stderr'))) end) end) @@ -743,12 +740,12 @@ describe('fs function', function() end describe('os_mkdir', function() - it('returns non-zero when given an already existing directory', function() + itp('returns non-zero when given an already existing directory', function() local mode = ffi.C.kS_IRUSR + ffi.C.kS_IWUSR + ffi.C.kS_IXUSR neq(0, (os_mkdir('unit-test-directory', mode))) end) - it('creates a directory and returns 0', function() + itp('creates a directory and returns 0', function() local mode = ffi.C.kS_IRUSR + ffi.C.kS_IWUSR + ffi.C.kS_IXUSR eq(false, (os_isdir('unit-test-directory/new-dir'))) eq(0, (os_mkdir('unit-test-directory/new-dir', mode))) @@ -758,14 +755,14 @@ describe('fs function', function() end) describe('os_mkdir_recurse', function() - it('returns zero when given an already existing directory', function() + itp('returns zero when given an already existing directory', function() local mode = ffi.C.kS_IRUSR + ffi.C.kS_IWUSR + ffi.C.kS_IXUSR local ret, failed_str = os_mkdir_recurse('unit-test-directory', mode) eq(0, ret) eq(nil, failed_str) end) - it('fails to create a directory where there is a file', function() + itp('fails to create a directory where there is a file', function() local mode = ffi.C.kS_IRUSR + ffi.C.kS_IWUSR + ffi.C.kS_IXUSR local ret, failed_str = os_mkdir_recurse( 'unit-test-directory/test.file', mode) @@ -773,7 +770,7 @@ describe('fs function', function() eq('unit-test-directory/test.file', failed_str) end) - it('fails to create a directory where there is a file in path', function() + itp('fails to create a directory where there is a file in path', function() local mode = ffi.C.kS_IRUSR + ffi.C.kS_IWUSR + ffi.C.kS_IXUSR local ret, failed_str = os_mkdir_recurse( 'unit-test-directory/test.file/test', mode) @@ -781,7 +778,7 @@ describe('fs function', function() eq('unit-test-directory/test.file', failed_str) end) - it('succeeds to create a directory', function() + itp('succeeds to create a directory', function() local mode = ffi.C.kS_IRUSR + ffi.C.kS_IWUSR + ffi.C.kS_IXUSR local ret, failed_str = os_mkdir_recurse( 'unit-test-directory/new-dir-recurse', mode) @@ -792,7 +789,7 @@ describe('fs function', function() eq(false, os_isdir('unit-test-directory/new-dir-recurse')) end) - it('succeeds to create a directory ending with ///', function() + itp('succeeds to create a directory ending with ///', function() local mode = ffi.C.kS_IRUSR + ffi.C.kS_IWUSR + ffi.C.kS_IXUSR local ret, failed_str = os_mkdir_recurse( 'unit-test-directory/new-dir-recurse///', mode) @@ -803,7 +800,7 @@ describe('fs function', function() eq(false, os_isdir('unit-test-directory/new-dir-recurse')) end) - it('succeeds to create a directory ending with /', function() + itp('succeeds to create a directory ending with /', function() local mode = ffi.C.kS_IRUSR + ffi.C.kS_IWUSR + ffi.C.kS_IXUSR local ret, failed_str = os_mkdir_recurse( 'unit-test-directory/new-dir-recurse/', mode) @@ -814,7 +811,7 @@ describe('fs function', function() eq(false, os_isdir('unit-test-directory/new-dir-recurse')) end) - it('succeeds to create a directory tree', function() + itp('succeeds to create a directory tree', function() local mode = ffi.C.kS_IRUSR + ffi.C.kS_IWUSR + ffi.C.kS_IXUSR local ret, failed_str = os_mkdir_recurse( 'unit-test-directory/new-dir-recurse/1/2/3', mode) @@ -833,11 +830,11 @@ describe('fs function', function() end) describe('os_rmdir', function() - it('returns non_zero when given a non-existing directory', function() + itp('returns non_zero when given a non-existing directory', function() neq(0, (os_rmdir('non-existing-directory'))) end) - it('removes the given directory and returns 0', function() + itp('removes the given directory and returns 0', function() lfs.mkdir('unit-test-directory/new-dir') eq(0, os_rmdir('unit-test-directory/new-dir')) eq(false, (os_isdir('unit-test-directory/new-dir'))) @@ -865,19 +862,24 @@ describe('fs function', function() end describe('os_fileinfo', function() - it('returns false if given a non-existing file', function() + itp('returns false if path=NULL', function() + local file_info = file_info_new() + assert.is_false((fs.os_fileinfo(nil, file_info))) + end) + + itp('returns false if given a non-existing file', function() local file_info = file_info_new() assert.is_false((fs.os_fileinfo('/non-existent', file_info))) end) - it('returns true if given an existing file and fills file_info', function() + itp('returns true if given an existing file and fills file_info', function() local file_info = file_info_new() local path = 'unit-test-directory/test.file' assert.is_true((fs.os_fileinfo(path, file_info))) assert.is_true((is_file_info_filled(file_info))) end) - it('returns the file info of the linked file, not the link', function() + itp('returns the file info of the linked file, not the link', function() local file_info = file_info_new() local path = 'unit-test-directory/test_link.file' assert.is_true((fs.os_fileinfo(path, file_info))) @@ -888,19 +890,19 @@ describe('fs function', function() end) describe('os_fileinfo_link', function() - it('returns false if given a non-existing file', function() + itp('returns false if given a non-existing file', function() local file_info = file_info_new() assert.is_false((fs.os_fileinfo_link('/non-existent', file_info))) end) - it('returns true if given an existing file and fills file_info', function() + itp('returns true if given an existing file and fills file_info', function() local file_info = file_info_new() local path = 'unit-test-directory/test.file' assert.is_true((fs.os_fileinfo_link(path, file_info))) assert.is_true((is_file_info_filled(file_info))) end) - it('returns the file info of the link, not the linked file', function() + itp('returns the file info of the link, not the linked file', function() local file_info = file_info_new() local path = 'unit-test-directory/test_link.file' assert.is_true((fs.os_fileinfo_link(path, file_info))) @@ -911,12 +913,12 @@ describe('fs function', function() end) describe('os_fileinfo_fd', function() - it('returns false if given an invalid file descriptor', function() + itp('returns false if given an invalid file descriptor', function() local file_info = file_info_new() assert.is_false((fs.os_fileinfo_fd(-1, file_info))) end) - it('returns true if given a file descriptor and fills file_info', function() + itp('returns true if given a file descriptor and fills file_info', function() local file_info = file_info_new() local path = 'unit-test-directory/test.file' local fd = ffi.C.open(path, 0) @@ -927,7 +929,7 @@ describe('fs function', function() end) describe('os_fileinfo_id_equal', function() - it('returns false if file infos represent different files', function() + itp('returns false if file infos represent different files', function() local file_info_1 = file_info_new() local file_info_2 = file_info_new() local path_1 = 'unit-test-directory/test.file' @@ -937,7 +939,7 @@ describe('fs function', function() assert.is_false((fs.os_fileinfo_id_equal(file_info_1, file_info_2))) end) - it('returns true if file infos represent the same file', function() + itp('returns true if file infos represent the same file', function() local file_info_1 = file_info_new() local file_info_2 = file_info_new() local path = 'unit-test-directory/test.file' @@ -946,7 +948,7 @@ describe('fs function', function() assert.is_true((fs.os_fileinfo_id_equal(file_info_1, file_info_2))) end) - it('returns true if file infos represent the same file (symlink)', function() + itp('returns true if file infos represent the same file (symlink)', function() local file_info_1 = file_info_new() local file_info_2 = file_info_new() local path_1 = 'unit-test-directory/test.file' @@ -958,7 +960,7 @@ describe('fs function', function() end) describe('os_fileinfo_id', function() - it('extracts ino/dev from file_info into file_id', function() + itp('extracts ino/dev from file_info into file_id', function() local file_info = file_info_new() local file_id = file_id_new() local path = 'unit-test-directory/test.file' @@ -970,7 +972,7 @@ describe('fs function', function() end) describe('os_fileinfo_inode', function() - it('returns the inode from file_info', function() + itp('returns the inode from file_info', function() local file_info = file_info_new() local path = 'unit-test-directory/test.file' assert.is_true((fs.os_fileinfo(path, file_info))) @@ -980,7 +982,7 @@ describe('fs function', function() end) describe('os_fileinfo_size', function() - it('returns the correct size of a file', function() + itp('returns the correct size of a file', function() local path = 'unit-test-directory/test.file' local file = io.open(path, 'w') file:write('some bytes to get filesize != 0') @@ -994,7 +996,7 @@ describe('fs function', function() end) describe('os_fileinfo_hardlinks', function() - it('returns the correct number of hardlinks', function() + itp('returns the correct number of hardlinks', function() local path = 'unit-test-directory/test.file' local path_link = 'unit-test-directory/test_hlink.file' local file_info = file_info_new() @@ -1007,7 +1009,7 @@ describe('fs function', function() end) describe('os_fileinfo_blocksize', function() - it('returns the correct blocksize of a file', function() + itp('returns the correct blocksize of a file', function() local path = 'unit-test-directory/test.file' -- there is a bug in luafilesystem where -- `lfs.attributes path, 'blksize'` returns the worng value: @@ -1028,12 +1030,12 @@ describe('fs function', function() end) describe('os_fileid', function() - it('returns false if given an non-existing file', function() + itp('returns false if given an non-existing file', function() local file_id = file_id_new() assert.is_false((fs.os_fileid('/non-existent', file_id))) end) - it('returns true if given an existing file and fills file_id', function() + itp('returns true if given an existing file and fills file_id', function() local file_id = file_id_new() local path = 'unit-test-directory/test.file' assert.is_true((fs.os_fileid(path, file_id))) @@ -1043,14 +1045,14 @@ describe('fs function', function() end) describe('os_fileid_equal', function() - it('returns true if two FileIDs are equal', function() + itp('returns true if two FileIDs are equal', function() local file_id = file_id_new() local path = 'unit-test-directory/test.file' assert.is_true((fs.os_fileid(path, file_id))) assert.is_true((fs.os_fileid_equal(file_id, file_id))) end) - it('returns false if two FileIDs are not equal', function() + itp('returns false if two FileIDs are not equal', function() local file_id_1 = file_id_new() local file_id_2 = file_id_new() local path_1 = 'unit-test-directory/test.file' @@ -1062,7 +1064,7 @@ describe('fs function', function() end) describe('os_fileid_equal_fileinfo', function() - it('returns true if file_id and file_info represent the same file', function() + itp('returns true if file_id and file_info represent the same file', function() local file_id = file_id_new() local file_info = file_info_new() local path = 'unit-test-directory/test.file' @@ -1071,7 +1073,7 @@ describe('fs function', function() assert.is_true((fs.os_fileid_equal_fileinfo(file_id, file_info))) end) - it('returns false if file_id and file_info represent different files', function() + itp('returns false if file_id and file_info represent different files', function() local file_id = file_id_new() local file_info = file_info_new() local path_1 = 'unit-test-directory/test.file' diff --git a/test/unit/os/shell_spec.lua b/test/unit/os/shell_spec.lua index 3603403daf..37274502de 100644 --- a/test/unit/os/shell_spec.lua +++ b/test/unit/os/shell_spec.lua @@ -1,4 +1,5 @@ -local helpers = require('test.unit.helpers') +local helpers = require('test.unit.helpers')(after_each) +local itp = helpers.gen_itp(it) local cimported = helpers.cimport( './src/nvim/os/shell.h', './src/nvim/option_defs.h', @@ -14,7 +15,7 @@ local NULL = ffi.cast('void *', 0) describe('shell functions', function() before_each(function() -- os_system() can't work when the p_sh and p_shcf variables are unset - cimported.p_sh = to_cstr('/bin/bash') + cimported.p_sh = to_cstr('/bin/sh') cimported.p_shcf = to_cstr('-c') cimported.p_sxq = to_cstr('') cimported.p_sxe = to_cstr('') @@ -51,63 +52,51 @@ describe('shell functions', function() end describe('os_system', function() - it('can echo some output (shell builtin)', function() - local cmd, text = 'echo -n', 'some text' + itp('can echo some output (shell builtin)', function() + local cmd, text = 'printf "%s "', 'some text ' local status, output = os_system(cmd .. ' ' .. text) eq(text, output) eq(0, status) end) - it('can deal with empty output', function() - local cmd = 'echo -n' + itp('can deal with empty output', function() + local cmd = 'printf ""' local status, output = os_system(cmd) eq('', output) eq(0, status) end) - it('can pass input on stdin', function() + itp('can pass input on stdin', function() local cmd, input = 'cat -', 'some text\nsome other text' local status, output = os_system(cmd, input) eq(input, output) eq(0, status) end) - it ('returns non-zero exit code', function() + itp('returns non-zero exit code', function() local status = os_system('exit 2') eq(2, status) end) end) describe('shell_build_argv', function() - local saved_opts = {} - - setup(function() - saved_opts.p_sh = cimported.p_sh - saved_opts.p_shcf = cimported.p_shcf - end) - - teardown(function() - cimported.p_sh = saved_opts.p_sh - cimported.p_shcf = saved_opts.p_shcf - end) - - it('works with NULL arguments', function() - eq({'/bin/bash'}, shell_build_argv(nil, nil)) + itp('works with NULL arguments', function() + eq({'/bin/sh'}, shell_build_argv(nil, nil)) end) - it('works with cmd', function() - eq({'/bin/bash', '-c', 'abc def'}, shell_build_argv('abc def', nil)) + itp('works with cmd', function() + eq({'/bin/sh', '-c', 'abc def'}, shell_build_argv('abc def', nil)) end) - it('works with extra_args', function() - eq({'/bin/bash', 'ghi jkl'}, shell_build_argv(nil, 'ghi jkl')) + itp('works with extra_args', function() + eq({'/bin/sh', 'ghi jkl'}, shell_build_argv(nil, 'ghi jkl')) end) - it('works with cmd and extra_args', function() - eq({'/bin/bash', 'ghi jkl', '-c', 'abc def'}, shell_build_argv('abc def', 'ghi jkl')) + itp('works with cmd and extra_args', function() + eq({'/bin/sh', 'ghi jkl', '-c', 'abc def'}, shell_build_argv('abc def', 'ghi jkl')) end) - it('splits and unquotes &shell and &shellcmdflag', function() + itp('splits and unquotes &shell and &shellcmdflag', function() cimported.p_sh = to_cstr('/Program" "Files/zsh -f') cimported.p_shcf = to_cstr('-x -o "sh word split" "-"c') eq({'/Program Files/zsh', '-f', @@ -117,46 +106,46 @@ describe('shell functions', function() shell_build_argv('abc def', 'ghi jkl')) end) - it('applies shellxescape (p_sxe) and shellxquote (p_sxq)', function() + itp('applies shellxescape (p_sxe) and shellxquote (p_sxq)', function() cimported.p_sxq = to_cstr('(') cimported.p_sxe = to_cstr('"&|<>()@^') local argv = ffi.cast('char**', cimported.shell_build_argv(to_cstr('echo &|<>()@^'), nil)) - eq(ffi.string(argv[0]), '/bin/bash') + eq(ffi.string(argv[0]), '/bin/sh') eq(ffi.string(argv[1]), '-c') eq(ffi.string(argv[2]), '(echo ^&^|^<^>^(^)^@^^)') eq(nil, argv[3]) end) - it('applies shellxquote="(', function() + itp('applies shellxquote="(', function() cimported.p_sxq = to_cstr('"(') cimported.p_sxe = to_cstr('"&|<>()@^') local argv = ffi.cast('char**', cimported.shell_build_argv( to_cstr('echo -n some text'), nil)) - eq(ffi.string(argv[0]), '/bin/bash') + eq(ffi.string(argv[0]), '/bin/sh') eq(ffi.string(argv[1]), '-c') eq(ffi.string(argv[2]), '"(echo -n some text)"') eq(nil, argv[3]) end) - it('applies shellxquote="', function() + itp('applies shellxquote="', function() cimported.p_sxq = to_cstr('"') cimported.p_sxe = to_cstr('') local argv = ffi.cast('char**', cimported.shell_build_argv( to_cstr('echo -n some text'), nil)) - eq(ffi.string(argv[0]), '/bin/bash') + eq(ffi.string(argv[0]), '/bin/sh') eq(ffi.string(argv[1]), '-c') eq(ffi.string(argv[2]), '"echo -n some text"') eq(nil, argv[3]) end) - it('with empty shellxquote/shellxescape', function() + itp('with empty shellxquote/shellxescape', function() local argv = ffi.cast('char**', cimported.shell_build_argv( to_cstr('echo -n some text'), nil)) - eq(ffi.string(argv[0]), '/bin/bash') + eq(ffi.string(argv[0]), '/bin/sh') eq(ffi.string(argv[1]), '-c') eq(ffi.string(argv[2]), 'echo -n some text') eq(nil, argv[3]) diff --git a/test/unit/os/users_spec.lua b/test/unit/os/users_spec.lua index 236481e9e7..f92413c7de 100644 --- a/test/unit/os/users_spec.lua +++ b/test/unit/os/users_spec.lua @@ -1,4 +1,5 @@ -local helpers = require('test.unit.helpers') +local helpers = require('test.unit.helpers')(after_each) +local itp = helpers.gen_itp(it) local cimport = helpers.cimport local eq = helpers.eq @@ -27,11 +28,11 @@ describe('users function', function() local current_username = os.getenv('USER') describe('os_get_usernames', function() - it('returns FAIL if called with NULL', function() + itp('returns FAIL if called with NULL', function() eq(FAIL, users.os_get_usernames(NULL)) end) - it('fills the names garray with os usernames and returns OK', function() + itp('fills the names garray with os usernames and returns OK', function() local ga_users = garray_new() eq(OK, users.os_get_usernames(ga_users)) local user_count = garray_get_len(ga_users) @@ -48,7 +49,7 @@ describe('users function', function() end) describe('os_get_user_name', function() - it('should write the username into the buffer and return OK', function() + itp('should write the username into the buffer and return OK', function() local name_out = ffi.new('char[100]') eq(OK, users.os_get_user_name(name_out, 100)) eq(current_username, ffi.string(name_out)) @@ -56,14 +57,14 @@ describe('users function', function() end) describe('os_get_uname', function() - it('should write the username into the buffer and return OK', function() + itp('should write the username into the buffer and return OK', function() local name_out = ffi.new('char[100]') local user_id = lib.getuid() eq(OK, users.os_get_uname(user_id, name_out, 100)) eq(current_username, ffi.string(name_out)) end) - it('should FAIL if the userid is not found', function() + itp('should FAIL if the userid is not found', function() local name_out = ffi.new('char[100]') -- hoping nobody has this uid local user_id = 2342 @@ -73,16 +74,16 @@ describe('users function', function() end) describe('os_get_user_directory', function() - it('should return NULL if called with NULL', function() + itp('should return NULL if called with NULL', function() eq(NULL, users.os_get_user_directory(NULL)) end) - it('should return $HOME for the current user', function() + itp('should return $HOME for the current user', function() local home = os.getenv('HOME') eq(home, ffi.string((users.os_get_user_directory(current_username)))) end) - it('should return NULL if the user is not found', function() + itp('should return NULL if the user is not found', function() eq(NULL, users.os_get_user_directory('neovim_user_not_found_test')) end) end) diff --git a/test/unit/path_spec.lua b/test/unit/path_spec.lua index ccaf0228ab..a9cba7df84 100644 --- a/test/unit/path_spec.lua +++ b/test/unit/path_spec.lua @@ -1,5 +1,6 @@ local lfs = require('lfs') -local helpers = require('test.unit.helpers') +local helpers = require('test.unit.helpers')(after_each) +local itp = helpers.gen_itp(it) local cimport = helpers.cimport local eq = helpers.eq @@ -12,19 +13,12 @@ local OK = helpers.OK local FAIL = helpers.FAIL cimport('string.h') -local path = cimport('./src/nvim/path.h') - --- import constants parsed by ffi -local kEqualFiles = path.kEqualFiles -local kDifferentFiles = path.kDifferentFiles -local kBothFilesMissing = path.kBothFilesMissing -local kOneFileMissing = path.kOneFileMissing -local kEqualFileNames = path.kEqualFileNames +local cimp = cimport('./src/nvim/os/os.h', './src/nvim/path.h') local length = 0 local buffer = nil -describe('path function', function() +describe('path.c', function() describe('path_full_dir_name', function() setup(function() lfs.mkdir('unit-test-directory') @@ -36,7 +30,7 @@ describe('path function', function() local function path_full_dir_name(directory, buf, len) directory = to_cstr(directory) - return path.path_full_dir_name(directory, buf, len) + return cimp.path_full_dir_name(directory, buf, len) end before_each(function() @@ -45,7 +39,7 @@ describe('path function', function() buffer = cstr(length, '') end) - it('returns the absolute directory name of a given relative one', function() + itp('returns the absolute directory name of a given relative one', function() local result = path_full_dir_name('..', buffer, length) eq(OK, result) local old_dir = lfs.currentdir() @@ -55,16 +49,16 @@ describe('path function', function() eq(expected, (ffi.string(buffer))) end) - it('returns the current directory name if the given string is empty', function() + itp('returns the current directory name if the given string is empty', function() eq(OK, (path_full_dir_name('', buffer, length))) eq(lfs.currentdir(), (ffi.string(buffer))) end) - it('fails if the given directory does not exist', function() + itp('fails if the given directory does not exist', function() eq(FAIL, path_full_dir_name('does_not_exist', buffer, length)) end) - it('works with a normal relative dir', function() + itp('works with a normal relative dir', function() local result = path_full_dir_name('unit-test-directory', buffer, length) eq(lfs.currentdir() .. '/unit-test-directory', (ffi.string(buffer))) eq(OK, result) @@ -75,7 +69,7 @@ describe('path function', function() local function path_full_compare(s1, s2, cn) s1 = to_cstr(s1) s2 = to_cstr(s2) - return path.path_full_compare(s1, s2, cn or 0) + return cimp.path_full_compare(s1, s2, cn or 0) end local f1 = 'f1.o' @@ -91,70 +85,70 @@ describe('path function', function() os.remove(f2) end) - it('returns kEqualFiles when passed the same file', function() - eq(kEqualFiles, (path_full_compare(f1, f1))) + itp('returns kEqualFiles when passed the same file', function() + eq(cimp.kEqualFiles, (path_full_compare(f1, f1))) end) - it('returns kEqualFileNames when files that dont exist and have same name', function() - eq(kEqualFileNames, (path_full_compare('null.txt', 'null.txt', true))) + itp('returns kEqualFileNames when files that dont exist and have same name', function() + eq(cimp.kEqualFileNames, (path_full_compare('null.txt', 'null.txt', true))) end) - it('returns kBothFilesMissing when files that dont exist', function() - eq(kBothFilesMissing, (path_full_compare('null.txt', 'null.txt'))) + itp('returns kBothFilesMissing when files that dont exist', function() + eq(cimp.kBothFilesMissing, (path_full_compare('null.txt', 'null.txt'))) end) - it('returns kDifferentFiles when passed different files', function() - eq(kDifferentFiles, (path_full_compare(f1, f2))) - eq(kDifferentFiles, (path_full_compare(f2, f1))) + itp('returns kDifferentFiles when passed different files', function() + eq(cimp.kDifferentFiles, (path_full_compare(f1, f2))) + eq(cimp.kDifferentFiles, (path_full_compare(f2, f1))) end) - it('returns kOneFileMissing if only one does not exist', function() - eq(kOneFileMissing, (path_full_compare(f1, 'null.txt'))) - eq(kOneFileMissing, (path_full_compare('null.txt', f1))) + itp('returns kOneFileMissing if only one does not exist', function() + eq(cimp.kOneFileMissing, (path_full_compare(f1, 'null.txt'))) + eq(cimp.kOneFileMissing, (path_full_compare('null.txt', f1))) end) end) describe('path_tail', function() local function path_tail(file) - local res = path.path_tail((to_cstr(file))) + local res = cimp.path_tail((to_cstr(file))) neq(NULL, res) return ffi.string(res) end - it('returns the tail of a given file path', function() + itp('returns the tail of a given file path', function() eq('file.txt', path_tail('directory/file.txt')) end) - it('returns an empty string if file ends in a slash', function() + itp('returns an empty string if file ends in a slash', function() eq('', path_tail('directory/')) end) end) describe('path_tail_with_sep', function() local function path_tail_with_sep(file) - local res = path.path_tail_with_sep((to_cstr(file))) + local res = cimp.path_tail_with_sep((to_cstr(file))) neq(NULL, res) return ffi.string(res) end - it('returns the tail of a file together with its separator', function() + itp('returns the tail of a file together with its separator', function() eq('///file.txt', path_tail_with_sep('directory///file.txt')) end) - it('returns an empty string when given an empty file name', function() + itp('returns an empty string when given an empty file name', function() eq('', path_tail_with_sep('')) end) - it('returns only the separator if there is a trailing separator', function() + itp('returns only the separator if there is a trailing separator', function() eq('/', path_tail_with_sep('some/directory/')) end) - it('cuts a leading separator', function() + itp('cuts a leading separator', function() eq('file.txt', path_tail_with_sep('/file.txt')) eq('', path_tail_with_sep('/')) end) - it('returns the whole file name if there is no separator', function() + itp('returns the whole file name if there is no separator', function() eq('file.txt', path_tail_with_sep('file.txt')) end) end) @@ -165,11 +159,11 @@ describe('path function', function() -- strcmp. local function invocation_path_tail(invk) local plen = ffi.new('size_t[?]', 1) - local ptail = path.invocation_path_tail((to_cstr(invk)), plen) + local ptail = cimp.invocation_path_tail((to_cstr(invk)), plen) neq(NULL, ptail) -- it does not change the output if len==NULL - local tail2 = path.invocation_path_tail((to_cstr(invk)), NULL) + local tail2 = cimp.invocation_path_tail((to_cstr(invk)), NULL) neq(NULL, tail2) eq((ffi.string(ptail)), (ffi.string(tail2))) return ptail, plen[0] @@ -180,13 +174,13 @@ describe('path function', function() return eq(0, (ffi.C.strncmp((to_cstr(base)), pinvk, len))) end - it('returns the executable name of an invocation given a relative invocation', function() + itp('returns the executable name of an invocation given a relative invocation', function() local invk, len = invocation_path_tail('directory/exe a b c') compare("exe a b c", invk, len) eq(3, len) end) - it('returns the executable name of an invocation given an absolute invocation', function() + itp('returns the executable name of an invocation given an absolute invocation', function() if ffi.os == 'Windows' then local invk, len = invocation_path_tail('C:\\Users\\anyone\\Program Files\\z a b') compare('z a b', invk, len) @@ -198,27 +192,27 @@ describe('path function', function() end end) - it('does not count arguments to the executable as part of its path', function() + itp('does not count arguments to the executable as part of its path', function() local invk, len = invocation_path_tail('exe a/b\\c') compare("exe a/b\\c", invk, len) eq(3, len) end) - it('only accepts whitespace as a terminator for the executable name', function() + itp('only accepts whitespace as a terminator for the executable name', function() local invk, _ = invocation_path_tail('exe-a+b_c[]()|#!@$%^&*') eq('exe-a+b_c[]()|#!@$%^&*', (ffi.string(invk))) end) - it('is equivalent to path_tail when args do not contain a path separator', function() - local ptail = path.path_tail(to_cstr("a/b/c x y z")) + itp('is equivalent to path_tail when args do not contain a path separator', function() + local ptail = cimp.path_tail(to_cstr("a/b/c x y z")) neq(NULL, ptail) local tail = ffi.string(ptail) local invk, _ = invocation_path_tail("a/b/c x y z") eq(tail, ffi.string(invk)) end) - it('is not equivalent to path_tail when args contain a path separator', function() - local ptail = path.path_tail(to_cstr("a/b/c x y/z")) + itp('is not equivalent to path_tail when args contain a path separator', function() + local ptail = cimp.path_tail(to_cstr("a/b/c x y/z")) neq(NULL, ptail) local invk, _ = invocation_path_tail("a/b/c x y/z") neq((ffi.string(ptail)), (ffi.string(invk))) @@ -227,42 +221,42 @@ describe('path function', function() describe('path_next_component', function() local function path_next_component(file) - local res = path.path_next_component((to_cstr(file))) + local res = cimp.path_next_component((to_cstr(file))) neq(NULL, res) return ffi.string(res) end - it('returns', function() + itp('returns', function() eq('directory/file.txt', path_next_component('some/directory/file.txt')) end) - it('returns empty string if given file contains no separator', function() + itp('returns empty string if given file contains no separator', function() eq('', path_next_component('file.txt')) end) end) describe('path_shorten_fname', function() - it('returns NULL if `full_path` is NULL', function() + itp('returns NULL if `full_path` is NULL', function() local dir = to_cstr('some/directory/file.txt') - eq(NULL, (path.path_shorten_fname(NULL, dir))) + eq(NULL, (cimp.path_shorten_fname(NULL, dir))) end) - it('returns NULL if the path and dir does not match', function() + itp('returns NULL if the path and dir does not match', function() local dir = to_cstr('not/the/same') local full = to_cstr('as/this.txt') - eq(NULL, (path.path_shorten_fname(full, dir))) + eq(NULL, (cimp.path_shorten_fname(full, dir))) end) - it('returns NULL if the path is not separated properly', function() + itp('returns NULL if the path is not separated properly', function() local dir = to_cstr('some/very/long/') local full = to_cstr('some/very/long/directory/file.txt') - eq(NULL, (path.path_shorten_fname(full, dir))) + eq(NULL, (cimp.path_shorten_fname(full, dir))) end) - it('shortens the filename if `dir_name` is the start of `full_path`', function() + itp('shortens the filename if `dir_name` is the start of `full_path`', function() local full = to_cstr('some/very/long/directory/file.txt') local dir = to_cstr('some/very/long') - eq('directory/file.txt', (ffi.string(path.path_shorten_fname(full, dir)))) + eq('directory/file.txt', (ffi.string(cimp.path_shorten_fname(full, dir)))) end) end) end) @@ -280,26 +274,79 @@ describe('path_shorten_fname_if_possible', function() end) describe('path_shorten_fname_if_possible', function() - it('returns shortened path if possible', function() + itp('returns shortened path if possible', function() lfs.chdir('ut_directory') local full = to_cstr(lfs.currentdir() .. '/subdir/file.txt') - eq('subdir/file.txt', (ffi.string(path.path_shorten_fname_if_possible(full)))) + eq('subdir/file.txt', (ffi.string(cimp.path_shorten_fname_if_possible(full)))) end) - it('returns `full_path` if a shorter version is not possible', function() + itp('returns `full_path` if a shorter version is not possible', function() local old = lfs.currentdir() lfs.chdir('ut_directory') local full = old .. '/subdir/file.txt' - eq(full, (ffi.string(path.path_shorten_fname_if_possible(to_cstr(full))))) + eq(full, (ffi.string(cimp.path_shorten_fname_if_possible(to_cstr(full))))) end) - it('returns NULL if `full_path` is NULL', function() - eq(NULL, (path.path_shorten_fname_if_possible(NULL))) + itp('returns NULL if `full_path` is NULL', function() + eq(NULL, (cimp.path_shorten_fname_if_possible(NULL))) end) end) end) -describe('more path function', function() +describe('path.c path_guess_exepath', function() + local cwd = lfs.currentdir() + + for _,name in ipairs({'./nvim', '.nvim', 'foo/nvim'}) do + itp('"'..name..'" returns name catenated with CWD', function() + local bufsize = 255 + local buf = cstr(bufsize, '') + cimp.path_guess_exepath(name, buf, bufsize) + eq(cwd..'/'..name, ffi.string(buf)) + end) + end + + itp('absolute path returns the name unmodified', function() + local name = '/foo/bar/baz' + local bufsize = 255 + local buf = cstr(bufsize, '') + cimp.path_guess_exepath(name, buf, bufsize) + eq(name, ffi.string(buf)) + end) + + itp('returns the name unmodified if not found in $PATH', function() + local name = '23u0293_not_in_path' + local bufsize = 255 + local buf = cstr(bufsize, '') + cimp.path_guess_exepath(name, buf, bufsize) + eq(name, ffi.string(buf)) + end) + + itp('does not crash if $PATH item exceeds MAXPATHL', function() + local orig_path_env = os.getenv('PATH') + local name = 'cat' -- Some executable in $PATH. + local bufsize = 255 + local buf = cstr(bufsize, '') + local insane_path = orig_path_env..':'..(("x/"):rep(4097)) + + cimp.os_setenv('PATH', insane_path, true) + cimp.path_guess_exepath(name, buf, bufsize) + eq('bin/' .. name, ffi.string(buf):sub(-#('bin/' .. name), -1)) + + -- Restore $PATH. + cimp.os_setenv('PATH', orig_path_env, true) + end) + + itp('returns full path found in $PATH', function() + local name = 'cat' -- Some executable in $PATH. + local bufsize = 255 + local buf = cstr(bufsize, '') + cimp.path_guess_exepath(name, buf, bufsize) + -- Usually "/bin/cat" on unix, "/path/to/nvim/cat" on Windows. + eq('bin/' .. name, ffi.string(buf):sub(-#('bin/' .. name), -1)) + end) +end) + +describe('path.c', function() setup(function() lfs.mkdir('unit-test-directory'); io.open('unit-test-directory/test.file', 'w').close() @@ -321,7 +368,7 @@ describe('more path function', function() describe('vim_FullName', function() local function vim_FullName(filename, buf, len, force) filename = to_cstr(filename) - return path.vim_FullName(filename, buf, len, force) + return cimp.vim_FullName(filename, buf, len, force) end before_each(function() @@ -330,24 +377,24 @@ describe('more path function', function() buffer = cstr(length, '') end) - it('fails if given filename is NULL', function() + itp('fails if given filename is NULL', function() local force_expansion = 1 - local result = path.vim_FullName(NULL, buffer, length, force_expansion) + local result = cimp.vim_FullName(NULL, buffer, length, force_expansion) eq(FAIL, result) end) - it('fails safely if given length is wrong #5737', function() + itp('fails safely if given length is wrong #5737', function() local force_expansion = 1 local filename = 'foo/bar/bazzzzzzz/buz/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/a' local too_short_len = 8 local buf = cstr(too_short_len, '') - local result = path.vim_FullName(filename, buf, too_short_len, force_expansion) + local result = cimp.vim_FullName(filename, buf, too_short_len, force_expansion) local expected = string.sub(filename, 1, (too_short_len - 1)) eq(expected, (ffi.string(buf))) eq(FAIL, result) end) - it('uses the filename if the filename is a URL', function() + itp('uses the filename if the filename is a URL', function() local force_expansion = 1 local filename = 'http://www.neovim.org' local result = vim_FullName(filename, buffer, length, force_expansion) @@ -355,7 +402,7 @@ describe('more path function', function() eq(OK, result) end) - it('fails and uses filename if given filename contains non-existing directory', function() + itp('fails and uses filename if given filename contains non-existing directory', function() local force_expansion = 1 local filename = 'non_existing_dir/test.file' local result = vim_FullName(filename, buffer, length, force_expansion) @@ -363,7 +410,7 @@ describe('more path function', function() eq(FAIL, result) end) - it('concatenates given filename if it does not contain a slash', function() + itp('concatenates filename if it does not contain a slash', function() local force_expansion = 1 local result = vim_FullName('test.file', buffer, length, force_expansion) local expected = lfs.currentdir() .. '/test.file' @@ -371,7 +418,7 @@ describe('more path function', function() eq(OK, result) end) - it('concatenates given filename if it is a directory but does not contain a\n slash', function() + itp('concatenates directory name if it does not contain a slash', function() local force_expansion = 1 local result = vim_FullName('..', buffer, length, force_expansion) local expected = lfs.currentdir() .. '/..' @@ -381,7 +428,7 @@ describe('more path function', function() -- Is it possible for every developer to enter '..' directory while running -- the unit tests? Which other directory would be better? - it('enters given directory (instead of just concatenating the strings) if possible and if path contains a slash', function() + itp('enters given directory (instead of just concatenating the strings) if possible and if path contains a slash', function() local force_expansion = 1 local result = vim_FullName('../test.file', buffer, length, force_expansion) local old_dir = lfs.currentdir() @@ -392,7 +439,7 @@ describe('more path function', function() eq(OK, result) end) - it('just copies the path if it is already absolute and force=0', function() + itp('just copies the path if it is already absolute and force=0', function() local force_expansion = 0 local absolute_path = '/absolute/path' local result = vim_FullName(absolute_path, buffer, length, force_expansion) @@ -400,7 +447,8 @@ describe('more path function', function() eq(OK, result) end) - it('fails and uses filename when the path is relative to HOME', function() + itp('fails and uses filename when the path is relative to HOME', function() + eq(false, cimp.os_isdir('~')) -- sanity check: no literal "~" directory. local force_expansion = 1 local absolute_path = '~/home.file' local result = vim_FullName(absolute_path, buffer, length, force_expansion) @@ -408,28 +456,28 @@ describe('more path function', function() eq(FAIL, result) end) - it('works with some "normal" relative path with directories', function() + itp('works with some "normal" relative path with directories', function() local force_expansion = 1 local result = vim_FullName('unit-test-directory/test.file', buffer, length, force_expansion) eq(OK, result) eq(lfs.currentdir() .. '/unit-test-directory/test.file', (ffi.string(buffer))) end) - it('does not modify the given filename', function() + itp('does not modify the given filename', function() local force_expansion = 1 local filename = to_cstr('unit-test-directory/test.file') -- Don't use the wrapper here but pass a cstring directly to the c -- function. - local result = path.vim_FullName(filename, buffer, length, force_expansion) + local result = cimp.vim_FullName(filename, buffer, length, force_expansion) eq(lfs.currentdir() .. '/unit-test-directory/test.file', (ffi.string(buffer))) eq('unit-test-directory/test.file', (ffi.string(filename))) eq(OK, result) end) - it('works with directories that have one path component', function() + itp('works with directories that have one path component', function() local force_expansion = 1 local filename = to_cstr('/tmp') - local result = path.vim_FullName(filename, buffer, length, force_expansion) + local result = cimp.vim_FullName(filename, buffer, length, force_expansion) eq('/tmp', ffi.string(buffer)) eq(OK, result) end) @@ -438,7 +486,7 @@ describe('more path function', function() describe('path_fix_case', function() local function fix_case(file) local c_file = to_cstr(file) - path.path_fix_case(c_file) + cimp.path_fix_case(c_file) return ffi.string(c_file) end @@ -446,12 +494,12 @@ describe('more path function', function() after_each(function() lfs.rmdir('CamelCase') end) if ffi.os == 'Windows' or ffi.os == 'OSX' then - it('Corrects the case of file names in Mac and Windows', function() + itp('Corrects the case of file names in Mac and Windows', function() eq('CamelCase', fix_case('camelcase')) eq('CamelCase', fix_case('cAMELcASE')) end) else - it('does nothing on Linux', function() + itp('does nothing on Linux', function() eq('camelcase', fix_case('camelcase')) eq('cAMELcASE', fix_case('cAMELcASE')) end) @@ -459,44 +507,44 @@ describe('more path function', function() end) describe('append_path', function() - it('joins given paths with a slash', function() + itp('joins given paths with a slash', function() local path1 = cstr(100, 'path1') local to_append = to_cstr('path2') - eq(OK, (path.append_path(path1, to_append, 100))) + eq(OK, (cimp.append_path(path1, to_append, 100))) eq("path1/path2", (ffi.string(path1))) end) - it('joins given paths without adding an unnecessary slash', function() + itp('joins given paths without adding an unnecessary slash', function() local path1 = cstr(100, 'path1/') local to_append = to_cstr('path2') - eq(OK, path.append_path(path1, to_append, 100)) + eq(OK, cimp.append_path(path1, to_append, 100)) eq("path1/path2", (ffi.string(path1))) end) - it('fails and uses filename if there is not enough space left for to_append', function() + itp('fails and uses filename if there is not enough space left for to_append', function() local path1 = cstr(11, 'path1/') local to_append = to_cstr('path2') - eq(FAIL, (path.append_path(path1, to_append, 11))) + eq(FAIL, (cimp.append_path(path1, to_append, 11))) end) - it('does not append a slash if to_append is empty', function() + itp('does not append a slash if to_append is empty', function() local path1 = cstr(6, 'path1') local to_append = to_cstr('') - eq(OK, (path.append_path(path1, to_append, 6))) + eq(OK, (cimp.append_path(path1, to_append, 6))) eq('path1', (ffi.string(path1))) end) - it('does not append unnecessary dots', function() + itp('does not append unnecessary dots', function() local path1 = cstr(6, 'path1') local to_append = to_cstr('.') - eq(OK, (path.append_path(path1, to_append, 6))) + eq(OK, (cimp.append_path(path1, to_append, 6))) eq('path1', (ffi.string(path1))) end) - it('copies to_append to path, if path is empty', function() + itp('copies to_append to path, if path is empty', function() local path1 = cstr(7, '') local to_append = to_cstr('/path2') - eq(OK, (path.append_path(path1, to_append, 7))) + eq(OK, (cimp.append_path(path1, to_append, 7))) eq('/path2', (ffi.string(path1))) end) end) @@ -504,18 +552,18 @@ describe('more path function', function() describe('path_is_absolute_path', function() local function path_is_absolute_path(filename) filename = to_cstr(filename) - return path.path_is_absolute_path(filename) + return cimp.path_is_absolute_path(filename) end - it('returns true if filename starts with a slash', function() + itp('returns true if filename starts with a slash', function() eq(OK, path_is_absolute_path('/some/directory/')) end) - it('returns true if filename starts with a tilde', function() + itp('returns true if filename starts with a tilde', function() eq(OK, path_is_absolute_path('~/in/my/home~/directory')) end) - it('returns false if filename starts not with slash nor tilde', function() + itp('returns false if filename starts not with slash nor tilde', function() eq(FAIL, path_is_absolute_path('not/in/my/home~/directory')) end) end) diff --git a/test/unit/preload.lua b/test/unit/preload.lua index d8ec2c3943..841e19b878 100644 --- a/test/unit/preload.lua +++ b/test/unit/preload.lua @@ -2,6 +2,6 @@ -- Busted started doing this to help provide more isolation. See issue #62 -- for more information about this. local ffi = require('ffi') -local helpers = require('test.unit.helpers') +local helpers = require('test.unit.helpers')(nil) local lfs = require('lfs') local preprocess = require('test.unit.preprocess') diff --git a/test/unit/preprocess.lua b/test/unit/preprocess.lua index 1c9b290462..363358d134 100644 --- a/test/unit/preprocess.lua +++ b/test/unit/preprocess.lua @@ -124,6 +124,7 @@ function Gcc:init_defines() self:define('_GNU_SOURCE') self:define('INCLUDE_GENERATED_DECLARATIONS') self:define('UNIT_TESTING') + self:define('UNIT_TESTING_LUA_PREPROCESSING') -- Needed for FreeBSD self:define('_Thread_local', nil, '') -- Needed for macOS Sierra @@ -185,6 +186,30 @@ local function repeated_call(...) return nil end +function Gcc:filter_standard_defines(defines) + if not self.standard_defines then + local pseudoheader_fname = 'tmp_empty_pseudoheader.h' + local pseudoheader_file = io.open(pseudoheader_fname, 'w') + pseudoheader_file:close() + local standard_defines = repeated_call(self.path, + self.preprocessor_extra_flags, + self.get_defines_extra_flags, + {pseudoheader_fname}) + os.remove(pseudoheader_fname) + self.standard_defines = {} + for line in standard_defines:gmatch('[^\n]+') do + self.standard_defines[line] = true + end + end + local ret = {} + for line in defines:gmatch('[^\n]+') do + if not self.standard_defines[line] then + ret[#ret + 1] = line + end + end + return table.concat(ret, "\n") +end + -- returns a stream representing a preprocessed form of the passed-in headers. -- Don't forget to close the stream by calling the close() method on it. function Gcc:preprocess(previous_defines, ...) @@ -201,6 +226,7 @@ function Gcc:preprocess(previous_defines, ...) local defines = repeated_call(self.path, self.preprocessor_extra_flags, self.get_defines_extra_flags, {pseudoheader_fname}) + defines = self:filter_standard_defines(defines) -- lfs = require("lfs") -- print("CWD: #{lfs.currentdir!}") diff --git a/test/unit/profile_spec.lua b/test/unit/profile_spec.lua index 852475fe2c..08e5cedbab 100644 --- a/test/unit/profile_spec.lua +++ b/test/unit/profile_spec.lua @@ -1,10 +1,13 @@ -local helpers = require 'test.unit.helpers' +local helpers = require('test.unit.helpers')(after_each) +local itp = helpers.gen_itp(it) -local prof = helpers.cimport './src/nvim/profile.h' +local cimport = helpers.cimport local ffi = helpers.ffi local eq = helpers.eq local neq = helpers.neq +local prof = cimport('./src/nvim/profile.h') + local function split(inputstr, sep) if sep == nil then sep = "%s" @@ -78,7 +81,7 @@ describe('profiling related functions', function() end describe('profile_equal', function() - it('times are equal to themselves', function() + itp('times are equal to themselves', function() local start = profile_start() assert.is_true(profile_equal(start, start)) @@ -86,7 +89,7 @@ describe('profiling related functions', function() assert.is_true(profile_equal(e, e)) end) - it('times are unequal to others', function() + itp('times are unequal to others', function() assert.is_false(profile_equal(profile_start(), profile_start())) end) end) @@ -95,24 +98,24 @@ describe('profiling related functions', function() -- the profiling package. Those functions in turn will probably be tested -- using profile_cmp... circular reasoning. describe('profile_cmp', function() - it('can compare subsequent starts', function() + itp('can compare subsequent starts', function() local s1, s2 = profile_start(), profile_start() assert.is_true(profile_cmp(s1, s2) > 0) assert.is_true(profile_cmp(s2, s1) < 0) end) - it('can compare the zero element', function() + itp('can compare the zero element', function() assert.is_true(profile_cmp(profile_zero(), profile_zero()) == 0) end) - it('correctly orders divisions', function() + itp('correctly orders divisions', function() local start = profile_start() assert.is_true(profile_cmp(start, profile_divide(start, 10)) <= 0) end) end) describe('profile_divide', function() - it('actually performs division', function() + itp('actually performs division', function() -- note: the routine actually performs floating-point division to get -- better rounding behaviour, we have to take that into account when -- checking. (check range, not exact number). @@ -134,14 +137,14 @@ describe('profiling related functions', function() end) describe('profile_zero', function() - it('returns the same value on each call', function() + itp('returns the same value on each call', function() eq(0, profile_zero()) assert.is_true(profile_equal(profile_zero(), profile_zero())) end) end) describe('profile_start', function() - it('increases', function() + itp('increases', function() local last = profile_start() for _ = 1, 100 do local curr = profile_start() @@ -152,11 +155,11 @@ describe('profiling related functions', function() end) describe('profile_end', function() - it('the elapsed time cannot be zero', function() + itp('the elapsed time cannot be zero', function() neq(profile_zero(), profile_end(profile_start())) end) - it('outer elapsed >= inner elapsed', function() + itp('outer elapsed >= inner elapsed', function() for _ = 1, 100 do local start_outer = profile_start() local start_inner = profile_start() @@ -169,11 +172,11 @@ describe('profiling related functions', function() end) describe('profile_setlimit', function() - it('sets no limit when 0 is passed', function() + itp('sets no limit when 0 is passed', function() eq(true, profile_equal(profile_setlimit(0), profile_zero())) end) - it('sets a limit in the future otherwise', function() + itp('sets a limit in the future otherwise', function() local future = profile_setlimit(1000) local now = profile_start() assert.is_true(profile_cmp(future, now) < 0) @@ -181,12 +184,12 @@ describe('profiling related functions', function() end) describe('profile_passed_limit', function() - it('start is in the past', function() + itp('start is in the past', function() local start = profile_start() eq(true, profile_passed_limit(start)) end) - it('start + start is in the future', function() + itp('start + start is in the future', function() local start = profile_start() local future = profile_add(start, start) eq(false, profile_passed_limit(future)) @@ -194,12 +197,12 @@ describe('profiling related functions', function() end) describe('profile_msg', function() - it('prints the zero time as 0.00000', function() + itp('prints the zero time as 0.00000', function() local str = trim(profile_msg(profile_zero())) eq(str, "0.000000") end) - it('prints the time passed, in seconds.microsends', function() + itp('prints the time passed, in seconds.microsends', function() local start = profile_start() local endt = profile_end(start) local str = trim(profile_msg(endt)) @@ -221,14 +224,14 @@ describe('profiling related functions', function() end) describe('profile_add', function() - it('adds profiling times', function() + itp('adds profiling times', function() local start = profile_start() assert.equals(start, profile_add(profile_zero(), start)) end) end) describe('profile_sub', function() - it('subtracts profiling times', function() + itp('subtracts profiling times', function() -- subtracting zero does nothing local start = profile_start() assert.equals(start, profile_sub(start, profile_zero())) diff --git a/test/unit/rbuffer_spec.lua b/test/unit/rbuffer_spec.lua index 89136410d3..e9104dd5c4 100644 --- a/test/unit/rbuffer_spec.lua +++ b/test/unit/rbuffer_spec.lua @@ -1,9 +1,11 @@ -local helpers = require("test.unit.helpers") +local helpers = require("test.unit.helpers")(after_each) +local itp = helpers.gen_itp(it) -local ffi = helpers.ffi -local eq = helpers.eq -local cstr = helpers.cstr +local eq = helpers.eq +local ffi = helpers.ffi +local cstr = helpers.cstr local to_cstr = helpers.to_cstr +local child_call_once = helpers.child_call_once local rbuffer = helpers.cimport("./test/unit/fixtures/rbuffer.h") @@ -31,9 +33,11 @@ describe('rbuffer functions', function() end before_each(function() - rbuf = ffi.gc(rbuffer.rbuffer_new(capacity), rbuffer.rbuffer_free) - -- fill the internal buffer with the character '0' to simplify inspecting - ffi.C.memset(rbuf.start_ptr, string.byte('0'), capacity) + child_call_once(function() + rbuf = ffi.gc(rbuffer.rbuffer_new(capacity), rbuffer.rbuffer_free) + -- fill the internal buffer with the character '0' to simplify inspecting + ffi.C.memset(rbuf.start_ptr, string.byte('0'), capacity) + end) end) describe('RBUFFER_UNTIL_FULL', function() @@ -50,66 +54,51 @@ describe('rbuffer functions', function() end) describe('with empty buffer in one contiguous chunk', function() - it('is called once with the empty chunk', function() + itp('is called once with the empty chunk', function() collect_write_chunks() eq({'0000000000000000'}, chunks) end) end) describe('with partially empty buffer in one contiguous chunk', function() - before_each(function() + itp('is called once with the empty chunk', function() write('string') - end) - - it('is called once with the empty chunk', function() collect_write_chunks() eq({'0000000000'}, chunks) end) end) describe('with filled buffer in one contiguous chunk', function() - before_each(function() + itp('is not called', function() write('abcdefghijklmnopq') - end) - - it('is not called', function() collect_write_chunks() eq({}, chunks) end) end) describe('with buffer partially empty in two contiguous chunks', function() - before_each(function() + itp('is called twice with each filled chunk', function() write('1234567890') read(8) - end) - - it('is called twice with each filled chunk', function() collect_write_chunks() eq({'000000', '12345678'}, chunks) end) end) describe('with buffer empty in two contiguous chunks', function() - before_each(function() + itp('is called twice with each filled chunk', function() write('12345678') read(8) - end) - - it('is called twice with each filled chunk', function() collect_write_chunks() eq({'00000000', '12345678'}, chunks) end) end) describe('with buffer filled in two contiguous chunks', function() - before_each(function() + itp('is not called', function() write('12345678') read(8) write('abcdefghijklmnopq') - end) - - it('is not called', function() collect_write_chunks() eq({}, chunks) end) @@ -130,55 +119,43 @@ describe('rbuffer functions', function() end) describe('with empty buffer', function() - it('is not called', function() + itp('is not called', function() collect_read_chunks() eq({}, chunks) end) end) describe('with partially filled buffer in one contiguous chunk', function() - before_each(function() + itp('is called once with the filled chunk', function() write('string') - end) - - it('is called once with the filled chunk', function() collect_read_chunks() eq({'string'}, chunks) end) end) describe('with filled buffer in one contiguous chunk', function() - before_each(function() + itp('is called once with the filled chunk', function() write('abcdefghijklmnopq') - end) - - it('is called once with the filled chunk', function() collect_read_chunks() eq({'abcdefghijklmnop'}, chunks) end) end) describe('with buffer partially filled in two contiguous chunks', function() - before_each(function() + itp('is called twice with each filled chunk', function() write('1234567890') read(10) write('long string') - end) - - it('is called twice with each filled chunk', function() collect_read_chunks() eq({'long s', 'tring'}, chunks) end) end) describe('with buffer filled in two contiguous chunks', function() - before_each(function() + itp('is called twice with each filled chunk', function() write('12345678') read(8) write('abcdefghijklmnopq') - end) - - it('is called twice with each filled chunk', function() collect_read_chunks() eq({'abcdefgh', 'ijklmnop'}, chunks) end) @@ -198,20 +175,17 @@ describe('rbuffer functions', function() end) describe('with empty buffer', function() - it('is not called', function() + itp('is not called', function() collect_chars() eq({}, chars) end) end) describe('with buffer filled in two contiguous chunks', function() - before_each(function() + itp('collects each character and index', function() write('1234567890') read(10) write('long string') - end) - - it('collects each character and index', function() collect_chars() eq({{'l', 0}, {'o', 1}, {'n', 2}, {'g', 3}, {' ', 4}, {'s', 5}, {'t', 6}, {'r', 7}, {'i', 8}, {'n', 9}, {'g', 10}}, chars) @@ -232,20 +206,17 @@ describe('rbuffer functions', function() end) describe('with empty buffer', function() - it('is not called', function() + itp('is not called', function() collect_chars() eq({}, chars) end) end) describe('with buffer filled in two contiguous chunks', function() - before_each(function() + itp('collects each character and index', function() write('1234567890') read(10) write('long string') - end) - - it('collects each character and index', function() collect_chars() eq({{'g', 10}, {'n', 9}, {'i', 8}, {'r', 7}, {'t', 6}, {'s', 5}, {' ', 4}, {'g', 3}, {'n', 2}, {'o', 1}, {'l', 0}}, chars) @@ -264,13 +235,10 @@ describe('rbuffer functions', function() end describe('with buffer filled in two contiguous chunks', function() - before_each(function() + itp('compares the common longest sequence', function() write('1234567890') read(10) write('long string') - end) - - it('compares the common longest sequence', function() eq(0, cmp('long string')) eq(0, cmp('long strin')) eq(-1, cmp('long striM')) @@ -282,31 +250,31 @@ describe('rbuffer functions', function() end) describe('with empty buffer', function() - it('returns 0 since no characters are compared', function() + itp('returns 0 since no characters are compared', function() eq(0, cmp('')) end) end) end) describe('rbuffer_write', function() - it('fills the internal buffer and returns the write count', function() + itp('fills the internal buffer and returns the write count', function() eq(12, write('short string')) eq('short string0000', inspect()) end) - it('wont write beyond capacity', function() + itp('wont write beyond capacity', function() eq(16, write('very very long string')) eq('very very long s', inspect()) end) end) describe('rbuffer_read', function() - it('reads what was previously written', function() + itp('reads what was previously written', function() write('to read') eq('to read', read(20)) end) - it('reads nothing if the buffer is empty', function() + itp('reads nothing if the buffer is empty', function() eq('', read(20)) write('empty') eq('empty', read(20)) @@ -315,7 +283,7 @@ describe('rbuffer functions', function() end) describe('rbuffer_get', function() - it('fetch the pointer at offset, wrapping if required', function() + itp('fetch the pointer at offset, wrapping if required', function() write('1234567890') read(10) write('long string') @@ -334,7 +302,7 @@ describe('rbuffer functions', function() end) describe('wrapping behavior', function() - it('writing/reading wraps across the end of the internal buffer', function() + itp('writing/reading wraps across the end of the internal buffer', function() write('1234567890') eq('1234', read(4)) eq('5678', read(4)) diff --git a/test/unit/set.lua b/test/unit/set.lua index 4e66546f32..f3d68c3042 100644 --- a/test/unit/set.lua +++ b/test/unit/set.lua @@ -26,6 +26,22 @@ function Set:new(items) return obj end +function Set:copy() + local obj = {} + obj.nelem = self.nelem + obj.tbl = {} + obj.items = {} + for k, v in pairs(self.tbl) do + obj.tbl[k] = v + end + for k, v in pairs(self.items) do + obj.items[k] = v + end + setmetatable(obj, Set) + obj.__index = Set + return obj +end + -- adds the argument Set to this Set function Set:union(other) for e in other:iterator() do diff --git a/test/unit/strings_spec.lua b/test/unit/strings_spec.lua index 072701ea78..e54c82b26a 100644 --- a/test/unit/strings_spec.lua +++ b/test/unit/strings_spec.lua @@ -1,4 +1,5 @@ -local helpers = require("test.unit.helpers") +local helpers = require("test.unit.helpers")(after_each) +local itp = helpers.gen_itp(it) local cimport = helpers.cimport local eq = helpers.eq @@ -19,23 +20,23 @@ describe('vim_strsave_escaped()', function() return ret end - it('precedes by a backslash all chars from second argument', function() + itp('precedes by a backslash all chars from second argument', function() eq([[\a\b\c\d]], vim_strsave_escaped('abcd','abcd')) end) - it('precedes by a backslash chars only from second argument', function() + itp('precedes by a backslash chars only from second argument', function() eq([[\a\bcd]], vim_strsave_escaped('abcd','ab')) end) - it('returns a copy of passed string if second argument is empty', function() + itp('returns a copy of passed string if second argument is empty', function() eq('text \n text', vim_strsave_escaped('text \n text','')) end) - it('returns an empty string if first argument is empty string', function() + itp('returns an empty string if first argument is empty string', function() eq('', vim_strsave_escaped('','\r')) end) - it('returns a copy of passed string if it does not contain chars from 2nd argument', function() + itp('returns a copy of passed string if it does not contain chars from 2nd argument', function() eq('some text', vim_strsave_escaped('some text', 'a')) end) end) @@ -50,51 +51,90 @@ describe('vim_strnsave_unquoted()', function() return ret end - it('copies unquoted strings as-is', function() + itp('copies unquoted strings as-is', function() eq('-c', vim_strnsave_unquoted('-c')) eq('', vim_strnsave_unquoted('')) end) - it('respects length argument', function() + itp('respects length argument', function() eq('', vim_strnsave_unquoted('-c', 0)) eq('-', vim_strnsave_unquoted('-c', 1)) eq('-', vim_strnsave_unquoted('"-c', 2)) end) - it('unquotes fully quoted word', function() + itp('unquotes fully quoted word', function() eq('/bin/sh', vim_strnsave_unquoted('"/bin/sh"')) end) - it('unquotes partially quoted word', function() + itp('unquotes partially quoted word', function() eq('/Program Files/sh', vim_strnsave_unquoted('/Program" "Files/sh')) end) - it('removes ""', function() + itp('removes ""', function() eq('/Program Files/sh', vim_strnsave_unquoted('/""Program" "Files/sh')) end) - it('performs unescaping of "', function() + itp('performs unescaping of "', function() eq('/"Program Files"/sh', vim_strnsave_unquoted('/"\\""Program Files"\\""/sh')) end) - it('performs unescaping of \\', function() + itp('performs unescaping of \\', function() eq('/\\Program Files\\foo/sh', vim_strnsave_unquoted('/"\\\\"Program Files"\\\\foo"/sh')) end) - it('strips quote when there is no pair to it', function() + itp('strips quote when there is no pair to it', function() eq('/Program Files/sh', vim_strnsave_unquoted('/Program" Files/sh')) eq('', vim_strnsave_unquoted('"')) end) - it('allows string to end with one backslash unescaped', function() + itp('allows string to end with one backslash unescaped', function() eq('/Program Files/sh\\', vim_strnsave_unquoted('/Program" Files/sh\\')) end) - it('does not perform unescaping out of quotes', function() + itp('does not perform unescaping out of quotes', function() eq('/Program\\ Files/sh\\', vim_strnsave_unquoted('/Program\\ Files/sh\\')) end) - it('does not unescape \\n', function() + itp('does not unescape \\n', function() eq('/Program\\nFiles/sh', vim_strnsave_unquoted('/Program"\\n"Files/sh')) end) end) + +describe('vim_strchr()', function() + local vim_strchr = function(s, c) + local str = to_cstr(s) + local res = strings.vim_strchr(str, c) + if res == nil then + return nil + else + return res - str + end + end + itp('handles NUL and <0 correctly', function() + eq(nil, vim_strchr('abc', 0)) + eq(nil, vim_strchr('abc', -1)) + end) + itp('works', function() + eq(0, vim_strchr('abc', ('a'):byte())) + eq(1, vim_strchr('abc', ('b'):byte())) + eq(2, vim_strchr('abc', ('c'):byte())) + eq(0, vim_strchr('aยซbยปc', ('a'):byte())) + eq(3, vim_strchr('aยซbยปc', ('b'):byte())) + eq(6, vim_strchr('aยซbยปc', ('c'):byte())) + + eq(nil, vim_strchr('ยซยป', ('ยซ'):byte())) + -- 0xAB == 171 == 'ยซ' + eq(nil, vim_strchr('\171', 0xAB)) + eq(0, vim_strchr('ยซยป', 0xAB)) + eq(3, vim_strchr('โยซยปโ', 0xAB)) + + eq(7, vim_strchr('โยซยปโ', 0x201C)) + eq(nil, vim_strchr('โยซยปโ', 0x201D)) + eq(0, vim_strchr('โยซยปโ', 0x201E)) + + eq(0, vim_strchr('\244\143\188\128', 0x10FF00)) + eq(2, vim_strchr('ยซ\244\143\188\128ยป', 0x10FF00)) + -- |0xDBFF |0xDF00 - surrogate pair for 0x10FF00 + eq(nil, vim_strchr('ยซ\237\175\191\237\188\128ยป', 0x10FF00)) + end) +end) diff --git a/test/unit/tempfile_spec.lua b/test/unit/tempfile_spec.lua index cf0d78b7a7..c05abfd640 100644 --- a/test/unit/tempfile_spec.lua +++ b/test/unit/tempfile_spec.lua @@ -1,61 +1,68 @@ -local lfs = require 'lfs' -local helpers = require 'test.unit.helpers' +local lfs = require('lfs') +local helpers = require('test.unit.helpers')(after_each) +local itp = helpers.gen_itp(it) -local os = helpers.cimport './src/nvim/os/os.h' -local tempfile = helpers.cimport './src/nvim/fileio.h' +local eq = helpers.eq +local neq = helpers.neq +local cimport = helpers.cimport +local child_call_once = helpers.child_call_once +local child_cleanup_once = helpers.child_cleanup_once + +local lib = cimport('./src/nvim/os/os.h', './src/nvim/fileio.h') describe('tempfile related functions', function() before_each(function() - tempfile.vim_deltempdir() - end) - after_each(function() - tempfile.vim_deltempdir() + local function vim_deltempdir() + lib.vim_deltempdir() + end + child_call_once(vim_deltempdir) + child_cleanup_once(vim_deltempdir) end) local vim_gettempdir = function() - return helpers.ffi.string(tempfile.vim_gettempdir()) + return helpers.ffi.string(lib.vim_gettempdir()) end describe('vim_gettempdir', function() - it('returns path to Neovim own temp directory', function() + itp('returns path to Neovim own temp directory', function() local dir = vim_gettempdir() assert.True(dir ~= nil and dir:len() > 0) -- os_file_is_writable returns 2 for a directory which we have rights -- to write into. - assert.equals(os.os_file_is_writable(helpers.to_cstr(dir)), 2) + eq(lib.os_file_is_writable(helpers.to_cstr(dir)), 2) for entry in lfs.dir(dir) do assert.True(entry == '.' or entry == '..') end end) - it('returns the same directory on each call', function() + itp('returns the same directory on each call', function() local dir1 = vim_gettempdir() local dir2 = vim_gettempdir() - assert.equals(dir1, dir2) + eq(dir1, dir2) end) end) describe('vim_tempname', function() local vim_tempname = function() - return helpers.ffi.string(tempfile.vim_tempname()) + return helpers.ffi.string(lib.vim_tempname()) end - it('generate name of non-existing file', function() + itp('generate name of non-existing file', function() local file = vim_tempname() assert.truthy(file) - assert.False(os.os_path_exists(file)) + assert.False(lib.os_path_exists(file)) end) - it('generate different names on each call', function() + itp('generate different names on each call', function() local fst = vim_tempname() local snd = vim_tempname() - assert.not_equals(fst, snd) + neq(fst, snd) end) - it('generate file name in Neovim own temp directory', function() + itp('generate file name in Neovim own temp directory', function() local dir = vim_gettempdir() local file = vim_tempname() - assert.truthy(file:find('^' .. dir .. '[^/]*$')) + eq(string.sub(file, 1, string.len(dir)), dir) end) end) end) diff --git a/test/unit/testtest_spec.lua b/test/unit/testtest_spec.lua new file mode 100644 index 0000000000..d2f3632b6f --- /dev/null +++ b/test/unit/testtest_spec.lua @@ -0,0 +1,19 @@ +local helpers = require('test.unit.helpers')(after_each) +local assert = require('luassert') + +local itp = helpers.gen_itp(it) + +local sc = helpers.sc + +-- All of the below tests must fail. Check how exactly they fail. +if os.getenv('NVIM_TEST_RUN_TESTTEST') ~= '1' then + return +end +describe('test code', function() + itp('does not hang when working with lengthy errors', function() + assert.just_fail(('x'):rep(65536)) + end) + itp('shows trace after exiting abnormally', function() + sc.exit(0) + end) +end) diff --git a/third-party/CMakeLists.txt b/third-party/CMakeLists.txt index f7e2a9510b..ed2e7d02bb 100644 --- a/third-party/CMakeLists.txt +++ b/third-party/CMakeLists.txt @@ -1,6 +1,6 @@ # This is not meant to be included by the top-level. cmake_minimum_required (VERSION 2.8.7) -project(NEOVIM_DEPS) +project(NVIM_DEPS) # Point CMake at any custom modules we may ship list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake") @@ -87,38 +87,60 @@ endif() include(ExternalProject) -set(LIBUV_URL https://github.com/libuv/libuv/archive/v1.9.1.tar.gz) -set(LIBUV_SHA256 a6ca9f0648973d1463f46b495ce546ddcbe7cce2f04b32e802a15539e46c57ad) +set(LIBUV_URL https://github.com/libuv/libuv/archive/v1.12.0.tar.gz) +set(LIBUV_SHA256 41ce914a88da21d3b07a76023beca57576ca5b376c6ac440c80bc581cbca1250) -set(MSGPACK_URL https://github.com/msgpack/msgpack-c/archive/cpp-1.0.0.tar.gz) -set(MSGPACK_SHA256 afda64ca445203bb7092372b822bae8b2539fdcebbfc3f753f393628c2bcfe7d) +set(MSGPACK_URL https://github.com/msgpack/msgpack-c/archive/cpp-2.1.3.tar.gz) +set(MSGPACK_SHA256 42ff5c213fd24bd4388c45c1f21d84b476678ce6366ea4d4f4086618a1d2cd23) -set(LUAJIT_URL https://github.com/neovim/deps/raw/master/opt/LuaJIT-2.0.4.tar.gz) -set(LUAJIT_SHA256 620fa4eb12375021bef6e4f237cbd2dd5d49e56beb414bee052c746beef1807d) +set(LUAJIT_URL https://github.com/LuaJIT/LuaJIT/archive/82151a4514e6538086f3f5e01cb8d4b22287b14f.tar.gz) +set(LUAJIT_SHA256 8bc4e96ebab74e12ab84e751360e864714289bb089b51b6f396fa9a97df69798) set(LUA_URL https://www.lua.org/ftp/lua-5.1.5.tar.gz) set(LUA_SHA256 2640fc56a795f29d28ef15e13c34a47e223960b0240e8cb0a82d9b0738695333) -set(LUAROCKS_URL https://github.com/keplerproject/luarocks/archive/5d8a16526573b36d5b22aa74866120c998466697.tar.gz) -set(LUAROCKS_SHA256 cae709111c5701235770047dfd7169f66b82ae1c7b9b79207f9df0afb722bfd9) +# NOTE: Version must match LUAROCKS_VERSION in third-party/cmake/BuildLuarocks.cmake +set(LUAROCKS_URL https://github.com/luarocks/luarocks/archive/v2.4.2.tar.gz) +set(LUAROCKS_SHA256 eef88c2429c715a7beb921e4b1ba571dddb7c74a250fbb0d3cc0d4be7a5865d9) set(UNIBILIUM_URL https://github.com/mauke/unibilium/archive/v1.2.0.tar.gz) set(UNIBILIUM_SHA256 623af1099515e673abfd3cae5f2fa808a09ca55dda1c65a7b5c9424eb304ead8) -set(LIBTERMKEY_URL http://www.leonerd.org.uk/code/libtermkey/libtermkey-0.19.tar.gz) -set(LIBTERMKEY_SHA256 c505aa4cb48c8fa59c526265576b97a19e6ebe7b7da20f4ecaae898b727b48b7) +if(WIN32) +set(LIBTERMKEY_URL https://github.com/equalsraf/libtermkey/archive/tb-windows.zip) +set(LIBTERMKEY_SHA256 c81e33e38662b151a49847ff4feef4f8c4b2a66f3e159a28b575cbc9bcd8ffea) +else() +set(LIBTERMKEY_URL http://www.leonerd.org.uk/code/libtermkey/libtermkey-0.20.tar.gz) +set(LIBTERMKEY_SHA256 6c0d87c94ab9915e76ecd313baec08dedf3bd56de83743d9aa923a081935d2f5) +endif() set(LIBVTERM_URL https://github.com/neovim/libvterm/archive/a9c7c6fd20fa35e0ad3e0e98901ca12dfca9c25c.tar.gz) set(LIBVTERM_SHA256 1a4272be91d9614dc183a503786df83b6584e4afaab7feaaa5409f841afbd796) -set(JEMALLOC_URL https://github.com/jemalloc/jemalloc/releases/download/4.3.1/jemalloc-4.3.1.tar.bz2) -set(JEMALLOC_SHA256 f7bb183ad8056941791e0f075b802e8ff10bd6e2d904e682f87c8f6a510c278b) +set(JEMALLOC_URL https://github.com/jemalloc/jemalloc/releases/download/4.5.0/jemalloc-4.5.0.tar.bz2) +set(JEMALLOC_SHA256 9409d85664b4f135b77518b0b118c549009dc10f6cba14557d170476611f6780) + +set(LUV_URL https://github.com/luvit/luv/archive/1.9.1-1.tar.gz) +set(LUV_SHA256 562b9efaad30aa051a40eac9ade0c3df48bb8186763769abe47ec3fb3edb1268) + +set(GPERF_URL https://ftp.gnu.org/pub/gnu/gperf/gperf-3.1.tar.gz) +set(GPERF_SHA256 588546b945bba4b70b6a3a616e80b4ab466e3f33024a352fc2198112cdbb3ae2) -set(LUV_URL https://github.com/luvit/luv/archive/1.9.1-0.tar.gz) -set(LUV_SHA256 86a199403856018cd8e5529c8527450c83664a3d36f52d5253cbe909ea6c5a06) +# 7za.exe cat.exe curl.exe ca-bundle.crt diff.exe tee.exe tidy.exe xxd.exe +set(WINTOOLS_URL https://github.com/neovim/deps/raw/2f9acbecf06365c10baa3c0087f34a54c9c6f949/opt/win32tools.zip) +set(WINTOOLS_SHA256 8bfce7e3a365721a027ce842f2ec1cf878f1726233c215c05964aac07300798c) -set(GPERF_URL http://ftp.gnu.org/pub/gnu/gperf/gperf-3.0.4.tar.gz) -set(GPERF_SHA256 767112a204407e62dbc3106647cf839ed544f3cf5d0f0523aaa2508623aad63e) +set(WINGUI_URL https://github.com/equalsraf/neovim-qt/releases/download/v0.2.7/neovim-qt.zip) +set(WINGUI_SHA256 b548f6e4045f16a10163b0e433f05b115b2f877cb47c4eacbf80eaad1a8429ab) + +set(WIN32YANK_X86_URL https://github.com/equalsraf/win32yank/releases/download/v0.0.4/win32yank-x86.zip) +set(WIN32YANK_X86_SHA256 62f34e5a46c5d4a7b3f3b512e1ff7b77fedd432f42581cbe825233a996eed62c) + +set(WIN32YANK_X86_64_URL https://github.com/equalsraf/win32yank/releases/download/v0.0.4/win32yank-x64.zip) +set(WIN32YANK_X86_64_SHA256 33a747a92da60fb65e668edbf7661d3d902411a2d545fe9dc08623cecd142a20) + +set(WINPTY_URL https://github.com/rprichard/winpty/releases/download/0.4.2/winpty-0.4.2-msvc2015.zip) +set(WINPTY_SHA256 b465f2584ff394b3fe27c01aa1dcfc679583c1ee951d0e83de3f859d8b8305b8) if(USE_BUNDLED_UNIBILIUM) include(BuildUnibilium) @@ -164,6 +186,38 @@ if(USE_BUNDLED_GPERF) include(BuildGperf) endif() +include(GetBinaryDeps) + +if(WIN32) + GetBinaryDep(TARGET wintools + INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_directory . ${DEPS_INSTALL_DIR}/bin) + + GetBinaryDep(TARGET wingui + INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_directory bin ${DEPS_INSTALL_DIR}/bin) + + include(TargetArch) + GetBinaryDep(TARGET "win32yank_${TARGET_ARCH}" + INSTALL_COMMAND ${CMAKE_COMMAND} -E copy win32yank.exe ${DEPS_INSTALL_DIR}/bin) + + if("${TARGET_ARCH}" STREQUAL "X86_64") + set(TARGET_ARCH x64) + elseif(TARGET_ARCH STREQUAL "X86") + set(TARGET_ARCH ia32) + endif() + + GetBinaryDep(TARGET winpty + INSTALL_COMMAND ${CMAKE_COMMAND} -E make_directory ${DEPS_INSTALL_DIR}/bin + COMMAND ${CMAKE_COMMAND} -DFROM_GLOB=${DEPS_BUILD_DIR}/src/winpty/${TARGET_ARCH}/bin/* + -DTO=${DEPS_INSTALL_DIR}/bin/ + -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/CopyFilesGlob.cmake + COMMAND ${CMAKE_COMMAND} -DFROM_GLOB=${DEPS_BUILD_DIR}/src/winpty/include/* + -DTO=${DEPS_INSTALL_DIR}/include/ + -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/CopyFilesGlob.cmake + COMMAND ${CMAKE_COMMAND} -DFROM_GLOB=${DEPS_BUILD_DIR}/src/winpty/${TARGET_ARCH}/lib/* + -DTO=${DEPS_INSTALL_DIR}/lib/ + -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/CopyFilesGlob.cmake) +endif() + add_custom_target(clean-shared-libraries COMMAND ${CMAKE_COMMAND} -DREMOVE_FILE_GLOB=${DEPS_INSTALL_DIR}/lib/${CMAKE_SHARED_LIBRARY_PREFIX}*${CMAKE_SHARED_LIBRARY_SUFFIX}* diff --git a/third-party/README.md b/third-party/README.md deleted file mode 100644 index c3ec399695..0000000000 --- a/third-party/README.md +++ /dev/null @@ -1,8 +0,0 @@ -# Third party dependencies for neovim - -This directory contains the recipes to build any third party dependencies for -neovim which, for one reason or another, we cannot rely on the system to supply. - -Most of the details are captured in the `CMakeLists.txt`, but we have a -dedicated directory in case any of the dependencies requires patching and other -support. diff --git a/third-party/cmake/BuildLibtermkey.cmake b/third-party/cmake/BuildLibtermkey.cmake index 57e14d36d3..4b581c2a01 100644 --- a/third-party/cmake/BuildLibtermkey.cmake +++ b/third-party/cmake/BuildLibtermkey.cmake @@ -1,21 +1,41 @@ -if(WIN32) - message(STATUS "Building libtermkey in Windows is not supported (skipping)") - return() -endif() find_package(PkgConfig REQUIRED) +if(WIN32) +ExternalProject_Add(libtermkey + PREFIX ${DEPS_BUILD_DIR} + URL ${LIBTERMKEY_URL} + DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/libtermkey + DOWNLOAD_COMMAND ${CMAKE_COMMAND} + -DPREFIX=${DEPS_BUILD_DIR} + -DDOWNLOAD_DIR=${DEPS_DOWNLOAD_DIR}/libtermkey + -DURL=${LIBTERMKEY_URL} + -DEXPECTED_SHA256=${LIBTERMKEY_SHA256} + -DTARGET=libtermkey + -DUSE_EXISTING_SRC_DIR=${USE_EXISTING_SRC_DIR} + -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/DownloadAndExtractFile.cmake + CONFIGURE_COMMAND ${CMAKE_COMMAND} ${DEPS_BUILD_DIR}/src/libtermkey + -DCMAKE_INSTALL_PREFIX=${DEPS_INSTALL_DIR} + # Pass toolchain + -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN} + -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} + # Hack to avoid -rdynamic in Mingw + -DCMAKE_SHARED_LIBRARY_LINK_C_FLAGS="" + -DCMAKE_GENERATOR=${CMAKE_GENERATOR} + BUILD_COMMAND ${CMAKE_COMMAND} --build . --config ${CMAKE_BUILD_TYPE} + INSTALL_COMMAND ${CMAKE_COMMAND} --build . --target install --config ${CMAKE_BUILD_TYPE}) +else() ExternalProject_Add(libtermkey PREFIX ${DEPS_BUILD_DIR} URL ${LIBTERMKEY_URL} DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/libtermkey DOWNLOAD_COMMAND ${CMAKE_COMMAND} - -DPREFIX=${DEPS_BUILD_DIR} - -DDOWNLOAD_DIR=${DEPS_DOWNLOAD_DIR}/libtermkey - -DURL=${LIBTERMKEY_URL} - -DEXPECTED_SHA256=${LIBTERMKEY_SHA256} - -DTARGET=libtermkey - -DUSE_EXISTING_SRC_DIR=${USE_EXISTING_SRC_DIR} - -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/DownloadAndExtractFile.cmake + -DPREFIX=${DEPS_BUILD_DIR} + -DDOWNLOAD_DIR=${DEPS_DOWNLOAD_DIR}/libtermkey + -DURL=${LIBTERMKEY_URL} + -DEXPECTED_SHA256=${LIBTERMKEY_SHA256} + -DTARGET=libtermkey + -DUSE_EXISTING_SRC_DIR=${USE_EXISTING_SRC_DIR} + -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/DownloadAndExtractFile.cmake CONFIGURE_COMMAND "" BUILD_IN_SOURCE 1 BUILD_COMMAND "" @@ -24,6 +44,10 @@ ExternalProject_Add(libtermkey PKG_CONFIG_PATH=${DEPS_LIB_DIR}/pkgconfig CFLAGS=-fPIC install) +endif() list(APPEND THIRD_PARTY_DEPS libtermkey) -add_dependencies(libtermkey unibilium) +if(NOT WIN32) + # There is no unibilium build recipe for Windows yet + add_dependencies(libtermkey unibilium) +endif() diff --git a/third-party/cmake/BuildLibuv.cmake b/third-party/cmake/BuildLibuv.cmake index 5482f28557..06b527e5a2 100644 --- a/third-party/cmake/BuildLibuv.cmake +++ b/third-party/cmake/BuildLibuv.cmake @@ -75,16 +75,16 @@ elseif(WIN32 AND MSVC) message(FATAL_ERROR "Python2 is required to build libuv on windows, use -DPYTHON_EXECUTABLE to set a python interpreter") endif() - string(FIND ${CMAKE_GENERATOR} Win64 VS_WIN64) - if(VS_WIN64 EQUAL -1) - set(VS_ARCH x86) - else() - set(VS_ARCH x64) + include(TargetArch) + if("${TARGET_ARCH}" STREQUAL "X86_64") + set(TARGET_ARCH x64) + elseif(TARGET_ARCH STREQUAL "X86") + set(TARGET_ARCH x86) endif() string(TOLOWER ${CMAKE_BUILD_TYPE} LOWERCASE_BUILD_TYPE) set(UV_OUTPUT_DIR ${DEPS_BUILD_DIR}/src/libuv/${CMAKE_BUILD_TYPE}) BuildLibUv( - BUILD_COMMAND set PYTHON=${PYTHON_EXECUTABLE} COMMAND ${DEPS_BUILD_DIR}/src/libuv/vcbuild.bat shared ${LOWERCASE_BUILD_TYPE} ${VS_ARCH} + BUILD_COMMAND set PYTHON=${PYTHON_EXECUTABLE} COMMAND ${DEPS_BUILD_DIR}/src/libuv/vcbuild.bat shared ${LOWERCASE_BUILD_TYPE} ${TARGET_ARCH} INSTALL_COMMAND ${CMAKE_COMMAND} -E make_directory ${DEPS_INSTALL_DIR}/lib COMMAND ${CMAKE_COMMAND} -E make_directory ${DEPS_INSTALL_DIR}/bin COMMAND ${CMAKE_COMMAND} -E copy ${UV_OUTPUT_DIR}/libuv.lib ${DEPS_INSTALL_DIR}/lib diff --git a/third-party/cmake/BuildLua.cmake b/third-party/cmake/BuildLua.cmake index 1c5e2a186c..ea1371d1d5 100644 --- a/third-party/cmake/BuildLua.cmake +++ b/third-party/cmake/BuildLua.cmake @@ -51,19 +51,32 @@ else() endif() endif() +set(LUA_CFLAGS "-O0 -g3 -fPIC") +set(LUA_LDFLAGS "") + +if(CLANG_ASAN_UBSAN) + set(LUA_CFLAGS "${LUA_CFLAGS} -fsanitize=address") + set(LUA_CFLAGS "${LUA_CFLAGS} -fno-omit-frame-pointer") + set(LUA_CFLAGS "${LUA_CFLAGS} -fno-optimize-sibling-calls") + + set(LUA_LDFLAGS "${LUA_LDFLAGS} -fsanitize=address") +endif() + set(LUA_CONFIGURE_COMMAND sed -e "/^CC/s@gcc@${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_ARG1}@" - -e "/^CFLAGS/s@-O2@-g3@" + -e "/^CFLAGS/s@-O2@${LUA_CFLAGS}@" + -e "/^MYLDFLAGS/s@$@${LUA_LDFLAGS}@" -e "s@-lreadline@@g" -e "s@-lhistory@@g" -e "s@-lncurses@@g" -i ${DEPS_BUILD_DIR}/src/lua/src/Makefile && sed -e "/#define LUA_USE_READLINE/d" -i ${DEPS_BUILD_DIR}/src/lua/src/luaconf.h) +set(LUA_INSTALL_TOP_ARG "INSTALL_TOP=${DEPS_INSTALL_DIR}") set(LUA_BUILD_COMMAND - ${MAKE_PRG} ${LUA_TARGET}) + ${MAKE_PRG} ${LUA_INSTALL_TOP_ARG} ${LUA_TARGET}) set(LUA_INSTALL_COMMAND - ${MAKE_PRG} INSTALL_TOP=${DEPS_INSTALL_DIR} install) + ${MAKE_PRG} ${LUA_INSTALL_TOP_ARG} install) message(STATUS "Lua target is ${LUA_TARGET}") diff --git a/third-party/cmake/BuildLuarocks.cmake b/third-party/cmake/BuildLuarocks.cmake index 9ea96b7cc5..ef8a8450f1 100644 --- a/third-party/cmake/BuildLuarocks.cmake +++ b/third-party/cmake/BuildLuarocks.cmake @@ -41,6 +41,9 @@ endfunction() # The luarocks binary location set(LUAROCKS_BINARY ${HOSTDEPS_BIN_DIR}/luarocks) +# NOTE: Version must match version of LuaRocks in third-party/CMakeLists.txt +set(LUAROCKS_VERSION 2.4) + # Arguments for calls to 'luarocks build' if(NOT MSVC) # In MSVC don't pass the compiler/linker to luarocks, the bundled @@ -73,13 +76,13 @@ elseif(MSVC OR MINGW) /LIB ${DEPS_LIB_DIR} /BIN ${DEPS_BIN_DIR} /INC ${DEPS_INSTALL_DIR}/include/luajit-2.0/ - /P ${DEPS_INSTALL_DIR} /TREE ${DEPS_INSTALL_DIR} + /P ${DEPS_INSTALL_DIR}/${LUAROCKS_VERSION} /TREE ${DEPS_INSTALL_DIR} /SCRIPTS ${DEPS_BIN_DIR} /CMOD ${DEPS_BIN_DIR} ${MINGW_FLAG} /LUAMOD ${DEPS_BIN_DIR}/lua) - set(LUAROCKS_BINARY ${DEPS_INSTALL_DIR}/2.2/luarocks.bat) + set(LUAROCKS_BINARY ${DEPS_INSTALL_DIR}/${LUAROCKS_VERSION}/luarocks.bat) else() message(FATAL_ERROR "Trying to build luarocks in an unsupported system ${CMAKE_SYSTEM_NAME}/${CMAKE_C_COMPILER_ID}") endif() @@ -137,7 +140,7 @@ if(USE_BUNDLED_BUSTED) endif() add_custom_command(OUTPUT ${BUSTED_EXE} COMMAND ${LUAROCKS_BINARY} - ARGS build https://raw.githubusercontent.com/Olivine-Labs/busted/v2.0.rc11-0/busted-2.0.rc11-0.rockspec ${LUAROCKS_BUILDARGS} + ARGS build https://raw.githubusercontent.com/Olivine-Labs/busted/v2.0.rc12-1/busted-2.0.rc12-1.rockspec ${LUAROCKS_BUILDARGS} DEPENDS penlight) add_custom_target(busted DEPENDS ${BUSTED_EXE}) @@ -167,7 +170,7 @@ if(USE_BUNDLED_BUSTED) add_custom_command(OUTPUT ${HOSTDEPS_LIB_DIR}/luarocks/rocks/nvim-client COMMAND ${LUAROCKS_BINARY} - ARGS build https://raw.githubusercontent.com/neovim/lua-client/0.0.1-25/nvim-client-0.0.1-25.rockspec ${LUAROCKS_BUILDARGS} + ARGS build https://raw.githubusercontent.com/neovim/lua-client/0.0.1-26/nvim-client-0.0.1-26.rockspec ${LUAROCKS_BUILDARGS} DEPENDS luv) add_custom_target(nvim-client DEPENDS ${HOSTDEPS_LIB_DIR}/luarocks/rocks/nvim-client) diff --git a/third-party/cmake/BuildLuv.cmake b/third-party/cmake/BuildLuv.cmake index 8ba4a0b41b..2a786dd8f3 100644 --- a/third-party/cmake/BuildLuv.cmake +++ b/third-party/cmake/BuildLuv.cmake @@ -87,5 +87,9 @@ BuildLuv(PATCH_COMMAND ${LUV_PATCH_COMMAND} INSTALL_COMMAND ${LUV_INSTALL_COMMAND}) list(APPEND THIRD_PARTY_DEPS luv-static) -add_dependencies(luv-static luajit) -add_dependencies(luv-static libuv) +if(USE_BUNDLED_LUAJIT) + add_dependencies(luv-static luajit) +endif() +if(USE_BUNDLED_LIBUV) + add_dependencies(luv-static libuv) +endif() diff --git a/third-party/cmake/BuildMsgpack.cmake b/third-party/cmake/BuildMsgpack.cmake index 6b38508b0b..779cb1ebfe 100644 --- a/third-party/cmake/BuildMsgpack.cmake +++ b/third-party/cmake/BuildMsgpack.cmake @@ -35,6 +35,7 @@ endfunction() set(MSGPACK_CONFIGURE_COMMAND ${CMAKE_COMMAND} ${DEPS_BUILD_DIR}/src/msgpack -DMSGPACK_ENABLE_CXX=OFF -DMSGPACK_BUILD_TESTS=OFF + -DMSGPACK_BUILD_EXAMPLES=OFF -DCMAKE_INSTALL_PREFIX=${DEPS_INSTALL_DIR} -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} @@ -49,6 +50,7 @@ if(MINGW AND CMAKE_CROSSCOMPILING) set(MSGPACK_CONFIGURE_COMMAND ${CMAKE_COMMAND} ${DEPS_BUILD_DIR}/src/msgpack -DMSGPACK_ENABLE_CXX=OFF -DMSGPACK_BUILD_TESTS=OFF + -DMSGPACK_BUILD_EXAMPLES=OFF -DCMAKE_INSTALL_PREFIX=${DEPS_INSTALL_DIR} # Pass toolchain -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN} @@ -60,6 +62,7 @@ elseif(MSVC) set(MSGPACK_CONFIGURE_COMMAND ${CMAKE_COMMAND} ${DEPS_BUILD_DIR}/src/msgpack -DMSGPACK_ENABLE_CXX=OFF -DMSGPACK_BUILD_TESTS=OFF + -DMSGPACK_BUILD_EXAMPLES=OFF -DCMAKE_INSTALL_PREFIX=${DEPS_INSTALL_DIR} -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} "-DCMAKE_C_FLAGS:STRING=${CMAKE_C_COMPILER_ARG1}" diff --git a/third-party/cmake/DownloadAndExtractFile.cmake b/third-party/cmake/DownloadAndExtractFile.cmake index 24e431b5e5..2fc6e0415f 100644 --- a/third-party/cmake/DownloadAndExtractFile.cmake +++ b/third-party/cmake/DownloadAndExtractFile.cmake @@ -39,7 +39,7 @@ if(TIMEOUT) set(timeout_args TIMEOUT ${timeout}) set(timeout_msg "${timeout} seconds") else() - set(timeout_args "# no TIMEOUT") + set(timeout_args "") set(timeout_msg "none") endif() diff --git a/third-party/cmake/GetBinaryDeps.cmake b/third-party/cmake/GetBinaryDeps.cmake new file mode 100644 index 0000000000..1d98177924 --- /dev/null +++ b/third-party/cmake/GetBinaryDeps.cmake @@ -0,0 +1,46 @@ +# Download and install binary dependencies for windows +include(CMakeParseArguments) + +# This is similar to the build recipes, but instead downloads a third party +# binary and installs it under the the DEPS_PREFIX. The INSTALL_COMMAND is +# executed in the folder where downloaded files are extracted and the +# ${DEPS_INSTALL_DIR} holds the path to the third-party install root. +function(GetBinaryDep) + cmake_parse_arguments(_gettool + "BUILD_IN_SOURCE" + "TARGET" + "INSTALL_COMMAND" + ${ARGN}) + + if(NOT _gettool_TARGET OR NOT _gettool_INSTALL_COMMAND) + message(FATAL_ERROR "Must pass INSTALL_COMMAND and TARGET") + endif() + + string(TOUPPER "${_gettool_TARGET}_URL" URL_VARNAME) + string(TOUPPER "${_gettool_TARGET}_SHA256" HASH_VARNAME) + set(URL ${${URL_VARNAME}}) + set(HASH ${${HASH_VARNAME}}) + if(NOT URL OR NOT HASH ) + message(FATAL_ERROR "${URL_VARNAME} and ${HASH_VARNAME} must be set") + endif() + + ExternalProject_Add(${_gettool_TARGET} + PREFIX ${DEPS_BUILD_DIR} + URL ${URL} + DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR} + DOWNLOAD_COMMAND ${CMAKE_COMMAND} + -DPREFIX=${DEPS_BUILD_DIR} + -DDOWNLOAD_DIR=${DEPS_DOWNLOAD_DIR} + -DURL=${URL} + -DEXPECTED_SHA256=${HASH} + -DTARGET=${_gettool_TARGET} + -DUSE_EXISTING_SRC_DIR=${USE_EXISTING_SRC_DIR} + -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/DownloadAndExtractFile.cmake + CONFIGURE_COMMAND "" + BUILD_IN_SOURCE 1 + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND ${CMAKE_COMMAND} -E make_directory ${DEPS_INSTALL_DIR}/bin + COMMAND "${_gettool_INSTALL_COMMAND}") + list(APPEND THIRD_PARTY_DEPS ${__gettool_TARGET}) +endfunction() diff --git a/third-party/cmake/TargetArch.cmake b/third-party/cmake/TargetArch.cmake new file mode 100644 index 0000000000..71ea44ec59 --- /dev/null +++ b/third-party/cmake/TargetArch.cmake @@ -0,0 +1,23 @@ +# Sets TARGET_ARCH to a normalized name (X86 or X86_64). +# See https://github.com/axr/solar-cmake/blob/master/TargetArch.cmake +include(CheckSymbolExists) + +# X86 +check_symbol_exists("_M_IX86" "" T_M_IX86) +check_symbol_exists("__i386__" "" T_I386) +if(T_M_IX86 OR T_I386) +set(TARGET_ARCH "X86") + return() +endif() + +# X86_64 +check_symbol_exists("_M_AMD64" "" T_M_AMD64) +check_symbol_exists("__x86_64__" "" T_X86_64) +check_symbol_exists("__amd64__" "" T_AMD64) + +if(T_M_AMD64 OR T_X86_64 OR T_AMD64) +set(TARGET_ARCH "X86_64") + return() +endif() + +message(FATAL_ERROR "Unknown target architecture") diff --git a/unicode/CaseFolding.txt b/unicode/CaseFolding.txt index 372ee68bd8..efdf18e441 100644 --- a/unicode/CaseFolding.txt +++ b/unicode/CaseFolding.txt @@ -1,6 +1,6 @@ -# CaseFolding-9.0.0.txt -# Date: 2016-03-02, 18:54:54 GMT -# ยฉ 2016 Unicodeยฎ, Inc. +# CaseFolding-10.0.0.txt +# Date: 2017-04-14, 05:40:18 GMT +# ยฉ 2017 Unicodeยฎ, Inc. # Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries. # For terms of use, see http://www.unicode.org/terms_of_use.html # @@ -24,7 +24,7 @@ # # NOTE: case folding does not preserve normalization formats! # -# For information on case folding, including how to have case folding +# For information on case folding, including how to have case folding # preserve normalization formats, see Section 3.13 Default Case Algorithms in # The Unicode Standard. # diff --git a/unicode/EastAsianWidth.txt b/unicode/EastAsianWidth.txt index 5a2ede5d59..0d3129bb0a 100644 --- a/unicode/EastAsianWidth.txt +++ b/unicode/EastAsianWidth.txt @@ -1,6 +1,6 @@ -# EastAsianWidth-9.0.0.txt -# Date: 2016-05-27, 17:00:00 GMT [KW, LI] -# ยฉ 2016 Unicodeยฎ, Inc. +# EastAsianWidth-10.0.0.txt +# Date: 2017-03-08, 02:00:00 GMT [KW, LI] +# ยฉ 2017 Unicodeยฎ, Inc. # Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries. # For terms of use, see http://www.unicode.org/terms_of_use.html # @@ -328,6 +328,7 @@ 0840..0858;N # Lo [25] MANDAIC LETTER HALQA..MANDAIC LETTER AIN 0859..085B;N # Mn [3] MANDAIC AFFRICATION MARK..MANDAIC GEMINATION MARK 085E;N # Po MANDAIC PUNCTUATION +0860..086A;N # Lo [11] SYRIAC LETTER MALAYALAM NGA..SYRIAC LETTER MALAYALAM SSA 08A0..08B4;N # Lo [21] ARABIC LETTER BEH WITH SMALL V BELOW..ARABIC LETTER KAF WITH DOT BELOW 08B6..08BD;N # Lo [8] ARABIC LETTER BEH WITH SMALL MEEM ABOVE..ARABIC LETTER AFRICAN NOON 08D4..08E1;N # Mn [14] ARABIC SMALL HIGH WORD AR-RUB..ARABIC SMALL HIGH SIGN SAFHA @@ -381,6 +382,8 @@ 09F4..09F9;N # No [6] BENGALI CURRENCY NUMERATOR ONE..BENGALI CURRENCY DENOMINATOR SIXTEEN 09FA;N # So BENGALI ISSHAR 09FB;N # Sc BENGALI GANDA MARK +09FC;N # Lo BENGALI LETTER VEDIC ANUSVARA +09FD;N # Po BENGALI ABBREVIATION SIGN 0A01..0A02;N # Mn [2] GURMUKHI SIGN ADAK BINDI..GURMUKHI SIGN BINDI 0A03;N # Mc GURMUKHI SIGN VISARGA 0A05..0A0A;N # Lo [6] GURMUKHI LETTER A..GURMUKHI LETTER UU @@ -425,6 +428,7 @@ 0AF0;N # Po GUJARATI ABBREVIATION SIGN 0AF1;N # Sc GUJARATI RUPEE SIGN 0AF9;N # Lo GUJARATI LETTER ZHA +0AFA..0AFF;N # Mn [6] GUJARATI SIGN SUKUN..GUJARATI SIGN TWO-CIRCLE NUKTA ABOVE 0B01;N # Mn ORIYA SIGN CANDRABINDU 0B02..0B03;N # Mc [2] ORIYA SIGN ANUSVARA..ORIYA SIGN VISARGA 0B05..0B0C;N # Lo [8] ORIYA LETTER A..ORIYA LETTER VOCALIC L @@ -516,11 +520,12 @@ 0CE2..0CE3;N # Mn [2] KANNADA VOWEL SIGN VOCALIC L..KANNADA VOWEL SIGN VOCALIC LL 0CE6..0CEF;N # Nd [10] KANNADA DIGIT ZERO..KANNADA DIGIT NINE 0CF1..0CF2;N # Lo [2] KANNADA SIGN JIHVAMULIYA..KANNADA SIGN UPADHMANIYA -0D01;N # Mn MALAYALAM SIGN CANDRABINDU +0D00..0D01;N # Mn [2] MALAYALAM SIGN COMBINING ANUSVARA ABOVE..MALAYALAM SIGN CANDRABINDU 0D02..0D03;N # Mc [2] MALAYALAM SIGN ANUSVARA..MALAYALAM SIGN VISARGA 0D05..0D0C;N # Lo [8] MALAYALAM LETTER A..MALAYALAM LETTER VOCALIC L 0D0E..0D10;N # Lo [3] MALAYALAM LETTER E..MALAYALAM LETTER AI 0D12..0D3A;N # Lo [41] MALAYALAM LETTER O..MALAYALAM LETTER TTTA +0D3B..0D3C;N # Mn [2] MALAYALAM SIGN VERTICAL BAR VIRAMA..MALAYALAM SIGN CIRCULAR VIRAMA 0D3D;N # Lo MALAYALAM SIGN AVAGRAHA 0D3E..0D40;N # Mc [3] MALAYALAM VOWEL SIGN AA..MALAYALAM VOWEL SIGN II 0D41..0D44;N # Mn [4] MALAYALAM VOWEL SIGN U..MALAYALAM VOWEL SIGN VOCALIC RR @@ -853,6 +858,7 @@ 1CF2..1CF3;N # Mc [2] VEDIC SIGN ARDHAVISARGA..VEDIC SIGN ROTATED ARDHAVISARGA 1CF4;N # Mn VEDIC TONE CANDRA ABOVE 1CF5..1CF6;N # Lo [2] VEDIC SIGN JIHVAMULIYA..VEDIC SIGN UPADHMANIYA +1CF7;N # Mc VEDIC SIGN ATIKRAMA 1CF8..1CF9;N # Mn [2] VEDIC TONE RING ABOVE..VEDIC TONE DOUBLE RING ABOVE 1D00..1D2B;N # Ll [44] LATIN LETTER SMALL CAPITAL A..CYRILLIC LETTER SMALL CAPITAL EL 1D2C..1D6A;N # Lm [63] MODIFIER LETTER CAPITAL A..GREEK SUBSCRIPT SMALL LETTER CHI @@ -861,7 +867,7 @@ 1D79..1D7F;N # Ll [7] LATIN SMALL LETTER INSULAR G..LATIN SMALL LETTER UPSILON WITH STROKE 1D80..1D9A;N # Ll [27] LATIN SMALL LETTER B WITH PALATAL HOOK..LATIN SMALL LETTER EZH WITH RETROFLEX HOOK 1D9B..1DBF;N # Lm [37] MODIFIER LETTER SMALL TURNED ALPHA..MODIFIER LETTER SMALL THETA -1DC0..1DF5;N # Mn [54] COMBINING DOTTED GRAVE ACCENT..COMBINING UP TACK ABOVE +1DC0..1DF9;N # Mn [58] COMBINING DOTTED GRAVE ACCENT..COMBINING WIDE INVERTED BRIDGE BELOW 1DFB..1DFF;N # Mn [5] COMBINING DELETION MARK..COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW 1E00..1EFF;N # L& [256] LATIN CAPITAL LETTER A WITH RING BELOW..LATIN SMALL LETTER Y WITH LOOP 1F00..1F15;N # L& [22] GREEK SMALL LETTER ALPHA WITH PSILI..GREEK SMALL LETTER EPSILON WITH DASIA AND OXIA @@ -954,7 +960,7 @@ 20A9;H # Sc WON SIGN 20AA..20AB;N # Sc [2] NEW SHEQEL SIGN..DONG SIGN 20AC;A # Sc EURO SIGN -20AD..20BE;N # Sc [18] KIP SIGN..LARI SIGN +20AD..20BF;N # Sc [19] KIP SIGN..BITCOIN SIGN 20D0..20DC;N # Mn [13] COMBINING LEFT HARPOON ABOVE..COMBINING FOUR DOTS ABOVE 20DD..20E0;N # Me [4] COMBINING ENCLOSING CIRCLE..COMBINING ENCLOSING CIRCLE BACKSLASH 20E1;N # Mn COMBINING LEFT RIGHT ARROW ABOVE @@ -1120,7 +1126,7 @@ 23F0;W # So ALARM CLOCK 23F1..23F2;N # So [2] STOPWATCH..TIMER CLOCK 23F3;W # So HOURGLASS WITH FLOWING SAND -23F4..23FE;N # So [11] BLACK MEDIUM LEFT-POINTING TRIANGLE..POWER SLEEP SYMBOL +23F4..23FF;N # So [12] BLACK MEDIUM LEFT-POINTING TRIANGLE..OBSERVER EYE SYMBOL 2400..2426;N # So [39] SYMBOL FOR NULL..SYMBOL FOR SUBSTITUTE FORM TWO 2440..244A;N # So [11] OCR HOOK..OCR DOUBLE BACKSLASH 2460..249B;A # No [60] CIRCLED DIGIT ONE..NUMBER TWENTY FULL STOP @@ -1328,7 +1334,7 @@ 2B76..2B95;N # So [32] NORTH WEST TRIANGLE-HEADED ARROW TO BAR..RIGHTWARDS BLACK ARROW 2B98..2BB9;N # So [34] THREE-D TOP-LIGHTED LEFTWARDS EQUILATERAL ARROWHEAD..UP ARROWHEAD IN A RECTANGLE BOX 2BBD..2BC8;N # So [12] BALLOT BOX WITH LIGHT X..BLACK MEDIUM RIGHT-POINTING TRIANGLE CENTRED -2BCA..2BD1;N # So [8] TOP HALF BLACK CIRCLE..UNCERTAINTY SIGN +2BCA..2BD2;N # So [9] TOP HALF BLACK CIRCLE..GROUP MARK 2BEC..2BEF;N # So [4] LEFTWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS..DOWNWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS 2C00..2C2E;N # Lu [47] GLAGOLITIC CAPITAL LETTER AZU..GLAGOLITIC CAPITAL LETTER LATINATE MYSLITE 2C30..2C5E;N # Ll [47] GLAGOLITIC SMALL LETTER AZU..GLAGOLITIC SMALL LETTER LATINATE MYSLITE @@ -1397,7 +1403,7 @@ 2E40;N # Pd DOUBLE HYPHEN 2E41;N # Po REVERSED COMMA 2E42;N # Ps DOUBLE LOW-REVERSED-9 QUOTATION MARK -2E43..2E44;N # Po [2] DASH WITH LEFT UPTURN..DOUBLE SUSPENSION MARK +2E43..2E49;N # Po [7] DASH WITH LEFT UPTURN..DOUBLE STACKED COMMA 2E80..2E99;W # So [26] CJK RADICAL REPEAT..CJK RADICAL RAP 2E9B..2EF3;W # So [89] CJK RADICAL CHOKE..CJK RADICAL C-SIMPLIFIED TURTLE 2F00..2FD5;W # So [214] KANGXI RADICAL ONE..KANGXI RADICAL FLUTE @@ -1453,7 +1459,7 @@ 30FB;W # Po KATAKANA MIDDLE DOT 30FC..30FE;W # Lm [3] KATAKANA-HIRAGANA PROLONGED SOUND MARK..KATAKANA VOICED ITERATION MARK 30FF;W # Lo KATAKANA DIGRAPH KOTO -3105..312D;W # Lo [41] BOPOMOFO LETTER B..BOPOMOFO LETTER IH +3105..312E;W # Lo [42] BOPOMOFO LETTER B..BOPOMOFO LETTER O WITH DOT ABOVE 3131..318E;W # Lo [94] HANGUL LETTER KIYEOK..HANGUL LETTER ARAEAE 3190..3191;W # So [2] IDEOGRAPHIC ANNOTATION LINKING MARK..IDEOGRAPHIC ANNOTATION REVERSE MARK 3192..3195;W # No [4] IDEOGRAPHIC ANNOTATION ONE MARK..IDEOGRAPHIC ANNOTATION FOUR MARK @@ -1476,8 +1482,8 @@ 3400..4DB5;W # Lo [6582] CJK UNIFIED IDEOGRAPH-3400..CJK UNIFIED IDEOGRAPH-4DB5 4DB6..4DBF;W # Cn [10] <reserved-4DB6>..<reserved-4DBF> 4DC0..4DFF;N # So [64] HEXAGRAM FOR THE CREATIVE HEAVEN..HEXAGRAM FOR BEFORE COMPLETION -4E00..9FD5;W # Lo [20950] CJK UNIFIED IDEOGRAPH-4E00..CJK UNIFIED IDEOGRAPH-9FD5 -9FD6..9FFF;W # Cn [42] <reserved-9FD6>..<reserved-9FFF> +4E00..9FEA;W # Lo [20971] CJK UNIFIED IDEOGRAPH-4E00..CJK UNIFIED IDEOGRAPH-9FEA +9FEB..9FFF;W # Cn [21] <reserved-9FEB>..<reserved-9FFF> A000..A014;W # Lo [21] YI SYLLABLE IT..YI SYLLABLE E A015;W # Lm YI SYLLABLE WU A016..A48C;W # Lo [1143] YI SYLLABLE BIT..YI SYLLABLE YYR @@ -1803,6 +1809,7 @@ FFFD;A # So REPLACEMENT CHARACTER 102E1..102FB;N # No [27] COPTIC EPACT DIGIT ONE..COPTIC EPACT NUMBER NINE HUNDRED 10300..1031F;N # Lo [32] OLD ITALIC LETTER A..OLD ITALIC LETTER ESS 10320..10323;N # No [4] OLD ITALIC NUMERAL ONE..OLD ITALIC NUMERAL FIFTY +1032D..1032F;N # Lo [3] OLD ITALIC LETTER YE..OLD ITALIC LETTER SOUTHERN TSE 10330..10340;N # Lo [17] GOTHIC LETTER AHSA..GOTHIC LETTER PAIRTHRA 10341;N # Nl GOTHIC LETTER NINETY 10342..10349;N # Lo [8] GOTHIC LETTER RAIDA..GOTHIC LETTER OTHAL @@ -2050,6 +2057,28 @@ FFFD;A # So REPLACEMENT CHARACTER 118E0..118E9;N # Nd [10] WARANG CITI DIGIT ZERO..WARANG CITI DIGIT NINE 118EA..118F2;N # No [9] WARANG CITI NUMBER TEN..WARANG CITI NUMBER NINETY 118FF;N # Lo WARANG CITI OM +11A00;N # Lo ZANABAZAR SQUARE LETTER A +11A01..11A06;N # Mn [6] ZANABAZAR SQUARE VOWEL SIGN I..ZANABAZAR SQUARE VOWEL SIGN O +11A07..11A08;N # Mc [2] ZANABAZAR SQUARE VOWEL SIGN AI..ZANABAZAR SQUARE VOWEL SIGN AU +11A09..11A0A;N # Mn [2] ZANABAZAR SQUARE VOWEL SIGN REVERSED I..ZANABAZAR SQUARE VOWEL LENGTH MARK +11A0B..11A32;N # Lo [40] ZANABAZAR SQUARE LETTER KA..ZANABAZAR SQUARE LETTER KSSA +11A33..11A38;N # Mn [6] ZANABAZAR SQUARE FINAL CONSONANT MARK..ZANABAZAR SQUARE SIGN ANUSVARA +11A39;N # Mc ZANABAZAR SQUARE SIGN VISARGA +11A3A;N # Lo ZANABAZAR SQUARE CLUSTER-INITIAL LETTER RA +11A3B..11A3E;N # Mn [4] ZANABAZAR SQUARE CLUSTER-FINAL LETTER YA..ZANABAZAR SQUARE CLUSTER-FINAL LETTER VA +11A3F..11A46;N # Po [8] ZANABAZAR SQUARE INITIAL HEAD MARK..ZANABAZAR SQUARE CLOSING DOUBLE-LINED HEAD MARK +11A47;N # Mn ZANABAZAR SQUARE SUBJOINER +11A50;N # Lo SOYOMBO LETTER A +11A51..11A56;N # Mn [6] SOYOMBO VOWEL SIGN I..SOYOMBO VOWEL SIGN OE +11A57..11A58;N # Mc [2] SOYOMBO VOWEL SIGN AI..SOYOMBO VOWEL SIGN AU +11A59..11A5B;N # Mn [3] SOYOMBO VOWEL SIGN VOCALIC R..SOYOMBO VOWEL LENGTH MARK +11A5C..11A83;N # Lo [40] SOYOMBO LETTER KA..SOYOMBO LETTER KSSA +11A86..11A89;N # Lo [4] SOYOMBO CLUSTER-INITIAL LETTER RA..SOYOMBO CLUSTER-INITIAL LETTER SA +11A8A..11A96;N # Mn [13] SOYOMBO FINAL CONSONANT SIGN G..SOYOMBO SIGN ANUSVARA +11A97;N # Mc SOYOMBO SIGN VISARGA +11A98..11A99;N # Mn [2] SOYOMBO GEMINATION MARK..SOYOMBO SUBJOINER +11A9A..11A9C;N # Po [3] SOYOMBO MARK TSHEG..SOYOMBO MARK DOUBLE SHAD +11A9E..11AA2;N # Po [5] SOYOMBO HEAD MARK WITH MOON AND SUN AND TRIPLE FLAME..SOYOMBO TERMINAL MARK-2 11AC0..11AF8;N # Lo [57] PAU CIN HAU LETTER PA..PAU CIN HAU GLOTTAL STOP FINAL 11C00..11C08;N # Lo [9] BHAIKSUKI LETTER A..BHAIKSUKI LETTER VOCALIC L 11C0A..11C2E;N # Lo [37] BHAIKSUKI LETTER E..BHAIKSUKI LETTER HA @@ -2071,6 +2100,16 @@ FFFD;A # So REPLACEMENT CHARACTER 11CB2..11CB3;N # Mn [2] MARCHEN VOWEL SIGN U..MARCHEN VOWEL SIGN E 11CB4;N # Mc MARCHEN VOWEL SIGN O 11CB5..11CB6;N # Mn [2] MARCHEN SIGN ANUSVARA..MARCHEN SIGN CANDRABINDU +11D00..11D06;N # Lo [7] MASARAM GONDI LETTER A..MASARAM GONDI LETTER E +11D08..11D09;N # Lo [2] MASARAM GONDI LETTER AI..MASARAM GONDI LETTER O +11D0B..11D30;N # Lo [38] MASARAM GONDI LETTER AU..MASARAM GONDI LETTER TRA +11D31..11D36;N # Mn [6] MASARAM GONDI VOWEL SIGN AA..MASARAM GONDI VOWEL SIGN VOCALIC R +11D3A;N # Mn MASARAM GONDI VOWEL SIGN E +11D3C..11D3D;N # Mn [2] MASARAM GONDI VOWEL SIGN AI..MASARAM GONDI VOWEL SIGN O +11D3F..11D45;N # Mn [7] MASARAM GONDI VOWEL SIGN AU..MASARAM GONDI VIRAMA +11D46;N # Lo MASARAM GONDI REPHA +11D47;N # Mn MASARAM GONDI RA-KARA +11D50..11D59;N # Nd [10] MASARAM GONDI DIGIT ZERO..MASARAM GONDI DIGIT NINE 12000..12399;N # Lo [922] CUNEIFORM SIGN A..CUNEIFORM SIGN U U 12400..1246E;N # Nl [111] CUNEIFORM NUMERIC SIGN TWO ASH..CUNEIFORM NUMERIC SIGN NINE U VARIANT FORM 12470..12474;N # Po [5] CUNEIFORM PUNCTUATION SIGN OLD ASSYRIAN WORD DIVIDER..CUNEIFORM PUNCTUATION SIGN DIAGONAL QUADCOLON @@ -2100,10 +2139,12 @@ FFFD;A # So REPLACEMENT CHARACTER 16F51..16F7E;N # Mc [46] MIAO SIGN ASPIRATION..MIAO VOWEL SIGN NG 16F8F..16F92;N # Mn [4] MIAO TONE RIGHT..MIAO TONE BELOW 16F93..16F9F;N # Lm [13] MIAO LETTER TONE-2..MIAO LETTER REFORMED TONE-8 -16FE0;W # Lm TANGUT ITERATION MARK +16FE0..16FE1;W # Lm [2] TANGUT ITERATION MARK..NUSHU ITERATION MARK 17000..187EC;W # Lo [6125] TANGUT IDEOGRAPH-17000..TANGUT IDEOGRAPH-187EC 18800..18AF2;W # Lo [755] TANGUT COMPONENT-001..TANGUT COMPONENT-755 -1B000..1B001;W # Lo [2] KATAKANA LETTER ARCHAIC E..HIRAGANA LETTER ARCHAIC YE +1B000..1B0FF;W # Lo [256] KATAKANA LETTER ARCHAIC E..HENTAIGANA LETTER RE-2 +1B100..1B11E;W # Lo [31] HENTAIGANA LETTER RE-3..HENTAIGANA LETTER N-MU-MO-2 +1B170..1B2FB;W # Lo [396] NUSHU CHARACTER-1B170..NUSHU CHARACTER-1B2FB 1BC00..1BC6A;N # Lo [107] DUPLOYAN LETTER H..DUPLOYAN LETTER VOCALIC M 1BC70..1BC7C;N # Lo [13] DUPLOYAN AFFIX LEFT HORIZONTAL SECANT..DUPLOYAN AFFIX ATTACHED TANGENT HOOK 1BC80..1BC88;N # Lo [9] DUPLOYAN AFFIX HIGH ACUTE..DUPLOYAN AFFIX HIGH VERTICAL @@ -2255,6 +2296,7 @@ FFFD;A # So REPLACEMENT CHARACTER 1F210..1F23B;W # So [44] SQUARED CJK UNIFIED IDEOGRAPH-624B..SQUARED CJK UNIFIED IDEOGRAPH-914D 1F240..1F248;W # So [9] TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-672C..TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-6557 1F250..1F251;W # So [2] CIRCLED IDEOGRAPH ADVANTAGE..CIRCLED IDEOGRAPH ACCEPT +1F260..1F265;W # So [6] ROUNDED SYMBOL FOR FU..ROUNDED SYMBOL FOR CAI 1F300..1F320;W # So [33] CYCLONE..SHOOTING STAR 1F321..1F32C;N # So [12] THERMOMETER..WIND BLOWING FACE 1F32D..1F335;W # So [9] HOT DOG..CACTUS @@ -2299,10 +2341,11 @@ FFFD;A # So REPLACEMENT CHARACTER 1F6CC;W # So SLEEPING ACCOMMODATION 1F6CD..1F6CF;N # So [3] SHOPPING BAGS..BED 1F6D0..1F6D2;W # So [3] PLACE OF WORSHIP..SHOPPING TROLLEY +1F6D3..1F6D4;N # So [2] STUPA..PAGODA 1F6E0..1F6EA;N # So [11] HAMMER AND WRENCH..NORTHEAST-POINTING AIRPLANE 1F6EB..1F6EC;W # So [2] AIRPLANE DEPARTURE..AIRPLANE ARRIVING 1F6F0..1F6F3;N # So [4] SATELLITE..PASSENGER SHIP -1F6F4..1F6F6;W # So [3] SCOOTER..CANOE +1F6F4..1F6F8;W # So [5] SCOOTER..FLYING SAUCER 1F700..1F773;N # So [116] ALCHEMICAL SYMBOL FOR QUINTESSENCE..ALCHEMICAL SYMBOL FOR HALF OUNCE 1F780..1F7D4;N # So [85] BLACK LEFT-POINTING ISOSCELES RIGHT TRIANGLE..HEAVY TWELVE POINTED PINWHEEL STAR 1F800..1F80B;N # So [12] LEFTWARDS ARROW WITH SMALL TRIANGLE ARROWHEAD..DOWNWARDS ARROW WITH LARGE TRIANGLE ARROWHEAD @@ -2310,14 +2353,13 @@ FFFD;A # So REPLACEMENT CHARACTER 1F850..1F859;N # So [10] LEFTWARDS SANS-SERIF ARROW..UP DOWN SANS-SERIF ARROW 1F860..1F887;N # So [40] WIDE-HEADED LEFTWARDS LIGHT BARB ARROW..WIDE-HEADED SOUTH WEST VERY HEAVY BARB ARROW 1F890..1F8AD;N # So [30] LEFTWARDS TRIANGLE ARROWHEAD..WHITE ARROW SHAFT WIDTH TWO THIRDS -1F910..1F91E;W # So [15] ZIPPER-MOUTH FACE..HAND WITH INDEX AND MIDDLE FINGERS CROSSED -1F920..1F927;W # So [8] FACE WITH COWBOY HAT..SNEEZING FACE -1F930;W # So PREGNANT WOMAN -1F933..1F93E;W # So [12] SELFIE..HANDBALL -1F940..1F94B;W # So [12] WILTED FLOWER..MARTIAL ARTS UNIFORM -1F950..1F95E;W # So [15] CROISSANT..PANCAKES -1F980..1F991;W # So [18] CRAB..SQUID +1F900..1F90B;N # So [12] CIRCLED CROSS FORMEE WITH FOUR DOTS..DOWNWARD FACING NOTCHED HOOK WITH DOT +1F910..1F93E;W # So [47] ZIPPER-MOUTH FACE..HANDBALL +1F940..1F94C;W # So [13] WILTED FLOWER..CURLING STONE +1F950..1F96B;W # So [28] CROISSANT..CANNED FOOD +1F980..1F997;W # So [24] CRAB..CRICKET 1F9C0;W # So CHEESE WEDGE +1F9D0..1F9E6;W # So [23] FACE WITH MONOCLE..SOCKS 20000..2A6D6;W # Lo [42711] CJK UNIFIED IDEOGRAPH-20000..CJK UNIFIED IDEOGRAPH-2A6D6 2A6D7..2A6FF;W # Cn [41] <reserved-2A6D7>..<reserved-2A6FF> 2A700..2B734;W # Lo [4149] CJK UNIFIED IDEOGRAPH-2A700..CJK UNIFIED IDEOGRAPH-2B734 @@ -2325,7 +2367,9 @@ FFFD;A # So REPLACEMENT CHARACTER 2B740..2B81D;W # Lo [222] CJK UNIFIED IDEOGRAPH-2B740..CJK UNIFIED IDEOGRAPH-2B81D 2B81E..2B81F;W # Cn [2] <reserved-2B81E>..<reserved-2B81F> 2B820..2CEA1;W # Lo [5762] CJK UNIFIED IDEOGRAPH-2B820..CJK UNIFIED IDEOGRAPH-2CEA1 -2CEA2..2F7FF;W # Cn [10590] <reserved-2CEA2>..<reserved-2F7FF> +2CEA2..2CEAF;W # Cn [14] <reserved-2CEA2>..<reserved-2CEAF> +2CEB0..2EBE0;W # Lo [7473] CJK UNIFIED IDEOGRAPH-2CEB0..CJK UNIFIED IDEOGRAPH-2EBE0 +2EBE1..2F7FF;W # Cn [3103] <reserved-2EBE1>..<reserved-2F7FF> 2F800..2FA1D;W # Lo [542] CJK COMPATIBILITY IDEOGRAPH-2F800..CJK COMPATIBILITY IDEOGRAPH-2FA1D 2FA1E..2FFFD;W # Cn [1504] <reserved-2FA1E>..<reserved-2FFFD> 30000..3FFFD;W # Cn [65534] <reserved-30000>..<reserved-3FFFD> diff --git a/unicode/UnicodeData.txt b/unicode/UnicodeData.txt index a756976461..d89c64f526 100644 --- a/unicode/UnicodeData.txt +++ b/unicode/UnicodeData.txt @@ -2072,6 +2072,17 @@ 085A;MANDAIC VOCALIZATION MARK;Mn;220;NSM;;;;;N;;;;; 085B;MANDAIC GEMINATION MARK;Mn;220;NSM;;;;;N;;;;; 085E;MANDAIC PUNCTUATION;Po;0;R;;;;;N;;;;; +0860;SYRIAC LETTER MALAYALAM NGA;Lo;0;AL;;;;;N;;;;; +0861;SYRIAC LETTER MALAYALAM JA;Lo;0;AL;;;;;N;;;;; +0862;SYRIAC LETTER MALAYALAM NYA;Lo;0;AL;;;;;N;;;;; +0863;SYRIAC LETTER MALAYALAM TTA;Lo;0;AL;;;;;N;;;;; +0864;SYRIAC LETTER MALAYALAM NNA;Lo;0;AL;;;;;N;;;;; +0865;SYRIAC LETTER MALAYALAM NNNA;Lo;0;AL;;;;;N;;;;; +0866;SYRIAC LETTER MALAYALAM BHA;Lo;0;AL;;;;;N;;;;; +0867;SYRIAC LETTER MALAYALAM RA;Lo;0;AL;;;;;N;;;;; +0868;SYRIAC LETTER MALAYALAM LLA;Lo;0;AL;;;;;N;;;;; +0869;SYRIAC LETTER MALAYALAM LLLA;Lo;0;AL;;;;;N;;;;; +086A;SYRIAC LETTER MALAYALAM SSA;Lo;0;AL;;;;;N;;;;; 08A0;ARABIC LETTER BEH WITH SMALL V BELOW;Lo;0;AL;;;;;N;;;;; 08A1;ARABIC LETTER BEH WITH HAMZA ABOVE;Lo;0;AL;;;;;N;;;;; 08A2;ARABIC LETTER JEEM WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;; @@ -2366,6 +2377,8 @@ 09F9;BENGALI CURRENCY DENOMINATOR SIXTEEN;No;0;L;;;;16;N;;;;; 09FA;BENGALI ISSHAR;So;0;L;;;;;N;;;;; 09FB;BENGALI GANDA MARK;Sc;0;ET;;;;;N;;;;; +09FC;BENGALI LETTER VEDIC ANUSVARA;Lo;0;L;;;;;N;;;;; +09FD;BENGALI ABBREVIATION SIGN;Po;0;L;;;;;N;;;;; 0A01;GURMUKHI SIGN ADAK BINDI;Mn;0;NSM;;;;;N;;;;; 0A02;GURMUKHI SIGN BINDI;Mn;0;NSM;;;;;N;;;;; 0A03;GURMUKHI SIGN VISARGA;Mc;0;L;;;;;N;;;;; @@ -2530,6 +2543,12 @@ 0AF0;GUJARATI ABBREVIATION SIGN;Po;0;L;;;;;N;;;;; 0AF1;GUJARATI RUPEE SIGN;Sc;0;ET;;;;;N;;;;; 0AF9;GUJARATI LETTER ZHA;Lo;0;L;;;;;N;;;;; +0AFA;GUJARATI SIGN SUKUN;Mn;0;NSM;;;;;N;;;;; +0AFB;GUJARATI SIGN SHADDA;Mn;0;NSM;;;;;N;;;;; +0AFC;GUJARATI SIGN MADDAH;Mn;0;NSM;;;;;N;;;;; +0AFD;GUJARATI SIGN THREE-DOT NUKTA ABOVE;Mn;0;NSM;;;;;N;;;;; +0AFE;GUJARATI SIGN CIRCLE NUKTA ABOVE;Mn;0;NSM;;;;;N;;;;; +0AFF;GUJARATI SIGN TWO-CIRCLE NUKTA ABOVE;Mn;0;NSM;;;;;N;;;;; 0B01;ORIYA SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; 0B02;ORIYA SIGN ANUSVARA;Mc;0;L;;;;;N;;;;; 0B03;ORIYA SIGN VISARGA;Mc;0;L;;;;;N;;;;; @@ -2876,6 +2895,7 @@ 0CEF;KANNADA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 0CF1;KANNADA SIGN JIHVAMULIYA;Lo;0;L;;;;;N;;;;; 0CF2;KANNADA SIGN UPADHMANIYA;Lo;0;L;;;;;N;;;;; +0D00;MALAYALAM SIGN COMBINING ANUSVARA ABOVE;Mn;0;NSM;;;;;N;;;;; 0D01;MALAYALAM SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; 0D02;MALAYALAM SIGN ANUSVARA;Mc;0;L;;;;;N;;;;; 0D03;MALAYALAM SIGN VISARGA;Mc;0;L;;;;;N;;;;; @@ -2931,6 +2951,8 @@ 0D38;MALAYALAM LETTER SA;Lo;0;L;;;;;N;;;;; 0D39;MALAYALAM LETTER HA;Lo;0;L;;;;;N;;;;; 0D3A;MALAYALAM LETTER TTTA;Lo;0;L;;;;;N;;;;; +0D3B;MALAYALAM SIGN VERTICAL BAR VIRAMA;Mn;9;NSM;;;;;N;;;;; +0D3C;MALAYALAM SIGN CIRCULAR VIRAMA;Mn;9;NSM;;;;;N;;;;; 0D3D;MALAYALAM SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; 0D3E;MALAYALAM VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 0D3F;MALAYALAM VOWEL SIGN I;Mc;0;L;;;;;N;;;;; @@ -6413,6 +6435,7 @@ 1CF4;VEDIC TONE CANDRA ABOVE;Mn;230;NSM;;;;;N;;;;; 1CF5;VEDIC SIGN JIHVAMULIYA;Lo;0;L;;;;;N;;;;; 1CF6;VEDIC SIGN UPADHMANIYA;Lo;0;L;;;;;N;;;;; +1CF7;VEDIC SIGN ATIKRAMA;Mc;0;L;;;;;N;;;;; 1CF8;VEDIC TONE RING ABOVE;Mn;230;NSM;;;;;N;;;;; 1CF9;VEDIC TONE DOUBLE RING ABOVE;Mn;230;NSM;;;;;N;;;;; 1D00;LATIN LETTER SMALL CAPITAL A;Ll;0;L;;;;;N;;;;; @@ -6661,6 +6684,10 @@ 1DF3;COMBINING LATIN SMALL LETTER O WITH DIAERESIS;Mn;230;NSM;;;;;N;;;;; 1DF4;COMBINING LATIN SMALL LETTER U WITH DIAERESIS;Mn;230;NSM;;;;;N;;;;; 1DF5;COMBINING UP TACK ABOVE;Mn;230;NSM;;;;;N;;;;; +1DF6;COMBINING KAVYKA ABOVE RIGHT;Mn;232;NSM;;;;;N;;;;; +1DF7;COMBINING KAVYKA ABOVE LEFT;Mn;228;NSM;;;;;N;;;;; +1DF8;COMBINING DOT ABOVE LEFT;Mn;228;NSM;;;;;N;;;;; +1DF9;COMBINING WIDE INVERTED BRIDGE BELOW;Mn;220;NSM;;;;;N;;;;; 1DFB;COMBINING DELETION MARK;Mn;230;NSM;;;;;N;;;;; 1DFC;COMBINING DOUBLE INVERTED BREVE BELOW;Mn;233;NSM;;;;;N;;;;; 1DFD;COMBINING ALMOST EQUAL TO BELOW;Mn;220;NSM;;;;;N;;;;; @@ -7339,6 +7366,7 @@ 20BC;MANAT SIGN;Sc;0;ET;;;;;N;;;;; 20BD;RUBLE SIGN;Sc;0;ET;;;;;N;;;;; 20BE;LARI SIGN;Sc;0;ET;;;;;N;;;;; +20BF;BITCOIN SIGN;Sc;0;ET;;;;;N;;;;; 20D0;COMBINING LEFT HARPOON ABOVE;Mn;230;NSM;;;;;N;NON-SPACING LEFT HARPOON ABOVE;;;; 20D1;COMBINING RIGHT HARPOON ABOVE;Mn;230;NSM;;;;;N;NON-SPACING RIGHT HARPOON ABOVE;;;; 20D2;COMBINING LONG VERTICAL LINE OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING LONG VERTICAL BAR OVERLAY;;;; @@ -8135,6 +8163,7 @@ 23FC;POWER ON-OFF SYMBOL;So;0;ON;;;;;N;;;;; 23FD;POWER ON SYMBOL;So;0;ON;;;;;N;;;;; 23FE;POWER SLEEP SYMBOL;So;0;ON;;;;;N;;;;; +23FF;OBSERVER EYE SYMBOL;So;0;ON;;;;;N;;;;; 2400;SYMBOL FOR NULL;So;0;ON;;;;;N;GRAPHIC FOR NULL;;;; 2401;SYMBOL FOR START OF HEADING;So;0;ON;;;;;N;GRAPHIC FOR START OF HEADING;;;; 2402;SYMBOL FOR START OF TEXT;So;0;ON;;;;;N;GRAPHIC FOR START OF TEXT;;;; @@ -10083,6 +10112,7 @@ 2BCF;ROTATED WHITE FOUR POINTED CUSP;So;0;ON;;;;;N;;;;; 2BD0;SQUARE POSITION INDICATOR;So;0;ON;;;;;N;;;;; 2BD1;UNCERTAINTY SIGN;So;0;ON;;;;;N;;;;; +2BD2;GROUP MARK;So;0;ON;;;;;N;;;;; 2BEC;LEFTWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS;So;0;ON;;;;;N;;;;; 2BED;UPWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS;So;0;ON;;;;;N;;;;; 2BEE;RIGHTWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS;So;0;ON;;;;;N;;;;; @@ -10615,6 +10645,11 @@ 2E42;DOUBLE LOW-REVERSED-9 QUOTATION MARK;Ps;0;ON;;;;;N;;;;; 2E43;DASH WITH LEFT UPTURN;Po;0;ON;;;;;N;;;;; 2E44;DOUBLE SUSPENSION MARK;Po;0;ON;;;;;N;;;;; +2E45;INVERTED LOW KAVYKA;Po;0;ON;;;;;N;;;;; +2E46;INVERTED LOW KAVYKA WITH KAVYKA ABOVE;Po;0;ON;;;;;N;;;;; +2E47;LOW KAVYKA;Po;0;ON;;;;;N;;;;; +2E48;LOW KAVYKA WITH DOT;Po;0;ON;;;;;N;;;;; +2E49;DOUBLE STACKED COMMA;Po;0;ON;;;;;N;;;;; 2E80;CJK RADICAL REPEAT;So;0;ON;;;;;N;;;;; 2E81;CJK RADICAL CLIFF;So;0;ON;;;;;N;;;;; 2E82;CJK RADICAL SECOND ONE;So;0;ON;;;;;N;;;;; @@ -11250,6 +11285,7 @@ 312B;BOPOMOFO LETTER NG;Lo;0;L;;;;;N;;;;; 312C;BOPOMOFO LETTER GN;Lo;0;L;;;;;N;;;;; 312D;BOPOMOFO LETTER IH;Lo;0;L;;;;;N;;;;; +312E;BOPOMOFO LETTER O WITH DOT ABOVE;Lo;0;L;;;;;N;;;;; 3131;HANGUL LETTER KIYEOK;Lo;0;L;<compat> 1100;;;;N;HANGUL LETTER GIYEOG;;;; 3132;HANGUL LETTER SSANGKIYEOK;Lo;0;L;<compat> 1101;;;;N;HANGUL LETTER SSANG GIYEOG;;;; 3133;HANGUL LETTER KIYEOK-SIOS;Lo;0;L;<compat> 11AA;;;;N;HANGUL LETTER GIYEOG SIOS;;;; @@ -12016,7 +12052,7 @@ 4DFE;HEXAGRAM FOR AFTER COMPLETION;So;0;ON;;;;;N;;;;; 4DFF;HEXAGRAM FOR BEFORE COMPLETION;So;0;ON;;;;;N;;;;; 4E00;<CJK Ideograph, First>;Lo;0;L;;;;;N;;;;; -9FD5;<CJK Ideograph, Last>;Lo;0;L;;;;;N;;;;; +9FEA;<CJK Ideograph, Last>;Lo;0;L;;;;;N;;;;; A000;YI SYLLABLE IT;Lo;0;L;;;;;N;;;;; A001;YI SYLLABLE IX;Lo;0;L;;;;;N;;;;; A002;YI SYLLABLE I;Lo;0;L;;;;;N;;;;; @@ -17093,6 +17129,9 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 10321;OLD ITALIC NUMERAL FIVE;No;0;L;;;;5;N;;;;; 10322;OLD ITALIC NUMERAL TEN;No;0;L;;;;10;N;;;;; 10323;OLD ITALIC NUMERAL FIFTY;No;0;L;;;;50;N;;;;; +1032D;OLD ITALIC LETTER YE;Lo;0;L;;;;;N;;;;; +1032E;OLD ITALIC LETTER NORTHERN TSE;Lo;0;L;;;;;N;;;;; +1032F;OLD ITALIC LETTER SOUTHERN TSE;Lo;0;L;;;;;N;;;;; 10330;GOTHIC LETTER AHSA;Lo;0;L;;;;;N;;;;; 10331;GOTHIC LETTER BAIRKAN;Lo;0;L;;;;;N;;;;; 10332;GOTHIC LETTER GIBA;Lo;0;L;;;;;N;;;;; @@ -20068,6 +20107,158 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 118F1;WARANG CITI NUMBER EIGHTY;No;0;L;;;;80;N;;;;; 118F2;WARANG CITI NUMBER NINETY;No;0;L;;;;90;N;;;;; 118FF;WARANG CITI OM;Lo;0;L;;;;;N;;;;; +11A00;ZANABAZAR SQUARE LETTER A;Lo;0;L;;;;;N;;;;; +11A01;ZANABAZAR SQUARE VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +11A02;ZANABAZAR SQUARE VOWEL SIGN UE;Mn;0;NSM;;;;;N;;;;; +11A03;ZANABAZAR SQUARE VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +11A04;ZANABAZAR SQUARE VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +11A05;ZANABAZAR SQUARE VOWEL SIGN OE;Mn;0;NSM;;;;;N;;;;; +11A06;ZANABAZAR SQUARE VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; +11A07;ZANABAZAR SQUARE VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; +11A08;ZANABAZAR SQUARE VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; +11A09;ZANABAZAR SQUARE VOWEL SIGN REVERSED I;Mn;0;NSM;;;;;N;;;;; +11A0A;ZANABAZAR SQUARE VOWEL LENGTH MARK;Mn;0;NSM;;;;;N;;;;; +11A0B;ZANABAZAR SQUARE LETTER KA;Lo;0;L;;;;;N;;;;; +11A0C;ZANABAZAR SQUARE LETTER KHA;Lo;0;L;;;;;N;;;;; +11A0D;ZANABAZAR SQUARE LETTER GA;Lo;0;L;;;;;N;;;;; +11A0E;ZANABAZAR SQUARE LETTER GHA;Lo;0;L;;;;;N;;;;; +11A0F;ZANABAZAR SQUARE LETTER NGA;Lo;0;L;;;;;N;;;;; +11A10;ZANABAZAR SQUARE LETTER CA;Lo;0;L;;;;;N;;;;; +11A11;ZANABAZAR SQUARE LETTER CHA;Lo;0;L;;;;;N;;;;; +11A12;ZANABAZAR SQUARE LETTER JA;Lo;0;L;;;;;N;;;;; +11A13;ZANABAZAR SQUARE LETTER NYA;Lo;0;L;;;;;N;;;;; +11A14;ZANABAZAR SQUARE LETTER TTA;Lo;0;L;;;;;N;;;;; +11A15;ZANABAZAR SQUARE LETTER TTHA;Lo;0;L;;;;;N;;;;; +11A16;ZANABAZAR SQUARE LETTER DDA;Lo;0;L;;;;;N;;;;; +11A17;ZANABAZAR SQUARE LETTER DDHA;Lo;0;L;;;;;N;;;;; +11A18;ZANABAZAR SQUARE LETTER NNA;Lo;0;L;;;;;N;;;;; +11A19;ZANABAZAR SQUARE LETTER TA;Lo;0;L;;;;;N;;;;; +11A1A;ZANABAZAR SQUARE LETTER THA;Lo;0;L;;;;;N;;;;; +11A1B;ZANABAZAR SQUARE LETTER DA;Lo;0;L;;;;;N;;;;; +11A1C;ZANABAZAR SQUARE LETTER DHA;Lo;0;L;;;;;N;;;;; +11A1D;ZANABAZAR SQUARE LETTER NA;Lo;0;L;;;;;N;;;;; +11A1E;ZANABAZAR SQUARE LETTER PA;Lo;0;L;;;;;N;;;;; +11A1F;ZANABAZAR SQUARE LETTER PHA;Lo;0;L;;;;;N;;;;; +11A20;ZANABAZAR SQUARE LETTER BA;Lo;0;L;;;;;N;;;;; +11A21;ZANABAZAR SQUARE LETTER BHA;Lo;0;L;;;;;N;;;;; +11A22;ZANABAZAR SQUARE LETTER MA;Lo;0;L;;;;;N;;;;; +11A23;ZANABAZAR SQUARE LETTER TSA;Lo;0;L;;;;;N;;;;; +11A24;ZANABAZAR SQUARE LETTER TSHA;Lo;0;L;;;;;N;;;;; +11A25;ZANABAZAR SQUARE LETTER DZA;Lo;0;L;;;;;N;;;;; +11A26;ZANABAZAR SQUARE LETTER DZHA;Lo;0;L;;;;;N;;;;; +11A27;ZANABAZAR SQUARE LETTER ZHA;Lo;0;L;;;;;N;;;;; +11A28;ZANABAZAR SQUARE LETTER ZA;Lo;0;L;;;;;N;;;;; +11A29;ZANABAZAR SQUARE LETTER -A;Lo;0;L;;;;;N;;;;; +11A2A;ZANABAZAR SQUARE LETTER YA;Lo;0;L;;;;;N;;;;; +11A2B;ZANABAZAR SQUARE LETTER RA;Lo;0;L;;;;;N;;;;; +11A2C;ZANABAZAR SQUARE LETTER LA;Lo;0;L;;;;;N;;;;; +11A2D;ZANABAZAR SQUARE LETTER VA;Lo;0;L;;;;;N;;;;; +11A2E;ZANABAZAR SQUARE LETTER SHA;Lo;0;L;;;;;N;;;;; +11A2F;ZANABAZAR SQUARE LETTER SSA;Lo;0;L;;;;;N;;;;; +11A30;ZANABAZAR SQUARE LETTER SA;Lo;0;L;;;;;N;;;;; +11A31;ZANABAZAR SQUARE LETTER HA;Lo;0;L;;;;;N;;;;; +11A32;ZANABAZAR SQUARE LETTER KSSA;Lo;0;L;;;;;N;;;;; +11A33;ZANABAZAR SQUARE FINAL CONSONANT MARK;Mn;0;NSM;;;;;N;;;;; +11A34;ZANABAZAR SQUARE SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; +11A35;ZANABAZAR SQUARE SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; +11A36;ZANABAZAR SQUARE SIGN CANDRABINDU WITH ORNAMENT;Mn;0;NSM;;;;;N;;;;; +11A37;ZANABAZAR SQUARE SIGN CANDRA WITH ORNAMENT;Mn;0;NSM;;;;;N;;;;; +11A38;ZANABAZAR SQUARE SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +11A39;ZANABAZAR SQUARE SIGN VISARGA;Mc;0;L;;;;;N;;;;; +11A3A;ZANABAZAR SQUARE CLUSTER-INITIAL LETTER RA;Lo;0;L;;;;;N;;;;; +11A3B;ZANABAZAR SQUARE CLUSTER-FINAL LETTER YA;Mn;0;NSM;;;;;N;;;;; +11A3C;ZANABAZAR SQUARE CLUSTER-FINAL LETTER RA;Mn;0;NSM;;;;;N;;;;; +11A3D;ZANABAZAR SQUARE CLUSTER-FINAL LETTER LA;Mn;0;NSM;;;;;N;;;;; +11A3E;ZANABAZAR SQUARE CLUSTER-FINAL LETTER VA;Mn;0;NSM;;;;;N;;;;; +11A3F;ZANABAZAR SQUARE INITIAL HEAD MARK;Po;0;L;;;;;N;;;;; +11A40;ZANABAZAR SQUARE CLOSING HEAD MARK;Po;0;L;;;;;N;;;;; +11A41;ZANABAZAR SQUARE MARK TSHEG;Po;0;L;;;;;N;;;;; +11A42;ZANABAZAR SQUARE MARK SHAD;Po;0;L;;;;;N;;;;; +11A43;ZANABAZAR SQUARE MARK DOUBLE SHAD;Po;0;L;;;;;N;;;;; +11A44;ZANABAZAR SQUARE MARK LONG TSHEG;Po;0;L;;;;;N;;;;; +11A45;ZANABAZAR SQUARE INITIAL DOUBLE-LINED HEAD MARK;Po;0;L;;;;;N;;;;; +11A46;ZANABAZAR SQUARE CLOSING DOUBLE-LINED HEAD MARK;Po;0;L;;;;;N;;;;; +11A47;ZANABAZAR SQUARE SUBJOINER;Mn;9;NSM;;;;;N;;;;; +11A50;SOYOMBO LETTER A;Lo;0;L;;;;;N;;;;; +11A51;SOYOMBO VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +11A52;SOYOMBO VOWEL SIGN UE;Mn;0;NSM;;;;;N;;;;; +11A53;SOYOMBO VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +11A54;SOYOMBO VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +11A55;SOYOMBO VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; +11A56;SOYOMBO VOWEL SIGN OE;Mn;0;NSM;;;;;N;;;;; +11A57;SOYOMBO VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; +11A58;SOYOMBO VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; +11A59;SOYOMBO VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; +11A5A;SOYOMBO VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; +11A5B;SOYOMBO VOWEL LENGTH MARK;Mn;0;NSM;;;;;N;;;;; +11A5C;SOYOMBO LETTER KA;Lo;0;L;;;;;N;;;;; +11A5D;SOYOMBO LETTER KHA;Lo;0;L;;;;;N;;;;; +11A5E;SOYOMBO LETTER GA;Lo;0;L;;;;;N;;;;; +11A5F;SOYOMBO LETTER GHA;Lo;0;L;;;;;N;;;;; +11A60;SOYOMBO LETTER NGA;Lo;0;L;;;;;N;;;;; +11A61;SOYOMBO LETTER CA;Lo;0;L;;;;;N;;;;; +11A62;SOYOMBO LETTER CHA;Lo;0;L;;;;;N;;;;; +11A63;SOYOMBO LETTER JA;Lo;0;L;;;;;N;;;;; +11A64;SOYOMBO LETTER JHA;Lo;0;L;;;;;N;;;;; +11A65;SOYOMBO LETTER NYA;Lo;0;L;;;;;N;;;;; +11A66;SOYOMBO LETTER TTA;Lo;0;L;;;;;N;;;;; +11A67;SOYOMBO LETTER TTHA;Lo;0;L;;;;;N;;;;; +11A68;SOYOMBO LETTER DDA;Lo;0;L;;;;;N;;;;; +11A69;SOYOMBO LETTER DDHA;Lo;0;L;;;;;N;;;;; +11A6A;SOYOMBO LETTER NNA;Lo;0;L;;;;;N;;;;; +11A6B;SOYOMBO LETTER TA;Lo;0;L;;;;;N;;;;; +11A6C;SOYOMBO LETTER THA;Lo;0;L;;;;;N;;;;; +11A6D;SOYOMBO LETTER DA;Lo;0;L;;;;;N;;;;; +11A6E;SOYOMBO LETTER DHA;Lo;0;L;;;;;N;;;;; +11A6F;SOYOMBO LETTER NA;Lo;0;L;;;;;N;;;;; +11A70;SOYOMBO LETTER PA;Lo;0;L;;;;;N;;;;; +11A71;SOYOMBO LETTER PHA;Lo;0;L;;;;;N;;;;; +11A72;SOYOMBO LETTER BA;Lo;0;L;;;;;N;;;;; +11A73;SOYOMBO LETTER BHA;Lo;0;L;;;;;N;;;;; +11A74;SOYOMBO LETTER MA;Lo;0;L;;;;;N;;;;; +11A75;SOYOMBO LETTER TSA;Lo;0;L;;;;;N;;;;; +11A76;SOYOMBO LETTER TSHA;Lo;0;L;;;;;N;;;;; +11A77;SOYOMBO LETTER DZA;Lo;0;L;;;;;N;;;;; +11A78;SOYOMBO LETTER ZHA;Lo;0;L;;;;;N;;;;; +11A79;SOYOMBO LETTER ZA;Lo;0;L;;;;;N;;;;; +11A7A;SOYOMBO LETTER -A;Lo;0;L;;;;;N;;;;; +11A7B;SOYOMBO LETTER YA;Lo;0;L;;;;;N;;;;; +11A7C;SOYOMBO LETTER RA;Lo;0;L;;;;;N;;;;; +11A7D;SOYOMBO LETTER LA;Lo;0;L;;;;;N;;;;; +11A7E;SOYOMBO LETTER VA;Lo;0;L;;;;;N;;;;; +11A7F;SOYOMBO LETTER SHA;Lo;0;L;;;;;N;;;;; +11A80;SOYOMBO LETTER SSA;Lo;0;L;;;;;N;;;;; +11A81;SOYOMBO LETTER SA;Lo;0;L;;;;;N;;;;; +11A82;SOYOMBO LETTER HA;Lo;0;L;;;;;N;;;;; +11A83;SOYOMBO LETTER KSSA;Lo;0;L;;;;;N;;;;; +11A86;SOYOMBO CLUSTER-INITIAL LETTER RA;Lo;0;L;;;;;N;;;;; +11A87;SOYOMBO CLUSTER-INITIAL LETTER LA;Lo;0;L;;;;;N;;;;; +11A88;SOYOMBO CLUSTER-INITIAL LETTER SHA;Lo;0;L;;;;;N;;;;; +11A89;SOYOMBO CLUSTER-INITIAL LETTER SA;Lo;0;L;;;;;N;;;;; +11A8A;SOYOMBO FINAL CONSONANT SIGN G;Mn;0;NSM;;;;;N;;;;; +11A8B;SOYOMBO FINAL CONSONANT SIGN K;Mn;0;NSM;;;;;N;;;;; +11A8C;SOYOMBO FINAL CONSONANT SIGN NG;Mn;0;NSM;;;;;N;;;;; +11A8D;SOYOMBO FINAL CONSONANT SIGN D;Mn;0;NSM;;;;;N;;;;; +11A8E;SOYOMBO FINAL CONSONANT SIGN N;Mn;0;NSM;;;;;N;;;;; +11A8F;SOYOMBO FINAL CONSONANT SIGN B;Mn;0;NSM;;;;;N;;;;; +11A90;SOYOMBO FINAL CONSONANT SIGN M;Mn;0;NSM;;;;;N;;;;; +11A91;SOYOMBO FINAL CONSONANT SIGN R;Mn;0;NSM;;;;;N;;;;; +11A92;SOYOMBO FINAL CONSONANT SIGN L;Mn;0;NSM;;;;;N;;;;; +11A93;SOYOMBO FINAL CONSONANT SIGN SH;Mn;0;NSM;;;;;N;;;;; +11A94;SOYOMBO FINAL CONSONANT SIGN S;Mn;0;NSM;;;;;N;;;;; +11A95;SOYOMBO FINAL CONSONANT SIGN -A;Mn;0;NSM;;;;;N;;;;; +11A96;SOYOMBO SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +11A97;SOYOMBO SIGN VISARGA;Mc;0;L;;;;;N;;;;; +11A98;SOYOMBO GEMINATION MARK;Mn;0;NSM;;;;;N;;;;; +11A99;SOYOMBO SUBJOINER;Mn;9;NSM;;;;;N;;;;; +11A9A;SOYOMBO MARK TSHEG;Po;0;L;;;;;N;;;;; +11A9B;SOYOMBO MARK SHAD;Po;0;L;;;;;N;;;;; +11A9C;SOYOMBO MARK DOUBLE SHAD;Po;0;L;;;;;N;;;;; +11A9E;SOYOMBO HEAD MARK WITH MOON AND SUN AND TRIPLE FLAME;Po;0;L;;;;;N;;;;; +11A9F;SOYOMBO HEAD MARK WITH MOON AND SUN AND FLAME;Po;0;L;;;;;N;;;;; +11AA0;SOYOMBO HEAD MARK WITH MOON AND SUN;Po;0;L;;;;;N;;;;; +11AA1;SOYOMBO TERMINAL MARK-1;Po;0;L;;;;;N;;;;; +11AA2;SOYOMBO TERMINAL MARK-2;Po;0;L;;;;;N;;;;; 11AC0;PAU CIN HAU LETTER PA;Lo;0;L;;;;;N;;;;; 11AC1;PAU CIN HAU LETTER KA;Lo;0;L;;;;;N;;;;; 11AC2;PAU CIN HAU LETTER LA;Lo;0;L;;;;;N;;;;; @@ -20290,6 +20481,81 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 11CB4;MARCHEN VOWEL SIGN O;Mc;0;L;;;;;N;;;;; 11CB5;MARCHEN SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; 11CB6;MARCHEN SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; +11D00;MASARAM GONDI LETTER A;Lo;0;L;;;;;N;;;;; +11D01;MASARAM GONDI LETTER AA;Lo;0;L;;;;;N;;;;; +11D02;MASARAM GONDI LETTER I;Lo;0;L;;;;;N;;;;; +11D03;MASARAM GONDI LETTER II;Lo;0;L;;;;;N;;;;; +11D04;MASARAM GONDI LETTER U;Lo;0;L;;;;;N;;;;; +11D05;MASARAM GONDI LETTER UU;Lo;0;L;;;;;N;;;;; +11D06;MASARAM GONDI LETTER E;Lo;0;L;;;;;N;;;;; +11D08;MASARAM GONDI LETTER AI;Lo;0;L;;;;;N;;;;; +11D09;MASARAM GONDI LETTER O;Lo;0;L;;;;;N;;;;; +11D0B;MASARAM GONDI LETTER AU;Lo;0;L;;;;;N;;;;; +11D0C;MASARAM GONDI LETTER KA;Lo;0;L;;;;;N;;;;; +11D0D;MASARAM GONDI LETTER KHA;Lo;0;L;;;;;N;;;;; +11D0E;MASARAM GONDI LETTER GA;Lo;0;L;;;;;N;;;;; +11D0F;MASARAM GONDI LETTER GHA;Lo;0;L;;;;;N;;;;; +11D10;MASARAM GONDI LETTER NGA;Lo;0;L;;;;;N;;;;; +11D11;MASARAM GONDI LETTER CA;Lo;0;L;;;;;N;;;;; +11D12;MASARAM GONDI LETTER CHA;Lo;0;L;;;;;N;;;;; +11D13;MASARAM GONDI LETTER JA;Lo;0;L;;;;;N;;;;; +11D14;MASARAM GONDI LETTER JHA;Lo;0;L;;;;;N;;;;; +11D15;MASARAM GONDI LETTER NYA;Lo;0;L;;;;;N;;;;; +11D16;MASARAM GONDI LETTER TTA;Lo;0;L;;;;;N;;;;; +11D17;MASARAM GONDI LETTER TTHA;Lo;0;L;;;;;N;;;;; +11D18;MASARAM GONDI LETTER DDA;Lo;0;L;;;;;N;;;;; +11D19;MASARAM GONDI LETTER DDHA;Lo;0;L;;;;;N;;;;; +11D1A;MASARAM GONDI LETTER NNA;Lo;0;L;;;;;N;;;;; +11D1B;MASARAM GONDI LETTER TA;Lo;0;L;;;;;N;;;;; +11D1C;MASARAM GONDI LETTER THA;Lo;0;L;;;;;N;;;;; +11D1D;MASARAM GONDI LETTER DA;Lo;0;L;;;;;N;;;;; +11D1E;MASARAM GONDI LETTER DHA;Lo;0;L;;;;;N;;;;; +11D1F;MASARAM GONDI LETTER NA;Lo;0;L;;;;;N;;;;; +11D20;MASARAM GONDI LETTER PA;Lo;0;L;;;;;N;;;;; +11D21;MASARAM GONDI LETTER PHA;Lo;0;L;;;;;N;;;;; +11D22;MASARAM GONDI LETTER BA;Lo;0;L;;;;;N;;;;; +11D23;MASARAM GONDI LETTER BHA;Lo;0;L;;;;;N;;;;; +11D24;MASARAM GONDI LETTER MA;Lo;0;L;;;;;N;;;;; +11D25;MASARAM GONDI LETTER YA;Lo;0;L;;;;;N;;;;; +11D26;MASARAM GONDI LETTER RA;Lo;0;L;;;;;N;;;;; +11D27;MASARAM GONDI LETTER LA;Lo;0;L;;;;;N;;;;; +11D28;MASARAM GONDI LETTER VA;Lo;0;L;;;;;N;;;;; +11D29;MASARAM GONDI LETTER SHA;Lo;0;L;;;;;N;;;;; +11D2A;MASARAM GONDI LETTER SSA;Lo;0;L;;;;;N;;;;; +11D2B;MASARAM GONDI LETTER SA;Lo;0;L;;;;;N;;;;; +11D2C;MASARAM GONDI LETTER HA;Lo;0;L;;;;;N;;;;; +11D2D;MASARAM GONDI LETTER LLA;Lo;0;L;;;;;N;;;;; +11D2E;MASARAM GONDI LETTER KSSA;Lo;0;L;;;;;N;;;;; +11D2F;MASARAM GONDI LETTER JNYA;Lo;0;L;;;;;N;;;;; +11D30;MASARAM GONDI LETTER TRA;Lo;0;L;;;;;N;;;;; +11D31;MASARAM GONDI VOWEL SIGN AA;Mn;0;NSM;;;;;N;;;;; +11D32;MASARAM GONDI VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +11D33;MASARAM GONDI VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; +11D34;MASARAM GONDI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +11D35;MASARAM GONDI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +11D36;MASARAM GONDI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; +11D3A;MASARAM GONDI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +11D3C;MASARAM GONDI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; +11D3D;MASARAM GONDI VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; +11D3F;MASARAM GONDI VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;; +11D40;MASARAM GONDI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +11D41;MASARAM GONDI SIGN VISARGA;Mn;0;NSM;;;;;N;;;;; +11D42;MASARAM GONDI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; +11D43;MASARAM GONDI SIGN CANDRA;Mn;0;NSM;;;;;N;;;;; +11D44;MASARAM GONDI SIGN HALANTA;Mn;9;NSM;;;;;N;;;;; +11D45;MASARAM GONDI VIRAMA;Mn;9;NSM;;;;;N;;;;; +11D46;MASARAM GONDI REPHA;Lo;0;L;;;;;N;;;;; +11D47;MASARAM GONDI RA-KARA;Mn;0;NSM;;;;;N;;;;; +11D50;MASARAM GONDI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +11D51;MASARAM GONDI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +11D52;MASARAM GONDI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +11D53;MASARAM GONDI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +11D54;MASARAM GONDI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +11D55;MASARAM GONDI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +11D56;MASARAM GONDI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +11D57;MASARAM GONDI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +11D58;MASARAM GONDI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +11D59;MASARAM GONDI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 12000;CUNEIFORM SIGN A;Lo;0;L;;;;;N;;;;; 12001;CUNEIFORM SIGN A TIMES A;Lo;0;L;;;;;N;;;;; 12002;CUNEIFORM SIGN A TIMES BAD;Lo;0;L;;;;;N;;;;; @@ -24087,6 +24353,7 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 16F9E;MIAO LETTER REFORMED TONE-6;Lm;0;L;;;;;N;;;;; 16F9F;MIAO LETTER REFORMED TONE-8;Lm;0;L;;;;;N;;;;; 16FE0;TANGUT ITERATION MARK;Lm;0;L;;;;;N;;;;; +16FE1;NUSHU ITERATION MARK;Lm;0;L;;;;;N;;;;; 17000;<Tangut Ideograph, First>;Lo;0;L;;;;;N;;;;; 187EC;<Tangut Ideograph, Last>;Lo;0;L;;;;;N;;;;; 18800;TANGUT COMPONENT-001;Lo;0;L;;;;;N;;;;; @@ -24846,6 +25113,687 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 18AF2;TANGUT COMPONENT-755;Lo;0;L;;;;;N;;;;; 1B000;KATAKANA LETTER ARCHAIC E;Lo;0;L;;;;;N;;;;; 1B001;HIRAGANA LETTER ARCHAIC YE;Lo;0;L;;;;;N;;;;; +1B002;HENTAIGANA LETTER A-1;Lo;0;L;;;;;N;;;;; +1B003;HENTAIGANA LETTER A-2;Lo;0;L;;;;;N;;;;; +1B004;HENTAIGANA LETTER A-3;Lo;0;L;;;;;N;;;;; +1B005;HENTAIGANA LETTER A-WO;Lo;0;L;;;;;N;;;;; +1B006;HENTAIGANA LETTER I-1;Lo;0;L;;;;;N;;;;; +1B007;HENTAIGANA LETTER I-2;Lo;0;L;;;;;N;;;;; +1B008;HENTAIGANA LETTER I-3;Lo;0;L;;;;;N;;;;; +1B009;HENTAIGANA LETTER I-4;Lo;0;L;;;;;N;;;;; +1B00A;HENTAIGANA LETTER U-1;Lo;0;L;;;;;N;;;;; +1B00B;HENTAIGANA LETTER U-2;Lo;0;L;;;;;N;;;;; +1B00C;HENTAIGANA LETTER U-3;Lo;0;L;;;;;N;;;;; +1B00D;HENTAIGANA LETTER U-4;Lo;0;L;;;;;N;;;;; +1B00E;HENTAIGANA LETTER U-5;Lo;0;L;;;;;N;;;;; +1B00F;HENTAIGANA LETTER E-2;Lo;0;L;;;;;N;;;;; +1B010;HENTAIGANA LETTER E-3;Lo;0;L;;;;;N;;;;; +1B011;HENTAIGANA LETTER E-4;Lo;0;L;;;;;N;;;;; +1B012;HENTAIGANA LETTER E-5;Lo;0;L;;;;;N;;;;; +1B013;HENTAIGANA LETTER E-6;Lo;0;L;;;;;N;;;;; +1B014;HENTAIGANA LETTER O-1;Lo;0;L;;;;;N;;;;; +1B015;HENTAIGANA LETTER O-2;Lo;0;L;;;;;N;;;;; +1B016;HENTAIGANA LETTER O-3;Lo;0;L;;;;;N;;;;; +1B017;HENTAIGANA LETTER KA-1;Lo;0;L;;;;;N;;;;; +1B018;HENTAIGANA LETTER KA-2;Lo;0;L;;;;;N;;;;; +1B019;HENTAIGANA LETTER KA-3;Lo;0;L;;;;;N;;;;; +1B01A;HENTAIGANA LETTER KA-4;Lo;0;L;;;;;N;;;;; +1B01B;HENTAIGANA LETTER KA-5;Lo;0;L;;;;;N;;;;; +1B01C;HENTAIGANA LETTER KA-6;Lo;0;L;;;;;N;;;;; +1B01D;HENTAIGANA LETTER KA-7;Lo;0;L;;;;;N;;;;; +1B01E;HENTAIGANA LETTER KA-8;Lo;0;L;;;;;N;;;;; +1B01F;HENTAIGANA LETTER KA-9;Lo;0;L;;;;;N;;;;; +1B020;HENTAIGANA LETTER KA-10;Lo;0;L;;;;;N;;;;; +1B021;HENTAIGANA LETTER KA-11;Lo;0;L;;;;;N;;;;; +1B022;HENTAIGANA LETTER KA-KE;Lo;0;L;;;;;N;;;;; +1B023;HENTAIGANA LETTER KI-1;Lo;0;L;;;;;N;;;;; +1B024;HENTAIGANA LETTER KI-2;Lo;0;L;;;;;N;;;;; +1B025;HENTAIGANA LETTER KI-3;Lo;0;L;;;;;N;;;;; +1B026;HENTAIGANA LETTER KI-4;Lo;0;L;;;;;N;;;;; +1B027;HENTAIGANA LETTER KI-5;Lo;0;L;;;;;N;;;;; +1B028;HENTAIGANA LETTER KI-6;Lo;0;L;;;;;N;;;;; +1B029;HENTAIGANA LETTER KI-7;Lo;0;L;;;;;N;;;;; +1B02A;HENTAIGANA LETTER KI-8;Lo;0;L;;;;;N;;;;; +1B02B;HENTAIGANA LETTER KU-1;Lo;0;L;;;;;N;;;;; +1B02C;HENTAIGANA LETTER KU-2;Lo;0;L;;;;;N;;;;; +1B02D;HENTAIGANA LETTER KU-3;Lo;0;L;;;;;N;;;;; +1B02E;HENTAIGANA LETTER KU-4;Lo;0;L;;;;;N;;;;; +1B02F;HENTAIGANA LETTER KU-5;Lo;0;L;;;;;N;;;;; +1B030;HENTAIGANA LETTER KU-6;Lo;0;L;;;;;N;;;;; +1B031;HENTAIGANA LETTER KU-7;Lo;0;L;;;;;N;;;;; +1B032;HENTAIGANA LETTER KE-1;Lo;0;L;;;;;N;;;;; +1B033;HENTAIGANA LETTER KE-2;Lo;0;L;;;;;N;;;;; +1B034;HENTAIGANA LETTER KE-3;Lo;0;L;;;;;N;;;;; +1B035;HENTAIGANA LETTER KE-4;Lo;0;L;;;;;N;;;;; +1B036;HENTAIGANA LETTER KE-5;Lo;0;L;;;;;N;;;;; +1B037;HENTAIGANA LETTER KE-6;Lo;0;L;;;;;N;;;;; +1B038;HENTAIGANA LETTER KO-1;Lo;0;L;;;;;N;;;;; +1B039;HENTAIGANA LETTER KO-2;Lo;0;L;;;;;N;;;;; +1B03A;HENTAIGANA LETTER KO-3;Lo;0;L;;;;;N;;;;; +1B03B;HENTAIGANA LETTER KO-KI;Lo;0;L;;;;;N;;;;; +1B03C;HENTAIGANA LETTER SA-1;Lo;0;L;;;;;N;;;;; +1B03D;HENTAIGANA LETTER SA-2;Lo;0;L;;;;;N;;;;; +1B03E;HENTAIGANA LETTER SA-3;Lo;0;L;;;;;N;;;;; +1B03F;HENTAIGANA LETTER SA-4;Lo;0;L;;;;;N;;;;; +1B040;HENTAIGANA LETTER SA-5;Lo;0;L;;;;;N;;;;; +1B041;HENTAIGANA LETTER SA-6;Lo;0;L;;;;;N;;;;; +1B042;HENTAIGANA LETTER SA-7;Lo;0;L;;;;;N;;;;; +1B043;HENTAIGANA LETTER SA-8;Lo;0;L;;;;;N;;;;; +1B044;HENTAIGANA LETTER SI-1;Lo;0;L;;;;;N;;;;; +1B045;HENTAIGANA LETTER SI-2;Lo;0;L;;;;;N;;;;; +1B046;HENTAIGANA LETTER SI-3;Lo;0;L;;;;;N;;;;; +1B047;HENTAIGANA LETTER SI-4;Lo;0;L;;;;;N;;;;; +1B048;HENTAIGANA LETTER SI-5;Lo;0;L;;;;;N;;;;; +1B049;HENTAIGANA LETTER SI-6;Lo;0;L;;;;;N;;;;; +1B04A;HENTAIGANA LETTER SU-1;Lo;0;L;;;;;N;;;;; +1B04B;HENTAIGANA LETTER SU-2;Lo;0;L;;;;;N;;;;; +1B04C;HENTAIGANA LETTER SU-3;Lo;0;L;;;;;N;;;;; +1B04D;HENTAIGANA LETTER SU-4;Lo;0;L;;;;;N;;;;; +1B04E;HENTAIGANA LETTER SU-5;Lo;0;L;;;;;N;;;;; +1B04F;HENTAIGANA LETTER SU-6;Lo;0;L;;;;;N;;;;; +1B050;HENTAIGANA LETTER SU-7;Lo;0;L;;;;;N;;;;; +1B051;HENTAIGANA LETTER SU-8;Lo;0;L;;;;;N;;;;; +1B052;HENTAIGANA LETTER SE-1;Lo;0;L;;;;;N;;;;; +1B053;HENTAIGANA LETTER SE-2;Lo;0;L;;;;;N;;;;; +1B054;HENTAIGANA LETTER SE-3;Lo;0;L;;;;;N;;;;; +1B055;HENTAIGANA LETTER SE-4;Lo;0;L;;;;;N;;;;; +1B056;HENTAIGANA LETTER SE-5;Lo;0;L;;;;;N;;;;; +1B057;HENTAIGANA LETTER SO-1;Lo;0;L;;;;;N;;;;; +1B058;HENTAIGANA LETTER SO-2;Lo;0;L;;;;;N;;;;; +1B059;HENTAIGANA LETTER SO-3;Lo;0;L;;;;;N;;;;; +1B05A;HENTAIGANA LETTER SO-4;Lo;0;L;;;;;N;;;;; +1B05B;HENTAIGANA LETTER SO-5;Lo;0;L;;;;;N;;;;; +1B05C;HENTAIGANA LETTER SO-6;Lo;0;L;;;;;N;;;;; +1B05D;HENTAIGANA LETTER SO-7;Lo;0;L;;;;;N;;;;; +1B05E;HENTAIGANA LETTER TA-1;Lo;0;L;;;;;N;;;;; +1B05F;HENTAIGANA LETTER TA-2;Lo;0;L;;;;;N;;;;; +1B060;HENTAIGANA LETTER TA-3;Lo;0;L;;;;;N;;;;; +1B061;HENTAIGANA LETTER TA-4;Lo;0;L;;;;;N;;;;; +1B062;HENTAIGANA LETTER TI-1;Lo;0;L;;;;;N;;;;; +1B063;HENTAIGANA LETTER TI-2;Lo;0;L;;;;;N;;;;; +1B064;HENTAIGANA LETTER TI-3;Lo;0;L;;;;;N;;;;; +1B065;HENTAIGANA LETTER TI-4;Lo;0;L;;;;;N;;;;; +1B066;HENTAIGANA LETTER TI-5;Lo;0;L;;;;;N;;;;; +1B067;HENTAIGANA LETTER TI-6;Lo;0;L;;;;;N;;;;; +1B068;HENTAIGANA LETTER TI-7;Lo;0;L;;;;;N;;;;; +1B069;HENTAIGANA LETTER TU-1;Lo;0;L;;;;;N;;;;; +1B06A;HENTAIGANA LETTER TU-2;Lo;0;L;;;;;N;;;;; +1B06B;HENTAIGANA LETTER TU-3;Lo;0;L;;;;;N;;;;; +1B06C;HENTAIGANA LETTER TU-4;Lo;0;L;;;;;N;;;;; +1B06D;HENTAIGANA LETTER TU-TO;Lo;0;L;;;;;N;;;;; +1B06E;HENTAIGANA LETTER TE-1;Lo;0;L;;;;;N;;;;; +1B06F;HENTAIGANA LETTER TE-2;Lo;0;L;;;;;N;;;;; +1B070;HENTAIGANA LETTER TE-3;Lo;0;L;;;;;N;;;;; +1B071;HENTAIGANA LETTER TE-4;Lo;0;L;;;;;N;;;;; +1B072;HENTAIGANA LETTER TE-5;Lo;0;L;;;;;N;;;;; +1B073;HENTAIGANA LETTER TE-6;Lo;0;L;;;;;N;;;;; +1B074;HENTAIGANA LETTER TE-7;Lo;0;L;;;;;N;;;;; +1B075;HENTAIGANA LETTER TE-8;Lo;0;L;;;;;N;;;;; +1B076;HENTAIGANA LETTER TE-9;Lo;0;L;;;;;N;;;;; +1B077;HENTAIGANA LETTER TO-1;Lo;0;L;;;;;N;;;;; +1B078;HENTAIGANA LETTER TO-2;Lo;0;L;;;;;N;;;;; +1B079;HENTAIGANA LETTER TO-3;Lo;0;L;;;;;N;;;;; +1B07A;HENTAIGANA LETTER TO-4;Lo;0;L;;;;;N;;;;; +1B07B;HENTAIGANA LETTER TO-5;Lo;0;L;;;;;N;;;;; +1B07C;HENTAIGANA LETTER TO-6;Lo;0;L;;;;;N;;;;; +1B07D;HENTAIGANA LETTER TO-RA;Lo;0;L;;;;;N;;;;; +1B07E;HENTAIGANA LETTER NA-1;Lo;0;L;;;;;N;;;;; +1B07F;HENTAIGANA LETTER NA-2;Lo;0;L;;;;;N;;;;; +1B080;HENTAIGANA LETTER NA-3;Lo;0;L;;;;;N;;;;; +1B081;HENTAIGANA LETTER NA-4;Lo;0;L;;;;;N;;;;; +1B082;HENTAIGANA LETTER NA-5;Lo;0;L;;;;;N;;;;; +1B083;HENTAIGANA LETTER NA-6;Lo;0;L;;;;;N;;;;; +1B084;HENTAIGANA LETTER NA-7;Lo;0;L;;;;;N;;;;; +1B085;HENTAIGANA LETTER NA-8;Lo;0;L;;;;;N;;;;; +1B086;HENTAIGANA LETTER NA-9;Lo;0;L;;;;;N;;;;; +1B087;HENTAIGANA LETTER NI-1;Lo;0;L;;;;;N;;;;; +1B088;HENTAIGANA LETTER NI-2;Lo;0;L;;;;;N;;;;; +1B089;HENTAIGANA LETTER NI-3;Lo;0;L;;;;;N;;;;; +1B08A;HENTAIGANA LETTER NI-4;Lo;0;L;;;;;N;;;;; +1B08B;HENTAIGANA LETTER NI-5;Lo;0;L;;;;;N;;;;; +1B08C;HENTAIGANA LETTER NI-6;Lo;0;L;;;;;N;;;;; +1B08D;HENTAIGANA LETTER NI-7;Lo;0;L;;;;;N;;;;; +1B08E;HENTAIGANA LETTER NI-TE;Lo;0;L;;;;;N;;;;; +1B08F;HENTAIGANA LETTER NU-1;Lo;0;L;;;;;N;;;;; +1B090;HENTAIGANA LETTER NU-2;Lo;0;L;;;;;N;;;;; +1B091;HENTAIGANA LETTER NU-3;Lo;0;L;;;;;N;;;;; +1B092;HENTAIGANA LETTER NE-1;Lo;0;L;;;;;N;;;;; +1B093;HENTAIGANA LETTER NE-2;Lo;0;L;;;;;N;;;;; +1B094;HENTAIGANA LETTER NE-3;Lo;0;L;;;;;N;;;;; +1B095;HENTAIGANA LETTER NE-4;Lo;0;L;;;;;N;;;;; +1B096;HENTAIGANA LETTER NE-5;Lo;0;L;;;;;N;;;;; +1B097;HENTAIGANA LETTER NE-6;Lo;0;L;;;;;N;;;;; +1B098;HENTAIGANA LETTER NE-KO;Lo;0;L;;;;;N;;;;; +1B099;HENTAIGANA LETTER NO-1;Lo;0;L;;;;;N;;;;; +1B09A;HENTAIGANA LETTER NO-2;Lo;0;L;;;;;N;;;;; +1B09B;HENTAIGANA LETTER NO-3;Lo;0;L;;;;;N;;;;; +1B09C;HENTAIGANA LETTER NO-4;Lo;0;L;;;;;N;;;;; +1B09D;HENTAIGANA LETTER NO-5;Lo;0;L;;;;;N;;;;; +1B09E;HENTAIGANA LETTER HA-1;Lo;0;L;;;;;N;;;;; +1B09F;HENTAIGANA LETTER HA-2;Lo;0;L;;;;;N;;;;; +1B0A0;HENTAIGANA LETTER HA-3;Lo;0;L;;;;;N;;;;; +1B0A1;HENTAIGANA LETTER HA-4;Lo;0;L;;;;;N;;;;; +1B0A2;HENTAIGANA LETTER HA-5;Lo;0;L;;;;;N;;;;; +1B0A3;HENTAIGANA LETTER HA-6;Lo;0;L;;;;;N;;;;; +1B0A4;HENTAIGANA LETTER HA-7;Lo;0;L;;;;;N;;;;; +1B0A5;HENTAIGANA LETTER HA-8;Lo;0;L;;;;;N;;;;; +1B0A6;HENTAIGANA LETTER HA-9;Lo;0;L;;;;;N;;;;; +1B0A7;HENTAIGANA LETTER HA-10;Lo;0;L;;;;;N;;;;; +1B0A8;HENTAIGANA LETTER HA-11;Lo;0;L;;;;;N;;;;; +1B0A9;HENTAIGANA LETTER HI-1;Lo;0;L;;;;;N;;;;; +1B0AA;HENTAIGANA LETTER HI-2;Lo;0;L;;;;;N;;;;; +1B0AB;HENTAIGANA LETTER HI-3;Lo;0;L;;;;;N;;;;; +1B0AC;HENTAIGANA LETTER HI-4;Lo;0;L;;;;;N;;;;; +1B0AD;HENTAIGANA LETTER HI-5;Lo;0;L;;;;;N;;;;; +1B0AE;HENTAIGANA LETTER HI-6;Lo;0;L;;;;;N;;;;; +1B0AF;HENTAIGANA LETTER HI-7;Lo;0;L;;;;;N;;;;; +1B0B0;HENTAIGANA LETTER HU-1;Lo;0;L;;;;;N;;;;; +1B0B1;HENTAIGANA LETTER HU-2;Lo;0;L;;;;;N;;;;; +1B0B2;HENTAIGANA LETTER HU-3;Lo;0;L;;;;;N;;;;; +1B0B3;HENTAIGANA LETTER HE-1;Lo;0;L;;;;;N;;;;; +1B0B4;HENTAIGANA LETTER HE-2;Lo;0;L;;;;;N;;;;; +1B0B5;HENTAIGANA LETTER HE-3;Lo;0;L;;;;;N;;;;; +1B0B6;HENTAIGANA LETTER HE-4;Lo;0;L;;;;;N;;;;; +1B0B7;HENTAIGANA LETTER HE-5;Lo;0;L;;;;;N;;;;; +1B0B8;HENTAIGANA LETTER HE-6;Lo;0;L;;;;;N;;;;; +1B0B9;HENTAIGANA LETTER HE-7;Lo;0;L;;;;;N;;;;; +1B0BA;HENTAIGANA LETTER HO-1;Lo;0;L;;;;;N;;;;; +1B0BB;HENTAIGANA LETTER HO-2;Lo;0;L;;;;;N;;;;; +1B0BC;HENTAIGANA LETTER HO-3;Lo;0;L;;;;;N;;;;; +1B0BD;HENTAIGANA LETTER HO-4;Lo;0;L;;;;;N;;;;; +1B0BE;HENTAIGANA LETTER HO-5;Lo;0;L;;;;;N;;;;; +1B0BF;HENTAIGANA LETTER HO-6;Lo;0;L;;;;;N;;;;; +1B0C0;HENTAIGANA LETTER HO-7;Lo;0;L;;;;;N;;;;; +1B0C1;HENTAIGANA LETTER HO-8;Lo;0;L;;;;;N;;;;; +1B0C2;HENTAIGANA LETTER MA-1;Lo;0;L;;;;;N;;;;; +1B0C3;HENTAIGANA LETTER MA-2;Lo;0;L;;;;;N;;;;; +1B0C4;HENTAIGANA LETTER MA-3;Lo;0;L;;;;;N;;;;; +1B0C5;HENTAIGANA LETTER MA-4;Lo;0;L;;;;;N;;;;; +1B0C6;HENTAIGANA LETTER MA-5;Lo;0;L;;;;;N;;;;; +1B0C7;HENTAIGANA LETTER MA-6;Lo;0;L;;;;;N;;;;; +1B0C8;HENTAIGANA LETTER MA-7;Lo;0;L;;;;;N;;;;; +1B0C9;HENTAIGANA LETTER MI-1;Lo;0;L;;;;;N;;;;; +1B0CA;HENTAIGANA LETTER MI-2;Lo;0;L;;;;;N;;;;; +1B0CB;HENTAIGANA LETTER MI-3;Lo;0;L;;;;;N;;;;; +1B0CC;HENTAIGANA LETTER MI-4;Lo;0;L;;;;;N;;;;; +1B0CD;HENTAIGANA LETTER MI-5;Lo;0;L;;;;;N;;;;; +1B0CE;HENTAIGANA LETTER MI-6;Lo;0;L;;;;;N;;;;; +1B0CF;HENTAIGANA LETTER MI-7;Lo;0;L;;;;;N;;;;; +1B0D0;HENTAIGANA LETTER MU-1;Lo;0;L;;;;;N;;;;; +1B0D1;HENTAIGANA LETTER MU-2;Lo;0;L;;;;;N;;;;; +1B0D2;HENTAIGANA LETTER MU-3;Lo;0;L;;;;;N;;;;; +1B0D3;HENTAIGANA LETTER MU-4;Lo;0;L;;;;;N;;;;; +1B0D4;HENTAIGANA LETTER ME-1;Lo;0;L;;;;;N;;;;; +1B0D5;HENTAIGANA LETTER ME-2;Lo;0;L;;;;;N;;;;; +1B0D6;HENTAIGANA LETTER ME-MA;Lo;0;L;;;;;N;;;;; +1B0D7;HENTAIGANA LETTER MO-1;Lo;0;L;;;;;N;;;;; +1B0D8;HENTAIGANA LETTER MO-2;Lo;0;L;;;;;N;;;;; +1B0D9;HENTAIGANA LETTER MO-3;Lo;0;L;;;;;N;;;;; +1B0DA;HENTAIGANA LETTER MO-4;Lo;0;L;;;;;N;;;;; +1B0DB;HENTAIGANA LETTER MO-5;Lo;0;L;;;;;N;;;;; +1B0DC;HENTAIGANA LETTER MO-6;Lo;0;L;;;;;N;;;;; +1B0DD;HENTAIGANA LETTER YA-1;Lo;0;L;;;;;N;;;;; +1B0DE;HENTAIGANA LETTER YA-2;Lo;0;L;;;;;N;;;;; +1B0DF;HENTAIGANA LETTER YA-3;Lo;0;L;;;;;N;;;;; +1B0E0;HENTAIGANA LETTER YA-4;Lo;0;L;;;;;N;;;;; +1B0E1;HENTAIGANA LETTER YA-5;Lo;0;L;;;;;N;;;;; +1B0E2;HENTAIGANA LETTER YA-YO;Lo;0;L;;;;;N;;;;; +1B0E3;HENTAIGANA LETTER YU-1;Lo;0;L;;;;;N;;;;; +1B0E4;HENTAIGANA LETTER YU-2;Lo;0;L;;;;;N;;;;; +1B0E5;HENTAIGANA LETTER YU-3;Lo;0;L;;;;;N;;;;; +1B0E6;HENTAIGANA LETTER YU-4;Lo;0;L;;;;;N;;;;; +1B0E7;HENTAIGANA LETTER YO-1;Lo;0;L;;;;;N;;;;; +1B0E8;HENTAIGANA LETTER YO-2;Lo;0;L;;;;;N;;;;; +1B0E9;HENTAIGANA LETTER YO-3;Lo;0;L;;;;;N;;;;; +1B0EA;HENTAIGANA LETTER YO-4;Lo;0;L;;;;;N;;;;; +1B0EB;HENTAIGANA LETTER YO-5;Lo;0;L;;;;;N;;;;; +1B0EC;HENTAIGANA LETTER YO-6;Lo;0;L;;;;;N;;;;; +1B0ED;HENTAIGANA LETTER RA-1;Lo;0;L;;;;;N;;;;; +1B0EE;HENTAIGANA LETTER RA-2;Lo;0;L;;;;;N;;;;; +1B0EF;HENTAIGANA LETTER RA-3;Lo;0;L;;;;;N;;;;; +1B0F0;HENTAIGANA LETTER RA-4;Lo;0;L;;;;;N;;;;; +1B0F1;HENTAIGANA LETTER RI-1;Lo;0;L;;;;;N;;;;; +1B0F2;HENTAIGANA LETTER RI-2;Lo;0;L;;;;;N;;;;; +1B0F3;HENTAIGANA LETTER RI-3;Lo;0;L;;;;;N;;;;; +1B0F4;HENTAIGANA LETTER RI-4;Lo;0;L;;;;;N;;;;; +1B0F5;HENTAIGANA LETTER RI-5;Lo;0;L;;;;;N;;;;; +1B0F6;HENTAIGANA LETTER RI-6;Lo;0;L;;;;;N;;;;; +1B0F7;HENTAIGANA LETTER RI-7;Lo;0;L;;;;;N;;;;; +1B0F8;HENTAIGANA LETTER RU-1;Lo;0;L;;;;;N;;;;; +1B0F9;HENTAIGANA LETTER RU-2;Lo;0;L;;;;;N;;;;; +1B0FA;HENTAIGANA LETTER RU-3;Lo;0;L;;;;;N;;;;; +1B0FB;HENTAIGANA LETTER RU-4;Lo;0;L;;;;;N;;;;; +1B0FC;HENTAIGANA LETTER RU-5;Lo;0;L;;;;;N;;;;; +1B0FD;HENTAIGANA LETTER RU-6;Lo;0;L;;;;;N;;;;; +1B0FE;HENTAIGANA LETTER RE-1;Lo;0;L;;;;;N;;;;; +1B0FF;HENTAIGANA LETTER RE-2;Lo;0;L;;;;;N;;;;; +1B100;HENTAIGANA LETTER RE-3;Lo;0;L;;;;;N;;;;; +1B101;HENTAIGANA LETTER RE-4;Lo;0;L;;;;;N;;;;; +1B102;HENTAIGANA LETTER RO-1;Lo;0;L;;;;;N;;;;; +1B103;HENTAIGANA LETTER RO-2;Lo;0;L;;;;;N;;;;; +1B104;HENTAIGANA LETTER RO-3;Lo;0;L;;;;;N;;;;; +1B105;HENTAIGANA LETTER RO-4;Lo;0;L;;;;;N;;;;; +1B106;HENTAIGANA LETTER RO-5;Lo;0;L;;;;;N;;;;; +1B107;HENTAIGANA LETTER RO-6;Lo;0;L;;;;;N;;;;; +1B108;HENTAIGANA LETTER WA-1;Lo;0;L;;;;;N;;;;; +1B109;HENTAIGANA LETTER WA-2;Lo;0;L;;;;;N;;;;; +1B10A;HENTAIGANA LETTER WA-3;Lo;0;L;;;;;N;;;;; +1B10B;HENTAIGANA LETTER WA-4;Lo;0;L;;;;;N;;;;; +1B10C;HENTAIGANA LETTER WA-5;Lo;0;L;;;;;N;;;;; +1B10D;HENTAIGANA LETTER WI-1;Lo;0;L;;;;;N;;;;; +1B10E;HENTAIGANA LETTER WI-2;Lo;0;L;;;;;N;;;;; +1B10F;HENTAIGANA LETTER WI-3;Lo;0;L;;;;;N;;;;; +1B110;HENTAIGANA LETTER WI-4;Lo;0;L;;;;;N;;;;; +1B111;HENTAIGANA LETTER WI-5;Lo;0;L;;;;;N;;;;; +1B112;HENTAIGANA LETTER WE-1;Lo;0;L;;;;;N;;;;; +1B113;HENTAIGANA LETTER WE-2;Lo;0;L;;;;;N;;;;; +1B114;HENTAIGANA LETTER WE-3;Lo;0;L;;;;;N;;;;; +1B115;HENTAIGANA LETTER WE-4;Lo;0;L;;;;;N;;;;; +1B116;HENTAIGANA LETTER WO-1;Lo;0;L;;;;;N;;;;; +1B117;HENTAIGANA LETTER WO-2;Lo;0;L;;;;;N;;;;; +1B118;HENTAIGANA LETTER WO-3;Lo;0;L;;;;;N;;;;; +1B119;HENTAIGANA LETTER WO-4;Lo;0;L;;;;;N;;;;; +1B11A;HENTAIGANA LETTER WO-5;Lo;0;L;;;;;N;;;;; +1B11B;HENTAIGANA LETTER WO-6;Lo;0;L;;;;;N;;;;; +1B11C;HENTAIGANA LETTER WO-7;Lo;0;L;;;;;N;;;;; +1B11D;HENTAIGANA LETTER N-MU-MO-1;Lo;0;L;;;;;N;;;;; +1B11E;HENTAIGANA LETTER N-MU-MO-2;Lo;0;L;;;;;N;;;;; +1B170;NUSHU CHARACTER-1B170;Lo;0;L;;;;;N;;;;; +1B171;NUSHU CHARACTER-1B171;Lo;0;L;;;;;N;;;;; +1B172;NUSHU CHARACTER-1B172;Lo;0;L;;;;;N;;;;; +1B173;NUSHU CHARACTER-1B173;Lo;0;L;;;;;N;;;;; +1B174;NUSHU CHARACTER-1B174;Lo;0;L;;;;;N;;;;; +1B175;NUSHU CHARACTER-1B175;Lo;0;L;;;;;N;;;;; +1B176;NUSHU CHARACTER-1B176;Lo;0;L;;;;;N;;;;; +1B177;NUSHU CHARACTER-1B177;Lo;0;L;;;;;N;;;;; +1B178;NUSHU CHARACTER-1B178;Lo;0;L;;;;;N;;;;; +1B179;NUSHU CHARACTER-1B179;Lo;0;L;;;;;N;;;;; +1B17A;NUSHU CHARACTER-1B17A;Lo;0;L;;;;;N;;;;; +1B17B;NUSHU CHARACTER-1B17B;Lo;0;L;;;;;N;;;;; +1B17C;NUSHU CHARACTER-1B17C;Lo;0;L;;;;;N;;;;; +1B17D;NUSHU CHARACTER-1B17D;Lo;0;L;;;;;N;;;;; +1B17E;NUSHU CHARACTER-1B17E;Lo;0;L;;;;;N;;;;; +1B17F;NUSHU CHARACTER-1B17F;Lo;0;L;;;;;N;;;;; +1B180;NUSHU CHARACTER-1B180;Lo;0;L;;;;;N;;;;; +1B181;NUSHU CHARACTER-1B181;Lo;0;L;;;;;N;;;;; +1B182;NUSHU CHARACTER-1B182;Lo;0;L;;;;;N;;;;; +1B183;NUSHU CHARACTER-1B183;Lo;0;L;;;;;N;;;;; +1B184;NUSHU CHARACTER-1B184;Lo;0;L;;;;;N;;;;; +1B185;NUSHU CHARACTER-1B185;Lo;0;L;;;;;N;;;;; +1B186;NUSHU CHARACTER-1B186;Lo;0;L;;;;;N;;;;; +1B187;NUSHU CHARACTER-1B187;Lo;0;L;;;;;N;;;;; +1B188;NUSHU CHARACTER-1B188;Lo;0;L;;;;;N;;;;; +1B189;NUSHU CHARACTER-1B189;Lo;0;L;;;;;N;;;;; +1B18A;NUSHU CHARACTER-1B18A;Lo;0;L;;;;;N;;;;; +1B18B;NUSHU CHARACTER-1B18B;Lo;0;L;;;;;N;;;;; +1B18C;NUSHU CHARACTER-1B18C;Lo;0;L;;;;;N;;;;; +1B18D;NUSHU CHARACTER-1B18D;Lo;0;L;;;;;N;;;;; +1B18E;NUSHU CHARACTER-1B18E;Lo;0;L;;;;;N;;;;; +1B18F;NUSHU CHARACTER-1B18F;Lo;0;L;;;;;N;;;;; +1B190;NUSHU CHARACTER-1B190;Lo;0;L;;;;;N;;;;; +1B191;NUSHU CHARACTER-1B191;Lo;0;L;;;;;N;;;;; +1B192;NUSHU CHARACTER-1B192;Lo;0;L;;;;;N;;;;; +1B193;NUSHU CHARACTER-1B193;Lo;0;L;;;;;N;;;;; +1B194;NUSHU CHARACTER-1B194;Lo;0;L;;;;;N;;;;; +1B195;NUSHU CHARACTER-1B195;Lo;0;L;;;;;N;;;;; +1B196;NUSHU CHARACTER-1B196;Lo;0;L;;;;;N;;;;; +1B197;NUSHU CHARACTER-1B197;Lo;0;L;;;;;N;;;;; +1B198;NUSHU CHARACTER-1B198;Lo;0;L;;;;;N;;;;; +1B199;NUSHU CHARACTER-1B199;Lo;0;L;;;;;N;;;;; +1B19A;NUSHU CHARACTER-1B19A;Lo;0;L;;;;;N;;;;; +1B19B;NUSHU CHARACTER-1B19B;Lo;0;L;;;;;N;;;;; +1B19C;NUSHU CHARACTER-1B19C;Lo;0;L;;;;;N;;;;; +1B19D;NUSHU CHARACTER-1B19D;Lo;0;L;;;;;N;;;;; +1B19E;NUSHU CHARACTER-1B19E;Lo;0;L;;;;;N;;;;; +1B19F;NUSHU CHARACTER-1B19F;Lo;0;L;;;;;N;;;;; +1B1A0;NUSHU CHARACTER-1B1A0;Lo;0;L;;;;;N;;;;; +1B1A1;NUSHU CHARACTER-1B1A1;Lo;0;L;;;;;N;;;;; +1B1A2;NUSHU CHARACTER-1B1A2;Lo;0;L;;;;;N;;;;; +1B1A3;NUSHU CHARACTER-1B1A3;Lo;0;L;;;;;N;;;;; +1B1A4;NUSHU CHARACTER-1B1A4;Lo;0;L;;;;;N;;;;; +1B1A5;NUSHU CHARACTER-1B1A5;Lo;0;L;;;;;N;;;;; +1B1A6;NUSHU CHARACTER-1B1A6;Lo;0;L;;;;;N;;;;; +1B1A7;NUSHU CHARACTER-1B1A7;Lo;0;L;;;;;N;;;;; +1B1A8;NUSHU CHARACTER-1B1A8;Lo;0;L;;;;;N;;;;; +1B1A9;NUSHU CHARACTER-1B1A9;Lo;0;L;;;;;N;;;;; +1B1AA;NUSHU CHARACTER-1B1AA;Lo;0;L;;;;;N;;;;; +1B1AB;NUSHU CHARACTER-1B1AB;Lo;0;L;;;;;N;;;;; +1B1AC;NUSHU CHARACTER-1B1AC;Lo;0;L;;;;;N;;;;; +1B1AD;NUSHU CHARACTER-1B1AD;Lo;0;L;;;;;N;;;;; +1B1AE;NUSHU CHARACTER-1B1AE;Lo;0;L;;;;;N;;;;; +1B1AF;NUSHU CHARACTER-1B1AF;Lo;0;L;;;;;N;;;;; +1B1B0;NUSHU CHARACTER-1B1B0;Lo;0;L;;;;;N;;;;; +1B1B1;NUSHU CHARACTER-1B1B1;Lo;0;L;;;;;N;;;;; +1B1B2;NUSHU CHARACTER-1B1B2;Lo;0;L;;;;;N;;;;; +1B1B3;NUSHU CHARACTER-1B1B3;Lo;0;L;;;;;N;;;;; +1B1B4;NUSHU CHARACTER-1B1B4;Lo;0;L;;;;;N;;;;; +1B1B5;NUSHU CHARACTER-1B1B5;Lo;0;L;;;;;N;;;;; +1B1B6;NUSHU CHARACTER-1B1B6;Lo;0;L;;;;;N;;;;; +1B1B7;NUSHU CHARACTER-1B1B7;Lo;0;L;;;;;N;;;;; +1B1B8;NUSHU CHARACTER-1B1B8;Lo;0;L;;;;;N;;;;; +1B1B9;NUSHU CHARACTER-1B1B9;Lo;0;L;;;;;N;;;;; +1B1BA;NUSHU CHARACTER-1B1BA;Lo;0;L;;;;;N;;;;; +1B1BB;NUSHU CHARACTER-1B1BB;Lo;0;L;;;;;N;;;;; +1B1BC;NUSHU CHARACTER-1B1BC;Lo;0;L;;;;;N;;;;; +1B1BD;NUSHU CHARACTER-1B1BD;Lo;0;L;;;;;N;;;;; +1B1BE;NUSHU CHARACTER-1B1BE;Lo;0;L;;;;;N;;;;; +1B1BF;NUSHU CHARACTER-1B1BF;Lo;0;L;;;;;N;;;;; +1B1C0;NUSHU CHARACTER-1B1C0;Lo;0;L;;;;;N;;;;; +1B1C1;NUSHU CHARACTER-1B1C1;Lo;0;L;;;;;N;;;;; +1B1C2;NUSHU CHARACTER-1B1C2;Lo;0;L;;;;;N;;;;; +1B1C3;NUSHU CHARACTER-1B1C3;Lo;0;L;;;;;N;;;;; +1B1C4;NUSHU CHARACTER-1B1C4;Lo;0;L;;;;;N;;;;; +1B1C5;NUSHU CHARACTER-1B1C5;Lo;0;L;;;;;N;;;;; +1B1C6;NUSHU CHARACTER-1B1C6;Lo;0;L;;;;;N;;;;; +1B1C7;NUSHU CHARACTER-1B1C7;Lo;0;L;;;;;N;;;;; +1B1C8;NUSHU CHARACTER-1B1C8;Lo;0;L;;;;;N;;;;; +1B1C9;NUSHU CHARACTER-1B1C9;Lo;0;L;;;;;N;;;;; +1B1CA;NUSHU CHARACTER-1B1CA;Lo;0;L;;;;;N;;;;; +1B1CB;NUSHU CHARACTER-1B1CB;Lo;0;L;;;;;N;;;;; +1B1CC;NUSHU CHARACTER-1B1CC;Lo;0;L;;;;;N;;;;; +1B1CD;NUSHU CHARACTER-1B1CD;Lo;0;L;;;;;N;;;;; +1B1CE;NUSHU CHARACTER-1B1CE;Lo;0;L;;;;;N;;;;; +1B1CF;NUSHU CHARACTER-1B1CF;Lo;0;L;;;;;N;;;;; +1B1D0;NUSHU CHARACTER-1B1D0;Lo;0;L;;;;;N;;;;; +1B1D1;NUSHU CHARACTER-1B1D1;Lo;0;L;;;;;N;;;;; +1B1D2;NUSHU CHARACTER-1B1D2;Lo;0;L;;;;;N;;;;; +1B1D3;NUSHU CHARACTER-1B1D3;Lo;0;L;;;;;N;;;;; +1B1D4;NUSHU CHARACTER-1B1D4;Lo;0;L;;;;;N;;;;; +1B1D5;NUSHU CHARACTER-1B1D5;Lo;0;L;;;;;N;;;;; +1B1D6;NUSHU CHARACTER-1B1D6;Lo;0;L;;;;;N;;;;; +1B1D7;NUSHU CHARACTER-1B1D7;Lo;0;L;;;;;N;;;;; +1B1D8;NUSHU CHARACTER-1B1D8;Lo;0;L;;;;;N;;;;; +1B1D9;NUSHU CHARACTER-1B1D9;Lo;0;L;;;;;N;;;;; +1B1DA;NUSHU CHARACTER-1B1DA;Lo;0;L;;;;;N;;;;; +1B1DB;NUSHU CHARACTER-1B1DB;Lo;0;L;;;;;N;;;;; +1B1DC;NUSHU CHARACTER-1B1DC;Lo;0;L;;;;;N;;;;; +1B1DD;NUSHU CHARACTER-1B1DD;Lo;0;L;;;;;N;;;;; +1B1DE;NUSHU CHARACTER-1B1DE;Lo;0;L;;;;;N;;;;; +1B1DF;NUSHU CHARACTER-1B1DF;Lo;0;L;;;;;N;;;;; +1B1E0;NUSHU CHARACTER-1B1E0;Lo;0;L;;;;;N;;;;; +1B1E1;NUSHU CHARACTER-1B1E1;Lo;0;L;;;;;N;;;;; +1B1E2;NUSHU CHARACTER-1B1E2;Lo;0;L;;;;;N;;;;; +1B1E3;NUSHU CHARACTER-1B1E3;Lo;0;L;;;;;N;;;;; +1B1E4;NUSHU CHARACTER-1B1E4;Lo;0;L;;;;;N;;;;; +1B1E5;NUSHU CHARACTER-1B1E5;Lo;0;L;;;;;N;;;;; +1B1E6;NUSHU CHARACTER-1B1E6;Lo;0;L;;;;;N;;;;; +1B1E7;NUSHU CHARACTER-1B1E7;Lo;0;L;;;;;N;;;;; +1B1E8;NUSHU CHARACTER-1B1E8;Lo;0;L;;;;;N;;;;; +1B1E9;NUSHU CHARACTER-1B1E9;Lo;0;L;;;;;N;;;;; +1B1EA;NUSHU CHARACTER-1B1EA;Lo;0;L;;;;;N;;;;; +1B1EB;NUSHU CHARACTER-1B1EB;Lo;0;L;;;;;N;;;;; +1B1EC;NUSHU CHARACTER-1B1EC;Lo;0;L;;;;;N;;;;; +1B1ED;NUSHU CHARACTER-1B1ED;Lo;0;L;;;;;N;;;;; +1B1EE;NUSHU CHARACTER-1B1EE;Lo;0;L;;;;;N;;;;; +1B1EF;NUSHU CHARACTER-1B1EF;Lo;0;L;;;;;N;;;;; +1B1F0;NUSHU CHARACTER-1B1F0;Lo;0;L;;;;;N;;;;; +1B1F1;NUSHU CHARACTER-1B1F1;Lo;0;L;;;;;N;;;;; +1B1F2;NUSHU CHARACTER-1B1F2;Lo;0;L;;;;;N;;;;; +1B1F3;NUSHU CHARACTER-1B1F3;Lo;0;L;;;;;N;;;;; +1B1F4;NUSHU CHARACTER-1B1F4;Lo;0;L;;;;;N;;;;; +1B1F5;NUSHU CHARACTER-1B1F5;Lo;0;L;;;;;N;;;;; +1B1F6;NUSHU CHARACTER-1B1F6;Lo;0;L;;;;;N;;;;; +1B1F7;NUSHU CHARACTER-1B1F7;Lo;0;L;;;;;N;;;;; +1B1F8;NUSHU CHARACTER-1B1F8;Lo;0;L;;;;;N;;;;; +1B1F9;NUSHU CHARACTER-1B1F9;Lo;0;L;;;;;N;;;;; +1B1FA;NUSHU CHARACTER-1B1FA;Lo;0;L;;;;;N;;;;; +1B1FB;NUSHU CHARACTER-1B1FB;Lo;0;L;;;;;N;;;;; +1B1FC;NUSHU CHARACTER-1B1FC;Lo;0;L;;;;;N;;;;; +1B1FD;NUSHU CHARACTER-1B1FD;Lo;0;L;;;;;N;;;;; +1B1FE;NUSHU CHARACTER-1B1FE;Lo;0;L;;;;;N;;;;; +1B1FF;NUSHU CHARACTER-1B1FF;Lo;0;L;;;;;N;;;;; +1B200;NUSHU CHARACTER-1B200;Lo;0;L;;;;;N;;;;; +1B201;NUSHU CHARACTER-1B201;Lo;0;L;;;;;N;;;;; +1B202;NUSHU CHARACTER-1B202;Lo;0;L;;;;;N;;;;; +1B203;NUSHU CHARACTER-1B203;Lo;0;L;;;;;N;;;;; +1B204;NUSHU CHARACTER-1B204;Lo;0;L;;;;;N;;;;; +1B205;NUSHU CHARACTER-1B205;Lo;0;L;;;;;N;;;;; +1B206;NUSHU CHARACTER-1B206;Lo;0;L;;;;;N;;;;; +1B207;NUSHU CHARACTER-1B207;Lo;0;L;;;;;N;;;;; +1B208;NUSHU CHARACTER-1B208;Lo;0;L;;;;;N;;;;; +1B209;NUSHU CHARACTER-1B209;Lo;0;L;;;;;N;;;;; +1B20A;NUSHU CHARACTER-1B20A;Lo;0;L;;;;;N;;;;; +1B20B;NUSHU CHARACTER-1B20B;Lo;0;L;;;;;N;;;;; +1B20C;NUSHU CHARACTER-1B20C;Lo;0;L;;;;;N;;;;; +1B20D;NUSHU CHARACTER-1B20D;Lo;0;L;;;;;N;;;;; +1B20E;NUSHU CHARACTER-1B20E;Lo;0;L;;;;;N;;;;; +1B20F;NUSHU CHARACTER-1B20F;Lo;0;L;;;;;N;;;;; +1B210;NUSHU CHARACTER-1B210;Lo;0;L;;;;;N;;;;; +1B211;NUSHU CHARACTER-1B211;Lo;0;L;;;;;N;;;;; +1B212;NUSHU CHARACTER-1B212;Lo;0;L;;;;;N;;;;; +1B213;NUSHU CHARACTER-1B213;Lo;0;L;;;;;N;;;;; +1B214;NUSHU CHARACTER-1B214;Lo;0;L;;;;;N;;;;; +1B215;NUSHU CHARACTER-1B215;Lo;0;L;;;;;N;;;;; +1B216;NUSHU CHARACTER-1B216;Lo;0;L;;;;;N;;;;; +1B217;NUSHU CHARACTER-1B217;Lo;0;L;;;;;N;;;;; +1B218;NUSHU CHARACTER-1B218;Lo;0;L;;;;;N;;;;; +1B219;NUSHU CHARACTER-1B219;Lo;0;L;;;;;N;;;;; +1B21A;NUSHU CHARACTER-1B21A;Lo;0;L;;;;;N;;;;; +1B21B;NUSHU CHARACTER-1B21B;Lo;0;L;;;;;N;;;;; +1B21C;NUSHU CHARACTER-1B21C;Lo;0;L;;;;;N;;;;; +1B21D;NUSHU CHARACTER-1B21D;Lo;0;L;;;;;N;;;;; +1B21E;NUSHU CHARACTER-1B21E;Lo;0;L;;;;;N;;;;; +1B21F;NUSHU CHARACTER-1B21F;Lo;0;L;;;;;N;;;;; +1B220;NUSHU CHARACTER-1B220;Lo;0;L;;;;;N;;;;; +1B221;NUSHU CHARACTER-1B221;Lo;0;L;;;;;N;;;;; +1B222;NUSHU CHARACTER-1B222;Lo;0;L;;;;;N;;;;; +1B223;NUSHU CHARACTER-1B223;Lo;0;L;;;;;N;;;;; +1B224;NUSHU CHARACTER-1B224;Lo;0;L;;;;;N;;;;; +1B225;NUSHU CHARACTER-1B225;Lo;0;L;;;;;N;;;;; +1B226;NUSHU CHARACTER-1B226;Lo;0;L;;;;;N;;;;; +1B227;NUSHU CHARACTER-1B227;Lo;0;L;;;;;N;;;;; +1B228;NUSHU CHARACTER-1B228;Lo;0;L;;;;;N;;;;; +1B229;NUSHU CHARACTER-1B229;Lo;0;L;;;;;N;;;;; +1B22A;NUSHU CHARACTER-1B22A;Lo;0;L;;;;;N;;;;; +1B22B;NUSHU CHARACTER-1B22B;Lo;0;L;;;;;N;;;;; +1B22C;NUSHU CHARACTER-1B22C;Lo;0;L;;;;;N;;;;; +1B22D;NUSHU CHARACTER-1B22D;Lo;0;L;;;;;N;;;;; +1B22E;NUSHU CHARACTER-1B22E;Lo;0;L;;;;;N;;;;; +1B22F;NUSHU CHARACTER-1B22F;Lo;0;L;;;;;N;;;;; +1B230;NUSHU CHARACTER-1B230;Lo;0;L;;;;;N;;;;; +1B231;NUSHU CHARACTER-1B231;Lo;0;L;;;;;N;;;;; +1B232;NUSHU CHARACTER-1B232;Lo;0;L;;;;;N;;;;; +1B233;NUSHU CHARACTER-1B233;Lo;0;L;;;;;N;;;;; +1B234;NUSHU CHARACTER-1B234;Lo;0;L;;;;;N;;;;; +1B235;NUSHU CHARACTER-1B235;Lo;0;L;;;;;N;;;;; +1B236;NUSHU CHARACTER-1B236;Lo;0;L;;;;;N;;;;; +1B237;NUSHU CHARACTER-1B237;Lo;0;L;;;;;N;;;;; +1B238;NUSHU CHARACTER-1B238;Lo;0;L;;;;;N;;;;; +1B239;NUSHU CHARACTER-1B239;Lo;0;L;;;;;N;;;;; +1B23A;NUSHU CHARACTER-1B23A;Lo;0;L;;;;;N;;;;; +1B23B;NUSHU CHARACTER-1B23B;Lo;0;L;;;;;N;;;;; +1B23C;NUSHU CHARACTER-1B23C;Lo;0;L;;;;;N;;;;; +1B23D;NUSHU CHARACTER-1B23D;Lo;0;L;;;;;N;;;;; +1B23E;NUSHU CHARACTER-1B23E;Lo;0;L;;;;;N;;;;; +1B23F;NUSHU CHARACTER-1B23F;Lo;0;L;;;;;N;;;;; +1B240;NUSHU CHARACTER-1B240;Lo;0;L;;;;;N;;;;; +1B241;NUSHU CHARACTER-1B241;Lo;0;L;;;;;N;;;;; +1B242;NUSHU CHARACTER-1B242;Lo;0;L;;;;;N;;;;; +1B243;NUSHU CHARACTER-1B243;Lo;0;L;;;;;N;;;;; +1B244;NUSHU CHARACTER-1B244;Lo;0;L;;;;;N;;;;; +1B245;NUSHU CHARACTER-1B245;Lo;0;L;;;;;N;;;;; +1B246;NUSHU CHARACTER-1B246;Lo;0;L;;;;;N;;;;; +1B247;NUSHU CHARACTER-1B247;Lo;0;L;;;;;N;;;;; +1B248;NUSHU CHARACTER-1B248;Lo;0;L;;;;;N;;;;; +1B249;NUSHU CHARACTER-1B249;Lo;0;L;;;;;N;;;;; +1B24A;NUSHU CHARACTER-1B24A;Lo;0;L;;;;;N;;;;; +1B24B;NUSHU CHARACTER-1B24B;Lo;0;L;;;;;N;;;;; +1B24C;NUSHU CHARACTER-1B24C;Lo;0;L;;;;;N;;;;; +1B24D;NUSHU CHARACTER-1B24D;Lo;0;L;;;;;N;;;;; +1B24E;NUSHU CHARACTER-1B24E;Lo;0;L;;;;;N;;;;; +1B24F;NUSHU CHARACTER-1B24F;Lo;0;L;;;;;N;;;;; +1B250;NUSHU CHARACTER-1B250;Lo;0;L;;;;;N;;;;; +1B251;NUSHU CHARACTER-1B251;Lo;0;L;;;;;N;;;;; +1B252;NUSHU CHARACTER-1B252;Lo;0;L;;;;;N;;;;; +1B253;NUSHU CHARACTER-1B253;Lo;0;L;;;;;N;;;;; +1B254;NUSHU CHARACTER-1B254;Lo;0;L;;;;;N;;;;; +1B255;NUSHU CHARACTER-1B255;Lo;0;L;;;;;N;;;;; +1B256;NUSHU CHARACTER-1B256;Lo;0;L;;;;;N;;;;; +1B257;NUSHU CHARACTER-1B257;Lo;0;L;;;;;N;;;;; +1B258;NUSHU CHARACTER-1B258;Lo;0;L;;;;;N;;;;; +1B259;NUSHU CHARACTER-1B259;Lo;0;L;;;;;N;;;;; +1B25A;NUSHU CHARACTER-1B25A;Lo;0;L;;;;;N;;;;; +1B25B;NUSHU CHARACTER-1B25B;Lo;0;L;;;;;N;;;;; +1B25C;NUSHU CHARACTER-1B25C;Lo;0;L;;;;;N;;;;; +1B25D;NUSHU CHARACTER-1B25D;Lo;0;L;;;;;N;;;;; +1B25E;NUSHU CHARACTER-1B25E;Lo;0;L;;;;;N;;;;; +1B25F;NUSHU CHARACTER-1B25F;Lo;0;L;;;;;N;;;;; +1B260;NUSHU CHARACTER-1B260;Lo;0;L;;;;;N;;;;; +1B261;NUSHU CHARACTER-1B261;Lo;0;L;;;;;N;;;;; +1B262;NUSHU CHARACTER-1B262;Lo;0;L;;;;;N;;;;; +1B263;NUSHU CHARACTER-1B263;Lo;0;L;;;;;N;;;;; +1B264;NUSHU CHARACTER-1B264;Lo;0;L;;;;;N;;;;; +1B265;NUSHU CHARACTER-1B265;Lo;0;L;;;;;N;;;;; +1B266;NUSHU CHARACTER-1B266;Lo;0;L;;;;;N;;;;; +1B267;NUSHU CHARACTER-1B267;Lo;0;L;;;;;N;;;;; +1B268;NUSHU CHARACTER-1B268;Lo;0;L;;;;;N;;;;; +1B269;NUSHU CHARACTER-1B269;Lo;0;L;;;;;N;;;;; +1B26A;NUSHU CHARACTER-1B26A;Lo;0;L;;;;;N;;;;; +1B26B;NUSHU CHARACTER-1B26B;Lo;0;L;;;;;N;;;;; +1B26C;NUSHU CHARACTER-1B26C;Lo;0;L;;;;;N;;;;; +1B26D;NUSHU CHARACTER-1B26D;Lo;0;L;;;;;N;;;;; +1B26E;NUSHU CHARACTER-1B26E;Lo;0;L;;;;;N;;;;; +1B26F;NUSHU CHARACTER-1B26F;Lo;0;L;;;;;N;;;;; +1B270;NUSHU CHARACTER-1B270;Lo;0;L;;;;;N;;;;; +1B271;NUSHU CHARACTER-1B271;Lo;0;L;;;;;N;;;;; +1B272;NUSHU CHARACTER-1B272;Lo;0;L;;;;;N;;;;; +1B273;NUSHU CHARACTER-1B273;Lo;0;L;;;;;N;;;;; +1B274;NUSHU CHARACTER-1B274;Lo;0;L;;;;;N;;;;; +1B275;NUSHU CHARACTER-1B275;Lo;0;L;;;;;N;;;;; +1B276;NUSHU CHARACTER-1B276;Lo;0;L;;;;;N;;;;; +1B277;NUSHU CHARACTER-1B277;Lo;0;L;;;;;N;;;;; +1B278;NUSHU CHARACTER-1B278;Lo;0;L;;;;;N;;;;; +1B279;NUSHU CHARACTER-1B279;Lo;0;L;;;;;N;;;;; +1B27A;NUSHU CHARACTER-1B27A;Lo;0;L;;;;;N;;;;; +1B27B;NUSHU CHARACTER-1B27B;Lo;0;L;;;;;N;;;;; +1B27C;NUSHU CHARACTER-1B27C;Lo;0;L;;;;;N;;;;; +1B27D;NUSHU CHARACTER-1B27D;Lo;0;L;;;;;N;;;;; +1B27E;NUSHU CHARACTER-1B27E;Lo;0;L;;;;;N;;;;; +1B27F;NUSHU CHARACTER-1B27F;Lo;0;L;;;;;N;;;;; +1B280;NUSHU CHARACTER-1B280;Lo;0;L;;;;;N;;;;; +1B281;NUSHU CHARACTER-1B281;Lo;0;L;;;;;N;;;;; +1B282;NUSHU CHARACTER-1B282;Lo;0;L;;;;;N;;;;; +1B283;NUSHU CHARACTER-1B283;Lo;0;L;;;;;N;;;;; +1B284;NUSHU CHARACTER-1B284;Lo;0;L;;;;;N;;;;; +1B285;NUSHU CHARACTER-1B285;Lo;0;L;;;;;N;;;;; +1B286;NUSHU CHARACTER-1B286;Lo;0;L;;;;;N;;;;; +1B287;NUSHU CHARACTER-1B287;Lo;0;L;;;;;N;;;;; +1B288;NUSHU CHARACTER-1B288;Lo;0;L;;;;;N;;;;; +1B289;NUSHU CHARACTER-1B289;Lo;0;L;;;;;N;;;;; +1B28A;NUSHU CHARACTER-1B28A;Lo;0;L;;;;;N;;;;; +1B28B;NUSHU CHARACTER-1B28B;Lo;0;L;;;;;N;;;;; +1B28C;NUSHU CHARACTER-1B28C;Lo;0;L;;;;;N;;;;; +1B28D;NUSHU CHARACTER-1B28D;Lo;0;L;;;;;N;;;;; +1B28E;NUSHU CHARACTER-1B28E;Lo;0;L;;;;;N;;;;; +1B28F;NUSHU CHARACTER-1B28F;Lo;0;L;;;;;N;;;;; +1B290;NUSHU CHARACTER-1B290;Lo;0;L;;;;;N;;;;; +1B291;NUSHU CHARACTER-1B291;Lo;0;L;;;;;N;;;;; +1B292;NUSHU CHARACTER-1B292;Lo;0;L;;;;;N;;;;; +1B293;NUSHU CHARACTER-1B293;Lo;0;L;;;;;N;;;;; +1B294;NUSHU CHARACTER-1B294;Lo;0;L;;;;;N;;;;; +1B295;NUSHU CHARACTER-1B295;Lo;0;L;;;;;N;;;;; +1B296;NUSHU CHARACTER-1B296;Lo;0;L;;;;;N;;;;; +1B297;NUSHU CHARACTER-1B297;Lo;0;L;;;;;N;;;;; +1B298;NUSHU CHARACTER-1B298;Lo;0;L;;;;;N;;;;; +1B299;NUSHU CHARACTER-1B299;Lo;0;L;;;;;N;;;;; +1B29A;NUSHU CHARACTER-1B29A;Lo;0;L;;;;;N;;;;; +1B29B;NUSHU CHARACTER-1B29B;Lo;0;L;;;;;N;;;;; +1B29C;NUSHU CHARACTER-1B29C;Lo;0;L;;;;;N;;;;; +1B29D;NUSHU CHARACTER-1B29D;Lo;0;L;;;;;N;;;;; +1B29E;NUSHU CHARACTER-1B29E;Lo;0;L;;;;;N;;;;; +1B29F;NUSHU CHARACTER-1B29F;Lo;0;L;;;;;N;;;;; +1B2A0;NUSHU CHARACTER-1B2A0;Lo;0;L;;;;;N;;;;; +1B2A1;NUSHU CHARACTER-1B2A1;Lo;0;L;;;;;N;;;;; +1B2A2;NUSHU CHARACTER-1B2A2;Lo;0;L;;;;;N;;;;; +1B2A3;NUSHU CHARACTER-1B2A3;Lo;0;L;;;;;N;;;;; +1B2A4;NUSHU CHARACTER-1B2A4;Lo;0;L;;;;;N;;;;; +1B2A5;NUSHU CHARACTER-1B2A5;Lo;0;L;;;;;N;;;;; +1B2A6;NUSHU CHARACTER-1B2A6;Lo;0;L;;;;;N;;;;; +1B2A7;NUSHU CHARACTER-1B2A7;Lo;0;L;;;;;N;;;;; +1B2A8;NUSHU CHARACTER-1B2A8;Lo;0;L;;;;;N;;;;; +1B2A9;NUSHU CHARACTER-1B2A9;Lo;0;L;;;;;N;;;;; +1B2AA;NUSHU CHARACTER-1B2AA;Lo;0;L;;;;;N;;;;; +1B2AB;NUSHU CHARACTER-1B2AB;Lo;0;L;;;;;N;;;;; +1B2AC;NUSHU CHARACTER-1B2AC;Lo;0;L;;;;;N;;;;; +1B2AD;NUSHU CHARACTER-1B2AD;Lo;0;L;;;;;N;;;;; +1B2AE;NUSHU CHARACTER-1B2AE;Lo;0;L;;;;;N;;;;; +1B2AF;NUSHU CHARACTER-1B2AF;Lo;0;L;;;;;N;;;;; +1B2B0;NUSHU CHARACTER-1B2B0;Lo;0;L;;;;;N;;;;; +1B2B1;NUSHU CHARACTER-1B2B1;Lo;0;L;;;;;N;;;;; +1B2B2;NUSHU CHARACTER-1B2B2;Lo;0;L;;;;;N;;;;; +1B2B3;NUSHU CHARACTER-1B2B3;Lo;0;L;;;;;N;;;;; +1B2B4;NUSHU CHARACTER-1B2B4;Lo;0;L;;;;;N;;;;; +1B2B5;NUSHU CHARACTER-1B2B5;Lo;0;L;;;;;N;;;;; +1B2B6;NUSHU CHARACTER-1B2B6;Lo;0;L;;;;;N;;;;; +1B2B7;NUSHU CHARACTER-1B2B7;Lo;0;L;;;;;N;;;;; +1B2B8;NUSHU CHARACTER-1B2B8;Lo;0;L;;;;;N;;;;; +1B2B9;NUSHU CHARACTER-1B2B9;Lo;0;L;;;;;N;;;;; +1B2BA;NUSHU CHARACTER-1B2BA;Lo;0;L;;;;;N;;;;; +1B2BB;NUSHU CHARACTER-1B2BB;Lo;0;L;;;;;N;;;;; +1B2BC;NUSHU CHARACTER-1B2BC;Lo;0;L;;;;;N;;;;; +1B2BD;NUSHU CHARACTER-1B2BD;Lo;0;L;;;;;N;;;;; +1B2BE;NUSHU CHARACTER-1B2BE;Lo;0;L;;;;;N;;;;; +1B2BF;NUSHU CHARACTER-1B2BF;Lo;0;L;;;;;N;;;;; +1B2C0;NUSHU CHARACTER-1B2C0;Lo;0;L;;;;;N;;;;; +1B2C1;NUSHU CHARACTER-1B2C1;Lo;0;L;;;;;N;;;;; +1B2C2;NUSHU CHARACTER-1B2C2;Lo;0;L;;;;;N;;;;; +1B2C3;NUSHU CHARACTER-1B2C3;Lo;0;L;;;;;N;;;;; +1B2C4;NUSHU CHARACTER-1B2C4;Lo;0;L;;;;;N;;;;; +1B2C5;NUSHU CHARACTER-1B2C5;Lo;0;L;;;;;N;;;;; +1B2C6;NUSHU CHARACTER-1B2C6;Lo;0;L;;;;;N;;;;; +1B2C7;NUSHU CHARACTER-1B2C7;Lo;0;L;;;;;N;;;;; +1B2C8;NUSHU CHARACTER-1B2C8;Lo;0;L;;;;;N;;;;; +1B2C9;NUSHU CHARACTER-1B2C9;Lo;0;L;;;;;N;;;;; +1B2CA;NUSHU CHARACTER-1B2CA;Lo;0;L;;;;;N;;;;; +1B2CB;NUSHU CHARACTER-1B2CB;Lo;0;L;;;;;N;;;;; +1B2CC;NUSHU CHARACTER-1B2CC;Lo;0;L;;;;;N;;;;; +1B2CD;NUSHU CHARACTER-1B2CD;Lo;0;L;;;;;N;;;;; +1B2CE;NUSHU CHARACTER-1B2CE;Lo;0;L;;;;;N;;;;; +1B2CF;NUSHU CHARACTER-1B2CF;Lo;0;L;;;;;N;;;;; +1B2D0;NUSHU CHARACTER-1B2D0;Lo;0;L;;;;;N;;;;; +1B2D1;NUSHU CHARACTER-1B2D1;Lo;0;L;;;;;N;;;;; +1B2D2;NUSHU CHARACTER-1B2D2;Lo;0;L;;;;;N;;;;; +1B2D3;NUSHU CHARACTER-1B2D3;Lo;0;L;;;;;N;;;;; +1B2D4;NUSHU CHARACTER-1B2D4;Lo;0;L;;;;;N;;;;; +1B2D5;NUSHU CHARACTER-1B2D5;Lo;0;L;;;;;N;;;;; +1B2D6;NUSHU CHARACTER-1B2D6;Lo;0;L;;;;;N;;;;; +1B2D7;NUSHU CHARACTER-1B2D7;Lo;0;L;;;;;N;;;;; +1B2D8;NUSHU CHARACTER-1B2D8;Lo;0;L;;;;;N;;;;; +1B2D9;NUSHU CHARACTER-1B2D9;Lo;0;L;;;;;N;;;;; +1B2DA;NUSHU CHARACTER-1B2DA;Lo;0;L;;;;;N;;;;; +1B2DB;NUSHU CHARACTER-1B2DB;Lo;0;L;;;;;N;;;;; +1B2DC;NUSHU CHARACTER-1B2DC;Lo;0;L;;;;;N;;;;; +1B2DD;NUSHU CHARACTER-1B2DD;Lo;0;L;;;;;N;;;;; +1B2DE;NUSHU CHARACTER-1B2DE;Lo;0;L;;;;;N;;;;; +1B2DF;NUSHU CHARACTER-1B2DF;Lo;0;L;;;;;N;;;;; +1B2E0;NUSHU CHARACTER-1B2E0;Lo;0;L;;;;;N;;;;; +1B2E1;NUSHU CHARACTER-1B2E1;Lo;0;L;;;;;N;;;;; +1B2E2;NUSHU CHARACTER-1B2E2;Lo;0;L;;;;;N;;;;; +1B2E3;NUSHU CHARACTER-1B2E3;Lo;0;L;;;;;N;;;;; +1B2E4;NUSHU CHARACTER-1B2E4;Lo;0;L;;;;;N;;;;; +1B2E5;NUSHU CHARACTER-1B2E5;Lo;0;L;;;;;N;;;;; +1B2E6;NUSHU CHARACTER-1B2E6;Lo;0;L;;;;;N;;;;; +1B2E7;NUSHU CHARACTER-1B2E7;Lo;0;L;;;;;N;;;;; +1B2E8;NUSHU CHARACTER-1B2E8;Lo;0;L;;;;;N;;;;; +1B2E9;NUSHU CHARACTER-1B2E9;Lo;0;L;;;;;N;;;;; +1B2EA;NUSHU CHARACTER-1B2EA;Lo;0;L;;;;;N;;;;; +1B2EB;NUSHU CHARACTER-1B2EB;Lo;0;L;;;;;N;;;;; +1B2EC;NUSHU CHARACTER-1B2EC;Lo;0;L;;;;;N;;;;; +1B2ED;NUSHU CHARACTER-1B2ED;Lo;0;L;;;;;N;;;;; +1B2EE;NUSHU CHARACTER-1B2EE;Lo;0;L;;;;;N;;;;; +1B2EF;NUSHU CHARACTER-1B2EF;Lo;0;L;;;;;N;;;;; +1B2F0;NUSHU CHARACTER-1B2F0;Lo;0;L;;;;;N;;;;; +1B2F1;NUSHU CHARACTER-1B2F1;Lo;0;L;;;;;N;;;;; +1B2F2;NUSHU CHARACTER-1B2F2;Lo;0;L;;;;;N;;;;; +1B2F3;NUSHU CHARACTER-1B2F3;Lo;0;L;;;;;N;;;;; +1B2F4;NUSHU CHARACTER-1B2F4;Lo;0;L;;;;;N;;;;; +1B2F5;NUSHU CHARACTER-1B2F5;Lo;0;L;;;;;N;;;;; +1B2F6;NUSHU CHARACTER-1B2F6;Lo;0;L;;;;;N;;;;; +1B2F7;NUSHU CHARACTER-1B2F7;Lo;0;L;;;;;N;;;;; +1B2F8;NUSHU CHARACTER-1B2F8;Lo;0;L;;;;;N;;;;; +1B2F9;NUSHU CHARACTER-1B2F9;Lo;0;L;;;;;N;;;;; +1B2FA;NUSHU CHARACTER-1B2FA;Lo;0;L;;;;;N;;;;; +1B2FB;NUSHU CHARACTER-1B2FB;Lo;0;L;;;;;N;;;;; 1BC00;DUPLOYAN LETTER H;Lo;0;L;;;;;N;;;;; 1BC01;DUPLOYAN LETTER X;Lo;0;L;;;;;N;;;;; 1BC02;DUPLOYAN LETTER P;Lo;0;L;;;;;N;;;;; @@ -28269,6 +29217,12 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 1F248;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-6557;So;0;L;<compat> 3014 6557 3015;;;;N;;;;; 1F250;CIRCLED IDEOGRAPH ADVANTAGE;So;0;L;<circle> 5F97;;;;N;;;;; 1F251;CIRCLED IDEOGRAPH ACCEPT;So;0;L;<circle> 53EF;;;;N;;;;; +1F260;ROUNDED SYMBOL FOR FU;So;0;ON;;;;;N;;;;; +1F261;ROUNDED SYMBOL FOR LU;So;0;ON;;;;;N;;;;; +1F262;ROUNDED SYMBOL FOR SHOU;So;0;ON;;;;;N;;;;; +1F263;ROUNDED SYMBOL FOR XI;So;0;ON;;;;;N;;;;; +1F264;ROUNDED SYMBOL FOR SHUANGXI;So;0;ON;;;;;N;;;;; +1F265;ROUNDED SYMBOL FOR CAI;So;0;ON;;;;;N;;;;; 1F300;CYCLONE;So;0;ON;;;;;N;;;;; 1F301;FOGGY;So;0;ON;;;;;N;;;;; 1F302;CLOSED UMBRELLA;So;0;ON;;;;;N;;;;; @@ -29248,6 +30202,8 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 1F6D0;PLACE OF WORSHIP;So;0;ON;;;;;N;;;;; 1F6D1;OCTAGONAL SIGN;So;0;ON;;;;;N;;;;; 1F6D2;SHOPPING TROLLEY;So;0;ON;;;;;N;;;;; +1F6D3;STUPA;So;0;ON;;;;;N;;;;; +1F6D4;PAGODA;So;0;ON;;;;;N;;;;; 1F6E0;HAMMER AND WRENCH;So;0;ON;;;;;N;;;;; 1F6E1;SHIELD;So;0;ON;;;;;N;;;;; 1F6E2;OIL DRUM;So;0;ON;;;;;N;;;;; @@ -29268,6 +30224,8 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 1F6F4;SCOOTER;So;0;ON;;;;;N;;;;; 1F6F5;MOTOR SCOOTER;So;0;ON;;;;;N;;;;; 1F6F6;CANOE;So;0;ON;;;;;N;;;;; +1F6F7;SLED;So;0;ON;;;;;N;;;;; +1F6F8;FLYING SAUCER;So;0;ON;;;;;N;;;;; 1F700;ALCHEMICAL SYMBOL FOR QUINTESSENCE;So;0;ON;;;;;N;;;;; 1F701;ALCHEMICAL SYMBOL FOR AIR;So;0;ON;;;;;N;;;;; 1F702;ALCHEMICAL SYMBOL FOR FIRE;So;0;ON;;;;;N;;;;; @@ -29617,6 +30575,18 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 1F8AB;RIGHTWARDS FRONT-TILTED SHADOWED WHITE ARROW;So;0;ON;;;;;N;;;;; 1F8AC;WHITE ARROW SHAFT WIDTH ONE;So;0;ON;;;;;N;;;;; 1F8AD;WHITE ARROW SHAFT WIDTH TWO THIRDS;So;0;ON;;;;;N;;;;; +1F900;CIRCLED CROSS FORMEE WITH FOUR DOTS;So;0;ON;;;;;N;;;;; +1F901;CIRCLED CROSS FORMEE WITH TWO DOTS;So;0;ON;;;;;N;;;;; +1F902;CIRCLED CROSS FORMEE;So;0;ON;;;;;N;;;;; +1F903;LEFT HALF CIRCLE WITH FOUR DOTS;So;0;ON;;;;;N;;;;; +1F904;LEFT HALF CIRCLE WITH THREE DOTS;So;0;ON;;;;;N;;;;; +1F905;LEFT HALF CIRCLE WITH TWO DOTS;So;0;ON;;;;;N;;;;; +1F906;LEFT HALF CIRCLE WITH DOT;So;0;ON;;;;;N;;;;; +1F907;LEFT HALF CIRCLE;So;0;ON;;;;;N;;;;; +1F908;DOWNWARD FACING HOOK;So;0;ON;;;;;N;;;;; +1F909;DOWNWARD FACING NOTCHED HOOK;So;0;ON;;;;;N;;;;; +1F90A;DOWNWARD FACING HOOK WITH DOT;So;0;ON;;;;;N;;;;; +1F90B;DOWNWARD FACING NOTCHED HOOK WITH DOT;So;0;ON;;;;;N;;;;; 1F910;ZIPPER-MOUTH FACE;So;0;ON;;;;;N;;;;; 1F911;MONEY-MOUTH FACE;So;0;ON;;;;;N;;;;; 1F912;FACE WITH THERMOMETER;So;0;ON;;;;;N;;;;; @@ -29632,6 +30602,7 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 1F91C;RIGHT-FACING FIST;So;0;ON;;;;;N;;;;; 1F91D;HANDSHAKE;So;0;ON;;;;;N;;;;; 1F91E;HAND WITH INDEX AND MIDDLE FINGERS CROSSED;So;0;ON;;;;;N;;;;; +1F91F;I LOVE YOU HAND SIGN;So;0;ON;;;;;N;;;;; 1F920;FACE WITH COWBOY HAT;So;0;ON;;;;;N;;;;; 1F921;CLOWN FACE;So;0;ON;;;;;N;;;;; 1F922;NAUSEATED FACE;So;0;ON;;;;;N;;;;; @@ -29640,7 +30611,17 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 1F925;LYING FACE;So;0;ON;;;;;N;;;;; 1F926;FACE PALM;So;0;ON;;;;;N;;;;; 1F927;SNEEZING FACE;So;0;ON;;;;;N;;;;; +1F928;FACE WITH ONE EYEBROW RAISED;So;0;ON;;;;;N;;;;; +1F929;GRINNING FACE WITH STAR EYES;So;0;ON;;;;;N;;;;; +1F92A;GRINNING FACE WITH ONE LARGE AND ONE SMALL EYE;So;0;ON;;;;;N;;;;; +1F92B;FACE WITH FINGER COVERING CLOSED LIPS;So;0;ON;;;;;N;;;;; +1F92C;SERIOUS FACE WITH SYMBOLS COVERING MOUTH;So;0;ON;;;;;N;;;;; +1F92D;SMILING FACE WITH SMILING EYES AND HAND COVERING MOUTH;So;0;ON;;;;;N;;;;; +1F92E;FACE WITH OPEN MOUTH VOMITING;So;0;ON;;;;;N;;;;; +1F92F;SHOCKED FACE WITH EXPLODING HEAD;So;0;ON;;;;;N;;;;; 1F930;PREGNANT WOMAN;So;0;ON;;;;;N;;;;; +1F931;BREAST-FEEDING;So;0;ON;;;;;N;;;;; +1F932;PALMS UP TOGETHER;So;0;ON;;;;;N;;;;; 1F933;SELFIE;So;0;ON;;;;;N;;;;; 1F934;PRINCE;So;0;ON;;;;;N;;;;; 1F935;MAN IN TUXEDO;So;0;ON;;;;;N;;;;; @@ -29665,6 +30646,7 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 1F949;THIRD PLACE MEDAL;So;0;ON;;;;;N;;;;; 1F94A;BOXING GLOVE;So;0;ON;;;;;N;;;;; 1F94B;MARTIAL ARTS UNIFORM;So;0;ON;;;;;N;;;;; +1F94C;CURLING STONE;So;0;ON;;;;;N;;;;; 1F950;CROISSANT;So;0;ON;;;;;N;;;;; 1F951;AVOCADO;So;0;ON;;;;;N;;;;; 1F952;CUCUMBER;So;0;ON;;;;;N;;;;; @@ -29680,6 +30662,19 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 1F95C;PEANUTS;So;0;ON;;;;;N;;;;; 1F95D;KIWIFRUIT;So;0;ON;;;;;N;;;;; 1F95E;PANCAKES;So;0;ON;;;;;N;;;;; +1F95F;DUMPLING;So;0;ON;;;;;N;;;;; +1F960;FORTUNE COOKIE;So;0;ON;;;;;N;;;;; +1F961;TAKEOUT BOX;So;0;ON;;;;;N;;;;; +1F962;CHOPSTICKS;So;0;ON;;;;;N;;;;; +1F963;BOWL WITH SPOON;So;0;ON;;;;;N;;;;; +1F964;CUP WITH STRAW;So;0;ON;;;;;N;;;;; +1F965;COCONUT;So;0;ON;;;;;N;;;;; +1F966;BROCCOLI;So;0;ON;;;;;N;;;;; +1F967;PIE;So;0;ON;;;;;N;;;;; +1F968;PRETZEL;So;0;ON;;;;;N;;;;; +1F969;CUT OF MEAT;So;0;ON;;;;;N;;;;; +1F96A;SANDWICH;So;0;ON;;;;;N;;;;; +1F96B;CANNED FOOD;So;0;ON;;;;;N;;;;; 1F980;CRAB;So;0;ON;;;;;N;;;;; 1F981;LION FACE;So;0;ON;;;;;N;;;;; 1F982;SCORPION;So;0;ON;;;;;N;;;;; @@ -29698,7 +30693,36 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 1F98F;RHINOCEROS;So;0;ON;;;;;N;;;;; 1F990;SHRIMP;So;0;ON;;;;;N;;;;; 1F991;SQUID;So;0;ON;;;;;N;;;;; +1F992;GIRAFFE FACE;So;0;ON;;;;;N;;;;; +1F993;ZEBRA FACE;So;0;ON;;;;;N;;;;; +1F994;HEDGEHOG;So;0;ON;;;;;N;;;;; +1F995;SAUROPOD;So;0;ON;;;;;N;;;;; +1F996;T-REX;So;0;ON;;;;;N;;;;; +1F997;CRICKET;So;0;ON;;;;;N;;;;; 1F9C0;CHEESE WEDGE;So;0;ON;;;;;N;;;;; +1F9D0;FACE WITH MONOCLE;So;0;ON;;;;;N;;;;; +1F9D1;ADULT;So;0;ON;;;;;N;;;;; +1F9D2;CHILD;So;0;ON;;;;;N;;;;; +1F9D3;OLDER ADULT;So;0;ON;;;;;N;;;;; +1F9D4;BEARDED PERSON;So;0;ON;;;;;N;;;;; +1F9D5;PERSON WITH HEADSCARF;So;0;ON;;;;;N;;;;; +1F9D6;PERSON IN STEAMY ROOM;So;0;ON;;;;;N;;;;; +1F9D7;PERSON CLIMBING;So;0;ON;;;;;N;;;;; +1F9D8;PERSON IN LOTUS POSITION;So;0;ON;;;;;N;;;;; +1F9D9;MAGE;So;0;ON;;;;;N;;;;; +1F9DA;FAIRY;So;0;ON;;;;;N;;;;; +1F9DB;VAMPIRE;So;0;ON;;;;;N;;;;; +1F9DC;MERPERSON;So;0;ON;;;;;N;;;;; +1F9DD;ELF;So;0;ON;;;;;N;;;;; +1F9DE;GENIE;So;0;ON;;;;;N;;;;; +1F9DF;ZOMBIE;So;0;ON;;;;;N;;;;; +1F9E0;BRAIN;So;0;ON;;;;;N;;;;; +1F9E1;ORANGE HEART;So;0;ON;;;;;N;;;;; +1F9E2;BILLED CAP;So;0;ON;;;;;N;;;;; +1F9E3;SCARF;So;0;ON;;;;;N;;;;; +1F9E4;GLOVES;So;0;ON;;;;;N;;;;; +1F9E5;COAT;So;0;ON;;;;;N;;;;; +1F9E6;SOCKS;So;0;ON;;;;;N;;;;; 20000;<CJK Ideograph Extension B, First>;Lo;0;L;;;;;N;;;;; 2A6D6;<CJK Ideograph Extension B, Last>;Lo;0;L;;;;;N;;;;; 2A700;<CJK Ideograph Extension C, First>;Lo;0;L;;;;;N;;;;; @@ -29707,6 +30731,8 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 2B81D;<CJK Ideograph Extension D, Last>;Lo;0;L;;;;;N;;;;; 2B820;<CJK Ideograph Extension E, First>;Lo;0;L;;;;;N;;;;; 2CEA1;<CJK Ideograph Extension E, Last>;Lo;0;L;;;;;N;;;;; +2CEB0;<CJK Ideograph Extension F, First>;Lo;0;L;;;;;N;;;;; +2EBE0;<CJK Ideograph Extension F, Last>;Lo;0;L;;;;;N;;;;; 2F800;CJK COMPATIBILITY IDEOGRAPH-2F800;Lo;0;L;4E3D;;;;N;;;;; 2F801;CJK COMPATIBILITY IDEOGRAPH-2F801;Lo;0;L;4E38;;;;N;;;;; 2F802;CJK COMPATIBILITY IDEOGRAPH-2F802;Lo;0;L;4E41;;;;N;;;;; diff --git a/unicode/emoji-data.txt b/unicode/emoji-data.txt index 731b62c4c1..3ad46c081e 100644 --- a/unicode/emoji-data.txt +++ b/unicode/emoji-data.txt @@ -1,362 +1,383 @@ # emoji-data.txt -# Date: 2016-06-02, 09:26:10 GMT -# ยฉ 2016 Unicodeยฎ, Inc. +# Date: 2017-03-27, 07:29:32 GMT +# ยฉ 2017 Unicodeยฎ, Inc. # Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries. # For terms of use, see http://www.unicode.org/terms_of_use.html # # Emoji Data for UTR #51 -# Version: 3.0 +# Version: 5.0 # # For documentation and usage, see http://www.unicode.org/reports/tr51 # # Warning: the format has changed from Version 1.0 # Format: -# codepoint(s) ; property(=Yes) # version [count] name(s) +# codepoint(s) ; property(=Yes) # comments +# +# Characters and sequences are listed in code point order. Users should be shown a more natural order. +# See the CLDR collation order for Emoji. + # ================================================ # All omitted code points have Emoji=No # @missing: 0000..10FFFF ; Emoji ; No -0023 ; Emoji # 1.1 [1] (#) NUMBER SIGN -002A ; Emoji # 1.1 [1] (*) ASTERISK -0030..0039 ; Emoji # 1.1 [10] (0..9) DIGIT ZERO..DIGIT NINE -00A9 ; Emoji # 1.1 [1] (ยฉ) COPYRIGHT SIGN -00AE ; Emoji # 1.1 [1] (ยฎ) REGISTERED SIGN -203C ; Emoji # 1.1 [1] (โผ) DOUBLE EXCLAMATION MARK -2049 ; Emoji # 3.0 [1] (โ) EXCLAMATION QUESTION MARK -2122 ; Emoji # 1.1 [1] (โข) TRADE MARK SIGN -2139 ; Emoji # 3.0 [1] (โน) INFORMATION SOURCE -2194..2199 ; Emoji # 1.1 [6] (โ..โ) LEFT RIGHT ARROW..SOUTH WEST ARROW -21A9..21AA ; Emoji # 1.1 [2] (โฉ..โช) LEFTWARDS ARROW WITH HOOK..RIGHTWARDS ARROW WITH HOOK -231A..231B ; Emoji # 1.1 [2] (โ..โ) WATCH..HOURGLASS -2328 ; Emoji # 1.1 [1] (โจ) KEYBOARD -23CF ; Emoji # 4.0 [1] (โ) EJECT SYMBOL -23E9..23F3 ; Emoji # 6.0 [11] (โฉ..โณ) BLACK RIGHT-POINTING DOUBLE TRIANGLE..HOURGLASS WITH FLOWING SAND -23F8..23FA ; Emoji # 7.0 [3] (โธ..โบ) DOUBLE VERTICAL BAR..BLACK CIRCLE FOR RECORD -24C2 ; Emoji # 1.1 [1] (โ) CIRCLED LATIN CAPITAL LETTER M -25AA..25AB ; Emoji # 1.1 [2] (โช..โซ) BLACK SMALL SQUARE..WHITE SMALL SQUARE -25B6 ; Emoji # 1.1 [1] (โถ) BLACK RIGHT-POINTING TRIANGLE -25C0 ; Emoji # 1.1 [1] (โ) BLACK LEFT-POINTING TRIANGLE -25FB..25FE ; Emoji # 3.2 [4] (โป..โพ) WHITE MEDIUM SQUARE..BLACK MEDIUM SMALL SQUARE -2600..2604 ; Emoji # 1.1 [5] (โ..โ) BLACK SUN WITH RAYS..COMET -260E ; Emoji # 1.1 [1] (โ) BLACK TELEPHONE -2611 ; Emoji # 1.1 [1] (โ) BALLOT BOX WITH CHECK -2614..2615 ; Emoji # 4.0 [2] (โ..โ) UMBRELLA WITH RAIN DROPS..HOT BEVERAGE -2618 ; Emoji # 4.1 [1] (โ) SHAMROCK -261D ; Emoji # 1.1 [1] (โ) WHITE UP POINTING INDEX -2620 ; Emoji # 1.1 [1] (โ ) SKULL AND CROSSBONES -2622..2623 ; Emoji # 1.1 [2] (โข..โฃ) RADIOACTIVE SIGN..BIOHAZARD SIGN -2626 ; Emoji # 1.1 [1] (โฆ) ORTHODOX CROSS -262A ; Emoji # 1.1 [1] (โช) STAR AND CRESCENT -262E..262F ; Emoji # 1.1 [2] (โฎ..โฏ) PEACE SYMBOL..YIN YANG -2638..263A ; Emoji # 1.1 [3] (โธ..โบ) WHEEL OF DHARMA..WHITE SMILING FACE -2648..2653 ; Emoji # 1.1 [12] (โ..โ) ARIES..PISCES -2660 ; Emoji # 1.1 [1] (โ ) BLACK SPADE SUIT -2663 ; Emoji # 1.1 [1] (โฃ) BLACK CLUB SUIT -2665..2666 ; Emoji # 1.1 [2] (โฅ..โฆ) BLACK HEART SUIT..BLACK DIAMOND SUIT -2668 ; Emoji # 1.1 [1] (โจ) HOT SPRINGS -267B ; Emoji # 3.2 [1] (โป) BLACK UNIVERSAL RECYCLING SYMBOL -267F ; Emoji # 4.1 [1] (โฟ) WHEELCHAIR SYMBOL -2692..2694 ; Emoji # 4.1 [3] (โ..โ) HAMMER AND PICK..CROSSED SWORDS -2696..2697 ; Emoji # 4.1 [2] (โ..โ) SCALES..ALEMBIC -2699 ; Emoji # 4.1 [1] (โ) GEAR -269B..269C ; Emoji # 4.1 [2] (โ..โ) ATOM SYMBOL..FLEUR-DE-LIS -26A0..26A1 ; Emoji # 4.0 [2] (โ ..โก) WARNING SIGN..HIGH VOLTAGE SIGN -26AA..26AB ; Emoji # 4.1 [2] (โช..โซ) MEDIUM WHITE CIRCLE..MEDIUM BLACK CIRCLE -26B0..26B1 ; Emoji # 4.1 [2] (โฐ..โฑ) COFFIN..FUNERAL URN -26BD..26BE ; Emoji # 5.2 [2] (โฝ..โพ) SOCCER BALL..BASEBALL -26C4..26C5 ; Emoji # 5.2 [2] (โ..โ
) SNOWMAN WITHOUT SNOW..SUN BEHIND CLOUD -26C8 ; Emoji # 5.2 [1] (โ) THUNDER CLOUD AND RAIN -26CE ; Emoji # 6.0 [1] (โ) OPHIUCHUS -26CF ; Emoji # 5.2 [1] (โ) PICK -26D1 ; Emoji # 5.2 [1] (โ) HELMET WITH WHITE CROSS -26D3..26D4 ; Emoji # 5.2 [2] (โ..โ) CHAINS..NO ENTRY -26E9..26EA ; Emoji # 5.2 [2] (โฉ..โช) SHINTO SHRINE..CHURCH -26F0..26F5 ; Emoji # 5.2 [6] (โฐ..โต) MOUNTAIN..SAILBOAT -26F7..26FA ; Emoji # 5.2 [4] (โท..โบ) SKIER..TENT -26FD ; Emoji # 5.2 [1] (โฝ) FUEL PUMP -2702 ; Emoji # 1.1 [1] (โ) BLACK SCISSORS -2705 ; Emoji # 6.0 [1] (โ
) WHITE HEAVY CHECK MARK -2708..2709 ; Emoji # 1.1 [2] (โ..โ) AIRPLANE..ENVELOPE -270A..270B ; Emoji # 6.0 [2] (โ..โ) RAISED FIST..RAISED HAND -270C..270D ; Emoji # 1.1 [2] (โ..โ) VICTORY HAND..WRITING HAND -270F ; Emoji # 1.1 [1] (โ) PENCIL -2712 ; Emoji # 1.1 [1] (โ) BLACK NIB -2714 ; Emoji # 1.1 [1] (โ) HEAVY CHECK MARK -2716 ; Emoji # 1.1 [1] (โ) HEAVY MULTIPLICATION X -271D ; Emoji # 1.1 [1] (โ) LATIN CROSS -2721 ; Emoji # 1.1 [1] (โก) STAR OF DAVID -2728 ; Emoji # 6.0 [1] (โจ) SPARKLES -2733..2734 ; Emoji # 1.1 [2] (โณ..โด) EIGHT SPOKED ASTERISK..EIGHT POINTED BLACK STAR -2744 ; Emoji # 1.1 [1] (โ) SNOWFLAKE -2747 ; Emoji # 1.1 [1] (โ) SPARKLE -274C ; Emoji # 6.0 [1] (โ) CROSS MARK -274E ; Emoji # 6.0 [1] (โ) NEGATIVE SQUARED CROSS MARK -2753..2755 ; Emoji # 6.0 [3] (โ..โ) BLACK QUESTION MARK ORNAMENT..WHITE EXCLAMATION MARK ORNAMENT -2757 ; Emoji # 5.2 [1] (โ) HEAVY EXCLAMATION MARK SYMBOL -2763..2764 ; Emoji # 1.1 [2] (โฃ..โค) HEAVY HEART EXCLAMATION MARK ORNAMENT..HEAVY BLACK HEART -2795..2797 ; Emoji # 6.0 [3] (โ..โ) HEAVY PLUS SIGN..HEAVY DIVISION SIGN -27A1 ; Emoji # 1.1 [1] (โก) BLACK RIGHTWARDS ARROW -27B0 ; Emoji # 6.0 [1] (โฐ) CURLY LOOP -27BF ; Emoji # 6.0 [1] (โฟ) DOUBLE CURLY LOOP -2934..2935 ; Emoji # 3.2 [2] (โคด..โคต) ARROW POINTING RIGHTWARDS THEN CURVING UPWARDS..ARROW POINTING RIGHTWARDS THEN CURVING DOWNWARDS -2B05..2B07 ; Emoji # 4.0 [3] (โฌ
..โฌ) LEFTWARDS BLACK ARROW..DOWNWARDS BLACK ARROW -2B1B..2B1C ; Emoji # 5.1 [2] (โฌ..โฌ) BLACK LARGE SQUARE..WHITE LARGE SQUARE -2B50 ; Emoji # 5.1 [1] (โญ) WHITE MEDIUM STAR -2B55 ; Emoji # 5.2 [1] (โญ) HEAVY LARGE CIRCLE -3030 ; Emoji # 1.1 [1] (ใฐ) WAVY DASH -303D ; Emoji # 3.2 [1] (ใฝ) PART ALTERNATION MARK -3297 ; Emoji # 1.1 [1] (ใ) CIRCLED IDEOGRAPH CONGRATULATION -3299 ; Emoji # 1.1 [1] (ใ) CIRCLED IDEOGRAPH SECRET -1F004 ; Emoji # 5.1 [1] (๐) MAHJONG TILE RED DRAGON -1F0CF ; Emoji # 6.0 [1] (๐) PLAYING CARD BLACK JOKER -1F170..1F171 ; Emoji # 6.0 [2] (๐
ฐ..๐
ฑ) NEGATIVE SQUARED LATIN CAPITAL LETTER A..NEGATIVE SQUARED LATIN CAPITAL LETTER B -1F17E ; Emoji # 6.0 [1] (๐
พ) NEGATIVE SQUARED LATIN CAPITAL LETTER O -1F17F ; Emoji # 5.2 [1] (๐
ฟ) NEGATIVE SQUARED LATIN CAPITAL LETTER P -1F18E ; Emoji # 6.0 [1] (๐) NEGATIVE SQUARED AB -1F191..1F19A ; Emoji # 6.0 [10] (๐..๐) SQUARED CL..SQUARED VS -1F1E6..1F1FF ; Emoji # 6.0 [26] (๐ฆ..๐ฟ) REGIONAL INDICATOR SYMBOL LETTER A..REGIONAL INDICATOR SYMBOL LETTER Z -1F201..1F202 ; Emoji # 6.0 [2] (๐..๐) SQUARED KATAKANA KOKO..SQUARED KATAKANA SA -1F21A ; Emoji # 5.2 [1] (๐) SQUARED CJK UNIFIED IDEOGRAPH-7121 -1F22F ; Emoji # 5.2 [1] (๐ฏ) SQUARED CJK UNIFIED IDEOGRAPH-6307 -1F232..1F23A ; Emoji # 6.0 [9] (๐ฒ..๐บ) SQUARED CJK UNIFIED IDEOGRAPH-7981..SQUARED CJK UNIFIED IDEOGRAPH-55B6 -1F250..1F251 ; Emoji # 6.0 [2] (๐..๐) CIRCLED IDEOGRAPH ADVANTAGE..CIRCLED IDEOGRAPH ACCEPT -1F300..1F320 ; Emoji # 6.0 [33] (๐..๐ ) CYCLONE..SHOOTING STAR -1F321 ; Emoji # 7.0 [1] (๐ก) THERMOMETER -1F324..1F32C ; Emoji # 7.0 [9] (๐ค..๐ฌ) WHITE SUN WITH SMALL CLOUD..WIND BLOWING FACE -1F32D..1F32F ; Emoji # 8.0 [3] (๐ญ..๐ฏ) HOT DOG..BURRITO -1F330..1F335 ; Emoji # 6.0 [6] (๐ฐ..๐ต) CHESTNUT..CACTUS -1F336 ; Emoji # 7.0 [1] (๐ถ) HOT PEPPER -1F337..1F37C ; Emoji # 6.0 [70] (๐ท..๐ผ) TULIP..BABY BOTTLE -1F37D ; Emoji # 7.0 [1] (๐ฝ) FORK AND KNIFE WITH PLATE -1F37E..1F37F ; Emoji # 8.0 [2] (๐พ..๐ฟ) BOTTLE WITH POPPING CORK..POPCORN -1F380..1F393 ; Emoji # 6.0 [20] (๐..๐) RIBBON..GRADUATION CAP -1F396..1F397 ; Emoji # 7.0 [2] (๐..๐) MILITARY MEDAL..REMINDER RIBBON -1F399..1F39B ; Emoji # 7.0 [3] (๐..๐) STUDIO MICROPHONE..CONTROL KNOBS -1F39E..1F39F ; Emoji # 7.0 [2] (๐..๐) FILM FRAMES..ADMISSION TICKETS -1F3A0..1F3C4 ; Emoji # 6.0 [37] (๐ ..๐) CAROUSEL HORSE..SURFER -1F3C5 ; Emoji # 7.0 [1] (๐
) SPORTS MEDAL -1F3C6..1F3CA ; Emoji # 6.0 [5] (๐..๐) TROPHY..SWIMMER -1F3CB..1F3CE ; Emoji # 7.0 [4] (๐..๐) WEIGHT LIFTER..RACING CAR -1F3CF..1F3D3 ; Emoji # 8.0 [5] (๐..๐) CRICKET BAT AND BALL..TABLE TENNIS PADDLE AND BALL -1F3D4..1F3DF ; Emoji # 7.0 [12] (๐..๐) SNOW CAPPED MOUNTAIN..STADIUM -1F3E0..1F3F0 ; Emoji # 6.0 [17] (๐ ..๐ฐ) HOUSE BUILDING..EUROPEAN CASTLE -1F3F3..1F3F5 ; Emoji # 7.0 [3] (๐ณ..๐ต) WAVING WHITE FLAG..ROSETTE -1F3F7 ; Emoji # 7.0 [1] (๐ท) LABEL -1F3F8..1F3FF ; Emoji # 8.0 [8] (๐ธ..๐ฟ) BADMINTON RACQUET AND SHUTTLECOCK..EMOJI MODIFIER FITZPATRICK TYPE-6 -1F400..1F43E ; Emoji # 6.0 [63] (๐..๐พ) RAT..PAW PRINTS -1F43F ; Emoji # 7.0 [1] (๐ฟ) CHIPMUNK -1F440 ; Emoji # 6.0 [1] (๐) EYES -1F441 ; Emoji # 7.0 [1] (๐) EYE -1F442..1F4F7 ; Emoji # 6.0[182] (๐..๐ท) EAR..CAMERA -1F4F8 ; Emoji # 7.0 [1] (๐ธ) CAMERA WITH FLASH -1F4F9..1F4FC ; Emoji # 6.0 [4] (๐น..๐ผ) VIDEO CAMERA..VIDEOCASSETTE -1F4FD ; Emoji # 7.0 [1] (๐ฝ) FILM PROJECTOR -1F4FF ; Emoji # 8.0 [1] (๐ฟ) PRAYER BEADS -1F500..1F53D ; Emoji # 6.0 [62] (๐..๐ฝ) TWISTED RIGHTWARDS ARROWS..DOWN-POINTING SMALL RED TRIANGLE -1F549..1F54A ; Emoji # 7.0 [2] (๐..๐) OM SYMBOL..DOVE OF PEACE -1F54B..1F54E ; Emoji # 8.0 [4] (๐..๐) KAABA..MENORAH WITH NINE BRANCHES -1F550..1F567 ; Emoji # 6.0 [24] (๐..๐ง) CLOCK FACE ONE OCLOCK..CLOCK FACE TWELVE-THIRTY -1F56F..1F570 ; Emoji # 7.0 [2] (๐ฏ..๐ฐ) CANDLE..MANTELPIECE CLOCK -1F573..1F579 ; Emoji # 7.0 [7] (๐ณ..๐น) HOLE..JOYSTICK -1F57A ; Emoji # 9.0 [1] (๐บ) MAN DANCING -1F587 ; Emoji # 7.0 [1] (๐) LINKED PAPERCLIPS -1F58A..1F58D ; Emoji # 7.0 [4] (๐..๐) LOWER LEFT BALLPOINT PEN..LOWER LEFT CRAYON -1F590 ; Emoji # 7.0 [1] (๐) RAISED HAND WITH FINGERS SPLAYED -1F595..1F596 ; Emoji # 7.0 [2] (๐..๐) REVERSED HAND WITH MIDDLE FINGER EXTENDED..RAISED HAND WITH PART BETWEEN MIDDLE AND RING FINGERS -1F5A4 ; Emoji # 9.0 [1] (๐ค) BLACK HEART -1F5A5 ; Emoji # 7.0 [1] (๐ฅ) DESKTOP COMPUTER -1F5A8 ; Emoji # 7.0 [1] (๐จ) PRINTER -1F5B1..1F5B2 ; Emoji # 7.0 [2] (๐ฑ..๐ฒ) THREE BUTTON MOUSE..TRACKBALL -1F5BC ; Emoji # 7.0 [1] (๐ผ) FRAME WITH PICTURE -1F5C2..1F5C4 ; Emoji # 7.0 [3] (๐..๐) CARD INDEX DIVIDERS..FILE CABINET -1F5D1..1F5D3 ; Emoji # 7.0 [3] (๐..๐) WASTEBASKET..SPIRAL CALENDAR PAD -1F5DC..1F5DE ; Emoji # 7.0 [3] (๐..๐) COMPRESSION..ROLLED-UP NEWSPAPER -1F5E1 ; Emoji # 7.0 [1] (๐ก) DAGGER KNIFE -1F5E3 ; Emoji # 7.0 [1] (๐ฃ) SPEAKING HEAD IN SILHOUETTE -1F5E8 ; Emoji # 7.0 [1] (๐จ) LEFT SPEECH BUBBLE -1F5EF ; Emoji # 7.0 [1] (๐ฏ) RIGHT ANGER BUBBLE -1F5F3 ; Emoji # 7.0 [1] (๐ณ) BALLOT BOX WITH BALLOT -1F5FA ; Emoji # 7.0 [1] (๐บ) WORLD MAP -1F5FB..1F5FF ; Emoji # 6.0 [5] (๐ป..๐ฟ) MOUNT FUJI..MOYAI -1F600 ; Emoji # 6.1 [1] (๐) GRINNING FACE -1F601..1F610 ; Emoji # 6.0 [16] (๐..๐) GRINNING FACE WITH SMILING EYES..NEUTRAL FACE -1F611 ; Emoji # 6.1 [1] (๐) EXPRESSIONLESS FACE -1F612..1F614 ; Emoji # 6.0 [3] (๐..๐) UNAMUSED FACE..PENSIVE FACE -1F615 ; Emoji # 6.1 [1] (๐) CONFUSED FACE -1F616 ; Emoji # 6.0 [1] (๐) CONFOUNDED FACE -1F617 ; Emoji # 6.1 [1] (๐) KISSING FACE -1F618 ; Emoji # 6.0 [1] (๐) FACE THROWING A KISS -1F619 ; Emoji # 6.1 [1] (๐) KISSING FACE WITH SMILING EYES -1F61A ; Emoji # 6.0 [1] (๐) KISSING FACE WITH CLOSED EYES -1F61B ; Emoji # 6.1 [1] (๐) FACE WITH STUCK-OUT TONGUE -1F61C..1F61E ; Emoji # 6.0 [3] (๐..๐) FACE WITH STUCK-OUT TONGUE AND WINKING EYE..DISAPPOINTED FACE -1F61F ; Emoji # 6.1 [1] (๐) WORRIED FACE -1F620..1F625 ; Emoji # 6.0 [6] (๐ ..๐ฅ) ANGRY FACE..DISAPPOINTED BUT RELIEVED FACE -1F626..1F627 ; Emoji # 6.1 [2] (๐ฆ..๐ง) FROWNING FACE WITH OPEN MOUTH..ANGUISHED FACE -1F628..1F62B ; Emoji # 6.0 [4] (๐จ..๐ซ) FEARFUL FACE..TIRED FACE -1F62C ; Emoji # 6.1 [1] (๐ฌ) GRIMACING FACE -1F62D ; Emoji # 6.0 [1] (๐ญ) LOUDLY CRYING FACE -1F62E..1F62F ; Emoji # 6.1 [2] (๐ฎ..๐ฏ) FACE WITH OPEN MOUTH..HUSHED FACE -1F630..1F633 ; Emoji # 6.0 [4] (๐ฐ..๐ณ) FACE WITH OPEN MOUTH AND COLD SWEAT..FLUSHED FACE -1F634 ; Emoji # 6.1 [1] (๐ด) SLEEPING FACE -1F635..1F640 ; Emoji # 6.0 [12] (๐ต..๐) DIZZY FACE..WEARY CAT FACE -1F641..1F642 ; Emoji # 7.0 [2] (๐..๐) SLIGHTLY FROWNING FACE..SLIGHTLY SMILING FACE -1F643..1F644 ; Emoji # 8.0 [2] (๐..๐) UPSIDE-DOWN FACE..FACE WITH ROLLING EYES -1F645..1F64F ; Emoji # 6.0 [11] (๐
..๐) FACE WITH NO GOOD GESTURE..PERSON WITH FOLDED HANDS -1F680..1F6C5 ; Emoji # 6.0 [70] (๐..๐
) ROCKET..LEFT LUGGAGE -1F6CB..1F6CF ; Emoji # 7.0 [5] (๐..๐) COUCH AND LAMP..BED -1F6D0 ; Emoji # 8.0 [1] (๐) PLACE OF WORSHIP -1F6D1..1F6D2 ; Emoji # 9.0 [2] (๐..๐) OCTAGONAL SIGN..SHOPPING TROLLEY -1F6E0..1F6E5 ; Emoji # 7.0 [6] (๐ ..๐ฅ) HAMMER AND WRENCH..MOTOR BOAT -1F6E9 ; Emoji # 7.0 [1] (๐ฉ) SMALL AIRPLANE -1F6EB..1F6EC ; Emoji # 7.0 [2] (๐ซ..๐ฌ) AIRPLANE DEPARTURE..AIRPLANE ARRIVING -1F6F0 ; Emoji # 7.0 [1] (๐ฐ) SATELLITE -1F6F3 ; Emoji # 7.0 [1] (๐ณ) PASSENGER SHIP -1F6F4..1F6F6 ; Emoji # 9.0 [3] (๐ด..๐ถ) SCOOTER..CANOE -1F910..1F918 ; Emoji # 8.0 [9] (๐ค..๐ค) ZIPPER-MOUTH FACE..SIGN OF THE HORNS -1F919..1F91E ; Emoji # 9.0 [6] (๐ค..๐ค) CALL ME HAND..HAND WITH INDEX AND MIDDLE FINGERS CROSSED -1F920..1F927 ; Emoji # 9.0 [8] (๐ค ..๐คง) FACE WITH COWBOY HAT..SNEEZING FACE -1F930 ; Emoji # 9.0 [1] (๐คฐ) PREGNANT WOMAN -1F933..1F93A ; Emoji # 9.0 [8] (๐คณ..๐คบ) SELFIE..FENCER -1F93C..1F93E ; Emoji # 9.0 [3] (๐คผ..๐คพ) WRESTLERS..HANDBALL -1F940..1F945 ; Emoji # 9.0 [6] (๐ฅ..๐ฅ
) WILTED FLOWER..GOAL NET -1F947..1F94B ; Emoji # 9.0 [5] (๐ฅ..๐ฅ) FIRST PLACE MEDAL..MARTIAL ARTS UNIFORM -1F950..1F95E ; Emoji # 9.0 [15] (๐ฅ..๐ฅ) CROISSANT..PANCAKES -1F980..1F984 ; Emoji # 8.0 [5] (๐ฆ..๐ฆ) CRAB..UNICORN FACE -1F985..1F991 ; Emoji # 9.0 [13] (๐ฆ
..๐ฆ) EAGLE..SQUID -1F9C0 ; Emoji # 8.0 [1] (๐ง) CHEESE WEDGE +0023 ; Emoji # 1.1 [1] (#๏ธ) number sign +002A ; Emoji # 1.1 [1] (*๏ธ) asterisk +0030..0039 ; Emoji # 1.1 [10] (0๏ธ..9๏ธ) digit zero..digit nine +00A9 ; Emoji # 1.1 [1] (ยฉ๏ธ) copyright +00AE ; Emoji # 1.1 [1] (ยฎ๏ธ) registered +203C ; Emoji # 1.1 [1] (โผ๏ธ) double exclamation mark +2049 ; Emoji # 3.0 [1] (โ๏ธ) exclamation question mark +2122 ; Emoji # 1.1 [1] (โข๏ธ) trade mark +2139 ; Emoji # 3.0 [1] (โน๏ธ) information +2194..2199 ; Emoji # 1.1 [6] (โ๏ธ..โ๏ธ) left-right arrow..down-left arrow +21A9..21AA ; Emoji # 1.1 [2] (โฉ๏ธ..โช๏ธ) right arrow curving left..left arrow curving right +231A..231B ; Emoji # 1.1 [2] (โ..โ) watch..hourglass +2328 ; Emoji # 1.1 [1] (โจ๏ธ) keyboard +23CF ; Emoji # 4.0 [1] (โ๏ธ) eject button +23E9..23F3 ; Emoji # 6.0 [11] (โฉ..โณ) fast-forward button..hourglass with flowing sand +23F8..23FA ; Emoji # 7.0 [3] (โธ๏ธ..โบ๏ธ) pause button..record button +24C2 ; Emoji # 1.1 [1] (โ๏ธ) circled M +25AA..25AB ; Emoji # 1.1 [2] (โช๏ธ..โซ๏ธ) black small square..white small square +25B6 ; Emoji # 1.1 [1] (โถ๏ธ) play button +25C0 ; Emoji # 1.1 [1] (โ๏ธ) reverse button +25FB..25FE ; Emoji # 3.2 [4] (โป๏ธ..โพ) white medium square..black medium-small square +2600..2604 ; Emoji # 1.1 [5] (โ๏ธ..โ๏ธ) sun..comet +260E ; Emoji # 1.1 [1] (โ๏ธ) telephone +2611 ; Emoji # 1.1 [1] (โ๏ธ) ballot box with check +2614..2615 ; Emoji # 4.0 [2] (โ..โ) umbrella with rain drops..hot beverage +2618 ; Emoji # 4.1 [1] (โ๏ธ) shamrock +261D ; Emoji # 1.1 [1] (โ๏ธ) index pointing up +2620 ; Emoji # 1.1 [1] (โ ๏ธ) skull and crossbones +2622..2623 ; Emoji # 1.1 [2] (โข๏ธ..โฃ๏ธ) radioactive..biohazard +2626 ; Emoji # 1.1 [1] (โฆ๏ธ) orthodox cross +262A ; Emoji # 1.1 [1] (โช๏ธ) star and crescent +262E..262F ; Emoji # 1.1 [2] (โฎ๏ธ..โฏ๏ธ) peace symbol..yin yang +2638..263A ; Emoji # 1.1 [3] (โธ๏ธ..โบ๏ธ) wheel of dharma..smiling face +2640 ; Emoji # 1.1 [1] (โ๏ธ) female sign +2642 ; Emoji # 1.1 [1] (โ๏ธ) male sign +2648..2653 ; Emoji # 1.1 [12] (โ..โ) Aries..Pisces +2660 ; Emoji # 1.1 [1] (โ ๏ธ) spade suit +2663 ; Emoji # 1.1 [1] (โฃ๏ธ) club suit +2665..2666 ; Emoji # 1.1 [2] (โฅ๏ธ..โฆ๏ธ) heart suit..diamond suit +2668 ; Emoji # 1.1 [1] (โจ๏ธ) hot springs +267B ; Emoji # 3.2 [1] (โป๏ธ) recycling symbol +267F ; Emoji # 4.1 [1] (โฟ) wheelchair symbol +2692..2697 ; Emoji # 4.1 [6] (โ๏ธ..โ๏ธ) hammer and pick..alembic +2699 ; Emoji # 4.1 [1] (โ๏ธ) gear +269B..269C ; Emoji # 4.1 [2] (โ๏ธ..โ๏ธ) atom symbol..fleur-de-lis +26A0..26A1 ; Emoji # 4.0 [2] (โ ๏ธ..โก) warning..high voltage +26AA..26AB ; Emoji # 4.1 [2] (โช..โซ) white circle..black circle +26B0..26B1 ; Emoji # 4.1 [2] (โฐ๏ธ..โฑ๏ธ) coffin..funeral urn +26BD..26BE ; Emoji # 5.2 [2] (โฝ..โพ) soccer ball..baseball +26C4..26C5 ; Emoji # 5.2 [2] (โ..โ
) snowman without snow..sun behind cloud +26C8 ; Emoji # 5.2 [1] (โ๏ธ) cloud with lightning and rain +26CE ; Emoji # 6.0 [1] (โ) Ophiuchus +26CF ; Emoji # 5.2 [1] (โ๏ธ) pick +26D1 ; Emoji # 5.2 [1] (โ๏ธ) rescue workerโs helmet +26D3..26D4 ; Emoji # 5.2 [2] (โ๏ธ..โ) chains..no entry +26E9..26EA ; Emoji # 5.2 [2] (โฉ๏ธ..โช) shinto shrine..church +26F0..26F5 ; Emoji # 5.2 [6] (โฐ๏ธ..โต) mountain..sailboat +26F7..26FA ; Emoji # 5.2 [4] (โท๏ธ..โบ) skier..tent +26FD ; Emoji # 5.2 [1] (โฝ) fuel pump +2702 ; Emoji # 1.1 [1] (โ๏ธ) scissors +2705 ; Emoji # 6.0 [1] (โ
) white heavy check mark +2708..2709 ; Emoji # 1.1 [2] (โ๏ธ..โ๏ธ) airplane..envelope +270A..270B ; Emoji # 6.0 [2] (โ..โ) raised fist..raised hand +270C..270D ; Emoji # 1.1 [2] (โ๏ธ..โ๏ธ) victory hand..writing hand +270F ; Emoji # 1.1 [1] (โ๏ธ) pencil +2712 ; Emoji # 1.1 [1] (โ๏ธ) black nib +2714 ; Emoji # 1.1 [1] (โ๏ธ) heavy check mark +2716 ; Emoji # 1.1 [1] (โ๏ธ) heavy multiplication x +271D ; Emoji # 1.1 [1] (โ๏ธ) latin cross +2721 ; Emoji # 1.1 [1] (โก๏ธ) star of David +2728 ; Emoji # 6.0 [1] (โจ) sparkles +2733..2734 ; Emoji # 1.1 [2] (โณ๏ธ..โด๏ธ) eight-spoked asterisk..eight-pointed star +2744 ; Emoji # 1.1 [1] (โ๏ธ) snowflake +2747 ; Emoji # 1.1 [1] (โ๏ธ) sparkle +274C ; Emoji # 6.0 [1] (โ) cross mark +274E ; Emoji # 6.0 [1] (โ) cross mark button +2753..2755 ; Emoji # 6.0 [3] (โ..โ) question mark..white exclamation mark +2757 ; Emoji # 5.2 [1] (โ) exclamation mark +2763..2764 ; Emoji # 1.1 [2] (โฃ๏ธ..โค๏ธ) heavy heart exclamation..red heart +2795..2797 ; Emoji # 6.0 [3] (โ..โ) heavy plus sign..heavy division sign +27A1 ; Emoji # 1.1 [1] (โก๏ธ) right arrow +27B0 ; Emoji # 6.0 [1] (โฐ) curly loop +27BF ; Emoji # 6.0 [1] (โฟ) double curly loop +2934..2935 ; Emoji # 3.2 [2] (โคด๏ธ..โคต๏ธ) right arrow curving up..right arrow curving down +2B05..2B07 ; Emoji # 4.0 [3] (โฌ
๏ธ..โฌ๏ธ) left arrow..down arrow +2B1B..2B1C ; Emoji # 5.1 [2] (โฌ..โฌ) black large square..white large square +2B50 ; Emoji # 5.1 [1] (โญ) white medium star +2B55 ; Emoji # 5.2 [1] (โญ) heavy large circle +3030 ; Emoji # 1.1 [1] (ใฐ๏ธ) wavy dash +303D ; Emoji # 3.2 [1] (ใฝ๏ธ) part alternation mark +3297 ; Emoji # 1.1 [1] (ใ๏ธ) Japanese โcongratulationsโ button +3299 ; Emoji # 1.1 [1] (ใ๏ธ) Japanese โsecretโ button +1F004 ; Emoji # 5.1 [1] (๐) mahjong red dragon +1F0CF ; Emoji # 6.0 [1] (๐) joker +1F170..1F171 ; Emoji # 6.0 [2] (๐
ฐ๏ธ..๐
ฑ๏ธ) A button (blood type)..B button (blood type) +1F17E ; Emoji # 6.0 [1] (๐
พ๏ธ) O button (blood type) +1F17F ; Emoji # 5.2 [1] (๐
ฟ๏ธ) P button +1F18E ; Emoji # 6.0 [1] (๐) AB button (blood type) +1F191..1F19A ; Emoji # 6.0 [10] (๐..๐) CL button..VS button +1F1E6..1F1FF ; Emoji # 6.0 [26] (๐ฆ..๐ฟ) regional indicator symbol letter a..regional indicator symbol letter z +1F201..1F202 ; Emoji # 6.0 [2] (๐..๐๏ธ) Japanese โhereโ button..Japanese โservice chargeโ button +1F21A ; Emoji # 5.2 [1] (๐) Japanese โfree of chargeโ button +1F22F ; Emoji # 5.2 [1] (๐ฏ) Japanese โreservedโ button +1F232..1F23A ; Emoji # 6.0 [9] (๐ฒ..๐บ) Japanese โprohibitedโ button..Japanese โopen for businessโ button +1F250..1F251 ; Emoji # 6.0 [2] (๐..๐) Japanese โbargainโ button..Japanese โacceptableโ button +1F300..1F320 ; Emoji # 6.0 [33] (๐..๐ ) cyclone..shooting star +1F321 ; Emoji # 7.0 [1] (๐ก๏ธ) thermometer +1F324..1F32C ; Emoji # 7.0 [9] (๐ค๏ธ..๐ฌ๏ธ) sun behind small cloud..wind face +1F32D..1F32F ; Emoji # 8.0 [3] (๐ญ..๐ฏ) hot dog..burrito +1F330..1F335 ; Emoji # 6.0 [6] (๐ฐ..๐ต) chestnut..cactus +1F336 ; Emoji # 7.0 [1] (๐ถ๏ธ) hot pepper +1F337..1F37C ; Emoji # 6.0 [70] (๐ท..๐ผ) tulip..baby bottle +1F37D ; Emoji # 7.0 [1] (๐ฝ๏ธ) fork and knife with plate +1F37E..1F37F ; Emoji # 8.0 [2] (๐พ..๐ฟ) bottle with popping cork..popcorn +1F380..1F393 ; Emoji # 6.0 [20] (๐..๐) ribbon..graduation cap +1F396..1F397 ; Emoji # 7.0 [2] (๐๏ธ..๐๏ธ) military medal..reminder ribbon +1F399..1F39B ; Emoji # 7.0 [3] (๐๏ธ..๐๏ธ) studio microphone..control knobs +1F39E..1F39F ; Emoji # 7.0 [2] (๐๏ธ..๐๏ธ) film frames..admission tickets +1F3A0..1F3C4 ; Emoji # 6.0 [37] (๐ ..๐) carousel horse..person surfing +1F3C5 ; Emoji # 7.0 [1] (๐
) sports medal +1F3C6..1F3CA ; Emoji # 6.0 [5] (๐..๐) trophy..person swimming +1F3CB..1F3CE ; Emoji # 7.0 [4] (๐๏ธ..๐๏ธ) person lifting weights..racing car +1F3CF..1F3D3 ; Emoji # 8.0 [5] (๐..๐) cricket..ping pong +1F3D4..1F3DF ; Emoji # 7.0 [12] (๐๏ธ..๐๏ธ) snow-capped mountain..stadium +1F3E0..1F3F0 ; Emoji # 6.0 [17] (๐ ..๐ฐ) house..castle +1F3F3..1F3F5 ; Emoji # 7.0 [3] (๐ณ๏ธ..๐ต๏ธ) white flag..rosette +1F3F7 ; Emoji # 7.0 [1] (๐ท๏ธ) label +1F3F8..1F3FF ; Emoji # 8.0 [8] (๐ธ..๐ฟ) badminton..dark skin tone +1F400..1F43E ; Emoji # 6.0 [63] (๐..๐พ) rat..paw prints +1F43F ; Emoji # 7.0 [1] (๐ฟ๏ธ) chipmunk +1F440 ; Emoji # 6.0 [1] (๐) eyes +1F441 ; Emoji # 7.0 [1] (๐๏ธ) eye +1F442..1F4F7 ; Emoji # 6.0[182] (๐..๐ท) ear..camera +1F4F8 ; Emoji # 7.0 [1] (๐ธ) camera with flash +1F4F9..1F4FC ; Emoji # 6.0 [4] (๐น..๐ผ) video camera..videocassette +1F4FD ; Emoji # 7.0 [1] (๐ฝ๏ธ) film projector +1F4FF ; Emoji # 8.0 [1] (๐ฟ) prayer beads +1F500..1F53D ; Emoji # 6.0 [62] (๐..๐ฝ) shuffle tracks button..down button +1F549..1F54A ; Emoji # 7.0 [2] (๐๏ธ..๐๏ธ) om..dove +1F54B..1F54E ; Emoji # 8.0 [4] (๐..๐) kaaba..menorah +1F550..1F567 ; Emoji # 6.0 [24] (๐..๐ง) one oโclock..twelve-thirty +1F56F..1F570 ; Emoji # 7.0 [2] (๐ฏ๏ธ..๐ฐ๏ธ) candle..mantelpiece clock +1F573..1F579 ; Emoji # 7.0 [7] (๐ณ๏ธ..๐น๏ธ) hole..joystick +1F57A ; Emoji # 9.0 [1] (๐บ) man dancing +1F587 ; Emoji # 7.0 [1] (๐๏ธ) linked paperclips +1F58A..1F58D ; Emoji # 7.0 [4] (๐๏ธ..๐๏ธ) pen..crayon +1F590 ; Emoji # 7.0 [1] (๐๏ธ) raised hand with fingers splayed +1F595..1F596 ; Emoji # 7.0 [2] (๐..๐) middle finger..vulcan salute +1F5A4 ; Emoji # 9.0 [1] (๐ค) black heart +1F5A5 ; Emoji # 7.0 [1] (๐ฅ๏ธ) desktop computer +1F5A8 ; Emoji # 7.0 [1] (๐จ๏ธ) printer +1F5B1..1F5B2 ; Emoji # 7.0 [2] (๐ฑ๏ธ..๐ฒ๏ธ) computer mouse..trackball +1F5BC ; Emoji # 7.0 [1] (๐ผ๏ธ) framed picture +1F5C2..1F5C4 ; Emoji # 7.0 [3] (๐๏ธ..๐๏ธ) card index dividers..file cabinet +1F5D1..1F5D3 ; Emoji # 7.0 [3] (๐๏ธ..๐๏ธ) wastebasket..spiral calendar +1F5DC..1F5DE ; Emoji # 7.0 [3] (๐๏ธ..๐๏ธ) clamp..rolled-up newspaper +1F5E1 ; Emoji # 7.0 [1] (๐ก๏ธ) dagger +1F5E3 ; Emoji # 7.0 [1] (๐ฃ๏ธ) speaking head +1F5E8 ; Emoji # 7.0 [1] (๐จ๏ธ) left speech bubble +1F5EF ; Emoji # 7.0 [1] (๐ฏ๏ธ) right anger bubble +1F5F3 ; Emoji # 7.0 [1] (๐ณ๏ธ) ballot box with ballot +1F5FA ; Emoji # 7.0 [1] (๐บ๏ธ) world map +1F5FB..1F5FF ; Emoji # 6.0 [5] (๐ป..๐ฟ) mount fuji..moai +1F600 ; Emoji # 6.1 [1] (๐) grinning face +1F601..1F610 ; Emoji # 6.0 [16] (๐..๐) grinning face with smiling eyes..neutral face +1F611 ; Emoji # 6.1 [1] (๐) expressionless face +1F612..1F614 ; Emoji # 6.0 [3] (๐..๐) unamused face..pensive face +1F615 ; Emoji # 6.1 [1] (๐) confused face +1F616 ; Emoji # 6.0 [1] (๐) confounded face +1F617 ; Emoji # 6.1 [1] (๐) kissing face +1F618 ; Emoji # 6.0 [1] (๐) face blowing a kiss +1F619 ; Emoji # 6.1 [1] (๐) kissing face with smiling eyes +1F61A ; Emoji # 6.0 [1] (๐) kissing face with closed eyes +1F61B ; Emoji # 6.1 [1] (๐) face with stuck-out tongue +1F61C..1F61E ; Emoji # 6.0 [3] (๐..๐) face with stuck-out tongue & winking eye..disappointed face +1F61F ; Emoji # 6.1 [1] (๐) worried face +1F620..1F625 ; Emoji # 6.0 [6] (๐ ..๐ฅ) angry face..disappointed but relieved face +1F626..1F627 ; Emoji # 6.1 [2] (๐ฆ..๐ง) frowning face with open mouth..anguished face +1F628..1F62B ; Emoji # 6.0 [4] (๐จ..๐ซ) fearful face..tired face +1F62C ; Emoji # 6.1 [1] (๐ฌ) grimacing face +1F62D ; Emoji # 6.0 [1] (๐ญ) loudly crying face +1F62E..1F62F ; Emoji # 6.1 [2] (๐ฎ..๐ฏ) face with open mouth..hushed face +1F630..1F633 ; Emoji # 6.0 [4] (๐ฐ..๐ณ) face with open mouth & cold sweat..flushed face +1F634 ; Emoji # 6.1 [1] (๐ด) sleeping face +1F635..1F640 ; Emoji # 6.0 [12] (๐ต..๐) dizzy face..weary cat face +1F641..1F642 ; Emoji # 7.0 [2] (๐..๐) slightly frowning face..slightly smiling face +1F643..1F644 ; Emoji # 8.0 [2] (๐..๐) upside-down face..face with rolling eyes +1F645..1F64F ; Emoji # 6.0 [11] (๐
..๐) person gesturing NO..folded hands +1F680..1F6C5 ; Emoji # 6.0 [70] (๐..๐
) rocket..left luggage +1F6CB..1F6CF ; Emoji # 7.0 [5] (๐๏ธ..๐๏ธ) couch and lamp..bed +1F6D0 ; Emoji # 8.0 [1] (๐) place of worship +1F6D1..1F6D2 ; Emoji # 9.0 [2] (๐..๐) stop sign..shopping cart +1F6E0..1F6E5 ; Emoji # 7.0 [6] (๐ ๏ธ..๐ฅ๏ธ) hammer and wrench..motor boat +1F6E9 ; Emoji # 7.0 [1] (๐ฉ๏ธ) small airplane +1F6EB..1F6EC ; Emoji # 7.0 [2] (๐ซ..๐ฌ) airplane departure..airplane arrival +1F6F0 ; Emoji # 7.0 [1] (๐ฐ๏ธ) satellite +1F6F3 ; Emoji # 7.0 [1] (๐ณ๏ธ) passenger ship +1F6F4..1F6F6 ; Emoji # 9.0 [3] (๐ด..๐ถ) kick scooter..canoe +1F6F7..1F6F8 ; Emoji # 10.0 [2] (๐ท..๐ธ) sled..flying saucer +1F910..1F918 ; Emoji # 8.0 [9] (๐ค..๐ค) zipper-mouth face..sign of the horns +1F919..1F91E ; Emoji # 9.0 [6] (๐ค..๐ค) call me hand..crossed fingers +1F91F ; Emoji # 10.0 [1] (๐ค) love-you gesture +1F920..1F927 ; Emoji # 9.0 [8] (๐ค ..๐คง) cowboy hat face..sneezing face +1F928..1F92F ; Emoji # 10.0 [8] (๐คจ..๐คฏ) face with raised eyebrow..exploding head +1F930 ; Emoji # 9.0 [1] (๐คฐ) pregnant woman +1F931..1F932 ; Emoji # 10.0 [2] (๐คฑ..๐คฒ) breast-feeding..palms up together +1F933..1F93A ; Emoji # 9.0 [8] (๐คณ..๐คบ) selfie..person fencing +1F93C..1F93E ; Emoji # 9.0 [3] (๐คผ..๐คพ) people wrestling..person playing handball +1F940..1F945 ; Emoji # 9.0 [6] (๐ฅ..๐ฅ
) wilted flower..goal net +1F947..1F94B ; Emoji # 9.0 [5] (๐ฅ..๐ฅ) 1st place medal..martial arts uniform +1F94C ; Emoji # 10.0 [1] (๐ฅ) curling stone +1F950..1F95E ; Emoji # 9.0 [15] (๐ฅ..๐ฅ) croissant..pancakes +1F95F..1F96B ; Emoji # 10.0 [13] (๐ฅ..๐ฅซ) dumpling..canned food +1F980..1F984 ; Emoji # 8.0 [5] (๐ฆ..๐ฆ) crab..unicorn face +1F985..1F991 ; Emoji # 9.0 [13] (๐ฆ
..๐ฆ) eagle..squid +1F992..1F997 ; Emoji # 10.0 [6] (๐ฆ..๐ฆ) giraffe..cricket +1F9C0 ; Emoji # 8.0 [1] (๐ง) cheese wedge +1F9D0..1F9E6 ; Emoji # 10.0 [23] (๐ง..๐งฆ) face with monocle..socks -# Total elements: 1123 +# Total elements: 1182 # ================================================ # All omitted code points have Emoji_Presentation=No # @missing: 0000..10FFFF ; Emoji_Presentation ; No -231A..231B ; Emoji_Presentation # 1.1 [2] (โ..โ) WATCH..HOURGLASS -23E9..23EC ; Emoji_Presentation # 6.0 [4] (โฉ..โฌ) BLACK RIGHT-POINTING DOUBLE TRIANGLE..BLACK DOWN-POINTING DOUBLE TRIANGLE -23F0 ; Emoji_Presentation # 6.0 [1] (โฐ) ALARM CLOCK -23F3 ; Emoji_Presentation # 6.0 [1] (โณ) HOURGLASS WITH FLOWING SAND -25FD..25FE ; Emoji_Presentation # 3.2 [2] (โฝ..โพ) WHITE MEDIUM SMALL SQUARE..BLACK MEDIUM SMALL SQUARE -2614..2615 ; Emoji_Presentation # 4.0 [2] (โ..โ) UMBRELLA WITH RAIN DROPS..HOT BEVERAGE -2648..2653 ; Emoji_Presentation # 1.1 [12] (โ..โ) ARIES..PISCES -267F ; Emoji_Presentation # 4.1 [1] (โฟ) WHEELCHAIR SYMBOL -2693 ; Emoji_Presentation # 4.1 [1] (โ) ANCHOR -26A1 ; Emoji_Presentation # 4.0 [1] (โก) HIGH VOLTAGE SIGN -26AA..26AB ; Emoji_Presentation # 4.1 [2] (โช..โซ) MEDIUM WHITE CIRCLE..MEDIUM BLACK CIRCLE -26BD..26BE ; Emoji_Presentation # 5.2 [2] (โฝ..โพ) SOCCER BALL..BASEBALL -26C4..26C5 ; Emoji_Presentation # 5.2 [2] (โ..โ
) SNOWMAN WITHOUT SNOW..SUN BEHIND CLOUD -26CE ; Emoji_Presentation # 6.0 [1] (โ) OPHIUCHUS -26D4 ; Emoji_Presentation # 5.2 [1] (โ) NO ENTRY -26EA ; Emoji_Presentation # 5.2 [1] (โช) CHURCH -26F2..26F3 ; Emoji_Presentation # 5.2 [2] (โฒ..โณ) FOUNTAIN..FLAG IN HOLE -26F5 ; Emoji_Presentation # 5.2 [1] (โต) SAILBOAT -26FA ; Emoji_Presentation # 5.2 [1] (โบ) TENT -26FD ; Emoji_Presentation # 5.2 [1] (โฝ) FUEL PUMP -2705 ; Emoji_Presentation # 6.0 [1] (โ
) WHITE HEAVY CHECK MARK -270A..270B ; Emoji_Presentation # 6.0 [2] (โ..โ) RAISED FIST..RAISED HAND -2728 ; Emoji_Presentation # 6.0 [1] (โจ) SPARKLES -274C ; Emoji_Presentation # 6.0 [1] (โ) CROSS MARK -274E ; Emoji_Presentation # 6.0 [1] (โ) NEGATIVE SQUARED CROSS MARK -2753..2755 ; Emoji_Presentation # 6.0 [3] (โ..โ) BLACK QUESTION MARK ORNAMENT..WHITE EXCLAMATION MARK ORNAMENT -2757 ; Emoji_Presentation # 5.2 [1] (โ) HEAVY EXCLAMATION MARK SYMBOL -2795..2797 ; Emoji_Presentation # 6.0 [3] (โ..โ) HEAVY PLUS SIGN..HEAVY DIVISION SIGN -27B0 ; Emoji_Presentation # 6.0 [1] (โฐ) CURLY LOOP -27BF ; Emoji_Presentation # 6.0 [1] (โฟ) DOUBLE CURLY LOOP -2B1B..2B1C ; Emoji_Presentation # 5.1 [2] (โฌ..โฌ) BLACK LARGE SQUARE..WHITE LARGE SQUARE -2B50 ; Emoji_Presentation # 5.1 [1] (โญ) WHITE MEDIUM STAR -2B55 ; Emoji_Presentation # 5.2 [1] (โญ) HEAVY LARGE CIRCLE -1F004 ; Emoji_Presentation # 5.1 [1] (๐) MAHJONG TILE RED DRAGON -1F0CF ; Emoji_Presentation # 6.0 [1] (๐) PLAYING CARD BLACK JOKER -1F18E ; Emoji_Presentation # 6.0 [1] (๐) NEGATIVE SQUARED AB -1F191..1F19A ; Emoji_Presentation # 6.0 [10] (๐..๐) SQUARED CL..SQUARED VS -1F1E6..1F1FF ; Emoji_Presentation # 6.0 [26] (๐ฆ..๐ฟ) REGIONAL INDICATOR SYMBOL LETTER A..REGIONAL INDICATOR SYMBOL LETTER Z -1F201 ; Emoji_Presentation # 6.0 [1] (๐) SQUARED KATAKANA KOKO -1F21A ; Emoji_Presentation # 5.2 [1] (๐) SQUARED CJK UNIFIED IDEOGRAPH-7121 -1F22F ; Emoji_Presentation # 5.2 [1] (๐ฏ) SQUARED CJK UNIFIED IDEOGRAPH-6307 -1F232..1F236 ; Emoji_Presentation # 6.0 [5] (๐ฒ..๐ถ) SQUARED CJK UNIFIED IDEOGRAPH-7981..SQUARED CJK UNIFIED IDEOGRAPH-6709 -1F238..1F23A ; Emoji_Presentation # 6.0 [3] (๐ธ..๐บ) SQUARED CJK UNIFIED IDEOGRAPH-7533..SQUARED CJK UNIFIED IDEOGRAPH-55B6 -1F250..1F251 ; Emoji_Presentation # 6.0 [2] (๐..๐) CIRCLED IDEOGRAPH ADVANTAGE..CIRCLED IDEOGRAPH ACCEPT -1F300..1F320 ; Emoji_Presentation # 6.0 [33] (๐..๐ ) CYCLONE..SHOOTING STAR -1F32D..1F32F ; Emoji_Presentation # 8.0 [3] (๐ญ..๐ฏ) HOT DOG..BURRITO -1F330..1F335 ; Emoji_Presentation # 6.0 [6] (๐ฐ..๐ต) CHESTNUT..CACTUS -1F337..1F37C ; Emoji_Presentation # 6.0 [70] (๐ท..๐ผ) TULIP..BABY BOTTLE -1F37E..1F37F ; Emoji_Presentation # 8.0 [2] (๐พ..๐ฟ) BOTTLE WITH POPPING CORK..POPCORN -1F380..1F393 ; Emoji_Presentation # 6.0 [20] (๐..๐) RIBBON..GRADUATION CAP -1F3A0..1F3C4 ; Emoji_Presentation # 6.0 [37] (๐ ..๐) CAROUSEL HORSE..SURFER -1F3C5 ; Emoji_Presentation # 7.0 [1] (๐
) SPORTS MEDAL -1F3C6..1F3CA ; Emoji_Presentation # 6.0 [5] (๐..๐) TROPHY..SWIMMER -1F3CF..1F3D3 ; Emoji_Presentation # 8.0 [5] (๐..๐) CRICKET BAT AND BALL..TABLE TENNIS PADDLE AND BALL -1F3E0..1F3F0 ; Emoji_Presentation # 6.0 [17] (๐ ..๐ฐ) HOUSE BUILDING..EUROPEAN CASTLE -1F3F4 ; Emoji_Presentation # 7.0 [1] (๐ด) WAVING BLACK FLAG -1F3F8..1F3FF ; Emoji_Presentation # 8.0 [8] (๐ธ..๐ฟ) BADMINTON RACQUET AND SHUTTLECOCK..EMOJI MODIFIER FITZPATRICK TYPE-6 -1F400..1F43E ; Emoji_Presentation # 6.0 [63] (๐..๐พ) RAT..PAW PRINTS -1F440 ; Emoji_Presentation # 6.0 [1] (๐) EYES -1F442..1F4F7 ; Emoji_Presentation # 6.0[182] (๐..๐ท) EAR..CAMERA -1F4F8 ; Emoji_Presentation # 7.0 [1] (๐ธ) CAMERA WITH FLASH -1F4F9..1F4FC ; Emoji_Presentation # 6.0 [4] (๐น..๐ผ) VIDEO CAMERA..VIDEOCASSETTE -1F4FF ; Emoji_Presentation # 8.0 [1] (๐ฟ) PRAYER BEADS -1F500..1F53D ; Emoji_Presentation # 6.0 [62] (๐..๐ฝ) TWISTED RIGHTWARDS ARROWS..DOWN-POINTING SMALL RED TRIANGLE -1F54B..1F54E ; Emoji_Presentation # 8.0 [4] (๐..๐) KAABA..MENORAH WITH NINE BRANCHES -1F550..1F567 ; Emoji_Presentation # 6.0 [24] (๐..๐ง) CLOCK FACE ONE OCLOCK..CLOCK FACE TWELVE-THIRTY -1F57A ; Emoji_Presentation # 9.0 [1] (๐บ) MAN DANCING -1F595..1F596 ; Emoji_Presentation # 7.0 [2] (๐..๐) REVERSED HAND WITH MIDDLE FINGER EXTENDED..RAISED HAND WITH PART BETWEEN MIDDLE AND RING FINGERS -1F5A4 ; Emoji_Presentation # 9.0 [1] (๐ค) BLACK HEART -1F5FB..1F5FF ; Emoji_Presentation # 6.0 [5] (๐ป..๐ฟ) MOUNT FUJI..MOYAI -1F600 ; Emoji_Presentation # 6.1 [1] (๐) GRINNING FACE -1F601..1F610 ; Emoji_Presentation # 6.0 [16] (๐..๐) GRINNING FACE WITH SMILING EYES..NEUTRAL FACE -1F611 ; Emoji_Presentation # 6.1 [1] (๐) EXPRESSIONLESS FACE -1F612..1F614 ; Emoji_Presentation # 6.0 [3] (๐..๐) UNAMUSED FACE..PENSIVE FACE -1F615 ; Emoji_Presentation # 6.1 [1] (๐) CONFUSED FACE -1F616 ; Emoji_Presentation # 6.0 [1] (๐) CONFOUNDED FACE -1F617 ; Emoji_Presentation # 6.1 [1] (๐) KISSING FACE -1F618 ; Emoji_Presentation # 6.0 [1] (๐) FACE THROWING A KISS -1F619 ; Emoji_Presentation # 6.1 [1] (๐) KISSING FACE WITH SMILING EYES -1F61A ; Emoji_Presentation # 6.0 [1] (๐) KISSING FACE WITH CLOSED EYES -1F61B ; Emoji_Presentation # 6.1 [1] (๐) FACE WITH STUCK-OUT TONGUE -1F61C..1F61E ; Emoji_Presentation # 6.0 [3] (๐..๐) FACE WITH STUCK-OUT TONGUE AND WINKING EYE..DISAPPOINTED FACE -1F61F ; Emoji_Presentation # 6.1 [1] (๐) WORRIED FACE -1F620..1F625 ; Emoji_Presentation # 6.0 [6] (๐ ..๐ฅ) ANGRY FACE..DISAPPOINTED BUT RELIEVED FACE -1F626..1F627 ; Emoji_Presentation # 6.1 [2] (๐ฆ..๐ง) FROWNING FACE WITH OPEN MOUTH..ANGUISHED FACE -1F628..1F62B ; Emoji_Presentation # 6.0 [4] (๐จ..๐ซ) FEARFUL FACE..TIRED FACE -1F62C ; Emoji_Presentation # 6.1 [1] (๐ฌ) GRIMACING FACE -1F62D ; Emoji_Presentation # 6.0 [1] (๐ญ) LOUDLY CRYING FACE -1F62E..1F62F ; Emoji_Presentation # 6.1 [2] (๐ฎ..๐ฏ) FACE WITH OPEN MOUTH..HUSHED FACE -1F630..1F633 ; Emoji_Presentation # 6.0 [4] (๐ฐ..๐ณ) FACE WITH OPEN MOUTH AND COLD SWEAT..FLUSHED FACE -1F634 ; Emoji_Presentation # 6.1 [1] (๐ด) SLEEPING FACE -1F635..1F640 ; Emoji_Presentation # 6.0 [12] (๐ต..๐) DIZZY FACE..WEARY CAT FACE -1F641..1F642 ; Emoji_Presentation # 7.0 [2] (๐..๐) SLIGHTLY FROWNING FACE..SLIGHTLY SMILING FACE -1F643..1F644 ; Emoji_Presentation # 8.0 [2] (๐..๐) UPSIDE-DOWN FACE..FACE WITH ROLLING EYES -1F645..1F64F ; Emoji_Presentation # 6.0 [11] (๐
..๐) FACE WITH NO GOOD GESTURE..PERSON WITH FOLDED HANDS -1F680..1F6C5 ; Emoji_Presentation # 6.0 [70] (๐..๐
) ROCKET..LEFT LUGGAGE -1F6CC ; Emoji_Presentation # 7.0 [1] (๐) SLEEPING ACCOMMODATION -1F6D0 ; Emoji_Presentation # 8.0 [1] (๐) PLACE OF WORSHIP -1F6D1..1F6D2 ; Emoji_Presentation # 9.0 [2] (๐..๐) OCTAGONAL SIGN..SHOPPING TROLLEY -1F6EB..1F6EC ; Emoji_Presentation # 7.0 [2] (๐ซ..๐ฌ) AIRPLANE DEPARTURE..AIRPLANE ARRIVING -1F6F4..1F6F6 ; Emoji_Presentation # 9.0 [3] (๐ด..๐ถ) SCOOTER..CANOE -1F910..1F918 ; Emoji_Presentation # 8.0 [9] (๐ค..๐ค) ZIPPER-MOUTH FACE..SIGN OF THE HORNS -1F919..1F91E ; Emoji_Presentation # 9.0 [6] (๐ค..๐ค) CALL ME HAND..HAND WITH INDEX AND MIDDLE FINGERS CROSSED -1F920..1F927 ; Emoji_Presentation # 9.0 [8] (๐ค ..๐คง) FACE WITH COWBOY HAT..SNEEZING FACE -1F930 ; Emoji_Presentation # 9.0 [1] (๐คฐ) PREGNANT WOMAN -1F933..1F93A ; Emoji_Presentation # 9.0 [8] (๐คณ..๐คบ) SELFIE..FENCER -1F93C..1F93E ; Emoji_Presentation # 9.0 [3] (๐คผ..๐คพ) WRESTLERS..HANDBALL -1F940..1F945 ; Emoji_Presentation # 9.0 [6] (๐ฅ..๐ฅ
) WILTED FLOWER..GOAL NET -1F947..1F94B ; Emoji_Presentation # 9.0 [5] (๐ฅ..๐ฅ) FIRST PLACE MEDAL..MARTIAL ARTS UNIFORM -1F950..1F95E ; Emoji_Presentation # 9.0 [15] (๐ฅ..๐ฅ) CROISSANT..PANCAKES -1F980..1F984 ; Emoji_Presentation # 8.0 [5] (๐ฆ..๐ฆ) CRAB..UNICORN FACE -1F985..1F991 ; Emoji_Presentation # 9.0 [13] (๐ฆ
..๐ฆ) EAGLE..SQUID -1F9C0 ; Emoji_Presentation # 8.0 [1] (๐ง) CHEESE WEDGE +231A..231B ; Emoji_Presentation # 1.1 [2] (โ..โ) watch..hourglass +23E9..23EC ; Emoji_Presentation # 6.0 [4] (โฉ..โฌ) fast-forward button..fast down button +23F0 ; Emoji_Presentation # 6.0 [1] (โฐ) alarm clock +23F3 ; Emoji_Presentation # 6.0 [1] (โณ) hourglass with flowing sand +25FD..25FE ; Emoji_Presentation # 3.2 [2] (โฝ..โพ) white medium-small square..black medium-small square +2614..2615 ; Emoji_Presentation # 4.0 [2] (โ..โ) umbrella with rain drops..hot beverage +2648..2653 ; Emoji_Presentation # 1.1 [12] (โ..โ) Aries..Pisces +267F ; Emoji_Presentation # 4.1 [1] (โฟ) wheelchair symbol +2693 ; Emoji_Presentation # 4.1 [1] (โ) anchor +26A1 ; Emoji_Presentation # 4.0 [1] (โก) high voltage +26AA..26AB ; Emoji_Presentation # 4.1 [2] (โช..โซ) white circle..black circle +26BD..26BE ; Emoji_Presentation # 5.2 [2] (โฝ..โพ) soccer ball..baseball +26C4..26C5 ; Emoji_Presentation # 5.2 [2] (โ..โ
) snowman without snow..sun behind cloud +26CE ; Emoji_Presentation # 6.0 [1] (โ) Ophiuchus +26D4 ; Emoji_Presentation # 5.2 [1] (โ) no entry +26EA ; Emoji_Presentation # 5.2 [1] (โช) church +26F2..26F3 ; Emoji_Presentation # 5.2 [2] (โฒ..โณ) fountain..flag in hole +26F5 ; Emoji_Presentation # 5.2 [1] (โต) sailboat +26FA ; Emoji_Presentation # 5.2 [1] (โบ) tent +26FD ; Emoji_Presentation # 5.2 [1] (โฝ) fuel pump +2705 ; Emoji_Presentation # 6.0 [1] (โ
) white heavy check mark +270A..270B ; Emoji_Presentation # 6.0 [2] (โ..โ) raised fist..raised hand +2728 ; Emoji_Presentation # 6.0 [1] (โจ) sparkles +274C ; Emoji_Presentation # 6.0 [1] (โ) cross mark +274E ; Emoji_Presentation # 6.0 [1] (โ) cross mark button +2753..2755 ; Emoji_Presentation # 6.0 [3] (โ..โ) question mark..white exclamation mark +2757 ; Emoji_Presentation # 5.2 [1] (โ) exclamation mark +2795..2797 ; Emoji_Presentation # 6.0 [3] (โ..โ) heavy plus sign..heavy division sign +27B0 ; Emoji_Presentation # 6.0 [1] (โฐ) curly loop +27BF ; Emoji_Presentation # 6.0 [1] (โฟ) double curly loop +2B1B..2B1C ; Emoji_Presentation # 5.1 [2] (โฌ..โฌ) black large square..white large square +2B50 ; Emoji_Presentation # 5.1 [1] (โญ) white medium star +2B55 ; Emoji_Presentation # 5.2 [1] (โญ) heavy large circle +1F004 ; Emoji_Presentation # 5.1 [1] (๐) mahjong red dragon +1F0CF ; Emoji_Presentation # 6.0 [1] (๐) joker +1F18E ; Emoji_Presentation # 6.0 [1] (๐) AB button (blood type) +1F191..1F19A ; Emoji_Presentation # 6.0 [10] (๐..๐) CL button..VS button +1F1E6..1F1FF ; Emoji_Presentation # 6.0 [26] (๐ฆ..๐ฟ) regional indicator symbol letter a..regional indicator symbol letter z +1F201 ; Emoji_Presentation # 6.0 [1] (๐) Japanese โhereโ button +1F21A ; Emoji_Presentation # 5.2 [1] (๐) Japanese โfree of chargeโ button +1F22F ; Emoji_Presentation # 5.2 [1] (๐ฏ) Japanese โreservedโ button +1F232..1F236 ; Emoji_Presentation # 6.0 [5] (๐ฒ..๐ถ) Japanese โprohibitedโ button..Japanese โnot free of chargeโ button +1F238..1F23A ; Emoji_Presentation # 6.0 [3] (๐ธ..๐บ) Japanese โapplicationโ button..Japanese โopen for businessโ button +1F250..1F251 ; Emoji_Presentation # 6.0 [2] (๐..๐) Japanese โbargainโ button..Japanese โacceptableโ button +1F300..1F320 ; Emoji_Presentation # 6.0 [33] (๐..๐ ) cyclone..shooting star +1F32D..1F32F ; Emoji_Presentation # 8.0 [3] (๐ญ..๐ฏ) hot dog..burrito +1F330..1F335 ; Emoji_Presentation # 6.0 [6] (๐ฐ..๐ต) chestnut..cactus +1F337..1F37C ; Emoji_Presentation # 6.0 [70] (๐ท..๐ผ) tulip..baby bottle +1F37E..1F37F ; Emoji_Presentation # 8.0 [2] (๐พ..๐ฟ) bottle with popping cork..popcorn +1F380..1F393 ; Emoji_Presentation # 6.0 [20] (๐..๐) ribbon..graduation cap +1F3A0..1F3C4 ; Emoji_Presentation # 6.0 [37] (๐ ..๐) carousel horse..person surfing +1F3C5 ; Emoji_Presentation # 7.0 [1] (๐
) sports medal +1F3C6..1F3CA ; Emoji_Presentation # 6.0 [5] (๐..๐) trophy..person swimming +1F3CF..1F3D3 ; Emoji_Presentation # 8.0 [5] (๐..๐) cricket..ping pong +1F3E0..1F3F0 ; Emoji_Presentation # 6.0 [17] (๐ ..๐ฐ) house..castle +1F3F4 ; Emoji_Presentation # 7.0 [1] (๐ด) black flag +1F3F8..1F3FF ; Emoji_Presentation # 8.0 [8] (๐ธ..๐ฟ) badminton..dark skin tone +1F400..1F43E ; Emoji_Presentation # 6.0 [63] (๐..๐พ) rat..paw prints +1F440 ; Emoji_Presentation # 6.0 [1] (๐) eyes +1F442..1F4F7 ; Emoji_Presentation # 6.0[182] (๐..๐ท) ear..camera +1F4F8 ; Emoji_Presentation # 7.0 [1] (๐ธ) camera with flash +1F4F9..1F4FC ; Emoji_Presentation # 6.0 [4] (๐น..๐ผ) video camera..videocassette +1F4FF ; Emoji_Presentation # 8.0 [1] (๐ฟ) prayer beads +1F500..1F53D ; Emoji_Presentation # 6.0 [62] (๐..๐ฝ) shuffle tracks button..down button +1F54B..1F54E ; Emoji_Presentation # 8.0 [4] (๐..๐) kaaba..menorah +1F550..1F567 ; Emoji_Presentation # 6.0 [24] (๐..๐ง) one oโclock..twelve-thirty +1F57A ; Emoji_Presentation # 9.0 [1] (๐บ) man dancing +1F595..1F596 ; Emoji_Presentation # 7.0 [2] (๐..๐) middle finger..vulcan salute +1F5A4 ; Emoji_Presentation # 9.0 [1] (๐ค) black heart +1F5FB..1F5FF ; Emoji_Presentation # 6.0 [5] (๐ป..๐ฟ) mount fuji..moai +1F600 ; Emoji_Presentation # 6.1 [1] (๐) grinning face +1F601..1F610 ; Emoji_Presentation # 6.0 [16] (๐..๐) grinning face with smiling eyes..neutral face +1F611 ; Emoji_Presentation # 6.1 [1] (๐) expressionless face +1F612..1F614 ; Emoji_Presentation # 6.0 [3] (๐..๐) unamused face..pensive face +1F615 ; Emoji_Presentation # 6.1 [1] (๐) confused face +1F616 ; Emoji_Presentation # 6.0 [1] (๐) confounded face +1F617 ; Emoji_Presentation # 6.1 [1] (๐) kissing face +1F618 ; Emoji_Presentation # 6.0 [1] (๐) face blowing a kiss +1F619 ; Emoji_Presentation # 6.1 [1] (๐) kissing face with smiling eyes +1F61A ; Emoji_Presentation # 6.0 [1] (๐) kissing face with closed eyes +1F61B ; Emoji_Presentation # 6.1 [1] (๐) face with stuck-out tongue +1F61C..1F61E ; Emoji_Presentation # 6.0 [3] (๐..๐) face with stuck-out tongue & winking eye..disappointed face +1F61F ; Emoji_Presentation # 6.1 [1] (๐) worried face +1F620..1F625 ; Emoji_Presentation # 6.0 [6] (๐ ..๐ฅ) angry face..disappointed but relieved face +1F626..1F627 ; Emoji_Presentation # 6.1 [2] (๐ฆ..๐ง) frowning face with open mouth..anguished face +1F628..1F62B ; Emoji_Presentation # 6.0 [4] (๐จ..๐ซ) fearful face..tired face +1F62C ; Emoji_Presentation # 6.1 [1] (๐ฌ) grimacing face +1F62D ; Emoji_Presentation # 6.0 [1] (๐ญ) loudly crying face +1F62E..1F62F ; Emoji_Presentation # 6.1 [2] (๐ฎ..๐ฏ) face with open mouth..hushed face +1F630..1F633 ; Emoji_Presentation # 6.0 [4] (๐ฐ..๐ณ) face with open mouth & cold sweat..flushed face +1F634 ; Emoji_Presentation # 6.1 [1] (๐ด) sleeping face +1F635..1F640 ; Emoji_Presentation # 6.0 [12] (๐ต..๐) dizzy face..weary cat face +1F641..1F642 ; Emoji_Presentation # 7.0 [2] (๐..๐) slightly frowning face..slightly smiling face +1F643..1F644 ; Emoji_Presentation # 8.0 [2] (๐..๐) upside-down face..face with rolling eyes +1F645..1F64F ; Emoji_Presentation # 6.0 [11] (๐
..๐) person gesturing NO..folded hands +1F680..1F6C5 ; Emoji_Presentation # 6.0 [70] (๐..๐
) rocket..left luggage +1F6CC ; Emoji_Presentation # 7.0 [1] (๐) person in bed +1F6D0 ; Emoji_Presentation # 8.0 [1] (๐) place of worship +1F6D1..1F6D2 ; Emoji_Presentation # 9.0 [2] (๐..๐) stop sign..shopping cart +1F6EB..1F6EC ; Emoji_Presentation # 7.0 [2] (๐ซ..๐ฌ) airplane departure..airplane arrival +1F6F4..1F6F6 ; Emoji_Presentation # 9.0 [3] (๐ด..๐ถ) kick scooter..canoe +1F6F7..1F6F8 ; Emoji_Presentation # 10.0 [2] (๐ท..๐ธ) sled..flying saucer +1F910..1F918 ; Emoji_Presentation # 8.0 [9] (๐ค..๐ค) zipper-mouth face..sign of the horns +1F919..1F91E ; Emoji_Presentation # 9.0 [6] (๐ค..๐ค) call me hand..crossed fingers +1F91F ; Emoji_Presentation # 10.0 [1] (๐ค) love-you gesture +1F920..1F927 ; Emoji_Presentation # 9.0 [8] (๐ค ..๐คง) cowboy hat face..sneezing face +1F928..1F92F ; Emoji_Presentation # 10.0 [8] (๐คจ..๐คฏ) face with raised eyebrow..exploding head +1F930 ; Emoji_Presentation # 9.0 [1] (๐คฐ) pregnant woman +1F931..1F932 ; Emoji_Presentation # 10.0 [2] (๐คฑ..๐คฒ) breast-feeding..palms up together +1F933..1F93A ; Emoji_Presentation # 9.0 [8] (๐คณ..๐คบ) selfie..person fencing +1F93C..1F93E ; Emoji_Presentation # 9.0 [3] (๐คผ..๐คพ) people wrestling..person playing handball +1F940..1F945 ; Emoji_Presentation # 9.0 [6] (๐ฅ..๐ฅ
) wilted flower..goal net +1F947..1F94B ; Emoji_Presentation # 9.0 [5] (๐ฅ..๐ฅ) 1st place medal..martial arts uniform +1F94C ; Emoji_Presentation # 10.0 [1] (๐ฅ) curling stone +1F950..1F95E ; Emoji_Presentation # 9.0 [15] (๐ฅ..๐ฅ) croissant..pancakes +1F95F..1F96B ; Emoji_Presentation # 10.0 [13] (๐ฅ..๐ฅซ) dumpling..canned food +1F980..1F984 ; Emoji_Presentation # 8.0 [5] (๐ฆ..๐ฆ) crab..unicorn face +1F985..1F991 ; Emoji_Presentation # 9.0 [13] (๐ฆ
..๐ฆ) eagle..squid +1F992..1F997 ; Emoji_Presentation # 10.0 [6] (๐ฆ..๐ฆ) giraffe..cricket +1F9C0 ; Emoji_Presentation # 8.0 [1] (๐ง) cheese wedge +1F9D0..1F9E6 ; Emoji_Presentation # 10.0 [23] (๐ง..๐งฆ) face with monocle..socks -# Total elements: 910 +# Total elements: 966 # ================================================ # All omitted code points have Emoji_Modifier=No # @missing: 0000..10FFFF ; Emoji_Modifier ; No -1F3FB..1F3FF ; Emoji_Modifier # 8.0 [5] (๐ป..๐ฟ) EMOJI MODIFIER FITZPATRICK TYPE-1-2..EMOJI MODIFIER FITZPATRICK TYPE-6 +1F3FB..1F3FF ; Emoji_Modifier # 8.0 [5] (๐ป..๐ฟ) light skin tone..dark skin tone # Total elements: 5 @@ -365,39 +386,58 @@ # All omitted code points have Emoji_Modifier_Base=No # @missing: 0000..10FFFF ; Emoji_Modifier_Base ; No -261D ; Emoji_Modifier_Base # 1.1 [1] (โ) WHITE UP POINTING INDEX -26F9 ; Emoji_Modifier_Base # 5.2 [1] (โน) PERSON WITH BALL -270A..270B ; Emoji_Modifier_Base # 6.0 [2] (โ..โ) RAISED FIST..RAISED HAND -270C..270D ; Emoji_Modifier_Base # 1.1 [2] (โ..โ) VICTORY HAND..WRITING HAND -1F385 ; Emoji_Modifier_Base # 6.0 [1] (๐
) FATHER CHRISTMAS -1F3C3..1F3C4 ; Emoji_Modifier_Base # 6.0 [2] (๐..๐) RUNNER..SURFER -1F3CA ; Emoji_Modifier_Base # 6.0 [1] (๐) SWIMMER -1F3CB ; Emoji_Modifier_Base # 7.0 [1] (๐) WEIGHT LIFTER -1F442..1F443 ; Emoji_Modifier_Base # 6.0 [2] (๐..๐) EAR..NOSE -1F446..1F450 ; Emoji_Modifier_Base # 6.0 [11] (๐..๐) WHITE UP POINTING BACKHAND INDEX..OPEN HANDS SIGN -1F466..1F469 ; Emoji_Modifier_Base # 6.0 [4] (๐ฆ..๐ฉ) BOY..WOMAN -1F46E ; Emoji_Modifier_Base # 6.0 [1] (๐ฎ) POLICE OFFICER -1F470..1F478 ; Emoji_Modifier_Base # 6.0 [9] (๐ฐ..๐ธ) BRIDE WITH VEIL..PRINCESS -1F47C ; Emoji_Modifier_Base # 6.0 [1] (๐ผ) BABY ANGEL -1F481..1F483 ; Emoji_Modifier_Base # 6.0 [3] (๐..๐) INFORMATION DESK PERSON..DANCER -1F485..1F487 ; Emoji_Modifier_Base # 6.0 [3] (๐
..๐) NAIL POLISH..HAIRCUT -1F4AA ; Emoji_Modifier_Base # 6.0 [1] (๐ช) FLEXED BICEPS -1F575 ; Emoji_Modifier_Base # 7.0 [1] (๐ต) SLEUTH OR SPY -1F57A ; Emoji_Modifier_Base # 9.0 [1] (๐บ) MAN DANCING -1F590 ; Emoji_Modifier_Base # 7.0 [1] (๐) RAISED HAND WITH FINGERS SPLAYED -1F595..1F596 ; Emoji_Modifier_Base # 7.0 [2] (๐..๐) REVERSED HAND WITH MIDDLE FINGER EXTENDED..RAISED HAND WITH PART BETWEEN MIDDLE AND RING FINGERS -1F645..1F647 ; Emoji_Modifier_Base # 6.0 [3] (๐
..๐) FACE WITH NO GOOD GESTURE..PERSON BOWING DEEPLY -1F64B..1F64F ; Emoji_Modifier_Base # 6.0 [5] (๐..๐) HAPPY PERSON RAISING ONE HAND..PERSON WITH FOLDED HANDS -1F6A3 ; Emoji_Modifier_Base # 6.0 [1] (๐ฃ) ROWBOAT -1F6B4..1F6B6 ; Emoji_Modifier_Base # 6.0 [3] (๐ด..๐ถ) BICYCLIST..PEDESTRIAN -1F6C0 ; Emoji_Modifier_Base # 6.0 [1] (๐) BATH -1F918 ; Emoji_Modifier_Base # 8.0 [1] (๐ค) SIGN OF THE HORNS -1F919..1F91E ; Emoji_Modifier_Base # 9.0 [6] (๐ค..๐ค) CALL ME HAND..HAND WITH INDEX AND MIDDLE FINGERS CROSSED -1F926 ; Emoji_Modifier_Base # 9.0 [1] (๐คฆ) FACE PALM -1F930 ; Emoji_Modifier_Base # 9.0 [1] (๐คฐ) PREGNANT WOMAN -1F933..1F939 ; Emoji_Modifier_Base # 9.0 [7] (๐คณ..๐คน) SELFIE..JUGGLING -1F93C..1F93E ; Emoji_Modifier_Base # 9.0 [3] (๐คผ..๐คพ) WRESTLERS..HANDBALL +261D ; Emoji_Modifier_Base # 1.1 [1] (โ๏ธ) index pointing up +26F9 ; Emoji_Modifier_Base # 5.2 [1] (โน๏ธ) person bouncing ball +270A..270B ; Emoji_Modifier_Base # 6.0 [2] (โ..โ) raised fist..raised hand +270C..270D ; Emoji_Modifier_Base # 1.1 [2] (โ๏ธ..โ๏ธ) victory hand..writing hand +1F385 ; Emoji_Modifier_Base # 6.0 [1] (๐
) Santa Claus +1F3C2..1F3C4 ; Emoji_Modifier_Base # 6.0 [3] (๐..๐) snowboarder..person surfing +1F3C7 ; Emoji_Modifier_Base # 6.0 [1] (๐) horse racing +1F3CA ; Emoji_Modifier_Base # 6.0 [1] (๐) person swimming +1F3CB..1F3CC ; Emoji_Modifier_Base # 7.0 [2] (๐๏ธ..๐๏ธ) person lifting weights..person golfing +1F442..1F443 ; Emoji_Modifier_Base # 6.0 [2] (๐..๐) ear..nose +1F446..1F450 ; Emoji_Modifier_Base # 6.0 [11] (๐..๐) backhand index pointing up..open hands +1F466..1F469 ; Emoji_Modifier_Base # 6.0 [4] (๐ฆ..๐ฉ) boy..woman +1F46E ; Emoji_Modifier_Base # 6.0 [1] (๐ฎ) police officer +1F470..1F478 ; Emoji_Modifier_Base # 6.0 [9] (๐ฐ..๐ธ) bride with veil..princess +1F47C ; Emoji_Modifier_Base # 6.0 [1] (๐ผ) baby angel +1F481..1F483 ; Emoji_Modifier_Base # 6.0 [3] (๐..๐) person tipping hand..woman dancing +1F485..1F487 ; Emoji_Modifier_Base # 6.0 [3] (๐
..๐) nail polish..person getting haircut +1F4AA ; Emoji_Modifier_Base # 6.0 [1] (๐ช) flexed biceps +1F574..1F575 ; Emoji_Modifier_Base # 7.0 [2] (๐ด๏ธ..๐ต๏ธ) man in business suit levitating..detective +1F57A ; Emoji_Modifier_Base # 9.0 [1] (๐บ) man dancing +1F590 ; Emoji_Modifier_Base # 7.0 [1] (๐๏ธ) raised hand with fingers splayed +1F595..1F596 ; Emoji_Modifier_Base # 7.0 [2] (๐..๐) middle finger..vulcan salute +1F645..1F647 ; Emoji_Modifier_Base # 6.0 [3] (๐
..๐) person gesturing NO..person bowing +1F64B..1F64F ; Emoji_Modifier_Base # 6.0 [5] (๐..๐) person raising hand..folded hands +1F6A3 ; Emoji_Modifier_Base # 6.0 [1] (๐ฃ) person rowing boat +1F6B4..1F6B6 ; Emoji_Modifier_Base # 6.0 [3] (๐ด..๐ถ) person biking..person walking +1F6C0 ; Emoji_Modifier_Base # 6.0 [1] (๐) person taking bath +1F6CC ; Emoji_Modifier_Base # 7.0 [1] (๐) person in bed +1F918 ; Emoji_Modifier_Base # 8.0 [1] (๐ค) sign of the horns +1F919..1F91C ; Emoji_Modifier_Base # 9.0 [4] (๐ค..๐ค) call me hand..right-facing fist +1F91E ; Emoji_Modifier_Base # 9.0 [1] (๐ค) crossed fingers +1F91F ; Emoji_Modifier_Base # 10.0 [1] (๐ค) love-you gesture +1F926 ; Emoji_Modifier_Base # 9.0 [1] (๐คฆ) person facepalming +1F930 ; Emoji_Modifier_Base # 9.0 [1] (๐คฐ) pregnant woman +1F931..1F932 ; Emoji_Modifier_Base # 10.0 [2] (๐คฑ..๐คฒ) breast-feeding..palms up together +1F933..1F939 ; Emoji_Modifier_Base # 9.0 [7] (๐คณ..๐คน) selfie..person juggling +1F93D..1F93E ; Emoji_Modifier_Base # 9.0 [2] (๐คฝ..๐คพ) person playing water polo..person playing handball +1F9D1..1F9DD ; Emoji_Modifier_Base # 10.0 [13] (๐ง..๐ง) adult..elf + +# Total elements: 102 + +# ================================================ + +# All omitted code points have Emoji_Component=No +# @missing: 0000..10FFFF ; Emoji_Component ; No + +0023 ; Emoji_Component # 1.1 [1] (#๏ธ) number sign +002A ; Emoji_Component # 1.1 [1] (*๏ธ) asterisk +0030..0039 ; Emoji_Component # 1.1 [10] (0๏ธ..9๏ธ) digit zero..digit nine +1F1E6..1F1FF ; Emoji_Component # 6.0 [26] (๐ฆ..๐ฟ) regional indicator symbol letter a..regional indicator symbol letter z +1F3FB..1F3FF ; Emoji_Component # 8.0 [5] (๐ป..๐ฟ) light skin tone..dark skin tone -# Total elements: 83 +# Total elements: 43 #EOF |